object save optimization - object properties divided into groups and anly modified...
authorVictor Kirhenshtein <victor@netxms.org>
Tue, 17 Oct 2017 20:02:14 +0000 (23:02 +0300)
committerVictor Kirhenshtein <victor@netxms.org>
Tue, 17 Oct 2017 20:02:14 +0000 (23:02 +0300)
30 files changed:
doc/internal/debug_tags.txt
src/server/core/accesspoint.cpp
src/server/core/agent_policy.cpp
src/server/core/ap_config.cpp
src/server/core/ap_logparser.cpp
src/server/core/bizservice.cpp
src/server/core/bizsvcroot.cpp
src/server/core/chassis.cpp
src/server/core/cluster.cpp
src/server/core/condition.cpp
src/server/core/container.cpp
src/server/core/dctarget.cpp
src/server/core/entirenet.cpp
src/server/core/interface.cpp
src/server/core/mobile.cpp
src/server/core/netmap.cpp
src/server/core/netobj.cpp
src/server/core/netsrv.cpp
src/server/core/node.cpp
src/server/core/nodelink.cpp
src/server/core/sensor.cpp
src/server/core/slmcheck.cpp
src/server/core/subnet.cpp
src/server/core/svccontainer.cpp
src/server/core/syncer.cpp
src/server/core/template.cpp
src/server/core/uniroot.cpp
src/server/core/vpnconn.cpp
src/server/core/zone.cpp
src/server/include/nms_objects.h

index d5c3db9..4316612 100644 (file)
@@ -8,5 +8,8 @@ housekeeper     Housekeeper messages
 obj.*          Object related trace
 obj.dc.*       Data collection related
 obj.locks.*    Locks
+obj.sync       Object synchronization
+
+sync           Syncer messages
 
 threads.*      Thread related
index 0843a81..0ef6f25 100644 (file)
@@ -140,34 +140,41 @@ bool AccessPoint::saveToDatabase(DB_HANDLE hdb)
    saveCommonProperties(hdb);
 
    bool bResult;
-       DB_STATEMENT hStmt;
-   if (IsDatabaseRecordExist(hdb, _T("access_points"), _T("id"), m_id))
-               hStmt = DBPrepare(hdb, _T("UPDATE access_points SET mac_address=?,vendor=?,model=?,serial_number=?,node_id=?,ap_state=?,ap_index=? WHERE id=?"));
-       else
-               hStmt = DBPrepare(hdb, _T("INSERT INTO access_points (mac_address,vendor,model,serial_number,node_id,ap_state,ap_index,id) VALUES (?,?,?,?,?,?,?,?)"));
-       if (hStmt != NULL)
-       {
-               TCHAR macStr[16];
-               DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, BinToStr(m_macAddr, MAC_ADDR_LENGTH, macStr), DB_BIND_STATIC);
-               DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_vendor), DB_BIND_STATIC);
-               DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_model), DB_BIND_STATIC);
-               DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_serialNumber), DB_BIND_STATIC);
-               DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, m_nodeId);
-               DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, (INT32)m_apState);
-               DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, m_index);
-               DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_id);
-
-               bResult = DBExecute(hStmt);
-
-               DBFreeStatement(hStmt);
-       }
-       else
-       {
-               bResult = false;
-       }
+   if (m_modified & MODIFY_OTHER)
+   {
+      DB_STATEMENT hStmt;
+      if (IsDatabaseRecordExist(hdb, _T("access_points"), _T("id"), m_id))
+         hStmt = DBPrepare(hdb, _T("UPDATE access_points SET mac_address=?,vendor=?,model=?,serial_number=?,node_id=?,ap_state=?,ap_index=? WHERE id=?"));
+      else
+         hStmt = DBPrepare(hdb, _T("INSERT INTO access_points (mac_address,vendor,model,serial_number,node_id,ap_state,ap_index,id) VALUES (?,?,?,?,?,?,?,?)"));
+      if (hStmt != NULL)
+      {
+         TCHAR macStr[16];
+         DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, BinToStr(m_macAddr, MAC_ADDR_LENGTH, macStr), DB_BIND_STATIC);
+         DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_vendor), DB_BIND_STATIC);
+         DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_model), DB_BIND_STATIC);
+         DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_serialNumber), DB_BIND_STATIC);
+         DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, m_nodeId);
+         DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, (INT32)m_apState);
+         DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, m_index);
+         DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_id);
+
+         bResult = DBExecute(hStmt);
+
+         DBFreeStatement(hStmt);
+      }
+      else
+      {
+         bResult = false;
+      }
+   }
+   else
+   {
+      bResult = true;
+   }
 
    // Save data collection items
-   if (bResult)
+   if (bResult && (m_modified & MODIFY_DATA_COLLECTION))
    {
                lockDciAccess(false);
       for(int i = 0; i < m_dcObjects->size(); i++)
@@ -180,7 +187,7 @@ bool AccessPoint::saveToDatabase(DB_HANDLE hdb)
 
    // Clear modifications flag and unlock object
        if (bResult)
-               m_isModified = false;
+               m_modified = 0;
    unlockProperties();
 
    return bResult;
@@ -269,7 +276,7 @@ void AccessPoint::attachToNode(UINT32 nodeId)
 
        lockProperties();
        m_nodeId = nodeId;
-       setModified();
+       setModified(MODIFY_OTHER);
        unlockProperties();
 }
 
@@ -380,7 +387,7 @@ void AccessPoint::updateInfo(const TCHAR *vendor, const TCHAR *model, const TCHA
        free(m_serialNumber);
        m_serialNumber = (serialNumber != NULL) ? _tcsdup(serialNumber) : NULL;
 
-       setModified();
+       setModified(MODIFY_OTHER);
        unlockProperties();
 }
 
@@ -414,7 +421,7 @@ void AccessPoint::updateState(AccessPointState state)
             break;
       }
    }
-   setModified();
+   setModified(MODIFY_OTHER);
        unlockProperties();
 
    if ((state == AP_ADOPTED) || (state == AP_UNADOPTED) || (state == AP_DOWN))
index e4e749f..fc3798c 100644 (file)
@@ -121,7 +121,7 @@ bool AgentPolicy::saveToDatabase(DB_HANDLE hdb)
 
        // Clear modifications flag and unlock object
        if (success)
-               m_isModified = false;
+               m_modified = 0;
    unlockProperties();
 
    return success;
index 50d9949..05356ac 100644 (file)
@@ -85,7 +85,7 @@ bool AgentPolicyConfig::saveToDatabase(DB_HANDLE hdb)
 
        // Clear modifications flag and unlock object
        if (success)
-               m_isModified = false;
+               m_modified = 0;
    unlockProperties();
 
    return success;
index d235078..3561cc1 100644 (file)
@@ -85,7 +85,7 @@ bool AgentPolicyLogParser::saveToDatabase(DB_HANDLE hdb)
 
        // Clear modifications flag and unlock object
        if (success)
-               m_isModified = false;
+               m_modified = 0;
    unlockProperties();
 
    return success;
index f5bcca2..703e214 100644 (file)
@@ -135,7 +135,7 @@ bool BusinessService::saveToDatabase(DB_HANDLE hdb)
        saveACLToDB(hdb);
 
        lockProperties();
-       m_isModified = false;
+       m_modified = 0;
        unlockProperties();
 
        return ServiceContainer::saveToDatabase(hdb);
index 0982eee..21f4b14 100644 (file)
@@ -67,7 +67,7 @@ bool BusinessServiceRoot::saveToDatabase(DB_HANDLE hdb)
 
    // Unlock object and clear modification flag
    unlockProperties();
-   m_isModified = false;
+   m_modified = 0;
    return true;
 }
 
index aaf5130..0b608ec 100644 (file)
@@ -387,7 +387,7 @@ void Chassis::setBindUnderController(bool doBind)
       m_flags |= CHF_BIND_UNDER_CONTROLLER;
    else
       m_flags &= ~CHF_BIND_UNDER_CONTROLLER;
-   setModified(false);
+   setModified(MODIFY_COMMON_PROPERTIES, false);
    unlockProperties();
    updateControllerBinding();
 }
index 337d513..0308abf 100644 (file)
@@ -228,7 +228,7 @@ bool Cluster::saveToDatabase(DB_HANDLE hdb)
    }
    unlockProperties();
 
-   if (success)
+   if (success && (m_modified & MODIFY_DATA_COLLECTION))
    {
                lockDciAccess(false);
       for(int i = 0; (i < m_dcObjects->size()) && success; i++)
@@ -357,7 +357,7 @@ bool Cluster::saveToDatabase(DB_HANDLE hdb)
 
    // Clear modifications flag
    lockProperties();
-   m_isModified = false;
+   m_modified = 0;
    unlockProperties();
    return success;
 }
@@ -582,8 +582,7 @@ void Cluster::statusPoll(PollerInfo *poller, ClientSession *pSession, UINT32 dwR
       return;
    }
 
-       BOOL bModified = FALSE, bAllDown;
-       BYTE *pbResourceFound;
+   UINT32 modified = 0;
 
    // Create polling list
        ObjectArray<DataCollectionTarget> pollList(m_childList->size(), 16, false);
@@ -605,15 +604,16 @@ void Cluster::statusPoll(PollerInfo *poller, ClientSession *pSession, UINT32 dwR
    m_pollRequestor = pSession;
    sendPollerMsg(dwRqId, _T("CLUSTER STATUS POLL [%s]: Polling member nodes\r\n"), m_name);
        DbgPrintf(6, _T("CLUSTER STATUS POLL [%s]: Polling member nodes"), m_name);
-       for(i = 0, bAllDown = TRUE; i < pollList.size(); i++)
+       bool allDown = true;
+       for(i = 0; i < pollList.size(); i++)
        {
           DataCollectionTarget *object = pollList.get(i);
                object->statusPollPollerEntry(poller, pSession, dwRqId);
                if ((object->getObjectClass() == OBJECT_NODE) && !static_cast<Node*>(object)->isDown())
-                       bAllDown = FALSE;
+                       allDown = false;
        }
 
-       if (bAllDown)
+       if (allDown)
        {
                if (!(m_state & CLSF_DOWN))
                {
@@ -631,10 +631,9 @@ void Cluster::statusPoll(PollerInfo *poller, ClientSession *pSession, UINT32 dwR
        }
 
        // Check for cluster resource movement
-       if (!bAllDown)
+       if (!allDown)
        {
-               pbResourceFound = (BYTE *)malloc(m_dwNumResources);
-               memset(pbResourceFound, 0, m_dwNumResources);
+               BYTE *resourceFound = (BYTE *)calloc(m_dwNumResources, 1);
 
       poller->setStatus(_T("resource poll"));
           sendPollerMsg(dwRqId, _T("CLUSTER STATUS POLL [%s]: Polling resources\r\n"), m_name);
@@ -680,9 +679,9 @@ void Cluster::statusPoll(PollerInfo *poller, ClientSession *pSession, UINT32 dwR
                                                                                                 node->getId(), node->getName());
                                                                }
                                                                m_pResourceList[k].dwCurrOwner = node->getId();
-                                                               bModified = TRUE;
+                                                               modified |= MODIFIED_CLUSTER_RESOURCES;
                                                        }
-                                                       pbResourceFound[k] = 1;
+                                                       resourceFound[k] = 1;
                                                }
                                        }
                                }
@@ -701,7 +700,7 @@ void Cluster::statusPoll(PollerInfo *poller, ClientSession *pSession, UINT32 dwR
                lockProperties();
                for(i = 0; i < (int)m_dwNumResources; i++)
                {
-                       if ((!pbResourceFound[i]) && (m_pResourceList[i].dwCurrOwner != 0))
+                       if ((!resourceFound[i]) && (m_pResourceList[i].dwCurrOwner != 0))
                        {
                                NetObj *pObject = FindObjectById(m_pResourceList[i].dwCurrOwner);
                                PostEvent(EVENT_CLUSTER_RESOURCE_DOWN, m_id, "dsds",
@@ -709,14 +708,13 @@ void Cluster::statusPoll(PollerInfo *poller, ClientSession *pSession, UINT32 dwR
                                                         m_pResourceList[i].dwCurrOwner,
                                                         (pObject != NULL) ? pObject->getName() : _T("<unknown>"));
                                m_pResourceList[i].dwCurrOwner = 0;
-                               bModified = TRUE;
+            modified |= MODIFIED_CLUSTER_RESOURCES;
                        }
                }
                unlockProperties();
-               free(pbResourceFound);
+               free(resourceFound);
        }
 
-
    // Execute hook script
    poller->setStatus(_T("hook"));
    executeHookScript(_T("StatusPoll"));
@@ -731,8 +729,8 @@ void Cluster::statusPoll(PollerInfo *poller, ClientSession *pSession, UINT32 dwR
        }
 
        lockProperties();
-       if (bModified)
-               setModified();
+       if (modified != 0)
+               setModified(modified);
        m_lastStatusPoll = time(NULL);
        m_runtimeFlags &= ~DCDF_QUEUED_FOR_STATUS_POLL;
        unlockProperties();
index aff4328..f024903 100644 (file)
@@ -166,60 +166,63 @@ bool ConditionObject::saveToDatabase(DB_HANDLE hdb)
 
    saveCommonProperties(hdb);
 
-   pszEscScript = EncodeSQLString(CHECK_NULL_EX(m_scriptSource));
-       size_t qlen = _tcslen(pszEscScript) + 1024;
-   pszQuery = (TCHAR *)malloc(sizeof(TCHAR) * qlen);
-
-   // Check for object's existence in database
-   _sntprintf(pszQuery, qlen, _T("SELECT id FROM conditions WHERE id=%d"), m_id);
-   hResult = DBSelect(hdb, pszQuery);
-   if (hResult != NULL)
+   if (m_modified & MODIFY_OTHER)
    {
-      if (DBGetNumRows(hResult) > 0)
-         bNewObject = FALSE;
-      DBFreeResult(hResult);
-   }
+      pszEscScript = EncodeSQLString(CHECK_NULL_EX(m_scriptSource));
+      size_t qlen = _tcslen(pszEscScript) + 1024;
+      pszQuery = (TCHAR *)malloc(sizeof(TCHAR) * qlen);
+
+      // Check for object's existence in database
+      _sntprintf(pszQuery, qlen, _T("SELECT id FROM conditions WHERE id=%d"), m_id);
+      hResult = DBSelect(hdb, pszQuery);
+      if (hResult != NULL)
+      {
+         if (DBGetNumRows(hResult) > 0)
+            bNewObject = FALSE;
+         DBFreeResult(hResult);
+      }
 
-   // Form and execute INSERT or UPDATE query
-   if (bNewObject)
-   {
-      _sntprintf(pszQuery, qlen,
-                                        _T("INSERT INTO conditions (id,activation_event,")
-                          _T("deactivation_event,source_object,active_status,")
-                          _T("inactive_status,script) VALUES (%d,%d,%d,%d,%d,%d,'%s')"),
-                m_id, m_activationEventCode, m_deactivationEventCode,
-                m_sourceObject, m_activeStatus, m_inactiveStatus, pszEscScript);
-   }
-   else
-   {
-      _sntprintf(pszQuery, qlen,
-                                        _T("UPDATE conditions SET activation_event=%d,")
-                          _T("deactivation_event=%d,source_object=%d,active_status=%d,")
-                          _T("inactive_status=%d,script='%s' WHERE id=%d"),
-                m_activationEventCode, m_deactivationEventCode, m_sourceObject,
-                m_activeStatus, m_inactiveStatus, pszEscScript, m_id);
-   }
-   free(pszEscScript);
-   DBQuery(hdb, pszQuery);
+      // Form and execute INSERT or UPDATE query
+      if (bNewObject)
+      {
+         _sntprintf(pszQuery, qlen,
+                             _T("INSERT INTO conditions (id,activation_event,")
+                             _T("deactivation_event,source_object,active_status,")
+                             _T("inactive_status,script) VALUES (%d,%d,%d,%d,%d,%d,'%s')"),
+                   m_id, m_activationEventCode, m_deactivationEventCode,
+                   m_sourceObject, m_activeStatus, m_inactiveStatus, pszEscScript);
+      }
+      else
+      {
+         _sntprintf(pszQuery, qlen,
+                             _T("UPDATE conditions SET activation_event=%d,")
+                             _T("deactivation_event=%d,source_object=%d,active_status=%d,")
+                             _T("inactive_status=%d,script='%s' WHERE id=%d"),
+                   m_activationEventCode, m_deactivationEventCode, m_sourceObject,
+                   m_activeStatus, m_inactiveStatus, pszEscScript, m_id);
+      }
+      free(pszEscScript);
+      DBQuery(hdb, pszQuery);
 
-   // Save DCI mapping
-   _sntprintf(pszQuery, qlen, _T("DELETE FROM cond_dci_map WHERE condition_id=%d"), m_id);
-   DBQuery(hdb, pszQuery);
-   for(i = 0; i < m_dciCount; i++)
-   {
-      _sntprintf(pszQuery, qlen, _T("INSERT INTO cond_dci_map (condition_id,sequence_number,dci_id,node_id,")
-                                 _T("dci_func,num_polls) VALUES (%d,%d,%d,%d,%d,%d)"),
-                m_id, i, m_dciList[i].id, m_dciList[i].nodeId,
-                m_dciList[i].function, m_dciList[i].polls);
+      // Save DCI mapping
+      _sntprintf(pszQuery, qlen, _T("DELETE FROM cond_dci_map WHERE condition_id=%d"), m_id);
       DBQuery(hdb, pszQuery);
+      for(i = 0; i < m_dciCount; i++)
+      {
+         _sntprintf(pszQuery, qlen, _T("INSERT INTO cond_dci_map (condition_id,sequence_number,dci_id,node_id,")
+                                    _T("dci_func,num_polls) VALUES (%d,%d,%d,%d,%d,%d)"),
+                   m_id, i, m_dciList[i].id, m_dciList[i].nodeId,
+                   m_dciList[i].function, m_dciList[i].polls);
+         DBQuery(hdb, pszQuery);
+      }
+      free(pszQuery);
    }
-   free(pszQuery);
 
    // Save access list
    saveACLToDB(hdb);
 
    // Unlock object and clear modification flag
-   m_isModified = false;
+   m_modified = 0;
    unlockProperties();
    return true;
 }
@@ -447,7 +450,7 @@ void ConditionObject::check()
             lockProperties();
             m_status = m_inactiveStatus;
             m_isActive = FALSE;
