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 			&parameter, 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 			&parameter, 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 			&parameter, 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(&regexps);
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(&regexps, 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(&regexps, 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(&regexps);
310 	zbx_vector_ptr_destroy(&regexps);
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(&regexps);
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(&regexps, 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(&regexps, 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(&regexps);
400 	zbx_vector_ptr_destroy(&regexps);
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(&regexps);
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(&regexps, 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, &regexps);
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, &regexps);
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, &regexps);
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, &regexps);
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(&regexps);
855 	zbx_vector_ptr_destroy(&regexps);
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(&regexps);
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(&regexps, 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, &regexps,
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, &regexps,
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(&regexps);
2126 	zbx_vector_ptr_destroy(&regexps);
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