• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

LogObject.h

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 
00025 
00026 #ifndef LOG_OBJECT_H
00027 #define LOG_OBJECT_H
00028 
00029 #include "libts.h"
00030 #include "Log.h"
00031 #include "LogFile.h"
00032 #include "LogFormat.h"
00033 #include "LogFilter.h"
00034 #include "LogHost.h"
00035 #include "LogBuffer.h"
00036 #include "LogAccess.h"
00037 #include "LogFilter.h"
00038 #include "ts/Vec.h"
00039 
00040 /*-------------------------------------------------------------------------
00041   LogObject
00042 
00043   This is a new addition to the Traffic Server logging as of the 3.1
00044   (Panda) release.  This object corresponds to the new type of logfile
00045   entity that will be the focal point for all logging, replacing the role
00046   of the LogFormat object.  The LogObject will contain information about
00047   the format being used, the physical file  attached, and any filters that
00048   are in place.  The global logging configuration for a traffic server will
00049   consist of a list of LogObjects.
00050   -------------------------------------------------------------------------*/
00051 
00052 #define LOG_FILE_ASCII_OBJECT_FILENAME_EXTENSION ".log"
00053 #define LOG_FILE_BINARY_OBJECT_FILENAME_EXTENSION ".blog"
00054 #define LOG_FILE_PIPE_OBJECT_FILENAME_EXTENSION ".pipe"
00055 
00056 #define FLUSH_ARRAY_SIZE (512*4)
00057 
00058 #define LOG_OBJECT_ARRAY_DELTA 8
00059 
00060 #define ACQUIRE_API_MUTEX(_f) \
00061 ink_mutex_acquire(_APImutex); \
00062 Debug("log-api-mutex", _f)
00063 
00064 #define RELEASE_API_MUTEX(_f) \
00065 ink_mutex_release(_APImutex); \
00066 Debug("log-api-mutex", _f)
00067 
00068 class LogBufferManager
00069 {
00070   private:
00071     ASLL(LogBuffer, write_link) write_list;
00072     int _num_flush_buffers;
00073 
00074   public:
00075     LogBufferManager() : _num_flush_buffers(0) { }
00076 
00077     void add_to_flush_queue(LogBuffer *buffer) {
00078       write_list.push(buffer);
00079       ink_atomic_increment(&_num_flush_buffers, 1);
00080     }
00081 
00082     size_t preproc_buffers(LogBufferSink *sink);
00083 };
00084 
00085 // LogObject is atomically reference counted, and the reference count is always owned by
00086 // one or more LogObjectManagers.
00087 class LogObject : public RefCountObj
00088 {
00089 public:
00090   enum LogObjectFlags
00091   {
00092     BINARY = 1,
00093     REMOTE_DATA = 2,
00094     WRITES_TO_PIPE = 4,
00095     LOG_OBJECT_FMT_TIMESTAMP = 8, // always format a timestamp into each log line (for raw text logs)
00096   };
00097 
00098   // BINARY: log is written in binary format (rather than ascii)
00099   // REMOTE_DATA: object receives data from remote collation clients, so
00100   //              it should not be destroyed during a reconfiguration
00101   // WRITES_TO_PIPE: object writes to a named pipe rather than to a file
00102 
00103   LogObject(const LogFormat *format, const char *log_dir, const char *basename,
00104                  LogFileFormat file_format, const char *header,
00105                  Log::RollingEnabledValues rolling_enabled, int flush_threads,
00106                  int rolling_interval_sec = 0, int rolling_offset_hr = 0,
00107                  int rolling_size_mb = 0, bool auto_created = false)
00108     TS_NONNULL(2 /* format is required */);
00109   LogObject(LogObject &);
00110   virtual ~LogObject();
00111 
00112   void add_filter(LogFilter * filter, bool copy = true);
00113   void set_filter_list(const LogFilterList & list, bool copy = true);
00114   void add_loghost(LogHost * host, bool copy = true);
00115 
00116   void set_remote_flag() { m_flags |= REMOTE_DATA; };
00117   void set_fmt_timestamps() { m_flags |= LOG_OBJECT_FMT_TIMESTAMP; }
00118 
00119   int log(LogAccess * lad, const char *text_entry = NULL);
00120   int va_log(LogAccess * lad, const char * fmt, va_list ap);
00121 
00122   unsigned roll_files(long time_now = 0);
00123 
00124   int add_to_flush_queue(LogBuffer * buffer)
00125   {
00126     int idx = m_buffer_manager_idx++ % m_flush_threads;
00127 
00128     m_buffer_manager[idx].add_to_flush_queue(buffer);
00129 
00130     return idx;
00131   }
00132 
00133   size_t preproc_buffers(int idx = -1)
00134   {
00135     size_t nfb;
00136 
00137     if (idx == -1)
00138       idx = m_buffer_manager_idx++ % m_flush_threads;
00139 
00140     if (m_logFile) {
00141       nfb = m_buffer_manager[idx].preproc_buffers(m_logFile);
00142     } else {
00143       nfb = m_buffer_manager[idx].preproc_buffers(&m_host_list);
00144     }
00145     return nfb;
00146   }
00147 
00148   void check_buffer_expiration(long time_now);
00149 
00150   void display(FILE * fd = stdout);
00151   void displayAsXML(FILE * fd = stdout, bool extended = false);
00152   static uint64_t compute_signature(LogFormat * format, char *filename, unsigned int flags);
00153 
00154   const char *get_original_filename() const { return m_filename; }
00155   const char *get_full_filename() const { return (m_alt_filename ? m_alt_filename : m_filename); }
00156   const char *get_base_filename() const { return m_basename; }
00157 
00158   off_t get_file_size_bytes();
00159 
00160   uint64_t get_signature() const { return m_signature; }
00161 
00162   int get_rolling_interval() const { return m_rolling_interval_sec; }
00163 
00164   void set_log_file_header(const char *header) { m_logFile->change_header(header); }
00165 
00166   void set_rolling_enabled(Log::RollingEnabledValues rolling_enabled)
00167   {
00168     _setup_rolling(rolling_enabled, m_rolling_interval_sec, m_rolling_offset_hr, m_rolling_size_mb);
00169   }
00170 
00171   void set_rolling_interval_sec(int rolling_interval_sec)
00172   {
00173     _setup_rolling(m_rolling_enabled, rolling_interval_sec, m_rolling_offset_hr, m_rolling_size_mb);
00174   }
00175 
00176  void set_rolling_offset_hr(int rolling_offset_hr)
00177   {
00178     _setup_rolling(m_rolling_enabled, m_rolling_interval_sec, rolling_offset_hr, m_rolling_size_mb);
00179   }
00180 
00181   void set_rolling_size_mb(int rolling_size_mb)
00182   {
00183     m_rolling_size_mb = rolling_size_mb;
00184   }
00185 
00186   bool is_collation_client() const { return (m_logFile ? false : true); }
00187   bool receives_remote_data() const { return m_flags & REMOTE_DATA ? true : false; }
00188   bool writes_to_pipe() const { return m_flags & WRITES_TO_PIPE ? true : false; }
00189   bool writes_to_disk() { return (m_logFile && !(m_flags & WRITES_TO_PIPE) ? true : false); }
00190 
00191   unsigned int get_flags() const { return m_flags; }
00192 
00193   void rename(char *new_name);
00194 
00195   bool has_alternate_name() const { return (m_alt_filename ? true : false); }
00196 
00197   const char *get_format_string() { return (m_format ? m_format->format_string() : "<none>"); }
00198 
00199   void force_new_buffer() {
00200     _checkout_write(NULL, 0);
00201   }
00202 
00203   bool operator==(LogObject & rhs);
00204   int do_filesystem_checks();
00205 
00206 public:
00207   bool m_auto_created;
00208   LogFormat * m_format;
00209   Ptr<LogFile> m_logFile;
00210   LogFilterList m_filter_list;
00211   LogHostList m_host_list;
00212 
00213 private:
00214   char *m_basename;             // the name of the file associated
00215   // with this object, relative to
00216   // the logging directory
00217   char *m_filename;             // the full path of the file associated
00218   // with this object
00219   char *m_alt_filename;         // the full path of the file used
00220   // instead of m_filename if the latter
00221   // could not be used because of
00222   // name conflicts
00223 
00224   unsigned int m_flags;         // diverse object flags (see above)
00225   uint64_t m_signature;         // INK_MD5 signature for object
00226 
00227   Log::RollingEnabledValues m_rolling_enabled;
00228   int m_flush_threads;          // number of flush threads
00229   int m_rolling_interval_sec;   // time interval between rolls
00230   // 0 means no rolling
00231   int m_rolling_offset_hr;      //
00232   int m_rolling_size_mb;        // size at which the log file rolls
00233   long m_last_roll_time;        // the last time this object rolled
00234   // its files
00235 
00236   volatile head_p m_log_buffer;     // current work buffer
00237   unsigned m_buffer_manager_idx;
00238   LogBufferManager *m_buffer_manager;
00239 
00240   void generate_filenames(const char *log_dir, const char *basename, LogFileFormat file_format);
00241   void _setup_rolling(Log::RollingEnabledValues rolling_enabled, int rolling_interval_sec, int rolling_offset_hr, int rolling_size_mb);
00242   unsigned _roll_files(long interval_start, long interval_end);
00243 
00244   LogBuffer *_checkout_write(size_t * write_offset, size_t write_size);
00245 
00246 private:
00247   // -- member functions not allowed --
00248   LogObject();
00249   LogObject & operator=(const LogObject &);
00250 };
00251 
00252 /*-------------------------------------------------------------------------
00253   TextLog
00254   -------------------------------------------------------------------------*/
00255 
00256 class TextLogObject:public LogObject
00257 {
00258 public:
00259   inkcoreapi TextLogObject(const char *name, const char *log_dir,
00260                            bool timestamps, const char *header,
00261                            Log::RollingEnabledValues rolling_enabled,
00262                            int flush_threads,
00263                            int rolling_interval_sec,
00264                            int rolling_offset_hr,
00265                            int rolling_size_mb);
00266 
00267   inkcoreapi int write(const char *format, ...) TS_PRINTFLIKE(2, 3);
00268   inkcoreapi int va_write(const char *format, va_list ap);
00269 
00270   static const LogFormat * textfmt;
00271 };
00272 
00273 /*-------------------------------------------------------------------------
00274   RefCounter
00275   -------------------------------------------------------------------------*/
00276 class RefCounter
00277 {
00278 public:
00279   RefCounter(int *count)
00280     : m_count(count)
00281   {
00282     ink_atomic_increment(m_count, 1);
00283   }
00284 
00285   ~RefCounter() {
00286     ink_atomic_increment(m_count, -1);
00287   }
00288 
00289 private:
00290   int *m_count;
00291 };
00292 
00293 /*-------------------------------------------------------------------------
00294   LogObjectManager
00295 
00296   A log object manager keeps track of log objects and is responsible for
00297   their deletion
00298   -------------------------------------------------------------------------*/
00299 
00300 class LogObjectManager
00301 {
00302 public:
00303   // error status
00304   //
00305   enum
00306   {
00307     NO_FILENAME_CONFLICTS = 0,
00308     ERROR_ACCESSING_LOG_FILE,
00309     ERROR_DETERMINING_FILE_INFO,
00310     CANNOT_SOLVE_FILENAME_CONFLICTS,
00311     ERROR_DOING_FILESYSTEM_CHECKS
00312   };
00313 
00314 private:
00315 
00316   typedef Vec<LogObject *> LogObjectList;
00317 
00318   LogObjectList _objects;         // array of configured objects
00319   LogObjectList _APIobjects;      // array of API objects
00320 
00321 public:
00322     ink_mutex * _APImutex;      // synchronize access to array of API objects
00323 private:
00324 
00325   int _manage_object(LogObject * log_object, bool is_api_object, int maxConflicts);
00326   static bool _has_internal_filename_conflict(const char *filename, LogObjectList& objects);
00327   int _solve_filename_conflicts(LogObject * log_obj, int maxConflicts);
00328   int _solve_internal_filename_conflicts(LogObject * log_obj, int maxConflicts, int fileNum = 0);
00329 
00330 public:
00331   LogObjectManager();
00332   ~LogObjectManager();
00333 
00334   // we don't define a destructor because the objects that the
00335   // LogObjectManager manages are either passed along to another
00336   // manager or moved to the list of inactive objects to be destroyed
00337 
00338   int manage_object(LogObject * logObject, int maxConflicts = 99) {
00339     return _manage_object(logObject, false, maxConflicts);
00340   }
00341 
00342   int manage_api_object(LogObject * logObject, int maxConflicts = 99) {
00343     return _manage_object(logObject, true, maxConflicts);
00344   }
00345 
00346   // return success
00347   bool unmanage_api_object(LogObject * logObject);
00348 
00349   // Flush the buffers on all the managed log objects.
00350   void flush_all_objects();
00351 
00352   LogObject *get_object_with_signature(uint64_t signature);
00353   void check_buffer_expiration(long time_now);
00354 
00355   unsigned roll_files(long time_now);
00356 
00357   int log(LogAccess * lad);
00358   void display(FILE * str = stdout);
00359   void add_filter_to_all(LogFilter * filter);
00360   LogObject *find_by_format_name(const char *name) const ;
00361   size_t preproc_buffers(int idx);
00362   void open_local_pipes();
00363   void transfer_objects(LogObjectManager & mgr);
00364 
00365   bool has_api_objects() const  { return _APIobjects.length() > 0; }
00366   unsigned get_num_objects() const { return _objects.length(); }
00367   unsigned get_num_collation_clients() const;
00368 };
00369 
00370 inline bool
00371 LogObject::operator==(LogObject & old)
00372 {
00373   if (!receives_remote_data() && !old.receives_remote_data()) {
00374     return (get_signature() == old.get_signature() &&
00375             (is_collation_client() && old.is_collation_client()?
00376              m_host_list == old.m_host_list :
00377              m_logFile && old.m_logFile &&
00378              strcmp(m_logFile->get_name(), old.m_logFile->get_name()) == 0) &&
00379             (m_filter_list == old.m_filter_list) &&
00380             (m_rolling_interval_sec == old.m_rolling_interval_sec &&
00381              m_rolling_offset_hr == old.m_rolling_offset_hr && m_rolling_size_mb == old.m_rolling_size_mb));
00382   }
00383   return false;
00384 }
00385 
00386 inline off_t
00387 LogObject::get_file_size_bytes()
00388 {
00389   if (m_logFile) {
00390     return m_logFile->get_size_bytes();
00391   } else {
00392     off_t max_size = 0;
00393     LogHost *host;
00394     for (host = m_host_list.first(); host; host = m_host_list.next(host)) {
00395       LogFile *orphan_logfile = host->get_orphan_logfile();
00396       if (orphan_logfile) {
00397         off_t s = orphan_logfile->get_size_bytes();
00398         if (s > max_size)
00399           max_size = s;
00400       }
00401     }
00402     return max_size;
00403   }
00404 }
00405 
00406 #endif

Generated by  doxygen 1.7.1