StringMap implementation now uses hash
authorVictor Kirhenshtein <victor@netxms.org>
Thu, 18 Sep 2014 15:24:30 +0000 (18:24 +0300)
committerVictor Kirhenshtein <victor@netxms.org>
Thu, 18 Sep 2014 15:24:30 +0000 (18:24 +0300)
34 files changed:
include/nms_threads.h
include/nms_util.h
include/nxsl_classes.h
src/agent/core/epp.cpp
src/agent/subagents/oracle/db.cpp
src/agent/tools/nxapush/nxapush.cpp
src/libnetxms/Makefile.am
src/libnetxms/config.cpp
src/libnetxms/libnetxms.vcproj
src/libnetxms/strmap-internal.h [new file with mode: 0644]
src/libnetxms/strmap.cpp
src/libnetxms/strmapbase.cpp
src/libnxcl/epp.cpp
src/libnxcl/objects.cpp
src/libnxsl/variable.cpp
src/libnxsl/vm.cpp
src/server/core/ap_jobs.cpp
src/server/core/dcitem.cpp
src/server/core/epp.cpp
src/server/core/events.cpp
src/server/core/ldap.cpp
src/server/core/main.cpp
src/server/core/mt.cpp
src/server/core/netobj.cpp
src/server/core/node.cpp
src/server/core/situation.cpp
src/server/core/userdb.cpp
src/server/core/userdb_objects.cpp
src/server/drivers/lib/avaya-ers/avaya-ers.cpp
src/server/include/nms_core.h
src/server/include/nms_dcoll.h
src/server/include/nms_users.h
src/server/tools/driverloader/loader.cpp
tests/test-libnetxms/test-libnetxms.cpp

index 5dac519..48090d5 100644 (file)
@@ -233,10 +233,10 @@ inline void ConditionPulse(CONDITION hCond)
    PulseEvent(hCond);
 }
 
-inline BOOL ConditionWait(CONDITION hCond, UINT32 dwTimeOut)
+inline bool ConditionWait(CONDITION hCond, UINT32 dwTimeOut)
 {
        if (hCond == INVALID_CONDITION_HANDLE)
-               return FALSE;
+               return false;
    return WaitForSingleObject(hCond, dwTimeOut) == WAIT_OBJECT_0;
 }
 
@@ -451,9 +451,9 @@ inline void ConditionPulse(CONDITION cond)
        }
 }
 
-inline BOOL ConditionWait(CONDITION cond, UINT32 dwTimeOut)
+inline bool ConditionWait(CONDITION cond, UINT32 dwTimeOut)
 {
-       BOOL ret = FALSE;
+       bool ret = false;
 
        if (cond != NULL)
        {
@@ -462,7 +462,7 @@ inline BOOL ConditionWait(CONDITION cond, UINT32 dwTimeOut)
                pth_mutex_acquire(&cond->mutex, FALSE, NULL);
       if (cond->isSet)
       {
-         ret = TRUE;
+         ret = true;
          if (!cond->broadcast)
             cond->isSet = FALSE;
       }
@@ -485,7 +485,7 @@ inline BOOL ConditionWait(CONDITION cond, UINT32 dwTimeOut)
                   {
             if (!cond->broadcast)
                cond->isSet = FALSE;
-                          ret = TRUE;
+                          ret = true;
                   }
       }
 
@@ -810,9 +810,9 @@ inline void ConditionPulse(CONDITION cond)
        }
 }
 
-inline BOOL ConditionWait(CONDITION cond, UINT32 dwTimeOut)
+inline bool ConditionWait(CONDITION cond, UINT32 dwTimeOut)
 {
-       BOOL ret = FALSE;
+       bool ret = FALSE;
 
        if (cond != NULL)
        {
@@ -821,7 +821,7 @@ inline BOOL ConditionWait(CONDITION cond, UINT32 dwTimeOut)
                pthread_mutex_lock(&cond->mutex);
       if (cond->isSet)
       {
-         ret = TRUE;
+         ret = true;
          if (!cond->broadcast)
             cond->isSet = FALSE;
       }
@@ -868,7 +868,7 @@ inline BOOL ConditionWait(CONDITION cond, UINT32 dwTimeOut)
                   {
             if (!cond->broadcast)
                cond->isSet = FALSE;
-                          ret = TRUE;
+                          ret = true;
                   }
       }
 
index d198803..be5e428 100644 (file)
@@ -278,6 +278,11 @@ public:
        void shrink(int chars = 1);
 };
 
+/**
+ * Entry of string map
+ */
+struct StringMapEntry;
+
 /**
  * String maps base class
  */
@@ -285,13 +290,12 @@ class LIBNETXMS_EXPORTABLE StringMapBase
 {
 protected:
        int m_size;
-       TCHAR **m_keys;
-       void **m_values;
+   StringMapEntry *m_data;
        bool m_objectOwner;
    bool m_ignoreCase;
        void (*m_objectDestructor)(void *);
 
-       UINT32 find(const TCHAR *key);
+       StringMapEntry *find(const TCHAR *key);
        void setObject(TCHAR *key, void *value, bool keyPreAlloc);
        void *getObject(const TCHAR *key);
        void destroyObject(void *object) { if (object != NULL) m_objectDestructor(object); }
@@ -307,9 +311,16 @@ public:
        void clear();
 
        int size() { return m_size; }
-       const TCHAR *getKeyByIndex(int idx) { return ((idx >= 0) && (idx < m_size)) ? CHECK_NULL_EX(m_keys[idx]) : NULL; }
+   bool contains(const TCHAR *key) { return find(key) != NULL; }
+
+   bool forEach(bool (*cb)(const TCHAR *, const void *, void *), void *userData);
 };
 
+/**
+ * NXCP message class
+ */
+class CSCPMessage;
+
 /**
  * String map class
  */
@@ -332,7 +343,7 @@ public:
        UINT32 getULong(const TCHAR *key, UINT32 defaultValue);
        bool getBoolean(const TCHAR *key, bool defaultValue);
 
