Example #1
0
/******************************************************************************
 *                                                                            *
 * Purpose: evaluate "and"                                                    *
 *                                                                            *
 *      0.0 and Unknown  -> 0.0                                               *
 *  Unknown and 0.0      -> 0.0                                               *
 *      1.0 and Unknown  -> Unknown                                           *
 *  Unknown and 1.0      -> Unknown                                           *
 *  Unknown and Unknown  -> Unknown                                           *
 *                                                                            *
 ******************************************************************************/
static double	evaluate_term2(int *unknown_idx)
{
	double	result, operand;
	int	res_idx = -9, oper_idx = -10;	/* set invalid values to catch errors */

	if (ZBX_INFINITY == (result = evaluate_term3(&res_idx)))
		return ZBX_INFINITY;

	if (ZBX_UNKNOWN == result)
		*unknown_idx = res_idx;

	/* if evaluate_term3() returns ZBX_UNKNOWN then continue as with regular number */

	while ('a' == ptr[0] && 'n' == ptr[1] && 'd' == ptr[2] && SUCCEED == is_operator_delimiter(ptr[3]))
	{
		ptr += 3;

		if (ZBX_INFINITY == (operand = evaluate_term3(&oper_idx)))
			return ZBX_INFINITY;

		if (ZBX_UNKNOWN == result)
		{
			if (ZBX_UNKNOWN == operand)				/* Unknown and Unknown */
			{
				*unknown_idx = oper_idx;
				res_idx = oper_idx;
				result = ZBX_UNKNOWN;
			}
			else if (SUCCEED == zbx_double_compare(operand, 0.0))	/* Unknown and 0 */
			{
				result = 0.0;
			}
			else							/* Unknown and 1 */
				*unknown_idx = res_idx;
		}
		else if (ZBX_UNKNOWN == operand)
		{
			if (SUCCEED == zbx_double_compare(result, 0.0))		/* 0 and Unknown */
			{
				result = 0.0;
			}
			else							/* 1 and Unknown */
			{
				*unknown_idx = oper_idx;
				res_idx = oper_idx;
				result = ZBX_UNKNOWN;
			}
		}
		else
		{
			result = (SUCCEED != zbx_double_compare(result, 0.0) &&
					SUCCEED != zbx_double_compare(operand, 0.0));
		}
	}

	return result;
}
Example #2
0
/******************************************************************************
 *                                                                            *
 * Purpose: evaluate "=" and "<>"                                             *
 *                                                                            *
 *      0.0 = Unknown  ->  Unknown                                            *
 *      1.2 = Unknown  ->  Unknown                                            *
 *  Unknown = Unknown  ->  Unknown                                            *
 *     0.0 <> Unknown  ->  Unknown                                            *
 *     1.2 <> Unknown  ->  Unknown                                            *
 * Unknown <> Unknown  ->  Unknown                                            *
 *                                                                            *
 ******************************************************************************/
static double	evaluate_term3(int *unknown_idx)
{
	char	op;
	double	result, operand;
	int	res_idx = -7, oper_idx = -8;	/* set invalid values to catch errors */

	if (ZBX_INFINITY == (result = evaluate_term4(&res_idx)))
		return ZBX_INFINITY;

	if (ZBX_UNKNOWN == result)
		*unknown_idx = res_idx;

	/* if evaluate_term4() returns ZBX_UNKNOWN then continue as with regular number */

	while (1)
	{
		if ('=' == *ptr)
		{
			op = *ptr++;
		}
		else if ('<' == ptr[0] && '>' == ptr[1])
		{
			op = '#';
			ptr += 2;
		}
		else
			break;

		/* even if 1st operand is Unknown we evaluate 2nd operand to catch fatal error if any occurrs */

		if (ZBX_INFINITY == (operand = evaluate_term4(&oper_idx)))
			return ZBX_INFINITY;

		if (ZBX_UNKNOWN == operand)		/* (anything) = Unknown, (anything) <> Unknown */
		{
			*unknown_idx = oper_idx;
			res_idx = oper_idx;
			result = ZBX_UNKNOWN;
		}
		else if (ZBX_UNKNOWN == result)		/* Unknown = known, Unknown <> known */
		{
			*unknown_idx = res_idx;
		}
		else if ('=' == op)
		{
			result = (SUCCEED == zbx_double_compare(result, operand));
		}
		else
			result = (SUCCEED != zbx_double_compare(result, operand));
	}

	return result;
}
Example #3
0
/******************************************************************************
 *                                                                            *
 * Function: filter_evaluate_expression                                       *
 *                                                                            *
 * Purpose: check if the lld data passes filter evaluation by custom          *
 *          expression                                                        *
 *                                                                            *
 * Parameters: filter - [IN] the lld filter                                   *
 *             jp_row - [IN] the lld data row                                 *
 *                                                                            *
 * Return value: SUCCEED - the lld data passed filter evaluation              *
 *               FAIL    - otherwise                                          *
 *                                                                            *
 * Comments: 1) replace {item_condition} references with action condition     *
 *              evaluation results (1 or 0)                                   *
 *           2) call evaluate() to calculate the final result                 *
 *                                                                            *
 ******************************************************************************/
