windows-nt/Source/XPSP1/NT/admin/controls/smonctrl/cntrtree.cpp

648 lines
14 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (C) 1996-1999 Microsoft Corporation
Module Name:
cntrtree.cpp
Abstract:
Implements internal counter management.
--*/
#include <assert.h>
#include <stdio.h>
#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