diff options
author | Dmitrijs Goloscapovs <dmitrijs.goloscapovs@zabbix.com> | 2022-11-09 14:44:50 +0300 |
---|---|---|
committer | Dmitrijs Goloscapovs <dmitrijs.goloscapovs@zabbix.com> | 2022-11-09 14:44:50 +0300 |
commit | fb831f3178b898a0db64d2e7f017aae825d18533 (patch) | |
tree | f8220825cfdf8456d1325f85c68b4c07066e4531 | |
parent | 689a5591eb20a54bf5c1114a9147bc8e6451d43c (diff) | |
parent | 1873100855685ae887206895a1e119b93d9905fe (diff) |
........S. [ZBX-21616] fixed error due to non-existent macros in custom expressions
Merge in ZBX/zabbix from feature/ZBX-21616-6.3 to master
* commit '1873100855685ae887206895a1e119b93d9905fe':
........S. [ZBX-21616] renamed define
........S. [ZBX-21616] fixed function description comment
........S. [ZBX-21616] got rid of ZBX_FALLTROUGH
.......... [ZBX-21616] code style fix
........S. [ZBX-21616] fixed offseet calculation when replacing condition ids with values
........S. [ZBX-21616] added more optimizations to LLD filter processing
........S. [ZBX-21616] optimized
.......... [ZBX-21616] added changelog
.......... [ZBX-21616] added changelog
........S. [ZBX-21616] refactored and reimplemented parsing logics
........S. [ZBX-21616] fixed error due to non-existent macros in custom expressions
-rw-r--r-- | ChangeLog.d/bugfix/ZBX-21616 | 1 | ||||
-rw-r--r-- | include/zbxdbhigh.h | 8 | ||||
-rw-r--r-- | src/libs/zbxcacheconfig/dbconfig.c | 16 | ||||
-rw-r--r-- | src/libs/zbxdbupgrade/dbupgrade_3010.c | 4 | ||||
-rw-r--r-- | src/libs/zbxdbwrap/template_item.c | 4 | ||||
-rw-r--r-- | src/zabbix_server/actions.c | 16 | ||||
-rw-r--r-- | src/zabbix_server/escalator/escalator.c | 8 | ||||
-rw-r--r-- | src/zabbix_server/lld/lld.c | 284 | ||||
-rw-r--r-- | src/zabbix_server/service/service_manager.c | 6 |
9 files changed, 188 insertions, 159 deletions
diff --git a/ChangeLog.d/bugfix/ZBX-21616 b/ChangeLog.d/bugfix/ZBX-21616 new file mode 100644 index 00000000000..fcabe90b876 --- /dev/null +++ b/ChangeLog.d/bugfix/ZBX-21616 @@ -0,0 +1 @@ +........S. [ZBX-21616] fixed error due to non-existent macros in custom expressions (dgoloscapov, wiper) diff --git a/include/zbxdbhigh.h b/include/zbxdbhigh.h index 03067c163fd..f10862719ac 100644 --- a/include/zbxdbhigh.h +++ b/include/zbxdbhigh.h @@ -786,10 +786,10 @@ char *zbx_get_proxy_protocol_version_str(const struct zbx_json_parse *jp); int zbx_get_proxy_protocol_version_int(const char *version_str); /* condition evaluation types */ -#define ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR 0 -#define ZBX_ACTION_CONDITION_EVAL_TYPE_AND 1 -#define ZBX_ACTION_CONDITION_EVAL_TYPE_OR 2 -#define ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION 3 +#define ZBX_CONDITION_EVAL_TYPE_AND_OR 0 +#define ZBX_CONDITION_EVAL_TYPE_AND 1 +#define ZBX_CONDITION_EVAL_TYPE_OR 2 +#define ZBX_CONDITION_EVAL_TYPE_EXPRESSION 3 /* condition types */ #define ZBX_CONDITION_TYPE_HOST_GROUP 0 diff --git a/src/libs/zbxcacheconfig/dbconfig.c b/src/libs/zbxcacheconfig/dbconfig.c index 73098113be7..0785566d4e6 100644 --- a/src/libs/zbxcacheconfig/dbconfig.c +++ b/src/libs/zbxcacheconfig/dbconfig.c @@ -4448,7 +4448,7 @@ static void DCsync_action_conditions(zbx_dbsync_t *sync) zbx_vector_ptr_append(&action->conditions, condition); } - if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == action->evaltype) + if (ZBX_CONDITION_EVAL_TYPE_AND_OR == action->evaltype) zbx_vector_ptr_append(&actions, action); } @@ -4468,7 +4468,7 @@ static void DCsync_action_conditions(zbx_dbsync_t *sync) { zbx_vector_ptr_remove_noorder(&action->conditions, index); - if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == action->evaltype) + if (ZBX_CONDITION_EVAL_TYPE_AND_OR == action->evaltype) zbx_vector_ptr_append(&actions, action); } } @@ -4488,7 +4488,7 @@ static void DCsync_action_conditions(zbx_dbsync_t *sync) { action = (zbx_dc_action_t *)actions.values[i]; - if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == action->evaltype) + if (ZBX_CONDITION_EVAL_TYPE_AND_OR == action->evaltype) zbx_vector_ptr_sort(&action->conditions, dc_compare_action_conditions_by_type); } @@ -4755,7 +4755,7 @@ static void DCsync_corr_conditions(zbx_dbsync_t *sync) zbx_vector_ptr_append(&correlation->conditions, condition); /* sort the conditions later */ - if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == correlation->evaltype) + if (ZBX_CONDITION_EVAL_TYPE_AND_OR == correlation->evaltype) zbx_vector_ptr_append(&correlations, correlation); } @@ -4777,7 +4777,7 @@ static void DCsync_corr_conditions(zbx_dbsync_t *sync) ZBX_DEFAULT_PTR_COMPARE_FUNC))) { /* sort the conditions later */ - if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == correlation->evaltype) + if (ZBX_CONDITION_EVAL_TYPE_AND_OR == correlation->evaltype) zbx_vector_ptr_append(&correlations, correlation); zbx_vector_ptr_remove_noorder(&correlation->conditions, index); @@ -13349,7 +13349,7 @@ static char *dc_correlation_formula_dup(const zbx_dc_correlation_t *dc_correlati const zbx_dc_corr_condition_t *dc_condition; zbx_uint64_t last_id; - if (ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION == dc_correlation->evaltype || 0 == + if (ZBX_CONDITION_EVAL_TYPE_EXPRESSION == dc_correlation->evaltype || 0 == dc_correlation->conditions.values_num) { return zbx_strdup(NULL, dc_correlation->formula); @@ -13359,10 +13359,10 @@ static char *dc_correlation_formula_dup(const zbx_dc_correlation_t *dc_correlati switch (dc_correlation->evaltype) { - case ZBX_ACTION_CONDITION_EVAL_TYPE_OR: + case ZBX_CONDITION_EVAL_TYPE_OR: op = " or"; break; - case ZBX_ACTION_CONDITION_EVAL_TYPE_AND: + case ZBX_CONDITION_EVAL_TYPE_AND: op = " and"; break; } diff --git a/src/libs/zbxdbupgrade/dbupgrade_3010.c b/src/libs/zbxdbupgrade/dbupgrade_3010.c index 5b27f3904da..8110eff3759 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_3010.c +++ b/src/libs/zbxdbupgrade/dbupgrade_3010.c @@ -465,7 +465,7 @@ static int DBpatch_3010024_validate_action(zbx_uint64_t actionid, int eventsourc DB_RESULT result; int conditiontype, ret = ZBX_3010024_ACTION_DISABLE, value; - /* evaltype: 0 - ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR, 1 - ZBX_ACTION_CONDITION_EVAL_TYPE_AND */ + /* evaltype: 0 - ZBX_CONDITION_EVAL_TYPE_AND_OR, 1 - ZBX_CONDITION_EVAL_TYPE_AND */ if (evaltype != 0 && evaltype != 1) return ret; @@ -1045,7 +1045,7 @@ static int DBpatch_3010026(void) index = conditionids.values_num; DBpatch_3010026_get_conditionids(actionid, row[4], eventsource, &conditionids); - /* evaltype: 3 - ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION */ + /* evaltype: 3 - ZBX_CONDITION_EVAL_TYPE_EXPRESSION */ if (3 != evaltype) continue; diff --git a/src/libs/zbxdbwrap/template_item.c b/src/libs/zbxdbwrap/template_item.c index 37db1c92c0a..d399cd3c040 100644 --- a/src/libs/zbxdbwrap/template_item.c +++ b/src/libs/zbxdbwrap/template_item.c @@ -722,7 +722,7 @@ static void update_template_lld_rule_formulas(zbx_vector_ptr_t *items, zbx_vecto { zbx_template_item_t *item = (zbx_template_item_t *)items->values[i]; - if (0 == (ZBX_FLAG_DISCOVERY_RULE & item->flags) || ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION != + if (0 == (ZBX_FLAG_DISCOVERY_RULE & item->flags) || ZBX_CONDITION_EVAL_TYPE_EXPRESSION != item->evaltype) { continue; @@ -2297,7 +2297,7 @@ static void save_template_lld_overrides(zbx_vector_ptr_t *overrides, zbx_hashset override_conditionid, (int)override_condition->operator, override_condition->macro, override_condition->value); - if (ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION == override->evaltype) + if (ZBX_CONDITION_EVAL_TYPE_EXPRESSION == override->evaltype) { update_template_lld_formula(&override->formula, override_condition->override_conditionid, override_conditionid); diff --git a/src/zabbix_server/actions.c b/src/zabbix_server/actions.c index 0fda368e4eb..a021bca13f3 100644 --- a/src/zabbix_server/actions.c +++ b/src/zabbix_server/actions.c @@ -2587,14 +2587,14 @@ static int check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " eventsource:%d", __func__, action->actionid, (int)action->eventsource); - if (ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) + if (ZBX_CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) expression = zbx_strdup(expression, action->formula); for (i = 0; i < action->conditions.values_num; i++) { condition = (zbx_condition_t *)action->conditions.values[i]; - if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == action->evaltype && + if (ZBX_CONDITION_EVAL_TYPE_AND_OR == action->evaltype && old_type == condition->conditiontype && SUCCEED == ret) { continue; /* short-circuit true OR condition block to the next AND condition */ @@ -2609,7 +2609,7 @@ static int check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t switch (action->evaltype) { - case ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR: + case ZBX_CONDITION_EVAL_TYPE_AND_OR: if (old_type == condition->conditiontype) /* assume conditions are sorted by type */ { if (SUCCEED == condition_result) @@ -2625,7 +2625,7 @@ static int check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t } break; - case ZBX_ACTION_CONDITION_EVAL_TYPE_AND: + case ZBX_CONDITION_EVAL_TYPE_AND: if (FAIL == condition_result) /* break if any AND condition is FALSE */ { ret = FAIL; @@ -2633,7 +2633,7 @@ static int check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t } break; - case ZBX_ACTION_CONDITION_EVAL_TYPE_OR: + case ZBX_CONDITION_EVAL_TYPE_OR: if (SUCCEED == condition_result) /* break if any OR condition is TRUE */ { ret = SUCCEED; @@ -2642,7 +2642,7 @@ static int check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t ret = FAIL; break; - case ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION: + case ZBX_CONDITION_EVAL_TYPE_EXPRESSION: zbx_snprintf(tmp, sizeof(tmp), "{" ZBX_FS_UI64 "}", condition->conditionid); id_len = strlen(tmp); @@ -2659,7 +2659,7 @@ static int check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t } } - if (ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) + if (ZBX_CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) { if (SUCCEED == zbx_evaluate(&eval_result, expression, error, sizeof(error), NULL)) ret = (SUCCEED != zbx_double_compare(eval_result, 0) ? SUCCEED : FAIL); @@ -3053,7 +3053,7 @@ static void prepare_actions_conditions_eval(zbx_vector_ptr_t *actions, zbx_hashs } else { - if (ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) + if (ZBX_CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) { char search[ZBX_MAX_UINT64_LEN + 2]; char replace[ZBX_MAX_UINT64_LEN + 2]; diff --git a/src/zabbix_server/escalator/escalator.c b/src/zabbix_server/escalator/escalator.c index 96ad3046ac7..18f3b69e7aa 100644 --- a/src/zabbix_server/escalator/escalator.c +++ b/src/zabbix_server/escalator/escalator.c @@ -1799,7 +1799,7 @@ static int check_operation_conditions(const ZBX_DB_EVENT *event, zbx_uint64_t op DB_ROW row; zbx_condition_t condition; - int ret = SUCCEED; /* SUCCEED required for ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR */ + int ret = SUCCEED; /* SUCCEED required for ZBX_CONDITION_EVAL_TYPE_AND_OR */ int cond, exit = 0; unsigned char old_type = 0xff; @@ -1825,7 +1825,7 @@ static int check_operation_conditions(const ZBX_DB_EVENT *event, zbx_uint64_t op switch (evaltype) { - case ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR: + case ZBX_CONDITION_EVAL_TYPE_AND_OR: if (old_type == condition.conditiontype) /* OR conditions */ { if (SUCCEED == check_action_condition(event, &condition)) @@ -1841,7 +1841,7 @@ static int check_operation_conditions(const ZBX_DB_EVENT *event, zbx_uint64_t op } old_type = condition.conditiontype; break; - case ZBX_ACTION_CONDITION_EVAL_TYPE_AND: + case ZBX_CONDITION_EVAL_TYPE_AND: cond = check_action_condition(event, &condition); /* Break if any of AND conditions is FALSE */ if (cond == FAIL) @@ -1852,7 +1852,7 @@ static int check_operation_conditions(const ZBX_DB_EVENT *event, zbx_uint64_t op else ret = SUCCEED; break; - case ZBX_ACTION_CONDITION_EVAL_TYPE_OR: + case ZBX_CONDITION_EVAL_TYPE_OR: cond = check_action_condition(event, &condition); /* Break if any of OR conditions is TRUE */ if (cond == SUCCEED) diff --git a/src/zabbix_server/lld/lld.c b/src/zabbix_server/lld/lld.c index 3af8d4a0397..8e9681ac00a 100644 --- a/src/zabbix_server/lld/lld.c +++ b/src/zabbix_server/lld/lld.c @@ -116,7 +116,7 @@ static void lld_filter_init(lld_filter_t *filter) { zbx_vector_ptr_create(&filter->conditions); filter->expression = NULL; - filter->evaltype = ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR; + filter->evaltype = ZBX_CONDITION_EVAL_TYPE_AND_OR; } /****************************************************************************** @@ -195,7 +195,7 @@ static int lld_filter_load(lld_filter_t *filter, zbx_uint64_t lld_ruleid, const ; DBfree_result(result); - if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == filter->evaltype) + if (ZBX_CONDITION_EVAL_TYPE_AND_OR == filter->evaltype) zbx_vector_ptr_sort(&filter->conditions, lld_condition_compare_by_macro); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); @@ -210,6 +210,7 @@ static int lld_filter_load(lld_filter_t *filter, zbx_uint64_t lld_ruleid, const * Parameters: jp_row - [IN] the lld data row * * lld_macro_paths - [IN] use json path to extract from jp_row * * condition - [IN] the lld filter condition * + * result - [OUT] the result of evaluation * * info - [OUT] the warning description * * * * Return value: SUCCEED - the lld data passed filter evaluation * @@ -217,41 +218,54 @@ static int lld_filter_load(lld_filter_t *filter, zbx_uint64_t lld_ruleid, const * * ******************************************************************************/ static int filter_condition_match(const struct zbx_json_parse *jp_row, const zbx_vector_ptr_t *lld_macro_paths, - const lld_condition_t *condition, char **info) + const lld_condition_t *condition, int *result, char **info) { char *value = NULL; - int ret; + int ret = SUCCEED; - if (SUCCEED == (ret = zbx_lld_macro_value_by_name(jp_row, lld_macro_paths, condition->macro, &value))) + if (SUCCEED == zbx_lld_macro_value_by_name(jp_row, lld_macro_paths, condition->macro, &value)) { if (ZBX_CONDITION_OPERATOR_NOT_EXIST == condition->op) { - ret = FAIL; + *result = 0; } - else if (ZBX_CONDITION_OPERATOR_EXIST != condition->op) + else if (ZBX_CONDITION_OPERATOR_EXIST == condition->op) + { + *result = 1; + } + else { switch (regexp_match_ex(&condition->regexps, value, condition->regexp, ZBX_CASE_SENSITIVE)) { case ZBX_REGEXP_MATCH: - ret = (ZBX_CONDITION_OPERATOR_REGEXP == condition->op ? SUCCEED : FAIL); + *result = (ZBX_CONDITION_OPERATOR_REGEXP == condition->op ? 1 : 0); break; case ZBX_REGEXP_NO_MATCH: - ret = (ZBX_CONDITION_OPERATOR_NOT_REGEXP == condition->op ? SUCCEED : FAIL); + *result = (ZBX_CONDITION_OPERATOR_NOT_REGEXP == condition->op ? 1 : 0); + break; break; default: + *info = zbx_strdcatf(*info, "Cannot accurately apply filter: invalid regular " + "expression \"%s\".\n", condition->regexp); ret = FAIL; } } } - else if (ZBX_CONDITION_OPERATOR_NOT_EXIST == condition->op) - { - ret = SUCCEED; - } - else if (ZBX_CONDITION_OPERATOR_EXIST != condition->op) + else { - *info = zbx_strdcatf(*info, - "Cannot accurately apply filter: no value received for macro \"%s\".\n", - condition->macro); + switch (condition->op) + { + case ZBX_CONDITION_OPERATOR_NOT_EXIST: + *result = 1; + break; + case ZBX_CONDITION_OPERATOR_EXIST: + *result = 0; + break; + default: + *info = zbx_strdcatf(*info, "Cannot accurately apply filter: no value received for " + "macro \"%s\".\n", condition->macro); + ret = FAIL; + } } zbx_free(value); @@ -259,120 +273,104 @@ static int filter_condition_match(const struct zbx_json_parse *jp_row, const zbx return ret; } -/****************************************************************************** - * * - * Purpose: check if the lld data passes filter evaluation by and/or rule * - * * - * Parameters: filter - [IN] the lld filter * - * jp_row - [IN] the lld data row * - * lld_macro_paths - [IN] use json path to extract from jp_row * - * info - [OUT] the warning description * - * * - * Return value: SUCCEED - the lld data passed filter evaluation * - * FAIL - otherwise * - * * - ******************************************************************************/ -static int filter_evaluate_and_or(const lld_filter_t *filter, const struct zbx_json_parse *jp_row, +/**************************************************************************************** + * * + * Purpose: check if the lld data passes filter evaluation by and/or/andor rules * + * * + * Parameters: filter - [IN] the lld filter * + * jp_row - [IN] the lld data row * + * lld_macro_paths - [IN] use json path to extract from jp_row * + * info - [OUT] the warning description * + * * + * Return value: SUCCEED - the lld data passed filter evaluation * + * FAIL - otherwise * + * * + ****************************************************************************************/ +static int filter_evaluate_and_or_andor(const lld_filter_t *filter, const struct zbx_json_parse *jp_row, const zbx_vector_ptr_t *lld_macro_paths, char **info) { - int i, ret = SUCCEED; - char *lastmacro = NULL; + int i, ret = SUCCEED, error_num = 0, res; + double result; + char *lastmacro = NULL; + lld_condition_t *condition; + char *ops[] = {NULL, "and", "or"}, error[256], *expression = NULL, *errmsg = NULL; + size_t expression_alloc = 0, expression_offset = 0; + zbx_vector_ptr_t errmsgs; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); + zbx_vector_ptr_create(&errmsgs); + for (i = 0; i < filter->conditions.values_num; i++) { - int rc; - const lld_condition_t *condition = (lld_condition_t *)filter->conditions.values[i]; + condition = (lld_condition_t *)filter->conditions.values[i]; - rc = filter_condition_match(jp_row, lld_macro_paths, condition, info); - /* check if a new condition group has started */ - if (NULL == lastmacro || 0 != strcmp(lastmacro, condition->macro)) + switch (filter->evaltype) { - /* if any of condition groups are false the evaluation returns false */ - if (FAIL == ret) + case ZBX_CONDITION_EVAL_TYPE_AND_OR: + if (NULL == lastmacro) + { + zbx_chrcpy_alloc(&expression, &expression_alloc, &expression_offset, '('); + } + else if (0 != strcmp(lastmacro, condition->macro)) + { + zbx_strcpy_alloc(&expression, &expression_alloc, &expression_offset, ") and "); + } + else + zbx_strcpy_alloc(&expression, &expression_alloc, &expression_offset, " or "); + + lastmacro = condition->macro; break; + case ZBX_CONDITION_EVAL_TYPE_AND: + case ZBX_CONDITION_EVAL_TYPE_OR: + if (0 != i) + { + zbx_chrcpy_alloc(&expression, &expression_alloc, &expression_offset, ' '); + zbx_strcpy_alloc(&expression, &expression_alloc, &expression_offset, + ops[filter->evaltype]); + zbx_chrcpy_alloc(&expression, &expression_alloc, &expression_offset, ' '); + } + break; + default: + *info = zbx_strdcatf(*info, "Cannot accurately apply filter: invalid condition " + "type \"%d\".\n", filter->evaltype); + goto out; + } - ret = rc; + if (SUCCEED == (ret = filter_condition_match(jp_row, lld_macro_paths, condition, &res, &errmsg))) + { + zbx_snprintf_alloc(&expression, &expression_alloc, &expression_offset, "%d", res); } else { - if (SUCCEED == rc) - ret = rc; + zbx_snprintf_alloc(&expression, &expression_alloc, &expression_offset, ZBX_UNKNOWN_STR "%d", + error_num++); + zbx_vector_ptr_append(&errmsgs, errmsg); + errmsg = NULL; } - lastmacro = condition->macro; - } - - zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); - - return ret; -} - -/****************************************************************************** - * * - * Purpose: check if the lld data passes filter evaluation by and rule * - * * - * Parameters: filter - [IN] the lld filter * - * jp_row - [IN] the lld data row * - * lld_macro_paths - [IN] use json path to extract from jp_row * - * info - [OUT] the warning description * - * * - * Return value: SUCCEED - the lld data passed filter evaluation * - * FAIL - otherwise * - * * - ******************************************************************************/ -static int filter_evaluate_and(const lld_filter_t *filter, const struct zbx_json_parse *jp_row, - const zbx_vector_ptr_t *lld_macro_paths, char **info) -{ - int i, ret = SUCCEED; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - - for (i = 0; i < filter->conditions.values_num; i++) - { - /* if any of conditions are false the evaluation returns false */ - if (SUCCEED != (ret = filter_condition_match(jp_row, lld_macro_paths, - (lld_condition_t *)filter->conditions.values[i], info))) + if (filter->conditions.values_num == i + 1) { - break; + if (ZBX_CONDITION_EVAL_TYPE_AND_OR == filter->evaltype) + zbx_chrcpy_alloc(&expression, &expression_alloc, &expression_offset, ')'); + + expression_offset++; } } - zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); - - return ret; -} - -/****************************************************************************** - * * - * Purpose: check if the lld data passes filter evaluation by or rule * - * * - * Parameters: filter - [IN] the lld filter * - * jp_row - [IN] the lld data row * - * lld_macro_paths - [IN] use json path to extract from jp_row * - * info - [OUT] the warning description * - * * - * Return value: SUCCEED - the lld data passed filter evaluation * - * FAIL - otherwise * - * * - ******************************************************************************/ -static int filter_evaluate_or(const lld_filter_t *filter, const struct zbx_json_parse *jp_row, - const zbx_vector_ptr_t *lld_macro_paths, char **info) -{ - int i, ret = SUCCEED; - - zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); - - for (i = 0; i < filter->conditions.values_num; i++) + if (SUCCEED == zbx_evaluate(&result, expression, error, sizeof(error), &errmsgs)) { - /* if any of conditions are true the evaluation returns true */ - if (SUCCEED == (ret = filter_condition_match(jp_row, lld_macro_paths, - (lld_condition_t *)filter->conditions.values[i], info))) - { - break; - } + ret = (SUCCEED != zbx_double_compare(result, 0) ? SUCCEED : FAIL); + } + else + { + *info = zbx_strdcat(*info, error); + ret = FAIL; } +out: + zbx_free(expression); + zbx_vector_ptr_clear_ext(&errmsgs, zbx_ptr_free); + zbx_vector_ptr_destroy(&errmsgs); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); @@ -400,37 +398,66 @@ static int filter_evaluate_or(const lld_filter_t *filter, const struct zbx_json_ static int filter_evaluate_expression(const lld_filter_t *filter, const struct zbx_json_parse *jp_row, const zbx_vector_ptr_t *lld_macro_paths, char **info) { - int i, ret = FAIL, id_len; - char *expression, id[ZBX_MAX_UINT64_LEN + 2], *p, error[256]; - double result; + int i, ret = FAIL, res, error_num = 0; + char *expression = NULL, id[ZBX_MAX_UINT64_LEN + 2], *p, error[256], value[16], + *errmsg = NULL; + double result; + zbx_vector_ptr_t errmsgs; + size_t expression_alloc = 0, expression_offset = 0, id_len, value_len; zabbix_log(LOG_LEVEL_DEBUG, "In %s() expression:%s", __func__, filter->expression); - expression = zbx_strdup(NULL, filter->expression); + zbx_strcpy_alloc(&expression, &expression_alloc, &expression_offset, filter->expression); + + /* include trailing zero */ + expression_offset++; + + zbx_vector_ptr_create(&errmsgs); for (i = 0; i < filter->conditions.values_num; i++) { const lld_condition_t *condition = (lld_condition_t *)filter->conditions.values[i]; - ret = filter_condition_match(jp_row, lld_macro_paths, condition, info); + if (SUCCEED == (ret = filter_condition_match(jp_row, lld_macro_paths, condition, &res, &errmsg))) + { + zbx_snprintf(value, sizeof(value), "%d", res); + } + else + { + zbx_snprintf(value, sizeof(value), ZBX_UNKNOWN_STR "%d", error_num++); + zbx_vector_ptr_append(&errmsgs, errmsg); + errmsg = NULL; + } zbx_snprintf(id, sizeof(id), "{" ZBX_FS_UI64 "}", condition->id); + value_len = strlen(value); id_len = strlen(id); - p = expression; - while (NULL != (p = strstr(p, id))) + for (p = strstr(expression, id); NULL != p; p = strstr(p, id)) { - *p = (SUCCEED == ret ? '1' : '0'); - memset(p + 1, ' ', id_len - 1); - p += id_len; + size_t id_pos = p - expression; + + zbx_replace_mem_dyn(&expression, &expression_alloc, &expression_offset, id_pos, id_len, + value, value_len); + + p = expression + id_pos + value_len; } } - if (SUCCEED == zbx_evaluate(&result, expression, error, sizeof(error), NULL)) + if (SUCCEED == zbx_evaluate(&result, expression, error, sizeof(error), &errmsgs)) + { ret = (SUCCEED != zbx_double_compare(result, 0) ? SUCCEED : FAIL); + } + else + { + *info = zbx_strdcat(*info, error); + ret = FAIL; + } zbx_free(expression); + zbx_vector_ptr_clear_ext(&errmsgs, zbx_ptr_free); + zbx_vector_ptr_destroy(&errmsgs); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); @@ -453,15 +480,16 @@ static int filter_evaluate_expression(const lld_filter_t *filter, const struct z static int filter_evaluate(const lld_filter_t *filter, const struct zbx_json_parse *jp_row, const zbx_vector_ptr_t *lld_macro_paths, char **info) { + if (0 == filter->conditions.values_num) + return SUCCEED; + switch (filter->evaltype) { - case ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR: - return filter_evaluate_and_or(filter, jp_row, lld_macro_paths, info); - case ZBX_ACTION_CONDITION_EVAL_TYPE_AND: - return filter_evaluate_and(filter, jp_row, lld_macro_paths, info); - case ZBX_ACTION_CONDITION_EVAL_TYPE_OR: - return filter_evaluate_or(filter, jp_row, lld_macro_paths, info); - case ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION: + case ZBX_CONDITION_EVAL_TYPE_AND_OR: + case ZBX_CONDITION_EVAL_TYPE_AND: + case ZBX_CONDITION_EVAL_TYPE_OR: + return filter_evaluate_and_or_andor(filter, jp_row, lld_macro_paths, info); + case ZBX_CONDITION_EVAL_TYPE_EXPRESSION: return filter_evaluate_expression(filter, jp_row, lld_macro_paths, info); } @@ -512,7 +540,7 @@ static int lld_override_conditions_load(zbx_vector_ptr_t *overrides, const zbx_v { override = (lld_override_t *)overrides->values[i]; - if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == override->filter.evaltype) + if (ZBX_CONDITION_EVAL_TYPE_AND_OR == override->filter.evaltype) zbx_vector_ptr_sort(&override->filter.conditions, lld_condition_compare_by_macro); } diff --git a/src/zabbix_server/service/service_manager.c b/src/zabbix_server/service/service_manager.c index 3b578168c86..103dd1e40ee 100644 --- a/src/zabbix_server/service/service_manager.c +++ b/src/zabbix_server/service/service_manager.c @@ -966,14 +966,14 @@ static void update_action_formula(zbx_service_action_t *action) zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64, __func__, action->actionid); - if (0 == action->conditions.values_num || ZBX_ACTION_CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) + if (0 == action->conditions.values_num || ZBX_CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype) goto out; for (i = 0; i < action->conditions.values_num; i++) { condition = (zbx_service_action_condition_t *)action->conditions.values[i]; - if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == action->evaltype) + if (ZBX_CONDITION_EVAL_TYPE_AND_OR == action->evaltype) { if (last_type != condition->conditiontype) { @@ -1000,7 +1000,7 @@ static void update_action_formula(zbx_service_action_t *action) last_type = condition->conditiontype; } - if (ZBX_ACTION_CONDITION_EVAL_TYPE_AND_OR == action->evaltype) + if (ZBX_CONDITION_EVAL_TYPE_AND_OR == action->evaltype) zbx_chrcpy_alloc(&formula, &formula_alloc, &formula_offset, ')'); zbx_free(action->formula); |