-       const TCHAR *getValueByIndex(int idx) { return ((idx >= 0) && (idx < m_size)) ? CHECK_NULL_EX((TCHAR *)m_values[idx]) : NULL; }
+   void fillMessage(CSCPMessage *msg, UINT32 sizeFieldId, UINT32 baseFieldId);
 };
 
 /**
@@ -348,7 +359,6 @@ public:
 
        void set(const TCHAR *key, T *object) { setObject((TCHAR *)key, (void *)object, false); }
        T *get(const TCHAR *key) { return (T*)getObject(key); }
-       T *getValueByIndex(int idx) { return ((idx >= 0) && (idx < m_size)) ? (T *)m_values[idx] : NULL; }
 };
 
 /**
index 6fbfcee..519047d 100644 (file)
@@ -544,6 +544,9 @@ struct NXSL_CatchPoint
  */
 class LIBNXSL_EXPORTABLE NXSL_VM
 {
+private:
+   static bool createConstantsCallback(const TCHAR *key, const void *value, void *data);
+
 protected:
    NXSL_Environment *m_env;
        void *m_userData;
@@ -557,9 +560,9 @@ protected:
    NXSL_Stack *m_catchStack;
    int m_nBindPos;
 
-   NXSL_VariableSystem *m_pConstants;
-   NXSL_VariableSystem *m_pGlobals;
-   NXSL_VariableSystem *m_pLocals;
+   NXSL_VariableSystem *m_constants;
+   NXSL_VariableSystem *m_globals;
+   NXSL_VariableSystem *m_locals;
 
    ObjectArray<NXSL_Function> *m_functions;
    ObjectArray<NXSL_Module> *m_modules;
@@ -591,7 +594,7 @@ public:
    void loadModule(NXSL_Program *module, const TCHAR *name);
 
        void setGlobalVariable(const TCHAR *pszName, NXSL_Value *pValue);
-       NXSL_Variable *findGlobalVariable(const TCHAR *pszName) { return m_pGlobals->find(pszName); }
+       NXSL_Variable *findGlobalVariable(const TCHAR *pszName) { return m_globals->find(pszName); }
 
    bool load(NXSL_Program *program);
    bool run(ObjectArray<NXSL_Value> *args, NXSL_VariableSystem *pUserLocals = NULL,
index 13842b7..e9005d1 100644 (file)
@@ -81,14 +81,11 @@ LONG ParamProvider::getValue(const TCHAR *name, TCHAR *buffer)
 
        lock();
 
-       for(int i = 0; i < m_parameters->size(); i++)
-       {
-               if (!_tcsicmp(m_parameters->getKeyByIndex(i), name))
-               {
-                       nx_strncpy(buffer, m_parameters->getValueByIndex(i), MAX_RESULT_LENGTH);
-                       rc = SYSINFO_RC_SUCCESS;
-                       break;
-               }
+   const TCHAR *value = m_parameters->get(name);
+   if (value != NULL)
+   {
+               nx_strncpy(buffer, value, MAX_RESULT_LENGTH);
+               rc = SYSINFO_RC_SUCCESS;
        }
 
        unlock();
@@ -147,24 +144,53 @@ void ParamProvider::poll()
        m_lastPollTime = time(NULL);
 }
 
+/**
+ * Parameter list callback data
+ */
+struct ParameterListCallbackData
+{
+   CSCPMessage *msg;
+   UINT32 id;
+   UINT32 count;
+};
+
+/**
+ * Parameter list callback
+ */
+static bool ParameterListCallback(const TCHAR *key, const void *value, void *data)
+{
+       ((ParameterListCallbackData *)data)->msg->SetVariable(((ParameterListCallbackData *)data)->id++, key);
+       ((ParameterListCallbackData *)data)->msg->SetVariable(((ParameterListCallbackData *)data)->id++, _T(""));
+       ((ParameterListCallbackData *)data)->msg->SetVariable(((ParameterListCallbackData *)data)->id++, (WORD)DCI_DT_STRING);
+       ((ParameterListCallbackData *)data)->count++;
+   return true;
+}
+
 /**
  * List available parameters
  */
 void ParamProvider::listParameters(CSCPMessage *msg, UINT32 *baseId, UINT32 *count)
 {
-       UINT32 id = *baseId;
+   ParameterListCallbackData data;
+   data.msg = msg;
+   data.id = *baseId;
+   data.count = 0;
 
        lock();
-       for(int i = 0; i < m_parameters->size(); i++)
-       {
-               msg->SetVariable(id++, m_parameters->getKeyByIndex(i));
-               msg->SetVariable(id++, _T(""));
-               msg->SetVariable(id++, (WORD)DCI_DT_STRING);
-               (*count)++;
-       }
+   m_parameters->forEach(ParameterListCallback, &data);
        unlock();
 
-       *baseId = id;
+       *baseId = data.id;
+   *count += data.count;
+}
+
+/**
+ * Parameter list callback
+ */
+static bool ParameterListCallback2(const TCHAR *key, const void *value, void *data)
+{
+   ((StringList *)data)->add(key);
+   return true;
 }
 
 /**
@@ -173,10 +199,7 @@ void ParamProvider::listParameters(CSCPMessage *msg, UINT32 *baseId, UINT32 *cou
 void ParamProvider::listParameters(StringList *list)
 {
        lock();
-       for(int i = 0; i < m_parameters->size(); i++)
-       {
-               list->add(m_parameters->getKeyByIndex(i));
-       }
+   m_parameters->forEach(ParameterListCallback2, list);
        unlock();
 }
 
index 62bbe15..e8ce25c 100644 (file)
@@ -250,6 +250,35 @@ bool DatabaseInstance::getData(const TCHAR *tag, TCHAR *value)
    return success;
 }
 
+/**
+ * Tag list callback data
+ */
+struct TagListCallbackData
+{
+   regex_t preg;
+   StringList *list;
+};
+
+/**
+ * Tag list callback
+ */
+static bool TagListCallback(const TCHAR *key, const void *value, void *data)
+{
+   regmatch_t pmatch[16];
+   if (_tregexec(&(((TagListCallbackData *)data)->preg), key, 16, pmatch, 0) == 0) // MATCH
+   {
+      if (pmatch[1].rm_so != -1)
+      {
+         size_t slen = pmatch[1].rm_eo - pmatch[1].rm_so;
+         TCHAR *s = (TCHAR *)malloc((slen + 1) * sizeof(TCHAR));
+         memcpy(s, &key[pmatch[1].rm_so], slen * sizeof(TCHAR));
+         s[slen] = 0;
+         ((TagListCallbackData *)data)->list->addPreallocated(s);
+      }
+   }
+   return true;
+}
+
 /**
  * Get list of tags matching given pattern from collected data
  */
@@ -260,27 +289,11 @@ bool DatabaseInstance::getTagList(const TCHAR *pattern, StringList *value)
    MutexLock(m_dataLock);
    if (m_data != NULL)
    {
-      regex_t preg;
-          if (_tregcomp(&preg, pattern, REG_EXTENDED | REG_ICASE) == 0)
+      TagListCallbackData data;
+          if (_tregcomp(&data.preg, pattern, REG_EXTENDED | REG_ICASE) == 0)
           {
-         for(int i = 0; i < m_data->size(); i++)
-         {
-            const TCHAR *tag = m_data->getKeyByIndex(i);
-            regmatch_t pmatch[16];
-                  if (_tregexec(&preg, tag, 16, pmatch, 0) == 0) // MATCH
-            {
-               if (pmatch[1].rm_so != -1)
-               {
-                  size_t slen = pmatch[1].rm_eo - pmatch[1].rm_so;
-                  TCHAR *s = (TCHAR *)malloc((slen + 1) * sizeof(TCHAR));
-                  memcpy(s, &tag[pmatch[1].rm_so], slen * sizeof(TCHAR));
-                  s[slen] = 0;
-                  value->addPreallocated(s);
-               }
-            }
-         }
-
-         regfree(&preg);
+         m_data->forEach(TagListCallback, &data);
+         regfree(&data.preg);
          success = true;
           }
    }
index 7786769..2432bff 100644 (file)
@@ -341,14 +341,7 @@ static BOOL Send()
        CSCPMessage msg;
        msg.SetCode(CMD_PUSH_DCI_DATA);
    msg.SetVariable(VID_OBJECT_ID, optObjectId);
-   msg.SetVariable(VID_NUM_ITEMS, s_data->size());
-       for(int i = 0, varId = VID_PUSH_DCI_DATA_BASE; i < s_data->size(); i++)
-       {
-               msg.SetVariable(varId++, s_data->getKeyByIndex(i));
-               msg.SetVariable(varId++, s_data->getValueByIndex(i));
-               if (optVerbose > 2)
-                       _tprintf(_T("Record #%d: \"%s\" = \"%s\"\n"), (int)i + 1, s_data->getKeyByIndex(i), s_data->getValueByIndex(i));
-       }
+   s_data->fillMessage(&msg, VID_NUM_ITEMS, VID_PUSH_DCI_DATA_BASE);
 
        // Send response to pipe
        CSCP_MESSAGE *rawMsg = msg.createMessage();
index 6060d7f..db846a0 100644 (file)
@@ -30,7 +30,7 @@ endif
 
 EXTRA_DIST = \
        libnetxms.vcproj \
-       libnetxms.h ice.h md5.h sha1.h uuidP.h \
+       libnetxms.h ice.h md5.h sha1.h strmap-internal.h uuidP.h \
        dir.c dirw.c \
        seh.cpp StackWalker.cpp StackWalker.h \
        ldcw.s
index 804b377..cacb942 100644 (file)
@@ -580,6 +580,16 @@ void ConfigEntry::print(FILE *file, int level)
       _tprintf(_T("%*svalue: %s\n"), level * 4 + 2, _T(""), m_values[i]);
 }
 
+/**
+ * Add attribute
+ */
+static bool AddAttribute(const TCHAR *key, const void *value, void *userData)
+{
+   if (_tcscmp(key, _T("id")))
+      ((String *)userData)->addFormattedString(_T(" %s=\"%s\""), key, (const TCHAR *)value);
+   return true;
+}
+
 /**
  * Create XML element(s) from config entry
  */
@@ -594,11 +604,7 @@ void ConfigEntry::createXml(String &xml, int level)
       xml.addFormattedString(_T("%*s<%s"), level * 4, _T(""), name);
    else
       xml.addFormattedString(_T("%*s<%s id=\"%d\""), level * 4, _T(""), name, m_id);
-   for(int j = 0; j < m_attributes.size(); j++)
-   {
-      if (_tcscmp(m_attributes.getKeyByIndex(j), _T("id")))
-         xml.addFormattedString(_T(" %s=\"%s\""), m_attributes.getKeyByIndex(j), m_attributes.getValueByIndex(j));
-   }
+   m_attributes.forEach(AddAttribute, &xml);
    xml += _T(">");
 
    if (m_first != NULL)
index 275c0ca..de64d41 100644 (file)
                                RelativePath=".\StackWalker.h"
                                >
                        </File>
+                       <File
+                               RelativePath=".\strmap-internal.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\include\unicode.h"
                                >
diff --git a/src/libnetxms/strmap-internal.h b/src/libnetxms/strmap-internal.h
new file mode 100644 (file)
index 0000000..baa0d63
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+** NetXMS - Network Management System
+** Copyright (C) 2003-2014 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.
+**
+** File: strmap-internal.h
+**
+**/
+
+#ifndef _strmap_internal_h_
+#define _strmap_internal_h_
+
+#include <uthash.h>
+
+/**
+ * Entry
+ */
+struct StringMapEntry
+{
+   UT_hash_handle hh;
+   TCHAR *key;
+   void *value;
+};
+
+#endif
index ea546fb..14ea880 100644 (file)
 **/
 
 #include "libnetxms.h"
+#include "strmap-internal.h"
 
 /**
  * Copy constructor
  */
 StringMap::StringMap(const StringMap &src) : StringMapBase(true)
 {
-       m_size = src.m_size;
+       m_size = 0;
        m_objectOwner = src.m_objectOwner;
-       m_keys = (TCHAR **)malloc(sizeof(TCHAR *) * m_size);
-       m_values = (void **)malloc(sizeof(void *) * m_size);
-       for(int i = 0; i < m_size; i++)
-       {
-               m_keys[i] = _tcsdup(src.m_keys[i]);
-               m_values[i] = _tcsdup((TCHAR *)src.m_values[i]);
-       }
+   m_ignoreCase = src.m_ignoreCase;
+   m_objectDestructor = src.m_objectDestructor;
+
+   StringMapEntry *entry, *tmp;
+   HASH_ITER(hh, src.m_data, entry, tmp)
+   {
+      setObject(_tcsdup(entry->key), _tcsdup((TCHAR *)entry->value), true);
+   }
 }
 
 /**
@@ -53,14 +55,15 @@ StringMap::~StringMap()
 StringMap& StringMap::operator =(const StringMap &src)
 {
        clear();
-       m_size = src.m_size;
-       m_keys = (TCHAR **)malloc(sizeof(TCHAR *) * m_size);
-       m_values = (void **)malloc(sizeof(void *) * m_size);
-       for(int i = 0; i < m_size; i++)
-       {
-               m_keys[i] = _tcsdup(src.m_keys[i]);
-               m_values[i] = _tcsdup((TCHAR *)src.m_values[i]);
-       }
+       m_objectOwner = src.m_objectOwner;
+   m_ignoreCase = src.m_ignoreCase;
+   m_objectDestructor = src.m_objectDestructor;
+
+   StringMapEntry *entry, *tmp;
+   HASH_ITER(hh, src.m_data, entry, tmp)
+   {
+      setObject(_tcsdup(entry->key), _tcsdup((TCHAR *)entry->value), true);
+   }
        return *this;
 }
 
@@ -69,8 +72,11 @@ StringMap& StringMap::operator =(const StringMap &src)
  */
 void StringMap::addAll(StringMap *src)
 {
-   for(int i = 0; i < src->m_size; i++)
-      set(src->m_keys[i], (TCHAR *)src->m_values[i]);
+   StringMapEntry *entry, *tmp;
+   HASH_ITER(hh, src->m_data, entry, tmp)
+   {
+      setObject(_tcsdup(entry->key), _tcsdup((TCHAR *)entry->value), true);
+   }
 }
 
 /**
@@ -109,3 +115,18 @@ bool StringMap::getBoolean(const TCHAR *key, bool defaultValue)
                return true;
        return (_tcstoul(value, NULL, 0) != 0) ? true : false;
 }
+
+/**
+ * Fill NXCP message with map data
+ */
+void StringMap::fillMessage(CSCPMessage *msg, UINT32 sizeFieldId, UINT32 baseFieldId)
+{
+   msg->SetVariable(sizeFieldId, (UINT32)m_size);
+   UINT32 id = baseFieldId;
+   StringMapEntry *entry, *tmp;
+   HASH_ITER(hh, m_data, entry, tmp)
+   {
+      msg->SetVariable(id++, entry->key);
+      msg->SetVariable(id++, (TCHAR *)entry->value);
+   }
+}
index 1d605ea..35dfa54 100644 (file)
@@ -1,7 +1,7 @@
 /* 
 ** NetXMS - Network Management System
 ** NetXMS Foundation Library
-** Copyright (C) 2003-2013 Victor Kirhenshtein
+** Copyright (C) 2003-2014 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published
 ** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 **
-** File: strmap.cpp
+** File: strmapbase.cpp
 **
 **/
 
 #include "libnetxms.h"
+#include "strmap-internal.h"
 
 /**
  * Standard object destructor
@@ -37,8 +38,7 @@ static void ObjectDestructor(void *object)
 StringMapBase::StringMapBase(bool objectOwner)
 {
        m_size = 0;
-       m_keys = NULL;
-       m_values = NULL;
+       m_data = NULL;
        m_objectOwner = objectOwner;
    m_ignoreCase = true;
        m_objectDestructor = ObjectDestructor;
@@ -57,31 +57,39 @@ StringMapBase::~StringMapBase()
  */
 void StringMapBase::clear()
 {
-       for(int i = 0; i < m_size; i++)
-       {
-               safe_free(m_keys[i]);
-               if (m_objectOwner)
-                       destroyObject(m_values[i]);
-       }
+   StringMapEntry *entry, *tmp;
+   HASH_ITER(hh, m_data, entry, tmp)
+   {
+      HASH_DEL(m_data, entry);
+      free(entry->key);
+      destroyObject(entry->value);
+      free(entry);
+   }
        m_size = 0;
-       safe_free_and_null(m_keys);
-       safe_free_and_null(m_values);
 }
 
 /**
  * Find entry index by key
  */
-UINT32 StringMapBase::find(const TCHAR *key)
+StringMapEntry *StringMapBase::find(const TCHAR *key)
 {
        if (key == NULL)
-               return INVALID_INDEX;
+               return NULL;
 
-       for(int i = 0; i < m_size; i++)
-       {
-      if (m_ignoreCase ? !_tcsicmp(key, m_keys[i]) : !_tcscmp(key, m_keys[i]))
-                       return i;
-       }
-       return INVALID_INDEX;
+   StringMapEntry *entry;
+   int keyLen = (int)(_tcslen(key) * sizeof(TCHAR));
+   if (m_ignoreCase)
+   {
+      TCHAR *ukey = (TCHAR *)alloca(keyLen + sizeof(TCHAR));
+      memcpy(ukey, key, keyLen + sizeof(TCHAR));
+      _tcsupr(ukey);
+      HASH_FIND(hh, m_data, ukey, keyLen, entry);
+   }
+   else
+   {
+      HASH_FIND(hh, m_data, key, keyLen, entry);
+   }
+   return entry;
 }
 
 /**
@@ -92,21 +100,24 @@ void StringMapBase::setObject(TCHAR *key, void *value, bool keyPreAllocated)
    if (key == NULL)
       return;
 
-       UINT32 index = find(key);
-       if (index != INVALID_INDEX)
+       StringMapEntry *entry = find(key);
+       if (entry != NULL)
        {
                if (keyPreAllocated)
                        free(key);
                if (m_objectOwner)
-                       destroyObject(m_values[index]);
-               m_values[index] = value;
+         destroyObject(entry->value);
+      entry->value = value;
        }
        else
        {
-               m_keys = (TCHAR **)realloc(m_keys, (m_size + 1) * sizeof(TCHAR *));
-               m_values = (void **)realloc(m_values, (m_size + 1) * sizeof(void *));
-               m_keys[m_size] = keyPreAllocated ? key : _tcsdup(key);
-               m_values[m_size] = value;
+      entry = (StringMapEntry *)malloc(sizeof(StringMapEntry));
+      entry->key = keyPreAllocated ? key : _tcsdup(key);
+      if (m_ignoreCase)
+         _tcsupr(entry->key);
+      int keyLen = (int)(_tcslen(key) * sizeof(TCHAR));
+      entry->value = value;
+      HASH_ADD_KEYPTR(hh, m_data, entry->key, keyLen, entry);
                m_size++;
        }
 }
@@ -116,10 +127,8 @@ void StringMapBase::setObject(TCHAR *key, void *value, bool keyPreAllocated)
  */
 void *StringMapBase::getObject(const TCHAR *key)
 {
-       UINT32 index;
-
-       index = find(key);
-       return (index != INVALID_INDEX) ? m_values[index] : NULL;
+       StringMapEntry *entry = find(key);
+   return (entry != NULL) ? entry->value : NULL;
 }
 
 /**
@@ -127,16 +136,32 @@ void *StringMapBase::getObject(const TCHAR *key)
  */
 void StringMapBase::remove(const TCHAR *key)
 {
-       UINT32 index;
-
-       index = find(key);
-       if (index != INVALID_INDEX)
-       {
-               safe_free(m_keys[index]);
+   StringMapEntry *entry = find(key);
+   if (entry != NULL)
+   {
+      free(entry->key);
                if (m_objectOwner)
-                       destroyObject(m_values[index]);
-               m_size--;
-               memmove(&m_keys[index], &m_keys[index + 1], sizeof(TCHAR *) * (m_size - index));
-               memmove(&m_values[index], &m_values[index + 1], sizeof(void *) * (m_size - index));
-       }
+         destroyObject(entry->value);
+      free(entry);
+      m_size--;
+   }
+}
+
+/**
+ * Enumerate entries
+ * Returns true if whole map was enumerated and false if enumeration was aborted by callback.
+ */
+bool StringMapBase::forEach(bool (*cb)(const TCHAR *, const void *, void *), void *userData)
+{
+   bool result = true;
+   StringMapEntry *entry, *tmp;
+   HASH_ITER(hh, m_data, entry, tmp)
+   {
+      if (!cb(entry->key, entry->value, userData))
+      {
+         result = false;
+         break;
+      }
+   }
+   return result;
 }
index cb6345b..17cd9af 100644 (file)
@@ -223,25 +223,21 @@ UINT32 LIBNXCL_EXPORTABLE NXCOpenEventPolicy(NXC_SESSION hSession, NXC_EPP **ppE
    return dwRetCode;
 }
 
-
-//
-// Close event policy (without saving)
-//
-
+/**
+ * Close event policy (without saving)
+ */
 UINT32 LIBNXCL_EXPORTABLE NXCCloseEventPolicy(NXC_SESSION hSession)
 {
    return ((NXCL_Session *)hSession)->SimpleCommand(CMD_CLOSE_EPP);
 }
 
-
-//
-// Save (and install) new event policy
-//
-
+/**
+ * Save (and install) new event policy
+ */
 UINT32 LIBNXCL_EXPORTABLE NXCSaveEventPolicy(NXC_SESSION hSession, NXC_EPP *pEventPolicy)
 {
    CSCPMessage msg;
-   UINT32 i, j, id, count, dwRqId, dwRetCode;
+   UINT32 i, dwRqId, dwRetCode;
 
    dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
 
@@ -284,13 +280,14 @@ UINT32 LIBNXCL_EXPORTABLE NXCSaveEventPolicy(NXC_SESSION hSession, NXC_EPP *pEve
                        msg.SetVariable(VID_ALARM_TIMEOUT_EVENT, pEventPolicy->pRuleList[i].dwAlarmTimeoutEvent);
                        msg.SetVariable(VID_SITUATION_ID, pEventPolicy->pRuleList[i].dwSituationId);
                        msg.SetVariable(VID_SITUATION_INSTANCE, pEventPolicy->pRuleList[i].szSituationInstance);
-                       count = (pEventPolicy->pRuleList[i].pSituationAttrList != NULL) ? pEventPolicy->pRuleList[i].pSituationAttrList->size() : 0;
-                       msg.SetVariable(VID_SITUATION_NUM_ATTRS, count);
-                       for(j = 0, id = VID_SITUATION_ATTR_LIST_BASE; j < count; j++)
-                       {
-                               msg.SetVariable(id++, pEventPolicy->pRuleList[i].pSituationAttrList->getKeyByIndex(j));
-                               msg.SetVariable(id++, pEventPolicy->pRuleList[i].pSituationAttrList->getValueByIndex(j));
-                       }
+         if (pEventPolicy->pRuleList[i].pSituationAttrList != NULL)
+         {
+            pEventPolicy->pRuleList[i].pSituationAttrList->fillMessage(&msg, VID_SITUATION_NUM_ATTRS, VID_SITUATION_ATTR_LIST_BASE);
+         }
+         else
+         {
+                       msg.SetVariable(VID_SITUATION_NUM_ATTRS, (UINT32)0);
+         }
 
          ((NXCL_Session *)hSession)->SendMsg(&msg);
       }
index 42b5934..4720159 100644 (file)
@@ -1013,12 +1013,7 @@ UINT32 LIBNXCL_EXPORTABLE NXCModifyObject(NXC_SESSION hSession, NXC_OBJECT_UPDAT
    }
    if (pUpdate->qwFlags & OBJ_UPDATE_CUSTOM_ATTRS)
    {
-      msg.SetVariable(VID_NUM_CUSTOM_ATTRIBUTES, pUpdate->pCustomAttrs->size());
-      for(i = 0, dwId1 = VID_CUSTOM_ATTRIBUTES_BASE; i < pUpdate->pCustomAttrs->size(); i++)
-      {
-         msg.SetVariable(dwId1++, pUpdate->pCustomAttrs->getKeyByIndex(i));
-         msg.SetVariable(dwId1++, pUpdate->pCustomAttrs->getValueByIndex(i));
-      }
+      pUpdate->pCustomAttrs->fillMessage(&msg, VID_NUM_CUSTOM_ATTRIBUTES, VID_CUSTOM_ATTRIBUTES_BASE);
    }
    if (pUpdate->qwFlags & OBJ_UPDATE_AUTOBIND)
    {
index ae54de7..c05ef3f 100644 (file)
@@ -111,18 +111,21 @@ void NXSL_VariableSystem::merge(NXSL_VariableSystem *src)
 }
 
 /**
- * Add all values
+ * Callback for adding variables
+ */
+static bool AddVariableCallback(const TCHAR *key, const void *value, void *data)
+{
+   if (((NXSL_VariableSystem *)data)->find(key) == NULL)
+      ((NXSL_VariableSystem *)data)->create(key, new NXSL_Value((NXSL_Value *)value));
+   return true;
+}
+
+/**
+ * Add all values from given map
  */
 void NXSL_VariableSystem::addAll(StringObjectMap<NXSL_Value> *src)
 {
-       for(int i = 0; i < src->size(); i++)
-       {
-      const TCHAR *name = src->getKeyByIndex(i);
-      if (find(name) == NULL)
-               {
-         create(name, new NXSL_Value(src->getValueByIndex(i)));
-               }
-       }
+   src->forEach(AddVariableCallback, this);
 }
 
 /**
index d50b5dd..ee13155 100644 (file)
@@ -130,9 +130,9 @@ NXSL_VM::NXSL_VM(NXSL_Environment *env)
    m_errorCode = 0;
    m_errorLine = 0;
    m_errorText = NULL;
-   m_pConstants = new NXSL_VariableSystem(true);
-   m_pGlobals = new NXSL_VariableSystem(false);
-   m_pLocals = NULL;
+   m_constants = new NXSL_VariableSystem(true);
+   m_globals = new NXSL_VariableSystem(false);
+   m_locals = NULL;
    m_functions = NULL;
    m_modules = new ObjectArray<NXSL_Module>(4, 4, true);
    m_dwSubLevel = 0;    // Level of current subroutine
@@ -152,9 +152,9 @@ NXSL_VM::~NXSL_VM()
    delete m_codeStack;
    delete m_catchStack;
 
-   delete m_pConstants;
-   delete m_pGlobals;
-   delete m_pLocals;
+   delete m_constants;
+   delete m_globals;
+   delete m_locals;
 
    delete m_env;
    delete m_pRetValue;
@@ -165,6 +165,15 @@ NXSL_VM::~NXSL_VM()
    safe_free(m_errorText);
 }
 
+/**
+ * Constant creation callback
+ */
+bool NXSL_VM::createConstantsCallback(const TCHAR *key, const void *value, void *data)
+{
+   ((NXSL_VM *)data)->m_constants->create(key, new NXSL_Value((NXSL_Value *)value));
+   return true;
+}
+
 /**
  * Load program
  */
@@ -189,11 +198,8 @@ bool NXSL_VM::load(NXSL_Program *program)
       m_functions->add(new NXSL_Function(program->m_functions->get(i)));
 
    // Set constants
-   m_pConstants->clear();
-   for(i = 0; i < (int)program->m_constants->size(); i++)
-   {
-      m_pConstants->create(program->m_constants->getKeyByIndex(i), new NXSL_Value(program->m_constants->getValueByIndex(i)));
-   }
+   m_constants->clear();
+   program->m_constants->forEach(createConstantsCallback, this);
 
    // Load modules
    m_modules = new ObjectArray<NXSL_Module>(4, 4, true);
@@ -247,19 +253,19 @@ bool NXSL_VM::run(ObjectArray<NXSL_Value> *args,
    m_catchStack = new NXSL_Stack;
 
    // Create local variable system for main() and bind arguments
-   m_pLocals = (pUserLocals == NULL) ? new NXSL_VariableSystem : pUserLocals;
+   m_locals = (pUserLocals == NULL) ? new NXSL_VariableSystem : pUserLocals;
    for(int i = 0; i < args->size(); i++)
    {
       _sntprintf(szBuffer, 32, _T("$%d"), i + 1);
-      m_pLocals->create(szBuffer, args->get(i));
+      m_locals->create(szBuffer, args->get(i));
    }
 
    // Preserve original global variables and constants
-   pSavedGlobals = new NXSL_VariableSystem(m_pGlobals);
+   pSavedGlobals = new NXSL_VariableSystem(m_globals);
        if (pConstants != NULL)
        {
-               pSavedConstants = new NXSL_VariableSystem(m_pConstants);
-               m_pConstants->merge(pConstants);
+               pSavedConstants = new NXSL_VariableSystem(m_constants);
+               m_constants->merge(pConstants);
        }
 
    // Locate entry point and run
@@ -307,16 +313,16 @@ resume:
 
    // Restore global variables
    if (ppGlobals == NULL)
-          delete m_pGlobals;
+          delete m_globals;
        else
-               *ppGlobals = m_pGlobals;
-   m_pGlobals = pSavedGlobals;
+               *ppGlobals = m_globals;
+   m_globals = pSavedGlobals;
 
        // Restore constants
        if (pSavedConstants != NULL)
        {
-               delete m_pConstants;
-               m_pConstants = pSavedConstants;
+               delete m_constants;
+               m_constants = pSavedConstants;
        }
 
    // Cleanup
@@ -334,7 +340,7 @@ resume:
    while((p = (NXSL_CatchPoint *)m_catchStack->pop()) != NULL)
       delete p;
    
-   delete_and_null(m_pLocals);
+   delete_and_null(m_locals);
    delete_and_null(m_dataStack);
    delete_and_null(m_codeStack);
    delete_and_null(m_catchStack);
@@ -354,8 +360,8 @@ bool NXSL_VM::unwind()
    while(m_dwSubLevel > p->subLevel)
    {
       m_dwSubLevel--;
-      delete m_pLocals;
-      m_pLocals = (NXSL_VariableSystem *)m_codeStack->pop();
+      delete m_locals;
+      m_locals = (NXSL_VariableSystem *)m_codeStack->pop();
       m_codeStack->pop();
    }
 
@@ -374,9 +380,9 @@ void NXSL_VM::setGlobalVariable(const TCHAR *pszName, NXSL_Value *pValue)
 {
    NXSL_Variable *pVar;
 
-       pVar = m_pGlobals->find(pszName);
+       pVar = m_globals->find(pszName);
    if (pVar == NULL)
-               m_pGlobals->create(pszName, pValue);
+               m_globals->create(pszName, pValue);
        else
                pVar->setValue(pValue);
 }
@@ -388,13 +394,13 @@ NXSL_Variable *NXSL_VM::findVariable(const TCHAR *pszName)
 {
    NXSL_Variable *pVar;
 
-   pVar = m_pConstants->find(pszName);
+   pVar = m_constants->find(pszName);
    if (pVar == NULL)
    {
-      pVar = m_pGlobals->find(pszName);
+      pVar = m_globals->find(pszName);
       if (pVar == NULL)
       {
-         pVar = m_pLocals->find(pszName);
+         pVar = m_locals->find(pszName);
       }
    }
    return pVar;
@@ -408,7 +414,7 @@ NXSL_Variable *NXSL_VM::findOrCreateVariable(const TCHAR *pszName)
    NXSL_Variable *pVar = findVariable(pszName);
    if (pVar == NULL)
    {
-      pVar = m_pLocals->create(pszName);
+      pVar = m_locals->create(pszName);
    }
    return pVar;
 }
@@ -420,13 +426,13 @@ NXSL_Variable *NXSL_VM::createVariable(const TCHAR *pszName)
 {
    NXSL_Variable *pVar = NULL;
 
-   if (m_pConstants->find(pszName) == NULL)
+   if (m_constants->find(pszName) == NULL)
    {
-      if (m_pGlobals->find(pszName) == NULL)
+      if (m_globals->find(pszName) == NULL)
       {
-         if (m_pLocals->find(pszName) == NULL)
+         if (m_locals->find(pszName) == NULL)
          {
-            pVar = m_pLocals->create(pszName);
+            pVar = m_locals->create(pszName);
          }
       }
    }
@@ -512,7 +518,7 @@ void NXSL_VM::execute()
                        break;
                case OPCODE_GLOBAL_ARRAY:
                        // Check if variable already exist
-                       pVar = m_pGlobals->find(cp->m_operand.m_pszString);
+                       pVar = m_globals->find(cp->m_operand.m_pszString);
                        if (pVar == NULL)
                        {
                                // raise error if variable with given name already exist and is not global
@@ -522,7 +528,7 @@ void NXSL_VM::execute()
                                }
                                else
                                {
-                                       m_pGlobals->create(cp->m_operand.m_pszString, new NXSL_Value(new NXSL_Array));
+                                       m_globals->create(cp->m_operand.m_pszString, new NXSL_Value(new NXSL_Array));
                                }
                        }
                        else
@@ -535,7 +541,7 @@ void NXSL_VM::execute()
                        break;
                case OPCODE_GLOBAL:
                        // Check if variable already exist
-                       pVar = m_pGlobals->find(cp->m_operand.m_pszString);
+                       pVar = m_globals->find(cp->m_operand.m_pszString);
                        if (pVar == NULL)
                        {
                                // raise error if variable with given name already exist and is not global
@@ -550,7 +556,7 @@ void NXSL_VM::execute()
                                                pValue = (NXSL_Value *)m_dataStack->pop();
                                                if (pValue != NULL)
                                                {
-                                                       m_pGlobals->create(cp->m_operand.m_pszString, pValue);
+                                                       m_globals->create(cp->m_operand.m_pszString, pValue);
                                                }
                                                else
                                                {
@@ -559,7 +565,7 @@ void NXSL_VM::execute()
                                        }
                                        else
                                        {
-                                               m_pGlobals->create(cp->m_operand.m_pszString, new NXSL_Value);
+                                               m_globals->create(cp->m_operand.m_pszString, new NXSL_Value);
                                        }
                                }
                        }
@@ -915,8 +921,8 @@ void NXSL_VM::execute()
          if (m_dwSubLevel > 0)
          {
             m_dwSubLevel--;
-            delete m_pLocals;
-            m_pLocals = (NXSL_VariableSystem *)m_codeStack->pop();
+            delete m_locals;
+            m_locals = (NXSL_VariableSystem *)m_codeStack->pop();
             dwNext = CAST_FROM_POINTER(m_codeStack->pop(), UINT32);
          }
          else
@@ -927,11 +933,11 @@ void NXSL_VM::execute()
          break;
       case OPCODE_BIND:
          _sntprintf(szBuffer, 256, _T("$%d"), m_nBindPos++);
-         pVar = m_pLocals->find(szBuffer);
+         pVar = m_locals->find(szBuffer);
          pValue = (pVar != NULL) ? new NXSL_Value(pVar->getValue()) : new NXSL_Value;
-         pVar = m_pLocals->find(cp->m_operand.m_pszString);
+         pVar = m_locals->find(cp->m_operand.m_pszString);
          if (pVar == NULL)
-            m_pLocals->create(cp->m_operand.m_pszString, pValue);
+            m_locals->create(cp->m_operand.m_pszString, pValue);
          else
             pVar->setValue(pValue);
          break;
@@ -1210,7 +1216,7 @@ void NXSL_VM::doBinaryOperation(int nOpCode)
                   pVal2 = (NXSL_Value *)m_dataStack->peek();
          break;
       case OPCODE_CASE_CONST:
-         var = m_pConstants->find(m_instructionSet->get(m_cp)->m_operand.m_pszString);
+         var = m_constants->find(m_instructionSet->get(m_cp)->m_operand.m_pszString);
          if (var != NULL)
          {
             pVal1 = var->getValue();
@@ -1554,7 +1560,7 @@ void NXSL_VM::loadModule(NXSL_Program *module, const TCHAR *name)
    }
 
    // Add constants from module
-   m_pConstants->addAll(module->m_constants);
+   m_constants->addAll(module->m_constants);
 
    // Register module as loaded
    NXSL_Module *m = new NXSL_Module;
@@ -1579,8 +1585,8 @@ void NXSL_VM::callFunction(int nArgCount)
    {
       m_dwSubLevel++;
       m_codeStack->push(CAST_TO_POINTER(m_cp + 1, void *));
-      m_codeStack->push(m_pLocals);
-      m_pLocals = new NXSL_VariableSystem;
+      m_codeStack->push(m_locals);
+      m_locals = new NXSL_VariableSystem;
       m_nBindPos = 1;
 
       // Bind arguments
@@ -1590,13 +1596,13 @@ void NXSL_VM::callFunction(int nArgCount)
          if (pValue != NULL)
          {
             _sntprintf(szBuffer, 256, _T("$%d"), i);
-            m_pLocals->create(szBuffer, pValue);
+            m_locals->create(szBuffer, pValue);
                                if (pValue->getName() != NULL)
                                {
                                        // Named parameter
                                        _sntprintf(szBuffer, 255, _T("$%s"), pValue->getName());
                                        szBuffer[255] = 0;
-                   m_pLocals->create(szBuffer, new NXSL_Value(pValue));
+                   m_locals->create(szBuffer, new NXSL_Value(pValue));
                                }
          }
          else
@@ -1650,9 +1656,9 @@ NXSL_Value *NXSL_VM::matchRegexp(NXSL_Value *pValue, NXSL_Value *pRegexp, BOOL b
          for(i = 1; (i < 256) && (fields[i].rm_so != -1); i++)
          {
             _sntprintf(szName, 16, _T("$%d"), i);
-            pVar = m_pLocals->find(szName);
+            pVar = m_locals->find(szName);
             if (pVar == NULL)
-               m_pLocals->create(szName, new NXSL_Value(pValue->getValueAsCString() + fields[i].rm_so, fields[i].rm_eo - fields[i].rm_so));
+               m_locals->create(szName, new NXSL_Value(pValue->getValueAsCString() + fields[i].rm_so, fields[i].rm_eo - fields[i].rm_so));
             else
                pVar->setValue(new NXSL_Value(pValue->getValueAsCString() + fields[i].rm_so, fields[i].rm_eo - fields[i].rm_so));
          }
index 6361841..c7c41ff 100644 (file)
@@ -82,7 +82,7 @@ bool PolicyDeploymentJob::run()
       
       setDescription(_T("Policy deploy failed. Wainting 10 minutes to restart job."));
       success = SleepAndCheckForShutdown(600);
-   } while (!success);
+   } while(!success);
 
        return success;
 }
index d7e6613..6a8e7d4 100644 (file)
@@ -1643,93 +1643,115 @@ void DCItem::expandInstance()
 }
 
 /**
- * Filter instance list
+ * Filter callback data
  */
