- Initial DCI transformation support on server side
authorVictor Kirhenshtein <victor@netxms.org>
Mon, 20 Sep 2004 16:31:26 +0000 (16:31 +0000)
committerVictor Kirhenshtein <victor@netxms.org>
Mon, 20 Sep 2004 16:31:26 +0000 (16:31 +0000)
- New fields added to "config" table
- DB schema ready for templates implementation

23 files changed:
.gitattributes
include/netxmsdb.h
include/nms_cscp.h
include/nxclapi.h
include/nxevent.h
sql/clear.sql [deleted file]
sql/events.in
sql/schema.in
sql/setup.in
src/server/core/Makefile.am
src/server/core/container.cpp
src/server/core/datacoll.cpp
src/server/core/dcitem.cpp
src/server/core/dcithreshold.cpp
src/server/core/dcivalue.cpp [new file with mode: 0644]
src/server/core/interface.cpp
src/server/core/netxmsd.dsp
src/server/core/nms_dcoll.h
src/server/core/node.cpp
src/server/core/objects.cpp
src/server/core/session.cpp
src/server/core/subnet.cpp
src/server/core/syncer.cpp

index 583fd24..446acbd 100644 (file)
@@ -53,7 +53,6 @@ netware/bin/.keep -text
 sql/.cvsignore -text
 sql/Makefile.am -text
 sql/Makefile.w32 -text
-sql/clear.sql -text
 sql/dbinit.in -text
 sql/drop.sh -text
 sql/events.in -text
@@ -316,6 +315,7 @@ src/server/core/db.cpp -text
 src/server/core/dbwrite.cpp -text
 src/server/core/dcitem.cpp -text
 src/server/core/dcithreshold.cpp -text
+src/server/core/dcivalue.cpp -text
 src/server/core/debug.cpp -text
 src/server/core/discovery.cpp -text
 src/server/core/email.cpp -text
index c691775..d4410ab 100644 (file)
@@ -23,6 +23,6 @@
 #ifndef _netxms_db_h
 #define _netxms_db_h
 
-#define DB_FORMAT_VERSION      7
+#define DB_FORMAT_VERSION      8
 
 #endif
index 2a71116..3d84fbc 100644 (file)
@@ -361,6 +361,8 @@ typedef struct
 #define VID_RCPT_ADDR               ((DWORD)102)
 #define VID_CATEGORY_NAME           ((DWORD)103)
 #define VID_CATEGORY_ID             ((DWORD)104)
+#define VID_DCI_DELTA_CALCULATION   ((DWORD)105)
+#define VID_DCI_FORMULA             ((DWORD)106)
 
 // Variable ranges for object's ACL
 #define VID_ACL_USER_BASE           ((DWORD)0x00001000)
index 2ed2d50..2f8aca9 100644 (file)
@@ -320,6 +320,16 @@ typedef unsigned long HREQUEST;
 #define ITEM_STATUS_NOT_SUPPORTED   2
 
 
+//
+// Delta calculation methods for DCIs
+//
+
+#define DCM_ORIGINAL_VALUE       0
+#define DCM_SIMPLE               1
+#define DCM_AVERAGE_PER_SECOND   2
+#define DCM_AVERAGE_PER_MINUTE   3
+
+
 //
 // Threshold functions and operations
 //
@@ -378,6 +388,8 @@ typedef struct
    char szEmailSubject[MAX_EMAIL_SUBJECT_LEN];
    char *pszData;
 } NXC_ACTION;
+
+
 //
 // Alarm structure
 //
@@ -604,14 +616,18 @@ typedef struct
 typedef struct
 {
    DWORD dwId;
+   DWORD dwTemplateId;
    char szName[MAX_ITEM_NAME];
+   char szDescription[MAX_DB_STRING];
    int iPollingInterval;
    int iRetentionTime;
    BYTE iSource;
    BYTE iDataType;
    BYTE iStatus;
+   BYTE iDeltaCalculation;
    DWORD dwNumThresholds;
    NXC_DCI_THRESHOLD *pThresholdList;
+   char *pszFormula;
 } NXC_DCI;
 
 
index 021910b..f581389 100644 (file)
@@ -44,7 +44,7 @@
 // Event severity codes
 //
 
-#define EVENT_SEVERITY_INFO      0
+#define EVENT_SEVERITY_NORMAL    0
 #define EVENT_SEVERITY_WARNING   1
 #define EVENT_SEVERITY_MINOR     2
 #define EVENT_SEVERITY_MAJOR     3
diff --git a/sql/clear.sql b/sql/clear.sql
deleted file mode 100644 (file)
index ac142a3..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
---
--- Clear database
---
-
-DELETE FROM Nodes;
-DELETE FROM Interfaces;
-DELETE FROM Subnets;
-DELETE FROM nsmap;
-DELETE FROM NewNodes;
-DELETE FROM EventLog;
index b628330..fb60d4b 100644 (file)
@@ -6,8 +6,8 @@
 
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_NODE_ADDED, 'NX_NODE_ADDED',
-               EVENT_SEVERITY_INFO, 1,
+               EVENT_NODE_ADDED, 'SYS_NODE_ADDED',
+               EVENT_SEVERITY_NORMAL, 1,
                'Node added',
                'Generated when new node object added to the database.#0D#0A' CONCAT
                'Parameters:#0D#0A' CONCAT
@@ -15,8 +15,8 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_SUBNET_ADDED, 'NX_SUBNET_ADDED',
-               EVENT_SEVERITY_INFO, 0,
+               EVENT_SUBNET_ADDED, 'SYS_SUBNET_ADDED',
+               EVENT_SEVERITY_NORMAL, 0,
                'Subnet added',
                'Generated when new subnet object added to the database.#0D#0A' CONCAT
                'Parameters:#0D#0A' CONCAT
@@ -24,8 +24,8 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_INTERFACE_ADDED, 'NX_IF_ADDED',
-               EVENT_SEVERITY_INFO, 1,
+               EVENT_INTERFACE_ADDED, 'SYS_IF_ADDED',
+               EVENT_SEVERITY_NORMAL, 1,
                'Interface "%2" added (IP Addr: %3/%4, IfIndex: %5)',
                'Generated when new interface object added to the database.#0D#0A' CONCAT
                'Please note that source of event is node, not an interface itself.#0D#0A' CONCAT
@@ -38,8 +38,8 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_INTERFACE_UP, 'NX_IF_UP',
-               EVENT_SEVERITY_INFO, 1,
+               EVENT_INTERFACE_UP, 'SYS_IF_UP',
+               EVENT_SEVERITY_NORMAL, 1,
                'Interface "%2" changed state to UP (IP Addr: %3/%4, IfIndex: %5)',
                'Generated when interface goes up.#0D#0A' CONCAT
                'Please note that source of event is node, not an interface itself.#0D#0A' CONCAT
@@ -52,7 +52,7 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_INTERFACE_DOWN, 'NX_IF_DOWN',
+               EVENT_INTERFACE_DOWN, 'SYS_IF_DOWN',
                EVENT_SEVERITY_WARNING, 1,
                'Interface "%2" changed state to DOWN (IP Addr: %3/%4, IfIndex: %5)',
                'Generated when interface goes down.#0D#0A' CONCAT
@@ -66,8 +66,8 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_NODE_NORMAL, 'NX_NODE_NORMAL',
-               EVENT_SEVERITY_INFO, 1,
+               EVENT_NODE_NORMAL, 'SYS_NODE_NORMAL',
+               EVENT_SEVERITY_NORMAL, 1,
                'Node status changed to NORMAL',
                'Generated when node status changed to normal.#0D#0A' CONCAT
                'Parameters:#0D#0A' CONCAT
@@ -75,7 +75,7 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_NODE_WARNING, 'NX_NODE_WARNING', 
+               EVENT_NODE_WARNING, 'SYS_NODE_WARNING', 
                EVENT_SEVERITY_WARNING, 1,
                'Node status changed to WARNING',
                'Generated when node status changed to "Warning".#0D#0A' CONCAT
