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-23 17:49:55 +0300
committerAndris Zeila <andris.zeila@zabbix.com>2021-01-23 17:49:55 +0300
commit5afa58b768619e2a636aa3b5ca6473a1621aeb2f (patch)
tree436dfe3e4c165e0a6eb017a316a50086e14d3b3d
parentb4b45a38efb5caf817104ae263cef64cea3e8967 (diff)
........S. [ZBXNEXT-6451] added caching of serialized trigger expressions
-rw-r--r--include/common.h2
-rw-r--r--include/dbcache.h2
-rw-r--r--include/zbxserialize.h6
-rw-r--r--include/zbxserver.h13
-rw-r--r--src/libs/zbxalgo/Makefile.am3
-rw-r--r--src/libs/zbxcommon/str.c44
-rw-r--r--src/libs/zbxdbcache/dbconfig.c118
-rw-r--r--src/libs/zbxdbcache/dbconfig.h4
-rw-r--r--src/libs/zbxdbcache/dbsync.c155
-rw-r--r--src/libs/zbxdbcache/dbsync.h2
-rw-r--r--src/libs/zbxserver/Makefile.am3
-rw-r--r--src/libs/zbxserver/eval.c25
-rw-r--r--src/libs/zbxserver/eval_execute.c38
-rw-r--r--src/zabbix_proxy/Makefile.am2
-rw-r--r--src/zabbix_server/Makefile.am2
-rw-r--r--tests/libs/zbxserver/zbx_eval_compose_expression.c2
-rw-r--r--tests/libs/zbxserver/zbx_eval_execute.c2
-rw-r--r--tests/libs/zbxserver/zbx_eval_execute_ext.c2
-rw-r--r--tests/libs/zbxserver/zbx_eval_parse_expression.c2
-rw-r--r--tests/libs/zbxserver/zbx_eval_serialize.c4
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);
}