Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

359 lines
6.9 KiB

#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