a973cb1a60219ba365a01a52cf09879fef971aa7
[public/netxms.git] / src / server / core / dcobject.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2017 Victor Kirhenshtein
4 **
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.
9 **
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.
14 **
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.
18 **
19 ** File: dcobject.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24
25 /**
26 * Default retention time for collected data
27 */
28 int DCObject::m_defaultRetentionTime = 30;
29
30 /**
31 * Default data collection polling interval
32 */
33 int DCObject::m_defaultPollingInterval = 60;
34
35 /**
36 * Default constructor for DCObject
37 */
38 DCObject::DCObject()
39 {
40 m_id = 0;
41 m_guid = uuid::generate();
42 m_dwTemplateId = 0;
43 m_dwTemplateItemId = 0;
44 m_busy = 0;
45 m_scheduledForDeletion = 0;
46 m_iPollingInterval = 3600;
47 m_iRetentionTime = 0;
48 m_source = DS_INTERNAL;
49 m_status = ITEM_STATUS_NOT_SUPPORTED;
50 m_name[0] = 0;
51 m_description[0] = 0;
52 m_systemTag[0] = 0;
53 m_tLastPoll = 0;
54 m_owner = NULL;
55 m_hMutex = MutexCreateRecursive();
56 m_schedules = NULL;
57 m_tLastCheck = 0;
58 m_flags = 0;
59 m_dwErrorCount = 0;
60 m_dwResourceId = 0;
61 m_sourceNode = 0;
62 m_pszPerfTabSettings = NULL;
63 m_snmpPort = 0; // use default
64 m_transformationScriptSource = NULL;
65 m_transformationScript = NULL;
66 m_comments = NULL;
67 m_pollingSession = NULL;
68 m_instanceDiscoveryMethod = IDM_NONE;
69 m_instanceDiscoveryData = NULL;
70 m_instanceFilterSource = NULL;
71 m_instanceFilter = NULL;
72 m_instance[0] = 0;
73 }
74
75 /**
76 * Create DCObject from another DCObject
77 */
78 DCObject::DCObject(const DCObject *pSrc)
79 {
80 m_id = pSrc->m_id;
81 m_guid = pSrc->m_guid;
82 m_dwTemplateId = pSrc->m_dwTemplateId;
83 m_dwTemplateItemId = pSrc->m_dwTemplateItemId;
84 m_busy = 0;
85 m_scheduledForDeletion = 0;
86 m_iPollingInterval = pSrc->m_iPollingInterval;
87 m_iRetentionTime = pSrc->m_iRetentionTime;
88 m_source = pSrc->m_source;
89 m_status = pSrc->m_status;
90 m_tLastPoll = 0;
91 _tcscpy(m_name, pSrc->m_name);
92 _tcscpy(m_description, pSrc->m_description);
93 _tcscpy(m_systemTag, pSrc->m_systemTag);
94 m_owner = NULL;
95 m_hMutex = MutexCreateRecursive();
96 m_tLastCheck = 0;
97 m_dwErrorCount = 0;
98 m_flags = pSrc->m_flags;
99 m_dwResourceId = pSrc->m_dwResourceId;
100 m_sourceNode = pSrc->m_sourceNode;
101 m_pszPerfTabSettings = (pSrc->m_pszPerfTabSettings != NULL) ? _tcsdup(pSrc->m_pszPerfTabSettings) : NULL;
102 m_snmpPort = pSrc->m_snmpPort;
103 m_comments = (pSrc->m_comments != NULL) ? _tcsdup(pSrc->m_comments) : NULL;
104 m_pollingSession = pSrc->m_pollingSession;
105
106 m_transformationScriptSource = NULL;
107 m_transformationScript = NULL;
108 setTransformationScript(pSrc->m_transformationScriptSource);
109
110 m_schedules = (pSrc->m_schedules != NULL) ? new StringList(pSrc->m_schedules) : NULL;
111
112 m_instanceDiscoveryMethod = pSrc->m_instanceDiscoveryMethod;
113 m_instanceDiscoveryData = (pSrc->m_instanceDiscoveryData != NULL) ? _tcsdup(pSrc->m_instanceDiscoveryData) : NULL;
114 m_instanceFilterSource = NULL;
115 m_instanceFilter = NULL;
116 setInstanceFilter(pSrc->m_instanceFilterSource);
117 _tcscpy(m_instance, pSrc->m_instance);
118 }
119
120 /**
121 * Constructor for creating new DCObject from scratch
122 */
123 DCObject::DCObject(UINT32 dwId, const TCHAR *szName, int iSource,
124 int iPollingInterval, int iRetentionTime, Template *pNode,
125 const TCHAR *pszDescription, const TCHAR *systemTag)
126 {
127 m_id = dwId;
128 m_guid = uuid::generate();
129 m_dwTemplateId = 0;
130 m_dwTemplateItemId = 0;
131 nx_strncpy(m_name, szName, MAX_ITEM_NAME);
132 if (pszDescription != NULL)
133 nx_strncpy(m_description, pszDescription, MAX_DB_STRING);
134 else
135 _tcscpy(m_description, m_name);
136 nx_strncpy(m_systemTag, CHECK_NULL_EX(systemTag), MAX_DB_STRING);
137 m_source = iSource;
138 m_iPollingInterval = iPollingInterval;
139 m_iRetentionTime = iRetentionTime;
140 m_status = ITEM_STATUS_ACTIVE;
141 m_busy = 0;
142 m_scheduledForDeletion = 0;
143 m_tLastPoll = 0;
144 m_owner = pNode;
145 m_hMutex = MutexCreateRecursive();
146 m_flags = 0;
147 m_schedules = NULL;
148 m_tLastCheck = 0;
149 m_dwErrorCount = 0;
150 m_dwResourceId = 0;
151 m_sourceNode = 0;
152 m_pszPerfTabSettings = NULL;
153 m_snmpPort = 0; // use default
154 m_transformationScriptSource = NULL;
155 m_transformationScript = NULL;
156 m_comments = NULL;
157 m_pollingSession = NULL;
158 m_instanceDiscoveryMethod = IDM_NONE;
159 m_instanceDiscoveryData = NULL;
160 m_instanceFilterSource = NULL;
161 m_instanceFilter = NULL;
162 m_instance[0] = 0;
163 }
164
165 /**
166 * Create DCObject from import file
167 */
168 DCObject::DCObject(ConfigEntry *config, Template *owner)
169 {
170 m_id = CreateUniqueId(IDG_ITEM);
171 m_guid = config->getSubEntryValueAsUUID(_T("guid"));
172 if (m_guid.isNull())
173 m_guid = uuid::generate();
174 m_dwTemplateId = 0;
175 m_dwTemplateItemId = 0;
176 nx_strncpy(m_name, config->getSubEntryValue(_T("name"), 0, _T("unnamed")), MAX_ITEM_NAME);
177 nx_strncpy(m_description, config->getSubEntryValue(_T("description"), 0, m_name), MAX_DB_STRING);
178 nx_strncpy(m_systemTag, config->getSubEntryValue(_T("systemTag"), 0, _T("")), MAX_DB_STRING);
179 m_source = (BYTE)config->getSubEntryValueAsInt(_T("origin"));
180 m_iPollingInterval = config->getSubEntryValueAsInt(_T("interval"));
181 m_iRetentionTime = config->getSubEntryValueAsInt(_T("retention"));
182 m_status = ITEM_STATUS_ACTIVE;
183 m_busy = 0;
184 m_scheduledForDeletion = 0;
185 m_flags = (UINT16)config->getSubEntryValueAsInt(_T("flags"));
186 m_tLastPoll = 0;
187 m_owner = owner;
188 m_hMutex = MutexCreateRecursive();
189 m_tLastCheck = 0;
190 m_dwErrorCount = 0;
191 m_dwResourceId = 0;
192 m_sourceNode = 0;
193 const TCHAR *perfTabSettings = config->getSubEntryValue(_T("perfTabSettings"));
194 m_pszPerfTabSettings = (perfTabSettings != NULL) ? _tcsdup(perfTabSettings) : NULL;
195 m_snmpPort = (WORD)config->getSubEntryValueAsInt(_T("snmpPort"));
196 m_schedules = NULL;
197
198 m_transformationScriptSource = NULL;
199 m_transformationScript = NULL;
200 m_comments = NULL;
201 m_pollingSession = NULL;
202 setTransformationScript(config->getSubEntryValue(_T("transformation")));
203
204 // for compatibility with old format
205 if (config->getSubEntryValueAsInt(_T("advancedSchedule")))
206 m_flags |= DCF_ADVANCED_SCHEDULE;
207
208 ConfigEntry *schedules = config->findEntry(_T("schedules"));
209 if (schedules != NULL)
210 schedules = schedules->findEntry(_T("schedule"));
211 if ((schedules != NULL) && (schedules->getValueCount() > 0))
212 {
213 m_schedules = new StringList();
214 int count = schedules->getValueCount();
215 for(int i = 0; i < count; i++)
216 {
217 m_schedules->add(schedules->getValue(i));
218 }
219 }
220
221 m_instanceDiscoveryMethod = (WORD)config->getSubEntryValueAsInt(_T("instanceDiscoveryMethod"));
222 const TCHAR *value = config->getSubEntryValue(_T("instanceDiscoveryData"));
223 m_instanceDiscoveryData = (value != NULL) ? _tcsdup(value) : NULL;
224 m_instanceFilterSource = NULL;
225 m_instanceFilter = NULL;
226 setInstanceFilter(config->getSubEntryValue(_T("instanceFilter")));
227 nx_strncpy(m_instance, config->getSubEntryValue(_T("instance"), 0, _T("")), MAX_DB_STRING);
228 }
229
230 /**
231 * Destructor
232 */
233 DCObject::~DCObject()
234 {
235 free(m_transformationScriptSource);
236 delete m_transformationScript;
237 delete m_schedules;
238 free(m_pszPerfTabSettings);
239 free(m_comments);
240 MutexDestroy(m_hMutex);
241 free(m_instanceDiscoveryData);
242 free(m_instanceFilterSource);
243 delete m_instanceFilter;
244 }
245
246 /**
247 * Load custom schedules from database
248 * (assumes that no schedules was created before this call)
249 */
250 bool DCObject::loadCustomSchedules(DB_HANDLE hdb)
251 {
252 if (!(m_flags & DCF_ADVANCED_SCHEDULE))
253 return true;
254
255 TCHAR query[256];
256
257 _sntprintf(query, 256, _T("SELECT schedule FROM dci_schedules WHERE item_id=%d"), m_id);
258 DB_RESULT hResult = DBSelect(hdb, query);
259 if (hResult != NULL)
260 {
261 int count = DBGetNumRows(hResult);
262 if (count > 0)
263 {
264 m_schedules = new StringList();
265 for(int i = 0; i < count; i++)
266 {
267 m_schedules->addPreallocated(DBGetField(hResult, i, 0, NULL, 0));
268 }
269 }
270 DBFreeResult(hResult);
271 }
272
273 return hResult != NULL;
274 }
275
276 /**
277 * Check if associated cluster resource is active. Returns true also if
278 * DCI has no resource association
279 */
280 bool DCObject::matchClusterResource()
281 {
282 Cluster *pCluster;
283
284 if ((m_dwResourceId == 0) || (m_owner->getObjectClass() != OBJECT_NODE))
285 return true;
286
287 pCluster = ((Node *)m_owner)->getMyCluster();
288 if (pCluster == NULL)
289 return false; // Has association, but cluster object cannot be found
290
291 return pCluster->isResourceOnNode(m_dwResourceId, m_owner->getId());
292 }
293
294 /**
295 * Expand macros in text
296 */
297 void DCObject::expandMacros(const TCHAR *src, TCHAR *dst, size_t dstLen)
298 {
299 int index = 0, index2;
300 String temp = src;
301 while((index = temp.find(_T("%{"), index)) != String::npos)
302 {
303 String head = temp.substring(0, index);
304 index2 = temp.find(_T("}"), index);
305 if (index2 == String::npos)
306 break; // Missing closing }
307
308 String rest = temp.substring(index2 + 1, -1);
309 String macro = temp.substring(index + 2, index2 - index - 2);
310 macro.trim();
311
312 temp = head;
313 if (!_tcscmp(macro, _T("node_id")))
314 {
315 if (m_owner != NULL)
316 {
317 temp.appendFormattedString(_T("%d"), m_owner->getId());
318 }
319 else
320 {
321 temp += _T("(error)");
322 }
323 }
324 else if (!_tcscmp(macro, _T("node_name")))
325 {
326 if (m_owner != NULL)
327 {
328 temp += m_owner->getName();
329 }
330 else
331 {
332 temp += _T("(error)");
333 }
334 }
335 else if (!_tcscmp(macro, _T("node_primary_ip")))
336 {
337 if ((m_owner != NULL) && (m_owner->getObjectClass() == OBJECT_NODE))
338 {
339 TCHAR ipAddr[64];
340 temp += ((Node *)m_owner)->getIpAddress().toString(ipAddr);
341 }
342 else
343 {
344 temp += _T("(error)");
345 }
346 }
347 else if (!_tcsncmp(macro, _T("script:"), 7))
348 {
349 NXSL_VM *vm = CreateServerScriptVM(&macro[7]);
350 if (vm != NULL)
351 {
352 if (m_owner != NULL)
353 vm->setGlobalVariable(_T("$node"), new NXSL_Value(new NXSL_Object(&g_nxslNodeClass, m_owner)));
354
355 if (vm->run(0, NULL))
356 {
357 NXSL_Value *result = vm->getResult();
358 if (result != NULL)
359 temp += CHECK_NULL_EX(result->getValueAsCString());
360 DbgPrintf(4, _T("DCObject::expandMacros(%d,\"%s\"): Script %s executed successfully"), m_id, src, &macro[7]);
361 }
362 else
363 {
364 DbgPrintf(4, _T("DCObject::expandMacros(%d,\"%s\"): Script %s execution error: %s"),
365 m_id, src, &macro[7], vm->getErrorText());
366 PostEvent(EVENT_SCRIPT_ERROR, g_dwMgmtNode, "ssd", &macro[7], vm->getErrorText(), m_id);
367 }
368 delete vm;
369 }
370 else
371 {
372 DbgPrintf(4, _T("DCObject::expandMacros(%d,\"%s\"): Cannot find script %s"), m_id, src, &macro[7]);
373 }
374 }
375 temp.append(rest);
376 }
377 nx_strncpy(dst, temp, dstLen);
378 }
379
380 /**
381 * Delete all collected data
382 */
383 bool DCObject::deleteAllData()
384 {
385 return false;
386 }
387
388 /**
389 * Add schedule
390 */
391 void DCObject::addSchedule(const TCHAR *pszSchedule)
392 {
393 if (m_schedules == NULL)
394 m_schedules = new StringList();
395 m_schedules->add(pszSchedule);
396 }
397
398 /**
399 * Set new ID and node/template association
400 */
401 void DCObject::changeBinding(UINT32 dwNewId, Template *newOwner, BOOL doMacroExpansion)
402 {
403 lock();
404 m_owner = newOwner;
405 if (dwNewId != 0)
406 {
407 m_id = dwNewId;
408 m_guid = uuid::generate();
409 }
410
411 if (doMacroExpansion)
412 {
413 expandMacros(m_name, m_name, MAX_ITEM_NAME);
414 expandMacros(m_description, m_description, MAX_DB_STRING);
415 expandMacros(m_instance, m_instance, MAX_DB_STRING);
416 }
417
418 unlock();
419 }
420
421 /**
422 * Set DCI status
423 */
424 void DCObject::setStatus(int status, bool generateEvent)
425 {
426 if (generateEvent && (m_owner != NULL) && (m_status != (BYTE)status) && IsEventSource(m_owner->getObjectClass()))
427 {
428 static UINT32 eventCode[3] = { EVENT_DCI_ACTIVE, EVENT_DCI_DISABLED, EVENT_DCI_UNSUPPORTED };
429 static const TCHAR *originName[8] = { _T("Internal"), _T("NetXMS Agent"), _T("SNMP"), _T("CheckPoint SNMP"), _T("Push"), _T("WinPerf"), _T("iLO"), _T("Script") };
430 PostEvent(eventCode[status], m_owner->getId(), "dssds", m_id, m_name, m_description, m_source, originName[m_source]);
431 }
432 m_status = (BYTE)status;
433 }
434
435 /**
436 * Match schedule to current time
437 */
438 bool DCObject::matchSchedule(const TCHAR *schedule, bool *withSeconds, struct tm *currLocalTime, time_t currTimestamp)
439 {
440 TCHAR szValue[256], expandedSchedule[1024];
441 const TCHAR *realSchedule = schedule;
442
443 if (_tcslen(schedule) > 4 && !_tcsncmp(schedule, _T("%["), 2))
444 {
445 TCHAR *scriptName = _tcsdup(schedule + 2);
446 if (scriptName != NULL)
447 {
448 bool success = false;
449 TCHAR *closingBracker = _tcschr(scriptName, _T(']'));
450 if (closingBracker != NULL)
451 {
452 *closingBracker = 0;
453
454 NXSL_VM *vm = CreateServerScriptVM(scriptName);
455 if (vm != NULL)
456 {
457 vm->setGlobalVariable(_T("$node"), new NXSL_Value(new NXSL_Object(&g_nxslNodeClass, m_owner)));
458 vm->setGlobalVariable(_T("$dci"), createNXSLObject());
459 if (vm->run(0, NULL))
460 {
461 NXSL_Value *result = vm->getResult();
462 if (result != NULL)
463 {
464 const TCHAR *temp = result->getValueAsCString();
465 if (temp != NULL)
466 {
467 DbgPrintf(7, _T("DCObject::matchSchedule(%%[%s]) expanded to \"%s\""), scriptName, temp);
468 nx_strncpy(expandedSchedule, temp, 1024);
469 realSchedule = expandedSchedule;
470 success = true;
471 }
472 }
473 }
474 else
475 {
476 DbgPrintf(4, _T("DCObject::matchSchedule(%%[%s]) script execution failed (%s)"), scriptName, vm->getErrorText());
477 }
478 delete vm;
479 }
480 }
481 else
482 {
483 DbgPrintf(4, _T("DCObject::matchSchedule: invalid script schedule syntax in %d [%s]"), m_id, m_name);
484 }
485 free(scriptName);
486 if (!success)
487 return false;
488 }
489 else
490 {
491 DbgPrintf(4, _T("DCObject::matchSchedule: invalid script schedule syntax in %d [%s]"), m_id, m_name);
492 return false;
493 }
494 }
495
496 // Minute
497 const TCHAR *pszCurr = ExtractWord(realSchedule, szValue);
498 if (!MatchScheduleElement(szValue, currLocalTime->tm_min, 59, currLocalTime, currTimestamp))
499 return false;
500
501 // Hour
502 pszCurr = ExtractWord(pszCurr, szValue);
503 if (!MatchScheduleElement(szValue, currLocalTime->tm_hour, 23, currLocalTime, currTimestamp))
504 return false;
505
506 // Day of month
507 pszCurr = ExtractWord(pszCurr, szValue);
508 if (!MatchScheduleElement(szValue, currLocalTime->tm_mday, GetLastMonthDay(currLocalTime), currLocalTime, currTimestamp))
509 return false;
510
511 // Month
512 pszCurr = ExtractWord(pszCurr, szValue);
513 if (!MatchScheduleElement(szValue, currLocalTime->tm_mon + 1, 12, currLocalTime, currTimestamp))
514 return false;
515
516 // Day of week
517 pszCurr = ExtractWord(pszCurr, szValue);
518 for(int i = 0; szValue[i] != 0; i++)
519 if (szValue[i] == _T('7'))
520 szValue[i] = _T('0');
521 if (!MatchScheduleElement(szValue, currLocalTime->tm_wday, 7, currLocalTime, currTimestamp))
522 return false;
523
524 // Seconds
525 szValue[0] = _T('\0');
526 ExtractWord(pszCurr, szValue);
527 if (szValue[0] != _T('\0'))
528 {
529 if (withSeconds != NULL)
530 *withSeconds = true;
531 return MatchScheduleElement(szValue, currLocalTime->tm_sec, 59, currLocalTime, currTimestamp);
532 }
533
534 return true;
535 }
536
537 /**
538 * Check if data collection object have to be polled
539 */
540 bool DCObject::isReadyForPolling(time_t currTime)
541 {
542 // Normally data collection object will be locked when it is being
543 // changed or when it is processing new data
544 // In both cases there is no point to block item poller and wait, it
545 // is more effective to try schedule on next run
546 if (!tryLock())
547 {
548 nxlog_debug(3, _T("DCObject::isReadyForPolling: cannot obtain lock for data collection object %d"), m_id);
549 return false;
550 }
551
552 if ((m_pollingSession != NULL) && !m_busy)
553 {
554 if ((m_status != ITEM_STATUS_DISABLED) &&
555 isCacheLoaded() && (m_source != DS_PUSH_AGENT) &&
556 matchClusterResource() && hasValue() && (getAgentCacheMode() == AGENT_CACHE_OFF))
557 {
558 unlock();
559 return true;
560 }
561 else
562 {
563 // DCI cannot be force polled at the moment, clear force poll request
564 nxlog_debug(6, _T("Forced poll of DC object %s [%d] on node %s [%d] cancelled"), m_name, m_id, m_owner->getName(), m_owner->getId());
565 m_pollingSession->decRefCount();
566 m_pollingSession = NULL;
567 unlock();
568 return false;
569 }
570 }
571
572 bool result;
573 if ((m_status != ITEM_STATUS_DISABLED) && (!m_busy) &&
574 isCacheLoaded() && (m_source != DS_PUSH_AGENT) &&
575 matchClusterResource() && hasValue() && (getAgentCacheMode() == AGENT_CACHE_OFF))
576 {
577 if (m_flags & DCF_ADVANCED_SCHEDULE)
578 {
579 if (m_schedules != NULL)
580 {
581 struct tm tmCurrLocal, tmLastLocal;
582 #if HAVE_LOCALTIME_R
583 localtime_r(&currTime, &tmCurrLocal);
584 localtime_r(&m_tLastCheck, &tmLastLocal);
585 #else
586 memcpy(&tmCurrLocal, localtime(&currTime), sizeof(struct tm));
587 memcpy(&tmLastLocal, localtime(&m_tLastCheck), sizeof(struct tm));
588 #endif
589 result = false;
590 for(int i = 0; i < m_schedules->size(); i++)
591 {
592 bool withSeconds = false;
593 if (matchSchedule(m_schedules->get(i), &withSeconds, &tmCurrLocal, currTime))
594 {
595 // TODO: do we have to take care about the schedules with seconds
596 // that trigger polling too often?
597 if (withSeconds || (currTime - m_tLastCheck >= 60) || (tmCurrLocal.tm_min != tmLastLocal.tm_min))
598 {
599 result = true;
600 break;
601 }
602 }
603 }
604 }
605 else
606 {
607 result = false;
608 }
609 m_tLastCheck = currTime;
610 }
611 else
612 {
613 if (m_status == ITEM_STATUS_NOT_SUPPORTED)
614 result = (m_tLastPoll + getEffectivePollingInterval() * 10 <= currTime);
615 else
616 result = (m_tLastPoll + getEffectivePollingInterval() <= currTime);
617 }
618 }
619 else
620 {
621 result = false;
622 }
623 unlock();
624 return result;
625 }
626
627 /**
628 * Returns true if internal cache is loaded. If data collection object
629 * does not have cache should return true
630 */
631 bool DCObject::isCacheLoaded()
632 {
633 return true;
634 }
635
636 /**
637 * Prepare object for deletion
638 */
639 bool DCObject::prepareForDeletion()
640 {
641 DbgPrintf(9, _T("DCObject::prepareForDeletion for DCO %d"), m_id);
642
643 lock();
644 m_status = ITEM_STATUS_DISABLED; // Prevent future polls
645 m_scheduledForDeletion = 1;
646 bool canDelete = (m_busy ? false : true);
647 unlock();
648 DbgPrintf(9, _T("DCObject::prepareForDeletion: completed for DCO %d, canDelete=%d"), m_id, (int)canDelete);
649
650 return canDelete;
651 }
652
653 /**
654 * Create NXCP message with object data
655 */
656 void DCObject::createMessage(NXCPMessage *pMsg)
657 {
658 lock();
659 pMsg->setField(VID_DCI_ID, m_id);
660 pMsg->setField(VID_DCOBJECT_TYPE, (WORD)getType());
661 pMsg->setField(VID_TEMPLATE_ID, m_dwTemplateId);
662 pMsg->setField(VID_NAME, m_name);
663 pMsg->setField(VID_DESCRIPTION, m_description);
664 pMsg->setField(VID_TRANSFORMATION_SCRIPT, CHECK_NULL_EX(m_transformationScriptSource));
665 pMsg->setField(VID_FLAGS, m_flags);
666 pMsg->setField(VID_SYSTEM_TAG, m_systemTag);
667 pMsg->setField(VID_POLLING_INTERVAL, (UINT32)m_iPollingInterval);
668 pMsg->setField(VID_RETENTION_TIME, (UINT32)m_iRetentionTime);
669 pMsg->setField(VID_DCI_SOURCE_TYPE, (WORD)m_source);
670 pMsg->setField(VID_DCI_STATUS, (WORD)m_status);
671 pMsg->setField(VID_RESOURCE_ID, m_dwResourceId);
672 pMsg->setField(VID_AGENT_PROXY, m_sourceNode);
673 pMsg->setField(VID_SNMP_PORT, m_snmpPort);
674 if (m_comments != NULL)
675 pMsg->setField(VID_COMMENTS, m_comments);
676 if (m_pszPerfTabSettings != NULL)
677 pMsg->setField(VID_PERFTAB_SETTINGS, m_pszPerfTabSettings);
678 if (m_schedules != NULL)
679 {
680 pMsg->setField(VID_NUM_SCHEDULES, (UINT32)m_schedules->size());
681 UINT32 fieldId = VID_DCI_SCHEDULE_BASE;
682 for(int i = 0; i < m_schedules->size(); i++, fieldId++)
683 pMsg->setField(fieldId, m_schedules->get(i));
684 }
685 else
686 {
687 pMsg->setField(VID_NUM_SCHEDULES, (UINT32)0);
688 }
689 pMsg->setField(VID_INSTD_METHOD, m_instanceDiscoveryMethod);
690 if (m_instanceDiscoveryData != NULL)
691 pMsg->setField(VID_INSTD_DATA, m_instanceDiscoveryData);
692 if (m_instanceFilterSource != NULL)
693 pMsg->setField(VID_INSTD_FILTER, m_instanceFilterSource);
694 pMsg->setField(VID_INSTANCE, m_instance);
695 unlock();
696 }
697
698 /**
699 * Update data collection object from NXCP message
700 */
701 void DCObject::updateFromMessage(NXCPMessage *pMsg)
702 {
703 lock();
704
705 pMsg->getFieldAsString(VID_NAME, m_name, MAX_ITEM_NAME);
706 pMsg->getFieldAsString(VID_DESCRIPTION, m_description, MAX_DB_STRING);
707 pMsg->getFieldAsString(VID_SYSTEM_TAG, m_systemTag, MAX_DB_STRING);
708 m_flags = pMsg->getFieldAsUInt16(VID_FLAGS);
709 m_source = (BYTE)pMsg->getFieldAsUInt16(VID_DCI_SOURCE_TYPE);
710 m_iPollingInterval = pMsg->getFieldAsUInt32(VID_POLLING_INTERVAL);
711 m_iRetentionTime = pMsg->getFieldAsUInt32(VID_RETENTION_TIME);
712 setStatus(pMsg->getFieldAsUInt16(VID_DCI_STATUS), true);
713 m_dwResourceId = pMsg->getFieldAsUInt32(VID_RESOURCE_ID);
714 m_sourceNode = pMsg->getFieldAsUInt32(VID_AGENT_PROXY);
715 safe_free(m_pszPerfTabSettings);
716 m_pszPerfTabSettings = pMsg->getFieldAsString(VID_PERFTAB_SETTINGS);
717 m_snmpPort = pMsg->getFieldAsUInt16(VID_SNMP_PORT);
718 TCHAR *pszStr = pMsg->getFieldAsString(VID_TRANSFORMATION_SCRIPT);
719 safe_free_and_null(m_comments);
720 m_comments = pMsg->getFieldAsString(VID_COMMENTS);
721 setTransformationScript(pszStr);
722 safe_free(pszStr);
723
724 // Update schedules
725 int count = pMsg->getFieldAsInt32(VID_NUM_SCHEDULES);
726 if (count > 0)
727 {
728 if (m_schedules != NULL)
729 m_schedules->clear();
730 else
731 m_schedules = new StringList();
732
733 UINT32 fieldId = VID_DCI_SCHEDULE_BASE;
734 for(int i = 0; i < count; i++, fieldId++)
735 {
736 TCHAR *s = pMsg->getFieldAsString(fieldId);
737 if (s != NULL)
738 {
739 m_schedules->addPreallocated(s);
740 }
741 }
742 }
743 else
744 {
745 delete_and_null(m_schedules);
746 }
747
748 m_instanceDiscoveryMethod = pMsg->getFieldAsUInt16(VID_INSTD_METHOD);
749
750 safe_free(m_instanceDiscoveryData);
751 m_instanceDiscoveryData = pMsg->getFieldAsString(VID_INSTD_DATA);
752
753 pszStr = pMsg->getFieldAsString(VID_INSTD_FILTER);
754 setInstanceFilter(pszStr);
755 safe_free(pszStr);
756 pMsg->getFieldAsString(VID_INSTANCE, m_instance, MAX_DB_STRING);
757
758 unlock();
759 }
760
761 /**
762 * Save to database
763 */
764 bool DCObject::saveToDatabase(DB_HANDLE hdb)
765 {
766 TCHAR query[1024];
767
768 lock();
769
770 // Save schedules
771 _sntprintf(query, 1024, _T("DELETE FROM dci_schedules WHERE item_id=%d"), (int)m_id);
772 bool success = DBQuery(hdb, query);
773 if (success && (m_schedules != NULL))
774 {
775 for(int i = 0; i < m_schedules->size(); i++)
776 {
777 _sntprintf(query, 1024, _T("INSERT INTO dci_schedules (item_id,schedule_id,schedule) VALUES (%d,%d,%s)"),
778 m_id, i + 1, (const TCHAR *)DBPrepareString(hdb, m_schedules->get(i)));
779 success = DBQuery(hdb, query);
780 if (!success)
781 break;
782 }
783 }
784
785 unlock();
786
787 return success;
788 }
789
790 /**
791 * Delete object and collected data from database
792 */
793 void DCObject::deleteFromDatabase()
794 {
795 TCHAR query[256];
796 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("DELETE FROM dci_schedules WHERE item_id=%d"), (int)m_id);
797 QueueSQLRequest(query);
798 }
799
800 /**
801 * Load data collection object thresholds from database
802 */
803 bool DCObject::loadThresholdsFromDB(DB_HANDLE hdb)
804 {
805 return true;
806 }
807
808 /**
809 * Expand {instance} macro in name and description
810 */
811 void DCObject::expandInstance()
812 {
813 String temp = m_name;
814 temp.replace(_T("{instance}"), m_instanceDiscoveryData);
815 temp.replace(_T("{instance-name}"), m_instance);
816 nx_strncpy(m_name, (const TCHAR *)temp, MAX_ITEM_NAME);
817
818 temp = m_description;
819 temp.replace(_T("{instance}"), m_instanceDiscoveryData);
820 temp.replace(_T("{instance-name}"), m_instance);
821 nx_strncpy(m_description, (const TCHAR *)temp, MAX_DB_STRING);
822 }
823
824 /**
825 * Update DC object from template object
826 */
827 void DCObject::updateFromTemplate(DCObject *src)
828 {
829 lock();
830
831 expandMacros(src->m_name, m_name, MAX_ITEM_NAME);
832 expandMacros(src->m_description, m_description, MAX_DB_STRING);
833 expandMacros(src->m_systemTag, m_systemTag, MAX_DB_STRING);
834
835 m_iPollingInterval = src->m_iPollingInterval;
836 m_iRetentionTime = src->m_iRetentionTime;
837 m_source = src->m_source;
838 setStatus(src->m_status, true);
839 m_flags = src->m_flags;
840 m_sourceNode = src->m_sourceNode;
841 m_dwResourceId = src->m_dwResourceId;
842 m_snmpPort = src->m_snmpPort;
843
844 free(m_pszPerfTabSettings);
845 m_pszPerfTabSettings = _tcsdup_ex(src->m_pszPerfTabSettings);
846
847 setTransformationScript(src->m_transformationScriptSource);
848
849 // Copy schedules
850 delete m_schedules;
851 m_schedules = (src->m_schedules != NULL) ? new StringList(src->m_schedules) : NULL;
852
853 if ((src->getInstanceDiscoveryMethod() != IDM_NONE) && (m_instanceDiscoveryMethod == IDM_NONE))
854 {
855 expandInstance();
856 }
857 else
858 {
859 expandMacros(src->m_instance, m_instance, MAX_DB_STRING);
860 m_instanceDiscoveryMethod = src->m_instanceDiscoveryMethod;
861 free(m_instanceDiscoveryData);
862 m_instanceDiscoveryData = _tcsdup_ex(src->m_instanceDiscoveryData);
863 safe_free_and_null(m_instanceFilterSource);
864 delete_and_null(m_instanceFilter);
865 setInstanceFilter(src->m_instanceFilterSource);
866 }
867
868 unlock();
869 }
870
871 /**
872 * Process new collected value. Should return true on success.
873 * If returns false, current poll result will be converted into data collection error.
874 *
875 * @return true on success
876 */
877 bool DCObject::processNewValue(time_t nTimeStamp, const void *value, bool *updateStatus)
878 {
879 *updateStatus = false;
880 return false;
881 }
882
883 /**
884 * Process new data collection error
885 */
886 void DCObject::processNewError(bool noInstance)
887 {
888 time_t now = time(NULL);
889 processNewError(noInstance, now);
890 }
891
892 /**
893 * Process new data collection error
894 */
895 void DCObject::processNewError(bool noInstance, time_t now)
896 {
897 }
898
899 /**
900 * Should return true if object has (or can have) value
901 */
902 bool DCObject::hasValue()
903 {
904 if ((m_owner != NULL) && (m_owner->getObjectClass() == OBJECT_CLUSTER))
905 return isAggregateOnCluster() && (m_instanceDiscoveryMethod == IDM_NONE);
906 return m_instanceDiscoveryMethod == IDM_NONE;
907 }
908
909 /**
910 * Set new transformation script
911 */
912 void DCObject::setTransformationScript(const TCHAR *source)
913 {
914 free(m_transformationScriptSource);
915 delete m_transformationScript;
916 if (source != NULL)
917 {
918 m_transformationScriptSource = _tcsdup(source);
919 StrStrip(m_transformationScriptSource);
920 if (m_transformationScriptSource[0] != 0)
921 {
922 TCHAR errorText[1024];
923 m_transformationScript = NXSLCompile(m_transformationScriptSource, errorText, 1024, NULL);
924 if (m_transformationScript == NULL)
925 {
926 nxlog_write(MSG_TRANSFORMATION_SCRIPT_COMPILATION_ERROR, NXLOG_WARNING, "dsdss",
927 getOwnerId(), getOwnerName(), m_id, m_name, errorText);
928 }
929 }
930 else
931 {
932 m_transformationScript = NULL;
933 }
934 }
935 else
936 {
937 m_transformationScriptSource = NULL;
938 m_transformationScript = NULL;
939 }
940 }
941
942 /**
943 * Get actual agent cache mode
944 */
945 INT16 DCObject::getAgentCacheMode()
946 {
947 if ((m_source != DS_NATIVE_AGENT) && (m_source != DS_SNMP_AGENT))
948 return AGENT_CACHE_OFF;
949
950 Node *node = NULL;
951 if (m_sourceNode != 0)
952 {
953 node = (Node *)FindObjectById(m_sourceNode, OBJECT_NODE);
954 }
955 else
956 {
957 if (m_owner->getObjectClass() == OBJECT_NODE)
958 {
959 node = (Node *)m_owner;
960 }
961 else if (m_owner->getObjectClass() == OBJECT_CHASSIS)
962 {
963 node = (Node *)FindObjectById(((Chassis *)m_owner)->getControllerId(), OBJECT_NODE);
964 }
965 }
966 if (node == NULL)
967 return AGENT_CACHE_OFF;
968
969 if ((m_source == DS_SNMP_AGENT) && (node->getEffectiveSnmpProxy() == 0))
970 return AGENT_CACHE_OFF;
971
972 INT16 mode = DCF_GET_CACHE_MODE(m_flags);
973 if (mode != AGENT_CACHE_DEFAULT)
974 return mode;
975 return node->getAgentCacheMode();
976 }
977
978 /**
979 * Create DCObject from import file
980 */
981 void DCObject::updateFromImport(ConfigEntry *config)
982 {
983 lock();
984 nx_strncpy(m_name, config->getSubEntryValue(_T("name"), 0, _T("unnamed")), MAX_ITEM_NAME);
985 nx_strncpy(m_description, config->getSubEntryValue(_T("description"), 0, m_name), MAX_DB_STRING);
986 nx_strncpy(m_systemTag, config->getSubEntryValue(_T("systemTag"), 0, _T("")), MAX_DB_STRING);
987 m_source = (BYTE)config->getSubEntryValueAsInt(_T("origin"));
988 m_iPollingInterval = config->getSubEntryValueAsInt(_T("interval"));
989 m_iRetentionTime = config->getSubEntryValueAsInt(_T("retention"));
990 m_flags = (UINT16)config->getSubEntryValueAsInt(_T("flags"));
991 const TCHAR *perfTabSettings = config->getSubEntryValue(_T("perfTabSettings"));
992 safe_free(m_pszPerfTabSettings);
993 m_pszPerfTabSettings = _tcsdup_ex(perfTabSettings);
994 m_snmpPort = (WORD)config->getSubEntryValueAsInt(_T("snmpPort"));
995
996 setTransformationScript(config->getSubEntryValue(_T("transformation")));
997
998 ConfigEntry *schedules = config->findEntry(_T("schedules"));
999 if (schedules != NULL)
1000 schedules = schedules->findEntry(_T("schedule"));
1001 if ((schedules != NULL) && (schedules->getValueCount() > 0))
1002 {
1003 if (m_schedules != NULL)
1004 m_schedules->clear();
1005 else
1006 m_schedules = new StringList();
1007
1008 int count = schedules->getValueCount();
1009 for(int i = 0; i < count; i++)
1010 {
1011 m_schedules->add(schedules->getValue(i));
1012 }
1013 }
1014 else
1015 {
1016 delete_and_null(m_schedules);
1017 }
1018
1019 m_instanceDiscoveryMethod = (WORD)config->getSubEntryValueAsInt(_T("instanceDiscoveryMethod"));
1020 const TCHAR *value = config->getSubEntryValue(_T("instanceDiscoveryData"));
1021 safe_free(m_instanceDiscoveryData);
1022 m_instanceDiscoveryData = _tcsdup_ex(value);
1023 setInstanceFilter(config->getSubEntryValue(_T("instanceFilter")));
1024 nx_strncpy(m_instance, config->getSubEntryValue(_T("instance"), 0, _T("")), MAX_DB_STRING);
1025
1026 unlock();
1027 }
1028
1029 /**
1030 * Get owner ID
1031 */
1032 UINT32 DCObject::getOwnerId() const
1033 {
1034 return (m_owner != NULL) ? m_owner->getId() : 0;
1035 }
1036
1037 /**
1038 * Get owner name
1039 */
1040 const TCHAR *DCObject::getOwnerName() const
1041 {
1042 return (m_owner != NULL) ? m_owner->getName() : _T("(null)");
1043 }
1044
1045 /**
1046 * Create NXSL object for this data collection object
1047 */
1048 NXSL_Value *DCObject::createNXSLObject()
1049 {
1050 return new NXSL_Value(new NXSL_Object(&g_nxslDciClass, new DCObjectInfo(this)));
1051 }
1052
1053 /**
1054 * Process force poll request
1055 */
1056 ClientSession *DCObject::processForcePoll()
1057 {
1058 lock();
1059 ClientSession *session = m_pollingSession;
1060 m_pollingSession = NULL;
1061 unlock();
1062 return session;
1063 }
1064
1065 /**
1066 * Request force poll
1067 */
1068 void DCObject::requestForcePoll(ClientSession *session)
1069 {
1070 lock();
1071 if (m_pollingSession != NULL)
1072 m_pollingSession->decRefCount();
1073 m_pollingSession = session;
1074 m_pollingSession->incRefCount();
1075 unlock();
1076 }
1077
1078 /**
1079 * Filter callback data
1080 */
1081 struct FilterCallbackData
1082 {
1083 StringMap *filteredInstances;
1084 DCObject *dco;
1085 NXSL_VM *instanceFilter;
1086 };
1087
1088 /**
1089 * Callback for filtering instances
1090 */
1091 static EnumerationCallbackResult FilterCallback(const TCHAR *key, const void *value, void *data)
1092 {
1093 NXSL_VM *instanceFilter = ((FilterCallbackData *)data)->instanceFilter;
1094 DCObject *dco = ((FilterCallbackData *)data)->dco;
1095
1096 instanceFilter->setGlobalVariable(_T("$object"), dco->getOwner()->createNXSLObject());
1097 instanceFilter->setGlobalVariable(_T("$targetObject"), dco->getOwner()->createNXSLObject());
1098 if (dco->getOwner()->getObjectClass() == OBJECT_NODE)
1099 instanceFilter->setGlobalVariable(_T("$node"), dco->getOwner()->createNXSLObject());
1100 instanceFilter->setGlobalVariable(_T("$dci"), dco->createNXSLObject());
1101 if (dco->getSourceNode() != 0)
1102 {
1103 Node *sourceNode = (Node *)FindObjectById(dco->getSourceNode(), OBJECT_NODE);
1104 if (sourceNode != NULL)
1105 instanceFilter->setGlobalVariable(_T("$sourceNode"), sourceNode->createNXSLObject());
1106 }
1107
1108 NXSL_Value *argv[2];
1109 argv[0] = new NXSL_Value(key);
1110 argv[1] = new NXSL_Value((const TCHAR *)value);
1111
1112 if (instanceFilter->run(2, argv))
1113 {
1114 bool accepted;
1115 const TCHAR *instance = key;
1116 const TCHAR *name = (const TCHAR *)value;
1117 NXSL_Value *result = instanceFilter->getResult();
1118 if (result != NULL)
1119 {
1120 if (result->isArray())
1121 {
1122 NXSL_Array *array = result->getValueAsArray();
1123 if (array->size() > 0)
1124 {
1125 accepted = array->get(0)->getValueAsInt32() ? true : false;
1126 if (accepted && (array->size() > 1))
1127 {
1128 // transformed value
1129 const TCHAR *newValue = array->get(1)->getValueAsCString();
1130 if ((newValue != NULL) && (*newValue != 0))
1131 {
1132 DbgPrintf(5, _T("DCObject::filterInstanceList(%s [%d]): instance \"%s\" replaced by \"%s\""),
1133 dco->getName(), dco->getId(), instance, newValue);
1134 instance = newValue;
1135 }
1136
1137 if (array->size() > 2)
1138 {
1139 // instance name
1140 const TCHAR *newName = array->get(2)->getValueAsCString();
1141 if ((newName != NULL) && (*newName != 0))
1142 {
1143 DbgPrintf(5, _T("DCObject::filterInstanceList(%s [%d]): instance \"%s\" name set to \"%s\""),
1144 dco->getName(), dco->getId(), instance, newName);
1145 name = newName;
1146 }
1147 }
1148 }
1149 }
1150 else
1151 {
1152 accepted = true;
1153 }
1154 }
1155 else
1156 {
1157 accepted = result->getValueAsInt32() ? true : false;
1158 }
1159 }
1160 else
1161 {
1162 accepted = true;
1163 }
1164 if (accepted)
1165 {
1166 ((FilterCallbackData *)data)->filteredInstances->set(instance, name);
1167 }
1168 else
1169 {
1170 DbgPrintf(5, _T("DCObject::filterInstanceList(%s [%d]): instance \"%s\" removed by filtering script"),
1171 dco->getName(), dco->getId(), key);
1172 }
1173 }
1174 else
1175 {
1176 TCHAR szBuffer[1024];
1177 _sntprintf(szBuffer, 1024, _T("DCI::%s::%d::InstanceFilter"), dco->getOwnerName(), dco->getId());
1178 PostDciEvent(EVENT_SCRIPT_ERROR, g_dwMgmtNode, dco->getId(), "ssd", szBuffer, instanceFilter->getErrorText(), dco->getId());
1179 ((FilterCallbackData *)data)->filteredInstances->set(key, (const TCHAR *)value);
1180 }
1181 return _CONTINUE;
1182 }
1183
1184 /**
1185 * Filter instance list
1186 */
1187 void DCObject::filterInstanceList(StringMap *instances)
1188 {
1189 lock();
1190 if (m_instanceFilter == NULL)
1191 {
1192 unlock();
1193 return;
1194 }
1195
1196 FilterCallbackData data;
1197 data.instanceFilter = new NXSL_VM(new NXSL_ServerEnv());
1198 if (!data.instanceFilter->load(m_instanceFilter))
1199 {
1200 TCHAR szBuffer[1024];
1201 _sntprintf(szBuffer, 1024, _T("DCI::%s::%d::InstanceFilter"), getOwnerName(), m_id);
1202 PostDciEvent(EVENT_SCRIPT_ERROR, g_dwMgmtNode, m_id, "ssd", szBuffer, data.instanceFilter->getErrorText(), m_id);
1203 }
1204 unlock();
1205
1206 StringMap filteredInstances;
1207 data.filteredInstances = &filteredInstances;
1208 data.dco = this;
1209 instances->forEach(FilterCallback, &data);
1210 instances->clear();
1211 instances->addAll(&filteredInstances);
1212 delete data.instanceFilter;
1213 }
1214
1215
1216 /**
1217 * Set new instance discovery filter script
1218 */
1219 void DCObject::setInstanceFilter(const TCHAR *pszScript)
1220 {
1221 free(m_instanceFilterSource);
1222 delete m_instanceFilter;
1223 if (pszScript != NULL)
1224 {
1225 m_instanceFilterSource = _tcsdup(pszScript);
1226 StrStrip(m_instanceFilterSource);
1227 if (m_instanceFilterSource[0] != 0)
1228 {
1229 TCHAR errorText[1024];
1230 m_instanceFilter = NXSLCompile(m_instanceFilterSource, errorText, 1024, NULL);
1231 if (m_instanceFilter == NULL)
1232 {
1233 // node can be NULL if this DCO was just created from template
1234 // in this case compilation error will be reported on template level anyway
1235 if (m_owner != NULL)
1236 nxlog_write(MSG_INSTANCE_FILTER_SCRIPT_COMPILATION_ERROR, NXLOG_WARNING, "dsdss", m_owner->getId(), m_owner->getName(), m_id, m_name, errorText);
1237 }
1238 }
1239 else
1240 {
1241 m_instanceFilter = NULL;
1242 }
1243 }
1244 else
1245 {
1246 m_instanceFilterSource = NULL;
1247 m_instanceFilter = NULL;
1248 }
1249 }
1250
1251 /**
1252 * Serialize object to JSON
1253 */
1254 json_t *DCObject::toJson()
1255 {
1256 json_t *root = json_object();
1257 json_object_set_new(root, "id", json_integer(m_id));
1258 json_object_set_new(root, "guid", m_guid.toJson());
1259 json_object_set_new(root, "name", json_string_t(m_name));
1260 json_object_set_new(root, "description", json_string_t(m_description));
1261 json_object_set_new(root, "systemTag", json_string_t(m_systemTag));
1262 json_object_set_new(root, "lastPoll", json_integer(m_tLastPoll));
1263 json_object_set_new(root, "pollingInterval", json_integer(m_iPollingInterval));
1264 json_object_set_new(root, "retentionTime", json_integer(m_iRetentionTime));
1265 json_object_set_new(root, "source", json_integer(m_source));
1266 json_object_set_new(root, "status", json_integer(m_status));
1267 json_object_set_new(root, "busy", json_integer(m_busy));
1268 json_object_set_new(root, "scheduledForDeletion", json_integer(m_scheduledForDeletion));
1269 json_object_set_new(root, "flags", json_integer(m_flags));
1270 json_object_set_new(root, "dwTemplateId", json_integer(m_dwTemplateId));
1271 json_object_set_new(root, "dwTemplateItemId", json_integer(m_dwTemplateItemId));
1272 json_object_set_new(root, "schedules", (m_schedules != NULL) ? m_schedules->toJson() : json_array());
1273 json_object_set_new(root, "lastCheck", json_integer(m_tLastCheck));
1274 json_object_set_new(root, "errorCount", json_integer(m_dwErrorCount));
1275 json_object_set_new(root, "resourceId", json_integer(m_dwResourceId));
1276 json_object_set_new(root, "sourceNode", json_integer(m_sourceNode));
1277 json_object_set_new(root, "snmpPort", json_integer(m_snmpPort));
1278 json_object_set_new(root, "perfTabSettings", json_string_t(m_pszPerfTabSettings));
1279 json_object_set_new(root, "transformationScript", json_string_t(m_transformationScriptSource));
1280 json_object_set_new(root, "comments", json_string_t(m_comments));
1281 json_object_set_new(root, "instanceDiscoveryMethod", json_integer(m_instanceDiscoveryMethod));
1282 json_object_set_new(root, "instanceDiscoveryData", json_string_t(m_instanceDiscoveryData));
1283 json_object_set_new(root, "instanceFilter", json_string_t(m_instanceFilterSource));
1284 json_object_set_new(root, "instance", json_string_t(m_instance));
1285 return root;
1286 }
1287
1288 /**
1289 * Data collection object info - constructor
1290 */
1291 DCObjectInfo::DCObjectInfo(DCObject *object)
1292 {
1293 m_id = object->getId();
1294 m_type = object->getType();
1295 nx_strncpy(m_name, object->getName(), MAX_ITEM_NAME);
1296 nx_strncpy(m_description, object->getDescription(), MAX_DB_STRING);
1297 nx_strncpy(m_systemTag, object->getSystemTag(), MAX_DB_STRING);
1298 nx_strncpy(m_instance, object->getInstance(), MAX_DB_STRING);
1299 m_comments = _tcsdup_ex(object->getComments());
1300 m_dataType = (m_type == DCO_TYPE_ITEM) ? ((DCItem *)object)->getDataType() : -1;
1301 m_origin = object->getDataSource();
1302 m_status = object->getStatus();
1303 m_errorCount = object->getErrorCount();
1304 m_lastPollTime = object->getLastPollTime();
1305 m_ownerId = object->getOwnerId();
1306 }
1307
1308 /**
1309 * Data collection object info - destructor
1310 */
1311 DCObjectInfo::~DCObjectInfo()
1312 {
1313 free(m_comments);
1314 }