String class refactored; background log writer option implemented; fixed incorrect...
authorVictor Kirhenshtein <victor@netxms.org>
Sun, 28 Dec 2014 22:41:42 +0000 (00:41 +0200)
committerVictor Kirhenshtein <victor@netxms.org>
Sun, 28 Dec 2014 22:41:42 +0000 (00:41 +0200)
36 files changed:
include/nms_util.h
src/agent/core/nxagentd.cpp
src/agent/core/nxagentd.h
src/client/libnxclient/alarms.cpp
src/flow_analyzer/nxflowd/collector.cpp
src/libnetxms/config.cpp
src/libnetxms/log.cpp
src/libnetxms/message.cpp
src/libnetxms/string.cpp
src/libnetxms/strset.cpp
src/libnxlp/parser.cpp
src/libnxlp/rule.cpp
src/server/core/ap_config.cpp
src/server/core/audit.cpp
src/server/core/columnfilter.cpp
src/server/core/config.cpp
src/server/core/dcitem.cpp
src/server/core/dcithreshold.cpp
src/server/core/dcobject.cpp
src/server/core/dctable.cpp
src/server/core/dctcolumn.cpp
src/server/core/dctthreshold.cpp
src/server/core/epp.cpp
src/server/core/events.cpp
src/server/core/loghandle.cpp
src/server/core/main.cpp
src/server/core/netmap.cpp
src/server/core/session.cpp
src/server/core/snmptrap.cpp
src/server/core/template.cpp
src/server/include/nxsrvapi.h
src/server/tools/nxdbmgr/export.cpp
src/server/tools/nxdbmgr/import.cpp
src/server/tools/nxdbmgr/init.cpp
src/server/tools/nxdbmgr/upgrade.cpp
tests/test-libnetxms/test-libnetxms.cpp

index b1588e8..710d8af 100644 (file)
 /**
  * nxlog_open() flags
  */
-#define NXLOG_USE_SYSLOG               ((UINT32)0x00000001)
-#define NXLOG_PRINT_TO_STDOUT  ((UINT32)0x00000002)
-#define NXLOG_IS_OPEN         ((UINT32)0x80000000)
+#define NXLOG_USE_SYSLOG                 ((UINT32)0x00000001)
+#define NXLOG_PRINT_TO_STDOUT    ((UINT32)0x00000002)
+#define NXLOG_BACKGROUND_WRITER ((UINT32)0x00000004)
+#define NXLOG_IS_OPEN           ((UINT32)0x80000000)
 
 /**
  * nxlog rotation policy
@@ -248,8 +249,10 @@ public:
 class LIBNETXMS_EXPORTABLE String
 {
 protected:
-   TCHAR *m_pszBuffer;
-   UINT32 m_dwBufSize;
+   TCHAR *m_buffer;
+   size_t m_length;
+   size_t m_allocated;
+   int m_allocationStep;
 
 public:
        static const int npos;
@@ -259,32 +262,38 @@ public:
        String(const String &src);
    ~String();
 
-       TCHAR *getBuffer() { return m_pszBuffer; }
-   void setBuffer(TCHAR *pszBuffer);
+       TCHAR *getBuffer() { return m_buffer; }
+   void setBuffer(TCHAR *buffer);
 
-   const String& operator =(const TCHAR *pszStr);
+   int getAllocationStep() { return m_allocationStep; }
+   void setAllocationStep(int step) { m_allocationStep = step; }
+
+   const String& operator =(const TCHAR *str);
        const String& operator =(const String &src);
    const String&  operator +=(const TCHAR *str);
    const String&  operator +=(const String &str);
-   operator const TCHAR*() { return CHECK_NULL_EX(m_pszBuffer); }
+   operator const TCHAR*() { return CHECK_NULL_EX(m_buffer); }
 
        char *getUTF8String();
 
-       void addString(const TCHAR *pStr, UINT32 dwLen);
-       void addDynamicString(TCHAR *pszStr) { if (pszStr != NULL) { *this += pszStr; free(pszStr); } }
+   void append(const TCHAR *str) { if (str != NULL) append(str, _tcslen(str)); }
+       void append(const TCHAR *str, size_t len);
+
+       void appendPreallocated(TCHAR *str) { if (str != NULL) { append(str); free(str); } }
 
-       void addMultiByteString(const char *pStr, UINT32 size, int nCodePage);
-       void addWideCharString(const WCHAR *pStr, UINT32 size);
+       void appendMBString(const char *str, size_t len, int nCodePage);
+       void appendWideString(const WCHAR *str, size_t len);
 
-   void addFormattedString(const TCHAR *format, ...);
-   void addFormattedStringV(const TCHAR *format, va_list args);
+   void appendFormattedString(const TCHAR *format, ...);
+   void appendFormattedStringV(const TCHAR *format, va_list args);
+
+   void clear();
 
-       UINT32 getSize() { return m_dwBufSize > 0 ? m_dwBufSize - 1 : 0; }
-       BOOL isEmpty() { return m_dwBufSize <= 1; }
+       size_t length() const { return m_length; }
+       bool isEmpty() const { return m_length == 0; }
 
-       TCHAR *subStr(int nStart, int nLen, TCHAR *pszBuffer);
-       TCHAR *subStr(int nStart, int nLen) { return subStr(nStart, nLen, NULL); }
-       int find(const TCHAR *pszStr, int nStart = 0);
+       TCHAR *substring(int nStart, int nLen, TCHAR *pszBuffer = NULL);
+       int find(const TCHAR *str, int nStart = 0);
 
    void escapeCharacter(int ch, int esc);
    void replace(const TCHAR *pszSrc, const TCHAR *pszDst);
index 2269e04..3cbec05 100644 (file)
@@ -197,6 +197,7 @@ static NX_CFG_TEMPLATE m_cfgTemplate[] =
    { _T("Action"), CT_STRING_LIST, '\n', 0, 0, 0, &m_pszActionList, NULL },
    { _T("ActionShellExec"), CT_STRING_LIST, '\n', 0, 0, 0, &m_pszShellActionList, NULL },
    { _T("AppAgent"), CT_STRING_LIST, '\n', 0, 0, 0, &m_pszAppAgentList, NULL },
+   { _T("BackgroundLogWriter"), CT_BOOLEAN, 0, 0, AF_BACKGROUND_LOG_WRITER, 0, &g_dwFlags, NULL },
    { _T("ControlServers"), CT_STRING_LIST, ',', 0, 0, 0, &m_pszControlServerList, NULL },
    { _T("CreateCrashDumps"), CT_BOOLEAN, 0, 0, AF_CATCH_EXCEPTIONS, 0, &g_dwFlags, NULL },
        { _T("DataDirectory"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDataDirectory, NULL },
@@ -718,7 +719,8 @@ BOOL Initialize()
        }
    if (!nxlog_open((g_dwFlags & AF_USE_SYSLOG) ? NXAGENTD_SYSLOG_NAME : g_szLogFile,
                        ((g_dwFlags & AF_USE_SYSLOG) ? NXLOG_USE_SYSLOG : 0) |
-                          ((g_dwFlags & AF_DAEMON) ? 0 : NXLOG_PRINT_TO_STDOUT),
+                       ((g_dwFlags & AF_BACKGROUND_LOG_WRITER) ? NXLOG_BACKGROUND_WRITER : 0) |
+                   ((g_dwFlags & AF_DAEMON) ? 0 : NXLOG_PRINT_TO_STDOUT),
                        _T("NXAGENTD.EXE"),
 #ifdef _WIN32
                        0, NULL))
index 3c7aee7..8eef6ad 100644 (file)
 #define AF_DISABLE_IPV4             0x00080000
 #define AF_DISABLE_IPV6             0x00100000
 #define AF_ENABLE_SNMP_TRAP_PROXY   0x00200000
+#define AF_BACKGROUND_LOG_WRITER    0x00400000
 
 
 #ifdef _WIN32
index 57a339f..d55964e 100644 (file)
@@ -330,7 +330,7 @@ TCHAR *AlarmController::formatAlarmText(NXC_ALARM *alarm, const TCHAR *format)
                        out += prev;
                        break;
                }
-               out.addString(prev, (UINT32)(curr - prev));
+               out.append(prev, (size_t)(curr - prev));
                curr++;
                switch(*curr)
                {
@@ -344,25 +344,25 @@ TCHAR *AlarmController::formatAlarmText(NXC_ALARM *alarm, const TCHAR *format)
             out += ((object != NULL) && (object->getObjectClass() == OBJECT_NODE)) ? ((Node *)object)->getPrimaryHostname() : _T("<unknown>");
                                break;
                        case 'c':
-                               out.addFormattedString(_T("%u"), (unsigned int)alarm->dwRepeatCount);
+                               out.appendFormattedString(_T("%u"), (unsigned int)alarm->dwRepeatCount);
                                break;
                        case 'e':
-                               out.addFormattedString(_T("%u"), (unsigned int)alarm->dwSourceEventCode);
+                               out.appendFormattedString(_T("%u"), (unsigned int)alarm->dwSourceEventCode);
                                break;
                        case 'E':
             out += ((EventController *)m_session->getController(CONTROLLER_EVENTS))->getEventName(alarm->dwSourceEventCode, buffer, 128);
                                break;
                        case 'h':
-                               out.addFormattedString(_T("%d"), (int)alarm->nHelpDeskState);
+                               out.appendFormattedString(_T("%d"), (int)alarm->nHelpDeskState);
                                break;
                        case 'H':
                                out += helpdeskState[alarm->nHelpDeskState];
                                break;
                        case 'i':
-                               out.addFormattedString(_T("%u"), (unsigned int)alarm->dwSourceObject);
+                               out.appendFormattedString(_T("%u"), (unsigned int)alarm->dwSourceObject);
                                break;
                        case 'I':
-                               out.addFormattedString(_T("%u"), (unsigned int)alarm->dwAlarmId);
+                               out.appendFormattedString(_T("%u"), (unsigned int)alarm->dwAlarmId);
                                break;
                        case 'm':
                                out += alarm->szMessage;
@@ -371,13 +371,13 @@ TCHAR *AlarmController::formatAlarmText(NXC_ALARM *alarm, const TCHAR *format)
                                out += (object != NULL) ? object->getName() : _T("<unknown>");
                                break;
                        case 's':
-                               out.addFormattedString(_T("%d"), (int)alarm->nCurrentSeverity);
+                               out.appendFormattedString(_T("%d"), (int)alarm->nCurrentSeverity);
                                break;
                        case 'S':
                                out += severityText[alarm->nCurrentSeverity];
                                break;
                        case 'x':
-                               out.addFormattedString(_T("%d"), (int)alarm->nState);
+                               out.appendFormattedString(_T("%d"), (int)alarm->nState);
                                break;
                        case 'X':
                                out += alarmState[alarm->nState];
index 27a296b..ae7a788 100644 (file)
@@ -153,7 +153,7 @@ static int H_DataRecord(ipfixs_node_t *node, ipfixt_node_t *trec, ipfix_datareco
                                                fields += _T(",");
                                                fields += s_fieldMapping[j].dbField;
                                                trec->ipfixt->fields[i].elem->snprint(buffer, sizeof(buffer), data->addrs[i], data->lens[i]);
-                                               values.addFormattedString(_T(",'%hs'"), buffer);
+                                               values.appendFormattedString(_T(",'%hs'"), buffer);
                                                break;
                                        }
                                }
@@ -165,7 +165,7 @@ static int H_DataRecord(ipfixs_node_t *node, ipfixt_node_t *trec, ipfix_datareco
        {
                String query = _T("INSERT INTO flows (flow_id,start_time,end_time");
                query += (const TCHAR *)fields;
-               query.addFormattedString(_T(") VALUES (") INT64_FMT _T(",") INT64_FMT _T(",") INT64_FMT, s_flowId++, flowStartTime, flowEndTime);
+               query.appendFormattedString(_T(") VALUES (") INT64_FMT _T(",") INT64_FMT _T(",") INT64_FMT, s_flowId++, flowStartTime, flowEndTime);
                query += (const TCHAR *)values;
                query += _T(")");
 
index afc8f8b..95eef6e 100644 (file)
@@ -586,7 +586,7 @@ void ConfigEntry::print(FILE *file, int level)
 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);
+      ((String *)userData)->appendFormattedString(_T(" %s=\"%s\""), key, (const TCHAR *)value);
    return true;
 }
 
@@ -601,9 +601,9 @@ void ConfigEntry::createXml(String &xml, int level)
       *ptr = 0;
 
    if (m_id == 0)
-      xml.addFormattedString(_T("%*s<%s"), level * 4, _T(""), name);
+      xml.appendFormattedString(_T("%*s<%s"), level * 4, _T(""), name);
    else
-      xml.addFormattedString(_T("%*s<%s id=\"%d\""), level * 4, _T(""), name, m_id);
+      xml.appendFormattedString(_T("%*s<%s id=\"%d\""), level * 4, _T(""), name, m_id);
    m_attributes.forEach(AddAttribute, &xml);
    xml += _T(">");
 
@@ -612,21 +612,21 @@ void ConfigEntry::createXml(String &xml, int level)
       xml += _T("\n");
       for(ConfigEntry *e = m_first; e != NULL; e = e->getNext())
          e->createXml(xml, level + 1);
-      xml.addFormattedString(_T("%*s"), level * 4, _T(""));
+      xml.appendFormattedString(_T("%*s"), level * 4, _T(""));
    }
 
    if (m_valueCount > 0)
-      xml.addDynamicString(EscapeStringForXML(m_values[0], -1));
-   xml.addFormattedString(_T("</%s>\n"), name);
+      xml.appendPreallocated(EscapeStringForXML(m_values[0], -1));
+   xml.appendFormattedString(_T("</%s>\n"), name);
 
    for(int i = 1, len = 0; i < m_valueCount; i++)
    {
       if (m_id == 0)
-         xml.addFormattedString(_T("%*s<%s>"), level * 4, _T(""), name);
+         xml.appendFormattedString(_T("%*s<%s>"), level * 4, _T(""), name);
       else
-         xml.addFormattedString(_T("%*s<%s id=\"%d\">"), level * 4, _T(""), name, m_id);
-      xml.addDynamicString(EscapeStringForXML(m_values[i], -1));
-      xml.addFormattedString(_T("</%s>\n"), name);
+         xml.appendFormattedString(_T("%*s<%s id=\"%d\">"), level * 4, _T(""), name, m_id);
+      xml.appendPreallocated(EscapeStringForXML(m_values[i], -1));
+      xml.appendFormattedString(_T("</%s>\n"), name);
    }
 
    free(name);
@@ -1283,7 +1283,7 @@ static void CharData(void *userData, const XML_Char *s, int len)
    XML_PARSER_STATE *ps = (XML_PARSER_STATE *) userData;
 
    if ((ps->level > 0) && (ps->level <= MAX_STACK_DEPTH))
-      ps->charData[ps->level - 1].addMultiByteString(s, len, CP_UTF8);
+      ps->charData[ps->level - 1].appendMBString(s, len, CP_UTF8);
 }
 
 /**
index 2198de0..767b57d 100644 (file)
@@ -49,6 +49,9 @@ static int m_logHistorySize = 4;              // Keep up 4 previous log files
 static TCHAR m_dailyLogSuffixTemplate[64] = _T("%Y%m%d");
 static time_t m_currentDayStart = 0;
 static NxLogConsoleWriter m_consoleWriter = (NxLogConsoleWriter)_tprintf;
+static String s_logBuffer;
+static THREAD s_writerThread = INVALID_THREAD_HANDLE;
+static CONDITION s_writerStopCondition = INVALID_CONDITION_HANDLE;
 
 /**
  * Format current time for output
@@ -230,6 +233,54 @@ BOOL LIBNETXMS_EXPORTABLE nxlog_rotate()
        return RotateLog(TRUE);
 }
 
+/**
+ * Background writer thread
+ */
+static THREAD_RESULT THREAD_CALL BackgroundWriterThread(void *arg)
+{
+   bool stop = false;
+   while(!stop)
+   {
+      stop = ConditionWait(s_writerStopCondition, 1000);
+
+          // Check for new day start
+      time_t t = time(NULL);
+          if ((m_rotationMode == NXLOG_ROTATION_DAILY) && (t >= m_currentDayStart + 86400))
+          {
+                  RotateLog(FALSE);
+          }
+
+      MutexLock(m_mutexLogAccess);
+      if (!s_logBuffer.isEmpty())
+      {
+         if (m_flags & NXLOG_PRINT_TO_STDOUT)
+            m_consoleWriter(_T("%s"), s_logBuffer.getBuffer());
+
+         char *data = s_logBuffer.getUTF8String();
+         s_logBuffer.clear();
+         MutexUnlock(m_mutexLogAccess);
+
+         fwrite(data, 1, strlen(data), m_logFileHandle);
+                  fflush(m_logFileHandle);
+
+             // Check log size
+             if ((m_logFileHandle != NULL) && (m_rotationMode == NXLOG_ROTATION_BY_SIZE) && (m_maxLogSize != 0))
+             {
+                     struct stat st;
+
+                     fstat(fileno(m_logFileHandle), &st);
+                     if (st.st_size >= m_maxLogSize)
+                             RotateLog(FALSE);
+             }
+      }
+      else
+      {
+         MutexUnlock(m_mutexLogAccess);
+      }
+   }
+   return THREAD_OK;
+}
+
 /**
  * Initialize log
  */
