00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00042
00043
00044
00045
00046
00047
00048
00049
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
00086
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,
00096 };
00097
00098
00099
00100
00101
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 );
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;
00215
00216
00217 char *m_filename;
00218
00219 char *m_alt_filename;
00220
00221
00222
00223
00224 unsigned int m_flags;
00225 uint64_t m_signature;
00226
00227 Log::RollingEnabledValues m_rolling_enabled;
00228 int m_flush_threads;
00229 int m_rolling_interval_sec;
00230
00231 int m_rolling_offset_hr;
00232 int m_rolling_size_mb;
00233 long m_last_roll_time;
00234
00235
00236 volatile head_p m_log_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
00248 LogObject();
00249 LogObject & operator=(const LogObject &);
00250 };
00251
00252
00253
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
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
00295
00296
00297
00298
00299
00300 class LogObjectManager
00301 {
00302 public:
00303
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;
00319 LogObjectList _APIobjects;
00320
00321 public:
00322 ink_mutex * _APImutex;
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
00335
00336
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
00347 bool unmanage_api_object(LogObject * logObject);
00348
00349
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