#include "precompile.h" #if defined(_MSC_VER) #include #else #include #include "fileutil.h" #include #include #include #include #define TAG "SpHostLog" #include #define RWRWRE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) #endif //_MSC_VER #include "SpHostLog.h" #include #include using namespace std; #include "sp_dir.h" #include "sp_def.h" #include "SpBase.h" #include #include #include #include #define SPHOST_LOG_LOCK_NAME "sphost_Log_Lock" void* g_logProducer = NULL; class CMyLogFile { public: void PrintCurTime(); explicit CMyLogFile(); ~CMyLogFile(); void LOGERROR(const char* formatString, va_list argList); private: ofstream *m_cOutFile; bool GetRootDir(char *dirPath); void Init(); void Release(); BOOL Lock(DWORD dwTime); void Unlock(); void Output(const char* data); HANDLE m_hLock; private: CMyLogFile& operator <<(long lVal); CMyLogFile& operator <<(const char* str); CMyLogFile& operator <<(char tch); CMyLogFile& operator <<(int nVal); CMyLogFile& operator <<(unsigned long ulVal); CMyLogFile& operator <<(double dVal); CMyLogFile& operator <<(unsigned int unVal); #if defined(_MSC_VER) CMyLogFile& operator <<(unsigned __int64 unllVal); #endif //_MSC_VER }; CMyLogFile::CMyLogFile() :m_cOutFile(NULL) { } CMyLogFile::~CMyLogFile() { } void CMyLogFile::Output(const char *data) { if (NULL != m_cOutFile) m_cOutFile->write(data, strlen(data)); } #if defined(_MSC_VER) bool checkDirExist(char *filePath) { return (CreateDirectoryA(filePath, NULL) || (GetLastError() == ERROR_ALREADY_EXISTS)); } #endif //_MSC_VER void CMyLogFile::Init() { char tmp[MAX_PATH]; //TODO(Gifur): duplicate path value set, which would makd memory leak GetModuleFileNameA(NULL, tmp, MAX_PATH); *strrchr(tmp, SPLIT_SLASH) = 0; *strrchr(tmp, SPLIT_SLASH) = 0; *strrchr(tmp, SPLIT_SLASH) = 0; *strrchr(tmp, SPLIT_SLASH) = 0; *strrchr(tmp, SPLIT_SLASH) = 0; if (!m_cOutFile) { char m_dirPath[_MAX_PATH] = ""; sprintf_s(m_dirPath, _MAX_PATH, "%s" SPLIT_SLASH_STR "rvc" SPLIT_SLASH_STR "dbg" SPLIT_SLASH_STR "SpHost", tmp); #if defined(_MSC_VER) if (!checkDirExist(m_dirPath)) #else if (!ExistsDirA(m_dirPath) && !CreateDirA(m_dirPath, TRUE)) #endif return; SYSTEMTIME cur; GetSystemTime(&cur); sprintf(m_dirPath, "%s" SPLIT_SLASH_STR "%4d%.2d%.2d.log", m_dirPath, cur.wYear, cur.wMonth, cur.wDay); m_cOutFile = new ofstream(m_dirPath, ios_base::app); if (m_cOutFile->is_open()) return; delete m_cOutFile; m_cOutFile = NULL; } } void CMyLogFile::Release() { if (NULL != m_cOutFile) { m_cOutFile->close(); delete m_cOutFile; m_cOutFile = NULL; } } BOOL CMyLogFile::Lock(DWORD dwTime) { // 如果还没有创建锁就先创建一个 if (!m_hLock) { std::string strLockName = SPHOST_LOG_LOCK_NAME; m_hLock = ::CreateMutex(NULL, FALSE, strLockName.c_str()); if (!m_hLock) return FALSE; } // 哪个线程最先调用等待函数就最先占用这个互斥量 DWORD dwRet = ::WaitForSingleObject(m_hLock, dwTime); return (dwRet == WAIT_OBJECT_0 || dwRet == WAIT_ABANDONED); } void CMyLogFile::Unlock() { if (m_hLock) ::ReleaseMutex(m_hLock); } ///*TODO(80374374@3/23/2023): */ bool CMyLogFile::GetRootDir(char *dirPath) { char pathbuf[1024] = ""; int pathlen = ::GetModuleFileNameA(NULL, pathbuf, 1024);//获得GuiConsole路径 // 替换掉单杠 int times = 0; while (pathlen > 0) { if (pathbuf[pathlen--] == SPLIT_SLASH) times++; if (2 == times) break; } pathbuf[++pathlen] = '\0'; memcpy(dirPath, pathbuf, (pathlen + 1 > 1024 ? 1024 : pathlen + 1)); return pathlen; } void CMyLogFile::PrintCurTime() { char dateString[52]; SYSTEMTIME cur; GetLocalTime(&cur); sprintf(dateString, "[%4d%.2d%.2d %.2d:%.2d:%.2d.%03d][%u][%u] - ", cur.wYear, cur.wMonth, cur.wDay, cur.wHour, cur.wMinute, cur.wSecond, cur.wMilliseconds, GetCurrentProcessId(), #if defined(_MSC_VER) GetCurrentThreadId()); #else GetCurrentThreadIdFromSys()); #endif //_MSC_VER Output(dateString); } CMyLogFile& CMyLogFile::operator <<(unsigned int unVal) { strstream tmp; tmp << unVal; tmp << '\0'; char* output = tmp.str(); Output(output); tmp.freeze(false); return *this; } CMyLogFile& CMyLogFile::operator <<(long lVal) { strstream tmp; tmp << lVal; tmp << '\0'; char* output = tmp.str(); Output(output); tmp.freeze(false); return *this; } CMyLogFile& CMyLogFile::operator <<(const char* str) { Output(str); return *this; } CMyLogFile& CMyLogFile::operator <<(char tch) { char szCh[2]; szCh[0] = tch; szCh[1] = '\0'; Output(szCh); return *this; } CMyLogFile& CMyLogFile::operator <<(int nVal) { strstream tmp; tmp << nVal; tmp << '\0'; char* output = tmp.str(); Output(output); tmp.freeze(false); return *this; } CMyLogFile& CMyLogFile::operator <<(unsigned long ulVal) { strstream tmp; tmp << ulVal; tmp << '\0'; char* output = tmp.str(); Output(output); tmp.freeze(false); return *this; } CMyLogFile& CMyLogFile::operator <<(double dVal) { strstream tmp; tmp << dVal; tmp << '\0'; char* output = tmp.str(); Output(output); tmp.freeze(false); return *this; } #if defined(_MSC_VER) CMyLogFile& CMyLogFile::operator <<(unsigned __int64 unllVal) { strstream tmp; tmp << unllVal; tmp << '\0'; char* output = tmp.str(); Output(output); tmp.freeze(false); return *this; } #endif //_MSC_VER void CMyLogFile::LOGERROR(const char* formatString, va_list argList) { Lock(INFINITE); Init(); #if defined(_MSC_VER) __try{ if (NULL != m_cOutFile && !m_cOutFile->is_open()) return; /* ** Insert the current time.. */ PrintCurTime(); /* ** Parse the format string and write to the file */ if (formatString == NULL) { /* ** No point in continuiing */ return; } const char* ptr = formatString; while (*ptr != '\0') { char* str = NULL; int nInteger = 0; unsigned int unInt = 0; long lLong = 0; unsigned long ulLong = 0; double dDoub = 0; unsigned __int64 ullLong = 0; if (*ptr == '%') { switch (*(ptr + 1)) { case 's': str = va_arg(argList, char*); if (NULL == str) break; *this << str; ptr++; break; case 'd': nInteger = va_arg(argList, int); *this << nInteger; ptr++; break; case 'u': unInt = va_arg(argList, unsigned int); *this << unInt; ptr++; break; case 'l': ptr++; if (*(ptr + 1) == 'd') { lLong = va_arg(argList, long); *this << lLong; ptr++; } else if (*(ptr + 1) == 'u') { ulLong = va_arg(argList, unsigned long); *this << ulLong; ptr++; } else if (*(ptr + 1) == 'q') { ullLong = va_arg(argList, unsigned __int64); *this << ullLong; ptr++; } break; case 'f': dDoub = va_arg(argList, double); *this << dDoub; ptr++; break; default: *this << *ptr; } } // if(*ptr == '%') else { *this << *ptr; } /* ** Increment pointer.. */ ptr++; } *this << '\n'; } __finally { Release(); Unlock(); } #else do { if (NULL != m_cOutFile && !m_cOutFile->is_open()) break; PrintCurTime(); if (formatString == NULL) { break; } const char* ptr = formatString; while (*ptr != '\0') { char* str = NULL; int nInteger = 0; unsigned int unInt = 0; long lLong = 0; unsigned long ulLong = 0; double dDoub = 0; u__int64_t ullLong = 0; if (*ptr == '%') { switch (*(ptr + 1)) { case 's': str = va_arg(argList, char*); if (NULL == str) break; *this << str; ptr++; break; case 'd': nInteger = va_arg(argList, int); *this << nInteger; ptr++; break; case 'u': unInt = va_arg(argList, unsigned int); *this << unInt; ptr++; break; case 'l': ptr++; if (*(ptr + 1) == 'd') { lLong = va_arg(argList, long); *this << lLong; ptr++; } else if (*(ptr + 1) == 'u') { ulLong = va_arg(argList, unsigned long); *this << ulLong; ptr++; } else if (*(ptr + 1) == 'q') { ullLong = va_arg(argList, u__int64_t); *this << ullLong; ptr++; } break; case 'f': dDoub = va_arg(argList, double); *this << dDoub; ptr++; break; default: *this << *ptr; } } else { *this << *ptr; } ptr++; } *this << '\n'; } while (false); Release(); Unlock(); #endif } void DbgSphost(const char* formatStr, ...) { CMyLogFile log; va_list args; va_start(args, formatStr); log.LOGERROR(formatStr, args); va_end(args); } void DbgWithLink_sphost(const char* formatStr, ...) { va_list arg; va_start(arg, formatStr); //不这么写?貌似到DbgWithLink内后,arg会被析构? int n = _vscprintf(formatStr, arg); char* buf = (char*)_alloca(n + 1); vsprintf(buf, formatStr, arg); std::string dstPrint = std::string("<") + std::to_string((long long)GetCurrentProcessId()) + std::string(">") + std::string(buf); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).withLogProducer(g_logProducer).withExtendLog(false)(dstPrint.c_str()); //DbgSphost(buf); va_end(arg); } int createLogProducer(const char* entityName, const char *id) { g_logProducer = create_log_producer_storage("sphost", id, "", "", ""); if (g_logProducer == NULL) return -1; return 0; } void DestroyLogProducer() { if (g_logProducer != NULL) { destroy_log_producer_storage(g_logProducer); g_logProducer = NULL; } }