Refactored code for SNMP traps and NXSL scripts and implemented guids for both objects.
authorEriks Jenkevics <eriks@netxms.org>
Tue, 21 Feb 2017 16:33:14 +0000 (18:33 +0200)
committerEriks Jenkevics <eriks@netxms.org>
Tue, 28 Feb 2017 10:49:31 +0000 (12:49 +0200)
24 files changed:
include/netxms-version.h
include/netxmsdb.h
include/nms_cscp.h
include/nxcldefs.h
include/nxsl_classes.h
sql/schema.in
sql/scripts.in
sql/traps.in
src/java/client/netxms-base/src/main/java/org/netxms/base/NXCPCodes.java
src/java/client/netxms-client/src/main/java/org/netxms/client/NXCSession.java
src/java/client/netxms-client/src/main/java/org/netxms/client/ProtocolVersion.java
src/java/client/netxms-client/src/main/java/org/netxms/client/Script.java
src/java/client/netxms-client/src/main/java/org/netxms/client/snmp/SnmpTrap.java
src/java/client/netxms-client/src/main/java/org/netxms/client/snmp/SnmpTrapParameterMapping.java
src/java/netxms-eclipse/SNMP/src/org/netxms/ui/eclipse/snmp/dialogs/ParamMappingEditDialog.java
src/libnxsl/env.cpp
src/libnxsl/library.cpp
src/server/core/console.cpp
src/server/core/import.cpp
src/server/core/script.cpp
src/server/core/session.cpp
src/server/core/snmptrap.cpp
src/server/include/nms_core.h
src/server/tools/nxdbmgr/upgrade.cpp

index 15892b2..d912b09 100644 (file)
@@ -48,7 +48,7 @@
 #define CLIENT_PROTOCOL_VERSION_PUSH      1     /* Data push API */
 #define CLIENT_PROTOCOL_VERSION_TRAP      1     /* Event (trap) sending API */
 #define CLIENT_PROTOCOL_VERSION_MOBILE    1     /* All functionality relevant for mobile client */
-#define CLIENT_PROTOCOL_VERSION_FULL      7     /* All functionality */
+#define CLIENT_PROTOCOL_VERSION_FULL      8     /* All functionality */
 
 /**
  * Protocol version positions
index c08a7ff..6bb25e5 100644 (file)
@@ -23,6 +23,6 @@
 #ifndef _netxmsdb_h
 #define _netxmsdb_h
 
-#define DB_FORMAT_VERSION   437
+#define DB_FORMAT_VERSION   438
 
 #endif
index 671f825..8890665 100644 (file)
@@ -1166,6 +1166,7 @@ typedef struct
 #define VID_HOSTNAME                ((UINT32)569)
 #define VID_ENABLE_COMPRESSION      ((UINT32)570)
 #define VID_AGENT_COMPRESSION_MODE  ((UINT32)571)
+#define VID_TRAP_TYPE               ((UINT32)572)
 
 // Base variabe for single threshold in message
 #define VID_THRESHOLD_BASE          ((UINT32)0x00800000)
@@ -1197,7 +1198,8 @@ typedef struct
 #define VID_EVENT_ARG_LAST          ((UINT32)0x00008FFF)
 
 // Variable range for trap parameter list
-#define VID_TRAP_PLEN_BASE          ((UINT32)0x00009000)
+#define VID_TRAP_PBASE              ((UINT32)0x00009000)
+/* Unused
 #define VID_TRAP_PLEN_LAST          ((UINT32)0x000093FF)
 #define VID_TRAP_PNAME_BASE         ((UINT32)0x00009400)
 #define VID_TRAP_PNAME_LAST         ((UINT32)0x000097FF)
@@ -1205,6 +1207,7 @@ typedef struct
 #define VID_TRAP_PDESCR_LAST        ((UINT32)0x00009BFF)
 #define VID_TRAP_PFLAGS_BASE        ((UINT32)0x00009C00)
 #define VID_TRAP_PFLAGS_LAST        ((UINT32)0x00009FFF)
+*/
 
 // Object information can contain variable number of parent and child objects' ids.
 // Because each variable in message have to have unique identifier,
index ef04f3d..7f94e69 100644 (file)
@@ -25,6 +25,7 @@
 #define _nxcldefs_h_
 
 #include <nxlog.h>
+#include <uuid.h>
 
 /**
  * Some constants
@@ -1078,32 +1079,6 @@ typedef struct
 } NXC_ALARM;
 
 /**
- * Trap parameter mapping entry
- */
-typedef struct
-{
-   UINT32 *pdwObjectId;     // Trap OID
-   UINT32 dwOidLen;         // Trap OID length (if highest bit is set, then it's a position)
-       UINT32 dwFlags;
-   TCHAR szDescription[MAX_DB_STRING];
-} NXC_OID_MAP;
-
-/**
- * Trap configuration entry
- */
-typedef struct
-{
-   UINT32 dwId;             // Entry ID
-   UINT32 *pdwObjectId;     // Trap OID
-   UINT32 dwOidLen;         // Trap OID length
-   UINT32 dwEventCode;      // Event code
-   UINT32 dwNumMaps;        // Number of parameter mappings
-   NXC_OID_MAP *pMaps;
-   TCHAR szDescription[MAX_DB_STRING];
-       TCHAR szUserTag[MAX_USERTAG_LENGTH];
-} NXC_TRAP_CFG_ENTRY;
-
-/**
  * Condition's input DCI definition
  */
 typedef struct
index 13a2336..a582449 100644 (file)
@@ -27,7 +27,6 @@
 #include <nms_util.h>
 #include <nxcpapi.h>
 
-
 //
 // Constants
 //
@@ -654,15 +653,45 @@ public:
 };
 
 /**
+ * NXSL Script
+ */
+class LIBNXSL_EXPORTABLE NXSL_LibraryScript
+{
+protected:
+   UINT32 m_id;
+   uuid m_guid;
+   TCHAR m_name[1024];
+   TCHAR *m_source;
+   NXSL_Program *m_program;
+   TCHAR m_error[1024];
+
+public:
+   NXSL_LibraryScript();
+   NXSL_LibraryScript(UINT32 id, uuid guid, const TCHAR *name, TCHAR *source);
+   ~NXSL_LibraryScript();
+
+   bool isValid() const { return m_program != NULL; }
+
+   const uuid& getGuid() { return m_guid; }
+   UINT32 getId() { return m_id; }
+
+   const TCHAR *getName() { return m_name; }
+   const TCHAR *getCode() { return m_source; }
+   const TCHAR *getError() { return m_error; }
+
+   NXSL_Program *getProgram() { return m_program; }
+
+   void fillMessage(NXCPMessage *msg, UINT32 base);
+   void fillMessage(NXCPMessage *msg);
+};
+
+/**
  * Script library
  */
 class LIBNXSL_EXPORTABLE NXSL_Library
 {
 private:
-   UINT32 m_dwNumScripts;
-   NXSL_Program **m_ppScriptList;
-   TCHAR **m_ppszNames;
-   UINT32 *m_pdwIdList;
+   ObjectArray<NXSL_LibraryScript> *m_scriptList;
    MUTEX m_mutex;
 
    void deleteInternal(int nIndex);
@@ -674,13 +703,14 @@ public:
    void lock() { MutexLock(m_mutex); }
    void unlock() { MutexUnlock(m_mutex); }
 
-   BOOL addScript(UINT32 dwId, const TCHAR *pszName, NXSL_Program *pScript);
+   BOOL addScript(NXSL_LibraryScript *script);
    void deleteScript(const TCHAR *name);
    void deleteScript(UINT32 id);
-   NXSL_Program *findScript(const TCHAR *name);
+   NXSL_Program *findNxslProgram(const TCHAR *name);
+   NXSL_LibraryScript *findScript(UINT32 id);
    NXSL_VM *createVM(const TCHAR *name, NXSL_Environment *env);
 
-   void fillMessage(NXCPMessage *pMsg);
+   void fillMessage(NXCPMessage *msg);
 };
 
 /**
index a40c62b..ea87a0e 100644 (file)
@@ -1571,6 +1571,7 @@ COMMENT_COLUMN(alarm_category_map.category_id, 'Category ID')
 
 CREATE TABLE snmp_trap_cfg
 (
+  guid varchar(36) not null,
   trap_id integer not null,
   snmp_oid varchar(255),
   event_code integer not null,
@@ -1580,6 +1581,7 @@ CREATE TABLE snmp_trap_cfg
 ) TABLE_TYPE;
 
 COMMENT_TABLE(snmp_trap_cfg, '')
+COMMENT_COLUMN(snmp_trap_cfg.guid, '')
 COMMENT_COLUMN(snmp_trap_cfg.trap_id, '')
 COMMENT_COLUMN(snmp_trap_cfg.snmp_oid, '')
 COMMENT_COLUMN(snmp_trap_cfg.event_code, '')
@@ -1754,6 +1756,7 @@ COMMENT_COLUMN(syslog.msg_text, '')
 */
 CREATE TABLE script_library
 (
+  guid varchar(36) not null,
   script_id integer not null,
   script_name varchar(255) not null,
   script_code SQL_TEXT null,
@@ -1761,6 +1764,7 @@ CREATE TABLE script_library
 ) TABLE_TYPE;
 
 COMMENT_TABLE(script_library, '')
+COMMENT_COLUMN(script_library.guid, '')
 COMMENT_COLUMN(script_library.script_id, '')
 COMMENT_COLUMN(script_library.script_name, '')
 COMMENT_COLUMN(script_library.script_code, '')
index 909de27..b757b79 100644 (file)
@@ -4,25 +4,25 @@
 ** ex: syntax=sql
 */
 
-INSERT INTO script_library (script_id,script_name,script_code)
-       VALUES (1,'Filter::SNMP','return $1->isSNMP;' CONCAT CRLF);
-INSERT INTO script_library (script_id,script_name,script_code)
-       VALUES (2,'Filter::Agent','return $1->isAgent;' CONCAT CRLF);
-INSERT INTO script_library (script_id,script_name,script_code)
-       VALUES (3,'Filter::AgentOrSNMP','return $1->isAgent || $1->isSNMP;' CONCAT CRLF);
+INSERT INTO script_library (guid,script_id,script_name,script_code)
+       VALUES ('3b7bddce-3505-42ff-ac60-6a48a64bd0ae',1,'Filter::SNMP','return $1->isSNMP;' CONCAT CRLF);
+INSERT INTO script_library (guid,script_id,script_name,script_code)
+       VALUES ('2fb9212b-97e6-40e7-b434-2df4f7e8f6aa',2,'Filter::Agent','return $1->isAgent;' CONCAT CRLF);
+INSERT INTO script_library (guid,script_id,script_name,script_code)
+       VALUES ('38696a00-c519-438c-8cbd-4b3a0cba4af1',3,'Filter::AgentOrSNMP','return $1->isAgent || $1->isSNMP;' CONCAT CRLF);
 
-INSERT INTO script_library (script_id,script_name,script_code)
-       VALUES (4,'DCI::SampleTransform','sub dci_transform()' CONCAT CRLF CONCAT '{' CONCAT CRLF CONCAT '   return $1 + 1;' CONCAT CRLF CONCAT '}' CONCAT CRLF);
+INSERT INTO script_library (guid,script_id,script_name,script_code)
+       VALUES ('efe50915-47b2-43d8-b4f4-2c09a44970c3',4,'DCI::SampleTransform','sub dci_transform()' CONCAT CRLF CONCAT '{' CONCAT CRLF CONCAT '   return $1 + 1;' CONCAT CRLF CONCAT '}' CONCAT CRLF);
 
-INSERT INTO script_library (script_id,script_name,script_code)
-       VALUES (11,'Hook::StatusPoll','/* Available global variables:' CONCAT CRLF CONCAT ' *  $node - current node, object of ''Node'' type' CONCAT CRLF CONCAT ' *' CONCAT CRLF CONCAT ' * Expected return value:' CONCAT CRLF CONCAT ' *  none - returned value is ignored' CONCAT CRLF CONCAT ' */' CONCAT CRLF);
-INSERT INTO script_library (script_id,script_name,script_code)
-       VALUES (12,'Hook::ConfigurationPoll','/* Available global variables:' CONCAT CRLF CONCAT ' *  $node - current node, object of ''Node'' type' CONCAT CRLF CONCAT ' *' CONCAT CRLF CONCAT ' * Expected return value:' CONCAT CRLF CONCAT ' *  none - returned value is ignored' CONCAT CRLF CONCAT ' */' CONCAT CRLF);
-INSERT INTO script_library (script_id,script_name,script_code)
-       VALUES (13,'Hook::InstancePoll','/* Available global variables:' CONCAT CRLF CONCAT ' *  $node - current node, object of ''Node'' type' CONCAT CRLF CONCAT ' *' CONCAT CRLF CONCAT ' * Expected return value:' CONCAT CRLF CONCAT ' *  none - returned value is ignored' CONCAT CRLF CONCAT ' */' CONCAT CRLF);
-INSERT INTO script_library (script_id,script_name,script_code)
-       VALUES (14,'Hook::TopologyPoll','/* Available global variables:' CONCAT CRLF CONCAT ' *  $node - current node, object of ''Node'' type' CONCAT CRLF CONCAT ' *' CONCAT CRLF CONCAT ' * Expected return value:' CONCAT CRLF CONCAT ' *  none - returned value is ignored' CONCAT CRLF CONCAT ' */' CONCAT CRLF);
-INSERT INTO script_library (script_id,script_name,script_code)
-       VALUES (15,'Hook::CreateInterface','/* Available global variables:' CONCAT CRLF CONCAT ' *  $node - current node, object of ''Node'' type' CONCAT CRLF CONCAT ' *  $1 - current interface, object of ''Interface'' type' CONCAT CRLF CONCAT ' *' CONCAT CRLF CONCAT ' * Expected return value:' CONCAT CRLF CONCAT ' *  true/false - boolean - whether interface should be created' CONCAT CRLF CONCAT ' */' CONCAT CRLF CONCAT 'return true;' CONCAT CRLF);
-INSERT INTO script_library (script_id,script_name,script_code)
-       VALUES (16,'Hook::AcceptNewNode','/* Available global variables:' CONCAT CRLF CONCAT ' *  $ipAddr - IP address of the node being processed' CONCAT CRLF CONCAT ' *  $ipNetMask - netmask of the node being processed' CONCAT CRLF CONCAT ' *  $macAddr - MAC address of the node being processed' CONCAT CRLF CONCAT ' *  $zoneId - zone ID of the node being processed' CONCAT CRLF CONCAT ' *' CONCAT CRLF CONCAT ' * Expected return value:' CONCAT CRLF CONCAT ' *  true/false - boolean - whether node should be created' CONCAT CRLF CONCAT ' */' CONCAT CRLF CONCAT 'return true;' CONCAT CRLF);
+INSERT INTO script_library (guid,script_id,script_name,script_code)
+       VALUES ('7837580c-4054-40f2-981f-7185797fe7d7',11,'Hook::StatusPoll','/* Available global variables:' CONCAT CRLF CONCAT ' *  $node - current node, object of ''Node'' type' CONCAT CRLF CONCAT ' *' CONCAT CRLF CONCAT ' * Expected return value:' CONCAT CRLF CONCAT ' *  none - returned value is ignored' CONCAT CRLF CONCAT ' */' CONCAT CRLF);
+INSERT INTO script_library (guid,script_id,script_name,script_code)
+       VALUES ('f7d1bc7e-4046-4ee4-adb2-718f7361984d',12,'Hook::ConfigurationPoll','/* Available global variables:' CONCAT CRLF CONCAT ' *  $node - current node, object of ''Node'' type' CONCAT CRLF CONCAT ' *' CONCAT CRLF CONCAT ' * Expected return value:' CONCAT CRLF CONCAT ' *  none - returned value is ignored' CONCAT CRLF CONCAT ' */' CONCAT CRLF);
+INSERT INTO script_library (guid,script_id,script_name,script_code)
+       VALUES ('048fcf32-765b-4702-9c70-f012f62d5a90',13,'Hook::InstancePoll','/* Available global variables:' CONCAT CRLF CONCAT ' *  $node - current node, object of ''Node'' type' CONCAT CRLF CONCAT ' *' CONCAT CRLF CONCAT ' * Expected return value:' CONCAT CRLF CONCAT ' *  none - returned value is ignored' CONCAT CRLF CONCAT ' */' CONCAT CRLF);
+INSERT INTO script_library (guid,script_id,script_name,script_code)
+       VALUES ('d515c10f-a5c9-4f41-afcd-9ddc8845f288',14,'Hook::TopologyPoll','/* Available global variables:' CONCAT CRLF CONCAT ' *  $node - current node, object of ''Node'' type' CONCAT CRLF CONCAT ' *' CONCAT CRLF CONCAT ' * Expected return value:' CONCAT CRLF CONCAT ' *  none - returned value is ignored' CONCAT CRLF CONCAT ' */' CONCAT CRLF);
+INSERT INTO script_library (guid,script_id,script_name,script_code)
+       VALUES ('7cd1c471-2f14-4fae-8743-8899fed64d18',15,'Hook::CreateInterface','/* Available global variables:' CONCAT CRLF CONCAT ' *  $node - current node, object of ''Node'' type' CONCAT CRLF CONCAT ' *  $1 - current interface, object of ''Interface'' type' CONCAT CRLF CONCAT ' *' CONCAT CRLF CONCAT ' * Expected return value:' CONCAT CRLF CONCAT ' *  true/false - boolean - whether interface should be created' CONCAT CRLF CONCAT ' */' CONCAT CRLF CONCAT 'return true;' CONCAT CRLF);
+INSERT INTO script_library (guid,script_id,script_name,script_code)
+       VALUES ('befdb083-ac68-481d-a7b7-127e11c3fae0',16,'Hook::AcceptNewNode','/* Available global variables:' CONCAT CRLF CONCAT ' *  $ipAddr - IP address of the node being processed' CONCAT CRLF CONCAT ' *  $ipNetMask - netmask of the node being processed' CONCAT CRLF CONCAT ' *  $macAddr - MAC address of the node being processed' CONCAT CRLF CONCAT ' *  $zoneId - zone ID of the node being processed' CONCAT CRLF CONCAT ' *' CONCAT CRLF CONCAT ' * Expected return value:' CONCAT CRLF CONCAT ' *  true/false - boolean - whether node should be created' CONCAT CRLF CONCAT ' */' CONCAT CRLF CONCAT 'return true;' CONCAT CRLF);
index eaf3e31..f84d9ac 100644 (file)
@@ -4,18 +4,18 @@
 ** ex: syntax=sql
 */
 