-void DCItem::filterInstanceList(StringMap *instances)
+struct FilterCallbackData
 {
-   if (m_instanceFilter == NULL)
-               return;
+   StringMap *filteredInstances;
+   DCItem *dci;
+   NXSL_VM *instanceFilter;
+};
 
-   StringMap filteredInstances;
-       for(int i = 0; i < instances->size(); i++)
-       {
-      NXSL_Value *pValue = new NXSL_Value(instances->getKeyByIndex(i));
-      m_instanceFilter->setGlobalVariable(_T("$node"), new NXSL_Value(new NXSL_Object(&g_nxslNodeClass, m_pNode)));
-      m_instanceFilter->setGlobalVariable(_T("$dci"), new NXSL_Value(new NXSL_Object(&g_nxslDciClass, this)));
+/**
+ * Callback for filtering instances
+ */
+static bool FilterCallback(const TCHAR *key, const void *value, void *data)
+{
+   NXSL_VM *instanceFilter = ((FilterCallbackData *)data)->instanceFilter;
+   DCItem *dci = ((FilterCallbackData *)data)->dci;
 
-      if (m_instanceFilter->run(1, &pValue))
+   NXSL_Value *pValue = new NXSL_Value(key);
+   instanceFilter->setGlobalVariable(_T("$node"), new NXSL_Value(new NXSL_Object(&g_nxslNodeClass, dci->getNode())));
+   instanceFilter->setGlobalVariable(_T("$dci"), new NXSL_Value(new NXSL_Object(&g_nxslDciClass, dci)));
+
+   if (instanceFilter->run(1, &pValue))
+   {
+      bool accepted;
+      const TCHAR *instance = key;
+      const TCHAR *name = (const TCHAR *)value;
+      pValue = instanceFilter->getResult();
+      if (pValue != NULL)
       {
-         bool accepted;
-         const TCHAR *instance = instances->getKeyByIndex(i);
-         const TCHAR *name = instances->getValueByIndex(i);
-         pValue = m_instanceFilter->getResult();
-         if (pValue != NULL)
+         if (pValue->isArray())
          {
-            if (pValue->isArray())
+            NXSL_Array *array = pValue->getValueAsArray();
+            if (array->size() > 0)
             {
-               NXSL_Array *array = pValue->getValueAsArray();
-               if (array->size() > 0)
+               accepted = array->get(0)->getValueAsInt32() ? true : false;
+               if (accepted && (array->size() > 1))
                {
-                  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))
                   {
-                     // transformed value
-                     const TCHAR *newValue = array->get(1)->getValueAsCString();
-                     if ((newValue != NULL) && (*newValue != 0))
-                     {
-                        DbgPrintf(5, _T("DCItem::filterInstanceList(%s [%d]): instance %d \"%s\" replaced by \"%s\""),
-                                  m_szName, m_dwId, i, instance, newValue);
-                        instance = newValue;
-                     }
+                     DbgPrintf(5, _T("DCItem::filterInstanceList(%s [%d]): instance \"%s\" replaced by \"%s\""),
+                               dci->getName(), dci->getId(), instance, newValue);
+                     instance = newValue;
+                  }
 
-                     if (array->size() > 2)
+                  if (array->size() > 2)
+                  {
+                     // instance name
+                     const TCHAR *newName = array->get(2)->getValueAsCString();
+                     if ((newName != NULL) && (*newName != 0))
                      {
-                        // instance name
-                        const TCHAR *newName = array->get(2)->getValueAsCString();
-                        if ((newName != NULL) && (*newName != 0))
-                        {
-                           DbgPrintf(5, _T("DCItem::filterInstanceList(%s [%d]): instance %d \"%s\" name set to \"%s\""),
-                                     m_szName, m_dwId, i, instance, newName);
-                           name = newName;
-                        }
+                        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 = pValue->getValueAsInt32() ? true : false;
+               accepted = true;
             }
          }
          else
          {
-            accepted = true;
-         }
-                       if (accepted)
-         {
-            filteredInstances.set(instance, name);
+            accepted = pValue->getValueAsInt32() ? true : false;
          }
-         else
-                       {
-                               DbgPrintf(5, _T("DCItem::filterInstanceList(%s [%d]): instance \"%s\" removed by filtering script"),
-                                         m_szName, m_dwId, instances->getKeyByIndex(i));
-                       }
       }
       else
       {
-         TCHAR szBuffer[1024];
-
-                       _sntprintf(szBuffer, 1024, _T("DCI::%s::%d::InstanceFilter"),
-                    (m_pNode != NULL) ? m_pNode->Name() : _T("(null)"), m_dwId);
-         PostEvent(EVENT_SCRIPT_ERROR, g_dwMgmtNode, "ssd", szBuffer,
-                   m_instanceFilter->getErrorText(), m_dwId);
-         filteredInstances.set(instances->getKeyByIndex(i), instances->getValueByIndex(i));
+         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->getNode() != NULL) ? dci->getNode()->Name() : _T("(null)"), dci->getId());
+      PostEvent(EVENT_SCRIPT_ERROR, g_dwMgmtNode, "ssd", szBuffer, instanceFilter->getErrorText(), dci->getId());
+      ((FilterCallbackData *)data)->filteredInstances->set(key, (const TCHAR *)value);
    }
+   return true;
+}
+
+/**
+ * Filter instance list
+ */
+void DCItem::filterInstanceList(StringMap *instances)
+{
+   if (m_instanceFilter == NULL)
+               return;
+
+   StringMap filteredInstances;
+   FilterCallbackData data;
+   data.filteredInstances = &filteredInstances;
+   data.instanceFilter = m_instanceFilter;
+   data.dci = this;
+   instances->forEach(FilterCallback, &data);
    instances->clear();
    instances->addAll(&filteredInstances);
 }
index 6ae1d38..ea15a6d 100644 (file)
@@ -446,6 +446,29 @@ bool EPRule::matchScript(Event *pEvent)
    return bRet;
 }
 
