Fixed some bugs in node creation
[public/netxms.git] / src / server / core / objects.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003, 2004 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 ** $module: objects.cpp
20 **
21 **/
22
23 #include "nms_core.h"
24
25
26 //
27 // Global data
28 //
29
30 Network *g_pEntireNet = NULL;
31 ServiceRoot *g_pServiceRoot = NULL;
32 TemplateRoot *g_pTemplateRoot = NULL;
33
34 DWORD g_dwMgmtNode = 0;
35 INDEX *g_pIndexById = NULL;
36 DWORD g_dwIdIndexSize = 0;
37 INDEX *g_pSubnetIndexByAddr = NULL;
38 DWORD g_dwSubnetAddrIndexSize = 0;
39 INDEX *g_pNodeIndexByAddr = NULL;
40 DWORD g_dwNodeAddrIndexSize = 0;
41 INDEX *g_pInterfaceIndexByAddr = NULL;
42 DWORD g_dwInterfaceAddrIndexSize = 0;
43
44 MUTEX g_hMutexObjectAccess;
45 RWLOCK g_rwlockIdIndex;
46 RWLOCK g_rwlockNodeIndex;
47 RWLOCK g_rwlockSubnetIndex;
48 RWLOCK g_rwlockInterfaceIndex;
49
50 DWORD g_dwNumCategories = 0;
51 CONTAINER_CATEGORY *g_pContainerCatList = NULL;
52
53 char *g_pszStatusName[] = { "Normal", "Warning", "Minor", "Major", "Critical",
54 "Unknown", "Unmanaged", "Disabled", "Testing" };
55 char *g_szClassName[]={ "Generic", "Subnet", "Node", "Interface",
56 "Network", "Container", "Zone", "ServiceRoot",
57 "Template", "TemplateGroup", "TemplateRoot" };
58
59
60 //
61 // Initialize objects infrastructure
62 //
63
64 void ObjectsInit(void)
65 {
66 g_hMutexObjectAccess = MutexCreate();
67 g_rwlockIdIndex = RWLockCreate();
68 g_rwlockNodeIndex = RWLockCreate();
69 g_rwlockSubnetIndex = RWLockCreate();
70 g_rwlockInterfaceIndex = RWLockCreate();
71
72 // Create "Entire Network" object
73 g_pEntireNet = new Network;
74 NetObjInsert(g_pEntireNet, FALSE);
75
76 // Create "Service Root" object
77 g_pServiceRoot = new ServiceRoot;
78 NetObjInsert(g_pServiceRoot, FALSE);
79
80 // Create "Template Root" object
81 g_pTemplateRoot = new TemplateRoot;
82 NetObjInsert(g_pTemplateRoot, FALSE);
83 }
84
85
86 //
87 // Lock write access to all objects
88 //
89
90 void ObjectsGlobalLock(void)
91 {
92 MutexLock(g_hMutexObjectAccess, INFINITE);
93 }
94
95
96 //
97 // Unlock write access to all objects
98 //
99
100 void ObjectsGlobalUnlock(void)
101 {
102 MutexUnlock(g_hMutexObjectAccess);
103 }
104
105
106 //
107 // Function to compare two indexes
108 //
109
110 static int IndexCompare(const void *pArg1, const void *pArg2)
111 {
112 return (((INDEX *)pArg1)->dwKey < ((INDEX *)pArg2)->dwKey) ? -1 :
113 ((((INDEX *)pArg1)->dwKey > ((INDEX *)pArg2)->dwKey) ? 1 : 0);
114 }
115
116
117 //
118 // Add new object to index
119 //
120
121 static void AddObjectToIndex(INDEX **ppIndex, DWORD *pdwIndexSize, DWORD dwKey, NetObj *pObject)
122 {
123 *ppIndex = (INDEX *)realloc(*ppIndex, sizeof(INDEX) * ((*pdwIndexSize) + 1));
124 (*ppIndex)[*pdwIndexSize].dwKey = dwKey;
125 (*ppIndex)[*pdwIndexSize].pObject = pObject;
126 (*pdwIndexSize)++;
127 qsort(*ppIndex, *pdwIndexSize, sizeof(INDEX), IndexCompare);
128 }
129
130
131 //
132 // Perform binary search on index
133 // Returns INVALID_INDEX if key not found or position of appropriate network object
134 // We assume that pIndex == NULL will not be passed
135 //
136
137 static DWORD SearchIndex(INDEX *pIndex, DWORD dwIndexSize, DWORD dwKey)
138 {
139 DWORD dwFirst, dwLast, dwMid;
140
141 dwFirst = 0;
142 dwLast = dwIndexSize - 1;
143
144 if ((dwKey < pIndex[0].dwKey) || (dwKey > pIndex[dwLast].dwKey))
145 return INVALID_INDEX;
146
147 while(dwFirst < dwLast)
148 {
149 dwMid = (dwFirst + dwLast) / 2;
150 if (dwKey == pIndex[dwMid].dwKey)
151 return dwMid;
152 if (dwKey < pIndex[dwMid].dwKey)
153 dwLast = dwMid - 1;
154 else
155 dwFirst = dwMid + 1;
156 }
157
158 if (dwKey == pIndex[dwLast].dwKey)
159 return dwLast;
160
161 return INVALID_INDEX;
162 }
163
164
165 //
166 // Delete object from index
167 //
168
169 static void DeleteObjectFromIndex(INDEX **ppIndex, DWORD *pdwIndexSize, DWORD dwKey)
170 {
171 DWORD dwPos;
172 INDEX *pIndex = *ppIndex;
173
174 dwPos = SearchIndex(pIndex, *pdwIndexSize, dwKey);
175 if (dwPos != INVALID_INDEX)
176 {
177 (*pdwIndexSize)--;
178 memmove(&pIndex[dwPos], &pIndex[dwPos + 1], sizeof(INDEX) * (*pdwIndexSize - dwPos));
179 }
180 }
181
182
183 //
184 // Insert new object into network
185 //
186
187 void NetObjInsert(NetObj *pObject, BOOL bNewObject)
188 {
189 ObjectsGlobalLock();
190 if (bNewObject)
191 {
192 // Assign unique ID to new object
193 pObject->SetId(CreateUniqueId(IDG_NETWORK_OBJECT));
194
195 // Create table for storing data collection values
196 if (pObject->Type() == OBJECT_NODE)
197 {
198 char szQuery[256], szQueryTemplate[256];
199
200 ConfigReadStr("IDataTableCreationCommand", szQueryTemplate, 255, "");
201 sprintf(szQuery, szQueryTemplate, pObject->Id());
202 DBQuery(g_hCoreDB, szQuery);
203 }
204 }
205 RWLockWriteLock(g_rwlockIdIndex, INFINITE);
206 AddObjectToIndex(&g_pIndexById, &g_dwIdIndexSize, pObject->Id(), pObject);
207 RWLockUnlock(g_rwlockIdIndex);
208 if ((pObject->IpAddr() != 0) && (!pObject->IsDeleted()))
209 {
210 switch(pObject->Type())
211 {
212 case OBJECT_GENERIC:
213 case OBJECT_NETWORK:
214 case OBJECT_CONTAINER:
215 case OBJECT_SERVICEROOT:
216 break;
217 case OBJECT_SUBNET:
218 RWLockWriteLock(g_rwlockSubnetIndex, INFINITE);
219 AddObjectToIndex(&g_pSubnetIndexByAddr, &g_dwSubnetAddrIndexSize, pObject->IpAddr(), pObject);
220 RWLockUnlock(g_rwlockSubnetIndex);
221 if (bNewObject)
222 PostEvent(EVENT_SUBNET_ADDED, pObject->Id(), NULL);
223 break;
224 case OBJECT_NODE:
225 RWLockWriteLock(g_rwlockNodeIndex, INFINITE);
226 AddObjectToIndex(&g_pNodeIndexByAddr, &g_dwNodeAddrIndexSize, pObject->IpAddr(), pObject);
227 RWLockUnlock(g_rwlockNodeIndex);
228 if (bNewObject)
229 PostEvent(EVENT_NODE_ADDED, pObject->Id(), NULL);
230 break;
231 case OBJECT_INTERFACE:
232 RWLockWriteLock(g_rwlockInterfaceIndex, INFINITE);
233 AddObjectToIndex(&g_pInterfaceIndexByAddr, &g_dwInterfaceAddrIndexSize, pObject->IpAddr(), pObject);
234 RWLockUnlock(g_rwlockInterfaceIndex);
235 break;
236 default:
237 WriteLog(MSG_BAD_NETOBJ_TYPE, EVENTLOG_ERROR_TYPE, "d", pObject->Type());
238 break;
239 }
240 }
241 ObjectsGlobalUnlock();
242 }
243
244
245 //
246 // Delete object from indexes
247 // If object has an IP address, this function will delete it from
248 // appropriate index. Normally this function should be called from
249 // NetObj::Delete() method.
250 //
251
252 void NetObjDeleteFromIndexes(NetObj *pObject)
253 {
254 if (pObject->IpAddr() != 0)
255 switch(pObject->Type())
256 {
257 case OBJECT_GENERIC:
258 case OBJECT_NETWORK:
259 case OBJECT_CONTAINER:
260 case OBJECT_SERVICEROOT:
261 break;
262 case OBJECT_SUBNET:
263 RWLockWriteLock(g_rwlockSubnetIndex, INFINITE);
264 DeleteObjectFromIndex(&g_pSubnetIndexByAddr, &g_dwSubnetAddrIndexSize, pObject->IpAddr());
265 RWLockUnlock(g_rwlockSubnetIndex);
266 break;
267 case OBJECT_NODE:
268 RWLockWriteLock(g_rwlockNodeIndex, INFINITE);
269 DeleteObjectFromIndex(&g_pNodeIndexByAddr, &g_dwNodeAddrIndexSize, pObject->IpAddr());
270 RWLockUnlock(g_rwlockNodeIndex);
271 break;
272 case OBJECT_INTERFACE:
273 RWLockWriteLock(g_rwlockInterfaceIndex, INFINITE);
274 DeleteObjectFromIndex(&g_pInterfaceIndexByAddr, &g_dwInterfaceAddrIndexSize, pObject->IpAddr());
275 RWLockUnlock(g_rwlockInterfaceIndex);
276 break;
277 default:
278 WriteLog(MSG_BAD_NETOBJ_TYPE, EVENTLOG_ERROR_TYPE, "d", pObject->Type());
279 break;
280 }
281 }
282
283
284 //
285 // Get IP netmask for object of any class
286 //
287
288 DWORD GetObjectNetmask(NetObj *pObject)
289 {
290 switch(pObject->Type())
291 {
292 case OBJECT_INTERFACE:
293 return ((Interface *)pObject)->IpNetMask();
294 case OBJECT_SUBNET:
295 return ((Subnet *)pObject)->IpNetMask();
296 default:
297 return 0;
298 }
299 }
300
301
302 //
303 // Delete object (final step)
304 // This function should be called only by syncer thread when access to objects are locked.
305 // Object will be removed from index by ID and destroyed.
306 //
307
308 void NetObjDelete(NetObj *pObject)
309 {
310 char szQuery[256], szIpAddr[16], szNetMask[16];
311
312 // Write object to deleted objects table
313 snprintf(szQuery, 256, "INSERT INTO deleted_objects (object_id,object_class,name,"
314 "ip_addr,ip_netmask) VALUES (%ld,%ld,'%s','%s','%s')",
315 pObject->Id(), pObject->Type(), pObject->Name(),
316 IpToStr(pObject->IpAddr(), szIpAddr),
317 IpToStr(GetObjectNetmask(pObject), szNetMask));
318 DBQuery(g_hCoreDB, szQuery);
319
320 // Delete object from index by ID
321 RWLockWriteLock(g_rwlockIdIndex, INFINITE);
322 DeleteObjectFromIndex(&g_pIndexById, &g_dwIdIndexSize, pObject->Id());
323 RWLockUnlock(g_rwlockIdIndex);
324
325 delete pObject;
326 }
327
328
329 //
330 // Find node by IP address
331 //
332
333 Node *FindNodeByIP(DWORD dwAddr)
334 {
335 DWORD dwPos;
336 Node *pNode;
337
338 if ((g_pInterfaceIndexByAddr == NULL) || (dwAddr == 0))
339 return NULL;
340
341 RWLockReadLock(g_rwlockInterfaceIndex, INFINITE);
342 dwPos = SearchIndex(g_pInterfaceIndexByAddr, g_dwInterfaceAddrIndexSize, dwAddr);
343 pNode = (dwPos == INVALID_INDEX) ? NULL : (Node *)g_pInterfaceIndexByAddr[dwPos].pObject->GetParent();
344 RWLockUnlock(g_rwlockInterfaceIndex);
345 return pNode;
346 }
347
348
349 //
350 // Find subnet by IP address
351 //
352
353 Subnet *FindSubnetByIP(DWORD dwAddr)
354 {
355 DWORD dwPos;
356 Subnet *pSubnet;
357
358 if ((g_pSubnetIndexByAddr == NULL) || (dwAddr == 0))
359 return NULL;
360
361 RWLockReadLock(g_rwlockSubnetIndex, INFINITE);
362 dwPos = SearchIndex(g_pSubnetIndexByAddr, g_dwSubnetAddrIndexSize, dwAddr);
363 pSubnet = (dwPos == INVALID_INDEX) ? NULL : (Subnet *)g_pSubnetIndexByAddr[dwPos].pObject;
364 RWLockUnlock(g_rwlockSubnetIndex);
365 return pSubnet;
366 }
367
368
369 //
370 // Find subnet for given IP address
371 //
372
373 Subnet *FindSubnetForNode(DWORD dwNodeAddr)
374 {
375 DWORD i;
376 Subnet *pSubnet = NULL;
377
378 if ((g_pSubnetIndexByAddr == NULL) || (dwNodeAddr == 0))
379 return NULL;
380
381 RWLockReadLock(g_rwlockSubnetIndex, INFINITE);
382 for(i = 0; i < g_dwSubnetAddrIndexSize; i++)
383 if ((dwNodeAddr & ((Subnet *)g_pSubnetIndexByAddr[i].pObject)->IpNetMask()) ==
384 ((Subnet *)g_pSubnetIndexByAddr[i].pObject)->IpAddr())
385 {
386 pSubnet = (Subnet *)g_pSubnetIndexByAddr[i].pObject;
387 break;
388 }
389 RWLockUnlock(g_rwlockSubnetIndex);
390 return pSubnet;
391 }
392
393
394 //
395 // Find object by ID
396 //
397
398 NetObj *FindObjectById(DWORD dwId)
399 {
400 DWORD dwPos;
401 NetObj *pObject;
402
403 if (g_pIndexById == NULL)
404 return NULL;
405
406 RWLockReadLock(g_rwlockIdIndex, INFINITE);
407 dwPos = SearchIndex(g_pIndexById, g_dwIdIndexSize, dwId);
408 pObject = (dwPos == INVALID_INDEX) ? NULL : g_pIndexById[dwPos].pObject;
409 RWLockUnlock(g_rwlockIdIndex);
410 return pObject;
411 }
412
413
414 //
415 // Find local management node ID
416 //
417
418 DWORD FindLocalMgmtNode(void)
419 {
420 DWORD i, dwId = 0;
421
422 if (g_pNodeIndexByAddr == NULL)
423 return 0;
424
425 RWLockReadLock(g_rwlockNodeIndex, INFINITE);
426 for(i = 0; i < g_dwNodeAddrIndexSize; i++)
427 if (((Node *)g_pNodeIndexByAddr[i].pObject)->Flags() & NF_IS_LOCAL_MGMT)
428 {
429 dwId = g_pNodeIndexByAddr[i].pObject->Id();
430 break;
431 }
432 RWLockUnlock(g_rwlockNodeIndex);
433 return dwId;
434 }
435
436
437 //
438 // Load objects from database at stratup
439 //
440
441 BOOL LoadObjects(void)
442 {
443 DB_RESULT hResult;
444 DWORD i, dwNumRows;
445 DWORD dwId;
446 char szQuery[256];
447
448 // Load container categories
449 hResult = DBSelect(g_hCoreDB, "SELECT category,name,image_id,description FROM container_categories");
450 if (hResult != NULL)
451 {
452 g_dwNumCategories = DBGetNumRows(hResult);
453 g_pContainerCatList = (CONTAINER_CATEGORY *)malloc(sizeof(CONTAINER_CATEGORY) * g_dwNumCategories);
454 for(i = 0; i < (int)g_dwNumCategories; i++)
455 {
456 g_pContainerCatList[i].dwCatId = DBGetFieldULong(hResult, i, 0);
457 strncpy(g_pContainerCatList[i].szName, DBGetField(hResult, i, 1), MAX_OBJECT_NAME);
458 g_pContainerCatList[i].dwImageId = DBGetFieldULong(hResult, i, 2);
459 g_pContainerCatList[i].pszDescription = strdup(DBGetField(hResult, i, 3));
460 }
461 DBFreeResult(hResult);
462 }
463
464 // Load built-in object properties
465 g_pEntireNet->LoadFromDB();
466 g_pServiceRoot->LoadFromDB();
467 g_pTemplateRoot->LoadFromDB();
468
469 // Load subnets
470 hResult = DBSelect(g_hCoreDB, "SELECT id FROM subnets");
471 if (hResult != 0)
472 {
473 Subnet *pSubnet;
474
475 dwNumRows = DBGetNumRows(hResult);
476 for(i = 0; i < dwNumRows; i++)
477 {
478 dwId = DBGetFieldULong(hResult, i, 0);
479 pSubnet = new Subnet;
480 if (pSubnet->CreateFromDB(dwId))
481 {
482 if (!pSubnet->IsDeleted())
483 g_pEntireNet->AddSubnet(pSubnet);
484 NetObjInsert(pSubnet, FALSE); // Insert into indexes
485 }
486 else // Object load failed
487 {
488 delete pSubnet;
489 WriteLog(MSG_SUBNET_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
490 }
491 }
492 DBFreeResult(hResult);
493 }
494
495 // Load nodes
496 hResult = DBSelect(g_hCoreDB, "SELECT id FROM nodes");
497 if (hResult != 0)
498 {
499 Node *pNode;
500
501 dwNumRows = DBGetNumRows(hResult);
502 for(i = 0; i < dwNumRows; i++)
503 {
504 dwId = DBGetFieldULong(hResult, i, 0);
505 pNode = new Node;
506 if (pNode->CreateFromDB(dwId))
507 {
508 NetObjInsert(pNode, FALSE); // Insert into indexes
509 }
510 else // Object load failed
511 {
512 delete pNode;
513 WriteLog(MSG_NODE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
514 }
515 }
516 DBFreeResult(hResult);
517 }
518
519 // Load interfaces
520 hResult = DBSelect(g_hCoreDB, "SELECT id FROM interfaces");
521 if (hResult != 0)
522 {
523 Interface *pInterface;
524
525 dwNumRows = DBGetNumRows(hResult);
526 for(i = 0; i < dwNumRows; i++)
527 {
528 dwId = DBGetFieldULong(hResult, i, 0);
529 pInterface = new Interface;
530 if (pInterface->CreateFromDB(dwId))
531 {
532 NetObjInsert(pInterface, FALSE); // Insert into indexes
533 }
534 else // Object load failed
535 {
536 delete pInterface;
537 WriteLog(MSG_INTERFACE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
538 }
539 }
540 DBFreeResult(hResult);
541 }
542
543 // Load templates
544 hResult = DBSelect(g_hCoreDB, "SELECT id FROM templates");
545 if (hResult != 0)
546 {
547 Template *pTemplate;
548
549 dwNumRows = DBGetNumRows(hResult);
550 for(i = 0; i < dwNumRows; i++)
551 {
552 dwId = DBGetFieldULong(hResult, i, 0);
553 pTemplate = new Template;
554 if (pTemplate->CreateFromDB(dwId))
555 {
556 NetObjInsert(pTemplate, FALSE); // Insert into indexes
557 }
558 else // Object load failed
559 {
560 delete pTemplate;
561 WriteLog(MSG_TEMPLATE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
562 }
563 }
564 DBFreeResult(hResult);
565 }
566
567 // Load container objects
568 sprintf(szQuery, "SELECT id FROM containers WHERE object_class=%d", OBJECT_CONTAINER);
569 hResult = DBSelect(g_hCoreDB, szQuery);
570 if (hResult != 0)
571 {
572 Container *pContainer;
573
574 dwNumRows = DBGetNumRows(hResult);
575 for(i = 0; i < dwNumRows; i++)
576 {
577 dwId = DBGetFieldULong(hResult, i, 0);
578 pContainer = new Container;
579 if (pContainer->CreateFromDB(dwId))
580 {
581 NetObjInsert(pContainer, FALSE); // Insert into indexes
582 }
583 else // Object load failed
584 {
585 delete pContainer;
586 WriteLog(MSG_CONTAINER_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
587 }
588 }
589 DBFreeResult(hResult);
590 }
591
592 // Load template group objects
593 sprintf(szQuery, "SELECT id FROM containers WHERE object_class=%d", OBJECT_TEMPLATEGROUP);
594 hResult = DBSelect(g_hCoreDB, szQuery);
595 if (hResult != 0)
596 {
597 TemplateGroup *pGroup;
598
599 dwNumRows = DBGetNumRows(hResult);
600 for(i = 0; i < dwNumRows; i++)
601 {
602 dwId = DBGetFieldULong(hResult, i, 0);
603 pGroup = new TemplateGroup;
604 if (pGroup->CreateFromDB(dwId))
605 {
606 NetObjInsert(pGroup, FALSE); // Insert into indexes
607 }
608 else // Object load failed
609 {
610 delete pGroup;
611 WriteLog(MSG_TG_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
612 }
613 }
614 DBFreeResult(hResult);
615 }
616
617 // Link childs to container and template group objects
618 for(i = 0; i < g_dwIdIndexSize; i++)
619 if ((g_pIndexById[i].pObject->Type() == OBJECT_CONTAINER) ||
620 (g_pIndexById[i].pObject->Type() == OBJECT_TEMPLATEGROUP))
621 ((Container *)g_pIndexById[i].pObject)->LinkChildObjects();
622
623 // Link childs to "Service Root" and "Template Root" objects
624 g_pServiceRoot->LinkChildObjects();
625 g_pTemplateRoot->LinkChildObjects();
626
627 // Recalculate status for built-in objects
628 g_pEntireNet->CalculateCompoundStatus();
629 g_pServiceRoot->CalculateCompoundStatus();
630 g_pTemplateRoot->CalculateCompoundStatus();
631
632 return TRUE;
633 }
634
635
636 //
637 // Delete user or group from all objects' ACLs
638 //
639
640 void DeleteUserFromAllObjects(DWORD dwUserId)
641 {
642 DWORD i;
643
644 ObjectsGlobalLock();
645
646 // Walk through all objects
647 RWLockReadLock(g_rwlockIdIndex, INFINITE);
648 for(i = 0; i < g_dwIdIndexSize; i++)
649 g_pIndexById[i].pObject->DropUserAccess(dwUserId);
650 RWLockUnlock(g_rwlockIdIndex);
651
652 ObjectsGlobalUnlock();
653 }
654
655
656 //
657 // Dump objects to console in standalone mode
658 //
659
660 void DumpObjects(void)
661 {
662 DWORD i;
663 char *pBuffer;
664 CONTAINER_CATEGORY *pCat;
665
666 pBuffer = (char *)malloc(128000);
667 RWLockReadLock(g_rwlockIdIndex, INFINITE);
668 for(i = 0; i < g_dwIdIndexSize; i++)
669 {
670 printf("Object ID %d \"%s\"\n"
671 " Class: %s Primary IP: %s Status: %s IsModified: %d IsDeleted: %d\n",
672 g_pIndexById[i].pObject->Id(),g_pIndexById[i].pObject->Name(),
673 g_szClassName[g_pIndexById[i].pObject->Type()],
674 IpToStr(g_pIndexById[i].pObject->IpAddr(), pBuffer),
675 g_pszStatusName[g_pIndexById[i].pObject->Status()],
676 g_pIndexById[i].pObject->IsModified(), g_pIndexById[i].pObject->IsDeleted());
677 printf(" Parents: <%s>\n Childs: <%s>\n",
678 g_pIndexById[i].pObject->ParentList(pBuffer),
679 g_pIndexById[i].pObject->ChildList(&pBuffer[4096]));
680 switch(g_pIndexById[i].pObject->Type())
681 {
682 case OBJECT_NODE:
683 printf(" IsSNMP: %d IsAgent: %d IsLocal: %d OID: %s\n",
684 ((Node *)(g_pIndexById[i].pObject))->IsSNMPSupported(),
685 ((Node *)(g_pIndexById[i].pObject))->IsNativeAgent(),
686 ((Node *)(g_pIndexById[i].pObject))->IsLocalManagement(),
687 ((Node *)(g_pIndexById[i].pObject))->ObjectId());
688 break;
689 case OBJECT_SUBNET:
690 printf(" Network mask: %s\n",
691 IpToStr(((Subnet *)g_pIndexById[i].pObject)->IpNetMask(), pBuffer));
692 break;
693 case OBJECT_CONTAINER:
694 pCat = FindContainerCategory(((Container *)g_pIndexById[i].pObject)->Category());
695 printf(" Category: %s\n Description: %s\n", pCat ? pCat->szName : "<unknown>",
696 ((Container *)g_pIndexById[i].pObject)->Description());
697 break;
698 case OBJECT_TEMPLATE:
699 printf(" Version: %d.%d\n Description: %s\n",
700 ((Template *)(g_pIndexById[i].pObject))->VersionMajor(),
701 ((Template *)(g_pIndexById[i].pObject))->VersionMinor(),
702 ((Template *)(g_pIndexById[i].pObject))->Description());
703 break;
704 }
705 }
706 RWLockUnlock(g_rwlockIdIndex);
707 free(pBuffer);
708 }
709
710
711 //
712 // Check is given object class is a valid parent class for other object
713 // This function is used to check manually created bindings, so i won't
714 // return TRUE for node -- subnet for example
715 //
716
717 BOOL IsValidParentClass(int iChildClass, int iParentClass)
718 {
719 switch(iParentClass)
720 {
721 case OBJECT_SERVICEROOT:
722 case OBJECT_CONTAINER:
723 if ((iChildClass == OBJECT_CONTAINER) ||
724 (iChildClass == OBJECT_NODE))
725 return TRUE;
726 break;
727 case OBJECT_TEMPLATEROOT:
728 case OBJECT_TEMPLATEGROUP:
729 if ((iChildClass == OBJECT_TEMPLATEGROUP) ||
730 (iChildClass == OBJECT_TEMPLATE))
731 return TRUE;
732 break;
733 case -1: // Creating object without parent
734 if (iChildClass == OBJECT_NODE)
735 return TRUE; // OK only for nodes, because parent subnet will be created automatically
736 break;
737 }
738 return FALSE;
739 }