@@ -84,7 +84,7 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_NODE_MINOR, 'NX_NODE_MINOR',
+               EVENT_NODE_MINOR, 'SYS_NODE_MINOR',
                EVENT_SEVERITY_MINOR, 1,
                'Node status changed to MINOR',
                'Generated when node status changed to "Minor Problem" (informational).#0D#0A' CONCAT
@@ -93,7 +93,7 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_NODE_MAJOR, 'NX_NODE_MAJOR', 
+               EVENT_NODE_MAJOR, 'SYS_NODE_MAJOR', 
                EVENT_SEVERITY_MAJOR, 1,
                'Node status changed to MAJOR',
                'Generated when node status changed to "Major Problem".#0D#0A' CONCAT
@@ -102,7 +102,7 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_NODE_CRITICAL, 'NX_NODE_CRITICAL', 
+               EVENT_NODE_CRITICAL, 'SYS_NODE_CRITICAL', 
                EVENT_SEVERITY_CRITICAL, 1,
                'Node status changed to CRITICAL',
                'Generated when node status changed to critical.#0D#0A' CONCAT
@@ -111,8 +111,8 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_NODE_UNKNOWN, 'NX_NODE_UNKNOWN',
-               EVENT_SEVERITY_INFO, 1,
+               EVENT_NODE_UNKNOWN, 'SYS_NODE_UNKNOWN',
+               EVENT_SEVERITY_NORMAL, 1,
                'Node status changed to UNKNOWN',
                'Generated when node status changed to unknown.#0D#0A' CONCAT
                'Parameters:#0D#0A' CONCAT
@@ -120,8 +120,8 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_NODE_UNMANAGED, 'NX_NODE_UNMANAGED',
-               EVENT_SEVERITY_INFO, 1,
+               EVENT_NODE_UNMANAGED, 'SYS_NODE_UNMANAGED',
+               EVENT_SEVERITY_NORMAL, 1,
                'Node status changed to UNMANAGED',
                'Generated when node status changed to unmanaged.#0D#0A' CONCAT
                'Parameters:#0D#0A' CONCAT
@@ -129,8 +129,8 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_NODE_FLAGS_CHANGED, 'NX_NODE_CAP_CHANGED',
-               EVENT_SEVERITY_INFO, 0,
+               EVENT_NODE_FLAGS_CHANGED, 'SYS_NODE_CAP_CHANGED',
+               EVENT_SEVERITY_NORMAL, 0,
                'Node capabilities changed (Old: %1; New: %2)',
                'Generated when node capabilities changed.#0D#0A' CONCAT
                'Parameters:#0D#0A' CONCAT
@@ -139,8 +139,8 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_SNMP_FAIL, 'NX_SNMP_UNREACHEABLE', 
-               EVENT_SEVERITY_INFO, 0,
+               EVENT_SNMP_FAIL, 'SYS_SNMP_UNREACHEABLE', 
+               EVENT_SEVERITY_NORMAL, 0,
                'SNMP agent is not responding',
                'Generated when node#27s SNMP agent is not responding.#0D#0A' CONCAT
                'Parameters:#0D#0A' CONCAT
@@ -148,8 +148,8 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_AGENT_FAIL, 'NX_AGENT_UNREACHEABLE',
-               EVENT_SEVERITY_INFO, 0,
+               EVENT_AGENT_FAIL, 'SYS_AGENT_UNREACHEABLE',
+               EVENT_SEVERITY_NORMAL, 0,
                'Native agent is not responding',
                'Generated when node#27s native agent is not responding.#0D#0A' CONCAT
                'Parameters:#0D#0A' CONCAT
@@ -157,8 +157,8 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_INTERFACE_DELETED, 'NX_IF_DELETED',
-               EVENT_SEVERITY_INFO, 1,
+               EVENT_INTERFACE_DELETED, 'SYS_IF_DELETED',
+               EVENT_SEVERITY_NORMAL, 1,
                'Interface "%2" deleted (IP Addr: %3/%4, IfIndex: %1)',
                'Generated when interface object deleted from the database.#0D#0A' CONCAT
                'Please note that source of event is node, not an interface itself.#0D#0A' CONCAT
@@ -170,7 +170,7 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_THRESHOLD_REACHED, 'NX_THRESHOLD_REACHED',
+               EVENT_THRESHOLD_REACHED, 'SYS_THRESHOLD_REACHED',
                EVENT_SEVERITY_WARNING, 1,
                'Threshold reached for parameter %1 (Threshold value: %2; Actual value: %3)',
                'Generated when threshold value reached for specific data collection item.#0D#0A' CONCAT
@@ -181,8 +181,8 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_THRESHOLD_REARMED, 'NX_THRESHOLD_REARMED',
-               EVENT_SEVERITY_INFO, 0,
+               EVENT_THRESHOLD_REARMED, 'SYS_THRESHOLD_REARMED',
+               EVENT_SEVERITY_NORMAL, 0,
                'Threshold rearmed for parameter %1',
                'Generated when threshold check is rearmed for specific data collection item.#0D#0A' CONCAT
                'Parameters:#0D#0A' CONCAT
@@ -190,8 +190,8 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_SUBNET_DELETED, 'NX_SUBNET_DELETED',
-               EVENT_SEVERITY_INFO, 0,
+               EVENT_SUBNET_DELETED, 'SYS_SUBNET_DELETED',
+               EVENT_SEVERITY_NORMAL, 0,
                'Subnet deleted',
                'Generated when subnet object deleted from the database.#0D#0A' CONCAT
                'Parameters:#0D#0A' CONCAT
@@ -199,7 +199,7 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_THREAD_HANGS, 'NX_SYS_THREAD_HANG', 
+               EVENT_THREAD_HANGS, 'SYS_THREAD_HANG', 
                EVENT_SEVERITY_CRITICAL, 1,
                'Thread "%1" is not responding',
                'Generated when one of the system threads hangs or stops unexpectedly.#0D#0A' CONCAT
@@ -208,8 +208,8 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_THREAD_RUNNING, 'NX_SYS_THREAD_RUNNING', 
-               EVENT_SEVERITY_INFO, 1,
+               EVENT_THREAD_RUNNING, 'SYS_THREAD_RUNNING',
+               EVENT_SEVERITY_NORMAL, 1,
                'Thread "%1" was returned to running state',
                'Generated when one of the system threads which previously hangs or stops unexpectedly was returned to running state.#0D#0A' CONCAT
                'Parameters:#0D#0A' CONCAT
@@ -217,7 +217,7 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        );
 INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
        (
-               EVENT_SMTP_FAILURE, 'NX_SMTP_FAILURE', 
+               EVENT_SMTP_FAILURE, 'SYS_SMTP_FAILURE', 
                EVENT_SEVERITY_WARNING, 1,
                'Unable to send e-mail to <%3>: %2',
                'Generated when server is unable to send e-mail.#0D#0A' CONCAT
@@ -227,3 +227,43 @@ INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
                '   3) Recipient address#0D#0A' CONCAT
                '   4) Mail subject'
        );
