implemented log file monitoring using Windows VSS snapshots
[public/netxms.git] / src / nxlptest / nxlptest.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** NetXMS Log Parser Testing Utility
4 ** Copyright (C) 2009-2017 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: nxlptest.cpp
21 **
22 **/
23
24 #include "nxlptest.h"
25
26 #ifndef _WIN32
27 #include <signal.h>
28 #endif
29
30 /**
31 * Stop condition
32 */
33 static CONDITION m_stopCondition = INVALID_CONDITION_HANDLE;
34
35 /**
36 * Help text
37 */
38 static TCHAR m_helpText[] =
39 _T("NetXMS Log Parsing Tester Version ") NETXMS_VERSION_STRING _T("\n")
40 _T("Copyright (c) 2009-2012 Victor Kirhenshtein\n\n")
41 _T("Usage:\n")
42 _T(" nxlptest [options] parser\n\n")
43 _T("Where valid options are:\n")
44 _T(" -D level : Set debug level\n")
45 _T(" -f file : Input file (overrides parser settings)\n")
46 _T(" -h : Show this help\n")
47 _T(" -i : Use standard input instead of file defined in parser\n" )
48 #ifdef _WIN32
49 _T(" -s : Use VSS snapshots (overrides parser settings)\n")
50 #endif
51 _T(" -t level : Set trace level (overrides parser settings)\n")
52 _T(" -v : Show version and exit\n")
53 _T("\n");
54
55 /**
56 * Debug writer
57 */
58 static void DebugWriter(const TCHAR *tag, const TCHAR *message)
59 {
60 _tprintf(_T("[%s] %s\n"), tag, message);
61 }
62
63 /**
64 * Trace callback
65 */
66 static void TraceCallback(int level, const TCHAR *format, va_list args)
67 {
68 _vtprintf(format, args);
69 _puttc(_T('\n'), stdout);
70 }
71
72 /**
73 * Logger callback
74 */
75 static void LoggerCallback(int level, const TCHAR *format, va_list args)
76 {
77 TraceCallback(level, format, args);
78 }
79
80 /**
81 * File parsing thread
82 */
83 static THREAD_RESULT THREAD_CALL ParserThread(void *arg)
84 {
85 ((LogParser *)arg)->monitorFile(m_stopCondition);
86 return THREAD_OK;
87 }
88
89 #ifndef _WIN32
90
91 bool s_stop = false;
92
93 static void OnBreak(int sig)
94 {
95 s_stop = true;
96 }
97
98 #endif
99
100 /**
101 * main()
102 */
103 int main(int argc, char *argv[])
104 {
105 int rc = 0, ch, traceLevel = -1;
106 BYTE *xml;
107 UINT32 size;
108 TCHAR *inputFile = NULL;
109 #ifdef _WIN32
110 bool vssSnapshots = false;
111 #endif
112
113 InitNetXMSProcess(true);
114
115 // Parse command line
116 opterr = 1;
117 while((ch = getopt(argc, argv, "D:f:hist:v")) != -1)
118 {
119 switch(ch)
120 {
121 case 'D':
122 nxlog_set_debug_level(strtol(optarg, NULL, 0));
123 break;
124 case 'h':
125 _tprintf(m_helpText);
126 return 0;
127 case 'v':
128 _tprintf(_T("NetXMS Log Parsing Tester Version ") NETXMS_VERSION_STRING _T("\n")
129 _T("Copyright (c) 2009-2017 Victor Kirhenshtein\n\n"));
130 return 0;
131 case 'f':
132 #ifdef UNICODE
133 inputFile = WideStringFromMBString(optarg);
134 #else
135 inputFile = optarg;
136 #endif
137 break;
138 #ifdef _WIN32
139 case 's':
140 vssSnapshots = true;
141 break;
142 #endif
143 case 't':
144 traceLevel = strtol(optarg, NULL, 0);
145 break;
146 case '?':
147 return 1;
148 default:
149 break;
150 }
151 }
152
153 if (argc - optind < 1)
154 {
155 _tprintf(_T("Required arguments missing\n"));
156 return 1;
157 }
158
159 nxlog_set_debug_writer(DebugWriter);
160
161 InitLogParserLibrary();
162 SetLogParserTraceCallback(LoggerCallback);
163
164 #ifdef UNICODE
165 WCHAR *wname = WideStringFromMBString(argv[optind]);
166 xml = LoadFile(wname, &size);
167 free(wname);
168 #else
169 xml = LoadFile(argv[optind], &size);
170 #endif
171 if (xml != NULL)
172 {
173 TCHAR errorText[1024];
174 THREAD thread;
175
176 ObjectArray<LogParser> *parsers = LogParser::createFromXml((const char *)xml, size, errorText, 1024);
177 if ((parsers != NULL) && (parsers->size() > 0))
178 {
179 LogParser *parser = parsers->get(0);
180 parser->setTraceCallback(TraceCallback);
181 if (traceLevel != -1)
182 parser->setTraceLevel(traceLevel);
183 if (inputFile != NULL)
184 parser->setFileName(inputFile);
185 #ifdef _WIN32
186 if (vssSnapshots)
187 parser->setSnapshotMode(true);
188 #endif
189
190 m_stopCondition = ConditionCreate(true);
191 thread = ThreadCreateEx(ParserThread, 0, parser);
192 #ifdef _WIN32
193 _tprintf(_T("Parser started. Press ESC to stop.\nFile: %s\nTrace level: %d\n\n"),
194 parser->getFileName(), parser->getTraceLevel());
195 while(1)
196 {
197 ch = _getch();
198 if (ch == 27)
199 break;
200 }
201 #else
202 _tprintf(_T("Parser started. Press Ctrl+C to stop.\nFile: %s\nTrace level: %d\n\n"),
203 parser->getFileName(), parser->getTraceLevel());
204
205 signal(SIGINT, OnBreak);
206
207 sigset_t signals;
208 sigemptyset(&signals);
209 sigaddset(&signals, SIGINT);
210 pthread_sigmask(SIG_UNBLOCK, &signals, NULL);
211
212 while(!s_stop)
213 ThreadSleepMs(500);
214 #endif
215 ConditionSet(m_stopCondition);
216 ThreadJoin(thread);
217 ConditionDestroy(m_stopCondition);
218 }
219 else
220 {
221 _tprintf(_T("ERROR: invalid parser definition file (%s)\n"), errorText);
222 rc = 1;
223 }
224 free(xml);
225 }
226 else
227 {
228 _tprintf(_T("ERROR: unable to load parser definition file (%s)\n"), _tcserror(errno));
229 rc = 2;
230 }
231
232 CleanupLogParserLibrary();
233 return rc;
234 }