/* ** 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 "pp_task.h" #include "pp_error.h" #include "zbxcommon.h" #include "log.h" #include "zbxalgo.h" #include "zbxsysinc.h" #include "zbxipcservice.h" #define PP_TASK_QUEUE_INIT_NONE 0x00 #define PP_TASK_QUEUE_INIT_LOCK 0x01 #define PP_TASK_QUEUE_INIT_EVENT 0x02 ZBX_PTR_VECTOR_IMPL(pp_task_ptr, zbx_pp_task_t *) void pp_task_free(zbx_pp_task_t *task); /****************************************************************************** * * * Purpose: create task * * * * Parameters: size - [IN] the task data size * * * * Return value: The created task. * * * ******************************************************************************/ static zbx_pp_task_t *pp_task_create(size_t size) { zbx_pp_task_t *task; task = (zbx_pp_task_t *)zbx_malloc(NULL, offsetof(zbx_pp_task_t, data) + size); return task; } /****************************************************************************** * * * Purpose: create preprocessing test task * * * * Parameters: preproc - [IN] the item preprocessing data * * value - [IN] the value to preprocess, its contents will be * * directly copied over and cleared by the task * * (optional) * * ts - [IN] the value timestamp * * client - [IN] the request source * * * * Return value: The created task. * * * ******************************************************************************/ zbx_pp_task_t *pp_task_test_create(zbx_pp_item_preproc_t *preproc, zbx_variant_t *value, zbx_timespec_t ts, zbx_ipc_client_t *client) { zbx_pp_task_t *task = pp_task_create(sizeof(zbx_pp_task_test_t)); zbx_pp_task_test_t *d = (zbx_pp_task_test_t *)PP_TASK_DATA(task); task->itemid = 0; task->type = ZBX_PP_TASK_TEST; d->value = *value; d->ts = ts; d->results = NULL; d->results_num = 0; zbx_variant_set_none(&d->result); d->preproc = pp_item_preproc_copy(preproc); d->client = client; zbx_ipc_client_addref(client); return task; } /****************************************************************************** * * * Purpose: clear test task * * * * Parameters: task - [IN] the task to clear * * * ******************************************************************************/ static void pp_task_test_clear(zbx_pp_task_test_t *task) { zbx_variant_clear(&task->value); zbx_variant_clear(&task->result); pp_free_results(task->results, task->results_num); zbx_pp_item_preproc_release(task->preproc); zbx_ipc_client_release(task->client); } /****************************************************************************** * * * Purpose: create value preprocesing task * * * * Parameters: itemid - [IN] the item identifier * * preproc - [IN] the item preprocessing data * * value - [IN] the value to preprocess, its contents will be * * directly copied over and cleared by the task * * (optional) * * ts - [IN] the value timestamp * * value_opt - [IN] the optional value data (optional) * * cache - [IN] the preprocessing cache (optional) * * * * Return value: The created task. * * * ******************************************************************************/ zbx_pp_task_t *pp_task_value_create(zbx_uint64_t itemid, zbx_pp_item_preproc_t *preproc, zbx_variant_t *value, zbx_timespec_t ts, const zbx_pp_value_opt_t *value_opt, zbx_pp_cache_t *cache) { zbx_pp_task_t *task = pp_task_create(sizeof(zbx_pp_task_value_t)); zbx_pp_task_value_t *d = (zbx_pp_task_value_t *)PP_TASK_DATA(task); task->itemid = itemid; task->type = ZBX_PP_TASK_VALUE; if (NULL != value) d->value = *value; else zbx_variant_set_none(&d->value); zbx_variant_set_none(&d->result); d->cache = pp_cache_copy(cache); d->ts = ts; if (NULL != value_opt) d->opt = *value_opt; else d->opt.flags = ZBX_PP_VALUE_OPT_NONE; d->preproc = pp_item_preproc_copy(preproc); return task; } /****************************************************************************** * * * Purpose: clear value preprocessing task * * * * Parameters: task - [IN] the task to clear * * * ******************************************************************************/ static void pp_task_value_clear(zbx_pp_task_value_t *task) { zbx_pp_value_opt_clear(&task->opt); zbx_variant_clear(&task->value); zbx_variant_clear(&task->result); zbx_pp_item_preproc_release(task->preproc); pp_cache_release(task->cache); } /****************************************************************************** * * * Purpose: create serial value preprocesing task * * * * Parameters: itemid - [IN] the item identifier * * preproc - [IN] the item preprocessing data * * value - [IN] the value to preprocess, its contents will be * * directly copied over and cleared by the task * * (optional) * * ts - [IN] the value timestamp * * value_opt - [IN] the optional value data (optional) * * cache - [IN] the preprocessing cache (optional) * * * * Return value: The created task. * * * ******************************************************************************/ zbx_pp_task_t *pp_task_value_seq_create(zbx_uint64_t itemid, zbx_pp_item_preproc_t *preproc, zbx_variant_t *value, zbx_timespec_t ts, const zbx_pp_value_opt_t *value_opt, zbx_pp_cache_t *cache) { zbx_pp_task_t *task = pp_task_value_create(itemid, preproc, value, ts, value_opt, cache); task->type = ZBX_PP_TASK_VALUE_SEQ; return task; } /****************************************************************************** * * * Purpose: create dependent item preprocessing task * * * * Parameters: itemid - [IN] the item identifier * * preproc - [IN] the item preprocessing data * * * * Return value: The created task. * * * ******************************************************************************/ zbx_pp_task_t *pp_task_dependent_create(zbx_uint64_t itemid, zbx_pp_item_preproc_t *preproc) { zbx_pp_task_t *task = pp_task_create(sizeof(zbx_pp_task_dependent_t)); zbx_pp_task_dependent_t *d = (zbx_pp_task_dependent_t *)PP_TASK_DATA(task); task->itemid = itemid; task->type = ZBX_PP_TASK_DEPENDENT; d->primary = NULL; d->cache = NULL; d->preproc = pp_item_preproc_copy(preproc); return task; } /****************************************************************************** * * * Purpose: clear dependent item preprocessing task * * * * Parameters: task - [IN] the task to clear * * * ******************************************************************************/ static void pp_task_dependent_clear(zbx_pp_task_dependent_t *task) { zbx_pp_item_preproc_release(task->preproc); pp_cache_release(task->cache); if (NULL != task->primary) pp_task_free(task->primary); } /****************************************************************************** * * * Purpose: create sequence task * * * * Parameters: itemid - [IN] the item identifier * * * * Return value: The created task. * * * ******************************************************************************/ zbx_pp_task_t *pp_task_sequence_create(zbx_uint64_t itemid) { zbx_pp_task_t *task = pp_task_create(sizeof(zbx_pp_task_sequence_t)); zbx_pp_task_sequence_t *d = (zbx_pp_task_sequence_t *)PP_TASK_DATA(task); task->itemid = itemid; task->type = ZBX_PP_TASK_SEQUENCE; zbx_list_create(&d->tasks); return task; } /****************************************************************************** * * * Purpose: clear sequence task task * * * * Parameters: task - [IN] the task to clear * * * ******************************************************************************/ static void pp_task_sequence_clear(zbx_pp_task_sequence_t *seq) { zbx_pp_task_t *task; while (SUCCEED == zbx_list_pop(&seq->tasks, (void **)&task)) pp_task_free(task); zbx_list_destroy(&seq->tasks); } /****************************************************************************** * * * Purpose: free task * * * ******************************************************************************/ void pp_task_free(zbx_pp_task_t *task) { if (NULL == task) return; switch (task->type) { case ZBX_PP_TASK_TEST: pp_task_test_clear((zbx_pp_task_test_t *)PP_TASK_DATA(task)); break; case ZBX_PP_TASK_VALUE: case ZBX_PP_TASK_VALUE_SEQ: pp_task_value_clear((zbx_pp_task_value_t *)PP_TASK_DATA(task)); break; case ZBX_PP_TASK_DEPENDENT: pp_task_dependent_clear((zbx_pp_task_dependent_t *)PP_TASK_DATA(task)); break; case ZBX_PP_TASK_SEQUENCE: pp_task_sequence_clear((zbx_pp_task_sequence_t *)PP_TASK_DATA(task)); break; } zbx_free(task); } /****************************************************************************** * * * Purpose: clear tasks * * * ******************************************************************************/ void zbx_pp_tasks_clear(zbx_vector_pp_task_ptr_t *tasks) { zbx_vector_pp_task_ptr_clear_ext(tasks, pp_task_free); } /****************************************************************************** * * * Purpose: extract value task data * * * ******************************************************************************/ void zbx_pp_value_task_get_data(zbx_pp_task_t *task, unsigned char *value_type, unsigned char *flags, zbx_variant_t **value, zbx_timespec_t *ts, zbx_pp_value_opt_t **value_opt) { zbx_pp_task_value_t *d = (zbx_pp_task_value_t *)PP_TASK_DATA(task); *value_type = d->preproc->value_type; *flags = d->preproc->flags; *value = &d->result; *ts = d->ts; *value_opt = &d->opt; } /****************************************************************************** * * * Purpose: extract test task data * * * ******************************************************************************/ void zbx_pp_test_task_get_data(zbx_pp_task_t *task, zbx_ipc_client_t **client, zbx_variant_t **value, zbx_pp_result_t **results, int *results_num, zbx_pp_history_t **history) { zbx_pp_task_test_t *d = (zbx_pp_task_test_t *)PP_TASK_DATA(task); *client = d->client; *value = &d->result; *results = d->results; *results_num = d->results_num; *history = d->preproc->history; }