static int	filter_evaluate_expression(lld_filter_t *filter, struct zbx_json_parse *jp_row)
{
	const char	*__function_name = "filter_evaluate_expression";

	int		i, ret = FAIL, id_len;
	char		*expression, id[ZBX_MAX_UINT64_LEN + 2], *p, error[256];
	double		result;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s() expression:%s", __function_name, filter->expression);

	expression = zbx_strdup(NULL, filter->expression);

	for (i = 0; i < filter->conditions.values_num; i++)
	{
		char		*value = NULL;
		size_t		value_alloc = 0;
		lld_condition_t	*condition = (lld_condition_t *)filter->conditions.values[i];

		if (SUCCEED == (ret = zbx_json_value_by_name_dyn(jp_row, condition->macro, &value, &value_alloc)))
		{
			ret = (ZBX_REGEXP_MATCH == regexp_match_ex(&condition->regexps, value, condition->regexp,
					ZBX_CASE_SENSITIVE) ? SUCCEED : FAIL);
		}

		zbx_free(value);

		zbx_snprintf(id, sizeof(id), "{" ZBX_FS_UI64 "}", condition->id);

		id_len = strlen(id);
		p = expression;

		while (NULL != (p = strstr(p, id)))
		{
			*p = (SUCCEED == ret ? '1' : '0');
			memset(p + 1, ' ', id_len - 1);
			p += id_len;
		}
	}

	if (SUCCEED == evaluate(&result, expression, error, sizeof(error)))
		ret = (SUCCEED != zbx_double_compare(result, 0) ? SUCCEED : FAIL);

	zbx_free(expression);

	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));

	return ret;
}
Example #4
0
/******************************************************************************
 *                                                                            *
 * Purpose: evaluate "not"                                                    *
 *                                                                            *
 * not 0.0     ->  1.0                                                        *
 * not 1.2     ->  0.0                                                        *
 * not Unknown ->  Unknown                                                    *
 *                                                                            *
 ******************************************************************************/
static double	evaluate_term7(int *unknown_idx)
{
	double	result;

	while (' ' == *ptr || '\r' == *ptr || '\n' == *ptr || '\t' == *ptr)
		ptr++;

	if ('n' == ptr[0] && 'o' == ptr[1] && 't' == ptr[2] && SUCCEED == is_operator_delimiter(ptr[3]))
	{
		ptr += 3;

		if (ZBX_UNKNOWN == (result = evaluate_term8(unknown_idx)) || ZBX_INFINITY == result)
			return result;

		result = (SUCCEED == zbx_double_compare(result, 0.0) ? 1.0 : 0.0);
	}
	else
		result = evaluate_term8(unknown_idx);

	return result;
}
Example #5
0
/******************************************************************************
 *                                                                            *
 * Function: variant_compare_dbl                                              *
 *                                                                            *
 * Purpose: compares two variant values when at least one is double and the   *
 *          other is double or uint64                                         *
 *                                                                            *
 ******************************************************************************/
static int	variant_compare_dbl(const zbx_variant_t *value1, const zbx_variant_t *value2)
{
	double	value1_dbl, value2_dbl;

	switch (value1->type)
	{
		case ZBX_VARIANT_DBL:
			value1_dbl = value1->data.dbl;
			break;
		case ZBX_VARIANT_UI64:
			value1_dbl = value1->data.ui64;
			break;
		default:
			THIS_SHOULD_NEVER_HAPPEN;
			exit(EXIT_FAILURE);
	}

	switch (value2->type)
	{
		case ZBX_VARIANT_DBL:
			value2_dbl = value2->data.dbl;
			break;
		case ZBX_VARIANT_UI64:
			value2_dbl = value2->data.ui64;
			break;
		default:
			THIS_SHOULD_NEVER_HAPPEN;
			exit(EXIT_FAILURE);
	}

	if (SUCCEED == zbx_double_compare(value1_dbl, value2_dbl))
		return 0;

	ZBX_RETURN_IF_NOT_EQUAL(value1_dbl, value2_dbl);
	THIS_SHOULD_NEVER_HAPPEN;
	exit(EXIT_FAILURE);
}
Example #6
0
/******************************************************************************
 *                                                                            *
 * Purpose: evaluate "or"                                                     *
 *                                                                            *
 *      1.0 or Unknown  -> 1.0                                                *
 *  Unknown or 1.0      -> 1.0                                                *
 *      0.0 or Unknown  -> Unknown                                            *
 *  Unknown or 0.0      -> Unknown                                            *
 *  Unknown or Unknown  -> Unknown                                            *
 *                                                                            *
 ******************************************************************************/
