Implemented instance discovery functionality for Table DCIs. Fixes #NX1119
authorEriks Jenkevics <eriks@netxms.org>
Mon, 6 Feb 2017 08:43:59 +0000 (10:43 +0200)
committerEriks Jenkevics <eriks@netxms.org>
Fri, 17 Mar 2017 11:22:49 +0000 (13:22 +0200)
18 files changed:
include/netxmsdb.h
sql/schema.in
src/java/client/netxms-client/src/main/java/org/netxms/client/datacollection/DataCollectionItem.java
src/java/client/netxms-client/src/main/java/org/netxms/client/datacollection/DataCollectionObject.java
src/java/client/netxms-client/src/main/java/org/netxms/client/datacollection/DataCollectionTable.java
src/java/netxms-eclipse/DataCollection/plugin.xml
src/java/netxms-eclipse/DataCollection/src/org/netxms/ui/eclipse/datacollection/propertypages/InstanceDiscovery.java
src/server/core/dcitem.cpp
src/server/core/dcobject.cpp
src/server/core/dctable.cpp
src/server/core/node.cpp
src/server/core/template.cpp
src/server/include/nms_dcoll.h
src/server/include/nms_objects.h
src/server/tools/nxdbmgr/upgrade.cpp
webui/webapp/DataCollection/plugin.xml
webui/webapp/DataCollection/src/org/netxms/ui/eclipse/datacollection/propertypages/InstanceDiscovery.java
webui/webapp/DataCollection/src/org/netxms/ui/eclipse/datacollection/widgets/LastValuesWidget.java

index 3439dde..e52effe 100644 (file)
@@ -23,6 +23,6 @@
 #ifndef _netxmsdb_h
 #define _netxmsdb_h
 
-#define DB_FORMAT_VERSION   442
+#define DB_FORMAT_VERSION   443
 
 #endif
index 80373ec..9b103c1 100644 (file)
@@ -653,6 +653,10 @@ CREATE TABLE dc_tables
   perftab_settings SQL_TEXT null,     // Settings for displaying graph on performance tab
   transformation_script SQL_TEXT null,
   comments SQL_TEXT null,
+  instance varchar(255) null,
+  instd_method integer not null.
+  instd_data varchar(255) null,
+  instd_filter SQL TEXT null,
   PRIMARY KEY(item_id)
 ) TABLE_TYPE;
 
index 805e2a2..b8eaed6 100644 (file)
@@ -58,26 +58,14 @@ public class DataCollectionItem extends DataCollectionObject
        public static final int SNMP_RAWTYPE_IP_ADDR = 6;
        public static final int SNMP_RAWTYPE_MAC_ADDR = 7;
        
-       // Instance discovery methods
-       public static final int IDM_NONE = 0;
-       public static final int IDM_AGENT_LIST = 1;
-       public static final int IDM_AGENT_TABLE = 2;
-       public static final int IDM_SNMP_WALK_VALUES = 3;
-       public static final int IDM_SNMP_WALK_OIDS = 4;
-   public static final int IDM_SCRIPT = 5;
-       
        private int dataType;
        private int deltaCalculation;
        private int sampleCount;
-       private String instance;
        private int baseUnits;
        private int multiplier;
        private String customUnitName;
        private int snmpRawValueType;
        private ArrayList<Threshold> thresholds;
-       private int instanceDiscoveryMethod;
-       private String instanceDiscoveryData;
-       private String instanceDiscoveryFilter;
        private String predictionEngine;
        
        /**
@@ -93,14 +81,10 @@ public class DataCollectionItem extends DataCollectionObject
                dataType = msg.getFieldAsInt32(NXCPCodes.VID_DCI_DATA_TYPE);
                deltaCalculation = msg.getFieldAsInt32(NXCPCodes.VID_DCI_DELTA_CALCULATION);
                sampleCount = msg.getFieldAsInt32(NXCPCodes.VID_SAMPLE_COUNT);
-               instance = msg.getFieldAsString(NXCPCodes.VID_INSTANCE);
                baseUnits = msg.getFieldAsInt32(NXCPCodes.VID_BASE_UNITS);
                multiplier = msg.getFieldAsInt32(NXCPCodes.VID_MULTIPLIER);
                customUnitName = msg.getFieldAsString(NXCPCodes.VID_CUSTOM_UNITS_NAME);
                snmpRawValueType = msg.getFieldAsInt32(NXCPCodes.VID_SNMP_RAW_VALUE_TYPE);
-               instanceDiscoveryMethod = msg.getFieldAsInt32(NXCPCodes.VID_INSTD_METHOD);
-               instanceDiscoveryData = msg.getFieldAsString(NXCPCodes.VID_INSTD_DATA);
-               instanceDiscoveryFilter = msg.getFieldAsString(NXCPCodes.VID_INSTD_FILTER);
                predictionEngine = msg.getFieldAsString(NXCPCodes.VID_NPE_NAME);
                
                int count = msg.getFieldAsInt32(NXCPCodes.VID_NUM_THRESHOLDS);
@@ -125,7 +109,6 @@ public class DataCollectionItem extends DataCollectionObject
                dataType = DT_INT;
                deltaCalculation = DELTA_NONE;
                sampleCount = 0;
-               instance = "";
                baseUnits = 0;
                multiplier = 0;
                customUnitName = null;
@@ -147,7 +130,6 @@ public class DataCollectionItem extends DataCollectionObject
                msg.setFieldInt16(NXCPCodes.VID_DCI_DATA_TYPE, dataType);
                msg.setFieldInt16(NXCPCodes.VID_DCI_DELTA_CALCULATION, deltaCalculation);
                msg.setFieldInt16(NXCPCodes.VID_SAMPLE_COUNT, sampleCount);
-               msg.setField(NXCPCodes.VID_INSTANCE, instance);
                msg.setFieldInt16(NXCPCodes.VID_SNMP_RAW_VALUE_TYPE, snmpRawValueType);
                msg.setField(NXCPCodes.VID_NPE_NAME, predictionEngine);
                msg.setFieldInt16(NXCPCodes.VID_BASE_UNITS, baseUnits);
@@ -155,12 +137,6 @@ public class DataCollectionItem extends DataCollectionObject
                if (customUnitName != null)
                        msg.setField(NXCPCodes.VID_CUSTOM_UNITS_NAME, customUnitName);
                
-               msg.setFieldInt16(NXCPCodes.VID_INSTD_METHOD, instanceDiscoveryMethod);
-               if (instanceDiscoveryData != null)
-                       msg.setField(NXCPCodes.VID_INSTD_DATA, instanceDiscoveryData);
-               if (instanceDiscoveryFilter != null)
-                       msg.setField(NXCPCodes.VID_INSTD_FILTER, instanceDiscoveryFilter);
-               
                msg.setFieldInt32(NXCPCodes.VID_NUM_THRESHOLDS, thresholds.size());
                long varId = NXCPCodes.VID_DCI_THRESHOLD_BASE;
                for(int i = 0; i < thresholds.size(); i++, varId +=10)
@@ -295,22 +271,6 @@ public class DataCollectionItem extends DataCollectionObject
                flags = (flags & ~DCF_AGGREGATE_FUNCTION_MASK) | ((func & 0x07) << 4);
        }
 
-       /**
-        * @return the instance
-        */
-       public String getInstance()
-       {
-               return instance;
-       }
-
-       /**
-        * @param instance the instance to set
-        */
-       public void setInstance(String instance)
-       {
-               this.instance = instance;
-       }
-
        /**
         * @return the baseUnits
         */
@@ -383,54 +343,6 @@ public class DataCollectionItem extends DataCollectionObject
                this.snmpRawValueType = snmpRawValueType;
        }
 
-       /**
-        * @return the instanceDiscoveryMethod
-        */
-       public final int getInstanceDiscoveryMethod()
-       {
-               return instanceDiscoveryMethod;
-       }
-
-       /**
-        * @param instanceDiscoveryMethod the instanceDiscoveryMethod to set
-        */
-       public final void setInstanceDiscoveryMethod(int instanceDiscoveryMethod)
-       {
-               this.instanceDiscoveryMethod = instanceDiscoveryMethod;
-       }
-
-       /**
-        * @return the instanceDiscoveryData
-        */
-       public final String getInstanceDiscoveryData()
-       {
-               return instanceDiscoveryData;
-       }
-
-       /**
-        * @param instanceDiscoveryData the instanceDiscoveryData to set
-        */
-       public final void setInstanceDiscoveryData(String instanceDiscoveryData)
-       {
-               this.instanceDiscoveryData = instanceDiscoveryData;
-       }
-
-       /**
-        * @return the instanceDiscoveryFilter
-        */
-       public final String getInstanceDiscoveryFilter()
-       {
-               return instanceDiscoveryFilter;
-       }
-
-       /**
-        * @param instanceDiscoveryFilter the instanceDiscoveryFilter to set
-        */
-       public final void setInstanceDiscoveryFilter(String instanceDiscoveryFilter)
-       {
-               this.instanceDiscoveryFilter = instanceDiscoveryFilter;
-       }
-
        /**
         * @return the sampleCount
         */
index ac37683..3420fa0 100644 (file)
@@ -67,6 +67,14 @@ public abstract class DataCollectionObject
    public static final int DCF_NO_STORAGE            = 0x0200;
    public static final int DCF_CACHE_MODE_MASK       = 0x3000;
    public static final int DCF_AGGREGATE_WITH_ERRORS = 0x4000;
+   
+   // Instance discovery methods
+   public static final int IDM_NONE = 0;
+   public static final int IDM_AGENT_LIST = 1;
+   public static final int IDM_AGENT_TABLE = 2;
+   public static final int IDM_SNMP_WALK_VALUES = 3;
+   public static final int IDM_SNMP_WALK_OIDS = 4;
+   public static final int IDM_SCRIPT = 5;
        
        protected DataCollectionConfiguration owner;
        protected long id;
@@ -87,6 +95,10 @@ public abstract class DataCollectionObject
        protected ArrayList<String> schedules;
        protected Object userData;
        private String comments;