+/**
+ * Situation update callback data
+ */
+struct SituationUpdateCallbackData
+{
+   Situation *s;
+   TCHAR *text;
+   Event *evt;
+};
+
+/**
+ * Situation update callback
+ */
+static bool SituationUpdateCallback(const TCHAR *key, const void *value, void *data)
+{
+       TCHAR *attrName = ((SituationUpdateCallbackData *)data)->evt->expandText(key);
+       TCHAR *attrValue = ((SituationUpdateCallbackData *)data)->evt->expandText((const TCHAR *)value);
+       ((SituationUpdateCallbackData *)data)->s->UpdateSituation(((SituationUpdateCallbackData *)data)->text, attrName, attrValue);
+       free(attrName);
+       free(attrValue);
+   return true;
+}
+
 /**
  * Check if event match to rule and perform required actions if yes
  * Method will return TRUE if event matched and RF_STOP_PROCESSING flag is set
@@ -481,22 +504,15 @@ bool EPRule::processEvent(Event *pEvent)
                        // Update situation of needed
                        if (m_dwSituationId != 0)
                        {
-                               Situation *pSituation;
-                               TCHAR *pszAttr, *pszValue;
-
-                               pSituation = FindSituationById(m_dwSituationId);
+                               Situation *pSituation = FindSituationById(m_dwSituationId);
                                if (pSituation != NULL)
                                {
-                                       TCHAR *pszText = pEvent->expandText(m_szSituationInstance);
-                                       for(int i = 0; i < m_situationAttrList.size(); i++)
-                                       {
-                                               pszAttr = pEvent->expandText(m_situationAttrList.getKeyByIndex(i));
-                                               pszValue = pEvent->expandText(m_situationAttrList.getValueByIndex(i));
-                                               pSituation->UpdateSituation(pszText, pszAttr, pszValue);
-                                               free(pszAttr);
-                                               free(pszValue);
-                                       }
-                                       free(pszText);
+               SituationUpdateCallbackData data;
+                                       data.text = pEvent->expandText(m_szSituationInstance);
+               data.s = pSituation;
+               data.evt = pEvent;
+               m_situationAttrList.forEach(SituationUpdateCallback, &data);
+                                       free(data.text);
                                }
                                else
                                {
@@ -612,6 +628,18 @@ bool EPRule::loadFromDB()
    return bSuccess;
 }
 
+/**
+ * Callback for saving situation attributes
+ */
+static bool SaveSituationAttribute(const TCHAR *key, const void *value, void *data)
+{
+   DB_STATEMENT hStmt = (DB_STATEMENT)data;
+   DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, key, DB_BIND_STATIC);
+   DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, (const TCHAR *)value, DB_BIND_STATIC);
+   DBExecute(hStmt);
+   return true;
+}
+
 /**
  * Save rule to database
  */
