/*++ Copyright (c) 1996 Microsoft Corporation Module Name: perfcach.c Abstract: This file implements an Performance Object that presents File System Cache data Created: Bob Watson 22-Oct-1996 Revision History --*/ // // Include Files // #include #include #include #include #include #include #include #include #include "perfos.h" #include "datacach.h" // // The following special defines are used to produce numbers for // cache measurement counters // #define SYNC_ASYNC(FLD) ((SysPerfInfo.FLD##Wait) + (SysPerfInfo.FLD##NoWait)) // // Hit Rate Macro // #define HITRATE(FLD) (((Changes = SysPerfInfo.FLD) == 0) ? 0 : \ ((Changes < (Misses = SysPerfInfo.FLD##Miss)) ? 0 : \ (Changes - Misses) )) // // Hit Rate Macro combining Sync and Async cases // #define SYNC_ASYNC_HITRATE(FLD) (((Changes = SYNC_ASYNC(FLD)) == 0) ? 0 : \ ((Changes < \ (Misses = SysPerfInfo.FLD##WaitMiss + \ SysPerfInfo.FLD##NoWaitMiss) \ ) ? 0 : \ (Changes - Misses) )) DWORD APIENTRY CollectCacheObjectData ( IN OUT LPVOID *lppData, IN OUT LPDWORD lpcbTotalBytes, IN OUT LPDWORD lpNumObjectTypes ) /*++ Routine Description: This routine will return the data for the XXX object Arguments: IN OUT LPVOID *lppData IN: pointer to the address of the buffer to receive the completed PerfDataBlock and subordinate structures. This routine will append its data to the buffer starting at the point referenced by *lppData. OUT: points to the first byte after the data structure added by this routine. This routine updated the value at lppdata after appending its data. IN OUT LPDWORD lpcbTotalBytes IN: the address of the DWORD that tells the size in bytes of the buffer referenced by the lppData argument OUT: the number of bytes added by this routine is writted to the DWORD pointed to by this argument IN OUT LPDWORD NumObjectTypes IN: the address of the DWORD to receive the number of objects added by this routine OUT: the number of objects added by this routine is writted to the DWORD pointed to by this argument Returns: 0 if successful, else Win 32 error code of failure --*/ { DWORD TotalLen; // Length of the total return block DWORD Changes; // Used by macros to compute cache DWORD Misses; // ...statistics PCACHE_DATA_DEFINITION pCacheDataDefinition; PCACHE_COUNTER_DATA pCCD; // // Check for enough space for cache data block // pCacheDataDefinition = (CACHE_DATA_DEFINITION *) *lppData; TotalLen = sizeof(CACHE_DATA_DEFINITION) + sizeof(CACHE_COUNTER_DATA); TotalLen = QWORD_MULTIPLE(TotalLen); if ( *lpcbTotalBytes < TotalLen ) { *lpcbTotalBytes = (DWORD) 0; *lpNumObjectTypes = (DWORD) 0; return ERROR_MORE_DATA; } // // Define cache data block // memcpy (pCacheDataDefinition, &CacheDataDefinition, sizeof(CACHE_DATA_DEFINITION)); // // Format and collect memory data // pCCD = (PCACHE_COUNTER_DATA)&pCacheDataDefinition[1]; // No need to align this since it is the only counter block // and the total byte will be aligned. pCCD->CounterBlock.ByteLength = sizeof(CACHE_COUNTER_DATA); // // The Data Map counter is the sum of the Wait/NoWait cases // pCCD->DataMaps = SYNC_ASYNC(CcMapData); pCCD->SyncDataMaps = SysPerfInfo.CcMapDataWait; pCCD->AsyncDataMaps = SysPerfInfo.CcMapDataNoWait; // // The Data Map Hits is a percentage of Data Maps that hit // the cache; second counter is the base (divisor) // pCCD->DataMapHits = SYNC_ASYNC_HITRATE(CcMapData); pCCD->DataMapHitsBase = SYNC_ASYNC(CcMapData); // // The next pair of counters forms a percentage of // Pins as a portion of Data Maps // pCCD->DataMapPins = SysPerfInfo.CcPinMappedDataCount; pCCD->DataMapPinsBase = SYNC_ASYNC(CcMapData); pCCD->PinReads = SYNC_ASYNC(CcPinRead); pCCD->SyncPinReads = SysPerfInfo.CcPinReadWait; pCCD->AsyncPinReads = SysPerfInfo.CcPinReadNoWait; // // The Pin Read Hits is a percentage of Pin Reads that hit // the cache; second counter is the base (divisor) // pCCD->PinReadHits = SYNC_ASYNC_HITRATE(CcPinRead); pCCD->PinReadHitsBase = SYNC_ASYNC(CcPinRead); pCCD->CopyReads = SYNC_ASYNC(CcCopyRead); pCCD->SyncCopyReads = SysPerfInfo.CcCopyReadWait; pCCD->AsyncCopyReads = SysPerfInfo.CcCopyReadNoWait; // // The Copy Read Hits is a percentage of Copy Reads that hit // the cache; second counter is the base (divisor) // pCCD->CopyReadHits = SYNC_ASYNC_HITRATE(CcCopyRead); pCCD->CopyReadHitsBase = SYNC_ASYNC(CcCopyRead); pCCD->MdlReads = SYNC_ASYNC(CcMdlRead); pCCD->SyncMdlReads = SysPerfInfo.CcMdlReadWait; pCCD->AsyncMdlReads = SysPerfInfo.CcMdlReadNoWait; // // The Mdl Read Hits is a percentage of Mdl Reads that hit // the cache; second counter is the base (divisor) // pCCD->MdlReadHits = SYNC_ASYNC_HITRATE(CcMdlRead); pCCD->MdlReadHitsBase = SYNC_ASYNC(CcMdlRead); pCCD->ReadAheads = SysPerfInfo.CcReadAheadIos; pCCD->FastReads = SYNC_ASYNC(CcFastRead); pCCD->SyncFastReads = SysPerfInfo.CcFastReadWait; pCCD->AsyncFastReads = SysPerfInfo.CcFastReadNoWait; pCCD->FastReadResourceMiss = SysPerfInfo.CcFastReadResourceMiss; pCCD->FastReadNotPossibles = SysPerfInfo.CcFastReadNotPossible; pCCD->LazyWriteFlushes = SysPerfInfo.CcLazyWriteIos; pCCD->LazyWritePages = SysPerfInfo.CcLazyWritePages; pCCD->DataFlushes = SysPerfInfo.CcDataFlushes; pCCD->DataPages = SysPerfInfo.CcDataPages; *lpcbTotalBytes = pCacheDataDefinition->CacheObjectType.TotalByteLength = (DWORD) QWORD_MULTIPLE(((LPBYTE) (& pCCD[1])) - (LPBYTE) pCacheDataDefinition); * lppData = (LPVOID) (((LPBYTE) pCacheDataDefinition) + * lpcbTotalBytes); assert(*lpcbTotalBytes == TotalLen); *lpNumObjectTypes = 1; return ERROR_SUCCESS; }