Implemented: Comments for DCIs (Feature #537)
authorzev <zev@radensolutions.com>
Thu, 17 Jul 2014 18:04:26 +0000 (21:04 +0300)
committerzev <zev@radensolutions.com>
Thu, 17 Jul 2014 18:04:58 +0000 (21:04 +0300)
17 files changed:
include/netxmsdb.h
include/nxclapi.h
sql/schema.in
src/java/netxms-client/src/main/java/org/netxms/client/datacollection/DataCollectionObject.java
src/java/netxms-eclipse/DataCollection/plugin.xml
src/java/netxms-eclipse/DataCollection/src/org/netxms/ui/eclipse/datacollection/propertypages/Comments.java [new file with mode: 0644]
src/libnxcl/datacoll.cpp
src/libnxcl/session.cpp
src/server/core/dcitem.cpp
src/server/core/dcithreshold.cpp
src/server/core/dcobject.cpp
src/server/core/dctable.cpp
src/server/core/template.cpp
src/server/include/nms_dcoll.h
src/server/tools/nxdbmgr/upgrade.cpp
webui/webapp/DataCollection/plugin.xml
webui/webapp/DataCollection/src/org/netxms/ui/eclipse/datacollection/propertypages/Comments.java [new file with mode: 0644]

index 67c2ca7..8d04ad8 100644 (file)
@@ -23,6 +23,6 @@
 #ifndef _netxmsdb_h
 #define _netxmsdb_h
 
-#define DB_FORMAT_VERSION   328
+#define DB_FORMAT_VERSION   329
 
 #endif
index 6f2aa4d..3701d83 100644 (file)
@@ -1508,6 +1508,7 @@ typedef struct
        TCHAR *pszPerfTabSettings;
        WORD nSnmpPort;
        WORD wSnmpRawType;
+       TCHAR *comments;
 } NXC_DCI;
 
 
index aa1697e..3a50e9b 100644 (file)
@@ -558,7 +558,7 @@ CREATE TABLE items
        node_id integer not null,
        template_id integer not null,
        template_item_id integer not null,
-       name varchar(1024) null,
+       name varchar(1023) null,
        description varchar(255) null,
        flags integer not null,
        source integer not null,        // 0 for internal or 1 for native agent or 2 for SNMP
@@ -582,6 +582,7 @@ CREATE TABLE items
        instd_data varchar(255) null,
        instd_filter SQL_TEXT null,
        samples integer not null,
+       comments SQL_TEXT null,
        PRIMARY KEY(item_id)
 ) TABLE_TYPE;
 
index 4687884..a16be78 100644 (file)
@@ -80,6 +80,7 @@ public abstract class DataCollectionObject
        protected int snmpPort;
        protected ArrayList<String> schedules;
        protected Object userData;
+       private String comments;
 
        /**
         * Create data collection object from NXCP message
@@ -105,6 +106,7 @@ public abstract class DataCollectionObject
                systemTag = msg.getVariableAsString(NXCPCodes.VID_SYSTEM_TAG);
                perfTabSettings = msg.getVariableAsString(NXCPCodes.VID_PERFTAB_SETTINGS);
                snmpPort = msg.getVariableAsInteger(NXCPCodes.VID_SNMP_PORT);
+               comments = msg.getVariableAsString(NXCPCodes.VID_COMMENTS);
                
                int count = msg.getVariableAsInteger(NXCPCodes.VID_NUM_SCHEDULES);
                schedules = new ArrayList<String>(count);
@@ -140,6 +142,7 @@ public abstract class DataCollectionObject
                systemTag = "";
                snmpPort = 0;
                schedules = new ArrayList<String>(0);
+               comments = "";
        }
        
        /**
@@ -164,6 +167,7 @@ public abstract class DataCollectionObject
                if (perfTabSettings != null)
                        msg.setVariable(NXCPCodes.VID_PERFTAB_SETTINGS, perfTabSettings);
                msg.setVariableInt16(NXCPCodes.VID_SNMP_PORT, snmpPort);
+               msg.setVariable(NXCPCodes.VID_COMMENTS, comments);
                
                msg.setVariableInt32(NXCPCodes.VID_NUM_SCHEDULES, schedules.size());
                long varId = NXCPCodes.VID_DCI_SCHEDULE_BASE;
@@ -523,4 +527,20 @@ public abstract class DataCollectionObject
       else
          flags &= ~DCF_TRANSFORM_AGGREGATED;
    }
+
+   /**
+    * @return the comments
+    */
+   public String getComments()
+   {
+      return comments;
+   }
+
+   /**
+    * @param comments the comments to set
+    */
+   public void setComments(String comments)
+   {
+      this.comments = comments;
+   }
 }
index 6391a59..5372d69 100644 (file)
               class="org.netxms.ui.eclipse.datacollection.propertypages.GeneralTable"
               id="org.netxms.ui.eclipse.datacollection.propertypages.GeneralTable#1"
               name="%page.name.General">
+            <enabledWhen>
+               <instanceof
+                    value="org.netxms.client.datacollection.DataCollectionTable">
+               </instanceof>
+            </enabledWhen>
+        </page>
+        <page
+              class="org.netxms.ui.eclipse.datacollection.propertypages.Comments"
+              id="org.netxms.ui.eclipse.datacollection.propertypages.Comments"
+              name="Comments">
            <enabledWhen>
               <instanceof
