Registry configuration moved into agent database. Created upgrade procedure for agent...
authorTatjana Dubrovica <zev@radensolutions.com>
Wed, 18 May 2016 13:04:20 +0000 (16:04 +0300)
committerTatjana Dubrovica <zev@radensolutions.com>
Wed, 18 May 2016 13:04:28 +0000 (16:04 +0300)
20 files changed:
include/nms_agent.h
src/agent/core/Makefile.am
src/agent/core/datacoll.cpp
src/agent/core/dbupgrade.cpp [new file with mode: 0644]
src/agent/core/localdb.cpp
src/agent/core/localdb.h [new file with mode: 0644]
src/agent/core/nxagentd.cpp
src/agent/core/nxagentd.h
src/agent/core/policy.cpp
src/agent/core/session.cpp
src/agent/libnxagent/bridge.cpp
src/server/core/ap_jobs.cpp
src/server/core/node.cpp
src/server/core/userdb.cpp
src/server/include/nms_objects.h
src/server/include/nxsrvapi.h
src/server/libnxsrv/agent.cpp
src/server/libnxsrv/apinfo.cpp
src/server/tools/nxap/nxap.cpp
src/server/tools/nxdbmgr/nxdbmgr.h

index b90d5c7..354f328 100644 (file)
@@ -652,10 +652,6 @@ bool LIBNXAGENT_EXPORTABLE AgentPushParameterDataDouble(const TCHAR *parameter,
 
 CONDITION LIBNXAGENT_EXPORTABLE AgentGetShutdownCondition();
 bool LIBNXAGENT_EXPORTABLE AgentSleepAndCheckForShutdown(UINT32 sleepTime);
-
-Config LIBNXAGENT_EXPORTABLE *AgentOpenRegistry();
-void LIBNXAGENT_EXPORTABLE AgentCloseRegistry(bool modified);
-
 const TCHAR LIBNXAGENT_EXPORTABLE *AgentGetDataDirectory();
 
 DB_HANDLE LIBNXAGENT_EXPORTABLE AgentGetLocalDatabaseHandle();
index dbc57ac..14fc0da 100644 (file)
@@ -1,8 +1,8 @@
 AM_CPPFLAGS=-I@top_srcdir@/include
 bin_PROGRAMS = nxagentd
 nxagentd_SOURCES = messages.c actions.cpp appagent.cpp comm.cpp config.cpp \
-                   ctrl.cpp datacoll.cpp dcsnmp.cpp epp.cpp exec.cpp \
-                   extagent.cpp getparam.cpp localdb.cpp master.cpp \
+                   ctrl.cpp datacoll.cpp dcsnmp.cpp dbupgrade.cpp epp.cpp \
+                   exec.cpp extagent.cpp getparam.cpp localdb.cpp master.cpp \
                    nxagentd.cpp policy.cpp push.cpp register.cpp sa.cpp \
                    sd.cpp session.cpp snmpproxy.cpp snmptrapproxy.cpp \
                    static_subagents.cpp subagent.cpp sysinfo.cpp tools.cpp \
@@ -37,4 +37,5 @@ EXTRA_DIST = \
     win32.cpp resource.h \
     nxagentd.h \
     hddinfo.cpp \
-    service.cpp
+    service.cpp \
+    localdb.h
index ad98bef..4308fb0 100644 (file)
 void UpdateSnmpTarget(SNMPTarget *target);
 bool GetSnmpValue(const uuid& target, UINT16 port, const TCHAR *oid, TCHAR *value, int interpretRawValue);
 
-/**
- * Database schema version
- */
-#define DATACOLL_SCHEMA_VERSION     3
-
 /**
  * Data collector start indicator
  */
@@ -1118,48 +1113,6 @@ static void LoadState()
    }
 }
 
-/**
- * SQL script array
- */
-static const TCHAR *s_upgradeQueries[] =
-{
-   _T("CREATE TABLE dc_queue (")
-   _T("  server_id number(20) not null,")
-   _T("  dci_id integer not null,")
-   _T("  dci_type integer not null,")
-   _T("  dci_origin integer not null,")
-   _T("  snmp_target_guid varchar(36) not null,")
-   _T("  timestamp integer not null,")
-   _T("  value varchar not null,")
-   _T("  PRIMARY KEY(server_id,dci_id,timestamp))"),
-
-   _T("CREATE TABLE dc_config (")
-   _T("  server_id number(20) not null,")
-   _T("  dci_id integer not null,")
-   _T("  type integer not null,")
-   _T("  origin integer not null,")
-   _T("  name varchar(1023) null,")
-   _T("  polling_interval integer not null,")
-   _T("  last_poll integer not null,")
-   _T("  snmp_port integer not null,")
-   _T("  snmp_target_guid varchar(36) not null,")
-   _T("  snmp_raw_type integer not null,")
-   _T("  PRIMARY KEY(server_id,dci_id))"),
-
-   _T("CREATE TABLE dc_snmp_targets (")
-   _T("  guid varchar(36) not null,")
-   _T("  server_id number(20) not null,")
-   _T("  ip_address varchar(48) not null,")
-   _T("  snmp_version integer not null,")
-   _T("  port integer not null,")
-   _T("  auth_type integer not null,")
-   _T("  enc_type integer not null,")
-   _T("  auth_name varchar(63),")
-   _T("  auth_pass varchar(63),")
-   _T("  enc_pass varchar(63),")
-   _T("  PRIMARY KEY(guid))")
-};
-
 /**
  * Data collector and sender thread handles
  */
@@ -1180,18 +1133,6 @@ void StartLocalDataCollector()
       return;
    }
 
