360 lines
6.9 KiB
C++
360 lines
6.9 KiB
C++
|
#include "precomp.h"
|
||
|
|
||
|
#ifdef PLS_DEBUG
|
||
|
#include "plog.h"
|
||
|
|
||
|
|
||
|
|
||
|
CCallLog::CCallLog(int size)
|
||
|
{
|
||
|
m_bValid = false;
|
||
|
|
||
|
DBG_SAVE_FILE_LINE
|
||
|
m_pLogEntry = new CPacketLogEntry[size];
|
||
|
if (m_pLogEntry == NULL)
|
||
|
{
|
||
|
WARNING_OUT(("CCallLog:Out of memory"));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_currentIndex = 0;
|
||
|
m_size = size;
|
||
|
m_bValid = true;
|
||
|
}
|
||
|
|
||
|
CCallLog::~CCallLog()
|
||
|
{
|
||
|
if (m_bValid)
|
||
|
{
|
||
|
delete [] m_pLogEntry;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
bool CCallLog::AddEntry(DWORD dwTimeStamp, DWORD dwSeqNum, LARGE_INTEGER LL_ArrivalTime, DWORD dwSize, bool fMark)
|
||
|
{
|
||
|
CPacketLogEntry Entry;
|
||
|
|
||
|
if (m_bValid == false) return false;
|
||
|
|
||
|
Entry.dwTimeStamp = dwTimeStamp;
|
||
|
Entry.dwSequenceNumber = dwSeqNum;
|
||
|
Entry.LL_ArrivalTime = LL_ArrivalTime;
|
||
|
Entry.dwSize = dwSize;
|
||
|
Entry.dwLosses = 0;
|
||
|
Entry.bLate = false;
|
||
|
Entry.bMark = fMark;
|
||
|
|
||
|
if (SizeCheck() == false)
|
||
|
return false;
|
||
|
|
||
|
m_pLogEntry[m_currentIndex++] = Entry;
|
||
|
return true;
|
||
|
|
||
|
}
|
||
|
|
||
|
bool CCallLog::SizeCheck()
|
||
|
{
|
||
|
if (m_bValid == false)
|
||
|
return false;
|
||
|
|
||
|
if (m_currentIndex < m_size)
|
||
|
return true;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool CCallLog::Flush(HANDLE hFile)
|
||
|
{
|
||
|
int index;
|
||
|
CPacketLogEntry *pEntry;
|
||
|
char szOutputLine[80];
|
||
|
DWORD dwNumWritten;
|
||
|
__int64 ArrivalTime64;
|
||
|
__int64 PerfFreq64;
|
||
|
LARGE_INTEGER LL_PerfFreq;
|
||
|
|
||
|
if (m_bValid == false)
|
||
|
return false;
|
||
|
|
||
|
if (hFile == INVALID_HANDLE_VALUE)
|
||
|
return false;
|
||
|
|
||
|
PerformStats();
|
||
|
|
||
|
// what's the performance frequency of this machine
|
||
|
QueryPerformanceFrequency(&LL_PerfFreq);
|
||
|
PerfFreq64 = LL_PerfFreq.QuadPart;
|
||
|
|
||
|
for (index = 0; index < m_currentIndex; index++)
|
||
|
{
|
||
|
pEntry = &m_pLogEntry[index];
|
||
|
|
||
|
ArrivalTime64 = pEntry->LL_ArrivalTime.QuadPart * 1000;
|
||
|
ArrivalTime64 = ArrivalTime64 / PerfFreq64;
|
||
|
|
||
|
sprintf(szOutputLine, "%d\t%d\t%d\t%d\t%d",
|
||
|
pEntry->dwTimeStamp,
|
||
|
pEntry->dwSequenceNumber,
|
||
|
(int)ArrivalTime64,
|
||
|
pEntry->dwSize,
|
||
|
pEntry->dwLosses);
|
||
|
|
||
|
if (pEntry->bMark)
|
||
|
strcat(szOutputLine, "\tMARK");
|
||
|
else strcat(szOutputLine, "\t");
|
||
|
|
||
|
if (pEntry->bLate)
|
||
|
strcat(szOutputLine, "\tLATE");
|
||
|
|
||
|
strcat(szOutputLine, "\n");
|
||
|
|
||
|
WriteFile(hFile, szOutputLine, strlen(szOutputLine), &dwNumWritten, NULL);
|
||
|
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
CCallLog& CCallLog::operator=(const CCallLog& log)
|
||
|
{
|
||
|
WARNING_OUT(("CCallLog:Assignment not supported"));
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
CCallLog::CCallLog(const CCallLog& log)
|
||
|
{
|
||
|
WARNING_OUT(("CCallLog:Copy constructor not supported"));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
bool CCallLog::PerformStats()
|
||
|
{
|
||
|
int index, probeIndex;
|
||
|
DWORD nextExpected;
|
||
|
bool bFound;
|
||
|
|
||
|
if (m_bValid == false)
|
||
|
return false;
|
||
|
|
||
|
if (m_currentIndex == 0)
|
||
|
return false;
|
||
|
|
||
|
// Set the current "loss" value for each entry to 0
|
||
|
for (index = 0; index < m_currentIndex; index++)
|
||
|
{
|
||
|
m_pLogEntry[index].dwLosses = 0;
|
||
|
m_pLogEntry[index].bLate = false;
|
||
|
}
|
||
|
|
||
|
// the first packet will always be a match with nextExpected
|
||
|
nextExpected = m_pLogEntry[0].dwSequenceNumber;
|
||
|
|
||
|
for (index = 0; index < m_currentIndex; index++)
|
||
|
{
|
||
|
if (nextExpected > 65535)
|
||
|
nextExpected = 0;
|
||
|
// if the packet has the next expected seq num, then everything is ok
|
||
|
if (m_pLogEntry[index].dwSequenceNumber == nextExpected)
|
||
|
{
|
||
|
nextExpected++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// we've detected a missing packet... time to go hunting
|
||
|
else if (m_pLogEntry[index].dwSequenceNumber > nextExpected)
|
||
|
{
|
||
|
bFound = false;
|
||
|
probeIndex = index+1;
|
||
|
while ((probeIndex < m_currentIndex) &&
|
||
|
(probeIndex < (index+PLOG_MAX_NOT_LATE)) )
|
||
|
{
|
||
|
if (m_pLogEntry[index].dwSequenceNumber == nextExpected)
|
||
|
bFound = true;
|
||
|
probeIndex++;
|
||
|
}
|
||
|
|
||
|
// the packet was merely out of sequence
|
||
|
if (bFound == true)
|
||
|
{
|
||
|
nextExpected++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// the packet is probably lost
|
||
|
// notice that we are simply incrementing dwLoss measure,
|
||
|
// rolling the index back one
|
||
|
m_pLogEntry[index].dwLosses++;
|
||
|
nextExpected++;
|
||
|
index--; // this is so we can continue to count additional
|
||
|
// loss packets for the same index
|
||
|
continue; // back to the top of the for-loop
|
||
|
}
|
||
|
|
||
|
// a packet that was either previously thought of as lost or late
|
||
|
else
|
||
|
{
|
||
|
m_pLogEntry[index].bLate = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
// --------------------------------------------------------------
|
||
|
|
||
|
CPacketLog::CPacketLog(LPTSTR szDiskFile):
|
||
|
m_hFile(INVALID_HANDLE_VALUE),
|
||
|
m_nExtension(0)
|
||
|
{
|
||
|
m_pCallLog = NULL;
|
||
|
strcpy(m_szDiskFile, szDiskFile);
|
||
|
}
|
||
|
|
||
|
|
||
|
// initializes an output file. Closes the current file if still open
|
||
|
bool CPacketLog::InitFile()
|
||
|
{
|
||
|
char szFileName[120];
|
||
|
|
||
|
if (m_hFile != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
CloseHandle(m_hFile);
|
||
|
m_hFile = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
|
||
|
sprintf(szFileName, "%s%d%s", m_szDiskFile, m_nExtension, PLOG_FILE_EXT);
|
||
|
m_hFile = CreateFile(szFileName,
|
||
|
GENERIC_READ|GENERIC_WRITE,
|
||
|
0, NULL, OPEN_EXISTING,
|
||
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
|
||
|
while ((m_hFile != INVALID_HANDLE_VALUE) && (m_nExtension < 100))
|
||
|
{
|
||
|
CloseHandle(m_hFile);
|
||
|
sprintf(szFileName, "%s%d%s", m_szDiskFile, m_nExtension, PLOG_FILE_EXT);
|
||
|
m_hFile = CreateFile(szFileName,
|
||
|
GENERIC_READ|GENERIC_WRITE,
|
||
|
0, NULL, OPEN_EXISTING,
|
||
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
m_nExtension++;
|
||
|
}
|
||
|
|
||
|
|
||
|
m_hFile = CreateFile(szFileName,
|
||
|
GENERIC_READ|GENERIC_WRITE,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
CREATE_ALWAYS,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL);
|
||
|
|
||
|
|
||
|
if (m_hFile == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
WARNING_OUT(("CPacketLog:Unable to initialize output file"));
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
CPacketLog::CPacketLog(const CPacketLog& packet_log)
|
||
|
{
|
||
|
// it wouldn't be an error if duphandle was used correctly
|
||
|
ERROR_OUT(("CPacketLog:Invalid to create a new packetLog via a copy constructor"));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
CPacketLog& CPacketLog::operator=(const CPacketLog& packet_log)
|
||
|
{
|
||
|
// it wouldn't be an error if duphandle was used correctly
|
||
|
ERROR_OUT(("CPacketLog:Invalid to create a new packetLog via the assignment operator"));
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
|
||
|
CPacketLog::~CPacketLog()
|
||
|
{
|
||
|
if (m_pCallLog != NULL)
|
||
|
{
|
||
|
Flush();
|
||
|
delete (m_pCallLog);
|
||
|
}
|
||
|
|
||
|
if (m_hFile != INVALID_HANDLE_VALUE)
|
||
|
CloseHandle(m_hFile);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
bool CPacketLog::Flush()
|
||
|
{
|
||
|
char *szCallHeader = "CALLSTART\n";
|
||
|
DWORD dwNumWritten;
|
||
|
|
||
|
if (m_pCallLog == NULL)
|
||
|
return false;
|
||
|
|
||
|
WriteFile(m_hFile, szCallHeader, strlen(szCallHeader), &dwNumWritten, NULL);
|
||
|
m_pCallLog->Flush(m_hFile);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
bool CPacketLog::MarkCallStart()
|
||
|
{
|
||
|
// write the previous call to file
|
||
|
if (m_pCallLog != NULL)
|
||
|
{
|
||
|
Flush();
|
||
|
CloseHandle(m_hFile);
|
||
|
m_hFile = INVALID_HANDLE_VALUE;
|
||
|
delete m_pCallLog;
|
||
|
}
|
||
|
|
||
|
if (false == InitFile())
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
DBG_SAVE_FILE_LINE
|
||
|
m_pCallLog = new CCallLog(PLOG_MAX_PACKETS_CALL);
|
||
|
if (m_pCallLog == NULL)
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool CPacketLog::AddEntry(DWORD dwTimeStamp, DWORD dwSeqNum, LARGE_INTEGER LL_ArrivalTime, DWORD dwSize, bool fMark)
|
||
|
{
|
||
|
if (m_pCallLog == NULL)
|
||
|
{
|
||
|
if (false == MarkCallStart())
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return (m_pCallLog->AddEntry(dwTimeStamp, dwSeqNum, LL_ArrivalTime, dwSize, fMark));
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
// if-def pls_debug
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
|