+
+
+/*
+** Following is a set of predefined events for thresholds
+** These events can occupy ID space 4000 ... 4999
+*/
+
+INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
+       (
+               4000, 'DC_HIGH_CPU_UTIL',
+               EVENT_SEVERITY_MINOR, 1,
+               'CPU utilization exceeds allowed maximum of %2 (Current: %3)',
+               'Custom data collection threshold event.#0D#0A' CONCAT
+               'Parameters:#0D#0A' CONCAT
+               '   1) Item name#0D#0A' CONCAT
+               '   2) Threshold value#0D#0A' CONCAT
+               '   3) Actual value'
+       );
+INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
+       (
+               4001, 'DC_HIGH_PROCLOAD',
+               EVENT_SEVERITY_MINOR, 1,
+               'Processor load average exceeds allowed maximum of %2 (Current: %3)',
+               'Custom data collection threshold event.#0D#0A' CONCAT
+               'Parameters:#0D#0A' CONCAT
+               '   1) Item name#0D#0A' CONCAT
+               '   2) Threshold value#0D#0A' CONCAT
+               '   3) Actual value'
+       );
+INSERT INTO events (event_id,name,severity,flags,message,description) VALUES
+       (
+               4002, 'DC_HOST_RESTARTED',
+               EVENT_SEVERITY_NORMAL, 1,
+               'Host has been restarted within last 5 minutes',
+               'Custom data collection threshold event.#0D#0A' CONCAT
+               'Parameters:#0D#0A' CONCAT
+               '   1) Item name#0D#0A' CONCAT
+               '   2) Threshold value#0D#0A' CONCAT
+               '   3) Actual value'
+       );
index c32821c..33321d6 100644 (file)
@@ -7,6 +7,8 @@ CREATE TABLE config
 (
        var_name varchar(63) not null,
        var_value varchar(255),
+       is_visible integer,
+       need_server_restart integer,
        PRIMARY KEY(var_name)
 );
 
@@ -232,12 +234,20 @@ CREATE TABLE access_options
 
 /*
 ** Data collection items
+**
+** If node_id != 0, it's an item bound to node,        and template_id points to 
+** the template used for creating this item. In this case, template_id = 0
+** means that item was created manually.
+** If node_id = 0, it's a template item, and template_id points to a template
+** this item belongs to.
+** If both node_id and template_id is 0, it's an error.
 */
 
 CREATE TABLE items
 (
        item_id integer not null,
-       node_id integer not null,
+       node_id integer not null,       
+       template_id integer not null,
        name varchar(255) not null,
        description varchar(255),
        source integer,                 // 0 for internal or 1 for native agent or 2 for SNMP
@@ -245,6 +255,8 @@ CREATE TABLE items
        polling_interval integer,
        retention_time integer,
        status integer,                 // ACTIVE, DISABLED or NOT_SUPPORTED
+       delta_calculation integer,
+       transformation TEXT,            // Transformation formula
        PRIMARY KEY(item_id)
 );
 
@@ -412,24 +424,6 @@ CREATE TABLE dct
 );
 
 
-/*
-** Items in data collection templates
-*/
-
-CREATE TABLE dct_items
-(
-       template_id integer not null,
-       item_id integer not null,
-       name varchar(255),
-       description varchar(255),
-       source integer,                 // 0 for internal or 1 for native agent or 2 for SNMP
-       datatype integer,
-       polling_interval integer,
-       retention_time integer,
-       PRIMARY KEY(template_id,item_id)
-);
-
-
 /*
 ** Mapping hosts to templates
 */
index fdd4a78..dc75d1b 100644 (file)
@@ -4,25 +4,44 @@
 ** ex: syntax=sql
 */
 
