#ifndef __HIT_LOG_HEADER #define __HIT_LOG_HEADER #include #include #include #include #include #include #include #include #include #include "dataqueue.h" #define INFO_BUF_LEN 4096//2048 typedef void* voidPtr; extern "C" voidPtr __attribute__((visibility("default"))) OpenLogFile(const char* strPath, const char* strFileName, bool bLogByDay); //----------------------------------------------------------------------------------------------------------------- extern "C" int __attribute__((visibility("default"))) WriteLog(void* pLogFile, const char* fmt, ...); //----------------------------------------------------------------------------------------------------------------- extern "C" void __attribute__((visibility("default"))) CloseLog(void* pLogFile); namespace QUEUE_LOG_COFIG { static uint64_t g_iLogFileMaxSize = 2L * 1024 * 1024 * 1024; static uint64_t g_iCheckLogInterval = 20;//20s inline int checkdir(const char* sPathName) { char DirName[256]; strcpy(DirName, sPathName); int i, len = strlen(DirName); if (DirName[len - 1] != '/') strcat(DirName, "/"); len = strlen(DirName); for (i = 1; i < len; i++) { if (DirName[i] == '/') { DirName[i] = 0; if (access(DirName, 0) != 0) { if (mkdir(DirName, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) { perror(" mkdir error"); return -1; } } DirName[i] = '/'; } } return 0; } /* ** log class, it is not thread safe. */ void* WriteLogThread(void* param); struct InfoItem { struct tm t; bool bLogTime; char strInfo[INFO_BUF_LEN]; int GetLen() { return (uint64_t)(&strInfo[0]) - (uint64_t)(this) + strlen(strInfo) + 1; } }; class CLogFile { private: char* log_filename; char* log_dirpath; char* log_fullpath_filename; int m_bRecordByDay; int current_day; FILE* file_handle; DataQueue m_InfoQueue; // bool m_bExit; bool m_bUseQueue; bool m_bWriteFinish; pthread_t m_pWriteThreadHandle; private: void set_log_fullpath_filename(struct tm* t) { if (log_fullpath_filename == NULL) log_fullpath_filename = (char*)calloc(strlen(log_dirpath) + 1 + 8 + 1 + strlen(log_filename) + 1 + 10, sizeof(char)); if (m_bRecordByDay) { current_day = t->tm_mday; sprintf(log_fullpath_filename, "%s%02d%02d%02d/", log_dirpath, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday); } else sprintf(log_fullpath_filename, "%s", log_dirpath); checkdir(log_fullpath_filename); strcat(log_fullpath_filename, log_filename); } void open_log_file() { file_handle = fopen(log_fullpath_filename, "a"); if (file_handle == NULL) {//2019.07.18------------------ fprintf(stderr, "\n----------------------------------------------------------------\n"); fprintf(stderr, "***Fatal error: can't open file: %s", log_fullpath_filename); fprintf(stderr, "----------------------------------------------------------------\n"); fflush(stderr); exit(1); } } struct tm* get_time() { time_t clock; time(&clock); struct tm* t = localtime(&clock); return t; } void print_time() { struct tm* t = get_time(); fprintf(file_handle, "%4d-%02d-%02d %02d:%02d:%02d\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); } public: FILE* GetFileHande() { return file_handle; } CLogFile(const char* dir, const char* name, int byDay, bool bUseQueue = false) { m_bRecordByDay = byDay; m_bUseQueue = bUseQueue; file_handle = NULL; m_bWriteFinish = true; m_bExit = false; log_dirpath = (char*)calloc(strlen(dir) + 10, sizeof(char)); log_filename = (char*)calloc(strlen(name) + 10, sizeof(char)); strcpy(log_dirpath, dir); int i, len = strlen(log_dirpath); if (log_dirpath[len - 1] != '/') strcat(log_dirpath, "/"); strcpy(log_filename, name); log_fullpath_filename = NULL; struct tm* t = get_time(); set_log_fullpath_filename(t); open_log_file(); if (bUseQueue) { m_InfoQueue.InitQueue(32 * 1024, 8 * 2048); pthread_create(&m_pWriteThreadHandle, NULL, WriteLogThread, this); } } ~CLogFile() { m_bExit = true; pthread_join(m_pWriteThreadHandle, NULL); close_log_file(); free(log_filename); free(log_dirpath); free(log_fullpath_filename); } void append_one_item(int print_time_flag, const char* fmt, ...) {//append the new info into the queue char fmtbuf[INFO_BUF_LEN]; va_list arglist; if (m_bExit) return; InfoItem tmpInfoItem; va_start(arglist, fmt); vsprintf(fmtbuf, fmt, arglist); va_end(arglist); snprintf(tmpInfoItem.strInfo, sizeof(tmpInfoItem.strInfo), fmtbuf); tmpInfoItem.t = *get_time(); tmpInfoItem.bLogTime = print_time_flag; if (m_bUseQueue) m_InfoQueue.EnQueue((void*)(&tmpInfoItem), tmpInfoItem.GetLen()); else { writeItem2File(&tmpInfoItem); } } void checksize(uint64_t iSize) { uint64_t iFileBytes = ftell(file_handle); if (iFileBytes > iSize) { char strBackupName[500]; char strCurTime[20]; time_t tt; tt = time(NULL); strftime(strCurTime, sizeof(strCurTime), "%Y.%m.%d-%H.%M.%S", localtime(&tt));//产生“YYYY-MM-DD hh:mm:ss”格式的字符串。 sprintf(strBackupName, "%s-bak%s", log_fullpath_filename, strCurTime); close_log_file(); rename(log_fullpath_filename, strBackupName);//把原文件重命名为新的文件名 open_log_file(); } }; void writeItem2File(InfoItem* pInfoItem) { if (file_handle == NULL) {//2019.07.18 return; } int iBytes; if ((m_bRecordByDay) && (pInfoItem->t.tm_mday != current_day)) {//change_to_new_day close_log_file(); current_day = pInfoItem->t.tm_mday; set_log_fullpath_filename(&(pInfoItem->t)); open_log_file(); char strCmd[300]; sprintf(strCmd, "find %s -type d -mtime +30 -exec rm -rf {} \\;", log_dirpath); system(strCmd); } if (pInfoItem->bLogTime) { iBytes = fprintf(file_handle, "%s %4d.%02d.%02d %02d:%02d:%02d\n", pInfoItem->strInfo, pInfoItem->t.tm_year + 1900, pInfoItem->t.tm_mon + 1, pInfoItem->t.tm_mday, pInfoItem->t.tm_hour, pInfoItem->t.tm_min, pInfoItem->t.tm_sec); } else iBytes = fprintf(file_handle, "%s", pInfoItem->strInfo); if (iBytes < 0) fprintf(stderr, "***writing \"%s\" to log failed! errno:%d, %s\n", pInfoItem->strInfo, errno, strerror(errno)); else fflush(file_handle); } void writeQueue2File() { unsigned int iWiteItems = 0; InfoItem* pInfoItem; struct tm* t; m_bWriteFinish = false; unsigned n = 0; int iBytes; while (!m_bExit) { iBytes = m_InfoQueue.DeQueue((void**)(&pInfoItem)); if (iBytes <= 0) { sleep(1);//10ms continue; } writeItem2File(pInfoItem); if ((++n % g_iCheckLogInterval == 0) && (!m_bRecordByDay)) checksize(g_iLogFileMaxSize);// 2L * 1024 * 1024 * 1024);//不超过2GB } t = get_time(); fprintf(file_handle, "...finish and exit! @%4d.%02d.%02d %02d:%02d:%02d\n\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); fflush(file_handle); m_bWriteFinish = true; } void close_log_file() { if (file_handle != NULL) { fflush(file_handle); fclose(file_handle); file_handle = NULL; } } void clear_expired_logs() { } }; //void * WriteLogThread(void* param) //{ // CLogFile *pLog = (CLogFile*)(param); // pLog->writeQueue2File();// //} //--------------------------------------------------------------------------------------------------- } #endif