-            setModified();
+            setModified(MODIFY_RUNTIME);
             unlockProperties();
 
             PostEvent(m_deactivationEventCode,
@@ -465,7 +468,7 @@ void ConditionObject::check()
             if (m_status != m_inactiveStatus)
             {
                m_status = m_inactiveStatus;
-               setModified();
+               setModified(MODIFY_RUNTIME);
             }
             unlockProperties();
          }
@@ -478,7 +481,7 @@ void ConditionObject::check()
             lockProperties();
             m_status = m_activeStatus;
             m_isActive = TRUE;
-            setModified();
+            setModified(MODIFY_RUNTIME);
             unlockProperties();
 
             PostEvent(m_activationEventCode,
@@ -496,7 +499,7 @@ void ConditionObject::check()
             if (m_status != m_activeStatus)
             {
                m_status = m_activeStatus;
-               setModified();
+               setModified(MODIFY_RUNTIME);
             }
             unlockProperties();
          }
@@ -511,7 +514,7 @@ void ConditionObject::check()
       if (m_status != STATUS_UNKNOWN)
       {
          m_status = STATUS_UNKNOWN;
-         setModified();
+         setModified(MODIFY_RUNTIME);
       }
       unlockProperties();
    }
index 8af9ff9..6ae65a7 100644 (file)
@@ -135,30 +135,33 @@ bool Container::saveToDatabase(DB_HANDLE hdb)
    // Lock object's access
    lockProperties();
 
-   saveCommonProperties(hdb);
+   bool success = saveCommonProperties(hdb);
 
-       DB_STATEMENT hStmt;
-   if (IsDatabaseRecordExist(hdb, _T("object_containers"), _T("id"), m_id))
-       {
-               hStmt = DBPrepare(hdb, _T("UPDATE object_containers SET object_class=?,auto_bind_filter=? WHERE id=?"));
-       }
-   else
-       {
-               hStmt = DBPrepare(hdb, _T("INSERT INTO object_containers (object_class,auto_bind_filter,id) VALUES (?,?,?)"));
-       }
-       if (hStmt == NULL)
-       {
-               unlockProperties();
-               return FALSE;
-       }
+   if (success && (m_modified & MODIFY_OTHER))
+   {
+      DB_STATEMENT hStmt;
+      if (IsDatabaseRecordExist(hdb, _T("object_containers"), _T("id"), m_id))
+      {
+         hStmt = DBPrepare(hdb, _T("UPDATE object_containers SET object_class=?,auto_bind_filter=? WHERE id=?"));
+      }
+      else
+      {
+         hStmt = DBPrepare(hdb, _T("INSERT INTO object_containers (object_class,auto_bind_filter,id) VALUES (?,?,?)"));
+      }
+      if (hStmt == NULL)
+      {
+         unlockProperties();
+         return false;
+      }
 
-       DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, (LONG)getObjectClass());
-       DBBind(hStmt, 2, DB_SQLTYPE_TEXT, m_bindFilterSource, DB_BIND_STATIC);
-       DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, m_id);
-       bool success = DBExecute(hStmt);
-       DBFreeStatement(hStmt);
+      DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, (LONG)getObjectClass());
+      DBBind(hStmt, 2, DB_SQLTYPE_TEXT, m_bindFilterSource, DB_BIND_STATIC);
+      DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, m_id);
+      success = DBExecute(hStmt);
+      DBFreeStatement(hStmt);
+   }
 
-       if (success)
+       if (success && (m_modified & MODIFY_RELATIONS))
        {
                TCHAR query[256];
 
@@ -172,14 +175,14 @@ bool Container::saveToDatabase(DB_HANDLE hdb)
                        DBQuery(hdb, query);
                }
                unlockChildList();
-
-               // Save access list
-               saveACLToDB(hdb);
-
-               // Clear modifications flag and unlock object
-               m_isModified = false;
        }
 
+   // Save access list
+       if (success)
+               success = saveACLToDB(hdb);
+
+   // Clear modifications flag and unlock object
+   m_modified = 0;
    unlockProperties();
    return success;
 }
@@ -234,7 +237,7 @@ void Container::calculateCompoundStatus(BOOL bForcedRecalc)
    {
                lockProperties();
                m_status = STATUS_NORMAL;
-               setModified();
+               setModified(MODIFY_RUNTIME);
                unlockProperties();
        }
 }