-INSERT INTO config (var_name,var_value) VALUES ('DBFormatVersion',DB_FORMAT_VERSION);
-INSERT INTO config (var_name,var_value) VALUES ('SyncInterval','60');
-INSERT INTO config (var_name,var_value) VALUES ('NewNodePollingInterval','60');
-INSERT INTO config (var_name,var_value) VALUES ('DiscoveryPollingInterval','900');
-INSERT INTO config (var_name,var_value) VALUES ('StatusPollingInterval','30');
-INSERT INTO config (var_name,var_value) VALUES ('ConfigurationPollingInterval','3600');
-INSERT INTO config (var_name,var_value) VALUES ('ResolveNodeNames','0');
-INSERT INTO config (var_name,var_value) VALUES ('NumberOfEventProcessors','1');
-INSERT INTO config (var_name,var_value) VALUES ('ClientListenerPort','4701');
-INSERT INTO config (var_name,var_value) VALUES ('NumberOfDataCollectors','10');
-INSERT INTO config (var_name,var_value) VALUES ('IDataTableCreationCommand','CREATE TABLE idata_%d (item_id integer not null,idata_timestamp integer,idata_value varchar(255))');
-INSERT INTO config (var_name,var_value) VALUES ('RunNetworkDiscovery','1');
-INSERT INTO config (var_name,var_value) VALUES ('EnableAdminInterface','1');
-INSERT INTO config (var_name,var_value) VALUES ('EnableAccessControl','1');
-INSERT INTO config (var_name,var_value) VALUES ('EnableEventsAccessControl','0');
-INSERT INTO config (var_name,var_value) VALUES ('EventLogRetentionTime','5184000'); // Default retention time is 60 days == 5184000 seconds
-INSERT INTO config (var_name,var_value) VALUES ('HouseKeepingInterval','3600');
-INSERT INTO config (var_name,var_value) VALUES ('DeleteEmptySubnets','1');
-INSERT INTO config (var_name,var_value) VALUES ('EnableSNMPTraps','1');
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('DBFormatVersion',DB_FORMAT_VERSION,0,1);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('SyncInterval','60',1,1);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('NewNodePollingInterval','60',1,1);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('DiscoveryPollingInterval','900',1,1);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('StatusPollingInterval','30',1,1);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('ConfigurationPollingInterval','3600',1,1);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('ResolveNodeNames','0',1,0);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('NumberOfEventProcessors','1',1,1);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('ClientListenerPort','4701',1,1);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('NumberOfDataCollectors','10',1,1);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('IDataTableCreationCommand','CREATE TABLE idata_%d (item_id integer not null,idata_timestamp integer,idata_value varchar(255))',0,1);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('RunNetworkDiscovery','0',1,1);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('EnableAdminInterface','1',1,1);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('EnableAccessControl','1',1,0);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('EnableEventsAccessControl','0',1,0);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('EventLogRetentionTime','5184000',1,0); // Default retention time is 60 days == 5184000 seconds
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('HouseKeepingInterval','3600',1,1);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('DeleteEmptySubnets','1',1,1);
+INSERT INTO config (var_name,var_value,is_visible,need_server_restart)
+       VALUES ('EnableSNMPTraps','1',1,1);
 
 
 /*
index 04523a4..e5f63a9 100644 (file)
@@ -1,7 +1,7 @@
 INCLUDES=-I@top_srcdir@/include -I@top_srcdir@/src/server/include
 
 bin_PROGRAMS = netxmsd
-netxmsd_SOURCES = messages.c acl.cpp actions.cpp admin.cpp alarm.cpp client.cpp config.cpp container.cpp datacoll.cpp db.cpp dbwrite.cpp dcitem.cpp dcithreshold.cpp debug.cpp discovery.cpp email.cpp entirenet.cpp epp.cpp events.cpp evproc.cpp hk.cpp id.cpp image.cpp interface.cpp locks.cpp log.cpp main.cpp netinfo.cpp netobj.cpp node.cpp np.cpp objects.cpp session.cpp snmp.cpp srvroot.cpp status.cpp subnet.cpp syncer.cpp tools.cpp users.cpp watchdog.cpp winsrv.cpp
+netxmsd_SOURCES = messages.c acl.cpp actions.cpp admin.cpp alarm.cpp client.cpp config.cpp container.cpp datacoll.cpp db.cpp dbwrite.cpp dcitem.cpp dcithreshold.cpp dcivalue.cpp debug.cpp discovery.cpp email.cpp entirenet.cpp epp.cpp events.cpp evproc.cpp hk.cpp id.cpp image.cpp interface.cpp locks.cpp log.cpp main.cpp netinfo.cpp netobj.cpp node.cpp np.cpp objects.cpp session.cpp snmp.cpp srvroot.cpp status.cpp subnet.cpp syncer.cpp tools.cpp users.cpp watchdog.cpp winsrv.cpp
 netxmsd_LDADD = @PTHREAD_LIBS@ ../../libnetxms/libnetxms.la ../../libnxcscp/libnxcscp.la ../libnxsrv/libnxsrv.la -lsnmp
 
 messages.c: messages.mc
index 8db8fec..cde4424 100644 (file)
@@ -88,7 +88,7 @@ BOOL Container::CreateFromDB(DWORD dwId)
    DB_RESULT hResult;
    DWORD i;
 
-   sprintf(szQuery, "SELECT id,name,status,category,description,image_id FROM containers WHERE id=%d", dwId);
+   sprintf(szQuery, "SELECT id,name,status,category,description,image_id,is_deleted FROM containers WHERE id=%d", dwId);
    hResult = DBSelect(g_hCoreDB, szQuery);
    if (hResult == NULL)
       return FALSE;     // Query failed
@@ -106,6 +106,7 @@ BOOL Container::CreateFromDB(DWORD dwId)
    m_dwCategory = DBGetFieldULong(hResult, 0, 3);
    m_pszDescription = strdup(CHECK_NULL(DBGetField(hResult, 0, 4)));
    m_dwImageId = DBGetFieldULong(hResult, 0, 5);
+   m_bIsDeleted = DBGetFieldLong(hResult, 0, 6);
 
    DBFreeResult(hResult);
 
@@ -113,18 +114,21 @@ BOOL Container::CreateFromDB(DWORD dwId)
    LoadACLFromDB();
 
    // Load child list for later linkage
-   sprintf(szQuery, "SELECT object_id FROM container_members WHERE container_id=%d", m_dwId);
-   hResult = DBSelect(g_hCoreDB, szQuery);
-   if (hResult != NULL)
+   if (!m_bIsDeleted)
    {
-      m_dwChildIdListSize = DBGetNumRows(hResult);
-      if (m_dwChildIdListSize > 0)
+      sprintf(szQuery, "SELECT object_id FROM container_members WHERE container_id=%d", m_dwId);
+      hResult = DBSelect(g_hCoreDB, szQuery);
+      if (hResult != NULL)
       {
-         m_pdwChildIdList = (DWORD *)malloc(sizeof(DWORD) * m_dwChildIdListSize);
-         for(i = 0; i < m_dwChildIdListSize; i++)
-            m_pdwChildIdList[i] = DBGetFieldULong(hResult, i, 0);
+         m_dwChildIdListSize = DBGetNumRows(hResult);
+         if (m_dwChildIdListSize > 0)
+         {
+            m_pdwChildIdList = (DWORD *)malloc(sizeof(DWORD) * m_dwChildIdListSize);
+            for(i = 0; i < m_dwChildIdListSize; i++)
+               m_pdwChildIdList[i] = DBGetFieldULong(hResult, i, 0);
+         }
+         DBFreeResult(hResult);
       }
-      DBFreeResult(hResult);
    }
 
    return TRUE;
index c8374a5..115f802 100644 (file)
@@ -40,7 +40,7 @@ static THREAD_RESULT THREAD_CALL DataCollector(void *pArg)
    Node *pNode;
    DWORD dwError;
    time_t currTime;
-   char *pBuffer, szQuery[MAX_LINE_SIZE + 128];
+   char *pBuffer;
 
    pBuffer = (char *)malloc(MAX_LINE_SIZE);
 
@@ -67,15 +67,11 @@ static THREAD_RESULT THREAD_CALL DataCollector(void *pArg)
          currTime = time(NULL);
          pItem->SetLastPollTime(currTime);
 
-         // Store received value into database or handle error
+         // Transform and store received value into database or handle error
          switch(dwError)
          {
             case DCE_SUCCESS:
-               sprintf(szQuery, "INSERT INTO idata_%d (item_id,idata_timestamp,idata_value)"
-                                " VALUES (%d,%d,'%s')", pNode->Id(), pItem->Id(), 
-                       currTime, pBuffer);
-               QueueSQLRequest(szQuery);
-               pItem->CheckThresholds(pBuffer);
+               pItem->NewValue(currTime, pBuffer);
                break;
             case DCE_COMM_ERROR:
                break;
index 1830ddc..a60cf9a 100644 (file)
 DCItem::DCItem()
 {
    m_dwId = 0;
+   m_dwTemplateId = 0;
    m_dwNumThresholds = 0;
    m_ppThresholdList = NULL;
    m_iBusy = 0;
    m_iDataType = DCI_DT_INTEGER;
    m_iPollingInterval = 3600;
    m_iRetentionTime = 0;
+   m_iDeltaCalculation = DCM_ORIGINAL_VALUE;
    m_iSource = DS_INTERNAL;
    m_iStatus = ITEM_STATUS_NOT_SUPPORTED;
    m_szName[0] = 0;
    m_tLastPoll = 0;
+   m_pszFormula = strdup("");
    m_pNode = NULL;
    m_hMutex = MutexCreate();
+   m_dwCacheSize = 0;
+   m_ppValueCache = NULL;
 }
 
 
 //
 // Constructor for creating DCItem from database
 // Assumes that fields in SELECT query are in following order:
-// item_id,name,source,datatype,polling_interval,retention_time,status
+// item_id,name,source,datatype,polling_interval,retention_time,status,
+// delta_calculation,transformation,template_id
 //
 
 DCItem::DCItem(DB_RESULT hResult, int iRow, Node *pNode)
@@ -60,12 +66,17 @@ DCItem::DCItem(DB_RESULT hResult, int iRow, Node *pNode)
    m_iPollingInterval = DBGetFieldLong(hResult, iRow, 4);
    m_iRetentionTime = DBGetFieldLong(hResult, iRow, 5);
    m_iStatus = (BYTE)DBGetFieldLong(hResult, iRow, 6);
+   m_iDeltaCalculation = (BYTE)DBGetFieldLong(hResult, iRow, 7);
+   m_pszFormula = strdup(DBGetField(hResult, iRow, 8));
+   m_dwTemplateId = DBGetFieldULong(hResult, iRow, 9);
    m_iBusy = 0;
    m_tLastPoll = 0;
    m_dwNumThresholds = 0;
    m_ppThresholdList = NULL;
    m_pNode = pNode;
    m_hMutex = MutexCreate();
+   m_dwCacheSize = 0;
+   m_ppValueCache = NULL;
 }
 
 
@@ -77,18 +88,23 @@ DCItem::DCItem(DWORD dwId, char *szName, int iSource, int iDataType,
                int iPollingInterval, int iRetentionTime, Node *pNode)
 {
    m_dwId = dwId;
+   m_dwTemplateId = 0;
    strncpy(m_szName, szName, MAX_ITEM_NAME);
    m_iSource = iSource;
    m_iDataType = iDataType;
    m_iPollingInterval = iPollingInterval;
    m_iRetentionTime = iRetentionTime;
+   m_iDeltaCalculation = DCM_ORIGINAL_VALUE;
    m_iStatus = ITEM_STATUS_ACTIVE;
    m_iBusy = 0;
    m_tLastPoll = 0;
+   m_pszFormula = strdup("");
    m_dwNumThresholds = 0;
    m_ppThresholdList = NULL;
    m_pNode = pNode;
    m_hMutex = MutexCreate();
+   m_dwCacheSize = 0;
+   m_ppValueCache = NULL;
 }
 
 
@@ -103,6 +119,10 @@ DCItem::~DCItem()
    for(i = 0; i < m_dwNumThresholds; i++)
       delete m_ppThresholdList[i];
    safe_free(m_ppThresholdList);
+   safe_free(m_pszFormula);
+   for(i = 0; i < m_dwCacheSize; i++)
+      delete m_ppValueCache[i];
+   safe_free(m_ppValueCache);
    MutexDestroy(m_hMutex);
 }
 
@@ -145,15 +165,10 @@ BOOL DCItem::LoadThresholdsFromDB(void)
 
 BOOL DCItem::SaveToDB(void)
 {
-   char szQuery[512];
+   char *pszEscFormula, szQuery[1024];
    DB_RESULT hResult;
    BOOL bNewObject = TRUE, bResult;
 
-   // Paranoid check, DCItem::SaveToDB() normally called only
-   // for items binded to some node object
-   if (m_pNode == NULL)
-      return FALSE;
-
    Lock();
 
    // Check for object's existence in database
@@ -167,18 +182,23 @@ BOOL DCItem::SaveToDB(void)
    }
 
    // Prepare and execute query
+   pszEscFormula = EncodeSQLString(m_pszFormula);
    if (bNewObject)
-      sprintf(szQuery, "INSERT INTO items (item_id,node_id,name,description,source,"
-                       "datatype,polling_interval,retention_time,status) VALUES "
-                       "(%ld,%ld,'%s','',%d,%d,%ld,%ld,%d)", m_dwId, m_pNode->Id(),
+      sprintf(szQuery, "INSERT INTO items (item_id,node_id,template_id,name,description,source,"
+                       "datatype,polling_interval,retention_time,status,delta_calculation,"
+                       "transformation) VALUES (%ld,%ld,%ld,'%s','',%d,%d,%ld,%ld,%d,%d,'%s')",
+                       m_dwId, (m_pNode == NULL) ? 0 : m_pNode->Id(), m_dwTemplateId,
                        m_szName, m_iSource, m_iDataType, m_iPollingInterval,
-                       m_iRetentionTime, m_iStatus);
+                       m_iRetentionTime, m_iStatus, m_iDeltaCalculation, pszEscFormula);
    else
-      sprintf(szQuery, "UPDATE items SET node_id=%ld,name='%s',source=%d,datatype=%d,"
-                       "polling_interval=%ld,retention_time=%ld,status=%d WHERE item_id=%ld",
-                       m_pNode->Id(), m_szName, m_iSource, m_iDataType, m_iPollingInterval,
-                       m_iRetentionTime, m_iStatus, m_dwId);
+      sprintf(szQuery, "UPDATE items SET node_id=%ld,template_id=%ld,name='%s',source=%d,"
+                       "datatype=%d,polling_interval=%ld,retention_time=%ld,status=%d,"
+                       "delta_calculation=%d,transformation='%s' WHERE item_id=%ld",
+                       (m_pNode == NULL) ? 0 : m_pNode->Id(), m_dwTemplateId,
+                       m_szName, m_iSource, m_iDataType, m_iPollingInterval,
+                       m_iRetentionTime, m_iStatus, m_iDeltaCalculation, pszEscFormula, m_dwId);
    bResult = DBQuery(g_hCoreDB, szQuery);
+   free(pszEscFormula);
 
    // Save thresholds
    if (bResult)
@@ -222,19 +242,19 @@ BOOL DCItem::SaveToDB(void)
 // Check last value for threshold breaches
 //
 
-void DCItem::CheckThresholds(const char *pszLastValue)
+void DCItem::CheckThresholds(ItemValue &value)
 {
    DWORD i, iResult;
 
    Lock();
    for(i = 0; i < m_dwNumThresholds; i++)
    {
-      iResult = m_ppThresholdList[i]->Check(pszLastValue);
+      iResult = m_ppThresholdList[i]->Check(value);
       switch(iResult)
       {
          case THRESHOLD_REACHED:
             PostEvent(m_ppThresholdList[i]->EventCode(), m_pNode->Id(), "sss", m_szName,
-                      m_ppThresholdList[i]->Value(), pszLastValue);
+                      m_ppThresholdList[i]->Value(), (const char *)value);
             i = m_dwNumThresholds;  // Stop processing
             break;
          case THRESHOLD_REARMED:
@@ -267,6 +287,8 @@ void DCItem::CreateMessage(CSCPMessage *pMsg)
    pMsg->SetVariable(VID_DCI_SOURCE_TYPE, (WORD)m_iSource);
    pMsg->SetVariable(VID_DCI_DATA_TYPE, (WORD)m_iDataType);
    pMsg->SetVariable(VID_DCI_STATUS, (WORD)m_iStatus);
+   pMsg->SetVariable(VID_DCI_DELTA_CALCULATION, (WORD)m_iDeltaCalculation);
+   pMsg->SetVariable(VID_DCI_FORMULA, m_pszFormula);
    pMsg->SetVariable(VID_NUM_THRESHOLDS, m_dwNumThresholds);
    for(i = 0, dwId = VID_DCI_THRESHOLD_BASE; i < m_dwNumThresholds; i++, dwId++)
    {
@@ -313,6 +335,9 @@ void DCItem::UpdateFromMessage(CSCPMessage *pMsg, DWORD *pdwNumMaps,
    m_iPollingInterval = pMsg->GetVariableLong(VID_POLLING_INTERVAL);
    m_iRetentionTime = pMsg->GetVariableLong(VID_RETENTION_TIME);
    m_iStatus = (BYTE)pMsg->GetVariableShort(VID_DCI_STATUS);
+   m_iDeltaCalculation = (BYTE)pMsg->GetVariableShort(VID_DCI_DELTA_CALCULATION);
+   safe_free(m_pszFormula);
+   m_pszFormula = pMsg->GetVariableStr(VID_DCI_FORMULA);
 
    // Update thresholds
    dwNum = pMsg->GetVariableLong(VID_NUM_THRESHOLDS);
@@ -372,3 +397,68 @@ void DCItem::UpdateFromMessage(CSCPMessage *pMsg, DWORD *pdwNumMaps,
    safe_free(pNewThresholds);
    Unlock();
 }
+
+
+//
+// Process new value
+//
+
+void DCItem::NewValue(DWORD dwTimeStamp, const char *pszOriginalValue)
+{
+   char szQuery[MAX_LINE_SIZE + 128];
+   ItemValue *pValue;
+
+   // Normally m_pNode shouldn't be NULL for polled items,
+   // but who knows...
+   if (m_pNode == NULL)
+      return;
+
+   // Create new ItemValue object and transform it as needed
+   pValue = new ItemValue(pszOriginalValue);
+   m_prevRawValue = *pValue;
+   Transform(*pValue);
+
+   // Save transformed value to database
+   sprintf(szQuery, "INSERT INTO idata_%ld (item_id,idata_timestamp,idata_value)"
+                    " VALUES (%ld,%ld,'%s')", m_pNode->Id(), m_dwId, dwTimeStamp, 
+           pValue->String());
+   QueueSQLRequest(szQuery);
+
+   // Check thresholds and add value to cache
+   CheckThresholds(*pValue);
+}
+
+
+//
+// Transform received value
+//
+
+void DCItem::Transform(ItemValue &value)
+{
+   switch(m_iDeltaCalculation)
+   {
+      case DCM_SIMPLE:
+         switch(m_iDataType)
+         {
+            case DCI_DT_INTEGER:
+               value = (long)value - (long)m_prevRawValue;
+               break;
+            case DCI_DT_INT64:
+               value = (INT64)value - (INT64)m_prevRawValue;
+               break;
+            case DCI_DT_FLOAT:
+               value = (double)value - (double)m_prevRawValue;
+               break;
+            default:
+               // Delta calculation is not supported for other types
+               break;
+         }
+         break;
+      case DCM_AVERAGE_PER_SECOND:
+         break;
+      case DCM_AVERAGE_PER_MINUTE:
+         break;
+      default:    // Default is no transformation
+         break;
+   }
+}
index cac88bb..df189b8 100644 (file)
@@ -144,7 +144,7 @@ BOOL Threshold::SaveToDB(DWORD dwIndex)
 //    NO_ACTION - when there are no changes in item's value match to threshold's condition
 //
 
-int Threshold::Check(const char *pszValue)
+int Threshold::Check(ItemValue &value)
 {
    BOOL bMatch = FALSE;
    int iResult;
@@ -163,16 +163,16 @@ int Threshold::Check(const char *pszValue)
          switch(m_iDataType)
          {
             case DCI_DT_INTEGER:
-               fvalue.iInteger = strtol(pszValue, NULL, 0);
+               fvalue.iInteger = (long)value;
                break;
             case DCI_DT_INT64:
-               /* TODO: add 64-bit conversion code */
+               fvalue.qwInt64 = (INT64)value;
                break;
             case DCI_DT_FLOAT:
