/*++ Copyright (C) 1999-2001 Microsoft Corporation Module Name: PERFLIBSCHEMA.CPP Abstract: implementation of the CPerfLibSchema class. History: --*/ #include "precomp.h" #include #include #include #include #include "PerfLibSchema.h" #include "AdapUtil.h" //////////////////////////////////////////////////////////////////////////////// // // CIndexTable // // This is a look aside table used for processing the perflib data blob. It // guarentees that no duplicate indicies will be allowed to be added to the // table. // //////////////////////////////////////////////////////////////////////////////// int CIndexTable::Locate( int nIndex ) { int nRet = not_found; int nSize = m_array.Size(); for ( int n = 0; ( not_found == nRet ) && ( n < nSize ); n++ ) { int* pIndex = (int*)m_array.GetAt( n ); if ( *pIndex == nIndex ) nRet = n; } return nRet; } BOOL CIndexTable::Add( int nIndex ) { BOOL bRet = FALSE; if ( not_found == Locate( nIndex ) ) { int* pIndex = new int( nIndex ); if (NULL == pIndex) return FALSE; if (CFlexArray::no_error != m_array.Add( pIndex )) return FALSE; bRet = TRUE; } return bRet; } void CIndexTable::Empty() { int nSize = m_array.Size(); for ( int nIndex = 0; nIndex < nSize; nIndex++ ) { int* pIndex = (int*)m_array.GetAt( nIndex ); delete pIndex; } m_array.Empty(); } ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CPerfLibSchema::CPerfLibSchema( WCHAR* pwcsServiceName, CLocaleCache* pLocaleCache ): m_pLocaleCache(pLocaleCache), m_dwFirstCtr(2), m_dwLastCtr(CPerfNameDb::GetSystemReservedHigh()) { if ( NULL != m_pLocaleCache ) m_pLocaleCache->AddRef(); memset( m_apClassList, NULL, WMI_ADAP_NUM_TYPES * sizeof( CPerfClassList* ) ); m_wstrServiceName = pwcsServiceName; } CPerfLibSchema::~CPerfLibSchema() { if ( NULL != m_pLocaleCache ) m_pLocaleCache->Release(); for ( DWORD dwType = 0; dwType < WMI_ADAP_NUM_TYPES; dwType++ ) { if ( NULL != m_apClassList[ dwType ] ) m_apClassList[ dwType ]->Release(); m_aIndexTable[ dwType ].Empty(); } } HRESULT CPerfLibSchema::Initialize( BOOL bDelta, DWORD * pLoadStatus) { HRESULT hr = WBEM_S_NO_ERROR; CAdapPerfLib* pPerfLib = NULL; BOOL bInactive = TRUE; try { // Create and initialize the perflib wrapper // ========================================= pPerfLib = new CAdapPerfLib( m_wstrServiceName,pLoadStatus ); CAdapReleaseMe rmPerfLib( pPerfLib ); if ( NULL != pPerfLib ) { if ( bDelta && pPerfLib->CheckStatus( ADAP_PERFLIB_PREVIOUSLY_PROCESSED ) ) { hr = WBEM_S_ALREADY_EXISTS; } else if ( pPerfLib->IsOK() ) { m_dwFirstCtr = pPerfLib->GetFirstCtr(); m_dwLastCtr = pPerfLib->GetLastCtr(); // // errors from the perflib!Open call are returned here // hr = pPerfLib->Initialize(); // Get the perflib blobs // ===================== if ( SUCCEEDED ( hr ) ) { m_aBlob[COSTLY].SetCostly( TRUE ); for ( int nBlob = GLOBAL; SUCCEEDED ( hr ) && nBlob < NUMBLOBS; nBlob ++ ) { hr = pPerfLib->GetBlob( m_aBlob[nBlob].GetPerfBlockPtrPtr(), m_aBlob[nBlob].GetSizePtr(), m_aBlob[nBlob].GetNumObjectsPtr(), m_aBlob[nBlob].GetCostly() ); if (FAILED(hr)) { ERRORTRACE((LOG_WMIADAP,"Collect for service %S for %s counters failed\n",(WCHAR *)m_wstrServiceName,m_aBlob[nBlob].GetCostly()?"Costly":"Global")); } // check the return status hr if (FAILED(hr) && (!pPerfLib->IsCollectOK()) && pLoadStatus ) { (*pLoadStatus) |= EX_STATUS_COLLECTFAIL; } // Perflib is inactive if ALL blobs are 0 length // ============================================= bInactive = bInactive && ( 0 == m_aBlob[nBlob].GetSize() ); } if ( bInactive ) { pPerfLib->SetStatus( ADAP_PERFLIB_IS_INACTIVE ); hr = WBEM_E_FAILED; ERRORTRACE((LOG_WMIADAP,"Collect for service %S returned 0-Size BLOBs\n",(WCHAR *)m_wstrServiceName)); } pPerfLib->Close(); } } else { hr = WBEM_E_FAILED; } } else { hr = WBEM_E_OUT_OF_MEMORY; } // store the final status in the registry in the EndProcessingStatus if ( NULL != pPerfLib ) { pPerfLib->Cleanup(); } } catch(...) { hr = WBEM_E_OUT_OF_MEMORY; } return hr; } HRESULT CPerfLibSchema::GetClassList( DWORD dwType, CClassList** ppClassList ) { HRESULT hr = WBEM_S_NO_ERROR; // If the class list does not already exist, then create it // ======================================================== if ( NULL == m_apClassList[ dwType ] ) { hr = CreateClassList( dwType ); } // Set pass back the pointer // ========================= if ( SUCCEEDED( hr ) ) { *ppClassList = m_apClassList[ dwType ]; if ( NULL != *ppClassList ) (*ppClassList)->AddRef(); } return hr; } HRESULT CPerfLibSchema::CreateClassList( DWORD dwType ) { HRESULT hr = WBEM_S_NO_ERROR; m_apClassList[ dwType ] = new CPerfClassList( m_pLocaleCache, m_wstrServiceName ); if ( NULL == m_apClassList[ dwType ] ) { hr = WBEM_E_OUT_OF_MEMORY; } // Cycle through all perfomance blobs (Global & Costly) // ==================================================== if ( SUCCEEDED( hr ) ) { for ( DWORD dwBlob = GLOBAL; dwBlob < NUMBLOBS; dwBlob++ ) { PERF_OBJECT_TYPE* pCurrentObject = NULL; CPerfLibBlobDefn* pBlobDefn = &m_aBlob[dwBlob]; DWORD dwNumObjects = pBlobDefn->GetNumObjects(); for ( DWORD dwCtr = 0; SUCCEEDED( hr ) && dwCtr < dwNumObjects; dwCtr++ ) { // Get the current object // ====================== if ( 0 == dwCtr ) { pCurrentObject = pBlobDefn->GetBlob(); } else { LPBYTE pbData = (LPBYTE) pCurrentObject; pbData += pCurrentObject->TotalByteLength; pCurrentObject = (PERF_OBJECT_TYPE*) pbData; } if (m_dwFirstCtr <= pCurrentObject->ObjectNameTitleIndex && pCurrentObject->ObjectNameTitleIndex <= m_dwLastCtr) { // To ensure uniqueness, we manage a list of processed indicies // ============================================================ if ( m_aIndexTable[dwType].Add( pCurrentObject->ObjectNameTitleIndex ) ) { hr = m_apClassList[dwType]->AddPerfObject( pCurrentObject, dwType, pBlobDefn->GetCostly() ); } } else { ERRORTRACE((LOG_WMIADAP,"Skipping Object of index %d of service %S " " because index does not belong to the range %d - %d " " assigned to the service by LodCtr\n", pCurrentObject->ObjectNameTitleIndex, (WCHAR *)m_wstrServiceName, m_dwFirstCtr, m_dwLastCtr)); } } } } return hr; }