-INSERT INTO snmp_trap_cfg (trap_id,snmp_oid,event_code,user_tag,description)
-   VALUES (1,'.1.3.6.1.6.3.1.1.5.1',EVENT_SNMP_COLD_START,'','Generic coldStart trap');
-INSERT INTO snmp_trap_cfg (trap_id,snmp_oid,event_code,user_tag,description)
-   VALUES (2,'.1.3.6.1.6.3.1.1.5.2',EVENT_SNMP_WARM_START,'','Generic warmStart trap');
-INSERT INTO snmp_trap_cfg (trap_id,snmp_oid,event_code,user_tag,description)
-   VALUES (3,'.1.3.6.1.6.3.1.1.5.3',EVENT_SNMP_LINK_DOWN,'','Generic linkDown trap');
-INSERT INTO snmp_trap_cfg (trap_id,snmp_oid,event_code,user_tag,description)
-   VALUES (4,'.1.3.6.1.6.3.1.1.5.4',EVENT_SNMP_LINK_UP,'','Generic linkUp trap');
-INSERT INTO snmp_trap_cfg (trap_id,snmp_oid,event_code,user_tag,description)
-   VALUES (5,'.1.3.6.1.6.3.1.1.5.5',EVENT_SNMP_AUTH_FAILURE,'','Generic authenticationFailure trap');
-INSERT INTO snmp_trap_cfg (trap_id,snmp_oid,event_code,user_tag,description)
-   VALUES (6,'.1.3.6.1.6.3.1.1.5.6',EVENT_SNMP_EGP_NL,'','Generic egpNeighborLoss trap');
+INSERT INTO snmp_trap_cfg (guid,trap_id,snmp_oid,event_code,user_tag,description)
+   VALUES ('5d01e7e5-edbb-46ce-b53c-f7f64d1bf8ff',1,'.1.3.6.1.6.3.1.1.5.1',EVENT_SNMP_COLD_START,'','Generic coldStart trap');
+INSERT INTO snmp_trap_cfg (guid,trap_id,snmp_oid,event_code,user_tag,description)
+   VALUES ('c5464919-fd76-4624-9c21-b6ab73d9df80',2,'.1.3.6.1.6.3.1.1.5.2',EVENT_SNMP_WARM_START,'','Generic warmStart trap');
+INSERT INTO snmp_trap_cfg (guid,trap_id,snmp_oid,event_code,user_tag,description)
+   VALUES ('44d3b32e-33c5-4a39-b2ad-990a1120155d',3,'.1.3.6.1.6.3.1.1.5.3',EVENT_SNMP_LINK_DOWN,'','Generic linkDown trap');
+INSERT INTO snmp_trap_cfg (guid,trap_id,snmp_oid,event_code,user_tag,description)
+   VALUES ('c9660f48-a4b3-41c8-b3f9-e9a6a8129db5',4,'.1.3.6.1.6.3.1.1.5.4',EVENT_SNMP_LINK_UP,'','Generic linkUp trap');
+INSERT INTO snmp_trap_cfg (guid,trap_id,snmp_oid,event_code,user_tag,description)
+   VALUES ('4b422ba6-4b45-4881-931a-ed38dc798f9f',5,'.1.3.6.1.6.3.1.1.5.5',EVENT_SNMP_AUTH_FAILURE,'','Generic authenticationFailure trap');
+INSERT INTO snmp_trap_cfg (guid,trap_id,snmp_oid,event_code,user_tag,description)
+   VALUES ('bd8b6971-a3e4-4cad-9c70-3a33e61e0913',6,'.1.3.6.1.6.3.1.1.5.6',EVENT_SNMP_EGP_NL,'','Generic egpNeighborLoss trap');
 
 INSERT INTO snmp_trap_pmap (trap_id,parameter,flags,snmp_oid,description)
    VALUES (3,1,0,'.1.3.6.1.2.1.2.2.1.1','Interface index');
index 9865ac0..375b26e 100644 (file)
@@ -965,7 +965,8 @@ public class NXCPCodes
        public static final long VID_DCI_SCHEDULE_BASE = 0x10000000L;
        public static final long VID_EVENT_ARG_BASE = 0x00008000L;
        public static final long VID_EVENT_ARG_LAST = 0x00008FFFL;
-       public static final long VID_TRAP_PLEN_BASE = 0x00009000L;
+       public static final long VID_TRAP_PBASE = 0x00009000L;
+       /* Unused
        public static final long VID_TRAP_PLEN_LAST = 0x000093FFL;
        public static final long VID_TRAP_PNAME_BASE = 0x00009400L;
        public static final long VID_TRAP_PNAME_LAST = 0x000097FFL;
@@ -973,6 +974,7 @@ public class NXCPCodes
        public static final long VID_TRAP_PDESCR_LAST = 0x00009BFFL;
        public static final long VID_TRAP_PFLAGS_BASE = 0x00009C00L;
        public static final long VID_TRAP_PFLAGS_LAST = 0x00009FFFL;
+       */
        public static final long VID_PARENT_ID_BASE = 0x00003000L;
        public static final long VID_PARENT_ID_LAST = 0x00003FFFL;
        public static final long VID_CHILD_ID_BASE = 0x80000000L;
index 41171d0..9a82efa 100644 (file)
@@ -7155,11 +7155,9 @@ public class NXCSession
       int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_SCRIPTS);
       List<Script> scripts = new ArrayList<Script>(count);
       long varId = NXCPCodes.VID_SCRIPT_LIST_BASE;
-      for(int i = 0; i < count; i++)
+      for(int i = 0; i < count; i++, varId +=2)
       {
-         final long id = response.getFieldAsInt64(varId++);
-         final String name = response.getFieldAsString(varId++);
-         scripts.add(new Script(id, name, null));
+         scripts.add(new Script(response, varId));
       }
       return scripts;
    }
@@ -7178,8 +7176,7 @@ public class NXCSession
       msg.setFieldInt32(NXCPCodes.VID_SCRIPT_ID, (int) scriptId);
       sendMessage(msg);
       final NXCPMessage response = waitForRCC(msg.getMessageId());
-      return new Script(scriptId, response.getFieldAsString(NXCPCodes.VID_NAME),
-         response.getFieldAsString(NXCPCodes.VID_SCRIPT_CODE));
+      return new Script(response);
    }
 
    /**
index 57d6d68..9727867 100644 (file)
@@ -33,7 +33,7 @@ public final class ProtocolVersion
    public static final int PUSH = 1;
    public static final int TRAP = 1;
    public static final int MOBILE = 1;
-   public static final int FULL = 7;
+   public static final int FULL = 8;
    
    // Indexes
    public static final int INDEX_BASE = 0;
index cf831d4..006fee2 100644 (file)
@@ -18,6 +18,9 @@
  */
 package org.netxms.client;
 
+import org.netxms.base.NXCPCodes;
+import org.netxms.base.NXCPMessage;
+
 /**
  * NXSL script object
  */
@@ -38,7 +41,28 @@ public class Script
                this.id = id;
                this.name = (name != null) ? name : ("[" + Long.toString(id) + "]");
                this.source = source;
-       }
+   }
+       
+   /**
+   * Create script object from msg
+   */
+       public Script(NXCPMessage msg)
+       {
+      this.id = msg.getFieldAsInt64(NXCPCodes.VID_SCRIPT_ID);
+      this.name = msg.getFieldAsString(NXCPCodes.VID_NAME).equals("") ? ("[" + Long.toString(id) + "]") : msg.getFieldAsString(NXCPCodes.VID_NAME);
+      this.source = msg.getFieldAsString(NXCPCodes.VID_SCRIPT_CODE);
+   }
+       
+   /**
+   * Create script object for list from msg
+   */
+   public Script(NXCPMessage msg, long base)
+   {
+      this.id = msg.getFieldAsInt64(base++);
+      this.name = msg.getFieldAsString(base).equals("") ? ("[" + Long.toString(id) + "]") : msg.getFieldAsString(base);
+      base++;
+      this.source = null;
+   }
 
        /**
         * @return the id
index 0a7c33b..eb315f3 100644 (file)
@@ -60,23 +60,10 @@ public class SnmpTrap
                
                int count = msg.getFieldAsInt32(NXCPCodes.VID_TRAP_NUM_MAPS);
                parameterMapping = new ArrayList<SnmpTrapParameterMapping>(count);
-               for(int i = 0; i < count; i++)
+               long base = NXCPCodes.VID_TRAP_PBASE;
+               for(int i = 0; i < count; i++, base += 10)
                {
-                       SnmpTrapParameterMapping pm;
-                       long oidLen = msg.getFieldAsInt64(NXCPCodes.VID_TRAP_PLEN_BASE + i);
-                       if ((oidLen & 0x80000000) == 0)
-                       {
-                               // mapping by OID
-                               pm = new SnmpTrapParameterMapping(new SnmpObjectId(msg.getFieldAsUInt32Array(NXCPCodes.VID_TRAP_PNAME_BASE + i)));
-                       }
-                       else
-                       {
-                               // mapping by position
-                               pm = new SnmpTrapParameterMapping((int)(oidLen & 0x7FFFFFFF));
-                       }
-                       pm.setDescription(msg.getFieldAsString(NXCPCodes.VID_TRAP_PDESCR_BASE + i));
-                       pm.setFlags(msg.getFieldAsInt32(NXCPCodes.VID_TRAP_PFLAGS_BASE + i));
-                       parameterMapping.add(pm);
+                       parameterMapping.add(new SnmpTrapParameterMapping(msg, base));
                }
        }
        
@@ -88,7 +75,7 @@ public class SnmpTrap
        public SnmpTrap(NXCPMessage msg, long baseId)
        {
                id = msg.getFieldAsInt64(baseId);
-               description = msg.getFieldAsString(baseId + 4);
+               description = msg.getFieldAsString(baseId + 1);
                objectId = new SnmpObjectId(msg.getFieldAsUInt32Array(baseId + 2));
                eventCode = msg.getFieldAsInt32(baseId + 3);
                parameterMapping = new ArrayList<SnmpTrapParameterMapping>(0);
@@ -108,9 +95,10 @@ public class SnmpTrap
                msg.setFieldInt32(NXCPCodes.VID_TRAP_OID_LEN, objectId.getLength());
                objectId.setNXCPVariable(msg, NXCPCodes.VID_TRAP_OID);
                msg.setFieldInt32(NXCPCodes.VID_TRAP_NUM_MAPS, parameterMapping.size());
-               for(int i = 0; i < parameterMapping.size(); i++)
+               long base = NXCPCodes.VID_TRAP_PBASE;
+               for(int i = 0; i < parameterMapping.size(); i++, base += 10)
                {
-                       parameterMapping.get(i).fillMessage(msg, i);
+                       parameterMapping.get(i).fillMessage(msg, base);
                }
        }
 
index 85e140e..8670450 100644 (file)
@@ -60,24 +60,37 @@ public class SnmpTrapParameterMapping
                type = BY_OBJECT_ID;
                objectId = oid;
        }
+       
+   public SnmpTrapParameterMapping(NXCPMessage msg, long base)
+   {
+      type = msg.getFieldAsInt32(base);
+      if (type == BY_POSITION)
+         position = (int)msg.getFieldAsInt64(base + 1);
+      else
+         objectId = new SnmpObjectId(msg.getFieldAsUInt32Array(base + 1));
+      
+      description = msg.getFieldAsString(base + 2);
+      flags = msg.getFieldAsInt32(base + 3);
+   }
 
        /**
         * Fill NXCP message with parameter mapping's data
         * 
         * @param index mapping index
         */
-       public void fillMessage(NXCPMessage msg, int index)
+       public void fillMessage(NXCPMessage msg, long base)
        {
-               msg.setFieldInt32(NXCPCodes.VID_TRAP_PFLAGS_BASE + index, flags);
-               msg.setField(NXCPCodes.VID_TRAP_PDESCR_BASE + index, description);
+      msg.setFieldInt32(base, flags);
+      msg.setField(base + 1, description);
+      msg.setFieldInt32(base + 2, type);
                if (type == BY_POSITION)
                {
-                       msg.setFieldInt32(NXCPCodes.VID_TRAP_PLEN_BASE + index, position | 0x80000000);
+                       msg.setFieldInt32(base + 3, position);
                }
                else
                {
-                       msg.setFieldInt32(NXCPCodes.VID_TRAP_PLEN_BASE + index, objectId.getLength());
-                       objectId.setNXCPVariable(msg, NXCPCodes.VID_TRAP_PNAME_BASE + index);
+         objectId.setNXCPVariable(msg, base + 3);
+                       msg.setFieldInt32(base + 4, objectId.getLength());
                }
        }
 
index b54c79d..3578fb9 100644 (file)
@@ -186,6 +186,7 @@ public class ParamMappingEditDialog extends Dialog
                position.setIncrement(1);
                position.setMaximum(255);
                position.setMinimum(1);
+               position.setSelection(pm.getPosition());
                gd = new GridData();
                gd.widthHint = 40;
                position.setLayoutData(gd);