-               fvalue.dFloat = strtod(pszValue, NULL);
+               fvalue.dFloat = (double)value;
                break;
             case DCI_DT_STRING:
-               fvalue.pszStr = pszValue;
+               fvalue.pszStr = (const char *)value;
                break;
             default:
                WriteLog(MSG_INVALID_DTYPE, EVENTLOG_ERROR_TYPE, "ds", m_iDataType, "Threshold::Check()");
diff --git a/src/server/core/dcivalue.cpp b/src/server/core/dcivalue.cpp
new file mode 100644 (file)
index 0000000..247792c
--- /dev/null
@@ -0,0 +1,156 @@
+/* 
+** NetXMS - Network Management System
+** Copyright (C) 2003, 2004 Victor Kirhenshtein
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+** $module: dcivalue.cpp
+**
+**/
+
+#include "nms_core.h"
+
+
+//
+// Default constructor
+//
+
+ItemValue::ItemValue()
+{
+   m_szString[0] = 0;
+   m_iInt32 = 0;
+   m_iInt64 = 0;
+   m_dwInt32 = 0;
+   m_qwInt64 = 0;
+   m_dFloat = 0;
+}
+
+
+//
+// Construct value object from string value
+//
+
+ItemValue::ItemValue(const char *pszValue)
+{
+   /* TODO: add 64-bit conversion !!! */
+   strncpy(m_szString, pszValue, MAX_DB_STRING);
+   m_iInt32 = strtol(m_szString, NULL, 0);
+   m_iInt64 = 0;
+   m_dwInt32 = strtoul(m_szString, NULL, 0);
+   m_qwInt64 = 0;
+   m_dFloat = strtod(m_szString, NULL);
+}
+
+
+//
+// Construct value object from another ItemValue object
+//
+
+ItemValue::ItemValue(const ItemValue *pValue)
+{
+   strcpy(m_szString, pValue->m_szString);
+   m_iInt32 = pValue->m_iInt32;
+   m_iInt64 = pValue->m_iInt64;
+   m_dwInt32 = pValue->m_dwInt32;
+   m_qwInt64 = pValue->m_qwInt64;
+   m_dFloat = pValue->m_dFloat;
+}
+
+
+//
+// Destructor
+//
+
+ItemValue::~ItemValue()
+{
+}
+
+
+//
+// Assignment operators
+//
+
+const ItemValue& ItemValue::operator=(ItemValue &src)
+{
+   strcpy(m_szString, src.m_szString);
+   m_iInt32 = src.m_iInt32;
+   m_iInt64 = src.m_iInt64;
+   m_dwInt32 = src.m_dwInt32;
+   m_qwInt64 = src.m_qwInt64;
+   m_dFloat = src.m_dFloat;
+   return *this;
+}
+
+const ItemValue& ItemValue::operator=(double dFloat)
+{
+   m_dFloat = dFloat;
+   sprintf(m_szString, "%f", m_dFloat);
+   m_iInt32 = (long)m_dFloat;
+   m_iInt64 = (UINT64)m_dFloat;
+   m_dwInt32 = (DWORD)m_dFloat;
+   m_qwInt64 = (QWORD)m_dFloat;
+   return *this;
+}
+
+const ItemValue& ItemValue::operator=(long iInt32)
+{
+   m_iInt32 = iInt32;
+   sprintf(m_szString, "%ld", m_iInt32);
+   m_dFloat = (double)m_iInt32;
+   m_iInt64 = (UINT64)m_iInt32;
+   m_dwInt32 = (DWORD)m_iInt32;
+   m_qwInt64 = (QWORD)m_iInt32;
+   return *this;
+}
+
+const ItemValue& ItemValue::operator=(INT64 iInt64)
+{
+   m_iInt64 = iInt64;
+#ifdef _WIN32
+   sprintf(m_szString, "%I64d", m_iInt64);
+#else    /* _WIN32 */
+   sprintf(m_szString, "%lld", m_iInt64);
+#endif
+   m_dFloat = (double)m_iInt64;
+   m_iInt32 = (long)m_iInt64;
+   m_dwInt32 = (DWORD)m_iInt64;
+   m_qwInt64 = (QWORD)m_iInt64;
+   return *this;
+}
+
+const ItemValue& ItemValue::operator=(DWORD dwInt32)
+{
+   m_dwInt32 = dwInt32;
+   sprintf(m_szString, "%lu", m_dwInt32);
+   m_dFloat = (double)m_dwInt32;
+   m_iInt32 = (long)m_dwInt32;
+   m_iInt64 = (UINT64)m_dwInt32;
+   m_qwInt64 = (QWORD)m_dwInt32;
+   return *this;
+}
+
+const ItemValue& ItemValue::operator=(QWORD qwInt64)
+{
+   m_qwInt64 = qwInt64;
+#ifdef _WIN32
+   sprintf(m_szString, "%I64u", m_qwInt64);
+#else    /* _WIN32 */
+   sprintf(m_szString, "%llu", m_qwInt64);
+#endif
+   m_dFloat = (double)((INT64)m_qwInt64);
+   m_iInt32 = (long)m_qwInt64;
+   m_iInt64 = (UINT64)m_qwInt64;
+   return *this;
+}
index ec22f11..bd8b6f6 100644 (file)
@@ -87,10 +87,10 @@ BOOL Interface::CreateFromDB(DWORD dwId)
    NetObj *pObject;
    BOOL bResult = FALSE;
 