@@ -275,7 +278,7 @@ void Container::setAutoBindFilterInternal(const TCHAR *script)
 {
        if (script != NULL)
        {
-               safe_free(m_bindFilterSource);
+               free(m_bindFilterSource);
                delete m_bindFilter;
                m_bindFilterSource = _tcsdup(script);
                if (m_bindFilterSource != NULL)
@@ -301,7 +304,7 @@ void Container::setAutoBindFilterInternal(const TCHAR *script)
                delete_and_null(m_bindFilter);
                safe_free_and_null(m_bindFilterSource);
        }
-       setModified();
+       setModified(MODIFY_OTHER);
 }
 
 /**
@@ -321,7 +324,7 @@ void Container::setAutoBindMode(bool doBind, bool doUnbind)
    else
       m_flags &= ~CF_AUTO_UNBIND;
 
-   setModified();
+   setModified(MODIFY_COMMON_PROPERTIES);
    unlockProperties();
 }
 
index 102aa6a..b3a4a32 100644 (file)
@@ -354,7 +354,7 @@ bool DataCollectionTarget::applyTemplateItem(UINT32 dwTemplateId, DCObject *dcOb
        if (bResult)
        {
                lockProperties();
-               m_isModified = true;
+               setModified(MODIFY_DATA_COLLECTION, false);
                unlockProperties();
        }
    return bResult;
@@ -1132,7 +1132,7 @@ void DataCollectionTarget::enterMaintenanceMode()
    lockProperties();
    m_maintenanceMode = true;
    m_maintenanceEventId = eventId;
-   setModified();
+   setModified(MODIFY_COMMON_PROPERTIES);
    unlockProperties();
 }
 
@@ -1146,7 +1146,7 @@ void DataCollectionTarget::leaveMaintenanceMode()
    lockProperties();
    m_maintenanceMode = false;
    m_maintenanceEventId = 0;
-   setModified();
+   setModified(MODIFY_COMMON_PROPERTIES);
    unlockProperties();
 }
 
index 4b0a970..a918b48 100644 (file)
@@ -1,6 +1,6 @@
 /* 
 ** NetXMS - Network Management System
-** Copyright (C) 2003-2013 Victor Kirhenshtein
+** Copyright (C) 2003-2017 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -45,13 +45,14 @@ bool Network::saveToDatabase(DB_HANDLE hdb)
 {
    lockProperties();
 
-   saveCommonProperties(hdb);
-   saveACLToDB(hdb);
+   bool success = saveCommonProperties(hdb);
+   if (success)
+      success = saveACLToDB(hdb);
 
    // Unlock object and clear modification flag
-   m_isModified = false;
+   m_modified = 0;
    unlockProperties();
-   return true;
+   return success;
 }
 
 /**
index e6f5b92..474d0d7 100644 (file)
@@ -335,109 +335,117 @@ bool Interface::saveToDatabase(DB_HANDLE hdb)
        }
 
    // Determine owning node's ID
-   Node *pNode = getParentNode();
-   if (pNode != NULL)
-      dwNodeId = pNode->getId();
-   else
-      dwNodeId = 0;
-
-   // Form and execute INSERT or UPDATE query
-       DB_STATEMENT hStmt;
-   if (IsDatabaseRecordExist(hdb, _T("interfaces"), _T("id"), m_id))
-       {
-               hStmt = DBPrepare(hdb,
-                       _T("UPDATE interfaces SET node_id=?,if_type=?,if_index=?,mac_addr=?,")
-                       _T("required_polls=?,bridge_port=?,phy_slot=?,phy_port=?,")
-                       _T("peer_node_id=?,peer_if_id=?,description=?,admin_state=?,")
-                       _T("oper_state=?,dot1x_pae_state=?,dot1x_backend_state=?,")
-         _T("peer_proto=?,alias=?,mtu=?,speed=?,parent_iface=?,")
-         _T("iftable_suffix=? WHERE id=?"));
-       }
-   else
-       {
-               hStmt = DBPrepare(hdb,
-                       _T("INSERT INTO interfaces (node_id,if_type,if_index,mac_addr,")
-                       _T("required_polls,bridge_port,phy_slot,phy_port,peer_node_id,peer_if_id,description,")
-         _T("admin_state,oper_state,dot1x_pae_state,dot1x_backend_state,peer_proto,alias,mtu,speed,")
-         _T("parent_iface,iftable_suffix,id) ")
-                       _T("VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
-       }
-       if (hStmt == NULL)
-       {
-               unlockProperties();
-               return FALSE;
-       }
-
-       DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, dwNodeId);
-       DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_type);
-       DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, m_index);
-       DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, BinToStr(m_macAddr, MAC_ADDR_LENGTH, szMacStr), DB_BIND_STATIC);
-       DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, (LONG)m_requiredPollCount);
-       DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, m_bridgePortNumber);
-       DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, m_slotNumber);
-       DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_portNumber);
-       DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, m_peerNodeId);
-       DBBind(hStmt, 10, DB_SQLTYPE_INTEGER, m_peerInterfaceId);
-       DBBind(hStmt, 11, DB_SQLTYPE_VARCHAR, m_description, DB_BIND_STATIC);
-       DBBind(hStmt, 12, DB_SQLTYPE_INTEGER, (UINT32)m_adminState);
-       DBBind(hStmt, 13, DB_SQLTYPE_INTEGER, (UINT32)m_operState);
-       DBBind(hStmt, 14, DB_SQLTYPE_INTEGER, (UINT32)m_dot1xPaeAuthState);
-       DBBind(hStmt, 15, DB_SQLTYPE_INTEGER, (UINT32)m_dot1xBackendAuthState);
-       DBBind(hStmt, 16, DB_SQLTYPE_INTEGER, (INT32)m_peerDiscoveryProtocol);
-       DBBind(hStmt, 17, DB_SQLTYPE_VARCHAR, m_alias, DB_BIND_STATIC);
-       DBBind(hStmt, 18, DB_SQLTYPE_INTEGER, m_mtu);
-       DBBind(hStmt, 19, DB_SQLTYPE_BIGINT, m_speed);
-   DBBind(hStmt, 20, DB_SQLTYPE_INTEGER, m_parentInterfaceId);
-   if (m_ifTableSuffixLen > 0)
+   bool success;
+   if (m_modified & MODIFY_INTERFACE_PROPERTIES)
    {
-      TCHAR buffer[128];
-      DBBind(hStmt, 21, DB_SQLTYPE_VARCHAR, SNMPConvertOIDToText(m_ifTableSuffixLen, m_ifTableSuffix, buffer, 128), DB_BIND_TRANSIENT);
-   }
-   else
-   {
-          DBBind(hStmt, 21, DB_SQLTYPE_VARCHAR, NULL, DB_BIND_STATIC);
-   }
-       DBBind(hStmt, 22, DB_SQLTYPE_INTEGER, m_id);
-
-       bool success = DBExecute(hStmt);
-       DBFreeStatement(hStmt);
+      Node *pNode = getParentNode();
+      if (pNode != NULL)
+         dwNodeId = pNode->getId();
+      else
+         dwNodeId = 0;
 
-   // Save IP addresses
-   if (success)
-   {
-      success = false;
+      // Form and execute INSERT or UPDATE query
+      DB_STATEMENT hStmt;
+      if (IsDatabaseRecordExist(hdb, _T("interfaces"), _T("id"), m_id))
+      {
+         hStmt = DBPrepare(hdb,
+            _T("UPDATE interfaces SET node_id=?,if_type=?,if_index=?,mac_addr=?,")
+            _T("required_polls=?,bridge_port=?,phy_slot=?,phy_port=?,")
+            _T("peer_node_id=?,peer_if_id=?,description=?,admin_state=?,")
+            _T("oper_state=?,dot1x_pae_state=?,dot1x_backend_state=?,")
+            _T("peer_proto=?,alias=?,mtu=?,speed=?,parent_iface=?,")
+            _T("iftable_suffix=? WHERE id=?"));
+      }
+      else
+      {
+         hStmt = DBPrepare(hdb,
+            _T("INSERT INTO interfaces (node_id,if_type,if_index,mac_addr,")
+            _T("required_polls,bridge_port,phy_slot,phy_port,peer_node_id,peer_if_id,description,")
+            _T("admin_state,oper_state,dot1x_pae_state,dot1x_backend_state,peer_proto,alias,mtu,speed,")
+            _T("parent_iface,iftable_suffix,id) ")
+            _T("VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+      }
+      if (hStmt == NULL)
+      {
+         unlockProperties();
+         return FALSE;
+      }
 
-               hStmt = DBPrepare(hdb, _T("DELETE FROM interface_address_list WHERE iface_id = ?"));
-      if (hStmt != NULL)
+      DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, dwNodeId);
+      DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_type);
+      DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, m_index);
+      DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, BinToStr(m_macAddr, MAC_ADDR_LENGTH, szMacStr), DB_BIND_STATIC);
+      DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, (LONG)m_requiredPollCount);
+      DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, m_bridgePortNumber);
+      DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, m_slotNumber);
+      DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_portNumber);
+      DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, m_peerNodeId);
+      DBBind(hStmt, 10, DB_SQLTYPE_INTEGER, m_peerInterfaceId);
+      DBBind(hStmt, 11, DB_SQLTYPE_VARCHAR, m_description, DB_BIND_STATIC);
+      DBBind(hStmt, 12, DB_SQLTYPE_INTEGER, (UINT32)m_adminState);
+      DBBind(hStmt, 13, DB_SQLTYPE_INTEGER, (UINT32)m_operState);
+      DBBind(hStmt, 14, DB_SQLTYPE_INTEGER, (UINT32)m_dot1xPaeAuthState);
+      DBBind(hStmt, 15, DB_SQLTYPE_INTEGER, (UINT32)m_dot1xBackendAuthState);
+      DBBind(hStmt, 16, DB_SQLTYPE_INTEGER, (INT32)m_peerDiscoveryProtocol);
+      DBBind(hStmt, 17, DB_SQLTYPE_VARCHAR, m_alias, DB_BIND_STATIC);
+      DBBind(hStmt, 18, DB_SQLTYPE_INTEGER, m_mtu);
+      DBBind(hStmt, 19, DB_SQLTYPE_BIGINT, m_speed);
+      DBBind(hStmt, 20, DB_SQLTYPE_INTEGER, m_parentInterfaceId);
+      if (m_ifTableSuffixLen > 0)
       {
-         DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
-         success = DBExecute(hStmt);
-         DBFreeStatement(hStmt);
+         TCHAR buffer[128];
+         DBBind(hStmt, 21, DB_SQLTYPE_VARCHAR, SNMPConvertOIDToText(m_ifTableSuffixLen, m_ifTableSuffix, buffer, 128), DB_BIND_TRANSIENT);
       }
-   }
+      else
+      {
+         DBBind(hStmt, 21, DB_SQLTYPE_VARCHAR, NULL, DB_BIND_STATIC);
+      }
+      DBBind(hStmt, 22, DB_SQLTYPE_INTEGER, m_id);
 
-   if (success && (m_ipAddressList.size() > 0))
-   {
-               hStmt = DBPrepare(hdb, _T("INSERT INTO interface_address_list (iface_id,ip_addr,ip_netmask) VALUES (?,?,?)"));
-      if (hStmt != NULL)
+      success = DBExecute(hStmt);
+      DBFreeStatement(hStmt);
+
+      // Save IP addresses
+      if (success)
       {
-         DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
-         const ObjectArray<InetAddress> *list = m_ipAddressList.getList();
-         for(int i = 0; (i < list->size()) && success; i++)
+         success = false;
+
+         hStmt = DBPrepare(hdb, _T("DELETE FROM interface_address_list WHERE iface_id = ?"));
+         if (hStmt != NULL)
          {
-            InetAddress *a = list->get(i);
-            TCHAR buffer[64];
-            DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, a->toString(buffer), DB_BIND_STATIC);
-            DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, a->getMaskBits());
+            DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
             success = DBExecute(hStmt);
+            DBFreeStatement(hStmt);
          }
-         DBFreeStatement(hStmt);
       }
-      else
+
+      if (success && (m_ipAddressList.size() > 0))
       {
-         success = false;
+         hStmt = DBPrepare(hdb, _T("INSERT INTO interface_address_list (iface_id,ip_addr,ip_netmask) VALUES (?,?,?)"));
+         if (hStmt != NULL)
+         {
+            DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
+            const ObjectArray<InetAddress> *list = m_ipAddressList.getList();
+            for(int i = 0; (i < list->size()) && success; i++)
+            {
+               InetAddress *a = list->get(i);
+               TCHAR buffer[64];
+               DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, a->toString(buffer), DB_BIND_STATIC);
+               DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, a->getMaskBits());
+               success = DBExecute(hStmt);
+            }
+            DBFreeStatement(hStmt);
+         }
+         else
+         {
+            success = false;
+         }
       }
    }
+   else
+   {
+      success = true;
+   }
 
    // Save access list
        if (success)
@@ -445,7 +453,7 @@ bool Interface::saveToDatabase(DB_HANDLE hdb)
 
    // Clear modifications flag and unlock object
        if (success)
-               m_isModified = false;
+               m_modified = 0;
    unlockProperties();
 
    return success;
@@ -699,7 +707,7 @@ void Interface::statusPoll(ClientSession *session, UINT32 rqId, Queue *eventQueu
        {
                m_adminState = (WORD)adminState;
                m_operState = (WORD)operState;
-               setModified();
+               setModified(MODIFY_INTERFACE_PROPERTIES);
        }
        unlockProperties();
 
@@ -1000,7 +1008,7 @@ void Interface::paeStatusPoll(UINT32 rqId, SNMP_Transport *pTransport, Node *nod
                lockProperties();
                m_dot1xPaeAuthState = (WORD)paeState;
                m_dot1xBackendAuthState = (WORD)backendState;
-               setModified();
+               setModified(MODIFY_INTERFACE_PROPERTIES);
                unlockProperties();
        }
 }
@@ -1073,7 +1081,7 @@ void Interface::setExpectedStateInternal(int state)
        {
       m_flags &= ~IF_EXPECTED_STATE_MASK;
       m_flags |= (UINT32)state << 28;
-      setModified();
+      setModified(MODIFY_COMMON_PROPERTIES);
       if (state != IF_EXPECTED_STATE_AUTO)
          PostEvent(eventCode[state], getParentNodeId(), "ds", m_index, m_name);
        }
@@ -1089,7 +1097,7 @@ void Interface::setExcludeFromTopology(bool excluded)
       m_flags |= IF_EXCLUDE_FROM_TOPOLOGY;
    else
       m_flags &= ~IF_EXCLUDE_FROM_TOPOLOGY;
-   setModified();
+   setModified(MODIFY_COMMON_PROPERTIES);
    unlockProperties();
 }
 
@@ -1157,7 +1165,7 @@ void Interface::updateZoneUIN()
 
                lockProperties();
                m_zoneUIN = node->getZoneUIN();
-               setModified();
+               setModified(MODIFY_INTERFACE_PROPERTIES);
                unlockProperties();
 
                // Register in new zone
@@ -1177,7 +1185,7 @@ void Interface::onObjectDelete(UINT32 dwObjectId)
                lockProperties();
                m_peerNodeId = 0;
                m_peerInterfaceId = 0;
-               setModified();
+               setModified(MODIFY_INTERFACE_PROPERTIES);
                unlockProperties();
        }
        NetObj::onObjectDelete(dwObjectId);
@@ -1194,7 +1202,7 @@ void Interface::setPeer(Node *node, Interface *iface, LinkLayerProtocol protocol
       {
          // set peer information as confirmed
          m_flags &= ~IF_PEER_REFLECTION;
-         setModified();
+         setModified(MODIFY_COMMON_PROPERTIES);
       }
       return;
    }
@@ -1206,7 +1214,7 @@ void Interface::setPeer(Node *node, Interface *iface, LinkLayerProtocol protocol
       m_flags |= IF_PEER_REFLECTION;
    else
       m_flags &= ~IF_PEER_REFLECTION;
-   setModified();
+   setModified(MODIFY_INTERFACE_PROPERTIES | MODIFY_COMMON_PROPERTIES);
    if (!m_isSystem)
    {
       static const TCHAR *names[] = { _T("localIfId"), _T("localIfIndex"), _T("localIfName"),
@@ -1231,7 +1239,7 @@ void Interface::setMacAddr(const BYTE *macAddr, bool updateMacDB)
    memcpy(m_macAddr, macAddr, MAC_ADDR_LENGTH);
    if (updateMacDB)
       MacDbAddInterface(this);
-   setModified();
+   setModified(MODIFY_INTERFACE_PROPERTIES);
    unlockProperties();
 }
 
@@ -1246,7 +1254,7 @@ void Interface::setIpAddress(const InetAddress& addr)
       UpdateInterfaceIndex(m_ipAddressList.get(0), addr, this);
       m_ipAddressList.clear();
       m_ipAddressList.add(addr);
-      setModified();
+      setModified(MODIFY_INTERFACE_PROPERTIES);
    }
    unlockProperties();
 }
@@ -1267,7 +1275,7 @@ void Interface::addIpAddress(const InetAddress& addr)
 {
    lockProperties();
    m_ipAddressList.add(addr);
-   setModified();
+   setModified(MODIFY_INTERFACE_PROPERTIES);
    unlockProperties();
    if (!isExcludedFromTopology())
    {
@@ -1297,7 +1305,7 @@ void Interface::deleteIpAddress(InetAddress addr)
 {
    lockProperties();
    m_ipAddressList.remove(addr);
-   setModified();
+   setModified(MODIFY_INTERFACE_PROPERTIES);
    unlockProperties();
    if (!isExcludedFromTopology())
    {
@@ -1327,7 +1335,7 @@ void Interface::setNetMask(const InetAddress& addr)
 {
    lockProperties();
    m_ipAddressList.replace(addr);
-   setModified();
+   setModified(MODIFY_INTERFACE_PROPERTIES);
    unlockProperties();
 }
 
index 28031af..aa1e735 100644 (file)
@@ -114,37 +114,39 @@ bool MobileDevice::saveToDatabase(DB_HANDLE hdb)
    // Lock object's access
    lockProperties();
 
-   saveCommonProperties(hdb);
+   bool success = saveCommonProperties(hdb);
 
-   bool bResult;
-       DB_STATEMENT hStmt;
-   if (IsDatabaseRecordExist(hdb, _T("mobile_devices"), _T("id"), m_id))
-               hStmt = DBPrepare(hdb, _T("UPDATE mobile_devices SET device_id=?,vendor=?,model=?,serial_number=?,os_name=?,os_version=?,user_id=?,battery_level=? WHERE id=?"));
-       else
-               hStmt = DBPrepare(hdb, _T("INSERT INTO mobile_devices (device_id,vendor,model,serial_number,os_name,os_version,user_id,battery_level,id) VALUES (?,?,?,?,?,?,?,?,?)"));
-       if (hStmt != NULL)
-       {
-               DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_deviceId), DB_BIND_STATIC);
-               DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_vendor), DB_BIND_STATIC);
-               DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_model), DB_BIND_STATIC);
-               DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_serialNumber), DB_BIND_STATIC);
-               DBBind(hStmt, 5, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_osName), DB_BIND_STATIC);
-               DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_osVersion), DB_BIND_STATIC);
-               DBBind(hStmt, 7, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_userId), DB_BIND_STATIC);
-               DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_batteryLevel);
-               DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, m_id);
-
-               bResult = DBExecute(hStmt);
-
-               DBFreeStatement(hStmt);
-       }
-       else
-       {
-               bResult = false;
-       }
+   if (success && (m_modified & MODIFY_OTHER))
+   {
+      DB_STATEMENT hStmt;
+      if (IsDatabaseRecordExist(hdb, _T("mobile_devices"), _T("id"), m_id))
+         hStmt = DBPrepare(hdb, _T("UPDATE mobile_devices SET device_id=?,vendor=?,model=?,serial_number=?,os_name=?,os_version=?,user_id=?,battery_level=? WHERE id=?"));
+      else
+         hStmt = DBPrepare(hdb, _T("INSERT INTO mobile_devices (device_id,vendor,model,serial_number,os_name,os_version,user_id,battery_level,id) VALUES (?,?,?,?,?,?,?,?,?)"));
+      if (hStmt != NULL)
+      {
+         DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_deviceId), DB_BIND_STATIC);
+         DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_vendor), DB_BIND_STATIC);
+         DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_model), DB_BIND_STATIC);
+         DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_serialNumber), DB_BIND_STATIC);
+         DBBind(hStmt, 5, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_osName), DB_BIND_STATIC);
+         DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_osVersion), DB_BIND_STATIC);
+         DBBind(hStmt, 7, DB_SQLTYPE_VARCHAR, CHECK_NULL_EX(m_userId), DB_BIND_STATIC);
+         DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_batteryLevel);
+         DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, m_id);
+
+         success = DBExecute(hStmt);
+
+         DBFreeStatement(hStmt);
+      }
+      else
+      {
+         success = false;
+      }
+   }
 
    // Save data collection items
-   if (bResult)
+   if (success && (m_modified & MODIFY_DATA_COLLECTION))
    {
                lockDciAccess(false);
       for(int i = 0; i < m_dcObjects->size(); i++)
@@ -153,14 +155,15 @@ bool MobileDevice::saveToDatabase(DB_HANDLE hdb)
    }
 
    // Save access list
-   saveACLToDB(hdb);
+   if (success)
+      success = saveACLToDB(hdb);
 
    // Clear modifications flag and unlock object
-       if (bResult)
-               m_isModified = false;
+       if (success)
+               m_modified = 0;
    unlockProperties();
 
-   return bResult;
+   return success;
 }
 
 /**
@@ -209,25 +212,25 @@ void MobileDevice::updateSystemInfo(NXCPMessage *msg)
 
        m_lastReportTime = time(NULL);
 
-       safe_free(m_vendor);
+       free(m_vendor);
        m_vendor = msg->getFieldAsString(VID_VENDOR);
 
-       safe_free(m_model);
+       free(m_model);
        m_model = msg->getFieldAsString(VID_MODEL);
 
-       safe_free(m_serialNumber);
+       free(m_serialNumber);
        m_serialNumber = msg->getFieldAsString(VID_SERIAL_NUMBER);
 
-       safe_free(m_osName);
+       free(m_osName);
        m_osName = msg->getFieldAsString(VID_OS_NAME);
 
-       safe_free(m_osVersion);
+       free(m_osVersion);
        m_osVersion = msg->getFieldAsString(VID_OS_VERSION);
 
-       safe_free(m_userId);
+       free(m_userId);
        m_userId = msg->getFieldAsString(VID_USER_NAME);
 
-       setModified();
+       setModified(MODIFY_OTHER);
        unlockProperties();
 }
 
@@ -262,7 +265,7 @@ void MobileDevice::updateStatus(NXCPMessage *msg)
                  m_name, (int)m_id, m_batteryLevel, m_ipAddress.toString(temp),
                                 m_geoLocation.getLatitudeAsString(), m_geoLocation.getLongitudeAsString());
 
-       setModified();
+       setModified(MODIFY_OTHER);
        unlockProperties();
 }
 
@@ -332,7 +335,7 @@ void MobileDevice::calculateCompoundStatus(BOOL bForcedRecalc)
    {
       lockProperties();
       m_status = STATUS_NORMAL;
-      setModified();
+      setModified(MODIFY_RUNTIME);
       unlockProperties();
    }
 }
index 895d04c..164091e 100644 (file)
@@ -209,7 +209,7 @@ void NetworkMap::calculateCompoundStatus(BOOL bForcedRecalc)
                m_parentList->get(i)->calculateCompoundStatus();
             unlockParentList();
             lockProperties();
-            setModified();
+            setModified(MODIFY_RUNTIME);
             unlockProperties();
          }
       }
@@ -224,7 +224,7 @@ void NetworkMap::calculateCompoundStatus(BOOL bForcedRecalc)
             m_parentList->get(i)->calculateCompoundStatus();
          unlockParentList();
          lockProperties();
-         setModified();
+         setModified(MODIFY_RUNTIME);
          unlockProperties();
       }
    }
@@ -238,7 +238,7 @@ bool NetworkMap::saveToDatabase(DB_HANDLE hdb)
        lockProperties();
 
        bool success = saveCommonProperties(hdb);
-   if (success)
+   if (success && (m_modified & MODIFY_OTHER))
    {
       DB_STATEMENT hStmt;
       if (IsDatabaseRecordExist(hdb, _T("network_maps"), _T("id"), m_id))
@@ -278,95 +278,99 @@ bool NetworkMap::saveToDatabase(DB_HANDLE hdb)
           success = saveACLToDB(hdb);
 
    // Save elements
-   if (success)
+   if (success && (m_modified & MODIFY_MAP_CONTENT))
+   {
       success = executeQueryOnObject(hdb, _T("DELETE FROM network_map_elements WHERE map_id=?"));
 
-   if (success && (m_elements->size() > 0))
-   {
-      DB_STATEMENT hStmt = DBPrepare(hdb, _T("INSERT INTO network_map_elements (map_id,element_id,element_type,element_data,flags) VALUES (?,?,?,?,?)"));
-      if (hStmt != NULL)
+      if (success && (m_elements->size() > 0))
       {
-         DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
-         for(int i = 0; success && (i < m_elements->size()); i++)
+         DB_STATEMENT hStmt = DBPrepare(hdb, _T("INSERT INTO network_map_elements (map_id,element_id,element_type,element_data,flags) VALUES (?,?,?,?,?)"));
+         if (hStmt != NULL)
          {
-            NetworkMapElement *e = m_elements->get(i);
-            Config *config = new Config();
-            config->setTopLevelTag(_T("element"));
-            e->updateConfig(config);
-
-            DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, e->getId());
-            DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, e->getType());
-            DBBind(hStmt, 4, DB_SQLTYPE_TEXT, config->createXml(), DB_BIND_TRANSIENT);
-            DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, e->getFlags());
-            
-            success = DBExecute(hStmt);
-            delete config;
+            DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
+            for(int i = 0; success && (i < m_elements->size()); i++)
+            {
+               NetworkMapElement *e = m_elements->get(i);
+               Config *config = new Config();
+               config->setTopLevelTag(_T("element"));
+               e->updateConfig(config);
+
+               DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, e->getId());
+               DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, e->getType());
+               DBBind(hStmt, 4, DB_SQLTYPE_TEXT, config->createXml(), DB_BIND_TRANSIENT);
+               DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, e->getFlags());
+
+               success = DBExecute(hStmt);
+               delete config;
+            }
+            DBFreeStatement(hStmt);
+         }
+         else
+         {
+            success = false;
          }
-         DBFreeStatement(hStmt);
-      }
-      else
-      {
-         success = false;
       }
-   }
 
-       // Save links
-   if (success)
-      success = executeQueryOnObject(hdb, _T("DELETE FROM network_map_links WHERE map_id=?"));
+      // Save links
+      if (success)
+         success = executeQueryOnObject(hdb, _T("DELETE FROM network_map_links WHERE map_id=?"));
 
-   if (success && (m_links->size() > 0))
-   {
-          DB_STATEMENT hStmt = DBPrepare(hdb, _T("INSERT INTO network_map_links (map_id,element1,element2,link_type,link_name,connector_name1,connector_name2,element_data,flags) VALUES (?,?,?,?,?,?,?,?,?)"));
-       if (hStmt != NULL)
+      if (success && (m_links->size() > 0))
       {
-         DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
-         for(int i = 0; success && (i < m_links->size()); i++)
+         DB_STATEMENT hStmt = DBPrepare(hdb, _T("INSERT INTO network_map_links (map_id,element1,element2,link_type,link_name,connector_name1,connector_name2,element_data,flags) VALUES (?,?,?,?,?,?,?,?,?)"));
+         if (hStmt != NULL)
          {
-            NetworkMapLink *l = m_links->get(i);
-            DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, l->getElement1());
-            DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, l->getElement2());
-            DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, (LONG)l->getType());
-            DBBind(hStmt, 5, DB_SQLTYPE_VARCHAR, l->getName(), DB_BIND_STATIC);
-            DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, l->getConnector1Name(), DB_BIND_STATIC);
-            DBBind(hStmt, 7, DB_SQLTYPE_VARCHAR, l->getConnector2Name(), DB_BIND_STATIC);
-            DBBind(hStmt, 8, DB_SQLTYPE_VARCHAR, l->getConfig(), DB_BIND_STATIC);
-            DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, l->getFlags());
-            success = DBExecute(hStmt);
+            DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
+            for(int i = 0; success && (i < m_links->size()); i++)
+            {
+               NetworkMapLink *l = m_links->get(i);
+               DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, l->getElement1());
+               DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, l->getElement2());
+               DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, (LONG)l->getType());
+               DBBind(hStmt, 5, DB_SQLTYPE_VARCHAR, l->getName(), DB_BIND_STATIC);
+               DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, l->getConnector1Name(), DB_BIND_STATIC);
+               DBBind(hStmt, 7, DB_SQLTYPE_VARCHAR, l->getConnector2Name(), DB_BIND_STATIC);
+               DBBind(hStmt, 8, DB_SQLTYPE_VARCHAR, l->getConfig(), DB_BIND_STATIC);
+               DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, l->getFlags());
+               success = DBExecute(hStmt);
+            }
+            DBFreeStatement(hStmt);
+         }
+         else
+         {
+            success = false;
          }
-         DBFreeStatement(hStmt);
-      }
-      else
-      {
-         success = false;
       }
    }
 
        // Save seed nodes
-   if (success)
+   if (success && (m_modified & MODIFY_OTHER))
+   {
       success = executeQueryOnObject(hdb, _T("DELETE FROM network_map_seed_nodes WHERE map_id=?"));
 
-   if (success && (m_seedObjects->size() > 0))
-   {
-      DB_STATEMENT hStmt = DBPrepare(hdb, _T("INSERT INTO network_map_seed_nodes (map_id,seed_node_id) VALUES (?,?)"));
-      if (hStmt != NULL)
+      if (success && (m_seedObjects->size() > 0))
       {
-         DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
-         for(int i = 0; success && (i < m_seedObjects->size()); i++)
+         DB_STATEMENT hStmt = DBPrepare(hdb, _T("INSERT INTO network_map_seed_nodes (map_id,seed_node_id) VALUES (?,?)"));
+         if (hStmt != NULL)
          {
-            DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_seedObjects->get(i));
-            success = DBExecute(hStmt);
+            DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
+            for(int i = 0; success && (i < m_seedObjects->size()); i++)
+            {
+               DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_seedObjects->get(i));
+               success = DBExecute(hStmt);
+            }
+            DBFreeStatement(hStmt);
+         }
+         else
+         {
+            success = false;
          }
-         DBFreeStatement(hStmt);
-      }
-      else
-      {
-         success = false;
       }
    }
 
-   m_isModified = false;
+   m_modified = 0;
 
-       unlockProperties();
+   unlockProperties();
        return success;
 }
 
@@ -856,7 +860,7 @@ void NetworkMap::updateObjects(NetworkMapObjectList *objects)
    }
 
    if (modified)
-      setModified();
+      setModified(MODIFY_MAP_CONTENT);
 
    unlockProperties();
    nxlog_debug(5, _T("NetworkMap(%s): updateObjects completed"), m_name);
@@ -998,7 +1002,7 @@ void NetworkMap::onObjectDelete(UINT32 dwObjectId)
       }
    }
 
-   setModified();
+   setModified(MODIFY_MAP_CONTENT);
 
    unlockProperties();
 
index 0829d31..97a9178 100644 (file)
@@ -58,7 +58,7 @@ NetObj::NetObj()
    m_status = STATUS_UNKNOWN;
    m_name[0] = 0;
    m_comments = NULL;
-   m_isModified = false;
+   m_modified = 0;
    m_isDeleted = false;
    m_isHidden = false;
        m_isSystem = false;
@@ -175,10 +175,17 @@ static EnumerationCallbackResult SaveModuleRuntimeDataCallback(const TCHAR *key,
  */
 bool NetObj::saveRuntimeData(DB_HANDLE hdb)
 {
-   bool success = true;
+   DB_STATEMENT hStmt = DBPrepare(hdb, _T("UPDATE object_properties SET status=? WHERE object_id=?"));
+   if (hStmt == NULL)
+      return false;
 
-   // Delete module data
-   if (m_moduleData != NULL)
+   DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_status);
+   DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_id);
+   bool success = DBExecute(hStmt);
+   DBFreeStatement(hStmt);
+
+   // Save module data
+   if (success && (m_moduleData != NULL))
    {
       ModuleDataDatabaseCallbackParams data;
       data.id = m_id;
@@ -455,6 +462,9 @@ static EnumerationCallbackResult SaveModuleDataCallback(const TCHAR *key, const
  */
 bool NetObj::saveCommonProperties(DB_HANDLE hdb)
 {
+   if (!(m_modified & MODIFY_COMMON_PROPERTIES))
+      return true;
+
        DB_STATEMENT hStmt;
        if (IsDatabaseRecordExist(hdb, _T("object_properties"), _T("object_id"), m_id))
        {
@@ -630,7 +640,7 @@ void NetObj::addChild(NetObj *object)
    m_childList->add(object);
    unlockChildList();
        incRefCount();
-   setModified();
+   setModified(MODIFY_RELATIONS);
    DbgPrintf(7, _T("NetObj::addChild: this=%s [%d]; object=%s [%d]"), m_name, m_id, object->m_name, object->m_id);
 }
 
@@ -648,7 +658,7 @@ void NetObj::addParent(NetObj *object)
    m_parentList->add(object);
    unlockParentList();
        incRefCount();
-   setModified();
+   setModified(MODIFY_RELATIONS);
    DbgPrintf(7, _T("NetObj::addParent: this=%s [%d]; object=%s [%d]"), m_name, m_id, object->m_name, object->m_id);
 }
 
@@ -674,7 +684,7 @@ void NetObj::deleteChild(NetObj *object)
    m_childList->remove(i);
    unlockChildList();
        decRefCount();
-   setModified();
+   setModified(MODIFY_RELATIONS);
 }
 
 /**
@@ -699,7 +709,7 @@ void NetObj::deleteParent(NetObj *object)
    m_parentList->remove(i);
    unlockParentList();
        decRefCount();
-   setModified();
+   setModified(MODIFY_RELATIONS);
 }
 
 /**
@@ -798,7 +808,7 @@ void NetObj::deleteObject(NetObj *initiator)
    lockProperties();
    m_isHidden = false;
    m_isDeleted = true;
-   setModified();
+   setModified(MODIFY_ALL);
    unlockProperties();
 
    // Notify all other objects about object deletion
@@ -994,7 +1004,7 @@ void NetObj::calculateCompoundStatus(BOOL bForcedRecalc)
          m_parentList->get(i)->calculateCompoundStatus();
       unlockParentList();
       lockProperties();
-      setModified();
+      setModified(MODIFY_RUNTIME);  // only notify clients
       unlockProperties();
    }
 }
@@ -1050,6 +1060,9 @@ static void EnumerationHandler(UINT32 dwUserId, UINT32 dwAccessRights, void *pAr
  */
 bool NetObj::saveACLToDB(DB_HANDLE hdb)
 {
+   if (!(m_modified & MODIFY_ACCESS_LIST))
+      return true;
+
    TCHAR szQuery[256];
    bool success = false;
    SAVE_PARAM sp;
@@ -1220,12 +1233,12 @@ static void BroadcastObjectChange(ClientSession *pSession, void *pArg)
  * Mark object as modified and put on client's notification queue
  * We assume that object is locked at the time of function call
  */
-void NetObj::setModified(bool notify)
+void NetObj::setModified(UINT32 flags, bool notify)
 {
    if (g_bModificationsLocked)
       return;
 
-   m_isModified = true;
+   m_modified |= flags;
    m_timestamp = time(NULL);
 
    // Send event to all connected clients
@@ -1240,7 +1253,7 @@ UINT32 NetObj::modifyFromMessage(NXCPMessage *msg)
 {
    lockProperties();
    UINT32 rcc = modifyFromMessageInternal(msg);
-   setModified();
+   setModified(MODIFY_ALL);
    unlockProperties();
    return rcc;
 }
@@ -1448,7 +1461,7 @@ void NetObj::dropUserAccess(UINT32 dwUserId)
    if (modified)
    {
       lockProperties();
-      setModified();
+      setModified(MODIFY_ACCESS_LIST);
       unlockProperties();
    }
 }
@@ -1476,7 +1489,7 @@ void NetObj::setMgmtStatus(BOOL bIsManaged)
    if (getObjectClass() == OBJECT_NODE)
       PostEvent(bIsManaged ? EVENT_NODE_UNKNOWN : EVENT_NODE_UNMANAGED, m_id, "d", oldStatus);
 
-   setModified();
+   setModified(MODIFY_COMMON_PROPERTIES);
    unlockProperties();
 
    // Change status for child objects also
@@ -1721,7 +1734,7 @@ void NetObj::setComments(TCHAR *text)
    lockProperties();
    free(m_comments);
    m_comments = text;
-   setModified();
+   setModified(MODIFY_COMMON_PROPERTIES);
    unlockProperties();
 }
 
@@ -2160,7 +2173,7 @@ void NetObj::setStatusCalculation(int method, int arg1, int arg2, int arg3, int
       default:
          break;
    }
-   setModified();
+   setModified(MODIFY_COMMON_PROPERTIES);
    unlockProperties();
 }
 
