Added new status for collection error. Communication error does not reset status...
[public/netxms.git] / src / server / core / datacoll.cpp
CommitLineData
6da535d9 1/*
5039dede 2** NetXMS - Network Management System
4804be4e 3** Copyright (C) 2003-2016 Victor Kirhenshtein
5039dede
AK
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: datacoll.cpp
20**
21**/
22
23#include "nxcore.h"
24
46ee6286
VK
25/**
26 * Interval between DCI polling
27 */
6da535d9 28#define ITEM_POLLING_INTERVAL 1
5039dede 29
46ee6286
VK
30/**
31 * Externals
32 */
f1784ab6
VK
33extern Queue g_syslogProcessingQueue;
34extern Queue g_syslogWriteQueue;
5039dede 35
6fd6de0a
VK
36/**
37 * Global data
38 */
5039dede
AK
39double g_dAvgPollerQueueSize = 0;
40double g_dAvgDBWriterQueueSize = 0;
cf084617 41double g_dAvgIDataWriterQueueSize = 0;
76fcb995 42double g_dAvgRawDataWriterQueueSize = 0;
cf084617 43double g_dAvgDBAndIDataWriterQueueSize = 0;
f1784ab6
VK
44double g_dAvgSyslogProcessingQueueSize = 0;
45double g_dAvgSyslogWriterQueueSize = 0;
967893bb 46UINT32 g_dwAvgDCIQueuingTime = 0;
d140955e
VK
47Queue g_dataCollectionQueue(4096, 256);
48Queue g_dciCacheLoaderQueue;
5039dede 49
171c2fd6
VK
50/**
51 * Collect data for DCI
52 */
967893bb 53static void *GetItemData(DataCollectionTarget *dcTarget, DCItem *pItem, TCHAR *pBuffer, UINT32 *error)
df94e0ce 54{
c42b4551 55 if (dcTarget->getObjectClass() == OBJECT_CLUSTER)
df94e0ce 56 {
85ae39bc
VK
57 if (pItem->isAggregateOnCluster())
58 {
59 *error = ((Cluster *)dcTarget)->collectAggregatedData(pItem, pBuffer);
60 }
61 else
62 {
3cd6f508 63 *error = DCE_IGNORE;
85ae39bc
VK
64 }
65 }
66 else
67 {
68 switch(pItem->getDataSource())
69 {
70 case DS_INTERNAL: // Server internal parameters (like status)
71 *error = dcTarget->getInternalItem(pItem->getName(), MAX_LINE_SIZE, pBuffer);
72 break;
73 case DS_SNMP_AGENT:
c42b4551 74 if (dcTarget->getObjectClass() == OBJECT_NODE)
6da535d9 75 *error = ((Node *)dcTarget)->getItemFromSNMP(pItem->getSnmpPort(), pItem->getName(), MAX_LINE_SIZE,
85ae39bc
VK
76 pBuffer, pItem->isInterpretSnmpRawValue() ? (int)pItem->getSnmpRawValueType() : SNMP_RAWTYPE_NONE);
77 else
78 *error = DCE_NOT_SUPPORTED;
79 break;
80 case DS_CHECKPOINT_AGENT:
c42b4551 81 if (dcTarget->getObjectClass() == OBJECT_NODE)
85ae39bc
VK
82 *error = ((Node *)dcTarget)->getItemFromCheckPointSNMP(pItem->getName(), MAX_LINE_SIZE, pBuffer);
83 else
84 *error = DCE_NOT_SUPPORTED;
85 break;
86 case DS_NATIVE_AGENT:
c42b4551 87 if (dcTarget->getObjectClass() == OBJECT_NODE)
85ae39bc
VK
88 *error = ((Node *)dcTarget)->getItemFromAgent(pItem->getName(), MAX_LINE_SIZE, pBuffer);
89 else
90 *error = DCE_NOT_SUPPORTED;
91 break;
92 case DS_WINPERF:
c42b4551 93 if (dcTarget->getObjectClass() == OBJECT_NODE)
85ae39bc
VK
94 {
95 TCHAR name[MAX_PARAM_NAME];
1d919454 96 _sntprintf(name, MAX_PARAM_NAME, _T("PDH.CounterValue(\"%s\",%d)"), (const TCHAR *)EscapeStringForAgent(pItem->getName()), pItem->getSampleCount());
85ae39bc
VK
97 *error = ((Node *)dcTarget)->getItemFromAgent(name, MAX_LINE_SIZE, pBuffer);
98 }
99 else
100 {
101 *error = DCE_NOT_SUPPORTED;
102 }
103 break;
241541f4
VK
104 case DS_SSH:
105 if (dcTarget->getObjectClass() == OBJECT_NODE)
106 {
107 UINT32 proxyId = ((Node *)dcTarget)->getSshProxy();
108 if (proxyId == 0)
109 {
110 if (IsZoningEnabled())
111 {
112 Zone *zone = (Zone *)FindZoneByGUID(((Node *)dcTarget)->getZoneId());
43b62436
VK
113 if ((zone != NULL) && (zone->getProxyNodeId() != 0))
114 proxyId = zone->getProxyNodeId();
241541f4
VK
115 else
116 proxyId = g_dwMgmtNode;
117 }
118 else
119 {
120 proxyId = g_dwMgmtNode;
121 }
122 }
123 Node *proxy = (Node *)FindObjectById(proxyId, OBJECT_NODE);
124 if (proxy != NULL)
125 {
126 TCHAR name[MAX_PARAM_NAME], ipAddr[64];
127 _sntprintf(name, MAX_PARAM_NAME, _T("SSH.Command(%s,\"%s\",\"%s\",\"%s\")"),
128 ((Node *)dcTarget)->getIpAddress().toString(ipAddr),
129 (const TCHAR *)EscapeStringForAgent(((Node *)dcTarget)->getSshLogin()),
130 (const TCHAR *)EscapeStringForAgent(((Node *)dcTarget)->getSshPassword()),
131 (const TCHAR *)EscapeStringForAgent(pItem->getName()));
132 *error = proxy->getItemFromAgent(name, MAX_LINE_SIZE, pBuffer);
133 }
134 else
135 {
136 *error = DCE_COMM_ERROR;
137 }
138 }
139 else
140 {
141 *error = DCE_NOT_SUPPORTED;
142 }
143 break;
1d0d82b3 144 case DS_SMCLP:
c42b4551 145 if (dcTarget->getObjectClass() == OBJECT_NODE)
03bc96df 146 {
1d0d82b3 147 *error = ((Node *)dcTarget)->getItemFromSMCLP(pItem->getName(), MAX_LINE_SIZE, pBuffer);
03bc96df 148 }
85ae39bc
VK
149 else
150 {
151 *error = DCE_NOT_SUPPORTED;
152 }
17b1ab4a
VK
153 break;
154 case DS_SCRIPT:
155 *error = dcTarget->getScriptItem(pItem->getName(), MAX_LINE_SIZE, pBuffer);
85ae39bc
VK
156 break;
157 default:
158 *error = DCE_NOT_SUPPORTED;
159 break;
160 }
df94e0ce
VK
161 }
162 return pBuffer;
163}
164
171c2fd6
VK
165/**
166 * Collect data for table
167 */
967893bb 168static void *GetTableData(DataCollectionTarget *dcTarget, DCTable *table, UINT32 *error)
df94e0ce
VK
169{
170 Table *result = NULL;
c42b4551 171 if (dcTarget->getObjectClass() == OBJECT_CLUSTER)
a0ddfb29
VK
172 {
173 if (table->isAggregateOnCluster())
174 {
175 *error = ((Cluster *)dcTarget)->collectAggregatedData(table, &result);
176 }
177 else
178 {
3cd6f508 179 *error = DCE_IGNORE;
a0ddfb29
VK
180 }
181 }
182 else
df94e0ce 183 {
a0ddfb29
VK
184 switch(table->getDataSource())
185 {
186 case DS_NATIVE_AGENT:
c42b4551 187 if (dcTarget->getObjectClass() == OBJECT_NODE)
a0ddfb29
VK
188 {
189 *error = ((Node *)dcTarget)->getTableFromAgent(table->getName(), &result);
190 if ((*error == DCE_SUCCESS) && (result != NULL))
191 table->updateResultColumns(result);
192 }
193 else
194 {
195 *error = DCE_NOT_SUPPORTED;
196 }
197 break;
db117859 198 case DS_SNMP_AGENT:
c42b4551 199 if (dcTarget->getObjectClass() == OBJECT_NODE)
db117859
VK
200 {
201 *error = ((Node *)dcTarget)->getTableFromSNMP(table->getSnmpPort(), table->getName(), table->getColumns(), &result);
202 if ((*error == DCE_SUCCESS) && (result != NULL))
203 table->updateResultColumns(result);
204 }
205 else
206 {
207 *error = DCE_NOT_SUPPORTED;
208 }
209 break;
a0ddfb29
VK
210 default:
211 *error = DCE_NOT_SUPPORTED;
212 break;
213 }
214 }
df94e0ce
VK
215 return result;
216}
217
6fd6de0a
VK
218/**
219 * Data collector
220 */
5039dede
AK
221static THREAD_RESULT THREAD_CALL DataCollector(void *pArg)
222{
967893bb 223 UINT32 dwError;
5039dede 224
df94e0ce 225 TCHAR *pBuffer = (TCHAR *)malloc(MAX_LINE_SIZE * sizeof(TCHAR));
89135050 226 while(!IsShutdownInProgress())
5039dede 227 {
19dbc8ef 228 DCObject *pItem = (DCObject *)g_dataCollectionQueue.getOrBlock();
4804be4e 229 DataCollectionTarget *target = (DataCollectionTarget *)pItem->getOwner();
ced80327
VK
230
231 if (pItem->isScheduledForDeletion())
232 {
46e2b370
VK
233 nxlog_debug(7, _T("DataCollector(): about to destroy DC object %d \"%s\" owner=%d"),
234 pItem->getId(), pItem->getName(), (target != NULL) ? (int)target->getId() : -1);
c42b4551 235 pItem->deleteFromDatabase();
ced80327
VK
236 delete pItem;
237 continue;
238 }
239
46e2b370
VK
240 if (target == NULL)
241 {
242 nxlog_debug(3, _T("DataCollector: attempt to collect information for non-existing node (DCI=%d \"%s\")"),
243 pItem->getId(), pItem->getName());
244
245 // Update item's last poll time and clear busy flag so item can be polled again
246 pItem->setLastPollTime(time(NULL));
247 pItem->setBusyFlag(FALSE);
248 continue;
249 }
250
191e4784
VK
251 DbgPrintf(8, _T("DataCollector(): processing DC object %d \"%s\" owner=%d sourceNode=%d"),
252 pItem->getId(), pItem->getName(), (target != NULL) ? (int)target->getId() : -1, pItem->getSourceNode());
46e2b370
VK
253 UINT32 sourceNodeId = target->getEffectiveSourceNode(pItem);
254 if (sourceNodeId != 0)
5039dede 255 {
46e2b370
VK
256 Node *sourceNode = (Node *)FindObjectById(sourceNodeId, OBJECT_NODE);
257 if (sourceNode != NULL)
5039dede 258 {
46e2b370
VK
259 if (((target->getObjectClass() == OBJECT_CHASSIS) && (((Chassis *)target)->getControllerId() == sourceNodeId)) ||
260 sourceNode->isTrustedNode(target->getId()))
5039dede 261 {
46e2b370 262 target = sourceNode;
21c9acce 263 target->incRefCount();
5039dede
AK
264 }
265 else
266 {
35f836fe 267 // Change item's status to _T("not supported")
a8f60046 268 pItem->setStatus(ITEM_STATUS_NOT_SUPPORTED, true);
46e2b370
VK
269 target->decRefCount();
270 target = NULL;
5039dede
AK
271 }
272 }
273 else
274 {
46e2b370
VK
275 target->decRefCount();
276 target = NULL;
5039dede
AK
277 }
278 }
279
df94e0ce 280 time_t currTime = time(NULL);
6fd6de0a 281 if (target != NULL)
5039dede 282 {
88dc9091 283 if (!IsShutdownInProgress())
5039dede 284 {
88dc9091
VK
285 void *data;
286 switch(pItem->getType())
287 {
288 case DCO_TYPE_ITEM:
289 data = GetItemData(target, (DCItem *)pItem, pBuffer, &dwError);
290 break;
291 case DCO_TYPE_TABLE:
292 data = GetTableData(target, (DCTable *)pItem, &dwError);
293 break;
294 default:
295 data = NULL;
296 dwError = DCE_NOT_SUPPORTED;
297 break;
298 }
299
300 // Transform and store received value into database or handle error
301 switch(dwError)
302 {
303 case DCE_SUCCESS:
304 if (pItem->getStatus() == ITEM_STATUS_NOT_SUPPORTED)
305 pItem->setStatus(ITEM_STATUS_ACTIVE, true);
4804be4e 306 if (!((DataCollectionTarget *)pItem->getOwner())->processNewDCValue(pItem, currTime, data))
88dc9091
VK
307 {
308 // value processing failed, convert to data collection error
82493366 309 pItem->processNewError(false);
88dc9091
VK
310 }
311 break;
a8164c20 312 case DCE_COLLECTION_ERROR:
88dc9091
VK
313 if (pItem->getStatus() == ITEM_STATUS_NOT_SUPPORTED)
314 pItem->setStatus(ITEM_STATUS_ACTIVE, true);
82493366
VK
315 pItem->processNewError(false);
316 break;
317 case DCE_NO_SUCH_INSTANCE:
a8164c20 318 if (pItem->getStatus() == ITEM_STATUS_NOT_SUPPORTED)
319 pItem->setStatus(ITEM_STATUS_ACTIVE, true);
82493366 320 pItem->processNewError(true);
88dc9091 321 break;
a8164c20 322 case DCE_COMM_ERROR:
323 pItem->processNewError(false);
324 break;
88dc9091
VK
325 case DCE_NOT_SUPPORTED:
326 // Change item's status
327 pItem->setStatus(ITEM_STATUS_NOT_SUPPORTED, true);
328 break;
329 }
5039dede
AK
330 }
331
6da535d9
EJ
332 // Send session notification when force poll is performed
333 if (pItem->getPollingSession() != NULL)
334 {
335 ClientSession *session = pItem->processForcePoll();
690f7fa5 336 session->notify(NX_NOTIFY_FORCE_DCI_POLL, pItem->getOwnerId());
6da535d9
EJ
337 session->decRefCount();
338 }
339
5039dede 340 // Decrement node's usage counter
21c9acce 341 target->decRefCount();
4804be4e 342 if ((pItem->getSourceNode() != 0) && (pItem->getOwner() != NULL))
5039dede 343 {
4804be4e 344 pItem->getOwner()->decRefCount();
5039dede
AK
345 }
346 }
6fd6de0a 347 else /* target == NULL */
5039dede 348 {
4804be4e 349 Template *n = pItem->getOwner();
46e2b370
VK
350 nxlog_debug(5, _T("DataCollector: attempt to collect information for non-existing or inaccessible node (DCI=%d \"%s\" target=%d sourceNode=%d)"),
351 pItem->getId(), pItem->getName(), (n != NULL) ? (int)n->getId() : -1, sourceNodeId);
5039dede 352 }
61b48d2f
VK
353
354 // Update item's last poll time and clear busy flag so item can be polled again
355 pItem->setLastPollTime(currTime);
356 pItem->setBusyFlag(FALSE);
5039dede
AK
357 }
358
359 free(pBuffer);
35f836fe 360 DbgPrintf(1, _T("Data collector thread terminated"));
5039dede
AK
361 return THREAD_OK;
362}
363
6fd6de0a
VK
364/**
365 * Callback for queueing DCIs
366 */
6aba3998
VK
367static void QueueItems(NetObj *object, void *data)
368{
88dc9091
VK
369 if (IsShutdownInProgress())
370 return;
371
fa179b75 372 WatchdogNotify(*((UINT32 *)data));
6fd6de0a 373 DbgPrintf(8, _T("ItemPoller: calling DataCollectionTarget::queueItemsForPolling for object %s [%d]"),
c42b4551 374 object->getName(), object->getId());
d140955e 375 ((DataCollectionTarget *)object)->queueItemsForPolling(&g_dataCollectionQueue);
6aba3998
VK
376}
377
6fd6de0a 378/**
6da535d9 379 * Item poller thread: check nodes' items and put into the
6fd6de0a
VK
380 * data collector queue when data polling required
381 */
5039dede
AK
382static THREAD_RESULT THREAD_CALL ItemPoller(void *pArg)
383{
3c15eedb 384 UINT32 dwSum, currPos = 0;
967893bb 385 UINT32 dwTimingHistory[60 / ITEM_POLLING_INTERVAL];
5039dede
AK
386 INT64 qwStart;
387
fa179b75 388 UINT32 watchdogId = WatchdogAddThread(_T("Item Poller"), 10);
967893bb 389 memset(dwTimingHistory, 0, sizeof(UINT32) * (60 / ITEM_POLLING_INTERVAL));
5039dede 390
89135050 391 while(!IsShutdownInProgress())
5039dede
AK
392 {
393 if (SleepAndCheckForShutdown(ITEM_POLLING_INTERVAL))
394 break; // Shutdown has arrived
3c15eedb 395 WatchdogNotify(watchdogId);
5039dede
AK
396 DbgPrintf(8, _T("ItemPoller: wakeup"));
397
5039dede 398 qwStart = GetCurrentTimeMs();
fa179b75
VK
399 g_idxNodeById.forEach(QueueItems, &watchdogId);
400 g_idxClusterById.forEach(QueueItems, &watchdogId);
401 g_idxMobileDeviceById.forEach(QueueItems, &watchdogId);
402 g_idxChassisById.forEach(QueueItems, &watchdogId);
5039dede
AK
403
404 // Save last poll time
f1784ab6
VK
405 dwTimingHistory[currPos] = (UINT32)(GetCurrentTimeMs() - qwStart);
406 currPos++;
407 if (currPos == (60 / ITEM_POLLING_INTERVAL))
408 currPos = 0;
5039dede
AK
409
410 // Calculate new average for last minute
6aba3998
VK
411 dwSum = 0;
412 for(int i = 0; i < (60 / ITEM_POLLING_INTERVAL); i++)
5039dede
AK
413 dwSum += dwTimingHistory[i];
414 g_dwAvgDCIQueuingTime = dwSum / (60 / ITEM_POLLING_INTERVAL);
415 }
35f836fe 416 DbgPrintf(1, _T("Item poller thread terminated"));
5039dede
AK
417 return THREAD_OK;
418}
419
6fd6de0a
VK
420/**
421 * Statistics collection thread
422 */
5039dede
AK
423static THREAD_RESULT THREAD_CALL StatCollector(void *pArg)
424{
f1784ab6
VK
425 UINT32 i, currPos = 0;
426 UINT32 pollerQS[12], dbWriterQS[12];
76fcb995 427 UINT32 iDataWriterQS[12], rawDataWriterQS[12], dbAndIDataWriterQS[12];
f1784ab6 428 UINT32 syslogProcessingQS[12], syslogWriterQS[12];
208d7427 429 double sum1, sum2, sum3, sum4, sum5, sum8, sum9;
5039dede 430
f1784ab6
VK
431 memset(pollerQS, 0, sizeof(UINT32) * 12);
432 memset(dbWriterQS, 0, sizeof(UINT32) * 12);
433 memset(iDataWriterQS, 0, sizeof(UINT32) * 12);
76fcb995 434 memset(rawDataWriterQS, 0, sizeof(UINT32) * 12);
f1784ab6 435 memset(dbAndIDataWriterQS, 0, sizeof(UINT32) * 12);
f1784ab6
VK
436 memset(syslogProcessingQS, 0, sizeof(UINT32) * 12);
437 memset(syslogWriterQS, 0, sizeof(UINT32) * 12);
5039dede
AK
438 g_dAvgPollerQueueSize = 0;
439 g_dAvgDBWriterQueueSize = 0;
cf084617 440 g_dAvgIDataWriterQueueSize = 0;
76fcb995 441 g_dAvgRawDataWriterQueueSize = 0;
cf084617 442 g_dAvgDBAndIDataWriterQueueSize = 0;
f1784ab6
VK
443 g_dAvgSyslogProcessingQueueSize = 0;
444 g_dAvgSyslogWriterQueueSize = 0;
89135050 445 while(!IsShutdownInProgress())
5039dede
AK
446 {
447 if (SleepAndCheckForShutdown(5))
448 break; // Shutdown has arrived
449
450 // Get current values
19dbc8ef
VK
451 pollerQS[currPos] = g_dataCollectionQueue.size();
452 dbWriterQS[currPos] = g_dbWriterQueue->size();
453 iDataWriterQS[currPos] = g_dciDataWriterQueue->size();
454 rawDataWriterQS[currPos] = g_dciRawDataWriterQueue->size();
455 dbAndIDataWriterQS[currPos] = g_dbWriterQueue->size() + g_dciDataWriterQueue->size() + g_dciRawDataWriterQueue->size();
19dbc8ef
VK
456 syslogProcessingQS[currPos] = g_syslogProcessingQueue.size();
457 syslogWriterQS[currPos] = g_syslogWriteQueue.size();
f1784ab6
VK
458 currPos++;
459 if (currPos == 12)
460 currPos = 0;
5039dede
AK
461
462 // Calculate new averages
208d7427 463 for(i = 0, sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum8 = 0, sum9 = 0; i < 12; i++)
5039dede 464 {
f1784ab6
VK
465 sum1 += pollerQS[i];
466 sum2 += dbWriterQS[i];
467 sum3 += iDataWriterQS[i];
76fcb995
VK
468 sum4 += rawDataWriterQS[i];
469 sum5 += dbAndIDataWriterQS[i];
76fcb995
VK
470 sum8 += syslogProcessingQS[i];
471 sum9 += syslogWriterQS[i];
5039dede 472 }
f1784ab6
VK
473 g_dAvgPollerQueueSize = sum1 / 12;
474 g_dAvgDBWriterQueueSize = sum2 / 12;
475 g_dAvgIDataWriterQueueSize = sum3 / 12;
76fcb995
VK
476 g_dAvgRawDataWriterQueueSize = sum4 / 12;
477 g_dAvgDBAndIDataWriterQueueSize = sum5 / 12;
76fcb995
VK
478 g_dAvgSyslogProcessingQueueSize = sum8 / 12;
479 g_dAvgSyslogWriterQueueSize = sum9 / 12;
5039dede
AK
480 }
481 return THREAD_OK;
482}
483
d140955e
VK
484/**
485 * DCI cache loader
486 */
487THREAD_RESULT THREAD_CALL CacheLoader(void *arg)
488{
489 DbgPrintf(2, _T("DCI cache loader thread started"));
490 while(true)
491 {
19dbc8ef 492 DCItem *dci = (DCItem *)g_dciCacheLoaderQueue.getOrBlock();
d140955e
VK
493 if (dci == INVALID_POINTER_VALUE)
494 break;
495
6da535d9 496 DbgPrintf(6, _T("Loading cache for DCI %s [%d] on %s [%d]"),
4804be4e 497 dci->getName(), dci->getId(), dci->getOwnerName(), dci->getOwnerId());
d140955e 498 dci->reloadCache();
4804be4e 499 dci->getOwner()->decRefCount();
d140955e
VK
500 }
501 DbgPrintf(2, _T("DCI cache loader thread stopped"));
502 return THREAD_OK;
503}
504
6fd6de0a
VK
505/**
506 * Initialize data collection subsystem
507 */
4fe87cdc 508BOOL InitDataCollector()
5039dede
AK
509{
510 int i, iNumCollectors;
511
5039dede 512 // Start data collection threads
35f836fe 513 iNumCollectors = ConfigReadInt(_T("NumberOfDataCollectors"), 10);
5039dede
AK
514 for(i = 0; i < iNumCollectors; i++)
515 ThreadCreate(DataCollector, 0, NULL);
516
5039dede 517 ThreadCreate(ItemPoller, 0, NULL);
5039dede 518 ThreadCreate(StatCollector, 0, NULL);
d140955e 519 ThreadCreate(CacheLoader, 0, NULL);
5039dede
AK
520
521 return TRUE;
522}
523
d140955e
VK
524/**
525 * Update parameter list from node
526 */
6aba3998
VK
527static void UpdateParamList(NetObj *object, void *data)
528{
86c126f5 529 ObjectArray<AgentParameterDefinition> *fullList = (ObjectArray<AgentParameterDefinition> *)data;
6aba3998 530
86c126f5 531 ObjectArray<AgentParameterDefinition> *paramList;
cc8ce218
VK
532 ((Node *)object)->openParamList(&paramList);
533 if ((paramList != NULL) && (paramList->size() > 0))
6aba3998 534 {
cc8ce218 535 for(int i = 0; i < paramList->size(); i++)
889d7ff7 536 {
86c126f5
VK
537 int j;
538 for(j = 0; j < fullList->size(); j++)
889d7ff7 539 {
86c126f5 540 if (!_tcsicmp(paramList->get(i)->getName(), fullList->get(j)->getName()))
6aba3998
VK
541 break;
542 }
543
86c126f5 544 if (j == fullList->size())
6aba3998 545 {
86c126f5 546 fullList->add(new AgentParameterDefinition(paramList->get(i)));
889d7ff7 547 }
889d7ff7 548 }
6aba3998 549 }
f1ff4cc9 550 ((Node *)object)->closeParamList();
6aba3998
VK
551}
552
d140955e
VK
553/**
554 * Update table list from node
555 */
074498ac
VK
556static void UpdateTableList(NetObj *object, void *data)
557{
86c126f5 558 ObjectArray<AgentTableDefinition> *fullList = (ObjectArray<AgentTableDefinition> *)data;
074498ac 559
86c126f5 560 ObjectArray<AgentTableDefinition> *tableList;
074498ac
VK
561 ((Node *)object)->openTableList(&tableList);
562 if ((tableList != NULL) && (tableList->size() > 0))
563 {
074498ac
VK
564 for(int i = 0; i < tableList->size(); i++)
565 {
86c126f5
VK
566 int j;
567 for(j = 0; j < fullList->size(); j++)
074498ac 568 {
86c126f5 569 if (!_tcsicmp(tableList->get(i)->getName(), fullList->get(j)->getName()))
074498ac
VK
570 break;
571 }
572
86c126f5 573 if (j == fullList->size())
074498ac 574 {
86c126f5 575 fullList->add(new AgentTableDefinition(tableList->get(i)));
074498ac
VK
576 }
577 }
578 }
579 ((Node *)object)->closeTableList();
580}
581
d140955e
VK
582/**
583 * Write full (from all nodes) agent parameters list to NXCP message
584 */
b368969c 585void WriteFullParamListToMessage(NXCPMessage *pMsg, WORD flags)
6aba3998
VK
586{
587 // Gather full parameter list
074498ac
VK
588 if (flags & 0x01)
589 {
86c126f5 590 ObjectArray<AgentParameterDefinition> fullList(64, 64, true);
074498ac
VK
591 g_idxNodeById.forEach(UpdateParamList, &fullList);
592
593 // Put list into the message
b368969c 594 pMsg->setField(VID_NUM_PARAMETERS, (UINT32)fullList.size());
967893bb 595 UINT32 varId = VID_PARAM_LIST_BASE;
86c126f5 596 for(int i = 0; i < fullList.size(); i++)
074498ac 597 {
86c126f5 598 varId += fullList.get(i)->fillMessage(pMsg, varId);
074498ac 599 }
074498ac
VK
600 }
601
602 // Gather full table list
603 if (flags & 0x02)
604 {
86c126f5 605 ObjectArray<AgentTableDefinition> fullList(64, 64, true);
074498ac
VK
606 g_idxNodeById.forEach(UpdateTableList, &fullList);
607
608 // Put list into the message
b368969c 609 pMsg->setField(VID_NUM_TABLES, (UINT32)fullList.size());
967893bb 610 UINT32 varId = VID_TABLE_LIST_BASE;
86c126f5 611 for(int i = 0; i < fullList.size(); i++)
074498ac 612 {
86c126f5 613 varId += fullList.get(i)->fillMessage(pMsg, varId);
074498ac 614 }
074498ac 615 }
5039dede 616}
9fddfb91
VK
617
618/**
619 * Get type of data collection object
620 */
621int GetDCObjectType(UINT32 nodeId, UINT32 dciId)
622{
623 Node *node = (Node *)FindObjectById(nodeId, OBJECT_NODE);
624 if (node != NULL)
625 {
626 DCObject *dco = node->getDCObjectById(dciId);
627 if (dco != NULL)
628 {
629 return dco->getType();
630 }
631 }
632 return DCO_TYPE_ITEM; // default
633}