@@ -659,14 +687,17 @@ void EPRule::saveToDB(DB_HANDLE hdb)
    }
 
        // Situation attributes
-       for(i = 0; i < m_situationAttrList.size(); i++)
-       {
-      _sntprintf(pszQuery, len, _T("INSERT INTO policy_situation_attr_list (rule_id,situation_id,attr_name,attr_value) VALUES (%d,%d,%s,%s)"),
-                m_dwId, m_dwSituationId,
-                                        (const TCHAR *)DBPrepareString(hdb, m_situationAttrList.getKeyByIndex(i)),
-                                        (const TCHAR *)DBPrepareString(hdb, m_situationAttrList.getValueByIndex(i)));
-      DBQuery(hdb, pszQuery);
-       }
+   if (m_situationAttrList.size() > 0)
+   {
+      DB_STATEMENT hStmt = DBPrepare(hdb, _T("INSERT INTO policy_situation_attr_list (rule_id,situation_id,attr_name,attr_value) VALUES (?,?,?,?)"));
+      if (hStmt != NULL)
+      {
+         DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_dwId);
+         DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_dwSituationId);
+         m_situationAttrList.forEach(SaveSituationAttribute, hStmt);
+         DBFreeStatement(hStmt);
+      }
+   }
 
    free(pszQuery);
 }
@@ -694,13 +725,7 @@ void EPRule::createMessage(CSCPMessage *pMsg)
    pMsg->SetVariable(VID_SCRIPT, CHECK_NULL_EX(m_pszScript));
        pMsg->SetVariable(VID_SITUATION_ID, m_dwSituationId);
        pMsg->SetVariable(VID_SITUATION_INSTANCE, m_szSituationInstance);
-       pMsg->SetVariable(VID_SITUATION_NUM_ATTRS, m_situationAttrList.size());
-       UINT32 id = VID_SITUATION_ATTR_LIST_BASE;
-   for(int i = 0; i < m_situationAttrList.size(); i++)
-       {
-               pMsg->SetVariable(id++, m_situationAttrList.getKeyByIndex(i));
-               pMsg->SetVariable(id++, m_situationAttrList.getValueByIndex(i));
-       }
+   m_situationAttrList.fillMessage(pMsg, VID_SITUATION_NUM_ATTRS, VID_SITUATION_ATTR_LIST_BASE);
 }
 
 /**
index 650a7d5..f5b2cb3 100644 (file)
@@ -940,6 +940,7 @@ BOOL NXCORE_EXPORTABLE PostEventWithNames(UINT32 eventCode, UINT32 sourceId, con
  */
 BOOL NXCORE_EXPORTABLE PostEventWithNames(UINT32 eventCode, UINT32 sourceId, StringMap *parameters)
 {
+   /*
    int count = parameters->size();
    if (count > 1023)
       count = 1023;
@@ -956,8 +957,8 @@ BOOL NXCORE_EXPORTABLE PostEventWithNames(UINT32 eventCode, UINT32 sourceId, Str
       args[i] = parameters->getValueByIndex(i);
    }
 
-//   BOOL bResult = RealPostEvent(g_pEventQueue, eventCode, sourceId, NULL, format, names, args);
-//   return bResult;
+   return RealPostEvent(g_pEventQueue, eventCode, sourceId, NULL, format, names, args);
+   */
    return FALSE;
 }
 