@@ -2188,7 +2201,21 @@ void NetObj::setStatusPropagation(int method, int arg1, int arg2, int arg3, int
       default:
          break;
    }
-   setModified();
+   setModified(MODIFY_COMMON_PROPERTIES);
+   unlockProperties();
+}
+
+/**
+ * Set geographical location
+ */
+void NetObj::setGeoLocation(const GeoLocation& geoLocation)
+{
+   lockProperties();
+   if (!m_geoLocation.equals(geoLocation))
+   {
+      m_geoLocation = geoLocation;
+      setModified(MODIFY_COMMON_PROPERTIES);
+   }
    unlockProperties();
 }
 
@@ -2236,7 +2263,7 @@ void NetObj::setCustomAttribute(const TCHAR *name, const TCHAR *value)
    if ((curr == NULL) || _tcscmp(curr, value))
    {
       m_customAttributes.set(name, value);
-      setModified();
+      setModified(MODIFY_CUSTOM_ATTRIBUTES);
    }
    unlockProperties();
 }
@@ -2251,7 +2278,7 @@ void NetObj::setCustomAttributePV(const TCHAR *name, TCHAR *value)
    if ((curr == NULL) || _tcscmp(curr, value))
    {
       m_customAttributes.setPreallocated(_tcsdup(name), value);
-      setModified();
+      setModified(MODIFY_CUSTOM_ATTRIBUTES);
    }
    else
    {
@@ -2269,7 +2296,7 @@ void NetObj::deleteCustomAttribute(const TCHAR *name)
    if (m_customAttributes.contains(name))
    {
       m_customAttributes.remove(name);
-      setModified();
+      setModified(MODIFY_CUSTOM_ATTRIBUTES);
    }
    unlockProperties();
 }
@@ -2366,9 +2393,6 @@ json_t *NetObj::toJson()
    json_object_set_new(root, "statusTranslation", json_integer_array(m_statusTranslation, 4));
    json_object_set_new(root, "statusSingleThreshold", json_integer(m_statusSingleThreshold));
    json_object_set_new(root, "statusThresholds", json_integer_array(m_statusThresholds, 4));
-   json_object_set_new(root, "isModified", json_boolean(m_isModified));
-   json_object_set_new(root, "isDeleted", json_boolean(m_isDeleted));
-   json_object_set_new(root, "isHidden", json_boolean(m_isHidden));
    json_object_set_new(root, "isSystem", json_boolean(m_isSystem));
    json_object_set_new(root, "maintenanceMode", json_boolean(m_maintenanceMode));
    json_object_set_new(root, "maintenanceEventId", json_integer(m_maintenanceEventId));
index 1453e71..94a1a58 100644 (file)
@@ -79,52 +79,59 @@ bool NetworkService::saveToDatabase(DB_HANDLE hdb)
 {
    lockProperties();
 
-   saveCommonProperties(hdb);
+   bool success = saveCommonProperties(hdb);
 
-   // Form and execute INSERT or UPDATE query
-       DB_STATEMENT hStmt;
-   if (IsDatabaseRecordExist(hdb, _T("network_services"), _T("id"), m_id))
+   if (success && (m_modified & MODIFY_OTHER))
    {
-               hStmt = DBPrepare(hdb, _T("UPDATE network_services SET node_id=?,")
-                             _T("service_type=?,ip_bind_addr=?,")
-                             _T("ip_proto=?,ip_port=?,check_request=?,")
-                             _T("check_responce=?,poller_node_id=?,")
-                                      _T("required_polls=? WHERE id=?"));
-   }
-   else
-   {
-               hStmt = DBPrepare(hdb, _T("INSERT INTO network_services (node_id,")
-                             _T("service_type,ip_bind_addr,ip_proto,ip_port,")
-                             _T("check_request,check_responce,poller_node_id,")
-                                      _T("required_polls,id) VALUES (?,?,?,?,?,?,?,?,?,?)"));
+      DB_STATEMENT hStmt;
+      if (IsDatabaseRecordExist(hdb, _T("network_services"), _T("id"), m_id))
+      {
+         hStmt = DBPrepare(hdb, _T("UPDATE network_services SET node_id=?,")
+                                _T("service_type=?,ip_bind_addr=?,")
+                                _T("ip_proto=?,ip_port=?,check_request=?,")
+                                _T("check_responce=?,poller_node_id=?,")
+                                _T("required_polls=? WHERE id=?"));
+      }
+      else
+      {
+         hStmt = DBPrepare(hdb, _T("INSERT INTO network_services (node_id,")
+                                _T("service_type,ip_bind_addr,ip_proto,ip_port,")
+                                _T("check_request,check_responce,poller_node_id,")
+                                _T("required_polls,id) VALUES (?,?,?,?,?,?,?,?,?,?)"));
+      }
+      if (hStmt != NULL)
+      {
+         TCHAR szIpAddr[64];
+
+         DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_hostNode->getId());
+         DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, (LONG)m_serviceType);
+         DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, m_ipAddress.toString(szIpAddr), DB_BIND_STATIC);
+         DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, (UINT32)m_proto);
+         DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, (UINT32)m_port);
+         DBBind(hStmt, 6, DB_SQLTYPE_TEXT, m_request, DB_BIND_STATIC);
+         DBBind(hStmt, 7, DB_SQLTYPE_TEXT, m_response, DB_BIND_STATIC);
+         DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_pollerNode);
+         DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, (LONG)m_requiredPollCount);
+         DBBind(hStmt, 10, DB_SQLTYPE_INTEGER, m_id);
+
+         success = DBExecute(hStmt);
+
+         DBFreeStatement(hStmt);
+      }
+      else
+      {
+         success = false;
+      }
    }
-       if (hStmt != NULL)
-       {
-          TCHAR szIpAddr[64];
-
-               DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_hostNode->getId());
-               DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, (LONG)m_serviceType);
-               DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, m_ipAddress.toString(szIpAddr), DB_BIND_STATIC);
-               DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, (UINT32)m_proto);
-               DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, (UINT32)m_port);
-               DBBind(hStmt, 6, DB_SQLTYPE_TEXT, m_request, DB_BIND_STATIC);
-               DBBind(hStmt, 7, DB_SQLTYPE_TEXT, m_response, DB_BIND_STATIC);
-               DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_pollerNode);
-               DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, (LONG)m_requiredPollCount);
-               DBBind(hStmt, 10, DB_SQLTYPE_INTEGER, m_id);
-
-               DBExecute(hStmt);
-
-               DBFreeStatement(hStmt);
-       }
 
    // Save access list
-   saveACLToDB(hdb);
+   if (success)
+      success = saveACLToDB(hdb);
 
    // Unlock object and clear modification flag
-   m_isModified = false;
+   m_modified = 0;
    unlockProperties();
