#include "liblog.h" #include "libdiff.h" #include #include #include #include #include #include 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); }