-   sprintf(szQuery, "SELECT id,name,status,ip_addr,ip_netmask,if_type,if_index,node_id,image_id"
-                    " FROM interfaces WHERE id=%d", dwId);
+   sprintf(szQuery, "SELECT id,name,status,ip_addr,ip_netmask,if_type,if_index,node_id,"
+                    "image_id,is_deleted FROM interfaces WHERE id=%d", dwId);
    hResult = DBSelect(g_hCoreDB, szQuery);
-   if (hResult == 0)
+   if (hResult == NULL)
       return FALSE;     // Query failed
 
    if (DBGetNumRows(hResult) != 0)
@@ -104,21 +104,29 @@ BOOL Interface::CreateFromDB(DWORD dwId)
       m_dwIfIndex = DBGetFieldULong(hResult, 0, 6);
       dwNodeId = DBGetFieldULong(hResult, 0, 7);
       m_dwImageId = DBGetFieldULong(hResult, 0, 8);
+      m_bIsDeleted = DBGetFieldLong(hResult, 0, 9);
 
       // Link interface to node
-      pObject = FindObjectById(dwNodeId);
-      if (pObject == NULL)
+      if (!m_bIsDeleted)
       {
-         WriteLog(MSG_INVALID_NODE_ID, EVENTLOG_ERROR_TYPE, "dd", dwId, dwNodeId);
-      }
-      else if (pObject->Type() != OBJECT_NODE)
-      {
-         WriteLog(MSG_NODE_NOT_NODE, EVENTLOG_ERROR_TYPE, "dd", dwId, dwNodeId);
+         pObject = FindObjectById(dwNodeId);
+         if (pObject == NULL)
+         {
+            WriteLog(MSG_INVALID_NODE_ID, EVENTLOG_ERROR_TYPE, "dd", dwId, dwNodeId);
+         }
+         else if (pObject->Type() != OBJECT_NODE)
+         {
+            WriteLog(MSG_NODE_NOT_NODE, EVENTLOG_ERROR_TYPE, "dd", dwId, dwNodeId);
+         }
+         else
+         {
+            pObject->AddChild(this);
+            AddParent(pObject);
+            bResult = TRUE;
+         }
       }
       else
       {
-         pObject->AddChild(this);
-         AddParent(pObject);
          bResult = TRUE;
       }
    }