index 2f4cbff..f51fa06 100644 (file)
@@ -409,27 +409,39 @@ TCHAR *LDAPConnection::getAttrValue(LDAPMessage *entry, const char *attr, UINT32
    return result;
 }
 
+/**
+ * Update user callback
+ */
+static bool UpdateUserCallback(const TCHAR *key, const void *value, void *data)
+{
+   UpdateLDAPUser(key, (Entry *)value);
+   return true;
+}
+
 /**
  * Updates user list according to newly recievd user list
  */
 void LDAPConnection::compareUserLists(StringObjectMap<Entry> *userEntryList)
 {
-   for(int i = 0; i < userEntryList->size(); i++)
-   {
-      UpdateLDAPUsers(userEntryList->getKeyByIndex(i), userEntryList->getValueByIndex(i));
-   }
+   userEntryList->forEach(UpdateUserCallback, NULL);
    RemoveDeletedLDAPEntry(userEntryList, m_action, true);
 }
 
+/**
+ * Update group callback
+ */
+static bool UpdateGroupCallback(const TCHAR *key, const void *value, void *data)
+{
+   UpdateLDAPGroup(key, (Entry *)value);
+   return true;
+}
+
 /**
  * Updates group list according to newly recievd user list
  */
 void LDAPConnection::compareGroupList(StringObjectMap<Entry> *groupEntryList)
 {
-   for(int i = 0; i < groupEntryList->size(); i++)
-   {
-      UpdateLDAPGroups(groupEntryList->getKeyByIndex(i), groupEntryList->getValueByIndex(i));
-   }
+   groupEntryList->forEach(UpdateGroupCallback, NULL);
    RemoveDeletedLDAPEntry(groupEntryList, m_action, false);
 }
 
index 5f73917..8763bbc 100644 (file)
@@ -173,7 +173,7 @@ static pthread_t m_signalHandlerThread;
  * @param seconds seconds to sleep
  * @return true if server is shutting down
  */
-BOOL NXCORE_EXPORTABLE SleepAndCheckForShutdown(int seconds)
+bool NXCORE_EXPORTABLE SleepAndCheckForShutdown(int seconds)
 {
        return ConditionWait(m_condShutdown, seconds * 1000);
 }
index 53770fb..9650dcc 100644 (file)
@@ -134,6 +134,28 @@ MappingTable::~MappingTable()
        delete m_data;
 }
 
+/**
+ * Data for FillMessageCallback
+ */
+struct FillMessageCallbackData
+{
+   CSCPMessage *msg;
+   UINT32 id;
+};
+
+/**
+ * Callback for setting mapping table elements in NXCP message
+ */
+static bool FillMessageCallback(const TCHAR *key, const void *value, void *data)
+{
+   UINT32 id = ((FillMessageCallbackData *)data)->id;
+       ((FillMessageCallbackData *)data)->msg->SetVariable(id, key);
+       ((FillMessageCallbackData *)data)->msg->SetVariable(id + 1, ((MappingTableElement *)value)->getValue());
+       ((FillMessageCallbackData *)data)->msg->SetVariable(id + 2, ((MappingTableElement *)value)->getDescription());
+       ((FillMessageCallbackData *)data)->id += 10;
+   return true;
+}
+
 /**
  * Fill NXCP message with mapping table's data
  */
@@ -145,15 +167,22 @@ void MappingTable::fillMessage(CSCPMessage *msg)
        msg->SetVariable(VID_DESCRIPTION, CHECK_NULL_EX(m_description));
        
        msg->SetVariable(VID_NUM_ELEMENTS, (UINT32)m_data->size());
-       UINT32 varId = VID_ELEMENT_LIST_BASE;
-       for(int i = 0; i < m_data->size(); i++)
-       {
-               msg->SetVariable(varId++, m_data->getKeyByIndex(i));
-               MappingTableElement *e = m_data->getValueByIndex(i);
-               msg->SetVariable(varId++, e->getValue());
-               msg->SetVariable(varId++, e->getDescription());
-               varId += 7;
-       }
+   FillMessageCallbackData data;
+   data.msg = msg;
+       data.id = VID_ELEMENT_LIST_BASE;
+   m_data->forEach(FillMessageCallback, &data);
+}
+
+/**
+ * Callback for saving elements into database
+ */
+static bool SaveElementCallback(const TCHAR *key, const void *value, void *data)
+{
+   DB_STATEMENT hStmt = (DB_STATEMENT)data;
+       DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, key, DB_BIND_STATIC);
+       DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, ((MappingTableElement *)value)->getValue(), DB_BIND_STATIC);
+       DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, ((MappingTableElement *)value)->getDescription(), DB_BIND_STATIC);
+   return DBExecute(hStmt) ? true : false;
 }
 
 /**
@@ -203,16 +232,9 @@ bool MappingTable::saveToDatabase()
        if (hStmt == NULL)
                goto failure2;
 
-       for(int i = 0; i < m_data->size(); i++)
-       {
-               MappingTableElement *e = m_data->getValueByIndex(i);
-               DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
-               DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, m_data->getKeyByIndex(i), DB_BIND_STATIC);
-               DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, e->getValue(), DB_BIND_STATIC);
-               DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, e->getDescription(), DB_BIND_STATIC);
-               if (!DBExecute(hStmt))
-                       goto failure;
-       }
+       DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
+   if (!m_data->forEach(SaveElementCallback, hStmt))
+      goto failure;
        DBFreeStatement(hStmt);
 
        DBCommit(hdb);
index 7f93052..cb141da 100644 (file)
@@ -102,6 +102,23 @@ BOOL NetObj::SaveToDB(DB_HANDLE hdb)
    return FALSE;     // Abstract objects cannot be saved to database
 }
 
+/**
+ * Parameters for DeleteModuleDataCallback and SaveModuleDataCallback
+ */
+struct ModuleDataDatabaseCallbackParams
+{
+   UINT32 id;
+   DB_HANDLE hdb;
+};
+
+/**
+ * Callback for deleting module data from database
+ */
+static bool DeleteModuleDataCallback(const TCHAR *key, const void *value, void *data)
+{
+   return ((ModuleData *)value)->deleteFromDatabase(((ModuleDataDatabaseCallbackParams *)data)->hdb, ((ModuleDataDatabaseCallbackParams *)data)->id);
+}
+
 /**
  * Delete object from database
  */
@@ -129,8 +146,10 @@ bool NetObj::deleteFromDB(DB_HANDLE hdb)
    // Delete module data
    if (success && (m_moduleData != NULL))
    {
-      for(int i = 0; (i < m_moduleData->size()) && success; i++)
-         success = m_moduleData->getValueByIndex(i)->deleteFromDatabase(hdb, m_dwId);
+      ModuleDataDatabaseCallbackParams data;
+      data.id = m_dwId;
+      data.hdb = hdb;
+      success = m_moduleData->forEach(DeleteModuleDataCallback, &data);
    }
 
    return success;
@@ -251,6 +270,25 @@ bool NetObj::loadCommonProperties()
    return success;
 }
 
+/**
+ * Callback for saving custom attribute in database
+ */
+static bool SaveAttributeCallback(const TCHAR *key, const void *value, void *data)
+{
+   DB_STATEMENT hStmt = (DB_STATEMENT)data;
+   DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, key, DB_BIND_STATIC);
+   DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, (const TCHAR *)value, DB_BIND_STATIC);
+   return DBExecute(hStmt) ? true : false;
+}
+
+/**
+ * Callback for saving module data in database
+ */
+static bool SaveModuleDataCallback(const TCHAR *key, const void *value, void *data)
+{
+   return ((ModuleData *)value)->saveToDatabase(((ModuleDataDatabaseCallbackParams *)data)->hdb, ((ModuleDataDatabaseCallbackParams *)data)->id);
+}
+
 /**
  * Save common object properties to database
  */
@@ -330,15 +368,8 @@ bool NetObj::saveCommonProperties(DB_HANDLE hdb)
                        hStmt = DBPrepare(hdb, _T("INSERT INTO object_custom_attributes (object_id,attr_name,attr_value) VALUES (?,?,?)"));
                        if (hStmt != NULL)
                        {
-                               for(int i = 0; i < m_customAttributes.size(); i++)
-                               {
-                                       DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_dwId);
-                                       DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, m_customAttributes.getKeyByIndex(i), DB_BIND_STATIC);
-                                       DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, m_customAttributes.getValueByIndex(i), DB_BIND_STATIC);
-               success = DBExecute(hStmt) ? true : false;
-                                       if (!success)
-                                               break;
-                               }
+                               DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_dwId);
+            success = m_customAttributes.forEach(SaveAttributeCallback, hStmt);
                                DBFreeStatement(hStmt);
                        }
                        else
@@ -351,8 +382,10 @@ bool NetObj::saveCommonProperties(DB_HANDLE hdb)
    // Save module data
    if (success && (m_moduleData != NULL))
    {
-      for(int i = 0; (i < m_moduleData->size()) && success; i++)
-         success = m_moduleData->getValueByIndex(i)->saveToDatabase(hdb, m_dwId);
+      ModuleDataDatabaseCallbackParams data;
+      data.id = m_dwId;
+      data.hdb = hdb;
+      success = m_moduleData->forEach(SaveModuleDataCallback, &data);
    }
 
        if (success)
@@ -822,6 +855,26 @@ bool NetObj::saveACLToDB(DB_HANDLE hdb)
    return success;
 }
 
+/**
+ * Data for SendModuleDataCallback
+ */
+struct SendModuleDataCallbackData
+{
+   CSCPMessage *msg;
+   UINT32 id;
+};
+
+/**
+ * Callback for sending module data in NXCP message
+ */
+static bool SendModuleDataCallback(const TCHAR *key, const void *value, void *data)
+{
+   ((SendModuleDataCallbackData *)data)->msg->SetVariable(((SendModuleDataCallbackData *)data)->id, key);
+   ((ModuleData *)value)->fillMessage(((SendModuleDataCallbackData *)data)->msg, ((SendModuleDataCallbackData *)data)->id + 1);
+   ((SendModuleDataCallbackData *)data)->id += 0x100000;
+   return true;
+}
+
 /**
  * Create NXCP message with object's data
  */
@@ -871,12 +924,7 @@ void NetObj::CreateMessage(CSCPMessage *pMsg)
        if (m_dwNumTrustedNodes > 0)
                pMsg->setFieldInt32Array(VID_TRUSTED_NODES, m_dwNumTrustedNodes, m_pdwTrustedNodes);
 