index c2fba9c..457c4bd 100644 (file)
@@ -239,7 +239,7 @@ bool NXSL_Environment::loadModule(NXSL_VM *vm, const NXSL_ModuleImport *importIn
    // First, try to find module in library
    if (m_library != NULL)
    {
-      pScript = m_library->findScript(importInfo->name);
+      pScript = m_library->findNxslProgram(importInfo->name);
       if (pScript != NULL)
       {
          vm->loadModule(pScript, importInfo);
index 8c3db5f..9b53179 100644 (file)
  */
 NXSL_Library::NXSL_Library()
 {
+   m_scriptList = new ObjectArray<NXSL_LibraryScript>(16, 16, true);
    m_mutex = MutexCreate();
-   m_dwNumScripts = 0;
-   m_ppScriptList = NULL;
-   m_ppszNames = NULL;
-   m_pdwIdList = NULL;
 }
 
 /**
@@ -40,89 +37,67 @@ NXSL_Library::NXSL_Library()
  */
 NXSL_Library::~NXSL_Library()
 {
-   for(UINT32 i = 0; i < m_dwNumScripts; i++)
-   {
-      delete m_ppScriptList[i];
-      free(m_ppszNames[i]);
-   }
-   safe_free(m_ppScriptList);
-   safe_free(m_ppszNames);
-   safe_free(m_pdwIdList);
+   delete m_scriptList;
    MutexDestroy(m_mutex);
 }
 
 /**
  * Add script to library
  */
-BOOL NXSL_Library::addScript(UINT32 dwId, const TCHAR *pszName, NXSL_Program *pScript)
+BOOL NXSL_Library::addScript(NXSL_LibraryScript *script)
 {
-   UINT32 i;
-
-   for(i = 0; i < m_dwNumScripts; i++)
-      if (!_tcsicmp(m_ppszNames[i], pszName))
-         return FALSE;
-
-   m_dwNumScripts++;
-   m_ppScriptList = (NXSL_Program **)realloc(m_ppScriptList, sizeof(NXSL_Program *) * m_dwNumScripts);
-   m_ppszNames = (TCHAR **)realloc(m_ppszNames, sizeof(TCHAR *) * m_dwNumScripts);
-   m_pdwIdList = (UINT32 *)realloc(m_pdwIdList, sizeof(UINT32) * m_dwNumScripts);
-   m_ppScriptList[i] = pScript;
-   m_ppszNames[i] = _tcsdup(pszName);
-   m_pdwIdList[i] = dwId;
+   m_scriptList->add(script);
    return TRUE;
 }
 
 /**
- * Delete script from library
+ * Delete script by name
  */
-void NXSL_Library::deleteInternal(int nIndex)
-{
-   delete m_ppScriptList[nIndex];
-   free(m_ppszNames[nIndex]);
-   m_dwNumScripts--;
-   memmove(&m_ppScriptList[nIndex], &m_ppScriptList[nIndex + 1],
-           sizeof(NXSL_Program *) * (m_dwNumScripts - nIndex));
-   memmove(&m_ppszNames[nIndex], &m_ppszNames[nIndex + 1],
-           sizeof(char *) * (m_dwNumScripts - nIndex));
-   memmove(&m_pdwIdList[nIndex], &m_pdwIdList[nIndex + 1],
-           sizeof(UINT32) * (m_dwNumScripts - nIndex));
-}
-
 void NXSL_Library::deleteScript(const TCHAR *pszName)
 {
-   UINT32 i;
-
-   for(i = 0; i < m_dwNumScripts; i++)
-      if (!_tcsicmp(m_ppszNames[i], pszName))
+   for(int i = 0; i < m_scriptList->size(); i++)
+      if (!_tcsicmp(m_scriptList->get(i)->getName(), pszName))
       {
-         deleteInternal(i);
+         m_scriptList->remove(i);
          break;
       }
 }
 
+/**
+ * Delete script by id
+ */
 void NXSL_Library::deleteScript(UINT32 dwId)
 {
-   UINT32 i;
-
-   for(i = 0; i < m_dwNumScripts; i++)
-      if (m_pdwIdList[i] == dwId)
+   for(int i = 0; i < m_scriptList->size(); i++)
+      if (m_scriptList->get(i)->getId() == dwId)
       {
-         deleteInternal(i);
+         m_scriptList->remove(i);
          break;
       }
 }
 
 /**
- * Find script by name
+ * Find compiled NXSL program by name
  */
-NXSL_Program *NXSL_Library::findScript(const TCHAR *name)
+NXSL_Program *NXSL_Library::findNxslProgram(const TCHAR *name)
 {
-   UINT32 i;
+   for(int i = 0; i < m_scriptList->size(); i++)
+      if (!_tcsicmp(m_scriptList->get(i)->getName(), name))
+      {
+         return m_scriptList->get(i)->getProgram();
+      }
+   return NULL;
+}
 
-   for(i = 0; i < m_dwNumScripts; i++)
-      if (!_tcsicmp(m_ppszNames[i], name))
+/**
+ * Find script object by ID
+ */
+NXSL_LibraryScript *NXSL_Library::findScript(UINT32 id)
+{
+   for(int i = 0; i < m_scriptList->size(); i++)
+      if (m_scriptList->get(i)->getId() == id)
       {
-         return m_ppScriptList[i];
+         return m_scriptList->get(i);
       }
    return NULL;
 }
@@ -135,7 +110,7 @@ NXSL_VM *NXSL_Library::createVM(const TCHAR *name, NXSL_Environment *env)
 {
    NXSL_VM *vm = NULL;
    lock();
-   NXSL_Program *p = findScript(name);
+   NXSL_Program *p = findNxslProgram(name);
    if (p != NULL)
    {
       vm = new NXSL_VM(env);
@@ -154,16 +129,68 @@ NXSL_VM *NXSL_Library::createVM(const TCHAR *name, NXSL_Environment *env)
 }
 
 /**
- * Fill NXCP message with script data
+ * Fill message with script library
  */
-void NXSL_Library::fillMessage(NXCPMessage *pMsg)
+void NXSL_Library::fillMessage(NXCPMessage *msg)
 {
-   UINT32 i, dwId;
-
-   pMsg->setField(VID_NUM_SCRIPTS, m_dwNumScripts);
-   for(i = 0, dwId = VID_SCRIPT_LIST_BASE; i < m_dwNumScripts; i++)
+   lock();
+   msg->setField(VID_NUM_SCRIPTS, m_scriptList->size());
+   UINT32 fieldId = VID_SCRIPT_LIST_BASE;
+   for(int i = 0; i < m_scriptList->size(); i++, fieldId+=2)
    {
-      pMsg->setField(dwId++, m_pdwIdList[i]);
-      pMsg->setField(dwId++, m_ppszNames[i]);
+      m_scriptList->get(i)->fillMessage(msg, fieldId);
    }
+   unlock();
 }
+
+/**
+ * Create empty NXSL Script
+ */
+NXSL_LibraryScript::NXSL_LibraryScript()
+{
+   m_id = 0;
+   nx_strncpy(m_name, _T(""), 1);
+   m_source = NULL;
+   m_program = new NXSL_Program();
+}
+
+/**
+ * Create NXSL Script
+ */
+NXSL_LibraryScript::NXSL_LibraryScript(UINT32 id, uuid guid, const TCHAR *name, TCHAR *source)
+{
+   m_id = id;
+   m_guid = guid;
+   nx_strncpy(m_name, name, 1024);
+   m_source = source;
+   m_program = (NXSL_Program *)NXSLCompile(m_source, m_error, 1024, NULL);
+}
+
+/**
+ * NXSL Script destructor
+ */
+NXSL_LibraryScript::~NXSL_LibraryScript()
+{
+   free(m_source);
+   delete m_program;
+}
+
+/**
+ * Fill message with script id and name for list
+ */
+void NXSL_LibraryScript::fillMessage(NXCPMessage *msg, UINT32 base)
+{
+   msg->setField(base, m_id);
+   msg->setField(base + 1, m_name);
+}
+
+/**
+ * Fill message with script data
+ */
+void NXSL_LibraryScript::fillMessage(NXCPMessage *msg)
+{
+   msg->setField(VID_SCRIPT_ID, m_id);
+   msg->setField(VID_NAME, m_name);
+   msg->setField(VID_SCRIPT_CODE, m_source);
+}
+
index 2ac6d9a..d5f3dce 100644 (file)
@@ -922,7 +922,7 @@ int ProcessConsoleCommand(const TCHAR *pszCmdLine, CONSOLE_CTX pCtx)
       bool destroyCompiledScript = false;
       g_pScriptLibrary->lock();
 
-      NXSL_Program *compiledScript = g_pScriptLibrary->findScript(szBuffer);
+      NXSL_Program *compiledScript = g_pScriptLibrary->findNxslProgram(szBuffer);
       if (compiledScript == NULL)
       {
          g_pScriptLibrary->unlock();
index 52b38d7..16383c5 100644 (file)
@@ -325,64 +325,75 @@ static UINT32 ImportEvent(ConfigEntry *event)
 /**
  * Import SNMP trap configuration
  */
-static UINT32 ImportTrap(ConfigEntry *trap)
+static UINT32 ImportTrap(ConfigEntry *trap) // TODO transactions needed?
 {
+   UINT32 rcc = RCC_INTERNAL_ERROR;
        EventTemplate *event = FindEventTemplateByName(trap->getSubEntryValue(_T("event"), 0, _T("")));
        if (event == NULL)
-               return RCC_INTERNAL_ERROR;
-
-   NXC_TRAP_CFG_ENTRY tc;
-       memset(&tc, 0, sizeof(NXC_TRAP_CFG_ENTRY));
-       tc.dwEventCode = event->getCode();
-       nx_strncpy(tc.szDescription, trap->getSubEntryValue(_T("description"), 0, _T("")), MAX_DB_STRING);
-       nx_strncpy(tc.szUserTag, trap->getSubEntryValue(_T("userTag"), 0, _T("")), MAX_USERTAG_LENGTH);
+               return rcc;
 
-       event->decRefCount();
+       uuid guid = trap->getSubEntryValueAsUUID(_T("guid"));
+   if (guid.isNull())
+   {
+      guid = uuid::generate();
+      nxlog_debug(4, _T("ImportTrap: GUID not found in config, generated GUID %s"), (const TCHAR *)guid.toString());
+   }
+   UINT32 id = ResolveTrapGuid(guid);
+       SNMP_TrapCfg *trapCfg = new SNMP_TrapCfg(trap, guid, id, event->getCode());
 
-       UINT32 oid[256];
-       tc.dwOidLen = (UINT32)SNMPParseOID(trap->getSubEntryValue(_T("oid"), 0, _T("")), oid, 256);
-       tc.pdwObjectId = oid;
-       if (tc.dwOidLen == 0)
-               return RCC_INTERNAL_ERROR;
+       if (trapCfg->getOidLength() == 0)
+       {
+          delete trapCfg;
+               return rcc;
+       }
 
-       ConfigEntry *parametersRoot = trap->findEntry(_T("parameters"));
-       if (parametersRoot != NULL)
+       DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
+       DB_STATEMENT hStmt;
+       if (id == 0)
        {
-               ObjectArray<ConfigEntry> *parameters = parametersRoot->getOrderedSubEntries(_T("parameter#*"));
-               if (parameters->size() > 0)
-               {
-                       tc.dwNumMaps = parameters->size();
-                       tc.pMaps = (NXC_OID_MAP *)malloc(sizeof(NXC_OID_MAP) * tc.dwNumMaps);
-                       for(int i = 0; i < parameters->size(); i++)
-                       {
-                               ConfigEntry *parameter = parameters->get(i);
+          hStmt = DBPrepare(hdb, _T("INSERT INTO snmp_trap_cfg (snmp_oid,event_code,description,user_tag,trap_id,guid) VALUES (?,?,?,?,?,?)"));
+       }
+       else
+          hStmt = DBPrepare(hdb, _T("UPDATE snmp_trap_cfg SET snmp_oid=?,event_code=?,description=?,user_tag=? WHERE trap_id=?"));
 
-                               int position = parameter->getSubEntryValueAsInt(_T("position"), 0, -1);
-                               if (position > 0)
-                               {
-                                       // Positional parameter
-                                       tc.pMaps[i].pdwObjectId = NULL;
-                                       tc.pMaps[i].dwOidLen = (UINT32)position | 0x80000000;
-                               }
-                               else
-                               {
-                                       // OID parameter
-                                       UINT32 temp[256];
-                                       tc.pMaps[i].dwOidLen = (UINT32)SNMPParseOID(parameter->getSubEntryValue(_T("oid"), 0, _T("")), temp, 256);
-                                       tc.pMaps[i].pdwObjectId = (UINT32 *)nx_memdup(temp, sizeof(UINT32) * tc.pMaps[i].dwOidLen);
-                               }
-                               nx_strncpy(tc.pMaps[i].szDescription, parameter->getSubEntryValue(_T("description"), 0, _T("")), MAX_DB_STRING);
-                               tc.pMaps[i].dwFlags = parameter->getSubEntryValueAsUInt(_T("flags"), 0, 0);
-                       }
-               }
-               delete parameters;
+       if (hStmt != NULL)
+       {
+          TCHAR oid[1024];
+          SNMPConvertOIDToText(trapCfg->getOidLength(), trapCfg->getOid()->value(), oid, 1024);
+          DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, oid, DB_BIND_STATIC);
+          DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, trapCfg->getEventCode());
+          DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, trapCfg->getDescription(), DB_BIND_STATIC);
+      DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, trapCfg->getUserTag(), DB_BIND_STATIC);
+      DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, trapCfg->getId());
+      if (id == 0)
+         DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, trapCfg->getGuid());
+
+      if (DBBegin(hdb))
+      {
+         if(DBExecute(hStmt) && trapCfg->saveParameterMapping(hdb))
+         {
+            AddTrapCfgToList(trapCfg);
+            trapCfg->notifyOnTrapCfgChange(NX_NOTIFY_TRAPCFG_CREATED);
+            rcc = RCC_SUCCESS;
+            DBCommit(hdb);
+         }
+         else
+         {
+            DBRollback(hdb);
+            rcc = RCC_DB_FAILURE;
+         }
+      }
+      else
+         rcc = RCC_DB_FAILURE;
+      DBFreeStatement(hStmt);
        }
+       else
+          rcc = RCC_DB_FAILURE;
 
-       UINT32 rcc = CreateNewTrap(&tc);
+       if (rcc != RCC_SUCCESS)
+          delete trapCfg;
 
-       // Cleanup
-       for(UINT32 i = 0; i < tc.dwNumMaps; i++)
-               safe_free(tc.pMaps[i].pdwObjectId);
+       DBConnectionPoolReleaseConnection(hdb);
 
        return rcc;
 }
