231 lines
5.8 KiB
C++
231 lines
5.8 KiB
C++
#include "liblog.h"
|
|
#include "libdiff.h"
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <iostream>
|
|
#include <cstdlib>
|
|
#include <unistd.h>
|
|
|
|
using namespace std;
|
|
|
|
LogFile::LogFile()
|
|
{
|
|
logmethod = -1;
|
|
logpath = "";
|
|
file = NULL;
|
|
initialized = false;
|
|
}
|
|
|
|
string IntToLength(int a, int len)
|
|
{
|
|
string s = ToString(a);
|
|
while ((int)s.length() < len) s = '0' + s;
|
|
return s;
|
|
}
|
|
|
|
|
|
void LogFile::InitLogging(string logpath, int method, string prefix, bool reopen)
|
|
{
|
|
this->logmethod = method;
|
|
this->logpath = logpath;
|
|
this->fileprefix = prefix;
|
|
this->reopen = reopen;
|
|
// инициализируем mutex
|
|
if (pthread_mutex_init(&filemutex, NULL) != 0)
|
|
{
|
|
throw (string)("Unable to create mutex");
|
|
}
|
|
if (!reopen)
|
|
{
|
|
// открываем файл
|
|
if (method == LIBLOGSINGLEFILE)
|
|
{
|
|
// формируем имя файла
|
|
ostringstream filename;
|
|
filename << logpath << "/" << fileprefix << ".log";
|
|
file = OpenFileWithRetries(filename.str(), "at");
|
|
if (file == NULL)
|
|
{
|
|
throw (string)("Unable to open file for logging");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
struct tm curtime;
|
|
time_t ct = time(NULL);
|
|
localtime_r(&ct, &curtime);
|
|
// теперь имя файла выглядит намного забавнее
|
|
ostringstream filename;
|
|
filename << logpath << "/" << fileprefix << curtime.tm_year + 1900 << IntToLength(curtime.tm_mon + 1, 2)
|
|
<< IntToLength(curtime.tm_mday, 2) << ".log";
|
|
file = OpenFileWithRetries(filename.str(), "at");
|
|
lastname = filename.str();
|
|
if (file == NULL)
|
|
{
|
|
throw (string)("Unable to open file for logging");
|
|
}
|
|
}
|
|
}
|
|
initialized = true;
|
|
}
|
|
|
|
|
|
// записывает в лог-файл строку
|
|
// файл определяется исходя из метода
|
|
// строка предваряется текущим временем
|
|
// в некотором формате
|
|
void LogFile::LogString(string s, string pfx)
|
|
{
|
|
// Если лог еще не инициализирован, ничего не пишем (штатная ситуация, если,
|
|
// например, лог пришлось заглушить).
|
|
if (!initialized) return;
|
|
#ifdef FTC_DEBUG
|
|
cout << s << endl;
|
|
#endif
|
|
int res;
|
|
while ((res = pthread_mutex_lock(&filemutex)) != 0)
|
|
{
|
|
if (res != EAGAIN)
|
|
{
|
|
throw (string)("Fatal error acquiring mutex");
|
|
}
|
|
}
|
|
struct tm curtime;
|
|
time_t ct = time(NULL);
|
|
localtime_r(&ct, &curtime);
|
|
if (this->logmethod == LIBLOGSINGLEFILE)
|
|
{
|
|
if (reopen)
|
|
{
|
|
// формируем имя файла
|
|
ostringstream filename;
|
|
filename << logpath << "/" << fileprefix << ".log";
|
|
file = OpenFileWithRetries(filename.str(), "at");
|
|
if (file == NULL)
|
|
{
|
|
throw (string)("Unable to open file for logging");
|
|
pthread_mutex_unlock(&filemutex);
|
|
return;
|
|
}
|
|
}
|
|
// теперь сгенерить строку
|
|
ostringstream oss;
|
|
oss << pfx << " " << IntToLength(curtime.tm_year + 1900, 4) << "-" << IntToLength(curtime.tm_mon + 1, 2) << "-"
|
|
<< IntToLength(curtime.tm_mday, 2) << " " << IntToLength(curtime.tm_hour, 2)
|
|
<< ":" << IntToLength(curtime.tm_min, 2) << ":" << IntToLength(curtime.tm_sec, 2);
|
|
oss << " " << s + "\n";
|
|
// и записать ее куда следует
|
|
fprintf(file, "%s", oss.str().c_str());
|
|
if (reopen)
|
|
{
|
|
if (file != NULL)
|
|
{
|
|
fclose(file);
|
|
file = NULL;
|
|
}
|
|
}
|
|
}
|
|
else if (this->logmethod == LIBLOGDAYFILES)
|
|
{
|
|
// переоткрываем файл если нужно
|
|
ostringstream filename;
|
|
filename << logpath << "/" << fileprefix << curtime.tm_year + 1900 << IntToLength(curtime.tm_mon + 1, 2)
|
|
<< IntToLength(curtime.tm_mday, 2) << ".log";
|
|
if (!reopen)
|
|
{
|
|
if (filename.str() != lastname)
|
|
{
|
|
if (file != NULL)
|
|
{
|
|
cerr << "LIBLOG, fclose " << file << "\n";
|
|
cerr << "LIBLOG, lastname = " << lastname << " newname = " << filename.str() << "\n";
|
|
fclose(file);
|
|
}
|
|
file = OpenFileWithRetries(filename.str(), "at");
|
|
if (file == NULL)
|
|
{
|
|
throw (string)("Unable to open file for logging");
|
|
pthread_mutex_unlock(&filemutex);
|
|
return;
|
|
}
|
|
lastname = filename.str();
|
|
cerr << "LIBLOG, reopened file = " << file << "\n";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
file = OpenFileWithRetries(filename.str(), "at");
|
|
if (file == NULL)
|
|
{
|
|
throw (string)("Unable to open file for logging");
|
|
pthread_mutex_unlock(&filemutex);
|
|
return;
|
|
}
|
|
}
|
|
// теперь сгенерить строку
|
|
ostringstream oss;
|
|
oss << pfx << " " << IntToLength(curtime.tm_hour, 2)
|
|
<< ":" << IntToLength(curtime.tm_min, 2) << ":" << IntToLength(curtime.tm_sec, 2);
|
|
oss << " " << s << "\n";
|
|
// и записать ее куда следует
|
|
if (file != NULL) fprintf(file, "%s", oss.str().c_str());
|
|
if (reopen)
|
|
{
|
|
if (file != NULL)
|
|
{
|
|
fclose(file);
|
|
file = NULL;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ничего не делаем - неинициализированный лог - не проблема
|
|
}
|
|
if (!reopen)
|
|
{
|
|
if (file != NULL) fflush(file);
|
|
}
|
|
pthread_mutex_unlock(&filemutex);
|
|
}
|
|
|
|
char GHC(char c)
|
|
{
|
|
if (c < 10) return (c + '0');
|
|
else return (c - 10 + 'A');
|
|
}
|
|
|
|
string GetHex(unsigned char c)
|
|
{
|
|
string res;
|
|
int l, h;
|
|
h = (c >> 4) & 15;
|
|
l = c & 15;
|
|
res += GHC(h);
|
|
res += GHC(l);
|
|
return res;
|
|
}
|
|
|
|
|
|
FILE* LogFile::OpenFileWithRetries(string fname, const char *mode)
|
|
{
|
|
FILE *res = fopen(fname.c_str(), mode);
|
|
int rcnt = 0;
|
|
while (res == NULL)
|
|
{
|
|
rcnt++;
|
|
if (rcnt > LIBLOGNUMRETRIESTOOPEN) break;
|
|
sleep(1);
|
|
res = fopen(fname.c_str(), mode);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
string GetHexString(unsigned int a)
|
|
{
|
|
return GetHex((a >> 24) & 0xFF) + GetHex((a >> 16) & 0xFF) + GetHex((a >> 8) & 0xFF) + GetHex(a & 0xFF);
|
|
}
|