-   INT32 dbVersion = ReadMetadataAsInt(_T("DataCollectionSchemaVersion"));
-   while(dbVersion < DATACOLL_SCHEMA_VERSION)
-   {
-      if (!DBQuery(db, s_upgradeQueries[dbVersion]))
-      {
-         nxlog_write(MSG_DC_DBSCHEMA_UPGRADE_FAILED, NXLOG_ERROR, NULL);
-         return;
-      }
-      dbVersion++;
-      WriteMetadata(_T("DataCollectionSchemaVersion"), dbVersion);
-   }
-
    s_itemLock = MutexCreate();
    s_serverSyncStatusLock = MutexCreate();
 
diff --git a/src/agent/core/dbupgrade.cpp b/src/agent/core/dbupgrade.cpp
new file mode 100644 (file)
index 0000000..bb50800
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+** NetXMS multiplatform core agent
+** Copyright (C) 2016 Raden Solutions
+**
+** 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
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+** File: dbupgrade.cpp
+**
+**/
+
+#include "nxagentd.h"
+
+/**
+ * Execute with error check
+ */
+#define CHK_EXEC(x) do { if (!(x)) if (!g_ignoreAgentDbErrors) return false; } while (0)
+
+bool g_ignoreAgentDbErrors = FALSE;
+
+#define Query(sql) DBQuery(s_db, sql)
+
+/**
+ * Database handle
+ */
+static DB_HANDLE s_db = NULL;
+
+/**
+ * Upgrade from V1 to V2
+ */
+static BOOL H_UpgradeFromV1(int currVersion, int newVersion)
+{
+   //This upgrade contains: \
+     1. check that version and depending on version of DATACOLL_SCHEMA_VERSION apply second or both patchs \
+        move upgrade of data collection database to this function \
+     2. remove DATACOLL_SCHEMA_VERSION from metadata \
+     3. create policy table (guid, type, server, version) unique giud \
+     4. Move policy information from registry to database \
+     5. Create table registry that will store (key, value) unique key \
+     6. Move upgrade file storage pleace from registry to db \
+     7. Delete registry file (remove unused functions for registry)
+
+
+   //Data collection upgrade procedure
+   const TCHAR *s_upgradeQueries[] =
+   {
+      _T("CREATE TABLE dc_queue (")
+      _T("  server_id number(20) not null,")
+      _T("  dci_id integer not null,")
+      _T("  dci_type integer not null,")
+      _T("  dci_origin integer not null,")
+      _T("  snmp_target_guid varchar(36) not null,")
+      _T("  timestamp integer not null,")
+      _T("  value varchar not null,")
+      _T("  PRIMARY KEY(server_id,dci_id,timestamp))"),
+
+      _T("CREATE TABLE dc_config (")
+      _T("  server_id number(20) not null,")
+      _T("  dci_id integer not null,")
+      _T("  type integer not null,")
+      _T("  origin integer not null,")
+      _T("  name varchar(1023) null,")
+      _T("  polling_interval integer not null,")
+      _T("  last_poll integer not null,")
+      _T("  snmp_port integer not null,")
+      _T("  snmp_target_guid varchar(36) not null,")
+      _T("  snmp_raw_type integer not null,")
+      _T("  PRIMARY KEY(server_id,dci_id))"),
+
+      _T("CREATE TABLE dc_snmp_targets (")
+      _T("  guid varchar(36) not null,")
+      _T("  server_id number(20) not null,")
+      _T("  ip_address varchar(48) not null,")
+      _T("  snmp_version integer not null,")
+      _T("  port integer not null,")
+      _T("  auth_type integer not null,")
+      _T("  enc_type integer not null,")
+      _T("  auth_name varchar(63),")
+      _T("  auth_pass varchar(63),")
+      _T("  enc_pass varchar(63),")
+      _T("  PRIMARY KEY(guid))")
+   };
+
+   UINT32 dbVersion = ReadMetadataAsInt(_T("DataCollectionSchemaVersion"));
+   while(dbVersion < 3)
+   {
+      CHK_EXEC(Query(s_upgradeQueries[dbVersion]));
+      dbVersion++;
+   }
+
+   CHK_EXEC(Query(_T("DELETE FROM metadata WHERE attribute='DataCollectionSchemaVersion'")));
+
+   //Policy upgrade procedure
+   TCHAR createPolicyTable[] = _T("CREATE TABLE agent_policy (")
+                              _T("  guid varchar(36) not null,")
+                              _T("  type integer not null,")
+                              _T("  server_info varchar(64) null,")
+                              _T("  server_id number(20) not null,")
+                              _T("  version integer not null,")
+                              _T("  PRIMARY KEY(guid))");
+   CHK_EXEC(Query(createPolicyTable));
+
+   //Create registry table
+   TCHAR crateRegistryTable[] = _T("CREATE TABLE registry (")
+                              _T("  attribute varchar(63) null,")
+                              _T("  value varchar null,")
+                              _T("  PRIMARY KEY(attribute))");
+   CHK_EXEC(Query(crateRegistryTable));
+
+   // Initialize persistent storage
+   bool registryExists = false;
+   Config *registry = new Config;
+       registry->setTopLevelTag(_T("registry"));
+       TCHAR regPath[MAX_PATH];
+       nx_strncpy(regPath, g_szDataDirectory, MAX_PATH - _tcslen(_T("registry.dat")) - 1);
+       if (regPath[_tcslen(regPath) - 1] != FS_PATH_SEPARATOR_CHAR)
+               _tcscat(regPath, FS_PATH_SEPARATOR);
+       _tcscat(regPath, _T("registry.dat"));
+       registryExists = registry->loadXmlConfig(regPath, "registry");
+       if(!registryExists)
+   {
+      DebugPrintf(INVALID_INDEX, 1, _T("Registry file doesn't exist. No data will be moved from registry to database\n"));
+      CHK_EXEC(WriteMetadata(_T("SchemaVersion"), 2));
+      return TRUE;
+   }
+
+   //Move policy data form registry file to agent database
+       ObjectArray<ConfigEntry> *list = registry->getSubEntries(_T("/policyRegistry"), NULL);
+   DB_STATEMENT hStmt = DBPrepare(s_db,
+                 _T("INSERT INTO agent_policy (guid,type,server_info,server_id,version)")
+                 _T(" VALUES (?,?,?,0,0)"));
+       if(hStmt != NULL)
+       {
+          if (list != NULL)
+      {
+         for(int i = 0; i < list->size(); i++)
+         {
+            ConfigEntry *e = list->get(i);
+            uuid_t guid;
+            TCHAR tmp[512];
+
+            if (MatchString(_T("policy-*"), e->getName(), TRUE))
+            {
+               _uuid_parse(&(e->getName()[7]), guid);
+
+               DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, guid);
+               DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, e->getSubEntryValueAsInt(_T("type")));
+               DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, e->getSubEntryValue(_T("server")), DB_BIND_STATIC);
+               CHK_EXEC(DBExecute(hStmt));
+            }
+         }
+         delete list;
+      }
+      DBFreeStatement(hStmt);
+       }
+
+   //Move upgrade file url variable to database
+   const TCHAR* szFullPath = registry->getValue(_T("/upgrade/file"));
+   if(szFullPath != NULL)
+   {
+      TCHAR upgradeFileInsert[256];
+      _sntprintf(upgradeFileInsert, 256, _T("INSERT INTO registry (attribute,value) VALUES ('upgrade.file','%s')"), szFullPath);
+      CHK_EXEC(Query(upgradeFileInsert));
+   }
+   delete registry;
+   //Delete registry file
+   _tremove(regPath);
+
+   CHK_EXEC(WriteMetadata(_T("SchemaVersion"), 2));
+   return TRUE;
+}
+
+/**
+ * Upgrade map
+ */
+static struct
+{
+   int version;
+   int newVersion;
+   BOOL (* fpProc)(int, int);
+} m_dbUpgradeMap[] =
+{
+   { 1, 2, H_UpgradeFromV1 },
+   { 0, 0, NULL }
+};
+
+
+/**
+ * Upgrade database to new version
+ */
+bool UpgradeDatabase()
+{
+   int i;
+   UINT32 version = 0;
+   BOOL bLocked = FALSE;
+   s_db = GetLocalDatabaseHandle();
+
+   // Get database format version
+       version = ReadMetadataAsInt(_T("SchemaVersion"));
+   if (version == DB_SCHEMA_VERSION)
+   {
+      DebugPrintf(INVALID_INDEX, 1, _T("Database format is up to date"));
+   }
+   else if (version > DB_SCHEMA_VERSION)
+   {
+        DebugPrintf(INVALID_INDEX, 1, _T("Your database has format version %d, this agent is compiled for version %d.\n"), version, DB_SCHEMA_VERSION);
+         DebugPrintf(INVALID_INDEX, 1, _T("You need to upgrade your agent before using this database.\n"));
+
+   }
+   else
+   {
+      // Upgrade database
+      while(version < DB_SCHEMA_VERSION)
+      {
+         // Find upgrade procedure
+         for(i = 0; m_dbUpgradeMap[i].fpProc != NULL; i++)
+            if (m_dbUpgradeMap[i].version == version)
+               break;
+         if (m_dbUpgradeMap[i].fpProc == NULL)
+         {
+            DebugPrintf(INVALID_INDEX, 1, _T("Unable to find upgrade procedure for version %d"), version);
+            break;
+         }
+         DebugPrintf(INVALID_INDEX, 1, _T("Upgrading from version %d to %d"), version, m_dbUpgradeMap[i].newVersion);
+         DBBegin(s_db);
+         if (m_dbUpgradeMap[i].fpProc(version, m_dbUpgradeMap[i].newVersion))
+         {
+            DBCommit(s_db);
+            version = ReadMetadataAsInt(_T("SchemaVersion"));
+         }
+         else
+         {
+            DebugPrintf(INVALID_INDEX, 1, _T("Rolling back last stage due to upgrade errors..."));
+            DBRollback(s_db);
+            break;
+         }
+      }
+
+      DebugPrintf(INVALID_INDEX, 1, _T("Database upgrade %s"), (version == DB_SCHEMA_VERSION) ? _T("succeeded") : _T("failed"));
+   }
+   return version == DB_SCHEMA_VERSION;
+}
index 7f9df09..53fd49d 100644 (file)
 
 #include "nxagentd.h"
 