index d83b416..0913869 100644 (file)
@@ -33,32 +33,28 @@ NXSL_Library *g_pScriptLibrary = NULL;
 void LoadScripts()
 {
    DB_RESULT hResult;
-   NXSL_Program *pScript;
-   TCHAR *pszCode, szError[1024], szBuffer[MAX_DB_STRING];
-   int i, nRows;
+   NXSL_LibraryScript *pScript;
+   TCHAR buffer[MAX_DB_STRING];
 
-   g_pScriptLibrary = new NXSL_Library;
+   g_pScriptLibrary = new NXSL_Library();
    DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-   hResult = DBSelect(hdb, _T("SELECT script_id,script_name,script_code FROM script_library"));
+   hResult = DBSelect(hdb, _T("SELECT script_id,guid,script_name,script_code FROM script_library"));
    if (hResult != NULL)
    {
-      nRows = DBGetNumRows(hResult);
-      for(i = 0; i < nRows; i++)
+      int numRows = DBGetNumRows(hResult);
+      for(int i = 0; i < numRows; i++)
       {
-         pszCode = DBGetField(hResult, i, 2, NULL, 0);
-         pScript = (NXSL_Program *)NXSLCompile(pszCode, szError, 1024, NULL);
-         free(pszCode);
-         if (pScript != NULL)
+         pScript = new NXSL_LibraryScript(DBGetFieldULong(hResult, i, 0), DBGetFieldGUID(hResult, i, 1),
+                  DBGetField(hResult, i, 2, buffer, MAX_DB_STRING), DBGetField(hResult, i, 3, NULL, 0));
+         if (pScript->isValid())
          {
-            g_pScriptLibrary->addScript(DBGetFieldULong(hResult, i, 0),
-                                        DBGetField(hResult, i, 1, szBuffer, MAX_DB_STRING), pScript);
-                               DbgPrintf(2, _T("Script %s added to library"), szBuffer);
+            g_pScriptLibrary->addScript(pScript);
+            DbgPrintf(2, _T("Script %s added to library"), pScript->getName());
          }
          else
          {
             nxlog_write(MSG_SCRIPT_COMPILATION_ERROR, NXLOG_WARNING, "dss",
-                        DBGetFieldULong(hResult, i, 0),
-                        DBGetField(hResult, i, 1, szBuffer, MAX_DB_STRING), szError);
+                        pScript->getId(), pScript->getName(), pScript->getError());
          }
       }
       DBFreeResult(hResult);
@@ -69,16 +65,13 @@ void LoadScripts()
 /**
  * Load script name and code from database
  */
-static bool LoadScriptFromDatabase(UINT32 id, TCHAR **name, TCHAR **code)
+NXSL_LibraryScript *LoadScriptFromDatabase(UINT32 id)
 {
-   bool success = false;
-
-   *name = NULL;
-   *code = NULL;
+   NXSL_LibraryScript *script = NULL;
 
    DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
 
-   DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT script_name,script_code FROM script_library WHERE script_id=?"));
+   DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT script_id,guid,script_name,script_code FROM script_library WHERE script_id=?"));
    if (hStmt != NULL)
    {
       DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, id);
@@ -87,9 +80,9 @@ static bool LoadScriptFromDatabase(UINT32 id, TCHAR **name, TCHAR **code)
       {
          if (DBGetNumRows(hResult) > 0)
          {
-            *name = DBGetField(hResult, 0, 0, NULL, 0);
-            *code = DBGetField(hResult, 0, 1, NULL, 0);
-            success = true;
+            TCHAR buffer[MAX_DB_STRING];
+            script = new NXSL_LibraryScript(DBGetFieldULong(hResult, 0, 0), DBGetFieldGUID(hResult, 0, 1),
+                     DBGetField(hResult, 0, 2, buffer, MAX_DB_STRING), DBGetField(hResult, 0, 3, NULL, 0));
          }
          DBFreeResult(hResult);
       }
@@ -97,7 +90,7 @@ static bool LoadScriptFromDatabase(UINT32 id, TCHAR **name, TCHAR **code)
    }
 
    DBConnectionPoolReleaseConnection(hdb);
-   return success;
+   return script;
 }
 
 /**
@@ -105,29 +98,25 @@ static bool LoadScriptFromDatabase(UINT32 id, TCHAR **name, TCHAR **code)
  */
 void ReloadScript(UINT32 id)
 {
-   TCHAR *name, *code;
-   if (!LoadScriptFromDatabase(id, &name, &code))
+   NXSL_LibraryScript *script = LoadScriptFromDatabase(id);
+   if (script == NULL)
    {
       DbgPrintf(3, _T("ReloadScript: failed to load script with ID %d from database"), (int)id);
       return;
    }
 
-   TCHAR error[1024];
-   NXSL_Program *script = NXSLCompile(code, error, 1024, NULL);
-   free(code);
-
    g_pScriptLibrary->lock();
    g_pScriptLibrary->deleteScript(id);
-   if (script != NULL)
+   if (script->isValid())
    {
-      g_pScriptLibrary->addScript(id, name, script);
+      g_pScriptLibrary->addScript(script);
    }
    else
    {
-      nxlog_write(MSG_SCRIPT_COMPILATION_ERROR, NXLOG_WARNING, "dss", id, name, error);
+      nxlog_write(MSG_SCRIPT_COMPILATION_ERROR, NXLOG_WARNING, "dss", id, script->getName(), script->getError());
+      delete script;
    }
    g_pScriptLibrary->unlock();
-   free(name);
 }
 
 /**
@@ -157,7 +146,35 @@ UINT32 ResolveScriptName(const TCHAR *name)
       DB_RESULT hResult = DBSelectPrepared(hStmt);
       if (hResult != NULL)
       {
-         id = DBGetFieldULong(hResult, 0, 0);
+         if (DBGetNumRows(hResult) > 0)
+            id = DBGetFieldULong(hResult, 0, 0);
+         DBFreeResult(hResult);
+      }
+      DBFreeStatement(hStmt);
+   }
+
+   DBConnectionPoolReleaseConnection(hdb);
+   return id;
+}
+
+/**
+ * Resolve script GUID to ID
+ */
+UINT32 ResolveScriptGuid(const uuid& guid)
+{
+   UINT32 id = 0;
+
+   DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
+
+   DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT script_id FROM script_library WHERE guid=?"));
+   if (hStmt != NULL)
+   {
+      DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, guid);
+      DB_RESULT hResult = DBSelectPrepared(hStmt);
+      if (hResult != NULL)
+      {
+         if (DBGetNumRows(hResult) > 0)
+            id = DBGetFieldULong(hResult, 0, 0);
          DBFreeResult(hResult);
       }
       DBFreeStatement(hStmt);
@@ -168,12 +185,138 @@ UINT32 ResolveScriptName(const TCHAR *name)
 }
 
 /**
+ * Update or create new script
+ */
+UINT32 UpdateScript(const NXCPMessage *request, UINT32 *scriptId)
+{
+   UINT32 rcc = RCC_DB_FAILURE;
+
+   TCHAR scriptName[MAX_DB_STRING];
+   request->getFieldAsString(VID_NAME, scriptName, MAX_DB_STRING);
+   TCHAR *scriptSource = request->getFieldAsString(VID_SCRIPT_CODE);
+
+   if (scriptSource == NULL)
+      return RCC_INVALID_REQUEST;
+
+   if (IsValidScriptName(scriptName))
+   {
+      DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
+      DB_STATEMENT hStmt;
+
+      UINT32 id = ResolveScriptName(scriptName);
+      uuid guid;
+      if (id == 0) // Create new script
+      {
+         guid = uuid::generate();
+         id = CreateUniqueId(IDG_SCRIPT);
+         hStmt = DBPrepare(hdb, _T("INSERT INTO script_library (script_name,script_code,script_id,guid) VALUES (?,?,?,?)"));
+      }
+      else // Update existing script
+         hStmt = DBPrepare(hdb, _T("UPDATE script_library SET script_name=?,script_code=? WHERE script_id=?"));
+
+      if (hStmt != NULL)
+      {
+         DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, scriptName, DB_BIND_STATIC);
+         DBBind(hStmt, 2, DB_SQLTYPE_TEXT, scriptSource, DB_BIND_STATIC);
+         DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, id);
+         if (!guid.isNull())
+            DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, (const TCHAR *)guid.toString(), DB_BIND_STATIC);
+
+         if (DBExecute(hStmt))
+         {
+            ReloadScript(id);
+            *scriptId = id;
+            rcc = RCC_SUCCESS;
+         }
+         DBFreeStatement(hStmt);
+      }
+      DBConnectionPoolReleaseConnection(hdb);
+   }
+   else
+      rcc = RCC_INVALID_SCRIPT_NAME;
+
+   free(scriptSource);
+
+   return rcc;
+}
+
+/*
+ * Rename script
+ */
+UINT32 RenameScript(const NXCPMessage *request)
+{
+   UINT32 rcc = RCC_DB_FAILURE;
+   UINT32 id = request->getFieldAsUInt32(VID_SCRIPT_ID);
+
+   if (IsValidScriptId(id))
+   {
+      TCHAR scriptName[MAX_DB_STRING];
+      request->getFieldAsString(VID_NAME, scriptName, MAX_DB_STRING);
+      if (IsValidScriptName(scriptName))
+      {
+         DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
+         DB_STATEMENT hStmt = DBPrepare(hdb, _T("UPDATE script_library SET script_name=? WHERE script_id=?"));
+         if (hStmt != NULL)
+         {
+            DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, scriptName, DB_BIND_STATIC);
+            DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, id);
+            if (DBExecute(hStmt))
+            {
+               ReloadScript(id);
+               rcc = RCC_SUCCESS;
+            }
+            DBFreeStatement(hStmt);
+         }
+         DBConnectionPoolReleaseConnection(hdb);
+      }
+      else
+         rcc = RCC_INVALID_SCRIPT_NAME;
+   }
+   else
+      rcc = RCC_INVALID_SCRIPT_ID;
+
+   return rcc;
+}
+
+/**
+ * Delete script
+ */
+UINT32 DeleteScript(const NXCPMessage *request)
+{
+   UINT32 rcc = RCC_DB_FAILURE;
+   UINT32 id = request->getFieldAsUInt32(VID_SCRIPT_ID);
+
+   if (IsValidScriptId(id))
+   {
+      DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
+      DB_STATEMENT hStmt = DBPrepare(hdb, _T("DELETE FROM script_library WHERE script_id=?"));
+      if (hStmt != NULL)
+      {
+         DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, id);
+         if (DBExecute(hStmt))
+         {
+            g_pScriptLibrary->lock();
+            g_pScriptLibrary->deleteScript(id);
+            g_pScriptLibrary->unlock();
+            rcc = RCC_SUCCESS;
+         }
+         DBFreeStatement(hStmt);
+      }
+      DBConnectionPoolReleaseConnection(hdb);
+   }
+   else
+      rcc = RCC_INVALID_SCRIPT_ID;
+
+   return rcc;
+}
+
+/**
  * Create export record for library script
  */
 void CreateScriptExportRecord(String &xml, UINT32 id)
 {
-   TCHAR *name, *code;
-   if (!LoadScriptFromDatabase(id, &name, &code))
+   NXSL_LibraryScript *script = LoadScriptFromDatabase(id);
+   if (script == NULL)
    {
       DbgPrintf(3, _T("CreateScriptExportRecord: failed to load script with ID %d from database"), (int)id);
       return;
@@ -182,15 +325,15 @@ void CreateScriptExportRecord(String &xml, UINT32 id)
    xml.append(_T("\t\t<script id=\""));
    xml.append(id);
    xml.append(_T("\">\n"));
+   xml.append(_T("\t\t\t<guid>"));
+   xml.append((const TCHAR *)script->getGuid().toString());
+   xml.append(_T("</guid>\n"));
    xml.append(_T("\t\t\t<name>"));
-   xml.append(EscapeStringForXML2(name));
+   xml.append(EscapeStringForXML2(script->getName()));
    xml.append(_T("</name>\n"));
    xml.append(_T("\t\t\t<code>"));
-   xml.append(EscapeStringForXML2(code));
+   xml.append(EscapeStringForXML2(script->getCode()));
    xml.append(_T("</code>\n\t\t</script>\n"));
-
-   free(name);
-   free(code);
 }
 
 /**
@@ -205,6 +348,13 @@ void ImportScript(ConfigEntry *config)
       return;
    }
 
+   uuid guid = config->getSubEntryValueAsUUID(_T("guid"));
+   if (guid.isNull())
+   {
+      guid = uuid::generate();
+      DbgPrintf(4, _T("ImportScript: GUID not found in config, generated GUID %s for script \"%s\""), (const TCHAR *)guid.toString(), name);
+   }
+
    const TCHAR *code = config->getSubEntryValue(_T("code"));
    if (code == NULL)
    {
@@ -212,32 +362,36 @@ void ImportScript(ConfigEntry *config)
       return;
    }
 
-   DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-
-   DB_STATEMENT hStmt;
-   UINT32 id = ResolveScriptName(name);
-   if (id == 0)
-   {
-      id = CreateUniqueId(IDG_SCRIPT);
-      hStmt = DBPrepare(hdb, _T("INSERT INTO script_library (script_name,script_code,script_id) VALUES (?,?,?)"));
-   }
-   else
+   if (IsValidScriptName(name))
    {
-      hStmt = DBPrepare(hdb, _T("UPDATE script_library SET script_name=?,script_code=? WHERE script_id=?"));
-   }
+      DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
+      DB_STATEMENT hStmt;
 
-   if (hStmt != NULL)
-   {
-      DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, name, DB_BIND_STATIC);
-      DBBind(hStmt, 2, DB_SQLTYPE_TEXT, code, DB_BIND_STATIC);
-      DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, id);
-      DBExecute(hStmt);
-      DBFreeStatement(hStmt);
-   }
-
-   DBConnectionPoolReleaseConnection(hdb);
+      bool newScript = false;
+      UINT32 id = ResolveScriptGuid(guid);
+      if (id == 0) // Create new script
+      {
+         id = CreateUniqueId(IDG_SCRIPT);
+         hStmt = DBPrepare(hdb, _T("INSERT INTO script_library (script_name,script_code,script_id,guid) VALUES (?,?,?,?)"));
+         newScript = true;
+      }
+      else // Update existing script
+         hStmt = DBPrepare(hdb, _T("UPDATE script_library SET script_name=?,script_code=? WHERE script_id=?"));
 
-   ReloadScript(id);
+      if (hStmt != NULL)
+      {
+         DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, name, DB_BIND_STATIC);
+         DBBind(hStmt, 2, DB_SQLTYPE_TEXT, code, DB_BIND_STATIC);
+         DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, id);
+         if (newScript)
+            DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, guid);
+
+         if (DBExecute(hStmt))
+            ReloadScript(id);
+         DBFreeStatement(hStmt);
+      }
+      DBConnectionPoolReleaseConnection(hdb);
+   }
 }
 
 /**
index 41d87c8..2d86165 100644 (file)
@@ -6720,7 +6720,7 @@ void ClientSession::sendAllTraps2(UINT32 dwRqId)
        if (checkSysAccessRights(SYSTEM_ACCESS_CONFIGURE_TRAPS))
    {
       msg.setField(VID_RCC, RCC_SUCCESS);
-      CreateTrapCfgMessage(msg);
+      CreateTrapCfgMessage(&msg);
    }
    else
    {
@@ -8285,38 +8285,15 @@ void ClientSession::sendServerStats(UINT32 dwRqId)
 void ClientSession::sendScriptList(UINT32 dwRqId)
 {
    NXCPMessage msg;
-   DB_RESULT hResult;
-   UINT32 i, dwNumScripts, dwId;
-   TCHAR szBuffer[MAX_DB_STRING];
-
    msg.setCode(CMD_REQUEST_COMPLETED);
    msg.setId(dwRqId);
    if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_SCRIPTS)
    {
-      DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-      hResult = DBSelect(hdb, _T("SELECT script_id,script_name FROM script_library"));
-      if (hResult != NULL)
-      {
-         msg.setField(VID_RCC, RCC_SUCCESS);
-         dwNumScripts = DBGetNumRows(hResult);
-         msg.setField(VID_NUM_SCRIPTS, dwNumScripts);
-         for(i = 0, dwId = VID_SCRIPT_LIST_BASE; i < dwNumScripts; i++)
-         {
-            msg.setField(dwId++, DBGetFieldULong(hResult, i, 0));
-            msg.setField(dwId++, DBGetField(hResult, i, 1, szBuffer, MAX_DB_STRING));
-         }
-         DBFreeResult(hResult);
-      }
-      else
-      {
-         msg.setField(VID_RCC, RCC_DB_FAILURE);
-      }
-      DBConnectionPoolReleaseConnection(hdb);
+      g_pScriptLibrary->fillMessage(&msg);
+      msg.setField(VID_RCC, RCC_SUCCESS);;
    }
    else
-   {
       msg.setField(VID_RCC, RCC_ACCESS_DENIED);
-   }
    sendMessage(&msg);
 }
 
@@ -8326,46 +8303,20 @@ void ClientSession::sendScriptList(UINT32 dwRqId)
 void ClientSession::sendScript(NXCPMessage *pRequest)
 {
    NXCPMessage msg;
-   DB_RESULT hResult;
-   UINT32 dwScriptId;
-   TCHAR *pszCode, szQuery[256];
-
    msg.setCode(CMD_REQUEST_COMPLETED);
    msg.setId(pRequest->getId());
+
    if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_SCRIPTS)
    {
-      DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-      dwScriptId = pRequest->getFieldAsUInt32(VID_SCRIPT_ID);
-      _sntprintf(szQuery, 256, _T("SELECT script_name,script_code FROM script_library WHERE script_id=%d"), dwScriptId);
-      hResult = DBSelect(hdb, szQuery);
-      if (hResult != NULL)
-      {
-         if (DBGetNumRows(hResult) > 0)
-         {
-                               TCHAR name[MAX_DB_STRING];
-
-            msg.setField(VID_NAME, DBGetField(hResult, 0, 0, name, MAX_DB_STRING));
-
-                               pszCode = DBGetField(hResult, 0, 1, NULL, 0);
-            msg.setField(VID_SCRIPT_CODE, pszCode);
-            free(pszCode);
-         }
-         else
-         {
-            msg.setField(VID_RCC, RCC_INVALID_SCRIPT_ID);
-         }
-         DBFreeResult(hResult);
-      }
+      UINT32 id = pRequest->getFieldAsUInt32(VID_SCRIPT_ID);
+      NXSL_LibraryScript *script = g_pScriptLibrary->findScript(id);
+      if (script != NULL)
+         script->fillMessage(&msg);
       else
-      {
-         msg.setField(VID_RCC, RCC_DB_FAILURE);
-      }
-      DBConnectionPoolReleaseConnection(hdb);
+         msg.setField(VID_RCC, RCC_INVALID_SCRIPT_ID);
    }
    else
-   {
       msg.setField(VID_RCC, RCC_ACCESS_DENIED);
-   }
    sendMessage(&msg);
 }
 
@@ -8375,70 +8326,14 @@ void ClientSession::sendScript(NXCPMessage *pRequest)
 void ClientSession::updateScript(NXCPMessage *pRequest)
 {
    NXCPMessage msg;
+   UINT32 scriptId = 0;
 
    msg.setCode(CMD_REQUEST_COMPLETED);
    msg.setId(pRequest->getId());
    if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_SCRIPTS)
    {
-      TCHAR scriptName[MAX_DB_STRING];
-      pRequest->getFieldAsString(VID_NAME, scriptName, MAX_DB_STRING);
-      if (IsValidScriptName(scriptName))
-      {
-         TCHAR *scriptSource = pRequest->getFieldAsString(VID_SCRIPT_CODE);
-         if (scriptSource != NULL)
-         {
-            UINT32 scriptId = pRequest->getFieldAsUInt32(VID_SCRIPT_ID);
-
-            DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-
-            DB_STATEMENT hStmt;
-            if (scriptId == 0)
-            {
-               // New script
-               scriptId = CreateUniqueId(IDG_SCRIPT);
-               hStmt = DBPrepare(hdb, _T("INSERT INTO script_library (script_name,script_code,script_id) VALUES (?,?,?)"));
-            }
-            else
-            {
-               hStmt = DBPrepare(hdb, _T("UPDATE script_library SET script_name=?,script_code=? WHERE script_id=?"));
-            }
-
-            if (hStmt != NULL)
-            {
-               DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, scriptName, DB_BIND_STATIC);
-               DBBind(hStmt, 2, DB_SQLTYPE_TEXT, scriptSource, DB_BIND_STATIC);
-               DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, scriptId);
-
-               if (DBExecute(hStmt))
-               {
-                  ReloadScript(scriptId);
-                  msg.setField(VID_RCC, RCC_SUCCESS);
-                  msg.setField(VID_SCRIPT_ID, scriptId);
-               }
-               else
-               {
-                  msg.setField(VID_RCC, RCC_DB_FAILURE);
-               }
-
-               DBFreeStatement(hStmt);
-            }
-            else
-            {
-               msg.setField(VID_RCC, RCC_DB_FAILURE);
-            }
-
-            free(scriptSource);
-            DBConnectionPoolReleaseConnection(hdb);
-         }
-         else
-         {
-            msg.setField(VID_RCC, RCC_INVALID_REQUEST);
-         }
-      }
-      else
-      {
-         msg.setField(VID_RCC, RCC_INVALID_SCRIPT_NAME);
-      }
+      msg.setField(VID_RCC, UpdateScript(pRequest, &scriptId));
+      msg.setField(VID_SCRIPT_ID, scriptId);
    }
    else
    {
@@ -8453,42 +8348,12 @@ void ClientSession::updateScript(NXCPMessage *pRequest)
 void ClientSession::renameScript(NXCPMessage *pRequest)
 {
    NXCPMessage msg;
-   TCHAR szQuery[4096], szName[MAX_DB_STRING];
-   UINT32 dwScriptId;
 
    msg.setCode(CMD_REQUEST_COMPLETED);
    msg.setId(pRequest->getId());
    if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_SCRIPTS)
    {
-      dwScriptId = pRequest->getFieldAsUInt32(VID_SCRIPT_ID);
-      pRequest->getFieldAsString(VID_NAME, szName, MAX_DB_STRING);
-      if (IsValidScriptName(szName))
-      {
-         if (IsValidScriptId(dwScriptId))
-         {
-            DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-            _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("UPDATE script_library SET script_name=%s WHERE script_id=%d"),
-                      (const TCHAR *)DBPrepareString(hdb, szName), dwScriptId);
-            if (DBQuery(hdb, szQuery))
-            {
-               ReloadScript(dwScriptId);
-               msg.setField(VID_RCC, RCC_SUCCESS);
-            }
-            else
-            {
-               msg.setField(VID_RCC, RCC_DB_FAILURE);
-            }
-            DBConnectionPoolReleaseConnection(hdb);
-         }
-         else
-         {
-            msg.setField(VID_RCC, RCC_INVALID_SCRIPT_ID);
-         }
-      }
-      else
-      {
-         msg.setField(VID_RCC, RCC_INVALID_SCRIPT_NAME);
-      }
+      msg.setField(VID_RCC, RenameScript(pRequest));
    }
    else
    {
@@ -8503,35 +8368,12 @@ void ClientSession::renameScript(NXCPMessage *pRequest)
 void ClientSession::deleteScript(NXCPMessage *pRequest)
 {
    NXCPMessage msg;
-   TCHAR szQuery[256];
-   UINT32 dwScriptId;
 
    msg.setCode(CMD_REQUEST_COMPLETED);
    msg.setId(pRequest->getId());
    if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_SCRIPTS)
    {
-      dwScriptId = pRequest->getFieldAsUInt32(VID_SCRIPT_ID);
-      if (IsValidScriptId(dwScriptId))
-      {
-         DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-         _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("DELETE FROM script_library WHERE script_id=%d"), dwScriptId);
-         if (DBQuery(hdb, szQuery))
-         {
-            g_pScriptLibrary->lock();
-            g_pScriptLibrary->deleteScript(dwScriptId);
-            g_pScriptLibrary->unlock();
-            msg.setField(VID_RCC, RCC_SUCCESS);
-         }
-         else
-         {
-            msg.setField(VID_RCC, RCC_DB_FAILURE);
-         }
-         DBConnectionPoolReleaseConnection(hdb);
-      }
-      else
-      {
-         msg.setField(VID_RCC, RCC_INVALID_SCRIPT_ID);
-      }
+      msg.setField(VID_RCC, DeleteScript(pRequest));
    }
    else
    {
@@ -14171,6 +14013,7 @@ void ClientSession::compileScript(NXCPMessage *request)
          msg.setField(VID_ERROR_LINE, (INT32)errorLine);
       }
       msg.setField(VID_RCC, RCC_SUCCESS);
+      free(source);
        }
        else
        {
index e9dec2f..9f2966e 100644 (file)
@@ -22,6 +22,9 @@
 
 #include "nxcore.h"
 
+#define BY_OBJECT_ID 0
+#define BY_POSITION 1
+
 /**
  * Externals
  */
@@ -41,104 +44,314 @@ UINT64 g_snmpTrapsReceived = 0;
  * Static data
  */
 static MUTEX m_mutexTrapCfgAccess = NULL;
-static NXC_TRAP_CFG_ENTRY *m_pTrapCfg = NULL;
-static UINT32 m_dwNumTraps = 0;
+static ObjectArray<SNMP_TrapCfg> m_trapCfgList(16, 4, true);
 static BOOL m_bLogAllTraps = FALSE;
 static INT64 m_qnTrapId = 1;
 static bool s_allowVarbindConversion = true;
 static UINT16 m_wTrapPort = 162;
 
 /**
- * Load trap configuration from database
+ * Create new SNMP trap configuration object
  */
-static BOOL LoadTrapCfg()
+SNMP_TrapCfg::SNMP_TrapCfg()
 {
-   DB_RESULT hResult;
-   BOOL bResult = TRUE;
-   TCHAR *pszOID, szQuery[256], szBuffer[MAX_DB_STRING];
-   UINT32 i, j, pdwBuffer[MAX_OID_LEN];
+   m_guid = uuid::generate();
+   m_id = CreateUniqueId(IDG_SNMP_TRAP);
+   m_objectId = new SNMP_ObjectId();
+   m_eventCode = EVENT_SNMP_UNMATCHED_TRAP;
+   m_pMaps = new ObjectArray<SNMP_TrapParamMap>(4, 2, true);
+   nx_strncpy(m_description, _T(""), 1);
+   nx_strncpy(m_userTag, _T(""), 1);
+}
 
-   DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
+/**
+ * Create SNMP trap configuration object from database
+ */
+SNMP_TrapCfg::SNMP_TrapCfg(DB_RESULT trapResult, DB_STATEMENT stmt, int row)
+{
+   m_id = DBGetFieldULong(trapResult, row, 0);
+   TCHAR buffer[MAX_OID_LENGTH];
+   m_objectId = new SNMP_ObjectId(SNMP_ObjectId::parse(DBGetField(trapResult, row, 1, buffer, MAX_DB_STRING)));
+   m_eventCode = DBGetFieldULong(trapResult, row, 2);
+   DBGetField(trapResult, row, 3, m_description, MAX_DB_STRING);
+   DBGetField(trapResult, row, 4, m_userTag, MAX_DB_STRING);
+   m_guid = DBGetFieldGUID(trapResult, row, 5);
+
+   m_pMaps = new ObjectArray<SNMP_TrapParamMap>(4, 2, true);
+   DBBind(stmt, 1, DB_SQLTYPE_INTEGER, m_id);
+   DB_RESULT mapResult = DBSelectPrepared(stmt);
+
+   if (mapResult != NULL)
+   {
+      UINT32 mapCount = DBGetNumRows(mapResult);
+      SNMP_TrapParamMap *param;
+      for(int i = 0; i < mapCount; i++)
+      {
+         param = new SNMP_TrapParamMap(mapResult, i);
+         if (param->getOidLength() <= 0)
+            nxlog_write(MSG_INVALID_TRAP_ARG_OID, EVENTLOG_ERROR_TYPE, "sd", (const TCHAR *)param->getOid()->toString(), m_id);
+         m_pMaps->add(param);
 
-   // Load traps
-   hResult = DBSelect(hdb, _T("SELECT trap_id,snmp_oid,event_code,description,user_tag FROM snmp_trap_cfg"));
-   if (hResult != NULL)
+      }
+      DBFreeResult(mapResult);
+   }
+}
+
+/**
+ * Create SNMP trap configuration object from config entry
+ */
+SNMP_TrapCfg::SNMP_TrapCfg(ConfigEntry *entry, const uuid& guid, UINT32 id, UINT32 eventCode)
+{
+   if (id == 0)
+      m_id = CreateUniqueId(IDG_SNMP_TRAP);
+   else
+      m_id = id;
+
+   m_guid = guid;
+   m_objectId = new SNMP_ObjectId(SNMP_ObjectId::parse(entry->getSubEntryValue(_T("oid"), 0, _T(""))));
+   m_eventCode = eventCode;
+   nx_strncpy(m_description, entry->getSubEntryValue(_T("description"), 0, _T("")), MAX_DB_STRING);
+   nx_strncpy(m_userTag, entry->getSubEntryValue(_T("userTag"), 0, _T("")), MAX_USERTAG_LENGTH);
+
+   m_pMaps = new ObjectArray<SNMP_TrapParamMap>(4, 2, true);
+   ConfigEntry *parametersRoot = entry->findEntry(_T("parameters"));
+   if (parametersRoot != NULL)
    {
-      m_dwNumTraps = DBGetNumRows(hResult);
-      m_pTrapCfg = (NXC_TRAP_CFG_ENTRY *)malloc(sizeof(NXC_TRAP_CFG_ENTRY) * m_dwNumTraps);
-      memset(m_pTrapCfg, 0, sizeof(NXC_TRAP_CFG_ENTRY) * m_dwNumTraps);
-      for(i = 0; i < m_dwNumTraps; i++)
+      SNMP_TrapParamMap *param;
+      ObjectArray<ConfigEntry> *parameters = parametersRoot->getOrderedSubEntries(_T("parameter#*"));
+      if (parameters->size() > 0)
       {
-         m_pTrapCfg[i].dwId = DBGetFieldULong(hResult, i, 0);
-         m_pTrapCfg[i].dwOidLen = (UINT32)SNMPParseOID(DBGetField(hResult, i, 1, szBuffer, MAX_DB_STRING),
-                                                       pdwBuffer, MAX_OID_LEN);
-         if (m_pTrapCfg[i].dwOidLen > 0)
+         for(int i = 0; i < parameters->size(); i++)
          {
-            m_pTrapCfg[i].pdwObjectId = (UINT32 *)nx_memdup(pdwBuffer, m_pTrapCfg[i].dwOidLen * sizeof(UINT32));
+            param = new SNMP_TrapParamMap(parameters->get(i));
+            if (param->getOidLength() <= 0)
+               nxlog_write(MSG_INVALID_TRAP_ARG_OID, EVENTLOG_ERROR_TYPE, "sd", (const TCHAR *)param->getOid()->toString(), m_id);
+            m_pMaps->add(param);
          }
-         else
-         {
-            nxlog_write(MSG_INVALID_TRAP_OID, NXLOG_ERROR, "s",
-                        DBGetField(hResult, i, 1, szBuffer, MAX_DB_STRING));
-            bResult = FALSE;
-         }
-         m_pTrapCfg[i].dwEventCode = DBGetFieldULong(hResult, i, 2);
-         DBGetField(hResult, i, 3, m_pTrapCfg[i].szDescription, MAX_DB_STRING);
-         DBGetField(hResult, i, 4, m_pTrapCfg[i].szUserTag, MAX_USERTAG_LENGTH);
       }
-      DBFreeResult(hResult);
+      delete parameters;
+   }
+}
 
-      // Load parameter mappings
-      for(i = 0; i < m_dwNumTraps; i++)
+/**
+ * Create SNMP trap configuration object from NXCPMessage
+ */
+SNMP_TrapCfg::SNMP_TrapCfg(NXCPMessage *msg)
+{
+   UINT32 buffer[MAX_OID_LENGTH];
+
+   m_id = msg->getFieldAsUInt32(VID_TRAP_ID);
+   msg->getFieldAsInt32Array(VID_TRAP_OID, msg->getFieldAsUInt32(VID_TRAP_OID_LEN), buffer);
+   m_objectId = new SNMP_ObjectId(buffer, msg->getFieldAsUInt32(VID_TRAP_OID_LEN));
+   m_eventCode = msg->getFieldAsUInt32(VID_EVENT_CODE);
+   msg->getFieldAsString(VID_DESCRIPTION, m_description, MAX_DB_STRING);
+   msg->getFieldAsString(VID_USER_TAG, m_userTag, MAX_USERTAG_LENGTH);
+
+   // Read new mappings from message
+   UINT32 numMaps = msg->getFieldAsUInt32(VID_TRAP_NUM_MAPS);
+   UINT32 base = VID_TRAP_PBASE;
+   m_pMaps = new ObjectArray<SNMP_TrapParamMap>(numMaps, 4, true);
+
+   for(int i = 0; i < numMaps; i++, base += 10)
+   {
+      m_pMaps->add(new SNMP_TrapParamMap(msg, base));
+   }
+}
+
+/**
+ * Destructor for SNMP trap configuration object
+ */
+SNMP_TrapCfg::~SNMP_TrapCfg()
+{
+   delete m_objectId;
+   delete m_pMaps;
+}
+
+/**
+ * Fill NXCP message with trap configuration data
+ */
+void SNMP_TrapCfg::fillMessage(NXCPMessage *msg)
+{
+   msg->setField(VID_TRAP_ID, m_id);
+   msg->setField(VID_TRAP_OID_LEN, (UINT32)m_objectId->length());
+   msg->setFieldFromInt32Array(VID_TRAP_OID, (UINT32)m_objectId->length(), m_objectId->value());
+   msg->setField(VID_EVENT_CODE, m_eventCode);
+   msg->setField(VID_DESCRIPTION, m_description);
+   msg->setField(VID_USER_TAG, m_userTag);
+
+   msg->setField(VID_TRAP_NUM_MAPS, m_pMaps->size());
+   UINT32 base = VID_TRAP_PBASE;
+   for(int i = 0; i < m_pMaps->size(); i++, base += 10)
+   {
+      m_pMaps->get(i)->fillMessage(msg, base);
+   }
+}
+
+/**
+ * Fill NXCP message with trap configuration for list
+ */
+void SNMP_TrapCfg::fillMessage(NXCPMessage *msg, UINT32 base)
+{
+   msg->setField(base, m_id);
+   msg->setField(base + 1, m_description);
+   msg->setFieldFromInt32Array(base + 2, (UINT32)m_objectId->length(), m_objectId->value());
+   msg->setField(base + 3, m_eventCode);
+}
+
+/**
+ * Notify clients about trap configuration change
+ */
+void NotifyOnTrapCfgChangeCB(ClientSession *session, void *arg)
+{
+   if (session->isAuthenticated())
+      session->postMessage((NXCPMessage *)arg);
+}
+
+/**
+ * Notify clients of trap cfg change
+ */
+void SNMP_TrapCfg::notifyOnTrapCfgChange(UINT32 code)
+{
+   NXCPMessage msg;
+
+   msg.setCode(CMD_TRAP_CFG_UPDATE);
+   msg.setField(VID_NOTIFICATION_CODE, code);
+   fillMessage(&msg);
+   EnumerateClientSessions(NotifyOnTrapCfgChangeCB, &msg);
+}
+
+/**
+ * SNMP trap parameter map default constructor
+ */
+SNMP_TrapParamMap::SNMP_TrapParamMap()
+{
+   m_objectId = new SNMP_ObjectId();
+   m_position = 0;
+   m_flags = 0;
+   nx_strncpy(m_description, _T(""), 1);
+}
+
+/**
+ * Create SNMP trap parameter map object from database
+ */
+SNMP_TrapParamMap::SNMP_TrapParamMap(DB_RESULT mapResult, int row)
+{
+   TCHAR oid[MAX_DB_STRING];
+   DBGetField(mapResult, row, 0, oid, MAX_DB_STRING);
+
+   if (!_tcsncmp(oid, _T("POS:"), 4))
+   {
+      m_objectId = NULL;
+      m_position = _tcstoul(&oid[4], NULL, 10);
+   }
+   else
+   {
+      m_objectId = new SNMP_ObjectId(SNMP_ObjectId::parse(oid));
+      m_position = 0;
+   }
+
+   DBGetField(mapResult, row, 1, m_description, MAX_DB_STRING);
+   m_flags = DBGetFieldULong(mapResult, row, 2);
+}
+
+/**
+ * Create SNMP trap parameter map object from config entry
+ */
+SNMP_TrapParamMap::SNMP_TrapParamMap(ConfigEntry *entry)
+{
+   int position = entry->getSubEntryValueAsInt(_T("position"), 0, -1);
+   if (position > 0)
+   {
+      m_objectId = NULL;
+      m_position = position; // Positional parameter
+   }
+   else
+   {
+      m_objectId = new SNMP_ObjectId(SNMP_ObjectId::parse(entry->getSubEntryValue(_T("oid"), 0, _T("")))); // OID parameter
+      m_position = 0;
+   }
+
+   nx_strncpy(m_description, entry->getSubEntryValue(_T("description"), 0, _T("")), MAX_DB_STRING);
+   m_flags = entry->getSubEntryValueAsUInt(_T("flags"), 0, 0);
+}
+
+/**
+ * Create SNMP trap parameter map object from NXCPMessage
+ */
+SNMP_TrapParamMap::SNMP_TrapParamMap(NXCPMessage *msg, UINT32 base)
+{
+   m_flags = msg->getFieldAsUInt32(base);
+   msg->getFieldAsString(base + 1, m_description, MAX_DB_STRING);
+   if (msg->getFieldAsUInt32(base + 2) == BY_POSITION)
+   {
+      m_objectId = NULL;
+      m_position = msg->getFieldAsUInt32(base + 3);
+   }
+   else
+   {
+      UINT32 buffer[MAX_OID_LENGTH];
+      msg->getFieldAsInt32Array(base + 3, msg->getFieldAsUInt32(base + 4), buffer);
+      m_objectId = new SNMP_ObjectId(buffer, msg->getFieldAsUInt32(base + 4));
+   }
+}
+
+/**
+ * Destructor for SNMP trap parameter map object
+ */
+SNMP_TrapParamMap::~SNMP_TrapParamMap()
+{
+   delete m_objectId;
+}
+
+/**
+ * Fill NXCP message with trap parameter map configuration data
+ */
+void SNMP_TrapParamMap::fillMessage(NXCPMessage *msg, UINT32 base)
+{
+   msg->setField(base, isPosition());
+   if (isPosition())
+      msg->setField(base + 1, m_position);
+   else
+      msg->setFieldFromInt32Array(base + 1, m_objectId->length(), m_objectId->value());
+   msg->setField(base + 2, m_description);
+   msg->setField(base + 3, m_flags);
+
+}
+
+/**
+ * Load trap configuration from database
+ */
+void LoadTrapCfg()
+{
+   SNMP_TrapCfg *trapCfg;
+   TCHAR buffer[MAX_DB_STRING];
+
+   DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
+
+   // Load traps
+   DB_RESULT hResult = DBSelect(hdb, _T("SELECT trap_id,snmp_oid,event_code,description,user_tag,guid FROM snmp_trap_cfg"));
+   DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT snmp_oid,description,flags FROM snmp_trap_pmap WHERE trap_id=? ORDER BY parameter"));
+   if (hResult != NULL)
+   {
+      if (hStmt != NULL)
       {
-         _sntprintf(szQuery, 256, _T("SELECT snmp_oid,description,flags FROM snmp_trap_pmap ")
-                                  _T("WHERE trap_id=%d ORDER BY parameter"),
-                    m_pTrapCfg[i].dwId);
-         hResult = DBSelect(hdb, szQuery);
-         if (hResult != NULL)
+         UINT32 numRows = DBGetNumRows(hResult);
+         for(int i = 0; i < numRows; i++)
          {
-            m_pTrapCfg[i].dwNumMaps = DBGetNumRows(hResult);
-            m_pTrapCfg[i].pMaps = (NXC_OID_MAP *)malloc(sizeof(NXC_OID_MAP) * m_pTrapCfg[i].dwNumMaps);
-            for(j = 0; j < m_pTrapCfg[i].dwNumMaps; j++)
+            trapCfg = new SNMP_TrapCfg(hResult, hStmt, i);
+            if (trapCfg->getOidLength() <= 0)
             {
-               pszOID = DBGetField(hResult, j, 0, szBuffer, MAX_DB_STRING);
-               if (!_tcsncmp(pszOID, _T("POS:"), 4))
-               {
-                  m_pTrapCfg[i].pMaps[j].dwOidLen = _tcstoul(&pszOID[4], NULL, 10) | 0x80000000;
-                  m_pTrapCfg[i].pMaps[j].pdwObjectId = NULL;
-               }
-               else
-               {
-                  m_pTrapCfg[i].pMaps[j].dwOidLen = (UINT32)SNMPParseOID(pszOID, pdwBuffer, MAX_OID_LEN);
-                  if (m_pTrapCfg[i].pMaps[j].dwOidLen > 0)
-                  {
-                     m_pTrapCfg[i].pMaps[j].pdwObjectId =
-                        (UINT32 *)nx_memdup(pdwBuffer, m_pTrapCfg[i].pMaps[j].dwOidLen * sizeof(UINT32));
-                  }
-                  else
-                  {
-                     nxlog_write(MSG_INVALID_TRAP_ARG_OID, EVENTLOG_ERROR_TYPE, "sd",
-                              DBGetField(hResult, j, 0, szBuffer, MAX_DB_STRING), m_pTrapCfg[i].dwId);
-                     bResult = FALSE;
-                  }
-               }
-               DBGetField(hResult, j, 1, m_pTrapCfg[i].pMaps[j].szDescription, MAX_DB_STRING);
-                                       m_pTrapCfg[i].pMaps[j].dwFlags = DBGetFieldULong(hResult, j, 2);
+               nxlog_write(MSG_INVALID_TRAP_OID, NXLOG_ERROR, "s",
+                           DBGetField(hResult, i, 1, buffer, MAX_DB_STRING));
             }
-            DBFreeResult(hResult);
-         }
-         else
-         {
-            bResult = FALSE;
+            m_trapCfgList.add(trapCfg);
          }
+         DBFreeStatement(hStmt);
       }
+      DBFreeResult(hResult);
    }
-   else
-   {
-      bResult = FALSE;
-   }
+
    DBConnectionPoolReleaseConnection(hdb);
-   return bResult;
 }
 
 /**
@@ -146,15 +359,13 @@ static BOOL LoadTrapCfg()
  */
 void InitTraps()
 {
-       DB_RESULT hResult;
-
        m_mutexTrapCfgAccess = MutexCreate();
        LoadTrapCfg();
        m_bLogAllTraps = ConfigReadInt(_T("LogAllSNMPTraps"), FALSE);
        s_allowVarbindConversion = ConfigReadInt(_T("AllowTrapVarbindsConversion"), 1) ? true : false;
 
        DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-       hResult = DBSelect(hdb, _T("SELECT max(trap_id) FROM snmp_trap_log"));
+       DB_RESULT hResult = DBSelect(hdb, _T("SELECT max(trap_id) FROM snmp_trap_log"));
        if (hResult != NULL)
        {
                if (DBGetNumRows(hResult) > 0)
@@ -174,7 +385,8 @@ static void GenerateTrapEvent(UINT32 dwObjectId, UINT32 dwIndex, SNMP_PDU *pdu,
    TCHAR *argList[32], szBuffer[256];
    TCHAR *names[33];
    char szFormat[] = "sssssssssssssssssssssssssssssssss";
-   UINT32 i;
+   SNMP_TrapCfg *trapCfg = m_trapCfgList.get(dwIndex);
+   UINT32 i, numMaps = trapCfg->getNumMaps();
    int iResult;
 
    memset(argList, 0, sizeof(argList));
@@ -182,17 +394,17 @@ static void GenerateTrapEvent(UINT32 dwObjectId, UINT32 dwIndex, SNMP_PDU *pdu,
    names[0] = (TCHAR *)_T("oid");
 
        // Extract varbinds from trap and add them as event's parameters
-   for(i = 0; i < m_pTrapCfg[dwIndex].dwNumMaps; i++)
+   for(i = 0; i < numMaps; i++)
    {
-      if (m_pTrapCfg[dwIndex].pMaps[i].dwOidLen & 0x80000000)
+      if (trapCfg->getMap(i)->isPosition())
       {
                        // Extract by varbind position
-         SNMP_Variable *varbind = pdu->getVariable((m_pTrapCfg[dwIndex].pMaps[i].dwOidLen & 0x7FFFFFFF) - 1);
+         SNMP_Variable *varbind = pdu->getVariable(trapCfg->getMap(i)->getOidLength()- 1);
          if (varbind != NULL)
          {
                                bool convertToHex = true;
                                argList[i] = _tcsdup(
-               (s_allowVarbindConversion && !(m_pTrapCfg[dwIndex].pMaps[i].dwFlags & TRAP_VARBIND_FORCE_TEXT)) ?
+               (s_allowVarbindConversion && !(trapCfg->getMap(i)->getFlags() & TRAP_VARBIND_FORCE_TEXT)) ?
                   varbind->getValueAsPrintableString(szBuffer, 256, &convertToHex) :
                   varbind->getValueAsString(szBuffer, 256));
                                names[i + 1] = _tcsdup(varbind->getName().toString());
@@ -204,14 +416,12 @@ static void GenerateTrapEvent(UINT32 dwObjectId, UINT32 dwIndex, SNMP_PDU *pdu,
          for(int j = 0; j < pdu->getNumVariables(); j++)
          {
             SNMP_Variable *varbind = pdu->getVariable(j);
-            iResult = varbind->getName().compare(
-                  m_pTrapCfg[dwIndex].pMaps[i].pdwObjectId,
-                  m_pTrapCfg[dwIndex].pMaps[i].dwOidLen);
+            iResult = varbind->getName().compare(*(trapCfg->getMap(i)->getOid()));
             if ((iResult == OID_EQUAL) || (iResult == OID_LONGER))
             {
                                        bool convertToHex = true;
                                        argList[i] = _tcsdup(
-                  (s_allowVarbindConversion && !(m_pTrapCfg[dwIndex].pMaps[i].dwFlags & TRAP_VARBIND_FORCE_TEXT)) ?
+                  (s_allowVarbindConversion && !(trapCfg->getMap(i)->getFlags() & TRAP_VARBIND_FORCE_TEXT)) ?
                      varbind->getValueAsPrintableString(szBuffer, 256, &convertToHex) :
                      varbind->getValueAsString(szBuffer, 256));
                    names[i + 1] = _tcsdup(varbind->getName().toString());
@@ -221,29 +431,29 @@ static void GenerateTrapEvent(UINT32 dwObjectId, UINT32 dwIndex, SNMP_PDU *pdu,
       }
    }
 
-   argList[m_pTrapCfg[dwIndex].dwNumMaps] = (TCHAR *)malloc(16 * sizeof(TCHAR));
-   _sntprintf(argList[m_pTrapCfg[dwIndex].dwNumMaps], 16, _T("%d"), sourcePort);
-   names[m_pTrapCfg[dwIndex].dwNumMaps + 1] = (TCHAR *)_T("sourcePort");
-   szFormat[m_pTrapCfg[dwIndex].dwNumMaps + 2] = 0;
+   argList[numMaps] = (TCHAR *)malloc(16 * sizeof(TCHAR));
+   _sntprintf(argList[numMaps], 16, _T("%d"), sourcePort);
+   names[numMaps + 1] = (TCHAR *)_T("sourcePort");
+   szFormat[numMaps + 2] = 0;
    PostEventWithTagAndNames(
-      m_pTrapCfg[dwIndex].dwEventCode, dwObjectId,
-          m_pTrapCfg[dwIndex].szUserTag, szFormat, (const TCHAR **)names,
-      (const TCHAR *)pdu->getTrapId()->toString(),
-      argList[0], argList[1], argList[2], argList[3],
-      argList[4], argList[5], argList[6], argList[7],
-      argList[8], argList[9], argList[10], argList[11],
-      argList[12], argList[13], argList[14], argList[15],
-      argList[16], argList[17], argList[18], argList[19],
-      argList[20], argList[21], argList[22], argList[23],
-      argList[24], argList[25], argList[26], argList[27],
-      argList[28], argList[29], argList[30], argList[31]);
-
-   for(i = 0; i < m_pTrapCfg[dwIndex].dwNumMaps; i++)
+            trapCfg->getEventCode(), dwObjectId,
+            trapCfg->getUserTag(), szFormat, (const TCHAR **)names,
+            (const TCHAR *)pdu->getTrapId()->toString(),
+            argList[0], argList[1], argList[2], argList[3],
+            argList[4], argList[5], argList[6], argList[7],
+            argList[8], argList[9], argList[10], argList[11],
+            argList[12], argList[13], argList[14], argList[15],
+            argList[16], argList[17], argList[18], argList[19],
+            argList[20], argList[21], argList[22], argList[23],
+            argList[24], argList[25], argList[26], argList[27],
+            argList[28], argList[29], argList[30], argList[31]);
+
+   for(i = 0; i < numMaps; i++)
    {
       free(argList[i]);
       free(names[i + 1]);
    }
-   free(argList[m_pTrapCfg[dwIndex].dwNumMaps]);
+   free(argList[numMaps]);
 }
 
 /**
@@ -360,22 +570,22 @@ void ProcessTrap(SNMP_PDU *pdu, const InetAddress& srcAddr, UINT32 zoneId, int s
          MutexLock(m_mutexTrapCfgAccess);
 
          // Try to find closest match
-         for(i = 0, dwMatchLen = 0; i < m_dwNumTraps; i++)
+         for(i = 0, dwMatchLen = 0; i < m_trapCfgList.size(); i++)
          {
-            if (m_pTrapCfg[i].dwOidLen > 0)
+            if (m_trapCfgList.get(i)->getOidLength() > 0)
             {
-               iResult = pdu->getTrapId()->compare(m_pTrapCfg[i].pdwObjectId, m_pTrapCfg[i].dwOidLen);
+               iResult = pdu->getTrapId()->compare(*(m_trapCfgList.get(i)->getOid()));
                if (iResult == OID_EQUAL)
                {
-                  dwMatchLen = m_pTrapCfg[i].dwOidLen;
+                  dwMatchLen = m_trapCfgList.get(i)->getOidLength();
                   dwMatchIdx = i;
                   break;   // Find exact match
                }
                else if (iResult == OID_LONGER)
                {
-                  if (m_pTrapCfg[i].dwOidLen > dwMatchLen)
+                  if (m_trapCfgList.get(i)->getOidLength() > dwMatchLen)
                   {
-                     dwMatchLen = m_pTrapCfg[i].dwOidLen;
+                     dwMatchLen = m_trapCfgList.get(i)->getOidLength();
                      dwMatchIdx = i;
                   }
                }
@@ -700,36 +910,10 @@ THREAD_RESULT THREAD_CALL SNMPTrapReceiver(void *pArg)
 }
 
 /**
- * Fill NXCP message with trap configuration data
- */
-static void FillTrapConfigDataMsg(NXCPMessage &msg, NXC_TRAP_CFG_ENTRY *trap)
-{
-   UINT32 i, dwId1, dwId2, dwId3, dwId4;
-
-       msg.setField(VID_TRAP_ID, trap->dwId);
-   msg.setField(VID_TRAP_OID_LEN, trap->dwOidLen);
-   msg.setFieldFromInt32Array(VID_TRAP_OID, trap->dwOidLen, trap->pdwObjectId);
-   msg.setField(VID_EVENT_CODE, trap->dwEventCode);
-   msg.setField(VID_DESCRIPTION, trap->szDescription);
-   msg.setField(VID_USER_TAG, trap->szUserTag);
-   msg.setField(VID_TRAP_NUM_MAPS, trap->dwNumMaps);
-   for(i = 0, dwId1 = VID_TRAP_PLEN_BASE, dwId2 = VID_TRAP_PNAME_BASE, dwId3 = VID_TRAP_PDESCR_BASE, dwId4 = VID_TRAP_PFLAGS_BASE;
-       i < trap->dwNumMaps; i++, dwId1++, dwId2++, dwId3++, dwId4++)
-   {
-      msg.setField(dwId1, trap->pMaps[i].dwOidLen);
-      if ((trap->pMaps[i].dwOidLen & 0x80000000) == 0)
-         msg.setFieldFromInt32Array(dwId2, trap->pMaps[i].dwOidLen, trap->pMaps[i].pdwObjectId);
-      msg.setField(dwId3, trap->pMaps[i].szDescription);
-               msg.setField(dwId4, trap->pMaps[i].dwFlags);
-   }
-}
-
-/**
  * Send all trap configuration records to client
  */
 void SendTrapsToClient(ClientSession *pSession, UINT32 dwRqId)
 {
-   UINT32 i;
    NXCPMessage msg;
 
    // Prepare message
@@ -737,9 +921,9 @@ void SendTrapsToClient(ClientSession *pSession, UINT32 dwRqId)
    msg.setId(dwRqId);
 
    MutexLock(m_mutexTrapCfgAccess);
-   for(i = 0; i < m_dwNumTraps; i++)
+   for(int i = 0; i < m_trapCfgList.size(); i++)
    {
-               FillTrapConfigDataMsg(msg, &m_pTrapCfg[i]);
+      m_trapCfgList.get(i)->fillMessage(&msg);
       pSession->sendMessage(&msg);
       msg.deleteAllFields();
    }
@@ -752,42 +936,15 @@ void SendTrapsToClient(ClientSession *pSession, UINT32 dwRqId)
 /**
  * Prepare single message with all trap configuration records
  */
-void CreateTrapCfgMessage(NXCPMessage &msg)
+void CreateTrapCfgMessage(NXCPMessage *msg)
 {
-   UINT32 i, id;
-
    MutexLock(m_mutexTrapCfgAccess);
-       msg.setField(VID_NUM_TRAPS, m_dwNumTraps);
-   for(i = 0, id = VID_TRAP_INFO_BASE; i < m_dwNumTraps; i++, id += 5)
-   {
-      msg.setField(id++, m_pTrapCfg[i].dwId);
-      msg.setField(id++, m_pTrapCfg[i].dwOidLen);
-      msg.setFieldFromInt32Array(id++, m_pTrapCfg[i].dwOidLen, m_pTrapCfg[i].pdwObjectId);
-      msg.setField(id++, m_pTrapCfg[i].dwEventCode);
-      msg.setField(id++, m_pTrapCfg[i].szDescription);
-   }
+       msg->setField(VID_NUM_TRAPS, m_trapCfgList.size());
+   for(int i = 0, id = VID_TRAP_INFO_BASE; i < m_trapCfgList.size(); i++, id += 10)
+      m_trapCfgList.get(i)->fillMessage(msg, id);
    MutexUnlock(m_mutexTrapCfgAccess);
 }
 
-/**
- * Notify clients about trap configuration change
- */
-static void NotifyOnTrapCfgChangeCB(ClientSession *session, void *arg)
-{
-       if (session->isAuthenticated())
-               session->postMessage((NXCPMessage *)arg);
-}
-
-static void NotifyOnTrapCfgChange(UINT32 code, NXC_TRAP_CFG_ENTRY *trap)
-{
-       NXCPMessage msg;
-
-       msg.setCode(CMD_TRAP_CFG_UPDATE);
-       msg.setField(VID_NOTIFICATION_CODE, code);
-       FillTrapConfigDataMsg(msg, trap);
-       EnumerateClientSessions(NotifyOnTrapCfgChangeCB, &msg);
-}
-
 static void NotifyOnTrapCfgDelete(UINT32 id)
 {
        NXCPMessage msg;
@@ -803,33 +960,42 @@ static void NotifyOnTrapCfgDelete(UINT32 id)
  */
 UINT32 DeleteTrap(UINT32 id)
 {
-   UINT32 i, j, dwResult = RCC_INVALID_TRAP_ID;
+   UINT32 dwResult = RCC_INVALID_TRAP_ID;
    TCHAR szQuery[256];
 
    MutexLock(m_mutexTrapCfgAccess);
 
-   for(i = 0; i < m_dwNumTraps; i++)
+   for(int i = 0; i < m_trapCfgList.size(); i++)
    {
-      if (m_pTrapCfg[i].dwId == id)
+      if (m_trapCfgList.get(i)->getId() == id)
       {
-         // Free allocated resources
-         for(j = 0; j < m_pTrapCfg[i].dwNumMaps; j++)
-            safe_free(m_pTrapCfg[i].pMaps[j].pdwObjectId);
-         safe_free(m_pTrapCfg[i].pMaps);
-         safe_free(m_pTrapCfg[i].pdwObjectId);
+         // Remove trap entry from database
+         DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
+         DB_STATEMENT hStmtCfg = DBPrepare(hdb, _T("DELETE FROM snmp_trap_cfg WHERE trap_id=?"));
+         DB_STATEMENT hStmtMap = DBPrepare(hdb, _T("DELETE FROM snmp_trap_pmap WHERE trap_id=?"));
 
-         // Remove trap entry from list
-         m_dwNumTraps--;
-         memmove(&m_pTrapCfg[i], &m_pTrapCfg[i + 1], sizeof(NXC_TRAP_CFG_ENTRY) * (m_dwNumTraps - i));
+         if (hStmtCfg != NULL && hStmtMap != NULL)
+         {
+            DBBind(hStmtCfg, 1, DB_SQLTYPE_INTEGER, id);
+            DBBind(hStmtMap, 1, DB_SQLTYPE_INTEGER, id);
 
-         // Remove trap entry from database
-         _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("DELETE FROM snmp_trap_cfg WHERE trap_id=%d"), id);
-         QueueSQLRequest(szQuery);
-         _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("DELETE FROM snmp_trap_pmap WHERE trap_id=%d"), id);
-         QueueSQLRequest(szQuery);
-         dwResult = RCC_SUCCESS;
+            if (DBBegin(hdb))
+            {
+               if (DBExecute(hStmtCfg) && DBExecute(hStmtMap))
+               {
+                  m_trapCfgList.remove(i);
+                  NotifyOnTrapCfgDelete(id);
+                  dwResult = RCC_SUCCESS;
+                  DBCommit(hdb);
+               }
+               else
+                  DBRollback(hdb);
 
-                       NotifyOnTrapCfgDelete(id);
+               DBFreeStatement(hStmtCfg);
+               DBFreeStatement(hStmtMap);
+            }
+         }
+         DBConnectionPoolReleaseConnection(hdb);
          break;
       }
    }
@@ -841,51 +1007,49 @@ UINT32 DeleteTrap(UINT32 id)
 /**
  * Save parameter mapping to database
  */
-static BOOL SaveParameterMapping(DB_HANDLE hdb, NXC_TRAP_CFG_ENTRY *pTrap)
+bool SNMP_TrapCfg::saveParameterMapping(DB_HANDLE hdb)
 {
-       TCHAR szQuery[1024];
-   _sntprintf(szQuery, 1024, _T("DELETE FROM snmp_trap_pmap WHERE trap_id=%d"), pTrap->dwId);
-   BOOL bRet = DBQuery(hdb, szQuery);
+   bool result = true;
+   DB_STATEMENT hStmt = DBPrepare(hdb, _T("DELETE FROM snmp_trap_pmap WHERE trap_id=?"));
+   DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
 
-       if (bRet)
+       if (DBExecute(hStmt))
    {
-               DB_STATEMENT hStmt = DBPrepare(hdb, _T("INSERT INTO snmp_trap_pmap (trap_id,parameter,snmp_oid,description,flags) VALUES (?,?,?,?,?)"));
+          DBFreeStatement(hStmt);
+
+               hStmt = DBPrepare(hdb, _T("INSERT INTO snmp_trap_pmap (trap_id,parameter,snmp_oid,description,flags) VALUES (?,?,?,?,?)"));
                if (hStmt != NULL)
                {
-                       for(UINT32 i = 0; i < pTrap->dwNumMaps; i++)
+         TCHAR oid[1024];
+                       for(UINT32 i = 0; i < m_pMaps->size(); i++)
                        {
-                               TCHAR oid[1024];
-
-                               if ((pTrap->pMaps[i].dwOidLen & 0x80000000) == 0)
+                               if (!m_pMaps->get(i)->isPosition())
                                {
-                                       SNMPConvertOIDToText(pTrap->pMaps[i].dwOidLen,
-                                                                                               pTrap->pMaps[i].pdwObjectId,
+                                       SNMPConvertOIDToText(m_pMaps->get(i)->getOidLength(),
+                                                            m_pMaps->get(i)->getOid()->value(),
                                                                                                oid, 1024);
                                }
                                else
-                               {
-                                       _sntprintf(oid, 1024, _T("POS:%d"), pTrap->pMaps[i].dwOidLen & 0x7FFFFFFF);
-                               }
+                                       _sntprintf(oid, 1024, _T("POS:%d"), m_pMaps->get(i)->getOidLength());
 
-                               DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, pTrap->dwId);
+                               DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
                                DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, i + 1);
                                DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, oid, DB_BIND_STATIC);
-                               DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, pTrap->pMaps[i].szDescription, DB_BIND_STATIC);
-                               DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, pTrap->pMaps[i].dwFlags);
+                               DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, m_pMaps->get(i)->getDescription(), DB_BIND_STATIC);
+                               DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, m_pMaps->get(i)->getFlags());
 
-                               bRet = DBExecute(hStmt);
-                               if (!bRet)
-                                       break;
+                               if (!DBExecute(hStmt))
+                               {
+                                  result = false;
+                                  break;
+                               }
                        }
                        DBFreeStatement(hStmt);
-               }
-               else
-               {
-                       bRet = FALSE;
+                       return result;
                }
    }
 
-       return bRet;
+       return false;
 }
 
 /**
@@ -893,90 +1057,32 @@ static BOOL SaveParameterMapping(DB_HANDLE hdb, NXC_TRAP_CFG_ENTRY *pTrap)
  */
 UINT32 CreateNewTrap(UINT32 *pdwTrapId)
 {
-   UINT32 dwResult = RCC_SUCCESS;
-   TCHAR szQuery[256];
-
-   MutexLock(m_mutexTrapCfgAccess);
-
-   *pdwTrapId = CreateUniqueId(IDG_SNMP_TRAP);
-   m_pTrapCfg = (NXC_TRAP_CFG_ENTRY *)realloc(m_pTrapCfg, sizeof(NXC_TRAP_CFG_ENTRY) * (m_dwNumTraps + 1));
-   memset(&m_pTrapCfg[m_dwNumTraps], 0, sizeof(NXC_TRAP_CFG_ENTRY));
-   m_pTrapCfg[m_dwNumTraps].dwId = *pdwTrapId;
-   m_pTrapCfg[m_dwNumTraps].dwEventCode = EVENT_SNMP_UNMATCHED_TRAP;
-
-       NotifyOnTrapCfgChange(NX_NOTIFY_TRAPCFG_CREATED, &m_pTrapCfg[m_dwNumTraps]);
-
-       m_dwNumTraps++;
-   MutexUnlock(m_mutexTrapCfgAccess);
+   UINT32 rcc = RCC_DB_FAILURE;
 
    DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-   _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("INSERT INTO snmp_trap_cfg (trap_id,snmp_oid,event_code,description,user_tag) ")
-                      _T("VALUES (%d,'',%d,'','')"), *pdwTrapId, (UINT32)EVENT_SNMP_UNMATCHED_TRAP);
-   if (!DBQuery(hdb, szQuery))
-      dwResult = RCC_DB_FAILURE;
-   DBConnectionPoolReleaseConnection(hdb);
-
-   return dwResult;
-}
-
-/**
- * Create new trap configuration record from NXMP data
- */
-UINT32 CreateNewTrap(NXC_TRAP_CFG_ENTRY *pTrap)
-{
-   UINT32 i, dwResult;
-   TCHAR szQuery[4096], szOID[1024];
-       BOOL bSuccess;
-
-   MutexLock(m_mutexTrapCfgAccess);
-
-   m_pTrapCfg = (NXC_TRAP_CFG_ENTRY *)realloc(m_pTrapCfg, sizeof(NXC_TRAP_CFG_ENTRY) * (m_dwNumTraps + 1));
-   memcpy(&m_pTrapCfg[m_dwNumTraps], pTrap, sizeof(NXC_TRAP_CFG_ENTRY));
-   m_pTrapCfg[m_dwNumTraps].dwId = CreateUniqueId(IDG_SNMP_TRAP);
-       m_pTrapCfg[m_dwNumTraps].pdwObjectId = (UINT32 *)nx_memdup(pTrap->pdwObjectId, sizeof(UINT32) * pTrap->dwOidLen);
-       m_pTrapCfg[m_dwNumTraps].pMaps = (NXC_OID_MAP *)nx_memdup(pTrap->pMaps, sizeof(NXC_OID_MAP) * pTrap->dwNumMaps);
-       for(i = 0; i < m_pTrapCfg[m_dwNumTraps].dwNumMaps; i++)
-       {
-      if ((m_pTrapCfg[m_dwNumTraps].pMaps[i].dwOidLen & 0x80000000) == 0)
-                       m_pTrapCfg[m_dwNumTraps].pMaps[i].pdwObjectId = (UINT32 *)nx_memdup(pTrap->pMaps[i].pdwObjectId, sizeof(UINT32) * pTrap->pMaps[i].dwOidLen);
-       }
-
-   DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
-
-       // Write new trap to database
-   SNMPConvertOIDToText(m_pTrapCfg[m_dwNumTraps].dwOidLen, m_pTrapCfg[m_dwNumTraps].pdwObjectId, szOID, 1024);
-   _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("INSERT INTO snmp_trap_cfg (trap_id,snmp_oid,event_code,description,user_tag) ")
-                      _T("VALUES (%d,'%s',%d,%s,%s)"), m_pTrapCfg[m_dwNumTraps].dwId,
-                 szOID, m_pTrapCfg[m_dwNumTraps].dwEventCode,
-                                (const TCHAR *)DBPrepareString(hdb, m_pTrapCfg[m_dwNumTraps].szDescription),
-                                (const TCHAR *)DBPrepareString(hdb, m_pTrapCfg[m_dwNumTraps].szUserTag));
-
-       if(DBBegin(hdb))
+   DB_STATEMENT hStmt = DBPrepare(hdb, _T("INSERT INTO snmp_trap_cfg (guid,trap_id,snmp_oid,event_code,description,user_tag) VALUES (?,?,'',?,'','')"));
+   if (hStmt != NULL)
    {
-      bSuccess = DBQuery(hdb, szQuery);
-      if (bSuccess)
+      SNMP_TrapCfg *trapCfg = new SNMP_TrapCfg();
+      DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, trapCfg->getGuid());
+      DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, trapCfg->getId());
+      DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, trapCfg->getEventCode());
+
+      if (DBExecute(hStmt))
       {
-                       bSuccess = SaveParameterMapping(hdb, &m_pTrapCfg[m_dwNumTraps]);
+         AddTrapCfgToList(trapCfg);
+         trapCfg->notifyOnTrapCfgChange(NX_NOTIFY_TRAPCFG_CREATED);
+         *pdwTrapId = trapCfg->getId();
+         rcc = RCC_SUCCESS;
       }