-   return true;
+   return success;
 }
 
 /**
@@ -407,7 +414,7 @@ void NetworkService::statusPoll(ClientSession *session, UINT32 rqId, Node *polle
                                                        (m_status == STATUS_CRITICAL ? EVENT_SERVICE_DOWN : EVENT_SERVICE_UNKNOWN),
                                                        m_hostNode->getId(), "sdd", m_name, m_id, m_serviceType);
                        lockProperties();
-                       setModified();
+                       setModified(MODIFY_RUNTIME);
                        unlockProperties();
                }
    }
@@ -424,7 +431,7 @@ void NetworkService::onObjectDelete(UINT32 dwObjectId)
    {
       // If deleted object is our poller node, change it to default
       m_pollerNode = 0;
-      setModified();
+      setModified(MODIFY_OTHER);
       DbgPrintf(3, _T("Service \"%s\": poller node %d deleted"), m_name, dwObjectId);
    }
        unlockProperties();
index cac7abc..33825c8 100644 (file)
@@ -490,134 +490,134 @@ bool Node::saveToDatabase(DB_HANDLE hdb)
    // Lock object's access
    lockProperties();
 
-   if (!saveCommonProperties(hdb))
-   {
-      unlockProperties();
-      return false;
-   }
+   bool success = saveCommonProperties(hdb);
 
-   // Form and execute INSERT or UPDATE query
-   int snmpMethods = m_snmpSecurity->getAuthMethod() | (m_snmpSecurity->getPrivMethod() << 8);
-   DB_STATEMENT hStmt;
-   if (IsDatabaseRecordExist(hdb, _T("nodes"), _T("id"), m_id))
+   if (success && (m_modified & MODIFY_NODE_PROPERTIES))
    {
-      hStmt = DBPrepare(hdb,
-         _T("UPDATE nodes SET primary_ip=?,primary_name=?,snmp_port=?,capabilities=?,snmp_version=?,community=?,")
-         _T("status_poll_type=?,agent_port=?,auth_method=?,secret=?,snmp_oid=?,uname=?,agent_version=?,")
-         _T("platform_name=?,poller_node_id=?,zone_guid=?,proxy_node=?,snmp_proxy=?,icmp_proxy=?,required_polls=?,")
-         _T("use_ifxtable=?,usm_auth_password=?,usm_priv_password=?,usm_methods=?,snmp_sys_name=?,bridge_base_addr=?,")
-         _T("down_since=?,driver_name=?,rack_image=?,rack_position=?,rack_height=?,rack_id=?,boot_time=?,")
-         _T("agent_cache_mode=?,snmp_sys_contact=?,snmp_sys_location=?,last_agent_comm_time=?,")
-         _T("syslog_msg_count=?,snmp_trap_count=?,node_type=?,node_subtype=?,ssh_login=?,ssh_password=?,")
-         _T("ssh_proxy=?,chassis_id=?,port_rows=?,port_numbering_scheme=?,agent_comp_mode=?,tunnel_id=?,")
-         _T("lldp_id=?,fail_time_snmp=?,fail_time_agent=? WHERE id=?"));
-   }
-   else
-   {
-      hStmt = DBPrepare(hdb,
-        _T("INSERT INTO nodes (primary_ip,primary_name,snmp_port,capabilities,snmp_version,community,status_poll_type,")
-        _T("agent_port,auth_method,secret,snmp_oid,uname,agent_version,platform_name,poller_node_id,zone_guid,")
-        _T("proxy_node,snmp_proxy,icmp_proxy,required_polls,use_ifxtable,usm_auth_password,usm_priv_password,usm_methods,")
-        _T("snmp_sys_name,bridge_base_addr,down_since,driver_name,rack_image,rack_position,rack_height,rack_id,boot_time,")
-        _T("agent_cache_mode,snmp_sys_contact,snmp_sys_location,last_agent_comm_time,syslog_msg_count,snmp_trap_count,")
-        _T("node_type,node_subtype,ssh_login,ssh_password,ssh_proxy,chassis_id,port_rows,port_numbering_scheme,agent_comp_mode,")
-        _T("tunnel_id,lldp_id,fail_time_snmp,fail_time_agent,id) ")
-        _T("VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
-   }
-   if (hStmt == NULL)
-   {
-      unlockProperties();
-      return false;
-   }
-
-   TCHAR ipAddr[64], baseAddress[16], cacheMode[16], compressionMode[16];
-
-   DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, m_ipAddress.toString(ipAddr), DB_BIND_STATIC);
-   DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, m_primaryName, DB_BIND_STATIC);
-   DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, (LONG)m_snmpPort);
-   DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, m_capabilities);
-   DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, (LONG)m_snmpVersion);
+      int snmpMethods = m_snmpSecurity->getAuthMethod() | (m_snmpSecurity->getPrivMethod() << 8);
+      DB_STATEMENT hStmt;
+      if (IsDatabaseRecordExist(hdb, _T("nodes"), _T("id"), m_id))
+      {
+         hStmt = DBPrepare(hdb,
+            _T("UPDATE nodes SET primary_ip=?,primary_name=?,snmp_port=?,capabilities=?,snmp_version=?,community=?,")
+            _T("status_poll_type=?,agent_port=?,auth_method=?,secret=?,snmp_oid=?,uname=?,agent_version=?,")
+            _T("platform_name=?,poller_node_id=?,zone_guid=?,proxy_node=?,snmp_proxy=?,icmp_proxy=?,required_polls=?,")
+            _T("use_ifxtable=?,usm_auth_password=?,usm_priv_password=?,usm_methods=?,snmp_sys_name=?,bridge_base_addr=?,")
+            _T("down_since=?,driver_name=?,rack_image=?,rack_position=?,rack_height=?,rack_id=?,boot_time=?,")
+            _T("agent_cache_mode=?,snmp_sys_contact=?,snmp_sys_location=?,last_agent_comm_time=?,")
+            _T("syslog_msg_count=?,snmp_trap_count=?,node_type=?,node_subtype=?,ssh_login=?,ssh_password=?,")
+            _T("ssh_proxy=?,chassis_id=?,port_rows=?,port_numbering_scheme=?,agent_comp_mode=?,tunnel_id=?,")
+            _T("lldp_id=?,fail_time_snmp=?,fail_time_agent=? WHERE id=?"));
+      }
+      else
+      {
+         hStmt = DBPrepare(hdb,
+           _T("INSERT INTO nodes (primary_ip,primary_name,snmp_port,capabilities,snmp_version,community,status_poll_type,")
+           _T("agent_port,auth_method,secret,snmp_oid,uname,agent_version,platform_name,poller_node_id,zone_guid,")
+           _T("proxy_node,snmp_proxy,icmp_proxy,required_polls,use_ifxtable,usm_auth_password,usm_priv_password,usm_methods,")
+           _T("snmp_sys_name,bridge_base_addr,down_since,driver_name,rack_image,rack_position,rack_height,rack_id,boot_time,")
+           _T("agent_cache_mode,snmp_sys_contact,snmp_sys_location,last_agent_comm_time,syslog_msg_count,snmp_trap_count,")
+           _T("node_type,node_subtype,ssh_login,ssh_password,ssh_proxy,chassis_id,port_rows,port_numbering_scheme,agent_comp_mode,")
+           _T("tunnel_id,lldp_id,fail_time_snmp,fail_time_agent,id) ")
+           _T("VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+      }
+      if (hStmt != NULL)
+      {
+         TCHAR ipAddr[64], baseAddress[16], cacheMode[16], compressionMode[16];
+
+         DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, m_ipAddress.toString(ipAddr), DB_BIND_STATIC);
+         DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, m_primaryName, DB_BIND_STATIC);
+         DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, (LONG)m_snmpPort);
+         DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, m_capabilities);
+         DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, (LONG)m_snmpVersion);
 #ifdef UNICODE
-   DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, WideStringFromMBString(m_snmpSecurity->getCommunity()), DB_BIND_DYNAMIC);
+         DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, WideStringFromMBString(m_snmpSecurity->getCommunity()), DB_BIND_DYNAMIC);
 #else
-   DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, m_snmpSecurity->getCommunity(), DB_BIND_STATIC);
+         DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, m_snmpSecurity->getCommunity(), DB_BIND_STATIC);
 #endif
-   DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, (LONG)m_iStatusPollType);
-   DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, (LONG)m_agentPort);
-   DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, (LONG)m_agentAuthMethod);
-   DBBind(hStmt, 10, DB_SQLTYPE_VARCHAR, m_szSharedSecret, DB_BIND_STATIC);
-   DBBind(hStmt, 11, DB_SQLTYPE_VARCHAR, m_snmpObjectId, DB_BIND_STATIC);
-   DBBind(hStmt, 12, DB_SQLTYPE_VARCHAR, m_sysDescription, DB_BIND_STATIC);
-   DBBind(hStmt, 13, DB_SQLTYPE_VARCHAR, m_agentVersion, DB_BIND_STATIC);
-   DBBind(hStmt, 14, DB_SQLTYPE_VARCHAR, m_platformName, DB_BIND_STATIC);
-   DBBind(hStmt, 15, DB_SQLTYPE_INTEGER, m_pollerNode);
-   DBBind(hStmt, 16, DB_SQLTYPE_INTEGER, m_zoneUIN);
-   DBBind(hStmt, 17, DB_SQLTYPE_INTEGER, m_agentProxy);
-   DBBind(hStmt, 18, DB_SQLTYPE_INTEGER, m_snmpProxy);
-   DBBind(hStmt, 19, DB_SQLTYPE_INTEGER, m_icmpProxy);
-   DBBind(hStmt, 20, DB_SQLTYPE_INTEGER, (LONG)m_requiredPollCount);
-   DBBind(hStmt, 21, DB_SQLTYPE_INTEGER, (LONG)m_nUseIfXTable);
+         DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, (LONG)m_iStatusPollType);
+         DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, (LONG)m_agentPort);
+         DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, (LONG)m_agentAuthMethod);
+         DBBind(hStmt, 10, DB_SQLTYPE_VARCHAR, m_szSharedSecret, DB_BIND_STATIC);
+         DBBind(hStmt, 11, DB_SQLTYPE_VARCHAR, m_snmpObjectId, DB_BIND_STATIC);
+         DBBind(hStmt, 12, DB_SQLTYPE_VARCHAR, m_sysDescription, DB_BIND_STATIC);
+         DBBind(hStmt, 13, DB_SQLTYPE_VARCHAR, m_agentVersion, DB_BIND_STATIC);
+         DBBind(hStmt, 14, DB_SQLTYPE_VARCHAR, m_platformName, DB_BIND_STATIC);
+         DBBind(hStmt, 15, DB_SQLTYPE_INTEGER, m_pollerNode);
+         DBBind(hStmt, 16, DB_SQLTYPE_INTEGER, m_zoneUIN);
+         DBBind(hStmt, 17, DB_SQLTYPE_INTEGER, m_agentProxy);
+         DBBind(hStmt, 18, DB_SQLTYPE_INTEGER, m_snmpProxy);
+         DBBind(hStmt, 19, DB_SQLTYPE_INTEGER, m_icmpProxy);
+         DBBind(hStmt, 20, DB_SQLTYPE_INTEGER, (LONG)m_requiredPollCount);
+         DBBind(hStmt, 21, DB_SQLTYPE_INTEGER, (LONG)m_nUseIfXTable);
 #ifdef UNICODE
-   DBBind(hStmt, 22, DB_SQLTYPE_VARCHAR, WideStringFromMBString(m_snmpSecurity->getAuthPassword()), DB_BIND_DYNAMIC);
-   DBBind(hStmt, 23, DB_SQLTYPE_VARCHAR, WideStringFromMBString(m_snmpSecurity->getPrivPassword()), DB_BIND_DYNAMIC);
+         DBBind(hStmt, 22, DB_SQLTYPE_VARCHAR, WideStringFromMBString(m_snmpSecurity->getAuthPassword()), DB_BIND_DYNAMIC);
+         DBBind(hStmt, 23, DB_SQLTYPE_VARCHAR, WideStringFromMBString(m_snmpSecurity->getPrivPassword()), DB_BIND_DYNAMIC);
 #else
-   DBBind(hStmt, 22, DB_SQLTYPE_VARCHAR, m_snmpSecurity->getAuthPassword(), DB_BIND_STATIC);
-   DBBind(hStmt, 23, DB_SQLTYPE_VARCHAR, m_snmpSecurity->getPrivPassword(), DB_BIND_STATIC);
+         DBBind(hStmt, 22, DB_SQLTYPE_VARCHAR, m_snmpSecurity->getAuthPassword(), DB_BIND_STATIC);
+         DBBind(hStmt, 23, DB_SQLTYPE_VARCHAR, m_snmpSecurity->getPrivPassword(), DB_BIND_STATIC);
 #endif
-   DBBind(hStmt, 24, DB_SQLTYPE_INTEGER, (LONG)snmpMethods);
-   DBBind(hStmt, 25, DB_SQLTYPE_VARCHAR, m_sysName, DB_BIND_STATIC);
-   DBBind(hStmt, 26, DB_SQLTYPE_VARCHAR, BinToStr(m_baseBridgeAddress, MAC_ADDR_LENGTH, baseAddress), DB_BIND_STATIC);
-   DBBind(hStmt, 27, DB_SQLTYPE_INTEGER, (LONG)m_downSince);
-   DBBind(hStmt, 28, DB_SQLTYPE_VARCHAR, (m_driver != NULL) ? m_driver->getName() : _T(""), DB_BIND_STATIC);
-   DBBind(hStmt, 29, DB_SQLTYPE_VARCHAR, m_rackImage);   // rack image
-   DBBind(hStmt, 30, DB_SQLTYPE_INTEGER, m_rackPosition); // rack position
-   DBBind(hStmt, 31, DB_SQLTYPE_INTEGER, m_rackHeight);   // device height in rack units
-   DBBind(hStmt, 32, DB_SQLTYPE_INTEGER, m_rackId);   // rack ID
-   DBBind(hStmt, 33, DB_SQLTYPE_INTEGER, (LONG)m_bootTime);
-   DBBind(hStmt, 34, DB_SQLTYPE_VARCHAR, _itot(m_agentCacheMode, cacheMode, 10), DB_BIND_STATIC, 1);
-   DBBind(hStmt, 35, DB_SQLTYPE_VARCHAR, m_sysContact, DB_BIND_STATIC);
-   DBBind(hStmt, 36, DB_SQLTYPE_VARCHAR, m_sysLocation, DB_BIND_STATIC);
-   DBBind(hStmt, 37, DB_SQLTYPE_INTEGER, (LONG)m_lastAgentCommTime);
-   DBBind(hStmt, 38, DB_SQLTYPE_BIGINT, m_syslogMessageCount);
-   DBBind(hStmt, 39, DB_SQLTYPE_BIGINT, m_snmpTrapCount);
-   DBBind(hStmt, 40, DB_SQLTYPE_INTEGER, (INT32)m_type);
-   DBBind(hStmt, 41, DB_SQLTYPE_VARCHAR, m_subType, DB_BIND_STATIC);
-   DBBind(hStmt, 42, DB_SQLTYPE_VARCHAR, m_sshLogin, DB_BIND_STATIC);
-   DBBind(hStmt, 43, DB_SQLTYPE_VARCHAR, m_sshPassword, DB_BIND_STATIC);
-   DBBind(hStmt, 44, DB_SQLTYPE_INTEGER, m_sshProxy);
-   DBBind(hStmt, 45, DB_SQLTYPE_INTEGER, m_chassisId);
-   DBBind(hStmt, 46, DB_SQLTYPE_INTEGER, m_portRowCount);
-   DBBind(hStmt, 47, DB_SQLTYPE_INTEGER, m_portNumberingScheme);
-   DBBind(hStmt, 48, DB_SQLTYPE_VARCHAR, _itot(m_agentCompressionMode, compressionMode, 10), DB_BIND_STATIC, 1);
-   DBBind(hStmt, 49, DB_SQLTYPE_VARCHAR, m_tunnelId);
-   DBBind(hStmt, 50, DB_SQLTYPE_VARCHAR, m_lldpNodeId, DB_BIND_STATIC);
-   DBBind(hStmt, 51, DB_SQLTYPE_INTEGER, (LONG)m_failTimeSNMP);
-   DBBind(hStmt, 52, DB_SQLTYPE_INTEGER, (LONG)m_failTimeAgent);
-   DBBind(hStmt, 53, DB_SQLTYPE_INTEGER, m_id);
-
-   bool bResult = DBExecute(hStmt);
-   DBFreeStatement(hStmt);
+         DBBind(hStmt, 24, DB_SQLTYPE_INTEGER, (LONG)snmpMethods);
+         DBBind(hStmt, 25, DB_SQLTYPE_VARCHAR, m_sysName, DB_BIND_STATIC);
+         DBBind(hStmt, 26, DB_SQLTYPE_VARCHAR, BinToStr(m_baseBridgeAddress, MAC_ADDR_LENGTH, baseAddress), DB_BIND_STATIC);
+         DBBind(hStmt, 27, DB_SQLTYPE_INTEGER, (LONG)m_downSince);
+         DBBind(hStmt, 28, DB_SQLTYPE_VARCHAR, (m_driver != NULL) ? m_driver->getName() : _T(""), DB_BIND_STATIC);
+         DBBind(hStmt, 29, DB_SQLTYPE_VARCHAR, m_rackImage);   // rack image
+         DBBind(hStmt, 30, DB_SQLTYPE_INTEGER, m_rackPosition); // rack position
+         DBBind(hStmt, 31, DB_SQLTYPE_INTEGER, m_rackHeight);   // device height in rack units
+         DBBind(hStmt, 32, DB_SQLTYPE_INTEGER, m_rackId);   // rack ID
+         DBBind(hStmt, 33, DB_SQLTYPE_INTEGER, (LONG)m_bootTime);
+         DBBind(hStmt, 34, DB_SQLTYPE_VARCHAR, _itot(m_agentCacheMode, cacheMode, 10), DB_BIND_STATIC, 1);
+         DBBind(hStmt, 35, DB_SQLTYPE_VARCHAR, m_sysContact, DB_BIND_STATIC);
+         DBBind(hStmt, 36, DB_SQLTYPE_VARCHAR, m_sysLocation, DB_BIND_STATIC);
+         DBBind(hStmt, 37, DB_SQLTYPE_INTEGER, (LONG)m_lastAgentCommTime);
+         DBBind(hStmt, 38, DB_SQLTYPE_BIGINT, m_syslogMessageCount);
+         DBBind(hStmt, 39, DB_SQLTYPE_BIGINT, m_snmpTrapCount);
+         DBBind(hStmt, 40, DB_SQLTYPE_INTEGER, (INT32)m_type);
+         DBBind(hStmt, 41, DB_SQLTYPE_VARCHAR, m_subType, DB_BIND_STATIC);
+         DBBind(hStmt, 42, DB_SQLTYPE_VARCHAR, m_sshLogin, DB_BIND_STATIC);
+         DBBind(hStmt, 43, DB_SQLTYPE_VARCHAR, m_sshPassword, DB_BIND_STATIC);
+         DBBind(hStmt, 44, DB_SQLTYPE_INTEGER, m_sshProxy);
+         DBBind(hStmt, 45, DB_SQLTYPE_INTEGER, m_chassisId);
+         DBBind(hStmt, 46, DB_SQLTYPE_INTEGER, m_portRowCount);
+         DBBind(hStmt, 47, DB_SQLTYPE_INTEGER, m_portNumberingScheme);
+         DBBind(hStmt, 48, DB_SQLTYPE_VARCHAR, _itot(m_agentCompressionMode, compressionMode, 10), DB_BIND_STATIC, 1);
+         DBBind(hStmt, 49, DB_SQLTYPE_VARCHAR, m_tunnelId);
+         DBBind(hStmt, 50, DB_SQLTYPE_VARCHAR, m_lldpNodeId, DB_BIND_STATIC);
+         DBBind(hStmt, 51, DB_SQLTYPE_INTEGER, (LONG)m_failTimeSNMP);
+         DBBind(hStmt, 52, DB_SQLTYPE_INTEGER, (LONG)m_failTimeAgent);
+         DBBind(hStmt, 53, DB_SQLTYPE_INTEGER, m_id);
+
+         success = DBExecute(hStmt);
+         DBFreeStatement(hStmt);
+      }
+      else
+      {
+         success = false;
+      }
+   }
 
    // Save access list
-   saveACLToDB(hdb);
+   if (success)
+      success = saveACLToDB(hdb);
 
    unlockProperties();
 
    // Save data collection items
-   if (bResult)
+   if (success && (m_modified & MODIFY_DATA_COLLECTION))
    {
       lockDciAccess(false);
-      for(int i = 0; i < m_dcObjects->size(); i++)
-         m_dcObjects->get(i)->saveToDatabase(hdb);
+      for(int i = 0; success && (i < m_dcObjects->size()); i++)
+         success = m_dcObjects->get(i)->saveToDatabase(hdb);
       unlockDciAccess();
    }
 
    // Clear modifications flag
    lockProperties();
-   m_isModified = false;
+   m_modified = 0;
    unlockProperties();
 
-   return bResult;
+   return success;
 }
 
 /**
@@ -1781,10 +1781,7 @@ restart_agent_check:
          if (loc.getType() != GL_UNSET)
          {
             DbgPrintf(5, _T("StatusPoll(%s [%d]): location set to %s, %s from agent"), m_name, m_id, loc.getLatitudeAsString(), loc.getLongitudeAsString());
-            lockProperties();
-            m_geoLocation = loc;
-            setModified();
-            unlockProperties();
+            setGeoLocation(loc);
          }
       }
       else
@@ -1850,13 +1847,13 @@ restart_agent_check:
    if (pPollerNode != NULL)
       pPollerNode->decRefCount();
 
-   if (oldCapabilities != m_capabilities) //currectly not flags but capabilities
+   if (oldCapabilities != m_capabilities)
       PostEvent(EVENT_NODE_CAPABILITIES_CHANGED, m_id, "xx", oldCapabilities, m_capabilities);
 
    if (oldState != m_state || oldCapabilities != m_capabilities)
    {
       lockProperties();
-      setModified();
+      setModified(MODIFY_NODE_PROPERTIES);
       unlockProperties();
    }
 
@@ -2238,7 +2235,7 @@ void Node::updatePrimaryIpAddr()
       {
          lockProperties();
          m_ipAddress = ipAddr;
-         setModified();
+         setModified(MODIFY_NODE_PROPERTIES);
          unlockProperties();
       }
       else
@@ -2355,9 +2352,9 @@ void Node::configurationPoll(PollerInfo *poller, ClientSession *session, UINT32
    if (IsShutdownInProgress())
       return;
 
-   UINT32 dwOldFlags = m_capabilities;
+   UINT32 oldCapabilities = m_capabilities;
    TCHAR szBuffer[4096];
-   bool hasChanges = false;
+   UINT32 modified = 0;
 
    poller->setStatus(_T("wait for lock"));
    pollerLock();
@@ -2403,9 +2400,9 @@ void Node::configurationPoll(PollerInfo *poller, ClientSession *session, UINT32
       sendPollerMsg(rqId, _T("Checking node's capabilities...\r\n"));
 
       if (confPollAgent(rqId))
-         hasChanges = true;
+         modified |= MODIFY_NODE_PROPERTIES;
       if (confPollSnmp(rqId))
-         hasChanges = true;
+         modified |= MODIFY_NODE_PROPERTIES;
 
       // Check for CheckPoint SNMP agent on port 260
       if (ConfigReadInt(_T("EnableCheckPointSNMP"), 0))
@@ -2429,10 +2426,10 @@ void Node::configurationPoll(PollerInfo *poller, ClientSession *session, UINT32
       }
 
       // Generate event if node flags has been changed
-      if (dwOldFlags != m_capabilities)
+      if (oldCapabilities != m_capabilities)
       {
-         PostEvent(EVENT_NODE_CAPABILITIES_CHANGED, m_id, "xx", dwOldFlags, m_capabilities);
-         hasChanges = true;
+         PostEvent(EVENT_NODE_CAPABILITIES_CHANGED, m_id, "xx", oldCapabilities, m_capabilities);
+         modified |= MODIFY_NODE_PROPERTIES;
       }
 
       // Retrieve interface list
@@ -2440,7 +2437,7 @@ void Node::configurationPoll(PollerInfo *poller, ClientSession *session, UINT32
       sendPollerMsg(rqId, _T("Capability check finished\r\n"));
 
       if (updateInterfaceConfiguration(rqId, 0)) // maskBits
-         hasChanges = true;
+         modified |= MODIFY_NODE_PROPERTIES;
 
       m_lastConfigurationPoll = time(NULL);
 
@@ -2457,7 +2454,7 @@ void Node::configurationPoll(PollerInfo *poller, ClientSession *session, UINT32
          if (resolveName(FALSE))
          {
             sendPollerMsg(rqId, POLLER_INFO _T("Node name resolved to %s\r\n"), m_name);
-            hasChanges = true;
+            modified |= MODIFY_COMMON_PROPERTIES;
          }
          else
          {
@@ -2473,7 +2470,7 @@ void Node::configurationPoll(PollerInfo *poller, ClientSession *session, UINT32
             if (resolveName(TRUE))
             {
                sendPollerMsg(rqId, POLLER_INFO _T("Node name resolved to %s\r\n"), m_name);
-               hasChanges = true;
+               modified |= MODIFY_COMMON_PROPERTIES;
             }
          }
          else
@@ -2493,7 +2490,7 @@ void Node::configurationPoll(PollerInfo *poller, ClientSession *session, UINT32
          {
             DbgPrintf(5, _T("ConfigurationPoll(%s [%d]): calling hook in module %s"), m_name, m_id, g_pModuleList[i].szName);
             if (g_pModuleList[i].pfConfPollHook(this, session, rqId, poller))
-               hasChanges = true;
+               modified |= MODIFY_ALL;   // FIXME: change module call to get exact modifications
          }
       }
 
@@ -2512,7 +2509,7 @@ void Node::configurationPoll(PollerInfo *poller, ClientSession *session, UINT32
       if ((type != NODE_TYPE_UNKNOWN) && (type != m_type))
       {
          m_type = type;
-         hasChanges = true;
+         modified |= MODIFY_NODE_PROPERTIES;
          nxlog_debug(5, _T("ConfPoll(%s): node type set to %d (%s)"), m_name, type, typeName(type));
          sendPollerMsg(rqId, _T("   Node type changed to %s\r\n"), typeName(type));
       }
@@ -2523,7 +2520,7 @@ void Node::configurationPoll(PollerInfo *poller, ClientSession *session, UINT32
       executeHookScript(_T("ConfigurationPoll"));
 
       sendPollerMsg(rqId, _T("Finished configuration poll for node %s\r\n"), m_name);
-      sendPollerMsg(rqId, _T("Node configuration was%schanged after poll\r\n"), hasChanges ? _T(" ") : _T(" not "));
+      sendPollerMsg(rqId, _T("Node configuration was%schanged after poll\r\n"), (modified != 0) ? _T(" ") : _T(" not "));
 
       m_runtimeFlags |= DCDF_CONFIGURATION_POLL_PASSED;
    }
@@ -2536,10 +2533,10 @@ void Node::configurationPoll(PollerInfo *poller, ClientSession *session, UINT32
    pollerUnlock();
    DbgPrintf(4, _T("Finished configuration poll for node %s (ID: %d)"), m_name, m_id);
 
-   if (hasChanges)
+   if (modified != 0)
    {
       lockProperties();
-      setModified();
+      setModified(modified);
       unlockProperties();
    }
 }
@@ -2685,7 +2682,7 @@ bool Node::confPollAgent(UINT32 rqId)
          lockProperties();
          if ((m_sysDescription == NULL) || _tcscmp(m_sysDescription, buffer))
          {
-            safe_free(m_sysDescription);
+            free(m_sysDescription);
             m_sysDescription = _tcsdup(buffer);
             hasChanges = true;
             sendPollerMsg(rqId, _T("   System description changed to %s\r\n"), m_sysDescription);
@@ -2836,7 +2833,7 @@ bool Node::confPollSnmp(UINT32 rqId)
    lockProperties();
    if (_tcscmp(m_snmpObjectId, szBuffer))
    {
-      nx_strncpy(m_snmpObjectId, szBuffer, MAX_OID_LEN * 4);
+      _tcslcpy(m_snmpObjectId, szBuffer, MAX_OID_LEN * 4);
       hasChanges = true;
    }
    unlockProperties();
@@ -4862,7 +4859,7 @@ UINT32 Node::modifyFromMessageInternal(NXCPMessage *pRequest)
       {
          lockProperties();
          m_ipAddress = ipAddr;
-         setModified();
+         setModified(MODIFY_NODE_PROPERTIES);
          unlockProperties();
       }
       else
@@ -5337,7 +5334,7 @@ void Node::onObjectDelete(UINT32 dwObjectId)
    {
       // If deleted object is our poller node, change it to default
       m_pollerNode = 0;
-      setModified();
+      setModified(MODIFY_NODE_PROPERTIES);
       DbgPrintf(3, _T("Node \"%s\": poller node %d deleted"), m_name, dwObjectId);
    }
    unlockProperties();
@@ -5525,7 +5522,7 @@ void Node::changeIPAddress(const InetAddress& ipAddr)
       }
       unlockChildList();
 
-      setModified();
+      setModified(MODIFY_NODE_PROPERTIES);
    }
    unlockProperties();
 
@@ -5575,7 +5572,7 @@ void Node::changeZone(UINT32 newZone)
    unlockChildList();
 
    lockProperties();
-   setModified();
+   setModified(MODIFY_RELATIONS | MODIFY_NODE_PROPERTIES);
    unlockProperties();
 
    agentLock();
@@ -6373,13 +6370,13 @@ void Node::topologyPoll(PollerInfo *poller, ClientSession *pSession, UINT32 rqId
          MutexUnlock(m_mutexTopoAccess);
 
          lockProperties();
-         UINT32 oldFlags = m_flags;
+         UINT32 oldCaps = m_capabilities;
          if (vlanList != NULL)
             m_capabilities |= NC_HAS_VLANS;
          else
             m_capabilities &= ~NC_HAS_VLANS;
-         if (oldFlags != m_flags)
-            setModified();
+         if (oldCaps != m_capabilities)
+            setModified(MODIFY_NODE_PROPERTIES);
          unlockProperties();
       }
    }
@@ -7906,7 +7903,7 @@ void Node::setSshCredentials(const TCHAR *login, const TCHAR *password)
       nx_strncpy(m_sshLogin, login, MAX_SSH_LOGIN_LEN);
    if (password != NULL)
       nx_strncpy(m_sshPassword, password, MAX_SSH_PASSWORD_LEN);
-   setModified();
+   setModified(MODIFY_NODE_PROPERTIES);
    unlockProperties();
 }
 
@@ -7944,7 +7941,7 @@ void Node::setTunnelId(const uuid& tunnelId)
 {
    lockProperties();
    m_tunnelId = tunnelId;
-   setModified(false);
+   setModified(MODIFY_NODE_PROPERTIES, false);
    unlockProperties();
 
    TCHAR buffer[128];
index 36acb0f..dc5895d 100644 (file)
@@ -101,48 +101,45 @@ bool NodeLink::loadFromDatabase(DB_HANDLE hdb, UINT32 id)
  */
 bool NodeLink::saveToDatabase(DB_HANDLE hdb)
 {
-       BOOL bNewObject = TRUE;
-
-       DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT nodelink_id FROM node_links WHERE nodelink_id=?"));
-       if (hStmt == NULL)
-       {
-               DbgPrintf(4, _T("Cannot prepare select from node_links"));
-               return false;
-       }
-
-       lockProperties();
-
-       DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
-       DB_RESULT hResult = DBSelectPrepared(hStmt);
-       if (hResult != NULL)
-       {
-               bNewObject = (DBGetNumRows(hResult) <= 0);
-               DBFreeResult(hResult);
-       }
-       DBFreeStatement(hStmt);
-
-       hStmt = DBPrepare(hdb, bNewObject ? _T("INSERT INTO node_links (node_id,nodelink_id) VALUES (?,?)") :
-                                                                                         _T("UPDATE node_links SET node_id=? WHERE nodelink_id=?"));
-       if (hStmt == NULL)
-       {
-               unlockProperties();
-               return false;
-       }
-       DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_nodeId);
-       DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_id);
-       unlockProperties();
-       if (!DBExecute(hStmt))
-       {
-               DBFreeStatement(hStmt);
-               return false;
-       }
-       DBFreeStatement(hStmt);
-
-       saveACLToDB(hdb);
-
-       lockProperties();
-       m_isModified = false;
-       unlockProperties();
+   if (m_modified & MODIFY_OTHER)
+   {
+      BOOL bNewObject = TRUE;
+
+      DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT nodelink_id FROM node_links WHERE nodelink_id=?"));
+      if (hStmt == NULL)
+      {
+         DbgPrintf(4, _T("Cannot prepare select from node_links"));
+         return false;
+      }
+
+      lockProperties();
+
+      DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
+      DB_RESULT hResult = DBSelectPrepared(hStmt);
+      if (hResult != NULL)
+      {
+         bNewObject = (DBGetNumRows(hResult) <= 0);
+         DBFreeResult(hResult);
+      }
+      DBFreeStatement(hStmt);
+
+      hStmt = DBPrepare(hdb, bNewObject ? _T("INSERT INTO node_links (node_id,nodelink_id) VALUES (?,?)") :
+                                      _T("UPDATE node_links SET node_id=? WHERE nodelink_id=?"));
+      if (hStmt == NULL)
+      {
+         unlockProperties();
+         return false;
+      }
+      DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_nodeId);
+      DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_id);
+      unlockProperties();
+      if (!DBExecute(hStmt))
+      {
+         DBFreeStatement(hStmt);
+         return false;
+      }
+      DBFreeStatement(hStmt);
+   }
        return ServiceContainer::saveToDatabase(hdb);
 }
 