index 58d89f0..3742dbe 100644 (file)
@@ -139,6 +139,10 @@ SOURCE=.\dcithreshold.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\dcivalue.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\debug.cpp
 # End Source File
 # Begin Source File
index a0f0a86..870d00b 100644 (file)
 #define NO_ACTION          2
 
 
+//
+// DCI value
+//
+
+class ItemValue
+{
+private:
+   double m_dFloat;
+   long m_iInt32;
+   INT64 m_iInt64;
+   DWORD m_dwInt32;
+   QWORD m_qwInt64;
+   char m_szString[MAX_DB_STRING];
+
+public:
+   ItemValue();
+   ItemValue(const char *pszValue);
+   ItemValue(const ItemValue *pValue);
+   ~ItemValue();
+
+   const char *String(void) { return m_szString; }
+
+   operator double() { return m_dFloat; }
+   operator DWORD() { return m_dwInt32; }
+   operator QWORD() { return m_qwInt64; }
+   operator long() { return m_iInt32; }
+   operator INT64() { return m_iInt64; }
+   operator const char*() const { return m_szString; }
+
+   const ItemValue& operator=(ItemValue &src);
+   const ItemValue& operator=(double dFloat);
+   const ItemValue& operator=(long iInt32);
+   const ItemValue& operator=(INT64 iInt64);
+   const ItemValue& operator=(DWORD dwInt32);
+   const ItemValue& operator=(QWORD qwInt64);
+};
+
+
 //
 // Threshold definition class
 //
@@ -79,7 +117,7 @@ public:
    BOOL IsReached(void) { return m_bIsReached; }
 
    BOOL SaveToDB(DWORD dwIndex);
-   int Check(const char *pszValue);
+   int Check(ItemValue &value);
 
    void CreateMessage(DCI_THRESHOLD *pData);
    void UpdateFromMessage(DCI_THRESHOLD *pData);
@@ -99,21 +137,30 @@ class DCItem
 private:
    DWORD m_dwId;
    char m_szName[MAX_ITEM_NAME];
-   time_t m_tLastPoll;       // Last poll time
-   int m_iPollingInterval;   // Polling interval in seconds
-   int m_iRetentionTime;     // Retention time in seconds
-   BYTE m_iSource;           // SNMP or native agent?
+   time_t m_tLastPoll;        // Last poll time
+   int m_iPollingInterval;    // Polling interval in seconds
+   int m_iRetentionTime;      // Retention time in seconds
+   BYTE m_iDeltaCalculation;  // Delta calculation method
+   BYTE m_iSource;            // SNMP or native agent?
    BYTE m_iDataType;
-   BYTE m_iStatus;           // Item status: active, disabled or not supported
-   BYTE m_iBusy;             // 1 when item is queued for polling, 0 if not
+   BYTE m_iStatus;            // Item status: active, disabled or not supported
+   BYTE m_iBusy;              // 1 when item is queued for polling, 0 if not
+   DWORD m_dwTemplateId;      // Related template's id
    DWORD m_dwNumThresholds;
    Threshold **m_ppThresholdList;
    Node *m_pNode;             // Pointer to node object this item related to
+   char *m_pszFormula;        // Transformation formula
    MUTEX m_hMutex;
+   DWORD m_dwCacheSize;       // Number of items in cache
+   ItemValue **m_ppValueCache;
+   ItemValue m_prevRawValue;  // Previous raw value (used for delta calculation)
 
    void Lock(void) { MutexLock(m_hMutex, INFINITE); }
    void Unlock(void) { MutexUnlock(m_hMutex); }
 
+   void Transform(ItemValue &value);
+   void CheckThresholds(ItemValue &value);
+
 public:
    DCItem();
    DCItem(DB_RESULT hResult, int iRow, Node *pNode);
@@ -141,7 +188,7 @@ public:
    void SetStatus(int iStatus) { m_iStatus = (BYTE)iStatus; }
    void SetBusyFlag(BOOL bIsBusy) { m_iBusy = (BYTE)bIsBusy; }
 
-   void CheckThresholds(const char *pszLastValue);
+   void NewValue(DWORD dwTimeStamp, const char *pszValue);
 
    void CreateMessage(CSCPMessage *pMsg);
    void UpdateFromMessage(CSCPMessage *pMsg, DWORD *pdwNumMaps, DWORD **ppdwMapIndex, DWORD **ppdwMapId);
index 9e20463..75270a6 100644 (file)
@@ -126,11 +126,12 @@ BOOL Node::CreateFromDB(DWORD dwId)
    int i, iNumRows;
    DWORD dwSubnetId;
    NetObj *pObject;
+   BOOL bResult = FALSE;
 
    sprintf(szQuery, "SELECT id,name,status,primary_ip,is_snmp,is_agent,is_bridge,"
                     "is_router,snmp_version,discovery_flags,auth_method,secret,"
                     "agent_port,status_poll_type,community,snmp_oid,is_local_mgmt,"
-                    "image_id FROM nodes WHERE id=%d", dwId);
+                    "image_id,is_deleted FROM nodes WHERE id=%d", dwId);
    hResult = DBSelect(g_hCoreDB, szQuery);
    if (hResult == 0)
       return FALSE;     // Query failed
@@ -167,53 +168,60 @@ BOOL Node::CreateFromDB(DWORD dwId)
    strncpy(m_szCommunityString, DBGetField(hResult, 0, 14), MAX_COMMUNITY_LENGTH);
    strncpy(m_szObjectId, DBGetField(hResult, 0, 15), MAX_OID_LEN * 4);
    m_dwImageId = DBGetFieldULong(hResult, 0, 17);
+   m_bIsDeleted = DBGetFieldLong(hResult, 0, 18);
 
    DBFreeResult(hResult);
 
-   // Link node to subnets
-   sprintf(szQuery, "SELECT subnet_id FROM nsmap WHERE node_id=%d", dwId);
-   hResult = DBSelect(g_hCoreDB, szQuery);
-   if (hResult == 0)
-      return FALSE;     // Query failed
-
-   if (DBGetNumRows(hResult) == 0)
+   if (!m_bIsDeleted)
    {
-      DBFreeResult(hResult);
-      return FALSE;     // No parents - it shouldn't happen if database isn't corrupted
-   }
+      // Link node to subnets
+      sprintf(szQuery, "SELECT subnet_id FROM nsmap WHERE node_id=%d", dwId);
+      hResult = DBSelect(g_hCoreDB, szQuery);
+      if (hResult == NULL)
+         return FALSE;     // Query failed
 
-   BOOL bResult = FALSE;
-   iNumRows = DBGetNumRows(hResult);
-   for(i = 0; i < iNumRows; i++)
-   {
-      dwSubnetId = DBGetFieldULong(hResult, i, 0);
-      pObject = FindObjectById(dwSubnetId);
-      if (pObject == NULL)
-      {
-         WriteLog(MSG_INVALID_SUBNET_ID, EVENTLOG_ERROR_TYPE, "dd", dwId, dwSubnetId);
-         break;
-      }
-      else if (pObject->Type() != OBJECT_SUBNET)
+      if (DBGetNumRows(hResult) == 0)
       {
-         WriteLog(MSG_SUBNET_NOT_SUBNET, EVENTLOG_ERROR_TYPE, "dd", dwId, dwSubnetId);
-         break;
+         DBFreeResult(hResult);
+         return FALSE;     // No parents - it shouldn't happen if database isn't corrupted
       }
-      else
+
+      iNumRows = DBGetNumRows(hResult);
+      for(i = 0; i < iNumRows; i++)
       {
-         pObject->AddChild(this);
-         AddParent(pObject);
-         bResult = TRUE;
+         dwSubnetId = DBGetFieldULong(hResult, i, 0);
+         pObject = FindObjectById(dwSubnetId);
+         if (pObject == NULL)
+         {
+            WriteLog(MSG_INVALID_SUBNET_ID, EVENTLOG_ERROR_TYPE, "dd", dwId, dwSubnetId);
+            break;
+         }
+         else if (pObject->Type() != OBJECT_SUBNET)
+         {
+            WriteLog(MSG_SUBNET_NOT_SUBNET, EVENTLOG_ERROR_TYPE, "dd", dwId, dwSubnetId);
+            break;
+         }
+         else
+         {
+            pObject->AddChild(this);
+            AddParent(pObject);
+            bResult = TRUE;
+         }
       }
-   }
 