@@ -277,6 +328,12 @@ BOOL LIBNETXMS_EXPORTABLE nxlog_open(const TCHAR *logName, UINT32 flags,
       {
                        m_flags |= NXLOG_IS_OPEN;
          _ftprintf(m_logFileHandle, _T("\n%s Log file opened\n"), FormatLogTimestamp(buffer));
+         if (m_flags & NXLOG_BACKGROUND_WRITER)
+         {
+            s_logBuffer.setAllocationStep(8192);
+            s_writerStopCondition = ConditionCreate(TRUE);
+            s_writerThread = ThreadCreateEx(BackgroundWriterThread, 0, NULL);
+         }
       }
 
       m_mutexLogAccess = MutexCreate();
@@ -302,6 +359,12 @@ void LIBNETXMS_EXPORTABLE nxlog_close()
       }
       else
       {
+         if (m_flags & NXLOG_BACKGROUND_WRITER)
+         {
+            ConditionSet(s_writerStopCondition);
+            ThreadJoin(s_writerThread);
+            ConditionDestroy(s_writerStopCondition);
+         }
          if (m_logFileHandle != NULL)
             fclose(m_logFileHandle);
          if (m_mutexLogAccess != INVALID_MUTEX_HANDLE)
@@ -338,36 +401,51 @@ static void WriteLogToFile(TCHAR *message, const WORD wType)
              break;
    }
 
