// PassportPerfMon.cpp: implementation of the PassportPerfMon class. // ////////////////////////////////////////////////////////////////////// #define _PassportExport_ #include "PassportExport.h" #include "PassportPerfMon.h" #include "PassportPerf.h" #include //------------------------------------------------------------- // // PassportPerfMon const // //------------------------------------------------------------- PassportPerfMon::PassportPerfMon( ) : PassportSharedMemory() { isInited = FALSE; dwNumInstances = 0; } //------------------------------------------------------------- // // ~PassportPerfMon // //------------------------------------------------------------- PassportPerfMon::~PassportPerfMon() { } //------------------------------------------------------------- // // init // //------------------------------------------------------------- BOOL PassportPerfMon::init( LPCTSTR lpcPerfObjectName ) { if (isInited) { return FALSE; } _ASSERT( lpcPerfObjectName ); InitializeCriticalSection(&mInitLock); EnterCriticalSection(&mInitLock); // File mapped memory layout // 1. MAX_COUNTERS of DWORD for the counter types // 2. if dwNumInstances == 0, then // (a) MAX_COUNTERS of DWORDS of the counter data // else (dwNumInstances > 0) // (b) MAX_COUNTERS of INSTANCE_DATA structures each followed // immediately by MAX_COUNTERS of DWORDS of the counter data DWORD dwSize = ( (MAX_COUNTERS * sizeof(DWORD)) // for counter type + (MAX_INSTANCES * (sizeof(INSTANCE_DATA) + (MAX_COUNTERS * sizeof(DWORD)))) ); if (!CreateSharedMemory(0, dwSize, lpcPerfObjectName, TRUE)) { // raise information alert if (!OpenSharedMemory (lpcPerfObjectName, TRUE )) { LeaveCriticalSection(&mInitLock); return FALSE; } } // zero new memory memset((void *)m_pbShMem, 0, dwSize); // setup counter types to default, note that the counters // start at index 1 in SHM PPERF_COUNTER_BLOCK pCounterBlock = (PPERF_COUNTER_BLOCK)m_pbShMem; _ASSERT(pCounterBlock); for (DWORD i = 0; i < MAX_COUNTERS; i++) { PDWORD pdwCounter = ((PDWORD) pCounterBlock) + i; _ASSERT(pdwCounter); *pdwCounter = (LONG)PERF_TYPE_ZERO; } isInited = TRUE; LeaveCriticalSection(&mInitLock); return isInited; } //------------------------------------------------------------- // // incrementCounter // //------------------------------------------------------------- BOOL PassportPerfMon::incrementCounter ( const DWORD &dwType, LPCSTR lpszInstanceName ) { if (!isInited) { return FALSE; } _ASSERT( (dwType >= 0) && (dwType < MAX_COUNTERS)); _ASSERT(m_pbShMem); DWORD dwIndex = ((dwType == 0) ? 0 : (DWORD)(dwType/2)); BYTE* pb = (BYTE*)m_pbShMem; _ASSERT(pb); pb += MAX_COUNTERS * sizeof(DWORD); // if lpszInstanceName == NULL, select the first datablock after // the first INSTANCE_DATA, else iterate until we find the // right instance name // TBD insert thread locking for (DWORD i = 0; i < MAX_INSTANCES; i++) { INSTANCE_DATA * pInst = (INSTANCE_DATA *)pb; _ASSERT(pInst); pb += sizeof(INSTANCE_DATA); //TODO** mikeguo -- tune up this lookup -- too expensive -- check the first character or something if (lpszInstanceName == NULL || (pInst->active && strcmp(pInst->szInstanceName, lpszInstanceName) == 0) ) { PPERF_COUNTER_BLOCK pCounterBlock = (PPERF_COUNTER_BLOCK)pb; _ASSERT(pCounterBlock); PDWORD pdwCounter = ((PDWORD) pCounterBlock) + dwIndex; _ASSERT(pdwCounter); InterlockedIncrement((long *)pdwCounter); return TRUE; } pb += (MAX_COUNTERS * sizeof(DWORD)); } return FALSE; } //------------------------------------------------------------- // // decrementCounter // //------------------------------------------------------------- BOOL PassportPerfMon::decrementCounter ( const DWORD &dwType, LPCSTR lpszInstanceName ) { if (!isInited) { return FALSE; } _ASSERT( (dwType >= 0) && (dwType < MAX_COUNTERS)); _ASSERT(m_pbShMem); DWORD dwIndex = ((dwType == 0) ? 0 : (DWORD)(dwType/2)); BYTE* pb = (BYTE*)m_pbShMem; _ASSERT(pb); pb += MAX_COUNTERS * sizeof(DWORD); // if lpszInstanceName == NULL, select the first datablock after // the first INSTANCE_DATA, else iterate until we find the // right instance name // TBD insert thread locking for (DWORD i = 0; i < MAX_INSTANCES; i++) { INSTANCE_DATA * pInst = (INSTANCE_DATA *)pb; _ASSERT(pInst); pb += sizeof(INSTANCE_DATA); if (lpszInstanceName == NULL || (pInst->active && strcmp(pInst->szInstanceName, lpszInstanceName) == 0) ) { PPERF_COUNTER_BLOCK pCounterBlock = (PPERF_COUNTER_BLOCK)pb; _ASSERT(pCounterBlock); PDWORD pdwCounter = ((PDWORD) pCounterBlock) + dwIndex; _ASSERT(pdwCounter); InterlockedDecrement((long *)pdwCounter); return TRUE; } pb += (MAX_COUNTERS * sizeof(DWORD)); } return FALSE; } //------------------------------------------------------------- // // setCounter // //------------------------------------------------------------- BOOL PassportPerfMon::setCounter ( const DWORD &dwType, const DWORD &dwValue, LPCSTR lpszInstanceName ) { if (!isInited) { return FALSE; } _ASSERT( (dwType >= 0) && (dwType < MAX_COUNTERS)); _ASSERT(m_pbShMem); DWORD dwIndex = ((dwType == 0) ? 0 : (DWORD)(dwType/2)); BYTE* pb = (BYTE*)m_pbShMem; _ASSERT(pb); pb += MAX_COUNTERS * sizeof(DWORD); // if lpszInstanceName == NULL, select the first datablock after // the first INSTANCE_DATA, else iterate until we find the // right instance name // TBD insert thread locking for (DWORD i = 0; i < MAX_INSTANCES; i++) { INSTANCE_DATA * pInst = (INSTANCE_DATA *)pb; _ASSERT(pInst); pb += sizeof(INSTANCE_DATA); if (lpszInstanceName == NULL || (pInst->active && strcmp(pInst->szInstanceName, lpszInstanceName) == 0) ) { PPERF_COUNTER_BLOCK pCounterBlock = (PPERF_COUNTER_BLOCK)pb; _ASSERT(pCounterBlock); PDWORD pdwCounter = ((PDWORD) pCounterBlock) + dwIndex; _ASSERT(pdwCounter); InterlockedExchange((LPLONG) pdwCounter, (LONG)dwValue); return TRUE; } pb += (MAX_COUNTERS * sizeof(DWORD)); } return FALSE; } //------------------------------------------------------------- // // getCounterValue // //------------------------------------------------------------- BOOL PassportPerfMon::getCounterValue ( DWORD &dwValue, const DWORD &dwType, LPCSTR lpszInstanceName ) { if (!isInited) { dwValue = 0; return FALSE; } _ASSERT( (dwType >= 0) && (dwType < MAX_COUNTERS)); _ASSERT(m_pbShMem); DWORD dwIndex = ((dwType == 0) ? 0 : (DWORD)(dwType/2)); BYTE* pb = (BYTE*)m_pbShMem; _ASSERT(pb); pb += MAX_COUNTERS * sizeof(DWORD); // if lpszInstanceName == NULL, select the first datablock after // the first INSTANCE_DATA, else iterate until we find the // right instance name // TBD insert thread locking for (DWORD i = 0; i < MAX_INSTANCES; i++) { INSTANCE_DATA * pInst = (INSTANCE_DATA *)pb; _ASSERT(pInst); pb += sizeof(INSTANCE_DATA); if (lpszInstanceName == NULL || (pInst->active && strcmp(pInst->szInstanceName, lpszInstanceName) == 0) ) { PPERF_COUNTER_BLOCK pCounterBlock = (PPERF_COUNTER_BLOCK)pb; _ASSERT(pCounterBlock); PDWORD pdwCounter = ((PDWORD) pCounterBlock) + dwIndex; _ASSERT(pdwCounter); // // The counter is aligned with DWORD. Simple read does not need // the sync operation here. // dwValue = (*pdwCounter); return TRUE; } pb += (MAX_COUNTERS * sizeof(DWORD)); } return TRUE; } //------------------------------------------------------------- // // setCounterType // //------------------------------------------------------------- BOOL PassportPerfMon::setCounterType ( const DWORD &dwType, const PassportPerfInterface::COUNTER_SAMPLING_TYPE &counterSampleType) { if (!isInited) { return FALSE; } _ASSERT( (dwType >= 0) && (dwType < MAX_COUNTERS)); _ASSERT(m_pbShMem); DWORD dwIndex = ((dwType == 0) ? 0 : (DWORD)(dwType/2)); DWORD dwPerfType = 0; switch ( counterSampleType ) { case (PassportPerfInterface::COUNTER_COUNTER): dwPerfType = PERF_COUNTER_COUNTER; break; case (PassportPerfInterface::AVERAGE_TIMER): dwPerfType = PERF_AVERAGE_TIMER; break; case (PassportPerfInterface::COUNTER_DELTA): dwPerfType = PERF_COUNTER_DELTA; break; case (PassportPerfInterface::COUNTER_RAWCOUNT): case (PassportPerfInterface::COUNTER_UNDEFINED): default: dwPerfType = PERF_COUNTER_RAWCOUNT; break; } PPERF_COUNTER_BLOCK pCounterBlock = (PPERF_COUNTER_BLOCK)m_pbShMem; _ASSERT(pCounterBlock); PDWORD pdwCounter = ((PDWORD) pCounterBlock) + (dwIndex-1); _ASSERT(pdwCounter); InterlockedExchange((LPLONG) pdwCounter, (LONG)dwPerfType); return FALSE; } //------------------------------------------------------------- // // getCounterType // //------------------------------------------------------------- PassportPerfInterface::COUNTER_SAMPLING_TYPE PassportPerfMon::getCounterType( const DWORD &dwType ) const { if (!isInited) { return PassportPerfInterface::COUNTER_UNDEFINED; } _ASSERT( (dwType >= 0) && (dwType < MAX_COUNTERS)); _ASSERT(m_pbShMem); DWORD dwIndex = ((dwType == 0) ? 0 : (DWORD)(dwType/2)); DWORD dwPerfType = 0; PPERF_COUNTER_BLOCK pCounterBlock = (PPERF_COUNTER_BLOCK)m_pbShMem; PDWORD pdwCounter = ((PDWORD) pCounterBlock) + (dwIndex-1); _ASSERT(pdwCounter); // // Simple read does not need the sync op here // dwPerfType = (*pdwCounter); switch ( dwPerfType ) { case (PERF_COUNTER_COUNTER): return PassportPerfInterface::COUNTER_COUNTER; case (PERF_AVERAGE_TIMER): return PassportPerfInterface::AVERAGE_TIMER; case (PERF_COUNTER_DELTA): return PassportPerfInterface::COUNTER_DELTA; case (PERF_COUNTER_RAWCOUNT): return PassportPerfInterface::COUNTER_RAWCOUNT; default: return PassportPerfInterface::COUNTER_UNDEFINED; } } //------------------------------------------------------------- // // addInstance // //------------------------------------------------------------- BOOL PassportPerfMon::addInstance( LPCSTR lpszInstanceName ) { if (!isInited || lpszInstanceName == NULL) { return FALSE; } if (strlen(lpszInstanceName) >= sizeof(INSTANCENAME)) { // // Why not TCHAR here? // return FALSE; } _ASSERT(m_pbShMem); BYTE* pb = (BYTE*)m_pbShMem; _ASSERT(pb); pb += MAX_COUNTERS * sizeof(DWORD); DWORD dw = WaitForSingleObject(m_hMutex,INFINITE); if (dw == WAIT_OBJECT_0) { // find if the instance already exists, if so fail for (DWORD i = 0; i < MAX_INSTANCES; i++) { INSTANCE_DATA * pInst = (INSTANCE_DATA *)pb; _ASSERT(pInst); if (pInst->active) { if (strcmp(pInst->szInstanceName, lpszInstanceName) == 0) { ReleaseMutex(m_hMutex); return FALSE; } } pb += sizeof(INSTANCE_DATA) + (MAX_COUNTERS * sizeof(DWORD)); } // insert the instance in the first available slot pb = (BYTE*)m_pbShMem; _ASSERT(pb); pb += MAX_COUNTERS * sizeof(DWORD); for (i = 0; i < MAX_INSTANCES; i++) { INSTANCE_DATA * pInst = (INSTANCE_DATA *)pb; _ASSERT(pInst); if (!pInst->active) { strcpy(pInst->szInstanceName, lpszInstanceName); pInst->active = TRUE; InterlockedIncrement(&dwNumInstances); pb += sizeof(INSTANCE_DATA); memset(pb,0,(MAX_COUNTERS * sizeof(DWORD))); ReleaseMutex(m_hMutex); return TRUE; } pb += sizeof(INSTANCE_DATA) + (MAX_COUNTERS * sizeof(DWORD)); } // didn't find it, fail ReleaseMutex(m_hMutex); return FALSE; } else { ReleaseMutex(m_hMutex); return FALSE; } } //------------------------------------------------------------- // // deleteInstance // //------------------------------------------------------------- BOOL PassportPerfMon::deleteInstance( LPCSTR lpszInstanceName ) { if (!isInited || lpszInstanceName == NULL) { return FALSE; } _ASSERT(m_pbShMem); BYTE* pb = (BYTE*)m_pbShMem; _ASSERT(pb); pb += MAX_COUNTERS * sizeof(DWORD); DWORD dw = WaitForSingleObject(m_hMutex,INFINITE); if (dw == WAIT_OBJECT_0) { // find if the instance already exists, if so set it inactive for (DWORD i = 0; i < MAX_INSTANCES; i++) { INSTANCE_DATA * pInst = (INSTANCE_DATA *)pb; _ASSERT(pInst); if (pInst->active && strcmp(pInst->szInstanceName, lpszInstanceName) == 0) { pInst->active = FALSE; InterlockedDecrement(&dwNumInstances); // zero the data pb += sizeof(INSTANCE_DATA); memset(pb,0,(MAX_COUNTERS * sizeof(DWORD))); ReleaseMutex(m_hMutex); return TRUE; } pb += sizeof(INSTANCE_DATA)+(MAX_COUNTERS * sizeof(DWORD)); } // didn't find it, fail ReleaseMutex(m_hMutex); return FALSE; } else { ReleaseMutex(m_hMutex); return FALSE; } } //------------------------------------------------------------- // // hasInstances // //------------------------------------------------------------- BOOL PassportPerfMon::hasInstances( void ) { DWORD dwNum = (DWORD)InterlockedExchangeAdd(&dwNumInstances,0); if (dwNum > 0) return TRUE; else return FALSE; } //------------------------------------------------------------- // // numInstances // //------------------------------------------------------------- DWORD PassportPerfMon::numInstances( void ) { DWORD rv = (DWORD)InterlockedExchangeAdd(&dwNumInstances,0); return rv; } //------------------------------------------------------------- // // instanceExists // //------------------------------------------------------------- BOOL PassportPerfMon::instanceExists ( LPCSTR lpszInstanceName ) { if (!isInited || lpszInstanceName == NULL) { return FALSE; } _ASSERT(m_pbShMem); BYTE* pb = (BYTE*)m_pbShMem; _ASSERT(pb); DWORD dw = WaitForSingleObject(m_hMutex,INFINITE); if (dw == WAIT_OBJECT_0) { pb += MAX_COUNTERS * sizeof(DWORD); for (DWORD i = 0; i < MAX_INSTANCES; i++) { INSTANCE_DATA * pInst = (INSTANCE_DATA *)pb; _ASSERT(pInst); if (pInst->active && strcmp(pInst->szInstanceName, lpszInstanceName) == 0) { ReleaseMutex(m_hMutex); return TRUE; } pb += sizeof(INSTANCE_DATA) + (MAX_COUNTERS * sizeof(DWORD)); } // didn't find it, fail ReleaseMutex(m_hMutex); return FALSE; } else { ReleaseMutex(m_hMutex); return FALSE; } return FALSE; }