-   DBFreeResult(hResult);
-   LoadItemsFromDB();
-   LoadACLFromDB();
+      DBFreeResult(hResult);
+      LoadItemsFromDB();
+      LoadACLFromDB();
 
-   // Walk through all items in the node and load appropriate thresholds
-   for(i = 0; i < (int)m_dwNumItems; i++)
-      if (!m_ppItems[i]->LoadThresholdsFromDB())
-         bResult = FALSE;
+      // Walk through all items in the node and load appropriate thresholds
+      for(i = 0; i < (int)m_dwNumItems; i++)
+         if (!m_ppItems[i]->LoadThresholdsFromDB())
+            bResult = FALSE;
+   }
+   else
+   {
+      bResult = TRUE;
+   }
 
    return bResult;
 }
@@ -229,7 +237,8 @@ void Node::LoadItemsFromDB(void)
    DB_RESULT hResult;
 
    sprintf(szQuery, "SELECT item_id,name,source,datatype,polling_interval,retention_time,"
-                    "status FROM items WHERE node_id=%d", m_dwId);
+                    "status,delta_calculation,transformation,template_id "
+                    "FROM items WHERE node_id=%d", m_dwId);
    hResult = DBSelect(g_hCoreDB, szQuery);
 
    if (hResult != 0)
index ed278a7..67dfbe9 100644 (file)
@@ -194,7 +194,8 @@ void NetObjInsert(NetObj *pObject, BOOL bNewObject)
    MutexLock(g_hMutexIdIndex, INFINITE);
    AddObjectToIndex(&g_pIndexById, &g_dwIdIndexSize, pObject->Id(), pObject);
    MutexUnlock(g_hMutexIdIndex);
-   if (pObject->IpAddr() != 0)
+   if ((pObject->IpAddr() != 0) && (!pObject->IsDeleted()))
+   {
       switch(pObject->Type())
       {
          case OBJECT_GENERIC:
@@ -225,6 +226,7 @@ void NetObjInsert(NetObj *pObject, BOOL bNewObject)
             WriteLog(MSG_BAD_NETOBJ_TYPE, EVENTLOG_ERROR_TYPE, "d", pObject->Type());
             break;
       }
+   }
    ObjectsGlobalUnlock();
 }
 
@@ -425,7 +427,7 @@ BOOL LoadObjects(void)
    g_pServiceRoot->LoadFromDB();
 
    // Load subnets
-   hResult = DBSelect(g_hCoreDB, "SELECT id FROM subnets WHERE is_deleted=0");
+   hResult = DBSelect(g_hCoreDB, "SELECT id FROM subnets");
    if (hResult != 0)
    {
       Subnet *pSubnet;
@@ -437,7 +439,8 @@ BOOL LoadObjects(void)
          pSubnet = new Subnet;
          if (pSubnet->CreateFromDB(dwId))
          {
-            g_pEntireNet->AddSubnet(pSubnet);
+            if (!pSubnet->IsDeleted())
+               g_pEntireNet->AddSubnet(pSubnet);
             NetObjInsert(pSubnet, FALSE);  // Insert into indexes
          }
          else     // Object load failed
@@ -450,7 +453,7 @@ BOOL LoadObjects(void)
    }
 
    // Load nodes
-   hResult = DBSelect(g_hCoreDB, "SELECT id FROM nodes WHERE is_deleted=0");
+   hResult = DBSelect(g_hCoreDB, "SELECT id FROM nodes");
    if (hResult != 0)
    {
       Node *pNode;
@@ -474,7 +477,7 @@ BOOL LoadObjects(void)
    }
 
    // Load interfaces
-   hResult = DBSelect(g_hCoreDB, "SELECT id FROM interfaces WHERE is_deleted=0");
+   hResult = DBSelect(g_hCoreDB, "SELECT id FROM interfaces");
    if (hResult != 0)
    {
       Interface *pInterface;
@@ -498,7 +501,7 @@ BOOL LoadObjects(void)
    }
 
    // Load container objects
-   hResult = DBSelect(g_hCoreDB, "SELECT id FROM containers WHERE is_deleted=0");
+   hResult = DBSelect(g_hCoreDB, "SELECT id FROM containers");
    if (hResult != 0)
    {
       Container *pContainer;
@@ -574,12 +577,12 @@ void DumpObjects(void)
    for(i = 0; i < g_dwIdIndexSize; i++)
    {
       printf("Object ID %d \"%s\"\n"
-             "   Class: %s  Primary IP: %s  Status: %s  IsModified: %d\n",
+             "   Class: %s  Primary IP: %s  Status: %s  IsModified: %d  IsDeleted: %d\n",
              g_pIndexById[i].pObject->Id(),g_pIndexById[i].pObject->Name(),
              objTypes[g_pIndexById[i].pObject->Type()],
              IpToStr(g_pIndexById[i].pObject->IpAddr(), pBuffer),
              statusName[g_pIndexById[i].pObject->Status()],
-             g_pIndexById[i].pObject->IsModified());
+             g_pIndexById[i].pObject->IsModified(), g_pIndexById[i].pObject->IsDeleted());
       printf("   Parents: <%s>\n   Childs: <%s>\n", 
              g_pIndexById[i].pObject->ParentList(pBuffer),
              g_pIndexById[i].pObject->ChildList(&pBuffer[4096]));
index c6630bf..22030d1 100644 (file)
@@ -862,8 +862,8 @@ void ClientSession::OnObjectChange(NetObj *pObject)
          pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
          pUpdate->dwCategory = INFO_CAT_OBJECT_CHANGE;
          pUpdate->pData = pObject;
-         m_pUpdateQueue->Put(pUpdate);
          pObject->IncRefCount();
+         m_pUpdateQueue->Put(pUpdate);
       }
 }
 
index 71d72bf..f169768 100644 (file)
@@ -66,7 +66,7 @@ BOOL Subnet::CreateFromDB(DWORD dwId)
    char szQuery[256];
    DB_RESULT hResult;
 
-   sprintf(szQuery, "SELECT id,name,status,ip_addr,ip_netmask,image_id FROM subnets WHERE id=%d", dwId);
+   sprintf(szQuery, "SELECT id,name,status,ip_addr,ip_netmask,image_id,is_deleted FROM subnets WHERE id=%d", dwId);
    hResult = DBSelect(g_hCoreDB, szQuery);
    if (hResult == 0)
       return FALSE;     // Query failed
@@ -83,6 +83,7 @@ BOOL Subnet::CreateFromDB(DWORD dwId)
    m_dwIpAddr = DBGetFieldULong(hResult, 0, 3);
    m_dwIpNetMask = DBGetFieldULong(hResult, 0, 4);
    m_dwImageId = DBGetFieldULong(hResult, 0, 5);
+   m_bIsDeleted = DBGetFieldLong(hResult, 0, 6);
 
    DBFreeResult(hResult);
 
index 09ddbee..7a75bef 100644 (file)
@@ -38,6 +38,8 @@ void SaveObjects(void)
       if (g_pIndexById[i].pObject->IsDeleted())
          if (g_pIndexById[i].pObject->RefCount() == 0)
          {
+            DbgPrintf(AF_DEBUG_HOUSEKEEPER, "* Syncer * Object %d \"%s\" deleted\n",
+                      g_pIndexById[i].pObject->Id(), g_pIndexById[i].pObject->Name());
             g_pIndexById[i].pObject->DeleteFromDB();
             NetObjDelete(g_pIndexById[i].pObject);
             i = 0xFFFFFFFF;   // Restart loop