288 lines
7.5 KiB
C++
Executable File
288 lines
7.5 KiB
C++
Executable File
#ifndef __HIT_LOG_HEADER
|
||
#define __HIT_LOG_HEADER
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <stdarg.h>
|
||
#include <string.h>
|
||
#include <memory.h>
|
||
#include <unistd.h>
|
||
#include <sys/stat.h>
|
||
#include <sys/types.h>
|
||
#include <errno.h>
|
||
#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));//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>YYYY-MM-DD hh:mm:ss<73><73><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>
|
||
sprintf(strBackupName, "%s-bak%s", log_fullpath_filename, strCurTime);
|
||
|
||
close_log_file();
|
||
rename(log_fullpath_filename, strBackupName);//<2F><>ԭ<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>µ<EFBFBD><C2B5>ļ<EFBFBD><C4BC><EFBFBD>
|
||
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);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>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
|