设计思路:
1 用一个INI配置文件管理日志目录,日志文件限制的大小,特殊的日志名,特殊日志的大小限制。
2 读取INI文件中的所有信息:每一个日志目录对应的大小限制,每一个特殊日志对应的大小限制。如特殊日志在既定的日志目录中需去除。
3 按设置的大小循环检测并清理每一个日志文件。
4 监听有名管道的信号,如读取到了修改了INI文件的信号,则重新开始读取,循环。
代码:
LogSizeLimit.h
#ifndef LOGSIZELIMIT_H_ #define LOGSIZELIMIT_H_ #include <map> #include <vector> #include <string.h> #include "GlobDefine.h" #include "Mutex.h" static const INT8 *IniFileName = "/LogService/LogSizeManage.ini"; //static const UINT32 LogFileSizeDefault = 2 * 1024 * 1024; static const INT8 * LogFileSizeDefault = "2M"; static const INT8 *LogPipeName = "/LogService/LOGSIZE.fifo"; static const INT8 *ChangedStr = "changed"; static const UINT32 CleanInterval = 4; static const UINT32 LogFilePathMaxLen = 64; static const UINT32 LogFileAttrMaxLen = 8; class LogSizeLimit { // static Mutex mutex; public: LogSizeLimit(const string iniFile); ~LogSizeLimit(); bool start(); bool getChangeFlag() { return changeFlag; } void setChangeFlag(bool status) { changeFlag = status; } private: string _iniFile; map<string, string> _catelogAttr; map<string, string> _specialFileAttr; map<string, vector<string> > _logFiles; bool changeFlag; static void *run(void *args); static void *listenChanged(void*args); bool readConfig(); bool limitLogFile(); bool readFileList(const INT8 *mapStrPath, const INT8 *basePath); bool checkAndCleanLog(string logName, INT32 size); INT32 transSizeToBytes(const INT8 * size); bool readPipeMsg(); }; #endif /* LOGSIZELIMIT_H_ */
LogSizeLimit.cpp
#include <pthread.h> #include <unistd.h> #include <dirent.h> #include <sys/stat.h> #include <sys/types.h> #include <errno.h> #include <fcntl.h> #include "LogSizeLimit.h" #include "IniConfigFile.h" #include "Logger.h" #include "FileOperation.h" using namespace FrameWork; LogSizeLimit::LogSizeLimit(const string iniFile) : _iniFile(iniFile), changeFlag(true) { } LogSizeLimit::~LogSizeLimit() { } bool LogSizeLimit::start() { pthread_t tid, changetid; pthread_create(&tid, NULL, run, (void*) this); pthread_create(&changetid, NULL, listenChanged, (void*) this); return true; } bool LogSizeLimit::readConfig() { //Clean map vars map<string, string>::iterator iter_tmp = _catelogAttr.begin(); while (iter_tmp != _catelogAttr.end()) { _catelogAttr.erase(iter_tmp); iter_tmp++; } //Clean map vars iter_tmp = _specialFileAttr.begin(); while (iter_tmp != _specialFileAttr.end()) { _specialFileAttr.erase(iter_tmp); iter_tmp++; } //Clean map vars map<string, vector<string> >::iterator mvIter_tmp = _logFiles.begin(); while (mvIter_tmp != _logFiles.end()) { _logFiles.erase(mvIter_tmp); mvIter_tmp++; } if (!FileOperation::isExistFile(_iniFile)) { Logger::GetInstance().Fatal("Can not find ini file : %s !", _iniFile.c_str()); return false; } //Create ini file handling var. IniConfigFile iniSet(_iniFile.c_str()); INT8 logPath[LogFilePathMaxLen] = { 0 }; INT8 logFileAttr[LogFileAttrMaxLen] = { 0 }; INT8 specialFile_1[LogFilePathMaxLen] = { 0 }; INT8 specialFileAttr_1[LogFileAttrMaxLen] = { 0 }; const INT8 *catelogBase = "catelog_"; const INT8 *limitBase = "logSizeLimit_"; const INT8 *specialFileBase = "specialFile_"; const INT8 *specialLimitBase = "specialFileSizeLimit_"; INT8 catelogCnt = '1'; bool isExist = true; INT8 catelogIndex[32] = { 0 }; INT8 logSizeIndex[32] = { 0 }; while (isExist) { memset(catelogIndex, 0, 32); memset(logSizeIndex, 0, 32); memset(logPath, 0, LogFilePathMaxLen); memset(logFileAttr, 0, LogFileAttrMaxLen); memcpy(catelogIndex, catelogBase, strlen(catelogBase)); memcpy(catelogIndex + strlen(catelogBase), &catelogCnt, 1); memcpy(logSizeIndex, limitBase, strlen(limitBase)); memcpy(logSizeIndex + strlen(limitBase), &catelogCnt, 1); //section key value do { if (iniSet.readIniConfFile("LogSizeManage", catelogIndex, logPath, LogFilePathMaxLen) != true) { Logger::GetInstance().Error("Can not locate %s !", catelogIndex); isExist = false; break; } else Logger::GetInstance().Info("Get a catelog %s=%s !", catelogIndex, logPath); if (iniSet.readIniConfFile("LogSizeManage", logSizeIndex, logFileAttr, LogFilePathMaxLen) != true) { Logger::GetInstance().Error( "Can not get size %s, using default size %s !", logSizeIndex, LogFileSizeDefault); memcpy(logFileAttr, LogFileSizeDefault, strlen(LogFileSizeDefault)); } else Logger::GetInstance().Info("Get a log size attr %s !", logFileAttr); _catelogAttr[logPath] = logFileAttr; isExist = true; map<string, string>::iterator iter; iter = _catelogAttr.begin(); for (UINT32 i = 1; i < _catelogAttr.size(); i++) iter++; cout << "_catelogAttr_size : " << _catelogAttr.size() << " begin : " << iter->first << " end : " << iter->second << endl; } while (0); // read the normal catelogs memset(catelogIndex, 0, 32); memset(logSizeIndex, 0, 32); memset(logPath, 0, LogFilePathMaxLen); memset(logFileAttr, 0, LogFileAttrMaxLen); memcpy(catelogIndex, specialFileBase, strlen(specialFileBase)); memcpy(catelogIndex + strlen(specialFileBase), &catelogCnt, 1); memcpy(logSizeIndex, specialLimitBase, strlen(specialLimitBase)); memcpy(logSizeIndex + strlen(specialLimitBase), &catelogCnt, 1); do { if (iniSet.readIniConfFile("LogSizeManage", catelogIndex, logPath, LogFilePathMaxLen) != true) { Logger::GetInstance().Error("Can not locate a special log %s !", catelogIndex); break; } else Logger::GetInstance().Info("Get a special log %s=%s !", catelogIndex, logPath); if (iniSet.readIniConfFile("LogSizeManage", logSizeIndex, logFileAttr, LogFilePathMaxLen) != true) { Logger::GetInstance().Error( "Can not get log size %s, using default size %s !", logFileAttr, LogFileSizeDefault); memcpy(logFileAttr, LogFileSizeDefault, strlen(LogFileSizeDefault)); // break; } else Logger::GetInstance().Info("Get a special log size %s !", logFileAttr); if (!isExist) isExist = true; _specialFileAttr[logPath] = logFileAttr; map<string, string>::iterator iter; iter = _specialFileAttr.begin(); cout << "_specialFileAttr_size : " << _specialFileAttr.size() << " begin : " << iter->first << " end : " << iter->second << endl; } while (0); // read the special log files catelogCnt++; } //while return true; } //struct dirent //{ // long d_ino; /* inode number 索引节点号 */ // off_t d_off; /* offset to this dirent 在目录文件中的偏移 */ // unsigned short d_reclen; /* length of this d_name 文件名长 */ // unsigned char d_type; /* the type of d_name 文件类型 */其中d_type表明该文件的类型:文件(8)、目录(4)、链接文件(10)等。 // char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */ //} bool LogSizeLimit::readFileList(const INT8 *mapStrPath, const INT8 *basePath) { DIR *dir; struct dirent *direntPtr; char base[LogFilePathMaxLen] = { 0 }; if ((dir = opendir(basePath)) == NULL) { Logger::GetInstance().Error("Can not open directory %s ! ", basePath); return false; } while ((direntPtr = readdir(dir)) != NULL) { if (strcmp(direntPtr->d_name, ".") == 0 || strcmp(direntPtr->d_name, "..") == 0) ///current dir OR parrent dir continue; else if (direntPtr->d_type == 8) { ///file string fileName; fileName += basePath; if (basePath[strlen(basePath) - 1] != '/') fileName += '/'; fileName += direntPtr->d_name; _logFiles[mapStrPath].push_back(fileName); } else if (direntPtr->d_type == 10) ///link file Logger::GetInstance().Info("A link file : %s !", direntPtr->d_name); else if (direntPtr->d_type == 4) ///dir { memset(base, '