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