#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