-       pMsg->SetVariable(VID_NUM_CUSTOM_ATTRIBUTES, m_customAttributes.size());
-       for(i = 0, dwId = VID_CUSTOM_ATTRIBUTES_BASE; i < (UINT32)m_customAttributes.size(); i++)
-       {
-               pMsg->SetVariable(dwId++, m_customAttributes.getKeyByIndex(i));
-               pMsg->SetVariable(dwId++, m_customAttributes.getValueByIndex(i));
-       }
+   m_customAttributes.fillMessage(pMsg, VID_NUM_CUSTOM_ATTRIBUTES, VID_CUSTOM_ATTRIBUTES_BASE);
 
    m_pAccessList->fillMessage(pMsg);
        m_geoLocation.fillMessage(*pMsg);
@@ -884,12 +932,10 @@ void NetObj::CreateMessage(CSCPMessage *pMsg)
    if (m_moduleData != NULL)
    {
       pMsg->SetVariable(VID_MODULE_DATA_COUNT, (UINT16)m_moduleData->size());
-      for(i = 0, dwId = VID_MODULE_DATA_BASE; i < (UINT32)m_moduleData->size(); i++, dwId += 0x100000)
-      {
-         pMsg->SetVariable(dwId, m_moduleData->getKeyByIndex(i));
-         ModuleData *d = m_moduleData->getValueByIndex(i);
-         d->fillMessage(pMsg, dwId + 1);
-      }
+      SendModuleDataCallbackData data;
+      data.msg = pMsg;
+      data.id = VID_MODULE_DATA_BASE;
+      m_moduleData->forEach(SendModuleDataCallback, &data);
    }
    else
    {
index d043853..17936bb 100644 (file)
@@ -2965,6 +2965,46 @@ StringMap *Node::getInstanceList(DCItem *dci)
        return instanceMap;
 }
 
+/**
+ * Callback for finding instance
+ */
+static bool FindInstanceCallback(const TCHAR *key, const void *value, void *data)
+{
+   return _tcscmp((const TCHAR *)data, key) != 0;  // return false if instance found - it will stop enumeration
+}
+
+/**
+ * Data for CreateInstanceDCI
+ */
+struct CreateInstanceDCIData
+{
+   DCItem *root;
+   Template *object;
+};
+
+/**
+ * Callback for creating instance DCIs
+ */
+static bool CreateInstanceDCI(const TCHAR *key, const void *value, void *data)
+{
+   Template *object = ((CreateInstanceDCIData *)data)->object;
+   DCItem *root = ((CreateInstanceDCIData *)data)->root;
+
+       DbgPrintf(5, _T("Node::updateInstances(%s [%u], %s [%u]): creating new DCI for instance \"%s\""),
+                 object->Name(), object->Id(), root->getName(), root->getId(), key);
+
+       DCItem *dci = new DCItem(root);
+   dci->setTemplateId(object->Id(), 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);
+   return true;
+}
+
 /**
  * Update instance DCIs created from instance discovery DCI
  */
@@ -2982,23 +3022,19 @@ void Node::updateInstances(DCItem *root, StringMap *instances)
                         (object->getTemplateItemId() != root->getId()))
                        continue;
 
-               int j;
-               for(j = 0; j < instances->size(); j++)
-         if (!_tcscmp(((DCItem *)object)->getInstanceDiscoveryData(), instances->getKeyByIndex(j)))
-                               break;
-
-               if (j < instances->size())
+      const TCHAR *dciInstance = ((DCItem *)object)->getInstanceDiscoveryData();
+      if (!instances->forEach(FindInstanceCallback, (void *)dciInstance))
                {
                        // found, remove value from instances
                        DbgPrintf(5, _T("Node::updateInstances(%s [%u], %s [%u]): instance \"%s\" found"),
-                                 m_szName, m_dwId, root->getName(), root->getId(), instances->getKeyByIndex(j));
-                       instances->remove(instances->getKeyByIndex(j));
+                                 m_szName, m_dwId, root->getName(), root->getId(), dciInstance);
+                       instances->remove(dciInstance);
                }
                else
                {
                        // not found, delete DCI
                        DbgPrintf(5, _T("Node::updateInstances(%s [%u], %s [%u]): instance \"%s\" not found, instance DCI will be deleted"),
-                                 m_szName, m_dwId, root->getName(), root->getId(), ((DCItem *)object)->getInstance());
+                                 m_szName, m_dwId, root->getName(), root->getId(), dciInstance);
                        deleteList.add(object->getId());
                }
    }
@@ -3007,21 +3043,10 @@ void Node::updateInstances(DCItem *root, StringMap *instances)
                deleteDCObject(deleteList.get(i), false);
 
        // Create new instances
-       for(int i = 0; i < instances->size(); i++)
-       {
-               DbgPrintf(5, _T("Node::updateInstances(%s [%u], %s [%u]): creating new DCI for instance \"%s\""),
-                         m_szName, m_dwId, root->getName(), root->getId(), instances->getKeyByIndex(i));
-
-               DCItem *dci = new DCItem(root);
-               dci->setTemplateId(m_dwId, root->getId());
-               dci->setInstance(instances->getValueByIndex(i));
-               dci->setInstanceDiscoveryMethod(IDM_NONE);
-               dci->setInstanceDiscoveryData(instances->getKeyByIndex(i));
-               dci->setInstanceFilter(NULL);
-      dci->expandInstance();
-               dci->changeBinding(CreateUniqueId(IDG_ITEM), this, FALSE);
-               addDCObject(dci, true);
-       }
+   CreateInstanceDCIData data;
+   data.root = root;
+   data.object = this;
+   instances->forEach(CreateInstanceDCI, &data);
 
    unlockDciAccess();
 }
index 138e045..e406881 100644 (file)
@@ -98,16 +98,9 @@ const TCHAR *SituationInstance::GetAttribute(const TCHAR *attribute)
  */
 UINT32 SituationInstance::CreateMessage(CSCPMessage *msg, UINT32 baseId)
 {
-       UINT32 id = baseId;
-       
-       msg->SetVariable(id++, m_name);
-       msg->SetVariable(id++, (UINT32)m_attributes.size());
-       for(int i = 0; i < m_attributes.size(); i++)
-       {
-               msg->SetVariable(id++, m_attributes.getKeyByIndex(i));
-               msg->SetVariable(id++, m_attributes.getValueByIndex(i));
-       }
-       return id;
+       msg->SetVariable(baseId, m_name);
+   m_attributes.fillMessage(msg, baseId + 1, baseId + 2);
+   return baseId + m_attributes.size() * 2 + 2;
 }
 
 /**
index 1120c30..1404b65 100644 (file)
@@ -503,7 +503,7 @@ bool NXCORE_EXPORTABLE ResolveUserId(UINT32 id, TCHAR *buffer, int bufSize)
 /**
  * Update/Add LDAP user
  */
-void NXCORE_EXPORTABLE UpdateLDAPUsers(const TCHAR* dn, Entry *obj)
+void NXCORE_EXPORTABLE UpdateLDAPUser(const TCHAR *dn, Entry *obj)
 {
    MutexLock(m_mutexUserDatabaseAccess);
    bool userModified = false;
@@ -519,7 +519,7 @@ void NXCORE_EXPORTABLE UpdateLDAPUsers(const TCHAR* dn, Entry *obj)
             {
                user->setSyncException();
                TCHAR mistakeDescription[MAX_USER_DESCR];
-               _sntprintf(mistakeDescription, MAX_USER_DESCR, _T("UpdateLDAPUsers(): Ldap sync error. User with name \"%s\" already exists."), obj->m_loginName);
+               _sntprintf(mistakeDescription, MAX_USER_DESCR, _T("UpdateLDAPUser(): Ldap sync error. User with name \"%s\" already exists."), obj->m_loginName);
                user->setDescription(mistakeDescription);
                DbgPrintf(4, mistakeDescription);
             }
@@ -528,7 +528,7 @@ void NXCORE_EXPORTABLE UpdateLDAPUsers(const TCHAR* dn, Entry *obj)
                user->setName(obj->m_loginName);
                user->setFullName(obj->m_fullName);
                user->setDescription(obj->m_description);
-               DbgPrintf(4, _T("UpdateLDAPUsers(): User updated: dn: %s, login name: %s, full name: %s, description: %s"), dn, obj->m_loginName, CHECK_NULL(obj->m_fullName), CHECK_NULL(obj->m_description));
+               DbgPrintf(4, _T("UpdateLDAPUser(): User updated: dn: %s, login name: %s, full name: %s, description: %s"), dn, obj->m_loginName, CHECK_NULL(obj->m_fullName), CHECK_NULL(obj->m_description));
             }
             if(user->isModified())
             {
@@ -553,11 +553,11 @@ void NXCORE_EXPORTABLE UpdateLDAPUsers(const TCHAR* dn, Entry *obj)
          m_users[m_userCount] = user;
          m_userCount++;
          SendUserDBUpdate(USER_DB_CREATE, user->getId(), user);
-         DbgPrintf(4, _T("UpdateLDAPUsers(): User added: dn: %s, login name: %s, full name: %s, description: %s"), dn, obj->m_loginName, CHECK_NULL(obj->m_fullName), CHECK_NULL(obj->m_description));
+         DbgPrintf(4, _T("UpdateLDAPUser(): User added: dn: %s, login name: %s, full name: %s, description: %s"), dn, obj->m_loginName, CHECK_NULL(obj->m_fullName), CHECK_NULL(obj->m_description));
       }
       else
       {
-         DbgPrintf(4, _T("UpdateLDAPUsers(): User with name %s already exists, but is not LDAP user. LDAP user won`t be creadted."), obj->m_loginName);
+         DbgPrintf(4, _T("UpdateLDAPUser(): User with name %s already exists, but is not LDAP user. LDAP user won`t be creadted."), obj->m_loginName);
       }
    }
    MutexUnlock(m_mutexUserDatabaseAccess);
