correct handling of monitored log rename and delete
authorVictor Kirhenshtein <victor@netxms.org>
Wed, 21 Oct 2009 19:27:21 +0000 (19:27 +0000)
committerVictor Kirhenshtein <victor@netxms.org>
Wed, 21 Oct 2009 19:27:21 +0000 (19:27 +0000)
reconf
src/libnxlp/unixfile.cpp

diff --git a/reconf b/reconf
index 6a38572..b4b2b47 100755 (executable)
--- a/reconf
+++ b/reconf
@@ -13,8 +13,14 @@ ACLOCAL=aclocal
 AUTOCONF=autoconf
 AUTOHEADER=autoheader
 AUTOMAKE=automake
-which libtoolize > /dev/null && LIBTOOLIZE=libtoolize
-which glibtoolize > /dev/null && LIBTOOLIZE=glibtoolize
+if test -x `which libtoolize`; then
+       LIBTOOLIZE=libtoolize
+fi
+if test -x `which glibtoolize`; then
+       LIBTOOLIZE=glibtoolize
+fi
+#which libtoolize > /dev/null && LIBTOOLIZE=libtoolize
+#which glibtoolize > /dev/null && LIBTOOLIZE=glibtoolize
 
 mkdir -p config
 touch README
index 4ff956e..9902a17 100644 (file)
-/*\r
-** NetXMS - Network Management System\r
-** Log Parsing Library\r
-** Copyright (C) 2008, 2009 Victor Kirhenshtein\r
-**\r
-** This program is free software; you can redistribute it and/or modify\r
-** it under the terms of the GNU General Public License as published by\r
-** the Free Software Foundation; either version 2 of the License, or\r
-** (at your option) any later version.\r
-**\r
-** This program is distributed in the hope that it will be useful,\r
-** but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-** GNU General Public License for more details.\r
-**\r
-** You should have received a copy of the GNU General Public License\r
-** along with this program; if not, write to the Free Software\r
-** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
-**\r
-** File: unixfile.cpp\r
-**\r
-**/\r
-\r
-#include "libnxlp.h"\r
-\r
-\r
-//\r
-// Constants\r
-//\r
-\r
-#define READ_BUFFER_SIZE      4096\r
-\r
-\r
-//\r
-// Generate current file name\r
-// \r
-\r
-static void GenerateCurrentFileName(LogParser *parser, char *fname)\r
-{\r
-       time_t t;\r
-       struct tm *ltm;\r
-#if HAVE_LOCALTIME_R\r
-       struct tm buffer;\r
-#endif\r
-\r
-       t = time(NULL);\r
-#if HAVE_LOCALTIME_R\r
-       ltm = localtime_r(&t, &buffer);\r
-#else\r
-       ltm = localtime(&t);\r
-#endif\r
-       _tcsftime(fname, MAX_PATH, parser->getFileName(), ltm);\r
-}\r
-\r
-\r
-//\r
-// Parse new log records\r
-//\r
-\r
-static void ParseNewRecords(LogParser *parser, int fh)\r
-{\r
-   char *ptr, *eptr, buffer[READ_BUFFER_SIZE];\r
-   int bytes, bufPos = 0;\r
-\r
-   do\r
-   {\r
-      if ((bytes = read(fh, &buffer[bufPos], READ_BUFFER_SIZE - bufPos)) > 0)\r
-      {\r
-         bytes += bufPos;\r
-         for(ptr = buffer;; ptr = eptr + 1)\r
-         {\r
-            bufPos = ptr - buffer;\r
-            eptr = (char *)memchr(ptr, '\n', bytes - bufPos);\r
-            if (eptr == NULL)\r
-            {\r
-                                       bufPos = bytes - bufPos;\r
-               memmove(buffer, ptr, bufPos);\r
-               break;\r
-            }\r
-                               if (*(eptr - 1) == '\r')\r
-                                       *(eptr - 1) = 0;\r
-                               else\r
-                                       *eptr = 0;\r
-                               parser->matchLine(ptr);\r
-         }\r
-      }\r
-      else\r
-      {\r
-         bytes = 0;\r
-      }\r
-   } while(bytes == READ_BUFFER_SIZE);\r
-}\r
-\r
-\r
-//\r
-// File parser thread\r
-//\r
-\r
-bool LogParser::monitorFile(CONDITION stopCondition, bool *stopFlag, void (*logger)(int, const TCHAR *, ...))\r
-{\r
-       char fname[MAX_PATH], temp[MAX_PATH];\r
-       struct stat st, stn;\r
-       size_t size;\r
-       int err, fh;\r
-\r
-       if ((m_fileName == NULL) || (stopFlag == NULL))\r
-               return false;\r
-\r
-\r
-       if (logger != NULL)\r
-               logger(EVENTLOG_DEBUG_TYPE, _T("LogParser: parser thread for file \"%s\" started"), m_fileName);\r
-\r
-       while(!(*stopFlag))\r
-       {\r
-               GenerateCurrentFileName(this, fname);\r
-               if (stat(fname, &st) == 0)\r
-               {\r
-                       fh = open(fname, O_RDONLY);\r
-                       if (fh != -1)\r
-                       {\r
-                               size = st.st_size;\r
-                               lseek(fh, 0, SEEK_END);\r
-\r
-                               if (logger != NULL)\r
-                                       logger(EVENTLOG_DEBUG_TYPE, _T("LogParser: file \"%s\" successfully opened"), m_fileName);\r
-\r
-                               while(!(*stopFlag))\r
-                               {\r
-                                       ThreadSleep(1);\r
-\r
-                                       // Check if file name was changed\r
-                                       GenerateCurrentFileName(this, temp);\r
-                                       if (_tcscmp(temp, fname))\r
-                                       {\r
-                                               if (logger != NULL)\r
-                                                       logger(EVENTLOG_DEBUG_TYPE, _T("LogParser: file name change for \"%s\" (\"%s\" -> \"%s\")"),\r
-                                                         m_fileName, fname, temp);\r
-                                               break;\r
-                                       }\r
-                                       \r
-                                       if ((fstat(fh, &st) < 0) || (stat(fname, &stn) < 0))\r
-                                               break;\r
-\r
-                                       if (st.st_size != stn.st_size)\r
-                                       {\r
-                                               if (logger != NULL)\r
-                                                       logger(EVENTLOG_DEBUG_TYPE, _T("LogParser: file size differs for stat(%d) and fstat(%s), assume file rename"), fh, fname);\r
-                                               break;\r
-                                       }\r
-                                               \r
-                                       if (st.st_size != size)\r
-                                       {\r
-                                               if (st.st_size < size)\r
-                                               {\r
-                                                       // File was cleared, start from the beginning\r
-                                                       lseek(fh, 0, SEEK_SET);\r
-                                                       if (logger != NULL)\r
-                                                               logger(EVENTLOG_DEBUG_TYPE, _T("LogParser: file \"%s\" st_size != size"), m_fileName);\r
-                                               }\r
-                                               size = st.st_size;\r
-                                               if (logger != NULL)\r
-                                                       logger(EVENTLOG_DEBUG_TYPE, _T("LogParser: new data avialable in file \"%s\""), m_fileName);\r
-                                               ParseNewRecords(this, fh);\r
-                                       }\r
-                               }\r
-                               close(fh);\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       if (ConditionWait(stopCondition, 10000))\r
-                               break;\r
-               }\r
-       }\r
-\r
-       if (logger != NULL)\r
-               logger(EVENTLOG_DEBUG_TYPE, _T("LogParser: parser thread for file \"%s\" stopped"), m_fileName);\r
-       return true;\r
-}\r
+/*
+** NetXMS - Network Management System
+** Log Parsing Library
+** Copyright (C) 2008, 2009 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: unixfile.cpp
+**
+**/
+
+#include "libnxlp.h"
+
+
+//
+// Constants
+//
+
+#define READ_BUFFER_SIZE      4096
+
+
+//
+// Generate current file name
+// 
+
+static void GenerateCurrentFileName(LogParser *parser, char *fname)
+{
+       time_t t;
+       struct tm *ltm;
+#if HAVE_LOCALTIME_R
+       struct tm buffer;
+#endif
+
+       t = time(NULL);
+#if HAVE_LOCALTIME_R
+       ltm = localtime_r(&t, &buffer);
+#else
+       ltm = localtime(&t);
+#endif
+       _tcsftime(fname, MAX_PATH, parser->getFileName(), ltm);
+}
+
+
+//
+// Parse new log records
+//
+
+static void ParseNewRecords(LogParser *parser, int fh)
+{
+   char *ptr, *eptr, buffer[READ_BUFFER_SIZE];
+   int bytes, bufPos = 0;
+
+   do
+   {
+      if ((bytes = read(fh, &buffer[bufPos], READ_BUFFER_SIZE - bufPos)) > 0)
+      {
+         bytes += bufPos;
+         for(ptr = buffer;; ptr = eptr + 1)
+         {
+            bufPos = ptr - buffer;
+            eptr = (char *)memchr(ptr, '\n', bytes - bufPos);
+            if (eptr == NULL)
+            {
+                                       bufPos = bytes - bufPos;
+               memmove(buffer, ptr, bufPos);
+               break;
+            }
+                               if (*(eptr - 1) == '\r')
+                                       *(eptr - 1) = 0;
+                               else
+                                       *eptr = 0;
+                               parser->matchLine(ptr);
+         }
+      }
+      else
+      {
+         bytes = 0;
+      }
+   } while(bytes == READ_BUFFER_SIZE);
+}
+
+
+//
+// File parser thread
+//
+
+bool LogParser::monitorFile(CONDITION stopCondition, bool *stopFlag, void (*logger)(int, const TCHAR *, ...))
+{
+       char fname[MAX_PATH], temp[MAX_PATH];
+       struct stat st, stn;
+       size_t size;
+       int err, fh;
+       bool readFromStart = false;
+
+       if ((m_fileName == NULL) || (stopFlag == NULL))
+               return false;
+
+
+       if (logger != NULL)
+               logger(EVENTLOG_DEBUG_TYPE, _T("LogParser: parser thread for file \"%s\" started"), m_fileName);
+
+       while(!(*stopFlag))
+       {
+               GenerateCurrentFileName(this, fname);
+               if (stat(fname, &st) == 0)
+               {
+                       fh = open(fname, O_RDONLY);
+                       if (fh != -1)
+                       {
+                               size = st.st_size;
+                               if (readFromStart)
+                               {
+                                       ParseNewRecords(this, fh);
+                                       readFromStart = false;
+                               }
+                               else
+                               {
+                                       lseek(fh, 0, SEEK_END);
+                               }
+
+                               if (logger != NULL)
+                                       logger(EVENTLOG_DEBUG_TYPE, _T("LogParser: file \"%s\" successfully opened"), m_fileName);
+
+                               while(!(*stopFlag))
+                               {
+                                       ThreadSleep(1);
+
+                                       // Check if file name was changed
+                                       GenerateCurrentFileName(this, temp);
+                                       if (_tcscmp(temp, fname))
+                                       {
+                                               if (logger != NULL)
+                                                       logger(EVENTLOG_DEBUG_TYPE, _T("LogParser: file name change for \"%s\" (\"%s\" -> \"%s\")"),
+                                                         m_fileName, fname, temp);
+                                               readFromStart = true;
+                                               break;
+                                       }
+                                       
+                                       if ((fstat(fh, &st) < 0) || (stat(fname, &stn) < 0))
+                                       {
+                                               if (logger != NULL)
+                                                       logger(EVENTLOG_DEBUG_TYPE, _T("LogParser: stat(%d) or fstat(%s) failed, errno=%d"), fh, fname, errno);
+                                               readFromStart = true;
+                                               break;
+                                       }
+
+                                       if (st.st_size != stn.st_size)
+                                       {
+                                               if (logger != NULL)
+                                                       logger(EVENTLOG_DEBUG_TYPE, _T("LogParser: file size differs for stat(%d) and fstat(%s), assume file rename"), fh, fname);
+                                               readFromStart = true;
+                                               break;
+                                       }
+                                               
+                                       if (st.st_size != size)
+                                       {
+                                               if (st.st_size < size)
+                                               {
+                                                       // File was cleared, start from the beginning
+                                                       lseek(fh, 0, SEEK_SET);
+                                                       if (logger != NULL)
+                                                               logger(EVENTLOG_DEBUG_TYPE, _T("LogParser: file \"%s\" st_size != size"), m_fileName);
+                                               }
+                                               size = st.st_size;
+                                               if (logger != NULL)
+                                                       logger(EVENTLOG_DEBUG_TYPE, _T("LogParser: new data avialable in file \"%s\""), m_fileName);
+                                               ParseNewRecords(this, fh);
+                                       }
+                               }
+                               close(fh);
+                       }
+               }
+               else
+               {
+                       if (ConditionWait(stopCondition, 10000))
+                               break;
+               }
+       }
+
+       if (logger != NULL)
+               logger(EVENTLOG_DEBUG_TYPE, _T("LogParser: parser thread for file \"%s\" stopped"), m_fileName);
+       return true;
+}