/*++ Copyright (C) 1996-1999 Microsoft Corporation Module Name: cntrtree.cpp Abstract: Implements internal counter management. --*/ #include #include #include "polyline.h" #include "smonmsg.h" #include "appmema.h" #include "grphitem.h" #include "cntrtree.h" CCounterTree::CCounterTree() : m_nItems (0) { } HRESULT CCounterTree::AddCounterItem(LPTSTR pszPath, PCGraphItem pItem, BOOL bMonitorDuplicateInstances) { HRESULT hr; TCHAR achInfoBuf[sizeof(PDH_COUNTER_PATH_ELEMENTS) + MAX_PATH + 5]; PPDH_COUNTER_PATH_ELEMENTS pPathInfo = (PPDH_COUNTER_PATH_ELEMENTS)achInfoBuf; ULONG ulBufSize; PDH_STATUS stat; CMachineNode *pMachine; CObjectNode *pObject; CCounterNode *pCounter; CInstanceNode *pInstance; // Record whether machine is explicit or defaults to local pItem->m_fLocalMachine = !(pszPath[0] == TEXT('\\') && pszPath[1] == TEXT('\\')); // Parse pathname ulBufSize = sizeof(achInfoBuf); stat = PdhParseCounterPath(pszPath, pPathInfo, &ulBufSize, 0); if (stat != 0) return E_FAIL; /* stat = PdhValidatePath(pszPath); if (stat != 0) return E_FAIL; */ // Find or create each level of hierarchy hr = GetMachine( pPathInfo->szMachineName, &pMachine); if (FAILED(hr)) return hr; hr = pMachine->GetCounterObject(pPathInfo->szObjectName, &pObject); if (FAILED(hr)) return hr; hr = pObject->GetCounter(pPathInfo->szCounterName, &pCounter); if (FAILED(hr)) return hr; hr = pObject->GetInstance( pPathInfo->szParentInstance, pPathInfo->szInstanceName, pPathInfo->dwInstanceIndex, bMonitorDuplicateInstances, &pInstance); if (FAILED(hr)) return hr; hr = pInstance->AddItem(pCounter, pItem); if (SUCCEEDED(hr)) { m_nItems++; UpdateAppPerfDwordData (DD_ITEM_COUNT, m_nItems); } return hr; } HRESULT CCounterTree::GetMachine ( IN LPTSTR pszName, OUT PCMachineNode *ppMachineRet ) { PCMachineNode pMachine; PCMachineNode pMachineNew; if (m_listMachines.FindByName(pszName, FIELD_OFFSET(CMachineNode, m_szName), (PCNamedNode*)&pMachine)) { *ppMachineRet = pMachine; return NOERROR; } pMachineNew = new(lstrlen(pszName) * sizeof(TCHAR)) CMachineNode; if (!pMachineNew) return E_OUTOFMEMORY; pMachineNew->m_pCounterTree = this; lstrcpy(pMachineNew->m_szName, pszName); m_listMachines.Add(pMachineNew, pMachine); *ppMachineRet = pMachineNew; return NOERROR; } void CCounterTree::RemoveMachine ( IN PCMachineNode pMachine ) { // Remove machine from list and delete it m_listMachines.Remove(pMachine); delete pMachine ; } PCGraphItem CCounterTree::FirstCounter ( void ) { if (!FirstMachine()) return NULL; else return FirstMachine()->FirstObject()->FirstInstance()->FirstItem(); } HRESULT CMachineNode::GetCounterObject ( IN LPTSTR pszName, OUT PCObjectNode *ppObjectRet ) { PCObjectNode pObject; PCObjectNode pObjectNew; if (m_listObjects.FindByName(pszName, FIELD_OFFSET(CObjectNode, m_szName), (PCNamedNode*)&pObject)) { *ppObjectRet = pObject; return NOERROR; } pObjectNew = new(lstrlen(pszName) * sizeof(TCHAR)) CObjectNode; if (!pObjectNew) return E_OUTOFMEMORY; pObjectNew->m_pMachine = this; lstrcpy(pObjectNew->m_szName, pszName); m_listObjects.Add(pObjectNew, pObject); *ppObjectRet = pObjectNew; return NOERROR; } void CMachineNode::RemoveObject ( IN PCObjectNode pObject ) { // Remove object from list and delete it m_listObjects.Remove(pObject); delete pObject; // If this was the last one, remove ourself if (m_listObjects.IsEmpty()) m_pCounterTree->RemoveMachine(this); } void CMachineNode::DeleteNode ( BOOL bPropagateUp ) { PCObjectNode pObject; PCObjectNode pNextObject; // Delete all object nodes pObject = FirstObject(); while ( NULL != pObject ) { pNextObject = pObject->Next(); pObject->DeleteNode(FALSE); m_listObjects.Remove(pObject); delete pObject; pObject = pNextObject; } assert(m_listObjects.IsEmpty()); // Notify parent if requested if (bPropagateUp) { m_pCounterTree->RemoveMachine(this); } } HRESULT CObjectNode::GetCounter ( IN LPTSTR pszName, OUT PCCounterNode *ppCounterRet ) { PCCounterNode pCounter; PCCounterNode pCounterNew; if (m_listCounters.FindByName(pszName, FIELD_OFFSET(CCounterNode, m_szName), (PCNamedNode*)&pCounter)) { *ppCounterRet = pCounter; return NOERROR; } pCounterNew = new(lstrlen(pszName) * sizeof(TCHAR)) CCounterNode; if (!pCounterNew) return E_OUTOFMEMORY; pCounterNew->m_pObject = this; lstrcpy(pCounterNew->m_szName, pszName); m_listCounters.Add(pCounterNew, pCounter); *ppCounterRet = pCounterNew; return NOERROR; } HRESULT CObjectNode::GetInstance ( IN LPTSTR pszParent, IN LPTSTR pszInstance, IN DWORD dwIndex, IN BOOL bMonitorDuplicateInstances, OUT PCInstanceNode *ppInstanceRet ) { PCInstanceNode pInstance; PCInstanceNode pInstanceNew; INT nParentLen = 0; TCHAR achInstName[MAX_PATH]; if (pszInstance) { if (pszParent) { nParentLen = lstrlen(pszParent); lstrcpy(achInstName, pszParent); achInstName[nParentLen] = TEXT('/'); lstrcpy(&achInstName[nParentLen+1], pszInstance); } else { lstrcpy(achInstName, pszInstance); } // "#n" is only appended to the stored name if the index is > 0. if ( dwIndex > 0 && bMonitorDuplicateInstances ) { _stprintf(&achInstName[lstrlen(achInstName)], TEXT("#%d"), dwIndex); } } else { achInstName[0] = 0; } if (m_listInstances.FindByName(achInstName, FIELD_OFFSET(CInstanceNode, m_szName), (PCNamedNode*)&pInstance)) { *ppInstanceRet = pInstance; return NOERROR; } pInstanceNew = new(lstrlen(achInstName) * sizeof(TCHAR)) CInstanceNode; if (!pInstanceNew) return E_OUTOFMEMORY; pInstanceNew->m_pObject = this; pInstanceNew->m_nParentLen = nParentLen; lstrcpy(pInstanceNew->m_szName, achInstName); m_listInstances.Add(pInstanceNew, pInstance); *ppInstanceRet = pInstanceNew; return NOERROR; } void CObjectNode::RemoveInstance ( IN PCInstanceNode pInstance ) { // Remove instance from list and delete it m_listInstances.Remove(pInstance); delete pInstance ; // if that was the last instance, remove ourself if (m_listInstances.IsEmpty()) m_pMachine->RemoveObject(this); } void CObjectNode::RemoveCounter ( IN PCCounterNode pCounter ) { // Remove counter from list and delete it m_listCounters.Remove(pCounter); delete pCounter; // Don't propagate removal up to object. // It will go away when the last instance is removed. } void CObjectNode::DeleteNode ( BOOL bPropagateUp ) { PCInstanceNode pInstance; PCInstanceNode pNextInstance; // Delete all instance nodes pInstance = FirstInstance(); while ( NULL != pInstance ) { pNextInstance = pInstance->Next(); pInstance->DeleteNode(FALSE); m_listInstances.Remove(pInstance); delete pInstance; pInstance = pNextInstance; } // No need to delete counters nodes as they get // deleted as their last paired instance does // Notify parent if requested if (bPropagateUp) m_pMachine->RemoveObject(this); } HRESULT CInstanceNode::AddItem ( IN PCCounterNode pCounter, IN PCGraphItem pItemNew ) { PCGraphItem pItemPrev = NULL; PCGraphItem pItem = m_pItems; INT iStat = 1; // Check for existing item for specified counter, stopping at insertion point while ( pItem != NULL && (iStat = lstrcmp(pCounter->Name(), pItem->m_pCounter->Name())) > 0) { pItemPrev = pItem; pItem = pItem->m_pNextItem; } // if item exists, return duplicate error status if (iStat == 0) { return SMON_STATUS_DUPL_COUNTER_PATH; } // else insert the new item else { if (pItemPrev != NULL) { pItemNew->m_pNextItem = pItemPrev->m_pNextItem; pItemPrev->m_pNextItem = pItemNew; } else if (m_pItems != NULL) { pItemNew->m_pNextItem = m_pItems; m_pItems = pItemNew; } else { m_pItems = pItemNew; } } // Set back links pItemNew->m_pInstance = this; pItemNew->m_pCounter = pCounter; pCounter->AddItem(pItem); return NOERROR; } void CInstanceNode::RemoveItem ( IN PCGraphItem pitem ) { PCGraphItem pitemPrev = NULL; PCGraphItem pitemTemp = m_pItems; // Locate item in list while (pitemTemp != NULL && pitemTemp != pitem) { pitemPrev = pitemTemp; pitemTemp = pitemTemp->m_pNextItem; } if (pitemTemp == NULL) return; // Remove from list if (pitemPrev) pitemPrev->m_pNextItem = pitem->m_pNextItem; else m_pItems = pitem->m_pNextItem; // Remove item from Counter set pitem->Counter()->RemoveItem(pitem); // Decrement the total item count pitem->Tree()->m_nItems--; UpdateAppPerfDwordData (DD_ITEM_COUNT, pitem->Tree()->m_nItems); // Release the item pitem->Release(); // if last item under this instance, remove the instance if (m_pItems == NULL) m_pObject->RemoveInstance(this); } void CInstanceNode::DeleteNode ( BOOL bPropagateUp ) { PCGraphItem pItem; pItem = m_pItems; while ( NULL != pItem ) { m_pItems = pItem->m_pNextItem; pItem->Delete(FALSE); pItem->Counter()->RemoveItem(pItem); pItem->Release(); pItem = m_pItems; } if (bPropagateUp) m_pObject->RemoveInstance(this); } INT CInstanceNode::GetParentName ( LPTSTR pszName ) { if (m_nParentLen) lstrcpyn(pszName, m_szName, m_nParentLen + 1); else pszName[0] = 0; return m_nParentLen; } INT CInstanceNode::GetInstanceName ( LPTSTR pszName ) { LPTSTR pszInst = m_nParentLen ? (m_szName + m_nParentLen + 1) : m_szName; lstrcpy(pszName, pszInst); return lstrlen(pszInst); } void CCounterNode::DeleteNode ( BOOL bPropagateUp ) { PCInstanceNode pInstance, pInstNext; PCGraphItem pItem, pItemNext; if (!bPropagateUp) return; // We have to delete the counters item via the instances // because they maintain the linked list of items pInstance = m_pObject->FirstInstance(); while (pInstance) { pInstNext = pInstance->Next(); pItem = pInstance->FirstItem(); while (pItem) { if (pItem->Counter() == this) { // Delete all UI associated with the item pItem->Delete(FALSE); pItemNext = pItem->m_pNextItem; // Note that Instance->RemoveItem() will // also remove counters that have no more items pItem->Instance()->RemoveItem(pItem); pItem = pItemNext; } else { pItem = pItem->m_pNextItem; } } pInstance = pInstNext; } } /******************************* CCounterNode::~CCounterNode ( IN PCGraphItem pItem ) { PCGraphItem pItemPrev = NULL; PCGraphItem pItemFind = m_pItems; // Find item in list while (pItemFind != NULL && pItemFind != pItem) { pItemPrev = pItem; pItem = pItem->m_pNextItem; } if (pItemFind != pItem) return E_FAIL; // Unlink from counter item list if (pItemPrev) pItemPrev->m_pNextItem = pItem->m_pNextItem; else m_pItems = pItem->m_pNextItem; // Unlink from instance pItem->m_pInstance->RemoveCounter(pItem); // if no more items, remove self from parnet object if (m_pItems == NULL) { m_pObject->RemoveCounter(this); return NOERROR; } *******************************/ /* void* CMachineNode::operator new( size_t stBlock, LPTSTR pszName ) { return malloc(stBlock + lstrlen(pszName) * sizeof(TCHAR)); } void CMachineNode::operator delete ( void * pObject, LPTSTR ) { free(pObject); } void* CObjectNode::operator new( size_t stBlock, LPTSTR pszName ) { return malloc(stBlock + lstrlen(pszName) * sizeof(TCHAR)); } void CObjectNode::operator delete ( void * pObject, LPTSTR ) { free(pObject); } void* CInstanceNode::operator new( size_t stBlock, LPTSTR pszName ) { return malloc(stBlock + lstrlen(pszName) * sizeof(TCHAR)); } void CInstanceNode::operator delete ( void * pObject, LPTSTR ) { free(pObject); } void* CCounterNode::operator new( size_t stBlock, LPTSTR pszName ) { return malloc(stBlock + lstrlen(pszName) * sizeof(TCHAR)); } void CCounterNode::operator delete ( void * pObject, LPTSTR ) { free(pObject); }CMachineNode::operator new( size_t stBlock, INT iLength ) */ void * CMachineNode::operator new( size_t stBlock, UINT iLength ) { return malloc(stBlock + iLength); } void CMachineNode::operator delete ( void * pObject, UINT ) { free(pObject); } void* CObjectNode::operator new( size_t stBlock, UINT iLength ) { return malloc(stBlock + iLength); } void CObjectNode::operator delete ( void * pObject, UINT ) { free(pObject); } void* CInstanceNode::operator new( size_t stBlock, UINT iLength ) { return malloc(stBlock + iLength); } void CInstanceNode::operator delete ( void * pObject, UINT ) { free(pObject); } void* CCounterNode::operator new( size_t stBlock, UINT iLength ) { return malloc(stBlock + iLength); } void CCounterNode::operator delete ( void * pObject, UINT ) { free(pObject); } #if _MSC_VER >= 1300 void CMachineNode::operator delete ( void * pObject ) { free(pObject); } void CObjectNode::operator delete ( void * pObject ) { free(pObject); } void CInstanceNode::operator delete ( void * pObject ) { free(pObject); } void CCounterNode::operator delete ( void * pObject ) { free(pObject); } #endif