用于EagleEye3.0 规则集漏报和误报测试的示例项目,项目收集于github和gitee
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1924 lines
48 KiB

/*
* Log4z License
* -----------
*
* Log4z is licensed under the terms of the MIT license reproduced below.
* This means that Log4z is free software and can be used for both academic
* and commercial purposes at absolutely no cost.
*
*
* ===============================================================================
*
* Copyright (C) 2010-2015 YaweiZhang <yawei.zhang@foxmail.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* ===============================================================================
*
* (end of COPYRIGHT)
*/
#include "log4z.h"
#include <unknown/obj-ref-impl.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <string>
#include <vector>
#include <map>
#include <list>
#include <sstream>
#include <iostream>
#include <fstream>
#include <algorithm>
#if defined (WIN32) || defined(_WIN64)
#include <io.h>
#include <shlwapi.h>
#include <process.h>
#pragma comment(lib, "shlwapi")
#pragma warning(disable:4996)
#else
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<pthread.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <semaphore.h>
#endif
#ifdef __APPLE__
#include <dispatch/dispatch.h>
#include <libproc.h>
#endif
#include <string>
#include <sstream>
#include <errno.h>
#include <stdio.h>
#if defined(WIN32) || defined(_WIN64)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <intrin.h>
#endif
#include <vector>
#include <map>
#include <list>
#include <queue>
#include <deque>
using namespace SOUI;
static const char *const LOG_STRING[]=
{
"TRACE",
"DEBUG",
"INFO ",
"WARN ",
"ERROR",
"ALARM",
"FATAL",
};
#if defined (WIN32) || defined(_WIN64)
const static WORD LOG_COLOR[ILog4zManager::LOG_LEVEL_FATAL + 1] = {
0,
0,
FOREGROUND_BLUE | FOREGROUND_GREEN,
FOREGROUND_GREEN | FOREGROUND_RED,
FOREGROUND_RED,
FOREGROUND_GREEN,
FOREGROUND_RED | FOREGROUND_BLUE };
#else
const static char LOG_COLOR[LOG_LEVEL_FATAL + 1][50] = {
"\e[0m",
"\e[0m",
"\e[34m\e[1m",//hight blue
"\e[33m", //yellow
"\e[31m", //red
"\e[32m", //green
"\e[35m" };
#endif
//////////////////////////////////////////////////////////////////////////
//! Log4zFileHandler
//////////////////////////////////////////////////////////////////////////
class Log4zFileHandler
{
public:
Log4zFileHandler(){ _file = NULL; }
~Log4zFileHandler(){ close(); }
inline bool isOpen(){ return _file != NULL; }
inline bool open(const char *path, const char * mod)
{
if (_file != NULL){fclose(_file);_file = NULL;}
_file = fopen(path, mod);
return _file != NULL;
}
inline void close()
{
if (_file != NULL){fclose(_file);_file = NULL;}
}
inline void write(const char * data, size_t len)
{
if (_file && len > 0)
{
if (fwrite(data, 1, len, _file) != len)
{
close();
}
}
}
inline void flush(){ if (_file) fflush(_file); }
inline std::string readLine()
{
char buf[500] = { 0 };
if (_file && fgets(buf, 500, _file) != NULL)
{
return std::string(buf);
}
return std::string();
}
inline const std::string readContent();
inline size_t size() const{
if(!_file) return 0;
size_t pos = ftell(_file);
fseek(_file,0,SEEK_END);
size_t ret = ftell(_file);
fseek(_file,pos,SEEK_SET);
return ret;
}
public:
FILE *_file;
};
//////////////////////////////////////////////////////////////////////////
//! UTILITY
//////////////////////////////////////////////////////////////////////////
static void sleepMillisecond(unsigned int ms);
static tm timeToTm(time_t t);
static bool isSameDay(time_t t1, time_t t2);
static void fixPath(std::string &path);
static void trimLogConfig(std::string &str, std::string extIgnore = std::string());
static std::pair<std::string, std::string> splitPairString(const std::string & str, const std::string & delimiter);
static bool isDirectory(std::string path);
static bool createRecursionDir(std::string path);
static unsigned int getProcessID();
static std::string getProcessName();
//////////////////////////////////////////////////////////////////////////
//! LockHelper
//////////////////////////////////////////////////////////////////////////
class LockHelper
{
public:
LockHelper();
virtual ~LockHelper();
public:
void lock();
void unLock();
private:
#if defined (WIN32) || defined(_WIN64)
CRITICAL_SECTION _crit;
#else
pthread_mutex_t _crit;
#endif
};
//////////////////////////////////////////////////////////////////////////
//! AutoLock
//////////////////////////////////////////////////////////////////////////
class AutoLock
{
public:
explicit AutoLock(LockHelper & lk):_lock(lk){_lock.lock();}
~AutoLock(){_lock.unLock();}
private:
LockHelper & _lock;
};
//////////////////////////////////////////////////////////////////////////
//! SemHelper
//////////////////////////////////////////////////////////////////////////
class SemHelper
{
public:
SemHelper();
virtual ~SemHelper();
public:
bool create(int initcount);
bool wait(int timeout = 0);
bool post();
private:
#if defined (WIN32) || defined(_WIN64)
HANDLE _hSem;
#elif defined(__APPLE__)
dispatch_semaphore_t _semid;
#else
sem_t _semid;
bool _isCreate;
#endif
};
//////////////////////////////////////////////////////////////////////////
//! ThreadHelper
//////////////////////////////////////////////////////////////////////////
#if defined (WIN32) || defined(_WIN64)
static unsigned int WINAPI threadProc(LPVOID lpParam);
#else
static void * threadProc(void * pParam);
#endif
class ThreadHelper
{
public:
ThreadHelper(){_hThreadID = 0;}
virtual ~ThreadHelper(){}
public:
bool start();
bool wait();
virtual void run() = 0;
private:
unsigned long long _hThreadID;
#ifndef WIN32
pthread_t _phtreadID;
#endif
};
#if defined (WIN32) || defined(_WIN64)
unsigned int WINAPI threadProc(LPVOID lpParam)
{
ThreadHelper * p = (ThreadHelper *) lpParam;
p->run();
return 0;
}
#else
void * threadProc(void * pParam)
{
ThreadHelper * p = (ThreadHelper *) pParam;
p->run();
return NULL;
}
#endif
//////////////////////////////////////////////////////////////////////////
//! LogData
//////////////////////////////////////////////////////////////////////////
struct LogData
{
LoggerId _id; //dest logger id
int _level; //log level
unsigned __int64 _time; //create time
DWORD _pid;
DWORD _tid;
std::string _content; //content
std::string _filter;
std::string _moduleName;
std::string _file;
std::string _func;
int _line;
};
//////////////////////////////////////////////////////////////////////////
//! LoggerInfo
//////////////////////////////////////////////////////////////////////////
struct LoggerInfo
{
//! attribute
std::string _key; //logger key
std::string _name; // one logger one name.
std::string _path; //path for log file.
int _level; //filter level
bool _display; //display to screen
bool _outfile; //output to file
unsigned int _limitsize; //limit file's size, unit Million byte.
bool _enable; //logger is enable
bool _fileLine; //enable/disable the log's suffix.(file name:line number)
//! runtime info
time_t _curFileCreateTime; //file create time
unsigned int _curWriteLen; //current file length
Log4zFileHandler _handle; //file handle.
LoggerInfo()
{
_enable = false;
_path = LOG4Z_DEFAULT_PATH;
_level = LOG4Z_DEFAULT_LEVEL;
_display = LOG4Z_DEFAULT_DISPLAY;
_outfile = LOG4Z_DEFAULT_OUTFILE;
_limitsize = LOG4Z_DEFAULT_LIMITSIZE;
_fileLine = LOG4Z_DEFAULT_SHOWSUFFIX;
_curFileCreateTime = 0;
_curWriteLen = 0;
}
};
class COutoutFileBuilder : public ILog4zManager::IOutputFileBuilder
{
public:
virtual bool monthDir() const
{
return false;
}
virtual bool dayLog() const
{
return false;
}
virtual bool buildOutputFile(char *pszFileName,int nLen,tm time,const char * pszLogName,unsigned long pid,int curFileIndex) const
{
sprintf_s(pszFileName,nLen,"%s-%d.log",pszLogName,curFileIndex);
return true;
}
}s_defOutputFileBuilder;
//////////////////////////////////////////////////////////////////////////
//! LogerManager
//////////////////////////////////////////////////////////////////////////
class LogerManager : public ThreadHelper, public TObjRefImpl<ILog4zManager>
{
public:
LogerManager();
virtual ~LogerManager();
bool configFromStringImpl(std::string content, bool isUpdate);
//! 读取配置文件并覆写
virtual bool config(const char* configPath);
virtual bool configFromString(const char* configContent);
//! 覆写式创建
virtual LoggerId createLogger(const char* key);
virtual bool start();
virtual bool stop();
virtual bool prePushLog(LoggerId id, int level);
virtual bool prePushLog(const char * name, int level);
virtual bool pushLog(LoggerId id, int level,const char * filter, const char * log, const char * file, int line, const char *func, const void * pRetAddr);
virtual bool pushLog(const char * name, int level, const char * filter, const char * log, const char * file, int line, const char *func, const void * pRetAddr);
//! 查找ID
virtual LoggerId findLogger(const char* key);
virtual bool enableLogger(LoggerId id, bool enable);
virtual bool setLoggerName(LoggerId id, const char * name);
virtual bool setLoggerPath(LoggerId id, const char * path);
virtual bool setLoggerLevel(LoggerId id, int nLevel);
virtual bool setLoggerFileLine(LoggerId id, bool enable);
virtual bool setLoggerDisplay(LoggerId id, bool enable);
virtual bool setLoggerOutFile(LoggerId id, bool enable);
virtual bool setLoggerLimitsize(LoggerId id, unsigned int limitsize);
virtual void setOutputFileBuilder(IOutputFileBuilder *pOutputFileBuilder);
virtual bool setLoggerFileMaxNum(unsigned int maxnum);
virtual bool setAutoUpdate(int interval);
virtual bool updateConfig();
virtual bool isLoggerEnable(LoggerId id);
virtual unsigned long long getStatusTotalWriteCount(){return _ullStatusTotalWriteFileCount;}
virtual unsigned long long getStatusTotalWriteBytes(){return _ullStatusTotalWriteFileBytes;}
virtual unsigned long long getStatusWaitingCount(){return _ullStatusTotalPushLog - _ullStatusTotalPopLog;}
virtual unsigned int getStatusActiveLoggers();
virtual void setOutputListener(IOutputListener *pListener);
protected:
void showColorText(const char *text, int level = LOG_LEVEL_DEBUG);
LoggerId getLoggerId(const char * name);
bool openLogger(LogData * log);
bool closeLogger(LoggerId id);
bool popLog(LogData *& log);
virtual void run();
private:
//! thread status.
bool _runing;
//! hot change name or path for one logger
LockHelper _hotLock;
int _hotUpdateInterval;
unsigned int _checksum;
//! the process info.
unsigned int _pid;
std::string _proName;
//! config file name
std::string _configFile;
//! logger id manager, [logger name]:[logger id].
std::map<std::string, LoggerId> _ids;
std::map<LoggerId, std::string> _names;
// the last used id of _loggers
LoggerId _lastId;
LoggerInfo _loggers[LOG4Z_LOGGER_MAX];
//! log queue
std::list<LogData *> _logs;
LockHelper _logLock;
//show color lock
LockHelper _scLock;
//status statistics
//write file
unsigned long long _ullStatusTotalWriteFileCount;
unsigned long long _ullStatusTotalWriteFileBytes;
//Log queue statistics
unsigned long long _ullStatusTotalPushLog;
unsigned long long _ullStatusTotalPopLog;
IOutputFileBuilder * m_pOutputFileBuilder;
IOutputListener * m_pListener;
unsigned int _maxFileNum;
};
//////////////////////////////////////////////////////////////////////////
//! Log4zFileHandler
//////////////////////////////////////////////////////////////////////////
const std::string Log4zFileHandler::readContent()
{
std::string content;
if (!_file)
{
return content;
}
char buf[BUFSIZ];
size_t ret = 0;
do
{
ret = fread(buf, sizeof(char), BUFSIZ, _file);
content.append(buf, ret);
}
while (ret == BUFSIZ);
return content;
}
//////////////////////////////////////////////////////////////////////////
//! utility
//////////////////////////////////////////////////////////////////////////
void sleepMillisecond(unsigned int ms)
{
#if defined (WIN32) || defined(_WIN64)
::Sleep(ms);
#else
usleep(1000*ms);
#endif
}
struct tm timeToTm(time_t t)
{
#if defined (WIN32) || defined(_WIN64)
#if _MSC_VER < 1400 //VS2003
return * localtime(&t);
#else //vs2005->vs2013->
struct tm tt = { 0 };
localtime_s(&tt, &t);
return tt;
#endif
#else //linux
struct tm tt = { 0 };
localtime_r(&t, &tt);
return tt;
#endif
}
bool isSameDay(time_t t1, time_t t2)
{
tm tm1 = timeToTm(t1);
tm tm2 = timeToTm(t2);
if ( tm1.tm_year == tm2.tm_year
&& tm1.tm_yday == tm2.tm_yday)
{
return true;
}
return false;
}
void fixPath(std::string &path)
{
if (path.empty()){return;}
for (std::string::iterator iter = path.begin(); iter != path.end(); ++iter)
{
if (*iter == '\\'){*iter = '/';}
}
if (path.at(path.length()-1) != '/'){path.append("/");}
}
static void trimLogConfig(std::string &str, std::string extIgnore)
{
if (str.empty()){return;}
extIgnore += "\r\n\t ";
int length = (int)str.length();
int posBegin = 0;
int posEnd = 0;
//trim utf8 file bom
if (str.length() >= 3
&& (unsigned char)str[0] == 0xef
&& (unsigned char)str[1] == 0xbb
&& (unsigned char)str[2] == 0xbf)
{
posBegin = 3;
}
//trim character
for (int i = posBegin; i<length; i++)
{
bool bCheck = false;
for (int j = 0; j < (int)extIgnore.length(); j++)
{
if (str[i] == extIgnore[j])
{
bCheck = true;
}
}
if (bCheck)
{
if (i == posBegin)
{
posBegin++;
}
}
else
{
posEnd = i + 1;
}
}
if (posBegin < posEnd)
{
str = str.substr(posBegin, posEnd-posBegin);
}
else
{
str.clear();
}
}
//split
static std::pair<std::string, std::string> splitPairString(const std::string & str, const std::string & delimiter)
{
std::string::size_type pos = str.find(delimiter.c_str());
if (pos == std::string::npos)
{
return std::make_pair(str, "");
}
return std::make_pair(str.substr(0, pos), str.substr(pos+delimiter.length()));
}
static bool parseConfigLine(const std::string& line, int curLineNum, std::string & key, std::map<std::string, LoggerInfo> & outInfo)
{
std::pair<std::string, std::string> kv = splitPairString(line, "=");
if (kv.first.empty())
{
return false;
}
trimLogConfig(kv.first);
trimLogConfig(kv.second);
if (kv.first.empty() || kv.first.at(0) == '#')
{
return true;
}
if (kv.first.at(0) == '[')
{
trimLogConfig(kv.first, "[]");
key = kv.first;
{
std::string tmpstr = kv.first;
std::transform(tmpstr.begin(), tmpstr.end(), tmpstr.begin(), ::tolower);
if (tmpstr == "main")
{
key = "Main";
}
}
std::map<std::string, LoggerInfo>::iterator iter = outInfo.find(key);
if (iter == outInfo.end())
{
LoggerInfo li;
li._enable = true;
li._key = key;
li._name = key;
outInfo.insert(std::make_pair(li._key, li));
}
else
{
std::cout << "log4z configure warning: duplicate logger key:["<< key << "] at line:" << curLineNum << std::endl;
}
return true;
}
trimLogConfig(kv.first);
trimLogConfig(kv.second);
std::map<std::string, LoggerInfo>::iterator iter = outInfo.find(key);
if (iter == outInfo.end())
{
std::cout << "log4z configure warning: not found current logger name:["<< key << "] at line:" << curLineNum
<< ", key=" << kv.first << ", value=" << kv.second << std::endl;
return true;
}
std::transform(kv.first.begin(), kv.first.end(), kv.first.begin(), ::tolower);
//! path
if (kv.first == "path")
{
iter->second._path = kv.second;
return true;
}
else if (kv.first == "name")
{
iter->second._name = kv.second;
return true;
}
std::transform(kv.second.begin(), kv.second.end(), kv.second.begin(), ::tolower);
//! level
if (kv.first == "level")
{
if (kv.second == "trace" || kv.second == "all")
{
iter->second._level = ILog4zManager::LOG_LEVEL_TRACE;
}
else if (kv.second == "debug")
{
iter->second._level = ILog4zManager::LOG_LEVEL_DEBUG;
}
else if (kv.second == "info")
{
iter->second._level = ILog4zManager::LOG_LEVEL_INFO;
}
else if (kv.second == "warn" || kv.second == "warning")
{
iter->second._level = ILog4zManager::LOG_LEVEL_WARN;
}
else if (kv.second == "error")
{
iter->second._level = ILog4zManager::LOG_LEVEL_ERROR;
}
else if (kv.second == "alarm")
{
iter->second._level = ILog4zManager::LOG_LEVEL_ALARM;
}
else if (kv.second == "fatal")
{
iter->second._level = ILog4zManager::LOG_LEVEL_FATAL;
}
}
//! display
else if (kv.first == "display")
{
if (kv.second == "false" || kv.second == "0")
{
iter->second._display = false;
}
else
{
iter->second._display = true;
}
}
//! output to file
else if (kv.first == "outfile")
{
if (kv.second == "false" || kv.second == "0")
{
iter->second._outfile = false;
}
else
{
iter->second._outfile = true;
}
}
//! limit file size
else if (kv.first == "limitsize")
{
iter->second._limitsize = atoi(kv.second.c_str());
}
//! display log in file line
else if (kv.first == "fileline")
{
if (kv.second == "false" || kv.second == "0")
{
iter->second._fileLine = false;
}
else
{
iter->second._fileLine = true;
}
}
//! enable/disable one logger
else if (kv.first == "enable")
{
if (kv.second == "false" || kv.second == "0")
{
iter->second._enable = false;
}
else
{
iter->second._enable = true;
}
}
return true;
}
static bool parseConfigFromString(std::string content, std::map<std::string, LoggerInfo> & outInfo)
{
std::string key;
int curLine = 1;
std::string line;
std::string::size_type curPos = 0;
if (content.empty())
{
return true;
}
do
{
std::string::size_type pos = std::string::npos;
for (std::string::size_type i = curPos; i < content.length(); ++i)
{
//support linux/unix/windows LRCF
if (content[i] == '\r' || content[i] == '\n')
{
pos = i;
break;
}
}
line = content.substr(curPos, pos - curPos);
parseConfigLine(line, curLine, key, outInfo);
curLine++;
if (pos == std::string::npos)
{
break;
}
else
{
curPos = pos+1;
}
} while (1);
return true;
}
bool isDirectory(std::string path)
{
#if defined (WIN32) || defined(_WIN64)
return PathIsDirectoryA(path.c_str()) ? true : false;
#else
DIR * pdir = opendir(path.c_str());
if (pdir == NULL)
{
return false;
}
else
{
closedir(pdir);
pdir = NULL;
return true;
}
#endif
}
bool createRecursionDir(std::string path)
{
if (path.length() == 0) return true;
std::string sub;
fixPath(path);
std::string::size_type pos = path.find('/');
while (pos != std::string::npos)
{
std::string cur = path.substr(0, pos-0);
if (cur.length() > 0 && !isDirectory(cur))
{
bool ret = false;
#if defined (WIN32) || defined(_WIN64)
ret = CreateDirectoryA(cur.c_str(), NULL) ? true : false;
#else
ret = (mkdir(cur.c_str(), S_IRWXU|S_IRWXG|S_IRWXO) == 0);
#endif
if (!ret)
{
return false;
}
}
pos = path.find('/', pos+1);
}
return true;
}
unsigned int getProcessID()
{
#if defined (WIN32) || defined(_WIN64)
return GetCurrentProcessId();
#else
return getpid();
#endif
}
std::string getProcessName()
{
std::string name = "MainLog";
char buf[260] = {0};
#if defined (WIN32) || defined(_WIN64)
if (GetModuleFileNameA(NULL, buf, 259) > 0)
{
name = buf;
}
std::string::size_type pos = name.rfind("\\");
if (pos != std::string::npos)
{
name = name.substr(pos+1, std::string::npos);
}
pos = name.rfind(".");
if (pos != std::string::npos)
{
name = name.substr(0, pos-0);
}
#elif defined(__APPLE__)
proc_name(getpid(), buf, 260);
name = buf;
return name;;
#else
sprintf(buf, "/proc/%d/cmdline", (int)getpid());
Log4zFileHandler i;
i.open(buf, "rb");
if (!i.isOpen())
{
return name;
}
name = i.readLine();
i.close();
std::string::size_type pos = name.rfind("/");
if (pos != std::string::npos)
{
name = name.substr(pos+1, std::string::npos);
}
#endif
return name;
}
//////////////////////////////////////////////////////////////////////////
// LockHelper
//////////////////////////////////////////////////////////////////////////
LockHelper::LockHelper()
{
#if defined (WIN32) || defined(_WIN64)
InitializeCriticalSection(&_crit);
#else
//_crit = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&_crit, &attr);
pthread_mutexattr_destroy(&attr);
#endif
}
LockHelper::~LockHelper()
{
#if defined (WIN32) || defined(_WIN64)
DeleteCriticalSection(&_crit);
#else
pthread_mutex_destroy(&_crit);
#endif
}
void LockHelper::lock()
{
#if defined (WIN32) || defined(_WIN64)
EnterCriticalSection(&_crit);
#else
pthread_mutex_lock(&_crit);
#endif
}
void LockHelper::unLock()
{
#if defined (WIN32) || defined(_WIN64)
LeaveCriticalSection(&_crit);
#else
pthread_mutex_unlock(&_crit);
#endif
}
//////////////////////////////////////////////////////////////////////////
// SemHelper
//////////////////////////////////////////////////////////////////////////
SemHelper::SemHelper()
{
#if defined (WIN32) || defined(_WIN64)
_hSem = NULL;
#elif defined(__APPLE__)
_semid = NULL;
#else
_isCreate = false;
#endif
}
SemHelper::~SemHelper()
{
#if defined (WIN32) || defined(_WIN64)
if (_hSem != NULL)
{
CloseHandle(_hSem);
_hSem = NULL;
}
#elif defined(__APPLE__)
if (_semid)
{
dispatch_release(_semid);
_semid = NULL;
}
#else
if (_isCreate)
{
_isCreate = false;
sem_destroy(&_semid);
}
#endif
}
bool SemHelper::create(int initcount)
{
if (initcount < 0)
{
initcount = 0;
}
#if defined (WIN32) || defined(_WIN64)
if (initcount > 64)
{
return false;
}
_hSem = CreateSemaphore(NULL, initcount, 64, NULL);
if (_hSem == NULL)
{
return false;
}
#elif defined(__APPLE__)
_semid = dispatch_semaphore_create(initcount);
if (!_semid)
{
return false;
}
#else
if (sem_init(&_semid, 0, initcount) != 0)
{
return false;
}
_isCreate = true;
#endif
return true;
}
bool SemHelper::wait(int timeout)
{
#if defined (WIN32) || defined(_WIN64)
if (timeout <= 0)
{
timeout = INFINITE;
}
if (WaitForSingleObject(_hSem, timeout) != WAIT_OBJECT_0)
{
return false;
}
#elif defined(__APPLE__)
if (dispatch_semaphore_wait(_semid, dispatch_time(DISPATCH_TIME_NOW, timeout*1000)) != 0)
{
return false;
}
#else
if (timeout <= 0)
{
return (sem_wait(&_semid) == 0);
}
else
{
struct timeval tm;
gettimeofday(&tm, NULL);
long long endtime = tm.tv_sec *1000 + tm.tv_usec/1000 + timeout;
do
{
sleepMillisecond(50);
int ret = sem_trywait(&_semid);
if (ret == 0)
{
return true;
}
struct timeval tv_cur;
gettimeofday(&tv_cur, NULL);
if (tv_cur.tv_sec*1000 + tv_cur.tv_usec/1000 > endtime)
{
return false;
}
if (ret == -1 && errno == EAGAIN)
{
continue;
}
else
{
return false;
}
} while (true);
return false;
}
#endif
return true;
}
bool SemHelper::post()
{
#if defined (WIN32) || defined(_WIN64)
return ReleaseSemaphore(_hSem, 1, NULL) ? true : false;
#elif defined(__APPLE__)
return dispatch_semaphore_signal(_semid) == 0;
#else
return (sem_post(&_semid) == 0);
#endif
}
//////////////////////////////////////////////////////////////////////////
//! ThreadHelper
//////////////////////////////////////////////////////////////////////////
bool ThreadHelper::start()
{
#if defined (WIN32) || defined(_WIN64)
unsigned long long ret = _beginthreadex(NULL, 0, threadProc, (void *) this, 0, NULL);
if (ret == -1 || ret == 0)
{
std::cout << "log4z: create log4z thread error! \r\n" <<std::endl;
return false;
}
_hThreadID = ret;
#else
int ret = pthread_create(&_phtreadID, NULL, threadProc, (void*)this);
if (ret != 0)
{
std::cout <<"log4z: create log4z thread error! \r\n" << std::endl;
return false;
}
#endif
return true;
}
bool ThreadHelper::wait()
{
#if defined (WIN32) || defined(_WIN64)
if (WaitForSingleObject((HANDLE)_hThreadID, INFINITE) != WAIT_OBJECT_0)
{
return false;
}
#else
if (pthread_join(_phtreadID, NULL) != 0)
{
return false;
}
#endif
return true;
}
static const char * LOG4Z_MAIN_LOGGER_KEY = "main";
static const LoggerId LOG4Z_INVALID_LOGGER_ID = -1;
//////////////////////////////////////////////////////////////////////////
//! LogerManager
//////////////////////////////////////////////////////////////////////////
LogerManager::LogerManager()
{
_runing = false;
_lastId = LOG4Z_MAIN_LOGGER_ID;
_hotUpdateInterval = 0;
_ullStatusTotalPushLog = 0;
_ullStatusTotalPopLog = 0;
_ullStatusTotalWriteFileCount = 0;
_ullStatusTotalWriteFileBytes = 0;
_pid = getProcessID();
_proName = getProcessName();
_loggers[LOG4Z_MAIN_LOGGER_ID]._enable = true;
_ids[LOG4Z_MAIN_LOGGER_KEY] = LOG4Z_MAIN_LOGGER_ID;
_names[LOG4Z_MAIN_LOGGER_ID] = LOG4Z_MAIN_LOGGER_KEY;
_loggers[LOG4Z_MAIN_LOGGER_ID]._key = LOG4Z_MAIN_LOGGER_KEY;
_loggers[LOG4Z_MAIN_LOGGER_ID]._name = _proName;
m_pOutputFileBuilder = & s_defOutputFileBuilder;
m_pListener = NULL;
}
LogerManager::~LogerManager()
{
stop();
}
LoggerId LogerManager::getLoggerId(const char * name)
{
if(_ids.find(name) == _ids.end())
return LOG4Z_INVALID_LOGGER_ID;
else
return _ids[name];
}
void LogerManager::showColorText(const char *text, int level)
{
if (level <= LOG_LEVEL_DEBUG || level > LOG_LEVEL_FATAL)
{
printf("%s", text);
return;
}
#ifndef WIN32
printf("%s%s\e[0m", LOG_COLOR[level], text);
#else
AutoLock l(_scLock);
HANDLE hStd = ::GetStdHandle(STD_OUTPUT_HANDLE);
if (hStd == INVALID_HANDLE_VALUE) return;
CONSOLE_SCREEN_BUFFER_INFO oldInfo;
if (!GetConsoleScreenBufferInfo(hStd, &oldInfo))
{
return;
}
else
{
SetConsoleTextAttribute(hStd, LOG_COLOR[level]);
printf("%s", text);
SetConsoleTextAttribute(hStd, oldInfo.wAttributes);
}
#endif
return;
}
bool LogerManager::configFromStringImpl(std::string content, bool isUpdate)
{
unsigned int sum = 0;
for (std::string::iterator iter = content.begin(); iter != content.end(); ++iter)
{
sum += (unsigned char)*iter;
}
if (sum == _checksum)
{
return true;
}
_checksum = sum;
std::map<std::string, LoggerInfo> loggerMap;
if (!parseConfigFromString(content, loggerMap))
{
std::cout << " !!! !!! !!! !!!" << std::endl;
std::cout << " !!! !!! log4z load config file error" << std::endl;
std::cout << " !!! !!! !!! !!!" << std::endl;
return false;
}
for (std::map<std::string, LoggerInfo>::iterator iter = loggerMap.begin(); iter != loggerMap.end(); ++iter)
{
LoggerId id = LOG4Z_INVALID_LOGGER_ID;
id = findLogger(iter->second._key.c_str());
if (id == LOG4Z_INVALID_LOGGER_ID)
{
if (isUpdate)
{
continue;
}
else
{
id = createLogger(iter->second._key.c_str());
if (id == LOG4Z_INVALID_LOGGER_ID)
{
continue;
}
}
}
enableLogger(id, iter->second._enable);
setLoggerName(id, iter->second._name.c_str());
setLoggerPath(id, iter->second._path.c_str());
setLoggerLevel(id, iter->second._level);
setLoggerFileLine(id, iter->second._fileLine);
setLoggerDisplay(id, iter->second._display);
setLoggerOutFile(id, iter->second._outfile);
setLoggerLimitsize(id, iter->second._limitsize);
}
return true;
}
//! read configure and create with overwriting
bool LogerManager::config(const char* configPath)
{
if (!_configFile.empty())
{
std::cout << " !!! !!! !!! !!!" << std::endl;
std::cout << " !!! !!! log4z configure error: too many calls to Config. the old config file=" << _configFile << ", the new config file=" << configPath << " !!! !!! " << std::endl;
std::cout << " !!! !!! !!! !!!" << std::endl;
return false;
}
_configFile = configPath;
Log4zFileHandler f;
f.open(_configFile.c_str(), "rb");
if (!f.isOpen())
{
std::cout << " !!! !!! !!! !!!" << std::endl;
std::cout << " !!! !!! log4z load config file error. filename=" << configPath << " !!! !!! " << std::endl;
std::cout << " !!! !!! !!! !!!" << std::endl;
return false;
}
return configFromStringImpl(f.readContent().c_str(), false);
}
//! read configure and create with overwriting
bool LogerManager::configFromString(const char* configContent)
{
return configFromStringImpl(configContent, false);
}
//! create with overwriting
LoggerId LogerManager::createLogger(const char* key)
{
if (key == NULL)
{
return LOG4Z_INVALID_LOGGER_ID;
}
std::string copyKey = key;
trimLogConfig(copyKey);
LoggerId newID = LOG4Z_INVALID_LOGGER_ID;
{
std::map<std::string, LoggerId>::iterator iter = _ids.find(copyKey);
if (iter != _ids.end())
{
newID = iter->second;
}
}
if (newID == LOG4Z_INVALID_LOGGER_ID)
{
if (_lastId +1 >= LOG4Z_LOGGER_MAX)
{
showColorText("log4z: CreateLogger can not create|writeover, because loggerid need < LOGGER_MAX! \r\n", LOG_LEVEL_FATAL);
return LOG4Z_INVALID_LOGGER_ID;
}
newID = ++ _lastId;
_ids[copyKey] = newID;
_names[newID] = copyKey;
_loggers[newID]._enable = true;
_loggers[newID]._key = copyKey;
_loggers[newID]._name = copyKey;
}
return newID;
}
bool LogerManager::start()
{
if (_runing)
{
return false;
}
return ThreadHelper::start();
}
bool LogerManager::stop()
{
if (_runing == true)
{
_runing = false;
wait();
return true;
}
return false;
}
bool LogerManager::prePushLog(const char * name, int level)
{
LoggerId id = getLoggerId(name);
if(id == LOG4Z_INVALID_LOGGER_ID) return false;
return prePushLog(id,level);
}
bool LogerManager::prePushLog(LoggerId id, int level)
{
if (id < 0 || id > _lastId || !_runing || !_loggers[id]._enable)
{
return false;
}
if (level < _loggers[id]._level)
{
return false;
}
return true;
}
bool LogerManager::pushLog(const char * name, int level, const char * filter, const char * log, const char * file, int line, const char *func, const void * pRetAddr)
{
LoggerId id = getLoggerId(name);
if(id == LOG4Z_INVALID_LOGGER_ID) return false;
return pushLog(id,level,filter,log,file,line,func,pRetAddr);
}
bool LogerManager::pushLog(LoggerId id, int level, const char * filter, const char * log, const char * file, int line, const char *func, const void * pRetAddr)
{
// discard log
if (id < 0 || id > _lastId || !_runing || !_loggers[id]._enable)
{
return false;
}
//filter log
if (level < _loggers[id]._level)
{
return false;
}
//create log data
LogData * pLog = new LogData;
pLog->_id =id;
pLog->_level = level;
pLog->_filter = filter;
pLog->_content = log;
if(file != NULL) pLog->_file = file;
pLog->_func = func;
pLog->_line = line;
//append precise time to log
{
#if defined (WIN32) || defined(_WIN64)
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
unsigned long long now = ft.dwHighDateTime;
now <<= 32;
now |= ft.dwLowDateTime;
now /=10;
now -=11644473600000000ULL;
now /=1000;
pLog->_time = now;
#else
struct timeval tm;
gettimeofday(&tm, NULL);
pLog->_time = tm.tv_sec*1000+tm.tv_usec/1000;
#endif
}
#if defined (WIN32) || defined(_WIN64)
char szPath[MAX_PATH]={0};
char *pModuleName = szPath;
if(pRetAddr)
{
HMODULE hMod = 0;
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS| GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,(LPCSTR)pRetAddr,&hMod);
GetModuleFileNameA(hMod,szPath,100);
pModuleName = strrchr(szPath,'\\')+1;
}
pLog->_moduleName = pModuleName;
pLog->_pid = GetCurrentProcessId();
pLog->_tid = GetCurrentThreadId();
#endif
AutoLock l(_logLock);
_logs.push_back(pLog);
_ullStatusTotalPushLog ++;
return true;
}
//! 查找ID from name
LoggerId LogerManager::findLogger(const char * key)
{
std::map<std::string, LoggerId>::iterator iter;
iter = _ids.find(key);
if (iter != _ids.end())
{
return iter->second;
}
return LOG4Z_INVALID_LOGGER_ID;
}
bool LogerManager::enableLogger(LoggerId id, bool enable)
{
if (id <0 || id > _lastId) return false;
_loggers[id]._enable = enable;
return true;
}
bool LogerManager::setLoggerLevel(LoggerId id, int level)
{
if (id <0 || id > _lastId || level < LOG_LEVEL_TRACE || level >LOG_LEVEL_FATAL) return false;
_loggers[id]._level = level;
return true;
}
bool LogerManager::setLoggerDisplay(LoggerId id, bool enable)
{
if (id <0 || id > _lastId) return false;
_loggers[id]._display = enable;
return true;
}
bool LogerManager::setLoggerOutFile(LoggerId id, bool enable)
{
if (id <0 || id > _lastId) return false;
_loggers[id]._outfile = enable;
return true;
}
void LogerManager::setOutputFileBuilder(IOutputFileBuilder *pOutputFileBuilder)
{
AutoLock l(_logLock);
m_pOutputFileBuilder = pOutputFileBuilder;
}
bool LogerManager::setLoggerFileMaxNum(unsigned int maxnum)
{
_maxFileNum = maxnum;
return true;
}
bool LogerManager::setLoggerLimitsize(LoggerId id, unsigned int limitsize)
{
if (id <0 || id > _lastId) return false;
if (limitsize == 0 ) {limitsize = (unsigned int)-1;}
_loggers[id]._limitsize = limitsize;
return true;
}
bool LogerManager::setLoggerFileLine(LoggerId id, bool enable)
{
if (id <0 || id > _lastId) return false;
_loggers[id]._fileLine = enable;
return true;
}
bool LogerManager::setLoggerName(LoggerId id, const char * name)
{
if (id <0 || id > _lastId) return false;
//the name by main logger is the process name and it's can't change.
if (id == LOG4Z_MAIN_LOGGER_ID) return false;
if (name == NULL || strlen(name) == 0)
{
return false;
}
AutoLock l(_hotLock);
if (_loggers[id]._name != name)
{
_loggers[id]._name = name;
}
return true;
}
bool LogerManager::setLoggerPath(LoggerId id, const char * path)
{
if (id <0 || id > _lastId) return false;
std::string copyPath;
if (path == NULL || strlen(path) == 0)
{
copyPath = LOG4Z_DEFAULT_PATH;
}
else
{
copyPath = path;
}
{
char ch = copyPath.at(copyPath.length() - 1);
if (ch != '\\' && ch != '/')
{
copyPath.append("/");
}
}
AutoLock l(_hotLock);
if (copyPath != _loggers[id]._path)
{
_loggers[id]._path = copyPath;
}
return true;
}
bool LogerManager::setAutoUpdate(int interval)
{
_hotUpdateInterval = interval;
return true;
}
bool LogerManager::updateConfig()
{
if (_configFile.empty())
{
//LOGW("log4z update config file error. filename is empty.");
return false;
}
Log4zFileHandler f;
f.open(_configFile.c_str(), "rb");
if (!f.isOpen())
{
std::cout << " !!! !!! !!! !!!" << std::endl;
std::cout << " !!! !!! log4z load config file error. filename=" << _configFile << " !!! !!! " << std::endl;
std::cout << " !!! !!! !!! !!!" << std::endl;
return false;
}
return configFromStringImpl(f.readContent().c_str(), true);
}
bool LogerManager::isLoggerEnable(LoggerId id)
{
if (id <0 || id > _lastId) return false;
return _loggers[id]._enable;
}
unsigned int LogerManager::getStatusActiveLoggers()
{
unsigned int actives = 0;
for (int i=0; i<= _lastId; i++)
{
if (_loggers[i]._enable)
{
actives ++;
}
}
return actives;
}
bool LogerManager::openLogger(LogData * pLog)
{
int id = pLog->_id;
if (id < 0 || id >_lastId)
{
showColorText("log4z: openLogger can not open, invalid logger id! \r\n", LOG_LEVEL_FATAL);
return false;
}
LoggerInfo * pLogger = &_loggers[id];
if (!pLogger->_enable || !pLogger->_outfile || pLog->_level < pLogger->_level)
{
return false;
}
bool needChangeFile = pLogger->_curWriteLen > pLogger->_limitsize * 1024 * 1024;
if ( needChangeFile)
{
if (pLogger->_handle.isOpen())
{
pLogger->_handle.close();
}
std::string name = pLogger->_name;
char buf[MAX_PATH];
tm t = timeToTm(pLogger->_curFileCreateTime);
const int KMaxLogIndex = _maxFileNum;
m_pOutputFileBuilder->buildOutputFile(buf,100,t,name.c_str(),_pid,KMaxLogIndex);
std::string path = pLogger->_path+buf;
remove(path.c_str());
for(int i=KMaxLogIndex;i>0;i--)//max to _maxFileNum log index.
{
m_pOutputFileBuilder->buildOutputFile(buf,100,t,name.c_str(),_pid,i-1);
std::string pathOld = pLogger->_path+buf;
m_pOutputFileBuilder->buildOutputFile(buf,100,t,name.c_str(),_pid,i);
std::string pathNew = pLogger->_path+buf;
rename(pathOld.c_str(),pathNew.c_str());
}
}
if (!pLogger->_handle.isOpen())
{
pLogger->_curFileCreateTime = pLog->_time;
pLogger->_curWriteLen = 0;
tm t = timeToTm(pLogger->_curFileCreateTime);
std::string name;
std::string path;
_hotLock.lock();
name = pLogger->_name;
path = pLogger->_path;
_hotLock.unLock();
char buf[100] = { 0 };
if (!isDirectory(path))
{
createRecursionDir(path);
}
m_pOutputFileBuilder->buildOutputFile(buf,100,t,name.c_str(),_pid,0);
path += buf;
pLogger->_handle.open(path.c_str(), "ab");
if (!pLogger->_handle.isOpen())
{
pLogger->_outfile = false;
return false;
}
pLogger->_curWriteLen = pLogger->_handle.size();
return true;
}
return true;
}
bool LogerManager::closeLogger(LoggerId id)
{
if (id < 0 || id >_lastId)
{
showColorText("log4z: closeLogger can not close, invalid logger id! \r\n", LOG_LEVEL_FATAL);
return false;
}
LoggerInfo * pLogger = &_loggers[id];
if (pLogger->_handle.isOpen())
{
pLogger->_handle.close();
return true;
}
return false;
}
bool LogerManager::popLog(LogData *& log)
{
AutoLock l(_logLock);
if (_logs.empty())
{
return false;
}
log = _logs.front();
_logs.pop_front();
return true;
}
void LogerManager::run()
{
_runing = true;
pushLog(0, LOG_LEVEL_ALARM, "logger", "----------------- log4z thread started! ----------------------------", __FILE__, __LINE__ , __FUNCTION__,_ReturnAddress());
for (int i = 0; i <= _lastId; i++)
{
if (_loggers[i]._enable)
{
std::stringstream ss;
ss <<"logger id=" <<i
<<" key=" <<_loggers[i]._key
<<" name=" <<_loggers[i]._name
<<" path=" <<_loggers[i]._path
<<" level=" << _loggers[i]._level
<<" display=" << _loggers[i]._display;
pushLog(0, LOG_LEVEL_ALARM, "logger", ss.str().c_str(), __FILE__, __LINE__ , __FUNCTION__,_ReturnAddress());
}
}
char *pszBuf = new char[LOG4Z_LOG_BUF_SIZE];
LogData * pLog = NULL;
int needFlush[LOG4Z_LOGGER_MAX] = {0};
time_t lastCheckUpdate = time(NULL);
while (true)
{
while(popLog(pLog))
{
//
_ullStatusTotalPopLog ++;
//discard
LoggerInfo & curLogger = _loggers[pLog->_id];
if (!curLogger._enable || pLog->_level <curLogger._level )
{
delete pLog;
pLog = NULL;
continue;
}
int nContentLen = 0;
//format log
{
tm tt = timeToTm(pLog->_time/1000);
if (pLog->_file.empty() || !_loggers[pLog->_id]._fileLine)
{
#if defined (WIN32) || defined(_WIN64)
int ret = _snprintf_s(pszBuf, LOG4Z_LOG_BUF_SIZE, _TRUNCATE, "pid=%u tid=%u %d-%02d-%02d %02d:%02d:%02d.%03d %s %s %s \"%s\"\r\n",
pLog->_pid, pLog->_tid,
tt.tm_year + 1900, tt.tm_mon + 1, tt.tm_mday, tt.tm_hour, tt.tm_min, tt.tm_sec, (int)(pLog->_time%1000),
LOG_STRING[pLog->_level], pLog->_moduleName.c_str(), pLog->_filter.c_str(), pLog->_content.c_str());
if (ret == -1)
{
ret = LOG4Z_LOG_BUF_SIZE - 1;
}
nContentLen = ret;
#else
int ret = snprintf(pszBuf, LOG4Z_LOG_BUF_SIZE, "%d-%02d-%02d %02d:%02d:%02d.%03d %s %s %s\r\n",
tt.tm_year + 1900, tt.tm_mon + 1, tt.tm_mday, tt.tm_hour, tt.tm_min, tt.tm_sec, (int)(pLog->_time%1000),
LOG_STRING[pLog->_level],pLog->_filter.c_str(), pLog->_content.c_str());
if (ret == -1)
{
ret = 0;
}
if (ret >= LOG4Z_LOG_BUF_SIZE)
{
ret = LOG4Z_LOG_BUF_SIZE-1;
}
nContentLen = ret;
#endif
}
else
{
#if defined (WIN32) || defined(_WIN64)
const char * pNameBegin = strrchr(pLog->_file.c_str(),'\\');
#else
const char * pNameBegin = strrchr(pLog->_file.c_str(),'/');
#endif
if(!pNameBegin) pNameBegin = pLog->_file.c_str();
else pNameBegin ++;
#if defined (WIN32) || defined(_WIN64)
int ret = _snprintf_s(pszBuf, LOG4Z_LOG_BUF_SIZE, _TRUNCATE, "pid=%u tid=%u %d-%02d-%02d %02d:%02d:%02d.%03d %s %s %s \"%s\" %s (%s):%d\r\n",
pLog->_pid, pLog->_tid,
tt.tm_year + 1900, tt.tm_mon + 1, tt.tm_mday, tt.tm_hour, tt.tm_min, tt.tm_sec, (int)(pLog->_time%1000),
LOG_STRING[pLog->_level], pLog->_moduleName.c_str(), pLog->_filter.c_str(), pLog->_content.c_str(), pLog->_func.c_str(), pNameBegin, pLog->_line);
if (ret == -1)
{
ret = LOG4Z_LOG_BUF_SIZE - 1;
}
nContentLen = ret;
#else
int ret = snprintf(pszBuf, LOG4Z_LOG_BUF_SIZE, "%d-%02d-%02d %02d:%02d:%02d.%03d %s %s %s (%s):%d %s\r\n",
tt.tm_year + 1900, tt.tm_mon + 1, tt.tm_mday, tt.tm_hour, tt.tm_min, tt.tm_sec, (int)(pLog->_time%1000),
LOG_STRING[pLog->_level], pLog->_filter.c_str(), pLog->_content.c_str(), pNameBegin, pLog->_line, pLog->_func.c_str());
if (ret == -1)
{
ret = 0;
}
if (ret >= LOG4Z_LOG_BUF_SIZE)
{
ret = LOG4Z_LOG_BUF_SIZE-1;
}
nContentLen = ret;
#endif
}
}
if(m_pListener)
{
m_pListener->onOutputLog(pLog->_level,pLog->_filter.c_str(),pLog->_content.c_str(),pLog->_content.length(),pLog->_time);
}
if (curLogger._display)
{
showColorText(pszBuf, pLog->_level);
#if defined (WIN32) || defined(_WIN64)
OutputDebugStringA(pszBuf);
#endif
}
if (curLogger._outfile)
{
if (!openLogger(pLog))
{
delete pLog;
pLog = NULL;
continue;
}
curLogger._handle.write(pszBuf, nContentLen);
curLogger._curWriteLen += (unsigned int)nContentLen;
needFlush[pLog->_id] ++;
_ullStatusTotalWriteFileCount++;
_ullStatusTotalWriteFileBytes += nContentLen;
}
else
{
_ullStatusTotalWriteFileCount++;
_ullStatusTotalWriteFileBytes += nContentLen;
}
delete pLog;
pLog = NULL;
}
for (int i=0; i<=_lastId; i++)
{
if (_loggers[i]._enable && needFlush[i] > 0)
{
_loggers[i]._handle.flush();
needFlush[i] = 0;
}
if(!_loggers[i]._enable && _loggers[i]._handle.isOpen())
{
_loggers[i]._handle.close();
}
}
//! delay.
sleepMillisecond(100);
//! quit
if (!_runing && _logs.empty())
{
break;
}
if (_hotUpdateInterval != 0 && time(NULL) - lastCheckUpdate > _hotUpdateInterval)
{
updateConfig();
lastCheckUpdate = time(NULL);
}
}
for (int i=0; i <= _lastId; i++)
{
if (_loggers[i]._enable)
{
_loggers[i]._enable = false;
closeLogger(i);
}
}
delete []pszBuf;
}
void LogerManager::setOutputListener(IOutputListener *pListener){
AutoLock l(_hotLock);
m_pListener = pListener;
}
namespace SOUI{
namespace LOG4Z{
SOUI_COM_C BOOL SOUI_COM_API SCreateInstance(IObjRef **ppLogMgr)
{
*ppLogMgr = new LogerManager;
return TRUE;
}
}
}