43aa9b4ecca13d1a042c9cc7a841e063e2e8bd7a
[public/netxms.git] / src / server / core / template.cpp
1 /* $Id: template.cpp,v 1.40 2008-01-29 21:12:51 victor Exp $ */
2 /*
3 ** NetXMS - Network Management System
4 ** Copyright (C) 2003, 2004, 2005, 2006, 2007 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: template.cpp
21 **
22 **/
23
24 #include "nxcore.h"
25
26
27 //
28 // Template object constructor
29 //
30
31 Template::Template()
32 :NetObj()
33 {
34 m_dwNumItems = 0;
35 m_ppItems = NULL;
36 m_dwDCILockStatus = INVALID_INDEX;
37 m_dwVersion = 0x00010000; // Initial version is 1.0
38 }
39
40
41 //
42 // Constructor for new template object
43 //
44
45 Template::Template(const TCHAR *pszName)
46 :NetObj()
47 {
48 nx_strncpy(m_szName, pszName, MAX_OBJECT_NAME);
49 m_dwNumItems = 0;
50 m_ppItems = NULL;
51 m_dwDCILockStatus = INVALID_INDEX;
52 m_dwVersion = 0x00010000; // Initial version is 1.0
53 m_bIsHidden = TRUE;
54 }
55
56
57 //
58 // Destructor
59 //
60
61 Template::~Template()
62 {
63 DestroyItems();
64 }
65
66
67 //
68 // Destroy all related data collection items
69 //
70
71 void Template::DestroyItems(void)
72 {
73 DWORD i;
74
75 for(i = 0; i < m_dwNumItems; i++)
76 delete m_ppItems[i];
77 safe_free(m_ppItems);
78 m_dwNumItems = 0;
79 m_ppItems = NULL;
80 }
81
82
83 //
84 // Create object from database data
85 //
86
87 BOOL Template::CreateFromDB(DWORD dwId)
88 {
89 TCHAR szQuery[256];
90 DB_RESULT hResult;
91 DWORD i, dwNumNodes, dwNodeId;
92 NetObj *pObject;
93 BOOL bResult = TRUE;
94
95 m_dwId = dwId;
96
97 if (!LoadCommonProperties())
98 return FALSE;
99
100 _stprintf(szQuery, _T("SELECT version FROM templates WHERE id=%d"), dwId);
101 hResult = DBSelect(g_hCoreDB, szQuery);
102 if (hResult == NULL)
103 return FALSE; // Query failed
104
105 if (DBGetNumRows(hResult) == 0)
106 {
107 // No object with given ID in database
108 DBFreeResult(hResult);
109 return FALSE;
110 }
111
112 m_dwVersion = DBGetFieldULong(hResult, 0, 0);
113 DBFreeResult(hResult);
114
115 // Load DCI and access list
116 LoadACLFromDB();
117 LoadItemsFromDB();
118 for(i = 0; i < (int)m_dwNumItems; i++)
119 if (!m_ppItems[i]->LoadThresholdsFromDB())
120 bResult = FALSE;
121
122 // Load related nodes list
123 if (!m_bIsDeleted)
124 {
125 _stprintf(szQuery, _T("SELECT node_id FROM dct_node_map WHERE template_id=%d"), m_dwId);
126 hResult = DBSelect(g_hCoreDB, szQuery);
127 if (hResult != NULL)
128 {
129 dwNumNodes = DBGetNumRows(hResult);
130 for(i = 0; i < dwNumNodes; i++)
131 {
132 dwNodeId = DBGetFieldULong(hResult, i, 0);
133 pObject = FindObjectById(dwNodeId);
134 if (pObject != NULL)
135 {
136 if (pObject->Type() == OBJECT_NODE)
137 {
138 AddChild(pObject);
139 pObject->AddParent(this);
140 }
141 else
142 {
143 WriteLog(MSG_DCT_MAP_NOT_NODE, EVENTLOG_ERROR_TYPE, "dd", m_dwId, dwNodeId);
144 }
145 }
146 else
147 {
148 WriteLog(MSG_INVALID_DCT_MAP, EVENTLOG_ERROR_TYPE, "dd", m_dwId, dwNodeId);
149 }
150 }
151 DBFreeResult(hResult);
152 }
153 }
154
155 return bResult;
156 }
157
158
159 //
160 // Save object to database
161 //
162
163 BOOL Template::SaveToDB(DB_HANDLE hdb)
164 {
165 TCHAR szQuery[1024];
166 DB_RESULT hResult;
167 DWORD i;
168 BOOL bNewObject = TRUE;
169
170 // Lock object's access
171 LockData();
172
173 SaveCommonProperties(hdb);
174
175 // Check for object's existence in database
176 _stprintf(szQuery, _T("SELECT id FROM templates WHERE id=%d"), m_dwId);
177 hResult = DBSelect(hdb, szQuery);
178 if (hResult != 0)
179 {
180 if (DBGetNumRows(hResult) > 0)
181 bNewObject = FALSE;
182 DBFreeResult(hResult);
183 }
184
185 // Form and execute INSERT or UPDATE query
186 if (bNewObject)
187 sprintf(szQuery, "INSERT INTO templates (id,version) VALUES (%d,%d)",
188 m_dwId, m_dwVersion);
189 else
190 sprintf(szQuery, "UPDATE templates SET version=%d WHERE id=%d",
191 m_dwVersion, m_dwId);
192 DBQuery(hdb, szQuery);
193
194 // Update members list
195 sprintf(szQuery, "DELETE FROM dct_node_map WHERE template_id=%d", m_dwId);
196 DBQuery(hdb, szQuery);
197 LockChildList(FALSE);
198 for(i = 0; i < m_dwChildCount; i++)
199 {
200 sprintf(szQuery, "INSERT INTO dct_node_map (template_id,node_id) VALUES (%d,%d)", m_dwId, m_pChildList[i]->Id());
201 DBQuery(hdb, szQuery);
202 }
203 UnlockChildList();
204
205 // Save data collection items
206 for(i = 0; i < m_dwNumItems; i++)
207 m_ppItems[i]->SaveToDB(hdb);
208
209 // Save access list
210 SaveACLToDB(hdb);
211
212 // Clear modifications flag and unlock object
213 m_bIsModified = FALSE;
214 UnlockData();
215
216 return TRUE;
217 }
218
219
220 //
221 // Delete object from database
222 //
223
224 BOOL Template::DeleteFromDB(void)
225 {
226 char szQuery[256];
227 BOOL bSuccess;
228
229 bSuccess = NetObj::DeleteFromDB();
230 if (bSuccess)
231 {
232 if (Type() == OBJECT_TEMPLATE)
233 {
234 sprintf(szQuery, "DELETE FROM templates WHERE id=%d", m_dwId);
235 QueueSQLRequest(szQuery);
236 sprintf(szQuery, "DELETE FROM dct_node_map WHERE template_id=%d", m_dwId);
237 QueueSQLRequest(szQuery);
238 }
239 else
240 {
241 sprintf(szQuery, "DELETE FROM dct_node_map WHERE node_id=%d", m_dwId);
242 QueueSQLRequest(szQuery);
243 }
244 sprintf(szQuery, "DELETE FROM items WHERE node_id=%d", m_dwId);
245 QueueSQLRequest(szQuery);
246 sprintf(szQuery, "UPDATE items SET template_id=0 WHERE template_id=%d", m_dwId);
247 QueueSQLRequest(szQuery);
248 }
249 return bSuccess;
250 }
251
252
253 //
254 // Load data collection items from database
255 //
256
257 void Template::LoadItemsFromDB(void)
258 {
259 char szQuery[256];
260 DB_RESULT hResult;
261
262 sprintf(szQuery, "SELECT item_id,name,source,datatype,polling_interval,retention_time,"
263 "status,delta_calculation,transformation,template_id,description,"
264 "instance,template_item_id,adv_schedule,all_thresholds,resource_id,"
265 "proxy_node FROM items WHERE node_id=%d", m_dwId);
266 hResult = DBSelect(g_hCoreDB, szQuery);
267
268 if (hResult != 0)
269 {
270 int i, iRows;
271
272 iRows = DBGetNumRows(hResult);
273 if (iRows > 0)
274 {
275 m_dwNumItems = iRows;
276 m_ppItems = (DCItem **)malloc(sizeof(DCItem *) * iRows);
277 for(i = 0; i < iRows; i++)
278 m_ppItems[i] = new DCItem(hResult, i, this);
279 }
280 DBFreeResult(hResult);
281 }
282 }
283
284
285 //
286 // Add item to node
287 //
288
289 BOOL Template::AddItem(DCItem *pItem, BOOL bLocked)
290 {
291 DWORD i;
292 BOOL bResult = FALSE;
293
294 if (!bLocked)
295 LockData();
296
297 // Check if that item exists
298 for(i = 0; i < m_dwNumItems; i++)
299 if (m_ppItems[i]->Id() == pItem->Id())
300 break; // Item with specified id already exist
301
302 if (i == m_dwNumItems) // Add new item
303 {
304 m_dwNumItems++;
305 m_ppItems = (DCItem **)realloc(m_ppItems, sizeof(DCItem *) * m_dwNumItems);
306 m_ppItems[i] = pItem;
307 m_ppItems[i]->SetLastPollTime(0); // Cause item to be polled immediatelly
308 if (m_ppItems[i]->Status() != ITEM_STATUS_DISABLED)
309 m_ppItems[i]->SetStatus(ITEM_STATUS_ACTIVE);
310 m_ppItems[i]->SetBusyFlag(FALSE);
311 Modify();
312 bResult = TRUE;
313 }
314
315 if (!bLocked)
316 UnlockData();
317 return bResult;
318 }
319
320
321 //
322 // Delete item from node
323 //
324
325 BOOL Template::DeleteItem(DWORD dwItemId, BOOL bNeedLock)
326 {
327 DWORD i;
328 BOOL bResult = FALSE;
329
330 if (bNeedLock)
331 LockData();
332
333 // Check if that item exists
334 for(i = 0; i < m_dwNumItems; i++)
335 if (m_ppItems[i]->Id() == dwItemId)
336 {
337 // Destroy item
338 m_ppItems[i]->PrepareForDeletion();
339 m_ppItems[i]->DeleteFromDB();
340 delete m_ppItems[i];
341 m_dwNumItems--;
342 memmove(&m_ppItems[i], &m_ppItems[i + 1], sizeof(DCItem *) * (m_dwNumItems - i));
343 bResult = TRUE;
344 break;
345 }
346
347 if (bNeedLock)
348 UnlockData();
349 return bResult;
350 }
351
352
353 //
354 // Modify data collection item from CSCP message
355 //
356
357 BOOL Template::UpdateItem(DWORD dwItemId, CSCPMessage *pMsg, DWORD *pdwNumMaps,
358 DWORD **ppdwMapIndex, DWORD **ppdwMapId)
359 {
360 DWORD i;
361 BOOL bResult = FALSE;
362
363 LockData();
364
365 // Check if that item exists
366 for(i = 0; i < m_dwNumItems; i++)
367 if (m_ppItems[i]->Id() == dwItemId)
368 {
369 m_ppItems[i]->UpdateFromMessage(pMsg, pdwNumMaps, ppdwMapIndex, ppdwMapId);
370 bResult = TRUE;
371 m_bIsModified = TRUE;
372 break;
373 }
374
375 UnlockData();
376 return bResult;
377 }
378
379
380 //
381 // Set status for group of DCIs
382 //
383
384 BOOL Template::SetItemStatus(DWORD dwNumItems, DWORD *pdwItemList, int iStatus)
385 {
386 DWORD i, j;
387 BOOL bResult = TRUE;
388
389 LockData();
390 for(i = 0; i < dwNumItems; i++)
391 {
392 for(j = 0; j < m_dwNumItems; j++)
393 {
394 if (m_ppItems[j]->Id() == pdwItemList[i])
395 {
396 m_ppItems[j]->SetStatus(iStatus);
397 break;
398 }
399 }
400 if (j == m_dwNumItems)
401 bResult = FALSE; // Invalid DCI ID provided
402 }
403 UnlockData();
404 return bResult;
405 }
406
407
408 //
409 // Lock data collection items list
410 //
411
412 BOOL Template::LockDCIList(DWORD dwSessionId, const TCHAR *pszNewOwner, TCHAR *pszCurrOwner)
413 {
414 BOOL bSuccess;
415
416 LockData();
417 if (m_dwDCILockStatus == INVALID_INDEX)
418 {
419 m_dwDCILockStatus = dwSessionId;
420 m_bDCIListModified = FALSE;
421 nx_strncpy(m_szCurrDCIOwner, pszNewOwner, MAX_SESSION_NAME);
422 bSuccess = TRUE;
423 }
424 else
425 {
426 if (pszCurrOwner != NULL)
427 _tcscpy(pszCurrOwner, m_szCurrDCIOwner);
428 bSuccess = FALSE;
429 }
430 UnlockData();
431 return bSuccess;
432 }
433
434
435 //
436 // Unlock data collection items list
437 //
438
439 BOOL Template::UnlockDCIList(DWORD dwSessionId)
440 {
441 BOOL bSuccess = FALSE;
442
443 LockData();
444 if (m_dwDCILockStatus == dwSessionId)
445 {
446 m_dwDCILockStatus = INVALID_INDEX;
447 if (m_bDCIListModified && (Type() == OBJECT_TEMPLATE))
448 {
449 m_dwVersion++;
450 Modify();
451 }
452 m_bDCIListModified = FALSE;
453 bSuccess = TRUE;
454 }
455 UnlockData();
456 return bSuccess;
457 }
458
459
460 //
461 // Send DCI list to client
462 //
463
464 void Template::SendItemsToClient(ClientSession *pSession, DWORD dwRqId)
465 {
466 CSCPMessage msg;
467 DWORD i;
468
469 // Prepare message
470 msg.SetId(dwRqId);
471 msg.SetCode(CMD_NODE_DCI);
472
473 LockData();
474
475 // Walk through items list
476 for(i = 0; i < m_dwNumItems; i++)
477 {
478 if ((_tcsnicmp(m_ppItems[i]->Description(), _T("@system."), 8)) ||
479 (Type() == OBJECT_TEMPLATE))
480 {
481 m_ppItems[i]->CreateMessage(&msg);
482 pSession->SendMessage(&msg);
483 msg.DeleteAllVariables();
484 }
485 }
486
487 UnlockData();
488
489 // Send end-of-list indicator
490 msg.SetCode(CMD_NODE_DCI_LIST_END);
491 pSession->SendMessage(&msg);
492 }
493
494
495 //
496 // Get DCI item's type
497 //
498
499 int Template::GetItemType(DWORD dwItemId)
500 {
501 DWORD i;
502 int iType = -1;
503
504 LockData();
505 // Check if that item exists
506 for(i = 0; i < m_dwNumItems; i++)
507 if (m_ppItems[i]->Id() == dwItemId)
508 {
509 iType = m_ppItems[i]->DataType();
510 break;
511 }
512
513 UnlockData();
514 return iType;
515 }
516
517
518 //
519 // Get item by it's id
520 //
521
522 DCItem *Template::GetItemById(DWORD dwItemId)
523 {
524 DWORD i;
525 DCItem *pItem = NULL;
526
527 LockData();
528 // Check if that item exists
529 for(i = 0; i < m_dwNumItems; i++)
530 if (m_ppItems[i]->Id() == dwItemId)
531 {
532 pItem = m_ppItems[i];
533 break;
534 }
535
536 UnlockData();
537 return pItem;
538 }
539
540
541 //
542 // Get item by it's name (case-insensetive)
543 //
544
545 DCItem *Template::GetItemByName(TCHAR *pszName)
546 {
547 DWORD i;
548 DCItem *pItem = NULL;
549
550 LockData();
551 // Check if that item exists
552 for(i = 0; i < m_dwNumItems; i++)
553 if (!_tcsicmp(m_ppItems[i]->Name(), pszName))
554 {
555 pItem = m_ppItems[i];
556 break;
557 }
558
559 UnlockData();
560 return pItem;
561 }
562
563
564 //
565 // Get item by it's index
566 //
567
568 DCItem *Template::GetItemByIndex(DWORD dwIndex)
569 {
570 DCItem *pItem = NULL;
571
572 LockData();
573
574 if (dwIndex < m_dwNumItems)
575 pItem = m_ppItems[dwIndex];
576
577 UnlockData();
578 return pItem;
579 }
580
581
582 //
583 // Redefined status calculation for template
584 //
585
586 void Template::CalculateCompoundStatus(BOOL bForcedRecalc)
587 {
588 m_iStatus = STATUS_UNMANAGED;
589 }
590
591
592 //
593 // Create CSCP message with object's data
594 //
595
596 void Template::CreateMessage(CSCPMessage *pMsg)
597 {
598 NetObj::CreateMessage(pMsg);
599 pMsg->SetVariable(VID_TEMPLATE_VERSION, m_dwVersion);
600 }
601
602
603 //
604 // Modify object from message
605 //
606
607 DWORD Template::ModifyFromMessage(CSCPMessage *pRequest, BOOL bAlreadyLocked)
608 {
609 if (!bAlreadyLocked)
610 LockData();
611
612 // Change template version
613 if (pRequest->IsVariableExist(VID_TEMPLATE_VERSION))
614 m_dwVersion = pRequest->GetVariableLong(VID_TEMPLATE_VERSION);
615
616 return NetObj::ModifyFromMessage(pRequest, TRUE);
617 }
618
619
620 //
621 // Apply template to node
622 //
623
624 BOOL Template::ApplyToNode(Node *pNode)
625 {
626 DWORD i, *pdwItemList;
627 BOOL bErrors = FALSE;
628
629 // Link node to template
630 if (!IsChild(pNode->Id()))
631 {
632 AddChild(pNode);
633 pNode->AddParent(this);
634 }
635
636 pdwItemList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumItems);
637 DbgPrintf(2, "Apply %d items from template \"%s\" to node \"%s\"",
638 m_dwNumItems, m_szName, pNode->Name());
639
640 // Copy items
641 for(i = 0; i < m_dwNumItems; i++)
642 {
643 if (m_ppItems[i] != NULL)
644 {
645 pdwItemList[i] = m_ppItems[i]->Id();
646 if (!pNode->ApplyTemplateItem(m_dwId, m_ppItems[i]))
647 {
648 bErrors = TRUE;
649 }
650 }
651 else
652 {
653 bErrors = TRUE;
654 }
655 }
656
657 // Clean items deleted from template
658 pNode->CleanDeletedTemplateItems(m_dwId, m_dwNumItems, pdwItemList);
659
660 // Cleanup
661 free(pdwItemList);
662
663 return bErrors;
664 }
665
666
667 //
668 // Queue template update
669 //
670
671 void Template::QueueUpdate(void)
672 {
673 DWORD i;
674 TEMPLATE_UPDATE_INFO *pInfo;
675
676 LockData();
677 for(i = 0; i < m_dwChildCount; i++)
678 if (m_pChildList[i]->Type() == OBJECT_NODE)
679 {
680 IncRefCount();
681 pInfo = (TEMPLATE_UPDATE_INFO *)malloc(sizeof(TEMPLATE_UPDATE_INFO));
682 pInfo->iUpdateType = APPLY_TEMPLATE;
683 pInfo->pTemplate = this;
684 pInfo->dwNodeId = m_pChildList[i]->Id();
685 g_pTemplateUpdateQueue->Put(pInfo);
686 }
687 UnlockData();
688 }
689
690
691 //
692 // Queue template remove from node
693 //
694
695 void Template::QueueRemoveFromNode(DWORD dwNodeId, BOOL bRemoveDCI)
696 {
697 TEMPLATE_UPDATE_INFO *pInfo;
698
699 LockData();
700 IncRefCount();
701 pInfo = (TEMPLATE_UPDATE_INFO *)malloc(sizeof(TEMPLATE_UPDATE_INFO));
702 pInfo->iUpdateType = REMOVE_TEMPLATE;
703 pInfo->pTemplate = this;
704 pInfo->dwNodeId = dwNodeId;
705 pInfo->bRemoveDCI = bRemoveDCI;
706 g_pTemplateUpdateQueue->Put(pInfo);
707 UnlockData();
708 }
709
710
711 //
712 // Get list of events used by DCIs
713 //
714
715 DWORD *Template::GetDCIEventsList(DWORD *pdwCount)
716 {
717 DWORD i, j, *pdwList;
718 DCItem *pItem = NULL;
719
720 pdwList = NULL;
721 *pdwCount = 0;
722
723 LockData();
724 for(i = 0; i < m_dwNumItems; i++)
725 {
726 m_ppItems[i]->GetEventList(&pdwList, pdwCount);
727 }
728 UnlockData();
729
730 // Clean list from duplicates
731 for(i = 0; i < *pdwCount; i++)
732 {
733 for(j = i + 1; j < *pdwCount; j++)
734 {
735 if (pdwList[i] == pdwList[j])
736 {
737 (*pdwCount)--;
738 memmove(&pdwList[j], &pdwList[j + 1], sizeof(DWORD) * (*pdwCount - j));
739 j--;
740 }
741 }
742 }
743
744 return pdwList;
745 }
746
747
748 //
749 // Create management pack record
750 //
751
752 void Template::CreateNXMPRecord(String &str)
753 {
754 DWORD i;
755
756 str.AddFormattedString(_T("\t@TEMPLATE %s\n\t{\n\t\t@DCI_LIST\n\t\t{\n"), m_szName);
757
758 LockData();
759 for(i = 0; i < m_dwNumItems; i++)
760 m_ppItems[i]->CreateNXMPRecord(str);
761 UnlockData();
762
763 str += _T("\t\t}\n\t}\n");
764 }
765
766
767 //
768 // Validate template agains specific DCI list
769 //
770
771 void Template::ValidateDCIList(DCI_CFG *cfg)
772 {
773 DWORD i, j, dwNumDeleted, *pdwDeleteList;
774
775 LockData();
776
777 pdwDeleteList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumItems);
778 dwNumDeleted = 0;
779
780 for(i = 0; i < m_dwNumItems; i++)
781 {
782 for(j = 0; cfg[j].pszName != NULL; j++)
783 {
784 if (!_tcsicmp(m_ppItems[i]->Description(), cfg[j].pszName))
785 {
786 m_ppItems[i]->SystemModify(cfg[j].pszParam, cfg[j].nOrigin,
787 cfg[j].nRetention, cfg[j].nInterval,
788 cfg[j].nDataType);
789 cfg[j].nFound = 1;
790 break;
791 }
792 }
793
794 // Mark non-existing items
795 if (cfg[j].pszName == NULL)
796 pdwDeleteList[dwNumDeleted++] = m_ppItems[i]->Id();
797 }
798
799 // Delete unneeded items
800 for(i = 0; i < dwNumDeleted; i++)
801 DeleteItem(pdwDeleteList[i], FALSE);
802
803 // Create missing items
804 for(i = 0; cfg[i].pszName != NULL; i++)
805 {
806 if (!cfg[i].nFound)
807 {
808 AddItem(new DCItem(CreateUniqueId(IDG_ITEM), cfg[i].pszParam,
809 cfg[i].nOrigin, cfg[i].nDataType,
810 cfg[i].nInterval, cfg[i].nRetention,
811 this, cfg[i].pszName), TRUE);
812 }
813 }
814
815 UnlockData();
816 }
817
818
819 //
820 // Validate system template
821 //
822
823 void Template::ValidateSystemTemplate(void)
824 {
825 if (!_tcsicmp(m_szName, _T("@System.Agent")))
826 {
827 DCI_CFG dciCfgAgent[] =
828 {
829 { _T("@system.cpu_usage"), _T("System.CPU.Usage"), 60, 1, DCI_DT_INT, DS_NATIVE_AGENT, 0 },
830 { _T("@system.load_avg"), _T("System.CPU.LoadAvg"), 60, 1, DCI_DT_FLOAT, DS_NATIVE_AGENT, 0 },
831 { _T("@system.usedmem"), _T("System.Memory.Physical.Used"), 60, 1, DCI_DT_UINT64, DS_NATIVE_AGENT, 0 },
832 { _T("@system.totalmem"), _T("System.Memory.Physical.Total"), 60, 1, DCI_DT_UINT64, DS_NATIVE_AGENT, 0 },
833 { _T("@system.disk_queue"), _T("System.IO.DiskQueue"), 60, 1, DCI_DT_FLOAT, DS_NATIVE_AGENT, 0 },
834 { NULL, NULL, 0, 0, 0, 0 }
835 };
836
837 ValidateDCIList(dciCfgAgent);
838 }
839 else if (!_tcsicmp(m_szName, _T("@System.SNMP")))
840 {
841 DCI_CFG dciCfgSNMP[] =
842 {
843 { _T("@system.cpu_usage.cisco"), _T(".1.3.6.1.4.1.9.9.109.1.1.1.1.7.0"),
844 60, 1, DCI_DT_INT, DS_SNMP_AGENT, 0 }, // Cisco devices
845 { _T("@system.cpu_usage.passport"), _T(".1.3.6.1.4.1.2272.1.1.20.0"),
846 60, 1, DCI_DT_INT, DS_SNMP_AGENT, 0 }, // Nortel Passport switches
847 { _T("@system.cpu_usage.netscreen"), _T(".1.3.6.1.4.1.3224.16.1.2.0"),
848 60, 1, DCI_DT_INT, DS_SNMP_AGENT, 0 }, // Netscreen devices
849 { _T("@system.cpu_usage.ipso"), _T(".1.3.6.1.4.1.94.1.21.1.7.1.0"),
850 60, 1, DCI_DT_INT, DS_SNMP_AGENT, 0 }, // Nokia IPSO
851 { NULL, NULL, 0, 0, 0, 0 }
852 };
853
854 ValidateDCIList(dciCfgSNMP);
855 }
856 }
857
858
859 //
860 // Enumerate all DCIs
861 //
862
863 BOOL Template::EnumDCI(BOOL (* pfCallback)(DCItem *, DWORD, void *), void *pArg)
864 {
865 DWORD i;
866 BOOL bRet = TRUE;
867
868 LockData();
869 for(i = 0; i < m_dwNumItems; i++)
870 {
871 if (!pfCallback(m_ppItems[i], i, pArg))
872 {
873 bRet = FALSE;
874 break;
875 }
876 }
877 UnlockData();
878 return bRet;
879 }
880
881
882 //
883 // (Re)associate all DCIs
884 //
885
886 void Template::AssociateItems(void)
887 {
888 DWORD i;
889
890 LockData();
891 for(i = 0; i < m_dwNumItems; i++)
892 m_ppItems[i]->ChangeBinding(0, this, FALSE);
893 UnlockData();
894 }