fixed LLDP based topology discovery issues on some devices (mostly D-Link)
[public/netxms.git] / src / server / core / objects.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2016 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: objects.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24
25 /**
26 * Global data
27 */
28 BOOL g_bModificationsLocked = FALSE;
29
30 Network NXCORE_EXPORTABLE *g_pEntireNet = NULL;
31 ServiceRoot NXCORE_EXPORTABLE *g_pServiceRoot = NULL;
32 TemplateRoot NXCORE_EXPORTABLE *g_pTemplateRoot = NULL;
33 PolicyRoot NXCORE_EXPORTABLE *g_pPolicyRoot = NULL;
34 NetworkMapRoot NXCORE_EXPORTABLE *g_pMapRoot = NULL;
35 DashboardRoot NXCORE_EXPORTABLE *g_pDashboardRoot = NULL;
36 BusinessServiceRoot NXCORE_EXPORTABLE *g_pBusinessServiceRoot = NULL;
37
38 UINT32 NXCORE_EXPORTABLE g_dwMgmtNode = 0;
39
40 Queue *g_pTemplateUpdateQueue = NULL;
41
42 ObjectIndex g_idxObjectById;
43 InetAddressIndex g_idxSubnetByAddr;
44 InetAddressIndex g_idxInterfaceByAddr;
45 ObjectIndex g_idxZoneByGUID;
46 ObjectIndex g_idxNodeById;
47 InetAddressIndex g_idxNodeByAddr;
48 ObjectIndex g_idxClusterById;
49 ObjectIndex g_idxMobileDeviceById;
50 ObjectIndex g_idxAccessPointById;
51 ObjectIndex g_idxConditionById;
52 ObjectIndex g_idxServiceCheckById;
53 ObjectIndex g_idxNetMapById;
54
55 /**
56 * Static data
57 */
58 static int m_iStatusCalcAlg = SA_CALCULATE_MOST_CRITICAL;
59 static int m_iStatusPropAlg = SA_PROPAGATE_UNCHANGED;
60 static int m_iFixedStatus; // Status if propagation is "Fixed"
61 static int m_iStatusShift; // Shift value for "shifted" status propagation
62 static int m_iStatusTranslation[4];
63 static int m_iStatusSingleThreshold;
64 static int m_iStatusThresholds[4];
65 static CONDITION s_condUpdateMaps = INVALID_CONDITION_HANDLE;
66
67 /**
68 * Thread which apply template updates
69 */
70 static THREAD_RESULT THREAD_CALL ApplyTemplateThread(void *pArg)
71 {
72 DbgPrintf(1, _T("Apply template thread started"));
73 while(1)
74 {
75 TEMPLATE_UPDATE_INFO *pInfo = (TEMPLATE_UPDATE_INFO *)g_pTemplateUpdateQueue->getOrBlock();
76 if (pInfo == INVALID_POINTER_VALUE)
77 break;
78
79 DbgPrintf(5, _T("ApplyTemplateThread: template=%d(%s) updateType=%d target=%d removeDci=%s"),
80 pInfo->pTemplate->getId(), pInfo->pTemplate->getName(), pInfo->updateType, pInfo->targetId, pInfo->removeDCI ? _T("true") : _T("false"));
81 BOOL bSuccess = FALSE;
82 NetObj *dcTarget = FindObjectById(pInfo->targetId);
83 if (dcTarget != NULL)
84 {
85 if ((dcTarget->getObjectClass() == OBJECT_NODE) || (dcTarget->getObjectClass() == OBJECT_CLUSTER) || (dcTarget->getObjectClass() == OBJECT_MOBILEDEVICE))
86 {
87 BOOL lock1, lock2;
88
89 switch(pInfo->updateType)
90 {
91 case APPLY_TEMPLATE:
92 lock1 = pInfo->pTemplate->lockDCIList(0x7FFFFFFF, _T("SYSTEM"), NULL);
93 lock2 = ((DataCollectionTarget *)dcTarget)->lockDCIList(0x7FFFFFFF, _T("SYSTEM"), NULL);
94 if (lock1 && lock2)
95 {
96 pInfo->pTemplate->applyToTarget((DataCollectionTarget *)dcTarget);
97 bSuccess = TRUE;
98 }
99 if (lock1)
100 pInfo->pTemplate->unlockDCIList(0x7FFFFFFF);
101 if (lock2)
102 ((DataCollectionTarget *)dcTarget)->unlockDCIList(0x7FFFFFFF);
103 break;
104 case REMOVE_TEMPLATE:
105 if (((DataCollectionTarget *)dcTarget)->lockDCIList(0x7FFFFFFF, _T("SYSTEM"), NULL))
106 {
107 ((DataCollectionTarget *)dcTarget)->unbindFromTemplate(pInfo->pTemplate->getId(), pInfo->removeDCI);
108 ((DataCollectionTarget *)dcTarget)->unlockDCIList(0x7FFFFFFF);
109 bSuccess = TRUE;
110 }
111 break;
112 default:
113 bSuccess = TRUE;
114 break;
115 }
116 }
117 }
118
119 if (bSuccess)
120 {
121 DbgPrintf(8, _T("ApplyTemplateThread: success"));
122 pInfo->pTemplate->decRefCount();
123 free(pInfo);
124 }
125 else
126 {
127 DbgPrintf(8, _T("ApplyTemplateThread: failed"));
128 g_pTemplateUpdateQueue->put(pInfo); // Requeue
129 ThreadSleepMs(500);
130 }
131 }
132
133 DbgPrintf(1, _T("Apply template thread stopped"));
134 return THREAD_OK;
135 }
136
137 /**
138 * Update DCI cache for all data collection targets referenced by given index
139 */
140 static void UpdateDataCollectionCache(ObjectIndex *idx)
141 {
142 ObjectArray<NetObj> *objects = idx->getObjects(true);
143 for(int i = 0; i < objects->size(); i++)
144 {
145 DataCollectionTarget *t = (DataCollectionTarget *)objects->get(i);
146 t->updateDciCache();
147 t->decRefCount();
148 }
149 delete objects;
150 }
151
152 /**
153 * DCI cache loading thread
154 */
155 static THREAD_RESULT THREAD_CALL CacheLoadingThread(void *pArg)
156 {
157 DbgPrintf(1, _T("Started caching of DCI values"));
158
159 UpdateDataCollectionCache(&g_idxNodeById);
160 UpdateDataCollectionCache(&g_idxClusterById);
161 UpdateDataCollectionCache(&g_idxMobileDeviceById);
162 UpdateDataCollectionCache(&g_idxAccessPointById);
163
164 DbgPrintf(1, _T("Finished caching of DCI values"));
165 return THREAD_OK;
166 }
167
168 /**
169 * Callback for map update thread
170 */
171 static void UpdateMapCallback(NetObj *object, void *data)
172 {
173 ((NetworkMap *)object)->updateContent();
174 ((NetworkMap *)object)->calculateCompoundStatus();
175 }
176
177 /**
178 * Map update thread
179 */
180 static THREAD_RESULT THREAD_CALL MapUpdateThread(void *pArg)
181 {
182 DbgPrintf(2, _T("Map update thread started"));
183 while(!SleepAndCheckForShutdown(60))
184 {
185 DbgPrintf(5, _T("Updating maps..."));
186 g_idxNetMapById.forEach(UpdateMapCallback, NULL);
187 DbgPrintf(5, _T("Map update completed"));
188 }
189 DbgPrintf(2, _T("Map update thread stopped"));
190 return THREAD_OK;
191 }
192
193 /**
194 * Initialize objects infrastructure
195 */
196 void ObjectsInit()
197 {
198 // Load default status calculation info
199 m_iStatusCalcAlg = ConfigReadInt(_T("StatusCalculationAlgorithm"), SA_CALCULATE_MOST_CRITICAL);
200 m_iStatusPropAlg = ConfigReadInt(_T("StatusPropagationAlgorithm"), SA_PROPAGATE_UNCHANGED);
201 m_iFixedStatus = ConfigReadInt(_T("FixedStatusValue"), STATUS_NORMAL);
202 m_iStatusShift = ConfigReadInt(_T("StatusShift"), 0);
203 ConfigReadByteArray(_T("StatusTranslation"), m_iStatusTranslation, 4, STATUS_WARNING);
204 m_iStatusSingleThreshold = ConfigReadInt(_T("StatusSingleThreshold"), 75);
205 ConfigReadByteArray(_T("StatusThresholds"), m_iStatusThresholds, 4, 50);
206
207 g_pTemplateUpdateQueue = new Queue;
208
209 s_condUpdateMaps = ConditionCreate(FALSE);
210
211 // Create "Entire Network" object
212 g_pEntireNet = new Network;
213 NetObjInsert(g_pEntireNet, false, false);
214
215 // Create "Service Root" object
216 g_pServiceRoot = new ServiceRoot;
217 NetObjInsert(g_pServiceRoot, false, false);
218
219 // Create "Template Root" object
220 g_pTemplateRoot = new TemplateRoot;
221 NetObjInsert(g_pTemplateRoot, false, false);
222
223 // Create "Policy Root" object
224 g_pPolicyRoot = new PolicyRoot;
225 NetObjInsert(g_pPolicyRoot, false, false);
226
227 // Create "Network Maps Root" object
228 g_pMapRoot = new NetworkMapRoot;
229 NetObjInsert(g_pMapRoot, false, false);
230
231 // Create "Dashboard Root" object
232 g_pDashboardRoot = new DashboardRoot;
233 NetObjInsert(g_pDashboardRoot, false, false);
234
235 // Create "Business Service Root" object
236 g_pBusinessServiceRoot = new BusinessServiceRoot;
237 NetObjInsert(g_pBusinessServiceRoot, false, false);
238
239 DbgPrintf(1, _T("Built-in objects created"));
240
241 // Initialize service checks
242 SlmCheck::init();
243 }
244
245 /**
246 * Insert new object into network
247 */
248 void NetObjInsert(NetObj *pObject, bool newObject, bool importedObject)
249 {
250 if (newObject)
251 {
252 // Assign unique ID to new object
253 pObject->setId(CreateUniqueId(IDG_NETWORK_OBJECT));
254 if (!importedObject) // imported objects already have valid GUID
255 pObject->generateGuid();
256
257 // Create tables for storing data collection values
258 if ((pObject->getObjectClass() == OBJECT_NODE) ||
259 (pObject->getObjectClass() == OBJECT_MOBILEDEVICE) ||
260 (pObject->getObjectClass() == OBJECT_CLUSTER) ||
261 (pObject->getObjectClass() == OBJECT_ACCESSPOINT))
262 {
263 TCHAR szQuery[256], szQueryTemplate[256];
264 UINT32 i;
265
266 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
267
268 MetaDataReadStr(_T("IDataTableCreationCommand"), szQueryTemplate, 255, _T(""));
269 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), szQueryTemplate, pObject->getId());
270 DBQuery(hdb, szQuery);
271
272 for(i = 0; i < 10; i++)
273 {
274 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("IDataIndexCreationCommand_%d"), i);
275 MetaDataReadStr(szQuery, szQueryTemplate, 255, _T(""));
276 if (szQueryTemplate[0] != 0)
277 {
278 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), szQueryTemplate, pObject->getId(), pObject->getId());
279 DBQuery(hdb, szQuery);
280 }
281 }
282
283 for(i = 0; i < 10; i++)
284 {
285 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("TDataTableCreationCommand_%d"), i);
286 MetaDataReadStr(szQuery, szQueryTemplate, 255, _T(""));
287 if (szQueryTemplate[0] != 0)
288 {
289 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), szQueryTemplate, pObject->getId(), pObject->getId());
290 DBQuery(hdb, szQuery);
291 }
292 }
293
294 for(i = 0; i < 10; i++)
295 {
296 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("TDataIndexCreationCommand_%d"), i);
297 MetaDataReadStr(szQuery, szQueryTemplate, 255, _T(""));
298 if (szQueryTemplate[0] != 0)
299 {
300 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), szQueryTemplate, pObject->getId(), pObject->getId());
301 DBQuery(hdb, szQuery);
302 }
303 }
304
305 DBConnectionPoolReleaseConnection(hdb);
306 }
307 }
308 g_idxObjectById.put(pObject->getId(), pObject);
309 if (!pObject->isDeleted())
310 {
311 switch(pObject->getObjectClass())
312 {
313 case OBJECT_GENERIC:
314 case OBJECT_NETWORK:
315 case OBJECT_CONTAINER:
316 case OBJECT_SERVICEROOT:
317 case OBJECT_NETWORKSERVICE:
318 case OBJECT_TEMPLATE:
319 case OBJECT_TEMPLATEGROUP:
320 case OBJECT_TEMPLATEROOT:
321 case OBJECT_VPNCONNECTOR:
322 case OBJECT_POLICYGROUP:
323 case OBJECT_POLICYROOT:
324 case OBJECT_AGENTPOLICY:
325 case OBJECT_AGENTPOLICY_CONFIG:
326 case OBJECT_NETWORKMAPROOT:
327 case OBJECT_NETWORKMAPGROUP:
328 case OBJECT_DASHBOARDROOT:
329 case OBJECT_DASHBOARD:
330 case OBJECT_BUSINESSSERVICEROOT:
331 case OBJECT_BUSINESSSERVICE:
332 case OBJECT_NODELINK:
333 case OBJECT_RACK:
334 break;
335 case OBJECT_NODE:
336 g_idxNodeById.put(pObject->getId(), pObject);
337 if (!(((Node *)pObject)->getFlags() & NF_REMOTE_AGENT))
338 {
339 if (IsZoningEnabled())
340 {
341 Zone *zone = (Zone *)g_idxZoneByGUID.get(((Node *)pObject)->getZoneId());
342 if (zone != NULL)
343 {
344 zone->addToIndex((Node *)pObject);
345 }
346 else
347 {
348 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for node object %s [%d]"),
349 (int)((Node *)pObject)->getZoneId(), pObject->getName(), (int)pObject->getId());
350 }
351 }
352 else
353 {
354 if (((Node *)pObject)->getIpAddress().isValidUnicast())
355 g_idxNodeByAddr.put(((Node *)pObject)->getIpAddress(), pObject);
356 }
357 }
358 break;
359 case OBJECT_CLUSTER:
360 g_idxClusterById.put(pObject->getId(), pObject);
361 break;
362 case OBJECT_MOBILEDEVICE:
363 g_idxMobileDeviceById.put(pObject->getId(), pObject);
364 break;
365 case OBJECT_ACCESSPOINT:
366 g_idxAccessPointById.put(pObject->getId(), pObject);
367 MacDbAddAccessPoint((AccessPoint *)pObject);
368 break;
369 case OBJECT_SUBNET:
370 if (((Subnet *)pObject)->getIpAddress().isValidUnicast())
371 {
372 if (IsZoningEnabled())
373 {
374 Zone *zone = (Zone *)g_idxZoneByGUID.get(((Subnet *)pObject)->getZoneId());
375 if (zone != NULL)
376 {
377 zone->addToIndex((Subnet *)pObject);
378 }
379 else
380 {
381 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for subnet object %s [%d]"),
382 (int)((Subnet *)pObject)->getZoneId(), pObject->getName(), (int)pObject->getId());
383 }
384 }
385 else
386 {
387 g_idxSubnetByAddr.put(((Subnet *)pObject)->getIpAddress(), pObject);
388 }
389 if (newObject)
390 {
391 PostEvent(EVENT_SUBNET_ADDED, g_dwMgmtNode, "isAd", pObject->getId(), pObject->getName(),
392 &((Subnet *)pObject)->getIpAddress(), ((Subnet *)pObject)->getIpAddress().getMaskBits());
393 }
394 }
395 break;
396 case OBJECT_INTERFACE:
397 if (!((Interface *)pObject)->isExcludedFromTopology())
398 {
399 if (IsZoningEnabled())
400 {
401 Zone *zone = (Zone *)g_idxZoneByGUID.get(((Interface *)pObject)->getZoneId());
402 if (zone != NULL)
403 {
404 zone->addToIndex((Interface *)pObject);
405 }
406 else
407 {
408 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for interface object %s [%d]"),
409 (int)((Interface *)pObject)->getZoneId(), pObject->getName(), (int)pObject->getId());
410 }
411 }
412 else
413 {
414 g_idxInterfaceByAddr.put(((Interface *)pObject)->getIpAddressList(), pObject);
415 }
416 }
417 MacDbAddInterface((Interface *)pObject);
418 break;
419 case OBJECT_ZONE:
420 g_idxZoneByGUID.put(((Zone *)pObject)->getZoneId(), pObject);
421 break;
422 case OBJECT_CONDITION:
423 g_idxConditionById.put(pObject->getId(), pObject);
424 break;
425 case OBJECT_SLMCHECK:
426 g_idxServiceCheckById.put(pObject->getId(), pObject);
427 break;
428 case OBJECT_NETWORKMAP:
429 g_idxNetMapById.put(pObject->getId(), pObject);
430 break;
431 default:
432 {
433 bool processed = false;
434 for(UINT32 i = 0; i < g_dwNumModules; i++)
435 {
436 if (g_pModuleList[i].pfNetObjInsert != NULL)
437 {
438 if (g_pModuleList[i].pfNetObjInsert(pObject))
439 processed = true;
440 }
441 }
442 if (!processed)
443 nxlog_write(MSG_BAD_NETOBJ_TYPE, EVENTLOG_ERROR_TYPE, "d", pObject->getObjectClass());
444 }
445 break;
446 }
447 }
448
449 // Notify modules about object creation
450 if (newObject)
451 {
452 CALL_ALL_MODULES(pfPostObjectCreate, (pObject));
453 }
454 else
455 {
456 CALL_ALL_MODULES(pfPostObjectLoad, (pObject));
457 }
458 }
459
460 /**
461 * Delete object from indexes
462 * If object has an IP address, this function will delete it from
463 * appropriate index. Normally this function should be called from
464 * NetObj::deleteObject() method.
465 */
466 void NetObjDeleteFromIndexes(NetObj *pObject)
467 {
468 switch(pObject->getObjectClass())
469 {
470 case OBJECT_GENERIC:
471 case OBJECT_NETWORK:
472 case OBJECT_CONTAINER:
473 case OBJECT_SERVICEROOT:
474 case OBJECT_NETWORKSERVICE:
475 case OBJECT_TEMPLATE:
476 case OBJECT_TEMPLATEGROUP:
477 case OBJECT_TEMPLATEROOT:
478 case OBJECT_VPNCONNECTOR:
479 case OBJECT_POLICYGROUP:
480 case OBJECT_POLICYROOT:
481 case OBJECT_AGENTPOLICY:
482 case OBJECT_AGENTPOLICY_CONFIG:
483 case OBJECT_NETWORKMAPROOT:
484 case OBJECT_NETWORKMAPGROUP:
485 case OBJECT_DASHBOARDROOT:
486 case OBJECT_DASHBOARD:
487 case OBJECT_BUSINESSSERVICEROOT:
488 case OBJECT_BUSINESSSERVICE:
489 case OBJECT_NODELINK:
490 case OBJECT_RACK:
491 break;
492 case OBJECT_NODE:
493 g_idxNodeById.remove(pObject->getId());
494 if (!(((Node *)pObject)->getFlags() & NF_REMOTE_AGENT))
495 {
496 if (IsZoningEnabled())
497 {
498 Zone *zone = (Zone *)g_idxZoneByGUID.get(((Node *)pObject)->getZoneId());
499 if (zone != NULL)
500 {
501 zone->removeFromIndex((Node *)pObject);
502 }
503 else
504 {
505 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for node object %s [%d]"),
506 (int)((Node *)pObject)->getZoneId(), pObject->getName(), (int)pObject->getId());
507 }
508 }
509 else
510 {
511 if (((Node *)pObject)->getIpAddress().isValidUnicast())
512 g_idxNodeByAddr.remove(((Node *)pObject)->getIpAddress());
513 }
514 }
515 break;
516 case OBJECT_CLUSTER:
517 g_idxClusterById.remove(pObject->getId());
518 break;
519 case OBJECT_MOBILEDEVICE:
520 g_idxMobileDeviceById.remove(pObject->getId());
521 break;
522 case OBJECT_ACCESSPOINT:
523 g_idxAccessPointById.remove(pObject->getId());
524 MacDbRemove(((AccessPoint *)pObject)->getMacAddr());
525 break;
526 case OBJECT_SUBNET:
527 if (((Subnet *)pObject)->getIpAddress().isValidUnicast())
528 {
529 if (IsZoningEnabled())
530 {
531 Zone *zone = (Zone *)g_idxZoneByGUID.get(((Subnet *)pObject)->getZoneId());
532 if (zone != NULL)
533 {
534 zone->removeFromIndex((Subnet *)pObject);
535 }
536 else
537 {
538 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for subnet object %s [%d]"),
539 (int)((Subnet *)pObject)->getZoneId(), pObject->getName(), (int)pObject->getId());
540 }
541 }
542 else
543 {
544 g_idxSubnetByAddr.remove(((Subnet *)pObject)->getIpAddress());
545 }
546 }
547 break;
548 case OBJECT_INTERFACE:
549 if (IsZoningEnabled())
550 {
551 Zone *zone = (Zone *)g_idxZoneByGUID.get(((Interface *)pObject)->getZoneId());
552 if (zone != NULL)
553 {
554 zone->removeFromIndex((Interface *)pObject);
555 }
556 else
557 {
558 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for interface object %s [%d]"),
559 (int)((Interface *)pObject)->getZoneId(), pObject->getName(), (int)pObject->getId());
560 }
561 }
562 else
563 {
564 const ObjectArray<InetAddress> *list = ((Interface *)pObject)->getIpAddressList()->getList();
565 for(int i = 0; i < list->size(); i++)
566 {
567 InetAddress *addr = list->get(i);
568 if (addr->isValidUnicast())
569 {
570 NetObj *o = g_idxInterfaceByAddr.get(*addr);
571 if ((o != NULL) && (o->getId() == pObject->getId()))
572 {
573 g_idxInterfaceByAddr.remove(*addr);
574 }
575 }
576 }
577 }
578 MacDbRemove(((Interface *)pObject)->getMacAddr());
579 break;
580 case OBJECT_ZONE:
581 g_idxZoneByGUID.remove(((Zone *)pObject)->getZoneId());
582 break;
583 case OBJECT_CONDITION:
584 g_idxConditionById.remove(pObject->getId());
585 break;
586 case OBJECT_SLMCHECK:
587 g_idxServiceCheckById.remove(pObject->getId());
588 break;
589 case OBJECT_NETWORKMAP:
590 g_idxNetMapById.remove(pObject->getId());
591 break;
592 default:
593 {
594 bool processed = false;
595 for(UINT32 i = 0; i < g_dwNumModules; i++)
596 {
597 if (g_pModuleList[i].pfNetObjDelete != NULL)
598 {
599 if (g_pModuleList[i].pfNetObjDelete(pObject))
600 processed = true;
601 }
602 }
603 if (!processed)
604 nxlog_write(MSG_BAD_NETOBJ_TYPE, EVENTLOG_ERROR_TYPE, "d", pObject->getObjectClass());
605 }
606 break;
607 }
608 }
609
610 /**
611 * Find access point by MAC address
612 */
613 AccessPoint NXCORE_EXPORTABLE *FindAccessPointByMAC(const BYTE *macAddr)
614 {
615 if (!memcmp(macAddr, "\x00\x00\x00\x00\x00\x00", 6))
616 return NULL;
617
618 NetObj *object = MacDbFind(macAddr);
619 return ((object != NULL) && (object->getObjectClass() == OBJECT_ACCESSPOINT)) ? (AccessPoint *)object : NULL;
620 }
621
622 /**
623 * Mobile device id comparator
624 */
625 static bool DeviceIdComparator(NetObj *object, void *deviceId)
626 {
627 return ((object->getObjectClass() == OBJECT_MOBILEDEVICE) && !object->isDeleted() &&
628 !_tcscmp((const TCHAR *)deviceId, ((MobileDevice *)object)->getDeviceId()));
629 }
630
631 /**
632 * Find mobile device by device ID
633 */
634 MobileDevice NXCORE_EXPORTABLE *FindMobileDeviceByDeviceID(const TCHAR *deviceId)
635 {
636 if ((deviceId == NULL) || (*deviceId == 0))
637 return NULL;
638
639 return (MobileDevice *)g_idxMobileDeviceById.find(DeviceIdComparator, (void *)deviceId);
640 }
641
642 static Node *FindNodeByIPInternal(UINT32 zoneId, const InetAddress& ipAddr)
643 {
644 Zone *zone = IsZoningEnabled() ? (Zone *)g_idxZoneByGUID.get(zoneId) : NULL;
645
646 Node *node = NULL;
647 if (IsZoningEnabled())
648 {
649 if (zone != NULL)
650 {
651 node = zone->getNodeByAddr(ipAddr);
652 }
653 }
654 else
655 {
656 node = (Node *)g_idxNodeByAddr.get(ipAddr);
657 }
658 if (node != NULL)
659 return node;
660
661 Interface *iface = NULL;
662 if (IsZoningEnabled())
663 {
664 if (zone != NULL)
665 {
666 iface = zone->getInterfaceByAddr(ipAddr);
667 }
668 }
669 else
670 {
671 iface = (Interface *)g_idxInterfaceByAddr.get(ipAddr);
672 }
673 return (iface != NULL) ? iface->getParentNode() : NULL;
674 }
675
676 /**
677 * Data for node find callback
678 */
679 struct NodeFindCBData
680 {
681 const InetAddress *addr;
682 Node *node;
683 };
684
685 /**
686 * Callback for finding node in all zones
687 */
688 static bool NodeFindCB(NetObj *zone, void *data)
689 {
690 Node *node = ((Zone *)zone)->getNodeByAddr(*((NodeFindCBData *)data)->addr);
691 if (node == NULL)
692 {
693 Interface *iface = ((Zone *)zone)->getInterfaceByAddr(*((NodeFindCBData *)data)->addr);
694 if (iface != NULL)
695 node = iface->getParentNode();
696 }
697
698 if (node == NULL)
699 return false;
700
701 ((NodeFindCBData *)data)->node = node;
702 return true;
703 }
704
705 /**
706 * Find node by IP address
707 */
708 Node NXCORE_EXPORTABLE *FindNodeByIP(UINT32 zoneId, const InetAddress& ipAddr)
709 {
710 if (!ipAddr.isValidUnicast())
711 return NULL;
712
713 if ((zoneId == ALL_ZONES) && IsZoningEnabled())
714 {
715 NodeFindCBData data;
716 data.addr = &ipAddr;
717 data.node = NULL;
718 g_idxZoneByGUID.find(NodeFindCB, &data);
719 return data.node;
720 }
721 else
722 {
723 return FindNodeByIPInternal(zoneId, ipAddr);
724 }
725 }
726
727 /**
728 * Find node by IP address using first match from IP address list
729 */
730 Node NXCORE_EXPORTABLE *FindNodeByIP(UINT32 zoneId, const InetAddressList *ipAddrList)
731 {
732 for(int i = 0; i < ipAddrList->size(); i++)
733 {
734 Node *node = FindNodeByIP(zoneId, ipAddrList->get(i));
735 if (node != NULL)
736 return node;
737 }
738 return NULL;
739 }
740
741 /**
742 * Find interface by IP address
743 */
744 Interface NXCORE_EXPORTABLE *FindInterfaceByIP(UINT32 zoneId, const InetAddress& ipAddr)
745 {
746 if (!ipAddr.isValidUnicast())
747 return NULL;
748
749 Zone *zone = IsZoningEnabled() ? (Zone *)g_idxZoneByGUID.get(zoneId) : NULL;
750
751 Interface *iface = NULL;
752 if (IsZoningEnabled())
753 {
754 if (zone != NULL)
755 {
756 iface = zone->getInterfaceByAddr(ipAddr);
757 }
758 }
759 else
760 {
761 iface = (Interface *)g_idxInterfaceByAddr.get(ipAddr);
762 }
763 return iface;
764 }
765
766 /**
767 * Find node by MAC address
768 */
769 Node NXCORE_EXPORTABLE *FindNodeByMAC(const BYTE *macAddr)
770 {
771 Interface *pInterface = FindInterfaceByMAC(macAddr);
772 return (pInterface != NULL) ? pInterface->getParentNode() : NULL;
773 }
774
775 /**
776 * Find interface by MAC address
777 */
778 Interface NXCORE_EXPORTABLE *FindInterfaceByMAC(const BYTE *macAddr)
779 {
780 if (!memcmp(macAddr, "\x00\x00\x00\x00\x00\x00", 6))
781 return NULL;
782
783 NetObj *object = MacDbFind(macAddr);
784 return ((object != NULL) && (object->getObjectClass() == OBJECT_INTERFACE)) ? (Interface *)object : NULL;
785 }
786
787 /**
788 * Interface description comparator
789 */
790 static bool DescriptionComparator(NetObj *object, void *description)
791 {
792 return ((object->getObjectClass() == OBJECT_INTERFACE) && !object->isDeleted() &&
793 !_tcscmp((const TCHAR *)description, ((Interface *)object)->getDescription()));
794 }
795
796 /**
797 * Find interface by description
798 */
799 Interface NXCORE_EXPORTABLE *FindInterfaceByDescription(const TCHAR *description)
800 {
801 return (Interface *)g_idxObjectById.find(DescriptionComparator, (void *)description);
802 }
803
804 /**
805 * LLDP ID comparator
806 */
807 static bool LldpIdComparator(NetObj *object, void *lldpId)
808 {
809 const TCHAR *id = ((Node *)object)->getLLDPNodeId();
810 return (id != NULL) && !_tcscmp(id, (const TCHAR *)lldpId);
811 }
812
813 /**
814 * Find node by LLDP ID
815 */
816 Node NXCORE_EXPORTABLE *FindNodeByLLDPId(const TCHAR *lldpId)
817 {
818 return (Node *)g_idxNodeById.find(LldpIdComparator, (void *)lldpId);
819 }
820
821 /**
822 * SNMP sysName comparator
823 */
824 static bool SysNameComparator(NetObj *object, void *sysName)
825 {
826 const TCHAR *n = ((Node *)object)->getSysName();
827 return (n != NULL) && !_tcscmp(n, (const TCHAR *)sysName);
828 }
829
830 /**
831 * Find node by SNMP sysName
832 */
833 Node NXCORE_EXPORTABLE *FindNodeBySysName(const TCHAR *sysName)
834 {
835 if ((sysName == NULL) || (sysName[0] == 0))
836 return NULL;
837 return (Node *)g_idxNodeById.find(SysNameComparator, (void *)sysName);
838 }
839
840 /**
841 * Bridge ID comparator
842 */
843 static bool BridgeIdComparator(NetObj *object, void *bridgeId)
844 {
845 return ((Node *)object)->isBridge() && !memcmp(((Node *)object)->getBridgeId(), bridgeId, MAC_ADDR_LENGTH);
846 }
847
848 /**
849 * Find node by bridge ID (bridge base address)
850 */
851 Node NXCORE_EXPORTABLE *FindNodeByBridgeId(const BYTE *bridgeId)
852 {
853 return (Node *)g_idxNodeById.find(BridgeIdComparator, (void *)bridgeId);
854 }
855
856 /**
857 * Find subnet by IP address
858 */
859 Subnet NXCORE_EXPORTABLE *FindSubnetByIP(UINT32 zoneId, const InetAddress& ipAddr)
860 {
861 if (!ipAddr.isValidUnicast())
862 return NULL;
863
864 Subnet *subnet = NULL;
865 if (IsZoningEnabled())
866 {
867 Zone *zone = (Zone *)g_idxZoneByGUID.get(zoneId);
868 if (zone != NULL)
869 {
870 subnet = zone->getSubnetByAddr(ipAddr);
871 }
872 }
873 else
874 {
875 subnet = (Subnet *)g_idxSubnetByAddr.get(ipAddr);
876 }
877 return subnet;
878 }
879
880 /**
881 * Subnet matching data
882 */
883 struct SUBNET_MATCHING_DATA
884 {
885 InetAddress ipAddr; // IP address to find subnet for
886 int maskLen; // Current match mask length
887 Subnet *subnet; // search result
888 };
889
890 /**
891 * Subnet matching callback
892 */
893 static void SubnetMatchCallback(const InetAddress& addr, NetObj *object, void *arg)
894 {
895 SUBNET_MATCHING_DATA *data = (SUBNET_MATCHING_DATA *)arg;
896 if (((Subnet *)object)->getIpAddress().contain(data->ipAddr))
897 {
898 int maskLen = ((Subnet *)object)->getIpAddress().getMaskBits();
899 if (maskLen > data->maskLen)
900 {
901 data->maskLen = maskLen;
902 data->subnet = (Subnet *)object;
903 }
904 }
905 }
906
907 /**
908 * Find subnet for given IP address
909 */
910 Subnet NXCORE_EXPORTABLE *FindSubnetForNode(UINT32 zoneId, const InetAddress& nodeAddr)
911 {
912 if (!nodeAddr.isValidUnicast())
913 return NULL;
914
915 SUBNET_MATCHING_DATA matchData;
916 matchData.ipAddr = nodeAddr;
917 matchData.maskLen = -1;
918 matchData.subnet = NULL;
919 if (IsZoningEnabled())
920 {
921 Zone *zone = (Zone *)g_idxZoneByGUID.get(zoneId);
922 if (zone != NULL)
923 {
924 zone->forEachSubnet(SubnetMatchCallback, &matchData);
925 }
926 }
927 else
928 {
929 g_idxSubnetByAddr.forEach(SubnetMatchCallback, &matchData);
930 }
931 return matchData.subnet;
932 }
933
934 /**
935 * Find object by ID
936 */
937 NetObj NXCORE_EXPORTABLE *FindObjectById(UINT32 dwId, int objClass)
938 {
939 NetObj *object = g_idxObjectById.get(dwId);
940 if ((object == NULL) || (objClass == -1))
941 return object;
942 return (objClass == object->getObjectClass()) ? object : NULL;
943 }
944
945 /**
946 * Get object name by ID
947 */
948 const TCHAR NXCORE_EXPORTABLE *GetObjectName(DWORD id, const TCHAR *defaultName)
949 {
950 NetObj *object = g_idxObjectById.get(id);
951 return (object != NULL) ? object->getName() : defaultName;
952 }
953
954 /**
955 * Callback data for FindObjectByName
956 */
957 struct __find_object_data
958 {
959 int objClass;
960 const TCHAR *name;
961 };
962
963 /**
964 * Object name comparator for FindObjectByName
965 */
966 static bool ObjectNameComparator(NetObj *object, void *data)
967 {
968 struct __find_object_data *fd = (struct __find_object_data *)data;
969 return ((fd->objClass == -1) || (fd->objClass == object->getObjectClass())) &&
970 !object->isDeleted() && !_tcsicmp(object->getName(), fd->name);
971 }
972
973 /**
974 * Find object by name
975 */
976 NetObj NXCORE_EXPORTABLE *FindObjectByName(const TCHAR *name, int objClass)
977 {
978 struct __find_object_data data;
979
980 data.objClass = objClass;
981 data.name = name;
982 return g_idxObjectById.find(ObjectNameComparator, &data);
983 }
984
985 /**
986 * GUID comparator for FindObjectByGUID
987 */
988 static bool ObjectGuidComparator(NetObj *object, void *data)
989 {
990 return !object->isDeleted() && object->getGuid().equals(*((const uuid *)data));
991 }
992
993 /**
994 * Find object by GUID
995 */
996 NetObj NXCORE_EXPORTABLE *FindObjectByGUID(const uuid& guid, int objClass)
997 {
998 NetObj *object = g_idxObjectById.find(ObjectGuidComparator, (void *)&guid);
999 return (object != NULL) ? (((objClass == -1) || (objClass == object->getObjectClass())) ? object : NULL) : NULL;
1000 }
1001
1002 /**
1003 * Template name comparator for FindTemplateByName
1004 */
1005 static bool TemplateNameComparator(NetObj *object, void *name)
1006 {
1007 return (object->getObjectClass() == OBJECT_TEMPLATE) && !object->isDeleted() && !_tcsicmp(object->getName(), (const TCHAR *)name);
1008 }
1009
1010 /**
1011 * Find template object by name
1012 */
1013 Template NXCORE_EXPORTABLE *FindTemplateByName(const TCHAR *pszName)
1014 {
1015 return (Template *)g_idxObjectById.find(TemplateNameComparator, (void *)pszName);
1016 }
1017
1018 /**
1019 * Callback for FindClusterByResourceIP
1020 */
1021 static bool ClusterResourceIPComparator(NetObj *object, void *ipAddr)
1022 {
1023 return (object->getObjectClass() == OBJECT_CLUSTER) && !object->isDeleted() && ((Cluster *)object)->isVirtualAddr(*((const InetAddress *)ipAddr));
1024 }
1025
1026 /**
1027 * Find cluster by resource IP
1028 */
1029 Cluster NXCORE_EXPORTABLE *FindClusterByResourceIP(const InetAddress& ipAddr)
1030 {
1031 return (Cluster *)g_idxObjectById.find(ClusterResourceIPComparator, (void *)&ipAddr);
1032 }
1033
1034 /**
1035 * Data structure for IsClusterIP callback
1036 */
1037 struct __cluster_ip_data
1038 {
1039 InetAddress ipAddr;
1040 UINT32 zoneId;
1041 };
1042
1043 /**
1044 * Cluster IP comparator - returns true if given address in given zone is cluster IP address
1045 */
1046 static bool ClusterIPComparator(NetObj *object, void *data)
1047 {
1048 struct __cluster_ip_data *d = (struct __cluster_ip_data *)data;
1049 return (object->getObjectClass() == OBJECT_CLUSTER) && !object->isDeleted() &&
1050 (((Cluster *)object)->getZoneId() == d->zoneId) &&
1051 (((Cluster *)object)->isVirtualAddr(d->ipAddr) ||
1052 ((Cluster *)object)->isSyncAddr(d->ipAddr));
1053 }
1054
1055 /**
1056 * Check if given IP address is used by cluster (it's either
1057 * resource IP or located on one of sync subnets)
1058 */
1059 bool NXCORE_EXPORTABLE IsClusterIP(UINT32 zoneId, const InetAddress& ipAddr)
1060 {
1061 struct __cluster_ip_data data;
1062 data.zoneId = zoneId;
1063 data.ipAddr = ipAddr;
1064 return g_idxObjectById.find(ClusterIPComparator, &data) != NULL;
1065 }
1066
1067 /**
1068 * Find zone object by GUID
1069 */
1070 Zone NXCORE_EXPORTABLE *FindZoneByGUID(UINT32 dwZoneGUID)
1071 {
1072 return (Zone *)g_idxZoneByGUID.get(dwZoneGUID);
1073 }
1074
1075 /**
1076 * Object comparator for FindLocalMgmtNode()
1077 */
1078 static bool LocalMgmtNodeComparator(NetObj *object, void *data)
1079 {
1080 return (((Node *)object)->getFlags() & NF_IS_LOCAL_MGMT) ? true : false;
1081 }
1082
1083 /**
1084 * Find local management node ID
1085 */
1086 UINT32 FindLocalMgmtNode()
1087 {
1088 NetObj *object = g_idxNodeById.find(LocalMgmtNodeComparator, NULL);
1089 return (object != NULL) ? object->getId() : 0;
1090 }
1091
1092 /**
1093 * ObjectIndex::forEach callback which recalculates object's status
1094 */
1095 static void RecalcStatusCallback(NetObj *object, void *data)
1096 {
1097 object->calculateCompoundStatus();
1098 }
1099
1100 /**
1101 * ObjectIndex::forEach callback which links container child objects
1102 */
1103 static void LinkChildObjectsCallback(NetObj *object, void *data)
1104 {
1105 if ((object->getObjectClass() == OBJECT_CONTAINER) ||
1106 (object->getObjectClass() == OBJECT_RACK) ||
1107 (object->getObjectClass() == OBJECT_TEMPLATEGROUP) ||
1108 (object->getObjectClass() == OBJECT_POLICYGROUP) ||
1109 (object->getObjectClass() == OBJECT_NETWORKMAPGROUP) ||
1110 (object->getObjectClass() == OBJECT_DASHBOARD) ||
1111 (object->getObjectClass() == OBJECT_BUSINESSSERVICE) ||
1112 (object->getObjectClass() == OBJECT_NODELINK))
1113 {
1114 ((Container *)object)->linkChildObjects();
1115 }
1116 }
1117
1118 /**
1119 * Load objects from database at stratup
1120 */
1121 BOOL LoadObjects()
1122 {
1123 DB_RESULT hResult;
1124 UINT32 i, dwNumRows;
1125 UINT32 dwId;
1126 Template *pTemplate;
1127 TCHAR szQuery[256];
1128
1129 // Prevent objects to change it's modification flag
1130 g_bModificationsLocked = TRUE;
1131
1132 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
1133
1134 // Load built-in object properties
1135 DbgPrintf(2, _T("Loading built-in object properties..."));
1136 g_pEntireNet->loadFromDatabase(hdb);
1137 g_pServiceRoot->loadFromDatabase(hdb);
1138 g_pTemplateRoot->loadFromDatabase(hdb);
1139 g_pPolicyRoot->loadFromDatabase(hdb);
1140 g_pMapRoot->loadFromDatabase(hdb);
1141 g_pDashboardRoot->loadFromDatabase(hdb);
1142 g_pBusinessServiceRoot->loadFromDatabase(hdb);
1143
1144 // Load zones
1145 if (g_flags & AF_ENABLE_ZONING)
1146 {
1147 Zone *pZone;
1148
1149 DbgPrintf(2, _T("Loading zones..."));
1150
1151 // Load (or create) default zone
1152 pZone = new Zone;
1153 pZone->generateGuid();
1154 pZone->loadFromDatabase(hdb, BUILTIN_OID_ZONE0);
1155 NetObjInsert(pZone, false, false);
1156 g_pEntireNet->AddZone(pZone);
1157
1158 hResult = DBSelect(hdb, _T("SELECT id FROM zones WHERE id<>4"));
1159 if (hResult != 0)
1160 {
1161 dwNumRows = DBGetNumRows(hResult);
1162 for(i = 0; i < dwNumRows; i++)
1163 {
1164 dwId = DBGetFieldULong(hResult, i, 0);
1165 pZone = new Zone;
1166 if (pZone->loadFromDatabase(hdb, dwId))
1167 {
1168 if (!pZone->isDeleted())
1169 g_pEntireNet->AddZone(pZone);
1170 NetObjInsert(pZone, false, false); // Insert into indexes
1171 }
1172 else // Object load failed
1173 {
1174 delete pZone;
1175 nxlog_write(MSG_ZONE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1176 }
1177 }
1178 DBFreeResult(hResult);
1179 }
1180 }
1181
1182 // Load conditions
1183 // We should load conditions before nodes because
1184 // DCI cache size calculation uses information from condition objects
1185 DbgPrintf(2, _T("Loading conditions..."));
1186 hResult = DBSelect(hdb, _T("SELECT id FROM conditions"));
1187 if (hResult != NULL)
1188 {
1189 Condition *pCondition;
1190
1191 dwNumRows = DBGetNumRows(hResult);
1192 for(i = 0; i < dwNumRows; i++)
1193 {
1194 dwId = DBGetFieldULong(hResult, i, 0);
1195 pCondition = new Condition;
1196 if (pCondition->loadFromDatabase(hdb, dwId))
1197 {
1198 NetObjInsert(pCondition, false, false); // Insert into indexes
1199 }
1200 else // Object load failed
1201 {
1202 delete pCondition;
1203 nxlog_write(MSG_CONDITION_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1204 }
1205 }
1206 DBFreeResult(hResult);
1207 }
1208
1209 // Load subnets
1210 DbgPrintf(2, _T("Loading subnets..."));
1211 hResult = DBSelect(hdb, _T("SELECT id FROM subnets"));
1212 if (hResult != 0)
1213 {
1214 Subnet *pSubnet;
1215
1216 dwNumRows = DBGetNumRows(hResult);
1217 for(i = 0; i < dwNumRows; i++)
1218 {
1219 dwId = DBGetFieldULong(hResult, i, 0);
1220 pSubnet = new Subnet;
1221 if (pSubnet->loadFromDatabase(hdb, dwId))
1222 {
1223 if (!pSubnet->isDeleted())
1224 {
1225 if (g_flags & AF_ENABLE_ZONING)
1226 {
1227 Zone *pZone;
1228
1229 pZone = FindZoneByGUID(pSubnet->getZoneId());
1230 if (pZone != NULL)
1231 pZone->addSubnet(pSubnet);
1232 }
1233 else
1234 {
1235 g_pEntireNet->AddSubnet(pSubnet);
1236 }
1237 }
1238 NetObjInsert(pSubnet, false, false); // Insert into indexes
1239 }
1240 else // Object load failed
1241 {
1242 delete pSubnet;
1243 nxlog_write(MSG_SUBNET_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1244 }
1245 }
1246 DBFreeResult(hResult);
1247 }
1248
1249 // Load racks
1250 DbgPrintf(2, _T("Loading racks..."));
1251 hResult = DBSelect(hdb, _T("SELECT id FROM racks"));
1252 if (hResult != 0)
1253 {
1254 Rack *rack;
1255
1256 dwNumRows = DBGetNumRows(hResult);
1257 for(i = 0; i < dwNumRows; i++)
1258 {
1259 dwId = DBGetFieldULong(hResult, i, 0);
1260 rack = new Rack;
1261 if (rack->loadFromDatabase(hdb, dwId))
1262 {
1263 NetObjInsert(rack, false, false); // Insert into indexes
1264 }
1265 else // Object load failed
1266 {
1267 nxlog_write(MSG_RACK_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1268 delete rack;
1269 }
1270 }
1271 DBFreeResult(hResult);
1272 }
1273
1274 // Load mobile devices
1275 DbgPrintf(2, _T("Loading mobile devices..."));
1276 hResult = DBSelect(hdb, _T("SELECT id FROM mobile_devices"));
1277 if (hResult != 0)
1278 {
1279 MobileDevice *md;
1280
1281 dwNumRows = DBGetNumRows(hResult);
1282 for(i = 0; i < dwNumRows; i++)
1283 {
1284 dwId = DBGetFieldULong(hResult, i, 0);
1285 md = new MobileDevice;
1286 if (md->loadFromDatabase(hdb, dwId))
1287 {
1288 NetObjInsert(md, false, false); // Insert into indexes
1289 }
1290 else // Object load failed
1291 {
1292 delete md;
1293 nxlog_write(MSG_MOBILEDEVICE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1294 }
1295 }
1296 DBFreeResult(hResult);
1297 }
1298
1299 // Load nodes
1300 DbgPrintf(2, _T("Loading nodes..."));
1301 hResult = DBSelect(hdb, _T("SELECT id FROM nodes"));
1302 if (hResult != NULL)
1303 {
1304 Node *pNode;
1305
1306 dwNumRows = DBGetNumRows(hResult);
1307 for(i = 0; i < dwNumRows; i++)
1308 {
1309 dwId = DBGetFieldULong(hResult, i, 0);
1310 pNode = new Node;
1311 if (pNode->loadFromDatabase(hdb, dwId))
1312 {
1313 NetObjInsert(pNode, false, false); // Insert into indexes
1314 }
1315 else // Object load failed
1316 {
1317 delete pNode;
1318 nxlog_write(MSG_NODE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1319 }
1320 }
1321 DBFreeResult(hResult);
1322 }
1323
1324 // Load access points
1325 DbgPrintf(2, _T("Loading access points..."));
1326 hResult = DBSelect(hdb, _T("SELECT id FROM access_points"));
1327 if (hResult != NULL)
1328 {
1329 AccessPoint *ap;
1330
1331 dwNumRows = DBGetNumRows(hResult);
1332 for(i = 0; i < dwNumRows; i++)
1333 {
1334 dwId = DBGetFieldULong(hResult, i, 0);
1335 ap = new AccessPoint;
1336 if (ap->loadFromDatabase(hdb, dwId))
1337 {
1338 NetObjInsert(ap, false, false); // Insert into indexes
1339 }
1340 else // Object load failed
1341 {
1342 nxlog_write(MSG_AP_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1343 delete ap;
1344 }
1345 }
1346 DBFreeResult(hResult);
1347 }
1348
1349 // Load interfaces
1350 DbgPrintf(2, _T("Loading interfaces..."));
1351 hResult = DBSelect(hdb, _T("SELECT id FROM interfaces"));
1352 if (hResult != 0)
1353 {
1354 Interface *pInterface;
1355
1356 dwNumRows = DBGetNumRows(hResult);
1357 for(i = 0; i < dwNumRows; i++)
1358 {
1359 dwId = DBGetFieldULong(hResult, i, 0);
1360 pInterface = new Interface;
1361 if (pInterface->loadFromDatabase(hdb, dwId))
1362 {
1363 NetObjInsert(pInterface, false, false); // Insert into indexes
1364 }
1365 else // Object load failed
1366 {
1367 nxlog_write(MSG_INTERFACE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1368 delete pInterface;
1369 }
1370 }
1371 DBFreeResult(hResult);
1372 }
1373
1374 // Load network services
1375 DbgPrintf(2, _T("Loading network services..."));
1376 hResult = DBSelect(hdb, _T("SELECT id FROM network_services"));
1377 if (hResult != 0)
1378 {
1379 NetworkService *pService;
1380
1381 dwNumRows = DBGetNumRows(hResult);
1382 for(i = 0; i < dwNumRows; i++)
1383 {
1384 dwId = DBGetFieldULong(hResult, i, 0);
1385 pService = new NetworkService;
1386 if (pService->loadFromDatabase(hdb, dwId))
1387 {
1388 NetObjInsert(pService, false, false); // Insert into indexes
1389 }
1390 else // Object load failed
1391 {
1392 delete pService;
1393 nxlog_write(MSG_NETSRV_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1394 }
1395 }
1396 DBFreeResult(hResult);
1397 }
1398
1399 // Load VPN connectors
1400 DbgPrintf(2, _T("Loading VPN connectors..."));
1401 hResult = DBSelect(hdb, _T("SELECT id FROM vpn_connectors"));
1402 if (hResult != NULL)
1403 {
1404 VPNConnector *pConnector;
1405
1406 dwNumRows = DBGetNumRows(hResult);
1407 for(i = 0; i < dwNumRows; i++)
1408 {
1409 dwId = DBGetFieldULong(hResult, i, 0);
1410 pConnector = new VPNConnector;
1411 if (pConnector->loadFromDatabase(hdb, dwId))
1412 {
1413 NetObjInsert(pConnector, false, false); // Insert into indexes
1414 }
1415 else // Object load failed
1416 {
1417 delete pConnector;
1418 nxlog_write(MSG_VPNC_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1419 }
1420 }
1421 DBFreeResult(hResult);
1422 }
1423
1424 // Load clusters
1425 DbgPrintf(2, _T("Loading clusters..."));
1426 hResult = DBSelect(hdb, _T("SELECT id FROM clusters"));
1427 if (hResult != NULL)
1428 {
1429 Cluster *pCluster;
1430
1431 dwNumRows = DBGetNumRows(hResult);
1432 for(i = 0; i < dwNumRows; i++)
1433 {
1434 dwId = DBGetFieldULong(hResult, i, 0);
1435 pCluster = new Cluster;
1436 if (pCluster->loadFromDatabase(hdb, dwId))
1437 {
1438 NetObjInsert(pCluster, false, false); // Insert into indexes
1439 }
1440 else // Object load failed
1441 {
1442 delete pCluster;
1443 nxlog_write(MSG_CLUSTER_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1444 }
1445 }
1446 DBFreeResult(hResult);
1447 }
1448
1449 // Start cache loading thread.
1450 // All data collection targets must be loaded at this point.
1451 ThreadCreate(CacheLoadingThread, 0, NULL);
1452
1453 // Load templates
1454 DbgPrintf(2, _T("Loading templates..."));
1455 hResult = DBSelect(hdb, _T("SELECT id FROM templates"));
1456 if (hResult != NULL)
1457 {
1458 dwNumRows = DBGetNumRows(hResult);
1459 for(i = 0; i < dwNumRows; i++)
1460 {
1461 dwId = DBGetFieldULong(hResult, i, 0);
1462 pTemplate = new Template;
1463 if (pTemplate->loadFromDatabase(hdb, dwId))
1464 {
1465 NetObjInsert(pTemplate, false, false); // Insert into indexes
1466 pTemplate->calculateCompoundStatus(); // Force status change to NORMAL
1467 }
1468 else // Object load failed
1469 {
1470 delete pTemplate;
1471 nxlog_write(MSG_TEMPLATE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1472 }
1473 }
1474 DBFreeResult(hResult);
1475 }
1476
1477 // Load agent policies
1478 DbgPrintf(2, _T("Loading agent policies..."));
1479 hResult = DBSelect(hdb, _T("SELECT id,policy_type FROM ap_common"));
1480 if (hResult != NULL)
1481 {
1482 dwNumRows = DBGetNumRows(hResult);
1483 for(i = 0; i < dwNumRows; i++)
1484 {
1485 AgentPolicy *policy;
1486
1487 dwId = DBGetFieldULong(hResult, i, 0);
1488 int type = DBGetFieldLong(hResult, i, 1);
1489 switch(type)
1490 {
1491 case AGENT_POLICY_CONFIG:
1492 policy = new AgentPolicyConfig();
1493 break;
1494 case AGENT_POLICY_LOG_PARSER:
1495 policy = new AgentPolicyLogParser();
1496 break;
1497 default:
1498 policy = new AgentPolicy(type);
1499 break;
1500 }
1501 if (policy->loadFromDatabase(hdb, dwId))
1502 {
1503 NetObjInsert(policy, false, false); // Insert into indexes
1504 policy->calculateCompoundStatus(); // Force status change to NORMAL
1505 }
1506 else // Object load failed
1507 {
1508 delete policy;
1509 nxlog_write(MSG_AGENTPOLICY_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1510 }
1511 }
1512 DBFreeResult(hResult);
1513 }
1514
1515 // Load network maps
1516 DbgPrintf(2, _T("Loading network maps..."));
1517 hResult = DBSelect(hdb, _T("SELECT id FROM network_maps"));
1518 if (hResult != NULL)
1519 {
1520 dwNumRows = DBGetNumRows(hResult);
1521 for(i = 0; i < dwNumRows; i++)
1522 {
1523 dwId = DBGetFieldULong(hResult, i, 0);
1524 NetworkMap *map = new NetworkMap;
1525 if (map->loadFromDatabase(hdb, dwId))
1526 {
1527 NetObjInsert(map, false, false); // Insert into indexes
1528 }
1529 else // Object load failed
1530 {
1531 delete map;
1532 nxlog_write(MSG_NETMAP_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1533 }
1534 }
1535 DBFreeResult(hResult);
1536 }
1537
1538 // Load container objects
1539 DbgPrintf(2, _T("Loading containers..."));
1540 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_CONTAINER);
1541 hResult = DBSelect(hdb, szQuery);
1542 if (hResult != 0)
1543 {
1544 Container *pContainer;
1545
1546 dwNumRows = DBGetNumRows(hResult);
1547 for(i = 0; i < dwNumRows; i++)
1548 {
1549 dwId = DBGetFieldULong(hResult, i, 0);
1550 pContainer = new Container;
1551 if (pContainer->loadFromDatabase(hdb, dwId))
1552 {
1553 NetObjInsert(pContainer, false, false); // Insert into indexes
1554 }
1555 else // Object load failed
1556 {
1557 delete pContainer;
1558 nxlog_write(MSG_CONTAINER_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1559 }
1560 }
1561 DBFreeResult(hResult);
1562 }
1563
1564 // Load template group objects
1565 DbgPrintf(2, _T("Loading template groups..."));
1566 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_TEMPLATEGROUP);
1567 hResult = DBSelect(hdb, szQuery);
1568 if (hResult != 0)
1569 {
1570 TemplateGroup *pGroup;
1571
1572 dwNumRows = DBGetNumRows(hResult);
1573 for(i = 0; i < dwNumRows; i++)
1574 {
1575 dwId = DBGetFieldULong(hResult, i, 0);
1576 pGroup = new TemplateGroup;
1577 if (pGroup->loadFromDatabase(hdb, dwId))
1578 {
1579 NetObjInsert(pGroup, false, false); // Insert into indexes
1580 }
1581 else // Object load failed
1582 {
1583 delete pGroup;
1584 nxlog_write(MSG_TG_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1585 }
1586 }
1587 DBFreeResult(hResult);
1588 }
1589
1590 // Load policy group objects
1591 DbgPrintf(2, _T("Loading policy groups..."));
1592 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_POLICYGROUP);
1593 hResult = DBSelect(hdb, szQuery);
1594 if (hResult != 0)
1595 {
1596 PolicyGroup *pGroup;
1597
1598 dwNumRows = DBGetNumRows(hResult);
1599 for(i = 0; i < dwNumRows; i++)
1600 {
1601 dwId = DBGetFieldULong(hResult, i, 0);
1602 pGroup = new PolicyGroup;
1603 if (pGroup->loadFromDatabase(hdb, dwId))
1604 {
1605 NetObjInsert(pGroup, false, false); // Insert into indexes
1606 }
1607 else // Object load failed
1608 {
1609 delete pGroup;
1610 nxlog_write(MSG_PG_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1611 }
1612 }
1613 DBFreeResult(hResult);
1614 }
1615
1616 // Load map group objects
1617 DbgPrintf(2, _T("Loading map groups..."));
1618 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_NETWORKMAPGROUP);
1619 hResult = DBSelect(hdb, szQuery);
1620 if (hResult != 0)
1621 {
1622 NetworkMapGroup *pGroup;
1623
1624 dwNumRows = DBGetNumRows(hResult);
1625 for(i = 0; i < dwNumRows; i++)
1626 {
1627 dwId = DBGetFieldULong(hResult, i, 0);
1628 pGroup = new NetworkMapGroup;
1629 if (pGroup->loadFromDatabase(hdb, dwId))
1630 {
1631 NetObjInsert(pGroup, false, false); // Insert into indexes
1632 }
1633 else // Object load failed
1634 {
1635 delete pGroup;
1636 nxlog_write(MSG_MG_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1637 }
1638 }
1639 DBFreeResult(hResult);
1640 }
1641
1642 // Load dashboard objects
1643 DbgPrintf(2, _T("Loading dashboards..."));
1644 hResult = DBSelect(hdb, _T("SELECT id FROM dashboards"));
1645 if (hResult != 0)
1646 {
1647 Dashboard *pd;
1648
1649 dwNumRows = DBGetNumRows(hResult);
1650 for(i = 0; i < dwNumRows; i++)
1651 {
1652 dwId = DBGetFieldULong(hResult, i, 0);
1653 pd = new Dashboard;
1654 if (pd->loadFromDatabase(hdb, dwId))
1655 {
1656 NetObjInsert(pd, false, false); // Insert into indexes
1657 }
1658 else // Object load failed
1659 {
1660 delete pd;
1661 nxlog_write(MSG_DASHBOARD_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1662 }
1663 }
1664 DBFreeResult(hResult);
1665 }
1666
1667 // Loading business service objects
1668 DbgPrintf(2, _T("Loading business services..."));
1669 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_BUSINESSSERVICE);
1670 hResult = DBSelect(hdb, szQuery);
1671 if (hResult != 0)
1672 {
1673 dwNumRows = DBGetNumRows(hResult);
1674 for(i = 0; i < dwNumRows; i++)
1675 {
1676 dwId = DBGetFieldULong(hResult, i, 0);
1677 BusinessService *service = new BusinessService;
1678 if (service->loadFromDatabase(hdb, dwId))
1679 {
1680 NetObjInsert(service, false, false); // Insert into indexes
1681 }
1682 else // Object load failed
1683 {
1684 delete service;
1685 nxlog_write(MSG_BUSINESS_SERVICE_LOAD_FAILED, NXLOG_ERROR, "d", dwId);
1686 }
1687 }
1688 DBFreeResult(hResult);
1689 }
1690
1691 // Loading business service objects
1692 DbgPrintf(2, _T("Loading node links..."));
1693 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_NODELINK);
1694 hResult = DBSelect(hdb, szQuery);
1695 if (hResult != 0)
1696 {
1697 dwNumRows = DBGetNumRows(hResult);
1698 for(i = 0; i < dwNumRows; i++)
1699 {
1700 dwId = DBGetFieldULong(hResult, i, 0);
1701 NodeLink *nl = new NodeLink;
1702 if (nl->loadFromDatabase(hdb, dwId))
1703 {
1704 NetObjInsert(nl, false, false); // Insert into indexes
1705 }
1706 else // Object load failed
1707 {
1708 delete nl;
1709 nxlog_write(MSG_NODE_LINK_LOAD_FAILED, NXLOG_ERROR, "d", dwId);
1710 }
1711 }
1712 DBFreeResult(hResult);
1713 }
1714
1715 // Load service check objects
1716 DbgPrintf(2, _T("Loading service checks..."));
1717 hResult = DBSelect(hdb, _T("SELECT id FROM slm_checks"));
1718 if (hResult != 0)
1719 {
1720 dwNumRows = DBGetNumRows(hResult);
1721 for(i = 0; i < dwNumRows; i++)
1722 {
1723 dwId = DBGetFieldULong(hResult, i, 0);
1724 SlmCheck *check = new SlmCheck;
1725 if (check->loadFromDatabase(hdb, dwId))
1726 {
1727 NetObjInsert(check, false, false); // Insert into indexes
1728 }
1729 else // Object load failed
1730 {
1731 delete check;
1732 nxlog_write(MSG_SERVICE_CHECK_LOAD_FAILED, NXLOG_ERROR, "d", dwId);
1733 }
1734 }
1735 DBFreeResult(hResult);
1736 }
1737
1738 DBConnectionPoolReleaseConnection(hdb);
1739
1740 // Load custom object classes provided by modules
1741 CALL_ALL_MODULES(pfLoadObjects, ());
1742
1743 // Link children to container and template group objects
1744 DbgPrintf(2, _T("Linking objects..."));
1745 g_idxObjectById.forEach(LinkChildObjectsCallback, NULL);
1746
1747 // Link children to root objects
1748 g_pServiceRoot->linkChildObjects();
1749 g_pTemplateRoot->linkChildObjects();
1750 g_pPolicyRoot->linkChildObjects();
1751 g_pMapRoot->linkChildObjects();
1752 g_pDashboardRoot->linkChildObjects();
1753 g_pBusinessServiceRoot->linkChildObjects();
1754
1755 // Link custom object classes provided by modules
1756 CALL_ALL_MODULES(pfLinkObjects, ());
1757
1758 // Allow objects to change it's modification flag
1759 g_bModificationsLocked = FALSE;
1760
1761 // Recalculate status for built-in objects
1762 g_pEntireNet->calculateCompoundStatus();
1763 g_pServiceRoot->calculateCompoundStatus();
1764 g_pTemplateRoot->calculateCompoundStatus();
1765 g_pPolicyRoot->calculateCompoundStatus();
1766 g_pMapRoot->calculateCompoundStatus();
1767 g_pBusinessServiceRoot->calculateCompoundStatus();
1768
1769 // Recalculate status for zone objects
1770 if (g_flags & AF_ENABLE_ZONING)
1771 {
1772 g_idxZoneByGUID.forEach(RecalcStatusCallback, NULL);
1773 }
1774
1775 // Start map update thread
1776 ThreadCreate(MapUpdateThread, 0, NULL);
1777
1778 // Start template update applying thread
1779 ThreadCreate(ApplyTemplateThread, 0, NULL);
1780
1781 return TRUE;
1782 }
1783
1784 /**
1785 * Callback for DeleteUserFromAllObjects
1786 */
1787 static void DropUserAccess(NetObj *object, void *userId)
1788 {
1789 object->dropUserAccess(CAST_FROM_POINTER(userId, UINT32));
1790 }
1791
1792 /**
1793 * Delete user or group from all objects' ACLs
1794 */
1795 void DeleteUserFromAllObjects(UINT32 dwUserId)
1796 {
1797 g_idxObjectById.forEach(DropUserAccess, CAST_TO_POINTER(dwUserId, void *));
1798 }
1799
1800 /**
1801 * User data for DumpObjectCallback
1802 */
1803 struct __dump_objects_data
1804 {
1805 CONSOLE_CTX console;
1806 TCHAR *buffer;
1807 const TCHAR *filter;
1808 };
1809
1810 /**
1811 * Enumeration callback for DumpObjects
1812 */
1813 static void DumpObjectCallback(NetObj *object, void *data)
1814 {
1815 struct __dump_objects_data *dd = (struct __dump_objects_data *)data;
1816
1817 // Apply name filter
1818 if ((dd->filter != NULL) && !MatchString(dd->filter, object->getName(), false))
1819 return;
1820
1821 CONSOLE_CTX pCtx = dd->console;
1822
1823 ConsolePrintf(pCtx, _T("Object ID %d \"%s\"\n")
1824 _T(" Class: %s Status: %s IsModified: %d IsDeleted: %d\n"),
1825 object->getId(), object->getName(), object->getObjectClassName(),
1826 GetStatusAsText(object->Status(), true),
1827 object->isModified(), object->isDeleted());
1828 ConsolePrintf(pCtx, _T(" Parents: <%s>\n Childs: <%s>\n"),
1829 object->dbgGetParentList(dd->buffer), object->dbgGetChildList(&dd->buffer[4096]));
1830 time_t t = object->getTimeStamp();
1831 struct tm *ltm = localtime(&t);
1832 _tcsftime(dd->buffer, 256, _T("%d.%b.%Y %H:%M:%S"), ltm);
1833 ConsolePrintf(pCtx, _T(" Last change: %s\n"), dd->buffer);
1834 switch(object->getObjectClass())
1835 {
1836 case OBJECT_NODE:
1837 ConsolePrintf(pCtx, _T(" Primary IP: %s\n IsSNMP: %d IsAgent: %d IsLocal: %d OID: %s\n"),
1838 ((Node *)object)->getIpAddress().toString(dd->buffer),
1839 ((Node *)object)->isSNMPSupported(),
1840 ((Node *)object)->isNativeAgent(),
1841 ((Node *)object)->isLocalManagement(),
1842 ((Node *)object)->getObjectId());
1843 break;
1844 case OBJECT_SUBNET:
1845 ConsolePrintf(pCtx, _T(" IP address: %s/%d\n"), ((Subnet *)object)->getIpAddress().toString(dd->buffer), ((Subnet *)object)->getIpAddress().getMaskBits());
1846 break;
1847 case OBJECT_ACCESSPOINT:
1848 ConsolePrintf(pCtx, _T(" IP address: %s\n"), ((AccessPoint *)object)->getIpAddress().toString(dd->buffer));
1849 break;
1850 case OBJECT_INTERFACE:
1851 ConsolePrintf(pCtx, _T(" MAC address: %s\n"), MACToStr(((Interface *)object)->getMacAddr(), dd->buffer));
1852 for(int n = 0; n < ((Interface *)object)->getIpAddressList()->size(); n++)
1853 {
1854 const InetAddress& a = ((Interface *)object)->getIpAddressList()->get(n);
1855 ConsolePrintf(pCtx, _T(" IP address: %s/%d\n"), a.toString(dd->buffer), a.getMaskBits());
1856 }
1857 break;
1858 case OBJECT_TEMPLATE:
1859 ConsolePrintf(pCtx, _T(" Version: %d.%d\n"),
1860 ((Template *)(object))->getVersionMajor(),
1861 ((Template *)(object))->getVersionMinor());
1862 break;
1863 }
1864 }
1865
1866 /**
1867 * Dump objects to debug console
1868 */
1869 void DumpObjects(CONSOLE_CTX pCtx, const TCHAR *filter)
1870 {
1871 struct __dump_objects_data data;
1872
1873 data.buffer = (TCHAR *)malloc(128000 * sizeof(TCHAR));
1874 data.console = pCtx;
1875 data.filter = filter;
1876 g_idxObjectById.forEach(DumpObjectCallback, &data);
1877 free(data.buffer);
1878 }
1879
1880 /**
1881 * Check is given object class is a valid parent class for other object
1882 * This function is used to check manually created bindings, so it won't
1883 * return TRUE for node -- subnet for example
1884 */
1885 bool IsValidParentClass(int iChildClass, int iParentClass)
1886 {
1887 switch(iParentClass)
1888 {
1889 case OBJECT_NETWORK:
1890 if ((iChildClass == OBJECT_ZONE) && (g_flags & AF_ENABLE_ZONING))
1891 return true;
1892 break;
1893 case OBJECT_SERVICEROOT:
1894 case OBJECT_CONTAINER:
1895 if ((iChildClass == OBJECT_CONTAINER) ||
1896 (iChildClass == OBJECT_RACK) ||
1897 (iChildClass == OBJECT_NODE) ||
1898 (iChildClass == OBJECT_CLUSTER) ||
1899 (iChildClass == OBJECT_MOBILEDEVICE) ||
1900 (iChildClass == OBJECT_CONDITION) ||
1901 (iChildClass == OBJECT_SUBNET))
1902 return true;
1903 break;
1904 case OBJECT_RACK:
1905 if (iChildClass == OBJECT_NODE)
1906 return true;
1907 break;
1908 case OBJECT_TEMPLATEROOT:
1909 case OBJECT_TEMPLATEGROUP:
1910 if ((iChildClass == OBJECT_TEMPLATEGROUP) ||
1911 (iChildClass == OBJECT_TEMPLATE))
1912 return true;
1913 break;
1914 case OBJECT_TEMPLATE:
1915 if ((iChildClass == OBJECT_NODE) ||
1916 (iChildClass == OBJECT_CLUSTER) ||
1917 (iChildClass == OBJECT_MOBILEDEVICE))
1918 return true;
1919 break;
1920 case OBJECT_NETWORKMAPROOT:
1921 case OBJECT_NETWORKMAPGROUP:
1922 if ((iChildClass == OBJECT_NETWORKMAPGROUP) ||
1923 (iChildClass == OBJECT_NETWORKMAP))
1924 return true;
1925 break;
1926 case OBJECT_DASHBOARDROOT:
1927 case OBJECT_DASHBOARD:
1928 if (iChildClass == OBJECT_DASHBOARD)
1929 return true;
1930 break;
1931 case OBJECT_POLICYROOT:
1932 case OBJECT_POLICYGROUP:
1933 if ((iChildClass == OBJECT_POLICYGROUP) ||
1934 (iChildClass == OBJECT_AGENTPOLICY) ||
1935 (iChildClass == OBJECT_AGENTPOLICY_CONFIG) ||
1936 (iChildClass == OBJECT_AGENTPOLICY_LOGPARSER))
1937 return true;
1938 break;
1939 case OBJECT_NODE:
1940 if ((iChildClass == OBJECT_NETWORKSERVICE) ||
1941 (iChildClass == OBJECT_VPNCONNECTOR) ||
1942 (iChildClass == OBJECT_INTERFACE))
1943 return true;
1944 break;
1945 case OBJECT_CLUSTER:
1946 if (iChildClass == OBJECT_NODE)
1947 return true;
1948 break;
1949 case OBJECT_BUSINESSSERVICEROOT:
1950 if ((iChildClass == OBJECT_BUSINESSSERVICE) ||
1951 (iChildClass == OBJECT_NODELINK))
1952 return true;
1953 break;
1954 case OBJECT_BUSINESSSERVICE:
1955 if ((iChildClass == OBJECT_BUSINESSSERVICE) ||
1956 (iChildClass == OBJECT_NODELINK) ||
1957 (iChildClass == OBJECT_SLMCHECK))
1958 return true;
1959 break;
1960 case OBJECT_NODELINK:
1961 if (iChildClass == OBJECT_SLMCHECK)
1962 return true;
1963 break;
1964 case -1: // Creating object without parent
1965 if (iChildClass == OBJECT_NODE)
1966 return true; // OK only for nodes, because parent subnet will be created automatically
1967 break;
1968 }
1969
1970 // Additional check by loaded modules
1971 for(UINT32 i = 0; i < g_dwNumModules; i++)
1972 {
1973 if (g_pModuleList[i].pfIsValidParentClass != NULL)
1974 {
1975 if (g_pModuleList[i].pfIsValidParentClass(iChildClass, iParentClass))
1976 return true; // accepted by module
1977 }
1978 }
1979
1980 return false;
1981 }
1982
1983 /**
1984 * Callback for postponed object deletion
1985 */
1986 static void DeleteObjectCallback(void *arg)
1987 {
1988 NetObj *object = (NetObj *)arg;
1989 while(object->getRefCount() > 0)
1990 ThreadSleep(1);
1991 DbgPrintf(4, _T("Executing postponed delete of object %s [%d]"), object->getName(), object->getId());
1992 delete object;
1993 }
1994
1995 /**
1996 * Delete object (final step)
1997 * This function should be called ONLY from syncer thread
1998 * Object will be removed from index by ID and destroyed.
1999 */
2000 void NetObjDelete(NetObj *object)
2001 {
2002 DbgPrintf(4, _T("Final delete step for object %s [%d]"), object->getName(), object->getId());
2003
2004 // Delete object from index by ID and object itself
2005 g_idxObjectById.remove(object->getId());
2006 if (object->getRefCount() == 0)
2007 {
2008 delete object;
2009 }
2010 else
2011 {
2012 DbgPrintf(4, _T("Object %s [%d] has %d references at final delete step - postpone deletion"), object->getName(), object->getId());
2013 ThreadPoolExecuteSerialized(g_mainThreadPool, _T("DeleteObject"), DeleteObjectCallback, object);
2014 }
2015 }
2016
2017 /**
2018 * Update interface index when IP address changes
2019 */
2020 void UpdateInterfaceIndex(const InetAddress& oldIpAddr, const InetAddress& newIpAddr, Interface *iface)
2021 {
2022 if (IsZoningEnabled())
2023 {
2024 Zone *zone = (Zone *)g_idxZoneByGUID.get(iface->getZoneId());
2025 if (zone != NULL)
2026 {
2027 zone->updateInterfaceIndex(oldIpAddr, newIpAddr, iface);
2028 }
2029 else
2030 {
2031 DbgPrintf(1, _T("UpdateInterfaceIndex: Cannot find zone object for interface %s [%d] (zone id %d)"),
2032 iface->getName(), (int)iface->getId(), (int)iface->getZoneId());
2033 }
2034 }
2035 else
2036 {
2037 g_idxInterfaceByAddr.remove(oldIpAddr);
2038 g_idxInterfaceByAddr.put(newIpAddr, iface);
2039 }
2040 }
2041
2042 /**
2043 * Calculate propagated status for object using default algorithm
2044 */
2045 int DefaultPropagatedStatus(int iObjectStatus)
2046 {
2047 int iStatus;
2048
2049 switch(m_iStatusPropAlg)
2050 {
2051 case SA_PROPAGATE_UNCHANGED:
2052 iStatus = iObjectStatus;
2053 break;
2054 case SA_PROPAGATE_FIXED:
2055 iStatus = ((iObjectStatus > STATUS_NORMAL) && (iObjectStatus < STATUS_UNKNOWN)) ? m_iFixedStatus : iObjectStatus;
2056 break;
2057 case SA_PROPAGATE_RELATIVE:
2058 if ((iObjectStatus > STATUS_NORMAL) && (iObjectStatus < STATUS_UNKNOWN))
2059 {
2060 iStatus = iObjectStatus + m_iStatusShift;
2061 if (iStatus < 0)
2062 iStatus = 0;
2063 if (iStatus > STATUS_CRITICAL)
2064 iStatus = STATUS_CRITICAL;
2065 }
2066 else
2067 {
2068 iStatus = iObjectStatus;
2069 }
2070 break;
2071 case SA_PROPAGATE_TRANSLATED:
2072 if ((iObjectStatus > STATUS_NORMAL) && (iObjectStatus < STATUS_UNKNOWN))
2073 {
2074 iStatus = m_iStatusTranslation[iObjectStatus - 1];
2075 }
2076 else
2077 {
2078 iStatus = iObjectStatus;
2079 }
2080 break;
2081 default:
2082 iStatus = STATUS_UNKNOWN;
2083 break;
2084 }
2085 return iStatus;
2086 }
2087
2088 /**
2089 * Get default data for status calculation
2090 */
2091 int GetDefaultStatusCalculation(int *pnSingleThreshold, int **ppnThresholds)
2092 {
2093 *pnSingleThreshold = m_iStatusSingleThreshold;
2094 *ppnThresholds = m_iStatusThresholds;
2095 return m_iStatusCalcAlg;
2096 }
2097
2098 /**
2099 * Check if given object is an agent policy object
2100 */
2101 bool IsAgentPolicyObject(NetObj *object)
2102 {
2103 return (object->getObjectClass() == OBJECT_AGENTPOLICY) || (object->getObjectClass() == OBJECT_AGENTPOLICY_CONFIG);
2104 }
2105
2106 /**
2107 * Returns true if object of given class can be event source
2108 */
2109 bool IsEventSource(int objectClass)
2110 {
2111 return (objectClass == OBJECT_NODE) ||
2112 (objectClass == OBJECT_CONTAINER) ||
2113 (objectClass == OBJECT_CLUSTER) ||
2114 (objectClass == OBJECT_MOBILEDEVICE);
2115 }