00001 //------------------------------------------------------------------------------ 00002 // Copyright (c) 2011-2014 by European Organization for Nuclear Research (CERN) 00003 // Author: Lukasz Janyst <ljanyst@cern.ch> 00004 //------------------------------------------------------------------------------ 00005 // This file is part of the XRootD software suite. 00006 // 00007 // XRootD is free software: you can redistribute it and/or modify 00008 // it under the terms of the GNU Lesser General Public License as published by 00009 // the Free Software Foundation, either version 3 of the License, or 00010 // (at your option) any later version. 00011 // 00012 // XRootD is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU Lesser General Public License 00018 // along with XRootD. If not, see <http://www.gnu.org/licenses/>. 00019 // 00020 // In applying this licence, CERN does not waive the privileges and immunities 00021 // granted to it by virtue of its status as an Intergovernmental Organization 00022 // or submit itself to any jurisdiction. 00023 //------------------------------------------------------------------------------ 00024 00025 #ifndef __XRD_CL_LOG_HH__ 00026 #define __XRD_CL_LOG_HH__ 00027 00028 #include <stdarg.h> 00029 #include <string> 00030 #include <map> 00031 #include <stdint.h> 00032 #include "XrdSys/XrdSysPthread.hh" 00033 00034 //------------------------------------------------------------------------------ 00035 // C++11 atomics are used to avoid illegal behavior when setting/getting the 00036 // log level. To minimize costs across all platforms, we use 00037 // std::memory_order_relaxed; this means threads may reorder SetLogLevel writes 00038 // and the visibility is relatively undefined. However, we know the stores are 00039 // at least atomic. 00040 //------------------------------------------------------------------------------ 00041 #if __cplusplus >= 201103L 00042 #include <atomic> 00043 #endif 00044 00045 namespace XrdCl 00046 { 00047 //---------------------------------------------------------------------------- 00049 //---------------------------------------------------------------------------- 00050 class LogOut 00051 { 00052 public: 00053 virtual ~LogOut() {} 00054 00055 //------------------------------------------------------------------------ 00059 //------------------------------------------------------------------------ 00060 virtual void Write( const std::string &message ) = 0; 00061 }; 00062 00063 //---------------------------------------------------------------------------- 00065 //---------------------------------------------------------------------------- 00066 class LogOutFile: public LogOut 00067 { 00068 public: 00069 LogOutFile(): pFileDes(-1) {}; 00070 virtual ~LogOutFile() { Close(); }; 00071 00072 //------------------------------------------------------------------------ 00074 //------------------------------------------------------------------------ 00075 bool Open( const std::string &fileName ); 00076 00077 //------------------------------------------------------------------------ 00079 //------------------------------------------------------------------------ 00080 void Close(); 00081 virtual void Write( const std::string &message ); 00082 private: 00083 int pFileDes; 00084 }; 00085 00086 //---------------------------------------------------------------------------- 00088 //---------------------------------------------------------------------------- 00089 class LogOutCerr: public LogOut 00090 { 00091 public: 00092 virtual void Write( const std::string &message ); 00093 virtual ~LogOutCerr() {} 00094 private: 00095 XrdSysMutex pMutex; 00096 }; 00097 00098 //---------------------------------------------------------------------------- 00100 //---------------------------------------------------------------------------- 00101 class Log 00102 { 00103 public: 00104 //------------------------------------------------------------------------ 00106 //------------------------------------------------------------------------ 00107 enum LogLevel 00108 { 00109 NoMsg = 0, 00110 ErrorMsg = 1, 00111 WarningMsg = 2, 00112 InfoMsg = 3, 00113 DebugMsg = 4, 00114 DumpMsg = 5 00115 }; 00116 00117 //------------------------------------------------------------------------ 00119 //------------------------------------------------------------------------ 00120 Log(): pLevel( NoMsg ), pTopicMaxLength( 18 ), pPid(0) 00121 { 00122 pOutput = new LogOutCerr(); 00123 int maxMask = (int)DumpMsg+1; 00124 for( int i = 0; i < maxMask; ++i ) 00125 pMask[i] = 0xffffffffffffffffULL; 00126 } 00127 00128 //------------------------------------------------------------------------ 00129 // Destructor 00130 //------------------------------------------------------------------------ 00131 ~Log() 00132 { 00133 delete pOutput; 00134 } 00135 00136 //------------------------------------------------------------------------ 00138 //------------------------------------------------------------------------ 00139 void Error( uint64_t topic, const char *format, ... ); 00140 00141 //------------------------------------------------------------------------ 00143 //------------------------------------------------------------------------ 00144 void Warning( uint64_t topic, const char *format, ... ); 00145 00146 //------------------------------------------------------------------------ 00148 //------------------------------------------------------------------------ 00149 void Info( uint64_t topic, const char *format, ... ); 00150 00151 //------------------------------------------------------------------------ 00153 //------------------------------------------------------------------------ 00154 void Debug( uint64_t topic, const char *format, ... ); 00155 00156 //------------------------------------------------------------------------ 00158 //------------------------------------------------------------------------ 00159 void Dump( uint64_t topic, const char *format, ... ); 00160 00161 //------------------------------------------------------------------------ 00168 //------------------------------------------------------------------------ 00169 void Say( LogLevel level, uint64_t topic, const char *format, va_list list ); 00170 00171 //------------------------------------------------------------------------ 00173 //------------------------------------------------------------------------ 00174 void SetLevel( LogLevel level ) 00175 { 00176 #if __cplusplus >= 201103L 00177 pLevel.store(level, std::memory_order_relaxed); 00178 #else 00179 pLevel = level; 00180 #endif 00181 } 00182 00183 //------------------------------------------------------------------------ 00185 //------------------------------------------------------------------------ 00186 void SetLevel( const std::string &level ) 00187 { 00188 LogLevel lvl; 00189 if( StringToLogLevel( level, lvl ) ) 00190 SetLevel( lvl ); 00191 } 00192 00193 //------------------------------------------------------------------------ 00195 //------------------------------------------------------------------------ 00196 void SetOutput( LogOut *output ) 00197 { 00198 delete pOutput; 00199 pOutput = output; 00200 } 00201 00202 //------------------------------------------------------------------------ 00204 //------------------------------------------------------------------------ 00205 void SetMask( LogLevel level, uint64_t mask ) 00206 { 00207 pMask[level] = mask; 00208 } 00209 00210 //------------------------------------------------------------------------ 00212 //------------------------------------------------------------------------ 00213 void SetMask( const std::string &level, uint64_t mask ) 00214 { 00215 LogLevel lvl; 00216 if( StringToLogLevel( level, lvl ) ) 00217 pMask[lvl] = mask; 00218 } 00219 00220 //------------------------------------------------------------------------ 00222 //------------------------------------------------------------------------ 00223 void SetTopicName( uint64_t topic, std::string name ); 00224 00225 //------------------------------------------------------------------------ 00227 //------------------------------------------------------------------------ 00228 LogLevel GetLevel() const 00229 { 00230 #if __cplusplus >= 201103L 00231 LogLevel lvl = pLevel.load(std::memory_order_relaxed); 00232 return lvl; 00233 #else 00234 return pLevel; 00235 #endif 00236 } 00237 00238 //------------------------------------------------------------------------ 00240 //------------------------------------------------------------------------ 00241 void SetPid(pid_t pid) 00242 { 00243 pPid = pid; 00244 } 00245 00246 private: 00247 typedef std::map<uint64_t, std::string> TopicMap; 00248 std::string LogLevelToString( LogLevel level ); 00249 bool StringToLogLevel( const std::string &strLevel, LogLevel &level ); 00250 std::string TopicToString( uint64_t topic ); 00251 00252 #if __cplusplus >= 201103L 00253 std::atomic<LogLevel> pLevel; 00254 #else 00255 LogLevel pLevel; 00256 #endif 00257 uint64_t pMask[DumpMsg+1]; 00258 LogOut *pOutput; 00259 TopicMap pTopicMap; 00260 uint32_t pTopicMaxLength; 00261 pid_t pPid; 00262 }; 00263 } 00264 00265 #endif // __XRD_CL_LOG_HH__