-/**
- * Database schema version
- */
-#define DB_SCHEMA_VERSION     1
-
 /**
  * Database driver
  */
@@ -150,7 +145,7 @@ bool OpenLocalDatabase()
       return false;
    }
 
-   if (!CheckDatabaseStructure())
+   if (!CheckDatabaseStructure() || !UpgradeDatabase())
    {
       DBDisconnect(s_db);
       s_db = NULL;
diff --git a/src/agent/core/localdb.h b/src/agent/core/localdb.h
new file mode 100644 (file)
index 0000000..b12af6f
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+** NetXMS multiplatform core agent
+** Copyright (C) 2016 Raden Solutions
+**
+** 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
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+** File: localdb.h
+**
+**/
+
+
+#ifndef _localdb_h_
+#define _localdb_h_
+
+/**
+ * Database schema version
+ */
+#define DB_SCHEMA_VERSION     2
+
+bool OpenLocalDatabase();
+void CloseLocalDatabase();
+DB_HANDLE GetLocalDatabaseHandle();
+
+TCHAR *ReadMetadata(const TCHAR *attr, TCHAR *buffer);
+INT32 ReadMetadataAsInt(const TCHAR *attr);
+bool WriteMetadata(const TCHAR *name, const TCHAR *value);
+bool WriteMetadata(const TCHAR *name, INT32 value);
+
+bool UpgradeDatabase();
+
+#endif
index b77a9da..52250a8 100644 (file)
@@ -95,8 +95,8 @@ void LIBNXAGENT_EXPORTABLE InitSubAgentAPI(void (* writeLog)(int, int, const TCH
                                            AbstractCommSession *(* findServerSession)(UINT64),
                                            bool (* sendFile)(void *, UINT32, const TCHAR *, long),
                                            bool (* pushData)(const TCHAR *, const TCHAR *, UINT32, time_t),
-                                           void (* saveRegistry)(), DB_HANDLE (* getLocalDatabaseHandle)(),
-                                           CONDITION shutdownCondition, Config *registry, const TCHAR *dataDirectory);
+                                           DB_HANDLE (* getLocalDatabaseHandle)(),
+                                           CONDITION shutdownCondition, const TCHAR *dataDirectory);
 
 /**
  * Messages generated by mc.pl (for UNIX version only)
@@ -202,7 +202,6 @@ static UINT32 s_maxLogSize = 16384 * 1024;
 static UINT32 s_logHistorySize = 4;
 static UINT32 s_logRotationMode = NXLOG_ROTATION_BY_SIZE;
 static TCHAR s_dailyLogFileSuffix[64] = _T("");
-static Config *s_registry = NULL;
 static TCHAR s_executableName[MAX_PATH];
 static UINT32 s_debugLevel = (UINT32)NXCONFIG_UNINITIALIZED_VALUE;
 
@@ -394,36 +393,6 @@ bool ServerInfo::match(const InetAddress &addr)
    return result;
 }
 
-/**
- * Save registry
- */
-static void SaveRegistry()
-{
-       TCHAR regPath[MAX_PATH];
-       nx_strncpy(regPath, g_szDataDirectory, MAX_PATH - _tcslen(REGISTRY_FILE_NAME) - 1);
-       if (regPath[_tcslen(regPath) - 1] != FS_PATH_SEPARATOR_CHAR)
-               _tcscat(regPath, FS_PATH_SEPARATOR);
-       _tcscat(regPath, REGISTRY_FILE_NAME);
-
-       String xml = s_registry->createXml();
-       FILE *f = _tfopen(regPath, _T("w"));
-       if (f != NULL)
-       {
-#ifdef UNICODE
-               char *utf8xml = UTF8StringFromWideString((const WCHAR *)xml);
-               fputs(utf8xml, f);
-               safe_free(utf8xml);
-#else
-               fputs((const char *)xml, f);
-#endif
-               fclose(f);
-       }
-       else
-       {
-               nxlog_write(MSG_REGISTRY_SAVE_FAILED, NXLOG_ERROR, "ss", regPath, _tcserror(errno));
-       }
-}
-
 #ifdef _WIN32
 
 /**
@@ -735,20 +704,6 @@ BOOL Initialize()
               LOGPARSER_AP_FOLDER FS_PATH_SEPARATOR);
    DebugPrintf(INVALID_INDEX, 6, _T("Log parser policy directory: %s"), g_szLogParserDirectory);
        CreateFolder(g_szLogParserDirectory);
-
-       // Initialize persistent storage
-       s_registry = new Config;
-       s_registry->setTopLevelTag(_T("registry"));
-       nx_strncpy(regPath, g_szDataDirectory, MAX_PATH - _tcslen(REGISTRY_FILE_NAME) - 1);
-       if (regPath[_tcslen(regPath) - 1] != FS_PATH_SEPARATOR_CHAR)
-               _tcscat(regPath, FS_PATH_SEPARATOR);
-       _tcscat(regPath, REGISTRY_FILE_NAME);
-       if (!s_registry->loadXmlConfig(regPath, "registry"))
-       {
-               nxlog_write(MSG_REGISTRY_LOAD_FAILED, NXLOG_ERROR, "s", regPath);
-               SaveRegistry();
-       }
-
    CreateFolder(g_szFileStore);
 
 #ifdef _WIN32
@@ -764,7 +719,7 @@ BOOL Initialize()
    // Initialize API for subagents
    s_subAgentsStopCondition = ConditionCreate(TRUE);
    InitSubAgentAPI(WriteSubAgentMsg, SendTrap, SendTrap, EnumerateSessions, FindServerSession,
-      SendFileToServer, PushData, SaveRegistry, GetLocalDatabaseHandle, s_subAgentsStopCondition, s_registry, g_szDataDirectory);
+      SendFileToServer, PushData, GetLocalDatabaseHandle, s_subAgentsStopCondition, g_szDataDirectory);
    DebugPrintf(INVALID_INDEX, 1, _T("Subagent API initialized"));
 
    // Initialize cryptografy
@@ -1036,14 +991,22 @@ BOOL Initialize()
        }
 
        // Delete file used for upgrade if exists
-   Config *registry = AgentOpenRegistry();
-   const TCHAR* szFullPath = registry->getValue(_T("/upgrade/file"));
-   if(szFullPath != NULL)
+       DB_HANDLE hdb = GetLocalDatabaseHandle();
+       if(hdb != NULL)
    {
-      _tremove(szFullPath);
+      DB_RESULT hResult = DBSelect(hdb, _T("SELECT value FROM registry WHERE attribute='upgrade.file'"));
+      if (hResult != NULL && DBGetNumRows(hResult) > 0)
+      {
+         TCHAR upgradeFileAnme[MAX_PATH];
+         DBGetField(hResult, 0, 0, upgradeFileAnme, MAX_PATH);
+         if(upgradeFileAnme != NULL)
+         {
+            _tremove(upgradeFileAnme);
+         }
+         DBQuery(hdb, _T("DELETE FROM registry WHERE attribute='upgrade.file'"));
+         DBFreeResult(hResult);
+      }
    }
-   registry->deleteEntry(_T("/upgrade/file"));
-   AgentCloseRegistry(true);
 
    return TRUE;
 }
index 1255a70..a01ecf7 100644 (file)
@@ -34,6 +34,7 @@
 #include <nxdbapi.h>
 #include "messages.h"
 #include "nxsnmp.h"
+#include "localdb.h"
 
 #ifdef _NETWARE
 #undef SEVERITY_CRITICAL
@@ -84,8 +85,6 @@
 #define AGENT_DEFAULT_DATA_DIR   _T("{default}")
 #endif
 
-#define REGISTRY_FILE_NAME       _T("registry.dat")
-
 
 /**
  * Constants
@@ -584,15 +583,6 @@ SessionAgentConnector *AcquireSessionAgentConnector(const TCHAR *sessionName);
 
 UINT32 GenerateMessageId();
 
-bool OpenLocalDatabase();
-void CloseLocalDatabase();
-DB_HANDLE GetLocalDatabaseHandle();
-
-TCHAR *ReadMetadata(const TCHAR *attr, TCHAR *buffer);
-INT32 ReadMetadataAsInt(const TCHAR *attr);
-bool WriteMetadata(const TCHAR *name, const TCHAR *value);
-bool WriteMetadata(const TCHAR *name, INT32 value);
-
 void ConfigureDataCollection(UINT64 serverId, NXCPMessage *msg);
 
 bool EnumerateSessions(EnumerationCallbackResult (* callback)(AbstractCommSession *, void* ), void *data);
index 094111c..e996b9e 100644 (file)
  */
 static void RegisterPolicy(CommSession *session, UINT32 type, const uuid& guid)
 {
-       TCHAR path[256], buffer[64];
-       int tail;
-
-   _sntprintf(path, 256, POLICY_REGISTRY_PATH _T("/policy-%s/"), guid.toString(buffer));
-       tail = (int)_tcslen(path);
-
-       Config *registry = AgentOpenRegistry();
-
-       _tcscpy(&path[tail], _T("type"));
-       registry->setValue(path, type);
-
-       _tcscpy(&path[tail], _T("server"));
-   registry->setValue(path, session->getServerAddress().toString(buffer));
-
-       AgentCloseRegistry(true);
+   bool isNew = true;
+   TCHAR buffer[64];
+   DB_HANDLE hdb = GetLocalDatabaseHandle();
+       if(hdb != NULL)
+   {
+      DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT * FROM agent_policy WHERE guid=?"));
+      if (hStmt != NULL)
+      {
+         DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, guid);
+         DB_RESULT hResult = DBSelectPrepared(hStmt);
+         if (hResult != NULL)
+         {
+            isNew = DBGetNumRows(hResult) <= 0;
+            DBFreeResult(hResult);
+         }
+         DBFreeStatement(hStmt);
+      }
+
+      if(isNew)
+      {
+         hStmt = DBPrepare(hdb,
+                       _T("INSERT INTO agent_policy (type,server_info,server_id,version, guid)")
+                       _T(" VALUES (?,?,?,0,?)"));
+      }
+      else
+      {
+         hStmt = DBPrepare(hdb,
+                       _T("UPDATE agent_policy SET type=?,server_info=?,server_id=?,version=0")
+                       _T(" WHERE guid=?"));
+      }
+
+      if (hStmt == NULL)
+         return;
+
+      DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, (LONG)type);
+      session->getServerAddress().toString(buffer);
+      DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, buffer, DB_BIND_STATIC);
+      DBBind(hStmt, 3, DB_SQLTYPE_BIGINT, session->getServerId());
+      DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, guid);
+
+      DBExecute(hStmt);
+      DBFreeStatement(hStmt);
+   }
 }
 
 /**
@@ -56,12 +84,20 @@ static void RegisterPolicy(CommSession *session, UINT32 type, const uuid& guid)
  */
 static void UnregisterPolicy(const uuid& guid)
 {
-       TCHAR path[256], buffer[64];
+   DB_HANDLE hdb = GetLocalDatabaseHandle();
+       if(hdb != NULL)
+   {
+      DB_STATEMENT hStmt = DBPrepare(hdb,
+                    _T("DELETE FROM agent_policy WHERE guid=?"));
+
+      if (hStmt == NULL)
+         return;
 
-   _sntprintf(path, 256, POLICY_REGISTRY_PATH _T("/policy-%s"), guid.toString(buffer));
-       Config *registry = AgentOpenRegistry();
-       registry->deleteEntry(path);
-       AgentCloseRegistry(true);
+      DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, guid);
+
+      DBExecute(hStmt);
+      DBFreeStatement(hStmt);
+   }
 }
 
 /**
@@ -69,13 +105,23 @@ static void UnregisterPolicy(const uuid& guid)
  */
 static int GetPolicyType(const uuid& guid)
 {
-       TCHAR path[256], buffer[64];
-       int type;
-
-   _sntprintf(path, 256, POLICY_REGISTRY_PATH _T("/policy-%s/type"), guid.toString(buffer));
-       Config *registry = AgentOpenRegistry();
-       type = registry->getValueAsInt(path, -1);
-       AgentCloseRegistry(false);
+   int type = -1;
+       DB_HANDLE hdb = GetLocalDatabaseHandle();
+       if(hdb != NULL)
+   {
+      DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT type FROM agent_policy WHERE guid=?"));
+          if (hStmt != NULL)
+      {
+         DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, guid);
+         DB_RESULT hResult = DBSelectPrepared(hStmt);
+         if (hResult != NULL)
+         {
+            type = DBGetNumRows(hResult) > 0 ? DBGetFieldULong(hResult, 0, 0) : -1;
+            DBFreeResult(hResult);
+         }
+         DBFreeStatement(hStmt);
+          }
+   }
        return type;
 }
 