-   // Prevent simultaneous write to log file
-   MutexLock(m_mutexLogAccess);
-
-       // Check for new day start
-   time_t t = time(NULL);
-       if ((m_rotationMode == NXLOG_ROTATION_DAILY) && (t >= m_currentDayStart + 86400))
-       {
-               RotateLog(FALSE);
-       }
+   if (m_flags & NXLOG_BACKGROUND_WRITER)
+   {
+      MutexLock(m_mutexLogAccess);
 
-       FormatLogTimestamp(buffer);
-   if (m_logFileHandle != NULL)
-       {
-      _ftprintf(m_logFileHandle, _T("%s %s%s"), buffer, loglevel, message);
-               fflush(m_logFileHandle);
-       }
-   if (m_flags & NXLOG_PRINT_TO_STDOUT)
-      m_consoleWriter(_T("%s %s%s"), buffer, loglevel, message);
+          FormatLogTimestamp(buffer);
+      s_logBuffer.append(buffer);
+      s_logBuffer.append(_T(" "));
+      s_logBuffer.append(loglevel);
+      s_logBuffer.append(message);
 
-       // Check log size
-       if ((m_logFileHandle != NULL) && (m_rotationMode == NXLOG_ROTATION_BY_SIZE) && (m_maxLogSize != 0))
-       {
-               struct stat st;
+      MutexUnlock(m_mutexLogAccess);
+   }
+   else
+   {
+      // Prevent simultaneous write to log file
+      MutexLock(m_mutexLogAccess);
 
-               fstat(fileno(m_logFileHandle), &st);
-               if (st.st_size >= m_maxLogSize)
-                       RotateLog(FALSE);
-       }
+          // Check for new day start
+      time_t t = time(NULL);
+          if ((m_rotationMode == NXLOG_ROTATION_DAILY) && (t >= m_currentDayStart + 86400))
+          {
+                  RotateLog(FALSE);
+          }
 
-   MutexUnlock(m_mutexLogAccess);
+          FormatLogTimestamp(buffer);
+      if (m_logFileHandle != NULL)
+          {
+         _ftprintf(m_logFileHandle, _T("%s %s%s"), buffer, loglevel, message);
+                  fflush(m_logFileHandle);
+          }
+      if (m_flags & NXLOG_PRINT_TO_STDOUT)
+         m_consoleWriter(_T("%s %s%s"), buffer, loglevel, message);
+
+          // Check log size
+          if ((m_logFileHandle != NULL) && (m_rotationMode == NXLOG_ROTATION_BY_SIZE) && (m_maxLogSize != 0))
+          {
+                  struct stat st;
+
+                  fstat(fileno(m_logFileHandle), &st);
+                  if (st.st_size >= m_maxLogSize)
+                          RotateLog(FALSE);
+          }
+
+      MutexUnlock(m_mutexLogAccess);
+   }
 }
 
 /**
index 9d49ea4..165ffda 100644 (file)
@@ -952,11 +952,11 @@ String NXCPMessage::dump(NXCP_MESSAGE *msg, int version)
    for(i = 0; i < (int)size; i += 16)
    {
       BinToStr(((BYTE *)msg) + i, min(16, size - i), buffer); 
-      out.addFormattedString(_T("  ** %s\n"), buffer);
+      out.appendFormattedString(_T("  ** %s\n"), buffer);
    }
 
    // header
-   out.addFormattedString(_T("  ** code=0x%04X (%s) flags=0x%04X id=%d size=%d numFields=%d\n"), 
+   out.appendFormattedString(_T("  ** code=0x%04X (%s) flags=0x%04X id=%d size=%d numFields=%d\n"), 
       code, NXCPMessageCodeName(code, buffer), flags, id, size, numFields);
    if (flags & MF_BINARY)
    {
@@ -979,7 +979,7 @@ String NXCPMessage::dump(NXCP_MESSAGE *msg, int version)
       if ((pos > size - 12) && 
           ((field->type == NXCP_DT_STRING) || (field->type == NXCP_DT_BINARY)))
       {
-         out.addFormattedString(_T("  ** message format error (pos > size - 8 and field type %d)\n"), (int)field->type);
+         out.appendFormattedString(_T("  ** message format error (pos > size - 8 and field type %d)\n"), (int)field->type);
          break;
       }
 
@@ -1001,19 +1001,19 @@ String NXCPMessage::dump(NXCP_MESSAGE *msg, int version)
       {
          case NXCP_DT_INT32:
             convertedField->df_int32 = ntohl(convertedField->df_int32);
-            out.addFormattedString(_T("  ** [%6d] INT32  %d\n"), (int)convertedField->fieldId, convertedField->df_int32);
+            out.appendFormattedString(_T("  ** [%6d] INT32  %d\n"), (int)convertedField->fieldId, convertedField->df_int32);
             break;
          case NXCP_DT_INT64:
             convertedField->df_int64 = ntohq(convertedField->df_int64);
-            out.addFormattedString(_T("  ** [%6d] INT64  ") INT64_FMT _T("\n"), (int)convertedField->fieldId, convertedField->df_int64);
+            out.appendFormattedString(_T("  ** [%6d] INT64  ") INT64_FMT _T("\n"), (int)convertedField->fieldId, convertedField->df_int64);
             break;
          case NXCP_DT_INT16:
             convertedField->df_int16 = ntohs(convertedField->df_int16);
-            out.addFormattedString(_T("  ** [%6d] INT16  %d\n"), (int)convertedField->fieldId, (int)convertedField->df_int16);
+            out.appendFormattedString(_T("  ** [%6d] INT16  %d\n"), (int)convertedField->fieldId, (int)convertedField->df_int16);
             break;
          case NXCP_DT_FLOAT:
             convertedField->df_real = ntohd(convertedField->df_real);
-            out.addFormattedString(_T("  ** [%6d] FLOAT  %f\n"), (int)convertedField->fieldId, convertedField->df_real);
+            out.appendFormattedString(_T("  ** [%6d] FLOAT  %f\n"), (int)convertedField->fieldId, convertedField->df_real);
             break;
          case NXCP_DT_STRING:
 #if !(WORDS_BIGENDIAN)
@@ -1022,15 +1022,15 @@ String NXCPMessage::dump(NXCP_MESSAGE *msg, int version)
                convertedField->df_string.value[i] = ntohs(convertedField->df_string.value[i]);
 #endif
             str = GetStringFromField((BYTE *)convertedField + 8);
-            out.addFormattedString(_T("  ** [%6d] STRING \"%s\"\n"), (int)convertedField->fieldId, str);
+            out.appendFormattedString(_T("  ** [%6d] STRING \"%s\"\n"), (int)convertedField->fieldId, str);
             free(str);
             break;
          case NXCP_DT_BINARY:
             convertedField->df_string.length = ntohl(convertedField->df_string.length);
-            out.addFormattedString(_T("  ** [%6d] BINARY len=%d\n"), (int)convertedField->fieldId, (int)convertedField->df_string.length);
+            out.appendFormattedString(_T("  ** [%6d] BINARY len=%d\n"), (int)convertedField->fieldId, (int)convertedField->df_string.length);
             break;
          default:
-            out.addFormattedString(_T("  ** [%6d] unknown type %d\n"), (int)convertedField->fieldId, (int)field->type);
+            out.appendFormattedString(_T("  ** [%6d] unknown type %d\n"), (int)convertedField->fieldId, (int)field->type);
             break;
       }
       free(convertedField);
index dc313bf..ad942df 100644 (file)
  */
 const int String::npos = -1;
 
-
-//
-// Constructors
-//
-
+/**
+ * Create empty string
+ */
 String::String()
 {
-   m_dwBufSize = 1;
-   m_pszBuffer = NULL;
+   m_buffer = NULL;
+   m_length = 0;
+   m_allocated = 0;
+   m_allocationStep = 256;
 }
 
+/**
+ * Copy constructor
+ */
 String::String(const String &src)
 {
-       m_dwBufSize = src.m_dwBufSize;
-       m_pszBuffer = (src.m_pszBuffer != NULL) ? (TCHAR *)nx_memdup(src.m_pszBuffer, src.m_dwBufSize * sizeof(TCHAR)) : NULL;
+   m_length = src.m_length;
+   m_allocated = src.m_length + 1;
+   m_allocationStep = src.m_allocationStep;
+       m_buffer = ((src.m_buffer != NULL) && (src.m_length > 0)) ? (TCHAR *)nx_memdup(src.m_buffer, m_allocated * sizeof(TCHAR)) : NULL;
 }
 
+/**
+ * Create string with given initial content
+ */
 String::String(const TCHAR *init)
 {
-   m_dwBufSize = (UINT32)_tcslen(init) + 1;
-   m_pszBuffer = _tcsdup(init);
+   m_buffer = _tcsdup(init);
+   m_length = _tcslen(init);
+   m_allocated = m_length + 1;
+   m_allocationStep = 256;
 }
 
 /**
@@ -56,17 +66,18 @@ String::String(const TCHAR *init)
  */
 String::~String()
 {
-   safe_free(m_pszBuffer);
+   safe_free(m_buffer);
 }
 
 /**
  * Operator =
  */
-const String& String::operator =(const TCHAR *pszStr)
+const String& String::operator =(const TCHAR *str)
 {
-   safe_free(m_pszBuffer);
-   m_pszBuffer = _tcsdup(CHECK_NULL_EX(pszStr));
-   m_dwBufSize = (UINT32)_tcslen(CHECK_NULL_EX(pszStr)) + 1;
+   safe_free(m_buffer);
+   m_buffer = _tcsdup(CHECK_NULL_EX(str));
+   m_length = _tcslen(CHECK_NULL_EX(str));
+   m_allocated = m_length + 1;
    return *this;
 }
 
@@ -77,9 +88,11 @@ const String& String::operator =(const String &src)
 {
        if (&src == this)
                return *this;
-   safe_free(m_pszBuffer);
-       m_dwBufSize = src.m_dwBufSize;
-       m_pszBuffer = (src.m_pszBuffer != NULL) ? (TCHAR *)nx_memdup(src.m_pszBuffer, src.m_dwBufSize * sizeof(TCHAR)) : NULL;
+   safe_free(m_buffer);
+       m_length = src.m_length;
+   m_allocated = src.m_length + 1;
+   m_allocationStep = src.m_allocationStep;
+       m_buffer = ((src.m_buffer != NULL) && (src.m_length > 0)) ? (TCHAR *)nx_memdup(src.m_buffer, m_allocated * sizeof(TCHAR)) : NULL;
    return *this;
 }
 
@@ -90,10 +103,14 @@ const String& String::operator +=(const TCHAR *str)
 {
        if (str != NULL)
        {
-       UINT32 dwLen = (UINT32)_tcslen(str);
-       m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwLen) * sizeof(TCHAR));
-       _tcscpy(&m_pszBuffer[m_dwBufSize - 1], str);
-       m_dwBufSize += dwLen;
+       size_t len = _tcslen(str);
+      if (m_length + len >= m_allocated)
+      {
+         m_allocated += max(m_allocationStep, len);
+       m_buffer = (TCHAR *)realloc(m_buffer, m_allocated * sizeof(TCHAR));
+      }
+       _tcscpy(&m_buffer[m_length], str);
+       m_length += len;
        }
    return *this;
 }
@@ -103,13 +120,15 @@ const String& String::operator +=(const TCHAR *str)
  */
 const String& String::operator +=(const String &str)
 {
-   UINT32 dwLen = str.m_dwBufSize;
-   if (dwLen > 1)
+   if (str.m_length > 0)
    {
-      dwLen--;
-          m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwLen) * sizeof(TCHAR));
-      _tcscpy(&m_pszBuffer[m_dwBufSize - 1], str.m_pszBuffer);
-          m_dwBufSize += dwLen;
+      if (m_length + str.m_length >= m_allocated)
+      {
+         m_allocated += max(m_allocationStep, str.m_length);
+       m_buffer = (TCHAR *)realloc(m_buffer, m_allocated * sizeof(TCHAR));
+      }
+      memcpy(&m_buffer[m_length], str.m_buffer, (str.m_length + 1) * sizeof(TCHAR));
+          m_length += str.m_length;
    }
    return *this;
 }
@@ -117,16 +136,16 @@ const String& String::operator +=(const String &str)
 /**
  * Add formatted string to the end of buffer
  */
-void String::addFormattedString(const TCHAR *format, ...)
+void String::appendFormattedString(const TCHAR *format, ...)
 {
    va_list args;
 
        va_start(args, format);
-       addFormattedStringV(format, args);
+       appendFormattedStringV(format, args);
        va_end(args);
 }
 
-void String::addFormattedStringV(const TCHAR *format, va_list args)
+void String::appendFormattedStringV(const TCHAR *format, va_list args)
 {
    int len;
    TCHAR *buffer;
@@ -188,47 +207,62 @@ void String::addFormattedStringV(const TCHAR *format, va_list args)
 
 #endif /* UNICODE */
 
-   *this += buffer;
+   append(buffer, _tcslen(buffer));
    free(buffer);
 }
 
 /**
- * Add string to the end of buffer
+ * Append string to the end of buffer
  */
-void String::addString(const TCHAR *pStr, UINT32 dwSize)
+void String::append(const TCHAR *str, size_t len)
 {
-   m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwSize) * sizeof(TCHAR));
-   memcpy(&m_pszBuffer[m_dwBufSize - 1], pStr, dwSize * sizeof(TCHAR));
-   m_dwBufSize += dwSize;
-       m_pszBuffer[m_dwBufSize - 1] = 0;
+   if (len <= 0)
+      return;
+
+   if (m_length + len >= m_allocated)
+   {
+      m_allocated += max(m_allocationStep, len);
+       m_buffer = (TCHAR *)realloc(m_buffer, m_allocated * sizeof(TCHAR));
+   }
+   memcpy(&m_buffer[m_length], str, len * sizeof(TCHAR));
+   m_length += len;
+   m_buffer[m_length] = 0;
 }
 
 /**
- * Add multibyte string to the end of buffer
+ * Append multibyte string to the end of buffer
  */