-      if (bSuccess)
-         DBCommit(hdb);
       else
-         DBRollback(hdb);
-      dwResult = bSuccess ? RCC_SUCCESS : RCC_DB_FAILURE;
-   }
-   else
-   {
-      dwResult = RCC_DB_FAILURE;
-   }
-       DBConnectionPoolReleaseConnection(hdb);
-
-       if (dwResult == RCC_SUCCESS)
-               NotifyOnTrapCfgChange(NX_NOTIFY_TRAPCFG_CREATED, &m_pTrapCfg[m_dwNumTraps]);
+         delete trapCfg;
 
-   m_dwNumTraps++;
-   MutexUnlock(m_mutexTrapCfgAccess);
+      DBFreeStatement(hStmt);
+   }
+   DBConnectionPoolReleaseConnection(hdb);
 
-   return dwResult;
+   return rcc;
 }
 
 /**
@@ -984,88 +1090,56 @@ UINT32 CreateNewTrap(NXC_TRAP_CFG_ENTRY *pTrap)
  */
 UINT32 UpdateTrapFromMsg(NXCPMessage *pMsg)
 {
-   UINT32 i, j, dwId1, dwId2, dwId3, dwId4, dwTrapId, dwResult = RCC_INVALID_TRAP_ID;
-   TCHAR szQuery[1024], szOID[1024];
-   BOOL bSuccess;
+   UINT32 rcc = RCC_INVALID_TRAP_ID;
+   TCHAR oid[1024];
 
-   dwTrapId = pMsg->getFieldAsUInt32(VID_TRAP_ID);
+   UINT32 id = pMsg->getFieldAsUInt32(VID_TRAP_ID);
+   DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
 
-   MutexLock(m_mutexTrapCfgAccess);
-   for(i = 0; i < m_dwNumTraps; i++)
+   for(int i = 0; i < m_trapCfgList.size(); i++)
    {
-      if (m_pTrapCfg[i].dwId == dwTrapId)
+      if (m_trapCfgList.get(i)->getId() == id)
       {
-         // Read trap configuration from event
-         m_pTrapCfg[i].dwEventCode = pMsg->getFieldAsUInt32(VID_EVENT_CODE);
-         m_pTrapCfg[i].dwOidLen = pMsg->getFieldAsUInt32(VID_TRAP_OID_LEN);
-         m_pTrapCfg[i].pdwObjectId = (UINT32 *)realloc(m_pTrapCfg[i].pdwObjectId, sizeof(UINT32) * m_pTrapCfg[i].dwOidLen);
-         pMsg->getFieldAsInt32Array(VID_TRAP_OID, m_pTrapCfg[i].dwOidLen, m_pTrapCfg[i].pdwObjectId);
-         pMsg->getFieldAsString(VID_DESCRIPTION, m_pTrapCfg[i].szDescription, MAX_DB_STRING);
-         pMsg->getFieldAsString(VID_USER_TAG, m_pTrapCfg[i].szUserTag, MAX_USERTAG_LENGTH);
-
-         // Destroy current parameter mapping
-         for(j = 0; j < m_pTrapCfg[i].dwNumMaps; j++)
-            safe_free(m_pTrapCfg[i].pMaps[j].pdwObjectId);
-         safe_free(m_pTrapCfg[i].pMaps);
-
-         // Read new mappings from message
-         m_pTrapCfg[i].dwNumMaps = pMsg->getFieldAsUInt32(VID_TRAP_NUM_MAPS);
-         m_pTrapCfg[i].pMaps = (NXC_OID_MAP *)malloc(sizeof(NXC_OID_MAP) * m_pTrapCfg[i].dwNumMaps);
-         for(j = 0, dwId1 = VID_TRAP_PLEN_BASE, dwId2 = VID_TRAP_PNAME_BASE, dwId3 = VID_TRAP_PDESCR_BASE, dwId4 = VID_TRAP_PFLAGS_BASE;
-             j < m_pTrapCfg[i].dwNumMaps; j++, dwId1++, dwId2++, dwId3++, dwId4++)
+         DB_STATEMENT hStmt = DBPrepare(hdb, _T("UPDATE snmp_trap_cfg SET snmp_oid=?,event_code=?,description=?,user_tag=? WHERE trap_id=?"));
+         if (hStmt != NULL)
          {
-            m_pTrapCfg[i].pMaps[j].dwOidLen = pMsg->getFieldAsUInt32(dwId1);
-            if ((m_pTrapCfg[i].pMaps[j].dwOidLen & 0x80000000) == 0)
+            SNMP_TrapCfg *trapCfg = new SNMP_TrapCfg(pMsg);
+            SNMPConvertOIDToText(trapCfg->getOidLength(), trapCfg->getOid()->value(), oid, 1024);
+            DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, oid, DB_BIND_STATIC);
+            DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, trapCfg->getEventCode());
+            DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, trapCfg->getDescription(), DB_BIND_STATIC);
+            DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, trapCfg->getUserTag(), DB_BIND_STATIC);
+            DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, trapCfg->getId());
+
+            if(DBBegin(hdb))
             {
-               m_pTrapCfg[i].pMaps[j].pdwObjectId =
-                  (UINT32 *)malloc(sizeof(UINT32) * m_pTrapCfg[i].pMaps[j].dwOidLen);
-               pMsg->getFieldAsInt32Array(dwId2, m_pTrapCfg[i].pMaps[j].dwOidLen,
-                                           m_pTrapCfg[i].pMaps[j].pdwObjectId);
+               if (DBExecute(hStmt) && trapCfg->saveParameterMapping(hdb))
+               {
+                  AddTrapCfgToList(trapCfg);
+                  trapCfg->notifyOnTrapCfgChange(NX_NOTIFY_TRAPCFG_MODIFIED);
+                  rcc = RCC_SUCCESS;
+                  DBCommit(hdb);
+               }
+               else
+               {
+                  DBRollback(hdb);
+                  rcc = RCC_DB_FAILURE;
+               }
             }
             else
