Index: ch.vc140.sln =================================================================== diff -u -rcca174e74e108de1f5729e4cc6c46d2b9a5e25a7 -r545098ae76e9ce23598d37d2bee4020d6cb59f3c --- ch.vc140.sln (.../ch.vc140.sln) (revision cca174e74e108de1f5729e4cc6c46d2b9a5e25a7) +++ ch.vc140.sln (.../ch.vc140.sln) (revision 545098ae76e9ce23598d37d2bee4020d6cb59f3c) @@ -34,6 +34,8 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblogger", "src\liblogger\liblogger.vc140.vcxproj", "{DF9957D4-3D95-4AC3-AD3F-DCBEA058F79D}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ext", "ext", "{0E7F04BC-F111-4174-A665-F58CDF142934}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -178,6 +180,10 @@ GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {D41831F5-B2A5-4C92-9F15-1D9AB04722CC} = {0E7F04BC-F111-4174-A665-F58CDF142934} + {D98F2D98-2352-4303-93EE-A5430C4E98AB} = {0E7F04BC-F111-4174-A665-F58CDF142934} + EndGlobalSection GlobalSection(DPCodeReviewSolutionGUID) = preSolution DPCodeReviewSolutionGUID = {00000000-0000-0000-0000-000000000000} EndGlobalSection Index: src/libchcore/Tests/TestsTTaskConfigVerifier.cpp =================================================================== diff -u -r3f15d095b6b6692c9c9c469f979b9798f448b7c6 -r545098ae76e9ce23598d37d2bee4020d6cb59f3c --- src/libchcore/Tests/TestsTTaskConfigVerifier.cpp (.../TestsTTaskConfigVerifier.cpp) (revision 3f15d095b6b6692c9c9c469f979b9798f448b7c6) +++ src/libchcore/Tests/TestsTTaskConfigVerifier.cpp (.../TestsTTaskConfigVerifier.cpp) (revision 545098ae76e9ce23598d37d2bee4020d6cb59f3c) @@ -78,7 +78,6 @@ TEST(TestsTTaskConfigVerifier, VerifyAndUpdate_NextAlternateFilenameFormat_InvalidExt) { - log_file log; TConfig config; SetTaskPropValue(config, L"Subsequent copy of %name (%count)%et"); Index: src/liblogger/TLogFile.cpp =================================================================== diff -u -r800b6e4dd2e62623eab76ac2d16d63af2a67a045 -r545098ae76e9ce23598d37d2bee4020d6cb59f3c --- src/liblogger/TLogFile.cpp (.../TLogFile.cpp) (revision 800b6e4dd2e62623eab76ac2d16d63af2a67a045) +++ src/liblogger/TLogFile.cpp (.../TLogFile.cpp) (revision 545098ae76e9ce23598d37d2bee4020d6cb59f3c) @@ -25,163 +25,166 @@ namespace logger { - TLogFile::TLogFile(PCTSTR pszPath, const TLoggerRotationInfoPtr& spRotationInfo) : - m_strLogPath(pszPath), - m_spFileHandle(), - m_spRotationInfo(spRotationInfo) + namespace internal { - if(!pszPath) - throw std::invalid_argument("pszPath"); - if(!spRotationInfo) - throw std::invalid_argument("spRotationInfo"); + TLogFile::TLogFile(PCTSTR pszPath, const TLoggerRotationInfoPtr& spRotationInfo) : + m_strLogPath(pszPath), + m_spFileHandle(), + m_spRotationInfo(spRotationInfo) + { + if (!pszPath) + throw std::invalid_argument("pszPath"); + if (!spRotationInfo) + throw std::invalid_argument("spRotationInfo"); - ScanForRotatedLogs(); - } + ScanForRotatedLogs(); + } - void TLogFile::Write(std::list& rListEntries) - { - if (rListEntries.empty()) - return; - - try + void TLogFile::Write(std::list& rListEntries) { - std::wstring_convert> utf8Converter; + if (rListEntries.empty()) + return; - for (const std::wstring& rstrEntry : rListEntries) + try { - std::string strUtf8Line = utf8Converter.to_bytes(rstrEntry); + std::wstring_convert> utf8Converter; - size_t stEntryLen = strUtf8Line.length(); - if (NeedRotation(stEntryLen)) - RotateFile(); + for (const std::wstring& rstrEntry : rListEntries) + { + std::string strUtf8Line = utf8Converter.to_bytes(rstrEntry); - DWORD dwWritten = 0; - if (!WriteFile(GetFileHandle(), strUtf8Line.c_str(), boost::numeric_cast(stEntryLen), &dwWritten, nullptr)) - throw std::runtime_error("Cannot write to log, system error"); + size_t stEntryLen = strUtf8Line.length(); + if (NeedRotation(stEntryLen)) + RotateFile(); + + DWORD dwWritten = 0; + if (!WriteFile(GetFileHandle(), strUtf8Line.c_str(), boost::numeric_cast(stEntryLen), &dwWritten, nullptr)) + throw std::runtime_error("Cannot write to log, system error"); + } } + catch (const std::exception&) + { + rListEntries.clear(); + return; + } + + m_timeLastWriteTime = time(nullptr); + rListEntries.clear(); } - catch (const std::exception&) + + void TLogFile::CloseIfUnused() { - rListEntries.clear(); - return; + if (time(nullptr) - m_timeLastWriteTime > MaxHandleCacheTime) + CloseLogFile(); } - m_timeLastWriteTime = time(nullptr); - rListEntries.clear(); - } + void TLogFile::CloseLogFile() + { + m_spFileHandle.reset(); + } - void TLogFile::CloseIfUnused() - { - if (time(nullptr) - m_timeLastWriteTime > MaxHandleCacheTime) - CloseLogFile(); - } + HANDLE TLogFile::GetFileHandle() + { + if (m_spFileHandle != nullptr) + return m_spFileHandle.get(); - void TLogFile::CloseLogFile() - { - m_spFileHandle.reset(); - } + HANDLE hFile = CreateFile(m_strLogPath.c_str(), GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + if (hFile == INVALID_HANDLE_VALUE) + throw std::runtime_error("Cannot open log file"); - HANDLE TLogFile::GetFileHandle() - { - if (m_spFileHandle != nullptr) - return m_spFileHandle.get(); + m_spFileHandle.reset(hFile, CloseHandle); - HANDLE hFile = CreateFile(m_strLogPath.c_str(), GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - if (hFile == INVALID_HANDLE_VALUE) - throw std::runtime_error("Cannot open log file"); + LARGE_INTEGER liSeek = { 0 }; - m_spFileHandle.reset(hFile, CloseHandle); + BOOL bRes = SetFilePointerEx(hFile, liSeek, nullptr, SEEK_END); + if (!bRes) + throw std::runtime_error("Cannot seek to the end of log file"); - LARGE_INTEGER liSeek = { 0 }; + return m_spFileHandle.get(); + } - BOOL bRes = SetFilePointerEx(hFile, liSeek, nullptr, SEEK_END); - if (!bRes) - throw std::runtime_error("Cannot seek to the end of log file"); + unsigned long long TLogFile::GetCurrentLogSize() + { + LARGE_INTEGER liSize = { 0 }; + if (!GetFileSizeEx(GetFileHandle(), &liSize)) + throw std::runtime_error("Cannot determine current log size"); - return m_spFileHandle.get(); - } + return liSize.QuadPart; + } - unsigned long long TLogFile::GetCurrentLogSize() - { - LARGE_INTEGER liSize = { 0 }; - if (!GetFileSizeEx(GetFileHandle(), &liSize)) - throw std::runtime_error("Cannot determine current log size"); + void TLogFile::RotateFile() + { + m_spFileHandle.reset(); - return liSize.QuadPart; - } + std::wstring pathNew = m_strLogPath; + if (boost::iends_with(pathNew, L".log")) + pathNew.erase(pathNew.end() - 4, pathNew.end()); - void TLogFile::RotateFile() - { - m_spFileHandle.reset(); + boost::posix_time::ptime timeNow = boost::posix_time::microsec_clock::local_time(); + boost::posix_time::wtime_facet* facet = new boost::posix_time::wtime_facet(); + facet->format(L"%Y%m%d%H%M%S%f"); + std::wstringstream stream; + stream.imbue(std::locale(std::locale::classic(), facet)); + stream << timeNow; + pathNew += L"."; + pathNew += stream.str().c_str(); + pathNew += L".log"; - std::wstring pathNew = m_strLogPath; - if (boost::iends_with(pathNew, L".log")) - pathNew.erase(pathNew.end() - 4, pathNew.end()); + if (!MoveFile(m_strLogPath.c_str(), pathNew.c_str()) && GetLastError() != ERROR_FILE_NOT_FOUND) + throw std::runtime_error("Cannot rotate file"); - boost::posix_time::ptime timeNow = boost::posix_time::microsec_clock::local_time(); - boost::posix_time::wtime_facet* facet = new boost::posix_time::wtime_facet(); - facet->format(L"%Y%m%d%H%M%S%f"); - std::wstringstream stream; - stream.imbue(std::locale(std::locale::classic(), facet)); - stream << timeNow; - pathNew += L"."; - pathNew += stream.str().c_str(); - pathNew += L".log"; + m_vRotatedFiles.push_back(std::move(pathNew)); + RemoveObsoleteRotatedLogs(); + } - if (!MoveFile(m_strLogPath.c_str(), pathNew.c_str()) && GetLastError() != ERROR_FILE_NOT_FOUND) - throw std::runtime_error("Cannot rotate file"); + void TLogFile::RemoveObsoleteRotatedLogs() + { + while (m_vRotatedFiles.size() > m_spRotationInfo->GetMaxRotatedCount()) + { + auto iterRotatedFile = m_vRotatedFiles.begin(); + if (!DeleteFile(iterRotatedFile->c_str())) + break; - m_vRotatedFiles.push_back(std::move(pathNew)); - RemoveObsoleteRotatedLogs(); - } + m_vRotatedFiles.erase(iterRotatedFile); + } + } - void TLogFile::RemoveObsoleteRotatedLogs() - { - while (m_vRotatedFiles.size() > m_spRotationInfo->GetMaxRotatedCount()) + void TLogFile::ScanForRotatedLogs() { - auto iterRotatedFile = m_vRotatedFiles.begin(); - if (!DeleteFile(iterRotatedFile->c_str())) - break; + std::wstring strSearchMask = m_strLogPath; + std::wstring strDir; - m_vRotatedFiles.erase(iterRotatedFile); - } - } + size_t stDirPos = strSearchMask.find_last_of(L"\\/"); + if (stDirPos != std::wstring::npos) + strDir = strSearchMask.substr(0, stDirPos + 1); - void TLogFile::ScanForRotatedLogs() - { - std::wstring strSearchMask = m_strLogPath; - std::wstring strDir; + if (boost::iends_with(strSearchMask, L".log")) + strSearchMask.erase(strSearchMask.end() - 4, strSearchMask.end()); + strSearchMask += L".*.log"; - size_t stDirPos = strSearchMask.find_last_of(L"\\/"); - if (stDirPos != std::wstring::npos) - strDir = strSearchMask.substr(0, stDirPos + 1); + std::vector vPaths; + WIN32_FIND_DATA wfd = { 0 }; - if (boost::iends_with(strSearchMask, L".log")) - strSearchMask.erase(strSearchMask.end() - 4, strSearchMask.end()); - strSearchMask += L".*.log"; + HANDLE hFind = FindFirstFile(strSearchMask.c_str(), &wfd); + BOOL bFound = (hFind != INVALID_HANDLE_VALUE); + while (bFound) + { + std::wstring strLogFullPath = strDir + wfd.cFileName; + vPaths.push_back(strLogFullPath); - std::vector vPaths; - WIN32_FIND_DATA wfd = { 0 }; + bFound = FindNextFile(hFind, &wfd); + } - HANDLE hFind = FindFirstFile(strSearchMask.c_str(), &wfd); - BOOL bFound = (hFind != INVALID_HANDLE_VALUE); - while (bFound) + std::sort(vPaths.begin(), vPaths.end(), [](const std::wstring& path1, const std::wstring& path2) { return boost::ilexicographical_compare(path1, path2); }); + std::swap(m_vRotatedFiles, vPaths); + } + + bool TLogFile::NeedRotation(size_t stDataSize) { - std::wstring strLogFullPath = strDir + wfd.cFileName; - vPaths.push_back(strLogFullPath); + unsigned long long ullCurrentSize = GetCurrentLogSize(); + unsigned long long ullMaxLogSize = m_spRotationInfo->GetMaxLogSize(); - bFound = FindNextFile(hFind, &wfd); + return ullCurrentSize + stDataSize > ullMaxLogSize; } - - std::sort(vPaths.begin(), vPaths.end(), [](const std::wstring& path1, const std::wstring& path2) { return boost::ilexicographical_compare(path1, path2); }); - std::swap(m_vRotatedFiles, vPaths); } - - bool TLogFile::NeedRotation(size_t stDataSize) - { - unsigned long long ullCurrentSize = GetCurrentLogSize(); - unsigned long long ullMaxLogSize = m_spRotationInfo->GetMaxLogSize(); - - return ullCurrentSize + stDataSize > ullMaxLogSize; - } } Index: src/liblogger/TLogFile.h =================================================================== diff -u -r7de00e54431d78b6c54fad6fb163dbc306381ef5 -r545098ae76e9ce23598d37d2bee4020d6cb59f3c --- src/liblogger/TLogFile.h (.../TLogFile.h) (revision 7de00e54431d78b6c54fad6fb163dbc306381ef5) +++ src/liblogger/TLogFile.h (.../TLogFile.h) (revision 545098ae76e9ce23598d37d2bee4020d6cb59f3c) @@ -26,37 +26,39 @@ namespace logger { - // not exportable - class TLogFile + namespace internal { - public: - static const time_t MaxHandleCacheTime = 60; + class TLogFile + { + public: + static const time_t MaxHandleCacheTime = 60; - public: - TLogFile(PCTSTR pszPath, const TLoggerRotationInfoPtr& spRotationInfo); + public: + TLogFile(PCTSTR pszPath, const TLoggerRotationInfoPtr& spRotationInfo); - void Write(std::list& pszData); - void CloseIfUnused(); - void CloseLogFile(); + void Write(std::list& pszData); + void CloseIfUnused(); + void CloseLogFile(); - private: - HANDLE GetFileHandle(); - unsigned long long GetCurrentLogSize(); - void RotateFile(); - void RemoveObsoleteRotatedLogs(); - void ScanForRotatedLogs(); - bool NeedRotation(size_t stDataSize); + private: + HANDLE GetFileHandle(); + unsigned long long GetCurrentLogSize(); + void RotateFile(); + void RemoveObsoleteRotatedLogs(); + void ScanForRotatedLogs(); + bool NeedRotation(size_t stDataSize); - private: - std::wstring m_strLogPath; + private: + std::wstring m_strLogPath; - time_t m_timeLastWriteTime = 0; - std::shared_ptr m_spFileHandle; + time_t m_timeLastWriteTime = 0; + std::shared_ptr m_spFileHandle; - // rotation - TLoggerRotationInfoPtr m_spRotationInfo; - std::vector m_vRotatedFiles; - }; + // rotation + TLoggerRotationInfoPtr m_spRotationInfo; + std::vector m_vRotatedFiles; + }; + } } #endif Index: src/liblogger/TLogFileData.h =================================================================== diff -u -r7de00e54431d78b6c54fad6fb163dbc306381ef5 -r545098ae76e9ce23598d37d2bee4020d6cb59f3c --- src/liblogger/TLogFileData.h (.../TLogFileData.h) (revision 7de00e54431d78b6c54fad6fb163dbc306381ef5) +++ src/liblogger/TLogFileData.h (.../TLogFileData.h) (revision 545098ae76e9ce23598d37d2bee4020d6cb59f3c) @@ -52,7 +52,7 @@ TMultiLoggerConfigPtr m_spLoggerConfig; - TLogFile m_logFile; + internal::TLogFile m_logFile; #pragma warning(pop) friend class TLogRecord; Index: src/liblogger/liblogger.vc140.vcxproj =================================================================== diff -u -r7de00e54431d78b6c54fad6fb163dbc306381ef5 -r545098ae76e9ce23598d37d2bee4020d6cb59f3c --- src/liblogger/liblogger.vc140.vcxproj (.../liblogger.vc140.vcxproj) (revision 7de00e54431d78b6c54fad6fb163dbc306381ef5) +++ src/liblogger/liblogger.vc140.vcxproj (.../liblogger.vc140.vcxproj) (revision 545098ae76e9ce23598d37d2bee4020d6cb59f3c) @@ -468,6 +468,20 @@ + + true + true + true + true + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing + Index: src/liblogger/liblogger.vc140.vcxproj.filters =================================================================== diff -u -r7de00e54431d78b6c54fad6fb163dbc306381ef5 -r545098ae76e9ce23598d37d2bee4020d6cb59f3c --- src/liblogger/liblogger.vc140.vcxproj.filters (.../liblogger.vc140.vcxproj.filters) (revision 7de00e54431d78b6c54fad6fb163dbc306381ef5) +++ src/liblogger/liblogger.vc140.vcxproj.filters (.../liblogger.vc140.vcxproj.filters) (revision 545098ae76e9ce23598d37d2bee4020d6cb59f3c) @@ -12,6 +12,12 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + {30839f8d-ff2c-45d2-86fe-a7a494f42c8b} + + + {d67e75ea-a3ac-4115-b546-93a6914ee712} + @@ -35,18 +41,18 @@ Source Files - - Source Files - Source Files - - Source Files - Source Files\Library files + + Source Files\internal + + + Source Files + @@ -64,9 +70,6 @@ Source Files - - Source Files - Source Files @@ -76,5 +79,11 @@ Source Files\Library files + + Tests + + + Source Files\internal + \ No newline at end of file