static double	evaluate_term1(int *unknown_idx)
{
	double	result, operand;
	int	res_idx = -11, oper_idx = -12;	/* set invalid values to catch errors */

	level++;

	if (32 < level)
	{
		zbx_strlcpy(buffer, "Cannot evaluate expression: nesting level is too deep.", max_buffer_len);
		return ZBX_INFINITY;
	}

	if (ZBX_INFINITY == (result = evaluate_term2(&res_idx)))
		return ZBX_INFINITY;

	if (ZBX_UNKNOWN == result)
		*unknown_idx = res_idx;

	/* if evaluate_term2() returns ZBX_UNKNOWN then continue as with regular number */

	while ('o' == ptr[0] && 'r' == ptr[1] && SUCCEED == is_operator_delimiter(ptr[2]))
	{
		ptr += 2;

		if (ZBX_INFINITY == (operand = evaluate_term2(&oper_idx)))
			return ZBX_INFINITY;

		if (ZBX_UNKNOWN == result)
		{
			if (ZBX_UNKNOWN == operand)				/* Unknown or Unknown */
			{
				*unknown_idx = oper_idx;
				res_idx = oper_idx;
				result = ZBX_UNKNOWN;
			}
			else if (SUCCEED != zbx_double_compare(operand, 0.0))	/* Unknown or 1 */
			{
				result = 1;
			}
			else							/* Unknown or 0 */
				*unknown_idx = res_idx;
		}
		else if (ZBX_UNKNOWN == operand)
		{
			if (SUCCEED != zbx_double_compare(result, 0.0))		/* 1 or Unknown */
			{
				result = 1;
			}
			else							/* 0 or Unknown */
			{
				*unknown_idx = oper_idx;
				res_idx = oper_idx;
				result = ZBX_UNKNOWN;
			}
		}
		else
		{
			result = (SUCCEED != zbx_double_compare(result, 0.0) ||
					SUCCEED != zbx_double_compare(operand, 0.0));
		}
	}

	level--;

	return result;
}
Example #7
0
/******************************************************************************
 *                                                                            *
 * Purpose: evaluate "*" and "/"                                              *
 *                                                                            *
 *     0.0 * Unknown  ->  Unknown (yes, not 0 as we don't want to lose        *
 *                        Unknown in arithmetic operations)                   *
 *     1.2 * Unknown  ->  Unknown                                             *
 *     0.0 / 1.2      ->  0.0                                                 *
 *     1.2 / 0.0      ->  error (ZBX_INFINITY)                                *
 * Unknown / 0.0      ->  error (ZBX_INFINITY)                                *
 * Unknown / 1.2      ->  Unknown                                             *
 * Unknown / Unknown  ->  Unknown                                             *
 *     0.0 / Unknown  ->  Unknown                                             *
 *     1.2 / Unknown  ->  Unknown                                             *
 *                                                                            *
 ******************************************************************************/
static double	evaluate_term6(int *unknown_idx)
{
	char	op;
	double	result, operand;
	int	res_idx = -1, oper_idx = -2;	/* set invalid values to catch errors */

	if (ZBX_INFINITY == (result = evaluate_term7(&res_idx)))
		return ZBX_INFINITY;

	if (ZBX_UNKNOWN == result)
		*unknown_idx = res_idx;

	/* if evaluate_term7() returns ZBX_UNKNOWN then continue as with regular number */

	while ('*' == *ptr || '/' == *ptr)
	{
		op = *ptr++;

		/* 'ZBX_UNKNOWN' in multiplication and division produces 'ZBX_UNKNOWN'. */
		/* Even if 1st operand is Unknown we evaluate 2nd operand too to catch fatal errors in it. */

		if (ZBX_INFINITY == (operand = evaluate_term7(&oper_idx)))
			return ZBX_INFINITY;

		if ('*' == op)
		{
			if (ZBX_UNKNOWN == operand)		/* (anything) * Unknown */
			{
				*unknown_idx = oper_idx;
				res_idx = oper_idx;
				result = ZBX_UNKNOWN;
			}
			else if (ZBX_UNKNOWN == result)		/* Unknown * known */
			{
				*unknown_idx = res_idx;
			}
			else
				result *= operand;
		}
		else
		{
			/* catch division by 0 even if 1st operand is Unknown */

			if (ZBX_UNKNOWN != operand && SUCCEED == zbx_double_compare(operand, 0.0))
			{
				zbx_strlcpy(buffer, "Cannot evaluate expression: division by zero.", max_buffer_len);
				return ZBX_INFINITY;
			}

			if (ZBX_UNKNOWN == operand)		/* (anything) / Unknown */
			{
				*unknown_idx = oper_idx;
				res_idx = oper_idx;
				result = ZBX_UNKNOWN;
			}
			else if (ZBX_UNKNOWN == result)		/* Unknown / known */
			{
				*unknown_idx = res_idx;
			}
			else
				result /= operand;
		}
	}

	return result;
}