-            {
-               m_pTrapCfg[i].pMaps[j].pdwObjectId = NULL;
-            }
-            pMsg->getFieldAsString(dwId3, m_pTrapCfg[i].pMaps[j].szDescription, MAX_DB_STRING);
-                               m_pTrapCfg[i].pMaps[j].dwFlags = pMsg->getFieldAsUInt32(dwId4);
-         }
-
-         DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
+               rcc = RCC_DB_FAILURE;
+            DBFreeStatement(hStmt);
 
-         // Update database
-         SNMPConvertOIDToText(m_pTrapCfg[i].dwOidLen, m_pTrapCfg[i].pdwObjectId, szOID, 1024);
-         _sntprintf(szQuery, 1024, _T("UPDATE snmp_trap_cfg SET snmp_oid='%s',event_code=%d,description=%s,user_tag=%s WHERE trap_id=%d"),
-                    szOID, m_pTrapCfg[i].dwEventCode,
-                                                 (const TCHAR *)DBPrepareString(hdb, m_pTrapCfg[i].szDescription),
-                                                 (const TCHAR *)DBPrepareString(hdb, m_pTrapCfg[i].szUserTag), m_pTrapCfg[i].dwId);
-         if(DBBegin(hdb))
-         {
-            bSuccess = DBQuery(hdb, szQuery);
-            if (bSuccess)
-            {
-                                       bSuccess = SaveParameterMapping(hdb, &m_pTrapCfg[i]);
-            }
-            if (bSuccess)
-               DBCommit(hdb);
-            else
-               DBRollback(hdb);
-            dwResult = bSuccess ? RCC_SUCCESS : RCC_DB_FAILURE;
-         }
-         else
-         {
-            dwResult = RCC_DB_FAILURE;
+            if (rcc != RCC_SUCCESS)
+               delete trapCfg;
          }
