1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21 #include "db.h"
22 #include "log.h"
23 #include "zbxserver.h"
24 #include "valuecache.h"
25 #include "evalfunc.h"
26 #include "zbxregexp.h"
27
28 typedef enum
29 {
30 ZBX_PARAM_OPTIONAL,
31 ZBX_PARAM_MANDATORY
32 }
33 zbx_param_type_t;
34
35 typedef enum
36 {
37 ZBX_VALUE_SECONDS,
38 ZBX_VALUE_NVALUES
39 }
40 zbx_value_type_t;
41
zbx_type_string(zbx_value_type_t type)42 static const char *zbx_type_string(zbx_value_type_t type)
43 {
44 switch (type)
45 {
46 case ZBX_VALUE_SECONDS:
47 return "sec";
48 case ZBX_VALUE_NVALUES:
49 return "num";
50 default:
51 THIS_SHOULD_NEVER_HAPPEN;
52 return "unknown";
53 }
54 }
55
56 /******************************************************************************
57 * *
58 * Function: get_function_parameter_int *
59 * *
60 * Purpose: get the value of sec|#num trigger function parameter *
61 * *
62 * Parameters: hostid - [IN] hostid of the host trigger function *
63 * belongs to *
64 * parameters - [IN] trigger function parameters *
65 * Nparam - [IN] specifies which parameter to extract *
66 * parameter_type - [IN] specifies whether parameter is mandatory *
67 * or optional *
68 * value - [OUT] parameter value (preserved as is if the *
69 * parameter is optional and empty) *
70 * type - [OUT] parameter value type (number of seconds *
71 * or number of values) *
72 * *
73 * Return value: SUCCEED - parameter is valid *
74 * FAIL - otherwise *
75 * *
76 ******************************************************************************/
get_function_parameter_int(zbx_uint64_t hostid,const char * parameters,int Nparam,zbx_param_type_t parameter_type,int * value,zbx_value_type_t * type)77 static int get_function_parameter_int(zbx_uint64_t hostid, const char *parameters, int Nparam,
78 zbx_param_type_t parameter_type, int *value, zbx_value_type_t *type)
79 {
80 const char *__function_name = "get_function_parameter_int";
81 char *parameter;
82 int ret = FAIL;
83
84 zabbix_log(LOG_LEVEL_DEBUG, "In %s() parameters:'%s' Nparam:%d", __function_name, parameters, Nparam);
85
86 if (NULL == (parameter = zbx_function_get_param_dyn(parameters, Nparam)))
87 goto out;
88
89 if (SUCCEED == substitute_simple_macros(NULL, NULL, NULL, NULL, &hostid, NULL, NULL, NULL, NULL,
90 ¶meter, MACRO_TYPE_COMMON, NULL, 0))
91 {
92 if ('\0' == *parameter)
93 {
94 switch (parameter_type)
95 {
96 case ZBX_PARAM_OPTIONAL:
97 ret = SUCCEED;
98 break;
99 case ZBX_PARAM_MANDATORY:
100 break;
101 default:
102 THIS_SHOULD_NEVER_HAPPEN;
103 }
104 }
105 else if ('#' == *parameter)
106 {
107 *type = ZBX_VALUE_NVALUES;
108 if (SUCCEED == is_uint31(parameter + 1, value) && 0 < *value)
109 ret = SUCCEED;
110 }
111 else if ('-' == *parameter)
112 {
113 if (SUCCEED == is_time_suffix(parameter + 1, value, ZBX_LENGTH_UNLIMITED))
114 {
115 *value = -(*value);
116 *type = ZBX_VALUE_SECONDS;
117 ret = SUCCEED;
118 }
119 }
120 else if (SUCCEED == is_time_suffix(parameter, value, ZBX_LENGTH_UNLIMITED))
121 {
122 *type = ZBX_VALUE_SECONDS;
123 ret = SUCCEED;
124 }
125 }
126
127 if (SUCCEED == ret)
128 zabbix_log(LOG_LEVEL_DEBUG, "%s() type:%s value:%d", __function_name, zbx_type_string(*type), *value);
129
130 zbx_free(parameter);
131 out:
132 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
133
134 return ret;
135 }
136
get_function_parameter_uint64(zbx_uint64_t hostid,const char * parameters,int Nparam,zbx_uint64_t * value)137 static int get_function_parameter_uint64(zbx_uint64_t hostid, const char *parameters, int Nparam,
138 zbx_uint64_t *value)
139 {
140 const char *__function_name = "get_function_parameter_uint64";
141 char *parameter;
142 int ret = FAIL;
143
144 zabbix_log(LOG_LEVEL_DEBUG, "In %s() parameters:'%s' Nparam:%d", __function_name, parameters, Nparam);
145
146 if (NULL == (parameter = zbx_function_get_param_dyn(parameters, Nparam)))
147 goto out;
148
149 if (SUCCEED == substitute_simple_macros(NULL, NULL, NULL, NULL, &hostid, NULL, NULL, NULL, NULL,
150 ¶meter, MACRO_TYPE_COMMON, NULL, 0))
151 {
152 if (SUCCEED == is_uint64(parameter, value))
153 ret = SUCCEED;
154 }
155
156 if (SUCCEED == ret)
157 zabbix_log(LOG_LEVEL_DEBUG, "%s() value:" ZBX_FS_UI64, __function_name, *value);
158
159 zbx_free(parameter);
160 out:
161 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
162
163 return ret;
164 }
165
get_function_parameter_float(zbx_uint64_t hostid,const char * parameters,int Nparam,unsigned char flags,double * value)166 static int get_function_parameter_float(zbx_uint64_t hostid, const char *parameters, int Nparam,
167 unsigned char flags, double *value)
168 {
169 const char *__function_name = "get_function_parameter_float";
170 char *parameter;
171 int ret = FAIL;
172
173 zabbix_log(LOG_LEVEL_DEBUG, "In %s() parameters:'%s' Nparam:%d", __function_name, parameters, Nparam);
174
175 if (NULL == (parameter = zbx_function_get_param_dyn(parameters, Nparam)))
176 goto out;
177
178 if (SUCCEED == substitute_simple_macros(NULL, NULL, NULL, NULL, &hostid, NULL, NULL, NULL, NULL,
179 ¶meter, MACRO_TYPE_COMMON, NULL, 0))
180 {
181 if (SUCCEED != is_double_suffix(parameter, flags))
182 goto clean;
183
184 *value = str2double(parameter);
185
186 ret = SUCCEED;
187 }
188
189 if (SUCCEED == ret)
190 zabbix_log(LOG_LEVEL_DEBUG, "%s() value:" ZBX_FS_DBL, __function_name, *value);
191 clean:
192 zbx_free(parameter);
193 out:
194 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
195
196 return ret;
197 }
198
get_function_parameter_str(zbx_uint64_t hostid,const char * parameters,int Nparam,char ** value)199 static int get_function_parameter_str(zbx_uint64_t hostid, const char *parameters, int Nparam, char **value)
200 {
201 const char *__function_name = "get_function_parameter_str";
202 int ret = FAIL;
203
204 zabbix_log(LOG_LEVEL_DEBUG, "In %s() parameters:'%s' Nparam:%d", __function_name, parameters, Nparam);
205
206 if (NULL == (*value = zbx_function_get_param_dyn(parameters, Nparam)))
207 goto out;
208
209 ret = substitute_simple_macros(NULL, NULL, NULL, NULL, &hostid, NULL, NULL, NULL, NULL,
210 value, MACRO_TYPE_COMMON, NULL, 0);
211
212 if (SUCCEED == ret)
213 zabbix_log(LOG_LEVEL_DEBUG, "%s() value:'%s'", __function_name, *value);
214 else
215 zbx_free(*value);
216 out:
217 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
218
219 return ret;
220 }
221
222 /******************************************************************************
223 * *
224 * Function: evaluate_LOGEVENTID *
225 * *
226 * Purpose: evaluate function 'logeventid' for the item *
227 * *
228 * Parameters: item - item (performance metric) *
229 * parameter - regex string for event id matching *
230 * *
231 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
232 * FAIL - failed to evaluate function *
233 * *
234 ******************************************************************************/
evaluate_LOGEVENTID(char * value,DC_ITEM * item,const char * parameters,const zbx_timespec_t * ts,char ** error)235 static int evaluate_LOGEVENTID(char *value, DC_ITEM *item, const char *parameters,
236 const zbx_timespec_t *ts, char **error)
237 {
238 const char *__function_name = "evaluate_LOGEVENTID";
239
240 char *arg1 = NULL;
241 int ret = FAIL;
242 zbx_vector_ptr_t regexps;
243 zbx_history_record_t vc_value;
244
245 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
246
247 zbx_vector_ptr_create(®exps);
248
249 if (ITEM_VALUE_TYPE_LOG != item->value_type)
250 {
251 *error = zbx_strdup(*error, "invalid value type");
252 goto out;
253 }
254
255 if (1 < num_param(parameters))
256 {
257 *error = zbx_strdup(*error, "invalid number of parameters");
258 goto out;
259 }
260
261 if (SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 1, &arg1))
262 {
263 *error = zbx_strdup(*error, "invalid first parameter");
264 goto out;
265 }
266
267 if ('@' == *arg1)
268 {
269 DCget_expressions_by_name(®exps, arg1 + 1);
270
271 if (0 == regexps.values_num)
272 {
273 *error = zbx_dsprintf(*error, "global regular expression \"%s\" does not exist", arg1 + 1);
274 goto out;
275 }
276 }
277
278 if (SUCCEED == zbx_vc_get_value(item->itemid, item->value_type, ts, &vc_value))
279 {
280 char logeventid[16];
281 int regexp_ret;
282
283 zbx_snprintf(logeventid, sizeof(logeventid), "%d", vc_value.value.log->logeventid);
284
285 if (FAIL == (regexp_ret = regexp_match_ex(®exps, logeventid, arg1, ZBX_CASE_SENSITIVE)))
286 {
287 *error = zbx_dsprintf(*error, "invalid regular expression \"%s\"", arg1);
288 }
289 else
290 {
291 if (ZBX_REGEXP_MATCH == regexp_ret)
292 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
293 else if (ZBX_REGEXP_NO_MATCH == regexp_ret)
294 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
295
296 ret = SUCCEED;
297 }
298
299 zbx_history_record_clear(&vc_value, item->value_type);
300 }
301 else
302 {
303 zabbix_log(LOG_LEVEL_DEBUG, "result for LOGEVENTID is empty");
304 *error = zbx_strdup(*error, "cannot get values from value cache");
305 }
306 out:
307 zbx_free(arg1);
308
309 zbx_regexp_clean_expressions(®exps);
310 zbx_vector_ptr_destroy(®exps);
311
312 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
313
314 return ret;
315 }
316
317 /******************************************************************************
318 * *
319 * Function: evaluate_LOGSOURCE *
320 * *
321 * Purpose: evaluate function 'logsource' for the item *
322 * *
323 * Parameters: item - item (performance metric) *
324 * parameter - ignored *
325 * *
326 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
327 * FAIL - failed to evaluate function *
328 * *
329 ******************************************************************************/
evaluate_LOGSOURCE(char * value,DC_ITEM * item,const char * parameters,const zbx_timespec_t * ts,char ** error)330 static int evaluate_LOGSOURCE(char *value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts,
331 char **error)
332 {
333 const char *__function_name = "evaluate_LOGSOURCE";
334
335 char *arg1 = NULL;
336 int ret = FAIL;
337 zbx_vector_ptr_t regexps;
338 zbx_history_record_t vc_value;
339
340 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
341
342 zbx_vector_ptr_create(®exps);
343
344 if (ITEM_VALUE_TYPE_LOG != item->value_type)
345 {
346 *error = zbx_strdup(*error, "invalid value type");
347 goto out;
348 }
349
350 if (1 < num_param(parameters))
351 {
352 *error = zbx_strdup(*error, "invalid number of parameters");
353 goto out;
354 }
355
356 if (SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 1, &arg1))
357 {
358 *error = zbx_strdup(*error, "invalid first parameter");
359 goto out;
360 }
361
362 if ('@' == *arg1)
363 {
364 DCget_expressions_by_name(®exps, arg1 + 1);
365
366 if (0 == regexps.values_num)
367 {
368 *error = zbx_dsprintf(*error, "global regular expression \"%s\" does not exist", arg1 + 1);
369 goto out;
370 }
371 }
372
373 if (SUCCEED == zbx_vc_get_value(item->itemid, item->value_type, ts, &vc_value))
374 {
375 switch (regexp_match_ex(®exps, vc_value.value.log->source, arg1, ZBX_CASE_SENSITIVE))
376 {
377 case ZBX_REGEXP_MATCH:
378 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
379 ret = SUCCEED;
380 break;
381 case ZBX_REGEXP_NO_MATCH:
382 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
383 ret = SUCCEED;
384 break;
385 case FAIL:
386 *error = zbx_dsprintf(*error, "invalid regular expression");
387 }
388
389 zbx_history_record_clear(&vc_value, item->value_type);
390 }
391 else
392 {
393 zabbix_log(LOG_LEVEL_DEBUG, "result for LOGSOURCE is empty");
394 *error = zbx_strdup(*error, "cannot get values from value cache");
395 }
396 out:
397 zbx_free(arg1);
398
399 zbx_regexp_clean_expressions(®exps);
400 zbx_vector_ptr_destroy(®exps);
401
402 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
403
404 return ret;
405 }
406
407 /******************************************************************************
408 * *
409 * Function: evaluate_LOGSEVERITY *
410 * *
411 * Purpose: evaluate function 'logseverity' for the item *
412 * *
413 * Parameters: item - item (performance metric) *
414 * *
415 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
416 * FAIL - failed to evaluate function *
417 * *
418 ******************************************************************************/
evaluate_LOGSEVERITY(char * value,DC_ITEM * item,const zbx_timespec_t * ts,char ** error)419 static int evaluate_LOGSEVERITY(char *value, DC_ITEM *item, const zbx_timespec_t *ts, char **error)
420 {
421 const char *__function_name = "evaluate_LOGSEVERITY";
422
423 int ret = FAIL;
424 zbx_history_record_t vc_value;
425
426 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
427
428 if (ITEM_VALUE_TYPE_LOG != item->value_type)
429 {
430 *error = zbx_strdup(*error, "invalid value type");
431 goto out;
432 }
433
434 if (SUCCEED == zbx_vc_get_value(item->itemid, item->value_type, ts, &vc_value))
435 {
436 zbx_snprintf(value, MAX_BUFFER_LEN, "%d", vc_value.value.log->severity);
437 zbx_history_record_clear(&vc_value, item->value_type);
438
439 ret = SUCCEED;
440 }
441 else
442 {
443 zabbix_log(LOG_LEVEL_DEBUG, "result for LOGSEVERITY is empty");
444 *error = zbx_strdup(*error, "cannot get value from value cache");
445 }
446 out:
447 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
448
449 return ret;
450 }
451
452 #define OP_UNKNOWN -1
453 #define OP_EQ 0
454 #define OP_NE 1
455 #define OP_GT 2
456 #define OP_GE 3
457 #define OP_LT 4
458 #define OP_LE 5
459 #define OP_LIKE 6
460 #define OP_REGEXP 7
461 #define OP_IREGEXP 8
462 #define OP_BAND 9
463 #define OP_MAX 10
464
count_one_ui64(int * count,int op,zbx_uint64_t value,zbx_uint64_t pattern,zbx_uint64_t mask)465 static void count_one_ui64(int *count, int op, zbx_uint64_t value, zbx_uint64_t pattern, zbx_uint64_t mask)
466 {
467 switch (op)
468 {
469 case OP_EQ:
470 if (value == pattern)
471 (*count)++;
472 break;
473 case OP_NE:
474 if (value != pattern)
475 (*count)++;
476 break;
477 case OP_GT:
478 if (value > pattern)
479 (*count)++;
480 break;
481 case OP_GE:
482 if (value >= pattern)
483 (*count)++;
484 break;
485 case OP_LT:
486 if (value < pattern)
487 (*count)++;
488 break;
489 case OP_LE:
490 if (value <= pattern)
491 (*count)++;
492 break;
493 case OP_BAND:
494 if ((value & mask) == pattern)
495 (*count)++;
496 }
497 }
498
count_one_dbl(int * count,int op,double value,double pattern)499 static void count_one_dbl(int *count, int op, double value, double pattern)
500 {
501 switch (op)
502 {
503 case OP_EQ:
504 if (value > pattern - ZBX_DOUBLE_EPSILON && value < pattern + ZBX_DOUBLE_EPSILON)
505 (*count)++;
506 break;
507 case OP_NE:
508 if (!(value > pattern - ZBX_DOUBLE_EPSILON && value < pattern + ZBX_DOUBLE_EPSILON))
509 (*count)++;
510 break;
511 case OP_GT:
512 if (value >= pattern + ZBX_DOUBLE_EPSILON)
513 (*count)++;
514 break;
515 case OP_GE:
516 if (value > pattern - ZBX_DOUBLE_EPSILON)
517 (*count)++;
518 break;
519 case OP_LT:
520 if (value <= pattern - ZBX_DOUBLE_EPSILON)
521 (*count)++;
522 break;
523 case OP_LE:
524 if (value < pattern + ZBX_DOUBLE_EPSILON)
525 (*count)++;
526 }
527 }
528
count_one_str(int * count,int op,const char * value,const char * pattern,zbx_vector_ptr_t * regexps)529 static void count_one_str(int *count, int op, const char *value, const char *pattern, zbx_vector_ptr_t *regexps)
530 {
531 int res;
532
533 switch (op)
534 {
535 case OP_EQ:
536 if (0 == strcmp(value, pattern))
537 (*count)++;
538 break;
539 case OP_NE:
540 if (0 != strcmp(value, pattern))
541 (*count)++;
542 break;
543 case OP_LIKE:
544 if (NULL != strstr(value, pattern))
545 (*count)++;
546 break;
547 case OP_REGEXP:
548 if (ZBX_REGEXP_MATCH == (res = regexp_match_ex(regexps, value, pattern, ZBX_CASE_SENSITIVE)))
549 (*count)++;
550 else if (FAIL == res)
551 *count = FAIL;
552 break;
553 case OP_IREGEXP:
554 if (ZBX_REGEXP_MATCH == (res = regexp_match_ex(regexps, value, pattern, ZBX_IGNORE_CASE)))
555 (*count)++;
556 else if (FAIL == res)
557 *count = FAIL;
558 }
559 }
560
561 /******************************************************************************
562 * *
563 * Function: evaluate_COUNT *
564 * *
565 * Purpose: evaluate function 'count' for the item *
566 * *
567 * Parameters: item - item (performance metric) *
568 * parameters - up to four comma-separated fields: *
569 * (1) number of seconds/values *
570 * (2) value to compare with (optional) *
571 * Becomes mandatory for numeric items if 3rd *
572 * parameter is specified and is not "regexp" *
573 * or "iregexp". With "band" can take one of *
574 * 2 forms: *
575 * - value_to_compare_with/mask *
576 * - mask *
577 * (3) comparison operator (optional) *
578 * (4) time shift (optional) *
579 * *
580 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
581 * FAIL - failed to evaluate function *
582 * *
583 ******************************************************************************/
evaluate_COUNT(char * value,DC_ITEM * item,const char * parameters,const zbx_timespec_t * ts,char ** error)584 static int evaluate_COUNT(char *value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts,
585 char **error)
586 {
587 const char *__function_name = "evaluate_COUNT";
588 int arg1, op = OP_UNKNOWN, numeric_search, nparams, count = 0, i, ret = FAIL;
589 int seconds = 0, nvalues = 0;
590 char *arg2 = NULL, *arg2_2 = NULL, *arg3 = NULL, buf[ZBX_MAX_UINT64_LEN];
591 double arg2_dbl;
592 zbx_uint64_t arg2_ui64, arg2_2_ui64;
593 zbx_value_type_t arg1_type;
594 zbx_vector_ptr_t regexps;
595 zbx_vector_history_record_t values;
596 zbx_timespec_t ts_end = *ts;
597
598 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
599
600 zbx_vector_ptr_create(®exps);
601 zbx_history_record_vector_create(&values);
602
603 numeric_search = (ITEM_VALUE_TYPE_UINT64 == item->value_type || ITEM_VALUE_TYPE_FLOAT == item->value_type);
604
605 if (4 < (nparams = num_param(parameters)))
606 {
607 *error = zbx_strdup(*error, "invalid number of parameters");
608 goto out;
609 }
610
611 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
612 &arg1_type) || 0 >= arg1)
613 {
614 *error = zbx_strdup(*error, "invalid first parameter");
615 goto out;
616 }
617
618 if (2 <= nparams && SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 2, &arg2))
619 {
620 *error = zbx_strdup(*error, "invalid second parameter");
621 goto out;
622 }
623
624 if (3 <= nparams && SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 3, &arg3))
625 {
626 *error = zbx_strdup(*error, "invalid third parameter");
627 goto out;
628 }
629
630 if (4 <= nparams)
631 {
632 int time_shift = 0;
633 zbx_value_type_t time_shift_type = ZBX_VALUE_SECONDS;
634
635 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 4, ZBX_PARAM_OPTIONAL,
636 &time_shift, &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type ||
637 0 > time_shift)
638 {
639 *error = zbx_strdup(*error, "invalid fourth parameter");
640 goto out;
641 }
642
643 ts_end.sec -= time_shift;
644 }
645
646 if (NULL == arg3 || '\0' == *arg3)
647 op = (0 != numeric_search ? OP_EQ : OP_LIKE);
648 else if (0 == strcmp(arg3, "eq"))
649 op = OP_EQ;
650 else if (0 == strcmp(arg3, "ne"))
651 op = OP_NE;
652 else if (0 == strcmp(arg3, "gt"))
653 op = OP_GT;
654 else if (0 == strcmp(arg3, "ge"))
655 op = OP_GE;
656 else if (0 == strcmp(arg3, "lt"))
657 op = OP_LT;
658 else if (0 == strcmp(arg3, "le"))
659 op = OP_LE;
660 else if (0 == strcmp(arg3, "like"))
661 op = OP_LIKE;
662 else if (0 == strcmp(arg3, "regexp"))
663 op = OP_REGEXP;
664 else if (0 == strcmp(arg3, "iregexp"))
665 op = OP_IREGEXP;
666 else if (0 == strcmp(arg3, "band"))
667 op = OP_BAND;
668
669 if (OP_UNKNOWN == op)
670 {
671 *error = zbx_dsprintf(*error, "operator \"%s\" is not supported for function COUNT", arg3);
672 goto out;
673 }
674
675 numeric_search = (0 != numeric_search && OP_REGEXP != op && OP_IREGEXP != op);
676
677 if (0 != numeric_search)
678 {
679 if (NULL != arg3 && '\0' != *arg3 && '\0' == *arg2)
680 {
681 *error = zbx_strdup(*error, "pattern must be provided along with operator for numeric values");
682 goto out;
683 }
684
685 if (OP_LIKE == op)
686 {
687 *error = zbx_dsprintf(*error, "operator \"%s\" is not supported for counting numeric values",
688 arg3);
689 goto out;
690 }
691
692 if (OP_BAND == op && ITEM_VALUE_TYPE_FLOAT == item->value_type)
693 {
694 *error = zbx_dsprintf(*error, "operator \"%s\" is not supported for counting float values",
695 arg3);
696 goto out;
697 }
698
699 if (OP_BAND == op && NULL != (arg2_2 = strchr(arg2, '/')))
700 {
701 *arg2_2 = '\0'; /* end of the 1st part of the 2nd parameter (number to compare with) */
702 arg2_2++; /* start of the 2nd part of the 2nd parameter (mask) */
703 }
704
705 if (NULL != arg2 && '\0' != *arg2)
706 {
707 if (ITEM_VALUE_TYPE_UINT64 == item->value_type)
708 {
709 if (OP_BAND != op)
710 {
711 if (SUCCEED != str2uint64(arg2, ZBX_UNIT_SYMBOLS, &arg2_ui64))
712 {
713 *error = zbx_dsprintf(*error, "\"%s\" is not a valid numeric unsigned"
714 " value", arg2);
715 goto out;
716 }
717 }
718 else
719 {
720 if (SUCCEED != is_uint64(arg2, &arg2_ui64))
721 {
722 *error = zbx_dsprintf(*error, "\"%s\" is not a valid numeric unsigned"
723 " value", arg2);
724 goto out;
725 }
726
727 if (NULL != arg2_2)
728 {
729 if (SUCCEED != is_uint64(arg2_2, &arg2_2_ui64))
730 {
731 *error = zbx_dsprintf(*error, "\"%s\" is not a valid numeric"
732 " unsigned value", arg2_2);
733 goto out;
734 }
735 }
736 else
737 arg2_2_ui64 = arg2_ui64;
738 }
739 }
740 else
741 {
742 if (SUCCEED != is_double_suffix(arg2, ZBX_FLAG_DOUBLE_SUFFIX))
743 {
744 *error = zbx_dsprintf(*error, "\"%s\" is not a valid numeric float value",
745 arg2);
746 goto out;
747 }
748
749 arg2_dbl = str2double(arg2);
750 }
751 }
752 }
753 else if (OP_LIKE != op && OP_REGEXP != op && OP_IREGEXP != op && OP_EQ != op && OP_NE != op)
754 {
755 *error = zbx_dsprintf(*error, "operator \"%s\" is not supported for counting textual values", arg3);
756 goto out;
757 }
758
759 if ((OP_REGEXP == op || OP_IREGEXP == op) && '@' == *arg2)
760 {
761 DCget_expressions_by_name(®exps, arg2 + 1);
762
763 if (0 == regexps.values_num)
764 {
765 *error = zbx_dsprintf(*error, "global regular expression \"%s\" does not exist", arg2 + 1);
766 goto out;
767 }
768 }
769
770 switch (arg1_type)
771 {
772 case ZBX_VALUE_SECONDS:
773 seconds = arg1;
774 break;
775 case ZBX_VALUE_NVALUES:
776 nvalues = arg1;
777 break;
778 default:
779 THIS_SHOULD_NEVER_HAPPEN;
780 }
781
782 if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
783 {
784 *error = zbx_strdup(*error, "cannot get values from value cache");
785 goto out;
786 }
787
788 /* skip counting values one by one if both pattern and operator are empty or "" is searched in text values */
789 if ((NULL != arg2 && '\0' != *arg2) || (NULL != arg3 && '\0' != *arg3 &&
790 OP_LIKE != op && OP_REGEXP != op && OP_IREGEXP != op))
791 {
792 switch (item->value_type)
793 {
794 case ITEM_VALUE_TYPE_UINT64:
795 if (0 != numeric_search)
796 {
797 for (i = 0; i < values.values_num; i++)
798 {
799 count_one_ui64(&count, op, values.values[i].value.ui64, arg2_ui64,
800 arg2_2_ui64);
801 }
802 }
803 else
804 {
805 for (i = 0; i < values.values_num && FAIL != count; i++)
806 {
807 zbx_snprintf(buf, sizeof(buf), ZBX_FS_UI64,
808 values.values[i].value.ui64);
809 count_one_str(&count, op, buf, arg2, ®exps);
810 }
811 }
812 break;
813 case ITEM_VALUE_TYPE_FLOAT:
814 if (0 != numeric_search)
815 {
816 for (i = 0; i < values.values_num; i++)
817 count_one_dbl(&count, op, values.values[i].value.dbl, arg2_dbl);
818 }
819 else
820 {
821 for (i = 0; i < values.values_num && FAIL != count; i++)
822 {
823 zbx_snprintf(buf, sizeof(buf), ZBX_FS_DBL_EXT(4),
824 values.values[i].value.dbl);
825 count_one_str(&count, op, buf, arg2, ®exps);
826 }
827 }
828 break;
829 case ITEM_VALUE_TYPE_LOG:
830 for (i = 0; i < values.values_num && FAIL != count; i++)
831 count_one_str(&count, op, values.values[i].value.log->value, arg2, ®exps);
832 break;
833 default:
834 for (i = 0; i < values.values_num && FAIL != count; i++)
835 count_one_str(&count, op, values.values[i].value.str, arg2, ®exps);
836 }
837
838 if (FAIL == count)
839 {
840 *error = zbx_strdup(*error, "invalid regular expression");
841 goto out;
842 }
843 }
844 else
845 count = values.values_num;
846
847 zbx_snprintf(value, MAX_BUFFER_LEN, "%d", count);
848
849 ret = SUCCEED;
850 out:
851 zbx_free(arg2);
852 zbx_free(arg3);
853
854 zbx_regexp_clean_expressions(®exps);
855 zbx_vector_ptr_destroy(®exps);
856
857 zbx_history_record_vector_destroy(&values, item->value_type);
858
859 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
860
861 return ret;
862 }
863
864 #undef OP_UNKNOWN
865 #undef OP_EQ
866 #undef OP_NE
867 #undef OP_GT
868 #undef OP_GE
869 #undef OP_LT
870 #undef OP_LE
871 #undef OP_LIKE
872 #undef OP_REGEXP
873 #undef OP_IREGEXP
874 #undef OP_BAND
875 #undef OP_MAX
876
877 /******************************************************************************
878 * *
879 * Function: evaluate_SUM *
880 * *
881 * Purpose: evaluate function 'sum' for the item *
882 * *
883 * Parameters: item - item (performance metric) *
884 * parameters - number of seconds/values and time shift (optional)*
885 * *
886 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
887 * FAIL - failed to evaluate function *
888 * *
889 ******************************************************************************/
evaluate_SUM(char * value,DC_ITEM * item,const char * parameters,const zbx_timespec_t * ts,char ** error)890 static int evaluate_SUM(char *value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts, char **error)
891 {
892 const char *__function_name = "evaluate_SUM";
893 int nparams, arg1, i, ret = FAIL, seconds = 0, nvalues = 0;
894 zbx_value_type_t arg1_type;
895 zbx_vector_history_record_t values;
896 history_value_t result;
897 zbx_timespec_t ts_end = *ts;
898
899 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
900
901 zbx_history_record_vector_create(&values);
902
903 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
904 {
905 *error = zbx_strdup(*error, "invalid value type");
906 goto out;
907 }
908
909 if (2 < (nparams = num_param(parameters)))
910 {
911 *error = zbx_strdup(*error, "invalid number of parameters");
912 goto out;
913 }
914
915 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
916 &arg1_type) || 0 >= arg1)
917 {
918 *error = zbx_strdup(*error, "invalid first parameter");
919 goto out;
920 }
921
922 if (2 == nparams)
923 {
924 int time_shift = 0;
925 zbx_value_type_t time_shift_type = ZBX_VALUE_SECONDS;
926
927 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL,
928 &time_shift, &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type ||
929 0 > time_shift)
930 {
931 *error = zbx_strdup(*error, "invalid second parameter");
932 goto out;
933 }
934
935 ts_end.sec -= time_shift;
936 }
937
938 switch (arg1_type)
939 {
940 case ZBX_VALUE_SECONDS:
941 seconds = arg1;
942 break;
943 case ZBX_VALUE_NVALUES:
944 nvalues = arg1;
945 break;
946 default:
947 THIS_SHOULD_NEVER_HAPPEN;
948 }
949
950 if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
951 {
952 *error = zbx_strdup(*error, "cannot get values from value cache");
953 goto out;
954 }
955
956 if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
957 {
958 result.dbl = 0;
959
960 for (i = 0; i < values.values_num; i++)
961 result.dbl += values.values[i].value.dbl;
962 }
963 else
964 {
965 result.ui64 = 0;
966
967 for (i = 0; i < values.values_num; i++)
968 result.ui64 += values.values[i].value.ui64;
969 }
970
971 zbx_history_value2str(value, MAX_BUFFER_LEN, &result, item->value_type);
972 ret = SUCCEED;
973 out:
974 zbx_history_record_vector_destroy(&values, item->value_type);
975
976 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
977
978 return ret;
979 }
980
981 /******************************************************************************
982 * *
983 * Function: evaluate_AVG *
984 * *
985 * Purpose: evaluate function 'avg' for the item *
986 * *
987 * Parameters: item - item (performance metric) *
988 * parameters - number of seconds/values and time shift (optional)*
989 * *
990 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
991 * FAIL - failed to evaluate function *
992 * *
993 ******************************************************************************/
evaluate_AVG(char * value,DC_ITEM * item,const char * parameters,const zbx_timespec_t * ts,char ** error)994 static int evaluate_AVG(char *value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts, char **error)
995 {
996 const char *__function_name = "evaluate_AVG";
997 int nparams, arg1, ret = FAIL, i, seconds = 0, nvalues = 0;
998 zbx_value_type_t arg1_type;
999 zbx_vector_history_record_t values;
1000 zbx_timespec_t ts_end = *ts;
1001
1002 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1003
1004 zbx_history_record_vector_create(&values);
1005
1006 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
1007 {
1008 *error = zbx_strdup(*error, "invalid value type");
1009 goto out;
1010 }
1011
1012 if (2 < (nparams = num_param(parameters)))
1013 {
1014 *error = zbx_strdup(*error, "invalid number of parameters");
1015 goto out;
1016 }
1017
1018 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
1019 &arg1_type) || 0 >= arg1)
1020 {
1021 *error = zbx_strdup(*error, "invalid first parameter");
1022 goto out;
1023 }
1024
1025 if (2 == nparams)
1026 {
1027 int time_shift = 0;
1028 zbx_value_type_t time_shift_type = ZBX_VALUE_SECONDS;
1029
1030 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL,
1031 &time_shift, &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type ||
1032 0 > time_shift)
1033 {
1034 *error = zbx_strdup(*error, "invalid second parameter");
1035 goto out;
1036 }
1037
1038 ts_end.sec -= time_shift;
1039 }
1040
1041 switch (arg1_type)
1042 {
1043 case ZBX_VALUE_SECONDS:
1044 seconds = arg1;
1045 break;
1046 case ZBX_VALUE_NVALUES:
1047 nvalues = arg1;
1048 break;
1049 default:
1050 THIS_SHOULD_NEVER_HAPPEN;
1051 }
1052
1053 if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
1054 {
1055 *error = zbx_strdup(*error, "cannot get values from value cache");
1056 goto out;
1057 }
1058
1059 if (0 < values.values_num)
1060 {
1061 double sum = 0;
1062
1063 if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
1064 {
1065 for (i = 0; i < values.values_num; i++)
1066 sum += values.values[i].value.dbl;
1067 }
1068 else
1069 {
1070 for (i = 0; i < values.values_num; i++)
1071 sum += values.values[i].value.ui64;
1072 }
1073 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_DBL, sum / values.values_num);
1074
1075 ret = SUCCEED;
1076 }
1077 else
1078 {
1079 zabbix_log(LOG_LEVEL_DEBUG, "result for AVG is empty");
1080 *error = zbx_strdup(*error, "not enough data");
1081 }
1082 out:
1083 zbx_history_record_vector_destroy(&values, item->value_type);
1084
1085 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1086
1087 return ret;
1088 }
1089
1090 /******************************************************************************
1091 * *
1092 * Function: evaluate_LAST *
1093 * *
1094 * Purpose: evaluate functions 'last' and 'prev' for the item *
1095 * *
1096 * Parameters: value - buffer of size MAX_BUFFER_LEN *
1097 * item - item (performance metric) *
1098 * parameters - Nth last value and time shift (optional) *
1099 * *
1100 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1101 * FAIL - failed to evaluate function *
1102 * *
1103 ******************************************************************************/
evaluate_LAST(char * value,DC_ITEM * item,const char * parameters,const zbx_timespec_t * ts,char ** error)1104 static int evaluate_LAST(char *value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts,
1105 char **error)
1106 {
1107 const char *__function_name = "evaluate_LAST";
1108 int arg1 = 1, ret = FAIL;
1109 zbx_value_type_t arg1_type = ZBX_VALUE_NVALUES;
1110 zbx_vector_history_record_t values;
1111 zbx_timespec_t ts_end = *ts;
1112
1113 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1114
1115 zbx_history_record_vector_create(&values);
1116
1117 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_OPTIONAL, &arg1,
1118 &arg1_type))
1119 {
1120 *error = zbx_strdup(*error, "invalid first parameter");
1121 goto out;
1122 }
1123
1124 if (ZBX_VALUE_NVALUES != arg1_type)
1125 arg1 = 1; /* non-# first parameter is ignored to support older syntax "last(0)" */
1126
1127 if (2 == num_param(parameters))
1128 {
1129 int time_shift = 0;
1130 zbx_value_type_t time_shift_type = ZBX_VALUE_SECONDS;
1131
1132 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL,
1133 &time_shift, &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type ||
1134 0 > time_shift)
1135 {
1136 *error = zbx_strdup(*error, "invalid second parameter");
1137 goto out;
1138 }
1139
1140 ts_end.sec -= time_shift;
1141 }
1142
1143 if (SUCCEED == zbx_vc_get_values(item->itemid, item->value_type, &values, 0, arg1, &ts_end))
1144 {
1145 if (arg1 <= values.values_num)
1146 {
1147 zbx_history_value2str(value, MAX_BUFFER_LEN, &values.values[arg1 - 1].value,
1148 item->value_type);
1149 ret = SUCCEED;
1150 }
1151 else
1152 {
1153 *error = zbx_strdup(*error, "not enough data");
1154 goto out;
1155 }
1156 }
1157 else
1158 {
1159 *error = zbx_strdup(*error, "cannot get values from value cache");
1160 }
1161 out:
1162 zbx_history_record_vector_destroy(&values, item->value_type);
1163
1164 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1165
1166 return ret;
1167 }
1168
1169 /******************************************************************************
1170 * *
1171 * Function: evaluate_MIN *
1172 * *
1173 * Purpose: evaluate function 'min' for the item *
1174 * *
1175 * Parameters: item - item (performance metric) *
1176 * parameters - number of seconds/values and time shift (optional)*
1177 * *
1178 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1179 * FAIL - failed to evaluate function *
1180 * *
1181 ******************************************************************************/
evaluate_MIN(char * value,DC_ITEM * item,const char * parameters,const zbx_timespec_t * ts,char ** error)1182 static int evaluate_MIN(char *value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts, char **error)
1183 {
1184 const char *__function_name = "evaluate_MIN";
1185 int nparams, arg1, i, ret = FAIL, seconds = 0, nvalues = 0;
1186 zbx_value_type_t arg1_type;
1187 zbx_vector_history_record_t values;
1188 zbx_timespec_t ts_end = *ts;
1189
1190 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1191
1192 zbx_history_record_vector_create(&values);
1193
1194 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
1195 {
1196 *error = zbx_strdup(*error, "invalid value type");
1197 goto out;
1198 }
1199
1200 if (2 < (nparams = num_param(parameters)))
1201 {
1202 *error = zbx_strdup(*error, "invalid number of parameters");
1203 goto out;
1204 }
1205
1206 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
1207 &arg1_type) || 0 >= arg1)
1208 {
1209 *error = zbx_strdup(*error, "invalid first parameter");
1210 goto out;
1211 }
1212
1213 if (2 == nparams)
1214 {
1215 int time_shift = 0;
1216 zbx_value_type_t time_shift_type = ZBX_VALUE_SECONDS;
1217
1218 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL,
1219 &time_shift, &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type ||
1220 0 > time_shift)
1221 {
1222 *error = zbx_strdup(*error, "invalid second parameter");
1223 goto out;
1224 }
1225
1226 ts_end.sec -= time_shift;
1227 }
1228
1229 switch (arg1_type)
1230 {
1231 case ZBX_VALUE_SECONDS:
1232 seconds = arg1;
1233 break;
1234 case ZBX_VALUE_NVALUES:
1235 nvalues = arg1;
1236 break;
1237 default:
1238 THIS_SHOULD_NEVER_HAPPEN;
1239 }
1240
1241 if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
1242 {
1243 *error = zbx_strdup(*error, "cannot get values from value cache");
1244 goto out;
1245 }
1246
1247 if (0 < values.values_num)
1248 {
1249 int index = 0;
1250
1251 if (ITEM_VALUE_TYPE_UINT64 == item->value_type)
1252 {
1253 for (i = 1; i < values.values_num; i++)
1254 {
1255 if (values.values[i].value.ui64 < values.values[index].value.ui64)
1256 index = i;
1257 }
1258 }
1259 else
1260 {
1261 for (i = 1; i < values.values_num; i++)
1262 {
1263 if (values.values[i].value.dbl < values.values[index].value.dbl)
1264 index = i;
1265 }
1266 }
1267 zbx_history_value2str(value, MAX_BUFFER_LEN, &values.values[index].value, item->value_type);
1268
1269 ret = SUCCEED;
1270 }
1271 else
1272 {
1273 zabbix_log(LOG_LEVEL_DEBUG, "result for MIN is empty");
1274 *error = zbx_strdup(*error, "not enough data");
1275 }
1276 out:
1277 zbx_history_record_vector_destroy(&values, item->value_type);
1278
1279 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1280
1281 return ret;
1282 }
1283
1284 /******************************************************************************
1285 * *
1286 * Function: evaluate_MAX *
1287 * *
1288 * Purpose: evaluate function 'max' for the item *
1289 * *
1290 * Parameters: item - item (performance metric) *
1291 * parameters - number of seconds/values and time shift (optional)*
1292 * *
1293 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1294 * FAIL - failed to evaluate function *
1295 * *
1296 ******************************************************************************/
evaluate_MAX(char * value,DC_ITEM * item,const char * parameters,const zbx_timespec_t * ts,char ** error)1297 static int evaluate_MAX(char *value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts, char **error)
1298 {
1299 const char *__function_name = "evaluate_MAX";
1300 int nparams, arg1, ret = FAIL, i, seconds = 0, nvalues = 0;
1301 zbx_value_type_t arg1_type;
1302 zbx_vector_history_record_t values;
1303 zbx_timespec_t ts_end = *ts;
1304
1305 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1306
1307 zbx_history_record_vector_create(&values);
1308
1309 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
1310 {
1311 *error = zbx_strdup(*error, "invalid value type");
1312 goto out;
1313 }
1314
1315 if (2 < (nparams = num_param(parameters)))
1316 {
1317 *error = zbx_strdup(*error, "invalid number of parameters");
1318 goto out;
1319 }
1320
1321 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
1322 &arg1_type) || 0 >= arg1)
1323 {
1324 *error = zbx_strdup(*error, "invalid first parameter");
1325 goto out;
1326 }
1327
1328 if (2 == nparams)
1329 {
1330 int time_shift = 0;
1331 zbx_value_type_t time_shift_type = ZBX_VALUE_SECONDS;
1332
1333 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL,
1334 &time_shift, &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type ||
1335 0 > time_shift)
1336 {
1337 *error = zbx_strdup(*error, "invalid second parameter");
1338 goto out;
1339 }
1340
1341 ts_end.sec -= time_shift;
1342 }
1343
1344 switch (arg1_type)
1345 {
1346 case ZBX_VALUE_SECONDS:
1347 seconds = arg1;
1348 break;
1349 case ZBX_VALUE_NVALUES:
1350 nvalues = arg1;
1351 break;
1352 default:
1353 THIS_SHOULD_NEVER_HAPPEN;
1354 }
1355
1356 if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
1357 {
1358 *error = zbx_strdup(*error, "cannot get values from value cache");
1359 goto out;
1360 }
1361
1362 if (0 < values.values_num)
1363 {
1364 int index = 0;
1365
1366 if (ITEM_VALUE_TYPE_UINT64 == item->value_type)
1367 {
1368 for (i = 1; i < values.values_num; i++)
1369 {
1370 if (values.values[i].value.ui64 > values.values[index].value.ui64)
1371 index = i;
1372 }
1373 }
1374 else
1375 {
1376 for (i = 1; i < values.values_num; i++)
1377 {
1378 if (values.values[i].value.dbl > values.values[index].value.dbl)
1379 index = i;
1380 }
1381 }
1382 zbx_history_value2str(value, MAX_BUFFER_LEN, &values.values[index].value, item->value_type);
1383
1384 ret = SUCCEED;
1385 }
1386 else
1387 {
1388 zabbix_log(LOG_LEVEL_DEBUG, "result for MAX is empty");
1389 *error = zbx_strdup(*error, "not enough data");
1390 }
1391 out:
1392 zbx_history_record_vector_destroy(&values, item->value_type);
1393
1394 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1395
1396 return ret;
1397 }
1398
__history_record_float_compare(const zbx_history_record_t * d1,const zbx_history_record_t * d2)1399 static int __history_record_float_compare(const zbx_history_record_t *d1, const zbx_history_record_t *d2)
1400 {
1401 ZBX_RETURN_IF_NOT_EQUAL(d1->value.dbl, d2->value.dbl);
1402
1403 return 0;
1404 }
1405
__history_record_uint64_compare(const zbx_history_record_t * d1,const zbx_history_record_t * d2)1406 static int __history_record_uint64_compare(const zbx_history_record_t *d1, const zbx_history_record_t *d2)
1407 {
1408 ZBX_RETURN_IF_NOT_EQUAL(d1->value.ui64, d2->value.ui64);
1409
1410 return 0;
1411 }
1412
1413 /******************************************************************************
1414 * *
1415 * Function: evaluate_PERCENTILE *
1416 * *
1417 * Purpose: evaluate function 'percentile' for the item *
1418 * *
1419 * Parameters: item - [IN] item (performance metric) *
1420 * parameters - [IN] seconds/values, time shift (optional), *
1421 * percentage *
1422 * *
1423 * Return value: SUCCEED - evaluated successfully, result is stored in *
1424 * 'value' *
1425 * FAIL - failed to evaluate function *
1426 * *
1427 ******************************************************************************/
evaluate_PERCENTILE(char * value,DC_ITEM * item,const char * parameters,const zbx_timespec_t * ts,char ** error)1428 static int evaluate_PERCENTILE(char *value, DC_ITEM *item, const char *parameters,
1429 const zbx_timespec_t *ts, char **error)
1430 {
1431 const char *__function_name = "evaluate_PERCENTILE";
1432
1433 int nparams, arg1, time_shift = 0, ret = FAIL, seconds = 0, nvalues = 0;
1434 zbx_value_type_t arg1_type, time_shift_type = ZBX_VALUE_SECONDS;
1435 double percentage;
1436 zbx_vector_history_record_t values;
1437 zbx_timespec_t ts_end = *ts;
1438
1439 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1440
1441 zbx_history_record_vector_create(&values);
1442
1443 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
1444 {
1445 *error = zbx_strdup(*error, "invalid value type");
1446 goto out;
1447 }
1448
1449 if (3 != (nparams = num_param(parameters)))
1450 {
1451 *error = zbx_strdup(*error, "invalid number of parameters");
1452 goto out;
1453 }
1454
1455 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
1456 &arg1_type) || 0 >= arg1)
1457 {
1458 *error = zbx_strdup(*error, "invalid first parameter");
1459 goto out;
1460 }
1461
1462 switch (arg1_type)
1463 {
1464 case ZBX_VALUE_SECONDS:
1465 seconds = arg1;
1466 break;
1467 case ZBX_VALUE_NVALUES:
1468 nvalues = arg1;
1469 break;
1470 default:
1471 THIS_SHOULD_NEVER_HAPPEN;
1472 }
1473
1474 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL, &time_shift,
1475 &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type || 0 > time_shift)
1476 {
1477 *error = zbx_strdup(*error, "invalid second parameter");
1478 goto out;
1479 }
1480
1481 ts_end.sec -= time_shift;
1482
1483 if (SUCCEED != get_function_parameter_float(item->host.hostid, parameters, 3, ZBX_FLAG_DOUBLE_PLAIN,
1484 &percentage) || 0.0 > percentage || 100.0 < percentage)
1485 {
1486 *error = zbx_strdup(*error, "invalid third parameter");
1487 goto out;
1488 }
1489
1490 if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
1491 {
1492 *error = zbx_strdup(*error, "cannot get values from value cache");
1493 goto out;
1494 }
1495
1496 if (0 < values.values_num)
1497 {
1498 int index;
1499
1500 if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
1501 zbx_vector_history_record_sort(&values, (zbx_compare_func_t)__history_record_float_compare);
1502 else
1503 zbx_vector_history_record_sort(&values, (zbx_compare_func_t)__history_record_uint64_compare);
1504
1505 if (0 == percentage)
1506 index = 1;
1507 else
1508 index = (int)ceil(values.values_num * (percentage / 100));
1509
1510 zbx_history_value2str(value, MAX_BUFFER_LEN, &values.values[index - 1].value, item->value_type);
1511
1512 ret = SUCCEED;
1513 }
1514 else
1515 {
1516 zabbix_log(LOG_LEVEL_DEBUG, "result for PERCENTILE is empty");
1517 *error = zbx_strdup(*error, "not enough data");
1518 }
1519 out:
1520 zbx_history_record_vector_destroy(&values, item->value_type);
1521
1522 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1523
1524 return ret;
1525 }
1526
1527 /******************************************************************************
1528 * *
1529 * Function: evaluate_DELTA *
1530 * *
1531 * Purpose: evaluate function 'delta' for the item *
1532 * *
1533 * Parameters: item - item (performance metric) *
1534 * parameters - number of seconds/values and time shift (optional)*
1535 * *
1536 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1537 * FAIL - failed to evaluate function *
1538 * *
1539 ******************************************************************************/
evaluate_DELTA(char * value,DC_ITEM * item,const char * parameters,const zbx_timespec_t * ts,char ** error)1540 static int evaluate_DELTA(char *value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts,
1541 char **error)
1542 {
1543 const char *__function_name = "evaluate_DELTA";
1544 int nparams, arg1, ret = FAIL, i, seconds = 0, nvalues = 0;
1545 zbx_value_type_t arg1_type;
1546 zbx_vector_history_record_t values;
1547 zbx_timespec_t ts_end = *ts;
1548
1549 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1550
1551 zbx_history_record_vector_create(&values);
1552
1553 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
1554 {
1555 *error = zbx_strdup(*error, "invalid value type");
1556 goto out;
1557 }
1558
1559 if (2 < (nparams = num_param(parameters)))
1560 {
1561 *error = zbx_strdup(*error, "invalid number of parameters");
1562 goto out;
1563 }
1564
1565 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
1566 &arg1_type) || 0 >= arg1)
1567 {
1568 *error = zbx_strdup(*error, "invalid first parameter");
1569 goto out;
1570 }
1571
1572 if (2 == nparams)
1573 {
1574 int time_shift = 0;
1575 zbx_value_type_t time_shift_type = ZBX_VALUE_SECONDS;
1576
1577 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL,
1578 &time_shift, &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type ||
1579 0 > time_shift)
1580 {
1581 *error = zbx_strdup(*error, "invalid second parameter");
1582 goto out;
1583 }
1584
1585 ts_end.sec -= time_shift;
1586 }
1587
1588 switch (arg1_type)
1589 {
1590 case ZBX_VALUE_SECONDS:
1591 seconds = arg1;
1592 break;
1593 case ZBX_VALUE_NVALUES:
1594 nvalues = arg1;
1595 break;
1596 default:
1597 THIS_SHOULD_NEVER_HAPPEN;
1598 }
1599
1600 if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
1601 {
1602 *error = zbx_strdup(*error, "cannot get values from value cache");
1603 goto out;
1604 }
1605
1606 if (0 < values.values_num)
1607 {
1608 history_value_t result;
1609 int index_min = 0, index_max = 0;
1610
1611 if (ITEM_VALUE_TYPE_UINT64 == item->value_type)
1612 {
1613 for (i = 1; i < values.values_num; i++)
1614 {
1615 if (values.values[i].value.ui64 > values.values[index_max].value.ui64)
1616 index_max = i;
1617
1618 if (values.values[i].value.ui64 < values.values[index_min].value.ui64)
1619 index_min = i;
1620 }
1621
1622 result.ui64 = values.values[index_max].value.ui64 - values.values[index_min].value.ui64;
1623 }
1624 else
1625 {
1626 for (i = 1; i < values.values_num; i++)
1627 {
1628 if (values.values[i].value.dbl > values.values[index_max].value.dbl)
1629 index_max = i;
1630
1631 if (values.values[i].value.dbl < values.values[index_min].value.dbl)
1632 index_min = i;
1633 }
1634
1635 result.dbl = values.values[index_max].value.dbl - values.values[index_min].value.dbl;
1636 }
1637
1638 zbx_history_value2str(value, MAX_BUFFER_LEN, &result, item->value_type);
1639
1640 ret = SUCCEED;
1641 }
1642 else
1643 {
1644 zabbix_log(LOG_LEVEL_DEBUG, "result for DELTA is empty");
1645 *error = zbx_strdup(*error, "not enough data");
1646 }
1647 out:
1648 zbx_history_record_vector_destroy(&values, item->value_type);
1649
1650 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1651
1652 return ret;
1653 }
1654
1655 /******************************************************************************
1656 * *
1657 * Function: evaluate_NODATA *
1658 * *
1659 * Purpose: evaluate function 'nodata' for the item *
1660 * *
1661 * Parameters: item - item (performance metric) *
1662 * parameter - number of seconds *
1663 * *
1664 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1665 * FAIL - failed to evaluate function *
1666 * *
1667 ******************************************************************************/
evaluate_NODATA(char * value,DC_ITEM * item,const char * parameters,char ** error)1668 static int evaluate_NODATA(char *value, DC_ITEM *item, const char *parameters, char **error)
1669 {
1670 const char *__function_name = "evaluate_NODATA";
1671 int arg1, ret = FAIL;
1672 zbx_value_type_t arg1_type;
1673 zbx_vector_history_record_t values;
1674 zbx_timespec_t ts;
1675
1676 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1677
1678 zbx_history_record_vector_create(&values);
1679
1680 if (1 < num_param(parameters))
1681 {
1682 *error = zbx_strdup(*error, "invalid number of parameters");
1683 goto out;
1684 }
1685
1686 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
1687 &arg1_type) || ZBX_VALUE_SECONDS != arg1_type || 0 >= arg1)
1688 {
1689 *error = zbx_strdup(*error, "invalid first parameter");
1690 goto out;
1691 }
1692
1693 zbx_timespec(&ts);
1694
1695 if (SUCCEED == zbx_vc_get_values(item->itemid, item->value_type, &values, arg1, 1, &ts) &&
1696 1 == values.values_num)
1697 {
1698 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1699 }
1700 else
1701 {
1702 int seconds;
1703
1704 if (SUCCEED != DCget_data_expected_from(item->itemid, &seconds))
1705 {
1706 *error = zbx_strdup(*error, "item does not exist, is disabled or belongs to a disabled host");
1707 goto out;
1708 }
1709
1710 if (seconds + arg1 > ts.sec)
1711 {
1712 *error = zbx_strdup(*error,
1713 "item does not have enough data after server start or item creation");
1714 goto out;
1715 }
1716
1717 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1718 }
1719
1720 ret = SUCCEED;
1721 out:
1722 zbx_history_record_vector_destroy(&values, item->value_type);
1723
1724 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1725
1726 return ret;
1727 }
1728
1729 /******************************************************************************
1730 * *
1731 * Function: evaluate_ABSCHANGE *
1732 * *
1733 * Purpose: evaluate function 'abschange' for the item *
1734 * *
1735 * Parameters: item - item (performance metric) *
1736 * parameter - number of seconds *
1737 * *
1738 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1739 * FAIL - failed to evaluate function *
1740 * *
1741 ******************************************************************************/
evaluate_ABSCHANGE(char * value,DC_ITEM * item,const zbx_timespec_t * ts,char ** error)1742 static int evaluate_ABSCHANGE(char *value, DC_ITEM *item, const zbx_timespec_t *ts, char **error)
1743 {
1744 const char *__function_name = "evaluate_ABSCHANGE";
1745 int ret = FAIL;
1746 zbx_vector_history_record_t values;
1747
1748 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1749
1750 zbx_history_record_vector_create(&values);
1751
1752 if (SUCCEED != zbx_vc_get_values(item->itemid, item->value_type, &values, 0, 2, ts) ||
1753 2 > values.values_num)
1754 {
1755 *error = zbx_strdup(*error, "cannot get values from value cache");
1756 goto out;
1757 }
1758
1759 switch (item->value_type)
1760 {
1761 case ITEM_VALUE_TYPE_FLOAT:
1762 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_DBL,
1763 fabs(values.values[0].value.dbl - values.values[1].value.dbl));
1764 break;
1765 case ITEM_VALUE_TYPE_UINT64:
1766 /* to avoid overflow */
1767 if (values.values[0].value.ui64 >= values.values[1].value.ui64)
1768 {
1769 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_UI64,
1770 values.values[0].value.ui64 - values.values[1].value.ui64);
1771 }
1772 else
1773 {
1774 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_UI64,
1775 values.values[1].value.ui64 - values.values[0].value.ui64);
1776 }
1777 break;
1778 case ITEM_VALUE_TYPE_LOG:
1779 if (0 == strcmp(values.values[0].value.log->value, values.values[1].value.log->value))
1780 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1781 else
1782 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1783 break;
1784
1785 case ITEM_VALUE_TYPE_STR:
1786 case ITEM_VALUE_TYPE_TEXT:
1787 if (0 == strcmp(values.values[0].value.str, values.values[1].value.str))
1788 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1789 else
1790 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1791 break;
1792 default:
1793 *error = zbx_strdup(*error, "invalid value type");
1794 goto out;
1795 }
1796 ret = SUCCEED;
1797 out:
1798 zbx_history_record_vector_destroy(&values, item->value_type);
1799
1800 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1801
1802 return ret;
1803 }
1804
1805 /******************************************************************************
1806 * *
1807 * Function: evaluate_CHANGE *
1808 * *
1809 * Purpose: evaluate function 'change' for the item *
1810 * *
1811 * Parameters: item - item (performance metric) *
1812 * parameter - number of seconds *
1813 * *
1814 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1815 * FAIL - failed to evaluate function *
1816 * *
1817 ******************************************************************************/
evaluate_CHANGE(char * value,DC_ITEM * item,const zbx_timespec_t * ts,char ** error)1818 static int evaluate_CHANGE(char *value, DC_ITEM *item, const zbx_timespec_t *ts, char **error)
1819 {
1820 const char *__function_name = "evaluate_CHANGE";
1821 int ret = FAIL;
1822 zbx_vector_history_record_t values;
1823
1824 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1825
1826 zbx_history_record_vector_create(&values);
1827
1828 if (SUCCEED != zbx_vc_get_values(item->itemid, item->value_type, &values, 0, 2, ts) ||
1829 2 > values.values_num)
1830 {
1831 *error = zbx_strdup(*error, "cannot get values from value cache");
1832 goto out;
1833 }
1834
1835 switch (item->value_type)
1836 {
1837 case ITEM_VALUE_TYPE_FLOAT:
1838 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_DBL,
1839 values.values[0].value.dbl - values.values[1].value.dbl);
1840 break;
1841 case ITEM_VALUE_TYPE_UINT64:
1842 /* to avoid overflow */
1843 if (values.values[0].value.ui64 >= values.values[1].value.ui64)
1844 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_UI64,
1845 values.values[0].value.ui64 - values.values[1].value.ui64);
1846 else
1847 zbx_snprintf(value, MAX_BUFFER_LEN, "-" ZBX_FS_UI64,
1848 values.values[1].value.ui64 - values.values[0].value.ui64);
1849 break;
1850 case ITEM_VALUE_TYPE_LOG:
1851 if (0 == strcmp(values.values[0].value.log->value, values.values[1].value.log->value))
1852 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1853 else
1854 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1855 break;
1856
1857 case ITEM_VALUE_TYPE_STR:
1858 case ITEM_VALUE_TYPE_TEXT:
1859 if (0 == strcmp(values.values[0].value.str, values.values[1].value.str))
1860 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1861 else
1862 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1863 break;
1864 default:
1865 *error = zbx_strdup(*error, "invalid value type");
1866 goto out;
1867 }
1868
1869 ret = SUCCEED;
1870 out:
1871 zbx_history_record_vector_destroy(&values, item->value_type);
1872
1873 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1874
1875 return ret;
1876 }
1877
1878 /******************************************************************************
1879 * *
1880 * Function: evaluate_DIFF *
1881 * *
1882 * Purpose: evaluate function 'diff' for the item *
1883 * *
1884 * Parameters: item - item (performance metric) *
1885 * parameter - number of seconds *
1886 * *
1887 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1888 * FAIL - failed to evaluate function *
1889 * *
1890 ******************************************************************************/
evaluate_DIFF(char * value,DC_ITEM * item,const zbx_timespec_t * ts,char ** error)1891 static int evaluate_DIFF(char *value, DC_ITEM *item, const zbx_timespec_t *ts, char **error)
1892 {
1893 const char *__function_name = "evaluate_DIFF";
1894 int ret = FAIL;
1895 zbx_vector_history_record_t values;
1896
1897 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1898
1899 zbx_history_record_vector_create(&values);
1900
1901 if (SUCCEED != zbx_vc_get_values(item->itemid, item->value_type, &values, 0, 2, ts) || 2 > values.values_num)
1902 {
1903 *error = zbx_strdup(*error, "cannot get values from value cache");
1904 goto out;
1905 }
1906
1907 switch (item->value_type)
1908 {
1909 case ITEM_VALUE_TYPE_FLOAT:
1910 if (SUCCEED == zbx_double_compare(values.values[0].value.dbl, values.values[1].value.dbl))
1911 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1912 else
1913 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1914 break;
1915 case ITEM_VALUE_TYPE_UINT64:
1916 if (values.values[0].value.ui64 == values.values[1].value.ui64)
1917 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1918 else
1919 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1920 break;
1921 case ITEM_VALUE_TYPE_LOG:
1922 if (0 == strcmp(values.values[0].value.log->value, values.values[1].value.log->value))
1923 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1924 else
1925 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1926 break;
1927 case ITEM_VALUE_TYPE_STR:
1928 case ITEM_VALUE_TYPE_TEXT:
1929 if (0 == strcmp(values.values[0].value.str, values.values[1].value.str))
1930 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1931 else
1932 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1933 break;
1934 default:
1935 *error = zbx_strdup(*error, "invalid value type");
1936 goto out;
1937 }
1938
1939 ret = SUCCEED;
1940 out:
1941 zbx_history_record_vector_destroy(&values, item->value_type);
1942
1943 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1944
1945 return ret;
1946 }
1947
1948 /******************************************************************************
1949 * *
1950 * Function: evaluate_STR *
1951 * *
1952 * Purpose: evaluate function 'str' for the item *
1953 * *
1954 * Parameters: item - item (performance metric) *
1955 * parameters - <string>[,seconds] *
1956 * *
1957 * Return value: SUCCEED - evaluated successfully, result stored in 'value' *
1958 * FAIL - failed to match the regular expression *
1959 * NOTSUPPORTED - invalid regular expression *
1960 * *
1961 ******************************************************************************/
1962
1963 #define ZBX_FUNC_STR 1
1964 #define ZBX_FUNC_REGEXP 2
1965 #define ZBX_FUNC_IREGEXP 3
1966
evaluate_STR_one(int func,zbx_vector_ptr_t * regexps,const char * value,const char * arg1)1967 static int evaluate_STR_one(int func, zbx_vector_ptr_t *regexps, const char *value, const char *arg1)
1968 {
1969 switch (func)
1970 {
1971 case ZBX_FUNC_STR:
1972 if (NULL != strstr(value, arg1))
1973 return SUCCEED;
1974 break;
1975 case ZBX_FUNC_REGEXP:
1976 switch (regexp_match_ex(regexps, value, arg1, ZBX_CASE_SENSITIVE))
1977 {
1978 case ZBX_REGEXP_MATCH:
1979 return SUCCEED;
1980 case FAIL:
1981 return NOTSUPPORTED;
1982 }
1983 break;
1984 case ZBX_FUNC_IREGEXP:
1985 switch (regexp_match_ex(regexps, value, arg1, ZBX_IGNORE_CASE))
1986 {
1987 case ZBX_REGEXP_MATCH:
1988 return SUCCEED;
1989 case FAIL:
1990 return NOTSUPPORTED;
1991 }
1992 break;
1993 }
1994
1995 return FAIL;
1996 }
1997
evaluate_STR(char * value,DC_ITEM * item,const char * function,const char * parameters,const zbx_timespec_t * ts,char ** error)1998 static int evaluate_STR(char *value, DC_ITEM *item, const char *function, const char *parameters,
1999 const zbx_timespec_t *ts, char **error)
2000 {
2001 const char *__function_name = "evaluate_STR";
2002 char *arg1 = NULL;
2003 int arg2 = 1, func, found = 0, i, ret = FAIL, seconds = 0, nvalues = 0, nparams;
2004 int str_one_ret;
2005 zbx_value_type_t arg2_type = ZBX_VALUE_NVALUES;
2006 zbx_vector_ptr_t regexps;
2007 zbx_vector_history_record_t values;
2008
2009 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2010
2011 zbx_vector_ptr_create(®exps);
2012 zbx_history_record_vector_create(&values);
2013
2014 if (ITEM_VALUE_TYPE_STR != item->value_type && ITEM_VALUE_TYPE_TEXT != item->value_type &&
2015 ITEM_VALUE_TYPE_LOG != item->value_type)
2016 {
2017 *error = zbx_strdup(*error, "invalid value type");
2018 goto out;
2019 }
2020
2021 if (0 == strcmp(function, "str"))
2022 func = ZBX_FUNC_STR;
2023 else if (0 == strcmp(function, "regexp"))
2024 func = ZBX_FUNC_REGEXP;
2025 else if (0 == strcmp(function, "iregexp"))
2026 func = ZBX_FUNC_IREGEXP;
2027 else
2028 goto out;
2029
2030 if (2 < (nparams = num_param(parameters)))
2031 {
2032 *error = zbx_strdup(*error, "invalid number of parameters");
2033 goto out;
2034 }
2035
2036 if (SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 1, &arg1))
2037 {
2038 *error = zbx_strdup(*error, "invalid first parameter");
2039 goto out;
2040 }
2041
2042 if (2 == nparams)
2043 {
2044 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL, &arg2,
2045 &arg2_type) || 0 >= arg2)
2046 {
2047 *error = zbx_strdup(*error, "invalid second parameter");
2048 goto out;
2049 }
2050 }
2051
2052 if ((ZBX_FUNC_REGEXP == func || ZBX_FUNC_IREGEXP == func) && '@' == *arg1)
2053 {
2054 DCget_expressions_by_name(®exps, arg1 + 1);
2055
2056 if (0 == regexps.values_num)
2057 {
2058 *error = zbx_dsprintf(*error, "global regular expression \"%s\" does not exist", arg1 + 1);
2059 goto out;
2060 }
2061 }
2062
2063 switch (arg2_type)
2064 {
2065 case ZBX_VALUE_SECONDS:
2066 seconds = arg2;
2067 break;
2068 case ZBX_VALUE_NVALUES:
2069 nvalues = arg2;
2070 break;
2071 default:
2072 THIS_SHOULD_NEVER_HAPPEN;
2073 }
2074
2075 if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, ts))
2076 {
2077 *error = zbx_strdup(*error, "cannot get values from value cache");
2078 goto out;
2079 }
2080
2081 if (0 != values.values_num)
2082 {
2083 /* at this point the value type can be only str, text or log */
2084 if (ITEM_VALUE_TYPE_LOG == item->value_type)
2085 {
2086 for (i = 0; i < values.values_num; i++)
2087 {
2088 if (SUCCEED == (str_one_ret = evaluate_STR_one(func, ®exps,
2089 values.values[i].value.log->value, arg1)))
2090 {
2091 found = 1;
2092 break;
2093 }
2094
2095 if (NOTSUPPORTED == str_one_ret)
2096 {
2097 *error = zbx_dsprintf(*error, "invalid regular expression \"%s\"", arg1);
2098 goto out;
2099 }
2100 }
2101 }
2102 else
2103 {
2104 for (i = 0; i < values.values_num; i++)
2105 {
2106 if (SUCCEED == (str_one_ret = evaluate_STR_one(func, ®exps,
2107 values.values[i].value.str, arg1)))
2108 {
2109 found = 1;
2110 break;
2111 }
2112
2113 if (NOTSUPPORTED == str_one_ret)
2114 {
2115 *error = zbx_dsprintf(*error, "invalid regular expression \"%s\"", arg1);
2116 goto out;
2117 }
2118 }
2119 }
2120 }
2121
2122 zbx_snprintf(value, MAX_BUFFER_LEN, "%d", found);
2123 ret = SUCCEED;
2124 out:
2125 zbx_regexp_clean_expressions(®exps);
2126 zbx_vector_ptr_destroy(®exps);
2127
2128 zbx_history_record_vector_destroy(&values, item->value_type);
2129
2130 zbx_free(arg1);
2131
2132 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
2133
2134 return ret;
2135 }
2136
2137 #undef ZBX_FUNC_STR
2138 #undef ZBX_FUNC_REGEXP
2139 #undef ZBX_FUNC_IREGEXP
2140
2141 /******************************************************************************
2142 * *
2143 * Function: evaluate_STRLEN *
2144 * *
2145 * Purpose: evaluate function 'strlen' for the item *
2146 * *
2147 * Parameters: value - buffer of size MAX_BUFFER_LEN *
2148 * item - item (performance metric) *
2149 * parameters - Nth last value and time shift (optional) *
2150 * *
2151 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
2152 * FAIL - failed to evaluate function *
2153 * *
2154 ******************************************************************************/
evaluate_STRLEN(char * value,DC_ITEM * item,const char * parameters,const zbx_timespec_t * ts,char ** error)2155 static int evaluate_STRLEN(char *value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts,
2156 char **error)
2157 {
2158 const char *__function_name = "evaluate_STRLEN";
2159 int ret = FAIL;
2160
2161 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2162
2163 if (ITEM_VALUE_TYPE_STR != item->value_type && ITEM_VALUE_TYPE_TEXT != item->value_type &&
2164 ITEM_VALUE_TYPE_LOG != item->value_type)
2165 {
2166 *error = zbx_strdup(*error, "invalid value type");
2167 goto clean;
2168 }
2169
2170 if (SUCCEED == evaluate_LAST(value, item, parameters, ts, error))
2171 {
2172 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_SIZE_T, (zbx_fs_size_t)zbx_strlen_utf8(value));
2173 ret = SUCCEED;
2174 }
2175 clean:
2176 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
2177
2178 return ret;
2179 }
2180
2181 /******************************************************************************
2182 * *
2183 * Function: evaluate_FUZZYTIME *
2184 * *
2185 * Purpose: evaluate function 'fuzzytime' for the item *
2186 * *
2187 * Parameters: item - item (performance metric) *
2188 * parameter - number of seconds *
2189 * *
2190 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
2191 * FAIL - failed to evaluate function *
2192 * *
2193 ******************************************************************************/
evaluate_FUZZYTIME(char * value,DC_ITEM * item,const char * parameters,const zbx_timespec_t * ts,char ** error)2194 static int evaluate_FUZZYTIME(char *value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts,
2195 char **error)
2196 {
2197 const char *__function_name = "evaluate_FUZZYTIME";
2198
2199 int arg1, ret = FAIL;
2200 zbx_value_type_t arg1_type;
2201 zbx_history_record_t vc_value;
2202 zbx_uint64_t fuzlow, fuzhig;
2203
2204 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2205
2206 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
2207 {
2208 *error = zbx_strdup(*error, "invalid value type");
2209 goto out;
2210 }
2211
2212 if (1 < num_param(parameters))
2213 {
2214 *error = zbx_strdup(*error, "invalid number of parameters");
2215 goto out;
2216 }
2217
2218 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
2219 &arg1_type) || 0 >= arg1)
2220 {
2221 *error = zbx_strdup(*error, "invalid first parameter");
2222 goto out;
2223 }
2224
2225 if (ZBX_VALUE_SECONDS != arg1_type || ts->sec <= arg1)
2226 {
2227 *error = zbx_strdup(*error, "invalid argument type or value");
2228 goto out;
2229 }
2230
2231 if (SUCCEED != zbx_vc_get_value(item->itemid, item->value_type, ts, &vc_value))
2232 {
2233 *error = zbx_strdup(*error, "cannot get value from value cache");
2234 goto out;
2235 }
2236
2237 fuzlow = (int)(ts->sec - arg1);
2238 fuzhig = (int)(ts->sec + arg1);
2239
2240 if (ITEM_VALUE_TYPE_UINT64 == item->value_type)
2241 {
2242 if (vc_value.value.ui64 >= fuzlow && vc_value.value.ui64 <= fuzhig)
2243 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
2244 else
2245 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
2246 }
2247 else
2248 {
2249 if (vc_value.value.dbl >= fuzlow && vc_value.value.dbl <= fuzhig)
2250 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
2251 else
2252 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
2253 }
2254
2255 zbx_history_record_clear(&vc_value, item->value_type);
2256
2257 ret = SUCCEED;
2258 out:
2259 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
2260
2261 return ret;
2262 }
2263
2264 /******************************************************************************
2265 * *
2266 * Function: evaluate_BAND *
2267 * *
2268 * Purpose: evaluate logical bitwise function 'and' for the item *
2269 * *
2270 * Parameters: value - buffer of size MAX_BUFFER_LEN *
2271 * item - item (performance metric) *
2272 * parameters - up to 3 comma-separated fields: *
2273 * (1) same as the 1st parameter for function *
2274 * evaluate_LAST() (see documentation of *
2275 * trigger function last()), *
2276 * (2) mask to bitwise AND with (mandatory), *
2277 * (3) same as the 2nd parameter for function *
2278 * evaluate_LAST() (see documentation of *
2279 * trigger function last()). *
2280 * *
2281 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
2282 * FAIL - failed to evaluate function *
2283 * *
2284 ******************************************************************************/
evaluate_BAND(char * value,DC_ITEM * item,const char * parameters,const zbx_timespec_t * ts,char ** error)2285 static int evaluate_BAND(char *value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts,
2286 char **error)
2287 {
2288 const char *__function_name = "evaluate_BAND";
2289 char *last_parameters = NULL;
2290 int nparams, ret = FAIL;
2291 zbx_uint64_t last_uint64, mask;
2292
2293 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2294
2295 if (ITEM_VALUE_TYPE_UINT64 != item->value_type)
2296 {
2297 *error = zbx_strdup(*error, "invalid value type");
2298 goto clean;
2299 }
2300
2301 if (3 < (nparams = num_param(parameters)))
2302 {
2303 *error = zbx_strdup(*error, "invalid number of parameters");
2304 goto clean;
2305 }
2306
2307 if (SUCCEED != get_function_parameter_uint64(item->host.hostid, parameters, 2, &mask))
2308 {
2309 *error = zbx_strdup(*error, "invalid second parameter");
2310 goto clean;
2311 }
2312
2313 /* prepare the 1st and the 3rd parameter for passing to evaluate_LAST() */
2314 last_parameters = zbx_strdup(NULL, parameters);
2315 remove_param(last_parameters, 2);
2316
2317 if (SUCCEED == evaluate_LAST(value, item, last_parameters, ts, error))
2318 {
2319 ZBX_STR2UINT64(last_uint64, value);
2320 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_UI64, last_uint64 & (zbx_uint64_t)mask);
2321 ret = SUCCEED;
2322 }
2323
2324 zbx_free(last_parameters);
2325 clean:
2326 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
2327
2328 return ret;
2329 }
2330
2331 /******************************************************************************
2332 * *
2333 * Function: evaluate_FORECAST *
2334 * *
2335 * Purpose: evaluate function 'forecast' for the item *
2336 * *
2337 * Parameters: item - item (performance metric) *
2338 * parameters - number of seconds/values and time shift (optional)*
2339 * *
2340 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
2341 * FAIL - failed to evaluate function *
2342 * *
2343 ******************************************************************************/
evaluate_FORECAST(char * value,DC_ITEM * item,const char * parameters,const zbx_timespec_t * ts,char ** error)2344 static int evaluate_FORECAST(char *value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts,
2345 char **error)
2346 {
2347 const char *__function_name = "evaluate_FORECAST";
2348 char *fit_str = NULL, *mode_str = NULL;
2349 double *t = NULL, *x = NULL;
2350 int nparams, time, arg1, i, ret = FAIL, seconds = 0, nvalues = 0, time_shift = 0;
2351 zbx_value_type_t time_type, time_shift_type = ZBX_VALUE_SECONDS, arg1_type;
2352 unsigned int k = 0;
2353 zbx_vector_history_record_t values;
2354 zbx_timespec_t zero_time;
2355 zbx_fit_t fit;
2356 zbx_mode_t mode;
2357 zbx_timespec_t ts_end = *ts;
2358
2359 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2360
2361 zbx_history_record_vector_create(&values);
2362
2363 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
2364 {
2365 *error = zbx_strdup(*error, "invalid value type");
2366 goto out;
2367 }
2368
2369 if (3 > (nparams = num_param(parameters)) || nparams > 5)
2370 {
2371 *error = zbx_strdup(*error, "invalid number of parameters");
2372 goto out;
2373 }
2374
2375 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
2376 &arg1_type) || 0 >= arg1)
2377 {
2378 *error = zbx_strdup(*error, "invalid first parameter");
2379 goto out;
2380 }
2381
2382 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL, &time_shift,
2383 &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type || 0 > time_shift)
2384 {
2385 *error = zbx_strdup(*error, "invalid second parameter");
2386 goto out;
2387 }
2388
2389 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 3, ZBX_PARAM_MANDATORY, &time,
2390 &time_type) || ZBX_VALUE_SECONDS != time_type)
2391 {
2392 *error = zbx_strdup(*error, "invalid third parameter");
2393 goto out;
2394 }
2395
2396 if (4 <= nparams)
2397 {
2398 if (SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 4, &fit_str) ||
2399 SUCCEED != zbx_fit_code(fit_str, &fit, &k, error))
2400 {
2401 *error = zbx_strdup(*error, "invalid fourth parameter");
2402 goto out;
2403 }
2404 }
2405 else
2406 {
2407 fit = FIT_LINEAR;
2408 }
2409
2410 if (5 == nparams)
2411 {
2412 if (SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 5, &mode_str) ||
2413 SUCCEED != zbx_mode_code(mode_str, &mode, error))
2414 {
2415 *error = zbx_strdup(*error, "invalid fifth parameter");
2416 goto out;
2417 }
2418 }
2419 else
2420 {
2421 mode = MODE_VALUE;
2422 }
2423
2424 switch (arg1_type)
2425 {
2426 case ZBX_VALUE_SECONDS:
2427 seconds = arg1;
2428 break;
2429 case ZBX_VALUE_NVALUES:
2430 nvalues = arg1;
2431 break;
2432 default:
2433 THIS_SHOULD_NEVER_HAPPEN;
2434 }
2435
2436 ts_end.sec -= time_shift;
2437
2438 if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
2439 {
2440 *error = zbx_strdup(*error, "cannot get values from value cache");
2441 goto out;
2442 }
2443
2444 if (0 < values.values_num)
2445 {
2446 t = (double *)zbx_malloc(t, values.values_num * sizeof(double));
2447 x = (double *)zbx_malloc(x, values.values_num * sizeof(double));
2448
2449 zero_time.sec = values.values[values.values_num - 1].timestamp.sec;
2450 zero_time.ns = values.values[values.values_num - 1].timestamp.ns;
2451
2452 if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
2453 {
2454 for (i = 0; i < values.values_num; i++)
2455 {
2456 t[i] = values.values[i].timestamp.sec - zero_time.sec + 1.0e-9 *
2457 (values.values[i].timestamp.ns - zero_time.ns + 1);
2458 x[i] = values.values[i].value.dbl;
2459 }
2460 }
2461 else
2462 {
2463 for (i = 0; i < values.values_num; i++)
2464 {
2465 t[i] = values.values[i].timestamp.sec - zero_time.sec + 1.0e-9 *
2466 (values.values[i].timestamp.ns - zero_time.ns + 1);
2467 x[i] = values.values[i].value.ui64;
2468 }
2469 }
2470
2471 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_DBL, zbx_forecast(t, x, values.values_num,
2472 ts->sec - zero_time.sec - 1.0e-9 * (zero_time.ns + 1), time, fit, k, mode));
2473 }
2474 else
2475 {
2476 zabbix_log(LOG_LEVEL_DEBUG, "no data available");
2477 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_DBL, ZBX_MATH_ERROR);
2478 }
2479
2480 ret = SUCCEED;
2481 out:
2482 zbx_history_record_vector_destroy(&values, item->value_type);
2483
2484 zbx_free(fit_str);
2485 zbx_free(mode_str);
2486
2487 zbx_free(t);
2488 zbx_free(x);
2489
2490 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
2491
2492 return ret;
2493 }
2494
2495 /******************************************************************************
2496 * *
2497 * Function: evaluate_TIMELEFT *
2498 * *
2499 * Purpose: evaluate function 'timeleft' for the item *
2500 * *
2501 * Parameters: item - item (performance metric) *
2502 * parameters - number of seconds/values and time shift (optional)*
2503 * *
2504 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
2505 * FAIL - failed to evaluate function *
2506 * *
2507 ******************************************************************************/
evaluate_TIMELEFT(char * value,DC_ITEM * item,const char * parameters,const zbx_timespec_t * ts,char ** error)2508 static int evaluate_TIMELEFT(char *value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts,
2509 char **error)
2510 {
2511 const char *__function_name = "evaluate_TIMELEFT";
2512 char *fit_str = NULL;
2513 double *t = NULL, *x = NULL, threshold;
2514 int nparams, arg1, i, ret = FAIL, seconds = 0, nvalues = 0, time_shift = 0;
2515 zbx_value_type_t arg1_type, time_shift_type = ZBX_VALUE_SECONDS;
2516 unsigned k = 0;
2517 zbx_vector_history_record_t values;
2518 zbx_timespec_t zero_time;
2519 zbx_fit_t fit;
2520 zbx_timespec_t ts_end = *ts;
2521
2522 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2523
2524 zbx_history_record_vector_create(&values);
2525
2526 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
2527 {
2528 *error = zbx_strdup(*error, "invalid value type");
2529 goto out;
2530 }
2531
2532 if (3 > (nparams = num_param(parameters)) || nparams > 4)
2533 {
2534 *error = zbx_strdup(*error, "invalid number of parameters");
2535 goto out;
2536 }
2537
2538 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
2539 &arg1_type) || 0 >= arg1)
2540 {
2541 *error = zbx_strdup(*error, "invalid first parameter");
2542 goto out;
2543 }
2544
2545 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL, &time_shift,
2546 &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type || 0 > time_shift)
2547 {
2548 *error = zbx_strdup(*error, "invalid second parameter");
2549 goto out;
2550 }
2551
2552 if (SUCCEED != get_function_parameter_float(item->host.hostid, parameters, 3, ZBX_FLAG_DOUBLE_SUFFIX,
2553 &threshold))
2554 {
2555 *error = zbx_strdup(*error, "invalid third parameter");
2556 goto out;
2557 }
2558
2559 if (4 == nparams)
2560 {
2561 if (SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 4, &fit_str) ||
2562 SUCCEED != zbx_fit_code(fit_str, &fit, &k, error))
2563 {
2564 *error = zbx_strdup(*error, "invalid fourth parameter");
2565 goto out;
2566 }
2567 }
2568 else
2569 {
2570 fit = FIT_LINEAR;
2571 }
2572
2573 if ((FIT_EXPONENTIAL == fit || FIT_POWER == fit) && 0.0 >= threshold)
2574 {
2575 *error = zbx_strdup(*error, "exponential and power functions are always positive");
2576 goto out;
2577 }
2578
2579 switch (arg1_type)
2580 {
2581 case ZBX_VALUE_SECONDS:
2582 seconds = arg1;
2583 break;
2584 case ZBX_VALUE_NVALUES:
2585 nvalues = arg1;
2586 break;
2587 default:
2588 THIS_SHOULD_NEVER_HAPPEN;
2589 }
2590
2591 ts_end.sec -= time_shift;
2592
2593 if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
2594 {
2595 *error = zbx_strdup(*error, "cannot get values from value cache");
2596 goto out;
2597 }
2598
2599 if (0 < values.values_num)
2600 {
2601 t = (double *)zbx_malloc(t, values.values_num * sizeof(double));
2602 x = (double *)zbx_malloc(x, values.values_num * sizeof(double));
2603
2604 zero_time.sec = values.values[values.values_num - 1].timestamp.sec;
2605 zero_time.ns = values.values[values.values_num - 1].timestamp.ns;
2606
2607 if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
2608 {
2609 for (i = 0; i < values.values_num; i++)
2610 {
2611 t[i] = values.values[i].timestamp.sec - zero_time.sec + 1.0e-9 *
2612 (values.values[i].timestamp.ns - zero_time.ns + 1);
2613 x[i] = values.values[i].value.dbl;
2614 }
2615 }
2616 else
2617 {
2618 for (i = 0; i < values.values_num; i++)
2619 {
2620 t[i] = values.values[i].timestamp.sec - zero_time.sec + 1.0e-9 *
2621 (values.values[i].timestamp.ns - zero_time.ns + 1);
2622 x[i] = values.values[i].value.ui64;
2623 }
2624 }
2625
2626 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_DBL, zbx_timeleft(t, x, values.values_num,
2627 ts->sec - zero_time.sec - 1.0e-9 * (zero_time.ns + 1), threshold, fit, k));
2628 }
2629 else
2630 {
2631 zabbix_log(LOG_LEVEL_DEBUG, "no data available");
2632 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_DBL, ZBX_MATH_ERROR);
2633 }
2634
2635 ret = SUCCEED;
2636 out:
2637 zbx_history_record_vector_destroy(&values, item->value_type);
2638
2639 zbx_free(fit_str);
2640
2641 zbx_free(t);
2642 zbx_free(x);
2643
2644 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
2645
2646 return ret;
2647 }
2648
2649 /******************************************************************************
2650 * *
2651 * Function: evaluate_function *
2652 * *
2653 * Purpose: evaluate function *
2654 * *
2655 * Parameters: item - item to calculate function for *
2656 * function - function (for example, 'max') *
2657 * parameter - parameter of the function *
2658 * *
2659 * Return value: SUCCEED - evaluated successfully, value contains its value *
2660 * FAIL - evaluation failed *
2661 * *
2662 ******************************************************************************/
evaluate_function(char * value,DC_ITEM * item,const char * function,const char * parameter,const zbx_timespec_t * ts,char ** error)2663 int evaluate_function(char *value, DC_ITEM *item, const char *function, const char *parameter,
2664 const zbx_timespec_t *ts, char **error)
2665 {
2666 const char *__function_name = "evaluate_function";
2667
2668 int ret;
2669 struct tm *tm = NULL;
2670
2671 zabbix_log(LOG_LEVEL_DEBUG, "In %s() function:'%s:%s.%s(%s)'", __function_name,
2672 item->host.host, item->key_orig, function, parameter);
2673
2674 *value = '\0';
2675
2676 if (0 == strcmp(function, "last"))
2677 {
2678 ret = evaluate_LAST(value, item, parameter, ts, error);
2679 }
2680 else if (0 == strcmp(function, "prev"))
2681 {
2682 ret = evaluate_LAST(value, item, "#2", ts, error);
2683 }
2684 else if (0 == strcmp(function, "min"))
2685 {
2686 ret = evaluate_MIN(value, item, parameter, ts, error);
2687 }
2688 else if (0 == strcmp(function, "max"))
2689 {
2690 ret = evaluate_MAX(value, item, parameter, ts, error);
2691 }
2692 else if (0 == strcmp(function, "avg"))
2693 {
2694 ret = evaluate_AVG(value, item, parameter, ts, error);
2695 }
2696 else if (0 == strcmp(function, "sum"))
2697 {
2698 ret = evaluate_SUM(value, item, parameter, ts, error);
2699 }
2700 else if (0 == strcmp(function, "percentile"))
2701 {
2702 ret = evaluate_PERCENTILE(value, item, parameter, ts, error);
2703 }
2704 else if (0 == strcmp(function, "count"))
2705 {
2706 ret = evaluate_COUNT(value, item, parameter, ts, error);
2707 }
2708 else if (0 == strcmp(function, "delta"))
2709 {
2710 ret = evaluate_DELTA(value, item, parameter, ts, error);
2711 }
2712 else if (0 == strcmp(function, "nodata"))
2713 {
2714 ret = evaluate_NODATA(value, item, parameter, error);
2715 }
2716 else if (0 == strcmp(function, "date"))
2717 {
2718 time_t now = ts->sec;
2719
2720 tm = localtime(&now);
2721 zbx_snprintf(value, MAX_BUFFER_LEN, "%.4d%.2d%.2d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
2722 ret = SUCCEED;
2723 }
2724 else if (0 == strcmp(function, "dayofweek"))
2725 {
2726 time_t now = ts->sec;
2727
2728 tm = localtime(&now);
2729 zbx_snprintf(value, MAX_BUFFER_LEN, "%d", 0 == tm->tm_wday ? 7 : tm->tm_wday);
2730 ret = SUCCEED;
2731 }
2732 else if (0 == strcmp(function, "dayofmonth"))
2733 {
2734 time_t now = ts->sec;
2735
2736 tm = localtime(&now);
2737 zbx_snprintf(value, MAX_BUFFER_LEN, "%d", tm->tm_mday);
2738 ret = SUCCEED;
2739 }
2740 else if (0 == strcmp(function, "time"))
2741 {
2742 time_t now = ts->sec;
2743
2744 tm = localtime(&now);
2745 zbx_snprintf(value, MAX_BUFFER_LEN, "%.2d%.2d%.2d", tm->tm_hour, tm->tm_min, tm->tm_sec);
2746 ret = SUCCEED;
2747 }
2748 else if (0 == strcmp(function, "abschange"))
2749 {
2750 ret = evaluate_ABSCHANGE(value, item, ts, error);
2751 }
2752 else if (0 == strcmp(function, "change"))
2753 {
2754 ret = evaluate_CHANGE(value, item, ts, error);
2755 }
2756 else if (0 == strcmp(function, "diff"))
2757 {
2758 ret = evaluate_DIFF(value, item, ts, error);
2759 }
2760 else if (0 == strcmp(function, "str") || 0 == strcmp(function, "regexp") || 0 == strcmp(function, "iregexp"))
2761 {
2762 ret = evaluate_STR(value, item, function, parameter, ts, error);
2763 }
2764 else if (0 == strcmp(function, "strlen"))
2765 {
2766 ret = evaluate_STRLEN(value, item, parameter, ts, error);
2767 }
2768 else if (0 == strcmp(function, "now"))
2769 {
2770 zbx_snprintf(value, MAX_BUFFER_LEN, "%d", ts->sec);
2771 ret = SUCCEED;
2772 }
2773 else if (0 == strcmp(function, "fuzzytime"))
2774 {
2775 ret = evaluate_FUZZYTIME(value, item, parameter, ts, error);
2776 }
2777 else if (0 == strcmp(function, "logeventid"))
2778 {
2779 ret = evaluate_LOGEVENTID(value, item, parameter, ts, error);
2780 }
2781 else if (0 == strcmp(function, "logseverity"))
2782 {
2783 ret = evaluate_LOGSEVERITY(value, item, ts, error);
2784 }
2785 else if (0 == strcmp(function, "logsource"))
2786 {
2787 ret = evaluate_LOGSOURCE(value, item, parameter, ts, error);
2788 }
2789 else if (0 == strcmp(function, "band"))
2790 {
2791 ret = evaluate_BAND(value, item, parameter, ts, error);
2792 }
2793 else if (0 == strcmp(function, "forecast"))
2794 {
2795 ret = evaluate_FORECAST(value, item, parameter, ts, error);
2796 }
2797 else if (0 == strcmp(function, "timeleft"))
2798 {
2799 ret = evaluate_TIMELEFT(value, item, parameter, ts, error);
2800 }
2801 else
2802 {
2803 *error = zbx_strdup(*error, "function is not supported");
2804 ret = FAIL;
2805 }
2806
2807 if (SUCCEED == ret)
2808 del_zeros(value);
2809
2810 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s value:'%s'", __function_name, zbx_result_string(ret), value);
2811
2812 return ret;
2813 }
2814
2815 /******************************************************************************
2816 * *
2817 * Function: add_value_suffix_uptime *
2818 * *
2819 * Purpose: Process suffix 'uptime' *
2820 * *
2821 * Parameters: value - value for adjusting *
2822 * max_len - max len of the value *
2823 * *
2824 ******************************************************************************/
add_value_suffix_uptime(char * value,size_t max_len)2825 static void add_value_suffix_uptime(char *value, size_t max_len)
2826 {
2827 const char *__function_name = "add_value_suffix_uptime";
2828
2829 double secs, days;
2830 size_t offset = 0;
2831 int hours, mins;
2832
2833 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2834
2835 if (0 > (secs = round(atof(value))))
2836 {
2837 offset += zbx_snprintf(value, max_len, "-");
2838 secs = -secs;
2839 }
2840
2841 days = floor(secs / SEC_PER_DAY);
2842 secs -= days * SEC_PER_DAY;
2843
2844 hours = (int)(secs / SEC_PER_HOUR);
2845 secs -= (double)hours * SEC_PER_HOUR;
2846
2847 mins = (int)(secs / SEC_PER_MIN);
2848 secs -= (double)mins * SEC_PER_MIN;
2849
2850 if (0 != days)
2851 {
2852 if (1 == days)
2853 offset += zbx_snprintf(value + offset, max_len - offset, ZBX_FS_DBL_EXT(0) " day, ", days);
2854 else
2855 offset += zbx_snprintf(value + offset, max_len - offset, ZBX_FS_DBL_EXT(0) " days, ", days);
2856 }
2857
2858 zbx_snprintf(value + offset, max_len - offset, "%02d:%02d:%02d", hours, mins, (int)secs);
2859
2860 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2861 }
2862
2863 /******************************************************************************
2864 * *
2865 * Function: add_value_suffix_s *
2866 * *
2867 * Purpose: Process suffix 's' *
2868 * *
2869 * Parameters: value - value for adjusting *
2870 * max_len - max len of the value *
2871 * *
2872 ******************************************************************************/
add_value_suffix_s(char * value,size_t max_len)2873 static void add_value_suffix_s(char *value, size_t max_len)
2874 {
2875 const char *__function_name = "add_value_suffix_s";
2876
2877 double secs, n;
2878 size_t offset = 0;
2879 int n_unit = 0;
2880
2881 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2882
2883 secs = atof(value);
2884
2885 if (0 == floor(fabs(secs) * 1000))
2886 {
2887 zbx_snprintf(value, max_len, "%s", (0 == secs ? "0s" : "< 1ms"));
2888 goto clean;
2889 }
2890
2891 if (0 > (secs = round(secs * 1000) / 1000))
2892 {
2893 offset += zbx_snprintf(value, max_len, "-");
2894 secs = -secs;
2895 }
2896 else
2897 *value = '\0';
2898
2899 if (0 != (n = floor(secs / SEC_PER_YEAR)))
2900 {
2901 offset += zbx_snprintf(value + offset, max_len - offset, ZBX_FS_DBL_EXT(0) "y ", n);
2902 secs -= n * SEC_PER_YEAR;
2903 if (0 == n_unit)
2904 n_unit = 4;
2905 }
2906
2907 if (0 != (n = floor(secs / SEC_PER_MONTH)))
2908 {
2909 offset += zbx_snprintf(value + offset, max_len - offset, "%dm ", (int)n);
2910 secs -= n * SEC_PER_MONTH;
2911 if (0 == n_unit)
2912 n_unit = 3;
2913 }
2914
2915 if (0 != (n = floor(secs / SEC_PER_DAY)))
2916 {
2917 offset += zbx_snprintf(value + offset, max_len - offset, "%dd ", (int)n);
2918 secs -= n * SEC_PER_DAY;
2919 if (0 == n_unit)
2920 n_unit = 2;
2921 }
2922
2923 if (4 > n_unit && 0 != (n = floor(secs / SEC_PER_HOUR)))
2924 {
2925 offset += zbx_snprintf(value + offset, max_len - offset, "%dh ", (int)n);
2926 secs -= n * SEC_PER_HOUR;
2927 if (0 == n_unit)
2928 n_unit = 1;
2929 }
2930
2931 if (3 > n_unit && 0 != (n = floor(secs / SEC_PER_MIN)))
2932 {
2933 offset += zbx_snprintf(value + offset, max_len - offset, "%dm ", (int)n);
2934 secs -= n * SEC_PER_MIN;
2935 }
2936
2937 if (2 > n_unit && 0 != (n = floor(secs)))
2938 {
2939 offset += zbx_snprintf(value + offset, max_len - offset, "%ds ", (int)n);
2940 secs -= n;
2941 }
2942
2943 if (1 > n_unit && 0 != (n = round(secs * 1000)))
2944 offset += zbx_snprintf(value + offset, max_len - offset, "%dms", (int)n);
2945
2946 if (0 != offset && ' ' == value[--offset])
2947 value[offset] = '\0';
2948 clean:
2949 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2950 }
2951
2952 /******************************************************************************
2953 * *
2954 * Function: is_blacklisted_unit *
2955 * *
2956 * Purpose: check if unit is blacklisted or not *
2957 * *
2958 * Parameters: unit - unit to check *
2959 * *
2960 * Return value: SUCCEED - unit blacklisted *
2961 * FAIL - unit is not blacklisted *
2962 * *
2963 ******************************************************************************/
is_blacklisted_unit(const char * unit)2964 static int is_blacklisted_unit(const char *unit)
2965 {
2966 const char *__function_name = "is_blacklisted_unit";
2967
2968 int ret;
2969
2970 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2971
2972 ret = str_in_list("%,ms,rpm,RPM", unit, ',');
2973
2974 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
2975
2976 return ret;
2977 }
2978
2979 /******************************************************************************
2980 * *
2981 * Function: add_value_units_no_kmgt *
2982 * *
2983 * Purpose: add only units to the value *
2984 * *
2985 * Parameters: value - value for adjusting *
2986 * max_len - max len of the value *
2987 * units - units (bps, b, B, etc) *
2988 * *
2989 ******************************************************************************/
add_value_units_no_kmgt(char * value,size_t max_len,const char * units)2990 static void add_value_units_no_kmgt(char *value, size_t max_len, const char *units)
2991 {
2992 const char *__function_name = "add_value_units_no_kmgt";
2993
2994 const char *minus = "";
2995 char tmp[64];
2996 double value_double;
2997
2998 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2999
3000 if (0 > (value_double = atof(value)))
3001 {
3002 minus = "-";
3003 value_double = -value_double;
3004 }
3005
3006 if (SUCCEED != zbx_double_compare(round(value_double), value_double))
3007 {
3008 zbx_snprintf(tmp, sizeof(tmp), ZBX_FS_DBL_EXT(2), value_double);
3009 del_zeros(tmp);
3010 }
3011 else
3012 zbx_snprintf(tmp, sizeof(tmp), ZBX_FS_DBL_EXT(0), value_double);
3013
3014 zbx_snprintf(value, max_len, "%s%s %s", minus, tmp, units);
3015
3016 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3017 }
3018
3019 /******************************************************************************
3020 * *
3021 * Function: add_value_units_with_kmgt *
3022 * *
3023 * Purpose: add units with K,M,G,T prefix to the value *
3024 * *
3025 * Parameters: value - value for adjusting *
3026 * max_len - max len of the value *
3027 * units - units (bps, b, B, etc) *
3028 * *
3029 ******************************************************************************/
add_value_units_with_kmgt(char * value,size_t max_len,const char * units)3030 static void add_value_units_with_kmgt(char *value, size_t max_len, const char *units)
3031 {
3032 const char *__function_name = "add_value_units_with_kmgt";
3033
3034 const char *minus = "";
3035 char kmgt[8];
3036 char tmp[64];
3037 double base;
3038 double value_double;
3039
3040 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3041
3042 if (0 > (value_double = atof(value)))
3043 {
3044 minus = "-";
3045 value_double = -value_double;
3046 }
3047
3048 base = (0 == strcmp(units, "B") || 0 == strcmp(units, "Bps") ? 1024 : 1000);
3049
3050 if (value_double < base)
3051 {
3052 strscpy(kmgt, "");
3053 }
3054 else if (value_double < base * base)
3055 {
3056 strscpy(kmgt, "K");
3057 value_double /= base;
3058 }
3059 else if (value_double < base * base * base)
3060 {
3061 strscpy(kmgt, "M");
3062 value_double /= base * base;
3063 }
3064 else if (value_double < base * base * base * base)
3065 {
3066 strscpy(kmgt, "G");
3067 value_double /= base * base * base;
3068 }
3069 else
3070 {
3071 strscpy(kmgt, "T");
3072 value_double /= base * base * base * base;
3073 }
3074
3075 if (SUCCEED != zbx_double_compare(round(value_double), value_double))
3076 {
3077 zbx_snprintf(tmp, sizeof(tmp), ZBX_FS_DBL_EXT(2), value_double);
3078 del_zeros(tmp);
3079 }
3080 else
3081 zbx_snprintf(tmp, sizeof(tmp), ZBX_FS_DBL_EXT(0), value_double);
3082
3083 zbx_snprintf(value, max_len, "%s%s %s%s", minus, tmp, kmgt, units);
3084
3085 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3086 }
3087
3088 /******************************************************************************
3089 * *
3090 * Function: add_value_suffix *
3091 * *
3092 * Purpose: Add suffix for value *
3093 * *
3094 * Parameters: value - value for replacing *
3095 * *
3096 * Return value: SUCCEED - suffix added successfully, value contains new value*
3097 * FAIL - adding failed, value contains old value *
3098 * *
3099 ******************************************************************************/
add_value_suffix(char * value,size_t max_len,const char * units,unsigned char value_type)3100 static void add_value_suffix(char *value, size_t max_len, const char *units, unsigned char value_type)
3101 {
3102 const char *__function_name = "add_value_suffix";
3103
3104 struct tm *local_time;
3105 time_t time;
3106
3107 zabbix_log(LOG_LEVEL_DEBUG, "In %s() value:'%s' units:'%s' value_type:%d",
3108 __function_name, value, units, (int)value_type);
3109
3110 switch (value_type)
3111 {
3112 case ITEM_VALUE_TYPE_UINT64:
3113 if (0 == strcmp(units, "unixtime"))
3114 {
3115 time = (time_t)atoi(value);
3116 local_time = localtime(&time);
3117 strftime(value, max_len, "%Y.%m.%d %H:%M:%S", local_time);
3118 break;
3119 }
3120 ZBX_FALLTHROUGH;
3121 case ITEM_VALUE_TYPE_FLOAT:
3122 if (0 == strcmp(units, "s"))
3123 add_value_suffix_s(value, max_len);
3124 else if (0 == strcmp(units, "uptime"))
3125 add_value_suffix_uptime(value, max_len);
3126 else if ('!' == *units)
3127 add_value_units_no_kmgt(value, max_len, (const char *)(units + 1));
3128 else if (SUCCEED == is_blacklisted_unit(units))
3129 add_value_units_no_kmgt(value, max_len, units);
3130 else if ('\0' != *units)
3131 add_value_units_with_kmgt(value, max_len, units);
3132 break;
3133 default:
3134 ;
3135 }
3136
3137 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() value:'%s'", __function_name, value);
3138 }
3139
3140 /******************************************************************************
3141 * *
3142 * Function: replace_value_by_map *
3143 * *
3144 * Purpose: replace value by mapping value *
3145 * *
3146 * Parameters: value - value for replacing *
3147 * valuemapid - index of value map *
3148 * *
3149 * Return value: SUCCEED - evaluated successfully, value contains new value *
3150 * FAIL - evaluation failed, value contains old value *
3151 * *
3152 ******************************************************************************/
replace_value_by_map(char * value,size_t max_len,zbx_uint64_t valuemapid)3153 static int replace_value_by_map(char *value, size_t max_len, zbx_uint64_t valuemapid)
3154 {
3155 const char *__function_name = "replace_value_by_map";
3156
3157 DB_RESULT result;
3158 DB_ROW row;
3159 char *value_esc, *value_tmp;
3160 int ret = FAIL;
3161
3162 zabbix_log(LOG_LEVEL_DEBUG, "In %s() value:'%s' valuemapid:" ZBX_FS_UI64, __function_name, value, valuemapid);
3163
3164 if (0 == valuemapid)
3165 goto clean;
3166
3167 value_esc = DBdyn_escape_string(value);
3168 result = DBselect(
3169 "select newvalue"
3170 " from mappings"
3171 " where valuemapid=" ZBX_FS_UI64
3172 " and value" ZBX_SQL_STRCMP,
3173 valuemapid, ZBX_SQL_STRVAL_EQ(value_esc));
3174 zbx_free(value_esc);
3175
3176 if (NULL != (row = DBfetch(result)) && FAIL == DBis_null(row[0]))
3177 {
3178 del_zeros(row[0]);
3179
3180 value_tmp = zbx_dsprintf(NULL, "%s (%s)", row[0], value);
3181 zbx_strlcpy_utf8(value, value_tmp, max_len);
3182 zbx_free(value_tmp);
3183
3184 ret = SUCCEED;
3185 }
3186 DBfree_result(result);
3187 clean:
3188 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() value:'%s'", __function_name, value);
3189
3190 return ret;
3191 }
3192
3193 /******************************************************************************
3194 * *
3195 * Function: zbx_format_value *
3196 * *
3197 * Purpose: replace value by value mapping or by units *
3198 * *
3199 * Parameters: value - [IN/OUT] value for replacing *
3200 * valuemapid - [IN] identificator of value map *
3201 * units - [IN] units *
3202 * value_type - [IN] value type; ITEM_VALUE_TYPE_* *
3203 * *
3204 ******************************************************************************/
zbx_format_value(char * value,size_t max_len,zbx_uint64_t valuemapid,const char * units,unsigned char value_type)3205 void zbx_format_value(char *value, size_t max_len, zbx_uint64_t valuemapid,
3206 const char *units, unsigned char value_type)
3207 {
3208 const char *__function_name = "zbx_format_value";
3209
3210 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3211
3212 switch (value_type)
3213 {
3214 case ITEM_VALUE_TYPE_STR:
3215 replace_value_by_map(value, max_len, valuemapid);
3216 break;
3217 case ITEM_VALUE_TYPE_FLOAT:
3218 del_zeros(value);
3219 ZBX_FALLTHROUGH;
3220 case ITEM_VALUE_TYPE_UINT64:
3221 if (SUCCEED != replace_value_by_map(value, max_len, valuemapid))
3222 add_value_suffix(value, max_len, units, value_type);
3223 break;
3224 default:
3225 ;
3226 }
3227
3228 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3229 }
3230
3231 /******************************************************************************
3232 * *
3233 * Function: evaluate_macro_function *
3234 * *
3235 * Purpose: evaluate function used in simple macro *
3236 * *
3237 * Parameters: result - [OUT] evaluation result (if it's successful) *
3238 * host - [IN] host the key belongs to *
3239 * key - [IN] item's key *
3240 * (for example, 'system.cpu.load[,avg1]') *
3241 * function - [IN] function name (for example, 'max') *
3242 * parameter - [IN] function parameter list *
3243 * *
3244 * Return value: SUCCEED - evaluated successfully, value contains its value *
3245 * FAIL - evaluation failed *
3246 * *
3247 * Comments: used for evaluation of notification macros *
3248 * *
3249 ******************************************************************************/
evaluate_macro_function(char ** result,const char * host,const char * key,const char * function,const char * parameter)3250 int evaluate_macro_function(char **result, const char *host, const char *key, const char *function,
3251 const char *parameter)
3252 {
3253 const char *__function_name = "evaluate_macro_function";
3254
3255 zbx_host_key_t host_key = {(char *)host, (char *)key};
3256 DC_ITEM item;
3257 char value[MAX_BUFFER_LEN], *error = NULL;
3258 int ret, errcode;
3259 zbx_timespec_t ts;
3260
3261 zabbix_log(LOG_LEVEL_DEBUG, "In %s() function:'%s:%s.%s(%s)'", __function_name, host, key, function, parameter);
3262
3263 DCconfig_get_items_by_keys(&item, &host_key, &errcode, 1);
3264
3265 zbx_timespec(&ts);
3266
3267 if (SUCCEED != errcode || SUCCEED != evaluate_function(value, &item, function, parameter, &ts, &error))
3268 {
3269 zabbix_log(LOG_LEVEL_DEBUG, "cannot evaluate function \"%s:%s.%s(%s)\": %s", host, key, function,
3270 parameter, (NULL == error ? "item does not exist" : error));
3271 ret = FAIL;
3272 }
3273 else
3274 {
3275 if (SUCCEED == str_in_list("last,prev", function, ','))
3276 {
3277 zbx_format_value(value, MAX_BUFFER_LEN, item.valuemapid, item.units, item.value_type);
3278 }
3279 else if (SUCCEED == str_in_list("abschange,avg,change,delta,max,min,percentile,sum,forecast", function,
3280 ','))
3281 {
3282 switch (item.value_type)
3283 {
3284 case ITEM_VALUE_TYPE_FLOAT:
3285 case ITEM_VALUE_TYPE_UINT64:
3286 add_value_suffix(value, MAX_BUFFER_LEN, item.units, item.value_type);
3287 break;
3288 default:
3289 ;
3290 }
3291 }
3292 else if (SUCCEED == str_in_list("timeleft", function, ','))
3293 {
3294 add_value_suffix(value, MAX_BUFFER_LEN, "s", ITEM_VALUE_TYPE_FLOAT);
3295 }
3296
3297 *result = zbx_strdup(NULL, value);
3298 ret = SUCCEED;
3299 }
3300
3301 DCconfig_clean_items(&item, &errcode, 1);
3302 zbx_free(error);
3303
3304 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s value:'%s'", __function_name, zbx_result_string(ret), value);
3305
3306 return ret;
3307 }
3308
3309 /******************************************************************************
3310 * *
3311 * Function: evaluatable_for_notsupported *
3312 * *
3313 * Purpose: check is function to be evaluated for NOTSUPPORTED items *
3314 * *
3315 * Parameters: fn - [IN] function name *
3316 * *
3317 * Return value: SUCCEED - do evaluate the function for NOTSUPPORTED items *
3318 * FAIL - don't evaluate the function for NOTSUPPORTED items *
3319 * *
3320 ******************************************************************************/
evaluatable_for_notsupported(const char * fn)3321 int evaluatable_for_notsupported(const char *fn)
3322 {
3323 /* functions date(), dayofmonth(), dayofweek(), now(), time() and nodata() are exceptions, */
3324 /* they should be evaluated for NOTSUPPORTED items, too */
3325
3326 if ('n' != *fn && 'd' != *fn && 't' != *fn)
3327 return FAIL;
3328
3329 if (('n' == *fn) && (0 == strcmp(fn, "nodata") || 0 == strcmp(fn, "now")))
3330 return SUCCEED;
3331
3332 if (('d' == *fn) && (0 == strcmp(fn, "dayofweek") || 0 == strcmp(fn, "dayofmonth") || 0 == strcmp(fn, "date")))
3333 return SUCCEED;
3334
3335 if (0 == strcmp(fn, "time"))
3336 return SUCCEED;
3337
3338 return FAIL;
3339 }
3340