You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
831 lines
29 KiB
831 lines
29 KiB
/*
|
|
** Zabbix
|
|
** Copyright (C) 2001-2023 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 "zbxmocktest.h"
|
|
#include "zbxmockdata.h"
|
|
#include "zbxmockassert.h"
|
|
#include "zbxmockutil.h"
|
|
|
|
#include "zbxnum.h"
|
|
#include "zbxalgo.h"
|
|
#include "zbxcacheconfig/user_macro.h"
|
|
#include "um_cache_mock.h"
|
|
#include "zbxshmem.h"
|
|
|
|
char *um_mock_format_macro(const char *name, const char *context);
|
|
void *__wrap___zbx_shmem_malloc(const char *file, int line, zbx_shmem_info_t *info, const void *old, size_t size);
|
|
void *__wrap___zbx_shmem_realloc(const char *file, int line, zbx_shmem_info_t *info, void *old, size_t size);
|
|
void __wrap___zbx_shmem_free(const char *file, int line, zbx_shmem_info_t *info, void *ptr);
|
|
|
|
ZBX_PTR_VECTOR_IMPL(um_mock_macro, zbx_um_mock_macro_t *)
|
|
|
|
ZBX_PTR_VECTOR_DECL(um_mock_host, zbx_um_mock_host_t *)
|
|
ZBX_PTR_VECTOR_IMPL(um_mock_host, zbx_um_mock_host_t *)
|
|
|
|
ZBX_PTR_VECTOR_IMPL(um_mock_kv, zbx_um_mock_kv_t *)
|
|
ZBX_PTR_VECTOR_IMPL(um_mock_kvset, zbx_um_mock_kvset_t *)
|
|
|
|
static void um_mock_macro_free(zbx_um_mock_macro_t *macro)
|
|
{
|
|
zbx_free(macro->macro);
|
|
zbx_free(macro->value);
|
|
zbx_free(macro);
|
|
}
|
|
|
|
static void um_mock_macro_init(zbx_um_mock_macro_t *macro, zbx_uint64_t hostid, zbx_mock_handle_t hmacro)
|
|
{
|
|
zbx_mock_handle_t handle;
|
|
const char *str;
|
|
zbx_mock_error_t err;
|
|
|
|
macro->macroid = zbx_mock_get_object_member_uint64(hmacro, "macroid");
|
|
macro->hostid = hostid;
|
|
macro->macro = zbx_strdup(NULL, zbx_mock_get_object_member_string(hmacro, "macro"));
|
|
|
|
if (ZBX_MOCK_SUCCESS == zbx_mock_object_member(hmacro, "value", &handle))
|
|
{
|
|
if (ZBX_MOCK_SUCCESS != (err = zbx_mock_string(handle, &str)))
|
|
fail_msg("Cannot read macro value: %s", zbx_mock_error_string(err));
|
|
|
|
macro->value = zbx_strdup(NULL, str);
|
|
}
|
|
else
|
|
macro->value = NULL;
|
|
|
|
if (ZBX_MOCK_SUCCESS == zbx_mock_object_member(hmacro, "type", &handle))
|
|
{
|
|
if (ZBX_MOCK_SUCCESS != (err = zbx_mock_string(handle, &str)))
|
|
fail_msg("Cannot read macro type: %s", zbx_mock_error_string(err));
|
|
|
|
if (0 == strcmp(str, "ZBX_MACRO_VALUE_TEXT"))
|
|
macro->type = ZBX_MACRO_VALUE_TEXT;
|
|
else if (0 == strcmp(str, "ZBX_MACRO_VALUE_SECRET"))
|
|
macro->type = ZBX_MACRO_VALUE_SECRET;
|
|
else if (0 == strcmp(str, "ZBX_MACRO_VALUE_VAULT"))
|
|
macro->type = ZBX_MACRO_VALUE_VAULT;
|
|
else
|
|
fail_msg("unknown macro type '%s'", str);
|
|
}
|
|
else
|
|
macro->type = ZBX_MACRO_VALUE_TEXT;
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: initialize mock user macro host from test data *
|
|
* *
|
|
*********************************************************************************/
|
|
static void um_mock_host_init(zbx_um_mock_host_t *host, zbx_mock_handle_t handle)
|
|
{
|
|
zbx_mock_handle_t hmacros, hmacro, htemplates, htemplate;
|
|
zbx_mock_error_t err;
|
|
|
|
host->hostid = zbx_mock_get_object_member_uint64(handle, "hostid");
|
|
zbx_vector_um_mock_macro_create(&host->macros);
|
|
zbx_vector_uint64_create(&host->templateids);
|
|
|
|
hmacros = zbx_mock_get_object_member_handle(handle, "macros");
|
|
while (ZBX_MOCK_END_OF_VECTOR != (err = (zbx_mock_vector_element(hmacros, &hmacro))))
|
|
{
|
|
zbx_um_mock_macro_t *macro;
|
|
|
|
macro = (zbx_um_mock_macro_t *)zbx_malloc(NULL, sizeof(zbx_um_mock_macro_t));
|
|
um_mock_macro_init(macro, host->hostid, hmacro);
|
|
zbx_vector_um_mock_macro_append(&host->macros, macro);
|
|
}
|
|
|
|
htemplates = zbx_mock_get_object_member_handle(handle, "templates");
|
|
while (ZBX_MOCK_END_OF_VECTOR != (err = (zbx_mock_vector_element(htemplates, &htemplate))))
|
|
{
|
|
const char *template;
|
|
zbx_uint64_t templateid;
|
|
|
|
if (ZBX_MOCK_SUCCESS != (err = zbx_mock_string(htemplate, &template)))
|
|
fail_msg("Cannot read templateid: %s", zbx_mock_error_string(err));
|
|
|
|
if (SUCCEED != zbx_is_uint64(template, &templateid))
|
|
fail_msg("Invalid templateid: %s", template);
|
|
|
|
zbx_vector_uint64_append(&host->templateids, templateid);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: initialize mock kv path *
|
|
* *
|
|
*********************************************************************************/
|
|
static void um_mock_kvset_init(zbx_um_mock_kvset_t *kvset, zbx_mock_handle_t handle)
|
|
{
|
|
zbx_mock_handle_t hvalues, hvalue;
|
|
zbx_mock_error_t err;
|
|
|
|
kvset->path = zbx_mock_get_object_member_string(handle, "path");
|
|
zbx_vector_um_mock_kv_create(&kvset->kvs);
|
|
|
|
hvalues = zbx_mock_get_object_member_handle(handle, "values");
|
|
while (ZBX_MOCK_END_OF_VECTOR != (err = (zbx_mock_vector_element(hvalues, &hvalue))))
|
|
{
|
|
zbx_um_mock_kv_t *kv;
|
|
|
|
kv = (zbx_um_mock_kv_t *)zbx_malloc(NULL, sizeof(zbx_um_mock_kv_t));
|
|
kv->key = zbx_mock_get_object_member_string(hvalue, "key");
|
|
kv->value = zbx_mock_get_object_member_string(hvalue, "value");
|
|
zbx_vector_um_mock_kv_append(&kvset->kvs, kv);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: free mock mock kv path *
|
|
* *
|
|
*********************************************************************************/
|
|
static void um_mock_kvset_free(zbx_um_mock_kvset_t *kvset)
|
|
{
|
|
zbx_vector_um_mock_kv_clear_ext(&kvset->kvs, (zbx_um_mock_kv_free_func_t)zbx_ptr_free);
|
|
zbx_vector_um_mock_kv_destroy(&kvset->kvs);
|
|
zbx_free(kvset);
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: initialize mock user macro cache from test data *
|
|
* *
|
|
*********************************************************************************/
|
|
void um_mock_cache_init(zbx_um_mock_cache_t *cache, zbx_mock_handle_t handle)
|
|
{
|
|
zbx_mock_handle_t hhost, hhosts, hvault, hset;
|
|
zbx_mock_error_t err;
|
|
|
|
zbx_hashset_create(&cache->hosts, 10, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
|
|
zbx_vector_um_mock_kvset_create(&cache->kvsets);
|
|
|
|
if (-1 == handle)
|
|
return;
|
|
|
|
hhosts = zbx_mock_get_object_member_handle(handle, "hosts");
|
|
|
|
while (ZBX_MOCK_END_OF_VECTOR != (err = (zbx_mock_vector_element(hhosts, &hhost))))
|
|
{
|
|
zbx_um_mock_host_t host_local;
|
|
|
|
um_mock_host_init(&host_local, hhost);
|
|
zbx_hashset_insert(&cache->hosts, &host_local, sizeof(host_local));
|
|
}
|
|
|
|
hvault = zbx_mock_get_object_member_handle(handle, "vault");
|
|
|
|
while (ZBX_MOCK_END_OF_VECTOR != (err = (zbx_mock_vector_element(hvault, &hset))))
|
|
{
|
|
zbx_um_mock_kvset_t *kvset;
|
|
|
|
kvset = (zbx_um_mock_kvset_t *)zbx_malloc(NULL, sizeof(zbx_um_mock_kvset_t));
|
|
um_mock_kvset_init(kvset, hset);
|
|
zbx_vector_um_mock_kvset_append(&cache->kvsets, kvset);
|
|
}
|
|
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: restore database macro format from cached macro name/context *
|
|
* *
|
|
* Comments: In database user macro has format '{$NAME:context}' (:context being *
|
|
* optional), but in cache macro name and context are stored separately*
|
|
* - '{$NAME}' and 'context' (context can be NULL). This function takes*
|
|
* the macro name and context from cache and assembles in original *
|
|
* format (note that spacing/quotes around the context might be lost). *
|
|
* *
|
|
* *
|
|
*********************************************************************************/
|
|
char *um_mock_format_macro(const char *name, const char *context)
|
|
{
|
|
char *context_esc, *macro = NULL;
|
|
size_t macro_alloc = 0, macro_offset = 0;
|
|
|
|
zbx_strcpy_alloc(¯o, ¯o_alloc, ¯o_offset, name);
|
|
|
|
if (NULL != context)
|
|
{
|
|
macro_offset--;
|
|
zbx_chrcpy_alloc(¯o, ¯o_alloc, ¯o_offset, ':');
|
|
|
|
if (zbx_get_escape_string_len(context, "\"") != strlen(context))
|
|
{
|
|
context_esc = zbx_dyn_escape_string(context, "\"");
|
|
zbx_snprintf_alloc(¯o, ¯o_alloc, ¯o_offset, "\"%s\"", context_esc);
|
|
zbx_free(context_esc);
|
|
}
|
|
else
|
|
zbx_strcpy_alloc(¯o, ¯o_alloc, ¯o_offset, context);
|
|
|
|
zbx_chrcpy_alloc(¯o, ¯o_alloc, ¯o_offset, '}');
|
|
}
|
|
|
|
return macro;
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: initialize mock user macro cache from cache *
|
|
* *
|
|
*********************************************************************************/
|
|
void um_mock_cache_init_from_config(zbx_um_mock_cache_t *cache, zbx_um_cache_t *cfg)
|
|
{
|
|
zbx_hashset_iter_t iter;
|
|
zbx_um_host_t **phost;
|
|
|
|
zbx_hashset_create(&cache->hosts, (size_t)cfg->hosts.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
|
|
ZBX_DEFAULT_UINT64_COMPARE_FUNC);
|
|
|
|
zbx_vector_um_mock_kvset_create(&cache->kvsets);
|
|
|
|
zbx_hashset_iter_reset(&cfg->hosts, &iter);
|
|
while (NULL != (phost = (zbx_um_host_t **)zbx_hashset_iter_next(&iter)))
|
|
{
|
|
zbx_um_mock_host_t host_local;
|
|
int i;
|
|
|
|
host_local.hostid = (*phost)->hostid;
|
|
zbx_vector_um_mock_macro_create(&host_local.macros);
|
|
zbx_vector_uint64_create(&host_local.templateids);
|
|
zbx_vector_uint64_append_array(&host_local.templateids, (*phost)->templateids.values,
|
|
(*phost)->templateids.values_num);
|
|
|
|
for (i = 0; i < (*phost)->macros.values_num; i++)
|
|
{
|
|
zbx_um_mock_macro_t *macro;
|
|
|
|
macro = (zbx_um_mock_macro_t *)zbx_malloc(NULL, sizeof(zbx_um_mock_macro_t));
|
|
macro->hostid = (*phost)->hostid;
|
|
macro->macroid = (*phost)->macros.values[i]->macroid;
|
|
macro->macro = um_mock_format_macro((*phost)->macros.values[i]->name,
|
|
(*phost)->macros.values[i]->context);
|
|
macro->value = zbx_strdup(NULL, (*phost)->macros.values[i]->value);
|
|
macro->type = (*phost)->macros.values[i]->type;
|
|
|
|
zbx_vector_um_mock_macro_append(&host_local.macros, macro);
|
|
}
|
|
|
|
zbx_hashset_insert(&cache->hosts, &host_local, sizeof(host_local));
|
|
}
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: frees resources used by mock macro cache *
|
|
* *
|
|
*********************************************************************************/
|
|
void um_mock_cache_clear(zbx_um_mock_cache_t *cache)
|
|
{
|
|
zbx_hashset_iter_t iter;
|
|
zbx_um_mock_host_t *host;
|
|
|
|
zbx_hashset_iter_reset(&cache->hosts, &iter);
|
|
while (NULL != (host = (zbx_um_mock_host_t *)zbx_hashset_iter_next(&iter)))
|
|
{
|
|
zbx_vector_um_mock_macro_clear_ext(&host->macros, um_mock_macro_free);
|
|
zbx_vector_um_mock_macro_destroy(&host->macros);
|
|
zbx_vector_uint64_destroy(&host->templateids);
|
|
}
|
|
zbx_hashset_destroy(&cache->hosts);
|
|
|
|
zbx_vector_um_mock_kvset_clear_ext(&cache->kvsets, um_mock_kvset_free);
|
|
zbx_vector_um_mock_kvset_destroy(&cache->kvsets);
|
|
}
|
|
|
|
static int um_mock_compare_macros_by_id(const void *d1, const void *d2)
|
|
{
|
|
const zbx_um_mock_macro_t *m1 = *(const zbx_um_mock_macro_t * const *)d1;
|
|
const zbx_um_mock_macro_t *m2 = *(const zbx_um_mock_macro_t * const *)d2;
|
|
|
|
ZBX_RETURN_IF_NOT_EQUAL(m1->macroid, m2->macroid);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: compare macros by name, context and value *
|
|
* *
|
|
* Comments: Macros are parsed and the name/context are compared separately to *
|
|
* handle any spacing/quoting loss because of formatting. *
|
|
* *
|
|
*********************************************************************************/
|
|
static int um_mock_compare_macros_by_content(const zbx_um_mock_macro_t *m1, const zbx_um_mock_macro_t *m2)
|
|
{
|
|
int ret;
|
|
char *name1 = NULL, *name2 = NULL, *context1 = NULL, *context2 = NULL;
|
|
unsigned char context_op1, context_op2;
|
|
|
|
if (SUCCEED != zbx_user_macro_parse_dyn(m1->macro, &name1, &context1, NULL, &context_op1))
|
|
{
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (SUCCEED != zbx_user_macro_parse_dyn(m2->macro, &name2, &context2, NULL, &context_op2))
|
|
{
|
|
ret = 1;
|
|
goto out;
|
|
}
|
|
|
|
if (0 != (ret = strcmp(name1, name2)))
|
|
goto out;
|
|
|
|
if (0 != (ret = zbx_strcmp_null(context1, context2)))
|
|
goto out;
|
|
|
|
if (context_op1 > context_op2)
|
|
{
|
|
ret = 1;
|
|
goto out;
|
|
}
|
|
|
|
if (context_op1 < context_op2)
|
|
{
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (0 != (ret = (int)m1->type - (int)m2->type))
|
|
goto out;
|
|
|
|
ret = strcmp(m1->value, m2->value);
|
|
out:
|
|
zbx_free(name1);
|
|
zbx_free(name2);
|
|
zbx_free(context1);
|
|
zbx_free(context2);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void um_mock_dbsync_update_stats(zbx_dbsync_t *sync, unsigned char tag)
|
|
{
|
|
switch (tag)
|
|
{
|
|
case ZBX_DBSYNC_ROW_ADD:
|
|
sync->add_num++;
|
|
break;
|
|
case ZBX_DBSYNC_ROW_UPDATE:
|
|
sync->update_num++;
|
|
break;
|
|
case ZBX_DBSYNC_ROW_REMOVE:
|
|
sync->remove_num++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: add macro as dbsync row with the specified dbsync operation tag *
|
|
* *
|
|
* Comments: Global macros have 0 hostid and it will be omitted from dbsync row. *
|
|
* *
|
|
*********************************************************************************/
|
|
static void um_mock_dbsync_add_macro(zbx_dbsync_t *sync, unsigned char tag, const zbx_um_mock_macro_t *macro)
|
|
{
|
|
zbx_dbsync_row_t *row;
|
|
char **prow;
|
|
|
|
if (0 == sync->columns_num)
|
|
sync->columns_num = (0 == macro->hostid ? 4 : 5);
|
|
|
|
row = (zbx_dbsync_row_t *)zbx_malloc(NULL, sizeof(zbx_dbsync_row_t));
|
|
row->rowid = macro->macroid;
|
|
row->tag = tag;
|
|
|
|
prow = row->row = (char **)zbx_malloc(NULL, sizeof(char *) * (size_t)sync->columns_num);
|
|
*prow++ = zbx_dsprintf(NULL, ZBX_FS_UI64, macro->macroid);
|
|
if (0 != macro->hostid)
|
|
*prow++ = zbx_dsprintf(NULL, ZBX_FS_UI64, macro->hostid);
|
|
*prow++ = zbx_strdup(NULL, macro->macro);
|
|
*prow++ = zbx_strdup(NULL, macro->value);
|
|
*prow++ = zbx_dsprintf(NULL, "%u", macro->type);
|
|
|
|
zbx_vector_ptr_append(&sync->rows, row);
|
|
|
|
um_mock_dbsync_update_stats(sync, tag);
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: add hosts_templates dbsync row *
|
|
* *
|
|
*********************************************************************************/
|
|
static void um_mock_dbsync_add_htmpl(zbx_dbsync_t *sync, unsigned char tag, zbx_uint64_t hostid,
|
|
zbx_uint64_t templateid)
|
|
{
|
|
zbx_dbsync_row_t *row;
|
|
|
|
if (0 == sync->columns_num)
|
|
sync->columns_num = 2;
|
|
|
|
row = (zbx_dbsync_row_t *)zbx_malloc(NULL, sizeof(zbx_dbsync_row_t));
|
|
row->rowid = 0;
|
|
row->tag = tag;
|
|
|
|
row->row = (char **)zbx_malloc(NULL, sizeof(char *) * (size_t)sync->columns_num);
|
|
row->row[0] = zbx_dsprintf(NULL, ZBX_FS_UI64, hostid);
|
|
row->row[1] = zbx_dsprintf(NULL, ZBX_FS_UI64, templateid);
|
|
|
|
zbx_vector_ptr_append(&sync->rows, row);
|
|
|
|
um_mock_dbsync_update_stats(sync, tag);
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: compare macros on two hosts and: *
|
|
* 1) add new/updated macros to the sync object *
|
|
* 2) remove macros by adding them into the del_macros vector *
|
|
* *
|
|
*********************************************************************************/
|
|
static void um_mock_host_macro_diff(const zbx_um_mock_host_t *host1, const zbx_um_mock_host_t *host2,
|
|
zbx_dbsync_t *sync, zbx_vector_um_mock_macro_t *del_macros)
|
|
{
|
|
zbx_vector_um_mock_macro_t macros;
|
|
int i, j;
|
|
|
|
zbx_vector_um_mock_macro_create(¯os);
|
|
|
|
if (NULL != host2)
|
|
zbx_vector_um_mock_macro_append_array(¯os, host2->macros.values, host2->macros.values_num);
|
|
|
|
if (NULL != host1)
|
|
{
|
|
for (i = 0; i < host1->macros.values_num; i++)
|
|
{
|
|
if (FAIL != (j = zbx_vector_um_mock_macro_search(¯os, host1->macros.values[i],
|
|
um_mock_compare_macros_by_id)))
|
|
{
|
|
if (0 != um_mock_compare_macros_by_content(host1->macros.values[i], macros.values[j]))
|
|
um_mock_dbsync_add_macro(sync, ZBX_DBSYNC_ROW_UPDATE, macros.values[j]);
|
|
|
|
zbx_vector_um_mock_macro_remove_noorder(¯os, j);
|
|
}
|
|
else
|
|
zbx_vector_um_mock_macro_append(del_macros, host1->macros.values[i]);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < macros.values_num; i++)
|
|
um_mock_dbsync_add_macro(sync, ZBX_DBSYNC_ROW_ADD, macros.values[i]);
|
|
|
|
zbx_vector_um_mock_macro_destroy(¯os);
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: compare template ids on two hosts and add new/updated ids to sync and*
|
|
* removed ids to del_templateids vector *
|
|
* *
|
|
*********************************************************************************/
|
|
static void um_mock_host_template_diff(const zbx_um_mock_host_t *host1, const zbx_um_mock_host_t *host2,
|
|
zbx_dbsync_t *sync, zbx_vector_uint64_pair_t *del_templateids)
|
|
{
|
|
zbx_vector_uint64_t templateids;
|
|
int i, j;
|
|
zbx_uint64_pair_t pair;
|
|
|
|
zbx_vector_uint64_create(&templateids);
|
|
|
|
if (NULL != host2)
|
|
zbx_vector_uint64_append_array(&templateids, host2->templateids.values, host2->templateids.values_num);
|
|
|
|
if (NULL != host1)
|
|
{
|
|
for (i = 0; i < host1->templateids.values_num; i++)
|
|
{
|
|
if (FAIL != (j = zbx_vector_uint64_search(&templateids, host1->templateids.values[i],
|
|
ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
|
|
{
|
|
zbx_vector_uint64_remove_noorder(&templateids, j);
|
|
}
|
|
else
|
|
{
|
|
pair.first = host1->hostid;
|
|
pair.second = host1->templateids.values[i];
|
|
zbx_vector_uint64_pair_append(del_templateids, pair);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < templateids.values_num; i++)
|
|
um_mock_dbsync_add_htmpl(sync, ZBX_DBSYNC_ROW_ADD, host2->hostid, templateids.values[i]);
|
|
|
|
zbx_vector_uint64_destroy(&templateids);
|
|
}
|
|
|
|
static int um_mock_compare_hosts_by_id(const void *d1, const void *d2)
|
|
{
|
|
const zbx_um_mock_host_t *h1 = *(const zbx_um_mock_host_t * const *)d1;
|
|
const zbx_um_mock_host_t *h2 = *(const zbx_um_mock_host_t * const *)d2;
|
|
|
|
ZBX_RETURN_IF_NOT_EQUAL(h1->hostid, h2->hostid);
|
|
return 0;
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: compare two mock caches and output difference as database rows *
|
|
* stored into sync objects *
|
|
* *
|
|
*********************************************************************************/
|
|
void um_mock_cache_diff(zbx_um_mock_cache_t *cache1, zbx_um_mock_cache_t *cache2,
|
|
zbx_dbsync_t *gmacros, zbx_dbsync_t *hmacros, zbx_dbsync_t *htmpls)
|
|
{
|
|
zbx_hashset_iter_t iter;
|
|
zbx_vector_um_mock_host_t hosts;
|
|
zbx_vector_um_mock_macro_t del_macros;
|
|
zbx_vector_uint64_pair_t del_templateids;
|
|
zbx_um_mock_host_t *host1, *host2;
|
|
int i;
|
|
zbx_uint64_t hostid = 0;
|
|
|
|
zbx_vector_um_mock_host_create(&hosts);
|
|
zbx_vector_um_mock_macro_create(&del_macros);
|
|
zbx_vector_uint64_pair_create(&del_templateids);
|
|
|
|
/* compare global macros */
|
|
|
|
host1 = (zbx_um_mock_host_t *)zbx_hashset_search(&cache1->hosts, &hostid);
|
|
host2 = (zbx_um_mock_host_t *)zbx_hashset_search(&cache2->hosts, &hostid);
|
|
|
|
um_mock_host_macro_diff(host1, host2, gmacros, &del_macros);
|
|
|
|
for (i = 0; i < del_macros.values_num; i++)
|
|
um_mock_dbsync_add_macro(gmacros, ZBX_DBSYNC_ROW_REMOVE, del_macros.values[i]);
|
|
|
|
zbx_vector_um_mock_macro_clear(&del_macros);
|
|
|
|
/* compare host macros and templates */
|
|
|
|
zbx_hashset_iter_reset(&cache2->hosts, &iter);
|
|
while (NULL != (host2 = (zbx_um_mock_host_t *)zbx_hashset_iter_next(&iter)))
|
|
{
|
|
if (0 == host2->hostid)
|
|
continue;
|
|
|
|
zbx_vector_um_mock_host_append(&hosts, host2);
|
|
}
|
|
|
|
zbx_hashset_iter_reset(&cache1->hosts, &iter);
|
|
while (NULL != (host1 = (zbx_um_mock_host_t *)zbx_hashset_iter_next(&iter)))
|
|
{
|
|
if (0 == host1->hostid)
|
|
continue;
|
|
|
|
if (FAIL != (i = zbx_vector_um_mock_host_search(&hosts, host1, um_mock_compare_hosts_by_id)))
|
|
{
|
|
um_mock_host_macro_diff(host1, hosts.values[i], hmacros, &del_macros);
|
|
um_mock_host_template_diff(host1, hosts.values[i], htmpls, &del_templateids);
|
|
|
|
zbx_vector_um_mock_host_remove_noorder(&hosts, i);
|
|
}
|
|
else
|
|
{
|
|
um_mock_host_macro_diff(host1, NULL, hmacros, &del_macros);
|
|
um_mock_host_template_diff(host1, NULL, htmpls, &del_templateids);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < hosts.values_num; i++)
|
|
{
|
|
um_mock_host_macro_diff(NULL, hosts.values[i], hmacros, &del_macros);
|
|
um_mock_host_template_diff(NULL, hosts.values[i], htmpls, &del_templateids);
|
|
}
|
|
|
|
for (i = 0; i < del_macros.values_num; i++)
|
|
um_mock_dbsync_add_macro(hmacros, ZBX_DBSYNC_ROW_REMOVE, del_macros.values[i]);
|
|
|
|
for (i = 0; i < del_templateids.values_num; i++)
|
|
{
|
|
um_mock_dbsync_add_htmpl(htmpls, ZBX_DBSYNC_ROW_REMOVE, del_templateids.values[i].first,
|
|
del_templateids.values[i].second);
|
|
}
|
|
|
|
zbx_vector_uint64_pair_destroy(&del_templateids);
|
|
zbx_vector_um_mock_macro_destroy(&del_macros);
|
|
zbx_vector_um_mock_host_destroy(&hosts);
|
|
}
|
|
|
|
#define REFCOUNT_FIELD_SIZE sizeof(zbx_uint32_t)
|
|
|
|
static zbx_hash_t mock_strpool_hash(const void *data)
|
|
{
|
|
return ZBX_DEFAULT_STRING_HASH_FUNC((char *)data + REFCOUNT_FIELD_SIZE);
|
|
}
|
|
|
|
static int mock_strpool_compare(const void *d1, const void *d2)
|
|
{
|
|
return strcmp((char *)d1 + REFCOUNT_FIELD_SIZE, (char *)d2 + REFCOUNT_FIELD_SIZE);
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: initialize configuration cache with mocked user macros and string *
|
|
* pool *
|
|
* *
|
|
*********************************************************************************/
|
|
void um_mock_config_init(void)
|
|
{
|
|
config = (ZBX_DC_CONFIG *)zbx_malloc(NULL, sizeof(ZBX_DC_CONFIG));
|
|
memset(config, 0, sizeof(ZBX_DC_CONFIG));
|
|
|
|
zbx_hashset_create(&config->gmacros, 100, um_macro_hash, um_macro_compare);
|
|
zbx_hashset_create(&config->hmacros, 100, um_macro_hash, um_macro_compare);
|
|
zbx_hashset_create(&config->strpool, 100, mock_strpool_hash, mock_strpool_compare);
|
|
|
|
zbx_vector_ptr_create(&config->kvs_paths);
|
|
|
|
zbx_hashset_create(&config->gmacro_kv, 100, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
|
|
zbx_hashset_create(&config->hmacro_kv, 100, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
|
|
}
|
|
|
|
static void um_mock_kv_path_free(zbx_dc_kvs_path_t *kvspath)
|
|
{
|
|
zbx_hashset_iter_t iter;
|
|
zbx_dc_kv_t *kv;
|
|
|
|
zbx_hashset_iter_reset(&kvspath->kvs, &iter);
|
|
while (NULL != (kv = (zbx_dc_kv_t *)zbx_hashset_iter_next(&iter)))
|
|
zbx_vector_uint64_pair_destroy(&kv->macros);
|
|
|
|
zbx_hashset_destroy(&kvspath->kvs);
|
|
zbx_free(kvspath);
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: destroy configuration cache *
|
|
* *
|
|
*********************************************************************************/
|
|
void um_mock_config_destroy(void)
|
|
{
|
|
zbx_hashset_iter_t iter;
|
|
zbx_um_macro_t **pmacro;
|
|
|
|
zbx_hashset_iter_reset(&config->gmacros, &iter);
|
|
while (NULL != (pmacro = (zbx_um_macro_t **)zbx_hashset_iter_next(&iter)))
|
|
um_macro_release(*pmacro);
|
|
|
|
zbx_hashset_iter_reset(&config->hmacros, &iter);
|
|
while (NULL != (pmacro = (zbx_um_macro_t **)zbx_hashset_iter_next(&iter)))
|
|
um_macro_release(*pmacro);
|
|
|
|
zbx_vector_ptr_clear_ext(&config->kvs_paths, (zbx_ptr_free_func_t)um_mock_kv_path_free);
|
|
zbx_vector_ptr_destroy(&config->kvs_paths);
|
|
|
|
zbx_hashset_destroy(&config->gmacro_kv);
|
|
zbx_hashset_destroy(&config->hmacro_kv);
|
|
zbx_hashset_destroy(&config->gmacros);
|
|
zbx_hashset_destroy(&config->hmacros);
|
|
zbx_hashset_destroy(&config->strpool);
|
|
|
|
zbx_free(config);
|
|
}
|
|
|
|
/*********************************************************************************
|
|
* *
|
|
* Purpose: clear mocked sync data *
|
|
* *
|
|
*********************************************************************************/
|
|
void mock_dbsync_clear(zbx_dbsync_t *sync)
|
|
{
|
|
/* free the resources allocated by row pre-processing */
|
|
zbx_vector_ptr_clear_ext(&sync->columns, zbx_ptr_free);
|
|
zbx_vector_ptr_destroy(&sync->columns);
|
|
|
|
zbx_free(sync->row);
|
|
|
|
if (ZBX_DBSYNC_UPDATE == sync->mode)
|
|
{
|
|
int i, j;
|
|
zbx_dbsync_row_t *row;
|
|
|
|
for (i = 0; i < sync->rows.values_num; i++)
|
|
{
|
|
row = (zbx_dbsync_row_t *)sync->rows.values[i];
|
|
|
|
if (NULL != row->row)
|
|
{
|
|
for (j = 0; j < sync->columns_num; j++)
|
|
zbx_free(row->row[j]);
|
|
|
|
zbx_free(row->row);
|
|
}
|
|
|
|
zbx_free(row);
|
|
}
|
|
|
|
zbx_vector_ptr_destroy(&sync->rows);
|
|
}
|
|
else
|
|
{
|
|
zbx_db_free_result(sync->dbresult);
|
|
sync->dbresult = NULL;
|
|
}
|
|
}
|
|
|
|
/* mocked functions */
|
|
|
|
void *__wrap___zbx_shmem_malloc(const char *file, int line, zbx_shmem_info_t *info, const void *old, size_t size)
|
|
{
|
|
ZBX_UNUSED(file);
|
|
ZBX_UNUSED(line);
|
|
ZBX_UNUSED(info);
|
|
ZBX_UNUSED(old);
|
|
|
|
return zbx_malloc(NULL, size);
|
|
}
|
|
|
|
void *__wrap___zbx_shmem_realloc(const char *file, int line, zbx_shmem_info_t *info, void *old, size_t size)
|
|
{
|
|
ZBX_UNUSED(file);
|
|
ZBX_UNUSED(line);
|
|
ZBX_UNUSED(info);
|
|
|
|
return zbx_realloc(old, size);
|
|
}
|
|
|
|
void __wrap___zbx_shmem_free(const char *file, int line, zbx_shmem_info_t *info, void *ptr)
|
|
{
|
|
ZBX_UNUSED(file);
|
|
ZBX_UNUSED(line);
|
|
ZBX_UNUSED(info);
|
|
|
|
zbx_free(ptr);
|
|
}
|
|
|
|
/* debug */
|
|
|
|
static void um_mock_host_dump(const zbx_um_mock_host_t *host)
|
|
{
|
|
int i;
|
|
const char *separator;
|
|
|
|
printf("\thostid: " ZBX_FS_UI64 "\n\t\tmacros:\n", host->hostid);
|
|
|
|
for (i = 0; i < host->macros.values_num; i++)
|
|
{
|
|
printf("\t\t\t" ZBX_FS_UI64 " => %s:%s\n", host->macros.values[i]->macroid,
|
|
host->macros.values[i]->macro, host->macros.values[i]->value);
|
|
}
|
|
|
|
separator = "";
|
|
printf("\n\t\ttemplates: [");
|
|
for (i = 0; i < host->templateids.values_num; i++)
|
|
{
|
|
printf("%s" ZBX_FS_UI64 , separator, host->templateids.values[i]);
|
|
separator = ", ";
|
|
}
|
|
printf("]\n");
|
|
}
|
|
|
|
static void um_mock_kvset_dump(zbx_um_mock_kvset_t *kvset)
|
|
{
|
|
int i;
|
|
|
|
printf("\tpath:%s\n", kvset->path);
|
|
|
|
for (i = 0; i < kvset->kvs.values_num; i++)
|
|
printf("\t\t%s:%s\n", kvset->kvs.values[i]->key, kvset->kvs.values[i]->value);
|
|
}
|
|
|
|
void um_mock_cache_dump(zbx_um_mock_cache_t *cache)
|
|
{
|
|
zbx_hashset_iter_t iter;
|
|
zbx_um_mock_host_t *host;
|
|
int i;
|
|
|
|
printf("\nhosts:\n");
|
|
zbx_hashset_iter_reset(&cache->hosts, &iter);
|
|
while (NULL != (host = (zbx_um_mock_host_t *)zbx_hashset_iter_next(&iter)))
|
|
um_mock_host_dump(host);
|
|
|
|
printf("vault:\n");
|
|
for (i = 0; i < cache->kvsets.values_num; i++)
|
|
um_mock_kvset_dump(cache->kvsets.values[i]);
|
|
|
|
printf("---\n");
|
|
}
|