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