@@ -286,33 +332,37 @@ UINT32 UninstallPolicy(CommSession *session, NXCPMessage *request)
  */
 UINT32 GetPolicyInventory(CommSession *session, NXCPMessage *msg)
 {
-       Config *registry = AgentOpenRegistry();
-
-       ObjectArray<ConfigEntry> *list = registry->getSubEntries(_T("/policyRegistry"), NULL);
-       if (list != NULL)
-       {
-               msg->setField(VID_NUM_ELEMENTS, (UINT32)list->size());
-               UINT32 varId = VID_ELEMENT_LIST_BASE;
-               for(int i = 0; i < list->size(); i++, varId += 7)
-               {
-                       ConfigEntry *e = list->get(i);
-                       uuid_t guid;
-
-                       if (MatchString(_T("policy-*"), e->getName(), TRUE))
-                       {
-                               _uuid_parse(&(e->getName()[7]), guid);
-                               msg->setField(varId++, guid, UUID_LENGTH);
-                               msg->setField(varId++, (WORD)e->getSubEntryValueAsInt(_T("type")));
-                               msg->setField(varId++, e->getSubEntryValue(_T("server")));
-                       }
-               }
-               delete list;
-       }
-       else
-       {
-               msg->setField(VID_NUM_ELEMENTS, (UINT32)0);
-       }
-
-       AgentCloseRegistry(false);
-       return RCC_SUCCESS;
+   UINT32 success = RCC_DB_FAILURE;
+       DB_HANDLE hdb = GetLocalDatabaseHandle();
+       if(hdb != NULL)
+   {
+      DB_RESULT hResult = DBSelect(hdb, _T("SELECT guid,type,server_info,server_id,version FROM agent_policy"));
+      if (hResult != NULL)
+      {
+         int count = DBGetNumRows(hResult);
+         if(count > 0 )
+         {
+            msg->setField(VID_NUM_ELEMENTS, (UINT32)count);
+         }
+         else
+            msg->setField(VID_NUM_ELEMENTS, (UINT32)0);
+
+         UINT32 varId = VID_ELEMENT_LIST_BASE;
+         for(int row = 0; row < count; row++, varId += 5)
+         {
+                               msg->setField(varId++, DBGetFieldGUID(hResult, row, 0));
+                               msg->setField(varId++, DBGetFieldULong(hResult, row, 1));
+                               TCHAR *text = DBGetField(hResult, row, 2, NULL, 0);
+                               msg->setField(varId++, CHECK_NULL_EX(text));
+                               free(text);
+                               msg->setField(varId++, DBGetFieldInt64(hResult, row, 3));
+                               msg->setField(varId++, DBGetFieldULong(hResult, row, 4));
+
+         }
+         DBFreeResult(hResult);
+      }
+      success = RCC_SUCCESS;
+   }
+
+       return success;
 }
