1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include <stddef.h>
21
22 #include "common.h"
23 #include "log.h"
24 #include "threads.h"
25 #include "dbcache.h"
26 #include "ipc.h"
27 #include "mutexs.h"
28 #include "memalloc.h"
29 #include "zbxserver.h"
30 #include "zbxalgo.h"
31 #include "zbxregexp.h"
32 #include "cfg.h"
33 #include "zbxtasks.h"
34 #include "../zbxcrypto/tls_tcp_active.h"
35 #include "../zbxalgo/vectorimpl.h"
36 #include "base64.h"
37 #include "zbxeval.h"
38
39 #define ZBX_DBCONFIG_IMPL
40 #include "dbconfig.h"
41 #include "dbsync.h"
42 #include "proxy.h"
43 #include "actions.h"
44 #include "zbxtrends.h"
45 #include "zbxvault.h"
46 #include "zbxserialize.h"
47
48 int sync_in_progress = 0;
49
50 #define START_SYNC WRLOCK_CACHE; sync_in_progress = 1
51 #define FINISH_SYNC sync_in_progress = 0; UNLOCK_CACHE
52
53 #define ZBX_LOC_NOWHERE 0
54 #define ZBX_LOC_QUEUE 1
55 #define ZBX_LOC_POLLER 2
56
57 #define ZBX_SNMP_OID_TYPE_NORMAL 0
58 #define ZBX_SNMP_OID_TYPE_DYNAMIC 1
59 #define ZBX_SNMP_OID_TYPE_MACRO 2
60
61 /* trigger is functional unless its expression contains disabled or not monitored items */
62 #define TRIGGER_FUNCTIONAL_TRUE 0
63 #define TRIGGER_FUNCTIONAL_FALSE 1
64
65 /* trigger contains time functions and is also scheduled by timer queue */
66 #define ZBX_TRIGGER_TIMER_UNKNOWN 0
67 #define ZBX_TRIGGER_TIMER_QUEUE 1
68
69 /* item priority in poller queue */
70 #define ZBX_QUEUE_PRIORITY_HIGH 0
71 #define ZBX_QUEUE_PRIORITY_NORMAL 1
72 #define ZBX_QUEUE_PRIORITY_LOW 2
73
74 /* shorthand macro for calling in_maintenance_without_data_collection() */
75 #define DCin_maintenance_without_data_collection(dc_host, dc_item) \
76 in_maintenance_without_data_collection(dc_host->maintenance_status, \
77 dc_host->maintenance_type, dc_item->type)
78
79 /******************************************************************************
80 * *
81 * Function: zbx_value_validator_func_t *
82 * *
83 * Purpose: validate macro value when expanding user macros *
84 * *
85 * Parameters: macro - [IN] the user macro *
86 * value - [IN] the macro value *
87 * error - [OUT] the error message *
88 * *
89 * Return value: SUCCEED - the value is valid *
90 * FAIL - otherwise *
91 * *
92 ******************************************************************************/
93 typedef int (*zbx_value_validator_func_t)(const char *macro, const char *value, char **error);
94
95 ZBX_DC_CONFIG *config = NULL;
96 zbx_rwlock_t config_lock = ZBX_RWLOCK_NULL;
97 static zbx_mem_info_t *config_mem;
98
99 extern unsigned char program_type;
100 extern int CONFIG_TIMER_FORKS;
101
102 ZBX_MEM_FUNC_IMPL(__config, config_mem)
103
104 static void dc_maintenance_precache_nested_groups(void);
105
106 /* by default the macro environment is non-secure and all secret macros are masked with ****** */
107 static unsigned char macro_env = ZBX_MACRO_ENV_NONSECURE;
108 extern char *CONFIG_VAULTDBPATH;
109 extern char *CONFIG_VAULTTOKEN;
110 /******************************************************************************
111 * *
112 * Function: dc_strdup *
113 * *
114 * Purpose: copies string into configuration cache shared memory *
115 * *
116 ******************************************************************************/
dc_strdup(const char * source)117 static char *dc_strdup(const char *source)
118 {
119 char *dst;
120 size_t len;
121
122 len = strlen(source) + 1;
123 dst = (char *)__config_mem_malloc_func(NULL, len);
124 memcpy(dst, source, len);
125 return dst;
126 }
127
128 /******************************************************************************
129 * *
130 * Function: is_item_processed_by_server *
131 * *
132 * Parameters: type - [IN] item type [ITEM_TYPE_* flag] *
133 * key - [IN] item key *
134 * *
135 * Return value: SUCCEED when an item should be processed by server *
136 * FAIL otherwise *
137 * *
138 * Comments: list of the items, always processed by server *
139 * ,------------------+--------------------------------------, *
140 * | type | key | *
141 * +------------------+--------------------------------------+ *
142 * | Zabbix internal | zabbix[host,,items] | *
143 * | Zabbix internal | zabbix[host,,items_unsupported] | *
144 * | Zabbix internal | zabbix[host,discovery,interfaces] | *
145 * | Zabbix internal | zabbix[host,,maintenance] | *
146 * | Zabbix internal | zabbix[proxy,<proxyname>,lastaccess] | *
147 * | Zabbix internal | zabbix[proxy,<proxyname>,delay] | *
148 * | Zabbix aggregate | * | *
149 * | Calculated | * | *
150 * '------------------+--------------------------------------' *
151 * *
152 ******************************************************************************/
is_item_processed_by_server(unsigned char type,const char * key)153 int is_item_processed_by_server(unsigned char type, const char *key)
154 {
155 int ret = FAIL;
156
157 switch (type)
158 {
159 case ITEM_TYPE_CALCULATED:
160 ret = SUCCEED;
161 break;
162
163 case ITEM_TYPE_INTERNAL:
164 if (0 == strncmp(key, "zabbix[", 7))
165 {
166 AGENT_REQUEST request;
167 char *arg1, *arg2, *arg3;
168
169 init_request(&request);
170
171 if (SUCCEED != parse_item_key(key, &request) || 3 != request.nparam)
172 goto clean;
173
174 arg1 = get_rparam(&request, 0);
175 arg2 = get_rparam(&request, 1);
176 arg3 = get_rparam(&request, 2);
177
178 if (0 == strcmp(arg1, "host"))
179 {
180 if ('\0' == *arg2)
181 {
182 if (0 == strcmp(arg3, "maintenance") || 0 == strcmp(arg3, "items") ||
183 0 == strcmp(arg3, "items_unsupported"))
184 {
185 ret = SUCCEED;
186 }
187 }
188 else if (0 == strcmp(arg2, "discovery") && 0 == strcmp(arg3, "interfaces"))
189 ret = SUCCEED;
190 }
191 else if (0 == strcmp(arg1, "proxy") &&
192 (0 == strcmp(arg3, "lastaccess") || 0 == strcmp(arg3, "delay")))
193 ret = SUCCEED;
194 clean:
195 free_request(&request);
196 }
197 break;
198 }
199
200 return ret;
201 }
202
poller_by_item(unsigned char type,const char * key)203 static unsigned char poller_by_item(unsigned char type, const char *key)
204 {
205 switch (type)
206 {
207 case ITEM_TYPE_SIMPLE:
208 if (SUCCEED == cmp_key_id(key, SERVER_ICMPPING_KEY) ||
209 SUCCEED == cmp_key_id(key, SERVER_ICMPPINGSEC_KEY) ||
210 SUCCEED == cmp_key_id(key, SERVER_ICMPPINGLOSS_KEY))
211 {
212 if (0 == CONFIG_PINGER_FORKS)
213 break;
214
215 return ZBX_POLLER_TYPE_PINGER;
216 }
217 ZBX_FALLTHROUGH;
218 case ITEM_TYPE_ZABBIX:
219 case ITEM_TYPE_SNMP:
220 case ITEM_TYPE_EXTERNAL:
221 case ITEM_TYPE_DB_MONITOR:
222 case ITEM_TYPE_SSH:
223 case ITEM_TYPE_TELNET:
224 case ITEM_TYPE_HTTPAGENT:
225 case ITEM_TYPE_SCRIPT:
226 if (0 == CONFIG_POLLER_FORKS)
227 break;
228
229 return ZBX_POLLER_TYPE_NORMAL;
230 case ITEM_TYPE_CALCULATED:
231 case ITEM_TYPE_INTERNAL:
232 if (0 == CONFIG_HISTORYPOLLER_FORKS)
233 break;
234
235 return ZBX_POLLER_TYPE_HISTORY;
236 case ITEM_TYPE_IPMI:
237 if (0 == CONFIG_IPMIPOLLER_FORKS)
238 break;
239
240 return ZBX_POLLER_TYPE_IPMI;
241 case ITEM_TYPE_JMX:
242 if (0 == CONFIG_JAVAPOLLER_FORKS)
243 break;
244
245 return ZBX_POLLER_TYPE_JAVA;
246 }
247
248 return ZBX_NO_POLLER;
249 }
250
251 /******************************************************************************
252 * *
253 * Function: zbx_is_counted_in_item_queue *
254 * *
255 * Purpose: determine whether the given item type is counted in item queue *
256 * *
257 * Return value: SUCCEED if item is counted in the queue, FAIL otherwise *
258 * *
259 ******************************************************************************/
zbx_is_counted_in_item_queue(unsigned char type,const char * key)260 int zbx_is_counted_in_item_queue(unsigned char type, const char *key)
261 {
262 switch (type)
263 {
264 case ITEM_TYPE_ZABBIX_ACTIVE:
265 if (0 == strncmp(key, "log[", 4) ||
266 0 == strncmp(key, "logrt[", 6) ||
267 0 == strncmp(key, "eventlog[", 9) ||
268 0 == strncmp(key, "mqtt.get[", ZBX_CONST_STRLEN("mqtt.get[")))
269 {
270 return FAIL;
271 }
272 break;
273 case ITEM_TYPE_TRAPPER:
274 case ITEM_TYPE_DEPENDENT:
275 case ITEM_TYPE_HTTPTEST:
276 case ITEM_TYPE_SNMPTRAP:
277 return FAIL;
278 }
279
280 return SUCCEED;
281 }
282
283 /******************************************************************************
284 * *
285 * Function: get_item_nextcheck_seed *
286 * *
287 * Purpose: get the seed value to be used for item nextcheck calculations *
288 * *
289 * Return value: the seed for nextcheck calculations *
290 * *
291 * Comments: The seed value is used to spread multiple item nextchecks over *
292 * the item delay period to even the system load. *
293 * Items with the same delay period and seed value will have the *
294 * same nextcheck values. *
295 * *
296 ******************************************************************************/
get_item_nextcheck_seed(zbx_uint64_t itemid,zbx_uint64_t interfaceid,unsigned char type,const char * key)297 static zbx_uint64_t get_item_nextcheck_seed(zbx_uint64_t itemid, zbx_uint64_t interfaceid, unsigned char type,
298 const char *key)
299 {
300 if (ITEM_TYPE_JMX == type)
301 return interfaceid;
302
303 if (ITEM_TYPE_SNMP == type)
304 {
305 ZBX_DC_SNMPINTERFACE *snmp;
306
307 if (NULL == (snmp = (ZBX_DC_SNMPINTERFACE *)zbx_hashset_search(&config->interfaces_snmp, &interfaceid))
308 || SNMP_BULK_ENABLED != snmp->bulk)
309 {
310 return itemid;
311 }
312
313 return interfaceid;
314 }
315
316 if (ITEM_TYPE_SIMPLE == type)
317 {
318 if (SUCCEED == cmp_key_id(key, SERVER_ICMPPING_KEY) ||
319 SUCCEED == cmp_key_id(key, SERVER_ICMPPINGSEC_KEY) ||
320 SUCCEED == cmp_key_id(key, SERVER_ICMPPINGLOSS_KEY))
321 {
322 return interfaceid;
323 }
324 }
325
326 return itemid;
327 }
328
329 #define ZBX_ITEM_COLLECTED 0x01 /* force item rescheduling after new value collection */
330 #define ZBX_HOST_UNREACHABLE 0x02
331 #define ZBX_ITEM_KEY_CHANGED 0x04
332 #define ZBX_ITEM_TYPE_CHANGED 0x08
333 #define ZBX_ITEM_DELAY_CHANGED 0x10
334
DCget_disable_until(const ZBX_DC_ITEM * item,const ZBX_DC_INTERFACE * interface)335 static int DCget_disable_until(const ZBX_DC_ITEM *item, const ZBX_DC_INTERFACE *interface)
336 {
337 switch (item->type)
338 {
339 case ITEM_TYPE_ZABBIX:
340 case ITEM_TYPE_SNMP:
341 case ITEM_TYPE_IPMI:
342 case ITEM_TYPE_JMX:
343 return (NULL == interface) ? 0 : interface->disable_until;
344 default:
345 return 0;
346 }
347 }
348
DCitem_nextcheck_update(ZBX_DC_ITEM * item,const ZBX_DC_INTERFACE * interface,int flags,int now,char ** error)349 static int DCitem_nextcheck_update(ZBX_DC_ITEM *item, const ZBX_DC_INTERFACE *interface, int flags, int now,
350 char **error)
351 {
352 zbx_uint64_t seed;
353 int simple_interval;
354 zbx_custom_interval_t *custom_intervals;
355 int disable_until;
356
357 if (0 == (flags & ZBX_ITEM_COLLECTED) && 0 != item->nextcheck &&
358 0 == (flags & ZBX_ITEM_KEY_CHANGED) && 0 == (flags & ZBX_ITEM_TYPE_CHANGED) &&
359 0 == (flags & ZBX_ITEM_DELAY_CHANGED))
360 {
361 return SUCCEED; /* avoid unnecessary nextcheck updates when syncing items in cache */
362 }
363
364 seed = get_item_nextcheck_seed(item->itemid, item->interfaceid, item->type, item->key);
365
366 if (SUCCEED != zbx_interval_preproc(item->delay, &simple_interval, &custom_intervals, error))
367 {
368 /* Polling items with invalid update intervals repeatedly does not make sense because they */
369 /* can only be healed by editing configuration (either update interval or macros involved) */
370 /* and such changes will be detected during configuration synchronization. DCsync_items() */
371 /* detects item configuration changes affecting check scheduling and passes them in flags. */
372
373 item->nextcheck = ZBX_JAN_2038;
374 item->schedulable = 0;
375 return FAIL;
376 }
377
378 if (0 != (flags & ZBX_HOST_UNREACHABLE) && NULL != interface && 0 != (disable_until =
379 DCget_disable_until(item, interface)))
380 {
381 item->nextcheck = calculate_item_nextcheck_unreachable(simple_interval,
382 custom_intervals, disable_until);
383 }
384 else
385 {
386 /* supported items and items that could not have been scheduled previously, but had */
387 /* their update interval fixed, should be scheduled using their update intervals */
388 item->nextcheck = calculate_item_nextcheck(seed, item->type, simple_interval,
389 custom_intervals, now);
390 }
391
392 zbx_custom_interval_free(custom_intervals);
393
394 item->schedulable = 1;
395
396 return SUCCEED;
397 }
398
DCitem_poller_type_update(ZBX_DC_ITEM * dc_item,const ZBX_DC_HOST * dc_host,int flags)399 static void DCitem_poller_type_update(ZBX_DC_ITEM *dc_item, const ZBX_DC_HOST *dc_host, int flags)
400 {
401 unsigned char poller_type;
402
403 if (0 != dc_host->proxy_hostid && SUCCEED != is_item_processed_by_server(dc_item->type, dc_item->key))
404 {
405 dc_item->poller_type = ZBX_NO_POLLER;
406 return;
407 }
408
409 poller_type = poller_by_item(dc_item->type, dc_item->key);
410
411 if (0 != (flags & ZBX_HOST_UNREACHABLE))
412 {
413 if (ZBX_POLLER_TYPE_NORMAL == poller_type || ZBX_POLLER_TYPE_JAVA == poller_type)
414 poller_type = ZBX_POLLER_TYPE_UNREACHABLE;
415
416 dc_item->poller_type = poller_type;
417 return;
418 }
419
420 if (0 != (flags & ZBX_ITEM_COLLECTED))
421 {
422 dc_item->poller_type = poller_type;
423 return;
424 }
425
426 if (ZBX_POLLER_TYPE_UNREACHABLE != dc_item->poller_type ||
427 (ZBX_POLLER_TYPE_NORMAL != poller_type && ZBX_POLLER_TYPE_JAVA != poller_type))
428 {
429 dc_item->poller_type = poller_type;
430 }
431 }
432
DCincrease_disable_until(ZBX_DC_INTERFACE * interface,int now)433 static void DCincrease_disable_until(ZBX_DC_INTERFACE *interface, int now)
434 {
435 if (NULL != interface && 0 != interface->errors_from)
436 interface->disable_until = now + CONFIG_TIMEOUT;
437 }
438
439 /******************************************************************************
440 * *
441 * Function: DCfind_id *
442 * *
443 * Purpose: Find an element in a hashset by its 'id' or create the element if *
444 * it does not exist *
445 * *
446 * Parameters: *
447 * hashset - [IN] hashset to search *
448 * id - [IN] id of element to search for *
449 * size - [IN] size of element to search for *
450 * found - [OUT flag. 0 - element did not exist, it was created. *
451 * 1 - existing element was found. *
452 * *
453 * Return value: pointer to the found or created element *
454 * *
455 ******************************************************************************/
DCfind_id(zbx_hashset_t * hashset,zbx_uint64_t id,size_t size,int * found)456 void *DCfind_id(zbx_hashset_t *hashset, zbx_uint64_t id, size_t size, int *found)
457 {
458 void *ptr;
459 zbx_uint64_t buffer[1024]; /* adjust buffer size to accommodate any type DCfind_id() can be called for */
460
461 if (NULL == (ptr = zbx_hashset_search(hashset, &id)))
462 {
463 *found = 0;
464
465 buffer[0] = id;
466 ptr = zbx_hashset_insert(hashset, &buffer[0], size);
467 }
468 else
469 {
470 *found = 1;
471 }
472
473 return ptr;
474 }
475
DCfind_item(zbx_uint64_t hostid,const char * key)476 static ZBX_DC_ITEM *DCfind_item(zbx_uint64_t hostid, const char *key)
477 {
478 ZBX_DC_ITEM_HK *item_hk, item_hk_local;
479
480 item_hk_local.hostid = hostid;
481 item_hk_local.key = key;
482
483 if (NULL == (item_hk = (ZBX_DC_ITEM_HK *)zbx_hashset_search(&config->items_hk, &item_hk_local)))
484 return NULL;
485 else
486 return item_hk->item_ptr;
487 }
488
DCfind_host(const char * host)489 static ZBX_DC_HOST *DCfind_host(const char *host)
490 {
491 ZBX_DC_HOST_H *host_h, host_h_local;
492
493 host_h_local.host = host;
494
495 if (NULL == (host_h = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_h, &host_h_local)))
496 return NULL;
497 else
498 return host_h->host_ptr;
499 }
500
501 /******************************************************************************
502 * *
503 * Function: DCfind_proxy *
504 * *
505 * Purpose: Find a record with proxy details in configuration cache using the *
506 * proxy name *
507 * *
508 * Parameters: host - [IN] proxy name *
509 * *
510 * Return value: pointer to record if found or NULL otherwise *
511 * *
512 ******************************************************************************/
DCfind_proxy(const char * host)513 static ZBX_DC_HOST *DCfind_proxy(const char *host)
514 {
515 ZBX_DC_HOST_H *host_p, host_p_local;
516
517 host_p_local.host = host;
518
519 if (NULL == (host_p = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_p, &host_p_local)))
520 return NULL;
521 else
522 return host_p->host_ptr;
523 }
524
525 /* private strpool functions */
526
527 #define REFCOUNT_FIELD_SIZE sizeof(zbx_uint32_t)
528
__config_strpool_hash(const void * data)529 static zbx_hash_t __config_strpool_hash(const void *data)
530 {
531 return ZBX_DEFAULT_STRING_HASH_FUNC((char *)data + REFCOUNT_FIELD_SIZE);
532 }
533
__config_strpool_compare(const void * d1,const void * d2)534 static int __config_strpool_compare(const void *d1, const void *d2)
535 {
536 return strcmp((char *)d1 + REFCOUNT_FIELD_SIZE, (char *)d2 + REFCOUNT_FIELD_SIZE);
537 }
538
zbx_strpool_intern(const char * str)539 static const char *zbx_strpool_intern(const char *str)
540 {
541 void *record;
542 zbx_uint32_t *refcount;
543
544 record = zbx_hashset_search(&config->strpool, str - REFCOUNT_FIELD_SIZE);
545
546 if (NULL == record)
547 {
548 record = zbx_hashset_insert_ext(&config->strpool, str - REFCOUNT_FIELD_SIZE,
549 REFCOUNT_FIELD_SIZE + strlen(str) + 1, REFCOUNT_FIELD_SIZE);
550 *(zbx_uint32_t *)record = 0;
551 }
552
553 refcount = (zbx_uint32_t *)record;
554 (*refcount)++;
555
556 return (char *)record + REFCOUNT_FIELD_SIZE;
557 }
558
zbx_strpool_release(const char * str)559 void zbx_strpool_release(const char *str)
560 {
561 zbx_uint32_t *refcount;
562
563 refcount = (zbx_uint32_t *)(str - REFCOUNT_FIELD_SIZE);
564 if (0 == --(*refcount))
565 zbx_hashset_remove(&config->strpool, str - REFCOUNT_FIELD_SIZE);
566 }
567
zbx_strpool_acquire(const char * str)568 static const char *zbx_strpool_acquire(const char *str)
569 {
570 zbx_uint32_t *refcount;
571
572 refcount = (zbx_uint32_t *)(str - REFCOUNT_FIELD_SIZE);
573 (*refcount)++;
574
575 return str;
576 }
577
DCstrpool_replace(int found,const char ** curr,const char * new_str)578 int DCstrpool_replace(int found, const char **curr, const char *new_str)
579 {
580 if (1 == found)
581 {
582 if (0 == strcmp(*curr, new_str))
583 return FAIL;
584
585 zbx_strpool_release(*curr);
586 }
587
588 *curr = zbx_strpool_intern(new_str);
589
590 return SUCCEED; /* indicate that the string has been replaced */
591 }
592
DCupdate_item_queue(ZBX_DC_ITEM * item,unsigned char old_poller_type,int old_nextcheck)593 static void DCupdate_item_queue(ZBX_DC_ITEM *item, unsigned char old_poller_type, int old_nextcheck)
594 {
595 zbx_binary_heap_elem_t elem;
596
597 if (ZBX_LOC_POLLER == item->location)
598 return;
599
600 if (ZBX_LOC_QUEUE == item->location && old_poller_type != item->poller_type)
601 {
602 item->location = ZBX_LOC_NOWHERE;
603 zbx_binary_heap_remove_direct(&config->queues[old_poller_type], item->itemid);
604 }
605
606 if (item->poller_type == ZBX_NO_POLLER)
607 return;
608
609 if (ZBX_LOC_QUEUE == item->location && old_nextcheck == item->nextcheck)
610 return;
611
612 elem.key = item->itemid;
613 elem.data = (const void *)item;
614
615 if (ZBX_LOC_QUEUE != item->location)
616 {
617 item->location = ZBX_LOC_QUEUE;
618 zbx_binary_heap_insert(&config->queues[item->poller_type], &elem);
619 }
620 else
621 zbx_binary_heap_update_direct(&config->queues[item->poller_type], &elem);
622 }
623
DCupdate_proxy_queue(ZBX_DC_PROXY * proxy)624 static void DCupdate_proxy_queue(ZBX_DC_PROXY *proxy)
625 {
626 zbx_binary_heap_elem_t elem;
627
628 if (ZBX_LOC_POLLER == proxy->location)
629 return;
630
631 proxy->nextcheck = proxy->proxy_tasks_nextcheck;
632 if (proxy->proxy_data_nextcheck < proxy->nextcheck)
633 proxy->nextcheck = proxy->proxy_data_nextcheck;
634 if (proxy->proxy_config_nextcheck < proxy->nextcheck)
635 proxy->nextcheck = proxy->proxy_config_nextcheck;
636
637 elem.key = proxy->hostid;
638 elem.data = (const void *)proxy;
639
640 if (ZBX_LOC_QUEUE != proxy->location)
641 {
642 proxy->location = ZBX_LOC_QUEUE;
643 zbx_binary_heap_insert(&config->pqueue, &elem);
644 }
645 else
646 zbx_binary_heap_update_direct(&config->pqueue, &elem);
647 }
648
649 /******************************************************************************
650 * *
651 * Function: config_gmacro_add_index *
652 * *
653 * Purpose: adds global macro index *
654 * *
655 * Parameters: gmacro_index - [IN/OUT] a global macro index hashset *
656 * gmacro - [IN] the macro to index *
657 * *
658 * Return value: The macro index record. *
659 * *
660 ******************************************************************************/
config_gmacro_add_index(zbx_hashset_t * gmacro_index,ZBX_DC_GMACRO * gmacro)661 static ZBX_DC_GMACRO_M *config_gmacro_add_index(zbx_hashset_t *gmacro_index, ZBX_DC_GMACRO *gmacro)
662 {
663 ZBX_DC_GMACRO_M *gmacro_m, gmacro_m_local;
664
665 gmacro_m_local.macro = gmacro->macro;
666
667 if (NULL == (gmacro_m = (ZBX_DC_GMACRO_M *)zbx_hashset_search(gmacro_index, &gmacro_m_local)))
668 {
669 gmacro_m_local.macro = zbx_strpool_acquire(gmacro->macro);
670 zbx_vector_ptr_create_ext(&gmacro_m_local.gmacros, __config_mem_malloc_func, __config_mem_realloc_func,
671 __config_mem_free_func);
672
673 gmacro_m = (ZBX_DC_GMACRO_M *)zbx_hashset_insert(gmacro_index, &gmacro_m_local, sizeof(ZBX_DC_GMACRO_M));
674 }
675
676 zbx_vector_ptr_append(&gmacro_m->gmacros, gmacro);
677 return gmacro_m;
678 }
679
680 /******************************************************************************
681 * *
682 * Function: config_gmacro_remove_index *
683 * *
684 * Purpose: removes global macro index *
685 * *
686 * Parameters: gmacro_index - [IN/OUT] a global macro index hashset *
687 * gmacro - [IN] the macro to remove *
688 * *
689 ******************************************************************************/
config_gmacro_remove_index(zbx_hashset_t * gmacro_index,ZBX_DC_GMACRO * gmacro)690 static ZBX_DC_GMACRO_M *config_gmacro_remove_index(zbx_hashset_t *gmacro_index, ZBX_DC_GMACRO *gmacro)
691 {
692 ZBX_DC_GMACRO_M *gmacro_m, gmacro_m_local;
693 int index;
694
695 gmacro_m_local.macro = gmacro->macro;
696
697 if (NULL != (gmacro_m = (ZBX_DC_GMACRO_M *)zbx_hashset_search(gmacro_index, &gmacro_m_local)))
698 {
699 if (FAIL != (index = zbx_vector_ptr_search(&gmacro_m->gmacros, gmacro, ZBX_DEFAULT_PTR_COMPARE_FUNC)))
700 zbx_vector_ptr_remove(&gmacro_m->gmacros, index);
701 }
702 return gmacro_m;
703 }
704
705 /******************************************************************************
706 * *
707 * Function: config_gmacro_context_compare *
708 * *
709 * Purpose: comparison function to sort global macro vector by context *
710 * operator, value and macro name *
711 * *
712 ******************************************************************************/
config_gmacro_context_compare(const void * d1,const void * d2)713 static int config_gmacro_context_compare(const void *d1, const void *d2)
714 {
715 const ZBX_DC_GMACRO *m1 = *(const ZBX_DC_GMACRO **)d1;
716 const ZBX_DC_GMACRO *m2 = *(const ZBX_DC_GMACRO **)d2;
717
718 /* macros without context have higher priority than macros with */
719 if (NULL == m1->context)
720 return NULL == m2->context ? 0 : -1;
721
722 if (NULL == m2->context)
723 return 1;
724
725 /* CONDITION_OPERATOR_EQUAL (0) has higher priority than CONDITION_OPERATOR_REGEXP (8) */
726 ZBX_RETURN_IF_NOT_EQUAL(m1->context_op, m2->context_op);
727
728 return strcmp(m1->context, m2->context);
729 }
730
731 /******************************************************************************
732 * *
733 * Function: config_hmacro_add_index *
734 * *
735 * Purpose: adds host macro index *
736 * *
737 * Parameters: hmacro_index - [IN/OUT] a host macro index hashset *
738 * hmacro - [IN] the macro to index *
739 * *
740 ******************************************************************************/
config_hmacro_add_index(zbx_hashset_t * hmacro_index,ZBX_DC_HMACRO * hmacro)741 static ZBX_DC_HMACRO_HM *config_hmacro_add_index(zbx_hashset_t *hmacro_index, ZBX_DC_HMACRO *hmacro)
742 {
743 ZBX_DC_HMACRO_HM *hmacro_hm, hmacro_hm_local;
744
745 hmacro_hm_local.hostid = hmacro->hostid;
746 hmacro_hm_local.macro = hmacro->macro;
747
748 if (NULL == (hmacro_hm = (ZBX_DC_HMACRO_HM *)zbx_hashset_search(hmacro_index, &hmacro_hm_local)))
749 {
750 hmacro_hm_local.macro = zbx_strpool_acquire(hmacro->macro);
751 zbx_vector_ptr_create_ext(&hmacro_hm_local.hmacros, __config_mem_malloc_func, __config_mem_realloc_func,
752 __config_mem_free_func);
753
754 hmacro_hm = (ZBX_DC_HMACRO_HM *)zbx_hashset_insert(hmacro_index, &hmacro_hm_local, sizeof(ZBX_DC_HMACRO_HM));
755 }
756
757 zbx_vector_ptr_append(&hmacro_hm->hmacros, hmacro);
758 return hmacro_hm;
759 }
760
761 /******************************************************************************
762 * *
763 * Function: config_hmacro_remove_index *
764 * *
765 * Purpose: removes host macro index *
766 * *
767 * Parameters: hmacro_index - [IN/OUT] a host macro index hashset *
768 * hmacro - [IN] the macro name to remove *
769 * *
770 ******************************************************************************/
config_hmacro_remove_index(zbx_hashset_t * hmacro_index,ZBX_DC_HMACRO * hmacro)771 static ZBX_DC_HMACRO_HM *config_hmacro_remove_index(zbx_hashset_t *hmacro_index, ZBX_DC_HMACRO *hmacro)
772 {
773 ZBX_DC_HMACRO_HM *hmacro_hm, hmacro_hm_local;
774 int index;
775
776 hmacro_hm_local.hostid = hmacro->hostid;
777 hmacro_hm_local.macro = hmacro->macro;
778
779 if (NULL != (hmacro_hm = (ZBX_DC_HMACRO_HM *)zbx_hashset_search(hmacro_index, &hmacro_hm_local)))
780 {
781 if (FAIL != (index = zbx_vector_ptr_search(&hmacro_hm->hmacros, hmacro, ZBX_DEFAULT_PTR_COMPARE_FUNC)))
782 zbx_vector_ptr_remove(&hmacro_hm->hmacros, index);
783 }
784 return hmacro_hm;
785 }
786
787 /******************************************************************************
788 * *
789 * Function: config_hmacro_context_compare *
790 * *
791 * Purpose: comparison function to sort host macro vector by context *
792 * operator, value and macro name *
793 * *
794 ******************************************************************************/
config_hmacro_context_compare(const void * d1,const void * d2)795 static int config_hmacro_context_compare(const void *d1, const void *d2)
796 {
797 const ZBX_DC_HMACRO *m1 = *(const ZBX_DC_HMACRO **)d1;
798 const ZBX_DC_HMACRO *m2 = *(const ZBX_DC_HMACRO **)d2;
799
800 /* macros without context have higher priority than macros with */
801 if (NULL == m1->context)
802 return NULL == m2->context ? 0 : -1;
803
804 if (NULL == m2->context)
805 return 1;
806
807 /* CONDITION_OPERATOR_EQUAL (0) has higher priority than CONDITION_OPERATOR_REGEXP (8) */
808 ZBX_RETURN_IF_NOT_EQUAL(m1->context_op, m2->context_op);
809
810 return strcmp(m1->context, m2->context);
811 }
812
dc_compare_kvs_path(const void * d1,const void * d2)813 static int dc_compare_kvs_path(const void *d1, const void *d2)
814 {
815 const zbx_dc_kvs_path_t *ptr1 = *((const zbx_dc_kvs_path_t **)d1);
816 const zbx_dc_kvs_path_t *ptr2 = *((const zbx_dc_kvs_path_t **)d2);
817
818 return strcmp(ptr1->path, ptr2->path);
819 }
820
dc_kv_hash(const void * data)821 static zbx_hash_t dc_kv_hash(const void *data)
822 {
823 return ZBX_DEFAULT_STRING_HASH_FUNC(((zbx_dc_kv_t *)data)->key);
824 }
825
dc_kv_compare(const void * d1,const void * d2)826 static int dc_kv_compare(const void *d1, const void *d2)
827 {
828 return strcmp(((zbx_dc_kv_t *)d1)->key, ((zbx_dc_kv_t *)d2)->key);
829 }
830
config_kvs_path_add(const char * path,const char * key)831 static zbx_dc_kv_t *config_kvs_path_add(const char *path, const char *key)
832 {
833 zbx_dc_kvs_path_t *kvs_path, kvs_path_local;
834 zbx_dc_kv_t *kv, kv_local;
835 int i;
836
837 kvs_path_local.path = path;
838
839 if (FAIL == (i = zbx_vector_ptr_search(&config->kvs_paths, &kvs_path_local, dc_compare_kvs_path)))
840 {
841 kvs_path = (zbx_dc_kvs_path_t *)__config_mem_malloc_func(NULL, sizeof(zbx_dc_kvs_path_t));
842 DCstrpool_replace(0, &kvs_path->path, path);
843 zbx_vector_ptr_append(&config->kvs_paths, kvs_path);
844
845 zbx_hashset_create_ext(&kvs_path->kvs, 0, dc_kv_hash, dc_kv_compare, NULL,
846 __config_mem_malloc_func, __config_mem_realloc_func, __config_mem_free_func);
847 kv = NULL;
848 }
849 else
850 {
851 kvs_path = (zbx_dc_kvs_path_t *)config->kvs_paths.values[i];
852 kv_local.key = key;
853 kv = (zbx_dc_kv_t *)zbx_hashset_search(&kvs_path->kvs, &kv_local);
854 }
855
856 if (NULL == kv)
857 {
858 DCstrpool_replace(0, &kv_local.key, key);
859 kv_local.value = NULL;
860 kv_local.refcount = 0;
861
862 kv = (zbx_dc_kv_t *)zbx_hashset_insert(&kvs_path->kvs, &kv_local, sizeof(zbx_dc_kv_t));
863 }
864
865 kv->refcount++;
866
867 return kv;
868 }
869
config_kvs_path_remove(const char * value,zbx_dc_kv_t * kv)870 static void config_kvs_path_remove(const char *value, zbx_dc_kv_t *kv)
871 {
872 zbx_dc_kvs_path_t *kvs_path, kvs_path_local;
873 int i;
874 char *path, *key;
875
876 if (0 != --kv->refcount)
877 return;
878
879 zbx_strsplit(value, ':', &path, &key);
880 zbx_free(key);
881
882 zbx_strpool_release(kv->key);
883 if (NULL != kv->value)
884 zbx_strpool_release(kv->value);
885
886 kvs_path_local.path = path;
887
888 if (FAIL == (i = zbx_vector_ptr_search(&config->kvs_paths, &kvs_path_local, dc_compare_kvs_path)))
889 {
890 THIS_SHOULD_NEVER_HAPPEN;
891 goto clean;
892 }
893 kvs_path = (zbx_dc_kvs_path_t *)config->kvs_paths.values[i];
894
895 zbx_hashset_remove_direct(&kvs_path->kvs, kv);
896
897 if (0 == kvs_path->kvs.num_data)
898 {
899 zbx_strpool_release(kvs_path->path);
900 __config_mem_free_func(kvs_path);
901 zbx_vector_ptr_remove_noorder(&config->kvs_paths, i);
902 }
903 clean:
904 zbx_free(path);
905 }
906
907 /******************************************************************************
908 * *
909 * Function: set_hk_opt *
910 * *
911 * Purpose: sets and validates global housekeeping option *
912 * *
913 * Parameters: value - [OUT] housekeeping setting *
914 * non_zero - [IN] 0 if value is allowed to be zero, 1 otherwise *
915 * value_min - [IN] minimal acceptable setting value *
916 * value_raw - [IN] setting value to validate *
917 * *
918 ******************************************************************************/
set_hk_opt(int * value,int non_zero,int value_min,const char * value_raw)919 static int set_hk_opt(int *value, int non_zero, int value_min, const char *value_raw)
920 {
921 if (SUCCEED != is_time_suffix(value_raw, value, ZBX_LENGTH_UNLIMITED))
922 return FAIL;
923
924 if (0 != non_zero && 0 == *value)
925 return FAIL;
926
927 if (0 != *value && (value_min > *value || ZBX_HK_PERIOD_MAX < *value))
928 return FAIL;
929
930 return SUCCEED;
931 }
932
DCsync_config(zbx_dbsync_t * sync,int * flags)933 static int DCsync_config(zbx_dbsync_t *sync, int *flags)
934 {
935 const ZBX_TABLE *config_table;
936
937 const char *selected_fields[] = {"discovery_groupid", "snmptrap_logging",
938 "severity_name_0", "severity_name_1", "severity_name_2", "severity_name_3",
939 "severity_name_4", "severity_name_5", "hk_events_mode", "hk_events_trigger",
940 "hk_events_internal", "hk_events_discovery", "hk_events_autoreg",
941 "hk_services_mode", "hk_services", "hk_audit_mode", "hk_audit",
942 "hk_sessions_mode", "hk_sessions", "hk_history_mode", "hk_history_global",
943 "hk_history", "hk_trends_mode", "hk_trends_global", "hk_trends",
944 "default_inventory_mode", "db_extension", "autoreg_tls_accept",
945 "compression_status", "compress_older", "instanceid",
946 "default_timezone"}; /* sync with zbx_dbsync_compare_config() */
947 const char *row[ARRSIZE(selected_fields)];
948 size_t i;
949 int j, found = 1, ret;
950 char **db_row;
951 zbx_uint64_t rowid;
952 unsigned char tag;
953
954 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
955
956 *flags = 0;
957
958 if (NULL == config->config)
959 {
960 found = 0;
961 config->config = (ZBX_DC_CONFIG_TABLE *)__config_mem_malloc_func(NULL, sizeof(ZBX_DC_CONFIG_TABLE));
962 }
963
964 if (SUCCEED != (ret = zbx_dbsync_next(sync, &rowid, &db_row, &tag)))
965 {
966 /* load default config data */
967
968 if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
969 zabbix_log(LOG_LEVEL_ERR, "no records in table 'config'");
970
971 config_table = DBget_table("config");
972
973 for (i = 0; i < ARRSIZE(selected_fields); i++)
974 row[i] = DBget_field(config_table, selected_fields[i])->default_value;
975 }
976 else
977 {
978 for (i = 0; i < ARRSIZE(selected_fields); i++)
979 row[i] = db_row[i];
980 }
981
982 /* store the config data */
983
984 if (NULL != row[0])
985 ZBX_STR2UINT64(config->config->discovery_groupid, row[0]);
986 else
987 config->config->discovery_groupid = ZBX_DISCOVERY_GROUPID_UNDEFINED;
988
989 ZBX_STR2UCHAR(config->config->snmptrap_logging, row[1]);
990 config->config->default_inventory_mode = atoi(row[25]);
991 DCstrpool_replace(found, (const char **)&config->config->db.extension, row[26]);
992 ZBX_STR2UCHAR(config->config->autoreg_tls_accept, row[27]);
993 ZBX_STR2UCHAR(config->config->db.history_compression_status, row[28]);
994
995 if (SUCCEED != is_time_suffix(row[29], &config->config->db.history_compress_older, ZBX_LENGTH_UNLIMITED))
996 {
997 zabbix_log(LOG_LEVEL_WARNING, "invalid history compression age: %s", row[29]);
998 config->config->db.history_compress_older = 0;
999 }
1000
1001 for (j = 0; TRIGGER_SEVERITY_COUNT > j; j++)
1002 DCstrpool_replace(found, &config->config->severity_name[j], row[2 + j]);
1003
1004 /* instance id cannot be changed - update it only at first sync to avoid read locks later */
1005 if (0 == found)
1006 DCstrpool_replace(found, &config->config->instanceid, row[30]);
1007
1008 #if TRIGGER_SEVERITY_COUNT != 6
1009 # error "row indexes below are based on assumption of six trigger severity levels"
1010 #endif
1011
1012 /* read housekeeper configuration */
1013
1014 if (ZBX_HK_OPTION_ENABLED == (config->config->hk.events_mode = atoi(row[8])) &&
1015 (SUCCEED != set_hk_opt(&config->config->hk.events_trigger, 1, SEC_PER_DAY, row[9]) ||
1016 SUCCEED != set_hk_opt(&config->config->hk.events_internal, 1, SEC_PER_DAY, row[10]) ||
1017 SUCCEED != set_hk_opt(&config->config->hk.events_discovery, 1, SEC_PER_DAY, row[11]) ||
1018 SUCCEED != set_hk_opt(&config->config->hk.events_autoreg, 1, SEC_PER_DAY, row[12])))
1019 {
1020 zabbix_log(LOG_LEVEL_WARNING, "trigger, internal, network discovery and auto-registration data"
1021 " housekeeping will be disabled due to invalid settings");
1022 config->config->hk.events_mode = ZBX_HK_OPTION_DISABLED;
1023 }
1024
1025 if (ZBX_HK_OPTION_ENABLED == (config->config->hk.services_mode = atoi(row[13])) &&
1026 SUCCEED != set_hk_opt(&config->config->hk.services, 1, SEC_PER_DAY, row[14]))
1027 {
1028 zabbix_log(LOG_LEVEL_WARNING, "IT services data housekeeping will be disabled due to invalid"
1029 " settings");
1030 config->config->hk.services_mode = ZBX_HK_OPTION_DISABLED;
1031 }
1032
1033 if (ZBX_HK_OPTION_ENABLED == (config->config->hk.audit_mode = atoi(row[15])) &&
1034 SUCCEED != set_hk_opt(&config->config->hk.audit, 1, SEC_PER_DAY, row[16]))
1035 {
1036 zabbix_log(LOG_LEVEL_WARNING, "audit data housekeeping will be disabled due to invalid"
1037 " settings");
1038 config->config->hk.audit_mode = ZBX_HK_OPTION_DISABLED;
1039 }
1040
1041 if (ZBX_HK_OPTION_ENABLED == (config->config->hk.sessions_mode = atoi(row[17])) &&
1042 SUCCEED != set_hk_opt(&config->config->hk.sessions, 1, SEC_PER_DAY, row[18]))
1043 {
1044 zabbix_log(LOG_LEVEL_WARNING, "user sessions data housekeeping will be disabled due to invalid"
1045 " settings");
1046 config->config->hk.sessions_mode = ZBX_HK_OPTION_DISABLED;
1047 }
1048
1049 config->config->hk.history_mode = atoi(row[19]);
1050 if (ZBX_HK_OPTION_ENABLED == (config->config->hk.history_global = atoi(row[20])) &&
1051 SUCCEED != set_hk_opt(&config->config->hk.history, 0, ZBX_HK_HISTORY_MIN, row[21]))
1052 {
1053 zabbix_log(LOG_LEVEL_WARNING, "history data housekeeping will be disabled and all items will"
1054 " store their history due to invalid global override settings");
1055 config->config->hk.history_mode = ZBX_HK_MODE_DISABLED;
1056 config->config->hk.history = 1; /* just enough to make 0 == items[i].history condition fail */
1057 }
1058
1059 #ifdef HAVE_POSTGRESQL
1060 if (ZBX_HK_MODE_DISABLED != config->config->hk.history_mode &&
1061 ZBX_HK_OPTION_ENABLED == config->config->hk.history_global &&
1062 0 == zbx_strcmp_null(config->config->db.extension, ZBX_CONFIG_DB_EXTENSION_TIMESCALE))
1063 {
1064 config->config->hk.history_mode = ZBX_HK_MODE_PARTITION;
1065 }
1066 #endif
1067
1068 config->config->hk.trends_mode = atoi(row[22]);
1069 if (ZBX_HK_OPTION_ENABLED == (config->config->hk.trends_global = atoi(row[23])) &&
1070 SUCCEED != set_hk_opt(&config->config->hk.trends, 0, ZBX_HK_TRENDS_MIN, row[24]))
1071 {
1072 zabbix_log(LOG_LEVEL_WARNING, "trends data housekeeping will be disabled and all numeric items"
1073 " will store their history due to invalid global override settings");
1074 config->config->hk.trends_mode = ZBX_HK_MODE_DISABLED;
1075 config->config->hk.trends = 1; /* just enough to make 0 == items[i].trends condition fail */
1076 }
1077
1078 #ifdef HAVE_POSTGRESQL
1079 if (ZBX_HK_MODE_DISABLED != config->config->hk.trends_mode &&
1080 ZBX_HK_OPTION_ENABLED == config->config->hk.trends_global &&
1081 0 == zbx_strcmp_null(config->config->db.extension, ZBX_CONFIG_DB_EXTENSION_TIMESCALE))
1082 {
1083 config->config->hk.trends_mode = ZBX_HK_MODE_PARTITION;
1084 }
1085 #endif
1086 DCstrpool_replace(found, &config->config->default_timezone, row[31]);
1087
1088 if (SUCCEED == ret && SUCCEED == zbx_dbsync_next(sync, &rowid, &db_row, &tag)) /* table must have */
1089 zabbix_log(LOG_LEVEL_ERR, "table 'config' has multiple records"); /* only one record */
1090
1091 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1092
1093 return SUCCEED;
1094 }
1095
DCsync_autoreg_config(zbx_dbsync_t * sync)1096 static void DCsync_autoreg_config(zbx_dbsync_t *sync)
1097 {
1098 /* sync this function with zbx_dbsync_compare_autoreg_psk() */
1099 char **db_row;
1100 zbx_uint64_t rowid;
1101 unsigned char tag;
1102
1103 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1104
1105 if (SUCCEED == zbx_dbsync_next(sync, &rowid, &db_row, &tag))
1106 {
1107 switch (tag)
1108 {
1109 case ZBX_DBSYNC_ROW_ADD:
1110 case ZBX_DBSYNC_ROW_UPDATE:
1111 zbx_strlcpy(config->autoreg_psk_identity, db_row[0],
1112 sizeof(config->autoreg_psk_identity));
1113 zbx_strlcpy(config->autoreg_psk, db_row[1], sizeof(config->autoreg_psk));
1114 break;
1115 case ZBX_DBSYNC_ROW_REMOVE:
1116 config->autoreg_psk_identity[0] = '\0';
1117 zbx_guaranteed_memset(config->autoreg_psk, 0, sizeof(config->autoreg_psk));
1118 break;
1119 default:
1120 THIS_SHOULD_NEVER_HAPPEN;
1121 }
1122 }
1123
1124 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1125 }
1126
DCsync_proxy_remove(ZBX_DC_PROXY * proxy)1127 static void DCsync_proxy_remove(ZBX_DC_PROXY *proxy)
1128 {
1129 if (ZBX_LOC_QUEUE == proxy->location)
1130 {
1131 zbx_binary_heap_remove_direct(&config->pqueue, proxy->hostid);
1132 proxy->location = ZBX_LOC_NOWHERE;
1133 }
1134
1135 zbx_strpool_release(proxy->proxy_address);
1136 zbx_hashset_remove_direct(&config->proxies, proxy);
1137 }
1138
DCsync_hosts(zbx_dbsync_t * sync)1139 static void DCsync_hosts(zbx_dbsync_t *sync)
1140 {
1141 char **row;
1142 zbx_uint64_t rowid;
1143 unsigned char tag;
1144
1145 ZBX_DC_HOST *host;
1146 ZBX_DC_IPMIHOST *ipmihost;
1147 ZBX_DC_PROXY *proxy;
1148 ZBX_DC_HOST_H *host_h, host_h_local, *host_p, host_p_local;
1149
1150 int found;
1151 int update_index_h, update_index_p, ret;
1152 zbx_uint64_t hostid, proxy_hostid;
1153 unsigned char status;
1154 time_t now;
1155 signed char ipmi_authtype;
1156 unsigned char ipmi_privilege;
1157 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1158 ZBX_DC_PSK *psk_i, psk_i_local;
1159 zbx_ptr_pair_t *psk_owner, psk_owner_local;
1160 zbx_hashset_t psk_owners;
1161 #endif
1162 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1163
1164 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1165 zbx_hashset_create(&psk_owners, 0, ZBX_DEFAULT_PTR_HASH_FUNC, ZBX_DEFAULT_PTR_COMPARE_FUNC);
1166 #endif
1167 now = time(NULL);
1168
1169 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
1170 {
1171 /* removed rows will be always added at the end */
1172 if (ZBX_DBSYNC_ROW_REMOVE == tag)
1173 break;
1174
1175 ZBX_STR2UINT64(hostid, row[0]);
1176 ZBX_DBROW2UINT64(proxy_hostid, row[1]);
1177 ZBX_STR2UCHAR(status, row[10]);
1178
1179 host = (ZBX_DC_HOST *)DCfind_id(&config->hosts, hostid, sizeof(ZBX_DC_HOST), &found);
1180
1181 /* see whether we should and can update 'hosts_h' and 'hosts_p' indexes at this point */
1182
1183 update_index_h = 0;
1184 update_index_p = 0;
1185
1186 if ((HOST_STATUS_MONITORED == status || HOST_STATUS_NOT_MONITORED == status) &&
1187 (0 == found || 0 != strcmp(host->host, row[2])))
1188 {
1189 if (1 == found)
1190 {
1191 host_h_local.host = host->host;
1192 host_h = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_h, &host_h_local);
1193
1194 if (NULL != host_h && host == host_h->host_ptr) /* see ZBX-4045 for NULL check */
1195 {
1196 zbx_strpool_release(host_h->host);
1197 zbx_hashset_remove_direct(&config->hosts_h, host_h);
1198 }
1199 }
1200
1201 host_h_local.host = row[2];
1202 host_h = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_h, &host_h_local);
1203
1204 if (NULL != host_h)
1205 host_h->host_ptr = host;
1206 else
1207 update_index_h = 1;
1208 }
1209 else if ((HOST_STATUS_PROXY_ACTIVE == status || HOST_STATUS_PROXY_PASSIVE == status) &&
1210 (0 == found || 0 != strcmp(host->host, row[2])))
1211 {
1212 if (1 == found)
1213 {
1214 host_p_local.host = host->host;
1215 host_p = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_p, &host_p_local);
1216
1217 if (NULL != host_p && host == host_p->host_ptr)
1218 {
1219 zbx_strpool_release(host_p->host);
1220 zbx_hashset_remove_direct(&config->hosts_p, host_p);
1221 }
1222 }
1223
1224 host_p_local.host = row[2];
1225 host_p = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_p, &host_p_local);
1226
1227 if (NULL != host_p)
1228 host_p->host_ptr = host;
1229 else
1230 update_index_p = 1;
1231 }
1232
1233 /* store new information in host structure */
1234
1235 DCstrpool_replace(found, &host->host, row[2]);
1236 DCstrpool_replace(found, &host->name, row[11]);
1237 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1238 DCstrpool_replace(found, &host->tls_issuer, row[15]);
1239 DCstrpool_replace(found, &host->tls_subject, row[16]);
1240
1241 /* maintain 'config->psks' in configuration cache */
1242
1243 /*****************************************************************************/
1244 /* */
1245 /* cases to cover (PSKid means PSK identity): */
1246 /* */
1247 /* Incoming data record */
1248 /* / \ */
1249 /* new new */
1250 /* PSKid PSKid */
1251 /* non-empty empty */
1252 /* / \ / \ */
1253 /* / \ / \ */
1254 /* 'host' 'host' 'host' 'host' */
1255 /* record record record record */
1256 /* has has has has */
1257 /* non-empty empty non-empty empty PSK */
1258 /* PSK PSK PSK | \ */
1259 /* / \ | | | \ */
1260 /* / \ | | | \ */
1261 /* / \ | | | \ */
1262 /* new PSKid new PSKid | | existing new */
1263 /* same as differs | | record record */
1264 /* old PSKid from | | | | */
1265 /* / | old PSKid | | done | */
1266 /* / | | | | | */
1267 /* new PSK new PSK delete | delete | */
1268 /* value value old PSKid | old PSKid | */
1269 /* same as differs and value | and value | */
1270 /* old from from psks | from psks | */
1271 /* | old hashset | hashset | */
1272 /* done / (if ref | (if ref | */
1273 /* / count=0) | count=0) | */
1274 /* / / \ /| \ / */
1275 /* / /--------- | \ / */
1276 /* / / \ | \ / */
1277 /* delete new PSKid new PSKid set pointer in */
1278 /* old PSK already not in 'hosts' record */
1279 /* value in psks psks to NULL PSK */
1280 /* from hashset hashset | */
1281 /* string / \ \ done */
1282 /* pool / \ \ */
1283 /* | / \ \ */
1284 /* change PSK value PSK value insert */
1285 /* PSK value in hashset in hashset new PSKid */
1286 /* for this same as differs and value */
1287 /* PSKid new PSK from new into psks */
1288 /* | value PSK value hashset */
1289 /* done \ | / */
1290 /* \ replace / */
1291 /* \ PSK value / */
1292 /* \ in hashset / */
1293 /* \ with new / */
1294 /* \ PSK value / */
1295 /* \ | / */
1296 /* \ | / */
1297 /* set pointer */
1298 /* in 'host' */
1299 /* record to */
1300 /* new PSKid */
1301 /* | */
1302 /* done */
1303 /* */
1304 /*****************************************************************************/
1305
1306 psk_owner = NULL;
1307
1308 if ('\0' == *row[17] || '\0' == *row[18]) /* new PSKid or value empty */
1309 {
1310 /* In case of "impossible" errors ("PSK value without identity" or "PSK identity without */
1311 /* value") assume empty PSK identity and value. These errors should have been prevented */
1312 /* by validation in frontend/API. Be prepared when making a connection requiring PSK - */
1313 /* the PSK might not be available. */
1314
1315 if (1 == found)
1316 {
1317 if (NULL == host->tls_dc_psk) /* 'host' record has empty PSK */
1318 goto done;
1319
1320 /* 'host' record has non-empty PSK. Unlink and delete PSK. */
1321
1322 psk_i_local.tls_psk_identity = host->tls_dc_psk->tls_psk_identity;
1323
1324 if (NULL != (psk_i = (ZBX_DC_PSK *)zbx_hashset_search(&config->psks, &psk_i_local)) &&
1325 0 == --(psk_i->refcount))
1326 {
1327 zbx_strpool_release(psk_i->tls_psk_identity);
1328 zbx_strpool_release(psk_i->tls_psk);
1329 zbx_hashset_remove_direct(&config->psks, psk_i);
1330 }
1331 }
1332
1333 host->tls_dc_psk = NULL;
1334 goto done;
1335 }
1336
1337 /* new PSKid and value non-empty */
1338
1339 zbx_strlower(row[18]);
1340
1341 if (1 == found && NULL != host->tls_dc_psk) /* 'host' record has non-empty PSK */
1342 {
1343 if (0 == strcmp(host->tls_dc_psk->tls_psk_identity, row[17])) /* new PSKid same as */
1344 /* old PSKid */
1345 {
1346 if (0 != strcmp(host->tls_dc_psk->tls_psk, row[18])) /* new PSK value */
1347 /* differs from old */
1348 {
1349 if (NULL == (psk_owner = (zbx_ptr_pair_t *)zbx_hashset_search(&psk_owners,
1350 &host->tls_dc_psk->tls_psk_identity)))
1351 {
1352 /* change underlying PSK value and 'config->psks' is updated, too */
1353 DCstrpool_replace(1, &host->tls_dc_psk->tls_psk, row[18]);
1354 }
1355 else
1356 {
1357 zabbix_log(LOG_LEVEL_WARNING, "conflicting PSK values for PSK identity"
1358 " \"%s\" on hosts \"%s\" and \"%s\" (and maybe others)",
1359 (char *)psk_owner->first, (char *)psk_owner->second,
1360 host->host);
1361 }
1362 }
1363
1364 goto done;
1365 }
1366
1367 /* New PSKid differs from old PSKid. Unlink and delete old PSK. */
1368
1369 psk_i_local.tls_psk_identity = host->tls_dc_psk->tls_psk_identity;
1370
1371 if (NULL != (psk_i = (ZBX_DC_PSK *)zbx_hashset_search(&config->psks, &psk_i_local)) &&
1372 0 == --(psk_i->refcount))
1373 {
1374 zbx_strpool_release(psk_i->tls_psk_identity);
1375 zbx_strpool_release(psk_i->tls_psk);
1376 zbx_hashset_remove_direct(&config->psks, psk_i);
1377 }
1378
1379 host->tls_dc_psk = NULL;
1380 }
1381
1382 /* new PSK identity already stored? */
1383
1384 psk_i_local.tls_psk_identity = row[17];
1385
1386 if (NULL != (psk_i = (ZBX_DC_PSK *)zbx_hashset_search(&config->psks, &psk_i_local)))
1387 {
1388 /* new PSKid already in psks hashset */
1389
1390 if (0 != strcmp(psk_i->tls_psk, row[18])) /* PSKid stored but PSK value is different */
1391 {
1392 if (NULL == (psk_owner = (zbx_ptr_pair_t *)zbx_hashset_search(&psk_owners, &psk_i->tls_psk_identity)))
1393 {
1394 DCstrpool_replace(1, &psk_i->tls_psk, row[18]);
1395 }
1396 else
1397 {
1398 zabbix_log(LOG_LEVEL_WARNING, "conflicting PSK values for PSK identity"
1399 " \"%s\" on hosts \"%s\" and \"%s\" (and maybe others)",
1400 (char *)psk_owner->first, (char *)psk_owner->second,
1401 host->host);
1402 }
1403 }
1404
1405 host->tls_dc_psk = psk_i;
1406 psk_i->refcount++;
1407 goto done;
1408 }
1409
1410 /* insert new PSKid and value into psks hashset */
1411
1412 DCstrpool_replace(0, &psk_i_local.tls_psk_identity, row[17]);
1413 DCstrpool_replace(0, &psk_i_local.tls_psk, row[18]);
1414 psk_i_local.refcount = 1;
1415 host->tls_dc_psk = zbx_hashset_insert(&config->psks, &psk_i_local, sizeof(ZBX_DC_PSK));
1416 done:
1417 if (NULL != host->tls_dc_psk && NULL == psk_owner)
1418 {
1419 if (NULL == zbx_hashset_search(&psk_owners, &host->tls_dc_psk->tls_psk_identity))
1420 {
1421 /* register this host as the PSK identity owner, against which to report conflicts */
1422
1423 psk_owner_local.first = (char *)host->tls_dc_psk->tls_psk_identity;
1424 psk_owner_local.second = (char *)host->host;
1425
1426 zbx_hashset_insert(&psk_owners, &psk_owner_local, sizeof(psk_owner_local));
1427 }
1428 }
1429 #endif
1430 ZBX_STR2UCHAR(host->tls_connect, row[13]);
1431 ZBX_STR2UCHAR(host->tls_accept, row[14]);
1432
1433 if ((HOST_STATUS_PROXY_PASSIVE == status && 0 != (ZBX_TCP_SEC_UNENCRYPTED & host->tls_connect)) ||
1434 (HOST_STATUS_PROXY_ACTIVE == status && 0 != (ZBX_TCP_SEC_UNENCRYPTED & host->tls_accept)))
1435 {
1436 if (NULL != CONFIG_VAULTTOKEN)
1437 {
1438 zabbix_log(LOG_LEVEL_WARNING, "connection with Zabbix proxy \"%s\" should not be"
1439 " unencrypted when using Vault", host->host);
1440 }
1441 }
1442
1443 if (0 == found)
1444 {
1445 ZBX_DBROW2UINT64(host->maintenanceid, row[17 + ZBX_HOST_TLS_OFFSET]);
1446 host->maintenance_status = (unsigned char)atoi(row[7]);
1447 host->maintenance_type = (unsigned char)atoi(row[8]);
1448 host->maintenance_from = atoi(row[9]);
1449 host->data_expected_from = now;
1450 host->update_items = 0;
1451
1452 zbx_vector_ptr_create_ext(&host->interfaces_v, __config_mem_malloc_func,
1453 __config_mem_realloc_func, __config_mem_free_func);
1454 }
1455 else
1456 {
1457 int reset_availability = 0;
1458
1459 if (HOST_STATUS_MONITORED == status && HOST_STATUS_MONITORED != host->status)
1460 host->data_expected_from = now;
1461
1462 /* reset host status if host status has been changed (e.g., if host has been disabled) */
1463 if (status != host->status)
1464 reset_availability = 1;
1465
1466 /* reset host status if host proxy assignment has been changed */
1467 if (proxy_hostid != host->proxy_hostid)
1468 reset_availability = 1;
1469
1470 if (0 != reset_availability)
1471 {
1472 int i;
1473 ZBX_DC_INTERFACE *interface;
1474
1475 for (i = 0; i < host->interfaces_v.values_num; i++)
1476 {
1477 interface = (ZBX_DC_INTERFACE *)host->interfaces_v.values[i];
1478 interface->reset_availability = 1;
1479 }
1480 }
1481
1482 }
1483
1484 host->proxy_hostid = proxy_hostid;
1485
1486 /* update 'hosts_h' and 'hosts_p' indexes using new data, if not done already */
1487
1488 if (1 == update_index_h)
1489 {
1490 host_h_local.host = zbx_strpool_acquire(host->host);
1491 host_h_local.host_ptr = host;
1492 zbx_hashset_insert(&config->hosts_h, &host_h_local, sizeof(ZBX_DC_HOST_H));
1493 }
1494
1495 if (1 == update_index_p)
1496 {
1497 host_p_local.host = zbx_strpool_acquire(host->host);
1498 host_p_local.host_ptr = host;
1499 zbx_hashset_insert(&config->hosts_p, &host_p_local, sizeof(ZBX_DC_HOST_H));
1500 }
1501
1502 /* IPMI hosts */
1503
1504 ipmi_authtype = (signed char)atoi(row[3]);
1505 ipmi_privilege = (unsigned char)atoi(row[4]);
1506
1507 if (ZBX_IPMI_DEFAULT_AUTHTYPE != ipmi_authtype || ZBX_IPMI_DEFAULT_PRIVILEGE != ipmi_privilege ||
1508 '\0' != *row[5] || '\0' != *row[6]) /* useipmi */
1509 {
1510 ipmihost = (ZBX_DC_IPMIHOST *)DCfind_id(&config->ipmihosts, hostid, sizeof(ZBX_DC_IPMIHOST), &found);
1511
1512 ipmihost->ipmi_authtype = ipmi_authtype;
1513 ipmihost->ipmi_privilege = ipmi_privilege;
1514 DCstrpool_replace(found, &ipmihost->ipmi_username, row[5]);
1515 DCstrpool_replace(found, &ipmihost->ipmi_password, row[6]);
1516 }
1517 else if (NULL != (ipmihost = (ZBX_DC_IPMIHOST *)zbx_hashset_search(&config->ipmihosts, &hostid)))
1518 {
1519 /* remove IPMI connection parameters for hosts without IPMI */
1520
1521 zbx_strpool_release(ipmihost->ipmi_username);
1522 zbx_strpool_release(ipmihost->ipmi_password);
1523
1524 zbx_hashset_remove_direct(&config->ipmihosts, ipmihost);
1525 }
1526
1527 /* proxies */
1528
1529 if (HOST_STATUS_PROXY_ACTIVE == status || HOST_STATUS_PROXY_PASSIVE == status)
1530 {
1531 proxy = (ZBX_DC_PROXY *)DCfind_id(&config->proxies, hostid, sizeof(ZBX_DC_PROXY), &found);
1532
1533 if (0 == found)
1534 {
1535 proxy->location = ZBX_LOC_NOWHERE;
1536 proxy->version = 0;
1537 proxy->lastaccess = atoi(row[12]);
1538 proxy->last_cfg_error_time = 0;
1539 proxy->proxy_delay = 0;
1540 proxy->nodata_win.flags = ZBX_PROXY_SUPPRESS_DISABLE;
1541 proxy->nodata_win.values_num = 0;
1542 proxy->nodata_win.period_end = 0;
1543 }
1544
1545 proxy->auto_compress = atoi(row[16 + ZBX_HOST_TLS_OFFSET]);
1546 DCstrpool_replace(found, &proxy->proxy_address, row[15 + ZBX_HOST_TLS_OFFSET]);
1547
1548 if (HOST_STATUS_PROXY_PASSIVE == status && (0 == found || status != host->status))
1549 {
1550 proxy->proxy_config_nextcheck = (int)calculate_proxy_nextcheck(
1551 hostid, CONFIG_PROXYCONFIG_FREQUENCY, now);
1552 proxy->proxy_data_nextcheck = (int)calculate_proxy_nextcheck(
1553 hostid, CONFIG_PROXYDATA_FREQUENCY, now);
1554 proxy->proxy_tasks_nextcheck = (int)calculate_proxy_nextcheck(
1555 hostid, ZBX_TASK_UPDATE_FREQUENCY, now);
1556
1557 DCupdate_proxy_queue(proxy);
1558 }
1559 else if (HOST_STATUS_PROXY_ACTIVE == status && ZBX_LOC_QUEUE == proxy->location)
1560 {
1561 zbx_binary_heap_remove_direct(&config->pqueue, proxy->hostid);
1562 proxy->location = ZBX_LOC_NOWHERE;
1563 }
1564 proxy->last_version_error_time = time(NULL);
1565 }
1566 else if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &hostid)))
1567 DCsync_proxy_remove(proxy);
1568
1569 host->status = status;
1570 }
1571
1572 /* remove deleted hosts from buffer */
1573 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
1574 {
1575 if (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &rowid)))
1576 continue;
1577
1578 hostid = host->hostid;
1579
1580 /* IPMI hosts */
1581
1582 if (NULL != (ipmihost = (ZBX_DC_IPMIHOST *)zbx_hashset_search(&config->ipmihosts, &hostid)))
1583 {
1584 zbx_strpool_release(ipmihost->ipmi_username);
1585 zbx_strpool_release(ipmihost->ipmi_password);
1586
1587 zbx_hashset_remove_direct(&config->ipmihosts, ipmihost);
1588 }
1589
1590 /* proxies */
1591
1592 if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &hostid)))
1593 DCsync_proxy_remove(proxy);
1594
1595 /* hosts */
1596
1597 if (HOST_STATUS_MONITORED == host->status || HOST_STATUS_NOT_MONITORED == host->status)
1598 {
1599 host_h_local.host = host->host;
1600 host_h = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_h, &host_h_local);
1601
1602 if (NULL != host_h && host == host_h->host_ptr) /* see ZBX-4045 for NULL check */
1603 {
1604 zbx_strpool_release(host_h->host);
1605 zbx_hashset_remove_direct(&config->hosts_h, host_h);
1606 }
1607 }
1608 else if (HOST_STATUS_PROXY_ACTIVE == host->status || HOST_STATUS_PROXY_PASSIVE == host->status)
1609 {
1610 host_p_local.host = host->host;
1611 host_p = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_p, &host_p_local);
1612
1613 if (NULL != host_p && host == host_p->host_ptr)
1614 {
1615 zbx_strpool_release(host_p->host);
1616 zbx_hashset_remove_direct(&config->hosts_p, host_p);
1617 }
1618 }
1619
1620 zbx_strpool_release(host->host);
1621 zbx_strpool_release(host->name);
1622
1623 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1624 zbx_strpool_release(host->tls_issuer);
1625 zbx_strpool_release(host->tls_subject);
1626
1627 /* Maintain 'psks' index. Unlink and delete the PSK identity. */
1628 if (NULL != host->tls_dc_psk)
1629 {
1630 psk_i_local.tls_psk_identity = host->tls_dc_psk->tls_psk_identity;
1631
1632 if (NULL != (psk_i = (ZBX_DC_PSK *)zbx_hashset_search(&config->psks, &psk_i_local)) &&
1633 0 == --(psk_i->refcount))
1634 {
1635 zbx_strpool_release(psk_i->tls_psk_identity);
1636 zbx_strpool_release(psk_i->tls_psk);
1637 zbx_hashset_remove_direct(&config->psks, psk_i);
1638 }
1639 }
1640 #endif
1641 zbx_vector_ptr_destroy(&host->interfaces_v);
1642 zbx_hashset_remove_direct(&config->hosts, host);
1643 }
1644
1645 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1646 zbx_hashset_destroy(&psk_owners);
1647 #endif
1648
1649 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1650 }
1651
DCsync_host_inventory(zbx_dbsync_t * sync)1652 static void DCsync_host_inventory(zbx_dbsync_t *sync)
1653 {
1654 ZBX_DC_HOST_INVENTORY *host_inventory, *host_inventory_auto;
1655 zbx_uint64_t rowid, hostid;
1656 int found, ret, i;
1657 char **row;
1658 unsigned char tag;
1659
1660 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1661
1662 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
1663 {
1664 /* removed rows will be always added at the end */
1665 if (ZBX_DBSYNC_ROW_REMOVE == tag)
1666 break;
1667
1668 ZBX_STR2UINT64(hostid, row[0]);
1669
1670 host_inventory = (ZBX_DC_HOST_INVENTORY *)DCfind_id(&config->host_inventories, hostid, sizeof(ZBX_DC_HOST_INVENTORY), &found);
1671
1672 ZBX_STR2UCHAR(host_inventory->inventory_mode, row[1]);
1673
1674 /* store new information in host_inventory structure */
1675 for (i = 0; i < HOST_INVENTORY_FIELD_COUNT; i++)
1676 DCstrpool_replace(found, &(host_inventory->values[i]), row[i + 2]);
1677
1678 host_inventory_auto = (ZBX_DC_HOST_INVENTORY *)DCfind_id(&config->host_inventories_auto, hostid, sizeof(ZBX_DC_HOST_INVENTORY),
1679 &found);
1680
1681 host_inventory_auto->inventory_mode = host_inventory->inventory_mode;
1682
1683 if (1 == found)
1684 {
1685 for (i = 0; i < HOST_INVENTORY_FIELD_COUNT; i++)
1686 {
1687 if (NULL == host_inventory_auto->values[i])
1688 continue;
1689
1690 zbx_strpool_release(host_inventory_auto->values[i]);
1691 host_inventory_auto->values[i] = NULL;
1692 }
1693 }
1694 else
1695 {
1696 for (i = 0; i < HOST_INVENTORY_FIELD_COUNT; i++)
1697 host_inventory_auto->values[i] = NULL;
1698 }
1699 }
1700
1701 /* remove deleted host inventory from cache */
1702 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
1703 {
1704 if (NULL == (host_inventory = (ZBX_DC_HOST_INVENTORY *)zbx_hashset_search(&config->host_inventories, &rowid)))
1705 continue;
1706
1707 for (i = 0; i < HOST_INVENTORY_FIELD_COUNT; i++)
1708 zbx_strpool_release(host_inventory->values[i]);
1709
1710 zbx_hashset_remove_direct(&config->host_inventories, host_inventory);
1711
1712 if (NULL == (host_inventory_auto = (ZBX_DC_HOST_INVENTORY *)zbx_hashset_search(&config->host_inventories_auto, &rowid)))
1713 {
1714 THIS_SHOULD_NEVER_HAPPEN;
1715 continue;
1716 }
1717
1718 for (i = 0; i < HOST_INVENTORY_FIELD_COUNT; i++)
1719 {
1720 if (NULL != host_inventory_auto->values[i])
1721 zbx_strpool_release(host_inventory_auto->values[i]);
1722 }
1723
1724 zbx_hashset_remove_direct(&config->host_inventories_auto, host_inventory_auto);
1725 }
1726
1727 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1728 }
1729
DCsync_htmpls(zbx_dbsync_t * sync)1730 static void DCsync_htmpls(zbx_dbsync_t *sync)
1731 {
1732 char **row;
1733 zbx_uint64_t rowid;
1734 unsigned char tag;
1735
1736 ZBX_DC_HTMPL *htmpl = NULL;
1737
1738 int found, i, index, ret;
1739 zbx_uint64_t _hostid = 0, hostid, templateid;
1740 zbx_vector_ptr_t sort;
1741
1742 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1743
1744 zbx_vector_ptr_create(&sort);
1745
1746 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
1747 {
1748 /* removed rows will be always added at the end */
1749 if (ZBX_DBSYNC_ROW_REMOVE == tag)
1750 break;
1751
1752 ZBX_STR2UINT64(hostid, row[0]);
1753 ZBX_STR2UINT64(templateid, row[1]);
1754
1755 if (_hostid != hostid || 0 == _hostid)
1756 {
1757 _hostid = hostid;
1758
1759 htmpl = (ZBX_DC_HTMPL *)DCfind_id(&config->htmpls, hostid, sizeof(ZBX_DC_HTMPL), &found);
1760
1761 if (0 == found)
1762 {
1763 zbx_vector_uint64_create_ext(&htmpl->templateids,
1764 __config_mem_malloc_func,
1765 __config_mem_realloc_func,
1766 __config_mem_free_func);
1767 zbx_vector_uint64_reserve(&htmpl->templateids, 1);
1768 }
1769
1770 zbx_vector_ptr_append(&sort, htmpl);
1771 }
1772
1773 zbx_vector_uint64_append(&htmpl->templateids, templateid);
1774 }
1775
1776 /* remove deleted host templates from cache */
1777 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
1778 {
1779 ZBX_STR2UINT64(hostid, row[0]);
1780
1781 if (NULL == (htmpl = (ZBX_DC_HTMPL *)zbx_hashset_search(&config->htmpls, &hostid)))
1782 continue;
1783
1784 ZBX_STR2UINT64(templateid, row[1]);
1785
1786 if (-1 == (index = zbx_vector_uint64_search(&htmpl->templateids, templateid,
1787 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
1788 {
1789 continue;
1790 }
1791
1792 if (1 == htmpl->templateids.values_num)
1793 {
1794 zbx_vector_uint64_destroy(&htmpl->templateids);
1795 zbx_hashset_remove_direct(&config->htmpls, htmpl);
1796 }
1797 else
1798 {
1799 zbx_vector_uint64_remove_noorder(&htmpl->templateids, index);
1800 zbx_vector_ptr_append(&sort, htmpl);
1801 }
1802 }
1803
1804 /* sort the changed template lists */
1805
1806 zbx_vector_ptr_sort(&sort, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
1807 zbx_vector_ptr_uniq(&sort, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
1808
1809 for (i = 0; i < sort.values_num; i++)
1810 {
1811 htmpl = (ZBX_DC_HTMPL *)sort.values[i];
1812 zbx_vector_uint64_sort(&htmpl->templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1813 }
1814
1815 zbx_vector_ptr_destroy(&sort);
1816
1817 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1818 }
1819
DCsync_gmacros(zbx_dbsync_t * sync)1820 static void DCsync_gmacros(zbx_dbsync_t *sync)
1821 {
1822 char **row;
1823 zbx_uint64_t rowid;
1824 unsigned char tag, context_op, type;
1825 ZBX_DC_GMACRO *gmacro;
1826 int found, context_existed, update_index, ret, i;
1827 zbx_uint64_t globalmacroid;
1828 char *macro = NULL, *context = NULL, *path = NULL, *key = NULL;
1829 zbx_vector_ptr_t indexes;
1830 ZBX_DC_GMACRO_M *gmacro_m;
1831
1832 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1833
1834 zbx_vector_ptr_create(&indexes);
1835
1836 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
1837 {
1838 /* removed rows will be always added at the end */
1839 if (ZBX_DBSYNC_ROW_REMOVE == tag)
1840 break;
1841
1842 ZBX_STR2UINT64(globalmacroid, row[0]);
1843 ZBX_STR2UCHAR(type, row[3]);
1844
1845 if (SUCCEED != zbx_user_macro_parse_dyn(row[1], ¯o, &context, NULL, &context_op))
1846 {
1847 zabbix_log(LOG_LEVEL_WARNING, "cannot parse user macro \"%s\"", row[1]);
1848 continue;
1849 }
1850
1851 if (ZBX_MACRO_VALUE_VAULT == type)
1852 {
1853 zbx_free(path);
1854 zbx_free(key);
1855 zbx_strsplit(row[2], ':', &path, &key);
1856 if (NULL == key)
1857 {
1858 zabbix_log(LOG_LEVEL_WARNING, "cannot parse user macro \"%s\" Vault location \"%s\":"
1859 " missing separator \":\"", row[1], row[2]);
1860 continue;
1861 }
1862
1863 if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER) && NULL != CONFIG_VAULTDBPATH &&
1864 0 == strcasecmp(CONFIG_VAULTDBPATH, path) &&
1865 (0 == strcasecmp(key, ZBX_PROTO_TAG_PASSWORD)
1866 || 0 == strcasecmp(key, ZBX_PROTO_TAG_USERNAME)))
1867 {
1868 zabbix_log(LOG_LEVEL_WARNING, "cannot parse macro \"%s\" Vault location \"%s\":"
1869 " database credentials should not be used with Vault macros",
1870 row[1], row[2]);
1871 continue;
1872 }
1873 }
1874
1875 gmacro = (ZBX_DC_GMACRO *)DCfind_id(&config->gmacros, globalmacroid, sizeof(ZBX_DC_GMACRO), &found);
1876
1877 /* see whether we should and can update gmacros_m index at this point */
1878 update_index = 0;
1879
1880 if (0 == found || 0 != strcmp(gmacro->macro, macro) || 0 != zbx_strcmp_null(gmacro->context, context) ||
1881 gmacro->context_op != context_op)
1882 {
1883 if (1 == found)
1884 {
1885 gmacro_m = config_gmacro_remove_index(&config->gmacros_m, gmacro);
1886 zbx_vector_ptr_append(&indexes, gmacro_m);
1887 }
1888
1889 update_index = 1;
1890 }
1891
1892 if (0 != found && NULL != gmacro->kv)
1893 config_kvs_path_remove(gmacro->value, gmacro->kv);
1894
1895 if (ZBX_MACRO_VALUE_VAULT == type)
1896 gmacro->kv = config_kvs_path_add(path, key);
1897 else
1898 gmacro->kv = NULL;
1899
1900 /* store new information in macro structure */
1901 gmacro->type = type;
1902 gmacro->context_op = context_op;
1903 DCstrpool_replace(found, &gmacro->macro, macro);
1904 DCstrpool_replace(found, &gmacro->value, row[2]);
1905
1906 context_existed = (1 == found && NULL != gmacro->context);
1907
1908 if (NULL == context)
1909 {
1910 /* release the context if it was removed from the macro */
1911 if (1 == context_existed)
1912 zbx_strpool_release(gmacro->context);
1913
1914 gmacro->context = NULL;
1915 }
1916 else
1917 {
1918 /* replace the existing context (1) or add context to macro (0) */
1919 DCstrpool_replace(context_existed, &gmacro->context, context);
1920 }
1921
1922 /* update gmacros_m index using new data */
1923 if (1 == update_index)
1924 {
1925 gmacro_m = config_gmacro_add_index(&config->gmacros_m, gmacro);
1926 zbx_vector_ptr_append(&indexes, gmacro_m);
1927 }
1928 }
1929
1930 /* remove deleted global macros from cache */
1931 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
1932 {
1933 if (NULL == (gmacro = (ZBX_DC_GMACRO *)zbx_hashset_search(&config->gmacros, &rowid)))
1934 continue;
1935
1936 if (NULL != gmacro->kv)
1937 config_kvs_path_remove(gmacro->value, gmacro->kv);
1938
1939 gmacro_m = config_gmacro_remove_index(&config->gmacros_m, gmacro);
1940 zbx_vector_ptr_append(&indexes, gmacro_m);
1941
1942 zbx_strpool_release(gmacro->macro);
1943 zbx_strpool_release(gmacro->value);
1944
1945 if (NULL != gmacro->context)
1946 zbx_strpool_release(gmacro->context);
1947
1948 zbx_hashset_remove_direct(&config->gmacros, gmacro);
1949 }
1950
1951 zbx_vector_ptr_sort(&indexes, ZBX_DEFAULT_PTR_COMPARE_FUNC);
1952 zbx_vector_ptr_uniq(&indexes, ZBX_DEFAULT_PTR_COMPARE_FUNC);
1953
1954 for (i = 0; i < indexes.values_num; i++)
1955 {
1956 gmacro_m = (ZBX_DC_GMACRO_M *)indexes.values[i];
1957 if (0 == gmacro_m->gmacros.values_num)
1958 {
1959 zbx_strpool_release(gmacro_m->macro);
1960 zbx_vector_ptr_destroy(&gmacro_m->gmacros);
1961 zbx_hashset_remove_direct(&config->gmacros_m, gmacro_m);
1962 }
1963 else
1964 zbx_vector_ptr_sort(&gmacro_m->gmacros, config_gmacro_context_compare);
1965 }
1966
1967 zbx_free(key);
1968 zbx_free(path);
1969 zbx_free(context);
1970 zbx_free(macro);
1971 zbx_vector_ptr_destroy(&indexes);
1972
1973 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1974 }
1975
DCsync_hmacros(zbx_dbsync_t * sync)1976 static void DCsync_hmacros(zbx_dbsync_t *sync)
1977 {
1978 char **row;
1979 zbx_uint64_t rowid;
1980 unsigned char tag, context_op, type;
1981 ZBX_DC_HMACRO *hmacro;
1982 int found, context_existed, update_index, ret, i;
1983 zbx_uint64_t hostmacroid, hostid;
1984 char *macro = NULL, *context = NULL, *path = NULL, *key = NULL;
1985 zbx_vector_ptr_t indexes;
1986 ZBX_DC_HMACRO_HM *hmacro_hm;
1987
1988 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1989
1990 zbx_vector_ptr_create(&indexes);
1991
1992 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
1993 {
1994 /* removed rows will be always added at the end */
1995 if (ZBX_DBSYNC_ROW_REMOVE == tag)
1996 break;
1997
1998 ZBX_STR2UINT64(hostmacroid, row[0]);
1999 ZBX_STR2UINT64(hostid, row[1]);
2000 ZBX_STR2UCHAR(type, row[4]);
2001
2002 if (SUCCEED != zbx_user_macro_parse_dyn(row[2], ¯o, &context, NULL, &context_op))
2003 {
2004 zabbix_log(LOG_LEVEL_WARNING, "cannot parse host \"%s\" macro \"%s\"", row[1], row[2]);
2005 continue;
2006 }
2007
2008 if (ZBX_MACRO_VALUE_VAULT == type)
2009 {
2010 zbx_free(path);
2011 zbx_free(key);
2012 zbx_strsplit(row[3], ':', &path, &key);
2013 if (NULL == key)
2014 {
2015 zabbix_log(LOG_LEVEL_WARNING, "cannot parse host \"%s\" macro \"%s\" Vault location"
2016 " \"%s\": missing separator \":\"", row[1], row[2], row[3]);
2017 continue;
2018 }
2019
2020 if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER) && NULL != CONFIG_VAULTDBPATH &&
2021 0 == strcasecmp(CONFIG_VAULTDBPATH, path) &&
2022 (0 == strcasecmp(key, ZBX_PROTO_TAG_PASSWORD)
2023 || 0 == strcasecmp(key, ZBX_PROTO_TAG_USERNAME)))
2024 {
2025 zabbix_log(LOG_LEVEL_WARNING, "cannot parse host \"%s\" macro \"%s\" Vault location"
2026 " \"%s\": database credentials should not be used with Vault macros",
2027 row[1], row[2], row[3]);
2028 continue;
2029 }
2030 }
2031
2032 hmacro = (ZBX_DC_HMACRO *)DCfind_id(&config->hmacros, hostmacroid, sizeof(ZBX_DC_HMACRO), &found);
2033
2034 /* see whether we should and can update hmacros_hm index at this point */
2035 update_index = 0;
2036
2037 if (0 == found || hmacro->hostid != hostid || 0 != strcmp(hmacro->macro, macro) ||
2038 0 != zbx_strcmp_null(hmacro->context, context) || hmacro->context_op != context_op)
2039 {
2040 if (1 == found)
2041 {
2042 hmacro_hm = config_hmacro_remove_index(&config->hmacros_hm, hmacro);
2043 zbx_vector_ptr_append(&indexes, hmacro_hm);
2044 }
2045
2046 update_index = 1;
2047 }
2048
2049 if (0 != found && NULL != hmacro->kv)
2050 config_kvs_path_remove(hmacro->value, hmacro->kv);
2051
2052 if (ZBX_MACRO_VALUE_VAULT == type)
2053 hmacro->kv = config_kvs_path_add(path, key);
2054 else
2055 hmacro->kv = NULL;
2056
2057 /* store new information in macro structure */
2058 hmacro->hostid = hostid;
2059 hmacro->type = type;
2060 hmacro->context_op = context_op;
2061 DCstrpool_replace(found, &hmacro->macro, macro);
2062 DCstrpool_replace(found, &hmacro->value, row[3]);
2063
2064 context_existed = (1 == found && NULL != hmacro->context);
2065
2066 if (NULL == context)
2067 {
2068 /* release the context if it was removed from the macro */
2069 if (1 == context_existed)
2070 zbx_strpool_release(hmacro->context);
2071
2072 hmacro->context = NULL;
2073 }
2074 else
2075 {
2076 /* replace the existing context (1) or add context to macro (0) */
2077 DCstrpool_replace(context_existed, &hmacro->context, context);
2078 }
2079
2080 /* update hmacros_hm index using new data */
2081 if (1 == update_index)
2082 {
2083 hmacro_hm = config_hmacro_add_index(&config->hmacros_hm, hmacro);
2084 zbx_vector_ptr_append(&indexes, hmacro_hm);
2085 }
2086 }
2087
2088 /* remove deleted host macros from buffer */
2089 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
2090 {
2091 if (NULL == (hmacro = (ZBX_DC_HMACRO *)zbx_hashset_search(&config->hmacros, &rowid)))
2092 continue;
2093
2094 if (NULL != hmacro->kv)
2095 config_kvs_path_remove(hmacro->value, hmacro->kv);
2096
2097 hmacro_hm = config_hmacro_remove_index(&config->hmacros_hm, hmacro);
2098 zbx_vector_ptr_append(&indexes, hmacro_hm);
2099
2100 zbx_strpool_release(hmacro->macro);
2101 zbx_strpool_release(hmacro->value);
2102
2103 if (NULL != hmacro->context)
2104 zbx_strpool_release(hmacro->context);
2105
2106 zbx_hashset_remove_direct(&config->hmacros, hmacro);
2107 }
2108
2109 zbx_vector_ptr_sort(&indexes, ZBX_DEFAULT_PTR_COMPARE_FUNC);
2110 zbx_vector_ptr_uniq(&indexes, ZBX_DEFAULT_PTR_COMPARE_FUNC);
2111
2112 for (i = 0; i < indexes.values_num; i++)
2113 {
2114 hmacro_hm = (ZBX_DC_HMACRO_HM *)indexes.values[i];
2115 if (0 == hmacro_hm->hmacros.values_num)
2116 {
2117 zbx_strpool_release(hmacro_hm->macro);
2118 zbx_vector_ptr_destroy(&hmacro_hm->hmacros);
2119 zbx_hashset_remove_direct(&config->hmacros_hm, hmacro_hm);
2120 }
2121 else
2122 zbx_vector_ptr_sort(&hmacro_hm->hmacros, config_hmacro_context_compare);
2123 }
2124
2125 zbx_free(key);
2126 zbx_free(path);
2127 zbx_free(context);
2128 zbx_free(macro);
2129 zbx_vector_ptr_destroy(&indexes);
2130
2131 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
2132 }
2133
DCsync_kvs_paths(const struct zbx_json_parse * jp_kvs_paths)2134 static int DCsync_kvs_paths(const struct zbx_json_parse *jp_kvs_paths)
2135 {
2136 zbx_dc_kvs_path_t *dc_kvs_path;
2137 zbx_dc_kv_t *dc_kv;
2138 zbx_hashset_t kvs;
2139 zbx_hashset_iter_t iter;
2140 int i, j, ret;
2141 zbx_vector_ptr_pair_t diff;
2142
2143 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
2144
2145 zbx_vector_ptr_pair_create(&diff);
2146 zbx_hashset_create_ext(&kvs, 100, zbx_vault_kv_hash, zbx_vault_kv_compare, zbx_vault_kv_clean,
2147 ZBX_DEFAULT_MEM_MALLOC_FUNC, ZBX_DEFAULT_MEM_REALLOC_FUNC, ZBX_DEFAULT_MEM_FREE_FUNC);
2148
2149 for (i = 0; i < config->kvs_paths.values_num; i++)
2150 {
2151 char *error = NULL;
2152
2153 dc_kvs_path = (zbx_dc_kvs_path_t *)config->kvs_paths.values[i];
2154
2155 if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER))
2156 {
2157 if (NULL == jp_kvs_paths)
2158 {
2159 ret = FAIL;
2160 goto fail;
2161 }
2162
2163 if (FAIL == zbx_vault_json_kvs_get(dc_kvs_path->path, jp_kvs_paths, &kvs, &error))
2164 {
2165 zabbix_log(LOG_LEVEL_WARNING, "cannot get secrets for path \"%s\": %s",
2166 dc_kvs_path->path, error);
2167 zbx_free(error);
2168 continue;
2169 }
2170
2171 }
2172 else if (FAIL == zbx_vault_kvs_get(dc_kvs_path->path, &kvs, &error))
2173 {
2174 zabbix_log(LOG_LEVEL_WARNING, "cannot get secrets for path \"%s\": %s", dc_kvs_path->path, error);
2175 zbx_free(error);
2176 continue;
2177 }
2178
2179 zbx_hashset_iter_reset(&dc_kvs_path->kvs, &iter);
2180 while (NULL != (dc_kv = (zbx_dc_kv_t *)zbx_hashset_iter_next(&iter)))
2181 {
2182 zbx_kv_t *kv, kv_local;
2183 zbx_ptr_pair_t pair;
2184
2185 kv_local.key = (char *)dc_kv->key;
2186 if (NULL != (kv = zbx_hashset_search(&kvs, &kv_local)))
2187 {
2188 if (0 == zbx_strcmp_null(dc_kv->value, kv->value))
2189 continue;
2190 }
2191 else if (NULL == dc_kv->value)
2192 continue;
2193
2194 pair.first = dc_kv;
2195 pair.second = kv;
2196 zbx_vector_ptr_pair_append(&diff, pair);
2197 }
2198
2199 if (0 != diff.values_num)
2200 {
2201 START_SYNC;
2202
2203 for (j = 0; j < diff.values_num; j++)
2204 {
2205 zbx_kv_t *kv;
2206
2207 dc_kv = (zbx_dc_kv_t *)diff.values[j].first;
2208 kv = (zbx_kv_t *)diff.values[j].second;
2209
2210 if (NULL != kv)
2211 {
2212 DCstrpool_replace(dc_kv->value != NULL ? 1 : 0, &dc_kv->value, kv->value);
2213 continue;
2214 }
2215
2216 zbx_strpool_release(dc_kv->value);
2217 dc_kv->value = NULL;
2218 }
2219
2220 FINISH_SYNC;
2221 }
2222
2223 zbx_vector_ptr_pair_clear(&diff);
2224 zbx_hashset_clear(&kvs);
2225 }
2226 ret = SUCCEED;
2227 fail:
2228 zbx_vector_ptr_pair_destroy(&diff);
2229 zbx_hashset_destroy(&kvs);
2230 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
2231
2232 return ret;
2233 }
2234
2235 /******************************************************************************
2236 * *
2237 * Function: substitute_host_interface_macros *
2238 * *
2239 * Purpose: trying to resolve the macros in host interface *
2240 * *
2241 ******************************************************************************/
substitute_host_interface_macros(ZBX_DC_INTERFACE * interface)2242 static void substitute_host_interface_macros(ZBX_DC_INTERFACE *interface)
2243 {
2244 int macros;
2245 char *addr;
2246 DC_HOST host;
2247
2248 macros = STR_CONTAINS_MACROS(interface->ip) ? 0x01 : 0;
2249 macros |= STR_CONTAINS_MACROS(interface->dns) ? 0x02 : 0;
2250
2251 if (0 != macros)
2252 {
2253 DCget_host_by_hostid(&host, interface->hostid);
2254
2255 if (0 != (macros & 0x01))
2256 {
2257 addr = zbx_strdup(NULL, interface->ip);
2258 substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, &host, NULL, NULL, NULL, NULL,
2259 &addr, MACRO_TYPE_INTERFACE_ADDR, NULL, 0);
2260 if (SUCCEED == is_ip(addr) || SUCCEED == zbx_validate_hostname(addr))
2261 DCstrpool_replace(1, &interface->ip, addr);
2262 zbx_free(addr);
2263 }
2264
2265 if (0 != (macros & 0x02))
2266 {
2267 addr = zbx_strdup(NULL, interface->dns);
2268 substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, &host, NULL, NULL, NULL, NULL,
2269 &addr, MACRO_TYPE_INTERFACE_ADDR, NULL, 0);
2270 if (SUCCEED == is_ip(addr) || SUCCEED == zbx_validate_hostname(addr))
2271 DCstrpool_replace(1, &interface->dns, addr);
2272 zbx_free(addr);
2273 }
2274 }
2275 }
2276
2277 /******************************************************************************
2278 * *
2279 * Function: dc_interface_snmpaddrs_remove *
2280 * *
2281 * Purpose: remove interface from SNMP address -> interfaceid index *
2282 * *
2283 * Parameters: interface - [IN] the interface *
2284 * *
2285 ******************************************************************************/
dc_interface_snmpaddrs_remove(ZBX_DC_INTERFACE * interface)2286 static void dc_interface_snmpaddrs_remove(ZBX_DC_INTERFACE *interface)
2287 {
2288 ZBX_DC_INTERFACE_ADDR *ifaddr, ifaddr_local;
2289 int index;
2290
2291 ifaddr_local.addr = (0 != interface->useip ? interface->ip : interface->dns);
2292
2293 if ('\0' == *ifaddr_local.addr)
2294 return;
2295
2296 if (NULL == (ifaddr = (ZBX_DC_INTERFACE_ADDR *)zbx_hashset_search(&config->interface_snmpaddrs, &ifaddr_local)))
2297 return;
2298
2299 if (FAIL == (index = zbx_vector_uint64_search(&ifaddr->interfaceids, interface->interfaceid,
2300 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2301 {
2302 return;
2303 }
2304
2305 zbx_vector_uint64_remove_noorder(&ifaddr->interfaceids, index);
2306
2307 if (0 == ifaddr->interfaceids.values_num)
2308 {
2309 zbx_strpool_release(ifaddr->addr);
2310 zbx_vector_uint64_destroy(&ifaddr->interfaceids);
2311 zbx_hashset_remove_direct(&config->interface_snmpaddrs, ifaddr);
2312 }
2313 }
2314
2315 /******************************************************************************
2316 * *
2317 * Function: dc_interface_snmp_set *
2318 * *
2319 * Purpose: setup SNMP attributes for interface with interfaceid index *
2320 * *
2321 * Parameters: interface - [IN] the interface *
2322 * row - [IN] the row data from DB *
2323 *
2324 * *
2325 ******************************************************************************/
dc_interface_snmp_set(zbx_uint64_t interfaceid,const char ** row,unsigned char * bulk_changed)2326 static ZBX_DC_SNMPINTERFACE *dc_interface_snmp_set(zbx_uint64_t interfaceid, const char **row,
2327 unsigned char *bulk_changed)
2328 {
2329 int found;
2330 ZBX_DC_SNMPINTERFACE *snmp;
2331 unsigned char bulk;
2332
2333 snmp = (ZBX_DC_SNMPINTERFACE *)DCfind_id(&config->interfaces_snmp, interfaceid, sizeof(ZBX_DC_SNMPINTERFACE),
2334 &found);
2335
2336 ZBX_STR2UCHAR(bulk, row[13]);
2337
2338 if (0 == found)
2339 *bulk_changed = 1;
2340 else if (snmp->bulk != bulk)
2341 *bulk_changed = 1;
2342 else
2343 *bulk_changed = 0;
2344
2345 if (0 != *bulk_changed)
2346 snmp->bulk = bulk;
2347
2348 ZBX_STR2UCHAR(snmp->version, row[12]);
2349 DCstrpool_replace(found, &snmp->community, row[14]);
2350 DCstrpool_replace(found, &snmp->securityname, row[15]);
2351 ZBX_STR2UCHAR(snmp->securitylevel, row[16]);
2352 DCstrpool_replace(found, &snmp->authpassphrase, row[17]);
2353 DCstrpool_replace(found, &snmp->privpassphrase, row[18]);
2354 ZBX_STR2UCHAR(snmp->authprotocol, row[19]);
2355 ZBX_STR2UCHAR(snmp->privprotocol, row[20]);
2356 DCstrpool_replace(found, &snmp->contextname, row[21]);
2357
2358 return snmp;
2359 }
2360
2361 /******************************************************************************
2362 * *
2363 * Function: dc_interface_snmp_remove *
2364 * *
2365 * Purpose: remove interface from SNMP address -> interfaceid index *
2366 * *
2367 * Parameters: interface - [IN] the interface *
2368 * *
2369 ******************************************************************************/
dc_interface_snmp_remove(zbx_uint64_t interfaceid)2370 static void dc_interface_snmp_remove(zbx_uint64_t interfaceid)
2371 {
2372 ZBX_DC_SNMPINTERFACE *snmp;
2373
2374 if (NULL == (snmp = (ZBX_DC_SNMPINTERFACE *)zbx_hashset_search(&config->interfaces_snmp, &interfaceid)))
2375 return;
2376
2377 zbx_strpool_release(snmp->community);
2378 zbx_strpool_release(snmp->securityname);
2379 zbx_strpool_release(snmp->authpassphrase);
2380 zbx_strpool_release(snmp->privpassphrase);
2381 zbx_strpool_release(snmp->contextname);
2382
2383 zbx_hashset_remove_direct(&config->interfaces_snmp, snmp);
2384
2385 return;
2386 }
2387
DCsync_interfaces(zbx_dbsync_t * sync)2388 static void DCsync_interfaces(zbx_dbsync_t *sync)
2389 {
2390 char **row;
2391 zbx_uint64_t rowid;
2392 unsigned char tag;
2393
2394 ZBX_DC_INTERFACE *interface;
2395 ZBX_DC_INTERFACE_HT *interface_ht, interface_ht_local;
2396 ZBX_DC_INTERFACE_ADDR *interface_snmpaddr, interface_snmpaddr_local;
2397 ZBX_DC_HOST *host;
2398
2399 int found, update_index, ret, i;
2400 zbx_uint64_t interfaceid, hostid;
2401 unsigned char type, main_, useip;
2402 unsigned char reset_snmp_stats;
2403 zbx_vector_ptr_t interfaces;
2404
2405 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
2406
2407 zbx_vector_ptr_create(&interfaces);
2408
2409 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
2410 {
2411 /* removed rows will be always added at the end */
2412 if (ZBX_DBSYNC_ROW_REMOVE == tag)
2413 break;
2414
2415 ZBX_STR2UINT64(interfaceid, row[0]);
2416 ZBX_STR2UINT64(hostid, row[1]);
2417 ZBX_STR2UCHAR(type, row[2]);
2418 ZBX_STR2UCHAR(main_, row[3]);
2419 ZBX_STR2UCHAR(useip, row[4]);
2420
2421 /* If there is no host for this interface, skip it. */
2422 /* This may be possible if the host was added after we synced config for hosts. */
2423 if (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)))
2424 continue;
2425
2426 interface = (ZBX_DC_INTERFACE *)DCfind_id(&config->interfaces, interfaceid, sizeof(ZBX_DC_INTERFACE), &found);
2427 zbx_vector_ptr_append(&interfaces, interface);
2428
2429 /* remove old address->interfaceid index */
2430 if (0 != found && INTERFACE_TYPE_SNMP == interface->type)
2431 dc_interface_snmpaddrs_remove(interface);
2432
2433 /* see whether we should and can update interfaces_ht index at this point */
2434
2435 update_index = 0;
2436
2437 if (0 == found || interface->hostid != hostid || interface->type != type || interface->main != main_)
2438 {
2439 if (1 == found && 1 == interface->main)
2440 {
2441 interface_ht_local.hostid = interface->hostid;
2442 interface_ht_local.type = interface->type;
2443 interface_ht = (ZBX_DC_INTERFACE_HT *)zbx_hashset_search(&config->interfaces_ht, &interface_ht_local);
2444
2445 if (NULL != interface_ht && interface == interface_ht->interface_ptr)
2446 {
2447 /* see ZBX-4045 for NULL check in the conditional */
2448 zbx_hashset_remove(&config->interfaces_ht, &interface_ht_local);
2449 }
2450 }
2451
2452 if (1 == main_)
2453 {
2454 interface_ht_local.hostid = hostid;
2455 interface_ht_local.type = type;
2456 interface_ht = (ZBX_DC_INTERFACE_HT *)zbx_hashset_search(&config->interfaces_ht, &interface_ht_local);
2457
2458 if (NULL != interface_ht)
2459 interface_ht->interface_ptr = interface;
2460 else
2461 update_index = 1;
2462 }
2463 }
2464
2465 /* store new information in interface structure */
2466
2467 reset_snmp_stats = (0 == found || interface->hostid != hostid || interface->type != type ||
2468 interface->useip != useip);
2469
2470 interface->hostid = hostid;
2471 interface->type = type;
2472 interface->main = main_;
2473 interface->useip = useip;
2474 reset_snmp_stats |= (SUCCEED == DCstrpool_replace(found, &interface->ip, row[5]));
2475 reset_snmp_stats |= (SUCCEED == DCstrpool_replace(found, &interface->dns, row[6]));
2476 reset_snmp_stats |= (SUCCEED == DCstrpool_replace(found, &interface->port, row[7]));
2477 reset_snmp_stats |= (SUCCEED == DCstrpool_replace(found, &interface->error, row[10]));
2478
2479 if (0 == found)
2480 {
2481 interface->errors_from = atoi(row[11]);
2482 interface->available = (unsigned char)atoi(row[8]);
2483 interface->disable_until = atoi(row[9]);
2484 interface->availability_ts = time(NULL);
2485 interface->reset_availability = 0;
2486 interface->items_num = 0;
2487 }
2488
2489 /* update interfaces_ht index using new data, if not done already */
2490
2491 if (1 == update_index)
2492 {
2493 interface_ht_local.hostid = interface->hostid;
2494 interface_ht_local.type = interface->type;
2495 interface_ht_local.interface_ptr = interface;
2496 zbx_hashset_insert(&config->interfaces_ht, &interface_ht_local, sizeof(ZBX_DC_INTERFACE_HT));
2497 }
2498
2499 /* update interface_snmpaddrs for SNMP traps or reset bulk request statistics */
2500
2501 if (INTERFACE_TYPE_SNMP == interface->type)
2502 {
2503 ZBX_DC_SNMPINTERFACE *snmp;
2504 unsigned char bulk_changed;
2505
2506 interface_snmpaddr_local.addr = (0 != interface->useip ? interface->ip : interface->dns);
2507
2508 if ('\0' != *interface_snmpaddr_local.addr)
2509 {
2510 if (NULL == (interface_snmpaddr = (ZBX_DC_INTERFACE_ADDR *)zbx_hashset_search(&config->interface_snmpaddrs,
2511 &interface_snmpaddr_local)))
2512 {
2513 zbx_strpool_acquire(interface_snmpaddr_local.addr);
2514
2515 interface_snmpaddr = (ZBX_DC_INTERFACE_ADDR *)zbx_hashset_insert(&config->interface_snmpaddrs,
2516 &interface_snmpaddr_local, sizeof(ZBX_DC_INTERFACE_ADDR));
2517 zbx_vector_uint64_create_ext(&interface_snmpaddr->interfaceids,
2518 __config_mem_malloc_func,
2519 __config_mem_realloc_func,
2520 __config_mem_free_func);
2521 }
2522
2523 zbx_vector_uint64_append(&interface_snmpaddr->interfaceids, interfaceid);
2524 }
2525
2526 if (FAIL == DBis_null(row[12]))
2527 {
2528 snmp = dc_interface_snmp_set(interfaceid, (const char **)row, &bulk_changed);
2529
2530 if (1 == reset_snmp_stats || 0 != bulk_changed)
2531 {
2532 snmp->max_succeed = 0;
2533 snmp->min_fail = MAX_SNMP_ITEMS + 1;
2534 }
2535 }
2536 else
2537 THIS_SHOULD_NEVER_HAPPEN;
2538 }
2539
2540 /* first resolve macros for ip and dns fields in main agent interface */
2541 /* because other interfaces might reference main interfaces ip and dns */
2542 /* with {HOST.IP} and {HOST.DNS} macros */
2543 if (1 == interface->main && INTERFACE_TYPE_AGENT == interface->type)
2544 substitute_host_interface_macros(interface);
2545
2546 if (0 == found)
2547 {
2548 /* new interface - add it to a list of host interfaces in 'config->hosts' hashset */
2549
2550 int exists = 0;
2551
2552 /* It is an error if the pointer is already in the list. Detect it. */
2553
2554 for (i = 0; i < host->interfaces_v.values_num; i++)
2555 {
2556 if (interface == host->interfaces_v.values[i])
2557 {
2558 exists = 1;
2559 break;
2560 }
2561 }
2562
2563 if (0 == exists)
2564 zbx_vector_ptr_append(&host->interfaces_v, interface);
2565 else
2566 THIS_SHOULD_NEVER_HAPPEN;
2567 }
2568 }
2569
2570 /* resolve macros in other interfaces */
2571
2572 for (i = 0; i < interfaces.values_num; i++)
2573 {
2574 interface = (ZBX_DC_INTERFACE *)interfaces.values[i];
2575
2576 if (1 != interface->main || INTERFACE_TYPE_AGENT != interface->type)
2577 substitute_host_interface_macros(interface);
2578 }
2579
2580 /* remove deleted interfaces from buffer */
2581
2582 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
2583 {
2584 if (NULL == (interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces, &rowid)))
2585 continue;
2586
2587 /* remove interface from the list of host interfaces in 'config->hosts' hashset */
2588
2589 if (NULL != (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &interface->hostid)))
2590 {
2591 for (i = 0; i < host->interfaces_v.values_num; i++)
2592 {
2593 if (interface == host->interfaces_v.values[i])
2594 {
2595 zbx_vector_ptr_remove(&host->interfaces_v, i);
2596 break;
2597 }
2598 }
2599 }
2600
2601 if (INTERFACE_TYPE_SNMP == interface->type)
2602 {
2603 dc_interface_snmpaddrs_remove(interface);
2604 dc_interface_snmp_remove(interface->interfaceid);
2605 }
2606
2607 if (1 == interface->main)
2608 {
2609 interface_ht_local.hostid = interface->hostid;
2610 interface_ht_local.type = interface->type;
2611 interface_ht = (ZBX_DC_INTERFACE_HT *)zbx_hashset_search(&config->interfaces_ht, &interface_ht_local);
2612
2613 if (NULL != interface_ht && interface == interface_ht->interface_ptr)
2614 {
2615 /* see ZBX-4045 for NULL check in the conditional */
2616 zbx_hashset_remove(&config->interfaces_ht, &interface_ht_local);
2617 }
2618 }
2619
2620 zbx_strpool_release(interface->ip);
2621 zbx_strpool_release(interface->dns);
2622 zbx_strpool_release(interface->port);
2623 zbx_strpool_release(interface->error);
2624
2625 zbx_hashset_remove_direct(&config->interfaces, interface);
2626 }
2627
2628 zbx_vector_ptr_destroy(&interfaces);
2629
2630 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
2631 }
2632
2633 /******************************************************************************
2634 * *
2635 * Function: dc_interface_snmpitems_remove *
2636 * *
2637 * Purpose: remove item from interfaceid -> itemid index *
2638 * *
2639 * Parameters: interface - [IN] the item *
2640 * *
2641 ******************************************************************************/
dc_interface_snmpitems_remove(ZBX_DC_ITEM * item)2642 static void dc_interface_snmpitems_remove(ZBX_DC_ITEM *item)
2643 {
2644 ZBX_DC_INTERFACE_ITEM *ifitem;
2645 int index;
2646 zbx_uint64_t interfaceid;
2647
2648 if (0 == (interfaceid = item->interfaceid))
2649 return;
2650
2651 if (NULL == (ifitem = (ZBX_DC_INTERFACE_ITEM *)zbx_hashset_search(&config->interface_snmpitems, &interfaceid)))
2652 return;
2653
2654 if (FAIL == (index = zbx_vector_uint64_search(&ifitem->itemids, item->itemid, ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2655 return;
2656
2657 zbx_vector_uint64_remove_noorder(&ifitem->itemids, index);
2658
2659 if (0 == ifitem->itemids.values_num)
2660 {
2661 zbx_vector_uint64_destroy(&ifitem->itemids);
2662 zbx_hashset_remove_direct(&config->interface_snmpitems, ifitem);
2663 }
2664 }
2665
2666 /******************************************************************************
2667 * *
2668 * Function: dc_masteritem_remove_depitem *
2669 * *
2670 * Purpose: remove itemid from master item dependent itemid vector *
2671 * *
2672 * Parameters: master_itemid - [IN] the master item identifier *
2673 * dep_itemid - [IN] the dependent item identifier *
2674 * *
2675 ******************************************************************************/
dc_masteritem_remove_depitem(zbx_uint64_t master_itemid,zbx_uint64_t dep_itemid)2676 static void dc_masteritem_remove_depitem(zbx_uint64_t master_itemid, zbx_uint64_t dep_itemid)
2677 {
2678 ZBX_DC_MASTERITEM *masteritem;
2679 int index;
2680 zbx_uint64_pair_t pair;
2681
2682 if (NULL == (masteritem = (ZBX_DC_MASTERITEM *)zbx_hashset_search(&config->masteritems, &master_itemid)))
2683 return;
2684
2685 pair.first = dep_itemid;
2686 if (FAIL == (index = zbx_vector_uint64_pair_search(&masteritem->dep_itemids, pair,
2687 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2688 {
2689 return;
2690 }
2691
2692 zbx_vector_uint64_pair_remove_noorder(&masteritem->dep_itemids, index);
2693
2694 if (0 == masteritem->dep_itemids.values_num)
2695 {
2696 zbx_vector_uint64_pair_destroy(&masteritem->dep_itemids);
2697 zbx_hashset_remove_direct(&config->masteritems, masteritem);
2698 }
2699 }
2700
2701 /******************************************************************************
2702 * *
2703 * Function: dc_interface_update_agent_stats *
2704 * *
2705 * Purpose: update number of items per agent statistics *
2706 * *
2707 * Parameters: interface - [IN/OUT] the interface *
2708 * * type - [IN] the item type (ITEM_TYPE_*) *
2709 * num - [IN] the number of items (+) added, (-) removed *
2710 * *
2711 ******************************************************************************/
dc_interface_update_agent_stats(ZBX_DC_INTERFACE * interface,unsigned char type,int num)2712 static void dc_interface_update_agent_stats(ZBX_DC_INTERFACE *interface, unsigned char type, int num)
2713 {
2714 if ((NULL != interface) && ((ITEM_TYPE_ZABBIX == type && INTERFACE_TYPE_AGENT == interface->type) ||
2715 (ITEM_TYPE_SNMP == type && INTERFACE_TYPE_SNMP == interface->type) ||
2716 (ITEM_TYPE_JMX == type && INTERFACE_TYPE_JMX == interface->type) ||
2717 (ITEM_TYPE_IPMI == type && INTERFACE_TYPE_IPMI == interface->type)))
2718 interface->items_num += num;
2719 }
2720
dup_serialized_expression(const unsigned char * src)2721 static unsigned char *dup_serialized_expression(const unsigned char *src)
2722 {
2723 zbx_uint32_t offset, len;
2724 unsigned char *dst;
2725
2726 if (NULL == src || '\0' == *src)
2727 return NULL;
2728
2729 offset = zbx_deserialize_uint31_compact(src, &len);
2730 if (0 == len)
2731 return NULL;
2732
2733 dst = (unsigned char *)zbx_malloc(NULL, offset + len);
2734 memcpy(dst, src, offset + len);
2735
2736 return dst;
2737 }
2738
config_decode_serialized_expression(const char * src)2739 static unsigned char *config_decode_serialized_expression(const char *src)
2740 {
2741 unsigned char *dst;
2742 int data_len, src_len;
2743
2744 if (NULL == src || '\0' == *src)
2745 return NULL;
2746
2747 src_len = strlen(src) * 3 / 4;
2748 dst = __config_mem_malloc_func(NULL, src_len);
2749 str_base64_decode(src, (char *)dst, src_len, &data_len);
2750
2751 return dst;
2752 }
2753
DCsync_items(zbx_dbsync_t * sync,int flags)2754 static void DCsync_items(zbx_dbsync_t *sync, int flags)
2755 {
2756 char **row;
2757 zbx_uint64_t rowid;
2758 unsigned char tag;
2759
2760 ZBX_DC_HOST *host;
2761
2762 ZBX_DC_ITEM *item;
2763 ZBX_DC_NUMITEM *numitem;
2764 ZBX_DC_SNMPITEM *snmpitem;
2765 ZBX_DC_IPMIITEM *ipmiitem;
2766 ZBX_DC_TRAPITEM *trapitem;
2767 ZBX_DC_DEPENDENTITEM *depitem;
2768 ZBX_DC_LOGITEM *logitem;
2769 ZBX_DC_DBITEM *dbitem;
2770 ZBX_DC_SSHITEM *sshitem;
2771 ZBX_DC_TELNETITEM *telnetitem;
2772 ZBX_DC_SIMPLEITEM *simpleitem;
2773 ZBX_DC_JMXITEM *jmxitem;
2774 ZBX_DC_CALCITEM *calcitem;
2775 ZBX_DC_INTERFACE_ITEM *interface_snmpitem;
2776 ZBX_DC_MASTERITEM *master;
2777 ZBX_DC_PREPROCITEM *preprocitem;
2778 ZBX_DC_HTTPITEM *httpitem;
2779 ZBX_DC_SCRIPTITEM *scriptitem;
2780 ZBX_DC_ITEM_HK *item_hk, item_hk_local;
2781 ZBX_DC_INTERFACE *interface;
2782
2783 time_t now;
2784 unsigned char status, type, value_type, old_poller_type;
2785 int found, update_index, ret, i, old_nextcheck;
2786 zbx_uint64_t itemid, hostid, interfaceid;
2787 zbx_vector_ptr_t dep_items;
2788
2789 zbx_vector_ptr_create(&dep_items);
2790
2791 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
2792
2793 now = time(NULL);
2794
2795 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
2796 {
2797 /* removed rows will be always added at the end */
2798 if (ZBX_DBSYNC_ROW_REMOVE == tag)
2799 break;
2800
2801 ZBX_STR2UINT64(itemid, row[0]);
2802 ZBX_STR2UINT64(hostid, row[1]);
2803 ZBX_STR2UCHAR(status, row[2]);
2804 ZBX_STR2UCHAR(type, row[3]);
2805
2806 if (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)))
2807 continue;
2808
2809 item = (ZBX_DC_ITEM *)DCfind_id(&config->items, itemid, sizeof(ZBX_DC_ITEM), &found);
2810
2811 /* template item */
2812 ZBX_DBROW2UINT64(item->templateid, row[48]);
2813
2814 /* LLD item prototype */
2815 ZBX_DBROW2UINT64(item->parent_itemid, row[49]);
2816
2817 if (0 != found && ITEM_TYPE_SNMPTRAP == item->type)
2818 dc_interface_snmpitems_remove(item);
2819
2820 /* see whether we should and can update items_hk index at this point */
2821
2822 update_index = 0;
2823
2824 if (0 == found || item->hostid != hostid || 0 != strcmp(item->key, row[5]))
2825 {
2826 if (1 == found)
2827 {
2828 item_hk_local.hostid = item->hostid;
2829 item_hk_local.key = item->key;
2830
2831 if (NULL == (item_hk = (ZBX_DC_ITEM_HK *)zbx_hashset_search(&config->items_hk,
2832 &item_hk_local)))
2833 {
2834 /* item keys should be unique for items within a host, otherwise items with */
2835 /* same key share index and removal of last added item already cleared index */
2836 THIS_SHOULD_NEVER_HAPPEN;
2837 }
2838 else if (item == item_hk->item_ptr)
2839 {
2840 zbx_strpool_release(item_hk->key);
2841 zbx_hashset_remove_direct(&config->items_hk, item_hk);
2842 }
2843 }
2844
2845 item_hk_local.hostid = hostid;
2846 item_hk_local.key = row[5];
2847 item_hk = (ZBX_DC_ITEM_HK *)zbx_hashset_search(&config->items_hk, &item_hk_local);
2848
2849 if (NULL != item_hk)
2850 item_hk->item_ptr = item;
2851 else
2852 update_index = 1;
2853 }
2854
2855 /* store new information in item structure */
2856
2857 item->hostid = hostid;
2858 item->flags = (unsigned char)atoi(row[18]);
2859 ZBX_DBROW2UINT64(interfaceid, row[19]);
2860
2861 if (SUCCEED != is_time_suffix(row[22], &item->history_sec, ZBX_LENGTH_UNLIMITED))
2862 item->history_sec = ZBX_HK_PERIOD_MAX;
2863
2864 if (0 != item->history_sec && ZBX_HK_OPTION_ENABLED == config->config->hk.history_global)
2865 item->history_sec = config->config->hk.history;
2866
2867 item->history = (0 != item->history_sec);
2868
2869 ZBX_STR2UCHAR(item->inventory_link, row[24]);
2870 ZBX_DBROW2UINT64(item->valuemapid, row[25]);
2871
2872 if (0 != (ZBX_FLAG_DISCOVERY_RULE & item->flags))
2873 value_type = ITEM_VALUE_TYPE_TEXT;
2874 else
2875 ZBX_STR2UCHAR(value_type, row[4]);
2876
2877 if (SUCCEED == DCstrpool_replace(found, &item->key, row[5]))
2878 flags |= ZBX_ITEM_KEY_CHANGED;
2879
2880 if (0 == found)
2881 {
2882 item->triggers = NULL;
2883 item->update_triggers = 0;
2884 item->nextcheck = 0;
2885 item->state = (unsigned char)atoi(row[12]);
2886 ZBX_STR2UINT64(item->lastlogsize, row[20]);
2887 item->mtime = atoi(row[21]);
2888 DCstrpool_replace(found, &item->error, row[27]);
2889 item->data_expected_from = now;
2890 item->location = ZBX_LOC_NOWHERE;
2891 item->poller_type = ZBX_NO_POLLER;
2892 item->queue_priority = ZBX_QUEUE_PRIORITY_NORMAL;
2893 item->schedulable = 1;
2894
2895 zbx_vector_ptr_create_ext(&item->tags, __config_mem_malloc_func, __config_mem_realloc_func,
2896 __config_mem_free_func);
2897 }
2898 else
2899 {
2900 if (item->type != type)
2901 flags |= ZBX_ITEM_TYPE_CHANGED;
2902
2903 if (ITEM_STATUS_ACTIVE == status && ITEM_STATUS_ACTIVE != item->status)
2904 item->data_expected_from = now;
2905
2906 if (ITEM_STATUS_ACTIVE == item->status)
2907 {
2908 ZBX_DC_INTERFACE *interface_old;
2909
2910 interface_old = (ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces,
2911 &item->interfaceid);
2912 dc_interface_update_agent_stats(interface_old, item->type, -1);
2913 }
2914 }
2915
2916 if (ITEM_STATUS_ACTIVE == status)
2917 {
2918 interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces, &interfaceid);
2919 dc_interface_update_agent_stats(interface, type, 1);
2920 }
2921
2922 item->type = type;
2923 item->status = status;
2924 item->value_type = value_type;
2925 item->interfaceid = interfaceid;
2926
2927 /* update items_hk index using new data, if not done already */
2928
2929 if (1 == update_index)
2930 {
2931 item_hk_local.hostid = item->hostid;
2932 item_hk_local.key = zbx_strpool_acquire(item->key);
2933 item_hk_local.item_ptr = item;
2934 zbx_hashset_insert(&config->items_hk, &item_hk_local, sizeof(ZBX_DC_ITEM_HK));
2935 }
2936
2937 /* process item intervals and update item nextcheck */
2938
2939 if (SUCCEED == DCstrpool_replace(found, &item->delay, row[8]))
2940 flags |= ZBX_ITEM_DELAY_CHANGED;
2941
2942 /* numeric items */
2943
2944 if (ITEM_VALUE_TYPE_FLOAT == item->value_type || ITEM_VALUE_TYPE_UINT64 == item->value_type)
2945 {
2946 int trends_sec;
2947
2948 numitem = (ZBX_DC_NUMITEM *)DCfind_id(&config->numitems, itemid, sizeof(ZBX_DC_NUMITEM), &found);
2949
2950 if (SUCCEED != is_time_suffix(row[23], &trends_sec, ZBX_LENGTH_UNLIMITED))
2951 trends_sec = ZBX_HK_PERIOD_MAX;
2952
2953 if (0 != trends_sec && ZBX_HK_OPTION_ENABLED == config->config->hk.trends_global)
2954 trends_sec = config->config->hk.trends;
2955
2956 numitem->trends = (0 != trends_sec);
2957 numitem->trends_sec = trends_sec;
2958
2959 DCstrpool_replace(found, &numitem->units, row[26]);
2960 }
2961 else if (NULL != (numitem = (ZBX_DC_NUMITEM *)zbx_hashset_search(&config->numitems, &itemid)))
2962 {
2963 /* remove parameters for non-numeric item */
2964
2965 zbx_strpool_release(numitem->units);
2966
2967 zbx_hashset_remove_direct(&config->numitems, numitem);
2968 }
2969
2970 /* SNMP items */
2971
2972 if (ITEM_TYPE_SNMP == item->type)
2973 {
2974 snmpitem = (ZBX_DC_SNMPITEM *)DCfind_id(&config->snmpitems, itemid, sizeof(ZBX_DC_SNMPITEM), &found);
2975
2976 if (SUCCEED == DCstrpool_replace(found, &snmpitem->snmp_oid, row[6]))
2977 {
2978 if (NULL != strchr(snmpitem->snmp_oid, '{'))
2979 snmpitem->snmp_oid_type = ZBX_SNMP_OID_TYPE_MACRO;
2980 else if (NULL != strchr(snmpitem->snmp_oid, '['))
2981 snmpitem->snmp_oid_type = ZBX_SNMP_OID_TYPE_DYNAMIC;
2982 else
2983 snmpitem->snmp_oid_type = ZBX_SNMP_OID_TYPE_NORMAL;
2984 }
2985 }
2986 else if (NULL != (snmpitem = (ZBX_DC_SNMPITEM *)zbx_hashset_search(&config->snmpitems, &itemid)))
2987 {
2988 /* remove SNMP parameters for non-SNMP item */
2989
2990 zbx_strpool_release(snmpitem->snmp_oid);
2991 zbx_hashset_remove_direct(&config->snmpitems, snmpitem);
2992 }
2993
2994 /* IPMI items */
2995
2996 if (ITEM_TYPE_IPMI == item->type)
2997 {
2998 ipmiitem = (ZBX_DC_IPMIITEM *)DCfind_id(&config->ipmiitems, itemid, sizeof(ZBX_DC_IPMIITEM), &found);
2999
3000 DCstrpool_replace(found, &ipmiitem->ipmi_sensor, row[7]);
3001 }
3002 else if (NULL != (ipmiitem = (ZBX_DC_IPMIITEM *)zbx_hashset_search(&config->ipmiitems, &itemid)))
3003 {
3004 /* remove IPMI parameters for non-IPMI item */
3005 zbx_strpool_release(ipmiitem->ipmi_sensor);
3006 zbx_hashset_remove_direct(&config->ipmiitems, ipmiitem);
3007 }
3008
3009 /* trapper items */
3010
3011 if (ITEM_TYPE_TRAPPER == item->type && '\0' != *row[9])
3012 {
3013 trapitem = (ZBX_DC_TRAPITEM *)DCfind_id(&config->trapitems, itemid, sizeof(ZBX_DC_TRAPITEM), &found);
3014 DCstrpool_replace(found, &trapitem->trapper_hosts, row[9]);
3015 }
3016 else if (NULL != (trapitem = (ZBX_DC_TRAPITEM *)zbx_hashset_search(&config->trapitems, &itemid)))
3017 {
3018 /* remove trapper_hosts parameter */
3019 zbx_strpool_release(trapitem->trapper_hosts);
3020 zbx_hashset_remove_direct(&config->trapitems, trapitem);
3021 }
3022
3023 /* dependent items */
3024
3025 if (ITEM_TYPE_DEPENDENT == item->type && SUCCEED != DBis_null(row[29]))
3026 {
3027 depitem = (ZBX_DC_DEPENDENTITEM *)DCfind_id(&config->dependentitems, itemid,
3028 sizeof(ZBX_DC_DEPENDENTITEM), &found);
3029
3030 if (1 == found)
3031 depitem->last_master_itemid = depitem->master_itemid;
3032 else
3033 depitem->last_master_itemid = 0;
3034
3035 depitem->flags = item->flags;
3036 ZBX_STR2UINT64(depitem->master_itemid, row[29]);
3037
3038 if (depitem->last_master_itemid != depitem->master_itemid)
3039 zbx_vector_ptr_append(&dep_items, depitem);
3040 }
3041 else if (NULL != (depitem = (ZBX_DC_DEPENDENTITEM *)zbx_hashset_search(&config->dependentitems, &itemid)))
3042 {
3043 dc_masteritem_remove_depitem(depitem->master_itemid, itemid);
3044 zbx_hashset_remove_direct(&config->dependentitems, depitem);
3045 }
3046
3047 /* log items */
3048
3049 if (ITEM_VALUE_TYPE_LOG == item->value_type && '\0' != *row[10])
3050 {
3051 logitem = (ZBX_DC_LOGITEM *)DCfind_id(&config->logitems, itemid, sizeof(ZBX_DC_LOGITEM), &found);
3052
3053 DCstrpool_replace(found, &logitem->logtimefmt, row[10]);
3054 }
3055 else if (NULL != (logitem = (ZBX_DC_LOGITEM *)zbx_hashset_search(&config->logitems, &itemid)))
3056 {
3057 /* remove logtimefmt parameter */
3058 zbx_strpool_release(logitem->logtimefmt);
3059 zbx_hashset_remove_direct(&config->logitems, logitem);
3060 }
3061
3062 /* db items */
3063
3064 if (ITEM_TYPE_DB_MONITOR == item->type && '\0' != *row[11])
3065 {
3066 dbitem = (ZBX_DC_DBITEM *)DCfind_id(&config->dbitems, itemid, sizeof(ZBX_DC_DBITEM), &found);
3067
3068 DCstrpool_replace(found, &dbitem->params, row[11]);
3069 DCstrpool_replace(found, &dbitem->username, row[14]);
3070 DCstrpool_replace(found, &dbitem->password, row[15]);
3071 }
3072 else if (NULL != (dbitem = (ZBX_DC_DBITEM *)zbx_hashset_search(&config->dbitems, &itemid)))
3073 {
3074 /* remove db item parameters */
3075 zbx_strpool_release(dbitem->params);
3076 zbx_strpool_release(dbitem->username);
3077 zbx_strpool_release(dbitem->password);
3078
3079 zbx_hashset_remove_direct(&config->dbitems, dbitem);
3080 }
3081
3082 /* SSH items */
3083
3084 if (ITEM_TYPE_SSH == item->type)
3085 {
3086 sshitem = (ZBX_DC_SSHITEM *)DCfind_id(&config->sshitems, itemid, sizeof(ZBX_DC_SSHITEM), &found);
3087
3088 sshitem->authtype = (unsigned short)atoi(row[13]);
3089 DCstrpool_replace(found, &sshitem->username, row[14]);
3090 DCstrpool_replace(found, &sshitem->password, row[15]);
3091 DCstrpool_replace(found, &sshitem->publickey, row[16]);
3092 DCstrpool_replace(found, &sshitem->privatekey, row[17]);
3093 DCstrpool_replace(found, &sshitem->params, row[11]);
3094 }
3095 else if (NULL != (sshitem = (ZBX_DC_SSHITEM *)zbx_hashset_search(&config->sshitems, &itemid)))
3096 {
3097 /* remove SSH item parameters */
3098
3099 zbx_strpool_release(sshitem->username);
3100 zbx_strpool_release(sshitem->password);
3101 zbx_strpool_release(sshitem->publickey);
3102 zbx_strpool_release(sshitem->privatekey);
3103 zbx_strpool_release(sshitem->params);
3104
3105 zbx_hashset_remove_direct(&config->sshitems, sshitem);
3106 }
3107
3108 /* TELNET items */
3109
3110 if (ITEM_TYPE_TELNET == item->type)
3111 {
3112 telnetitem = (ZBX_DC_TELNETITEM *)DCfind_id(&config->telnetitems, itemid, sizeof(ZBX_DC_TELNETITEM), &found);
3113
3114 DCstrpool_replace(found, &telnetitem->username, row[14]);
3115 DCstrpool_replace(found, &telnetitem->password, row[15]);
3116 DCstrpool_replace(found, &telnetitem->params, row[11]);
3117 }
3118 else if (NULL != (telnetitem = (ZBX_DC_TELNETITEM *)zbx_hashset_search(&config->telnetitems, &itemid)))
3119 {
3120 /* remove TELNET item parameters */
3121
3122 zbx_strpool_release(telnetitem->username);
3123 zbx_strpool_release(telnetitem->password);
3124 zbx_strpool_release(telnetitem->params);
3125
3126 zbx_hashset_remove_direct(&config->telnetitems, telnetitem);
3127 }
3128
3129 /* simple items */
3130
3131 if (ITEM_TYPE_SIMPLE == item->type)
3132 {
3133 simpleitem = (ZBX_DC_SIMPLEITEM *)DCfind_id(&config->simpleitems, itemid, sizeof(ZBX_DC_SIMPLEITEM), &found);
3134
3135 DCstrpool_replace(found, &simpleitem->username, row[14]);
3136 DCstrpool_replace(found, &simpleitem->password, row[15]);
3137 }
3138 else if (NULL != (simpleitem = (ZBX_DC_SIMPLEITEM *)zbx_hashset_search(&config->simpleitems, &itemid)))
3139 {
3140 /* remove simple item parameters */
3141
3142 zbx_strpool_release(simpleitem->username);
3143 zbx_strpool_release(simpleitem->password);
3144
3145 zbx_hashset_remove_direct(&config->simpleitems, simpleitem);
3146 }
3147
3148 /* JMX items */
3149
3150 if (ITEM_TYPE_JMX == item->type)
3151 {
3152 jmxitem = (ZBX_DC_JMXITEM *)DCfind_id(&config->jmxitems, itemid, sizeof(ZBX_DC_JMXITEM), &found);
3153
3154 DCstrpool_replace(found, &jmxitem->username, row[14]);
3155 DCstrpool_replace(found, &jmxitem->password, row[15]);
3156 DCstrpool_replace(found, &jmxitem->jmx_endpoint, row[28]);
3157 }
3158 else if (NULL != (jmxitem = (ZBX_DC_JMXITEM *)zbx_hashset_search(&config->jmxitems, &itemid)))
3159 {
3160 /* remove JMX item parameters */
3161
3162 zbx_strpool_release(jmxitem->username);
3163 zbx_strpool_release(jmxitem->password);
3164 zbx_strpool_release(jmxitem->jmx_endpoint);
3165
3166 zbx_hashset_remove_direct(&config->jmxitems, jmxitem);
3167 }
3168
3169 /* SNMP trap items for current server/proxy */
3170
3171 if (ITEM_TYPE_SNMPTRAP == item->type && 0 == host->proxy_hostid)
3172 {
3173 interface_snmpitem = (ZBX_DC_INTERFACE_ITEM *)DCfind_id(&config->interface_snmpitems,
3174 item->interfaceid, sizeof(ZBX_DC_INTERFACE_ITEM), &found);
3175
3176 if (0 == found)
3177 {
3178 zbx_vector_uint64_create_ext(&interface_snmpitem->itemids,
3179 __config_mem_malloc_func,
3180 __config_mem_realloc_func,
3181 __config_mem_free_func);
3182 }
3183
3184 zbx_vector_uint64_append(&interface_snmpitem->itemids, itemid);
3185 }
3186
3187 /* calculated items */
3188
3189 if (ITEM_TYPE_CALCULATED == item->type)
3190 {
3191 calcitem = (ZBX_DC_CALCITEM *)DCfind_id(&config->calcitems, itemid, sizeof(ZBX_DC_CALCITEM),
3192 &found);
3193
3194 DCstrpool_replace(found, &calcitem->params, row[11]);
3195
3196 if (1 == found && NULL != calcitem->formula_bin)
3197 __config_mem_free_func((void *)calcitem->formula_bin);
3198
3199 calcitem->formula_bin = config_decode_serialized_expression(row[50]);
3200 }
3201 else if (NULL != (calcitem = (ZBX_DC_CALCITEM *)zbx_hashset_search(&config->calcitems, &itemid)))
3202 {
3203 /* remove calculated item parameters */
3204
3205 if (NULL != calcitem->formula_bin)
3206 __config_mem_free_func((void *)calcitem->formula_bin);
3207 zbx_strpool_release(calcitem->params);
3208 zbx_hashset_remove_direct(&config->calcitems, calcitem);
3209 }
3210
3211 /* HTTP agent items */
3212
3213 if (ITEM_TYPE_HTTPAGENT == item->type)
3214 {
3215 httpitem = (ZBX_DC_HTTPITEM *)DCfind_id(&config->httpitems, itemid, sizeof(ZBX_DC_HTTPITEM),
3216 &found);
3217
3218 DCstrpool_replace(found, &httpitem->timeout, row[30]);
3219 DCstrpool_replace(found, &httpitem->url, row[31]);
3220 DCstrpool_replace(found, &httpitem->query_fields, row[32]);
3221 DCstrpool_replace(found, &httpitem->posts, row[33]);
3222 DCstrpool_replace(found, &httpitem->status_codes, row[34]);
3223 httpitem->follow_redirects = (unsigned char)atoi(row[35]);
3224 httpitem->post_type = (unsigned char)atoi(row[36]);
3225 DCstrpool_replace(found, &httpitem->http_proxy, row[37]);
3226 DCstrpool_replace(found, &httpitem->headers, row[38]);
3227 httpitem->retrieve_mode = (unsigned char)atoi(row[39]);
3228 httpitem->request_method = (unsigned char)atoi(row[40]);
3229 httpitem->output_format = (unsigned char)atoi(row[41]);
3230 DCstrpool_replace(found, &httpitem->ssl_cert_file, row[42]);
3231 DCstrpool_replace(found, &httpitem->ssl_key_file, row[43]);
3232 DCstrpool_replace(found, &httpitem->ssl_key_password, row[44]);
3233 httpitem->verify_peer = (unsigned char)atoi(row[45]);
3234 httpitem->verify_host = (unsigned char)atoi(row[46]);
3235 httpitem->allow_traps = (unsigned char)atoi(row[47]);
3236
3237 httpitem->authtype = (unsigned char)atoi(row[13]);
3238 DCstrpool_replace(found, &httpitem->username, row[14]);
3239 DCstrpool_replace(found, &httpitem->password, row[15]);
3240 DCstrpool_replace(found, &httpitem->trapper_hosts, row[9]);
3241 }
3242 else if (NULL != (httpitem = (ZBX_DC_HTTPITEM *)zbx_hashset_search(&config->httpitems, &itemid)))
3243 {
3244 zbx_strpool_release(httpitem->timeout);
3245 zbx_strpool_release(httpitem->url);
3246 zbx_strpool_release(httpitem->query_fields);
3247 zbx_strpool_release(httpitem->posts);
3248 zbx_strpool_release(httpitem->status_codes);
3249 zbx_strpool_release(httpitem->http_proxy);
3250 zbx_strpool_release(httpitem->headers);
3251 zbx_strpool_release(httpitem->ssl_cert_file);
3252 zbx_strpool_release(httpitem->ssl_key_file);
3253 zbx_strpool_release(httpitem->ssl_key_password);
3254 zbx_strpool_release(httpitem->username);
3255 zbx_strpool_release(httpitem->password);
3256 zbx_strpool_release(httpitem->trapper_hosts);
3257
3258 zbx_hashset_remove_direct(&config->httpitems, httpitem);
3259 }
3260
3261 /* Script items */
3262
3263 if (ITEM_TYPE_SCRIPT == item->type)
3264 {
3265 scriptitem = (ZBX_DC_SCRIPTITEM *)DCfind_id(&config->scriptitems, itemid,
3266 sizeof(ZBX_DC_SCRIPTITEM), &found);
3267
3268 DCstrpool_replace(found, &scriptitem->timeout, row[30]);
3269 DCstrpool_replace(found, &scriptitem->script, row[11]);
3270
3271 if (0 == found)
3272 {
3273 zbx_vector_ptr_create_ext(&scriptitem->params, __config_mem_malloc_func,
3274 __config_mem_realloc_func, __config_mem_free_func);
3275 }
3276 }
3277 else if (NULL != (scriptitem = (ZBX_DC_SCRIPTITEM *)zbx_hashset_search(&config->scriptitems, &itemid)))
3278 {
3279 zbx_strpool_release(scriptitem->timeout);
3280 zbx_strpool_release(scriptitem->script);
3281
3282 zbx_vector_ptr_destroy(&scriptitem->params);
3283 zbx_hashset_remove_direct(&config->scriptitems, scriptitem);
3284 }
3285
3286 /* it is crucial to update type specific (config->snmpitems, config->ipmiitems, etc.) hashsets before */
3287 /* attempting to requeue an item because type specific properties are used to arrange items in queues */
3288
3289 old_poller_type = item->poller_type;
3290 old_nextcheck = item->nextcheck;
3291
3292 if (ITEM_STATUS_ACTIVE == item->status && HOST_STATUS_MONITORED == host->status)
3293 {
3294 DCitem_poller_type_update(item, host, flags);
3295
3296 if (SUCCEED == zbx_is_counted_in_item_queue(item->type, item->key))
3297 {
3298 char *error = NULL;
3299
3300 if (FAIL == DCitem_nextcheck_update(item, interface, flags, now, &error))
3301 {
3302 zbx_timespec_t ts = {now, 0};
3303
3304 /* Usual way for an item to become not supported is to receive an error */
3305 /* instead of value. Item state and error will be updated by history syncer */
3306 /* during history sync following a regular procedure with item update in */
3307 /* database and config cache, logging etc. There is no need to set */
3308 /* ITEM_STATE_NOTSUPPORTED here. */
3309
3310 if (0 == host->proxy_hostid)
3311 {
3312 dc_add_history(item->itemid, item->value_type, 0, NULL, &ts,
3313 ITEM_STATE_NOTSUPPORTED, error);
3314 }
3315 zbx_free(error);
3316 }
3317 }
3318 }
3319 else
3320 {
3321 item->nextcheck = 0;
3322 item->queue_priority = ZBX_QUEUE_PRIORITY_NORMAL;
3323 item->poller_type = ZBX_NO_POLLER;
3324 }
3325
3326 DCupdate_item_queue(item, old_poller_type, old_nextcheck);
3327 }
3328
3329 /* update dependent item vectors within master items */
3330
3331 for (i = 0; i < dep_items.values_num; i++)
3332 {
3333 zbx_uint64_pair_t pair;
3334
3335 depitem = (ZBX_DC_DEPENDENTITEM *)dep_items.values[i];
3336 dc_masteritem_remove_depitem(depitem->last_master_itemid, depitem->itemid);
3337 pair.first = depitem->itemid;
3338 pair.second = depitem->flags;
3339
3340 /* append item to dependent item vector of master item */
3341 if (NULL == (master = (ZBX_DC_MASTERITEM *)zbx_hashset_search(&config->masteritems, &depitem->master_itemid)))
3342 {
3343 ZBX_DC_MASTERITEM master_local;
3344
3345 master_local.itemid = depitem->master_itemid;
3346 master = (ZBX_DC_MASTERITEM *)zbx_hashset_insert(&config->masteritems, &master_local, sizeof(master_local));
3347
3348 zbx_vector_uint64_pair_create_ext(&master->dep_itemids, __config_mem_malloc_func,
3349 __config_mem_realloc_func, __config_mem_free_func);
3350 }
3351
3352 zbx_vector_uint64_pair_append(&master->dep_itemids, pair);
3353 }
3354
3355 zbx_vector_ptr_destroy(&dep_items);
3356
3357 /* remove deleted items from buffer */
3358 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
3359 {
3360 if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &rowid)))
3361 continue;
3362
3363 if (ITEM_STATUS_ACTIVE == item->status)
3364 {
3365 interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces, &item->interfaceid);
3366 dc_interface_update_agent_stats(interface, item->type, -1);
3367 }
3368
3369 itemid = item->itemid;
3370
3371 if (ITEM_TYPE_SNMPTRAP == item->type)
3372 dc_interface_snmpitems_remove(item);
3373
3374 /* numeric items */
3375
3376 if (ITEM_VALUE_TYPE_FLOAT == item->value_type || ITEM_VALUE_TYPE_UINT64 == item->value_type)
3377 {
3378 numitem = (ZBX_DC_NUMITEM *)zbx_hashset_search(&config->numitems, &itemid);
3379
3380 zbx_strpool_release(numitem->units);
3381
3382 zbx_hashset_remove_direct(&config->numitems, numitem);
3383 }
3384
3385 /* SNMP items */
3386
3387 if (ITEM_TYPE_SNMP == item->type)
3388 {
3389 snmpitem = (ZBX_DC_SNMPITEM *)zbx_hashset_search(&config->snmpitems, &itemid);
3390 zbx_strpool_release(snmpitem->snmp_oid);
3391 zbx_hashset_remove_direct(&config->snmpitems, snmpitem);
3392 }
3393
3394 /* IPMI items */
3395
3396 if (ITEM_TYPE_IPMI == item->type)
3397 {
3398 ipmiitem = (ZBX_DC_IPMIITEM *)zbx_hashset_search(&config->ipmiitems, &itemid);
3399 zbx_strpool_release(ipmiitem->ipmi_sensor);
3400 zbx_hashset_remove_direct(&config->ipmiitems, ipmiitem);
3401 }
3402
3403 /* trapper items */
3404
3405 if (ITEM_TYPE_TRAPPER == item->type &&
3406 NULL != (trapitem = (ZBX_DC_TRAPITEM *)zbx_hashset_search(&config->trapitems, &itemid)))
3407 {
3408 zbx_strpool_release(trapitem->trapper_hosts);
3409 zbx_hashset_remove_direct(&config->trapitems, trapitem);
3410 }
3411
3412 /* dependent items */
3413
3414 if (NULL != (depitem = (ZBX_DC_DEPENDENTITEM *)zbx_hashset_search(&config->dependentitems, &itemid)))
3415 {
3416 dc_masteritem_remove_depitem(depitem->master_itemid, itemid);
3417 zbx_hashset_remove_direct(&config->dependentitems, depitem);
3418 }
3419
3420 /* log items */
3421
3422 if (ITEM_VALUE_TYPE_LOG == item->value_type &&
3423 NULL != (logitem = (ZBX_DC_LOGITEM *)zbx_hashset_search(&config->logitems, &itemid)))
3424 {
3425 zbx_strpool_release(logitem->logtimefmt);
3426 zbx_hashset_remove_direct(&config->logitems, logitem);
3427 }
3428
3429 /* db items */
3430
3431 if (ITEM_TYPE_DB_MONITOR == item->type &&
3432 NULL != (dbitem = (ZBX_DC_DBITEM *)zbx_hashset_search(&config->dbitems, &itemid)))
3433 {
3434 zbx_strpool_release(dbitem->params);
3435 zbx_strpool_release(dbitem->username);
3436 zbx_strpool_release(dbitem->password);
3437
3438 zbx_hashset_remove_direct(&config->dbitems, dbitem);
3439 }
3440
3441 /* SSH items */
3442
3443 if (ITEM_TYPE_SSH == item->type)
3444 {
3445 sshitem = (ZBX_DC_SSHITEM *)zbx_hashset_search(&config->sshitems, &itemid);
3446
3447 zbx_strpool_release(sshitem->username);
3448 zbx_strpool_release(sshitem->password);
3449 zbx_strpool_release(sshitem->publickey);
3450 zbx_strpool_release(sshitem->privatekey);
3451 zbx_strpool_release(sshitem->params);
3452
3453 zbx_hashset_remove_direct(&config->sshitems, sshitem);
3454 }
3455
3456 /* TELNET items */
3457
3458 if (ITEM_TYPE_TELNET == item->type)
3459 {
3460 telnetitem = (ZBX_DC_TELNETITEM *)zbx_hashset_search(&config->telnetitems, &itemid);
3461
3462 zbx_strpool_release(telnetitem->username);
3463 zbx_strpool_release(telnetitem->password);
3464 zbx_strpool_release(telnetitem->params);
3465
3466 zbx_hashset_remove_direct(&config->telnetitems, telnetitem);
3467 }
3468
3469 /* simple items */
3470
3471 if (ITEM_TYPE_SIMPLE == item->type)
3472 {
3473 simpleitem = (ZBX_DC_SIMPLEITEM *)zbx_hashset_search(&config->simpleitems, &itemid);
3474
3475 zbx_strpool_release(simpleitem->username);
3476 zbx_strpool_release(simpleitem->password);
3477
3478 zbx_hashset_remove_direct(&config->simpleitems, simpleitem);
3479 }
3480
3481 /* JMX items */
3482
3483 if (ITEM_TYPE_JMX == item->type)
3484 {
3485 jmxitem = (ZBX_DC_JMXITEM *)zbx_hashset_search(&config->jmxitems, &itemid);
3486
3487 zbx_strpool_release(jmxitem->username);
3488 zbx_strpool_release(jmxitem->password);
3489 zbx_strpool_release(jmxitem->jmx_endpoint);
3490
3491 zbx_hashset_remove_direct(&config->jmxitems, jmxitem);
3492 }
3493
3494 /* calculated items */
3495
3496 if (ITEM_TYPE_CALCULATED == item->type)
3497 {
3498 calcitem = (ZBX_DC_CALCITEM *)zbx_hashset_search(&config->calcitems, &itemid);
3499 zbx_strpool_release(calcitem->params);
3500
3501 if (NULL != calcitem->formula_bin)
3502 __config_mem_free_func((void *)calcitem->formula_bin);
3503
3504 zbx_hashset_remove_direct(&config->calcitems, calcitem);
3505 }
3506
3507 /* HTTP agent items */
3508
3509 if (ITEM_TYPE_HTTPAGENT == item->type)
3510 {
3511 httpitem = (ZBX_DC_HTTPITEM *)zbx_hashset_search(&config->httpitems, &itemid);
3512
3513 zbx_strpool_release(httpitem->timeout);
3514 zbx_strpool_release(httpitem->url);
3515 zbx_strpool_release(httpitem->query_fields);
3516 zbx_strpool_release(httpitem->posts);
3517 zbx_strpool_release(httpitem->status_codes);
3518 zbx_strpool_release(httpitem->http_proxy);
3519 zbx_strpool_release(httpitem->headers);
3520 zbx_strpool_release(httpitem->ssl_cert_file);
3521 zbx_strpool_release(httpitem->ssl_key_file);
3522 zbx_strpool_release(httpitem->ssl_key_password);
3523 zbx_strpool_release(httpitem->username);
3524 zbx_strpool_release(httpitem->password);
3525 zbx_strpool_release(httpitem->trapper_hosts);
3526
3527 zbx_hashset_remove_direct(&config->httpitems, httpitem);
3528 }
3529
3530 /* Script items */
3531
3532 if (ITEM_TYPE_SCRIPT == item->type)
3533 {
3534 scriptitem = (ZBX_DC_SCRIPTITEM *)zbx_hashset_search(&config->scriptitems, &itemid);
3535
3536 zbx_strpool_release(scriptitem->timeout);
3537 zbx_strpool_release(scriptitem->script);
3538
3539 zbx_vector_ptr_destroy(&scriptitem->params);
3540 zbx_hashset_remove_direct(&config->scriptitems, scriptitem);
3541 }
3542
3543 /* items */
3544
3545 item_hk_local.hostid = item->hostid;
3546 item_hk_local.key = item->key;
3547
3548 if (NULL == (item_hk = (ZBX_DC_ITEM_HK *)zbx_hashset_search(&config->items_hk, &item_hk_local)))
3549 {
3550 /* item keys should be unique for items within a host, otherwise items with */
3551 /* same key share index and removal of last added item already cleared index */
3552 THIS_SHOULD_NEVER_HAPPEN;
3553 }
3554 else if (item == item_hk->item_ptr)
3555 {
3556 zbx_strpool_release(item_hk->key);
3557 zbx_hashset_remove_direct(&config->items_hk, item_hk);
3558 }
3559
3560 if (ZBX_LOC_QUEUE == item->location)
3561 zbx_binary_heap_remove_direct(&config->queues[item->poller_type], item->itemid);
3562
3563 zbx_strpool_release(item->key);
3564 zbx_strpool_release(item->error);
3565 zbx_strpool_release(item->delay);
3566
3567 if (NULL != item->triggers)
3568 config->items.mem_free_func(item->triggers);
3569
3570 zbx_vector_ptr_destroy(&item->tags);
3571
3572 if (NULL != (preprocitem = (ZBX_DC_PREPROCITEM *)zbx_hashset_search(&config->preprocitems, &item->itemid)))
3573 {
3574 zbx_vector_ptr_destroy(&preprocitem->preproc_ops);
3575 zbx_hashset_remove_direct(&config->preprocitems, preprocitem);
3576 }
3577
3578 zbx_hashset_remove_direct(&config->items, item);
3579 }
3580
3581 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3582 }
3583
DCsync_template_items(zbx_dbsync_t * sync)3584 static void DCsync_template_items(zbx_dbsync_t *sync)
3585 {
3586 char **row;
3587 zbx_uint64_t rowid, itemid;
3588 unsigned char tag;
3589 int ret, found;
3590 ZBX_DC_TEMPLATE_ITEM *item;
3591
3592 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3593
3594 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
3595 {
3596 /* removed rows will be always added at the end */
3597 if (ZBX_DBSYNC_ROW_REMOVE == tag)
3598 break;
3599
3600 ZBX_STR2UINT64(itemid, row[0]);
3601 item = (ZBX_DC_TEMPLATE_ITEM *)DCfind_id(&config->template_items, itemid, sizeof(ZBX_DC_TEMPLATE_ITEM),
3602 &found);
3603
3604 ZBX_STR2UINT64(item->hostid, row[1]);
3605 ZBX_DBROW2UINT64(item->templateid, row[2]);
3606 }
3607
3608 /* remove deleted template items from buffer */
3609 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
3610 {
3611 if (NULL == (item = (ZBX_DC_TEMPLATE_ITEM *)zbx_hashset_search(&config->template_items, &rowid)))
3612 continue;
3613
3614 zbx_hashset_remove_direct(&config->template_items, item);
3615 }
3616
3617 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3618 }
3619
DCsync_prototype_items(zbx_dbsync_t * sync)3620 static void DCsync_prototype_items(zbx_dbsync_t *sync)
3621 {
3622 char **row;
3623 zbx_uint64_t rowid, itemid;
3624 unsigned char tag;
3625 int ret, found;
3626 ZBX_DC_PROTOTYPE_ITEM *item;
3627
3628 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3629
3630 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
3631 {
3632 /* removed rows will be always added at the end */
3633 if (ZBX_DBSYNC_ROW_REMOVE == tag)
3634 break;
3635
3636 ZBX_STR2UINT64(itemid, row[0]);
3637 item = (ZBX_DC_PROTOTYPE_ITEM *)DCfind_id(&config->prototype_items, itemid,
3638 sizeof(ZBX_DC_PROTOTYPE_ITEM), &found);
3639
3640 ZBX_STR2UINT64(item->hostid, row[1]);
3641 ZBX_DBROW2UINT64(item->templateid, row[2]);
3642 }
3643
3644 /* remove deleted prototype items from buffer */
3645 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
3646 {
3647 if (NULL == (item = (ZBX_DC_PROTOTYPE_ITEM *)zbx_hashset_search(&config->prototype_items, &rowid)))
3648 continue;
3649
3650 zbx_hashset_remove_direct(&config->prototype_items, item);
3651 }
3652
3653 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3654 }
3655
DCsync_triggers(zbx_dbsync_t * sync)3656 static void DCsync_triggers(zbx_dbsync_t *sync)
3657 {
3658 char **row;
3659 zbx_uint64_t rowid;
3660 unsigned char tag;
3661
3662 ZBX_DC_TRIGGER *trigger;
3663
3664 int found, ret;
3665 zbx_uint64_t triggerid;
3666
3667 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3668
3669 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
3670 {
3671 /* removed rows will be always added at the end */
3672 if (ZBX_DBSYNC_ROW_REMOVE == tag)
3673 break;
3674
3675 ZBX_STR2UINT64(triggerid, row[0]);
3676
3677 trigger = (ZBX_DC_TRIGGER *)DCfind_id(&config->triggers, triggerid, sizeof(ZBX_DC_TRIGGER), &found);
3678
3679 /* store new information in trigger structure */
3680
3681 DCstrpool_replace(found, &trigger->description, row[1]);
3682 DCstrpool_replace(found, &trigger->expression, row[2]);
3683 DCstrpool_replace(found, &trigger->recovery_expression, row[11]);
3684 DCstrpool_replace(found, &trigger->correlation_tag, row[13]);
3685 DCstrpool_replace(found, &trigger->opdata, row[14]);
3686 DCstrpool_replace(found, &trigger->event_name, row[15]);
3687 ZBX_STR2UCHAR(trigger->priority, row[4]);
3688 ZBX_STR2UCHAR(trigger->type, row[5]);
3689 ZBX_STR2UCHAR(trigger->status, row[9]);
3690 ZBX_STR2UCHAR(trigger->recovery_mode, row[10]);
3691 ZBX_STR2UCHAR(trigger->correlation_mode, row[12]);
3692
3693 if (0 == found)
3694 {
3695 DCstrpool_replace(found, &trigger->error, row[3]);
3696 ZBX_STR2UCHAR(trigger->value, row[6]);
3697 ZBX_STR2UCHAR(trigger->state, row[7]);
3698 trigger->lastchange = atoi(row[8]);
3699 trigger->locked = 0;
3700 trigger->timer_revision = 0;
3701
3702 zbx_vector_ptr_create_ext(&trigger->tags, __config_mem_malloc_func, __config_mem_realloc_func,
3703 __config_mem_free_func);
3704 trigger->topoindex = 1;
3705 }
3706 else
3707 {
3708 if (NULL != trigger->expression_bin)
3709 __config_mem_free_func((void *)trigger->expression_bin);
3710 if (NULL != trigger->recovery_expression_bin)
3711 __config_mem_free_func((void *)trigger->recovery_expression_bin);
3712 }
3713
3714 trigger->expression_bin = config_decode_serialized_expression(row[16]);
3715 trigger->recovery_expression_bin = config_decode_serialized_expression(row[17]);
3716 trigger->timer = atoi(row[18]);
3717 trigger->revision = config->sync_start_ts;
3718 }
3719
3720 /* remove deleted triggers from buffer */
3721 if (SUCCEED == ret)
3722 {
3723 zbx_vector_uint64_t functionids;
3724 int i;
3725 ZBX_DC_ITEM *item;
3726 ZBX_DC_FUNCTION *function;
3727
3728 zbx_vector_uint64_create(&functionids);
3729
3730 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
3731 {
3732 if (NULL == (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &rowid)))
3733 continue;
3734
3735 /* force trigger list update for items used in removed trigger */
3736
3737 if (NULL != trigger->expression_bin)
3738 {
3739 zbx_get_serialized_expression_functionids(trigger->expression, trigger->expression_bin,
3740 &functionids);
3741 }
3742
3743 if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == trigger->recovery_mode &&
3744 NULL != trigger->recovery_expression_bin)
3745 {
3746 zbx_get_serialized_expression_functionids(trigger->recovery_expression,
3747 trigger->recovery_expression_bin, &functionids);
3748 }
3749
3750 for (i = 0; i < functionids.values_num; i++)
3751 {
3752 if (NULL == (function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &functionids.values[i])))
3753 continue;
3754
3755 if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &function->itemid)))
3756 continue;
3757
3758 item->update_triggers = 1;
3759 if (NULL != item->triggers)
3760 {
3761 config->items.mem_free_func(item->triggers);
3762 item->triggers = NULL;
3763 }
3764 }
3765 zbx_vector_uint64_clear(&functionids);
3766
3767 zbx_strpool_release(trigger->description);
3768 zbx_strpool_release(trigger->expression);
3769 zbx_strpool_release(trigger->recovery_expression);
3770 zbx_strpool_release(trigger->error);
3771 zbx_strpool_release(trigger->correlation_tag);
3772 zbx_strpool_release(trigger->opdata);
3773 zbx_strpool_release(trigger->event_name);
3774
3775 zbx_vector_ptr_destroy(&trigger->tags);
3776
3777 if (NULL != trigger->expression_bin)
3778 __config_mem_free_func((void *)trigger->expression_bin);
3779 if (NULL != trigger->recovery_expression_bin)
3780 __config_mem_free_func((void *)trigger->recovery_expression_bin);
3781
3782 zbx_hashset_remove_direct(&config->triggers, trigger);
3783 }
3784 zbx_vector_uint64_destroy(&functionids);
3785 }
3786
3787 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3788 }
3789
3790 static void DCconfig_sort_triggers_topologically(void);
3791
3792 /******************************************************************************
3793 * *
3794 * Function: dc_trigger_deplist_release *
3795 * *
3796 * Purpose: releases trigger dependency list, removing it if necessary *
3797 * *
3798 ******************************************************************************/
dc_trigger_deplist_release(ZBX_DC_TRIGGER_DEPLIST * trigdep)3799 static int dc_trigger_deplist_release(ZBX_DC_TRIGGER_DEPLIST *trigdep)
3800 {
3801 if (0 == --trigdep->refcount)
3802 {
3803 zbx_vector_ptr_destroy(&trigdep->dependencies);
3804 zbx_hashset_remove_direct(&config->trigdeps, trigdep);
3805 return SUCCEED;
3806 }
3807
3808 return FAIL;
3809 }
3810
3811 /******************************************************************************
3812 * *
3813 * Function: dc_trigger_deplist_init *
3814 * *
3815 * Purpose: initializes trigger dependency list *
3816 * *
3817 ******************************************************************************/
dc_trigger_deplist_init(ZBX_DC_TRIGGER_DEPLIST * trigdep,ZBX_DC_TRIGGER * trigger)3818 static void dc_trigger_deplist_init(ZBX_DC_TRIGGER_DEPLIST *trigdep, ZBX_DC_TRIGGER *trigger)
3819 {
3820 trigdep->refcount = 1;
3821 trigdep->trigger = trigger;
3822 zbx_vector_ptr_create_ext(&trigdep->dependencies, __config_mem_malloc_func, __config_mem_realloc_func,
3823 __config_mem_free_func);
3824 }
3825
3826 /******************************************************************************
3827 * *
3828 * Function: dc_trigger_deplist_reset *
3829 * *
3830 * Purpose: resets trigger dependency list to release memory allocated by *
3831 * dependencies vector *
3832 * *
3833 ******************************************************************************/
dc_trigger_deplist_reset(ZBX_DC_TRIGGER_DEPLIST * trigdep)3834 static void dc_trigger_deplist_reset(ZBX_DC_TRIGGER_DEPLIST *trigdep)
3835 {
3836 zbx_vector_ptr_destroy(&trigdep->dependencies);
3837 zbx_vector_ptr_create_ext(&trigdep->dependencies, __config_mem_malloc_func, __config_mem_realloc_func,
3838 __config_mem_free_func);
3839 }
3840
DCsync_trigdeps(zbx_dbsync_t * sync)3841 static void DCsync_trigdeps(zbx_dbsync_t *sync)
3842 {
3843 char **row;
3844 zbx_uint64_t rowid;
3845 unsigned char tag;
3846
3847 ZBX_DC_TRIGGER_DEPLIST *trigdep_down, *trigdep_up;
3848
3849 int found, index, ret;
3850 zbx_uint64_t triggerid_down, triggerid_up;
3851 ZBX_DC_TRIGGER *trigger_up, *trigger_down;
3852
3853 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3854
3855 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
3856 {
3857 /* removed rows will be always added at the end */
3858 if (ZBX_DBSYNC_ROW_REMOVE == tag)
3859 break;
3860
3861 /* find trigdep_down pointer */
3862
3863 ZBX_STR2UINT64(triggerid_down, row[0]);
3864 if (NULL == (trigger_down = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &triggerid_down)))
3865 continue;
3866
3867 ZBX_STR2UINT64(triggerid_up, row[1]);
3868 if (NULL == (trigger_up = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &triggerid_up)))
3869 continue;
3870
3871 trigdep_down = (ZBX_DC_TRIGGER_DEPLIST *)DCfind_id(&config->trigdeps, triggerid_down, sizeof(ZBX_DC_TRIGGER_DEPLIST), &found);
3872 if (0 == found)
3873 dc_trigger_deplist_init(trigdep_down, trigger_down);
3874 else
3875 trigdep_down->refcount++;
3876
3877 trigdep_up = (ZBX_DC_TRIGGER_DEPLIST *)DCfind_id(&config->trigdeps, triggerid_up, sizeof(ZBX_DC_TRIGGER_DEPLIST), &found);
3878 if (0 == found)
3879 dc_trigger_deplist_init(trigdep_up, trigger_up);
3880 else
3881 trigdep_up->refcount++;
3882
3883 zbx_vector_ptr_append(&trigdep_down->dependencies, trigdep_up);
3884 }
3885
3886 /* remove deleted trigger dependencies from buffer */
3887 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
3888 {
3889 ZBX_STR2UINT64(triggerid_down, row[0]);
3890 if (NULL == (trigdep_down = (ZBX_DC_TRIGGER_DEPLIST *)zbx_hashset_search(&config->trigdeps,
3891 &triggerid_down)))
3892 {
3893 continue;
3894 }
3895
3896 ZBX_STR2UINT64(triggerid_up, row[1]);
3897 if (NULL != (trigdep_up = (ZBX_DC_TRIGGER_DEPLIST *)zbx_hashset_search(&config->trigdeps,
3898 &triggerid_up)))
3899 {
3900 dc_trigger_deplist_release(trigdep_up);
3901 }
3902
3903 if (SUCCEED != dc_trigger_deplist_release(trigdep_down))
3904 {
3905 if (FAIL == (index = zbx_vector_ptr_search(&trigdep_down->dependencies, &triggerid_up,
3906 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
3907 {
3908 continue;
3909 }
3910
3911 if (1 == trigdep_down->dependencies.values_num)
3912 dc_trigger_deplist_reset(trigdep_down);
3913 else
3914 zbx_vector_ptr_remove_noorder(&trigdep_down->dependencies, index);
3915 }
3916 }
3917
3918 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3919 }
3920
3921 #define ZBX_TIMER_DELAY 30
3922
dc_function_calculate_trends_nextcheck(time_t from,const char * period_shift,zbx_time_unit_t base,time_t * nextcheck,char ** error)3923 static int dc_function_calculate_trends_nextcheck(time_t from, const char *period_shift, zbx_time_unit_t base,
3924 time_t *nextcheck, char **error)
3925 {
3926 time_t next = from;
3927 struct tm tm;
3928
3929 localtime_r(&next, &tm);
3930
3931 while (SUCCEED == zbx_trends_parse_nextcheck(next, period_shift, nextcheck, error))
3932 {
3933 if (*nextcheck > from)
3934 return SUCCEED;
3935
3936 zbx_tm_add(&tm, 1, base);
3937 if (-1 == (next = mktime(&tm)))
3938 {
3939 *error = zbx_strdup(*error, zbx_strerror(errno));
3940 return FAIL;
3941 }
3942 }
3943
3944 return FAIL;
3945 }
3946
dc_function_calculate_nextcheck(const zbx_trigger_timer_t * timer,time_t from,zbx_uint64_t seed)3947 static int dc_function_calculate_nextcheck(const zbx_trigger_timer_t *timer, time_t from, zbx_uint64_t seed)
3948 {
3949 if (ZBX_TRIGGER_TIMER_FUNCTION_TIME == timer->type || ZBX_TRIGGER_TIMER_TRIGGER == timer->type)
3950 {
3951 int nextcheck;
3952
3953 nextcheck = ZBX_TIMER_DELAY * (int)(from / (time_t)ZBX_TIMER_DELAY) +
3954 (int)(seed % (zbx_uint64_t)ZBX_TIMER_DELAY);
3955
3956 while (nextcheck <= from)
3957 nextcheck += ZBX_TIMER_DELAY;
3958
3959 return nextcheck;
3960 }
3961 else if (ZBX_TRIGGER_TIMER_FUNCTION_TREND == timer->type)
3962 {
3963 struct tm tm;
3964 time_t nextcheck;
3965 int offsets[ZBX_TIME_UNIT_COUNT] = {0, 0, 0, SEC_PER_MIN * 10,
3966 SEC_PER_HOUR + SEC_PER_MIN * 10, SEC_PER_HOUR + SEC_PER_MIN * 10,
3967 SEC_PER_HOUR + SEC_PER_MIN * 10, SEC_PER_HOUR + SEC_PER_MIN * 10};
3968 int periods[ZBX_TIME_UNIT_COUNT] = {0, 0, 0, SEC_PER_MIN * 10, SEC_PER_HOUR,
3969 SEC_PER_HOUR * 11, SEC_PER_DAY - SEC_PER_HOUR, SEC_PER_DAY - SEC_PER_HOUR};
3970
3971 if (ZBX_TIME_UNIT_HOUR == timer->trend_base)
3972 {
3973 localtime_r(&from, &tm);
3974 zbx_tm_round_up(&tm, timer->trend_base);
3975
3976 if (-1 == (nextcheck = mktime(&tm)))
3977 {
3978 zabbix_log(LOG_LEVEL_WARNING, "cannot calculate trend function \"" ZBX_FS_UI64
3979 "\" schedule: %s", timer->objectid, zbx_strerror(errno));
3980 THIS_SHOULD_NEVER_HAPPEN;
3981
3982 return 0;
3983 }
3984 }
3985 else
3986 {
3987 int ret = FAIL;
3988 char *error = NULL, *period_shift;
3989
3990 if (NULL != (period_shift = strchr(timer->parameter, ':')))
3991 {
3992 period_shift++;
3993 ret = dc_function_calculate_trends_nextcheck(from, period_shift, timer->trend_base,
3994 &nextcheck, &error);
3995 }
3996 else
3997 error = zbx_dsprintf(NULL, "invalid first parameter");
3998
3999 if (FAIL == ret)
4000 {
4001 zabbix_log(LOG_LEVEL_WARNING, "cannot calculate trend function \"" ZBX_FS_UI64
4002 "\" schedule: %s", timer->objectid, error);
4003 zbx_free(error);
4004
4005 return 0;
4006 }
4007 }
4008
4009 return nextcheck + offsets[timer->trend_base] + seed % periods[timer->trend_base];
4010 }
4011
4012 THIS_SHOULD_NEVER_HAPPEN;
4013
4014 return 0;
4015 }
4016
4017 /******************************************************************************
4018 * *
4019 * Function: dc_trigger_function_timer_create *
4020 * *
4021 * Purpose: create trigger timer based on the trend function *
4022 * *
4023 * Return value: Created timer or NULL in the case of error. *
4024 * *
4025 ******************************************************************************/
dc_trigger_function_timer_create(ZBX_DC_FUNCTION * function)4026 static zbx_trigger_timer_t *dc_trigger_function_timer_create(ZBX_DC_FUNCTION *function)
4027 {
4028 zbx_trigger_timer_t *timer;
4029 zbx_time_unit_t trend_base;
4030 zbx_uint32_t type;
4031
4032 if (ZBX_FUNCTION_TYPE_TRENDS == function->type)
4033 {
4034 char *error = NULL;
4035
4036 if (FAIL == zbx_trends_parse_base(function->parameter, &trend_base, &error))
4037 {
4038 zabbix_log(LOG_LEVEL_WARNING, "cannot parse function " ZBX_FS_UI64 " period base: %s",
4039 function->functionid, error);
4040 zbx_free(error);
4041 return NULL;
4042 }
4043 type = ZBX_TRIGGER_TIMER_FUNCTION_TREND;
4044 }
4045 else
4046 {
4047 trend_base = ZBX_TIME_UNIT_UNKNOWN;
4048 type = ZBX_TRIGGER_TIMER_FUNCTION_TIME;
4049 }
4050
4051 timer = (zbx_trigger_timer_t *)__config_mem_malloc_func(NULL, sizeof(zbx_trigger_timer_t));
4052
4053 timer->objectid = function->functionid;
4054 timer->triggerid = function->triggerid;
4055 timer->revision = function->revision;
4056 timer->trend_base = trend_base;
4057 timer->lock = 0;
4058 timer->type = type;
4059
4060 function->timer_revision = function->revision;
4061
4062 if (ZBX_FUNCTION_TYPE_TRENDS == function->type)
4063 DCstrpool_replace(0, &timer->parameter, function->parameter);
4064 else
4065 timer->parameter = NULL;
4066
4067 return timer;
4068 }
4069
4070 /******************************************************************************
4071 * *
4072 * Function: dc_trigger_timer_create *
4073 * *
4074 * Purpose: create trigger timer based on the specified trigger *
4075 * *
4076 * Return value: Created timer or NULL in the case of error. *
4077 * *
4078 ******************************************************************************/
dc_trigger_timer_create(ZBX_DC_TRIGGER * trigger)4079 static zbx_trigger_timer_t *dc_trigger_timer_create(ZBX_DC_TRIGGER *trigger)
4080 {
4081 zbx_trigger_timer_t *timer;
4082
4083 timer = (zbx_trigger_timer_t *)__config_mem_malloc_func(NULL, sizeof(zbx_trigger_timer_t));
4084 timer->type = ZBX_TRIGGER_TIMER_TRIGGER;
4085 timer->objectid = trigger->triggerid;
4086 timer->triggerid = trigger->triggerid;
4087 timer->revision = trigger->revision;
4088 timer->trend_base = ZBX_TIME_UNIT_UNKNOWN;
4089 timer->lock = 0;
4090 timer->parameter = NULL;
4091
4092 trigger->timer_revision = trigger->revision;
4093
4094 return timer;
4095 }
4096
4097 /******************************************************************************
4098 * *
4099 * Function: dc_trigger_timer_free *
4100 * *
4101 * Purpose: free trigger timer *
4102 * *
4103 ******************************************************************************/
dc_trigger_timer_free(zbx_trigger_timer_t * timer)4104 static void dc_trigger_timer_free(zbx_trigger_timer_t *timer)
4105 {
4106 if (NULL != timer->parameter)
4107 zbx_strpool_release(timer->parameter);
4108
4109 __config_mem_free_func(timer);
4110 }
4111
4112 /******************************************************************************
4113 * *
4114 * Function: dc_schedule_trigger_timer *
4115 * *
4116 * Purpose: schedule trigger timer to be executed at the specified time *
4117 * *
4118 * Parameter: timer - [IN] the timer to schedule *
4119 * eval_ts - [IN] the history snapshot time, by default (NULL) *
4120 * execution time will be used. *
4121 * exec_ts - [IN] the tiemer execution time *
4122 * *
4123 ******************************************************************************/
dc_schedule_trigger_timer(zbx_trigger_timer_t * timer,const zbx_timespec_t * eval_ts,const zbx_timespec_t * exec_ts)4124 static void dc_schedule_trigger_timer(zbx_trigger_timer_t *timer, const zbx_timespec_t *eval_ts,
4125 const zbx_timespec_t *exec_ts)
4126 {
4127 zbx_binary_heap_elem_t elem;
4128
4129 if (NULL == eval_ts)
4130 timer->eval_ts = *exec_ts;
4131 else
4132 timer->eval_ts = *eval_ts;
4133
4134 timer->exec_ts = *exec_ts;
4135
4136 elem.key = 0;
4137 elem.data = (void *)timer;
4138 zbx_binary_heap_insert(&config->trigger_queue, &elem);
4139 }
4140
4141 /******************************************************************************
4142 * *
4143 * Function: dc_schedule_new_trigger_timers *
4144 * *
4145 * Purpose: set timer schedule and evaluation times based on functions and *
4146 * old trend function queue *
4147 * *
4148 ******************************************************************************/
dc_schedule_trigger_timers(zbx_hashset_t * trend_queue,int now)4149 static void dc_schedule_trigger_timers(zbx_hashset_t *trend_queue, int now)
4150 {
4151 ZBX_DC_FUNCTION *function;
4152 ZBX_DC_TRIGGER *trigger;
4153 zbx_trigger_timer_t *timer, *old;
4154 zbx_timespec_t ts;
4155 zbx_hashset_iter_t iter;
4156
4157 ts.ns = 0;
4158
4159 zbx_hashset_iter_reset(&config->functions, &iter);
4160 while (NULL != (function = (ZBX_DC_FUNCTION *)zbx_hashset_iter_next(&iter)))
4161 {
4162 if (ZBX_FUNCTION_TYPE_TIMER != function->type && ZBX_FUNCTION_TYPE_TRENDS != function->type)
4163 continue;
4164
4165 if (function->timer_revision == function->revision)
4166 continue;
4167
4168 if (NULL == (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &function->triggerid)))
4169 continue;
4170
4171 if (TRIGGER_STATUS_ENABLED != trigger->status || TRIGGER_FUNCTIONAL_TRUE != trigger->functional)
4172 continue;
4173
4174 if (NULL == (timer = dc_trigger_function_timer_create(function)))
4175 continue;
4176
4177 if (NULL != trend_queue && NULL != (old = (zbx_trigger_timer_t *)zbx_hashset_search(trend_queue,
4178 &timer->objectid)) && old->eval_ts.sec < now + 10 * SEC_PER_MIN)
4179 {
4180 /* if the trigger was scheduled during next 10 minutes */
4181 /* schedule its evaluation later to reduce server startup load */
4182 if (old->eval_ts.sec < now + 10 * SEC_PER_MIN)
4183 ts.sec = now + 10 * SEC_PER_MIN + timer->triggerid % (10 * SEC_PER_MIN);
4184 else
4185 ts.sec = old->eval_ts.sec;
4186
4187 dc_schedule_trigger_timer(timer, &old->eval_ts, &ts);
4188 }
4189 else
4190 {
4191 if (0 == (ts.sec = dc_function_calculate_nextcheck(timer, now, timer->triggerid)))
4192 {
4193 dc_trigger_timer_free(timer);
4194 function->timer_revision = 0;
4195 }
4196 else
4197 dc_schedule_trigger_timer(timer, NULL, &ts);
4198 }
4199 }
4200
4201 zbx_hashset_iter_reset(&config->triggers, &iter);
4202 while (NULL != (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_iter_next(&iter)))
4203 {
4204 if (ZBX_TRIGGER_TIMER_DEFAULT == trigger->timer)
4205 continue;
4206
4207 if (trigger->timer_revision == trigger->revision)
4208 continue;
4209
4210 if (NULL == (timer = dc_trigger_timer_create(trigger)))
4211 continue;
4212
4213 if (0 == (ts.sec = dc_function_calculate_nextcheck(timer, now, timer->triggerid)))
4214 {
4215 dc_trigger_timer_free(timer);
4216 trigger->timer_revision = 0;
4217 }
4218 else
4219 dc_schedule_trigger_timer(timer, NULL, &ts);
4220
4221 }
4222 }
4223
DCsync_functions(zbx_dbsync_t * sync)4224 static void DCsync_functions(zbx_dbsync_t *sync)
4225 {
4226 char **row;
4227 zbx_uint64_t rowid;
4228 unsigned char tag;
4229
4230 ZBX_DC_ITEM *item;
4231 ZBX_DC_FUNCTION *function;
4232
4233 int found, ret;
4234 zbx_uint64_t itemid, functionid, triggerid;
4235
4236 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4237
4238 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
4239 {
4240 /* removed rows will be always added at the end */
4241 if (ZBX_DBSYNC_ROW_REMOVE == tag)
4242 break;
4243
4244 ZBX_STR2UINT64(itemid, row[0]);
4245 ZBX_STR2UINT64(functionid, row[1]);
4246 ZBX_STR2UINT64(triggerid, row[4]);
4247
4248 if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemid)))
4249 {
4250 /* Item could have been created after we have selected them in the */
4251 /* previous queries. However, we shall avoid the check for functions being the */
4252 /* same as in the trigger expression, because that is somewhat expensive, not */
4253 /* 100% (think functions keeping their functionid, but changing their function */
4254 /* or parameters), and even if there is an inconsistency, we can live with it. */
4255
4256 continue;
4257 }
4258
4259 /* process function information */
4260
4261 function = (ZBX_DC_FUNCTION *)DCfind_id(&config->functions, functionid, sizeof(ZBX_DC_FUNCTION), &found);
4262
4263 if (1 == found)
4264 {
4265 if (function->itemid != itemid)
4266 {
4267 ZBX_DC_ITEM *item_last;
4268
4269 if (NULL != (item_last = zbx_hashset_search(&config->items, &function->itemid)))
4270 {
4271 item_last->update_triggers = 1;
4272 if (NULL != item_last->triggers)
4273 {
4274 config->items.mem_free_func(item_last->triggers);
4275 item_last->triggers = NULL;
4276 }
4277 }
4278 }
4279 }
4280 else
4281 function->timer_revision = 0;
4282
4283 function->triggerid = triggerid;
4284 function->itemid = itemid;
4285 DCstrpool_replace(found, &function->function, row[2]);
4286 DCstrpool_replace(found, &function->parameter, row[3]);
4287
4288 function->type = zbx_get_function_type(function->function);
4289 function->revision = config->sync_start_ts;
4290
4291 item->update_triggers = 1;
4292 if (NULL != item->triggers)
4293 item->triggers[0] = NULL;
4294 }
4295
4296 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
4297 {
4298 if (NULL == (function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &rowid)))
4299 continue;
4300
4301 if (NULL != (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &function->itemid)))
4302 {
4303 item->update_triggers = 1;
4304 if (NULL != item->triggers)
4305 {
4306 config->items.mem_free_func(item->triggers);
4307 item->triggers = NULL;
4308 }
4309 }
4310
4311 zbx_strpool_release(function->function);
4312 zbx_strpool_release(function->parameter);
4313
4314 zbx_hashset_remove_direct(&config->functions, function);
4315 }
4316
4317 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4318 }
4319
4320 /******************************************************************************
4321 * *
4322 * Function: dc_regexp_remove_expression *
4323 * *
4324 * Purpose: removes expression from regexp *
4325 * *
4326 ******************************************************************************/
dc_regexp_remove_expression(const char * regexp_name,zbx_uint64_t expressionid)4327 static ZBX_DC_REGEXP *dc_regexp_remove_expression(const char *regexp_name, zbx_uint64_t expressionid)
4328 {
4329 ZBX_DC_REGEXP *regexp, regexp_local;
4330 int index;
4331
4332 regexp_local.name = regexp_name;
4333
4334 if (NULL == (regexp = (ZBX_DC_REGEXP *)zbx_hashset_search(&config->regexps, ®exp_local)))
4335 return NULL;
4336
4337 if (FAIL == (index = zbx_vector_uint64_search(®exp->expressionids, expressionid,
4338 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
4339 {
4340 return NULL;
4341 }
4342
4343 zbx_vector_uint64_remove_noorder(®exp->expressionids, index);
4344
4345 return regexp;
4346 }
4347
4348 /******************************************************************************
4349 * *
4350 * Function: DCsync_expressions *
4351 * *
4352 * Purpose: Updates expressions configuration cache *
4353 * *
4354 * Parameters: result - [IN] the result of expressions database select *
4355 * *
4356 ******************************************************************************/
DCsync_expressions(zbx_dbsync_t * sync)4357 static void DCsync_expressions(zbx_dbsync_t *sync)
4358 {
4359 char **row;
4360 zbx_uint64_t rowid;
4361 unsigned char tag;
4362 zbx_hashset_iter_t iter;
4363 ZBX_DC_EXPRESSION *expression;
4364 ZBX_DC_REGEXP *regexp, regexp_local;
4365 zbx_uint64_t expressionid;
4366 int found, ret;
4367
4368 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4369
4370 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
4371 {
4372 /* removed rows will be always added at the end */
4373 if (ZBX_DBSYNC_ROW_REMOVE == tag)
4374 break;
4375
4376 ZBX_STR2UINT64(expressionid, row[1]);
4377 expression = (ZBX_DC_EXPRESSION *)DCfind_id(&config->expressions, expressionid, sizeof(ZBX_DC_EXPRESSION), &found);
4378
4379 if (0 != found)
4380 dc_regexp_remove_expression(expression->regexp, expressionid);
4381
4382 DCstrpool_replace(found, &expression->regexp, row[0]);
4383 DCstrpool_replace(found, &expression->expression, row[2]);
4384 ZBX_STR2UCHAR(expression->type, row[3]);
4385 ZBX_STR2UCHAR(expression->case_sensitive, row[5]);
4386 expression->delimiter = *row[4];
4387
4388 regexp_local.name = row[0];
4389
4390 if (NULL == (regexp = (ZBX_DC_REGEXP *)zbx_hashset_search(&config->regexps, ®exp_local)))
4391 {
4392 DCstrpool_replace(0, ®exp_local.name, row[0]);
4393 zbx_vector_uint64_create_ext(®exp_local.expressionids,
4394 __config_mem_malloc_func,
4395 __config_mem_realloc_func,
4396 __config_mem_free_func);
4397
4398 regexp = (ZBX_DC_REGEXP *)zbx_hashset_insert(&config->regexps, ®exp_local, sizeof(ZBX_DC_REGEXP));
4399 }
4400
4401 zbx_vector_uint64_append(®exp->expressionids, expressionid);
4402 }
4403
4404 /* remove regexps with no expressions related to it */
4405 zbx_hashset_iter_reset(&config->regexps, &iter);
4406
4407 while (NULL != (regexp = (ZBX_DC_REGEXP *)zbx_hashset_iter_next(&iter)))
4408 {
4409 if (0 < regexp->expressionids.values_num)
4410 continue;
4411
4412 zbx_strpool_release(regexp->name);
4413 zbx_vector_uint64_destroy(®exp->expressionids);
4414 zbx_hashset_iter_remove(&iter);
4415 }
4416
4417 /* remove unused expressions */
4418 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
4419 {
4420 if (NULL == (expression = (ZBX_DC_EXPRESSION *)zbx_hashset_search(&config->expressions, &rowid)))
4421 continue;
4422
4423 if (NULL != (regexp = dc_regexp_remove_expression(expression->regexp, expression->expressionid)))
4424 {
4425 if (0 == regexp->expressionids.values_num)
4426 {
4427 zbx_strpool_release(regexp->name);
4428 zbx_vector_uint64_destroy(®exp->expressionids);
4429 zbx_hashset_remove_direct(&config->regexps, regexp);
4430 }
4431 }
4432
4433 zbx_strpool_release(expression->expression);
4434 zbx_strpool_release(expression->regexp);
4435 zbx_hashset_remove_direct(&config->expressions, expression);
4436 }
4437
4438 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4439 }
4440
4441 /******************************************************************************
4442 * *
4443 * Function: DCsync_actions *
4444 * *
4445 * Purpose: Updates actions configuration cache *
4446 * *
4447 * Parameters: sync - [IN] the db synchronization data *
4448 * *
4449 * Comments: The result contains the following fields: *
4450 * 0 - actionid *
4451 * 1 - eventsource *
4452 * 2 - evaltype *
4453 * 3 - formula *
4454 * *
4455 ******************************************************************************/
DCsync_actions(zbx_dbsync_t * sync)4456 static void DCsync_actions(zbx_dbsync_t *sync)
4457 {
4458 char **row;
4459 zbx_uint64_t rowid;
4460 unsigned char tag;
4461 zbx_uint64_t actionid;
4462 zbx_dc_action_t *action;
4463 int found, ret;
4464
4465 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4466
4467 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
4468 {
4469 /* removed rows will be always added at the end */
4470 if (ZBX_DBSYNC_ROW_REMOVE == tag)
4471 break;
4472
4473 ZBX_STR2UINT64(actionid, row[0]);
4474 action = (zbx_dc_action_t *)DCfind_id(&config->actions, actionid, sizeof(zbx_dc_action_t), &found);
4475
4476 ZBX_STR2UCHAR(action->eventsource, row[1]);
4477 ZBX_STR2UCHAR(action->evaltype, row[2]);
4478
4479 DCstrpool_replace(found, &action->formula, row[3]);
4480
4481 if (0 == found)
4482 {
4483 if (EVENT_SOURCE_INTERNAL == action->eventsource)
4484 config->internal_actions++;
4485
4486 zbx_vector_ptr_create_ext(&action->conditions, __config_mem_malloc_func,
4487 __config_mem_realloc_func, __config_mem_free_func);
4488
4489 zbx_vector_ptr_reserve(&action->conditions, 1);
4490
4491 action->opflags = ZBX_ACTION_OPCLASS_NONE;
4492 }
4493 }
4494
4495 /* remove deleted actions */
4496 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
4497 {
4498 if (NULL == (action = (zbx_dc_action_t *)zbx_hashset_search(&config->actions, &rowid)))
4499 continue;
4500
4501 if (EVENT_SOURCE_INTERNAL == action->eventsource)
4502 config->internal_actions--;
4503
4504 zbx_strpool_release(action->formula);
4505 zbx_vector_ptr_destroy(&action->conditions);
4506
4507 zbx_hashset_remove_direct(&config->actions, action);
4508 }
4509
4510 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4511 }
4512
4513 /******************************************************************************
4514 * *
4515 * Function: DCsync_action_ops *
4516 * *
4517 * Purpose: Updates action operation class flags in configuration cache *
4518 * *
4519 * Parameters: sync - [IN] the db synchronization data *
4520 * *
4521 * Comments: The result contains the following fields: *
4522 * 0 - actionid *
4523 * 1 - action operation class flags *
4524 * *
4525 ******************************************************************************/
DCsync_action_ops(zbx_dbsync_t * sync)4526 static void DCsync_action_ops(zbx_dbsync_t *sync)
4527 {
4528 char **row;
4529 zbx_uint64_t rowid;
4530 unsigned char tag;
4531 zbx_uint64_t actionid;
4532 zbx_dc_action_t *action;
4533
4534 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4535
4536 while (SUCCEED == zbx_dbsync_next(sync, &rowid, &row, &tag))
4537 {
4538 ZBX_STR2UINT64(actionid, row[0]);
4539
4540 if (NULL == (action = (zbx_dc_action_t *)zbx_hashset_search(&config->actions, &actionid)))
4541 continue;
4542
4543 action->opflags = atoi(row[1]);
4544 }
4545
4546 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4547 }
4548
4549 /******************************************************************************
4550 * *
4551 * Function: dc_compare_action_conditions_by_type *
4552 * *
4553 * Purpose: compare two action conditions by their type *
4554 * *
4555 * Comments: This function is used to sort action conditions by type. *
4556 * *
4557 ******************************************************************************/
dc_compare_action_conditions_by_type(const void * d1,const void * d2)4558 static int dc_compare_action_conditions_by_type(const void *d1, const void *d2)
4559 {
4560 zbx_dc_action_condition_t *c1 = *(zbx_dc_action_condition_t **)d1;
4561 zbx_dc_action_condition_t *c2 = *(zbx_dc_action_condition_t **)d2;
4562
4563 ZBX_RETURN_IF_NOT_EQUAL(c1->conditiontype, c2->conditiontype);
4564
4565 return 0;
4566 }
4567
4568 /******************************************************************************
4569 * *
4570 * Function: DCsync_action_conditions *
4571 * *
4572 * Purpose: Updates action conditions configuration cache *
4573 * *
4574 * Parameters: sync - [IN] the db synchronization data *
4575 * *
4576 * Comments: The result contains the following fields: *
4577 * 0 - conditionid *
4578 * 1 - actionid *
4579 * 2 - conditiontype *
4580 * 3 - operator *
4581 * 4 - value *
4582 * *
4583 ******************************************************************************/
DCsync_action_conditions(zbx_dbsync_t * sync)4584 static void DCsync_action_conditions(zbx_dbsync_t *sync)
4585 {
4586 char **row;
4587 zbx_uint64_t rowid;
4588 unsigned char tag;
4589 zbx_uint64_t actionid, conditionid;
4590 zbx_dc_action_t *action;
4591 zbx_dc_action_condition_t *condition;
4592 int found, i, index, ret;
4593 zbx_vector_ptr_t actions;
4594
4595 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4596
4597 zbx_vector_ptr_create(&actions);
4598
4599 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
4600 {
4601 /* removed rows will be always added at the end */
4602 if (ZBX_DBSYNC_ROW_REMOVE == tag)
4603 break;
4604
4605 ZBX_STR2UINT64(actionid, row[1]);
4606
4607 if (NULL == (action = (zbx_dc_action_t *)zbx_hashset_search(&config->actions, &actionid)))
4608 continue;
4609
4610 ZBX_STR2UINT64(conditionid, row[0]);
4611
4612 condition = (zbx_dc_action_condition_t *)DCfind_id(&config->action_conditions, conditionid, sizeof(zbx_dc_action_condition_t),
4613 &found);
4614
4615 ZBX_STR2UCHAR(condition->conditiontype, row[2]);
4616 ZBX_STR2UCHAR(condition->op, row[3]);
4617
4618 DCstrpool_replace(found, &condition->value, row[4]);
4619 DCstrpool_replace(found, &condition->value2, row[5]);
4620
4621 if (0 == found)
4622 {
4623 condition->actionid = actionid;
4624 zbx_vector_ptr_append(&action->conditions, condition);
4625 }
4626
4627 if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype)
4628 zbx_vector_ptr_append(&actions, action);
4629 }
4630
4631 /* remove deleted conditions */
4632 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
4633 {
4634 if (NULL == (condition = (zbx_dc_action_condition_t *)zbx_hashset_search(&config->action_conditions, &rowid)))
4635 continue;
4636
4637 if (NULL != (action = (zbx_dc_action_t *)zbx_hashset_search(&config->actions, &condition->actionid)))
4638 {
4639 if (FAIL != (index = zbx_vector_ptr_search(&action->conditions, condition,
4640 ZBX_DEFAULT_PTR_COMPARE_FUNC)))
4641 {
4642 zbx_vector_ptr_remove_noorder(&action->conditions, index);
4643
4644 if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype)
4645 zbx_vector_ptr_append(&actions, action);
4646 }
4647 }
4648
4649 zbx_strpool_release(condition->value);
4650 zbx_strpool_release(condition->value2);
4651
4652 zbx_hashset_remove_direct(&config->action_conditions, condition);
4653 }
4654
4655 /* sort conditions by type */
4656
4657 zbx_vector_ptr_sort(&actions, ZBX_DEFAULT_PTR_COMPARE_FUNC);
4658 zbx_vector_ptr_uniq(&actions, ZBX_DEFAULT_PTR_COMPARE_FUNC);
4659
4660 for (i = 0; i < actions.values_num; i++)
4661 {
4662 action = (zbx_dc_action_t *)actions.values[i];
4663
4664 if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype)
4665 zbx_vector_ptr_sort(&action->conditions, dc_compare_action_conditions_by_type);
4666 }
4667
4668 zbx_vector_ptr_destroy(&actions);
4669
4670 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4671 }
4672
4673 /******************************************************************************
4674 * *
4675 * Function: DCsync_correlations *
4676 * *
4677 * Purpose: Updates correlations configuration cache *
4678 * *
4679 * Parameters: sync - [IN] the db synchronization data *
4680 * *
4681 * Comments: The result contains the following fields: *
4682 * 0 - correlationid *
4683 * 1 - name *
4684 * 2 - evaltype *
4685 * 3 - formula *
4686 * *
4687 ******************************************************************************/
DCsync_correlations(zbx_dbsync_t * sync)4688 static void DCsync_correlations(zbx_dbsync_t *sync)
4689 {
4690 char **row;
4691 zbx_uint64_t rowid;
4692 unsigned char tag;
4693 zbx_uint64_t correlationid;
4694 zbx_dc_correlation_t *correlation;
4695 int found, ret;
4696
4697 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4698
4699 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
4700 {
4701 /* removed rows will be always added at the end */
4702 if (ZBX_DBSYNC_ROW_REMOVE == tag)
4703 break;
4704
4705 ZBX_STR2UINT64(correlationid, row[0]);
4706
4707 correlation = (zbx_dc_correlation_t *)DCfind_id(&config->correlations, correlationid, sizeof(zbx_dc_correlation_t), &found);
4708
4709 if (0 == found)
4710 {
4711 zbx_vector_ptr_create_ext(&correlation->conditions, __config_mem_malloc_func,
4712 __config_mem_realloc_func, __config_mem_free_func);
4713
4714 zbx_vector_ptr_create_ext(&correlation->operations, __config_mem_malloc_func,
4715 __config_mem_realloc_func, __config_mem_free_func);
4716 }
4717
4718 DCstrpool_replace(found, &correlation->name, row[1]);
4719 DCstrpool_replace(found, &correlation->formula, row[3]);
4720
4721 ZBX_STR2UCHAR(correlation->evaltype, row[2]);
4722 }
4723
4724 /* remove deleted correlations */
4725
4726 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
4727 {
4728 if (NULL == (correlation = (zbx_dc_correlation_t *)zbx_hashset_search(&config->correlations, &rowid)))
4729 continue;
4730
4731 zbx_strpool_release(correlation->name);
4732 zbx_strpool_release(correlation->formula);
4733
4734 zbx_vector_ptr_destroy(&correlation->conditions);
4735 zbx_vector_ptr_destroy(&correlation->operations);
4736
4737 zbx_hashset_remove_direct(&config->correlations, correlation);
4738 }
4739
4740 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4741 }
4742
4743 /******************************************************************************
4744 * *
4745 * Function: dc_corr_condition_get_size *
4746 * *
4747 * Purpose: get the actual size of correlation condition data depending on *
4748 * its type *
4749 * *
4750 * Parameters: type - [IN] the condition type *
4751 * *
4752 * Return value: the size *
4753 * *
4754 ******************************************************************************/
dc_corr_condition_get_size(unsigned char type)4755 static size_t dc_corr_condition_get_size(unsigned char type)
4756 {
4757 switch (type)
4758 {
4759 case ZBX_CORR_CONDITION_OLD_EVENT_TAG:
4760 /* break; is not missing here */
4761 case ZBX_CORR_CONDITION_NEW_EVENT_TAG:
4762 return offsetof(zbx_dc_corr_condition_t, data) + sizeof(zbx_dc_corr_condition_tag_t);
4763 case ZBX_CORR_CONDITION_NEW_EVENT_HOSTGROUP:
4764 return offsetof(zbx_dc_corr_condition_t, data) + sizeof(zbx_dc_corr_condition_group_t);
4765 case ZBX_CORR_CONDITION_EVENT_TAG_PAIR:
4766 return offsetof(zbx_dc_corr_condition_t, data) + sizeof(zbx_dc_corr_condition_tag_pair_t);
4767 case ZBX_CORR_CONDITION_OLD_EVENT_TAG_VALUE:
4768 /* break; is not missing here */
4769 case ZBX_CORR_CONDITION_NEW_EVENT_TAG_VALUE:
4770 return offsetof(zbx_dc_corr_condition_t, data) + sizeof(zbx_dc_corr_condition_tag_value_t);
4771 }
4772
4773 THIS_SHOULD_NEVER_HAPPEN;
4774 return 0;
4775 }
4776
4777 /******************************************************************************
4778 * *
4779 * Function: dc_corr_condition_init_data *
4780 * *
4781 * Purpose: initializes correlation condition data from database row *
4782 * *
4783 * Parameters: condition - [IN] the condition to initialize *
4784 * found - [IN] 0 - new condition, 1 - cached condition *
4785 * row - [IN] the database row containing condition data *
4786 * *
4787 ******************************************************************************/
dc_corr_condition_init_data(zbx_dc_corr_condition_t * condition,int found,DB_ROW row)4788 static void dc_corr_condition_init_data(zbx_dc_corr_condition_t *condition, int found, DB_ROW row)
4789 {
4790 if (ZBX_CORR_CONDITION_OLD_EVENT_TAG == condition->type || ZBX_CORR_CONDITION_NEW_EVENT_TAG == condition->type)
4791 {
4792 DCstrpool_replace(found, &condition->data.tag.tag, row[0]);
4793 return;
4794 }
4795
4796 row++;
4797
4798 if (ZBX_CORR_CONDITION_OLD_EVENT_TAG_VALUE == condition->type ||
4799 ZBX_CORR_CONDITION_NEW_EVENT_TAG_VALUE == condition->type)
4800 {
4801 DCstrpool_replace(found, &condition->data.tag_value.tag, row[0]);
4802 DCstrpool_replace(found, &condition->data.tag_value.value, row[1]);
4803 ZBX_STR2UCHAR(condition->data.tag_value.op, row[2]);
4804 return;
4805 }
4806
4807 row += 3;
4808
4809 if (ZBX_CORR_CONDITION_NEW_EVENT_HOSTGROUP == condition->type)
4810 {
4811 ZBX_STR2UINT64(condition->data.group.groupid, row[0]);
4812 ZBX_STR2UCHAR(condition->data.group.op, row[1]);
4813 return;
4814 }
4815
4816 row += 2;
4817
4818 if (ZBX_CORR_CONDITION_EVENT_TAG_PAIR == condition->type)
4819 {
4820 DCstrpool_replace(found, &condition->data.tag_pair.oldtag, row[0]);
4821 DCstrpool_replace(found, &condition->data.tag_pair.newtag, row[1]);
4822 return;
4823 }
4824 }
4825
4826 /******************************************************************************
4827 * *
4828 * Function: corr_condition_free_data *
4829 * *
4830 * Purpose: frees correlation condition data *
4831 * *
4832 * Parameters: condition - [IN] the condition *
4833 * *
4834 ******************************************************************************/
corr_condition_free_data(zbx_dc_corr_condition_t * condition)4835 static void corr_condition_free_data(zbx_dc_corr_condition_t *condition)
4836 {
4837 switch (condition->type)
4838 {
4839 case ZBX_CORR_CONDITION_OLD_EVENT_TAG:
4840 /* break; is not missing here */
4841 case ZBX_CORR_CONDITION_NEW_EVENT_TAG:
4842 zbx_strpool_release(condition->data.tag.tag);
4843 break;
4844 case ZBX_CORR_CONDITION_EVENT_TAG_PAIR:
4845 zbx_strpool_release(condition->data.tag_pair.oldtag);
4846 zbx_strpool_release(condition->data.tag_pair.newtag);
4847 break;
4848 case ZBX_CORR_CONDITION_OLD_EVENT_TAG_VALUE:
4849 /* break; is not missing here */
4850 case ZBX_CORR_CONDITION_NEW_EVENT_TAG_VALUE:
4851 zbx_strpool_release(condition->data.tag_value.tag);
4852 zbx_strpool_release(condition->data.tag_value.value);
4853 break;
4854 }
4855 }
4856
4857 /******************************************************************************
4858 * *
4859 * Function: dc_compare_corr_conditions_by_type *
4860 * *
4861 * Purpose: compare two correlation conditions by their type *
4862 * *
4863 * Comments: This function is used to sort correlation conditions by type. *
4864 * *
4865 ******************************************************************************/
dc_compare_corr_conditions_by_type(const void * d1,const void * d2)4866 static int dc_compare_corr_conditions_by_type(const void *d1, const void *d2)
4867 {
4868 zbx_dc_corr_condition_t *c1 = *(zbx_dc_corr_condition_t **)d1;
4869 zbx_dc_corr_condition_t *c2 = *(zbx_dc_corr_condition_t **)d2;
4870
4871 ZBX_RETURN_IF_NOT_EQUAL(c1->type, c2->type);
4872
4873 return 0;
4874 }
4875
4876 /******************************************************************************
4877 * *
4878 * Function: DCsync_corr_conditions *
4879 * *
4880 * Purpose: Updates correlation conditions configuration cache *
4881 * *
4882 * Parameters: sync - [IN] the db synchronization data *
4883 * *
4884 * Comments: The result contains the following fields: *
4885 * 0 - corr_conditionid *
4886 * 1 - correlationid *
4887 * 2 - type *
4888 * 3 - corr_condition_tag.tag *
4889 * 4 - corr_condition_tagvalue.tag *
4890 * 5 - corr_condition_tagvalue.value *
4891 * 6 - corr_condition_tagvalue.operator *
4892 * 7 - corr_condition_group.groupid *
4893 * 8 - corr_condition_group.operator *
4894 * 9 - corr_condition_tagpair.oldtag *
4895 * 10 - corr_condition_tagpair.newtag *
4896 * *
4897 ******************************************************************************/
DCsync_corr_conditions(zbx_dbsync_t * sync)4898 static void DCsync_corr_conditions(zbx_dbsync_t *sync)
4899 {
4900 char **row;
4901 zbx_uint64_t rowid;
4902 unsigned char tag;
4903 zbx_uint64_t conditionid, correlationid;
4904 zbx_dc_corr_condition_t *condition;
4905 zbx_dc_correlation_t *correlation;
4906 int found, ret, i, index;
4907 unsigned char type;
4908 size_t condition_size;
4909 zbx_vector_ptr_t correlations;
4910
4911 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4912
4913 zbx_vector_ptr_create(&correlations);
4914
4915 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
4916 {
4917 /* removed rows will be always added at the end */
4918 if (ZBX_DBSYNC_ROW_REMOVE == tag)
4919 break;
4920
4921 ZBX_STR2UINT64(correlationid, row[1]);
4922
4923 if (NULL == (correlation = (zbx_dc_correlation_t *)zbx_hashset_search(&config->correlations, &correlationid)))
4924 continue;
4925
4926 ZBX_STR2UINT64(conditionid, row[0]);
4927 ZBX_STR2UCHAR(type, row[2]);
4928
4929 condition_size = dc_corr_condition_get_size(type);
4930 condition = (zbx_dc_corr_condition_t *)DCfind_id(&config->corr_conditions, conditionid, condition_size, &found);
4931
4932 condition->correlationid = correlationid;
4933 condition->type = type;
4934 dc_corr_condition_init_data(condition, found, row + 3);
4935
4936 if (0 == found)
4937 zbx_vector_ptr_append(&correlation->conditions, condition);
4938
4939 /* sort the conditions later */
4940 if (CONDITION_EVAL_TYPE_AND_OR == correlation->evaltype)
4941 zbx_vector_ptr_append(&correlations, correlation);
4942 }
4943
4944 /* remove deleted correlation conditions */
4945
4946 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
4947 {
4948 if (NULL == (condition = (zbx_dc_corr_condition_t *)zbx_hashset_search(&config->corr_conditions, &rowid)))
4949 continue;
4950
4951 /* remove condition from correlation->conditions vector */
4952 if (NULL != (correlation = (zbx_dc_correlation_t *)zbx_hashset_search(&config->correlations, &condition->correlationid)))
4953 {
4954 if (FAIL != (index = zbx_vector_ptr_search(&correlation->conditions, condition,
4955 ZBX_DEFAULT_PTR_COMPARE_FUNC)))
4956 {
4957 /* sort the conditions later */
4958 if (CONDITION_EVAL_TYPE_AND_OR == correlation->evaltype)
4959 zbx_vector_ptr_append(&correlations, correlation);
4960
4961 zbx_vector_ptr_remove_noorder(&correlation->conditions, index);
4962 }
4963 }
4964
4965 corr_condition_free_data(condition);
4966 zbx_hashset_remove_direct(&config->corr_conditions, condition);
4967 }
4968
4969 /* sort conditions by type */
4970
4971 zbx_vector_ptr_sort(&correlations, ZBX_DEFAULT_PTR_COMPARE_FUNC);
4972 zbx_vector_ptr_uniq(&correlations, ZBX_DEFAULT_PTR_COMPARE_FUNC);
4973
4974 for (i = 0; i < correlations.values_num; i++)
4975 {
4976 correlation = (zbx_dc_correlation_t *)correlations.values[i];
4977 zbx_vector_ptr_sort(&correlation->conditions, dc_compare_corr_conditions_by_type);
4978 }
4979
4980 zbx_vector_ptr_destroy(&correlations);
4981
4982 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4983 }
4984
4985 /******************************************************************************
4986 * *
4987 * Function: DCsync_corr_operations *
4988 * *
4989 * Purpose: Updates correlation operations configuration cache *
4990 * *
4991 * Parameters: result - [IN] the result of correlation operations database *
4992 * select *
4993 * *
4994 * Comments: The result contains the following fields: *
4995 * 0 - corr_operationid *
4996 * 1 - correlationid *
4997 * 2 - type *
4998 * *
4999 ******************************************************************************/
DCsync_corr_operations(zbx_dbsync_t * sync)5000 static void DCsync_corr_operations(zbx_dbsync_t *sync)
5001 {
5002 char **row;
5003 zbx_uint64_t rowid;
5004 unsigned char tag;
5005 zbx_uint64_t operationid, correlationid;
5006 zbx_dc_corr_operation_t *operation;
5007 zbx_dc_correlation_t *correlation;
5008 int found, ret, index;
5009 unsigned char type;
5010
5011 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
5012
5013 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
5014 {
5015 /* removed rows will be always added at the end */
5016 if (ZBX_DBSYNC_ROW_REMOVE == tag)
5017 break;
5018
5019 ZBX_STR2UINT64(correlationid, row[1]);
5020
5021 if (NULL == (correlation = (zbx_dc_correlation_t *)zbx_hashset_search(&config->correlations, &correlationid)))
5022 continue;
5023
5024 ZBX_STR2UINT64(operationid, row[0]);
5025 ZBX_STR2UCHAR(type, row[2]);
5026
5027 operation = (zbx_dc_corr_operation_t *)DCfind_id(&config->corr_operations, operationid, sizeof(zbx_dc_corr_operation_t), &found);
5028
5029 operation->type = type;
5030
5031 if (0 == found)
5032 {
5033 operation->correlationid = correlationid;
5034 zbx_vector_ptr_append(&correlation->operations, operation);
5035 }
5036 }
5037
5038 /* remove deleted correlation operations */
5039
5040 /* remove deleted actions */
5041 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
5042 {
5043 if (NULL == (operation = (zbx_dc_corr_operation_t *)zbx_hashset_search(&config->corr_operations, &rowid)))
5044 continue;
5045
5046 /* remove operation from correlation->conditions vector */
5047 if (NULL != (correlation = (zbx_dc_correlation_t *)zbx_hashset_search(&config->correlations, &operation->correlationid)))
5048 {
5049 if (FAIL != (index = zbx_vector_ptr_search(&correlation->operations, operation,
5050 ZBX_DEFAULT_PTR_COMPARE_FUNC)))
5051 {
5052 zbx_vector_ptr_remove_noorder(&correlation->operations, index);
5053 }
5054 }
5055 zbx_hashset_remove_direct(&config->corr_operations, operation);
5056 }
5057
5058 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
5059 }
5060
dc_compare_hgroups(const void * d1,const void * d2)5061 static int dc_compare_hgroups(const void *d1, const void *d2)
5062 {
5063 const zbx_dc_hostgroup_t *g1 = *((const zbx_dc_hostgroup_t **)d1);
5064 const zbx_dc_hostgroup_t *g2 = *((const zbx_dc_hostgroup_t **)d2);
5065
5066 return strcmp(g1->name, g2->name);
5067 }
5068
5069 /******************************************************************************
5070 * *
5071 * Function: DCsync_hostgroups *
5072 * *
5073 * Purpose: Updates host groups configuration cache *
5074 * *
5075 * Parameters: sync - [IN] the db synchronization data *
5076 * *
5077 * Comments: The result contains the following fields: *
5078 * 0 - groupid *
5079 * 1 - name *
5080 * *
5081 ******************************************************************************/
DCsync_hostgroups(zbx_dbsync_t * sync)5082 static void DCsync_hostgroups(zbx_dbsync_t *sync)
5083 {
5084 char **row;
5085 zbx_uint64_t rowid;
5086 unsigned char tag;
5087 zbx_uint64_t groupid;
5088 zbx_dc_hostgroup_t *group;
5089 int found, ret, index;
5090
5091 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
5092
5093 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
5094 {
5095 /* removed rows will be always added at the end */
5096 if (ZBX_DBSYNC_ROW_REMOVE == tag)
5097 break;
5098
5099 ZBX_STR2UINT64(groupid, row[0]);
5100
5101 group = (zbx_dc_hostgroup_t *)DCfind_id(&config->hostgroups, groupid, sizeof(zbx_dc_hostgroup_t), &found);
5102
5103 if (0 == found)
5104 {
5105 group->flags = ZBX_DC_HOSTGROUP_FLAGS_NONE;
5106 zbx_vector_ptr_append(&config->hostgroups_name, group);
5107
5108 zbx_hashset_create_ext(&group->hostids, 0, ZBX_DEFAULT_UINT64_HASH_FUNC,
5109 ZBX_DEFAULT_UINT64_COMPARE_FUNC, NULL, __config_mem_malloc_func,
5110 __config_mem_realloc_func, __config_mem_free_func);
5111 }
5112
5113 DCstrpool_replace(found, &group->name, row[1]);
5114 }
5115
5116 /* remove deleted host groups */
5117
5118 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
5119 {
5120 if (NULL == (group = (zbx_dc_hostgroup_t *)zbx_hashset_search(&config->hostgroups, &rowid)))
5121 continue;
5122
5123 if (FAIL != (index = zbx_vector_ptr_search(&config->hostgroups_name, group, ZBX_DEFAULT_PTR_COMPARE_FUNC)))
5124 zbx_vector_ptr_remove_noorder(&config->hostgroups_name, index);
5125
5126 if (ZBX_DC_HOSTGROUP_FLAGS_NONE != group->flags)
5127 zbx_vector_uint64_destroy(&group->nested_groupids);
5128
5129 zbx_strpool_release(group->name);
5130 zbx_hashset_destroy(&group->hostids);
5131 zbx_hashset_remove_direct(&config->hostgroups, group);
5132 }
5133
5134 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
5135 }
5136
5137 /******************************************************************************
5138 * *
5139 * Function: DCsync_trigger_tags *
5140 * *
5141 * Purpose: Updates trigger tags in configuration cache *
5142 * *
5143 * Parameters: sync - [IN] the db synchronization data *
5144 * *
5145 * Comments: The result contains the following fields: *
5146 * 0 - triggertagid *
5147 * 1 - triggerid *
5148 * 2 - tag *
5149 * 3 - value *
5150 * *
5151 ******************************************************************************/
DCsync_trigger_tags(zbx_dbsync_t * sync)5152 static void DCsync_trigger_tags(zbx_dbsync_t *sync)
5153 {
5154 char **row;
5155 zbx_uint64_t rowid;
5156 unsigned char tag;
5157 int found, ret, index;
5158 zbx_uint64_t triggerid, triggertagid;
5159 ZBX_DC_TRIGGER *trigger;
5160 zbx_dc_trigger_tag_t *trigger_tag;
5161
5162 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
5163
5164 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
5165 {
5166 /* removed rows will be always added at the end */
5167 if (ZBX_DBSYNC_ROW_REMOVE == tag)
5168 break;
5169
5170 ZBX_STR2UINT64(triggerid, row[1]);
5171
5172 if (NULL == (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &triggerid)))
5173 continue;
5174
5175 ZBX_STR2UINT64(triggertagid, row[0]);
5176
5177 trigger_tag = (zbx_dc_trigger_tag_t *)DCfind_id(&config->trigger_tags, triggertagid,
5178 sizeof(zbx_dc_trigger_tag_t), &found);
5179 DCstrpool_replace(found, &trigger_tag->tag, row[2]);
5180 DCstrpool_replace(found, &trigger_tag->value, row[3]);
5181
5182 if (0 == found)
5183 {
5184 trigger_tag->triggerid = triggerid;
5185 zbx_vector_ptr_append(&trigger->tags, trigger_tag);
5186 }
5187 }
5188
5189 /* remove unused trigger tags */
5190
5191 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
5192 {
5193 if (NULL == (trigger_tag = (zbx_dc_trigger_tag_t *)zbx_hashset_search(&config->trigger_tags, &rowid)))
5194 continue;
5195
5196 if (NULL != (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &trigger_tag->triggerid)))
5197 {
5198 if (FAIL != (index = zbx_vector_ptr_search(&trigger->tags, trigger_tag,
5199 ZBX_DEFAULT_PTR_COMPARE_FUNC)))
5200 {
5201 zbx_vector_ptr_remove_noorder(&trigger->tags, index);
5202
5203 /* recreate empty tags vector to release used memory */
5204 if (0 == trigger->tags.values_num)
5205 {
5206 zbx_vector_ptr_destroy(&trigger->tags);
5207 zbx_vector_ptr_create_ext(&trigger->tags, __config_mem_malloc_func,
5208 __config_mem_realloc_func, __config_mem_free_func);
5209 }
5210 }
5211 }
5212
5213 zbx_strpool_release(trigger_tag->tag);
5214 zbx_strpool_release(trigger_tag->value);
5215
5216 zbx_hashset_remove_direct(&config->trigger_tags, trigger_tag);
5217 }
5218
5219 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
5220 }
5221
5222 /******************************************************************************
5223 * *
5224 * Function: DCsync_item_tags *
5225 * *
5226 * Purpose: Updates item tags in configuration cache *
5227 * *
5228 * Parameters: sync - [IN] the db synchronization data *
5229 * *
5230 * Comments: The result contains the following fields: *
5231 * 0 - itemtagid *
5232 * 1 - itemid *
5233 * 2 - tag *
5234 * 3 - value *
5235 * *
5236 ******************************************************************************/
DCsync_item_tags(zbx_dbsync_t * sync)5237 static void DCsync_item_tags(zbx_dbsync_t *sync)
5238 {
5239 char **row;
5240 zbx_uint64_t rowid;
5241 unsigned char tag;
5242 int found, ret, index;
5243 zbx_uint64_t itemid, itemtagid;
5244 ZBX_DC_ITEM *item;
5245 zbx_dc_item_tag_t *item_tag;
5246
5247 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
5248
5249 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
5250 {
5251 /* removed rows will be always added at the end */
5252 if (ZBX_DBSYNC_ROW_REMOVE == tag)
5253 break;
5254
5255 ZBX_STR2UINT64(itemid, row[1]);
5256
5257 if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemid)))
5258 continue;
5259
5260 ZBX_STR2UINT64(itemtagid, row[0]);
5261
5262 item_tag = (zbx_dc_item_tag_t *)DCfind_id(&config->item_tags, itemtagid, sizeof(zbx_dc_item_tag_t),
5263 &found);
5264 DCstrpool_replace(found, &item_tag->tag, row[2]);
5265 DCstrpool_replace(found, &item_tag->value, row[3]);
5266
5267 if (0 == found)
5268 {
5269 item_tag->itemid = itemid;
5270 zbx_vector_ptr_append(&item->tags, item_tag);
5271 }
5272 }
5273
5274 /* remove unused item tags */
5275
5276 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
5277 {
5278 if (NULL == (item_tag = (zbx_dc_item_tag_t *)zbx_hashset_search(&config->item_tags, &rowid)))
5279 continue;
5280
5281 if (NULL != (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &item_tag->itemid)))
5282 {
5283 if (FAIL != (index = zbx_vector_ptr_search(&item->tags, item_tag,
5284 ZBX_DEFAULT_PTR_COMPARE_FUNC)))
5285 {
5286 zbx_vector_ptr_remove_noorder(&item->tags, index);
5287
5288 /* recreate empty tags vector to release used memory */
5289 if (0 == item->tags.values_num)
5290 {
5291 zbx_vector_ptr_destroy(&item->tags);
5292 zbx_vector_ptr_create_ext(&item->tags, __config_mem_malloc_func,
5293 __config_mem_realloc_func, __config_mem_free_func);
5294 }
5295 }
5296 }
5297
5298 zbx_strpool_release(item_tag->tag);
5299 zbx_strpool_release(item_tag->value);
5300
5301 zbx_hashset_remove_direct(&config->item_tags, item_tag);
5302 }
5303
5304 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
5305 }
5306
5307 /******************************************************************************
5308 * *
5309 * Function: DCsync_host_tags *
5310 * *
5311 * Purpose: Updates host tags in configuration cache *
5312 * *
5313 * Parameters: sync - [IN] the db synchronization data *
5314 * *
5315 * Comments: The result contains the following fields: *
5316 * 0 - hosttagid *
5317 * 1 - hostid *
5318 * 2 - tag *
5319 * 3 - value *
5320 * *
5321 ******************************************************************************/
DCsync_host_tags(zbx_dbsync_t * sync)5322 static void DCsync_host_tags(zbx_dbsync_t *sync)
5323 {
5324 char **row;
5325 zbx_uint64_t rowid;
5326 unsigned char tag;
5327
5328 zbx_dc_host_tag_t *host_tag;
5329 zbx_dc_host_tag_index_t *host_tag_index_entry;
5330
5331 int found, index, ret;
5332 zbx_uint64_t hosttagid, hostid;
5333
5334 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
5335
5336 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
5337 {
5338 /* removed rows will be always added at the end */
5339 if (ZBX_DBSYNC_ROW_REMOVE == tag)
5340 break;
5341
5342 ZBX_STR2UINT64(hosttagid, row[0]);
5343 ZBX_STR2UINT64(hostid, row[1]);
5344
5345 host_tag = (zbx_dc_host_tag_t *)DCfind_id(&config->host_tags, hosttagid,
5346 sizeof(zbx_dc_host_tag_t), &found);
5347
5348 /* store new information in host_tag structure */
5349 host_tag->hostid = hostid;
5350 DCstrpool_replace(found, &host_tag->tag, row[2]);
5351 DCstrpool_replace(found, &host_tag->value, row[3]);
5352
5353 /* update host_tags_index*/
5354 if (tag == ZBX_DBSYNC_ROW_ADD)
5355 {
5356 host_tag_index_entry = (zbx_dc_host_tag_index_t *)DCfind_id(&config->host_tags_index, hostid,
5357 sizeof(zbx_dc_host_tag_index_t), &found);
5358
5359 if (0 == found)
5360 {
5361 zbx_vector_ptr_create_ext(&host_tag_index_entry->tags, __config_mem_malloc_func,
5362 __config_mem_realloc_func, __config_mem_free_func);
5363 }
5364
5365 zbx_vector_ptr_append(&host_tag_index_entry->tags, host_tag);
5366 }
5367 }
5368
5369 /* remove deleted host tags from buffer */
5370 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
5371 {
5372 if (NULL == (host_tag = (zbx_dc_host_tag_t *)zbx_hashset_search(&config->host_tags, &rowid)))
5373 continue;
5374
5375 /* update host_tags_index*/
5376 host_tag_index_entry = (zbx_dc_host_tag_index_t *)zbx_hashset_search(&config->host_tags_index,
5377 &host_tag->hostid);
5378
5379 if (NULL != host_tag_index_entry)
5380 {
5381 if (FAIL != (index = zbx_vector_ptr_search(&host_tag_index_entry->tags, host_tag,
5382 ZBX_DEFAULT_PTR_COMPARE_FUNC)))
5383 {
5384 zbx_vector_ptr_remove(&host_tag_index_entry->tags, index);
5385 }
5386
5387 /* remove index entry if it's empty */
5388 if (0 == host_tag_index_entry->tags.values_num)
5389 {
5390 zbx_vector_ptr_destroy(&host_tag_index_entry->tags);
5391 zbx_hashset_remove_direct(&config->host_tags_index, host_tag_index_entry);
5392 }
5393 }
5394
5395 /* clear host_tag structure */
5396 zbx_strpool_release(host_tag->tag);
5397 zbx_strpool_release(host_tag->value);
5398
5399 zbx_hashset_remove_direct(&config->host_tags, host_tag);
5400 }
5401
5402 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
5403 }
5404
5405 /******************************************************************************
5406 * *
5407 * Function: dc_compare_itemscript_param *
5408 * *
5409 * Purpose: compare two item script parameters *
5410 * *
5411 ******************************************************************************/
dc_compare_itemscript_param(const void * d1,const void * d2)5412 static int dc_compare_itemscript_param(const void *d1, const void *d2)
5413 {
5414 zbx_dc_scriptitem_param_t *p1 = *(zbx_dc_scriptitem_param_t **)d1;
5415 zbx_dc_scriptitem_param_t *p2 = *(zbx_dc_scriptitem_param_t **)d2;
5416
5417 ZBX_RETURN_IF_NOT_EQUAL(p1->name, p2->name);
5418 ZBX_RETURN_IF_NOT_EQUAL(p1->value, p2->value);
5419
5420 return 0;
5421 }
5422
5423 /******************************************************************************
5424 * *
5425 * Function: dc_compare_item_preproc_by_step *
5426 * *
5427 * Purpose: compare two item preprocessing operations by step *
5428 * *
5429 * Comments: This function is used to sort correlation conditions by type. *
5430 * *
5431 ******************************************************************************/
dc_compare_preprocops_by_step(const void * d1,const void * d2)5432 static int dc_compare_preprocops_by_step(const void *d1, const void *d2)
5433 {
5434 zbx_dc_preproc_op_t *p1 = *(zbx_dc_preproc_op_t **)d1;
5435 zbx_dc_preproc_op_t *p2 = *(zbx_dc_preproc_op_t **)d2;
5436
5437 if (ZBX_PREPROC_VALIDATE_NOT_SUPPORTED == p1->type)
5438 return -1;
5439
5440 if (ZBX_PREPROC_VALIDATE_NOT_SUPPORTED == p2->type)
5441 return 1;
5442
5443 ZBX_RETURN_IF_NOT_EQUAL(p1->step, p2->step);
5444
5445 return 0;
5446 }
5447
5448 /******************************************************************************
5449 * *
5450 * Function: DCsync_item_preproc *
5451 * *
5452 * Purpose: Updates item preprocessing steps in configuration cache *
5453 * *
5454 * Parameters: sync - [IN] the db synchronization data *
5455 * *
5456 * Comments: The result contains the following fields: *
5457 * 0 - item_preprocid *
5458 * 1 - itemid *
5459 * 2 - type *
5460 * 3 - params *
5461 * *
5462 ******************************************************************************/
DCsync_item_preproc(zbx_dbsync_t * sync,int timestamp)5463 static void DCsync_item_preproc(zbx_dbsync_t *sync, int timestamp)
5464 {
5465 char **row;
5466 zbx_uint64_t rowid;
5467 unsigned char tag;
5468 zbx_uint64_t item_preprocid, itemid;
5469 int found, ret, i, index;
5470 ZBX_DC_PREPROCITEM *preprocitem = NULL;
5471 zbx_dc_preproc_op_t *op;
5472 zbx_vector_ptr_t items;
5473
5474 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
5475
5476 zbx_vector_ptr_create(&items);
5477
5478 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
5479 {
5480 /* removed rows will be always added at the end */
5481 if (ZBX_DBSYNC_ROW_REMOVE == tag)
5482 break;
5483
5484 ZBX_STR2UINT64(itemid, row[1]);
5485
5486 if (NULL == preprocitem || itemid != preprocitem->itemid)
5487 {
5488 if (NULL == (preprocitem = (ZBX_DC_PREPROCITEM *)zbx_hashset_search(&config->preprocitems, &itemid)))
5489 {
5490 ZBX_DC_PREPROCITEM preprocitem_local;
5491
5492 preprocitem_local.itemid = itemid;
5493
5494 preprocitem = (ZBX_DC_PREPROCITEM *)zbx_hashset_insert(&config->preprocitems, &preprocitem_local,
5495 sizeof(preprocitem_local));
5496
5497 zbx_vector_ptr_create_ext(&preprocitem->preproc_ops, __config_mem_malloc_func,
5498 __config_mem_realloc_func, __config_mem_free_func);
5499 }
5500
5501 preprocitem->update_time = timestamp;
5502 }
5503
5504 ZBX_STR2UINT64(item_preprocid, row[0]);
5505
5506 op = (zbx_dc_preproc_op_t *)DCfind_id(&config->preprocops, item_preprocid, sizeof(zbx_dc_preproc_op_t), &found);
5507
5508 ZBX_STR2UCHAR(op->type, row[2]);
5509 DCstrpool_replace(found, &op->params, row[3]);
5510 op->step = atoi(row[4]);
5511 op->error_handler = atoi(row[6]);
5512 DCstrpool_replace(found, &op->error_handler_params, row[7]);
5513
5514 if (0 == found)
5515 {
5516 op->itemid = itemid;
5517 zbx_vector_ptr_append(&preprocitem->preproc_ops, op);
5518 }
5519
5520 zbx_vector_ptr_append(&items, preprocitem);
5521 }
5522
5523 /* remove deleted item preprocessing operations */
5524
5525 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
5526 {
5527 if (NULL == (op = (zbx_dc_preproc_op_t *)zbx_hashset_search(&config->preprocops, &rowid)))
5528 continue;
5529
5530 if (NULL != (preprocitem = (ZBX_DC_PREPROCITEM *)zbx_hashset_search(&config->preprocitems, &op->itemid)))
5531 {
5532 if (FAIL != (index = zbx_vector_ptr_search(&preprocitem->preproc_ops, op,
5533 ZBX_DEFAULT_PTR_COMPARE_FUNC)))
5534 {
5535 zbx_vector_ptr_remove_noorder(&preprocitem->preproc_ops, index);
5536 zbx_vector_ptr_append(&items, preprocitem);
5537 }
5538 }
5539
5540 zbx_strpool_release(op->params);
5541 zbx_strpool_release(op->error_handler_params);
5542 zbx_hashset_remove_direct(&config->preprocops, op);
5543 }
5544
5545 /* sort item preprocessing operations by step */
5546
5547 zbx_vector_ptr_sort(&items, ZBX_DEFAULT_PTR_COMPARE_FUNC);
5548 zbx_vector_ptr_uniq(&items, ZBX_DEFAULT_PTR_COMPARE_FUNC);
5549
5550 for (i = 0; i < items.values_num; i++)
5551 {
5552 preprocitem = (ZBX_DC_PREPROCITEM *)items.values[i];
5553
5554 if (0 == preprocitem->preproc_ops.values_num)
5555 {
5556 zbx_vector_ptr_destroy(&preprocitem->preproc_ops);
5557 zbx_hashset_remove_direct(&config->preprocitems, preprocitem);
5558 }
5559 else
5560 zbx_vector_ptr_sort(&preprocitem->preproc_ops, dc_compare_preprocops_by_step);
5561 }
5562
5563 zbx_vector_ptr_destroy(&items);
5564
5565 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
5566 }
5567
5568 /******************************************************************************
5569 * *
5570 * Function: DCsync_itemscript_param *
5571 * *
5572 * Purpose: Updates item script parameters in configuration cache *
5573 * *
5574 * Parameters: sync - [IN] the db synchronization data *
5575 * *
5576 * Comments: The result contains the following fields: *
5577 * 0 - item_script_paramid *
5578 * 1 - itemid *
5579 * 2 - name *
5580 * 3 - value *
5581 * *
5582 ******************************************************************************/
DCsync_itemscript_param(zbx_dbsync_t * sync)5583 static void DCsync_itemscript_param(zbx_dbsync_t *sync)
5584 {
5585 char **row;
5586 zbx_uint64_t rowid;
5587 unsigned char tag;
5588 zbx_uint64_t item_script_paramid, itemid;
5589 int found, ret, i, index;
5590 ZBX_DC_SCRIPTITEM *scriptitem;
5591 zbx_dc_scriptitem_param_t *scriptitem_params;
5592 zbx_vector_ptr_t items;
5593
5594 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
5595
5596 zbx_vector_ptr_create(&items);
5597
5598 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
5599 {
5600 /* removed rows will be always added at the end */
5601 if (ZBX_DBSYNC_ROW_REMOVE == tag)
5602 break;
5603
5604 ZBX_STR2UINT64(itemid, row[1]);
5605
5606 if (NULL == (scriptitem = (ZBX_DC_SCRIPTITEM *) zbx_hashset_search(&config->scriptitems, &itemid)))
5607 {
5608 zabbix_log(LOG_LEVEL_DEBUG,
5609 "cannot find parent item for item parameters (itemid=" ZBX_FS_UI64")", itemid);
5610 continue;
5611 }
5612
5613 ZBX_STR2UINT64(item_script_paramid, row[0]);
5614 scriptitem_params = (zbx_dc_scriptitem_param_t *)DCfind_id(&config->itemscript_params,
5615 item_script_paramid, sizeof(zbx_dc_scriptitem_param_t), &found);
5616
5617 DCstrpool_replace(found, &scriptitem_params->name, row[2]);
5618 DCstrpool_replace(found, &scriptitem_params->value, row[3]);
5619
5620 if (0 == found)
5621 {
5622 scriptitem_params->itemid = itemid;
5623 zbx_vector_ptr_append(&scriptitem->params, scriptitem_params);
5624 }
5625
5626 zbx_vector_ptr_append(&items, scriptitem);
5627 }
5628
5629 /* remove deleted item script parameters */
5630
5631 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
5632 {
5633 if (NULL == (scriptitem_params =
5634 (zbx_dc_scriptitem_param_t *)zbx_hashset_search(&config->itemscript_params, &rowid)))
5635 {
5636 continue;
5637 }
5638
5639 if (NULL != (scriptitem = (ZBX_DC_SCRIPTITEM *)zbx_hashset_search(&config->scriptitems,
5640 &scriptitem_params->itemid)))
5641 {
5642 if (FAIL != (index = zbx_vector_ptr_search(&scriptitem->params, scriptitem_params,
5643 ZBX_DEFAULT_PTR_COMPARE_FUNC)))
5644 {
5645 zbx_vector_ptr_remove_noorder(&scriptitem->params, index);
5646 zbx_vector_ptr_append(&items, scriptitem);
5647 }
5648 }
5649
5650 zbx_strpool_release(scriptitem_params->name);
5651 zbx_strpool_release(scriptitem_params->value);
5652 zbx_hashset_remove_direct(&config->itemscript_params, scriptitem_params);
5653 }
5654
5655 /* sort item script parameters */
5656
5657 zbx_vector_ptr_sort(&items, ZBX_DEFAULT_PTR_COMPARE_FUNC);
5658 zbx_vector_ptr_uniq(&items, ZBX_DEFAULT_PTR_COMPARE_FUNC);
5659
5660 for (i = 0; i < items.values_num; i++)
5661 {
5662 scriptitem = (ZBX_DC_SCRIPTITEM *)items.values[i];
5663
5664 if (0 == scriptitem->params.values_num)
5665 {
5666 zbx_vector_ptr_destroy(&scriptitem->params);
5667 zbx_hashset_remove_direct(&config->scriptitems, scriptitem);
5668 }
5669 else
5670 zbx_vector_ptr_sort(&scriptitem->params, dc_compare_itemscript_param);
5671 }
5672
5673 zbx_vector_ptr_destroy(&items);
5674
5675 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
5676 }
5677
5678 /******************************************************************************
5679 * *
5680 * Function: DCsync_hostgroup_hosts *
5681 * *
5682 * Purpose: Updates group hosts in configuration cache *
5683 * *
5684 * Parameters: sync - [IN] the db synchronization data *
5685 * *
5686 * Comments: The result contains the following fields: *
5687 * 0 - groupid *
5688 * 1 - hostid *
5689 * *
5690 ******************************************************************************/
DCsync_hostgroup_hosts(zbx_dbsync_t * sync)5691 static void DCsync_hostgroup_hosts(zbx_dbsync_t *sync)
5692 {
5693 char **row;
5694 zbx_uint64_t rowid;
5695 unsigned char tag;
5696
5697 zbx_dc_hostgroup_t *group = NULL;
5698
5699 int ret;
5700 zbx_uint64_t last_groupid = 0, groupid, hostid;
5701
5702 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
5703
5704 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
5705 {
5706 config->maintenance_update = ZBX_MAINTENANCE_UPDATE_TRUE;
5707
5708 /* removed rows will be always added at the end */
5709 if (ZBX_DBSYNC_ROW_REMOVE == tag)
5710 break;
5711
5712 ZBX_STR2UINT64(groupid, row[0]);
5713
5714 if (last_groupid != groupid)
5715 {
5716 group = (zbx_dc_hostgroup_t *)zbx_hashset_search(&config->hostgroups, &groupid);
5717 last_groupid = groupid;
5718 }
5719
5720 if (NULL == group)
5721 continue;
5722
5723 ZBX_STR2UINT64(hostid, row[1]);
5724 zbx_hashset_insert(&group->hostids, &hostid, sizeof(hostid));
5725 }
5726
5727 /* remove deleted group hostids from cache */
5728 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
5729 {
5730 ZBX_STR2UINT64(groupid, row[0]);
5731
5732 if (NULL == (group = (zbx_dc_hostgroup_t *)zbx_hashset_search(&config->hostgroups, &groupid)))
5733 continue;
5734
5735 ZBX_STR2UINT64(hostid, row[1]);
5736 zbx_hashset_remove(&group->hostids, &hostid);
5737 }
5738
5739 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
5740 }
5741
5742 /******************************************************************************
5743 * *
5744 * Function: dc_trigger_update_topology *
5745 * *
5746 * Purpose: updates trigger topology after trigger dependency changes *
5747 * *
5748 ******************************************************************************/
dc_trigger_update_topology(void)5749 static void dc_trigger_update_topology(void)
5750 {
5751 zbx_hashset_iter_t iter;
5752 ZBX_DC_TRIGGER *trigger;
5753
5754 zbx_hashset_iter_reset(&config->triggers, &iter);
5755 while (NULL != (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_iter_next(&iter)))
5756 trigger->topoindex = 1;
5757
5758 DCconfig_sort_triggers_topologically();
5759 }
5760
zbx_default_ptr_pair_ptr_compare_func(const void * d1,const void * d2)5761 static int zbx_default_ptr_pair_ptr_compare_func(const void *d1, const void *d2)
5762 {
5763 const zbx_ptr_pair_t *p1 = (const zbx_ptr_pair_t *)d1;
5764 const zbx_ptr_pair_t *p2 = (const zbx_ptr_pair_t *)d2;
5765
5766 ZBX_RETURN_IF_NOT_EQUAL(p1->first, p2->first);
5767 ZBX_RETURN_IF_NOT_EQUAL(p1->second, p2->second);
5768
5769 return 0;
5770 }
5771
5772 /******************************************************************************
5773 * *
5774 * Function: dc_trigger_update_cache *
5775 * *
5776 * Purpose: updates trigger related cache data; *
5777 * 1) time triggers assigned to timer processes *
5778 * 2) trigger functionality (if it uses contain disabled *
5779 * items/hosts) *
5780 * 3) list of triggers each item is used by *
5781 * *
5782 ******************************************************************************/
dc_trigger_update_cache(void)5783 static void dc_trigger_update_cache(void)
5784 {
5785 zbx_hashset_iter_t iter;
5786 ZBX_DC_TRIGGER *trigger;
5787 ZBX_DC_FUNCTION *function;
5788 ZBX_DC_ITEM *item;
5789 int i, j, k;
5790 zbx_ptr_pair_t itemtrig;
5791 zbx_vector_ptr_pair_t itemtrigs;
5792 ZBX_DC_HOST *host;
5793
5794 zbx_hashset_iter_reset(&config->triggers, &iter);
5795 while (NULL != (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_iter_next(&iter)))
5796 trigger->functional = TRIGGER_FUNCTIONAL_TRUE;
5797
5798 zbx_vector_ptr_pair_create(&itemtrigs);
5799 zbx_hashset_iter_reset(&config->functions, &iter);
5800 while (NULL != (function = (ZBX_DC_FUNCTION *)zbx_hashset_iter_next(&iter)))
5801 {
5802
5803 if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &function->itemid)) ||
5804 NULL == (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &function->triggerid)))
5805 {
5806 continue;
5807 }
5808
5809 /* cache item - trigger link */
5810 if (0 != item->update_triggers)
5811 {
5812 itemtrig.first = item;
5813 itemtrig.second = trigger;
5814 zbx_vector_ptr_pair_append(&itemtrigs, itemtrig);
5815 }
5816
5817 /* disable functionality for triggers with expression containing */
5818 /* disabled or not monitored items */
5819
5820 if (TRIGGER_FUNCTIONAL_FALSE == trigger->functional)
5821 continue;
5822
5823 if (ITEM_STATUS_DISABLED == item->status ||
5824 (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &item->hostid)) ||
5825 HOST_STATUS_NOT_MONITORED == host->status))
5826 {
5827 trigger->functional = TRIGGER_FUNCTIONAL_FALSE;
5828 }
5829 }
5830
5831 zbx_vector_ptr_pair_sort(&itemtrigs, zbx_default_ptr_pair_ptr_compare_func);
5832 zbx_vector_ptr_pair_uniq(&itemtrigs, zbx_default_ptr_pair_ptr_compare_func);
5833
5834 /* update links from items to triggers */
5835 for (i = 0; i < itemtrigs.values_num; i++)
5836 {
5837 for (j = i + 1; j < itemtrigs.values_num; j++)
5838 {
5839 if (itemtrigs.values[i].first != itemtrigs.values[j].first)
5840 break;
5841 }
5842
5843 item = (ZBX_DC_ITEM *)itemtrigs.values[i].first;
5844 item->update_triggers = 0;
5845 item->triggers = (ZBX_DC_TRIGGER **)config->items.mem_realloc_func(item->triggers, (j - i + 1) * sizeof(ZBX_DC_TRIGGER *));
5846
5847 for (k = i; k < j; k++)
5848 item->triggers[k - i] = (ZBX_DC_TRIGGER *)itemtrigs.values[k].second;
5849
5850 item->triggers[j - i] = NULL;
5851
5852 i = j - 1;
5853 }
5854
5855 zbx_vector_ptr_pair_destroy(&itemtrigs);
5856 }
5857
5858 /******************************************************************************
5859 * *
5860 * Function: dc_hostgroups_update_cache *
5861 * *
5862 * Purpose: updates hostgroup name index and resets nested group lists *
5863 * *
5864 ******************************************************************************/
dc_hostgroups_update_cache(void)5865 static void dc_hostgroups_update_cache(void)
5866 {
5867 zbx_hashset_iter_t iter;
5868 zbx_dc_hostgroup_t *group;
5869
5870 zbx_vector_ptr_sort(&config->hostgroups_name, dc_compare_hgroups);
5871
5872 zbx_hashset_iter_reset(&config->hostgroups, &iter);
5873 while (NULL != (group = (zbx_dc_hostgroup_t *)zbx_hashset_iter_next(&iter)))
5874 {
5875 if (ZBX_DC_HOSTGROUP_FLAGS_NONE != group->flags)
5876 {
5877 group->flags = ZBX_DC_HOSTGROUP_FLAGS_NONE;
5878 zbx_vector_uint64_destroy(&group->nested_groupids);
5879 }
5880 }
5881 }
5882
5883 /******************************************************************************
5884 * *
5885 * Function: dc_load_trigger_queue *
5886 * *
5887 * Purpose: load trigger queue from database *
5888 * *
5889 * Comments: This function is called when syncing configuration cache for the *
5890 * first time after server start. After loading trigger queue it *
5891 * will clear the corresponding data in database. *
5892 * *
5893 ******************************************************************************/
dc_load_trigger_queue(zbx_hashset_t * trend_functions)5894 static void dc_load_trigger_queue(zbx_hashset_t *trend_functions)
5895 {
5896 DB_RESULT result;
5897 DB_ROW row;
5898
5899 result = DBselect("select objectid,type,clock,ns from trigger_queue");
5900
5901 while (NULL != (row = DBfetch(result)))
5902 {
5903 zbx_trigger_timer_t timer_local, *timer;
5904
5905 if (ZBX_TRIGGER_TIMER_FUNCTION_TREND != atoi(row[1]))
5906 {
5907 THIS_SHOULD_NEVER_HAPPEN;
5908 continue;
5909 }
5910
5911 ZBX_STR2UINT64(timer_local.objectid, row[0]);
5912
5913 timer_local.eval_ts.sec = atoi(row[2]);
5914 timer_local.eval_ts.ns = atoi(row[3]);
5915 timer = zbx_hashset_insert(trend_functions, &timer_local, sizeof(timer_local));
5916
5917 /* in the case function was scheduled multiple times use the latest data */
5918 if (0 > zbx_timespec_compare(&timer->eval_ts, &timer_local.eval_ts))
5919 timer->eval_ts = timer_local.eval_ts;
5920
5921 }
5922 DBfree_result(result);
5923 }
5924
5925 /******************************************************************************
5926 * *
5927 * Function: DCsync_configuration *
5928 * *
5929 * Purpose: Synchronize configuration data from database *
5930 * *
5931 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
5932 * *
5933 ******************************************************************************/
DCsync_configuration(unsigned char mode,const struct zbx_json_parse * jp_kvs_paths)5934 void DCsync_configuration(unsigned char mode, const struct zbx_json_parse *jp_kvs_paths)
5935 {
5936 int i, flags;
5937 double sec, csec, hsec, hisec, htsec, gmsec, hmsec, ifsec, isec, tsec, dsec, fsec, expr_sec, csec2,
5938 hsec2, hisec2, htsec2, gmsec2, hmsec2, ifsec2, isec2, tsec2, dsec2, fsec2, expr_sec2,
5939 action_sec, action_sec2, action_op_sec, action_op_sec2, action_condition_sec,
5940 action_condition_sec2, trigger_tag_sec, trigger_tag_sec2, host_tag_sec, host_tag_sec2,
5941 correlation_sec, correlation_sec2, corr_condition_sec, corr_condition_sec2, corr_operation_sec,
5942 corr_operation_sec2, hgroups_sec, hgroups_sec2, itempp_sec, itempp_sec2, itemscrp_sec,
5943 itemscrp_sec2, total, total2, update_sec, maintenance_sec, maintenance_sec2, item_tag_sec,
5944 item_tag_sec2;
5945
5946 zbx_dbsync_t config_sync, hosts_sync, hi_sync, htmpl_sync, gmacro_sync, hmacro_sync, if_sync, items_sync,
5947 template_items_sync, prototype_items_sync, triggers_sync, tdep_sync, func_sync, expr_sync,
5948 action_sync, action_op_sync, action_condition_sync, trigger_tag_sync, item_tag_sync,
5949 host_tag_sync, correlation_sync, corr_condition_sync, corr_operation_sync, hgroups_sync,
5950 itempp_sync, itemscrp_sync, maintenance_sync, maintenance_period_sync, maintenance_tag_sync,
5951 maintenance_group_sync, maintenance_host_sync, hgroup_host_sync;
5952
5953 double autoreg_csec, autoreg_csec2;
5954 zbx_dbsync_t autoreg_config_sync;
5955 zbx_uint64_t update_flags = 0;
5956
5957 zbx_hashset_t trend_queue;
5958
5959 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
5960
5961 config->sync_start_ts = time(NULL);
5962
5963 if (ZBX_SYNC_SECRETS == mode)
5964 {
5965 DCsync_kvs_paths(NULL);
5966 goto skip;
5967 }
5968
5969 zbx_dbsync_init_env(config);
5970
5971 if (ZBX_DBSYNC_INIT == mode)
5972 {
5973 zbx_hashset_create(&trend_queue, 1000, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
5974 dc_load_trigger_queue(&trend_queue);
5975 }
5976
5977 /* global configuration must be synchronized directly with database */
5978 zbx_dbsync_init(&config_sync, ZBX_DBSYNC_INIT);
5979 zbx_dbsync_init(&autoreg_config_sync, mode);
5980 zbx_dbsync_init(&hosts_sync, mode);
5981 zbx_dbsync_init(&hi_sync, mode);
5982 zbx_dbsync_init(&htmpl_sync, mode);
5983 zbx_dbsync_init(&gmacro_sync, mode);
5984 zbx_dbsync_init(&hmacro_sync, mode);
5985 zbx_dbsync_init(&if_sync, mode);
5986 zbx_dbsync_init(&items_sync, mode);
5987 zbx_dbsync_init(&template_items_sync, mode);
5988 zbx_dbsync_init(&prototype_items_sync, mode);
5989 zbx_dbsync_init(&triggers_sync, mode);
5990 zbx_dbsync_init(&tdep_sync, mode);
5991 zbx_dbsync_init(&func_sync, mode);
5992 zbx_dbsync_init(&expr_sync, mode);
5993 zbx_dbsync_init(&action_sync, mode);
5994
5995 /* Action operation sync produces virtual rows with two columns - actionid, opflags. */
5996 /* Because of this it cannot return the original database select and must always be */
5997 /* initialized in update mode. */
5998 zbx_dbsync_init(&action_op_sync, ZBX_DBSYNC_UPDATE);
5999
6000 zbx_dbsync_init(&action_condition_sync, mode);
6001 zbx_dbsync_init(&trigger_tag_sync, mode);
6002 zbx_dbsync_init(&item_tag_sync, mode);
6003 zbx_dbsync_init(&host_tag_sync, mode);
6004 zbx_dbsync_init(&correlation_sync, mode);
6005 zbx_dbsync_init(&corr_condition_sync, mode);
6006 zbx_dbsync_init(&corr_operation_sync, mode);
6007 zbx_dbsync_init(&hgroups_sync, mode);
6008 zbx_dbsync_init(&hgroup_host_sync, mode);
6009 zbx_dbsync_init(&itempp_sync, mode);
6010 zbx_dbsync_init(&itemscrp_sync, mode);
6011
6012 zbx_dbsync_init(&maintenance_sync, mode);
6013 zbx_dbsync_init(&maintenance_period_sync, mode);
6014 zbx_dbsync_init(&maintenance_tag_sync, mode);
6015 zbx_dbsync_init(&maintenance_group_sync, mode);
6016 zbx_dbsync_init(&maintenance_host_sync, mode);
6017
6018 sec = zbx_time();
6019 if (FAIL == zbx_dbsync_compare_config(&config_sync))
6020 goto out;
6021 csec = zbx_time() - sec;
6022
6023 sec = zbx_time();
6024 if (FAIL == zbx_dbsync_compare_autoreg_psk(&autoreg_config_sync))
6025 goto out;
6026 autoreg_csec = zbx_time() - sec;
6027
6028 /* sync global configuration settings */
6029 START_SYNC;
6030 sec = zbx_time();
6031 DCsync_config(&config_sync, &flags);
6032 csec2 = zbx_time() - sec;
6033
6034 sec = zbx_time();
6035 DCsync_autoreg_config(&autoreg_config_sync); /* must be done in the same cache locking with config sync */
6036 autoreg_csec2 = zbx_time() - sec;
6037 FINISH_SYNC;
6038
6039 /* sync macro related data, to support macro resolving during configuration sync */
6040
6041 sec = zbx_time();
6042 if (FAIL == zbx_dbsync_compare_host_templates(&htmpl_sync))
6043 goto out;
6044 htsec = zbx_time() - sec;
6045
6046 sec = zbx_time();
6047 if (FAIL == zbx_dbsync_compare_global_macros(&gmacro_sync))
6048 goto out;
6049 gmsec = zbx_time() - sec;
6050
6051 sec = zbx_time();
6052 if (FAIL == zbx_dbsync_compare_host_macros(&hmacro_sync))
6053 goto out;
6054 hmsec = zbx_time() - sec;
6055
6056 sec = zbx_time();
6057 if (FAIL == zbx_dbsync_compare_host_tags(&host_tag_sync))
6058 goto out;
6059 host_tag_sec = zbx_time() - sec;
6060
6061 START_SYNC;
6062 sec = zbx_time();
6063 DCsync_htmpls(&htmpl_sync);
6064 htsec2 = zbx_time() - sec;
6065
6066 sec = zbx_time();
6067 DCsync_gmacros(&gmacro_sync);
6068 gmsec2 = zbx_time() - sec;
6069
6070 sec = zbx_time();
6071 DCsync_hmacros(&hmacro_sync);
6072 hmsec2 = zbx_time() - sec;
6073
6074 sec = zbx_time();
6075 DCsync_host_tags(&host_tag_sync);
6076 host_tag_sec2 = zbx_time() - sec;
6077 FINISH_SYNC;
6078
6079 if (FAIL == DCsync_kvs_paths(jp_kvs_paths))
6080 {
6081 START_SYNC;
6082 goto out;
6083 }
6084
6085 /* sync host data to support host lookups when resolving macros during configuration sync */
6086
6087 sec = zbx_time();
6088 if (FAIL == zbx_dbsync_compare_hosts(&hosts_sync))
6089 goto out;
6090 hsec = zbx_time() - sec;
6091
6092 sec = zbx_time();
6093 if (FAIL == zbx_dbsync_compare_host_inventory(&hi_sync))
6094 goto out;
6095 hisec = zbx_time() - sec;
6096
6097 sec = zbx_time();
6098 if (FAIL == zbx_dbsync_compare_host_groups(&hgroups_sync))
6099 goto out;
6100 if (FAIL == zbx_dbsync_compare_host_group_hosts(&hgroup_host_sync))
6101 goto out;
6102 hgroups_sec = zbx_time() - sec;
6103
6104 sec = zbx_time();
6105 if (FAIL == zbx_dbsync_compare_maintenances(&maintenance_sync))
6106 goto out;
6107 if (FAIL == zbx_dbsync_compare_maintenance_tags(&maintenance_tag_sync))
6108 goto out;
6109 if (FAIL == zbx_dbsync_compare_maintenance_periods(&maintenance_period_sync))
6110 goto out;
6111 if (FAIL == zbx_dbsync_compare_maintenance_groups(&maintenance_group_sync))
6112 goto out;
6113 if (FAIL == zbx_dbsync_compare_maintenance_hosts(&maintenance_host_sync))
6114 goto out;
6115 maintenance_sec = zbx_time() - sec;
6116
6117 START_SYNC;
6118 sec = zbx_time();
6119 DCsync_hosts(&hosts_sync);
6120 hsec2 = zbx_time() - sec;
6121
6122 sec = zbx_time();
6123 DCsync_host_inventory(&hi_sync);
6124 hisec2 = zbx_time() - sec;
6125
6126 sec = zbx_time();
6127 DCsync_hostgroups(&hgroups_sync);
6128 DCsync_hostgroup_hosts(&hgroup_host_sync);
6129 hgroups_sec2 = zbx_time() - sec;
6130
6131 sec = zbx_time();
6132 DCsync_maintenances(&maintenance_sync);
6133 DCsync_maintenance_tags(&maintenance_tag_sync);
6134 DCsync_maintenance_groups(&maintenance_group_sync);
6135 DCsync_maintenance_hosts(&maintenance_host_sync);
6136 DCsync_maintenance_periods(&maintenance_period_sync);
6137 maintenance_sec2 = zbx_time() - sec;
6138
6139 if (0 != hgroups_sync.add_num + hgroups_sync.update_num + hgroups_sync.remove_num)
6140 update_flags |= ZBX_DBSYNC_UPDATE_HOST_GROUPS;
6141
6142 if (0 != maintenance_group_sync.add_num + maintenance_group_sync.update_num + maintenance_group_sync.remove_num)
6143 update_flags |= ZBX_DBSYNC_UPDATE_MAINTENANCE_GROUPS;
6144
6145 if (0 != (update_flags & ZBX_DBSYNC_UPDATE_HOST_GROUPS))
6146 dc_hostgroups_update_cache();
6147
6148 /* pre-cache nested groups used in maintenances to allow read lock */
6149 /* during host maintenance update calculations */
6150 if (0 != (update_flags & (ZBX_DBSYNC_UPDATE_HOST_GROUPS | ZBX_DBSYNC_UPDATE_MAINTENANCE_GROUPS)))
6151 dc_maintenance_precache_nested_groups();
6152
6153 FINISH_SYNC;
6154
6155 /* sync item data to support item lookups when resolving macros during configuration sync */
6156
6157 sec = zbx_time();
6158 if (FAIL == zbx_dbsync_compare_interfaces(&if_sync))
6159 goto out;
6160 ifsec = zbx_time() - sec;
6161
6162 sec = zbx_time();
6163 if (FAIL == zbx_dbsync_compare_items(&items_sync))
6164 goto out;
6165
6166 if (FAIL == zbx_dbsync_compare_template_items(&template_items_sync))
6167 goto out;
6168
6169 if (FAIL == zbx_dbsync_compare_prototype_items(&prototype_items_sync))
6170 goto out;
6171 isec = zbx_time() - sec;
6172
6173 sec = zbx_time();
6174 if (FAIL == zbx_dbsync_compare_item_preprocs(&itempp_sync))
6175 goto out;
6176 itempp_sec = zbx_time() - sec;
6177
6178 sec = zbx_time();
6179 if (FAIL == zbx_dbsync_compare_item_script_param(&itemscrp_sync))
6180 goto out;
6181 itemscrp_sec = zbx_time() - sec;
6182
6183 START_SYNC;
6184
6185 /* resolves macros for interface_snmpaddrs, must be after DCsync_hmacros() */
6186 sec = zbx_time();
6187 DCsync_interfaces(&if_sync);
6188 ifsec2 = zbx_time() - sec;
6189
6190 /* relies on hosts, proxies and interfaces, must be after DCsync_{hosts,interfaces}() */
6191 sec = zbx_time();
6192 DCsync_items(&items_sync, flags);
6193 DCsync_template_items(&template_items_sync);
6194 DCsync_prototype_items(&prototype_items_sync);
6195 isec2 = zbx_time() - sec;
6196
6197 /* relies on items, must be after DCsync_items() */
6198 sec = zbx_time();
6199 DCsync_item_preproc(&itempp_sync, sec);
6200 itempp_sec2 = zbx_time() - sec;
6201
6202 /* relies on items, must be after DCsync_items() */
6203 sec = zbx_time();
6204 DCsync_itemscript_param(&itemscrp_sync);
6205 itemscrp_sec2 = zbx_time() - sec;
6206
6207 config->item_sync_ts = time(NULL);
6208 FINISH_SYNC;
6209
6210 dc_flush_history(); /* misconfigured items generate pseudo-historic values to become notsupported */
6211
6212 /* sync function data to support function lookups when resolving macros during configuration sync */
6213
6214 /* relies on items, must be after DCsync_items() */
6215 sec = zbx_time();
6216 if (FAIL == zbx_dbsync_compare_item_tags(&item_tag_sync))
6217 goto out;
6218 item_tag_sec = zbx_time() - sec;
6219
6220 sec = zbx_time();
6221 if (FAIL == zbx_dbsync_compare_functions(&func_sync))
6222 goto out;
6223 fsec = zbx_time() - sec;
6224
6225 START_SYNC;
6226 sec = zbx_time();
6227 DCsync_functions(&func_sync);
6228 fsec2 = zbx_time() - sec;
6229 FINISH_SYNC;
6230
6231 /* sync rest of the data */
6232
6233 sec = zbx_time();
6234 if (FAIL == zbx_dbsync_compare_triggers(&triggers_sync))
6235 goto out;
6236 tsec = zbx_time() - sec;
6237
6238 sec = zbx_time();
6239 if (FAIL == zbx_dbsync_compare_trigger_dependency(&tdep_sync))
6240 goto out;
6241 dsec = zbx_time() - sec;
6242
6243 sec = zbx_time();
6244 if (FAIL == zbx_dbsync_compare_expressions(&expr_sync))
6245 goto out;
6246 expr_sec = zbx_time() - sec;
6247
6248 sec = zbx_time();
6249 if (FAIL == zbx_dbsync_compare_actions(&action_sync))
6250 goto out;
6251 action_sec = zbx_time() - sec;
6252
6253 sec = zbx_time();
6254 if (FAIL == zbx_dbsync_compare_action_ops(&action_op_sync))
6255 goto out;
6256 action_op_sec = zbx_time() - sec;
6257
6258 sec = zbx_time();
6259 if (FAIL == zbx_dbsync_compare_action_conditions(&action_condition_sync))
6260 goto out;
6261 action_condition_sec = zbx_time() - sec;
6262
6263 sec = zbx_time();
6264 if (FAIL == zbx_dbsync_compare_trigger_tags(&trigger_tag_sync))
6265 goto out;
6266 trigger_tag_sec = zbx_time() - sec;
6267
6268 sec = zbx_time();
6269 if (FAIL == zbx_dbsync_compare_correlations(&correlation_sync))
6270 goto out;
6271 correlation_sec = zbx_time() - sec;
6272
6273 sec = zbx_time();
6274 if (FAIL == zbx_dbsync_compare_corr_conditions(&corr_condition_sync))
6275 goto out;
6276 corr_condition_sec = zbx_time() - sec;
6277
6278 sec = zbx_time();
6279 if (FAIL == zbx_dbsync_compare_corr_operations(&corr_operation_sync))
6280 goto out;
6281 corr_operation_sec = zbx_time() - sec;
6282
6283 START_SYNC;
6284
6285 sec = zbx_time();
6286 DCsync_triggers(&triggers_sync);
6287 tsec2 = zbx_time() - sec;
6288
6289 sec = zbx_time();
6290 DCsync_trigdeps(&tdep_sync);
6291 dsec2 = zbx_time() - sec;
6292
6293 sec = zbx_time();
6294 DCsync_expressions(&expr_sync);
6295 expr_sec2 = zbx_time() - sec;
6296
6297 sec = zbx_time();
6298 DCsync_actions(&action_sync);
6299 action_sec2 = zbx_time() - sec;
6300
6301 sec = zbx_time();
6302 DCsync_action_ops(&action_op_sync);
6303 action_op_sec2 = zbx_time() - sec;
6304
6305 sec = zbx_time();
6306 DCsync_action_conditions(&action_condition_sync);
6307 action_condition_sec2 = zbx_time() - sec;
6308
6309 sec = zbx_time();
6310 /* relies on triggers, must be after DCsync_triggers() */
6311 DCsync_trigger_tags(&trigger_tag_sync);
6312 trigger_tag_sec2 = zbx_time() - sec;
6313
6314 sec = zbx_time();
6315 DCsync_item_tags(&item_tag_sync);
6316 item_tag_sec2 = zbx_time() - sec;
6317
6318 sec = zbx_time();
6319 DCsync_correlations(&correlation_sync);
6320 correlation_sec2 = zbx_time() - sec;
6321
6322 sec = zbx_time();
6323 /* relies on correlation rules, must be after DCsync_correlations() */
6324 DCsync_corr_conditions(&corr_condition_sync);
6325 corr_condition_sec2 = zbx_time() - sec;
6326
6327 sec = zbx_time();
6328 /* relies on correlation rules, must be after DCsync_correlations() */
6329 DCsync_corr_operations(&corr_operation_sync);
6330 corr_operation_sec2 = zbx_time() - sec;
6331
6332 sec = zbx_time();
6333
6334 if (0 != hosts_sync.add_num + hosts_sync.update_num + hosts_sync.remove_num)
6335 update_flags |= ZBX_DBSYNC_UPDATE_HOSTS;
6336
6337 if (0 != items_sync.add_num + items_sync.update_num + items_sync.remove_num)
6338 update_flags |= ZBX_DBSYNC_UPDATE_ITEMS;
6339
6340 if (0 != func_sync.add_num + func_sync.update_num + func_sync.remove_num)
6341 update_flags |= ZBX_DBSYNC_UPDATE_FUNCTIONS;
6342
6343 if (0 != triggers_sync.add_num + triggers_sync.update_num + triggers_sync.remove_num)
6344 update_flags |= ZBX_DBSYNC_UPDATE_TRIGGERS;
6345
6346 if (0 != tdep_sync.add_num + tdep_sync.update_num + tdep_sync.remove_num)
6347 update_flags |= ZBX_DBSYNC_UPDATE_TRIGGER_DEPENDENCY;
6348
6349 /* update trigger topology if trigger dependency was changed */
6350 if (0 != (update_flags & ZBX_DBSYNC_UPDATE_TRIGGER_DEPENDENCY))
6351 dc_trigger_update_topology();
6352
6353 /* update various trigger related links in cache */
6354 if (0 != (update_flags & (ZBX_DBSYNC_UPDATE_HOSTS | ZBX_DBSYNC_UPDATE_ITEMS | ZBX_DBSYNC_UPDATE_FUNCTIONS |
6355 ZBX_DBSYNC_UPDATE_TRIGGERS)))
6356 {
6357 dc_trigger_update_cache();
6358 dc_schedule_trigger_timers((ZBX_DBSYNC_INIT == mode ? &trend_queue : NULL), time(NULL));
6359 }
6360
6361 update_sec = zbx_time() - sec;
6362
6363 if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_DEBUG))
6364 {
6365 total = csec + hsec + hisec + htsec + gmsec + hmsec + ifsec + isec + tsec + dsec + fsec + expr_sec +
6366 action_sec + action_op_sec + action_condition_sec + trigger_tag_sec + correlation_sec +
6367 corr_condition_sec + corr_operation_sec + hgroups_sec + itempp_sec + maintenance_sec +
6368 item_tag_sec;
6369 total2 = csec2 + hsec2 + hisec2 + htsec2 + gmsec2 + hmsec2 + ifsec2 + isec2 + tsec2 + dsec2 + fsec2 +
6370 expr_sec2 + action_op_sec2 + action_sec2 + action_condition_sec2 + trigger_tag_sec2 +
6371 correlation_sec2 + corr_condition_sec2 + corr_operation_sec2 + hgroups_sec2 +
6372 itempp_sec2 + maintenance_sec2 + item_tag_sec2 + update_sec;
6373
6374 zabbix_log(LOG_LEVEL_DEBUG, "%s() config : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6375 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6376 __func__, csec, csec2, config_sync.add_num, config_sync.update_num,
6377 config_sync.remove_num);
6378
6379 total += autoreg_csec;
6380 total2 += autoreg_csec2;
6381 zabbix_log(LOG_LEVEL_DEBUG, "%s() autoreg : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6382 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6383 __func__, autoreg_csec, autoreg_csec2, autoreg_config_sync.add_num,
6384 autoreg_config_sync.update_num, autoreg_config_sync.remove_num);
6385
6386 zabbix_log(LOG_LEVEL_DEBUG, "%s() hosts : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6387 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6388 __func__, hsec, hsec2, hosts_sync.add_num, hosts_sync.update_num,
6389 hosts_sync.remove_num);
6390 zabbix_log(LOG_LEVEL_DEBUG, "%s() host_invent: sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6391 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6392 __func__, hisec, hisec2, hi_sync.add_num, hi_sync.update_num,
6393 hi_sync.remove_num);
6394 zabbix_log(LOG_LEVEL_DEBUG, "%s() templates : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6395 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6396 __func__, htsec, htsec2, htmpl_sync.add_num, htmpl_sync.update_num,
6397 htmpl_sync.remove_num);
6398 zabbix_log(LOG_LEVEL_DEBUG, "%s() globmacros : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6399 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6400 __func__, gmsec, gmsec2, gmacro_sync.add_num, gmacro_sync.update_num,
6401 gmacro_sync.remove_num);
6402 zabbix_log(LOG_LEVEL_DEBUG, "%s() hostmacros : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6403 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6404 __func__, hmsec, hmsec2, hmacro_sync.add_num, hmacro_sync.update_num,
6405 hmacro_sync.remove_num);
6406 zabbix_log(LOG_LEVEL_DEBUG, "%s() interfaces : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6407 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6408 __func__, ifsec, ifsec2, if_sync.add_num, if_sync.update_num,
6409 if_sync.remove_num);
6410 zabbix_log(LOG_LEVEL_DEBUG, "%s() items : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6411 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6412 __func__, isec, isec2, items_sync.add_num, items_sync.update_num,
6413 items_sync.remove_num);
6414 zabbix_log(LOG_LEVEL_DEBUG, "%s() template_items : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6415 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6416 __func__, isec, isec2, template_items_sync.add_num,
6417 template_items_sync.update_num, template_items_sync.remove_num);
6418 zabbix_log(LOG_LEVEL_DEBUG, "%s() prototype_items : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6419 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6420 __func__, isec, isec2, prototype_items_sync.add_num,
6421 prototype_items_sync.update_num, prototype_items_sync.remove_num);
6422 zabbix_log(LOG_LEVEL_DEBUG, "%s() triggers : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6423 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6424 __func__, tsec, tsec2, triggers_sync.add_num, triggers_sync.update_num,
6425 triggers_sync.remove_num);
6426 zabbix_log(LOG_LEVEL_DEBUG, "%s() trigdeps : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6427 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6428 __func__, dsec, dsec2, tdep_sync.add_num, tdep_sync.update_num,
6429 tdep_sync.remove_num);
6430 zabbix_log(LOG_LEVEL_DEBUG, "%s() trig. tags : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6431 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6432 __func__, trigger_tag_sec, trigger_tag_sec2, trigger_tag_sync.add_num,
6433 trigger_tag_sync.update_num, trigger_tag_sync.remove_num);
6434 zabbix_log(LOG_LEVEL_DEBUG, "%s() host tags : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6435 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6436 __func__, host_tag_sec, host_tag_sec2, host_tag_sync.add_num,
6437 host_tag_sync.update_num, host_tag_sync.remove_num);
6438 zabbix_log(LOG_LEVEL_DEBUG, "%s() item tags : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6439 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6440 __func__, item_tag_sec, item_tag_sec2, item_tag_sync.add_num,
6441 item_tag_sync.update_num, item_tag_sync.remove_num);
6442 zabbix_log(LOG_LEVEL_DEBUG, "%s() functions : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6443 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6444 __func__, fsec, fsec2, func_sync.add_num, func_sync.update_num,
6445 func_sync.remove_num);
6446 zabbix_log(LOG_LEVEL_DEBUG, "%s() expressions: sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6447 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6448 __func__, expr_sec, expr_sec2, expr_sync.add_num, expr_sync.update_num,
6449 expr_sync.remove_num);
6450 zabbix_log(LOG_LEVEL_DEBUG, "%s() actions : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6451 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6452 __func__, action_sec, action_sec2, action_sync.add_num, action_sync.update_num,
6453 action_sync.remove_num);
6454 zabbix_log(LOG_LEVEL_DEBUG, "%s() operations : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6455 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6456 __func__, action_op_sec, action_op_sec2, action_op_sync.add_num,
6457 action_op_sync.update_num, action_op_sync.remove_num);
6458 zabbix_log(LOG_LEVEL_DEBUG, "%s() conditions : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6459 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6460 __func__, action_condition_sec, action_condition_sec2,
6461 action_condition_sync.add_num, action_condition_sync.update_num,
6462 action_condition_sync.remove_num);
6463 zabbix_log(LOG_LEVEL_DEBUG, "%s() corr : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6464 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6465 __func__, correlation_sec, correlation_sec2, correlation_sync.add_num,
6466 correlation_sync.update_num, correlation_sync.remove_num);
6467 zabbix_log(LOG_LEVEL_DEBUG, "%s() corr_cond : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6468 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6469 __func__, corr_condition_sec, corr_condition_sec2, corr_condition_sync.add_num,
6470 corr_condition_sync.update_num, corr_condition_sync.remove_num);
6471 zabbix_log(LOG_LEVEL_DEBUG, "%s() corr_op : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6472 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6473 __func__, corr_operation_sec, corr_operation_sec2, corr_operation_sync.add_num,
6474 corr_operation_sync.update_num, corr_operation_sync.remove_num);
6475 zabbix_log(LOG_LEVEL_DEBUG, "%s() hgroups : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6476 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6477 __func__, hgroups_sec, hgroups_sec2, hgroups_sync.add_num,
6478 hgroups_sync.update_num, hgroups_sync.remove_num);
6479 zabbix_log(LOG_LEVEL_DEBUG, "%s() item pproc : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6480 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6481 __func__, itempp_sec, itempp_sec2, itempp_sync.add_num, itempp_sync.update_num,
6482 itempp_sync.remove_num);
6483 zabbix_log(LOG_LEVEL_DEBUG, "%s() item script param: sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6484 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6485 __func__, itemscrp_sec, itemscrp_sec2, itemscrp_sync.add_num,
6486 itemscrp_sync.update_num, itemscrp_sync.remove_num);
6487 zabbix_log(LOG_LEVEL_DEBUG, "%s() maintenance: sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
6488 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
6489 __func__, maintenance_sec, maintenance_sec2, maintenance_sync.add_num,
6490 maintenance_sync.update_num, maintenance_sync.remove_num);
6491
6492 zabbix_log(LOG_LEVEL_DEBUG, "%s() reindex : " ZBX_FS_DBL " sec.", __func__, update_sec);
6493
6494 zabbix_log(LOG_LEVEL_DEBUG, "%s() total sql : " ZBX_FS_DBL " sec.", __func__, total);
6495 zabbix_log(LOG_LEVEL_DEBUG, "%s() total sync : " ZBX_FS_DBL " sec.", __func__, total2);
6496
6497 zabbix_log(LOG_LEVEL_DEBUG, "%s() proxies : %d (%d slots)", __func__,
6498 config->proxies.num_data, config->proxies.num_slots);
6499 zabbix_log(LOG_LEVEL_DEBUG, "%s() hosts : %d (%d slots)", __func__,
6500 config->hosts.num_data, config->hosts.num_slots);
6501 zabbix_log(LOG_LEVEL_DEBUG, "%s() hosts_h : %d (%d slots)", __func__,
6502 config->hosts_h.num_data, config->hosts_h.num_slots);
6503 zabbix_log(LOG_LEVEL_DEBUG, "%s() hosts_p : %d (%d slots)", __func__,
6504 config->hosts_p.num_data, config->hosts_p.num_slots);
6505 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
6506 zabbix_log(LOG_LEVEL_DEBUG, "%s() psks : %d (%d slots)", __func__,
6507 config->psks.num_data, config->psks.num_slots);
6508 #endif
6509 zabbix_log(LOG_LEVEL_DEBUG, "%s() ipmihosts : %d (%d slots)", __func__,
6510 config->ipmihosts.num_data, config->ipmihosts.num_slots);
6511 zabbix_log(LOG_LEVEL_DEBUG, "%s() host_invent: %d (%d slots)", __func__,
6512 config->host_inventories.num_data, config->host_inventories.num_slots);
6513 zabbix_log(LOG_LEVEL_DEBUG, "%s() htmpls : %d (%d slots)", __func__,
6514 config->htmpls.num_data, config->htmpls.num_slots);
6515 zabbix_log(LOG_LEVEL_DEBUG, "%s() gmacros : %d (%d slots)", __func__,
6516 config->gmacros.num_data, config->gmacros.num_slots);
6517 zabbix_log(LOG_LEVEL_DEBUG, "%s() gmacros_m : %d (%d slots)", __func__,
6518 config->gmacros_m.num_data, config->gmacros_m.num_slots);
6519 zabbix_log(LOG_LEVEL_DEBUG, "%s() hmacros : %d (%d slots)", __func__,
6520 config->hmacros.num_data, config->hmacros.num_slots);
6521 zabbix_log(LOG_LEVEL_DEBUG, "%s() hmacros_hm : %d (%d slots)", __func__,
6522 config->hmacros_hm.num_data, config->hmacros_hm.num_slots);
6523 zabbix_log(LOG_LEVEL_DEBUG, "%s() kvs_paths : %d", __func__, config->kvs_paths.values_num);
6524 zabbix_log(LOG_LEVEL_DEBUG, "%s() interfaces : %d (%d slots)", __func__,
6525 config->interfaces.num_data, config->interfaces.num_slots);
6526 zabbix_log(LOG_LEVEL_DEBUG, "%s() interfaces_snmp : %d (%d slots)", __func__,
6527 config->interfaces_snmp.num_data, config->interfaces_snmp.num_slots);
6528 zabbix_log(LOG_LEVEL_DEBUG, "%s() interfac_ht: %d (%d slots)", __func__,
6529 config->interfaces_ht.num_data, config->interfaces_ht.num_slots);
6530 zabbix_log(LOG_LEVEL_DEBUG, "%s() if_snmpitms: %d (%d slots)", __func__,
6531 config->interface_snmpitems.num_data, config->interface_snmpitems.num_slots);
6532 zabbix_log(LOG_LEVEL_DEBUG, "%s() if_snmpaddr: %d (%d slots)", __func__,
6533 config->interface_snmpaddrs.num_data, config->interface_snmpaddrs.num_slots);
6534 zabbix_log(LOG_LEVEL_DEBUG, "%s() items : %d (%d slots)", __func__,
6535 config->items.num_data, config->items.num_slots);
6536 zabbix_log(LOG_LEVEL_DEBUG, "%s() items_hk : %d (%d slots)", __func__,
6537 config->items_hk.num_data, config->items_hk.num_slots);
6538 zabbix_log(LOG_LEVEL_DEBUG, "%s() numitems : %d (%d slots)", __func__,
6539 config->numitems.num_data, config->numitems.num_slots);
6540 zabbix_log(LOG_LEVEL_DEBUG, "%s() preprocitems: %d (%d slots)", __func__,
6541 config->preprocitems.num_data, config->preprocitems.num_slots);
6542 zabbix_log(LOG_LEVEL_DEBUG, "%s() preprocops : %d (%d slots)", __func__,
6543 config->preprocops.num_data, config->preprocops.num_slots);
6544 zabbix_log(LOG_LEVEL_DEBUG, "%s() snmpitems : %d (%d slots)", __func__,
6545 config->snmpitems.num_data, config->snmpitems.num_slots);
6546 zabbix_log(LOG_LEVEL_DEBUG, "%s() ipmiitems : %d (%d slots)", __func__,
6547 config->ipmiitems.num_data, config->ipmiitems.num_slots);
6548 zabbix_log(LOG_LEVEL_DEBUG, "%s() trapitems : %d (%d slots)", __func__,
6549 config->trapitems.num_data, config->trapitems.num_slots);
6550 zabbix_log(LOG_LEVEL_DEBUG, "%s() dependentitems : %d (%d slots)", __func__,
6551 config->dependentitems.num_data, config->dependentitems.num_slots);
6552 zabbix_log(LOG_LEVEL_DEBUG, "%s() logitems : %d (%d slots)", __func__,
6553 config->logitems.num_data, config->logitems.num_slots);
6554 zabbix_log(LOG_LEVEL_DEBUG, "%s() dbitems : %d (%d slots)", __func__,
6555 config->dbitems.num_data, config->dbitems.num_slots);
6556 zabbix_log(LOG_LEVEL_DEBUG, "%s() sshitems : %d (%d slots)", __func__,
6557 config->sshitems.num_data, config->sshitems.num_slots);
6558 zabbix_log(LOG_LEVEL_DEBUG, "%s() telnetitems: %d (%d slots)", __func__,
6559 config->telnetitems.num_data, config->telnetitems.num_slots);
6560 zabbix_log(LOG_LEVEL_DEBUG, "%s() simpleitems: %d (%d slots)", __func__,
6561 config->simpleitems.num_data, config->simpleitems.num_slots);
6562 zabbix_log(LOG_LEVEL_DEBUG, "%s() jmxitems : %d (%d slots)", __func__,
6563 config->jmxitems.num_data, config->jmxitems.num_slots);
6564 zabbix_log(LOG_LEVEL_DEBUG, "%s() calcitems : %d (%d slots)", __func__,
6565 config->calcitems.num_data, config->calcitems.num_slots);
6566 zabbix_log(LOG_LEVEL_DEBUG, "%s() httpitems : %d (%d slots)", __func__,
6567 config->httpitems.num_data, config->httpitems.num_slots);
6568 zabbix_log(LOG_LEVEL_DEBUG, "%s() scriptitems : %d (%d slots)", __func__,
6569 config->scriptitems.num_data, config->scriptitems.num_slots);
6570 zabbix_log(LOG_LEVEL_DEBUG, "%s() functions : %d (%d slots)", __func__,
6571 config->functions.num_data, config->functions.num_slots);
6572 zabbix_log(LOG_LEVEL_DEBUG, "%s() triggers : %d (%d slots)", __func__,
6573 config->triggers.num_data, config->triggers.num_slots);
6574 zabbix_log(LOG_LEVEL_DEBUG, "%s() trigdeps : %d (%d slots)", __func__,
6575 config->trigdeps.num_data, config->trigdeps.num_slots);
6576 zabbix_log(LOG_LEVEL_DEBUG, "%s() trig. tags : %d (%d slots)", __func__,
6577 config->trigger_tags.num_data, config->trigger_tags.num_slots);
6578 zabbix_log(LOG_LEVEL_DEBUG, "%s() expressions: %d (%d slots)", __func__,
6579 config->expressions.num_data, config->expressions.num_slots);
6580
6581 zabbix_log(LOG_LEVEL_DEBUG, "%s() actions : %d (%d slots)", __func__,
6582 config->actions.num_data, config->actions.num_slots);
6583 zabbix_log(LOG_LEVEL_DEBUG, "%s() conditions : %d (%d slots)", __func__,
6584 config->action_conditions.num_data, config->action_conditions.num_slots);
6585
6586 zabbix_log(LOG_LEVEL_DEBUG, "%s() corr. : %d (%d slots)", __func__,
6587 config->correlations.num_data, config->correlations.num_slots);
6588 zabbix_log(LOG_LEVEL_DEBUG, "%s() corr. conds: %d (%d slots)", __func__,
6589 config->corr_conditions.num_data, config->corr_conditions.num_slots);
6590 zabbix_log(LOG_LEVEL_DEBUG, "%s() corr. ops : %d (%d slots)", __func__,
6591 config->corr_operations.num_data, config->corr_operations.num_slots);
6592 zabbix_log(LOG_LEVEL_DEBUG, "%s() hgroups : %d (%d slots)", __func__,
6593 config->hostgroups.num_data, config->hostgroups.num_slots);
6594 zabbix_log(LOG_LEVEL_DEBUG, "%s() item procs : %d (%d slots)", __func__,
6595 config->preprocops.num_data, config->preprocops.num_slots);
6596
6597 zabbix_log(LOG_LEVEL_DEBUG, "%s() maintenance: %d (%d slots)", __func__,
6598 config->maintenances.num_data, config->maintenances.num_slots);
6599 zabbix_log(LOG_LEVEL_DEBUG, "%s() maint tags : %d (%d slots)", __func__,
6600 config->maintenance_tags.num_data, config->maintenance_tags.num_slots);
6601 zabbix_log(LOG_LEVEL_DEBUG, "%s() maint time : %d (%d slots)", __func__,
6602 config->maintenance_periods.num_data, config->maintenance_periods.num_slots);
6603
6604 for (i = 0; ZBX_POLLER_TYPE_COUNT > i; i++)
6605 {
6606 zabbix_log(LOG_LEVEL_DEBUG, "%s() queue[%d] : %d (%d allocated)", __func__,
6607 i, config->queues[i].elems_num, config->queues[i].elems_alloc);
6608 }
6609
6610 zabbix_log(LOG_LEVEL_DEBUG, "%s() pqueue : %d (%d allocated)", __func__,
6611 config->pqueue.elems_num, config->pqueue.elems_alloc);
6612
6613 zabbix_log(LOG_LEVEL_DEBUG, "%s() timer queue: %d (%d allocated)", __func__,
6614 config->trigger_queue.elems_num, config->trigger_queue.elems_alloc);
6615
6616 zabbix_log(LOG_LEVEL_DEBUG, "%s() configfree : " ZBX_FS_DBL "%%", __func__,
6617 100 * ((double)config_mem->free_size / config_mem->orig_size));
6618
6619 zabbix_log(LOG_LEVEL_DEBUG, "%s() strings : %d (%d slots)", __func__,
6620 config->strpool.num_data, config->strpool.num_slots);
6621
6622 zbx_mem_dump_stats(LOG_LEVEL_DEBUG, config_mem);
6623 }
6624 out:
6625 if (0 == sync_in_progress)
6626 {
6627 /* non recoverable database error is encountered */
6628 THIS_SHOULD_NEVER_HAPPEN;
6629 START_SYNC;
6630 }
6631
6632 config->status->last_update = 0;
6633 config->sync_ts = time(NULL);
6634
6635 FINISH_SYNC;
6636
6637 zbx_dbsync_clear(&config_sync);
6638 zbx_dbsync_clear(&autoreg_config_sync);
6639 zbx_dbsync_clear(&hosts_sync);
6640 zbx_dbsync_clear(&hi_sync);
6641 zbx_dbsync_clear(&htmpl_sync);
6642 zbx_dbsync_clear(&gmacro_sync);
6643 zbx_dbsync_clear(&hmacro_sync);
6644 zbx_dbsync_clear(&host_tag_sync);
6645 zbx_dbsync_clear(&if_sync);
6646 zbx_dbsync_clear(&items_sync);
6647 zbx_dbsync_clear(&template_items_sync);
6648 zbx_dbsync_clear(&prototype_items_sync);
6649 zbx_dbsync_clear(&triggers_sync);
6650 zbx_dbsync_clear(&tdep_sync);
6651 zbx_dbsync_clear(&func_sync);
6652 zbx_dbsync_clear(&expr_sync);
6653 zbx_dbsync_clear(&action_sync);
6654 zbx_dbsync_clear(&action_op_sync);
6655 zbx_dbsync_clear(&action_condition_sync);
6656 zbx_dbsync_clear(&trigger_tag_sync);
6657 zbx_dbsync_clear(&correlation_sync);
6658 zbx_dbsync_clear(&corr_condition_sync);
6659 zbx_dbsync_clear(&corr_operation_sync);
6660 zbx_dbsync_clear(&hgroups_sync);
6661 zbx_dbsync_clear(&itempp_sync);
6662 zbx_dbsync_clear(&itemscrp_sync);
6663 zbx_dbsync_clear(&item_tag_sync);
6664 zbx_dbsync_clear(&maintenance_sync);
6665 zbx_dbsync_clear(&maintenance_period_sync);
6666 zbx_dbsync_clear(&maintenance_tag_sync);
6667 zbx_dbsync_clear(&maintenance_group_sync);
6668 zbx_dbsync_clear(&maintenance_host_sync);
6669 zbx_dbsync_clear(&hgroup_host_sync);
6670
6671 if (ZBX_DBSYNC_INIT == mode)
6672 zbx_hashset_destroy(&trend_queue);
6673
6674 zbx_dbsync_free_env();
6675 skip:
6676 if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_TRACE))
6677 DCdump_configuration();
6678
6679 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
6680 }
6681
6682 /******************************************************************************
6683 * *
6684 * Helper functions for configuration cache data structure element comparison *
6685 * and hash value calculation. *
6686 * *
6687 * The __config_mem_XXX_func(), __config_XXX_hash and __config_XXX_compare *
6688 * functions are used only inside init_configuration_cache() function to *
6689 * initialize internal data structures. *
6690 * *
6691 ******************************************************************************/
6692
__config_item_hk_hash(const void * data)6693 static zbx_hash_t __config_item_hk_hash(const void *data)
6694 {
6695 const ZBX_DC_ITEM_HK *item_hk = (const ZBX_DC_ITEM_HK *)data;
6696
6697 zbx_hash_t hash;
6698
6699 hash = ZBX_DEFAULT_UINT64_HASH_FUNC(&item_hk->hostid);
6700 hash = ZBX_DEFAULT_STRING_HASH_ALGO(item_hk->key, strlen(item_hk->key), hash);
6701
6702 return hash;
6703 }
6704
__config_item_hk_compare(const void * d1,const void * d2)6705 static int __config_item_hk_compare(const void *d1, const void *d2)
6706 {
6707 const ZBX_DC_ITEM_HK *item_hk_1 = (const ZBX_DC_ITEM_HK *)d1;
6708 const ZBX_DC_ITEM_HK *item_hk_2 = (const ZBX_DC_ITEM_HK *)d2;
6709
6710 ZBX_RETURN_IF_NOT_EQUAL(item_hk_1->hostid, item_hk_2->hostid);
6711
6712 return item_hk_1->key == item_hk_2->key ? 0 : strcmp(item_hk_1->key, item_hk_2->key);
6713 }
6714
__config_host_h_hash(const void * data)6715 static zbx_hash_t __config_host_h_hash(const void *data)
6716 {
6717 const ZBX_DC_HOST_H *host_h = (const ZBX_DC_HOST_H *)data;
6718
6719 return ZBX_DEFAULT_STRING_HASH_ALGO(host_h->host, strlen(host_h->host), ZBX_DEFAULT_HASH_SEED);
6720 }
6721
__config_host_h_compare(const void * d1,const void * d2)6722 static int __config_host_h_compare(const void *d1, const void *d2)
6723 {
6724 const ZBX_DC_HOST_H *host_h_1 = (const ZBX_DC_HOST_H *)d1;
6725 const ZBX_DC_HOST_H *host_h_2 = (const ZBX_DC_HOST_H *)d2;
6726
6727 return host_h_1->host == host_h_2->host ? 0 : strcmp(host_h_1->host, host_h_2->host);
6728 }
6729
__config_gmacro_m_hash(const void * data)6730 static zbx_hash_t __config_gmacro_m_hash(const void *data)
6731 {
6732 const ZBX_DC_GMACRO_M *gmacro_m = (const ZBX_DC_GMACRO_M *)data;
6733
6734 zbx_hash_t hash;
6735
6736 hash = ZBX_DEFAULT_STRING_HASH_FUNC(gmacro_m->macro);
6737
6738 return hash;
6739 }
6740
__config_gmacro_m_compare(const void * d1,const void * d2)6741 static int __config_gmacro_m_compare(const void *d1, const void *d2)
6742 {
6743 const ZBX_DC_GMACRO_M *gmacro_m_1 = (const ZBX_DC_GMACRO_M *)d1;
6744 const ZBX_DC_GMACRO_M *gmacro_m_2 = (const ZBX_DC_GMACRO_M *)d2;
6745
6746 return gmacro_m_1->macro == gmacro_m_2->macro ? 0 : strcmp(gmacro_m_1->macro, gmacro_m_2->macro);
6747 }
6748
__config_hmacro_hm_hash(const void * data)6749 static zbx_hash_t __config_hmacro_hm_hash(const void *data)
6750 {
6751 const ZBX_DC_HMACRO_HM *hmacro_hm = (const ZBX_DC_HMACRO_HM *)data;
6752
6753 zbx_hash_t hash;
6754
6755 hash = ZBX_DEFAULT_UINT64_HASH_FUNC(&hmacro_hm->hostid);
6756 hash = ZBX_DEFAULT_STRING_HASH_ALGO(hmacro_hm->macro, strlen(hmacro_hm->macro), hash);
6757
6758 return hash;
6759 }
6760
__config_hmacro_hm_compare(const void * d1,const void * d2)6761 static int __config_hmacro_hm_compare(const void *d1, const void *d2)
6762 {
6763 const ZBX_DC_HMACRO_HM *hmacro_hm_1 = (const ZBX_DC_HMACRO_HM *)d1;
6764 const ZBX_DC_HMACRO_HM *hmacro_hm_2 = (const ZBX_DC_HMACRO_HM *)d2;
6765
6766 ZBX_RETURN_IF_NOT_EQUAL(hmacro_hm_1->hostid, hmacro_hm_2->hostid);
6767
6768 return hmacro_hm_1->macro == hmacro_hm_2->macro ? 0 : strcmp(hmacro_hm_1->macro, hmacro_hm_2->macro);
6769 }
6770
__config_interface_ht_hash(const void * data)6771 static zbx_hash_t __config_interface_ht_hash(const void *data)
6772 {
6773 const ZBX_DC_INTERFACE_HT *interface_ht = (const ZBX_DC_INTERFACE_HT *)data;
6774
6775 zbx_hash_t hash;
6776
6777 hash = ZBX_DEFAULT_UINT64_HASH_FUNC(&interface_ht->hostid);
6778 hash = ZBX_DEFAULT_STRING_HASH_ALGO((char *)&interface_ht->type, 1, hash);
6779
6780 return hash;
6781 }
6782
__config_interface_ht_compare(const void * d1,const void * d2)6783 static int __config_interface_ht_compare(const void *d1, const void *d2)
6784 {
6785 const ZBX_DC_INTERFACE_HT *interface_ht_1 = (const ZBX_DC_INTERFACE_HT *)d1;
6786 const ZBX_DC_INTERFACE_HT *interface_ht_2 = (const ZBX_DC_INTERFACE_HT *)d2;
6787
6788 ZBX_RETURN_IF_NOT_EQUAL(interface_ht_1->hostid, interface_ht_2->hostid);
6789 ZBX_RETURN_IF_NOT_EQUAL(interface_ht_1->type, interface_ht_2->type);
6790
6791 return 0;
6792 }
6793
__config_interface_addr_hash(const void * data)6794 static zbx_hash_t __config_interface_addr_hash(const void *data)
6795 {
6796 const ZBX_DC_INTERFACE_ADDR *interface_addr = (const ZBX_DC_INTERFACE_ADDR *)data;
6797
6798 return ZBX_DEFAULT_STRING_HASH_ALGO(interface_addr->addr, strlen(interface_addr->addr), ZBX_DEFAULT_HASH_SEED);
6799 }
6800
__config_interface_addr_compare(const void * d1,const void * d2)6801 static int __config_interface_addr_compare(const void *d1, const void *d2)
6802 {
6803 const ZBX_DC_INTERFACE_ADDR *interface_addr_1 = (const ZBX_DC_INTERFACE_ADDR *)d1;
6804 const ZBX_DC_INTERFACE_ADDR *interface_addr_2 = (const ZBX_DC_INTERFACE_ADDR *)d2;
6805
6806 return (interface_addr_1->addr == interface_addr_2->addr ? 0 : strcmp(interface_addr_1->addr, interface_addr_2->addr));
6807 }
6808
__config_snmp_item_compare(const ZBX_DC_ITEM * i1,const ZBX_DC_ITEM * i2)6809 static int __config_snmp_item_compare(const ZBX_DC_ITEM *i1, const ZBX_DC_ITEM *i2)
6810 {
6811 const ZBX_DC_SNMPITEM *s1;
6812 const ZBX_DC_SNMPITEM *s2;
6813
6814 unsigned char f1;
6815 unsigned char f2;
6816
6817 ZBX_RETURN_IF_NOT_EQUAL(i1->interfaceid, i2->interfaceid);
6818 ZBX_RETURN_IF_NOT_EQUAL(i1->type, i2->type);
6819
6820 f1 = ZBX_FLAG_DISCOVERY_RULE & i1->flags;
6821 f2 = ZBX_FLAG_DISCOVERY_RULE & i2->flags;
6822
6823 ZBX_RETURN_IF_NOT_EQUAL(f1, f2);
6824
6825 s1 = (ZBX_DC_SNMPITEM *)zbx_hashset_search(&config->snmpitems, &i1->itemid);
6826 s2 = (ZBX_DC_SNMPITEM *)zbx_hashset_search(&config->snmpitems, &i2->itemid);
6827
6828 ZBX_RETURN_IF_NOT_EQUAL(s1->snmp_oid_type, s2->snmp_oid_type);
6829
6830 return 0;
6831 }
6832
__config_heap_elem_compare(const void * d1,const void * d2)6833 static int __config_heap_elem_compare(const void *d1, const void *d2)
6834 {
6835 const zbx_binary_heap_elem_t *e1 = (const zbx_binary_heap_elem_t *)d1;
6836 const zbx_binary_heap_elem_t *e2 = (const zbx_binary_heap_elem_t *)d2;
6837
6838 const ZBX_DC_ITEM *i1 = (const ZBX_DC_ITEM *)e1->data;
6839 const ZBX_DC_ITEM *i2 = (const ZBX_DC_ITEM *)e2->data;
6840
6841 ZBX_RETURN_IF_NOT_EQUAL(i1->nextcheck, i2->nextcheck);
6842 ZBX_RETURN_IF_NOT_EQUAL(i1->queue_priority, i2->queue_priority);
6843
6844 if (ITEM_TYPE_SNMP != i1->type)
6845 {
6846 if (ITEM_TYPE_SNMP != i2->type)
6847 return 0;
6848
6849 return -1;
6850 }
6851 else
6852 {
6853 if (ITEM_TYPE_SNMP != i2->type)
6854 return +1;
6855
6856 return __config_snmp_item_compare(i1, i2);
6857 }
6858 }
6859
__config_pinger_elem_compare(const void * d1,const void * d2)6860 static int __config_pinger_elem_compare(const void *d1, const void *d2)
6861 {
6862 const zbx_binary_heap_elem_t *e1 = (const zbx_binary_heap_elem_t *)d1;
6863 const zbx_binary_heap_elem_t *e2 = (const zbx_binary_heap_elem_t *)d2;
6864
6865 const ZBX_DC_ITEM *i1 = (const ZBX_DC_ITEM *)e1->data;
6866 const ZBX_DC_ITEM *i2 = (const ZBX_DC_ITEM *)e2->data;
6867
6868 ZBX_RETURN_IF_NOT_EQUAL(i1->nextcheck, i2->nextcheck);
6869 ZBX_RETURN_IF_NOT_EQUAL(i1->queue_priority, i2->queue_priority);
6870 ZBX_RETURN_IF_NOT_EQUAL(i1->interfaceid, i2->interfaceid);
6871
6872 return 0;
6873 }
6874
__config_java_item_compare(const ZBX_DC_ITEM * i1,const ZBX_DC_ITEM * i2)6875 static int __config_java_item_compare(const ZBX_DC_ITEM *i1, const ZBX_DC_ITEM *i2)
6876 {
6877 const ZBX_DC_JMXITEM *j1;
6878 const ZBX_DC_JMXITEM *j2;
6879
6880 ZBX_RETURN_IF_NOT_EQUAL(i1->interfaceid, i2->interfaceid);
6881
6882 j1 = (ZBX_DC_JMXITEM *)zbx_hashset_search(&config->jmxitems, &i1->itemid);
6883 j2 = (ZBX_DC_JMXITEM *)zbx_hashset_search(&config->jmxitems, &i2->itemid);
6884
6885 ZBX_RETURN_IF_NOT_EQUAL(j1->username, j2->username);
6886 ZBX_RETURN_IF_NOT_EQUAL(j1->password, j2->password);
6887 ZBX_RETURN_IF_NOT_EQUAL(j1->jmx_endpoint, j2->jmx_endpoint);
6888
6889 return 0;
6890 }
6891
__config_java_elem_compare(const void * d1,const void * d2)6892 static int __config_java_elem_compare(const void *d1, const void *d2)
6893 {
6894 const zbx_binary_heap_elem_t *e1 = (const zbx_binary_heap_elem_t *)d1;
6895 const zbx_binary_heap_elem_t *e2 = (const zbx_binary_heap_elem_t *)d2;
6896
6897 const ZBX_DC_ITEM *i1 = (const ZBX_DC_ITEM *)e1->data;
6898 const ZBX_DC_ITEM *i2 = (const ZBX_DC_ITEM *)e2->data;
6899
6900 ZBX_RETURN_IF_NOT_EQUAL(i1->nextcheck, i2->nextcheck);
6901 ZBX_RETURN_IF_NOT_EQUAL(i1->queue_priority, i2->queue_priority);
6902
6903 return __config_java_item_compare(i1, i2);
6904 }
6905
__config_proxy_compare(const void * d1,const void * d2)6906 static int __config_proxy_compare(const void *d1, const void *d2)
6907 {
6908 const zbx_binary_heap_elem_t *e1 = (const zbx_binary_heap_elem_t *)d1;
6909 const zbx_binary_heap_elem_t *e2 = (const zbx_binary_heap_elem_t *)d2;
6910
6911 const ZBX_DC_PROXY *p1 = (const ZBX_DC_PROXY *)e1->data;
6912 const ZBX_DC_PROXY *p2 = (const ZBX_DC_PROXY *)e2->data;
6913
6914 ZBX_RETURN_IF_NOT_EQUAL(p1->nextcheck, p2->nextcheck);
6915
6916 return 0;
6917 }
6918
6919 /* hash and compare functions for expressions hashset */
6920
__config_regexp_hash(const void * data)6921 static zbx_hash_t __config_regexp_hash(const void *data)
6922 {
6923 const ZBX_DC_REGEXP *regexp = (const ZBX_DC_REGEXP *)data;
6924
6925 return ZBX_DEFAULT_STRING_HASH_FUNC(regexp->name);
6926 }
6927
__config_regexp_compare(const void * d1,const void * d2)6928 static int __config_regexp_compare(const void *d1, const void *d2)
6929 {
6930 const ZBX_DC_REGEXP *r1 = (const ZBX_DC_REGEXP *)d1;
6931 const ZBX_DC_REGEXP *r2 = (const ZBX_DC_REGEXP *)d2;
6932
6933 return r1->name == r2->name ? 0 : strcmp(r1->name, r2->name);
6934 }
6935
6936 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
__config_psk_hash(const void * data)6937 static zbx_hash_t __config_psk_hash(const void *data)
6938 {
6939 const ZBX_DC_PSK *psk_i = (const ZBX_DC_PSK *)data;
6940
6941 return ZBX_DEFAULT_STRING_HASH_ALGO(psk_i->tls_psk_identity, strlen(psk_i->tls_psk_identity),
6942 ZBX_DEFAULT_HASH_SEED);
6943 }
6944
__config_psk_compare(const void * d1,const void * d2)6945 static int __config_psk_compare(const void *d1, const void *d2)
6946 {
6947 const ZBX_DC_PSK *psk_1 = (const ZBX_DC_PSK *)d1;
6948 const ZBX_DC_PSK *psk_2 = (const ZBX_DC_PSK *)d2;
6949
6950 return psk_1->tls_psk_identity == psk_2->tls_psk_identity ? 0 : strcmp(psk_1->tls_psk_identity,
6951 psk_2->tls_psk_identity);
6952 }
6953 #endif
6954
__config_timer_compare(const void * d1,const void * d2)6955 static int __config_timer_compare(const void *d1, const void *d2)
6956 {
6957 const zbx_binary_heap_elem_t *e1 = (const zbx_binary_heap_elem_t *)d1;
6958 const zbx_binary_heap_elem_t *e2 = (const zbx_binary_heap_elem_t *)d2;
6959
6960 const zbx_trigger_timer_t *t1 = (const zbx_trigger_timer_t *)e1->data;
6961 const zbx_trigger_timer_t *t2 = (const zbx_trigger_timer_t *)e2->data;
6962
6963 int ret;
6964
6965 if (0 != (ret = zbx_timespec_compare(&t1->exec_ts, &t2->exec_ts)))
6966 return ret;
6967
6968 ZBX_RETURN_IF_NOT_EQUAL(t1->triggerid, t2->triggerid);
6969
6970 if (0 != (ret = zbx_timespec_compare(&t1->eval_ts, &t2->eval_ts)))
6971 return ret;
6972
6973 return 0;
6974 }
6975
__config_data_session_hash(const void * data)6976 static zbx_hash_t __config_data_session_hash(const void *data)
6977 {
6978 const zbx_data_session_t *session = (const zbx_data_session_t *)data;
6979 zbx_hash_t hash;
6980
6981 hash = ZBX_DEFAULT_UINT64_HASH_FUNC(&session->hostid);
6982 return ZBX_DEFAULT_STRING_HASH_ALGO(session->token, strlen(session->token), hash);
6983 }
6984
__config_data_session_compare(const void * d1,const void * d2)6985 static int __config_data_session_compare(const void *d1, const void *d2)
6986 {
6987 const zbx_data_session_t *s1 = (const zbx_data_session_t *)d1;
6988 const zbx_data_session_t *s2 = (const zbx_data_session_t *)d2;
6989
6990 ZBX_RETURN_IF_NOT_EQUAL(s1->hostid, s2->hostid);
6991 return strcmp(s1->token, s2->token);
6992 }
6993
6994 /******************************************************************************
6995 * *
6996 * Function: init_configuration_cache *
6997 * *
6998 * Purpose: Allocate shared memory for configuration cache *
6999 * *
7000 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
7001 * *
7002 ******************************************************************************/
init_configuration_cache(char ** error)7003 int init_configuration_cache(char **error)
7004 {
7005 int i, ret;
7006
7007 zabbix_log(LOG_LEVEL_DEBUG, "In %s() size:" ZBX_FS_UI64, __func__, CONFIG_CONF_CACHE_SIZE);
7008
7009 if (SUCCEED != (ret = zbx_rwlock_create(&config_lock, ZBX_RWLOCK_CONFIG, error)))
7010 goto out;
7011
7012 if (SUCCEED != (ret = zbx_mem_create(&config_mem, CONFIG_CONF_CACHE_SIZE, "configuration cache",
7013 "CacheSize", 0, error)))
7014 {
7015 goto out;
7016 }
7017
7018 config = (ZBX_DC_CONFIG *)__config_mem_malloc_func(NULL, sizeof(ZBX_DC_CONFIG) +
7019 CONFIG_TIMER_FORKS * sizeof(zbx_vector_ptr_t));
7020
7021 #define CREATE_HASHSET(hashset, hashset_size) \
7022 \
7023 CREATE_HASHSET_EXT(hashset, hashset_size, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC)
7024
7025 #define CREATE_HASHSET_EXT(hashset, hashset_size, hash_func, compare_func) \
7026 \
7027 zbx_hashset_create_ext(&hashset, hashset_size, hash_func, compare_func, NULL, \
7028 __config_mem_malloc_func, __config_mem_realloc_func, __config_mem_free_func)
7029
7030 CREATE_HASHSET(config->items, 100);
7031 CREATE_HASHSET(config->numitems, 0);
7032 CREATE_HASHSET(config->snmpitems, 0);
7033 CREATE_HASHSET(config->ipmiitems, 0);
7034 CREATE_HASHSET(config->trapitems, 0);
7035 CREATE_HASHSET(config->dependentitems, 0);
7036 CREATE_HASHSET(config->logitems, 0);
7037 CREATE_HASHSET(config->dbitems, 0);
7038 CREATE_HASHSET(config->sshitems, 0);
7039 CREATE_HASHSET(config->telnetitems, 0);
7040 CREATE_HASHSET(config->simpleitems, 0);
7041 CREATE_HASHSET(config->jmxitems, 0);
7042 CREATE_HASHSET(config->calcitems, 0);
7043 CREATE_HASHSET(config->masteritems, 0);
7044 CREATE_HASHSET(config->preprocitems, 0);
7045 CREATE_HASHSET(config->httpitems, 0);
7046 CREATE_HASHSET(config->scriptitems, 0);
7047 CREATE_HASHSET(config->itemscript_params, 0);
7048 CREATE_HASHSET(config->template_items, 0);
7049 CREATE_HASHSET(config->prototype_items, 0);
7050 CREATE_HASHSET(config->functions, 100);
7051 CREATE_HASHSET(config->triggers, 100);
7052 CREATE_HASHSET(config->trigdeps, 0);
7053 CREATE_HASHSET(config->hosts, 10);
7054 CREATE_HASHSET(config->proxies, 0);
7055 CREATE_HASHSET(config->host_inventories, 0);
7056 CREATE_HASHSET(config->host_inventories_auto, 0);
7057 CREATE_HASHSET(config->ipmihosts, 0);
7058 CREATE_HASHSET(config->htmpls, 0);
7059 CREATE_HASHSET(config->gmacros, 0);
7060 CREATE_HASHSET(config->hmacros, 0);
7061 CREATE_HASHSET(config->interfaces, 10);
7062 CREATE_HASHSET(config->interfaces_snmp, 0);
7063 CREATE_HASHSET(config->interface_snmpitems, 0);
7064 CREATE_HASHSET(config->expressions, 0);
7065 CREATE_HASHSET(config->actions, 0);
7066 CREATE_HASHSET(config->action_conditions, 0);
7067 CREATE_HASHSET(config->trigger_tags, 0);
7068 CREATE_HASHSET(config->item_tags, 0);
7069 CREATE_HASHSET(config->host_tags, 0);
7070 CREATE_HASHSET(config->host_tags_index, 0);
7071 CREATE_HASHSET(config->correlations, 0);
7072 CREATE_HASHSET(config->corr_conditions, 0);
7073 CREATE_HASHSET(config->corr_operations, 0);
7074 CREATE_HASHSET(config->hostgroups, 0);
7075 zbx_vector_ptr_create_ext(&config->hostgroups_name, __config_mem_malloc_func, __config_mem_realloc_func,
7076 __config_mem_free_func);
7077 zbx_vector_ptr_create_ext(&config->kvs_paths, __config_mem_malloc_func, __config_mem_realloc_func,
7078 __config_mem_free_func);
7079
7080 CREATE_HASHSET(config->preprocops, 0);
7081
7082 CREATE_HASHSET(config->maintenances, 0);
7083 CREATE_HASHSET(config->maintenance_periods, 0);
7084 CREATE_HASHSET(config->maintenance_tags, 0);
7085
7086 CREATE_HASHSET_EXT(config->items_hk, 100, __config_item_hk_hash, __config_item_hk_compare);
7087 CREATE_HASHSET_EXT(config->hosts_h, 10, __config_host_h_hash, __config_host_h_compare);
7088 CREATE_HASHSET_EXT(config->hosts_p, 0, __config_host_h_hash, __config_host_h_compare);
7089 CREATE_HASHSET_EXT(config->gmacros_m, 0, __config_gmacro_m_hash, __config_gmacro_m_compare);
7090 CREATE_HASHSET_EXT(config->hmacros_hm, 0, __config_hmacro_hm_hash, __config_hmacro_hm_compare);
7091 CREATE_HASHSET_EXT(config->interfaces_ht, 10, __config_interface_ht_hash, __config_interface_ht_compare);
7092 CREATE_HASHSET_EXT(config->interface_snmpaddrs, 0, __config_interface_addr_hash, __config_interface_addr_compare);
7093 CREATE_HASHSET_EXT(config->regexps, 0, __config_regexp_hash, __config_regexp_compare);
7094
7095 CREATE_HASHSET_EXT(config->strpool, 100, __config_strpool_hash, __config_strpool_compare);
7096
7097 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
7098 CREATE_HASHSET_EXT(config->psks, 0, __config_psk_hash, __config_psk_compare);
7099 #endif
7100
7101 for (i = 0; i < ZBX_POLLER_TYPE_COUNT; i++)
7102 {
7103 switch (i)
7104 {
7105 case ZBX_POLLER_TYPE_JAVA:
7106 zbx_binary_heap_create_ext(&config->queues[i],
7107 __config_java_elem_compare,
7108 ZBX_BINARY_HEAP_OPTION_DIRECT,
7109 __config_mem_malloc_func,
7110 __config_mem_realloc_func,
7111 __config_mem_free_func);
7112 break;
7113 case ZBX_POLLER_TYPE_PINGER:
7114 zbx_binary_heap_create_ext(&config->queues[i],
7115 __config_pinger_elem_compare,
7116 ZBX_BINARY_HEAP_OPTION_DIRECT,
7117 __config_mem_malloc_func,
7118 __config_mem_realloc_func,
7119 __config_mem_free_func);
7120 break;
7121 default:
7122 zbx_binary_heap_create_ext(&config->queues[i],
7123 __config_heap_elem_compare,
7124 ZBX_BINARY_HEAP_OPTION_DIRECT,
7125 __config_mem_malloc_func,
7126 __config_mem_realloc_func,
7127 __config_mem_free_func);
7128 break;
7129 }
7130 }
7131
7132 zbx_binary_heap_create_ext(&config->pqueue,
7133 __config_proxy_compare,
7134 ZBX_BINARY_HEAP_OPTION_DIRECT,
7135 __config_mem_malloc_func,
7136 __config_mem_realloc_func,
7137 __config_mem_free_func);
7138
7139 zbx_binary_heap_create_ext(&config->trigger_queue,
7140 __config_timer_compare,
7141 ZBX_BINARY_HEAP_OPTION_EMPTY,
7142 __config_mem_malloc_func,
7143 __config_mem_realloc_func,
7144 __config_mem_free_func);
7145
7146 CREATE_HASHSET_EXT(config->data_sessions, 0, __config_data_session_hash, __config_data_session_compare);
7147
7148 config->config = NULL;
7149
7150 config->status = (ZBX_DC_STATUS *)__config_mem_malloc_func(NULL, sizeof(ZBX_DC_STATUS));
7151 config->status->last_update = 0;
7152
7153 config->availability_diff_ts = 0;
7154 config->sync_ts = 0;
7155 config->item_sync_ts = 0;
7156 config->sync_start_ts = 0;
7157
7158 config->internal_actions = 0;
7159
7160 /* maintenance data are used only when timers are defined (server) */
7161 if (0 != CONFIG_TIMER_FORKS)
7162 {
7163 config->maintenance_update = ZBX_MAINTENANCE_UPDATE_FALSE;
7164 config->maintenance_update_flags = (zbx_uint64_t *)__config_mem_malloc_func(NULL, sizeof(zbx_uint64_t) *
7165 ZBX_MAINTENANCE_UPDATE_FLAGS_NUM());
7166 memset(config->maintenance_update_flags, 0, sizeof(zbx_uint64_t) * ZBX_MAINTENANCE_UPDATE_FLAGS_NUM());
7167 }
7168
7169 config->proxy_lastaccess_ts = time(NULL);
7170
7171 /* create data session token for proxies */
7172 if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY))
7173 {
7174 char *token;
7175
7176 token = zbx_create_token(0);
7177 config->session_token = dc_strdup(token);
7178 zbx_free(token);
7179 }
7180 else
7181 config->session_token = NULL;
7182
7183 #undef CREATE_HASHSET
7184 #undef CREATE_HASHSET_EXT
7185 out:
7186 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
7187
7188 return ret;
7189 }
7190
7191 /******************************************************************************
7192 * *
7193 * Function: free_configuration_cache *
7194 * *
7195 * Purpose: Free memory allocated for configuration cache *
7196 * *
7197 * Author: Alexei Vladishev, Aleksandrs Saveljevs *
7198 * *
7199 ******************************************************************************/
free_configuration_cache(void)7200 void free_configuration_cache(void)
7201 {
7202 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
7203
7204 WRLOCK_CACHE;
7205
7206 config = NULL;
7207
7208 UNLOCK_CACHE;
7209
7210 zbx_rwlock_destroy(&config_lock);
7211
7212 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
7213 }
7214
7215 /******************************************************************************
7216 * *
7217 * Function: in_maintenance_without_data_collection *
7218 * *
7219 * Parameters: maintenance_status - [IN] maintenance status *
7220 * HOST_MAINTENANCE_STATUS_* flag *
7221 * maintenance_type - [IN] maintenance type *
7222 * MAINTENANCE_TYPE_* flag *
7223 * type - [IN] item type *
7224 * ITEM_TYPE_* flag *
7225 * *
7226 * Return value: SUCCEED if host in maintenance without data collection *
7227 * FAIL otherwise *
7228 * *
7229 ******************************************************************************/
in_maintenance_without_data_collection(unsigned char maintenance_status,unsigned char maintenance_type,unsigned char type)7230 int in_maintenance_without_data_collection(unsigned char maintenance_status, unsigned char maintenance_type,
7231 unsigned char type)
7232 {
7233 if (HOST_MAINTENANCE_STATUS_ON != maintenance_status)
7234 return FAIL;
7235
7236 if (MAINTENANCE_TYPE_NODATA != maintenance_type)
7237 return FAIL;
7238
7239 if (ITEM_TYPE_INTERNAL == type)
7240 return FAIL;
7241
7242 return SUCCEED;
7243 }
7244
DCget_host(DC_HOST * dst_host,const ZBX_DC_HOST * src_host,unsigned int mode)7245 static void DCget_host(DC_HOST *dst_host, const ZBX_DC_HOST *src_host, unsigned int mode)
7246 {
7247 const ZBX_DC_IPMIHOST *ipmihost;
7248 const ZBX_DC_HOST_INVENTORY *host_inventory;
7249
7250 dst_host->hostid = src_host->hostid;
7251 dst_host->proxy_hostid = src_host->proxy_hostid;
7252 dst_host->status = src_host->status;
7253
7254 strscpy(dst_host->host, src_host->host);
7255
7256 if (ZBX_ITEM_GET_HOSTNAME & mode)
7257 zbx_strlcpy_utf8(dst_host->name, src_host->name, sizeof(dst_host->name));
7258
7259 if (ZBX_ITEM_GET_MAINTENANCE & mode)
7260 {
7261 dst_host->maintenance_status = src_host->maintenance_status;
7262 dst_host->maintenance_type = src_host->maintenance_type;
7263 dst_host->maintenance_from = src_host->maintenance_from;
7264 }
7265
7266 if (ZBX_ITEM_GET_HOSTINFO & mode)
7267 {
7268 dst_host->tls_connect = src_host->tls_connect;
7269 dst_host->tls_accept = src_host->tls_accept;
7270 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
7271 strscpy(dst_host->tls_issuer, src_host->tls_issuer);
7272 strscpy(dst_host->tls_subject, src_host->tls_subject);
7273
7274 if (NULL == src_host->tls_dc_psk)
7275 {
7276 *dst_host->tls_psk_identity = '\0';
7277 *dst_host->tls_psk = '\0';
7278 }
7279 else
7280 {
7281 strscpy(dst_host->tls_psk_identity, src_host->tls_dc_psk->tls_psk_identity);
7282 strscpy(dst_host->tls_psk, src_host->tls_dc_psk->tls_psk);
7283 }
7284 #endif
7285 if (NULL != (ipmihost = (ZBX_DC_IPMIHOST *)zbx_hashset_search(&config->ipmihosts, &src_host->hostid)))
7286 {
7287 dst_host->ipmi_authtype = ipmihost->ipmi_authtype;
7288 dst_host->ipmi_privilege = ipmihost->ipmi_privilege;
7289 strscpy(dst_host->ipmi_username, ipmihost->ipmi_username);
7290 strscpy(dst_host->ipmi_password, ipmihost->ipmi_password);
7291 }
7292 else
7293 {
7294 dst_host->ipmi_authtype = ZBX_IPMI_DEFAULT_AUTHTYPE;
7295 dst_host->ipmi_privilege = ZBX_IPMI_DEFAULT_PRIVILEGE;
7296 *dst_host->ipmi_username = '\0';
7297 *dst_host->ipmi_password = '\0';
7298 }
7299 }
7300
7301 if (ZBX_ITEM_GET_INVENTORY & mode)
7302 {
7303 if (NULL != (host_inventory = (ZBX_DC_HOST_INVENTORY *)zbx_hashset_search(&config->host_inventories, &src_host->hostid)))
7304 dst_host->inventory_mode = (char)host_inventory->inventory_mode;
7305 else
7306 dst_host->inventory_mode = HOST_INVENTORY_DISABLED;
7307 }
7308 }
7309
7310 /******************************************************************************
7311 * *
7312 * Function: DCget_host_by_hostid *
7313 * *
7314 * Purpose: Locate host in configuration cache *
7315 * *
7316 * Parameters: host - [OUT] pointer to DC_HOST structure *
7317 * hostid - [IN] host ID from database *
7318 * *
7319 * Return value: SUCCEED if record located and FAIL otherwise *
7320 * *
7321 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
7322 * *
7323 ******************************************************************************/
DCget_host_by_hostid(DC_HOST * host,zbx_uint64_t hostid)7324 int DCget_host_by_hostid(DC_HOST *host, zbx_uint64_t hostid)
7325 {
7326 int ret = FAIL;
7327 const ZBX_DC_HOST *dc_host;
7328
7329 RDLOCK_CACHE;
7330
7331 if (NULL != (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)))
7332 {
7333 DCget_host(host, dc_host, ZBX_ITEM_GET_ALL);
7334 ret = SUCCEED;
7335 }
7336
7337 UNLOCK_CACHE;
7338
7339 return ret;
7340 }
7341
7342 /******************************************************************************
7343 * *
7344 * Function: DCcheck_proxy_permissions *
7345 * *
7346 * Purpose: *
7347 * Check access rights for an active proxy and get the proxy ID *
7348 * *
7349 * Parameters: *
7350 * host - [IN] proxy name *
7351 * sock - [IN] connection socket context *
7352 * hostid - [OUT] proxy ID found in configuration cache *
7353 * error - [OUT] error message why access was denied *
7354 * *
7355 * Return value: *
7356 * SUCCEED - access is allowed, FAIL - access denied *
7357 * *
7358 * Comments: *
7359 * Generating of error messages is done outside of configuration cache *
7360 * locking. *
7361 * *
7362 ******************************************************************************/
DCcheck_proxy_permissions(const char * host,const zbx_socket_t * sock,zbx_uint64_t * hostid,char ** error)7363 int DCcheck_proxy_permissions(const char *host, const zbx_socket_t *sock, zbx_uint64_t *hostid, char **error)
7364 {
7365 const ZBX_DC_HOST *dc_host;
7366 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
7367 zbx_tls_conn_attr_t attr;
7368
7369 if (ZBX_TCP_SEC_TLS_CERT == sock->connection_type)
7370 {
7371 if (SUCCEED != zbx_tls_get_attr_cert(sock, &attr))
7372 {
7373 *error = zbx_strdup(*error, "internal error: cannot get connection attributes");
7374 THIS_SHOULD_NEVER_HAPPEN;
7375 return FAIL;
7376 }
7377 }
7378 #if defined(HAVE_GNUTLS) || (defined(HAVE_OPENSSL) && defined(HAVE_OPENSSL_WITH_PSK))
7379 else if (ZBX_TCP_SEC_TLS_PSK == sock->connection_type)
7380 {
7381 if (SUCCEED != zbx_tls_get_attr_psk(sock, &attr))
7382 {
7383 *error = zbx_strdup(*error, "internal error: cannot get connection attributes");
7384 THIS_SHOULD_NEVER_HAPPEN;
7385 return FAIL;
7386 }
7387 }
7388 #endif
7389 else if (ZBX_TCP_SEC_UNENCRYPTED != sock->connection_type)
7390 {
7391 *error = zbx_strdup(*error, "internal error: invalid connection type");
7392 THIS_SHOULD_NEVER_HAPPEN;
7393 return FAIL;
7394 }
7395 #endif
7396 RDLOCK_CACHE;
7397
7398 if (NULL == (dc_host = DCfind_proxy(host)))
7399 {
7400 UNLOCK_CACHE;
7401 *error = zbx_dsprintf(*error, "proxy \"%s\" not found", host);
7402 return FAIL;
7403 }
7404
7405 if (HOST_STATUS_PROXY_ACTIVE != dc_host->status)
7406 {
7407 UNLOCK_CACHE;
7408 *error = zbx_dsprintf(*error, "proxy \"%s\" is configured in passive mode", host);
7409 return FAIL;
7410 }
7411
7412 if (0 == ((unsigned int)dc_host->tls_accept & sock->connection_type))
7413 {
7414 UNLOCK_CACHE;
7415 *error = zbx_dsprintf(NULL, "connection of type \"%s\" is not allowed for proxy \"%s\"",
7416 zbx_tcp_connection_type_name(sock->connection_type), host);
7417 return FAIL;
7418 }
7419
7420 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
7421 if (ZBX_TCP_SEC_TLS_CERT == sock->connection_type)
7422 {
7423 /* simplified match, not compliant with RFC 4517, 4518 */
7424 if ('\0' != *dc_host->tls_issuer && 0 != strcmp(dc_host->tls_issuer, attr.issuer))
7425 {
7426 UNLOCK_CACHE;
7427 *error = zbx_dsprintf(*error, "proxy \"%s\" certificate issuer does not match", host);
7428 return FAIL;
7429 }
7430
7431 /* simplified match, not compliant with RFC 4517, 4518 */
7432 if ('\0' != *dc_host->tls_subject && 0 != strcmp(dc_host->tls_subject, attr.subject))
7433 {
7434 UNLOCK_CACHE;
7435 *error = zbx_dsprintf(*error, "proxy \"%s\" certificate subject does not match", host);
7436 return FAIL;
7437 }
7438 }
7439 #if defined(HAVE_GNUTLS) || (defined(HAVE_OPENSSL) && defined(HAVE_OPENSSL_WITH_PSK))
7440 else if (ZBX_TCP_SEC_TLS_PSK == sock->connection_type)
7441 {
7442 if (NULL != dc_host->tls_dc_psk)
7443 {
7444 if (strlen(dc_host->tls_dc_psk->tls_psk_identity) != attr.psk_identity_len ||
7445 0 != memcmp(dc_host->tls_dc_psk->tls_psk_identity, attr.psk_identity,
7446 attr.psk_identity_len))
7447 {
7448 UNLOCK_CACHE;
7449 *error = zbx_dsprintf(*error, "proxy \"%s\" is using false PSK identity", host);
7450 return FAIL;
7451 }
7452 }
7453 else
7454 {
7455 UNLOCK_CACHE;
7456 *error = zbx_dsprintf(*error, "active proxy \"%s\" is connecting with PSK but there is no PSK"
7457 " in the database for this proxy", host);
7458 return FAIL;
7459 }
7460 }
7461 #endif
7462 #endif
7463 *hostid = dc_host->hostid;
7464
7465 UNLOCK_CACHE;
7466
7467 return SUCCEED;
7468 }
7469
7470 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
7471 /******************************************************************************
7472 * *
7473 * Function: DCget_psk_by_identity *
7474 * *
7475 * Purpose: *
7476 * Find PSK with the specified identity in configuration cache *
7477 * *
7478 * Parameters: *
7479 * psk_identity - [IN] PSK identity to search for ('\0' terminated) *
7480 * psk_buf - [OUT] output buffer for PSK value with size *
7481 * HOST_TLS_PSK_LEN_MAX *
7482 * psk_usage - [OUT] 0 - PSK not found, 1 - found in host PSKs, *
7483 * 2 - found in autoregistration PSK, 3 - found in *
7484 * both *
7485 * Return value: *
7486 * PSK length in bytes if PSK found. 0 - if PSK not found. *
7487 * *
7488 * Comments: *
7489 * ATTENTION! This function's address and arguments are described and *
7490 * used in file src/libs/zbxcrypto/tls.c for calling this function by *
7491 * pointer. If you ever change this DCget_psk_by_identity() function *
7492 * arguments or return value do not forget to synchronize changes with *
7493 * the src/libs/zbxcrypto/tls.c. *
7494 * *
7495 ******************************************************************************/
DCget_psk_by_identity(const unsigned char * psk_identity,unsigned char * psk_buf,unsigned int * psk_usage)7496 size_t DCget_psk_by_identity(const unsigned char *psk_identity, unsigned char *psk_buf, unsigned int *psk_usage)
7497 {
7498 const ZBX_DC_PSK *psk_i;
7499 ZBX_DC_PSK psk_i_local;
7500 size_t psk_len = 0;
7501 unsigned char autoreg_psk_tmp[HOST_TLS_PSK_LEN_MAX];
7502
7503 *psk_usage = 0;
7504
7505 psk_i_local.tls_psk_identity = (const char *)psk_identity;
7506
7507 RDLOCK_CACHE;
7508
7509 /* Is it among host PSKs? */
7510 if (NULL != (psk_i = (ZBX_DC_PSK *)zbx_hashset_search(&config->psks, &psk_i_local)))
7511 {
7512 psk_len = zbx_strlcpy((char *)psk_buf, psk_i->tls_psk, HOST_TLS_PSK_LEN_MAX);
7513 *psk_usage |= ZBX_PSK_FOR_HOST;
7514 }
7515
7516 /* Does it match autoregistration PSK? */
7517 if (0 != strcmp(config->autoreg_psk_identity, (const char *)psk_identity))
7518 {
7519 UNLOCK_CACHE;
7520 return psk_len;
7521 }
7522
7523 if (0 == *psk_usage) /* only as autoregistration PSK */
7524 {
7525 psk_len = zbx_strlcpy((char *)psk_buf, config->autoreg_psk, HOST_TLS_PSK_LEN_MAX);
7526 UNLOCK_CACHE;
7527 *psk_usage |= ZBX_PSK_FOR_AUTOREG;
7528
7529 return psk_len;
7530 }
7531
7532 /* the requested PSK is used as host PSK and as autoregistration PSK */
7533 zbx_strlcpy((char *)autoreg_psk_tmp, config->autoreg_psk, sizeof(autoreg_psk_tmp));
7534
7535 UNLOCK_CACHE;
7536
7537 if (0 == strcmp((const char *)psk_buf, (const char *)autoreg_psk_tmp))
7538 {
7539 *psk_usage |= ZBX_PSK_FOR_AUTOREG;
7540 return psk_len;
7541 }
7542
7543 zabbix_log(LOG_LEVEL_WARNING, "host PSK and autoregistration PSK have the same identity \"%s\" but"
7544 " different PSK values, autoregistration will not be allowed", psk_identity);
7545 return psk_len;
7546 }
7547 #endif
7548
7549 /******************************************************************************
7550 * *
7551 * Function: DCget_autoregistration_psk *
7552 * *
7553 * Purpose: *
7554 * Copy autoregistration PSK identity and value from configuration cache *
7555 * into caller's buffers *
7556 * *
7557 * Parameters: *
7558 * psk_identity_buf - [OUT] buffer for PSK identity *
7559 * psk_identity_buf_len - [IN] buffer length for PSK identity *
7560 * psk_buf - [OUT] buffer for PSK value *
7561 * psk_buf_len - [IN] buffer length for PSK value *
7562 * *
7563 * Comments: if autoregistration PSK is not configured then empty strings *
7564 * will be copied into buffers *
7565 * *
7566 ******************************************************************************/
DCget_autoregistration_psk(char * psk_identity_buf,size_t psk_identity_buf_len,unsigned char * psk_buf,size_t psk_buf_len)7567 void DCget_autoregistration_psk(char *psk_identity_buf, size_t psk_identity_buf_len,
7568 unsigned char *psk_buf, size_t psk_buf_len)
7569 {
7570 RDLOCK_CACHE;
7571
7572 zbx_strlcpy((char *)psk_identity_buf, config->autoreg_psk_identity, psk_identity_buf_len);
7573 zbx_strlcpy((char *)psk_buf, config->autoreg_psk, psk_buf_len);
7574
7575 UNLOCK_CACHE;
7576 }
7577
DCget_interface(DC_INTERFACE * dst_interface,const ZBX_DC_INTERFACE * src_interface)7578 static void DCget_interface(DC_INTERFACE *dst_interface, const ZBX_DC_INTERFACE *src_interface)
7579 {
7580 if (NULL != src_interface)
7581 {
7582 dst_interface->interfaceid = src_interface->interfaceid;
7583 strscpy(dst_interface->ip_orig, src_interface->ip);
7584 strscpy(dst_interface->dns_orig, src_interface->dns);
7585 strscpy(dst_interface->port_orig, src_interface->port);
7586 dst_interface->useip = src_interface->useip;
7587 dst_interface->type = src_interface->type;
7588 dst_interface->main = src_interface->main;
7589 dst_interface->available = src_interface->available;
7590 dst_interface->disable_until = src_interface->disable_until;
7591 dst_interface->errors_from = src_interface->errors_from;
7592 strscpy(dst_interface->error, src_interface->error);
7593 }
7594 else
7595 {
7596 dst_interface->interfaceid = 0;
7597 *dst_interface->ip_orig = '\0';
7598 *dst_interface->dns_orig = '\0';
7599 *dst_interface->port_orig = '\0';
7600 dst_interface->useip = 1;
7601 dst_interface->type = INTERFACE_TYPE_UNKNOWN;
7602 dst_interface->main = 0;
7603 dst_interface->available = INTERFACE_AVAILABLE_UNKNOWN;
7604 dst_interface->disable_until = 0;
7605 dst_interface->errors_from = 0;
7606 *dst_interface->error = '\0';
7607 }
7608
7609 dst_interface->addr = (1 == dst_interface->useip ? dst_interface->ip_orig : dst_interface->dns_orig);
7610 dst_interface->port = 0;
7611 }
7612
DCget_item(DC_ITEM * dst_item,const ZBX_DC_ITEM * src_item,unsigned int mode)7613 static void DCget_item(DC_ITEM *dst_item, const ZBX_DC_ITEM *src_item, unsigned int mode)
7614 {
7615 const ZBX_DC_NUMITEM *numitem;
7616 const ZBX_DC_LOGITEM *logitem;
7617 const ZBX_DC_SNMPITEM *snmpitem;
7618 const ZBX_DC_SNMPINTERFACE *snmp;
7619 const ZBX_DC_TRAPITEM *trapitem;
7620 const ZBX_DC_IPMIITEM *ipmiitem;
7621 const ZBX_DC_DBITEM *dbitem;
7622 const ZBX_DC_SSHITEM *sshitem;
7623 const ZBX_DC_TELNETITEM *telnetitem;
7624 const ZBX_DC_SIMPLEITEM *simpleitem;
7625 const ZBX_DC_JMXITEM *jmxitem;
7626 const ZBX_DC_CALCITEM *calcitem;
7627 const ZBX_DC_INTERFACE *dc_interface;
7628 const ZBX_DC_HTTPITEM *httpitem;
7629 const ZBX_DC_SCRIPTITEM *scriptitem;
7630
7631 dst_item->type = src_item->type;
7632 dst_item->value_type = src_item->value_type;
7633
7634 dst_item->state = src_item->state;
7635 dst_item->lastlogsize = src_item->lastlogsize;
7636 dst_item->mtime = src_item->mtime;
7637
7638 dst_item->history = src_item->history;
7639
7640 dst_item->inventory_link = src_item->inventory_link;
7641 dst_item->valuemapid = src_item->valuemapid;
7642 dst_item->status = src_item->status;
7643
7644 dst_item->history_sec = src_item->history_sec;
7645 strscpy(dst_item->key_orig, src_item->key);
7646
7647 if (ZBX_ITEM_GET_MISC & mode)
7648 {
7649 dst_item->itemid = src_item->itemid; /* set after lock */
7650 dst_item->flags = src_item->flags;
7651 dst_item->key = NULL; /* set during initialization */
7652 }
7653
7654 if (ZBX_ITEM_GET_DELAY & mode)
7655 dst_item->delay = zbx_strdup(NULL, src_item->delay); /* not used, should be initialized */
7656
7657 if ((ZBX_ITEM_GET_EMPTY_ERROR & mode) || '\0' != *src_item->error) /* allocate after lock */
7658 dst_item->error = zbx_strdup(NULL, src_item->error);
7659
7660 switch (src_item->value_type)
7661 {
7662 case ITEM_VALUE_TYPE_FLOAT:
7663 case ITEM_VALUE_TYPE_UINT64:
7664 if (0 != (ZBX_ITEM_GET_NUM & mode))
7665 {
7666 numitem = (ZBX_DC_NUMITEM *)zbx_hashset_search(&config->numitems, &src_item->itemid);
7667
7668 dst_item->trends = numitem->trends;
7669 dst_item->trends_sec = numitem->trends_sec;
7670
7671 /* allocate after lock */
7672 if (0 != (ZBX_ITEM_GET_EMPTY_UNITS & mode) || '\0' != *numitem->units)
7673 dst_item->units = zbx_strdup(NULL, numitem->units);
7674 }
7675 break;
7676 case ITEM_VALUE_TYPE_LOG:
7677 if (ZBX_ITEM_GET_LOGTIMEFMT & mode)
7678 {
7679 if (NULL != (logitem = (ZBX_DC_LOGITEM *)zbx_hashset_search(&config->logitems,
7680 &src_item->itemid)))
7681 {
7682 strscpy(dst_item->logtimefmt, logitem->logtimefmt);
7683 }
7684 else
7685 *dst_item->logtimefmt = '\0';
7686 }
7687 break;
7688 }
7689
7690 if (ZBX_ITEM_GET_INTERFACE & mode) /* not used by history syncer */
7691 {
7692 dc_interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces, &src_item->interfaceid);
7693
7694 DCget_interface(&dst_item->interface, dc_interface);
7695 }
7696
7697 if (0 == (ZBX_ITEM_GET_POLLINFO & mode)) /* not used by history syncer */
7698 return;
7699
7700 switch (src_item->type)
7701 {
7702 case ITEM_TYPE_SNMP:
7703 snmpitem = (ZBX_DC_SNMPITEM *)zbx_hashset_search(&config->snmpitems, &src_item->itemid);
7704 snmp = (ZBX_DC_SNMPINTERFACE *)zbx_hashset_search(&config->interfaces_snmp, &src_item->interfaceid);
7705
7706 if (NULL != snmpitem && NULL != snmp)
7707 {
7708 strscpy(dst_item->snmp_community_orig, snmp->community);
7709 strscpy(dst_item->snmp_oid_orig, snmpitem->snmp_oid);
7710 strscpy(dst_item->snmpv3_securityname_orig, snmp->securityname);
7711 dst_item->snmpv3_securitylevel = snmp->securitylevel;
7712 strscpy(dst_item->snmpv3_authpassphrase_orig, snmp->authpassphrase);
7713 strscpy(dst_item->snmpv3_privpassphrase_orig, snmp->privpassphrase);
7714 dst_item->snmpv3_authprotocol = snmp->authprotocol;
7715 dst_item->snmpv3_privprotocol = snmp->privprotocol;
7716 strscpy(dst_item->snmpv3_contextname_orig, snmp->contextname);
7717 dst_item->snmp_version = snmp->version;
7718 }
7719 else
7720 {
7721 *dst_item->snmp_community_orig = '\0';
7722 *dst_item->snmp_oid_orig = '\0';
7723 *dst_item->snmpv3_securityname_orig = '\0';
7724 dst_item->snmpv3_securitylevel = ITEM_SNMPV3_SECURITYLEVEL_NOAUTHNOPRIV;
7725 *dst_item->snmpv3_authpassphrase_orig = '\0';
7726 *dst_item->snmpv3_privpassphrase_orig = '\0';
7727 dst_item->snmpv3_authprotocol = 0;
7728 dst_item->snmpv3_privprotocol = 0;
7729 *dst_item->snmpv3_contextname_orig = '\0';
7730 dst_item->snmp_version = ZBX_IF_SNMP_VERSION_2;
7731 }
7732
7733 dst_item->snmp_community = NULL;
7734 dst_item->snmp_oid = NULL;
7735 dst_item->snmpv3_securityname = NULL;
7736 dst_item->snmpv3_authpassphrase = NULL;
7737 dst_item->snmpv3_privpassphrase = NULL;
7738 dst_item->snmpv3_contextname = NULL;
7739 break;
7740 case ITEM_TYPE_TRAPPER:
7741 if (NULL != (trapitem = (ZBX_DC_TRAPITEM *)zbx_hashset_search(&config->trapitems, &src_item->itemid)))
7742 strscpy(dst_item->trapper_hosts, trapitem->trapper_hosts);
7743 else
7744 *dst_item->trapper_hosts = '\0';
7745 break;
7746 case ITEM_TYPE_IPMI:
7747 if (NULL != (ipmiitem = (ZBX_DC_IPMIITEM *)zbx_hashset_search(&config->ipmiitems, &src_item->itemid)))
7748 strscpy(dst_item->ipmi_sensor, ipmiitem->ipmi_sensor);
7749 else
7750 *dst_item->ipmi_sensor = '\0';
7751 break;
7752 case ITEM_TYPE_DB_MONITOR:
7753 if (NULL != (dbitem = (ZBX_DC_DBITEM *)zbx_hashset_search(&config->dbitems, &src_item->itemid)))
7754 {
7755 dst_item->params = zbx_strdup(NULL, dbitem->params);
7756 strscpy(dst_item->username_orig, dbitem->username);
7757 strscpy(dst_item->password_orig, dbitem->password);
7758 }
7759 else
7760 {
7761 dst_item->params = zbx_strdup(NULL, "");
7762 *dst_item->username_orig = '\0';
7763 *dst_item->password_orig = '\0';
7764 }
7765 dst_item->username = NULL;
7766 dst_item->password = NULL;
7767
7768 break;
7769 case ITEM_TYPE_SSH:
7770 if (NULL != (sshitem = (ZBX_DC_SSHITEM *)zbx_hashset_search(&config->sshitems, &src_item->itemid)))
7771 {
7772 dst_item->authtype = sshitem->authtype;
7773 strscpy(dst_item->username_orig, sshitem->username);
7774 strscpy(dst_item->publickey_orig, sshitem->publickey);
7775 strscpy(dst_item->privatekey_orig, sshitem->privatekey);
7776 strscpy(dst_item->password_orig, sshitem->password);
7777 dst_item->params = zbx_strdup(NULL, sshitem->params);
7778 }
7779 else
7780 {
7781 dst_item->authtype = 0;
7782 *dst_item->username_orig = '\0';
7783 *dst_item->publickey_orig = '\0';
7784 *dst_item->privatekey_orig = '\0';
7785 *dst_item->password_orig = '\0';
7786 dst_item->params = zbx_strdup(NULL, "");
7787 }
7788 dst_item->username = NULL;
7789 dst_item->publickey = NULL;
7790 dst_item->privatekey = NULL;
7791 dst_item->password = NULL;
7792 break;
7793 case ITEM_TYPE_HTTPAGENT:
7794 if (NULL != (httpitem = (ZBX_DC_HTTPITEM *)zbx_hashset_search(&config->httpitems, &src_item->itemid)))
7795 {
7796 strscpy(dst_item->timeout_orig, httpitem->timeout);
7797 strscpy(dst_item->url_orig, httpitem->url);
7798 strscpy(dst_item->query_fields_orig, httpitem->query_fields);
7799 strscpy(dst_item->status_codes_orig, httpitem->status_codes);
7800 dst_item->follow_redirects = httpitem->follow_redirects;
7801 dst_item->post_type = httpitem->post_type;
7802 strscpy(dst_item->http_proxy_orig, httpitem->http_proxy);
7803 dst_item->headers = zbx_strdup(NULL, httpitem->headers);
7804 dst_item->retrieve_mode = httpitem->retrieve_mode;
7805 dst_item->request_method = httpitem->request_method;
7806 dst_item->output_format = httpitem->output_format;
7807 strscpy(dst_item->ssl_cert_file_orig, httpitem->ssl_cert_file);
7808 strscpy(dst_item->ssl_key_file_orig, httpitem->ssl_key_file);
7809 strscpy(dst_item->ssl_key_password_orig, httpitem->ssl_key_password);
7810 dst_item->verify_peer = httpitem->verify_peer;
7811 dst_item->verify_host = httpitem->verify_host;
7812 dst_item->authtype = httpitem->authtype;
7813 strscpy(dst_item->username_orig, httpitem->username);
7814 strscpy(dst_item->password_orig, httpitem->password);
7815 dst_item->posts = zbx_strdup(NULL, httpitem->posts);
7816 dst_item->allow_traps = httpitem->allow_traps;
7817 strscpy(dst_item->trapper_hosts, httpitem->trapper_hosts);
7818 }
7819 else
7820 {
7821 *dst_item->timeout_orig = '\0';
7822 *dst_item->url_orig = '\0';
7823 *dst_item->query_fields_orig = '\0';
7824 *dst_item->status_codes_orig = '\0';
7825 dst_item->follow_redirects = 0;
7826 dst_item->post_type = 0;
7827 *dst_item->http_proxy_orig = '\0';
7828 dst_item->headers = zbx_strdup(NULL, "");
7829 dst_item->retrieve_mode = 0;
7830 dst_item->request_method = 0;
7831 dst_item->output_format = 0;
7832 *dst_item->ssl_cert_file_orig = '\0';
7833 *dst_item->ssl_key_file_orig = '\0';
7834 *dst_item->ssl_key_password_orig = '\0';
7835 dst_item->verify_peer = 0;
7836 dst_item->verify_host = 0;
7837 dst_item->authtype = 0;
7838 *dst_item->username_orig = '\0';
7839 *dst_item->password_orig = '\0';
7840 dst_item->posts = zbx_strdup(NULL, "");
7841 dst_item->allow_traps = 0;
7842 *dst_item->trapper_hosts = '\0';
7843 }
7844 dst_item->timeout = NULL;
7845 dst_item->url = NULL;
7846 dst_item->query_fields = NULL;
7847 dst_item->status_codes = NULL;
7848 dst_item->http_proxy = NULL;
7849 dst_item->ssl_cert_file = NULL;
7850 dst_item->ssl_key_file = NULL;
7851 dst_item->ssl_key_password = NULL;
7852 dst_item->username = NULL;
7853 dst_item->password = NULL;
7854 break;
7855 case ITEM_TYPE_SCRIPT:
7856 if (NULL != (scriptitem = (ZBX_DC_SCRIPTITEM *)zbx_hashset_search(&config->scriptitems,
7857 &src_item->itemid)))
7858 {
7859 int i;
7860 struct zbx_json json;
7861
7862 zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);
7863
7864 strscpy(dst_item->timeout_orig, scriptitem->timeout);
7865 dst_item->params = zbx_strdup(NULL, scriptitem->script);
7866
7867 for (i = 0; i < scriptitem->params.values_num; i++)
7868 {
7869 zbx_dc_scriptitem_param_t *params =
7870 (zbx_dc_scriptitem_param_t*)(scriptitem->params.values[i]);
7871
7872 zbx_json_addstring(&json, params->name, params->value, ZBX_JSON_TYPE_STRING);
7873 }
7874
7875 dst_item->script_params = zbx_strdup(NULL, json.buffer);
7876 zbx_json_free(&json);
7877 }
7878 else
7879 {
7880 *dst_item->timeout_orig = '\0';
7881 dst_item->params = zbx_strdup(NULL, "");
7882 dst_item->script_params = zbx_strdup(NULL, "");
7883 }
7884
7885 dst_item->timeout = NULL;
7886 break;
7887 case ITEM_TYPE_TELNET:
7888 if (NULL != (telnetitem = (ZBX_DC_TELNETITEM *)zbx_hashset_search(&config->telnetitems, &src_item->itemid)))
7889 {
7890 strscpy(dst_item->username_orig, telnetitem->username);
7891 strscpy(dst_item->password_orig, telnetitem->password);
7892 dst_item->params = zbx_strdup(NULL, telnetitem->params);
7893 }
7894 else
7895 {
7896 *dst_item->username_orig = '\0';
7897 *dst_item->password_orig = '\0';
7898 dst_item->params = zbx_strdup(NULL, "");
7899 }
7900 dst_item->username = NULL;
7901 dst_item->password = NULL;
7902 break;
7903 case ITEM_TYPE_SIMPLE:
7904 if (NULL != (simpleitem = (ZBX_DC_SIMPLEITEM *)zbx_hashset_search(&config->simpleitems, &src_item->itemid)))
7905 {
7906 strscpy(dst_item->username_orig, simpleitem->username);
7907 strscpy(dst_item->password_orig, simpleitem->password);
7908 }
7909 else
7910 {
7911 *dst_item->username_orig = '\0';
7912 *dst_item->password_orig = '\0';
7913 }
7914 dst_item->username = NULL;
7915 dst_item->password = NULL;
7916 break;
7917 case ITEM_TYPE_JMX:
7918 if (NULL != (jmxitem = (ZBX_DC_JMXITEM *)zbx_hashset_search(&config->jmxitems, &src_item->itemid)))
7919 {
7920 strscpy(dst_item->username_orig, jmxitem->username);
7921 strscpy(dst_item->password_orig, jmxitem->password);
7922 strscpy(dst_item->jmx_endpoint_orig, jmxitem->jmx_endpoint);
7923 }
7924 else
7925 {
7926 *dst_item->username_orig = '\0';
7927 *dst_item->password_orig = '\0';
7928 *dst_item->jmx_endpoint_orig = '\0';
7929 }
7930 dst_item->username = NULL;
7931 dst_item->password = NULL;
7932 dst_item->jmx_endpoint = NULL;
7933 break;
7934 case ITEM_TYPE_CALCULATED:
7935 if (NULL != (calcitem = (ZBX_DC_CALCITEM *)zbx_hashset_search(&config->calcitems,
7936 &src_item->itemid)))
7937 {
7938 dst_item->params = zbx_strdup(NULL, calcitem->params);
7939 dst_item->formula_bin = dup_serialized_expression(calcitem->formula_bin);
7940 }
7941 else
7942 {
7943 dst_item->params = zbx_strdup(NULL, "");
7944 dst_item->formula_bin = NULL;
7945 }
7946
7947 break;
7948 default:
7949 /* nothing to do */;
7950 }
7951 }
7952
DCconfig_clean_items(DC_ITEM * items,int * errcodes,size_t num)7953 void DCconfig_clean_items(DC_ITEM *items, int *errcodes, size_t num)
7954 {
7955 size_t i;
7956
7957 for (i = 0; i < num; i++)
7958 {
7959 if (NULL != errcodes && SUCCEED != errcodes[i])
7960 continue;
7961
7962 if (ITEM_VALUE_TYPE_FLOAT == items[i].value_type || ITEM_VALUE_TYPE_UINT64 == items[i].value_type)
7963 {
7964 zbx_free(items[i].units);
7965 }
7966
7967 switch (items[i].type)
7968 {
7969 case ITEM_TYPE_HTTPAGENT:
7970 zbx_free(items[i].headers);
7971 zbx_free(items[i].posts);
7972 break;
7973 case ITEM_TYPE_SCRIPT:
7974 zbx_free(items[i].script_params);
7975 ZBX_FALLTHROUGH;
7976 case ITEM_TYPE_DB_MONITOR:
7977 case ITEM_TYPE_SSH:
7978 case ITEM_TYPE_TELNET:
7979 zbx_free(items[i].params);
7980 break;
7981 case ITEM_TYPE_CALCULATED:
7982 zbx_free(items[i].params);
7983 zbx_free(items[i].formula_bin);
7984 break;
7985 }
7986
7987 zbx_free(items[i].delay);
7988 zbx_free(items[i].error);
7989 }
7990 }
7991
DCget_function(DC_FUNCTION * dst_function,const ZBX_DC_FUNCTION * src_function)7992 static void DCget_function(DC_FUNCTION *dst_function, const ZBX_DC_FUNCTION *src_function)
7993 {
7994 size_t sz_function, sz_parameter;
7995
7996 dst_function->functionid = src_function->functionid;
7997 dst_function->triggerid = src_function->triggerid;
7998 dst_function->itemid = src_function->itemid;
7999
8000 sz_function = strlen(src_function->function) + 1;
8001 sz_parameter = strlen(src_function->parameter) + 1;
8002 dst_function->function = (char *)zbx_malloc(NULL, sz_function + sz_parameter);
8003 dst_function->parameter = dst_function->function + sz_function;
8004 memcpy(dst_function->function, src_function->function, sz_function);
8005 memcpy(dst_function->parameter, src_function->parameter, sz_parameter);
8006 }
8007
DCget_trigger(DC_TRIGGER * dst_trigger,const ZBX_DC_TRIGGER * src_trigger)8008 static void DCget_trigger(DC_TRIGGER *dst_trigger, const ZBX_DC_TRIGGER *src_trigger)
8009 {
8010 int i;
8011
8012 dst_trigger->triggerid = src_trigger->triggerid;
8013 dst_trigger->description = zbx_strdup(NULL, src_trigger->description);
8014 dst_trigger->error = zbx_strdup(NULL, src_trigger->error);
8015 dst_trigger->timespec.sec = 0;
8016 dst_trigger->timespec.ns = 0;
8017 dst_trigger->priority = src_trigger->priority;
8018 dst_trigger->type = src_trigger->type;
8019 dst_trigger->value = src_trigger->value;
8020 dst_trigger->state = src_trigger->state;
8021 dst_trigger->new_value = TRIGGER_VALUE_UNKNOWN;
8022 dst_trigger->lastchange = src_trigger->lastchange;
8023 dst_trigger->topoindex = src_trigger->topoindex;
8024 dst_trigger->status = src_trigger->status;
8025 dst_trigger->recovery_mode = src_trigger->recovery_mode;
8026 dst_trigger->correlation_mode = src_trigger->correlation_mode;
8027 dst_trigger->correlation_tag = zbx_strdup(NULL, src_trigger->correlation_tag);
8028 dst_trigger->opdata = zbx_strdup(NULL, src_trigger->opdata);
8029 dst_trigger->event_name = ('\0' != *src_trigger->event_name ? zbx_strdup(NULL, src_trigger->event_name) : NULL);
8030 dst_trigger->flags = 0;
8031 dst_trigger->new_error = NULL;
8032
8033 dst_trigger->expression = zbx_strdup(NULL, src_trigger->expression);
8034 dst_trigger->recovery_expression = zbx_strdup(NULL, src_trigger->recovery_expression);
8035
8036 dst_trigger->expression_bin = dup_serialized_expression(src_trigger->expression_bin);
8037 dst_trigger->recovery_expression_bin = dup_serialized_expression(src_trigger->recovery_expression_bin);
8038
8039 dst_trigger->eval_ctx = NULL;
8040 dst_trigger->eval_ctx_r = NULL;
8041
8042 zbx_vector_ptr_create(&dst_trigger->tags);
8043
8044 if (0 != src_trigger->tags.values_num)
8045 {
8046 zbx_vector_ptr_reserve(&dst_trigger->tags, src_trigger->tags.values_num);
8047
8048 for (i = 0; i < src_trigger->tags.values_num; i++)
8049 {
8050 const zbx_dc_trigger_tag_t *dc_trigger_tag = (const zbx_dc_trigger_tag_t *)src_trigger->tags.values[i];
8051 zbx_tag_t *tag;
8052
8053 tag = (zbx_tag_t *)zbx_malloc(NULL, sizeof(zbx_tag_t));
8054 tag->tag = zbx_strdup(NULL, dc_trigger_tag->tag);
8055 tag->value = zbx_strdup(NULL, dc_trigger_tag->value);
8056
8057 zbx_vector_ptr_append(&dst_trigger->tags, tag);
8058 }
8059 }
8060 }
8061
zbx_free_tag(zbx_tag_t * tag)8062 void zbx_free_tag(zbx_tag_t *tag)
8063 {
8064 zbx_free(tag->tag);
8065 zbx_free(tag->value);
8066 zbx_free(tag);
8067 }
8068
zbx_free_item_tag(zbx_item_tag_t * item_tag)8069 void zbx_free_item_tag(zbx_item_tag_t *item_tag)
8070 {
8071 zbx_free(item_tag->tag.tag);
8072 zbx_free(item_tag->tag.value);
8073 zbx_free(item_tag);
8074 }
8075
DCclean_trigger(DC_TRIGGER * trigger)8076 static void DCclean_trigger(DC_TRIGGER *trigger)
8077 {
8078 zbx_free(trigger->new_error);
8079 zbx_free(trigger->error);
8080 zbx_free(trigger->expression);
8081 zbx_free(trigger->recovery_expression);
8082 zbx_free(trigger->description);
8083 zbx_free(trigger->correlation_tag);
8084 zbx_free(trigger->opdata);
8085 zbx_free(trigger->event_name);
8086 zbx_free(trigger->expression_bin);
8087 zbx_free(trigger->recovery_expression_bin);
8088
8089 zbx_vector_ptr_clear_ext(&trigger->tags, (zbx_clean_func_t)zbx_free_tag);
8090 zbx_vector_ptr_destroy(&trigger->tags);
8091
8092 if (NULL != trigger->eval_ctx)
8093 {
8094 zbx_eval_clear(trigger->eval_ctx);
8095 zbx_free(trigger->eval_ctx);
8096 }
8097
8098 if (NULL != trigger->eval_ctx_r)
8099 {
8100 zbx_eval_clear(trigger->eval_ctx_r);
8101 zbx_free(trigger->eval_ctx_r);
8102 }
8103
8104 }
8105
8106 /******************************************************************************
8107 * *
8108 * Function: DCconfig_get_items_by_keys *
8109 * *
8110 * Purpose: locate item in configuration cache by host and key *
8111 * *
8112 * Parameters: items - [OUT] pointer to array of DC_ITEM structures *
8113 * keys - [IN] list of item keys with host names *
8114 * errcodes - [OUT] SUCCEED if record located and FAIL otherwise *
8115 * num - [IN] number of elements in items, keys, errcodes *
8116 * *
8117 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
8118 * *
8119 ******************************************************************************/
DCconfig_get_items_by_keys(DC_ITEM * items,zbx_host_key_t * keys,int * errcodes,size_t num)8120 void DCconfig_get_items_by_keys(DC_ITEM *items, zbx_host_key_t *keys, int *errcodes, size_t num)
8121 {
8122 size_t i;
8123 const ZBX_DC_ITEM *dc_item;
8124 const ZBX_DC_HOST *dc_host;
8125
8126 RDLOCK_CACHE;
8127
8128 for (i = 0; i < num; i++)
8129 {
8130 if (NULL == (dc_host = DCfind_host(keys[i].host)) ||
8131 NULL == (dc_item = DCfind_item(dc_host->hostid, keys[i].key)))
8132 {
8133 errcodes[i] = FAIL;
8134 continue;
8135 }
8136
8137 DCget_host(&items[i].host, dc_host, ZBX_ITEM_GET_ALL);
8138 DCget_item(&items[i], dc_item, ZBX_ITEM_GET_ALL);
8139 errcodes[i] = SUCCEED;
8140 }
8141
8142 UNLOCK_CACHE;
8143 }
8144
DCconfig_get_hostid_by_name(const char * host,zbx_uint64_t * hostid)8145 int DCconfig_get_hostid_by_name(const char *host, zbx_uint64_t *hostid)
8146 {
8147 const ZBX_DC_HOST *dc_host;
8148 int ret;
8149
8150 RDLOCK_CACHE;
8151
8152 if (NULL != (dc_host = DCfind_host(host)))
8153 {
8154 *hostid = dc_host->hostid;
8155 ret = SUCCEED;
8156 }
8157 else
8158 ret = FAIL;
8159
8160 UNLOCK_CACHE;
8161
8162 return ret;
8163 }
8164
8165 /******************************************************************************
8166 * *
8167 * Function: DCconfig_get_items_by_itemids *
8168 * *
8169 * Purpose: Get item with specified ID *
8170 * *
8171 * Parameters: items - [OUT] pointer to DC_ITEM structures *
8172 * itemids - [IN] array of item IDs *
8173 * errcodes - [OUT] SUCCEED if item found, otherwise FAIL *
8174 * num - [IN] number of elements *
8175 * *
8176 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
8177 * *
8178 ******************************************************************************/
DCconfig_get_items_by_itemids(DC_ITEM * items,const zbx_uint64_t * itemids,int * errcodes,size_t num)8179 void DCconfig_get_items_by_itemids(DC_ITEM *items, const zbx_uint64_t *itemids, int *errcodes, size_t num)
8180 {
8181 size_t i;
8182 const ZBX_DC_ITEM *dc_item;
8183 const ZBX_DC_HOST *dc_host;
8184
8185 RDLOCK_CACHE;
8186
8187 for (i = 0; i < num; i++)
8188 {
8189 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemids[i])) ||
8190 NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
8191 {
8192 errcodes[i] = FAIL;
8193 continue;
8194 }
8195
8196 DCget_host(&items[i].host, dc_host, ZBX_ITEM_GET_ALL);
8197 DCget_item(&items[i], dc_item, ZBX_ITEM_GET_ALL);
8198 errcodes[i] = SUCCEED;
8199 }
8200
8201 UNLOCK_CACHE;
8202 }
8203
DCconfig_get_items_by_itemids_partial(DC_ITEM * items,const zbx_uint64_t * itemids,int * errcodes,size_t num,unsigned int mode)8204 void DCconfig_get_items_by_itemids_partial(DC_ITEM *items, const zbx_uint64_t *itemids, int *errcodes, size_t num,
8205 unsigned int mode)
8206 {
8207 size_t i;
8208 const ZBX_DC_ITEM *dc_item;
8209 const ZBX_DC_HOST *dc_host = NULL;
8210
8211 memset(items, 0, sizeof(DC_ITEM) * (size_t)num);
8212 memset(errcodes, 0, sizeof(int) * (size_t)num);
8213
8214 RDLOCK_CACHE;
8215
8216 for (i = 0; i < num; i++)
8217 {
8218 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemids[i])))
8219 {
8220 errcodes[i] = FAIL;
8221 continue;
8222 }
8223
8224 if (NULL == dc_host || dc_host->hostid != dc_item->hostid)
8225 {
8226 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
8227 {
8228 errcodes[i] = FAIL;
8229 continue;
8230 }
8231 }
8232
8233 DCget_host(&items[i].host, dc_host, mode);
8234 DCget_item(&items[i], dc_item, mode);
8235 }
8236
8237 UNLOCK_CACHE;
8238
8239 /* avoid unnecessary allocations inside lock if there are no error or units */
8240 for (i = 0; i < num; i++)
8241 {
8242 if (FAIL == errcodes[i])
8243 continue;
8244
8245 items[i].itemid = itemids[i];
8246
8247 if (NULL == items[i].error)
8248 items[i].error = zbx_strdup(NULL, "");
8249
8250 if (ITEM_VALUE_TYPE_FLOAT == items[i].value_type || ITEM_VALUE_TYPE_UINT64 == items[i].value_type)
8251 {
8252 if (NULL == items[i].units)
8253 items[i].units = zbx_strdup(NULL, "");
8254 }
8255 }
8256 }
8257
8258 /******************************************************************************
8259 * *
8260 * Function: dc_preproc_item_init *
8261 * *
8262 * Purpose: initialize new preprocessor item from configuration cache *
8263 * *
8264 * Parameters: item - [OUT] the item to initialize *
8265 * itemid - [IN] the item identifier *
8266 * *
8267 * Return value: SUCCEED - the item was initialized successfully *
8268 * FAIL - item with the specified itemid is not cached or *
8269 * monitored *
8270 * *
8271 ******************************************************************************/
dc_preproc_item_init(zbx_preproc_item_t * item,zbx_uint64_t itemid)8272 static int dc_preproc_item_init(zbx_preproc_item_t *item, zbx_uint64_t itemid)
8273 {
8274 const ZBX_DC_ITEM *dc_item;
8275 const ZBX_DC_HOST *dc_host;
8276
8277 if (NULL == (dc_item = (const ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemid)))
8278 return FAIL;
8279
8280 if (ITEM_STATUS_ACTIVE != dc_item->status)
8281 return FAIL;
8282
8283 if (NULL == (dc_host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
8284 return FAIL;
8285
8286 if (HOST_STATUS_MONITORED != dc_host->status)
8287 return FAIL;
8288
8289 item->itemid = itemid;
8290 item->type = dc_item->type;
8291 item->value_type = dc_item->value_type;
8292
8293 item->dep_itemids = NULL;
8294 item->dep_itemids_num = 0;
8295
8296 item->preproc_ops = NULL;
8297 item->preproc_ops_num = 0;
8298 item->update_time = 0;
8299
8300 return SUCCEED;
8301 }
8302
8303 /******************************************************************************
8304 * *
8305 * Function: DCconfig_get_preprocessable_items *
8306 * *
8307 * Purpose: get preprocessable items: *
8308 * * items with preprocessing steps *
8309 * * items with dependent items *
8310 * * internal items *
8311 * *
8312 * Parameters: items - [IN/OUT] hashset with DC_ITEMs *
8313 * timestamp - [IN/OUT] timestamp of a last update *
8314 * *
8315 ******************************************************************************/
DCconfig_get_preprocessable_items(zbx_hashset_t * items,int * timestamp)8316 void DCconfig_get_preprocessable_items(zbx_hashset_t *items, int *timestamp)
8317 {
8318 const ZBX_DC_PREPROCITEM *dc_preprocitem;
8319 const ZBX_DC_MASTERITEM *dc_masteritem;
8320 const ZBX_DC_ITEM *dc_item;
8321 const zbx_dc_preproc_op_t *dc_op;
8322 zbx_preproc_item_t *item, item_local;
8323 zbx_hashset_iter_t iter;
8324 zbx_preproc_op_t *op;
8325 int i;
8326
8327 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
8328
8329 /* no changes */
8330 if (0 != *timestamp && *timestamp == config->item_sync_ts)
8331 goto out;
8332
8333 zbx_hashset_clear(items);
8334 *timestamp = config->item_sync_ts;
8335
8336 RDLOCK_CACHE;
8337
8338 zbx_hashset_iter_reset(&config->preprocitems, &iter);
8339 while (NULL != (dc_preprocitem = (const ZBX_DC_PREPROCITEM *)zbx_hashset_iter_next(&iter)))
8340 {
8341 if (FAIL == dc_preproc_item_init(&item_local, dc_preprocitem->itemid))
8342 continue;
8343
8344 item = (zbx_preproc_item_t *)zbx_hashset_insert(items, &item_local, sizeof(item_local));
8345
8346 item->preproc_ops_num = dc_preprocitem->preproc_ops.values_num;
8347 item->preproc_ops = (zbx_preproc_op_t *)zbx_malloc(NULL, sizeof(zbx_preproc_op_t) * item->preproc_ops_num);
8348 item->update_time = dc_preprocitem->update_time;
8349
8350 for (i = 0; i < dc_preprocitem->preproc_ops.values_num; i++)
8351 {
8352 dc_op = (const zbx_dc_preproc_op_t *)dc_preprocitem->preproc_ops.values[i];
8353 op = &item->preproc_ops[i];
8354 op->type = dc_op->type;
8355 op->params = zbx_strdup(NULL, dc_op->params);
8356 op->error_handler = dc_op->error_handler;
8357 op->error_handler_params = zbx_strdup(NULL, dc_op->error_handler_params);
8358 }
8359 }
8360
8361 zbx_hashset_iter_reset(&config->masteritems, &iter);
8362 while (NULL != (dc_masteritem = (const ZBX_DC_MASTERITEM *)zbx_hashset_iter_next(&iter)))
8363 {
8364 if (NULL == (item = (zbx_preproc_item_t *)zbx_hashset_search(items, &dc_masteritem->itemid)))
8365 {
8366 if (FAIL == dc_preproc_item_init(&item_local, dc_masteritem->itemid))
8367 continue;
8368
8369 item = (zbx_preproc_item_t *)zbx_hashset_insert(items, &item_local, sizeof(item_local));
8370 }
8371
8372 item->dep_itemids_num = 0;
8373 item->dep_itemids = (zbx_uint64_pair_t *)zbx_malloc(NULL, sizeof(zbx_uint64_pair_t) *
8374 dc_masteritem->dep_itemids.values_num);
8375
8376 for (i = 0; i < dc_masteritem->dep_itemids.values_num; i++)
8377 {
8378 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items,
8379 &dc_masteritem->dep_itemids.values[i].first)) ||
8380 ITEM_STATUS_ACTIVE != dc_item->status)
8381 {
8382 continue;
8383 }
8384 item->dep_itemids[item->dep_itemids_num++] = dc_masteritem->dep_itemids.values[i];
8385 }
8386 }
8387
8388 zbx_hashset_iter_reset(&config->items, &iter);
8389 while (NULL != (dc_item = (const ZBX_DC_ITEM *)zbx_hashset_iter_next(&iter)))
8390 {
8391 if (ITEM_TYPE_INTERNAL != dc_item->type)
8392 continue;
8393
8394 if (NULL == zbx_hashset_search(items, &dc_item->itemid))
8395 {
8396 if (FAIL == dc_preproc_item_init(&item_local, dc_item->itemid))
8397 continue;
8398
8399 zbx_hashset_insert(items, &item_local, sizeof(item_local));
8400 }
8401 }
8402
8403 UNLOCK_CACHE;
8404 out:
8405 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() items:%d", __func__, items->num_data);
8406 }
8407
DCconfig_get_hosts_by_itemids(DC_HOST * hosts,const zbx_uint64_t * itemids,int * errcodes,size_t num)8408 void DCconfig_get_hosts_by_itemids(DC_HOST *hosts, const zbx_uint64_t *itemids, int *errcodes, size_t num)
8409 {
8410 size_t i;
8411 const ZBX_DC_ITEM *dc_item;
8412 const ZBX_DC_HOST *dc_host;
8413
8414 RDLOCK_CACHE;
8415
8416 for (i = 0; i < num; i++)
8417 {
8418 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemids[i])) ||
8419 NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
8420 {
8421 errcodes[i] = FAIL;
8422 continue;
8423 }
8424
8425 DCget_host(&hosts[i], dc_host, ZBX_ITEM_GET_ALL);
8426 errcodes[i] = SUCCEED;
8427 }
8428
8429 UNLOCK_CACHE;
8430 }
8431
DCconfig_trigger_exists(zbx_uint64_t triggerid)8432 int DCconfig_trigger_exists(zbx_uint64_t triggerid)
8433 {
8434 int ret = SUCCEED;
8435
8436 RDLOCK_CACHE;
8437
8438 if (NULL == zbx_hashset_search(&config->triggers, &triggerid))
8439 ret = FAIL;
8440
8441 UNLOCK_CACHE;
8442
8443 return ret;
8444 }
8445
DCconfig_get_triggers_by_triggerids(DC_TRIGGER * triggers,const zbx_uint64_t * triggerids,int * errcode,size_t num)8446 void DCconfig_get_triggers_by_triggerids(DC_TRIGGER *triggers, const zbx_uint64_t *triggerids, int *errcode,
8447 size_t num)
8448 {
8449 size_t i;
8450 const ZBX_DC_TRIGGER *dc_trigger;
8451
8452 RDLOCK_CACHE;
8453
8454 for (i = 0; i < num; i++)
8455 {
8456 if (NULL == (dc_trigger = (const ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &triggerids[i])))
8457 {
8458 errcode[i] = FAIL;
8459 continue;
8460 }
8461
8462 DCget_trigger(&triggers[i], dc_trigger);
8463 errcode[i] = SUCCEED;
8464 }
8465
8466 UNLOCK_CACHE;
8467 }
8468
8469 /******************************************************************************
8470 * *
8471 * Function: DCconfig_get_functions_by_functionids *
8472 * *
8473 * Purpose: Get functions by IDs *
8474 * *
8475 * Parameters: functions - [OUT] pointer to DC_FUNCTION structures *
8476 * functionids - [IN] array of function IDs *
8477 * errcodes - [OUT] SUCCEED if item found, otherwise FAIL *
8478 * num - [IN] number of elements *
8479 * *
8480 * Author: Aleksandrs Saveljevs, Alexander Vladishev *
8481 * *
8482 ******************************************************************************/
DCconfig_get_functions_by_functionids(DC_FUNCTION * functions,zbx_uint64_t * functionids,int * errcodes,size_t num)8483 void DCconfig_get_functions_by_functionids(DC_FUNCTION *functions, zbx_uint64_t *functionids, int *errcodes,
8484 size_t num)
8485 {
8486 size_t i;
8487 const ZBX_DC_FUNCTION *dc_function;
8488
8489 RDLOCK_CACHE;
8490
8491 for (i = 0; i < num; i++)
8492 {
8493 if (NULL == (dc_function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &functionids[i])))
8494 {
8495 errcodes[i] = FAIL;
8496 continue;
8497 }
8498
8499 DCget_function(&functions[i], dc_function);
8500 errcodes[i] = SUCCEED;
8501 }
8502
8503 UNLOCK_CACHE;
8504 }
8505
8506 /******************************************************************************
8507 * *
8508 * Function: DCconfig_clean_functions *
8509 * *
8510 * Author: Alexander Vladishev *
8511 * *
8512 ******************************************************************************/
DCconfig_clean_functions(DC_FUNCTION * functions,int * errcodes,size_t num)8513 void DCconfig_clean_functions(DC_FUNCTION *functions, int *errcodes, size_t num)
8514 {
8515 size_t i;
8516
8517 for (i = 0; i < num; i++)
8518 {
8519 if (SUCCEED != errcodes[i])
8520 continue;
8521
8522 zbx_free(functions[i].function);
8523 }
8524 }
8525
DCconfig_clean_triggers(DC_TRIGGER * triggers,int * errcodes,size_t num)8526 void DCconfig_clean_triggers(DC_TRIGGER *triggers, int *errcodes, size_t num)
8527 {
8528 size_t i;
8529
8530 for (i = 0; i < num; i++)
8531 {
8532 if (SUCCEED != errcodes[i])
8533 continue;
8534
8535 DCclean_trigger(&triggers[i]);
8536 }
8537 }
8538
8539 /******************************************************************************
8540 * *
8541 * Function: DCconfig_lock_triggers_by_history_items *
8542 * *
8543 * Purpose: Lock triggers for specified items so that multiple processes do *
8544 * not process one trigger simultaneously. Otherwise, this leads to *
8545 * problems like multiple successive OK events or escalations being *
8546 * started and not cancelled, because they are not seen in parallel *
8547 * transactions. *
8548 * *
8549 * Parameters: history_items - [IN/OUT] list of history items history syncer *
8550 * wishes to take for processing; on *
8551 * output, the item locked field is set *
8552 * to 0 if the corresponding item cannot *
8553 * be taken *
8554 * triggerids - [OUT] list of trigger IDs that this function has *
8555 * locked for processing; unlock those using *
8556 * DCconfig_unlock_triggers() function *
8557 * *
8558 * Author: Aleksandrs Saveljevs *
8559 * *
8560 * Comments: This does not solve the problem fully (e.g., ZBX-7484). There is *
8561 * a significant time period between the place where we lock the *
8562 * triggers and the place where we process them. So it could happen *
8563 * that a configuration cache update happens after we have locked *
8564 * the triggers and it turns out that in the updated configuration *
8565 * there is a new trigger for two of the items that two different *
8566 * history syncers have taken for processing. In that situation, *
8567 * the problem we are solving here might still happen. However, *
8568 * locking triggers makes this problem much less likely and only in *
8569 * case configuration changes. On a stable configuration, it should *
8570 * work without any problems. *
8571 * *
8572 * Return value: the number of items available for processing (unlocked). *
8573 * *
8574 ******************************************************************************/
DCconfig_lock_triggers_by_history_items(zbx_vector_ptr_t * history_items,zbx_vector_uint64_t * triggerids)8575 int DCconfig_lock_triggers_by_history_items(zbx_vector_ptr_t *history_items, zbx_vector_uint64_t *triggerids)
8576 {
8577 int i, j, locked_num = 0;
8578 const ZBX_DC_ITEM *dc_item;
8579 ZBX_DC_TRIGGER *dc_trigger;
8580 zbx_hc_item_t *history_item;
8581
8582 WRLOCK_CACHE;
8583
8584 for (i = 0; i < history_items->values_num; i++)
8585 {
8586 history_item = (zbx_hc_item_t *)history_items->values[i];
8587
8588 if (0 != (ZBX_DC_FLAG_NOVALUE & history_item->tail->flags))
8589 continue;
8590
8591 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &history_item->itemid)))
8592 continue;
8593
8594 if (NULL == dc_item->triggers)
8595 continue;
8596
8597 for (j = 0; NULL != (dc_trigger = dc_item->triggers[j]); j++)
8598 {
8599 if (TRIGGER_STATUS_ENABLED != dc_trigger->status)
8600 continue;
8601
8602 if (1 == dc_trigger->locked)
8603 {
8604 locked_num++;
8605 history_item->status = ZBX_HC_ITEM_STATUS_BUSY;
8606 goto next;
8607 }
8608 }
8609
8610 for (j = 0; NULL != (dc_trigger = dc_item->triggers[j]); j++)
8611 {
8612 if (TRIGGER_STATUS_ENABLED != dc_trigger->status)
8613 continue;
8614
8615 dc_trigger->locked = 1;
8616 zbx_vector_uint64_append(triggerids, dc_trigger->triggerid);
8617 }
8618 next:;
8619 }
8620
8621 UNLOCK_CACHE;
8622
8623 return history_items->values_num - locked_num;
8624 }
8625
8626 /******************************************************************************
8627 * *
8628 * Function: DCconfig_lock_triggers_by_triggerids *
8629 * *
8630 * Purpose: Lock triggers so that multiple processes do not process one *
8631 * trigger simultaneously. *
8632 * *
8633 * Parameters: triggerids_in - [IN] ids of triggers to lock *
8634 * triggerids_out - [OUT] ids of locked triggers *
8635 * *
8636 ******************************************************************************/
DCconfig_lock_triggers_by_triggerids(zbx_vector_uint64_t * triggerids_in,zbx_vector_uint64_t * triggerids_out)8637 void DCconfig_lock_triggers_by_triggerids(zbx_vector_uint64_t *triggerids_in, zbx_vector_uint64_t *triggerids_out)
8638 {
8639 int i;
8640 ZBX_DC_TRIGGER *dc_trigger;
8641
8642 if (0 == triggerids_in->values_num)
8643 return;
8644
8645 WRLOCK_CACHE;
8646
8647 for (i = 0; i < triggerids_in->values_num; i++)
8648 {
8649 if (NULL == (dc_trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &triggerids_in->values[i])))
8650 continue;
8651
8652 if (1 == dc_trigger->locked)
8653 continue;
8654
8655 dc_trigger->locked = 1;
8656 zbx_vector_uint64_append(triggerids_out, dc_trigger->triggerid);
8657 }
8658
8659 UNLOCK_CACHE;
8660 }
8661
8662 /******************************************************************************
8663 * *
8664 * Function: DCconfig_unlock_triggers *
8665 * *
8666 * Author: Aleksandrs Saveljevs *
8667 * *
8668 ******************************************************************************/
DCconfig_unlock_triggers(const zbx_vector_uint64_t * triggerids)8669 void DCconfig_unlock_triggers(const zbx_vector_uint64_t *triggerids)
8670 {
8671 int i;
8672 ZBX_DC_TRIGGER *dc_trigger;
8673
8674 /* no other process can modify already locked triggers without write lock */
8675 RDLOCK_CACHE;
8676
8677 for (i = 0; i < triggerids->values_num; i++)
8678 {
8679 if (NULL == (dc_trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &triggerids->values[i])))
8680 continue;
8681
8682 dc_trigger->locked = 0;
8683 }
8684
8685 UNLOCK_CACHE;
8686 }
8687
8688 /******************************************************************************
8689 * *
8690 * Function: DCconfig_unlock_all_triggers *
8691 * *
8692 * Purpose: Unlocks all locked triggers before doing full history sync at *
8693 * program exit *
8694 * *
8695 ******************************************************************************/
DCconfig_unlock_all_triggers(void)8696 void DCconfig_unlock_all_triggers(void)
8697 {
8698 ZBX_DC_TRIGGER *dc_trigger;
8699 zbx_hashset_iter_t iter;
8700
8701 WRLOCK_CACHE;
8702
8703 zbx_hashset_iter_reset(&config->triggers, &iter);
8704
8705 while (NULL != (dc_trigger = (ZBX_DC_TRIGGER *)zbx_hashset_iter_next(&iter)))
8706 dc_trigger->locked = 0;
8707
8708 UNLOCK_CACHE;
8709 }
8710
8711 /******************************************************************************
8712 * *
8713 * Function: DCconfig_get_triggers_by_itemids *
8714 * *
8715 * Purpose: get enabled triggers for specified items *
8716 * *
8717 * Author: Aleksandrs Saveljevs *
8718 * *
8719 ******************************************************************************/
DCconfig_get_triggers_by_itemids(zbx_hashset_t * trigger_info,zbx_vector_ptr_t * trigger_order,const zbx_uint64_t * itemids,const zbx_timespec_t * timespecs,int itemids_num)8720 void DCconfig_get_triggers_by_itemids(zbx_hashset_t *trigger_info, zbx_vector_ptr_t *trigger_order,
8721 const zbx_uint64_t *itemids, const zbx_timespec_t *timespecs, int itemids_num)
8722 {
8723 int i, j, found;
8724 const ZBX_DC_ITEM *dc_item;
8725 const ZBX_DC_TRIGGER *dc_trigger;
8726 DC_TRIGGER *trigger;
8727
8728 RDLOCK_CACHE;
8729
8730 for (i = 0; i < itemids_num; i++)
8731 {
8732 /* skip items which are not in configuration cache and items without triggers */
8733
8734 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemids[i])) || NULL == dc_item->triggers)
8735 continue;
8736
8737 /* process all triggers for the specified item */
8738
8739 for (j = 0; NULL != (dc_trigger = dc_item->triggers[j]); j++)
8740 {
8741 if (TRIGGER_STATUS_ENABLED != dc_trigger->status)
8742 continue;
8743
8744 /* find trigger by id or create a new record in hashset if not found */
8745 trigger = (DC_TRIGGER *)DCfind_id(trigger_info, dc_trigger->triggerid, sizeof(DC_TRIGGER), &found);
8746
8747 if (0 == found)
8748 {
8749 DCget_trigger(trigger, dc_trigger);
8750 zbx_vector_ptr_append(trigger_order, trigger);
8751 }
8752
8753 /* copy latest change timestamp */
8754
8755 if (trigger->timespec.sec < timespecs[i].sec ||
8756 (trigger->timespec.sec == timespecs[i].sec &&
8757 trigger->timespec.ns < timespecs[i].ns))
8758 {
8759 /* DCconfig_get_triggers_by_itemids() function is called during trigger processing */
8760 /* when syncing history cache. A trigger cannot be processed by two syncers at the */
8761 /* same time, so its safe to update trigger timespec within read lock. */
8762 trigger->timespec = timespecs[i];
8763 }
8764 }
8765 }
8766
8767 UNLOCK_CACHE;
8768 }
8769
8770 /******************************************************************************
8771 * *
8772 * Function: DCconfig_find_active_time_function *
8773 * *
8774 * Purpose: check if the expression contains time based functions *
8775 * *
8776 * Parameters: expression - [IN] the original expression *
8777 * data - [IN] the parsed and serialized expression *
8778 * trigger_timer - [IN] the trigger time function flags *
8779 * *
8780 ******************************************************************************/
DCconfig_find_active_time_function(const char * expression,const unsigned char * data,unsigned char trigger_timer)8781 static int DCconfig_find_active_time_function(const char *expression, const unsigned char *data,
8782 unsigned char trigger_timer)
8783 {
8784 int i, ret = SUCCEED;
8785 const ZBX_DC_FUNCTION *dc_function;
8786 const ZBX_DC_HOST *dc_host;
8787 const ZBX_DC_ITEM *dc_item;
8788 zbx_vector_uint64_t functionids;
8789
8790 zbx_vector_uint64_create(&functionids);
8791 zbx_get_serialized_expression_functionids(expression, data, &functionids);
8792
8793 for (i = 0; i < functionids.values_num; i++)
8794 {
8795 if (NULL == (dc_function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions,
8796 &functionids.values[i])))
8797 {
8798 continue;
8799 }
8800
8801 if (ZBX_TRIGGER_TIMER_DEFAULT != trigger_timer || ZBX_FUNCTION_TYPE_TRENDS == dc_function->type ||
8802 ZBX_FUNCTION_TYPE_TIMER == dc_function->type)
8803 {
8804 if (NULL == (dc_item = zbx_hashset_search(&config->items, &dc_function->itemid)))
8805 continue;
8806
8807 if (NULL == (dc_host = zbx_hashset_search(&config->hosts, &dc_item->hostid)))
8808 continue;
8809
8810 if (SUCCEED != DCin_maintenance_without_data_collection(dc_host, dc_item))
8811 goto out;
8812 }
8813 }
8814
8815 ret = (ZBX_TRIGGER_TIMER_DEFAULT != trigger_timer ? SUCCEED : FAIL);
8816 out:
8817 zbx_vector_uint64_destroy(&functionids);
8818
8819 return ret;
8820 }
8821
8822 /******************************************************************************
8823 * *
8824 * Function: zbx_dc_get_triggers_by_timers *
8825 * *
8826 * Purpose: gets timer triggers from cache *
8827 * *
8828 * Parameters: trigger_info - [IN/OUT] triggers *
8829 * trigger_order - [IN/OUT] triggers in processing order *
8830 * timers - [IN] timers of triggers to retrieve *
8831 * *
8832 ******************************************************************************/
zbx_dc_get_triggers_by_timers(zbx_hashset_t * trigger_info,zbx_vector_ptr_t * trigger_order,const zbx_vector_ptr_t * timers)8833 void zbx_dc_get_triggers_by_timers(zbx_hashset_t *trigger_info, zbx_vector_ptr_t *trigger_order,
8834 const zbx_vector_ptr_t *timers)
8835 {
8836 int i;
8837 ZBX_DC_TRIGGER *dc_trigger;
8838
8839 RDLOCK_CACHE;
8840
8841 for (i = 0; i < timers->values_num; i++)
8842 {
8843 zbx_trigger_timer_t *timer = (zbx_trigger_timer_t *)timers->values[i];
8844
8845 /* skip timers of 'busy' (being processed) triggers */
8846 if (0 == timer->lock)
8847 continue;
8848
8849 if (NULL != (dc_trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &timer->triggerid)))
8850 {
8851 DC_TRIGGER *trigger, trigger_local;
8852 unsigned char flags;
8853
8854 if (SUCCEED == DCconfig_find_active_time_function(dc_trigger->expression,
8855 dc_trigger->expression_bin, dc_trigger->timer & ZBX_TRIGGER_TIMER_EXPRESSION))
8856 {
8857 flags = ZBX_DC_TRIGGER_PROBLEM_EXPRESSION;
8858 }
8859 else
8860 {
8861 if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION != dc_trigger->recovery_mode)
8862 continue;
8863
8864 if (TRIGGER_VALUE_PROBLEM != dc_trigger->value)
8865 continue;
8866
8867 if (SUCCEED != DCconfig_find_active_time_function(dc_trigger->recovery_expression,
8868 dc_trigger->recovery_expression_bin,
8869 dc_trigger->timer & ZBX_TRIGGER_TIMER_RECOVERY_EXPRESSION))
8870 {
8871 continue;
8872 }
8873
8874 flags = 0;
8875 }
8876
8877 trigger_local.triggerid = dc_trigger->triggerid;
8878 trigger = (DC_TRIGGER *)zbx_hashset_insert(trigger_info, &trigger_local, sizeof(trigger_local));
8879 DCget_trigger(trigger, dc_trigger);
8880
8881 trigger->timespec = timer->eval_ts;
8882 trigger->flags = flags;
8883
8884 zbx_vector_ptr_append(trigger_order, trigger);
8885 }
8886 }
8887
8888 UNLOCK_CACHE;
8889 }
8890
8891 /******************************************************************************
8892 * *
8893 * Function: trigger_timer_validate *
8894 * *
8895 * Purpose: validate trigger timer *
8896 * *
8897 * Parameters: timer - [IN] trigger timer *
8898 * dc_trigger - [OUT] the trigger data *
8899 * *
8900 * Return value: SUCCEED - the timer is valid *
8901 * FAIL - otherwise *
8902 * *
8903 ******************************************************************************/
trigger_timer_validate(zbx_trigger_timer_t * timer,ZBX_DC_TRIGGER ** dc_trigger)8904 static int trigger_timer_validate(zbx_trigger_timer_t *timer, ZBX_DC_TRIGGER **dc_trigger)
8905 {
8906 ZBX_DC_FUNCTION *dc_function;
8907
8908 *dc_trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &timer->triggerid);
8909
8910 if (0 != (timer->type & ZBX_TRIGGER_TIMER_FUNCTION))
8911 {
8912 if (NULL == (dc_function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &timer->objectid)))
8913 return FAIL;
8914
8915 if (dc_function->revision > timer->revision ||
8916 NULL == *dc_trigger ||
8917 TRIGGER_STATUS_ENABLED != (*dc_trigger)->status ||
8918 TRIGGER_FUNCTIONAL_TRUE != (*dc_trigger)->functional)
8919 {
8920 if (dc_function->timer_revision == timer->revision)
8921 dc_function->timer_revision = 0;
8922 return FAIL;
8923 }
8924 }
8925 else
8926 {
8927 if (NULL == (*dc_trigger))
8928 return FAIL;
8929
8930 if ((*dc_trigger)->revision > timer->revision ||
8931 TRIGGER_STATUS_ENABLED != (*dc_trigger)->status ||
8932 TRIGGER_FUNCTIONAL_TRUE != (*dc_trigger)->functional)
8933 {
8934 if ((*dc_trigger)->timer_revision == timer->revision)
8935 (*dc_trigger)->timer_revision = 0;
8936 return FAIL;
8937 }
8938 }
8939
8940 return SUCCEED;
8941 }
8942
8943 /******************************************************************************
8944 * *
8945 * Function: zbx_dc_get_trigger_timers *
8946 * *
8947 * Purpose: gets timers from trigger queue *
8948 * *
8949 * Parameters: timers - [OUT] the timer triggers that must be processed *
8950 * now - [IN] current time *
8951 * soft_limit - [IN] the number of timers to return unless timers *
8952 * of the same trigger are split over multiple *
8953 * batches. *
8954 * *
8955 * hard_limit - [IN] the maximum number of timers to return *
8956 * *
8957 * Comments: This function locks corresponding triggers in configuration *
8958 * cache. *
8959 * If the returned timer has lock field set, then trigger is *
8960 * already being processed and should not be recalculated. *
8961 * *
8962 ******************************************************************************/
zbx_dc_get_trigger_timers(zbx_vector_ptr_t * timers,int now,int soft_limit,int hard_limit)8963 void zbx_dc_get_trigger_timers(zbx_vector_ptr_t *timers, int now, int soft_limit, int hard_limit)
8964 {
8965 zbx_trigger_timer_t *first_timer = NULL, *timer;
8966 int found = 0;
8967 zbx_binary_heap_elem_t *elem;
8968
8969 RDLOCK_CACHE;
8970
8971 if (SUCCEED != zbx_binary_heap_empty(&config->trigger_queue))
8972 {
8973 elem = zbx_binary_heap_find_min(&config->trigger_queue);
8974 timer = (zbx_trigger_timer_t *)elem->data;
8975
8976 if (timer->exec_ts.sec <= now)
8977 found = 1;
8978 }
8979
8980 UNLOCK_CACHE;
8981
8982 if (0 == found)
8983 return;
8984
8985 WRLOCK_CACHE;
8986
8987 while (SUCCEED != zbx_binary_heap_empty(&config->trigger_queue) && timers->values_num < hard_limit)
8988 {
8989 ZBX_DC_TRIGGER *dc_trigger;
8990
8991 elem = zbx_binary_heap_find_min(&config->trigger_queue);
8992 timer = (zbx_trigger_timer_t *)elem->data;
8993
8994 if (timer->exec_ts.sec > now)
8995 break;
8996
8997 /* first_timer stores the first timer from a list of timers of the same trigger with the same */
8998 /* evaluation timestamp. Reset first_timer if the conditions do not apply. */
8999 if (NULL != first_timer && (timer->triggerid != first_timer->triggerid ||
9000 0 != zbx_timespec_compare(&timer->eval_ts, &first_timer->eval_ts)))
9001 {
9002 first_timer = NULL;
9003 }
9004
9005 /* use soft limit to avoid (mostly) splitting multiple functions of the same trigger */
9006 /* over consequent batches */
9007 if (timers->values_num >= soft_limit && NULL == first_timer)
9008 break;
9009
9010 zbx_binary_heap_remove_min(&config->trigger_queue);
9011
9012 if (SUCCEED != trigger_timer_validate(timer, &dc_trigger))
9013 {
9014 dc_trigger_timer_free(timer);
9015 continue;
9016 }
9017
9018 zbx_vector_ptr_append(timers, timer);
9019
9020 /* Trigger expression must be calculated using function evaluation time. If a trigger is locked */
9021 /* keep rescheduling its timer until trigger is unlocked and can be calculated using the required */
9022 /* evaluation time. However there are exceptions when evaluation time of a locked trigger is */
9023 /* acceptable to evaluate other functions: */
9024 /* 1) time functions uses current time, so trigger evaluation time does not affect their results */
9025 /* 2) trend function of the same trigger with the same evaluation timestamp is being */
9026 /* evaluated by the same process */
9027 if (0 == dc_trigger->locked || ZBX_TRIGGER_TIMER_FUNCTION_TREND != timer->type ||
9028 (NULL != first_timer && 1 == first_timer->lock))
9029 {
9030 /* resetting execution timer will cause a new execution time to be set */
9031 /* when timer is put back into queue */
9032 timer->exec_ts.sec = 0;
9033 }
9034
9035 /* remember if the timer locked trigger, so it would unlock during rescheduling */
9036 if (0 == dc_trigger->locked)
9037 dc_trigger->locked = timer->lock = 1;
9038
9039 if (NULL == first_timer)
9040 first_timer = timer;
9041 }
9042
9043 UNLOCK_CACHE;
9044 }
9045
9046 /******************************************************************************
9047 * *
9048 * Function: dc_reschedule_trigger_timers *
9049 * *
9050 * Purpose: reschedule trigger timers *
9051 * *
9052 * Comments: Triggers are unlocked by DCconfig_unlock_triggers() *
9053 * *
9054 ******************************************************************************/
dc_reschedule_trigger_timers(zbx_vector_ptr_t * timers)9055 static void dc_reschedule_trigger_timers(zbx_vector_ptr_t *timers)
9056 {
9057 int i;
9058
9059 for (i = 0; i < timers->values_num; i++)
9060 {
9061 zbx_trigger_timer_t *timer = (zbx_trigger_timer_t *)timers->values[i];
9062
9063 timer->lock = 0;
9064
9065 /* schedule calculation error can result in 0 execution time */
9066 if (0 == timer->exec_ts.sec)
9067 {
9068 if (0 != (timer->type & ZBX_TRIGGER_TIMER_FUNCTION))
9069 {
9070 ZBX_DC_FUNCTION *function;
9071
9072 if (NULL != (function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions,
9073 &timer->objectid)) && function->timer_revision == timer->revision)
9074 {
9075 function->timer_revision = 0;
9076 }
9077 }
9078 else if (ZBX_TRIGGER_TIMER_TRIGGER == timer->type)
9079 {
9080 ZBX_DC_TRIGGER *trigger;
9081
9082 if (NULL != (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers,
9083 &timer->objectid)) && trigger->timer_revision == timer->revision)
9084 {
9085 trigger->timer_revision = 0;
9086 }
9087 }
9088 dc_trigger_timer_free(timer);
9089 }
9090 else
9091 dc_schedule_trigger_timer(timer, &timer->eval_ts, &timer->exec_ts);
9092 }
9093 }
9094
9095 /******************************************************************************
9096 * *
9097 * Function: zbx_dc_reschedule_trigger_timers *
9098 * *
9099 * Purpose: reschedule trigger timers while locking configuration cache *
9100 * *
9101 * Comments: Triggers are unlocked by DCconfig_unlock_triggers() *
9102 * *
9103 ******************************************************************************/
zbx_dc_reschedule_trigger_timers(zbx_vector_ptr_t * timers,int now)9104 void zbx_dc_reschedule_trigger_timers(zbx_vector_ptr_t *timers, int now)
9105 {
9106 int i;
9107
9108 /* calculate new execution/evaluation time for the evaluated triggers */
9109 /* (timers with reseted execution time) */
9110 for (i = 0; i < timers->values_num; i++)
9111 {
9112 zbx_trigger_timer_t *timer = (zbx_trigger_timer_t *)timers->values[i];
9113
9114 if (0 == timer->exec_ts.sec)
9115 {
9116 if (0 != (timer->exec_ts.sec = dc_function_calculate_nextcheck(timer, now, timer->triggerid)))
9117 timer->eval_ts = timer->exec_ts;
9118 }
9119 }
9120
9121 WRLOCK_CACHE;
9122 dc_reschedule_trigger_timers(timers);
9123 UNLOCK_CACHE;
9124 }
9125
9126 /******************************************************************************
9127 * *
9128 * Function: zbx_dc_get_timer_queue *
9129 * *
9130 * Purpose: clears timer trigger queue *
9131 * *
9132 ******************************************************************************/
zbx_dc_clear_timer_queue(zbx_vector_ptr_t * timers)9133 void zbx_dc_clear_timer_queue(zbx_vector_ptr_t *timers)
9134 {
9135 ZBX_DC_FUNCTION *function;
9136 int i;
9137
9138 zbx_vector_ptr_reserve(timers, config->trigger_queue.elems_num);
9139
9140 WRLOCK_CACHE;
9141
9142 for (i = 0; i < config->trigger_queue.elems_num; i++)
9143 {
9144 zbx_trigger_timer_t *timer = (zbx_trigger_timer_t *)config->trigger_queue.elems[i].data;
9145
9146 if (ZBX_TRIGGER_TIMER_FUNCTION_TREND == timer->type &&
9147 NULL != (function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions,
9148 &timer->objectid)) &&
9149 function->timer_revision == timer->revision)
9150 {
9151 zbx_vector_ptr_append(timers, timer);
9152 }
9153 else
9154 dc_trigger_timer_free(timer);
9155 }
9156
9157 zbx_binary_heap_clear(&config->trigger_queue);
9158
9159 UNLOCK_CACHE;
9160 }
9161
9162 /******************************************************************************
9163 * *
9164 * Function: zbx_dc_free_timers *
9165 * *
9166 ******************************************************************************/
zbx_dc_free_timers(zbx_vector_ptr_t * timers)9167 void zbx_dc_free_timers(zbx_vector_ptr_t *timers)
9168 {
9169 int i;
9170
9171 WRLOCK_CACHE;
9172
9173 for (i = 0; i < timers->values_num; i++)
9174 dc_trigger_timer_free(timers->values[i]);
9175
9176 UNLOCK_CACHE;
9177 }
9178
DCfree_triggers(zbx_vector_ptr_t * triggers)9179 void DCfree_triggers(zbx_vector_ptr_t *triggers)
9180 {
9181 int i;
9182
9183 for (i = 0; i < triggers->values_num; i++)
9184 DCclean_trigger((DC_TRIGGER *)triggers->values[i]);
9185
9186 zbx_vector_ptr_clear(triggers);
9187 }
9188
DCconfig_update_interface_snmp_stats(zbx_uint64_t interfaceid,int max_snmp_succeed,int min_snmp_fail)9189 void DCconfig_update_interface_snmp_stats(zbx_uint64_t interfaceid, int max_snmp_succeed, int min_snmp_fail)
9190 {
9191 ZBX_DC_SNMPINTERFACE *dc_snmp;
9192
9193 WRLOCK_CACHE;
9194
9195 if (NULL != (dc_snmp = (ZBX_DC_SNMPINTERFACE *)zbx_hashset_search(&config->interfaces_snmp, &interfaceid)) &&
9196 SNMP_BULK_ENABLED == dc_snmp->bulk)
9197 {
9198 if (dc_snmp->max_succeed < max_snmp_succeed)
9199 dc_snmp->max_succeed = (unsigned char)max_snmp_succeed;
9200
9201 if (dc_snmp->min_fail > min_snmp_fail)
9202 dc_snmp->min_fail = (unsigned char)min_snmp_fail;
9203 }
9204
9205 UNLOCK_CACHE;
9206 }
9207
DCconfig_get_suggested_snmp_vars_nolock(zbx_uint64_t interfaceid,int * bulk)9208 static int DCconfig_get_suggested_snmp_vars_nolock(zbx_uint64_t interfaceid, int *bulk)
9209 {
9210 int num;
9211 const ZBX_DC_SNMPINTERFACE *dc_snmp;
9212
9213 dc_snmp = (const ZBX_DC_SNMPINTERFACE *)zbx_hashset_search(&config->interfaces_snmp, &interfaceid);
9214
9215 if (NULL != bulk)
9216 *bulk = (NULL == dc_snmp ? SNMP_BULK_DISABLED : dc_snmp->bulk);
9217
9218 if (NULL == dc_snmp || SNMP_BULK_ENABLED != dc_snmp->bulk)
9219 return 1;
9220
9221 /* The general strategy is to multiply request size by 3/2 in order to approach the limit faster. */
9222 /* However, once we are over the limit, we change the strategy to increasing the value by 1. This */
9223 /* is deemed better than going backwards from the error because less timeouts are going to occur. */
9224
9225 if (1 >= dc_snmp->max_succeed || MAX_SNMP_ITEMS + 1 != dc_snmp->min_fail)
9226 num = dc_snmp->max_succeed + 1;
9227 else
9228 num = dc_snmp->max_succeed * 3 / 2;
9229
9230 if (num < dc_snmp->min_fail)
9231 return num;
9232
9233 /* If we have already found the optimal number of variables to query, we wish to base our suggestion on that */
9234 /* number. If we occasionally get a timeout in this area, it can mean two things: either the device's actual */
9235 /* limit is a bit lower than that (it can process requests above it, but only sometimes) or a UDP packet in */
9236 /* one of the directions was lost. In order to account for the former, we allow ourselves to lower the count */
9237 /* of variables, but only up to two times. Otherwise, performance will gradually degrade due to the latter. */
9238
9239 return MAX(dc_snmp->max_succeed - 2, dc_snmp->min_fail - 1);
9240 }
9241
DCconfig_get_suggested_snmp_vars(zbx_uint64_t interfaceid,int * bulk)9242 int DCconfig_get_suggested_snmp_vars(zbx_uint64_t interfaceid, int *bulk)
9243 {
9244 int ret;
9245
9246 RDLOCK_CACHE;
9247
9248 ret = DCconfig_get_suggested_snmp_vars_nolock(interfaceid, bulk);
9249
9250 UNLOCK_CACHE;
9251
9252 return ret;
9253 }
9254
dc_get_interface_by_type(DC_INTERFACE * interface,zbx_uint64_t hostid,unsigned char type)9255 static int dc_get_interface_by_type(DC_INTERFACE *interface, zbx_uint64_t hostid, unsigned char type)
9256 {
9257 int res = FAIL;
9258 const ZBX_DC_INTERFACE *dc_interface;
9259 const ZBX_DC_INTERFACE_HT *interface_ht;
9260 ZBX_DC_INTERFACE_HT interface_ht_local;
9261
9262 interface_ht_local.hostid = hostid;
9263 interface_ht_local.type = type;
9264
9265 if (NULL != (interface_ht = (const ZBX_DC_INTERFACE_HT *)zbx_hashset_search(&config->interfaces_ht, &interface_ht_local)))
9266 {
9267 dc_interface = interface_ht->interface_ptr;
9268 DCget_interface(interface, dc_interface);
9269 res = SUCCEED;
9270 }
9271
9272 return res;
9273 }
9274
9275 /******************************************************************************
9276 * *
9277 * Function: DCconfig_get_interface_by_type *
9278 * *
9279 * Purpose: Locate main interface of specified type in configuration cache *
9280 * *
9281 * Parameters: interface - [OUT] pointer to DC_INTERFACE structure *
9282 * hostid - [IN] host ID *
9283 * type - [IN] interface type *
9284 * *
9285 * Return value: SUCCEED if record located and FAIL otherwise *
9286 * *
9287 ******************************************************************************/
DCconfig_get_interface_by_type(DC_INTERFACE * interface,zbx_uint64_t hostid,unsigned char type)9288 int DCconfig_get_interface_by_type(DC_INTERFACE *interface, zbx_uint64_t hostid, unsigned char type)
9289 {
9290 int res;
9291
9292 RDLOCK_CACHE;
9293
9294 res = dc_get_interface_by_type(interface, hostid, type);
9295
9296 UNLOCK_CACHE;
9297
9298 return res;
9299 }
9300
9301 /******************************************************************************
9302 * *
9303 * Function: DCconfig_get_interface *
9304 * *
9305 * Purpose: Locate interface in configuration cache *
9306 * *
9307 * Parameters: interface - [OUT] pointer to DC_INTERFACE structure *
9308 * hostid - [IN] host ID *
9309 * itemid - [IN] item ID *
9310 * *
9311 * Return value: SUCCEED if record located and FAIL otherwise *
9312 * *
9313 ******************************************************************************/
DCconfig_get_interface(DC_INTERFACE * interface,zbx_uint64_t hostid,zbx_uint64_t itemid)9314 int DCconfig_get_interface(DC_INTERFACE *interface, zbx_uint64_t hostid, zbx_uint64_t itemid)
9315 {
9316 int res = FAIL, i;
9317 const ZBX_DC_ITEM *dc_item;
9318 const ZBX_DC_INTERFACE *dc_interface;
9319
9320 RDLOCK_CACHE;
9321
9322 if (0 != itemid)
9323 {
9324 if (NULL == (dc_item = (const ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemid)))
9325 goto unlock;
9326
9327 if (0 != dc_item->interfaceid)
9328 {
9329 if (NULL == (dc_interface = (const ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces,
9330 &dc_item->interfaceid)))
9331 {
9332 goto unlock;
9333 }
9334
9335 DCget_interface(interface, dc_interface);
9336 res = SUCCEED;
9337 goto unlock;
9338 }
9339
9340 hostid = dc_item->hostid;
9341 }
9342
9343 if (0 == hostid)
9344 goto unlock;
9345
9346 for (i = 0; i < (int)ARRSIZE(INTERFACE_TYPE_PRIORITY); i++)
9347 {
9348 if (SUCCEED == (res = dc_get_interface_by_type(interface, hostid, INTERFACE_TYPE_PRIORITY[i])))
9349 break;
9350 }
9351
9352 unlock:
9353 UNLOCK_CACHE;
9354
9355 return res;
9356 }
9357
9358 /******************************************************************************
9359 * *
9360 * Function: dc_config_get_queue_nextcheck *
9361 * *
9362 * Purpose: Get nextcheck for selected queue *
9363 * *
9364 * Parameters: queue - [IN] the queue *
9365 * *
9366 * Return value: nextcheck or FAIL if no items for the specified queue *
9367 * *
9368 ******************************************************************************/
dc_config_get_queue_nextcheck(zbx_binary_heap_t * queue)9369 static int dc_config_get_queue_nextcheck(zbx_binary_heap_t *queue)
9370 {
9371 int nextcheck;
9372 const zbx_binary_heap_elem_t *min;
9373 const ZBX_DC_ITEM *dc_item;
9374
9375 if (FAIL == zbx_binary_heap_empty(queue))
9376 {
9377 min = zbx_binary_heap_find_min(queue);
9378 dc_item = (const ZBX_DC_ITEM *)min->data;
9379
9380 nextcheck = dc_item->nextcheck;
9381 }
9382 else
9383 nextcheck = FAIL;
9384
9385 return nextcheck;
9386 }
9387
9388 /******************************************************************************
9389 * *
9390 * Function: DCconfig_get_poller_nextcheck *
9391 * *
9392 * Purpose: Get nextcheck for selected poller *
9393 * *
9394 * Parameters: poller_type - [IN] poller type (ZBX_POLLER_TYPE_...) *
9395 * *
9396 * Return value: nextcheck or FAIL if no items for selected poller *
9397 * *
9398 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
9399 * *
9400 ******************************************************************************/
DCconfig_get_poller_nextcheck(unsigned char poller_type)9401 int DCconfig_get_poller_nextcheck(unsigned char poller_type)
9402 {
9403 int nextcheck;
9404 zbx_binary_heap_t *queue;
9405
9406 zabbix_log(LOG_LEVEL_DEBUG, "In %s() poller_type:%d", __func__, (int)poller_type);
9407
9408 queue = &config->queues[poller_type];
9409
9410 RDLOCK_CACHE;
9411
9412 nextcheck = dc_config_get_queue_nextcheck(queue);
9413
9414 UNLOCK_CACHE;
9415
9416 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __func__, nextcheck);
9417
9418 return nextcheck;
9419 }
9420
dc_requeue_item(ZBX_DC_ITEM * dc_item,const ZBX_DC_HOST * dc_host,const ZBX_DC_INTERFACE * dc_interface,int flags,int lastclock)9421 static void dc_requeue_item(ZBX_DC_ITEM *dc_item, const ZBX_DC_HOST *dc_host, const ZBX_DC_INTERFACE *dc_interface,
9422 int flags, int lastclock)
9423 {
9424 unsigned char old_poller_type;
9425 int old_nextcheck;
9426
9427 old_nextcheck = dc_item->nextcheck;
9428 DCitem_nextcheck_update(dc_item, dc_interface, flags, lastclock, NULL);
9429
9430 old_poller_type = dc_item->poller_type;
9431 DCitem_poller_type_update(dc_item, dc_host, flags);
9432
9433 DCupdate_item_queue(dc_item, old_poller_type, old_nextcheck);
9434 }
9435
9436 /******************************************************************************
9437 * *
9438 * Function: dc_requeue_item_at *
9439 * *
9440 * Purpose: requeues items at the specified time *
9441 * *
9442 * Parameters: dc_item - [IN] the item to reque *
9443 * dc_host - [IN] item's host *
9444 * nextcheck - [IN] the scheduled time *
9445 * *
9446 ******************************************************************************/
dc_requeue_item_at(ZBX_DC_ITEM * dc_item,ZBX_DC_HOST * dc_host,int nextcheck)9447 static void dc_requeue_item_at(ZBX_DC_ITEM *dc_item, ZBX_DC_HOST *dc_host, int nextcheck)
9448 {
9449 unsigned char old_poller_type;
9450 int old_nextcheck;
9451
9452 dc_item->queue_priority = ZBX_QUEUE_PRIORITY_HIGH;
9453
9454 old_nextcheck = dc_item->nextcheck;
9455 dc_item->nextcheck = nextcheck;
9456
9457 old_poller_type = dc_item->poller_type;
9458 DCitem_poller_type_update(dc_item, dc_host, ZBX_ITEM_COLLECTED);
9459
9460 DCupdate_item_queue(dc_item, old_poller_type, old_nextcheck);
9461 }
9462
9463 /******************************************************************************
9464 * *
9465 * Function: DCconfig_get_poller_items *
9466 * *
9467 * Purpose: Get array of items for selected poller *
9468 * *
9469 * Parameters: poller_type - [IN] poller type (ZBX_POLLER_TYPE_...) *
9470 * items - [OUT] array of items *
9471 * *
9472 * Return value: number of items in items array *
9473 * *
9474 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
9475 * *
9476 * Comments: Items leave the queue only through this function. Pollers must *
9477 * always return the items they have taken using DCrequeue_items() *
9478 * or DCpoller_requeue_items(). *
9479 * *
9480 * Currently batch polling is supported only for JMX, SNMP and *
9481 * icmpping* simple checks. In other cases only single item is *
9482 * retrieved. *
9483 * *
9484 * IPMI poller queue are handled by DCconfig_get_ipmi_poller_items()*
9485 * function. *
9486 * *
9487 ******************************************************************************/
DCconfig_get_poller_items(unsigned char poller_type,DC_ITEM ** items)9488 int DCconfig_get_poller_items(unsigned char poller_type, DC_ITEM **items)
9489 {
9490 int now, num = 0, max_items;
9491 zbx_binary_heap_t *queue;
9492
9493 zabbix_log(LOG_LEVEL_DEBUG, "In %s() poller_type:%d", __func__, (int)poller_type);
9494
9495 now = time(NULL);
9496
9497 queue = &config->queues[poller_type];
9498
9499 switch (poller_type)
9500 {
9501 case ZBX_POLLER_TYPE_JAVA:
9502 max_items = MAX_JAVA_ITEMS;
9503 break;
9504 case ZBX_POLLER_TYPE_PINGER:
9505 max_items = MAX_PINGER_ITEMS;
9506 break;
9507 default:
9508 max_items = 1;
9509 }
9510
9511 WRLOCK_CACHE;
9512
9513 while (num < max_items && FAIL == zbx_binary_heap_empty(queue))
9514 {
9515 int disable_until;
9516 const zbx_binary_heap_elem_t *min;
9517 ZBX_DC_HOST *dc_host;
9518 ZBX_DC_INTERFACE *dc_interface;
9519 ZBX_DC_ITEM *dc_item;
9520 static const ZBX_DC_ITEM *dc_item_prev = NULL;
9521
9522 min = zbx_binary_heap_find_min(queue);
9523 dc_item = (ZBX_DC_ITEM *)min->data;
9524
9525 if (dc_item->nextcheck > now)
9526 break;
9527
9528 if (0 != num)
9529 {
9530 if (ITEM_TYPE_SNMP == dc_item_prev->type)
9531 {
9532 if (0 != __config_snmp_item_compare(dc_item_prev, dc_item))
9533 break;
9534 }
9535 else if (ITEM_TYPE_JMX == dc_item_prev->type)
9536 {
9537 if (0 != __config_java_item_compare(dc_item_prev, dc_item))
9538 break;
9539 }
9540 }
9541
9542 zbx_binary_heap_remove_min(queue);
9543 dc_item->location = ZBX_LOC_NOWHERE;
9544
9545 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
9546 continue;
9547
9548 dc_interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces, &dc_item->interfaceid);
9549
9550 if (HOST_STATUS_MONITORED != dc_host->status)
9551 continue;
9552
9553 if (SUCCEED == DCin_maintenance_without_data_collection(dc_host, dc_item))
9554 {
9555 dc_requeue_item(dc_item, dc_host, dc_interface, ZBX_ITEM_COLLECTED, now);
9556 continue;
9557 }
9558
9559 /* don't apply unreachable item/host throttling for prioritized items */
9560 if (ZBX_QUEUE_PRIORITY_HIGH != dc_item->queue_priority)
9561 {
9562 if (0 == (disable_until = DCget_disable_until(dc_item, dc_interface)))
9563 {
9564 /* move reachable items on reachable hosts to normal pollers */
9565 if (ZBX_POLLER_TYPE_UNREACHABLE == poller_type &&
9566 ZBX_QUEUE_PRIORITY_LOW != dc_item->queue_priority)
9567 {
9568 dc_requeue_item(dc_item, dc_host, dc_interface, ZBX_ITEM_COLLECTED, now);
9569 continue;
9570 }
9571 }
9572 else
9573 {
9574 /* move items on unreachable hosts to unreachable pollers or */
9575 /* postpone checks on hosts that have been checked recently and */
9576 /* are still unreachable */
9577 if (ZBX_POLLER_TYPE_NORMAL == poller_type || ZBX_POLLER_TYPE_JAVA == poller_type ||
9578 disable_until > now)
9579 {
9580 dc_requeue_item(dc_item, dc_host, dc_interface,
9581 ZBX_ITEM_COLLECTED | ZBX_HOST_UNREACHABLE, now);
9582 continue;
9583 }
9584
9585 DCincrease_disable_until(dc_interface, now);
9586 }
9587 }
9588
9589 if (0 == num)
9590 {
9591 if (ZBX_POLLER_TYPE_NORMAL == poller_type && ITEM_TYPE_SNMP == dc_item->type &&
9592 0 == (ZBX_FLAG_DISCOVERY_RULE & dc_item->flags))
9593 {
9594 ZBX_DC_SNMPITEM *snmpitem;
9595
9596 snmpitem = (ZBX_DC_SNMPITEM *)zbx_hashset_search(&config->snmpitems, &dc_item->itemid);
9597
9598 if (ZBX_SNMP_OID_TYPE_NORMAL == snmpitem->snmp_oid_type ||
9599 ZBX_SNMP_OID_TYPE_DYNAMIC == snmpitem->snmp_oid_type)
9600 {
9601 max_items = DCconfig_get_suggested_snmp_vars_nolock(dc_item->interfaceid, NULL);
9602 }
9603 }
9604
9605 if (1 < max_items)
9606 *items = zbx_malloc(NULL, sizeof(DC_ITEM) * max_items);
9607 }
9608
9609 dc_item_prev = dc_item;
9610 dc_item->location = ZBX_LOC_POLLER;
9611 DCget_host(&(*items)[num].host, dc_host, ZBX_ITEM_GET_ALL);
9612 DCget_item(&(*items)[num], dc_item, ZBX_ITEM_GET_ALL);
9613 num++;
9614 }
9615
9616 UNLOCK_CACHE;
9617
9618 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __func__, num);
9619
9620 return num;
9621 }
9622
9623 /******************************************************************************
9624 * *
9625 * Function: DCconfig_get_ipmi_poller_items *
9626 * *
9627 * Purpose: Get array of items for IPMI poller *
9628 * *
9629 * Parameters: now - [IN] current timestamp *
9630 * items - [OUT] array of items *
9631 * items_num - [IN] the number of items to get *
9632 * nextcheck - [OUT] the next scheduled check *
9633 * *
9634 * Return value: number of items in items array *
9635 * *
9636 * Comments: IPMI items leave the queue only through this function. IPMI *
9637 * manager must always return the items they have taken using *
9638 * DCrequeue_items() or DCpoller_requeue_items(). *
9639 * *
9640 ******************************************************************************/
DCconfig_get_ipmi_poller_items(int now,DC_ITEM * items,int items_num,int * nextcheck)9641 int DCconfig_get_ipmi_poller_items(int now, DC_ITEM *items, int items_num, int *nextcheck)
9642 {
9643 int num = 0;
9644 zbx_binary_heap_t *queue;
9645
9646 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
9647
9648 queue = &config->queues[ZBX_POLLER_TYPE_IPMI];
9649
9650 WRLOCK_CACHE;
9651
9652 while (num < items_num && FAIL == zbx_binary_heap_empty(queue))
9653 {
9654 int disable_until;
9655 const zbx_binary_heap_elem_t *min;
9656 ZBX_DC_HOST *dc_host;
9657 ZBX_DC_INTERFACE *dc_interface;
9658 ZBX_DC_ITEM *dc_item;
9659
9660 min = zbx_binary_heap_find_min(queue);
9661 dc_item = (ZBX_DC_ITEM *)min->data;
9662
9663 if (dc_item->nextcheck > now)
9664 break;
9665
9666 zbx_binary_heap_remove_min(queue);
9667 dc_item->location = ZBX_LOC_NOWHERE;
9668
9669 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
9670 continue;
9671
9672 if (HOST_STATUS_MONITORED != dc_host->status)
9673 continue;
9674
9675 if (NULL == (dc_interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces,
9676 &dc_item->interfaceid)))
9677 {
9678 continue;
9679 }
9680
9681 if (SUCCEED == DCin_maintenance_without_data_collection(dc_host, dc_item))
9682 {
9683 dc_requeue_item(dc_item, dc_host, dc_interface, ZBX_ITEM_COLLECTED, now);
9684 continue;
9685 }
9686
9687 /* don't apply unreachable item/host throttling for prioritized items */
9688 if (ZBX_QUEUE_PRIORITY_HIGH != dc_item->queue_priority)
9689 {
9690 if (0 != (disable_until = DCget_disable_until(dc_item, dc_interface)))
9691 {
9692 if (disable_until > now)
9693 {
9694 dc_requeue_item(dc_item, dc_host, dc_interface,
9695 ZBX_ITEM_COLLECTED | ZBX_HOST_UNREACHABLE, now);
9696 continue;
9697 }
9698
9699 DCincrease_disable_until(dc_interface, now);
9700 }
9701 }
9702
9703 dc_item->location = ZBX_LOC_POLLER;
9704 DCget_host(&items[num].host, dc_host, ZBX_ITEM_GET_ALL);
9705 DCget_item(&items[num], dc_item, ZBX_ITEM_GET_ALL);
9706 num++;
9707 }
9708
9709 *nextcheck = dc_config_get_queue_nextcheck(&config->queues[ZBX_POLLER_TYPE_IPMI]);
9710
9711 UNLOCK_CACHE;
9712
9713 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __func__, num);
9714
9715 return num;
9716 }
9717
9718
9719 /******************************************************************************
9720 * *
9721 * Function: DCconfig_get_snmp_interfaceids_by_addr *
9722 * *
9723 * Purpose: get array of interface IDs for the specified address *
9724 * *
9725 * Return value: number of interface IDs returned *
9726 * *
9727 * Author: Rudolfs Kreicbergs *
9728 * *
9729 ******************************************************************************/
DCconfig_get_snmp_interfaceids_by_addr(const char * addr,zbx_uint64_t ** interfaceids)9730 int DCconfig_get_snmp_interfaceids_by_addr(const char *addr, zbx_uint64_t **interfaceids)
9731 {
9732 int count = 0, i;
9733 const ZBX_DC_INTERFACE_ADDR *dc_interface_snmpaddr;
9734 ZBX_DC_INTERFACE_ADDR dc_interface_snmpaddr_local;
9735
9736 zabbix_log(LOG_LEVEL_DEBUG, "In %s() addr:'%s'", __func__, addr);
9737
9738 dc_interface_snmpaddr_local.addr = addr;
9739
9740 RDLOCK_CACHE;
9741
9742 if (NULL == (dc_interface_snmpaddr = (const ZBX_DC_INTERFACE_ADDR *)zbx_hashset_search(&config->interface_snmpaddrs, &dc_interface_snmpaddr_local)))
9743 goto unlock;
9744
9745 *interfaceids = (zbx_uint64_t *)zbx_malloc(*interfaceids, dc_interface_snmpaddr->interfaceids.values_num * sizeof(zbx_uint64_t));
9746
9747 for (i = 0; i < dc_interface_snmpaddr->interfaceids.values_num; i++)
9748 (*interfaceids)[i] = dc_interface_snmpaddr->interfaceids.values[i];
9749
9750 count = i;
9751 unlock:
9752 UNLOCK_CACHE;
9753
9754 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __func__, count);
9755
9756 return count;
9757 }
9758
9759 /******************************************************************************
9760 * *
9761 * Function: DCconfig_get_snmp_items_by_interfaceid *
9762 * *
9763 * Purpose: get array of snmp trap items for the specified interfaceid *
9764 * *
9765 * Return value: number of items returned *
9766 * *
9767 * Author: Rudolfs Kreicbergs *
9768 * *
9769 ******************************************************************************/
DCconfig_get_snmp_items_by_interfaceid(zbx_uint64_t interfaceid,DC_ITEM ** items)9770 size_t DCconfig_get_snmp_items_by_interfaceid(zbx_uint64_t interfaceid, DC_ITEM **items)
9771 {
9772 size_t items_num = 0, items_alloc = 8;
9773 int i;
9774 const ZBX_DC_ITEM *dc_item;
9775 const ZBX_DC_INTERFACE_ITEM *dc_interface_snmpitem;
9776 const ZBX_DC_INTERFACE *dc_interface;
9777 const ZBX_DC_HOST *dc_host;
9778
9779 zabbix_log(LOG_LEVEL_DEBUG, "In %s() interfaceid:" ZBX_FS_UI64, __func__, interfaceid);
9780
9781 RDLOCK_CACHE;
9782
9783 if (NULL == (dc_interface = (const ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces, &interfaceid)))
9784 goto unlock;
9785
9786 if (NULL == (dc_host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_interface->hostid)))
9787 goto unlock;
9788
9789 if (HOST_STATUS_MONITORED != dc_host->status)
9790 goto unlock;
9791
9792 if (NULL == (dc_interface_snmpitem = (const ZBX_DC_INTERFACE_ITEM *)zbx_hashset_search(&config->interface_snmpitems, &interfaceid)))
9793 goto unlock;
9794
9795 *items = (DC_ITEM *)zbx_malloc(*items, items_alloc * sizeof(DC_ITEM));
9796
9797 for (i = 0; i < dc_interface_snmpitem->itemids.values_num; i++)
9798 {
9799 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &dc_interface_snmpitem->itemids.values[i])))
9800 continue;
9801
9802 if (ITEM_STATUS_ACTIVE != dc_item->status)
9803 continue;
9804
9805 if (SUCCEED == DCin_maintenance_without_data_collection(dc_host, dc_item))
9806 continue;
9807
9808 if (items_num == items_alloc)
9809 {
9810 items_alloc += 8;
9811 *items = (DC_ITEM *)zbx_realloc(*items, items_alloc * sizeof(DC_ITEM));
9812 }
9813
9814 DCget_host(&(*items)[items_num].host, dc_host, ZBX_ITEM_GET_ALL);
9815 DCget_item(&(*items)[items_num], dc_item, ZBX_ITEM_GET_ALL);
9816 items_num++;
9817 }
9818 unlock:
9819 UNLOCK_CACHE;
9820
9821 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():" ZBX_FS_SIZE_T, __func__, (zbx_fs_size_t)items_num);
9822
9823 return items_num;
9824 }
9825
dc_requeue_items(const zbx_uint64_t * itemids,const int * lastclocks,const int * errcodes,size_t num)9826 static void dc_requeue_items(const zbx_uint64_t *itemids, const int *lastclocks, const int *errcodes, size_t num)
9827 {
9828 size_t i;
9829 ZBX_DC_ITEM *dc_item;
9830 ZBX_DC_HOST *dc_host;
9831 ZBX_DC_INTERFACE *dc_interface;
9832
9833 for (i = 0; i < num; i++)
9834 {
9835 if (FAIL == errcodes[i])
9836 continue;
9837
9838 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemids[i])))
9839 continue;
9840
9841 if (ZBX_LOC_POLLER == dc_item->location)
9842 dc_item->location = ZBX_LOC_NOWHERE;
9843
9844 if (ITEM_STATUS_ACTIVE != dc_item->status)
9845 continue;
9846
9847 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
9848 continue;
9849
9850 if (HOST_STATUS_MONITORED != dc_host->status)
9851 continue;
9852
9853 if (SUCCEED != zbx_is_counted_in_item_queue(dc_item->type, dc_item->key))
9854 continue;
9855
9856 dc_interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces, &dc_item->interfaceid);
9857
9858 switch (errcodes[i])
9859 {
9860 case SUCCEED:
9861 case NOTSUPPORTED:
9862 case AGENT_ERROR:
9863 case CONFIG_ERROR:
9864 dc_item->queue_priority = ZBX_QUEUE_PRIORITY_NORMAL;
9865 dc_requeue_item(dc_item, dc_host, dc_interface, ZBX_ITEM_COLLECTED, lastclocks[i]);
9866 break;
9867 case NETWORK_ERROR:
9868 case GATEWAY_ERROR:
9869 case TIMEOUT_ERROR:
9870 dc_item->queue_priority = ZBX_QUEUE_PRIORITY_LOW;
9871 dc_requeue_item(dc_item, dc_host, dc_interface,
9872 ZBX_ITEM_COLLECTED | ZBX_HOST_UNREACHABLE, time(NULL));
9873 break;
9874 default:
9875 THIS_SHOULD_NEVER_HAPPEN;
9876 }
9877 }
9878 }
9879
DCrequeue_items(const zbx_uint64_t * itemids,const int * lastclocks,const int * errcodes,size_t num)9880 void DCrequeue_items(const zbx_uint64_t *itemids, const int *lastclocks,
9881 const int *errcodes, size_t num)
9882 {
9883 WRLOCK_CACHE;
9884
9885 dc_requeue_items(itemids, lastclocks, errcodes, num);
9886
9887 UNLOCK_CACHE;
9888 }
9889
DCpoller_requeue_items(const zbx_uint64_t * itemids,const int * lastclocks,const int * errcodes,size_t num,unsigned char poller_type,int * nextcheck)9890 void DCpoller_requeue_items(const zbx_uint64_t *itemids, const int *lastclocks,
9891 const int *errcodes, size_t num, unsigned char poller_type, int *nextcheck)
9892 {
9893 WRLOCK_CACHE;
9894
9895 dc_requeue_items(itemids, lastclocks, errcodes, num);
9896 *nextcheck = dc_config_get_queue_nextcheck(&config->queues[poller_type]);
9897
9898 UNLOCK_CACHE;
9899 }
9900
9901 /******************************************************************************
9902 * *
9903 * Function: zbx_dc_requeue_unreachable_items *
9904 * *
9905 * Purpose: requeue unreachable items *
9906 * *
9907 * Parameters: itemids - [IN] the item id array *
9908 * itemids_num - [IN] the number of values in itemids array *
9909 * *
9910 * Comments: This function is used when items must be put back in the queue *
9911 * without polling them. For example if a poller has taken a batch *
9912 * of items from queue, host becomes unreachable during while *
9913 * polling the items, so the unpolled items of the same host must *
9914 * be returned to queue without updating their status. *
9915 * *
9916 ******************************************************************************/
zbx_dc_requeue_unreachable_items(zbx_uint64_t * itemids,size_t itemids_num)9917 void zbx_dc_requeue_unreachable_items(zbx_uint64_t *itemids, size_t itemids_num)
9918 {
9919 size_t i;
9920 ZBX_DC_ITEM *dc_item;
9921 ZBX_DC_HOST *dc_host;
9922 ZBX_DC_INTERFACE *dc_interface;
9923
9924 WRLOCK_CACHE;
9925
9926 for (i = 0; i < itemids_num; i++)
9927 {
9928 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemids[i])))
9929 continue;
9930
9931 if (ZBX_LOC_POLLER == dc_item->location)
9932 dc_item->location = ZBX_LOC_NOWHERE;
9933
9934 if (ITEM_STATUS_ACTIVE != dc_item->status)
9935 continue;
9936
9937 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
9938 continue;
9939
9940 if (HOST_STATUS_MONITORED != dc_host->status)
9941 continue;
9942
9943 dc_interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces, &dc_item->interfaceid);
9944
9945 dc_requeue_item(dc_item, dc_host, dc_interface, ZBX_ITEM_COLLECTED | ZBX_HOST_UNREACHABLE,
9946 time(NULL));
9947 }
9948
9949 UNLOCK_CACHE;
9950 }
9951
9952 /******************************************************************************
9953 * *
9954 * Function: DCinterface_get_agent_availability *
9955 * *
9956 * Purpose: get interface availability data for the specified agent *
9957 * *
9958 * Parameters: dc_interface - [IN] the interface *
9959 * availability - [OUT] the interface availability data *
9960 * *
9961 * Comments: The configuration cache must be locked already. *
9962 * *
9963 ******************************************************************************/
DCinterface_get_agent_availability(const ZBX_DC_INTERFACE * dc_interface,zbx_agent_availability_t * agent)9964 static void DCinterface_get_agent_availability(const ZBX_DC_INTERFACE *dc_interface,
9965 zbx_agent_availability_t *agent)
9966 {
9967
9968 agent->flags = ZBX_FLAGS_AGENT_STATUS;
9969
9970 agent->available = dc_interface->available;
9971 agent->error = zbx_strdup(agent->error, dc_interface->error);
9972 agent->errors_from = dc_interface->errors_from;
9973 agent->disable_until = dc_interface->disable_until;
9974 }
9975
DCagent_set_availability(zbx_agent_availability_t * av,unsigned char * available,const char ** error,int * errors_from,int * disable_until)9976 static void DCagent_set_availability(zbx_agent_availability_t *av, unsigned char *available, const char **error,
9977 int *errors_from, int *disable_until)
9978 {
9979 #define AGENT_AVAILABILITY_ASSIGN(flags, mask, dst, src) \
9980 if (0 != (flags & mask)) \
9981 { \
9982 if (dst != src) \
9983 dst = src; \
9984 else \
9985 flags &= (~(mask)); \
9986 }
9987
9988 #define AGENT_AVAILABILITY_ASSIGN_STR(flags, mask, dst, src) \
9989 if (0 != (flags & mask)) \
9990 { \
9991 if (0 != strcmp(dst, src)) \
9992 DCstrpool_replace(1, &dst, src); \
9993 else \
9994 flags &= (~(mask)); \
9995 }
9996
9997 AGENT_AVAILABILITY_ASSIGN(av->flags, ZBX_FLAGS_AGENT_STATUS_AVAILABLE, *available, av->available);
9998 AGENT_AVAILABILITY_ASSIGN_STR(av->flags, ZBX_FLAGS_AGENT_STATUS_ERROR, *error, av->error);
9999 AGENT_AVAILABILITY_ASSIGN(av->flags, ZBX_FLAGS_AGENT_STATUS_ERRORS_FROM, *errors_from, av->errors_from);
10000 AGENT_AVAILABILITY_ASSIGN(av->flags, ZBX_FLAGS_AGENT_STATUS_DISABLE_UNTIL, *disable_until, av->disable_until);
10001
10002 #undef AGENT_AVAILABILITY_ASSIGN_STR
10003 #undef AGENT_AVAILABILITY_ASSIGN
10004 }
10005
10006 /******************************************************************************
10007 * *
10008 * Function: DCinterface_set_agent_availability *
10009 * *
10010 * Purpose: set interface availability data in configuration cache *
10011 * *
10012 * Parameters: dc_interface - [OUT] the interface *
10013 * now - [IN] current timestamp *
10014 * agent - [IN/OUT] the agent availability data *
10015 * *
10016 * Return value: SUCCEED - at least one availability field was updated *
10017 * FAIL - no availability fields were updated *
10018 * *
10019 * Comments: The configuration cache must be locked already. *
10020 * *
10021 * This function clears availability flags of non updated fields *
10022 * updated leaving only flags identifying changed fields. *
10023 * *
10024 ******************************************************************************/
DCinterface_set_agent_availability(ZBX_DC_INTERFACE * dc_interface,int now,zbx_agent_availability_t * agent)10025 static int DCinterface_set_agent_availability(ZBX_DC_INTERFACE *dc_interface, int now,
10026 zbx_agent_availability_t *agent)
10027 {
10028 DCagent_set_availability(agent, &dc_interface->available, &dc_interface->error,
10029 &dc_interface->errors_from, &dc_interface->disable_until);
10030
10031 if (ZBX_FLAGS_AGENT_STATUS_NONE == agent->flags)
10032 return FAIL;
10033
10034 if (0 != (agent->flags & (ZBX_FLAGS_AGENT_STATUS_AVAILABLE | ZBX_FLAGS_AGENT_STATUS_ERROR)))
10035 dc_interface->availability_ts = now;
10036
10037 return SUCCEED;
10038 }
10039
10040 /******************************************************************************
10041 * *
10042 * Function: DCinterface_set_availability *
10043 * *
10044 * Purpose: set interface availability data in configuration cache *
10045 * *
10046 * Parameters: dc_interface - [OUT] the interface *
10047 * ia - [IN/OUT] the interface availability data *
10048 * *
10049 * Return value: SUCCEED - at least one availability field was updated *
10050 * FAIL - no availability fields were updated *
10051 * *
10052 * Comments: The configuration cache must be locked already. *
10053 * *
10054 * This function clears availability flags of non updated fields *
10055 * updated leaving only flags identifying changed fields. *
10056 * *
10057 ******************************************************************************/
DCinterface_set_availability(ZBX_DC_INTERFACE * dc_interface,int now,zbx_interface_availability_t * ia)10058 static int DCinterface_set_availability(ZBX_DC_INTERFACE *dc_interface, int now, zbx_interface_availability_t *ia)
10059 {
10060 unsigned char flags = ZBX_FLAGS_AGENT_STATUS_NONE;
10061
10062 DCagent_set_availability(&ia->agent, &dc_interface->available, &dc_interface->error,
10063 &dc_interface->errors_from, &dc_interface->disable_until);
10064
10065 flags |= ia->agent.flags;
10066
10067 if (ZBX_FLAGS_AGENT_STATUS_NONE == flags)
10068 return FAIL;
10069
10070 if (0 != (flags & (ZBX_FLAGS_AGENT_STATUS_AVAILABLE | ZBX_FLAGS_AGENT_STATUS_ERROR)))
10071 dc_interface->availability_ts = now;
10072
10073 return SUCCEED;
10074 }
10075
10076 /******************************************************************************
10077 * *
10078 * Function: zbx_interface_availability_init *
10079 * *
10080 * Purpose: initializes interface availability data *
10081 * *
10082 * Parameters: availability - [IN/OUT] interface availability data *
10083 * interfaceid - [IN] interface id *
10084 * *
10085 ******************************************************************************/
zbx_interface_availability_init(zbx_interface_availability_t * availability,zbx_uint64_t interfaceid)10086 void zbx_interface_availability_init(zbx_interface_availability_t *availability, zbx_uint64_t interfaceid)
10087 {
10088 memset(availability, 0, sizeof(zbx_interface_availability_t));
10089 availability->interfaceid = interfaceid;
10090 }
10091
10092 /********************************************************************************
10093 * *
10094 * Function: zbx_interface_availability_clean *
10095 * *
10096 * Purpose: releases resources allocated to store interface availability data *
10097 * *
10098 * Parameters: ia - [IN] interface availability data *
10099 * *
10100 ********************************************************************************/
zbx_interface_availability_clean(zbx_interface_availability_t * ia)10101 void zbx_interface_availability_clean(zbx_interface_availability_t *ia)
10102 {
10103 zbx_free(ia->agent.error);
10104 }
10105
10106 /******************************************************************************
10107 * *
10108 * Function: zbx_interface_availability_free *
10109 * *
10110 * Purpose: frees interface availability data *
10111 * *
10112 * Parameters: availability - [IN] interface availability data *
10113 * *
10114 ******************************************************************************/
zbx_interface_availability_free(zbx_interface_availability_t * availability)10115 void zbx_interface_availability_free(zbx_interface_availability_t *availability)
10116 {
10117 zbx_interface_availability_clean(availability);
10118 zbx_free(availability);
10119 }
10120
10121 ZBX_PTR_VECTOR_IMPL(availability_ptr, zbx_interface_availability_t *);
10122 /******************************************************************************
10123 * *
10124 * Function: zbx_agent_availability_init *
10125 * *
10126 * Purpose: initializes agent availability with the specified data *
10127 * *
10128 * Parameters: agent - [IN/OUT] agent availability data *
10129 * available - [IN] the availability data *
10130 * error - [IN] the availability error *
10131 * errors_from - [IN] error starting timestamp *
10132 * disable_until - [IN] disable until timestamp *
10133 * *
10134 ******************************************************************************/
zbx_agent_availability_init(zbx_agent_availability_t * agent,unsigned char available,const char * error,int errors_from,int disable_until)10135 static void zbx_agent_availability_init(zbx_agent_availability_t *agent, unsigned char available, const char *error,
10136 int errors_from, int disable_until)
10137 {
10138 agent->flags = ZBX_FLAGS_AGENT_STATUS;
10139 agent->available = available;
10140 agent->error = zbx_strdup(NULL, error);
10141 agent->errors_from = errors_from;
10142 agent->disable_until = disable_until;
10143 }
10144
10145 /******************************************************************************
10146 * *
10147 * Function: zbx_interface_availability_is_set *
10148 * *
10149 * Purpose: checks interface availability if agent availability field is set *
10150 * *
10151 * Parameters: ia - [IN] interface availability data *
10152 * *
10153 * Return value: SUCCEED - an agent availability field is set *
10154 * FAIL - no agent availability field is set *
10155 * *
10156 ******************************************************************************/
zbx_interface_availability_is_set(const zbx_interface_availability_t * ia)10157 int zbx_interface_availability_is_set(const zbx_interface_availability_t *ia)
10158 {
10159 if (ZBX_FLAGS_AGENT_STATUS_NONE != ia->agent.flags)
10160 return SUCCEED;
10161
10162 return FAIL;
10163 }
10164
10165 /**************************************************************************************
10166 * *
10167 * Host availability update example *
10168 * *
10169 * *
10170 * | UnreachablePeriod *
10171 * | (conf file) *
10172 * | ______________ *
10173 * | / \ *
10174 * | p p p p p p *
10175 * | o o o o o o *
10176 * | l l l l l l *
10177 * | l l l l l l *
10178 * | n *
10179 * | e e e e e e e *
10180 * agent | w p p r r r r r r p p p *
10181 * polls | o o r r r r r r o o o *
10182 * | h l l o o o o o o l l l *
10183 * | o l l r r r r r r l l l *
10184 * | s *
10185 * | t ok ok E1 E1 E2 E1 E1 E2 ok ok ok *
10186 * -------------------------------------------------------------------------------- *
10187 * available | 0 1 1 1 1 1 2 2 2 0 0 0 *
10188 * | *
10189 * error | "" "" "" "" "" "" E1 E1 E2 "" "" "" *
10190 * | *
10191 * errors_from | 0 0 0 T4 T4 T4 T4 T4 T4 0 0 0 *
10192 * | *
10193 * disable_until| 0 0 0 T5 T6 T7 T8 T9 T10 0 0 0 *
10194 * -------------------------------------------------------------------------------- *
10195 * timestamps | T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 *
10196 * | \_/ \_/ \_/ \___/ \___/ \___/ \_____/ \_____/ \_____/ \_/ \_/ *
10197 * | | | | | | | | | | | | *
10198 * polling | item delay UnreachableDelay UnavailableDelay item | *
10199 * periods | (conf file) (conf file) delay *
10200 * *
10201 * *
10202 **************************************************************************************/
10203
10204 /*******************************************************************************
10205 * *
10206 * Function: DCinterface_activate *
10207 * *
10208 * Purpose: set interface as available based on the agent availability data *
10209 * *
10210 * Parameters: interfaceid - [IN] the interface identifier *
10211 * ts - [IN] the last timestamp *
10212 * in - [IN/OUT] IN: the caller's agent availability data *
10213 * OUT: the agent availability data in cache *
10214 * before changes *
10215 * out - [OUT] the agent availability data after changes *
10216 * *
10217 * Return value: SUCCEED - the interface was activated successfully *
10218 * FAIL - the interface was already activated or activation *
10219 * failed *
10220 * *
10221 * Comments: The interface availability fields are updated according to the *
10222 * above schema. *
10223 * *
10224 *******************************************************************************/
DCinterface_activate(zbx_uint64_t interfaceid,const zbx_timespec_t * ts,zbx_agent_availability_t * in,zbx_agent_availability_t * out)10225 int DCinterface_activate(zbx_uint64_t interfaceid, const zbx_timespec_t *ts,
10226 zbx_agent_availability_t *in, zbx_agent_availability_t *out)
10227 {
10228 int ret = FAIL;
10229 ZBX_DC_HOST *dc_host;
10230 ZBX_DC_INTERFACE *dc_interface;
10231
10232 /* don't try activating interface if there were no errors detected */
10233 if (0 == in->errors_from && INTERFACE_AVAILABLE_TRUE == in->available)
10234 goto out;
10235
10236 WRLOCK_CACHE;
10237
10238 if (NULL == (dc_interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces, &interfaceid)))
10239 goto unlock;
10240
10241 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_interface->hostid)))
10242 goto unlock;
10243
10244 /* Don't try activating interface if: */
10245 /* - (server, proxy) host is not monitored any more; */
10246 /* - (server) host is monitored by proxy. */
10247 if ((0 != (program_type & ZBX_PROGRAM_TYPE_SERVER) && 0 != dc_host->proxy_hostid) ||
10248 HOST_STATUS_MONITORED != dc_host->status)
10249 {
10250 goto unlock;
10251 }
10252
10253 DCinterface_get_agent_availability(dc_interface, in);
10254 zbx_agent_availability_init(out, INTERFACE_AVAILABLE_TRUE, "", 0, 0);
10255
10256 if (SUCCEED == DCinterface_set_agent_availability(dc_interface, ts->sec, out) &&
10257 ZBX_FLAGS_AGENT_STATUS_NONE != out->flags)
10258 {
10259 ret = SUCCEED;
10260 }
10261 unlock:
10262 UNLOCK_CACHE;
10263 out:
10264 return ret;
10265 }
10266
10267 /************************************************************************************
10268 * *
10269 * Function: DCinterface_deactivate *
10270 * *
10271 * Purpose: attempt to set interface as unavailable based on agent availability *
10272 * *
10273 * Parameters: interfaceid - [IN] the interface identifier *
10274 * ts - [IN] the last timestamp *
10275 * in - [IN/OUT] IN: the caller's interface availability data *
10276 * OUT: the interface availability data in cache *
10277 * before changes *
10278 * out - [OUT] the interface availability data after changes *
10279 * error_msg - [IN] the error message *
10280 * *
10281 * Return value: SUCCEED - the interface was deactivated successfully *
10282 * FAIL - the interface was already deactivated or deactivation *
10283 * failed *
10284 * *
10285 * Comments: The interface availability fields are updated according to the above *
10286 * schema. *
10287 * *
10288 ***********************************************************************************/
DCinterface_deactivate(zbx_uint64_t interfaceid,const zbx_timespec_t * ts,zbx_agent_availability_t * in,zbx_agent_availability_t * out,const char * error_msg)10289 int DCinterface_deactivate(zbx_uint64_t interfaceid, const zbx_timespec_t *ts, zbx_agent_availability_t *in,
10290 zbx_agent_availability_t *out, const char *error_msg)
10291 {
10292 int ret = FAIL, errors_from, disable_until;
10293 const char *error;
10294 unsigned char available;
10295 ZBX_DC_HOST *dc_host;
10296 ZBX_DC_INTERFACE *dc_interface;
10297
10298 /* don't try deactivating interface if the unreachable delay has not passed since the first error */
10299 if (CONFIG_UNREACHABLE_DELAY > ts->sec - in->errors_from)
10300 goto out;
10301
10302 WRLOCK_CACHE;
10303
10304 if (NULL == (dc_interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces, &interfaceid)))
10305 goto unlock;
10306
10307 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_interface->hostid)))
10308 goto unlock;
10309
10310 /* Don't try deactivating interface if: */
10311 /* - (server, proxy) host is not monitored any more; */
10312 /* - (server) host is monitored by proxy. */
10313 if ((0 != (program_type & ZBX_PROGRAM_TYPE_SERVER) && 0 != dc_host->proxy_hostid) ||
10314 HOST_STATUS_MONITORED != dc_host->status)
10315 {
10316 goto unlock;
10317 }
10318
10319 DCinterface_get_agent_availability(dc_interface, in);
10320
10321 available = in->available;
10322 error = in->error;
10323
10324 if (0 == in->errors_from)
10325 {
10326 /* first error, schedule next unreachable check */
10327 errors_from = ts->sec;
10328 disable_until = ts->sec + CONFIG_UNREACHABLE_DELAY;
10329 }
10330 else
10331 {
10332 errors_from = in->errors_from;
10333 disable_until = in->disable_until;
10334
10335 /* Check if other pollers haven't already attempted deactivating host. */
10336 /* In that case should wait the initial unreachable delay before */
10337 /* trying to make it unavailable. */
10338 if (CONFIG_UNREACHABLE_DELAY <= ts->sec - errors_from)
10339 {
10340 /* repeating error */
10341 if (CONFIG_UNREACHABLE_PERIOD > ts->sec - errors_from)
10342 {
10343 /* leave host available, schedule next unreachable check */
10344 disable_until = ts->sec + CONFIG_UNREACHABLE_DELAY;
10345 }
10346 else
10347 {
10348 /* make host unavailable, schedule next unavailable check */
10349 disable_until = ts->sec + CONFIG_UNAVAILABLE_DELAY;
10350 available = INTERFACE_AVAILABLE_FALSE;
10351 error = error_msg;
10352 }
10353 }
10354 }
10355
10356 zbx_agent_availability_init(out, available, error, errors_from, disable_until);
10357
10358 if (SUCCEED == DCinterface_set_agent_availability(dc_interface, ts->sec, out) &&
10359 ZBX_FLAGS_AGENT_STATUS_NONE != out->flags)
10360 {
10361 ret = SUCCEED;
10362 }
10363 unlock:
10364 UNLOCK_CACHE;
10365 out:
10366 return ret;
10367 }
10368
10369 /******************************************************************************
10370 * *
10371 * Function: DCset_interfaces_availability *
10372 * *
10373 * Purpose: update availability of interfaces in configuration cache and *
10374 * return the updated field flags *
10375 * *
10376 * Parameters: availabilities - [IN/OUT] the interfacess availability data *
10377 * *
10378 * Return value: SUCCEED - at least one interface availability data *
10379 * was updated *
10380 * FAIL - no interfaces were updated *
10381 * *
10382 ******************************************************************************/
DCset_interfaces_availability(zbx_vector_availability_ptr_t * availabilities)10383 int DCset_interfaces_availability(zbx_vector_availability_ptr_t *availabilities)
10384 {
10385 int i;
10386 ZBX_DC_INTERFACE *dc_interface;
10387 zbx_interface_availability_t *ia;
10388 int ret = FAIL, now;
10389
10390 now = time(NULL);
10391
10392 WRLOCK_CACHE;
10393
10394 for (i = 0; i < availabilities->values_num; i++)
10395 {
10396 ia = availabilities->values[i];
10397
10398 if (NULL == (dc_interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces,
10399 &ia->interfaceid)))
10400 {
10401 int j;
10402
10403 /* reset availability flag so this host is ignored when saving availability diff to DB */
10404 for (j = 0; j < ZBX_AGENT_MAX; j++)
10405 ia->agent.flags = ZBX_FLAGS_AGENT_STATUS_NONE;
10406
10407 continue;
10408 }
10409
10410 if (SUCCEED == DCinterface_set_availability(dc_interface, now, ia))
10411 ret = SUCCEED;
10412 }
10413
10414 UNLOCK_CACHE;
10415
10416 return ret;
10417 }
10418
10419 /******************************************************************************
10420 * *
10421 * Comments: helper function for trigger dependency checking *
10422 * *
10423 * Parameters: trigdep - [IN] the trigger dependency data *
10424 * level - [IN] the trigger dependency level *
10425 * triggerids - [IN] the currently processing trigger ids *
10426 * for bulk trigger operations *
10427 * (optional, can be NULL) *
10428 * master_triggerids - [OUT] unresolved master trigger ids *
10429 * for bulk trigger operations *
10430 * (optional together with triggerids *
10431 * parameter) *
10432 * *
10433 * Return value: SUCCEED - trigger dependency check succeed / was unresolved *
10434 * FAIL - otherwise *
10435 * *
10436 * Comments: With bulk trigger processing a master trigger can be in the same *
10437 * batch as dependent trigger. In this case it might be impossible *
10438 * to perform dependency check based on cashed trigger values. The *
10439 * unresolved master trigger ids will be added to master_triggerids *
10440 * vector, so the dependency check can be performed after a new *
10441 * master trigger value has been calculated. *
10442 * *
10443 ******************************************************************************/
DCconfig_check_trigger_dependencies_rec(const ZBX_DC_TRIGGER_DEPLIST * trigdep,int level,const zbx_vector_uint64_t * triggerids,zbx_vector_uint64_t * master_triggerids)10444 static int DCconfig_check_trigger_dependencies_rec(const ZBX_DC_TRIGGER_DEPLIST *trigdep, int level,
10445 const zbx_vector_uint64_t *triggerids, zbx_vector_uint64_t *master_triggerids)
10446 {
10447 int i;
10448 const ZBX_DC_TRIGGER *next_trigger;
10449 const ZBX_DC_TRIGGER_DEPLIST *next_trigdep;
10450
10451 if (ZBX_TRIGGER_DEPENDENCY_LEVELS_MAX < level)
10452 {
10453 zabbix_log(LOG_LEVEL_CRIT, "recursive trigger dependency is too deep (triggerid:" ZBX_FS_UI64 ")",
10454 trigdep->triggerid);
10455 return SUCCEED;
10456 }
10457
10458 if (0 != trigdep->dependencies.values_num)
10459 {
10460 for (i = 0; i < trigdep->dependencies.values_num; i++)
10461 {
10462 next_trigdep = (const ZBX_DC_TRIGGER_DEPLIST *)trigdep->dependencies.values[i];
10463
10464 if (NULL != (next_trigger = next_trigdep->trigger) &&
10465 TRIGGER_STATUS_ENABLED == next_trigger->status &&
10466 TRIGGER_FUNCTIONAL_TRUE == next_trigger->functional)
10467 {
10468
10469 if (NULL == triggerids || FAIL == zbx_vector_uint64_bsearch(triggerids,
10470 next_trigger->triggerid, ZBX_DEFAULT_UINT64_COMPARE_FUNC))
10471 {
10472 if (TRIGGER_VALUE_PROBLEM == next_trigger->value)
10473 return FAIL;
10474 }
10475 else
10476 zbx_vector_uint64_append(master_triggerids, next_trigger->triggerid);
10477 }
10478
10479 if (FAIL == DCconfig_check_trigger_dependencies_rec(next_trigdep, level + 1, triggerids,
10480 master_triggerids))
10481 {
10482 return FAIL;
10483 }
10484 }
10485 }
10486
10487 return SUCCEED;
10488 }
10489
10490 /******************************************************************************
10491 * *
10492 * Function: DCconfig_check_trigger_dependencies *
10493 * *
10494 * Purpose: check whether any of trigger dependencies have value PROBLEM *
10495 * *
10496 * Return value: SUCCEED - trigger can change its value *
10497 * FAIL - otherwise *
10498 * *
10499 * Author: Alexei Vladishev, Aleksandrs Saveljevs *
10500 * *
10501 ******************************************************************************/
DCconfig_check_trigger_dependencies(zbx_uint64_t triggerid)10502 int DCconfig_check_trigger_dependencies(zbx_uint64_t triggerid)
10503 {
10504 int ret = SUCCEED;
10505 const ZBX_DC_TRIGGER_DEPLIST *trigdep;
10506
10507 RDLOCK_CACHE;
10508
10509 if (NULL != (trigdep = (const ZBX_DC_TRIGGER_DEPLIST *)zbx_hashset_search(&config->trigdeps, &triggerid)))
10510 ret = DCconfig_check_trigger_dependencies_rec(trigdep, 0, NULL, NULL);
10511
10512 UNLOCK_CACHE;
10513
10514 return ret;
10515 }
10516
10517 /******************************************************************************
10518 * *
10519 * Comments: helper function for DCconfig_sort_triggers_topologically() *
10520 * *
10521 ******************************************************************************/
DCconfig_sort_triggers_topologically_rec(const ZBX_DC_TRIGGER_DEPLIST * trigdep,int level)10522 static unsigned char DCconfig_sort_triggers_topologically_rec(const ZBX_DC_TRIGGER_DEPLIST *trigdep, int level)
10523 {
10524 int i;
10525 unsigned char topoindex = 2, next_topoindex;
10526 const ZBX_DC_TRIGGER_DEPLIST *next_trigdep;
10527
10528 if (32 < level)
10529 {
10530 zabbix_log(LOG_LEVEL_CRIT, "recursive trigger dependency is too deep (triggerid:" ZBX_FS_UI64 ")",
10531 trigdep->triggerid);
10532 goto exit;
10533 }
10534
10535 if (0 == trigdep->trigger->topoindex)
10536 {
10537 zabbix_log(LOG_LEVEL_CRIT, "trigger dependencies contain a cycle (triggerid:" ZBX_FS_UI64 ")",
10538 trigdep->triggerid);
10539 goto exit;
10540 }
10541
10542 trigdep->trigger->topoindex = 0;
10543
10544 for (i = 0; i < trigdep->dependencies.values_num; i++)
10545 {
10546 next_trigdep = (const ZBX_DC_TRIGGER_DEPLIST *)trigdep->dependencies.values[i];
10547
10548 if (1 < (next_topoindex = next_trigdep->trigger->topoindex))
10549 goto next;
10550
10551 if (0 == next_trigdep->dependencies.values_num)
10552 continue;
10553
10554 next_topoindex = DCconfig_sort_triggers_topologically_rec(next_trigdep, level + 1);
10555 next:
10556 if (topoindex < next_topoindex + 1)
10557 topoindex = next_topoindex + 1;
10558 }
10559
10560 trigdep->trigger->topoindex = topoindex;
10561 exit:
10562 return topoindex;
10563 }
10564
10565 /******************************************************************************
10566 * *
10567 * Function: DCconfig_sort_triggers_topologically *
10568 * *
10569 * Purpose: assign each trigger an index based on trigger dependency topology *
10570 * *
10571 * Author: Aleksandrs Saveljevs *
10572 * *
10573 ******************************************************************************/
DCconfig_sort_triggers_topologically(void)10574 static void DCconfig_sort_triggers_topologically(void)
10575 {
10576 zbx_hashset_iter_t iter;
10577 ZBX_DC_TRIGGER *trigger;
10578 const ZBX_DC_TRIGGER_DEPLIST *trigdep;
10579
10580 zbx_hashset_iter_reset(&config->trigdeps, &iter);
10581
10582 while (NULL != (trigdep = (ZBX_DC_TRIGGER_DEPLIST *)zbx_hashset_iter_next(&iter)))
10583 {
10584 trigger = trigdep->trigger;
10585
10586 if (NULL == trigger || 1 < trigger->topoindex || 0 == trigdep->dependencies.values_num)
10587 continue;
10588
10589 DCconfig_sort_triggers_topologically_rec(trigdep, 0);
10590 }
10591 }
10592
10593 /******************************************************************************
10594 * *
10595 * Function: DCconfig_triggers_apply_changes *
10596 * *
10597 * Purpose: apply trigger value,state,lastchange or error changes to *
10598 * configuration cache after committed to database *
10599 * *
10600 ******************************************************************************/
DCconfig_triggers_apply_changes(zbx_vector_ptr_t * trigger_diff)10601 void DCconfig_triggers_apply_changes(zbx_vector_ptr_t *trigger_diff)
10602 {
10603 int i;
10604 zbx_trigger_diff_t *diff;
10605 ZBX_DC_TRIGGER *dc_trigger;
10606
10607 if (0 == trigger_diff->values_num)
10608 return;
10609
10610 WRLOCK_CACHE;
10611
10612 for (i = 0; i < trigger_diff->values_num; i++)
10613 {
10614 diff = (zbx_trigger_diff_t *)trigger_diff->values[i];
10615
10616 if (NULL == (dc_trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &diff->triggerid)))
10617 continue;
10618
10619 if (0 != (diff->flags & ZBX_FLAGS_TRIGGER_DIFF_UPDATE_LASTCHANGE))
10620 dc_trigger->lastchange = diff->lastchange;
10621
10622 if (0 != (diff->flags & ZBX_FLAGS_TRIGGER_DIFF_UPDATE_VALUE))
10623 dc_trigger->value = diff->value;
10624
10625 if (0 != (diff->flags & ZBX_FLAGS_TRIGGER_DIFF_UPDATE_STATE))
10626 dc_trigger->state = diff->state;
10627
10628 if (0 != (diff->flags & ZBX_FLAGS_TRIGGER_DIFF_UPDATE_ERROR))
10629 DCstrpool_replace(1, &dc_trigger->error, diff->error);
10630 }
10631
10632 UNLOCK_CACHE;
10633 }
10634
10635 /******************************************************************************
10636 * *
10637 * Function: DCconfig_get_stats *
10638 * *
10639 * Purpose: get statistics of the database cache *
10640 * *
10641 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
10642 * *
10643 ******************************************************************************/
DCconfig_get_stats(int request)10644 void *DCconfig_get_stats(int request)
10645 {
10646 static zbx_uint64_t value_uint;
10647 static double value_double;
10648
10649 switch (request)
10650 {
10651 case ZBX_CONFSTATS_BUFFER_TOTAL:
10652 value_uint = config_mem->orig_size;
10653 return &value_uint;
10654 case ZBX_CONFSTATS_BUFFER_USED:
10655 value_uint = config_mem->orig_size - config_mem->free_size;
10656 return &value_uint;
10657 case ZBX_CONFSTATS_BUFFER_FREE:
10658 value_uint = config_mem->free_size;
10659 return &value_uint;
10660 case ZBX_CONFSTATS_BUFFER_PUSED:
10661 value_double = 100 * (double)(config_mem->orig_size - config_mem->free_size) /
10662 config_mem->orig_size;
10663 return &value_double;
10664 case ZBX_CONFSTATS_BUFFER_PFREE:
10665 value_double = 100 * (double)config_mem->free_size / config_mem->orig_size;
10666 return &value_double;
10667 default:
10668 return NULL;
10669 }
10670 }
10671
DCget_proxy(DC_PROXY * dst_proxy,const ZBX_DC_PROXY * src_proxy)10672 static void DCget_proxy(DC_PROXY *dst_proxy, const ZBX_DC_PROXY *src_proxy)
10673 {
10674 const ZBX_DC_HOST *host;
10675 ZBX_DC_INTERFACE_HT *interface_ht, interface_ht_local;
10676
10677 dst_proxy->hostid = src_proxy->hostid;
10678 dst_proxy->proxy_config_nextcheck = src_proxy->proxy_config_nextcheck;
10679 dst_proxy->proxy_data_nextcheck = src_proxy->proxy_data_nextcheck;
10680 dst_proxy->proxy_tasks_nextcheck = src_proxy->proxy_tasks_nextcheck;
10681 dst_proxy->last_cfg_error_time = src_proxy->last_cfg_error_time;
10682 dst_proxy->version = src_proxy->version;
10683 dst_proxy->lastaccess = src_proxy->lastaccess;
10684 dst_proxy->auto_compress = src_proxy->auto_compress;
10685 dst_proxy->last_version_error_time = src_proxy->last_version_error_time;
10686
10687 if (NULL != (host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &src_proxy->hostid)))
10688 {
10689 strscpy(dst_proxy->host, host->host);
10690 strscpy(dst_proxy->proxy_address, src_proxy->proxy_address);
10691
10692 dst_proxy->tls_connect = host->tls_connect;
10693 dst_proxy->tls_accept = host->tls_accept;
10694 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
10695 strscpy(dst_proxy->tls_issuer, host->tls_issuer);
10696 strscpy(dst_proxy->tls_subject, host->tls_subject);
10697
10698 if (NULL == host->tls_dc_psk)
10699 {
10700 *dst_proxy->tls_psk_identity = '\0';
10701 *dst_proxy->tls_psk = '\0';
10702 }
10703 else
10704 {
10705 strscpy(dst_proxy->tls_psk_identity, host->tls_dc_psk->tls_psk_identity);
10706 strscpy(dst_proxy->tls_psk, host->tls_dc_psk->tls_psk);
10707 }
10708 #endif
10709 }
10710 else
10711 {
10712 /* DCget_proxy() is called only from DCconfig_get_proxypoller_hosts(), which is called only from */
10713 /* process_proxy(). So, this branch should never happen. */
10714 *dst_proxy->host = '\0';
10715 *dst_proxy->proxy_address = '\0';
10716 dst_proxy->tls_connect = ZBX_TCP_SEC_TLS_PSK; /* set PSK to deliberately fail in this case */
10717 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
10718 *dst_proxy->tls_psk_identity = '\0';
10719 *dst_proxy->tls_psk = '\0';
10720 #endif
10721 THIS_SHOULD_NEVER_HAPPEN;
10722 }
10723
10724 interface_ht_local.hostid = src_proxy->hostid;
10725 interface_ht_local.type = INTERFACE_TYPE_UNKNOWN;
10726
10727 if (NULL != (interface_ht = (ZBX_DC_INTERFACE_HT *)zbx_hashset_search(&config->interfaces_ht, &interface_ht_local)))
10728 {
10729 const ZBX_DC_INTERFACE *interface = interface_ht->interface_ptr;
10730
10731 strscpy(dst_proxy->addr_orig, interface->useip ? interface->ip : interface->dns);
10732 strscpy(dst_proxy->port_orig, interface->port);
10733 }
10734 else
10735 {
10736 *dst_proxy->addr_orig = '\0';
10737 *dst_proxy->port_orig = '\0';
10738 }
10739
10740 dst_proxy->addr = NULL;
10741 dst_proxy->port = 0;
10742 }
10743
DCconfig_get_last_sync_time(void)10744 int DCconfig_get_last_sync_time(void)
10745 {
10746 return config->sync_ts;
10747 }
10748
DCconfig_wait_sync(void)10749 void DCconfig_wait_sync(void)
10750 {
10751 struct timespec ts = {0, 1e8};
10752
10753 while (0 == config->sync_ts)
10754 nanosleep(&ts, NULL);
10755 }
10756
10757 /******************************************************************************
10758 * *
10759 * Function: DCconfig_get_proxypoller_hosts *
10760 * *
10761 * Purpose: Get array of proxies for proxy poller *
10762 * *
10763 * Parameters: hosts - [OUT] array of hosts *
10764 * max_hosts - [IN] elements in hosts array *
10765 * *
10766 * Return value: number of proxies in hosts array *
10767 * *
10768 * Author: Alexander Vladishev *
10769 * *
10770 * Comments: Proxies leave the queue only through this function. Pollers must *
10771 * always return the proxies they have taken using DCrequeue_proxy. *
10772 * *
10773 ******************************************************************************/
DCconfig_get_proxypoller_hosts(DC_PROXY * proxies,int max_hosts)10774 int DCconfig_get_proxypoller_hosts(DC_PROXY *proxies, int max_hosts)
10775 {
10776 int now, num = 0;
10777 zbx_binary_heap_t *queue;
10778
10779 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
10780
10781 now = time(NULL);
10782
10783 queue = &config->pqueue;
10784
10785 WRLOCK_CACHE;
10786
10787 while (num < max_hosts && FAIL == zbx_binary_heap_empty(queue))
10788 {
10789 const zbx_binary_heap_elem_t *min;
10790 ZBX_DC_PROXY *dc_proxy;
10791
10792 min = zbx_binary_heap_find_min(queue);
10793 dc_proxy = (ZBX_DC_PROXY *)min->data;
10794
10795 if (dc_proxy->nextcheck > now)
10796 break;
10797
10798 zbx_binary_heap_remove_min(queue);
10799 dc_proxy->location = ZBX_LOC_POLLER;
10800
10801 DCget_proxy(&proxies[num], dc_proxy);
10802 num++;
10803 }
10804
10805 UNLOCK_CACHE;
10806
10807 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __func__, num);
10808
10809 return num;
10810 }
10811
10812 /******************************************************************************
10813 * *
10814 * Function: DCconfig_get_proxypoller_nextcheck *
10815 * *
10816 * Purpose: Get nextcheck for passive proxies *
10817 * *
10818 * Return value: nextcheck or FAIL if no passive proxies in queue *
10819 * *
10820 * Author: Alexander Vladishev *
10821 * *
10822 ******************************************************************************/
DCconfig_get_proxypoller_nextcheck(void)10823 int DCconfig_get_proxypoller_nextcheck(void)
10824 {
10825 int nextcheck;
10826 zbx_binary_heap_t *queue;
10827
10828 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
10829
10830 queue = &config->pqueue;
10831
10832 RDLOCK_CACHE;
10833
10834 if (FAIL == zbx_binary_heap_empty(queue))
10835 {
10836 const zbx_binary_heap_elem_t *min;
10837 const ZBX_DC_PROXY *dc_proxy;
10838
10839 min = zbx_binary_heap_find_min(queue);
10840 dc_proxy = (const ZBX_DC_PROXY *)min->data;
10841
10842 nextcheck = dc_proxy->nextcheck;
10843 }
10844 else
10845 nextcheck = FAIL;
10846
10847 UNLOCK_CACHE;
10848
10849 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __func__, nextcheck);
10850
10851 return nextcheck;
10852 }
10853
DCrequeue_proxy(zbx_uint64_t hostid,unsigned char update_nextcheck,int proxy_conn_err)10854 void DCrequeue_proxy(zbx_uint64_t hostid, unsigned char update_nextcheck, int proxy_conn_err)
10855 {
10856 time_t now;
10857 ZBX_DC_HOST *dc_host;
10858 ZBX_DC_PROXY *dc_proxy;
10859
10860 zabbix_log(LOG_LEVEL_DEBUG, "In %s() update_nextcheck:%d", __func__, (int)update_nextcheck);
10861
10862 now = time(NULL);
10863
10864 WRLOCK_CACHE;
10865
10866 if (NULL != (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)) &&
10867 NULL != (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &hostid)))
10868 {
10869 if (ZBX_LOC_POLLER == dc_proxy->location)
10870 dc_proxy->location = ZBX_LOC_NOWHERE;
10871
10872 /* set or clear passive proxy misconfiguration error timestamp */
10873 if (SUCCEED == proxy_conn_err)
10874 dc_proxy->last_cfg_error_time = 0;
10875 else if (CONFIG_ERROR == proxy_conn_err)
10876 dc_proxy->last_cfg_error_time = (int)now;
10877
10878 if (HOST_STATUS_PROXY_PASSIVE == dc_host->status)
10879 {
10880 if (0 != (update_nextcheck & ZBX_PROXY_CONFIG_NEXTCHECK))
10881 {
10882 dc_proxy->proxy_config_nextcheck = (int)calculate_proxy_nextcheck(
10883 hostid, CONFIG_PROXYCONFIG_FREQUENCY, now);
10884 }
10885
10886 if (0 != (update_nextcheck & ZBX_PROXY_DATA_NEXTCHECK))
10887 {
10888 dc_proxy->proxy_data_nextcheck = (int)calculate_proxy_nextcheck(
10889 hostid, CONFIG_PROXYDATA_FREQUENCY, now);
10890 }
10891 if (0 != (update_nextcheck & ZBX_PROXY_TASKS_NEXTCHECK))
10892 {
10893 dc_proxy->proxy_tasks_nextcheck = (int)calculate_proxy_nextcheck(
10894 hostid, ZBX_TASK_UPDATE_FREQUENCY, now);
10895 }
10896
10897 DCupdate_proxy_queue(dc_proxy);
10898 }
10899 }
10900
10901 UNLOCK_CACHE;
10902
10903 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
10904 }
10905
dc_get_host_macro_value(const ZBX_DC_HMACRO * macro,char ** value)10906 static void dc_get_host_macro_value(const ZBX_DC_HMACRO *macro, char **value)
10907 {
10908 if (ZBX_MACRO_ENV_NONSECURE == macro_env && (ZBX_MACRO_VALUE_SECRET == macro->type ||
10909 ZBX_MACRO_VALUE_VAULT == macro->type))
10910 {
10911 *value = zbx_strdup(*value, ZBX_MACRO_SECRET_MASK);
10912 }
10913 else if (ZBX_MACRO_VALUE_VAULT == macro->type)
10914 {
10915 if (NULL == macro->kv->value)
10916 *value = zbx_strdup(*value, ZBX_MACRO_SECRET_MASK);
10917 else
10918 *value = zbx_strdup(*value, macro->kv->value);
10919 }
10920 else
10921 *value = zbx_strdup(*value, macro->value);
10922 }
10923
dc_match_macro_context(const char * context,const char * pattern,unsigned char op)10924 static int dc_match_macro_context(const char *context, const char *pattern, unsigned char op)
10925 {
10926 switch (op)
10927 {
10928 case CONDITION_OPERATOR_EQUAL:
10929 return 0 == zbx_strcmp_null(context, pattern) ? SUCCEED : FAIL;
10930 case CONDITION_OPERATOR_REGEXP:
10931 if (NULL == context)
10932 return FAIL;
10933 return NULL != zbx_regexp_match(context, pattern, NULL) ? SUCCEED : FAIL;
10934 default:
10935 THIS_SHOULD_NEVER_HAPPEN;
10936 return FAIL;
10937 }
10938 }
10939
dc_get_host_macro(const zbx_uint64_t * hostids,int host_num,const char * macro,const char * context,char ** value,char ** value_default)10940 static void dc_get_host_macro(const zbx_uint64_t *hostids, int host_num, const char *macro, const char *context,
10941 char **value, char **value_default)
10942 {
10943 int i, j;
10944 const ZBX_DC_HMACRO_HM *hmacro_hm;
10945 ZBX_DC_HMACRO_HM hmacro_hm_local;
10946 const ZBX_DC_HTMPL *htmpl;
10947 zbx_vector_uint64_t templateids;
10948 const ZBX_DC_HMACRO *hmacro;
10949
10950 if (0 == host_num)
10951 return;
10952
10953 hmacro_hm_local.macro = macro;
10954
10955 for (i = 0; i < host_num; i++)
10956 {
10957 hmacro_hm_local.hostid = hostids[i];
10958
10959 if (NULL != (hmacro_hm = (const ZBX_DC_HMACRO_HM *)zbx_hashset_search(&config->hmacros_hm, &hmacro_hm_local)))
10960 {
10961 for (j = 0; j < hmacro_hm->hmacros.values_num; j++)
10962 {
10963 hmacro = (const ZBX_DC_HMACRO *)hmacro_hm->hmacros.values[j];
10964
10965 if (SUCCEED == dc_match_macro_context(context, hmacro->context, hmacro->context_op))
10966 {
10967 dc_get_host_macro_value(hmacro, value);
10968 return;
10969 }
10970 }
10971 /* Check for the default (without context) macro value. If macro has a value without */
10972 /* context it will be the first element in the macro index vector. */
10973 hmacro = (const ZBX_DC_HMACRO *)hmacro_hm->hmacros.values[0];
10974 if (NULL == *value_default && NULL != context && NULL == hmacro->context)
10975 dc_get_host_macro_value(hmacro, value_default);
10976 }
10977 }
10978
10979 zbx_vector_uint64_create(&templateids);
10980 zbx_vector_uint64_reserve(&templateids, 32);
10981
10982 for (i = 0; i < host_num; i++)
10983 {
10984 if (NULL != (htmpl = (const ZBX_DC_HTMPL *)zbx_hashset_search(&config->htmpls, &hostids[i])))
10985 {
10986 for (j = 0; j < htmpl->templateids.values_num; j++)
10987 zbx_vector_uint64_append(&templateids, htmpl->templateids.values[j]);
10988 }
10989 }
10990
10991 if (0 != templateids.values_num)
10992 {
10993 zbx_vector_uint64_sort(&templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
10994 dc_get_host_macro(templateids.values, templateids.values_num, macro, context, value, value_default);
10995 }
10996
10997 zbx_vector_uint64_destroy(&templateids);
10998 }
10999
dc_get_global_macro_value(const ZBX_DC_GMACRO * macro,char ** value)11000 static void dc_get_global_macro_value(const ZBX_DC_GMACRO *macro, char **value)
11001 {
11002 if (ZBX_MACRO_ENV_NONSECURE == macro_env && (ZBX_MACRO_VALUE_SECRET == macro->type ||
11003 ZBX_MACRO_VALUE_VAULT == macro->type))
11004 {
11005 *value = zbx_strdup(*value, ZBX_MACRO_SECRET_MASK);
11006 }
11007 else if (ZBX_MACRO_VALUE_VAULT == macro->type)
11008 {
11009 if (NULL == macro->kv->value)
11010 *value = zbx_strdup(*value, ZBX_MACRO_SECRET_MASK);
11011 else
11012 *value = zbx_strdup(*value, macro->kv->value);
11013 }
11014 else
11015 *value = zbx_strdup(*value, macro->value);
11016 }
11017
dc_get_global_macro(const char * macro,const char * context,char ** value,char ** value_default)11018 static void dc_get_global_macro(const char *macro, const char *context, char **value, char **value_default)
11019 {
11020 int i;
11021 const ZBX_DC_GMACRO_M *gmacro_m;
11022 ZBX_DC_GMACRO_M gmacro_m_local;
11023 const ZBX_DC_GMACRO *gmacro;
11024
11025 gmacro_m_local.macro = macro;
11026
11027 if (NULL != (gmacro_m = (const ZBX_DC_GMACRO_M *)zbx_hashset_search(&config->gmacros_m, &gmacro_m_local)))
11028 {
11029 for (i = 0; i < gmacro_m->gmacros.values_num; i++)
11030 {
11031 gmacro = (const ZBX_DC_GMACRO *)gmacro_m->gmacros.values[i];
11032
11033 if (SUCCEED == dc_match_macro_context(context, gmacro->context, gmacro->context_op))
11034 {
11035 dc_get_global_macro_value(gmacro, value);
11036 break;
11037 }
11038 }
11039
11040 /* Check for the default (without context) macro value. If macro has a value without */
11041 /* context it will be the first element in the macro index vector. */
11042 gmacro = (const ZBX_DC_GMACRO *)gmacro_m->gmacros.values[0];
11043 if (NULL == *value_default && NULL != context && NULL == gmacro->context)
11044 dc_get_global_macro_value(gmacro, value_default);
11045 }
11046 }
11047
dc_get_user_macro(const zbx_uint64_t * hostids,int hostids_num,const char * macro,const char * context,char ** replace_to)11048 static void dc_get_user_macro(const zbx_uint64_t *hostids, int hostids_num, const char *macro, const char *context,
11049 char **replace_to)
11050 {
11051 char *value = NULL, *value_default = NULL;
11052
11053 /* User macros should be expanded according to the following priority: */
11054 /* */
11055 /* 1) host context macro */
11056 /* 2) global context macro */
11057 /* 3) host base (default) macro */
11058 /* 4) global base (default) macro */
11059 /* */
11060 /* We try to expand host macros first. If there is no perfect match on */
11061 /* the host level, we try to expand global macros, passing the default */
11062 /* macro value found on the host level, if any. */
11063
11064 dc_get_host_macro(hostids, hostids_num, macro, context, &value, &value_default);
11065
11066 if (NULL == value)
11067 dc_get_global_macro(macro, context, &value, &value_default);
11068
11069 if (NULL != value)
11070 {
11071 zbx_free(*replace_to);
11072 *replace_to = value;
11073
11074 zbx_free(value_default);
11075 }
11076 else if (NULL != value_default)
11077 {
11078 zbx_free(*replace_to);
11079 *replace_to = value_default;
11080 }
11081 }
11082
DCget_user_macro(const zbx_uint64_t * hostids,int hostids_num,const char * macro,char ** replace_to)11083 void DCget_user_macro(const zbx_uint64_t *hostids, int hostids_num, const char *macro, char **replace_to)
11084 {
11085 char *name = NULL, *context = NULL;
11086
11087 zabbix_log(LOG_LEVEL_DEBUG, "In %s() macro:'%s'", __func__, macro);
11088
11089 if (SUCCEED != zbx_user_macro_parse_dyn(macro, &name, &context, NULL, NULL))
11090 goto out;
11091
11092 RDLOCK_CACHE;
11093
11094 dc_get_user_macro(hostids, hostids_num, name, context, replace_to);
11095
11096 UNLOCK_CACHE;
11097
11098 zbx_free(context);
11099 zbx_free(name);
11100 out:
11101 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
11102 }
11103
11104 /******************************************************************************
11105 * *
11106 * Function: dc_expand_user_macros *
11107 * *
11108 * Purpose: expand user macros in the specified text value *
11109 * *
11110 * Parameters: text - [IN] the text value to expand *
11111 * len - [IN] the text length *
11112 * hostids - [IN] an array of related hostids *
11113 * hostids_num - [IN] the number of hostids *
11114 * value - [IN] the expanded macro with expanded user *
11115 * macros. Unknown or invalid macros will be *
11116 * left unresolved. *
11117 * error - [IN] the error message, optional. If specified *
11118 * the function will return failure on first *
11119 * unknown user macro *
11120 * *
11121 * Return value: SUCCEED - the macros were expanded successfully *
11122 * FAIL - error parameter was given and at least one of *
11123 * macros was not expanded *
11124 * *
11125 * Comments: The returned value must be freed by the caller. *
11126 * *
11127 ******************************************************************************/
dc_expand_user_macros_len(const char * text,size_t text_len,zbx_uint64_t * hostids,int hostids_num,char ** value,char ** error)11128 int dc_expand_user_macros_len(const char *text, size_t text_len, zbx_uint64_t *hostids, int hostids_num,
11129 char **value, char **error)
11130 {
11131 zbx_token_t token;
11132 int len;
11133 char *str = NULL, *name = NULL, *context = NULL, *macro_value = NULL;
11134 size_t str_alloc = 0, str_offset = 0, pos = 0, last_pos = 0;
11135
11136 if ('\0' == *text)
11137 {
11138 *value = zbx_strdup(NULL, text);
11139 return SUCCEED;
11140 }
11141
11142 for (; SUCCEED == zbx_token_find(text, pos, &token, ZBX_TOKEN_SEARCH_BASIC) && token.loc.r < text_len; pos++)
11143 {
11144 if (ZBX_TOKEN_USER_MACRO != token.type)
11145 continue;
11146
11147 if (SUCCEED != zbx_user_macro_parse_dyn(text + token.loc.l, &name, &context, &len, NULL))
11148 continue;
11149
11150 if (last_pos < token.loc.l)
11151 zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + last_pos, token.loc.l - last_pos);
11152
11153 dc_get_user_macro(hostids, hostids_num, name, context, ¯o_value);
11154
11155 zbx_free(name);
11156 zbx_free(context);
11157
11158 if (NULL != macro_value)
11159 {
11160 zbx_strcpy_alloc(&str, &str_alloc, &str_offset, macro_value);
11161 zbx_free(macro_value);
11162 }
11163 else
11164 {
11165 if (NULL != error)
11166 {
11167 *error = zbx_dsprintf(NULL, "unknown user macro \"%.*s\"",
11168 (int)(token.loc.r - token.loc.l + 1), text + token.loc.l);
11169 zbx_free(str);
11170 return FAIL;
11171 }
11172 zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + token.loc.l,
11173 token.loc.r - token.loc.l + 1);
11174 }
11175
11176 pos = token.loc.r;
11177 last_pos = pos + 1;
11178 }
11179
11180 if (last_pos < text_len)
11181 zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + last_pos, text_len - last_pos);
11182
11183 *value = str;
11184
11185 return SUCCEED;
11186 }
11187
11188 /******************************************************************************
11189 * *
11190 * Function: zbx_dc_expand_user_macros_len *
11191 * *
11192 * Purpose: expand user macros in the specified text *
11193 * *
11194 * Parameters: text - [IN] the text value to expand *
11195 * len - [IN] the text length *
11196 * hostids - [IN] an array of related hostids *
11197 * hostids_num - [IN] the number of hostids *
11198 * value - [IN] the expanded macro with expanded user *
11199 * macros. Unknown or invalid macros will be *
11200 * left unresolved. *
11201 * error - [IN] the error message, optional. If specified *
11202 * the function will return failure on first *
11203 * unknown user macro *
11204 * *
11205 * Return value: SUCCEED - the macros were expanded successfully *
11206 * FAIL - error parameter was given and at least one of *
11207 * macros was not expanded *
11208 * *
11209 * Comments: The returned value must be freed by the caller. *
11210 * *
11211 ******************************************************************************/
zbx_dc_expand_user_macros_len(const char * text,size_t text_len,zbx_uint64_t * hostids,int hostids_num,char ** value,char ** error)11212 int zbx_dc_expand_user_macros_len(const char *text, size_t text_len, zbx_uint64_t *hostids, int hostids_num,
11213 char **value, char **error)
11214 {
11215 int ret;
11216
11217 RDLOCK_CACHE;
11218 ret = dc_expand_user_macros_len(text, text_len, hostids, hostids_num, value, error);
11219 UNLOCK_CACHE;
11220
11221 return ret;
11222 }
11223
11224 /******************************************************************************
11225 * *
11226 * Function: dc_expand_user_macros *
11227 * *
11228 * Purpose: expand user macros in the specified text value *
11229 * WARNING - DO NOT USE FOR TRIGGERS, for triggers use the dedicated function *
11230 * *
11231 * Parameters: text - [IN] the text value to expand *
11232 * hostids - [IN] an array of related hostids *
11233 * hostids_num - [IN] the number of hostids *
11234 * *
11235 * Return value: The text value with expanded user macros. Unknown or invalid *
11236 * macros will be left unresolved. *
11237 * *
11238 * Comments: The returned value must be freed by the caller. *
11239 * This function must be used only by configuration syncer *
11240 * *
11241 ******************************************************************************/
dc_expand_user_macros(const char * text,zbx_uint64_t * hostids,int hostids_num)11242 char *dc_expand_user_macros(const char *text, zbx_uint64_t *hostids, int hostids_num)
11243 {
11244 zbx_token_t token;
11245 int pos = 0, len, last_pos = 0;
11246 char *str = NULL, *name = NULL, *context = NULL, *value = NULL;
11247 size_t str_alloc = 0, str_offset = 0;
11248
11249 if ('\0' == *text)
11250 return zbx_strdup(NULL, text);
11251
11252 for (; SUCCEED == zbx_token_find(text, pos, &token, ZBX_TOKEN_SEARCH_BASIC); pos++)
11253 {
11254 if (ZBX_TOKEN_USER_MACRO != token.type)
11255 continue;
11256
11257 if (SUCCEED != zbx_user_macro_parse_dyn(text + token.loc.l, &name, &context, &len, NULL))
11258 continue;
11259
11260 zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + last_pos, token.loc.l - last_pos);
11261 dc_get_user_macro(hostids, hostids_num, name, context, &value);
11262
11263 if (NULL != value)
11264 {
11265 zbx_strcpy_alloc(&str, &str_alloc, &str_offset, value);
11266 zbx_free(value);
11267
11268 }
11269 else
11270 {
11271 zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + token.loc.l,
11272 token.loc.r - token.loc.l + 1);
11273 }
11274
11275 zbx_free(name);
11276 zbx_free(context);
11277
11278 pos = token.loc.r;
11279 last_pos = pos + 1;
11280 }
11281
11282 zbx_strcpy_alloc(&str, &str_alloc, &str_offset, text + last_pos);
11283
11284 return str;
11285 }
11286
11287 /******************************************************************************
11288 * *
11289 * Function: zbx_dc_expand_user_macros *
11290 * *
11291 * Purpose: expand user macros in the specified text value *
11292 * *
11293 * Parameters: text - [IN] the text value to expand *
11294 * hostid - [IN] related hostid *
11295 * *
11296 * Return value: The text value with expanded user macros. Unknown or invalid *
11297 * macros will be left unresolved. *
11298 * *
11299 * Comments: The returned value must be freed by the caller. *
11300 * *
11301 ******************************************************************************/
zbx_dc_expand_user_macros(const char * text,zbx_uint64_t hostid)11302 char *zbx_dc_expand_user_macros(const char *text, zbx_uint64_t hostid)
11303 {
11304 char *resolved_text;
11305
11306 RDLOCK_CACHE;
11307 resolved_text = dc_expand_user_macros(text, &hostid, 1);
11308 UNLOCK_CACHE;
11309
11310 return resolved_text;
11311 }
11312
11313 /******************************************************************************
11314 * *
11315 * Function: DCfree_item_queue *
11316 * *
11317 * Purpose: frees the item queue data vector created by DCget_item_queue() *
11318 * *
11319 * Parameters: queue - [IN] the item queue data vector to free *
11320 * *
11321 ******************************************************************************/
DCfree_item_queue(zbx_vector_ptr_t * queue)11322 void DCfree_item_queue(zbx_vector_ptr_t *queue)
11323 {
11324 int i;
11325
11326 for (i = 0; i < queue->values_num; i++)
11327 zbx_free(queue->values[i]);
11328 }
11329
11330 /******************************************************************************
11331 * *
11332 * Function: DCget_item_queue *
11333 * *
11334 * Purpose: retrieves vector of delayed items *
11335 * *
11336 * Parameters: queue - [OUT] the vector of delayed items (optional) *
11337 * from - [IN] the minimum delay time in seconds (non-negative) *
11338 * to - [IN] the maximum delay time in seconds or *
11339 * ZBX_QUEUE_TO_INFINITY if there is no limit *
11340 * *
11341 * Return value: the number of delayed items *
11342 * *
11343 ******************************************************************************/
DCget_item_queue(zbx_vector_ptr_t * queue,int from,int to)11344 int DCget_item_queue(zbx_vector_ptr_t *queue, int from, int to)
11345 {
11346 zbx_hashset_iter_t iter;
11347 const ZBX_DC_ITEM *dc_item;
11348 int now, nitems = 0, data_expected_from, delay;
11349 zbx_queue_item_t *queue_item;
11350
11351 now = time(NULL);
11352
11353 RDLOCK_CACHE;
11354
11355 zbx_hashset_iter_reset(&config->items, &iter);
11356
11357 while (NULL != (dc_item = (const ZBX_DC_ITEM *)zbx_hashset_iter_next(&iter)))
11358 {
11359 const ZBX_DC_HOST *dc_host;
11360 const ZBX_DC_INTERFACE *dc_interface;
11361
11362 if (ITEM_STATUS_ACTIVE != dc_item->status)
11363 continue;
11364
11365 if (SUCCEED != zbx_is_counted_in_item_queue(dc_item->type, dc_item->key))
11366 continue;
11367
11368 if (NULL == (dc_host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
11369 continue;
11370
11371 if (HOST_STATUS_MONITORED != dc_host->status)
11372 continue;
11373
11374 if (NULL == (dc_interface = (const ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces,
11375 &dc_item->interfaceid)))
11376 {
11377 continue;
11378 }
11379
11380 if (SUCCEED == DCin_maintenance_without_data_collection(dc_host, dc_item))
11381 continue;
11382
11383 switch (dc_item->type)
11384 {
11385 case ITEM_TYPE_ZABBIX:
11386 case ITEM_TYPE_SNMP:
11387 case ITEM_TYPE_IPMI:
11388 case ITEM_TYPE_JMX:
11389 if (INTERFACE_AVAILABLE_TRUE != dc_interface->available)
11390 continue;
11391 break;
11392 case ITEM_TYPE_ZABBIX_ACTIVE:
11393 if (dc_host->data_expected_from > (data_expected_from = dc_item->data_expected_from))
11394 data_expected_from = dc_host->data_expected_from;
11395 if (SUCCEED != zbx_interval_preproc(dc_item->delay, &delay, NULL, NULL))
11396 continue;
11397 if (data_expected_from + delay > now)
11398 continue;
11399 break;
11400
11401 }
11402
11403 if (now - dc_item->nextcheck < from || (ZBX_QUEUE_TO_INFINITY != to && now - dc_item->nextcheck >= to))
11404 continue;
11405
11406 if (NULL != queue)
11407 {
11408 queue_item = (zbx_queue_item_t *)zbx_malloc(NULL, sizeof(zbx_queue_item_t));
11409 queue_item->itemid = dc_item->itemid;
11410 queue_item->type = dc_item->type;
11411 queue_item->nextcheck = dc_item->nextcheck;
11412 queue_item->proxy_hostid = dc_host->proxy_hostid;
11413
11414 zbx_vector_ptr_append(queue, queue_item);
11415 }
11416 nitems++;
11417 }
11418
11419 UNLOCK_CACHE;
11420
11421 return nitems;
11422 }
11423
11424 /******************************************************************************
11425 * *
11426 * Function: dc_trigger_items_hosts_enabled *
11427 * *
11428 * Purpose: check that functionids in trigger (recovery) expression *
11429 * *
11430 * Parameters: expression - [IN] trigger (recovery) expression *
11431 * data - [IN] parsed and serialized expression *
11432 * *
11433 * Return value: SUCCEED - all functionids correspond to enabled items and *
11434 * enabled hosts *
11435 * FAIL - at least one item or host is disabled *
11436 * *
11437 ******************************************************************************/
dc_trigger_items_hosts_enabled(const char * expression,const unsigned char * data)11438 static int dc_trigger_items_hosts_enabled(const char *expression, const unsigned char *data)
11439 {
11440 zbx_uint64_t functionid;
11441 const ZBX_DC_ITEM *dc_item;
11442 const ZBX_DC_FUNCTION *dc_function;
11443 const ZBX_DC_HOST *dc_host;
11444 int i, ret = FAIL;
11445 zbx_vector_uint64_t functionids;
11446
11447 zbx_vector_uint64_create(&functionids);
11448 zbx_get_serialized_expression_functionids(expression, data, &functionids);
11449
11450 for (i = 0; i < functionids.values_num; i++)
11451 {
11452 functionid = functionids.values[i];
11453
11454 if (NULL == (dc_function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &functionid)))
11455 goto out;
11456
11457 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &dc_function->itemid)))
11458 goto out;
11459
11460 if (ITEM_STATUS_ACTIVE != dc_item->status)
11461 goto out;
11462
11463 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
11464 goto out;
11465
11466 if (HOST_STATUS_MONITORED != dc_host->status)
11467 goto out;
11468 }
11469
11470 ret = SUCCEED;
11471 out:
11472 zbx_vector_uint64_destroy(&functionids);
11473
11474 return ret;
11475 }
11476
11477 /******************************************************************************
11478 * *
11479 * Function: dc_status_update *
11480 * *
11481 * Purpose: check when status information stored in configuration cache was *
11482 * updated last time and update it if necessary *
11483 * *
11484 * Comments: This function gathers the following information: *
11485 * - number of enabled hosts (total and per proxy) *
11486 * - number of disabled hosts (total and per proxy) *
11487 * - number of enabled and supported items (total, per host and *
11488 * per proxy) *
11489 * - number of enabled and not supported items (total, per host *
11490 * and per proxy) *
11491 * - number of disabled items (total and per proxy) *
11492 * - number of enabled triggers with value OK *
11493 * - number of enabled triggers with value PROBLEM *
11494 * - number of disabled triggers *
11495 * - required performance (total and per proxy) *
11496 * Gathered information can then be displayed in the frontend (see *
11497 * "status.get" request) and used in calculation of zabbix[] items. *
11498 * *
11499 * NOTE: Always call this function before accessing information stored in *
11500 * config->status as well as host and required performance counters *
11501 * stored in elements of config->proxies and item counters in elements *
11502 * of config->hosts. *
11503 * *
11504 ******************************************************************************/
dc_status_update(void)11505 static void dc_status_update(void)
11506 {
11507 #define ZBX_STATUS_LIFETIME SEC_PER_MIN
11508
11509 zbx_hashset_iter_t iter;
11510 ZBX_DC_PROXY *dc_proxy;
11511 ZBX_DC_HOST *dc_host, *dc_proxy_host;
11512 const ZBX_DC_ITEM *dc_item;
11513 const ZBX_DC_TRIGGER *dc_trigger;
11514
11515 if (0 != config->status->last_update && config->status->last_update + ZBX_STATUS_LIFETIME > time(NULL))
11516 return;
11517
11518 /* reset global counters */
11519
11520 config->status->hosts_monitored = 0;
11521 config->status->hosts_not_monitored = 0;
11522 config->status->items_active_normal = 0;
11523 config->status->items_active_notsupported = 0;
11524 config->status->items_disabled = 0;
11525 config->status->triggers_enabled_ok = 0;
11526 config->status->triggers_enabled_problem = 0;
11527 config->status->triggers_disabled = 0;
11528 config->status->required_performance = 0.0;
11529
11530 /* loop over proxies to reset per-proxy host and required performance counters */
11531
11532 zbx_hashset_iter_reset(&config->proxies, &iter);
11533
11534 while (NULL != (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_iter_next(&iter)))
11535 {
11536 dc_proxy->hosts_monitored = 0;
11537 dc_proxy->hosts_not_monitored = 0;
11538 dc_proxy->required_performance = 0.0;
11539 }
11540
11541 /* loop over hosts */
11542
11543 zbx_hashset_iter_reset(&config->hosts, &iter);
11544
11545 while (NULL != (dc_host = (ZBX_DC_HOST *)zbx_hashset_iter_next(&iter)))
11546 {
11547 /* reset per-host/per-proxy item counters */
11548
11549 dc_host->items_active_normal = 0;
11550 dc_host->items_active_notsupported = 0;
11551 dc_host->items_disabled = 0;
11552
11553 /* gather per-proxy statistics of enabled and disabled hosts */
11554 switch (dc_host->status)
11555 {
11556 case HOST_STATUS_MONITORED:
11557 config->status->hosts_monitored++;
11558 if (0 == dc_host->proxy_hostid)
11559 break;
11560 if (NULL == (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &dc_host->proxy_hostid)))
11561 break;
11562 dc_proxy->hosts_monitored++;
11563 break;
11564 case HOST_STATUS_NOT_MONITORED:
11565 config->status->hosts_not_monitored++;
11566 if (0 == dc_host->proxy_hostid)
11567 break;
11568 if (NULL == (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &dc_host->proxy_hostid)))
11569 break;
11570 dc_proxy->hosts_not_monitored++;
11571 break;
11572 }
11573 }
11574
11575 /* loop over items to gather per-host and per-proxy statistics */
11576
11577 zbx_hashset_iter_reset(&config->items, &iter);
11578
11579 while (NULL != (dc_item = (ZBX_DC_ITEM *)zbx_hashset_iter_next(&iter)))
11580 {
11581 dc_proxy = NULL;
11582 dc_proxy_host = NULL;
11583
11584 if (ZBX_FLAG_DISCOVERY_NORMAL != dc_item->flags && ZBX_FLAG_DISCOVERY_CREATED != dc_item->flags)
11585 continue;
11586
11587 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
11588 continue;
11589
11590 if (0 != dc_host->proxy_hostid)
11591 {
11592 dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &dc_host->proxy_hostid);
11593 dc_proxy_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_host->proxy_hostid);
11594 }
11595
11596 switch (dc_item->status)
11597 {
11598 case ITEM_STATUS_ACTIVE:
11599 if (HOST_STATUS_MONITORED == dc_host->status)
11600 {
11601 int delay;
11602
11603 if (SUCCEED == zbx_interval_preproc(dc_item->delay, &delay, NULL, NULL) &&
11604 0 != delay)
11605 {
11606 config->status->required_performance += 1.0 / delay;
11607
11608 if (NULL != dc_proxy)
11609 dc_proxy->required_performance += 1.0 / delay;
11610 }
11611
11612 switch (dc_item->state)
11613 {
11614 case ITEM_STATE_NORMAL:
11615 config->status->items_active_normal++;
11616 dc_host->items_active_normal++;
11617 if (NULL != dc_proxy_host)
11618 dc_proxy_host->items_active_normal++;
11619 break;
11620 case ITEM_STATE_NOTSUPPORTED:
11621 config->status->items_active_notsupported++;
11622 dc_host->items_active_notsupported++;
11623 if (NULL != dc_proxy_host)
11624 dc_proxy_host->items_active_notsupported++;
11625 break;
11626 default:
11627 THIS_SHOULD_NEVER_HAPPEN;
11628 }
11629
11630 break;
11631 }
11632 ZBX_FALLTHROUGH;
11633 case ITEM_STATUS_DISABLED:
11634 config->status->items_disabled++;
11635 if (NULL != dc_proxy_host)
11636 dc_proxy_host->items_disabled++;
11637 break;
11638 default:
11639 THIS_SHOULD_NEVER_HAPPEN;
11640 }
11641 }
11642
11643 /* loop over triggers to gather enabled and disabled trigger statistics */
11644
11645 zbx_hashset_iter_reset(&config->triggers, &iter);
11646
11647 while (NULL != (dc_trigger = (ZBX_DC_TRIGGER *)zbx_hashset_iter_next(&iter)))
11648 {
11649 switch (dc_trigger->status)
11650 {
11651 case TRIGGER_STATUS_ENABLED:
11652 if (SUCCEED == dc_trigger_items_hosts_enabled(dc_trigger->expression,
11653 dc_trigger->expression_bin) &&
11654 (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION != dc_trigger->recovery_mode ||
11655 SUCCEED == dc_trigger_items_hosts_enabled(dc_trigger->recovery_expression,
11656 dc_trigger->recovery_expression_bin)))
11657 {
11658 switch (dc_trigger->value)
11659 {
11660 case TRIGGER_VALUE_OK:
11661 config->status->triggers_enabled_ok++;
11662 break;
11663 case TRIGGER_VALUE_PROBLEM:
11664 config->status->triggers_enabled_problem++;
11665 break;
11666 default:
11667 THIS_SHOULD_NEVER_HAPPEN;
11668 }
11669
11670 break;
11671 }
11672 ZBX_FALLTHROUGH;
11673 case TRIGGER_STATUS_DISABLED:
11674 config->status->triggers_disabled++;
11675 break;
11676 default:
11677 THIS_SHOULD_NEVER_HAPPEN;
11678 }
11679 }
11680
11681 config->status->last_update = time(NULL);
11682
11683 #undef ZBX_STATUS_LIFETIME
11684 }
11685
11686 /******************************************************************************
11687 * *
11688 * Function: DCget_item_count *
11689 * *
11690 * Purpose: return the number of active items *
11691 * *
11692 * Parameters: hostid - [IN] the host id, pass 0 to specify all hosts *
11693 * *
11694 * Return value: the number of active items *
11695 * *
11696 ******************************************************************************/
DCget_item_count(zbx_uint64_t hostid)11697 zbx_uint64_t DCget_item_count(zbx_uint64_t hostid)
11698 {
11699 zbx_uint64_t count;
11700 const ZBX_DC_HOST *dc_host;
11701
11702 WRLOCK_CACHE;
11703
11704 dc_status_update();
11705
11706 if (0 == hostid)
11707 count = config->status->items_active_normal + config->status->items_active_notsupported;
11708 else if (NULL != (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)))
11709 count = dc_host->items_active_normal + dc_host->items_active_notsupported;
11710 else
11711 count = 0;
11712
11713 UNLOCK_CACHE;
11714
11715 return count;
11716 }
11717
11718 /******************************************************************************
11719 * *
11720 * Function: DCget_item_unsupported_count *
11721 * *
11722 * Purpose: return the number of active unsupported items *
11723 * *
11724 * Parameters: hostid - [IN] the host id, pass 0 to specify all hosts *
11725 * *
11726 * Return value: the number of active unsupported items *
11727 * *
11728 ******************************************************************************/
DCget_item_unsupported_count(zbx_uint64_t hostid)11729 zbx_uint64_t DCget_item_unsupported_count(zbx_uint64_t hostid)
11730 {
11731 zbx_uint64_t count;
11732 const ZBX_DC_HOST *dc_host;
11733
11734 WRLOCK_CACHE;
11735
11736 dc_status_update();
11737
11738 if (0 == hostid)
11739 count = config->status->items_active_notsupported;
11740 else if (NULL != (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)))
11741 count = dc_host->items_active_notsupported;
11742 else
11743 count = 0;
11744
11745 UNLOCK_CACHE;
11746
11747 return count;
11748 }
11749
11750 /******************************************************************************
11751 * *
11752 * Function: DCget_trigger_count *
11753 * *
11754 * Purpose: count active triggers *
11755 * *
11756 ******************************************************************************/
DCget_trigger_count(void)11757 zbx_uint64_t DCget_trigger_count(void)
11758 {
11759 zbx_uint64_t count;
11760
11761 WRLOCK_CACHE;
11762
11763 dc_status_update();
11764
11765 count = config->status->triggers_enabled_ok + config->status->triggers_enabled_problem;
11766
11767 UNLOCK_CACHE;
11768
11769 return count;
11770 }
11771
11772 /******************************************************************************
11773 * *
11774 * Function: DCget_host_count *
11775 * *
11776 * Purpose: count monitored and not monitored hosts *
11777 * *
11778 ******************************************************************************/
DCget_host_count(void)11779 zbx_uint64_t DCget_host_count(void)
11780 {
11781 zbx_uint64_t nhosts;
11782
11783 WRLOCK_CACHE;
11784
11785 dc_status_update();
11786
11787 nhosts = config->status->hosts_monitored;
11788
11789 UNLOCK_CACHE;
11790
11791 return nhosts;
11792 }
11793
11794 /******************************************************************************
11795 * *
11796 * Function: DCget_required_performance *
11797 * *
11798 * Return value: the required nvps number *
11799 * *
11800 ******************************************************************************/
DCget_required_performance(void)11801 double DCget_required_performance(void)
11802 {
11803 double nvps;
11804
11805 WRLOCK_CACHE;
11806
11807 dc_status_update();
11808
11809 nvps = config->status->required_performance;
11810
11811 UNLOCK_CACHE;
11812
11813 return nvps;
11814 }
11815
11816 /******************************************************************************
11817 * *
11818 * Function: DCget_count_stats_all *
11819 * *
11820 * Purpose: retrieves all internal metrics of the configuration cache *
11821 * *
11822 * Parameters: stats - [OUT] the configuration cache statistics *
11823 * *
11824 ******************************************************************************/
DCget_count_stats_all(zbx_config_cache_info_t * stats)11825 void DCget_count_stats_all(zbx_config_cache_info_t *stats)
11826 {
11827 WRLOCK_CACHE;
11828
11829 dc_status_update();
11830
11831 stats->hosts = config->status->hosts_monitored;
11832 stats->items = config->status->items_active_normal + config->status->items_active_notsupported;
11833 stats->items_unsupported = config->status->items_active_notsupported;
11834 stats->requiredperformance = config->status->required_performance;
11835
11836 UNLOCK_CACHE;
11837 }
11838
proxy_counter_ui64_push(zbx_vector_ptr_t * vector,zbx_uint64_t proxyid,zbx_uint64_t counter)11839 static void proxy_counter_ui64_push(zbx_vector_ptr_t *vector, zbx_uint64_t proxyid, zbx_uint64_t counter)
11840 {
11841 zbx_proxy_counter_t *proxy_counter;
11842
11843 proxy_counter = (zbx_proxy_counter_t *)zbx_malloc(NULL, sizeof(zbx_proxy_counter_t));
11844 proxy_counter->proxyid = proxyid;
11845 proxy_counter->counter_value.ui64 = counter;
11846 zbx_vector_ptr_append(vector, proxy_counter);
11847 }
11848
proxy_counter_dbl_push(zbx_vector_ptr_t * vector,zbx_uint64_t proxyid,double counter)11849 static void proxy_counter_dbl_push(zbx_vector_ptr_t *vector, zbx_uint64_t proxyid, double counter)
11850 {
11851 zbx_proxy_counter_t *proxy_counter;
11852
11853 proxy_counter = (zbx_proxy_counter_t *)zbx_malloc(NULL, sizeof(zbx_proxy_counter_t));
11854 proxy_counter->proxyid = proxyid;
11855 proxy_counter->counter_value.dbl = counter;
11856 zbx_vector_ptr_append(vector, proxy_counter);
11857 }
11858
DCget_status(zbx_vector_ptr_t * hosts_monitored,zbx_vector_ptr_t * hosts_not_monitored,zbx_vector_ptr_t * items_active_normal,zbx_vector_ptr_t * items_active_notsupported,zbx_vector_ptr_t * items_disabled,zbx_uint64_t * triggers_enabled_ok,zbx_uint64_t * triggers_enabled_problem,zbx_uint64_t * triggers_disabled,zbx_vector_ptr_t * required_performance)11859 void DCget_status(zbx_vector_ptr_t *hosts_monitored, zbx_vector_ptr_t *hosts_not_monitored,
11860 zbx_vector_ptr_t *items_active_normal, zbx_vector_ptr_t *items_active_notsupported,
11861 zbx_vector_ptr_t *items_disabled, zbx_uint64_t *triggers_enabled_ok,
11862 zbx_uint64_t *triggers_enabled_problem, zbx_uint64_t *triggers_disabled,
11863 zbx_vector_ptr_t *required_performance)
11864 {
11865 zbx_hashset_iter_t iter;
11866 const ZBX_DC_PROXY *dc_proxy;
11867 const ZBX_DC_HOST *dc_proxy_host;
11868
11869 WRLOCK_CACHE;
11870
11871 dc_status_update();
11872
11873 proxy_counter_ui64_push(hosts_monitored, 0, config->status->hosts_monitored);
11874 proxy_counter_ui64_push(hosts_not_monitored, 0, config->status->hosts_not_monitored);
11875 proxy_counter_ui64_push(items_active_normal, 0, config->status->items_active_normal);
11876 proxy_counter_ui64_push(items_active_notsupported, 0, config->status->items_active_notsupported);
11877 proxy_counter_ui64_push(items_disabled, 0, config->status->items_disabled);
11878 *triggers_enabled_ok = config->status->triggers_enabled_ok;
11879 *triggers_enabled_problem = config->status->triggers_enabled_problem;
11880 *triggers_disabled = config->status->triggers_disabled;
11881 proxy_counter_dbl_push(required_performance, 0, config->status->required_performance);
11882
11883 zbx_hashset_iter_reset(&config->proxies, &iter);
11884
11885 while (NULL != (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_iter_next(&iter)))
11886 {
11887 proxy_counter_ui64_push(hosts_monitored, dc_proxy->hostid, dc_proxy->hosts_monitored);
11888 proxy_counter_ui64_push(hosts_not_monitored, dc_proxy->hostid, dc_proxy->hosts_not_monitored);
11889
11890 if (NULL != (dc_proxy_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_proxy->hostid)))
11891 {
11892 proxy_counter_ui64_push(items_active_normal, dc_proxy->hostid,
11893 dc_proxy_host->items_active_normal);
11894 proxy_counter_ui64_push(items_active_notsupported, dc_proxy->hostid,
11895 dc_proxy_host->items_active_notsupported);
11896 proxy_counter_ui64_push(items_disabled, dc_proxy->hostid, dc_proxy_host->items_disabled);
11897 }
11898
11899 proxy_counter_dbl_push(required_performance, dc_proxy->hostid, dc_proxy->required_performance);
11900 }
11901
11902 UNLOCK_CACHE;
11903 }
11904
11905 /******************************************************************************
11906 * *
11907 * Function: DCget_expressions_by_names *
11908 * *
11909 * Purpose: retrieves global expression data from cache *
11910 * *
11911 * Parameters: expressions - [OUT] a vector of expression data pointers *
11912 * names - [IN] a vector containing expression names *
11913 * names_num - [IN] the number of items in names vector *
11914 * *
11915 * Comment: The expressions vector contains allocated data, which must be *
11916 * freed afterwards with zbx_regexp_clean_expressions() function. *
11917 * *
11918 ******************************************************************************/
DCget_expressions_by_names(zbx_vector_ptr_t * expressions,const char * const * names,int names_num)11919 void DCget_expressions_by_names(zbx_vector_ptr_t *expressions, const char * const *names, int names_num)
11920 {
11921 int i, iname;
11922 const ZBX_DC_EXPRESSION *expression;
11923 const ZBX_DC_REGEXP *regexp;
11924 ZBX_DC_REGEXP search_regexp;
11925
11926 RDLOCK_CACHE;
11927
11928 for (iname = 0; iname < names_num; iname++)
11929 {
11930 search_regexp.name = names[iname];
11931
11932 if (NULL != (regexp = (const ZBX_DC_REGEXP *)zbx_hashset_search(&config->regexps, &search_regexp)))
11933 {
11934 for (i = 0; i < regexp->expressionids.values_num; i++)
11935 {
11936 zbx_uint64_t expressionid = regexp->expressionids.values[i];
11937 zbx_expression_t *rxp;
11938
11939 if (NULL == (expression = (const ZBX_DC_EXPRESSION *)zbx_hashset_search(&config->expressions, &expressionid)))
11940 continue;
11941
11942 rxp = (zbx_expression_t *)zbx_malloc(NULL, sizeof(zbx_expression_t));
11943 rxp->name = zbx_strdup(NULL, regexp->name);
11944 rxp->expression = zbx_strdup(NULL, expression->expression);
11945 rxp->exp_delimiter = expression->delimiter;
11946 rxp->case_sensitive = expression->case_sensitive;
11947 rxp->expression_type = expression->type;
11948
11949 zbx_vector_ptr_append(expressions, rxp);
11950 }
11951 }
11952 }
11953
11954 UNLOCK_CACHE;
11955 }
11956
11957 /******************************************************************************
11958 * *
11959 * Function: DCget_expression *
11960 * *
11961 * Purpose: retrieves regular expression data from cache *
11962 * *
11963 * Parameters: expressions - [OUT] a vector of expression data pointers *
11964 * name - [IN] the regular expression name *
11965 * *
11966 * Comment: The expressions vector contains allocated data, which must be *
11967 * freed afterwards with zbx_regexp_clean_expressions() function. *
11968 * *
11969 ******************************************************************************/
DCget_expressions_by_name(zbx_vector_ptr_t * expressions,const char * name)11970 void DCget_expressions_by_name(zbx_vector_ptr_t *expressions, const char *name)
11971 {
11972 DCget_expressions_by_names(expressions, &name, 1);
11973 }
11974
11975 /******************************************************************************
11976 * *
11977 * Function: DCget_data_expected_from *
11978 * *
11979 * Purpose: Returns time since which data is expected for the given item. We *
11980 * would not mind not having data for the item before that time, but *
11981 * since that time we expect data to be coming. *
11982 * *
11983 * Parameters: itemid - [IN] the item id *
11984 * seconds - [OUT] the time data is expected as a Unix timestamp *
11985 * *
11986 ******************************************************************************/
DCget_data_expected_from(zbx_uint64_t itemid,int * seconds)11987 int DCget_data_expected_from(zbx_uint64_t itemid, int *seconds)
11988 {
11989 const ZBX_DC_ITEM *dc_item;
11990 const ZBX_DC_HOST *dc_host;
11991 int ret = FAIL;
11992
11993 RDLOCK_CACHE;
11994
11995 if (NULL == (dc_item = (const ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemid)))
11996 goto unlock;
11997
11998 if (ITEM_STATUS_ACTIVE != dc_item->status)
11999 goto unlock;
12000
12001 if (NULL == (dc_host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
12002 goto unlock;
12003
12004 if (HOST_STATUS_MONITORED != dc_host->status)
12005 goto unlock;
12006
12007 *seconds = MAX(dc_item->data_expected_from, dc_host->data_expected_from);
12008
12009 ret = SUCCEED;
12010 unlock:
12011 UNLOCK_CACHE;
12012
12013 return ret;
12014 }
12015
12016 /******************************************************************************
12017 * *
12018 * Function: dc_get_hostids_by_functionids *
12019 * *
12020 * Purpose: get host identifiers for the specified list of functions *
12021 * *
12022 * Parameters: functionids - [IN] the function ids *
12023 * functionids_num - [IN] the number of function ids *
12024 * hostids - [OUT] the host ids *
12025 * *
12026 * Comments: this function must be used only by configuration syncer *
12027 * *
12028 ******************************************************************************/
dc_get_hostids_by_functionids(const zbx_uint64_t * functionids,int functionids_num,zbx_vector_uint64_t * hostids)12029 void dc_get_hostids_by_functionids(const zbx_uint64_t *functionids, int functionids_num,
12030 zbx_vector_uint64_t *hostids)
12031 {
12032 const ZBX_DC_FUNCTION *function;
12033 const ZBX_DC_ITEM *item;
12034 int i;
12035
12036 for (i = 0; i < functionids_num; i++)
12037 {
12038 if (NULL == (function = (const ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &functionids[i])))
12039 continue;
12040
12041 if (NULL != (item = (const ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &function->itemid)))
12042 zbx_vector_uint64_append(hostids, item->hostid);
12043 }
12044
12045 zbx_vector_uint64_sort(hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
12046 zbx_vector_uint64_uniq(hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
12047 }
12048
12049 /******************************************************************************
12050 * *
12051 * Function: DCget_hostids_by_functionids *
12052 * *
12053 * Purpose: get function host ids grouped by an object (trigger) id *
12054 * *
12055 * Parameters: functionids - [IN] the function ids *
12056 * hostids - [OUT] the host ids *
12057 * *
12058 ******************************************************************************/
DCget_hostids_by_functionids(zbx_vector_uint64_t * functionids,zbx_vector_uint64_t * hostids)12059 void DCget_hostids_by_functionids(zbx_vector_uint64_t *functionids, zbx_vector_uint64_t *hostids)
12060 {
12061 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
12062
12063 RDLOCK_CACHE;
12064
12065 dc_get_hostids_by_functionids(functionids->values, functionids->values_num, hostids);
12066
12067 UNLOCK_CACHE;
12068
12069 zabbix_log(LOG_LEVEL_DEBUG, "End of %s(): found %d hosts", __func__, hostids->values_num);
12070 }
12071
12072 /******************************************************************************
12073 * *
12074 * Function: dc_get_hosts_by_functionids *
12075 * *
12076 * Purpose: get hosts for the specified list of functions *
12077 * *
12078 * Parameters: functionids - [IN] the function ids *
12079 * functionids_num - [IN] the number of function ids *
12080 * hosts - [OUT] hosts *
12081 * *
12082 ******************************************************************************/
dc_get_hosts_by_functionids(const zbx_uint64_t * functionids,int functionids_num,zbx_hashset_t * hosts)12083 static void dc_get_hosts_by_functionids(const zbx_uint64_t *functionids, int functionids_num, zbx_hashset_t *hosts)
12084 {
12085 const ZBX_DC_FUNCTION *dc_function;
12086 const ZBX_DC_ITEM *dc_item;
12087 const ZBX_DC_HOST *dc_host;
12088 DC_HOST host;
12089 int i;
12090
12091 for (i = 0; i < functionids_num; i++)
12092 {
12093 if (NULL == (dc_function = (const ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &functionids[i])))
12094 continue;
12095
12096 if (NULL == (dc_item = (const ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &dc_function->itemid)))
12097 continue;
12098
12099 if (NULL == (dc_host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
12100 continue;
12101
12102 DCget_host(&host, dc_host, ZBX_ITEM_GET_ALL);
12103 zbx_hashset_insert(hosts, &host, sizeof(host));
12104 }
12105 }
12106
12107 /******************************************************************************
12108 * *
12109 * Function: DCget_hosts_by_functionids *
12110 * *
12111 * Purpose: get hosts for the specified list of functions *
12112 * *
12113 * Parameters: functionids - [IN] the function ids *
12114 * hosts - [OUT] hosts *
12115 * *
12116 ******************************************************************************/
DCget_hosts_by_functionids(const zbx_vector_uint64_t * functionids,zbx_hashset_t * hosts)12117 void DCget_hosts_by_functionids(const zbx_vector_uint64_t *functionids, zbx_hashset_t *hosts)
12118 {
12119 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
12120
12121 RDLOCK_CACHE;
12122
12123 dc_get_hosts_by_functionids(functionids->values, functionids->values_num, hosts);
12124
12125 UNLOCK_CACHE;
12126
12127 zabbix_log(LOG_LEVEL_DEBUG, "End of %s(): found %d hosts", __func__, hosts->num_data);
12128 }
12129
12130 /******************************************************************************
12131 * *
12132 * Function: DCget_internal_action_count *
12133 * *
12134 * Purpose: get number of enabled internal actions *
12135 * *
12136 * Return value: number of enabled internal actions *
12137 * *
12138 ******************************************************************************/
DCget_internal_action_count(void)12139 unsigned int DCget_internal_action_count(void)
12140 {
12141 unsigned int count;
12142
12143 RDLOCK_CACHE;
12144
12145 count = config->internal_actions;
12146
12147 UNLOCK_CACHE;
12148
12149 return count;
12150 }
12151
12152 /******************************************************************************
12153 * *
12154 * Function: zbx_config_get *
12155 * *
12156 * Purpose: get global configuration data *
12157 * *
12158 * Parameters: cfg - [OUT] the global configuration data *
12159 * flags - [IN] the flags specifying fields to get, *
12160 * see ZBX_CONFIG_FLAGS_ defines *
12161 * *
12162 * Comments: It's recommended to cleanup 'cfg' structure after use with *
12163 * zbx_config_clean() function even if only simple fields were *
12164 * requested. *
12165 * *
12166 ******************************************************************************/
zbx_config_get(zbx_config_t * cfg,zbx_uint64_t flags)12167 void zbx_config_get(zbx_config_t *cfg, zbx_uint64_t flags)
12168 {
12169 RDLOCK_CACHE;
12170
12171 if (0 != (flags & ZBX_CONFIG_FLAGS_SEVERITY_NAME))
12172 {
12173 int i;
12174
12175 cfg->severity_name = (char **)zbx_malloc(NULL, TRIGGER_SEVERITY_COUNT * sizeof(char *));
12176
12177 for (i = 0; i < TRIGGER_SEVERITY_COUNT; i++)
12178 cfg->severity_name[i] = zbx_strdup(NULL, config->config->severity_name[i]);
12179 }
12180
12181 if (0 != (flags & ZBX_CONFIG_FLAGS_DISCOVERY_GROUPID))
12182 cfg->discovery_groupid = config->config->discovery_groupid;
12183
12184 if (0 != (flags & ZBX_CONFIG_FLAGS_DEFAULT_INVENTORY_MODE))
12185 cfg->default_inventory_mode = config->config->default_inventory_mode;
12186
12187 if (0 != (flags & ZBX_CONFIG_FLAGS_SNMPTRAP_LOGGING))
12188 cfg->snmptrap_logging = config->config->snmptrap_logging;
12189
12190 if (0 != (flags & ZBX_CONFIG_FLAGS_HOUSEKEEPER))
12191 cfg->hk = config->config->hk;
12192
12193 if (0 != (flags & ZBX_CONFIG_FLAGS_DB_EXTENSION))
12194 {
12195 cfg->db.extension = zbx_strdup(NULL, config->config->db.extension);
12196 cfg->db.history_compression_status = config->config->db.history_compression_status;
12197 cfg->db.history_compress_older = config->config->db.history_compress_older;
12198 }
12199
12200 if (0 != (flags & ZBX_CONFIG_FLAGS_AUTOREG_TLS_ACCEPT))
12201 cfg->autoreg_tls_accept = config->config->autoreg_tls_accept;
12202
12203 if (0 != (flags & ZBX_CONFIG_FLAGS_DEFAULT_TIMEZONE))
12204 cfg->default_timezone = zbx_strdup(NULL, config->config->default_timezone);
12205
12206 UNLOCK_CACHE;
12207
12208 cfg->flags = flags;
12209 }
12210
12211 /******************************************************************************
12212 * *
12213 * Function: zbx_config_get_hk_mode *
12214 * *
12215 * Purpose: get housekeeping mode for history and trends tables *
12216 * *
12217 * Parameters: history_mode - [OUT] history housekeeping mode, can be either *
12218 * disabled, enabled or partitioning *
12219 * trends_mode - [OUT] trends housekeeping mode, can be either *
12220 * disabled, enabled or partitioning *
12221 * *
12222 ******************************************************************************/
zbx_config_get_hk_mode(unsigned char * history_mode,unsigned char * trends_mode)12223 void zbx_config_get_hk_mode(unsigned char *history_mode, unsigned char *trends_mode)
12224 {
12225 RDLOCK_CACHE;
12226 *history_mode = config->config->hk.history_mode;
12227 *trends_mode = config->config->hk.trends_mode;
12228 UNLOCK_CACHE;
12229 }
12230
12231 /******************************************************************************
12232 * *
12233 * Function: zbx_config_clean *
12234 * *
12235 * Purpose: cleans global configuration data structure filled *
12236 * by zbx_config_get() function *
12237 * *
12238 * Parameters: cfg - [IN] the global configuration data *
12239 * *
12240 ******************************************************************************/
zbx_config_clean(zbx_config_t * cfg)12241 void zbx_config_clean(zbx_config_t *cfg)
12242 {
12243 if (0 != (cfg->flags & ZBX_CONFIG_FLAGS_SEVERITY_NAME))
12244 {
12245 int i;
12246
12247 for (i = 0; i < TRIGGER_SEVERITY_COUNT; i++)
12248 zbx_free(cfg->severity_name[i]);
12249
12250 zbx_free(cfg->severity_name);
12251 }
12252
12253 if (0 != (cfg->flags & ZBX_CONFIG_FLAGS_DB_EXTENSION))
12254 zbx_free(cfg->db.extension);
12255
12256 if (0 != (cfg->flags & ZBX_CONFIG_FLAGS_DEFAULT_TIMEZONE))
12257 zbx_free(cfg->default_timezone);
12258 }
12259
12260 /*********************************************************************************
12261 * *
12262 * Function: DCreset_interfaces_availability *
12263 * *
12264 * Purpose: resets interfaces availability for disabled hosts and hosts *
12265 * without enabled items for the corresponding interface *
12266 * *
12267 * Parameters: interfaces - [OUT] changed interface availability data *
12268 * *
12269 * Return value: SUCCEED - interface availability was reset for at least one *
12270 * interface *
12271 * FAIL - no interfaces required availability reset *
12272 * *
12273 * Comments: This function resets interface availability in configuration cache. *
12274 * The caller must perform corresponding database updates based on *
12275 * returned interface availability reset data. On server the function *
12276 * skips hosts handled by proxies. *
12277 * *
12278 ********************************************************************************/
DCreset_interfaces_availability(zbx_vector_availability_ptr_t * interfaces)12279 int DCreset_interfaces_availability(zbx_vector_availability_ptr_t *interfaces)
12280 {
12281 ZBX_DC_HOST *host;
12282 ZBX_DC_INTERFACE *interface;
12283 zbx_hashset_iter_t iter;
12284 zbx_interface_availability_t *ia = NULL;
12285 int now;
12286
12287 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
12288
12289 now = time(NULL);
12290
12291 WRLOCK_CACHE;
12292
12293 zbx_hashset_iter_reset(&config->interfaces, &iter);
12294
12295 while (NULL != (interface = (ZBX_DC_INTERFACE *)zbx_hashset_iter_next(&iter)))
12296 {
12297 int items_num = 0;
12298
12299 if (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &interface->hostid)))
12300 continue;
12301
12302 /* On server skip hosts handled by proxies. They are handled directly */
12303 /* when receiving hosts' availability data from proxies. */
12304 /* Unless a host was just (re)assigned to a proxy or the proxy has */
12305 /* not updated its status during the maximum proxy heartbeat period. */
12306 /* In this case reset all interfaces to unknown status. */
12307 if (0 == interface->reset_availability &&
12308 0 != (program_type & ZBX_PROGRAM_TYPE_SERVER) && 0 != host->proxy_hostid)
12309 {
12310 ZBX_DC_PROXY *proxy;
12311
12312 if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &host->proxy_hostid)))
12313 {
12314 /* SEC_PER_MIN is a tolerance interval, it was chosen arbitrarily */
12315 if (ZBX_PROXY_HEARTBEAT_FREQUENCY_MAX + SEC_PER_MIN >= now - proxy->lastaccess)
12316 continue;
12317 }
12318
12319 interface->reset_availability = 1;
12320 }
12321
12322 if (NULL == ia)
12323 ia = (zbx_interface_availability_t *)zbx_malloc(NULL, sizeof(zbx_interface_availability_t));
12324
12325 zbx_interface_availability_init(ia, interface->interfaceid);
12326
12327 if (0 == interface->reset_availability)
12328 items_num = interface->items_num;
12329
12330 if (0 == items_num && INTERFACE_AVAILABLE_UNKNOWN != interface->available)
12331 zbx_agent_availability_init(&ia->agent, INTERFACE_AVAILABLE_UNKNOWN, "", 0, 0);
12332
12333 if (SUCCEED == zbx_interface_availability_is_set(ia))
12334 {
12335 if (SUCCEED == DCinterface_set_availability(interface, now, ia))
12336 {
12337 zbx_vector_availability_ptr_append(interfaces, ia);
12338 ia = NULL;
12339 }
12340 else
12341 zbx_interface_availability_clean(ia);
12342 }
12343
12344 interface->reset_availability = 0;
12345 }
12346 UNLOCK_CACHE;
12347
12348 zbx_free(ia);
12349
12350 zbx_vector_availability_ptr_sort(interfaces, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
12351
12352 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() interfaces:%d", __func__, interfaces->values_num);
12353
12354 return 0 == interfaces->values_num ? FAIL : SUCCEED;
12355 }
12356
12357 /*******************************************************************************
12358 * *
12359 * Function: DCget_interfaces_availability *
12360 * *
12361 * Purpose: gets availability data for interfaces with availability data *
12362 * changed in period from last availability update to the specified *
12363 * timestamp *
12364 * *
12365 * Parameters: interfaces - [OUT] changed interfaces availability data *
12366 * ts - [OUT] the availability diff timestamp *
12367 * *
12368 * Return value: SUCCEED - availability was changed for at least one interface *
12369 * FAIL - no interface availability was changed *
12370 * *
12371 *******************************************************************************/
DCget_interfaces_availability(zbx_vector_ptr_t * interfaces,int * ts)12372 int DCget_interfaces_availability(zbx_vector_ptr_t *interfaces, int *ts)
12373 {
12374 const ZBX_DC_INTERFACE *interface;
12375 zbx_hashset_iter_t iter;
12376 zbx_interface_availability_t *ia = NULL;
12377
12378 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
12379
12380 RDLOCK_CACHE;
12381
12382 *ts = time(NULL);
12383
12384 zbx_hashset_iter_reset(&config->interfaces, &iter);
12385
12386 while (NULL != (interface = (const ZBX_DC_INTERFACE *)zbx_hashset_iter_next(&iter)))
12387 {
12388 if (config->availability_diff_ts <= interface->availability_ts && interface->availability_ts < *ts)
12389 {
12390 ia = (zbx_interface_availability_t *)zbx_malloc(NULL, sizeof(zbx_interface_availability_t));
12391 zbx_interface_availability_init(ia, interface->interfaceid);
12392
12393 zbx_agent_availability_init(&ia->agent, interface->available, interface->error,
12394 interface->errors_from, interface->disable_until);
12395
12396 zbx_vector_ptr_append(interfaces, ia);
12397 }
12398 }
12399
12400 UNLOCK_CACHE;
12401
12402 zbx_vector_ptr_sort(interfaces, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
12403
12404 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() interfaces:%d", __func__, interfaces->values_num);
12405
12406 return 0 == interfaces->values_num ? FAIL : SUCCEED;
12407 }
12408
12409 /******************************************************************************
12410 * *
12411 * Function: DCtouch_interfaces_availability *
12412 * *
12413 * Purpose: sets availability timestamp to current time for the specified *
12414 * interfaces *
12415 * *
12416 * Parameters: interfaceids - [IN] the interfaces identifiers *
12417 * *
12418 ******************************************************************************/
DCtouch_interfaces_availability(const zbx_vector_uint64_t * interfaceids)12419 void DCtouch_interfaces_availability(const zbx_vector_uint64_t *interfaceids)
12420 {
12421 ZBX_DC_INTERFACE *dc_interface;
12422 int i, now;
12423
12424 zabbix_log(LOG_LEVEL_DEBUG, "In %s() interfaceids:%d", __func__, interfaceids->values_num);
12425
12426 now = time(NULL);
12427
12428 WRLOCK_CACHE;
12429
12430 for (i = 0; i < interfaceids->values_num; i++)
12431 {
12432 if (NULL != (dc_interface = zbx_hashset_search(&config->interfaces, &interfaceids->values[i])))
12433 dc_interface->availability_ts = now;
12434 }
12435
12436 UNLOCK_CACHE;
12437
12438 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
12439 }
12440
12441 /******************************************************************************
12442 * *
12443 * Function: dc_action_copy_conditions *
12444 * *
12445 * Purpose: copies configuration cache action conditions to the specified *
12446 * vector *
12447 * *
12448 * Parameters: dc_action - [IN] the source action *
12449 * conditions - [OUT] the conditions vector *
12450 * *
12451 ******************************************************************************/
dc_action_copy_conditions(const zbx_dc_action_t * dc_action,zbx_vector_ptr_t * conditions)12452 static void dc_action_copy_conditions(const zbx_dc_action_t *dc_action, zbx_vector_ptr_t *conditions)
12453 {
12454 int i;
12455 zbx_condition_t *condition;
12456 zbx_dc_action_condition_t *dc_condition;
12457
12458 zbx_vector_ptr_reserve(conditions, dc_action->conditions.values_num);
12459
12460 for (i = 0; i < dc_action->conditions.values_num; i++)
12461 {
12462 dc_condition = (zbx_dc_action_condition_t *)dc_action->conditions.values[i];
12463
12464 condition = (zbx_condition_t *)zbx_malloc(NULL, sizeof(zbx_condition_t));
12465
12466 condition->conditionid = dc_condition->conditionid;
12467 condition->actionid = dc_action->actionid;
12468 condition->conditiontype = dc_condition->conditiontype;
12469 condition->op = dc_condition->op;
12470 condition->value = zbx_strdup(NULL, dc_condition->value);
12471 condition->value2 = zbx_strdup(NULL, dc_condition->value2);
12472 zbx_vector_uint64_create(&condition->eventids);
12473
12474 zbx_vector_ptr_append(conditions, condition);
12475 }
12476 }
12477
12478 /******************************************************************************
12479 * *
12480 * Function: dc_action_eval_create *
12481 * *
12482 * Purpose: creates action evaluation data from configuration cache action *
12483 * *
12484 * Parameters: dc_action - [IN] the source action *
12485 * *
12486 * Return value: the action evaluation data *
12487 * *
12488 * Comments: The returned value must be freed with zbx_action_eval_free() *
12489 * function later. *
12490 * *
12491 ******************************************************************************/
dc_action_eval_create(const zbx_dc_action_t * dc_action)12492 static zbx_action_eval_t *dc_action_eval_create(const zbx_dc_action_t *dc_action)
12493 {
12494 zbx_action_eval_t *action;
12495
12496 action = (zbx_action_eval_t *)zbx_malloc(NULL, sizeof(zbx_action_eval_t));
12497
12498 action->actionid = dc_action->actionid;
12499 action->eventsource = dc_action->eventsource;
12500 action->evaltype = dc_action->evaltype;
12501 action->opflags = dc_action->opflags;
12502 action->formula = zbx_strdup(NULL, dc_action->formula);
12503 zbx_vector_ptr_create(&action->conditions);
12504
12505 dc_action_copy_conditions(dc_action, &action->conditions);
12506
12507 return action;
12508 }
12509
12510 /******************************************************************************
12511 * *
12512 * Function: zbx_dc_get_actions_eval *
12513 * *
12514 * Purpose: gets action evaluation data *
12515 * *
12516 * Parameters: actions - [OUT] the action evaluation data *
12517 * uniq_conditions - [OUT] unique conditions that actions *
12518 * point to (several sources) *
12519 * opflags - [IN] flags specifying which actions to get *
12520 * based on their operation classes *
12521 * (see ZBX_ACTION_OPCLASS_* defines) *
12522 * *
12523 * Comments: The returned actions and conditions must be freed with *
12524 * zbx_action_eval_free() function later. *
12525 * *
12526 ******************************************************************************/
zbx_dc_get_actions_eval(zbx_vector_ptr_t * actions,unsigned char opflags)12527 void zbx_dc_get_actions_eval(zbx_vector_ptr_t *actions, unsigned char opflags)
12528 {
12529 const zbx_dc_action_t *dc_action;
12530 zbx_hashset_iter_t iter;
12531
12532 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
12533
12534 RDLOCK_CACHE;
12535
12536 zbx_hashset_iter_reset(&config->actions, &iter);
12537
12538 while (NULL != (dc_action = (const zbx_dc_action_t *)zbx_hashset_iter_next(&iter)))
12539 {
12540 if (0 != (opflags & dc_action->opflags))
12541 zbx_vector_ptr_append(actions, dc_action_eval_create(dc_action));
12542 }
12543
12544 UNLOCK_CACHE;
12545
12546 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() actions:%d", __func__, actions->values_num);
12547 }
12548
12549 /******************************************************************************
12550 * *
12551 * Function: zbx_set_availability_update_ts *
12552 * *
12553 * Purpose: sets timestamp of the last availability update *
12554 * *
12555 * Parameter: ts - [IN] the last availability update timestamp *
12556 * *
12557 * Comments: This function is used only by proxies when preparing host *
12558 * availability data to be sent to server. *
12559 * *
12560 ******************************************************************************/
zbx_set_availability_diff_ts(int ts)12561 void zbx_set_availability_diff_ts(int ts)
12562 {
12563 /* this data can't be accessed simultaneously from multiple processes - locking is not necessary */
12564 config->availability_diff_ts = ts;
12565 }
12566
12567 /******************************************************************************
12568 * *
12569 * Function: corr_condition_clean *
12570 * *
12571 * Purpose: frees correlation condition *
12572 * *
12573 * Parameter: condition - [IN] the condition to free *
12574 * *
12575 ******************************************************************************/
corr_condition_clean(zbx_corr_condition_t * condition)12576 static void corr_condition_clean(zbx_corr_condition_t *condition)
12577 {
12578 switch (condition->type)
12579 {
12580 case ZBX_CORR_CONDITION_OLD_EVENT_TAG:
12581 /* break; is not missing here */
12582 case ZBX_CORR_CONDITION_NEW_EVENT_TAG:
12583 zbx_free(condition->data.tag.tag);
12584 break;
12585 case ZBX_CORR_CONDITION_EVENT_TAG_PAIR:
12586 zbx_free(condition->data.tag_pair.oldtag);
12587 zbx_free(condition->data.tag_pair.newtag);
12588 break;
12589 case ZBX_CORR_CONDITION_OLD_EVENT_TAG_VALUE:
12590 /* break; is not missing here */
12591 case ZBX_CORR_CONDITION_NEW_EVENT_TAG_VALUE:
12592 zbx_free(condition->data.tag_value.tag);
12593 zbx_free(condition->data.tag_value.value);
12594 break;
12595 }
12596 }
12597
12598 /******************************************************************************
12599 * *
12600 * Function: dc_correlation_free *
12601 * *
12602 * Purpose: frees global correlation rule *
12603 * *
12604 * Parameter: condition - [IN] the condition to free *
12605 * *
12606 ******************************************************************************/
dc_correlation_free(zbx_correlation_t * correlation)12607 static void dc_correlation_free(zbx_correlation_t *correlation)
12608 {
12609 zbx_free(correlation->name);
12610 zbx_free(correlation->formula);
12611
12612 zbx_vector_ptr_clear_ext(&correlation->operations, zbx_ptr_free);
12613 zbx_vector_ptr_destroy(&correlation->operations);
12614 zbx_vector_ptr_destroy(&correlation->conditions);
12615
12616 zbx_free(correlation);
12617 }
12618
12619 /******************************************************************************
12620 * *
12621 * Function: dc_corr_condition_copy *
12622 * *
12623 * Purpose: copies cached correlation condition to memory *
12624 * *
12625 * Parameter: dc_condition - [IN] the condition to copy *
12626 * condition - [OUT] the destination condition *
12627 * *
12628 * Return value: The cloned correlation condition. *
12629 * *
12630 ******************************************************************************/
dc_corr_condition_copy(const zbx_dc_corr_condition_t * dc_condition,zbx_corr_condition_t * condition)12631 static void dc_corr_condition_copy(const zbx_dc_corr_condition_t *dc_condition, zbx_corr_condition_t *condition)
12632 {
12633 condition->type = dc_condition->type;
12634
12635 switch (condition->type)
12636 {
12637 case ZBX_CORR_CONDITION_OLD_EVENT_TAG:
12638 /* break; is not missing here */
12639 case ZBX_CORR_CONDITION_NEW_EVENT_TAG:
12640 condition->data.tag.tag = zbx_strdup(NULL, dc_condition->data.tag.tag);
12641 break;
12642 case ZBX_CORR_CONDITION_EVENT_TAG_PAIR:
12643 condition->data.tag_pair.oldtag = zbx_strdup(NULL, dc_condition->data.tag_pair.oldtag);
12644 condition->data.tag_pair.newtag = zbx_strdup(NULL, dc_condition->data.tag_pair.newtag);
12645 break;
12646 case ZBX_CORR_CONDITION_OLD_EVENT_TAG_VALUE:
12647 /* break; is not missing here */
12648 case ZBX_CORR_CONDITION_NEW_EVENT_TAG_VALUE:
12649 condition->data.tag_value.tag = zbx_strdup(NULL, dc_condition->data.tag_value.tag);
12650 condition->data.tag_value.value = zbx_strdup(NULL, dc_condition->data.tag_value.value);
12651 condition->data.tag_value.op = dc_condition->data.tag_value.op;
12652 break;
12653 case ZBX_CORR_CONDITION_NEW_EVENT_HOSTGROUP:
12654 condition->data.group.groupid = dc_condition->data.group.groupid;
12655 condition->data.group.op = dc_condition->data.group.op;
12656 break;
12657 }
12658 }
12659
12660 /******************************************************************************
12661 * *
12662 * Function: zbx_dc_corr_operation_dup *
12663 * *
12664 * Purpose: clones cached correlation operation to memory *
12665 * *
12666 * Parameter: operation - [IN] the operation to clone *
12667 * *
12668 * Return value: The cloned correlation operation. *
12669 * *
12670 ******************************************************************************/
zbx_dc_corr_operation_dup(const zbx_dc_corr_operation_t * dc_operation)12671 static zbx_corr_operation_t *zbx_dc_corr_operation_dup(const zbx_dc_corr_operation_t *dc_operation)
12672 {
12673 zbx_corr_operation_t *operation;
12674
12675 operation = (zbx_corr_operation_t *)zbx_malloc(NULL, sizeof(zbx_corr_operation_t));
12676 operation->type = dc_operation->type;
12677
12678 return operation;
12679 }
12680
12681 /******************************************************************************
12682 * *
12683 * Function: dc_correlation_formula_dup *
12684 * *
12685 * Purpose: clones cached correlation formula, generating it if necessary *
12686 * *
12687 * Parameter: correlation - [IN] the correlation *
12688 * *
12689 * Return value: The cloned correlation formula. *
12690 * *
12691 ******************************************************************************/
dc_correlation_formula_dup(const zbx_dc_correlation_t * dc_correlation)12692 static char *dc_correlation_formula_dup(const zbx_dc_correlation_t *dc_correlation)
12693 {
12694 #define ZBX_OPERATION_TYPE_UNKNOWN 0
12695 #define ZBX_OPERATION_TYPE_OR 1
12696 #define ZBX_OPERATION_TYPE_AND 2
12697
12698 char *formula = NULL;
12699 const char *op = NULL;
12700 size_t formula_alloc = 0, formula_offset = 0;
12701 int i, last_type = -1, last_op = ZBX_OPERATION_TYPE_UNKNOWN;
12702 const zbx_dc_corr_condition_t *dc_condition;
12703 zbx_uint64_t last_id;
12704
12705 if (CONDITION_EVAL_TYPE_EXPRESSION == dc_correlation->evaltype || 0 == dc_correlation->conditions.values_num)
12706 return zbx_strdup(NULL, dc_correlation->formula);
12707
12708 dc_condition = (const zbx_dc_corr_condition_t *)dc_correlation->conditions.values[0];
12709
12710 switch (dc_correlation->evaltype)
12711 {
12712 case CONDITION_EVAL_TYPE_OR:
12713 op = " or";
12714 break;
12715 case CONDITION_EVAL_TYPE_AND:
12716 op = " and";
12717 break;
12718 }
12719
12720 if (NULL != op)
12721 {
12722 zbx_snprintf_alloc(&formula, &formula_alloc, &formula_offset, "{" ZBX_FS_UI64 "}",
12723 dc_condition->corr_conditionid);
12724
12725 for (i = 1; i < dc_correlation->conditions.values_num; i++)
12726 {
12727 dc_condition = (const zbx_dc_corr_condition_t *)dc_correlation->conditions.values[i];
12728
12729 zbx_strcpy_alloc(&formula, &formula_alloc, &formula_offset, op);
12730 zbx_snprintf_alloc(&formula, &formula_alloc, &formula_offset, " {" ZBX_FS_UI64 "}",
12731 dc_condition->corr_conditionid);
12732 }
12733
12734 return formula;
12735 }
12736
12737 last_id = dc_condition->corr_conditionid;
12738 last_type = dc_condition->type;
12739
12740 for (i = 1; i < dc_correlation->conditions.values_num; i++)
12741 {
12742 dc_condition = (const zbx_dc_corr_condition_t *)dc_correlation->conditions.values[i];
12743
12744 if (last_type == dc_condition->type)
12745 {
12746 if (last_op != ZBX_OPERATION_TYPE_OR)
12747 zbx_chrcpy_alloc(&formula, &formula_alloc, &formula_offset, '(');
12748
12749 zbx_snprintf_alloc(&formula, &formula_alloc, &formula_offset, "{" ZBX_FS_UI64 "} or ", last_id);
12750 last_op = ZBX_OPERATION_TYPE_OR;
12751 }
12752 else
12753 {
12754 zbx_snprintf_alloc(&formula, &formula_alloc, &formula_offset, "{" ZBX_FS_UI64 "}", last_id);
12755
12756 if (last_op == ZBX_OPERATION_TYPE_OR)
12757 zbx_chrcpy_alloc(&formula, &formula_alloc, &formula_offset, ')');
12758
12759 zbx_strcpy_alloc(&formula, &formula_alloc, &formula_offset, " and ");
12760
12761 last_op = ZBX_OPERATION_TYPE_AND;
12762 }
12763
12764 last_type = dc_condition->type;
12765 last_id = dc_condition->corr_conditionid;
12766 }
12767
12768 zbx_snprintf_alloc(&formula, &formula_alloc, &formula_offset, "{" ZBX_FS_UI64 "}", last_id);
12769
12770 if (last_op == ZBX_OPERATION_TYPE_OR)
12771 zbx_chrcpy_alloc(&formula, &formula_alloc, &formula_offset, ')');
12772
12773 return formula;
12774
12775 #undef ZBX_OPERATION_TYPE_UNKNOWN
12776 #undef ZBX_OPERATION_TYPE_OR
12777 #undef ZBX_OPERATION_TYPE_AND
12778 }
12779
zbx_dc_correlation_rules_init(zbx_correlation_rules_t * rules)12780 void zbx_dc_correlation_rules_init(zbx_correlation_rules_t *rules)
12781 {
12782 zbx_vector_ptr_create(&rules->correlations);
12783 zbx_hashset_create_ext(&rules->conditions, 0, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC,
12784 (zbx_clean_func_t)corr_condition_clean, ZBX_DEFAULT_MEM_MALLOC_FUNC,
12785 ZBX_DEFAULT_MEM_REALLOC_FUNC, ZBX_DEFAULT_MEM_FREE_FUNC);
12786
12787 rules->sync_ts = 0;
12788 }
12789
zbx_dc_correlation_rules_clean(zbx_correlation_rules_t * rules)12790 void zbx_dc_correlation_rules_clean(zbx_correlation_rules_t *rules)
12791 {
12792 zbx_vector_ptr_clear_ext(&rules->correlations, (zbx_clean_func_t)dc_correlation_free);
12793 zbx_hashset_clear(&rules->conditions);
12794 }
12795
zbx_dc_correlation_rules_free(zbx_correlation_rules_t * rules)12796 void zbx_dc_correlation_rules_free(zbx_correlation_rules_t *rules)
12797 {
12798 zbx_dc_correlation_rules_clean(rules);
12799 zbx_vector_ptr_destroy(&rules->correlations);
12800 zbx_hashset_destroy(&rules->conditions);
12801 }
12802
12803 /******************************************************************************
12804 * *
12805 * Function: zbx_dc_correlation_get_rules *
12806 * *
12807 * Purpose: gets correlation rules from configuration cache *
12808 * *
12809 * Parameter: rules - [IN/OUT] the correlation rules *
12810 * *
12811 ******************************************************************************/
zbx_dc_correlation_rules_get(zbx_correlation_rules_t * rules)12812 void zbx_dc_correlation_rules_get(zbx_correlation_rules_t *rules)
12813 {
12814 int i;
12815 zbx_hashset_iter_t iter;
12816 const zbx_dc_correlation_t *dc_correlation;
12817 const zbx_dc_corr_condition_t *dc_condition;
12818 zbx_correlation_t *correlation;
12819 zbx_corr_condition_t *condition, condition_local;
12820
12821 RDLOCK_CACHE;
12822
12823 /* The correlation rules are refreshed only if the sync timestamp */
12824 /* does not match current configuration cache sync timestamp. This */
12825 /* allows to locally cache the correlation rules. */
12826 if (config->sync_ts == rules->sync_ts)
12827 {
12828 UNLOCK_CACHE;
12829 return;
12830 }
12831
12832 zbx_dc_correlation_rules_clean(rules);
12833
12834 zbx_hashset_iter_reset(&config->correlations, &iter);
12835 while (NULL != (dc_correlation = (const zbx_dc_correlation_t *)zbx_hashset_iter_next(&iter)))
12836 {
12837 correlation = (zbx_correlation_t *)zbx_malloc(NULL, sizeof(zbx_correlation_t));
12838 correlation->correlationid = dc_correlation->correlationid;
12839 correlation->evaltype = dc_correlation->evaltype;
12840 correlation->name = zbx_strdup(NULL, dc_correlation->name);
12841 correlation->formula = dc_correlation_formula_dup(dc_correlation);
12842 zbx_vector_ptr_create(&correlation->conditions);
12843 zbx_vector_ptr_create(&correlation->operations);
12844
12845 for (i = 0; i < dc_correlation->conditions.values_num; i++)
12846 {
12847 dc_condition = (const zbx_dc_corr_condition_t *)dc_correlation->conditions.values[i];
12848 condition_local.corr_conditionid = dc_condition->corr_conditionid;
12849 condition = (zbx_corr_condition_t *)zbx_hashset_insert(&rules->conditions, &condition_local, sizeof(condition_local));
12850 dc_corr_condition_copy(dc_condition, condition);
12851 zbx_vector_ptr_append(&correlation->conditions, condition);
12852 }
12853
12854 for (i = 0; i < dc_correlation->operations.values_num; i++)
12855 {
12856 zbx_vector_ptr_append(&correlation->operations,
12857 zbx_dc_corr_operation_dup((const zbx_dc_corr_operation_t *)dc_correlation->operations.values[i]));
12858 }
12859
12860 zbx_vector_ptr_append(&rules->correlations, correlation);
12861 }
12862
12863 rules->sync_ts = config->sync_ts;
12864
12865 UNLOCK_CACHE;
12866
12867 zbx_vector_ptr_sort(&rules->correlations, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
12868 }
12869
12870 /******************************************************************************
12871 * *
12872 * Function: dc_hostgroup_cache_nested_groupids *
12873 * *
12874 * Purpose: cache nested group identifiers *
12875 * *
12876 ******************************************************************************/
dc_hostgroup_cache_nested_groupids(zbx_dc_hostgroup_t * parent_group)12877 void dc_hostgroup_cache_nested_groupids(zbx_dc_hostgroup_t *parent_group)
12878 {
12879 zbx_dc_hostgroup_t *group;
12880
12881 if (0 == (parent_group->flags & ZBX_DC_HOSTGROUP_FLAGS_NESTED_GROUPIDS))
12882 {
12883 int index, len;
12884
12885 zbx_vector_uint64_create_ext(&parent_group->nested_groupids, __config_mem_malloc_func,
12886 __config_mem_realloc_func, __config_mem_free_func);
12887
12888 index = zbx_vector_ptr_bsearch(&config->hostgroups_name, parent_group, dc_compare_hgroups);
12889 len = strlen(parent_group->name);
12890
12891 while (++index < config->hostgroups_name.values_num)
12892 {
12893 group = (zbx_dc_hostgroup_t *)config->hostgroups_name.values[index];
12894
12895 if (0 != strncmp(group->name, parent_group->name, len))
12896 break;
12897
12898 if ('\0' == group->name[len] || '/' == group->name[len])
12899 zbx_vector_uint64_append(&parent_group->nested_groupids, group->groupid);
12900 }
12901
12902 parent_group->flags |= ZBX_DC_HOSTGROUP_FLAGS_NESTED_GROUPIDS;
12903 }
12904 }
12905
12906 /******************************************************************************
12907 * *
12908 * Function: dc_maintenance_precache_nested_groups *
12909 * *
12910 * Purpose: pre-caches nested groups for groups used in running maintenances *
12911 * *
12912 ******************************************************************************/
dc_maintenance_precache_nested_groups(void)12913 static void dc_maintenance_precache_nested_groups(void)
12914 {
12915 zbx_hashset_iter_t iter;
12916 zbx_dc_maintenance_t *maintenance;
12917 zbx_vector_uint64_t groupids;
12918 int i;
12919 zbx_dc_hostgroup_t *group;
12920
12921 if (0 == config->maintenances.num_data)
12922 return;
12923
12924 zbx_vector_uint64_create(&groupids);
12925 zbx_hashset_iter_reset(&config->maintenances, &iter);
12926 while (NULL != (maintenance = (zbx_dc_maintenance_t *)zbx_hashset_iter_next(&iter)))
12927 {
12928 if (ZBX_MAINTENANCE_RUNNING != maintenance->state)
12929 continue;
12930
12931 zbx_vector_uint64_append_array(&groupids, maintenance->groupids.values,
12932 maintenance->groupids.values_num);
12933 }
12934
12935 zbx_vector_uint64_sort(&groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
12936 zbx_vector_uint64_uniq(&groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
12937
12938 for (i = 0; i < groupids.values_num; i++)
12939 {
12940 if (NULL != (group = (zbx_dc_hostgroup_t *)zbx_hashset_search(&config->hostgroups,
12941 &groupids.values[i])))
12942 {
12943 dc_hostgroup_cache_nested_groupids(group);
12944 }
12945 }
12946
12947 zbx_vector_uint64_destroy(&groupids);
12948 }
12949
12950 /******************************************************************************
12951 * *
12952 * Function: dc_get_nested_hostgroupids *
12953 * *
12954 * Purpose: gets nested group ids for the specified host group *
12955 * (including the target group id) *
12956 * *
12957 * Parameter: groupid - [IN] the parent group identifier *
12958 * nested_groupids - [OUT] the nested + parent group ids *
12959 * *
12960 ******************************************************************************/
dc_get_nested_hostgroupids(zbx_uint64_t groupid,zbx_vector_uint64_t * nested_groupids)12961 void dc_get_nested_hostgroupids(zbx_uint64_t groupid, zbx_vector_uint64_t *nested_groupids)
12962 {
12963 zbx_dc_hostgroup_t *parent_group;
12964
12965 zbx_vector_uint64_append(nested_groupids, groupid);
12966
12967 /* The target group id will not be found in the configuration cache if target group was removed */
12968 /* between call to this function and the configuration cache look-up below. The target group id */
12969 /* is nevertheless returned so that the SELECT statements of the callers work even if no group */
12970 /* was found. */
12971
12972 if (NULL != (parent_group = (zbx_dc_hostgroup_t *)zbx_hashset_search(&config->hostgroups, &groupid)))
12973 {
12974 dc_hostgroup_cache_nested_groupids(parent_group);
12975
12976 if (0 != parent_group->nested_groupids.values_num)
12977 {
12978 zbx_vector_uint64_append_array(nested_groupids, parent_group->nested_groupids.values,
12979 parent_group->nested_groupids.values_num);
12980 }
12981 }
12982 }
12983
12984 /******************************************************************************
12985 * *
12986 * Function: zbx_dc_get_nested_hostgroupids *
12987 * *
12988 * Purpose: gets nested group ids for the specified host groups *
12989 * *
12990 * Parameter: groupids - [IN] the parent group identifiers *
12991 * groupids_num - [IN] the number of parent groups *
12992 * nested_groupids - [OUT] the nested + parent group ids *
12993 * *
12994 ******************************************************************************/
zbx_dc_get_nested_hostgroupids(zbx_uint64_t * groupids,int groupids_num,zbx_vector_uint64_t * nested_groupids)12995 void zbx_dc_get_nested_hostgroupids(zbx_uint64_t *groupids, int groupids_num, zbx_vector_uint64_t *nested_groupids)
12996 {
12997 int i;
12998
12999 WRLOCK_CACHE;
13000
13001 for (i = 0; i < groupids_num; i++)
13002 dc_get_nested_hostgroupids(groupids[i], nested_groupids);
13003
13004 UNLOCK_CACHE;
13005
13006 zbx_vector_uint64_sort(nested_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
13007 zbx_vector_uint64_uniq(nested_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
13008 }
13009
13010 /******************************************************************************
13011 * *
13012 * Function: zbx_dc_get_hostids_by_group_name *
13013 * *
13014 * Purpose: gets hostids belonging to the group and its nested groups *
13015 * *
13016 * Parameter: name - [IN] the group name *
13017 * hostids - [OUT] the hostids *
13018 * *
13019 ******************************************************************************/
zbx_dc_get_hostids_by_group_name(const char * name,zbx_vector_uint64_t * hostids)13020 void zbx_dc_get_hostids_by_group_name(const char *name, zbx_vector_uint64_t *hostids)
13021 {
13022 int i;
13023 zbx_vector_uint64_t groupids;
13024 zbx_dc_hostgroup_t group_local, *group;
13025
13026 zbx_vector_uint64_create(&groupids);
13027
13028 group_local.name = name;
13029
13030 WRLOCK_CACHE;
13031
13032 if (FAIL != (i = zbx_vector_ptr_bsearch(&config->hostgroups_name, &group_local, dc_compare_hgroups)))
13033 {
13034 group = (zbx_dc_hostgroup_t *)config->hostgroups_name.values[i];
13035 dc_get_nested_hostgroupids(group->groupid, &groupids);
13036 }
13037
13038 UNLOCK_CACHE;
13039
13040 zbx_vector_uint64_sort(&groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
13041 zbx_vector_uint64_uniq(&groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
13042
13043 RDLOCK_CACHE;
13044
13045 for (i = 0; i < groupids.values_num; i++)
13046 {
13047 zbx_hashset_iter_t iter;
13048 zbx_uint64_t *phostid;
13049
13050 if (NULL == (group = (zbx_dc_hostgroup_t *)zbx_hashset_search(&config->hostgroups,
13051 &groupids.values[i])))
13052 {
13053 continue;
13054 }
13055
13056 zbx_hashset_iter_reset(&group->hostids, &iter);
13057
13058 while (NULL != (phostid = (zbx_uint64_t *)zbx_hashset_iter_next(&iter)))
13059 zbx_vector_uint64_append(hostids, *phostid);
13060 }
13061
13062 UNLOCK_CACHE;
13063
13064 zbx_vector_uint64_destroy(&groupids);
13065
13066 zbx_vector_uint64_sort(hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
13067 zbx_vector_uint64_uniq(hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
13068 }
13069
13070 /******************************************************************************
13071 * *
13072 * Function: zbx_dc_get_active_proxy_by_name *
13073 * *
13074 * Purpose: gets active proxy data by its name from configuration cache *
13075 * *
13076 * Parameters: *
13077 * name - [IN] the proxy name *
13078 * proxy - [OUT] the proxy data *
13079 * error - [OUT] error message *
13080 * *
13081 * Return value: *
13082 * SUCCEED - proxy data were retrieved successfully *
13083 * FAIL - failed to retrieve proxy data, error message is set *
13084 * *
13085 ******************************************************************************/
zbx_dc_get_active_proxy_by_name(const char * name,DC_PROXY * proxy,char ** error)13086 int zbx_dc_get_active_proxy_by_name(const char *name, DC_PROXY *proxy, char **error)
13087 {
13088 int ret = FAIL;
13089 const ZBX_DC_HOST *dc_host;
13090 const ZBX_DC_PROXY *dc_proxy;
13091
13092 RDLOCK_CACHE;
13093
13094 if (NULL == (dc_host = DCfind_proxy(name)))
13095 {
13096 *error = zbx_dsprintf(*error, "proxy \"%s\" not found", name);
13097 goto out;
13098 }
13099
13100 if (HOST_STATUS_PROXY_ACTIVE != dc_host->status)
13101 {
13102 *error = zbx_dsprintf(*error, "proxy \"%s\" is configured for passive mode", name);
13103 goto out;
13104 }
13105
13106 if (NULL == (dc_proxy = (const ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &dc_host->hostid)))
13107 {
13108 *error = zbx_dsprintf(*error, "proxy \"%s\" not found in configuration cache", name);
13109 goto out;
13110 }
13111
13112 DCget_proxy(proxy, dc_proxy);
13113 ret = SUCCEED;
13114 out:
13115 UNLOCK_CACHE;
13116
13117 return ret;
13118 }
13119
13120 /******************************************************************************
13121 * *
13122 * Function: zbx_dc_items_update_nextcheck *
13123 * *
13124 * Purpose: updates item nextcheck values in configuration cache *
13125 * *
13126 * Parameters: items - [IN] the items to update *
13127 * values - [IN] the items values containing new properties *
13128 * errcodes - [IN] item error codes. Update only items with *
13129 * SUCCEED code *
13130 * values_num - [IN] the number of elements in items,values and *
13131 * errcodes arrays *
13132 * *
13133 ******************************************************************************/
zbx_dc_items_update_nextcheck(DC_ITEM * items,zbx_agent_value_t * values,int * errcodes,size_t values_num)13134 void zbx_dc_items_update_nextcheck(DC_ITEM *items, zbx_agent_value_t *values, int *errcodes, size_t values_num)
13135 {
13136 size_t i;
13137 ZBX_DC_ITEM *dc_item;
13138 ZBX_DC_HOST *dc_host;
13139 ZBX_DC_INTERFACE *dc_interface;
13140
13141 RDLOCK_CACHE;
13142
13143 for (i = 0; i < values_num; i++)
13144 {
13145 if (FAIL == errcodes[i])
13146 continue;
13147
13148 /* update nextcheck for items that are counted in queue for monitoring purposes */
13149 if (FAIL == zbx_is_counted_in_item_queue(items[i].type, items[i].key_orig))
13150 continue;
13151
13152 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &items[i].itemid)))
13153 continue;
13154
13155 if (ITEM_STATUS_ACTIVE != dc_item->status)
13156 continue;
13157
13158 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
13159 continue;
13160
13161 if (HOST_STATUS_MONITORED != dc_host->status)
13162 continue;
13163
13164 if (ZBX_LOC_NOWHERE != dc_item->location)
13165 continue;
13166
13167 dc_interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces, &dc_item->interfaceid);
13168
13169 /* update nextcheck for items that are counted in queue for monitoring purposes */
13170 DCitem_nextcheck_update(dc_item, dc_interface, ZBX_ITEM_COLLECTED, values[i].ts.sec,
13171 NULL);
13172 }
13173
13174 UNLOCK_CACHE;
13175 }
13176
13177 /******************************************************************************
13178 * *
13179 * Function: zbx_dc_get_host_interfaces *
13180 * *
13181 * Purpose: get data of all network interfaces for a host in configuration *
13182 * cache *
13183 * *
13184 * Parameter: hostid - [IN] the host identifier *
13185 * interfaces - [OUT] array with interface data *
13186 * n - [OUT] number of allocated 'interfaces' elements *
13187 * *
13188 * Return value: SUCCEED - interface data retrieved successfully *
13189 * FAIL - host not found *
13190 * *
13191 * Comments: if host is found but has no interfaces (should not happen) this *
13192 * function sets 'n' to 0 and no memory is allocated for *
13193 * 'interfaces'. It is a caller responsibility to deallocate *
13194 * memory of 'interfaces' and its components. *
13195 * *
13196 ******************************************************************************/
zbx_dc_get_host_interfaces(zbx_uint64_t hostid,DC_INTERFACE2 ** interfaces,int * n)13197 int zbx_dc_get_host_interfaces(zbx_uint64_t hostid, DC_INTERFACE2 **interfaces, int *n)
13198 {
13199 const ZBX_DC_HOST *host;
13200 int i, ret = FAIL;
13201
13202 if (0 == hostid)
13203 return FAIL;
13204
13205 RDLOCK_CACHE;
13206
13207 /* find host entry in 'config->hosts' hashset */
13208
13209 if (NULL == (host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)))
13210 goto unlock;
13211
13212 /* allocate memory for results */
13213
13214 if (0 < (*n = host->interfaces_v.values_num))
13215 *interfaces = (DC_INTERFACE2 *)zbx_malloc(NULL, sizeof(DC_INTERFACE2) * (size_t)*n);
13216
13217 /* copy data about all host interfaces */
13218
13219 for (i = 0; i < *n; i++)
13220 {
13221 const ZBX_DC_INTERFACE *src = (const ZBX_DC_INTERFACE *)host->interfaces_v.values[i];
13222 DC_INTERFACE2 *dst = *interfaces + i;
13223
13224 dst->interfaceid = src->interfaceid;
13225 dst->type = src->type;
13226 dst->main = src->main;
13227 dst->useip = src->useip;
13228 strscpy(dst->ip_orig, src->ip);
13229 strscpy(dst->dns_orig, src->dns);
13230 strscpy(dst->port_orig, src->port);
13231 dst->addr = (1 == src->useip ? dst->ip_orig : dst->dns_orig);
13232
13233 if (INTERFACE_TYPE_SNMP == dst->type)
13234 {
13235 ZBX_DC_SNMPINTERFACE *snmp;
13236
13237 if (NULL == (snmp = (ZBX_DC_SNMPINTERFACE *)zbx_hashset_search(&config->interfaces_snmp,
13238 &dst->interfaceid)))
13239 {
13240 zbx_free(*interfaces);
13241 goto unlock;
13242 }
13243
13244 dst->bulk = snmp->bulk;
13245 dst->snmp_version= snmp->version;
13246 }
13247 }
13248
13249 ret = SUCCEED;
13250 unlock:
13251 UNLOCK_CACHE;
13252
13253 return ret;
13254 }
13255
13256 /******************************************************************************
13257 * *
13258 * Function: DCconfig_items_apply_changes *
13259 * *
13260 * Purpose: apply item state, error, mtime, lastlogsize changes to *
13261 * configuration cache *
13262 * *
13263 ******************************************************************************/
DCconfig_items_apply_changes(const zbx_vector_ptr_t * item_diff)13264 void DCconfig_items_apply_changes(const zbx_vector_ptr_t *item_diff)
13265 {
13266 int i;
13267 const zbx_item_diff_t *diff;
13268 ZBX_DC_ITEM *dc_item;
13269
13270 if (0 == item_diff->values_num)
13271 return;
13272
13273 WRLOCK_CACHE;
13274
13275 for (i = 0; i < item_diff->values_num; i++)
13276 {
13277 diff = (const zbx_item_diff_t *)item_diff->values[i];
13278
13279 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &diff->itemid)))
13280 continue;
13281
13282 if (0 != (ZBX_FLAGS_ITEM_DIFF_UPDATE_LASTLOGSIZE & diff->flags))
13283 dc_item->lastlogsize = diff->lastlogsize;
13284
13285 if (0 != (ZBX_FLAGS_ITEM_DIFF_UPDATE_MTIME & diff->flags))
13286 dc_item->mtime = diff->mtime;
13287
13288 if (0 != (ZBX_FLAGS_ITEM_DIFF_UPDATE_ERROR & diff->flags))
13289 DCstrpool_replace(1, &dc_item->error, diff->error);
13290
13291 if (0 != (ZBX_FLAGS_ITEM_DIFF_UPDATE_STATE & diff->flags))
13292 dc_item->state = diff->state;
13293 }
13294
13295 UNLOCK_CACHE;
13296 }
13297
13298 /******************************************************************************
13299 * *
13300 * Function: DCconfig_update_inventory_values *
13301 * *
13302 * Purpose: update automatic inventory in configuration cache *
13303 * *
13304 ******************************************************************************/
DCconfig_update_inventory_values(const zbx_vector_ptr_t * inventory_values)13305 void DCconfig_update_inventory_values(const zbx_vector_ptr_t *inventory_values)
13306 {
13307 ZBX_DC_HOST_INVENTORY *host_inventory = NULL;
13308 int i;
13309
13310 WRLOCK_CACHE;
13311
13312 for (i = 0; i < inventory_values->values_num; i++)
13313 {
13314 const zbx_inventory_value_t *inventory_value = (zbx_inventory_value_t *)inventory_values->values[i];
13315 const char **value;
13316
13317 if (NULL == host_inventory || inventory_value->hostid != host_inventory->hostid)
13318 {
13319 host_inventory = (ZBX_DC_HOST_INVENTORY *)zbx_hashset_search(&config->host_inventories_auto, &inventory_value->hostid);
13320
13321 if (NULL == host_inventory)
13322 continue;
13323 }
13324
13325 value = &host_inventory->values[inventory_value->idx];
13326
13327 DCstrpool_replace((NULL != *value ? 1 : 0), value, inventory_value->value);
13328 }
13329
13330 UNLOCK_CACHE;
13331 }
13332
13333 /******************************************************************************
13334 * *
13335 * Function: dc_get_host_inventory_value_by_hostid *
13336 * *
13337 * Purpose: find inventory value in automatically populated cache, if not *
13338 * found then look in main inventory cache *
13339 * *
13340 * Comments: This function must be called inside configuration cache read *
13341 * (or write) lock. *
13342 * *
13343 ******************************************************************************/
dc_get_host_inventory_value_by_hostid(zbx_uint64_t hostid,char ** replace_to,int value_idx)13344 static int dc_get_host_inventory_value_by_hostid(zbx_uint64_t hostid, char **replace_to, int value_idx)
13345 {
13346 const ZBX_DC_HOST_INVENTORY *dc_inventory;
13347
13348 if (NULL != (dc_inventory = (const ZBX_DC_HOST_INVENTORY *)zbx_hashset_search(&config->host_inventories_auto,
13349 &hostid)) && NULL != dc_inventory->values[value_idx])
13350 {
13351 *replace_to = zbx_strdup(*replace_to, dc_inventory->values[value_idx]);
13352 return SUCCEED;
13353 }
13354
13355 if (NULL != (dc_inventory = (const ZBX_DC_HOST_INVENTORY *)zbx_hashset_search(&config->host_inventories,
13356 &hostid)))
13357 {
13358 *replace_to = zbx_strdup(*replace_to, dc_inventory->values[value_idx]);
13359 return SUCCEED;
13360 }
13361
13362 return FAIL;
13363 }
13364
13365 /******************************************************************************
13366 * *
13367 * Function: DCget_host_inventory_value_by_itemid *
13368 * *
13369 * Purpose: find inventory value in automatically populated cache, if not *
13370 * found then look in main inventory cache *
13371 * *
13372 ******************************************************************************/
DCget_host_inventory_value_by_itemid(zbx_uint64_t itemid,char ** replace_to,int value_idx)13373 int DCget_host_inventory_value_by_itemid(zbx_uint64_t itemid, char **replace_to, int value_idx)
13374 {
13375 const ZBX_DC_ITEM *dc_item;
13376 int ret = FAIL;
13377
13378 RDLOCK_CACHE;
13379
13380 if (NULL != (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemid)))
13381 ret = dc_get_host_inventory_value_by_hostid(dc_item->hostid, replace_to, value_idx);
13382
13383 UNLOCK_CACHE;
13384
13385 return ret;
13386 }
13387
13388 /******************************************************************************
13389 * *
13390 * Function: DCget_host_inventory_value_by_hostid *
13391 * *
13392 * Purpose: find inventory value in automatically populated cache, if not *
13393 * found then look in main inventory cache *
13394 * *
13395 ******************************************************************************/
DCget_host_inventory_value_by_hostid(zbx_uint64_t hostid,char ** replace_to,int value_idx)13396 int DCget_host_inventory_value_by_hostid(zbx_uint64_t hostid, char **replace_to, int value_idx)
13397 {
13398 int ret;
13399
13400 RDLOCK_CACHE;
13401
13402 ret = dc_get_host_inventory_value_by_hostid(hostid, replace_to, value_idx);
13403
13404 UNLOCK_CACHE;
13405
13406 return ret;
13407 }
13408
13409 /******************************************************************************
13410 * *
13411 * Function: zbx_dc_get_trigger_dependencies *
13412 * *
13413 * Purpose: checks/returns trigger dependencies for a set of triggers *
13414 * *
13415 * Parameter: triggerids - [IN] the currently processing trigger ids *
13416 * deps - [OUT] list of dependency check results for failed *
13417 * or unresolved dependencies *
13418 * *
13419 * Comments: This function returns list of zbx_trigger_dep_t structures *
13420 * for failed or unresolved dependency checks. *
13421 * Dependency check is failed if any of the master triggers that *
13422 * are not being processed in this batch (present in triggerids *
13423 * vector) has a problem value. *
13424 * Dependency check is unresolved if a master trigger is being *
13425 * processed in this batch (present in triggerids vector) and no *
13426 * other master triggers have problem value. *
13427 * Dependency check is successful if all master triggers (if any) *
13428 * have OK value and are not being processed in this batch. *
13429 * *
13430 ******************************************************************************/
zbx_dc_get_trigger_dependencies(const zbx_vector_uint64_t * triggerids,zbx_vector_ptr_t * deps)13431 void zbx_dc_get_trigger_dependencies(const zbx_vector_uint64_t *triggerids, zbx_vector_ptr_t *deps)
13432 {
13433 int i, ret;
13434 const ZBX_DC_TRIGGER_DEPLIST *trigdep;
13435 zbx_vector_uint64_t masterids;
13436 zbx_trigger_dep_t *dep;
13437
13438 zbx_vector_uint64_create(&masterids);
13439 zbx_vector_uint64_reserve(&masterids, 64);
13440
13441 RDLOCK_CACHE;
13442
13443 for (i = 0; i < triggerids->values_num; i++)
13444 {
13445 if (NULL == (trigdep = (ZBX_DC_TRIGGER_DEPLIST *)zbx_hashset_search(&config->trigdeps, &triggerids->values[i])))
13446 continue;
13447
13448 if (FAIL == (ret = DCconfig_check_trigger_dependencies_rec(trigdep, 0, triggerids, &masterids)) ||
13449 0 != masterids.values_num)
13450 {
13451 dep = (zbx_trigger_dep_t *)zbx_malloc(NULL, sizeof(zbx_trigger_dep_t));
13452 dep->triggerid = triggerids->values[i];
13453 zbx_vector_uint64_create(&dep->masterids);
13454
13455 if (SUCCEED == ret)
13456 {
13457 dep->status = ZBX_TRIGGER_DEPENDENCY_UNRESOLVED;
13458 zbx_vector_uint64_append_array(&dep->masterids, masterids.values, masterids.values_num);
13459 }
13460 else
13461 dep->status = ZBX_TRIGGER_DEPENDENCY_FAIL;
13462
13463 zbx_vector_ptr_append(deps, dep);
13464 }
13465
13466 zbx_vector_uint64_clear(&masterids);
13467 }
13468
13469 UNLOCK_CACHE;
13470
13471 zbx_vector_uint64_destroy(&masterids);
13472 }
13473
13474 /******************************************************************************
13475 * *
13476 * Function: zbx_dc_reschedule_items *
13477 * *
13478 * Purpose: reschedules items that are processed by the target daemon *
13479 * *
13480 * Parameter: itemids - [IN] the item identifiers *
13481 * nextcheck - [IN] the schedueld time *
13482 * proxy_hostids - [OUT] the proxy_hostids of the given itemids *
13483 * (optional, can be NULL) *
13484 * *
13485 * Comments: On server this function reschedules items monitored by server. *
13486 * On proxy only items monitored by the proxy is accessible, so *
13487 * all items can be safely rescheduled. *
13488 * *
13489 ******************************************************************************/
zbx_dc_reschedule_items(const zbx_vector_uint64_t * itemids,int nextcheck,zbx_uint64_t * proxy_hostids)13490 void zbx_dc_reschedule_items(const zbx_vector_uint64_t *itemids, int nextcheck, zbx_uint64_t *proxy_hostids)
13491 {
13492 int i;
13493 ZBX_DC_ITEM *dc_item;
13494 ZBX_DC_HOST *dc_host;
13495 zbx_uint64_t proxy_hostid;
13496
13497 WRLOCK_CACHE;
13498
13499 for (i = 0; i < itemids->values_num; i++)
13500 {
13501 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemids->values[i])) ||
13502 NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
13503 {
13504 zabbix_log(LOG_LEVEL_WARNING, "cannot perform check now for itemid [" ZBX_FS_UI64 "]"
13505 ": item is not in cache", itemids->values[i]);
13506
13507 proxy_hostid = 0;
13508 }
13509 else if (0 == dc_item->schedulable)
13510 {
13511 zabbix_log(LOG_LEVEL_WARNING, "cannot perform check now for item \"%s\" on host \"%s\""
13512 ": item configuration error", dc_item->key, dc_host->host);
13513
13514 proxy_hostid = 0;
13515 }
13516 else if (0 == (proxy_hostid = dc_host->proxy_hostid) ||
13517 SUCCEED == is_item_processed_by_server(dc_item->type, dc_item->key))
13518 {
13519 dc_requeue_item_at(dc_item, dc_host, nextcheck);
13520 proxy_hostid = 0;
13521 }
13522
13523 if (NULL != proxy_hostids)
13524 proxy_hostids[i] = proxy_hostid;
13525 }
13526
13527 UNLOCK_CACHE;
13528 }
13529
13530 /******************************************************************************
13531 * *
13532 * Function: zbx_dc_proxy_update_nodata *
13533 * *
13534 * Purpose: stop suppress mode of the nodata() trigger *
13535 * *
13536 * Parameter: subscriptions - [IN] the array of trigger id and time of values *
13537 * *
13538 ******************************************************************************/
zbx_dc_proxy_update_nodata(zbx_vector_uint64_pair_t * subscriptions)13539 void zbx_dc_proxy_update_nodata(zbx_vector_uint64_pair_t *subscriptions)
13540 {
13541 ZBX_DC_PROXY *proxy = NULL;
13542 int i;
13543 zbx_uint64_pair_t p;
13544
13545 WRLOCK_CACHE;
13546
13547 for (i = 0; i < subscriptions->values_num; i++)
13548 {
13549 p = subscriptions->values[i];
13550
13551 if ((NULL == proxy || p.first != proxy->hostid) &&
13552 NULL == (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &p.first)))
13553 {
13554 continue;
13555 }
13556
13557 if (0 == (proxy->nodata_win.flags & ZBX_PROXY_SUPPRESS_ACTIVE))
13558 continue;
13559
13560 if (0 != (proxy->nodata_win.flags & ZBX_PROXY_SUPPRESS_MORE) &&
13561 (int)p.second > proxy->nodata_win.period_end)
13562 {
13563 continue;
13564 }
13565
13566 proxy->nodata_win.values_num --;
13567
13568 if (0 < proxy->nodata_win.values_num || 0 != (proxy->nodata_win.flags & ZBX_PROXY_SUPPRESS_MORE))
13569 continue;
13570
13571 proxy->nodata_win.flags = ZBX_PROXY_SUPPRESS_DISABLE;
13572 proxy->nodata_win.period_end = 0;
13573 proxy->nodata_win.values_num = 0;
13574 }
13575
13576 UNLOCK_CACHE;
13577 }
13578
13579 /******************************************************************************
13580 * *
13581 * Function: zbx_dc_update_proxy *
13582 * *
13583 * Purpose: updates changed proxy data in configuration cache and updates *
13584 * diff flags to reflect the updated data *
13585 * *
13586 * Parameter: diff - [IN/OUT] the properties to update *
13587 * *
13588 ******************************************************************************/
zbx_dc_update_proxy(zbx_proxy_diff_t * diff)13589 void zbx_dc_update_proxy(zbx_proxy_diff_t *diff)
13590 {
13591 ZBX_DC_PROXY *proxy;
13592
13593 WRLOCK_CACHE;
13594
13595 if (diff->lastaccess < config->proxy_lastaccess_ts)
13596 diff->lastaccess = config->proxy_lastaccess_ts;
13597
13598 if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &diff->hostid)))
13599 {
13600 if (0 != (diff->flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_LASTACCESS))
13601 {
13602 int lost = 0; /* communication lost */
13603
13604 if (0 != (diff->flags &
13605 (ZBX_FLAGS_PROXY_DIFF_UPDATE_HEARTBEAT | ZBX_FLAGS_PROXY_DIFF_UPDATE_CONFIG)))
13606 {
13607 int delay = diff->lastaccess - proxy->lastaccess;
13608
13609 if (NET_DELAY_MAX < delay)
13610 lost = 1;
13611 }
13612
13613 if (0 == lost && proxy->lastaccess != diff->lastaccess)
13614 proxy->lastaccess = diff->lastaccess;
13615
13616 /* proxy last access in database is updated separately in */
13617 /* every ZBX_PROXY_LASTACCESS_UPDATE_FREQUENCY seconds */
13618 diff->flags &= (~ZBX_FLAGS_PROXY_DIFF_UPDATE_LASTACCESS);
13619 }
13620
13621 if (0 != (diff->flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_VERSION))
13622 {
13623 if (proxy->version != diff->version)
13624 proxy->version = diff->version;
13625 else
13626 diff->flags &= (~ZBX_FLAGS_PROXY_DIFF_UPDATE_VERSION);
13627 }
13628
13629 if (0 != (diff->flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_COMPRESS))
13630 {
13631 if (proxy->auto_compress == diff->compress)
13632 diff->flags &= (~ZBX_FLAGS_PROXY_DIFF_UPDATE_COMPRESS);
13633 proxy->auto_compress = diff->compress;
13634 }
13635 if (0 != (diff->flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_LASTERROR))
13636 {
13637 proxy->last_version_error_time = diff->last_version_error_time;
13638 diff->flags &= (~ZBX_FLAGS_PROXY_DIFF_UPDATE_LASTERROR);
13639 }
13640
13641 if (0 != (diff->flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_PROXYDELAY))
13642 {
13643 proxy->proxy_delay = diff->proxy_delay;
13644 diff->flags &= (~ZBX_FLAGS_PROXY_DIFF_UPDATE_PROXYDELAY);
13645 }
13646
13647 if (0 != (diff->flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_SUPPRESS_WIN))
13648 {
13649 zbx_proxy_suppress_t *ps_win = &proxy->nodata_win, *ds_win = &diff->nodata_win;
13650
13651 if ((ps_win->flags & ZBX_PROXY_SUPPRESS_ACTIVE) != (ds_win->flags & ZBX_PROXY_SUPPRESS_ACTIVE))
13652 {
13653 ps_win->period_end = ds_win->period_end;
13654 }
13655
13656 if (ps_win->flags != ds_win->flags)
13657 ps_win->flags = ds_win->flags;
13658
13659 if (0 > ps_win->values_num) /* some new values was processed faster than old */
13660 ps_win->values_num = 0; /* we will suppress more */
13661
13662 ps_win->values_num += ds_win->values_num;
13663 diff->flags &= (~ZBX_FLAGS_PROXY_DIFF_UPDATE_SUPPRESS_WIN);
13664 }
13665 }
13666
13667 UNLOCK_CACHE;
13668 }
13669
13670 /******************************************************************************
13671 * *
13672 * Function: zbx_dc_get_proxy_lastaccess *
13673 * *
13674 * Purpose: returns proxy lastaccess changes since last lastaccess request *
13675 * *
13676 * Parameter: lastaccess - [OUT] last access updates for proxies that need *
13677 * to be synced with database, sorted by *
13678 * hostid *
13679 * *
13680 ******************************************************************************/
zbx_dc_get_proxy_lastaccess(zbx_vector_uint64_pair_t * lastaccess)13681 void zbx_dc_get_proxy_lastaccess(zbx_vector_uint64_pair_t *lastaccess)
13682 {
13683 ZBX_DC_PROXY *proxy;
13684 int now;
13685
13686 if (ZBX_PROXY_LASTACCESS_UPDATE_FREQUENCY < (now = time(NULL)) - config->proxy_lastaccess_ts)
13687 {
13688 zbx_hashset_iter_t iter;
13689
13690 WRLOCK_CACHE;
13691
13692 zbx_hashset_iter_reset(&config->proxies, &iter);
13693
13694 while (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_iter_next(&iter)))
13695 {
13696 if (proxy->lastaccess >= config->proxy_lastaccess_ts)
13697 {
13698 zbx_uint64_pair_t pair = {proxy->hostid, proxy->lastaccess};
13699
13700 zbx_vector_uint64_pair_append(lastaccess, pair);
13701 }
13702 }
13703
13704 config->proxy_lastaccess_ts = now;
13705
13706 UNLOCK_CACHE;
13707
13708 zbx_vector_uint64_pair_sort(lastaccess, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
13709 }
13710 }
13711
13712 /******************************************************************************
13713 * *
13714 * Function: zbx_dc_get_session_token *
13715 * *
13716 * Purpose: returns session token *
13717 * *
13718 * Return value: pointer to session token (NULL for server). *
13719 * *
13720 * Comments: The session token is generated during configuration cache *
13721 * initialization and is not changed later. Therefore no locking *
13722 * is required. *
13723 * *
13724 ******************************************************************************/
zbx_dc_get_session_token(void)13725 const char *zbx_dc_get_session_token(void)
13726 {
13727 return config->session_token;
13728 }
13729
13730 /******************************************************************************
13731 * *
13732 * Function: zbx_dc_get_or_create_data_session *
13733 * *
13734 * Purpose: returns data session, creates a new session if none found *
13735 * *
13736 * Parameter: hostid - [IN] the host (proxy) identifier *
13737 * token - [IN] the session token (not NULL) *
13738 * *
13739 * Return value: pointer to data session. *
13740 * *
13741 * Comments: The last_valueid property of the returned session object can be *
13742 * updated directly without locking cache because only one data *
13743 * session is updated at the same time and after retrieving the *
13744 * session object will not be deleted for 24 hours. *
13745 * *
13746 ******************************************************************************/
zbx_dc_get_or_create_data_session(zbx_uint64_t hostid,const char * token)13747 zbx_data_session_t *zbx_dc_get_or_create_data_session(zbx_uint64_t hostid, const char *token)
13748 {
13749 zbx_data_session_t *session, session_local;
13750 time_t now;
13751
13752 now = time(NULL);
13753 session_local.hostid = hostid;
13754 session_local.token = token;
13755
13756 RDLOCK_CACHE;
13757 session = (zbx_data_session_t *)zbx_hashset_search(&config->data_sessions, &session_local);
13758 UNLOCK_CACHE;
13759
13760 if (NULL == session)
13761 {
13762 WRLOCK_CACHE;
13763 session = (zbx_data_session_t *)zbx_hashset_insert(&config->data_sessions, &session_local,
13764 sizeof(session_local));
13765 session->token = dc_strdup(token);
13766 UNLOCK_CACHE;
13767
13768 session->last_valueid = 0;
13769 }
13770
13771 session->lastaccess = now;
13772
13773 return session;
13774 }
13775
13776 /******************************************************************************
13777 * *
13778 * Function: zbx_dc_cleanup_data_sessions *
13779 * *
13780 * Purpose: removes data sessions not accessed for 24 hours *
13781 * *
13782 ******************************************************************************/
zbx_dc_cleanup_data_sessions(void)13783 void zbx_dc_cleanup_data_sessions(void)
13784 {
13785 zbx_data_session_t *session;
13786 zbx_hashset_iter_t iter;
13787 time_t now;
13788
13789 now = time(NULL);
13790
13791 WRLOCK_CACHE;
13792
13793 zbx_hashset_iter_reset(&config->data_sessions, &iter);
13794 while (NULL != (session = (zbx_data_session_t *)zbx_hashset_iter_next(&iter)))
13795 {
13796 if (session->lastaccess + SEC_PER_DAY <= now)
13797 {
13798 __config_mem_free_func((char *)session->token);
13799 zbx_hashset_iter_remove(&iter);
13800 }
13801 }
13802
13803 UNLOCK_CACHE;
13804 }
13805
zbx_gather_item_tags(ZBX_DC_ITEM * item,zbx_vector_ptr_t * item_tags)13806 static void zbx_gather_item_tags(ZBX_DC_ITEM *item, zbx_vector_ptr_t *item_tags)
13807 {
13808 zbx_dc_item_tag_t *dc_tag;
13809 zbx_item_tag_t *tag;
13810 int i;
13811
13812 for (i = 0; i < item->tags.values_num; i++)
13813 {
13814 dc_tag = (zbx_dc_item_tag_t *)item->tags.values[i];
13815 tag = (zbx_item_tag_t *) zbx_malloc(NULL, sizeof(zbx_item_tag_t));
13816 tag->tag.tag = zbx_strdup(NULL, dc_tag->tag);
13817 tag->tag.value = zbx_strdup(NULL, dc_tag->value);
13818 zbx_vector_ptr_append(item_tags, tag);
13819 }
13820 }
13821
zbx_gather_tags_from_host(zbx_uint64_t hostid,zbx_vector_ptr_t * item_tags)13822 static void zbx_gather_tags_from_host(zbx_uint64_t hostid, zbx_vector_ptr_t *item_tags)
13823 {
13824 zbx_dc_host_tag_index_t *dc_tag_index;
13825 zbx_dc_host_tag_t *dc_tag;
13826 zbx_item_tag_t *tag;
13827 int i;
13828
13829 if (NULL != (dc_tag_index = zbx_hashset_search(&config->host_tags_index, &hostid)))
13830 {
13831 for (i = 0; i < dc_tag_index->tags.values_num; i++)
13832 {
13833 dc_tag = (zbx_dc_host_tag_t *)dc_tag_index->tags.values[i];
13834 tag = (zbx_item_tag_t *) zbx_malloc(NULL, sizeof(zbx_item_tag_t));
13835 tag->tag.tag = zbx_strdup(NULL, dc_tag->tag);
13836 tag->tag.value = zbx_strdup(NULL, dc_tag->value);
13837 zbx_vector_ptr_append(item_tags, tag);
13838 }
13839 }
13840 }
13841
zbx_gather_tags_from_template_chain(zbx_uint64_t itemid,zbx_vector_ptr_t * item_tags)13842 static void zbx_gather_tags_from_template_chain(zbx_uint64_t itemid, zbx_vector_ptr_t *item_tags)
13843 {
13844 ZBX_DC_TEMPLATE_ITEM *item;
13845
13846 if (NULL != (item = (ZBX_DC_TEMPLATE_ITEM *)zbx_hashset_search(&config->template_items, &itemid)))
13847 {
13848 zbx_gather_tags_from_host(item->hostid, item_tags);
13849
13850 if (0 != item->templateid)
13851 zbx_gather_tags_from_template_chain(item->templateid, item_tags);
13852 }
13853 }
13854
zbx_get_item_tags(zbx_uint64_t itemid,zbx_vector_ptr_t * item_tags)13855 static void zbx_get_item_tags(zbx_uint64_t itemid, zbx_vector_ptr_t *item_tags)
13856 {
13857 ZBX_DC_ITEM *item;
13858 ZBX_DC_PROTOTYPE_ITEM *lld_item;
13859 zbx_item_tag_t *tag;
13860 int n, i;
13861
13862 if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemid)))
13863 return;
13864
13865 n = item_tags->values_num;
13866
13867 zbx_gather_item_tags(item, item_tags);
13868
13869 zbx_gather_tags_from_host(item->hostid, item_tags);
13870
13871 if (0 != item->templateid)
13872 zbx_gather_tags_from_template_chain(item->templateid, item_tags);
13873
13874 /* check for discovered item */
13875 if (0 != item->parent_itemid && 4 == item->flags)
13876 {
13877 if (NULL != (lld_item = (ZBX_DC_PROTOTYPE_ITEM *)zbx_hashset_search(&config->prototype_items,
13878 &item->parent_itemid)))
13879 {
13880 if (0 != lld_item->templateid)
13881 zbx_gather_tags_from_template_chain(lld_item->templateid, item_tags);
13882 }
13883 }
13884
13885 /* assign hostid and itemid values to newly gathered tags */
13886 for (i = n; i < item_tags->values_num; i++)
13887 {
13888 tag = (zbx_item_tag_t *)item_tags->values[i];
13889 tag->hostid = item->hostid;
13890 tag->itemid = item->itemid;
13891 }
13892 }
13893
zbx_dc_get_item_tags(zbx_uint64_t itemid,zbx_vector_ptr_t * item_tags)13894 void zbx_dc_get_item_tags(zbx_uint64_t itemid, zbx_vector_ptr_t *item_tags)
13895 {
13896 RDLOCK_CACHE;
13897
13898 zbx_get_item_tags(itemid, item_tags);
13899
13900 UNLOCK_CACHE;
13901 }
13902
zbx_dc_get_item_tags_by_functionids(const zbx_uint64_t * functionids,size_t functionids_num,zbx_vector_ptr_t * item_tags)13903 void zbx_dc_get_item_tags_by_functionids(const zbx_uint64_t *functionids, size_t functionids_num,
13904 zbx_vector_ptr_t *item_tags)
13905 {
13906 const ZBX_DC_FUNCTION *dc_function;
13907 size_t i;
13908
13909 RDLOCK_CACHE;
13910
13911 for (i = 0; i < functionids_num; i++)
13912 {
13913 if (NULL == (dc_function = (const ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions,
13914 &functionids[i])))
13915 {
13916 continue;
13917 }
13918
13919 zbx_get_item_tags(dc_function->itemid, item_tags);
13920 }
13921
13922 UNLOCK_CACHE;
13923 }
13924
13925 /******************************************************************************
13926 * *
13927 * Function: DCget_proxy_nodata_win *
13928 * *
13929 * Purpose: retrieves proxy suppress window data from the cache *
13930 * *
13931 * Parameters: hostid - [IN] proxy host id *
13932 * nodata_win - [OUT] suppress window data *
13933 * lastaccess - [OUT] proxy last access time *
13934 * *
13935 * Return value: SUCCEED - the data is retrieved *
13936 * FAIL - the data cannot be retrieved, proxy not found in *
13937 * configuration cache *
13938 * *
13939 ******************************************************************************/
DCget_proxy_nodata_win(zbx_uint64_t hostid,zbx_proxy_suppress_t * nodata_win,int * lastaccess)13940 int DCget_proxy_nodata_win(zbx_uint64_t hostid, zbx_proxy_suppress_t *nodata_win, int *lastaccess)
13941 {
13942 const ZBX_DC_PROXY *dc_proxy;
13943 int ret;
13944
13945 RDLOCK_CACHE;
13946
13947 if (NULL != (dc_proxy = (const ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &hostid)))
13948 {
13949 const zbx_proxy_suppress_t *proxy_nodata_win = &dc_proxy->nodata_win;
13950
13951 nodata_win->period_end = proxy_nodata_win->period_end;
13952 nodata_win->values_num = proxy_nodata_win->values_num;
13953 nodata_win->flags = proxy_nodata_win->flags;
13954 *lastaccess = dc_proxy->lastaccess;
13955 ret = SUCCEED;
13956 }
13957 else
13958 ret = FAIL;
13959
13960 UNLOCK_CACHE;
13961
13962 return ret;
13963 }
13964
13965 /******************************************************************************
13966 * *
13967 * Function: DCget_proxy_delay *
13968 * *
13969 * Purpose: retrieves proxy delay from the cache *
13970 * *
13971 * Parameters: hostid - [IN] proxy host id *
13972 * delay - [OUT] proxy delay *
13973 * *
13974 * Return value: SUCCEED - the delay is retrieved *
13975 * FAIL - the delay cannot be retrieved, proxy not found in *
13976 * configuration cache *
13977 * *
13978 ******************************************************************************/
DCget_proxy_delay(zbx_uint64_t hostid,int * delay)13979 int DCget_proxy_delay(zbx_uint64_t hostid, int *delay)
13980 {
13981 const ZBX_DC_PROXY *dc_proxy;
13982 int ret;
13983
13984 RDLOCK_CACHE;
13985
13986 if (NULL != (dc_proxy = (const ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &hostid)))
13987 {
13988 *delay = dc_proxy->proxy_delay;
13989 ret = SUCCEED;
13990 }
13991 else
13992 ret = FAIL;
13993
13994 UNLOCK_CACHE;
13995
13996 return ret;
13997 }
13998
13999 /******************************************************************************
14000 * *
14001 * Function: DCget_proxy_delay_by_name *
14002 * *
14003 * Purpose: retrieves proxy delay from the cache *
14004 * *
14005 * Parameters: name - [IN] proxy host name *
14006 * delay - [OUT] proxy delay *
14007 * error - [OUT] error *
14008 * *
14009 * Return value: SUCCEED - proxy delay is retrieved *
14010 * FAIL - proxy delay cannot be retrieved *
14011 * *
14012 ******************************************************************************/
DCget_proxy_delay_by_name(const char * name,int * delay,char ** error)14013 int DCget_proxy_delay_by_name(const char *name, int *delay, char **error)
14014 {
14015 const ZBX_DC_HOST *dc_host;
14016
14017 RDLOCK_CACHE;
14018 dc_host = DCfind_proxy(name);
14019 UNLOCK_CACHE;
14020
14021 if (NULL == dc_host)
14022 {
14023 *error = zbx_dsprintf(*error, "Proxy \"%s\" not found.", name);
14024 return FAIL;
14025 }
14026
14027 if (SUCCEED != DCget_proxy_delay(dc_host->hostid, delay))
14028 {
14029 *error = zbx_dsprintf(*error, "Proxy \"%s\" not found in configuration cache.", name);
14030 return FAIL;
14031 }
14032
14033 return SUCCEED;
14034 }
14035
14036 /******************************************************************************
14037 * *
14038 * Function: zbx_dc_set_macro_env *
14039 * *
14040 * Purpose: sets user macro environment security level *
14041 * *
14042 * Parameter: env - [IN] the security level (see ZBX_MACRO_ENV_* defines) *
14043 * *
14044 * Comments: The security level affects how the secret macros are resolved - *
14045 * as they values or '******'. *
14046 * *
14047 ******************************************************************************/
zbx_dc_set_macro_env(unsigned char env)14048 unsigned char zbx_dc_set_macro_env(unsigned char env)
14049 {
14050 unsigned char old_env = macro_env;
14051 macro_env = env;
14052 return old_env;
14053 }
14054
14055 /******************************************************************************
14056 * *
14057 * Function: zbx_dc_get_instanceid *
14058 * *
14059 * Purpose: returns server/proxy instance id *
14060 * *
14061 * Return value: the instance id *
14062 * *
14063 ******************************************************************************/
zbx_dc_get_instanceid(void)14064 const char *zbx_dc_get_instanceid(void)
14065 {
14066 /* instanceid is initialized during the first configuration cache synchronization */
14067 /* and is never updated - so it can be accessed without locking cache */
14068 return config->config->instanceid;
14069 }
14070
14071 /******************************************************************************
14072 * *
14073 * Function: dc_expand_user_macros_in_func_params *
14074 * *
14075 * Purpose: expand user macros in trigger function parameters *
14076 * *
14077 * Parameters: params - [IN] the function parameters *
14078 * hostid - [IN] host of the item used in function *
14079 * *
14080 * Return value: The function parameters with expanded user macros. *
14081 * *
14082 ******************************************************************************/
dc_expand_user_macros_in_func_params(const char * params,zbx_uint64_t hostid)14083 char *dc_expand_user_macros_in_func_params(const char *params, zbx_uint64_t hostid)
14084 {
14085 const char *ptr;
14086 size_t params_len;
14087 char *buf;
14088 size_t buf_alloc, buf_offset = 0, sep_pos;
14089
14090 if ('\0' == *params)
14091 return zbx_strdup(NULL, params);
14092
14093 buf_alloc = params_len = strlen(params);
14094 buf = zbx_malloc(NULL, buf_alloc);
14095
14096 for (ptr = params; ptr < params + params_len; ptr += sep_pos + 1)
14097 {
14098 size_t param_pos, param_len;
14099 int quoted;
14100 char *param, *resolved_param;
14101
14102 zbx_function_param_parse(ptr, ¶m_pos, ¶m_len, &sep_pos);
14103
14104 param = zbx_function_param_unquote_dyn(ptr + param_pos, param_len, "ed);
14105 resolved_param = dc_expand_user_macros(param, &hostid, 1);
14106
14107 if (SUCCEED == zbx_function_param_quote(&resolved_param, quoted))
14108 zbx_strcpy_alloc(&buf, &buf_alloc, &buf_offset, resolved_param);
14109 else
14110 zbx_strncpy_alloc(&buf, &buf_alloc, &buf_offset, ptr + param_pos, param_len);
14111
14112 if (',' == ptr[sep_pos])
14113 zbx_chrcpy_alloc(&buf, &buf_alloc, &buf_offset, ',');
14114
14115 zbx_free(resolved_param);
14116 zbx_free(param);
14117 }
14118
14119 return buf;
14120 }
14121
zbx_dc_expand_user_macros_in_func_params(const char * params,zbx_uint64_t hostid)14122 char *zbx_dc_expand_user_macros_in_func_params(const char *params, zbx_uint64_t hostid)
14123 {
14124 char *resolved_params;
14125
14126 RDLOCK_CACHE;
14127 resolved_params = dc_expand_user_macros_in_func_params(params, hostid);
14128 UNLOCK_CACHE;
14129
14130 return resolved_params;
14131 }
14132
14133 /*********************************************************************************
14134 * *
14135 * Function: zbx_get_host_interfaces_availability *
14136 * *
14137 * Purpose: get host interfaces availability *
14138 * *
14139 * Parameters: hostid - [IN] the host id *
14140 * agents - [OUT] Zabbix agent availability *
14141 * *
14142 ********************************************************************************/
zbx_get_host_interfaces_availability(zbx_uint64_t hostid,zbx_agent_availability_t * agents)14143 void zbx_get_host_interfaces_availability(zbx_uint64_t hostid, zbx_agent_availability_t *agents)
14144 {
14145 const ZBX_DC_INTERFACE *interface;
14146 zbx_hashset_iter_t iter;
14147 int i;
14148
14149 for (i = 0; i < ZBX_AGENT_MAX; i++)
14150 zbx_agent_availability_init(&agents[i], INTERFACE_AVAILABLE_UNKNOWN, "", 0, 0);
14151
14152 RDLOCK_CACHE;
14153
14154 zbx_hashset_iter_reset(&config->interfaces, &iter);
14155
14156 while (NULL != (interface = (const ZBX_DC_INTERFACE *)zbx_hashset_iter_next(&iter)))
14157 {
14158 if (1 != interface->main)
14159 continue;
14160
14161 if (hostid != interface->hostid)
14162 continue;
14163
14164 i = ZBX_AGENT_UNKNOWN;
14165
14166 if (INTERFACE_TYPE_AGENT == interface->type)
14167 i = ZBX_AGENT_ZABBIX;
14168 else if (INTERFACE_TYPE_IPMI == interface->type)
14169 i = ZBX_AGENT_IPMI;
14170 else if (INTERFACE_TYPE_JMX == interface->type)
14171 i = ZBX_AGENT_JMX;
14172 else if (INTERFACE_TYPE_SNMP == interface->type)
14173 i = ZBX_AGENT_SNMP;
14174
14175 if (ZBX_AGENT_UNKNOWN != i)
14176 DCinterface_get_agent_availability(interface, &agents[i]);
14177 }
14178
14179 UNLOCK_CACHE;
14180
14181 }
14182
14183 /*********************************************************************************
14184 * *
14185 * Function: zbx_dc_eval_expand_user_macros *
14186 * *
14187 * Purpose: resolve user macros in parsed expression *
14188 * *
14189 * Parameters: ctx - [IN] the expression evaluation context *
14190 * *
14191 ********************************************************************************/
zbx_dc_eval_expand_user_macros(zbx_eval_context_t * ctx)14192 void zbx_dc_eval_expand_user_macros(zbx_eval_context_t *ctx)
14193 {
14194 zbx_vector_uint64_t hostids, functionids;
14195
14196 zbx_vector_uint64_create(&hostids);
14197 zbx_vector_uint64_create(&functionids);
14198
14199 zbx_eval_get_functionids(ctx, &functionids);
14200 zbx_vector_uint64_sort(&functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
14201 zbx_vector_uint64_uniq(&functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
14202
14203 RDLOCK_CACHE;
14204
14205 dc_get_hostids_by_functionids(functionids.values, functionids.values_num, &hostids);
14206 (void)zbx_eval_expand_user_macros(ctx, hostids.values, hostids.values_num, dc_expand_user_macros_len, NULL);
14207
14208 UNLOCK_CACHE;
14209
14210 zbx_vector_uint64_destroy(&functionids);
14211 zbx_vector_uint64_destroy(&hostids);
14212 }
14213
zbx_dc_maintenance_has_tags(void)14214 int zbx_dc_maintenance_has_tags(void)
14215 {
14216 int ret;
14217
14218 RDLOCK_CACHE;
14219 ret = config->maintenance_tags.num_data != 0 ? SUCCEED : FAIL;
14220 UNLOCK_CACHE;
14221
14222 return ret;
14223 }
14224
14225 #ifdef HAVE_TESTS
14226 # include "../../../tests/libs/zbxdbcache/dc_item_poller_type_update_test.c"
14227 # include "../../../tests/libs/zbxdbcache/dc_function_calculate_nextcheck_test.c"
14228 #endif
14229