index bf69a00..4381f6a 100644 (file)
@@ -265,7 +265,7 @@ bool Sensor::saveToDatabase(DB_HANDLE hdb)
 
    bool success = saveCommonProperties(hdb);
 
-   if(success)
+   if (success && (m_modified & MODIFY_SENSOR_PROPERTIES))
    {
       DB_STATEMENT hStmt;
       bool isNew = !(IsDatabaseRecordExist(hdb, _T("sensors"), _T("id"), m_id));
@@ -291,7 +291,7 @@ bool Sensor::saveToDatabase(DB_HANDLE hdb)
          DBBind(hStmt, 14, DB_SQLTYPE_INTEGER, m_frequency);
          DBBind(hStmt, 15, DB_SQLTYPE_INTEGER, m_proxyNodeId);
          DBBind(hStmt, 16, DB_SQLTYPE_INTEGER, m_id);
-         if(isNew)
+         if (isNew)
             DBBind(hStmt, 17, DB_SQLTYPE_VARCHAR, m_xmlRegConfig, DB_BIND_STATIC);
 
          success = DBExecute(hStmt);
@@ -305,7 +305,7 @@ bool Sensor::saveToDatabase(DB_HANDLE hdb)
        }
 
    // Save data collection items
-   if (success)
+   if (success && (m_modified & MODIFY_DATA_COLLECTION))
    {
                lockDciAccess(false);
       for(int i = 0; i < m_dcObjects->size(); i++)
@@ -319,7 +319,7 @@ bool Sensor::saveToDatabase(DB_HANDLE hdb)
 
    // Clear modifications flag and unlock object
        if (success)
-               m_isModified = FALSE;
+               m_modified = 0;
    unlockProperties();
 
    return success;
@@ -440,7 +440,7 @@ void Sensor::calculateCompoundStatus(BOOL bForcedRecalc)
    calculateStatus(bForcedRecalc);
    lockProperties();
    if (oldStatus != m_status)
-      setModified(true);
+      setModified(MODIFY_RUNTIME);
    unlockProperties();
 }
 
@@ -551,7 +551,7 @@ void Sensor::configurationPoll(PollerInfo *poller, ClientSession *session, UINT3
 
    bool hasChanges = false;
 
-   if(m_commProtocol == COMM_LORAWAN)
+   if (m_commProtocol == COMM_LORAWAN)
    {
       if (!(m_state & SSF_PROVISIONED))
       {
@@ -592,7 +592,7 @@ void Sensor::configurationPoll(PollerInfo *poller, ClientSession *session, UINT3
    if (hasChanges)
    {
       lockProperties();
-      setModified();
+      setModified(MODIFY_SENSOR_PROPERTIES);
       unlockProperties();
    }
 
@@ -635,6 +635,8 @@ void Sensor::statusPoll(PollerInfo *poller, ClientSession *session, UINT32 rqId)
    sendPollerMsg(rqId, _T("Starting status poll for sensor %s\r\n"), m_name);
    nxlog_debug(5, _T("Starting status poll for sensor %s (ID: %d)"), m_name, m_id);
 
+   UINT32 prevState = m_state;
+
    nxlog_debug(6, _T("StatusPoll(%s): checking agent"), m_name);
    poller->setStatus(_T("check agent"));
    sendPollerMsg(rqId, _T("Checking NetXMS agent connectivity\r\n"));
@@ -695,6 +697,7 @@ void Sensor::statusPoll(PollerInfo *poller, ClientSession *session, UINT32 rqId)
                }
                else
                {
+                  // FIXME: modify runtime if needed
                   m_state |= SSF_ACTIVE;
                   nxlog_debug(6, _T("StatusPoll(%s [%d]): Status set to ACTIVE"), m_name, m_id);
                   getItemFromAgent(_T("LoraWAN.RSSI(*)"), MAX_DCI_STRING_VALUE, lastValue);
@@ -706,15 +709,11 @@ void Sensor::statusPoll(PollerInfo *poller, ClientSession *session, UINT32 rqId)
                }
             }
 
-            setModified();
             unlockProperties();
          }
          break;
       case COMM_DLMS:
          checkDlmsConverterAccessibility();
-         lockProperties();
-         setModified();
-         unlockProperties();
          break;
       default:
          break;
@@ -733,6 +732,9 @@ void Sensor::statusPoll(PollerInfo *poller, ClientSession *session, UINT32 rqId)
    if (rqId == 0)
       m_runtimeFlags &= ~DCDF_QUEUED_FOR_STATUS_POLL;
 
+   if (prevState != m_state)
+      setModified(MODIFY_SENSOR_PROPERTIES);
+
    sendPollerMsg(rqId, _T("Finished status poll for sensor %s\r\n"), m_name);
    sendPollerMsg(rqId, _T("Sensor status after poll is %s\r\n"), GetStatusAsText(m_status, true));
 
index 01b389b..f49e924 100644 (file)
@@ -102,11 +102,9 @@ SlmCheck::~SlmCheck()
        delete m_pCompiledScript;
 }
 
-
-//
-// Update this check from a check template
-//
-
+/**
+ * Update this check from a check template
+ */
 void SlmCheck::updateFromTemplate(SlmCheck *tmpl)
 {
        lockProperties();
@@ -114,10 +112,10 @@ void SlmCheck::updateFromTemplate(SlmCheck *tmpl)
        DbgPrintf(4, _T("Updating service check %s [%d] from service check template template %s [%d]"), m_name, m_id, tmpl->getName(), tmpl->getId());
 
        delete m_threshold;
-       safe_free(m_script);
+       free(m_script);
        delete m_pCompiledScript;
 
-       nx_strncpy(m_name, tmpl->m_name, MAX_OBJECT_NAME);
+       _tcslcpy(m_name, tmpl->m_name, MAX_OBJECT_NAME);
        m_type = tmpl->m_type;
        m_script = ((m_type == check_script) && (tmpl->m_script != NULL)) ? _tcsdup(tmpl->m_script) : NULL;
        m_threshold = NULL;
@@ -127,7 +125,7 @@ void SlmCheck::updateFromTemplate(SlmCheck *tmpl)
 
        tmpl->unlockProperties();
 
-       setModified();
+       setModified(MODIFY_COMMON_PROPERTIES | MODIFY_OTHER);
        unlockProperties();
 }
 
@@ -211,43 +209,48 @@ bool SlmCheck::loadFromDatabase(DB_HANDLE hdb, UINT32 id)
  */
 bool SlmCheck::saveToDatabase(DB_HANDLE hdb)
 {
-       bool ret = false;
-
        lockProperties();
 
-       saveCommonProperties(hdb);
+       bool success = saveCommonProperties(hdb);
 
-       DB_STATEMENT hStmt;
-       if (IsDatabaseRecordExist(hdb, _T("slm_checks"), _T("id"), m_id))
-       {
-          hStmt = DBPrepare(hdb, _T("UPDATE slm_checks SET type=?,content=?,threshold_id=?,reason=?,is_template=?,template_id=?,current_ticket=? WHERE id=?"));
-       }
-       else
+       if (success && (m_modified & MODIFY_OTHER))
        {
-      hStmt = DBPrepare(hdb, _T("INSERT INTO slm_checks (type,content,threshold_id,reason,is_template,template_id,current_ticket,id) VALUES (?,?,?,?,?,?,?,?)"));
+      DB_STATEMENT hStmt;
+      if (IsDatabaseRecordExist(hdb, _T("slm_checks"), _T("id"), m_id))
+      {
+         hStmt = DBPrepare(hdb, _T("UPDATE slm_checks SET type=?,content=?,threshold_id=?,reason=?,is_template=?,template_id=?,current_ticket=? WHERE id=?"));
+      }
+      else
+      {
+         hStmt = DBPrepare(hdb, _T("INSERT INTO slm_checks (type,content,threshold_id,reason,is_template,template_id,current_ticket,id) VALUES (?,?,?,?,?,?,?,?)"));
+      }
+
+      if (hStmt != NULL)
+      {
+         DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, (UINT32)m_type);
+         DBBind(hStmt, 2, DB_SQLTYPE_TEXT, m_script, DB_BIND_STATIC);
+         DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, m_threshold ? m_threshold->getId() : 0);
+         DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, m_reason, DB_BIND_STATIC);
+         DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, (LONG)(m_isTemplate ? 1 : 0));
+         DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, m_templateId);
+         DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, m_currentTicketId);
+         DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_id);
+
+         success = DBExecute(hStmt);
+         DBFreeStatement(hStmt);
+      }
+      else
+      {
+         success = false;
+      }
        }
 
-       if (hStmt != NULL)
-       {
-      DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, (UINT32)m_type);
-      DBBind(hStmt, 2, DB_SQLTYPE_TEXT, m_script, DB_BIND_STATIC);
-      DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, m_threshold ? m_threshold->getId() : 0);
-      DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, m_reason, DB_BIND_STATIC);
-      DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, (LONG)(m_isTemplate ? 1 : 0));
-      DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, m_templateId);
-      DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, m_currentTicketId);
-      DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_id);
-
-      ret = DBExecute(hStmt);
-      DBFreeStatement(hStmt);
-
-      if (ret)
-         ret = saveACLToDB(hdb);
-       }
+   if (success)
+      success = saveACLToDB(hdb);
 
-   m_isModified = false;
+   m_modified = 0;
        unlockProperties();