index 4bc3153..bc22abf 100644 (file)
@@ -917,9 +917,13 @@ UINT32 CommSession::upgrade(NXCPMessage *pRequest)
       BuildFullPath(szPkgName, szFullPath);
 
       //Create line in registry file with upgrade file name to delete it after system start
-      Config *registry = AgentOpenRegistry();
-      registry->setValue(_T("/upgrade/file"), szFullPath);
-      AgentCloseRegistry(true);
+      DB_HANDLE hdb = GetLocalDatabaseHandle();
+      if(hdb != NULL)
+      {
+         TCHAR upgradeFileInsert[256];
+         _sntprintf(upgradeFileInsert, 256, _T("INSERT INTO registry (attribute,value) VALUES ('upgrade.file',%s)"), szPkgName);
+         DBQuery(hdb, upgradeFileInsert);
+      }
 
       return UpgradeAgent(szFullPath);
    }
index 84cdd76..b173d31 100644 (file)
@@ -33,8 +33,6 @@ static bool (* s_fpEnumerateSessions)(EnumerationCallbackResult (*)(AbstractComm
 static bool (* s_fpSendFile)(void *, UINT32, const TCHAR *, long) = NULL;
 static bool (* s_fpPushData)(const TCHAR *, const TCHAR *, UINT32, time_t) = NULL;
 static CONDITION s_agentShutdownCondition = INVALID_CONDITION_HANDLE;
-static Config *s_registry = NULL;
-static void (* s_fpSaveRegistry)() = NULL;
 static const TCHAR *s_dataDirectory = NULL;
 static DB_HANDLE (*s_fpGetLocalDatabaseHandle)() = NULL;
 
@@ -48,8 +46,8 @@ void LIBNXAGENT_EXPORTABLE InitSubAgentAPI(void (* writeLog)(int, int, const TCH
                                            AbstractCommSession *(* findServerSession)(UINT64),
                                            bool (* sendFile)(void *, UINT32, const TCHAR *, long),
                                            bool (* pushData)(const TCHAR *, const TCHAR *, UINT32, time_t),
-                                           void (* saveRegistry)(), DB_HANDLE (* getLocalDatabaseHandle)(),
-                                           CONDITION shutdownCondition, Config *registry, const TCHAR *dataDirectory)
+                                           DB_HANDLE (* getLocalDatabaseHandle)(),
+                                           CONDITION shutdownCondition, const TCHAR *dataDirectory)
 {
    s_fpWriteLog = writeLog;
        s_fpSendTrap1 = sendTrap1;
@@ -58,9 +56,7 @@ void LIBNXAGENT_EXPORTABLE InitSubAgentAPI(void (* writeLog)(int, int, const TCH
    s_fpFindServerSession = findServerSession;
        s_fpSendFile = sendFile;
        s_fpPushData = pushData;
-   s_fpSaveRegistry = saveRegistry;
    s_agentShutdownCondition = shutdownCondition;
-   s_registry = registry;
    s_dataDirectory = dataDirectory;
    s_fpGetLocalDatabaseHandle = getLocalDatabaseHandle;
 }
@@ -257,28 +253,6 @@ bool LIBNXAGENT_EXPORTABLE AgentSleepAndCheckForShutdown(UINT32 sleepTime)
    return ConditionWait(s_agentShutdownCondition, sleepTime);
 }
 
-/**
- * Open registry
- */
-Config LIBNXAGENT_EXPORTABLE *AgentOpenRegistry()
-{
-       s_registry->lock();
-       return s_registry;
-}
-
-/**
- * Close registry
- */
-void LIBNXAGENT_EXPORTABLE AgentCloseRegistry(bool modified)
-{
-       if (modified)
-   {
-      if (s_fpSaveRegistry != NULL)
-                  s_fpSaveRegistry();
-   }
-       s_registry->unlock();
-}
-
 /**
  * Get data directory
  */
index 6dc245a..ab5d71f 100644 (file)
@@ -129,7 +129,7 @@ ServerJobResult PolicyDeploymentJob::run()
    _sntprintf(jobName, 1024, _T("Deploy policy %s"), m_policy->getName());
 
    setDescription(jobName);
-   AgentConnectionEx *conn = m_node->createAgentConnection();
+   AgentConnectionEx *conn = m_node->createAgentConnection(true);
    if (conn != NULL)
    {
       UINT32 rcc = conn->deployPolicy(m_policy);
index 6e4d293..37d91b9 100644 (file)
@@ -3616,7 +3616,7 @@ bool Node::connectToAgent(UINT32 *error, UINT32 *socketError, bool *newConnectio
    m_agentConnection->setAuthData(m_agentAuthMethod, m_szSharedSecret);
    setAgentProxy(m_agentConnection);
        DbgPrintf(7, _T("Node::connectToAgent(%s [%d]): calling connect on port %d"), m_name, m_id, (int)m_agentPort);
-   bool success = m_agentConnection->connect(g_pServerKey, FALSE, error, socketError);
+   bool success = m_agentConnection->connect(g_pServerKey, FALSE, error, socketError, g_serverId);
    if (success)
        {
                m_agentConnection->setCommandTimeout(g_agentCommandTimeout);
@@ -5121,7 +5121,7 @@ void Node::checkOSPFSupport(SNMP_Transport *pTransport)
 /**
  * Create ready to use agent connection
  */
-AgentConnectionEx *Node::createAgentConnection()
+AgentConnectionEx *Node::createAgentConnection(bool sendServerId)
 {
    AgentConnectionEx *conn;
 
@@ -5133,7 +5133,7 @@ AgentConnectionEx *Node::createAgentConnection()
 
    conn = new AgentConnectionEx(m_id, m_ipAddress, m_agentPort, m_agentAuthMethod, m_szSharedSecret);
    setAgentProxy(conn);
-   if (!conn->connect(g_pServerKey))
+   if (!conn->connect(g_pServerKey, FALSE, NULL, NULL, sendServerId ? g_serverId : 0))
    {
       conn->decRefCount();
       conn = NULL;
index 0583778..b58a1cd 100644 (file)
@@ -660,7 +660,7 @@ void RemoveDeletedLDAPEntries(StringObjectMap<Entry> *entryList, UINT32 m_action
             }
             else if (m_action == USER_DISABLE)
             {
-               DbgPrintf(4, _T("RemoveDeletedLDAPEntry(): LDAP %s object %s was unlinked form user database"), isUser ? _T("user") : _T("group"), object->getDn());
+               DbgPrintf(4, _T("RemoveDeletedLDAPEntry(): LDAP %s object %s was disabled"), isUser ? _T("user") : _T("group"), object->getDn());
                object->disable();
                object->setDescription(_T("LDAP entry was deleted."));
             }
index 38aafa9..30dd481 100644 (file)
@@ -1516,7 +1516,7 @@ public:
    void openTableList(ObjectArray<AgentTableDefinition> **tableList);
    void closeTableList() { unlockProperties(); }
 
-   AgentConnectionEx *createAgentConnection();
+   AgentConnectionEx *createAgentConnection(bool sendServerId = false);
    AgentConnectionEx *acquireSnmpProxyConnection();
        SNMP_Transport *createSnmpTransport(WORD port = 0, const TCHAR *context = NULL);
        SNMP_SecurityContext *getSnmpSecurityContext();
index 41091a1..75cea86 100644 (file)
@@ -372,7 +372,9 @@ private:
        int m_size;
        BYTE *m_guidList;
        int *m_typeList;
-       TCHAR **m_serverList;
+   TCHAR **m_serverInfoList;
+       UINT64 *m_serverIdList;
+       int *m_version;
 
 public:
        AgentPolicyInfo(NXCPMessage *msg);
@@ -381,7 +383,9 @@ public:
        int size() { return m_size; }
        uuid getGuid(int index);
        int getType(int index) { return ((index >= 0) && (index < m_size)) ? m_typeList[index] : -1; }
-       const TCHAR *getServer(int index) { return ((index >= 0) && (index < m_size)) ? m_serverList[index] : NULL; }
+       const TCHAR *getServerInfo(int index) { return ((index >= 0) && (index < m_size)) ? m_serverInfoList[index] : NULL; }
+       UINT64 getServerId(int index) { return ((index >= 0) && (index < m_size)) ? m_serverIdList[index] : -1; }
+       int getVersion(int index) { return ((index >= 0) && (index < m_size)) ? m_version[index] : -1; }
 };
 
 /**
@@ -529,7 +533,7 @@ public:
    void incRefCount() { InterlockedIncrement(&m_userRefCount); }
    void decRefCount() { if (InterlockedDecrement(&m_userRefCount) == 0) { disconnect(); decInternalRefCount(); } }
 
-   bool connect(RSA *pServerKey = NULL, BOOL bVerbose = FALSE, UINT32 *pdwError = NULL, UINT32 *pdwSocketError = NULL);
+   bool connect(RSA *pServerKey = NULL, BOOL bVerbose = FALSE, UINT32 *pdwError = NULL, UINT32 *pdwSocketError = NULL, UINT64 serverId = 0);
    void disconnect();
    bool isConnected() { return m_isConnected; }
        int getProtocolVersion() { return m_nProtocolVersion; }
index 59fbb04..26eb4e2 100644 (file)
@@ -433,7 +433,7 @@ void AgentConnection::receiverThread()
 /**
  * Connect to agent
  */
-bool AgentConnection::connect(RSA *pServerKey, BOOL bVerbose, UINT32 *pdwError, UINT32 *pdwSocketError)
+bool AgentConnection::connect(RSA *pServerKey, BOOL bVerbose, UINT32 *pdwError, UINT32 *pdwSocketError, UINT64 serverId)
 {
    TCHAR szBuffer[256];
    bool success = false;
@@ -564,6 +564,9 @@ setup_encryption:
       goto setup_encryption;
    }
 
+   if(serverId != 0)
+      setServerId(serverId);
+
    success = true;
    dwError = ERR_SUCCESS;
 
index cab7d94..1ad489c 100644 (file)
@@ -32,21 +32,27 @@ AgentPolicyInfo::AgentPolicyInfo(NXCPMessage *msg)
        {
                m_guidList = (BYTE *)malloc(UUID_LENGTH * m_size);
                m_typeList = (int *)malloc(sizeof(int) * m_size);
-               m_serverList = (TCHAR **)malloc(sizeof(TCHAR *) * m_size);
+               m_serverIdList = (UINT64*)malloc(sizeof(UINT64) * m_size);
+               m_serverInfoList = (TCHAR **)malloc(sizeof(TCHAR *) * m_size);
+               m_version = (int *)malloc(sizeof(int) * m_size);
 
                UINT32 varId = VID_ELEMENT_LIST_BASE;
-               for(int i = 0; i < m_size; i++, varId += 7)
+               for(int i = 0; i < m_size; i++, varId += 5)
                {
                        msg->getFieldAsBinary(varId++, &m_guidList[i * UUID_LENGTH], UUID_LENGTH);
-                       m_typeList[i] = (int)msg->getFieldAsUInt16(varId++);
-                       m_serverList[i] = msg->getFieldAsString(varId++);
+                       m_typeList[i] = (int)msg->getFieldAsUInt32(varId++);
+                       m_serverInfoList[i] = msg->getFieldAsString(varId++);
+                       m_serverIdList[i] = msg->getFieldAsUInt64(varId++);
+                       m_version[i] = (int)msg->getFieldAsUInt32(varId++);
                }
        }
        else
        {
                m_guidList = NULL;
                m_typeList = NULL;
-               m_serverList = NULL;
+               m_serverInfoList = NULL;
+               m_serverIdList = NULL;
+               m_version = NULL;
        }
 }
 
@@ -55,11 +61,12 @@ AgentPolicyInfo::AgentPolicyInfo(NXCPMessage *msg)
  */
 AgentPolicyInfo::~AgentPolicyInfo()
 {
-       for(int i = 0; i < m_size; i++)
-               safe_free(m_serverList[i]);
-       safe_free(m_serverList);
-       safe_free(m_typeList);
-       safe_free(m_guidList);
+   for(int i = 0; i < m_size; i++)
+               free(m_serverInfoList[i]);
+       free(m_serverIdList);
+       free(m_typeList);
+       free(m_guidList);
+       free(m_version);
 }
 
 /**
index f084bed..6aab77e 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
 ** nxap - command line tool used to manage agent policies
 ** Copyright (C) 2010-2015 Victor Kirhenshtein
 **
@@ -38,12 +38,12 @@ static int GetPolicyInventory(AgentConnection *conn)
        UINT32 rcc = conn->getPolicyInventory(&ap);
        if (rcc == ERR_SUCCESS)
        {
-               _tprintf(_T("GUID                                 Type Server\n")
-                        _T("----------------------------------------------------------\n"));
+               _tprintf(_T("GUID                                 Type ServerInfo                                                       ServerId         Version\n")
+                        _T("-----------------------------------------------------------------------------------------------------------------------------------\n"));
                for(int i = 0; i < ap->size(); i++)
                {
                   TCHAR buffer[64];
-                       _tprintf(_T("%-16s %-4d %s\n"), ap->getGuid(i).toString(buffer), ap->getType(i), ap->getServer(i));
+                       _tprintf(_T("%-16s %-4d %-64s ") UINT64X_FMT(_T("016")) _T(" %-3d\n"), ap->getGuid(i).toString(buffer), ap->getType(i), ap->getServerInfo(i), ap->getServerId(i), ap->getVersion(i));
                }
                delete ap;
        }
@@ -132,7 +132,7 @@ int main(int argc, char *argv[])
                      _T("   -v           : Display version and exit.\n")
                      _T("   -w <seconds> : Set command timeout (default is 5 seconds)\n")
                      _T("   -W <seconds> : Set connection timeout (default is 30 seconds)\n")
-                     _T("\n"), 
+                     _T("\n"),
 #ifdef _WITH_ENCRYPTION
                      szKeyFile,
 #endif
index 4379e1f..5255160 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
 ** nxdbmgr - NetXMS database manager
 ** Copyright (C) 2004-2016 Victor Kirhenshtein
 **