-                    value="org.netxms.client.datacollection.DataCollectionTable">
+                    value="org.netxms.client.datacollection.DataCollectionObject">
               </instanceof>
            </enabledWhen>
         </page>
diff --git a/src/java/netxms-eclipse/DataCollection/src/org/netxms/ui/eclipse/datacollection/propertypages/Comments.java b/src/java/netxms-eclipse/DataCollection/src/org/netxms/ui/eclipse/datacollection/propertypages/Comments.java
new file mode 100644 (file)
index 0000000..72572de
--- /dev/null
@@ -0,0 +1,122 @@
+/**
+ * NetXMS - open source network management system
+ * Copyright (C) 2003-2013 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.
+ */
+package org.netxms.ui.eclipse.datacollection.propertypages;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.PropertyPage;
+import org.netxms.client.datacollection.DataCollectionObject;
+import org.netxms.ui.eclipse.datacollection.api.DataCollectionObjectEditor;
+import org.netxms.ui.eclipse.tools.WidgetHelper;
+
+/**
+ * "Comments" property page for NetXMS object
+ *
+ */
+public class Comments extends PropertyPage
+{
+   private DataCollectionObjectEditor editor;
+   private DataCollectionObject dci;
+       private Text comments;
+       private String initialComments;
+       
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
+        */
+       @Override
+       protected Control createContents(Composite parent)
+       {
+               Composite dialogArea = new Composite(parent, SWT.NONE);
+               
+               editor = (DataCollectionObjectEditor)getElement().getAdapter(DataCollectionObjectEditor.class);
+      dci = editor.getObject();
+      
+               initialComments = dci.getComments();
+               if (initialComments == null)
+                       initialComments = ""; //$NON-NLS-1$
+
+               GridLayout layout = new GridLayout();
+               layout.verticalSpacing = WidgetHelper.OUTER_SPACING;
+               layout.marginWidth = 0;
+               layout.marginHeight = 0;
+      dialogArea.setLayout(layout);
+
+      comments = new Text(dialogArea, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+               comments.setText(initialComments);
+
+               GridData gd = new GridData();
+               gd.grabExcessHorizontalSpace = true;
+               gd.grabExcessVerticalSpace = true;
+               gd.horizontalAlignment = SWT.FILL;
+               gd.verticalAlignment = SWT.FILL;
+               gd.widthHint = 0;
+      gd.heightHint = 0;
+               comments.setLayoutData(gd);
+               
+               return dialogArea;
+       }
+
+       /**
+        * Apply changes
+        * 
+        * @param isApply true if update operation caused by "Apply" button
+        */
+       protected void applyChanges(final boolean isApply)
+       {
+               if (initialComments.equals(comments.getText()))
+                       return; // Nothing to apply
+               
+               final String newComments = new String(comments.getText());
+               dci.setComments(newComments);
+               editor.modify();
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.preference.PreferencePage#performOk()
+        */
+       @Override
+       public boolean performOk()
+       {
+               applyChanges(false);
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.preference.PreferencePage#performApply()
+        */
+       @Override
+       protected void performApply()
+       {
+               applyChanges(true);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
+        */
+       @Override
+       protected void performDefaults()
+       {
+               super.performDefaults();
+               comments.setText(""); //$NON-NLS-1$
+       }
+}
index 92e00af..3941c86 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
 ** NetXMS - Network Management System
 ** Client Library
 ** Copyright (C) 2003-2013 Victor Kirhenshtein
@@ -27,7 +27,7 @@
  * Load data collection items list for specified node
  * This function is NOT REENTRANT
  */
-UINT32 LIBNXCL_EXPORTABLE NXCOpenNodeDCIList(NXC_SESSION hSession, UINT32 dwNodeId, 
+UINT32 LIBNXCL_EXPORTABLE NXCOpenNodeDCIList(NXC_SESSION hSession, UINT32 dwNodeId,
                                             NXC_DCI_LIST **ppItemList)
 {
    return ((NXCL_Session *)hSession)->OpenNodeDCIList(dwNodeId, ppItemList);
@@ -99,7 +99,7 @@ UINT32 LIBNXCL_EXPORTABLE NXCCreateNewDCI(NXC_SESSION hSession, NXC_DCI_LIST *pI
          *pdwItemId = pResponse->GetVariableLong(VID_DCI_ID);
 
          // Create new entry in list
-         pItemList->pItems = (NXC_DCI *)realloc(pItemList->pItems, 
+         pItemList->pItems = (NXC_DCI *)realloc(pItemList->pItems,
                                                    sizeof(NXC_DCI) * (pItemList->dwNumItems + 1));
          memset(&pItemList->pItems[pItemList->dwNumItems], 0, sizeof(NXC_DCI));
          pItemList->pItems[pItemList->dwNumItems].dwId = *pdwItemId;
@@ -159,6 +159,7 @@ UINT32 LIBNXCL_EXPORTABLE NXCUpdateDCI(NXC_SESSION hSession, UINT32 dwNodeId, NX
        msg.SetVariable(VID_BASE_UNITS, (WORD)pItem->nBaseUnits);
        msg.SetVariable(VID_MULTIPLIER, (UINT32)pItem->nMultiplier);
        msg.SetVariable(VID_SNMP_PORT, (WORD)pItem->nSnmpPort);
+   msg.SetVariable(VID_COMMENTS, (pItem->comments));
        if (pItem->pszCustomUnitName != NULL)
                msg.SetVariable(VID_CUSTOM_UNITS_NAME, pItem->pszCustomUnitName);
        if (pItem->pszPerfTabSettings)
@@ -256,7 +257,7 @@ UINT32 LIBNXCL_EXPORTABLE NXCDeleteDCI(NXC_SESSION hSession, NXC_DCI_LIST *pItem
                                safe_free(pItemList->pItems[i].pszCustomUnitName);
                                safe_free(pItemList->pItems[i].pszPerfTabSettings);
             pItemList->dwNumItems--;
-            memmove(&pItemList->pItems[i], &pItemList->pItems[i + 1], 
+            memmove(&pItemList->pItems[i], &pItemList->pItems[i + 1],
                     sizeof(NXC_DCI) * (pItemList->dwNumItems - i));
          }
          break;
@@ -267,7 +268,7 @@ UINT32 LIBNXCL_EXPORTABLE NXCDeleteDCI(NXC_SESSION hSession, NXC_DCI_LIST *pItem
 /**
  * Set status for multiple DCIs
  */
-UINT32 LIBNXCL_EXPORTABLE NXCSetDCIStatus(NXC_SESSION hSession, UINT32 dwNodeId, UINT32 dwNumItems, 
+UINT32 LIBNXCL_EXPORTABLE NXCSetDCIStatus(NXC_SESSION hSession, UINT32 dwNodeId, UINT32 dwNumItems,
                                          UINT32 *pdwItemList, int iStatus)
 {
    CSCPMessage msg;
@@ -303,8 +304,8 @@ UINT32 LIBNXCL_EXPORTABLE NXCItemIndex(NXC_DCI_LIST *pItemList, UINT32 dwItemId)
 /**
  * Retrieve collected data from server
  */
-UINT32 LIBNXCL_EXPORTABLE NXCGetDCIData(NXC_SESSION hSession, UINT32 dwNodeId, UINT32 dwItemId, 
-                                       UINT32 dwMaxRows, UINT32 dwTimeFrom, UINT32 dwTimeTo, 
+UINT32 LIBNXCL_EXPORTABLE NXCGetDCIData(NXC_SESSION hSession, UINT32 dwNodeId, UINT32 dwItemId,
+                                       UINT32 dwMaxRows, UINT32 dwTimeFrom, UINT32 dwTimeTo,
                                        NXC_DCI_DATA **ppData)
 {
        return NXCGetDCIDataEx(hSession, dwNodeId, dwItemId, dwMaxRows, dwTimeFrom, dwTimeTo, ppData, NULL, NULL);
@@ -313,8 +314,8 @@ UINT32 LIBNXCL_EXPORTABLE NXCGetDCIData(NXC_SESSION hSession, UINT32 dwNodeId, U
 /**
  * Retrieve collected data from server
  */
-UINT32 LIBNXCL_EXPORTABLE NXCGetDCIDataEx(NXC_SESSION hSession, UINT32 dwNodeId, UINT32 dwItemId, 
-                                         UINT32 dwMaxRows, UINT32 dwTimeFrom, UINT32 dwTimeTo, 
+UINT32 LIBNXCL_EXPORTABLE NXCGetDCIDataEx(NXC_SESSION hSession, UINT32 dwNodeId, UINT32 dwItemId,
+                                         UINT32 dwMaxRows, UINT32 dwTimeFrom, UINT32 dwTimeTo,
                                          NXC_DCI_DATA **ppData, NXC_DCI_THRESHOLD **thresholds, UINT32 *numThresholds)
 {
    CSCPMessage msg, *response;
@@ -430,7 +431,7 @@ UINT32 LIBNXCL_EXPORTABLE NXCGetDCIDataEx(NXC_SESSION hSession, UINT32 dwNodeId,
                      ucs2_to_ucs4(pSrc->value.string, -1, pDst->value.szString, MAX_STRING_VALUE);
 #else
                      wcscpy(pDst->value.szString, pSrc->value.string);
-#endif                     
+#endif
 #else
                      ucs2_to_mb(pSrc->value.string, -1, pDst->value.szString, MAX_STRING_VALUE);
 #endif
@@ -566,7 +567,7 @@ BOOL LIBNXCL_EXPORTABLE NXCSwapThresholds(NXC_DCI *pItem, UINT32 dwIndex1, UINT3
 /**
  * Copy data collection items from one node to another
  */
-UINT32 LIBNXCL_EXPORTABLE NXCCopyDCI(NXC_SESSION hSession, UINT32 dwSrcNodeId, UINT32 dwDstNodeId, 
+UINT32 LIBNXCL_EXPORTABLE NXCCopyDCI(NXC_SESSION hSession, UINT32 dwSrcNodeId, UINT32 dwDstNodeId,
                                     UINT32 dwNumItems, UINT32 *pdwItemList, BOOL bMove)
 {
    CSCPMessage msg;
@@ -591,8 +592,8 @@ UINT32 LIBNXCL_EXPORTABLE NXCCopyDCI(NXC_SESSION hSession, UINT32 dwSrcNodeId, U
 /**
  * Query value of specific parameter from node
  */
-UINT32 LIBNXCL_EXPORTABLE NXCQueryParameter(NXC_SESSION hSession, UINT32 dwNodeId, int iOrigin, 
-                                           TCHAR *pszParameter, TCHAR *pszBuffer, 
+UINT32 LIBNXCL_EXPORTABLE NXCQueryParameter(NXC_SESSION hSession, UINT32 dwNodeId, int iOrigin,
+                                           TCHAR *pszParameter, TCHAR *pszBuffer,
                                            UINT32 dwBufferSize)
 {
    CSCPMessage msg, *pResponse;
index fcfcade..9249083 100644 (file)
@@ -419,6 +419,7 @@ void NXCL_Session::processDCI(CSCPMessage *pMsg)
                m_pItemList->pItems[i].pszPerfTabSettings = pMsg->GetVariableStr(VID_PERFTAB_SETTINGS);
                m_pItemList->pItems[i].nSnmpPort = pMsg->GetVariableShort(VID_SNMP_PORT);
       m_pItemList->pItems[i].dwNumSchedules = pMsg->GetVariableLong(VID_NUM_SCHEDULES);
+      m_pItemList->pItems[i].comments = pMsg->GetVariableStr(VID_COMMENTS);
       m_pItemList->pItems[i].ppScheduleList = (TCHAR **)malloc(sizeof(TCHAR *) * m_pItemList->pItems[i].dwNumSchedules);
       for(j = 0, dwId = VID_DCI_SCHEDULE_BASE; j < m_pItemList->pItems[i].dwNumSchedules; j++, dwId++)
          m_pItemList->pItems[i].ppScheduleList[j] = pMsg->GetVariableStr(dwId);
index 4fd7cb3..8fa702f 100644 (file)
@@ -93,7 +93,7 @@ DCItem::DCItem(const DCItem *pSrc) : DCObject(pSrc)
  *    delta_calculation,transformation,template_id,description,instance,
  *    template_item_id,flags,resource_id,proxy_node,base_units,unit_multiplier,
  *    custom_units_name,perftab_settings,system_tag,snmp_port,snmp_raw_value_type,
- *    instd_method,instd_data,instd_filter,samples
+ *    instd_method,instd_data,instd_filter,samples,comments
  */
 DCItem::DCItem(DB_RESULT hResult, int iRow, Template *pNode) : DCObject()
 {
@@ -136,6 +136,7 @@ DCItem::DCItem(DB_RESULT hResult, int iRow, Template *pNode) : DCObject()
        setInstanceFilter(pszTmp);
    free(pszTmp);
        m_sampleCount = DBGetFieldLong(hResult, iRow, 26);
+   m_comments = DBGetField(hResult, iRow, 27, NULL, 0);
 
    // Load last raw value from database
        TCHAR szQuery[256];
@@ -322,7 +323,7 @@ BOOL DCItem::saveToDB(DB_HANDLE hdb)
                  _T("resource_id=?,proxy_node=?,base_units=?,")
                           _T("unit_multiplier=?,custom_units_name=?,perftab_settings=?,")
                      _T("system_tag=?,snmp_port=?,snmp_raw_value_type=?,")
-                                         _T("instd_method=?,instd_data=?,instd_filter=?,samples=? WHERE item_id=?"));
+                                         _T("instd_method=?,instd_data=?,instd_filter=?,samples=?,comments=? WHERE item_id=?"));
        }
    else
        {
@@ -332,8 +333,8 @@ BOOL DCItem::saveToDB(DB_HANDLE hdb)
                  _T("transformation,description,instance,template_item_id,flags,")
                  _T("resource_id,proxy_node,base_units,unit_multiplier,")
                           _T("custom_units_name,perftab_settings,system_tag,snmp_port,snmp_raw_value_type,")
-                                         _T("instd_method,instd_data,instd_filter,samples,item_id) VALUES ")
-                          _T("(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+                                         _T("instd_method,instd_data,instd_filter,samples,comments,item_id) VALUES ")
+                          _T("(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
        }
        if (hStmt == NULL)
                return FALSE;
@@ -367,7 +368,8 @@ BOOL DCItem::saveToDB(DB_HANDLE hdb)
        DBBind(hStmt, 25, DB_SQLTYPE_VARCHAR, m_instanceDiscoveryData, DB_BIND_STATIC);
        DBBind(hStmt, 26, DB_SQLTYPE_VARCHAR, m_instanceFilterSource, DB_BIND_STATIC);
        DBBind(hStmt, 27, DB_SQLTYPE_INTEGER, (INT32)m_sampleCount);
-       DBBind(hStmt, 28, DB_SQLTYPE_INTEGER, m_dwId);
+       DBBind(hStmt, 28, DB_SQLTYPE_INTEGER, m_comments, DB_BIND_STATIC);
+       DBBind(hStmt, 29, DB_SQLTYPE_INTEGER, m_dwId);
 
    BOOL bResult = DBExecute(hStmt);
        DBFreeStatement(hStmt);
index eb2526e..71f35cb 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
 ** NetXMS - Network Management System
 ** Copyright (C) 2003-2014 Victor Kirhenshtein
 **
@@ -167,7 +167,7 @@ Threshold::~Threshold()
  */
 void Threshold::createId()
 {
-   m_id = CreateUniqueId(IDG_THRESHOLD); 
+   m_id = CreateUniqueId(IDG_THRESHOLD);
 }
 
 /**
@@ -179,7 +179,7 @@ BOOL Threshold::saveToDB(DB_HANDLE hdb, UINT32 dwIndex)
        DB_STATEMENT hStmt;
        if (!IsDatabaseRecordExist(hdb, _T("thresholds"), _T("threshold_id"), m_id))
        {
-               hStmt = DBPrepare(hdb,                        
+               hStmt = DBPrepare(hdb,
                        _T("INSERT INTO thresholds (item_id,fire_value,rearm_value,")
                        _T("check_function,check_operation,sample_count,script,event_code,")
                        _T("sequence_number,current_state,rearm_event_code,repeat_interval,")
@@ -188,7 +188,7 @@ BOOL Threshold::saveToDB(DB_HANDLE hdb, UINT32 dwIndex)
        }
        else
        {
-               hStmt = DBPrepare(hdb,                        
+               hStmt = DBPrepare(hdb,
                        _T("UPDATE thresholds SET item_id=?,fire_value=?,rearm_value=?,check_function=?,")
          _T("check_operation=?,sample_count=?,script=?,event_code=?,")
          _T("sequence_number=?,current_state=?,rearm_event_code=?,")
index 7bf30be..e400228 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
 ** NetXMS - Network Management System
 ** Copyright (C) 2003-2013 Victor Kirhenshtein
 **
@@ -53,6 +53,7 @@ DCObject::DCObject()
        m_snmpPort = 0; // use default
    m_transformationScriptSource = NULL;
    m_transformationScript = NULL;
+   m_comments = NULL;
 }
 
 /**
@@ -84,6 +85,7 @@ DCObject::DCObject(const DCObject *pSrc)
        m_dwProxyNode = pSrc->m_dwProxyNode;
        m_pszPerfTabSettings = (pSrc->m_pszPerfTabSettings != NULL) ? _tcsdup(pSrc->m_pszPerfTabSettings) : NULL;
        m_snmpPort = pSrc->m_snmpPort;
+       m_comments = (pSrc->m_comments != NULL) ? _tcsdup(pSrc->m_comments) : NULL;
 
    m_transformationScriptSource = NULL;
    m_transformationScript = NULL;
@@ -108,7 +110,7 @@ DCObject::DCObject(const DCObject *pSrc)
 /**
  * Constructor for creating new DCObject from scratch
  */
-DCObject::DCObject(UINT32 dwId, const TCHAR *szName, int iSource, 
+DCObject::DCObject(UINT32 dwId, const TCHAR *szName, int iSource,
                int iPollingInterval, int iRetentionTime, Template *pNode,
                const TCHAR *pszDescription, const TCHAR *systemTag)
 {
@@ -141,6 +143,7 @@ DCObject::DCObject(UINT32 dwId, const TCHAR *szName, int iSource,
        m_snmpPort = 0; // use default
    m_transformationScriptSource = NULL;
    m_transformationScript = NULL;
+   m_comments = NULL;
 }
 
 /**
@@ -176,8 +179,9 @@ DCObject::DCObject(ConfigEntry *config, Template *owner)
 
        m_transformationScriptSource = NULL;
        m_transformationScript = NULL;
+       m_comments = NULL;
        setTransformationScript(config->getSubEntryValue(_T("transformation")));
-   
+
        if (config->getSubEntryValueAsInt(_T("advancedSchedule")))
                m_flags |= DCF_ADVANCED_SCHEDULE;
 
@@ -214,6 +218,7 @@ DCObject::~DCObject()
       safe_free(m_ppScheduleList);
    }
        safe_free(m_pszPerfTabSettings);
+       safe_free(m_comments);
    MutexDestroy(m_hMutex);
 }
 
@@ -357,7 +362,7 @@ void DCObject::expandMacros(const TCHAR *src, TCHAR *dst, size_t dstLen)
                        }
                }
                temp += rest;
-               
+
                free(head);
                free(rest);
                free(macro);
@@ -740,6 +745,8 @@ void DCObject::createMessage(CSCPMessage *pMsg)
        pMsg->SetVariable(VID_RESOURCE_ID, m_dwResourceId);
        pMsg->SetVariable(VID_AGENT_PROXY, m_dwProxyNode);
        pMsg->SetVariable(VID_SNMP_PORT, m_snmpPort);
+       if (m_comments != NULL)
+               pMsg->SetVariable(VID_COMMENTS, m_comments);
        if (m_pszPerfTabSettings != NULL)
                pMsg->SetVariable(VID_PERFTAB_SETTINGS, m_pszPerfTabSettings);
    pMsg->SetVariable(VID_NUM_SCHEDULES, m_dwNumSchedules);
@@ -769,6 +776,7 @@ void DCObject::updateFromMessage(CSCPMessage *pMsg)
        m_pszPerfTabSettings = pMsg->GetVariableStr(VID_PERFTAB_SETTINGS);
        m_snmpPort = pMsg->GetVariableShort(VID_SNMP_PORT);
    TCHAR *pszStr = pMsg->GetVariableStr(VID_TRANSFORMATION_SCRIPT);
+   m_comments = pMsg->GetVariableStr(VID_COMMENTS);
    setTransformationScript(pszStr);
    safe_free(pszStr);
 
index 0a3ed13..8801ac1 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
 ** NetXMS - Network Management System
 ** Copyright (C) 2003-2014 Victor Kirhenshtein
 **
@@ -94,7 +94,7 @@ INT32 DCTable::columnIdFromName(const TCHAR *name)
                                                DBFreeStatement(hStmt2);
                                        }
                                }
-                               
+
                                DBFreeResult(hResult);
 
                                // Add to cache
@@ -160,7 +160,7 @@ DCTable::DCTable(UINT32 id, const TCHAR *name, int source, int pollingInterval,
  *    item_id,template_id,template_item_id,name,
  *    description,flags,source,snmp_port,polling_interval,retention_time,
  *    status,system_tag,resource_id,proxy_node,perftab_settings,
- *    transformation_script
+ *    transformation_script,comments
  */
 DCTable::DCTable(DB_RESULT hResult, int iRow, Template *pNode) : DCObject()
 {
@@ -180,6 +180,7 @@ DCTable::DCTable(DB_RESULT hResult, int iRow, Template *pNode) : DCObject()
        m_dwProxyNode = DBGetFieldULong(hResult, iRow, 13);
        m_pszPerfTabSettings = DBGetField(hResult, iRow, 14, NULL, 0);
    TCHAR *pszTmp = DBGetField(hResult, iRow, 15, NULL, 0);
+   m_comments = DBGetField(hResult, iRow, 16, NULL, 0);
    setTransformationScript(pszTmp);
    free(pszTmp);
 
@@ -518,14 +519,14 @@ BOOL DCTable::saveToDB(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=? WHERE item_id=?"));
+                                                                         _T("perftab_settings=?,transformation_script=?,comments=? 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,item_id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+                                                                         _T("transformation_script,comments,item_id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
        }
        if (hStmt == NULL)
                return FALSE;
@@ -548,7 +549,8 @@ BOOL DCTable::saveToDB(DB_HANDLE hdb)
        DBBind(hStmt, 14, DB_SQLTYPE_INTEGER, m_dwProxyNode);
        DBBind(hStmt, 15, DB_SQLTYPE_TEXT, m_pszPerfTabSettings, DB_BIND_STATIC);
    DBBind(hStmt, 16, DB_SQLTYPE_TEXT, m_transformationScriptSource, DB_BIND_STATIC);
-       DBBind(hStmt, 17, DB_SQLTYPE_INTEGER, m_dwId);
+   DBBind(hStmt, 17, DB_SQLTYPE_TEXT, m_comments, DB_BIND_STATIC);
+       DBBind(hStmt, 18, DB_SQLTYPE_INTEGER, m_dwId);
 
        BOOL result = DBExecute(hStmt);
        DBFreeStatement(hStmt);
@@ -800,7 +802,7 @@ int DCTable::getColumnDataType(const TCHAR *name)
 {
    int dt = DCI_DT_STRING;
    bool found = false;
-   
+
    lock();
 
    // look in column definition first
@@ -986,7 +988,7 @@ void DCTable::createNXMPRecord(String &str)
        UINT32 i;
 
    lock();
-   
+
    str.addFormattedString(_T("\t\t\t\t<dctable id=\"%d\">\n")
                           _T("\t\t\t\t\t<name>%s</name>\n")
                           _T("\t\t\t\t\t<description>%s</description>\n")
@@ -1002,7 +1004,7 @@ void DCTable::createNXMPRecord(String &str)
                           (int)m_source, m_iPollingInterval, m_iRetentionTime,
                           (const TCHAR *)EscapeStringForXML2(m_systemTag),
                                                                  (m_flags & DCF_ADVANCED_SCHEDULE) ? 1 : 0,
-                                                                 (m_flags & DCF_RAW_VALUE_OCTET_STRING) ? 1 : 0, 
+                                                                 (m_flags & DCF_RAW_VALUE_OCTET_STRING) ? 1 : 0,
                                                                  (int)m_snmpPort);
 
        if (m_transformationScriptSource != NULL)
index 8ca49c3..70e5392 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
 ** NetXMS - Network Management System
 ** Copyright (C) 2003-2014 Victor Kirhenshtein
 **
@@ -351,13 +351,13 @@ bool Template::deleteFromDB(DB_HANDLE hdb)
  */
 void Template::loadItemsFromDB()
 {
-       DB_STATEMENT hStmt = DBPrepare(g_hCoreDB, 
+       DB_STATEMENT hStmt = DBPrepare(g_hCoreDB,
                   _T("SELECT item_id,name,source,datatype,polling_interval,retention_time,")
               _T("status,delta_calculation,transformation,template_id,description,")
               _T("instance,template_item_id,flags,resource_id,")
               _T("proxy_node,base_units,unit_multiplier,custom_units_name,")
                   _T("perftab_settings,system_tag,snmp_port,snmp_raw_value_type,")
-                                 _T("instd_method,instd_data,instd_filter,samples FROM items WHERE node_id=?"));
+                                 _T("instd_method,instd_data,instd_filter,samples,comments FROM items WHERE node_id=?"));
        if (hStmt != NULL)
        {
                DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_dwId);
@@ -372,10 +372,10 @@ void Template::loadItemsFromDB()
                DBFreeStatement(hStmt);
        }
 
-       hStmt = DBPrepare(g_hCoreDB, 
+       hStmt = DBPrepare(g_hCoreDB,
                   _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,transformation_script FROM dc_tables WHERE node_id=?"));
+              _T("status,system_tag,resource_id,proxy_node,perftab_settings,transformation_script,comments FROM dc_tables WHERE node_id=?"));
        if (hStmt != NULL)
        {
                DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_dwId);
@@ -406,7 +406,7 @@ bool Template::addDCObject(DCObject *object, bool alreadyLocked)
    for(i = 0; i < m_dcObjects->size(); i++)
       if (m_dcObjects->get(i)->getId() == object->getId())
          break;   // Object with specified id already exist
-   
+
    if (i == m_dcObjects->size())     // Add new item
    {
                m_dcObjects->add(object);
@@ -1019,7 +1019,7 @@ void Template::prepareForDeletion()
        if (Type() == OBJECT_TEMPLATE)
        {
                UINT32 i;
-       
+
                LockChildList(FALSE);
                for(i = 0; i < m_dwChildCount; i++)
                {
@@ -1061,7 +1061,7 @@ bool Template::isApplicable(Node *node)
 }
 
 /**
- * Get last (current) DCI values. Moved to Template from DataCollectionTarget to allow 
+ * Get last (current) DCI values. Moved to Template from DataCollectionTarget to allow
  * simplified creation of DCI selection dialog in management console. For classes not
  * derived from DataCollectionTarget actual values will always be empty strings
  * with data type DCI_DT_NULL.
@@ -1074,7 +1074,7 @@ UINT32 Template::getLastValues(CSCPMessage *msg, bool objectTooltipOnly)
    for(int i = 0; i < m_dcObjects->size(); i++)
        {
                DCObject *object = m_dcObjects->get(i);
-               if (object->hasValue() && 
+               if (object->hasValue() &&
           _tcsnicmp(object->getDescription(), _T("@system."), 8) &&
           (!objectTooltipOnly || object->isShowOnObjectTooltip()))
                {
index ac680a7..90b0113 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
 ** NetXMS - Network Management System
 ** Copyright (C) 2003-2013 Victor Kirhenshtein
 **
@@ -138,7 +138,7 @@ public:
        int getSampleCount() { return m_sampleCount; }
    const TCHAR *getStringValue() { return m_value.getString(); }
    BOOL isReached() { return m_isReached; }
-       
+
        int getRepeatInterval() { return m_repeatInterval; }
        time_t getLastEventTimestamp() { return m_lastEventTimestamp; }
        int getCurrentSeverity() { return m_currentSeverity; }
@@ -212,6 +212,7 @@ protected:
        TCHAR *m_pszPerfTabSettings;
    TCHAR *m_transformationScriptSource;   // Transformation script (source code)
    NXSL_VM *m_transformationScript;  // Compiled transformation script
+       TCHAR *m_comments;
 
    void lock() { MutexLock(m_hMutex); }
    void unlock() { MutexUnlock(m_hMutex); }
@@ -271,7 +272,7 @@ public:
    void setLastPollTime(time_t tLastPoll) { m_tLastPoll = tLastPoll; }
    void setStatus(int status, bool generateEvent);
    void setBusyFlag(BOOL busy) { m_busy = (BYTE)busy; }
-   void setTemplateId(UINT32 dwTemplateId, UINT32 dwItemId) 
+   void setTemplateId(UINT32 dwTemplateId, UINT32 dwItemId)
          { m_dwTemplateId = dwTemplateId; m_dwTemplateItemId = dwItemId; }
 
    virtual void createMessage(CSCPMessage *pMsg);
@@ -332,7 +333,7 @@ public:
    DCItem();
    DCItem(const DCItem *pItem);
    DCItem(DB_RESULT hResult, int iRow, Template *pNode);
-   DCItem(UINT32 dwId, const TCHAR *szName, int iSource, int iDataType, 
+   DCItem(UINT32 dwId, const TCHAR *szName, int iSource, int iDataType,
           int iPollingInterval, int iRetentionTime, Template *pNode,
           const TCHAR *pszDescription = NULL, const TCHAR *systemTag = NULL);
        DCItem(ConfigEntry *config, Template *owner);
@@ -538,7 +539,7 @@ protected:
 
    bool transform(Table *value);
    void checkThresholds(Table *value);
-   
+
    bool loadThresholds();
    bool saveThresholds(DB_HANDLE hdb);
 
index 17e8adc..3b8ba11 100644 (file)
@@ -388,6 +388,20 @@ static BOOL RecreateTData(const TCHAR *className, bool multipleTables, bool inde
 }
 
 /**
+ * Upgrade from V328 to V329
+ */
+static BOOL H_UpgradeFromV328(int currVersion, int newVersion)
+{
+       //Add column comments to table
+       if (!SQLQuery(_T("ALTER TABLE items ADD comments $SQL:TEXT")))
+      if (!g_bIgnoreErrors)
+         return FALSE;
+
+   CHK_EXEC(SQLQuery(_T("UPDATE metadata SET var_value='329' WHERE var_name='SchemaVersion'")));
+   return TRUE;
+}
+
+/**
  * Upgrade from V327 to V328
  */
 static BOOL H_UpgradeFromV327(int currVersion, int newVersion)
@@ -8022,6 +8036,7 @@ static struct
    { 325, 326, H_UpgradeFromV325 },
    { 326, 327, H_UpgradeFromV326 },
    { 327, 328, H_UpgradeFromV327 },
+   { 328, 329, H_UpgradeFromV328 },
    { 0, 0, NULL }
 };
 
index 6391a59..5372d69 100644 (file)
               class="org.netxms.ui.eclipse.datacollection.propertypages.GeneralTable"
               id="org.netxms.ui.eclipse.datacollection.propertypages.GeneralTable#1"
               name="%page.name.General">
+            <enabledWhen>
+               <instanceof
+                    value="org.netxms.client.datacollection.DataCollectionTable">
+               </instanceof>
+            </enabledWhen>
+        </page>
+        <page
+              class="org.netxms.ui.eclipse.datacollection.propertypages.Comments"
+              id="org.netxms.ui.eclipse.datacollection.propertypages.Comments"
+              name="Comments">
            <enabledWhen>
               <instanceof
-                    value="org.netxms.client.datacollection.DataCollectionTable">
+                    value="org.netxms.client.datacollection.DataCollectionObject">
               </instanceof>
            </enabledWhen>
         </page>
diff --git a/webui/webapp/DataCollection/src/org/netxms/ui/eclipse/datacollection/propertypages/Comments.java b/webui/webapp/DataCollection/src/org/netxms/ui/eclipse/datacollection/propertypages/Comments.java
new file mode 100644 (file)
index 0000000..72572de
--- /dev/null
@@ -0,0 +1,122 @@
+/**
+ * NetXMS - open source network management system
+ * Copyright (C) 2003-2013 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.
+ */
+package org.netxms.ui.eclipse.datacollection.propertypages;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.PropertyPage;
+import org.netxms.client.datacollection.DataCollectionObject;
+import org.netxms.ui.eclipse.datacollection.api.DataCollectionObjectEditor;
+import org.netxms.ui.eclipse.tools.WidgetHelper;
+
+/**
+ * "Comments" property page for NetXMS object
+ *
+ */
+public class Comments extends PropertyPage
+{
+   private DataCollectionObjectEditor editor;
+   private DataCollectionObject dci;
+       private Text comments;
+       private String initialComments;
+       
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
+        */
+       @Override
+       protected Control createContents(Composite parent)
+       {
+               Composite dialogArea = new Composite(parent, SWT.NONE);
+               
+               editor = (DataCollectionObjectEditor)getElement().getAdapter(DataCollectionObjectEditor.class);
+      dci = editor.getObject();
+      
+               initialComments = dci.getComments();
+               if (initialComments == null)
+                       initialComments = ""; //$NON-NLS-1$
+
+               GridLayout layout = new GridLayout();
+               layout.verticalSpacing = WidgetHelper.OUTER_SPACING;
+               layout.marginWidth = 0;
+               layout.marginHeight = 0;
+      dialogArea.setLayout(layout);
+
+      comments = new Text(dialogArea, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+               comments.setText(initialComments);
+
+               GridData gd = new GridData();
+               gd.grabExcessHorizontalSpace = true;
+               gd.grabExcessVerticalSpace = true;
+               gd.horizontalAlignment = SWT.FILL;
+               gd.verticalAlignment = SWT.FILL;
+               gd.widthHint = 0;
+      gd.heightHint = 0;
+               comments.setLayoutData(gd);
+               
+               return dialogArea;
+       }
+
+       /**
+        * Apply changes
+        * 
+        * @param isApply true if update operation caused by "Apply" button
+        */
+       protected void applyChanges(final boolean isApply)
+       {
+               if (initialComments.equals(comments.getText()))
+                       return; // Nothing to apply
+               
+               final String newComments = new String(comments.getText());
+               dci.setComments(newComments);
+               editor.modify();
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.preference.PreferencePage#performOk()
+        */
+       @Override
+       public boolean performOk()
+       {
+               applyChanges(false);
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.preference.PreferencePage#performApply()
+        */
+       @Override
+       protected void performApply()
+       {
+               applyChanges(true);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
+        */
+       @Override
+       protected void performDefaults()
+       {
+               super.performDefaults();
+               comments.setText(""); //$NON-NLS-1$
+       }
+}