preparation for object serialization to JSON
[public/netxms.git] / src / server / core / netobj.cpp
CommitLineData
3f39fdc2 1/*
5039dede 2** NetXMS - Network Management System
e9ef47dd 3** Copyright (C) 2003-2017 Victor Kirhenshtein
5039dede
AK
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19** File: netobj.cpp
20**
21**/
22
23#include "nxcore.h"
24
fc381a38 25/**
666d54e2
VK
26 * Class names
27 */
28static const TCHAR *s_className[]=
29 {
30 _T("Generic"), _T("Subnet"), _T("Node"), _T("Interface"),
31 _T("Network"), _T("Container"), _T("Zone"), _T("ServiceRoot"),
32 _T("Template"), _T("TemplateGroup"), _T("TemplateRoot"),
33 _T("NetworkService"), _T("VPNConnector"), _T("Condition"),
34 _T("Cluster"), _T("PolicyGroup"), _T("PolicyRoot"),
35 _T("AgentPolicy"), _T("AgentPolicyConfig"), _T("NetworkMapRoot"),
36 _T("NetworkMapGroup"), _T("NetworkMap"), _T("DashboardRoot"),
37 _T("Dashboard"), _T("ReportRoot"), _T("ReportGroup"), _T("Report"),
38 _T("BusinessServiceRoot"), _T("BusinessService"), _T("NodeLink"),
e4926628
VK
39 _T("ServiceCheck"), _T("MobileDevice"), _T("Rack"), _T("AccessPoint"),
40 _T("AgentPolicyLogParser"), _T("Chassis")
666d54e2
VK
41 };
42
43/**
fc381a38
VK
44 * Default constructor
45 */
5039dede
AK
46NetObj::NetObj()
47{
48 int i;
49
53a9a341 50 m_id = 0;
5039dede 51 m_dwRefCount = 0;
c42b4551 52 m_mutexProperties = MutexCreate();
5039dede
AK
53 m_mutexRefCount = MutexCreate();
54 m_mutexACL = MutexCreate();
55 m_rwlockParentList = RWLockCreate();
56 m_rwlockChildList = RWLockCreate();
db091a1f 57 m_status = STATUS_UNKNOWN;
c42b4551 58 m_name[0] = 0;
db091a1f 59 m_comments = NULL;
01152a54
VK
60 m_isModified = false;
61 m_isDeleted = false;
62 m_isHidden = false;
63 m_isSystem = false;
97afcb6e
VK
64 m_maintenanceMode = false;
65 m_maintenanceEventId = 0;
db091a1f
VK
66 m_childList = new ObjectArray<NetObj>(0, 16, false);
67 m_parentList = new ObjectArray<NetObj>(4, 4, false);
19a2cd39
VK
68 m_accessList = new AccessList();
69 m_inheritAccessRights = true;
5039dede
AK
70 m_dwNumTrustedNodes = 0;
71 m_pdwTrustedNodes = NULL;
c59466d2 72 m_pollRequestor = NULL;
db091a1f
VK
73 m_statusCalcAlg = SA_CALCULATE_DEFAULT;
74 m_statusPropAlg = SA_PROPAGATE_DEFAULT;
75 m_fixedStatus = STATUS_WARNING;
76 m_statusShift = 0;
77 m_statusSingleThreshold = 75;
5039dede
AK
78 m_dwTimeStamp = 0;
79 for(i = 0; i < 4; i++)
80 {
db091a1f
VK
81 m_statusTranslation[i] = i + 1;
82 m_statusThresholds[i] = 80 - i * 20;
5039dede 83 }
8f245200 84 m_submapId = 0;
4f5d216b 85 m_moduleData = NULL;
56fa1092 86 m_postalAddress = new PostalAddress();
8bdd26dc 87 m_dashboards = new IntegerArray<UINT32>();
d1c4701c 88 m_urls = new ObjectArray<ObjectUrl>(4, 4, true);
5039dede
AK
89}
90
fc381a38
VK
91/**
92 * Destructor
93 */
5039dede
AK
94NetObj::~NetObj()
95{
c42b4551 96 MutexDestroy(m_mutexProperties);
5039dede
AK
97 MutexDestroy(m_mutexRefCount);
98 MutexDestroy(m_mutexACL);
99 RWLockDestroy(m_rwlockParentList);
100 RWLockDestroy(m_rwlockChildList);
db091a1f
VK
101 delete m_childList;
102 delete m_parentList;
19a2cd39 103 delete m_accessList;
5039dede 104 safe_free(m_pdwTrustedNodes);
db091a1f 105 safe_free(m_comments);
4f5d216b 106 delete m_moduleData;
56fa1092 107 delete m_postalAddress;
8bdd26dc 108 delete m_dashboards;
d1c4701c 109 delete m_urls;
5039dede
AK
110}
111
fc381a38 112/**
666d54e2
VK
113 * Get class name for this object
114 */
115const TCHAR *NetObj::getObjectClassName() const
116{
117 int c = getObjectClass();
118 return ((c >= 0) && (c < sizeof(s_className) / sizeof(const TCHAR *))) ? s_className[c] : _T("Custom");
119}
120
121/**
e4926628
VK
122 * Get class name for given class ID
123 */
124const TCHAR *NetObj::getObjectClassName(int objectClass)
125{
126 return ((objectClass >= 0) && (objectClass < sizeof(s_className) / sizeof(const TCHAR *))) ? s_className[objectClass] : _T("Custom");
127}
128
129/**
fc381a38
VK
130 * Create object from database data
131 */
9bd1bace 132bool NetObj::loadFromDatabase(DB_HANDLE hdb, UINT32 dwId)
5039dede 133{
9bd1bace 134 return false; // Abstract objects cannot be loaded from database
5039dede
AK
135}
136
fc381a38 137/**
32a400d9
VK
138 * Link related objects after loading from database
139 */
140void NetObj::linkObjects()
141{
142}
143
144/**
fc381a38
VK
145 * Save object to database
146 */
c42b4551 147BOOL NetObj::saveToDatabase(DB_HANDLE hdb)
5039dede
AK
148{
149 return FALSE; // Abstract objects cannot be saved to database
150}
151
fc381a38 152/**
400e55c4
VK
153 * Parameters for DeleteModuleDataCallback and SaveModuleDataCallback
154 */
155struct ModuleDataDatabaseCallbackParams
156{
157 UINT32 id;
158 DB_HANDLE hdb;
159};
160
161/**
162 * Callback for deleting module data from database
163 */
53c3d1e7 164static EnumerationCallbackResult DeleteModuleDataCallback(const TCHAR *key, const void *value, void *data)
400e55c4 165{
53c3d1e7 166 return ((ModuleData *)value)->deleteFromDatabase(((ModuleDataDatabaseCallbackParams *)data)->hdb, ((ModuleDataDatabaseCallbackParams *)data)->id) ? _CONTINUE : _STOP;
400e55c4
VK
167}
168
169/**
fc381a38
VK
170 * Delete object from database
171 */
c42b4551 172bool NetObj::deleteFromDatabase(DB_HANDLE hdb)
5039dede 173{
5039dede 174 // Delete ACL
22ee6d97
VK
175 bool success = executeQueryOnObject(hdb, _T("DELETE FROM acl WHERE object_id=?"));
176 if (success)
177 success = executeQueryOnObject(hdb, _T("DELETE FROM object_properties WHERE object_id=?"));
178 if (success)
179 success = executeQueryOnObject(hdb, _T("DELETE FROM object_custom_attributes WHERE object_id=?"));
d1c4701c
VK
180 if (success)
181 success = executeQueryOnObject(hdb, _T("DELETE FROM object_urls WHERE object_id=?"));
22ee6d97
VK
182
183 // Delete events
3f39fdc2 184 if (success && ConfigReadInt(_T("DeleteEventsOfDeletedObject"), 1))
22ee6d97
VK
185 {
186 success = executeQueryOnObject(hdb, _T("DELETE FROM event_log WHERE event_source=?"));
187 }
188
189 // Delete alarms
3f39fdc2 190 if (success && ConfigReadInt(_T("DeleteAlarmsOfDeletedObject"), 1))
22ee6d97 191 {
c42b4551 192 success = DeleteObjectAlarms(m_id, hdb);
22ee6d97
VK
193 }
194
d81f090f
VK
195 if (success && isLocationTableExists(hdb))
196 {
197 TCHAR query[256];
198 _sntprintf(query, 256, _T("DROP TABLE gps_history_%d"), m_id);
199 success = DBQuery(hdb, query);
200 }
201
50546cb7
VK
202 // Delete module data
203 if (success && (m_moduleData != NULL))
204 {
400e55c4 205 ModuleDataDatabaseCallbackParams data;
c42b4551 206 data.id = m_id;
400e55c4 207 data.hdb = hdb;
53c3d1e7 208 success = (m_moduleData->forEach(DeleteModuleDataCallback, &data) == _CONTINUE);
50546cb7
VK
209 }
210
22ee6d97
VK
211 return success;
212}
213
214/**
fc381a38
VK
215 * Load common object properties from database
216 */
9bd1bace 217bool NetObj::loadCommonProperties(DB_HANDLE hdb)
5039dede 218{
50546cb7 219 bool success = false;
5039dede
AK
220
221 // Load access options
9bd1bace 222 DB_STATEMENT hStmt = DBPrepare(hdb,
ec19ded8
VK
223 _T("SELECT name,status,is_deleted,")
224 _T("inherit_access_rights,last_modified,status_calc_alg,")
225 _T("status_prop_alg,status_fixed_val,status_shift,")
226 _T("status_translation,status_single_threshold,")
227 _T("status_thresholds,comments,is_system,")
86634c2c 228 _T("location_type,latitude,longitude,location_accuracy,")
56fa1092 229 _T("location_timestamp,guid,image,submap_id,country,city,")
97afcb6e 230 _T("street_address,postcode,maint_mode,maint_event_id FROM object_properties ")
ec19ded8
VK
231 _T("WHERE object_id=?"));
232 if (hStmt != NULL)
233 {
c42b4551 234 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
cd5bb14b 235 DB_RESULT hResult = DBSelectPrepared(hStmt);
ec19ded8
VK
236 if (hResult != NULL)
237 {
238 if (DBGetNumRows(hResult) > 0)
e2babedf 239 {
c42b4551 240 DBGetField(hResult, 0, 0, m_name, MAX_OBJECT_NAME);
db091a1f 241 m_status = DBGetFieldLong(hResult, 0, 1);
386d7c46 242 m_isDeleted = DBGetFieldLong(hResult, 0, 2) ? true : false;
19a2cd39 243 m_inheritAccessRights = DBGetFieldLong(hResult, 0, 3) ? true : false;
ec19ded8 244 m_dwTimeStamp = DBGetFieldULong(hResult, 0, 4);
db091a1f
VK
245 m_statusCalcAlg = DBGetFieldLong(hResult, 0, 5);
246 m_statusPropAlg = DBGetFieldLong(hResult, 0, 6);
247 m_fixedStatus = DBGetFieldLong(hResult, 0, 7);
248 m_statusShift = DBGetFieldLong(hResult, 0, 8);
249 DBGetFieldByteArray(hResult, 0, 9, m_statusTranslation, 4, STATUS_WARNING);
250 m_statusSingleThreshold = DBGetFieldLong(hResult, 0, 10);
251 DBGetFieldByteArray(hResult, 0, 11, m_statusThresholds, 4, 50);
252 safe_free(m_comments);
253 m_comments = DBGetField(hResult, 0, 12, NULL, 0);
01152a54 254 m_isSystem = DBGetFieldLong(hResult, 0, 13) ? true : false;
ec19ded8
VK
255
256 int locType = DBGetFieldLong(hResult, 0, 14);
257 if (locType != GL_UNSET)
258 {
259 TCHAR lat[32], lon[32];
260
261 DBGetField(hResult, 0, 15, lat, 32);
262 DBGetField(hResult, 0, 16, lon, 32);
f2d5b2c4 263 m_geoLocation = GeoLocation(locType, lat, lon, DBGetFieldLong(hResult, 0, 17), DBGetFieldULong(hResult, 0, 18));
ec19ded8
VK
264 }
265 else
266 {
267 m_geoLocation = GeoLocation();
268 }
269
de4af576
VK
270 m_guid = DBGetFieldGUID(hResult, 0, 19);
271 m_image = DBGetFieldGUID(hResult, 0, 20);
f2d5b2c4 272 m_submapId = DBGetFieldULong(hResult, 0, 21);
ec19ded8 273
56fa1092
VK
274 TCHAR country[64], city[64], streetAddress[256], postcode[32];
275 DBGetField(hResult, 0, 22, country, 64);
276 DBGetField(hResult, 0, 23, city, 64);
277 DBGetField(hResult, 0, 24, streetAddress, 256);
278 DBGetField(hResult, 0, 25, postcode, 32);
279 delete m_postalAddress;
280 m_postalAddress = new PostalAddress(country, city, streetAddress, postcode);
281
89fd6fa4 282 m_maintenanceMode = DBGetFieldLong(hResult, 0, 26) ? true : false;
97afcb6e 283 m_maintenanceEventId = DBGetFieldUInt64(hResult, 0, 27);
89fd6fa4 284
50546cb7 285 success = true;
e2babedf 286 }
ec19ded8
VK
287 DBFreeResult(hResult);
288 }
289 DBFreeStatement(hStmt);
290 }
5039dede
AK
291
292 // Load custom attributes
50546cb7 293 if (success)
5039dede 294 {
9bd1bace 295 hStmt = DBPrepare(hdb, _T("SELECT attr_name,attr_value FROM object_custom_attributes WHERE object_id=?"));
cd5bb14b 296 if (hStmt != NULL)
5039dede 297 {
c42b4551 298 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
cd5bb14b
VK
299 DB_RESULT hResult = DBSelectPrepared(hStmt);
300 if (hResult != NULL)
301 {
302 int i, count;
303 TCHAR *name, *value;
3f39fdc2 304
cd5bb14b
VK
305 count = DBGetNumRows(hResult);
306 for(i = 0; i < count; i++)
307 {
308 name = DBGetField(hResult, i, 0, NULL, 0);
309 if (name != NULL)
310 {
cd5bb14b
VK
311 value = DBGetField(hResult, i, 1, NULL, 0);
312 if (value != NULL)
313 {
cd5bb14b
VK
314 m_customAttributes.setPreallocated(name, value);
315 }
5039dede
AK
316 }
317 }
cd5bb14b
VK
318 DBFreeResult(hResult);
319 }
320 else
321 {
50546cb7 322 success = false;
5039dede 323 }
cd5bb14b 324 DBFreeStatement(hStmt);
5039dede
AK
325 }
326 else
327 {
50546cb7 328 success = false;
5039dede
AK
329 }
330 }
3f39fdc2 331
8bdd26dc
VK
332 // Load associated dashboards
333 if (success)
334 {
9bd1bace 335 hStmt = DBPrepare(hdb, _T("SELECT dashboard_id FROM dashboard_associations WHERE object_id=?"));
8bdd26dc
VK
336 if (hStmt != NULL)
337 {
338 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
339 DB_RESULT hResult = DBSelectPrepared(hStmt);
340 if (hResult != NULL)
341 {
342 int count = DBGetNumRows(hResult);
343 for(int i = 0; i < count; i++)
344 {
345 m_dashboards->add(DBGetFieldULong(hResult, i, 0));
346 }
347 DBFreeResult(hResult);
348 }
349 else
350 {
351 success = false;
352 }
353 DBFreeStatement(hStmt);
354 }
355 else
356 {
357 success = false;
358 }
359 }
360
d1c4701c
VK
361 // Load associated URLs
362 if (success)
363 {
364 hStmt = DBPrepare(hdb, _T("SELECT url_id,url,description FROM object_urls WHERE object_id=?"));
365 if (hStmt != NULL)
366 {
367 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
368 DB_RESULT hResult = DBSelectPrepared(hStmt);
369 if (hResult != NULL)
370 {
371 int count = DBGetNumRows(hResult);
372 for(int i = 0; i < count; i++)
373 {
374 m_urls->add(new ObjectUrl(hResult, i));
375 }
376 DBFreeResult(hResult);
377 }
378 else
379 {
380 success = false;
381 }
382 DBFreeStatement(hStmt);
383 }
384 else
385 {
386 success = false;
387 }
388 }
389
50546cb7 390 if (success)
9bd1bace 391 success = loadTrustedNodes(hdb);
0d9b58ef 392
50546cb7 393 if (!success)
c42b4551 394 DbgPrintf(4, _T("NetObj::loadCommonProperties() failed for object %s [%ld] class=%d"), m_name, (long)m_id, getObjectClass());
3f39fdc2 395
50546cb7 396 return success;
5039dede
AK
397}
398
86634c2c 399/**
400e55c4
VK
400 * Callback for saving custom attribute in database
401 */
53c3d1e7 402static EnumerationCallbackResult SaveAttributeCallback(const TCHAR *key, const void *value, void *data)
400e55c4
VK
403{
404 DB_STATEMENT hStmt = (DB_STATEMENT)data;
405 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, key, DB_BIND_STATIC);
406 DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, (const TCHAR *)value, DB_BIND_STATIC);
53c3d1e7 407 return DBExecute(hStmt) ? _CONTINUE : _STOP;
400e55c4
VK
408}
409
410/**
411 * Callback for saving module data in database
412 */
53c3d1e7 413static EnumerationCallbackResult SaveModuleDataCallback(const TCHAR *key, const void *value, void *data)
400e55c4 414{
53c3d1e7 415 return ((ModuleData *)value)->saveToDatabase(((ModuleDataDatabaseCallbackParams *)data)->hdb, ((ModuleDataDatabaseCallbackParams *)data)->id) ? _CONTINUE : _STOP;
400e55c4
VK
416}
417
418/**
86634c2c
VK
419 * Save common object properties to database
420 */
50546cb7 421bool NetObj::saveCommonProperties(DB_HANDLE hdb)
5039dede 422{
f2d5b2c4 423 DB_STATEMENT hStmt;
c42b4551 424 if (IsDatabaseRecordExist(hdb, _T("object_properties"), _T("object_id"), m_id))
f2d5b2c4
VK
425 {
426 hStmt = DBPrepare(hdb,
427 _T("UPDATE object_properties SET name=?,status=?,")
428 _T("is_deleted=?,inherit_access_rights=?,")
429 _T("last_modified=?,status_calc_alg=?,status_prop_alg=?,")
430 _T("status_fixed_val=?,status_shift=?,status_translation=?,")
431 _T("status_single_threshold=?,status_thresholds=?,")
432 _T("comments=?,is_system=?,location_type=?,latitude=?,")
433 _T("longitude=?,location_accuracy=?,location_timestamp=?,")
56fa1092 434 _T("guid=?,image=?,submap_id=?,country=?,city=?,")
f249898f 435 _T("street_address=?,postcode=?,maint_mode=?,maint_event_id=? WHERE object_id=?"));
f2d5b2c4
VK
436 }
437 else
438 {
439 hStmt = DBPrepare(hdb,
440 _T("INSERT INTO object_properties (name,status,is_deleted,")
e2babedf 441 _T("inherit_access_rights,last_modified,status_calc_alg,")
5039dede 442 _T("status_prop_alg,status_fixed_val,status_shift,status_translation,")
e2babedf 443 _T("status_single_threshold,status_thresholds,comments,is_system,")
f2d5b2c4 444 _T("location_type,latitude,longitude,location_accuracy,location_timestamp,")
f249898f
VK
445 _T("guid,image,submap_id,country,city,street_address,postcode,maint_mode,")
446 _T("maint_event_id,object_id) ")
447 _T("VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
f2d5b2c4
VK
448 }
449 if (hStmt == NULL)
e4926628 450 return false;
3f39fdc2 451
de4af576 452 TCHAR szTranslation[16], szThresholds[16], lat[32], lon[32];
f2d5b2c4
VK
453 for(int i = 0, j = 0; i < 4; i++, j += 2)
454 {
db091a1f
VK
455 _sntprintf(&szTranslation[j], 16 - j, _T("%02X"), (BYTE)m_statusTranslation[i]);
456 _sntprintf(&szThresholds[j], 16 - j, _T("%02X"), (BYTE)m_statusThresholds[i]);
5039dede 457 }
f2d5b2c4
VK
458 _sntprintf(lat, 32, _T("%f"), m_geoLocation.getLatitude());
459 _sntprintf(lon, 32, _T("%f"), m_geoLocation.getLongitude());
460
c42b4551 461 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, m_name, DB_BIND_STATIC);
db091a1f 462 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, (LONG)m_status);
01152a54 463 DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, (LONG)(m_isDeleted ? 1 : 0));
19a2cd39 464 DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, (LONG)(m_inheritAccessRights ? 1 : 0));
f2d5b2c4 465 DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, (LONG)m_dwTimeStamp);
db091a1f
VK
466 DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, (LONG)m_statusCalcAlg);
467 DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, (LONG)m_statusPropAlg);
468 DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, (LONG)m_fixedStatus);
469 DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, (LONG)m_statusShift);
f2d5b2c4 470 DBBind(hStmt, 10, DB_SQLTYPE_VARCHAR, szTranslation, DB_BIND_STATIC);
db091a1f 471 DBBind(hStmt, 11, DB_SQLTYPE_INTEGER, (LONG)m_statusSingleThreshold);
f2d5b2c4 472 DBBind(hStmt, 12, DB_SQLTYPE_VARCHAR, szThresholds, DB_BIND_STATIC);
db091a1f 473 DBBind(hStmt, 13, DB_SQLTYPE_VARCHAR, m_comments, DB_BIND_STATIC);
01152a54 474 DBBind(hStmt, 14, DB_SQLTYPE_INTEGER, (LONG)(m_isSystem ? 1 : 0));
f2d5b2c4
VK
475 DBBind(hStmt, 15, DB_SQLTYPE_INTEGER, (LONG)m_geoLocation.getType());
476 DBBind(hStmt, 16, DB_SQLTYPE_VARCHAR, lat, DB_BIND_STATIC);
477 DBBind(hStmt, 17, DB_SQLTYPE_VARCHAR, lon, DB_BIND_STATIC);
478 DBBind(hStmt, 18, DB_SQLTYPE_INTEGER, (LONG)m_geoLocation.getAccuracy());
967893bb 479 DBBind(hStmt, 19, DB_SQLTYPE_INTEGER, (UINT32)m_geoLocation.getTimestamp());
de4af576
VK
480 DBBind(hStmt, 20, DB_SQLTYPE_VARCHAR, m_guid);
481 DBBind(hStmt, 21, DB_SQLTYPE_VARCHAR, m_image);
f2d5b2c4 482 DBBind(hStmt, 22, DB_SQLTYPE_INTEGER, m_submapId);
56fa1092
VK
483 DBBind(hStmt, 23, DB_SQLTYPE_VARCHAR, m_postalAddress->getCountry(), DB_BIND_STATIC);
484 DBBind(hStmt, 24, DB_SQLTYPE_VARCHAR, m_postalAddress->getCity(), DB_BIND_STATIC);
485 DBBind(hStmt, 25, DB_SQLTYPE_VARCHAR, m_postalAddress->getStreetAddress(), DB_BIND_STATIC);
486 DBBind(hStmt, 26, DB_SQLTYPE_VARCHAR, m_postalAddress->getPostCode(), DB_BIND_STATIC);
89fd6fa4 487 DBBind(hStmt, 27, DB_SQLTYPE_VARCHAR, m_maintenanceMode ? _T("1") : _T("0"), DB_BIND_STATIC);
f249898f
VK
488 DBBind(hStmt, 28, DB_SQLTYPE_BIGINT, m_maintenanceEventId);
489 DBBind(hStmt, 29, DB_SQLTYPE_INTEGER, m_id);
f2d5b2c4 490
8bdd26dc 491 bool success = DBExecute(hStmt);
f2d5b2c4 492 DBFreeStatement(hStmt);
3f39fdc2 493
5039dede 494 // Save custom attributes
50546cb7 495 if (success)
5039dede 496 {
f2d5b2c4 497 TCHAR szQuery[512];
c42b4551 498 _sntprintf(szQuery, 512, _T("DELETE FROM object_custom_attributes WHERE object_id=%d"), m_id);
8bdd26dc 499 success = DBQuery(hdb, szQuery);
50546cb7 500 if (success)
5039dede 501 {
f2d5b2c4 502 hStmt = DBPrepare(hdb, _T("INSERT INTO object_custom_attributes (object_id,attr_name,attr_value) VALUES (?,?,?)"));
ff392ecf 503 if (hStmt != NULL)
5039dede 504 {
c42b4551 505 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
53c3d1e7 506 success = (m_customAttributes.forEach(SaveAttributeCallback, hStmt) == _CONTINUE);
ff392ecf
VK
507 DBFreeStatement(hStmt);
508 }
509 else
510 {
50546cb7 511 success = false;
5039dede
AK
512 }
513 }
514 }
515
8bdd26dc
VK
516 // Save dashboard associations
517 if (success)
518 {
d1c4701c 519 success = ExecuteQueryOnObject(hdb, m_id, _T("DELETE FROM dashboard_associations WHERE object_id=?"));
8bdd26dc
VK
520 if (success && (m_dashboards->size() > 0))
521 {
522 hStmt = DBPrepare(hdb, _T("INSERT INTO dashboard_associations (object_id,dashboard_id) VALUES (?,?)"));
523 if (hStmt != NULL)
524 {
525 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
526 for(int i = 0; (i < m_dashboards->size()) && success; i++)
527 {
528 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_dashboards->get(i));
529 success = DBExecute(hStmt);
530 }
531 DBFreeStatement(hStmt);
532 }
533 else
534 {
535 success = false;
536 }
537 }
538 }
539
d1c4701c
VK
540 // Save URL associations
541 if (success)
542 {
543 success = ExecuteQueryOnObject(hdb, m_id, _T("DELETE FROM object_urls WHERE object_id=?"));
544 if (success && (m_urls->size() > 0))
545 {
546 hStmt = DBPrepare(hdb, _T("INSERT INTO object_urls (object_id,url_id,url,description) VALUES (?,?,?,?)"));
547 if (hStmt != NULL)
548 {
549 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
550 for(int i = 0; (i < m_urls->size()) && success; i++)
551 {
552 const ObjectUrl *url = m_urls->get(i);
553 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, url->getId());
554 DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, url->getUrl(), DB_BIND_STATIC);
555 DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, url->getDescription(), DB_BIND_STATIC);
556 success = DBExecute(hStmt);
557 }
558 DBFreeStatement(hStmt);
559 }
560 else
561 {
562 success = false;
563 }
564 }
565 }
566
50546cb7
VK
567 // Save module data
568 if (success && (m_moduleData != NULL))
569 {
400e55c4 570 ModuleDataDatabaseCallbackParams data;
c42b4551 571 data.id = m_id;
400e55c4 572 data.hdb = hdb;
53c3d1e7 573 success = (m_moduleData->forEach(SaveModuleDataCallback, &data) == _CONTINUE);
50546cb7 574 }
5039dede 575
50546cb7
VK
576 if (success)
577 success = saveTrustedNodes(hdb);
578
579 return success;
5039dede
AK
580}
581
f2d5b2c4
VK
582/**
583 * Add reference to the new child object
584 */
1f8be1f4 585void NetObj::addChild(NetObj *object)
5039dede 586{
db091a1f
VK
587 lockChildList(true);
588 if (m_childList->contains(object))
bf788217
VK
589 {
590 unlockChildList();
db091a1f 591 return; // Already in the child list
bf788217 592 }
db091a1f
VK
593 m_childList->add(object);
594 unlockChildList();
21c9acce 595 incRefCount();
c42b4551 596 setModified();
1f8be1f4 597 DbgPrintf(7, _T("NetObj::addChild: this=%s [%d]; object=%s [%d]"), m_name, m_id, object->m_name, object->m_id);
5039dede
AK
598}
599
21c9acce
VK
600/**
601 * Add reference to parent object
602 */
1f8be1f4 603void NetObj::addParent(NetObj *object)
5039dede 604{
db091a1f
VK
605 lockParentList(true);
606 if (m_parentList->contains(object))
bf788217
VK
607 {
608 unlockParentList();
db091a1f 609 return; // Already in the parents list
bf788217 610 }
db091a1f
VK
611 m_parentList->add(object);
612 unlockParentList();
21c9acce 613 incRefCount();
c42b4551 614 setModified();
1f8be1f4 615 DbgPrintf(7, _T("NetObj::addParent: this=%s [%d]; object=%s [%d]"), m_name, m_id, object->m_name, object->m_id);
5039dede
AK
616}
617
f2d5b2c4
VK
618/**
619 * Delete reference to child object
620 */
1f8be1f4 621void NetObj::deleteChild(NetObj *object)
5039dede 622{
db091a1f 623 int i;
5039dede 624
db091a1f
VK
625 lockChildList(true);
626 for(i = 0; i < m_childList->size(); i++)
627 if (m_childList->get(i) == object)
5039dede
AK
628 break;
629
db091a1f 630 if (i == m_childList->size()) // No such object
5039dede 631 {
db091a1f 632 unlockChildList();
5039dede
AK
633 return;
634 }
1f8be1f4
VK
635
636 DbgPrintf(7, _T("NetObj::deleteChild: this=%s [%d]; object=%s [%d]"), m_name, m_id, object->m_name, object->m_id);
db091a1f
VK
637 m_childList->remove(i);
638 unlockChildList();
21c9acce 639 decRefCount();
c42b4551 640 setModified();
5039dede
AK
641}
642
21c9acce
VK
643/**
644 * Delete reference to parent object
645 */
1f8be1f4 646void NetObj::deleteParent(NetObj *object)
5039dede 647{
db091a1f 648 int i;
5039dede 649
db091a1f
VK
650 lockParentList(true);
651 for(i = 0; i < m_parentList->size(); i++)
652 if (m_parentList->get(i) == object)
5039dede 653 break;
db091a1f 654 if (i == m_parentList->size()) // No such object
5039dede 655 {
db091a1f 656 unlockParentList();
5039dede
AK
657 return;
658 }
1f8be1f4
VK
659
660 DbgPrintf(7, _T("NetObj::deleteParent: this=%s [%d]; object=%s [%d]"), m_name, m_id, object->m_name, object->m_id);
661
db091a1f
VK
662 m_parentList->remove(i);
663 unlockParentList();
21c9acce 664 decRefCount();
c42b4551 665 setModified();
5039dede
AK
666}
667
c50f77f7
VK
668/**
669 * Walker callback to call OnObjectDelete for each active object
670 */
27de5dab
VK
671void NetObj::onObjectDeleteCallback(NetObj *object, void *data)
672{
c42b4551
VK
673 UINT32 currId = ((NetObj *)data)->getId();
674 if ((object->getId() != currId) && !object->isDeleted())
22ee6d97 675 object->onObjectDelete(currId);
27de5dab
VK
676}
677
c50f77f7
VK
678/**
679 * Prepare object for deletion - remove all references, etc.
9dea3344
VK
680 *
681 * @param initiator pointer to parent object which causes recursive deletion or NULL
c50f77f7 682 */
9dea3344 683void NetObj::deleteObject(NetObj *initiator)
5039dede 684{
c42b4551 685 DbgPrintf(4, _T("Deleting object %d [%s]"), m_id, m_name);
5039dede 686
dcfafffb 687 // Prevent object change propagation until it's marked as deleted
9dea3344 688 // (to prevent the object's incorrect appearance in GUI
c42b4551 689 lockProperties();
01152a54 690 m_isHidden = true;
c42b4551 691 unlockProperties();
5039dede 692
95171c4b 693 // Notify modules about object deletion
a0efa7b5 694 CALL_ALL_MODULES(pfPreObjectDelete, (this));
95171c4b 695
22ee6d97 696 prepareForDeletion();
5039dede 697
c42b4551 698 DbgPrintf(5, _T("NetObj::deleteObject(): deleting object %d from indexes"), m_id);
98de9b1f
VK
699 NetObjDeleteFromIndexes(this);
700
5039dede 701 // Delete references to this object from child objects
c42b4551 702 DbgPrintf(5, _T("NetObj::deleteObject(): clearing child list for object %d"), m_id);
98de9b1f 703 ObjectArray<NetObj> *deleteList = NULL;
db091a1f 704 lockChildList(true);
274d9c7a 705 for(int i = 0; i < m_childList->size(); i++)
5039dede 706 {
db091a1f
VK
707 NetObj *o = m_childList->get(i);
708 if (o->getParentCount() == 1)
9dea3344
VK
709 {
710 // last parent, delete object
98de9b1f
VK
711 if (deleteList == NULL)
712 deleteList = new ObjectArray<NetObj>(16, 16, false);
db091a1f 713 deleteList->add(o);
9dea3344
VK
714 }
715 else
716 {
db091a1f 717 o->deleteParent(this);
9dea3344 718 }
21c9acce 719 decRefCount();
5039dede 720 }
db091a1f
VK
721 m_childList->clear();
722 unlockChildList();
5039dede 723
9dea3344 724 // Remove references to this object from parent objects
c42b4551 725 DbgPrintf(5, _T("NetObj::Delete(): clearing parent list for object %d"), m_id);
db091a1f
VK
726 lockParentList(true);
727 for(int i = 0; i < m_parentList->size(); i++)
9dea3344 728 {
6e0d3549 729 // If parent is deletion initiator then this object already
9dea3344 730 // removed from parent's list
db091a1f
VK
731 NetObj *obj = m_parentList->get(i);
732 if (obj != initiator)
9dea3344 733 {
db091a1f 734 obj->deleteChild(this);
48d6f530
EJ
735 if ((obj->getObjectClass() == OBJECT_SUBNET) && (g_flags & AF_DELETE_EMPTY_SUBNETS) && (obj->getChildCount() == 0))
736 {
737 if (deleteList == NULL)
738 deleteList = new ObjectArray<NetObj>(16, 16, false);
739 deleteList->add(obj);
740 }
741 else
742 obj->calculateCompoundStatus();
9dea3344
VK
743 }
744 decRefCount();
745 }
db091a1f
VK
746 m_parentList->clear();
747 unlockParentList();
9dea3344 748
48d6f530
EJ
749 // Delete orphaned child objects and empty subnets
750 if (deleteList != NULL)
751 {
752 for(int i = 0; i < deleteList->size(); i++)
753 {
754 NetObj *obj = deleteList->get(i);
755 DbgPrintf(5, _T("NetObj::deleteObject(): calling deleteObject() on %s [%d]"), obj->getName(), obj->getId());
756 obj->deleteObject(this);
757 }
758 delete deleteList;
759 }
760
c42b4551 761 lockProperties();
01152a54
VK
762 m_isHidden = false;
763 m_isDeleted = true;
c42b4551
VK
764 setModified();
765 unlockProperties();
5039dede 766
5039dede 767 // Notify all other objects about object deletion
c42b4551 768 DbgPrintf(5, _T("NetObj::deleteObject(): calling onObjectDelete(%d)"), m_id);
27de5dab 769 g_idxObjectById.forEach(onObjectDeleteCallback, this);
5039dede 770
c42b4551 771 DbgPrintf(4, _T("Object %d successfully deleted"), m_id);
5039dede
AK
772}
773
fca08da9
VK
774/**
775 * Default handler for object deletion notification
776 */
967893bb 777void NetObj::onObjectDelete(UINT32 dwObjectId)
5039dede
AK
778{
779}
780
fca08da9
VK
781/**
782 * Get childs IDs in printable form
783 */
784const TCHAR *NetObj::dbgGetChildList(TCHAR *szBuffer)
5039dede 785{
9f24efb3 786 TCHAR *pBuf = szBuffer;
5039dede 787 *pBuf = 0;
db091a1f
VK
788 lockChildList(false);
789 for(int i = 0; i < m_childList->size(); i++)
5039dede 790 {
db091a1f 791 _sntprintf(pBuf, 10, _T("%d "), m_childList->get(i)->getId());
5039dede
AK
792 while(*pBuf)
793 pBuf++;
794 }
db091a1f 795 unlockChildList();
5039dede
AK
796 if (pBuf != szBuffer)
797 *(pBuf - 1) = 0;
798 return szBuffer;
799}
800
fca08da9
VK
801/**
802 * Get parents IDs in printable form
803 */
804const TCHAR *NetObj::dbgGetParentList(TCHAR *szBuffer)
5039dede 805{
9f24efb3 806 TCHAR *pBuf = szBuffer;
5039dede 807 *pBuf = 0;
db091a1f
VK
808 lockParentList(false);
809 for(int i = 0; i < m_parentList->size(); i++)
5039dede 810 {
db091a1f 811 _sntprintf(pBuf, 10, _T("%d "), m_parentList->get(i)->getId());
5039dede
AK
812 while(*pBuf)
813 pBuf++;
814 }
db091a1f 815 unlockParentList();
5039dede
AK
816 if (pBuf != szBuffer)
817 *(pBuf - 1) = 0;
818 return szBuffer;
819}
820
fca08da9
VK
821/**
822 * Calculate status for compound object based on childs' status
823 */
27f9598d 824void NetObj::calculateCompoundStatus(BOOL bForcedRecalc)
5039dede 825{
db091a1f 826 if (m_status == STATUS_UNMANAGED)
a26c8857
VK
827 return;
828
c42b4551 829 int mostCriticalAlarm = GetMostCriticalStatusForObject(m_id);
e83d726c 830 int mostCriticalDCI =
c42b4551 831 (getObjectClass() == OBJECT_NODE || getObjectClass() == OBJECT_MOBILEDEVICE || getObjectClass() == OBJECT_CLUSTER || getObjectClass() == OBJECT_ACCESSPOINT) ?
e83d726c 832 ((DataCollectionTarget *)this)->getMostCriticalDCIStatus() : STATUS_UNKNOWN;
a26c8857 833
db091a1f
VK
834 int oldStatus = m_status;
835 int mostCriticalStatus, i, count, iStatusAlg;
a26c8857 836 int nSingleThreshold, *pnThresholds;
5039dede
AK
837 int nRating[5], iChildStatus, nThresholds[4];
838
c42b4551 839 lockProperties();
db091a1f 840 if (m_statusCalcAlg == SA_CALCULATE_DEFAULT)
5039dede 841 {
a26c8857
VK
842 iStatusAlg = GetDefaultStatusCalculation(&nSingleThreshold, &pnThresholds);
843 }
844 else
845 {
db091a1f
VK
846 iStatusAlg = m_statusCalcAlg;
847 nSingleThreshold = m_statusSingleThreshold;
848 pnThresholds = m_statusThresholds;
a26c8857
VK
849 }
850 if (iStatusAlg == SA_CALCULATE_SINGLE_THRESHOLD)
851 {
852 for(i = 0; i < 4; i++)
853 nThresholds[i] = nSingleThreshold;
854 pnThresholds = nThresholds;
855 }
5039dede 856
a26c8857
VK
857 switch(iStatusAlg)
858 {
859 case SA_CALCULATE_MOST_CRITICAL:
db091a1f
VK
860 lockChildList(false);
861 for(i = 0, count = 0, mostCriticalStatus = -1; i < m_childList->size(); i++)
a26c8857 862 {
db091a1f 863 iChildStatus = m_childList->get(i)->getPropagatedStatus();
a26c8857
VK
864 if ((iChildStatus < STATUS_UNKNOWN) &&
865 (iChildStatus > mostCriticalStatus))
5039dede 866 {
a26c8857
VK
867 mostCriticalStatus = iChildStatus;
868 count++;
5039dede 869 }
a26c8857 870 }
db091a1f
VK
871 m_status = (count > 0) ? mostCriticalStatus : STATUS_UNKNOWN;
872 unlockChildList();
a26c8857
VK
873 break;
874 case SA_CALCULATE_SINGLE_THRESHOLD:
875 case SA_CALCULATE_MULTIPLE_THRESHOLDS:
876 // Step 1: calculate severity raitings
877 memset(nRating, 0, sizeof(int) * 5);
db091a1f
VK
878 lockChildList(false);
879 for(i = 0, count = 0; i < m_childList->size(); i++)
a26c8857 880 {
db091a1f 881 iChildStatus = m_childList->get(i)->getPropagatedStatus();
a26c8857 882 if (iChildStatus < STATUS_UNKNOWN)
5039dede 883 {
a26c8857
VK
884 while(iChildStatus >= 0)
885 nRating[iChildStatus--]++;
886 count++;
5039dede 887 }
a26c8857 888 }
db091a1f 889 unlockChildList();
5039dede 890
a26c8857
VK
891 // Step 2: check what severity rating is above threshold
892 if (count > 0)
5039dede 893 {
a26c8857
VK
894 for(i = 4; i > 0; i--)
895 if (nRating[i] * 100 / count >= pnThresholds[i - 1])
896 break;
db091a1f 897 m_status = i;
5039dede
AK
898 }
899 else
900 {
db091a1f 901 m_status = STATUS_UNKNOWN;
5039dede 902 }
a26c8857
VK
903 break;
904 default:
db091a1f 905 m_status = STATUS_UNKNOWN;
a26c8857
VK
906 break;
907 }
908
909 // If alarms exist for object, apply alarm severity to object's status
910 if (mostCriticalAlarm != STATUS_UNKNOWN)
911 {
db091a1f 912 if (m_status == STATUS_UNKNOWN)
a26c8857 913 {
db091a1f 914 m_status = mostCriticalAlarm;
a26c8857
VK
915 }
916 else
917 {
db091a1f 918 m_status = max(m_status, mostCriticalAlarm);
a26c8857
VK
919 }
920 }
921
3f71633b 922 // If DCI status is calculated for object apply DCI object's status
a26c8857
VK
923 if (mostCriticalDCI != STATUS_UNKNOWN)
924 {
db091a1f 925 if (m_status == STATUS_UNKNOWN)
a26c8857 926 {
db091a1f 927 m_status = mostCriticalDCI;
a26c8857
VK
928 }
929 else
930 {
db091a1f 931 m_status = max(m_status, mostCriticalDCI);
5039dede 932 }
a26c8857 933 }
f84f22b5 934
a26c8857
VK
935 // Query loaded modules for object status
936 ENUMERATE_MODULES(pfCalculateObjectStatus)
937 {
938 int moduleStatus = g_pModuleList[__i].pfCalculateObjectStatus(this);
939 if (moduleStatus != STATUS_UNKNOWN)
cd68963b 940 {
db091a1f 941 if (m_status == STATUS_UNKNOWN)
cd68963b 942 {
db091a1f 943 m_status = moduleStatus;
cd68963b 944 }
945 else
946 {
db091a1f 947 m_status = max(m_status, moduleStatus);
cd68963b 948 }
949 }
a26c8857 950 }
cd68963b 951
c42b4551 952 unlockProperties();
f84f22b5 953
a26c8857 954 // Cause parent object(s) to recalculate it's status
db091a1f 955 if ((oldStatus != m_status) || bForcedRecalc)
a26c8857 956 {
db091a1f
VK
957 lockParentList(false);
958 for(i = 0; i < m_parentList->size(); i++)
959 m_parentList->get(i)->calculateCompoundStatus();
960 unlockParentList();
c42b4551
VK
961 lockProperties();
962 setModified();
963 unlockProperties();
5039dede
AK
964 }
965}
966
fca08da9
VK
967/**
968 * Load ACL from database
969 */
9bd1bace 970bool NetObj::loadACLFromDB(DB_HANDLE hdb)
5039dede 971{
50546cb7 972 bool success = false;
5039dede 973
9bd1bace 974 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT user_id,access_rights FROM acl WHERE object_id=?"));
92c51b1d
VK
975 if (hStmt != NULL)
976 {
c42b4551 977 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
92c51b1d
VK
978 DB_RESULT hResult = DBSelectPrepared(hStmt);
979 if (hResult != NULL)
980 {
19a2cd39
VK
981 int count = DBGetNumRows(hResult);
982 for(int i = 0; i < count; i++)
983 m_accessList->addElement(DBGetFieldULong(hResult, i, 0), DBGetFieldULong(hResult, i, 1));
92c51b1d 984 DBFreeResult(hResult);
50546cb7 985 success = true;
92c51b1d
VK
986 }
987 DBFreeStatement(hStmt);
988 }
50546cb7 989 return success;
5039dede
AK
990}
991
f2d5b2c4
VK
992/**
993 * ACL enumeration parameters structure
994 */
5039dede
AK
995struct SAVE_PARAM
996{
997 DB_HANDLE hdb;
967893bb 998 UINT32 dwObjectId;
5039dede
AK
999};
1000
f2d5b2c4
VK
1001/**
1002 * Handler for ACL elements enumeration
1003 */
967893bb 1004static void EnumerationHandler(UINT32 dwUserId, UINT32 dwAccessRights, void *pArg)
5039dede 1005{
35f836fe 1006 TCHAR szQuery[256];
5039dede 1007
4fe87cdc 1008 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("INSERT INTO acl (object_id,user_id,access_rights) VALUES (%d,%d,%d)"),
5039dede
AK
1009 ((SAVE_PARAM *)pArg)->dwObjectId, dwUserId, dwAccessRights);
1010 DBQuery(((SAVE_PARAM *)pArg)->hdb, szQuery);
1011}
1012
f2d5b2c4
VK
1013/**
1014 * Save ACL to database
1015 */
50546cb7 1016bool NetObj::saveACLToDB(DB_HANDLE hdb)
5039dede 1017{
35f836fe 1018 TCHAR szQuery[256];
50546cb7 1019 bool success = false;
5039dede
AK
1020 SAVE_PARAM sp;
1021
1022 // Save access list
e2c2154a 1023 lockACL();
c42b4551 1024 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("DELETE FROM acl WHERE object_id=%d"), m_id);
5039dede
AK
1025 if (DBQuery(hdb, szQuery))
1026 {
c42b4551 1027 sp.dwObjectId = m_id;
5039dede 1028 sp.hdb = hdb;
19a2cd39 1029 m_accessList->enumerateElements(EnumerationHandler, &sp);
50546cb7 1030 success = true;
5039dede 1031 }
e2c2154a 1032 unlockACL();
50546cb7 1033 return success;
5039dede
AK
1034}
1035
f2d5b2c4 1036/**
400e55c4
VK
1037 * Data for SendModuleDataCallback
1038 */
1039struct SendModuleDataCallbackData
1040{
b368969c 1041 NXCPMessage *msg;
400e55c4
VK
1042 UINT32 id;
1043};
1044
1045/**
1046 * Callback for sending module data in NXCP message
1047 */
53c3d1e7 1048static EnumerationCallbackResult SendModuleDataCallback(const TCHAR *key, const void *value, void *data)
400e55c4 1049{
b368969c 1050 ((SendModuleDataCallbackData *)data)->msg->setField(((SendModuleDataCallbackData *)data)->id, key);
400e55c4
VK
1051 ((ModuleData *)value)->fillMessage(((SendModuleDataCallbackData *)data)->msg, ((SendModuleDataCallbackData *)data)->id + 1);
1052 ((SendModuleDataCallbackData *)data)->id += 0x100000;
53c3d1e7 1053 return _CONTINUE;
400e55c4
VK
1054}
1055
1056/**
8fe90adb 1057 * Fill NXCP message with object's data
9289a3bb
VK
1058 * Object's properties are locked when this method is called. Method should not do any other locks.
1059 * Data required other locks should be filled in fillMessageInternalStage2().
f2d5b2c4 1060 */
8fe90adb 1061void NetObj::fillMessageInternal(NXCPMessage *pMsg)
5039dede 1062{
b368969c
VK
1063 pMsg->setField(VID_OBJECT_CLASS, (WORD)getObjectClass());
1064 pMsg->setField(VID_OBJECT_ID, m_id);
de4af576 1065 pMsg->setField(VID_GUID, m_guid);
b368969c 1066 pMsg->setField(VID_OBJECT_NAME, m_name);
db091a1f 1067 pMsg->setField(VID_OBJECT_STATUS, (WORD)m_status);
b368969c 1068 pMsg->setField(VID_IS_DELETED, (WORD)(m_isDeleted ? 1 : 0));
104e6c86
VK
1069 pMsg->setField(VID_IS_SYSTEM, (INT16)(m_isSystem ? 1 : 0));
1070 pMsg->setField(VID_MAINTENANCE_MODE, (INT16)(m_maintenanceEventId ? 1 : 0));
9fc55f9e 1071
19a2cd39 1072 pMsg->setField(VID_INHERIT_RIGHTS, m_inheritAccessRights);
db091a1f
VK
1073 pMsg->setField(VID_STATUS_CALCULATION_ALG, (WORD)m_statusCalcAlg);
1074 pMsg->setField(VID_STATUS_PROPAGATION_ALG, (WORD)m_statusPropAlg);
1075 pMsg->setField(VID_FIXED_STATUS, (WORD)m_fixedStatus);
1076 pMsg->setField(VID_STATUS_SHIFT, (WORD)m_statusShift);
1077 pMsg->setField(VID_STATUS_TRANSLATION_1, (WORD)m_statusTranslation[0]);
1078 pMsg->setField(VID_STATUS_TRANSLATION_2, (WORD)m_statusTranslation[1]);
1079 pMsg->setField(VID_STATUS_TRANSLATION_3, (WORD)m_statusTranslation[2]);
1080 pMsg->setField(VID_STATUS_TRANSLATION_4, (WORD)m_statusTranslation[3]);
1081 pMsg->setField(VID_STATUS_SINGLE_THRESHOLD, (WORD)m_statusSingleThreshold);
1082 pMsg->setField(VID_STATUS_THRESHOLD_1, (WORD)m_statusThresholds[0]);
1083 pMsg->setField(VID_STATUS_THRESHOLD_2, (WORD)m_statusThresholds[1]);
1084 pMsg->setField(VID_STATUS_THRESHOLD_3, (WORD)m_statusThresholds[2]);
1085 pMsg->setField(VID_STATUS_THRESHOLD_4, (WORD)m_statusThresholds[3]);
1086 pMsg->setField(VID_COMMENTS, CHECK_NULL_EX(m_comments));
de4af576 1087 pMsg->setField(VID_IMAGE, m_image);
10d79457 1088 pMsg->setField(VID_DRILL_DOWN_OBJECT_ID, m_submapId);
b368969c 1089 pMsg->setField(VID_NUM_TRUSTED_NODES, m_dwNumTrustedNodes);
5039dede 1090 if (m_dwNumTrustedNodes > 0)
b368969c 1091 pMsg->setFieldFromInt32Array(VID_TRUSTED_NODES, m_dwNumTrustedNodes, m_pdwTrustedNodes);
8bdd26dc 1092 pMsg->setFieldFromInt32Array(VID_DASHBOARDS, m_dashboards);
5039dede 1093
400e55c4 1094 m_customAttributes.fillMessage(pMsg, VID_NUM_CUSTOM_ATTRIBUTES, VID_CUSTOM_ATTRIBUTES_BASE);
5039dede 1095
40bd1038 1096 m_geoLocation.fillMessage(*pMsg);
2e590d1a 1097
b368969c
VK
1098 pMsg->setField(VID_COUNTRY, m_postalAddress->getCountry());
1099 pMsg->setField(VID_CITY, m_postalAddress->getCity());
1100 pMsg->setField(VID_STREET_ADDRESS, m_postalAddress->getStreetAddress());
1101 pMsg->setField(VID_POSTCODE, m_postalAddress->getPostCode());
56fa1092 1102
d1c4701c
VK
1103 pMsg->setField(VID_NUM_URLS, (UINT32)m_urls->size());
1104 UINT32 fieldId = VID_URL_LIST_BASE;
1105 for(int i = 0; i < m_urls->size(); i++)
1106 {
1107 const ObjectUrl *url = m_urls->get(i);
1108 pMsg->setField(fieldId++, url->getId());
1109 pMsg->setField(fieldId++, url->getUrl());
1110 pMsg->setField(fieldId++, url->getDescription());
1111 fieldId += 7;
1112 }
1113
d92045a2 1114 if (m_moduleData != NULL)
2e590d1a 1115 {
b368969c 1116 pMsg->setField(VID_MODULE_DATA_COUNT, (UINT16)m_moduleData->size());
400e55c4
VK
1117 SendModuleDataCallbackData data;
1118 data.msg = pMsg;
1119 data.id = VID_MODULE_DATA_BASE;
1120 m_moduleData->forEach(SendModuleDataCallback, &data);
d92045a2
VK
1121 }
1122 else
1123 {
b368969c 1124 pMsg->setField(VID_MODULE_DATA_COUNT, (UINT16)0);
2e590d1a 1125 }
8fe90adb 1126}
e83d726c 1127
8fe90adb 1128/**
9289a3bb
VK
1129 * Fill NXCP message with object's data - stage 2
1130 * Object's properties are not locked when this method is called. Should be
0088436b 1131 * used only to fill data where properties lock is not enough (like data
9289a3bb
VK
1132 * collection configuration).
1133 */
1134void NetObj::fillMessageInternalStage2(NXCPMessage *pMsg)
1135{
1136}
1137
1138/**
8fe90adb
VK
1139 * Fill NXCP message with object's data
1140 */
1141void NetObj::fillMessage(NXCPMessage *msg)
0088436b 1142{
1143 lockProperties();
9289a3bb 1144 fillMessageInternal(msg);
0088436b 1145 unlockProperties();
9289a3bb 1146 fillMessageInternalStage2(msg);
8fe90adb 1147
19a2cd39
VK
1148 lockACL();
1149 m_accessList->fillMessage(msg);
1150 unlockACL();
1151
db091a1f
VK
1152 UINT32 dwId;
1153 int i;
8fe90adb 1154
db091a1f
VK
1155 lockParentList(false);
1156 msg->setField(VID_PARENT_CNT, m_parentList->size());
1157 for(i = 0, dwId = VID_PARENT_ID_BASE; i < m_parentList->size(); i++, dwId++)
1158 msg->setField(dwId, m_parentList->get(i)->getId());
1159 unlockParentList();
8fe90adb 1160
db091a1f
VK
1161 lockChildList(false);
1162 msg->setField(VID_CHILD_CNT, m_childList->size());
1163 for(i = 0, dwId = VID_CHILD_ID_BASE; i < m_childList->size(); i++, dwId++)
1164 msg->setField(dwId, m_childList->get(i)->getId());
1165 unlockChildList();
5039dede
AK
1166}
1167
f2d5b2c4
VK
1168/**
1169 * Handler for EnumerateSessions()
1170 */
5039dede
AK
1171static void BroadcastObjectChange(ClientSession *pSession, void *pArg)
1172{
e05b1945
VK
1173 if (pSession->isAuthenticated())
1174 pSession->onObjectChange((NetObj *)pArg);
5039dede
AK
1175}
1176
f2d5b2c4
VK
1177/**
1178 * Mark object as modified and put on client's notification queue
1179 * We assume that object is locked at the time of function call
1180 */
ba756b1a 1181void NetObj::setModified(bool notify)
5039dede
AK
1182{
1183 if (g_bModificationsLocked)
1184 return;
1185
01152a54 1186 m_isModified = true;
967893bb 1187 m_dwTimeStamp = (UINT32)time(NULL);
5039dede
AK
1188
1189 // Send event to all connected clients
ba756b1a 1190 if (notify && !m_isHidden && !m_isSystem)
5039dede
AK
1191 EnumerateClientSessions(BroadcastObjectChange, this);
1192}
1193
f2d5b2c4 1194/**
8fe90adb
VK
1195 * Modify object from NXCP message - common wrapper
1196 */
1197UINT32 NetObj::modifyFromMessage(NXCPMessage *msg)
0088436b 1198{
1199 lockProperties();
8fe90adb
VK
1200 UINT32 rcc = modifyFromMessageInternal(msg);
1201 setModified();
1202 unlockProperties();
0088436b 1203 return rcc;
8fe90adb
VK
1204}
1205
1206/**
f2d5b2c4
VK
1207 * Modify object from NXCP message
1208 */
8fe90adb 1209UINT32 NetObj::modifyFromMessageInternal(NXCPMessage *pRequest)
5039dede 1210{
5039dede 1211 // Change object's name
5c44534b 1212 if (pRequest->isFieldExist(VID_OBJECT_NAME))
b368969c 1213 pRequest->getFieldAsString(VID_OBJECT_NAME, m_name, MAX_OBJECT_NAME);
5039dede 1214
5039dede 1215 // Change object's status calculation/propagation algorithms
5c44534b 1216 if (pRequest->isFieldExist(VID_STATUS_CALCULATION_ALG))
5039dede 1217 {
db091a1f
VK
1218 m_statusCalcAlg = pRequest->getFieldAsInt16(VID_STATUS_CALCULATION_ALG);
1219 m_statusPropAlg = pRequest->getFieldAsInt16(VID_STATUS_PROPAGATION_ALG);
1220 m_fixedStatus = pRequest->getFieldAsInt16(VID_FIXED_STATUS);
1221 m_statusShift = pRequest->getFieldAsInt16(VID_STATUS_SHIFT);
1222 m_statusTranslation[0] = pRequest->getFieldAsInt16(VID_STATUS_TRANSLATION_1);
1223 m_statusTranslation[1] = pRequest->getFieldAsInt16(VID_STATUS_TRANSLATION_2);
1224 m_statusTranslation[2] = pRequest->getFieldAsInt16(VID_STATUS_TRANSLATION_3);
1225 m_statusTranslation[3] = pRequest->getFieldAsInt16(VID_STATUS_TRANSLATION_4);
1226 m_statusSingleThreshold = pRequest->getFieldAsInt16(VID_STATUS_SINGLE_THRESHOLD);
1227 m_statusThresholds[0] = pRequest->getFieldAsInt16(VID_STATUS_THRESHOLD_1);
1228 m_statusThresholds[1] = pRequest->getFieldAsInt16(VID_STATUS_THRESHOLD_2);
1229 m_statusThresholds[2] = pRequest->getFieldAsInt16(VID_STATUS_THRESHOLD_3);
1230 m_statusThresholds[3] = pRequest->getFieldAsInt16(VID_STATUS_THRESHOLD_4);
5039dede
AK
1231 }
1232
f25b0d12 1233 // Change image
5c44534b 1234 if (pRequest->isFieldExist(VID_IMAGE))
de4af576 1235 m_image = pRequest->getFieldAsGUID(VID_IMAGE);
f25b0d12 1236
5039dede 1237 // Change object's ACL
5c44534b 1238 if (pRequest->isFieldExist(VID_ACL_SIZE))
5039dede 1239 {
e2c2154a 1240 lockACL();
19a2cd39
VK
1241 m_inheritAccessRights = pRequest->getFieldAsBoolean(VID_INHERIT_RIGHTS);
1242 m_accessList->deleteAll();
1243 int count = pRequest->getFieldAsUInt32(VID_ACL_SIZE);
1244 for(int i = 0; i < count; i++)
1245 m_accessList->addElement(pRequest->getFieldAsUInt32(VID_ACL_USER_BASE + i),
1246 pRequest->getFieldAsUInt32(VID_ACL_RIGHTS_BASE + i));
e2c2154a 1247 unlockACL();
5039dede
AK
1248 }
1249
1250 // Change trusted nodes list
5c44534b 1251 if (pRequest->isFieldExist(VID_NUM_TRUSTED_NODES))
5039dede 1252 {
b368969c 1253 m_dwNumTrustedNodes = pRequest->getFieldAsUInt32(VID_NUM_TRUSTED_NODES);
967893bb 1254 m_pdwTrustedNodes = (UINT32 *)realloc(m_pdwTrustedNodes, sizeof(UINT32) * m_dwNumTrustedNodes);
9a68ca24 1255 pRequest->getFieldAsInt32Array(VID_TRUSTED_NODES, m_dwNumTrustedNodes, m_pdwTrustedNodes);
5039dede 1256 }
3f39fdc2 1257
5039dede 1258 // Change custom attributes
5c44534b 1259 if (pRequest->isFieldExist(VID_NUM_CUSTOM_ATTRIBUTES))
5039dede 1260 {
967893bb 1261 UINT32 i, dwId, dwNumElements;
5039dede
AK
1262 TCHAR *name, *value;
1263
b368969c 1264 dwNumElements = pRequest->getFieldAsUInt32(VID_NUM_CUSTOM_ATTRIBUTES);
fb986055 1265 m_customAttributes.clear();
5039dede
AK
1266 for(i = 0, dwId = VID_CUSTOM_ATTRIBUTES_BASE; i < dwNumElements; i++)
1267 {
b368969c
VK
1268 name = pRequest->getFieldAsString(dwId++);
1269 value = pRequest->getFieldAsString(dwId++);
5039dede 1270 if ((name != NULL) && (value != NULL))
fb986055 1271 m_customAttributes.setPreallocated(name, value);
5039dede
AK
1272 }
1273 }
1274
40bd1038 1275 // Change geolocation
5c44534b 1276 if (pRequest->isFieldExist(VID_GEOLOCATION_TYPE))
40bd1038
VK
1277 {
1278 m_geoLocation = GeoLocation(*pRequest);
4899db4d 1279 addLocationToHistory();
40bd1038
VK
1280 }
1281
10d79457 1282 if (pRequest->isFieldExist(VID_DRILL_DOWN_OBJECT_ID))
8f245200 1283 {
10d79457 1284 m_submapId = pRequest->getFieldAsUInt32(VID_DRILL_DOWN_OBJECT_ID);
8f245200
VK
1285 }
1286
56fa1092
VK
1287 if (pRequest->isFieldExist(VID_COUNTRY))
1288 {
1289 TCHAR buffer[64];
b368969c 1290 pRequest->getFieldAsString(VID_COUNTRY, buffer, 64);
56fa1092
VK
1291 m_postalAddress->setCountry(buffer);
1292 }
1293
1294 if (pRequest->isFieldExist(VID_CITY))
1295 {
1296 TCHAR buffer[64];
b368969c 1297 pRequest->getFieldAsString(VID_CITY, buffer, 64);
56fa1092
VK
1298 m_postalAddress->setCity(buffer);
1299 }
1300
1301 if (pRequest->isFieldExist(VID_STREET_ADDRESS))
1302 {
1303 TCHAR buffer[256];
b368969c 1304 pRequest->getFieldAsString(VID_STREET_ADDRESS, buffer, 256);
56fa1092
VK
1305 m_postalAddress->setStreetAddress(buffer);
1306 }
1307
1308 if (pRequest->isFieldExist(VID_POSTCODE))
1309 {
1310 TCHAR buffer[32];
b368969c 1311 pRequest->getFieldAsString(VID_POSTCODE, buffer, 32);
56fa1092
VK
1312 m_postalAddress->setPostCode(buffer);
1313 }
1314
8bdd26dc
VK
1315 // Change dashboard list
1316 if (pRequest->isFieldExist(VID_DASHBOARDS))
1317 {
1318 pRequest->getFieldAsInt32Array(VID_DASHBOARDS, m_dashboards);
1319 }
1320
d1c4701c
VK
1321 // Update URL list
1322 if (pRequest->isFieldExist(VID_NUM_URLS))
1323 {
1324 m_urls->clear();
1325 int count = pRequest->getFieldAsInt32(VID_NUM_URLS);
1326 UINT32 fieldId = VID_URL_LIST_BASE;
1327 for(int i = 0; i < count; i++)
1328 {
1329 m_urls->add(new ObjectUrl(pRequest, fieldId));
1330 fieldId += 10;
1331 }
1332 }
1333
5039dede
AK
1334 return RCC_SUCCESS;
1335}
1336
6b8e9f96
VK
1337/**
1338 * Post-modify hook
1339 */
6ff21d27
VK
1340void NetObj::postModify()
1341{
cb1ae425 1342 calculateCompoundStatus(TRUE);
6ff21d27
VK
1343}
1344
6b8e9f96
VK
1345/**
1346 * Get rights to object for specific user
1347 *
1348 * @param userId user object ID
1349 */
967893bb 1350UINT32 NetObj::getUserRights(UINT32 userId)
5039dede 1351{
967893bb 1352 UINT32 dwRights;
5039dede
AK
1353
1354 // Admin always has all rights to any object
6b8e9f96 1355 if (userId == 0)
5039dede
AK
1356 return 0xFFFFFFFF;
1357
1358 // Non-admin users have no rights to system objects
01152a54 1359 if (m_isSystem)
5039dede
AK
1360 return 0;
1361
88b51c0e 1362 // Check if have direct right assignment
e2c2154a 1363 lockACL();
19a2cd39 1364 bool hasDirectRights = m_accessList->getUserRights(userId, &dwRights);
e2c2154a 1365 unlockACL();
5039dede 1366
88b51c0e 1367 if (!hasDirectRights)
5039dede
AK
1368 {
1369 // We don't. If this object inherit rights from parents, get them
19a2cd39 1370 if (m_inheritAccessRights)
5039dede 1371 {
db091a1f
VK
1372 dwRights = 0;
1373 lockParentList(false);
1374 for(int i = 0; i < m_parentList->size(); i++)
1375 dwRights |= m_parentList->get(i)->getUserRights(userId);
1376 unlockParentList();
5039dede
AK
1377 }
1378 }
1379
5039dede
AK
1380 return dwRights;
1381}
1382
6b8e9f96
VK
1383/**
1384 * Check if given user has specific rights on this object
1385 *
1386 * @param userId user object ID
1387 * @param requiredRights bit mask of requested right
1388 * @return true if user has all rights specified in requested rights bit mask
1389 */
967893bb 1390BOOL NetObj::checkAccessRights(UINT32 userId, UINT32 requiredRights)
5039dede 1391{
967893bb 1392 UINT32 effectiveRights = getUserRights(userId);
6b8e9f96 1393 return (effectiveRights & requiredRights) == requiredRights;
5039dede
AK
1394}
1395
6b8e9f96
VK
1396/**
1397 * Drop all user privileges on current object
1398 */
967893bb 1399void NetObj::dropUserAccess(UINT32 dwUserId)
5039dede 1400{
e2c2154a 1401 lockACL();
19a2cd39 1402 bool modified = m_accessList->deleteElement(dwUserId);
e2c2154a 1403 unlockACL();
88b51c0e
VK
1404 if (modified)
1405 {
c42b4551
VK
1406 lockProperties();
1407 setModified();
1408 unlockProperties();
88b51c0e 1409 }
5039dede
AK
1410}
1411
6b8e9f96
VK
1412/**
1413 * Set object's management status
1414 */
eec253a8 1415void NetObj::setMgmtStatus(BOOL bIsManaged)
5039dede 1416{
a26c8857 1417 int oldStatus;
5039dede 1418
c42b4551 1419 lockProperties();
5039dede 1420
db091a1f
VK
1421 if ((bIsManaged && (m_status != STATUS_UNMANAGED)) ||
1422 ((!bIsManaged) && (m_status == STATUS_UNMANAGED)))
5039dede 1423 {
c42b4551 1424 unlockProperties();
5039dede
AK
1425 return; // Status is already correct
1426 }
1427
db091a1f
VK
1428 oldStatus = m_status;
1429 m_status = (bIsManaged ? STATUS_UNKNOWN : STATUS_UNMANAGED);
5039dede
AK
1430
1431 // Generate event if current object is a node
c42b4551
VK
1432 if (getObjectClass() == OBJECT_NODE)
1433 PostEvent(bIsManaged ? EVENT_NODE_UNKNOWN : EVENT_NODE_UNMANAGED, m_id, "d", oldStatus);
5039dede 1434
c42b4551
VK
1435 setModified();
1436 unlockProperties();
5039dede
AK
1437
1438 // Change status for child objects also
db091a1f
VK
1439 lockChildList(false);
1440 for(int i = 0; i < m_childList->size(); i++)
1441 m_childList->get(i)->setMgmtStatus(bIsManaged);
1442 unlockChildList();
5039dede
AK
1443
1444 // Cause parent object(s) to recalculate it's status
db091a1f
VK
1445 lockParentList(false);
1446 for(int i = 0; i < m_parentList->size(); i++)
1447 m_parentList->get(i)->calculateCompoundStatus();
1448 unlockParentList();
5039dede
AK
1449}
1450
21c9acce
VK
1451/**
1452 * Check if given object is an our child (possibly indirect, i.e child of child)
1453 *
1454 * @param id object ID to test
1455 */
967893bb 1456bool NetObj::isChild(UINT32 id)
5039dede 1457{
21c9acce 1458 bool bResult = false;
5039dede
AK
1459
1460 // Check for our own ID (object ID should never change, so we may not lock object's data)
c42b4551 1461 if (m_id == id)
21c9acce 1462 bResult = true;
5039dede
AK
1463
1464 // First, walk through our own child list
1465 if (!bResult)
1466 {
db091a1f
VK
1467 lockChildList(false);
1468 for(int i = 0; i < m_childList->size(); i++)
1469 if (m_childList->get(i)->getId() == id)
5039dede 1470 {
21c9acce 1471 bResult = true;
5039dede
AK
1472 break;
1473 }
db091a1f 1474 unlockChildList();
5039dede
AK
1475 }
1476
1477 // If given object is not in child list, check if it is indirect child
1478 if (!bResult)
1479 {
db091a1f
VK
1480 lockChildList(false);
1481 for(int i = 0; i < m_childList->size(); i++)
1482 if (m_childList->get(i)->isChild(id))
5039dede 1483 {
21c9acce 1484 bResult = true;
5039dede
AK
1485 break;
1486 }
db091a1f 1487 unlockChildList();
5039dede
AK
1488 }
1489
1490 return bResult;
1491}
1492
21c9acce
VK
1493/**
1494 * Send message to client, who requests poll, if any
1495 * This method is used by Node and Interface class objects
1496 */
967893bb 1497void NetObj::sendPollerMsg(UINT32 dwRqId, const TCHAR *pszFormat, ...)
5039dede 1498{
c59466d2 1499 if (m_pollRequestor != NULL)
5039dede
AK
1500 {
1501 va_list args;
1502 TCHAR szBuffer[1024];
1503
1504 va_start(args, pszFormat);
1505 _vsntprintf(szBuffer, 1024, pszFormat, args);
1506 va_end(args);
c59466d2 1507 m_pollRequestor->sendPollerMsg(dwRqId, szBuffer);
5039dede
AK
1508 }
1509}
1510
6fd6de0a
VK
1511/**
1512 * Add child node objects (direct and indirect childs) to list
1513 */
967893bb 1514void NetObj::addChildNodesToList(ObjectArray<Node> *nodeList, UINT32 dwUserId)
5039dede 1515{
db091a1f 1516 lockChildList(false);
5039dede
AK
1517
1518 // Walk through our own child list
db091a1f 1519 for(int i = 0; i < m_childList->size(); i++)
5039dede 1520 {
db091a1f
VK
1521 NetObj *object = m_childList->get(i);
1522 if (object->getObjectClass() == OBJECT_NODE)
5039dede
AK
1523 {
1524 // Check if this node already in the list
711e5e9a
VK
1525 int j;
1526 for(j = 0; j < nodeList->size(); j++)
db091a1f 1527 if (nodeList->get(j)->getId() == object->getId())
5039dede 1528 break;
711e5e9a 1529 if (j == nodeList->size())
5039dede 1530 {
db091a1f
VK
1531 object->incRefCount();
1532 nodeList->add((Node *)object);
5039dede
AK
1533 }
1534 }
1535 else
1536 {
db091a1f
VK
1537 if (object->checkAccessRights(dwUserId, OBJECT_ACCESS_READ))
1538 object->addChildNodesToList(nodeList, dwUserId);
5039dede
AK
1539 }
1540 }
1541
db091a1f 1542 unlockChildList();
5039dede
AK
1543}
1544
6fd6de0a
VK
1545/**
1546 * Add child data collection targets (direct and indirect childs) to list
1547 */
967893bb 1548void NetObj::addChildDCTargetsToList(ObjectArray<DataCollectionTarget> *dctList, UINT32 dwUserId)
6fd6de0a 1549{
db091a1f 1550 lockChildList(false);
6fd6de0a
VK
1551
1552 // Walk through our own child list
db091a1f 1553 for(int i = 0; i < m_childList->size(); i++)
6fd6de0a 1554 {
db091a1f
VK
1555 NetObj *object = m_childList->get(i);
1556 if (!object->checkAccessRights(dwUserId, OBJECT_ACCESS_READ))
1557 continue;
1558
1559 if (object->isDataCollectionTarget())
6fd6de0a
VK
1560 {
1561 // Check if this objects already in the list
1562 int j;
1563 for(j = 0; j < dctList->size(); j++)
db091a1f 1564 if (dctList->get(j)->getId() == object->getId())
6fd6de0a
VK
1565 break;
1566 if (j == dctList->size())
1567 {
db091a1f
VK
1568 object->incRefCount();
1569 dctList->add((DataCollectionTarget *)object);
6fd6de0a
VK
1570 }
1571 }
db091a1f 1572 object->addChildDCTargetsToList(dctList, dwUserId);
6fd6de0a
VK
1573 }
1574
db091a1f 1575 unlockChildList();
6fd6de0a 1576}
5039dede 1577
6fd6de0a
VK
1578/**
1579 * Hide object and all its childs
1580 */
478d4ff4 1581void NetObj::hide()
5039dede 1582{
db091a1f
VK
1583 lockChildList(false);
1584 for(int i = 0; i < m_childList->size(); i++)
1585 m_childList->get(i)->hide();
1586 unlockChildList();
f5d16551 1587
c42b4551 1588 lockProperties();
01152a54 1589 m_isHidden = true;
c42b4551 1590 unlockProperties();
5039dede
AK
1591}
1592
fca08da9
VK
1593/**
1594 * Unhide object and all its childs
1595 */
478d4ff4 1596void NetObj::unhide()
5039dede 1597{
c42b4551 1598 lockProperties();
01152a54
VK
1599 m_isHidden = false;
1600 if (!m_isSystem)
1601 EnumerateClientSessions(BroadcastObjectChange, this);
c42b4551 1602 unlockProperties();
5039dede 1603
db091a1f
VK
1604 lockChildList(false);
1605 for(int i = 0; i < m_childList->size(); i++)
1606 m_childList->get(i)->unhide();
1607 unlockChildList();
5039dede
AK
1608}
1609
fca08da9
VK
1610/**
1611 * Return status propagated to parent
1612 */
6ff21d27 1613int NetObj::getPropagatedStatus()
5039dede
AK
1614{
1615 int iStatus;
1616
db091a1f 1617 if (m_statusPropAlg == SA_PROPAGATE_DEFAULT)
5039dede 1618 {
db091a1f 1619 iStatus = DefaultPropagatedStatus(m_status);
5039dede
AK
1620 }
1621 else
1622 {
db091a1f 1623 switch(m_statusPropAlg)
5039dede
AK
1624 {
1625 case SA_PROPAGATE_UNCHANGED:
db091a1f 1626 iStatus = m_status;
5039dede
AK
1627 break;
1628 case SA_PROPAGATE_FIXED:
db091a1f 1629 iStatus = ((m_status > STATUS_NORMAL) && (m_status < STATUS_UNKNOWN)) ? m_fixedStatus : m_status;
5039dede
AK
1630 break;
1631 case SA_PROPAGATE_RELATIVE:
db091a1f 1632 if ((m_status > STATUS_NORMAL) && (m_status < STATUS_UNKNOWN))
5039dede 1633 {
db091a1f 1634 iStatus = m_status + m_statusShift;
5039dede
AK
1635 if (iStatus < 0)
1636 iStatus = 0;
1637 if (iStatus > STATUS_CRITICAL)
1638 iStatus = STATUS_CRITICAL;
1639 }
1640 else
1641 {
db091a1f 1642 iStatus = m_status;
5039dede
AK
1643 }
1644 break;
1645 case SA_PROPAGATE_TRANSLATED:
db091a1f 1646 if ((m_status > STATUS_NORMAL) && (m_status < STATUS_UNKNOWN))
5039dede 1647 {
db091a1f 1648 iStatus = m_statusTranslation[m_status - 1];
5039dede
AK
1649 }
1650 else
1651 {
db091a1f 1652 iStatus = m_status;
5039dede
AK
1653 }
1654 break;
1655 default:
1656 iStatus = STATUS_UNKNOWN;
1657 break;
1658 }
1659 }
1660 return iStatus;
1661}
1662
fca08da9
VK
1663/**
1664 * Prepare object for deletion. Method should return only
1665 * when object deletion is safe
1666 */
22ee6d97 1667void NetObj::prepareForDeletion()
5039dede
AK
1668{
1669}
1670
fca08da9 1671/**
3f39fdc2 1672 * Set object's comments.
fca08da9
VK
1673 * NOTE: pszText should be dynamically allocated or NULL
1674 */
c42b4551 1675void NetObj::setComments(TCHAR *text)
5039dede 1676{
c42b4551 1677 lockProperties();
e4926628 1678 free(m_comments);
db091a1f 1679 m_comments = text;
c42b4551
VK
1680 setModified();
1681 unlockProperties();
5039dede
AK
1682}
1683
fca08da9 1684/**
6b8e9f96 1685 * Copy object's comments to NXCP message
fca08da9 1686 */
b368969c 1687void NetObj::commentsToMessage(NXCPMessage *pMsg)
5039dede 1688{
c42b4551 1689 lockProperties();
db091a1f 1690 pMsg->setField(VID_COMMENTS, CHECK_NULL_EX(m_comments));
c42b4551 1691 unlockProperties();
5039dede
AK
1692}
1693
fca08da9
VK
1694/**
1695 * Load trusted nodes list from database
1696 */
9bd1bace 1697bool NetObj::loadTrustedNodes(DB_HANDLE hdb)
5039dede
AK
1698{
1699 DB_RESULT hResult;
1700 TCHAR query[256];
1701 int i, count;
1702
c42b4551 1703 _sntprintf(query, 256, _T("SELECT target_node_id FROM trusted_nodes WHERE source_object_id=%d"), m_id);
9bd1bace 1704 hResult = DBSelect(hdb, query);
5039dede
AK
1705 if (hResult != NULL)
1706 {
1707 count = DBGetNumRows(hResult);
1708 if (count > 0)
1709 {
1710 m_dwNumTrustedNodes = count;
967893bb 1711 m_pdwTrustedNodes = (UINT32 *)malloc(sizeof(UINT32) * count);
5039dede
AK
1712 for(i = 0; i < count; i++)
1713 {
1714 m_pdwTrustedNodes[i] = DBGetFieldULong(hResult, i, 0);
1715 }
1716 }
1717 DBFreeResult(hResult);
1718 }
1719 return (hResult != NULL);
1720}
1721
fca08da9
VK
1722/**
1723 * Save list of trusted nodes to database
1724 */
50546cb7 1725bool NetObj::saveTrustedNodes(DB_HANDLE hdb)
5039dede
AK
1726{
1727 TCHAR query[256];
967893bb 1728 UINT32 i;
50546cb7 1729 bool rc = false;
5039dede 1730
c42b4551 1731 _sntprintf(query, 256, _T("DELETE FROM trusted_nodes WHERE source_object_id=%d"), m_id);
5039dede
AK
1732 if (DBQuery(hdb, query))
1733 {
1734 for(i = 0; i < m_dwNumTrustedNodes; i++)
1735 {
1736 _sntprintf(query, 256, _T("INSERT INTO trusted_nodes (source_object_id,target_node_id) VALUES (%d,%d)"),
c42b4551 1737 m_id, m_pdwTrustedNodes[i]);
5039dede
AK
1738 if (!DBQuery(hdb, query))
1739 break;
1740 }
1741 if (i == m_dwNumTrustedNodes)
50546cb7 1742 rc = true;
5039dede
AK
1743 }
1744 return rc;
1745}
1746
fca08da9
VK
1747/**
1748 * Check if given node is in trust list
1749 * Will always return TRUE if system parameter CheckTrustedNodes set to 0
1750 */
967893bb 1751bool NetObj::isTrustedNode(UINT32 id)
5039dede 1752{
21c9acce 1753 bool rc;
5039dede 1754
c8076b19 1755 if (g_flags & AF_CHECK_TRUSTED_NODES)
5039dede 1756 {
967893bb 1757 UINT32 i;
5039dede 1758
c42b4551 1759 lockProperties();
21c9acce 1760 for(i = 0, rc = false; i < m_dwNumTrustedNodes; i++)
5039dede
AK
1761 {
1762 if (m_pdwTrustedNodes[i] == id)
1763 {
21c9acce 1764 rc = true;
5039dede
AK
1765 break;
1766 }
1767 }
c42b4551 1768 unlockProperties();
5039dede
AK
1769 }
1770 else
1771 {
21c9acce 1772 rc = true;
5039dede
AK
1773 }
1774 return rc;
1775}
06c104c6 1776
fca08da9
VK
1777/**
1778 * Get list of parent objects for NXSL script
1779 */
06c104c6
VK
1780NXSL_Array *NetObj::getParentsForNXSL()
1781{
1782 NXSL_Array *parents = new NXSL_Array;
1783 int index = 0;
1784
db091a1f
VK
1785 lockParentList(false);
1786 for(int i = 0; i < m_parentList->size(); i++)
06c104c6 1787 {
db091a1f
VK
1788 NetObj *obj = m_parentList->get(i);
1789 if ((obj->getObjectClass() == OBJECT_CONTAINER) ||
1790 (obj->getObjectClass() == OBJECT_SERVICEROOT) ||
1791 (obj->getObjectClass() == OBJECT_NETWORK))
06c104c6 1792 {
db091a1f 1793 parents->set(index++, new NXSL_Value(new NXSL_Object(&g_nxslNetObjClass, obj)));
06c104c6
VK
1794 }
1795 }
db091a1f 1796 unlockParentList();
06c104c6
VK
1797
1798 return parents;
1799}
d679defa 1800
fc381a38
VK
1801/**
1802 * Get list of child objects for NXSL script
1803 */
d679defa
VK
1804NXSL_Array *NetObj::getChildrenForNXSL()
1805{
1806 NXSL_Array *children = new NXSL_Array;
1807 int index = 0;
1808
db091a1f
VK
1809 lockChildList(false);
1810 for(int i = 0; i < m_childList->size(); i++)
d679defa 1811 {
fa36e7f0 1812 children->set(index++, m_childList->get(i)->createNXSLObject());
d679defa 1813 }
db091a1f 1814 unlockChildList();
d679defa
VK
1815
1816 return children;
1817}
fc381a38
VK
1818
1819/**
1820 * Get full list of child objects (including both direct and indirect childs)
1821 */
1822void NetObj::getFullChildListInternal(ObjectIndex *list, bool eventSourceOnly)
1823{
db091a1f
VK
1824 lockChildList(false);
1825 for(int i = 0; i < m_childList->size(); i++)
fc381a38 1826 {
db091a1f
VK
1827 NetObj *obj = m_childList->get(i);
1828 if (!eventSourceOnly || IsEventSource(obj->getObjectClass()))
1829 list->put(obj->getId(), obj);
1830 obj->getFullChildListInternal(list, eventSourceOnly);
fc381a38 1831 }
db091a1f 1832 unlockChildList();
fc381a38
VK
1833}
1834
1835/**
fca08da9
VK
1836 * Get full list of child objects (including both direct and indirect childs).
1837 * Returned array is dynamically allocated and must be deleted by the caller.
1838 *
1839 * @param eventSourceOnly if true, only objects that can be event source will be included
fc381a38 1840 */
da9cf449 1841ObjectArray<NetObj> *NetObj::getFullChildList(bool eventSourceOnly, bool updateRefCount)
fc381a38
VK
1842{
1843 ObjectIndex list;
1844 getFullChildListInternal(&list, eventSourceOnly);
da9cf449 1845 return list.getObjects(updateRefCount);
fc381a38 1846}
fca08da9
VK
1847
1848/**
1849 * Get list of child objects (direct only). Returned array is
1850 * dynamically allocated and must be deleted by the caller.
1851 *
3f39fdc2 1852 * @param typeFilter Only return objects with class ID equals given value.
fca08da9
VK
1853 * Set to -1 to disable filtering.
1854 */
1855ObjectArray<NetObj> *NetObj::getChildList(int typeFilter)
1856{
db091a1f
VK
1857 lockChildList(false);
1858 ObjectArray<NetObj> *list = new ObjectArray<NetObj>((int)m_childList->size(), 16, false);
1859 for(int i = 0; i < m_childList->size(); i++)
fca08da9 1860 {
db091a1f
VK
1861 if ((typeFilter == -1) || (typeFilter == m_childList->get(i)->getObjectClass()))
1862 list->add(m_childList->get(i));
fca08da9 1863 }
db091a1f 1864 unlockChildList();
fca08da9
VK
1865 return list;
1866}
27bbb906
VK
1867
1868/**
64e87664
VK
1869 * Get list of parent objects (direct only). Returned array is
1870 * dynamically allocated and must be deleted by the caller.
1871 *
1872 * @param typeFilter Only return objects with class ID equals given value.
1873 * Set to -1 to disable filtering.
1874 */
1875ObjectArray<NetObj> *NetObj::getParentList(int typeFilter)
1876{
db091a1f
VK
1877 lockParentList(false);
1878 ObjectArray<NetObj> *list = new ObjectArray<NetObj>(m_parentList->size(), 16, false);
1879 for(int i = 0; i < m_parentList->size(); i++)
64e87664 1880 {
db091a1f
VK
1881 if ((typeFilter == -1) || (typeFilter == m_parentList->get(i)->getObjectClass()))
1882 list->add(m_parentList->get(i));
64e87664 1883 }
db091a1f 1884 unlockParentList();
64e87664
VK
1885 return list;
1886}
1887
1888/**
67de55fd
VK
1889 * FInd child object by name (with optional class filter)
1890 */
1891NetObj *NetObj::findChildObject(const TCHAR *name, int typeFilter)
1892{
1893 NetObj *object = NULL;
db091a1f
VK
1894 lockChildList(false);
1895 for(int i = 0; i < m_childList->size(); i++)
67de55fd 1896 {
db091a1f
VK
1897 NetObj *o = m_childList->get(i);
1898 if (((typeFilter == -1) || (typeFilter == o->getObjectClass())) && !_tcsicmp(name, o->getName()))
67de55fd 1899 {
db091a1f 1900 object = o;
67de55fd
VK
1901 break;
1902 }
1903 }
db091a1f 1904 unlockChildList();
67de55fd
VK
1905 return object;
1906}
1907
1908/**
41c081df
VK
1909 * Find child node by IP address
1910 */
1911Node *NetObj::findChildNode(const InetAddress& addr)
1912{
1913 Node *node = NULL;
1914 lockChildList(false);
1915 for(int i = 0; i < m_childList->size(); i++)
1916 {
1917 NetObj *curr = m_childList->get(i);
1918 if ((curr->getObjectClass() == OBJECT_NODE) && addr.equals(((Node *)curr)->getIpAddress()))
1919 {
1920 node = (Node *)curr;
1921 break;
1922 }
1923 }
1924 unlockChildList();
1925 return node;
1926}
1927
1928/**
27bbb906
VK
1929 * Called by client session handler to check if threshold summary should
1930 * be shown for this object. Default implementation always returns false.
1931 */
1932bool NetObj::showThresholdSummary()
1933{
1934 return false;
1935}
d1730ccf
VK
1936
1937/**
1938 * Must return true if object is a possible event source
1939 */
1940bool NetObj::isEventSource()
1941{
1942 return false;
1943}
4f5d216b
VK
1944
1945/**
db091a1f
VK
1946 * Must return true if object is a possible data collection target
1947 */
1948bool NetObj::isDataCollectionTarget()
1949{
1950 return false;
1951}
1952
1953/**
4f5d216b
VK
1954 * Get module data
1955 */
4899db4d 1956ModuleData *NetObj::getModuleData(const TCHAR *module)
1957{
c42b4551 1958 lockProperties();
4f5d216b 1959 ModuleData *data = (m_moduleData != NULL) ? m_moduleData->get(module) : NULL;
c42b4551 1960 unlockProperties();
4f5d216b
VK
1961 return data;
1962}
1963
1964/**
1965 * Set module data
1966 */
1967void NetObj::setModuleData(const TCHAR *module, ModuleData *data)
1968{
c42b4551 1969 lockProperties();
4f5d216b
VK
1970 if (m_moduleData == NULL)
1971 m_moduleData = new StringObjectMap<ModuleData>(true);
1972 m_moduleData->set(module, data);
c42b4551 1973 unlockProperties();
4f5d216b 1974}
4899db4d 1975
1976/**
1977 * Add new location entry
1978 */
1979void NetObj::addLocationToHistory()
1980{
4899db4d 1981 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
4899db4d 1982 bool isSamePlace;
0088436b 1983 double latitude = 0;
1984 double longitude = 0;
1985 UINT32 accuracy = 0;
1986 UINT32 startTimestamp = 0;
4899db4d 1987 DB_RESULT hResult;
d81f090f 1988 if (!isLocationTableExists(hdb))
4899db4d 1989 {
c42b4551 1990 DbgPrintf(4, _T("NetObj::addLocationToHistory: Geolocation history table will be created for object %s [%d]"), m_name, m_id);
7221dde1 1991 if (!createLocationHistoryTable(hdb))
4899db4d 1992 {
c42b4551 1993 DbgPrintf(4, _T("NetObj::addLocationToHistory: Error creating geolocation history table for object %s [%d]"), m_name, m_id);
4899db4d 1994 return;
1995 }
1996 }
1997 const TCHAR *query;
1998 switch(g_dbSyntax)
1999 {
2000 case DB_SYNTAX_ORACLE:
8054880d 2001 query = _T("SELECT * FROM (SELECT latitude,longitude,accuracy,start_timestamp FROM gps_history_%d ORDER BY start_timestamp DESC) WHERE ROWNUM<=1");
4899db4d 2002 break;
2003 case DB_SYNTAX_MSSQL:
2004 query = _T("SELECT TOP 1 latitude,longitude,accuracy,start_timestamp FROM gps_history_%d ORDER BY start_timestamp DESC");
2005 break;
2006 case DB_SYNTAX_DB2:
2007 query = _T("SELECT latitude,longitude,accuracy,start_timestamp FROM gps_history_%d ORDER BY start_timestamp DESC FETCH FIRST 200 ROWS ONLY");
2008 break;
2009 default:
2010 query = _T("SELECT latitude,longitude,accuracy,start_timestamp FROM gps_history_%d ORDER BY start_timestamp DESC LIMIT 1");
2011 break;
2012 }
2013 TCHAR preparedQuery[256];
c42b4551 2014 _sntprintf(preparedQuery, 256, query, m_id);
4899db4d 2015 DB_STATEMENT hStmt = DBPrepare(hdb, preparedQuery);
2016
2017 if (hStmt == NULL)
2018 goto onFail;
2019
2020 hResult = DBSelectPrepared(hStmt);
7221dde1 2021 if (hResult == NULL)
4899db4d 2022 goto onFail;
7221dde1 2023 if (DBGetNumRows(hResult) > 0)
4899db4d 2024 {
0088436b 2025 latitude = DBGetFieldDouble(hResult, 0, 0);
2026 longitude = DBGetFieldDouble(hResult, 0, 1);
2027 accuracy = DBGetFieldLong(hResult, 0, 2);
4899db4d 2028 startTimestamp = DBGetFieldULong(hResult, 0, 3);
0088436b 2029 isSamePlace = m_geoLocation.sameLocation(latitude, longitude, accuracy);
4899db4d 2030 }
2031 else
2032 {
2033 isSamePlace = false;
2034 }
0088436b 2035 DBFreeResult(hResult);
2036 DBFreeStatement(hStmt);
4899db4d 2037
7221dde1 2038 if (isSamePlace)
4899db4d 2039 {
2040 TCHAR query[256];
c42b4551 2041 _sntprintf(query, 255, _T("UPDATE gps_history_%d SET end_timestamp = ? WHERE start_timestamp =? "), m_id);
4899db4d 2042 hStmt = DBPrepare(hdb, query);
0088436b 2043 if (hStmt == NULL)
2044 goto onFail;
4899db4d 2045 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, (UINT32)m_geoLocation.getTimestamp());
2046 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, startTimestamp);
2047 }
2048 else
2049 {
2050 TCHAR query[256];
2051 _sntprintf(query, 255, _T("INSERT INTO gps_history_%d (latitude,longitude,")
c42b4551 2052 _T("accuracy,start_timestamp,end_timestamp) VALUES (?,?,?,?,?)"), m_id);
4899db4d 2053 hStmt = DBPrepare(hdb, query);
0088436b 2054 if (hStmt == NULL)
2055 goto onFail;
4899db4d 2056
a83a24ea 2057 TCHAR lat[32], lon[32];
4899db4d 2058 _sntprintf(lat, 32, _T("%f"), m_geoLocation.getLatitude());
2059 _sntprintf(lon, 32, _T("%f"), m_geoLocation.getLongitude());
2060
2061 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, lat, DB_BIND_STATIC);
2062 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, lon, DB_BIND_STATIC);
2063 DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, (LONG)m_geoLocation.getAccuracy());
2064 DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, (UINT32)m_geoLocation.getTimestamp());
2065 DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, (UINT32)m_geoLocation.getTimestamp());
2066 }
2067
0088436b 2068 if(!DBExecute(hStmt))
2069 {
678e7522 2070 DbgPrintf(1, _T("NetObj::addLocationToHistory: Failed to add location to history. New: lat %f, lon %f, ac %d, t %d. Old: lat %f, lon %f, ac %d, t %d."),
0088436b 2071 m_geoLocation.getLatitude(), m_geoLocation.getLongitude(), m_geoLocation.getAccuracy(), (UINT32)m_geoLocation.getTimestamp(),
2072 latitude, longitude, accuracy, startTimestamp);
2073 }
4899db4d 2074 DBFreeStatement(hStmt);
2075 DBConnectionPoolReleaseConnection(hdb);
2076 return;
2077
2078onFail:
0088436b 2079 if(hStmt != NULL)
2080 DBFreeStatement(hStmt);
c42b4551 2081 DbgPrintf(4, _T("NetObj::addLocationToHistory(%s [%d]): Failed to add location to history"), m_name, m_id);
4899db4d 2082 DBConnectionPoolReleaseConnection(hdb);
2083 return;
2084}
2085
2086/**
2087 * Check if given data table exist
2088 */
d81f090f 2089bool NetObj::isLocationTableExists(DB_HANDLE hdb)
4899db4d 2090{
2091 TCHAR table[256];
c42b4551 2092 _sntprintf(table, 256, _T("gps_history_%d"), m_id);
9bd1bace 2093 int rc = DBIsTableExist(hdb, table);
4899db4d 2094 if (rc == DBIsTableExist_Failure)
2095 {
2096 _tprintf(_T("WARNING: call to DBIsTableExist(\"%s\") failed\n"), table);
2097 }
2098 return rc != DBIsTableExist_NotFound;
2099}
2100
7221dde1
VK
2101/**
2102 * Create table for storing geolocation history for this object
2103 */
2104bool NetObj::createLocationHistoryTable(DB_HANDLE hdb)
4899db4d 2105{
2106 TCHAR szQuery[256], szQueryTemplate[256];
2107 MetaDataReadStr(_T("LocationHistory"), szQueryTemplate, 255, _T(""));
c42b4551 2108 _sntprintf(szQuery, 256, szQueryTemplate, m_id);
4899db4d 2109 if (!DBQuery(hdb, szQuery))
2110 return false;
2111
2112 return true;
2113}
9d850e8b
VK
2114
2115/**
2116 * Set status calculation method
2117 */
2118void NetObj::setStatusCalculation(int method, int arg1, int arg2, int arg3, int arg4)
2119{
c42b4551 2120 lockProperties();
db091a1f 2121 m_statusCalcAlg = method;
9d850e8b
VK
2122 switch(method)
2123 {
2124 case SA_CALCULATE_SINGLE_THRESHOLD:
db091a1f 2125 m_statusSingleThreshold = arg1;
9d850e8b
VK
2126 break;
2127 case SA_CALCULATE_MULTIPLE_THRESHOLDS:
db091a1f
VK
2128 m_statusThresholds[0] = arg1;
2129 m_statusThresholds[1] = arg2;
2130 m_statusThresholds[2] = arg3;
2131 m_statusThresholds[3] = arg4;
9d850e8b
VK
2132 break;
2133 default:
2134 break;
2135 }
c42b4551
VK
2136 setModified();
2137 unlockProperties();
9d850e8b
VK
2138}
2139
2140/**
2141 * Set status propagation method
2142 */
2143void NetObj::setStatusPropagation(int method, int arg1, int arg2, int arg3, int arg4)
2144{
c42b4551 2145 lockProperties();
db091a1f 2146 m_statusPropAlg = method;
9d850e8b
VK
2147 switch(method)
2148 {
2149 case SA_PROPAGATE_FIXED:
db091a1f 2150 m_fixedStatus = arg1;
9d850e8b
VK
2151 break;
2152 case SA_PROPAGATE_RELATIVE:
db091a1f 2153 m_statusShift = arg1;
9d850e8b
VK
2154 break;
2155 case SA_PROPAGATE_TRANSLATED:
db091a1f
VK
2156 m_statusTranslation[0] = arg1;
2157 m_statusTranslation[1] = arg2;
2158 m_statusTranslation[2] = arg3;
2159 m_statusTranslation[3] = arg4;
9d850e8b
VK
2160 break;
2161 default:
2162 break;
2163 }
c42b4551
VK
2164 setModified();
2165 unlockProperties();
9d850e8b 2166}
97afcb6e
VK
2167
2168/**
2169 * Enter maintenance mode
2170 */
2171void NetObj::enterMaintenanceMode()
2172{
666d54e2
VK
2173 DbgPrintf(4, _T("Entering maintenance mode for object %s [%d] (%s)"), m_name, m_id, getObjectClassName());
2174
db091a1f
VK
2175 lockChildList(false);
2176 for(int i = 0; i < m_childList->size(); i++)
666d54e2 2177 {
db091a1f
VK
2178 NetObj *object = m_childList->get(i);
2179 if (object->getStatus() != STATUS_UNMANAGED)
2180 object->enterMaintenanceMode();
666d54e2 2181 }
db091a1f 2182 unlockChildList();
97afcb6e
VK
2183}
2184
2185/**
2186 * Leave maintenance mode
2187 */
2188void NetObj::leaveMaintenanceMode()
2189{
666d54e2
VK
2190 DbgPrintf(4, _T("Leaving maintenance mode for object %s [%d] (%s)"), m_name, m_id, getObjectClassName());
2191
db091a1f
VK
2192 lockChildList(false);
2193 for(int i = 0; i < m_childList->size(); i++)
666d54e2 2194 {
db091a1f
VK
2195 NetObj *object = m_childList->get(i);
2196 if (object->getStatus() != STATUS_UNMANAGED)
2197 object->leaveMaintenanceMode();
666d54e2 2198 }
db091a1f 2199 unlockChildList();
97afcb6e 2200}
ca594353
VK
2201
2202/**
2203 * Get all custom attributes as NXSL hash map
2204 */
2205NXSL_Value *NetObj::getCustomAttributesForNXSL() const
2206{
2207 NXSL_HashMap *map = new NXSL_HashMap();
2208 lockProperties();
2209 StructArray<KeyValuePair> *attributes = m_customAttributes.toArray();
2210 for(int i = 0; i < attributes->size(); i++)
2211 {
2212 KeyValuePair *p = attributes->get(i);
2213 map->set(p->key, new NXSL_Value((const TCHAR *)p->value));
2214 }
2215 unlockProperties();
2216 delete attributes;
2217 return new NXSL_Value(map);
2218}
297a88eb
VK
2219
2220/**
2221 * Create NXSL object for this object
2222 */
2223NXSL_Value *NetObj::createNXSLObject()
2224{
2225 return new NXSL_Value(new NXSL_Object(&g_nxslNetObjClass, this));
2226}
e9ef47dd
VK
2227
2228/**
2229 * Serialize object to JSON
2230 */
2231json_t *NetObj::toJson()
2232{
2233 return NULL;
2234}