+   private String instance;
+   private int instanceDiscoveryMethod;
+   private String instanceDiscoveryData;
+   private String instanceDiscoveryFilter;
 
        /**
         * Create data collection object from NXCP message
@@ -121,6 +133,11 @@ public abstract class DataCollectionObject
                {
                        schedules.add(msg.getFieldAsString(varId));
                }
+               
+      instance = msg.getFieldAsString(NXCPCodes.VID_INSTANCE);
+      instanceDiscoveryMethod = msg.getFieldAsInt32(NXCPCodes.VID_INSTD_METHOD);
+      instanceDiscoveryData = msg.getFieldAsString(NXCPCodes.VID_INSTD_DATA);
+      instanceDiscoveryFilter = msg.getFieldAsString(NXCPCodes.VID_INSTD_FILTER);      
        }
 
        /**
@@ -149,6 +166,7 @@ public abstract class DataCollectionObject
                snmpPort = 0;
                schedules = new ArrayList<String>(0);
                comments = "";
+      instance = "";
        }
        
        /**
@@ -181,6 +199,13 @@ public abstract class DataCollectionObject
                {
                        msg.setField(varId++, schedules.get(i));
                }
+               
+      msg.setField(NXCPCodes.VID_INSTANCE, instance);
+      msg.setFieldInt16(NXCPCodes.VID_INSTD_METHOD, instanceDiscoveryMethod);
+      if (instanceDiscoveryData != null)
+         msg.setField(NXCPCodes.VID_INSTD_DATA, instanceDiscoveryData);
+      if (instanceDiscoveryFilter != null)
+         msg.setField(NXCPCodes.VID_INSTD_FILTER, instanceDiscoveryFilter);
        }
 
        /**
@@ -613,4 +638,68 @@ public abstract class DataCollectionObject
    {
       this.id = id;
    }
+   
+   /**
+    * @return the instance
+    */
+   public String getInstance()
+   {
+      return instance;
+   }
+
+   /**
+    * @param instance the instance to set
+    */
+   public void setInstance(String instance)
+   {
+      this.instance = instance;
+   }
+   
+   /**
+    * @return the instanceDiscoveryMethod
+    */
+   public final int getInstanceDiscoveryMethod()
+   {
+      return instanceDiscoveryMethod;
+   }
+
+   /**
+    * @param instanceDiscoveryMethod the instanceDiscoveryMethod to set
+    */
+   public final void setInstanceDiscoveryMethod(int instanceDiscoveryMethod)
+   {
+      this.instanceDiscoveryMethod = instanceDiscoveryMethod;
+   }
+
+   /**
+    * @return the instanceDiscoveryData
+    */
+   public final String getInstanceDiscoveryData()
+   {
+      return instanceDiscoveryData;
+   }
+
+   /**
+    * @param instanceDiscoveryData the instanceDiscoveryData to set
+    */
+   public final void setInstanceDiscoveryData(String instanceDiscoveryData)
+   {
+      this.instanceDiscoveryData = instanceDiscoveryData;
+   }
+
+   /**
+    * @return the instanceDiscoveryFilter
+    */
+   public final String getInstanceDiscoveryFilter()
+   {
+      return instanceDiscoveryFilter;
+   }
+
+   /**
+    * @param instanceDiscoveryFilter the instanceDiscoveryFilter to set
+    */
+   public final void setInstanceDiscoveryFilter(String instanceDiscoveryFilter)
+   {
+      this.instanceDiscoveryFilter = instanceDiscoveryFilter;
+   }
 }
