|
reSIProcate/rutil
9694
|
00001 #ifndef RESIP_Log_hxx 00002 #define RESIP_Log_hxx 00003 00004 #include "rutil/Data.hxx" 00005 00006 #ifndef WIN32 00007 #include <syslog.h> 00008 #include <unistd.h> 00009 #endif 00010 00011 #include <set> 00012 00013 #include "rutil/Mutex.hxx" 00014 #include "rutil/Lock.hxx" 00015 #include "rutil/HashMap.hxx" 00016 #include "rutil/ThreadIf.hxx" 00017 #include <iostream> 00018 00019 // !ipse! I think that this remark is no more valid with recent changes, 00020 // but I don't have MacOs X to test with. Someone should take this duty. 00021 // 00022 // NOTE: disabling thread setting code for native mac os applications. 00023 // since some logging takes place during static initialization we can't 00024 // be sure all the pthread stuff is ready to go. this eventually causes 00025 // crashes in the Mac OS native API. 00026 #if !defined(TARGET_OS_MAC) 00027 #define LOG_ENABLE_THREAD_SETTING 00028 // defining hash function in mac os (non-sdk api) and cygwin because 00029 // ThreadIf::Id is a pointer, (this assumes it's always the same pointer) 00030 #if defined(__APPLE__) || defined(__CYGWIN__) 00031 HashValue(resip::ThreadIf::Id); 00032 #endif 00033 #endif 00034 00035 extern "C" 00036 { 00037 // Forward declaration to make it friend of Log class. 00038 void freeLocalLogger(void* pThreadData); 00039 }; 00040 00041 00042 namespace resip 00043 { 00044 00045 class ExternalLogger; 00046 class Subsystem; 00047 00053 class Log 00054 { 00055 public: 00056 enum Type 00057 { 00058 Cout = 0, 00059 Syslog, 00060 File, 00061 Cerr, 00062 VSDebugWindow, 00063 OnlyExternal, 00064 OnlyExternalNoHeaders 00065 00066 }; 00067 00068 enum Level 00069 { 00070 None = -1, 00071 #ifdef WIN32 00072 Crit = 2, 00073 Err = 3, 00074 Warning = 4, 00075 Info = 6, 00076 Debug = 7, 00077 #else 00078 Crit = LOG_CRIT, 00079 // #ifdef ERR // ncurses defines a macro called ERR 00080 // SIP2_ERR = LOG_ERR, 00081 // #else 00082 // ERR = LOG_ERR, 00083 // #endif 00084 Err, 00085 Warning = LOG_WARNING, 00086 Info = LOG_INFO, 00087 Debug = LOG_DEBUG, 00088 #endif 00089 Stack = 8, 00090 StdErr = 9, 00091 Bogus = 666 00092 }; 00093 00095 typedef int LocalLoggerId; 00096 00102 class Guard 00103 { 00104 public: 00107 Guard(Level level, 00108 const Subsystem& system, 00109 const char* file, 00110 int line); 00111 00113 ~Guard(); 00114 00115 EncodeStream& asStream() {return mStream;} 00116 operator EncodeStream&() {return mStream;} 00117 00118 private: 00119 resip::Log::Level mLevel; 00120 const resip::Subsystem& mSubsystem; 00121 resip::Data::size_type mHeaderLength; 00122 const char* mFile; 00123 int mLine; 00124 char mBuffer[128]; 00125 Data mData; 00126 oDataStream mStream; 00127 Guard& operator=(const Guard&); 00128 }; 00129 00130 class ThreadSetting 00131 { 00132 public: 00133 ThreadSetting() 00134 : mService(-1), 00135 mLevel(Err) 00136 {} 00137 00138 ThreadSetting(int serv, Level level) 00139 : mService(serv), 00140 mLevel(level) 00141 { 00142 } 00143 00144 int mService; 00145 Level mLevel; 00146 }; 00147 00149 static EncodeStream& tags(Log::Level level, 00150 const Subsystem& subsystem, 00151 const char* file, 00152 int line, 00153 EncodeStream& strm); 00154 00155 static Data& timestamp(Data& result); 00156 static Data timestamp(); 00157 static ExternalLogger* getExternal() 00158 { 00159 return getLoggerData().mExternalLogger; 00160 } 00161 static Data getAppName() 00162 { 00163 return mAppName; 00164 } 00165 00166 static void initialize(Type type, 00167 Level level, 00168 const Data& appName, 00169 const char * logFileName = 0, 00170 ExternalLogger* externalLogger = 0); 00171 static void initialize(const Data& type, 00172 const Data& level, 00173 const Data& appName, 00174 const char * logFileName = 0, 00175 ExternalLogger* externalLogger = 0); 00176 static void initialize(const char* type, 00177 const char* level, 00178 const char* appName, 00179 const char * logFileName = 0, 00180 ExternalLogger* externalLogger = 0); 00181 static void initialize(Type type, 00182 Level level, 00183 const Data& appName, 00184 ExternalLogger& logger); 00185 00189 static void setLevel(Level level); 00191 static void setLevel(Level level, Subsystem& s); 00193 static void setLevel(Level level, LocalLoggerId loggerId); 00197 static Level level() { Lock lock(_mutex); return getLoggerData().mLevel; } 00199 static Level level(LocalLoggerId loggerId); 00200 static LocalLoggerId id() { Lock lock(_mutex); return getLoggerData().id(); } 00201 static void setMaxLineCount(unsigned int maxLineCount); 00202 static void setMaxLineCount(unsigned int maxLineCount, LocalLoggerId loggerId); 00203 static void setMaxByteCount(unsigned int maxByteCount); 00204 static void setMaxByteCount(unsigned int maxByteCount, LocalLoggerId loggerId); 00205 static Level toLevel(const Data& l); 00206 static Type toType(const Data& t); 00207 static Data toString(Level l); 00208 00210 static void setServiceLevel(int service, Level l); 00211 static Level getServiceLevel(int service); 00212 00214 static const ThreadSetting* getThreadSetting(); 00215 static void setThreadSetting(ThreadSetting info); 00216 static void setThreadSetting(int serv, Level l); 00217 static void setThreadSetting(int serv); 00218 00220 static LocalLoggerId localLoggerCreate(Type type, 00221 Level level, 00222 const char * logFileName = NULL, 00223 ExternalLogger* externalLogger = NULL); 00224 00229 static int localLoggerReinitialize(LocalLoggerId loggerId, 00230 Type type, 00231 Level level, 00232 const char * logFileName = NULL, 00233 ExternalLogger* externalLogger = NULL); 00234 00241 static int localLoggerRemove(LocalLoggerId loggerId); 00242 00249 static int setThreadLocalLogger(LocalLoggerId loggerId); 00250 00251 00252 static std::ostream& Instance(unsigned int bytesToWrite); 00253 static bool isLogging(Log::Level level, const Subsystem&); 00254 static void OutputToWin32DebugWindow(const Data& result); 00255 static void reset(); 00256 00257 public: 00258 static unsigned int MaxLineCount; 00259 static unsigned int MaxByteCount; 00260 00261 protected: 00262 static Mutex _mutex; 00263 static volatile short touchCount; 00264 static const Data delim; 00265 00266 class ThreadData 00267 { 00268 public: 00269 ThreadData(LocalLoggerId id, Type type=Cout, Level level=Info, 00270 const char *logFileName=NULL, 00271 ExternalLogger *pExternalLogger=NULL) 00272 : mLevel(level), 00273 mMaxLineCount(0), 00274 mMaxByteCount(0), 00275 mExternalLogger(pExternalLogger), 00276 mId(id), 00277 mType(type), 00278 mLogger(NULL), 00279 mLineCount(0) 00280 { 00281 if (logFileName) 00282 { 00283 mLogFileName = logFileName; 00284 } 00285 } 00286 ~ThreadData() { reset(); } 00287 00288 void set(Type type=Cout, Level level=Info, 00289 const char *logFileName=NULL, 00290 ExternalLogger *pExternalLogger=NULL) 00291 { 00292 mType = type; 00293 mLevel = level; 00294 00295 if (logFileName) 00296 { 00297 mLogFileName = logFileName; 00298 } 00299 mExternalLogger = pExternalLogger; 00300 } 00301 00302 LocalLoggerId id() const {return mId;} 00303 unsigned int maxLineCount() { return mMaxLineCount ? mMaxLineCount : MaxLineCount; } // return local max, if not set use global max 00304 unsigned int maxByteCount() { return mMaxByteCount ? mMaxByteCount : MaxByteCount; } // return local max, if not set use global max 00305 00306 std::ostream& Instance(unsigned int bytesToWrite); 00307 void reset(); 00308 00309 volatile Level mLevel; 00310 volatile unsigned int mMaxLineCount; 00311 volatile unsigned int mMaxByteCount; 00312 ExternalLogger* mExternalLogger; 00313 00314 protected: 00315 friend class Guard; 00316 const LocalLoggerId mId; 00317 Type mType; 00318 Data mLogFileName; 00319 std::ostream* mLogger; 00320 unsigned int mLineCount; 00321 }; 00322 00323 static ThreadData mDefaultLoggerData; 00324 static Data mAppName; 00325 static Data mHostname; 00326 #ifndef WIN32 00327 static pid_t mPid; 00328 #else 00329 static int mPid; 00330 #endif 00331 static const char mDescriptions[][32]; 00332 00333 static ThreadData &getLoggerData() 00334 { 00335 ThreadData* pData = static_cast<ThreadData*>(ThreadIf::tlsGetValue(*Log::mLocalLoggerKey)); 00336 return pData?*pData:mDefaultLoggerData; 00337 } 00338 00340 class LocalLoggerMap 00341 { 00342 public: 00343 LocalLoggerMap() 00344 : mLastLocalLoggerId(0) {}; 00345 00347 LocalLoggerId create(Type type, 00348 Level level, 00349 const char * logFileName = NULL, 00350 ExternalLogger* externalLogger = NULL); 00351 00356 int reinitialize(LocalLoggerId loggerId, 00357 Type type, 00358 Level level, 00359 const char * logFileName = NULL, 00360 ExternalLogger* externalLogger = NULL); 00361 00368 int remove(LocalLoggerId loggerId); 00369 00372 ThreadData *getData(LocalLoggerId loggerId); 00373 00375 void decreaseUseCount(LocalLoggerId loggerId); 00376 00377 protected: 00379 typedef HashMap<LocalLoggerId, std::pair<ThreadData*, int> > LoggerInstanceMap; 00380 LoggerInstanceMap mLoggerInstancesMap; 00382 LocalLoggerId mLastLocalLoggerId; 00384 Mutex mLoggerInstancesMapMutex; 00385 }; 00386 00387 friend void ::freeLocalLogger(void* pThreadData); 00388 friend class LogStaticInitializer; 00389 static LocalLoggerMap mLocalLoggerMap; 00390 static ThreadIf::TlsKey* mLocalLoggerKey; 00391 00392 00394 #ifdef LOG_ENABLE_THREAD_SETTING 00395 static HashMap<ThreadIf::Id, std::pair<ThreadSetting, bool> > mThreadToLevel; 00396 static HashMap<int, std::set<ThreadIf::Id> > mServiceToThreads; 00397 static ThreadIf::TlsKey* mLevelKey; 00398 #endif 00399 static HashMap<int, Level> mServiceToLevel; 00400 }; 00401 00404 class ExternalLogger 00405 { 00406 public: 00407 virtual ~ExternalLogger() {}; 00409 virtual bool operator()(Log::Level level, 00410 const Subsystem& subsystem, 00411 const Data& appName, 00412 const char* file, 00413 int line, 00414 const Data& message, 00415 const Data& messageWithHeaders) = 0; 00416 }; 00417 00419 class LogStaticInitializer { 00420 public: 00421 LogStaticInitializer(); 00422 ~LogStaticInitializer(); 00423 protected: 00424 static unsigned int mInstanceCounter; 00425 00426 #ifdef WIN32 00427 // LogStaticInitializer calls ThreadIf::tlsKeyCreate which 00428 // relies on the static TlsDestructorInitializer having set 00429 // up mTlsDestructorsMutex which is used to Lock TLS access 00430 // Since the order of static initialization is not reliable, 00431 // we must make sure that TlsDestructorInitializer is initialized 00432 // before LogStaticInitializer is inizialized: 00433 TlsDestructorInitializer tlsDestructorInitializer; 00434 #endif 00435 }; 00436 static LogStaticInitializer _staticLogInit; 00437 00438 } 00439 00440 #endif 00441 00442 /* ==================================================================== 00443 * The Vovida Software License, Version 1.0 00444 * 00445 * Copyright (c) 2000-2005. 00446 * 00447 * Redistribution and use in source and binary forms, with or without 00448 * modification, are permitted provided that the following conditions 00449 * are met: 00450 * 00451 * 1. Redistributions of source code must retain the above copyright 00452 * notice, this list of conditions and the following disclaimer. 00453 * 00454 * 2. Redistributions in binary form must reproduce the above copyright 00455 * notice, this list of conditions and the following disclaimer in 00456 * the documentation and/or other materials provided with the 00457 * distribution. 00458 * 00459 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00460 * and "Vovida Open Communication Application Library (VOCAL)" must 00461 * not be used to endorse or promote products derived from this 00462 * software without prior written permission. For written 00463 * permission, please contact vocal@vovida.org. 00464 * 00465 * 4. Products derived from this software may not be called "VOCAL", nor 00466 * may "VOCAL" appear in their name, without prior written 00467 * permission of Vovida Networks, Inc. 00468 * 00469 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00470 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00471 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00472 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00473 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00474 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00475 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00476 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00477 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00478 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00479 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00480 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00481 * DAMAGE. 00482 * 00483 * ==================================================================== 00484 * 00485 * This software consists of voluntary contributions made by Vovida 00486 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00487 * Inc. For more information on Vovida Networks, Inc., please see 00488 * <http://www.vovida.org/>. 00489 * 00490 */
1.7.5.1