cb8e33142a600b1241d25af1077352c12ad465c1
[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 container child objects
1108 */
1109 static void LinkChildObjectsCallback(NetObj *object, void *data)
1110 {
1111 if ((object->getObjectClass() == OBJECT_CONTAINER) ||
1112 (object->getObjectClass() == OBJECT_RACK) ||
1113 (object->getObjectClass() == OBJECT_TEMPLATEGROUP) ||
1114 (object->getObjectClass() == OBJECT_POLICYGROUP) ||
1115 (object->getObjectClass() == OBJECT_NETWORKMAPGROUP) ||
1116 (object->getObjectClass() == OBJECT_DASHBOARD) ||
1117 (object->getObjectClass() == OBJECT_BUSINESSSERVICE) ||
1118 (object->getObjectClass() == OBJECT_NODELINK))
1119 {
1120 ((Container *)object)->linkChildObjects();
1121 }
1122 }
1123
1124 /**
1125 * Load objects from database at stratup
1126 */
1127 BOOL LoadObjects()
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 DB_RESULT hResult = DBSelect(hdb, _T("SELECT id FROM zones WHERE id<>4"));
1159 if (hResult != NULL)
1160 {
1161 int count = DBGetNumRows(hResult);
1162 for(int i = 0; i < count; i++)
1163 {
1164 UINT32 id = DBGetFieldULong(hResult, i, 0);
1165 pZone = new Zone;
1166 if (pZone->loadFromDatabase(hdb, id))
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, NXLOG_ERROR, "d", id);
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 DB_RESULT hResult = DBSelect(hdb, _T("SELECT id FROM conditions"));
1187 if (hResult != NULL)
1188 {
1189 int count = DBGetNumRows(hResult);
1190 for(int i = 0; i < count; i++)
1191 {
1192 UINT32 id = DBGetFieldULong(hResult, i, 0);
1193 Condition *condition = new Condition;
1194 if (condition->loadFromDatabase(hdb, id))
1195 {
1196 NetObjInsert(condition, false, false); // Insert into indexes
1197 }
1198 else // Object load failed
1199 {
1200 delete condition;
1201 nxlog_write(MSG_CONDITION_LOAD_FAILED, NXLOG_ERROR, "d", id);
1202 }
1203 }
1204 DBFreeResult(hResult);
1205 }
1206
1207 // Load subnets
1208 DbgPrintf(2, _T("Loading subnets..."));
1209 hResult = DBSelect(hdb, _T("SELECT id FROM subnets"));
1210 if (hResult != NULL)
1211 {
1212 int count = DBGetNumRows(hResult);
1213 for(int i = 0; i < count; i++)
1214 {
1215 UINT32 id = DBGetFieldULong(hResult, i, 0);
1216 Subnet *subnet = new Subnet;
1217 if (subnet->loadFromDatabase(hdb, id))
1218 {
1219 if (!subnet->isDeleted())
1220 {
1221 if (g_flags & AF_ENABLE_ZONING)
1222 {
1223 Zone *pZone;
1224
1225 pZone = FindZoneByGUID(subnet->getZoneId());
1226 if (pZone != NULL)
1227 pZone->addSubnet(subnet);
1228 }
1229 else
1230 {
1231 g_pEntireNet->AddSubnet(subnet);
1232 }
1233 }
1234 NetObjInsert(subnet, false, false); // Insert into indexes
1235 }
1236 else // Object load failed
1237 {
1238 delete subnet;
1239 nxlog_write(MSG_SUBNET_LOAD_FAILED, NXLOG_ERROR, "d", id);
1240 }
1241 }
1242 DBFreeResult(hResult);
1243 }
1244
1245 // Load racks
1246 DbgPrintf(2, _T("Loading racks..."));
1247 hResult = DBSelect(hdb, _T("SELECT id FROM racks"));
1248 if (hResult != NULL)
1249 {
1250 int count = DBGetNumRows(hResult);
1251 for(int i = 0; i < count; i++)
1252 {
1253 UINT32 id = DBGetFieldULong(hResult, i, 0);
1254 Rack *rack = new Rack;
1255 if (rack->loadFromDatabase(hdb, id))
1256 {
1257 NetObjInsert(rack, false, false); // Insert into indexes
1258 }
1259 else // Object load failed
1260 {
1261 nxlog_write(MSG_RACK_LOAD_FAILED, NXLOG_ERROR, "d", id);
1262 delete rack;
1263 }
1264 }
1265 DBFreeResult(hResult);
1266 }
1267
1268 // Load chassis
1269 DbgPrintf(2, _T("Loading chassis..."));
1270 hResult = DBSelect(hdb, _T("SELECT id FROM chassis"));
1271 if (hResult != NULL)
1272 {
1273 int count = DBGetNumRows(hResult);
1274 for(int i = 0; i < count; i++)
1275 {
1276 UINT32 id = DBGetFieldULong(hResult, i, 0);
1277 Chassis *chassis = new Chassis;
1278 if (chassis->loadFromDatabase(hdb, id))
1279 {
1280 NetObjInsert(chassis, false, false); // Insert into indexes
1281 }
1282 else // Object load failed
1283 {
1284 nxlog_write(MSG_CHASSIS_LOAD_FAILED, NXLOG_ERROR, "d", id);
1285 delete chassis;
1286 }
1287 }
1288 DBFreeResult(hResult);
1289 }
1290
1291 // Load mobile devices
1292 DbgPrintf(2, _T("Loading mobile devices..."));
1293 hResult = DBSelect(hdb, _T("SELECT id FROM mobile_devices"));
1294 if (hResult != NULL)
1295 {
1296 int count = DBGetNumRows(hResult);
1297 for(int i = 0; i < count; i++)
1298 {
1299 UINT32 id = DBGetFieldULong(hResult, i, 0);
1300 MobileDevice *md = new MobileDevice;
1301 if (md->loadFromDatabase(hdb, id))
1302 {
1303 NetObjInsert(md, false, false); // Insert into indexes
1304 }
1305 else // Object load failed
1306 {
1307 delete md;
1308 nxlog_write(MSG_MOBILEDEVICE_LOAD_FAILED, NXLOG_ERROR, "d", id);
1309 }
1310 }
1311 DBFreeResult(hResult);
1312 }
1313
1314 // Load nodes
1315 DbgPrintf(2, _T("Loading nodes..."));
1316 hResult = DBSelect(hdb, _T("SELECT id FROM nodes"));
1317 if (hResult != NULL)
1318 {
1319 int count = DBGetNumRows(hResult);
1320 for(int i = 0; i < count; i++)
1321 {
1322 UINT32 id = DBGetFieldULong(hResult, i, 0);
1323 Node *node = new Node;
1324 if (node->loadFromDatabase(hdb, id))
1325 {
1326 NetObjInsert(node, false, false); // Insert into indexes
1327 }
1328 else // Object load failed
1329 {
1330 delete node;
1331 nxlog_write(MSG_NODE_LOAD_FAILED, NXLOG_ERROR, "d", id);
1332 }
1333 }
1334 DBFreeResult(hResult);
1335 }
1336
1337 // Load access points
1338 DbgPrintf(2, _T("Loading access points..."));
1339 hResult = DBSelect(hdb, _T("SELECT id FROM access_points"));
1340 if (hResult != NULL)
1341 {
1342 int count = DBGetNumRows(hResult);
1343 for(int i = 0; i < count; i++)
1344 {
1345 UINT32 id = DBGetFieldULong(hResult, i, 0);
1346 AccessPoint *ap = new AccessPoint;
1347 if (ap->loadFromDatabase(hdb, id))
1348 {
1349 NetObjInsert(ap, false, false); // Insert into indexes
1350 }
1351 else // Object load failed
1352 {
1353 nxlog_write(MSG_AP_LOAD_FAILED, NXLOG_ERROR, "d", id);
1354 delete ap;
1355 }
1356 }
1357 DBFreeResult(hResult);
1358 }
1359
1360 // Load interfaces
1361 DbgPrintf(2, _T("Loading interfaces..."));
1362 hResult = DBSelect(hdb, _T("SELECT id FROM interfaces"));
1363 if (hResult != NULL)
1364 {
1365 int count = DBGetNumRows(hResult);
1366 for(int i = 0; i < count; i++)
1367 {
1368 UINT32 id = DBGetFieldULong(hResult, i, 0);
1369 Interface *iface = new Interface;
1370 if (iface->loadFromDatabase(hdb, id))
1371 {
1372 NetObjInsert(iface, false, false); // Insert into indexes
1373 }
1374 else // Object load failed
1375 {
1376 nxlog_write(MSG_INTERFACE_LOAD_FAILED, NXLOG_ERROR, "d", id);
1377 delete iface;
1378 }
1379 }
1380 DBFreeResult(hResult);
1381 }
1382
1383 // Load network services
1384 DbgPrintf(2, _T("Loading network services..."));
1385 hResult = DBSelect(hdb, _T("SELECT id FROM network_services"));
1386 if (hResult != NULL)
1387 {
1388 int count = DBGetNumRows(hResult);
1389 for(int i = 0; i < count; i++)
1390 {
1391 UINT32 id = DBGetFieldULong(hResult, i, 0);
1392 NetworkService *service = new NetworkService;
1393 if (service->loadFromDatabase(hdb, id))
1394 {
1395 NetObjInsert(service, false, false); // Insert into indexes
1396 }
1397 else // Object load failed
1398 {
1399 delete service;
1400 nxlog_write(MSG_NETSRV_LOAD_FAILED, NXLOG_ERROR, "d", id);
1401 }
1402 }
1403 DBFreeResult(hResult);
1404 }
1405
1406 // Load VPN connectors
1407 DbgPrintf(2, _T("Loading VPN connectors..."));
1408 hResult = DBSelect(hdb, _T("SELECT id FROM vpn_connectors"));
1409 if (hResult != NULL)
1410 {
1411 int count = DBGetNumRows(hResult);
1412 for(int i = 0; i < count; i++)
1413 {
1414 UINT32 id = DBGetFieldULong(hResult, i, 0);
1415 VPNConnector *connector = new VPNConnector;
1416 if (connector->loadFromDatabase(hdb, id))
1417 {
1418 NetObjInsert(connector, false, false); // Insert into indexes
1419 }
1420 else // Object load failed
1421 {
1422 delete connector;
1423 nxlog_write(MSG_VPNC_LOAD_FAILED, NXLOG_ERROR, "d", id);
1424 }
1425 }
1426 DBFreeResult(hResult);
1427 }
1428
1429 // Load clusters
1430 DbgPrintf(2, _T("Loading clusters..."));
1431 hResult = DBSelect(hdb, _T("SELECT id FROM clusters"));
1432 if (hResult != NULL)
1433 {
1434 int count = DBGetNumRows(hResult);
1435 for(int i = 0; i < count; i++)
1436 {
1437 UINT32 id = DBGetFieldULong(hResult, i, 0);
1438 Cluster *cluster = new Cluster;
1439 if (cluster->loadFromDatabase(hdb, id))
1440 {
1441 NetObjInsert(cluster, false, false); // Insert into indexes
1442 }
1443 else // Object load failed
1444 {
1445 delete cluster;
1446 nxlog_write(MSG_CLUSTER_LOAD_FAILED, NXLOG_ERROR, "d", id);
1447 }
1448 }
1449 DBFreeResult(hResult);
1450 }
1451
1452 // Start cache loading thread.
1453 // All data collection targets must be loaded at this point.
1454 ThreadCreate(CacheLoadingThread, 0, NULL);
1455
1456 // Load templates
1457 DbgPrintf(2, _T("Loading templates..."));
1458 hResult = DBSelect(hdb, _T("SELECT id FROM templates"));
1459 if (hResult != NULL)
1460 {
1461 int count = DBGetNumRows(hResult);
1462 for(int i = 0; i < count; i++)
1463 {
1464 UINT32 id = DBGetFieldULong(hResult, i, 0);
1465 Template *tmpl = new Template;
1466 if (tmpl->loadFromDatabase(hdb, id))
1467 {
1468 NetObjInsert(tmpl, false, false); // Insert into indexes
1469 tmpl->calculateCompoundStatus(); // Force status change to NORMAL
1470 }
1471 else // Object load failed
1472 {
1473 delete tmpl;
1474 nxlog_write(MSG_TEMPLATE_LOAD_FAILED, NXLOG_ERROR, "d", id);
1475 }
1476 }
1477 DBFreeResult(hResult);
1478 }
1479
1480 // Load agent policies
1481 DbgPrintf(2, _T("Loading agent policies..."));
1482 hResult = DBSelect(hdb, _T("SELECT id,policy_type FROM ap_common"));
1483 if (hResult != NULL)
1484 {
1485 int count = DBGetNumRows(hResult);
1486 for(int i = 0; i < count; i++)
1487 {
1488 AgentPolicy *policy;
1489
1490 UINT32 id = DBGetFieldULong(hResult, i, 0);
1491 int type = DBGetFieldLong(hResult, i, 1);
1492 switch(type)
1493 {
1494 case AGENT_POLICY_CONFIG:
1495 policy = new AgentPolicyConfig();
1496 break;
1497 case AGENT_POLICY_LOG_PARSER:
1498 policy = new AgentPolicyLogParser();
1499 break;
1500 default:
1501 policy = new AgentPolicy(type);
1502 break;
1503 }
1504 if (policy->loadFromDatabase(hdb, id))
1505 {
1506 NetObjInsert(policy, false, false); // Insert into indexes
1507 policy->calculateCompoundStatus(); // Force status change to NORMAL
1508 }
1509 else // Object load failed
1510 {
1511 delete policy;
1512 nxlog_write(MSG_AGENTPOLICY_LOAD_FAILED, NXLOG_ERROR, "d", id);
1513 }
1514 }
1515 DBFreeResult(hResult);
1516 }
1517
1518 // Load network maps
1519 DbgPrintf(2, _T("Loading network maps..."));
1520 hResult = DBSelect(hdb, _T("SELECT id FROM network_maps"));
1521 if (hResult != NULL)
1522 {
1523 int count = DBGetNumRows(hResult);
1524 for(int i = 0; i < count; i++)
1525 {
1526 UINT32 id = DBGetFieldULong(hResult, i, 0);
1527 NetworkMap *map = new NetworkMap;
1528 if (map->loadFromDatabase(hdb, id))
1529 {
1530 NetObjInsert(map, false, false); // Insert into indexes
1531 }
1532 else // Object load failed
1533 {
1534 delete map;
1535 nxlog_write(MSG_NETMAP_LOAD_FAILED, NXLOG_ERROR, "d", id);
1536 }
1537 }
1538 DBFreeResult(hResult);
1539 }
1540
1541 // Load container objects
1542 DbgPrintf(2, _T("Loading containers..."));
1543 TCHAR query[256];
1544 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_CONTAINER);
1545 hResult = DBSelect(hdb, query);
1546 if (hResult != NULL)
1547 {
1548 Container *pContainer;
1549
1550 int count = DBGetNumRows(hResult);
1551 for(int i = 0; i < count; i++)
1552 {
1553 UINT32 id = DBGetFieldULong(hResult, i, 0);
1554 pContainer = new Container;
1555 if (pContainer->loadFromDatabase(hdb, id))
1556 {
1557 NetObjInsert(pContainer, false, false); // Insert into indexes
1558 }
1559 else // Object load failed
1560 {
1561 delete pContainer;
1562 nxlog_write(MSG_CONTAINER_LOAD_FAILED, NXLOG_ERROR, "d", id);
1563 }
1564 }
1565 DBFreeResult(hResult);
1566 }
1567
1568 // Load template group objects
1569 DbgPrintf(2, _T("Loading template groups..."));
1570 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_TEMPLATEGROUP);
1571 hResult = DBSelect(hdb, query);
1572 if (hResult != NULL)
1573 {
1574 TemplateGroup *pGroup;
1575
1576 int count = DBGetNumRows(hResult);
1577 for(int i = 0; i < count; i++)
1578 {
1579 UINT32 id = DBGetFieldULong(hResult, i, 0);
1580 pGroup = new TemplateGroup;
1581 if (pGroup->loadFromDatabase(hdb, id))
1582 {
1583 NetObjInsert(pGroup, false, false); // Insert into indexes
1584 }
1585 else // Object load failed
1586 {
1587 delete pGroup;
1588 nxlog_write(MSG_TG_LOAD_FAILED, NXLOG_ERROR, "d", id);
1589 }
1590 }
1591 DBFreeResult(hResult);
1592 }
1593
1594 // Load policy group objects
1595 DbgPrintf(2, _T("Loading policy groups..."));
1596 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_POLICYGROUP);
1597 hResult = DBSelect(hdb, query);
1598 if (hResult != NULL)
1599 {
1600 int count = DBGetNumRows(hResult);
1601 for(int i = 0; i < count; i++)
1602 {
1603 UINT32 id = DBGetFieldULong(hResult, i, 0);
1604 PolicyGroup *group = new PolicyGroup;
1605 if (group->loadFromDatabase(hdb, id))
1606 {
1607 NetObjInsert(group, false, false); // Insert into indexes
1608 }
1609 else // Object load failed
1610 {
1611 delete group;
1612 nxlog_write(MSG_PG_LOAD_FAILED, NXLOG_ERROR, "d", id);
1613 }
1614 }
1615 DBFreeResult(hResult);
1616 }
1617
1618 // Load map group objects
1619 DbgPrintf(2, _T("Loading map groups..."));
1620 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_NETWORKMAPGROUP);
1621 hResult = DBSelect(hdb, query);
1622 if (hResult != NULL)
1623 {
1624 int count = DBGetNumRows(hResult);
1625 for(int i = 0; i < count; i++)
1626 {
1627 UINT32 id = DBGetFieldULong(hResult, i, 0);
1628 NetworkMapGroup *group = new NetworkMapGroup;
1629 if (group->loadFromDatabase(hdb, id))
1630 {
1631 NetObjInsert(group, false, false); // Insert into indexes
1632 }
1633 else // Object load failed
1634 {
1635 delete group;
1636 nxlog_write(MSG_MG_LOAD_FAILED, NXLOG_ERROR, "d", id);
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 != NULL)
1646 {
1647 int count = DBGetNumRows(hResult);
1648 for(int i = 0; i < count; i++)
1649 {
1650 UINT32 id = DBGetFieldULong(hResult, i, 0);
1651 Dashboard *dashboard = new Dashboard;
1652 if (dashboard->loadFromDatabase(hdb, id))
1653 {
1654 NetObjInsert(dashboard, false, false); // Insert into indexes
1655 }
1656 else // Object load failed
1657 {
1658 delete dashboard;
1659 nxlog_write(MSG_DASHBOARD_LOAD_FAILED, NXLOG_ERROR, "d", id);
1660 }
1661 }
1662 DBFreeResult(hResult);
1663 }
1664
1665 // Loading business service objects
1666 DbgPrintf(2, _T("Loading business services..."));
1667 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_BUSINESSSERVICE);
1668 hResult = DBSelect(hdb, query);
1669 if (hResult != NULL)
1670 {
1671 int count = DBGetNumRows(hResult);
1672 for(int i = 0; i < count; i++)
1673 {
1674 UINT32 id = DBGetFieldULong(hResult, i, 0);
1675 BusinessService *service = new BusinessService;
1676 if (service->loadFromDatabase(hdb, id))
1677 {
1678 NetObjInsert(service, false, false); // Insert into indexes
1679 }
1680 else // Object load failed
1681 {
1682 delete service;
1683 nxlog_write(MSG_BUSINESS_SERVICE_LOAD_FAILED, NXLOG_ERROR, "d", id);
1684 }
1685 }
1686 DBFreeResult(hResult);
1687 }
1688
1689 // Loading business service objects
1690 DbgPrintf(2, _T("Loading node links..."));
1691 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_NODELINK);
1692 hResult = DBSelect(hdb, query);
1693 if (hResult != NULL)
1694 {
1695 int count = DBGetNumRows(hResult);
1696 for(int i = 0; i < count; i++)
1697 {
1698 UINT32 id = DBGetFieldULong(hResult, i, 0);
1699 NodeLink *nl = new NodeLink;
1700 if (nl->loadFromDatabase(hdb, id))
1701 {
1702 NetObjInsert(nl, false, false); // Insert into indexes
1703 }
1704 else // Object load failed
1705 {
1706 delete nl;
1707 nxlog_write(MSG_NODE_LINK_LOAD_FAILED, NXLOG_ERROR, "d", id);
1708 }
1709 }
1710 DBFreeResult(hResult);
1711 }
1712
1713 // Load service check objects
1714 DbgPrintf(2, _T("Loading service checks..."));
1715 hResult = DBSelect(hdb, _T("SELECT id FROM slm_checks"));
1716 if (hResult != NULL)
1717 {
1718 int count = DBGetNumRows(hResult);
1719 for(int i = 0; i < count; i++)
1720 {
1721 UINT32 id = DBGetFieldULong(hResult, i, 0);
1722 SlmCheck *check = new SlmCheck;
1723 if (check->loadFromDatabase(hdb, id))
1724 {
1725 NetObjInsert(check, false, false); // Insert into indexes
1726 }
1727 else // Object load failed
1728 {
1729 delete check;
1730 nxlog_write(MSG_SERVICE_CHECK_LOAD_FAILED, NXLOG_ERROR, "d", id);
1731 }
1732 }
1733 DBFreeResult(hResult);
1734 }
1735
1736 DBConnectionPoolReleaseConnection(hdb);
1737
1738 // Load custom object classes provided by modules
1739 CALL_ALL_MODULES(pfLoadObjects, ());
1740
1741 // Link children to container and template group objects
1742 DbgPrintf(2, _T("Linking objects..."));
1743 g_idxObjectById.forEach(LinkChildObjectsCallback, NULL);
1744
1745 // Link children to root objects
1746 g_pServiceRoot->linkChildObjects();
1747 g_pTemplateRoot->linkChildObjects();
1748 g_pPolicyRoot->linkChildObjects();
1749 g_pMapRoot->linkChildObjects();
1750 g_pDashboardRoot->linkChildObjects();
1751 g_pBusinessServiceRoot->linkChildObjects();
1752
1753 // Link custom object classes provided by modules
1754 CALL_ALL_MODULES(pfLinkObjects, ());
1755
1756 // Allow objects to change it's modification flag
1757 g_bModificationsLocked = FALSE;
1758
1759 // Recalculate status for built-in objects
1760 g_pEntireNet->calculateCompoundStatus();
1761 g_pServiceRoot->calculateCompoundStatus();
1762 g_pTemplateRoot->calculateCompoundStatus();
1763 g_pPolicyRoot->calculateCompoundStatus();
1764 g_pMapRoot->calculateCompoundStatus();
1765 g_pBusinessServiceRoot->calculateCompoundStatus();
1766
1767 // Recalculate status for zone objects
1768 if (g_flags & AF_ENABLE_ZONING)
1769 {
1770 g_idxZoneByGUID.forEach(RecalcStatusCallback, NULL);
1771 }
1772
1773 // Start map update thread
1774 ThreadCreate(MapUpdateThread, 0, NULL);
1775
1776 // Start template update applying thread
1777 ThreadCreate(ApplyTemplateThread, 0, NULL);
1778
1779 return TRUE;
1780 }
1781
1782 /**
1783 * Callback for DeleteUserFromAllObjects
1784 */
1785 static void DropUserAccess(NetObj *object, void *userId)
1786 {
1787 object->dropUserAccess(CAST_FROM_POINTER(userId, UINT32));
1788 }
1789
1790 /**
1791 * Delete user or group from all objects' ACLs
1792 */
1793 void DeleteUserFromAllObjects(UINT32 dwUserId)
1794 {
1795 g_idxObjectById.forEach(DropUserAccess, CAST_TO_POINTER(dwUserId, void *));
1796 }
1797
1798 /**
1799 * User data for DumpObjectCallback
1800 */
1801 struct __dump_objects_data
1802 {
1803 CONSOLE_CTX console;
1804 TCHAR *buffer;
1805 const TCHAR *filter;
1806 };
1807
1808 /**
1809 * Enumeration callback for DumpObjects
1810 */
1811 static void DumpObjectCallback(NetObj *object, void *data)
1812 {
1813 struct __dump_objects_data *dd = (struct __dump_objects_data *)data;
1814
1815 // Apply name filter
1816 if ((dd->filter != NULL) && !MatchString(dd->filter, object->getName(), false))
1817 return;
1818
1819 CONSOLE_CTX pCtx = dd->console;
1820
1821 ConsolePrintf(pCtx, _T("Object ID %d \"%s\"\n")
1822 _T(" Class: %s Status: %s IsModified: %d IsDeleted: %d\n"),
1823 object->getId(), object->getName(), object->getObjectClassName(),
1824 GetStatusAsText(object->getStatus(), true),
1825 object->isModified(), object->isDeleted());
1826 ConsolePrintf(pCtx, _T(" Parents: <%s>\n Childs: <%s>\n"),
1827 object->dbgGetParentList(dd->buffer), object->dbgGetChildList(&dd->buffer[4096]));
1828 time_t t = object->getTimeStamp();
1829 struct tm *ltm = localtime(&t);
1830 _tcsftime(dd->buffer, 256, _T("%d.%b.%Y %H:%M:%S"), ltm);
1831 ConsolePrintf(pCtx, _T(" Last change: %s\n"), dd->buffer);
1832 switch(object->getObjectClass())
1833 {
1834 case OBJECT_NODE:
1835 ConsolePrintf(pCtx, _T(" Primary IP: %s\n IsSNMP: %d IsAgent: %d IsLocal: %d OID: %s\n"),
1836 ((Node *)object)->getIpAddress().toString(dd->buffer),
1837 ((Node *)object)->isSNMPSupported(),
1838 ((Node *)object)->isNativeAgent(),
1839 ((Node *)object)->isLocalManagement(),
1840 ((Node *)object)->getObjectId());
1841 break;
1842 case OBJECT_SUBNET:
1843 ConsolePrintf(pCtx, _T(" IP address: %s/%d\n"), ((Subnet *)object)->getIpAddress().toString(dd->buffer), ((Subnet *)object)->getIpAddress().getMaskBits());
1844 break;
1845 case OBJECT_ACCESSPOINT:
1846 ConsolePrintf(pCtx, _T(" IP address: %s\n"), ((AccessPoint *)object)->getIpAddress().toString(dd->buffer));
1847 break;
1848 case OBJECT_INTERFACE:
1849 ConsolePrintf(pCtx, _T(" MAC address: %s\n"), MACToStr(((Interface *)object)->getMacAddr(), dd->buffer));
1850 for(int n = 0; n < ((Interface *)object)->getIpAddressList()->size(); n++)
1851 {
1852 const InetAddress& a = ((Interface *)object)->getIpAddressList()->get(n);
1853 ConsolePrintf(pCtx, _T(" IP address: %s/%d\n"), a.toString(dd->buffer), a.getMaskBits());
1854 }
1855 break;
1856 case OBJECT_TEMPLATE:
1857 ConsolePrintf(pCtx, _T(" Version: %d.%d\n"),
1858 ((Template *)(object))->getVersionMajor(),
1859 ((Template *)(object))->getVersionMinor());
1860 break;
1861 }
1862 }
1863
1864 /**
1865 * Dump objects to debug console
1866 */
1867 void DumpObjects(CONSOLE_CTX pCtx, const TCHAR *filter)
1868 {
1869 struct __dump_objects_data data;
1870
1871 data.buffer = (TCHAR *)malloc(128000 * sizeof(TCHAR));
1872 data.console = pCtx;
1873 data.filter = filter;
1874 g_idxObjectById.forEach(DumpObjectCallback, &data);
1875 free(data.buffer);
1876 }
1877
1878 /**
1879 * Check is given object class is a valid parent class for other object
1880 * This function is used to check manually created bindings, so it won't
1881 * return TRUE for node -- subnet for example
1882 */
1883 bool IsValidParentClass(int childClass, int parentClass)
1884 {
1885 switch(parentClass)
1886 {
1887 case OBJECT_NETWORK:
1888 if ((childClass == OBJECT_ZONE) && (g_flags & AF_ENABLE_ZONING))
1889 return true;
1890 break;
1891 case OBJECT_SERVICEROOT:
1892 case OBJECT_CONTAINER:
1893 if ((childClass == OBJECT_CHASSIS) ||
1894 (childClass == OBJECT_CLUSTER) ||
1895 (childClass == OBJECT_CONDITION) ||
1896 (childClass == OBJECT_CONTAINER) ||
1897 (childClass == OBJECT_MOBILEDEVICE) ||
1898 (childClass == OBJECT_NODE) ||
1899 (childClass == OBJECT_RACK) ||
1900 (childClass == OBJECT_SUBNET))
1901 return true;
1902 break;
1903 case OBJECT_CHASSIS:
1904 case OBJECT_RACK:
1905 if (childClass == OBJECT_NODE)
1906 return true;
1907 break;
1908 case OBJECT_TEMPLATEROOT:
1909 case OBJECT_TEMPLATEGROUP:
1910 if ((childClass == OBJECT_TEMPLATEGROUP) ||
1911 (childClass == OBJECT_TEMPLATE))
1912 return true;
1913 break;
1914 case OBJECT_TEMPLATE:
1915 if ((childClass == OBJECT_NODE) ||
1916 (childClass == OBJECT_CLUSTER) ||
1917 (childClass == OBJECT_MOBILEDEVICE))
1918 return true;
1919 break;
1920 case OBJECT_NETWORKMAPROOT:
1921 case OBJECT_NETWORKMAPGROUP:
1922 if ((childClass == OBJECT_NETWORKMAPGROUP) ||
1923 (childClass == OBJECT_NETWORKMAP))
1924 return true;
1925 break;
1926 case OBJECT_DASHBOARDROOT:
1927 case OBJECT_DASHBOARD:
1928 if (childClass == OBJECT_DASHBOARD)
1929 return true;
1930 break;
1931 case OBJECT_POLICYROOT:
1932 case OBJECT_POLICYGROUP:
1933 if ((childClass == OBJECT_POLICYGROUP) ||
1934 (childClass == OBJECT_AGENTPOLICY) ||
1935 (childClass == OBJECT_AGENTPOLICY_CONFIG) ||
1936 (childClass == OBJECT_AGENTPOLICY_LOGPARSER))
1937 return true;
1938 break;
1939 case OBJECT_NODE:
1940 if ((childClass == OBJECT_NETWORKSERVICE) ||
1941 (childClass == OBJECT_VPNCONNECTOR) ||
1942 (childClass == OBJECT_INTERFACE))
1943 return true;
1944 break;
1945 case OBJECT_CLUSTER:
1946 if (childClass == OBJECT_NODE)
1947 return true;
1948 break;
1949 case OBJECT_BUSINESSSERVICEROOT:
1950 if ((childClass == OBJECT_BUSINESSSERVICE) ||
1951 (childClass == OBJECT_NODELINK))
1952 return true;
1953 break;
1954 case OBJECT_BUSINESSSERVICE:
1955 if ((childClass == OBJECT_BUSINESSSERVICE) ||
1956 (childClass == OBJECT_NODELINK) ||
1957 (childClass == OBJECT_SLMCHECK))
1958 return true;
1959 break;
1960 case OBJECT_NODELINK:
1961 if (childClass == OBJECT_SLMCHECK)
1962 return true;
1963 break;
1964 case -1: // Creating object without parent
1965 if (childClass == 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(childClass, parentClass))
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) || (object->getObjectClass() == OBJECT_AGENTPOLICY_LOGPARSER);
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 }