third-party libs
This commit is contained in:
parent
f836927d3a
commit
b154ee9266
3667 changed files with 854591 additions and 0 deletions
332
third-party/BugTrap-1.3-57bd515/source/XmlLogFile.cpp
vendored
Normal file
332
third-party/BugTrap-1.3-57bd515/source/XmlLogFile.cpp
vendored
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
/*
|
||||
* This is a part of the BugTrap package.
|
||||
* Copyright (c) 2005-2009 IntelleSoft.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: XML log file.
|
||||
* Author: Maksim Pyatkovskiy.
|
||||
*
|
||||
* This source code is only intended as a supplement to the
|
||||
* BugTrap package reference and related electronic documentation
|
||||
* provided with the product. See these sources for detailed
|
||||
* information regarding the BugTrap package.
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "XmlLogFile.h"
|
||||
#include "FileStream.h"
|
||||
#include "XmlReader.h"
|
||||
#include "XmlWriter.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#endif
|
||||
|
||||
CXmlLogFile::CStrLogRecord::CStrLogRecord(void) :
|
||||
m_strLogLevel(8),
|
||||
m_strTimeStatistics(32),
|
||||
m_strEntryText(1024)
|
||||
{
|
||||
}
|
||||
|
||||
void CXmlLogFile::CStrLogRecord::Reset(void)
|
||||
{
|
||||
m_strLogLevel.Reset();
|
||||
m_strTimeStatistics.Reset();
|
||||
m_strEntryText.Reset();
|
||||
}
|
||||
|
||||
void CXmlLogFile::CPtrLogRecord::Reset(void)
|
||||
{
|
||||
m_pszLogLevel = _T("");
|
||||
m_pszTimeStatistics = _T("");
|
||||
m_pszEntryText = _T("");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the log was loaded successfully.
|
||||
*/
|
||||
BOOL CXmlLogFile::LoadEntries(void)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
DWORD dwStartTime = GetTickCount();
|
||||
#endif
|
||||
BOOL bResult = FALSE;
|
||||
PCTSTR pszLogFileName = GetLogFileName();
|
||||
CFileStream FileStream;
|
||||
if (FileStream.Open(pszLogFileName, OPEN_EXISTING, GENERIC_READ, FILE_SHARE_READ))
|
||||
{
|
||||
size_t nFileSize = FileStream.GetLength();
|
||||
if (nFileSize == 0)
|
||||
{
|
||||
// ignore empty files
|
||||
return TRUE;
|
||||
}
|
||||
CXmlReader XmlReader(&FileStream);
|
||||
CXmlReader::CXmlNode XmlNode;
|
||||
int iResult = XmlReader.GotoNextElement(_T("log"), XmlNode, CXmlReader::XGF_ALLOW_ELEMENT_END);
|
||||
if (iResult < 0)
|
||||
goto end;
|
||||
if (iResult > 0 && XmlNode.GetNodeType() == CXmlReader::CXmlNode::XNT_ELEMENT_BEGIN)
|
||||
{
|
||||
CStrLogRecord LogRecord;
|
||||
for (;;)
|
||||
{
|
||||
iResult = XmlReader.GotoNextElement(_T("entry"), XmlNode, CXmlReader::XGF_ALLOW_ELEMENT_END);
|
||||
if (iResult <= 0)
|
||||
goto end;
|
||||
if (XmlNode.GetNodeType() == CXmlReader::CXmlNode::XNT_ELEMENT_END)
|
||||
break;
|
||||
_ASSERTE(XmlNode.GetNodeType() == CXmlReader::CXmlNode::XNT_ELEMENT_BEGIN);
|
||||
LogRecord.Reset();
|
||||
|
||||
iResult = XmlReader.GotoNextElement(_T("level"), XmlNode, 0);
|
||||
if (iResult <= 0)
|
||||
goto end;
|
||||
_ASSERTE(
|
||||
XmlNode.GetNodeType() == CXmlReader::CXmlNode::XNT_ELEMENT_BEGIN ||
|
||||
XmlNode.GetNodeType() == CXmlReader::CXmlNode::XNT_ELEMENT);
|
||||
// enforce constraint: log level is required field
|
||||
if (XmlNode.GetNodeType() != CXmlReader::CXmlNode::XNT_ELEMENT_BEGIN)
|
||||
goto end;
|
||||
iResult = XmlReader.GotoText(XmlNode, 0);
|
||||
if (iResult <= 0)
|
||||
goto end;
|
||||
_ASSERTE(XmlNode.GetNodeType() == CXmlReader::CXmlNode::XNT_TEXT);
|
||||
LogRecord.SetLogLevel(XmlNode.GetNodeValue());
|
||||
iResult = XmlReader.GotoNextElementEnd(XmlNode, 0);
|
||||
if (iResult <= 0)
|
||||
goto end;
|
||||
|
||||
iResult = XmlReader.GotoNextElement(_T("time"), XmlNode, 0);
|
||||
if (iResult <= 0)
|
||||
goto end;
|
||||
_ASSERTE(
|
||||
XmlNode.GetNodeType() == CXmlReader::CXmlNode::XNT_ELEMENT_BEGIN ||
|
||||
XmlNode.GetNodeType() == CXmlReader::CXmlNode::XNT_ELEMENT);
|
||||
// enforce constraint: time statistics is required field
|
||||
if (XmlNode.GetNodeType() != CXmlReader::CXmlNode::XNT_ELEMENT_BEGIN)
|
||||
goto end;
|
||||
iResult = XmlReader.GotoText(XmlNode, 0);
|
||||
if (iResult <= 0)
|
||||
goto end;
|
||||
_ASSERTE(XmlNode.GetNodeType() == CXmlReader::CXmlNode::XNT_TEXT);
|
||||
LogRecord.SetTimeStatistics(XmlNode.GetNodeValue());
|
||||
iResult = XmlReader.GotoNextElementEnd(XmlNode, 0);
|
||||
if (iResult <= 0)
|
||||
goto end;
|
||||
|
||||
iResult = XmlReader.GotoNextElement(_T("text"), XmlNode, 0);
|
||||
if (iResult <= 0)
|
||||
goto end;
|
||||
_ASSERTE(
|
||||
XmlNode.GetNodeType() == CXmlReader::CXmlNode::XNT_ELEMENT_BEGIN ||
|
||||
XmlNode.GetNodeType() == CXmlReader::CXmlNode::XNT_ELEMENT);
|
||||
// entry text is optional field
|
||||
if (XmlNode.GetNodeType() == CXmlReader::CXmlNode::XNT_ELEMENT_BEGIN)
|
||||
{
|
||||
iResult = XmlReader.GotoText(XmlNode, CXmlReader::XGF_ALLOW_ELEMENT_END);
|
||||
if (iResult <= 0)
|
||||
goto end;
|
||||
_ASSERTE(
|
||||
XmlNode.GetNodeType() == CXmlReader::CXmlNode::XNT_TEXT ||
|
||||
XmlNode.GetNodeType() == CXmlReader::CXmlNode::XNT_ELEMENT_END);
|
||||
if (XmlNode.GetNodeType() == CXmlReader::CXmlNode::XNT_TEXT)
|
||||
{
|
||||
LogRecord.SetEntryText(XmlNode.GetNodeValue());
|
||||
iResult = XmlReader.GotoNextElementEnd(XmlNode, 0);
|
||||
if (iResult <= 0)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (! AddToTail(LogRecord))
|
||||
goto end;
|
||||
iResult = XmlReader.GotoNextElementEnd(XmlNode, 0);
|
||||
if (iResult <= 0)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
bResult = TRUE;
|
||||
end:
|
||||
if (! bResult)
|
||||
FreeEntries();
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD dwLastError = FileStream.GetLastError();
|
||||
if (dwLastError == ERROR_FILE_NOT_FOUND ||
|
||||
dwLastError == ERROR_PATH_NOT_FOUND ||
|
||||
GetFileAttributes(pszLogFileName) == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
bResult = TRUE; // ignore missing files
|
||||
}
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
DWORD dwEndTime = GetTickCount();
|
||||
TCHAR szMessage[128];
|
||||
_stprintf_s(szMessage, countof(szMessage), _T("CXmlLogFile::LoadEntries(): %lu entries, %lu bytes, %lu milliseconds\r\n"), GetNumEntries(), GetNumBytes(), dwEndTime - dwStartTime);
|
||||
OutputDebugString(szMessage);
|
||||
#endif
|
||||
return bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bCrash - true if crash has occurred.
|
||||
* @return true if the log was saved successfully.
|
||||
*/
|
||||
BOOL CXmlLogFile::SaveEntries(BOOL /*bCrash*/)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
DWORD dwStartTime = GetTickCount();
|
||||
#endif
|
||||
PCTSTR pszLogFileName = GetLogFileName();
|
||||
CFileStream FileStream(1024);
|
||||
if (! FileStream.Open(pszLogFileName, CREATE_ALWAYS, GENERIC_WRITE))
|
||||
return FALSE;
|
||||
CXmlWriter XmlWriter(&FileStream);
|
||||
XmlWriter.SetIndentation(_T(' '), 2);
|
||||
XmlWriter.WriteStartDocument();
|
||||
XmlWriter.WriteStartElement(_T("log")); // <log>
|
||||
CLogEntry* pLogEntry = GetFirstEntry();
|
||||
while (pLogEntry)
|
||||
{
|
||||
CXmlLogEntry* pXmlLogEntry = (CXmlLogEntry*)pLogEntry;
|
||||
PTCHAR pchPointer = pXmlLogEntry->m_pchData;
|
||||
_ASSERTE(pchPointer != NULL);
|
||||
PCTSTR pszLogLevel = pchPointer;
|
||||
pchPointer += _tcslen(pchPointer) + 1;
|
||||
PCTSTR pszTimeStatistics = pchPointer;
|
||||
pchPointer += _tcslen(pchPointer) + 1;
|
||||
PCTSTR pszEntry = pchPointer;
|
||||
//pchPointer += _tcslen(pchPointer) + 1;
|
||||
XmlWriter.WriteStartElement(_T("entry")); // <entry>
|
||||
XmlWriter.WriteElementString(_T("level"), pszLogLevel); // <level>...</level>
|
||||
XmlWriter.WriteElementString(_T("time"), pszTimeStatistics); // <time>...</time>
|
||||
XmlWriter.WriteElementString(_T("text"), pszEntry); // <text>...</text>
|
||||
XmlWriter.WriteEndElement(); // </entry>
|
||||
pLogEntry = pLogEntry->m_pNextEntry;
|
||||
}
|
||||
XmlWriter.WriteEndElement(); // </log>
|
||||
XmlWriter.WriteEndDocument();
|
||||
#ifdef _DEBUG
|
||||
DWORD dwEndTime = GetTickCount();
|
||||
TCHAR szMessage[128];
|
||||
_stprintf_s(szMessage, countof(szMessage), _T("CXmlLogFile::SaveEntries(): %lu entries, %lu bytes, %lu milliseconds\r\n"), GetNumEntries(), GetNumBytes(), dwEndTime - dwStartTime);
|
||||
OutputDebugString(szMessage);
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rLogRecord - reference the log record.
|
||||
* @return pointer to the new entry.
|
||||
*/
|
||||
CXmlLogFile::CXmlLogEntry* CXmlLogFile::AllocLogEntry(const CBaseLogRecord& rLogRecord)
|
||||
{
|
||||
PCTSTR pszLogLevel = rLogRecord.GetLogLevel();
|
||||
DWORD dwLogLevelSize = rLogRecord.GetLogLevelLength() + 1;
|
||||
PCTSTR pszTimeStatistics = rLogRecord.GetTimeStatistics();
|
||||
DWORD dwTimeStatisticsSize = rLogRecord.GetTimeStatisticsLength() + 1;
|
||||
PCTSTR pszEntryText = rLogRecord.GetEntryText();
|
||||
DWORD dwEntryTextSize = rLogRecord.GetEntryTextLength() + 1;
|
||||
DWORD dwLogRecordSize = dwLogLevelSize + dwTimeStatisticsSize + dwEntryTextSize + 1;
|
||||
CXmlLogEntry* pLogEntry = (CXmlLogEntry*)new BYTE[sizeof(CXmlLogEntry) + dwLogRecordSize * sizeof(TCHAR)];
|
||||
if (pLogEntry)
|
||||
{
|
||||
PTCHAR pchPointer = pLogEntry->m_pchData;
|
||||
_ASSERTE(pchPointer != NULL);
|
||||
|
||||
_tcscpy_s(pchPointer, dwLogLevelSize, pszLogLevel);
|
||||
pchPointer += dwLogLevelSize;
|
||||
dwLogLevelSize = (DWORD)GetStringSizeInUTF8(pszLogLevel);
|
||||
|
||||
_tcscpy_s(pchPointer, dwTimeStatisticsSize, pszTimeStatistics);
|
||||
pchPointer += dwTimeStatisticsSize;
|
||||
dwTimeStatisticsSize = (DWORD)GetStringSizeInUTF8(pszTimeStatistics);
|
||||
|
||||
_tcscpy_s(pchPointer, dwEntryTextSize, pszEntryText);
|
||||
pchPointer += dwEntryTextSize;
|
||||
dwEntryTextSize = (DWORD)GetStringSizeInUTF8(pszEntryText);
|
||||
|
||||
*pchPointer = _T('\0');
|
||||
pLogEntry->m_dwSize = dwLogLevelSize + dwTimeStatisticsSize + dwEntryTextSize +
|
||||
sizeof(" <entry>\r\n"
|
||||
" <level></level>\r\n"
|
||||
" <time></time>\r\n"
|
||||
" <text></text>\r\n"
|
||||
" </entry>\r\n") - 1;
|
||||
}
|
||||
return pLogEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rLogRecord - reference the log record.
|
||||
* @return true if entry was added.
|
||||
*/
|
||||
BOOL CXmlLogFile::AddToHead(const CBaseLogRecord& rLogRecord)
|
||||
{
|
||||
CXmlLogEntry* pLogEntry = AllocLogEntry(rLogRecord);
|
||||
if (pLogEntry)
|
||||
{
|
||||
CInMemLogFile::AddToHead(pLogEntry);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rLogRecord - reference the log record.
|
||||
* @return true if entry was added.
|
||||
*/
|
||||
BOOL CXmlLogFile::AddToTail(const CBaseLogRecord& rLogRecord)
|
||||
{
|
||||
CXmlLogEntry* pLogEntry = AllocLogEntry(rLogRecord);
|
||||
if (pLogEntry)
|
||||
{
|
||||
CInMemLogFile::AddToTail(pLogEntry);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param eLogLevel - log level number.
|
||||
* @param eEntryMode - entry mode.
|
||||
* @param rcsConsoleAccess - provides synchronous access to the console.
|
||||
* @param pszEntry - log entry text.
|
||||
* @return true if operation was completed successfully.
|
||||
*/
|
||||
BOOL CXmlLogFile::WriteLogEntry(BUGTRAP_LOGLEVEL eLogLevel, ENTRY_MODE eEntryMode, CRITICAL_SECTION& rcsConsoleAccess, PCTSTR pszEntry)
|
||||
{
|
||||
BOOL bResult = TRUE;
|
||||
BUGTRAP_LOGLEVEL eLogFileLevel = GetLogLevel();
|
||||
if (eLogLevel <= eLogFileLevel)
|
||||
{
|
||||
SYSTEMTIME st;
|
||||
GetLocalTime(&st);
|
||||
WriteLogEntryToConsole(eLogLevel, &st, rcsConsoleAccess, pszEntry);
|
||||
PCTSTR pszLogLevelPrefix = GetLogLevelPrefix(eLogLevel);
|
||||
TCHAR szTimeStatistics[32];
|
||||
GetTimeStatistics(&st, szTimeStatistics, countof(szTimeStatistics));
|
||||
CPtrLogRecord LogRecord;
|
||||
LogRecord.SetLogLevel(pszLogLevelPrefix);
|
||||
LogRecord.SetTimeStatistics(szTimeStatistics);
|
||||
LogRecord.SetEntryText(pszEntry);
|
||||
switch (eEntryMode)
|
||||
{
|
||||
case EM_APPEND:
|
||||
AddToTail(LogRecord);
|
||||
break;
|
||||
case EM_INSERT:
|
||||
AddToHead(LogRecord);
|
||||
break;
|
||||
default:
|
||||
_ASSERT(FALSE);
|
||||
bResult = FALSE;
|
||||
}
|
||||
}
|
||||
return bResult;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue