diff options
author | Andris Zeila <andris.zeila@zabbix.com> | 2022-06-21 16:26:35 +0300 |
---|---|---|
committer | Andris Zeila <andris.zeila@zabbix.com> | 2022-06-21 16:26:35 +0300 |
commit | 52fadc279aa4abf360b0bf1f39499b53296c3db4 (patch) | |
tree | c48a316e6e2b121c8e3be7e5d02c06bdd31e9ce2 | |
parent | d1faf66c02fa53702e7a51dfc58faf65b67c0cc6 (diff) | |
parent | f3fb36f424064c1251a467e5f6b577c8f7508715 (diff) |
........S. [ZBX-21145] changed host, item and trigger tag merging logic during template linking and LLD to reduce database updates
Merge in ZBX/zabbix from feature/ZBX-21145-6.0 to release/6.0
* commit 'f3fb36f424064c1251a467e5f6b577c8f7508715': (21 commits)
........S. [ZBX-21145] fixed sql query when copying trigger tags during trigger linking
........S. [ZBX-21145] fixed trigger tak copying when linking templates
........S. [ZBX-21145] style fix
........S. [ZBX-21145] fixed item tag creation in LLD
........S. [ZBX-21145] fixed host prototype lookup result checking
........S. [ZBX-21145] fixed resetting of duplicate tag validation result
........S. [ZBX-21145] backported tag merging/validation
.D........ [ZBX-21145] added changelog entry
........S. [ZBX-21145] fixed warnings
........S. [ZBX-21145] added LLD error messages when host/item/trigger creation failed because of invalid tags
........S. [ZBX-21145] replaced trigger tag validation in lld with common tag validator
........S. [ZBX-21145] replaced item tag validation in lld with common tag validator
........S. [ZBX-21145] added common tag validator, replaced host tag validation in LLD
........S. [ZBX-21145] allow partial lld trigger update in the case of invalid tags
........S. [ZBX-21145] changed item tag LLD to allow item update with invalid tags
........S. [ZBX-21145] reworked lld trigger tag copying
........S. [ZBX-21145] reworked item LLD linking to use common tag merging logic
........S. [ZBX-21145] added auditlog support when copying template trigger tags
........S. [ZBX-21145] reworked trigger/trigger prototype template linking to use common tag merging logic (without auditlog updates)
........S. [ZBX-21145] reworked item/item prototype template linking to use common tag merging logic
...
-rw-r--r-- | ChangeLog.d/bugfix/ZBX-21145 | 1 | ||||
-rw-r--r-- | include/db.h | 10 | ||||
-rw-r--r-- | src/libs/zbxaudit/audit_trigger.c | 45 | ||||
-rw-r--r-- | src/libs/zbxaudit/audit_trigger.h | 6 | ||||
-rw-r--r-- | src/libs/zbxdbhigh/host.c | 96 | ||||
-rw-r--r-- | src/libs/zbxdbhigh/tag.c | 323 | ||||
-rw-r--r-- | src/libs/zbxdbhigh/template.h | 6 | ||||
-rw-r--r-- | src/libs/zbxdbhigh/template_item.c | 88 | ||||
-rw-r--r-- | src/libs/zbxdbhigh/trigger_linking.c | 304 | ||||
-rw-r--r-- | src/zabbix_server/lld/lld.h | 4 | ||||
-rw-r--r-- | src/zabbix_server/lld/lld_host.c | 136 | ||||
-rw-r--r-- | src/zabbix_server/lld/lld_item.c | 312 | ||||
-rw-r--r-- | src/zabbix_server/lld/lld_trigger.c | 343 |
13 files changed, 798 insertions, 876 deletions
diff --git a/ChangeLog.d/bugfix/ZBX-21145 b/ChangeLog.d/bugfix/ZBX-21145 new file mode 100644 index 00000000000..f7fe5e8c5fd --- /dev/null +++ b/ChangeLog.d/bugfix/ZBX-21145 @@ -0,0 +1 @@ +........S. [ZBX-21145] changed host, item and trigger tag merging logic during template linking and LLD to reduce database updates (wiper) diff --git a/include/db.h b/include/db.h index e2a192fd56c..82af4018dcd 100644 --- a/include/db.h +++ b/include/db.h @@ -83,8 +83,6 @@ zbx_graph_item_type; # define TRIGGER_COMMENTS_LEN 65535 #endif #define TRIGGER_EVENT_NAME_LEN 2048 -#define TAG_NAME_LEN 255 -#define TAG_VALUE_LEN 255 #define GROUP_NAME_LEN 255 @@ -176,7 +174,9 @@ zbx_graph_item_type; #define ITEM_PARAMETER_NAME_LEN 255 #define ITEM_PARAMETER_VALUE_LEN 2048 -#define ITEM_TAG_FIELD_LEN 255 +/* common tag/value field lengths for all tags */ +#define TAG_NAME_LEN 255 +#define TAG_VALUE_LEN 255 #define HISTORY_STR_VALUE_LEN 255 #define HISTORY_TEXT_VALUE_LEN 65535 @@ -894,12 +894,14 @@ typedef struct } zbx_db_tag_t; +ZBX_PTR_VECTOR_DECL(db_tag_ptr, zbx_db_tag_t *) + zbx_db_tag_t *zbx_db_tag_create(const char *tag_tag, const char *tag_value); void zbx_db_tag_free(zbx_db_tag_t *tag); int zbx_db_tag_compare_func(const void *d1, const void *d2); int zbx_db_tag_compare_func_template(const void *d1, const void *d2); -ZBX_PTR_VECTOR_DECL(db_tag_ptr, zbx_db_tag_t *) +int zbx_merge_tags(zbx_vector_db_tag_ptr_t *dst, zbx_vector_db_tag_ptr_t *src, const char *owner, char **error); typedef enum { diff --git a/src/libs/zbxaudit/audit_trigger.c b/src/libs/zbxaudit/audit_trigger.c index 4085a48c772..292d9e58035 100644 --- a/src/libs/zbxaudit/audit_trigger.c +++ b/src/libs/zbxaudit/audit_trigger.c @@ -351,20 +351,55 @@ void zbx_audit_trigger_update_json_delete_tags(zbx_uint64_t triggerid, int flags zbx_audit_update_json_append_no_value(triggerid, AUDIT_TRIGGER_ID, AUDIT_DETAILS_ACTION_DELETE, audit_key); } +#define TRIGGER_RESOURCE_KEY_RESOLVE_TAG(resource, nested) \ + if (AUDIT_RESOURCE_TRIGGER == resource_type) \ + { \ + zbx_snprintf(audit_key_##resource, sizeof(audit_key_##resource), "trigger.tag[" ZBX_FS_UI64 \ + "]"#nested#resource, triggertagid); \ + } \ + else if (AUDIT_RESOURCE_TRIGGER_PROTOTYPE == resource_type) \ + { \ + zbx_snprintf(audit_key_##resource, sizeof(audit_key_##resource), "triggerprototype.tag[" \ + ZBX_FS_UI64 "]"#nested#resource, triggertagid); \ + } \ + else \ + { \ + THIS_SHOULD_NEVER_HAPPEN; \ + return; \ + } + #define PREPARE_AUDIT_TRIGGER_UPDATE_TAG(resource, type1, type2) \ -void zbx_audit_trigger_update_json_update_tag_##resource(zbx_uint64_t triggerid, zbx_uint64_t triggertagid, \ - type1 resource##_old, type1 resource##_new) \ +void zbx_audit_trigger_update_json_update_tag_##resource(zbx_uint64_t triggerid, int trigger_flags, \ + zbx_uint64_t triggertagid, type1 resource##_old, type1 resource##_new) \ { \ - char buf[AUDIT_DETAILS_KEY_LEN]; \ + int resource_type; \ + char audit_key_##resource[AUDIT_DETAILS_KEY_LEN]; \ \ RETURN_IF_AUDIT_OFF(); \ + resource_type = trigger_flag_to_resource_type(trigger_flags); \ \ - zbx_snprintf(buf, sizeof(buf), "trigger.tags[" ZBX_FS_UI64 "]", triggertagid); \ + TRIGGER_RESOURCE_KEY_RESOLVE_TAG(resource,.) \ \ - zbx_audit_update_json_update_##type2(triggerid, AUDIT_TRIGGER_ID, buf, resource##_old, resource##_new); \ + zbx_audit_update_json_update_##type2(triggerid, AUDIT_TRIGGER_ID, audit_key_##resource, resource##_old, \ + resource##_new); \ } PREPARE_AUDIT_TRIGGER_UPDATE_TAG(tag, const char*, string) PREPARE_AUDIT_TRIGGER_UPDATE_TAG(value, const char*, string) #undef PREPARE_AUDIT_TRIGGER_UPDATE_TAG + +void zbx_audit_trigger_update_json_update_trigger_tag_create_entry(zbx_uint64_t triggerid, int trigger_flags, + zbx_uint64_t triggertagid) +{ + int resource_type; + char audit_key_[AUDIT_DETAILS_KEY_LEN]; + + RETURN_IF_AUDIT_OFF(); + + resource_type = trigger_flag_to_resource_type(trigger_flags); + + TRIGGER_RESOURCE_KEY_RESOLVE_TAG(,) + + zbx_audit_update_json_append_no_value(triggerid, AUDIT_TRIGGER_ID, AUDIT_DETAILS_ACTION_UPDATE, audit_key_); +} diff --git a/src/libs/zbxaudit/audit_trigger.h b/src/libs/zbxaudit/audit_trigger.h index 11f30420b3e..aadb3ceee84 100644 --- a/src/libs/zbxaudit/audit_trigger.h +++ b/src/libs/zbxaudit/audit_trigger.h @@ -62,10 +62,12 @@ void zbx_audit_trigger_update_json_remove_dependency(int flags, zbx_uint64_t tri void zbx_audit_trigger_update_json_add_tags_and_values(zbx_uint64_t triggerid, int flags, zbx_uint64_t triggertagid, const char *tag, const char *value); void zbx_audit_trigger_update_json_delete_tags(zbx_uint64_t triggerid, int flags, zbx_uint64_t triggertagid); +void zbx_audit_trigger_update_json_update_trigger_tag_create_entry(zbx_uint64_t trigger, int trigger_flags, + zbx_uint64_t tagid); #define PREPARE_AUDIT_TRIGGER_UPDATE_TAG_H(resource, type1) \ -void zbx_audit_trigger_update_json_update_tag_##resource(zbx_uint64_t triggerid, zbx_uint64_t triggertagid, \ - type1 resource##_old, type1 resource##_new); +void zbx_audit_trigger_update_json_update_tag_##resource(zbx_uint64_t triggerid, int trigger_flags, \ + zbx_uint64_t triggertagid, type1 resource##_old, type1 resource##_new); PREPARE_AUDIT_TRIGGER_UPDATE_TAG_H(tag, const char*) PREPARE_AUDIT_TRIGGER_UPDATE_TAG_H(value, const char*) diff --git a/src/libs/zbxdbhigh/host.c b/src/libs/zbxdbhigh/host.c index 71eefab809d..311db4ccc05 100644 --- a/src/libs/zbxdbhigh/host.c +++ b/src/libs/zbxdbhigh/host.c @@ -2014,6 +2014,7 @@ typedef struct zbx_vector_ptr_t group_prototypes; /* list of group prototypes */ zbx_vector_macros_t hostmacros; /* list of user macros */ zbx_vector_db_tag_ptr_t tags; /* list of host prototype tags */ + zbx_vector_db_tag_ptr_t new_tags; /* list of host prototype template tags */ zbx_vector_interfaces_t interfaces; /* list of interfaces */ char *host; char *name_orig; @@ -2105,6 +2106,8 @@ static void DBhost_prototype_clean(zbx_host_prototype_t *host_prototype) zbx_vector_macros_destroy(&host_prototype->hostmacros); zbx_vector_db_tag_ptr_clear_ext(&host_prototype->tags, zbx_db_tag_free); zbx_vector_db_tag_ptr_destroy(&host_prototype->tags); + zbx_vector_db_tag_ptr_clear_ext(&host_prototype->new_tags, zbx_db_tag_free); + zbx_vector_db_tag_ptr_destroy(&host_prototype->new_tags); zbx_vector_interfaces_clear_ext(&host_prototype->interfaces, DBhost_interface_free); zbx_vector_interfaces_destroy(&host_prototype->interfaces); DBgroup_prototypes_clean(&host_prototype->group_prototypes); @@ -2191,6 +2194,7 @@ static void DBhost_prototypes_make(zbx_uint64_t hostid, zbx_vector_uint64_t *tem zbx_vector_ptr_create(&host_prototype->group_prototypes); zbx_vector_macros_create(&host_prototype->hostmacros); zbx_vector_db_tag_ptr_create(&host_prototype->tags); + zbx_vector_db_tag_ptr_create(&host_prototype->new_tags); zbx_vector_interfaces_create(&host_prototype->interfaces); host_prototype->host = zbx_strdup(NULL, row[2]); host_prototype->name = zbx_strdup(NULL, row[3]); @@ -2956,20 +2960,18 @@ static void DBhost_prototypes_macros_make(zbx_vector_ptr_t *host_prototypes, zbx * * * Parameters: host_prototypes - [IN/OUT] list of host prototypes * * should be sorted by templateid * - * del_tagids - [OUT] list of host tagids which * - * should be deleted * * * * Comments: auxiliary function for DBcopy_template_host_prototypes() * * * ******************************************************************************/ -static void DBhost_prototypes_tags_make(zbx_vector_ptr_t *host_prototypes, zbx_vector_uint64_t *del_tagids) +static void DBhost_prototypes_tags_make(zbx_vector_ptr_t *host_prototypes) { DB_RESULT result; DB_ROW row; char *sql = NULL; size_t sql_alloc = 0, sql_offset = 0; zbx_vector_uint64_t hostids; - zbx_uint64_t hostid, tagid; + zbx_uint64_t hostid; zbx_host_prototype_t *host_prototype = NULL; zbx_db_tag_t *tag; int i; @@ -3010,7 +3012,7 @@ static void DBhost_prototypes_tags_make(zbx_vector_ptr_t *host_prototypes, zbx_v tag = zbx_db_tag_create(row[1], row[2]); tag->tagid = 0; - zbx_vector_db_tag_ptr_append(&host_prototype->tags, tag); + zbx_vector_db_tag_ptr_append(&host_prototype->new_tags, tag); } DBfree_result(result); @@ -3028,11 +3030,9 @@ static void DBhost_prototypes_tags_make(zbx_vector_ptr_t *host_prototypes, zbx_v zbx_vector_uint64_append(&hostids, host_prototype->hostid); } - /* replace existing tags with the new tags */ if (0 != hostids.values_num) { - int tag_index = 0; - zbx_host_prototype_t *host_prototype_local = NULL; + host_prototype = NULL; zbx_vector_uint64_sort(&hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); @@ -3045,55 +3045,37 @@ static void DBhost_prototypes_tags_make(zbx_vector_ptr_t *host_prototypes, zbx_v while (NULL != (row = DBfetch(result))) { - ZBX_STR2UINT64(tagid, row[0]); - ZBX_STR2UINT64(hostid, row[1]); + ZBX_DBROW2UINT64(hostid, row[1]); - if (NULL == host_prototype_local || host_prototype_local->hostid != hostid) + if (NULL == host_prototype || host_prototype->hostid != hostid) { - tag_index = 0; - for (i = 0; i < host_prototypes->values_num; i++) { - host_prototype_local = (zbx_host_prototype_t *)host_prototypes->values[i]; + host_prototype = (zbx_host_prototype_t *)host_prototypes->values[i]; - if (host_prototype_local->hostid == hostid) + if (host_prototype->hostid == hostid) break; } - if (NULL != host_prototype_local && host_prototype_local->hostid != hostid) + if (NULL == host_prototype || host_prototype->hostid != hostid) { THIS_SHOULD_NEVER_HAPPEN; continue; } } - if (NULL == host_prototype_local) - continue; - - if (tag_index < host_prototype_local->tags.values_num) - { - host_prototype_local->tags.values[tag_index]->tagid = tagid; - host_prototype_local->tags.values[tag_index]->flags |= ZBX_FLAG_DB_TAG_UPDATE_TAG | - ZBX_FLAG_DB_TAG_UPDATE_VALUE; - - host_prototype_local->tags.values[tag_index]->tag_orig = zbx_strdup(NULL, row[2]); - host_prototype_local->tags.values[tag_index]->value_orig = zbx_strdup(NULL, row[3]); - } - else - { - zbx_vector_uint64_append(del_tagids, tagid); - - zbx_audit_host_prototype_create_entry(AUDIT_ACTION_UPDATE, host_prototype_local->hostid, - host_prototype_local->host); - zbx_audit_host_prototype_update_json_delete_tag(host_prototype_local->hostid, tagid); - } - - tag_index++; + tag = zbx_db_tag_create(row[2], row[3]); + ZBX_DBROW2UINT64(tag->tagid, row[0]); + zbx_vector_db_tag_ptr_append(&host_prototype->tags, tag); } DBfree_result(result); } - zbx_vector_uint64_sort(del_tagids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + for (i = 0; i < host_prototypes->values_num; i++) + { + host_prototype = (zbx_host_prototype_t *)host_prototypes->values[i]; + (void)zbx_merge_tags(&host_prototype->tags, &host_prototype->new_tags, NULL, NULL); + } zbx_vector_uint64_destroy(&hostids); zbx_free(sql); @@ -3477,7 +3459,6 @@ static void DBhost_prototypes_interface_snmp_prepare_sql(zbx_uint64_t hostid, co * Parameters: host_prototypes - [IN] vector of host prototypes * * del_hosttemplateids - [IN] host template ids for delete * * del_hostmacroids - [IN] host macro ids for delete * - * del_tagids - [IN] tag ids for delete * * del_interfaceids - [IN] interface ids for delete * * del_snmpids - [IN] SNMP interface ids for delete * * db_insert_htemplates - [IN/OUT] templates insert structure * @@ -3485,8 +3466,8 @@ static void DBhost_prototypes_interface_snmp_prepare_sql(zbx_uint64_t hostid, co ******************************************************************************/ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, const zbx_vector_uint64_t *del_hosttemplateids, const zbx_vector_uint64_t *del_hostmacroids, - const zbx_vector_uint64_t *del_tagids, const zbx_vector_uint64_t *del_interfaceids, - const zbx_vector_uint64_t *del_snmpids, zbx_db_insert_t *db_insert_htemplates) + const zbx_vector_uint64_t *del_interfaceids, const zbx_vector_uint64_t *del_snmpids, + zbx_db_insert_t *db_insert_htemplates) { char *sql1 = NULL, *sql2 = NULL, *name_esc, *value_esc; size_t sql1_alloc = ZBX_KIBIBYTE, sql1_offset = 0, @@ -3505,12 +3486,13 @@ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, db_insert_hmacro, db_insert_tag, db_insert_iface, db_insert_snmp, db_insert_inventory_mode; zbx_vector_db_tag_ptr_t upd_tags; - zbx_vector_uint64_t del_inventory_modes_hostids; + zbx_vector_uint64_t del_inventory_modes_hostids, del_tagids; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); zbx_vector_db_tag_ptr_create(&upd_tags); zbx_vector_uint64_create(&del_inventory_modes_hostids); + zbx_vector_uint64_create(&del_tagids); for (i = 0; i < host_prototypes->values_num; i++) { @@ -3590,6 +3572,13 @@ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, tag->tagid, tag->value_orig, tag->value); } } + else if (ZBX_FLAG_DB_TAG_REMOVE == tag->flags) + { + zbx_audit_host_prototype_create_entry(AUDIT_ACTION_UPDATE, host_prototype->hostid, + host_prototype->host); + zbx_audit_host_prototype_update_json_delete_tag(host_prototype->hostid, tag->tagid); + zbx_vector_uint64_append(&del_tagids, tag->tagid); + } } for (j = 0; j < host_prototype->interfaces.values_num; j++) @@ -3634,7 +3623,7 @@ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, if (0 != new_hosts_templates) hosttemplateid = DBget_maxid_num("hosts_templates", new_hosts_templates); - if (0 != del_hosttemplateids->values_num || 0 != del_hostmacroids->values_num || 0 != del_tagids->values_num || + if (0 != del_hosttemplateids->values_num || 0 != del_hostmacroids->values_num || 0 != del_tagids.values_num || 0 != del_snmpids->values_num || 0 != del_interfaceids->values_num || 0 != del_inventory_modes_hostids.values_num) { @@ -3658,11 +3647,11 @@ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n"); } - if (0 != del_tagids->values_num) + if (0 != del_tagids.values_num) { zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from host_tag where"); - DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hosttagid", del_tagids->values, - del_tagids->values_num); + DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hosttagid", del_tagids.values, + del_tagids.values_num); zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n"); } @@ -4197,7 +4186,7 @@ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, } if (SUCCEED == res && (NULL != sql2 || 0 != del_hosttemplateids->values_num || - 0 != del_hostmacroids->values_num || 0 != del_tagids->values_num || + 0 != del_hostmacroids->values_num || 0 != del_tagids.values_num || 0 != del_interfaceids->values_num || 0 != del_snmpids->values_num || 0 != del_inventory_modes_hostids.values_num)) { @@ -4213,6 +4202,7 @@ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, zbx_vector_db_tag_ptr_destroy(&upd_tags); zbx_vector_uint64_destroy(&del_inventory_modes_hostids); + zbx_vector_uint64_destroy(&del_tagids); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } @@ -4245,26 +4235,24 @@ static void DBcopy_template_host_prototypes(zbx_uint64_t hostid, zbx_vector_uint if (0 != host_prototypes.values_num) { - zbx_vector_uint64_t del_hosttemplateids, del_group_prototypeids, del_macroids, del_tagids, - del_interfaceids, del_snmp_interfaceids; + zbx_vector_uint64_t del_hosttemplateids, del_group_prototypeids, del_macroids, del_interfaceids, + del_snmp_interfaceids; zbx_vector_uint64_create(&del_hosttemplateids); zbx_vector_uint64_create(&del_group_prototypeids); zbx_vector_uint64_create(&del_macroids); - zbx_vector_uint64_create(&del_tagids); zbx_vector_uint64_create(&del_interfaceids); zbx_vector_uint64_create(&del_snmp_interfaceids); DBhost_prototypes_templates_make(&host_prototypes, &del_hosttemplateids); DBhost_prototypes_groups_make(&host_prototypes, &del_group_prototypeids); DBhost_prototypes_macros_make(&host_prototypes, &del_macroids); - DBhost_prototypes_tags_make(&host_prototypes, &del_tagids); + DBhost_prototypes_tags_make(&host_prototypes); DBhost_prototypes_interfaces_make(&host_prototypes, &del_interfaceids, &del_snmp_interfaceids); - DBhost_prototypes_save(&host_prototypes, &del_hosttemplateids, &del_macroids, &del_tagids, + DBhost_prototypes_save(&host_prototypes, &del_hosttemplateids, &del_macroids, &del_interfaceids, &del_snmp_interfaceids, db_insert_htemplates); DBgroup_prototypes_delete(&del_group_prototypeids); - zbx_vector_uint64_destroy(&del_tagids); zbx_vector_uint64_destroy(&del_macroids); zbx_vector_uint64_destroy(&del_group_prototypeids); zbx_vector_uint64_destroy(&del_snmp_interfaceids); diff --git a/src/libs/zbxdbhigh/tag.c b/src/libs/zbxdbhigh/tag.c index 02e9506a461..9fbd4c38403 100644 --- a/src/libs/zbxdbhigh/tag.c +++ b/src/libs/zbxdbhigh/tag.c @@ -18,15 +18,18 @@ **/ #include "common.h" -#include "../zbxalgo/vectorimpl.h" +#include "../zbxalgo/vectorimpl.h" #include "db.h" +ZBX_PTR_VECTOR_IMPL(db_tag_ptr, zbx_db_tag_t *) + zbx_db_tag_t *zbx_db_tag_create(const char *tag_tag, const char *tag_value) { zbx_db_tag_t *tag; tag = (zbx_db_tag_t *)zbx_malloc(NULL, sizeof(zbx_db_tag_t)); + tag->tagid = 0; tag->flags = ZBX_FLAG_DB_TAG_UNSET; tag->tag = zbx_strdup(NULL, tag_tag); tag->value = zbx_strdup(NULL, tag_value); @@ -71,4 +74,320 @@ int zbx_db_tag_compare_func_template(const void *d1, const void *d2) return 0; } -ZBX_PTR_VECTOR_IMPL(db_tag_ptr, zbx_db_tag_t *) +/****************************************************************************** + * * + * Purpose: roll back tag updates done during merge process * + * * + * Return value: SUCCEED - updates were rolled back * + * FAIL - new tag, rollback impossible * + * * + ******************************************************************************/ +static int db_tag_rollback(zbx_db_tag_t *tag) +{ + if (0 == tag->tagid) + return FAIL; + + if (0 != (tag->flags & ZBX_FLAG_DB_TAG_UPDATE_TAG)) + { + zbx_free(tag->tag); + tag->tag = tag->tag_orig; + tag->tag_orig = NULL; + tag->flags &= (~ZBX_FLAG_DB_TAG_UPDATE_TAG); + } + + if (0 != (tag->flags & ZBX_FLAG_DB_TAG_UPDATE_VALUE)) + { + zbx_free(tag->value); + tag->value = tag->value_orig; + tag->value_orig = NULL; + tag->flags &= (~ZBX_FLAG_DB_TAG_UPDATE_VALUE); + } + + return SUCCEED; +} + +#define ZBX_TAG_OP(tag) (0 == tag->tagid ? "create" : "update") + +typedef enum +{ + ZBX_DB_TAG_TAG, + ZBX_DB_TAG_VALUE +} +zbx_db_tag_field_t; + +/****************************************************************************** + * * + * Purpose: check validness of a single tag field (tag or value) * + * * + * Return value: SUCCEED - tag field is valid * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int db_tag_check_field(const zbx_db_tag_t *tag, zbx_db_tag_field_t type, const char *owner, char **error) +{ + const char *field, *str; + size_t field_len, str_len; + + switch (type) + { + case ZBX_DB_TAG_TAG: + field = "tag"; + str = tag->tag; + field_len = TAG_NAME_LEN; + break; + case ZBX_DB_TAG_VALUE: + field = "value"; + str = tag->value; + field_len = TAG_VALUE_LEN; + break; + default: + THIS_SHOULD_NEVER_HAPPEN; + + if (NULL != *error) + { + *error = zbx_strdcatf(*error, "Cannot %s %s tag: invalid field type.\n", ZBX_TAG_OP(tag), + owner); + } + return FAIL; + } + + if (SUCCEED != zbx_is_utf8(str)) + { + if (NULL != error) + { + char *ptr_utf8; + + ptr_utf8 = zbx_strdup(NULL, str); + zbx_replace_invalid_utf8(ptr_utf8); + *error = zbx_strdcatf(*error, "Cannot %s %s tag: %s \"%s\" has invalid UTF-8 sequence.\n", + ZBX_TAG_OP(tag), owner, field, ptr_utf8); + zbx_free(ptr_utf8); + } + + return FAIL; + } + + str_len = zbx_strlen_utf8(str); + + if (field_len < str_len) + { + if (NULL != *error) + { + *error = zbx_strdcatf(*error, "Cannot %s %s tag: %s \"%128s...\" is too long.\n", + ZBX_TAG_OP(tag), owner, field, str); + } + return FAIL; + } + + return SUCCEED; +} + +/****************************************************************************** + * * + * Purpose: check validness of all fields for a list of tags * + * * + * Return value: SUCCEED - tags have valid fields * + * FAIL - otherwise * + * * + ******************************************************************************/ +static int check_tag_fields(zbx_vector_db_tag_ptr_t *tags, const char *owner, char **error) +{ + int i, ret = SUCCEED; + + for (i = 0; i < tags->values_num; i++) + { + zbx_db_tag_t *tag = tags->values[i]; + int errors = 0; + + if (0 != (tag->flags & ZBX_FLAG_DB_TAG_REMOVE)) + continue; + + if ('\0' == *tag->tag) + { + if (NULL != error) + { + *error = zbx_strdcatf(*error, "Cannot %s %s tag: empty tag name.\n", ZBX_TAG_OP(tag), + owner); + } + errors += FAIL; + } + + errors += db_tag_check_field(tag, ZBX_DB_TAG_TAG, owner, error); + errors += db_tag_check_field(tag, ZBX_DB_TAG_VALUE, owner, error); + + if (0 > errors) + { + if (SUCCEED != db_tag_rollback(tag)) + { + zbx_db_tag_free(tag); + zbx_vector_db_tag_ptr_remove_noorder(tags, i--); + } + + ret = FAIL; + } + } + + return ret; +} + +/****************************************************************************** + * * + * Purpose: check new tags for duplicate tag+value combinations * + * * + * Parameters: tags - [IN/OUT] the tags to check * + * owner - [IN] the owned object (host, item, trigger) * + * error - [OUT] the error message * + * * + * Return value: SUCCEED - tags have no duplicates * + * FAIL - otherwise * + * * + * Comments: Existing tags are rolled back to their original values, while * + * new tags are removed. * + * * + ******************************************************************************/ +static int check_duplicate_tags(zbx_vector_db_tag_ptr_t *tags, const char *owner, char **error) +{ + int i, j, ret = SUCCEED; + + for (i = 0; i < tags->values_num; i++) + { + zbx_db_tag_t *left = tags->values[i]; + + for (j = 0; j < i; j++) + { + zbx_db_tag_t *right = tags->values[j]; + + if (0 == strcmp(left->tag, right->tag) && 0 == strcmp(left->value, right->value)) + { + if (NULL != error) + { + *error = zbx_strdcatf(*error, "Cannot %s %s tag: \"%s: %s\" already exists.\n", + ZBX_TAG_OP(left), owner, left->tag, right->value); + } + + zbx_db_tag_free(left); + zbx_vector_db_tag_ptr_remove_noorder(tags, i--); + + ret = FAIL; + break; + } + } + } + + return ret; +} + +/****************************************************************************** + * * + * Purpose: merge new tags into existing * + * * + * Parameters: dst - [IN/OUT] vector of existing tags * + * src - [IN/OUT] vector or new tags * + * owner - [IN] the tag owner (host, item, trigger), * + * optional - must be specified if error parameter * + * is not null * + * error - [IN,OUT] the error message (appended to existing), * + * optional * + * * + * Comments: The tags are merged using the following logic: * + * 1) tags with matching name+value are left as it is * + * 2) tags with matching names will have their values updated * + * 3) tags without matches will have: * + * a) their name and value updated if there are new tags left * + * b) flagged to be removed otherwise * + * 4) all leftover new tags will be created * + * * + * Return value: SUCCEED - tags were merged without issues * + * FAIL - tags were merged with errors * + * * + ******************************************************************************/ +int zbx_merge_tags(zbx_vector_db_tag_ptr_t *dst, zbx_vector_db_tag_ptr_t *src, const char *owner, char **error) +{ + int i, j, ret; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s() old_tags:%d new_tags:%d", __func__, dst->values_num, src->values_num); + + ret = check_duplicate_tags(src, owner, error); + + /* perform exact tag + value match */ + for (i = 0; i < dst->values_num; i++) + { + for (j = 0; j < src->values_num; j++) + { + if (0 == strcmp(dst->values[i]->tag, src->values[j]->tag) && + 0 == strcmp(dst->values[i]->value, src->values[j]->value)) + { + break; + } + } + + if (j != src->values_num) + { + zbx_db_tag_free(src->values[j]); + zbx_vector_db_tag_ptr_remove_noorder(src, j); + continue; + } + + dst->values[i]->flags = ZBX_FLAG_DB_TAG_REMOVE; + } + + if (0 == src->values_num) + goto out; + + /* perform tag match */ + for (i = 0; i < dst->values_num; i++) + { + if (ZBX_FLAG_DB_TAG_REMOVE != dst->values[i]->flags) + continue; + + for (j = 0; j < src->values_num; j++) + { + if (0 == strcmp(dst->values[i]->tag, src->values[j]->tag)) + break; + } + + if (j != src->values_num) + { + dst->values[i]->value_orig = dst->values[i]->value; + dst->values[i]->value = src->values[j]->value; + dst->values[i]->flags = ZBX_FLAG_DB_TAG_UPDATE_VALUE; + src->values[j]->value = NULL; + zbx_db_tag_free(src->values[j]); + zbx_vector_db_tag_ptr_remove_noorder(src, j); + continue; + } + } + + if (0 == src->values_num) + goto out; + + /* update rest of the tags */ + for (i = 0; i < dst->values_num && 0 < src->values_num; i++) + { + if (ZBX_FLAG_DB_TAG_REMOVE != dst->values[i]->flags) + continue; + + dst->values[i]->tag_orig = dst->values[i]->tag; + dst->values[i]->value_orig = dst->values[i]->value; + dst->values[i]->tag = src->values[0]->tag; + dst->values[i]->value = src->values[0]->value; + dst->values[i]->flags = ZBX_FLAG_DB_TAG_UPDATE_TAG | ZBX_FLAG_DB_TAG_UPDATE_VALUE; + src->values[0]->tag = NULL; + src->values[0]->value = NULL; + zbx_db_tag_free(src->values[0]); + zbx_vector_db_tag_ptr_remove_noorder(src, 0); + } + + /* add leftover new tags */ + zbx_vector_db_tag_ptr_append_array(dst, src->values, src->values_num); + zbx_vector_db_tag_ptr_clear(src); +out: + if (SUCCEED != check_tag_fields(dst, owner, error)) + ret = FAIL; + + zbx_vector_db_tag_ptr_sort(dst, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s() tags:%d", __func__, dst->values_num); + + return ret; +} diff --git a/src/libs/zbxdbhigh/template.h b/src/libs/zbxdbhigh/template.h index 737e203fd59..aeae77e1309 100644 --- a/src/libs/zbxdbhigh/template.h +++ b/src/libs/zbxdbhigh/template.h @@ -28,8 +28,6 @@ typedef struct _zbx_template_item_preproc_t zbx_template_item_preproc_t; ZBX_PTR_VECTOR_DECL(item_preproc_ptr, zbx_template_item_preproc_t *) -ZBX_PTR_VECTOR_DECL(item_tag_ptr, zbx_db_tag_t *) - typedef struct _zbx_template_item_param_t zbx_template_item_param_t; ZBX_PTR_VECTOR_DECL(item_param_ptr, zbx_template_item_param_t *) @@ -190,8 +188,8 @@ typedef struct zbx_vector_ptr_t dependent_items; zbx_vector_item_preproc_ptr_t item_preprocs; zbx_vector_item_preproc_ptr_t template_preprocs; - zbx_vector_item_tag_ptr_t item_tags; - zbx_vector_item_tag_ptr_t template_tags; + zbx_vector_db_tag_ptr_t item_tags; + zbx_vector_db_tag_ptr_t template_tags; zbx_vector_item_param_ptr_t item_params; zbx_vector_item_param_ptr_t template_params; zbx_vector_lld_macro_ptr_t item_lld_macros; diff --git a/src/libs/zbxdbhigh/template_item.c b/src/libs/zbxdbhigh/template_item.c index 863dd105dc1..cd095ef3834 100644 --- a/src/libs/zbxdbhigh/template_item.c +++ b/src/libs/zbxdbhigh/template_item.c @@ -57,8 +57,6 @@ struct _zbx_template_item_preproc_t ZBX_PTR_VECTOR_IMPL(item_preproc_ptr, zbx_template_item_preproc_t *) -ZBX_PTR_VECTOR_IMPL(item_tag_ptr, zbx_db_tag_t *) - struct _zbx_template_item_param_t { zbx_uint64_t item_parameterid; @@ -505,8 +503,8 @@ static void get_template_items(zbx_uint64_t hostid, const zbx_vector_uint64_t *t zbx_vector_ptr_create(&item->dependent_items); zbx_vector_item_preproc_ptr_create(&item->item_preprocs); zbx_vector_item_preproc_ptr_create(&item->template_preprocs); - zbx_vector_item_tag_ptr_create(&item->item_tags); - zbx_vector_item_tag_ptr_create(&item->template_tags); + zbx_vector_db_tag_ptr_create(&item->item_tags); + zbx_vector_db_tag_ptr_create(&item->template_tags); zbx_vector_item_param_ptr_create(&item->item_params); zbx_vector_item_param_ptr_create(&item->template_params); zbx_vector_lld_macro_ptr_create(&item->item_lld_macros); @@ -1399,16 +1397,16 @@ static void free_template_item(zbx_template_item_t *item) zbx_vector_ptr_destroy(&item->dependent_items); zbx_vector_item_preproc_ptr_clear_ext(&item->item_preprocs, zbx_item_preproc_free); zbx_vector_item_preproc_ptr_clear_ext(&item->template_preprocs, zbx_item_preproc_free); - zbx_vector_item_tag_ptr_clear_ext(&item->item_tags, zbx_db_tag_free); - zbx_vector_item_tag_ptr_clear_ext(&item->template_tags, zbx_db_tag_free); + zbx_vector_db_tag_ptr_clear_ext(&item->item_tags, zbx_db_tag_free); + zbx_vector_db_tag_ptr_clear_ext(&item->template_tags, zbx_db_tag_free); zbx_vector_item_param_ptr_clear_ext(&item->item_params, zbx_item_params_free); zbx_vector_item_param_ptr_clear_ext(&item->template_params, zbx_item_params_free); zbx_vector_lld_macro_ptr_clear_ext(&item->item_lld_macros, zbx_lld_macros_free); zbx_vector_lld_macro_ptr_clear_ext(&item->template_lld_macros, zbx_lld_macros_free); zbx_vector_item_preproc_ptr_destroy(&item->item_preprocs); zbx_vector_item_preproc_ptr_destroy(&item->template_preprocs); - zbx_vector_item_tag_ptr_destroy(&item->item_tags); - zbx_vector_item_tag_ptr_destroy(&item->template_tags); + zbx_vector_db_tag_ptr_destroy(&item->item_tags); + zbx_vector_db_tag_ptr_destroy(&item->template_tags); zbx_vector_item_param_ptr_destroy(&item->item_params); zbx_vector_item_param_ptr_destroy(&item->template_params); zbx_vector_lld_macro_ptr_destroy(&item->item_lld_macros); @@ -1821,6 +1819,8 @@ static void copy_template_item_tags(const zbx_vector_ptr_t *items) if (0 != deleteids.values_num) { + zbx_vector_uint64_sort(&deleteids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + sql_offset = 0; zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "delete from item_tag where"); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemtagid", deleteids.values, @@ -2882,7 +2882,7 @@ static void link_template_items_tag(const zbx_vector_uint64_t *templateids, zbx_ char *sql = NULL; size_t sql_alloc = 0, sql_offset = 0; zbx_uint64_t itemid; - zbx_db_tag_t *ptsrc, *ptdst; + zbx_db_tag_t *db_tag; zbx_template_item_t *item; zbx_hashset_t items_t; zbx_vector_uint64_t itemids; @@ -2926,9 +2926,9 @@ static void link_template_items_tag(const zbx_vector_uint64_t *templateids, zbx_ } item = (zbx_template_item_t *)items->values[index]; - ptdst = zbx_db_tag_create(row[2], row[3]); - ZBX_STR2UINT64(ptdst->tagid, row[0]); - zbx_vector_item_tag_ptr_append(&item->item_tags, ptdst); + db_tag = zbx_db_tag_create(row[2], row[3]); + ZBX_STR2UINT64(db_tag->tagid, row[0]); + zbx_vector_db_tag_ptr_append(&item->item_tags, db_tag); } DBfree_result(result); @@ -2938,7 +2938,7 @@ static void link_template_items_tag(const zbx_vector_uint64_t *templateids, zbx_ } zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, - "select it.itemtagid,it.itemid,it.tag,it.value" + "select it.itemid,it.tag,it.value" " from item_tag it,items ti" " where it.itemid=ti.itemid" " and"); @@ -2950,7 +2950,7 @@ static void link_template_items_tag(const zbx_vector_uint64_t *templateids, zbx_ { zbx_template_item_t item_local, *pitem_local = &item_local, **pitem; - ZBX_STR2UINT64(item_local.templateid, row[1]); + ZBX_STR2UINT64(item_local.templateid, row[0]); if (NULL == (pitem = (zbx_template_item_t **)zbx_hashset_search(&items_t, &pitem_local))) { @@ -2958,70 +2958,16 @@ static void link_template_items_tag(const zbx_vector_uint64_t *templateids, zbx_ continue; } - ptdst = zbx_db_tag_create(row[2], row[3]); - ZBX_STR2UINT64(ptdst->tagid, row[0]); - zbx_vector_item_tag_ptr_append(&(*pitem)->template_tags, ptdst); + db_tag = zbx_db_tag_create(row[1], row[2]); + zbx_vector_db_tag_ptr_append(&(*pitem)->template_tags, db_tag); } DBfree_result(result); zbx_free(sql); for (i = 0; i < items->values_num; i++) { - int j, tag_num; - char *buffer = NULL; - item = (zbx_template_item_t *)items->values[i]; - - zbx_vector_item_tag_ptr_sort(&item->item_tags, zbx_db_tag_compare_func_template); - zbx_vector_item_tag_ptr_sort(&item->template_tags, zbx_db_tag_compare_func_template); - - tag_num = MAX(item->item_tags.values_num, item->template_tags.values_num); - - for (j = 0; j < tag_num; j++) - { - if (j >= item->item_tags.values_num) - { - ptsrc = (zbx_db_tag_t *)item->template_tags.values[j]; - ptdst = zbx_db_tag_create(ptsrc->tag, ptsrc->value); - ptdst->tagid = 0; - zbx_vector_item_tag_ptr_append(&item->item_tags, ptdst); - continue; - } - - ptdst = (zbx_db_tag_t *)item->item_tags.values[j]; - - if (j >= item->template_tags.values_num) - { - ptdst->flags |= ZBX_FLAG_DB_TAG_REMOVE; - continue; - } - - ptsrc = (zbx_db_tag_t *)item->template_tags.values[j]; - - buffer = zbx_strdup(buffer, ptsrc->tag); - - if (0 != strcmp(ptdst->tag, buffer)) - { - ptdst->tag_orig = zbx_strdup(NULL, ptdst->tag); - zbx_free(ptdst->tag); - ptdst->tag = buffer; - buffer = NULL; - ptdst->flags |= ZBX_FLAG_DB_TAG_UPDATE_TAG; - } - - buffer = zbx_strdup(buffer, ptsrc->value); - - if (0 != strcmp(ptdst->value, buffer)) - { - ptdst->value_orig = zbx_strdup(NULL, ptdst->value); - zbx_free(ptdst->value); - ptdst->value = buffer; - buffer = NULL; - ptdst->flags |= ZBX_FLAG_DB_TAG_UPDATE_VALUE; - } - else - zbx_free(buffer); - } + (void)zbx_merge_tags(&item->item_tags, &item->template_tags, NULL, NULL); } zbx_hashset_destroy(&items_t); zbx_vector_uint64_destroy(&itemids); diff --git a/src/libs/zbxdbhigh/trigger_linking.c b/src/libs/zbxdbhigh/trigger_linking.c index 09023346bc6..1b90d5a2fe8 100644 --- a/src/libs/zbxdbhigh/trigger_linking.c +++ b/src/libs/zbxdbhigh/trigger_linking.c @@ -280,21 +280,38 @@ static void zbx_triggers_descriptions_clean(zbx_hashset_t *x) typedef struct { - zbx_uint64_t triggerid; - char *tag; - char *value; - int flags; + zbx_uint64_t triggerid; + unsigned char flags; + zbx_vector_db_tag_ptr_t tags; + zbx_vector_db_tag_ptr_t new_tags; } -zbx_trigger_tag_insert_temp_t; +zbx_trigger_tags_t; -ZBX_PTR_VECTOR_DECL(trigger_tag_insert_temps, zbx_trigger_tag_insert_temp_t *) -ZBX_PTR_VECTOR_IMPL(trigger_tag_insert_temps, zbx_trigger_tag_insert_temp_t *) +ZBX_PTR_VECTOR_DECL(trigger_tags, zbx_trigger_tags_t *) +ZBX_PTR_VECTOR_IMPL(trigger_tags, zbx_trigger_tags_t *) -static void trigger_tag_insert_temp_free(zbx_trigger_tag_insert_temp_t *trigger_tag_insert_temp) +static zbx_trigger_tags_t *trigger_tags_create(zbx_uint64_t triggerid, unsigned char flags) { - zbx_free(trigger_tag_insert_temp->tag); - zbx_free(trigger_tag_insert_temp->value); - zbx_free(trigger_tag_insert_temp); + zbx_trigger_tags_t *trigger_tags; + + trigger_tags = (zbx_trigger_tags_t *)zbx_malloc(NULL, sizeof(zbx_trigger_tags_t)); + trigger_tags->triggerid = triggerid; + trigger_tags->flags = flags; + zbx_vector_db_tag_ptr_create(&trigger_tags->tags); + zbx_vector_db_tag_ptr_create(&trigger_tags->new_tags); + + return trigger_tags; +} + +static void trigger_tags_free(zbx_trigger_tags_t *trigger_tags) +{ + zbx_vector_db_tag_ptr_clear_ext(&trigger_tags->tags, zbx_db_tag_free); + zbx_vector_db_tag_ptr_destroy(&trigger_tags->tags); + + zbx_vector_db_tag_ptr_clear_ext(&trigger_tags->new_tags, zbx_db_tag_free); + zbx_vector_db_tag_ptr_destroy(&trigger_tags->new_tags); + + zbx_free(trigger_tags); } /******************************************************************************** @@ -310,14 +327,18 @@ static void trigger_tag_insert_temp_free(zbx_trigger_tag_insert_temp_t *trigger_ static int DBcopy_template_trigger_tags(const zbx_vector_uint64_t *new_triggerids, const zbx_vector_uint64_t *cur_triggerids) { - DB_RESULT result; - DB_ROW row; - char *sql = NULL; - size_t sql_alloc = 0, sql_offset = 0; - int i, ret = SUCCEED; - zbx_vector_uint64_t triggerids; - zbx_db_insert_t db_insert; - zbx_vector_trigger_tag_insert_temps_t trigger_tag_insert_temps; + DB_RESULT result; + DB_ROW row; + char *sql = NULL; + size_t sql_alloc = 0, sql_offset = 0; + int i, j, ret = SUCCEED, insert_num = 0, update_num = 0, delete_num = 0; + zbx_db_insert_t db_insert; + zbx_vector_uint64_t triggerids, del_tagids; + zbx_vector_trigger_tags_t triggers_tags; + zbx_trigger_tags_t *trigger_tags = NULL; + zbx_uint64_t triggerid, tagid; + zbx_db_tag_t *db_tag; + zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); @@ -326,61 +347,53 @@ static int DBcopy_template_trigger_tags(const zbx_vector_uint64_t *new_triggerid zbx_vector_uint64_create(&triggerids); zbx_vector_uint64_reserve(&triggerids, (size_t)(new_triggerids->values_num + cur_triggerids->values_num)); - zbx_vector_trigger_tag_insert_temps_create(&trigger_tag_insert_temps); + zbx_vector_uint64_append_array(&triggerids, new_triggerids->values, new_triggerids->values_num); + zbx_vector_uint64_append_array(&triggerids, cur_triggerids->values, cur_triggerids->values_num); + zbx_vector_uint64_sort(&triggerids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - if (0 != cur_triggerids->values_num) - { - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, - "select tt.triggertagid,tt.triggerid,t.flags" - " from trigger_tag tt,triggers t" - " where tt.triggerid=t.triggerid and "); - DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.triggerid", cur_triggerids->values, - cur_triggerids->values_num); - - if (NULL == (result = DBselect("%s", sql))) - { - ret = FAIL; - goto clean; - } + zbx_vector_trigger_tags_create(&triggers_tags); + zbx_vector_trigger_tags_reserve(&triggers_tags, (size_t)triggerids.values_alloc); - while (NULL != (row = DBfetch(result))) - { - zbx_uint64_t audit_del_triggerid, audit_del_triggertagid; + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, + "select tt.triggertagid,t.triggerid,t.flags,tt.tag,tt.value" + " from triggers t" + " left join trigger_tag tt on tt.triggerid=t.triggerid" + " where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.triggerid", triggerids.values, + triggerids.values_num); + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by t.triggerid"); - ZBX_STR2UINT64(audit_del_triggerid, row[1]); - ZBX_STR2UINT64(audit_del_triggertagid, row[0]); + if (NULL == (result = DBselect("%s", sql))) + { + ret = FAIL; + goto clean; + } - zbx_audit_trigger_update_json_delete_tags(audit_del_triggerid, atoi(row[2]), - audit_del_triggertagid); - } + while (NULL != (row = DBfetch(result))) + { + ZBX_STR2UINT64(triggerid, row[1]); - sql_offset = 0; - DBfree_result(result); + if (NULL == trigger_tags || trigger_tags->triggerid != triggerid) + { + unsigned char flags; - /* remove tags from host triggers that were linked to template triggers */ - zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from trigger_tag where"); - DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "triggerid", cur_triggerids->values, - cur_triggerids->values_num); + ZBX_STR2UCHAR(flags, row[2]); + trigger_tags = trigger_tags_create(triggerid, flags); + zbx_vector_trigger_tags_append(&triggers_tags, trigger_tags); + } - if (ZBX_DB_OK > DBexecute("%s", sql)) + if (SUCCEED != DBis_null(row[3])) { - ret = FAIL; - goto clean; + db_tag = zbx_db_tag_create(row[3], row[4]); + ZBX_DBROW2UINT64(db_tag->tagid, row[0]); + zbx_vector_db_tag_ptr_append(&trigger_tags->tags, db_tag); } - - sql_offset = 0; - - for (i = 0; i < cur_triggerids->values_num; i++) - zbx_vector_uint64_append(&triggerids, cur_triggerids->values[i]); } + DBfree_result(result); - for (i = 0; i < new_triggerids->values_num; i++) - zbx_vector_uint64_append(&triggerids, new_triggerids->values[i]); - - zbx_vector_uint64_sort(&triggerids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - + sql_offset = 0; zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, - "select t.triggerid,tt.tag,tt.value,t.flags" + "select t.triggerid,tt.tag,tt.value" " from trigger_tag tt,triggers t" " where tt.triggerid=t.templateid" " and"); @@ -395,54 +408,165 @@ static int DBcopy_template_trigger_tags(const zbx_vector_uint64_t *new_triggerid while (NULL != (row = DBfetch(result))) { - zbx_trigger_tag_insert_temp_t *zbx_trigger_tag_insert_temp; - - zbx_trigger_tag_insert_temp = (zbx_trigger_tag_insert_temp_t *)zbx_malloc(NULL, - sizeof(zbx_trigger_tag_insert_temp_t)); - ZBX_STR2UINT64(zbx_trigger_tag_insert_temp->triggerid, row[0]); - zbx_trigger_tag_insert_temp->tag = zbx_strdup(NULL, row[1]); - zbx_trigger_tag_insert_temp->value = zbx_strdup(NULL, row[2]); - zbx_trigger_tag_insert_temp->flags = atoi(row[3]); - zbx_vector_trigger_tag_insert_temps_append(&trigger_tag_insert_temps, zbx_trigger_tag_insert_temp); + zbx_trigger_tags_t trigger_tags_local; + + ZBX_STR2UINT64(trigger_tags_local.triggerid, row[0]); + + if (FAIL == (i = zbx_vector_trigger_tags_bsearch(&triggers_tags, &trigger_tags_local, + ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC))) + { + THIS_SHOULD_NEVER_HAPPEN; + continue; + } + + zbx_vector_db_tag_ptr_append(&triggers_tags.values[i]->new_tags, zbx_db_tag_create(row[1], row[2])); + } + DBfree_result(result); + + for (i = 0; i < triggers_tags.values_num; i++) + { + trigger_tags = triggers_tags.values[i]; + (void)zbx_merge_tags(&trigger_tags->tags, &trigger_tags->new_tags, NULL, NULL); + + for (j = 0; j < trigger_tags->tags.values_num; j++) + { + db_tag = trigger_tags->tags.values[j]; + + if (0 == db_tag->tagid) + insert_num++; + else if (0 != (db_tag->flags & ZBX_FLAG_DB_TAG_UPDATE)) + update_num++; + else if (0 != (db_tag->flags & ZBX_FLAG_DB_TAG_REMOVE)) + delete_num++; + } } - if (0 < trigger_tag_insert_temps.values_num) + if (0 == insert_num && 0 == update_num && 0 == delete_num) + goto clean; + + if (0 != update_num) { - zbx_uint64_t triggertagid; + sql_offset = 0; + DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset); + } - triggertagid = DBget_maxid_num("trigger_tag", trigger_tag_insert_temps.values_num); + if (0 != insert_num) + { zbx_db_insert_prepare(&db_insert, "trigger_tag", "triggertagid", "triggerid", "tag", "value", NULL); + tagid = DBget_maxid_num("trigger_tag", insert_num); + } - for (i = 0; i < trigger_tag_insert_temps.values_num; i++) + if (0 != delete_num) + { + zbx_vector_uint64_create(&del_tagids); + zbx_vector_uint64_reserve(&del_tagids, (size_t)delete_num); + } + + for (i = 0; i < triggers_tags.values_num; i++) + { + trigger_tags = triggers_tags.values[i]; + + for (j = 0; j < trigger_tags->tags.values_num; j++) { - zbx_db_insert_add_values(&db_insert, triggertagid, - trigger_tag_insert_temps.values[i]->triggerid, - trigger_tag_insert_temps.values[i]->tag, - trigger_tag_insert_temps.values[i]->value); + const char *d = ""; + + db_tag = trigger_tags->tags.values[j]; - zbx_audit_trigger_update_json_add_tags_and_values(trigger_tag_insert_temps.values[i]->triggerid, - trigger_tag_insert_temps.values[i]->flags, - triggertagid, trigger_tag_insert_temps.values[i]->tag, - trigger_tag_insert_temps.values[i]->value); + if (0 == db_tag->tagid) + { + zbx_db_insert_add_values(&db_insert, tagid, trigger_tags->triggerid, + db_tag->tag, db_tag->value); + + zbx_audit_trigger_update_json_add_tags_and_values(trigger_tags->triggerid, + trigger_tags->flags, tagid, db_tag->tag, db_tag->value); + + tagid++; + } + else if (0 != (db_tag->flags & ZBX_FLAG_DB_TAG_UPDATE)) + { + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update trigger_tag set "); + + zbx_audit_trigger_update_json_update_trigger_tag_create_entry(trigger_tags->triggerid, + trigger_tags->flags, db_tag->tagid); + + if (0 != (db_tag->flags & ZBX_FLAG_DB_TAG_UPDATE_TAG)) + { + char *tag_esc; + + tag_esc = DBdyn_escape_string(db_tag->tag); + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%stag='%s'", d, tag_esc); + + d = ","; + zbx_free(tag_esc); + + zbx_audit_trigger_update_json_update_tag_tag(trigger_tags->triggerid, + trigger_tags->flags, db_tag->tagid, db_tag->tag_orig, + db_tag->tag); + + } - triggertagid++; + if (0 != (db_tag->flags & ZBX_FLAG_DB_TAG_UPDATE_VALUE)) + { + char *value_esc; + + value_esc = DBdyn_escape_string(db_tag->value); + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%svalue='%s'", d, value_esc); + zbx_free(value_esc); + + zbx_audit_trigger_update_json_update_tag_value(trigger_tags->triggerid, + trigger_tags->flags, db_tag->tagid, db_tag->value_orig, + db_tag->value); + } + + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where triggertagid=" ZBX_FS_UI64 + ";\n", db_tag->tagid); + + DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset); + } + else if (0 != (db_tag->flags & ZBX_FLAG_DB_TAG_REMOVE)) + { + zbx_vector_uint64_append(&del_tagids, db_tag->tagid); + + zbx_audit_trigger_update_json_delete_tags(trigger_tags->triggerid, trigger_tags->flags, + db_tag->tagid); + } } } - DBfree_result(result); + if (0 != update_num) + { + DBend_multiple_update(&sql, &sql_alloc, &sql_offset); - zbx_free(sql); + if (16 < sql_offset) /* in ORACLE always present begin..end; */ + DBexecute("%s", sql); + } - if (0 < trigger_tag_insert_temps.values_num) + if (0 != insert_num) { - zbx_db_insert_autoincrement(&db_insert, "triggertagid"); zbx_db_insert_execute(&db_insert); zbx_db_insert_clean(&db_insert); } + + if (0 != delete_num) + { + zbx_vector_uint64_sort(&del_tagids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); + + sql_offset = 0; + zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "delete from trigger_tag where"); + DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "triggertagid", del_tagids.values, + del_tagids.values_num); + DBexecute("%s", sql); + + zbx_vector_uint64_destroy(&del_tagids); + } + clean: - zbx_vector_trigger_tag_insert_temps_clear_ext(&trigger_tag_insert_temps, trigger_tag_insert_temp_free); - zbx_vector_trigger_tag_insert_temps_destroy(&trigger_tag_insert_temps); + zbx_free(sql); zbx_vector_uint64_destroy(&triggerids); + + zbx_vector_trigger_tags_clear_ext(&triggers_tags, trigger_tags_free); + zbx_vector_trigger_tags_destroy(&triggers_tags); + out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); diff --git a/src/zabbix_server/lld/lld.h b/src/zabbix_server/lld/lld.h index c86f096c949..57abcb8c336 100644 --- a/src/zabbix_server/lld/lld.h +++ b/src/zabbix_server/lld/lld.h @@ -89,7 +89,7 @@ typedef struct zbx_vector_ptr_t lld_rows; zbx_vector_ptr_t preproc_ops; zbx_vector_ptr_t item_params; - zbx_vector_ptr_t item_tags; + zbx_vector_db_tag_ptr_t item_tags; } zbx_lld_item_prototype_t; @@ -198,7 +198,7 @@ typedef struct zbx_vector_ptr_t preproc_ops; zbx_vector_ptr_t dependent_items; zbx_vector_ptr_t item_params; - zbx_vector_ptr_t item_tags; + zbx_vector_db_tag_ptr_t item_tags; zbx_vector_db_tag_ptr_t override_tags; unsigned char status; unsigned char type_orig; diff --git a/src/zabbix_server/lld/lld_host.c b/src/zabbix_server/lld/lld_host.c index f87b9e92c93..fbec72bd1d3 100644 --- a/src/zabbix_server/lld/lld_host.c +++ b/src/zabbix_server/lld/lld_host.c @@ -302,7 +302,7 @@ typedef struct zbx_lld_group_rights_t; static void lld_host_update_tags(zbx_lld_host_t *host, const zbx_vector_db_tag_ptr_t *tags, - const zbx_vector_ptr_t *lld_macros, char **info); + const zbx_vector_ptr_t *lld_macros, char **error); typedef struct { @@ -820,7 +820,7 @@ static void lld_hosts_validate(zbx_vector_ptr_t *hosts, char **error) static zbx_lld_host_t *lld_host_make(zbx_vector_ptr_t *hosts, const char *host_proto, const char *name_proto, signed char inventory_mode_proto, unsigned char status_proto, unsigned char discover_proto, zbx_vector_db_tag_ptr_t *tags, const zbx_lld_row_t *lld_row, const zbx_vector_ptr_t *lld_macros, - char **info, unsigned char custom_iface) + unsigned char custom_iface, char **error) { char *buffer = NULL; int i, host_found = 0; @@ -968,7 +968,7 @@ static zbx_lld_host_t *lld_host_make(zbx_vector_ptr_t *hosts, const char *host_p if (0 != (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED)) { zbx_vector_db_tag_ptr_append_array(&tmp_tags, tags->values, tags->values_num); - lld_host_update_tags(host, &tmp_tags, lld_macros, info); + lld_host_update_tags(host, &tmp_tags, lld_macros, error); if (0 != lnk_templateids.values_num) { @@ -2210,80 +2210,6 @@ static void lld_proto_tags_get(zbx_uint64_t parent_hostid, zbx_vector_db_tag_ptr /****************************************************************************** * * - * Purpose: validate host tag field * - * * - * Parameters: name - [IN] the field name (tag, value) * - * field - [IN] the field value * - * field_len - [IN] the field length * - * info - [OUT] error information * - * * - ******************************************************************************/ -static int lld_tag_validate_field(const char *name, const char *field, size_t field_len, char **info) -{ - if (SUCCEED != zbx_is_utf8(field)) - { - char *field_utf8; - - field_utf8 = zbx_strdup(NULL, field); - zbx_replace_invalid_utf8(field_utf8); - *info = zbx_strdcatf(*info, "Cannot create host tag: %s \"%s\" has invalid UTF-8 sequence.\n", - name, field_utf8); - zbx_free(field_utf8); - return FAIL; - } - - if (zbx_strlen_utf8(field) > field_len) - { - *info = zbx_strdcatf(*info, "Cannot create host tag: %s \"%128s...\" is too long.\n", name, field); - return FAIL; - } - - return SUCCEED; -} - -/****************************************************************************** - * * - * Purpose: validate host tag * - * * - * Parameters: tags - [IN] the current host tags * - * tags_num - [IN] the number of host tags * - * name - [IN] the new tag name * - * value - [IN] the new tag value * - * info - [OUT] error information * - * * - ******************************************************************************/ -static int lld_tag_validate(zbx_db_tag_t **tags, int tags_num, const char *name, const char *value, char **info) -{ - int i; - - if ('\0' == *name) - { - *info = zbx_strdcatf(*info, "Cannot create host tag: empty tag name.\n"); - return FAIL; - } - - if (SUCCEED != lld_tag_validate_field("name", name, TAG_NAME_LEN, info)) - return FAIL; - - if (SUCCEED != lld_tag_validate_field("value", value, TAG_VALUE_LEN, info)) - return FAIL; - - for (i = 0; i < tags_num; i++) - { - if (0 == strcmp(tags[i]->tag, name) && 0 == strcmp(tags[i]->value, value)) - { - *info = zbx_strdcatf(*info, "Cannot create host tag: tag \"%s\",\"%s\" already exists.\n", - name, value); - - return FAIL; - } - } - - return SUCCEED; -} - -/****************************************************************************** - * * * Purpose: update host tags * * * * Parameters: host - [IN] a host with existing tags, sorted by tag + * @@ -2301,10 +2227,10 @@ static int lld_tag_validate(zbx_db_tag_t **tags, int tags_num, const char *name, * * ******************************************************************************/ static void lld_host_update_tags(zbx_lld_host_t *host, const zbx_vector_db_tag_ptr_t *tags, - const zbx_vector_ptr_t *lld_macros, char **info) + const zbx_vector_ptr_t *lld_macros, char **error) { int i; - zbx_db_tag_t *host_tag, *proto_tag; + zbx_db_tag_t *proto_tag; zbx_vector_db_tag_ptr_t new_tags; char *tag = NULL, *value = NULL; @@ -2320,9 +2246,6 @@ static void lld_host_update_tags(zbx_lld_host_t *host, const zbx_vector_db_tag_p substitute_lld_macros(&tag, host->jp_row, lld_macros, ZBX_MACRO_FUNC, NULL, 0); substitute_lld_macros(&value, host->jp_row, lld_macros, ZBX_MACRO_FUNC, NULL, 0); - if (SUCCEED != lld_tag_validate(new_tags.values, new_tags.values_num, tag, value, info)) - continue; - proto_tag = zbx_db_tag_create(tag, value); zbx_vector_db_tag_ptr_append(&new_tags, proto_tag); @@ -2330,51 +2253,13 @@ static void lld_host_update_tags(zbx_lld_host_t *host, const zbx_vector_db_tag_p zbx_free(value); } - zbx_vector_db_tag_ptr_sort(&new_tags, zbx_db_tag_compare_func); - - zbx_vector_db_tag_ptr_reserve(&host->tags, (size_t)new_tags.values_num); - - /* update host tags or flag them for removal */ - for (i = 0; i < host->tags.values_num; i++) - { - host_tag = (zbx_db_tag_t *)host->tags.values[i]; - if (i < new_tags.values_num) - { - proto_tag = (zbx_db_tag_t *)new_tags.values[i]; - - if (0 != strcmp(host_tag->tag, proto_tag->tag)) - { - host_tag->tag_orig = zbx_strdup(NULL, host_tag->tag); - host_tag->tag = zbx_strdup(host_tag->tag, proto_tag->tag); - host_tag->flags |= ZBX_FLAG_DB_TAG_UPDATE_TAG; - } - - if (0 != strcmp(host_tag->value, proto_tag->value)) - { - host_tag->value_orig = zbx_strdup(NULL, host_tag->value); - host_tag->value = zbx_strdup(host_tag->value, proto_tag->value); - host_tag->flags |= ZBX_FLAG_DB_TAG_UPDATE_VALUE; - } - } - else - host_tag->flags = ZBX_FLAG_DB_TAG_REMOVE; - } - - /* add missing tags */ - if (i < new_tags.values_num) + if (SUCCEED != zbx_merge_tags(&host->tags, &new_tags, "host", error)) { - int j; - - /* set uninitialized properties of new tags that will be moved to host */ - for (j = i; j < new_tags.values_num; j++) + if (0 == host->hostid) { - proto_tag = (zbx_db_tag_t *)new_tags.values[j]; - proto_tag->tagid = 0; - proto_tag->flags = 0; + host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED; + *error = zbx_strdcatf(*error, "Cannot create host: tag validation failed.\n"); } - - zbx_vector_db_tag_ptr_append_array(&host->tags, new_tags.values + i, new_tags.values_num - i); - new_tags.values_num = i; } zbx_free(tag); @@ -4541,7 +4426,8 @@ void lld_update_hosts(zbx_uint64_t lld_ruleid, const zbx_vector_ptr_t *lld_rows, const zbx_lld_row_t *lld_row = (zbx_lld_row_t *)lld_rows->values[i]; if (NULL == (host = lld_host_make(&hosts, host_proto, name_proto, inventory_mode_proto, - status, discover, &tags, lld_row, lld_macro_paths, error, use_custom_interfaces))) + status, discover, &tags, lld_row, lld_macro_paths, use_custom_interfaces, + error))) { continue; } diff --git a/src/zabbix_server/lld/lld_item.c b/src/zabbix_server/lld/lld_item.c index 2ea606e3c73..8813fc12054 100644 --- a/src/zabbix_server/lld/lld_item.c +++ b/src/zabbix_server/lld/lld_item.c @@ -120,24 +120,6 @@ zbx_lld_item_param_t; #define ZBX_ITEM_TAG_FIELD_TAG 1 #define ZBX_ITEM_TAG_FIELD_VALUE 2 -typedef struct -{ - zbx_uint64_t item_tagid; - char *tag; - char *tag_orig; - char *value; - char *value_orig; - -#define ZBX_FLAG_LLD_ITEM_TAG_UNSET __UINT64_C(0x00) -#define ZBX_FLAG_LLD_ITEM_TAG_DISCOVERED __UINT64_C(0x01) -#define ZBX_FLAG_LLD_ITEM_TAG_UPDATE_TAG __UINT64_C(0x02) -#define ZBX_FLAG_LLD_ITEM_TAG_UPDATE_VALUE __UINT64_C(0x04) -#define ZBX_FLAG_LLD_ITEM_TAG_UPDATE \ - (ZBX_FLAG_LLD_ITEM_TAG_UPDATE_TAG | ZBX_FLAG_LLD_ITEM_TAG_UPDATE_VALUE) - zbx_uint64_t flags; -} -zbx_lld_item_tag_t; - /* item index by prototype (parent) id and lld row */ typedef struct { @@ -206,15 +188,6 @@ static int lld_item_param_sort_by_name(const void *d1, const void *d2) return 0; } -static int lld_item_tag_sort_by_tag(const void *d1, const void *d2) -{ - zbx_lld_item_tag_t *it1 = *(zbx_lld_item_tag_t **)d1; - zbx_lld_item_tag_t *it2 = *(zbx_lld_item_tag_t **)d2; - - ZBX_RETURN_IF_NOT_EQUAL(it1->tag, it2->tag); - return 0; -} - static void lld_item_preproc_free(zbx_lld_item_preproc_t *op) { zbx_free(op->params); @@ -237,17 +210,6 @@ static void lld_item_param_free(zbx_lld_item_param_t *param) zbx_free(param); } -static void lld_item_tag_free(zbx_lld_item_tag_t *tag) -{ - zbx_free(tag->tag); - if (0 != (tag->flags & ZBX_FLAG_LLD_ITEM_TAG_UPDATE_TAG)) - zbx_free(tag->tag_orig); - zbx_free(tag->value); - if (0 != (tag->flags & ZBX_FLAG_LLD_ITEM_TAG_UPDATE_VALUE)) - zbx_free(tag->value_orig); - zbx_free(tag); -} - static void lld_item_prototype_free(zbx_lld_item_prototype_t *item_prototype) { zbx_free(item_prototype->name); @@ -287,8 +249,8 @@ static void lld_item_prototype_free(zbx_lld_item_prototype_t *item_prototype) zbx_vector_ptr_clear_ext(&item_prototype->item_params, (zbx_clean_func_t)lld_item_param_free); zbx_vector_ptr_destroy(&item_prototype->item_params); - zbx_vector_ptr_clear_ext(&item_prototype->item_tags, (zbx_clean_func_t)lld_item_tag_free); - zbx_vector_ptr_destroy(&item_prototype->item_tags); + zbx_vector_db_tag_ptr_clear_ext(&item_prototype->item_tags, zbx_db_tag_free); + zbx_vector_db_tag_ptr_destroy(&item_prototype->item_tags); zbx_free(item_prototype); } @@ -352,8 +314,8 @@ static void lld_item_free(zbx_lld_item_t *item) zbx_vector_ptr_destroy(&item->preproc_ops); zbx_vector_ptr_clear_ext(&item->item_params, (zbx_clean_func_t)lld_item_param_free); zbx_vector_ptr_destroy(&item->item_params); - zbx_vector_ptr_clear_ext(&item->item_tags, (zbx_clean_func_t)lld_item_tag_free); - zbx_vector_ptr_destroy(&item->item_tags); + zbx_vector_db_tag_ptr_clear_ext(&item->item_tags, zbx_db_tag_free); + zbx_vector_db_tag_ptr_destroy(&item->item_tags); zbx_vector_ptr_destroy(&item->dependent_items); zbx_vector_db_tag_ptr_destroy(&item->override_tags); @@ -376,7 +338,6 @@ static void lld_items_get(const zbx_vector_ptr_t *item_prototypes, zbx_vector_pt zbx_lld_item_t *item, *master; zbx_lld_item_preproc_t *preproc_op; zbx_lld_item_param_t *item_param; - zbx_lld_item_tag_t *item_tag; const zbx_lld_item_prototype_t *item_prototype; zbx_uint64_t db_valuemapid, db_interfaceid, itemid, master_itemid; zbx_vector_uint64_t parent_itemids; @@ -628,7 +589,7 @@ static void lld_items_get(const zbx_vector_ptr_t *item_prototypes, zbx_vector_pt zbx_vector_ptr_create(&item->preproc_ops); zbx_vector_ptr_create(&item->dependent_items); zbx_vector_ptr_create(&item->item_params); - zbx_vector_ptr_create(&item->item_tags); + zbx_vector_db_tag_ptr_create(&item->item_tags); zbx_vector_db_tag_ptr_create(&item->override_tags); zbx_vector_ptr_append(items, item); @@ -756,6 +717,8 @@ static void lld_items_get(const zbx_vector_ptr_t *item_prototypes, zbx_vector_pt while (NULL != (row = DBfetch(result))) { + zbx_db_tag_t *db_tag; + ZBX_STR2UINT64(itemid, row[1]); if (FAIL == (index = zbx_vector_ptr_bsearch(items, &itemid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC))) @@ -766,14 +729,9 @@ static void lld_items_get(const zbx_vector_ptr_t *item_prototypes, zbx_vector_pt item = (zbx_lld_item_t *)items->values[index]; - item_tag = (zbx_lld_item_tag_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_tag_t)); - item_tag->flags = ZBX_FLAG_LLD_ITEM_TAG_UNSET; - ZBX_STR2UINT64(item_tag->item_tagid, row[0]); - item_tag->tag = zbx_strdup(NULL, row[2]); - item_tag->tag_orig = NULL; - item_tag->value = zbx_strdup(NULL, row[3]); - item_tag->value_orig = NULL; - zbx_vector_ptr_append(&item->item_tags, item_tag); + db_tag = zbx_db_tag_create(row[2], row[3]); + ZBX_STR2UINT64(db_tag->tagid, row[0]); + zbx_vector_db_tag_ptr_append(&item->item_tags, db_tag); } DBfree_result(result); out: @@ -834,40 +792,6 @@ static int lld_validate_item_param(zbx_uint64_t itemid, int type, size_t len, ch return SUCCEED; } -static int lld_validate_item_tag(zbx_uint64_t itemid, int type, char *tag, char **error) -{ - size_t len; - if (SUCCEED != zbx_is_utf8(tag)) - { - char *tag_utf8; - - tag_utf8 = zbx_strdup(NULL, tag); - zbx_replace_invalid_utf8(tag_utf8); - *error = zbx_strdcatf(*error, "Cannot %s item: tag's %s \"%s\" has invalid UTF-8 sequence.\n", - (0 != itemid ? "update" : "create"), - (ZBX_ITEM_TAG_FIELD_TAG != type ? "tag" : "value"), tag_utf8); - zbx_free(tag_utf8); - return FAIL; - } - - len = zbx_strlen_utf8(tag); - - if (ITEM_TAG_FIELD_LEN < len) - { - *error = zbx_strdcatf(*error, "Cannot %s item: tag's %s \"%s\" is too long.\n", - (0 != itemid ? "update" : "create"), - (ZBX_ITEM_TAG_FIELD_TAG != type ? "tag" : "value"), tag); - return FAIL; - } - else if (0 == len && ZBX_ITEM_TAG_FIELD_TAG == type) - { - *error = zbx_strdcatf(*error, "Cannot %s item: empty tag name.\n", (0 != itemid ? "update" : "create")); - return FAIL; - } - - return SUCCEED; -} - static void lld_validate_item_field(zbx_lld_item_t *item, char **field, char **field_orig, zbx_uint64_t flag, size_t field_len, char **error) { @@ -1640,50 +1564,6 @@ static void lld_items_validate(zbx_uint64_t hostid, zbx_vector_ptr_t *items, zbx } } - /* check item tags for new and updated discovered items */ - for (i = 0; i < items->values_num; i++) - { - item = (zbx_lld_item_t *)items->values[i]; - - if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED)) - continue; - - for (j = 0; j < item->item_tags.values_num; j++) - { - zbx_lld_item_tag_t *item_tag = (zbx_lld_item_tag_t *)item->item_tags.values[j], *tag_dup; - int k; - - if (SUCCEED != lld_validate_item_tag(item->itemid, ZBX_ITEM_TAG_FIELD_TAG, item_tag->tag, - error) || SUCCEED != lld_validate_item_tag(item->itemid, - ZBX_ITEM_TAG_FIELD_VALUE, item_tag->value, error)) - { - item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED; - break; - } - - if (0 == (item_tag->flags & ZBX_FLAG_LLD_ITEM_TAG_DISCOVERED)) - continue; - - /* check for duplicated tag */ - for (k = 0; k < j; k++) - { - tag_dup = (zbx_lld_item_tag_t *)item->item_tags.values[k]; - - if (0 == strcmp(item_tag->tag, tag_dup->tag) && - 0 == strcmp(item_tag->value, tag_dup->value)) - { - item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED; - *error = zbx_strdcatf(*error, "Cannot create item tag: tag \"%s\"," - "\"%s\" already exists.\n", item_tag->tag, item_tag->value); - break; - } - } - - if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED)) - break; - } - } - /* check preprocessing steps for new and updated discovered items */ for (i = 0; i < items->values_num; i++) { @@ -2084,7 +1964,7 @@ static zbx_lld_item_t *lld_item_make(const zbx_lld_item_prototype_t *item_protot zbx_vector_ptr_create(&item->preproc_ops); zbx_vector_ptr_create(&item->dependent_items); zbx_vector_ptr_create(&item->item_params); - zbx_vector_ptr_create(&item->item_tags); + zbx_vector_db_tag_ptr_create(&item->item_tags); if (SUCCEED == ret && ZBX_PROTOTYPE_NO_DISCOVER != discover) item->flags = ZBX_FLAG_LLD_ITEM_DISCOVERED; @@ -2867,18 +2747,19 @@ static void lld_items_param_make(const zbx_vector_ptr_t *item_prototypes, * Parameters: item_prototypes - [IN] the item prototypes * * lld_macro_paths - [IN] use json path to extract from jp_row * * items - [IN/OUT] sorted list of items * + * error - [OUT] error message * * * ******************************************************************************/ static void lld_items_tags_make(const zbx_vector_ptr_t *item_prototypes, const zbx_vector_ptr_t *lld_macro_paths, - zbx_vector_ptr_t *items) + zbx_vector_ptr_t *items, char **error) { - int i, j, index, item_tag_num; + int i, j, index; zbx_lld_item_t *item; zbx_lld_item_prototype_t *item_proto; - zbx_lld_item_tag_t *itsrc, *itdst; - zbx_db_tag_t *override_tags; - char *buffer = NULL; - const char *name, *value; + zbx_vector_db_tag_ptr_t new_tags; + zbx_db_tag_t *db_tag; + + zbx_vector_db_tag_ptr_create(&new_tags); for (i = 0; i < items->values_num; i++) { @@ -2894,88 +2775,41 @@ static void lld_items_tags_make(const zbx_vector_ptr_t *item_prototypes, const z continue; } - zbx_vector_ptr_sort(&item->item_tags, lld_item_tag_sort_by_tag); - zbx_vector_db_tag_ptr_sort(&item->override_tags, zbx_db_tag_compare_func); - item_proto = (zbx_lld_item_prototype_t *)item_prototypes->values[index]; - item_tag_num = MAX(item->item_tags.values_num, - item_proto->item_tags.values_num + item->override_tags.values_num); - - for (j = 0; j < item_tag_num; j++) + for (j = 0; j < item_proto->item_tags.values_num; j++) { - if (j < item->item_tags.values_num && - j >= item_proto->item_tags.values_num + item->override_tags.values_num) - { - itdst = (zbx_lld_item_tag_t *)item->item_tags.values[j]; - itdst->flags &= ~ZBX_FLAG_LLD_ITEM_TAG_DISCOVERED; - continue; - } - - if (j >= item_proto->item_tags.values_num) - { - override_tags = item->override_tags.values[j - item_proto->item_tags.values_num]; - name = override_tags->tag; - value = override_tags->value; - } - else - { - itsrc = (zbx_lld_item_tag_t *)item_proto->item_tags.values[j]; - name = itsrc->tag; - value = itsrc->value; - } - - if (j >= item->item_tags.values_num) - { - itdst = (zbx_lld_item_tag_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_tag_t)); - itdst->item_tagid = 0; - itdst->flags = ZBX_FLAG_LLD_ITEM_TAG_DISCOVERED | ZBX_FLAG_LLD_ITEM_TAG_UPDATE; - itdst->tag = zbx_strdup(NULL, name); - itdst->tag_orig = NULL; - itdst->value = zbx_strdup(NULL, value); - itdst->value_orig = NULL; - - substitute_lld_macros(&itdst->tag, &item->lld_row->jp_row, - lld_macro_paths, ZBX_MACRO_ANY, NULL, 0); - substitute_lld_macros(&itdst->value, &item->lld_row->jp_row, - lld_macro_paths, ZBX_MACRO_ANY, NULL, 0); - - zbx_vector_ptr_append(&item->item_tags, itdst); - continue; - } - - itdst = (zbx_lld_item_tag_t *)item->item_tags.values[j]; - itdst->flags |= ZBX_FLAG_LLD_ITEM_TAG_DISCOVERED; - - buffer = zbx_strdup(buffer, name); - substitute_lld_macros(&buffer, &item->lld_row->jp_row, lld_macro_paths, ZBX_MACRO_ANY, NULL, 0); + db_tag = zbx_db_tag_create(item_proto->item_tags.values[j]->tag, + item_proto->item_tags.values[j]->value); + zbx_vector_db_tag_ptr_append(&new_tags, db_tag); + } - if (0 != strcmp(itdst->tag, buffer)) - { - itdst->tag_orig = zbx_strdup(NULL, itdst->tag); - zbx_free(itdst->tag); - itdst->tag = buffer; - buffer = NULL; - itdst->flags |= ZBX_FLAG_LLD_ITEM_PARAM_UPDATE_NAME; - } - else - zbx_free(buffer); + for (j = 0; j < item->override_tags.values_num; j++) + { + db_tag = zbx_db_tag_create(item->override_tags.values[j]->tag, + item->override_tags.values[j]->value); + zbx_vector_db_tag_ptr_append(&new_tags, db_tag); + } - buffer = zbx_strdup(buffer, value); - substitute_lld_macros(&buffer, &item->lld_row->jp_row, lld_macro_paths, ZBX_MACRO_ANY, NULL, 0); + for (j = 0; j < new_tags.values_num; j++) + { + substitute_lld_macros(&new_tags.values[j]->tag, &item->lld_row->jp_row, lld_macro_paths, + ZBX_MACRO_ANY, NULL, 0); + substitute_lld_macros(&new_tags.values[j]->value, &item->lld_row->jp_row, lld_macro_paths, + ZBX_MACRO_ANY, NULL, 0); + } - if (0 != strcmp(itdst->value, buffer)) + if (SUCCEED != zbx_merge_tags(&item->item_tags, &new_tags, "item", error)) + { + if (0 == item->itemid) { - itdst->value_orig = zbx_strdup(NULL, itdst->value); - zbx_free(itdst->value); - itdst->value = buffer; - buffer = NULL; - itdst->flags |= ZBX_FLAG_LLD_ITEM_PARAM_UPDATE_VALUE; + item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED; + *error = zbx_strdcatf(*error, "Cannot create item: tag validation failed.\n"); } - else - zbx_free(buffer); } } + + zbx_vector_db_tag_ptr_destroy(&new_tags); } /****************************************************************************** @@ -4101,7 +3935,7 @@ static int lld_items_tags_save(zbx_uint64_t hostid, zbx_vector_ptr_t *items, int { int ret = SUCCEED, i, j, new_tag_num = 0, update_tag_num = 0, delete_tag_num = 0; zbx_lld_item_t *item; - zbx_lld_item_tag_t *item_tag; + zbx_db_tag_t *item_tag; zbx_vector_uint64_t deleteids; zbx_db_insert_t db_insert; char *sql = NULL; @@ -4121,30 +3955,33 @@ static int lld_items_tags_save(zbx_uint64_t hostid, zbx_vector_ptr_t *items, int for (j = 0; j < item->item_tags.values_num; j++) { - item_tag = (zbx_lld_item_tag_t *)item->item_tags.values[j]; + item_tag = item->item_tags.values[j]; - if (0 == (item_tag->flags & ZBX_FLAG_LLD_ITEM_TAG_DISCOVERED)) + if (0 != (item_tag->flags & ZBX_FLAG_DB_TAG_REMOVE)) { - zbx_vector_uint64_append(&deleteids, item_tag->item_tagid); + zbx_vector_uint64_append(&deleteids, item_tag->tagid); zbx_audit_item_delete_tag(item->itemid, (int)ZBX_FLAG_DISCOVERY_CREATED, - item_tag->item_tagid); + item_tag->tagid); continue; } - if (0 == item_tag->item_tagid) + if (0 == item_tag->tagid) { new_tag_num++; continue; } - if (0 == (item_tag->flags & ZBX_FLAG_LLD_ITEM_TAG_UPDATE)) + if (0 == (item_tag->flags & ZBX_FLAG_DB_TAG_UPDATE)) continue; update_tag_num++; } } - if (0 == *host_locked && (0 != update_tag_num || 0 != new_tag_num || 0 != deleteids.values_num)) + if (0 == update_tag_num && 0 == new_tag_num && 0 == deleteids.values_num) + goto out; + + if (0 == *host_locked) { if (SUCCEED != DBlock_hostid(hostid)) { @@ -4179,9 +4016,9 @@ static int lld_items_tags_save(zbx_uint64_t hostid, zbx_vector_ptr_t *items, int { char delim = ' '; - item_tag = (zbx_lld_item_tag_t *)item->item_tags.values[j]; + item_tag = item->item_tags.values[j]; - if (0 == item_tag->item_tagid) + if (0 == item_tag->tagid) { zbx_db_insert_add_values(&db_insert, new_tagid, item->itemid, item_tag->tag, item_tag->value); @@ -4191,14 +4028,14 @@ static int lld_items_tags_save(zbx_uint64_t hostid, zbx_vector_ptr_t *items, int continue; } - if (0 == (item_tag->flags & ZBX_FLAG_LLD_ITEM_TAG_UPDATE)) + if (0 == (item_tag->flags & ZBX_FLAG_DB_TAG_UPDATE)) continue; zbx_audit_item_update_json_update_item_tag_create_entry(item->itemid, - (int)ZBX_FLAG_DISCOVERY_CREATED, item_tag->item_tagid); + (int)ZBX_FLAG_DISCOVERY_CREATED, item_tag->tagid); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update item_tag set"); - if (0 != (item_tag->flags & ZBX_FLAG_LLD_ITEM_TAG_UPDATE_TAG)) + if (0 != (item_tag->flags & ZBX_FLAG_DB_TAG_UPDATE_TAG)) { char *tag_esc; @@ -4206,13 +4043,13 @@ static int lld_items_tags_save(zbx_uint64_t hostid, zbx_vector_ptr_t *items, int zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%ctag='%s'", delim, tag_esc); zbx_audit_item_update_json_update_item_tag_tag(item->itemid, - (int)ZBX_FLAG_DISCOVERY_CREATED, item_tag->item_tagid, + (int)ZBX_FLAG_DISCOVERY_CREATED, item_tag->tagid, item_tag->tag_orig, item_tag->tag); zbx_free(tag_esc); delim = ','; } - if (0 != (item_tag->flags & ZBX_FLAG_LLD_ITEM_TAG_UPDATE_VALUE)) + if (0 != (item_tag->flags & ZBX_FLAG_DB_TAG_UPDATE_VALUE)) { char *value_esc; @@ -4220,14 +4057,14 @@ static int lld_items_tags_save(zbx_uint64_t hostid, zbx_vector_ptr_t *items, int zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%cvalue='%s'", delim, value_esc); zbx_audit_item_update_json_update_item_tag_value(item->itemid, - (int)ZBX_FLAG_DISCOVERY_CREATED, item_tag->item_tagid, + (int)ZBX_FLAG_DISCOVERY_CREATED, item_tag->tagid, item_tag->value_orig, item_tag->value); zbx_free(value_esc); } zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where itemtagid=" ZBX_FS_UI64 ";\n", - item_tag->item_tagid); + item_tag->tagid); DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset); } @@ -4344,7 +4181,6 @@ static void lld_item_prototypes_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *i zbx_lld_item_prototype_t *item_prototype; zbx_lld_item_preproc_t *preproc_op; zbx_lld_item_param_t *item_param; - zbx_lld_item_tag_t *item_tag; zbx_uint64_t itemid; int index, i; @@ -4418,7 +4254,7 @@ static void lld_item_prototypes_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *i zbx_vector_ptr_create(&item_prototype->lld_rows); zbx_vector_ptr_create(&item_prototype->preproc_ops); zbx_vector_ptr_create(&item_prototype->item_params); - zbx_vector_ptr_create(&item_prototype->item_tags); + zbx_vector_db_tag_ptr_create(&item_prototype->item_tags); zbx_vector_ptr_append(item_prototypes, item_prototype); } @@ -4510,6 +4346,8 @@ static void lld_item_prototypes_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *i while (NULL != (row = DBfetch(result))) { + zbx_db_tag_t *db_tag; + ZBX_STR2UINT64(itemid, row[0]); if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &itemid, @@ -4521,22 +4359,10 @@ static void lld_item_prototypes_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *i item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index]; - item_tag = (zbx_lld_item_tag_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_tag_t)); - item_tag->item_tagid = 0; - item_tag->tag = zbx_strdup(NULL, row[1]); - item_tag->tag_orig = NULL; - item_tag->value = zbx_strdup(NULL, row[2]); - item_tag->value_orig = NULL; - item_tag->flags = ZBX_FLAG_LLD_ITEM_TAG_UNSET; - zbx_vector_ptr_append(&item_prototype->item_tags, item_tag); + db_tag = zbx_db_tag_create(row[1], row[2]); + zbx_vector_db_tag_ptr_append(&item_prototype->item_tags, db_tag); } DBfree_result(result); - - for (i = 0; i < item_prototypes->values_num; i++) - { - item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i]; - zbx_vector_ptr_sort(&item_prototype->item_tags, lld_item_tag_sort_by_tag); - } out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d prototypes", __func__, item_prototypes->values_num); } @@ -4610,7 +4436,7 @@ int lld_update_items(zbx_uint64_t hostid, zbx_uint64_t lld_ruleid, zbx_vector_pt lld_items_make(&item_prototypes, lld_rows, lld_macro_paths, &items, &items_index, error); lld_items_preproc_make(&item_prototypes, lld_macro_paths, &items); lld_items_param_make(&item_prototypes, lld_macro_paths, &items); - lld_items_tags_make(&item_prototypes, lld_macro_paths, &items); + lld_items_tags_make(&item_prototypes, lld_macro_paths, &items, error); lld_link_dependent_items(&items, &items_index); diff --git a/src/zabbix_server/lld/lld_trigger.c b/src/zabbix_server/lld/lld_trigger.c index 245b948d51a..63f351da5f0 100644 --- a/src/zabbix_server/lld/lld_trigger.c +++ b/src/zabbix_server/lld/lld_trigger.c @@ -45,7 +45,7 @@ typedef struct unsigned char discover; zbx_vector_ptr_t functions; zbx_vector_ptr_t dependencies; - zbx_vector_ptr_t tags; + zbx_vector_db_tag_ptr_t tags; zbx_eval_context_t eval_ctx; zbx_eval_context_t eval_ctx_r; } @@ -74,7 +74,7 @@ typedef struct zbx_vector_ptr_t functions; zbx_vector_ptr_t dependencies; zbx_vector_ptr_t dependents; - zbx_vector_ptr_t tags; + zbx_vector_db_tag_ptr_t tags; zbx_vector_db_tag_ptr_t override_tags; #define ZBX_FLAG_LLD_TRIGGER_UNSET __UINT64_C(0x0000) #define ZBX_FLAG_LLD_TRIGGER_DISCOVERED __UINT64_C(0x0001) @@ -143,24 +143,6 @@ zbx_lld_dependency_t; typedef struct { - zbx_uint64_t triggertagid; - char *tag_orig; - char *tag; - char *value_orig; - char *value; -#define ZBX_FLAG_LLD_TAG_UNSET __UINT64_C(0x00) -#define ZBX_FLAG_LLD_TAG_DISCOVERED __UINT64_C(0x01) -#define ZBX_FLAG_LLD_TAG_UPDATE_TAG __UINT64_C(0x02) -#define ZBX_FLAG_LLD_TAG_UPDATE_VALUE __UINT64_C(0x04) -#define ZBX_FLAG_LLD_TAG_UPDATE \ - (ZBX_FLAG_LLD_TAG_UPDATE_TAG | ZBX_FLAG_LLD_TAG_UPDATE_VALUE) -#define ZBX_FLAG_LLD_TAG_DELETE __UINT64_C(0x08) - zbx_uint64_t flags; -} -zbx_lld_tag_t; - -typedef struct -{ zbx_uint64_t parent_triggerid; zbx_uint64_t itemid; zbx_lld_trigger_t *trigger; @@ -223,15 +205,6 @@ typedef struct } zbx_lld_trigger_node_iter_t; -static void lld_tag_free(zbx_lld_tag_t *tag) -{ - zbx_free(tag->tag); - zbx_free(tag->tag_orig); - zbx_free(tag->value); - zbx_free(tag->value_orig); - zbx_free(tag); -} - static void lld_item_free(zbx_lld_item_t *item) { zbx_free(item); @@ -251,8 +224,8 @@ static void lld_trigger_prototype_free(zbx_lld_trigger_prototype_t *trigger_prot zbx_eval_clear(&trigger_prototype->eval_ctx); zbx_eval_clear(&trigger_prototype->eval_ctx_r); - zbx_vector_ptr_clear_ext(&trigger_prototype->tags, (zbx_clean_func_t)lld_tag_free); - zbx_vector_ptr_destroy(&trigger_prototype->tags); + zbx_vector_db_tag_ptr_clear_ext(&trigger_prototype->tags, zbx_db_tag_free); + zbx_vector_db_tag_ptr_destroy(&trigger_prototype->tags); zbx_vector_ptr_clear_ext(&trigger_prototype->dependencies, zbx_ptr_free); zbx_vector_ptr_destroy(&trigger_prototype->dependencies); zbx_vector_ptr_clear_ext(&trigger_prototype->functions, (zbx_mem_free_func_t)lld_function_free); @@ -270,9 +243,9 @@ static void lld_trigger_prototype_free(zbx_lld_trigger_prototype_t *trigger_prot static void lld_trigger_free(zbx_lld_trigger_t *trigger) { - zbx_vector_ptr_clear_ext(&trigger->tags, (zbx_clean_func_t)lld_tag_free); + zbx_vector_db_tag_ptr_clear_ext(&trigger->tags, zbx_db_tag_free); zbx_vector_db_tag_ptr_destroy(&trigger->override_tags); - zbx_vector_ptr_destroy(&trigger->tags); + zbx_vector_db_tag_ptr_destroy(&trigger->tags); zbx_vector_ptr_destroy(&trigger->dependents); zbx_vector_ptr_clear_ext(&trigger->dependencies, zbx_ptr_free); zbx_vector_ptr_destroy(&trigger->dependencies); @@ -350,7 +323,7 @@ static void lld_trigger_prototypes_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t zbx_vector_ptr_create(&trigger_prototype->functions); zbx_vector_ptr_create(&trigger_prototype->dependencies); - zbx_vector_ptr_create(&trigger_prototype->tags); + zbx_vector_db_tag_ptr_create(&trigger_prototype->tags); zbx_eval_init(&trigger_prototype->eval_ctx); zbx_eval_init(&trigger_prototype->eval_ctx_r); @@ -512,7 +485,7 @@ static void lld_triggers_get(const zbx_vector_ptr_t *trigger_prototypes, zbx_vec zbx_vector_ptr_create(&trigger->functions); zbx_vector_ptr_create(&trigger->dependencies); zbx_vector_ptr_create(&trigger->dependents); - zbx_vector_ptr_create(&trigger->tags); + zbx_vector_db_tag_ptr_create(&trigger->tags); zbx_vector_db_tag_ptr_create(&trigger->override_tags); zbx_vector_ptr_append(triggers, trigger); @@ -796,55 +769,37 @@ static void lld_tags_get(const zbx_vector_ptr_t *trigger_prototypes, zbx_vector_ while (NULL != (row = DBfetch(result))) { + zbx_db_tag_t *tag; int index; zbx_uint64_t triggerid; - zbx_lld_tag_t *tag = (zbx_lld_tag_t *)zbx_malloc(NULL, sizeof(zbx_lld_tag_t)); - ZBX_STR2UINT64(tag->triggertagid, row[0]); + tag = zbx_db_tag_create(row[2], row[3]); ZBX_STR2UINT64(triggerid, row[1]); - tag->tag = zbx_strdup(NULL, row[2]); - tag->tag_orig = NULL; - tag->value = zbx_strdup(NULL, row[3]); - tag->value_orig = NULL; - tag->flags = ZBX_FLAG_LLD_DEPENDENCY_UNSET; if (FAIL != (index = zbx_vector_ptr_bsearch(trigger_prototypes, &triggerid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC))) { trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[index]; - zbx_vector_ptr_append(&trigger_prototype->tags, tag); + zbx_vector_db_tag_ptr_append(&trigger_prototype->tags, tag); } else if (FAIL != (index = zbx_vector_ptr_bsearch(triggers, &triggerid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC))) { trigger = (zbx_lld_trigger_t *)triggers->values[index]; - zbx_vector_ptr_append(&trigger->tags, tag); + ZBX_STR2UINT64(tag->tagid, row[0]); + zbx_vector_db_tag_ptr_append(&trigger->tags, tag); } else { THIS_SHOULD_NEVER_HAPPEN; - lld_tag_free(tag); + zbx_db_tag_free(tag); } } DBfree_result(result); - for (i = 0; i < trigger_prototypes->values_num; i++) - { - trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[i]; - - zbx_vector_ptr_sort(&trigger_prototype->tags, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC); - } - - for (i = 0; i < triggers->values_num; i++) - { - trigger = (zbx_lld_trigger_t *)triggers->values[i]; - - zbx_vector_ptr_sort(&trigger->tags, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC); - } - zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } @@ -1562,7 +1517,7 @@ static void lld_trigger_make(const zbx_lld_trigger_prototype_t *trigger_prototy zbx_vector_ptr_create(&trigger->functions); zbx_vector_ptr_create(&trigger->dependencies); zbx_vector_ptr_create(&trigger->dependents); - zbx_vector_ptr_create(&trigger->tags); + zbx_vector_db_tag_ptr_create(&trigger->tags); trigger->flags = ZBX_FLAG_LLD_TRIGGER_UNSET; @@ -1891,95 +1846,50 @@ static void lld_trigger_dependencies_make(const zbx_vector_ptr_t *trigger_protot * * ******************************************************************************/ static void lld_trigger_tag_make(const zbx_lld_trigger_prototype_t *trigger_prototype, - zbx_hashset_t *items_triggers, const zbx_lld_row_t *lld_row, const zbx_vector_ptr_t *lld_macro_paths) + zbx_hashset_t *items_triggers, const zbx_lld_row_t *lld_row, const zbx_vector_ptr_t *lld_macro_paths, + char **error) { zbx_lld_trigger_t *trigger; int i; + zbx_vector_db_tag_ptr_t new_tags; + zbx_db_tag_t *tag; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); if (NULL == (trigger = lld_trigger_get(trigger_prototype->triggerid, items_triggers, &lld_row->item_links))) goto out; - zbx_vector_db_tag_ptr_sort(&trigger->override_tags, zbx_db_tag_compare_func); + zbx_vector_db_tag_ptr_create(&new_tags); - for (i = 0; i < trigger_prototype->tags.values_num + trigger->override_tags.values_num; i++) + for (i = 0; i < trigger_prototype->tags.values_num; i++) { - zbx_lld_tag_t *tag; - const char *key, *value; - - if (i < trigger_prototype->tags.values_num) - { - zbx_lld_tag_t *tag_proto; - - tag_proto = (zbx_lld_tag_t *)trigger_prototype->tags.values[i]; - key = tag_proto->tag; - value = tag_proto->value; - } - else - { - zbx_db_tag_t *dbtag; - - dbtag = trigger->override_tags.values[i - trigger_prototype->tags.values_num]; - key = dbtag->tag; - value = dbtag->value; - } - - if (i < trigger->tags.values_num) - { - char *buffer = NULL; - - tag = (zbx_lld_tag_t *)trigger->tags.values[i]; - - buffer = zbx_strdup(buffer, key); - substitute_lld_macros(&buffer, &lld_row->jp_row, lld_macro_paths, ZBX_MACRO_FUNC, NULL, 0); - zbx_lrtrim(buffer, ZBX_WHITESPACE); - - if (0 != strcmp(buffer, tag->tag)) - { - tag->tag_orig = tag->tag; - tag->tag = buffer; - buffer = NULL; - tag->flags |= ZBX_FLAG_LLD_TAG_UPDATE_TAG; - } - - buffer = zbx_strdup(buffer, value); - substitute_lld_macros(&buffer, &lld_row->jp_row, lld_macro_paths, ZBX_MACRO_FUNC, NULL, 0); - zbx_lrtrim(buffer, ZBX_WHITESPACE); - - if (0 != strcmp(buffer, tag->value)) - { - tag->value_orig = tag->value; - tag->value = buffer; - buffer = NULL; - tag->flags |= ZBX_FLAG_LLD_TAG_UPDATE_VALUE; - } - - zbx_free(buffer); - } - else - { - tag = (zbx_lld_tag_t *)zbx_malloc(NULL, sizeof(zbx_lld_tag_t)); - - tag->triggertagid = 0; - - tag->tag = zbx_strdup(NULL, key); - tag->tag_orig = NULL; - substitute_lld_macros(&tag->tag, &lld_row->jp_row, lld_macro_paths, ZBX_MACRO_FUNC, NULL, 0); - zbx_lrtrim(tag->tag, ZBX_WHITESPACE); - - tag->value = zbx_strdup(NULL, value); - tag->value_orig = NULL; - substitute_lld_macros(&tag->value, &lld_row->jp_row, lld_macro_paths, ZBX_MACRO_FUNC, NULL, 0); - zbx_lrtrim(tag->value, ZBX_WHITESPACE); + tag = zbx_db_tag_create(trigger_prototype->tags.values[i]->tag, + trigger_prototype->tags.values[i]->value); + zbx_vector_db_tag_ptr_append(&new_tags, tag); + } - tag->flags = ZBX_FLAG_LLD_TAG_UNSET; + for (i = 0; i < trigger->override_tags.values_num; i++) + { + tag = zbx_db_tag_create(trigger->override_tags.values[i]->tag, + trigger->override_tags.values[i]->value); + zbx_vector_db_tag_ptr_append(&new_tags, tag); + } - zbx_vector_ptr_append(&trigger->tags, tag); - } + for (i = 0; i < new_tags.values_num; i++) + { + substitute_lld_macros(&new_tags.values[i]->tag, &lld_row->jp_row, lld_macro_paths, ZBX_MACRO_FUNC, + NULL, 0); + substitute_lld_macros(&new_tags.values[i]->value, &lld_row->jp_row, lld_macro_paths, ZBX_MACRO_FUNC, + NULL, 0); + } - tag->flags |= ZBX_FLAG_LLD_TAG_DISCOVERED; + if (SUCCEED != zbx_merge_tags(&trigger->tags, &new_tags, "trigger", error) && 0 == trigger->triggerid) + { + trigger->flags &= ~ZBX_FLAG_LLD_TRIGGER_DISCOVERED; + *error = zbx_strdcatf(*error, "Cannot create trigger: tag validation failed.\n"); } + + zbx_vector_db_tag_ptr_destroy(&new_tags); out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } @@ -1990,7 +1900,7 @@ out: * * ******************************************************************************/ static void lld_trigger_tags_make(const zbx_vector_ptr_t *trigger_prototypes, zbx_vector_ptr_t *triggers, - const zbx_vector_ptr_t *lld_rows, const zbx_vector_ptr_t *lld_macro_paths) + const zbx_vector_ptr_t *lld_rows, const zbx_vector_ptr_t *lld_macro_paths, char **error) { zbx_lld_trigger_prototype_t *trigger_prototype; int i, j; @@ -1998,7 +1908,6 @@ static void lld_trigger_tags_make(const zbx_vector_ptr_t *trigger_prototypes, zb zbx_lld_trigger_t *trigger; zbx_lld_function_t *function; zbx_lld_item_trigger_t item_trigger; - zbx_lld_tag_t *tag; /* used for fast search of trigger by item prototype */ zbx_hashset_create(&items_triggers, 512, items_triggers_hash_func, items_triggers_compare_func); @@ -2029,24 +1938,7 @@ static void lld_trigger_tags_make(const zbx_vector_ptr_t *trigger_prototypes, zb { zbx_lld_row_t *lld_row = (zbx_lld_row_t *)lld_rows->values[j]; - lld_trigger_tag_make(trigger_prototype, &items_triggers, lld_row, lld_macro_paths); - } - } - - /* marking tags which will be deleted */ - for (i = 0; i < triggers->values_num; i++) - { - trigger = (zbx_lld_trigger_t *)triggers->values[i]; - - if (0 == (trigger->flags & ZBX_FLAG_LLD_TRIGGER_DISCOVERED)) - continue; - - for (j = 0; j < trigger->tags.values_num; j++) - { - tag = (zbx_lld_tag_t *)trigger->tags.values[j]; - - if (0 == (tag->flags & ZBX_FLAG_LLD_TAG_DISCOVERED)) - tag->flags = ZBX_FLAG_LLD_TAG_DELETE; + lld_trigger_tag_make(trigger_prototype, &items_triggers, lld_row, lld_macro_paths, error); } } @@ -2280,7 +2172,7 @@ static void lld_triggers_validate(zbx_uint64_t hostid, zbx_vector_ptr_t *trigger zbx_vector_ptr_create(&db_trigger->functions); zbx_vector_ptr_create(&db_trigger->dependencies); zbx_vector_ptr_create(&db_trigger->dependents); - zbx_vector_ptr_create(&db_trigger->tags); + zbx_vector_db_tag_ptr_create(&db_trigger->tags); zbx_vector_db_tag_ptr_create(&db_trigger->override_tags); zbx_vector_ptr_append(&db_triggers, db_trigger); @@ -2354,98 +2246,6 @@ static void lld_triggers_validate(zbx_uint64_t hostid, zbx_vector_ptr_t *trigger zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } -static void lld_validate_trigger_tag_field(zbx_lld_tag_t *tag, const char *field, zbx_uint64_t flag, - size_t field_len, char **error) -{ - size_t len; - - if (0 == (tag->flags & ZBX_FLAG_LLD_TAG_DISCOVERED)) - return; - - /* only new trigger tags or tags with changed data will be validated */ - if (0 != tag->triggertagid && 0 == (tag->flags & flag)) - return; - - if (SUCCEED != zbx_is_utf8(field)) - { - char *field_utf8; - - field_utf8 = zbx_strdup(NULL, field); - zbx_replace_invalid_utf8(field_utf8); - *error = zbx_strdcatf(*error, "Cannot create trigger tag: value \"%s\" has invalid UTF-8 sequence.\n", - field_utf8); - zbx_free(field_utf8); - } - else if ((len = zbx_strlen_utf8(field)) > field_len) - *error = zbx_strdcatf(*error, "Cannot create trigger tag: value \"%s\" is too long.\n", field); - else if (0 != (flag & ZBX_FLAG_LLD_TAG_UPDATE_TAG) && 0 == len) - *error = zbx_strdcatf(*error, "Cannot create trigger tag: empty tag name.\n"); - else - return; - - if (0 != tag->triggertagid) - tag->flags = ZBX_FLAG_LLD_TAG_DELETE; - else - tag->flags &= ~ZBX_FLAG_LLD_TAG_DISCOVERED; -} - -/****************************************************************************** - * * - * Purpose: validate created or updated trigger tags * - * * - ******************************************************************************/ -static void lld_trigger_tags_validate(zbx_vector_ptr_t *triggers, char **error) -{ - int i, j, k; - zbx_lld_trigger_t *trigger; - zbx_lld_tag_t *tag, *tag_tmp; - - for (i = 0; i < triggers->values_num; i++) - { - trigger = (zbx_lld_trigger_t *)triggers->values[i]; - - if (0 == (trigger->flags & ZBX_FLAG_LLD_TRIGGER_DISCOVERED)) - continue; - - for (j = 0; j < trigger->tags.values_num; j++) - { - tag = (zbx_lld_tag_t *)trigger->tags.values[j]; - - lld_validate_trigger_tag_field(tag, tag->tag, ZBX_FLAG_LLD_TAG_UPDATE_TAG, - TAG_NAME_LEN, error); - lld_validate_trigger_tag_field(tag, tag->value, ZBX_FLAG_LLD_TAG_UPDATE_VALUE, - TAG_VALUE_LEN, error); - - if (0 == (tag->flags & ZBX_FLAG_LLD_TAG_DISCOVERED)) - continue; - - /* check for duplicated tag,values pairs */ - for (k = 0; k < j; k++) - { - tag_tmp = (zbx_lld_tag_t *)trigger->tags.values[k]; - - if (0 == strcmp(tag->tag, tag_tmp->tag) && 0 == strcmp(tag->value, tag_tmp->value)) - { - *error = zbx_strdcatf(*error, "Cannot create trigger tag: tag \"%s\"," - "\"%s\" already exists.\n", tag->tag, tag->value); - - if (0 != tag->triggertagid) - tag->flags = ZBX_FLAG_LLD_TAG_DELETE; - else - tag->flags &= ~ZBX_FLAG_LLD_TAG_DISCOVERED; - } - } - - /* reset trigger discovery flags for new trigger if tag discovery failed */ - if (0 == trigger->triggerid && 0 == (tag->flags & ZBX_FLAG_LLD_TAG_DISCOVERED)) - { - trigger->flags &= ~ZBX_FLAG_LLD_TRIGGER_DISCOVERED; - break; - } - } - } -} - /****************************************************************************** * * * Purpose: transforms the simple trigger expression to the DB format * @@ -2552,7 +2352,7 @@ static int lld_triggers_save(zbx_uint64_t hostid, const zbx_vector_ptr_t *trigge zbx_lld_trigger_t *trigger; zbx_lld_function_t *function; zbx_lld_dependency_t *dependency; - zbx_lld_tag_t *tag; + zbx_db_tag_t *tag; zbx_vector_uint64_t del_functionids, del_triggerdepids, del_triggertagids, trigger_protoids; zbx_uint64_t triggerid = 0, functionid = 0, triggerdepid = 0, triggerid_up, triggertagid; char *sql = NULL; @@ -2625,23 +2425,20 @@ static int lld_triggers_save(zbx_uint64_t hostid, const zbx_vector_ptr_t *trigge for (j = 0; j < trigger->tags.values_num; j++) { - tag = (zbx_lld_tag_t *)trigger->tags.values[j]; + tag = trigger->tags.values[j]; - if (0 != (tag->flags & ZBX_FLAG_LLD_TAG_DELETE)) + if (0 != (tag->flags & ZBX_FLAG_DB_TAG_REMOVE)) { - zbx_vector_uint64_append(&del_triggertagids, tag->triggertagid); + zbx_vector_uint64_append(&del_triggertagids, tag->tagid); zbx_audit_trigger_update_json_delete_tags(trigger->triggerid, - (int)ZBX_FLAG_DISCOVERY_CREATED, tag->triggertagid); + (int)ZBX_FLAG_DISCOVERY_CREATED, tag->tagid); continue; } - if (0 == (tag->flags & ZBX_FLAG_LLD_TAG_DISCOVERED)) - continue; - - if (0 == tag->triggertagid) + if (0 == tag->tagid) new_tags++; - else if (0 != (tag->flags & ZBX_FLAG_LLD_TAG_UPDATE)) + else if (0 != (tag->flags & ZBX_FLAG_DB_TAG_UPDATE)) upd_tags++; } } @@ -3012,31 +2809,28 @@ static int lld_triggers_save(zbx_uint64_t hostid, const zbx_vector_ptr_t *trigge { char *value_esc; - tag = (zbx_lld_tag_t *)trigger->tags.values[j]; - - if (0 != (tag->flags & ZBX_FLAG_LLD_TAG_DELETE)) - continue; + tag = trigger->tags.values[j]; - if (0 == (tag->flags & ZBX_FLAG_LLD_TAG_DISCOVERED)) + if (0 != (tag->flags & ZBX_FLAG_DB_TAG_REMOVE)) continue; - if (0 == tag->triggertagid) + if (0 == tag->tagid) { - tag->triggertagid = triggertagid++; - zbx_db_insert_add_values(&db_insert_ttags, tag->triggertagid, trigger->triggerid, + tag->tagid = triggertagid++; + zbx_db_insert_add_values(&db_insert_ttags, tag->tagid, trigger->triggerid, tag->tag, tag->value); zbx_audit_trigger_update_json_add_tags_and_values(trigger->triggerid, - (int)ZBX_FLAG_DISCOVERY_CREATED, tag->triggertagid, tag->tag, + (int)ZBX_FLAG_DISCOVERY_CREATED, tag->tagid, tag->tag, tag->value); } - else if (0 != (tag->flags & ZBX_FLAG_LLD_TAG_UPDATE)) + else if (0 != (tag->flags & ZBX_FLAG_DB_TAG_UPDATE)) { const char *d = ""; zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update trigger_tag set "); - if (0 != (tag->flags & ZBX_FLAG_LLD_TAG_UPDATE_TAG)) + if (0 != (tag->flags & ZBX_FLAG_DB_TAG_UPDATE_TAG)) { value_esc = DBdyn_escape_string(tag->tag); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "tag='%s'", value_esc); @@ -3044,21 +2838,23 @@ static int lld_triggers_save(zbx_uint64_t hostid, const zbx_vector_ptr_t *trigge d = ","; zbx_audit_trigger_update_json_update_tag_tag(trigger->triggerid, - tag->triggertagid, tag->tag_orig, tag->tag); + ZBX_FLAG_DISCOVERY_CREATED, tag->tagid, tag->tag_orig, + tag->tag); } - if (0 != (tag->flags & ZBX_FLAG_LLD_TAG_UPDATE_VALUE)) + if (0 != (tag->flags & ZBX_FLAG_DB_TAG_UPDATE_VALUE)) { value_esc = DBdyn_escape_string(tag->value); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%svalue='%s'", d, value_esc); zbx_free(value_esc); zbx_audit_trigger_update_json_update_tag_value(trigger->triggerid, - tag->triggertagid, tag->value_orig, tag->value); + ZBX_FLAG_DISCOVERY_CREATED, tag->tagid, tag->value_orig, + tag->value); } zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, - " where triggertagid=" ZBX_FS_UI64 ";\n", tag->triggertagid); + " where triggertagid=" ZBX_FS_UI64 ";\n", tag->tagid); } } } @@ -3807,8 +3603,7 @@ int lld_update_triggers(zbx_uint64_t hostid, zbx_uint64_t lld_ruleid, const zbx_ lld_triggers_validate(hostid, &triggers, error); lld_trigger_dependencies_make(&trigger_prototypes, &triggers, lld_rows, error); lld_trigger_dependencies_validate(&triggers, error); - lld_trigger_tags_make(&trigger_prototypes, &triggers, lld_rows, lld_macro_paths); - lld_trigger_tags_validate(&triggers, error); + lld_trigger_tags_make(&trigger_prototypes, &triggers, lld_rows, lld_macro_paths, error); ret = lld_triggers_save(hostid, &trigger_prototypes, &triggers); lld_remove_lost_objects("trigger_discovery", "triggerid", &triggers, lifetime, lastcheck, DBdelete_triggers, get_trigger_info); |