Fixed incorrect data type constants usage; confusing DT_xxx and DTYPE_xxx constants...
[public/netxms.git] / src / server / core / dcithreshold.cpp
CommitLineData
3ea35b38
VK
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
30Threshold::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
52Threshold::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 {
42d7ed00 67 case DCI_DT_INTEGER:
3ea35b38
VK
68 m_value.iInteger = strtol(m_pszValueStr, NULL, 0);
69 break;
42d7ed00 70 case DCI_DT_INT64:
3ea35b38
VK
71 /* TODO: add 64-bit string to binary conversion */
72 break;
42d7ed00 73 case DCI_DT_FLOAT:
3ea35b38
VK
74 m_value.dFloat = strtod(m_pszValueStr, NULL);
75 break;
76 default:
77 break;
78 }
79}
80
81
82//
83// Destructor
84//
85
86Threshold::~Threshold()
87{
88 safe_free(m_pszValueStr);
89}
90
91
92//
07a45e04
VK
93// Create new unique id for object
94//
95
96void Threshold::CreateId(void)
97{
98 m_dwId = CreateUniqueId(IDG_THRESHOLD);
99}
100
101
102//
3ea35b38
VK
103// Save threshold to database
104//
105
06e7be2f 106BOOL Threshold::SaveToDB(DWORD dwIndex)
3ea35b38
VK
107{
108 char szQuery[512];
109 DB_RESULT hResult;
110 BOOL bNewObject = TRUE;
111
112 // Check for object's existence in database
113 sprintf(szQuery, "SELECT threshold_id FROM thresholds WHERE threshold_id=%ld", m_dwId);
114 hResult = DBSelect(g_hCoreDB, szQuery);
115 if (hResult != 0)
116 {
117 if (DBGetNumRows(hResult) > 0)
118 bNewObject = FALSE;
119 DBFreeResult(hResult);
120 }
121
122 // Prepare and execute query
123 if (bNewObject)
124 sprintf(szQuery, "INSERT INTO thresholds (threshold_id,item_id,fire_value,rearm_value,"
06e7be2f
VK
125 "check_function,check_operation,parameter_1,parameter_2,event_code,"
126 "sequence_number) VALUES (%ld,%ld,'%s','',%d,%d,%ld,%ld,%ld,%ld)",
127 m_dwId, m_dwItemId, m_pszValueStr, m_iFunction, m_iOperation, m_iParam1,
128 m_iParam2, m_dwEventCode, dwIndex);
3ea35b38
VK
129 else
130 sprintf(szQuery, "UPDATE thresholds SET item_id=%ld,fire_value='%s',check_function=%d,"
06e7be2f
VK
131 "check_operation=%d,parameter_1=%ld,parameter_2=%ld,event_code=%ld,"
132 "sequence_number=%ld WHERE threshold_id=%ld", m_dwItemId,
133 m_pszValueStr, m_iFunction, m_iOperation, m_iParam1, m_iParam2, m_dwEventCode,
134 dwIndex, m_dwId);
3ea35b38
VK
135 return DBQuery(g_hCoreDB, szQuery);
136}
137
138
139//
140// Check threshold
141// Function will return the following codes:
142// THRESHOLD_REACHED - when item's value match the threshold condition while previous check doesn't
143// THRESHOLD_REARMED - when item's value doesn't match the threshold condition while previous check do
144// NO_ACTION - when there are no changes in item's value match to threshold's condition
145//
146
147int Threshold::Check(const char *pszValue)
148{
149 BOOL bMatch = FALSE;
150 int iResult;
151 union
152 {
153 const char *pszStr;
154 int iInteger;
521d90e7 155 INT64 qwInt64;
3ea35b38
VK
156 double dFloat;
157 } fvalue;
158
159 // Execute function on value
160 switch(m_iFunction)
161 {
162 case F_LAST: // Check last value only
163 switch(m_iDataType)
164 {
42d7ed00 165 case DCI_DT_INTEGER:
3ea35b38
VK
166 fvalue.iInteger = strtol(pszValue, NULL, 0);
167 break;
42d7ed00 168 case DCI_DT_INT64:
3ea35b38
VK
169 /* TODO: add 64-bit conversion code */
170 break;
42d7ed00 171 case DCI_DT_FLOAT:
3ea35b38
VK
172 fvalue.dFloat = strtod(pszValue, NULL);
173 break;
42d7ed00 174 case DCI_DT_STRING:
3ea35b38
VK
175 fvalue.pszStr = pszValue;
176 break;
177 default:
178 WriteLog(MSG_INVALID_DTYPE, EVENTLOG_ERROR_TYPE, "ds", m_iDataType, "Threshold::Check()");
179 break;
180 }
181 break;
182 case F_AVERAGE: // Check average value for last n polls
183 /* TODO */
184 break;
185 case F_DEVIATION: // Check deviation from the mean value
186 /* TODO */
187 break;
188 default:
189 break;
190 }
191
192 // Run comparision operation on function result and threshold value
193 switch(m_iOperation)
194 {
195 case OP_LE: // Less
196 switch(m_iDataType)
197 {
42d7ed00 198 case DCI_DT_INTEGER:
3ea35b38
VK
199 bMatch = (fvalue.iInteger < m_value.iInteger);
200 break;
42d7ed00 201 case DCI_DT_INT64:
3ea35b38
VK
202 bMatch = (fvalue.qwInt64 < m_value.qwInt64);
203 break;
42d7ed00 204 case DCI_DT_FLOAT:
3ea35b38
VK
205 bMatch = (fvalue.dFloat < m_value.dFloat);
206 break;
207 }
208 break;
209 case OP_LE_EQ: // Less or equal
210 switch(m_iDataType)
211 {
42d7ed00 212 case DCI_DT_INTEGER:
3ea35b38
VK
213 bMatch = (fvalue.iInteger <= m_value.iInteger);
214 break;
42d7ed00 215 case DCI_DT_INT64:
3ea35b38
VK
216 bMatch = (fvalue.qwInt64 <= m_value.qwInt64);
217 break;
42d7ed00 218 case DCI_DT_FLOAT:
3ea35b38
VK
219 bMatch = (fvalue.dFloat <= m_value.dFloat);
220 break;
221 }
222 break;
223 case OP_EQ: // Equal
224 switch(m_iDataType)
225 {
42d7ed00 226 case DCI_DT_INTEGER:
3ea35b38
VK
227 bMatch = (fvalue.iInteger == m_value.iInteger);
228 break;
42d7ed00 229 case DCI_DT_INT64:
3ea35b38
VK
230 bMatch = (fvalue.qwInt64 == m_value.qwInt64);
231 break;
42d7ed00 232 case DCI_DT_FLOAT:
3ea35b38
VK
233 bMatch = (fvalue.dFloat == m_value.dFloat);
234 break;
42d7ed00 235 case DCI_DT_STRING:
3ea35b38
VK
236 bMatch = !strcmp(fvalue.pszStr, m_pszValueStr);
237 break;
238 }
239 break;
240 case OP_GT_EQ: // Greater or equal
241 switch(m_iDataType)
242 {
42d7ed00 243 case DCI_DT_INTEGER:
3ea35b38
VK
244 bMatch = (fvalue.iInteger >= m_value.iInteger);
245 break;
42d7ed00 246 case DCI_DT_INT64:
3ea35b38
VK
247 bMatch = (fvalue.qwInt64 >= m_value.qwInt64);
248 break;
42d7ed00 249 case DCI_DT_FLOAT:
3ea35b38
VK
250 bMatch = (fvalue.dFloat >= m_value.dFloat);
251 break;
252 }
253 break;
254 case OP_GT: // Greater
255 switch(m_iDataType)
256 {
42d7ed00 257 case DCI_DT_INTEGER:
3ea35b38
VK
258 bMatch = (fvalue.iInteger > m_value.iInteger);
259 break;
42d7ed00 260 case DCI_DT_INT64:
3ea35b38
VK
261 bMatch = (fvalue.qwInt64 > m_value.qwInt64);
262 break;
42d7ed00 263 case DCI_DT_FLOAT:
3ea35b38
VK
264 bMatch = (fvalue.dFloat > m_value.dFloat);
265 break;
266 }
267 break;
268 case OP_NE: // Not equal
269 switch(m_iDataType)
270 {
42d7ed00 271 case DCI_DT_INTEGER:
3ea35b38
VK
272 bMatch = (fvalue.iInteger != m_value.iInteger);
273 break;
42d7ed00 274 case DCI_DT_INT64:
3ea35b38
VK
275 bMatch = (fvalue.qwInt64 != m_value.qwInt64);
276 break;
42d7ed00 277 case DCI_DT_FLOAT:
3ea35b38
VK
278 bMatch = (fvalue.dFloat != m_value.dFloat);
279 break;
42d7ed00 280 case DCI_DT_STRING:
3ea35b38
VK
281 bMatch = strcmp(fvalue.pszStr, m_pszValueStr);
282 break;
283 }
284 break;
285 case OP_LIKE:
286 // This operation can be performed only on strings
42d7ed00 287 if (m_iDataType == DCI_DT_STRING)
3ea35b38
VK
288 bMatch = MatchString(m_pszValueStr, fvalue.pszStr, TRUE);
289 break;
290 case OP_NOTLIKE:
291 // This operation can be performed only on strings
42d7ed00 292 if (m_iDataType == DCI_DT_STRING)
3ea35b38
VK
293 bMatch = !MatchString(m_pszValueStr, fvalue.pszStr, TRUE);
294 break;
295 default:
296 break;
297 }
298
299 iResult = (bMatch & !m_bIsReached) ? THRESHOLD_REACHED :
300 ((!bMatch & m_bIsReached) ? THRESHOLD_REARMED : NO_ACTION);
301 m_bIsReached = bMatch;
302 return iResult;
303}
07a45e04
VK
304
305
306//
307// Fill DCI_THRESHOLD with object's data ready to send over the network
308//
309
310void Threshold::CreateMessage(DCI_THRESHOLD *pData)
311{
312 pData->dwId = htonl(m_dwId);
313 pData->dwEvent = htonl(m_dwEventCode);
314 pData->wFunction = htons((WORD)m_iFunction);
315 pData->wOperation = htons((WORD)m_iOperation);
316 pData->dwArg1 = htonl(m_iParam1);
317 pData->dwArg2 = htonl(m_iParam2);
318 switch(m_iDataType)
319 {
42d7ed00 320 case DCI_DT_INTEGER:
07a45e04
VK
321 pData->value.dwInt32 = htonl(m_value.iInteger);
322 break;
42d7ed00 323 case DCI_DT_INT64:
07a45e04
VK
324 pData->value.qwInt64 = htonq(m_value.qwInt64);
325 break;
42d7ed00 326 case DCI_DT_FLOAT:
07a45e04
VK
327 pData->value.dFloat = htond(m_value.dFloat);
328 break;
42d7ed00 329 case DCI_DT_STRING:
07a45e04
VK
330 strcpy(pData->value.szString, m_pszValueStr);
331 break;
332 default:
333 break;
334 }
335}
336
337
338//
339// Update threshold object from DCI_THRESHOLD structure
340//
341
342void Threshold::UpdateFromMessage(DCI_THRESHOLD *pData)
343{
344 m_dwEventCode = ntohl(pData->dwEvent);
345 m_iFunction = (BYTE)ntohs(pData->wFunction);
346 m_iOperation = (BYTE)ntohs(pData->wOperation);
347 m_iParam1 = ntohl(pData->dwArg1);
348 m_iParam2 = ntohl(pData->dwArg2);
06e7be2f 349 safe_free(m_pszValueStr);
07a45e04
VK
350 switch(m_iDataType)
351 {
42d7ed00 352 case DCI_DT_INTEGER:
07a45e04 353 m_value.iInteger = ntohl(pData->value.dwInt32);
06e7be2f
VK
354 m_pszValueStr = (char *)malloc(32);
355 sprintf(m_pszValueStr, "%ld", m_value.iInteger);
07a45e04 356 break;
42d7ed00 357 case DCI_DT_INT64:
07a45e04 358 m_value.qwInt64 = ntohq(pData->value.qwInt64);
06e7be2f 359 m_pszValueStr = (char *)malloc(32);
e9d6c290 360#ifdef _WIN32
06e7be2f 361 sprintf(m_pszValueStr, "%64I", m_value.qwInt64);
e9d6c290
VK
362#else
363 sprintf(m_pszValueStr, "%lld", m_value.qwInt64);
364#endif
07a45e04 365 break;
42d7ed00 366 case DCI_DT_FLOAT:
07a45e04 367 m_value.dFloat = ntohd(pData->value.dFloat);
06e7be2f
VK
368 m_pszValueStr = (char *)malloc(32);
369 sprintf(m_pszValueStr, "%f", m_value.dFloat);
07a45e04 370 break;
42d7ed00 371 case DCI_DT_STRING:
07a45e04
VK
372 m_pszValueStr = strdup(pData->value.szString);
373 break;
374 default:
e9d6c290 375 DbgPrintf(AF_DEBUG_DC, "WARNING: Invalid datatype %d in threshold object %d\n", m_iDataType, m_dwId);
07a45e04
VK
376 break;
377 }
378}