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
00027
00028
00029
00030 #include "w_defines.h"
00031
00032
00033
00034 #define __ERRLOG_C__
00035
00036
00037 #include <cstdarg>
00038 #include <cstdlib>
00039 #include <cstddef>
00040 #include <cstring>
00041 #include <cassert>
00042 #include <cstdio>
00043 #include <iostream>
00044
00045 #ifdef __GNUC__
00046 #pragma implementation "errlog.h"
00047 #pragma implementation "errlog_s.h"
00048 #pragma implementation "w_debug.h"
00049 #endif
00050
00051 #include "w.h"
00052 #include "errlog.h"
00053 #include <errlog_s.h>
00054 #include <w_strstream.h>
00055
00056 #ifdef EXPLICIT_TEMPLATE
00057 template class w_list_t<ErrLogInfo,unsafe_list_dummy_lock_t>;
00058 template class w_list_i<ErrLogInfo,unsafe_list_dummy_lock_t>;
00059 template class w_keyed_list_t<ErrLogInfo,,unsafe_list_dummy_lock_t simple_string>;
00060 #endif
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 ostream &operator<<(ostream &out, const simple_string x) {
00071 out << x._s;
00072 return out;
00073 }
00074
00075
00076 #if SM_PAGESIZE < 8192
00077 #define ERRLOG_BUF_SIZE 8192
00078 #else
00079 #define ERRLOG_BUF_SIZE SM_PAGESIZE
00080 #endif
00081 static char buffer[ERRLOG_BUF_SIZE];
00082
00083
00084
00085 ErrLogInfo::ErrLogInfo(ErrLog *e)
00086 : _ident(e->ident()), _e(e)
00087
00088 {
00089 }
00090
00091
00092
00093 static w_keyed_list_t<ErrLogInfo,unsafe_list_dummy_lock_t,simple_string>
00094 _tab(W_KEYED_ARG(ErrLogInfo, _ident, hash_link), unsafe_nolock);
00095
00096
00097
00098 class errlog_dummy {
00099
00100
00101
00102
00103
00104 friend class ErrLog;
00105
00106 protected:
00107 bool table_cleared;
00108
00109 public:
00110 errlog_dummy(){
00111 table_cleared = false;
00112 #ifdef ZERO_INIT
00113 memset(buffer, '\0', sizeof(buffer));
00114 #endif
00115 }
00116 ~errlog_dummy();
00117 void dump();
00118 }_d;
00119
00120 errlog_dummy::~errlog_dummy() {
00121 ErrLogInfo *ei;
00122
00123 while((ei = _tab.pop())) {
00124 delete ei;
00125 }
00126 table_cleared = true;
00127 }
00128
00129 void
00130 errlog_dummy::dump() {
00131 ErrLogInfo *ei;
00132 w_list_i <ErrLogInfo,unsafe_list_dummy_lock_t> iter(_tab);
00133 while((ei=iter.next())) {
00134 ei->dump();
00135 }
00136 }
00137
00138
00139
00140 logstream *
00141 is_logstream(std::basic_ostream<char, std::char_traits<char > > &o)
00142 {
00143 logstream *l=0;
00144 const ostream *tied = NULL;
00145 if((&o)->ios::good()) {
00146 tied = o.ios::tie();
00147 }
00148
00149
00150 {
00151 l = (logstream *)&o;
00152 }
00153 if(l) {
00154
00155
00156
00157 }
00158 if(l &&
00159 (l->__magic1 == logstream::LOGSTREAM__MAGIC) &&
00160 (l->__magic2 == logstream::LOGSTREAM__MAGIC) &&
00161 (l->_prio >= log_none) &&
00162 (l->_prio <= log_all) &&
00163 (l->_log->_magic == ErrLog::ERRORLOG__MAGIC)
00164 ) {
00165
00166 return l;
00167 } else {
00168
00169 return (logstream *)0;
00170 }
00171 }
00172
00173 ostream &
00174 flush_and_setprio(ostream& o, LogPriority p)
00175 {
00176
00177
00178 logstream *l = is_logstream(o);
00179 if(l) {
00180 l->_log->_flush();
00181 if(p != log_none) {
00182 l->_prio = p;
00183 }
00184 } else {
00185 o << flush;
00186 }
00187 return o;
00188 }
00189
00190 ostream& flushl(ostream& out)
00191 {
00192 out << endl;
00193 return flush_and_setprio(out, log_none);
00194 }
00195 ostream& emerg_prio(ostream& o){return flush_and_setprio(o, log_emerg); }
00196 ostream& fatal_prio(ostream& o){return flush_and_setprio(o, log_fatal); }
00197 ostream& internal_prio(ostream& o){ return flush_and_setprio(o, log_internal); }
00198 ostream& error_prio(ostream& o){return flush_and_setprio(o, log_error); }
00199 ostream& warning_prio(ostream& o){ return flush_and_setprio(o, log_warning); }
00200 ostream& info_prio(ostream& o){ return flush_and_setprio(o, log_info); }
00201 ostream& debug_prio(ostream& o){ return flush_and_setprio(o, log_debug); }
00202
00203 #ifdef USE_REGEX
00204 #include "regex_posix.h"
00205 #endif
00206 #include "w_debug.cpp"
00207
00208 #if W_DEBUG_LEVEL > 3
00209 void dummy() { DBG(<<""); }
00210 #endif
00211
00212 #include <critical_section.h>
00213
00214 LogPriority
00215 ErrLog::setloglevel( LogPriority prio)
00216 {
00217 CRITICAL_SECTION(cs, _errlog_mutex);
00218 LogPriority old = _level;
00219 _level = prio;
00220 return old;
00221 }
00222
00223
00224 LogPriority
00225 ErrLog::parse(const char *arg, bool *ok)
00226
00227 {
00228 LogPriority level = log_none;
00229
00230 if(strcmp(arg, "off")==0) {
00231 level = log_none;
00232 } else
00233 if(strcmp(arg, "trace")==0 || strcmp(arg,"debug")==0) {
00234 level = log_debug;
00235 } else
00236 if(strcmp(arg, "info")==0) {
00237 level = log_info;
00238 } else
00239 if(strcmp(arg, "warning")==0) {
00240 level = log_warning;
00241 } else
00242 if(strcmp(arg, "error")==0) {
00243 level = log_error;
00244 } else
00245 if(strcmp(arg, "internal")==0 || strcmp(arg,"critical")==0) {
00246 level = log_internal;
00247 } else
00248 if(strcmp(arg, "fatal")==0 || strcmp(arg,"alert")==0) {
00249 level = log_fatal;
00250 } else
00251 if(strcmp(arg, "emerg")==0) {
00252 level = log_emerg;
00253 } else {
00254 if (ok) *ok = false;
00255 }
00256 return level;
00257 }
00258
00259 void
00260 ErrLog::_closelogfile()
00261 {
00262
00263 assert(_file != NULL);
00264 fclose(_file);
00265 }
00266
00267 void
00268 ErrLog::_openlogfile(
00269 const char *fn
00270 )
00271 {
00272
00273 const char *filename=fn;
00274 if(strcmp(filename, "-")==0) {
00275
00276 _destination = log_to_stderr;
00277 _file = stderr;
00278 return;
00279 }
00280 if(filename) {
00281 _destination = log_to_unix_file;
00282 if(strncmp(filename, "unix:", 5) == 0) {
00283 filename += 5;
00284 } else if (strncmp(filename, "shore:", 6) == 0) {
00285 filename += 6;
00286 }
00287 _file = fopen(filename, "a+");
00288 if(_file == NULL) {
00289 w_rc_t e = RC(fcOS);
00290 cerr << "Cannot fopen Unix file " << filename << endl;
00291 cerr << e << endl;
00292 W_COERCE(e);
00293 }
00294 } else {
00295 cerr << "Unknown logging destination." << endl;
00296 W_FATAL(fcINTERNAL);
00297 }
00298
00299 }
00300
00301 void
00302 ErrLog::_init1()
00303 {
00304
00305 clog.init_errlog(this);
00306 w_reset_strstream(this->clog);
00307 }
00308
00309 void
00310 ErrLog::_init2()
00311 {
00312
00313 ErrLogInfo *ei;
00314 if((ei = _tab.search(this->_ident)) == 0) {
00315 ei = new ErrLogInfo(this);
00316 _tab.put_in_order(ei);
00317 } else {
00318 cerr << "An ErrLog called " << _ident << " already exists." << endl;
00319 W_FATAL(fcINTERNAL);
00320 }
00321 }
00322
00323 ErrLog::ErrLog(
00324 const char *ident,
00325 LoggingDestination dest,
00326 const char *filename,
00327 LogPriority level,
00328 char *ownbuf,
00329 int ownbufsz
00330
00331 ) :
00332 _destination(dest),
00333 _level(level),
00334 _file(0),
00335 _ident(ident),
00336 _buffer(ownbuf?ownbuf:buffer),
00337 _bufsize(ownbuf?ownbufsz:sizeof(buffer)),
00338 _magic(ERRORLOG__MAGIC),
00339 _errlog_mutex(new pthread_mutex_t),
00340 clog(ownbuf?ownbuf:buffer, ownbuf?ownbufsz:sizeof(buffer))
00341 {
00342 DO_PTHREAD(pthread_mutex_init(_errlog_mutex, NULL));
00343 CRITICAL_SECTION(cs, _errlog_mutex);
00344 _init1();
00345
00346 switch( dest ) {
00347 case log_to_unix_file:
00348 {
00349 if(!filename) {
00350 filename = "-";
00351 }
00352 _openlogfile(filename);
00353 }
00354 break;
00355
00356 case log_to_stderr:
00357 _file = stderr;
00358 break;
00359
00360 case log_to_ether:
00361 _file = 0;
00362 break;
00363
00364 default:
00365
00366 cerr << "Bad argument 2 to ErrLog constructor" <<endl;
00367 W_FATAL_MSG(fcINTERNAL, << "Bad argument 2 to ErrLog constructor");
00368 break;
00369 }
00370 _init2();
00371 }
00372
00373 ErrLog::ErrLog(
00374 const char *ident,
00375 LoggingDestination dest,
00376 FILE *file,
00377 LogPriority level,
00378 char *ownbuf,
00379 int ownbufsz
00380
00381 ) :
00382 _destination(dest),
00383 _level(level),
00384 _file(file),
00385 _ident(ident),
00386 _buffer(ownbuf?ownbuf:buffer),
00387 _bufsize(ownbuf?ownbufsz:sizeof(buffer)),
00388 _magic(ERRORLOG__MAGIC),
00389 _errlog_mutex(new pthread_mutex_t),
00390 clog(ownbuf?ownbuf:buffer, ownbuf?ownbufsz:sizeof(buffer))
00391 {
00392 DO_PTHREAD(pthread_mutex_init(_errlog_mutex, NULL));
00393 CRITICAL_SECTION(cs, _errlog_mutex);
00394 _init1();
00395 w_assert9( dest == log_to_open_file );
00396 _init2();
00397 }
00398
00399 ErrLog::~ErrLog()
00400 {
00401 {
00402 CRITICAL_SECTION(cs, _errlog_mutex);
00403 switch(_destination) {
00404 case log_to_unix_file:
00405 case log_to_open_file:
00406 _closelogfile();
00407 break;
00408
00409 case log_to_stderr:
00410
00411
00412
00413 break;
00414
00415 case log_to_ether:
00416 break;
00417 }
00418 if( !_d.table_cleared ) {
00419 ErrLogInfo *ei = _tab.search(this->_ident);
00420 assert(ei!=NULL);
00421
00422 (void) ei->hash_link.detach();
00423 delete ei;
00424 }
00425 }
00426 DO_PTHREAD(pthread_mutex_destroy(_errlog_mutex));
00427 }
00428
00429 void
00430 ErrLog::log(enum LogPriority prio, const char *format, ...)
00431 {
00432 if(_magic != ERRORLOG__MAGIC) {
00433 cerr << "Trying to use uninitialized ErrLog." <<endl;
00434 ::exit(1);
00435 }
00436 va_list ap;
00437 va_start(ap, format);
00438
00439 _flush();
00440
00441 if (prio > _level) {
00442 return;
00443 }
00444
00445 CRITICAL_SECTION(cs, _errlog_mutex);
00446 switch(_destination) {
00447
00448 case log_to_unix_file:
00449 case log_to_open_file:
00450 case log_to_stderr:
00451
00452 #if HAVE_VPRINTF
00453 (void) vfprintf(_file,format, ap);
00454 #else
00455 #error need vfprintf
00456 #endif
00457 fputc('\n', _file);
00458 fflush(_file);
00459 break;
00460
00461 case log_to_ether:
00462 break;
00463 }
00464 va_end(ap);
00465
00466
00467 w_reset_strstream(this->clog);
00468 }
00469
00470 void
00471 ErrLog::_flush()
00472 {
00473 CRITICAL_SECTION(cs, _errlog_mutex);
00474 if(_magic != ERRORLOG__MAGIC) {
00475 cerr << "Fatal error: Trying to use uninitialized ErrLog." <<endl;
00476 ::exit(1);
00477 }
00478 this->clog << ends ;
00479
00480 if (this->clog._prio <= _level) {
00481 switch(_destination) {
00482
00483 case log_to_unix_file:
00484 case log_to_open_file:
00485 case log_to_stderr:
00486 fprintf(_file, "%s", this->clog.c_str());
00487
00488 fflush(_file);
00489 break;
00490
00491 case log_to_ether:
00492 break;
00493 }
00494 }
00495 this->clog.flush();
00496
00497
00498 w_reset_strstream(this->clog);
00499 }