/* ** Zabbix ** Copyright (C) 2001-2021 Zabbix SIA ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ #include "db.h" #include "../../libs/zbxaudit/audit_graph.h" #include "graph_linking.h" typedef struct { zbx_uint64_t itemid; zbx_uint64_t gitemid; char key[ITEM_KEY_LEN * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1]; int drawtype_orig; int drawtype_new; int sortorder_orig; int sortorder_new; char color_orig[GRAPH_ITEM_COLOR_LEN_MAX]; char color_new[GRAPH_ITEM_COLOR_LEN_MAX]; int yaxisside_orig; int yaxisside_new; int calc_fnc_orig; int calc_fnc_new; int type_orig; int type_new; unsigned char flags; #define ZBX_FLAG_LINK_GRAPHITEM_UNSET __UINT64_C(0x00) #define ZBX_FLAG_LINK_GRAPHITEM_UPDATE_DRAWTYPE __UINT64_C(0x01) #define ZBX_FLAG_LINK_GRAPHITEM_UPDATE_SORTORDER __UINT64_C(0x02) #define ZBX_FLAG_LINK_GRAPHITEM_UPDATE_COLOR __UINT64_C(0x04) #define ZBX_FLAG_LINK_GRAPHITEM_UPDATE_YAXISSIDE __UINT64_C(0x08) #define ZBX_FLAG_LINK_GRAPHITEM_UPDATE_CALC_FNC __UINT64_C(0x10) #define ZBX_FLAG_LINK_GRAPHITEM_UPDATE_TYPE __UINT64_C(0x20) #define ZBX_FLAG_LINK_GRAPHITEM_UPDATE \ (ZBX_FLAG_LINK_GRAPHITEM_UPDATE_DRAWTYPE | ZBX_FLAG_LINK_GRAPHITEM_UPDATE_SORTORDER | \ ZBX_FLAG_LINK_GRAPHITEM_UPDATE_COLOR | ZBX_FLAG_LINK_GRAPHITEM_UPDATE_YAXISSIDE | \ ZBX_FLAG_LINK_GRAPHITEM_UPDATE_CALC_FNC | ZBX_FLAG_LINK_GRAPHITEM_UPDATE_TYPE) zbx_uint64_t update_flags; } graph_item_entry; typedef struct { zbx_uint64_t graphid; char *name_orig; char *name; int width_orig; int width; int height_orig; int height; double yaxismin_orig; double yaxismin; double yaxismax_orig; double yaxismax; unsigned char show_work_period_orig; unsigned char show_work_period; unsigned char show_triggers_orig; unsigned char show_triggers; unsigned char graphtype_orig; unsigned char graphtype; unsigned char show_legend_orig; unsigned char show_legend; unsigned char show_3d_orig; unsigned char show_3d; double percent_left_orig; double percent_left; double percent_right_orig; double percent_right; unsigned char ymin_type_orig; unsigned char ymin_type; unsigned char ymax_type_orig; unsigned char ymax_type; zbx_uint64_t ymin_itemid_orig; zbx_uint64_t ymin_itemid; zbx_uint64_t ymax_itemid_orig; zbx_uint64_t ymax_itemid; unsigned char flags; unsigned char discover_orig; unsigned char discover; #define ZBX_FLAG_LINK_GRAPH_UNSET __UINT64_C(0x00000000) #define ZBX_FLAG_LINK_GRAPH_UPDATE_NAME __UINT64_C(0x00000001) #define ZBX_FLAG_LINK_GRAPH_UPDATE_WIDTH __UINT64_C(0x00000002) #define ZBX_FLAG_LINK_GRAPH_UPDATE_HEIGHT __UINT64_C(0x00000004) #define ZBX_FLAG_LINK_GRAPH_UPDATE_YAXISMIN __UINT64_C(0x00000008) #define ZBX_FLAG_LINK_GRAPH_UPDATE_YAXISMAX __UINT64_C(0x00000010) #define ZBX_FLAG_LINK_GRAPH_UPDATE_SHOW_WORK_PERIOD __UINT64_C(0x00000020) #define ZBX_FLAG_LINK_GRAPH_UPDATE_SHOW_TRIGGERS __UINT64_C(0x00000040) #define ZBX_FLAG_LINK_GRAPH_UPDATE_GRAPHTYPE __UINT64_C(0x00000080) #define ZBX_FLAG_LINK_GRAPH_UPDATE_SHOW_LEGEND __UINT64_C(0x00000100) #define ZBX_FLAG_LINK_GRAPH_UPDATE_SHOW_3D __UINT64_C(0x00000200) #define ZBX_FLAG_LINK_GRAPH_UPDATE_PERCENT_LEFT __UINT64_C(0x00000400) #define ZBX_FLAG_LINK_GRAPH_UPDATE_PERCENT_RIGHT __UINT64_C(0x00000800) #define ZBX_FLAG_LINK_GRAPH_UPDATE_YMIN_TYPE __UINT64_C(0x00001000) #define ZBX_FLAG_LINK_GRAPH_UPDATE_YMAX_TYPE __UINT64_C(0x00002000) #define ZBX_FLAG_LINK_GRAPH_UPDATE_YMIN_ITEMID __UINT64_C(0x00004000) #define ZBX_FLAG_LINK_GRAPH_UPDATE_YMAX_ITEMID __UINT64_C(0x00008000) #define ZBX_FLAG_LINK_GRAPH_UPDATE_DISCOVER __UINT64_C(0x00020000) zbx_uint64_t update_flags; zbx_uint64_t templateid_orig; zbx_uint64_t templateid; } zbx_graph_copy_t; static zbx_graph_copy_t *zbx_graph_copy_init_new(zbx_uint64_t graphid, const char *name, int width, int height, double yaxismin, double yaxismax, unsigned char show_work_period, unsigned char show_triggers, unsigned char graphtype, unsigned char show_legend, unsigned char show_3d, double percent_left, double percent_right, unsigned char ymin_type, unsigned char ymax_type, zbx_uint64_t ymin_itemid, zbx_uint64_t ymax_itemid, unsigned char flags, unsigned char discover, zbx_uint64_t templateid) { zbx_graph_copy_t *graph_copy; graph_copy = (zbx_graph_copy_t*)zbx_malloc(NULL, sizeof(zbx_graph_copy_t)); graph_copy->graphid = graphid; #define INIT_STR_N(r) graph_copy->r = zbx_strdup(NULL, r); \ graph_copy->r##_orig = NULL; #define INIT_INT_OR_DBL_N(r) graph_copy->r = r; \ graph_copy->r##_orig = 0; INIT_STR_N(name) INIT_INT_OR_DBL_N(width) INIT_INT_OR_DBL_N(height) INIT_INT_OR_DBL_N(yaxismin) INIT_INT_OR_DBL_N(yaxismax) INIT_INT_OR_DBL_N(show_work_period) INIT_INT_OR_DBL_N(show_triggers) INIT_INT_OR_DBL_N(graphtype) INIT_INT_OR_DBL_N(show_legend) INIT_INT_OR_DBL_N(show_3d) INIT_INT_OR_DBL_N(percent_left) INIT_INT_OR_DBL_N(percent_right) INIT_INT_OR_DBL_N(ymin_type) INIT_INT_OR_DBL_N(ymax_type) INIT_INT_OR_DBL_N(ymin_itemid) INIT_INT_OR_DBL_N(ymax_itemid) graph_copy->flags = flags; INIT_INT_OR_DBL_N(discover) #undef INIT_STR_N #undef INIT_INT_OR_DBL_N graph_copy->update_flags = ZBX_FLAG_LINK_GRAPH_UNSET; graph_copy->templateid = templateid; graph_copy->templateid_orig = 0; return graph_copy; } static void zbx_graph_copy_init_orig(zbx_graph_copy_t *graph_copy, zbx_uint64_t graphid, const char *name, int width, int height, double yaxismin, double yaxismax, unsigned char show_work_period, unsigned char show_triggers, unsigned char graphtype, unsigned char show_legend, unsigned char show_3d, double percent_left, double percent_right, unsigned char ymin_type, unsigned char ymax_type, zbx_uint64_t ymin_itemid, zbx_uint64_t ymax_itemid, unsigned char flags, unsigned char discover, zbx_uint64_t templateid_orig) { graph_copy->graphid = graphid; #define INIT_STR_ORIG(r) graph_copy->r = NULL; \ graph_copy->r##_orig = zbx_strdup(NULL, r); #define INIT_INT_OR_DBL_ORIG(r) graph_copy->r = 0; \ graph_copy->r##_orig = r; INIT_STR_ORIG(name) INIT_INT_OR_DBL_ORIG(width) INIT_INT_OR_DBL_ORIG(height) INIT_INT_OR_DBL_ORIG(yaxismin) INIT_INT_OR_DBL_ORIG(yaxismax) INIT_INT_OR_DBL_ORIG(show_work_period) INIT_INT_OR_DBL_ORIG(show_triggers) INIT_INT_OR_DBL_ORIG(graphtype) INIT_INT_OR_DBL_ORIG(show_legend) INIT_INT_OR_DBL_ORIG(show_3d) INIT_INT_OR_DBL_ORIG(percent_left) INIT_INT_OR_DBL_ORIG(percent_right) INIT_INT_OR_DBL_ORIG(ymin_type) INIT_INT_OR_DBL_ORIG(ymax_type) INIT_INT_OR_DBL_ORIG(ymin_itemid) INIT_INT_OR_DBL_ORIG(ymax_itemid) graph_copy->flags = flags; INIT_INT_OR_DBL_ORIG(discover) #undef INIT_STR_ORIG #undef INIT_INT_OR_DBL_ORIG graph_copy->update_flags = ZBX_FLAG_LINK_GRAPH_UNSET; graph_copy->templateid = 0; graph_copy->templateid_orig = templateid_orig; } static zbx_hash_t graphs_copies_hash_func(const void *data) { const zbx_graph_copy_t *graph_copy = (const zbx_graph_copy_t *)data; return ZBX_DEFAULT_UINT64_HASH_ALGO(&((graph_copy)->graphid), sizeof((graph_copy)->graphid), ZBX_DEFAULT_HASH_SEED); } static int graphs_copies_compare_func(const void *d1, const void *d2) { const zbx_graph_copy_t *graph_copy_1 = (const zbx_graph_copy_t *)d1; const zbx_graph_copy_t *graph_copy_2 = (const zbx_graph_copy_t *)d2; ZBX_RETURN_IF_NOT_EQUAL((graph_copy_1)->graphid, (graph_copy_2)->graphid); return 0; } static void graphs_copies_clean(zbx_hashset_t *x) { zbx_hashset_iter_t iter; zbx_graph_copy_t *graph_copy; zbx_hashset_iter_reset(x, &iter); while (NULL != (graph_copy = (zbx_graph_copy_t *)zbx_hashset_iter_next(&iter))) { zbx_free(graph_copy->name_orig); if (0 != (graph_copy->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_NAME)) zbx_free(graph_copy->name); } zbx_hashset_destroy(x); } typedef struct zbx_graph_names_entry { const char *name; zbx_vector_uint64_t graphids; } zbx_graph_names_entry_t; static zbx_hash_t zbx_graphs_names_hash_func(const void *data) { const zbx_graph_names_entry_t *graph_names_entry = (const zbx_graph_names_entry_t *)data; return ZBX_DEFAULT_STRING_HASH_ALGO(graph_names_entry->name, strlen(graph_names_entry->name), ZBX_DEFAULT_HASH_SEED); } static int zbx_graphs_names_compare_func(const void *d1, const void *d2) { const zbx_graph_names_entry_t *graph_names_entry_1 = (const zbx_graph_names_entry_t *)d1; const zbx_graph_names_entry_t *graph_names_entry_2 = (const zbx_graph_names_entry_t *)d2; return strcmp((graph_names_entry_1)->name, (graph_names_entry_2)->name); } static void graphs_names_clean(zbx_hashset_t *x) { zbx_hashset_iter_t iter; zbx_graph_names_entry_t *graph_name_entry; zbx_hashset_iter_reset(x, &iter); while (NULL != (graph_name_entry = (zbx_graph_names_entry_t *)zbx_hashset_iter_next(&iter))) { zbx_vector_uint64_destroy(&(graph_name_entry->graphids)); } zbx_hashset_destroy(x); } static void graphs_copies_clean_vec_entry(zbx_graph_copy_t *copy) { zbx_free(copy->name); zbx_free(copy); } ZBX_PTR_VECTOR_DECL(graphs_copies, zbx_graph_copy_t*) ZBX_PTR_VECTOR_IMPL(graphs_copies, zbx_graph_copy_t*) ZBX_PTR_VECTOR_DECL(gitems, graph_item_entry*) ZBX_PTR_VECTOR_IMPL(gitems, graph_item_entry*) typedef struct { zbx_uint64_t graphid; zbx_vector_gitems_t gitems; } graphs_items_entry_t; static zbx_hash_t graphs_items_hash_func(const void *data) { const graphs_items_entry_t *trigger_entry = (const graphs_items_entry_t*)data; return ZBX_DEFAULT_UINT64_HASH_ALGO(&(trigger_entry->graphid), sizeof((trigger_entry)->graphid), ZBX_DEFAULT_HASH_SEED); } static int graphs_items_compare_func(const void *d1, const void *d2) { const graphs_items_entry_t *trigger_entry_1 = (const graphs_items_entry_t*)d1; const graphs_items_entry_t *trigger_entry_2 = (const graphs_items_entry_t*)d2; ZBX_RETURN_IF_NOT_EQUAL((trigger_entry_1)->graphid, (trigger_entry_2)->graphid); return 0; } static void graph_item_entry_clean(graph_item_entry *x) { zbx_free(x); } static void graphs_items_clean(zbx_hashset_t *x) { zbx_hashset_iter_t iter; graphs_items_entry_t *trigger_entry; zbx_hashset_iter_reset(x, &iter); while (NULL != (trigger_entry = (graphs_items_entry_t *)zbx_hashset_iter_next(&iter))) { zbx_vector_gitems_clear_ext(&(trigger_entry->gitems), graph_item_entry_clean); zbx_vector_gitems_destroy(&(trigger_entry->gitems)); } zbx_hashset_destroy(x); } typedef struct { zbx_uint64_t key_itemid; zbx_uint64_t val_itemid; } itemids_map_entry_t; static zbx_hash_t itemids_map_hash_func(const void *data) { const itemids_map_entry_t *itemids_map_entry = (const itemids_map_entry_t*)data; return ZBX_DEFAULT_UINT64_HASH_ALGO(&(itemids_map_entry->key_itemid), sizeof(itemids_map_entry->key_itemid), ZBX_DEFAULT_HASH_SEED); } static int itemids_map_compare_func(const void *d1, const void *d2) { const itemids_map_entry_t *itemids_map_entry_1 = (const itemids_map_entry_t*)d1; const itemids_map_entry_t *itemids_map_entry_2 = (const itemids_map_entry_t*)d2; ZBX_RETURN_IF_NOT_EQUAL((itemids_map_entry_1)->key_itemid, (itemids_map_entry_2)->key_itemid); return 0; } static int get_templates_graphs_data(const zbx_vector_uint64_t *templateids, zbx_vector_graphs_copies_t *graphs_copies_templates, zbx_vector_uint64_t *templates_graphs_ids, zbx_vector_str_t *templates_graphs_names) { char *sql = NULL; size_t sql_alloc = 512, sql_offset = 0; int res = SUCCEED; DB_RESULT result; DB_ROW row; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); sql = (char *)zbx_malloc(sql, sql_alloc); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select distinct g.graphid,g.name,g.width,g.height,g.yaxismin," "g.yaxismax,g.show_work_period,g.show_triggers," "g.graphtype,g.show_legend,g.show_3d,g.percent_left," "g.percent_right,g.ymin_type,g.ymax_type,g.ymin_itemid," "g.ymax_itemid,g.flags,g.discover" " from graphs g,graphs_items gi,items i" " where g.graphid=gi.graphid" " and gi.itemid=i.itemid" " and"); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.hostid", templateids->values, templateids->values_num); if (NULL == (result = DBselect("%s", sql))) { res = FAIL; goto clean; } while (NULL != (row = DBfetch(result))) { zbx_uint64_t graphid, ymin_itemid, ymax_itemid; zbx_graph_copy_t *graph_copy; ZBX_STR2UINT64(graphid, row[0]); ZBX_DBROW2UINT64(ymin_itemid, row[15]); ZBX_DBROW2UINT64(ymax_itemid, row[16]); graph_copy = zbx_graph_copy_init_new(graphid, row[1], atoi(row[2]), atoi(row[3]), atof(row[4]), atof(row[5]), (unsigned char)atoi(row[6]), (unsigned char)atoi(row[7]), (unsigned char)atoi(row[8]), (unsigned char)atoi(row[9]), (unsigned char)atoi(row[10]), atof(row[11]), atof(row[12]), (unsigned char)atoi(row[13]), (unsigned char)atoi(row[14]), ymin_itemid, ymax_itemid, (unsigned char)atoi(row[17]), (unsigned char)atoi(row[18]), 0); zbx_vector_graphs_copies_append(graphs_copies_templates, graph_copy); zbx_vector_uint64_append(templates_graphs_ids, graph_copy->graphid); zbx_vector_str_append(templates_graphs_names, DBdyn_escape_string(graph_copy->name)); } clean: DBfree_result(result); zbx_free(sql); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(res)); return res; } static int update_same_itemids(zbx_uint64_t hostid, zbx_vector_graphs_copies_t *graphs_copies_templates) { int i, res = SUCCEED; char *sql = NULL; size_t sql_alloc = 256, sql_offset = 0; zbx_hashset_t y_data_map; zbx_vector_uint64_t y_data_ids; DB_RESULT result; DB_ROW row; zabbix_log(LOG_LEVEL_DEBUG, "In %s() hostid:" ZBX_FS_UI64, __func__, hostid); zbx_vector_uint64_create(&y_data_ids); for (i = 0; i < graphs_copies_templates->values_num; i++) { zbx_vector_uint64_append(&y_data_ids, graphs_copies_templates->values[i]->ymin_itemid); zbx_vector_uint64_append(&y_data_ids, graphs_copies_templates->values[i]->ymax_itemid); } if (0 == y_data_ids.values_num) goto out; #define TRIGGER_GITEMS_HASHSET_DEF_SIZE 100 zbx_hashset_create(&y_data_map, TRIGGER_GITEMS_HASHSET_DEF_SIZE, itemids_map_hash_func, itemids_map_compare_func); #undef TRIGGER_GITEMS_HASHSET_DEF_SIZE sql = (char *)zbx_malloc(sql, sql_alloc); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select ti.itemid,hi.itemid from items hi,items ti" " where hi.key_=ti.key_ " " and hi.hostid="ZBX_FS_UI64 " and", hostid); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ti.itemid", y_data_ids.values, y_data_ids.values_num); if (NULL == (result = DBselect("%s", sql))) { res = FAIL; goto clean; } while (NULL != (row = DBfetch(result))) { itemids_map_entry_t itemids_map_entry; ZBX_STR2UINT64(itemids_map_entry.key_itemid, row[0]); ZBX_STR2UINT64(itemids_map_entry.val_itemid, row[1]); zbx_hashset_insert(&y_data_map, &itemids_map_entry, sizeof(itemids_map_entry)); } for (i = 0; i < graphs_copies_templates->values_num; i++) { zbx_uint64_t ymin_itemid_new = 0, ymax_itemid_new = 0; itemids_map_entry_t *found, temp_t; if (GRAPH_YAXIS_TYPE_ITEM_VALUE == graphs_copies_templates->values[i]->ymin_type) { temp_t.key_itemid = graphs_copies_templates->values[i]->ymin_itemid; if (NULL != (found = (itemids_map_entry_t*)zbx_hashset_search(&y_data_map, &temp_t))) ymin_itemid_new = found->val_itemid; } if (GRAPH_YAXIS_TYPE_ITEM_VALUE == graphs_copies_templates->values[i]->ymax_type) { temp_t.key_itemid = graphs_copies_templates->values[i]->ymax_itemid; if (NULL != (found = (itemids_map_entry_t*)zbx_hashset_search(&y_data_map, &temp_t))) ymax_itemid_new = found->val_itemid; } graphs_copies_templates->values[i]->ymin_itemid = ymin_itemid_new; graphs_copies_templates->values[i]->ymax_itemid = ymax_itemid_new; } clean: zbx_free(sql); zbx_hashset_destroy(&y_data_map); DBfree_result(result); out: zbx_vector_uint64_destroy(&y_data_ids); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(res)); return res; } /* hostid is necessary for template, for host hostid is 0 */ static int get_graphs_items(zbx_uint64_t hostid, const zbx_vector_uint64_t *graphs_ids, zbx_hashset_t *graphs_items) { char *sql = NULL; size_t sql_alloc = 512, sql_offset = 0; int res = SUCCEED; DB_RESULT result; DB_ROW row; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); if (0 == graphs_ids->values_num) goto out; if (0 != hostid) { /* template */ zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select 0,dst.itemid,dst.key_,gi.drawtype,gi.sortorder,gi.color,gi.yaxisside," "gi.calc_fnc,gi.type,i.flags,gi.graphid" " from graphs_items gi,items i,items dst" " where gi.itemid=i.itemid" " and i.key_=dst.key_"); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " and dst.hostid=" ZBX_FS_UI64, hostid); } else { /* host */ zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select gi.gitemid,i.itemid,i.key_,gi.drawtype,gi.sortorder,gi.color,gi.yaxisside," "gi.calc_fnc,gi.type,i.flags,gi.graphid" " from graphs_items gi,items i" " where gi.itemid=i.itemid"); } zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and"); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "gi.graphid", graphs_ids->values, graphs_ids->values_num); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by i.key_"); if (NULL == (result = DBselect("%s", sql))) { res = FAIL; goto clean; } while (NULL != (row = DBfetch(result))) { graphs_items_entry_t *found, temp_t; graph_item_entry *gitem; gitem = (graph_item_entry*)zbx_malloc(NULL, sizeof(graph_item_entry)); ZBX_STR2UINT64(gitem->itemid, row[1]); ZBX_STR2UINT64(gitem->gitemid, row[0]); zbx_strlcpy(gitem->key, row[2], sizeof(gitem->key)); gitem->drawtype_orig = atoi(row[3]); gitem->drawtype_new = 0; gitem->sortorder_orig = atoi(row[4]); gitem->sortorder_new = 0; zbx_strlcpy(gitem->color_orig, row[5], sizeof(gitem->color_orig)); gitem->yaxisside_orig = atoi(row[6]); gitem->yaxisside_new = 0; gitem->calc_fnc_orig = atoi(row[7]); gitem->calc_fnc_new = 0; gitem->type_orig = atoi(row[8]); gitem->type_new = 0; gitem->flags = (unsigned char)atoi(row[9]); gitem->update_flags = ZBX_FLAG_LINK_GRAPHITEM_UNSET; ZBX_STR2UINT64(temp_t.graphid, row[10]); if (NULL != (found = (graphs_items_entry_t*)zbx_hashset_search(graphs_items, &temp_t))) { zbx_vector_gitems_append(&(found->gitems), gitem); } else { zbx_vector_gitems_create(&(temp_t.gitems)); zbx_vector_gitems_append(&(temp_t.gitems), gitem); ZBX_STR2UINT64(temp_t.graphid, row[10]); zbx_hashset_insert(graphs_items, &temp_t, sizeof(temp_t)); } } clean: zbx_free(sql); DBfree_result(result); out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(res)); return res; } static int get_target_host_main_data(zbx_uint64_t hostid, zbx_vector_str_t *templates_graphs_names, zbx_vector_uint64_t *host_graphs_ids, zbx_hashset_t *host_graphs_main_data, zbx_hashset_t *host_graphs_names) { char *sql = NULL; size_t sql_alloc = 256, sql_offset = 0; int res = SUCCEED; DB_RESULT result; DB_ROW row; zabbix_log(LOG_LEVEL_DEBUG, "In %s() hostid:" ZBX_FS_UI64, __func__, hostid); sql = (char *)zbx_malloc(sql, sql_alloc); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select distinct g.graphid,g.name,g.width,g.height,g.yaxismin,g.yaxismax,g.show_work_period" ",g.show_triggers,g.graphtype,g.show_legend,g.show_3d,g.percent_left,g.percent_right" ",g.ymin_type,g.ymax_type,g.ymin_itemid,g.ymax_itemid,g.discover,g.templateid,g.flags" " from graphs g,graphs_items gi,items i" " where g.graphid=gi.graphid" " and gi.itemid=i.itemid" " and i.hostid=" ZBX_FS_UI64 " and g.templateid is null" " and", hostid); DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "g.name", (const char**)templates_graphs_names->values, templates_graphs_names->values_num); if (NULL == (result = DBselect("%s", sql))) { res = FAIL; goto clean; } while (NULL != (row = DBfetch(result))) { zbx_uint64_t graphid, ymin_itemid, ymax_itemid, templateid_orig; zbx_graph_copy_t graph_copy; zbx_graph_names_entry_t temp_t, *found; graph_copy.update_flags = ZBX_FLAG_LINK_GRAPH_UNSET; ZBX_STR2UINT64(graphid, row[0]); zbx_vector_uint64_append(host_graphs_ids, graphid); ZBX_DBROW2UINT64(ymin_itemid, row[15]); ZBX_DBROW2UINT64(ymax_itemid, row[16]); ZBX_DBROW2UINT64(templateid_orig, row[18]); zbx_graph_copy_init_orig(&graph_copy, graphid, row[1], atoi(row[2]), atoi(row[3]), atof(row[4]), atof(row[5]), (unsigned char)atoi(row[6]), (unsigned char)atoi(row[7]), (unsigned char)atoi(row[8]), (unsigned char)atoi(row[9]), (unsigned char)atoi(row[10]), atof(row[11]), atof(row[12]), (unsigned char)atoi(row[13]), (unsigned char)atoi(row[14]), ymin_itemid, ymax_itemid, (unsigned char)atoi(row[19]), (unsigned char)atoi(row[17]), templateid_orig); zbx_hashset_insert(host_graphs_main_data, &graph_copy, sizeof(graph_copy)); temp_t.name = graph_copy.name_orig; if (NULL != (found = (zbx_graph_names_entry_t *)zbx_hashset_search(host_graphs_names, &temp_t))) { zbx_vector_uint64_append(&(found->graphids), graphid); } else { zbx_graph_names_entry_t local_temp_t; zbx_vector_uint64_create(&(local_temp_t.graphids)); local_temp_t.name = graph_copy.name_orig; zbx_vector_uint64_append(&(local_temp_t.graphids), graphid); zbx_hashset_insert(host_graphs_names, &local_temp_t, sizeof(local_temp_t)); } } clean: zbx_free(sql); DBfree_result(result); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(res)); return res; } static void mark_updates_for_host_graph(zbx_graph_copy_t *template_graph_copy, zbx_graph_copy_t *host_graph_copy_found) { if (0 != strcmp(template_graph_copy->name, host_graph_copy_found->name_orig)) { host_graph_copy_found->name = zbx_strdup(NULL, template_graph_copy->name); host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_NAME; } if (template_graph_copy->width != host_graph_copy_found->width_orig) { host_graph_copy_found->width = template_graph_copy->width; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_WIDTH; } if (template_graph_copy->height != host_graph_copy_found->height_orig) { host_graph_copy_found->height = template_graph_copy->height; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_HEIGHT; } if (FAIL == zbx_double_compare(template_graph_copy->yaxismin, host_graph_copy_found->yaxismin_orig)) { host_graph_copy_found->yaxismin = template_graph_copy->yaxismin; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_YAXISMIN; } if (FAIL == zbx_double_compare(template_graph_copy->yaxismax, host_graph_copy_found->yaxismax_orig)) { host_graph_copy_found->yaxismax = template_graph_copy->yaxismax; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_YAXISMAX; } if (template_graph_copy->show_work_period != host_graph_copy_found->show_work_period_orig) { host_graph_copy_found->show_work_period = template_graph_copy->show_work_period; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_SHOW_WORK_PERIOD; } if (template_graph_copy->show_triggers != host_graph_copy_found->show_triggers_orig) { host_graph_copy_found->show_triggers = template_graph_copy->show_triggers; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_SHOW_TRIGGERS; } if (template_graph_copy->graphtype != host_graph_copy_found->graphtype_orig) { host_graph_copy_found->graphtype = template_graph_copy->graphtype; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_GRAPHTYPE; } if (template_graph_copy->show_legend != host_graph_copy_found->show_legend_orig) { host_graph_copy_found->show_legend = template_graph_copy->show_legend; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_SHOW_LEGEND; } if (template_graph_copy->show_3d != host_graph_copy_found->show_3d_orig) { host_graph_copy_found->show_3d = template_graph_copy->show_3d; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_SHOW_3D; } if (FAIL == zbx_double_compare(template_graph_copy->percent_left, host_graph_copy_found->percent_left_orig)) { host_graph_copy_found->percent_left = template_graph_copy->percent_left; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_PERCENT_LEFT; } if (FAIL == zbx_double_compare(template_graph_copy->percent_right, host_graph_copy_found->percent_right_orig)) { host_graph_copy_found->percent_right = template_graph_copy->percent_right; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_PERCENT_RIGHT; } if (template_graph_copy->ymin_type != host_graph_copy_found->ymin_type_orig) { host_graph_copy_found->ymin_type = template_graph_copy->ymin_type; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_YMIN_TYPE; } if (template_graph_copy->ymax_type != host_graph_copy_found->ymax_type_orig) { host_graph_copy_found->ymax_type = template_graph_copy->ymax_type; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_YMAX_TYPE; } if (template_graph_copy->ymin_itemid != host_graph_copy_found->ymin_itemid_orig) { host_graph_copy_found->ymin_itemid = template_graph_copy->ymin_itemid; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_YMIN_ITEMID; } if (template_graph_copy->ymax_itemid != host_graph_copy_found->ymax_itemid_orig) { host_graph_copy_found->ymax_itemid = template_graph_copy->ymax_itemid; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_YMAX_ITEMID; } if (template_graph_copy->discover != host_graph_copy_found->discover_orig) { host_graph_copy_found->discover = template_graph_copy->discover; host_graph_copy_found->update_flags |= ZBX_FLAG_LINK_GRAPH_UPDATE_DISCOVER; } host_graph_copy_found->templateid = template_graph_copy->graphid; } static int mark_updates_for_host_graph_items(graphs_items_entry_t *graphs_items_template_entry_found, graphs_items_entry_t *graphs_items_host_entry_found) { int j, res = FAIL; graph_item_entry *template_entry, *host_entry; for (j = 0; j < graphs_items_template_entry_found->gitems.values_num; j++) { template_entry = graphs_items_template_entry_found->gitems.values[j]; host_entry = graphs_items_host_entry_found->gitems.values[j]; if (template_entry->drawtype_orig != host_entry->drawtype_orig) { host_entry->drawtype_new = template_entry->drawtype_orig; host_entry->update_flags |= ZBX_FLAG_LINK_GRAPHITEM_UPDATE_DRAWTYPE; res = SUCCEED; } if (template_entry->sortorder_orig != host_entry->sortorder_orig) { host_entry->sortorder_new = template_entry->sortorder_orig; host_entry->update_flags |= ZBX_FLAG_LINK_GRAPHITEM_UPDATE_SORTORDER; res = SUCCEED; } if (0 != strcmp(template_entry->color_orig, host_entry->color_orig)) { zbx_strlcpy(host_entry->color_new, template_entry->color_orig, sizeof(template_entry->color_orig)); host_entry->update_flags |= ZBX_FLAG_LINK_GRAPHITEM_UPDATE_COLOR; res = SUCCEED; } if (template_entry->yaxisside_orig != host_entry->yaxisside_orig) { host_entry->yaxisside_new = template_entry->yaxisside_orig; host_entry->update_flags |= ZBX_FLAG_LINK_GRAPHITEM_UPDATE_YAXISSIDE; res = SUCCEED; } if (template_entry->calc_fnc_orig != host_entry->calc_fnc_orig) { host_entry->calc_fnc_new = template_entry->calc_fnc_orig; host_entry->update_flags |= ZBX_FLAG_LINK_GRAPHITEM_UPDATE_CALC_FNC; res = SUCCEED; } if (template_entry->type_orig != host_entry->type_orig) { host_entry->type_new = template_entry->type_orig; host_entry->update_flags |= ZBX_FLAG_LINK_GRAPHITEM_UPDATE_TYPE; res = SUCCEED; } } return res; } static void prepare_graph_for_insert(graphs_items_entry_t *graphs_items_template_entry_temp, zbx_vector_graphs_copies_t *graphs_copies_insert, zbx_graph_copy_t *template_graph_copy) { zbx_graph_copy_t *graph_copy; char *esc_name; esc_name = DBdyn_escape_string(template_graph_copy->name); graph_copy = zbx_graph_copy_init_new(0, esc_name, template_graph_copy->width, template_graph_copy->height, template_graph_copy->yaxismin, template_graph_copy->yaxismax, template_graph_copy->show_work_period, template_graph_copy->show_triggers, template_graph_copy->graphtype, template_graph_copy->show_legend, template_graph_copy->show_3d, template_graph_copy->percent_left, template_graph_copy->percent_right, template_graph_copy->ymin_type, template_graph_copy->ymax_type, template_graph_copy->ymin_itemid, template_graph_copy->ymax_itemid, template_graph_copy->flags, template_graph_copy->discover, graphs_items_template_entry_temp->graphid); zbx_free(esc_name); zbx_vector_graphs_copies_append(graphs_copies_insert, graph_copy); } /************************************************************************************ * * * Description: 1) gets a template graph and host graph and compares them * * 2) if they are the same (they have same names and all of * * their items keys are the same) and checks which fields * * on the target host graph need to be updated and marks * * them for update * * * * Parameters: host_graphid - [IN] target host graphid * * host_graphs_main_data - [IN] set of host graph copies * * with names that match the * * graphs from the templates * * host_graphs_items - [IN] helper set for the * * host_graphs_main_data * * graphs_items_template_entry_found - [IN/OUT] helper set for * * template_graph_copy * * template_graph_copy - [IN] template data * * upd_graphs_or_graphs_items - [IN/OUT] counter of updated * * graphs or graphs items * * * * Return value: SUCCEED - the templates graph and host graph are the same * * FAIL - otherwise * * * ***********************************************************************************/ static int process_template_graph(zbx_uint64_t host_graphid, zbx_hashset_t *host_graphs_main_data, zbx_hashset_t *host_graphs_items, graphs_items_entry_t *graphs_items_template_entry_found, zbx_graph_copy_t *template_graph_copy, int *upd_graphs_or_graphs_items) { int j, found_match = FAIL; zbx_graph_copy_t main_temp_t, *host_graph_copy_found; graphs_items_entry_t *graphs_items_host_entry_found, graphs_items_host_entry_temp_t; main_temp_t.graphid = host_graphid; if (NULL != (host_graph_copy_found = (zbx_graph_copy_t *)zbx_hashset_search(host_graphs_main_data, &main_temp_t))) { graphs_items_host_entry_temp_t.graphid = host_graph_copy_found->graphid; /* iterate over host graphs items */ if (NULL != (graphs_items_host_entry_found = (graphs_items_entry_t*)zbx_hashset_search( host_graphs_items, &graphs_items_host_entry_temp_t))) { int same_gitems = SUCCEED; if (graphs_items_template_entry_found->gitems.values_num != graphs_items_host_entry_found->gitems.values_num) { return FAIL; } for (j = 0; j < graphs_items_template_entry_found->gitems.values_num; j++) { if (0 != strcmp(graphs_items_template_entry_found->gitems.values[j]->key, graphs_items_host_entry_found->gitems.values[j]->key)) { same_gitems = FAIL; break; } } if (SUCCEED == same_gitems) found_match = SUCCEED; } } if (SUCCEED == found_match) { mark_updates_for_host_graph(template_graph_copy, host_graph_copy_found); mark_updates_for_host_graph_items(graphs_items_template_entry_found, graphs_items_host_entry_found); (*upd_graphs_or_graphs_items)++; } return found_match; } /************************************************************************************ * * * Description: 1) gets a list graph from the templates * * 2) gets a list of graphs_items for that graph * * 3) gets all the current host graphs (with names that match any of * * the templates graphs names) * * 4) iterates over template graphs * * 5) for each template graph finds the target host graphs with names * * that match the template graph * * 6) calls the process_template_graph() that compares both graphs and * * if they are the same marks the target host graph fields for * * update * * 7) if process_template_graph() returns they are not the same, the * * copy graph from the template is prepared for insert into a * * target host * * * * Parameters: template_graph_copy - [IN] main template graph data * * host_graphs_main_data - [IN] set of host graph copies * * with names that match the * * graphs from the templates * * host_graphs_names - [IN] helper set for faster search * * of graphs by names * * templates_graphs_items - [IN] helper set for the * * template_graph_copy * * host_graphs_items - [IN/OUT] helper set for the * * host_graphs_main_data * * upd_graphs_or_graphs_items - [IN/OUT] counter of updated graphs * * graphs_copies_insert - [OUT] prepared graphs for insert * * total_insert_gitems_count - [OUT] total number of total * * insert gitems_count * * * ***********************************************************************************/ static void process_graphs(zbx_graph_copy_t *template_graph_copy, zbx_hashset_t *host_graphs_main_data, zbx_hashset_t *host_graphs_names, zbx_hashset_t *templates_graphs_items, zbx_hashset_t *host_graphs_items, int *upd_graphs_or_graphs_items, zbx_vector_graphs_copies_t *graphs_copies_insert, int *total_insert_gitems_count) { int i; graphs_items_entry_t *graphs_items_template_entry_found, graphs_items_template_entry_temp; graphs_items_template_entry_temp.graphid = template_graph_copy->graphid; if (NULL != (graphs_items_template_entry_found = (graphs_items_entry_t*)zbx_hashset_search( templates_graphs_items, &graphs_items_template_entry_temp))) { int found_match = FAIL; zbx_graph_names_entry_t temp_t, *found; temp_t.name = template_graph_copy->name; if (NULL != (found = (zbx_graph_names_entry_t *)zbx_hashset_search(host_graphs_names, &temp_t))) { for (i = 0; i < found->graphids.values_num; i++) { if (SUCCEED == process_template_graph(found->graphids.values[i], host_graphs_main_data, host_graphs_items, graphs_items_template_entry_found, template_graph_copy, upd_graphs_or_graphs_items)) { found_match = SUCCEED; break; } } } if (FAIL == found_match) { /* not found any entries on host */ prepare_graph_for_insert(&graphs_items_template_entry_temp, graphs_copies_insert, template_graph_copy); *total_insert_gitems_count += graphs_items_template_entry_found->gitems.values_num; } } } static int update_graphs_items_updates(char **sql, size_t *sql_alloc, size_t *sql_offset, zbx_uint64_t graphid, int graph_flags, zbx_hashset_t *host_graphs_items) { int j, res = SUCCEED; graphs_items_entry_t *graphs_items_host_entry_found, graphs_items_host_entry_temp_t; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); graphs_items_host_entry_temp_t.graphid = graphid; if (NULL != (graphs_items_host_entry_found = (graphs_items_entry_t*)zbx_hashset_search(host_graphs_items, &graphs_items_host_entry_temp_t))) { for (j = 0; j < graphs_items_host_entry_found->gitems.values_num; j++) { const char *d2; graph_item_entry *host_items_entry; host_items_entry = graphs_items_host_entry_found->gitems.values[j]; d2 = ""; if (0 != (host_items_entry->update_flags & ZBX_FLAG_LINK_GRAPHITEM_UPDATE)) { zbx_audit_graph_update_json_update_gitem_create_entry(graphid, graph_flags, host_items_entry->gitemid); zbx_strcpy_alloc(sql, sql_alloc, sql_offset, "update graphs_items set "); if (0 != (host_items_entry->update_flags & ZBX_FLAG_LINK_GRAPHITEM_UPDATE_DRAWTYPE)) { zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "drawtype=%d", host_items_entry->drawtype_new); d2 = ","; zbx_audit_graph_update_json_update_gitem_update_drawtype(graphid, (int)graph_flags, host_items_entry->gitemid, host_items_entry->drawtype_orig, host_items_entry->drawtype_new); } if (0 != (host_items_entry->update_flags & ZBX_FLAG_LINK_GRAPHITEM_UPDATE_SORTORDER)) { zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssortorder=%d", d2, host_items_entry->sortorder_new); d2 = ","; zbx_audit_graph_update_json_update_gitem_update_sortorder(graphid, (int)graph_flags, host_items_entry->gitemid, host_items_entry->sortorder_orig, host_items_entry->sortorder_new); } if (0 != (host_items_entry->update_flags & ZBX_FLAG_LINK_GRAPHITEM_UPDATE_COLOR)) { char *color_esc = DBdyn_escape_string(host_items_entry->color_new); zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%scolor='%s'", d2, color_esc); zbx_free(color_esc); d2 = ","; zbx_audit_graph_update_json_update_gitem_update_color(graphid, (int)graph_flags, host_items_entry->gitemid, host_items_entry->color_orig, host_items_entry->color_new); } if (0 != (host_items_entry->update_flags & ZBX_FLAG_LINK_GRAPHITEM_UPDATE_YAXISSIDE)) { zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%syaxisside=%d", d2, host_items_entry->yaxisside_new); d2 = ","; zbx_audit_graph_update_json_update_gitem_update_yaxisside(graphid, (int)graph_flags, host_items_entry->gitemid, host_items_entry->yaxisside_orig, host_items_entry->yaxisside_new); } if (0 != (host_items_entry->update_flags & ZBX_FLAG_LINK_GRAPHITEM_UPDATE_CALC_FNC)) { zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%scalc_fnc=%d", d2, host_items_entry->calc_fnc_new); d2 = ","; zbx_audit_graph_update_json_update_gitem_update_calc_fnc(graphid, (int)graph_flags, host_items_entry->gitemid, host_items_entry->calc_fnc_orig, host_items_entry->calc_fnc_new); } if (0 != (host_items_entry->update_flags & ZBX_FLAG_LINK_GRAPHITEM_UPDATE_TYPE)) { zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%stype=%d", d2, host_items_entry->type_new); zbx_audit_graph_update_json_update_gitem_update_type(graphid, (int)graph_flags, host_items_entry->gitemid, host_items_entry->type_orig, host_items_entry->type_new); } zbx_snprintf_alloc(sql, sql_alloc, sql_offset, " where gitemid=" ZBX_FS_UI64 ";\n", host_items_entry->gitemid); if (SUCCEED != (res = DBexecute_overflowed_sql(sql, sql_alloc, sql_offset))) goto out; } } } out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(res)); return res; } static int execute_graphs_updates(zbx_hashset_t *host_graphs_main_data, zbx_hashset_t *host_graphs_items) { int res = SUCCEED; const char *d; char *sql = NULL, *sql2 = NULL; size_t sql_alloc = 512, sql_offset = 0, sql_alloc2 = 512, sql_offset2 = 0; zbx_hashset_iter_t iter1; zbx_graph_copy_t *found; zbx_hashset_iter_reset(host_graphs_main_data, &iter1); DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset); DBbegin_multiple_update(&sql2, &sql_alloc2, &sql_offset2); while (SUCCEED == res && NULL != (found = (zbx_graph_copy_t *)zbx_hashset_iter_next(&iter1))) { d = ""; zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update graphs set "); zbx_audit_graph_create_entry(AUDIT_ACTION_UPDATE, found->graphid, found->name_orig, (int)(found->flags)); if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_NAME)) { char *name_esc = DBdyn_escape_string(found->name); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "name='%s'", name_esc); zbx_free(name_esc); d = ","; zbx_audit_graph_update_json_update_name(found->graphid, (int)(found->flags), found->name_orig, found->name); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_WIDTH)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%swidth=%d", d, found->width); d = ","; zbx_audit_graph_update_json_update_width(found->graphid, (int)(found->flags), found->width_orig, found->width); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_HEIGHT)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sheight=%d", d, found->height); d = ","; zbx_audit_graph_update_json_update_height(found->graphid, (int)(found->flags), found->height_orig, found->height); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_YAXISMIN)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%syaxismin=" ZBX_FS_DBL64_SQL, d, found->yaxismin); d = ","; zbx_audit_graph_update_json_update_yaxismin(found->graphid, (int)(found->flags), found->yaxismin_orig, found->yaxismin); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_YAXISMAX)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%syaxismax=" ZBX_FS_DBL64_SQL, d, found->yaxismax); d = ","; zbx_audit_graph_update_json_update_yaxismax(found->graphid, (int)(found->flags), found->yaxismax_orig, found->yaxismax); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_SHOW_WORK_PERIOD)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sshow_work_period=%d", d, (int)found->show_work_period); d = ","; zbx_audit_graph_update_json_update_show_work_period(found->graphid, (int)(found->flags), found->show_work_period_orig, found->show_work_period); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_SHOW_TRIGGERS)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sshow_triggers=%d", d, (int)found->show_triggers); d = ","; zbx_audit_graph_update_json_update_show_triggers(found->graphid, (int)(found->flags), found->show_triggers_orig, found->show_triggers); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_GRAPHTYPE)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sgraphtype=%d", d, (int)found->graphtype); d = ","; zbx_audit_graph_update_json_update_graphtype(found->graphid, (int)(found->flags), (int)found->graphtype_orig, (int)found->graphtype); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_SHOW_LEGEND)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sshow_legend=%d", d, (int)found->show_legend); d = ","; zbx_audit_graph_update_json_update_show_legend(found->graphid, (int)(found->flags), (int)found->show_legend_orig, (int)found->show_legend); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_SHOW_3D)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sshow_3d=%d", d, (int)found->show_3d); d = ","; zbx_audit_graph_update_json_update_show_3d(found->graphid, (int)(found->flags), (int)found->show_3d_orig, (int)found->show_3d); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_PERCENT_LEFT)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%spercent_left=" ZBX_FS_DBL64_SQL, d, found->percent_left); d = ","; zbx_audit_graph_update_json_update_percent_left(found->graphid, (int)(found->flags), found->percent_left_orig, found->percent_left); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_PERCENT_RIGHT)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%spercent_right=" ZBX_FS_DBL64_SQL, d, found->percent_right); d = ","; zbx_audit_graph_update_json_update_percent_right(found->graphid, (int)(found->flags), found->percent_right_orig, found->percent_right); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_YMIN_TYPE)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%symin_type=%d", d, (int)found->ymin_type); d = ","; zbx_audit_graph_update_json_update_ymin_type(found->graphid, (int)(found->flags), found->ymin_type_orig, found->ymin_type); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_YMAX_TYPE)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%symax_type=%d", d, (int)found->ymax_type); d = ","; zbx_audit_graph_update_json_update_ymax_type(found->graphid, (int)(found->flags), found->ymax_type_orig, found->ymax_type); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_YMIN_ITEMID)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%symin_itemid=%s", d, DBsql_id_ins(found->ymin_itemid)); d = ","; zbx_audit_graph_update_json_update_ymin_itemid(found->graphid, (int)(found->flags), found->ymin_itemid_orig, found->ymin_itemid); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_YMAX_ITEMID)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%symax_itemid=%s", d, DBsql_id_ins(found->ymax_itemid)); d = ","; zbx_audit_graph_update_json_update_ymax_itemid(found->graphid, (int)(found->flags), found->ymax_itemid_orig, found->ymax_itemid); } if (0 != (found->update_flags & ZBX_FLAG_LINK_GRAPH_UPDATE_DISCOVER)) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sdiscover=%d", d, (int)found->discover); d = ","; zbx_audit_graph_update_json_update_discover(found->graphid, (int)(found->flags), found->discover_orig, found->discover); } zbx_audit_graph_update_json_update_templateid(found->graphid, (int)(found->flags), found->templateid_orig, found->templateid); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%stemplateid=" ZBX_FS_UI64, d, found->templateid); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where graphid=" ZBX_FS_UI64 ";\n", found->graphid); res = DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset); if (SUCCEED == res) { res = update_graphs_items_updates(&sql2, &sql_alloc2, &sql_offset2, found->graphid, found->flags, host_graphs_items); } } DBend_multiple_update(&sql, &sql_alloc, &sql_offset); if (SUCCEED == res && 16 < sql_offset && ZBX_DB_OK > DBexecute("%s", sql)) { zabbix_log(LOG_LEVEL_WARNING, "failed to execute graphs updates"); res = FAIL; } zbx_free(sql); if (SUCCEED == res) { DBend_multiple_update(&sql2, &sql_alloc2, &sql_offset2); if (16 < sql_offset2 && (ZBX_DB_OK > DBexecute("%s", sql2))) { zabbix_log(LOG_LEVEL_WARNING, "failed to execute graphs items updates"); res = FAIL; } } zbx_free(sql2); return res; } static int execute_graphs_inserts(zbx_vector_graphs_copies_t *graphs_copies_insert, int *total_insert_gitems_count, zbx_hashset_t *templates_graphs_items) { int i, j, res; zbx_db_insert_t db_insert, db_insert_graphs_items; zbx_uint64_t graphid, graphs_itemsid; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); zbx_db_insert_prepare(&db_insert, "graphs", "graphid", "name", "width", "height", "yaxismin", "yaxismax", "templateid", "show_work_period", "show_triggers", "graphtype", "show_legend", "show_3d", "percent_left", "percent_right", "ymin_type", "ymax_type", "ymin_itemid", "ymax_itemid", "flags", "discover", NULL); zbx_db_insert_prepare(&db_insert_graphs_items, "graphs_items", "gitemid", "graphid", "itemid", "drawtype", "sortorder", "color", "yaxisside", "calc_fnc", "type", NULL); graphid = DBget_maxid_num("graphs", graphs_copies_insert->values_num); graphs_itemsid = DBget_maxid_num("graphs_items", *total_insert_gitems_count); for (i = 0; i < graphs_copies_insert->values_num; i++) { char *graph_copy_name; zbx_graph_copy_t *graph_copy = graphs_copies_insert->values[i]; graphs_items_entry_t *graphs_items_template_entry_found, graphs_items_template_entry_temp_t; graph_copy_name = DBdyn_escape_string(graph_copy->name); zbx_db_insert_add_values(&db_insert, graphid, graph_copy_name, graph_copy->width, graph_copy->height, graph_copy->yaxismin, graph_copy->yaxismax, graph_copy->templateid, (int)graph_copy->show_work_period, (int)(graph_copy->show_triggers), (int)(graph_copy->graphtype), (int)(graph_copy->show_legend), (int)(graph_copy->show_3d), graph_copy->percent_left, graph_copy->percent_right, (int)(graph_copy->ymin_type), (int)(graph_copy->ymax_type), graph_copy->ymin_itemid, graph_copy->ymax_itemid, (int)(graph_copy->flags), (int)(graph_copy->discover)); zbx_audit_graph_create_entry(AUDIT_ACTION_ADD, graphid, graph_copy_name, (int)(graph_copy->flags)); zbx_audit_graph_update_json_add_data(graphid, graph_copy_name, graph_copy->width, graph_copy->height, graph_copy->yaxismin, graph_copy->yaxismax, graph_copy->templateid, (int)graph_copy->show_work_period, (int)(graph_copy->show_triggers), (int)(graph_copy->graphtype), (int)(graph_copy->show_legend), (int)(graph_copy->show_3d), graph_copy->percent_left, graph_copy->percent_right, (int)(graph_copy->ymin_type), (int)(graph_copy->ymax_type), graph_copy->ymin_itemid, graph_copy->ymax_itemid, (int)(graph_copy->flags), (int)(graph_copy->discover)); zbx_free(graph_copy_name); graphs_items_template_entry_temp_t.graphid = graph_copy->templateid; if (NULL != (graphs_items_template_entry_found = (graphs_items_entry_t*)zbx_hashset_search( templates_graphs_items, &graphs_items_template_entry_temp_t))) { for (j = 0; j < graphs_items_template_entry_found->gitems.values_num; j++) { char *color_orig_esc; graph_item_entry *template_entry; template_entry = graphs_items_template_entry_found->gitems.values[j]; color_orig_esc = DBdyn_escape_string(template_entry->color_orig); zbx_db_insert_add_values(&db_insert_graphs_items, graphs_itemsid, graphid, template_entry->itemid, template_entry->drawtype_orig, template_entry->sortorder_orig, color_orig_esc, template_entry->yaxisside_orig, template_entry->calc_fnc_orig, template_entry->type_orig); zbx_free(color_orig_esc); zbx_audit_graph_update_json_add_gitems(graphid, (int)(graph_copy->flags), graphs_itemsid, template_entry->drawtype_orig, template_entry->sortorder_orig, template_entry->color_orig, template_entry->yaxisside_orig, template_entry->calc_fnc_orig, template_entry->type_orig, template_entry->itemid); graphs_itemsid++; } } graphid++; } res = zbx_db_insert_execute(&db_insert); zbx_db_insert_clean(&db_insert); if (SUCCEED == res) res = zbx_db_insert_execute(&db_insert_graphs_items); zbx_db_insert_clean(&db_insert_graphs_items); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(res)); return res; } /****************************************************************************** * * * Purpose: copy graphs from template to host * * * * Parameters: hostid - [IN] host identifier from database * * templateids - [IN] array of template IDs * * * * Return value: SUCCEED - db operations successful * * FAIL - otherwise * * * ******************************************************************************/ int DBcopy_template_graphs(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids) { int i, upd_graphs_or_graphs_items = 0, total_insert_gitems_count = 0, res = SUCCEED; zbx_vector_graphs_copies_t graphs_copies_templates, graphs_copies_insert; zbx_hashset_t host_graphs_main_data, templates_graphs_items, host_graphs_items, host_graphs_names; zbx_vector_str_t templates_graphs_names; zbx_vector_uint64_t templates_graphs_ids, host_graphs_ids; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); zbx_vector_str_create(&templates_graphs_names); zbx_vector_uint64_create(&templates_graphs_ids); zbx_vector_uint64_create(&host_graphs_ids); #define TRIGGER_GITEMS_HASHSET_DEF_SIZE 100 zbx_hashset_create(&templates_graphs_items, TRIGGER_GITEMS_HASHSET_DEF_SIZE, graphs_items_hash_func, graphs_items_compare_func); zbx_hashset_create(&host_graphs_items, TRIGGER_GITEMS_HASHSET_DEF_SIZE, graphs_items_hash_func, graphs_items_compare_func); zbx_hashset_create(&host_graphs_main_data, TRIGGER_GITEMS_HASHSET_DEF_SIZE, graphs_copies_hash_func, graphs_copies_compare_func); zbx_hashset_create(&host_graphs_names, TRIGGER_GITEMS_HASHSET_DEF_SIZE, zbx_graphs_names_hash_func, zbx_graphs_names_compare_func); #undef TRIGGER_GITEMS_HASHSET_DEF_SIZE zbx_vector_graphs_copies_create(&graphs_copies_templates); zbx_vector_graphs_copies_create(&graphs_copies_insert); res = get_templates_graphs_data(templateids, &graphs_copies_templates, &templates_graphs_ids, &templates_graphs_names); if (0 == templates_graphs_names.values_num) goto end; if (SUCCEED == res) res = get_graphs_items(hostid, &templates_graphs_ids, &templates_graphs_items); if (SUCCEED == res) res = update_same_itemids(hostid, &graphs_copies_templates); if (SUCCEED == res) { res = get_target_host_main_data(hostid, &templates_graphs_names, &host_graphs_ids, &host_graphs_main_data, &host_graphs_names); } if (SUCCEED == res) res = get_graphs_items(0, &host_graphs_ids, &host_graphs_items); if (SUCCEED == res) { for (i = 0; i < graphs_copies_templates.values_num; i++) { process_graphs(graphs_copies_templates.values[i], &host_graphs_main_data, &host_graphs_names, &templates_graphs_items, &host_graphs_items, &upd_graphs_or_graphs_items, &graphs_copies_insert, &total_insert_gitems_count); } if (0 < upd_graphs_or_graphs_items) res = execute_graphs_updates(&host_graphs_main_data, &host_graphs_items); } if (SUCCEED == res && 0 < graphs_copies_insert.values_num) { res = execute_graphs_inserts(&graphs_copies_insert, &total_insert_gitems_count, &templates_graphs_items); } end: zbx_vector_str_clear_ext(&templates_graphs_names, zbx_str_free); zbx_vector_str_destroy(&templates_graphs_names); zbx_vector_uint64_destroy(&templates_graphs_ids); zbx_vector_uint64_destroy(&host_graphs_ids); zbx_vector_graphs_copies_clear_ext(&graphs_copies_templates, graphs_copies_clean_vec_entry); zbx_vector_graphs_copies_destroy(&graphs_copies_templates); zbx_vector_graphs_copies_clear_ext(&graphs_copies_insert, graphs_copies_clean_vec_entry); zbx_vector_graphs_copies_destroy(&graphs_copies_insert); graphs_names_clean(&host_graphs_names); graphs_copies_clean(&host_graphs_main_data); graphs_items_clean(&templates_graphs_items); graphs_items_clean(&host_graphs_items); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(res)); return res; }