@@ -594,7 +594,7 @@ void RemoveDeletedLDAPEntry(StringObjectMap<Entry>* entryList, UINT32 m_action,
 /**
  * Update/Add LDAP group
  */
-void NXCORE_EXPORTABLE UpdateLDAPGroups(const TCHAR* dn, Entry *obj) //no full name, add users inside group, and delete removed from the group
+void NXCORE_EXPORTABLE UpdateLDAPGroup(const TCHAR *dn, Entry *obj) //no full name, add users inside group, and delete removed from the group
 {
    MutexLock(m_mutexUserDatabaseAccess);
    bool userModified = false;
@@ -610,7 +610,7 @@ void NXCORE_EXPORTABLE UpdateLDAPGroups(const TCHAR* dn, Entry *obj) //no full n
             {
                group->setSyncException();
                TCHAR mistakeDescription[MAX_USER_DESCR];
-               _sntprintf(mistakeDescription, MAX_USER_DESCR, _T("UpdateLDAPGroups(): LDAP sync error. Group with \"%s\" name already exists."), obj->m_loginName);
+               _sntprintf(mistakeDescription, MAX_USER_DESCR, _T("UpdateLDAPGroup(): LDAP sync error. Group with \"%s\" name already exists."), obj->m_loginName);
                group->setDescription(mistakeDescription);
                DbgPrintf(4, mistakeDescription);
             }
@@ -618,7 +618,7 @@ void NXCORE_EXPORTABLE UpdateLDAPGroups(const TCHAR* dn, Entry *obj) //no full n
             {
                group->setName(obj->m_loginName);
                group->setDescription(obj->m_description);
-               DbgPrintf(4, _T("UpdateLDAPGroups(): Group updated: dn: %s, login name: %s, description: %s"), dn, obj->m_loginName, CHECK_NULL(obj->m_description));
+               DbgPrintf(4, _T("UpdateLDAPGroup(): Group updated: dn: %s, login name: %s, description: %s"), dn, obj->m_loginName, CHECK_NULL(obj->m_description));
             }
             if(group->isModified())
             {
@@ -643,11 +643,11 @@ void NXCORE_EXPORTABLE UpdateLDAPGroups(const TCHAR* dn, Entry *obj) //no full n
          m_users[m_userCount] = group;
          m_userCount++;
          SyncGroupMembers(group , obj);
-         DbgPrintf(4, _T("UpdateLDAPGroups(): Group added: dn: %s, login name: %s, description: %s"), dn, obj->m_loginName, CHECK_NULL(obj->m_description));
+         DbgPrintf(4, _T("UpdateLDAPGroup(): Group added: dn: %s, login name: %s, description: %s"), dn, obj->m_loginName, CHECK_NULL(obj->m_description));
       }
       else
       {
-         DbgPrintf(4, _T("UpdateLDAPGroups(): Group with %s name already exists, but is not LDAP user. LDAP user won't be creadted."), obj->m_loginName);
+         DbgPrintf(4, _T("UpdateLDAPGroup(): Group with %s name already exists, but is not LDAP user. LDAP user won't be creadted."), obj->m_loginName);
       }
    }
    MutexUnlock(m_mutexUserDatabaseAccess);
index bf3cd65..3a28530 100644 (file)
@@ -99,13 +99,7 @@ void UserDatabaseObject::fillMessage(CSCPMessage *msg)
    msg->SetVariable(VID_USER_SYS_RIGHTS, m_systemRights);
    msg->SetVariable(VID_USER_DESCRIPTION, m_description);
    msg->SetVariable(VID_GUID, m_guid, UUID_LENGTH);
-       msg->SetVariable(VID_NUM_CUSTOM_ATTRIBUTES, m_attributes.size());
-       UINT32 varId = VID_CUSTOM_ATTRIBUTES_BASE;
-       for(int i = 0; i < m_attributes.size(); i++)
-       {
-               msg->SetVariable(varId++, m_attributes.getKeyByIndex(i));
-               msg->SetVariable(varId++, m_attributes.getValueByIndex(i));
-       }
+   m_attributes.fillMessage(msg, VID_NUM_CUSTOM_ATTRIBUTES, VID_CUSTOM_ATTRIBUTES_BASE);
 }
 
 /**
@@ -194,6 +188,17 @@ bool UserDatabaseObject::loadCustomAttributes(DB_HANDLE hdb)
        return success;
 }
 
+/**
+ * Callback for saving custom attribute in database
+ */
+static bool SaveAttributeCallback(const TCHAR *key, const void *value, void *data)
+{
+   DB_STATEMENT hStmt = (DB_STATEMENT)data;
+   DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, key, DB_BIND_STATIC);
+   DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, (const TCHAR *)value, DB_BIND_STATIC);
+   return DBExecute(hStmt) ? true : false;
+}
+
 /**
  * Save custom attributes to database
  */
@@ -209,15 +214,7 @@ bool UserDatabaseObject::saveCustomAttributes(DB_HANDLE hdb)
       if (hStmt != NULL)
       {
          DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
-         int i;
-                  for(i = 0; i < m_attributes.size(); i++)
-                  {
-            DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, m_attributes.getKeyByIndex(i), DB_BIND_STATIC);
-            DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, m_attributes.getValueByIndex(i), DB_BIND_STATIC);
-                          if (!DBExecute(hStmt))
-                                  break;
-                  }
-                  success = (i == m_attributes.size());
+         success = m_attributes.forEach(SaveAttributeCallback, hStmt);
          DBFreeStatement(hStmt);
       }
        }
index 8d6419b..a09be82 100644 (file)
@@ -43,14 +43,14 @@ static UINT32 HandlerVlanList(UINT32 dwVersion, SNMP_Variable *pVar, SNMP_Transp
    UINT32 oidName[MAX_OID_LEN], dwResult;
    VlanList *vlanList = (VlanList *)pArg;
 
-   UINT32 dwNameLen = pVar->getName()->getLength();
+   size_t nameLen = pVar->getName()->getLength();
        VlanInfo *vlan = new VlanInfo(pVar->getValueAsInt(), VLAN_PRM_IFINDEX);
 
    // Get VLAN name
-   memcpy(oidName, pVar->getName()->getValue(), dwNameLen * sizeof(UINT32));
-   oidName[dwNameLen - 2] = 2;
+   memcpy(oidName, pVar->getName()->getValue(), nameLen * sizeof(UINT32));
+   oidName[nameLen - 2] = 2;
    TCHAR buffer[256];
-       dwResult = SnmpGet(dwVersion, pTransport, NULL, oidName, dwNameLen, buffer, sizeof(buffer), SG_STRING_RESULT);
+       dwResult = SnmpGet(dwVersion, pTransport, NULL, oidName, nameLen, buffer, sizeof(buffer), SG_STRING_RESULT);
    if (dwResult != SNMP_ERR_SUCCESS)
        {
                delete vlan;
@@ -68,10 +68,10 @@ static UINT32 HandlerVlanList(UINT32 dwVersion, SNMP_Variable *pVar, SNMP_Transp
        //   bit of octet #1 corresponds to ifIndex 0, while the least significant 
        //   bit of octet #32 corresponds to ifIndex 255." 
        // Note: on newer devices port list can be longer
-   oidName[dwNameLen - 2] = 12;
+   oidName[nameLen - 2] = 12;
        BYTE portMask[256];
        memset(portMask, 0, sizeof(portMask));
-   dwResult = SnmpGet(dwVersion, pTransport, NULL, oidName, dwNameLen, portMask, sizeof(portMask), SG_RAW_RESULT);
+   dwResult = SnmpGet(dwVersion, pTransport, NULL, oidName, nameLen, portMask, sizeof(portMask), SG_RAW_RESULT);
    if (dwResult != SNMP_ERR_SUCCESS)
        {
                delete vlan;
index 33aa98a..6a4ed04 100644 (file)
@@ -832,7 +832,7 @@ THREAD_RESULT NXCORE_EXPORTABLE THREAD_CALL Main(void *);
 void NXCORE_EXPORTABLE ShutdownDB();
 void InitiateShutdown();
 
-BOOL NXCORE_EXPORTABLE SleepAndCheckForShutdown(int iSeconds);
+bool NXCORE_EXPORTABLE SleepAndCheckForShutdown(int iSeconds);
 
 void ConsolePrintf(CONSOLE_CTX pCtx, const TCHAR *pszFormat, ...)
 #if !defined(UNICODE) && (defined(__GNUC__) || defined(__clang__))
index fffae3d..32498c7 100644 (file)
@@ -265,6 +265,7 @@ public:
    bool isShowOnObjectTooltip() { return (m_flags & DCF_SHOW_ON_OBJECT_TOOLTIP) ? true : false; }
    bool isAggregateOnCluster() { return (m_flags & DCF_AGGREGATE_ON_CLUSTER) ? true : false; }
    int getAggregationFunction() { return DCF_GET_AGGREGATION_FUNCTION(m_flags); }
+   Template *getNode() { return m_pNode; }
 
        bool matchClusterResource();
    bool isReadyForPolling(time_t currTime);
index ab59b60..ee67c7f 100644 (file)
@@ -325,9 +325,9 @@ const TCHAR NXCORE_EXPORTABLE *GetUserDbObjectAttr(UINT32 id, const TCHAR *name)
 UINT32 NXCORE_EXPORTABLE GetUserDbObjectAttrAsULong(UINT32 id, const TCHAR *name);
 void NXCORE_EXPORTABLE SetUserDbObjectAttr(UINT32 id, const TCHAR *name, const TCHAR *value);
 bool NXCORE_EXPORTABLE ResolveUserId(UINT32 id, TCHAR *buffer, int bufSize);
-void NXCORE_EXPORTABLE UpdateLDAPUsers(const TCHAR* dn, Entry *obj);
+void NXCORE_EXPORTABLE UpdateLDAPUser(const TCHAR* dn, Entry *obj);
 void RemoveDeletedLDAPEntry(StringObjectMap<Entry>* userEntryList, UINT32 m_action, bool isUser);
-void NXCORE_EXPORTABLE UpdateLDAPGroups(const TCHAR* dn, Entry *obj);
+void NXCORE_EXPORTABLE UpdateLDAPGroup(const TCHAR* dn, Entry *obj);
 void SyncGroupMembers(Group* group, Entry *obj);
 UserDatabaseObject* GetUser(UINT32 userID);
 UserDatabaseObject* GetUser(const TCHAR* dn);
index 0708b05..9a2197a 100644 (file)
@@ -90,6 +90,15 @@ void PrintMobileUnits(NetworkDeviceDriver *driver, SNMP_Transport *transport)
    }
 }
 
+/**
+ * Print attribute
+ */
+static bool PrintAttributeCallback(const TCHAR *key, const void *value, void *data)
+{
+   _tprintf(_T("   %s = %s\n"), key, (const TCHAR *)value);
+   return true;
+}
+
 /**
  * Connect to device
  */
@@ -124,10 +133,7 @@ static bool ConnectToDevice(NetworkDeviceDriver *driver, SNMP_Transport *transpo
    
    driver->analyzeDevice(transport, oid, &s_customAttributes, &s_driverData);
    _tprintf(_T("Custom attributes after device analyze:\n"));
-   for(int i = 0; i < s_customAttributes.size(); i++)
-   {
-      _tprintf(_T("   %s = %s\n"), s_customAttributes.getKeyByIndex(i), s_customAttributes.getValueByIndex(i));
-   }
+   s_customAttributes.forEach(PrintAttributeCallback, NULL);
    return true;
 }
 
index fb0a689..10644b9 100644 (file)
@@ -99,7 +99,9 @@ static void TestStringMap()
       m->set(key, _T("Lorem ipsum dolor sit amet"));
    }
    AssertEquals(m->size(), 10000);
-   AssertTrue(!_tcscmp(m->get(_T("key-42")), _T("Lorem ipsum dolor sit amet")));
+   const TCHAR *v = m->get(_T("key-42"));
+   AssertNotNull(v);
+   AssertTrue(!_tcscmp(v, _T("Lorem ipsum dolor sit amet")));
    EndTest(GetCurrentTimeMs() - start);
 
    StartTest(_T("String map - replace"));
@@ -111,12 +113,14 @@ static void TestStringMap()
       m->set(key, _T("consectetur adipiscing elit"));
    }
    AssertEquals(m->size(), 10000);
-   AssertTrue(!_tcscmp(m->get(_T("key-42")), _T("consectetur adipiscing elit")));
+   v = m->get(_T("key-42"));
+   AssertNotNull(v);
+   AssertTrue(!_tcscmp(v, _T("consectetur adipiscing elit")));
    EndTest(GetCurrentTimeMs() - start);
 
    StartTest(_T("String map - get"));
    start = GetCurrentTimeMs();
-   const TCHAR *v = m->get(_T("key-888"));
+   v = m->get(_T("key-888"));
    AssertNotNull(v);
    AssertTrue(!_tcscmp(v, _T("consectetur adipiscing elit")));
    EndTest(GetCurrentTimeMs() - start);