- Changes in logging and debug output
[public/netxms.git] / src / server / core / dcithreshold.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003, 2004 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** $module: dcithreshold.cpp
20 **
21 **/
22
23 #include "nms_core.h"
24
25
26 //
27 // Default constructor
28 //
29
30 Threshold::Threshold(DCItem *pRelatedItem)
31 {
32 m_dwId = 0;
33 m_dwItemId = pRelatedItem->Id();
34 m_dwEventCode = EVENT_THRESHOLD_REACHED;
35 m_pszValueStr = NULL;
36 m_iFunction = F_LAST;
37 m_iOperation = OP_EQ;
38 m_iDataType = pRelatedItem->DataType();
39 m_iParam1 = 0;
40 m_iParam2 = 0;
41 m_bIsReached = FALSE;
42 }
43
44
45 //
46 // Constructor for creating object from database
47 // This constructor assumes that SELECT query look as following:
48 // SELECT threshold_id,fire_value,rearm_value,check_function,check_operation,
49 // parameter_1,parameter_2,event_code FROM thresholds
50 //
51
52 Threshold::Threshold(DB_RESULT hResult, int iRow, DCItem *pRelatedItem)
53 {
54 m_dwId = DBGetFieldULong(hResult, iRow, 0);
55 m_dwItemId = pRelatedItem->Id();
56 m_dwEventCode = DBGetFieldULong(hResult, iRow, 7);
57 m_pszValueStr = strdup(DBGetField(hResult, iRow, 1));
58 m_iFunction = (BYTE)DBGetFieldLong(hResult, iRow, 3);
59 m_iOperation = (BYTE)DBGetFieldLong(hResult, iRow, 4);
60 m_iDataType = pRelatedItem->DataType();
61 m_iParam1 = DBGetFieldLong(hResult, iRow, 5);
62 m_iParam2 = DBGetFieldLong(hResult, iRow, 6);
63 m_bIsReached = FALSE;
64
65 switch(m_iDataType)
66 {
67 case DCI_DT_INT:
68 m_value.iInt = strtol(m_pszValueStr, NULL, 0);
69 break;
70 case DCI_DT_UINT:
71 m_value.dwUInt = strtoul(m_pszValueStr, NULL, 0);
72 break;
73 case DCI_DT_INT64:
74 /* TODO: add 64-bit string to binary conversion */
75 break;
76 case DCI_DT_UINT64:
77 /* TODO: add 64-bit string to binary conversion */
78 break;
79 case DCI_DT_FLOAT:
80 m_value.dFloat = strtod(m_pszValueStr, NULL);
81 break;
82 default:
83 break;
84 }
85 }
86
87
88 //
89 // Destructor
90 //
91
92 Threshold::~Threshold()
93 {
94 safe_free(m_pszValueStr);
95 }
96
97
98 //
99 // Create new unique id for object
100 //
101
102 void Threshold::CreateId(void)
103 {
104 m_dwId = CreateUniqueId(IDG_THRESHOLD);
105 }
106
107
108 //
109 // Save threshold to database
110 //
111
112 BOOL Threshold::SaveToDB(DWORD dwIndex)
113 {
114 char szQuery[512];
115 DB_RESULT hResult;
116 BOOL bNewObject = TRUE;
117
118 // Check for object's existence in database
119 sprintf(szQuery, "SELECT threshold_id FROM thresholds WHERE threshold_id=%ld", m_dwId);
120 hResult = DBSelect(g_hCoreDB, szQuery);
121 if (hResult != 0)
122 {
123 if (DBGetNumRows(hResult) > 0)
124 bNewObject = FALSE;
125 DBFreeResult(hResult);
126 }
127
128 // Prepare and execute query
129 if (bNewObject)
130 sprintf(szQuery, "INSERT INTO thresholds (threshold_id,item_id,fire_value,rearm_value,"
131 "check_function,check_operation,parameter_1,parameter_2,event_code,"
132 "sequence_number) VALUES (%ld,%ld,'%s','',%d,%d,%ld,%ld,%ld,%ld)",
133 m_dwId, m_dwItemId, m_pszValueStr, m_iFunction, m_iOperation, m_iParam1,
134 m_iParam2, m_dwEventCode, dwIndex);
135 else
136 sprintf(szQuery, "UPDATE thresholds SET item_id=%ld,fire_value='%s',check_function=%d,"
137 "check_operation=%d,parameter_1=%ld,parameter_2=%ld,event_code=%ld,"
138 "sequence_number=%ld WHERE threshold_id=%ld", m_dwItemId,
139 m_pszValueStr, m_iFunction, m_iOperation, m_iParam1, m_iParam2, m_dwEventCode,
140 dwIndex, m_dwId);
141 return DBQuery(g_hCoreDB, szQuery);
142 }
143
144
145 //
146 // Check threshold
147 // Function will return the following codes:
148 // THRESHOLD_REACHED - when item's value match the threshold condition while previous check doesn't
149 // THRESHOLD_REARMED - when item's value doesn't match the threshold condition while previous check do
150 // NO_ACTION - when there are no changes in item's value match to threshold's condition
151 //
152
153 int Threshold::Check(ItemValue &value)
154 {
155 BOOL bMatch = FALSE;
156 int iResult;
157 union
158 {
159 const char *pszStr;
160 long iInt;
161 DWORD dwUInt;
162 INT64 iInt64;
163 QWORD qwUInt64;
164 double dFloat;
165 } fvalue;
166
167 // Execute function on value
168 switch(m_iFunction)
169 {
170 case F_LAST: // Check last value only
171 switch(m_iDataType)
172 {
173 case DCI_DT_INT:
174 fvalue.iInt = (long)value;
175 break;
176 case DCI_DT_UINT:
177 fvalue.dwUInt = (DWORD)value;
178 break;
179 case DCI_DT_INT64:
180 fvalue.iInt64 = (INT64)value;
181 break;
182 case DCI_DT_UINT64:
183 fvalue.qwUInt64 = (QWORD)value;
184 break;
185 case DCI_DT_FLOAT:
186 fvalue.dFloat = (double)value;
187 break;
188 case DCI_DT_STRING:
189 fvalue.pszStr = (const char *)value;
190 break;
191 default:
192 WriteLog(MSG_INVALID_DTYPE, EVENTLOG_ERROR_TYPE, "ds", m_iDataType, "Threshold::Check()");
193 break;
194 }
195 break;
196 case F_AVERAGE: // Check average value for last n polls
197 /* TODO */
198 break;
199 case F_DEVIATION: // Check deviation from the mean value
200 /* TODO */
201 break;
202 default:
203 break;
204 }
205
206 // Run comparision operation on function result and threshold value
207 switch(m_iOperation)
208 {
209 case OP_LE: // Less
210 switch(m_iDataType)
211 {
212 case DCI_DT_INT:
213 bMatch = (fvalue.iInt < m_value.iInt);
214 break;
215 case DCI_DT_UINT:
216 bMatch = (fvalue.dwUInt < m_value.dwUInt);
217 break;
218 case DCI_DT_INT64:
219 bMatch = (fvalue.iInt64 < m_value.iInt64);
220 break;
221 case DCI_DT_UINT64:
222 bMatch = (fvalue.qwUInt64 < m_value.qwUInt64);
223 break;
224 case DCI_DT_FLOAT:
225 bMatch = (fvalue.dFloat < m_value.dFloat);
226 break;
227 }
228 break;
229 case OP_LE_EQ: // Less or equal
230 switch(m_iDataType)
231 {
232 case DCI_DT_INT:
233 bMatch = (fvalue.iInt <= m_value.iInt);
234 break;
235 case DCI_DT_UINT:
236 bMatch = (fvalue.dwUInt <= m_value.dwUInt);
237 break;
238 case DCI_DT_INT64:
239 bMatch = (fvalue.iInt64 <= m_value.iInt64);
240 break;
241 case DCI_DT_UINT64:
242 bMatch = (fvalue.qwUInt64 <= m_value.qwUInt64);
243 break;
244 case DCI_DT_FLOAT:
245 bMatch = (fvalue.dFloat <= m_value.dFloat);
246 break;
247 }
248 break;
249 case OP_EQ: // Equal
250 switch(m_iDataType)
251 {
252 case DCI_DT_INT:
253 bMatch = (fvalue.iInt == m_value.iInt);
254 break;
255 case DCI_DT_UINT:
256 bMatch = (fvalue.dwUInt == m_value.dwUInt);
257 break;
258 case DCI_DT_INT64:
259 bMatch = (fvalue.iInt64 == m_value.iInt64);
260 break;
261 case DCI_DT_UINT64:
262 bMatch = (fvalue.qwUInt64 == m_value.qwUInt64);
263 break;
264 case DCI_DT_FLOAT:
265 bMatch = (fvalue.dFloat == m_value.dFloat);
266 break;
267 case DCI_DT_STRING:
268 bMatch = !strcmp(fvalue.pszStr, m_pszValueStr);
269 break;
270 }
271 break;
272 case OP_GT_EQ: // Greater or equal
273 switch(m_iDataType)
274 {
275 case DCI_DT_INT:
276 bMatch = (fvalue.iInt >= m_value.iInt);
277 break;
278 case DCI_DT_UINT:
279 bMatch = (fvalue.dwUInt >= m_value.dwUInt);
280 break;
281 case DCI_DT_INT64:
282 bMatch = (fvalue.iInt64 >= m_value.iInt64);
283 break;
284 case DCI_DT_UINT64:
285 bMatch = (fvalue.qwUInt64 >= m_value.qwUInt64);
286 break;
287 case DCI_DT_FLOAT:
288 bMatch = (fvalue.dFloat >= m_value.dFloat);
289 break;
290 }
291 break;
292 case OP_GT: // Greater
293 switch(m_iDataType)
294 {
295 case DCI_DT_INT:
296 bMatch = (fvalue.iInt > m_value.iInt);
297 break;
298 case DCI_DT_UINT:
299 bMatch = (fvalue.dwUInt > m_value.dwUInt);
300 break;
301 case DCI_DT_INT64:
302 bMatch = (fvalue.iInt64 > m_value.iInt64);
303 break;
304 case DCI_DT_UINT64:
305 bMatch = (fvalue.qwUInt64 > m_value.qwUInt64);
306 break;
307 case DCI_DT_FLOAT:
308 bMatch = (fvalue.dFloat > m_value.dFloat);
309 break;
310 }
311 break;
312 case OP_NE: // Not equal
313 switch(m_iDataType)
314 {
315 case DCI_DT_INT:
316 bMatch = (fvalue.iInt != m_value.iInt);
317 break;
318 case DCI_DT_UINT:
319 bMatch = (fvalue.dwUInt != m_value.dwUInt);
320 break;
321 case DCI_DT_INT64:
322 bMatch = (fvalue.iInt64 != m_value.iInt64);
323 break;
324 case DCI_DT_UINT64:
325 bMatch = (fvalue.qwUInt64 != m_value.qwUInt64);
326 break;
327 case DCI_DT_FLOAT:
328 bMatch = (fvalue.dFloat != m_value.dFloat);
329 break;
330 case DCI_DT_STRING:
331 bMatch = strcmp(fvalue.pszStr, m_pszValueStr);
332 break;
333 }
334 break;
335 case OP_LIKE:
336 // This operation can be performed only on strings
337 if (m_iDataType == DCI_DT_STRING)
338 bMatch = MatchString(m_pszValueStr, fvalue.pszStr, TRUE);
339 break;
340 case OP_NOTLIKE:
341 // This operation can be performed only on strings
342 if (m_iDataType == DCI_DT_STRING)
343 bMatch = !MatchString(m_pszValueStr, fvalue.pszStr, TRUE);
344 break;
345 default:
346 break;
347 }
348
349 iResult = (bMatch & !m_bIsReached) ? THRESHOLD_REACHED :
350 ((!bMatch & m_bIsReached) ? THRESHOLD_REARMED : NO_ACTION);
351 m_bIsReached = bMatch;
352 return iResult;
353 }
354
355
356 //
357 // Fill DCI_THRESHOLD with object's data ready to send over the network
358 //
359
360 void Threshold::CreateMessage(DCI_THRESHOLD *pData)
361 {
362 pData->dwId = htonl(m_dwId);
363 pData->dwEvent = htonl(m_dwEventCode);
364 pData->wFunction = htons((WORD)m_iFunction);
365 pData->wOperation = htons((WORD)m_iOperation);
366 pData->dwArg1 = htonl(m_iParam1);
367 pData->dwArg2 = htonl(m_iParam2);
368 switch(m_iDataType)
369 {
370 case DCI_DT_INT:
371 pData->value.dwInt32 = htonl(m_value.iInt);
372 break;
373 case DCI_DT_UINT:
374 pData->value.dwInt32 = htonl(m_value.dwUInt);
375 break;
376 case DCI_DT_INT64:
377 pData->value.qwInt64 = htonq(m_value.iInt64);
378 break;
379 case DCI_DT_UINT64:
380 pData->value.qwInt64 = htonq(m_value.qwUInt64);
381 break;
382 case DCI_DT_FLOAT:
383 pData->value.dFloat = htond(m_value.dFloat);
384 break;
385 case DCI_DT_STRING:
386 strcpy(pData->value.szString, m_pszValueStr);
387 break;
388 default:
389 break;
390 }
391 }
392
393
394 //
395 // Update threshold object from DCI_THRESHOLD structure
396 //
397
398 void Threshold::UpdateFromMessage(DCI_THRESHOLD *pData)
399 {
400 m_dwEventCode = ntohl(pData->dwEvent);
401 m_iFunction = (BYTE)ntohs(pData->wFunction);
402 m_iOperation = (BYTE)ntohs(pData->wOperation);
403 m_iParam1 = ntohl(pData->dwArg1);
404 m_iParam2 = ntohl(pData->dwArg2);
405 safe_free(m_pszValueStr);
406 switch(m_iDataType)
407 {
408 case DCI_DT_INT:
409 m_value.iInt = (long)ntohl(pData->value.dwInt32);
410 m_pszValueStr = (char *)malloc(32);
411 sprintf(m_pszValueStr, "%ld", m_value.iInt);
412 break;
413 case DCI_DT_UINT:
414 m_value.dwUInt = ntohl(pData->value.dwInt32);
415 m_pszValueStr = (char *)malloc(32);
416 sprintf(m_pszValueStr, "%lu", m_value.dwUInt);
417 break;
418 case DCI_DT_INT64:
419 m_value.iInt64 = (INT64)ntohq(pData->value.qwInt64);
420 m_pszValueStr = (char *)malloc(32);
421 #ifdef _WIN32
422 sprintf(m_pszValueStr, "%I64d", m_value.iInt64);
423 #else
424 sprintf(m_pszValueStr, "%lld", m_value.iInt64);
425 #endif
426 break;
427 case DCI_DT_UINT64:
428 m_value.iInt64 = (QWORD)ntohq(pData->value.qwInt64);
429 m_pszValueStr = (char *)malloc(32);
430 #ifdef _WIN32
431 sprintf(m_pszValueStr, "%I64u", m_value.qwUInt64);
432 #else
433 sprintf(m_pszValueStr, "%llu", m_value.qwUInt64);
434 #endif
435 break;
436 case DCI_DT_FLOAT:
437 m_value.dFloat = ntohd(pData->value.dFloat);
438 m_pszValueStr = (char *)malloc(32);
439 sprintf(m_pszValueStr, "%f", m_value.dFloat);
440 break;
441 case DCI_DT_STRING:
442 m_pszValueStr = strdup(pData->value.szString);
443 break;
444 default:
445 DbgPrintf(AF_DEBUG_DC, "WARNING: Invalid datatype %d in threshold object %d", m_iDataType, m_dwId);
446 break;
447 }
448 }