-       return ret;
+       return success;
 }
 
 /**
@@ -329,7 +332,7 @@ void SlmCheck::setScript(const TCHAR *script)
 {
        if (script != NULL)
        {
-               safe_free(m_script);
+               free(m_script);
                delete m_pCompiledScript;
                m_script = _tcsdup(script);
                if (m_script != NULL)
@@ -350,7 +353,7 @@ void SlmCheck::setScript(const TCHAR *script)
                delete_and_null(m_pCompiledScript);
                safe_free_and_null(m_script);
        }
-       setModified();
+       setModified(MODIFY_OTHER);
 }
 
 /**
@@ -413,7 +416,7 @@ void SlmCheck::execute()
                        insertTicket();
                else
                        closeTicket();
-               setModified();
+               setModified(MODIFY_COMMON_PROPERTIES);
        }
        unlockProperties();
 }
index bd3b2f2..047fdd1 100644 (file)
@@ -96,38 +96,45 @@ bool Subnet::saveToDatabase(DB_HANDLE hdb)
    // Lock object's access
    lockProperties();
 
-   saveCommonProperties(hdb);
-
-   // Form and execute INSERT or UPDATE query
-   if (IsDatabaseRecordExist(hdb, _T("subnets"), _T("id"), m_id))
-      _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR),
-                          _T("UPDATE subnets SET ip_addr='%s',ip_netmask=%d,zone_guid=%d,synthetic_mask=%d WHERE id=%d"),
-                 m_ipAddress.toString(szIpAddr), m_ipAddress.getMaskBits(), m_zoneUIN, m_bSyntheticMask ? 1 : 0, m_id);
-   else
-      _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR),
-                          _T("INSERT INTO subnets (id,ip_addr,ip_netmask,zone_guid,synthetic_mask) VALUES (%d,'%s',%d,%d,%d)"),
-                 m_id, m_ipAddress.toString(szIpAddr), m_ipAddress.getMaskBits(), m_zoneUIN, m_bSyntheticMask ? 1 : 0);
-   DBQuery(hdb, szQuery);
+   bool success = saveCommonProperties(hdb);
+
+   if (success && (m_modified & MODIFY_OTHER))
+   {
+      // Form and execute INSERT or UPDATE query
+      if (IsDatabaseRecordExist(hdb, _T("subnets"), _T("id"), m_id))
+         _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR),
+                    _T("UPDATE subnets SET ip_addr='%s',ip_netmask=%d,zone_guid=%d,synthetic_mask=%d WHERE id=%d"),
+                    m_ipAddress.toString(szIpAddr), m_ipAddress.getMaskBits(), m_zoneUIN, m_bSyntheticMask ? 1 : 0, m_id);
+      else
+         _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR),
+                    _T("INSERT INTO subnets (id,ip_addr,ip_netmask,zone_guid,synthetic_mask) VALUES (%d,'%s',%d,%d,%d)"),
+                    m_id, m_ipAddress.toString(szIpAddr), m_ipAddress.getMaskBits(), m_zoneUIN, m_bSyntheticMask ? 1 : 0);
+      success = DBQuery(hdb, szQuery);
+   }
 
    // Update node to subnet mapping
-   _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("DELETE FROM nsmap WHERE subnet_id=%d"), m_id);
-   DBQuery(hdb, szQuery);
-   lockChildList(false);
-   for(int i = 0; i < m_childList->size(); i++)
+   if (success && (m_modified & MODIFY_RELATIONS))
    {
-      _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("INSERT INTO nsmap (subnet_id,node_id) VALUES (%d,%d)"), m_id, m_childList->get(i)->getId());
+      _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("DELETE FROM nsmap WHERE subnet_id=%d"), m_id);
       DBQuery(hdb, szQuery);
+      lockChildList(false);
+      for(int i = 0; success && (i < m_childList->size()); i++)
+      {
+         _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("INSERT INTO nsmap (subnet_id,node_id) VALUES (%d,%d)"), m_id, m_childList->get(i)->getId());
+         success = DBQuery(hdb, szQuery);
+      }
+      unlockChildList();
    }
-   unlockChildList();
 
    // Save access list
-   saveACLToDB(hdb);
+   if (success)
+      success = saveACLToDB(hdb);
 
    // Clear modifications flag and unlock object
-   m_isModified = false;
+   m_modified = 0;
    unlockProperties();
 
-   return true;
+   return success;
 }
 
 /**
@@ -184,7 +191,7 @@ void Subnet::setCorrectMask(const InetAddress& addr)
    {
       g_idxSubnetByAddr.put(m_ipAddress, this);
    }
-       setModified();
+       setModified(MODIFY_OTHER);
        unlockProperties();
 }
 
index 9e41d6c..5f3d8ad 100644 (file)
@@ -140,7 +140,9 @@ void ServiceContainer::calculateCompoundStatus(BOOL bForcedRecalc)
                for(i = 0; i < m_parentList->size(); i++)
                        m_parentList->get(i)->calculateCompoundStatus();
                unlockParentList();
-               setModified();   /* LOCK? */
+               lockProperties();
+               setModified(MODIFY_COMMON_PROPERTIES);
+               unlockProperties();
        }
 
        DbgPrintf(6, _T("ServiceContainer::calculateCompoundStatus(%s [%d]): old_status=%d new_status=%d"), m_name, m_id, iOldStatus, m_status);
@@ -326,7 +328,7 @@ void ServiceContainer::updateUptimeStats(time_t currentTime, BOOL updateChilds)
 
        if ((prevUptimeDay != m_uptimeDay) || (prevUptimeWeek != m_uptimeWeek) || (prevUptimeMonth != m_uptimeMonth))
        {
-               setModified();
+               setModified(MODIFY_OTHER);
        }
        unlockProperties();
 
index 32adfb7..11d3aa4 100644 (file)
@@ -22,6 +22,9 @@
 
 #include "nxcore.h"
 
+#define DEBUG_TAG_SYNC           _T("sync")
+#define DEBUG_TAG_OBJECT_SYNC    _T("obj.sync")
+
 /**
  * Externals
  */
@@ -59,38 +62,38 @@ void SaveObjects(DB_HANDLE hdb, UINT32 watchdogId, bool saveRuntimeData)
       RWLockWriteLock(s_objectTxnLock, INFINITE);
 
        ObjectArray<NetObj> *objects = g_idxObjectById.getObjects(false);
-   DbgPrintf(5, _T("Syncer: %d objects to process"), objects->size());
+   nxlog_debug_tag(DEBUG_TAG_SYNC, 5, _T("%d objects to process"), objects->size());
        for(int i = 0; i < objects->size(); i++)
    {
           WatchdogNotify(watchdogId);
        NetObj *object = objects->get(i);
       if (object->isDeleted())
       {
-         DbgPrintf(5, _T("Syncer: object %s [%d] marked for deletion"), object->getName(), object->getId());
+         nxlog_debug_tag(DEBUG_TAG_OBJECT_SYNC, 5, _T("Object %s [%d] marked for deletion"), object->getName(), object->getId());
          if (object->getRefCount() == 0)
          {
                   DBBegin(hdb);
             if (object->deleteFromDatabase(hdb))
             {
-               DbgPrintf(4, _T("Syncer: Object %d \"%s\" deleted from database"), object->getId(), object->getName());
+               nxlog_debug_tag(DEBUG_TAG_OBJECT_SYNC, 4, _T("Object %d \"%s\" deleted from database"), object->getId(), object->getName());
                DBCommit(hdb);
                NetObjDelete(object);
             }
             else
             {
                DBRollback(hdb);
-               DbgPrintf(4, _T("Syncer: Call to deleteFromDatabase() failed for object %s [%d], transaction rollback"), object->getName(), object->getId());
+               nxlog_debug_tag(DEBUG_TAG_OBJECT_SYNC, 4, _T("Call to deleteFromDatabase() failed for object %s [%d], transaction rollback"), object->getName(), object->getId());
             }
          }
          else
          {
-            DbgPrintf(3, _T("Syncer: Unable to delete object with id %d because it is being referenced %d time(s)"),
+            nxlog_debug_tag(DEBUG_TAG_OBJECT_SYNC, 3, _T("Unable to delete object with id %d because it is being referenced %d time(s)"),
                       object->getId(), object->getRefCount());
          }
       }
                else if (object->isModified())
                {
-         DbgPrintf(5, _T("Syncer: object %s [%d] modified"), object->getName(), object->getId());
+                  nxlog_debug_tag(DEBUG_TAG_OBJECT_SYNC, 5, _T("Object %s [%d] modified"), object->getName(), object->getId());
                   DBBegin(hdb);
                        if (object->saveToDatabase(hdb))
                        {
@@ -110,7 +113,7 @@ void SaveObjects(DB_HANDLE hdb, UINT32 watchdogId, bool saveRuntimeData)
    if (g_flags & AF_ENABLE_OBJECT_TRANSACTIONS)
       RWLockUnlock(s_objectTxnLock);
        delete objects;
-   DbgPrintf(5, _T("Syncer: save objects completed"));
+       nxlog_debug_tag(DEBUG_TAG_SYNC, 5, _T("Save objects completed"));
 }
 
 /**
@@ -123,24 +126,28 @@ THREAD_RESULT THREAD_CALL Syncer(void *arg)
    int syncInterval = ConfigReadInt(_T("SyncInterval"), 60);
    UINT32 watchdogId = WatchdogAddThread(_T("Syncer Thread"), 30);
 
-   nxlog_debug(1, _T("Syncer thread started, sync_interval = %d"), syncInterval);
+   nxlog_debug_tag(DEBUG_TAG_SYNC, 1, _T("Syncer thread started, sync_interval = %d"), syncInterval);
 
    // Main syncer loop
    WatchdogStartSleep(watchdogId);
    while(!SleepAndCheckForShutdown(syncInterval))
    {
       WatchdogNotify(watchdogId);
+      nxlog_debug_tag(DEBUG_TAG_SYNC, 7, _T("Syncer wakeup"));
       if (!(g_flags & AF_DB_CONNECTION_LOST))    // Don't try to save if DB connection is lost
       {
          DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
          SaveObjects(hdb, watchdogId, false);
+         nxlog_debug_tag(DEBUG_TAG_SYNC, 5, _T("Saving user database"));
          SaveUsers(hdb, watchdogId);
+         nxlog_debug_tag(DEBUG_TAG_SYNC, 5, _T("Saving NXSL persistent storage"));
          UpdatePStorageDatabase(hdb, watchdogId);
          DBConnectionPoolReleaseConnection(hdb);
       }
       WatchdogStartSleep(watchdogId);
+      nxlog_debug_tag(DEBUG_TAG_SYNC, 7, _T("Syncer run completed"));
    }
 
-   DbgPrintf(1, _T("Syncer thread terminated"));
+   nxlog_debug_tag(DEBUG_TAG_SYNC, 1, _T("Syncer thread terminated"));
    return THREAD_OK;
 }
index 3526f36..c83cd32 100644 (file)
@@ -147,7 +147,7 @@ void Template::destroyItems()
 void Template::setAutoApplyFilter(const TCHAR *filter)
 {
        lockProperties();
-       safe_free(m_applyFilterSource);
+       free(m_applyFilterSource);
        delete m_applyFilter;
        if (filter != NULL)
        {
@@ -168,7 +168,7 @@ void Template::setAutoApplyFilter(const TCHAR *filter)
                m_applyFilterSource = NULL;
                m_applyFilter = NULL;
        }
-       setModified();
+       setModified(MODIFY_OTHER);
        unlockProperties();
 }
 
@@ -270,63 +270,77 @@ bool Template::saveToDatabase(DB_HANDLE hdb)
 {
    lockProperties();
 
-   if (!saveCommonProperties(hdb))
-       {
-               unlockProperties();
-               return FALSE;
-       }
+   bool success = saveCommonProperties(hdb);
 
-       DB_STATEMENT hStmt;
-   if (IsDatabaseRecordExist(hdb, _T("templates"), _T("id"), m_id))
-       {
-               hStmt = DBPrepare(hdb, _T("UPDATE templates SET version=?,apply_filter=? WHERE id=?"));
-       }
-   else
-       {
-               hStmt = DBPrepare(hdb, _T("INSERT INTO templates (version,apply_filter,id) VALUES (?,?,?)"));
-       }
-       if (hStmt == NULL)
-       {
-               unlockProperties();
-               return FALSE;
-       }
+   if (success && (m_modified & MODIFY_OTHER))
+   {
+      DB_STATEMENT hStmt;
+      if (IsDatabaseRecordExist(hdb, _T("templates"), _T("id"), m_id))
+      {
+         hStmt = DBPrepare(hdb, _T("UPDATE templates SET version=?,apply_filter=? WHERE id=?"));
+      }
+      else
+      {
+         hStmt = DBPrepare(hdb, _T("INSERT INTO templates (version,apply_filter,id) VALUES (?,?,?)"));
+      }
+      if (hStmt != NULL)
+      {
+         DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_dwVersion);
+         DBBind(hStmt, 2, DB_SQLTYPE_TEXT, m_applyFilterSource, DB_BIND_STATIC);
+         DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, m_id);
+         success = DBExecute(hStmt);
+         DBFreeStatement(hStmt);
+      }
+      else
+      {
+         success = false;
+      }
+   }
+
+   // Save access list
+   if (success)
+      success = saveACLToDB(hdb);
 
-       DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_dwVersion);
-       DBBind(hStmt, 2, DB_SQLTYPE_TEXT, m_applyFilterSource, DB_BIND_STATIC);
-       DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, m_id);
-       BOOL success = DBExecute(hStmt);
-       DBFreeStatement(hStmt);
+   unlockProperties();
 
-       if (success)
+       if (success && (m_modified & MODIFY_RELATIONS))
        {
-               TCHAR query[256];
-
                // Update members list
-               _sntprintf(query, 256, _T("DELETE FROM dct_node_map WHERE template_id=%d"), m_id);
-               DBQuery(hdb, query);
-               lockChildList(false);
-               for(int i = 0; i < m_childList->size(); i++)
+               success = executeQueryOnObject(hdb, _T("DELETE FROM dct_node_map WHERE template_id=?"));
+      lockChildList(false);
+               if (success && !m_childList->isEmpty())
                {
-                       _sntprintf(query, 256, _T("INSERT INTO dct_node_map (template_id,node_id) VALUES (%d,%d)"), m_id, m_childList->get(i)->getId());
-                       DBQuery(hdb, query);
+                  DB_STATEMENT hStmt = DBPrepare(hdb, _T("INSERT INTO dct_node_map (template_id,node_id) VALUES (?,?)"));
+                  if (hStmt != NULL)
+                  {
+                     DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
+            for(int i = 0; success && (i < m_childList->size()); i++)
+            {
+               DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_childList->get(i)->getId());
+               success = DBExecute(hStmt);
+            }
+            DBFreeStatement(hStmt);
+                  }
+                  else
+                  {
+                     success = false;
+                  }
                }
-               unlockChildList();
-
-               // Save access list
-               saveACLToDB(hdb);
+      unlockChildList();
        }
 
-   unlockProperties();
-
    // Save data collection items
-       lockDciAccess(false);
-   for(int i = 0; i < m_dcObjects->size(); i++)
-      m_dcObjects->get(i)->saveToDatabase(hdb);
-       unlockDciAccess();
+       if (success && (m_modified & MODIFY_DATA_COLLECTION))
+       {
+      lockDciAccess(false);
+      for(int i = 0; success && (i < m_dcObjects->size()); i++)
+         success = m_dcObjects->get(i)->saveToDatabase(hdb);
+      unlockDciAccess();
+       }
 
    // Clear modifications flag
        lockProperties();
-   m_isModified = false;
+   m_modified = 0;
        unlockProperties();
 
    return success;
@@ -426,7 +440,6 @@ bool Template::addDCObject(DCObject *object, bool alreadyLocked)
       if (object->getStatus() != ITEM_STATUS_DISABLED)
          object->setStatus(ITEM_STATUS_ACTIVE, false);
       object->clearBusyFlag();
-      m_isModified = true;
       success = true;
    }
 
@@ -436,7 +449,7 @@ bool Template::addDCObject(DCObject *object, bool alreadyLocked)
        if (success)
        {
                lockProperties();
-      setModified();
+      setModified(MODIFY_DATA_COLLECTION);
                unlockProperties();
        }
    return success;
@@ -482,7 +495,7 @@ bool Template::deleteDCObject(UINT32 dcObjectId, bool needLock)
        if (success)
        {
           lockProperties();
-          setModified(false);
+          setModified(MODIFY_DATA_COLLECTION, false);
           unlockProperties();
        }
    return success;
@@ -555,12 +568,19 @@ bool Template::updateDCObject(UINT32 dwItemId, NXCPMessage *pMsg, UINT32 *pdwNum
                                object->updateFromMessage(pMsg);
                        }
                        success = true;
-                       m_isModified = true;
          break;
       }
        }
 
    unlockDciAccess();
+
+   if (success)
+   {
+      lockProperties();
+      setModified(MODIFY_DATA_COLLECTION);
+      unlockProperties();
+   }
+
    return success;
 }
 
@@ -649,7 +669,7 @@ bool Template::unlockDCIList(int sessionId)
       {
          if (getObjectClass() == OBJECT_TEMPLATE)
             m_dwVersion++;
-         setModified();
+         setModified(MODIFY_OTHER | MODIFY_DATA_COLLECTION);
          callChangeHook = true;
       }
       m_dciListModified = false;
index 53aeee3..9c305bf 100644 (file)
@@ -74,30 +74,38 @@ void UniversalRoot::linkObjects()
  */
 bool UniversalRoot::saveToDatabase(DB_HANDLE hdb)
 {
-   TCHAR szQuery[1024];
-
    lockProperties();
 
-   saveCommonProperties(hdb);
+   bool success = saveCommonProperties(hdb);
+
+   // Save access list
+   if (success)
+      success = saveACLToDB(hdb);
+
+   unlockProperties();
 
    // Update members list
-   _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("DELETE FROM container_members WHERE container_id=%d"), m_id);
-   DBQuery(hdb, szQuery);
-   lockChildList(FALSE);
-   for(int i = 0; i < m_childList->size(); i++)
+   if (success && (m_modified & MODIFY_RELATIONS))
    {
-      _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("INSERT INTO container_members (container_id,object_id) VALUES (%d,%d)"), m_id, m_childList->get(i)->getId());
+      TCHAR szQuery[1024];
+
+      _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("DELETE FROM container_members WHERE container_id=%d"), m_id);
       DBQuery(hdb, szQuery);
+      lockChildList(FALSE);
+      for(int i = 0; success && (i < m_childList->size()); i++)
+      {
+         _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("INSERT INTO container_members (container_id,object_id) VALUES (%d,%d)"), m_id, m_childList->get(i)->getId());
+         success = DBQuery(hdb, szQuery);
+      }
+      unlockChildList();
    }