-void String::addMultiByteString(const char *pStr, UINT32 dwSize, int nCodePage)
+void String::appendMBString(const char *str, size_t len, int nCodePage)
 {
 #ifdef UNICODE
-   m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwSize) * sizeof(TCHAR));
-       m_dwBufSize += MultiByteToWideChar(nCodePage, (nCodePage == CP_UTF8) ? 0 : MB_PRECOMPOSED, pStr, dwSize, &m_pszBuffer[m_dwBufSize - 1], dwSize);
-       m_pszBuffer[m_dwBufSize - 1] = 0;
+   if (m_length + len >= m_allocated)
+   {
+      m_allocated += max(m_allocationStep, len);
+       m_buffer = (TCHAR *)realloc(m_buffer, m_allocated * sizeof(TCHAR));
+   }
+       m_length += MultiByteToWideChar(nCodePage, (nCodePage == CP_UTF8) ? 0 : MB_PRECOMPOSED, str, (int)len, &m_buffer[m_length], (int)len);
+       m_buffer[m_length] = 0;
 #else
-       addString(pStr, dwSize);
+       append(str, len);
 #endif
 }
 
 /**
- * Add widechar string to the end of buffer
+ * Append widechar string to the end of buffer
  */
-void String::addWideCharString(const WCHAR *pStr, UINT32 dwSize)
+void String::appendWideString(const WCHAR *str, size_t len)
 {
 #ifdef UNICODE
-       addString(pStr, dwSize);
+       append(str, len);
 #else
-   m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwSize) * sizeof(TCHAR));
-       WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, pStr, dwSize, &m_pszBuffer[m_dwBufSize - 1], dwSize, NULL, NULL);
-   m_dwBufSize += dwSize;
-       m_pszBuffer[m_dwBufSize - 1] = 0;
+   if (m_length + len >= m_allocated)
+   {
+      m_allocated += max(m_allocationStep, len);
+       m_buffer = (TCHAR *)realloc(m_buffer, m_allocated * sizeof(TCHAR));
+   }
+       WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, str, len, &m_buffer[m_length], len, NULL, NULL);
+   m_length += len;
+       m_buffer[m_length] = 0;
 #endif
 }
 
@@ -237,37 +271,49 @@ void String::addWideCharString(const WCHAR *pStr, UINT32 dwSize)
  */
 void String::escapeCharacter(int ch, int esc)
 {
-   int nCount;
-   UINT32 i;
-
-   if (m_pszBuffer == NULL)
+   if (m_buffer == NULL)
       return;
 
-   nCount = NumChars(m_pszBuffer, ch);
+   int nCount = NumChars(m_buffer, ch);
    if (nCount == 0)
       return;
 
-   m_dwBufSize += nCount;
-   m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, m_dwBufSize * sizeof(TCHAR));
-   for(i = 0; m_pszBuffer[i] != 0; i++)
+   if (m_length + nCount >= m_allocated)
    {
-      if (m_pszBuffer[i] == ch)
+      m_allocated += max(m_allocationStep, nCount);
+       m_buffer = (TCHAR *)realloc(m_buffer, m_allocated * sizeof(TCHAR));
+   }
+
+   m_length += nCount;
+   for(int i = 0; m_buffer[i] != 0; i++)
+   {
+      if (m_buffer[i] == ch)
       {
-         memmove(&m_pszBuffer[i + 1], &m_pszBuffer[i], (m_dwBufSize - i - 1) * sizeof(TCHAR));
-         m_pszBuffer[i] = esc;
+         memmove(&m_buffer[i + 1], &m_buffer[i], (m_length - i) * sizeof(TCHAR));
+         m_buffer[i] = esc;
          i++;
       }
    }
+   m_buffer[m_length] = 0;
 }
 
 /**
  * Set dynamically allocated string as a new buffer
  */
-void String::setBuffer(TCHAR *pszBuffer)
+void String::setBuffer(TCHAR *buffer)
 {
-   safe_free(m_pszBuffer);
-   m_pszBuffer = pszBuffer;
-   m_dwBufSize = (m_pszBuffer != NULL) ? (UINT32)_tcslen(m_pszBuffer) + 1 : 1;
+   safe_free(m_buffer);
+   m_buffer = buffer;
+   if (m_buffer != NULL)
+   {
+      m_length = _tcslen(m_buffer);
+      m_allocated = m_length + 1;
+   }
+   else
+   {
+      m_length = 0;
+      m_allocated = 0;
+   }
 }
 
 /**
@@ -275,37 +321,41 @@ void String::setBuffer(TCHAR *pszBuffer)
  */
 void String::replace(const TCHAR *pszSrc, const TCHAR *pszDst)
 {
-   if (m_pszBuffer == NULL)
+   if (m_buffer == NULL)
       return;
 
-   int lenSrc = (int)_tcslen(pszSrc);
-   int lenDst = (int)_tcslen(pszDst);
+   size_t lenSrc = _tcslen(pszSrc);
+   size_t lenDst = _tcslen(pszDst);
 
-   for(int i = 0; ((int)m_dwBufSize > lenSrc) && (i < (int)m_dwBufSize - lenSrc); i++)
+   for(size_t i = 0; (m_length > lenSrc) && (i <= m_length - lenSrc); i++)
    {
-      if (!memcmp(pszSrc, &m_pszBuffer[i], lenSrc * sizeof(TCHAR)))
+      if (!memcmp(pszSrc, &m_buffer[i], lenSrc * sizeof(TCHAR)))
       {
          if (lenSrc == lenDst)
          {
-            memcpy(&m_pszBuffer[i], pszDst, lenDst * sizeof(TCHAR));
+            memcpy(&m_buffer[i], pszDst, lenDst * sizeof(TCHAR));
             i += lenDst - 1;
          }
          else if (lenSrc > lenDst)
          {
-            memcpy(&m_pszBuffer[i], pszDst, lenDst * sizeof(TCHAR));
+            memcpy(&m_buffer[i], pszDst, lenDst * sizeof(TCHAR));
             i += lenDst;
-            int delta = lenSrc - lenDst;
-            m_dwBufSize -= (UINT32)delta;
-            memmove(&m_pszBuffer[i], &m_pszBuffer[i + delta], (m_dwBufSize - (UINT32)i) * sizeof(TCHAR));
+            size_t delta = lenSrc - lenDst;
+            m_length -= delta;
+            memmove(&m_buffer[i], &m_buffer[i + delta], (m_length - i + 1) * sizeof(TCHAR));
             i--;
          }
          else
          {
-            int delta = lenDst - lenSrc;
-            m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + (UINT32)delta) * sizeof(TCHAR));
-            memmove(&m_pszBuffer[i + lenDst], &m_pszBuffer[i + lenSrc], ((int)m_dwBufSize - i - lenSrc) * sizeof(TCHAR));
-            m_dwBufSize += (UINT32)delta;
-            memcpy(&m_pszBuffer[i], pszDst, lenDst * sizeof(TCHAR));
+            size_t delta = lenDst - lenSrc;
+            if (m_length + delta >= m_allocated)
+            {
+               m_allocated += max(m_allocationStep, delta);
+               m_buffer = (TCHAR *)realloc(m_buffer, m_allocated * sizeof(TCHAR));
+            }
+            memmove(&m_buffer[i + lenDst], &m_buffer[i + lenSrc], (m_length - i - lenSrc + 1) * sizeof(TCHAR));
+            m_length += delta;
+            memcpy(&m_buffer[i], pszDst, lenDst * sizeof(TCHAR));
             i += lenDst - 1;
          }
       }
@@ -315,23 +365,23 @@ void String::replace(const TCHAR *pszSrc, const TCHAR *pszDst)
 /**
  * Extract substring into buffer
  */
