diff options
author | Andris Zeila <andris.zeila@zabbix.com> | 2021-01-23 17:49:55 +0300 |
---|---|---|
committer | Andris Zeila <andris.zeila@zabbix.com> | 2021-01-23 17:49:55 +0300 |
commit | 5afa58b768619e2a636aa3b5ca6473a1621aeb2f (patch) | |
tree | 436dfe3e4c165e0a6eb017a316a50086e14d3b3d | |
parent | b4b45a38efb5caf817104ae263cef64cea3e8967 (diff) |
........S. [ZBXNEXT-6451] added caching of serialized trigger expressions
-rw-r--r-- | include/common.h | 2 | ||||
-rw-r--r-- | include/dbcache.h | 2 | ||||
-rw-r--r-- | include/zbxserialize.h | 6 | ||||
-rw-r--r-- | include/zbxserver.h | 13 | ||||
-rw-r--r-- | src/libs/zbxalgo/Makefile.am | 3 | ||||
-rw-r--r-- | src/libs/zbxcommon/str.c | 44 | ||||
-rw-r--r-- | src/libs/zbxdbcache/dbconfig.c | 118 | ||||
-rw-r--r-- | src/libs/zbxdbcache/dbconfig.h | 4 | ||||
-rw-r--r-- | src/libs/zbxdbcache/dbsync.c | 155 | ||||
-rw-r--r-- | src/libs/zbxdbcache/dbsync.h | 2 | ||||
-rw-r--r-- | src/libs/zbxserver/Makefile.am | 3 | ||||
-rw-r--r-- | src/libs/zbxserver/eval.c | 25 | ||||
-rw-r--r-- | src/libs/zbxserver/eval_execute.c | 38 | ||||
-rw-r--r-- | src/zabbix_proxy/Makefile.am | 2 | ||||
-rw-r--r-- | src/zabbix_server/Makefile.am | 2 | ||||
-rw-r--r-- | tests/libs/zbxserver/zbx_eval_compose_expression.c | 2 | ||||
-rw-r--r-- | tests/libs/zbxserver/zbx_eval_execute.c | 2 | ||||
-rw-r--r-- | tests/libs/zbxserver/zbx_eval_execute_ext.c | 2 | ||||
-rw-r--r-- | tests/libs/zbxserver/zbx_eval_parse_expression.c | 2 | ||||
-rw-r--r-- | tests/libs/zbxserver/zbx_eval_serialize.c | 4 |
20 files changed, 384 insertions, 47 deletions
diff --git a/include/common.h b/include/common.h index 9ce6001edab..a501e46711d 100644 --- a/include/common.h +++ b/include/common.h @@ -1684,4 +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); + #endif diff --git a/include/dbcache.h b/include/dbcache.h index 70daf1cd463..7759d3d645f 100644 --- a/include/dbcache.h +++ b/include/dbcache.h @@ -240,6 +240,8 @@ typedef struct _DC_TRIGGER char *correlation_tag; char *opdata; char *event_name; + unsigned char *expression_bin; + unsigned char *recovery_expression_bin; zbx_timespec_t timespec; int lastchange; unsigned char topoindex; diff --git a/include/zbxserialize.h b/include/zbxserialize.h index 8afc9787be5..47645e4337e 100644 --- a/include/zbxserialize.h +++ b/include/zbxserialize.h @@ -117,4 +117,10 @@ ) #endif + +/* complex serialization/deserialization functions */ + +zbx_uint32_t zbx_serialize_uint31_compact(unsigned char *ptr, zbx_uint32_t value); +zbx_uint32_t zbx_deserialize_uint31_compact(const unsigned char *ptr, zbx_uint32_t *value); + /* ZABBIX_SERIALIZE_H */ diff --git a/include/zbxserver.h b/include/zbxserver.h index ea80d304ecf..7864987b092 100644 --- a/include/zbxserver.h +++ b/include/zbxserver.h @@ -158,6 +158,7 @@ int xml_xpath_check(const char *xpath, char *error, size_t errlen); #define ZBX_EVAL_TOKEN_ARG_TIME (28 | ZBX_EVAL_CLASS_OPERAND) #define ZBX_EVAL_TOKEN_ARG_NULL (29 | ZBX_EVAL_CLASS_OPERAND) #define ZBX_EVAL_TOKEN_ARG_RAW (30 | ZBX_EVAL_CLASS_OPERAND) +#define ZBX_EVAL_TOKEN_EXCEPTION (31 | ZBX_EVAL_CLASS_FUNCTION) /* expression parsing rules */ @@ -241,14 +242,20 @@ typedef struct } zbx_eval_context_t; +typedef char *(*zbx_macro_resolve_func_t)(const char *str, size_t length, zbx_uint64_t *hostids, + int hostids_num); + int zbx_eval_parse_expression(zbx_eval_context_t *ctx, const char *expression, zbx_uint64_t rules, char **error); -void zbx_eval_clean(zbx_eval_context_t *ctx); -void zbx_eval_serialize(const zbx_eval_context_t *ctx, zbx_mem_malloc_func_t malloc_func, unsigned char **data); +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, const unsigned char *data); void zbx_eval_compose_expression(const zbx_eval_context_t *ctx, char **expression); 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_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); #endif diff --git a/src/libs/zbxalgo/Makefile.am b/src/libs/zbxalgo/Makefile.am index 17c668e3f8d..98b48c9b067 100644 --- a/src/libs/zbxalgo/Makefile.am +++ b/src/libs/zbxalgo/Makefile.am @@ -20,4 +20,5 @@ libzbxalgo_a_SOURCES = \ prediction.c \ queue.c \ vector.c \ - vectorimpl.h + vectorimpl.h \ + serialize.c diff --git a/src/libs/zbxcommon/str.c b/src/libs/zbxcommon/str.c index 54b9609491a..a88f16a33c7 100644 --- a/src/libs/zbxcommon/str.c +++ b/src/libs/zbxcommon/str.c @@ -6094,3 +6094,47 @@ const char *zbx_print_double(char *buffer, size_t size, double val) return buffer; } + +/****************************************************************************** + * * + * Function: zbx_strloc_unquote_dyn * + * * + * Purpose: unquotes substring at the specified location * + * * + * Parameters: src - [IN] the source string * + * loc - [IN] the substring location * + * * + * Return value: The unquoted and copied substring. * + * * + ******************************************************************************/ +char *zbx_strloc_unquote_dyn(const char *src, const zbx_strloc_t *loc) +{ + char *str, *ptr; + + src += loc->l + 1; + + str = ptr = zbx_malloc(NULL, loc->r - loc->l); + + while ('"' != *src) + { + if ('\\' == *src) + { + switch (*(++src)) + { + case '\\': + *ptr++ = '\\'; + break; + case '"': + *ptr++ = '"'; + break; + } + } + else + *ptr++ = *src; + src++; + } + *ptr = '\0'; + + return str; +} + diff --git a/src/libs/zbxdbcache/dbconfig.c b/src/libs/zbxdbcache/dbconfig.c index 192f672e4ae..b39240b2405 100644 --- a/src/libs/zbxdbcache/dbconfig.c +++ b/src/libs/zbxdbcache/dbconfig.c @@ -33,6 +33,7 @@ #include "zbxtasks.h" #include "../zbxcrypto/tls_tcp_active.h" #include "../zbxalgo/vectorimpl.h" +#include "base64.h" #define ZBX_DBCONFIG_IMPL #include "dbconfig.h" @@ -41,6 +42,7 @@ #include "actions.h" #include "zbxtrends.h" #include "zbxvault.h" +#include "zbxserialize.h" int sync_in_progress = 0; @@ -3585,6 +3587,40 @@ static void DCsync_prototype_items(zbx_dbsync_t *sync) zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } +static unsigned char *dup_serialized_expression(const unsigned char *src) +{ + zbx_uint32_t offset, len; + unsigned char *dst; + + if (NULL == src || '\0' == *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; + + dst = (unsigned char *)zbx_malloc(NULL, offset + len); + memcpy(dst, src, offset + len); + + return dst; +} + +static unsigned char *config_decode_serialized_expression(const char *src) +{ + unsigned char *dst; + int data_len, src_len; + + if (NULL == src || '\0' == *src) + return NULL; + + src_len = strlen(src) * 3 / 4; + dst = __config_mem_malloc_func(NULL, src_len); + str_base64_decode(src, (char *)dst, src_len, &data_len); + + return dst; +} + static void DCsync_triggers(zbx_dbsync_t *sync) { char **row; @@ -3634,6 +3670,16 @@ static void DCsync_triggers(zbx_dbsync_t *sync) __config_mem_free_func); trigger->topoindex = 1; } + else + { + if (NULL != trigger->expression_bin) + __config_mem_free_func((void *)trigger->expression_bin); + if (NULL != trigger->recovery_expression_bin) + __config_mem_free_func((void *)trigger->recovery_expression_bin); + } + + trigger->expression_bin = config_decode_serialized_expression(row[16]); + trigger->recovery_expression_bin = config_decode_serialized_expression(row[17]); } /* remove deleted triggers from buffer */ @@ -3685,6 +3731,11 @@ static void DCsync_triggers(zbx_dbsync_t *sync) zbx_vector_ptr_destroy(&trigger->tags); + if (NULL != trigger->expression_bin) + __config_mem_free_func((void *)trigger->expression_bin); + if (NULL != trigger->recovery_expression_bin) + __config_mem_free_func((void *)trigger->recovery_expression_bin); + zbx_hashset_remove_direct(&config->triggers, trigger); } zbx_vector_uint64_destroy(&functionids); @@ -7729,6 +7780,9 @@ static void DCget_trigger(DC_TRIGGER *dst_trigger, const ZBX_DC_TRIGGER *src_tri dst_trigger->expression = zbx_strdup(NULL, src_trigger->expression); dst_trigger->recovery_expression = zbx_strdup(NULL, src_trigger->recovery_expression); + dst_trigger->expression_bin = dup_serialized_expression(src_trigger->expression_bin); + dst_trigger->recovery_expression_bin = dup_serialized_expression(src_trigger->recovery_expression_bin); + zbx_vector_ptr_create(&dst_trigger->tags); if (0 != src_trigger->tags.values_num) @@ -7775,6 +7829,8 @@ static void DCclean_trigger(DC_TRIGGER *trigger) zbx_free(trigger->correlation_tag); zbx_free(trigger->opdata); zbx_free(trigger->event_name); + zbx_free(trigger->expression_bin); + zbx_free(trigger->recovery_expression_bin); zbx_vector_ptr_clear_ext(&trigger->tags, (zbx_clean_func_t)zbx_free_tag); zbx_vector_ptr_destroy(&trigger->tags); @@ -10621,6 +10677,68 @@ out: * Function: dc_expand_user_macros * * * * Purpose: expand user macros in the specified text value * + * * + * Parameters: text - [IN] the text value to expand * + * len - [IN] the text length * + * hostids - [IN] an array of related hostids * + * hostids_num - [IN] the number of hostids * + * * + * Return value: The text value with expanded user macros. Unknown or invalid * + * macros will be left unresolved. * + * * + * Comments: The returned value must be freed by the caller. * + * This function must be used only by configuration syncer * + * * + ******************************************************************************/ +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; + char *str = NULL, *name = NULL, *context = NULL, *value = NULL; + size_t str_alloc = 0, str_offset = 0; + + if ('\0' == *text) + return zbx_strdup(NULL, text); + + for (; SUCCEED == zbx_token_find(text, pos, &token, ZBX_TOKEN_SEARCH_BASIC) && token.loc.r < text_len; pos++) + { + if (ZBX_TOKEN_USER_MACRO != token.type) + continue; + + 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); + dc_get_user_macro(hostids, hostids_num, name, context, &value); + + if (NULL != value) + { + zbx_strcpy_alloc(&str, &str_alloc, &str_offset, value); + zbx_free(value); + } + else + { + zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + token.loc.l, + token.loc.r - token.loc.l + 1); + } + + zbx_free(name); + zbx_free(context); + + pos = token.loc.r; + last_pos = pos + 1; + } + + zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + last_pos, text_len - last_pos); + + return str; +} + +/****************************************************************************** + * * + * Function: dc_expand_user_macros * + * * + * Purpose: expand user macros in the specified text value * * WARNING - DO NOT USE FOR TRIGGERS, for triggers use the dedicated function * * * * Parameters: text - [IN] the text value to expand * diff --git a/src/libs/zbxdbcache/dbconfig.h b/src/libs/zbxdbcache/dbconfig.h index b874a3d3e14..7bb56a4d7fb 100644 --- a/src/libs/zbxdbcache/dbconfig.h +++ b/src/libs/zbxdbcache/dbconfig.h @@ -34,6 +34,8 @@ typedef struct const char *correlation_tag; const char *opdata; const char *event_name; + const unsigned char *expression_bin; + const unsigned char *recovery_expression_bin; int lastchange; unsigned char topoindex; unsigned char priority; @@ -909,4 +911,6 @@ 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); + #endif diff --git a/src/libs/zbxdbcache/dbsync.c b/src/libs/zbxdbcache/dbsync.c index a8f88d5c48a..7910d59ca78 100644 --- a/src/libs/zbxdbcache/dbsync.c +++ b/src/libs/zbxdbcache/dbsync.c @@ -22,6 +22,8 @@ #include "dbcache.h" #include "zbxserver.h" #include "mutexs.h" +#include "zbxserialize.h" +#include "base64.h" #define ZBX_DBCONFIG_IMPL #include "dbconfig.h" @@ -2060,6 +2062,56 @@ int zbx_dbsync_compare_prototype_items(zbx_dbsync_t *sync) /****************************************************************************** * * + * Function: dbsync_compare_serialized_expression * + * * + * Purpose: compare serialized expression * + * * + * Parameter: data1 - [IN] the base64 encoded expression * + * data2 - [IN] the serialized expression in cache * + * * + * Return value: SUCCEED - the expressions are identical * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int dbsync_compare_serialized_expression(const char *col, const unsigned char *data2) +{ + zbx_uint32_t offset1, len1, offset2, len2; + unsigned char *data1; + int col_len, data1_len, ret = FAIL; + + if (NULL == data2) + { + if (NULL == col || '\0' == *col) + return SUCCEED; + return FAIL; + } + + if (NULL == col || '\0' == *col) + return FAIL; + + col_len = strlen(col); + data1 = zbx_malloc(NULL, col_len); + + str_base64_decode(col, (char *)data1, col_len, &data1_len); + + offset1 = zbx_deserialize_uint31_compact((const unsigned char *)data1, &len1); + offset2 = zbx_deserialize_uint31_compact((const unsigned char *)data2, &len2); + + if (offset1 != offset2 || len1 != len2) + goto out; + + if (0 != memcmp(data1 + offset1, data2 + offset2, len1)) + goto out; + + ret = SUCCEED; +out: + zbx_free(data1); + + return ret; +} + +/****************************************************************************** + * * * Function: dbsync_compare_trigger * * * * Purpose: compares triggers table row with cached configuration data * @@ -2106,11 +2158,30 @@ static int dbsync_compare_trigger(const ZBX_DC_TRIGGER *trigger, const DB_ROW db if (FAIL == dbsync_compare_str(dbrow[15], trigger->event_name)) return FAIL; + if (FAIL == dbsync_compare_serialized_expression(dbrow[16], trigger->expression_bin)) + return FAIL; + + if (TRIGGER_RECOVERY_MODE_EXPRESSION == atoi(dbrow[10]) && + FAIL == dbsync_compare_serialized_expression(dbrow[17], trigger->recovery_expression_bin)) + { + return FAIL; + } + return SUCCEED; } -#define ZBX_DBSYNC_TRIGGER_COLUMN_EXPRESSION 0x01 -#define ZBX_DBSYNC_TRIGGER_COLUMN_RECOVERY_EXPRESSION 0x02 +static char *encode_expression(const zbx_eval_context_t *ctx) +{ + unsigned char *data; + size_t len; + char *str = NULL; + + len = zbx_eval_serialize(ctx, NULL, &data); + str_base64_encode_dyn((const char *)data, &str, len); + zbx_free(data); + + return str; +} /****************************************************************************** * * @@ -2124,41 +2195,61 @@ static int dbsync_compare_trigger(const ZBX_DC_TRIGGER *trigger, const DB_ROW db * * * Comments: The row preprocessing can be used to expand user macros in * * some columns. * + * During preprocessing trigger expression/recovery expression are * + * parsed, serialized and stored as base64 strings into 16,17 * + * columns. * * * ******************************************************************************/ static char **dbsync_trigger_preproc_row(char **row) { zbx_vector_uint64_t hostids, functionids; - unsigned char flags = 0; - - /* return the original row if user macros are not used in target columns */ - - if (SUCCEED == dbsync_check_row_macros(row, 2)) - flags |= ZBX_DBSYNC_TRIGGER_COLUMN_EXPRESSION; - - if (SUCCEED == dbsync_check_row_macros(row, 11)) - flags |= ZBX_DBSYNC_TRIGGER_COLUMN_RECOVERY_EXPRESSION; - - if (0 == flags) - return row; - - /* get associated host identifiers */ + zbx_eval_context_t ctx, ctx_r; + char *error; + unsigned char mode; zbx_vector_uint64_create(&hostids); zbx_vector_uint64_create(&functionids); - get_functionids(&functionids, row[2]); - get_functionids(&functionids, row[11]); + if (FAIL == zbx_eval_parse_expression(&ctx, row[2], ZBX_EVAL_TRIGGER_EXPRESSION, &error)) + { + zbx_eval_set_exception(&ctx, zbx_dsprintf(NULL, "cannot parse trigger expression: %s", error)); + zbx_free(error); + } + else + zbx_eval_get_functionids(&ctx, &functionids); + + 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)) + { + 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); + } dc_get_hostids_by_functionids(functionids.values, functionids.values_num, &hostids); - /* expand user macros */ + if (NULL != ctx.expression) + zbx_eval_expand_user_macros(&ctx, hostids.values, hostids.values_num, dc_expand_user_macros_len); - if (0 != (flags & ZBX_DBSYNC_TRIGGER_COLUMN_EXPRESSION)) - row[2] = dc_expand_user_macros_in_expression(row[2], hostids.values, hostids.values_num); + row[16] = encode_expression(&ctx); + zbx_eval_clear(&ctx); - if (0 != (flags & ZBX_DBSYNC_TRIGGER_COLUMN_RECOVERY_EXPRESSION)) - row[11] = dc_expand_user_macros_in_expression(row[11], hostids.values, hostids.values_num); + if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == mode) + { + if (NULL != ctx_r.expression) + { + zbx_eval_expand_user_macros(&ctx_r, hostids.values, hostids.values_num, + dc_expand_user_macros_len); + } + row[17] = encode_expression(&ctx_r); + zbx_eval_clear(&ctx_r); + } zbx_vector_uint64_destroy(&functionids); zbx_vector_uint64_destroy(&hostids); @@ -2177,6 +2268,9 @@ static char **dbsync_trigger_preproc_row(char **row) * Return value: SUCCEED - the changeset was successfully calculated * * FAIL - otherwise * * * + * Comment: The 16th and 17th fields (starting with 0) are placeholders for * + * serialized expression/recovery expression * + * * ******************************************************************************/ int zbx_dbsync_compare_triggers(zbx_dbsync_t *sync) { @@ -2191,7 +2285,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,opdata,event_name" + "t.correlation_mode,t.correlation_tag,t.opdata,t.event_name,null,null" " from hosts h,items i,functions f,triggers t" " where h.hostid=i.hostid" " and i.itemid=f.itemid" @@ -2204,7 +2298,7 @@ int zbx_dbsync_compare_triggers(zbx_dbsync_t *sync) return FAIL; } - dbsync_prepare(sync, 16, dbsync_trigger_preproc_row); + dbsync_prepare(sync, 18, dbsync_trigger_preproc_row); if (ZBX_DBSYNC_INIT == sync->mode) { @@ -2382,6 +2476,13 @@ static int dbsync_compare_function(const ZBX_DC_FUNCTION *function, const DB_ROW static char **dbsync_function_preproc_row(char **row) { zbx_uint64_t hostid; + const char *row3; + + /* first parameter is /host/key placeholder $, don't cache it */ + if (NULL == (row3 = strchr(row[3], ','))) + row3 = ""; + else + row3++; /* return the original row if user macros are not used in target columns */ if (SUCCEED == dbsync_check_row_macros(row, 3)) @@ -2389,8 +2490,10 @@ static char **dbsync_function_preproc_row(char **row) /* get associated host identifier */ ZBX_STR2UINT64(hostid, row[5]); - row[3] = dc_expand_user_macros_in_func_params(row[3], hostid); + row[3] = dc_expand_user_macros_in_func_params(row3, hostid); } + else + row[3] = zbx_strdup(NULL, row3); return row; } diff --git a/src/libs/zbxdbcache/dbsync.h b/src/libs/zbxdbcache/dbsync.h index b82f2889f4b..24f078f5305 100644 --- a/src/libs/zbxdbcache/dbsync.h +++ b/src/libs/zbxdbcache/dbsync.h @@ -46,6 +46,8 @@ # define ZBX_HOST_TLS_OFFSET 0 #endif +#define ZBX_DBSYNC_TRIGGER_ERROR 0x80 + /****************************************************************************** * * * Function: zbx_dbsync_preproc_row_func_t * diff --git a/src/libs/zbxserver/Makefile.am b/src/libs/zbxserver/Makefile.am index e3a5bdba0c1..debfef3b80e 100644 --- a/src/libs/zbxserver/Makefile.am +++ b/src/libs/zbxserver/Makefile.am @@ -11,7 +11,8 @@ libzbxserver_a_SOURCES = \ zabbix_stats.c \ zabbix_stats.h \ eval.c \ - eval_execute.c + eval_execute.c \ + eval_misc.c libzbxserver_server_a_SOURCES = \ zabbix_stats.h \ diff --git a/src/libs/zbxserver/eval.c b/src/libs/zbxserver/eval.c index f6c17eaa9f7..d3a22c85902 100644 --- a/src/libs/zbxserver/eval.c +++ b/src/libs/zbxserver/eval.c @@ -1057,6 +1057,7 @@ static void serialize_variant(unsigned char **buffer, size_t *size, const zbx_va 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; @@ -1125,14 +1126,14 @@ int zbx_eval_parse_expression(zbx_eval_context_t *ctx, const char *expression, z /****************************************************************************** * * - * Function: zbx_expression_eval_clean * + * Function: zbx_eval_clear * * * * Purpose: free resources allocated by evaluation context * * * * Parameters: ctx - [IN] the evaluation context * * * ******************************************************************************/ -void zbx_eval_clean(zbx_eval_context_t *ctx) +void zbx_eval_clear(zbx_eval_context_t *ctx) { eval_clean(ctx); } @@ -1155,15 +1156,16 @@ void zbx_eval_clean(zbx_eval_context_t *ctx) * Context serialization/deserialization must be used for * * context caching. * * * + * Return value: The size of serialized data. * * * ******************************************************************************/ -void zbx_eval_serialize(const zbx_eval_context_t *ctx, zbx_mem_malloc_func_t malloc_func, +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; + 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; + zbx_uint32_t len, len_offset; if (NULL == malloc_func) malloc_func = ZBX_DEFAULT_MEM_MALLOC_FUNC; @@ -1189,11 +1191,17 @@ void zbx_eval_serialize(const zbx_eval_context_t *ctx, zbx_mem_malloc_func_t mal } len = ptr - buffer; - *data = malloc_func(NULL, len); - memcpy(*data, buffer, len); + + 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; } /****************************************************************************** @@ -1212,12 +1220,13 @@ void zbx_eval_serialize(const zbx_eval_context_t *ctx, zbx_mem_malloc_func_t mal 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; + 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); diff --git a/src/libs/zbxserver/eval_execute.c b/src/libs/zbxserver/eval_execute.c index 54c1e143d80..649578de985 100644 --- a/src/libs/zbxserver/eval_execute.c +++ b/src/libs/zbxserver/eval_execute.c @@ -1120,6 +1120,40 @@ static int eval_execute_hist_function(const zbx_eval_context_t *ctx, const zbx_e /****************************************************************************** * * + * Function: eval_throw_execption * + * * + * Purpose: throw exception by returning the specified error * + * * + * Parameters: ctx - [IN] the evaluation context * + * token - [IN] the function token * + * output - [IN/OUT] the output value stack * + * error - [OUT] the error message in the case of failure * + * * + * Return value: FAIL - otherwise * + * * + ******************************************************************************/ +static int eval_throw_execption(const zbx_eval_context_t *ctx, const zbx_eval_token_t *token, + zbx_vector_var_t *output, char **error) +{ + zbx_variant_t *arg; + + if (1 != output->values_num || 1 != token->opt) + { + *error = zbx_dsprintf(*error, "exception must have one argument at \"%s\"", + ctx->expression + token->loc.l); + return FAIL; + } + + arg = &output->values[output->values_num - 1]; + zbx_variant_convert(arg, ZBX_VARIANT_STR); + *error = arg->data.str; + zbx_variant_set_none(arg); + + return FAIL; +} + +/****************************************************************************** + * * * Function: eval_execute * * * * Purpose: evaluate pre-parsed expression * @@ -1187,6 +1221,10 @@ static int eval_execute(const zbx_eval_context_t *ctx, zbx_variant_t *value, cha if (SUCCEED != eval_execute_push_value(ctx, token, &output, error)) goto out; break; + case ZBX_EVAL_TOKEN_EXCEPTION: + eval_throw_execption(ctx, token, &output, error); + ret = FAIL; + goto out; default: *error = zbx_dsprintf(*error, "unknown token at \"%s\"", ctx->expression + token->loc.l); diff --git a/src/zabbix_proxy/Makefile.am b/src/zabbix_proxy/Makefile.am index c5d55428da2..ae631ebbd9c 100644 --- a/src/zabbix_proxy/Makefile.am +++ b/src/zabbix_proxy/Makefile.am @@ -48,9 +48,9 @@ zabbix_proxy_LDADD = \ $(top_builddir)/src/libs/zbxsysinfo/simple/libsimplesysinfo.a \ $(top_builddir)/src/libs/zbxsysinfo/$(ARCH)/libspechostnamesysinfo.a \ $(top_builddir)/src/libs/zbxlog/libzbxlog.a \ + $(top_builddir)/src/libs/zbxdbcache/libzbxdbcache.a \ $(top_builddir)/src/libs/zbxserver/libzbxserver.a \ $(top_builddir)/src/libs/zbxserver/libzbxserver_proxy.a \ - $(top_builddir)/src/libs/zbxdbcache/libzbxdbcache.a \ $(top_builddir)/src/libs/zbxhistory/libzbxhistory.a \ $(top_builddir)/src/libs/zbxmemory/libzbxmemory.a \ $(top_builddir)/src/libs/zbxregexp/libzbxregexp.a \ diff --git a/src/zabbix_server/Makefile.am b/src/zabbix_server/Makefile.am index 25a12848a4c..010778462d0 100644 --- a/src/zabbix_server/Makefile.am +++ b/src/zabbix_server/Makefile.am @@ -74,8 +74,8 @@ zabbix_server_LDADD = \ $(top_builddir)/src/libs/zbxsysinfo/common/libcommonsysinfo.a \ $(top_builddir)/src/libs/zbxsysinfo/simple/libsimplesysinfo.a \ $(top_builddir)/src/libs/zbxlog/libzbxlog.a \ - $(top_builddir)/src/libs/zbxserver/libzbxserver.a \ $(top_builddir)/src/libs/zbxdbcache/libzbxdbcache.a \ + $(top_builddir)/src/libs/zbxserver/libzbxserver.a \ $(top_builddir)/src/libs/zbxhistory/libzbxhistory.a \ $(top_builddir)/src/libs/zbxmemory/libzbxmemory.a \ $(top_builddir)/src/libs/zbxregexp/libzbxregexp.a \ diff --git a/tests/libs/zbxserver/zbx_eval_compose_expression.c b/tests/libs/zbxserver/zbx_eval_compose_expression.c index 3ca1c916c66..93304098a8f 100644 --- a/tests/libs/zbxserver/zbx_eval_compose_expression.c +++ b/tests/libs/zbxserver/zbx_eval_compose_expression.c @@ -83,5 +83,5 @@ void zbx_mock_test_entry(void **state) zbx_mock_assert_str_eq("invalid composed expression", exp_expression, ret_expression); zbx_free(ret_expression); - zbx_eval_clean(&ctx); + zbx_eval_clear(&ctx); } diff --git a/tests/libs/zbxserver/zbx_eval_execute.c b/tests/libs/zbxserver/zbx_eval_execute.c index d1287bd6c2c..cbadac31aba 100644 --- a/tests/libs/zbxserver/zbx_eval_execute.c +++ b/tests/libs/zbxserver/zbx_eval_execute.c @@ -83,5 +83,5 @@ void zbx_mock_test_entry(void **state) } out: zbx_free(error); - zbx_eval_clean(&ctx); + zbx_eval_clear(&ctx); } diff --git a/tests/libs/zbxserver/zbx_eval_execute_ext.c b/tests/libs/zbxserver/zbx_eval_execute_ext.c index 9e113f1ee30..3258726834f 100644 --- a/tests/libs/zbxserver/zbx_eval_execute_ext.c +++ b/tests/libs/zbxserver/zbx_eval_execute_ext.c @@ -187,5 +187,5 @@ out: zbx_free(error); zbx_vector_ptr_clear_ext(&callbacks, (zbx_clean_func_t)mock_callback_free); zbx_vector_ptr_destroy(&callbacks); - zbx_eval_clean(&ctx); + zbx_eval_clear(&ctx); } diff --git a/tests/libs/zbxserver/zbx_eval_parse_expression.c b/tests/libs/zbxserver/zbx_eval_parse_expression.c index 47baff1bb51..ccccb5af419 100644 --- a/tests/libs/zbxserver/zbx_eval_parse_expression.c +++ b/tests/libs/zbxserver/zbx_eval_parse_expression.c @@ -209,7 +209,7 @@ void zbx_mock_test_entry(void **state) if (SUCCEED == expected_ret) compare_stack(&ctx, "out.stack"); - zbx_eval_clean(&ctx); + zbx_eval_clear(&ctx); zbx_free(error); } diff --git a/tests/libs/zbxserver/zbx_eval_serialize.c b/tests/libs/zbxserver/zbx_eval_serialize.c index 0a58c1d8286..db347eaf067 100644 --- a/tests/libs/zbxserver/zbx_eval_serialize.c +++ b/tests/libs/zbxserver/zbx_eval_serialize.c @@ -149,6 +149,6 @@ void zbx_mock_test_entry(void **state) mock_compare_stacks(&ctx1.stack, &ctx2.stack); - zbx_eval_clean(&ctx1); - zbx_eval_clean(&ctx2); + zbx_eval_clear(&ctx1); + zbx_eval_clear(&ctx2); } |