Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndris Zeila <andris.zeila@zabbix.com>2021-01-27 01:50:34 +0300
committerAndris Zeila <andris.zeila@zabbix.com>2021-01-27 01:55:43 +0300
commitffc0868ad96ffef7cbe1156c25f65d36388a6bfe (patch)
treeb03857921b67494a119b65a60b95e6a7ea66a0bc
parent477f6cf0ec943b422d571b256d4fb45160bb7744 (diff)
........S. [ZBXNEXT-6451] updated trigger expression processing to use new expression syntax
(trigger recalculation, macro resolving, etc - all places that parsed trigger expression to extract functionids).
-rw-r--r--include/common.h2
-rw-r--r--include/db.h16
-rw-r--r--include/dbcache.h10
-rw-r--r--include/zbxeval.h18
-rw-r--r--include/zbxserver.h1
-rw-r--r--src/libs/zbxcommon/misc.c2
-rw-r--r--src/libs/zbxcommon/str.c53
-rw-r--r--src/libs/zbxdbcache/dbcache.c11
-rw-r--r--src/libs/zbxdbcache/dbconfig.c413
-rw-r--r--src/libs/zbxdbcache/dbconfig.h15
-rw-r--r--src/libs/zbxdbcache/dbconfig_maintenance.c11
-rw-r--r--src/libs/zbxdbcache/dbsync.c24
-rw-r--r--src/libs/zbxdbhigh/event.c21
-rw-r--r--src/libs/zbxdbhigh/trigger.c384
-rw-r--r--src/libs/zbxeval/execute.c3
-rw-r--r--src/libs/zbxeval/misc.c688
-rw-r--r--src/libs/zbxeval/parse.c490
-rw-r--r--src/libs/zbxserver/evalfunc.c17
-rw-r--r--src/libs/zbxserver/evalfunc.h2
-rw-r--r--src/libs/zbxserver/expression.c714
-rw-r--r--src/libs/zbxsysinfo/sysinfo.c2
-rw-r--r--src/libs/zbxtrends/trends.c7
-rw-r--r--src/zabbix_server/escalator/escalator.c7
-rw-r--r--src/zabbix_server/events.c35
-rw-r--r--src/zabbix_server/poller/checks_calculated.c2
-rw-r--r--tests/libs/zbxdbcache/dc_function_calculate_nextcheck.c25
-rw-r--r--tests/libs/zbxdbcache/dc_function_calculate_nextcheck.yaml72
-rw-r--r--tests/libs/zbxeval/zbx_eval_execute.yaml8
-rw-r--r--ui/include/defines.inc.php2
29 files changed, 1825 insertions, 1230 deletions
diff --git a/include/common.h b/include/common.h
index a501e46711d..13beaf1acd8 100644
--- a/include/common.h
+++ b/include/common.h
@@ -1684,6 +1684,6 @@ int zbx_open_xml(char *data, int options, int maxerrlen, void **xml_doc, void **
int zbx_check_xml_memory(char *mem, int maxerrlen, char **errmsg);
#endif
-char *zbx_strloc_unquote_dyn(const char *src, const zbx_strloc_t *loc);
+char *zbx_strloc_get(const char *src, const zbx_strloc_t *loc);
#endif
diff --git a/include/db.h b/include/db.h
index fbdd8006e84..f9d469b3826 100644
--- a/include/db.h
+++ b/include/db.h
@@ -24,6 +24,7 @@
#include "zbxalgo.h"
#include "zbxdb.h"
#include "dbschema.h"
+#include "zbxeval.h"
extern char *CONFIG_DBHOST;
extern char *CONFIG_DBNAME;
@@ -307,6 +308,11 @@ typedef struct
}
DB_DSERVICE;
+#define ZBX_DB_TRIGGER_EVAL_NONE 0x0000
+#define ZBX_DB_TRIGGER_EVAL_EXPRESSION 0x0001
+#define ZBX_DB_TRIGGER_EVAL_EXPRESSION_USERMACRO 0x0002
+#define ZBX_DB_TRIGGER_EVAL_RECOVERY_EXPRESSION 0x0004
+
typedef struct
{
zbx_uint64_t triggerid;
@@ -323,6 +329,9 @@ typedef struct
unsigned char type;
unsigned char recovery_mode;
unsigned char correlation_mode;
+
+ /* temporary trigger cache for related data */
+ void *cache;
}
DB_TRIGGER;
@@ -871,6 +880,11 @@ void zbx_lld_override_operation_free(zbx_lld_override_operation_t *override_oper
void zbx_load_lld_override_operations(const zbx_vector_uint64_t *overrideids, char **sql, size_t *sql_alloc,
zbx_vector_ptr_t *ops);
-
+void zbx_db_trigger_get_all_functionids(const DB_TRIGGER *trigger, zbx_vector_uint64_t *functionids);
+void zbx_db_trigger_get_functionids(const DB_TRIGGER *trigger, zbx_vector_uint64_t *functionids);
+int zbx_db_trigger_get_all_hostids(const DB_TRIGGER *trigger, const zbx_vector_uint64_t **hostids);
+int zbx_db_trigger_get_constant(const DB_TRIGGER *trigger, int index, char **out);
+int zbx_db_trigger_get_itemid(const DB_TRIGGER *trigger, int index, zbx_uint64_t *itemid);
+void zbx_db_trigger_get_itemids(const DB_TRIGGER *trigger, zbx_vector_uint64_t *itemids);
#endif
diff --git a/include/dbcache.h b/include/dbcache.h
index e9c07adf576..b67930b2487 100644
--- a/include/dbcache.h
+++ b/include/dbcache.h
@@ -230,9 +230,6 @@ typedef struct _DC_TRIGGER
{
zbx_uint64_t triggerid;
char *description;
- char *expression_orig;
- char *recovery_expression_orig;
- /* temporary values, allocated during processing and freed right after */
char *expression;
char *recovery_expression;
@@ -750,7 +747,6 @@ void DCget_autoregistration_psk(char *psk_identity_buf, size_t psk_identity_buf_
#define ZBX_MACRO_SECRET_MASK "******"
void DCget_user_macro(const zbx_uint64_t *hostids, int hostids_num, const char *macro, char **replace_to);
-char *DCexpression_expand_user_macros(const char *expression);
char *zbx_dc_expand_func_params_user_macros(zbx_uint64_t hostid, const char *params);
int DCinterface_activate(zbx_uint64_t interfaceid, const zbx_timespec_t *ts, zbx_agent_availability_t *in,
@@ -990,10 +986,10 @@ typedef struct
{
zbx_uint64_t objectid;
zbx_uint64_t triggerid;
- zbx_function_type_t type;
+ zbx_uint32_t type;
zbx_time_unit_t trend_base;
unsigned char lock; /* 1 if the timer has locked trigger, 0 otherwise */
- int revision; /* function revision */
+ int revision; /* revision */
zbx_timespec_t eval_ts; /* the history time for which trigger must be recalculated */
zbx_timespec_t exec_ts; /* real time when the timer must be executed */
const char *parameter; /* function parameters (for trend functions) */
@@ -1012,4 +1008,6 @@ void zbx_db_trigger_queue_unlock(void);
void zbx_get_host_interfaces_availability(zbx_uint64_t hostid, zbx_agent_availability_t *agents);
+void zbx_dc_eval_expand_user_macros(zbx_eval_context_t *ctx);
+
#endif
diff --git a/include/zbxeval.h b/include/zbxeval.h
index c9482108acd..1ff895c8cc9 100644
--- a/include/zbxeval.h
+++ b/include/zbxeval.h
@@ -107,6 +107,7 @@
#define ZBX_EVAL_TRIGGER_EXPRESSION (ZBX_EVAL_PARSE_TRIGGER_EXPRESSSION | \
ZBX_EVAL_COMPOSE_TRIGGER_EXPRESSION | \
+ ZBX_EVAL_PARSE_CONST_INDEX | \
ZBX_EVAL_PROCESS_ERROR)
typedef zbx_uint32_t zbx_token_type_t;
@@ -160,6 +161,7 @@ typedef char *(*zbx_macro_resolve_func_t)(const char *str, size_t length, zbx_ui
int hostids_num);
int zbx_eval_parse_expression(zbx_eval_context_t *ctx, const char *expression, zbx_uint64_t rules, char **error);
+zbx_eval_context_t *zbx_eval_parse_expression_dyn(const char *expression, zbx_uint64_t rules, char **error);
void zbx_eval_clear(zbx_eval_context_t *ctx);
size_t zbx_eval_serialize(const zbx_eval_context_t *ctx, zbx_mem_malloc_func_t malloc_func, unsigned char **data);
void zbx_eval_deserialize(zbx_eval_context_t *ctx, const char *expression, zbx_uint64_t rules,
@@ -168,9 +170,23 @@ void zbx_eval_compose_expression(const zbx_eval_context_t *ctx, char **expressio
int zbx_eval_execute(zbx_eval_context_t *ctx, const zbx_timespec_t *ts, zbx_variant_t *value, char **error);
int zbx_eval_execute_ext(zbx_eval_context_t *ctx, const zbx_timespec_t *ts, zbx_eval_function_cb_t function_cb,
zbx_variant_t *value, char **error);
-void zbx_eval_get_functionids(const zbx_eval_context_t *ctx, zbx_vector_uint64_t *functionids);
+void zbx_eval_get_functionids(zbx_eval_context_t *ctx, zbx_vector_uint64_t *functionids);
+void zbx_eval_get_functionids_ordered(zbx_eval_context_t *ctx, zbx_vector_uint64_t *functionids);
void zbx_eval_expand_user_macros(const zbx_eval_context_t *ctx, zbx_uint64_t *hostids, int hostids_num,
zbx_macro_resolve_func_t resolver_cb);
void zbx_eval_set_exception(zbx_eval_context_t *ctx, char *message);
+#define ZBX_EVAL_EXTRACT_FUNCTIONID 0x0001
+#define ZBX_EVAL_EXTRACT_VAR_STR 0x0002
+#define ZBX_EVAL_EXTRACT_VAR_MACRO 0x0004
+
+#define ZBX_EVAL_EXCTRACT_ALL (ZBX_EVAL_EXTRACT_FUNCTIONID | ZBX_EVAL_EXTRACT_VAR_STR | ZBX_EVAL_EXTRACT_VAR_MACRO)
+
+zbx_eval_context_t *zbx_eval_deserialize_dyn(const unsigned char *data, const char *expression,
+ zbx_uint64_t mask);
+int zbx_eval_check_timer_functions(const zbx_eval_context_t *ctx);
+void zbx_get_serialized_expression_functionids(const char *expression, const unsigned char *data,
+ zbx_vector_uint64_t *functionids);
+void zbx_eval_get_constant(const zbx_eval_context_t *ctx, int index, char **value);
+
#endif
diff --git a/include/zbxserver.h b/include/zbxserver.h
index 29999ee4490..da0778313cf 100644
--- a/include/zbxserver.h
+++ b/include/zbxserver.h
@@ -74,6 +74,7 @@ int substitute_simple_macros_unmasked(zbx_uint64_t *actionid, const DB_EVENT *ev
int maxerrlen);
void evaluate_expressions(zbx_vector_ptr_t *triggers);
+void prepare_triggers(DC_TRIGGER **triggers, int triggers_num);
void zbx_format_value(char *value, size_t max_len, zbx_uint64_t valuemapid,
const char *units, unsigned char value_type);
diff --git a/src/libs/zbxcommon/misc.c b/src/libs/zbxcommon/misc.c
index 29288fe0d24..2f8f29ebc9a 100644
--- a/src/libs/zbxcommon/misc.c
+++ b/src/libs/zbxcommon/misc.c
@@ -3569,7 +3569,7 @@ zbx_function_type_t zbx_get_function_type(const char *func)
if (0 == strncmp(func, "trend", 5))
return ZBX_FUNCTION_TYPE_TRENDS;
- if (SUCCEED == str_in_list("nodata,date,dayofmonth,dayofweek,time,now", func, ','))
+ if (0 == strcmp(func, "nodata"))
return ZBX_FUNCTION_TYPE_TIMER;
return ZBX_FUNCTION_TYPE_HISTORY;
diff --git a/src/libs/zbxcommon/str.c b/src/libs/zbxcommon/str.c
index a88f16a33c7..aa5aeea7bf0 100644
--- a/src/libs/zbxcommon/str.c
+++ b/src/libs/zbxcommon/str.c
@@ -4296,7 +4296,7 @@ int zbx_token_find(const char *expression, int pos, zbx_token_t *token, zbx_toke
for (; '{' != *ptr || 0 != quoted; ptr++)
{
if ('\0' == *ptr)
- return FAIL;
+ break;
if (0 != (token_search & ZBX_TOKEN_SEARCH_FUNCTIONID))
{
@@ -4337,7 +4337,7 @@ int zbx_token_find(const char *expression, int pos, zbx_token_t *token, zbx_toke
token_search &= ~ZBX_TOKEN_SEARCH_REFERENCES;
}
- if (NULL == ptr)
+ if (NULL == ptr || '\0' == *ptr)
return FAIL;
if ('\0' == ptr[1])
@@ -6097,7 +6097,7 @@ const char *zbx_print_double(char *buffer, size_t size, double val)
/******************************************************************************
* *
- * Function: zbx_strloc_unquote_dyn *
+ * Function: zbx_strloc_unquote *
* *
* Purpose: unquotes substring at the specified location *
* *
@@ -6107,34 +6107,41 @@ const char *zbx_print_double(char *buffer, size_t size, double val)
* Return value: The unquoted and copied substring. *
* *
******************************************************************************/
-char *zbx_strloc_unquote_dyn(const char *src, const zbx_strloc_t *loc)
+char *zbx_strloc_get(const char *src, const zbx_strloc_t *loc)
{
- char *str, *ptr;
-
- src += loc->l + 1;
+ char *str, *ptr;
- str = ptr = zbx_malloc(NULL, loc->r - loc->l);
-
- while ('"' != *src)
+ if ('"' == src[loc->l])
{
- if ('\\' == *src)
+ src += loc->l + 1;
+ str = ptr = zbx_malloc(NULL, loc->r - loc->l);
+
+ while ('"' != *src)
{
- switch (*(++src))
+ if ('\\' == *src)
{
- case '\\':
- *ptr++ = '\\';
- break;
- case '"':
- *ptr++ = '"';
- break;
+ switch (*(++src))
+ {
+ case '\\':
+ *ptr++ = '\\';
+ break;
+ case '"':
+ *ptr++ = '"';
+ break;
+ }
}
+ else
+ *ptr++ = *src;
+ src++;
}
- else
- *ptr++ = *src;
- src++;
+ *ptr = '\0';
+ }
+ else
+ {
+ str = zbx_malloc(NULL, loc->r - loc->l + 2);
+ memcpy(str, src + loc->l, loc->r - loc->l + 1);
+ str[loc->r - loc->l + 1] = '\0';
}
- *ptr = '\0';
return str;
}
-
diff --git a/src/libs/zbxdbcache/dbcache.c b/src/libs/zbxdbcache/dbcache.c
index db6889b4089..882d3c364fd 100644
--- a/src/libs/zbxdbcache/dbcache.c
+++ b/src/libs/zbxdbcache/dbcache.c
@@ -1603,12 +1603,23 @@ static void recalculate_triggers(const ZBX_DC_HISTORY *history, int history_num,
if (0 != item_num)
{
DCconfig_get_triggers_by_itemids(&trigger_info, &trigger_order, itemids, timespecs, item_num);
+ prepare_triggers((DC_TRIGGER **)trigger_order.values, trigger_order.values_num);
zbx_determine_items_in_expressions(&trigger_order, itemids, item_num);
}
if (0 != timers_num)
+ {
+ int offset = trigger_order.values_num;
+
zbx_dc_get_triggers_by_timers(&trigger_info, &trigger_order, timers);
+ if (offset != trigger_order.values_num)
+ {
+ prepare_triggers((DC_TRIGGER **)trigger_order.values + offset,
+ trigger_order.values_num - offset);
+ }
+ }
+
zbx_vector_ptr_sort(&trigger_order, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
evaluate_expressions(&trigger_order);
zbx_process_triggers(&trigger_order, trigger_diff);
diff --git a/src/libs/zbxdbcache/dbconfig.c b/src/libs/zbxdbcache/dbconfig.c
index 9b90a3e822e..64b074dae0e 100644
--- a/src/libs/zbxdbcache/dbconfig.c
+++ b/src/libs/zbxdbcache/dbconfig.c
@@ -3597,7 +3597,6 @@ static unsigned char *dup_serialized_expression(const unsigned char *src)
return NULL;
offset = zbx_deserialize_uint31_compact(src, &len);
- zabbix_log(LOG_LEVEL_DEBUG, "[WDN] dup: offset:%d len:%d", offset, len);
if (0 == len)
return NULL;
@@ -3681,6 +3680,8 @@ static void DCsync_triggers(zbx_dbsync_t *sync)
trigger->expression_bin = config_decode_serialized_expression(row[16]);
trigger->recovery_expression_bin = config_decode_serialized_expression(row[17]);
+ trigger->timer = atoi(row[18]);
+ trigger->revision = config->sync_start_ts;
}
/* remove deleted triggers from buffer */
@@ -3700,10 +3701,14 @@ static void DCsync_triggers(zbx_dbsync_t *sync)
/* force trigger list update for items used in removed trigger */
- get_functionids(&functionids, trigger->expression);
+ zbx_get_serialized_expression_functionids(trigger->expression, trigger->expression_bin,
+ &functionids);
if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == trigger->recovery_mode)
- get_functionids(&functionids, trigger->recovery_expression);
+ {
+ zbx_get_serialized_expression_functionids(trigger->recovery_expression,
+ trigger->recovery_expression_bin, &functionids);
+ }
for (i = 0; i < functionids.values_num; i++)
{
@@ -3904,7 +3909,7 @@ static int dc_function_calculate_trends_nextcheck(time_t from, const char *perio
static int dc_function_calculate_nextcheck(const zbx_trigger_timer_t *timer, time_t from, zbx_uint64_t seed)
{
- if (ZBX_FUNCTION_TYPE_TIMER == timer->type)
+ if (ZBX_TRIGGER_TIMER_FUNCTION_TIME == timer->type || ZBX_TRIGGER_TIMER_TRIGGER == timer->type)
{
int nextcheck;
@@ -3916,7 +3921,7 @@ static int dc_function_calculate_nextcheck(const zbx_trigger_timer_t *timer, tim
return nextcheck;
}
- else if (ZBX_FUNCTION_TYPE_TRENDS == timer->type)
+ else if (ZBX_TRIGGER_TIMER_FUNCTION_TREND == timer->type)
{
struct tm tm;
time_t nextcheck;
@@ -3942,15 +3947,17 @@ static int dc_function_calculate_nextcheck(const zbx_trigger_timer_t *timer, tim
}
else
{
- int ret;
+ int ret = FAIL;
char *error = NULL, *period_shift;
- period_shift = zbx_function_get_param_dyn(timer->parameter, 2);
-
- ret = dc_function_calculate_trends_nextcheck(from, period_shift, timer->trend_base, &nextcheck,
- &error);
-
- zbx_free(period_shift);
+ if (NULL != (period_shift = strchr(timer->parameter, ':')))
+ {
+ period_shift++;
+ ret = dc_function_calculate_trends_nextcheck(from, period_shift, timer->trend_base,
+ &nextcheck, &error);
+ }
+ else
+ error = zbx_dsprintf(NULL, "invalid first parameter");
if (FAIL == ret)
{
@@ -3972,21 +3979,22 @@ static int dc_function_calculate_nextcheck(const zbx_trigger_timer_t *timer, tim
/******************************************************************************
* *
- * Function: dc_trigger_timer_create *
+ * Function: dc_trigger_function_timer_create *
* *
- * Purpose: create trigger timer based on the specified function *
+ * Purpose: create trigger timer based on the trend function *
* *
* Return value: Created timer or NULL in the case of error. *
* *
******************************************************************************/
-static zbx_trigger_timer_t *dc_trigger_timer_create(ZBX_DC_FUNCTION *function)
+static zbx_trigger_timer_t *dc_trigger_function_timer_create(ZBX_DC_FUNCTION *function)
{
zbx_trigger_timer_t *timer;
zbx_time_unit_t trend_base;
+ zbx_uint32_t type;
if (ZBX_FUNCTION_TYPE_TRENDS == function->type)
{
- char *error = NULL;
+ char *error = NULL;
if (FAIL == zbx_trends_parse_base(function->parameter, &trend_base, &error))
{
@@ -3995,17 +4003,22 @@ static zbx_trigger_timer_t *dc_trigger_timer_create(ZBX_DC_FUNCTION *function)
zbx_free(error);
return NULL;
}
+ type = ZBX_TRIGGER_TIMER_FUNCTION_TREND;
}
else
+ {
trend_base = ZBX_TIME_UNIT_UNKNOWN;
+ type = ZBX_TRIGGER_TIMER_FUNCTION_TIME;
+ }
timer = (zbx_trigger_timer_t *)__config_mem_malloc_func(NULL, sizeof(zbx_trigger_timer_t));
- timer->type = function->type;
+
timer->objectid = function->functionid;
timer->triggerid = function->triggerid;
timer->revision = function->revision;
timer->trend_base = trend_base;
timer->lock = 0;
+ timer->type = type;
function->timer_revision = function->revision;
@@ -4017,6 +4030,32 @@ static zbx_trigger_timer_t *dc_trigger_timer_create(ZBX_DC_FUNCTION *function)
return timer;
}
+/******************************************************************************
+ * *
+ * Function: dc_trigger_timer_create *
+ * *
+ * Purpose: create trigger timer based on the specified trigger *
+ * *
+ * Return value: Created timer or NULL in the case of error. *
+ * *
+ ******************************************************************************/
+static zbx_trigger_timer_t *dc_trigger_timer_create(ZBX_DC_TRIGGER *trigger)
+{
+ zbx_trigger_timer_t *timer;
+
+ timer = (zbx_trigger_timer_t *)__config_mem_malloc_func(NULL, sizeof(zbx_trigger_timer_t));
+ timer->type = ZBX_TRIGGER_TIMER_TRIGGER;
+ timer->objectid = trigger->triggerid;
+ timer->triggerid = trigger->triggerid;
+ timer->revision = trigger->revision;
+ timer->trend_base = ZBX_TIME_UNIT_UNKNOWN;
+ timer->lock = 0;
+ timer->parameter = NULL;
+
+ trigger->timer_revision = trigger->revision;
+
+ return timer;
+}
/******************************************************************************
* *
@@ -4095,7 +4134,7 @@ static void dc_schedule_trigger_timers(zbx_hashset_t *trend_queue, int now)
if (TRIGGER_STATUS_ENABLED != trigger->status || TRIGGER_FUNCTIONAL_TRUE != trigger->functional)
continue;
- if (NULL == (timer = dc_trigger_timer_create(function)))
+ if (NULL == (timer = dc_trigger_function_timer_create(function)))
continue;
if (NULL != trend_queue && NULL != (old = (zbx_trigger_timer_t *)zbx_hashset_search(trend_queue,
@@ -4121,6 +4160,25 @@ static void dc_schedule_trigger_timers(zbx_hashset_t *trend_queue, int now)
dc_schedule_trigger_timer(timer, NULL, &ts);
}
}
+
+ zbx_hashset_iter_reset(&config->triggers, &iter);
+ while (NULL != (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_iter_next(&iter)))
+ {
+ if (ZBX_TRIGGER_TIMER_DEFAULT == trigger->timer)
+ continue;
+
+ if (NULL == (timer = dc_trigger_timer_create(trigger)))
+ continue;
+
+ if (0 == (ts.sec = dc_function_calculate_nextcheck(timer, now, timer->triggerid)))
+ {
+ dc_trigger_timer_free(timer);
+ trigger->timer_revision = 0;
+ }
+ else
+ dc_schedule_trigger_timer(timer, NULL, &ts);
+
+ }
}
static void DCsync_functions(zbx_dbsync_t *sync)
@@ -7754,8 +7812,6 @@ static void DCget_trigger(DC_TRIGGER *dst_trigger, const ZBX_DC_TRIGGER *src_tri
dst_trigger->triggerid = src_trigger->triggerid;
dst_trigger->description = zbx_strdup(NULL, src_trigger->description);
- dst_trigger->expression_orig = zbx_strdup(NULL, src_trigger->expression);
- dst_trigger->recovery_expression_orig = zbx_strdup(NULL, src_trigger->recovery_expression);
dst_trigger->error = zbx_strdup(NULL, src_trigger->error);
dst_trigger->timespec.sec = 0;
dst_trigger->timespec.ns = 0;
@@ -7825,8 +7881,6 @@ static void DCclean_trigger(DC_TRIGGER *trigger)
{
zbx_free(trigger->new_error);
zbx_free(trigger->error);
- zbx_free(trigger->expression_orig);
- zbx_free(trigger->recovery_expression_orig);
zbx_free(trigger->expression);
zbx_free(trigger->recovery_expression);
zbx_free(trigger->description);
@@ -7838,6 +7892,19 @@ static void DCclean_trigger(DC_TRIGGER *trigger)
zbx_vector_ptr_clear_ext(&trigger->tags, (zbx_clean_func_t)zbx_free_tag);
zbx_vector_ptr_destroy(&trigger->tags);
+
+ if (NULL != trigger->eval_ctx)
+ {
+ zbx_eval_clear(trigger->eval_ctx);
+ zbx_free(trigger->eval_ctx);
+ }
+
+ if (NULL != trigger->eval_ctx_r)
+ {
+ zbx_eval_clear(trigger->eval_ctx_r);
+ zbx_free(trigger->eval_ctx_r);
+ }
+
}
/******************************************************************************
@@ -8439,22 +8506,35 @@ void DCconfig_get_triggers_by_itemids(zbx_hashset_t *trigger_info, zbx_vector_pt
* *
* Function: DCconfig_find_active_time_function *
* *
- * Purpose: checks if the expression contains time based functions *
+ * Purpose: check if the expression contains time based functions *
+ * *
+ * Parameters: expression - [IN] the original expression *
+ * data - [IN] the parsed and serialized expression *
+ * trigger_timer - [IN] the trigger time function flags *
* *
******************************************************************************/
-static int DCconfig_find_active_time_function(const char *expression)
+static int DCconfig_find_active_time_function(const char *expression, const unsigned char *data,
+ unsigned char trigger_timer)
{
- zbx_uint64_t functionid;
+ int i, ret = SUCCEED;
const ZBX_DC_FUNCTION *dc_function;
const ZBX_DC_HOST *dc_host;
const ZBX_DC_ITEM *dc_item;
+ zbx_vector_uint64_t functionids;
+
+ zbx_vector_uint64_create(&functionids);
+ zbx_get_serialized_expression_functionids(expression, data, &functionids);
- while (SUCCEED == get_N_functionid(expression, 1, &functionid, &expression))
+ for (i = 0; i < functionids.values_num; i++)
{
- if (NULL == (dc_function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &functionid)))
+ if (NULL == (dc_function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions,
+ &functionids.values[i])))
+ {
continue;
+ }
- if (ZBX_FUNCTION_TYPE_TIMER == dc_function->type || ZBX_FUNCTION_TYPE_TRENDS == dc_function->type)
+ if (ZBX_TRIGGER_TIMER_DEFAULT != trigger_timer || ZBX_FUNCTION_TYPE_TRENDS == dc_function->type ||
+ ZBX_FUNCTION_TYPE_TIMER == dc_function->type)
{
if (NULL == (dc_item = zbx_hashset_search(&config->items, &dc_function->itemid)))
continue;
@@ -8463,11 +8543,15 @@ static int DCconfig_find_active_time_function(const char *expression)
continue;
if (SUCCEED != DCin_maintenance_without_data_collection(dc_host, dc_item))
- return SUCCEED;
+ goto out;
}
}
- return FAIL;
+ ret = FAIL;
+out:
+ zbx_vector_uint64_destroy(&functionids);
+
+ return ret;
}
/******************************************************************************
@@ -8502,7 +8586,8 @@ void zbx_dc_get_triggers_by_timers(zbx_hashset_t *trigger_info, zbx_vector_ptr_t
DC_TRIGGER *trigger, trigger_local;
unsigned char flags;
- if (SUCCEED == DCconfig_find_active_time_function(dc_trigger->expression))
+ if (SUCCEED == DCconfig_find_active_time_function(dc_trigger->expression,
+ dc_trigger->expression_bin, dc_trigger->timer & ZBX_TRIGGER_TIMER_EXPRESSION))
{
flags = ZBX_DC_TRIGGER_PROBLEM_EXPRESSION;
}
@@ -8514,8 +8599,12 @@ void zbx_dc_get_triggers_by_timers(zbx_hashset_t *trigger_info, zbx_vector_ptr_t
if (TRIGGER_VALUE_PROBLEM != dc_trigger->value)
continue;
- if (SUCCEED != DCconfig_find_active_time_function(dc_trigger->recovery_expression))
+ if (SUCCEED != DCconfig_find_active_time_function(dc_trigger->recovery_expression,
+ dc_trigger->recovery_expression_bin,
+ dc_trigger->timer & ZBX_TRIGGER_TIMER_RECOVERY_EXPRESSION))
+ {
continue;
+ }
flags = 0;
}
@@ -8536,6 +8625,58 @@ void zbx_dc_get_triggers_by_timers(zbx_hashset_t *trigger_info, zbx_vector_ptr_t
/******************************************************************************
* *
+ * Function: trigger_timer_validate *
+ * *
+ * Purpose: validate trigger timer *
+ * *
+ * Parameters: timer - [IN] trigger timer *
+ * dc_trigger - [OUT] the trigger data *
+ * *
+ * Return value: SUCCEED - the timer is valid *
+ * FAIL - otherwise *
+ * *
+ ******************************************************************************/
+static int trigger_timer_validate(zbx_trigger_timer_t *timer, ZBX_DC_TRIGGER **dc_trigger)
+{
+ ZBX_DC_FUNCTION *dc_function;
+
+ *dc_trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &timer->triggerid);
+
+ if (0 != (timer->type & ZBX_TRIGGER_TIMER_FUNCTION))
+ {
+ if (NULL == (dc_function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &timer->objectid)))
+ return FAIL;
+
+ if (dc_function->revision > timer->revision ||
+ NULL == *dc_trigger ||
+ TRIGGER_STATUS_ENABLED != (*dc_trigger)->status ||
+ TRIGGER_FUNCTIONAL_TRUE != (*dc_trigger)->functional)
+ {
+ if (dc_function->timer_revision == timer->revision)
+ dc_function->timer_revision = 0;
+ return FAIL;
+ }
+ }
+ else
+ {
+ if (NULL == dc_trigger)
+ return FAIL;
+
+ if ((*dc_trigger)->revision > timer->revision ||
+ TRIGGER_STATUS_ENABLED != (*dc_trigger)->status ||
+ TRIGGER_FUNCTIONAL_TRUE != (*dc_trigger)->functional)
+ {
+ if ((*dc_trigger)->timer_revision == timer->revision)
+ (*dc_trigger)->timer_revision = 0;
+ return FAIL;
+ }
+ }
+
+ return SUCCEED;
+}
+
+/******************************************************************************
+ * *
* Function: zbx_dc_get_trigger_timers *
* *
* Purpose: gets timers from trigger queue *
@@ -8565,7 +8706,6 @@ void zbx_dc_get_trigger_timers(zbx_vector_ptr_t *timers, int now, int soft_limit
zbx_binary_heap_elem_t *elem;
zbx_trigger_timer_t *timer;
ZBX_DC_TRIGGER *dc_trigger;
- ZBX_DC_FUNCTION *dc_function;
elem = zbx_binary_heap_find_min(&config->trigger_queue);
timer = (zbx_trigger_timer_t *)elem->data;
@@ -8588,17 +8728,8 @@ void zbx_dc_get_trigger_timers(zbx_vector_ptr_t *timers, int now, int soft_limit
zbx_binary_heap_remove_min(&config->trigger_queue);
- /* check if function exists and trigger should be calculated */
- if (NULL == (dc_function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &timer->objectid)) ||
- dc_function->revision > timer->revision ||
- NULL == (dc_trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers,
- &timer->triggerid)) ||
- TRIGGER_STATUS_ENABLED != dc_trigger->status ||
- TRIGGER_FUNCTIONAL_TRUE != dc_trigger->functional)
+ if (SUCCEED != trigger_timer_validate(timer, &dc_trigger))
{
- if (NULL != dc_function && dc_function->revision == timer->revision)
- dc_function->timer_revision = 0;
-
dc_trigger_timer_free(timer);
continue;
}
@@ -8612,7 +8743,7 @@ void zbx_dc_get_trigger_timers(zbx_vector_ptr_t *timers, int now, int soft_limit
/* 1) time functions uses current time, so trigger evaluation time does not affect their results */
/* 2) trend function of the same trigger with the same evaluation timestamp is being */
/* evaluated by the same process */
- if (0 == dc_trigger->locked || ZBX_FUNCTION_TYPE_TRENDS != timer->type ||
+ if (0 == dc_trigger->locked || ZBX_TRIGGER_TIMER_FUNCTION_TREND != timer->type ||
(NULL != first_timer && 1 == first_timer->lock))
{
/* resetting execution timer will cause a new execution time to be set */
@@ -8653,12 +8784,25 @@ static void dc_reschedule_trigger_timers(zbx_vector_ptr_t *timers)
/* schedule calculation error can result in 0 execution time */
if (0 == timer->exec_ts.sec)
{
- ZBX_DC_FUNCTION *function;
+ if (0 != (timer->type & ZBX_TRIGGER_TIMER_FUNCTION))
+ {
+ ZBX_DC_FUNCTION *function;
- if (NULL != (function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions,
- &timer->objectid)) && function->timer_revision == timer->revision)
+ if (NULL != (function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions,
+ &timer->objectid)) && function->timer_revision == timer->revision)
+ {
+ function->timer_revision = 0;
+ }
+ }
+ else if (ZBX_TRIGGER_TIMER_TRIGGER == timer->type)
{
- function->timer_revision = 0;
+ ZBX_DC_TRIGGER *trigger;
+
+ if (NULL != (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers,
+ &timer->objectid)) && trigger->timer_revision == timer->revision)
+ {
+ trigger->timer_revision = 0;
+ }
}
dc_trigger_timer_free(timer);
}
@@ -8718,7 +8862,7 @@ void zbx_dc_clear_timer_queue(zbx_vector_ptr_t *timers)
{
zbx_trigger_timer_t *timer = (zbx_trigger_timer_t *)config->trigger_queue.elems[i].data;
- if (ZBX_FUNCTION_TYPE_TRENDS == timer->type &&
+ if (ZBX_TRIGGER_TIMER_FUNCTION_TREND == timer->type &&
NULL != (function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions,
&timer->objectid)) &&
function->timer_revision == timer->revision)
@@ -10697,9 +10841,9 @@ out:
char *dc_expand_user_macros_len(const char *text, size_t text_len, zbx_uint64_t *hostids, int hostids_num)
{
zbx_token_t token;
- int pos = 0, len, last_pos = 0;
+ int len;
char *str = NULL, *name = NULL, *context = NULL, *value = NULL;
- size_t str_alloc = 0, str_offset = 0;
+ size_t str_alloc = 0, str_offset = 0, pos = 0, last_pos = 0;
if ('\0' == *text)
return zbx_strdup(NULL, text);
@@ -10712,7 +10856,9 @@ char *dc_expand_user_macros_len(const char *text, size_t text_len, zbx_uint64_t
if (SUCCEED != zbx_user_macro_parse_dyn(text + token.loc.l, &name, &context, &len, NULL))
continue;
- zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + last_pos, token.loc.l - last_pos);
+ if (last_pos < token.loc.l)
+ zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + last_pos, token.loc.l - last_pos);
+
dc_get_user_macro(hostids, hostids_num, name, context, &value);
if (NULL != value)
@@ -10733,7 +10879,8 @@ char *dc_expand_user_macros_len(const char *text, size_t text_len, zbx_uint64_t
last_pos = pos + 1;
}
- zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + last_pos, text_len - last_pos);
+ if (last_pos < text_len)
+ zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + last_pos, text_len - last_pos);
return str;
}
@@ -10943,75 +11090,6 @@ char *dc_expand_user_macros_in_expression(const char *text, zbx_uint64_t *hostid
/******************************************************************************
* *
- * Function: dc_expression_expand_user_macros *
- * *
- * Purpose: expand user macros in trigger expression *
- * *
- * Parameters: expression - [IN] the expression to expand *
- * error - [OUT] the error message *
- * *
- * Return value: The expanded expression or NULL in the case of error. *
- * If NULL is returned the error message is set. *
- * *
- * Comments: The returned expression must be freed by the caller. *
- * *
- ******************************************************************************/
-static char *dc_expression_expand_user_macros(const char *expression)
-{
- zbx_vector_uint64_t functionids, hostids;
- char *out;
-
- zbx_vector_uint64_create(&functionids);
- zbx_vector_uint64_create(&hostids);
-
- get_functionids(&functionids, expression);
- dc_get_hostids_by_functionids(functionids.values, functionids.values_num, &hostids);
-
- out = dc_expand_user_macros_in_expression(expression, hostids.values, hostids.values_num);
-
- if (NULL != strstr(out, "{$"))
- {
- zabbix_log(LOG_LEVEL_DEBUG, "cannot evaluate expression: invalid macro value");
- zbx_free(out);
- }
-
- zbx_vector_uint64_destroy(&hostids);
- zbx_vector_uint64_destroy(&functionids);
-
- return out;
-}
-
-/******************************************************************************
- * *
- * Function: DCexpression_expand_user_macros *
- * *
- * Purpose: expand user macros in trigger expression *
- * *
- * Parameters: expression - [IN] the expression to expand *
- * *
- * Return value: The expanded expression or NULL in the case of error. *
- * If NULL is returned the error message is set. *
- * *
- * Comments: The returned expression must be freed by the caller. *
- * This function is a locking wrapper of *
- * dc_expression_expand_user_macros() function for external usage. *
- * *
- ******************************************************************************/
-char *DCexpression_expand_user_macros(const char *expression)
-{
- char *expression_ex;
-
- RDLOCK_CACHE;
-
- expression_ex = dc_expression_expand_user_macros(expression);
-
- UNLOCK_CACHE;
-
- return expression_ex;
-}
-
-/******************************************************************************
- * *
* Function: DCfree_item_queue *
* *
* Purpose: frees the item queue data vector created by DCget_item_queue() *
@@ -11126,59 +11204,52 @@ int DCget_item_queue(zbx_vector_ptr_t *queue, int from, int to)
* Function: dc_trigger_items_hosts_enabled *
* *
* Purpose: check that functionids in trigger (recovery) expression *
- * correspond to enabled items and hosts *
* *
* Parameters: expression - [IN] trigger (recovery) expression *
+ * data - [IN] parsed and serialized expression *
* *
* Return value: SUCCEED - all functionids correspond to enabled items and *
* enabled hosts *
* FAIL - at least one item or host is disabled *
* *
******************************************************************************/
-static int dc_trigger_items_hosts_enabled(const char *expression)
+static int dc_trigger_items_hosts_enabled(const char *expression, const unsigned char *data)
{
zbx_uint64_t functionid;
const ZBX_DC_ITEM *dc_item;
const ZBX_DC_FUNCTION *dc_function;
const ZBX_DC_HOST *dc_host;
- const char *p, *q;
-
- for (p = expression; '\0' != *p; p++)
- {
- if ('{' != *p)
- continue;
+ int i, ret = FAIL;
+ zbx_vector_uint64_t functionids;
- if ('$' == p[1])
- {
- int macro_r, context_l, context_r;
+ zbx_vector_uint64_create(&functionids);
+ zbx_get_serialized_expression_functionids(expression, data, &functionids);
- if (SUCCEED == zbx_user_macro_parse(p, &macro_r, &context_l, &context_r, NULL))
- p += macro_r;
- else
- p++;
+ for (i = 0; i < functionids.values_num; i++)
+ {
+ functionid = functionids.values[i];
- continue;
- }
+ if (NULL == (dc_function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &functionid)))
+ goto out;
- if (NULL == (q = strchr(p + 1, '}')))
- return FAIL;
+ if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &dc_function->itemid)))
+ goto out;
- if (SUCCEED != is_uint64_n(p + 1, q - p - 1, &functionid))
- continue;
+ if (ITEM_STATUS_ACTIVE != dc_item->status)
+ goto out;
- if (NULL == (dc_function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &functionid)) ||
- NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &dc_function->itemid)) ||
- ITEM_STATUS_ACTIVE != dc_item->status ||
- NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)) ||
- HOST_STATUS_MONITORED != dc_host->status)
- {
- return FAIL;
- }
+ if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
+ goto out;
- p = q;
+ if (HOST_STATUS_MONITORED != dc_host->status)
+ goto out;
}
- return SUCCEED;
+ ret = SUCCEED;
+out:
+ zbx_vector_uint64_destroy(&functionids);
+
+ return ret;
}
/******************************************************************************
@@ -11356,9 +11427,11 @@ static void dc_status_update(void)
switch (dc_trigger->status)
{
case TRIGGER_STATUS_ENABLED:
- if (SUCCEED == dc_trigger_items_hosts_enabled(dc_trigger->expression) &&
+ if (SUCCEED == dc_trigger_items_hosts_enabled(dc_trigger->expression,
+ dc_trigger->expression_bin) &&
(TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION != dc_trigger->recovery_mode ||
- SUCCEED == dc_trigger_items_hosts_enabled(dc_trigger->recovery_expression)))
+ SUCCEED == dc_trigger_items_hosts_enabled(dc_trigger->recovery_expression,
+ dc_trigger->recovery_expression_bin)))
{
switch (dc_trigger->value)
{
@@ -13909,7 +13982,37 @@ void zbx_get_host_interfaces_availability(zbx_uint64_t hostid, zbx_agent_availab
}
+/*********************************************************************************
+ * *
+ * Function: zbx_dc_eval_expand_user_macros *
+ * *
+ * Purpose: resolve user macros in parsed expression *
+ * *
+ * Parameters: ctx - [IN] the expression evalution context *
+ * *
+ ********************************************************************************/
+void zbx_dc_eval_expand_user_macros(zbx_eval_context_t *ctx)
+{
+ zbx_vector_uint64_t hostids, functionids;
+
+ zbx_vector_uint64_create(&hostids);
+ zbx_vector_uint64_create(&functionids);
+
+ zbx_eval_get_functionids(ctx, &functionids);
+
+ RDLOCK_CACHE;
+
+ dc_get_hostids_by_functionids(functionids.values, functionids.values_num, &hostids);
+ zbx_eval_expand_user_macros(ctx, hostids.values, hostids.values_num, dc_expand_user_macros_len);
+
+ UNLOCK_CACHE;
+
+ zbx_vector_uint64_destroy(&functionids);
+ zbx_vector_uint64_destroy(&hostids);
+}
+
#ifdef HAVE_TESTS
# include "../../../tests/libs/zbxdbcache/dc_item_poller_type_update_test.c"
# include "../../../tests/libs/zbxdbcache/dc_function_calculate_nextcheck_test.c"
#endif
+
diff --git a/src/libs/zbxdbcache/dbconfig.h b/src/libs/zbxdbcache/dbconfig.h
index 7bb56a4d7fb..f3d674695b1 100644
--- a/src/libs/zbxdbcache/dbconfig.h
+++ b/src/libs/zbxdbcache/dbconfig.h
@@ -37,6 +37,8 @@ typedef struct
const unsigned char *expression_bin;
const unsigned char *recovery_expression_bin;
int lastchange;
+ int revision;
+ int timer_revision;
unsigned char topoindex;
unsigned char priority;
unsigned char type;
@@ -47,11 +49,18 @@ typedef struct
unsigned char functional; /* see TRIGGER_FUNCTIONAL_* defines */
unsigned char recovery_mode; /* see TRIGGER_RECOVERY_MODE_* defines */
unsigned char correlation_mode; /* see ZBX_TRIGGER_CORRELATION_* defines */
+ unsigned char timer;
zbx_vector_ptr_t tags;
}
ZBX_DC_TRIGGER;
+/* specifies if trigger expression/recovery expression has timer functions */
+/* (date, time, now, dayofweek or dayofmonth) */
+#define ZBX_TRIGGER_TIMER_DEFAULT 0x00
+#define ZBX_TRIGGER_TIMER_EXPRESSION 0x01
+#define ZBX_TRIGGER_TIMER_RECOVERY_EXPRESSION 0x02
+
typedef struct zbx_dc_trigger_deplist
{
zbx_uint64_t triggerid;
@@ -913,4 +922,10 @@ char *dc_expand_user_macros_in_calcitem(const char *formula, zbx_uint64_t hostid
char *dc_expand_user_macros(const char *text, zbx_uint64_t *hostids, int hostids_num);
char *dc_expand_user_macros_len(const char *text, size_t len, zbx_uint64_t *hostids, int hostids_num);
+#define ZBX_TRIGGER_TIMER_NONE 0x0000
+#define ZBX_TRIGGER_TIMER_TRIGGER 0x0001
+#define ZBX_TRIGGER_TIMER_FUNCTION_TIME 0x0002
+#define ZBX_TRIGGER_TIMER_FUNCTION_TREND 0x0004
+#define ZBX_TRIGGER_TIMER_FUNCTION (ZBX_TRIGGER_TIMER_FUNCTION_TIME | ZBX_TRIGGER_TIMER_FUNCTION_TREND)
+
#endif
diff --git a/src/libs/zbxdbcache/dbconfig_maintenance.c b/src/libs/zbxdbcache/dbconfig_maintenance.c
index fde177b3e2c..43dccd68331 100644
--- a/src/libs/zbxdbcache/dbconfig_maintenance.c
+++ b/src/libs/zbxdbcache/dbconfig_maintenance.c
@@ -1532,8 +1532,15 @@ int zbx_dc_get_event_maintenances(zbx_vector_ptr_t *event_queries, const zbx_vec
{
continue;
}
- get_functionids(&query->functionids, trigger->expression);
- get_functionids(&query->functionids, trigger->recovery_expression);
+
+ zbx_get_serialized_expression_functionids(trigger->expression, trigger->expression_bin,
+ &query->functionids);
+
+ if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == trigger->recovery_mode)
+ {
+ zbx_get_serialized_expression_functionids(trigger->recovery_expression,
+ trigger->recovery_expression_bin, &query->functionids);
+ }
}
for (j = 0; j < query->functionids.values_num; j++)
diff --git a/src/libs/zbxdbcache/dbsync.c b/src/libs/zbxdbcache/dbsync.c
index f3cde1454fd..b0ab54a1d12 100644
--- a/src/libs/zbxdbcache/dbsync.c
+++ b/src/libs/zbxdbcache/dbsync.c
@@ -2206,7 +2206,7 @@ static char **dbsync_trigger_preproc_row(char **row)
zbx_vector_uint64_t hostids, functionids;
zbx_eval_context_t ctx, ctx_r;
char *error;
- unsigned char mode;
+ unsigned char mode, timer = ZBX_TRIGGER_TIMER_DEFAULT;
zbx_vector_uint64_create(&hostids);
zbx_vector_uint64_create(&functionids);
@@ -2217,20 +2217,30 @@ static char **dbsync_trigger_preproc_row(char **row)
zbx_free(error);
}
else
+ {
zbx_eval_get_functionids(&ctx, &functionids);
+ if (SUCCEED == zbx_eval_check_timer_functions(&ctx))
+ timer |= ZBX_TRIGGER_TIMER_EXPRESSION;
+ }
+
ZBX_STR2UCHAR(mode, row[10]);
if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == mode)
{
- if (FAIL == zbx_eval_parse_expression(&ctx_r, row[2], ZBX_EVAL_TRIGGER_EXPRESSION, &error))
+ if (FAIL == zbx_eval_parse_expression(&ctx_r, row[11], ZBX_EVAL_TRIGGER_EXPRESSION, &error))
{
zbx_eval_set_exception(&ctx_r, zbx_dsprintf(NULL, "cannot parse trigger recovery"
" expression: %s", error));
zbx_free(error);
}
else
+ {
zbx_eval_get_functionids(&ctx, &functionids);
+
+ if (SUCCEED == zbx_eval_check_timer_functions(&ctx))
+ timer |= ZBX_TRIGGER_TIMER_RECOVERY_EXPRESSION;
+ }
}
dc_get_hostids_by_functionids(functionids.values, functionids.values_num, &hostids);
@@ -2252,6 +2262,8 @@ static char **dbsync_trigger_preproc_row(char **row)
zbx_eval_clear(&ctx_r);
}
+ row[18] = zbx_dsprintf(NULL, "%d", timer);
+
zbx_vector_uint64_destroy(&functionids);
zbx_vector_uint64_destroy(&hostids);
@@ -2270,7 +2282,9 @@ static char **dbsync_trigger_preproc_row(char **row)
* FAIL - otherwise *
* *
* Comment: The 16th and 17th fields (starting with 0) are placeholders for *
- * serialized expression/recovery expression *
+ * serialized expression/recovery expression. *
+ * The 18th field is placeholder for trigger timer flag (set if *
+ * expression/recovery expression contains timer functions). *
* *
******************************************************************************/
int zbx_dbsync_compare_triggers(zbx_dbsync_t *sync)
@@ -2286,7 +2300,7 @@ int zbx_dbsync_compare_triggers(zbx_dbsync_t *sync)
if (NULL == (result = DBselect(
"select distinct t.triggerid,t.description,t.expression,t.error,t.priority,t.type,t.value,"
"t.state,t.lastchange,t.status,t.recovery_mode,t.recovery_expression,"
- "t.correlation_mode,t.correlation_tag,t.opdata,t.event_name,null,null"
+ "t.correlation_mode,t.correlation_tag,t.opdata,t.event_name,null,null,null"
" from hosts h,items i,functions f,triggers t"
" where h.hostid=i.hostid"
" and i.itemid=f.itemid"
@@ -2299,7 +2313,7 @@ int zbx_dbsync_compare_triggers(zbx_dbsync_t *sync)
return FAIL;
}
- dbsync_prepare(sync, 18, dbsync_trigger_preproc_row);
+ dbsync_prepare(sync, 19, dbsync_trigger_preproc_row);
if (ZBX_DBSYNC_INIT == sync->mode)
{
diff --git a/src/libs/zbxdbhigh/event.c b/src/libs/zbxdbhigh/event.c
index 4a3bfa131c8..5771cbc7eaa 100644
--- a/src/libs/zbxdbhigh/event.c
+++ b/src/libs/zbxdbhigh/event.c
@@ -198,6 +198,7 @@ void zbx_db_get_events_by_eventids(zbx_vector_uint64_t *eventids, zbx_vector_ptr
event->trigger.opdata = zbx_strdup(NULL, row[9]);
event->trigger.event_name = ('\0' != *row[10] ? zbx_strdup(NULL, row[10]) :
NULL);
+ event->trigger.cache = NULL;
}
}
}
@@ -212,26 +213,6 @@ void zbx_db_get_events_by_eventids(zbx_vector_uint64_t *eventids, zbx_vector_ptr
/******************************************************************************
* *
- * Function: zbx_db_trigger_clean *
- * *
- * Purpose: frees resources allocated to store trigger data *
- * *
- * Parameters: trigger - *
- * *
- ******************************************************************************/
-void zbx_db_trigger_clean(DB_TRIGGER *trigger)
-{
- zbx_free(trigger->description);
- zbx_free(trigger->expression);
- zbx_free(trigger->recovery_expression);
- zbx_free(trigger->comments);
- zbx_free(trigger->url);
- zbx_free(trigger->opdata);
- zbx_free(trigger->event_name);
-}
-
-/******************************************************************************
- * *
* Function: zbx_free_event *
* *
* Purpose: deallocate memory allocated in function 'get_db_events_info' *
diff --git a/src/libs/zbxdbhigh/trigger.c b/src/libs/zbxdbhigh/trigger.c
index 772b85e9f3d..82078904c9d 100644
--- a/src/libs/zbxdbhigh/trigger.c
+++ b/src/libs/zbxdbhigh/trigger.c
@@ -32,6 +32,14 @@
#define ZBX_FLAGS_TRIGGER_CREATE_EVENT \
(ZBX_FLAGS_TRIGGER_CREATE_TRIGGER_EVENT | ZBX_FLAGS_TRIGGER_CREATE_INTERNAL_EVENT)
+/* DB_TRIGGER cached objects */
+typedef enum
+{
+ ZBX_DB_TRIGGER_CACHE_EVAL_CTX,
+ ZBX_DB_TRIGGER_CACHE_EVAL_CTX_R,
+ ZBX_DB_TRIGGER_CACHE_EVAL_CTX_MACROS,
+}
+zbx_db_trigger_cache_t;
/******************************************************************************
* *
@@ -119,7 +127,7 @@ static int zbx_process_trigger(struct _DC_TRIGGER *trigger, zbx_vector_ptr_t *di
{
zbx_add_event(EVENT_SOURCE_TRIGGERS, EVENT_OBJECT_TRIGGER, trigger->triggerid,
&trigger->timespec, new_value, trigger->description,
- trigger->expression_orig, trigger->recovery_expression_orig,
+ trigger->expression, trigger->recovery_expression,
trigger->priority, trigger->type, &trigger->tags,
trigger->correlation_mode, trigger->correlation_tag, trigger->value, trigger->opdata,
trigger->event_name, NULL);
@@ -303,3 +311,377 @@ void zbx_append_trigger_diff(zbx_vector_ptr_t *trigger_diff, zbx_uint64_t trigge
zbx_vector_ptr_append(trigger_diff, diff);
}
+
+
+/* temporary cache of trigger related data */
+typedef struct
+{
+ zbx_uint64_t flags;
+ zbx_eval_context_t eval_ctx;
+ zbx_eval_context_t eval_ctx_r;
+ zbx_vector_uint64_t hostids;
+}
+zbx_trigger_cache_t;
+
+/* related trigger data caching states */
+typedef enum
+{
+ ZBX_TRIGGER_CACHE_EVAL_CTX,
+ ZBX_TRIGGER_CACHE_EVAL_CTX_R,
+ ZBX_TRIGGER_CACHE_EVAL_CTX_MACROS,
+ ZBX_TRIGGER_CACHE_HOSTIDS,
+}
+zbx_trigger_cache_state_t;
+
+/******************************************************************************
+ * *
+ * Function: db_trigger_get_cache *
+ * *
+ * Purpose: get trigger cache with the requested data cached *
+ * *
+ * Parameters: trigger - [IN] the trigger *
+ * state - [IN] the required cache state *
+ * *
+ ******************************************************************************/
+static zbx_trigger_cache_t *db_trigger_get_cache(const DB_TRIGGER *trigger, zbx_trigger_cache_state_t state)
+{
+ zbx_trigger_cache_t *cache;
+ char *error = NULL;
+ zbx_uint64_t flag = __UINT64_C(1) << state;
+ zbx_vector_uint64_t functionids;
+
+ if (NULL == trigger->cache)
+ {
+ cache = (zbx_trigger_cache_t *)zbx_malloc(NULL, sizeof(zbx_trigger_cache_t));
+ cache->flags = 0;
+ ((DB_TRIGGER *)trigger)->cache = cache;
+ }
+ else
+ cache = (zbx_trigger_cache_t *)trigger->cache;
+
+ if (0 != (cache->flags & flag))
+ return 0 != (cache->flags & (flag << 32)) ? cache : NULL;
+
+ cache->flags |= flag;
+
+ switch (state)
+ {
+ case ZBX_TRIGGER_CACHE_EVAL_CTX:
+ if ('\0' == *trigger->expression)
+ return NULL;
+
+ if (FAIL == zbx_eval_parse_expression(&cache->eval_ctx, trigger->expression,
+ ZBX_EVAL_TRIGGER_EXPRESSION, &error))
+ {
+ zbx_free(error);
+ return NULL;
+ }
+ break;
+ case ZBX_TRIGGER_CACHE_EVAL_CTX_R:
+ if ('\0' == *trigger->recovery_expression)
+ return NULL;
+
+ if (FAIL == zbx_eval_parse_expression(&cache->eval_ctx_r, trigger->recovery_expression,
+ ZBX_EVAL_TRIGGER_EXPRESSION, &error))
+ {
+ zbx_free(error);
+ return NULL;
+ }
+ break;
+ case ZBX_DB_TRIGGER_CACHE_EVAL_CTX_MACROS:
+ if (NULL == db_trigger_get_cache(trigger, ZBX_TRIGGER_CACHE_EVAL_CTX))
+ return NULL;
+ zbx_dc_eval_expand_user_macros(&cache->eval_ctx);
+ break;
+ case ZBX_TRIGGER_CACHE_HOSTIDS:
+ zbx_vector_uint64_create(&cache->hostids);
+ zbx_vector_uint64_create(&functionids);
+ zbx_db_trigger_get_all_functionids(trigger, &functionids);
+ DCget_hostids_by_functionids(&functionids, &cache->hostids);
+ zbx_vector_uint64_destroy(&functionids);
+ break;
+ default:
+ return NULL;
+ }
+
+ cache->flags |= (flag << 32);
+
+ return cache;
+}
+
+/******************************************************************************
+ * *
+ * Function: trigger_cache_free *
+ * *
+ * Purpose: free trigger cache *
+ * *
+ * Parameters: cache - [IN] the trigger cache *
+ * *
+ ******************************************************************************/
+static void trigger_cache_free(zbx_trigger_cache_t *cache)
+{
+ if (0 != (cache->flags & (__UINT64_C(1) << ZBX_TRIGGER_CACHE_EVAL_CTX << 32)))
+ zbx_eval_clear(&cache->eval_ctx);
+
+ if (0 != (cache->flags & (__UINT64_C(1) << ZBX_TRIGGER_CACHE_EVAL_CTX_R << 32)))
+ zbx_eval_clear(&cache->eval_ctx_r);
+
+ if (0 != (cache->flags & (__UINT64_C(1) << ZBX_TRIGGER_CACHE_HOSTIDS << 32)))
+ zbx_vector_uint64_destroy(&cache->hostids);
+
+ zbx_free(cache);
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_db_trigger_get_all_functionids *
+ * *
+ * Purpose: get functionids from trigger expression and recovery expression *
+ * *
+ * Parameters: trigger - [IN] the trigger *
+ * functionids - [OUT] the extracted functionids *
+ * *
+ * Comments: This function will cache parsed expressions in the trigger. *
+ * *
+ ******************************************************************************/
+void zbx_db_trigger_get_all_functionids(const DB_TRIGGER *trigger, zbx_vector_uint64_t *functionids)
+{
+ zbx_trigger_cache_t *cache;
+
+ if (NULL != (cache = db_trigger_get_cache(trigger, ZBX_TRIGGER_CACHE_EVAL_CTX)))
+ zbx_eval_get_functionids(&cache->eval_ctx, functionids);
+
+ if (NULL != (cache = db_trigger_get_cache(trigger, ZBX_TRIGGER_CACHE_EVAL_CTX_R)))
+ zbx_eval_get_functionids(&cache->eval_ctx_r, functionids);
+
+ zbx_vector_uint64_sort(functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
+ zbx_vector_uint64_uniq(functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_db_trigger_get_functionids *
+ * *
+ * Purpose: get functionids from trigger expression *
+ * *
+ * Parameters: trigger - [IN] the trigger *
+ * functionids - [OUT] the extracted functionids *
+ * *
+ * Comments: This function will cache parsed expressions in the trigger. *
+ * *
+ ******************************************************************************/
+void zbx_db_trigger_get_functionids(const DB_TRIGGER *trigger, zbx_vector_uint64_t *functionids)
+{
+ zbx_trigger_cache_t *cache;
+
+ if (NULL != (cache = db_trigger_get_cache(trigger, ZBX_TRIGGER_CACHE_EVAL_CTX)))
+ zbx_eval_get_functionids(&cache->eval_ctx, functionids);
+
+ zbx_vector_uint64_sort(functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
+ zbx_vector_uint64_uniq(functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
+}
+/******************************************************************************
+ * *
+ * Function: zbx_db_trigger_get_constant *
+ * *
+ * Purpose: get trigger expression constant at the specified location *
+ * *
+ * Parameters: trigger - [IN] the trigger *
+ * index - [IN] the constant index, starting with 1 *
+ * out - [IN] the constant value, if exists *
+ * *
+ * Return value: SUCCEED - the expression was parsed and constant extracted *
+ * (if the index was valid) *
+ * FAIL - the expression failed to parse *
+ * *
+ * Comments: This function will cache parsed expressions in the trigger. *
+ * *
+ ******************************************************************************/
+int zbx_db_trigger_get_constant(const DB_TRIGGER *trigger, int index, char **out)
+{
+ zbx_trigger_cache_t *cache;
+
+ if (NULL == (cache = db_trigger_get_cache(trigger, ZBX_TRIGGER_CACHE_EVAL_CTX_MACROS)))
+ return FAIL;
+
+ zbx_eval_get_constant(&cache->eval_ctx, index, out);
+
+ return SUCCEED;
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_db_trigger_get_itemid *
+ * *
+ * Purpose: get the Nth function item from trigger expression *
+ * *
+ * Parameters: trigger - [IN] the trigger *
+ * index - [IN] the function index *
+ * itemid - [IN] the function itemid *
+ * *
+ * Comments: SUCCEED - the itemid was extracted successfully *
+ * FAIL - otherwise *
+ * *
+ ******************************************************************************/
+int zbx_db_trigger_get_itemid(const DB_TRIGGER *trigger, int index, zbx_uint64_t *itemid)
+{
+ int i, ret = FAIL;
+ zbx_trigger_cache_t *cache;
+
+ if (NULL == (cache = db_trigger_get_cache(trigger, ZBX_TRIGGER_CACHE_EVAL_CTX)))
+ return FAIL;
+
+ for (i = 0; i < cache->eval_ctx.stack.values_num; i++)
+ {
+ zbx_eval_token_t *token = &cache->eval_ctx.stack.values[i];
+ zbx_uint64_t functionid;
+ DC_FUNCTION function;
+ int errcode;
+
+ if (ZBX_EVAL_TOKEN_FUNCTIONID != token->type || (int)token->opt + 1 != index)
+ continue;
+
+ switch (token->value.type)
+ {
+ case ZBX_VARIANT_UI64:
+ functionid = token->value.data.ui64;
+ break;
+ case ZBX_VARIANT_NONE:
+ if (SUCCEED != is_uint64_n(cache->eval_ctx.expression + token->loc.l + 1,
+ token->loc.r - token->loc.l - 1, &functionid))
+ {
+ return FAIL;
+ }
+ zbx_variant_set_ui64(&token->value, functionid);
+ break;
+ default:
+ return FAIL;
+ }
+
+ DCconfig_get_functions_by_functionids(&function, &functionid, &errcode, 1);
+
+ if (SUCCEED == errcode)
+ {
+ *itemid = function.itemid;
+ ret = SUCCEED;
+ }
+
+ DCconfig_clean_functions(&function, &errcode, 1);
+ break;
+ }
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_db_trigger_get_itemids *
+ * *
+ * Purpose: get unique itemids of trigger functions in the order at they are *
+ * written in expression *
+ * *
+ * Parameters: trigger - [IN] the trigger *
+ * itemids - [IN] the function itemids *
+ * *
+ ******************************************************************************/
+void zbx_db_trigger_get_itemids(const DB_TRIGGER *trigger, zbx_vector_uint64_t *itemids)
+{
+ zbx_vector_uint64_t functionids, functionids_ordered;
+ zbx_trigger_cache_t *cache;
+
+ if (NULL == (cache = db_trigger_get_cache(trigger, ZBX_TRIGGER_CACHE_EVAL_CTX)))
+ return;
+
+ zbx_vector_uint64_create(&functionids);
+ zbx_vector_uint64_create(&functionids_ordered);
+
+ zbx_eval_get_functionids_ordered(&cache->eval_ctx, &functionids_ordered);
+
+ if (0 != functionids_ordered.values_num)
+ {
+ DC_FUNCTION *function, *functions;
+ int i, *errcodes;
+
+ zbx_vector_uint64_append_array(&functionids, functionids_ordered.values,
+ functionids_ordered.values_num);
+
+ zbx_vector_uint64_sort(&functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
+ zbx_vector_uint64_uniq(&functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
+
+ functions = (DC_FUNCTION *)zbx_malloc(NULL, sizeof(DC_FUNCTION) * functionids.values_num);
+ errcodes = (int *)zbx_malloc(NULL, sizeof(int) * functionids.values_num);
+
+ DCconfig_get_functions_by_functionids(functions, functionids.values, errcodes,
+ functionids.values_num);
+
+ for (i = 0; i < functionids_ordered.values_num; i++)
+ {
+ if (NULL != (function = bsearch(&functionids_ordered.values[i], functions,
+ functionids.values_num, sizeof(DC_FUNCTION),
+ ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
+ {
+ if (FAIL == zbx_vector_uint64_search(itemids, function->itemid,
+ ZBX_DEFAULT_UINT64_COMPARE_FUNC))
+ {
+ zbx_vector_uint64_append(itemids, function->itemid);
+ }
+ }
+ }
+
+ DCconfig_clean_functions(functions, errcodes, functionids.values_num);
+ zbx_free(functions);
+ zbx_free(errcodes);
+ }
+
+ zbx_vector_uint64_destroy(&functionids_ordered);
+ zbx_vector_uint64_destroy(&functionids);
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_db_trigger_get_all_hostids *
+ * *
+ * Purpose: get hostids from trigger expression and recovery expression *
+ * *
+ * Parameters: trigger - [IN] the trigger *
+ * hostids - [OUT] the extracted hostids *
+ * *
+ * Return value: SUCCEED - the hostids vector was returned (but can be empty *
+ * FAIL - otherwise *
+ * *
+ * Comments: This function will cache parsed expressions in the trigger. *
+ * *
+ ******************************************************************************/
+int zbx_db_trigger_get_all_hostids(const DB_TRIGGER *trigger, const zbx_vector_uint64_t **hostids)
+{
+ zbx_trigger_cache_t *cache;
+
+ if (NULL == (cache = db_trigger_get_cache(trigger, ZBX_TRIGGER_CACHE_HOSTIDS)))
+ return FAIL;
+
+ *hostids = &cache->hostids;
+ return SUCCEED;
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_db_trigger_clean *
+ * *
+ * Purpose: frees resources allocated to store trigger data *
+ * *
+ * Parameters: trigger - *
+ * *
+ ******************************************************************************/
+void zbx_db_trigger_clean(DB_TRIGGER *trigger)
+{
+ zbx_free(trigger->description);
+ zbx_free(trigger->expression);
+ zbx_free(trigger->recovery_expression);
+ zbx_free(trigger->comments);
+ zbx_free(trigger->url);
+ zbx_free(trigger->opdata);
+ zbx_free(trigger->event_name);
+
+ if (NULL != trigger->cache)
+ trigger_cache_free((zbx_trigger_cache_t *)trigger->cache);
+}
diff --git a/src/libs/zbxeval/execute.c b/src/libs/zbxeval/execute.c
index 649578de985..e1431ffc742 100644
--- a/src/libs/zbxeval/execute.c
+++ b/src/libs/zbxeval/execute.c
@@ -22,6 +22,7 @@
#include "zbxalgo.h"
#include "zbxserver.h"
+#include "eval.h"
static zbx_variant_t var_zero = {.type = ZBX_VARIANT_DBL, .data = {.dbl = 0}};
@@ -360,7 +361,7 @@ static int eval_execute_push_value(const zbx_eval_context_t *ctx, const zbx_eval
* FAIL - otherwise *
* *
******************************************************************************/
-static int eval_compare_token(const zbx_eval_context_t *ctx, const zbx_strloc_t *loc, const char *text,
+int eval_compare_token(const zbx_eval_context_t *ctx, const zbx_strloc_t *loc, const char *text,
size_t len)
{
if (loc->r - loc->l + 1 != len)
diff --git a/src/libs/zbxeval/misc.c b/src/libs/zbxeval/misc.c
index d2fb08e2d5d..1641d592d00 100644
--- a/src/libs/zbxeval/misc.c
+++ b/src/libs/zbxeval/misc.c
@@ -25,36 +25,393 @@
#include "zbxvariant.h"
#include "zbxserialize.h"
#include "zbxserver.h"
+#include "eval.h"
+
+#define ZBX_EVAL_STATIC_BUFFER_SIZE 4096
/******************************************************************************
* *
- * Function: zbx_eval_get_functionids *
+ * Function: reserve_buffer *
+ * *
+ * Purpose: reserve number of bytes in the specified buffer, reallocating if *
+ * necessary *
+ * *
+ * Parameters: buffer - [IN/OUT] the buffer *
+ * buffer_size - [INT/OUT] the deserialized value *
+ * reserve - [IN] the number of bytes to reserve *
+ * ptr - [IN/OUT] a pointer to an offset in buffer *
+ * *
+ * Comments: Initially static buffer is used, allocating dynamic buffer when *
+ * static buffer is too small. *
+ * *
+ ******************************************************************************/
+static void reserve_buffer(unsigned char **buffer, size_t *buffer_size, size_t reserve, unsigned char **ptr)
+{
+ size_t offset = *ptr - *buffer, new_size;
+
+ if (offset + reserve <= *buffer_size)
+ return;
+
+ new_size = *buffer_size * 1.5;
+
+ if (ZBX_EVAL_STATIC_BUFFER_SIZE == *buffer_size)
+ {
+ unsigned char *old = *buffer;
+
+ *buffer = zbx_malloc(NULL, new_size);
+ memcpy(*buffer, old, offset);
+ }
+ else
+ *buffer = zbx_realloc(*buffer, new_size);
+
+ *buffer_size = new_size;
+ *ptr = *buffer + offset;
+}
+
+static void serialize_variant(unsigned char **buffer, size_t *size, const zbx_variant_t *value,
+ unsigned char **ptr)
+{
+ size_t len;
+
+ reserve_buffer(buffer, size, 1, ptr);
+ **ptr = value->type;
+ (*ptr)++;
+
+ switch (value->type)
+ {
+ case ZBX_VARIANT_UI64:
+ reserve_buffer(buffer, size, sizeof(value->data.ui64), ptr);
+ *ptr += zbx_serialize_uint64(*ptr, value->data.ui64);
+ break;
+ case ZBX_VARIANT_DBL:
+ reserve_buffer(buffer, size, sizeof(value->data.dbl), ptr);
+ *ptr += zbx_serialize_double(*ptr, value->data.dbl) + 1;
+ break;
+ case ZBX_VARIANT_STR:
+ len = strlen(value->data.str) + 1;
+ reserve_buffer(buffer, size, len, ptr);
+ memcpy(*ptr, value->data.str, len);
+ *ptr += len;
+ break;
+ case ZBX_VARIANT_NONE:
+ break;
+ default:
+ zabbix_log(LOG_LEVEL_DEBUG, "TYPE: %d", value->type);
+ THIS_SHOULD_NEVER_HAPPEN;
+ (*ptr)[-1] = ZBX_VARIANT_NONE;
+ break;
+ }
+}
+
+static zbx_uint32_t deserialize_variant(const unsigned char *ptr, zbx_variant_t *value)
+{
+ const unsigned char *start = ptr;
+ unsigned char type;
+ zbx_uint64_t ui64;
+ double dbl;
+ char *str;
+ size_t len;
+
+ ptr += zbx_deserialize_char(ptr, &type);
+
+ switch (type)
+ {
+ case ZBX_VARIANT_UI64:
+ ptr += zbx_deserialize_uint64(ptr, &ui64);
+ zbx_variant_set_ui64(value, ui64);
+ break;
+ case ZBX_VARIANT_DBL:
+ ptr += zbx_deserialize_double(ptr, &dbl);
+ zbx_variant_set_dbl(value, dbl);
+ break;
+ case ZBX_VARIANT_STR:
+ len = strlen((const char *)ptr) + 1;
+ str = zbx_malloc(NULL, len);
+ memcpy(str, ptr, len);
+ zbx_variant_set_str(value, str);
+ ptr += len;
+ break;
+ case ZBX_VARIANT_NONE:
+ zbx_variant_set_none(value);
+ break;
+ default:
+ THIS_SHOULD_NEVER_HAPPEN;
+ zbx_variant_set_none(value);
+ break;
+ }
+
+ return ptr - start;
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_eval_serialize *
* *
- * Purpose: extract functionids from the parsed expression *
+ * Purpose: serialize evaluation context into buffer *
* *
* Parameters: ctx - [IN] the evaluation context *
- * functionids - [OUT] the extracted functionids *
+ * malloc_func - [IN] the buffer memory allocation function, *
+ * optional (by default the buffer is *
+ * allocated in heap) *
+ * data - [OUT] the buffer with serialized evaluation context *
+ * *
+ * Comments: Location of the replaced tokens (with token.value set) are not *
+ * serialized, making it impossible to reconstruct the expression *
+ * text with replaced tokens. *
+ * Context serialization/deserialization must be used for *
+ * context caching. *
+ * *
+ * Return value: The size of serialized data. *
* *
******************************************************************************/
-void zbx_eval_get_functionids(const zbx_eval_context_t *ctx, zbx_vector_uint64_t *functionids)
+size_t zbx_eval_serialize(const zbx_eval_context_t *ctx, zbx_mem_malloc_func_t malloc_func,
+ unsigned char **data)
{
- int i;
+ int i;
+ unsigned char buffer_static[ZBX_EVAL_STATIC_BUFFER_SIZE], *buffer = buffer_static, *ptr = buffer, len_buff[4];
+ size_t buffer_size = ZBX_EVAL_STATIC_BUFFER_SIZE;
+ zbx_uint32_t len, len_offset;
+
+ if (NULL == malloc_func)
+ malloc_func = ZBX_DEFAULT_MEM_MALLOC_FUNC;
+
+ ptr += zbx_serialize_uint31_compact(ptr, ctx->stack.values_num);
for (i = 0; i < ctx->stack.values_num; i++)
{
+ const zbx_eval_token_t *token = &ctx->stack.values[i];
+
+ reserve_buffer(&buffer, &buffer_size, 20, &ptr);
+
+ ptr += zbx_serialize_value(ptr, token->type);
+ ptr += zbx_serialize_uint31_compact(ptr, token->opt);
+
+ serialize_variant(&buffer, &buffer_size, &token->value, &ptr);
+
+ ptr += zbx_serialize_uint31_compact(ptr, token->loc.l);
+ ptr += zbx_serialize_uint31_compact(ptr, token->loc.r);
+ }
+
+ len = ptr - buffer;
+
+ len_offset = zbx_serialize_uint31_compact(len_buff, len);
+
+ *data = malloc_func(NULL, len + len_offset);
+ memcpy(*data, len_buff, len_offset);
+ memcpy(*data + len_offset, buffer, len);
+
+ if (buffer != buffer_static)
+ zbx_free(buffer);
+
+ return len + len_offset;
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_eval_deserialize *
+ * *
+ * Purpose: deserialize evaluation context from buffer *
+ * *
+ * Parameters: ctx - [OUT] the evaluation context *
+ * expression - [IN] the expression the evaluation context was *
+ * created from *
+ * rules - [IN] the composition and evaluation rules *
+ * data - [IN] the buffer with serialized context *
+ * *
+ ******************************************************************************/
+void zbx_eval_deserialize(zbx_eval_context_t *ctx, const char *expression, zbx_uint64_t rules,
+ const unsigned char *data)
+{
+ zbx_uint32_t i, tokens_num, len, pos;
+
+ memset(ctx, 0, sizeof(zbx_eval_context_t));
+ ctx->expression = expression;
+ ctx->rules = rules;
+
+ data += zbx_deserialize_uint31_compact(data, &len);
+ data += zbx_deserialize_uint31_compact(data, &tokens_num);
+ zbx_vector_eval_token_create(&ctx->stack);
+ zbx_vector_eval_token_reserve(&ctx->stack, tokens_num);
+ ctx->stack.values_num = tokens_num;
+
+ for (i = 0; i < tokens_num; i++)
+ {
zbx_eval_token_t *token = &ctx->stack.values[i];
- if (ZBX_EVAL_TOKEN_FUNCTIONID == token->type)
+ data += zbx_deserialize_value(data, &token->type);
+ data += zbx_deserialize_uint31_compact(data, &token->opt);
+ data += deserialize_variant(data, &token->value);
+
+ data += zbx_deserialize_uint31_compact(data, &pos);
+ token->loc.l = pos;
+ data += zbx_deserialize_uint31_compact(data, &pos);
+ token->loc.r = pos;
+ }
+}
+
+static int compare_tokens_by_loc(const void *d1, const void *d2)
+{
+ const zbx_eval_token_t *t1 = *(const zbx_eval_token_t **)d1;
+ const zbx_eval_token_t *t2 = *(const zbx_eval_token_t **)d2;
+
+ ZBX_RETURN_IF_NOT_EQUAL(t1->loc.l, t2->loc.l);
+ return 0;
+}
+
+/******************************************************************************
+ * *
+ * Function: eval_token_print_alloc *
+ * *
+ * Purpose: print token into string quoting/escaping if necessary *
+ * *
+ * Parameters: ctx - [IN] the evaluation context *
+ * str - [IN/OUT] the output buffer *
+ * str_alloc - [IN/OUT] the output buffer size *
+ * str_offset - [IN/OUT] the output buffer offset *
+ * token - [IN] the token to print *
+ * *
+ ******************************************************************************/
+static void eval_token_print_alloc(const zbx_eval_context_t *ctx, char **str, size_t *str_alloc, size_t *str_offset,
+ const zbx_eval_token_t *token)
+{
+ int quoted = 0, len, check_value = 0;
+ const char *src, *value_str;
+ char *dst;
+ size_t size;
+
+ if (ZBX_VARIANT_NONE == token->value.type)
+ return;
+
+ switch (token->type)
+ {
+ case ZBX_EVAL_TOKEN_VAR_STR:
+ quoted = 1;
+ break;
+ case ZBX_EVAL_TOKEN_VAR_MACRO:
+ if (0 != (ctx->rules & ZBX_EVAL_QUOTE_MACRO))
+ check_value = 1;
+ break;
+ case ZBX_EVAL_TOKEN_VAR_USERMACRO:
+ if (0 != (ctx->rules & ZBX_EVAL_QUOTE_USERMACRO))
+ check_value = 1;
+ break;
+ case ZBX_EVAL_TOKEN_VAR_LLDMACRO:
+ if (0 != (ctx->rules & ZBX_EVAL_QUOTE_LLDMACRO))
+ check_value = 1;
+ break;
+ case ZBX_EVAL_TOKEN_FUNCTIONID:
+ check_value = 1;
+ break;
+ }
+
+ if (0 != check_value)
+ {
+ if (ZBX_VARIANT_STR == token->value.type && (SUCCEED != zbx_number_parse(token->value.data.str, &len) ||
+ strlen(token->value.data.str) != (size_t)len))
{
- zbx_uint64_t functionid;
+ quoted = 1;
+ }
+ }
- if (SUCCEED == is_uint64_n(ctx->expression + token->loc.l + 1, token->loc.r - token->loc.l - 1,
- &functionid))
- {
- zbx_vector_uint64_append(functionids, functionid);
- }
+ value_str = zbx_variant_value_desc(&token->value);
+
+ if (0 == quoted)
+ {
+ zbx_strcpy_alloc(str, str_alloc, str_offset, value_str);
+ return;
+ }
+
+ for (size = 2, src = value_str; '\0' != *src; src++)
+ {
+ switch (*src)
+ {
+ case '\\':
+ case '"':
+ size++;
+ }
+ size++;
+ }
+
+ if (*str_alloc <= *str_offset + size)
+ {
+ if (0 == *str_alloc)
+ *str_alloc = size;
+
+ do
+ {
+ *str_alloc *= 2;
+ }
+ while (*str_alloc - *str_offset <= size);
+
+ *str = zbx_realloc(*str, *str_alloc);
+ }
+
+ dst = *str + *str_offset;
+ *dst++ = '"';
+
+ for (src = value_str; '\0' != *src; src++, dst++)
+ {
+ switch (*src)
+ {
+ case '\\':
+ case '"':
+ *dst++ = '\\';
+ break;
+ }
+
+ *dst = *src;
+ }
+
+ *dst++ = '"';
+ *dst = '\0';
+ *str_offset += size;
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_eval_compose_expression *
+ * *
+ * Purpose: compose expression by replacing processed tokens (with values) in *
+ * the original expression *
+ * *
+ * Parameters: ctx - [IN] the evaluation context *
+ * expression - [OUT] the composed expression *
+ * *
+ ******************************************************************************/
+void zbx_eval_compose_expression(const zbx_eval_context_t *ctx, char **expression)
+{
+ zbx_vector_ptr_t tokens;
+ const zbx_eval_token_t *token;
+ int i;
+ size_t pos = 0, expression_alloc = 0, expression_offset = 0;
+
+ zbx_vector_ptr_create(&tokens);
+
+ for (i = 0; i < ctx->stack.values_num; i++)
+ {
+ if (ZBX_VARIANT_NONE != ctx->stack.values[i].value.type)
+ zbx_vector_ptr_append(&tokens, &ctx->stack.values[i]);
+ }
+
+ zbx_vector_ptr_sort(&tokens, compare_tokens_by_loc);
+
+ for (i = 0; i < tokens.values_num; i++)
+ {
+ token = (const zbx_eval_token_t *)tokens.values[i];
+
+ if (0 != token->loc.l)
+ {
+ zbx_strncpy_alloc(expression, &expression_alloc, &expression_offset, ctx->expression + pos,
+ token->loc.l - pos);
}
+ pos = token->loc.r + 1;
+ eval_token_print_alloc(ctx, expression, &expression_alloc, &expression_offset, token);
}
+
+ if ('\0' != ctx->expression[pos])
+ zbx_strcpy_alloc(expression, &expression_alloc, &expression_offset, ctx->expression + pos);
+
+ zbx_vector_ptr_destroy(&tokens);
}
/******************************************************************************
@@ -93,7 +450,7 @@ void zbx_eval_expand_user_macros(const zbx_eval_context_t *ctx, zbx_uint64_t *ho
continue;
}
- tmp = zbx_strloc_unquote_dyn(ctx->expression, &token->loc);
+ tmp = zbx_strloc_get(ctx->expression, &token->loc);
value = resolver_cb(tmp, strlen(tmp), hostids, hostids_num);
zbx_free(tmp);
break;
@@ -130,3 +487,308 @@ void zbx_eval_set_exception(zbx_eval_context_t *ctx, char *message)
zbx_variant_set_str(&token->value, message);
(++token)->type = ZBX_EVAL_TOKEN_EXCEPTION;
}
+
+/******************************************************************************
+ * *
+ * Function: expression_extract_functionid *
+ * *
+ * Purpose: extract functionid from token *
+ * *
+ * Parameters: expression - [IN] the original expression *
+ * token - [IN] the token *
+ * functionid - [OUT] the extracted functionid *
+ * expression - [IN] the original expression *
+ * *
+ * Return value: SUCCEED - functionid was extracted successfully *
+ * FAIL - otherwise (incorrect token or invalid data) *
+ * *
+ * Comment: The extracted functionid will be cached as token value, so the *
+ * next time it can be used without extracting the value from *
+ * expression. *
+ * *
+ ******************************************************************************/
+static int expression_extract_functionid(const char *expression, zbx_eval_token_t *token, zbx_uint64_t *functionid)
+{
+ if (ZBX_EVAL_TOKEN_FUNCTIONID != token->type)
+ return FAIL;
+
+ switch (token->value.type)
+ {
+ case ZBX_VARIANT_UI64:
+ *functionid = token->value.data.ui64;
+ return SUCCEED;
+ case ZBX_VARIANT_NONE:
+ if (SUCCEED != is_uint64_n(expression + token->loc.l + 1, token->loc.r - token->loc.l - 1,
+ functionid))
+ {
+ THIS_SHOULD_NEVER_HAPPEN;
+ break;
+ }
+ zbx_variant_set_ui64(&token->value, *functionid);
+ return SUCCEED;
+ }
+
+ return FAIL;
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_eval_deserialize_dyn *
+ * *
+ * Purpose: deserialize expression and extract specified tokens into values *
+ * *
+ * Parameters: data - [IN] serialized expression *
+ * expression - [IN] the original expression *
+ * triggerids *
+ * *
+ * Return value: Expression evaluation context. *
+ * *
+ ******************************************************************************/
+zbx_eval_context_t *zbx_eval_deserialize_dyn(const unsigned char *data, const char *expression,
+ zbx_uint64_t mask)
+{
+ zbx_eval_context_t *ctx;
+ int i;
+ zbx_uint64_t functionid;
+ char *value;
+
+ ctx = (zbx_eval_context_t *)zbx_malloc(NULL, sizeof(zbx_eval_context_t));
+ zbx_eval_deserialize(ctx, expression, ZBX_EVAL_TRIGGER_EXPRESSION, data);
+
+ for (i = 0; i < ctx->stack.values_num; i++)
+ {
+ zbx_eval_token_t *token = &ctx->stack.values[i];
+
+ switch (token->type)
+ {
+ case ZBX_EVAL_TOKEN_FUNCTIONID:
+ if (0 == (mask & ZBX_EVAL_EXTRACT_FUNCTIONID))
+ continue;
+ expression_extract_functionid(expression, token, &functionid);
+ break;
+ case ZBX_EVAL_TOKEN_VAR_STR:
+ if (0 != (mask & ZBX_EVAL_EXTRACT_VAR_STR) && ZBX_VARIANT_NONE == token->value.type)
+ {
+ /* extract string variable value for macro resolving */
+ value = zbx_strloc_get(expression, &token->loc);
+ zbx_variant_set_str(&token->value, value);
+ }
+ break;
+ case ZBX_EVAL_TOKEN_VAR_MACRO:
+ if (0 != (mask & ZBX_EVAL_EXTRACT_VAR_MACRO) && ZBX_VARIANT_NONE == token->value.type)
+ {
+ /* extract macro for resolving */
+ value = zbx_strloc_get(expression, &token->loc);
+ zbx_variant_set_str(&token->value, value);
+ }
+ break;
+ }
+ }
+
+ return ctx;
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_eval_get_functionids *
+ * *
+ * Purpose: get functionids from parsed expression *
+ * *
+ * Parameters: ctx - [IN] the evaluation context *
+ * functionids - [OUT] the extracted functionids *
+ * *
+ ******************************************************************************/
+void zbx_eval_get_functionids(zbx_eval_context_t *ctx, zbx_vector_uint64_t *functionids)
+{
+ int i;
+
+ for (i = 0; i < ctx->stack.values_num; i++)
+ {
+ zbx_eval_token_t *token = &ctx->stack.values[i];
+ zbx_uint64_t functionid;
+
+ if (SUCCEED == expression_extract_functionid(ctx->expression, token, &functionid))
+ zbx_vector_uint64_append(functionids, functionid);
+ }
+
+ zbx_vector_uint64_sort(functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
+ zbx_vector_uint64_uniq(functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_eval_get_functionids_ordered *
+ * *
+ * Purpose: get functionids from parsed expression in the order as they *
+ * were written
+ * *
+ * Parameters: ctx - [IN] the evaluation context *
+ * functionids - [OUT] the extracted functionids *
+ * *
+ ******************************************************************************/
+void zbx_eval_get_functionids_ordered(zbx_eval_context_t *ctx, zbx_vector_uint64_t *functionids)
+{
+ int i;
+ zbx_vector_ptr_t tokens;
+
+ zbx_vector_ptr_create(&tokens);
+
+ for (i = 0; i < ctx->stack.values_num; i++)
+ {
+ if (ZBX_EVAL_TOKEN_FUNCTIONID == ctx->stack.values[i].type)
+ zbx_vector_ptr_append(&tokens, &ctx->stack.values[i]);
+ }
+
+ zbx_vector_ptr_sort(&tokens, compare_tokens_by_loc);
+
+ for (i = 0; i < tokens.values_num; i++)
+ {
+ zbx_eval_token_t *token = (zbx_eval_token_t *)tokens.values[i];
+ zbx_uint64_t functionid;
+
+ if (SUCCEED == expression_extract_functionid(ctx->expression, token, &functionid))
+ zbx_vector_uint64_append(functionids, functionid);
+ }
+
+ zbx_vector_ptr_destroy(&tokens);
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_eval_check_timer_functions *
+ * *
+ * Purpose: check if expression contains timer function calls (date, time, *
+ * now, dayofweek, dayofmonth) *
+ * *
+ * Parameters: ctx - [IN] the evaluation context *
+ * *
+ * Return value: SUCCEED - expression contains timer function call(s) *
+ * FAIL - otherwise *
+ * *
+ ******************************************************************************/
+int zbx_eval_check_timer_functions(const zbx_eval_context_t *ctx)
+{
+ int i;
+
+ for (i = 0; i < ctx->stack.values_num; i++)
+ {
+ zbx_eval_token_t *token = &ctx->stack.values[i];
+
+ if (ZBX_EVAL_TOKEN_FUNCTION != token->type)
+ continue;
+
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "date", ZBX_CONST_STRLEN("date")))
+ return SUCCEED;
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "time", ZBX_CONST_STRLEN("time")))
+ return SUCCEED;
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "now", ZBX_CONST_STRLEN("now")))
+ return SUCCEED;
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "dayofmonth", ZBX_CONST_STRLEN("dayofmonth")))
+ return SUCCEED;
+ if (SUCCEED == eval_compare_token(ctx, &token->loc, "dayofweek", ZBX_CONST_STRLEN("dayofweek")))
+ return SUCCEED;
+ }
+
+ return FAIL;
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_get_serialized_expression_functionids *
+ * *
+ * Purpose: extract functionids from serialized expression *
+ * *
+ * Parameters: expression - [IN] the original expression *
+ * data - [IN] the serialized expression *
+ * functionids - [OUT] the extracted functionids *
+ * *
+ ******************************************************************************/
+void zbx_get_serialized_expression_functionids(const char *expression, const unsigned char *data,
+ zbx_vector_uint64_t *functionids)
+{
+ zbx_uint32_t i, tokens_num, len, loc_l, loc_r, opt;
+ zbx_token_type_t type;
+ zbx_uint64_t functionid;
+ unsigned char var_type;
+
+ data += zbx_deserialize_uint31_compact(data, &len);
+ data += zbx_deserialize_uint31_compact(data, &tokens_num);
+
+ for (i = 0; i < tokens_num; i++)
+ {
+ data += zbx_deserialize_value(data, &type);
+ data += zbx_deserialize_uint31_compact(data, &opt);
+
+ data += zbx_deserialize_char(data, &var_type);
+
+ switch (var_type)
+ {
+ case ZBX_VARIANT_UI64:
+ data += sizeof(zbx_uint64_t);
+ break;
+ case ZBX_VARIANT_DBL:
+ data += sizeof(double);
+ break;
+ case ZBX_VARIANT_STR:
+ data += strlen((char *)data) + 1;
+ break;
+ case ZBX_VARIANT_NONE:
+ break;
+ default:
+ THIS_SHOULD_NEVER_HAPPEN;
+ return;
+ }
+
+ data += zbx_deserialize_uint31_compact(data, &loc_l);
+ data += zbx_deserialize_uint31_compact(data, &loc_r);
+
+ if (ZBX_EVAL_TOKEN_FUNCTIONID == type)
+ {
+ if (SUCCEED == is_uint64_n(expression + loc_l + 1, loc_r - loc_l - 1, &functionid))
+ zbx_vector_uint64_append(functionids, functionid);
+ else
+ THIS_SHOULD_NEVER_HAPPEN;
+ }
+ }
+
+ zbx_vector_uint64_sort(functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
+ zbx_vector_uint64_uniq(functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_eval_get_constant *
+ * *
+ * Purpose: the the Nth constant in expression *
+ * *
+ * Parameters: ctx - [IN] the evaluation context *
+ * index - [IN] the constant index *
+ * value - [OUT] the constant value *
+ * *
+ ******************************************************************************/
+void zbx_eval_get_constant(const zbx_eval_context_t *ctx, int index, char **value)
+{
+ int i;
+
+ for (i = 0; i < ctx->stack.values_num; i++)
+ {
+ zbx_eval_token_t *token = &ctx->stack.values[i];
+
+ switch (token->type)
+ {
+ case ZBX_EVAL_TOKEN_VAR_STR:
+ case ZBX_EVAL_TOKEN_VAR_NUM:
+ case ZBX_EVAL_TOKEN_VAR_USERMACRO:
+ if (index == (int)token->opt + 1)
+ {
+ zbx_free(*value);
+ if (ZBX_VARIANT_NONE != token->value.type)
+ *value = zbx_strdup(NULL, zbx_variant_value_desc(&token->value));
+ else
+ *value = zbx_strloc_get(ctx->expression, &token->loc);
+ return;
+ }
+ break;
+ }
+ }
+}
diff --git a/src/libs/zbxeval/parse.c b/src/libs/zbxeval/parse.c
index d3a22c85902..8730c1cd193 100644
--- a/src/libs/zbxeval/parse.c
+++ b/src/libs/zbxeval/parse.c
@@ -677,14 +677,14 @@ static void eval_append_arg_null(zbx_eval_context_t *ctx)
/******************************************************************************
* *
- * Function: eval_clean *
+ * Function: eval_clear *
* *
* Purpose: free resources allocated by evaluation context *
* *
* Parameters: ctx - [IN] the evaluation context *
* *
******************************************************************************/
-static void eval_clean(zbx_eval_context_t *ctx)
+static void eval_clear(zbx_eval_context_t *ctx)
{
int i;
@@ -902,210 +902,13 @@ out:
zbx_vector_eval_token_destroy(&ctx->ops);
if (SUCCEED != ret)
- eval_clean(ctx);
+ eval_clear(ctx);
return ret;
}
/******************************************************************************
* *
- * Function: serialize_uint31_compact *
- * *
- * Purpose: serialize 31 bit unsigned integer into utf-8 like byte stream *
- * *
- * Parameters: ptr - [OUT] the output buffer *
- * value - [IN] the value to serialize *
- * *
- * Return value: The number of bytes written to the buffer. *
- * *
- * Comments: This serialization method should be used with variables usually *
- * having small value while still supporting larger values. *
- * *
- ******************************************************************************/
-static zbx_uint32_t serialize_uint31_compact(unsigned char *ptr, zbx_uint32_t value)
-{
- if (0x7f >= value)
- {
- ptr[0] = (unsigned char)value;
- return 1;
- }
- else
- {
- unsigned char buf[6];
- int pos = sizeof(buf) - 1;
- zbx_uint32_t len;
-
- while (value > (zbx_uint32_t)(0x3f >> (sizeof(buf) - pos)))
- {
- buf[pos] = 0x80 | (value & 0x3f);
- value >>= 6;
- pos--;
- }
-
- buf[pos] = value | (0xfe << (pos + 1));
-
- len = sizeof(buf) - pos;
- memcpy(ptr, buf + pos, len);
- return len;
- }
-}
-
-/******************************************************************************
- * *
- * Function: deserialize_uint31_compact *
- * *
- * Purpose: deserialize 31 bit unsigned integer from utf-8 like byte stream *
- * *
- * Parameters: ptr - [IN] the byte strem *
- * value - [OUT] the deserialized value *
- * *
- * Return value: The number of bytes read from byte strean. *
- * *
- ******************************************************************************/
-static zbx_uint32_t deserialize_uint31_compact(const unsigned char *ptr, zbx_uint32_t *value)
-{
- if (0 == (*ptr & 0x80))
- {
- *value = *ptr;
- return 1;
- }
- else
- {
- int pos = 2, i;
-
- while (0 != (*ptr & (0x80 >> pos)))
- pos++;
-
- *value = *ptr & (0xff >> (pos + 1));
-
- for (i = 1; i < pos; i++)
- {
- *value <<= 6;
- *value |= (*(++ptr)) & 0x3f;
- }
-
- return pos;
- }
-}
-
-#define ZBX_EVAL_STATIC_BUFFER_SIZE 4096
-
-/******************************************************************************
- * *
- * Function: reserve_buffer *
- * *
- * Purpose: reserve number of bytes in the specified buffer, reallocating if *
- * necessary *
- * *
- * Parameters: buffer - [IN/OUT] the buffer *
- * buffer_size - [INT/OUT] the deserialized value *
- * reserve - [IN] the number of bytes to reserve *
- * ptr - [IN/OUT] a pointer to an offset in buffer *
- * *
- * Comments: Initially static buffer is used, allocating dynamic buffer when *
- * static buffer is too small. *
- * *
- ******************************************************************************/
-static void reserve_buffer(unsigned char **buffer, size_t *buffer_size, size_t reserve, unsigned char **ptr)
-{
- size_t offset = *ptr - *buffer, new_size;
-
- if (offset + reserve <= *buffer_size)
- return;
-
- new_size = *buffer_size * 1.5;
-
- if (ZBX_EVAL_STATIC_BUFFER_SIZE == *buffer_size)
- {
- unsigned char *old = *buffer;
-
- *buffer = zbx_malloc(NULL, new_size);
- memcpy(*buffer, old, offset);
- }
- else
- *buffer = zbx_realloc(*buffer, new_size);
-
- *buffer_size = new_size;
- *ptr = *buffer + offset;
-}
-
-static void serialize_variant(unsigned char **buffer, size_t *size, const zbx_variant_t *value,
- unsigned char **ptr)
-{
- size_t len;
-
- reserve_buffer(buffer, size, 1, ptr);
- **ptr = value->type;
- (*ptr)++;
-
- switch (value->type)
- {
- case ZBX_VARIANT_UI64:
- reserve_buffer(buffer, size, sizeof(value->data.ui64), ptr);
- *ptr += zbx_serialize_uint64(*ptr, value->data.ui64);
- break;
- case ZBX_VARIANT_DBL:
- reserve_buffer(buffer, size, sizeof(value->data.dbl), ptr);
- *ptr += zbx_serialize_double(*ptr, value->data.dbl) + 1;
- break;
- case ZBX_VARIANT_STR:
- len = strlen(value->data.str) + 1;
- reserve_buffer(buffer, size, len, ptr);
- memcpy(*ptr, value->data.str, len);
- *ptr += len;
- break;
- case ZBX_VARIANT_NONE:
- break;
- default:
- zabbix_log(LOG_LEVEL_DEBUG, "TYPE: %d", value->type);
- THIS_SHOULD_NEVER_HAPPEN;
- (*ptr)[-1] = ZBX_VARIANT_NONE;
- break;
- }
-}
-
-static zbx_uint32_t deserialize_variant(const unsigned char *ptr, zbx_variant_t *value)
-{
- const unsigned char *start = ptr;
- unsigned char type;
- zbx_uint64_t ui64;
- double dbl;
- char *str;
- size_t len;
-
- ptr += zbx_deserialize_char(ptr, &type);
-
- switch (type)
- {
- case ZBX_VARIANT_UI64:
- ptr += zbx_deserialize_uint64(ptr, &ui64);
- zbx_variant_set_ui64(value, ui64);
- break;
- case ZBX_VARIANT_DBL:
- ptr += zbx_deserialize_uint64(ptr, &dbl);
- zbx_variant_set_dbl(value, dbl);
- break;
- case ZBX_VARIANT_STR:
- len = strlen((const char *)ptr) + 1;
- str = zbx_malloc(NULL, len);
- memcpy(str, ptr, len);
- zbx_variant_set_str(value, str);
- ptr += len;
- break;
- case ZBX_VARIANT_NONE:
- zbx_variant_set_none(value);
- break;
- default:
- THIS_SHOULD_NEVER_HAPPEN;
- zbx_variant_set_none(value);
- break;
- }
-
- return ptr - start;
-}
-
-/******************************************************************************
- * *
* Function: zbx_eval_parse_expression *
* *
* Purpose: parse expression into tokens in postfix notation order *
@@ -1126,291 +929,38 @@ int zbx_eval_parse_expression(zbx_eval_context_t *ctx, const char *expression, z
/******************************************************************************
* *
- * Function: zbx_eval_clear *
- * *
- * Purpose: free resources allocated by evaluation context *
- * *
- * Parameters: ctx - [IN] the evaluation context *
- * *
- ******************************************************************************/
-void zbx_eval_clear(zbx_eval_context_t *ctx)
-{
- eval_clean(ctx);
-}
-
-/******************************************************************************
- * *
- * Function: zbx_eval_serialize *
- * *
- * Purpose: serialize evaluation context into buffer *
- * *
- * Parameters: ctx - [IN] the evaluation context *
- * malloc_func - [IN] the buffer memory allocation function, *
- * optional (by default the buffer is *
- * allocated in heap) *
- * data - [OUT] the buffer with serialized evaluation context *
- * *
- * Comments: Location of the replaced tokens (with token.value set) are not *
- * serialized, making it impossible to reconstruct the expression *
- * text with replaced tokens. *
- * Context serialization/deserialization must be used for *
- * context caching. *
- * *
- * Return value: The size of serialized data. *
- * *
- ******************************************************************************/
-size_t zbx_eval_serialize(const zbx_eval_context_t *ctx, zbx_mem_malloc_func_t malloc_func,
- unsigned char **data)
-{
- int i;
- unsigned char buffer_static[ZBX_EVAL_STATIC_BUFFER_SIZE], *buffer = buffer_static, *ptr = buffer, len_buff[4];
- size_t buffer_size = ZBX_EVAL_STATIC_BUFFER_SIZE;
- zbx_uint32_t len, len_offset;
-
- if (NULL == malloc_func)
- malloc_func = ZBX_DEFAULT_MEM_MALLOC_FUNC;
-
- ptr += serialize_uint31_compact(ptr, ctx->stack.values_num);
-
- for (i = 0; i < ctx->stack.values_num; i++)
- {
- const zbx_eval_token_t *token = &ctx->stack.values[i];
-
- reserve_buffer(&buffer, &buffer_size, 20, &ptr);
-
- ptr += zbx_serialize_value(ptr, token->type);
- ptr += serialize_uint31_compact(ptr, token->opt);
-
- serialize_variant(&buffer, &buffer_size, &token->value, &ptr);
-
- if (ZBX_VARIANT_NONE == token->value.type)
- {
- ptr += serialize_uint31_compact(ptr, token->loc.l);
- ptr += serialize_uint31_compact(ptr, token->loc.r);
- }
- }
-
- len = ptr - buffer;
-
- len_offset = serialize_uint31_compact(len_buff, len);
-
- *data = malloc_func(NULL, len + len_offset);
- memcpy(*data, len_buff, len_offset);
- memcpy(*data + len_offset, buffer, len);
-
- if (buffer != buffer_static)
- zbx_free(buffer);
-
- return len + len_offset;
-}
-
-/******************************************************************************
- * *
- * Function: zbx_eval_deserialize *
- * *
- * Purpose: deserialize evaluation context from buffer *
- * *
- * Parameters: ctx - [OUT] the evaluation context *
- * expression - [IN] the expression the evaluation context was *
- * created from *
- * rules - [IN] the composition and evaluation rules *
- * data - [IN] the buffer with serialized context *
- * *
- ******************************************************************************/
-void zbx_eval_deserialize(zbx_eval_context_t *ctx, const char *expression, zbx_uint64_t rules,
- const unsigned char *data)
-{
- zbx_uint32_t i, tokens_num, len;
-
- memset(ctx, 0, sizeof(zbx_eval_context_t));
- ctx->expression = expression;
- ctx->rules = rules;
-
- data += deserialize_uint31_compact(data, &len);
- data += deserialize_uint31_compact(data, &tokens_num);
- zbx_vector_eval_token_create(&ctx->stack);
- zbx_vector_eval_token_reserve(&ctx->stack, tokens_num);
- ctx->stack.values_num = tokens_num;
-
- for (i = 0; i < tokens_num; i++)
- {
- zbx_eval_token_t *token = &ctx->stack.values[i];
-
- data += zbx_deserialize_value(data, &token->type);
- data += deserialize_uint31_compact(data, &token->opt);
- data += deserialize_variant(data, &token->value);
-
- if (ZBX_VARIANT_NONE == token->value.type)
- {
- zbx_uint32_t pos;
-
- data += deserialize_uint31_compact(data, &pos);
- token->loc.l = pos;
- data += deserialize_uint31_compact(data, &pos);
- token->loc.r = pos;
- }
- else
- token->loc.l = token->loc.r = 0;
- }
-}
-
-static int compare_tokens_by_loc(const void *d1, const void *d2)
-{
- const zbx_eval_token_t *t1 = *(const zbx_eval_token_t **)d1;
- const zbx_eval_token_t *t2 = *(const zbx_eval_token_t **)d2;
-
- ZBX_RETURN_IF_NOT_EQUAL(t1->loc.l, t2->loc.l);
- return 0;
-}
-
-/******************************************************************************
+ * Function: zbx_eval_parse_expression *
* *
- * Function: eval_token_print_alloc *
+ * Purpose: parse expression into tokens in postfix notation order *
* *
- * Purpose: print token into string quoting/escaping if necessary *
+ * Parameters: expression - [IN] the expression to parse *
+ * rules - [IN] the parsing rules *
+ * error - [OUT] the error message in the case of failure *
* *
- * Parameters: ctx - [IN] the evaluation context *
- * str - [IN/OUT] the output buffer *
- * str_alloc - [IN/OUT] the output buffer size *
- * str_offset - [IN/OUT] the output buffer offset *
- * token - [IN] the token to print *
+ * Return value: The evaluation context or NULL in the case of error. *
* *
******************************************************************************/
-static void eval_token_print_alloc(const zbx_eval_context_t *ctx, char **str, size_t *str_alloc, size_t *str_offset,
- const zbx_eval_token_t *token)
+zbx_eval_context_t *zbx_eval_parse_expression_dyn(const char *expression, zbx_uint64_t rules, char **error)
{
- int quoted = 0, len, check_value = 0;
- const char *src, *value_str;
- char *dst;
- size_t size;
+ zbx_eval_context_t *ctx;
- if (ZBX_VARIANT_NONE == token->value.type)
- return;
+ ctx = (zbx_eval_context_t *)zbx_malloc(NULL, sizeof(zbx_eval_context_t));
+ if (SUCCEED != zbx_eval_parse_expression(ctx, expression, rules, error))
+ zbx_free(ctx);
- switch (token->type)
- {
- case ZBX_EVAL_TOKEN_VAR_STR:
- quoted = 1;
- break;
- case ZBX_EVAL_TOKEN_VAR_MACRO:
- if (0 != (ctx->rules & ZBX_EVAL_QUOTE_MACRO))
- check_value = 1;
- break;
- case ZBX_EVAL_TOKEN_VAR_USERMACRO:
- if (0 != (ctx->rules & ZBX_EVAL_QUOTE_USERMACRO))
- check_value = 1;
- break;
- case ZBX_EVAL_TOKEN_VAR_LLDMACRO:
- if (0 != (ctx->rules & ZBX_EVAL_QUOTE_LLDMACRO))
- check_value = 1;
- break;
- }
-
- if (0 != check_value)
- {
- if (ZBX_VARIANT_STR == token->value.type && (SUCCEED != zbx_number_parse(token->value.data.str, &len) ||
- strlen(token->value.data.str) != (size_t)len))
- {
- quoted = 1;
- }
- }
-
- value_str = zbx_variant_value_desc(&token->value);
-
- if (0 == quoted)
- {
- zbx_strcpy_alloc(str, str_alloc, str_offset, value_str);
- return;
- }
-
- for (size = 2, src = value_str; '\0' != *src; src++)
- {
- switch (*src)
- {
- case '\\':
- case '"':
- size++;
- }
- size++;
- }
-
- if (*str_alloc - *str_offset <= size)
- {
- do
- {
- *str_alloc *= 2;
- }
- while (*str_alloc - *str_offset <= size);
-
- *str = zbx_realloc(*str, *str_alloc);
- }
-
- dst = *str + *str_offset;
- *dst++ = '"';
-
- for (src = value_str; '\0' != *src; src++, dst++)
- {
- switch (*src)
- {
- case '\\':
- case '"':
- *dst++ = '\\';
- break;
- }
-
- *dst = *src;
- }
-
- *dst++ = '"';
- *dst = '\0';
- *str_offset += size;
+ return ctx;
}
/******************************************************************************
* *
- * Function: zbx_eval_compose_expression *
+ * Function: zbx_eval_clear *
* *
- * Purpose: compose expression by replacing processed tokens (with values) in *
- * the original expression *
+ * Purpose: free resources allocated by evaluation context *
* *
- * Parameters: ctx - [IN] the evaluation context *
- * expression - [OUT] the composed expression *
+ * Parameters: ctx - [IN] the evaluation context *
* *
******************************************************************************/
-void zbx_eval_compose_expression(const zbx_eval_context_t *ctx, char **expression)
+void zbx_eval_clear(zbx_eval_context_t *ctx)
{
- zbx_vector_ptr_t tokens;
- const zbx_eval_token_t *token;
- int i;
- size_t pos = 0, expression_alloc = 0, expression_offset = 0;
-
- zbx_vector_ptr_create(&tokens);
-
- for (i = 0; i < ctx->stack.values_num; i++)
- {
- if (ZBX_VARIANT_NONE != ctx->stack.values[i].value.type)
- zbx_vector_ptr_append(&tokens, &ctx->stack.values[i]);
- }
-
- zbx_vector_ptr_sort(&tokens, compare_tokens_by_loc);
-
- for (i = 0; i < tokens.values_num; i++)
- {
- token = (const zbx_eval_token_t *)tokens.values[i];
-
- if (0 != token->loc.l)
- {
- zbx_strncpy_alloc(expression, &expression_alloc, &expression_offset, ctx->expression + pos,
- token->loc.l - pos);
- }
- pos = token->loc.r + 1;
- eval_token_print_alloc(ctx, expression, &expression_alloc, &expression_offset, token);
- }
-
- if ('\0' != ctx->expression[pos])
- zbx_strcpy_alloc(expression, &expression_alloc, &expression_offset, ctx->expression + pos);
-
- zbx_vector_ptr_destroy(&tokens);
+ eval_clear(ctx);
}
-
-
diff --git a/src/libs/zbxserver/evalfunc.c b/src/libs/zbxserver/evalfunc.c
index cf30dd560d5..812aa9e3a99 100644
--- a/src/libs/zbxserver/evalfunc.c
+++ b/src/libs/zbxserver/evalfunc.c
@@ -3487,21 +3487,12 @@ int evaluate_macro_function(char **result, const char *host, const char *key, co
* FAIL - don't evaluate the function for NOTSUPPORTED items *
* *
******************************************************************************/
-int evaluatable_for_notsupported(const char *fn)
+int zbx_evaluatable_for_notsupported(const char *fn)
{
- /* functions date(), dayofmonth(), dayofweek(), now(), time() and nodata() are exceptions, */
- /* they should be evaluated for NOTSUPPORTED items, too */
+ /* function nodata() are exceptions, */
+ /* and should be evaluated for NOTSUPPORTED items, too */
- if ('n' != *fn && 'd' != *fn && 't' != *fn)
- return FAIL;
-
- if (('n' == *fn) && (0 == strcmp(fn, "nodata") || 0 == strcmp(fn, "now")))
- return SUCCEED;
-
- if (('d' == *fn) && (0 == strcmp(fn, "dayofweek") || 0 == strcmp(fn, "dayofmonth") || 0 == strcmp(fn, "date")))
- return SUCCEED;
-
- if (0 == strcmp(fn, "time"))
+ if (0 == strcmp(fn, "nodata"))
return SUCCEED;
return FAIL;
diff --git a/src/libs/zbxserver/evalfunc.h b/src/libs/zbxserver/evalfunc.h
index 0de78f499d1..919da491f19 100644
--- a/src/libs/zbxserver/evalfunc.h
+++ b/src/libs/zbxserver/evalfunc.h
@@ -29,6 +29,6 @@ zbx_output_format_t;
int evaluate_macro_function(char **result, const char *host, const char *key, const char *function,
const char *parameter, zbx_output_format_t format);
-int evaluatable_for_notsupported(const char *fn);
+int zbx_evaluatable_for_notsupported(const char *fn);
#endif
diff --git a/src/libs/zbxserver/expression.c b/src/libs/zbxserver/expression.c
index fafa74250ce..93ad8c92b22 100644
--- a/src/libs/zbxserver/expression.c
+++ b/src/libs/zbxserver/expression.c
@@ -21,6 +21,7 @@
#include "evalfunc.h"
#include "log.h"
#include "zbxregexp.h"
+#include "zbxvariant.h"
#include "valuecache.h"
#include "macrofunc.h"
@@ -141,103 +142,6 @@ int get_N_functionid(const char *expression, int N_functionid, zbx_uint64_t *fun
/******************************************************************************
* *
- * Function: get_functionids *
- * *
- * Purpose: get identifiers of the functions used in expression *
- * *
- * Parameters: functionids - [OUT] the resulting vector of function ids *
- * expression - [IN] null terminated trigger expression *
- * '{11}=1 & {2346734}>5' *
- * *
- ******************************************************************************/
-void get_functionids(zbx_vector_uint64_t *functionids, const char *expression)
-{
- zbx_token_t token;
- int pos = 0;
- zbx_uint64_t functionid;
-
- if ('\0' == *expression)
- return;
-
- for (; SUCCEED == zbx_token_find(expression, pos, &token, ZBX_TOKEN_SEARCH_BASIC); pos++)
- {
- switch (token.type)
- {
- case ZBX_TOKEN_OBJECTID:
- is_uint64_n(expression + token.loc.l + 1, token.loc.r - token.loc.l - 1,
- &functionid);
- zbx_vector_uint64_append(functionids, functionid);
- ZBX_FALLTHROUGH;
- case ZBX_TOKEN_USER_MACRO:
- case ZBX_TOKEN_SIMPLE_MACRO:
- case ZBX_TOKEN_MACRO:
- pos = token.loc.r;
- break;
- }
- }
-
- zbx_vector_uint64_sort(functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
- zbx_vector_uint64_uniq(functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
-}
-
-/******************************************************************************
- * *
- * Function: get_N_itemid *
- * *
- * Parameters: expression - [IN] null terminated trigger expression *
- * '{11}=1 & {2346734}>5' *
- * N_functionid - [IN] number of function in trigger expression *
- * itemid - [OUT] ID of an item of N-th function in *
- * expression *
- * *
- ******************************************************************************/
-static int get_N_itemid(const char *expression, int N_functionid, zbx_uint64_t *itemid)
-{
- zbx_uint64_t functionid;
- DC_FUNCTION function;
- int errcode, ret = FAIL;
-
- zabbix_log(LOG_LEVEL_DEBUG, "In %s() expression:'%s' N_functionid:%d", __func__, expression, N_functionid);
-
- if (SUCCEED == get_N_functionid(expression, N_functionid, &functionid, NULL))
- {
- DCconfig_get_functions_by_functionids(&function, &functionid, &errcode, 1);
-
- if (SUCCEED == errcode)
- {
- *itemid = function.itemid;
- ret = SUCCEED;
- }
-
- DCconfig_clean_functions(&function, &errcode, 1);
- }
-
- zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
-
- return ret;
-}
-
-/******************************************************************************
- * *
- * Function: get_expanded_expression *
- * *
- * Purpose: get trigger expression with expanded user macros *
- * *
- * Comments: removes ' ', '\r', '\n' and '\t' for easier number search *
- * *
- ******************************************************************************/
-static char *get_expanded_expression(const char *expression)
-{
- char *expression_ex;
-
- if (NULL != (expression_ex = DCexpression_expand_user_macros(expression)))
- zbx_remove_whitespace(expression_ex);
-
- return expression_ex;
-}
-
-/******************************************************************************
- * *
* Function: get_trigger_expression_constant *
* *
* Purpose: get constant from a trigger expression corresponding a given *
@@ -1072,14 +976,14 @@ static int DBget_item_value(zbx_uint64_t itemid, char **replace_to, int request)
* otherwise FAIL *
* *
******************************************************************************/
-static int DBget_trigger_value(const char *expression, char **replace_to, int N_functionid, int request)
+static int DBget_trigger_value(const DB_TRIGGER *trigger, char **replace_to, int N_functionid, int request)
{
zbx_uint64_t itemid;
int ret = FAIL;
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
- if (SUCCEED == get_N_itemid(expression, N_functionid, &itemid))
+ if (SUCCEED == zbx_db_trigger_get_itemid(trigger, N_functionid, &itemid))
ret = DBget_item_value(itemid, replace_to, request);
zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
@@ -1480,7 +1384,7 @@ static int DBitem_get_value(zbx_uint64_t itemid, char **lastvalue, int raw, zbx_
* otherwise FAIL *
* *
******************************************************************************/
-static int DBitem_value(const char *expression, char **value, int N_functionid, int clock, int ns, int raw)
+static int DBitem_value(const DB_TRIGGER *trigger, char **value, int N_functionid, int clock, int ns, int raw)
{
zbx_uint64_t itemid;
zbx_timespec_t ts = {clock, ns};
@@ -1488,7 +1392,7 @@ static int DBitem_value(const char *expression, char **value, int N_functionid,
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
- if (SUCCEED == (ret = get_N_itemid(expression, N_functionid, &itemid)))
+ if (SUCCEED == (ret = zbx_db_trigger_get_itemid(trigger, N_functionid, &itemid)))
ret = DBitem_get_value(itemid, value, raw, &ts);
zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
@@ -1509,13 +1413,13 @@ static int DBitem_value(const char *expression, char **value, int N_functionid,
* otherwise FAIL *
* *
******************************************************************************/
-static int DBitem_lastvalue(const char *expression, char **lastvalue, int N_functionid, int raw)
+static int DBitem_lastvalue(const DB_TRIGGER *trigger, char **lastvalue, int N_functionid, int raw)
{
int ret;
zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
- ret = DBitem_value(expression, lastvalue, N_functionid, time(NULL), 999999999, raw);
+ ret = DBitem_value(trigger, lastvalue, N_functionid, time(NULL), 999999999, raw);
zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
@@ -2207,7 +2111,7 @@ static int get_action_value(const char *macro, zbx_uint64_t actionid, char **rep
* otherwise FAIL *
* *
******************************************************************************/
-static int get_host_inventory(const char *macro, const char *expression, char **replace_to,
+static int get_host_inventory(const char *macro, const DB_TRIGGER *trigger, char **replace_to,
int N_functionid)
{
int i;
@@ -2218,7 +2122,7 @@ static int get_host_inventory(const char *macro, const char *expression, char **
{
zbx_uint64_t itemid;
- if (SUCCEED != get_N_itemid(expression, N_functionid, &itemid))
+ if (SUCCEED != zbx_db_trigger_get_itemid(trigger, N_functionid, &itemid))
return FAIL;
return DCget_host_inventory_value_by_itemid(itemid, replace_to, inventory_fields[i].idx);
@@ -2592,7 +2496,7 @@ static int get_expression_macro_result(const DB_EVENT *event, const DB_EVENT *r_
* otherwise FAIL *
* *
******************************************************************************/
-static int get_history_log_value(const char *m, const char *expression, char **replace_to, int N_functionid,
+static int get_history_log_value(const char *m, const DB_TRIGGER *trigger, char **replace_to, int N_functionid,
int clock, int ns, const char *tz)
{
zbx_uint64_t itemid;
@@ -2627,7 +2531,7 @@ static int get_history_log_value(const char *m, const char *expression, char **r
else /* MVAR_ITEM_LOG_TIME */
request = ZBX_REQUEST_ITEM_LOG_TIME;
- if (SUCCEED == (ret = get_N_itemid(expression, N_functionid, &itemid)))
+ if (SUCCEED == (ret = zbx_db_trigger_get_itemid(trigger, N_functionid, &itemid)))
ret = DBget_history_log_value(itemid, replace_to, request, clock, ns, tz);
zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
@@ -2787,7 +2691,7 @@ static const char *func_macro_in_list(const char *str, zbx_token_func_macro_t *f
* Comments: example: " {Zabbix server:{ITEM.KEY1}.last(0)} " to " 1.34 " *
* *
******************************************************************************/
-static int get_trigger_function_value(const char *expression, char **replace_to, char *data,
+static int get_trigger_function_value(const DB_TRIGGER *trigger, char **replace_to, char *data,
const zbx_token_simple_macro_t *simple_macro, zbx_output_format_t format)
{
char *host = NULL, *key = NULL;
@@ -2795,13 +2699,13 @@ static int get_trigger_function_value(const char *expression, char **replace_to,
if (NULL != macro_in_list(data, simple_macro->host, simple_host_macros, &N_functionid))
{
- if (SUCCEED != DBget_trigger_value(expression, &host, N_functionid, ZBX_REQUEST_HOST_HOST))
+ if (SUCCEED != DBget_trigger_value(trigger, &host, N_functionid, ZBX_REQUEST_HOST_HOST))
goto out;
}
if (NULL != macro_in_list(data, simple_macro->key, simple_key_macros, &N_functionid))
{
- if (SUCCEED != DBget_trigger_value(expression, &key, N_functionid, ZBX_REQUEST_ITEM_KEY_ORIG))
+ if (SUCCEED != DBget_trigger_value(trigger, &key, N_functionid, ZBX_REQUEST_ITEM_KEY_ORIG))
goto out;
}
@@ -2827,33 +2731,6 @@ out:
/******************************************************************************
* *
- * Function: cache_trigger_hostids *
- * *
- * Purpose: cache host identifiers referenced by trigger expression *
- * *
- * Parameters: hostids - [OUT] the host identifier cache *
- * expression - [IN] the trigger expression *
- * recovery_expression - [IN] the trigger recovery expression *
- * (can be empty) *
- * *
- ******************************************************************************/
-static void cache_trigger_hostids(zbx_vector_uint64_t *hostids, const char *expression,
- const char *recovery_expression)
-{
- if (0 == hostids->values_num)
- {
- zbx_vector_uint64_t functionids;
-
- zbx_vector_uint64_create(&functionids);
- get_functionids(&functionids, expression);
- get_functionids(&functionids, recovery_expression);
- DCget_hostids_by_functionids(&functionids, hostids);
- zbx_vector_uint64_destroy(&functionids);
- }
-}
-
-/******************************************************************************
- * *
* Function: cache_item_hostid *
* *
* Purpose: cache host identifier referenced by an item or a lld-rule *
@@ -2955,9 +2832,7 @@ static void resolve_opdata(const DB_EVENT *event, char **replace_to, const char
if ('\0' == *event->trigger.opdata)
{
- int pos = 0;
- zbx_token_t token;
- zbx_uint64_t itemid;
+ int i;
zbx_vector_uint64_t itemids;
zbx_timespec_t ts;
@@ -2965,38 +2840,22 @@ static void resolve_opdata(const DB_EVENT *event, char **replace_to, const char
ts.ns = 999999999;
zbx_vector_uint64_create(&itemids);
+ zbx_db_trigger_get_itemids(&event->trigger, &itemids);
- for (; SUCCEED == zbx_token_find(event->trigger.expression, pos, &token, ZBX_TOKEN_SEARCH_BASIC); pos++)
+ for (i = 0; i < itemids.values_num; i++)
{
- switch (token.type)
- {
- case ZBX_TOKEN_OBJECTID:
- if (SUCCEED == get_N_itemid(event->trigger.expression + token.loc.l, 1,
- &itemid) &&
- FAIL == zbx_vector_uint64_search(&itemids, itemid,
- ZBX_DEFAULT_UINT64_COMPARE_FUNC))
- {
- char *val = NULL;
-
- zbx_vector_uint64_append(&itemids, itemid);
+ char *val = NULL;
- if (NULL != *replace_to)
- *replace_to = zbx_strdcat(*replace_to, ", ");
+ if (NULL != *replace_to)
+ *replace_to = zbx_strdcat(*replace_to, ", ");
- if (SUCCEED == DBitem_get_value(itemid, &val, 0, &ts))
- {
- *replace_to = zbx_strdcat(*replace_to, val);
- zbx_free(val);
- }
- else
- *replace_to = zbx_strdcat(*replace_to, STR_UNKNOWN_VARIABLE);
- }
- ZBX_FALLTHROUGH;
- case ZBX_TOKEN_USER_MACRO:
- case ZBX_TOKEN_SIMPLE_MACRO:
- case ZBX_TOKEN_MACRO:
- pos = token.loc.r;
+ if (SUCCEED == DBitem_get_value(itemids.values[i], &val, 0, &ts))
+ {
+ *replace_to = zbx_strdcat(*replace_to, val);
+ zbx_free(val);
}
+ else
+ *replace_to = zbx_strdcat(*replace_to, STR_UNKNOWN_VARIABLE);
}
zbx_vector_uint64_destroy(&itemids);
@@ -3024,16 +2883,17 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT
zbx_uint64_t *userid, const zbx_uint64_t *hostid, const DC_HOST *dc_host, const DC_ITEM *dc_item,
DB_ALERT *alert, const DB_ACKNOWLEDGE *ack, const char *tz, char **data, int macro_type, char *error, int maxerrlen)
{
- char c, *replace_to = NULL, sql[64];
- const char *m;
- int N_functionid, indexed_macro, require_address, ret, res = SUCCEED,
- pos = 0, found, user_names_found = 0, raw_value;
- size_t data_alloc, data_len;
- DC_INTERFACE interface;
- zbx_vector_uint64_t hostids;
- zbx_token_t token, inner_token;
- zbx_token_search_t token_search = ZBX_TOKEN_SEARCH_BASIC;
- char *expression = NULL, *user_alias = NULL, *user_name = NULL, *user_surname = NULL;
+ char c, *replace_to = NULL, sql[64];
+ const char *m;
+ int N_functionid, indexed_macro, require_address, ret, res = SUCCEED,
+ pos = 0, found, user_names_found = 0, raw_value;
+ size_t data_alloc, data_len;
+ DC_INTERFACE interface;
+ zbx_vector_uint64_t hostids;
+ const zbx_vector_uint64_t *phostids;
+ zbx_token_t token, inner_token;
+ zbx_token_search_t token_search = ZBX_TOKEN_SEARCH_BASIC;
+ char *expression = NULL, *user_alias = NULL, *user_name = NULL, *user_surname = NULL;
if (NULL == data || NULL == *data || '\0' == **data)
{
@@ -3144,14 +3004,13 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT
{
if (ZBX_TOKEN_USER_MACRO == token.type)
{
- cache_trigger_hostids(&hostids, c_event->trigger.expression,
- c_event->trigger.recovery_expression);
- DCget_user_macro(hostids.values, hostids.values_num, m, &replace_to);
+ if (SUCCEED == zbx_db_trigger_get_all_hostids(&c_event->trigger, &phostids))
+ DCget_user_macro(phostids->values, phostids->values_num, m, &replace_to);
pos = token.loc.r;
}
else if (ZBX_TOKEN_SIMPLE_MACRO == token.type)
{
- ret = get_trigger_function_value(c_event->trigger.expression, &replace_to,
+ ret = get_trigger_function_value(&c_event->trigger, &replace_to,
*data, &token.data.simple_macro, ZBX_FORMAT_HUMAN);
}
else if (0 == strncmp(m, MVAR_ACTION, ZBX_CONST_STRLEN(MVAR_ACTION)))
@@ -3221,113 +3080,112 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT
}
else if (0 == strcmp(m, MVAR_HOST_ID))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_ID);
}
else if (0 == strcmp(m, MVAR_HOST_HOST) || 0 == strcmp(m, MVAR_HOSTNAME))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_HOST);
}
else if (0 == strcmp(m, MVAR_HOST_NAME))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_NAME);
}
else if (0 == strcmp(m, MVAR_HOST_DESCRIPTION))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_DESCRIPTION);
}
else if (0 == strcmp(m, MVAR_HOST_IP) || 0 == strcmp(m, MVAR_IPADDRESS))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_IP);
}
else if (0 == strcmp(m, MVAR_HOST_DNS))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_DNS);
}
else if (0 == strcmp(m, MVAR_HOST_CONN))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_CONN);
}
else if (0 == strcmp(m, MVAR_HOST_PORT))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_PORT);
}
else if (0 == strncmp(m, MVAR_INVENTORY, ZBX_CONST_STRLEN(MVAR_INVENTORY)) ||
0 == strncmp(m, MVAR_PROFILE, ZBX_CONST_STRLEN(MVAR_PROFILE)))
{
- ret = get_host_inventory(m, c_event->trigger.expression, &replace_to,
- N_functionid);
+ ret = get_host_inventory(m, &c_event->trigger, &replace_to, N_functionid);
}
else if (0 == strcmp(m, MVAR_ITEM_DESCRIPTION))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_DESCRIPTION);
}
else if (0 == strcmp(m, MVAR_ITEM_DESCRIPTION_ORIG))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_DESCRIPTION_ORIG);
}
else if (0 == strcmp(m, MVAR_ITEM_ID))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_ID);
}
else if (0 == strcmp(m, MVAR_ITEM_KEY) || 0 == strcmp(m, MVAR_TRIGGER_KEY))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_KEY);
}
else if (0 == strcmp(m, MVAR_ITEM_KEY_ORIG))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_KEY_ORIG);
}
else if (0 == strcmp(m, MVAR_ITEM_LASTVALUE))
{
- ret = DBitem_lastvalue(c_event->trigger.expression, &replace_to, N_functionid,
+ ret = DBitem_lastvalue(&c_event->trigger, &replace_to, N_functionid,
raw_value);
}
else if (0 == strcmp(m, MVAR_ITEM_NAME))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_NAME);
}
else if (0 == strcmp(m, MVAR_ITEM_NAME_ORIG))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_NAME_ORIG);
}
else if (0 == strcmp(m, MVAR_ITEM_VALUE))
{
- ret = DBitem_value(c_event->trigger.expression, &replace_to, N_functionid,
+ ret = DBitem_value(&c_event->trigger, &replace_to, N_functionid,
c_event->clock, c_event->ns, raw_value);
}
else if (0 == strncmp(m, MVAR_ITEM_LOG, ZBX_CONST_STRLEN(MVAR_ITEM_LOG)))
{
- ret = get_history_log_value(m, c_event->trigger.expression, &replace_to,
+ ret = get_history_log_value(m, &c_event->trigger, &replace_to,
N_functionid, c_event->clock, c_event->ns, tz);
}
else if (0 == strcmp(m, MVAR_ITEM_VALUETYPE))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_VALUETYPE);
}
else if (0 == strcmp(m, MVAR_PROXY_NAME))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_PROXY_NAME);
}
else if (0 == strcmp(m, MVAR_PROXY_DESCRIPTION))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_PROXY_DESCRIPTION);
}
else if (0 == indexed_macro && 0 == strcmp(m, MVAR_TIME))
@@ -3454,9 +3312,8 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT
{
if (ZBX_TOKEN_USER_MACRO == token.type)
{
- cache_trigger_hostids(&hostids, c_event->trigger.expression,
- c_event->trigger.recovery_expression);
- DCget_user_macro(hostids.values, hostids.values_num, m, &replace_to);
+ if (SUCCEED == zbx_db_trigger_get_all_hostids(&c_event->trigger, &phostids))
+ DCget_user_macro(phostids->values, phostids->values_num, m, &replace_to);
pos = token.loc.r;
}
else if (0 == strncmp(m, MVAR_ACTION, ZBX_CONST_STRLEN(MVAR_ACTION)))
@@ -3490,98 +3347,98 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT
}
else if (0 == strcmp(m, MVAR_HOST_ID))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_ID);
}
else if (0 == strcmp(m, MVAR_HOST_HOST) || 0 == strcmp(m, MVAR_HOSTNAME))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_HOST);
}
else if (0 == strcmp(m, MVAR_HOST_NAME))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_NAME);
}
else if (0 == strcmp(m, MVAR_HOST_DESCRIPTION))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_DESCRIPTION);
}
else if (0 == strcmp(m, MVAR_HOST_IP) || 0 == strcmp(m, MVAR_IPADDRESS))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_IP);
}
else if (0 == strcmp(m, MVAR_HOST_DNS))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_DNS);
}
else if (0 == strcmp(m, MVAR_HOST_CONN))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_CONN);
}
else if (0 == strcmp(m, MVAR_HOST_PORT))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_HOST_PORT);
}
else if (0 == strncmp(m, MVAR_INVENTORY, ZBX_CONST_STRLEN(MVAR_INVENTORY)) ||
0 == strncmp(m, MVAR_PROFILE, ZBX_CONST_STRLEN(MVAR_PROFILE)))
{
- ret = get_host_inventory(m, c_event->trigger.expression, &replace_to,
+ ret = get_host_inventory(m, &c_event->trigger, &replace_to,
N_functionid);
}
else if (0 == strcmp(m, MVAR_ITEM_DESCRIPTION))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_DESCRIPTION);
}
else if (0 == strcmp(m, MVAR_ITEM_DESCRIPTION_ORIG))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_DESCRIPTION_ORIG);
}
else if (0 == strcmp(m, MVAR_ITEM_ID))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_ID);
}
else if (0 == strcmp(m, MVAR_ITEM_KEY) || 0 == strcmp(m, MVAR_TRIGGER_KEY))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_KEY);
}
else if (0 == strcmp(m, MVAR_ITEM_KEY_ORIG))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_KEY_ORIG);
}
else if (0 == strcmp(m, MVAR_ITEM_NAME))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_NAME);
}
else if (0 == strcmp(m, MVAR_ITEM_NAME_ORIG))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_NAME_ORIG);
}
else if (0 == strcmp(m, MVAR_ITEM_VALUETYPE))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_ITEM_VALUETYPE);
}
else if (0 == strcmp(m, MVAR_PROXY_NAME))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_PROXY_NAME);
}
else if (0 == strcmp(m, MVAR_PROXY_DESCRIPTION))
{
- ret = DBget_trigger_value(c_event->trigger.expression, &replace_to,
+ ret = DBget_trigger_value(&c_event->trigger, &replace_to,
N_functionid, ZBX_REQUEST_PROXY_DESCRIPTION);
}
else if (0 == indexed_macro && 0 == strcmp(m, MVAR_TIME))
@@ -4191,23 +4048,19 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT
{
if (ZBX_TOKEN_USER_MACRO == token.type)
{
- cache_trigger_hostids(&hostids, event->trigger.expression,
- event->trigger.recovery_expression);
- DCget_user_macro(hostids.values, hostids.values_num, m, &replace_to);
+ if (SUCCEED == zbx_db_trigger_get_all_hostids(&event->trigger, &phostids))
+ DCget_user_macro(phostids->values, phostids->values_num, m, &replace_to);
pos = token.loc.r;
}
else if (ZBX_TOKEN_REFERENCE == token.type)
{
- /* try to expand trigger expression if it hasn't been done yet */
- if (NULL == expression && NULL == (expression =
- get_expanded_expression(event->trigger.expression)))
+ if (SUCCEED != zbx_db_trigger_get_constant(&event->trigger,
+ token.data.reference.index, &replace_to))
{
/* expansion failed, reference substitution is impossible */
token_search &= ~ZBX_TOKEN_SEARCH_REFERENCES;
continue;
}
-
- get_trigger_expression_constant(expression, &token.data.reference, &replace_to);
}
else if (ZBX_TOKEN_EXPRESSION_MACRO == inner_token.type)
{
@@ -4227,47 +4080,47 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT
}
else if (0 == strcmp(m, MVAR_HOST_HOST) || 0 == strcmp(m, MVAR_HOSTNAME))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_HOST);
}
else if (0 == strcmp(m, MVAR_HOST_NAME))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_NAME);
}
else if (0 == strcmp(m, MVAR_HOST_IP) || 0 == strcmp(m, MVAR_IPADDRESS))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_IP);
}
else if (0 == strcmp(m, MVAR_HOST_DNS))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_DNS);
}
else if (0 == strcmp(m, MVAR_HOST_CONN))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_CONN);
}
else if (0 == strcmp(m, MVAR_HOST_PORT))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_PORT);
}
else if (0 == strcmp(m, MVAR_ITEM_VALUE))
{
- ret = DBitem_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBitem_value(&event->trigger, &replace_to, N_functionid,
event->clock, event->ns, raw_value);
}
else if (0 == strncmp(m, MVAR_ITEM_LOG, ZBX_CONST_STRLEN(MVAR_ITEM_LOG)))
{
- ret = get_history_log_value(m, event->trigger.expression, &replace_to,
+ ret = get_history_log_value(m, &event->trigger, &replace_to,
N_functionid, event->clock, event->ns, tz);
}
else if (0 == strcmp(m, MVAR_ITEM_LASTVALUE))
{
- ret = DBitem_lastvalue(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBitem_lastvalue(&event->trigger, &replace_to, N_functionid,
raw_value);
}
else if (0 == strcmp(m, MVAR_TIME) && 0 != (macro_type & MACRO_TYPE_EVENT_NAME))
@@ -4305,44 +4158,43 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT
{
if (ZBX_TOKEN_USER_MACRO == token.type)
{
- cache_trigger_hostids(&hostids, event->trigger.expression,
- event->trigger.recovery_expression);
- DCget_user_macro(hostids.values, hostids.values_num, m, &replace_to);
+ if (SUCCEED == zbx_db_trigger_get_all_hostids(&event->trigger, &phostids))
+ DCget_user_macro(phostids->values, phostids->values_num, m, &replace_to);
pos = token.loc.r;
}
else if (0 == strcmp(m, MVAR_HOST_ID))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_ID);
}
else if (0 == strcmp(m, MVAR_HOST_HOST))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_HOST);
}
else if (0 == strcmp(m, MVAR_HOST_NAME))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_NAME);
}
else if (0 == strcmp(m, MVAR_HOST_IP))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_IP);
}
else if (0 == strcmp(m, MVAR_HOST_DNS))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_DNS);
}
else if (0 == strcmp(m, MVAR_HOST_CONN))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_CONN);
}
else if (0 == strcmp(m, MVAR_HOST_PORT))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_PORT);
}
else if (0 == strcmp(m, MVAR_TRIGGER_ID))
@@ -4351,17 +4203,17 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT
}
else if (0 == strcmp(m, MVAR_ITEM_LASTVALUE))
{
- ret = DBitem_lastvalue(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBitem_lastvalue(&event->trigger, &replace_to, N_functionid,
raw_value);
}
else if (0 == strcmp(m, MVAR_ITEM_VALUE))
{
- ret = DBitem_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBitem_value(&event->trigger, &replace_to, N_functionid,
event->clock, event->ns, raw_value);
}
else if (0 == strncmp(m, MVAR_ITEM_LOG, ZBX_CONST_STRLEN(MVAR_ITEM_LOG)))
{
- ret = get_history_log_value(m, event->trigger.expression, &replace_to,
+ ret = get_history_log_value(m, &event->trigger, &replace_to,
N_functionid, event->clock, event->ns, tz);
}
else if (0 == strcmp(m, MVAR_EVENT_ID))
@@ -4679,64 +4531,63 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT
{
if (ZBX_TOKEN_USER_MACRO == token.type)
{
- cache_trigger_hostids(&hostids, event->trigger.expression,
- event->trigger.recovery_expression);
- DCget_user_macro(hostids.values, hostids.values_num, m, &replace_to);
+ if (SUCCEED == zbx_db_trigger_get_all_hostids(&event->trigger, &phostids))
+ DCget_user_macro(phostids->values, phostids->values_num, m, &replace_to);
pos = token.loc.r;
}
else if (0 == strncmp(m, MVAR_INVENTORY, ZBX_CONST_STRLEN(MVAR_INVENTORY)))
{
- ret = get_host_inventory(m, event->trigger.expression, &replace_to,
+ ret = get_host_inventory(m, &event->trigger, &replace_to,
N_functionid);
}
else if (0 == strcmp(m, MVAR_HOST_ID))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_ID);
}
else if (0 == strcmp(m, MVAR_HOST_HOST))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_HOST);
}
else if (0 == strcmp(m, MVAR_HOST_NAME))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_NAME);
}
else if (0 == strcmp(m, MVAR_HOST_IP))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_IP);
}
else if (0 == strcmp(m, MVAR_HOST_DNS))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_DNS);
}
else if (0 == strcmp(m, MVAR_HOST_CONN))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_CONN);
}
else if (0 == strcmp(m, MVAR_HOST_PORT))
{
- ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBget_trigger_value(&event->trigger, &replace_to, N_functionid,
ZBX_REQUEST_HOST_PORT);
}
else if (0 == strcmp(m, MVAR_ITEM_LASTVALUE))
{
- ret = DBitem_lastvalue(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBitem_lastvalue(&event->trigger, &replace_to, N_functionid,
raw_value);
}
else if (0 == strcmp(m, MVAR_ITEM_VALUE))
{
- ret = DBitem_value(event->trigger.expression, &replace_to, N_functionid,
+ ret = DBitem_value(&event->trigger, &replace_to, N_functionid,
event->clock, event->ns, raw_value);
}
else if (0 == strncmp(m, MVAR_ITEM_LOG, ZBX_CONST_STRLEN(MVAR_ITEM_LOG)))
{
- ret = get_history_log_value(m, event->trigger.expression, &replace_to,
+ ret = get_history_log_value(m, &event->trigger, &replace_to,
N_functionid, event->clock, event->ns, tz);
}
else if (0 == strcmp(m, MVAR_TRIGGER_ID))
@@ -4805,14 +4656,13 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT
if (ZBX_TOKEN_USER_MACRO == token.type)
{
- cache_trigger_hostids(&hostids, c_event->trigger.expression,
- c_event->trigger.recovery_expression);
- DCget_user_macro(hostids.values, hostids.values_num, m, &replace_to);
+ if (SUCCEED == zbx_db_trigger_get_all_hostids(&c_event->trigger, &phostids))
+ DCget_user_macro(phostids->values, phostids->values_num, m, &replace_to);
pos = token.loc.r;
}
else if (ZBX_TOKEN_SIMPLE_MACRO == token.type)
{
- ret = get_trigger_function_value(c_event->trigger.expression, &replace_to,
+ ret = get_trigger_function_value(&c_event->trigger, &replace_to,
*data, &token.data.simple_macro, ZBX_FORMAT_RAW);
}
}
@@ -4880,61 +4730,24 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT
return res;
}
-static int extract_expression_functionids(zbx_vector_uint64_t *functionids, const char *expression)
-{
- const char *bl, *br;
- zbx_uint64_t functionid;
-
- for (bl = strchr(expression, '{'); NULL != bl; bl = strchr(bl, '{'))
- {
- if (NULL == (br = strchr(bl, '}')))
- break;
-
- if (SUCCEED != is_uint64_n(bl + 1, br - bl - 1, &functionid))
- break;
-
- zbx_vector_uint64_append(functionids, functionid);
-
- bl = br + 1;
- }
-
- return (NULL == bl ? SUCCEED : FAIL);
-}
-
static void zbx_extract_functionids(zbx_vector_uint64_t *functionids, zbx_vector_ptr_t *triggers)
{
DC_TRIGGER *tr;
- int i, values_num_save;
+ int i;
zabbix_log(LOG_LEVEL_DEBUG, "In %s() tr_num:%d", __func__, triggers->values_num);
for (i = 0; i < triggers->values_num; i++)
{
- const char *error_expression = NULL;
-
tr = (DC_TRIGGER *)triggers->values[i];
if (NULL != tr->new_error)
continue;
- values_num_save = functionids->values_num;
+ zbx_eval_get_functionids(tr->eval_ctx, functionids);
- if (SUCCEED != extract_expression_functionids(functionids, tr->expression))
- {
- error_expression = tr->expression;
- }
- else if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == tr->recovery_mode &&
- SUCCEED != extract_expression_functionids(functionids, tr->recovery_expression))
- {
- error_expression = tr->recovery_expression;
- }
-
- if (NULL != error_expression)
- {
- tr->new_error = zbx_dsprintf(tr->new_error, "Invalid expression [%s]", error_expression);
- tr->new_value = TRIGGER_VALUE_UNKNOWN;
- functionids->values_num = values_num_save;
- }
+ if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == tr->recovery_mode)
+ zbx_eval_get_functionids(tr->eval_ctx_r, functionids);
}
zbx_vector_uint64_sort(functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
@@ -4963,18 +4776,23 @@ zbx_trigger_func_position_t;
* Author: Andrea Biscuola *
* *
******************************************************************************/
-static int expand_trigger_macros(DB_EVENT *event, DC_TRIGGER *trigger, char *error, size_t maxerrlen)
+static int expand_trigger_macros(zbx_eval_context_t *ctx, const DB_EVENT *event, char *error, size_t maxerrlen)
{
- if (FAIL == substitute_simple_macros_impl(NULL, event, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- &trigger->expression, MACRO_TYPE_TRIGGER_EXPRESSION, error, maxerrlen))
- {
- return FAIL;
- }
+ int i;
- if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == trigger->recovery_mode)
+ for (i = 0; i < ctx->stack.values_num; i++)
{
+ zbx_eval_token_t *token = &ctx->stack.values[i];
+
+ if (ZBX_EVAL_TOKEN_VAR_MACRO != token->type && ZBX_EVAL_TOKEN_VAR_STR != token->type)
+ continue;
+
+ /* all trigger macros macros are already extracted into strings */
+ if (ZBX_VARIANT_STR != token->value.type)
+ continue;
+
if (FAIL == substitute_simple_macros_impl(NULL, event, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- &trigger->recovery_expression, MACRO_TYPE_TRIGGER_EXPRESSION, error, maxerrlen))
+ &token->value.data.str, MACRO_TYPE_TRIGGER_EXPRESSION, error, maxerrlen))
{
return FAIL;
}
@@ -5001,7 +4819,6 @@ static void zbx_link_triggers_with_functions(zbx_vector_ptr_t *triggers_func_pos
{
zbx_vector_uint64_t funcids;
DC_TRIGGER *tr;
- DB_EVENT ev;
int i;
zabbix_log(LOG_LEVEL_DEBUG, "In %s() trigger_order_num:%d", __func__, trigger_order->values_num);
@@ -5009,8 +4826,6 @@ static void zbx_link_triggers_with_functions(zbx_vector_ptr_t *triggers_func_pos
zbx_vector_uint64_create(&funcids);
zbx_vector_uint64_reserve(&funcids, functionids->values_num);
- ev.object = EVENT_OBJECT_TRIGGER;
-
for (i = 0; i < trigger_order->values_num; i++)
{
zbx_trigger_func_position_t *tr_func_pos;
@@ -5020,20 +4835,14 @@ static void zbx_link_triggers_with_functions(zbx_vector_ptr_t *triggers_func_pos
if (NULL != tr->new_error)
continue;
- ev.value = tr->value;
-
- expand_trigger_macros(&ev, tr, NULL, 0);
-
- if (SUCCEED == extract_expression_functionids(&funcids, tr->expression))
- {
- tr_func_pos = (zbx_trigger_func_position_t *)zbx_malloc(NULL, sizeof(zbx_trigger_func_position_t));
- tr_func_pos->trigger = tr;
- tr_func_pos->start_index = functionids->values_num;
- tr_func_pos->count = funcids.values_num;
+ zbx_eval_get_functionids(tr->eval_ctx, &funcids);
+ tr_func_pos = (zbx_trigger_func_position_t *)zbx_malloc(NULL, sizeof(zbx_trigger_func_position_t));
+ tr_func_pos->trigger = tr;
+ tr_func_pos->start_index = functionids->values_num;
+ tr_func_pos->count = funcids.values_num;
- zbx_vector_uint64_append_array(functionids, funcids.values, funcids.values_num);
- zbx_vector_ptr_append(triggers_func_pos, tr_func_pos);
- }
+ zbx_vector_uint64_append_array(functionids, funcids.values, funcids.values_num);
+ zbx_vector_ptr_append(triggers_func_pos, tr_func_pos);
zbx_vector_uint64_clear(&funcids);
}
@@ -5117,7 +4926,7 @@ typedef struct
zbx_timespec_t timespec;
/* output data */
- char *value;
+ zbx_variant_t value;
char *error;
}
zbx_func_t;
@@ -5169,8 +4978,9 @@ static void func_clean(void *ptr)
zbx_free(func->function);
zbx_free(func->parameter);
- zbx_free(func->value);
zbx_free(func->error);
+
+ zbx_variant_clear(&func->value);
}
/******************************************************************************
@@ -5198,7 +5008,7 @@ static void zbx_populate_function_items(const zbx_vector_uint64_t *functionids,
zabbix_log(LOG_LEVEL_DEBUG, "In %s() functionids_num:%d", __func__, functionids->values_num);
- func_local.value = NULL;
+ zbx_variant_set_none(&func_local.value);
func_local.error = NULL;
functions = (DC_FUNCTION *)zbx_malloc(functions, sizeof(DC_FUNCTION) * functionids->values_num);
@@ -5248,7 +5058,7 @@ static void zbx_populate_function_items(const zbx_vector_uint64_t *functionids,
zabbix_log(LOG_LEVEL_DEBUG, "End of %s() ifuncs_num:%d", __func__, ifuncs->num_data);
}
-static void zbx_evaluate_item_functions(zbx_hashset_t *funcs, zbx_vector_ptr_t *unknown_msgs)
+static void zbx_evaluate_item_functions(zbx_hashset_t *funcs)
{
DC_ITEM *items = NULL;
char *error = NULL;
@@ -5278,8 +5088,7 @@ static void zbx_evaluate_item_functions(zbx_hashset_t *funcs, zbx_vector_ptr_t *
zbx_hashset_iter_reset(funcs, &iter);
while (NULL != (func = (zbx_func_t *)zbx_hashset_iter_next(&iter)))
{
- int ret_unknown = 0; /* flag raised if current function evaluates to ZBX_UNKNOWN */
- char *unknown_msg;
+ char *value = NULL;
i = zbx_vector_uint64_bsearch(&itemids, func->itemid, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
@@ -5309,59 +5118,40 @@ static void zbx_evaluate_item_functions(zbx_hashset_t *funcs, zbx_vector_ptr_t *
continue;
}
- /* If the item is NOTSUPPORTED then evaluation is allowed for: */
- /* - time-based functions and nodata(). Their values can be */
- /* evaluated to regular numbers even for NOTSUPPORTED items. */
- /* - other functions. Result of evaluation is ZBX_UNKNOWN. */
-
- if (ITEM_STATE_NOTSUPPORTED == items[i].state && FAIL == evaluatable_for_notsupported(func->function))
+ if (ITEM_STATE_NOTSUPPORTED == items[i].state &&
+ FAIL == zbx_evaluatable_for_notsupported(func->function))
{
- /* compose and store 'unknown' message for future use */
- unknown_msg = zbx_dsprintf(NULL,
+ /* set 'unknown' error value */
+ zbx_variant_set_error(&func->value, zbx_dsprintf(NULL,
"Cannot evaluate function \"%s:%s.%s(%s)\": item is not supported.",
- items[i].host.host, items[i].key_orig, func->function, func->parameter);
-
- zbx_free(func->error);
- zbx_vector_ptr_append(unknown_msgs, unknown_msg);
- ret_unknown = 1;
+ items[i].host.host, items[i].key_orig, func->function, func->parameter));
+ continue;
}
- if (0 == ret_unknown && SUCCEED != evaluate_function(&func->value, &items[i], func->function,
- func->parameter, &func->timespec, &error))
+ if (SUCCEED != evaluate_function(&value, &items[i], func->function, func->parameter, &func->timespec,
+ &error))
{
/* compose and store error message for future use */
if (NULL != error)
{
- unknown_msg = zbx_dsprintf(NULL,
+ zbx_variant_set_error(&func->value, zbx_dsprintf(NULL,
"Cannot evaluate function \"%s:%s.%s(%s)\": %s.",
items[i].host.host, items[i].key_orig, func->function,
- func->parameter, error);
-
- zbx_free(func->error);
+ func->parameter, error));
zbx_free(error);
}
else
{
- unknown_msg = zbx_dsprintf(NULL,
+ zbx_variant_set_error(&func->value, zbx_dsprintf(NULL,
"Cannot evaluate function \"%s:%s.%s(%s)\".",
items[i].host.host, items[i].key_orig,
- func->function, func->parameter);
-
- zbx_free(func->error);
+ func->function, func->parameter));
}
- zbx_vector_ptr_append(unknown_msgs, unknown_msg);
- ret_unknown = 1;
+ continue;
}
- if (0 != ret_unknown)
- {
- char buffer[MAX_ID_LEN + 1];
- /* write a special token of unknown value with 'unknown' message number, like */
- /* ZBX_UNKNOWN0, ZBX_UNKNOWN1 etc. not wrapped in () */
- zbx_snprintf(buffer, sizeof(buffer), ZBX_UNKNOWN_STR "%d", unknown_msgs->values_num - 1);
- func->value = zbx_strdup(func->value, buffer);
- }
+ zbx_variant_set_str(&func->value, value);
}
DCconfig_clean_items(items, errcodes, itemids.values_num);
@@ -5373,34 +5163,30 @@ static void zbx_evaluate_item_functions(zbx_hashset_t *funcs, zbx_vector_ptr_t *
zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
}
-static int substitute_expression_functions_results(zbx_hashset_t *ifuncs, char *expression, char **out,
- size_t *out_alloc, char **error)
+static int substitute_expression_functions_results(zbx_hashset_t *ifuncs, zbx_eval_context_t *ctx, char **error)
{
- char *br, *bl;
- size_t out_offset = 0;
zbx_uint64_t functionid;
zbx_func_t *func;
zbx_ifunc_t *ifunc;
+ int i;
- for (br = expression, bl = strchr(expression, '{'); NULL != bl; bl = strchr(bl, '{'))
+ for (i = 0; i < ctx->stack.values_num; i++)
{
- *bl = '\0';
- zbx_strcpy_alloc(out, out_alloc, &out_offset, br);
- *bl = '{';
+ zbx_eval_token_t *token = &ctx->stack.values[i];
- if (NULL == (br = strchr(bl, '}')))
+ if (ZBX_EVAL_TOKEN_FUNCTIONID != token->type)
+ continue;
+
+ if (ZBX_VARIANT_UI64 != token->value.type)
{
- *error = zbx_strdup(*error, "Invalid trigger expression");
+ /* functionids should be already extracted into uint64 vars */
+ THIS_SHOULD_NEVER_HAPPEN;
+ *error = zbx_dsprintf(*error, "Cannot parse function at: \"%s\"",
+ ctx->expression + token->loc.l);
return FAIL;
}
- *br = '\0';
-
- ZBX_STR2UINT64(functionid, bl + 1);
-
- *br++ = '}';
- bl = br;
-
+ functionid = token->value.data.ui64;
if (NULL == (ifunc = (zbx_ifunc_t *)zbx_hashset_search(ifuncs, &functionid)))
{
*error = zbx_dsprintf(*error, "Cannot obtain function"
@@ -5416,39 +5202,39 @@ static int substitute_expression_functions_results(zbx_hashset_t *ifuncs, char *
return FAIL;
}
- if (NULL == func->value)
+ if (ZBX_VARIANT_NONE == func->value.type)
{
*error = zbx_strdup(*error, "Unexpected error while processing a trigger expression");
return FAIL;
}
- if (SUCCEED != is_double_suffix(func->value, ZBX_FLAG_DOUBLE_SUFFIX) || '-' == *func->value)
- {
- zbx_chrcpy_alloc(out, out_alloc, &out_offset, '(');
- zbx_strcpy_alloc(out, out_alloc, &out_offset, func->value);
- zbx_chrcpy_alloc(out, out_alloc, &out_offset, ')');
- }
- else
- zbx_strcpy_alloc(out, out_alloc, &out_offset, func->value);
+ zbx_variant_copy(&token->value, &func->value);
}
- zbx_strcpy_alloc(out, out_alloc, &out_offset, br);
-
return SUCCEED;
}
+static void log_expression(const char *prefix, int index, const zbx_eval_context_t *ctx)
+{
+ if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_DEBUG))
+ {
+ char *expression = NULL;
+
+ zbx_eval_compose_expression(ctx, &expression);
+ zabbix_log(LOG_LEVEL_DEBUG, "%s() expression[%d]:'%s' => '%s'", prefix, index, ctx->expression,
+ expression);
+ zbx_free(expression);
+ }
+}
+
static void zbx_substitute_functions_results(zbx_hashset_t *ifuncs, zbx_vector_ptr_t *triggers)
{
DC_TRIGGER *tr;
- char *out = NULL;
- size_t out_alloc = TRIGGER_EXPRESSION_LEN_MAX;
int i;
zabbix_log(LOG_LEVEL_DEBUG, "In %s() ifuncs_num:%d tr_num:%d",
__func__, ifuncs->num_data, triggers->values_num);
- out = (char *)zbx_malloc(out, out_alloc);
-
for (i = 0; i < triggers->values_num; i++)
{
tr = (DC_TRIGGER *)triggers->values[i];
@@ -5456,35 +5242,26 @@ static void zbx_substitute_functions_results(zbx_hashset_t *ifuncs, zbx_vector_p
if (NULL != tr->new_error)
continue;
- if( SUCCEED != substitute_expression_functions_results(ifuncs, tr->expression, &out, &out_alloc,
- &tr->new_error))
+ if( SUCCEED != substitute_expression_functions_results(ifuncs, tr->eval_ctx, &tr->new_error))
{
tr->new_value = TRIGGER_VALUE_UNKNOWN;
continue;
}
- zabbix_log(LOG_LEVEL_DEBUG, "%s() expression[%d]:'%s' => '%s'", __func__, i, tr->expression, out);
-
- tr->expression = zbx_strdup(tr->expression, out);
+ log_expression(__func__, i, tr->eval_ctx);
if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == tr->recovery_mode)
{
- if (SUCCEED != substitute_expression_functions_results(ifuncs,
- tr->recovery_expression, &out, &out_alloc, &tr->new_error))
+ if (SUCCEED != substitute_expression_functions_results(ifuncs, tr->eval_ctx_r, &tr->new_error))
{
tr->new_value = TRIGGER_VALUE_UNKNOWN;
continue;
}
- zabbix_log(LOG_LEVEL_DEBUG, "%s() recovery_expression[%d]:'%s' => '%s'", __func__, i,
- tr->recovery_expression, out);
-
- tr->recovery_expression = zbx_strdup(tr->recovery_expression, out);
+ log_expression(__func__, i, tr->eval_ctx_r);
}
}
- zbx_free(out);
-
zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
}
@@ -5504,7 +5281,7 @@ static void zbx_substitute_functions_results(zbx_hashset_t *ifuncs, zbx_vector_p
* Comments: example: "({15}>10) or ({123}=1)" => "(26.416>10) or (0=1)" *
* *
******************************************************************************/
-static void substitute_functions(zbx_vector_ptr_t *triggers, zbx_vector_ptr_t *unknown_msgs)
+static void substitute_functions(zbx_vector_ptr_t *triggers)
{
zbx_vector_uint64_t functionids;
zbx_hashset_t ifuncs, funcs;
@@ -5527,7 +5304,7 @@ static void substitute_functions(zbx_vector_ptr_t *triggers, zbx_vector_ptr_t *u
if (0 != ifuncs.num_data)
{
- zbx_evaluate_item_functions(&funcs, unknown_msgs);
+ zbx_evaluate_item_functions(&funcs);
zbx_substitute_functions_results(&ifuncs, triggers);
}
@@ -5541,6 +5318,65 @@ empty:
/******************************************************************************
* *
+ * Function: prepare_triggers *
+ * *
+ * Purpose: prepare triggers for evaluation *
+ * *
+ * Parameters: triggers - [IN] array of DC_TRIGGER pointers *
+ * triggres_num - [IN] the number of triggers to prepare *
+ * *
+ ******************************************************************************/
+void prepare_triggers(DC_TRIGGER **triggers, int triggers_num)
+{
+ int i;
+
+ for (i = 0; i < triggers_num; i++)
+ {
+ DC_TRIGGER *tr = triggers[i];
+
+ tr->eval_ctx = zbx_eval_deserialize_dyn(tr->expression_bin, tr->expression, ZBX_EVAL_EXCTRACT_ALL);
+
+ if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == tr->recovery_mode)
+ {
+ tr->eval_ctx_r = zbx_eval_deserialize_dyn(tr->recovery_expression_bin, tr->recovery_expression,
+ ZBX_EVAL_EXCTRACT_ALL);
+ }
+ }
+}
+
+static int evaluate_expression(zbx_eval_context_t *ctx, const zbx_timespec_t *ts, double *result,
+ char **error)
+{
+ zbx_variant_t value;
+
+ if (SUCCEED != zbx_eval_execute(ctx, ts, &value, error))
+ return FAIL;
+
+ if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_DEBUG))
+ {
+ char *expression = NULL;
+
+ zbx_eval_compose_expression(ctx, &expression);
+ zabbix_log(LOG_LEVEL_DEBUG, "%s(): %s => %s", __func__, expression, zbx_variant_value_desc(&value));
+ zbx_free(expression);
+ }
+
+ if (SUCCEED != zbx_variant_convert(&value, ZBX_VARIANT_DBL))
+ {
+ *error = zbx_dsprintf(*error, "Cannot convert expression result of type \"%s\" to"
+ " floating point value", zbx_variant_type_desc(&value));
+ zbx_variant_clear(&value);
+
+ return FAIL;
+ }
+
+ *result = value.data.dbl;
+
+ return SUCCEED;
+}
+
+/******************************************************************************
+ * *
* Function: evaluate_expressions *
* *
* Purpose: evaluate trigger expressions *
@@ -5557,7 +5393,6 @@ void evaluate_expressions(zbx_vector_ptr_t *triggers)
DC_TRIGGER *tr;
int i;
double expr_result;
- zbx_vector_ptr_t unknown_msgs; /* pointers to messages about origins of 'unknown' values */
char err[MAX_STRING_LEN];
zabbix_log(LOG_LEVEL_DEBUG, "In %s() tr_num:%d", __func__, triggers->values_num);
@@ -5570,18 +5405,21 @@ void evaluate_expressions(zbx_vector_ptr_t *triggers)
event.value = tr->value;
- if (SUCCEED != expand_trigger_macros(&event, tr, err, sizeof(err)))
+ if (SUCCEED != expand_trigger_macros(tr->eval_ctx, &event, err, sizeof(err)))
{
tr->new_error = zbx_dsprintf(tr->new_error, "Cannot evaluate expression: %s", err);
tr->new_value = TRIGGER_VALUE_UNKNOWN;
}
- }
- /* Assumption: most often there will be no NOTSUPPORTED items and function errors. */
- /* Therefore initialize error messages vector but do not reserve any space. */
- zbx_vector_ptr_create(&unknown_msgs);
+ if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == tr->recovery_mode &&
+ SUCCEED != expand_trigger_macros(tr->eval_ctx_r, &event, err, sizeof(err)))
+ {
+ tr->new_error = zbx_dsprintf(tr->new_error, "Cannot evaluate expression: %s", err);
+ tr->new_value = TRIGGER_VALUE_UNKNOWN;
+ }
+ }
- substitute_functions(triggers, &unknown_msgs);
+ substitute_functions(triggers);
/* calculate new trigger values based on their recovery modes and expression evaluations */
for (i = 0; i < triggers->values_num; i++)
@@ -5591,12 +5429,8 @@ void evaluate_expressions(zbx_vector_ptr_t *triggers)
if (NULL != tr->new_error)
continue;
- if (SUCCEED != evaluate(&expr_result, tr->expression, err, sizeof(err), &unknown_msgs))
- {
- tr->new_error = zbx_strdup(tr->new_error, err);
- tr->new_value = TRIGGER_VALUE_UNKNOWN;
+ if (SUCCEED != evaluate_expression(tr->eval_ctx, &tr->timespec, &expr_result, &tr->new_error))
continue;
- }
/* trigger expression evaluates to true, set PROBLEM value */
if (SUCCEED != zbx_double_compare(expr_result, 0.0))
@@ -5624,9 +5458,8 @@ void evaluate_expressions(zbx_vector_ptr_t *triggers)
}
/* processing recovery expression mode */
- if (SUCCEED != evaluate(&expr_result, tr->recovery_expression, err, sizeof(err), &unknown_msgs))
+ if (SUCCEED != evaluate_expression(tr->eval_ctx_r, &tr->timespec, &expr_result, &tr->new_error))
{
- tr->new_error = zbx_strdup(tr->new_error, err);
tr->new_value = TRIGGER_VALUE_UNKNOWN;
continue;
}
@@ -5642,9 +5475,6 @@ void evaluate_expressions(zbx_vector_ptr_t *triggers)
tr->new_value = TRIGGER_VALUE_NONE;
}
- zbx_vector_ptr_clear_ext(&unknown_msgs, zbx_ptr_free);
- zbx_vector_ptr_destroy(&unknown_msgs);
-
if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_DEBUG))
{
for (i = 0; i < triggers->values_num; i++)
diff --git a/src/libs/zbxsysinfo/sysinfo.c b/src/libs/zbxsysinfo/sysinfo.c
index 9460f1f58d3..1cdec05eb76 100644
--- a/src/libs/zbxsysinfo/sysinfo.c
+++ b/src/libs/zbxsysinfo/sysinfo.c
@@ -187,8 +187,6 @@ int add_user_parameter(const char *itemkey, char *command, char *error, size_t m
metric.function = &EXECUTE_USER_PARAMETER;
metric.test_param = command;
- printf("[WDN] itemkey=%s, command=%s, metric.key=%s\n", itemkey, command, metric.key);
-
ret = add_metric(&metric, error, max_error_len);
}
else
diff --git a/src/libs/zbxtrends/trends.c b/src/libs/zbxtrends/trends.c
index 674dcd2d670..3ed8d841898 100644
--- a/src/libs/zbxtrends/trends.c
+++ b/src/libs/zbxtrends/trends.c
@@ -90,17 +90,16 @@ static int trends_parse_base(const char *period_shift, zbx_time_unit_t *base, ch
******************************************************************************/
int zbx_trends_parse_base(const char *params, zbx_time_unit_t *base, char **error)
{
- char *period_shift;
+ const char *period_shift;
int ret = FAIL;
- if (NULL == (period_shift = zbx_function_get_param_dyn(params, 2)))
+ if (NULL == (period_shift = strchr(params, ':')))
{
*error = zbx_strdup(*error, "missing period shift parameter");
return FAIL;
}
- ret = trends_parse_base(period_shift, base, error);
- zbx_free(period_shift);
+ ret = trends_parse_base(period_shift + 1, base, error);
return ret;
}
diff --git a/src/zabbix_server/escalator/escalator.c b/src/zabbix_server/escalator/escalator.c
index bd22ccbc22f..52a12fa6d16 100644
--- a/src/zabbix_server/escalator/escalator.c
+++ b/src/zabbix_server/escalator/escalator.c
@@ -1823,7 +1823,12 @@ static int check_escalation_trigger(zbx_uint64_t triggerid, unsigned char source
zbx_vector_uint64_create(&functionids);
zbx_vector_uint64_create(&itemids);
- get_functionids(&functionids, trigger.expression_orig);
+ zbx_get_serialized_expression_functionids(trigger.expression, trigger.expression_bin, &functionids);
+ if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == trigger.recovery_mode)
+ {
+ zbx_get_serialized_expression_functionids(trigger.recovery_expression, trigger.recovery_expression_bin,
+ &functionids);
+ }
functions = (DC_FUNCTION *)zbx_malloc(functions, sizeof(DC_FUNCTION) * functionids.values_num);
errcodes = (int *)zbx_malloc(errcodes, sizeof(int) * functionids.values_num);
diff --git a/src/zabbix_server/events.c b/src/zabbix_server/events.c
index c2e9b98818b..d4c8439b5da 100644
--- a/src/zabbix_server/events.c
+++ b/src/zabbix_server/events.c
@@ -155,12 +155,12 @@ static void process_item_tag(DB_EVENT* event, const zbx_item_tag_t *item_tag)
validate_and_add_tag(event, t);
}
-static void get_item_tags_by_expression(const char *expression, zbx_vector_ptr_t *item_tags)
+static void get_item_tags_by_expression(const DB_TRIGGER *trigger, zbx_vector_ptr_t *item_tags)
{
zbx_vector_uint64_t functionids;
zbx_vector_uint64_create(&functionids);
- get_functionids(&functionids, expression);
+ zbx_db_trigger_get_functionids(trigger, &functionids);
zbx_dc_get_item_tags_by_functionids(functionids.values, functionids.values_num, item_tags);
zbx_vector_uint64_destroy(&functionids);
}
@@ -240,6 +240,9 @@ DB_EVENT *zbx_add_event(unsigned char source, unsigned char object, zbx_uint64_t
event->trigger.opdata = zbx_strdup(NULL, trigger_opdata);
event->trigger.event_name = (NULL != event_name ? zbx_strdup(NULL, event_name) : NULL);
event->name = zbx_strdup(NULL, (NULL != event_name ? event_name : trigger_description));
+ event->trigger.cache = NULL;
+ event->trigger.url = NULL;
+ event->trigger.comments = NULL;
substitute_simple_macros(NULL, event, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
&event->trigger.correlation_tag, MACRO_TYPE_TRIGGER_TAG, err, sizeof(err));
@@ -256,7 +259,7 @@ DB_EVENT *zbx_add_event(unsigned char source, unsigned char object, zbx_uint64_t
}
zbx_vector_ptr_create(&item_tags);
- get_item_tags_by_expression(trigger_expression, &item_tags);
+ get_item_tags_by_expression(&event->trigger, &item_tags);
for (i = 0; i < item_tags.values_num; i++)
{
@@ -1476,7 +1479,7 @@ static void flush_correlation_queue(zbx_vector_ptr_t *trigger_diff, zbx_vector_u
close_trigger_event(recovery->eventid, recovery->objectid, &recovery->ts, 0,
recovery->correlationid, recovery->c_eventid, trigger->description,
- trigger->expression_orig, trigger->recovery_expression_orig,
+ trigger->expression, trigger->recovery_expression,
trigger->priority, trigger->type, trigger->opdata, trigger->event_name);
closed_num++;
@@ -1696,12 +1699,9 @@ static void zbx_clean_event(DB_EVENT *event)
if (EVENT_SOURCE_TRIGGERS == event->source)
{
- zbx_free(event->trigger.description);
- zbx_free(event->trigger.expression);
- zbx_free(event->trigger.recovery_expression);
+ zbx_db_trigger_clean(&event->trigger);
+
zbx_free(event->trigger.correlation_tag);
- zbx_free(event->trigger.opdata);
- zbx_free(event->trigger.event_name);
zbx_vector_ptr_clear_ext(&event->tags, (zbx_clean_func_t)zbx_free_tag);
zbx_vector_ptr_destroy(&event->tags);
@@ -1726,18 +1726,17 @@ void zbx_clean_events(void)
/******************************************************************************
* *
- * Function: get_hosts_by_expression *
+ * Function: db_trigger_get_hosts *
* *
- * Purpose: get hosts that are used in expression *
+ * Purpose: get hosts that are used trigger expression/recovery expression *
* *
******************************************************************************/
-static void get_hosts_by_expression(zbx_hashset_t *hosts, const char *expression, const char *recovery_expression)
+static void db_trigger_get_hosts(zbx_hashset_t *hosts, DB_TRIGGER *trigger)
{
zbx_vector_uint64_t functionids;
zbx_vector_uint64_create(&functionids);
- get_functionids(&functionids, expression);
- get_functionids(&functionids, recovery_expression);
+ zbx_db_trigger_get_all_functionids(trigger, &functionids);
DCget_hosts_by_functionids(&functionids, hosts);
zbx_vector_uint64_destroy(&functionids);
}
@@ -1793,8 +1792,7 @@ void zbx_export_events(void)
zbx_json_adduint64(&json, ZBX_PROTO_TAG_EVENTID, event->eventid);
zbx_json_addstring(&json, ZBX_PROTO_TAG_NAME, event->name, ZBX_JSON_TYPE_STRING);
- get_hosts_by_expression(&hosts, event->trigger.expression,
- event->trigger.recovery_expression);
+ db_trigger_get_hosts(&hosts, &event->trigger);
zbx_json_addarray(&json, ZBX_PROTO_TAG_HOSTS);
@@ -1901,8 +1899,7 @@ static void add_event_suppress_data(zbx_vector_ptr_t *event_refs, zbx_vector_uin
query->eventid = event->eventid;
zbx_vector_uint64_create(&query->functionids);
- get_functionids(&query->functionids, event->trigger.expression);
- get_functionids(&query->functionids, event->trigger.recovery_expression);
+ zbx_db_trigger_get_all_functionids(&event->trigger, &query->functionids);
zbx_vector_ptr_create(&query->tags);
if (0 != event->tags.values_num)
@@ -2813,7 +2810,7 @@ int zbx_close_problem(zbx_uint64_t triggerid, zbx_uint64_t eventid, zbx_uint64_t
DBbegin();
r_event = close_trigger_event(eventid, triggerid, &ts, userid, 0, 0, trigger.description,
- trigger.expression_orig, trigger.recovery_expression_orig, trigger.priority,
+ trigger.expression, trigger.recovery_expression, trigger.priority,
trigger.type, trigger.opdata, trigger.event_name);
r_event->eventid = DBget_maxid_num("events", 1);
diff --git a/src/zabbix_server/poller/checks_calculated.c b/src/zabbix_server/poller/checks_calculated.c
index 26fe1b89f7b..e0216dec64b 100644
--- a/src/zabbix_server/poller/checks_calculated.c
+++ b/src/zabbix_server/poller/checks_calculated.c
@@ -240,7 +240,7 @@ static int calcitem_evaluate_expression(expression_t *exp, char *error, size_t m
/* NOTSUPPORTED items. */
/* - other functions. Result of evaluation is ZBX_UNKNOWN. */
- if (ITEM_STATE_NOTSUPPORTED == items[i].state && FAIL == evaluatable_for_notsupported(f->func))
+ if (ITEM_STATE_NOTSUPPORTED == items[i].state && FAIL == zbx_evaluatable_for_notsupported(f->func))
{
/* compose and store 'unknown' message for future use */
unknown_msg = zbx_dsprintf(NULL,
diff --git a/tests/libs/zbxdbcache/dc_function_calculate_nextcheck.c b/tests/libs/zbxdbcache/dc_function_calculate_nextcheck.c
index d35438ff898..0eadec95d61 100644
--- a/tests/libs/zbxdbcache/dc_function_calculate_nextcheck.c
+++ b/tests/libs/zbxdbcache/dc_function_calculate_nextcheck.c
@@ -30,16 +30,21 @@
int zbx_dc_function_calculate_nextcheck(const zbx_trigger_timer_t *timer, time_t from, zbx_uint64_t seed);
-static int str_to_function_type(const char *str)
+/* copiedf from zbxdbcache/dbconfig.c */
+#define ZBX_TRIGGER_TIMER_TRIGGER 0x0001
+#define ZBX_TRIGGER_TIMER_FUNCTION_TIME 0x0002
+#define ZBX_TRIGGER_TIMER_FUNCTION_TREND 0x0004
+
+static int str_to_timer_type(const char *str)
{
- if (0 == strcmp(str, "ZBX_FUNCTION_TYPE_TIMER"))
- return ZBX_FUNCTION_TYPE_TIMER;
- if (0 == strcmp(str, "ZBX_FUNCTION_TYPE_TRENDS"))
- return ZBX_FUNCTION_TYPE_TRENDS;
- if (0 == strcmp(str, "ZBX_FUNCTION_TYPE_HISTORY"))
- return ZBX_FUNCTION_TYPE_HISTORY;
+ if (0 == strcmp(str, "ZBX_TRIGGER_TIMER_TRIGGER"))
+ return ZBX_TRIGGER_TIMER_TRIGGER;
+ if (0 == strcmp(str, "ZBX_TRIGGER_TIMER_FUNCTION_TIME"))
+ return ZBX_TRIGGER_TIMER_FUNCTION_TIME;
+ if (0 == strcmp(str, "ZBX_TRIGGER_TIMER_FUNCTION_TREND"))
+ return ZBX_TRIGGER_TIMER_FUNCTION_TREND;
- fail_msg("unknown function type \"%s\"", str);
+ fail_msg("unknown timer type \"%s\"", str);
return ZBX_FUNCTION_TYPE_UNKNOWN;
}
@@ -60,10 +65,10 @@ void zbx_mock_test_entry(void **state)
if (ZBX_MOCK_SUCCESS != zbx_strtime_to_timespec(zbx_mock_get_parameter_string("in.time"), &ts_from))
fail_msg("Invalid input time format");
- timer.type = str_to_function_type(zbx_mock_get_parameter_string("in.type"));
+ timer.type = str_to_timer_type(zbx_mock_get_parameter_string("in.type"));
timer.parameter = zbx_mock_get_parameter_string("in.params");
- if (ZBX_FUNCTION_TYPE_TRENDS == timer.type)
+ if (ZBX_TRIGGER_TIMER_FUNCTION_TREND == timer.type)
{
if (SUCCEED != zbx_trends_parse_base(timer.parameter, &timer.trend_base, &error))
{
diff --git a/tests/libs/zbxdbcache/dc_function_calculate_nextcheck.yaml b/tests/libs/zbxdbcache/dc_function_calculate_nextcheck.yaml
index 4c3414e3b74..de7cff99cb5 100644
--- a/tests/libs/zbxdbcache/dc_function_calculate_nextcheck.yaml
+++ b/tests/libs/zbxdbcache/dc_function_calculate_nextcheck.yaml
@@ -1,7 +1,7 @@
---
test case: Schedule time based trigger from 2020-09-01 00:00:00.000000000 +03:00
in:
- type: ZBX_FUNCTION_TYPE_TIMER
+ type: ZBX_TRIGGER_TIMER_FUNCTION_TIME
params:
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
@@ -10,7 +10,7 @@ out:
---
test case: Schedule time based trigger from 2020-09-01 00:00:15.000000000 +03:00
in:
- type: ZBX_FUNCTION_TYPE_TIMER
+ type: ZBX_TRIGGER_TIMER_FUNCTION_TIME
params:
timezone: :Europe/Riga
time: 2020-09-01 00:00:15.000000000 +03:00
@@ -19,107 +19,107 @@ out:
---
test case: Schedule time based trigger from 2020-09-01 00:00:30.000000000 +03:00
in:
- type: ZBX_FUNCTION_TYPE_TIMER
+ type: ZBX_TRIGGER_TIMER_FUNCTION_TIME
params:
timezone: :Europe/Riga
time: 2020-09-01 00:00:30.000000000 +03:00
out:
nextcheck: 2020-09-01 00:01:00.000000000 +03:00
---
-test case: Schedule 1h,now/h 2020-09-01 10:30:30.000000000 +03:00
+test case: Schedule 1h:now/h 2020-09-01 10:30:30.000000000 +03:00
in:
- type: ZBX_FUNCTION_TYPE_TRENDS
- params: 1h,now/h
+ type: ZBX_TRIGGER_TIMER_FUNCTION_TREND
+ params: 1h:now/h
timezone: :Europe/Riga
time: 2020-09-01 10:30:30.000000000 +03:00
out:
nextcheck: 2020-09-01 11:10:00.000000000 +03:00
---
-test case: Schedule 1h,now/h 2020-09-01 10:00:00.000000000 +03:00
+test case: Schedule 1h:now/h 2020-09-01 10:00:00.000000000 +03:00
in:
- type: ZBX_FUNCTION_TYPE_TRENDS
- params: 1h,now/h
+ type: ZBX_TRIGGER_TIMER_FUNCTION_TREND
+ params: 1h:now/h
timezone: :Europe/Riga
time: 2020-09-01 10:00:00.000000000 +03:00
out:
nextcheck: 2020-09-01 10:10:00.000000000 +03:00
---
-test case: Schedule 1h,now/h 2020-09-01 10:59:00.000000000 +03:00
+test case: Schedule 1h:now/h 2020-09-01 10:59:00.000000000 +03:00
in:
- type: ZBX_FUNCTION_TYPE_TRENDS
- params: 1h,now/h
+ type: ZBX_TRIGGER_TIMER_FUNCTION_TREND
+ params: 1h:now/h
timezone: :Europe/Riga
time: 2020-09-01 10:59:00.000000000 +03:00
out:
nextcheck: 2020-09-01 11:10:00.000000000 +03:00
---
-test case: Schedule 1h,now/d 2020-09-01 10:00:00.000000000 +03:00
+test case: Schedule 1h:now/d 2020-09-01 10:00:00.000000000 +03:00
in:
- type: ZBX_FUNCTION_TYPE_TRENDS
- params: 1h,now/d
+ type: ZBX_TRIGGER_TIMER_FUNCTION_TREND
+ params: 1h:now/d
timezone: :Europe/Riga
time: 2020-09-01 10:00:00.000000000 +03:00
out:
nextcheck: 2020-09-02 00:10:00.000000000 +03:00
---
-test case: Schedule 1h,now/M+1h 2020-09-01 10:00:00.000000000 +03:00
+test case: Schedule 1h:now/M+1h 2020-09-01 10:00:00.000000000 +03:00
in:
- type: ZBX_FUNCTION_TYPE_TRENDS
- params: 1h,now/M+1h
+ type: ZBX_TRIGGER_TIMER_FUNCTION_TREND
+ params: 1h:now/M+1h
timezone: :Europe/Riga
time: 2020-09-01 10:00:00.000000000 +03:00
out:
nextcheck: 2020-10-01 01:10:00.000000000 +03:00
---
-test case: Schedule 1h,now/M+1d 2020-09-01 10:00:00.000000000 +03:00
+test case: Schedule 1h:now/M+1d 2020-09-01 10:00:00.000000000 +03:00
in:
- type: ZBX_FUNCTION_TYPE_TRENDS
- params: 1h,now/M+1d
+ type: ZBX_TRIGGER_TIMER_FUNCTION_TREND
+ params: 1h:now/M+1d
timezone: :Europe/Riga
time: 2020-09-01 10:00:00.000000000 +03:00
out:
nextcheck: 2020-09-02 00:10:00.000000000 +03:00
---
-test case: Schedule 1h,now/M+1d 2020-09-02 10:00:00.000000000 +03:00
+test case: Schedule 1h:now/M+1d 2020-09-02 10:00:00.000000000 +03:00
in:
- type: ZBX_FUNCTION_TYPE_TRENDS
- params: 1h,now/M+1d
+ type: ZBX_TRIGGER_TIMER_FUNCTION_TREND
+ params: 1h:now/M+1d
timezone: :Europe/Riga
time: 2020-09-02 10:00:00.000000000 +03:00
out:
nextcheck: 2020-10-02 00:10:00.000000000 +03:00
---
-test case: Schedule 1d,now/M+6d/w+1d 2020-09-01 10:00:00.000000000 +03:00
+test case: Schedule 1d:now/M+6d/w+1d 2020-09-01 10:00:00.000000000 +03:00
in:
- type: ZBX_FUNCTION_TYPE_TRENDS
- params: 1h,now/M+6d/w+1d
+ type: ZBX_TRIGGER_TIMER_FUNCTION_TREND
+ params: 1h:now/M+6d/w+1d
timezone: :Europe/Riga
time: 2020-09-01 10:00:00.000000000 +03:00
out:
nextcheck: 2020-09-08 00:10:00.000000000 +03:00
---
-test case: Schedule 1d,now/M+6d/w+1d 2020-09-09 10:00:00.000000000 +03:00
+test case: Schedule 1d:now/M+6d/w+1d 2020-09-09 10:00:00.000000000 +03:00
in:
- type: ZBX_FUNCTION_TYPE_TRENDS
- params: 1h,now/M+6d/w+1d
+ type: ZBX_TRIGGER_TIMER_FUNCTION_TREND
+ params: 1h:now/M+6d/w+1d
timezone: :Europe/Riga
time: 2020-09-09 10:00:00.000000000 +03:00
out:
nextcheck: 2020-10-06 00:10:00.000000000 +03:00
---
-test case: Schedule 8h,now/d+17h 2020-09-01 10:00:00.000000000 +03:00
+test case: Schedule 8h:now/d+17h 2020-09-01 10:00:00.000000000 +03:00
in:
- type: ZBX_FUNCTION_TYPE_TRENDS
- params: 8h,now/d+17h
+ type: ZBX_TRIGGER_TIMER_FUNCTION_TREND
+ params: 8h:now/d+17h
timezone: :Europe/Riga
time: 2020-09-01 10:00:00.000000000 +03:00
out:
nextcheck: 2020-09-01 17:10:00.000000000 +03:00
---
-test case: Schedule 8h,now/d+17h 2020-09-01 18:00:00.000000000 +03:00
+test case: Schedule 8h:now/d+17h 2020-09-01 18:00:00.000000000 +03:00
in:
- type: ZBX_FUNCTION_TYPE_TRENDS
- params: 8h,now/d+17h
+ type: ZBX_TRIGGER_TIMER_FUNCTION_TREND
+ params: 8h:now/d+17h
timezone: :Europe/Riga
time: 2020-09-01 18:00:00.000000000 +03:00
out:
diff --git a/tests/libs/zbxeval/zbx_eval_execute.yaml b/tests/libs/zbxeval/zbx_eval_execute.yaml
index f87362f0fa9..dd99c430364 100644
--- a/tests/libs/zbxeval/zbx_eval_execute.yaml
+++ b/tests/libs/zbxeval/zbx_eval_execute.yaml
@@ -207,6 +207,14 @@ out:
result: SUCCEED
value: '1'
---
+test case: Expression '3<2'
+in:
+ rules: []
+ expression: '3<2'
+out:
+ result: SUCCEED
+ value: '0'
+---
test case: Expression '1<1'
in:
rules: []
diff --git a/ui/include/defines.inc.php b/ui/include/defines.inc.php
index 9cd8687be99..dc248420834 100644
--- a/ui/include/defines.inc.php
+++ b/ui/include/defines.inc.php
@@ -21,7 +21,7 @@
define('ZABBIX_VERSION', '5.4.0alpha1');
define('ZABBIX_API_VERSION', '5.4.0');
define('ZABBIX_EXPORT_VERSION', '5.4');
-define('ZABBIX_DB_VERSION', 5030025);
+define('ZABBIX_DB_VERSION', 5030026);
define('ZABBIX_COPYRIGHT_FROM', '2001');
define('ZABBIX_COPYRIGHT_TO', '2021');