-TCHAR *String::subStr(int nStart, int nLen, TCHAR *pszBuffer)
+TCHAR *String::substring(int nStart, int nLen, TCHAR *pszBuffer)
 {
        int nCount;
        TCHAR *pszOut;
 
-       if ((nStart < (int)m_dwBufSize - 1) && (nStart >= 0))
+       if ((nStart < (int)m_length) && (nStart >= 0))
        {
                if (nLen == -1)
                {
-                       nCount = (int)m_dwBufSize - nStart - 1;
+                       nCount = (int)m_length - nStart;
                }
                else
                {
-                       nCount = min(nLen, (int)m_dwBufSize - nStart - 1);
+                       nCount = min(nLen, (int)m_length - nStart);
                }
                pszOut = (pszBuffer != NULL) ? pszBuffer : (TCHAR *)malloc((nCount + 1) * sizeof(TCHAR));
-               memcpy(pszOut, &m_pszBuffer[nStart], nCount * sizeof(TCHAR));
+               memcpy(pszOut, &m_buffer[nStart], nCount * sizeof(TCHAR));
                pszOut[nCount] = 0;
        }
        else
@@ -345,15 +395,15 @@ TCHAR *String::subStr(int nStart, int nLen, TCHAR *pszBuffer)
 /**
  * Find substring in a string
  */
-int String::find(const TCHAR *pszStr, int nStart)
+int String::find(const TCHAR *str, int nStart)
 {
        TCHAR *p;
 
-       if ((nStart >= (int)m_dwBufSize - 1) || (nStart < 0))
+       if ((nStart >= (int)m_length) || (nStart < 0))
                return npos;
 
-       p = _tcsstr(&m_pszBuffer[nStart], pszStr);
-       return (p != NULL) ? (int)(((char *)p - (char *)m_pszBuffer) / sizeof(TCHAR)) : npos;
+       p = _tcsstr(&m_buffer[nStart], str);
+       return (p != NULL) ? (int)(((char *)p - (char *)m_buffer) / sizeof(TCHAR)) : npos;
 }
 
 /**
@@ -361,10 +411,10 @@ int String::find(const TCHAR *pszStr, int nStart)
  */
 void String::trim()
 {
-       if (m_pszBuffer != NULL)
+       if (m_buffer != NULL)
        {
-               Trim(m_pszBuffer);
-               m_dwBufSize = (UINT32)_tcslen(m_pszBuffer) + 1;
+               Trim(m_buffer);
+               m_length = _tcslen(m_buffer);
        }
 }
 
@@ -373,22 +423,32 @@ void String::trim()
  */
 void String::shrink(int chars)
 {
-       if (m_dwBufSize > 1)
+       if (m_length > 0)
        {
-               m_dwBufSize -= min(m_dwBufSize - 1, (UINT32)chars);
-               if (m_pszBuffer != NULL)
-                       m_pszBuffer[m_dwBufSize - 1] = 0;
+               m_length -= min(m_length, chars);
+               if (m_buffer != NULL)
+                       m_buffer[m_length] = 0;
        }
 }
 
+/**
+ * Clear string
+ */
+void String::clear()
+{
+   m_length = 0;
+   if (m_buffer != NULL)
+      m_buffer[m_length] = 0;
+}
+
 /**
  * Get content as dynamically allocated UTF-8 string
  */
 char *String::getUTF8String()
 {
 #ifdef UNICODE
-       return UTF8StringFromWideString(m_pszBuffer);
+       return UTF8StringFromWideString(m_buffer);
 #else
-       return strdup(m_pszBuffer);
+       return strdup(m_buffer);
 #endif
 }
index 1b73d68..db5f8e9 100644 (file)
@@ -250,10 +250,11 @@ void StringSet::addAllFromMessage(NXCPMessage *msg, UINT32 baseId, UINT32 countI
 String StringSet::getAll(const TCHAR *separator)
 {
    String result;
+   result.setAllocationStep(4096);
    StringSetEntry *entry, *tmp;
    HASH_ITER(hh, m_data, entry, tmp)
    {
-      if ((separator != NULL) && (result.getSize() > 0))
+      if ((separator != NULL) && (result.length() > 0))
          result += separator;
       result += entry->str;
    }
index 97a6822..7684f47 100644 (file)
@@ -414,7 +414,7 @@ static void StartElement(void *userData, const char *name, const char **attrs)
                name = XMLGetAttr(attrs, "name");
 #ifdef UNICODE
                ps->macroName = L"";
-               ps->macroName.addMultiByteString(name, (UINT32)strlen(name), CP_UTF8);
+               ps->macroName.appendMBString(name, strlen(name), CP_UTF8);
 #else
                ps->macroName = CHECK_NULL_A(name);
 #endif
@@ -439,7 +439,7 @@ static void StartElement(void *userData, const char *name, const char **attrs)
                ps->ruleContext = L"";
                const char *context = XMLGetAttr(attrs, "context");
                if (context != NULL)
-                       ps->ruleContext.addMultiByteString(context, (UINT32)strlen(context), CP_UTF8);
+                       ps->ruleContext.appendMBString(context, strlen(context), CP_UTF8);
 #else
                ps->ruleContext = XMLGetAttr(attrs, "context");
 #endif
@@ -653,31 +653,31 @@ static void CharData(void *userData, const XML_Char *s, int len)
        switch(ps->state)
        {
                case XML_STATE_MATCH:
-                       ps->regexp.addMultiByteString(s, len, CP_UTF8);
+                       ps->regexp.appendMBString(s, len, CP_UTF8);
                        break;
                case XML_STATE_ID:
-                       ps->id.addMultiByteString(s, len, CP_UTF8);
+                       ps->id.appendMBString(s, len, CP_UTF8);
                        break;
                case XML_STATE_LEVEL:
-                       ps->level.addMultiByteString(s, len, CP_UTF8);
+                       ps->level.appendMBString(s, len, CP_UTF8);
                        break;
                case XML_STATE_SOURCE:
-                       ps->source.addMultiByteString(s, len, CP_UTF8);
+                       ps->source.appendMBString(s, len, CP_UTF8);
                        break;
                case XML_STATE_EVENT:
-                       ps->event.addMultiByteString(s, len, CP_UTF8);
+                       ps->event.appendMBString(s, len, CP_UTF8);
                        break;
                case XML_STATE_FILE:
-                       ps->file.addMultiByteString(s, len, CP_UTF8);
+                       ps->file.appendMBString(s, len, CP_UTF8);
                        break;
                case XML_STATE_CONTEXT:
-                       ps->context.addMultiByteString(s, len, CP_UTF8);
+                       ps->context.appendMBString(s, len, CP_UTF8);
                        break;
                case XML_STATE_DESCRIPTION:
-                       ps->description.addMultiByteString(s, len, CP_UTF8);
+                       ps->description.appendMBString(s, len, CP_UTF8);
                        break;
                case XML_STATE_MACRO:
-                       ps->macro.addMultiByteString(s, len, CP_UTF8);
+                       ps->macro.appendMBString(s, len, CP_UTF8);
                        break;
                default:
                        break;
index 5264285..d26e689 100644 (file)
@@ -218,7 +218,7 @@ void LogParserRule::expandMacros(const TCHAR *regexp, String &out)
                        // Check for escape
                        if ((curr != regexp) && (*(curr - 1) == _T('\\')))
                        {
-                               out.addString(prev, (UINT32)(curr - prev - 1));
+                               out.append(prev, (size_t)(curr - prev - 1));
                                out += _T("@");
                        }
                        else
@@ -228,7 +228,7 @@ void LogParserRule::expandMacros(const TCHAR *regexp, String &out)
                                {
                                        int i;
 
-                                       out.addString(prev, (UINT32)(curr - prev));
+                                       out.append(prev, (size_t)(curr - prev));
                                        curr += 2;
                                        for(i = 0; (*curr != 0) && (*curr != '}'); i++)
                                                name[i] = *curr++;
@@ -237,11 +237,11 @@ void LogParserRule::expandMacros(const TCHAR *regexp, String &out)
                                }
                                else
                                {
-                                       out.addString(prev, (UINT32)(curr - prev + 1));
+                                       out.append(prev, (size_t)(curr - prev + 1));
                                }
                        }
                        prev = curr + 1;
                }
        }
-       out.addString(prev, (UINT32)(curr - prev));
+       out.append(prev, (size_t)(curr - prev));
 }