-   unlockChildList();
-
-   // Save access list
-   saveACLToDB(hdb);
 
    // Unlock object and clear modification flag
+   lockProperties();
+   m_modified = 0;
    unlockProperties();
-   m_isModified = false;
-   return true;
+
+   return success;
 }
 
 /**
index 8d9d7dc..407dc86 100644 (file)
@@ -1,6 +1,6 @@
 /*
 ** NetXMS - Network Management System
-** Copyright (C) 2003-2013 Victor Kirhenshtein
+** Copyright (C) 2003-2017 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -133,53 +133,57 @@ bool VPNConnector::saveToDatabase(DB_HANDLE hdb)
    // Lock object's access
    lockProperties();
 
-   saveCommonProperties(hdb);
+   bool success = saveCommonProperties(hdb);
 
-   // Determine owning node's ID
-   Node *pNode = getParentNode();
-   UINT32 dwNodeId = (pNode != NULL) ? pNode->getId() : 0;
-
-   // Form and execute INSERT or UPDATE query
-   TCHAR szQuery[1024];
-   if (IsDatabaseRecordExist(hdb, _T("vpn_connectors"), _T("id"), m_id))
-      _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("UPDATE vpn_connectors SET node_id=%d,peer_gateway=%d WHERE id=%d"),
-              dwNodeId, m_dwPeerGateway, m_id);
-   else
-      _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("INSERT INTO vpn_connectors (id,node_id,peer_gateway) VALUES (%d,%d,%d)"),
-              m_id, dwNodeId, m_dwPeerGateway);
-   DBQuery(hdb, szQuery);
+   if (success && (m_modified & MODIFY_OTHER))
+   {
+      // Determine owning node's ID
+      Node *pNode = getParentNode();
+      UINT32 dwNodeId = (pNode != NULL) ? pNode->getId() : 0;
+
+      // Form and execute INSERT or UPDATE query
+      TCHAR szQuery[1024];
+      if (IsDatabaseRecordExist(hdb, _T("vpn_connectors"), _T("id"), m_id))
+         _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("UPDATE vpn_connectors SET node_id=%d,peer_gateway=%d WHERE id=%d"),
+                 dwNodeId, m_dwPeerGateway, m_id);
+      else
+         _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("INSERT INTO vpn_connectors (id,node_id,peer_gateway) VALUES (%d,%d,%d)"),
+                 m_id, dwNodeId, m_dwPeerGateway);
+      success = DBQuery(hdb, szQuery);
 
-   // Save network list
-   _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("DELETE FROM vpn_connector_networks WHERE vpn_id=%d"), m_id);
-   DBQuery(hdb, szQuery);
+      // Save network list
+      if (success)
+         success = executeQueryOnObject(hdb, _T("DELETE FROM vpn_connector_networks WHERE vpn_id=?"));
 
-   int i;
-   TCHAR buffer[64];
-   for(i = 0; i < m_localNetworks->size(); i++)
-   {
-      InetAddress *addr = m_localNetworks->get(i);
-      _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR),
-                          _T("INSERT INTO vpn_connector_networks (vpn_id,network_type,ip_addr,ip_netmask) VALUES (%d,0,'%s',%d)"),
-                 (int)m_id, addr->toString(buffer), addr->getMaskBits());
-      DBQuery(hdb, szQuery);
-   }
-   for(i = 0; i < m_remoteNetworks->size(); i++)
-   {
-      InetAddress *addr = m_remoteNetworks->get(i);
-      _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR),
-                               _T("INSERT INTO vpn_connector_networks (vpn_id,network_type,ip_addr,ip_netmask) VALUES (%d,1,'%s',%d)"),
-                 (int)m_id, addr->toString(buffer), addr->getMaskBits());
-      DBQuery(hdb, szQuery);
+      int i;
+      TCHAR buffer[64];
+      for(i = 0; success && (i < m_localNetworks->size()); i++)
+      {
+         InetAddress *addr = m_localNetworks->get(i);
+         _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR),
+                    _T("INSERT INTO vpn_connector_networks (vpn_id,network_type,ip_addr,ip_netmask) VALUES (%d,0,'%s',%d)"),
+                    (int)m_id, addr->toString(buffer), addr->getMaskBits());
+         success = DBQuery(hdb, szQuery);
+      }
+      for(i = 0; success && (i < m_remoteNetworks->size()); i++)
+      {
+         InetAddress *addr = m_remoteNetworks->get(i);
+         _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR),
+                    _T("INSERT INTO vpn_connector_networks (vpn_id,network_type,ip_addr,ip_netmask) VALUES (%d,1,'%s',%d)"),
+                    (int)m_id, addr->toString(buffer), addr->getMaskBits());
+         success = DBQuery(hdb, szQuery);
+      }
    }
 
    // Save access list
-   saveACLToDB(hdb);
+   if (success)
+      success = saveACLToDB(hdb);
 
    // Clear modifications flag and unlock object
-   m_isModified = false;
+   m_modified = 0;
    unlockProperties();
 
-   return true;
+   return success;
 }
 
 /**
index a12e2ea..64cceff 100644 (file)
@@ -115,7 +115,7 @@ bool Zone::saveToDatabase(DB_HANDLE hdb)
    lockProperties();
 
    bool success = saveCommonProperties(hdb);
-   if (success)
+   if (success && (m_modified & MODIFY_OTHER))
    {
       DB_STATEMENT hStmt;
       if (IsDatabaseRecordExist(hdb, _T("zones"), _T("id"), m_id))
@@ -138,12 +138,13 @@ bool Zone::saveToDatabase(DB_HANDLE hdb)
       {
          success = false;
       }
-
-      if (success)
-         success = saveACLToDB(hdb);
    }
+
+   if (success)
+      success = saveACLToDB(hdb);
+
    // Unlock object and clear modification flag
-   m_isModified = false;
+   m_modified = 0;
    unlockProperties();
    return success;
 }
index b564e08..829ea87 100644 (file)
@@ -368,6 +368,23 @@ public:
 #define COLUMN_DEFINITION_MULTIVALUED     0x0002
 
 /**
+ * Object modification flags
+ */
+#define MODIFY_RUNTIME              0x0000
+#define MODIFY_OTHER                0x0001
+#define MODIFY_CUSTOM_ATTRIBUTES    0x0002
+#define MODIFY_DATA_COLLECTION      0x0004
+#define MODIFY_RELATIONS            0x0008
+#define MODIFY_COMMON_PROPERTIES    0x0010
+#define MODIFY_ACCESS_LIST          0x0020
+#define MODIFY_NODE_PROPERTIES      0x0040
+#define MODIFY_INTERFACE_PROPERTIES 0x0080
+#define MODIFIED_CLUSTER_RESOURCES  0x0100
+#define MODIFY_MAP_CONTENT          0x0200
+#define MODIFY_SENSOR_PROPERTIES    0x0400
+#define MODIFY_ALL                  0xFFFF
+
+/**
  * Column definition for DCI summary table
  */
 class NXCORE_EXPORTABLE SummaryTableColumn
@@ -478,7 +495,7 @@ protected:
    UINT32 m_flags;
    UINT32 m_runtimeFlags;
    UINT32 m_state;
-   bool m_isModified;
+   UINT32 m_modified;
    bool m_isDeleted;
    bool m_isHidden;
        bool m_isSystem;
@@ -529,7 +546,7 @@ protected:
    }
    void unlockChildList() { RWLockUnlock(m_rwlockChildList); }
 
-   void setModified(bool notify = true);                  // Used to mark object as modified
+   void setModified(UINT32 flags, bool notify = true);                  // Used to mark object as modified
 
    bool loadACLFromDB(DB_HANDLE hdb);
    bool saveACLToDB(DB_HANDLE hdb);
@@ -569,23 +586,23 @@ public:
        const TCHAR *getComments() const { return CHECK_NULL_EX(m_comments); }
 
        const GeoLocation& getGeoLocation() const { return m_geoLocation; }
-       void setGeoLocation(const GeoLocation& geoLocation) { lockProperties(); m_geoLocation = geoLocation; setModified(); unlockProperties(); }
+       void setGeoLocation(const GeoLocation& geoLocation);
 
    const PostalAddress *getPostalAddress() const { return m_postalAddress; }
-   void setPostalAddress(PostalAddress * addr) { lockProperties(); delete m_postalAddress; m_postalAddress = addr; setModified(); unlockProperties(); }
+   void setPostalAddress(PostalAddress * addr) { lockProperties(); delete m_postalAddress; m_postalAddress = addr; setModified(MODIFY_COMMON_PROPERTIES); unlockProperties(); }
 
    const uuid& getMapImage() { return m_image; }
-   void setMapImage(const uuid& image) { lockProperties(); m_image = image; setModified(); unlockProperties(); }
+   void setMapImage(const uuid& image) { lockProperties(); m_image = image; setModified(MODIFY_COMMON_PROPERTIES); unlockProperties(); }
 
-   bool isModified() const { return m_isModified; }
+   bool isModified() const { return m_modified != 0; }
    bool isDeleted() const { return m_isDeleted; }
    bool isOrphaned() const { return m_parentList->size() == 0; }
    bool isEmpty() const { return m_childList->size() == 0; }
 
        bool isSystem() const { return m_isSystem; }
        void setSystemFlag(bool flag) { m_isSystem = flag; }
-       void setFlag(UINT32 flag) { lockProperties(); m_flags |= flag; setModified(); unlockProperties(); }
-       void clearFlag(UINT32 flag) { lockProperties(); m_flags &= ~flag; setModified(); unlockProperties(); }
+       void setFlag(UINT32 flag) { lockProperties(); m_flags |= flag; setModified(MODIFY_COMMON_PROPERTIES); unlockProperties(); }
+       void clearFlag(UINT32 flag) { lockProperties(); m_flags &= ~flag; setModified(MODIFY_COMMON_PROPERTIES); unlockProperties(); }
 
    UINT32 getRefCount();
    void incRefCount();
@@ -605,7 +622,7 @@ public:
    bool isHidden() { return m_isHidden; }
    void hide();
    void unhide();
-   void markAsModified() { lockProperties(); setModified(); unlockProperties(); }  // external API to mark object as modified
+   void markAsModified(UINT32 flags) { lockProperties(); setModified(flags); unlockProperties(); }  // external API to mark object as modified
 
    virtual bool saveToDatabase(DB_HANDLE hdb);
    virtual bool saveRuntimeData(DB_HANDLE hdb);
@@ -613,10 +630,10 @@ public:
    virtual bool loadFromDatabase(DB_HANDLE hdb, UINT32 id);
    virtual void linkObjects();
 
-   void setId(UINT32 dwId) { m_id = dwId; setModified(); }
+   void setId(UINT32 dwId) { m_id = dwId; setModified(MODIFY_ALL); }
    void generateGuid() { m_guid = uuid::generate(); }
-   void setName(const TCHAR *pszName) { nx_strncpy(m_name, pszName, MAX_OBJECT_NAME); setModified(); }
-   void resetStatus() { m_status = STATUS_UNKNOWN; setModified(); }
+   void setName(const TCHAR *pszName) { lockProperties(); _tcslcpy(m_name, pszName, MAX_OBJECT_NAME); setModified(MODIFY_COMMON_PROPERTIES); unlockProperties(); }
+   void resetStatus() { m_status = STATUS_UNKNOWN; setModified(MODIFY_RUNTIME); }
    void setComments(TCHAR *text);      /* text must be dynamically allocated */
 
    bool isInMaintenanceMode() const { return m_maintenanceMode; }
@@ -918,22 +935,22 @@ public:
 
    void setMacAddr(const BYTE *macAddr, bool updateMacDB);
    void setIpAddress(const InetAddress& addr);
-   void setBridgePortNumber(UINT32 bpn) { m_bridgePortNumber = bpn; setModified(); }
-   void setSlotNumber(UINT32 slot) { m_slotNumber = slot; setModified(); }
-   void setPortNumber(UINT32 port) { m_portNumber = port; setModified(); }
-       void setPhysicalPortFlag(bool isPhysical) { if (isPhysical) m_flags |= IF_PHYSICAL_PORT; else m_flags &= ~IF_PHYSICAL_PORT; setModified(); }
-       void setManualCreationFlag(bool isManual) { if (isManual) m_flags |= IF_CREATED_MANUALLY; else m_flags &= ~IF_CREATED_MANUALLY; setModified(); }
+   void setBridgePortNumber(UINT32 bpn) { m_bridgePortNumber = bpn; setModified(MODIFY_INTERFACE_PROPERTIES); }
+   void setSlotNumber(UINT32 slot) { m_slotNumber = slot; setModified(MODIFY_INTERFACE_PROPERTIES); }
+   void setPortNumber(UINT32 port) { m_portNumber = port; setModified(MODIFY_INTERFACE_PROPERTIES); }
+       void setPhysicalPortFlag(bool isPhysical) { if (isPhysical) m_flags |= IF_PHYSICAL_PORT; else m_flags &= ~IF_PHYSICAL_PORT; setModified(MODIFY_INTERFACE_PROPERTIES); }
+       void setManualCreationFlag(bool isManual) { if (isManual) m_flags |= IF_CREATED_MANUALLY; else m_flags &= ~IF_CREATED_MANUALLY; setModified(MODIFY_INTERFACE_PROPERTIES); }
        void setPeer(Node *node, Interface *iface, LinkLayerProtocol protocol, bool reflection);
-   void clearPeer() { lockProperties(); m_peerNodeId = 0; m_peerInterfaceId = 0; m_peerDiscoveryProtocol = LL_PROTO_UNKNOWN; setModified(); unlockProperties(); }
-   void setDescription(const TCHAR *descr) { lockProperties(); nx_strncpy(m_description, descr, MAX_DB_STRING); setModified(); unlockProperties(); }
-   void setAlias(const TCHAR *alias) { lockProperties(); nx_strncpy(m_alias, alias, MAX_DB_STRING); setModified(); unlockProperties(); }
+   void clearPeer() { lockProperties(); m_peerNodeId = 0; m_peerInterfaceId = 0; m_peerDiscoveryProtocol = LL_PROTO_UNKNOWN; setModified(MODIFY_INTERFACE_PROPERTIES); unlockProperties(); }
+   void setDescription(const TCHAR *descr) { lockProperties(); nx_strncpy(m_description, descr, MAX_DB_STRING); setModified(MODIFY_INTERFACE_PROPERTIES); unlockProperties(); }
+   void setAlias(const TCHAR *alias) { lockProperties(); nx_strncpy(m_alias, alias, MAX_DB_STRING); setModified(MODIFY_INTERFACE_PROPERTIES); unlockProperties(); }
    void addIpAddress(const InetAddress& addr);
    void deleteIpAddress(InetAddress addr);
    void setNetMask(const InetAddress& addr);
-       void setMTU(int mtu) { m_mtu = mtu; setModified(); }
-       void setSpeed(UINT64 speed) { m_speed = speed; setModified(); }
-   void setIfTableSuffix(int len, const UINT32 *suffix) { lockProperties(); safe_free(m_ifTableSuffix); m_ifTableSuffixLen = len; m_ifTableSuffix = (len > 0) ? (UINT32 *)nx_memdup(suffix, len * sizeof(UINT32)) : NULL; setModified(); unlockProperties(); }
-   void setParentInterface(UINT32 parentInterfaceId) { m_parentInterfaceId = parentInterfaceId; setModified(); }
+       void setMTU(int mtu) { m_mtu = mtu; setModified(MODIFY_INTERFACE_PROPERTIES); }
+       void setSpeed(UINT64 speed) { m_speed = speed; setModified(MODIFY_INTERFACE_PROPERTIES); }
+   void setIfTableSuffix(int len, const UINT32 *suffix) { lockProperties(); free(m_ifTableSuffix); m_ifTableSuffixLen = len; m_ifTableSuffix = (len > 0) ? (UINT32 *)nx_memdup(suffix, len * sizeof(UINT32)) : NULL; setModified(MODIFY_INTERFACE_PROPERTIES); unlockProperties(); }
+   void setParentInterface(UINT32 parentInterfaceId) { m_parentInterfaceId = parentInterfaceId; setModified(MODIFY_INTERFACE_PROPERTIES); }
 
        void updateZoneUIN();
 
@@ -1344,7 +1361,7 @@ public:
    Node *getParentNode();
 
        void attachToNode(UINT32 nodeId);
-   void setIpAddress(const InetAddress& addr) { lockProperties(); m_ipAddress = addr; setModified(); unlockProperties(); }
+   void setIpAddress(const InetAddress& addr) { lockProperties(); m_ipAddress = addr; setModified(MODIFY_OTHER); unlockProperties(); }
        void updateRadioInterfaces(const ObjectArray<RadioInterfaceInfo> *ri);
        void updateInfo(const TCHAR *vendor, const TCHAR *model, const TCHAR *serialNumber);
    void updateState(AccessPointState state);
@@ -1828,10 +1845,10 @@ public:
    const TCHAR *getSubType() const { return m_subType; }
 
    UINT32 getCapabilities() { return m_capabilities; }
-   void setCapabilitie(UINT32 flag) { lockProperties(); m_capabilities |= flag; setModified(); unlockProperties(); }
-   void clearCapabilities(UINT32 flag) { lockProperties(); m_capabilities &= ~flag; setModified(); unlockProperties(); }
-   void setLocalMgmtFlag() { m_capabilities |= NC_IS_LOCAL_MGMT; }
-   void clearLocalMgmtFlag() { m_capabilities &= ~NC_IS_LOCAL_MGMT; }
+   void setCapabilities(UINT32 flag) { lockProperties(); m_capabilities |= flag; setModified(MODIFY_NODE_PROPERTIES); unlockProperties(); }
+   void clearCapabilities(UINT32 flag) { lockProperties(); m_capabilities &= ~flag; setModified(MODIFY_NODE_PROPERTIES); unlockProperties(); }
+   void setLocalMgmtFlag() { setCapabilities(NC_IS_LOCAL_MGMT); }
+   void clearLocalMgmtFlag() { clearCapabilities(NC_IS_LOCAL_MGMT); }
 
    void setType(NodeType type, const TCHAR *subType) { lockProperties(); m_type = type; nx_strncpy(m_subType, subType, MAX_NODE_SUBTYPE_LENGTH); unlockProperties(); }