-                       DBConnectionPoolReleaseConnection(hdb);
-
-                       if (dwResult == RCC_SUCCESS)
-                               NotifyOnTrapCfgChange(NX_NOTIFY_TRAPCFG_MODIFIED, &m_pTrapCfg[i]);
 
+                       DBConnectionPoolReleaseConnection(hdb);
          break;
       }
    }
 
-   MutexUnlock(m_mutexTrapCfgAccess);
-   return dwResult;
+   return rcc;
 }
 
 /**
@@ -1073,47 +1147,48 @@ UINT32 UpdateTrapFromMsg(NXCPMessage *pMsg)
  */
 void CreateTrapExportRecord(String &xml, UINT32 id)
 {
-       UINT32 i, j;
        TCHAR szBuffer[1024];
+       SNMP_TrapCfg *trapCfg;
 
    MutexLock(m_mutexTrapCfgAccess);
-   for(i = 0; i < m_dwNumTraps; i++)
+   for(int i = 0; i < m_trapCfgList.size(); i++)
    {
-      if (m_pTrapCfg[i].dwId == id)
+      trapCfg = m_trapCfgList.get(i);
+      if (trapCfg->getId() == id)
       {
                        xml.appendFormattedString(_T("\t\t<trap id=\"%d\">\n")
+                                              _T("\t\t\t<guid>%s</guid>\n")
                                               _T("\t\t\t<oid>%s</oid>\n")
                                               _T("\t\t\t<description>%s</description>\n")
                                               _T("\t\t\t<userTag>%s</userTag>\n"), id,
-                                              SNMPConvertOIDToText(m_pTrapCfg[i].dwOidLen,
-                                                                   m_pTrapCfg[i].pdwObjectId,
-                                                                                                                                         szBuffer, 1024),
-                                                                                 (const TCHAR *)EscapeStringForXML2(m_pTrapCfg[i].szDescription),
-                                                                                 (const TCHAR *)EscapeStringForXML2(m_pTrapCfg[i].szUserTag));
+                                (const TCHAR *)trapCfg->getGuid().toString(),
+                                (const TCHAR *)trapCfg->getOid()->toString(),
+                                                                                 (const TCHAR *)EscapeStringForXML2(trapCfg->getDescription()),
+                                                                                 (const TCHAR *)EscapeStringForXML2(trapCfg->getUserTag()));
 
-                  EventNameFromCode(m_pTrapCfg[i].dwEventCode, szBuffer);
+                  EventNameFromCode(trapCfg->getEventCode(), szBuffer);
                        xml.appendFormattedString(_T("\t\t\t<event>%s</event>\n"), (const TCHAR *)EscapeStringForXML2(szBuffer));
-                       if (m_pTrapCfg[i].dwNumMaps > 0)
+                       if (trapCfg->getNumMaps() > 0)
                        {
             xml.append(_T("\t\t\t<parameters>\n"));
-                               for(j = 0; j < m_pTrapCfg[i].dwNumMaps; j++)
+                               for(int j = 0; j < trapCfg->getNumMaps(); j++)
                                {
                                        xml.appendFormattedString(_T("\t\t\t\t<parameter id=\"%d\">\n")
                                                     _T("\t\t\t\t\t<flags>%d</flags>\n")
                                                               _T("\t\t\t\t\t<description>%s</description>\n"),
-                                                                                                 j + 1, m_pTrapCfg[i].pMaps[j].dwFlags,
-                                                                                                 (const TCHAR *)EscapeStringForXML2(m_pTrapCfg[i].pMaps[j].szDescription));
-               if ((m_pTrapCfg[i].pMaps[j].dwOidLen & 0x80000000) == 0)
+                                                                                                 j + 1, trapCfg->getMap(j)->getFlags(),
+                                                                                                 (const TCHAR *)EscapeStringForXML2(trapCfg->getMap(j)->getDescription()));
+               if (!trapCfg->getMap(j)->isPosition())
                                        {
                                                xml.appendFormattedString(_T("\t\t\t\t\t<oid>%s</oid>\n"),
-                                                                      SNMPConvertOIDToText(m_pTrapCfg[i].pMaps[j].dwOidLen,
-                                                                                                                              m_pTrapCfg[i].pMaps[j].pdwObjectId,
-                                                                                                                                                                 szBuffer, 1024));
+                                                                      SNMPConvertOIDToText(trapCfg->getMap(j)->getOidLength(),
+                                                                                           trapCfg->getMap(j)->getOid()->value(),
+                                                                                           szBuffer, 1024));
                                        }
                                        else
                                        {
                                                xml.appendFormattedString(_T("\t\t\t\t\t<position>%d</position>\n"),
-                                                                      m_pTrapCfg[i].pMaps[j].dwOidLen & 0x7FFFFFFF);
+                                                                      trapCfg->getMap(j)->getOidLength());
                                        }
                xml.append(_T("\t\t\t\t</parameter>\n"));
                                }
