2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2017 Victor Kirhenshtein
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 * Data collector thread pool
28 extern ThreadPool
*g_dataCollectorThreadPool
;
31 * Data collector worker
33 void DataCollector(void *arg
);
38 DataCollectionTarget
::DataCollectionTarget() : Template()
40 m_deletedItems
= new IntegerArray
<UINT32
>(32, 32);
41 m_deletedTables
= new IntegerArray
<UINT32
>(32, 32);
42 m_pingLastTimeStamp
= 0;
43 m_pingTime
= PING_TIME_TIMEOUT
;
44 m_lastConfigurationPoll
= 0;
46 m_lastInstancePoll
= 0;
47 m_hPollerMutex
= MutexCreate();
51 * Constructor for creating new data collection capable objects
53 DataCollectionTarget
::DataCollectionTarget(const TCHAR
*name
) : Template(name
)
55 m_deletedItems
= new IntegerArray
<UINT32
>(32, 32);
56 m_deletedTables
= new IntegerArray
<UINT32
>(32, 32);
57 m_pingLastTimeStamp
= 0;
58 m_pingTime
= PING_TIME_TIMEOUT
;
59 m_lastConfigurationPoll
= 0;
61 m_lastInstancePoll
= 0;
62 m_hPollerMutex
= MutexCreate();
68 DataCollectionTarget
::~DataCollectionTarget()
70 delete m_deletedItems
;
71 delete m_deletedTables
;
72 MutexDestroy(m_hPollerMutex
);
76 * Delete object from database
78 bool DataCollectionTarget
::deleteFromDatabase(DB_HANDLE hdb
)
80 bool success
= Template
::deleteFromDatabase(hdb
);
84 _sntprintf(query
, 256, _T("DROP TABLE idata_%d"), (int)m_id
);
85 QueueSQLRequest(query
);
87 _sntprintf(query
, 256, _T("DROP TABLE tdata_%d"), (int)m_id
);
88 QueueSQLRequest(query
);
94 * Create NXCP message with object's data
96 void DataCollectionTarget
::fillMessageInternal(NXCPMessage
*msg
)
98 Template
::fillMessageInternal(msg
);
102 * Create NXCP message with object's data - stage 2
104 void DataCollectionTarget
::fillMessageInternalStage2(NXCPMessage
*msg
)
106 Template
::fillMessageInternalStage2(msg
);
108 // Sent all DCIs marked for display on overview page or in tooltips
109 UINT32 fieldIdOverview
= VID_OVERVIEW_DCI_LIST_BASE
;
110 UINT32 countOverview
= 0;
111 UINT32 fieldIdTooltip
= VID_TOOLTIP_DCI_LIST_BASE
;
112 UINT32 countTooltip
= 0;
113 lockDciAccess(false);
114 for(int i
= 0; i
< m_dcObjects
->size(); i
++)
116 DCObject
*dci
= m_dcObjects
->get(i
);
117 if ((dci
->getType() == DCO_TYPE_ITEM
) &&
118 (dci
->getStatus() == ITEM_STATUS_ACTIVE
) &&
119 (((DCItem
*)dci
)->getInstanceDiscoveryMethod() == IDM_NONE
))
121 if (dci
->isShowInObjectOverview())
124 ((DCItem
*)dci
)->fillLastValueMessage(msg
, fieldIdOverview
);
125 fieldIdOverview
+= 50;
127 if (dci
->isShowOnObjectTooltip())
130 ((DCItem
*)dci
)->fillLastValueMessage(msg
, fieldIdTooltip
);
131 fieldIdTooltip
+= 50;
136 msg
->setField(VID_OVERVIEW_DCI_COUNT
, countOverview
);
137 msg
->setField(VID_TOOLTIP_DCI_COUNT
, countTooltip
);
141 * Modify object from message
143 UINT32 DataCollectionTarget
::modifyFromMessageInternal(NXCPMessage
*pRequest
)
145 return Template
::modifyFromMessageInternal(pRequest
);
149 * Update cache for all DCI's
151 void DataCollectionTarget
::updateDciCache()
153 lockDciAccess(false);
154 for(int i
= 0; i
< m_dcObjects
->size(); i
++)
156 if (m_dcObjects
->get(i
)->getType() == DCO_TYPE_ITEM
)
158 ((DCItem
*)m_dcObjects
->get(i
))->updateCacheSize();
165 * Clean expired DCI data
167 void DataCollectionTarget
::cleanDCIData(DB_HANDLE hdb
)
169 String queryItems
= _T("DELETE FROM idata_");
170 queryItems
.append(m_id
);
171 queryItems
.append(_T(" WHERE "));
173 String queryTables
= _T("DELETE FROM tdata_");
174 queryTables
.append(m_id
);
175 queryTables
.append(_T(" WHERE "));
179 time_t now
= time(NULL
);
181 lockDciAccess(false);
182 for(int i
= 0; i
< m_dcObjects
->size(); i
++)
184 DCObject
*o
= m_dcObjects
->get(i
);
185 if (o
->getType() == DCO_TYPE_ITEM
)
188 queryItems
.append(_T(" OR "));
189 queryItems
.append(_T("(item_id="));
190 queryItems
.append(o
->getId());
191 queryItems
.append(_T(" AND idata_timestamp<"));
192 queryItems
.append((INT64
)(now
- o
->getEffectiveRetentionTime() * 86400));
193 queryItems
.append(_T(')'));
196 else if (o
->getType() == DCO_TYPE_TABLE
)
199 queryTables
.append(_T(" OR "));
200 queryTables
.append(_T("(item_id="));
201 queryTables
.append(o
->getId());
202 queryTables
.append(_T(" AND tdata_timestamp<"));
203 queryTables
.append((INT64
)(now
- o
->getEffectiveRetentionTime() * 86400));
204 queryTables
.append(_T(')'));
211 for(int i
= 0; i
< m_deletedItems
->size(); i
++)
214 queryItems
.append(_T(" OR "));
215 queryItems
.append(_T("item_id="));
216 queryItems
.append(m_deletedItems
->get(i
));
219 m_deletedItems
->clear();
221 for(int i
= 0; i
< m_deletedTables
->size(); i
++)
224 queryTables
.append(_T(" OR "));
225 queryTables
.append(_T("item_id="));
226 queryTables
.append(m_deletedItems
->get(i
));
229 m_deletedTables
->clear();
234 nxlog_debug(6, _T("DataCollectionTarget::cleanDCIData(%s [%d]): running query \"%s\""), m_name
, m_id
, (const TCHAR
*)queryItems
);
235 DBQuery(hdb
, queryItems
);
240 nxlog_debug(6, _T("DataCollectionTarget::cleanDCIData(%s [%d]): running query \"%s\""), m_name
, m_id
, (const TCHAR
*)queryTables
);
241 DBQuery(hdb
, queryTables
);
246 * Schedule cleanup of DCI data after DCI deletion
248 void DataCollectionTarget
::scheduleItemDataCleanup(UINT32 dciId
)
251 m_deletedItems
->add(dciId
);
256 * Schedule cleanup of table DCI data after DCI deletion
258 void DataCollectionTarget
::scheduleTableDataCleanup(UINT32 dciId
)
261 m_deletedTables
->add(dciId
);
266 * Get last collected values of given table
268 UINT32 DataCollectionTarget
::getTableLastValues(UINT32 dciId
, NXCPMessage
*msg
)
270 UINT32 rcc
= RCC_INVALID_DCI_ID
;
272 lockDciAccess(false);
274 for(int i
= 0; i
< m_dcObjects
->size(); i
++)
276 DCObject
*object
= m_dcObjects
->get(i
);
277 if ((object
->getId() == dciId
) && (object
->getType() == DCO_TYPE_TABLE
))
279 ((DCTable
*)object
)->fillLastValueMessage(msg
);
290 * Apply DCI from template
291 * dcObject passed to this method should be a template's DCI
293 bool DataCollectionTarget
::applyTemplateItem(UINT32 dwTemplateId
, DCObject
*dcObject
)
297 lockDciAccess(true); // write lock
299 nxlog_debug(5, _T("Applying DCO \"%s\" to target \"%s\""), dcObject
->getName(), m_name
);
301 // Check if that template item exists
303 for(i
= 0; i
< m_dcObjects
->size(); i
++)
304 if ((m_dcObjects
->get(i
)->getTemplateId() == dwTemplateId
) &&
305 (m_dcObjects
->get(i
)->getTemplateItemId() == dcObject
->getId()))
306 break; // Item with specified id already exist
308 if (i
== m_dcObjects
->size())
310 // New item from template, just add it
312 switch(dcObject
->getType())
315 newObject
= new DCItem((DCItem
*)dcObject
);
318 newObject
= new DCTable((DCTable
*)dcObject
);
324 if (newObject
!= NULL
)
326 newObject
->setTemplateId(dwTemplateId
, dcObject
->getId());
327 newObject
->changeBinding(CreateUniqueId(IDG_ITEM
), this, TRUE
);
328 bResult
= addDCObject(newObject
, true);
333 // Update existing item unless it is disabled
334 DCObject
*curr
= m_dcObjects
->get(i
);
335 if ((curr
->getStatus() != ITEM_STATUS_DISABLED
) || (g_flags
& AF_APPLY_TO_DISABLED_DCI_FROM_TEMPLATE
))
337 curr
->updateFromTemplate(dcObject
);
338 DbgPrintf(9, _T("DCO \"%s\" NOT disabled or ApplyDCIFromTemplateToDisabledDCI set, updated (%d)"),
339 dcObject
->getName(), curr
->getStatus());
340 if ((curr
->getType() == DCO_TYPE_ITEM
) && (((DCItem
*)curr
)->getInstanceDiscoveryMethod() != IDM_NONE
))
342 updateInstanceDiscoveryItems((DCItem
*)curr
);
347 DbgPrintf(9, _T("DCO \"%s\" is disabled and ApplyDCIFromTemplateToDisabledDCI not set, no update (%d)"),
348 dcObject
->getName(), curr
->getStatus());
364 * Clean deleted template items from target's DCI list
365 * Arguments is template id and list of valid template item ids.
366 * all items related to given template and not presented in list should be deleted.
368 void DataCollectionTarget
::cleanDeletedTemplateItems(UINT32 dwTemplateId
, UINT32 dwNumItems
, UINT32
*pdwItemList
)
370 UINT32 i
, j
, dwNumDeleted
, *pdwDeleteList
;
372 lockDciAccess(true); // write lock
374 pdwDeleteList
= (UINT32
*)malloc(sizeof(UINT32
) * m_dcObjects
->size());
377 for(i
= 0; i
< (UINT32
)m_dcObjects
->size(); i
++)
378 if (m_dcObjects
->get(i
)->getTemplateId() == dwTemplateId
)
380 for(j
= 0; j
< dwNumItems
; j
++)
381 if (m_dcObjects
->get(i
)->getTemplateItemId() == pdwItemList
[j
])
384 // Delete DCI if it's not in list
386 pdwDeleteList
[dwNumDeleted
++] = m_dcObjects
->get(i
)->getId();
389 for(i
= 0; i
< dwNumDeleted
; i
++)
390 deleteDCObject(pdwDeleteList
[i
], false);
397 * Unbind data collection target from template, i.e either remove DCI
398 * association with template or remove these DCIs at all
400 void DataCollectionTarget
::unbindFromTemplate(UINT32 dwTemplateId
, bool removeDCI
)
404 lockDciAccess(true); // write lock
406 UINT32
*deleteList
= (UINT32
*)malloc(sizeof(UINT32
) * m_dcObjects
->size());
410 for(i
= 0; i
< m_dcObjects
->size(); i
++)
411 if (m_dcObjects
->get(i
)->getTemplateId() == dwTemplateId
)
413 deleteList
[numDeleted
++] = m_dcObjects
->get(i
)->getId();
416 for(i
= 0; i
< numDeleted
; i
++)
417 deleteDCObject(deleteList
[i
], false);
424 lockDciAccess(false);
426 for(int i
= 0; i
< m_dcObjects
->size(); i
++)
427 if (m_dcObjects
->get(i
)->getTemplateId() == dwTemplateId
)
429 m_dcObjects
->get(i
)->setTemplateId(0, 0);
437 * Get list of DCIs to be shown on performance tab
439 UINT32 DataCollectionTarget
::getPerfTabDCIList(NXCPMessage
*pMsg
)
441 lockDciAccess(false);
443 UINT32 dwId
= VID_SYSDCI_LIST_BASE
, dwCount
= 0;
444 for(int i
= 0; i
< m_dcObjects
->size(); i
++)
446 DCObject
*object
= m_dcObjects
->get(i
);
447 if ((object
->getPerfTabSettings() != NULL
) &&
448 object
->hasValue() &&
449 (object
->getStatus() == ITEM_STATUS_ACTIVE
) &&
450 object
->matchClusterResource())
452 pMsg
->setField(dwId
++, object
->getId());
453 pMsg
->setField(dwId
++, object
->getDescription());
454 pMsg
->setField(dwId
++, (WORD
)object
->getStatus());
455 pMsg
->setField(dwId
++, object
->getPerfTabSettings());
456 pMsg
->setField(dwId
++, (WORD
)object
->getType());
457 pMsg
->setField(dwId
++, object
->getTemplateItemId());
458 if (object
->getType() == DCO_TYPE_ITEM
)
460 pMsg
->setField(dwId
++, ((DCItem
*)object
)->getInstance());
461 if ((object
->getTemplateItemId() != 0) && (object
->getTemplateId() == m_id
))
463 // DCI created via instance discovery - send ID of root template item
464 // to allow UI to resolve double template case
465 // (template -> instance discovery item on node -> actual item on node)
466 DCObject
*src
= getDCObjectById(object
->getTemplateItemId(), false);
467 pMsg
->setField(dwId
++, (src
!= NULL
) ? src
->getTemplateItemId() : 0);
482 pMsg
->setField(VID_NUM_ITEMS
, dwCount
);
489 * Get threshold violation summary into NXCP message
491 UINT32 DataCollectionTarget
::getThresholdSummary(NXCPMessage
*msg
, UINT32 baseId
)
493 UINT32 varId
= baseId
;
495 msg
->setField(varId
++, m_id
);
496 UINT32 countId
= varId
++;
499 lockDciAccess(false);
500 for(int i
= 0; i
< m_dcObjects
->size(); i
++)
502 DCObject
*object
= m_dcObjects
->get(i
);
503 if (object
->hasValue() && (object
->getType() == DCO_TYPE_ITEM
) && (object
->getStatus() == ITEM_STATUS_ACTIVE
))
505 if (((DCItem
*)object
)->hasActiveThreshold())
507 ((DCItem
*)object
)->fillLastValueMessage(msg
, varId
);
514 msg
->setField(countId
, count
);
519 * Process new DCI value
521 bool DataCollectionTarget
::processNewDCValue(DCObject
*dco
, time_t currTime
, const void *value
)
524 bool result
= dco
->processNewValue(currTime
, value
, &updateStatus
);
527 calculateCompoundStatus(FALSE
);
533 * Check if data collection is disabled
535 bool DataCollectionTarget
::isDataCollectionDisabled()
541 * Put items which requires polling into the queue
543 void DataCollectionTarget
::queueItemsForPolling()
545 if ((m_status
== STATUS_UNMANAGED
) || isDataCollectionDisabled() || m_isDeleted
)
546 return; // Do not collect data for unmanaged objects or if data collection is disabled
548 time_t currTime
= time(NULL
);
550 lockDciAccess(false);
551 for(int i
= 0; i
< m_dcObjects
->size(); i
++)
553 DCObject
*object
= m_dcObjects
->get(i
);
554 if (object
->isReadyForPolling(currTime
))
556 object
->setBusyFlag();
557 incRefCount(); // Increment reference count for each queued DCI
559 if ((object
->getDataSource() == DS_NATIVE_AGENT
) ||
560 (object
->getDataSource() == DS_WINPERF
) ||
561 (object
->getDataSource() == DS_SSH
) ||
562 (object
->getDataSource() == DS_SMCLP
))
565 _sntprintf(key
, 32, _T("%08X/%s"),
566 m_id
, (object
->getDataSource() == DS_SSH
) ?
_T("ssh") :
567 (object
->getDataSource() == DS_SMCLP
) ?
_T("smclp") : _T("agent"));
568 ThreadPoolExecuteSerialized(g_dataCollectorThreadPool
, key
, DataCollector
, object
);
572 ThreadPoolExecute(g_dataCollectorThreadPool
, DataCollector
, object
);
574 nxlog_debug(8, _T("DataCollectionTarget(%s)->QueueItemsForPolling(): item %d \"%s\" added to queue"), m_name
, object
->getId(), object
->getName());
581 * Get object from parameter
583 NetObj
*DataCollectionTarget
::objectFromParameter(const TCHAR
*param
)
585 TCHAR
*eptr
, arg
[256];
586 AgentGetParameterArg(param
, 1, arg
, 256);
587 UINT32 objectId
= _tcstoul(arg
, &eptr
, 0);
590 // Argument is object's name
594 // Find child object with requested ID or name
595 NetObj
*object
= NULL
;
596 lockChildList(false);
597 for(int i
= 0; i
< m_childList
->size(); i
++)
599 NetObj
*curr
= m_childList
->get(i
);
600 if (((objectId
== 0) && (!_tcsicmp(curr
->getName(), arg
))) ||
601 (objectId
== curr
->getId()))
612 * Get value for server's internal parameter
614 UINT32 DataCollectionTarget
::getInternalItem(const TCHAR
*param
, size_t bufSize
, TCHAR
*buffer
)
616 UINT32 dwError
= DCE_SUCCESS
;
618 if (!_tcsicmp(param
, _T("Status")))
620 _sntprintf(buffer
, bufSize
, _T("%d"), m_status
);
622 else if (!_tcsicmp(param
, _T("Dummy")) || MatchString(_T("Dummy(*)"), param
, FALSE
))
624 _tcscpy(buffer
, _T("0"));
626 else if (MatchString(_T("ChildStatus(*)"), param
, FALSE
))
628 NetObj
*object
= objectFromParameter(param
);
631 _sntprintf(buffer
, bufSize
, _T("%d"), object
->getStatus());
635 dwError
= DCE_NOT_SUPPORTED
;
638 else if (MatchString(_T("ConditionStatus(*)"), param
, FALSE
))
640 TCHAR
*pEnd
, szArg
[256];
642 NetObj
*pObject
= NULL
;
644 AgentGetParameterArg(param
, 1, szArg
, 256);
645 dwId
= _tcstoul(szArg
, &pEnd
, 0);
648 pObject
= FindObjectById(dwId
);
650 if (pObject
->getObjectClass() != OBJECT_CONDITION
)
655 // Argument is object's name
656 pObject
= FindObjectByName(szArg
, OBJECT_CONDITION
);
661 if (pObject
->isTrustedNode(m_id
))
663 _sntprintf(buffer
, bufSize
, _T("%d"), pObject
->getStatus());
667 dwError
= DCE_NOT_SUPPORTED
;
672 dwError
= DCE_NOT_SUPPORTED
;
677 dwError
= DCE_NOT_SUPPORTED
;
684 * Run data collection script. Returns pointer to NXSL VM after successful run and NULL on failure.
686 NXSL_VM
*DataCollectionTarget
::runDataCollectionScript(const TCHAR
*param
, DataCollectionTarget
*targetObject
)
689 nx_strncpy(name
, param
, 256);
692 ObjectArray
<NXSL_Value
> args(16, 16, false);
694 // Can be in form parameter(arg1, arg2, ... argN)
695 TCHAR
*p
= _tcschr(name
, _T('('));
698 if (name
[_tcslen(name
) - 1] != _T(')'))
700 name
[_tcslen(name
) - 1] = 0;
702 if (!ParseValueList(&p
, args
))
704 // argument parsing error
710 NXSL_VM
*vm
= CreateServerScriptVM(name
);
713 vm
->setGlobalVariable(_T("$object"), createNXSLObject());
714 if (getObjectClass() == OBJECT_NODE
)
716 vm
->setGlobalVariable(_T("$node"), createNXSLObject());
718 vm
->setGlobalVariable(_T("$isCluster"), new NXSL_Value((getObjectClass() == OBJECT_CLUSTER
) ?
1 : 0));
719 if (targetObject
!= NULL
)
721 vm
->setGlobalVariable(_T("$targetObject"), targetObject
->createNXSLObject());
725 DbgPrintf(4, _T("DataCollectionTarget(%s)->runDataCollectionScript(%s): Script execution error: %s"), m_name
, param
, vm
->getErrorText());
726 PostEvent(EVENT_SCRIPT_ERROR
, g_dwMgmtNode
, "ssd", name
, vm
->getErrorText(), m_id
);
734 nxlog_debug(7, _T("DataCollectionTarget(%s)->runDataCollectionScript(%s): %s"), m_name
, param
, (vm
!= NULL
) ?
_T("success") : _T("failure"));
739 * Get parameter value from NXSL script
741 UINT32 DataCollectionTarget
::getScriptItem(const TCHAR
*param
, size_t bufSize
, TCHAR
*buffer
, DataCollectionTarget
*targetObject
)
743 UINT32 rc
= DCE_NOT_SUPPORTED
;
744 NXSL_VM
*vm
= runDataCollectionScript(param
, targetObject
);
747 NXSL_Value
*value
= vm
->getResult();
750 // NULL value is an error indicator
751 rc
= DCE_COLLECTION_ERROR
;
755 const TCHAR
*dciValue
= value
->getValueAsCString();
756 nx_strncpy(buffer
, CHECK_NULL_EX(dciValue
), bufSize
);
761 nxlog_debug(7, _T("DataCollectionTarget(%s)->getScriptItem(%s): rc=%d"), m_name
, param
, rc
);
766 * Get list from library script
768 UINT32 DataCollectionTarget
::getListFromScript(const TCHAR
*param
, StringList
**list
, DataCollectionTarget
*targetObject
)
770 UINT32 rc
= DCE_NOT_SUPPORTED
;
771 NXSL_VM
*vm
= runDataCollectionScript(param
, targetObject
);
775 NXSL_Value
*value
= vm
->getResult();
776 if (value
->isArray())
778 *list
= value
->getValueAsArray()->toStringList();
780 else if (value
->isString())
782 *list
= new StringList
;
783 (*list
)->add(value
->getValueAsCString());
785 else if (value
->isNull())
787 rc
= DCE_COLLECTION_ERROR
;
791 *list
= new StringList
;
795 nxlog_debug(7, _T("DataCollectionTarget(%s)->getListFromScript(%s): rc=%d"), m_name
, param
, rc
);
800 * Get table from NXSL script
802 UINT32 DataCollectionTarget
::getScriptTable(const TCHAR
*param
, Table
**result
, DataCollectionTarget
*targetObject
)
804 UINT32 rc
= DCE_NOT_SUPPORTED
;
805 NXSL_VM
*vm
= runDataCollectionScript(param
, targetObject
);
808 NXSL_Value
*value
= vm
->getResult();
809 if (value
->isObject(_T("Table")))
811 *result
= (Table
*)value
->getValueAsObject()->getData();
812 (*result
)->incRefCount();
817 rc
= DCE_COLLECTION_ERROR
;
821 nxlog_debug(7, _T("DataCollectionTarget(%s)->getScriptTable(%s): rc=%d"), m_name
, param
, rc
);
826 * Get string map from library script
828 UINT32 DataCollectionTarget
::getStringMapFromScript(const TCHAR
*param
, StringMap
**map
, DataCollectionTarget
*targetObject
)
831 nx_strncpy(name
, param
, 256);
834 ObjectArray
<NXSL_Value
> args(16, 16, false);
836 // Can be in form parameter(arg1, arg2, ... argN)
837 TCHAR
*p
= _tcschr(name
, _T('('));
840 if (name
[_tcslen(name
) - 1] != _T(')'))
841 return DCE_NOT_SUPPORTED
;
842 name
[_tcslen(name
) - 1] = 0;
844 if (!ParseValueList(&p
, args
))
846 // argument parsing error
848 return DCE_NOT_SUPPORTED
;
852 UINT32 rc
= DCE_NOT_SUPPORTED
;
853 NXSL_VM
*vm
= CreateServerScriptVM(name
);
856 vm
->setGlobalVariable(_T("$object"), createNXSLObject());
857 if (getObjectClass() == OBJECT_NODE
)
859 vm
->setGlobalVariable(_T("$node"), createNXSLObject());
861 vm
->setGlobalVariable(_T("$isCluster"), new NXSL_Value((getObjectClass() == OBJECT_CLUSTER
) ?
1 : 0));
862 if (targetObject
!= NULL
)
864 vm
->setGlobalVariable(_T("$targetObject"), targetObject
->createNXSLObject());
869 NXSL_Value
*value
= vm
->getResult();
870 if (value
->isHashMap())
872 *map
= value
->getValueAsHashMap()->toStringMap();
874 else if (value
->isArray())
876 *map
= new StringMap();
877 NXSL_Array
*a
= value
->getValueAsArray();
878 for(int i
= 0; i
< a
->size(); i
++)
880 NXSL_Value
*v
= a
->getByPosition(i
);
883 (*map
)->set(v
->getValueAsCString(), v
->getValueAsCString());
887 else if (value
->isString())
889 *map
= new StringMap();
890 (*map
)->set(value
->getValueAsCString(), value
->getValueAsCString());
892 else if (value
->isNull())
894 rc
= DCE_COLLECTION_ERROR
;
898 *map
= new StringMap();
903 DbgPrintf(4, _T("DataCollectionTarget(%s)->getListFromScript(%s): Script execution error: %s"), m_name
, param
, vm
->getErrorText());
904 PostEvent(EVENT_SCRIPT_ERROR
, g_dwMgmtNode
, "ssd", name
, vm
->getErrorText(), m_id
);
905 rc
= DCE_COLLECTION_ERROR
;
912 DbgPrintf(4, _T("DataCollectionTarget(%s)->getListFromScript(%s): script \"%s\" not found"), m_name
, param
, name
);
914 DbgPrintf(7, _T("DataCollectionTarget(%s)->getListFromScript(%s): rc=%d"), m_name
, param
, rc
);
919 * Get last (current) DCI values for summary table.
921 void DataCollectionTarget
::getDciValuesSummary(SummaryTable
*tableDefinition
, Table
*tableData
)
923 if (tableDefinition
->isTableDciSource())
924 getTableDciValuesSummary(tableDefinition
, tableData
);
926 getItemDciValuesSummary(tableDefinition
, tableData
);
930 * Get last (current) DCI values for summary table using single-value DCIs
932 void DataCollectionTarget
::getItemDciValuesSummary(SummaryTable
*tableDefinition
, Table
*tableData
)
934 int offset
= tableDefinition
->isMultiInstance() ?
2 : 1;
935 int baseRow
= tableData
->getNumRows();
936 bool rowAdded
= false;
937 lockDciAccess(false);
938 for(int i
= 0; i
< tableDefinition
->getNumColumns(); i
++)
940 SummaryTableColumn
*tc
= tableDefinition
->getColumn(i
);
941 for(int j
= 0; j
< m_dcObjects
->size(); j
++)
943 DCObject
*object
= m_dcObjects
->get(j
);
944 if ((object
->getType() == DCO_TYPE_ITEM
) && object
->hasValue() &&
945 (object
->getStatus() == ITEM_STATUS_ACTIVE
) &&
946 ((tc
->m_flags
& COLUMN_DEFINITION_REGEXP_MATCH
) ?
947 RegexpMatch(object
->getName(), tc
->m_dciName
, FALSE
) :
948 !_tcsicmp(object
->getName(), tc
->m_dciName
)
952 if (tableDefinition
->isMultiInstance())
955 const TCHAR
*instance
= ((DCItem
*)object
)->getInstance();
956 for(row
= baseRow
; row
< tableData
->getNumRows(); row
++)
958 const TCHAR
*v
= tableData
->getAsString(row
, 1);
959 if (!_tcscmp(CHECK_NULL_EX(v
), instance
))
962 if (row
== tableData
->getNumRows())
965 tableData
->set(0, m_name
);
966 tableData
->set(1, instance
);
967 tableData
->setObjectId(m_id
);
975 tableData
->set(0, m_name
);
976 tableData
->setObjectId(m_id
);
979 row
= tableData
->getNumRows() - 1;
981 tableData
->setStatusAt(row
, i
+ offset
, ((DCItem
*)object
)->getThresholdSeverity());
982 tableData
->setCellObjectIdAt(row
, i
+ offset
, object
->getId());
983 tableData
->getColumnDefinitions()->get(i
+ offset
)->setDataType(((DCItem
*)object
)->getDataType());
984 if (tableDefinition
->getAggregationFunction() == F_LAST
)
986 if (tc
->m_flags
& COLUMN_DEFINITION_MULTIVALUED
)
988 StringList
*values
= String(((DCItem
*)object
)->getLastValue()).split(tc
->m_separator
);
989 tableData
->setAt(row
, i
+ offset
, values
->get(0));
990 for(int r
= 1; r
< values
->size(); r
++)
992 if (row
+ r
>= tableData
->getNumRows())
995 tableData
->setObjectId(m_id
);
996 tableData
->setBaseRow(row
);
998 tableData
->setAt(row
+ r
, i
+ offset
, values
->get(r
));
999 tableData
->setStatusAt(row
+ r
, i
+ offset
, ((DCItem
*)object
)->getThresholdSeverity());
1000 tableData
->setCellObjectIdAt(row
+ r
, i
+ offset
, object
->getId());
1005 tableData
->setAt(row
, i
+ offset
, ((DCItem
*)object
)->getLastValue());
1010 tableData
->setAt(row
, i
+ offset
,
1011 ((DCItem
*)object
)->getAggregateValue(
1012 tableDefinition
->getAggregationFunction(),
1013 tableDefinition
->getPeriodStart(),
1014 tableDefinition
->getPeriodEnd()));
1017 if (!tableDefinition
->isMultiInstance())
1026 * Get last (current) DCI values for summary table using table DCIs
1028 void DataCollectionTarget
::getTableDciValuesSummary(SummaryTable
*tableDefinition
, Table
*tableData
)
1030 lockDciAccess(false);
1031 for(int i
= 0; i
< m_dcObjects
->size(); i
++)
1033 DCObject
*o
= m_dcObjects
->get(i
);
1034 if ((o
->getType() == DCO_TYPE_TABLE
) && o
->hasValue() &&
1035 (o
->getStatus() == ITEM_STATUS_ACTIVE
) &&
1036 !_tcsicmp(o
->getName(), tableDefinition
->getTableDciName()))
1038 Table
*lastValue
= ((DCTable
*)o
)->getLastValue();
1039 if (lastValue
== NULL
)
1042 for(int j
= 0; j
< lastValue
->getNumRows(); j
++)
1044 tableData
->addRow();
1045 tableData
->setObjectId(m_id
);
1046 tableData
->set(0, m_name
);
1047 for(int k
= 0; k
< lastValue
->getNumColumns(); k
++)
1049 int columnIndex
= tableData
->getColumnIndex(lastValue
->getColumnName(k
));
1050 if (columnIndex
== -1)
1051 columnIndex
= tableData
->addColumn(lastValue
->getColumnDefinition(k
));
1052 tableData
->set(columnIndex
, lastValue
->getAsString(j
, k
));
1061 * Must return true if object is a possible event source
1063 bool DataCollectionTarget
::isEventSource()
1069 * Returns most critical status of DCI used for
1070 * status calculation
1072 int DataCollectionTarget
::getMostCriticalDCIStatus()
1075 lockDciAccess(false);
1076 for(int i
= 0; i
< m_dcObjects
->size(); i
++)
1078 DCObject
*curr
= m_dcObjects
->get(i
);
1079 if (curr
->isStatusDCO() && (curr
->getType() == DCO_TYPE_ITEM
) &&
1080 curr
->hasValue() && (curr
->getStatus() == ITEM_STATUS_ACTIVE
))
1082 if (getObjectClass() == OBJECT_CLUSTER
&& !curr
->isAggregateOnCluster())
1083 continue; // Calculated only on those that are agregated on cluster
1085 ItemValue
*value
= ((DCItem
*)curr
)->getInternalLastValue();
1086 if (value
!= NULL
&& (INT32
)*value
>= STATUS_NORMAL
&& (INT32
)*value
<= STATUS_CRITICAL
)
1087 status
= std
::max(status
, (INT32
)*value
);
1092 return (status
== -1) ? STATUS_UNKNOWN
: status
;
1096 * Calculate compound status
1098 void DataCollectionTarget
::calculateCompoundStatus(BOOL bForcedRecalc
)
1100 NetObj
::calculateCompoundStatus(bForcedRecalc
);
1104 * Returns last ping time
1106 UINT32 DataCollectionTarget
::getPingTime()
1108 if ((time(NULL
) - m_pingLastTimeStamp
) > g_dwStatusPollingInterval
)
1111 DbgPrintf(7, _T("DataCollectionTarget::getPingTime: update ping time is required! Last ping time %d."), m_pingLastTimeStamp
);
1119 void DataCollectionTarget
::updatePingData()
1121 m_pingLastTimeStamp
= 0;
1122 m_pingTime
= PING_TIME_TIMEOUT
;
1126 * Enter maintenance mode
1128 void DataCollectionTarget
::enterMaintenanceMode()
1130 DbgPrintf(4, _T("Entering maintenance mode for %s [%d]"), m_name
, m_id
);
1131 UINT64 eventId
= PostEvent2(EVENT_MAINTENANCE_MODE_ENTERED
, m_id
, NULL
);
1133 m_maintenanceMode
= true;
1134 m_maintenanceEventId
= eventId
;
1140 * Leave maintenance mode
1142 void DataCollectionTarget
::leaveMaintenanceMode()
1144 DbgPrintf(4, _T("Leaving maintenance mode for %s [%d]"), m_name
, m_id
);
1145 PostEvent(EVENT_MAINTENANCE_MODE_LEFT
, m_id
, NULL
);
1147 m_maintenanceMode
= false;
1148 m_maintenanceEventId
= 0;
1154 * Update cache size for given data collection item
1156 void DataCollectionTarget
::updateDCItemCacheSize(UINT32 dciId
, UINT32 conditionId
)
1158 lockDciAccess(false);
1159 DCObject
*dci
= getDCObjectById(dciId
, false);
1160 if ((dci
!= NULL
) && (dci
->getType() == DCO_TYPE_ITEM
))
1162 ((DCItem
*)dci
)->updateCacheSize(conditionId
);
1168 * Returns true if object is data collection target
1170 bool DataCollectionTarget
::isDataCollectionTarget()
1176 * Add data collection element to proxy info structure
1178 void DataCollectionTarget
::addProxyDataCollectionElement(ProxyInfo
*info
, const DCObject
*dco
)
1180 info
->msg
->setField(info
->fieldId
++, dco
->getId());
1181 info
->msg
->setField(info
->fieldId
++, (INT16
)dco
->getType());
1182 info
->msg
->setField(info
->fieldId
++, (INT16
)dco
->getDataSource());
1183 info
->msg
->setField(info
->fieldId
++, dco
->getName());
1184 info
->msg
->setField(info
->fieldId
++, (INT32
)dco
->getEffectivePollingInterval());
1185 info
->msg
->setFieldFromTime(info
->fieldId
++, dco
->getLastPollTime());
1186 info
->msg
->setField(info
->fieldId
++, m_guid
);
1187 info
->msg
->setField(info
->fieldId
++, dco
->getSnmpPort());
1188 if (dco
->getType() == DCO_TYPE_ITEM
)
1189 info
->msg
->setField(info
->fieldId
++, ((DCItem
*)dco
)->getSnmpRawValueType());
1191 info
->msg
->setField(info
->fieldId
++, (INT16
)0);
1197 * Add SNMP target to proxy info structure
1199 void DataCollectionTarget
::addProxySnmpTarget(ProxyInfo
*info
, const Node
*node
)
1201 info
->msg
->setField(info
->nodeInfoFieldId
++, m_guid
);
1202 info
->msg
->setField(info
->nodeInfoFieldId
++, node
->getIpAddress());
1203 info
->msg
->setField(info
->nodeInfoFieldId
++, node
->getSNMPVersion());
1204 info
->msg
->setField(info
->nodeInfoFieldId
++, node
->getSNMPPort());
1205 SNMP_SecurityContext
*snmpSecurity
= node
->getSnmpSecurityContext();
1206 info
->msg
->setField(info
->nodeInfoFieldId
++, (INT16
)snmpSecurity
->getAuthMethod());
1207 info
->msg
->setField(info
->nodeInfoFieldId
++, (INT16
)snmpSecurity
->getPrivMethod());
1208 info
->msg
->setFieldFromMBString(info
->nodeInfoFieldId
++, snmpSecurity
->getUser());
1209 info
->msg
->setFieldFromMBString(info
->nodeInfoFieldId
++, snmpSecurity
->getAuthPassword());
1210 info
->msg
->setFieldFromMBString(info
->nodeInfoFieldId
++, snmpSecurity
->getPrivPassword());
1211 delete snmpSecurity
;
1212 info
->nodeInfoFieldId
+= 41;
1213 info
->nodeInfoCount
++;
1217 * Collect info for SNMP proxy and DCI source (proxy) nodes
1218 * Default implementation adds only agent based DCIs with source node set to requesting node
1220 void DataCollectionTarget
::collectProxyInfo(ProxyInfo
*info
)
1222 lockDciAccess(false);
1223 for(int i
= 0; i
< m_dcObjects
->size(); i
++)
1225 DCObject
*dco
= m_dcObjects
->get(i
);
1226 if (dco
->getStatus() == ITEM_STATUS_DISABLED
)
1229 if ((dco
->getDataSource() == DS_NATIVE_AGENT
) && (dco
->getSourceNode() == info
->proxyId
) &&
1230 dco
->hasValue() && (dco
->getAgentCacheMode() == AGENT_CACHE_ON
))
1232 addProxyDataCollectionElement(info
, dco
);
1239 * Callback for colecting proxied SNMP DCIs
1241 void DataCollectionTarget
::collectProxyInfoCallback(NetObj
*object
, void *data
)
1243 ((DataCollectionTarget
*)object
)->collectProxyInfo((ProxyInfo
*)data
);
1247 * Get effective source node for given data collection object
1249 UINT32 DataCollectionTarget
::getEffectiveSourceNode(DCObject
*dco
)
1251 return dco
->getSourceNode();
1255 * Filter for selecting templates from objects
1257 static bool TemplateSelectionFilter(NetObj
*object
, void *userData
)
1259 return (object
->getObjectClass() == OBJECT_TEMPLATE
) && !object
->isDeleted() && ((Template
*)object
)->isAutoApplyEnabled();
1263 * Apply user templates
1265 void DataCollectionTarget
::applyUserTemplates()
1267 if (IsShutdownInProgress())
1270 ObjectArray
<NetObj
> *templates
= g_idxObjectById
.getObjects(true, TemplateSelectionFilter
);
1271 for(int i
= 0; i
< templates
->size(); i
++)
1273 Template
*pTemplate
= (Template
*)templates
->get(i
);
1274 AutoBindDecision decision
= pTemplate
->isApplicable(this);
1275 if (decision
== AutoBindDecision_Bind
)
1277 if (!pTemplate
->isChild(m_id
))
1279 DbgPrintf(4, _T("DataCollectionTarget::applyUserTemplates(): applying template %d \"%s\" to object %d \"%s\""),
1280 pTemplate
->getId(), pTemplate
->getName(), m_id
, m_name
);
1281 pTemplate
->applyToTarget(this);
1282 PostEvent(EVENT_TEMPLATE_AUTOAPPLY
, g_dwMgmtNode
, "isis", m_id
, m_name
, pTemplate
->getId(), pTemplate
->getName());
1285 else if (decision
== AutoBindDecision_Unbind
)
1287 if (pTemplate
->isAutoRemoveEnabled() && pTemplate
->isChild(m_id
))
1289 DbgPrintf(4, _T("DataCollectionTarget::applyUserTemplates(): removing template %d \"%s\" from object %d \"%s\""),
1290 pTemplate
->getId(), pTemplate
->getName(), m_id
, m_name
);
1291 pTemplate
->deleteChild(this);
1292 deleteParent(pTemplate
);
1293 pTemplate
->queueRemoveFromTarget(m_id
, true);
1294 PostEvent(EVENT_TEMPLATE_AUTOREMOVE
, g_dwMgmtNode
, "isis", m_id
, m_name
, pTemplate
->getId(), pTemplate
->getName());
1297 pTemplate
->decRefCount();
1303 * Filter for selecting containers from objects
1305 static bool ContainerSelectionFilter(NetObj
*object
, void *userData
)
1307 return (object
->getObjectClass() == OBJECT_CONTAINER
) && !object
->isDeleted() && ((Container
*)object
)->isAutoBindEnabled();
1311 * Update container membership
1313 void DataCollectionTarget
::updateContainerMembership()
1315 if (IsShutdownInProgress())
1318 ObjectArray
<NetObj
> *containers
= g_idxObjectById
.getObjects(true, ContainerSelectionFilter
);
1319 for(int i
= 0; i
< containers
->size(); i
++)
1321 Container
*pContainer
= (Container
*)containers
->get(i
);
1322 AutoBindDecision decision
= pContainer
->isSuitableForObject(this);
1323 if (decision
== AutoBindDecision_Bind
)
1325 if (!pContainer
->isChild(m_id
))
1327 DbgPrintf(4, _T("DataCollectionTarget::updateContainerMembership(): binding object %d \"%s\" to container %d \"%s\""),
1328 m_id
, m_name
, pContainer
->getId(), pContainer
->getName());
1329 pContainer
->addChild(this);
1330 addParent(pContainer
);
1331 PostEvent(EVENT_CONTAINER_AUTOBIND
, g_dwMgmtNode
, "isis", m_id
, m_name
, pContainer
->getId(), pContainer
->getName());
1332 pContainer
->calculateCompoundStatus();
1335 else if (decision
== AutoBindDecision_Unbind
)
1337 if (pContainer
->isAutoUnbindEnabled() && pContainer
->isChild(m_id
))
1339 DbgPrintf(4, _T("DataCollectionTarget::updateContainerMembership(): removing object %d \"%s\" from container %d \"%s\""),
1340 m_id
, m_name
, pContainer
->getId(), pContainer
->getName());
1341 pContainer
->deleteChild(this);
1342 deleteParent(pContainer
);
1343 PostEvent(EVENT_CONTAINER_AUTOUNBIND
, g_dwMgmtNode
, "isis", m_id
, m_name
, pContainer
->getId(), pContainer
->getName());
1344 pContainer
->calculateCompoundStatus();
1347 pContainer
->decRefCount();
1353 * Serialize object to JSON
1355 json_t
*DataCollectionTarget
::toJson()
1357 json_t
*root
= Template
::toJson();
1358 json_object_set_new(root
, "pingTime", json_integer(m_pingTime
));
1359 json_object_set_new(root
, "pingLastTimeStamp", json_integer(m_pingLastTimeStamp
));
1364 * Entry point for status poll worker thread
1366 void DataCollectionTarget
::statusPollWorkerEntry(PollerInfo
*poller
)
1368 statusPollWorkerEntry(poller
, NULL
, 0);
1372 * Entry point for status poll worker thread
1374 void DataCollectionTarget
::statusPollWorkerEntry(PollerInfo
*poller
, ClientSession
*session
, UINT32 rqId
)
1376 poller
->startExecution();
1377 statusPoll(poller
, session
, rqId
);
1382 * Entry point for second level status poll (called by parent object)
1384 void DataCollectionTarget
::statusPollPollerEntry(PollerInfo
*poller
, ClientSession
*session
, UINT32 rqId
)
1386 poller
->setStatus(_T("child poll"));
1387 statusPoll(poller
, session
, rqId
);
1391 * Perform status poll on this data collection target. Default implementation do nothing.
1393 void DataCollectionTarget
::statusPoll(PollerInfo
*poller
, ClientSession
*session
, UINT32 rqId
)
1398 * Entry point for configuration poll worker thread
1400 void DataCollectionTarget
::configurationPollWorkerEntry(PollerInfo
*poller
)
1402 configurationPollWorkerEntry(poller
, NULL
, 0);
1406 * Entry point for configuration poll worker thread
1408 void DataCollectionTarget
::configurationPollWorkerEntry(PollerInfo
*poller
, ClientSession
*session
, UINT32 rqId
)
1410 poller
->startExecution();
1411 ObjectTransactionStart();
1412 configurationPoll(poller
, session
, rqId
);
1413 ObjectTransactionEnd();
1418 * Perform configuration poll on this data collection target. Default implementation do nothing.
1420 void DataCollectionTarget
::configurationPoll(PollerInfo
*poller
, ClientSession
*session
, UINT32 rqId
)
1425 * Entry point for instance discovery poll worker thread
1427 void DataCollectionTarget
::instanceDiscoveryPollWorkerEntry(PollerInfo
*poller
)
1429 instanceDiscoveryPollWorkerEntry(poller
, NULL
, 0);
1433 * Entry point for instance discovery poll worker thread
1435 void DataCollectionTarget
::instanceDiscoveryPollWorkerEntry(PollerInfo
*poller
, ClientSession
*session
, UINT32 requestId
)
1437 poller
->startExecution();
1438 ObjectTransactionStart();
1439 instanceDiscoveryPoll(poller
, session
, requestId
);
1440 ObjectTransactionEnd();
1445 * Perform instance discovery poll on data collection target
1447 void DataCollectionTarget
::instanceDiscoveryPoll(PollerInfo
*poller
, ClientSession
*session
, UINT32 requestId
)
1449 if (m_runtimeFlags
& DCDF_DELETE_IN_PROGRESS
)
1452 m_runtimeFlags
&= ~DCDF_QUEUED_FOR_INSTANCE_POLL
;
1456 if (IsShutdownInProgress())
1459 poller
->setStatus(_T("wait for lock"));
1462 if (IsShutdownInProgress())
1468 m_pollRequestor
= session
;
1469 sendPollerMsg(requestId
, _T("Starting instance discovery poll for %s %s\r\n"), getObjectClassName(), m_name
);
1470 DbgPrintf(4, _T("Starting instance discovery poll for %s %s (ID: %d)"), getObjectClassName(), m_name
, m_id
);
1472 // Check if DataCollectionTarget is marked as unreachable
1473 if (!(m_state
& DCSF_UNREACHABLE
))
1475 poller
->setStatus(_T("instance discovery"));
1476 doInstanceDiscovery(requestId
);
1478 // Execute hook script
1479 poller
->setStatus(_T("hook"));
1480 executeHookScript(_T("InstancePoll"));
1484 sendPollerMsg(requestId
, POLLER_WARNING
_T("%s is marked as unreachable, instance discovery poll aborted\r\n"), getObjectClassName());
1485 DbgPrintf(4, _T("%s is marked as unreachable, instance discovery poll aborted"), getObjectClassName());
1488 m_lastInstancePoll
= time(NULL
);
1490 // Finish instance discovery poll
1491 poller
->setStatus(_T("cleanup"));
1493 m_runtimeFlags
&= ~DCDF_QUEUED_FOR_INSTANCE_POLL
;
1495 DbgPrintf(4, _T("Finished instance discovery poll for %s %s (ID: %d)"), getObjectClassName(), m_name
, m_id
);
1499 * Get list of instances for given data collection object. Default implementation always returns NULL.
1501 StringMap
*DataCollectionTarget
::getInstanceList(DCObject
*dco
)
1507 * Do instance discovery
1509 void DataCollectionTarget
::doInstanceDiscovery(UINT32 requestId
)
1511 sendPollerMsg(requestId
, _T("Running DCI instance discovery\r\n"));
1513 // collect instance discovery DCIs
1514 ObjectArray
<DCObject
> rootObjects
;
1515 lockDciAccess(false);
1516 for(int i
= 0; i
< m_dcObjects
->size(); i
++)
1518 DCObject
*object
= m_dcObjects
->get(i
);
1519 if (object
->getInstanceDiscoveryMethod() != IDM_NONE
)
1521 object
->setBusyFlag();
1522 rootObjects
.add(object
);
1527 // process instance discovery DCIs
1528 // it should be done that way to prevent DCI list lock for long time
1529 bool changed
= false;
1530 for(int i
= 0; i
< rootObjects
.size(); i
++)
1532 DCObject
*object
= rootObjects
.get(i
);
1533 DbgPrintf(5, _T("DataCollectionTarget::doInstanceDiscovery(%s [%u]): Updating instances for instance discovery DCO %s [%d]"),
1534 m_name
, m_id
, object
->getName(), object
->getId());
1535 sendPollerMsg(requestId
, _T(" Updating instances for %s [%d]\r\n"), object
->getName(), object
->getId());
1536 StringMap
*instances
= getInstanceList(object
);
1537 if (instances
!= NULL
)
1539 DbgPrintf(5, _T("DataCollectionTarget::doInstanceDiscovery(%s [%u]): read %d values"), m_name
, m_id
, instances
->size());
1540 object
->filterInstanceList(instances
);
1541 if (updateInstances(object
, instances
, requestId
))
1547 DbgPrintf(5, _T("DataCollectionTarget::doInstanceDiscovery(%s [%u]): failed to get instance list for DCO %s [%d]"),
1548 m_name
, m_id
, object
->getName(), object
->getId());
1549 sendPollerMsg(requestId
, POLLER_ERROR
_T(" Failed to get instance list\r\n"));
1551 object
->clearBusyFlag();
1555 onDataCollectionChange();
1559 * Callback for finding instance
1561 static EnumerationCallbackResult
FindInstanceCallback(const TCHAR
*key
, const void *value
, void *data
)
1563 return !_tcscmp((const TCHAR
*)data
, key
) ? _STOP
: _CONTINUE
;
1567 * Data for CreateInstanceDCI
1569 struct CreateInstanceDCOData
1572 DataCollectionTarget
*object
;
1577 * Callback for creating instance DCIs
1579 static EnumerationCallbackResult
CreateInstanceDCI(const TCHAR
*key
, const void *value
, void *data
)
1581 DataCollectionTarget
*object
= ((CreateInstanceDCOData
*)data
)->object
;
1582 DCObject
*root
= ((CreateInstanceDCOData
*)data
)->root
;
1584 DbgPrintf(5, _T("DataCollectionTarget::updateInstances(%s [%u], %s [%u]): creating new DCO for instance \"%s\""),
1585 object
->getName(), object
->getId(), root
->getName(), root
->getId(), key
);
1586 object
->sendPollerMsg(((CreateInstanceDCOData
*)data
)->requestId
, _T(" Creating new DCO for instance \"%s\"\r\n"), key
);
1588 DCObject
*dco
= root
->clone();
1590 dco
->setTemplateId(object
->getId(), root
->getId());
1591 dco
->setInstance((const TCHAR
*)value
);
1592 dco
->setInstanceDiscoveryMethod(IDM_NONE
);
1593 dco
->setInstanceDiscoveryData(key
);
1594 dco
->setInstanceFilter(NULL
);
1595 dco
->expandInstance();
1596 dco
->changeBinding(CreateUniqueId(IDG_ITEM
), object
, FALSE
);
1597 object
->addDCObject(dco
, true);
1602 * Update instance DCIs created from instance discovery DCI
1604 bool DataCollectionTarget
::updateInstances(DCObject
*root
, StringMap
*instances
, UINT32 requestId
)
1606 bool changed
= false;
1608 lockDciAccess(true);
1610 // Delete DCIs for missing instances and update existing
1611 IntegerArray
<UINT32
> deleteList
;
1612 for(int i
= 0; i
< m_dcObjects
->size(); i
++)
1614 DCObject
*object
= m_dcObjects
->get(i
);
1615 if ((object
->getTemplateId() != m_id
) || (object
->getTemplateItemId() != root
->getId()))
1618 const TCHAR
*dcoInstance
= object
->getInstanceDiscoveryData();
1619 if (instances
->forEach(FindInstanceCallback
, (void *)dcoInstance
) == _STOP
)
1621 // found, remove value from instances
1622 DbgPrintf(5, _T("DataCollectionTarget::updateInstances(%s [%u], %s [%u]): instance \"%s\" found"),
1623 m_name
, m_id
, root
->getName(), root
->getId(), dcoInstance
);
1624 const TCHAR
*name
= instances
->get(dcoInstance
);
1625 if (_tcscmp(name
, object
->getInstance()))
1627 object
->setInstance(name
);
1628 object
->updateFromTemplate(root
);
1631 instances
->remove(dcoInstance
);
1635 // not found, delete DCO
1636 DbgPrintf(5, _T("DataCollectionTarget::updateInstances(%s [%u], %s [%u]): instance \"%s\" not found, instance DCO will be deleted"),
1637 m_name
, m_id
, root
->getName(), root
->getId(), dcoInstance
);
1638 sendPollerMsg(requestId
, _T(" Existing instance \"%s\" not found and will be deleted\r\n"), dcoInstance
);
1639 deleteList
.add(object
->getId());
1644 for(int i
= 0; i
< deleteList
.size(); i
++)
1645 deleteDCObject(deleteList
.get(i
), false);
1647 // Create new instances
1648 if (instances
->size() > 0)
1650 CreateInstanceDCOData data
;
1653 data
.requestId
= requestId
;
1654 instances
->forEach(CreateInstanceDCI
, &data
);
1663 * Execute hook script
1665 * @param hookName hook name. Will find and excute script named Hook::hookName
1667 void DataCollectionTarget
::executeHookScript(const TCHAR
*hookName
)
1669 TCHAR scriptName
[MAX_PATH
] = _T("Hook::");
1670 nx_strncpy(&scriptName
[6], hookName
, MAX_PATH
- 6);
1671 NXSL_VM
*vm
= CreateServerScriptVM(scriptName
);
1674 DbgPrintf(7, _T("DataCollectionTarget::executeHookScript(%s [%u]): hook script \"%s\" not found"), m_name
, m_id
, scriptName
);
1678 vm
->setGlobalVariable(_T("$object"), createNXSLObject());
1681 DbgPrintf(4, _T("DataCollectionTarget::executeHookScript(%s [%u]): hook script \"%s\" execution error: %s"),
1682 m_name
, m_id
, scriptName
, vm
->getErrorText());