Source code of Windows XP (NT5)
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

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. cntrtree.cpp
  5. Abstract:
  6. Implements internal counter management.
  7. --*/
  8. #include <assert.h>
  9. #include <stdio.h>
  10. #include "polyline.h"
  11. #include "smonmsg.h"
  12. #include "appmema.h"
  13. #include "grphitem.h"
  14. #include "cntrtree.h"
  15. CCounterTree::CCounterTree()
  16. : m_nItems (0)
  17. {
  18. }
  19. HRESULT
  20. CCounterTree::AddCounterItem(LPTSTR pszPath, PCGraphItem pItem, BOOL bMonitorDuplicateInstances)
  21. {
  22. HRESULT hr;
  23. TCHAR achInfoBuf[sizeof(PDH_COUNTER_PATH_ELEMENTS) + MAX_PATH + 5];
  24. PPDH_COUNTER_PATH_ELEMENTS pPathInfo = (PPDH_COUNTER_PATH_ELEMENTS)achInfoBuf;
  25. ULONG ulBufSize;
  26. PDH_STATUS stat;
  27. CMachineNode *pMachine;
  28. CObjectNode *pObject;
  29. CCounterNode *pCounter;
  30. CInstanceNode *pInstance;
  31. // Record whether machine is explicit or defaults to local
  32. pItem->m_fLocalMachine = !(pszPath[0] == TEXT('\\') && pszPath[1] == TEXT('\\'));
  33. // Parse pathname
  34. ulBufSize = sizeof(achInfoBuf);
  35. stat = PdhParseCounterPath(pszPath, pPathInfo, &ulBufSize, 0);
  36. if (stat != 0)
  37. return E_FAIL;
  38. /*
  39. stat = PdhValidatePath(pszPath);
  40. if (stat != 0)
  41. return E_FAIL;
  42. */
  43. // Find or create each level of hierarchy
  44. hr = GetMachine( pPathInfo->szMachineName, &pMachine);
  45. if (FAILED(hr))
  46. return hr;
  47. hr = pMachine->GetCounterObject(pPathInfo->szObjectName, &pObject);
  48. if (FAILED(hr))
  49. return hr;
  50. hr = pObject->GetCounter(pPathInfo->szCounterName, &pCounter);
  51. if (FAILED(hr))
  52. return hr;
  53. hr = pObject->GetInstance(
  54. pPathInfo->szParentInstance,
  55. pPathInfo->szInstanceName,
  56. pPathInfo->dwInstanceIndex,
  57. bMonitorDuplicateInstances,
  58. &pInstance);
  59. if (FAILED(hr))
  60. return hr;
  61. hr = pInstance->AddItem(pCounter, pItem);
  62. if (SUCCEEDED(hr)) {
  63. m_nItems++;
  64. UpdateAppPerfDwordData (DD_ITEM_COUNT, m_nItems);
  65. }
  66. return hr;
  67. }
  68. HRESULT
  69. CCounterTree::GetMachine (
  70. IN LPTSTR pszName,
  71. OUT PCMachineNode *ppMachineRet
  72. )
  73. {
  74. PCMachineNode pMachine;
  75. PCMachineNode pMachineNew;
  76. if (m_listMachines.FindByName(pszName, FIELD_OFFSET(CMachineNode, m_szName), (PCNamedNode*)&pMachine)) {
  77. *ppMachineRet = pMachine;
  78. return NOERROR;
  79. }
  80. pMachineNew = new(lstrlen(pszName) * sizeof(TCHAR)) CMachineNode;
  81. if (!pMachineNew)
  82. return E_OUTOFMEMORY;
  83. pMachineNew->m_pCounterTree = this;
  84. lstrcpy(pMachineNew->m_szName, pszName);
  85. m_listMachines.Add(pMachineNew, pMachine);
  86. *ppMachineRet = pMachineNew;
  87. return NOERROR;
  88. }
  89. void
  90. CCounterTree::RemoveMachine (
  91. IN PCMachineNode pMachine
  92. )
  93. {
  94. // Remove machine from list and delete it
  95. m_listMachines.Remove(pMachine);
  96. delete pMachine ;
  97. }
  98. PCGraphItem
  99. CCounterTree::FirstCounter (
  100. void
  101. )
  102. {
  103. if (!FirstMachine())
  104. return NULL;
  105. else
  106. return FirstMachine()->FirstObject()->FirstInstance()->FirstItem();
  107. }
  108. HRESULT
  109. CMachineNode::GetCounterObject (
  110. IN LPTSTR pszName,
  111. OUT PCObjectNode *ppObjectRet
  112. )
  113. {
  114. PCObjectNode pObject;
  115. PCObjectNode pObjectNew;
  116. if (m_listObjects.FindByName(pszName, FIELD_OFFSET(CObjectNode, m_szName), (PCNamedNode*)&pObject)) {
  117. *ppObjectRet = pObject;
  118. return NOERROR;
  119. }
  120. pObjectNew = new(lstrlen(pszName) * sizeof(TCHAR)) CObjectNode;
  121. if (!pObjectNew)
  122. return E_OUTOFMEMORY;
  123. pObjectNew->m_pMachine = this;
  124. lstrcpy(pObjectNew->m_szName, pszName);
  125. m_listObjects.Add(pObjectNew, pObject);
  126. *ppObjectRet = pObjectNew;
  127. return NOERROR;
  128. }
  129. void
  130. CMachineNode::RemoveObject (
  131. IN PCObjectNode pObject
  132. )
  133. {
  134. // Remove object from list and delete it
  135. m_listObjects.Remove(pObject);
  136. delete pObject;
  137. // If this was the last one, remove ourself
  138. if (m_listObjects.IsEmpty())
  139. m_pCounterTree->RemoveMachine(this);
  140. }
  141. void
  142. CMachineNode::DeleteNode (
  143. BOOL bPropagateUp
  144. )
  145. {
  146. PCObjectNode pObject;
  147. PCObjectNode pNextObject;
  148. // Delete all object nodes
  149. pObject = FirstObject();
  150. while ( NULL != pObject ) {
  151. pNextObject = pObject->Next();
  152. pObject->DeleteNode(FALSE);
  153. m_listObjects.Remove(pObject);
  154. delete pObject;
  155. pObject = pNextObject;
  156. }
  157. assert(m_listObjects.IsEmpty());
  158. // Notify parent if requested
  159. if (bPropagateUp) {
  160. m_pCounterTree->RemoveMachine(this);
  161. }
  162. }
  163. HRESULT
  164. CObjectNode::GetCounter (
  165. IN LPTSTR pszName,
  166. OUT PCCounterNode *ppCounterRet
  167. )
  168. {
  169. PCCounterNode pCounter;
  170. PCCounterNode pCounterNew;
  171. if (m_listCounters.FindByName(pszName, FIELD_OFFSET(CCounterNode, m_szName), (PCNamedNode*)&pCounter)) {
  172. *ppCounterRet = pCounter;
  173. return NOERROR;
  174. }
  175. pCounterNew = new(lstrlen(pszName) * sizeof(TCHAR)) CCounterNode;
  176. if (!pCounterNew)
  177. return E_OUTOFMEMORY;
  178. pCounterNew->m_pObject = this;
  179. lstrcpy(pCounterNew->m_szName, pszName);
  180. m_listCounters.Add(pCounterNew, pCounter);
  181. *ppCounterRet = pCounterNew;
  182. return NOERROR;
  183. }
  184. HRESULT
  185. CObjectNode::GetInstance (
  186. IN LPTSTR pszParent,
  187. IN LPTSTR pszInstance,
  188. IN DWORD dwIndex,
  189. IN BOOL bMonitorDuplicateInstances,
  190. OUT PCInstanceNode *ppInstanceRet
  191. )
  192. {
  193. PCInstanceNode pInstance;
  194. PCInstanceNode pInstanceNew;
  195. INT nParentLen = 0;
  196. TCHAR achInstName[MAX_PATH];
  197. if (pszInstance) {
  198. if (pszParent) {
  199. nParentLen = lstrlen(pszParent);
  200. lstrcpy(achInstName, pszParent);
  201. achInstName[nParentLen] = TEXT('/');
  202. lstrcpy(&achInstName[nParentLen+1], pszInstance);
  203. }
  204. else {
  205. lstrcpy(achInstName, pszInstance);
  206. }
  207. // "#n" is only appended to the stored name if the index is > 0.
  208. if ( dwIndex > 0 && bMonitorDuplicateInstances ) {
  209. _stprintf(&achInstName[lstrlen(achInstName)], TEXT("#%d"), dwIndex);
  210. }
  211. } else {
  212. achInstName[0] = 0;
  213. }
  214. if (m_listInstances.FindByName(achInstName, FIELD_OFFSET(CInstanceNode, m_szName), (PCNamedNode*)&pInstance)) {
  215. *ppInstanceRet = pInstance;
  216. return NOERROR;
  217. }
  218. pInstanceNew = new(lstrlen(achInstName) * sizeof(TCHAR)) CInstanceNode;
  219. if (!pInstanceNew)
  220. return E_OUTOFMEMORY;
  221. pInstanceNew->m_pObject = this;
  222. pInstanceNew->m_nParentLen = nParentLen;
  223. lstrcpy(pInstanceNew->m_szName, achInstName);
  224. m_listInstances.Add(pInstanceNew, pInstance);
  225. *ppInstanceRet = pInstanceNew;
  226. return NOERROR;
  227. }
  228. void
  229. CObjectNode::RemoveInstance (
  230. IN PCInstanceNode pInstance
  231. )
  232. {
  233. // Remove instance from list and delete it
  234. m_listInstances.Remove(pInstance);
  235. delete pInstance ;
  236. // if that was the last instance, remove ourself
  237. if (m_listInstances.IsEmpty())
  238. m_pMachine->RemoveObject(this);
  239. }
  240. void
  241. CObjectNode::RemoveCounter (
  242. IN PCCounterNode pCounter
  243. )
  244. {
  245. // Remove counter from list and delete it
  246. m_listCounters.Remove(pCounter);
  247. delete pCounter;
  248. // Don't propagate removal up to object.
  249. // It will go away when the last instance is removed.
  250. }
  251. void
  252. CObjectNode::DeleteNode (
  253. BOOL bPropagateUp
  254. )
  255. {
  256. PCInstanceNode pInstance;
  257. PCInstanceNode pNextInstance;
  258. // Delete all instance nodes
  259. pInstance = FirstInstance();
  260. while ( NULL != pInstance ) {
  261. pNextInstance = pInstance->Next();
  262. pInstance->DeleteNode(FALSE);
  263. m_listInstances.Remove(pInstance);
  264. delete pInstance;
  265. pInstance = pNextInstance;
  266. }
  267. // No need to delete counters nodes as they get
  268. // deleted as their last paired instance does
  269. // Notify parent if requested
  270. if (bPropagateUp)
  271. m_pMachine->RemoveObject(this);
  272. }
  273. HRESULT
  274. CInstanceNode::AddItem (
  275. IN PCCounterNode pCounter,
  276. IN PCGraphItem pItemNew
  277. )
  278. {
  279. PCGraphItem pItemPrev = NULL;
  280. PCGraphItem pItem = m_pItems;
  281. INT iStat = 1;
  282. // Check for existing item for specified counter, stopping at insertion point
  283. while ( pItem != NULL && (iStat = lstrcmp(pCounter->Name(), pItem->m_pCounter->Name())) > 0) {
  284. pItemPrev = pItem;
  285. pItem = pItem->m_pNextItem;
  286. }
  287. // if item exists, return duplicate error status
  288. if (iStat == 0) {
  289. return SMON_STATUS_DUPL_COUNTER_PATH;
  290. }
  291. // else insert the new item
  292. else {
  293. if (pItemPrev != NULL) {
  294. pItemNew->m_pNextItem = pItemPrev->m_pNextItem;
  295. pItemPrev->m_pNextItem = pItemNew;
  296. }
  297. else if (m_pItems != NULL) {
  298. pItemNew->m_pNextItem = m_pItems;
  299. m_pItems = pItemNew;
  300. }
  301. else {
  302. m_pItems = pItemNew;
  303. }
  304. }
  305. // Set back links
  306. pItemNew->m_pInstance = this;
  307. pItemNew->m_pCounter = pCounter;
  308. pCounter->AddItem(pItem);
  309. return NOERROR;
  310. }
  311. void
  312. CInstanceNode::RemoveItem (
  313. IN PCGraphItem pitem
  314. )
  315. {
  316. PCGraphItem pitemPrev = NULL;
  317. PCGraphItem pitemTemp = m_pItems;
  318. // Locate item in list
  319. while (pitemTemp != NULL && pitemTemp != pitem) {
  320. pitemPrev = pitemTemp;
  321. pitemTemp = pitemTemp->m_pNextItem;
  322. }
  323. if (pitemTemp == NULL)
  324. return;
  325. // Remove from list
  326. if (pitemPrev)
  327. pitemPrev->m_pNextItem = pitem->m_pNextItem;
  328. else
  329. m_pItems = pitem->m_pNextItem;
  330. // Remove item from Counter set
  331. pitem->Counter()->RemoveItem(pitem);
  332. // Decrement the total item count
  333. pitem->Tree()->m_nItems--;
  334. UpdateAppPerfDwordData (DD_ITEM_COUNT, pitem->Tree()->m_nItems);
  335. // Release the item
  336. pitem->Release();
  337. // if last item under this instance, remove the instance
  338. if (m_pItems == NULL)
  339. m_pObject->RemoveInstance(this);
  340. }
  341. void
  342. CInstanceNode::DeleteNode (
  343. BOOL bPropagateUp
  344. )
  345. {
  346. PCGraphItem pItem;
  347. pItem = m_pItems;
  348. while ( NULL != pItem ) {
  349. m_pItems = pItem->m_pNextItem;
  350. pItem->Delete(FALSE);
  351. pItem->Counter()->RemoveItem(pItem);
  352. pItem->Release();
  353. pItem = m_pItems;
  354. }
  355. if (bPropagateUp)
  356. m_pObject->RemoveInstance(this);
  357. }
  358. INT
  359. CInstanceNode::GetParentName (
  360. LPTSTR pszName
  361. )
  362. {
  363. if (m_nParentLen)
  364. lstrcpyn(pszName, m_szName, m_nParentLen + 1);
  365. else
  366. pszName[0] = 0;
  367. return m_nParentLen;
  368. }
  369. INT
  370. CInstanceNode::GetInstanceName (
  371. LPTSTR pszName
  372. )
  373. {
  374. LPTSTR pszInst = m_nParentLen ? (m_szName + m_nParentLen + 1) : m_szName;
  375. lstrcpy(pszName, pszInst);
  376. return lstrlen(pszInst);
  377. }
  378. void
  379. CCounterNode::DeleteNode (
  380. BOOL bPropagateUp
  381. )
  382. {
  383. PCInstanceNode pInstance, pInstNext;
  384. PCGraphItem pItem, pItemNext;
  385. if (!bPropagateUp)
  386. return;
  387. // We have to delete the counters item via the instances
  388. // because they maintain the linked list of items
  389. pInstance = m_pObject->FirstInstance();
  390. while (pInstance) {
  391. pInstNext = pInstance->Next();
  392. pItem = pInstance->FirstItem();
  393. while (pItem) {
  394. if (pItem->Counter() == this) {
  395. // Delete all UI associated with the item
  396. pItem->Delete(FALSE);
  397. pItemNext = pItem->m_pNextItem;
  398. // Note that Instance->RemoveItem() will
  399. // also remove counters that have no more items
  400. pItem->Instance()->RemoveItem(pItem);
  401. pItem = pItemNext;
  402. }
  403. else {
  404. pItem = pItem->m_pNextItem;
  405. }
  406. }
  407. pInstance = pInstNext;
  408. }
  409. }
  410. /*******************************
  411. CCounterNode::~CCounterNode (
  412. IN PCGraphItem pItem
  413. )
  414. {
  415. PCGraphItem pItemPrev = NULL;
  416. PCGraphItem pItemFind = m_pItems;
  417. // Find item in list
  418. while (pItemFind != NULL && pItemFind != pItem) {
  419. pItemPrev = pItem;
  420. pItem = pItem->m_pNextItem;
  421. }
  422. if (pItemFind != pItem)
  423. return E_FAIL;
  424. // Unlink from counter item list
  425. if (pItemPrev)
  426. pItemPrev->m_pNextItem = pItem->m_pNextItem;
  427. else
  428. m_pItems = pItem->m_pNextItem;
  429. // Unlink from instance
  430. pItem->m_pInstance->RemoveCounter(pItem);
  431. // if no more items, remove self from parnet object
  432. if (m_pItems == NULL) {
  433. m_pObject->RemoveCounter(this);
  434. return NOERROR;
  435. }
  436. *******************************/
  437. /*
  438. void*
  439. CMachineNode::operator new( size_t stBlock, LPTSTR pszName )
  440. { return malloc(stBlock + lstrlen(pszName) * sizeof(TCHAR)); }
  441. void
  442. CMachineNode::operator delete ( void * pObject, LPTSTR )
  443. { free(pObject); }
  444. void*
  445. CObjectNode::operator new( size_t stBlock, LPTSTR pszName )
  446. { return malloc(stBlock + lstrlen(pszName) * sizeof(TCHAR)); }
  447. void
  448. CObjectNode::operator delete ( void * pObject, LPTSTR )
  449. { free(pObject); }
  450. void*
  451. CInstanceNode::operator new( size_t stBlock, LPTSTR pszName )
  452. { return malloc(stBlock + lstrlen(pszName) * sizeof(TCHAR)); }
  453. void
  454. CInstanceNode::operator delete ( void * pObject, LPTSTR )
  455. { free(pObject); }
  456. void*
  457. CCounterNode::operator new( size_t stBlock, LPTSTR pszName )
  458. { return malloc(stBlock + lstrlen(pszName) * sizeof(TCHAR)); }
  459. void
  460. CCounterNode::operator delete ( void * pObject, LPTSTR )
  461. { free(pObject); }CMachineNode::operator new( size_t stBlock, INT iLength )
  462. */
  463. void *
  464. CMachineNode::operator new( size_t stBlock, UINT iLength )
  465. { return malloc(stBlock + iLength); }
  466. void
  467. CMachineNode::operator delete ( void * pObject, UINT )
  468. { free(pObject); }
  469. void*
  470. CObjectNode::operator new( size_t stBlock, UINT iLength )
  471. { return malloc(stBlock + iLength); }
  472. void
  473. CObjectNode::operator delete ( void * pObject, UINT )
  474. { free(pObject); }
  475. void*
  476. CInstanceNode::operator new( size_t stBlock, UINT iLength )
  477. { return malloc(stBlock + iLength); }
  478. void
  479. CInstanceNode::operator delete ( void * pObject, UINT )
  480. { free(pObject); }
  481. void*
  482. CCounterNode::operator new( size_t stBlock, UINT iLength )
  483. { return malloc(stBlock + iLength); }
  484. void
  485. CCounterNode::operator delete ( void * pObject, UINT )
  486. { free(pObject); }
  487. #if _MSC_VER >= 1300
  488. void
  489. CMachineNode::operator delete ( void * pObject )
  490. { free(pObject); }
  491. void
  492. CObjectNode::operator delete ( void * pObject )
  493. { free(pObject); }
  494. void
  495. CInstanceNode::operator delete ( void * pObject )
  496. { free(pObject); }
  497. void
  498. CCounterNode::operator delete ( void * pObject )
  499. { free(pObject); }
  500. #endif