@@ -1125,3 +1200,49 @@ void CreateTrapExportRecord(String &xml, UINT32 id)
        }
    MutexUnlock(m_mutexTrapCfgAccess);
 }
+
+/**
+ * Find if trap with guid already exists
+ */
+UINT32 ResolveTrapGuid(const uuid& guid)
+{
+   UINT32 id = 0;
+
+   DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
+
+   DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT trap_id FROM snmp_trap_cfg WHERE guid=?"));
+   if (hStmt != NULL)
+   {
+      DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, guid);
+      DB_RESULT hResult = DBSelectPrepared(hStmt);
+      if (hResult != NULL)
+      {
+         if (DBGetNumRows(hResult) > 0)
+            id = DBGetFieldULong(hResult, 0, 0);
+         DBFreeResult(hResult);
+      }
+      DBFreeStatement(hStmt);
+   }
+
+   DBConnectionPoolReleaseConnection(hdb);
+   return id;
+}
+
+/**
+ * Add SNMP trap configuration to local list
+ */
+void AddTrapCfgToList(SNMP_TrapCfg *trapCfg)
+{
+   MutexLock(m_mutexTrapCfgAccess);
+
+   for(int i = 0; i < m_trapCfgList.size(); i++)
+   {
+      if (m_trapCfgList.get(i)->getId() == trapCfg->getId())
+      {
+         m_trapCfgList.remove(i);
+      }
+   }
+   m_trapCfgList.add(trapCfg);
+
+   MutexUnlock(m_mutexTrapCfgAccess);
+}
index a547314..2038274 100644 (file)
@@ -913,6 +913,78 @@ public:
 };
 
 /**
+ * SNMP Trap parameter map object
+ */
+class LIBNXSNMP_EXPORTABLE SNMP_TrapParamMap
+{
+private:
+   SNMP_ObjectId *m_objectId;           // Trap OID
+   UINT32 m_position;                   // Trap position
+   UINT32 m_flags;
+   TCHAR m_description[MAX_DB_STRING];
+
+public:
+   SNMP_TrapParamMap();
+   SNMP_TrapParamMap(DB_RESULT mapResult, int row);
+   SNMP_TrapParamMap(ConfigEntry *entry);
+   SNMP_TrapParamMap(SNMP_ObjectId *oid, UINT32 flags, TCHAR *description);
+   SNMP_TrapParamMap(NXCPMessage *msg, UINT32 base);
+   ~SNMP_TrapParamMap();
+
+   void fillMessage(NXCPMessage *msg, UINT32 base);
+
+   SNMP_ObjectId *getOid() { return m_objectId; }
+   UINT32 getOidLength() { return (m_objectId == NULL) ? m_position : (UINT32)m_objectId->length(); }
+   bool isPosition() {  return m_objectId == NULL; }
+
+   UINT32 getFlags() { return m_flags; }
+
+   TCHAR *getDescription() { return m_description; }
+
+};
+
+/**
+ * SNMP Trap configuration object
+ */
+class LIBNXSNMP_EXPORTABLE SNMP_TrapCfg
+{
+private:
+   uuid m_guid;                   // Trap guid
+   UINT32 m_id;                   // Entry ID
+   SNMP_ObjectId *m_objectId;     // Trap OID
+   UINT32 m_eventCode;            // Event code
+   ObjectArray<SNMP_TrapParamMap> *m_pMaps;
+   TCHAR m_description[MAX_DB_STRING];
+   TCHAR m_userTag[MAX_USERTAG_LENGTH];
+
+public:
+   SNMP_TrapCfg();
+   SNMP_TrapCfg(DB_RESULT trapResult, DB_STATEMENT stmt, int row);
+   SNMP_TrapCfg(ConfigEntry *entry, const uuid& guid, UINT32 id, UINT32 eventCode);
+   SNMP_TrapCfg(NXCPMessage *msg);
+   ~SNMP_TrapCfg();
+
+   void fillMessage(NXCPMessage *msg);
+   void fillMessage(NXCPMessage *msg, UINT32 base);
+   bool saveParameterMapping(DB_HANDLE hdb);
+   void notifyOnTrapCfgChange(UINT32 code);
+
+   const uuid& getGuid() { return m_guid; }
+   UINT32 getId() { return m_id; }
+
+   SNMP_ObjectId *getOid() { return m_objectId; }
+   UINT32 getOidLength() { return (UINT32)m_objectId->length(); }
+
+   SNMP_TrapParamMap *getMap(int index) { return m_pMaps->get(index); }
+   UINT32 getNumMaps() { return m_pMaps->size(); }
+
+   UINT32 getEventCode() { return m_eventCode; }
+
+   TCHAR *getDescription() { return m_description; }
+   TCHAR *getUserTag() { return m_userTag; }
+};
+
+/**
  * Watchdog thread state codes
  */
 enum WatchdogState
@@ -1043,12 +1115,13 @@ void NXCORE_EXPORTABLE PostSMS(const TCHAR *pszRcpt, const TCHAR *pszText);
 
 void InitTraps();
 void SendTrapsToClient(ClientSession *pSession, UINT32 dwRqId);
-void CreateTrapCfgMessage(NXCPMessage &msg);
+void CreateTrapCfgMessage(NXCPMessage *msg);
 UINT32 CreateNewTrap(UINT32 *pdwTrapId);
-UINT32 CreateNewTrap(NXC_TRAP_CFG_ENTRY *pTrap);
 UINT32 UpdateTrapFromMsg(NXCPMessage *pMsg);
 UINT32 DeleteTrap(UINT32 dwId);
 void CreateTrapExportRecord(String &xml, UINT32 id);
+UINT32 ResolveTrapGuid(const uuid& guid);
+void AddTrapCfgToList(SNMP_TrapCfg *trapCfg);
 
 BOOL IsTableTool(UINT32 dwToolId);
 BOOL CheckObjectToolAccess(UINT32 dwToolId, UINT32 dwUserId);
@@ -1164,6 +1237,13 @@ void SendAlarmSummaryEmail(const ScheduledTaskParameters *params);
 void EnableAlarmSummaryEmails();
 
 /**
+ * NXSL script functions
+ */
+UINT32 UpdateScript(const NXCPMessage *request, UINT32 *scriptId);
+UINT32 RenameScript(const NXCPMessage *request);
+UINT32 DeleteScript(const NXCPMessage *request);
+
+/**
  * File monitoring
  */
 struct MONITORED_FILE
index 7dca491..fb9d36b 100644 (file)
@@ -747,6 +747,98 @@ static bool SetSchemaVersion(int version)
 }
 
 /**
+ * Upgrade from V437 to V438
+ */
+static BOOL H_UpgradeFromV437(int currVersion, int newVersion)
+{
+   static const TCHAR *batch =
+            _T("ALTER TABLE snmp_trap_cfg ADD guid varchar(36)\n")
+            _T("UPDATE snmp_trap_cfg SET guid='5d01e7e5-edbb-46ce-b53c-f7f64d1bf8ff' WHERE trap_id=1\n")
+            _T("UPDATE snmp_trap_cfg SET guid='c5464919-fd76-4624-9c21-b6ab73d9df80' WHERE trap_id=2\n")
+            _T("UPDATE snmp_trap_cfg SET guid='44d3b32e-33c5-4a39-b2ad-990a1120155d' WHERE trap_id=3\n")
+            _T("UPDATE snmp_trap_cfg SET guid='c9660f48-a4b3-41c8-b3f9-e9a6a8129db5' WHERE trap_id=4\n")
+            _T("UPDATE snmp_trap_cfg SET guid='4b422ba6-4b45-4881-931a-ed38dc798f9f' WHERE trap_id=5\n")
+            _T("UPDATE snmp_trap_cfg SET guid='bd8b6971-a3e4-4cad-9c70-3a33e61e0913' WHERE trap_id=6\n")
+            _T("ALTER TABLE script_library ADD guid varchar(36)\n")
+            _T("UPDATE script_library SET guid='3b7bddce-3505-42ff-ac60-6a48a64bd0ae' WHERE script_id=1\n")
+            _T("UPDATE script_library SET guid='2fb9212b-97e6-40e7-b434-2df4f7e8f6aa' WHERE script_id=2\n")
+            _T("UPDATE script_library SET guid='38696a00-c519-438c-8cbd-4b3a0cba4af1' WHERE script_id=3\n")
+            _T("UPDATE script_library SET guid='efe50915-47b2-43d8-b4f4-2c09a44970c3' WHERE script_id=4\n")
+            _T("UPDATE script_library SET guid='7837580c-4054-40f2-981f-7185797fe7d7' WHERE script_id=11\n")
+            _T("UPDATE script_library SET guid='f7d1bc7e-4046-4ee4-adb2-718f7361984d' WHERE script_id=12\n")
+            _T("UPDATE script_library SET guid='048fcf32-765b-4702-9c70-f012f62d5a90' WHERE script_id=13\n")
+            _T("UPDATE script_library SET guid='d515c10f-a5c9-4f41-afcd-9ddc8845f288' WHERE script_id=14\n")
+            _T("UPDATE script_library SET guid='7cd1c471-2f14-4fae-8743-8899fed64d18' WHERE script_id=15\n")
+            _T("UPDATE script_library SET guid='befdb083-ac68-481d-a7b7-127e11c3fae0' WHERE script_id=16\n")
+            _T("<END>");
+   CHK_EXEC(SQLBatch(batch));
+
+   uuid guid;
+   TCHAR buffer[MAX_DB_STRING];
+   UINT32 numRows;
+
+   DB_RESULT hResult = DBSelect(g_hCoreDB, _T("SELECT trap_id FROM snmp_trap_cfg WHERE guid IS NULL"));
+   DB_STATEMENT hStmt = DBPrepare(g_hCoreDB, _T("UPDATE snmp_trap_cfg SET guid=? WHERE trap_id=?"));
+   if (hResult != NULL)
+   {
+      if (hStmt != NULL)
+      {
+         numRows = DBGetNumRows(hResult);
+         for(int i = 0; i < numRows; i++)
+         {
+            guid = uuid::generate();
+            DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, guid);
+            DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, DBGetFieldULong(hResult, i, 0));
+
+            if (!SQLExecute(hStmt))
+            {
+               if (!g_bIgnoreErrors)
+               {
+                  DBFreeStatement(hStmt);
+                  DBFreeResult(hResult);
+                  return FALSE;
+               }
+            }
+         }
+         DBFreeStatement(hStmt);
+      }
+      DBFreeResult(hResult);
+   }
+
+   hResult = DBSelect(g_hCoreDB, _T("SELECT guid,script_id FROM script_library WHERE guid IS NULL"));
+   hStmt = DBPrepare(g_hCoreDB, _T("UPDATE script_library SET guid=? WHERE script_id=?"));
+   if (hResult != NULL)
+   {
+      if (hStmt != NULL)
+      {
+         numRows = DBGetNumRows(hResult);
+         for(int i = 0; i < numRows; i++)
+         {
+            guid = uuid::generate();
+            DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, guid);
+            DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, DBGetFieldULong(hResult, i, 1));
+            if (!SQLExecute(hStmt))
+            {
+               if (!g_bIgnoreErrors)
+               {
+                  DBFreeStatement(hStmt);
+                  DBFreeResult(hResult);
+                  return FALSE;
+               }
+            }
+         }
+         DBFreeStatement(hStmt);
+      }
+      DBFreeResult(hResult);
+   }
+
+   CHK_EXEC(SetNotNullConstraint(_T("snmp_trap_cfg"), _T("guid")));
+   CHK_EXEC(SetNotNullConstraint(_T("script_library"), _T("guid")));
+   CHK_EXEC(SetSchemaVersion(438));
+   return TRUE;
+}
+
+/**
  * Upgrade from V436 to V437
  */
 static BOOL H_UpgradeFromV436(int currVersion, int newVersion)
@@ -11426,6 +11518,7 @@ static struct
    { 434, 435, H_UpgradeFromV434 },
    { 435, 436, H_UpgradeFromV435 },
    { 436, 437, H_UpgradeFromV436 },
+   { 437, 438, H_UpgradeFromV437 },
    { 0, 0, NULL }
 };