index 63fbf83..c0bf43e 100644 (file)
@@ -28,6 +28,14 @@ import org.netxms.base.NXCPMessage;
  */
 public class DataCollectionTable extends DataCollectionObject
 {
+   // Instance discovery methods
+   public static final int IDM_NONE = 0;
+   public static final int IDM_AGENT_LIST = 1;
+   public static final int IDM_AGENT_TABLE = 2;
+   public static final int IDM_SNMP_WALK_VALUES = 3;
+   public static final int IDM_SNMP_WALK_OIDS = 4;
+   public static final int IDM_SCRIPT = 5;
+   
        private String instanceColumn;
        private List<ColumnDefinition> columns;
        private List<TableThreshold> thresholds;
index bba9d98..b1f8eca 100644 (file)
               name="%page.name.InstanceDiscovery">
            <enabledWhen>
               <instanceof
-                    value="org.netxms.client.datacollection.DataCollectionItem">
+                    value="org.netxms.client.datacollection.DataCollectionObject">
               </instanceof>
            </enabledWhen>
         </page>
index c44d634..7d67eda 100644 (file)
@@ -27,8 +27,9 @@ import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Combo;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
-import org.netxms.client.datacollection.DataCollectionItem;
+import org.netxms.client.datacollection.DataCollectionObject;
 import org.netxms.ui.eclipse.datacollection.Messages;
+import org.netxms.ui.eclipse.datacollection.api.DataCollectionObjectEditor;
 import org.netxms.ui.eclipse.datacollection.propertypages.helpers.DCIPropertyPageDialog;
 import org.netxms.ui.eclipse.nxsl.widgets.ScriptEditor;
 import org.netxms.ui.eclipse.tools.WidgetFactory;
@@ -36,14 +37,15 @@ import org.netxms.ui.eclipse.tools.WidgetHelper;
 import org.netxms.ui.eclipse.widgets.LabeledText;
 
 /**
- * "Instance Discovery" property page for DCI
+ * "Instance Discovery" property page for DCO
  */
 public class InstanceDiscovery extends DCIPropertyPageDialog
 {
        private static final String[] DCI_FUNCTIONS = { "FindDCIByName", "FindDCIByDescription", "GetDCIObject", "GetDCIValue", "GetDCIValueByDescription", "GetDCIValueByName" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
        private static final String[] DCI_VARIABLES = { "$dci", "$node" }; //$NON-NLS-1$ //$NON-NLS-2$
        
-       private DataCollectionItem dci;
+       private DataCollectionObjectEditor editor;
+       private DataCollectionObject dco;
        private Combo discoveryMethod;
        private LabeledText discoveryData;
        private ScriptEditor filterScript;
@@ -55,7 +57,8 @@ public class InstanceDiscovery extends DCIPropertyPageDialog
        protected Control createContents(Composite parent)
        {
           Composite dialogArea = (Composite)super.createContents(parent);
-               dci = editor.getObjectAsItem();
+               editor = (DataCollectionObjectEditor)getElement().getAdapter(DataCollectionObjectEditor.class);
+               dco = editor.getObject();
                
                GridLayout layout = new GridLayout();
                layout.verticalSpacing = WidgetHelper.OUTER_SPACING;
@@ -71,15 +74,15 @@ public class InstanceDiscovery extends DCIPropertyPageDialog
       discoveryMethod.add(Messages.get().InstanceDiscovery_SnmpWalkValues);
       discoveryMethod.add(Messages.get().InstanceDiscovery_SnmpWalkOids);
       discoveryMethod.add(Messages.get().InstanceDiscovery_Script);
-      discoveryMethod.select(dci.getInstanceDiscoveryMethod());
+      discoveryMethod.select(dco.getInstanceDiscoveryMethod());
       discoveryMethod.addSelectionListener(new SelectionListener() {
                        @Override
                        public void widgetSelected(SelectionEvent e)
                        {
                                int method = discoveryMethod.getSelectionIndex();
                      discoveryData.setLabel(getDataLabel(method));
-                     discoveryData.setEnabled(method != DataCollectionItem.IDM_NONE);
-                     filterScript.setEnabled(method != DataCollectionItem.IDM_NONE);
+                     discoveryData.setEnabled(method != DataCollectionObject.IDM_NONE);
+                     filterScript.setEnabled(method != DataCollectionObject.IDM_NONE);
                        }
                        
                        @Override
@@ -90,13 +93,13 @@ public class InstanceDiscovery extends DCIPropertyPageDialog
                });
       
       discoveryData = new LabeledText(dialogArea, SWT.NONE);
-      discoveryData.setLabel(getDataLabel(dci.getInstanceDiscoveryMethod()));
-      discoveryData.setText(dci.getInstanceDiscoveryData());
+      discoveryData.setLabel(getDataLabel(dco.getInstanceDiscoveryMethod()));
+      discoveryData.setText(dco.getInstanceDiscoveryData());
       GridData gd = new GridData();
       gd.horizontalAlignment = SWT.FILL;
       gd.grabExcessHorizontalSpace = true;
       discoveryData.setLayoutData(gd);
-      discoveryData.setEnabled(dci.getInstanceDiscoveryMethod() != DataCollectionItem.IDM_NONE);
+      discoveryData.setEnabled(dco.getInstanceDiscoveryMethod() != DataCollectionObject.IDM_NONE);
      
       gd = new GridData();
       gd.horizontalAlignment = SWT.FILL;
@@ -123,8 +126,8 @@ public class InstanceDiscovery extends DCIPropertyPageDialog
       gd.grabExcessHorizontalSpace = true;
       gd.grabExcessVerticalSpace = true;
       filterScript.setLayoutData(gd);
-      filterScript.setText(dci.getInstanceDiscoveryFilter());
-      filterScript.setEnabled(dci.getInstanceDiscoveryMethod() != DataCollectionItem.IDM_NONE);
+      filterScript.setText(dco.getInstanceDiscoveryFilter());
+      filterScript.setEnabled(dco.getInstanceDiscoveryMethod() != DataCollectionObject.IDM_NONE);
       
                return dialogArea;
        }
@@ -139,14 +142,14 @@ public class InstanceDiscovery extends DCIPropertyPageDialog
        {
                switch(method)
                {
-                       case DataCollectionItem.IDM_NONE:
+                       case DataCollectionObject.IDM_NONE:
                                return Messages.get().InstanceDiscovery_DiscoveryData;
-                       case DataCollectionItem.IDM_AGENT_LIST:
+                       case DataCollectionObject.IDM_AGENT_LIST:
                                return Messages.get().InstanceDiscovery_ListName;
-                       case DataCollectionItem.IDM_AGENT_TABLE:
+                       case DataCollectionObject.IDM_AGENT_TABLE:
                                return Messages.get().InstanceDiscovery_TableName;
-                       case DataCollectionItem.IDM_SNMP_WALK_VALUES:
-                       case DataCollectionItem.IDM_SNMP_WALK_OIDS:
+                       case DataCollectionObject.IDM_SNMP_WALK_VALUES:
+                       case DataCollectionObject.IDM_SNMP_WALK_OIDS:
                                return Messages.get().InstanceDiscovery_BaseOid;
                }
                return ""; //$NON-NLS-1$
@@ -159,9 +162,9 @@ public class InstanceDiscovery extends DCIPropertyPageDialog
         */
        protected void applyChanges(final boolean isApply)
        {
-               dci.setInstanceDiscoveryMethod(discoveryMethod.getSelectionIndex());
-               dci.setInstanceDiscoveryData(discoveryData.getText());
-               dci.setInstanceDiscoveryFilter(filterScript.getText());
+          dco.setInstanceDiscoveryMethod(discoveryMethod.getSelectionIndex());
+          dco.setInstanceDiscoveryData(discoveryData.getText());
+          dco.setInstanceDiscoveryFilter(filterScript.getText());
                editor.modify();
        }
 
@@ -191,8 +194,8 @@ public class InstanceDiscovery extends DCIPropertyPageDialog
        protected void performDefaults()
        {
                super.performDefaults();
-               discoveryMethod.select(DataCollectionItem.IDM_NONE);
-               discoveryData.setLabel(getDataLabel(DataCollectionItem.IDM_NONE));
+               discoveryMethod.select(DataCollectionObject.IDM_NONE);
+               discoveryData.setLabel(getDataLabel(DataCollectionObject.IDM_NONE));
                discoveryData.setText(""); //$NON-NLS-1$
                discoveryData.setEnabled(false);
                filterScript.setText(""); //$NON-NLS-1$
index 4ddead3..978b98e 100644 (file)
@@ -46,7 +46,6 @@ DCItem::DCItem() : DCObject()
    m_dataType = DCI_DT_INT;
    m_deltaCalculation = DCM_ORIGINAL_VALUE;
        m_sampleCount = 0;
-   m_instance[0] = 0;
    m_cacheSize = 0;
    m_requiredCacheSize = 0;
    m_ppValueCache = NULL;
@@ -56,10 +55,6 @@ DCItem::DCItem() : DCObject()
        m_nMultiplier = 1;
        m_customUnitName = NULL;
        m_snmpRawValueType = SNMP_RAWTYPE_NONE;
-       m_instanceDiscoveryMethod = IDM_NONE;
-       m_instanceDiscoveryData = NULL;
-       m_instanceFilterSource = NULL;
-       m_instanceFilter = NULL;
        m_predictionEngine[0] = 0;
 }
 
@@ -71,7 +66,6 @@ DCItem::DCItem(const DCItem *pSrc) : DCObject(pSrc)
    m_dataType = pSrc->m_dataType;
    m_deltaCalculation = pSrc->m_deltaCalculation;
        m_sampleCount = pSrc->m_sampleCount;
-       _tcscpy(m_instance, pSrc->m_instance);
    m_cacheSize = 0;
    m_requiredCacheSize = 0;
    m_ppValueCache = NULL;
@@ -81,11 +75,6 @@ DCItem::DCItem(const DCItem *pSrc) : DCObject(pSrc)
        m_nMultiplier = pSrc->m_nMultiplier;
        m_customUnitName = (pSrc->m_customUnitName != NULL) ? _tcsdup(pSrc->m_customUnitName) : NULL;
        m_snmpRawValueType = pSrc->m_snmpRawValueType;
-       m_instanceDiscoveryMethod = pSrc->m_instanceDiscoveryMethod;
-       m_instanceDiscoveryData = (pSrc->m_instanceDiscoveryData != NULL) ? _tcsdup(pSrc->m_instanceDiscoveryData) : NULL;
-       m_instanceFilterSource = NULL;
-       m_instanceFilter = NULL;
-   setInstanceFilter(pSrc->m_instanceFilterSource);
    _tcscpy(m_predictionEngine, pSrc->m_predictionEngine);
 
    // Copy thresholds
@@ -187,7 +176,6 @@ DCItem::DCItem(UINT32 dwId, const TCHAR *szName, int iSource, int iDataType,
                const TCHAR *pszDescription, const TCHAR *systemTag)
        : DCObject(dwId, szName, iSource, iPollingInterval, iRetentionTime, pNode, pszDescription, systemTag)
 {
-   m_instance[0] = 0;
    m_dataType = iDataType;
    m_deltaCalculation = DCM_ORIGINAL_VALUE;
        m_sampleCount = 0;
@@ -201,10 +189,6 @@ DCItem::DCItem(UINT32 dwId, const TCHAR *szName, int iSource, int iDataType,
        m_nMultiplier = 1;
        m_customUnitName = NULL;
        m_snmpRawValueType = SNMP_RAWTYPE_NONE;
-       m_instanceDiscoveryMethod = IDM_NONE;
-       m_instanceDiscoveryData = NULL;
-       m_instanceFilterSource = NULL;
-       m_instanceFilter = NULL;
        m_predictionEngine[0] = 0;
 
    updateCacheSizeInternal();
@@ -215,7 +199,6 @@ DCItem::DCItem(UINT32 dwId, const TCHAR *szName, int iSource, int iDataType,
  */
 DCItem::DCItem(ConfigEntry *config, Template *owner) : DCObject(config, owner)
 {
-   nx_strncpy(m_instance, config->getSubEntryValue(_T("instance"), 0, _T("")), MAX_DB_STRING);
    m_dataType = (BYTE)config->getSubEntryValueAsInt(_T("dataType"));
    m_deltaCalculation = (BYTE)config->getSubEntryValueAsInt(_T("delta"));
    m_sampleCount = (BYTE)config->getSubEntryValueAsInt(_T("samples"));
@@ -228,12 +211,6 @@ DCItem::DCItem(ConfigEntry *config, Template *owner) : DCObject(config, owner)
        m_nMultiplier = 1;
        m_customUnitName = NULL;
        m_snmpRawValueType = (WORD)config->getSubEntryValueAsInt(_T("snmpRawValueType"));
-       m_instanceDiscoveryMethod = (WORD)config->getSubEntryValueAsInt(_T("instanceDiscoveryMethod"));
-       const TCHAR *value = config->getSubEntryValue(_T("instanceDiscoveryData"));
-       m_instanceDiscoveryData = (value != NULL) ? _tcsdup(value) : NULL;
-       m_instanceFilterSource = NULL;
-       m_instanceFilter = NULL;
-       setInstanceFilter(config->getSubEntryValue(_T("instanceFilter")));
    nx_strncpy(m_predictionEngine, config->getSubEntryValue(_T("predictionEngine"), 0, _T("")), MAX_NPE_NAME_LEN);
 
    // for compatibility with old format
@@ -267,9 +244,6 @@ DCItem::DCItem(ConfigEntry *config, Template *owner) : DCObject(config, owner)
 DCItem::~DCItem()
 {
        delete m_thresholds;
-       free(m_instanceDiscoveryData);
-       free(m_instanceFilterSource);
-       delete m_instanceFilter;
        free(m_customUnitName);
    clearCache();
 }
@@ -537,7 +511,6 @@ void DCItem::createMessage(NXCPMessage *pMsg)
        DCObject::createMessage(pMsg);
 
    lock();
-   pMsg->setField(VID_INSTANCE, m_instance);
    pMsg->setField(VID_DCI_DATA_TYPE, (WORD)m_dataType);
    pMsg->setField(VID_DCI_DELTA_CALCULATION, (WORD)m_deltaCalculation);
    pMsg->setField(VID_SAMPLE_COUNT, (WORD)m_sampleCount);
@@ -545,11 +518,6 @@ void DCItem::createMessage(NXCPMessage *pMsg)
        pMsg->setField(VID_MULTIPLIER, (UINT32)m_nMultiplier);
        pMsg->setField(VID_SNMP_RAW_VALUE_TYPE, m_snmpRawValueType);
        pMsg->setField(VID_NPE_NAME, m_predictionEngine);
-       pMsg->setField(VID_INSTD_METHOD, m_instanceDiscoveryMethod);
-       if (m_instanceDiscoveryData != NULL)
-               pMsg->setField(VID_INSTD_DATA, m_instanceDiscoveryData);
-       if (m_instanceFilterSource != NULL)
-               pMsg->setField(VID_INSTD_FILTER, m_instanceFilterSource);
        if (m_customUnitName != NULL)
                pMsg->setField(VID_CUSTOM_UNITS_NAME, m_customUnitName);
        if (m_thresholds != NULL)
@@ -595,7 +563,6 @@ void DCItem::updateFromMessage(NXCPMessage *pMsg, UINT32 *pdwNumMaps, UINT32 **p
 
    lock();
 
-   pMsg->getFieldAsString(VID_INSTANCE, m_instance, MAX_DB_STRING);
    m_dataType = (BYTE)pMsg->getFieldAsUInt16(VID_DCI_DATA_TYPE);
    m_deltaCalculation = (BYTE)pMsg->getFieldAsUInt16(VID_DCI_DELTA_CALCULATION);
        m_sampleCount = (int)pMsg->getFieldAsUInt16(VID_SAMPLE_COUNT);
@@ -605,14 +572,6 @@ void DCItem::updateFromMessage(NXCPMessage *pMsg, UINT32 *pdwNumMaps, UINT32 **p
        m_customUnitName = pMsg->getFieldAsString(VID_CUSTOM_UNITS_NAME);
        m_snmpRawValueType = pMsg->getFieldAsUInt16(VID_SNMP_RAW_VALUE_TYPE);
    pMsg->getFieldAsString(VID_NPE_NAME, m_predictionEngine, MAX_NPE_NAME_LEN);
-       m_instanceDiscoveryMethod = pMsg->getFieldAsUInt16(VID_INSTD_METHOD);
-
-       safe_free(m_instanceDiscoveryData);
-       m_instanceDiscoveryData = pMsg->getFieldAsString(VID_INSTD_DATA);
-
-   TCHAR *pszStr = pMsg->getFieldAsString(VID_INSTD_FILTER);
-       setInstanceFilter(pszStr);
-   safe_free(pszStr);
 
    // Update thresholds
    UINT32 dwNum = pMsg->getFieldAsUInt32(VID_NUM_THRESHOLDS);
@@ -1034,9 +993,6 @@ void DCItem::changeBinding(UINT32 dwNewId, Template *pNewNode, BOOL doMacroExpan
          m_thresholds->get(i)->bindToItem(m_id, m_owner->getId());
        }
 
-       if (doMacroExpansion)
-               expandMacros(m_instance, m_instance, MAX_DB_STRING);
-
    clearCache();
    updateCacheSizeInternal();
    unlock();
@@ -1515,60 +1471,10 @@ void DCItem::updateFromTemplate(DCObject *src)
    for(i = 0; i < getThresholdCount(); i++)
       m_thresholds->get(i)->setDataType(m_dataType);
 
-   if ((item->getInstanceDiscoveryMethod() != IDM_NONE) && (m_instanceDiscoveryMethod == IDM_NONE))
-   {
-      expandInstance();
-   }
-   else
-   {
-      expandMacros(item->m_instance, m_instance, MAX_DB_STRING);
-      m_instanceDiscoveryMethod = item->m_instanceDiscoveryMethod;
-      safe_free(m_instanceDiscoveryData);
-          m_instanceDiscoveryData = _tcsdup_ex(item->m_instanceDiscoveryData);
-      safe_free_and_null(m_instanceFilterSource);
-      delete_and_null(m_instanceFilter);
-      setInstanceFilter(item->m_instanceFilterSource);
-   }
-
    updateCacheSizeInternal();
    unlock();
 }
 
-/**
- * Set new instance discovery filter script
- */
-void DCItem::setInstanceFilter(const TCHAR *pszScript)
-{
-       safe_free(m_instanceFilterSource);
-       delete m_instanceFilter;
-   if (pszScript != NULL)
-   {
-      m_instanceFilterSource = _tcsdup(pszScript);
-      StrStrip(m_instanceFilterSource);
-      if (m_instanceFilterSource[0] != 0)
-      {
-         TCHAR errorText[1024];
-         m_instanceFilter = NXSLCompile(m_instanceFilterSource, errorText, 1024, NULL);
-         if (m_instanceFilter == NULL)
-         {
-            // node can be NULL if this DCI was just created from template
-            // in this case compilation error will be reported on template level anyway
-            if (m_owner != NULL)
-               nxlog_write(MSG_INSTANCE_FILTER_SCRIPT_COMPILATION_ERROR, NXLOG_WARNING, "dsdss", m_owner->getId(), m_owner->getName(), m_id, m_name, errorText);
-         }
-      }
-      else
-      {
-         m_instanceFilter = NULL;
-      }
-   }
-   else
-   {
-      m_instanceFilterSource = NULL;
-      m_instanceFilter = NULL;
-   }
-}
-
 /**
  * Get list of used events
  */
@@ -1825,177 +1731,17 @@ bool DCItem::isCacheLoaded()
 }
 
 /**
- * Should return true if object has (or can have) value
- */
-bool DCItem::hasValue()
-{
-   if ((m_owner != NULL) && (m_owner->getObjectClass() == OBJECT_CLUSTER))
-      return isAggregateOnCluster() && (m_instanceDiscoveryMethod == IDM_NONE);
-       return m_instanceDiscoveryMethod == IDM_NONE;
-}
-
-/**
- * Expand {instance} macro in name and description
- */
-void DCItem::expandInstance()
-{
-       String temp = m_name;
-   temp.replace(_T("{instance}"), m_instanceDiscoveryData);
-       temp.replace(_T("{instance-name}"), m_instance);
-       nx_strncpy(m_name, (const TCHAR *)temp, MAX_ITEM_NAME);
-
-       temp = m_description;
-   temp.replace(_T("{instance}"), m_instanceDiscoveryData);
-       temp.replace(_T("{instance-name}"), m_instance);
-       nx_strncpy(m_description, (const TCHAR *)temp, MAX_DB_STRING);
-}
-
-/**
- * Filter callback data
- */
-struct FilterCallbackData
-{
-   StringMap *filteredInstances;
-   DCItem *dci;
-   NXSL_VM *instanceFilter;
-};
-
-/**
- * Callback for filtering instances
- */
-static EnumerationCallbackResult FilterCallback(const TCHAR *key, const void *value, void *data)
-{
-   NXSL_VM *instanceFilter = ((FilterCallbackData *)data)->instanceFilter;
-   DCItem *dci = ((FilterCallbackData *)data)->dci;
-
-   instanceFilter->setGlobalVariable(_T("$node"), dci->getOwner()->createNXSLObject());
-   instanceFilter->setGlobalVariable(_T("$dci"), dci->createNXSLObject());
-
-   NXSL_Value *argv[2];
-   argv[0] = new NXSL_Value(key);
-   argv[1] = new NXSL_Value((const TCHAR *)value);
-
-   if (instanceFilter->run(2, argv))
-   {
-      bool accepted;
-      const TCHAR *instance = key;
-      const TCHAR *name = (const TCHAR *)value;
-      NXSL_Value *result = instanceFilter->getResult();
-      if (result != NULL)
-      {
-         if (result->isArray())
-         {
-            NXSL_Array *array = result->getValueAsArray();
-            if (array->size() > 0)
-            {
-               accepted = array->get(0)->getValueAsInt32() ? true : false;
-               if (accepted && (array->size() > 1))
-               {
-                  // transformed value
-                  const TCHAR *newValue = array->get(1)->getValueAsCString();
-                  if ((newValue != NULL) && (*newValue != 0))
-                  {
-                     DbgPrintf(5, _T("DCItem::filterInstanceList(%s [%d]): instance \"%s\" replaced by \"%s\""),
-                               dci->getName(), dci->getId(), instance, newValue);
-                     instance = newValue;
-                  }
-
-                  if (array->size() > 2)
-                  {
-                     // instance name
-                     const TCHAR *newName = array->get(2)->getValueAsCString();
-                     if ((newName != NULL) && (*newName != 0))
-                     {
-                        DbgPrintf(5, _T("DCItem::filterInstanceList(%s [%d]): instance \"%s\" name set to \"%s\""),
-                                  dci->getName(), dci->getId(), instance, newName);
-                        name = newName;
-                     }
-                  }
-               }
-            }
-            else
-            {
-               accepted = true;
-            }
-         }
-         else
-         {
-            accepted = result->getValueAsInt32() ? true : false;
-         }
-      }
-      else
-      {
-         accepted = true;
-      }
-               if (accepted)
-      {
-         ((FilterCallbackData *)data)->filteredInstances->set(instance, name);
-      }
-      else
-               {
-                       DbgPrintf(5, _T("DCItem::filterInstanceList(%s [%d]): instance \"%s\" removed by filtering script"),
-                   dci->getName(), dci->getId(), key);
-               }
-   }
-   else
-   {
-      TCHAR szBuffer[1024];
-               _sntprintf(szBuffer, 1024, _T("DCI::%s::%d::InstanceFilter"), dci->getOwnerName(), dci->getId());
-      PostDciEvent(EVENT_SCRIPT_ERROR, g_dwMgmtNode, dci->getId(), "ssd", szBuffer, instanceFilter->getErrorText(), dci->getId());
-      ((FilterCallbackData *)data)->filteredInstances->set(key, (const TCHAR *)value);
-   }
-   return _CONTINUE;
-}
-
-/**
- * Filter instance list
- */
-void DCItem::filterInstanceList(StringMap *instances)
-{
-   lock();
-   if (m_instanceFilter == NULL)
-   {
-      unlock();
-               return;
-   }
-
-   FilterCallbackData data;
-   data.instanceFilter = new NXSL_VM(new NXSL_ServerEnv());
-   if (!data.instanceFilter->load(m_instanceFilter))
-   {
-      TCHAR szBuffer[1024];
-      _sntprintf(szBuffer, 1024, _T("DCI::%s::%d::InstanceFilter"), getOwnerName(), m_id);
-      PostDciEvent(EVENT_SCRIPT_ERROR, g_dwMgmtNode, m_id, "ssd", szBuffer, data.instanceFilter->getErrorText(), m_id);
-   }
-   unlock();
-
-   StringMap filteredInstances;
-   data.filteredInstances = &filteredInstances;
-   data.dci = this;
-   instances->forEach(FilterCallback, &data);
-   instances->clear();
-   instances->addAll(&filteredInstances);
-   delete data.instanceFilter;
-}
-
-/**
- * Create DCObject from import file
+ * Create DCI from import file
  */
 void DCItem::updateFromImport(ConfigEntry *config)
 {
    DCObject::updateFromImport(config);
 
    lock();
-   nx_strncpy(m_instance, config->getSubEntryValue(_T("instance"), 0, _T("")), MAX_DB_STRING);
    m_dataType = (BYTE)config->getSubEntryValueAsInt(_T("dataType"));
    m_deltaCalculation = (BYTE)config->getSubEntryValueAsInt(_T("delta"));
    m_sampleCount = (BYTE)config->getSubEntryValueAsInt(_T("samples"));
    m_snmpRawValueType = (WORD)config->getSubEntryValueAsInt(_T("snmpRawValueType"));
-   m_instanceDiscoveryMethod = (WORD)config->getSubEntryValueAsInt(_T("instanceDiscoveryMethod"));
-   const TCHAR *value = config->getSubEntryValue(_T("instanceDiscoveryData"));
-   safe_free(m_instanceDiscoveryData);
-   m_instanceDiscoveryData = _tcsdup_ex(value);
-   setInstanceFilter(config->getSubEntryValue(_T("instanceFilter")));
 
    ConfigEntry *thresholdsRoot = config->findEntry(_T("thresholds"));
    if (thresholdsRoot != NULL)
@@ -2019,3 +1765,11 @@ void DCItem::updateFromImport(ConfigEntry *config)
    updateCacheSizeInternal();
    unlock();
 }
+
+/*
+ * Clone DCI
+ */
+DCObject *DCItem::clone()
+{
+   return new DCItem(this);
+}
index 698cef1..9322903 100644 (file)
@@ -65,6 +65,11 @@ DCObject::DCObject()
    m_transformationScript = NULL;
    m_comments = NULL;
    m_pollingSession = NULL;
+   m_instanceDiscoveryMethod = IDM_NONE;
+   m_instanceDiscoveryData = NULL;
+   m_instanceFilterSource = NULL;
+   m_instanceFilter = NULL;
+   m_instance[0] = 0;
 }
 
 /**
@@ -103,6 +108,13 @@ DCObject::DCObject(const DCObject *pSrc)
    setTransformationScript(pSrc->m_transformationScriptSource);
 
    m_schedules = (pSrc->m_schedules != NULL) ? new StringList(pSrc->m_schedules) : NULL;
+
+   m_instanceDiscoveryMethod = pSrc->m_instanceDiscoveryMethod;
+   m_instanceDiscoveryData = (pSrc->m_instanceDiscoveryData != NULL) ? _tcsdup(pSrc->m_instanceDiscoveryData) : NULL;
+   m_instanceFilterSource = NULL;
+   m_instanceFilter = NULL;
+   setInstanceFilter(pSrc->m_instanceFilterSource);
+   _tcscpy(m_instance, pSrc->m_instance);
 }
 
 /**
@@ -143,6 +155,11 @@ DCObject::DCObject(UINT32 dwId, const TCHAR *szName, int iSource,
    m_transformationScript = NULL;
    m_comments = NULL;
    m_pollingSession = NULL;
+   m_instanceDiscoveryMethod = IDM_NONE;
+   m_instanceDiscoveryData = NULL;
+   m_instanceFilterSource = NULL;
+   m_instanceFilter = NULL;
+   m_instance[0] = 0;
 }
 
 /**
@@ -200,6 +217,14 @@ DCObject::DCObject(ConfigEntry *config, Template *owner)
          m_schedules->add(schedules->getValue(i));
       }
        }
+
+   m_instanceDiscoveryMethod = (WORD)config->getSubEntryValueAsInt(_T("instanceDiscoveryMethod"));
+   const TCHAR *value = config->getSubEntryValue(_T("instanceDiscoveryData"));
+   m_instanceDiscoveryData = (value != NULL) ? _tcsdup(value) : NULL;
+   m_instanceFilterSource = NULL;
+   m_instanceFilter = NULL;
+   setInstanceFilter(config->getSubEntryValue(_T("instanceFilter")));
+   nx_strncpy(m_instance, config->getSubEntryValue(_T("instance"), 0, _T("")), MAX_DB_STRING);
 }
 
 /**
@@ -213,6 +238,9 @@ DCObject::~DCObject()
        safe_free(m_pszPerfTabSettings);
        safe_free(m_comments);
    MutexDestroy(m_hMutex);
+   free(m_instanceDiscoveryData);
+   free(m_instanceFilterSource);
+   delete m_instanceFilter;
 }
 
 /**
@@ -334,11 +362,11 @@ void DCObject::expandMacros(const TCHAR *src, TCHAR *dst, size_t dstLen)
                                        NXSL_Value *result = vm->getResult();
                                        if (result != NULL)
                                                temp += CHECK_NULL_EX(result->getValueAsCString());
-                        DbgPrintf(4, _T("DCItem::expandMacros(%d,\"%s\"): Script %s executed successfully"), m_id, src, &macro[7]);
+                        DbgPrintf(4, _T("DCObject::expandMacros(%d,\"%s\"): Script %s executed successfully"), m_id, src, &macro[7]);
                                }
                                else
                                {
-                        DbgPrintf(4, _T("DCItem::expandMacros(%d,\"%s\"): Script %s execution error: %s"),
+                        DbgPrintf(4, _T("DCObject::expandMacros(%d,\"%s\"): Script %s execution error: %s"),
                                                  m_id, src, &macro[7], vm->getErrorText());
                                        PostEvent(EVENT_SCRIPT_ERROR, g_dwMgmtNode, "ssd", &macro[7], vm->getErrorText(), m_id);
                                }
@@ -346,7 +374,7 @@ void DCObject::expandMacros(const TCHAR *src, TCHAR *dst, size_t dstLen)
                        }
                        else
                        {
-                DbgPrintf(4, _T("DCItem::expandMacros(%d,\"%s\"): Cannot find script %s"), m_id, src, &macro[7]);
+                DbgPrintf(4, _T("DCObject::expandMacros(%d,\"%s\"): Cannot find script %s"), m_id, src, &macro[7]);
                        }
                }
                temp += rest;
@@ -400,6 +428,7 @@ void DCObject::changeBinding(UINT32 dwNewId, Template *newOwner, BOOL doMacroExp
        {
                expandMacros(m_name, m_name, MAX_ITEM_NAME);
                expandMacros(m_description, m_description, MAX_DB_STRING);
+      expandMacros(m_instance, m_instance, MAX_DB_STRING);
        }
 
    unlock();
@@ -669,6 +698,12 @@ void DCObject::createMessage(NXCPMessage *pMsg)
        {
       pMsg->setField(VID_NUM_SCHEDULES, (UINT32)0);
        }
+   pMsg->setField(VID_INSTD_METHOD, m_instanceDiscoveryMethod);
+   if (m_instanceDiscoveryData != NULL)
+      pMsg->setField(VID_INSTD_DATA, m_instanceDiscoveryData);
+   if (m_instanceFilterSource != NULL)
+      pMsg->setField(VID_INSTD_FILTER, m_instanceFilterSource);
+   pMsg->setField(VID_INSTANCE, m_instance);
    unlock();
 }
 
@@ -722,6 +757,16 @@ void DCObject::updateFromMessage(NXCPMessage *pMsg)
       delete_and_null(m_schedules);
    }
 
+   m_instanceDiscoveryMethod = pMsg->getFieldAsUInt16(VID_INSTD_METHOD);
+
+   safe_free(m_instanceDiscoveryData);
+   m_instanceDiscoveryData = pMsg->getFieldAsString(VID_INSTD_DATA);
+
+   pszStr = pMsg->getFieldAsString(VID_INSTD_FILTER);
+   setInstanceFilter(pszStr);
+   safe_free(pszStr);
+   pMsg->getFieldAsString(VID_INSTANCE, m_instance, MAX_DB_STRING);
+
        unlock();
 }
 
@@ -772,6 +817,22 @@ bool DCObject::loadThresholdsFromDB(DB_HANDLE hdb)
        return true;
 }
 
+/**
+ * Expand {instance} macro in name and description
+ */
+void DCObject::expandInstance()
+{
+   String temp = m_name;
+   temp.replace(_T("{instance}"), m_instanceDiscoveryData);
+   temp.replace(_T("{instance-name}"), m_instance);
+   nx_strncpy(m_name, (const TCHAR *)temp, MAX_ITEM_NAME);
+
+   temp = m_description;
+   temp.replace(_T("{instance}"), m_instanceDiscoveryData);
+   temp.replace(_T("{instance-name}"), m_instance);
+   nx_strncpy(m_description, (const TCHAR *)temp, MAX_DB_STRING);
+}
+
 /**
  * Update DC object from template object
  */
@@ -801,6 +862,21 @@ void DCObject::updateFromTemplate(DCObject *src)
    delete m_schedules;
    m_schedules = (src->m_schedules != NULL) ? new StringList(src->m_schedules) : NULL;
 
+   if ((src->getInstanceDiscoveryMethod() != IDM_NONE) && (m_instanceDiscoveryMethod == IDM_NONE))
+   {
+      expandInstance();
+   }
+   else
+   {
+      expandMacros(src->m_instance, m_instance, MAX_DB_STRING);
+      m_instanceDiscoveryMethod = src->m_instanceDiscoveryMethod;
+      safe_free(m_instanceDiscoveryData);
+      m_instanceDiscoveryData = _tcsdup_ex(src->m_instanceDiscoveryData);
+      safe_free_and_null(m_instanceFilterSource);
+      delete_and_null(m_instanceFilter);
+      setInstanceFilter(src->m_instanceFilterSource);
+   }
+
        unlock();
 }
 
@@ -837,7 +913,9 @@ void DCObject::processNewError(bool noInstance, time_t now)
  */
 bool DCObject::hasValue()
 {
-       return true;
+   if ((m_owner != NULL) && (m_owner->getObjectClass() == OBJECT_CLUSTER))
+      return isAggregateOnCluster() && (m_instanceDiscoveryMethod == IDM_NONE);
+   return m_instanceDiscoveryMethod == IDM_NONE;
 }
 
 /**
@@ -949,6 +1027,14 @@ void DCObject::updateFromImport(ConfigEntry *config)
    {
       delete_and_null(m_schedules);
    }
+
+   m_instanceDiscoveryMethod = (WORD)config->getSubEntryValueAsInt(_T("instanceDiscoveryMethod"));
+   const TCHAR *value = config->getSubEntryValue(_T("instanceDiscoveryData"));
+   safe_free(m_instanceDiscoveryData);
+   m_instanceDiscoveryData = _tcsdup_ex(value);
+   setInstanceFilter(config->getSubEntryValue(_T("instanceFilter")));
+   nx_strncpy(m_instance, config->getSubEntryValue(_T("instance"), 0, _T("")), MAX_DB_STRING);
+
    unlock();
 }
 
@@ -1001,6 +1087,170 @@ void DCObject::requestForcePoll(ClientSession *session)
    unlock();
 }
 
+/**
+ * Filter callback data
+ */
+struct FilterCallbackData
+{
+   StringMap *filteredInstances;
+   DCObject *dco;
+   NXSL_VM *instanceFilter;
+};
+
+/**
+ * Callback for filtering instances
+ */
+static EnumerationCallbackResult FilterCallback(const TCHAR *key, const void *value, void *data)
+{
+   NXSL_VM *instanceFilter = ((FilterCallbackData *)data)->instanceFilter;
+   DCObject *dco = ((FilterCallbackData *)data)->dco;
+
+   instanceFilter->setGlobalVariable(_T("$node"), dco->getOwner()->createNXSLObject());
+   instanceFilter->setGlobalVariable(_T("$dci"), dco->createNXSLObject());
+
+   NXSL_Value *argv[2];
+   argv[0] = new NXSL_Value(key);
+   argv[1] = new NXSL_Value((const TCHAR *)value);
+
+   if (instanceFilter->run(2, argv))
+   {
+      bool accepted;
+      const TCHAR *instance = key;
+      const TCHAR *name = (const TCHAR *)value;
+      NXSL_Value *result = instanceFilter->getResult();
+      if (result != NULL)
+      {
+         if (result->isArray())
+         {
+            NXSL_Array *array = result->getValueAsArray();
+            if (array->size() > 0)
+            {
+               accepted = array->get(0)->getValueAsInt32() ? true : false;
+               if (accepted && (array->size() > 1))
+               {
+                  // transformed value
+                  const TCHAR *newValue = array->get(1)->getValueAsCString();
+                  if ((newValue != NULL) && (*newValue != 0))
+                  {
+                     DbgPrintf(5, _T("DCObject::filterInstanceList(%s [%d]): instance \"%s\" replaced by \"%s\""),
+                              dco->getName(), dco->getId(), instance, newValue);
+                     instance = newValue;
+                  }
+
+                  if (array->size() > 2)
+                  {
+                     // instance name
+                     const TCHAR *newName = array->get(2)->getValueAsCString();
+                     if ((newName != NULL) && (*newName != 0))
+                     {
+                        DbgPrintf(5, _T("DCObject::filterInstanceList(%s [%d]): instance \"%s\" name set to \"%s\""),
+                                 dco->getName(), dco->getId(), instance, newName);
+                        name = newName;
+                     }
+                  }
+               }
+            }
+            else
+            {
+               accepted = true;
+            }
+         }
+         else
+         {
+            accepted = result->getValueAsInt32() ? true : false;
+         }
+      }
+      else
+      {
+         accepted = true;
+      }
+      if (accepted)
+      {
+         ((FilterCallbackData *)data)->filteredInstances->set(instance, name);
+      }
+      else
+      {
+         DbgPrintf(5, _T("DCObject::filterInstanceList(%s [%d]): instance \"%s\" removed by filtering script"),
+                  dco->getName(), dco->getId(), key);
+      }
+   }
+   else
+   {
+      TCHAR szBuffer[1024];
+      _sntprintf(szBuffer, 1024, _T("DCI::%s::%d::InstanceFilter"), dco->getOwnerName(), dco->getId());
+      PostDciEvent(EVENT_SCRIPT_ERROR, g_dwMgmtNode, dco->getId(), "ssd", szBuffer, instanceFilter->getErrorText(), dco->getId());
+      ((FilterCallbackData *)data)->filteredInstances->set(key, (const TCHAR *)value);
+   }
+   return _CONTINUE;
+}
+
+/**
+ * Filter instance list
+ */
+void DCObject::filterInstanceList(StringMap *instances)
+{
+   lock();
+   if (m_instanceFilter == NULL)
+   {
+      unlock();
+      return;
+   }
+
+   FilterCallbackData data;
+   data.instanceFilter = new NXSL_VM(new NXSL_ServerEnv());
+   if (!data.instanceFilter->load(m_instanceFilter))
+   {
+      TCHAR szBuffer[1024];
+      _sntprintf(szBuffer, 1024, _T("DCI::%s::%d::InstanceFilter"), getOwnerName(), m_id);
+      PostDciEvent(EVENT_SCRIPT_ERROR, g_dwMgmtNode, m_id, "ssd", szBuffer, data.instanceFilter->getErrorText(), m_id);
+   }
+   unlock();
+
+   StringMap filteredInstances;
+   data.filteredInstances = &filteredInstances;
+   data.dco = this;
+   instances->forEach(FilterCallback, &data);
+   instances->clear();
+   instances->addAll(&filteredInstances);
+   delete data.instanceFilter;
+}
+
+
+/**
+ * Set new instance discovery filter script
+ */
+void DCObject::setInstanceFilter(const TCHAR *pszScript)
+{
+   safe_free(m_instanceFilterSource);
+   delete m_instanceFilter;
+   if (pszScript != NULL)
+   {
+      m_instanceFilterSource = _tcsdup(pszScript);
+      StrStrip(m_instanceFilterSource);
+      if (m_instanceFilterSource[0] != 0)
+      {
+         TCHAR errorText[1024];
+         m_instanceFilter = NXSLCompile(m_instanceFilterSource, errorText, 1024, NULL);
+         if (m_instanceFilter == NULL)
+         {
+            // node can be NULL if this DCO was just created from template
+            // in this case compilation error will be reported on template level anyway
+            if (m_owner != NULL)
+               nxlog_write(MSG_INSTANCE_FILTER_SCRIPT_COMPILATION_ERROR, NXLOG_WARNING, "dsdss", m_owner->getId(), m_owner->getName(), m_id, m_name, errorText);
+         }
+      }
+      else
+      {
+         m_instanceFilter = NULL;
+      }
+   }
+   else
+   {
+      m_instanceFilterSource = NULL;
+      m_instanceFilter = NULL;
+   }
+}
+
 /**
  * Data collection object info - constructor
  */
@@ -1011,7 +1261,7 @@ DCObjectInfo::DCObjectInfo(DCObject *object)
    nx_strncpy(m_name, object->getName(), MAX_ITEM_NAME);
    nx_strncpy(m_description, object->getDescription(), MAX_DB_STRING);
    nx_strncpy(m_systemTag, object->getSystemTag(), MAX_DB_STRING);
-   nx_strncpy(m_instance, (m_type == DCO_TYPE_ITEM) ? ((DCItem *)object)->getInstance() : _T(""), MAX_DB_STRING);
+   nx_strncpy(m_instance, object->getInstance(), MAX_DB_STRING);
    m_comments = _tcsdup_ex(object->getComments());
    m_dataType = (m_type == DCO_TYPE_ITEM) ? ((DCItem *)object)->getDataType() : -1;
    m_origin = object->getDataSource();
index 1ea4af3..d218070 100644 (file)
@@ -208,6 +208,15 @@ DCTable::DCTable(DB_HANDLE hdb, DB_RESULT hResult, int iRow, Template *pNode) :
 
    m_thresholds = new ObjectArray<DCTableThreshold>(0, 4, true);
    loadThresholds(hdb);
+
+   m_instanceDiscoveryMethod = (WORD)DBGetFieldLong(hResult, iRow, 18);
+   m_instanceDiscoveryData = DBGetField(hResult, iRow, 19, NULL, 0);
+   m_instanceFilterSource = NULL;
+   m_instanceFilter = NULL;
+   pszTmp = DBGetField(hResult, iRow, 20, NULL, 0);
+   setInstanceFilter(pszTmp);
+   free(pszTmp);
+   DBGetField(hResult, iRow, 21, m_instance, MAX_DB_STRING);
 }
 
 /**
@@ -497,15 +506,17 @@ bool DCTable::saveToDatabase(DB_HANDLE hdb)
                hStmt = DBPrepare(hdb, _T("UPDATE dc_tables SET node_id=?,template_id=?,template_item_id=?,name=?,")
                                       _T("description=?,flags=?,source=?,snmp_port=?,polling_interval=?,")
                              _T("retention_time=?,status=?,system_tag=?,resource_id=?,proxy_node=?,")
-                                                                         _T("perftab_settings=?,transformation_script=?,comments=?,guid=? WHERE item_id=?"));
+                                                                         _T("perftab_settings=?,transformation_script=?,comments=?,guid=?,")
+                                                                         _T("instd_method=?,instd_data=?,instd_filter=?,instance=? WHERE item_id=?"));
        }
        else
        {
                hStmt = DBPrepare(hdb, _T("INSERT INTO dc_tables (node_id,template_id,template_item_id,name,")
                                       _T("description,flags,source,snmp_port,polling_interval,")
                                       _T("retention_time,status,system_tag,resource_id,proxy_node,perftab_settings,")
-                                                                         _T("transformation_script,comments,guid,item_id) ")
-                                                                         _T("VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+                                                                         _T("transformation_script,comments,guid, ")
+                                                                         _T("instd_method,instd_data,instd_filter,instance,item_id) ")
+                                                                         _T("VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
        }
        if (hStmt == NULL)
                return FALSE;
@@ -530,7 +541,11 @@ bool DCTable::saveToDatabase(DB_HANDLE hdb)
    DBBind(hStmt, 16, DB_SQLTYPE_TEXT, m_transformationScriptSource, DB_BIND_STATIC);
    DBBind(hStmt, 17, DB_SQLTYPE_TEXT, m_comments, DB_BIND_STATIC);
    DBBind(hStmt, 18, DB_SQLTYPE_VARCHAR, m_guid);
-       DBBind(hStmt, 19, DB_SQLTYPE_INTEGER, m_id);
+   DBBind(hStmt, 19, DB_SQLTYPE_INTEGER, (INT32)m_instanceDiscoveryMethod);
+   DBBind(hStmt, 20, DB_SQLTYPE_VARCHAR, m_instanceDiscoveryData, DB_BIND_STATIC);
+   DBBind(hStmt, 21, DB_SQLTYPE_TEXT, m_instanceFilterSource, DB_BIND_STATIC);
+   DBBind(hStmt, 22, DB_SQLTYPE_VARCHAR, m_instance, DB_BIND_STATIC);
+   DBBind(hStmt, 23, DB_SQLTYPE_INTEGER, m_id);
 
        bool result = DBExecute(hStmt);
        DBFreeStatement(hStmt);
@@ -979,13 +994,16 @@ void DCTable::createExportRecord(String &str)
                           _T("\t\t\t\t\t<retention>%d</retention>\n")
                           _T("\t\t\t\t\t<systemTag>%s</systemTag>\n")
                           _T("\t\t\t\t\t<flags>%d</flags>\n")
-                          _T("\t\t\t\t\t<snmpPort>%d</snmpPort>\n"),
+                          _T("\t\t\t\t\t<snmpPort>%d</snmpPort>\n")
+                          _T("\t\t\t\t\t<instanceDiscoveryMethod>%d</instanceDiscoveryMethod>\n")
+                          _T("\t\t\t\t\t<instance>%s</instance>\n"),
                                                                  (int)m_id, (const TCHAR *)m_guid.toString(),
                                                                  (const TCHAR *)EscapeStringForXML2(m_name),
                           (const TCHAR *)EscapeStringForXML2(m_description),
                           (int)m_source, m_iPollingInterval, m_iRetentionTime,
                           (const TCHAR *)EscapeStringForXML2(m_systemTag),
-                                                                 (int)m_flags, (int)m_snmpPort);
+                                                                 (int)m_flags, (int)m_snmpPort, (int)m_instanceDiscoveryMethod),
+                                                                 (const TCHAR *)EscapeStringForXML2(m_instance);
 
        if (m_transformationScriptSource != NULL)
        {
@@ -1033,6 +1051,20 @@ void DCTable::createExportRecord(String &str)
                str.append(_T("</perfTabSettings>\n"));
        }
 
+       if (m_instanceDiscoveryData != NULL)
+   {
+      str += _T("\t\t\t\t\t<instanceDiscoveryData>");
+      str.appendPreallocated(EscapeStringForXML(m_instanceDiscoveryData, -1));
+      str += _T("</instanceDiscoveryData>\n");
+   }
+
+   if (m_instanceFilterSource != NULL)
+   {
+      str += _T("\t\t\t\t\t<instanceFilter>");
+      str.appendPreallocated(EscapeStringForXML(m_instanceFilterSource, -1));
+      str += _T("</instanceFilter>\n");
+   }
+
    unlock();
    str.append(_T("\t\t\t\t</dctable>\n"));
 }
@@ -1071,16 +1103,6 @@ void DCTable::updateFromImport(ConfigEntry *config)
    unlock();
 }
 
-/**
- * Should return true if object has (or can have) value
- */
-bool DCTable::hasValue()
-{
-   if (m_owner->getObjectClass() == OBJECT_CLUSTER)
-      return isAggregateOnCluster();
-   return true;
-}
-
 /**
  * Get list of used events
  */
@@ -1097,3 +1119,11 @@ void DCTable::getEventList(IntegerArray<UINT32> *eventList)
    }
    unlock();
 }
+
+/*
+ * Clone DCTable
+ */
+DCObject *DCTable::clone()
+{
+   return new DCTable(this);
+}
index 7f8bf57..fdb3232 100644 (file)
@@ -3508,15 +3508,15 @@ void Node::doInstanceDiscovery(UINT32 requestId)
    sendPollerMsg(requestId, _T("Running DCI instance discovery\r\n"));
 
    // collect instance discovery DCIs
-   ObjectArray<DCItem> rootItems;
+   ObjectArray<DCObject> rootObjects;
    lockDciAccess(false);
    for(int i = 0; i < m_dcObjects->size(); i++)
    {
       DCObject *object = m_dcObjects->get(i);
-      if ((object->getType() == DCO_TYPE_ITEM) && (((DCItem *)object)->getInstanceDiscoveryMethod() != IDM_NONE))
+      if (object->getInstanceDiscoveryMethod() != IDM_NONE)
       {
          object->setBusyFlag();
-         rootItems.add((DCItem *)object);
+         rootObjects.add(object);
       }
    }
    unlockDciAccess();
@@ -3524,28 +3524,28 @@ void Node::doInstanceDiscovery(UINT32 requestId)
    // process instance discovery DCIs
    // it should be done that way to prevent DCI list lock for long time
    bool changed = false;
-   for(int i = 0; i < rootItems.size(); i++)
+   for(int i = 0; i < rootObjects.size(); i++)
    {
-      DCItem *dci = rootItems.get(i);
-      DbgPrintf(5, _T("Node::doInstanceDiscovery(%s [%u]): Updating instances for instance discovery DCI %s [%d]"),
-                m_name, m_id, dci->getName(), dci->getId());
-      sendPollerMsg(requestId, _T("   Updating instances for %s [%d]\r\n"), dci->getName(), dci->getId());
-      StringMap *instances = getInstanceList(dci);
+      DCObject *object = rootObjects.get(i);
+      DbgPrintf(5, _T("Node::doInstanceDiscovery(%s [%u]): Updating instances for instance discovery DCO %s [%d]"),
+                m_name, m_id, object->getName(), object->getId());
+      sendPollerMsg(requestId, _T("   Updating instances for %s [%d]\r\n"), object->getName(), object->getId());
+      StringMap *instances = getInstanceList(object);
       if (instances != NULL)
       {
          DbgPrintf(5, _T("Node::doInstanceDiscovery(%s [%u]): read %d values"), m_name, m_id, instances->size());
-         dci->filterInstanceList(instances);
-         if (updateInstances(dci, instances, requestId))
+         object->filterInstanceList(instances);
+         if (updateInstances(object, instances, requestId))
             changed = true;
          delete instances;
       }
       else
       {
-         DbgPrintf(5, _T("Node::doInstanceDiscovery(%s [%u]): failed to get instance list for DCI %s [%d]"),
-                   m_name, m_id, dci->getName(), dci->getId());
+         DbgPrintf(5, _T("Node::doInstanceDiscovery(%s [%u]): failed to get instance list for DCO %s [%d]"),
+                   m_name, m_id, object->getName(), object->getId());
          sendPollerMsg(requestId, POLLER_ERROR _T("      Failed to get instance list\r\n"));
       }
-      dci->clearBusyFlag();
+      object->clearBusyFlag();
    }
 
    if (changed)
@@ -3553,26 +3553,26 @@ void Node::doInstanceDiscovery(UINT32 requestId)
 }
 
 /**
- * Get instances for instance discovery DCI
+ * Get instances for instance discovery DCO
  */
-StringMap *Node::getInstanceList(DCItem *dci)
+StringMap *Node::getInstanceList(DCObject *dco)
 {
-   if (dci->getInstanceDiscoveryData() == NULL)
+   if (dco->getInstanceDiscoveryData() == NULL)
       return NULL;
 
    Node *node;
-   if (dci->getSourceNode() != 0)
+   if (dco->getSourceNode() != 0)
    {
-      node = (Node *)FindObjectById(dci->getSourceNode(), OBJECT_NODE);
+      node = (Node *)FindObjectById(dco->getSourceNode(), OBJECT_NODE);
       if (node == NULL)
       {
-         DbgPrintf(6, _T("Node::getInstanceList(%s [%d]): proxy node [%d] not found"), dci->getName(), dci->getId(), dci->getSourceNode());
+         DbgPrintf(6, _T("Node::getInstanceList(%s [%d]): proxy node [%d] not found"), dco->getName(), dco->getId(), dco->getSourceNode());
          return NULL;
       }
       if (!node->isTrustedNode(m_id))
       {
          DbgPrintf(6, _T("Node::getInstanceList(%s [%d]): this node (%s [%d]) is not trusted by proxy node %s [%d] not found"),
-                   dci->getName(), dci->getId(), m_name, m_id, node->getName(), node->getId());
+                  dco->getName(), dco->getId(), m_name, m_id, node->getName(), node->getId());
          return NULL;
       }
    }
@@ -3583,19 +3583,19 @@ StringMap *Node::getInstanceList(DCItem *dci)
 
    StringList *instances = NULL;
    StringMap *instanceMap = NULL;
-   switch(dci->getInstanceDiscoveryMethod())
+   switch(dco->getInstanceDiscoveryMethod())
    {
       case IDM_AGENT_LIST:
-         node->getListFromAgent(dci->getInstanceDiscoveryData(), &instances);
+         node->getListFromAgent(dco->getInstanceDiscoveryData(), &instances);
          break;
       case IDM_SCRIPT:
-         node->getStringMapFromScript(dci->getInstanceDiscoveryData(), &instanceMap);
+         node->getStringMapFromScript(dco->getInstanceDiscoveryData(), &instanceMap);
          break;
       case IDM_SNMP_WALK_VALUES:
-         node->getListFromSNMP(dci->getSnmpPort(), dci->getInstanceDiscoveryData(), &instances);
+         node->getListFromSNMP(dco->getSnmpPort(), dco->getInstanceDiscoveryData(), &instances);
          break;
       case IDM_SNMP_WALK_OIDS:
-         node->getOIDSuffixListFromSNMP(dci->getSnmpPort(), dci->getInstanceDiscoveryData(), &instanceMap);
+         node->getOIDSuffixListFromSNMP(dco->getSnmpPort(), dco->getInstanceDiscoveryData(), &instanceMap);
          break;
       default:
          instances = NULL;
@@ -3625,9 +3625,9 @@ static EnumerationCallbackResult FindInstanceCallback(const TCHAR *key, const vo
 /**
  * Data for CreateInstanceDCI
  */
-struct CreateInstanceDCIData
+struct CreateInstanceDCOData
 {
-   DCItem *root;
+   DCObject *root;
    Node *object;
    UINT32 requestId;
 };
@@ -3637,29 +3637,30 @@ struct CreateInstanceDCIData
  */
 static EnumerationCallbackResult CreateInstanceDCI(const TCHAR *key, const void *value, void *data)
 {
-   Node *object = ((CreateInstanceDCIData *)data)->object;
-   DCItem *root = ((CreateInstanceDCIData *)data)->root;
+   Node *object = ((CreateInstanceDCOData *)data)->object;
+   DCObject *root = ((CreateInstanceDCOData *)data)->root;
 
-   DbgPrintf(5, _T("Node::updateInstances(%s [%u], %s [%u]): creating new DCI for instance \"%s\""),
+   DbgPrintf(5, _T("Node::updateInstances(%s [%u], %s [%u]): creating new DCO for instance \"%s\""),
              object->getName(), object->getId(), root->getName(), root->getId(), key);
-   object->sendPollerMsg(((CreateInstanceDCIData *)data)->requestId, _T("      Creating new DCI for instance \"%s\"\r\n"), key);
-
-   DCItem *dci = new DCItem(root);
-   dci->setTemplateId(object->getId(), root->getId());
-   dci->setInstance((const TCHAR *)value);
-   dci->setInstanceDiscoveryMethod(IDM_NONE);
-   dci->setInstanceDiscoveryData(key);
-   dci->setInstanceFilter(NULL);
-   dci->expandInstance();
-   dci->changeBinding(CreateUniqueId(IDG_ITEM), object, FALSE);
-   object->addDCObject(dci, true);
+   object->sendPollerMsg(((CreateInstanceDCOData *)data)->requestId, _T("      Creating new DCO for instance \"%s\"\r\n"), key);
+
+   DCObject *dco = root->clone();
+
+   dco->setTemplateId(object->getId(), root->getId());
+   dco->setInstance((const TCHAR *)value);
+   dco->setInstanceDiscoveryMethod(IDM_NONE);
+   dco->setInstanceDiscoveryData(key);
+   dco->setInstanceFilter(NULL);
+   dco->expandInstance();
+   dco->changeBinding(CreateUniqueId(IDG_ITEM), object, FALSE);
+   object->addDCObject(dco, true);
    return _CONTINUE;
 }
 
 /**
  * Update instance DCIs created from instance discovery DCI
  */
-bool Node::updateInstances(DCItem *root, StringMap *instances, UINT32 requestId)
+bool Node::updateInstances(DCObject *root, StringMap *instances, UINT32 requestId)
 {
    bool changed = false;
 
@@ -3670,32 +3671,30 @@ bool Node::updateInstances(DCItem *root, StringMap *instances, UINT32 requestId)
    for(int i = 0; i < m_dcObjects->size(); i++)
    {
       DCObject *object = m_dcObjects->get(i);
-      if ((object->getType() != DCO_TYPE_ITEM) ||
-          (object->getTemplateId() != m_id) ||
-          (object->getTemplateItemId() != root->getId()))
+      if ((object->getTemplateId() != m_id) || (object->getTemplateItemId() != root->getId()))
          continue;
 
-      const TCHAR *dciInstance = ((DCItem *)object)->getInstanceDiscoveryData();
-      if (instances->forEach(FindInstanceCallback, (void *)dciInstance) == _STOP)
+      const TCHAR *dcoInstance = object->getInstanceDiscoveryData();
+      if (instances->forEach(FindInstanceCallback, (void *)dcoInstance) == _STOP)
       {
          // found, remove value from instances
          DbgPrintf(5, _T("Node::updateInstances(%s [%u], %s [%u]): instance \"%s\" found"),
-                   m_name, m_id, root->getName(), root->getId(), dciInstance);
-         const TCHAR *name = instances->get(dciInstance);
-         if (_tcscmp(name, ((DCItem *)object)->getInstance()))
+                   m_name, m_id, root->getName(), root->getId(), dcoInstance);
+         const TCHAR *name = instances->get(dcoInstance);
+         if (_tcscmp(name, object->getInstance()))
          {
-            ((DCItem *)object)->setInstance(name);
-            ((DCItem *)object)->updateFromTemplate(root);
+            object->setInstance(name);
+            object->updateFromTemplate(root);
             changed = true;
          }
-         instances->remove(dciInstance);
+         instances->remove(dcoInstance);
       }
       else
       {
-         // not found, delete DCI
-         DbgPrintf(5, _T("Node::updateInstances(%s [%u], %s [%u]): instance \"%s\" not found, instance DCI will be deleted"),
-                   m_name, m_id, root->getName(), root->getId(), dciInstance);
-         sendPollerMsg(requestId, _T("      Existing instance \"%s\" not found and will be deleted\r\n"), dciInstance);
+         // not found, delete DCO
+         DbgPrintf(5, _T("Node::updateInstances(%s [%u], %s [%u]): instance \"%s\" not found, instance DCO will be deleted"),
+                   m_name, m_id, root->getName(), root->getId(), dcoInstance);
+         sendPollerMsg(requestId, _T("      Existing instance \"%s\" not found and will be deleted\r\n"), dcoInstance);
          deleteList.add(object->getId());
          changed = true;
       }
@@ -3707,7 +3706,7 @@ bool Node::updateInstances(DCItem *root, StringMap *instances, UINT32 requestId)
    // Create new instances
    if (instances->size() > 0)
    {
-      CreateInstanceDCIData data;
+      CreateInstanceDCOData data;
       data.root = root;
       data.object = this;
       data.requestId = requestId;
index a6b87c8..4fb8cc9 100644 (file)
@@ -391,7 +391,7 @@ void Template::loadItemsFromDB(DB_HANDLE hdb)
                   _T("SELECT item_id,template_id,template_item_id,name,")
                                  _T("description,flags,source,snmp_port,polling_interval,retention_time,")
               _T("status,system_tag,resource_id,proxy_node,perftab_settings,")
-              _T("transformation_script,comments,guid FROM dc_tables WHERE node_id=?"));
+              _T("transformation_script,comments,guid,instd_method,instd_data,instd_filter,instance FROM dc_tables WHERE node_id=?"));
        if (hStmt != NULL)
        {
                DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
@@ -414,10 +414,8 @@ bool Template::addDCObject(DCObject *object, bool alreadyLocked)
 {
    int i;
    bool success = false;
-
    if (!alreadyLocked)
       lockDciAccess(true); // write lock
-
    // Check if that object exists
    for(i = 0; i < m_dcObjects->size(); i++)
       if (m_dcObjects->get(i)->getId() == object->getId())
index c4ec8a8..cbb706b 100644 (file)
@@ -211,6 +211,11 @@ protected:
    NXSL_Program *m_transformationScript;  // Compiled transformation script
        TCHAR *m_comments;
        ClientSession *m_pollingSession;
+   WORD m_instanceDiscoveryMethod;
+   TCHAR *m_instanceDiscoveryData;
+   TCHAR *m_instanceFilterSource;
+   NXSL_Program *m_instanceFilter;
+   TCHAR m_instance[MAX_DB_STRING];
 
    void lock() { MutexLock(m_hMutex); }
    bool tryLock() { return MutexTryLock(m_hMutex); }
@@ -225,14 +230,17 @@ protected:
 
        // --- constructors ---
    DCObject();
-   DCObject(const DCObject *src);
    DCObject(UINT32 dwId, const TCHAR *szName, int iSource, int iPollingInterval, int iRetentionTime, Template *pNode,
             const TCHAR *pszDescription = NULL, const TCHAR *systemTag = NULL);
        DCObject(ConfigEntry *config, Template *owner);
+   DCObject(const DCObject *src);
 
 public:
+
        virtual ~DCObject();
 
+   virtual DCObject *clone() = 0;
+
        virtual int getType() const { return DCO_TYPE_GENERIC; }
 
    virtual void updateFromTemplate(DCObject *dcObject);
@@ -246,8 +254,6 @@ public:
    void processNewError(bool noInstance);
    virtual void processNewError(bool noInstance, time_t now);
 
-       virtual bool hasValue();
-
        UINT32 getId() const { return m_id; }
        const uuid& getGuid() const { return m_guid; }
    int getDataSource() const { return m_source; }
@@ -316,6 +322,17 @@ public:
 
        static int m_defaultRetentionTime;
        static int m_defaultPollingInterval;
+
+   WORD getInstanceDiscoveryMethod() const { return m_instanceDiscoveryMethod; }
+   const TCHAR *getInstanceDiscoveryData() const { return m_instanceDiscoveryData; }
+   void filterInstanceList(StringMap *instances);
+   void setInstanceDiscoveryMethod(WORD method) { m_instanceDiscoveryMethod = method; }
+   void setInstanceDiscoveryData(const TCHAR *data) { safe_free(m_instanceDiscoveryData); m_instanceDiscoveryData = _tcsdup_ex(data); }
+   void setInstanceFilter(const TCHAR *pszScript);
+   void setInstance(const TCHAR *instance) { nx_strncpy(m_instance, instance, MAX_DB_STRING); }
+   const TCHAR *getInstance() const { return m_instance; }
+   void expandInstance();
+   bool hasValue();
 };
 
 /**
@@ -324,7 +341,6 @@ public:
 class NXCORE_EXPORTABLE DCItem : public DCObject
 {
 protected:
-   TCHAR m_instance[MAX_DB_STRING];
    BYTE m_deltaCalculation;      // Delta calculation method
    BYTE m_dataType;
        int m_sampleCount;            // Number of samples required to calculate value
@@ -339,10 +355,6 @@ protected:
        int m_nMultiplier;
        TCHAR *m_customUnitName;
        WORD m_snmpRawValueType;                // Actual SNMP raw value type for input transformation
-       WORD m_instanceDiscoveryMethod;
-       TCHAR *m_instanceDiscoveryData;
-       TCHAR *m_instanceFilterSource;
-       NXSL_Program *m_instanceFilter;
        TCHAR m_predictionEngine[MAX_NPE_NAME_LEN];
 
    bool transform(ItemValue &value, time_t nElapsedTime);
@@ -364,6 +376,8 @@ public:
        DCItem(ConfigEntry *config, Template *owner);
    virtual ~DCItem();
 
+   virtual DCObject *clone();
+
        virtual int getType() const { return DCO_TYPE_ITEM; }
 
    virtual void updateFromTemplate(DCObject *dcObject);
@@ -381,20 +395,12 @@ public:
        WORD getSnmpRawValueType() const { return m_snmpRawValueType; }
        bool hasActiveThreshold();
    int getThresholdSeverity();
-       WORD getInstanceDiscoveryMethod() const { return m_instanceDiscoveryMethod; }
-       const TCHAR *getInstanceDiscoveryData() const { return m_instanceDiscoveryData; }
-       const TCHAR *getInstance() const { return m_instance; }
        int getSampleCount() const { return m_sampleCount; }
        const TCHAR *getPredictionEngine() const { return m_predictionEngine; }
 
-       void filterInstanceList(StringMap *instances);
-       void expandInstance();
-
    virtual bool processNewValue(time_t nTimeStamp, const void *value, bool *updateStatus);
    virtual void processNewError(bool noInstance, time_t now);
 
-       virtual bool hasValue();
-
    void fillLastValueMessage(NXCPMessage *pMsg, UINT32 dwId);
    NXSL_Value *getValueForNXSL(int nFunction, int nPolls);
    NXSL_Value *getRawValueForNXSL();
@@ -417,15 +423,11 @@ public:
        int getThresholdCount() const { return (m_thresholds != NULL) ? m_thresholds->size() : 0; }
        BOOL enumThresholds(BOOL (* pfCallback)(Threshold *, UINT32, void *), void *pArg);
 
-       void setInstance(const TCHAR *instance) { nx_strncpy(m_instance, instance, MAX_DB_STRING); }
        void setDataType(int dataType) { m_dataType = dataType; }
        void setDeltaCalcMethod(int method) { m_deltaCalculation = method; }
        void setAllThresholdsFlag(BOOL bFlag) { if (bFlag) m_flags |= DCF_ALL_THRESHOLDS; else m_flags &= ~DCF_ALL_THRESHOLDS; }
        void addThreshold(Threshold *pThreshold);
        void deleteAllThresholds();
-       void setInstanceDiscoveryMethod(WORD method) { m_instanceDiscoveryMethod = method; }
-       void setInstanceDiscoveryData(const TCHAR *data) { safe_free(m_instanceDiscoveryData); m_instanceDiscoveryData = _tcsdup_ex(data); }
-   void setInstanceFilter(const TCHAR *pszScript);
 
    static bool testTransformation(DataCollectionTarget *object, const TCHAR *script, const TCHAR *value, TCHAR *buffer, size_t bufSize);
 };
@@ -577,6 +579,8 @@ public:
    DCTable(ConfigEntry *config, Template *owner);
        virtual ~DCTable();
 
+       virtual DCObject *clone();
+
        virtual int getType() const { return DCO_TYPE_TABLE; }
 
    virtual void updateFromTemplate(DCObject *dcObject);
@@ -588,8 +592,6 @@ public:
    virtual bool processNewValue(time_t nTimeStamp, const void *value, bool *updateStatus);
    virtual void processNewError(bool noInstance, time_t now);
 
-   virtual bool hasValue();
-
    virtual void createMessage(NXCPMessage *pMsg);
    virtual void updateFromMessage(NXCPMessage *pMsg);
 
index 06aee6e..6680b29 100644 (file)
@@ -1515,8 +1515,8 @@ protected:
        bool checkNetworkPathElement(UINT32 nodeId, const TCHAR *nodeType, bool isProxy, UINT32 requestId, bool secondPass);
 
        void doInstanceDiscovery(UINT32 requestId);
-       StringMap *getInstanceList(DCItem *dci);
-       bool updateInstances(DCItem *root, StringMap *instances, UINT32 requestId);
+       StringMap *getInstanceList(DCObject *dco);
+       bool updateInstances(DCObject *root, StringMap *instances, UINT32 requestId);
    void syncDataCollectionWithAgent(AgentConnectionEx *conn);
 
        bool updateInterfaceConfiguration(UINT32 rqid, int maskBits);
index df01b4b..9f69383 100644 (file)
@@ -746,6 +746,24 @@ static bool SetSchemaVersion(int version)
    return SQLQuery(query);
 }
 
+/*
+ * Upgrade from V442 to V443
+ */
+static BOOL H_UpgradeFromV442(int currVersion, int newVersion)
+{
+   static const TCHAR *batch =
+            _T("ALTER TABLE dc_tables ADD instance varchar(255) null\n")
+            _T("ALTER TABLE dc_tables ADD instd_method integer null\n")
+            _T("UPDATE dc_tables SET instd_method=0\n")
+            _T("ALTER TABLE dc_tables ADD instd_data varchar(255) null\n")
+            _T("ALTER TABLE dc_tables ADD instd_filter $SQL:TEXT null\n")
+            _T("<END>");
+   CHK_EXEC(SQLBatch(batch));
+   SetNotNullConstraint(_T("dc_tables"), _T("instd_method"));
+   CHK_EXEC(SetSchemaVersion(443));
+   return TRUE;
+}
+
 /**
  * Upgrade from V441 to V442
  */
@@ -11573,6 +11591,7 @@ static struct
    { 439, 440, H_UpgradeFromV439 },
    { 440, 441, H_UpgradeFromV440 },
    { 441, 442, H_UpgradeFromV441 },
+   { 442, 443, H_UpgradeFromV442 },
    { 0, 0, NULL }
 };
 
index bba9d98..b1f8eca 100644 (file)
               name="%page.name.InstanceDiscovery">
            <enabledWhen>
               <instanceof
-                    value="org.netxms.client.datacollection.DataCollectionItem">
+                    value="org.netxms.client.datacollection.DataCollectionObject">
               </instanceof>
            </enabledWhen>
         </page>
index c44d634..7d67eda 100644 (file)
@@ -27,8 +27,9 @@ import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Combo;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
-import org.netxms.client.datacollection.DataCollectionItem;
+import org.netxms.client.datacollection.DataCollectionObject;
 import org.netxms.ui.eclipse.datacollection.Messages;
+import org.netxms.ui.eclipse.datacollection.api.DataCollectionObjectEditor;
 import org.netxms.ui.eclipse.datacollection.propertypages.helpers.DCIPropertyPageDialog;
 import org.netxms.ui.eclipse.nxsl.widgets.ScriptEditor;
 import org.netxms.ui.eclipse.tools.WidgetFactory;
@@ -36,14 +37,15 @@ import org.netxms.ui.eclipse.tools.WidgetHelper;
 import org.netxms.ui.eclipse.widgets.LabeledText;
 
 /**
- * "Instance Discovery" property page for DCI
+ * "Instance Discovery" property page for DCO
  */
 public class InstanceDiscovery extends DCIPropertyPageDialog
 {
        private static final String[] DCI_FUNCTIONS = { "FindDCIByName", "FindDCIByDescription", "GetDCIObject", "GetDCIValue", "GetDCIValueByDescription", "GetDCIValueByName" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
        private static final String[] DCI_VARIABLES = { "$dci", "$node" }; //$NON-NLS-1$ //$NON-NLS-2$
        
-       private DataCollectionItem dci;
+       private DataCollectionObjectEditor editor;
+       private DataCollectionObject dco;
        private Combo discoveryMethod;
        private LabeledText discoveryData;
        private ScriptEditor filterScript;
@@ -55,7 +57,8 @@ public class InstanceDiscovery extends DCIPropertyPageDialog
        protected Control createContents(Composite parent)
        {
           Composite dialogArea = (Composite)super.createContents(parent);
-               dci = editor.getObjectAsItem();
+               editor = (DataCollectionObjectEditor)getElement().getAdapter(DataCollectionObjectEditor.class);
+               dco = editor.getObject();
                
                GridLayout layout = new GridLayout();
                layout.verticalSpacing = WidgetHelper.OUTER_SPACING;
@@ -71,15 +74,15 @@ public class InstanceDiscovery extends DCIPropertyPageDialog
       discoveryMethod.add(Messages.get().InstanceDiscovery_SnmpWalkValues);
       discoveryMethod.add(Messages.get().InstanceDiscovery_SnmpWalkOids);
       discoveryMethod.add(Messages.get().InstanceDiscovery_Script);
-      discoveryMethod.select(dci.getInstanceDiscoveryMethod());
+      discoveryMethod.select(dco.getInstanceDiscoveryMethod());
       discoveryMethod.addSelectionListener(new SelectionListener() {
                        @Override
                        public void widgetSelected(SelectionEvent e)
                        {
                                int method = discoveryMethod.getSelectionIndex();
                      discoveryData.setLabel(getDataLabel(method));
-                     discoveryData.setEnabled(method != DataCollectionItem.IDM_NONE);
-                     filterScript.setEnabled(method != DataCollectionItem.IDM_NONE);
+                     discoveryData.setEnabled(method != DataCollectionObject.IDM_NONE);
+                     filterScript.setEnabled(method != DataCollectionObject.IDM_NONE);
                        }
                        
                        @Override
@@ -90,13 +93,13 @@ public class InstanceDiscovery extends DCIPropertyPageDialog
                });
       
       discoveryData = new LabeledText(dialogArea, SWT.NONE);
-      discoveryData.setLabel(getDataLabel(dci.getInstanceDiscoveryMethod()));
-      discoveryData.setText(dci.getInstanceDiscoveryData());
+      discoveryData.setLabel(getDataLabel(dco.getInstanceDiscoveryMethod()));
+      discoveryData.setText(dco.getInstanceDiscoveryData());
       GridData gd = new GridData();
       gd.horizontalAlignment = SWT.FILL;
       gd.grabExcessHorizontalSpace = true;
       discoveryData.setLayoutData(gd);
-      discoveryData.setEnabled(dci.getInstanceDiscoveryMethod() != DataCollectionItem.IDM_NONE);
+      discoveryData.setEnabled(dco.getInstanceDiscoveryMethod() != DataCollectionObject.IDM_NONE);
      
       gd = new GridData();
       gd.horizontalAlignment = SWT.FILL;
@@ -123,8 +126,8 @@ public class InstanceDiscovery extends DCIPropertyPageDialog
       gd.grabExcessHorizontalSpace = true;
       gd.grabExcessVerticalSpace = true;
       filterScript.setLayoutData(gd);
-      filterScript.setText(dci.getInstanceDiscoveryFilter());
-      filterScript.setEnabled(dci.getInstanceDiscoveryMethod() != DataCollectionItem.IDM_NONE);
+      filterScript.setText(dco.getInstanceDiscoveryFilter());
+      filterScript.setEnabled(dco.getInstanceDiscoveryMethod() != DataCollectionObject.IDM_NONE);
       
                return dialogArea;
        }
@@ -139,14 +142,14 @@ public class InstanceDiscovery extends DCIPropertyPageDialog
        {
                switch(method)
                {
-                       case DataCollectionItem.IDM_NONE:
+                       case DataCollectionObject.IDM_NONE:
                                return Messages.get().InstanceDiscovery_DiscoveryData;
-                       case DataCollectionItem.IDM_AGENT_LIST:
+                       case DataCollectionObject.IDM_AGENT_LIST:
                                return Messages.get().InstanceDiscovery_ListName;
-                       case DataCollectionItem.IDM_AGENT_TABLE:
+                       case DataCollectionObject.IDM_AGENT_TABLE:
                                return Messages.get().InstanceDiscovery_TableName;
-                       case DataCollectionItem.IDM_SNMP_WALK_VALUES:
-                       case DataCollectionItem.IDM_SNMP_WALK_OIDS:
+                       case DataCollectionObject.IDM_SNMP_WALK_VALUES:
+                       case DataCollectionObject.IDM_SNMP_WALK_OIDS:
                                return Messages.get().InstanceDiscovery_BaseOid;
                }
                return ""; //$NON-NLS-1$
@@ -159,9 +162,9 @@ public class InstanceDiscovery extends DCIPropertyPageDialog
         */
        protected void applyChanges(final boolean isApply)
        {
-               dci.setInstanceDiscoveryMethod(discoveryMethod.getSelectionIndex());
-               dci.setInstanceDiscoveryData(discoveryData.getText());
-               dci.setInstanceDiscoveryFilter(filterScript.getText());
+          dco.setInstanceDiscoveryMethod(discoveryMethod.getSelectionIndex());
+          dco.setInstanceDiscoveryData(discoveryData.getText());
+          dco.setInstanceDiscoveryFilter(filterScript.getText());
                editor.modify();
        }
 
@@ -191,8 +194,8 @@ public class InstanceDiscovery extends DCIPropertyPageDialog
        protected void performDefaults()
        {
                super.performDefaults();
-               discoveryMethod.select(DataCollectionItem.IDM_NONE);
-               discoveryData.setLabel(getDataLabel(DataCollectionItem.IDM_NONE));
+               discoveryMethod.select(DataCollectionObject.IDM_NONE);
+               discoveryData.setLabel(getDataLabel(DataCollectionObject.IDM_NONE));
                discoveryData.setText(""); //$NON-NLS-1$
                discoveryData.setEnabled(false);
                filterScript.setText(""); //$NON-NLS-1$
index e6d059d..17a8047 100644 (file)
@@ -372,7 +372,7 @@ public class LastValuesWidget extends CompositeWithMessageBar
                        return;
                }
 
-               ConsoleJob job = new ConsoleJob(Messages.get().LastValuesWidget_JobTitle + dcTarget.getObjectName(), viewPart, Activator.PLUGIN_ID, LastValuesWidget.JOB_FAMILY) {
+               ConsoleJob job = new ConsoleJob(Messages.get(getDisplay()).LastValuesWidget_JobTitle + dcTarget.getObjectName(), viewPart, Activator.PLUGIN_ID, LastValuesWidget.JOB_FAMILY, getDisplay()) {
                        @Override
                        protected String getErrorMessage()
                        {