mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
647 lines
14 KiB
647 lines
14 KiB
/*++
|
|
|
|
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
|
|
|
|
|