index f541e4f..e07298f 100644 (file)
@@ -67,7 +67,7 @@ BOOL AgentPolicyConfig::saveToDatabase(DB_HANDLE hdb)
        if (success)
        {
                String data = DBPrepareString(hdb, m_fileContent);
-               int len = (int)data.getSize() + 256;
+               size_t len = data.length() + 256;
                TCHAR *query = (TCHAR *)malloc(len * sizeof(TCHAR));
 
                _sntprintf(query, len, _T("SELECT policy_id FROM ap_config_files WHERE policy_id=%d"), m_id);
index aa87192..4a96a4e 100644 (file)
@@ -146,10 +146,10 @@ void NXCORE_EXPORTABLE WriteAuditLog(const TCHAR *subsys, BOOL isSuccess, UINT32
        NXCPMessage msg;
 
        va_start(args, format);
-       text.addFormattedStringV(format, args);
+       text.appendFormattedStringV(format, args);
        va_end(args);
 
-       query.addFormattedString(_T("INSERT INTO audit_log (record_id,timestamp,subsystem,success,user_id,workstation,session_id,object_id,message) VALUES(%d,") TIME_T_FMT _T(",%s,%d,%d,%s,%d,%d,%s)"),
+       query.appendFormattedString(_T("INSERT INTO audit_log (record_id,timestamp,subsystem,success,user_id,workstation,session_id,object_id,message) VALUES(%d,") TIME_T_FMT _T(",%s,%d,%d,%s,%d,%d,%s)"),
       InterlockedIncrement(&m_recordId), time(NULL), (const TCHAR *)DBPrepareString(g_hCoreDB, subsys), isSuccess ? 1 : 0, 
                userId, (const TCHAR *)DBPrepareString(g_hCoreDB, workstation), sessionId, objectId, (const TCHAR *)DBPrepareString(g_hCoreDB, text));
        QueueSQLRequest(query);
@@ -176,10 +176,10 @@ void NXCORE_EXPORTABLE WriteAuditLog(const TCHAR *subsys, BOOL isSuccess, UINT32
                }
                else
                {
-                       extText.addFormattedString(_T("{%d}"), userId);
+                       extText.appendFormattedString(_T("{%d}"), userId);
                }
 
-               extText.addFormattedString(_T("@%s] "), workstation);
+               extText.appendFormattedString(_T("@%s] "), workstation);
 
                extText += (const TCHAR *)text;
                SendSyslogRecord((const TCHAR *)extText);
index 46a1f0c..1e2a374 100644 (file)
@@ -103,36 +103,36 @@ String ColumnFilter::generateSql()
                case FILTER_EQUALS:
                        if (m_negated)
                                sql += _T("NOT ");
-                       sql.addFormattedString(_T("%s = ") INT64_FMT, m_column, m_value.numericValue);
+                       sql.appendFormattedString(_T("%s = ") INT64_FMT, m_column, m_value.numericValue);
                        break;
                case FILTER_LESS:
                        if (m_negated)
                                sql += _T("NOT ");
-                       sql.addFormattedString(_T("%s < ") INT64_FMT, m_column, m_value.numericValue);
+                       sql.appendFormattedString(_T("%s < ") INT64_FMT, m_column, m_value.numericValue);
                        break;
                case FILTER_GREATER:
                        if (m_negated)
                                sql += _T("NOT ");
-                       sql.addFormattedString(_T("%s > ") INT64_FMT, m_column, m_value.numericValue);
+                       sql.appendFormattedString(_T("%s > ") INT64_FMT, m_column, m_value.numericValue);
                        break;
                case FILTER_RANGE:
                        if (m_negated)
                                sql += _T("NOT ");
-                       sql.addFormattedString(_T("%s BETWEEN ") INT64_FMT _T(" AND ") INT64_FMT, m_column, m_value.range.start, m_value.range.end);
+                       sql.appendFormattedString(_T("%s BETWEEN ") INT64_FMT _T(" AND ") INT64_FMT, m_column, m_value.range.start, m_value.range.end);
                        break;
                case FILTER_LIKE:
                        if (m_value.like[0] == 0)
                        {
                                if (m_negated)
-                                       sql.addFormattedString(_T("(%s IS NOT NULL) AND (%s <> '')"), m_column, m_column);
+                                       sql.appendFormattedString(_T("(%s IS NOT NULL) AND (%s <> '')"), m_column, m_column);
                                else
-                                       sql.addFormattedString(_T("(%s IS NULL) OR (%s = '')"), m_column, m_column);
+                                       sql.appendFormattedString(_T("(%s IS NULL) OR (%s = '')"), m_column, m_column);
                        }
                        else
                        {
                                if (m_negated)
                                        sql += _T("NOT ");
-                               sql.addFormattedString(_T("%s LIKE %s"), m_column, (const TCHAR *)DBPrepareString(g_hCoreDB, m_value.like));
+                               sql.appendFormattedString(_T("%s LIKE %s"), m_column, (const TCHAR *)DBPrepareString(g_hCoreDB, m_value.like));
                        }
                        break;
                case FILTER_SET:
index 17039b2..68e87b5 100644 (file)
@@ -47,6 +47,7 @@ TCHAR g_szDbSchema[MAX_DB_NAME] = _T("");
 static TCHAR s_encryptedDbPassword[MAX_DB_STRING] = _T("");
 static NX_CFG_TEMPLATE m_cfgTemplate[] =
 {
+   { _T("BackgroundLogWriter"), CT_BOOLEAN, 0, 0, AF_BACKGROUND_LOG_WRITER, 0, &g_flags, NULL },
    { _T("CodePage"), CT_MB_STRING, 0, 0, 256, 0, g_szCodePage, NULL },
    { _T("CreateCrashDumps"), CT_BOOLEAN, 0, 0, AF_CATCH_EXCEPTIONS, 0, &g_flags, NULL },
    { _T("DailyLogFileSuffix"), CT_STRING, 0, 0, 64, 0, g_szDailyLogFileSuffix, NULL },
index 530baad..53c1f54 100644 (file)
@@ -1485,7 +1485,7 @@ void DCItem::createNXMPRecord(String &str)
 
    lock();
 
-   str.addFormattedString(_T("\t\t\t\t<dci id=\"%d\">\n")
+   str.appendFormattedString(_T("\t\t\t\t<dci id=\"%d\">\n")
                           _T("\t\t\t\t\t<name>%s</name>\n")
                           _T("\t\t\t\t\t<description>%s</description>\n")
                           _T("\t\t\t\t\t<dataType>%d</dataType>\n")
@@ -1511,7 +1511,7 @@ void DCItem::createNXMPRecord(String &str)
        if (m_transformationScriptSource != NULL)
        {
                str += _T("\t\t\t\t\t<transformation>");
-               str.addDynamicString(EscapeStringForXML(m_transformationScriptSource, -1));
+               str.appendPreallocated(EscapeStringForXML(m_transformationScriptSource, -1));
                str += _T("</transformation>\n");
        }
 
@@ -1519,7 +1519,7 @@ void DCItem::createNXMPRecord(String &str)
    {
       str += _T("\t\t\t\t\t<schedules>\n");
       for(i = 0; i < m_dwNumSchedules; i++)
-         str.addFormattedString(_T("\t\t\t\t\t\t<schedule>%s</schedule>\n"), (const TCHAR *)EscapeStringForXML2(m_ppScheduleList[i]));
+         str.appendFormattedString(_T("\t\t\t\t\t\t<schedule>%s</schedule>\n"), (const TCHAR *)EscapeStringForXML2(m_ppScheduleList[i]));
       str += _T("\t\t\t\t\t</schedules>\n");
    }
 
@@ -1536,21 +1536,21 @@ void DCItem::createNXMPRecord(String &str)
        if (m_pszPerfTabSettings != NULL)
        {
                str += _T("\t\t\t\t\t<perfTabSettings>");
-               str.addDynamicString(EscapeStringForXML(m_pszPerfTabSettings, -1));
+               str.appendPreallocated(EscapeStringForXML(m_pszPerfTabSettings, -1));
                str += _T("</perfTabSettings>\n");
        }
 
    if (m_instanceDiscoveryData != NULL)
        {
                str += _T("\t\t\t\t\t<instanceDiscoveryData>");
-               str.addDynamicString(EscapeStringForXML(m_instanceDiscoveryData, -1));
+               str.appendPreallocated(EscapeStringForXML(m_instanceDiscoveryData, -1));
                str += _T("</instanceDiscoveryData>\n");
        }
 
    if (m_instanceFilterSource != NULL)
        {
                str += _T("\t\t\t\t\t<instanceFilter>");
-               str.addDynamicString(EscapeStringForXML(m_instanceFilterSource, -1));
+               str.appendPreallocated(EscapeStringForXML(m_instanceFilterSource, -1));
                str += _T("</instanceFilter>\n");
        }
 
index 83ad0d4..9dcf55c 100644 (file)
@@ -763,7 +763,7 @@ void Threshold::createNXMPRecord(String &str, int index)
 
    EventNameFromCode(m_eventCode, activationEvent);
    EventNameFromCode(m_rearmEventCode, deactivationEvent);
-   str.addFormattedString(_T("\t\t\t\t\t\t<threshold id=\"%d\">\n")
+   str.appendFormattedString(_T("\t\t\t\t\t\t<threshold id=\"%d\">\n")
                           _T("\t\t\t\t\t\t\t<function>%d</function>\n")
                           _T("\t\t\t\t\t\t\t<condition>%d</condition>\n")
                           _T("\t\t\t\t\t\t\t<value>%s</value>\n")
index 92abe7e..6a8fb05 100644 (file)
@@ -287,15 +287,15 @@ void DCObject::expandMacros(const TCHAR *src, TCHAR *dst, size_t dstLen)
        temp = src;
        while((index = temp.find(_T("%{"), index)) != String::npos)
        {
-               head = temp.subStr(0, index);
+               head = temp.substring(0, index);
                index2 = temp.find(_T("}"), index);
                if (index2 == String::npos)
                {
                        free(head);
                        break;  // Missing closing }
                }
-               rest = temp.subStr(index2 + 1, -1);
-               macro = temp.subStr(index + 2, index2 - index - 2);
+               rest = temp.substring(index2 + 1, -1);
+               macro = temp.substring(index + 2, index2 - index - 2);
                StrStrip(macro);
 
                temp = head;
@@ -303,7 +303,7 @@ void DCObject::expandMacros(const TCHAR *src, TCHAR *dst, size_t dstLen)
                {
                        if (m_pNode != NULL)
                        {
-                               temp.addFormattedString(_T("%d"), m_pNode->getId());
+                               temp.appendFormattedString(_T("%d"), m_pNode->getId());
                        }
                        else
                        {
index 2b2d727..a4e00d4 100644 (file)
@@ -1002,7 +1002,7 @@ void DCTable::createNXMPRecord(String &str)
 
    lock();
 
-   str.addFormattedString(_T("\t\t\t\t<dctable id=\"%d\">\n")
+   str.appendFormattedString(_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")
                           _T("\t\t\t\t\t<origin>%d</origin>\n")
@@ -1020,7 +1020,7 @@ void DCTable::createNXMPRecord(String &str)
        if (m_transformationScriptSource != NULL)
        {
                str += _T("\t\t\t\t\t<transformation>");
-               str.addDynamicString(EscapeStringForXML(m_transformationScriptSource, -1));
+               str.appendPreallocated(EscapeStringForXML(m_transformationScriptSource, -1));
                str += _T("</transformation>\n");
        }
 
@@ -1028,7 +1028,7 @@ void DCTable::createNXMPRecord(String &str)
    {
       str += _T("\t\t\t\t\t<schedules>\n");
       for(i = 0; i < m_dwNumSchedules; i++)
-         str.addFormattedString(_T("\t\t\t\t\t\t<schedule>%s</schedule>\n"), (const TCHAR *)EscapeStringForXML2(m_ppScheduleList[i]));
+         str.appendFormattedString(_T("\t\t\t\t\t\t<schedule>%s</schedule>\n"), (const TCHAR *)EscapeStringForXML2(m_ppScheduleList[i]));
       str += _T("\t\t\t\t\t</schedules>\n");
    }
 
@@ -1055,7 +1055,7 @@ void DCTable::createNXMPRecord(String &str)
        if (m_pszPerfTabSettings != NULL)
        {
                str += _T("\t\t\t\t\t<perfTabSettings>");
-               str.addDynamicString(EscapeStringForXML(m_pszPerfTabSettings, -1));
+               str.appendPreallocated(EscapeStringForXML(m_pszPerfTabSettings, -1));
                str += _T("</perfTabSettings>\n");
        }
 
index 920ac63..836cd21 100644 (file)
@@ -138,7 +138,7 @@ DCTableColumn::~DCTableColumn()
  */
 void DCTableColumn::createNXMPRecord(String &str, int id)
 {
-   str.addFormattedString(_T("\t\t\t\t\t\t<column id=\"%d\">\n")
+   str.appendFormattedString(_T("\t\t\t\t\t\t<column id=\"%d\">\n")
                           _T("\t\t\t\t\t\t\t<name>%s</name>\n")
                           _T("\t\t\t\t\t\t\t<displayName>%s</displayName>\n")
                           _T("\t\t\t\t\t\t\t<snmpOid>%s</snmpOid>\n")
index ee61e1f..ab8e2de 100644 (file)
@@ -529,7 +529,7 @@ void DCTableThreshold::createNXMPRecord(String &str, int id)
 
    EventNameFromCode(m_activationEvent, activationEvent);
    EventNameFromCode(m_deactivationEvent, deactivationEvent);
-   str.addFormattedString(_T("\t\t\t\t\t\t<threshold id=\"%d\">\n")
+   str.appendFormattedString(_T("\t\t\t\t\t\t<threshold id=\"%d\">\n")
                           _T("\t\t\t\t\t\t\t<activationEvent>%s</activationEvent>\n")
                           _T("\t\t\t\t\t\t\t<deactivationEvent>%s</deactivationEvent>\n")
                           _T("\t\t\t\t\t\t\t<groups>\n"),
@@ -537,12 +537,12 @@ void DCTableThreshold::createNXMPRecord(String &str, int id)
                                                                  (const TCHAR *)EscapeStringForXML2(deactivationEvent));
    for(int i = 0; i < m_groups->size(); i++)
    {
-      str.addFormattedString(_T("\t\t\t\t\t\t\t\t<group id=\"%d\">\n\t\t\t\t\t\t\t\t\t<conditions>\n"), i + 1);
+      str.appendFormattedString(_T("\t\t\t\t\t\t\t\t<group id=\"%d\">\n\t\t\t\t\t\t\t\t\t<conditions>\n"), i + 1);
       ObjectArray<DCTableCondition> *conditions = m_groups->get(i)->getConditions();
       for(int j = 0; j < conditions->size(); j++)
       {
          DCTableCondition *c = conditions->get(j);
-         str.addFormattedString(_T("\t\t\t\t\t\t\t\t\t\t<condition id=\"%d\">\n")
+         str.appendFormattedString(_T("\t\t\t\t\t\t\t\t\t\t<condition id=\"%d\">\n")
                                 _T("\t\t\t\t\t\t\t\t\t\t\t<column>%s</column>\n")
                                 _T("\t\t\t\t\t\t\t\t\t\t\t<operation>%d</operation>\n")
                                 _T("\t\t\t\t\t\t\t\t\t\t\t<value>%s</value>\n")
index 2aebcc2..0960b01 100644 (file)
@@ -229,7 +229,7 @@ EPRule::~EPRule()
  */
 void EPRule::createNXMPRecord(String &str)
 {
-   str.addFormattedString(_T("\t\t<rule id=\"%d\">\n")
+   str.appendFormattedString(_T("\t\t<rule id=\"%d\">\n")
                           _T("\t\t\t<flags>%d</flags>\n")
                           _T("\t\t\t<alarmMessage>%s</alarmMessage>\n")
                           _T("\t\t\t<alarmKey>%s</alarmKey>\n")
@@ -257,7 +257,7 @@ void EPRule::createNXMPRecord(String &str)
          uuid_t guid;
          object->getGuid(guid);
          TCHAR guidText[128];
-         str.addFormattedString(_T("\t\t\t\t<source id=\"%d\">\n")
+         str.appendFormattedString(_T("\t\t\t\t<source id=\"%d\">\n")
                                 _T("\t\t\t\t\t<name>%s</name>\n")
                                 _T("\t\t\t\t\t<guid>%s</guid>\n")
                                 _T("\t\t\t\t\t<class>%d</class>\n")
@@ -274,7 +274,7 @@ void EPRule::createNXMPRecord(String &str)
    {
       TCHAR eventName[MAX_EVENT_NAME];
       EventNameFromCode(m_pdwEventList[i], eventName);
-      str.addFormattedString(_T("\t\t\t\t<event id=\"%d\">\n")
+      str.appendFormattedString(_T("\t\t\t\t<event id=\"%d\">\n")
                              _T("\t\t\t\t\t<name>%s</name>\n")
                              _T("\t\t\t\t</event>\n"),
                              m_pdwEventList[i], (const TCHAR *)EscapeStringForXML2(eventName));
@@ -284,7 +284,7 @@ void EPRule::createNXMPRecord(String &str)
 
    for(UINT32 i = 0; i < m_dwNumActions; i++)
    {
-      str.addFormattedString(_T("\t\t\t\t<action id=\"%d\">\n")
+      str.appendFormattedString(_T("\t\t\t\t<action id=\"%d\">\n")
                              _T("\t\t\t\t</action>\n"),
                              m_pdwActionList[i]);
    }
index f10cc42..769ec38 100644 (file)
@@ -1089,7 +1089,7 @@ void CreateNXMPEventRecord(String &str, UINT32 eventCode)
       p = FindEventTemplate(eventCode);
       if (p != NULL)
       {
-         str.addFormattedString(_T("\t\t<event id=\"%d\">\n")
+         str.appendFormattedString(_T("\t\t<event id=\"%d\">\n")
                                               _T("\t\t\t<name>%s</name>\n")
                                 _T("\t\t\t<code>%d</code>\n")
                                 _T("\t\t\t<severity>%d</severity>\n")
index 44ee959..74978de 100644 (file)
@@ -175,7 +175,7 @@ String LogHandle::buildObjectAccessConstraint(const UINT32 userId)
 
       if (list->size() < 1000)
       {
-         constraint.addFormattedString(_T("%s IN ("), m_log->relatedObjectIdColumn);
+         constraint.appendFormattedString(_T("%s IN ("), m_log->relatedObjectIdColumn);
          for(int i = 0; i < list->size(); i++)
          {
             TCHAR buffer[32];
@@ -190,7 +190,7 @@ String LogHandle::buildObjectAccessConstraint(const UINT32 userId)
          for(int i = 0; i < list->size(); i++)
          {
             TCHAR buffer[32];
-                       constraint.addFormattedString(_T("(%s=%d)OR"), m_log->relatedObjectIdColumn, list->get(i));
+                       constraint.appendFormattedString(_T("(%s=%d)OR"), m_log->relatedObjectIdColumn, list->get(i));
             constraint += buffer;
          }
          constraint.shrink(2);
@@ -215,23 +215,23 @@ bool LogHandle::queryInternal(INT64 *rowCount, const UINT32 userId)
        switch(g_dbSyntax)
        {
                case DB_SYNTAX_MSSQL:
-                       query.addFormattedString(_T("SELECT TOP %u %s FROM %s "), m_rowCountLimit, (const TCHAR *)m_queryColumns, m_log->table);
+                       query.appendFormattedString(_T("SELECT TOP %u %s FROM %s "), m_rowCountLimit, (const TCHAR *)m_queryColumns, m_log->table);
                        break;
                case DB_SYNTAX_INFORMIX:
-                       query.addFormattedString(_T("SELECT FIRST %u %s FROM %s "), m_rowCountLimit, (const TCHAR *)m_queryColumns, m_log->table);
+                       query.appendFormattedString(_T("SELECT FIRST %u %s FROM %s "), m_rowCountLimit, (const TCHAR *)m_queryColumns, m_log->table);
                        break;
                case DB_SYNTAX_ORACLE:
-                       query.addFormattedString(_T("SELECT * FROM (SELECT %s FROM %s"), (const TCHAR *)m_queryColumns, m_log->table);
+                       query.appendFormattedString(_T("SELECT * FROM (SELECT %s FROM %s"), (const TCHAR *)m_queryColumns, m_log->table);
                        break;
                case DB_SYNTAX_SQLITE:
                case DB_SYNTAX_PGSQL:
                case DB_SYNTAX_MYSQL:
                case DB_SYNTAX_DB2:
-                       query.addFormattedString(_T("SELECT %s FROM %s"), (const TCHAR *)m_queryColumns, m_log->table);
+                       query.appendFormattedString(_T("SELECT %s FROM %s"), (const TCHAR *)m_queryColumns, m_log->table);
                        break;
        }
 
-       query.addFormattedString(_T(" WHERE %s<=") INT64_FMT, m_log->idColumn, m_maxRecordId);
+       query.appendFormattedString(_T(" WHERE %s<=") INT64_FMT, m_log->idColumn, m_maxRecordId);
 
        int filterSize = m_filter->getNumColumnFilter();
        if (filterSize > 0)
@@ -264,13 +264,13 @@ bool LogHandle::queryInternal(INT64 *rowCount, const UINT32 userId)
                case DB_SYNTAX_MYSQL:
                case DB_SYNTAX_PGSQL:
                case DB_SYNTAX_SQLITE:
-                       query.addFormattedString(_T(" LIMIT %u"), m_rowCountLimit);
+                       query.appendFormattedString(_T(" LIMIT %u"), m_rowCountLimit);
                        break;
                case DB_SYNTAX_ORACLE:
-                       query.addFormattedString(_T(") WHERE ROWNUM<=%u"), m_rowCountLimit);
+                       query.appendFormattedString(_T(") WHERE ROWNUM<=%u"), m_rowCountLimit);
                        break;
                case DB_SYNTAX_DB2:
-                       query.addFormattedString(_T(" FETCH FIRST %u ROWS ONLY"), m_rowCountLimit);
+                       query.appendFormattedString(_T(" FETCH FIRST %u ROWS ONLY"), m_rowCountLimit);
                        break;
        }
 
index ea2f455..1b60cff 100644 (file)
@@ -568,7 +568,9 @@ BOOL NXCORE_EXPORTABLE Initialize()
                                _tprintf(_T("WARNING: cannot set log rotation policy; using default values\n"));
        }
    if (!nxlog_open((g_flags & AF_USE_SYSLOG) ? NETXMSD_SYSLOG_NAME : g_szLogFile,
-                       ((g_flags & AF_USE_SYSLOG) ? NXLOG_USE_SYSLOG : 0) | ((g_flags & AF_DAEMON) ? 0 : NXLOG_PRINT_TO_STDOUT),
+                       ((g_flags & AF_USE_SYSLOG) ? NXLOG_USE_SYSLOG : 0) | 
+                       ((g_flags & AF_BACKGROUND_LOG_WRITER) ? NXLOG_BACKGROUND_WRITER : 0) | 
+                   ((g_flags & AF_DAEMON) ? 0 : NXLOG_PRINT_TO_STDOUT),
                    _T("LIBNXSRV.DLL"),
 #ifdef _WIN32
                                       0, NULL))
@@ -1331,6 +1333,7 @@ int ProcessConsoleCommand(const TCHAR *pszCmdLine, CONSOLE_CTX pCtx)
                        ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_TRAPS_FROM_UNMANAGED_NODES));
                        ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_RESOLVE_IP_FOR_EACH_STATUS_POLL));
                        ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_PERFDATA_STORAGE_DRIVER_LOADED));
+                       ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_BACKGROUND_LOG_WRITER));
                        ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_SERVER_INITIALIZED));
                        ConsolePrintf(pCtx, SHOW_FLAG_VALUE(AF_SHUTDOWN));
                        ConsolePrintf(pCtx, _T("\n"));
index 9b1a53f..fb7d556 100644 (file)
@@ -291,7 +291,7 @@ BOOL NetworkMap::saveToDatabase(DB_HANDLE hdb)
                e->updateConfig(config);
                String data = DBPrepareString(hdb, config->createXml());
                delete config;
-               int len = data.getSize() + 256;
+               size_t len = data.length() + 256;
                TCHAR *eq = (TCHAR *)malloc(len * sizeof(TCHAR));
       _sntprintf(eq, len, _T("INSERT INTO network_map_elements (map_id,element_id,element_type,element_data,flags) VALUES (%d,%d,%d,%s,%d)"),
                           m_id, e->getId(), e->getType(), (const TCHAR *)data, e->getFlags());
index 2a5d232..09e7bae 100644 (file)
@@ -4851,7 +4851,7 @@ void ClientSession::changeObjectBinding(NXCPMessage *pRequest, BOOL bBind)
                if ((pParent->getObjectClass() == OBJECT_TEMPLATE) &&
                    ((pChild->getObjectClass() == OBJECT_NODE) || (pChild->getObjectClass() == OBJECT_CLUSTER) || (pChild->getObjectClass() == OBJECT_MOBILEDEVICE)))
                {
-                  ((Template *)pParent)->queueRemoveFromTarget(pChild->getId(), pRequest->getFieldAsUInt16(VID_REMOVE_DCI));
+                  ((Template *)pParent)->queueRemoveFromTarget(pChild->getId(), pRequest->getFieldAsBoolean(VID_REMOVE_DCI));
                }
                else if ((pParent->getObjectClass() == OBJECT_CLUSTER) &&
                         (pChild->getObjectClass() == OBJECT_NODE))
@@ -8006,7 +8006,7 @@ void ClientSession::updateScript(NXCPMessage *pRequest)
                                String prepCode = DBPrepareString(g_hCoreDB, pszCode);
             free(pszCode);
 
-                               size_t qlen = (size_t)prepCode.getSize() + MAX_DB_STRING + 256;
+                               size_t qlen = prepCode.length() + MAX_DB_STRING + 256;
             pszQuery = (TCHAR *)malloc(qlen * sizeof(TCHAR));
 
             if (dwScriptId == 0)
@@ -9537,7 +9537,7 @@ void ClientSession::exportConfiguration(NXCPMessage *pRequest)
 
          str = _T("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration>\n\t<formatVersion>3</formatVersion>\n\t<description>");
                        temp = pRequest->getFieldAsString(VID_DESCRIPTION);
-                       str.addDynamicString(EscapeStringForXML(temp, -1));
+                       str.appendPreallocated(EscapeStringForXML(temp, -1));
                        free(temp);
          str += _T("</description>\n");
 
index 124809f..6e6eb6a 100644 (file)
@@ -939,7 +939,7 @@ void CreateNXMPTrapRecord(String &str, UINT32 dwId)
    {
       if (m_pTrapCfg[i].dwId == dwId)
       {
-                       str.addFormattedString(_T("\t\t<trap id=\"%d\">\n")
+                       str.appendFormattedString(_T("\t\t<trap id=\"%d\">\n")
                                               _T("\t\t\t<oid>%s</oid>\n")
                                               _T("\t\t\t<description>%s</description>\n")
                                               _T("\t\t\t<userTag>%s</userTag>\n"), dwId,
@@ -950,27 +950,27 @@ void CreateNXMPTrapRecord(String &str, UINT32 dwId)
                                                                                  (const TCHAR *)EscapeStringForXML2(m_pTrapCfg[i].szUserTag));
 
                   EventNameFromCode(m_pTrapCfg[i].dwEventCode, szBuffer);
-                       str.addFormattedString(_T("\t\t\t<event>%s</event>\n"), (const TCHAR *)EscapeStringForXML2(szBuffer));
+                       str.appendFormattedString(_T("\t\t\t<event>%s</event>\n"), (const TCHAR *)EscapeStringForXML2(szBuffer));
                        if (m_pTrapCfg[i].dwNumMaps > 0)
                        {
                                str += _T("\t\t\t<parameters>\n");
                                for(j = 0; j < m_pTrapCfg[i].dwNumMaps; j++)
                                {
-                                       str.addFormattedString(_T("\t\t\t\t<parameter id=\"%d\">\n")
+                                       str.appendFormattedString(_T("\t\t\t\t<parameter id=\"%d\">\n")
                                                     _T("\t\t\t\t\t<flags>%d</flags>\n")
                                                               _T("\t\t\t\t\t<description>%s</description>\n"),
                                                                                                  j + 1, m_pTrapCfg[i].pMaps[j].dwFlags,
                                                                                                  (const TCHAR *)EscapeStringForXML2(m_pTrapCfg[i].pMaps[j].szDescription));
                if ((m_pTrapCfg[i].pMaps[j].dwOidLen & 0x80000000) == 0)
                                        {
-                                               str.addFormattedString(_T("\t\t\t\t\t<oid>%s</oid>\n"),
+                                               str.appendFormattedString(_T("\t\t\t\t\t<oid>%s</oid>\n"),
                                                                       SNMPConvertOIDToText(m_pTrapCfg[i].pMaps[j].dwOidLen,
                                                                                                                               m_pTrapCfg[i].pMaps[j].pdwObjectId,
                                                                                                                                                                  szBuffer, 1024));
                                        }
                                        else
                                        {
-                                               str.addFormattedString(_T("\t\t\t\t\t<position>%d</position>\n"),
+                                               str.appendFormattedString(_T("\t\t\t\t\t<position>%d</position>\n"),
                                                                       m_pTrapCfg[i].pMaps[j].dwOidLen & 0x7FFFFFFF);
                                        }
                                        str += _T("\t\t\t\t</parameter>\n");
index afff7b3..8790301 100644 (file)
@@ -989,7 +989,7 @@ UINT32 *Template::getDCIEventsList(UINT32 *pdwCount)
  */
 void Template::createNXMPRecord(String &str)
 {
-   str.addFormattedString(_T("\t\t<template id=\"%d\">\n\t\t\t<name>%s</name>\n\t\t\t<flags>%d</flags>\n\t\t\t<dataCollection>\n"),
+   str.appendFormattedString(_T("\t\t<template id=\"%d\">\n\t\t\t<name>%s</name>\n\t\t\t<flags>%d</flags>\n\t\t\t<dataCollection>\n"),
                               m_id, (const TCHAR *)EscapeStringForXML2(m_name), m_flags);
 
    lockDciAccess(false);
@@ -1002,7 +1002,7 @@ void Template::createNXMPRecord(String &str)
        if (m_applyFilterSource != NULL)
        {
                str += _T("\t\t\t<filter>");
-               str.addDynamicString(EscapeStringForXML(m_applyFilterSource, -1));
+               str.appendPreallocated(EscapeStringForXML(m_applyFilterSource, -1));
                str += _T("</filter>\n");
        }
        unlockProperties();
index dc3fd68..b6b4269 100644 (file)
 #define AF_SNMP_TRAP_DISCOVERY                 _ULL(0x0000000020000000)
 #define AF_TRAPS_FROM_UNMANAGED_NODES          _ULL(0x0000000040000000)
 #define AF_RESOLVE_IP_FOR_EACH_STATUS_POLL     _ULL(0x0000000080000000)
-#define AF_PERFDATA_STORAGE_DRIVER_LOADED      _ULL(0x0000000080000000)
+#define AF_PERFDATA_STORAGE_DRIVER_LOADED      _ULL(0x0000000100000000)
+#define AF_BACKGROUND_LOG_WRITER               _ULL(0x0000000200000000)
 #define AF_SERVER_INITIALIZED                  _ULL(0x4000000000000000)
 #define AF_SHUTDOWN                            _ULL(0x8000000000000000)
 
index a02991f..cca1762 100644 (file)
@@ -91,7 +91,7 @@ static BOOL ExportTable(sqlite3 *db, const TCHAR *name)
 
                                // Column names
                                columnCount = DBGetColumnCountAsync(hResult);
-                               query.addFormattedString(_T("INSERT INTO %s ("), name);
+                               query.appendFormattedString(_T("INSERT INTO %s ("), name);
                                for(i = 0; i < columnCount; i++)
                                {
                                        DBGetColumnNameAsync(hResult, i, buffer, 256);
@@ -106,7 +106,7 @@ static BOOL ExportTable(sqlite3 *db, const TCHAR *name)
                                for(i = 0; i < columnCount; i++)
                                {
                                        TCHAR *escapedString = EscapeString(DBGetFieldAsync(hResult, i, data, 8192));
-                                       query.addDynamicString(escapedString);
+                                       query.appendPreallocated(escapedString);
                                        query += _T(",");
                                }
                                query.shrink();
index 105f9a7..177bad1 100644 (file)
@@ -36,10 +36,10 @@ static int ImportTableCB(void *arg, int cols, char **data, char **names)
        String query;
        int i;
 
-       query.addFormattedString(_T("INSERT INTO %s ("), arg);
+       query.appendFormattedString(_T("INSERT INTO %s ("), arg);
        for(i = 0; i < cols; i++)
        {
-               query.addMultiByteString(names[i], (DWORD)strlen(names[i]), CP_UTF8);
+               query.appendMBString(names[i], strlen(names[i]), CP_UTF8);
                query += _T(",");
        }
        query.shrink();
index 1b3ada6..bac50dd 100644 (file)
@@ -114,7 +114,7 @@ BOOL ExecSQLBatch(const char *pszFile)
                static const TCHAR *dbengine[] = { _T("mysql"), _T("pgsql"), _T("mssql"), _T("oracle"), _T("sqlite"), _T("db2"), _T("informix") };
 
                String name;
-               name.addMultiByteString(pszFile, (DWORD)strlen(pszFile), CP_ACP);
+               name.appendMBString(pszFile, strlen(pszFile), CP_ACP);
                name.replace(_T("@dbengine@"), dbengine[g_dbSyntax]);
           pBatch = LoadFile(name, &dwSize);
           if (pBatch == NULL)
index eb80656..5a14f5d 100644 (file)
@@ -146,7 +146,7 @@ static BOOL ConvertStrings(const TCHAR *table, const TCHAR *idColumn, const TCHA
 {
        DB_RESULT hResult;
        TCHAR *query;
-       int queryLen = 512;
+       size_t queryLen = 512;
        BOOL success = FALSE;
 
        query = (TCHAR *)malloc(queryLen * sizeof(TCHAR));
@@ -186,9 +186,9 @@ static BOOL ConvertStrings(const TCHAR *table, const TCHAR *idColumn, const TCHA
                {
                        DecodeSQLString(value);
                        String newValue = DBPrepareString(g_hCoreDB, value);
-                       if ((int)newValue.getSize() + 256 > queryLen)
+                       if (newValue.length() + 256 > queryLen)
                        {
-                               queryLen = newValue.getSize() + 256;
+                               queryLen = newValue.length() + 256;
                                query = (TCHAR *)realloc(query, queryLen * sizeof(TCHAR));
                        }
                        if (isStringId)
index bb787c4..7d44d5c 100644 (file)
@@ -181,11 +181,94 @@ static void TestStringSet()
    delete s;
 }
 
+/**
+ * Test string class
+ */
+static void TestString()
+{
+   String s;
+
+   StartTest(_T("String - append"));
+   for(int i = 0; i < 256; i++)
+      s.append(_T("ABC "));
+   AssertEquals(s.length(), 1024);
+   AssertTrue(!_tcsncmp(s.getBuffer(), _T("ABC ABC ABC ABC "), 16));
+   EndTest();
+
+   StartTest(_T("String - assign #1"));
+   s = _T("alpha");
+   AssertEquals(s.length(), 5);
+   AssertTrue(!_tcscmp(s.getBuffer(), _T("alpha")));
+   EndTest();
+
+   StartTest(_T("String - assign #2"));
+   String t(_T("init string"));
+   s = t;
+   AssertEquals(s.length(), 11);
+   AssertTrue(!_tcscmp(s.getBuffer(), _T("init string")));
+   EndTest();
+
+   StartTest(_T("String - shrink"));
+   s.shrink();
+   AssertEquals(s.length(), 10);
+   AssertTrue(!_tcscmp(s.getBuffer(), _T("init strin")));
+   EndTest();
+
+   StartTest(_T("String - escape"));
+   s.escapeCharacter('i', '+');
+   AssertEquals(s.length(), 13);
+   AssertTrue(!_tcscmp(s.getBuffer(), _T("+in+it str+in")));
+   EndTest();
+
+   StartTest(_T("String - replace #1"));
+   s = _T("alpha beta gamma");
+   s.replace(_T("beta"), _T("epsilon"));
+   AssertEquals(s.length(), 19);
+   AssertTrue(!_tcscmp(s.getBuffer(), _T("alpha epsilon gamma")));
+   EndTest();
+
+   StartTest(_T("String - replace #2"));
+   s = _T("alpha beta gamma");
+   s.replace(_T("beta"), _T("xxxx"));
+   AssertEquals(s.length(), 16);
+   AssertTrue(!_tcscmp(s.getBuffer(), _T("alpha xxxx gamma")));
+   EndTest();
+
+   StartTest(_T("String - replace #3"));
+   s = _T("alpha beta gamma alpha omega");
+   s.replace(_T("alpha"), _T("Z"));
+   AssertEquals(s.length(), 20);
+   AssertTrue(!_tcscmp(s.getBuffer(), _T("Z beta gamma Z omega")));
+   EndTest();
+
+   StartTest(_T("String - substring #1"));
+   s = _T("alpha beta gamma");
+   TCHAR *str = s.substring(0, 5);
+   AssertTrue(!_tcscmp(str, _T("alpha")));
+   free(str);
+   EndTest();
+
+   StartTest(_T("String - substring #2"));
+   s = _T("alpha beta gamma");
+   str = s.substring(5, -1);
+   AssertTrue(!_tcscmp(str, _T(" beta gamma")));
+   free(str);
+   EndTest();
+
+   StartTest(_T("String - substring #3"));
+   s = _T("alpha beta gamma");
+   str = s.substring(14, 4);
+   AssertTrue(!_tcscmp(str, _T("ma")));
+   free(str);
+   EndTest();
+}
+
 /**
  * main()
  */
 int main(int argc, char *argv[])
 {
+   TestString();
    TestStringConversion();
    TestStringMap();
    TestStringSet();