288 lines
7.5 KiB
C
288 lines
7.5 KiB
C
|
#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
|