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
36 #define ZBX_DBCONFIG_IMPL
37 #include "dbconfig.h"
38 #include "dbsync.h"
39 #include "proxy.h"
40 #include "actions.h"
41
42 int sync_in_progress = 0;
43
44 #define START_SYNC WRLOCK_CACHE; sync_in_progress = 1
45 #define FINISH_SYNC sync_in_progress = 0; UNLOCK_CACHE
46
47 #define ZBX_LOC_NOWHERE 0
48 #define ZBX_LOC_QUEUE 1
49 #define ZBX_LOC_POLLER 2
50
51 #define ZBX_SNMP_OID_TYPE_NORMAL 0
52 #define ZBX_SNMP_OID_TYPE_DYNAMIC 1
53 #define ZBX_SNMP_OID_TYPE_MACRO 2
54
55 /* trigger is functional unless its expression contains disabled or not monitored items */
56 #define TRIGGER_FUNCTIONAL_TRUE 0
57 #define TRIGGER_FUNCTIONAL_FALSE 1
58
59 /* trigger contains time functions and is also scheduled by timer queue */
60 #define ZBX_TRIGGER_TIMER_UNKNOWN 0
61 #define ZBX_TRIGGER_TIMER_QUEUE 1
62
63 /* item priority in poller queue */
64 #define ZBX_QUEUE_PRIORITY_HIGH 0
65 #define ZBX_QUEUE_PRIORITY_NORMAL 1
66 #define ZBX_QUEUE_PRIORITY_LOW 2
67
68 /* shorthand macro for calling in_maintenance_without_data_collection() */
69 #define DCin_maintenance_without_data_collection(dc_host, dc_item) \
70 in_maintenance_without_data_collection(dc_host->maintenance_status, \
71 dc_host->maintenance_type, dc_item->type)
72
73 /******************************************************************************
74 * *
75 * Function: zbx_value_validator_func_t *
76 * *
77 * Purpose: validate macro value when expanding user macros *
78 * *
79 * Parameters: macro - [IN] the user macro *
80 * value - [IN] the macro value *
81 * error - [OUT] the error message *
82 * *
83 * Return value: SUCCEED - the value is valid *
84 * FAIL - otherwise *
85 * *
86 ******************************************************************************/
87 typedef int (*zbx_value_validator_func_t)(const char *macro, const char *value, char **error);
88
89 ZBX_DC_CONFIG *config = NULL;
90 zbx_rwlock_t config_lock = ZBX_RWLOCK_NULL;
91 static zbx_mem_info_t *config_mem;
92
93 extern unsigned char program_type;
94 extern int CONFIG_TIMER_FORKS;
95
96 ZBX_MEM_FUNC_IMPL(__config, config_mem)
97
98 static void dc_maintenance_precache_nested_groups(void);
99
100 /* by default the macro environment is non-secure and all secret macros are masked with ****** */
101 static unsigned char macro_env = ZBX_MACRO_ENV_NONSECURE;
102
103 /******************************************************************************
104 * *
105 * Function: dc_strdup *
106 * *
107 * Purpose: copies string into configuration cache shared memory *
108 * *
109 ******************************************************************************/
dc_strdup(const char * source)110 static char *dc_strdup(const char *source)
111 {
112 char *dst;
113 size_t len;
114
115 len = strlen(source) + 1;
116 dst = (char *)__config_mem_malloc_func(NULL, len);
117 memcpy(dst, source, len);
118 return dst;
119 }
120
121 /******************************************************************************
122 * *
123 * Function: is_item_processed_by_server *
124 * *
125 * Parameters: type - [IN] item type [ITEM_TYPE_* flag] *
126 * key - [IN] item key *
127 * *
128 * Return value: SUCCEED when an item should be processed by server *
129 * FAIL otherwise *
130 * *
131 * Comments: list of the items, always processed by server *
132 * ,------------------+--------------------------------------, *
133 * | type | key | *
134 * +------------------+--------------------------------------+ *
135 * | Zabbix internal | zabbix[host,,items] | *
136 * | Zabbix internal | zabbix[host,,items_unsupported] | *
137 * | Zabbix internal | zabbix[host,discovery,interfaces] | *
138 * | Zabbix internal | zabbix[host,,maintenance] | *
139 * | Zabbix internal | zabbix[proxy,<proxyname>,lastaccess] | *
140 * | Zabbix internal | zabbix[proxy,<proxyname>,delay] | *
141 * | Zabbix aggregate | * | *
142 * | Calculated | * | *
143 * '------------------+--------------------------------------' *
144 * *
145 ******************************************************************************/
is_item_processed_by_server(unsigned char type,const char * key)146 int is_item_processed_by_server(unsigned char type, const char *key)
147 {
148 int ret = FAIL;
149
150 switch (type)
151 {
152 case ITEM_TYPE_AGGREGATE:
153 case ITEM_TYPE_CALCULATED:
154 ret = SUCCEED;
155 break;
156
157 case ITEM_TYPE_INTERNAL:
158 if (0 == strncmp(key, "zabbix[", 7))
159 {
160 AGENT_REQUEST request;
161 char *arg1, *arg2, *arg3;
162
163 init_request(&request);
164
165 if (SUCCEED != parse_item_key(key, &request) || 3 != request.nparam)
166 goto clean;
167
168 arg1 = get_rparam(&request, 0);
169 arg2 = get_rparam(&request, 1);
170 arg3 = get_rparam(&request, 2);
171
172 if (0 == strcmp(arg1, "host"))
173 {
174 if ('\0' == *arg2)
175 {
176 if (0 == strcmp(arg3, "maintenance") || 0 == strcmp(arg3, "items") ||
177 0 == strcmp(arg3, "items_unsupported"))
178 {
179 ret = SUCCEED;
180 }
181 }
182 else if (0 == strcmp(arg2, "discovery") && 0 == strcmp(arg3, "interfaces"))
183 ret = SUCCEED;
184 }
185 else if (0 == strcmp(arg1, "proxy") &&
186 (0 == strcmp(arg3, "lastaccess") || 0 == strcmp(arg3, "delay")))
187 ret = SUCCEED;
188 clean:
189 free_request(&request);
190 }
191 break;
192 }
193
194 return ret;
195 }
196
poller_by_item(unsigned char type,const char * key)197 static unsigned char poller_by_item(unsigned char type, const char *key)
198 {
199 switch (type)
200 {
201 case ITEM_TYPE_SIMPLE:
202 if (SUCCEED == cmp_key_id(key, SERVER_ICMPPING_KEY) ||
203 SUCCEED == cmp_key_id(key, SERVER_ICMPPINGSEC_KEY) ||
204 SUCCEED == cmp_key_id(key, SERVER_ICMPPINGLOSS_KEY))
205 {
206 if (0 == CONFIG_PINGER_FORKS)
207 break;
208
209 return ZBX_POLLER_TYPE_PINGER;
210 }
211 ZBX_FALLTHROUGH;
212 case ITEM_TYPE_ZABBIX:
213 case ITEM_TYPE_SNMP:
214 case ITEM_TYPE_INTERNAL:
215 case ITEM_TYPE_AGGREGATE:
216 case ITEM_TYPE_EXTERNAL:
217 case ITEM_TYPE_DB_MONITOR:
218 case ITEM_TYPE_SSH:
219 case ITEM_TYPE_TELNET:
220 case ITEM_TYPE_CALCULATED:
221 case ITEM_TYPE_HTTPAGENT:
222 if (0 == CONFIG_POLLER_FORKS)
223 break;
224
225 return ZBX_POLLER_TYPE_NORMAL;
226 case ITEM_TYPE_IPMI:
227 if (0 == CONFIG_IPMIPOLLER_FORKS)
228 break;
229
230 return ZBX_POLLER_TYPE_IPMI;
231 case ITEM_TYPE_JMX:
232 if (0 == CONFIG_JAVAPOLLER_FORKS)
233 break;
234
235 return ZBX_POLLER_TYPE_JAVA;
236 }
237
238 return ZBX_NO_POLLER;
239 }
240
241 /******************************************************************************
242 * *
243 * Function: zbx_is_counted_in_item_queue *
244 * *
245 * Purpose: determine whether the given item type is counted in item queue *
246 * *
247 * Return value: SUCCEED if item is counted in the queue, FAIL otherwise *
248 * *
249 ******************************************************************************/
zbx_is_counted_in_item_queue(unsigned char type,const char * key)250 int zbx_is_counted_in_item_queue(unsigned char type, const char *key)
251 {
252 switch (type)
253 {
254 case ITEM_TYPE_ZABBIX_ACTIVE:
255 if (0 == strncmp(key, "log[", 4) ||
256 0 == strncmp(key, "logrt[", 6) ||
257 0 == strncmp(key, "eventlog[", 9))
258 {
259 return FAIL;
260 }
261 break;
262 case ITEM_TYPE_TRAPPER:
263 case ITEM_TYPE_DEPENDENT:
264 case ITEM_TYPE_HTTPTEST:
265 case ITEM_TYPE_SNMPTRAP:
266 return FAIL;
267 }
268
269 return SUCCEED;
270 }
271
272 /******************************************************************************
273 * *
274 * Function: get_item_nextcheck_seed *
275 * *
276 * Purpose: get the seed value to be used for item nextcheck calculations *
277 * *
278 * Return value: the seed for nextcheck calculations *
279 * *
280 * Comments: The seed value is used to spread multiple item nextchecks over *
281 * the item delay period to even the system load. *
282 * Items with the same delay period and seed value will have the *
283 * same nextcheck values. *
284 * *
285 ******************************************************************************/
get_item_nextcheck_seed(zbx_uint64_t itemid,zbx_uint64_t interfaceid,unsigned char type,const char * key)286 static zbx_uint64_t get_item_nextcheck_seed(zbx_uint64_t itemid, zbx_uint64_t interfaceid, unsigned char type,
287 const char *key)
288 {
289 if (ITEM_TYPE_JMX == type)
290 return interfaceid;
291
292 if (ITEM_TYPE_SNMP == type)
293 {
294 ZBX_DC_SNMPINTERFACE *snmp;
295
296 if (NULL == (snmp = (ZBX_DC_SNMPINTERFACE *)zbx_hashset_search(&config->interfaces_snmp, &interfaceid))
297 || SNMP_BULK_ENABLED != snmp->bulk)
298 {
299 return itemid;
300 }
301
302 return interfaceid;
303 }
304
305 if (ITEM_TYPE_SIMPLE == type)
306 {
307 if (SUCCEED == cmp_key_id(key, SERVER_ICMPPING_KEY) ||
308 SUCCEED == cmp_key_id(key, SERVER_ICMPPINGSEC_KEY) ||
309 SUCCEED == cmp_key_id(key, SERVER_ICMPPINGLOSS_KEY))
310 {
311 return interfaceid;
312 }
313 }
314
315 return itemid;
316 }
317
318 static int DCget_disable_until(const ZBX_DC_ITEM *item, const ZBX_DC_HOST *host);
319
320 #define ZBX_ITEM_COLLECTED 0x01 /* force item rescheduling after new value collection */
321 #define ZBX_HOST_UNREACHABLE 0x02
322 #define ZBX_ITEM_KEY_CHANGED 0x04
323 #define ZBX_ITEM_TYPE_CHANGED 0x08
324 #define ZBX_ITEM_DELAY_CHANGED 0x10
325 #define ZBX_REFRESH_UNSUPPORTED_CHANGED 0x20
326
DCitem_nextcheck_update(ZBX_DC_ITEM * item,const ZBX_DC_HOST * host,unsigned char new_state,int flags,int now,char ** error)327 static int DCitem_nextcheck_update(ZBX_DC_ITEM *item, const ZBX_DC_HOST *host, unsigned char new_state,
328 int flags, int now, char **error)
329 {
330 zbx_uint64_t seed;
331
332 if (0 == (flags & ZBX_ITEM_COLLECTED) && 0 != item->nextcheck &&
333 0 == (flags & ZBX_ITEM_KEY_CHANGED) && 0 == (flags & ZBX_ITEM_TYPE_CHANGED) &&
334 ((ITEM_STATE_NORMAL == new_state && 0 == (flags & ZBX_ITEM_DELAY_CHANGED)) ||
335 (ITEM_STATE_NOTSUPPORTED == new_state && 0 == (flags & (0 == item->schedulable ?
336 ZBX_ITEM_DELAY_CHANGED : ZBX_REFRESH_UNSUPPORTED_CHANGED)))))
337 {
338 return SUCCEED; /* avoid unnecessary nextcheck updates when syncing items in cache */
339 }
340
341 seed = get_item_nextcheck_seed(item->itemid, item->interfaceid, item->type, item->key);
342
343 /* for new items, supported items and items that are notsupported due to invalid update interval try to parse */
344 /* interval first and then decide whether it should become/remain supported/notsupported */
345 if (0 == item->nextcheck || ITEM_STATE_NORMAL == new_state || 0 == item->schedulable)
346 {
347 int simple_interval;
348 zbx_custom_interval_t *custom_intervals;
349
350 if (SUCCEED != zbx_interval_preproc(item->delay, &simple_interval, &custom_intervals, error))
351 {
352 /* Polling items with invalid update intervals repeatedly does not make sense because they */
353 /* can only be healed by editing configuration (either update interval or macros involved) */
354 /* and such changes will be detected during configuration synchronization. DCsync_items() */
355 /* detects item configuration changes affecting check scheduling and passes them in flags. */
356
357 item->nextcheck = ZBX_JAN_2038;
358 item->schedulable = 0;
359 return FAIL;
360 }
361
362 if (ITEM_STATE_NORMAL == new_state || 0 == item->schedulable)
363 {
364 int disable_until;
365
366 if (0 != (flags & ZBX_HOST_UNREACHABLE) && 0 != (disable_until =
367 DCget_disable_until(item, host)))
368 {
369 item->nextcheck = calculate_item_nextcheck_unreachable(simple_interval,
370 custom_intervals, disable_until);
371 }
372 else
373 {
374 /* supported items and items that could not have been scheduled previously, but had */
375 /* their update interval fixed, should be scheduled using their update intervals */
376 item->nextcheck = calculate_item_nextcheck(seed, item->type, simple_interval,
377 custom_intervals, now);
378 }
379 }
380 else
381 {
382 /* use refresh_unsupported interval for new items that have a valid update interval of their */
383 /* own, but were synced from the database in ITEM_STATE_NOTSUPPORTED state */
384 item->nextcheck = calculate_item_nextcheck(seed, item->type, config->config->refresh_unsupported,
385 NULL, now);
386 }
387
388 zbx_custom_interval_free(custom_intervals);
389 }
390 else /* for items notsupported for other reasons use refresh_unsupported interval */
391 {
392 item->nextcheck = calculate_item_nextcheck(seed, item->type, config->config->refresh_unsupported, NULL,
393 now);
394 }
395
396 item->schedulable = 1;
397
398 return SUCCEED;
399 }
400
DCitem_poller_type_update(ZBX_DC_ITEM * dc_item,const ZBX_DC_HOST * dc_host,int flags)401 static void DCitem_poller_type_update(ZBX_DC_ITEM *dc_item, const ZBX_DC_HOST *dc_host, int flags)
402 {
403 unsigned char poller_type;
404
405 if (0 != dc_host->proxy_hostid && SUCCEED != is_item_processed_by_server(dc_item->type, dc_item->key))
406 {
407 dc_item->poller_type = ZBX_NO_POLLER;
408 return;
409 }
410
411 poller_type = poller_by_item(dc_item->type, dc_item->key);
412
413 if (0 != (flags & ZBX_HOST_UNREACHABLE))
414 {
415 if (ZBX_POLLER_TYPE_NORMAL == poller_type || ZBX_POLLER_TYPE_JAVA == poller_type)
416 poller_type = ZBX_POLLER_TYPE_UNREACHABLE;
417
418 dc_item->poller_type = poller_type;
419 return;
420 }
421
422 if (0 != (flags & ZBX_ITEM_COLLECTED))
423 {
424 dc_item->poller_type = poller_type;
425 return;
426 }
427
428 if (ZBX_POLLER_TYPE_UNREACHABLE != dc_item->poller_type ||
429 (ZBX_POLLER_TYPE_NORMAL != poller_type && ZBX_POLLER_TYPE_JAVA != poller_type))
430 {
431 dc_item->poller_type = poller_type;
432 }
433 }
434
DCget_disable_until(const ZBX_DC_ITEM * item,const ZBX_DC_HOST * host)435 static int DCget_disable_until(const ZBX_DC_ITEM *item, const ZBX_DC_HOST *host)
436 {
437 switch (item->type)
438 {
439 case ITEM_TYPE_ZABBIX:
440 if (0 != host->errors_from)
441 return host->disable_until;
442 break;
443 case ITEM_TYPE_SNMP:
444 if (0 != host->snmp_errors_from)
445 return host->snmp_disable_until;
446 break;
447 case ITEM_TYPE_IPMI:
448 if (0 != host->ipmi_errors_from)
449 return host->ipmi_disable_until;
450 break;
451 case ITEM_TYPE_JMX:
452 if (0 != host->jmx_errors_from)
453 return host->jmx_disable_until;
454 break;
455 default:
456 /* nothing to do */;
457 }
458
459 return 0;
460 }
461
DCincrease_disable_until(const ZBX_DC_ITEM * item,ZBX_DC_HOST * host,int now)462 static void DCincrease_disable_until(const ZBX_DC_ITEM *item, ZBX_DC_HOST *host, int now)
463 {
464 switch (item->type)
465 {
466 case ITEM_TYPE_ZABBIX:
467 if (0 != host->errors_from)
468 host->disable_until = now + CONFIG_TIMEOUT;
469 break;
470 case ITEM_TYPE_SNMP:
471 if (0 != host->snmp_errors_from)
472 host->snmp_disable_until = now + CONFIG_TIMEOUT;
473 break;
474 case ITEM_TYPE_IPMI:
475 if (0 != host->ipmi_errors_from)
476 host->ipmi_disable_until = now + CONFIG_TIMEOUT;
477 break;
478 case ITEM_TYPE_JMX:
479 if (0 != host->jmx_errors_from)
480 host->jmx_disable_until = now + CONFIG_TIMEOUT;
481 break;
482 default:
483 /* nothing to do */;
484 }
485 }
486
487 /******************************************************************************
488 * *
489 * Function: DCfind_id *
490 * *
491 * Purpose: Find an element in a hashset by its 'id' or create the element if *
492 * it does not exist *
493 * *
494 * Parameters: *
495 * hashset - [IN] hashset to search *
496 * id - [IN] id of element to search for *
497 * size - [IN] size of element to search for *
498 * found - [OUT flag. 0 - element did not exist, it was created. *
499 * 1 - existing element was found. *
500 * *
501 * Return value: pointer to the found or created element *
502 * *
503 ******************************************************************************/
DCfind_id(zbx_hashset_t * hashset,zbx_uint64_t id,size_t size,int * found)504 void *DCfind_id(zbx_hashset_t *hashset, zbx_uint64_t id, size_t size, int *found)
505 {
506 void *ptr;
507 zbx_uint64_t buffer[1024]; /* adjust buffer size to accommodate any type DCfind_id() can be called for */
508
509 if (NULL == (ptr = zbx_hashset_search(hashset, &id)))
510 {
511 *found = 0;
512
513 buffer[0] = id;
514 ptr = zbx_hashset_insert(hashset, &buffer[0], size);
515 }
516 else
517 {
518 *found = 1;
519 }
520
521 return ptr;
522 }
523
DCfind_item(zbx_uint64_t hostid,const char * key)524 static ZBX_DC_ITEM *DCfind_item(zbx_uint64_t hostid, const char *key)
525 {
526 ZBX_DC_ITEM_HK *item_hk, item_hk_local;
527
528 item_hk_local.hostid = hostid;
529 item_hk_local.key = key;
530
531 if (NULL == (item_hk = (ZBX_DC_ITEM_HK *)zbx_hashset_search(&config->items_hk, &item_hk_local)))
532 return NULL;
533 else
534 return item_hk->item_ptr;
535 }
536
DCfind_host(const char * host)537 static ZBX_DC_HOST *DCfind_host(const char *host)
538 {
539 ZBX_DC_HOST_H *host_h, host_h_local;
540
541 host_h_local.host = host;
542
543 if (NULL == (host_h = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_h, &host_h_local)))
544 return NULL;
545 else
546 return host_h->host_ptr;
547 }
548
549 /******************************************************************************
550 * *
551 * Function: DCfind_proxy *
552 * *
553 * Purpose: Find a record with proxy details in configuration cache using the *
554 * proxy name *
555 * *
556 * Parameters: host - [IN] proxy name *
557 * *
558 * Return value: pointer to record if found or NULL otherwise *
559 * *
560 ******************************************************************************/
DCfind_proxy(const char * host)561 static ZBX_DC_HOST *DCfind_proxy(const char *host)
562 {
563 ZBX_DC_HOST_H *host_p, host_p_local;
564
565 host_p_local.host = host;
566
567 if (NULL == (host_p = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_p, &host_p_local)))
568 return NULL;
569 else
570 return host_p->host_ptr;
571 }
572
573 /* private strpool functions */
574
575 #define REFCOUNT_FIELD_SIZE sizeof(zbx_uint32_t)
576
__config_strpool_hash(const void * data)577 static zbx_hash_t __config_strpool_hash(const void *data)
578 {
579 return ZBX_DEFAULT_STRING_HASH_FUNC((char *)data + REFCOUNT_FIELD_SIZE);
580 }
581
__config_strpool_compare(const void * d1,const void * d2)582 static int __config_strpool_compare(const void *d1, const void *d2)
583 {
584 return strcmp((char *)d1 + REFCOUNT_FIELD_SIZE, (char *)d2 + REFCOUNT_FIELD_SIZE);
585 }
586
zbx_strpool_intern(const char * str)587 static const char *zbx_strpool_intern(const char *str)
588 {
589 void *record;
590 zbx_uint32_t *refcount;
591
592 record = zbx_hashset_search(&config->strpool, str - REFCOUNT_FIELD_SIZE);
593
594 if (NULL == record)
595 {
596 record = zbx_hashset_insert_ext(&config->strpool, str - REFCOUNT_FIELD_SIZE,
597 REFCOUNT_FIELD_SIZE + strlen(str) + 1, REFCOUNT_FIELD_SIZE);
598 *(zbx_uint32_t *)record = 0;
599 }
600
601 refcount = (zbx_uint32_t *)record;
602 (*refcount)++;
603
604 return (char *)record + REFCOUNT_FIELD_SIZE;
605 }
606
zbx_strpool_release(const char * str)607 void zbx_strpool_release(const char *str)
608 {
609 zbx_uint32_t *refcount;
610
611 refcount = (zbx_uint32_t *)(str - REFCOUNT_FIELD_SIZE);
612 if (0 == --(*refcount))
613 zbx_hashset_remove(&config->strpool, str - REFCOUNT_FIELD_SIZE);
614 }
615
zbx_strpool_acquire(const char * str)616 static const char *zbx_strpool_acquire(const char *str)
617 {
618 zbx_uint32_t *refcount;
619
620 refcount = (zbx_uint32_t *)(str - REFCOUNT_FIELD_SIZE);
621 (*refcount)++;
622
623 return str;
624 }
625
DCstrpool_replace(int found,const char ** curr,const char * new_str)626 int DCstrpool_replace(int found, const char **curr, const char *new_str)
627 {
628 if (1 == found)
629 {
630 if (0 == strcmp(*curr, new_str))
631 return FAIL;
632
633 zbx_strpool_release(*curr);
634 }
635
636 *curr = zbx_strpool_intern(new_str);
637
638 return SUCCEED; /* indicate that the string has been replaced */
639 }
640
DCupdate_item_queue(ZBX_DC_ITEM * item,unsigned char old_poller_type,int old_nextcheck)641 static void DCupdate_item_queue(ZBX_DC_ITEM *item, unsigned char old_poller_type, int old_nextcheck)
642 {
643 zbx_binary_heap_elem_t elem;
644
645 if (ZBX_LOC_POLLER == item->location)
646 return;
647
648 if (ZBX_LOC_QUEUE == item->location && old_poller_type != item->poller_type)
649 {
650 item->location = ZBX_LOC_NOWHERE;
651 zbx_binary_heap_remove_direct(&config->queues[old_poller_type], item->itemid);
652 }
653
654 if (item->poller_type == ZBX_NO_POLLER)
655 return;
656
657 if (ZBX_LOC_QUEUE == item->location && old_nextcheck == item->nextcheck)
658 return;
659
660 elem.key = item->itemid;
661 elem.data = (const void *)item;
662
663 if (ZBX_LOC_QUEUE != item->location)
664 {
665 item->location = ZBX_LOC_QUEUE;
666 zbx_binary_heap_insert(&config->queues[item->poller_type], &elem);
667 }
668 else
669 zbx_binary_heap_update_direct(&config->queues[item->poller_type], &elem);
670 }
671
DCupdate_proxy_queue(ZBX_DC_PROXY * proxy)672 static void DCupdate_proxy_queue(ZBX_DC_PROXY *proxy)
673 {
674 zbx_binary_heap_elem_t elem;
675
676 if (ZBX_LOC_POLLER == proxy->location)
677 return;
678
679 proxy->nextcheck = proxy->proxy_tasks_nextcheck;
680 if (proxy->proxy_data_nextcheck < proxy->nextcheck)
681 proxy->nextcheck = proxy->proxy_data_nextcheck;
682 if (proxy->proxy_config_nextcheck < proxy->nextcheck)
683 proxy->nextcheck = proxy->proxy_config_nextcheck;
684
685 elem.key = proxy->hostid;
686 elem.data = (const void *)proxy;
687
688 if (ZBX_LOC_QUEUE != proxy->location)
689 {
690 proxy->location = ZBX_LOC_QUEUE;
691 zbx_binary_heap_insert(&config->pqueue, &elem);
692 }
693 else
694 zbx_binary_heap_update_direct(&config->pqueue, &elem);
695 }
696
697 /******************************************************************************
698 * *
699 * Function: config_gmacro_add_index *
700 * *
701 * Purpose: adds global macro index *
702 * *
703 * Parameters: gmacro_index - [IN/OUT] a global macro index hashset *
704 * gmacro - [IN] the macro to index *
705 * *
706 * Return value: The macro index record. *
707 * *
708 ******************************************************************************/
config_gmacro_add_index(zbx_hashset_t * gmacro_index,ZBX_DC_GMACRO * gmacro)709 static ZBX_DC_GMACRO_M *config_gmacro_add_index(zbx_hashset_t *gmacro_index, ZBX_DC_GMACRO *gmacro)
710 {
711 ZBX_DC_GMACRO_M *gmacro_m, gmacro_m_local;
712
713 gmacro_m_local.macro = gmacro->macro;
714
715 if (NULL == (gmacro_m = (ZBX_DC_GMACRO_M *)zbx_hashset_search(gmacro_index, &gmacro_m_local)))
716 {
717 gmacro_m_local.macro = zbx_strpool_acquire(gmacro->macro);
718 zbx_vector_ptr_create_ext(&gmacro_m_local.gmacros, __config_mem_malloc_func, __config_mem_realloc_func,
719 __config_mem_free_func);
720
721 gmacro_m = (ZBX_DC_GMACRO_M *)zbx_hashset_insert(gmacro_index, &gmacro_m_local, sizeof(ZBX_DC_GMACRO_M));
722 }
723
724 zbx_vector_ptr_append(&gmacro_m->gmacros, gmacro);
725 return gmacro_m;
726 }
727
728 /******************************************************************************
729 * *
730 * Function: config_gmacro_remove_index *
731 * *
732 * Purpose: removes global macro index *
733 * *
734 * Parameters: gmacro_index - [IN/OUT] a global macro index hashset *
735 * gmacro - [IN] the macro to remove *
736 * *
737 ******************************************************************************/
config_gmacro_remove_index(zbx_hashset_t * gmacro_index,ZBX_DC_GMACRO * gmacro)738 static ZBX_DC_GMACRO_M *config_gmacro_remove_index(zbx_hashset_t *gmacro_index, ZBX_DC_GMACRO *gmacro)
739 {
740 ZBX_DC_GMACRO_M *gmacro_m, gmacro_m_local;
741 int index;
742
743 gmacro_m_local.macro = gmacro->macro;
744
745 if (NULL != (gmacro_m = (ZBX_DC_GMACRO_M *)zbx_hashset_search(gmacro_index, &gmacro_m_local)))
746 {
747 if (FAIL != (index = zbx_vector_ptr_search(&gmacro_m->gmacros, gmacro, ZBX_DEFAULT_PTR_COMPARE_FUNC)))
748 zbx_vector_ptr_remove(&gmacro_m->gmacros, index);
749 }
750 return gmacro_m;
751 }
752
753 /******************************************************************************
754 * *
755 * Function: config_gmacro_context_compare *
756 * *
757 * Purpose: comparison function to sort global macro vector by context *
758 * operator, value and macro name *
759 * *
760 ******************************************************************************/
config_gmacro_context_compare(const void * d1,const void * d2)761 static int config_gmacro_context_compare(const void *d1, const void *d2)
762 {
763 const ZBX_DC_GMACRO *m1 = *(const ZBX_DC_GMACRO **)d1;
764 const ZBX_DC_GMACRO *m2 = *(const ZBX_DC_GMACRO **)d2;
765
766 /* macros without context have higher priority than macros with */
767 if (NULL == m1->context)
768 return NULL == m2->context ? 0 : -1;
769
770 if (NULL == m2->context)
771 return 1;
772
773 /* CONDITION_OPERATOR_EQUAL (0) has higher priority than CONDITION_OPERATOR_REGEXP (8) */
774 ZBX_RETURN_IF_NOT_EQUAL(m1->context_op, m2->context_op);
775
776 return strcmp(m1->context, m2->context);
777 }
778
779 /******************************************************************************
780 * *
781 * Function: config_hmacro_add_index *
782 * *
783 * Purpose: adds host macro index *
784 * *
785 * Parameters: hmacro_index - [IN/OUT] a host macro index hashset *
786 * hmacro - [IN] the macro to index *
787 * *
788 ******************************************************************************/
config_hmacro_add_index(zbx_hashset_t * hmacro_index,ZBX_DC_HMACRO * hmacro)789 static ZBX_DC_HMACRO_HM *config_hmacro_add_index(zbx_hashset_t *hmacro_index, ZBX_DC_HMACRO *hmacro)
790 {
791 ZBX_DC_HMACRO_HM *hmacro_hm, hmacro_hm_local;
792
793 hmacro_hm_local.hostid = hmacro->hostid;
794 hmacro_hm_local.macro = hmacro->macro;
795
796 if (NULL == (hmacro_hm = (ZBX_DC_HMACRO_HM *)zbx_hashset_search(hmacro_index, &hmacro_hm_local)))
797 {
798 hmacro_hm_local.macro = zbx_strpool_acquire(hmacro->macro);
799 zbx_vector_ptr_create_ext(&hmacro_hm_local.hmacros, __config_mem_malloc_func, __config_mem_realloc_func,
800 __config_mem_free_func);
801
802 hmacro_hm = (ZBX_DC_HMACRO_HM *)zbx_hashset_insert(hmacro_index, &hmacro_hm_local, sizeof(ZBX_DC_HMACRO_HM));
803 }
804
805 zbx_vector_ptr_append(&hmacro_hm->hmacros, hmacro);
806 return hmacro_hm;
807 }
808
809 /******************************************************************************
810 * *
811 * Function: config_hmacro_remove_index *
812 * *
813 * Purpose: removes host macro index *
814 * *
815 * Parameters: hmacro_index - [IN/OUT] a host macro index hashset *
816 * hmacro - [IN] the macro name to remove *
817 * *
818 ******************************************************************************/
config_hmacro_remove_index(zbx_hashset_t * hmacro_index,ZBX_DC_HMACRO * hmacro)819 static ZBX_DC_HMACRO_HM *config_hmacro_remove_index(zbx_hashset_t *hmacro_index, ZBX_DC_HMACRO *hmacro)
820 {
821 ZBX_DC_HMACRO_HM *hmacro_hm, hmacro_hm_local;
822 int index;
823
824 hmacro_hm_local.hostid = hmacro->hostid;
825 hmacro_hm_local.macro = hmacro->macro;
826
827 if (NULL != (hmacro_hm = (ZBX_DC_HMACRO_HM *)zbx_hashset_search(hmacro_index, &hmacro_hm_local)))
828 {
829 if (FAIL != (index = zbx_vector_ptr_search(&hmacro_hm->hmacros, hmacro, ZBX_DEFAULT_PTR_COMPARE_FUNC)))
830 zbx_vector_ptr_remove(&hmacro_hm->hmacros, index);
831 }
832 return hmacro_hm;
833 }
834
835 /******************************************************************************
836 * *
837 * Function: config_hmacro_context_compare *
838 * *
839 * Purpose: comparison function to sort host macro vector by context *
840 * operator, value and macro name *
841 * *
842 ******************************************************************************/
config_hmacro_context_compare(const void * d1,const void * d2)843 static int config_hmacro_context_compare(const void *d1, const void *d2)
844 {
845 const ZBX_DC_HMACRO *m1 = *(const ZBX_DC_HMACRO **)d1;
846 const ZBX_DC_HMACRO *m2 = *(const ZBX_DC_HMACRO **)d2;
847
848 /* macros without context have higher priority than macros with */
849 if (NULL == m1->context)
850 return NULL == m2->context ? 0 : -1;
851
852 if (NULL == m2->context)
853 return 1;
854
855 /* CONDITION_OPERATOR_EQUAL (0) has higher priority than CONDITION_OPERATOR_REGEXP (8) */
856 ZBX_RETURN_IF_NOT_EQUAL(m1->context_op, m2->context_op);
857
858 return strcmp(m1->context, m2->context);
859 }
860
861 /******************************************************************************
862 * *
863 * Function: set_hk_opt *
864 * *
865 * Purpose: sets and validates global housekeeping option *
866 * *
867 * Parameters: value - [OUT] housekeeping setting *
868 * non_zero - [IN] 0 if value is allowed to be zero, 1 otherwise *
869 * value_min - [IN] minimal acceptable setting value *
870 * value_raw - [IN] setting value to validate *
871 * *
872 ******************************************************************************/
set_hk_opt(int * value,int non_zero,int value_min,const char * value_raw)873 static int set_hk_opt(int *value, int non_zero, int value_min, const char *value_raw)
874 {
875 if (SUCCEED != is_time_suffix(value_raw, value, ZBX_LENGTH_UNLIMITED))
876 return FAIL;
877
878 if (0 != non_zero && 0 == *value)
879 return FAIL;
880
881 if (0 != *value && (value_min > *value || ZBX_HK_PERIOD_MAX < *value))
882 return FAIL;
883
884 return SUCCEED;
885 }
886
DCsync_config(zbx_dbsync_t * sync,int * flags)887 static int DCsync_config(zbx_dbsync_t *sync, int *flags)
888 {
889 const ZBX_TABLE *config_table;
890
891 const char *selected_fields[] = {"refresh_unsupported", "discovery_groupid", "snmptrap_logging",
892 "severity_name_0", "severity_name_1", "severity_name_2", "severity_name_3",
893 "severity_name_4", "severity_name_5", "hk_events_mode", "hk_events_trigger",
894 "hk_events_internal", "hk_events_discovery", "hk_events_autoreg",
895 "hk_services_mode", "hk_services", "hk_audit_mode", "hk_audit",
896 "hk_sessions_mode", "hk_sessions", "hk_history_mode", "hk_history_global",
897 "hk_history", "hk_trends_mode", "hk_trends_global", "hk_trends",
898 "default_inventory_mode", "db_extension", "autoreg_tls_accept",
899 "compression_status", "compression_availability", "compress_older",
900 "instanceid"}; /* sync with zbx_dbsync_compare_config() */
901 const char *row[ARRSIZE(selected_fields)];
902 size_t i;
903 int j, found = 1, refresh_unsupported, ret;
904 char **db_row;
905 zbx_uint64_t rowid;
906 unsigned char tag;
907
908 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
909
910 *flags = 0;
911
912 if (NULL == config->config)
913 {
914 found = 0;
915 config->config = (ZBX_DC_CONFIG_TABLE *)__config_mem_malloc_func(NULL, sizeof(ZBX_DC_CONFIG_TABLE));
916 }
917
918 if (SUCCEED != (ret = zbx_dbsync_next(sync, &rowid, &db_row, &tag)))
919 {
920 /* load default config data */
921
922 if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
923 zabbix_log(LOG_LEVEL_ERR, "no records in table 'config'");
924
925 config_table = DBget_table("config");
926
927 for (i = 0; i < ARRSIZE(selected_fields); i++)
928 row[i] = DBget_field(config_table, selected_fields[i])->default_value;
929 }
930 else
931 {
932 for (i = 0; i < ARRSIZE(selected_fields); i++)
933 row[i] = db_row[i];
934 }
935
936 /* store the config data */
937
938 if (SUCCEED != is_time_suffix(row[0], &refresh_unsupported, ZBX_LENGTH_UNLIMITED))
939 {
940 zabbix_log(LOG_LEVEL_WARNING, "invalid unsupported item refresh interval, restoring default");
941
942 config_table = DBget_table("config");
943
944 if (SUCCEED != is_time_suffix(DBget_field(config_table, "refresh_unsupported")->default_value,
945 &refresh_unsupported, ZBX_LENGTH_UNLIMITED))
946 {
947 THIS_SHOULD_NEVER_HAPPEN;
948 refresh_unsupported = 0;
949 }
950 }
951
952 if (0 == found || config->config->refresh_unsupported != refresh_unsupported)
953 *flags |= ZBX_REFRESH_UNSUPPORTED_CHANGED;
954
955 config->config->refresh_unsupported = refresh_unsupported;
956
957 if (NULL != row[1])
958 ZBX_STR2UINT64(config->config->discovery_groupid, row[1]);
959 else
960 config->config->discovery_groupid = ZBX_DISCOVERY_GROUPID_UNDEFINED;
961
962 ZBX_STR2UCHAR(config->config->snmptrap_logging, row[2]);
963 config->config->default_inventory_mode = atoi(row[26]);
964 DCstrpool_replace(found, (const char **)&config->config->db.extension, row[27]);
965 ZBX_STR2UCHAR(config->config->autoreg_tls_accept, row[28]);
966 ZBX_STR2UCHAR(config->config->db.history_compression_status, row[29]);
967 ZBX_STR2UCHAR(config->config->db.history_compression_availability, row[30]);
968
969 if (SUCCEED != is_time_suffix(row[31], &config->config->db.history_compress_older, ZBX_LENGTH_UNLIMITED))
970 {
971 zabbix_log(LOG_LEVEL_WARNING, "invalid history compression age: %s", row[31]);
972 config->config->db.history_compress_older = 0;
973 }
974
975 for (j = 0; TRIGGER_SEVERITY_COUNT > j; j++)
976 DCstrpool_replace(found, &config->config->severity_name[j], row[3 + j]);
977
978 /* instance id cannot be changed - update it only at first sync to avoid read locks later */
979 if (0 == found)
980 DCstrpool_replace(found, &config->config->instanceid, row[32]);
981
982 #if TRIGGER_SEVERITY_COUNT != 6
983 # error "row indexes below are based on assumption of six trigger severity levels"
984 #endif
985
986 /* read housekeeper configuration */
987
988 if (ZBX_HK_OPTION_ENABLED == (config->config->hk.events_mode = atoi(row[9])) &&
989 (SUCCEED != set_hk_opt(&config->config->hk.events_trigger, 1, SEC_PER_DAY, row[10]) ||
990 SUCCEED != set_hk_opt(&config->config->hk.events_internal, 1, SEC_PER_DAY, row[11]) ||
991 SUCCEED != set_hk_opt(&config->config->hk.events_discovery, 1, SEC_PER_DAY, row[12]) ||
992 SUCCEED != set_hk_opt(&config->config->hk.events_autoreg, 1, SEC_PER_DAY, row[13])))
993 {
994 zabbix_log(LOG_LEVEL_WARNING, "trigger, internal, network discovery and auto-registration data"
995 " housekeeping will be disabled due to invalid settings");
996 config->config->hk.events_mode = ZBX_HK_OPTION_DISABLED;
997 }
998
999 if (ZBX_HK_OPTION_ENABLED == (config->config->hk.services_mode = atoi(row[14])) &&
1000 SUCCEED != set_hk_opt(&config->config->hk.services, 1, SEC_PER_DAY, row[15]))
1001 {
1002 zabbix_log(LOG_LEVEL_WARNING, "IT services data housekeeping will be disabled due to invalid"
1003 " settings");
1004 config->config->hk.services_mode = ZBX_HK_OPTION_DISABLED;
1005 }
1006
1007 if (ZBX_HK_OPTION_ENABLED == (config->config->hk.audit_mode = atoi(row[16])) &&
1008 SUCCEED != set_hk_opt(&config->config->hk.audit, 1, SEC_PER_DAY, row[17]))
1009 {
1010 zabbix_log(LOG_LEVEL_WARNING, "audit data housekeeping will be disabled due to invalid"
1011 " settings");
1012 config->config->hk.audit_mode = ZBX_HK_OPTION_DISABLED;
1013 }
1014
1015 if (ZBX_HK_OPTION_ENABLED == (config->config->hk.sessions_mode = atoi(row[18])) &&
1016 SUCCEED != set_hk_opt(&config->config->hk.sessions, 1, SEC_PER_DAY, row[19]))
1017 {
1018 zabbix_log(LOG_LEVEL_WARNING, "user sessions data housekeeping will be disabled due to invalid"
1019 " settings");
1020 config->config->hk.sessions_mode = ZBX_HK_OPTION_DISABLED;
1021 }
1022
1023 config->config->hk.history_mode = atoi(row[20]);
1024 if (ZBX_HK_OPTION_ENABLED == (config->config->hk.history_global = atoi(row[21])) &&
1025 SUCCEED != set_hk_opt(&config->config->hk.history, 0, ZBX_HK_HISTORY_MIN, row[22]))
1026 {
1027 zabbix_log(LOG_LEVEL_WARNING, "history data housekeeping will be disabled and all items will"
1028 " store their history due to invalid global override settings");
1029 config->config->hk.history_mode = ZBX_HK_MODE_DISABLED;
1030 config->config->hk.history = 1; /* just enough to make 0 == items[i].history condition fail */
1031 }
1032
1033 #ifdef HAVE_POSTGRESQL
1034 if (ZBX_HK_MODE_DISABLED != config->config->hk.history_mode &&
1035 ZBX_HK_OPTION_ENABLED == config->config->hk.history_global &&
1036 0 == zbx_strcmp_null(config->config->db.extension, ZBX_CONFIG_DB_EXTENSION_TIMESCALE))
1037 {
1038 config->config->hk.history_mode = ZBX_HK_MODE_PARTITION;
1039 }
1040 #endif
1041
1042 config->config->hk.trends_mode = atoi(row[23]);
1043 if (ZBX_HK_OPTION_ENABLED == (config->config->hk.trends_global = atoi(row[24])) &&
1044 SUCCEED != set_hk_opt(&config->config->hk.trends, 0, ZBX_HK_TRENDS_MIN, row[25]))
1045 {
1046 zabbix_log(LOG_LEVEL_WARNING, "trends data housekeeping will be disabled and all numeric items"
1047 " will store their history due to invalid global override settings");
1048 config->config->hk.trends_mode = ZBX_HK_MODE_DISABLED;
1049 config->config->hk.trends = 1; /* just enough to make 0 == items[i].trends condition fail */
1050 }
1051
1052 #ifdef HAVE_POSTGRESQL
1053 if (ZBX_HK_MODE_DISABLED != config->config->hk.trends_mode &&
1054 ZBX_HK_OPTION_ENABLED == config->config->hk.trends_global &&
1055 0 == zbx_strcmp_null(config->config->db.extension, ZBX_CONFIG_DB_EXTENSION_TIMESCALE))
1056 {
1057 config->config->hk.trends_mode = ZBX_HK_MODE_PARTITION;
1058 }
1059 #endif
1060
1061 if (SUCCEED == ret && SUCCEED == zbx_dbsync_next(sync, &rowid, &db_row, &tag)) /* table must have */
1062 zabbix_log(LOG_LEVEL_ERR, "table 'config' has multiple records"); /* only one record */
1063
1064 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1065
1066 return SUCCEED;
1067 }
1068
DCsync_autoreg_config(zbx_dbsync_t * sync)1069 static void DCsync_autoreg_config(zbx_dbsync_t *sync)
1070 {
1071 /* sync this function with zbx_dbsync_compare_autoreg_psk() */
1072 char **db_row;
1073 zbx_uint64_t rowid;
1074 unsigned char tag;
1075
1076 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1077
1078 if (SUCCEED == zbx_dbsync_next(sync, &rowid, &db_row, &tag))
1079 {
1080 switch (tag)
1081 {
1082 case ZBX_DBSYNC_ROW_ADD:
1083 case ZBX_DBSYNC_ROW_UPDATE:
1084 zbx_strlcpy(config->autoreg_psk_identity, db_row[0],
1085 sizeof(config->autoreg_psk_identity));
1086 zbx_strlcpy(config->autoreg_psk, db_row[1], sizeof(config->autoreg_psk));
1087 break;
1088 case ZBX_DBSYNC_ROW_REMOVE:
1089 config->autoreg_psk_identity[0] = '\0';
1090 zbx_guaranteed_memset(config->autoreg_psk, 0, sizeof(config->autoreg_psk));
1091 break;
1092 default:
1093 THIS_SHOULD_NEVER_HAPPEN;
1094 }
1095 }
1096
1097 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1098 }
1099
DCsync_proxy_remove(ZBX_DC_PROXY * proxy)1100 static void DCsync_proxy_remove(ZBX_DC_PROXY *proxy)
1101 {
1102 if (ZBX_LOC_QUEUE == proxy->location)
1103 {
1104 zbx_binary_heap_remove_direct(&config->pqueue, proxy->hostid);
1105 proxy->location = ZBX_LOC_NOWHERE;
1106 }
1107
1108 zbx_strpool_release(proxy->proxy_address);
1109 zbx_hashset_remove_direct(&config->proxies, proxy);
1110 }
1111
DCsync_hosts(zbx_dbsync_t * sync)1112 static void DCsync_hosts(zbx_dbsync_t *sync)
1113 {
1114 char **row;
1115 zbx_uint64_t rowid;
1116 unsigned char tag;
1117
1118 ZBX_DC_HOST *host;
1119 ZBX_DC_IPMIHOST *ipmihost;
1120 ZBX_DC_PROXY *proxy;
1121 ZBX_DC_HOST_H *host_h, host_h_local, *host_p, host_p_local;
1122
1123 int found;
1124 int update_index_h, update_index_p, ret;
1125 zbx_uint64_t hostid, proxy_hostid;
1126 unsigned char status;
1127 time_t now;
1128 signed char ipmi_authtype;
1129 unsigned char ipmi_privilege;
1130 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1131 ZBX_DC_PSK *psk_i, psk_i_local;
1132 zbx_ptr_pair_t *psk_owner, psk_owner_local;
1133 zbx_hashset_t psk_owners;
1134 #endif
1135 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1136
1137 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1138 zbx_hashset_create(&psk_owners, 0, ZBX_DEFAULT_PTR_HASH_FUNC, ZBX_DEFAULT_PTR_COMPARE_FUNC);
1139 #endif
1140 now = time(NULL);
1141
1142 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
1143 {
1144 /* removed rows will be always added at the end */
1145 if (ZBX_DBSYNC_ROW_REMOVE == tag)
1146 break;
1147
1148 ZBX_STR2UINT64(hostid, row[0]);
1149 ZBX_DBROW2UINT64(proxy_hostid, row[1]);
1150 ZBX_STR2UCHAR(status, row[22]);
1151
1152 host = (ZBX_DC_HOST *)DCfind_id(&config->hosts, hostid, sizeof(ZBX_DC_HOST), &found);
1153
1154 /* see whether we should and can update 'hosts_h' and 'hosts_p' indexes at this point */
1155
1156 update_index_h = 0;
1157 update_index_p = 0;
1158
1159 if ((HOST_STATUS_MONITORED == status || HOST_STATUS_NOT_MONITORED == status) &&
1160 (0 == found || 0 != strcmp(host->host, row[2])))
1161 {
1162 if (1 == found)
1163 {
1164 host_h_local.host = host->host;
1165 host_h = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_h, &host_h_local);
1166
1167 if (NULL != host_h && host == host_h->host_ptr) /* see ZBX-4045 for NULL check */
1168 {
1169 zbx_strpool_release(host_h->host);
1170 zbx_hashset_remove_direct(&config->hosts_h, host_h);
1171 }
1172 }
1173
1174 host_h_local.host = row[2];
1175 host_h = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_h, &host_h_local);
1176
1177 if (NULL != host_h)
1178 host_h->host_ptr = host;
1179 else
1180 update_index_h = 1;
1181 }
1182 else if ((HOST_STATUS_PROXY_ACTIVE == status || HOST_STATUS_PROXY_PASSIVE == status) &&
1183 (0 == found || 0 != strcmp(host->host, row[2])))
1184 {
1185 if (1 == found)
1186 {
1187 host_p_local.host = host->host;
1188 host_p = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_p, &host_p_local);
1189
1190 if (NULL != host_p && host == host_p->host_ptr)
1191 {
1192 zbx_strpool_release(host_p->host);
1193 zbx_hashset_remove_direct(&config->hosts_p, host_p);
1194 }
1195 }
1196
1197 host_p_local.host = row[2];
1198 host_p = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_p, &host_p_local);
1199
1200 if (NULL != host_p)
1201 host_p->host_ptr = host;
1202 else
1203 update_index_p = 1;
1204 }
1205
1206 /* store new information in host structure */
1207
1208 DCstrpool_replace(found, &host->host, row[2]);
1209 DCstrpool_replace(found, &host->name, row[23]);
1210 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1211 DCstrpool_replace(found, &host->tls_issuer, row[31]);
1212 DCstrpool_replace(found, &host->tls_subject, row[32]);
1213
1214 /* maintain 'config->psks' in configuration cache */
1215
1216 /*****************************************************************************/
1217 /* */
1218 /* cases to cover (PSKid means PSK identity): */
1219 /* */
1220 /* Incoming data record */
1221 /* / \ */
1222 /* new new */
1223 /* PSKid PSKid */
1224 /* non-empty empty */
1225 /* / \ / \ */
1226 /* / \ / \ */
1227 /* 'host' 'host' 'host' 'host' */
1228 /* record record record record */
1229 /* has has has has */
1230 /* non-empty empty non-empty empty PSK */
1231 /* PSK PSK PSK | \ */
1232 /* / \ | | | \ */
1233 /* / \ | | | \ */
1234 /* / \ | | | \ */
1235 /* new PSKid new PSKid | | existing new */
1236 /* same as differs | | record record */
1237 /* old PSKid from | | | | */
1238 /* / | old PSKid | | done | */
1239 /* / | | | | | */
1240 /* new PSK new PSK delete | delete | */
1241 /* value value old PSKid | old PSKid | */
1242 /* same as differs and value | and value | */
1243 /* old from from psks | from psks | */
1244 /* | old hashset | hashset | */
1245 /* done / (if ref | (if ref | */
1246 /* / count=0) | count=0) | */
1247 /* / / \ /| \ / */
1248 /* / /--------- | \ / */
1249 /* / / \ | \ / */
1250 /* delete new PSKid new PSKid set pointer in */
1251 /* old PSK already not in 'hosts' record */
1252 /* value in psks psks to NULL PSK */
1253 /* from hashset hashset | */
1254 /* string / \ \ done */
1255 /* pool / \ \ */
1256 /* | / \ \ */
1257 /* change PSK value PSK value insert */
1258 /* PSK value in hashset in hashset new PSKid */
1259 /* for this same as differs and value */
1260 /* PSKid new PSK from new into psks */
1261 /* | value PSK value hashset */
1262 /* done \ | / */
1263 /* \ replace / */
1264 /* \ PSK value / */
1265 /* \ in hashset / */
1266 /* \ with new / */
1267 /* \ PSK value / */
1268 /* \ | / */
1269 /* \ | / */
1270 /* set pointer */
1271 /* in 'host' */
1272 /* record to */
1273 /* new PSKid */
1274 /* | */
1275 /* done */
1276 /* */
1277 /*****************************************************************************/
1278
1279 psk_owner = NULL;
1280
1281 if ('\0' == *row[33] || '\0' == *row[34]) /* new PSKid or value empty */
1282 {
1283 /* In case of "impossible" errors ("PSK value without identity" or "PSK identity without */
1284 /* value") assume empty PSK identity and value. These errors should have been prevented */
1285 /* by validation in frontend/API. Be prepared when making a connection requiring PSK - */
1286 /* the PSK might not be available. */
1287
1288 if (1 == found)
1289 {
1290 if (NULL == host->tls_dc_psk) /* 'host' record has empty PSK */
1291 goto done;
1292
1293 /* 'host' record has non-empty PSK. Unlink and delete PSK. */
1294
1295 psk_i_local.tls_psk_identity = host->tls_dc_psk->tls_psk_identity;
1296
1297 if (NULL != (psk_i = (ZBX_DC_PSK *)zbx_hashset_search(&config->psks, &psk_i_local)) &&
1298 0 == --(psk_i->refcount))
1299 {
1300 zbx_strpool_release(psk_i->tls_psk_identity);
1301 zbx_strpool_release(psk_i->tls_psk);
1302 zbx_hashset_remove_direct(&config->psks, psk_i);
1303 }
1304 }
1305
1306 host->tls_dc_psk = NULL;
1307 goto done;
1308 }
1309
1310 /* new PSKid and value non-empty */
1311
1312 zbx_strlower(row[34]);
1313
1314 if (1 == found && NULL != host->tls_dc_psk) /* 'host' record has non-empty PSK */
1315 {
1316 if (0 == strcmp(host->tls_dc_psk->tls_psk_identity, row[33])) /* new PSKid same as */
1317 /* old PSKid */
1318 {
1319 if (0 != strcmp(host->tls_dc_psk->tls_psk, row[34])) /* new PSK value */
1320 /* differs from old */
1321 {
1322 if (NULL == (psk_owner = (zbx_ptr_pair_t *)zbx_hashset_search(&psk_owners,
1323 &host->tls_dc_psk->tls_psk_identity)))
1324 {
1325 /* change underlying PSK value and 'config->psks' is updated, too */
1326 DCstrpool_replace(1, &host->tls_dc_psk->tls_psk, row[34]);
1327 }
1328 else
1329 {
1330 zabbix_log(LOG_LEVEL_WARNING, "conflicting PSK values for PSK identity"
1331 " \"%s\" on hosts \"%s\" and \"%s\" (and maybe others)",
1332 (char *)psk_owner->first, (char *)psk_owner->second,
1333 host->host);
1334 }
1335 }
1336
1337 goto done;
1338 }
1339
1340 /* New PSKid differs from old PSKid. Unlink and delete old PSK. */
1341
1342 psk_i_local.tls_psk_identity = host->tls_dc_psk->tls_psk_identity;
1343
1344 if (NULL != (psk_i = (ZBX_DC_PSK *)zbx_hashset_search(&config->psks, &psk_i_local)) &&
1345 0 == --(psk_i->refcount))
1346 {
1347 zbx_strpool_release(psk_i->tls_psk_identity);
1348 zbx_strpool_release(psk_i->tls_psk);
1349 zbx_hashset_remove_direct(&config->psks, psk_i);
1350 }
1351
1352 host->tls_dc_psk = NULL;
1353 }
1354
1355 /* new PSK identity already stored? */
1356
1357 psk_i_local.tls_psk_identity = row[33];
1358
1359 if (NULL != (psk_i = (ZBX_DC_PSK *)zbx_hashset_search(&config->psks, &psk_i_local)))
1360 {
1361 /* new PSKid already in psks hashset */
1362
1363 if (0 != strcmp(psk_i->tls_psk, row[34])) /* PSKid stored but PSK value is different */
1364 {
1365 if (NULL == (psk_owner = (zbx_ptr_pair_t *)zbx_hashset_search(&psk_owners, &psk_i->tls_psk_identity)))
1366 {
1367 DCstrpool_replace(1, &psk_i->tls_psk, row[34]);
1368 }
1369 else
1370 {
1371 zabbix_log(LOG_LEVEL_WARNING, "conflicting PSK values for PSK identity"
1372 " \"%s\" on hosts \"%s\" and \"%s\" (and maybe others)",
1373 (char *)psk_owner->first, (char *)psk_owner->second,
1374 host->host);
1375 }
1376 }
1377
1378 host->tls_dc_psk = psk_i;
1379 psk_i->refcount++;
1380 goto done;
1381 }
1382
1383 /* insert new PSKid and value into psks hashset */
1384
1385 DCstrpool_replace(0, &psk_i_local.tls_psk_identity, row[33]);
1386 DCstrpool_replace(0, &psk_i_local.tls_psk, row[34]);
1387 psk_i_local.refcount = 1;
1388 host->tls_dc_psk = zbx_hashset_insert(&config->psks, &psk_i_local, sizeof(ZBX_DC_PSK));
1389 done:
1390 if (NULL != host->tls_dc_psk && NULL == psk_owner)
1391 {
1392 if (NULL == zbx_hashset_search(&psk_owners, &host->tls_dc_psk->tls_psk_identity))
1393 {
1394 /* register this host as the PSK identity owner, against which to report conflicts */
1395
1396 psk_owner_local.first = (char *)host->tls_dc_psk->tls_psk_identity;
1397 psk_owner_local.second = (char *)host->host;
1398
1399 zbx_hashset_insert(&psk_owners, &psk_owner_local, sizeof(psk_owner_local));
1400 }
1401 }
1402 #endif
1403 ZBX_STR2UCHAR(host->tls_connect, row[29]);
1404 ZBX_STR2UCHAR(host->tls_accept, row[30]);
1405
1406 if (0 == found)
1407 {
1408 ZBX_DBROW2UINT64(host->maintenanceid, row[33 + ZBX_HOST_TLS_OFFSET]);
1409 host->maintenance_status = (unsigned char)atoi(row[7]);
1410 host->maintenance_type = (unsigned char)atoi(row[8]);
1411 host->maintenance_from = atoi(row[9]);
1412 host->data_expected_from = now;
1413 host->update_items = 0;
1414
1415 host->errors_from = atoi(row[10]);
1416 host->available = (unsigned char)atoi(row[11]);
1417 host->disable_until = atoi(row[12]);
1418 host->snmp_errors_from = atoi(row[13]);
1419 host->snmp_available = (unsigned char)atoi(row[14]);
1420 host->snmp_disable_until = atoi(row[15]);
1421 host->ipmi_errors_from = atoi(row[16]);
1422 host->ipmi_available = (unsigned char)atoi(row[17]);
1423 host->ipmi_disable_until = atoi(row[18]);
1424 host->jmx_errors_from = atoi(row[19]);
1425 host->jmx_available = (unsigned char)atoi(row[20]);
1426 host->jmx_disable_until = atoi(row[21]);
1427 host->availability_ts = now;
1428
1429 DCstrpool_replace(0, &host->error, row[25]);
1430 DCstrpool_replace(0, &host->snmp_error, row[26]);
1431 DCstrpool_replace(0, &host->ipmi_error, row[27]);
1432 DCstrpool_replace(0, &host->jmx_error, row[28]);
1433
1434 host->items_num = 0;
1435 host->snmp_items_num = 0;
1436 host->ipmi_items_num = 0;
1437 host->jmx_items_num = 0;
1438
1439 host->reset_availability = 0;
1440
1441 zbx_vector_ptr_create_ext(&host->interfaces_v, __config_mem_malloc_func,
1442 __config_mem_realloc_func, __config_mem_free_func);
1443 }
1444 else
1445 {
1446 if (HOST_STATUS_MONITORED == status && HOST_STATUS_MONITORED != host->status)
1447 host->data_expected_from = now;
1448
1449 /* reset host status if host status has been changed (e.g., if host has been disabled) */
1450 if (status != host->status)
1451 host->reset_availability = 1;
1452
1453 /* reset host status if host proxy assignment has been changed */
1454 if (proxy_hostid != host->proxy_hostid)
1455 host->reset_availability = 1;
1456 }
1457
1458 host->proxy_hostid = proxy_hostid;
1459
1460 /* update 'hosts_h' and 'hosts_p' indexes using new data, if not done already */
1461
1462 if (1 == update_index_h)
1463 {
1464 host_h_local.host = zbx_strpool_acquire(host->host);
1465 host_h_local.host_ptr = host;
1466 zbx_hashset_insert(&config->hosts_h, &host_h_local, sizeof(ZBX_DC_HOST_H));
1467 }
1468
1469 if (1 == update_index_p)
1470 {
1471 host_p_local.host = zbx_strpool_acquire(host->host);
1472 host_p_local.host_ptr = host;
1473 zbx_hashset_insert(&config->hosts_p, &host_p_local, sizeof(ZBX_DC_HOST_H));
1474 }
1475
1476 /* IPMI hosts */
1477
1478 ipmi_authtype = (signed char)atoi(row[3]);
1479 ipmi_privilege = (unsigned char)atoi(row[4]);
1480
1481 if (ZBX_IPMI_DEFAULT_AUTHTYPE != ipmi_authtype || ZBX_IPMI_DEFAULT_PRIVILEGE != ipmi_privilege ||
1482 '\0' != *row[5] || '\0' != *row[6]) /* useipmi */
1483 {
1484 ipmihost = (ZBX_DC_IPMIHOST *)DCfind_id(&config->ipmihosts, hostid, sizeof(ZBX_DC_IPMIHOST), &found);
1485
1486 ipmihost->ipmi_authtype = ipmi_authtype;
1487 ipmihost->ipmi_privilege = ipmi_privilege;
1488 DCstrpool_replace(found, &ipmihost->ipmi_username, row[5]);
1489 DCstrpool_replace(found, &ipmihost->ipmi_password, row[6]);
1490 }
1491 else if (NULL != (ipmihost = (ZBX_DC_IPMIHOST *)zbx_hashset_search(&config->ipmihosts, &hostid)))
1492 {
1493 /* remove IPMI connection parameters for hosts without IPMI */
1494
1495 zbx_strpool_release(ipmihost->ipmi_username);
1496 zbx_strpool_release(ipmihost->ipmi_password);
1497
1498 zbx_hashset_remove_direct(&config->ipmihosts, ipmihost);
1499 }
1500
1501 /* proxies */
1502
1503 if (HOST_STATUS_PROXY_ACTIVE == status || HOST_STATUS_PROXY_PASSIVE == status)
1504 {
1505 proxy = (ZBX_DC_PROXY *)DCfind_id(&config->proxies, hostid, sizeof(ZBX_DC_PROXY), &found);
1506
1507 if (0 == found)
1508 {
1509 proxy->location = ZBX_LOC_NOWHERE;
1510 proxy->version = 0;
1511 proxy->lastaccess = atoi(row[24]);
1512 proxy->last_cfg_error_time = 0;
1513 proxy->proxy_delay = 0;
1514 proxy->nodata_win.flags = ZBX_PROXY_SUPPRESS_DISABLE;
1515 proxy->nodata_win.values_num = 0;
1516 proxy->nodata_win.period_end = 0;
1517 }
1518
1519 proxy->auto_compress = atoi(row[32 + ZBX_HOST_TLS_OFFSET]);
1520 DCstrpool_replace(found, &proxy->proxy_address, row[31 + ZBX_HOST_TLS_OFFSET]);
1521
1522 if (HOST_STATUS_PROXY_PASSIVE == status && (0 == found || status != host->status))
1523 {
1524 proxy->proxy_config_nextcheck = (int)calculate_proxy_nextcheck(
1525 hostid, CONFIG_PROXYCONFIG_FREQUENCY, now);
1526 proxy->proxy_data_nextcheck = (int)calculate_proxy_nextcheck(
1527 hostid, CONFIG_PROXYDATA_FREQUENCY, now);
1528 proxy->proxy_tasks_nextcheck = (int)calculate_proxy_nextcheck(
1529 hostid, ZBX_TASK_UPDATE_FREQUENCY, now);
1530
1531 DCupdate_proxy_queue(proxy);
1532 }
1533 else if (HOST_STATUS_PROXY_ACTIVE == status && ZBX_LOC_QUEUE == proxy->location)
1534 {
1535 zbx_binary_heap_remove_direct(&config->pqueue, proxy->hostid);
1536 proxy->location = ZBX_LOC_NOWHERE;
1537 }
1538 proxy->last_version_error_time = time(NULL);
1539 }
1540 else if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &hostid)))
1541 DCsync_proxy_remove(proxy);
1542
1543 host->status = status;
1544 }
1545
1546 /* remove deleted hosts from buffer */
1547 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
1548 {
1549 if (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &rowid)))
1550 continue;
1551
1552 hostid = host->hostid;
1553
1554 /* IPMI hosts */
1555
1556 if (NULL != (ipmihost = (ZBX_DC_IPMIHOST *)zbx_hashset_search(&config->ipmihosts, &hostid)))
1557 {
1558 zbx_strpool_release(ipmihost->ipmi_username);
1559 zbx_strpool_release(ipmihost->ipmi_password);
1560
1561 zbx_hashset_remove_direct(&config->ipmihosts, ipmihost);
1562 }
1563
1564 /* proxies */
1565
1566 if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &hostid)))
1567 DCsync_proxy_remove(proxy);
1568
1569 /* hosts */
1570
1571 if (HOST_STATUS_MONITORED == host->status || HOST_STATUS_NOT_MONITORED == host->status)
1572 {
1573 host_h_local.host = host->host;
1574 host_h = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_h, &host_h_local);
1575
1576 if (NULL != host_h && host == host_h->host_ptr) /* see ZBX-4045 for NULL check */
1577 {
1578 zbx_strpool_release(host_h->host);
1579 zbx_hashset_remove_direct(&config->hosts_h, host_h);
1580 }
1581 }
1582 else if (HOST_STATUS_PROXY_ACTIVE == host->status || HOST_STATUS_PROXY_PASSIVE == host->status)
1583 {
1584 host_p_local.host = host->host;
1585 host_p = (ZBX_DC_HOST_H *)zbx_hashset_search(&config->hosts_p, &host_p_local);
1586
1587 if (NULL != host_p && host == host_p->host_ptr)
1588 {
1589 zbx_strpool_release(host_p->host);
1590 zbx_hashset_remove_direct(&config->hosts_p, host_p);
1591 }
1592 }
1593
1594 zbx_strpool_release(host->host);
1595 zbx_strpool_release(host->name);
1596
1597 zbx_strpool_release(host->error);
1598 zbx_strpool_release(host->snmp_error);
1599 zbx_strpool_release(host->ipmi_error);
1600 zbx_strpool_release(host->jmx_error);
1601 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1602 zbx_strpool_release(host->tls_issuer);
1603 zbx_strpool_release(host->tls_subject);
1604
1605 /* Maintain 'psks' index. Unlink and delete the PSK identity. */
1606 if (NULL != host->tls_dc_psk)
1607 {
1608 psk_i_local.tls_psk_identity = host->tls_dc_psk->tls_psk_identity;
1609
1610 if (NULL != (psk_i = (ZBX_DC_PSK *)zbx_hashset_search(&config->psks, &psk_i_local)) &&
1611 0 == --(psk_i->refcount))
1612 {
1613 zbx_strpool_release(psk_i->tls_psk_identity);
1614 zbx_strpool_release(psk_i->tls_psk);
1615 zbx_hashset_remove_direct(&config->psks, psk_i);
1616 }
1617 }
1618 #endif
1619 zbx_vector_ptr_destroy(&host->interfaces_v);
1620 zbx_hashset_remove_direct(&config->hosts, host);
1621 }
1622
1623 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1624 zbx_hashset_destroy(&psk_owners);
1625 #endif
1626
1627 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1628 }
1629
DCsync_host_inventory(zbx_dbsync_t * sync)1630 static void DCsync_host_inventory(zbx_dbsync_t *sync)
1631 {
1632 ZBX_DC_HOST_INVENTORY *host_inventory, *host_inventory_auto;
1633 zbx_uint64_t rowid, hostid;
1634 int found, ret, i;
1635 char **row;
1636 unsigned char tag;
1637
1638 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1639
1640 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
1641 {
1642 /* removed rows will be always added at the end */
1643 if (ZBX_DBSYNC_ROW_REMOVE == tag)
1644 break;
1645
1646 ZBX_STR2UINT64(hostid, row[0]);
1647
1648 host_inventory = (ZBX_DC_HOST_INVENTORY *)DCfind_id(&config->host_inventories, hostid, sizeof(ZBX_DC_HOST_INVENTORY), &found);
1649
1650 ZBX_STR2UCHAR(host_inventory->inventory_mode, row[1]);
1651
1652 /* store new information in host_inventory structure */
1653 for (i = 0; i < HOST_INVENTORY_FIELD_COUNT; i++)
1654 DCstrpool_replace(found, &(host_inventory->values[i]), row[i + 2]);
1655
1656 host_inventory_auto = (ZBX_DC_HOST_INVENTORY *)DCfind_id(&config->host_inventories_auto, hostid, sizeof(ZBX_DC_HOST_INVENTORY),
1657 &found);
1658
1659 host_inventory_auto->inventory_mode = host_inventory->inventory_mode;
1660
1661 if (1 == found)
1662 {
1663 for (i = 0; i < HOST_INVENTORY_FIELD_COUNT; i++)
1664 {
1665 if (NULL == host_inventory_auto->values[i])
1666 continue;
1667
1668 zbx_strpool_release(host_inventory_auto->values[i]);
1669 host_inventory_auto->values[i] = NULL;
1670 }
1671 }
1672 else
1673 {
1674 for (i = 0; i < HOST_INVENTORY_FIELD_COUNT; i++)
1675 host_inventory_auto->values[i] = NULL;
1676 }
1677 }
1678
1679 /* remove deleted host inventory from cache */
1680 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
1681 {
1682 if (NULL == (host_inventory = (ZBX_DC_HOST_INVENTORY *)zbx_hashset_search(&config->host_inventories, &rowid)))
1683 continue;
1684
1685 for (i = 0; i < HOST_INVENTORY_FIELD_COUNT; i++)
1686 zbx_strpool_release(host_inventory->values[i]);
1687
1688 zbx_hashset_remove_direct(&config->host_inventories, host_inventory);
1689
1690 if (NULL == (host_inventory_auto = (ZBX_DC_HOST_INVENTORY *)zbx_hashset_search(&config->host_inventories_auto, &rowid)))
1691 {
1692 THIS_SHOULD_NEVER_HAPPEN;
1693 continue;
1694 }
1695
1696 for (i = 0; i < HOST_INVENTORY_FIELD_COUNT; i++)
1697 {
1698 if (NULL != host_inventory_auto->values[i])
1699 zbx_strpool_release(host_inventory_auto->values[i]);
1700 }
1701
1702 zbx_hashset_remove_direct(&config->host_inventories_auto, host_inventory_auto);
1703 }
1704
1705 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1706 }
1707
DCsync_htmpls(zbx_dbsync_t * sync)1708 static void DCsync_htmpls(zbx_dbsync_t *sync)
1709 {
1710 char **row;
1711 zbx_uint64_t rowid;
1712 unsigned char tag;
1713
1714 ZBX_DC_HTMPL *htmpl = NULL;
1715
1716 int found, i, index, ret;
1717 zbx_uint64_t _hostid = 0, hostid, templateid;
1718 zbx_vector_ptr_t sort;
1719
1720 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1721
1722 zbx_vector_ptr_create(&sort);
1723
1724 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
1725 {
1726 /* removed rows will be always added at the end */
1727 if (ZBX_DBSYNC_ROW_REMOVE == tag)
1728 break;
1729
1730 ZBX_STR2UINT64(hostid, row[0]);
1731 ZBX_STR2UINT64(templateid, row[1]);
1732
1733 if (_hostid != hostid || 0 == _hostid)
1734 {
1735 _hostid = hostid;
1736
1737 htmpl = (ZBX_DC_HTMPL *)DCfind_id(&config->htmpls, hostid, sizeof(ZBX_DC_HTMPL), &found);
1738
1739 if (0 == found)
1740 {
1741 zbx_vector_uint64_create_ext(&htmpl->templateids,
1742 __config_mem_malloc_func,
1743 __config_mem_realloc_func,
1744 __config_mem_free_func);
1745 zbx_vector_uint64_reserve(&htmpl->templateids, 1);
1746 }
1747
1748 zbx_vector_ptr_append(&sort, htmpl);
1749 }
1750
1751 zbx_vector_uint64_append(&htmpl->templateids, templateid);
1752 }
1753
1754 /* remove deleted host templates from cache */
1755 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
1756 {
1757 ZBX_STR2UINT64(hostid, row[0]);
1758
1759 if (NULL == (htmpl = (ZBX_DC_HTMPL *)zbx_hashset_search(&config->htmpls, &hostid)))
1760 continue;
1761
1762 ZBX_STR2UINT64(templateid, row[1]);
1763
1764 if (-1 == (index = zbx_vector_uint64_search(&htmpl->templateids, templateid,
1765 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
1766 {
1767 continue;
1768 }
1769
1770 if (1 == htmpl->templateids.values_num)
1771 {
1772 zbx_vector_uint64_destroy(&htmpl->templateids);
1773 zbx_hashset_remove_direct(&config->htmpls, htmpl);
1774 }
1775 else
1776 {
1777 zbx_vector_uint64_remove_noorder(&htmpl->templateids, index);
1778 zbx_vector_ptr_append(&sort, htmpl);
1779 }
1780 }
1781
1782 /* sort the changed template lists */
1783
1784 zbx_vector_ptr_sort(&sort, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
1785 zbx_vector_ptr_uniq(&sort, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
1786
1787 for (i = 0; i < sort.values_num; i++)
1788 {
1789 htmpl = (ZBX_DC_HTMPL *)sort.values[i];
1790 zbx_vector_uint64_sort(&htmpl->templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1791 }
1792
1793 zbx_vector_ptr_destroy(&sort);
1794
1795 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1796 }
1797
DCsync_gmacros(zbx_dbsync_t * sync)1798 static void DCsync_gmacros(zbx_dbsync_t *sync)
1799 {
1800 char **row;
1801 zbx_uint64_t rowid;
1802 unsigned char tag, context_op;
1803 ZBX_DC_GMACRO *gmacro;
1804 int found, context_existed, update_index, ret, i;
1805 zbx_uint64_t globalmacroid;
1806 char *macro = NULL, *context = NULL;
1807 zbx_vector_ptr_t indexes;
1808 ZBX_DC_GMACRO_M *gmacro_m;
1809
1810 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1811
1812 zbx_vector_ptr_create(&indexes);
1813
1814 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
1815 {
1816 /* removed rows will be always added at the end */
1817 if (ZBX_DBSYNC_ROW_REMOVE == tag)
1818 break;
1819
1820 ZBX_STR2UINT64(globalmacroid, row[0]);
1821
1822 if (SUCCEED != zbx_user_macro_parse_dyn(row[1], ¯o, &context, NULL, &context_op))
1823 {
1824 zabbix_log(LOG_LEVEL_WARNING, "cannot parse user macro \"%s\"", row[1]);
1825 continue;
1826 }
1827
1828 gmacro = (ZBX_DC_GMACRO *)DCfind_id(&config->gmacros, globalmacroid, sizeof(ZBX_DC_GMACRO), &found);
1829
1830 /* see whether we should and can update gmacros_m index at this point */
1831 update_index = 0;
1832
1833 if (0 == found || 0 != strcmp(gmacro->macro, macro) || 0 != zbx_strcmp_null(gmacro->context, context) ||
1834 gmacro->context_op != context_op)
1835 {
1836 if (1 == found)
1837 {
1838 gmacro_m = config_gmacro_remove_index(&config->gmacros_m, gmacro);
1839 zbx_vector_ptr_append(&indexes, gmacro_m);
1840 }
1841
1842 update_index = 1;
1843 }
1844
1845 /* store new information in macro structure */
1846 ZBX_STR2UCHAR(gmacro->type, row[3]);
1847 gmacro->context_op = context_op;
1848 DCstrpool_replace(found, &gmacro->macro, macro);
1849 DCstrpool_replace(found, &gmacro->value, row[2]);
1850
1851 context_existed = (1 == found && NULL != gmacro->context);
1852
1853 if (NULL == context)
1854 {
1855 /* release the context if it was removed from the macro */
1856 if (1 == context_existed)
1857 zbx_strpool_release(gmacro->context);
1858
1859 gmacro->context = NULL;
1860 }
1861 else
1862 {
1863 /* replace the existing context (1) or add context to macro (0) */
1864 DCstrpool_replace(context_existed, &gmacro->context, context);
1865 }
1866
1867 /* update gmacros_m index using new data */
1868 if (1 == update_index)
1869 {
1870 gmacro_m = config_gmacro_add_index(&config->gmacros_m, gmacro);
1871 zbx_vector_ptr_append(&indexes, gmacro_m);
1872 }
1873 }
1874
1875 /* remove deleted global macros from cache */
1876 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
1877 {
1878 if (NULL == (gmacro = (ZBX_DC_GMACRO *)zbx_hashset_search(&config->gmacros, &rowid)))
1879 continue;
1880
1881 gmacro_m = config_gmacro_remove_index(&config->gmacros_m, gmacro);
1882 zbx_vector_ptr_append(&indexes, gmacro_m);
1883
1884 zbx_strpool_release(gmacro->macro);
1885 zbx_strpool_release(gmacro->value);
1886
1887 if (NULL != gmacro->context)
1888 zbx_strpool_release(gmacro->context);
1889
1890 zbx_hashset_remove_direct(&config->gmacros, gmacro);
1891 }
1892
1893 zbx_vector_ptr_sort(&indexes, ZBX_DEFAULT_PTR_COMPARE_FUNC);
1894 zbx_vector_ptr_uniq(&indexes, ZBX_DEFAULT_PTR_COMPARE_FUNC);
1895
1896 for (i = 0; i < indexes.values_num; i++)
1897 {
1898 gmacro_m = (ZBX_DC_GMACRO_M *)indexes.values[i];
1899 if (0 == gmacro_m->gmacros.values_num)
1900 {
1901 zbx_strpool_release(gmacro_m->macro);
1902 zbx_vector_ptr_destroy(&gmacro_m->gmacros);
1903 zbx_hashset_remove_direct(&config->gmacros_m, gmacro_m);
1904 }
1905 else
1906 zbx_vector_ptr_sort(&gmacro_m->gmacros, config_gmacro_context_compare);
1907 }
1908
1909 zbx_free(context);
1910 zbx_free(macro);
1911 zbx_vector_ptr_destroy(&indexes);
1912
1913 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1914 }
1915
DCsync_hmacros(zbx_dbsync_t * sync)1916 static void DCsync_hmacros(zbx_dbsync_t *sync)
1917 {
1918 char **row;
1919 zbx_uint64_t rowid;
1920 unsigned char tag, context_op;
1921 ZBX_DC_HMACRO *hmacro;
1922 int found, context_existed, update_index, ret, i;
1923 zbx_uint64_t hostmacroid, hostid;
1924 char *macro = NULL, *context = NULL;
1925 zbx_vector_ptr_t indexes;
1926 ZBX_DC_HMACRO_HM *hmacro_hm;
1927
1928 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1929
1930 zbx_vector_ptr_create(&indexes);
1931
1932 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
1933 {
1934 /* removed rows will be always added at the end */
1935 if (ZBX_DBSYNC_ROW_REMOVE == tag)
1936 break;
1937
1938 ZBX_STR2UINT64(hostmacroid, row[0]);
1939 ZBX_STR2UINT64(hostid, row[1]);
1940
1941 if (SUCCEED != zbx_user_macro_parse_dyn(row[2], ¯o, &context, NULL, &context_op))
1942 {
1943 zabbix_log(LOG_LEVEL_WARNING, "cannot parse host \"%s\" macro \"%s\"", row[1], row[2]);
1944 continue;
1945 }
1946
1947 hmacro = (ZBX_DC_HMACRO *)DCfind_id(&config->hmacros, hostmacroid, sizeof(ZBX_DC_HMACRO), &found);
1948
1949 /* see whether we should and can update hmacros_hm index at this point */
1950 update_index = 0;
1951
1952 if (0 == found || hmacro->hostid != hostid || 0 != strcmp(hmacro->macro, macro) ||
1953 0 != zbx_strcmp_null(hmacro->context, context) || hmacro->context_op != context_op)
1954 {
1955 if (1 == found)
1956 {
1957 hmacro_hm = config_hmacro_remove_index(&config->hmacros_hm, hmacro);
1958 zbx_vector_ptr_append(&indexes, hmacro_hm);
1959 }
1960
1961 update_index = 1;
1962 }
1963
1964 /* store new information in macro structure */
1965 hmacro->hostid = hostid;
1966 ZBX_STR2UCHAR(hmacro->type, row[4]);
1967 hmacro->context_op = context_op;
1968 DCstrpool_replace(found, &hmacro->macro, macro);
1969 DCstrpool_replace(found, &hmacro->value, row[3]);
1970
1971 context_existed = (1 == found && NULL != hmacro->context);
1972
1973 if (NULL == context)
1974 {
1975 /* release the context if it was removed from the macro */
1976 if (1 == context_existed)
1977 zbx_strpool_release(hmacro->context);
1978
1979 hmacro->context = NULL;
1980 }
1981 else
1982 {
1983 /* replace the existing context (1) or add context to macro (0) */
1984 DCstrpool_replace(context_existed, &hmacro->context, context);
1985 }
1986
1987 /* update hmacros_hm index using new data */
1988 if (1 == update_index)
1989 {
1990 hmacro_hm = config_hmacro_add_index(&config->hmacros_hm, hmacro);
1991 zbx_vector_ptr_append(&indexes, hmacro_hm);
1992 }
1993 }
1994
1995 /* remove deleted host macros from buffer */
1996 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
1997 {
1998 if (NULL == (hmacro = (ZBX_DC_HMACRO *)zbx_hashset_search(&config->hmacros, &rowid)))
1999 continue;
2000
2001 hmacro_hm = config_hmacro_remove_index(&config->hmacros_hm, hmacro);
2002 zbx_vector_ptr_append(&indexes, hmacro_hm);
2003
2004 zbx_strpool_release(hmacro->macro);
2005 zbx_strpool_release(hmacro->value);
2006
2007 if (NULL != hmacro->context)
2008 zbx_strpool_release(hmacro->context);
2009
2010 zbx_hashset_remove_direct(&config->hmacros, hmacro);
2011 }
2012
2013 zbx_vector_ptr_sort(&indexes, ZBX_DEFAULT_PTR_COMPARE_FUNC);
2014 zbx_vector_ptr_uniq(&indexes, ZBX_DEFAULT_PTR_COMPARE_FUNC);
2015
2016 for (i = 0; i < indexes.values_num; i++)
2017 {
2018 hmacro_hm = (ZBX_DC_HMACRO_HM *)indexes.values[i];
2019 if (0 == hmacro_hm->hmacros.values_num)
2020 {
2021 zbx_strpool_release(hmacro_hm->macro);
2022 zbx_vector_ptr_destroy(&hmacro_hm->hmacros);
2023 zbx_hashset_remove_direct(&config->hmacros_hm, hmacro_hm);
2024 }
2025 else
2026 zbx_vector_ptr_sort(&hmacro_hm->hmacros, config_hmacro_context_compare);
2027 }
2028
2029 zbx_free(context);
2030 zbx_free(macro);
2031 zbx_vector_ptr_destroy(&indexes);
2032
2033 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
2034 }
2035
2036 /******************************************************************************
2037 * *
2038 * Function: substitute_host_interface_macros *
2039 * *
2040 * Purpose: trying to resolve the macros in host interface *
2041 * *
2042 ******************************************************************************/
substitute_host_interface_macros(ZBX_DC_INTERFACE * interface)2043 static void substitute_host_interface_macros(ZBX_DC_INTERFACE *interface)
2044 {
2045 int macros;
2046 char *addr;
2047 DC_HOST host;
2048
2049 macros = STR_CONTAINS_MACROS(interface->ip) ? 0x01 : 0;
2050 macros |= STR_CONTAINS_MACROS(interface->dns) ? 0x02 : 0;
2051
2052 if (0 != macros)
2053 {
2054 DCget_host_by_hostid(&host, interface->hostid);
2055
2056 if (0 != (macros & 0x01))
2057 {
2058 addr = zbx_strdup(NULL, interface->ip);
2059 substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, &host, NULL, NULL, NULL,
2060 &addr, MACRO_TYPE_INTERFACE_ADDR, NULL, 0);
2061 if (SUCCEED == is_ip(addr) || SUCCEED == zbx_validate_hostname(addr))
2062 DCstrpool_replace(1, &interface->ip, addr);
2063 zbx_free(addr);
2064 }
2065
2066 if (0 != (macros & 0x02))
2067 {
2068 addr = zbx_strdup(NULL, interface->dns);
2069 substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, &host, NULL, NULL, NULL,
2070 &addr, MACRO_TYPE_INTERFACE_ADDR, NULL, 0);
2071 if (SUCCEED == is_ip(addr) || SUCCEED == zbx_validate_hostname(addr))
2072 DCstrpool_replace(1, &interface->dns, addr);
2073 zbx_free(addr);
2074 }
2075 }
2076 }
2077
2078 /******************************************************************************
2079 * *
2080 * Function: dc_interface_snmpaddrs_remove *
2081 * *
2082 * Purpose: remove interface from SNMP address -> interfaceid index *
2083 * *
2084 * Parameters: interface - [IN] the interface *
2085 * *
2086 ******************************************************************************/
dc_interface_snmpaddrs_remove(ZBX_DC_INTERFACE * interface)2087 static void dc_interface_snmpaddrs_remove(ZBX_DC_INTERFACE *interface)
2088 {
2089 ZBX_DC_INTERFACE_ADDR *ifaddr, ifaddr_local;
2090 int index;
2091
2092 ifaddr_local.addr = (0 != interface->useip ? interface->ip : interface->dns);
2093
2094 if ('\0' == *ifaddr_local.addr)
2095 return;
2096
2097 if (NULL == (ifaddr = (ZBX_DC_INTERFACE_ADDR *)zbx_hashset_search(&config->interface_snmpaddrs, &ifaddr_local)))
2098 return;
2099
2100 if (FAIL == (index = zbx_vector_uint64_search(&ifaddr->interfaceids, interface->interfaceid,
2101 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2102 {
2103 return;
2104 }
2105
2106 zbx_vector_uint64_remove_noorder(&ifaddr->interfaceids, index);
2107
2108 if (0 == ifaddr->interfaceids.values_num)
2109 {
2110 zbx_strpool_release(ifaddr->addr);
2111 zbx_vector_uint64_destroy(&ifaddr->interfaceids);
2112 zbx_hashset_remove_direct(&config->interface_snmpaddrs, ifaddr);
2113 }
2114 }
2115
2116 /******************************************************************************
2117 * *
2118 * Function: dc_interface_snmp_set *
2119 * *
2120 * Purpose: setup SNMP attributes for interface with interfaceid index *
2121 * *
2122 * Parameters: interface - [IN] the interface *
2123 * row - [IN] the row data from DB *
2124 *
2125 * *
2126 ******************************************************************************/
dc_interface_snmp_set(zbx_uint64_t interfaceid,const char ** row,unsigned char * bulk_changed)2127 static ZBX_DC_SNMPINTERFACE *dc_interface_snmp_set(zbx_uint64_t interfaceid, const char **row,
2128 unsigned char *bulk_changed)
2129 {
2130 int found;
2131 ZBX_DC_SNMPINTERFACE *snmp;
2132 unsigned char bulk;
2133
2134 snmp = (ZBX_DC_SNMPINTERFACE *)DCfind_id(&config->interfaces_snmp, interfaceid, sizeof(ZBX_DC_SNMPINTERFACE),
2135 &found);
2136
2137 ZBX_STR2UCHAR(bulk, row[9]);
2138
2139 if (0 == found)
2140 *bulk_changed = 1;
2141 else if (snmp->bulk != bulk)
2142 *bulk_changed = 1;
2143 else
2144 *bulk_changed = 0;
2145
2146 if (0 != *bulk_changed)
2147 snmp->bulk = bulk;
2148
2149 ZBX_STR2UCHAR(snmp->version, row[8]);
2150 DCstrpool_replace(found, &snmp->community, row[10]);
2151 DCstrpool_replace(found, &snmp->securityname, row[11]);
2152 ZBX_STR2UCHAR(snmp->securitylevel, row[12]);
2153 DCstrpool_replace(found, &snmp->authpassphrase, row[13]);
2154 DCstrpool_replace(found, &snmp->privpassphrase, row[14]);
2155 ZBX_STR2UCHAR(snmp->authprotocol, row[15]);
2156 ZBX_STR2UCHAR(snmp->privprotocol, row[16]);
2157 DCstrpool_replace(found, &snmp->contextname, row[17]);
2158
2159 return snmp;
2160 }
2161
2162 /******************************************************************************
2163 * *
2164 * Function: dc_interface_snmp_remove *
2165 * *
2166 * Purpose: remove interface from SNMP address -> interfaceid index *
2167 * *
2168 * Parameters: interface - [IN] the interface *
2169 * *
2170 ******************************************************************************/
dc_interface_snmp_remove(zbx_uint64_t interfaceid)2171 static void dc_interface_snmp_remove(zbx_uint64_t interfaceid)
2172 {
2173 ZBX_DC_SNMPINTERFACE *snmp;
2174
2175 if (NULL == (snmp = (ZBX_DC_SNMPINTERFACE *)zbx_hashset_search(&config->interfaces_snmp, &interfaceid)))
2176 return;
2177
2178 zbx_strpool_release(snmp->community);
2179 zbx_strpool_release(snmp->securityname);
2180 zbx_strpool_release(snmp->authpassphrase);
2181 zbx_strpool_release(snmp->privpassphrase);
2182 zbx_strpool_release(snmp->contextname);
2183
2184 zbx_hashset_remove_direct(&config->interfaces_snmp, snmp);
2185
2186 return;
2187 }
2188
DCsync_interfaces(zbx_dbsync_t * sync)2189 static void DCsync_interfaces(zbx_dbsync_t *sync)
2190 {
2191 char **row;
2192 zbx_uint64_t rowid;
2193 unsigned char tag;
2194
2195 ZBX_DC_INTERFACE *interface;
2196 ZBX_DC_INTERFACE_HT *interface_ht, interface_ht_local;
2197 ZBX_DC_INTERFACE_ADDR *interface_snmpaddr, interface_snmpaddr_local;
2198 ZBX_DC_HOST *host;
2199
2200 int found, update_index, ret, i;
2201 zbx_uint64_t interfaceid, hostid;
2202 unsigned char type, main_, useip;
2203 unsigned char reset_snmp_stats;
2204 zbx_vector_ptr_t interfaces;
2205
2206 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
2207
2208 zbx_vector_ptr_create(&interfaces);
2209
2210 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
2211 {
2212 /* removed rows will be always added at the end */
2213 if (ZBX_DBSYNC_ROW_REMOVE == tag)
2214 break;
2215
2216 ZBX_STR2UINT64(interfaceid, row[0]);
2217 ZBX_STR2UINT64(hostid, row[1]);
2218 ZBX_STR2UCHAR(type, row[2]);
2219 ZBX_STR2UCHAR(main_, row[3]);
2220 ZBX_STR2UCHAR(useip, row[4]);
2221
2222 /* If there is no host for this interface, skip it. */
2223 /* This may be possible if the host was added after we synced config for hosts. */
2224 if (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)))
2225 continue;
2226
2227 interface = (ZBX_DC_INTERFACE *)DCfind_id(&config->interfaces, interfaceid, sizeof(ZBX_DC_INTERFACE), &found);
2228 zbx_vector_ptr_append(&interfaces, interface);
2229
2230 /* remove old address->interfaceid index */
2231 if (0 != found && INTERFACE_TYPE_SNMP == interface->type)
2232 dc_interface_snmpaddrs_remove(interface);
2233
2234 /* see whether we should and can update interfaces_ht index at this point */
2235
2236 update_index = 0;
2237
2238 if (0 == found || interface->hostid != hostid || interface->type != type || interface->main != main_)
2239 {
2240 if (1 == found && 1 == interface->main)
2241 {
2242 interface_ht_local.hostid = interface->hostid;
2243 interface_ht_local.type = interface->type;
2244 interface_ht = (ZBX_DC_INTERFACE_HT *)zbx_hashset_search(&config->interfaces_ht, &interface_ht_local);
2245
2246 if (NULL != interface_ht && interface == interface_ht->interface_ptr)
2247 {
2248 /* see ZBX-4045 for NULL check in the conditional */
2249 zbx_hashset_remove(&config->interfaces_ht, &interface_ht_local);
2250 }
2251 }
2252
2253 if (1 == main_)
2254 {
2255 interface_ht_local.hostid = hostid;
2256 interface_ht_local.type = type;
2257 interface_ht = (ZBX_DC_INTERFACE_HT *)zbx_hashset_search(&config->interfaces_ht, &interface_ht_local);
2258
2259 if (NULL != interface_ht)
2260 interface_ht->interface_ptr = interface;
2261 else
2262 update_index = 1;
2263 }
2264 }
2265
2266 /* store new information in interface structure */
2267
2268 reset_snmp_stats = (0 == found || interface->hostid != hostid || interface->type != type ||
2269 interface->useip != useip);
2270
2271 interface->hostid = hostid;
2272 interface->type = type;
2273 interface->main = main_;
2274 interface->useip = useip;
2275 reset_snmp_stats |= (SUCCEED == DCstrpool_replace(found, &interface->ip, row[5]));
2276 reset_snmp_stats |= (SUCCEED == DCstrpool_replace(found, &interface->dns, row[6]));
2277 reset_snmp_stats |= (SUCCEED == DCstrpool_replace(found, &interface->port, row[7]));
2278
2279 /* update interfaces_ht index using new data, if not done already */
2280
2281 if (1 == update_index)
2282 {
2283 interface_ht_local.hostid = interface->hostid;
2284 interface_ht_local.type = interface->type;
2285 interface_ht_local.interface_ptr = interface;
2286 zbx_hashset_insert(&config->interfaces_ht, &interface_ht_local, sizeof(ZBX_DC_INTERFACE_HT));
2287 }
2288
2289 /* update interface_snmpaddrs for SNMP traps or reset bulk request statistics */
2290
2291 if (INTERFACE_TYPE_SNMP == interface->type)
2292 {
2293 ZBX_DC_SNMPINTERFACE *snmp;
2294 unsigned char bulk_changed;
2295
2296 interface_snmpaddr_local.addr = (0 != interface->useip ? interface->ip : interface->dns);
2297
2298 if ('\0' != *interface_snmpaddr_local.addr)
2299 {
2300 if (NULL == (interface_snmpaddr = (ZBX_DC_INTERFACE_ADDR *)zbx_hashset_search(&config->interface_snmpaddrs,
2301 &interface_snmpaddr_local)))
2302 {
2303 zbx_strpool_acquire(interface_snmpaddr_local.addr);
2304
2305 interface_snmpaddr = (ZBX_DC_INTERFACE_ADDR *)zbx_hashset_insert(&config->interface_snmpaddrs,
2306 &interface_snmpaddr_local, sizeof(ZBX_DC_INTERFACE_ADDR));
2307 zbx_vector_uint64_create_ext(&interface_snmpaddr->interfaceids,
2308 __config_mem_malloc_func,
2309 __config_mem_realloc_func,
2310 __config_mem_free_func);
2311 }
2312
2313 zbx_vector_uint64_append(&interface_snmpaddr->interfaceids, interfaceid);
2314 }
2315
2316 if (FAIL == DBis_null(row[8]))
2317 {
2318 snmp = dc_interface_snmp_set(interfaceid, (const char **)row, &bulk_changed);
2319
2320 if (1 == reset_snmp_stats || 0 != bulk_changed)
2321 {
2322 snmp->max_succeed = 0;
2323 snmp->min_fail = MAX_SNMP_ITEMS + 1;
2324 }
2325 }
2326 else
2327 THIS_SHOULD_NEVER_HAPPEN;
2328 }
2329
2330 /* first resolve macros for ip and dns fields in main agent interface */
2331 /* because other interfaces might reference main interfaces ip and dns */
2332 /* with {HOST.IP} and {HOST.DNS} macros */
2333 if (1 == interface->main && INTERFACE_TYPE_AGENT == interface->type)
2334 substitute_host_interface_macros(interface);
2335
2336 if (0 == found)
2337 {
2338 /* new interface - add it to a list of host interfaces in 'config->hosts' hashset */
2339
2340 int exists = 0;
2341
2342 /* It is an error if the pointer is already in the list. Detect it. */
2343
2344 for (i = 0; i < host->interfaces_v.values_num; i++)
2345 {
2346 if (interface == host->interfaces_v.values[i])
2347 {
2348 exists = 1;
2349 break;
2350 }
2351 }
2352
2353 if (0 == exists)
2354 zbx_vector_ptr_append(&host->interfaces_v, interface);
2355 else
2356 THIS_SHOULD_NEVER_HAPPEN;
2357 }
2358 }
2359
2360 /* resolve macros in other interfaces */
2361
2362 for (i = 0; i < interfaces.values_num; i++)
2363 {
2364 interface = (ZBX_DC_INTERFACE *)interfaces.values[i];
2365
2366 if (1 != interface->main || INTERFACE_TYPE_AGENT != interface->type)
2367 substitute_host_interface_macros(interface);
2368 }
2369
2370 /* remove deleted interfaces from buffer */
2371
2372 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
2373 {
2374 if (NULL == (interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces, &rowid)))
2375 continue;
2376
2377 /* remove interface from the list of host interfaces in 'config->hosts' hashset */
2378
2379 if (NULL != (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &interface->hostid)))
2380 {
2381 for (i = 0; i < host->interfaces_v.values_num; i++)
2382 {
2383 if (interface == host->interfaces_v.values[i])
2384 {
2385 zbx_vector_ptr_remove(&host->interfaces_v, i);
2386 break;
2387 }
2388 }
2389 }
2390
2391 if (INTERFACE_TYPE_SNMP == interface->type)
2392 {
2393 dc_interface_snmpaddrs_remove(interface);
2394 dc_interface_snmp_remove(interface->interfaceid);
2395 }
2396
2397 if (1 == interface->main)
2398 {
2399 interface_ht_local.hostid = interface->hostid;
2400 interface_ht_local.type = interface->type;
2401 interface_ht = (ZBX_DC_INTERFACE_HT *)zbx_hashset_search(&config->interfaces_ht, &interface_ht_local);
2402
2403 if (NULL != interface_ht && interface == interface_ht->interface_ptr)
2404 {
2405 /* see ZBX-4045 for NULL check in the conditional */
2406 zbx_hashset_remove(&config->interfaces_ht, &interface_ht_local);
2407 }
2408 }
2409
2410 zbx_strpool_release(interface->ip);
2411 zbx_strpool_release(interface->dns);
2412 zbx_strpool_release(interface->port);
2413
2414 zbx_hashset_remove_direct(&config->interfaces, interface);
2415 }
2416
2417 zbx_vector_ptr_destroy(&interfaces);
2418
2419 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
2420 }
2421
2422 /******************************************************************************
2423 * *
2424 * Function: dc_interface_snmpitems_remove *
2425 * *
2426 * Purpose: remove item from interfaceid -> itemid index *
2427 * *
2428 * Parameters: interface - [IN] the item *
2429 * *
2430 ******************************************************************************/
dc_interface_snmpitems_remove(ZBX_DC_ITEM * item)2431 static void dc_interface_snmpitems_remove(ZBX_DC_ITEM *item)
2432 {
2433 ZBX_DC_INTERFACE_ITEM *ifitem;
2434 int index;
2435 zbx_uint64_t interfaceid;
2436
2437 if (0 == (interfaceid = item->interfaceid))
2438 return;
2439
2440 if (NULL == (ifitem = (ZBX_DC_INTERFACE_ITEM *)zbx_hashset_search(&config->interface_snmpitems, &interfaceid)))
2441 return;
2442
2443 if (FAIL == (index = zbx_vector_uint64_search(&ifitem->itemids, item->itemid, ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2444 return;
2445
2446 zbx_vector_uint64_remove_noorder(&ifitem->itemids, index);
2447
2448 if (0 == ifitem->itemids.values_num)
2449 {
2450 zbx_vector_uint64_destroy(&ifitem->itemids);
2451 zbx_hashset_remove_direct(&config->interface_snmpitems, ifitem);
2452 }
2453 }
2454
2455 /******************************************************************************
2456 * *
2457 * Function: dc_masteritem_remove_depitem *
2458 * *
2459 * Purpose: remove itemid from master item dependent itemid vector *
2460 * *
2461 * Parameters: master_itemid - [IN] the master item identifier *
2462 * dep_itemid - [IN] the dependent item identifier *
2463 * *
2464 ******************************************************************************/
dc_masteritem_remove_depitem(zbx_uint64_t master_itemid,zbx_uint64_t dep_itemid)2465 static void dc_masteritem_remove_depitem(zbx_uint64_t master_itemid, zbx_uint64_t dep_itemid)
2466 {
2467 ZBX_DC_MASTERITEM *masteritem;
2468 int index;
2469 zbx_uint64_pair_t pair;
2470
2471 if (NULL == (masteritem = (ZBX_DC_MASTERITEM *)zbx_hashset_search(&config->masteritems, &master_itemid)))
2472 return;
2473
2474 pair.first = dep_itemid;
2475 if (FAIL == (index = zbx_vector_uint64_pair_search(&masteritem->dep_itemids, pair,
2476 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2477 {
2478 return;
2479 }
2480
2481 zbx_vector_uint64_pair_remove_noorder(&masteritem->dep_itemids, index);
2482
2483 if (0 == masteritem->dep_itemids.values_num)
2484 {
2485 zbx_vector_uint64_pair_destroy(&masteritem->dep_itemids);
2486 zbx_hashset_remove_direct(&config->masteritems, masteritem);
2487 }
2488 }
2489
2490 /******************************************************************************
2491 * *
2492 * Function: dc_host_update_agent_stats *
2493 * *
2494 * Purpose: update number of items per agent statistics *
2495 * *
2496 * Parameters: host - [IN] the host *
2497 * type - [IN] the item type (ITEM_TYPE_*) *
2498 * num - [IN] the number of items (+) added, (-) removed *
2499 * *
2500 ******************************************************************************/
dc_host_update_agent_stats(ZBX_DC_HOST * host,unsigned char type,int num)2501 static void dc_host_update_agent_stats(ZBX_DC_HOST *host, unsigned char type, int num)
2502 {
2503 switch (type)
2504 {
2505 case ITEM_TYPE_ZABBIX:
2506 host->items_num += num;
2507 break;
2508 case ITEM_TYPE_SNMP:
2509 host->snmp_items_num += num;
2510 break;
2511 case ITEM_TYPE_IPMI:
2512 host->ipmi_items_num += num;
2513 break;
2514 case ITEM_TYPE_JMX:
2515 host->jmx_items_num += num;
2516 }
2517 }
2518
DCsync_items(zbx_dbsync_t * sync,int flags)2519 static void DCsync_items(zbx_dbsync_t *sync, int flags)
2520 {
2521 char **row;
2522 zbx_uint64_t rowid;
2523 unsigned char tag;
2524
2525 ZBX_DC_HOST *host;
2526
2527 ZBX_DC_ITEM *item;
2528 ZBX_DC_NUMITEM *numitem;
2529 ZBX_DC_SNMPITEM *snmpitem;
2530 ZBX_DC_IPMIITEM *ipmiitem;
2531 ZBX_DC_TRAPITEM *trapitem;
2532 ZBX_DC_DEPENDENTITEM *depitem;
2533 ZBX_DC_LOGITEM *logitem;
2534 ZBX_DC_DBITEM *dbitem;
2535 ZBX_DC_SSHITEM *sshitem;
2536 ZBX_DC_TELNETITEM *telnetitem;
2537 ZBX_DC_SIMPLEITEM *simpleitem;
2538 ZBX_DC_JMXITEM *jmxitem;
2539 ZBX_DC_CALCITEM *calcitem;
2540 ZBX_DC_INTERFACE_ITEM *interface_snmpitem;
2541 ZBX_DC_MASTERITEM *master;
2542 ZBX_DC_PREPROCITEM *preprocitem;
2543 ZBX_DC_HTTPITEM *httpitem;
2544 ZBX_DC_ITEM_HK *item_hk, item_hk_local;
2545
2546 time_t now;
2547 unsigned char status, type, value_type, old_poller_type;
2548 int found, update_index, ret, i, old_nextcheck;
2549 zbx_uint64_t itemid, hostid;
2550 zbx_vector_ptr_t dep_items;
2551
2552 zbx_vector_ptr_create(&dep_items);
2553
2554 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
2555
2556 now = time(NULL);
2557
2558 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
2559 {
2560 /* removed rows will be always added at the end */
2561 if (ZBX_DBSYNC_ROW_REMOVE == tag)
2562 break;
2563
2564 flags &= ZBX_REFRESH_UNSUPPORTED_CHANGED;
2565
2566 ZBX_STR2UINT64(itemid, row[0]);
2567 ZBX_STR2UINT64(hostid, row[1]);
2568 ZBX_STR2UCHAR(status, row[2]);
2569 ZBX_STR2UCHAR(type, row[3]);
2570
2571 if (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)))
2572 continue;
2573
2574 item = (ZBX_DC_ITEM *)DCfind_id(&config->items, itemid, sizeof(ZBX_DC_ITEM), &found);
2575
2576 /* template item */
2577 ZBX_DBROW2UINT64(item->templateid, row[48]);
2578
2579 /* LLD item prototype */
2580 ZBX_DBROW2UINT64(item->parent_itemid, row[49]);
2581
2582 if (0 != found && ITEM_TYPE_SNMPTRAP == item->type)
2583 dc_interface_snmpitems_remove(item);
2584
2585 /* see whether we should and can update items_hk index at this point */
2586
2587 update_index = 0;
2588
2589 if (0 == found || item->hostid != hostid || 0 != strcmp(item->key, row[5]))
2590 {
2591 if (1 == found)
2592 {
2593 item_hk_local.hostid = item->hostid;
2594 item_hk_local.key = item->key;
2595
2596 if (NULL == (item_hk = (ZBX_DC_ITEM_HK *)zbx_hashset_search(&config->items_hk,
2597 &item_hk_local)))
2598 {
2599 /* item keys should be unique for items within a host, otherwise items with */
2600 /* same key share index and removal of last added item already cleared index */
2601 THIS_SHOULD_NEVER_HAPPEN;
2602 }
2603 else if (item == item_hk->item_ptr)
2604 {
2605 zbx_strpool_release(item_hk->key);
2606 zbx_hashset_remove_direct(&config->items_hk, item_hk);
2607 }
2608 }
2609
2610 item_hk_local.hostid = hostid;
2611 item_hk_local.key = row[5];
2612 item_hk = (ZBX_DC_ITEM_HK *)zbx_hashset_search(&config->items_hk, &item_hk_local);
2613
2614 if (NULL != item_hk)
2615 item_hk->item_ptr = item;
2616 else
2617 update_index = 1;
2618 }
2619
2620 /* store new information in item structure */
2621
2622 item->hostid = hostid;
2623 item->flags = (unsigned char)atoi(row[18]);
2624 ZBX_DBROW2UINT64(item->interfaceid, row[19]);
2625
2626 if (SUCCEED != is_time_suffix(row[22], &item->history_sec, ZBX_LENGTH_UNLIMITED))
2627 item->history_sec = ZBX_HK_PERIOD_MAX;
2628
2629 if (0 != item->history_sec && ZBX_HK_OPTION_ENABLED == config->config->hk.history_global)
2630 item->history_sec = config->config->hk.history;
2631
2632 item->history = (0 != item->history_sec);
2633
2634 ZBX_STR2UCHAR(item->inventory_link, row[24]);
2635 ZBX_DBROW2UINT64(item->valuemapid, row[25]);
2636
2637 if (0 != (ZBX_FLAG_DISCOVERY_RULE & item->flags))
2638 value_type = ITEM_VALUE_TYPE_TEXT;
2639 else
2640 ZBX_STR2UCHAR(value_type, row[4]);
2641
2642 if (SUCCEED == DCstrpool_replace(found, &item->key, row[5]))
2643 flags |= ZBX_ITEM_KEY_CHANGED;
2644
2645 if (0 == found)
2646 {
2647 item->triggers = NULL;
2648 item->update_triggers = 0;
2649 item->nextcheck = 0;
2650 item->lastclock = 0;
2651 item->state = (unsigned char)atoi(row[12]);
2652 ZBX_STR2UINT64(item->lastlogsize, row[20]);
2653 item->mtime = atoi(row[21]);
2654 DCstrpool_replace(found, &item->error, row[27]);
2655 item->data_expected_from = now;
2656 item->location = ZBX_LOC_NOWHERE;
2657 item->poller_type = ZBX_NO_POLLER;
2658 item->queue_priority = ZBX_QUEUE_PRIORITY_NORMAL;
2659 item->schedulable = 1;
2660 }
2661 else
2662 {
2663 if (item->type != type)
2664 flags |= ZBX_ITEM_TYPE_CHANGED;
2665
2666 if (ITEM_STATUS_ACTIVE == status && ITEM_STATUS_ACTIVE != item->status)
2667 item->data_expected_from = now;
2668
2669 if (ITEM_STATUS_ACTIVE == item->status)
2670 dc_host_update_agent_stats(host, item->type, -1);
2671 }
2672
2673 if (ITEM_STATUS_ACTIVE == status)
2674 dc_host_update_agent_stats(host, type, 1);
2675
2676 item->type = type;
2677 item->status = status;
2678 item->value_type = value_type;
2679
2680 /* update items_hk index using new data, if not done already */
2681
2682 if (1 == update_index)
2683 {
2684 item_hk_local.hostid = item->hostid;
2685 item_hk_local.key = zbx_strpool_acquire(item->key);
2686 item_hk_local.item_ptr = item;
2687 zbx_hashset_insert(&config->items_hk, &item_hk_local, sizeof(ZBX_DC_ITEM_HK));
2688 }
2689
2690 /* process item intervals and update item nextcheck */
2691
2692 if (SUCCEED == DCstrpool_replace(found, &item->delay, row[8]))
2693 flags |= ZBX_ITEM_DELAY_CHANGED;
2694
2695 /* numeric items */
2696
2697 if (ITEM_VALUE_TYPE_FLOAT == item->value_type || ITEM_VALUE_TYPE_UINT64 == item->value_type)
2698 {
2699 int trends_sec;
2700
2701 numitem = (ZBX_DC_NUMITEM *)DCfind_id(&config->numitems, itemid, sizeof(ZBX_DC_NUMITEM), &found);
2702
2703 if (SUCCEED != is_time_suffix(row[23], &trends_sec, ZBX_LENGTH_UNLIMITED))
2704 trends_sec = ZBX_HK_PERIOD_MAX;
2705
2706 if (0 != trends_sec && ZBX_HK_OPTION_ENABLED == config->config->hk.trends_global)
2707 trends_sec = config->config->hk.trends;
2708
2709 numitem->trends = (0 != trends_sec);
2710 numitem->trends_sec = trends_sec;
2711
2712 DCstrpool_replace(found, &numitem->units, row[26]);
2713 }
2714 else if (NULL != (numitem = (ZBX_DC_NUMITEM *)zbx_hashset_search(&config->numitems, &itemid)))
2715 {
2716 /* remove parameters for non-numeric item */
2717
2718 zbx_strpool_release(numitem->units);
2719
2720 zbx_hashset_remove_direct(&config->numitems, numitem);
2721 }
2722
2723 /* SNMP items */
2724
2725 if (ITEM_TYPE_SNMP == item->type)
2726 {
2727 snmpitem = (ZBX_DC_SNMPITEM *)DCfind_id(&config->snmpitems, itemid, sizeof(ZBX_DC_SNMPITEM), &found);
2728
2729 if (SUCCEED == DCstrpool_replace(found, &snmpitem->snmp_oid, row[6]))
2730 {
2731 if (NULL != strchr(snmpitem->snmp_oid, '{'))
2732 snmpitem->snmp_oid_type = ZBX_SNMP_OID_TYPE_MACRO;
2733 else if (NULL != strchr(snmpitem->snmp_oid, '['))
2734 snmpitem->snmp_oid_type = ZBX_SNMP_OID_TYPE_DYNAMIC;
2735 else
2736 snmpitem->snmp_oid_type = ZBX_SNMP_OID_TYPE_NORMAL;
2737 }
2738 }
2739 else if (NULL != (snmpitem = (ZBX_DC_SNMPITEM *)zbx_hashset_search(&config->snmpitems, &itemid)))
2740 {
2741 /* remove SNMP parameters for non-SNMP item */
2742
2743 zbx_strpool_release(snmpitem->snmp_oid);
2744 zbx_hashset_remove_direct(&config->snmpitems, snmpitem);
2745 }
2746
2747 /* IPMI items */
2748
2749 if (ITEM_TYPE_IPMI == item->type)
2750 {
2751 ipmiitem = (ZBX_DC_IPMIITEM *)DCfind_id(&config->ipmiitems, itemid, sizeof(ZBX_DC_IPMIITEM), &found);
2752
2753 DCstrpool_replace(found, &ipmiitem->ipmi_sensor, row[7]);
2754 }
2755 else if (NULL != (ipmiitem = (ZBX_DC_IPMIITEM *)zbx_hashset_search(&config->ipmiitems, &itemid)))
2756 {
2757 /* remove IPMI parameters for non-IPMI item */
2758 zbx_strpool_release(ipmiitem->ipmi_sensor);
2759 zbx_hashset_remove_direct(&config->ipmiitems, ipmiitem);
2760 }
2761
2762 /* trapper items */
2763
2764 if (ITEM_TYPE_TRAPPER == item->type && '\0' != *row[9])
2765 {
2766 trapitem = (ZBX_DC_TRAPITEM *)DCfind_id(&config->trapitems, itemid, sizeof(ZBX_DC_TRAPITEM), &found);
2767 DCstrpool_replace(found, &trapitem->trapper_hosts, row[9]);
2768 }
2769 else if (NULL != (trapitem = (ZBX_DC_TRAPITEM *)zbx_hashset_search(&config->trapitems, &itemid)))
2770 {
2771 /* remove trapper_hosts parameter */
2772 zbx_strpool_release(trapitem->trapper_hosts);
2773 zbx_hashset_remove_direct(&config->trapitems, trapitem);
2774 }
2775
2776 /* dependent items */
2777
2778 if (ITEM_TYPE_DEPENDENT == item->type && SUCCEED != DBis_null(row[29]))
2779 {
2780 depitem = (ZBX_DC_DEPENDENTITEM *)DCfind_id(&config->dependentitems, itemid,
2781 sizeof(ZBX_DC_DEPENDENTITEM), &found);
2782
2783 if (1 == found)
2784 depitem->last_master_itemid = depitem->master_itemid;
2785 else
2786 depitem->last_master_itemid = 0;
2787
2788 depitem->flags = item->flags;
2789 ZBX_STR2UINT64(depitem->master_itemid, row[29]);
2790
2791 if (depitem->last_master_itemid != depitem->master_itemid)
2792 zbx_vector_ptr_append(&dep_items, depitem);
2793 }
2794 else if (NULL != (depitem = (ZBX_DC_DEPENDENTITEM *)zbx_hashset_search(&config->dependentitems, &itemid)))
2795 {
2796 dc_masteritem_remove_depitem(depitem->master_itemid, itemid);
2797 zbx_hashset_remove_direct(&config->dependentitems, depitem);
2798 }
2799
2800 /* log items */
2801
2802 if (ITEM_VALUE_TYPE_LOG == item->value_type && '\0' != *row[10])
2803 {
2804 logitem = (ZBX_DC_LOGITEM *)DCfind_id(&config->logitems, itemid, sizeof(ZBX_DC_LOGITEM), &found);
2805
2806 DCstrpool_replace(found, &logitem->logtimefmt, row[10]);
2807 }
2808 else if (NULL != (logitem = (ZBX_DC_LOGITEM *)zbx_hashset_search(&config->logitems, &itemid)))
2809 {
2810 /* remove logtimefmt parameter */
2811 zbx_strpool_release(logitem->logtimefmt);
2812 zbx_hashset_remove_direct(&config->logitems, logitem);
2813 }
2814
2815 /* db items */
2816
2817 if (ITEM_TYPE_DB_MONITOR == item->type && '\0' != *row[11])
2818 {
2819 dbitem = (ZBX_DC_DBITEM *)DCfind_id(&config->dbitems, itemid, sizeof(ZBX_DC_DBITEM), &found);
2820
2821 DCstrpool_replace(found, &dbitem->params, row[11]);
2822 DCstrpool_replace(found, &dbitem->username, row[14]);
2823 DCstrpool_replace(found, &dbitem->password, row[15]);
2824 }
2825 else if (NULL != (dbitem = (ZBX_DC_DBITEM *)zbx_hashset_search(&config->dbitems, &itemid)))
2826 {
2827 /* remove db item parameters */
2828 zbx_strpool_release(dbitem->params);
2829 zbx_strpool_release(dbitem->username);
2830 zbx_strpool_release(dbitem->password);
2831
2832 zbx_hashset_remove_direct(&config->dbitems, dbitem);
2833 }
2834
2835 /* SSH items */
2836
2837 if (ITEM_TYPE_SSH == item->type)
2838 {
2839 sshitem = (ZBX_DC_SSHITEM *)DCfind_id(&config->sshitems, itemid, sizeof(ZBX_DC_SSHITEM), &found);
2840
2841 sshitem->authtype = (unsigned short)atoi(row[13]);
2842 DCstrpool_replace(found, &sshitem->username, row[14]);
2843 DCstrpool_replace(found, &sshitem->password, row[15]);
2844 DCstrpool_replace(found, &sshitem->publickey, row[16]);
2845 DCstrpool_replace(found, &sshitem->privatekey, row[17]);
2846 DCstrpool_replace(found, &sshitem->params, row[11]);
2847 }
2848 else if (NULL != (sshitem = (ZBX_DC_SSHITEM *)zbx_hashset_search(&config->sshitems, &itemid)))
2849 {
2850 /* remove SSH item parameters */
2851
2852 zbx_strpool_release(sshitem->username);
2853 zbx_strpool_release(sshitem->password);
2854 zbx_strpool_release(sshitem->publickey);
2855 zbx_strpool_release(sshitem->privatekey);
2856 zbx_strpool_release(sshitem->params);
2857
2858 zbx_hashset_remove_direct(&config->sshitems, sshitem);
2859 }
2860
2861 /* TELNET items */
2862
2863 if (ITEM_TYPE_TELNET == item->type)
2864 {
2865 telnetitem = (ZBX_DC_TELNETITEM *)DCfind_id(&config->telnetitems, itemid, sizeof(ZBX_DC_TELNETITEM), &found);
2866
2867 DCstrpool_replace(found, &telnetitem->username, row[14]);
2868 DCstrpool_replace(found, &telnetitem->password, row[15]);
2869 DCstrpool_replace(found, &telnetitem->params, row[11]);
2870 }
2871 else if (NULL != (telnetitem = (ZBX_DC_TELNETITEM *)zbx_hashset_search(&config->telnetitems, &itemid)))
2872 {
2873 /* remove TELNET item parameters */
2874
2875 zbx_strpool_release(telnetitem->username);
2876 zbx_strpool_release(telnetitem->password);
2877 zbx_strpool_release(telnetitem->params);
2878
2879 zbx_hashset_remove_direct(&config->telnetitems, telnetitem);
2880 }
2881
2882 /* simple items */
2883
2884 if (ITEM_TYPE_SIMPLE == item->type)
2885 {
2886 simpleitem = (ZBX_DC_SIMPLEITEM *)DCfind_id(&config->simpleitems, itemid, sizeof(ZBX_DC_SIMPLEITEM), &found);
2887
2888 DCstrpool_replace(found, &simpleitem->username, row[14]);
2889 DCstrpool_replace(found, &simpleitem->password, row[15]);
2890 }
2891 else if (NULL != (simpleitem = (ZBX_DC_SIMPLEITEM *)zbx_hashset_search(&config->simpleitems, &itemid)))
2892 {
2893 /* remove simple item parameters */
2894
2895 zbx_strpool_release(simpleitem->username);
2896 zbx_strpool_release(simpleitem->password);
2897
2898 zbx_hashset_remove_direct(&config->simpleitems, simpleitem);
2899 }
2900
2901 /* JMX items */
2902
2903 if (ITEM_TYPE_JMX == item->type)
2904 {
2905 jmxitem = (ZBX_DC_JMXITEM *)DCfind_id(&config->jmxitems, itemid, sizeof(ZBX_DC_JMXITEM), &found);
2906
2907 DCstrpool_replace(found, &jmxitem->username, row[14]);
2908 DCstrpool_replace(found, &jmxitem->password, row[15]);
2909 DCstrpool_replace(found, &jmxitem->jmx_endpoint, row[28]);
2910 }
2911 else if (NULL != (jmxitem = (ZBX_DC_JMXITEM *)zbx_hashset_search(&config->jmxitems, &itemid)))
2912 {
2913 /* remove JMX item parameters */
2914
2915 zbx_strpool_release(jmxitem->username);
2916 zbx_strpool_release(jmxitem->password);
2917 zbx_strpool_release(jmxitem->jmx_endpoint);
2918
2919 zbx_hashset_remove_direct(&config->jmxitems, jmxitem);
2920 }
2921
2922 /* SNMP trap items for current server/proxy */
2923
2924 if (ITEM_TYPE_SNMPTRAP == item->type && 0 == host->proxy_hostid)
2925 {
2926 interface_snmpitem = (ZBX_DC_INTERFACE_ITEM *)DCfind_id(&config->interface_snmpitems,
2927 item->interfaceid, sizeof(ZBX_DC_INTERFACE_ITEM), &found);
2928
2929 if (0 == found)
2930 {
2931 zbx_vector_uint64_create_ext(&interface_snmpitem->itemids,
2932 __config_mem_malloc_func,
2933 __config_mem_realloc_func,
2934 __config_mem_free_func);
2935 }
2936
2937 zbx_vector_uint64_append(&interface_snmpitem->itemids, itemid);
2938 }
2939
2940 /* calculated items */
2941
2942 if (ITEM_TYPE_CALCULATED == item->type)
2943 {
2944 calcitem = (ZBX_DC_CALCITEM *)DCfind_id(&config->calcitems, itemid, sizeof(ZBX_DC_CALCITEM), &found);
2945
2946 DCstrpool_replace(found, &calcitem->params, row[11]);
2947 }
2948 else if (NULL != (calcitem = (ZBX_DC_CALCITEM *)zbx_hashset_search(&config->calcitems, &itemid)))
2949 {
2950 /* remove calculated item parameters */
2951
2952 zbx_strpool_release(calcitem->params);
2953 zbx_hashset_remove_direct(&config->calcitems, calcitem);
2954 }
2955
2956 /* HTTP agent items */
2957
2958 if (ITEM_TYPE_HTTPAGENT == item->type)
2959 {
2960 httpitem = (ZBX_DC_HTTPITEM *)DCfind_id(&config->httpitems, itemid, sizeof(ZBX_DC_HTTPITEM),
2961 &found);
2962
2963 DCstrpool_replace(found, &httpitem->timeout, row[30]);
2964 DCstrpool_replace(found, &httpitem->url, row[31]);
2965 DCstrpool_replace(found, &httpitem->query_fields, row[32]);
2966 DCstrpool_replace(found, &httpitem->posts, row[33]);
2967 DCstrpool_replace(found, &httpitem->status_codes, row[34]);
2968 httpitem->follow_redirects = (unsigned char)atoi(row[35]);
2969 httpitem->post_type = (unsigned char)atoi(row[36]);
2970 DCstrpool_replace(found, &httpitem->http_proxy, row[37]);
2971 DCstrpool_replace(found, &httpitem->headers, row[38]);
2972 httpitem->retrieve_mode = (unsigned char)atoi(row[39]);
2973 httpitem->request_method = (unsigned char)atoi(row[40]);
2974 httpitem->output_format = (unsigned char)atoi(row[41]);
2975 DCstrpool_replace(found, &httpitem->ssl_cert_file, row[42]);
2976 DCstrpool_replace(found, &httpitem->ssl_key_file, row[43]);
2977 DCstrpool_replace(found, &httpitem->ssl_key_password, row[44]);
2978 httpitem->verify_peer = (unsigned char)atoi(row[45]);
2979 httpitem->verify_host = (unsigned char)atoi(row[46]);
2980 httpitem->allow_traps = (unsigned char)atoi(row[47]);
2981
2982 httpitem->authtype = (unsigned char)atoi(row[13]);
2983 DCstrpool_replace(found, &httpitem->username, row[14]);
2984 DCstrpool_replace(found, &httpitem->password, row[15]);
2985 DCstrpool_replace(found, &httpitem->trapper_hosts, row[9]);
2986 }
2987 else if (NULL != (httpitem = (ZBX_DC_HTTPITEM *)zbx_hashset_search(&config->httpitems, &itemid)))
2988 {
2989 zbx_strpool_release(httpitem->timeout);
2990 zbx_strpool_release(httpitem->url);
2991 zbx_strpool_release(httpitem->query_fields);
2992 zbx_strpool_release(httpitem->posts);
2993 zbx_strpool_release(httpitem->status_codes);
2994 zbx_strpool_release(httpitem->http_proxy);
2995 zbx_strpool_release(httpitem->headers);
2996 zbx_strpool_release(httpitem->ssl_cert_file);
2997 zbx_strpool_release(httpitem->ssl_key_file);
2998 zbx_strpool_release(httpitem->ssl_key_password);
2999 zbx_strpool_release(httpitem->username);
3000 zbx_strpool_release(httpitem->password);
3001 zbx_strpool_release(httpitem->trapper_hosts);
3002
3003 zbx_hashset_remove_direct(&config->httpitems, httpitem);
3004 }
3005
3006 /* it is crucial to update type specific (config->snmpitems, config->ipmiitems, etc.) hashsets before */
3007 /* attempting to requeue an item because type specific properties are used to arrange items in queues */
3008
3009 old_poller_type = item->poller_type;
3010 old_nextcheck = item->nextcheck;
3011
3012 if (ITEM_STATUS_ACTIVE == item->status && HOST_STATUS_MONITORED == host->status)
3013 {
3014 DCitem_poller_type_update(item, host, flags);
3015
3016 if (SUCCEED == zbx_is_counted_in_item_queue(item->type, item->key))
3017 {
3018 char *error = NULL;
3019
3020 if (FAIL == DCitem_nextcheck_update(item, host, item->state, flags, now, &error))
3021 {
3022 zbx_timespec_t ts = {now, 0};
3023
3024 /* Usual way for an item to become not supported is to receive an error */
3025 /* instead of value. Item state and error will be updated by history syncer */
3026 /* during history sync following a regular procedure with item update in */
3027 /* database and config cache, logging etc. There is no need to set */
3028 /* ITEM_STATE_NOTSUPPORTED here. */
3029
3030 if (0 == host->proxy_hostid)
3031 {
3032 dc_add_history(item->itemid, item->value_type, 0, NULL, &ts,
3033 ITEM_STATE_NOTSUPPORTED, error);
3034 }
3035 zbx_free(error);
3036 }
3037 }
3038 }
3039 else
3040 {
3041 item->nextcheck = 0;
3042 item->queue_priority = ZBX_QUEUE_PRIORITY_NORMAL;
3043 item->poller_type = ZBX_NO_POLLER;
3044 }
3045
3046 DCupdate_item_queue(item, old_poller_type, old_nextcheck);
3047 }
3048
3049 /* update dependent item vectors within master items */
3050
3051 for (i = 0; i < dep_items.values_num; i++)
3052 {
3053 zbx_uint64_pair_t pair;
3054
3055 depitem = (ZBX_DC_DEPENDENTITEM *)dep_items.values[i];
3056 dc_masteritem_remove_depitem(depitem->last_master_itemid, depitem->itemid);
3057 pair.first = depitem->itemid;
3058 pair.second = depitem->flags;
3059
3060 /* append item to dependent item vector of master item */
3061 if (NULL == (master = (ZBX_DC_MASTERITEM *)zbx_hashset_search(&config->masteritems, &depitem->master_itemid)))
3062 {
3063 ZBX_DC_MASTERITEM master_local;
3064
3065 master_local.itemid = depitem->master_itemid;
3066 master = (ZBX_DC_MASTERITEM *)zbx_hashset_insert(&config->masteritems, &master_local, sizeof(master_local));
3067
3068 zbx_vector_uint64_pair_create_ext(&master->dep_itemids, __config_mem_malloc_func,
3069 __config_mem_realloc_func, __config_mem_free_func);
3070 }
3071
3072 zbx_vector_uint64_pair_append(&master->dep_itemids, pair);
3073 }
3074
3075 zbx_vector_ptr_destroy(&dep_items);
3076
3077 /* remove deleted items from buffer */
3078 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
3079 {
3080 if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &rowid)))
3081 continue;
3082
3083 if (ITEM_STATUS_ACTIVE == item->status &&
3084 NULL != (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &item->hostid)))
3085 {
3086 dc_host_update_agent_stats(host, item->type, -1);
3087 }
3088
3089 itemid = item->itemid;
3090
3091 if (ITEM_TYPE_SNMPTRAP == item->type)
3092 dc_interface_snmpitems_remove(item);
3093
3094 /* numeric items */
3095
3096 if (ITEM_VALUE_TYPE_FLOAT == item->value_type || ITEM_VALUE_TYPE_UINT64 == item->value_type)
3097 {
3098 numitem = (ZBX_DC_NUMITEM *)zbx_hashset_search(&config->numitems, &itemid);
3099
3100 zbx_strpool_release(numitem->units);
3101
3102 zbx_hashset_remove_direct(&config->numitems, numitem);
3103 }
3104
3105 /* SNMP items */
3106
3107 if (ITEM_TYPE_SNMP == item->type)
3108 {
3109 snmpitem = (ZBX_DC_SNMPITEM *)zbx_hashset_search(&config->snmpitems, &itemid);
3110 zbx_strpool_release(snmpitem->snmp_oid);
3111 zbx_hashset_remove_direct(&config->snmpitems, snmpitem);
3112 }
3113
3114 /* IPMI items */
3115
3116 if (ITEM_TYPE_IPMI == item->type)
3117 {
3118 ipmiitem = (ZBX_DC_IPMIITEM *)zbx_hashset_search(&config->ipmiitems, &itemid);
3119 zbx_strpool_release(ipmiitem->ipmi_sensor);
3120 zbx_hashset_remove_direct(&config->ipmiitems, ipmiitem);
3121 }
3122
3123 /* trapper items */
3124
3125 if (ITEM_TYPE_TRAPPER == item->type &&
3126 NULL != (trapitem = (ZBX_DC_TRAPITEM *)zbx_hashset_search(&config->trapitems, &itemid)))
3127 {
3128 zbx_strpool_release(trapitem->trapper_hosts);
3129 zbx_hashset_remove_direct(&config->trapitems, trapitem);
3130 }
3131
3132 /* dependent items */
3133
3134 if (NULL != (depitem = (ZBX_DC_DEPENDENTITEM *)zbx_hashset_search(&config->dependentitems, &itemid)))
3135 {
3136 dc_masteritem_remove_depitem(depitem->master_itemid, itemid);
3137 zbx_hashset_remove_direct(&config->dependentitems, depitem);
3138 }
3139
3140 /* log items */
3141
3142 if (ITEM_VALUE_TYPE_LOG == item->value_type &&
3143 NULL != (logitem = (ZBX_DC_LOGITEM *)zbx_hashset_search(&config->logitems, &itemid)))
3144 {
3145 zbx_strpool_release(logitem->logtimefmt);
3146 zbx_hashset_remove_direct(&config->logitems, logitem);
3147 }
3148
3149 /* db items */
3150
3151 if (ITEM_TYPE_DB_MONITOR == item->type &&
3152 NULL != (dbitem = (ZBX_DC_DBITEM *)zbx_hashset_search(&config->dbitems, &itemid)))
3153 {
3154 zbx_strpool_release(dbitem->params);
3155 zbx_strpool_release(dbitem->username);
3156 zbx_strpool_release(dbitem->password);
3157
3158 zbx_hashset_remove_direct(&config->dbitems, dbitem);
3159 }
3160
3161 /* SSH items */
3162
3163 if (ITEM_TYPE_SSH == item->type)
3164 {
3165 sshitem = (ZBX_DC_SSHITEM *)zbx_hashset_search(&config->sshitems, &itemid);
3166
3167 zbx_strpool_release(sshitem->username);
3168 zbx_strpool_release(sshitem->password);
3169 zbx_strpool_release(sshitem->publickey);
3170 zbx_strpool_release(sshitem->privatekey);
3171 zbx_strpool_release(sshitem->params);
3172
3173 zbx_hashset_remove_direct(&config->sshitems, sshitem);
3174 }
3175
3176 /* TELNET items */
3177
3178 if (ITEM_TYPE_TELNET == item->type)
3179 {
3180 telnetitem = (ZBX_DC_TELNETITEM *)zbx_hashset_search(&config->telnetitems, &itemid);
3181
3182 zbx_strpool_release(telnetitem->username);
3183 zbx_strpool_release(telnetitem->password);
3184 zbx_strpool_release(telnetitem->params);
3185
3186 zbx_hashset_remove_direct(&config->telnetitems, telnetitem);
3187 }
3188
3189 /* simple items */
3190
3191 if (ITEM_TYPE_SIMPLE == item->type)
3192 {
3193 simpleitem = (ZBX_DC_SIMPLEITEM *)zbx_hashset_search(&config->simpleitems, &itemid);
3194
3195 zbx_strpool_release(simpleitem->username);
3196 zbx_strpool_release(simpleitem->password);
3197
3198 zbx_hashset_remove_direct(&config->simpleitems, simpleitem);
3199 }
3200
3201 /* JMX items */
3202
3203 if (ITEM_TYPE_JMX == item->type)
3204 {
3205 jmxitem = (ZBX_DC_JMXITEM *)zbx_hashset_search(&config->jmxitems, &itemid);
3206
3207 zbx_strpool_release(jmxitem->username);
3208 zbx_strpool_release(jmxitem->password);
3209 zbx_strpool_release(jmxitem->jmx_endpoint);
3210
3211 zbx_hashset_remove_direct(&config->jmxitems, jmxitem);
3212 }
3213
3214 /* calculated items */
3215
3216 if (ITEM_TYPE_CALCULATED == item->type)
3217 {
3218 calcitem = (ZBX_DC_CALCITEM *)zbx_hashset_search(&config->calcitems, &itemid);
3219 zbx_strpool_release(calcitem->params);
3220 zbx_hashset_remove_direct(&config->calcitems, calcitem);
3221 }
3222
3223 /* HTTP agent items */
3224
3225 if (ITEM_TYPE_HTTPAGENT == item->type)
3226 {
3227 httpitem = (ZBX_DC_HTTPITEM *)zbx_hashset_search(&config->httpitems, &itemid);
3228
3229 zbx_strpool_release(httpitem->timeout);
3230 zbx_strpool_release(httpitem->url);
3231 zbx_strpool_release(httpitem->query_fields);
3232 zbx_strpool_release(httpitem->posts);
3233 zbx_strpool_release(httpitem->status_codes);
3234 zbx_strpool_release(httpitem->http_proxy);
3235 zbx_strpool_release(httpitem->headers);
3236 zbx_strpool_release(httpitem->ssl_cert_file);
3237 zbx_strpool_release(httpitem->ssl_key_file);
3238 zbx_strpool_release(httpitem->ssl_key_password);
3239 zbx_strpool_release(httpitem->username);
3240 zbx_strpool_release(httpitem->password);
3241 zbx_strpool_release(httpitem->trapper_hosts);
3242
3243 zbx_hashset_remove_direct(&config->httpitems, httpitem);
3244 }
3245
3246 /* items */
3247
3248 item_hk_local.hostid = item->hostid;
3249 item_hk_local.key = item->key;
3250
3251 if (NULL == (item_hk = (ZBX_DC_ITEM_HK *)zbx_hashset_search(&config->items_hk, &item_hk_local)))
3252 {
3253 /* item keys should be unique for items within a host, otherwise items with */
3254 /* same key share index and removal of last added item already cleared index */
3255 THIS_SHOULD_NEVER_HAPPEN;
3256 }
3257 else if (item == item_hk->item_ptr)
3258 {
3259 zbx_strpool_release(item_hk->key);
3260 zbx_hashset_remove_direct(&config->items_hk, item_hk);
3261 }
3262
3263 if (ZBX_LOC_QUEUE == item->location)
3264 zbx_binary_heap_remove_direct(&config->queues[item->poller_type], item->itemid);
3265
3266 zbx_strpool_release(item->key);
3267 zbx_strpool_release(item->error);
3268 zbx_strpool_release(item->delay);
3269
3270 if (NULL != item->triggers)
3271 config->items.mem_free_func(item->triggers);
3272
3273 if (NULL != (preprocitem = (ZBX_DC_PREPROCITEM *)zbx_hashset_search(&config->preprocitems, &item->itemid)))
3274 {
3275 zbx_vector_ptr_destroy(&preprocitem->preproc_ops);
3276 zbx_hashset_remove_direct(&config->preprocitems, preprocitem);
3277 }
3278
3279 zbx_hashset_remove_direct(&config->items, item);
3280 }
3281
3282 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3283 }
3284
DCsync_template_items(zbx_dbsync_t * sync)3285 static void DCsync_template_items(zbx_dbsync_t *sync)
3286 {
3287 char **row;
3288 zbx_uint64_t rowid, itemid;
3289 unsigned char tag;
3290 int ret, found;
3291 ZBX_DC_TEMPLATE_ITEM *item;
3292
3293 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3294
3295 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
3296 {
3297 /* removed rows will be always added at the end */
3298 if (ZBX_DBSYNC_ROW_REMOVE == tag)
3299 break;
3300
3301 ZBX_STR2UINT64(itemid, row[0]);
3302 item = (ZBX_DC_TEMPLATE_ITEM *)DCfind_id(&config->template_items, itemid, sizeof(ZBX_DC_TEMPLATE_ITEM),
3303 &found);
3304
3305 ZBX_STR2UINT64(item->hostid, row[1]);
3306 ZBX_DBROW2UINT64(item->templateid, row[2]);
3307 }
3308
3309 /* remove deleted template items from buffer */
3310 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
3311 {
3312 if (NULL == (item = (ZBX_DC_TEMPLATE_ITEM *)zbx_hashset_search(&config->template_items, &rowid)))
3313 continue;
3314
3315 zbx_hashset_remove_direct(&config->template_items, item);
3316 }
3317
3318 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3319 }
3320
DCsync_prototype_items(zbx_dbsync_t * sync)3321 static void DCsync_prototype_items(zbx_dbsync_t *sync)
3322 {
3323 char **row;
3324 zbx_uint64_t rowid, itemid;
3325 unsigned char tag;
3326 int ret, found;
3327 ZBX_DC_PROTOTYPE_ITEM *item;
3328
3329 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3330
3331 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
3332 {
3333 /* removed rows will be always added at the end */
3334 if (ZBX_DBSYNC_ROW_REMOVE == tag)
3335 break;
3336
3337 ZBX_STR2UINT64(itemid, row[0]);
3338 item = (ZBX_DC_PROTOTYPE_ITEM *)DCfind_id(&config->prototype_items, itemid,
3339 sizeof(ZBX_DC_PROTOTYPE_ITEM), &found);
3340
3341 ZBX_STR2UINT64(item->hostid, row[1]);
3342 ZBX_DBROW2UINT64(item->templateid, row[2]);
3343 }
3344
3345 /* remove deleted prototype items from buffer */
3346 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
3347 {
3348 if (NULL == (item = (ZBX_DC_PROTOTYPE_ITEM *)zbx_hashset_search(&config->prototype_items, &rowid)))
3349 continue;
3350
3351 zbx_hashset_remove_direct(&config->prototype_items, item);
3352 }
3353
3354 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3355 }
3356
DCsync_triggers(zbx_dbsync_t * sync)3357 static void DCsync_triggers(zbx_dbsync_t *sync)
3358 {
3359 char **row;
3360 zbx_uint64_t rowid;
3361 unsigned char tag;
3362
3363 ZBX_DC_TRIGGER *trigger;
3364
3365 int found, ret;
3366 zbx_uint64_t triggerid;
3367
3368 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3369
3370 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
3371 {
3372 /* removed rows will be always added at the end */
3373 if (ZBX_DBSYNC_ROW_REMOVE == tag)
3374 break;
3375
3376 ZBX_STR2UINT64(triggerid, row[0]);
3377
3378 trigger = (ZBX_DC_TRIGGER *)DCfind_id(&config->triggers, triggerid, sizeof(ZBX_DC_TRIGGER), &found);
3379
3380 /* store new information in trigger structure */
3381
3382 DCstrpool_replace(found, &trigger->description, row[1]);
3383 DCstrpool_replace(found, &trigger->expression, row[2]);
3384 DCstrpool_replace(found, &trigger->recovery_expression, row[11]);
3385 DCstrpool_replace(found, &trigger->correlation_tag, row[13]);
3386 DCstrpool_replace(found, &trigger->opdata, row[14]);
3387 ZBX_STR2UCHAR(trigger->priority, row[4]);
3388 ZBX_STR2UCHAR(trigger->type, row[5]);
3389 ZBX_STR2UCHAR(trigger->status, row[9]);
3390 ZBX_STR2UCHAR(trigger->recovery_mode, row[10]);
3391 ZBX_STR2UCHAR(trigger->correlation_mode, row[12]);
3392
3393 if (0 == found)
3394 {
3395 DCstrpool_replace(found, &trigger->error, row[3]);
3396 ZBX_STR2UCHAR(trigger->value, row[6]);
3397 ZBX_STR2UCHAR(trigger->state, row[7]);
3398 trigger->lastchange = atoi(row[8]);
3399 trigger->locked = 0;
3400
3401 zbx_vector_ptr_create_ext(&trigger->tags, __config_mem_malloc_func, __config_mem_realloc_func,
3402 __config_mem_free_func);
3403 trigger->topoindex = 1;
3404 }
3405 }
3406
3407 /* remove deleted triggers from buffer */
3408 if (SUCCEED == ret)
3409 {
3410 zbx_vector_uint64_t functionids;
3411 int i;
3412 ZBX_DC_ITEM *item;
3413 ZBX_DC_FUNCTION *function;
3414
3415 zbx_vector_uint64_create(&functionids);
3416
3417 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
3418 {
3419 if (NULL == (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &rowid)))
3420 continue;
3421
3422 /* force trigger list update for items used in removed trigger */
3423
3424 get_functionids(&functionids, trigger->expression);
3425
3426 if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == trigger->recovery_mode)
3427 get_functionids(&functionids, trigger->recovery_expression);
3428
3429 for (i = 0; i < functionids.values_num; i++)
3430 {
3431 if (NULL == (function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &functionids.values[i])))
3432 continue;
3433
3434 if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &function->itemid)))
3435 continue;
3436
3437 item->update_triggers = 1;
3438 if (NULL != item->triggers)
3439 {
3440 config->items.mem_free_func(item->triggers);
3441 item->triggers = NULL;
3442 }
3443 }
3444 zbx_vector_uint64_clear(&functionids);
3445
3446 zbx_strpool_release(trigger->description);
3447 zbx_strpool_release(trigger->expression);
3448 zbx_strpool_release(trigger->recovery_expression);
3449 zbx_strpool_release(trigger->error);
3450 zbx_strpool_release(trigger->correlation_tag);
3451 zbx_strpool_release(trigger->opdata);
3452
3453 zbx_vector_ptr_destroy(&trigger->tags);
3454
3455 zbx_hashset_remove_direct(&config->triggers, trigger);
3456 }
3457 zbx_vector_uint64_destroy(&functionids);
3458 }
3459
3460 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3461 }
3462
3463 static void DCconfig_sort_triggers_topologically(void);
3464
3465 /******************************************************************************
3466 * *
3467 * Function: dc_trigger_deplist_release *
3468 * *
3469 * Purpose: releases trigger dependency list, removing it if necessary *
3470 * *
3471 ******************************************************************************/
dc_trigger_deplist_release(ZBX_DC_TRIGGER_DEPLIST * trigdep)3472 static int dc_trigger_deplist_release(ZBX_DC_TRIGGER_DEPLIST *trigdep)
3473 {
3474 if (0 == --trigdep->refcount)
3475 {
3476 zbx_vector_ptr_destroy(&trigdep->dependencies);
3477 zbx_hashset_remove_direct(&config->trigdeps, trigdep);
3478 return SUCCEED;
3479 }
3480
3481 return FAIL;
3482 }
3483
3484 /******************************************************************************
3485 * *
3486 * Function: dc_trigger_deplist_init *
3487 * *
3488 * Purpose: initializes trigger dependency list *
3489 * *
3490 ******************************************************************************/
dc_trigger_deplist_init(ZBX_DC_TRIGGER_DEPLIST * trigdep,ZBX_DC_TRIGGER * trigger)3491 static void dc_trigger_deplist_init(ZBX_DC_TRIGGER_DEPLIST *trigdep, ZBX_DC_TRIGGER *trigger)
3492 {
3493 trigdep->refcount = 1;
3494 trigdep->trigger = trigger;
3495 zbx_vector_ptr_create_ext(&trigdep->dependencies, __config_mem_malloc_func, __config_mem_realloc_func,
3496 __config_mem_free_func);
3497 }
3498
3499 /******************************************************************************
3500 * *
3501 * Function: dc_trigger_deplist_reset *
3502 * *
3503 * Purpose: resets trigger dependency list to release memory allocated by *
3504 * dependencies vector *
3505 * *
3506 ******************************************************************************/
dc_trigger_deplist_reset(ZBX_DC_TRIGGER_DEPLIST * trigdep)3507 static void dc_trigger_deplist_reset(ZBX_DC_TRIGGER_DEPLIST *trigdep)
3508 {
3509 zbx_vector_ptr_destroy(&trigdep->dependencies);
3510 zbx_vector_ptr_create_ext(&trigdep->dependencies, __config_mem_malloc_func, __config_mem_realloc_func,
3511 __config_mem_free_func);
3512 }
3513
DCsync_trigdeps(zbx_dbsync_t * sync)3514 static void DCsync_trigdeps(zbx_dbsync_t *sync)
3515 {
3516 char **row;
3517 zbx_uint64_t rowid;
3518 unsigned char tag;
3519
3520 ZBX_DC_TRIGGER_DEPLIST *trigdep_down, *trigdep_up;
3521
3522 int found, index, ret;
3523 zbx_uint64_t triggerid_down, triggerid_up;
3524 ZBX_DC_TRIGGER *trigger_up, *trigger_down;
3525
3526 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3527
3528 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
3529 {
3530 /* removed rows will be always added at the end */
3531 if (ZBX_DBSYNC_ROW_REMOVE == tag)
3532 break;
3533
3534 /* find trigdep_down pointer */
3535
3536 ZBX_STR2UINT64(triggerid_down, row[0]);
3537 if (NULL == (trigger_down = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &triggerid_down)))
3538 continue;
3539
3540 ZBX_STR2UINT64(triggerid_up, row[1]);
3541 if (NULL == (trigger_up = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &triggerid_up)))
3542 continue;
3543
3544 trigdep_down = (ZBX_DC_TRIGGER_DEPLIST *)DCfind_id(&config->trigdeps, triggerid_down, sizeof(ZBX_DC_TRIGGER_DEPLIST), &found);
3545 if (0 == found)
3546 dc_trigger_deplist_init(trigdep_down, trigger_down);
3547 else
3548 trigdep_down->refcount++;
3549
3550 trigdep_up = (ZBX_DC_TRIGGER_DEPLIST *)DCfind_id(&config->trigdeps, triggerid_up, sizeof(ZBX_DC_TRIGGER_DEPLIST), &found);
3551 if (0 == found)
3552 dc_trigger_deplist_init(trigdep_up, trigger_up);
3553 else
3554 trigdep_up->refcount++;
3555
3556 zbx_vector_ptr_append(&trigdep_down->dependencies, trigdep_up);
3557 }
3558
3559 /* remove deleted trigger dependencies from buffer */
3560 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
3561 {
3562 ZBX_STR2UINT64(triggerid_down, row[0]);
3563 if (NULL == (trigdep_down = (ZBX_DC_TRIGGER_DEPLIST *)zbx_hashset_search(&config->trigdeps,
3564 &triggerid_down)))
3565 {
3566 continue;
3567 }
3568
3569 ZBX_STR2UINT64(triggerid_up, row[1]);
3570 if (NULL != (trigdep_up = (ZBX_DC_TRIGGER_DEPLIST *)zbx_hashset_search(&config->trigdeps,
3571 &triggerid_up)))
3572 {
3573 dc_trigger_deplist_release(trigdep_up);
3574 }
3575
3576 if (SUCCEED != dc_trigger_deplist_release(trigdep_down))
3577 {
3578 if (FAIL == (index = zbx_vector_ptr_search(&trigdep_down->dependencies, &triggerid_up,
3579 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
3580 {
3581 continue;
3582 }
3583
3584 if (1 == trigdep_down->dependencies.values_num)
3585 dc_trigger_deplist_reset(trigdep_down);
3586 else
3587 zbx_vector_ptr_remove_noorder(&trigdep_down->dependencies, index);
3588 }
3589 }
3590
3591 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3592 }
3593
DCsync_functions(zbx_dbsync_t * sync)3594 static void DCsync_functions(zbx_dbsync_t *sync)
3595 {
3596 char **row;
3597 zbx_uint64_t rowid;
3598 unsigned char tag;
3599
3600 ZBX_DC_ITEM *item;
3601 ZBX_DC_FUNCTION *function;
3602
3603 int found, ret;
3604 zbx_uint64_t itemid, functionid, triggerid;
3605
3606 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3607
3608 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
3609 {
3610 /* removed rows will be always added at the end */
3611 if (ZBX_DBSYNC_ROW_REMOVE == tag)
3612 break;
3613
3614 ZBX_STR2UINT64(itemid, row[0]);
3615 ZBX_STR2UINT64(functionid, row[1]);
3616 ZBX_STR2UINT64(triggerid, row[4]);
3617
3618 if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemid)))
3619 {
3620 /* Item could have been created after we have selected them in the */
3621 /* previous queries. However, we shall avoid the check for functions being the */
3622 /* same as in the trigger expression, because that is somewhat expensive, not */
3623 /* 100% (think functions keeping their functionid, but changing their function */
3624 /* or parameters), and even if there is an inconsistency, we can live with it. */
3625
3626 continue;
3627 }
3628
3629 /* process function information */
3630
3631 function = (ZBX_DC_FUNCTION *)DCfind_id(&config->functions, functionid, sizeof(ZBX_DC_FUNCTION), &found);
3632
3633 if (1 == found && function->itemid != itemid)
3634 {
3635 ZBX_DC_ITEM *item_last;
3636
3637 if (NULL != (item_last = zbx_hashset_search(&config->items, &function->itemid)))
3638 {
3639 item_last->update_triggers = 1;
3640 if (NULL != item_last->triggers)
3641 {
3642 config->items.mem_free_func(item_last->triggers);
3643 item_last->triggers = NULL;
3644 }
3645 }
3646 }
3647
3648 function->triggerid = triggerid;
3649 function->itemid = itemid;
3650 DCstrpool_replace(found, &function->function, row[2]);
3651 DCstrpool_replace(found, &function->parameter, row[3]);
3652
3653 function->timer = (SUCCEED == is_time_function(function->function) ? 1 : 0);
3654
3655 item->update_triggers = 1;
3656 if (NULL != item->triggers)
3657 item->triggers[0] = NULL;
3658 }
3659
3660 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
3661 {
3662 if (NULL == (function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &rowid)))
3663 continue;
3664
3665 if (NULL != (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &function->itemid)))
3666 {
3667 item->update_triggers = 1;
3668 if (NULL != item->triggers)
3669 {
3670 config->items.mem_free_func(item->triggers);
3671 item->triggers = NULL;
3672 }
3673 }
3674
3675 zbx_strpool_release(function->function);
3676 zbx_strpool_release(function->parameter);
3677
3678 zbx_hashset_remove_direct(&config->functions, function);
3679 }
3680
3681 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3682 }
3683
3684 /******************************************************************************
3685 * *
3686 * Function: dc_regexp_remove_expression *
3687 * *
3688 * Purpose: removes expression from regexp *
3689 * *
3690 ******************************************************************************/
dc_regexp_remove_expression(const char * regexp_name,zbx_uint64_t expressionid)3691 static ZBX_DC_REGEXP *dc_regexp_remove_expression(const char *regexp_name, zbx_uint64_t expressionid)
3692 {
3693 ZBX_DC_REGEXP *regexp, regexp_local;
3694 int index;
3695
3696 regexp_local.name = regexp_name;
3697
3698 if (NULL == (regexp = (ZBX_DC_REGEXP *)zbx_hashset_search(&config->regexps, ®exp_local)))
3699 return NULL;
3700
3701 if (FAIL == (index = zbx_vector_uint64_search(®exp->expressionids, expressionid,
3702 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
3703 {
3704 return NULL;
3705 }
3706
3707 zbx_vector_uint64_remove_noorder(®exp->expressionids, index);
3708
3709 return regexp;
3710 }
3711
3712 /******************************************************************************
3713 * *
3714 * Function: DCsync_expressions *
3715 * *
3716 * Purpose: Updates expressions configuration cache *
3717 * *
3718 * Parameters: result - [IN] the result of expressions database select *
3719 * *
3720 ******************************************************************************/
DCsync_expressions(zbx_dbsync_t * sync)3721 static void DCsync_expressions(zbx_dbsync_t *sync)
3722 {
3723 char **row;
3724 zbx_uint64_t rowid;
3725 unsigned char tag;
3726 zbx_hashset_iter_t iter;
3727 ZBX_DC_EXPRESSION *expression;
3728 ZBX_DC_REGEXP *regexp, regexp_local;
3729 zbx_uint64_t expressionid;
3730 int found, ret;
3731
3732 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3733
3734 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
3735 {
3736 /* removed rows will be always added at the end */
3737 if (ZBX_DBSYNC_ROW_REMOVE == tag)
3738 break;
3739
3740 ZBX_STR2UINT64(expressionid, row[1]);
3741 expression = (ZBX_DC_EXPRESSION *)DCfind_id(&config->expressions, expressionid, sizeof(ZBX_DC_EXPRESSION), &found);
3742
3743 if (0 != found)
3744 dc_regexp_remove_expression(expression->regexp, expressionid);
3745
3746 DCstrpool_replace(found, &expression->regexp, row[0]);
3747 DCstrpool_replace(found, &expression->expression, row[2]);
3748 ZBX_STR2UCHAR(expression->type, row[3]);
3749 ZBX_STR2UCHAR(expression->case_sensitive, row[5]);
3750 expression->delimiter = *row[4];
3751
3752 regexp_local.name = row[0];
3753
3754 if (NULL == (regexp = (ZBX_DC_REGEXP *)zbx_hashset_search(&config->regexps, ®exp_local)))
3755 {
3756 DCstrpool_replace(0, ®exp_local.name, row[0]);
3757 zbx_vector_uint64_create_ext(®exp_local.expressionids,
3758 __config_mem_malloc_func,
3759 __config_mem_realloc_func,
3760 __config_mem_free_func);
3761
3762 regexp = (ZBX_DC_REGEXP *)zbx_hashset_insert(&config->regexps, ®exp_local, sizeof(ZBX_DC_REGEXP));
3763 }
3764
3765 zbx_vector_uint64_append(®exp->expressionids, expressionid);
3766 }
3767
3768 /* remove regexps with no expressions related to it */
3769 zbx_hashset_iter_reset(&config->regexps, &iter);
3770
3771 while (NULL != (regexp = (ZBX_DC_REGEXP *)zbx_hashset_iter_next(&iter)))
3772 {
3773 if (0 < regexp->expressionids.values_num)
3774 continue;
3775
3776 zbx_strpool_release(regexp->name);
3777 zbx_vector_uint64_destroy(®exp->expressionids);
3778 zbx_hashset_iter_remove(&iter);
3779 }
3780
3781 /* remove unused expressions */
3782 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
3783 {
3784 if (NULL == (expression = (ZBX_DC_EXPRESSION *)zbx_hashset_search(&config->expressions, &rowid)))
3785 continue;
3786
3787 if (NULL != (regexp = dc_regexp_remove_expression(expression->regexp, expression->expressionid)))
3788 {
3789 if (0 == regexp->expressionids.values_num)
3790 {
3791 zbx_strpool_release(regexp->name);
3792 zbx_vector_uint64_destroy(®exp->expressionids);
3793 zbx_hashset_remove_direct(&config->regexps, regexp);
3794 }
3795 }
3796
3797 zbx_strpool_release(expression->expression);
3798 zbx_strpool_release(expression->regexp);
3799 zbx_hashset_remove_direct(&config->expressions, expression);
3800 }
3801
3802 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3803 }
3804
3805 /******************************************************************************
3806 * *
3807 * Function: DCsync_actions *
3808 * *
3809 * Purpose: Updates actions configuration cache *
3810 * *
3811 * Parameters: sync - [IN] the db synchronization data *
3812 * *
3813 * Comments: The result contains the following fields: *
3814 * 0 - actionid *
3815 * 1 - eventsource *
3816 * 2 - evaltype *
3817 * 3 - formula *
3818 * *
3819 ******************************************************************************/
DCsync_actions(zbx_dbsync_t * sync)3820 static void DCsync_actions(zbx_dbsync_t *sync)
3821 {
3822 char **row;
3823 zbx_uint64_t rowid;
3824 unsigned char tag;
3825 zbx_uint64_t actionid;
3826 zbx_dc_action_t *action;
3827 int found, ret;
3828
3829 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3830
3831 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
3832 {
3833 /* removed rows will be always added at the end */
3834 if (ZBX_DBSYNC_ROW_REMOVE == tag)
3835 break;
3836
3837 ZBX_STR2UINT64(actionid, row[0]);
3838 action = (zbx_dc_action_t *)DCfind_id(&config->actions, actionid, sizeof(zbx_dc_action_t), &found);
3839
3840 ZBX_STR2UCHAR(action->eventsource, row[1]);
3841 ZBX_STR2UCHAR(action->evaltype, row[2]);
3842
3843 DCstrpool_replace(found, &action->formula, row[3]);
3844
3845 if (0 == found)
3846 {
3847 if (EVENT_SOURCE_INTERNAL == action->eventsource)
3848 config->internal_actions++;
3849
3850 zbx_vector_ptr_create_ext(&action->conditions, __config_mem_malloc_func,
3851 __config_mem_realloc_func, __config_mem_free_func);
3852
3853 zbx_vector_ptr_reserve(&action->conditions, 1);
3854
3855 action->opflags = ZBX_ACTION_OPCLASS_NONE;
3856 }
3857 }
3858
3859 /* remove deleted actions */
3860 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
3861 {
3862 if (NULL == (action = (zbx_dc_action_t *)zbx_hashset_search(&config->actions, &rowid)))
3863 continue;
3864
3865 if (EVENT_SOURCE_INTERNAL == action->eventsource)
3866 config->internal_actions--;
3867
3868 zbx_strpool_release(action->formula);
3869 zbx_vector_ptr_destroy(&action->conditions);
3870
3871 zbx_hashset_remove_direct(&config->actions, action);
3872 }
3873
3874 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3875 }
3876
3877 /******************************************************************************
3878 * *
3879 * Function: DCsync_action_ops *
3880 * *
3881 * Purpose: Updates action operation class flags in configuration cache *
3882 * *
3883 * Parameters: sync - [IN] the db synchronization data *
3884 * *
3885 * Comments: The result contains the following fields: *
3886 * 0 - actionid *
3887 * 1 - action operation class flags *
3888 * *
3889 ******************************************************************************/
DCsync_action_ops(zbx_dbsync_t * sync)3890 static void DCsync_action_ops(zbx_dbsync_t *sync)
3891 {
3892 char **row;
3893 zbx_uint64_t rowid;
3894 unsigned char tag;
3895 zbx_uint64_t actionid;
3896 zbx_dc_action_t *action;
3897
3898 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3899
3900 while (SUCCEED == zbx_dbsync_next(sync, &rowid, &row, &tag))
3901 {
3902 ZBX_STR2UINT64(actionid, row[0]);
3903
3904 if (NULL == (action = (zbx_dc_action_t *)zbx_hashset_search(&config->actions, &actionid)))
3905 continue;
3906
3907 action->opflags = atoi(row[1]);
3908 }
3909
3910 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3911 }
3912
3913 /******************************************************************************
3914 * *
3915 * Function: dc_compare_action_conditions_by_type *
3916 * *
3917 * Purpose: compare two action conditions by their type *
3918 * *
3919 * Comments: This function is used to sort action conditions by type. *
3920 * *
3921 ******************************************************************************/
dc_compare_action_conditions_by_type(const void * d1,const void * d2)3922 static int dc_compare_action_conditions_by_type(const void *d1, const void *d2)
3923 {
3924 zbx_dc_action_condition_t *c1 = *(zbx_dc_action_condition_t **)d1;
3925 zbx_dc_action_condition_t *c2 = *(zbx_dc_action_condition_t **)d2;
3926
3927 ZBX_RETURN_IF_NOT_EQUAL(c1->conditiontype, c2->conditiontype);
3928
3929 return 0;
3930 }
3931
3932 /******************************************************************************
3933 * *
3934 * Function: DCsync_action_conditions *
3935 * *
3936 * Purpose: Updates action conditions configuration cache *
3937 * *
3938 * Parameters: sync - [IN] the db synchronization data *
3939 * *
3940 * Comments: The result contains the following fields: *
3941 * 0 - conditionid *
3942 * 1 - actionid *
3943 * 2 - conditiontype *
3944 * 3 - operator *
3945 * 4 - value *
3946 * *
3947 ******************************************************************************/
DCsync_action_conditions(zbx_dbsync_t * sync)3948 static void DCsync_action_conditions(zbx_dbsync_t *sync)
3949 {
3950 char **row;
3951 zbx_uint64_t rowid;
3952 unsigned char tag;
3953 zbx_uint64_t actionid, conditionid;
3954 zbx_dc_action_t *action;
3955 zbx_dc_action_condition_t *condition;
3956 int found, i, index, ret;
3957 zbx_vector_ptr_t actions;
3958
3959 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3960
3961 zbx_vector_ptr_create(&actions);
3962
3963 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
3964 {
3965 /* removed rows will be always added at the end */
3966 if (ZBX_DBSYNC_ROW_REMOVE == tag)
3967 break;
3968
3969 ZBX_STR2UINT64(actionid, row[1]);
3970
3971 if (NULL == (action = (zbx_dc_action_t *)zbx_hashset_search(&config->actions, &actionid)))
3972 continue;
3973
3974 ZBX_STR2UINT64(conditionid, row[0]);
3975
3976 condition = (zbx_dc_action_condition_t *)DCfind_id(&config->action_conditions, conditionid, sizeof(zbx_dc_action_condition_t),
3977 &found);
3978
3979 ZBX_STR2UCHAR(condition->conditiontype, row[2]);
3980 ZBX_STR2UCHAR(condition->op, row[3]);
3981
3982 DCstrpool_replace(found, &condition->value, row[4]);
3983 DCstrpool_replace(found, &condition->value2, row[5]);
3984
3985 if (0 == found)
3986 {
3987 condition->actionid = actionid;
3988 zbx_vector_ptr_append(&action->conditions, condition);
3989 }
3990
3991 if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype)
3992 zbx_vector_ptr_append(&actions, action);
3993 }
3994
3995 /* remove deleted conditions */
3996 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
3997 {
3998 if (NULL == (condition = (zbx_dc_action_condition_t *)zbx_hashset_search(&config->action_conditions, &rowid)))
3999 continue;
4000
4001 if (NULL != (action = (zbx_dc_action_t *)zbx_hashset_search(&config->actions, &condition->actionid)))
4002 {
4003 if (FAIL != (index = zbx_vector_ptr_search(&action->conditions, condition,
4004 ZBX_DEFAULT_PTR_COMPARE_FUNC)))
4005 {
4006 zbx_vector_ptr_remove_noorder(&action->conditions, index);
4007
4008 if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype)
4009 zbx_vector_ptr_append(&actions, action);
4010 }
4011 }
4012
4013 zbx_strpool_release(condition->value);
4014 zbx_strpool_release(condition->value2);
4015
4016 zbx_hashset_remove_direct(&config->action_conditions, condition);
4017 }
4018
4019 /* sort conditions by type */
4020
4021 zbx_vector_ptr_sort(&actions, ZBX_DEFAULT_PTR_COMPARE_FUNC);
4022 zbx_vector_ptr_uniq(&actions, ZBX_DEFAULT_PTR_COMPARE_FUNC);
4023
4024 for (i = 0; i < actions.values_num; i++)
4025 {
4026 action = (zbx_dc_action_t *)actions.values[i];
4027
4028 if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype)
4029 zbx_vector_ptr_sort(&action->conditions, dc_compare_action_conditions_by_type);
4030 }
4031
4032 zbx_vector_ptr_destroy(&actions);
4033
4034 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4035 }
4036
4037 /******************************************************************************
4038 * *
4039 * Function: DCsync_correlations *
4040 * *
4041 * Purpose: Updates correlations configuration cache *
4042 * *
4043 * Parameters: sync - [IN] the db synchronization data *
4044 * *
4045 * Comments: The result contains the following fields: *
4046 * 0 - correlationid *
4047 * 1 - name *
4048 * 2 - evaltype *
4049 * 3 - formula *
4050 * *
4051 ******************************************************************************/
DCsync_correlations(zbx_dbsync_t * sync)4052 static void DCsync_correlations(zbx_dbsync_t *sync)
4053 {
4054 char **row;
4055 zbx_uint64_t rowid;
4056 unsigned char tag;
4057 zbx_uint64_t correlationid;
4058 zbx_dc_correlation_t *correlation;
4059 int found, ret;
4060
4061 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4062
4063 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
4064 {
4065 /* removed rows will be always added at the end */
4066 if (ZBX_DBSYNC_ROW_REMOVE == tag)
4067 break;
4068
4069 ZBX_STR2UINT64(correlationid, row[0]);
4070
4071 correlation = (zbx_dc_correlation_t *)DCfind_id(&config->correlations, correlationid, sizeof(zbx_dc_correlation_t), &found);
4072
4073 if (0 == found)
4074 {
4075 zbx_vector_ptr_create_ext(&correlation->conditions, __config_mem_malloc_func,
4076 __config_mem_realloc_func, __config_mem_free_func);
4077
4078 zbx_vector_ptr_create_ext(&correlation->operations, __config_mem_malloc_func,
4079 __config_mem_realloc_func, __config_mem_free_func);
4080 }
4081
4082 DCstrpool_replace(found, &correlation->name, row[1]);
4083 DCstrpool_replace(found, &correlation->formula, row[3]);
4084
4085 ZBX_STR2UCHAR(correlation->evaltype, row[2]);
4086 }
4087
4088 /* remove deleted correlations */
4089
4090 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
4091 {
4092 if (NULL == (correlation = (zbx_dc_correlation_t *)zbx_hashset_search(&config->correlations, &rowid)))
4093 continue;
4094
4095 zbx_strpool_release(correlation->name);
4096 zbx_strpool_release(correlation->formula);
4097
4098 zbx_vector_ptr_destroy(&correlation->conditions);
4099 zbx_vector_ptr_destroy(&correlation->operations);
4100
4101 zbx_hashset_remove_direct(&config->correlations, correlation);
4102 }
4103
4104 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4105 }
4106
4107 /******************************************************************************
4108 * *
4109 * Function: dc_corr_condition_get_size *
4110 * *
4111 * Purpose: get the actual size of correlation condition data depending on *
4112 * its type *
4113 * *
4114 * Parameters: type - [IN] the condition type *
4115 * *
4116 * Return value: the size *
4117 * *
4118 ******************************************************************************/
dc_corr_condition_get_size(unsigned char type)4119 static size_t dc_corr_condition_get_size(unsigned char type)
4120 {
4121 switch (type)
4122 {
4123 case ZBX_CORR_CONDITION_OLD_EVENT_TAG:
4124 /* break; is not missing here */
4125 case ZBX_CORR_CONDITION_NEW_EVENT_TAG:
4126 return offsetof(zbx_dc_corr_condition_t, data) + sizeof(zbx_dc_corr_condition_tag_t);
4127 case ZBX_CORR_CONDITION_NEW_EVENT_HOSTGROUP:
4128 return offsetof(zbx_dc_corr_condition_t, data) + sizeof(zbx_dc_corr_condition_group_t);
4129 case ZBX_CORR_CONDITION_EVENT_TAG_PAIR:
4130 return offsetof(zbx_dc_corr_condition_t, data) + sizeof(zbx_dc_corr_condition_tag_pair_t);
4131 case ZBX_CORR_CONDITION_OLD_EVENT_TAG_VALUE:
4132 /* break; is not missing here */
4133 case ZBX_CORR_CONDITION_NEW_EVENT_TAG_VALUE:
4134 return offsetof(zbx_dc_corr_condition_t, data) + sizeof(zbx_dc_corr_condition_tag_value_t);
4135 }
4136
4137 THIS_SHOULD_NEVER_HAPPEN;
4138 return 0;
4139 }
4140
4141 /******************************************************************************
4142 * *
4143 * Function: dc_corr_condition_init_data *
4144 * *
4145 * Purpose: initializes correlation condition data from database row *
4146 * *
4147 * Parameters: condition - [IN] the condition to initialize *
4148 * found - [IN] 0 - new condition, 1 - cached condition *
4149 * row - [IN] the database row containing condition data *
4150 * *
4151 ******************************************************************************/
dc_corr_condition_init_data(zbx_dc_corr_condition_t * condition,int found,DB_ROW row)4152 static void dc_corr_condition_init_data(zbx_dc_corr_condition_t *condition, int found, DB_ROW row)
4153 {
4154 if (ZBX_CORR_CONDITION_OLD_EVENT_TAG == condition->type || ZBX_CORR_CONDITION_NEW_EVENT_TAG == condition->type)
4155 {
4156 DCstrpool_replace(found, &condition->data.tag.tag, row[0]);
4157 return;
4158 }
4159
4160 row++;
4161
4162 if (ZBX_CORR_CONDITION_OLD_EVENT_TAG_VALUE == condition->type ||
4163 ZBX_CORR_CONDITION_NEW_EVENT_TAG_VALUE == condition->type)
4164 {
4165 DCstrpool_replace(found, &condition->data.tag_value.tag, row[0]);
4166 DCstrpool_replace(found, &condition->data.tag_value.value, row[1]);
4167 ZBX_STR2UCHAR(condition->data.tag_value.op, row[2]);
4168 return;
4169 }
4170
4171 row += 3;
4172
4173 if (ZBX_CORR_CONDITION_NEW_EVENT_HOSTGROUP == condition->type)
4174 {
4175 ZBX_STR2UINT64(condition->data.group.groupid, row[0]);
4176 ZBX_STR2UCHAR(condition->data.group.op, row[1]);
4177 return;
4178 }
4179
4180 row += 2;
4181
4182 if (ZBX_CORR_CONDITION_EVENT_TAG_PAIR == condition->type)
4183 {
4184 DCstrpool_replace(found, &condition->data.tag_pair.oldtag, row[0]);
4185 DCstrpool_replace(found, &condition->data.tag_pair.newtag, row[1]);
4186 return;
4187 }
4188 }
4189
4190 /******************************************************************************
4191 * *
4192 * Function: corr_condition_free_data *
4193 * *
4194 * Purpose: frees correlation condition data *
4195 * *
4196 * Parameters: condition - [IN] the condition *
4197 * *
4198 ******************************************************************************/
corr_condition_free_data(zbx_dc_corr_condition_t * condition)4199 static void corr_condition_free_data(zbx_dc_corr_condition_t *condition)
4200 {
4201 switch (condition->type)
4202 {
4203 case ZBX_CORR_CONDITION_OLD_EVENT_TAG:
4204 /* break; is not missing here */
4205 case ZBX_CORR_CONDITION_NEW_EVENT_TAG:
4206 zbx_strpool_release(condition->data.tag.tag);
4207 break;
4208 case ZBX_CORR_CONDITION_EVENT_TAG_PAIR:
4209 zbx_strpool_release(condition->data.tag_pair.oldtag);
4210 zbx_strpool_release(condition->data.tag_pair.newtag);
4211 break;
4212 case ZBX_CORR_CONDITION_OLD_EVENT_TAG_VALUE:
4213 /* break; is not missing here */
4214 case ZBX_CORR_CONDITION_NEW_EVENT_TAG_VALUE:
4215 zbx_strpool_release(condition->data.tag_value.tag);
4216 zbx_strpool_release(condition->data.tag_value.value);
4217 break;
4218 }
4219 }
4220
4221 /******************************************************************************
4222 * *
4223 * Function: dc_compare_corr_conditions_by_type *
4224 * *
4225 * Purpose: compare two correlation conditions by their type *
4226 * *
4227 * Comments: This function is used to sort correlation conditions by type. *
4228 * *
4229 ******************************************************************************/
dc_compare_corr_conditions_by_type(const void * d1,const void * d2)4230 static int dc_compare_corr_conditions_by_type(const void *d1, const void *d2)
4231 {
4232 zbx_dc_corr_condition_t *c1 = *(zbx_dc_corr_condition_t **)d1;
4233 zbx_dc_corr_condition_t *c2 = *(zbx_dc_corr_condition_t **)d2;
4234
4235 ZBX_RETURN_IF_NOT_EQUAL(c1->type, c2->type);
4236
4237 return 0;
4238 }
4239
4240 /******************************************************************************
4241 * *
4242 * Function: DCsync_corr_conditions *
4243 * *
4244 * Purpose: Updates correlation conditions configuration cache *
4245 * *
4246 * Parameters: sync - [IN] the db synchronization data *
4247 * *
4248 * Comments: The result contains the following fields: *
4249 * 0 - corr_conditionid *
4250 * 1 - correlationid *
4251 * 2 - type *
4252 * 3 - corr_condition_tag.tag *
4253 * 4 - corr_condition_tagvalue.tag *
4254 * 5 - corr_condition_tagvalue.value *
4255 * 6 - corr_condition_tagvalue.operator *
4256 * 7 - corr_condition_group.groupid *
4257 * 8 - corr_condition_group.operator *
4258 * 9 - corr_condition_tagpair.oldtag *
4259 * 10 - corr_condition_tagpair.newtag *
4260 * *
4261 ******************************************************************************/
DCsync_corr_conditions(zbx_dbsync_t * sync)4262 static void DCsync_corr_conditions(zbx_dbsync_t *sync)
4263 {
4264 char **row;
4265 zbx_uint64_t rowid;
4266 unsigned char tag;
4267 zbx_uint64_t conditionid, correlationid;
4268 zbx_dc_corr_condition_t *condition;
4269 zbx_dc_correlation_t *correlation;
4270 int found, ret, i, index;
4271 unsigned char type;
4272 size_t condition_size;
4273 zbx_vector_ptr_t correlations;
4274
4275 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4276
4277 zbx_vector_ptr_create(&correlations);
4278
4279 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
4280 {
4281 /* removed rows will be always added at the end */
4282 if (ZBX_DBSYNC_ROW_REMOVE == tag)
4283 break;
4284
4285 ZBX_STR2UINT64(correlationid, row[1]);
4286
4287 if (NULL == (correlation = (zbx_dc_correlation_t *)zbx_hashset_search(&config->correlations, &correlationid)))
4288 continue;
4289
4290 ZBX_STR2UINT64(conditionid, row[0]);
4291 ZBX_STR2UCHAR(type, row[2]);
4292
4293 condition_size = dc_corr_condition_get_size(type);
4294 condition = (zbx_dc_corr_condition_t *)DCfind_id(&config->corr_conditions, conditionid, condition_size, &found);
4295
4296 condition->correlationid = correlationid;
4297 condition->type = type;
4298 dc_corr_condition_init_data(condition, found, row + 3);
4299
4300 if (0 == found)
4301 zbx_vector_ptr_append(&correlation->conditions, condition);
4302
4303 /* sort the conditions later */
4304 if (CONDITION_EVAL_TYPE_AND_OR == correlation->evaltype)
4305 zbx_vector_ptr_append(&correlations, correlation);
4306 }
4307
4308 /* remove deleted correlation conditions */
4309
4310 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
4311 {
4312 if (NULL == (condition = (zbx_dc_corr_condition_t *)zbx_hashset_search(&config->corr_conditions, &rowid)))
4313 continue;
4314
4315 /* remove condition from correlation->conditions vector */
4316 if (NULL != (correlation = (zbx_dc_correlation_t *)zbx_hashset_search(&config->correlations, &condition->correlationid)))
4317 {
4318 if (FAIL != (index = zbx_vector_ptr_search(&correlation->conditions, condition,
4319 ZBX_DEFAULT_PTR_COMPARE_FUNC)))
4320 {
4321 /* sort the conditions later */
4322 if (CONDITION_EVAL_TYPE_AND_OR == correlation->evaltype)
4323 zbx_vector_ptr_append(&correlations, correlation);
4324
4325 zbx_vector_ptr_remove_noorder(&correlation->conditions, index);
4326 }
4327 }
4328
4329 corr_condition_free_data(condition);
4330 zbx_hashset_remove_direct(&config->corr_conditions, condition);
4331 }
4332
4333 /* sort conditions by type */
4334
4335 zbx_vector_ptr_sort(&correlations, ZBX_DEFAULT_PTR_COMPARE_FUNC);
4336 zbx_vector_ptr_uniq(&correlations, ZBX_DEFAULT_PTR_COMPARE_FUNC);
4337
4338 for (i = 0; i < correlations.values_num; i++)
4339 {
4340 correlation = (zbx_dc_correlation_t *)correlations.values[i];
4341 zbx_vector_ptr_sort(&correlation->conditions, dc_compare_corr_conditions_by_type);
4342 }
4343
4344 zbx_vector_ptr_destroy(&correlations);
4345
4346 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4347 }
4348
4349 /******************************************************************************
4350 * *
4351 * Function: DCsync_corr_operations *
4352 * *
4353 * Purpose: Updates correlation operations configuration cache *
4354 * *
4355 * Parameters: result - [IN] the result of correlation operations database *
4356 * select *
4357 * *
4358 * Comments: The result contains the following fields: *
4359 * 0 - corr_operationid *
4360 * 1 - correlationid *
4361 * 2 - type *
4362 * *
4363 ******************************************************************************/
DCsync_corr_operations(zbx_dbsync_t * sync)4364 static void DCsync_corr_operations(zbx_dbsync_t *sync)
4365 {
4366 char **row;
4367 zbx_uint64_t rowid;
4368 unsigned char tag;
4369 zbx_uint64_t operationid, correlationid;
4370 zbx_dc_corr_operation_t *operation;
4371 zbx_dc_correlation_t *correlation;
4372 int found, ret, index;
4373 unsigned char type;
4374
4375 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4376
4377 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
4378 {
4379 /* removed rows will be always added at the end */
4380 if (ZBX_DBSYNC_ROW_REMOVE == tag)
4381 break;
4382
4383 ZBX_STR2UINT64(correlationid, row[1]);
4384
4385 if (NULL == (correlation = (zbx_dc_correlation_t *)zbx_hashset_search(&config->correlations, &correlationid)))
4386 continue;
4387
4388 ZBX_STR2UINT64(operationid, row[0]);
4389 ZBX_STR2UCHAR(type, row[2]);
4390
4391 operation = (zbx_dc_corr_operation_t *)DCfind_id(&config->corr_operations, operationid, sizeof(zbx_dc_corr_operation_t), &found);
4392
4393 operation->type = type;
4394
4395 if (0 == found)
4396 {
4397 operation->correlationid = correlationid;
4398 zbx_vector_ptr_append(&correlation->operations, operation);
4399 }
4400 }
4401
4402 /* remove deleted correlation operations */
4403
4404 /* remove deleted actions */
4405 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
4406 {
4407 if (NULL == (operation = (zbx_dc_corr_operation_t *)zbx_hashset_search(&config->corr_operations, &rowid)))
4408 continue;
4409
4410 /* remove operation from correlation->conditions vector */
4411 if (NULL != (correlation = (zbx_dc_correlation_t *)zbx_hashset_search(&config->correlations, &operation->correlationid)))
4412 {
4413 if (FAIL != (index = zbx_vector_ptr_search(&correlation->operations, operation,
4414 ZBX_DEFAULT_PTR_COMPARE_FUNC)))
4415 {
4416 zbx_vector_ptr_remove_noorder(&correlation->operations, index);
4417 }
4418 }
4419 zbx_hashset_remove_direct(&config->corr_operations, operation);
4420 }
4421
4422 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4423 }
4424
dc_compare_hgroups(const void * d1,const void * d2)4425 static int dc_compare_hgroups(const void *d1, const void *d2)
4426 {
4427 const zbx_dc_hostgroup_t *g1 = *((const zbx_dc_hostgroup_t **)d1);
4428 const zbx_dc_hostgroup_t *g2 = *((const zbx_dc_hostgroup_t **)d2);
4429
4430 return strcmp(g1->name, g2->name);
4431 }
4432
4433 /******************************************************************************
4434 * *
4435 * Function: DCsync_hostgroups *
4436 * *
4437 * Purpose: Updates host groups configuration cache *
4438 * *
4439 * Parameters: sync - [IN] the db synchronization data *
4440 * *
4441 * Comments: The result contains the following fields: *
4442 * 0 - groupid *
4443 * 1 - name *
4444 * *
4445 ******************************************************************************/
DCsync_hostgroups(zbx_dbsync_t * sync)4446 static void DCsync_hostgroups(zbx_dbsync_t *sync)
4447 {
4448 char **row;
4449 zbx_uint64_t rowid;
4450 unsigned char tag;
4451 zbx_uint64_t groupid;
4452 zbx_dc_hostgroup_t *group;
4453 int found, ret, index;
4454
4455 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4456
4457 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
4458 {
4459 /* removed rows will be always added at the end */
4460 if (ZBX_DBSYNC_ROW_REMOVE == tag)
4461 break;
4462
4463 ZBX_STR2UINT64(groupid, row[0]);
4464
4465 group = (zbx_dc_hostgroup_t *)DCfind_id(&config->hostgroups, groupid, sizeof(zbx_dc_hostgroup_t), &found);
4466
4467 if (0 == found)
4468 {
4469 group->flags = ZBX_DC_HOSTGROUP_FLAGS_NONE;
4470 zbx_vector_ptr_append(&config->hostgroups_name, group);
4471
4472 zbx_hashset_create_ext(&group->hostids, 0, ZBX_DEFAULT_UINT64_HASH_FUNC,
4473 ZBX_DEFAULT_UINT64_COMPARE_FUNC, NULL, __config_mem_malloc_func,
4474 __config_mem_realloc_func, __config_mem_free_func);
4475 }
4476
4477 DCstrpool_replace(found, &group->name, row[1]);
4478 }
4479
4480 /* remove deleted host groups */
4481
4482 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
4483 {
4484 if (NULL == (group = (zbx_dc_hostgroup_t *)zbx_hashset_search(&config->hostgroups, &rowid)))
4485 continue;
4486
4487 if (FAIL != (index = zbx_vector_ptr_search(&config->hostgroups_name, group, ZBX_DEFAULT_PTR_COMPARE_FUNC)))
4488 zbx_vector_ptr_remove_noorder(&config->hostgroups_name, index);
4489
4490 if (ZBX_DC_HOSTGROUP_FLAGS_NONE != group->flags)
4491 zbx_vector_uint64_destroy(&group->nested_groupids);
4492
4493 zbx_strpool_release(group->name);
4494 zbx_hashset_destroy(&group->hostids);
4495 zbx_hashset_remove_direct(&config->hostgroups, group);
4496 }
4497
4498 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4499 }
4500
4501 /******************************************************************************
4502 * *
4503 * Function: DCsync_trigger_tags *
4504 * *
4505 * Purpose: Updates trigger tags in configuration cache *
4506 * *
4507 * Parameters: sync - [IN] the db synchronization data *
4508 * *
4509 * Comments: The result contains the following fields: *
4510 * 0 - triggertagid *
4511 * 1 - triggerid *
4512 * 2 - tag *
4513 * 3 - value *
4514 * *
4515 ******************************************************************************/
DCsync_trigger_tags(zbx_dbsync_t * sync)4516 static void DCsync_trigger_tags(zbx_dbsync_t *sync)
4517 {
4518 char **row;
4519 zbx_uint64_t rowid;
4520 unsigned char tag;
4521 int found, ret, index;
4522 zbx_uint64_t triggerid, triggertagid;
4523 ZBX_DC_TRIGGER *trigger;
4524 zbx_dc_trigger_tag_t *trigger_tag;
4525
4526 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4527
4528 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
4529 {
4530 /* removed rows will be always added at the end */
4531 if (ZBX_DBSYNC_ROW_REMOVE == tag)
4532 break;
4533
4534 ZBX_STR2UINT64(triggerid, row[1]);
4535
4536 if (NULL == (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &triggerid)))
4537 continue;
4538
4539 ZBX_STR2UINT64(triggertagid, row[0]);
4540
4541 trigger_tag = (zbx_dc_trigger_tag_t *)DCfind_id(&config->trigger_tags, triggertagid, sizeof(zbx_dc_trigger_tag_t), &found);
4542 DCstrpool_replace(found, &trigger_tag->tag, row[2]);
4543 DCstrpool_replace(found, &trigger_tag->value, row[3]);
4544
4545 if (0 == found)
4546 {
4547 trigger_tag->triggerid = triggerid;
4548 zbx_vector_ptr_append(&trigger->tags, trigger_tag);
4549 }
4550 }
4551
4552 /* remove unused trigger tags */
4553
4554 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
4555 {
4556 if (NULL == (trigger_tag = (zbx_dc_trigger_tag_t *)zbx_hashset_search(&config->trigger_tags, &rowid)))
4557 continue;
4558
4559 if (NULL != (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &trigger_tag->triggerid)))
4560 {
4561 if (FAIL != (index = zbx_vector_ptr_search(&trigger->tags, trigger_tag,
4562 ZBX_DEFAULT_PTR_COMPARE_FUNC)))
4563 {
4564 zbx_vector_ptr_remove_noorder(&trigger->tags, index);
4565
4566 /* recreate empty tags vector to release used memory */
4567 if (0 == trigger->tags.values_num)
4568 {
4569 zbx_vector_ptr_destroy(&trigger->tags);
4570 zbx_vector_ptr_create_ext(&trigger->tags, __config_mem_malloc_func,
4571 __config_mem_realloc_func, __config_mem_free_func);
4572 }
4573 }
4574 }
4575
4576 zbx_strpool_release(trigger_tag->tag);
4577 zbx_strpool_release(trigger_tag->value);
4578
4579 zbx_hashset_remove_direct(&config->trigger_tags, trigger_tag);
4580 }
4581
4582 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4583 }
4584
4585 /******************************************************************************
4586 * *
4587 * Function: DCsync_host_tags *
4588 * *
4589 * Purpose: Updates host tags in configuration cache *
4590 * *
4591 * Parameters: sync - [IN] the db synchronization data *
4592 * *
4593 * Comments: The result contains the following fields: *
4594 * 0 - hosttagid *
4595 * 1 - hostid *
4596 * 2 - tag *
4597 * 3 - value *
4598 * *
4599 ******************************************************************************/
DCsync_host_tags(zbx_dbsync_t * sync)4600 static void DCsync_host_tags(zbx_dbsync_t *sync)
4601 {
4602 char **row;
4603 zbx_uint64_t rowid;
4604 unsigned char tag;
4605
4606 zbx_dc_host_tag_t *host_tag;
4607 zbx_dc_host_tag_index_t *host_tag_index_entry;
4608
4609 int found, index, ret;
4610 zbx_uint64_t hosttagid, hostid;
4611
4612 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4613
4614 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
4615 {
4616 /* removed rows will be always added at the end */
4617 if (ZBX_DBSYNC_ROW_REMOVE == tag)
4618 break;
4619
4620 ZBX_STR2UINT64(hosttagid, row[0]);
4621 ZBX_STR2UINT64(hostid, row[1]);
4622
4623 host_tag = (zbx_dc_host_tag_t *)DCfind_id(&config->host_tags, hosttagid,
4624 sizeof(zbx_dc_host_tag_t), &found);
4625
4626 /* store new information in host_tag structure */
4627 host_tag->hostid = hostid;
4628 DCstrpool_replace(found, &host_tag->tag, row[2]);
4629 DCstrpool_replace(found, &host_tag->value, row[3]);
4630
4631 /* update host_tags_index*/
4632 if (tag == ZBX_DBSYNC_ROW_ADD)
4633 {
4634 host_tag_index_entry = (zbx_dc_host_tag_index_t *)DCfind_id(&config->host_tags_index, hostid,
4635 sizeof(zbx_dc_host_tag_index_t), &found);
4636
4637 if (0 == found)
4638 {
4639 zbx_vector_ptr_create_ext(&host_tag_index_entry->tags, __config_mem_malloc_func,
4640 __config_mem_realloc_func, __config_mem_free_func);
4641 }
4642
4643 zbx_vector_ptr_append(&host_tag_index_entry->tags, host_tag);
4644 }
4645 }
4646
4647 /* remove deleted host tags from buffer */
4648 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
4649 {
4650 if (NULL == (host_tag = (zbx_dc_host_tag_t *)zbx_hashset_search(&config->host_tags, &rowid)))
4651 continue;
4652
4653 /* update host_tags_index*/
4654 host_tag_index_entry = (zbx_dc_host_tag_index_t *)zbx_hashset_search(&config->host_tags_index,
4655 &host_tag->hostid);
4656
4657 if (NULL != host_tag_index_entry)
4658 {
4659 if (FAIL != (index = zbx_vector_ptr_search(&host_tag_index_entry->tags, host_tag,
4660 ZBX_DEFAULT_PTR_COMPARE_FUNC)))
4661 {
4662 zbx_vector_ptr_remove(&host_tag_index_entry->tags, index);
4663 }
4664
4665 /* remove index entry if it's empty */
4666 if (0 == host_tag_index_entry->tags.values_num)
4667 {
4668 zbx_vector_ptr_destroy(&host_tag_index_entry->tags);
4669 zbx_hashset_remove_direct(&config->host_tags_index, host_tag_index_entry);
4670 }
4671 }
4672
4673 /* clear host_tag structure */
4674 zbx_strpool_release(host_tag->tag);
4675 zbx_strpool_release(host_tag->value);
4676
4677 zbx_hashset_remove_direct(&config->host_tags, host_tag);
4678 }
4679
4680 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4681 }
4682
4683 /******************************************************************************
4684 * *
4685 * Function: dc_compare_item_preproc_by_step *
4686 * *
4687 * Purpose: compare two item preprocessing operations by step *
4688 * *
4689 * Comments: This function is used to sort correlation conditions by type. *
4690 * *
4691 ******************************************************************************/
dc_compare_preprocops_by_step(const void * d1,const void * d2)4692 static int dc_compare_preprocops_by_step(const void *d1, const void *d2)
4693 {
4694 zbx_dc_preproc_op_t *p1 = *(zbx_dc_preproc_op_t **)d1;
4695 zbx_dc_preproc_op_t *p2 = *(zbx_dc_preproc_op_t **)d2;
4696
4697 ZBX_RETURN_IF_NOT_EQUAL(p1->step, p2->step);
4698
4699 return 0;
4700 }
4701
4702 /******************************************************************************
4703 * *
4704 * Function: DCsync_item_preproc *
4705 * *
4706 * Purpose: Updates item preprocessing steps in configuration cache *
4707 * *
4708 * Parameters: sync - [IN] the db synchronization data *
4709 * *
4710 * Comments: The result contains the following fields: *
4711 * 0 - item_preprocid *
4712 * 1 - itemid *
4713 * 2 - type *
4714 * 3 - params *
4715 * *
4716 ******************************************************************************/
DCsync_item_preproc(zbx_dbsync_t * sync,int timestamp)4717 static void DCsync_item_preproc(zbx_dbsync_t *sync, int timestamp)
4718 {
4719 char **row;
4720 zbx_uint64_t rowid;
4721 unsigned char tag;
4722 zbx_uint64_t item_preprocid, itemid;
4723 int found, ret, i, index;
4724 ZBX_DC_PREPROCITEM *preprocitem = NULL;
4725 zbx_dc_preproc_op_t *op;
4726 zbx_vector_ptr_t items;
4727
4728 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4729
4730 zbx_vector_ptr_create(&items);
4731
4732 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
4733 {
4734 /* removed rows will be always added at the end */
4735 if (ZBX_DBSYNC_ROW_REMOVE == tag)
4736 break;
4737
4738 ZBX_STR2UINT64(itemid, row[1]);
4739
4740 if (NULL == preprocitem || itemid != preprocitem->itemid)
4741 {
4742 if (NULL == (preprocitem = (ZBX_DC_PREPROCITEM *)zbx_hashset_search(&config->preprocitems, &itemid)))
4743 {
4744 ZBX_DC_PREPROCITEM preprocitem_local;
4745
4746 preprocitem_local.itemid = itemid;
4747
4748 preprocitem = (ZBX_DC_PREPROCITEM *)zbx_hashset_insert(&config->preprocitems, &preprocitem_local,
4749 sizeof(preprocitem_local));
4750
4751 zbx_vector_ptr_create_ext(&preprocitem->preproc_ops, __config_mem_malloc_func,
4752 __config_mem_realloc_func, __config_mem_free_func);
4753 }
4754
4755 preprocitem->update_time = timestamp;
4756 }
4757
4758 ZBX_STR2UINT64(item_preprocid, row[0]);
4759
4760 op = (zbx_dc_preproc_op_t *)DCfind_id(&config->preprocops, item_preprocid, sizeof(zbx_dc_preproc_op_t), &found);
4761
4762 ZBX_STR2UCHAR(op->type, row[2]);
4763 DCstrpool_replace(found, &op->params, row[3]);
4764 op->step = atoi(row[4]);
4765 op->error_handler = atoi(row[6]);
4766 DCstrpool_replace(found, &op->error_handler_params, row[7]);
4767
4768 if (0 == found)
4769 {
4770 op->itemid = itemid;
4771 zbx_vector_ptr_append(&preprocitem->preproc_ops, op);
4772 }
4773
4774 zbx_vector_ptr_append(&items, preprocitem);
4775 }
4776
4777 /* remove deleted item preprocessing operations */
4778
4779 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
4780 {
4781 if (NULL == (op = (zbx_dc_preproc_op_t *)zbx_hashset_search(&config->preprocops, &rowid)))
4782 continue;
4783
4784 if (NULL != (preprocitem = (ZBX_DC_PREPROCITEM *)zbx_hashset_search(&config->preprocitems, &op->itemid)))
4785 {
4786 if (FAIL != (index = zbx_vector_ptr_search(&preprocitem->preproc_ops, op,
4787 ZBX_DEFAULT_PTR_COMPARE_FUNC)))
4788 {
4789 zbx_vector_ptr_remove_noorder(&preprocitem->preproc_ops, index);
4790 zbx_vector_ptr_append(&items, preprocitem);
4791 }
4792 }
4793
4794 zbx_strpool_release(op->params);
4795 zbx_strpool_release(op->error_handler_params);
4796 zbx_hashset_remove_direct(&config->preprocops, op);
4797 }
4798
4799 /* sort item preprocessing operations by step */
4800
4801 zbx_vector_ptr_sort(&items, ZBX_DEFAULT_PTR_COMPARE_FUNC);
4802 zbx_vector_ptr_uniq(&items, ZBX_DEFAULT_PTR_COMPARE_FUNC);
4803
4804 for (i = 0; i < items.values_num; i++)
4805 {
4806 preprocitem = (ZBX_DC_PREPROCITEM *)items.values[i];
4807
4808 if (0 == preprocitem->preproc_ops.values_num)
4809 {
4810 zbx_vector_ptr_destroy(&preprocitem->preproc_ops);
4811 zbx_hashset_remove_direct(&config->preprocitems, preprocitem);
4812 }
4813 else
4814 zbx_vector_ptr_sort(&preprocitem->preproc_ops, dc_compare_preprocops_by_step);
4815 }
4816
4817 zbx_vector_ptr_destroy(&items);
4818
4819 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4820 }
4821
4822 /******************************************************************************
4823 * *
4824 * Function: DCsync_hostgroup_hosts *
4825 * *
4826 * Purpose: Updates group hosts in configuration cache *
4827 * *
4828 * Parameters: sync - [IN] the db synchronization data *
4829 * *
4830 * Comments: The result contains the following fields: *
4831 * 0 - groupid *
4832 * 1 - hostid *
4833 * *
4834 ******************************************************************************/
DCsync_hostgroup_hosts(zbx_dbsync_t * sync)4835 static void DCsync_hostgroup_hosts(zbx_dbsync_t *sync)
4836 {
4837 char **row;
4838 zbx_uint64_t rowid;
4839 unsigned char tag;
4840
4841 zbx_dc_hostgroup_t *group = NULL;
4842
4843 int ret;
4844 zbx_uint64_t last_groupid = 0, groupid, hostid;
4845
4846 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4847
4848 while (SUCCEED == (ret = zbx_dbsync_next(sync, &rowid, &row, &tag)))
4849 {
4850 config->maintenance_update = ZBX_MAINTENANCE_UPDATE_TRUE;
4851
4852 /* removed rows will be always added at the end */
4853 if (ZBX_DBSYNC_ROW_REMOVE == tag)
4854 break;
4855
4856 ZBX_STR2UINT64(groupid, row[0]);
4857
4858 if (last_groupid != groupid)
4859 {
4860 group = (zbx_dc_hostgroup_t *)zbx_hashset_search(&config->hostgroups, &groupid);
4861 last_groupid = groupid;
4862 }
4863
4864 if (NULL == group)
4865 continue;
4866
4867 ZBX_STR2UINT64(hostid, row[1]);
4868 zbx_hashset_insert(&group->hostids, &hostid, sizeof(hostid));
4869 }
4870
4871 /* remove deleted group hostids from cache */
4872 for (; SUCCEED == ret; ret = zbx_dbsync_next(sync, &rowid, &row, &tag))
4873 {
4874 ZBX_STR2UINT64(groupid, row[0]);
4875
4876 if (NULL == (group = (zbx_dc_hostgroup_t *)zbx_hashset_search(&config->hostgroups, &groupid)))
4877 continue;
4878
4879 ZBX_STR2UINT64(hostid, row[1]);
4880 zbx_hashset_remove(&group->hostids, &hostid);
4881 }
4882
4883 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4884 }
4885
4886 /******************************************************************************
4887 * *
4888 * Function: dc_trigger_update_topology *
4889 * *
4890 * Purpose: updates trigger topology after trigger dependency changes *
4891 * *
4892 ******************************************************************************/
dc_trigger_update_topology(void)4893 static void dc_trigger_update_topology(void)
4894 {
4895 zbx_hashset_iter_t iter;
4896 ZBX_DC_TRIGGER *trigger;
4897
4898 zbx_hashset_iter_reset(&config->triggers, &iter);
4899 while (NULL != (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_iter_next(&iter)))
4900 trigger->topoindex = 1;
4901
4902 DCconfig_sort_triggers_topologically();
4903 }
4904
zbx_default_ptr_pair_ptr_compare_func(const void * d1,const void * d2)4905 static int zbx_default_ptr_pair_ptr_compare_func(const void *d1, const void *d2)
4906 {
4907 const zbx_ptr_pair_t *p1 = (const zbx_ptr_pair_t *)d1;
4908 const zbx_ptr_pair_t *p2 = (const zbx_ptr_pair_t *)d2;
4909
4910 ZBX_RETURN_IF_NOT_EQUAL(p1->first, p2->first);
4911 ZBX_RETURN_IF_NOT_EQUAL(p1->second, p2->second);
4912
4913 return 0;
4914 }
4915
4916 #define ZBX_TIMER_DELAY 30
4917
4918 /******************************************************************************
4919 * *
4920 * Function: dc_timer_calculate_nextcheck *
4921 * *
4922 * Purpose: calculates next check for timer queue item *
4923 * *
4924 ******************************************************************************/
dc_timer_calculate_nextcheck(time_t now,zbx_uint64_t seed)4925 static int dc_timer_calculate_nextcheck(time_t now, zbx_uint64_t seed)
4926 {
4927 int nextcheck;
4928
4929 nextcheck = ZBX_TIMER_DELAY * (int)(now / (time_t)ZBX_TIMER_DELAY) +
4930 (int)(seed % (zbx_uint64_t)ZBX_TIMER_DELAY);
4931
4932 while (nextcheck <= now)
4933 nextcheck += ZBX_TIMER_DELAY;
4934
4935 return nextcheck;
4936 }
4937
4938 /******************************************************************************
4939 * *
4940 * Function: dc_trigger_update_cache *
4941 * *
4942 * Purpose: updates trigger related cache data; *
4943 * 1) time triggers assigned to timer processes *
4944 * 2) trigger functionality (if it uses contain disabled *
4945 * items/hosts) *
4946 * 3) list of triggers each item is used by *
4947 * *
4948 ******************************************************************************/
dc_trigger_update_cache(void)4949 static void dc_trigger_update_cache(void)
4950 {
4951 zbx_hashset_iter_t iter;
4952 ZBX_DC_TRIGGER *trigger;
4953 ZBX_DC_FUNCTION *function;
4954 ZBX_DC_ITEM *item;
4955 int i, j, k, now;
4956 zbx_ptr_pair_t itemtrig;
4957 zbx_vector_ptr_pair_t itemtrigs;
4958 ZBX_DC_HOST *host;
4959
4960 zbx_hashset_iter_reset(&config->triggers, &iter);
4961 while (NULL != (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_iter_next(&iter)))
4962 {
4963 trigger->functional = TRIGGER_FUNCTIONAL_TRUE;
4964 trigger->timer = ZBX_TRIGGER_TIMER_UNKNOWN;
4965 }
4966
4967 zbx_vector_ptr_pair_create(&itemtrigs);
4968 zbx_hashset_iter_reset(&config->functions, &iter);
4969 while (NULL != (function = (ZBX_DC_FUNCTION *)zbx_hashset_iter_next(&iter)))
4970 {
4971
4972 if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &function->itemid)) ||
4973 NULL == (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &function->triggerid)))
4974 {
4975 continue;
4976 }
4977
4978 /* cache item - trigger link */
4979 if (0 != item->update_triggers)
4980 {
4981 itemtrig.first = item;
4982 itemtrig.second = trigger;
4983 zbx_vector_ptr_pair_append(&itemtrigs, itemtrig);
4984 }
4985
4986 /* disable functionality for triggers with expression containing */
4987 /* disabled or not monitored items */
4988
4989 if (TRIGGER_FUNCTIONAL_FALSE == trigger->functional)
4990 continue;
4991
4992 if (ITEM_STATUS_DISABLED == item->status ||
4993 (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &item->hostid)) ||
4994 HOST_STATUS_NOT_MONITORED == host->status))
4995 {
4996 trigger->functional = TRIGGER_FUNCTIONAL_FALSE;
4997 }
4998
4999 if (1 == function->timer)
5000 trigger->timer = ZBX_TRIGGER_TIMER_QUEUE;
5001 }
5002
5003 zbx_vector_ptr_pair_sort(&itemtrigs, zbx_default_ptr_pair_ptr_compare_func);
5004 zbx_vector_ptr_pair_uniq(&itemtrigs, zbx_default_ptr_pair_ptr_compare_func);
5005
5006 /* update links from items to triggers */
5007 for (i = 0; i < itemtrigs.values_num; i++)
5008 {
5009 for (j = i + 1; j < itemtrigs.values_num; j++)
5010 {
5011 if (itemtrigs.values[i].first != itemtrigs.values[j].first)
5012 break;
5013 }
5014
5015 item = (ZBX_DC_ITEM *)itemtrigs.values[i].first;
5016 item->update_triggers = 0;
5017 item->triggers = (ZBX_DC_TRIGGER **)config->items.mem_realloc_func(item->triggers, (j - i + 1) * sizeof(ZBX_DC_TRIGGER *));
5018
5019 for (k = i; k < j; k++)
5020 item->triggers[k - i] = (ZBX_DC_TRIGGER *)itemtrigs.values[k].second;
5021
5022 item->triggers[j - i] = NULL;
5023
5024 i = j - 1;
5025 }
5026
5027 zbx_vector_ptr_pair_destroy(&itemtrigs);
5028
5029 /* add triggers to timer queue */
5030 now = time(NULL);
5031 zbx_binary_heap_clear(&config->timer_queue);
5032 zbx_hashset_iter_reset(&config->triggers, &iter);
5033 while (NULL != (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_iter_next(&iter)))
5034 {
5035 zbx_binary_heap_elem_t elem;
5036
5037 if (TRIGGER_STATUS_DISABLED == trigger->status)
5038 continue;
5039
5040 if (TRIGGER_FUNCTIONAL_FALSE == trigger->functional)
5041 continue;
5042
5043 if (ZBX_TRIGGER_TIMER_QUEUE != trigger->timer)
5044 continue;
5045
5046 trigger->nextcheck = dc_timer_calculate_nextcheck(now, trigger->triggerid);
5047 elem.key = trigger->triggerid;
5048 elem.data = (void *)trigger;
5049 zbx_binary_heap_insert(&config->timer_queue, &elem);
5050 }
5051 }
5052
5053 /******************************************************************************
5054 * *
5055 * Function: dc_hostgroups_update_cache *
5056 * *
5057 * Purpose: updates hostgroup name index and resets nested group lists *
5058 * *
5059 ******************************************************************************/
dc_hostgroups_update_cache(void)5060 static void dc_hostgroups_update_cache(void)
5061 {
5062 zbx_hashset_iter_t iter;
5063 zbx_dc_hostgroup_t *group;
5064
5065 zbx_vector_ptr_sort(&config->hostgroups_name, dc_compare_hgroups);
5066
5067 zbx_hashset_iter_reset(&config->hostgroups, &iter);
5068 while (NULL != (group = (zbx_dc_hostgroup_t *)zbx_hashset_iter_next(&iter)))
5069 {
5070 if (ZBX_DC_HOSTGROUP_FLAGS_NONE != group->flags)
5071 {
5072 group->flags = ZBX_DC_HOSTGROUP_FLAGS_NONE;
5073 zbx_vector_uint64_destroy(&group->nested_groupids);
5074 }
5075 }
5076 }
5077
5078 /******************************************************************************
5079 * *
5080 * Function: DCsync_configuration *
5081 * *
5082 * Purpose: Synchronize configuration data from database *
5083 * *
5084 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
5085 * *
5086 ******************************************************************************/
DCsync_configuration(unsigned char mode)5087 void DCsync_configuration(unsigned char mode)
5088 {
5089 int i, flags;
5090 double sec, csec, hsec, hisec, htsec, gmsec, hmsec, ifsec, isec, tsec, dsec, fsec, expr_sec, csec2,
5091 hsec2, hisec2, htsec2, gmsec2, hmsec2, ifsec2, isec2, tsec2, dsec2, fsec2, expr_sec2,
5092 action_sec, action_sec2, action_op_sec, action_op_sec2, action_condition_sec,
5093 action_condition_sec2, trigger_tag_sec, trigger_tag_sec2, host_tag_sec, host_tag_sec2,
5094 correlation_sec, correlation_sec2, corr_condition_sec, corr_condition_sec2, corr_operation_sec,
5095 corr_operation_sec2, hgroups_sec, hgroups_sec2, itempp_sec, itempp_sec2, total, total2,
5096 update_sec, maintenance_sec, maintenance_sec2;
5097
5098 zbx_dbsync_t config_sync, hosts_sync, hi_sync, htmpl_sync, gmacro_sync, hmacro_sync, if_sync, items_sync,
5099 template_items_sync, prototype_items_sync, triggers_sync, tdep_sync, func_sync, expr_sync,
5100 action_sync, action_op_sync, action_condition_sync, trigger_tag_sync, host_tag_sync,
5101 correlation_sync, corr_condition_sync, corr_operation_sync, hgroups_sync, itempp_sync,
5102 maintenance_sync, maintenance_period_sync, maintenance_tag_sync, maintenance_group_sync,
5103 maintenance_host_sync, hgroup_host_sync;
5104
5105 double autoreg_csec, autoreg_csec2;
5106 zbx_dbsync_t autoreg_config_sync;
5107 zbx_uint64_t update_flags = 0;
5108
5109 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
5110
5111 zbx_dbsync_init_env(config);
5112
5113 /* global configuration must be synchronized directly with database */
5114 zbx_dbsync_init(&config_sync, ZBX_DBSYNC_INIT);
5115 zbx_dbsync_init(&autoreg_config_sync, mode);
5116 zbx_dbsync_init(&hosts_sync, mode);
5117 zbx_dbsync_init(&hi_sync, mode);
5118 zbx_dbsync_init(&htmpl_sync, mode);
5119 zbx_dbsync_init(&gmacro_sync, mode);
5120 zbx_dbsync_init(&hmacro_sync, mode);
5121 zbx_dbsync_init(&if_sync, mode);
5122 zbx_dbsync_init(&items_sync, mode);
5123 zbx_dbsync_init(&template_items_sync, mode);
5124 zbx_dbsync_init(&prototype_items_sync, mode);
5125 zbx_dbsync_init(&triggers_sync, mode);
5126 zbx_dbsync_init(&tdep_sync, mode);
5127 zbx_dbsync_init(&func_sync, mode);
5128 zbx_dbsync_init(&expr_sync, mode);
5129 zbx_dbsync_init(&action_sync, mode);
5130
5131 /* Action operation sync produces virtual rows with two columns - actionid, opflags. */
5132 /* Because of this it cannot return the original database select and must always be */
5133 /* initialized in update mode. */
5134 zbx_dbsync_init(&action_op_sync, ZBX_DBSYNC_UPDATE);
5135
5136 zbx_dbsync_init(&action_condition_sync, mode);
5137 zbx_dbsync_init(&trigger_tag_sync, mode);
5138 zbx_dbsync_init(&host_tag_sync, mode);
5139 zbx_dbsync_init(&correlation_sync, mode);
5140 zbx_dbsync_init(&corr_condition_sync, mode);
5141 zbx_dbsync_init(&corr_operation_sync, mode);
5142 zbx_dbsync_init(&hgroups_sync, mode);
5143 zbx_dbsync_init(&hgroup_host_sync, mode);
5144 zbx_dbsync_init(&itempp_sync, mode);
5145
5146 zbx_dbsync_init(&maintenance_sync, mode);
5147 zbx_dbsync_init(&maintenance_period_sync, mode);
5148 zbx_dbsync_init(&maintenance_tag_sync, mode);
5149 zbx_dbsync_init(&maintenance_group_sync, mode);
5150 zbx_dbsync_init(&maintenance_host_sync, mode);
5151
5152 sec = zbx_time();
5153 if (FAIL == zbx_dbsync_compare_config(&config_sync))
5154 goto out;
5155 csec = zbx_time() - sec;
5156
5157 sec = zbx_time();
5158 if (FAIL == zbx_dbsync_compare_autoreg_psk(&autoreg_config_sync))
5159 goto out;
5160 autoreg_csec = zbx_time() - sec;
5161
5162 /* sync global configuration settings */
5163 START_SYNC;
5164 sec = zbx_time();
5165 DCsync_config(&config_sync, &flags);
5166 csec2 = zbx_time() - sec;
5167
5168 sec = zbx_time();
5169 DCsync_autoreg_config(&autoreg_config_sync); /* must be done in the same cache locking with config sync */
5170 autoreg_csec2 = zbx_time() - sec;
5171 FINISH_SYNC;
5172
5173 /* sync macro related data, to support macro resolving during configuration sync */
5174
5175 sec = zbx_time();
5176 if (FAIL == zbx_dbsync_compare_host_templates(&htmpl_sync))
5177 goto out;
5178 htsec = zbx_time() - sec;
5179
5180 sec = zbx_time();
5181 if (FAIL == zbx_dbsync_compare_global_macros(&gmacro_sync))
5182 goto out;
5183 gmsec = zbx_time() - sec;
5184
5185 sec = zbx_time();
5186 if (FAIL == zbx_dbsync_compare_host_macros(&hmacro_sync))
5187 goto out;
5188 hmsec = zbx_time() - sec;
5189
5190 sec = zbx_time();
5191 if (FAIL == zbx_dbsync_compare_host_tags(&host_tag_sync))
5192 goto out;
5193 host_tag_sec = zbx_time() - sec;
5194
5195 START_SYNC;
5196 sec = zbx_time();
5197 DCsync_htmpls(&htmpl_sync);
5198 htsec2 = zbx_time() - sec;
5199
5200 sec = zbx_time();
5201 DCsync_gmacros(&gmacro_sync);
5202 gmsec2 = zbx_time() - sec;
5203
5204 sec = zbx_time();
5205 DCsync_hmacros(&hmacro_sync);
5206 hmsec2 = zbx_time() - sec;
5207
5208 sec = zbx_time();
5209 DCsync_host_tags(&host_tag_sync);
5210 host_tag_sec2 = zbx_time() - sec;
5211 FINISH_SYNC;
5212
5213 /* sync host data to support host lookups when resolving macros during configuration sync */
5214
5215 sec = zbx_time();
5216 if (FAIL == zbx_dbsync_compare_hosts(&hosts_sync))
5217 goto out;
5218 hsec = zbx_time() - sec;
5219
5220 sec = zbx_time();
5221 if (FAIL == zbx_dbsync_compare_host_inventory(&hi_sync))
5222 goto out;
5223 hisec = zbx_time() - sec;
5224
5225 sec = zbx_time();
5226 if (FAIL == zbx_dbsync_compare_host_groups(&hgroups_sync))
5227 goto out;
5228 if (FAIL == zbx_dbsync_compare_host_group_hosts(&hgroup_host_sync))
5229 goto out;
5230 hgroups_sec = zbx_time() - sec;
5231
5232 sec = zbx_time();
5233 if (FAIL == zbx_dbsync_compare_maintenances(&maintenance_sync))
5234 goto out;
5235 if (FAIL == zbx_dbsync_compare_maintenance_tags(&maintenance_tag_sync))
5236 goto out;
5237 if (FAIL == zbx_dbsync_compare_maintenance_periods(&maintenance_period_sync))
5238 goto out;
5239 if (FAIL == zbx_dbsync_compare_maintenance_groups(&maintenance_group_sync))
5240 goto out;
5241 if (FAIL == zbx_dbsync_compare_maintenance_hosts(&maintenance_host_sync))
5242 goto out;
5243 maintenance_sec = zbx_time() - sec;
5244
5245 START_SYNC;
5246 sec = zbx_time();
5247 DCsync_hosts(&hosts_sync);
5248 hsec2 = zbx_time() - sec;
5249
5250 sec = zbx_time();
5251 DCsync_host_inventory(&hi_sync);
5252 hisec2 = zbx_time() - sec;
5253
5254 sec = zbx_time();
5255 DCsync_hostgroups(&hgroups_sync);
5256 DCsync_hostgroup_hosts(&hgroup_host_sync);
5257 hgroups_sec2 = zbx_time() - sec;
5258
5259 sec = zbx_time();
5260 DCsync_maintenances(&maintenance_sync);
5261 DCsync_maintenance_tags(&maintenance_tag_sync);
5262 DCsync_maintenance_groups(&maintenance_group_sync);
5263 DCsync_maintenance_hosts(&maintenance_host_sync);
5264 DCsync_maintenance_periods(&maintenance_period_sync);
5265 maintenance_sec2 = zbx_time() - sec;
5266
5267 if (0 != hgroups_sync.add_num + hgroups_sync.update_num + hgroups_sync.remove_num)
5268 update_flags |= ZBX_DBSYNC_UPDATE_HOST_GROUPS;
5269
5270 if (0 != maintenance_group_sync.add_num + maintenance_group_sync.update_num + maintenance_group_sync.remove_num)
5271 update_flags |= ZBX_DBSYNC_UPDATE_MAINTENANCE_GROUPS;
5272
5273 if (0 != (update_flags & ZBX_DBSYNC_UPDATE_HOST_GROUPS))
5274 dc_hostgroups_update_cache();
5275
5276 /* pre-cache nested groups used in maintenances to allow read lock */
5277 /* during host maintenance update calculations */
5278 if (0 != (update_flags & (ZBX_DBSYNC_UPDATE_HOST_GROUPS | ZBX_DBSYNC_UPDATE_MAINTENANCE_GROUPS)))
5279 dc_maintenance_precache_nested_groups();
5280
5281 FINISH_SYNC;
5282
5283 /* sync item data to support item lookups when resolving macros during configuration sync */
5284
5285 sec = zbx_time();
5286 if (FAIL == zbx_dbsync_compare_interfaces(&if_sync))
5287 goto out;
5288 ifsec = zbx_time() - sec;
5289
5290 sec = zbx_time();
5291 if (FAIL == zbx_dbsync_compare_items(&items_sync))
5292 goto out;
5293
5294 if (FAIL == zbx_dbsync_compare_template_items(&template_items_sync))
5295 goto out;
5296
5297 if (FAIL == zbx_dbsync_compare_prototype_items(&prototype_items_sync))
5298 goto out;
5299 isec = zbx_time() - sec;
5300
5301 sec = zbx_time();
5302 if (FAIL == zbx_dbsync_compare_item_preprocs(&itempp_sync))
5303 goto out;
5304 itempp_sec = zbx_time() - sec;
5305
5306 START_SYNC;
5307
5308 /* resolves macros for interface_snmpaddrs, must be after DCsync_hmacros() */
5309 sec = zbx_time();
5310 DCsync_interfaces(&if_sync);
5311 ifsec2 = zbx_time() - sec;
5312
5313 /* relies on hosts, proxies and interfaces, must be after DCsync_{hosts,interfaces}() */
5314 sec = zbx_time();
5315 DCsync_items(&items_sync, flags);
5316 DCsync_template_items(&template_items_sync);
5317 DCsync_prototype_items(&prototype_items_sync);
5318 isec2 = zbx_time() - sec;
5319
5320 /* relies on items, must be after DCsync_items() */
5321 sec = zbx_time();
5322 DCsync_item_preproc(&itempp_sync, sec);
5323 itempp_sec2 = zbx_time() - sec;
5324
5325 config->item_sync_ts = time(NULL);
5326 FINISH_SYNC;
5327
5328 dc_flush_history(); /* misconfigured items generate pseudo-historic values to become notsupported */
5329
5330 /* sync function data to support function lookups when resolving macros during configuration sync */
5331
5332 sec = zbx_time();
5333 if (FAIL == zbx_dbsync_compare_functions(&func_sync))
5334 goto out;
5335 fsec = zbx_time() - sec;
5336
5337 START_SYNC;
5338 sec = zbx_time();
5339 DCsync_functions(&func_sync);
5340 fsec2 = zbx_time() - sec;
5341 FINISH_SYNC;
5342
5343 /* sync rest of the data */
5344
5345 sec = zbx_time();
5346 if (FAIL == zbx_dbsync_compare_triggers(&triggers_sync))
5347 goto out;
5348 tsec = zbx_time() - sec;
5349
5350 sec = zbx_time();
5351 if (FAIL == zbx_dbsync_compare_trigger_dependency(&tdep_sync))
5352 goto out;
5353 dsec = zbx_time() - sec;
5354
5355 sec = zbx_time();
5356 if (FAIL == zbx_dbsync_compare_expressions(&expr_sync))
5357 goto out;
5358 expr_sec = zbx_time() - sec;
5359
5360 sec = zbx_time();
5361 if (FAIL == zbx_dbsync_compare_actions(&action_sync))
5362 goto out;
5363 action_sec = zbx_time() - sec;
5364
5365 sec = zbx_time();
5366 if (FAIL == zbx_dbsync_compare_action_ops(&action_op_sync))
5367 goto out;
5368 action_op_sec = zbx_time() - sec;
5369
5370 sec = zbx_time();
5371 if (FAIL == zbx_dbsync_compare_action_conditions(&action_condition_sync))
5372 goto out;
5373 action_condition_sec = zbx_time() - sec;
5374
5375 sec = zbx_time();
5376 if (FAIL == zbx_dbsync_compare_trigger_tags(&trigger_tag_sync))
5377 goto out;
5378 trigger_tag_sec = zbx_time() - sec;
5379
5380 sec = zbx_time();
5381 if (FAIL == zbx_dbsync_compare_correlations(&correlation_sync))
5382 goto out;
5383 correlation_sec = zbx_time() - sec;
5384
5385 sec = zbx_time();
5386 if (FAIL == zbx_dbsync_compare_corr_conditions(&corr_condition_sync))
5387 goto out;
5388 corr_condition_sec = zbx_time() - sec;
5389
5390 sec = zbx_time();
5391 if (FAIL == zbx_dbsync_compare_corr_operations(&corr_operation_sync))
5392 goto out;
5393 corr_operation_sec = zbx_time() - sec;
5394
5395 START_SYNC;
5396
5397 sec = zbx_time();
5398 DCsync_triggers(&triggers_sync);
5399 tsec2 = zbx_time() - sec;
5400
5401 sec = zbx_time();
5402 DCsync_trigdeps(&tdep_sync);
5403 dsec2 = zbx_time() - sec;
5404
5405 sec = zbx_time();
5406 DCsync_expressions(&expr_sync);
5407 expr_sec2 = zbx_time() - sec;
5408
5409 sec = zbx_time();
5410 DCsync_actions(&action_sync);
5411 action_sec2 = zbx_time() - sec;
5412
5413 sec = zbx_time();
5414 DCsync_action_ops(&action_op_sync);
5415 action_op_sec2 = zbx_time() - sec;
5416
5417 sec = zbx_time();
5418 DCsync_action_conditions(&action_condition_sync);
5419 action_condition_sec2 = zbx_time() - sec;
5420
5421 sec = zbx_time();
5422 /* relies on triggers, must be after DCsync_triggers() */
5423 DCsync_trigger_tags(&trigger_tag_sync);
5424 trigger_tag_sec2 = zbx_time() - sec;
5425
5426 sec = zbx_time();
5427 DCsync_correlations(&correlation_sync);
5428 correlation_sec2 = zbx_time() - sec;
5429
5430 sec = zbx_time();
5431 /* relies on correlation rules, must be after DCsync_correlations() */
5432 DCsync_corr_conditions(&corr_condition_sync);
5433 corr_condition_sec2 = zbx_time() - sec;
5434
5435 sec = zbx_time();
5436 /* relies on correlation rules, must be after DCsync_correlations() */
5437 DCsync_corr_operations(&corr_operation_sync);
5438 corr_operation_sec2 = zbx_time() - sec;
5439
5440 sec = zbx_time();
5441
5442 if (0 != hosts_sync.add_num + hosts_sync.update_num + hosts_sync.remove_num)
5443 update_flags |= ZBX_DBSYNC_UPDATE_HOSTS;
5444
5445 if (0 != items_sync.add_num + items_sync.update_num + items_sync.remove_num)
5446 update_flags |= ZBX_DBSYNC_UPDATE_ITEMS;
5447
5448 if (0 != func_sync.add_num + func_sync.update_num + func_sync.remove_num)
5449 update_flags |= ZBX_DBSYNC_UPDATE_FUNCTIONS;
5450
5451 if (0 != triggers_sync.add_num + triggers_sync.update_num + triggers_sync.remove_num)
5452 update_flags |= ZBX_DBSYNC_UPDATE_TRIGGERS;
5453
5454 if (0 != tdep_sync.add_num + tdep_sync.update_num + tdep_sync.remove_num)
5455 update_flags |= ZBX_DBSYNC_UPDATE_TRIGGER_DEPENDENCY;
5456
5457 /* update trigger topology if trigger dependency was changed */
5458 if (0 != (update_flags & ZBX_DBSYNC_UPDATE_TRIGGER_DEPENDENCY))
5459 dc_trigger_update_topology();
5460
5461 /* update various trigger related links in cache */
5462 if (0 != (update_flags & (ZBX_DBSYNC_UPDATE_HOSTS | ZBX_DBSYNC_UPDATE_ITEMS | ZBX_DBSYNC_UPDATE_FUNCTIONS |
5463 ZBX_DBSYNC_UPDATE_TRIGGERS)))
5464 {
5465 dc_trigger_update_cache();
5466 }
5467
5468 update_sec = zbx_time() - sec;
5469
5470 if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_DEBUG))
5471 {
5472 total = csec + hsec + hisec + htsec + gmsec + hmsec + ifsec + isec + tsec + dsec + fsec + expr_sec +
5473 action_sec + action_op_sec + action_condition_sec + trigger_tag_sec + correlation_sec +
5474 corr_condition_sec + corr_operation_sec + hgroups_sec + itempp_sec + maintenance_sec;
5475 total2 = csec2 + hsec2 + hisec2 + htsec2 + gmsec2 + hmsec2 + ifsec2 + isec2 + tsec2 + dsec2 + fsec2 +
5476 expr_sec2 + action_op_sec2 + action_sec2 + action_condition_sec2 + trigger_tag_sec2 +
5477 correlation_sec2 + corr_condition_sec2 + corr_operation_sec2 + hgroups_sec2 +
5478 itempp_sec2 + maintenance_sec2 + update_sec;
5479
5480 zabbix_log(LOG_LEVEL_DEBUG, "%s() config : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5481 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5482 __func__, csec, csec2, config_sync.add_num, config_sync.update_num,
5483 config_sync.remove_num);
5484
5485 total += autoreg_csec;
5486 total2 += autoreg_csec2;
5487 zabbix_log(LOG_LEVEL_DEBUG, "%s() autoreg : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5488 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5489 __func__, autoreg_csec, autoreg_csec2, autoreg_config_sync.add_num,
5490 autoreg_config_sync.update_num, autoreg_config_sync.remove_num);
5491
5492 zabbix_log(LOG_LEVEL_DEBUG, "%s() hosts : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5493 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5494 __func__, hsec, hsec2, hosts_sync.add_num, hosts_sync.update_num,
5495 hosts_sync.remove_num);
5496 zabbix_log(LOG_LEVEL_DEBUG, "%s() host_invent: sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5497 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5498 __func__, hisec, hisec2, hi_sync.add_num, hi_sync.update_num,
5499 hi_sync.remove_num);
5500 zabbix_log(LOG_LEVEL_DEBUG, "%s() templates : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5501 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5502 __func__, htsec, htsec2, htmpl_sync.add_num, htmpl_sync.update_num,
5503 htmpl_sync.remove_num);
5504 zabbix_log(LOG_LEVEL_DEBUG, "%s() globmacros : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5505 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5506 __func__, gmsec, gmsec2, gmacro_sync.add_num, gmacro_sync.update_num,
5507 gmacro_sync.remove_num);
5508 zabbix_log(LOG_LEVEL_DEBUG, "%s() hostmacros : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5509 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5510 __func__, hmsec, hmsec2, hmacro_sync.add_num, hmacro_sync.update_num,
5511 hmacro_sync.remove_num);
5512 zabbix_log(LOG_LEVEL_DEBUG, "%s() interfaces : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5513 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5514 __func__, ifsec, ifsec2, if_sync.add_num, if_sync.update_num,
5515 if_sync.remove_num);
5516 zabbix_log(LOG_LEVEL_DEBUG, "%s() items : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5517 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5518 __func__, isec, isec2, items_sync.add_num, items_sync.update_num,
5519 items_sync.remove_num);
5520 zabbix_log(LOG_LEVEL_DEBUG, "%s() template_items : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5521 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5522 __func__, isec, isec2, template_items_sync.add_num,
5523 template_items_sync.update_num, template_items_sync.remove_num);
5524 zabbix_log(LOG_LEVEL_DEBUG, "%s() prototype_items : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5525 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5526 __func__, isec, isec2, prototype_items_sync.add_num,
5527 prototype_items_sync.update_num, prototype_items_sync.remove_num);
5528 zabbix_log(LOG_LEVEL_DEBUG, "%s() triggers : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5529 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5530 __func__, tsec, tsec2, triggers_sync.add_num, triggers_sync.update_num,
5531 triggers_sync.remove_num);
5532 zabbix_log(LOG_LEVEL_DEBUG, "%s() trigdeps : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5533 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5534 __func__, dsec, dsec2, tdep_sync.add_num, tdep_sync.update_num,
5535 tdep_sync.remove_num);
5536 zabbix_log(LOG_LEVEL_DEBUG, "%s() trig. tags : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5537 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5538 __func__, trigger_tag_sec, trigger_tag_sec2, trigger_tag_sync.add_num,
5539 trigger_tag_sync.update_num, trigger_tag_sync.remove_num);
5540 zabbix_log(LOG_LEVEL_DEBUG, "%s() host tags : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5541 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5542 __func__, host_tag_sec, host_tag_sec2, host_tag_sync.add_num,
5543 host_tag_sync.update_num, host_tag_sync.remove_num);
5544 zabbix_log(LOG_LEVEL_DEBUG, "%s() functions : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5545 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5546 __func__, fsec, fsec2, func_sync.add_num, func_sync.update_num,
5547 func_sync.remove_num);
5548 zabbix_log(LOG_LEVEL_DEBUG, "%s() expressions: sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5549 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5550 __func__, expr_sec, expr_sec2, expr_sync.add_num, expr_sync.update_num,
5551 expr_sync.remove_num);
5552 zabbix_log(LOG_LEVEL_DEBUG, "%s() actions : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5553 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5554 __func__, action_sec, action_sec2, action_sync.add_num, action_sync.update_num,
5555 action_sync.remove_num);
5556 zabbix_log(LOG_LEVEL_DEBUG, "%s() operations : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5557 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5558 __func__, action_op_sec, action_op_sec2, action_op_sync.add_num,
5559 action_op_sync.update_num, action_op_sync.remove_num);
5560 zabbix_log(LOG_LEVEL_DEBUG, "%s() conditions : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5561 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5562 __func__, action_condition_sec, action_condition_sec2,
5563 action_condition_sync.add_num, action_condition_sync.update_num,
5564 action_condition_sync.remove_num);
5565 zabbix_log(LOG_LEVEL_DEBUG, "%s() corr : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5566 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5567 __func__, correlation_sec, correlation_sec2, correlation_sync.add_num,
5568 correlation_sync.update_num, correlation_sync.remove_num);
5569 zabbix_log(LOG_LEVEL_DEBUG, "%s() corr_cond : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5570 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5571 __func__, corr_condition_sec, corr_condition_sec2, corr_condition_sync.add_num,
5572 corr_condition_sync.update_num, corr_condition_sync.remove_num);
5573 zabbix_log(LOG_LEVEL_DEBUG, "%s() corr_op : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5574 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5575 __func__, corr_operation_sec, corr_operation_sec2, corr_operation_sync.add_num,
5576 corr_operation_sync.update_num, corr_operation_sync.remove_num);
5577 zabbix_log(LOG_LEVEL_DEBUG, "%s() hgroups : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5578 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5579 __func__, hgroups_sec, hgroups_sec2, hgroups_sync.add_num,
5580 hgroups_sync.update_num, hgroups_sync.remove_num);
5581 zabbix_log(LOG_LEVEL_DEBUG, "%s() item pproc : sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5582 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5583 __func__, itempp_sec, itempp_sec2, itempp_sync.add_num, itempp_sync.update_num,
5584 itempp_sync.remove_num);
5585 zabbix_log(LOG_LEVEL_DEBUG, "%s() maintenance: sql:" ZBX_FS_DBL " sync:" ZBX_FS_DBL " sec ("
5586 ZBX_FS_UI64 "/" ZBX_FS_UI64 "/" ZBX_FS_UI64 ").",
5587 __func__, maintenance_sec, maintenance_sec2, maintenance_sync.add_num,
5588 maintenance_sync.update_num, maintenance_sync.remove_num);
5589
5590 zabbix_log(LOG_LEVEL_DEBUG, "%s() reindex : " ZBX_FS_DBL " sec.", __func__, update_sec);
5591
5592 zabbix_log(LOG_LEVEL_DEBUG, "%s() total sql : " ZBX_FS_DBL " sec.", __func__, total);
5593 zabbix_log(LOG_LEVEL_DEBUG, "%s() total sync : " ZBX_FS_DBL " sec.", __func__, total2);
5594
5595 zabbix_log(LOG_LEVEL_DEBUG, "%s() proxies : %d (%d slots)", __func__,
5596 config->proxies.num_data, config->proxies.num_slots);
5597 zabbix_log(LOG_LEVEL_DEBUG, "%s() hosts : %d (%d slots)", __func__,
5598 config->hosts.num_data, config->hosts.num_slots);
5599 zabbix_log(LOG_LEVEL_DEBUG, "%s() hosts_h : %d (%d slots)", __func__,
5600 config->hosts_h.num_data, config->hosts_h.num_slots);
5601 zabbix_log(LOG_LEVEL_DEBUG, "%s() hosts_p : %d (%d slots)", __func__,
5602 config->hosts_p.num_data, config->hosts_p.num_slots);
5603 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
5604 zabbix_log(LOG_LEVEL_DEBUG, "%s() psks : %d (%d slots)", __func__,
5605 config->psks.num_data, config->psks.num_slots);
5606 #endif
5607 zabbix_log(LOG_LEVEL_DEBUG, "%s() ipmihosts : %d (%d slots)", __func__,
5608 config->ipmihosts.num_data, config->ipmihosts.num_slots);
5609 zabbix_log(LOG_LEVEL_DEBUG, "%s() host_invent: %d (%d slots)", __func__,
5610 config->host_inventories.num_data, config->host_inventories.num_slots);
5611 zabbix_log(LOG_LEVEL_DEBUG, "%s() htmpls : %d (%d slots)", __func__,
5612 config->htmpls.num_data, config->htmpls.num_slots);
5613 zabbix_log(LOG_LEVEL_DEBUG, "%s() gmacros : %d (%d slots)", __func__,
5614 config->gmacros.num_data, config->gmacros.num_slots);
5615 zabbix_log(LOG_LEVEL_DEBUG, "%s() gmacros_m : %d (%d slots)", __func__,
5616 config->gmacros_m.num_data, config->gmacros_m.num_slots);
5617 zabbix_log(LOG_LEVEL_DEBUG, "%s() hmacros : %d (%d slots)", __func__,
5618 config->hmacros.num_data, config->hmacros.num_slots);
5619 zabbix_log(LOG_LEVEL_DEBUG, "%s() hmacros_hm : %d (%d slots)", __func__,
5620 config->hmacros_hm.num_data, config->hmacros_hm.num_slots);
5621 zabbix_log(LOG_LEVEL_DEBUG, "%s() interfaces : %d (%d slots)", __func__,
5622 config->interfaces.num_data, config->interfaces.num_slots);
5623 zabbix_log(LOG_LEVEL_DEBUG, "%s() interfaces_snmp : %d (%d slots)", __func__,
5624 config->interfaces_snmp.num_data, config->interfaces_snmp.num_slots);
5625 zabbix_log(LOG_LEVEL_DEBUG, "%s() interfac_ht: %d (%d slots)", __func__,
5626 config->interfaces_ht.num_data, config->interfaces_ht.num_slots);
5627 zabbix_log(LOG_LEVEL_DEBUG, "%s() if_snmpitms: %d (%d slots)", __func__,
5628 config->interface_snmpitems.num_data, config->interface_snmpitems.num_slots);
5629 zabbix_log(LOG_LEVEL_DEBUG, "%s() if_snmpaddr: %d (%d slots)", __func__,
5630 config->interface_snmpaddrs.num_data, config->interface_snmpaddrs.num_slots);
5631 zabbix_log(LOG_LEVEL_DEBUG, "%s() items : %d (%d slots)", __func__,
5632 config->items.num_data, config->items.num_slots);
5633 zabbix_log(LOG_LEVEL_DEBUG, "%s() items_hk : %d (%d slots)", __func__,
5634 config->items_hk.num_data, config->items_hk.num_slots);
5635 zabbix_log(LOG_LEVEL_DEBUG, "%s() numitems : %d (%d slots)", __func__,
5636 config->numitems.num_data, config->numitems.num_slots);
5637 zabbix_log(LOG_LEVEL_DEBUG, "%s() preprocitems: %d (%d slots)", __func__,
5638 config->preprocitems.num_data, config->preprocitems.num_slots);
5639 zabbix_log(LOG_LEVEL_DEBUG, "%s() preprocops : %d (%d slots)", __func__,
5640 config->preprocops.num_data, config->preprocops.num_slots);
5641 zabbix_log(LOG_LEVEL_DEBUG, "%s() snmpitems : %d (%d slots)", __func__,
5642 config->snmpitems.num_data, config->snmpitems.num_slots);
5643 zabbix_log(LOG_LEVEL_DEBUG, "%s() ipmiitems : %d (%d slots)", __func__,
5644 config->ipmiitems.num_data, config->ipmiitems.num_slots);
5645 zabbix_log(LOG_LEVEL_DEBUG, "%s() trapitems : %d (%d slots)", __func__,
5646 config->trapitems.num_data, config->trapitems.num_slots);
5647 zabbix_log(LOG_LEVEL_DEBUG, "%s() dependentitems : %d (%d slots)", __func__,
5648 config->dependentitems.num_data, config->dependentitems.num_slots);
5649 zabbix_log(LOG_LEVEL_DEBUG, "%s() logitems : %d (%d slots)", __func__,
5650 config->logitems.num_data, config->logitems.num_slots);
5651 zabbix_log(LOG_LEVEL_DEBUG, "%s() dbitems : %d (%d slots)", __func__,
5652 config->dbitems.num_data, config->dbitems.num_slots);
5653 zabbix_log(LOG_LEVEL_DEBUG, "%s() sshitems : %d (%d slots)", __func__,
5654 config->sshitems.num_data, config->sshitems.num_slots);
5655 zabbix_log(LOG_LEVEL_DEBUG, "%s() telnetitems: %d (%d slots)", __func__,
5656 config->telnetitems.num_data, config->telnetitems.num_slots);
5657 zabbix_log(LOG_LEVEL_DEBUG, "%s() simpleitems: %d (%d slots)", __func__,
5658 config->simpleitems.num_data, config->simpleitems.num_slots);
5659 zabbix_log(LOG_LEVEL_DEBUG, "%s() jmxitems : %d (%d slots)", __func__,
5660 config->jmxitems.num_data, config->jmxitems.num_slots);
5661 zabbix_log(LOG_LEVEL_DEBUG, "%s() calcitems : %d (%d slots)", __func__,
5662 config->calcitems.num_data, config->calcitems.num_slots);
5663 zabbix_log(LOG_LEVEL_DEBUG, "%s() httpitems : %d (%d slots)", __func__,
5664 config->httpitems.num_data, config->httpitems.num_slots);
5665 zabbix_log(LOG_LEVEL_DEBUG, "%s() functions : %d (%d slots)", __func__,
5666 config->functions.num_data, config->functions.num_slots);
5667 zabbix_log(LOG_LEVEL_DEBUG, "%s() triggers : %d (%d slots)", __func__,
5668 config->triggers.num_data, config->triggers.num_slots);
5669 zabbix_log(LOG_LEVEL_DEBUG, "%s() trigdeps : %d (%d slots)", __func__,
5670 config->trigdeps.num_data, config->trigdeps.num_slots);
5671 zabbix_log(LOG_LEVEL_DEBUG, "%s() trig. tags : %d (%d slots)", __func__,
5672 config->trigger_tags.num_data, config->trigger_tags.num_slots);
5673 zabbix_log(LOG_LEVEL_DEBUG, "%s() expressions: %d (%d slots)", __func__,
5674 config->expressions.num_data, config->expressions.num_slots);
5675
5676 zabbix_log(LOG_LEVEL_DEBUG, "%s() actions : %d (%d slots)", __func__,
5677 config->actions.num_data, config->actions.num_slots);
5678 zabbix_log(LOG_LEVEL_DEBUG, "%s() conditions : %d (%d slots)", __func__,
5679 config->action_conditions.num_data, config->action_conditions.num_slots);
5680
5681 zabbix_log(LOG_LEVEL_DEBUG, "%s() corr. : %d (%d slots)", __func__,
5682 config->correlations.num_data, config->correlations.num_slots);
5683 zabbix_log(LOG_LEVEL_DEBUG, "%s() corr. conds: %d (%d slots)", __func__,
5684 config->corr_conditions.num_data, config->corr_conditions.num_slots);
5685 zabbix_log(LOG_LEVEL_DEBUG, "%s() corr. ops : %d (%d slots)", __func__,
5686 config->corr_operations.num_data, config->corr_operations.num_slots);
5687 zabbix_log(LOG_LEVEL_DEBUG, "%s() hgroups : %d (%d slots)", __func__,
5688 config->hostgroups.num_data, config->hostgroups.num_slots);
5689 zabbix_log(LOG_LEVEL_DEBUG, "%s() item procs : %d (%d slots)", __func__,
5690 config->preprocops.num_data, config->preprocops.num_slots);
5691
5692 zabbix_log(LOG_LEVEL_DEBUG, "%s() maintenance: %d (%d slots)", __func__,
5693 config->maintenances.num_data, config->maintenances.num_slots);
5694 zabbix_log(LOG_LEVEL_DEBUG, "%s() maint tags : %d (%d slots)", __func__,
5695 config->maintenance_tags.num_data, config->maintenance_tags.num_slots);
5696 zabbix_log(LOG_LEVEL_DEBUG, "%s() maint time : %d (%d slots)", __func__,
5697 config->maintenance_periods.num_data, config->maintenance_periods.num_slots);
5698
5699 for (i = 0; ZBX_POLLER_TYPE_COUNT > i; i++)
5700 {
5701 zabbix_log(LOG_LEVEL_DEBUG, "%s() queue[%d] : %d (%d allocated)", __func__,
5702 i, config->queues[i].elems_num, config->queues[i].elems_alloc);
5703 }
5704
5705 zabbix_log(LOG_LEVEL_DEBUG, "%s() pqueue : %d (%d allocated)", __func__,
5706 config->pqueue.elems_num, config->pqueue.elems_alloc);
5707
5708 zabbix_log(LOG_LEVEL_DEBUG, "%s() timer queue: %d (%d allocated)", __func__,
5709 config->timer_queue.elems_num, config->timer_queue.elems_alloc);
5710
5711 zabbix_log(LOG_LEVEL_DEBUG, "%s() configfree : " ZBX_FS_DBL "%%", __func__,
5712 100 * ((double)config_mem->free_size / config_mem->orig_size));
5713
5714 zabbix_log(LOG_LEVEL_DEBUG, "%s() strings : %d (%d slots)", __func__,
5715 config->strpool.num_data, config->strpool.num_slots);
5716
5717 zbx_mem_dump_stats(LOG_LEVEL_DEBUG, config_mem);
5718 }
5719 out:
5720 if (0 == sync_in_progress)
5721 {
5722 /* non recoverable database error is encountered */
5723 THIS_SHOULD_NEVER_HAPPEN;
5724 START_SYNC;
5725 }
5726
5727 config->status->last_update = 0;
5728 config->sync_ts = time(NULL);
5729
5730 FINISH_SYNC;
5731
5732 zbx_dbsync_clear(&config_sync);
5733 zbx_dbsync_clear(&autoreg_config_sync);
5734 zbx_dbsync_clear(&hosts_sync);
5735 zbx_dbsync_clear(&hi_sync);
5736 zbx_dbsync_clear(&htmpl_sync);
5737 zbx_dbsync_clear(&gmacro_sync);
5738 zbx_dbsync_clear(&hmacro_sync);
5739 zbx_dbsync_clear(&host_tag_sync);
5740 zbx_dbsync_clear(&if_sync);
5741 zbx_dbsync_clear(&items_sync);
5742 zbx_dbsync_clear(&template_items_sync);
5743 zbx_dbsync_clear(&prototype_items_sync);
5744 zbx_dbsync_clear(&triggers_sync);
5745 zbx_dbsync_clear(&tdep_sync);
5746 zbx_dbsync_clear(&func_sync);
5747 zbx_dbsync_clear(&expr_sync);
5748 zbx_dbsync_clear(&action_sync);
5749 zbx_dbsync_clear(&action_op_sync);
5750 zbx_dbsync_clear(&action_condition_sync);
5751 zbx_dbsync_clear(&trigger_tag_sync);
5752 zbx_dbsync_clear(&correlation_sync);
5753 zbx_dbsync_clear(&corr_condition_sync);
5754 zbx_dbsync_clear(&corr_operation_sync);
5755 zbx_dbsync_clear(&hgroups_sync);
5756 zbx_dbsync_clear(&itempp_sync);
5757 zbx_dbsync_clear(&maintenance_sync);
5758 zbx_dbsync_clear(&maintenance_period_sync);
5759 zbx_dbsync_clear(&maintenance_tag_sync);
5760 zbx_dbsync_clear(&maintenance_group_sync);
5761 zbx_dbsync_clear(&maintenance_host_sync);
5762 zbx_dbsync_clear(&hgroup_host_sync);
5763
5764 zbx_dbsync_free_env();
5765
5766 if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_TRACE))
5767 DCdump_configuration();
5768
5769 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
5770 }
5771
5772 /******************************************************************************
5773 * *
5774 * Helper functions for configuration cache data structure element comparison *
5775 * and hash value calculation. *
5776 * *
5777 * The __config_mem_XXX_func(), __config_XXX_hash and __config_XXX_compare *
5778 * functions are used only inside init_configuration_cache() function to *
5779 * initialize internal data structures. *
5780 * *
5781 ******************************************************************************/
5782
__config_item_hk_hash(const void * data)5783 static zbx_hash_t __config_item_hk_hash(const void *data)
5784 {
5785 const ZBX_DC_ITEM_HK *item_hk = (const ZBX_DC_ITEM_HK *)data;
5786
5787 zbx_hash_t hash;
5788
5789 hash = ZBX_DEFAULT_UINT64_HASH_FUNC(&item_hk->hostid);
5790 hash = ZBX_DEFAULT_STRING_HASH_ALGO(item_hk->key, strlen(item_hk->key), hash);
5791
5792 return hash;
5793 }
5794
__config_item_hk_compare(const void * d1,const void * d2)5795 static int __config_item_hk_compare(const void *d1, const void *d2)
5796 {
5797 const ZBX_DC_ITEM_HK *item_hk_1 = (const ZBX_DC_ITEM_HK *)d1;
5798 const ZBX_DC_ITEM_HK *item_hk_2 = (const ZBX_DC_ITEM_HK *)d2;
5799
5800 ZBX_RETURN_IF_NOT_EQUAL(item_hk_1->hostid, item_hk_2->hostid);
5801
5802 return item_hk_1->key == item_hk_2->key ? 0 : strcmp(item_hk_1->key, item_hk_2->key);
5803 }
5804
__config_host_h_hash(const void * data)5805 static zbx_hash_t __config_host_h_hash(const void *data)
5806 {
5807 const ZBX_DC_HOST_H *host_h = (const ZBX_DC_HOST_H *)data;
5808
5809 return ZBX_DEFAULT_STRING_HASH_ALGO(host_h->host, strlen(host_h->host), ZBX_DEFAULT_HASH_SEED);
5810 }
5811
__config_host_h_compare(const void * d1,const void * d2)5812 static int __config_host_h_compare(const void *d1, const void *d2)
5813 {
5814 const ZBX_DC_HOST_H *host_h_1 = (const ZBX_DC_HOST_H *)d1;
5815 const ZBX_DC_HOST_H *host_h_2 = (const ZBX_DC_HOST_H *)d2;
5816
5817 return host_h_1->host == host_h_2->host ? 0 : strcmp(host_h_1->host, host_h_2->host);
5818 }
5819
__config_gmacro_m_hash(const void * data)5820 static zbx_hash_t __config_gmacro_m_hash(const void *data)
5821 {
5822 const ZBX_DC_GMACRO_M *gmacro_m = (const ZBX_DC_GMACRO_M *)data;
5823
5824 zbx_hash_t hash;
5825
5826 hash = ZBX_DEFAULT_STRING_HASH_FUNC(gmacro_m->macro);
5827
5828 return hash;
5829 }
5830
__config_gmacro_m_compare(const void * d1,const void * d2)5831 static int __config_gmacro_m_compare(const void *d1, const void *d2)
5832 {
5833 const ZBX_DC_GMACRO_M *gmacro_m_1 = (const ZBX_DC_GMACRO_M *)d1;
5834 const ZBX_DC_GMACRO_M *gmacro_m_2 = (const ZBX_DC_GMACRO_M *)d2;
5835
5836 return gmacro_m_1->macro == gmacro_m_2->macro ? 0 : strcmp(gmacro_m_1->macro, gmacro_m_2->macro);
5837 }
5838
__config_hmacro_hm_hash(const void * data)5839 static zbx_hash_t __config_hmacro_hm_hash(const void *data)
5840 {
5841 const ZBX_DC_HMACRO_HM *hmacro_hm = (const ZBX_DC_HMACRO_HM *)data;
5842
5843 zbx_hash_t hash;
5844
5845 hash = ZBX_DEFAULT_UINT64_HASH_FUNC(&hmacro_hm->hostid);
5846 hash = ZBX_DEFAULT_STRING_HASH_ALGO(hmacro_hm->macro, strlen(hmacro_hm->macro), hash);
5847
5848 return hash;
5849 }
5850
__config_hmacro_hm_compare(const void * d1,const void * d2)5851 static int __config_hmacro_hm_compare(const void *d1, const void *d2)
5852 {
5853 const ZBX_DC_HMACRO_HM *hmacro_hm_1 = (const ZBX_DC_HMACRO_HM *)d1;
5854 const ZBX_DC_HMACRO_HM *hmacro_hm_2 = (const ZBX_DC_HMACRO_HM *)d2;
5855
5856 ZBX_RETURN_IF_NOT_EQUAL(hmacro_hm_1->hostid, hmacro_hm_2->hostid);
5857
5858 return hmacro_hm_1->macro == hmacro_hm_2->macro ? 0 : strcmp(hmacro_hm_1->macro, hmacro_hm_2->macro);
5859 }
5860
__config_interface_ht_hash(const void * data)5861 static zbx_hash_t __config_interface_ht_hash(const void *data)
5862 {
5863 const ZBX_DC_INTERFACE_HT *interface_ht = (const ZBX_DC_INTERFACE_HT *)data;
5864
5865 zbx_hash_t hash;
5866
5867 hash = ZBX_DEFAULT_UINT64_HASH_FUNC(&interface_ht->hostid);
5868 hash = ZBX_DEFAULT_STRING_HASH_ALGO((char *)&interface_ht->type, 1, hash);
5869
5870 return hash;
5871 }
5872
__config_interface_ht_compare(const void * d1,const void * d2)5873 static int __config_interface_ht_compare(const void *d1, const void *d2)
5874 {
5875 const ZBX_DC_INTERFACE_HT *interface_ht_1 = (const ZBX_DC_INTERFACE_HT *)d1;
5876 const ZBX_DC_INTERFACE_HT *interface_ht_2 = (const ZBX_DC_INTERFACE_HT *)d2;
5877
5878 ZBX_RETURN_IF_NOT_EQUAL(interface_ht_1->hostid, interface_ht_2->hostid);
5879 ZBX_RETURN_IF_NOT_EQUAL(interface_ht_1->type, interface_ht_2->type);
5880
5881 return 0;
5882 }
5883
__config_interface_addr_hash(const void * data)5884 static zbx_hash_t __config_interface_addr_hash(const void *data)
5885 {
5886 const ZBX_DC_INTERFACE_ADDR *interface_addr = (const ZBX_DC_INTERFACE_ADDR *)data;
5887
5888 return ZBX_DEFAULT_STRING_HASH_ALGO(interface_addr->addr, strlen(interface_addr->addr), ZBX_DEFAULT_HASH_SEED);
5889 }
5890
__config_interface_addr_compare(const void * d1,const void * d2)5891 static int __config_interface_addr_compare(const void *d1, const void *d2)
5892 {
5893 const ZBX_DC_INTERFACE_ADDR *interface_addr_1 = (const ZBX_DC_INTERFACE_ADDR *)d1;
5894 const ZBX_DC_INTERFACE_ADDR *interface_addr_2 = (const ZBX_DC_INTERFACE_ADDR *)d2;
5895
5896 return (interface_addr_1->addr == interface_addr_2->addr ? 0 : strcmp(interface_addr_1->addr, interface_addr_2->addr));
5897 }
5898
__config_snmp_item_compare(const ZBX_DC_ITEM * i1,const ZBX_DC_ITEM * i2)5899 static int __config_snmp_item_compare(const ZBX_DC_ITEM *i1, const ZBX_DC_ITEM *i2)
5900 {
5901 const ZBX_DC_SNMPITEM *s1;
5902 const ZBX_DC_SNMPITEM *s2;
5903
5904 unsigned char f1;
5905 unsigned char f2;
5906
5907 ZBX_RETURN_IF_NOT_EQUAL(i1->interfaceid, i2->interfaceid);
5908 ZBX_RETURN_IF_NOT_EQUAL(i1->type, i2->type);
5909
5910 f1 = ZBX_FLAG_DISCOVERY_RULE & i1->flags;
5911 f2 = ZBX_FLAG_DISCOVERY_RULE & i2->flags;
5912
5913 ZBX_RETURN_IF_NOT_EQUAL(f1, f2);
5914
5915 s1 = (ZBX_DC_SNMPITEM *)zbx_hashset_search(&config->snmpitems, &i1->itemid);
5916 s2 = (ZBX_DC_SNMPITEM *)zbx_hashset_search(&config->snmpitems, &i2->itemid);
5917
5918 ZBX_RETURN_IF_NOT_EQUAL(s1->snmp_oid_type, s2->snmp_oid_type);
5919
5920 return 0;
5921 }
5922
__config_heap_elem_compare(const void * d1,const void * d2)5923 static int __config_heap_elem_compare(const void *d1, const void *d2)
5924 {
5925 const zbx_binary_heap_elem_t *e1 = (const zbx_binary_heap_elem_t *)d1;
5926 const zbx_binary_heap_elem_t *e2 = (const zbx_binary_heap_elem_t *)d2;
5927
5928 const ZBX_DC_ITEM *i1 = (const ZBX_DC_ITEM *)e1->data;
5929 const ZBX_DC_ITEM *i2 = (const ZBX_DC_ITEM *)e2->data;
5930
5931 ZBX_RETURN_IF_NOT_EQUAL(i1->nextcheck, i2->nextcheck);
5932 ZBX_RETURN_IF_NOT_EQUAL(i1->queue_priority, i2->queue_priority);
5933
5934 if (ITEM_TYPE_SNMP != i1->type)
5935 {
5936 if (ITEM_TYPE_SNMP != i2->type)
5937 return 0;
5938
5939 return -1;
5940 }
5941 else
5942 {
5943 if (ITEM_TYPE_SNMP != i2->type)
5944 return +1;
5945
5946 return __config_snmp_item_compare(i1, i2);
5947 }
5948 }
5949
__config_pinger_elem_compare(const void * d1,const void * d2)5950 static int __config_pinger_elem_compare(const void *d1, const void *d2)
5951 {
5952 const zbx_binary_heap_elem_t *e1 = (const zbx_binary_heap_elem_t *)d1;
5953 const zbx_binary_heap_elem_t *e2 = (const zbx_binary_heap_elem_t *)d2;
5954
5955 const ZBX_DC_ITEM *i1 = (const ZBX_DC_ITEM *)e1->data;
5956 const ZBX_DC_ITEM *i2 = (const ZBX_DC_ITEM *)e2->data;
5957
5958 ZBX_RETURN_IF_NOT_EQUAL(i1->nextcheck, i2->nextcheck);
5959 ZBX_RETURN_IF_NOT_EQUAL(i1->queue_priority, i2->queue_priority);
5960 ZBX_RETURN_IF_NOT_EQUAL(i1->interfaceid, i2->interfaceid);
5961
5962 return 0;
5963 }
5964
__config_java_item_compare(const ZBX_DC_ITEM * i1,const ZBX_DC_ITEM * i2)5965 static int __config_java_item_compare(const ZBX_DC_ITEM *i1, const ZBX_DC_ITEM *i2)
5966 {
5967 const ZBX_DC_JMXITEM *j1;
5968 const ZBX_DC_JMXITEM *j2;
5969
5970 ZBX_RETURN_IF_NOT_EQUAL(i1->interfaceid, i2->interfaceid);
5971
5972 j1 = (ZBX_DC_JMXITEM *)zbx_hashset_search(&config->jmxitems, &i1->itemid);
5973 j2 = (ZBX_DC_JMXITEM *)zbx_hashset_search(&config->jmxitems, &i2->itemid);
5974
5975 ZBX_RETURN_IF_NOT_EQUAL(j1->username, j2->username);
5976 ZBX_RETURN_IF_NOT_EQUAL(j1->password, j2->password);
5977 ZBX_RETURN_IF_NOT_EQUAL(j1->jmx_endpoint, j2->jmx_endpoint);
5978
5979 return 0;
5980 }
5981
__config_java_elem_compare(const void * d1,const void * d2)5982 static int __config_java_elem_compare(const void *d1, const void *d2)
5983 {
5984 const zbx_binary_heap_elem_t *e1 = (const zbx_binary_heap_elem_t *)d1;
5985 const zbx_binary_heap_elem_t *e2 = (const zbx_binary_heap_elem_t *)d2;
5986
5987 const ZBX_DC_ITEM *i1 = (const ZBX_DC_ITEM *)e1->data;
5988 const ZBX_DC_ITEM *i2 = (const ZBX_DC_ITEM *)e2->data;
5989
5990 ZBX_RETURN_IF_NOT_EQUAL(i1->nextcheck, i2->nextcheck);
5991 ZBX_RETURN_IF_NOT_EQUAL(i1->queue_priority, i2->queue_priority);
5992
5993 return __config_java_item_compare(i1, i2);
5994 }
5995
__config_proxy_compare(const void * d1,const void * d2)5996 static int __config_proxy_compare(const void *d1, const void *d2)
5997 {
5998 const zbx_binary_heap_elem_t *e1 = (const zbx_binary_heap_elem_t *)d1;
5999 const zbx_binary_heap_elem_t *e2 = (const zbx_binary_heap_elem_t *)d2;
6000
6001 const ZBX_DC_PROXY *p1 = (const ZBX_DC_PROXY *)e1->data;
6002 const ZBX_DC_PROXY *p2 = (const ZBX_DC_PROXY *)e2->data;
6003
6004 ZBX_RETURN_IF_NOT_EQUAL(p1->nextcheck, p2->nextcheck);
6005
6006 return 0;
6007 }
6008
6009 /* hash and compare functions for expressions hashset */
6010
__config_regexp_hash(const void * data)6011 static zbx_hash_t __config_regexp_hash(const void *data)
6012 {
6013 const ZBX_DC_REGEXP *regexp = (const ZBX_DC_REGEXP *)data;
6014
6015 return ZBX_DEFAULT_STRING_HASH_FUNC(regexp->name);
6016 }
6017
__config_regexp_compare(const void * d1,const void * d2)6018 static int __config_regexp_compare(const void *d1, const void *d2)
6019 {
6020 const ZBX_DC_REGEXP *r1 = (const ZBX_DC_REGEXP *)d1;
6021 const ZBX_DC_REGEXP *r2 = (const ZBX_DC_REGEXP *)d2;
6022
6023 return r1->name == r2->name ? 0 : strcmp(r1->name, r2->name);
6024 }
6025
6026 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
__config_psk_hash(const void * data)6027 static zbx_hash_t __config_psk_hash(const void *data)
6028 {
6029 const ZBX_DC_PSK *psk_i = (const ZBX_DC_PSK *)data;
6030
6031 return ZBX_DEFAULT_STRING_HASH_ALGO(psk_i->tls_psk_identity, strlen(psk_i->tls_psk_identity),
6032 ZBX_DEFAULT_HASH_SEED);
6033 }
6034
__config_psk_compare(const void * d1,const void * d2)6035 static int __config_psk_compare(const void *d1, const void *d2)
6036 {
6037 const ZBX_DC_PSK *psk_1 = (const ZBX_DC_PSK *)d1;
6038 const ZBX_DC_PSK *psk_2 = (const ZBX_DC_PSK *)d2;
6039
6040 return psk_1->tls_psk_identity == psk_2->tls_psk_identity ? 0 : strcmp(psk_1->tls_psk_identity,
6041 psk_2->tls_psk_identity);
6042 }
6043 #endif
6044
__config_timer_compare(const void * d1,const void * d2)6045 static int __config_timer_compare(const void *d1, const void *d2)
6046 {
6047 const zbx_binary_heap_elem_t *e1 = (const zbx_binary_heap_elem_t *)d1;
6048 const zbx_binary_heap_elem_t *e2 = (const zbx_binary_heap_elem_t *)d2;
6049
6050 const ZBX_DC_TRIGGER *t1 = (const ZBX_DC_TRIGGER *)e1->data;
6051 const ZBX_DC_TRIGGER *t2 = (const ZBX_DC_TRIGGER *)e2->data;
6052
6053 ZBX_RETURN_IF_NOT_EQUAL(t1->nextcheck, t2->nextcheck);
6054
6055 return 0;
6056 }
6057
__config_data_session_hash(const void * data)6058 static zbx_hash_t __config_data_session_hash(const void *data)
6059 {
6060 const zbx_data_session_t *session = (const zbx_data_session_t *)data;
6061 zbx_hash_t hash;
6062
6063 hash = ZBX_DEFAULT_UINT64_HASH_FUNC(&session->hostid);
6064 return ZBX_DEFAULT_STRING_HASH_ALGO(session->token, strlen(session->token), hash);
6065 }
6066
__config_data_session_compare(const void * d1,const void * d2)6067 static int __config_data_session_compare(const void *d1, const void *d2)
6068 {
6069 const zbx_data_session_t *s1 = (const zbx_data_session_t *)d1;
6070 const zbx_data_session_t *s2 = (const zbx_data_session_t *)d2;
6071
6072 ZBX_RETURN_IF_NOT_EQUAL(s1->hostid, s2->hostid);
6073 return strcmp(s1->token, s2->token);
6074 }
6075
6076 /******************************************************************************
6077 * *
6078 * Function: init_configuration_cache *
6079 * *
6080 * Purpose: Allocate shared memory for configuration cache *
6081 * *
6082 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
6083 * *
6084 ******************************************************************************/
init_configuration_cache(char ** error)6085 int init_configuration_cache(char **error)
6086 {
6087 int i, ret;
6088
6089 zabbix_log(LOG_LEVEL_DEBUG, "In %s() size:" ZBX_FS_UI64, __func__, CONFIG_CONF_CACHE_SIZE);
6090
6091 if (SUCCEED != (ret = zbx_rwlock_create(&config_lock, ZBX_RWLOCK_CONFIG, error)))
6092 goto out;
6093
6094 if (SUCCEED != (ret = zbx_mem_create(&config_mem, CONFIG_CONF_CACHE_SIZE, "configuration cache",
6095 "CacheSize", 0, error)))
6096 {
6097 goto out;
6098 }
6099
6100 config = (ZBX_DC_CONFIG *)__config_mem_malloc_func(NULL, sizeof(ZBX_DC_CONFIG) +
6101 CONFIG_TIMER_FORKS * sizeof(zbx_vector_ptr_t));
6102
6103 #define CREATE_HASHSET(hashset, hashset_size) \
6104 \
6105 CREATE_HASHSET_EXT(hashset, hashset_size, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC)
6106
6107 #define CREATE_HASHSET_EXT(hashset, hashset_size, hash_func, compare_func) \
6108 \
6109 zbx_hashset_create_ext(&hashset, hashset_size, hash_func, compare_func, NULL, \
6110 __config_mem_malloc_func, __config_mem_realloc_func, __config_mem_free_func)
6111
6112 CREATE_HASHSET(config->items, 100);
6113 CREATE_HASHSET(config->numitems, 0);
6114 CREATE_HASHSET(config->snmpitems, 0);
6115 CREATE_HASHSET(config->ipmiitems, 0);
6116 CREATE_HASHSET(config->trapitems, 0);
6117 CREATE_HASHSET(config->dependentitems, 0);
6118 CREATE_HASHSET(config->logitems, 0);
6119 CREATE_HASHSET(config->dbitems, 0);
6120 CREATE_HASHSET(config->sshitems, 0);
6121 CREATE_HASHSET(config->telnetitems, 0);
6122 CREATE_HASHSET(config->simpleitems, 0);
6123 CREATE_HASHSET(config->jmxitems, 0);
6124 CREATE_HASHSET(config->calcitems, 0);
6125 CREATE_HASHSET(config->masteritems, 0);
6126 CREATE_HASHSET(config->preprocitems, 0);
6127 CREATE_HASHSET(config->httpitems, 0);
6128 CREATE_HASHSET(config->template_items, 0);
6129 CREATE_HASHSET(config->prototype_items, 0);
6130 CREATE_HASHSET(config->functions, 100);
6131 CREATE_HASHSET(config->triggers, 100);
6132 CREATE_HASHSET(config->trigdeps, 0);
6133 CREATE_HASHSET(config->hosts, 10);
6134 CREATE_HASHSET(config->proxies, 0);
6135 CREATE_HASHSET(config->host_inventories, 0);
6136 CREATE_HASHSET(config->host_inventories_auto, 0);
6137 CREATE_HASHSET(config->ipmihosts, 0);
6138 CREATE_HASHSET(config->htmpls, 0);
6139 CREATE_HASHSET(config->gmacros, 0);
6140 CREATE_HASHSET(config->hmacros, 0);
6141 CREATE_HASHSET(config->interfaces, 10);
6142 CREATE_HASHSET(config->interfaces_snmp, 0);
6143 CREATE_HASHSET(config->interface_snmpitems, 0);
6144 CREATE_HASHSET(config->expressions, 0);
6145 CREATE_HASHSET(config->actions, 0);
6146 CREATE_HASHSET(config->action_conditions, 0);
6147 CREATE_HASHSET(config->trigger_tags, 0);
6148 CREATE_HASHSET(config->host_tags, 0);
6149 CREATE_HASHSET(config->host_tags_index, 0);
6150 CREATE_HASHSET(config->correlations, 0);
6151 CREATE_HASHSET(config->corr_conditions, 0);
6152 CREATE_HASHSET(config->corr_operations, 0);
6153 CREATE_HASHSET(config->hostgroups, 0);
6154 zbx_vector_ptr_create_ext(&config->hostgroups_name, __config_mem_malloc_func, __config_mem_realloc_func,
6155 __config_mem_free_func);
6156
6157 CREATE_HASHSET(config->preprocops, 0);
6158
6159 CREATE_HASHSET(config->maintenances, 0);
6160 CREATE_HASHSET(config->maintenance_periods, 0);
6161 CREATE_HASHSET(config->maintenance_tags, 0);
6162
6163 CREATE_HASHSET_EXT(config->items_hk, 100, __config_item_hk_hash, __config_item_hk_compare);
6164 CREATE_HASHSET_EXT(config->hosts_h, 10, __config_host_h_hash, __config_host_h_compare);
6165 CREATE_HASHSET_EXT(config->hosts_p, 0, __config_host_h_hash, __config_host_h_compare);
6166 CREATE_HASHSET_EXT(config->gmacros_m, 0, __config_gmacro_m_hash, __config_gmacro_m_compare);
6167 CREATE_HASHSET_EXT(config->hmacros_hm, 0, __config_hmacro_hm_hash, __config_hmacro_hm_compare);
6168 CREATE_HASHSET_EXT(config->interfaces_ht, 10, __config_interface_ht_hash, __config_interface_ht_compare);
6169 CREATE_HASHSET_EXT(config->interface_snmpaddrs, 0, __config_interface_addr_hash, __config_interface_addr_compare);
6170 CREATE_HASHSET_EXT(config->regexps, 0, __config_regexp_hash, __config_regexp_compare);
6171
6172 CREATE_HASHSET_EXT(config->strpool, 100, __config_strpool_hash, __config_strpool_compare);
6173
6174 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
6175 CREATE_HASHSET_EXT(config->psks, 0, __config_psk_hash, __config_psk_compare);
6176 #endif
6177
6178 for (i = 0; i < ZBX_POLLER_TYPE_COUNT; i++)
6179 {
6180 switch (i)
6181 {
6182 case ZBX_POLLER_TYPE_JAVA:
6183 zbx_binary_heap_create_ext(&config->queues[i],
6184 __config_java_elem_compare,
6185 ZBX_BINARY_HEAP_OPTION_DIRECT,
6186 __config_mem_malloc_func,
6187 __config_mem_realloc_func,
6188 __config_mem_free_func);
6189 break;
6190 case ZBX_POLLER_TYPE_PINGER:
6191 zbx_binary_heap_create_ext(&config->queues[i],
6192 __config_pinger_elem_compare,
6193 ZBX_BINARY_HEAP_OPTION_DIRECT,
6194 __config_mem_malloc_func,
6195 __config_mem_realloc_func,
6196 __config_mem_free_func);
6197 break;
6198 default:
6199 zbx_binary_heap_create_ext(&config->queues[i],
6200 __config_heap_elem_compare,
6201 ZBX_BINARY_HEAP_OPTION_DIRECT,
6202 __config_mem_malloc_func,
6203 __config_mem_realloc_func,
6204 __config_mem_free_func);
6205 break;
6206 }
6207 }
6208
6209 zbx_binary_heap_create_ext(&config->pqueue,
6210 __config_proxy_compare,
6211 ZBX_BINARY_HEAP_OPTION_DIRECT,
6212 __config_mem_malloc_func,
6213 __config_mem_realloc_func,
6214 __config_mem_free_func);
6215
6216 zbx_binary_heap_create_ext(&config->timer_queue,
6217 __config_timer_compare,
6218 ZBX_BINARY_HEAP_OPTION_DIRECT,
6219 __config_mem_malloc_func,
6220 __config_mem_realloc_func,
6221 __config_mem_free_func);
6222
6223 CREATE_HASHSET_EXT(config->data_sessions, 0, __config_data_session_hash, __config_data_session_compare);
6224
6225 config->config = NULL;
6226
6227 config->status = (ZBX_DC_STATUS *)__config_mem_malloc_func(NULL, sizeof(ZBX_DC_STATUS));
6228 config->status->last_update = 0;
6229
6230 config->availability_diff_ts = 0;
6231 config->sync_ts = 0;
6232 config->item_sync_ts = 0;
6233
6234 config->internal_actions = 0;
6235
6236 /* maintenance data are used only when timers are defined (server) */
6237 if (0 != CONFIG_TIMER_FORKS)
6238 {
6239 config->maintenance_update = ZBX_MAINTENANCE_UPDATE_FALSE;
6240 config->maintenance_update_flags = (zbx_uint64_t *)__config_mem_malloc_func(NULL, sizeof(zbx_uint64_t) *
6241 ZBX_MAINTENANCE_UPDATE_FLAGS_NUM());
6242 memset(config->maintenance_update_flags, 0, sizeof(zbx_uint64_t) * ZBX_MAINTENANCE_UPDATE_FLAGS_NUM());
6243 }
6244
6245 config->proxy_lastaccess_ts = time(NULL);
6246
6247 /* create data session token for proxies */
6248 if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY))
6249 {
6250 char *token;
6251
6252 token = zbx_create_token(0);
6253 config->session_token = dc_strdup(token);
6254 zbx_free(token);
6255 }
6256 else
6257 config->session_token = NULL;
6258
6259 #undef CREATE_HASHSET
6260 #undef CREATE_HASHSET_EXT
6261 out:
6262 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
6263
6264 return ret;
6265 }
6266
6267 /******************************************************************************
6268 * *
6269 * Function: free_configuration_cache *
6270 * *
6271 * Purpose: Free memory allocated for configuration cache *
6272 * *
6273 * Author: Alexei Vladishev, Aleksandrs Saveljevs *
6274 * *
6275 ******************************************************************************/
free_configuration_cache(void)6276 void free_configuration_cache(void)
6277 {
6278 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
6279
6280 WRLOCK_CACHE;
6281
6282 config = NULL;
6283
6284 UNLOCK_CACHE;
6285
6286 zbx_rwlock_destroy(&config_lock);
6287
6288 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
6289 }
6290
6291 /******************************************************************************
6292 * *
6293 * Function: in_maintenance_without_data_collection *
6294 * *
6295 * Parameters: maintenance_status - [IN] maintenance status *
6296 * HOST_MAINTENANCE_STATUS_* flag *
6297 * maintenance_type - [IN] maintenance type *
6298 * MAINTENANCE_TYPE_* flag *
6299 * type - [IN] item type *
6300 * ITEM_TYPE_* flag *
6301 * *
6302 * Return value: SUCCEED if host in maintenance without data collection *
6303 * FAIL otherwise *
6304 * *
6305 ******************************************************************************/
in_maintenance_without_data_collection(unsigned char maintenance_status,unsigned char maintenance_type,unsigned char type)6306 int in_maintenance_without_data_collection(unsigned char maintenance_status, unsigned char maintenance_type,
6307 unsigned char type)
6308 {
6309 if (HOST_MAINTENANCE_STATUS_ON != maintenance_status)
6310 return FAIL;
6311
6312 if (MAINTENANCE_TYPE_NODATA != maintenance_type)
6313 return FAIL;
6314
6315 if (ITEM_TYPE_INTERNAL == type)
6316 return FAIL;
6317
6318 return SUCCEED;
6319 }
6320
DCget_host(DC_HOST * dst_host,const ZBX_DC_HOST * src_host,unsigned int mode)6321 static void DCget_host(DC_HOST *dst_host, const ZBX_DC_HOST *src_host, unsigned int mode)
6322 {
6323 const ZBX_DC_IPMIHOST *ipmihost;
6324 const ZBX_DC_HOST_INVENTORY *host_inventory;
6325
6326 dst_host->hostid = src_host->hostid;
6327 dst_host->proxy_hostid = src_host->proxy_hostid;
6328 dst_host->status = src_host->status;
6329
6330 strscpy(dst_host->host, src_host->host);
6331
6332 if (ZBX_ITEM_GET_HOSTNAME & mode)
6333 zbx_strlcpy_utf8(dst_host->name, src_host->name, sizeof(dst_host->name));
6334
6335 if (ZBX_ITEM_GET_MAINTENANCE & mode)
6336 {
6337 dst_host->maintenance_status = src_host->maintenance_status;
6338 dst_host->maintenance_type = src_host->maintenance_type;
6339 dst_host->maintenance_from = src_host->maintenance_from;
6340 }
6341
6342 if (ZBX_ITEM_GET_HOSTINFO & mode)
6343 {
6344 dst_host->errors_from = src_host->errors_from;
6345 dst_host->available = src_host->available;
6346 dst_host->disable_until = src_host->disable_until;
6347 dst_host->snmp_errors_from = src_host->snmp_errors_from;
6348 dst_host->snmp_available = src_host->snmp_available;
6349 dst_host->snmp_disable_until = src_host->snmp_disable_until;
6350 dst_host->ipmi_errors_from = src_host->ipmi_errors_from;
6351 dst_host->ipmi_available = src_host->ipmi_available;
6352 dst_host->ipmi_disable_until = src_host->ipmi_disable_until;
6353 dst_host->jmx_errors_from = src_host->jmx_errors_from;
6354 dst_host->jmx_available = src_host->jmx_available;
6355 dst_host->jmx_disable_until = src_host->jmx_disable_until;
6356 strscpy(dst_host->error, src_host->error);
6357 strscpy(dst_host->snmp_error, src_host->snmp_error);
6358 strscpy(dst_host->ipmi_error, src_host->ipmi_error);
6359 strscpy(dst_host->jmx_error, src_host->jmx_error);
6360 dst_host->tls_connect = src_host->tls_connect;
6361 dst_host->tls_accept = src_host->tls_accept;
6362 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
6363 strscpy(dst_host->tls_issuer, src_host->tls_issuer);
6364 strscpy(dst_host->tls_subject, src_host->tls_subject);
6365
6366 if (NULL == src_host->tls_dc_psk)
6367 {
6368 *dst_host->tls_psk_identity = '\0';
6369 *dst_host->tls_psk = '\0';
6370 }
6371 else
6372 {
6373 strscpy(dst_host->tls_psk_identity, src_host->tls_dc_psk->tls_psk_identity);
6374 strscpy(dst_host->tls_psk, src_host->tls_dc_psk->tls_psk);
6375 }
6376 #endif
6377 if (NULL != (ipmihost = (ZBX_DC_IPMIHOST *)zbx_hashset_search(&config->ipmihosts, &src_host->hostid)))
6378 {
6379 dst_host->ipmi_authtype = ipmihost->ipmi_authtype;
6380 dst_host->ipmi_privilege = ipmihost->ipmi_privilege;
6381 strscpy(dst_host->ipmi_username, ipmihost->ipmi_username);
6382 strscpy(dst_host->ipmi_password, ipmihost->ipmi_password);
6383 }
6384 else
6385 {
6386 dst_host->ipmi_authtype = ZBX_IPMI_DEFAULT_AUTHTYPE;
6387 dst_host->ipmi_privilege = ZBX_IPMI_DEFAULT_PRIVILEGE;
6388 *dst_host->ipmi_username = '\0';
6389 *dst_host->ipmi_password = '\0';
6390 }
6391 }
6392
6393 if (ZBX_ITEM_GET_INVENTORY & mode)
6394 {
6395 if (NULL != (host_inventory = (ZBX_DC_HOST_INVENTORY *)zbx_hashset_search(&config->host_inventories, &src_host->hostid)))
6396 dst_host->inventory_mode = (char)host_inventory->inventory_mode;
6397 else
6398 dst_host->inventory_mode = HOST_INVENTORY_DISABLED;
6399 }
6400 }
6401
6402 /******************************************************************************
6403 * *
6404 * Function: DCget_host_by_hostid *
6405 * *
6406 * Purpose: Locate host in configuration cache *
6407 * *
6408 * Parameters: host - [OUT] pointer to DC_HOST structure *
6409 * hostid - [IN] host ID from database *
6410 * *
6411 * Return value: SUCCEED if record located and FAIL otherwise *
6412 * *
6413 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
6414 * *
6415 ******************************************************************************/
DCget_host_by_hostid(DC_HOST * host,zbx_uint64_t hostid)6416 int DCget_host_by_hostid(DC_HOST *host, zbx_uint64_t hostid)
6417 {
6418 int ret = FAIL;
6419 const ZBX_DC_HOST *dc_host;
6420
6421 RDLOCK_CACHE;
6422
6423 if (NULL != (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)))
6424 {
6425 DCget_host(host, dc_host, ZBX_ITEM_GET_ALL);
6426 ret = SUCCEED;
6427 }
6428
6429 UNLOCK_CACHE;
6430
6431 return ret;
6432 }
6433
6434 /******************************************************************************
6435 * *
6436 * Function: DCcheck_proxy_permissions *
6437 * *
6438 * Purpose: *
6439 * Check access rights for an active proxy and get the proxy ID *
6440 * *
6441 * Parameters: *
6442 * host - [IN] proxy name *
6443 * sock - [IN] connection socket context *
6444 * hostid - [OUT] proxy ID found in configuration cache *
6445 * error - [OUT] error message why access was denied *
6446 * *
6447 * Return value: *
6448 * SUCCEED - access is allowed, FAIL - access denied *
6449 * *
6450 * Comments: *
6451 * Generating of error messages is done outside of configuration cache *
6452 * locking. *
6453 * *
6454 ******************************************************************************/
DCcheck_proxy_permissions(const char * host,const zbx_socket_t * sock,zbx_uint64_t * hostid,char ** error)6455 int DCcheck_proxy_permissions(const char *host, const zbx_socket_t *sock, zbx_uint64_t *hostid, char **error)
6456 {
6457 const ZBX_DC_HOST *dc_host;
6458 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
6459 zbx_tls_conn_attr_t attr;
6460
6461 if (ZBX_TCP_SEC_TLS_CERT == sock->connection_type)
6462 {
6463 if (SUCCEED != zbx_tls_get_attr_cert(sock, &attr))
6464 {
6465 *error = zbx_strdup(*error, "internal error: cannot get connection attributes");
6466 THIS_SHOULD_NEVER_HAPPEN;
6467 return FAIL;
6468 }
6469 }
6470 #if defined(HAVE_GNUTLS) || (defined(HAVE_OPENSSL) && defined(HAVE_OPENSSL_WITH_PSK))
6471 else if (ZBX_TCP_SEC_TLS_PSK == sock->connection_type)
6472 {
6473 if (SUCCEED != zbx_tls_get_attr_psk(sock, &attr))
6474 {
6475 *error = zbx_strdup(*error, "internal error: cannot get connection attributes");
6476 THIS_SHOULD_NEVER_HAPPEN;
6477 return FAIL;
6478 }
6479 }
6480 #endif
6481 else if (ZBX_TCP_SEC_UNENCRYPTED != sock->connection_type)
6482 {
6483 *error = zbx_strdup(*error, "internal error: invalid connection type");
6484 THIS_SHOULD_NEVER_HAPPEN;
6485 return FAIL;
6486 }
6487 #endif
6488 RDLOCK_CACHE;
6489
6490 if (NULL == (dc_host = DCfind_proxy(host)))
6491 {
6492 UNLOCK_CACHE;
6493 *error = zbx_dsprintf(*error, "proxy \"%s\" not found", host);
6494 return FAIL;
6495 }
6496
6497 if (HOST_STATUS_PROXY_ACTIVE != dc_host->status)
6498 {
6499 UNLOCK_CACHE;
6500 *error = zbx_dsprintf(*error, "proxy \"%s\" is configured in passive mode", host);
6501 return FAIL;
6502 }
6503
6504 if (0 == ((unsigned int)dc_host->tls_accept & sock->connection_type))
6505 {
6506 UNLOCK_CACHE;
6507 *error = zbx_dsprintf(NULL, "connection of type \"%s\" is not allowed for proxy \"%s\"",
6508 zbx_tcp_connection_type_name(sock->connection_type), host);
6509 return FAIL;
6510 }
6511
6512 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
6513 if (ZBX_TCP_SEC_TLS_CERT == sock->connection_type)
6514 {
6515 /* simplified match, not compliant with RFC 4517, 4518 */
6516 if ('\0' != *dc_host->tls_issuer && 0 != strcmp(dc_host->tls_issuer, attr.issuer))
6517 {
6518 UNLOCK_CACHE;
6519 *error = zbx_dsprintf(*error, "proxy \"%s\" certificate issuer does not match", host);
6520 return FAIL;
6521 }
6522
6523 /* simplified match, not compliant with RFC 4517, 4518 */
6524 if ('\0' != *dc_host->tls_subject && 0 != strcmp(dc_host->tls_subject, attr.subject))
6525 {
6526 UNLOCK_CACHE;
6527 *error = zbx_dsprintf(*error, "proxy \"%s\" certificate subject does not match", host);
6528 return FAIL;
6529 }
6530 }
6531 #if defined(HAVE_GNUTLS) || (defined(HAVE_OPENSSL) && defined(HAVE_OPENSSL_WITH_PSK))
6532 else if (ZBX_TCP_SEC_TLS_PSK == sock->connection_type)
6533 {
6534 if (NULL != dc_host->tls_dc_psk)
6535 {
6536 if (strlen(dc_host->tls_dc_psk->tls_psk_identity) != attr.psk_identity_len ||
6537 0 != memcmp(dc_host->tls_dc_psk->tls_psk_identity, attr.psk_identity,
6538 attr.psk_identity_len))
6539 {
6540 UNLOCK_CACHE;
6541 *error = zbx_dsprintf(*error, "proxy \"%s\" is using false PSK identity", host);
6542 return FAIL;
6543 }
6544 }
6545 else
6546 {
6547 UNLOCK_CACHE;
6548 *error = zbx_dsprintf(*error, "active proxy \"%s\" is connecting with PSK but there is no PSK"
6549 " in the database for this proxy", host);
6550 return FAIL;
6551 }
6552 }
6553 #endif
6554 #endif
6555 *hostid = dc_host->hostid;
6556
6557 UNLOCK_CACHE;
6558
6559 return SUCCEED;
6560 }
6561
6562 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
6563 /******************************************************************************
6564 * *
6565 * Function: DCget_psk_by_identity *
6566 * *
6567 * Purpose: *
6568 * Find PSK with the specified identity in configuration cache *
6569 * *
6570 * Parameters: *
6571 * psk_identity - [IN] PSK identity to search for ('\0' terminated) *
6572 * psk_buf - [OUT] output buffer for PSK value with size *
6573 * HOST_TLS_PSK_LEN_MAX *
6574 * psk_usage - [OUT] 0 - PSK not found, 1 - found in host PSKs, *
6575 * 2 - found in autoregistration PSK, 3 - found in *
6576 * both *
6577 * Return value: *
6578 * PSK length in bytes if PSK found. 0 - if PSK not found. *
6579 * *
6580 * Comments: *
6581 * ATTENTION! This function's address and arguments are described and *
6582 * used in file src/libs/zbxcrypto/tls.c for calling this function by *
6583 * pointer. If you ever change this DCget_psk_by_identity() function *
6584 * arguments or return value do not forget to synchronize changes with *
6585 * the src/libs/zbxcrypto/tls.c. *
6586 * *
6587 ******************************************************************************/
DCget_psk_by_identity(const unsigned char * psk_identity,unsigned char * psk_buf,unsigned int * psk_usage)6588 size_t DCget_psk_by_identity(const unsigned char *psk_identity, unsigned char *psk_buf, unsigned int *psk_usage)
6589 {
6590 const ZBX_DC_PSK *psk_i;
6591 ZBX_DC_PSK psk_i_local;
6592 size_t psk_len = 0;
6593 unsigned char autoreg_psk_tmp[HOST_TLS_PSK_LEN_MAX];
6594
6595 *psk_usage = 0;
6596
6597 psk_i_local.tls_psk_identity = (const char *)psk_identity;
6598
6599 RDLOCK_CACHE;
6600
6601 /* Is it among host PSKs? */
6602 if (NULL != (psk_i = (ZBX_DC_PSK *)zbx_hashset_search(&config->psks, &psk_i_local)))
6603 {
6604 psk_len = zbx_strlcpy((char *)psk_buf, psk_i->tls_psk, HOST_TLS_PSK_LEN_MAX);
6605 *psk_usage |= ZBX_PSK_FOR_HOST;
6606 }
6607
6608 /* Does it match autoregistration PSK? */
6609 if (0 != strcmp(config->autoreg_psk_identity, (const char *)psk_identity))
6610 {
6611 UNLOCK_CACHE;
6612 return psk_len;
6613 }
6614
6615 if (0 == *psk_usage) /* only as autoregistration PSK */
6616 {
6617 psk_len = zbx_strlcpy((char *)psk_buf, config->autoreg_psk, HOST_TLS_PSK_LEN_MAX);
6618 UNLOCK_CACHE;
6619 *psk_usage |= ZBX_PSK_FOR_AUTOREG;
6620
6621 return psk_len;
6622 }
6623
6624 /* the requested PSK is used as host PSK and as autoregistration PSK */
6625 zbx_strlcpy((char *)autoreg_psk_tmp, config->autoreg_psk, sizeof(autoreg_psk_tmp));
6626
6627 UNLOCK_CACHE;
6628
6629 if (0 == strcmp((const char *)psk_buf, (const char *)autoreg_psk_tmp))
6630 {
6631 *psk_usage |= ZBX_PSK_FOR_AUTOREG;
6632 return psk_len;
6633 }
6634
6635 zabbix_log(LOG_LEVEL_WARNING, "host PSK and autoregistration PSK have the same identity \"%s\" but"
6636 " different PSK values, autoregistration will not be allowed", psk_identity);
6637 return psk_len;
6638 }
6639 #endif
6640
6641 /******************************************************************************
6642 * *
6643 * Function: DCget_autoregistration_psk *
6644 * *
6645 * Purpose: *
6646 * Copy autoregistration PSK identity and value from configuration cache *
6647 * into caller's buffers *
6648 * *
6649 * Parameters: *
6650 * psk_identity_buf - [OUT] buffer for PSK identity *
6651 * psk_identity_buf_len - [IN] buffer length for PSK identity *
6652 * psk_buf - [OUT] buffer for PSK value *
6653 * psk_buf_len - [IN] buffer length for PSK value *
6654 * *
6655 * Comments: if autoregistration PSK is not configured then empty strings *
6656 * will be copied into buffers *
6657 * *
6658 ******************************************************************************/
DCget_autoregistration_psk(char * psk_identity_buf,size_t psk_identity_buf_len,unsigned char * psk_buf,size_t psk_buf_len)6659 void DCget_autoregistration_psk(char *psk_identity_buf, size_t psk_identity_buf_len,
6660 unsigned char *psk_buf, size_t psk_buf_len)
6661 {
6662 RDLOCK_CACHE;
6663
6664 zbx_strlcpy((char *)psk_identity_buf, config->autoreg_psk_identity, psk_identity_buf_len);
6665 zbx_strlcpy((char *)psk_buf, config->autoreg_psk, psk_buf_len);
6666
6667 UNLOCK_CACHE;
6668 }
6669
DCget_interface(DC_INTERFACE * dst_interface,const ZBX_DC_INTERFACE * src_interface)6670 static void DCget_interface(DC_INTERFACE *dst_interface, const ZBX_DC_INTERFACE *src_interface)
6671 {
6672 if (NULL != src_interface)
6673 {
6674 dst_interface->interfaceid = src_interface->interfaceid;
6675 strscpy(dst_interface->ip_orig, src_interface->ip);
6676 strscpy(dst_interface->dns_orig, src_interface->dns);
6677 strscpy(dst_interface->port_orig, src_interface->port);
6678 dst_interface->useip = src_interface->useip;
6679 dst_interface->type = src_interface->type;
6680 dst_interface->main = src_interface->main;
6681 }
6682 else
6683 {
6684 dst_interface->interfaceid = 0;
6685 *dst_interface->ip_orig = '\0';
6686 *dst_interface->dns_orig = '\0';
6687 *dst_interface->port_orig = '\0';
6688 dst_interface->useip = 1;
6689 dst_interface->type = INTERFACE_TYPE_UNKNOWN;
6690 dst_interface->main = 0;
6691 }
6692
6693 dst_interface->addr = (1 == dst_interface->useip ? dst_interface->ip_orig : dst_interface->dns_orig);
6694 dst_interface->port = 0;
6695 }
6696
DCget_item(DC_ITEM * dst_item,const ZBX_DC_ITEM * src_item,unsigned int mode)6697 static void DCget_item(DC_ITEM *dst_item, const ZBX_DC_ITEM *src_item, unsigned int mode)
6698 {
6699 const ZBX_DC_NUMITEM *numitem;
6700 const ZBX_DC_LOGITEM *logitem;
6701 const ZBX_DC_SNMPITEM *snmpitem;
6702 const ZBX_DC_SNMPINTERFACE *snmp;
6703 const ZBX_DC_TRAPITEM *trapitem;
6704 const ZBX_DC_IPMIITEM *ipmiitem;
6705 const ZBX_DC_DBITEM *dbitem;
6706 const ZBX_DC_SSHITEM *sshitem;
6707 const ZBX_DC_TELNETITEM *telnetitem;
6708 const ZBX_DC_SIMPLEITEM *simpleitem;
6709 const ZBX_DC_JMXITEM *jmxitem;
6710 const ZBX_DC_CALCITEM *calcitem;
6711 const ZBX_DC_INTERFACE *dc_interface;
6712 const ZBX_DC_HTTPITEM *httpitem;
6713
6714 dst_item->type = src_item->type;
6715 dst_item->value_type = src_item->value_type;
6716
6717 dst_item->state = src_item->state;
6718 dst_item->lastlogsize = src_item->lastlogsize;
6719 dst_item->mtime = src_item->mtime;
6720
6721 dst_item->history = src_item->history;
6722
6723 dst_item->inventory_link = src_item->inventory_link;
6724 dst_item->valuemapid = src_item->valuemapid;
6725 dst_item->status = src_item->status;
6726
6727 dst_item->history_sec = src_item->history_sec;
6728 strscpy(dst_item->key_orig, src_item->key);
6729
6730 if (ZBX_ITEM_GET_MISC & mode)
6731 {
6732 dst_item->itemid = src_item->itemid; /* set after lock */
6733 dst_item->flags = src_item->flags;
6734 dst_item->nextcheck = src_item->nextcheck;
6735 dst_item->lastclock = src_item->lastclock;
6736 dst_item->key = NULL; /* set during initialization */
6737 }
6738
6739 if (ZBX_ITEM_GET_DELAY & mode)
6740 dst_item->delay = zbx_strdup(NULL, src_item->delay); /* not used, should be initialized */
6741
6742 if ((ZBX_ITEM_GET_EMPTY_ERROR & mode) || '\0' != *src_item->error) /* allocate after lock */
6743 dst_item->error = zbx_strdup(NULL, src_item->error);
6744
6745 switch (src_item->value_type)
6746 {
6747 case ITEM_VALUE_TYPE_FLOAT:
6748 case ITEM_VALUE_TYPE_UINT64:
6749 if (0 != (ZBX_ITEM_GET_NUM & mode))
6750 {
6751 numitem = (ZBX_DC_NUMITEM *)zbx_hashset_search(&config->numitems, &src_item->itemid);
6752
6753 dst_item->trends = numitem->trends;
6754 dst_item->trends_sec = numitem->trends_sec;
6755
6756 /* allocate after lock */
6757 if (0 != (ZBX_ITEM_GET_EMPTY_UNITS & mode) || '\0' != *numitem->units)
6758 dst_item->units = zbx_strdup(NULL, numitem->units);
6759 }
6760 break;
6761 case ITEM_VALUE_TYPE_LOG:
6762 if (ZBX_ITEM_GET_LOGTIMEFMT & mode)
6763 {
6764 if (NULL != (logitem = (ZBX_DC_LOGITEM *)zbx_hashset_search(&config->logitems,
6765 &src_item->itemid)))
6766 {
6767 strscpy(dst_item->logtimefmt, logitem->logtimefmt);
6768 }
6769 else
6770 *dst_item->logtimefmt = '\0';
6771 }
6772 break;
6773 }
6774
6775 if (ZBX_ITEM_GET_INTERFACE & mode) /* not used by history syncer */
6776 {
6777 dc_interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces, &src_item->interfaceid);
6778
6779 DCget_interface(&dst_item->interface, dc_interface);
6780 }
6781
6782 if (0 == (ZBX_ITEM_GET_POLLINFO & mode)) /* not used by history syncer */
6783 return;
6784
6785 switch (src_item->type)
6786 {
6787 case ITEM_TYPE_SNMP:
6788 snmpitem = (ZBX_DC_SNMPITEM *)zbx_hashset_search(&config->snmpitems, &src_item->itemid);
6789 snmp = (ZBX_DC_SNMPINTERFACE *)zbx_hashset_search(&config->interfaces_snmp, &src_item->interfaceid);
6790
6791 if (NULL != snmpitem && NULL != snmp)
6792 {
6793 strscpy(dst_item->snmp_community_orig, snmp->community);
6794 strscpy(dst_item->snmp_oid_orig, snmpitem->snmp_oid);
6795 strscpy(dst_item->snmpv3_securityname_orig, snmp->securityname);
6796 dst_item->snmpv3_securitylevel = snmp->securitylevel;
6797 strscpy(dst_item->snmpv3_authpassphrase_orig, snmp->authpassphrase);
6798 strscpy(dst_item->snmpv3_privpassphrase_orig, snmp->privpassphrase);
6799 dst_item->snmpv3_authprotocol = snmp->authprotocol;
6800 dst_item->snmpv3_privprotocol = snmp->privprotocol;
6801 strscpy(dst_item->snmpv3_contextname_orig, snmp->contextname);
6802 dst_item->snmp_version = snmp->version;
6803 }
6804 else
6805 {
6806 *dst_item->snmp_community_orig = '\0';
6807 *dst_item->snmp_oid_orig = '\0';
6808 *dst_item->snmpv3_securityname_orig = '\0';
6809 dst_item->snmpv3_securitylevel = ITEM_SNMPV3_SECURITYLEVEL_NOAUTHNOPRIV;
6810 *dst_item->snmpv3_authpassphrase_orig = '\0';
6811 *dst_item->snmpv3_privpassphrase_orig = '\0';
6812 dst_item->snmpv3_authprotocol = 0;
6813 dst_item->snmpv3_privprotocol = 0;
6814 *dst_item->snmpv3_contextname_orig = '\0';
6815 dst_item->snmp_version = ZBX_IF_SNMP_VERSION_2;
6816 }
6817
6818 dst_item->snmp_community = NULL;
6819 dst_item->snmp_oid = NULL;
6820 dst_item->snmpv3_securityname = NULL;
6821 dst_item->snmpv3_authpassphrase = NULL;
6822 dst_item->snmpv3_privpassphrase = NULL;
6823 dst_item->snmpv3_contextname = NULL;
6824 break;
6825 case ITEM_TYPE_TRAPPER:
6826 if (NULL != (trapitem = (ZBX_DC_TRAPITEM *)zbx_hashset_search(&config->trapitems, &src_item->itemid)))
6827 strscpy(dst_item->trapper_hosts, trapitem->trapper_hosts);
6828 else
6829 *dst_item->trapper_hosts = '\0';
6830 break;
6831 case ITEM_TYPE_IPMI:
6832 if (NULL != (ipmiitem = (ZBX_DC_IPMIITEM *)zbx_hashset_search(&config->ipmiitems, &src_item->itemid)))
6833 strscpy(dst_item->ipmi_sensor, ipmiitem->ipmi_sensor);
6834 else
6835 *dst_item->ipmi_sensor = '\0';
6836 break;
6837 case ITEM_TYPE_DB_MONITOR:
6838 if (NULL != (dbitem = (ZBX_DC_DBITEM *)zbx_hashset_search(&config->dbitems, &src_item->itemid)))
6839 {
6840 dst_item->params = zbx_strdup(NULL, dbitem->params);
6841 strscpy(dst_item->username_orig, dbitem->username);
6842 strscpy(dst_item->password_orig, dbitem->password);
6843 }
6844 else
6845 {
6846 dst_item->params = zbx_strdup(NULL, "");
6847 *dst_item->username_orig = '\0';
6848 *dst_item->password_orig = '\0';
6849 }
6850 dst_item->username = NULL;
6851 dst_item->password = NULL;
6852
6853 break;
6854 case ITEM_TYPE_SSH:
6855 if (NULL != (sshitem = (ZBX_DC_SSHITEM *)zbx_hashset_search(&config->sshitems, &src_item->itemid)))
6856 {
6857 dst_item->authtype = sshitem->authtype;
6858 strscpy(dst_item->username_orig, sshitem->username);
6859 strscpy(dst_item->publickey_orig, sshitem->publickey);
6860 strscpy(dst_item->privatekey_orig, sshitem->privatekey);
6861 strscpy(dst_item->password_orig, sshitem->password);
6862 dst_item->params = zbx_strdup(NULL, sshitem->params);
6863 }
6864 else
6865 {
6866 dst_item->authtype = 0;
6867 *dst_item->username_orig = '\0';
6868 *dst_item->publickey_orig = '\0';
6869 *dst_item->privatekey_orig = '\0';
6870 *dst_item->password_orig = '\0';
6871 dst_item->params = zbx_strdup(NULL, "");
6872 }
6873 dst_item->username = NULL;
6874 dst_item->publickey = NULL;
6875 dst_item->privatekey = NULL;
6876 dst_item->password = NULL;
6877 break;
6878 case ITEM_TYPE_HTTPAGENT:
6879 if (NULL != (httpitem = (ZBX_DC_HTTPITEM *)zbx_hashset_search(&config->httpitems, &src_item->itemid)))
6880 {
6881 strscpy(dst_item->timeout_orig, httpitem->timeout);
6882 strscpy(dst_item->url_orig, httpitem->url);
6883 strscpy(dst_item->query_fields_orig, httpitem->query_fields);
6884 strscpy(dst_item->status_codes_orig, httpitem->status_codes);
6885 dst_item->follow_redirects = httpitem->follow_redirects;
6886 dst_item->post_type = httpitem->post_type;
6887 strscpy(dst_item->http_proxy_orig, httpitem->http_proxy);
6888 dst_item->headers = zbx_strdup(NULL, httpitem->headers);
6889 dst_item->retrieve_mode = httpitem->retrieve_mode;
6890 dst_item->request_method = httpitem->request_method;
6891 dst_item->output_format = httpitem->output_format;
6892 strscpy(dst_item->ssl_cert_file_orig, httpitem->ssl_cert_file);
6893 strscpy(dst_item->ssl_key_file_orig, httpitem->ssl_key_file);
6894 strscpy(dst_item->ssl_key_password_orig, httpitem->ssl_key_password);
6895 dst_item->verify_peer = httpitem->verify_peer;
6896 dst_item->verify_host = httpitem->verify_host;
6897 dst_item->authtype = httpitem->authtype;
6898 strscpy(dst_item->username_orig, httpitem->username);
6899 strscpy(dst_item->password_orig, httpitem->password);
6900 dst_item->posts = zbx_strdup(NULL, httpitem->posts);
6901 dst_item->allow_traps = httpitem->allow_traps;
6902 strscpy(dst_item->trapper_hosts, httpitem->trapper_hosts);
6903 }
6904 else
6905 {
6906 *dst_item->timeout_orig = '\0';
6907 *dst_item->url_orig = '\0';
6908 *dst_item->query_fields_orig = '\0';
6909 *dst_item->status_codes_orig = '\0';
6910 dst_item->follow_redirects = 0;
6911 dst_item->post_type = 0;
6912 *dst_item->http_proxy_orig = '\0';
6913 dst_item->headers = zbx_strdup(NULL, "");
6914 dst_item->retrieve_mode = 0;
6915 dst_item->request_method = 0;
6916 dst_item->output_format = 0;
6917 *dst_item->ssl_cert_file_orig = '\0';
6918 *dst_item->ssl_key_file_orig = '\0';
6919 *dst_item->ssl_key_password_orig = '\0';
6920 dst_item->verify_peer = 0;
6921 dst_item->verify_host = 0;
6922 dst_item->authtype = 0;
6923 *dst_item->username_orig = '\0';
6924 *dst_item->password_orig = '\0';
6925 dst_item->posts = zbx_strdup(NULL, "");
6926 dst_item->allow_traps = 0;
6927 *dst_item->trapper_hosts = '\0';
6928 }
6929 dst_item->timeout = NULL;
6930 dst_item->url = NULL;
6931 dst_item->query_fields = NULL;
6932 dst_item->status_codes = NULL;
6933 dst_item->http_proxy = NULL;
6934 dst_item->ssl_cert_file = NULL;
6935 dst_item->ssl_key_file = NULL;
6936 dst_item->ssl_key_password = NULL;
6937 dst_item->username = NULL;
6938 dst_item->password = NULL;
6939 break;
6940 case ITEM_TYPE_TELNET:
6941 if (NULL != (telnetitem = (ZBX_DC_TELNETITEM *)zbx_hashset_search(&config->telnetitems, &src_item->itemid)))
6942 {
6943 strscpy(dst_item->username_orig, telnetitem->username);
6944 strscpy(dst_item->password_orig, telnetitem->password);
6945 dst_item->params = zbx_strdup(NULL, telnetitem->params);
6946 }
6947 else
6948 {
6949 *dst_item->username_orig = '\0';
6950 *dst_item->password_orig = '\0';
6951 dst_item->params = zbx_strdup(NULL, "");
6952 }
6953 dst_item->username = NULL;
6954 dst_item->password = NULL;
6955 break;
6956 case ITEM_TYPE_SIMPLE:
6957 if (NULL != (simpleitem = (ZBX_DC_SIMPLEITEM *)zbx_hashset_search(&config->simpleitems, &src_item->itemid)))
6958 {
6959 strscpy(dst_item->username_orig, simpleitem->username);
6960 strscpy(dst_item->password_orig, simpleitem->password);
6961 }
6962 else
6963 {
6964 *dst_item->username_orig = '\0';
6965 *dst_item->password_orig = '\0';
6966 }
6967 dst_item->username = NULL;
6968 dst_item->password = NULL;
6969 break;
6970 case ITEM_TYPE_JMX:
6971 if (NULL != (jmxitem = (ZBX_DC_JMXITEM *)zbx_hashset_search(&config->jmxitems, &src_item->itemid)))
6972 {
6973 strscpy(dst_item->username_orig, jmxitem->username);
6974 strscpy(dst_item->password_orig, jmxitem->password);
6975 strscpy(dst_item->jmx_endpoint_orig, jmxitem->jmx_endpoint);
6976 }
6977 else
6978 {
6979 *dst_item->username_orig = '\0';
6980 *dst_item->password_orig = '\0';
6981 *dst_item->jmx_endpoint_orig = '\0';
6982 }
6983 dst_item->username = NULL;
6984 dst_item->password = NULL;
6985 dst_item->jmx_endpoint = NULL;
6986 break;
6987 case ITEM_TYPE_CALCULATED:
6988 calcitem = (ZBX_DC_CALCITEM *)zbx_hashset_search(&config->calcitems, &src_item->itemid);
6989 dst_item->params = zbx_strdup(NULL, NULL != calcitem ? calcitem->params : "");
6990 break;
6991 default:
6992 /* nothing to do */;
6993 }
6994 }
6995
DCconfig_clean_items(DC_ITEM * items,int * errcodes,size_t num)6996 void DCconfig_clean_items(DC_ITEM *items, int *errcodes, size_t num)
6997 {
6998 size_t i;
6999
7000 for (i = 0; i < num; i++)
7001 {
7002 if (NULL != errcodes && SUCCEED != errcodes[i])
7003 continue;
7004
7005 if (ITEM_VALUE_TYPE_FLOAT == items[i].value_type || ITEM_VALUE_TYPE_UINT64 == items[i].value_type)
7006 {
7007 zbx_free(items[i].units);
7008 }
7009
7010 switch (items[i].type)
7011 {
7012 case ITEM_TYPE_HTTPAGENT:
7013 zbx_free(items[i].headers);
7014 zbx_free(items[i].posts);
7015 break;
7016 case ITEM_TYPE_DB_MONITOR:
7017 case ITEM_TYPE_SSH:
7018 case ITEM_TYPE_TELNET:
7019 case ITEM_TYPE_CALCULATED:
7020 zbx_free(items[i].params);
7021 break;
7022 }
7023
7024 zbx_free(items[i].delay);
7025 zbx_free(items[i].error);
7026 }
7027 }
7028
DCget_function(DC_FUNCTION * dst_function,const ZBX_DC_FUNCTION * src_function)7029 static void DCget_function(DC_FUNCTION *dst_function, const ZBX_DC_FUNCTION *src_function)
7030 {
7031 size_t sz_function, sz_parameter;
7032
7033 dst_function->functionid = src_function->functionid;
7034 dst_function->triggerid = src_function->triggerid;
7035 dst_function->itemid = src_function->itemid;
7036
7037 sz_function = strlen(src_function->function) + 1;
7038 sz_parameter = strlen(src_function->parameter) + 1;
7039 dst_function->function = (char *)zbx_malloc(NULL, sz_function + sz_parameter);
7040 dst_function->parameter = dst_function->function + sz_function;
7041 memcpy(dst_function->function, src_function->function, sz_function);
7042 memcpy(dst_function->parameter, src_function->parameter, sz_parameter);
7043 }
7044
DCget_trigger(DC_TRIGGER * dst_trigger,const ZBX_DC_TRIGGER * src_trigger)7045 static void DCget_trigger(DC_TRIGGER *dst_trigger, const ZBX_DC_TRIGGER *src_trigger)
7046 {
7047 int i;
7048
7049 dst_trigger->triggerid = src_trigger->triggerid;
7050 dst_trigger->description = zbx_strdup(NULL, src_trigger->description);
7051 dst_trigger->expression_orig = zbx_strdup(NULL, src_trigger->expression);
7052 dst_trigger->recovery_expression_orig = zbx_strdup(NULL, src_trigger->recovery_expression);
7053 dst_trigger->error = zbx_strdup(NULL, src_trigger->error);
7054 dst_trigger->timespec.sec = 0;
7055 dst_trigger->timespec.ns = 0;
7056 dst_trigger->priority = src_trigger->priority;
7057 dst_trigger->type = src_trigger->type;
7058 dst_trigger->value = src_trigger->value;
7059 dst_trigger->state = src_trigger->state;
7060 dst_trigger->new_value = TRIGGER_VALUE_UNKNOWN;
7061 dst_trigger->lastchange = src_trigger->lastchange;
7062 dst_trigger->topoindex = src_trigger->topoindex;
7063 dst_trigger->status = src_trigger->status;
7064 dst_trigger->recovery_mode = src_trigger->recovery_mode;
7065 dst_trigger->correlation_mode = src_trigger->correlation_mode;
7066 dst_trigger->correlation_tag = zbx_strdup(NULL, src_trigger->correlation_tag);
7067 dst_trigger->opdata = zbx_strdup(NULL, src_trigger->opdata);
7068 dst_trigger->flags = 0;
7069
7070 dst_trigger->expression = NULL;
7071 dst_trigger->recovery_expression = NULL;
7072 dst_trigger->new_error = NULL;
7073
7074 dst_trigger->expression = zbx_strdup(NULL, src_trigger->expression);
7075 dst_trigger->recovery_expression = zbx_strdup(NULL, src_trigger->recovery_expression);
7076
7077 zbx_vector_ptr_create(&dst_trigger->tags);
7078
7079 if (0 != src_trigger->tags.values_num)
7080 {
7081 zbx_vector_ptr_reserve(&dst_trigger->tags, src_trigger->tags.values_num);
7082
7083 for (i = 0; i < src_trigger->tags.values_num; i++)
7084 {
7085 const zbx_dc_trigger_tag_t *dc_trigger_tag = (const zbx_dc_trigger_tag_t *)src_trigger->tags.values[i];
7086 zbx_tag_t *tag;
7087
7088 tag = (zbx_tag_t *)zbx_malloc(NULL, sizeof(zbx_tag_t));
7089 tag->tag = zbx_strdup(NULL, dc_trigger_tag->tag);
7090 tag->value = zbx_strdup(NULL, dc_trigger_tag->value);
7091
7092 zbx_vector_ptr_append(&dst_trigger->tags, tag);
7093 }
7094 }
7095 }
7096
zbx_free_tag(zbx_tag_t * tag)7097 void zbx_free_tag(zbx_tag_t *tag)
7098 {
7099 zbx_free(tag->tag);
7100 zbx_free(tag->value);
7101 zbx_free(tag);
7102 }
7103
zbx_free_item_tag(zbx_item_tag_t * item_tag)7104 void zbx_free_item_tag(zbx_item_tag_t *item_tag)
7105 {
7106 zbx_free(item_tag->tag.tag);
7107 zbx_free(item_tag->tag.value);
7108 zbx_free(item_tag);
7109 }
7110
DCclean_trigger(DC_TRIGGER * trigger)7111 static void DCclean_trigger(DC_TRIGGER *trigger)
7112 {
7113 zbx_free(trigger->new_error);
7114 zbx_free(trigger->error);
7115 zbx_free(trigger->expression_orig);
7116 zbx_free(trigger->recovery_expression_orig);
7117 zbx_free(trigger->expression);
7118 zbx_free(trigger->recovery_expression);
7119 zbx_free(trigger->description);
7120 zbx_free(trigger->correlation_tag);
7121 zbx_free(trigger->opdata);
7122
7123 zbx_vector_ptr_clear_ext(&trigger->tags, (zbx_clean_func_t)zbx_free_tag);
7124 zbx_vector_ptr_destroy(&trigger->tags);
7125 }
7126
7127 /******************************************************************************
7128 * *
7129 * Function: DCconfig_get_items_by_keys *
7130 * *
7131 * Purpose: locate item in configuration cache by host and key *
7132 * *
7133 * Parameters: items - [OUT] pointer to array of DC_ITEM structures *
7134 * keys - [IN] list of item keys with host names *
7135 * errcodes - [OUT] SUCCEED if record located and FAIL otherwise *
7136 * num - [IN] number of elements in items, keys, errcodes *
7137 * *
7138 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
7139 * *
7140 ******************************************************************************/
DCconfig_get_items_by_keys(DC_ITEM * items,zbx_host_key_t * keys,int * errcodes,size_t num)7141 void DCconfig_get_items_by_keys(DC_ITEM *items, zbx_host_key_t *keys, int *errcodes, size_t num)
7142 {
7143 size_t i;
7144 const ZBX_DC_ITEM *dc_item;
7145 const ZBX_DC_HOST *dc_host;
7146
7147 RDLOCK_CACHE;
7148
7149 for (i = 0; i < num; i++)
7150 {
7151 if (NULL == (dc_host = DCfind_host(keys[i].host)) ||
7152 NULL == (dc_item = DCfind_item(dc_host->hostid, keys[i].key)))
7153 {
7154 errcodes[i] = FAIL;
7155 continue;
7156 }
7157
7158 DCget_host(&items[i].host, dc_host, ZBX_ITEM_GET_ALL);
7159 DCget_item(&items[i], dc_item, ZBX_ITEM_GET_ALL);
7160 errcodes[i] = SUCCEED;
7161 }
7162
7163 UNLOCK_CACHE;
7164 }
7165
DCconfig_get_hostid_by_name(const char * host,zbx_uint64_t * hostid)7166 int DCconfig_get_hostid_by_name(const char *host, zbx_uint64_t *hostid)
7167 {
7168 const ZBX_DC_HOST *dc_host;
7169 int ret;
7170
7171 RDLOCK_CACHE;
7172
7173 if (NULL != (dc_host = DCfind_host(host)))
7174 {
7175 *hostid = dc_host->hostid;
7176 ret = SUCCEED;
7177 }
7178 else
7179 ret = FAIL;
7180
7181 UNLOCK_CACHE;
7182
7183 return ret;
7184 }
7185
7186 /******************************************************************************
7187 * *
7188 * Function: DCconfig_get_items_by_itemids *
7189 * *
7190 * Purpose: Get item with specified ID *
7191 * *
7192 * Parameters: items - [OUT] pointer to DC_ITEM structures *
7193 * itemids - [IN] array of item IDs *
7194 * errcodes - [OUT] SUCCEED if item found, otherwise FAIL *
7195 * num - [IN] number of elements *
7196 * *
7197 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
7198 * *
7199 ******************************************************************************/
DCconfig_get_items_by_itemids(DC_ITEM * items,const zbx_uint64_t * itemids,int * errcodes,size_t num)7200 void DCconfig_get_items_by_itemids(DC_ITEM *items, const zbx_uint64_t *itemids, int *errcodes, size_t num)
7201 {
7202 size_t i;
7203 const ZBX_DC_ITEM *dc_item;
7204 const ZBX_DC_HOST *dc_host;
7205
7206 RDLOCK_CACHE;
7207
7208 for (i = 0; i < num; i++)
7209 {
7210 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemids[i])) ||
7211 NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
7212 {
7213 errcodes[i] = FAIL;
7214 continue;
7215 }
7216
7217 DCget_host(&items[i].host, dc_host, ZBX_ITEM_GET_ALL);
7218 DCget_item(&items[i], dc_item, ZBX_ITEM_GET_ALL);
7219 errcodes[i] = SUCCEED;
7220 }
7221
7222 UNLOCK_CACHE;
7223 }
7224
DCconfig_get_items_by_itemids_partial(DC_ITEM * items,const zbx_uint64_t * itemids,int * errcodes,size_t num,unsigned int mode)7225 void DCconfig_get_items_by_itemids_partial(DC_ITEM *items, const zbx_uint64_t *itemids, int *errcodes, size_t num,
7226 unsigned int mode)
7227 {
7228 size_t i;
7229 const ZBX_DC_ITEM *dc_item;
7230 const ZBX_DC_HOST *dc_host = NULL;
7231
7232 memset(items, 0, sizeof(DC_ITEM) * (size_t)num);
7233 memset(errcodes, 0, sizeof(int) * (size_t)num);
7234
7235 RDLOCK_CACHE;
7236
7237 for (i = 0; i < num; i++)
7238 {
7239 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemids[i])))
7240 {
7241 errcodes[i] = FAIL;
7242 continue;
7243 }
7244
7245 if (NULL == dc_host || dc_host->hostid != dc_item->hostid)
7246 {
7247 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
7248 {
7249 errcodes[i] = FAIL;
7250 continue;
7251 }
7252 }
7253
7254 DCget_host(&items[i].host, dc_host, mode);
7255 DCget_item(&items[i], dc_item, mode);
7256 }
7257
7258 UNLOCK_CACHE;
7259
7260 /* avoid unnecessary allocations inside lock if there are no error or units */
7261 for (i = 0; i < num; i++)
7262 {
7263 if (FAIL == errcodes[i])
7264 continue;
7265
7266 items[i].itemid = itemids[i];
7267
7268 if (NULL == items[i].error)
7269 items[i].error = zbx_strdup(NULL, "");
7270
7271 if (ITEM_VALUE_TYPE_FLOAT == items[i].value_type || ITEM_VALUE_TYPE_UINT64 == items[i].value_type)
7272 {
7273 if (NULL == items[i].units)
7274 items[i].units = zbx_strdup(NULL, "");
7275 }
7276 }
7277 }
7278
7279 /******************************************************************************
7280 * *
7281 * Function: dc_preproc_item_init *
7282 * *
7283 * Purpose: initialize new preprocessor item from configuration cache *
7284 * *
7285 * Parameters: item - [OUT] the item to initialize *
7286 * itemid - [IN] the item identifier *
7287 * *
7288 * Return value: SUCCEED - the item was initialized successfully *
7289 * FAIL - item with the specified itemid is not cached or *
7290 * monitored *
7291 * *
7292 ******************************************************************************/
dc_preproc_item_init(zbx_preproc_item_t * item,zbx_uint64_t itemid)7293 static int dc_preproc_item_init(zbx_preproc_item_t *item, zbx_uint64_t itemid)
7294 {
7295 const ZBX_DC_ITEM *dc_item;
7296 const ZBX_DC_HOST *dc_host;
7297
7298 if (NULL == (dc_item = (const ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemid)))
7299 return FAIL;
7300
7301 if (ITEM_STATUS_ACTIVE != dc_item->status)
7302 return FAIL;
7303
7304 if (NULL == (dc_host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
7305 return FAIL;
7306
7307 if (HOST_STATUS_MONITORED != dc_host->status)
7308 return FAIL;
7309
7310 item->itemid = itemid;
7311 item->type = dc_item->type;
7312 item->value_type = dc_item->value_type;
7313
7314 item->dep_itemids = NULL;
7315 item->dep_itemids_num = 0;
7316
7317 item->preproc_ops = NULL;
7318 item->preproc_ops_num = 0;
7319 item->update_time = 0;
7320
7321 return SUCCEED;
7322 }
7323
7324 /******************************************************************************
7325 * *
7326 * Function: DCconfig_get_preprocessable_items *
7327 * *
7328 * Purpose: get preprocessable items: *
7329 * * items with preprocessing steps *
7330 * * items with dependent items *
7331 * * internal items *
7332 * *
7333 * Parameters: items - [IN/OUT] hashset with DC_ITEMs *
7334 * timestamp - [IN/OUT] timestamp of a last update *
7335 * *
7336 ******************************************************************************/
DCconfig_get_preprocessable_items(zbx_hashset_t * items,int * timestamp)7337 void DCconfig_get_preprocessable_items(zbx_hashset_t *items, int *timestamp)
7338 {
7339 const ZBX_DC_PREPROCITEM *dc_preprocitem;
7340 const ZBX_DC_MASTERITEM *dc_masteritem;
7341 const ZBX_DC_ITEM *dc_item;
7342 const zbx_dc_preproc_op_t *dc_op;
7343 zbx_preproc_item_t *item, item_local;
7344 zbx_hashset_iter_t iter;
7345 zbx_preproc_op_t *op;
7346 int i;
7347
7348 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
7349
7350 /* no changes */
7351 if (0 != *timestamp && *timestamp == config->item_sync_ts)
7352 goto out;
7353
7354 zbx_hashset_clear(items);
7355 *timestamp = config->item_sync_ts;
7356
7357 RDLOCK_CACHE;
7358
7359 zbx_hashset_iter_reset(&config->preprocitems, &iter);
7360 while (NULL != (dc_preprocitem = (const ZBX_DC_PREPROCITEM *)zbx_hashset_iter_next(&iter)))
7361 {
7362 if (FAIL == dc_preproc_item_init(&item_local, dc_preprocitem->itemid))
7363 continue;
7364
7365 item = (zbx_preproc_item_t *)zbx_hashset_insert(items, &item_local, sizeof(item_local));
7366
7367 item->preproc_ops_num = dc_preprocitem->preproc_ops.values_num;
7368 item->preproc_ops = (zbx_preproc_op_t *)zbx_malloc(NULL, sizeof(zbx_preproc_op_t) * item->preproc_ops_num);
7369 item->update_time = dc_preprocitem->update_time;
7370
7371 for (i = 0; i < dc_preprocitem->preproc_ops.values_num; i++)
7372 {
7373 dc_op = (const zbx_dc_preproc_op_t *)dc_preprocitem->preproc_ops.values[i];
7374 op = &item->preproc_ops[i];
7375 op->type = dc_op->type;
7376 op->params = zbx_strdup(NULL, dc_op->params);
7377 op->error_handler = dc_op->error_handler;
7378 op->error_handler_params = zbx_strdup(NULL, dc_op->error_handler_params);
7379 }
7380 }
7381
7382 zbx_hashset_iter_reset(&config->masteritems, &iter);
7383 while (NULL != (dc_masteritem = (const ZBX_DC_MASTERITEM *)zbx_hashset_iter_next(&iter)))
7384 {
7385 if (NULL == (item = (zbx_preproc_item_t *)zbx_hashset_search(items, &dc_masteritem->itemid)))
7386 {
7387 if (FAIL == dc_preproc_item_init(&item_local, dc_masteritem->itemid))
7388 continue;
7389
7390 item = (zbx_preproc_item_t *)zbx_hashset_insert(items, &item_local, sizeof(item_local));
7391 }
7392
7393 item->dep_itemids_num = 0;
7394 item->dep_itemids = (zbx_uint64_pair_t *)zbx_malloc(NULL, sizeof(zbx_uint64_pair_t) *
7395 dc_masteritem->dep_itemids.values_num);
7396
7397 for (i = 0; i < dc_masteritem->dep_itemids.values_num; i++)
7398 {
7399 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items,
7400 &dc_masteritem->dep_itemids.values[i].first)) ||
7401 ITEM_STATUS_ACTIVE != dc_item->status)
7402 {
7403 continue;
7404 }
7405 item->dep_itemids[item->dep_itemids_num++] = dc_masteritem->dep_itemids.values[i];
7406 }
7407 }
7408
7409 zbx_hashset_iter_reset(&config->items, &iter);
7410 while (NULL != (dc_item = (const ZBX_DC_ITEM *)zbx_hashset_iter_next(&iter)))
7411 {
7412 if (ITEM_TYPE_INTERNAL != dc_item->type)
7413 continue;
7414
7415 if (NULL == zbx_hashset_search(items, &dc_item->itemid))
7416 {
7417 if (FAIL == dc_preproc_item_init(&item_local, dc_item->itemid))
7418 continue;
7419
7420 zbx_hashset_insert(items, &item_local, sizeof(item_local));
7421 }
7422 }
7423
7424 UNLOCK_CACHE;
7425 out:
7426 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() items:%d", __func__, items->num_data);
7427 }
7428
DCconfig_get_hosts_by_itemids(DC_HOST * hosts,const zbx_uint64_t * itemids,int * errcodes,size_t num)7429 void DCconfig_get_hosts_by_itemids(DC_HOST *hosts, const zbx_uint64_t *itemids, int *errcodes, size_t num)
7430 {
7431 size_t i;
7432 const ZBX_DC_ITEM *dc_item;
7433 const ZBX_DC_HOST *dc_host;
7434
7435 RDLOCK_CACHE;
7436
7437 for (i = 0; i < num; i++)
7438 {
7439 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemids[i])) ||
7440 NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
7441 {
7442 errcodes[i] = FAIL;
7443 continue;
7444 }
7445
7446 DCget_host(&hosts[i], dc_host, ZBX_ITEM_GET_ALL);
7447 errcodes[i] = SUCCEED;
7448 }
7449
7450 UNLOCK_CACHE;
7451 }
7452
DCconfig_trigger_exists(zbx_uint64_t triggerid)7453 int DCconfig_trigger_exists(zbx_uint64_t triggerid)
7454 {
7455 int ret = SUCCEED;
7456
7457 RDLOCK_CACHE;
7458
7459 if (NULL == zbx_hashset_search(&config->triggers, &triggerid))
7460 ret = FAIL;
7461
7462 UNLOCK_CACHE;
7463
7464 return ret;
7465 }
7466
DCconfig_get_triggers_by_triggerids(DC_TRIGGER * triggers,const zbx_uint64_t * triggerids,int * errcode,size_t num)7467 void DCconfig_get_triggers_by_triggerids(DC_TRIGGER *triggers, const zbx_uint64_t *triggerids, int *errcode,
7468 size_t num)
7469 {
7470 size_t i;
7471 const ZBX_DC_TRIGGER *dc_trigger;
7472
7473 RDLOCK_CACHE;
7474
7475 for (i = 0; i < num; i++)
7476 {
7477 if (NULL == (dc_trigger = (const ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &triggerids[i])))
7478 {
7479 errcode[i] = FAIL;
7480 continue;
7481 }
7482
7483 DCget_trigger(&triggers[i], dc_trigger);
7484 errcode[i] = SUCCEED;
7485 }
7486
7487 UNLOCK_CACHE;
7488 }
7489
7490 /******************************************************************************
7491 * *
7492 * Function: DCconfig_get_functions_by_functionids *
7493 * *
7494 * Purpose: Get functions by IDs *
7495 * *
7496 * Parameters: functions - [OUT] pointer to DC_FUNCTION structures *
7497 * functionids - [IN] array of function IDs *
7498 * errcodes - [OUT] SUCCEED if item found, otherwise FAIL *
7499 * num - [IN] number of elements *
7500 * *
7501 * Author: Aleksandrs Saveljevs, Alexander Vladishev *
7502 * *
7503 ******************************************************************************/
DCconfig_get_functions_by_functionids(DC_FUNCTION * functions,zbx_uint64_t * functionids,int * errcodes,size_t num)7504 void DCconfig_get_functions_by_functionids(DC_FUNCTION *functions, zbx_uint64_t *functionids, int *errcodes,
7505 size_t num)
7506 {
7507 size_t i;
7508 const ZBX_DC_FUNCTION *dc_function;
7509
7510 RDLOCK_CACHE;
7511
7512 for (i = 0; i < num; i++)
7513 {
7514 if (NULL == (dc_function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &functionids[i])))
7515 {
7516 errcodes[i] = FAIL;
7517 continue;
7518 }
7519
7520 DCget_function(&functions[i], dc_function);
7521 errcodes[i] = SUCCEED;
7522 }
7523
7524 UNLOCK_CACHE;
7525 }
7526
7527 /******************************************************************************
7528 * *
7529 * Function: DCconfig_clean_functions *
7530 * *
7531 * Author: Alexander Vladishev *
7532 * *
7533 ******************************************************************************/
DCconfig_clean_functions(DC_FUNCTION * functions,int * errcodes,size_t num)7534 void DCconfig_clean_functions(DC_FUNCTION *functions, int *errcodes, size_t num)
7535 {
7536 size_t i;
7537
7538 for (i = 0; i < num; i++)
7539 {
7540 if (SUCCEED != errcodes[i])
7541 continue;
7542
7543 zbx_free(functions[i].function);
7544 }
7545 }
7546
DCconfig_clean_triggers(DC_TRIGGER * triggers,int * errcodes,size_t num)7547 void DCconfig_clean_triggers(DC_TRIGGER *triggers, int *errcodes, size_t num)
7548 {
7549 size_t i;
7550
7551 for (i = 0; i < num; i++)
7552 {
7553 if (SUCCEED != errcodes[i])
7554 continue;
7555
7556 DCclean_trigger(&triggers[i]);
7557 }
7558 }
7559
7560 /******************************************************************************
7561 * *
7562 * Function: DCconfig_lock_triggers_by_history_items *
7563 * *
7564 * Purpose: Lock triggers for specified items so that multiple processes do *
7565 * not process one trigger simultaneously. Otherwise, this leads to *
7566 * problems like multiple successive OK events or escalations being *
7567 * started and not cancelled, because they are not seen in parallel *
7568 * transactions. *
7569 * *
7570 * Parameters: history_items - [IN/OUT] list of history items history syncer *
7571 * wishes to take for processing; on *
7572 * output, the item locked field is set *
7573 * to 0 if the corresponding item cannot *
7574 * be taken *
7575 * triggerids - [OUT] list of trigger IDs that this function has *
7576 * locked for processing; unlock those using *
7577 * DCconfig_unlock_triggers() function *
7578 * *
7579 * Author: Aleksandrs Saveljevs *
7580 * *
7581 * Comments: This does not solve the problem fully (e.g., ZBX-7484). There is *
7582 * a significant time period between the place where we lock the *
7583 * triggers and the place where we process them. So it could happen *
7584 * that a configuration cache update happens after we have locked *
7585 * the triggers and it turns out that in the updated configuration *
7586 * there is a new trigger for two of the items that two different *
7587 * history syncers have taken for processing. In that situation, *
7588 * the problem we are solving here might still happen. However, *
7589 * locking triggers makes this problem much less likely and only in *
7590 * case configuration changes. On a stable configuration, it should *
7591 * work without any problems. *
7592 * *
7593 * Return value: the number of items available for processing (unlocked). *
7594 * *
7595 ******************************************************************************/
DCconfig_lock_triggers_by_history_items(zbx_vector_ptr_t * history_items,zbx_vector_uint64_t * triggerids)7596 int DCconfig_lock_triggers_by_history_items(zbx_vector_ptr_t *history_items, zbx_vector_uint64_t *triggerids)
7597 {
7598 int i, j, locked_num = 0;
7599 const ZBX_DC_ITEM *dc_item;
7600 ZBX_DC_TRIGGER *dc_trigger;
7601 zbx_hc_item_t *history_item;
7602
7603 WRLOCK_CACHE;
7604
7605 for (i = 0; i < history_items->values_num; i++)
7606 {
7607 history_item = (zbx_hc_item_t *)history_items->values[i];
7608
7609 if (0 != (ZBX_DC_FLAG_NOVALUE & history_item->tail->flags))
7610 continue;
7611
7612 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &history_item->itemid)))
7613 continue;
7614
7615 if (NULL == dc_item->triggers)
7616 continue;
7617
7618 for (j = 0; NULL != (dc_trigger = dc_item->triggers[j]); j++)
7619 {
7620 if (TRIGGER_STATUS_ENABLED != dc_trigger->status)
7621 continue;
7622
7623 if (1 == dc_trigger->locked)
7624 {
7625 locked_num++;
7626 history_item->status = ZBX_HC_ITEM_STATUS_BUSY;
7627 goto next;
7628 }
7629 }
7630
7631 for (j = 0; NULL != (dc_trigger = dc_item->triggers[j]); j++)
7632 {
7633 if (TRIGGER_STATUS_ENABLED != dc_trigger->status)
7634 continue;
7635
7636 dc_trigger->locked = 1;
7637 zbx_vector_uint64_append(triggerids, dc_trigger->triggerid);
7638 }
7639 next:;
7640 }
7641
7642 UNLOCK_CACHE;
7643
7644 return history_items->values_num - locked_num;
7645 }
7646
7647 /******************************************************************************
7648 * *
7649 * Function: DCconfig_lock_triggers_by_triggerids *
7650 * *
7651 * Purpose: Lock triggers so that multiple processes do not process one *
7652 * trigger simultaneously. *
7653 * *
7654 * Parameters: triggerids_in - [IN] ids of triggers to lock *
7655 * triggerids_out - [OUT] ids of locked triggers *
7656 * *
7657 ******************************************************************************/
DCconfig_lock_triggers_by_triggerids(zbx_vector_uint64_t * triggerids_in,zbx_vector_uint64_t * triggerids_out)7658 void DCconfig_lock_triggers_by_triggerids(zbx_vector_uint64_t *triggerids_in, zbx_vector_uint64_t *triggerids_out)
7659 {
7660 int i;
7661 ZBX_DC_TRIGGER *dc_trigger;
7662
7663 if (0 == triggerids_in->values_num)
7664 return;
7665
7666 WRLOCK_CACHE;
7667
7668 for (i = 0; i < triggerids_in->values_num; i++)
7669 {
7670 if (NULL == (dc_trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &triggerids_in->values[i])))
7671 continue;
7672
7673 if (1 == dc_trigger->locked)
7674 continue;
7675
7676 dc_trigger->locked = 1;
7677 zbx_vector_uint64_append(triggerids_out, dc_trigger->triggerid);
7678 }
7679
7680 UNLOCK_CACHE;
7681 }
7682
7683 /******************************************************************************
7684 * *
7685 * Function: DCconfig_unlock_triggers *
7686 * *
7687 * Author: Aleksandrs Saveljevs *
7688 * *
7689 ******************************************************************************/
DCconfig_unlock_triggers(const zbx_vector_uint64_t * triggerids)7690 void DCconfig_unlock_triggers(const zbx_vector_uint64_t *triggerids)
7691 {
7692 int i;
7693 ZBX_DC_TRIGGER *dc_trigger;
7694
7695 /* no other process can modify already locked triggers without write lock */
7696 RDLOCK_CACHE;
7697
7698 for (i = 0; i < triggerids->values_num; i++)
7699 {
7700 if (NULL == (dc_trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &triggerids->values[i])))
7701 continue;
7702
7703 dc_trigger->locked = 0;
7704 }
7705
7706 UNLOCK_CACHE;
7707 }
7708
7709 /******************************************************************************
7710 * *
7711 * Function: DCconfig_unlock_all_triggers *
7712 * *
7713 * Purpose: Unlocks all locked triggers before doing full history sync at *
7714 * program exit *
7715 * *
7716 ******************************************************************************/
DCconfig_unlock_all_triggers(void)7717 void DCconfig_unlock_all_triggers(void)
7718 {
7719 ZBX_DC_TRIGGER *dc_trigger;
7720 zbx_hashset_iter_t iter;
7721
7722 WRLOCK_CACHE;
7723
7724 zbx_hashset_iter_reset(&config->triggers, &iter);
7725
7726 while (NULL != (dc_trigger = (ZBX_DC_TRIGGER *)zbx_hashset_iter_next(&iter)))
7727 dc_trigger->locked = 0;
7728
7729 UNLOCK_CACHE;
7730 }
7731
7732 /******************************************************************************
7733 * *
7734 * Function: DCconfig_get_triggers_by_itemids *
7735 * *
7736 * Purpose: get enabled triggers for specified items *
7737 * *
7738 * Author: Aleksandrs Saveljevs *
7739 * *
7740 ******************************************************************************/
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)7741 void DCconfig_get_triggers_by_itemids(zbx_hashset_t *trigger_info, zbx_vector_ptr_t *trigger_order,
7742 const zbx_uint64_t *itemids, const zbx_timespec_t *timespecs, int itemids_num)
7743 {
7744 int i, j, found;
7745 const ZBX_DC_ITEM *dc_item;
7746 const ZBX_DC_TRIGGER *dc_trigger;
7747 DC_TRIGGER *trigger;
7748
7749 RDLOCK_CACHE;
7750
7751 for (i = 0; i < itemids_num; i++)
7752 {
7753 /* skip items which are not in configuration cache and items without triggers */
7754
7755 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemids[i])) || NULL == dc_item->triggers)
7756 continue;
7757
7758 /* process all triggers for the specified item */
7759
7760 for (j = 0; NULL != (dc_trigger = dc_item->triggers[j]); j++)
7761 {
7762 if (TRIGGER_STATUS_ENABLED != dc_trigger->status)
7763 continue;
7764
7765 /* find trigger by id or create a new record in hashset if not found */
7766 trigger = (DC_TRIGGER *)DCfind_id(trigger_info, dc_trigger->triggerid, sizeof(DC_TRIGGER), &found);
7767
7768 if (0 == found)
7769 {
7770 DCget_trigger(trigger, dc_trigger);
7771 zbx_vector_ptr_append(trigger_order, trigger);
7772 }
7773
7774 /* copy latest change timestamp */
7775
7776 if (trigger->timespec.sec < timespecs[i].sec ||
7777 (trigger->timespec.sec == timespecs[i].sec &&
7778 trigger->timespec.ns < timespecs[i].ns))
7779 {
7780 /* DCconfig_get_triggers_by_itemids() function is called during trigger processing */
7781 /* when syncing history cache. A trigger cannot be processed by two syncers at the */
7782 /* same time, so its safe to update trigger timespec within read lock. */
7783 trigger->timespec = timespecs[i];
7784 }
7785 }
7786 }
7787
7788 UNLOCK_CACHE;
7789 }
7790
7791 /******************************************************************************
7792 * *
7793 * Function: DCconfig_find_active_time_function *
7794 * *
7795 * Purpose: checks if the expression contains time based functions *
7796 * *
7797 ******************************************************************************/
DCconfig_find_active_time_function(const char * expression)7798 static int DCconfig_find_active_time_function(const char *expression)
7799 {
7800 zbx_uint64_t functionid;
7801 const ZBX_DC_FUNCTION *dc_function;
7802 const ZBX_DC_HOST *dc_host;
7803 const ZBX_DC_ITEM *dc_item;
7804
7805 while (SUCCEED == get_N_functionid(expression, 1, &functionid, &expression))
7806 {
7807 if (NULL == (dc_function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &functionid)))
7808 continue;
7809
7810 if (1 == dc_function->timer)
7811 {
7812 if (NULL == (dc_item = zbx_hashset_search(&config->items, &dc_function->itemid)))
7813 continue;
7814
7815 if (NULL == (dc_host = zbx_hashset_search(&config->hosts, &dc_item->hostid)))
7816 continue;
7817
7818 if (SUCCEED != DCin_maintenance_without_data_collection(dc_host, dc_item))
7819 return SUCCEED;
7820 }
7821 }
7822
7823 return FAIL;
7824 }
7825
7826 /******************************************************************************
7827 * *
7828 * Function: zbx_dc_get_timer_triggers_by_triggerids *
7829 * *
7830 * Purpose: gets timer triggers from cache *
7831 * *
7832 * Parameters: trigger_info - [IN/OUT] triggers *
7833 * trigger_order - [IN/OUT] triggers in processing order *
7834 * triggerids - [IN] identifiers of the triggers to retrieve *
7835 * ts - [IN] current timestamp *
7836 * *
7837 ******************************************************************************/
zbx_dc_get_timer_triggers_by_triggerids(zbx_hashset_t * trigger_info,zbx_vector_ptr_t * trigger_order,const zbx_vector_uint64_t * triggerids,const zbx_timespec_t * ts)7838 void zbx_dc_get_timer_triggers_by_triggerids(zbx_hashset_t *trigger_info, zbx_vector_ptr_t *trigger_order,
7839 const zbx_vector_uint64_t *triggerids, const zbx_timespec_t *ts)
7840 {
7841 int i;
7842 ZBX_DC_TRIGGER *dc_trigger;
7843
7844 RDLOCK_CACHE;
7845
7846 for (i = 0; i < triggerids->values_num; i++)
7847 {
7848 if (NULL != (dc_trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers,
7849 &triggerids->values[i])))
7850 {
7851 DC_TRIGGER *trigger, trigger_local;
7852 unsigned char flags;
7853
7854 if (SUCCEED == DCconfig_find_active_time_function(dc_trigger->expression))
7855 {
7856 flags = ZBX_DC_TRIGGER_PROBLEM_EXPRESSION;
7857 }
7858 else
7859 {
7860 if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION != dc_trigger->recovery_mode)
7861 continue;
7862
7863 if (TRIGGER_VALUE_PROBLEM != dc_trigger->value)
7864 continue;
7865
7866 if (SUCCEED != DCconfig_find_active_time_function(dc_trigger->recovery_expression))
7867 continue;
7868
7869 flags = 0;
7870 }
7871
7872 trigger_local.triggerid = dc_trigger->triggerid;
7873 trigger = (DC_TRIGGER *)zbx_hashset_insert(trigger_info, &trigger_local, sizeof(trigger_local));
7874 DCget_trigger(trigger, dc_trigger);
7875
7876 /* DCconfig_get_triggers_by_itemids() function is called during trigger processing */
7877 /* when syncing history cache. A trigger cannot be processed by two syncers at the */
7878 /* same time, so its safe to update trigger timespec within read lock. */
7879 trigger->timespec = *ts;
7880 trigger->flags = flags;
7881
7882 zbx_vector_ptr_append(trigger_order, trigger);
7883 }
7884 }
7885
7886 UNLOCK_CACHE;
7887 }
7888
7889 /******************************************************************************
7890 * *
7891 * Function: zbx_dc_get_timer_triggerids *
7892 * *
7893 * Purpose: gets triggerids from timer queue *
7894 * *
7895 * Parameters: triggerids - [OUT] timer tirggerids to process *
7896 * now - [IN] current time *
7897 * limit - [IN] the maximum number of triggerids to return *
7898 * *
7899 * Comments: This function locks returned triggerids in configuration cache. *
7900 * *
7901 ******************************************************************************/
zbx_dc_get_timer_triggerids(zbx_vector_uint64_t * triggerids,int now,int limit)7902 void zbx_dc_get_timer_triggerids(zbx_vector_uint64_t *triggerids, int now, int limit)
7903 {
7904 zbx_binary_heap_elem_t *elem;
7905 ZBX_DC_TRIGGER *dc_trigger;
7906 int found = 0;
7907
7908 RDLOCK_CACHE;
7909
7910 if (SUCCEED != zbx_binary_heap_empty(&config->timer_queue))
7911 {
7912 elem = zbx_binary_heap_find_min(&config->timer_queue);
7913 dc_trigger = (ZBX_DC_TRIGGER *)elem->data;
7914
7915 if (dc_trigger->nextcheck <= now)
7916 found = 1;
7917 }
7918
7919 UNLOCK_CACHE;
7920
7921 if (0 == found)
7922 return;
7923
7924 WRLOCK_CACHE;
7925
7926 while (SUCCEED != zbx_binary_heap_empty(&config->timer_queue) && 0 != limit)
7927 {
7928 elem = zbx_binary_heap_find_min(&config->timer_queue);
7929 dc_trigger = (ZBX_DC_TRIGGER *)elem->data;
7930
7931 if (dc_trigger->nextcheck > now)
7932 break;
7933
7934 /* locked triggers are already being processed by other processes, we can skip them */
7935 if (0 == dc_trigger->locked)
7936 {
7937 zbx_vector_uint64_append(triggerids, dc_trigger->triggerid);
7938 dc_trigger->locked = 1;
7939 limit--;
7940 }
7941
7942 dc_trigger->nextcheck = dc_timer_calculate_nextcheck(now, dc_trigger->triggerid);
7943 zbx_binary_heap_update_direct(&config->timer_queue, elem);
7944 }
7945
7946 UNLOCK_CACHE;
7947 }
7948
7949 /******************************************************************************
7950 * *
7951 * Function: zbx_dc_clear_timer_queue *
7952 * *
7953 * Purpose: clears timer trigger queue *
7954 * *
7955 ******************************************************************************/
zbx_dc_clear_timer_queue(void)7956 void zbx_dc_clear_timer_queue(void)
7957 {
7958 WRLOCK_CACHE;
7959 zbx_binary_heap_clear(&config->timer_queue);
7960 UNLOCK_CACHE;
7961 }
7962
DCfree_triggers(zbx_vector_ptr_t * triggers)7963 void DCfree_triggers(zbx_vector_ptr_t *triggers)
7964 {
7965 int i;
7966
7967 for (i = 0; i < triggers->values_num; i++)
7968 DCclean_trigger((DC_TRIGGER *)triggers->values[i]);
7969
7970 zbx_vector_ptr_clear(triggers);
7971 }
7972
DCconfig_update_interface_snmp_stats(zbx_uint64_t interfaceid,int max_snmp_succeed,int min_snmp_fail)7973 void DCconfig_update_interface_snmp_stats(zbx_uint64_t interfaceid, int max_snmp_succeed, int min_snmp_fail)
7974 {
7975 ZBX_DC_SNMPINTERFACE *dc_snmp;
7976
7977 WRLOCK_CACHE;
7978
7979 if (NULL != (dc_snmp = (ZBX_DC_SNMPINTERFACE *)zbx_hashset_search(&config->interfaces_snmp, &interfaceid)) &&
7980 SNMP_BULK_ENABLED == dc_snmp->bulk)
7981 {
7982 if (dc_snmp->max_succeed < max_snmp_succeed)
7983 dc_snmp->max_succeed = (unsigned char)max_snmp_succeed;
7984
7985 if (dc_snmp->min_fail > min_snmp_fail)
7986 dc_snmp->min_fail = (unsigned char)min_snmp_fail;
7987 }
7988
7989 UNLOCK_CACHE;
7990 }
7991
DCconfig_get_suggested_snmp_vars_nolock(zbx_uint64_t interfaceid,int * bulk)7992 static int DCconfig_get_suggested_snmp_vars_nolock(zbx_uint64_t interfaceid, int *bulk)
7993 {
7994 int num;
7995 const ZBX_DC_SNMPINTERFACE *dc_snmp;
7996
7997 dc_snmp = (const ZBX_DC_SNMPINTERFACE *)zbx_hashset_search(&config->interfaces_snmp, &interfaceid);
7998
7999 if (NULL != bulk)
8000 *bulk = (NULL == dc_snmp ? SNMP_BULK_DISABLED : dc_snmp->bulk);
8001
8002 if (NULL == dc_snmp || SNMP_BULK_ENABLED != dc_snmp->bulk)
8003 return 1;
8004
8005 /* The general strategy is to multiply request size by 3/2 in order to approach the limit faster. */
8006 /* However, once we are over the limit, we change the strategy to increasing the value by 1. This */
8007 /* is deemed better than going backwards from the error because less timeouts are going to occur. */
8008
8009 if (1 >= dc_snmp->max_succeed || MAX_SNMP_ITEMS + 1 != dc_snmp->min_fail)
8010 num = dc_snmp->max_succeed + 1;
8011 else
8012 num = dc_snmp->max_succeed * 3 / 2;
8013
8014 if (num < dc_snmp->min_fail)
8015 return num;
8016
8017 /* If we have already found the optimal number of variables to query, we wish to base our suggestion on that */
8018 /* number. If we occasionally get a timeout in this area, it can mean two things: either the device's actual */
8019 /* limit is a bit lower than that (it can process requests above it, but only sometimes) or a UDP packet in */
8020 /* one of the directions was lost. In order to account for the former, we allow ourselves to lower the count */
8021 /* of variables, but only up to two times. Otherwise, performance will gradually degrade due to the latter. */
8022
8023 return MAX(dc_snmp->max_succeed - 2, dc_snmp->min_fail - 1);
8024 }
8025
DCconfig_get_suggested_snmp_vars(zbx_uint64_t interfaceid,int * bulk)8026 int DCconfig_get_suggested_snmp_vars(zbx_uint64_t interfaceid, int *bulk)
8027 {
8028 int ret;
8029
8030 RDLOCK_CACHE;
8031
8032 ret = DCconfig_get_suggested_snmp_vars_nolock(interfaceid, bulk);
8033
8034 UNLOCK_CACHE;
8035
8036 return ret;
8037 }
8038
dc_get_interface_by_type(DC_INTERFACE * interface,zbx_uint64_t hostid,unsigned char type)8039 static int dc_get_interface_by_type(DC_INTERFACE *interface, zbx_uint64_t hostid, unsigned char type)
8040 {
8041 int res = FAIL;
8042 const ZBX_DC_INTERFACE *dc_interface;
8043 const ZBX_DC_INTERFACE_HT *interface_ht;
8044 ZBX_DC_INTERFACE_HT interface_ht_local;
8045
8046 interface_ht_local.hostid = hostid;
8047 interface_ht_local.type = type;
8048
8049 if (NULL != (interface_ht = (const ZBX_DC_INTERFACE_HT *)zbx_hashset_search(&config->interfaces_ht, &interface_ht_local)))
8050 {
8051 dc_interface = interface_ht->interface_ptr;
8052 DCget_interface(interface, dc_interface);
8053 res = SUCCEED;
8054 }
8055
8056 return res;
8057 }
8058
8059 /******************************************************************************
8060 * *
8061 * Function: DCconfig_get_interface_by_type *
8062 * *
8063 * Purpose: Locate main interface of specified type in configuration cache *
8064 * *
8065 * Parameters: interface - [OUT] pointer to DC_INTERFACE structure *
8066 * hostid - [IN] host ID *
8067 * type - [IN] interface type *
8068 * *
8069 * Return value: SUCCEED if record located and FAIL otherwise *
8070 * *
8071 ******************************************************************************/
DCconfig_get_interface_by_type(DC_INTERFACE * interface,zbx_uint64_t hostid,unsigned char type)8072 int DCconfig_get_interface_by_type(DC_INTERFACE *interface, zbx_uint64_t hostid, unsigned char type)
8073 {
8074 int res;
8075
8076 RDLOCK_CACHE;
8077
8078 res = dc_get_interface_by_type(interface, hostid, type);
8079
8080 UNLOCK_CACHE;
8081
8082 return res;
8083 }
8084
8085 /******************************************************************************
8086 * *
8087 * Function: DCconfig_get_interface *
8088 * *
8089 * Purpose: Locate interface in configuration cache *
8090 * *
8091 * Parameters: interface - [OUT] pointer to DC_INTERFACE structure *
8092 * hostid - [IN] host ID *
8093 * itemid - [IN] item ID *
8094 * *
8095 * Return value: SUCCEED if record located and FAIL otherwise *
8096 * *
8097 ******************************************************************************/
DCconfig_get_interface(DC_INTERFACE * interface,zbx_uint64_t hostid,zbx_uint64_t itemid)8098 int DCconfig_get_interface(DC_INTERFACE *interface, zbx_uint64_t hostid, zbx_uint64_t itemid)
8099 {
8100 int res = FAIL, i;
8101 const ZBX_DC_ITEM *dc_item;
8102 const ZBX_DC_INTERFACE *dc_interface;
8103
8104 RDLOCK_CACHE;
8105
8106 if (0 != itemid)
8107 {
8108 if (NULL == (dc_item = (const ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemid)))
8109 goto unlock;
8110
8111 if (0 != dc_item->interfaceid)
8112 {
8113 if (NULL == (dc_interface = (const ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces,
8114 &dc_item->interfaceid)))
8115 {
8116 goto unlock;
8117 }
8118
8119 DCget_interface(interface, dc_interface);
8120 res = SUCCEED;
8121 goto unlock;
8122 }
8123
8124 hostid = dc_item->hostid;
8125 }
8126
8127 if (0 == hostid)
8128 goto unlock;
8129
8130 for (i = 0; i < (int)ARRSIZE(INTERFACE_TYPE_PRIORITY); i++)
8131 {
8132 if (SUCCEED == (res = dc_get_interface_by_type(interface, hostid, INTERFACE_TYPE_PRIORITY[i])))
8133 break;
8134 }
8135
8136 unlock:
8137 UNLOCK_CACHE;
8138
8139 return res;
8140 }
8141
8142 /******************************************************************************
8143 * *
8144 * Function: dc_config_get_queue_nextcheck *
8145 * *
8146 * Purpose: Get nextcheck for selected queue *
8147 * *
8148 * Parameters: queue - [IN] the queue *
8149 * *
8150 * Return value: nextcheck or FAIL if no items for the specified queue *
8151 * *
8152 ******************************************************************************/
dc_config_get_queue_nextcheck(zbx_binary_heap_t * queue)8153 static int dc_config_get_queue_nextcheck(zbx_binary_heap_t *queue)
8154 {
8155 int nextcheck;
8156 const zbx_binary_heap_elem_t *min;
8157 const ZBX_DC_ITEM *dc_item;
8158
8159 if (FAIL == zbx_binary_heap_empty(queue))
8160 {
8161 min = zbx_binary_heap_find_min(queue);
8162 dc_item = (const ZBX_DC_ITEM *)min->data;
8163
8164 nextcheck = dc_item->nextcheck;
8165 }
8166 else
8167 nextcheck = FAIL;
8168
8169 return nextcheck;
8170 }
8171
8172 /******************************************************************************
8173 * *
8174 * Function: DCconfig_get_poller_nextcheck *
8175 * *
8176 * Purpose: Get nextcheck for selected poller *
8177 * *
8178 * Parameters: poller_type - [IN] poller type (ZBX_POLLER_TYPE_...) *
8179 * *
8180 * Return value: nextcheck or FAIL if no items for selected poller *
8181 * *
8182 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
8183 * *
8184 ******************************************************************************/
DCconfig_get_poller_nextcheck(unsigned char poller_type)8185 int DCconfig_get_poller_nextcheck(unsigned char poller_type)
8186 {
8187 int nextcheck;
8188 zbx_binary_heap_t *queue;
8189
8190 zabbix_log(LOG_LEVEL_DEBUG, "In %s() poller_type:%d", __func__, (int)poller_type);
8191
8192 queue = &config->queues[poller_type];
8193
8194 RDLOCK_CACHE;
8195
8196 nextcheck = dc_config_get_queue_nextcheck(queue);
8197
8198 UNLOCK_CACHE;
8199
8200 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __func__, nextcheck);
8201
8202 return nextcheck;
8203 }
8204
dc_requeue_item(ZBX_DC_ITEM * dc_item,const ZBX_DC_HOST * dc_host,unsigned char new_state,int flags,int lastclock)8205 static void dc_requeue_item(ZBX_DC_ITEM *dc_item, const ZBX_DC_HOST *dc_host, unsigned char new_state, int flags,
8206 int lastclock)
8207 {
8208 unsigned char old_poller_type;
8209 int old_nextcheck;
8210
8211 old_nextcheck = dc_item->nextcheck;
8212 DCitem_nextcheck_update(dc_item, dc_host, new_state, flags, lastclock, NULL);
8213
8214 old_poller_type = dc_item->poller_type;
8215 DCitem_poller_type_update(dc_item, dc_host, flags);
8216
8217 DCupdate_item_queue(dc_item, old_poller_type, old_nextcheck);
8218 }
8219
8220 /******************************************************************************
8221 * *
8222 * Function: dc_requeue_item_at *
8223 * *
8224 * Purpose: requeues items at the specified time *
8225 * *
8226 * Parameters: dc_item - [IN] the item to reque *
8227 * dc_host - [IN] item's host *
8228 * nextcheck - [IN] the scheduled time *
8229 * *
8230 ******************************************************************************/
dc_requeue_item_at(ZBX_DC_ITEM * dc_item,ZBX_DC_HOST * dc_host,int nextcheck)8231 static void dc_requeue_item_at(ZBX_DC_ITEM *dc_item, ZBX_DC_HOST *dc_host, int nextcheck)
8232 {
8233 unsigned char old_poller_type;
8234 int old_nextcheck;
8235
8236 dc_item->queue_priority = ZBX_QUEUE_PRIORITY_HIGH;
8237
8238 old_nextcheck = dc_item->nextcheck;
8239 dc_item->nextcheck = nextcheck;
8240
8241 old_poller_type = dc_item->poller_type;
8242 DCitem_poller_type_update(dc_item, dc_host, ZBX_ITEM_COLLECTED);
8243
8244 DCupdate_item_queue(dc_item, old_poller_type, old_nextcheck);
8245 }
8246
8247 /******************************************************************************
8248 * *
8249 * Function: DCconfig_get_poller_items *
8250 * *
8251 * Purpose: Get array of items for selected poller *
8252 * *
8253 * Parameters: poller_type - [IN] poller type (ZBX_POLLER_TYPE_...) *
8254 * items - [OUT] array of items *
8255 * *
8256 * Return value: number of items in items array *
8257 * *
8258 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
8259 * *
8260 * Comments: Items leave the queue only through this function. Pollers must *
8261 * always return the items they have taken using DCrequeue_items() *
8262 * or DCpoller_requeue_items(). *
8263 * *
8264 * Currently batch polling is supported only for JMX, SNMP and *
8265 * icmpping* simple checks. In other cases only single item is *
8266 * retrieved. *
8267 * *
8268 * IPMI poller queue are handled by DCconfig_get_ipmi_poller_items()*
8269 * function. *
8270 * *
8271 ******************************************************************************/
DCconfig_get_poller_items(unsigned char poller_type,DC_ITEM ** items)8272 int DCconfig_get_poller_items(unsigned char poller_type, DC_ITEM **items)
8273 {
8274 int now, num = 0, max_items;
8275 zbx_binary_heap_t *queue;
8276
8277 zabbix_log(LOG_LEVEL_DEBUG, "In %s() poller_type:%d", __func__, (int)poller_type);
8278
8279 now = time(NULL);
8280
8281 queue = &config->queues[poller_type];
8282
8283 switch (poller_type)
8284 {
8285 case ZBX_POLLER_TYPE_JAVA:
8286 max_items = MAX_JAVA_ITEMS;
8287 break;
8288 case ZBX_POLLER_TYPE_PINGER:
8289 max_items = MAX_PINGER_ITEMS;
8290 break;
8291 default:
8292 max_items = 1;
8293 }
8294
8295 WRLOCK_CACHE;
8296
8297 while (num < max_items && FAIL == zbx_binary_heap_empty(queue))
8298 {
8299 int disable_until;
8300 const zbx_binary_heap_elem_t *min;
8301 ZBX_DC_HOST *dc_host;
8302 ZBX_DC_ITEM *dc_item;
8303 static const ZBX_DC_ITEM *dc_item_prev = NULL;
8304
8305 min = zbx_binary_heap_find_min(queue);
8306 dc_item = (ZBX_DC_ITEM *)min->data;
8307
8308 if (dc_item->nextcheck > now)
8309 break;
8310
8311 if (0 != num)
8312 {
8313 if (ITEM_TYPE_SNMP == dc_item_prev->type)
8314 {
8315 if (0 != __config_snmp_item_compare(dc_item_prev, dc_item))
8316 break;
8317 }
8318 else if (ITEM_TYPE_JMX == dc_item_prev->type)
8319 {
8320 if (0 != __config_java_item_compare(dc_item_prev, dc_item))
8321 break;
8322 }
8323 }
8324
8325 zbx_binary_heap_remove_min(queue);
8326 dc_item->location = ZBX_LOC_NOWHERE;
8327
8328 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
8329 continue;
8330
8331 if (HOST_STATUS_MONITORED != dc_host->status)
8332 continue;
8333
8334 if (SUCCEED == DCin_maintenance_without_data_collection(dc_host, dc_item))
8335 {
8336 dc_requeue_item(dc_item, dc_host, dc_item->state, ZBX_ITEM_COLLECTED, now);
8337 continue;
8338 }
8339
8340 /* don't apply unreachable item/host throttling for prioritized items */
8341 if (ZBX_QUEUE_PRIORITY_HIGH != dc_item->queue_priority)
8342 {
8343 if (0 == (disable_until = DCget_disable_until(dc_item, dc_host)))
8344 {
8345 /* move reachable items on reachable hosts to normal pollers */
8346 if (ZBX_POLLER_TYPE_UNREACHABLE == poller_type &&
8347 ZBX_QUEUE_PRIORITY_LOW != dc_item->queue_priority)
8348 {
8349 dc_requeue_item(dc_item, dc_host, dc_item->state, ZBX_ITEM_COLLECTED, now);
8350 continue;
8351 }
8352 }
8353 else
8354 {
8355 /* move items on unreachable hosts to unreachable pollers or */
8356 /* postpone checks on hosts that have been checked recently and */
8357 /* are still unreachable */
8358 if (ZBX_POLLER_TYPE_NORMAL == poller_type || ZBX_POLLER_TYPE_JAVA == poller_type ||
8359 disable_until > now)
8360 {
8361 dc_requeue_item(dc_item, dc_host, dc_item->state,
8362 ZBX_ITEM_COLLECTED | ZBX_HOST_UNREACHABLE, now);
8363 continue;
8364 }
8365
8366 DCincrease_disable_until(dc_item, dc_host, now);
8367 }
8368 }
8369
8370 if (0 == num)
8371 {
8372 if (ZBX_POLLER_TYPE_NORMAL == poller_type && ITEM_TYPE_SNMP == dc_item->type &&
8373 0 == (ZBX_FLAG_DISCOVERY_RULE & dc_item->flags))
8374 {
8375 ZBX_DC_SNMPITEM *snmpitem;
8376
8377 snmpitem = (ZBX_DC_SNMPITEM *)zbx_hashset_search(&config->snmpitems, &dc_item->itemid);
8378
8379 if (ZBX_SNMP_OID_TYPE_NORMAL == snmpitem->snmp_oid_type ||
8380 ZBX_SNMP_OID_TYPE_DYNAMIC == snmpitem->snmp_oid_type)
8381 {
8382 max_items = DCconfig_get_suggested_snmp_vars_nolock(dc_item->interfaceid, NULL);
8383 }
8384 }
8385
8386 if (1 < max_items)
8387 *items = zbx_malloc(NULL, sizeof(DC_ITEM) * max_items);
8388 }
8389
8390 dc_item_prev = dc_item;
8391 dc_item->location = ZBX_LOC_POLLER;
8392 DCget_host(&(*items)[num].host, dc_host, ZBX_ITEM_GET_ALL);
8393 DCget_item(&(*items)[num], dc_item, ZBX_ITEM_GET_ALL);
8394 num++;
8395 }
8396
8397 UNLOCK_CACHE;
8398
8399 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __func__, num);
8400
8401 return num;
8402 }
8403
8404 /******************************************************************************
8405 * *
8406 * Function: DCconfig_get_ipmi_poller_items *
8407 * *
8408 * Purpose: Get array of items for IPMI poller *
8409 * *
8410 * Parameters: now - [IN] current timestamp *
8411 * items - [OUT] array of items *
8412 * items_num - [IN] the number of items to get *
8413 * nextcheck - [OUT] the next scheduled check *
8414 * *
8415 * Return value: number of items in items array *
8416 * *
8417 * Comments: IPMI items leave the queue only through this function. IPMI *
8418 * manager must always return the items they have taken using *
8419 * DCrequeue_items() or DCpoller_requeue_items(). *
8420 * *
8421 ******************************************************************************/
DCconfig_get_ipmi_poller_items(int now,DC_ITEM * items,int items_num,int * nextcheck)8422 int DCconfig_get_ipmi_poller_items(int now, DC_ITEM *items, int items_num, int *nextcheck)
8423 {
8424 int num = 0;
8425 zbx_binary_heap_t *queue;
8426
8427 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
8428
8429 queue = &config->queues[ZBX_POLLER_TYPE_IPMI];
8430
8431 WRLOCK_CACHE;
8432
8433 while (num < items_num && FAIL == zbx_binary_heap_empty(queue))
8434 {
8435 int disable_until;
8436 const zbx_binary_heap_elem_t *min;
8437 ZBX_DC_HOST *dc_host;
8438 ZBX_DC_ITEM *dc_item;
8439
8440 min = zbx_binary_heap_find_min(queue);
8441 dc_item = (ZBX_DC_ITEM *)min->data;
8442
8443 if (dc_item->nextcheck > now)
8444 break;
8445
8446 zbx_binary_heap_remove_min(queue);
8447 dc_item->location = ZBX_LOC_NOWHERE;
8448
8449 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
8450 continue;
8451
8452 if (HOST_STATUS_MONITORED != dc_host->status)
8453 continue;
8454
8455 if (SUCCEED == DCin_maintenance_without_data_collection(dc_host, dc_item))
8456 {
8457 dc_requeue_item(dc_item, dc_host, dc_item->state, ZBX_ITEM_COLLECTED, now);
8458 continue;
8459 }
8460
8461 /* don't apply unreachable item/host throttling for prioritized items */
8462 if (ZBX_QUEUE_PRIORITY_HIGH != dc_item->queue_priority)
8463 {
8464 if (0 != (disable_until = DCget_disable_until(dc_item, dc_host)))
8465 {
8466 if (disable_until > now)
8467 {
8468 dc_requeue_item(dc_item, dc_host, dc_item->state,
8469 ZBX_ITEM_COLLECTED | ZBX_HOST_UNREACHABLE, now);
8470 continue;
8471 }
8472
8473 DCincrease_disable_until(dc_item, dc_host, now);
8474 }
8475 }
8476
8477 dc_item->location = ZBX_LOC_POLLER;
8478 DCget_host(&items[num].host, dc_host, ZBX_ITEM_GET_ALL);
8479 DCget_item(&items[num], dc_item, ZBX_ITEM_GET_ALL);
8480 num++;
8481 }
8482
8483 *nextcheck = dc_config_get_queue_nextcheck(&config->queues[ZBX_POLLER_TYPE_IPMI]);
8484
8485 UNLOCK_CACHE;
8486
8487 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __func__, num);
8488
8489 return num;
8490 }
8491
8492
8493 /******************************************************************************
8494 * *
8495 * Function: DCconfig_get_snmp_interfaceids_by_addr *
8496 * *
8497 * Purpose: get array of interface IDs for the specified address *
8498 * *
8499 * Return value: number of interface IDs returned *
8500 * *
8501 * Author: Rudolfs Kreicbergs *
8502 * *
8503 ******************************************************************************/
DCconfig_get_snmp_interfaceids_by_addr(const char * addr,zbx_uint64_t ** interfaceids)8504 int DCconfig_get_snmp_interfaceids_by_addr(const char *addr, zbx_uint64_t **interfaceids)
8505 {
8506 int count = 0, i;
8507 const ZBX_DC_INTERFACE_ADDR *dc_interface_snmpaddr;
8508 ZBX_DC_INTERFACE_ADDR dc_interface_snmpaddr_local;
8509
8510 zabbix_log(LOG_LEVEL_DEBUG, "In %s() addr:'%s'", __func__, addr);
8511
8512 dc_interface_snmpaddr_local.addr = addr;
8513
8514 RDLOCK_CACHE;
8515
8516 if (NULL == (dc_interface_snmpaddr = (const ZBX_DC_INTERFACE_ADDR *)zbx_hashset_search(&config->interface_snmpaddrs, &dc_interface_snmpaddr_local)))
8517 goto unlock;
8518
8519 *interfaceids = (zbx_uint64_t *)zbx_malloc(*interfaceids, dc_interface_snmpaddr->interfaceids.values_num * sizeof(zbx_uint64_t));
8520
8521 for (i = 0; i < dc_interface_snmpaddr->interfaceids.values_num; i++)
8522 (*interfaceids)[i] = dc_interface_snmpaddr->interfaceids.values[i];
8523
8524 count = i;
8525 unlock:
8526 UNLOCK_CACHE;
8527
8528 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __func__, count);
8529
8530 return count;
8531 }
8532
8533 /******************************************************************************
8534 * *
8535 * Function: DCconfig_get_snmp_items_by_interfaceid *
8536 * *
8537 * Purpose: get array of snmp trap items for the specified interfaceid *
8538 * *
8539 * Return value: number of items returned *
8540 * *
8541 * Author: Rudolfs Kreicbergs *
8542 * *
8543 ******************************************************************************/
DCconfig_get_snmp_items_by_interfaceid(zbx_uint64_t interfaceid,DC_ITEM ** items)8544 size_t DCconfig_get_snmp_items_by_interfaceid(zbx_uint64_t interfaceid, DC_ITEM **items)
8545 {
8546 size_t items_num = 0, items_alloc = 8;
8547 int i;
8548 const ZBX_DC_ITEM *dc_item;
8549 const ZBX_DC_INTERFACE_ITEM *dc_interface_snmpitem;
8550 const ZBX_DC_INTERFACE *dc_interface;
8551 const ZBX_DC_HOST *dc_host;
8552
8553 zabbix_log(LOG_LEVEL_DEBUG, "In %s() interfaceid:" ZBX_FS_UI64, __func__, interfaceid);
8554
8555 RDLOCK_CACHE;
8556
8557 if (NULL == (dc_interface = (const ZBX_DC_INTERFACE *)zbx_hashset_search(&config->interfaces, &interfaceid)))
8558 goto unlock;
8559
8560 if (NULL == (dc_host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_interface->hostid)))
8561 goto unlock;
8562
8563 if (HOST_STATUS_MONITORED != dc_host->status)
8564 goto unlock;
8565
8566 if (NULL == (dc_interface_snmpitem = (const ZBX_DC_INTERFACE_ITEM *)zbx_hashset_search(&config->interface_snmpitems, &interfaceid)))
8567 goto unlock;
8568
8569 *items = (DC_ITEM *)zbx_malloc(*items, items_alloc * sizeof(DC_ITEM));
8570
8571 for (i = 0; i < dc_interface_snmpitem->itemids.values_num; i++)
8572 {
8573 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &dc_interface_snmpitem->itemids.values[i])))
8574 continue;
8575
8576 if (ITEM_STATUS_ACTIVE != dc_item->status)
8577 continue;
8578
8579 if (SUCCEED == DCin_maintenance_without_data_collection(dc_host, dc_item))
8580 continue;
8581
8582 if (0 == config->config->refresh_unsupported && ITEM_STATE_NOTSUPPORTED == dc_item->state)
8583 continue;
8584
8585 if (items_num == items_alloc)
8586 {
8587 items_alloc += 8;
8588 *items = (DC_ITEM *)zbx_realloc(*items, items_alloc * sizeof(DC_ITEM));
8589 }
8590
8591 DCget_host(&(*items)[items_num].host, dc_host, ZBX_ITEM_GET_ALL);
8592 DCget_item(&(*items)[items_num], dc_item, ZBX_ITEM_GET_ALL);
8593 items_num++;
8594 }
8595 unlock:
8596 UNLOCK_CACHE;
8597
8598 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():" ZBX_FS_SIZE_T, __func__, (zbx_fs_size_t)items_num);
8599
8600 return items_num;
8601 }
8602
dc_requeue_items(const zbx_uint64_t * itemids,const unsigned char * states,const int * lastclocks,const int * errcodes,size_t num)8603 static void dc_requeue_items(const zbx_uint64_t *itemids, const unsigned char *states, const int *lastclocks,
8604 const int *errcodes, size_t num)
8605 {
8606 size_t i;
8607 ZBX_DC_ITEM *dc_item;
8608 ZBX_DC_HOST *dc_host;
8609
8610 for (i = 0; i < num; i++)
8611 {
8612 if (FAIL == errcodes[i])
8613 continue;
8614
8615 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemids[i])))
8616 continue;
8617
8618 if (ZBX_LOC_POLLER == dc_item->location)
8619 dc_item->location = ZBX_LOC_NOWHERE;
8620
8621 if (ITEM_STATUS_ACTIVE != dc_item->status)
8622 continue;
8623
8624 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
8625 continue;
8626
8627 if (HOST_STATUS_MONITORED != dc_host->status)
8628 continue;
8629
8630 if (SUCCEED != zbx_is_counted_in_item_queue(dc_item->type, dc_item->key))
8631 continue;
8632
8633 switch (errcodes[i])
8634 {
8635 case SUCCEED:
8636 case NOTSUPPORTED:
8637 case AGENT_ERROR:
8638 case CONFIG_ERROR:
8639 dc_item->queue_priority = ZBX_QUEUE_PRIORITY_NORMAL;
8640 dc_requeue_item(dc_item, dc_host, states[i], ZBX_ITEM_COLLECTED, lastclocks[i]);
8641 break;
8642 case NETWORK_ERROR:
8643 case GATEWAY_ERROR:
8644 case TIMEOUT_ERROR:
8645 dc_item->queue_priority = ZBX_QUEUE_PRIORITY_LOW;
8646 dc_requeue_item(dc_item, dc_host, states[i], ZBX_ITEM_COLLECTED | ZBX_HOST_UNREACHABLE,
8647 time(NULL));
8648 break;
8649 default:
8650 THIS_SHOULD_NEVER_HAPPEN;
8651 }
8652 }
8653 }
8654
DCrequeue_items(const zbx_uint64_t * itemids,const unsigned char * states,const int * lastclocks,const int * errcodes,size_t num)8655 void DCrequeue_items(const zbx_uint64_t *itemids, const unsigned char *states, const int *lastclocks,
8656 const int *errcodes, size_t num)
8657 {
8658 WRLOCK_CACHE;
8659
8660 dc_requeue_items(itemids, states, lastclocks, errcodes, num);
8661
8662 UNLOCK_CACHE;
8663 }
8664
DCpoller_requeue_items(const zbx_uint64_t * itemids,const unsigned char * states,const int * lastclocks,const int * errcodes,size_t num,unsigned char poller_type,int * nextcheck)8665 void DCpoller_requeue_items(const zbx_uint64_t *itemids, const unsigned char *states, const int *lastclocks,
8666 const int *errcodes, size_t num, unsigned char poller_type, int *nextcheck)
8667 {
8668 WRLOCK_CACHE;
8669
8670 dc_requeue_items(itemids, states, lastclocks, errcodes, num);
8671 *nextcheck = dc_config_get_queue_nextcheck(&config->queues[poller_type]);
8672
8673 UNLOCK_CACHE;
8674 }
8675
8676 /******************************************************************************
8677 * *
8678 * Function: zbx_dc_requeue_unreachable_items *
8679 * *
8680 * Purpose: requeue unreachable items *
8681 * *
8682 * Parameters: itemids - [IN] the item id array *
8683 * itemids_num - [IN] the number of values in itemids array *
8684 * *
8685 * Comments: This function is used when items must be put back in the queue *
8686 * without polling them. For example if a poller has taken a batch *
8687 * of items from queue, host becomes unreachable during while *
8688 * polling the items, so the unpolled items of the same host must *
8689 * be returned to queue without updating their status. *
8690 * *
8691 ******************************************************************************/
zbx_dc_requeue_unreachable_items(zbx_uint64_t * itemids,size_t itemids_num)8692 void zbx_dc_requeue_unreachable_items(zbx_uint64_t *itemids, size_t itemids_num)
8693 {
8694 size_t i;
8695 ZBX_DC_ITEM *dc_item;
8696 ZBX_DC_HOST *dc_host;
8697
8698 WRLOCK_CACHE;
8699
8700 for (i = 0; i < itemids_num; i++)
8701 {
8702 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemids[i])))
8703 continue;
8704
8705 if (ZBX_LOC_POLLER == dc_item->location)
8706 dc_item->location = ZBX_LOC_NOWHERE;
8707
8708 if (ITEM_STATUS_ACTIVE != dc_item->status)
8709 continue;
8710
8711 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
8712 continue;
8713
8714 if (HOST_STATUS_MONITORED != dc_host->status)
8715 continue;
8716
8717 dc_requeue_item(dc_item, dc_host, dc_item->state, ZBX_ITEM_COLLECTED | ZBX_HOST_UNREACHABLE,
8718 time(NULL));
8719 }
8720
8721 UNLOCK_CACHE;
8722 }
8723
8724 /******************************************************************************
8725 * *
8726 * Function: DChost_get_agent_availability *
8727 * *
8728 * Purpose: get host availability data for the specified agent *
8729 * *
8730 * Parameters: dc_host - [IN] the host *
8731 * agent - [IN] the agent (see ZBX_FLAGS_AGENT_STATUS_* *
8732 * defines *
8733 * availability - [OUT] the host availability data *
8734 * *
8735 * Comments: The configuration cache must be locked already. *
8736 * *
8737 ******************************************************************************/
DChost_get_agent_availability(const ZBX_DC_HOST * dc_host,unsigned char agent_type,zbx_agent_availability_t * agent)8738 static void DChost_get_agent_availability(const ZBX_DC_HOST *dc_host, unsigned char agent_type,
8739 zbx_agent_availability_t *agent)
8740 {
8741
8742 agent->flags = ZBX_FLAGS_AGENT_STATUS;
8743
8744 switch (agent_type)
8745 {
8746 case ZBX_AGENT_ZABBIX:
8747 agent->available = dc_host->available;
8748 agent->error = zbx_strdup(agent->error, dc_host->error);
8749 agent->errors_from = dc_host->errors_from;
8750 agent->disable_until = dc_host->disable_until;
8751 break;
8752 case ZBX_AGENT_SNMP:
8753 agent->available = dc_host->snmp_available;
8754 agent->error = zbx_strdup(agent->error, dc_host->snmp_error);
8755 agent->errors_from = dc_host->snmp_errors_from;
8756 agent->disable_until = dc_host->snmp_disable_until;
8757 break;
8758 case ZBX_AGENT_IPMI:
8759 agent->available = dc_host->ipmi_available;
8760 agent->error = zbx_strdup(agent->error, dc_host->ipmi_error);
8761 agent->errors_from = dc_host->ipmi_errors_from;
8762 agent->disable_until = dc_host->ipmi_disable_until;
8763 break;
8764 case ZBX_AGENT_JMX:
8765 agent->available = dc_host->jmx_available;
8766 agent->error = zbx_strdup(agent->error, dc_host->jmx_error);
8767 agent->errors_from = dc_host->jmx_errors_from;
8768 agent->disable_until = dc_host->jmx_disable_until;
8769 break;
8770 }
8771 }
8772
DCagent_set_availability(zbx_agent_availability_t * av,unsigned char * available,const char ** error,int * errors_from,int * disable_until)8773 static void DCagent_set_availability(zbx_agent_availability_t *av, unsigned char *available, const char **error,
8774 int *errors_from, int *disable_until)
8775 {
8776 #define AGENT_AVAILABILITY_ASSIGN(flags, mask, dst, src) \
8777 if (0 != (flags & mask)) \
8778 { \
8779 if (dst != src) \
8780 dst = src; \
8781 else \
8782 flags &= (~(mask)); \
8783 }
8784
8785 #define AGENT_AVAILABILITY_ASSIGN_STR(flags, mask, dst, src) \
8786 if (0 != (flags & mask)) \
8787 { \
8788 if (0 != strcmp(dst, src)) \
8789 DCstrpool_replace(1, &dst, src); \
8790 else \
8791 flags &= (~(mask)); \
8792 }
8793
8794 AGENT_AVAILABILITY_ASSIGN(av->flags, ZBX_FLAGS_AGENT_STATUS_AVAILABLE, *available, av->available);
8795 AGENT_AVAILABILITY_ASSIGN_STR(av->flags, ZBX_FLAGS_AGENT_STATUS_ERROR, *error, av->error);
8796 AGENT_AVAILABILITY_ASSIGN(av->flags, ZBX_FLAGS_AGENT_STATUS_ERRORS_FROM, *errors_from, av->errors_from);
8797 AGENT_AVAILABILITY_ASSIGN(av->flags, ZBX_FLAGS_AGENT_STATUS_DISABLE_UNTIL, *disable_until, av->disable_until);
8798
8799 #undef AGENT_AVAILABILITY_ASSIGN_STR
8800 #undef AGENT_AVAILABILITY_ASSIGN
8801 }
8802
8803 /******************************************************************************
8804 * *
8805 * Function: DChost_set_agent_availability *
8806 * *
8807 * Purpose: set host availability data in configuration cache *
8808 * *
8809 * Parameters: dc_host - [OUT] the host *
8810 * availability - [IN/OUT] the host availability data *
8811 * *
8812 * Return value: SUCCEED - at least one availability field was updated *
8813 * FAIL - no availability fields were updated *
8814 * *
8815 * Comments: The configuration cache must be locked already. *
8816 * *
8817 * This function clears availability flags of non updated fields *
8818 * updated leaving only flags identifying changed fields. *
8819 * *
8820 ******************************************************************************/
DChost_set_agent_availability(ZBX_DC_HOST * dc_host,int now,unsigned char agent_type,zbx_agent_availability_t * agent)8821 static int DChost_set_agent_availability(ZBX_DC_HOST *dc_host, int now, unsigned char agent_type,
8822 zbx_agent_availability_t *agent)
8823 {
8824 switch (agent_type)
8825 {
8826 case ZBX_AGENT_ZABBIX:
8827 DCagent_set_availability(agent, &dc_host->available,
8828 &dc_host->error, &dc_host->errors_from, &dc_host->disable_until);
8829 break;
8830 case ZBX_AGENT_SNMP:
8831 DCagent_set_availability(agent, &dc_host->snmp_available,
8832 &dc_host->snmp_error, &dc_host->snmp_errors_from, &dc_host->snmp_disable_until);
8833 break;
8834 case ZBX_AGENT_IPMI:
8835 DCagent_set_availability(agent, &dc_host->ipmi_available,
8836 &dc_host->ipmi_error, &dc_host->ipmi_errors_from, &dc_host->ipmi_disable_until);
8837 break;
8838 case ZBX_AGENT_JMX:
8839 DCagent_set_availability(agent, &dc_host->jmx_available,
8840 &dc_host->jmx_error, &dc_host->jmx_errors_from, &dc_host->jmx_disable_until);
8841 break;
8842 }
8843
8844 if (ZBX_FLAGS_AGENT_STATUS_NONE == agent->flags)
8845 return FAIL;
8846
8847 if (0 != (agent->flags & (ZBX_FLAGS_AGENT_STATUS_AVAILABLE | ZBX_FLAGS_AGENT_STATUS_ERROR)))
8848 dc_host->availability_ts = now;
8849
8850 return SUCCEED;
8851 }
8852
8853 /******************************************************************************
8854 * *
8855 * Function: DChost_set_availability *
8856 * *
8857 * Purpose: set host availability data in configuration cache *
8858 * *
8859 * Parameters: dc_host - [OUT] the host *
8860 * availability - [IN/OUT] the host availability data *
8861 * *
8862 * Return value: SUCCEED - at least one availability field was updated *
8863 * FAIL - no availability fields were updated *
8864 * *
8865 * Comments: The configuration cache must be locked already. *
8866 * *
8867 * This function clears availability flags of non updated fields *
8868 * updated leaving only flags identifying changed fields. *
8869 * *
8870 ******************************************************************************/
DChost_set_availability(ZBX_DC_HOST * dc_host,int now,zbx_host_availability_t * ha)8871 static int DChost_set_availability(ZBX_DC_HOST *dc_host, int now, zbx_host_availability_t *ha)
8872 {
8873 int i;
8874 unsigned char flags = ZBX_FLAGS_AGENT_STATUS_NONE;
8875
8876 DCagent_set_availability(&ha->agents[ZBX_AGENT_ZABBIX], &dc_host->available, &dc_host->error,
8877 &dc_host->errors_from, &dc_host->disable_until);
8878 DCagent_set_availability(&ha->agents[ZBX_AGENT_SNMP], &dc_host->snmp_available, &dc_host->snmp_error,
8879 &dc_host->snmp_errors_from, &dc_host->snmp_disable_until);
8880 DCagent_set_availability(&ha->agents[ZBX_AGENT_IPMI], &dc_host->ipmi_available, &dc_host->ipmi_error,
8881 &dc_host->ipmi_errors_from, &dc_host->ipmi_disable_until);
8882 DCagent_set_availability(&ha->agents[ZBX_AGENT_JMX], &dc_host->jmx_available, &dc_host->jmx_error,
8883 &dc_host->jmx_errors_from, &dc_host->jmx_disable_until);
8884
8885 for (i = 0; i < ZBX_AGENT_MAX; i++)
8886 flags |= ha->agents[i].flags;
8887
8888 if (ZBX_FLAGS_AGENT_STATUS_NONE == flags)
8889 return FAIL;
8890
8891 if (0 != (flags & (ZBX_FLAGS_AGENT_STATUS_AVAILABLE | ZBX_FLAGS_AGENT_STATUS_ERROR)))
8892 dc_host->availability_ts = now;
8893
8894 return SUCCEED;
8895 }
8896
8897 /******************************************************************************
8898 * *
8899 * Function: zbx_host_availability_init *
8900 * *
8901 * Purpose: initializes host availability data *
8902 * *
8903 * Parameters: availability - [IN/OUT] host availability data *
8904 * *
8905 ******************************************************************************/
zbx_host_availability_init(zbx_host_availability_t * availability,zbx_uint64_t hostid)8906 void zbx_host_availability_init(zbx_host_availability_t *availability, zbx_uint64_t hostid)
8907 {
8908 memset(availability, 0, sizeof(zbx_host_availability_t));
8909 availability->hostid = hostid;
8910 }
8911
8912 /******************************************************************************
8913 * *
8914 * Function: zbx_host_availability_clean *
8915 * *
8916 * Purpose: releases resources allocated to store host availability data *
8917 * *
8918 * Parameters: ha - [IN] host availability data *
8919 * *
8920 ******************************************************************************/
zbx_host_availability_clean(zbx_host_availability_t * ha)8921 void zbx_host_availability_clean(zbx_host_availability_t *ha)
8922 {
8923 int i;
8924
8925 for (i = 0; i < ZBX_AGENT_MAX; i++)
8926 zbx_free(ha->agents[i].error);
8927 }
8928
8929 /******************************************************************************
8930 * *
8931 * Function: zbx_host_availability_free *
8932 * *
8933 * Purpose: frees host availability data *
8934 * *
8935 * Parameters: availability - [IN] host availability data *
8936 * *
8937 ******************************************************************************/
zbx_host_availability_free(zbx_host_availability_t * availability)8938 void zbx_host_availability_free(zbx_host_availability_t *availability)
8939 {
8940 zbx_host_availability_clean(availability);
8941 zbx_free(availability);
8942 }
8943
8944 /******************************************************************************
8945 * *
8946 * Function: zbx_agent_availability_init *
8947 * *
8948 * Purpose: initializes agent availability with the specified data *
8949 * *
8950 * Parameters: availability - [IN/OUT] agent availability data *
8951 * hostid - [IN] the host identifier *
8952 * flags - [IN] the availability flags indicating which *
8953 * availability fields to set *
8954 * available - [IN] the availability data *
8955 * error - [IN] *
8956 * errors_from - [IN] *
8957 * disable_until - [IN] *
8958 * *
8959 ******************************************************************************/
zbx_agent_availability_init(zbx_agent_availability_t * agent,unsigned char available,const char * error,int errors_from,int disable_until)8960 static void zbx_agent_availability_init(zbx_agent_availability_t *agent, unsigned char available, const char *error,
8961 int errors_from, int disable_until)
8962 {
8963 agent->flags = ZBX_FLAGS_AGENT_STATUS;
8964 agent->available = available;
8965 agent->error = zbx_strdup(agent->error, error);
8966 agent->errors_from = errors_from;
8967 agent->disable_until = disable_until;
8968 }
8969
8970 /******************************************************************************
8971 * *
8972 * Function: zbx_host_availability_is_set *
8973 * *
8974 * Purpose: checks host availability if any agent availability field is set *
8975 * *
8976 * Parameters: availability - [IN] host availability data *
8977 * *
8978 * Return value: SUCCEED - an agent availability field is set *
8979 * FAIL - no agent availability fields are set *
8980 * *
8981 ******************************************************************************/
zbx_host_availability_is_set(const zbx_host_availability_t * ha)8982 int zbx_host_availability_is_set(const zbx_host_availability_t *ha)
8983 {
8984 int i;
8985
8986 for (i = 0; i < ZBX_AGENT_MAX; i++)
8987 {
8988 if (ZBX_FLAGS_AGENT_STATUS_NONE != ha->agents[i].flags)
8989 return SUCCEED;
8990 }
8991
8992 return FAIL;
8993 }
8994
8995 /**************************************************************************************
8996 * *
8997 * Host availability update example *
8998 * *
8999 * *
9000 * | UnreachablePeriod *
9001 * | (conf file) *
9002 * | ______________ *
9003 * | / \ *
9004 * | p p p p p p *
9005 * | o o o o o o *
9006 * | l l l l l l *
9007 * | l l l l l l *
9008 * | n *
9009 * | e e e e e e e *
9010 * agent | w p p r r r r r r p p p *
9011 * polls | o o r r r r r r o o o *
9012 * | h l l o o o o o o l l l *
9013 * | o l l r r r r r r l l l *
9014 * | s *
9015 * | t ok ok E1 E1 E2 E1 E1 E2 ok ok ok *
9016 * -------------------------------------------------------------------------------- *
9017 * available | 0 1 1 1 1 1 2 2 2 0 0 0 *
9018 * | *
9019 * error | "" "" "" "" "" "" E1 E1 E2 "" "" "" *
9020 * | *
9021 * errors_from | 0 0 0 T4 T4 T4 T4 T4 T4 0 0 0 *
9022 * | *
9023 * disable_until| 0 0 0 T5 T6 T7 T8 T9 T10 0 0 0 *
9024 * -------------------------------------------------------------------------------- *
9025 * timestamps | T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 *
9026 * | \_/ \_/ \_/ \___/ \___/ \___/ \_____/ \_____/ \_____/ \_/ \_/ *
9027 * | | | | | | | | | | | | *
9028 * polling | item delay UnreachableDelay UnavailableDelay item | *
9029 * periods | (conf file) (conf file) delay *
9030 * *
9031 * *
9032 **************************************************************************************/
9033
9034 /******************************************************************************
9035 * *
9036 * Function: DChost_activate *
9037 * *
9038 * Purpose: set host as available based on the agent availability data *
9039 * *
9040 * Parameters: hostid - [IN] the host identifier *
9041 * agent_type - [IN] the agent type (see ZBX_AGENT_* defines) *
9042 * ts - [IN] the last timestamp *
9043 * in - [IN/OUT] IN: the caller's agent availability data *
9044 * OUT: the agent availability data in cache *
9045 * before changes *
9046 * out - [OUT] the agent availability data after changes *
9047 * *
9048 * Return value: SUCCEED - the host was activated successfully *
9049 * FAIL - the host was already activated or activation *
9050 * failed *
9051 * *
9052 * Comments: The host availability fields are updated according to the above *
9053 * schema. *
9054 * *
9055 ******************************************************************************/
DChost_activate(zbx_uint64_t hostid,unsigned char agent_type,const zbx_timespec_t * ts,zbx_agent_availability_t * in,zbx_agent_availability_t * out)9056 int DChost_activate(zbx_uint64_t hostid, unsigned char agent_type, const zbx_timespec_t *ts,
9057 zbx_agent_availability_t *in, zbx_agent_availability_t *out)
9058 {
9059 int ret = FAIL;
9060 ZBX_DC_HOST *dc_host;
9061
9062 /* don't try activating host if there were no errors detected */
9063 if (0 == in->errors_from && HOST_AVAILABLE_TRUE == in->available)
9064 goto out;
9065
9066 WRLOCK_CACHE;
9067
9068 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)))
9069 goto unlock;
9070
9071 /* Don't try activating host if: */
9072 /* - (server, proxy) it's not monitored any more; */
9073 /* - (server) it's monitored by proxy. */
9074 if ((0 != (program_type & ZBX_PROGRAM_TYPE_SERVER) && 0 != dc_host->proxy_hostid) ||
9075 HOST_STATUS_MONITORED != dc_host->status)
9076 {
9077 goto unlock;
9078 }
9079
9080 DChost_get_agent_availability(dc_host, agent_type, in);
9081 zbx_agent_availability_init(out, HOST_AVAILABLE_TRUE, "", 0, 0);
9082 DChost_set_agent_availability(dc_host, ts->sec, agent_type, out);
9083
9084 if (ZBX_FLAGS_AGENT_STATUS_NONE != out->flags)
9085 ret = SUCCEED;
9086 unlock:
9087 UNLOCK_CACHE;
9088 out:
9089 return ret;
9090 }
9091
9092 /******************************************************************************
9093 * *
9094 * Function: DChost_deactivate *
9095 * *
9096 * Purpose: attempt to set host as unavailable based on agent availability *
9097 * *
9098 * Parameters: hostid - [IN] the host identifier *
9099 * agent_type - [IN] the agent type (see ZBX_AGENT_* defines) *
9100 * ts - [IN] the last timestamp *
9101 * in - [IN/OUT] IN: the caller's host availability data *
9102 * OUT: the host availability data in cache *
9103 * before changes *
9104 * out - [OUT] the host availability data after changes *
9105 * error_msg - [IN] the error message *
9106 * *
9107 * Return value: SUCCEED - the host was deactivated successfully *
9108 * FAIL - the host was already deactivated or deactivation *
9109 * failed *
9110 * *
9111 * Comments: The host availability fields are updated according to the above *
9112 * schema. *
9113 * *
9114 ******************************************************************************/
DChost_deactivate(zbx_uint64_t hostid,unsigned char agent_type,const zbx_timespec_t * ts,zbx_agent_availability_t * in,zbx_agent_availability_t * out,const char * error_msg)9115 int DChost_deactivate(zbx_uint64_t hostid, unsigned char agent_type, const zbx_timespec_t *ts,
9116 zbx_agent_availability_t *in, zbx_agent_availability_t *out, const char *error_msg)
9117 {
9118 int ret = FAIL, errors_from,disable_until;
9119 const char *error;
9120 unsigned char available;
9121 ZBX_DC_HOST *dc_host;
9122
9123
9124 /* don't try deactivating host if the unreachable delay has not passed since the first error */
9125 if (CONFIG_UNREACHABLE_DELAY > ts->sec - in->errors_from)
9126 goto out;
9127
9128 WRLOCK_CACHE;
9129
9130 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)))
9131 goto unlock;
9132
9133 /* Don't try deactivating host if: */
9134 /* - (server, proxy) it's not monitored any more; */
9135 /* - (server) it's monitored by proxy. */
9136 if ((0 != (program_type & ZBX_PROGRAM_TYPE_SERVER) && 0 != dc_host->proxy_hostid) ||
9137 HOST_STATUS_MONITORED != dc_host->status)
9138 {
9139 goto unlock;
9140 }
9141
9142 DChost_get_agent_availability(dc_host, agent_type, in);
9143
9144 available = in->available;
9145 error = in->error;
9146
9147 if (0 == in->errors_from)
9148 {
9149 /* first error, schedule next unreachable check */
9150 errors_from = ts->sec;
9151 disable_until = ts->sec + CONFIG_UNREACHABLE_DELAY;
9152 }
9153 else
9154 {
9155 errors_from = in->errors_from;
9156 disable_until = in->disable_until;
9157
9158 /* Check if other pollers haven't already attempted deactivating host. */
9159 /* In that case should wait the initial unreachable delay before */
9160 /* trying to make it unavailable. */
9161 if (CONFIG_UNREACHABLE_DELAY <= ts->sec - errors_from)
9162 {
9163 /* repeating error */
9164 if (CONFIG_UNREACHABLE_PERIOD > ts->sec - errors_from)
9165 {
9166 /* leave host available, schedule next unreachable check */
9167 disable_until = ts->sec + CONFIG_UNREACHABLE_DELAY;
9168 }
9169 else
9170 {
9171 /* make host unavailable, schedule next unavailable check */
9172 disable_until = ts->sec + CONFIG_UNAVAILABLE_DELAY;
9173 available = HOST_AVAILABLE_FALSE;
9174 error = error_msg;
9175 }
9176 }
9177 }
9178
9179 zbx_agent_availability_init(out, available, error, errors_from, disable_until);
9180 DChost_set_agent_availability(dc_host, ts->sec, agent_type, out);
9181
9182 if (ZBX_FLAGS_AGENT_STATUS_NONE != out->flags)
9183 ret = SUCCEED;
9184 unlock:
9185 UNLOCK_CACHE;
9186 out:
9187 return ret;
9188 }
9189
9190 /******************************************************************************
9191 * *
9192 * Function: DCset_hosts_availability *
9193 * *
9194 * Purpose: update availability of hosts in configuration cache and return *
9195 * the updated field flags *
9196 * *
9197 * Parameters: availabilities - [IN/OUT] the hosts availability data *
9198 * *
9199 * Return value: SUCCEED - at least one host availability data was updated *
9200 * FAIL - no hosts were updated *
9201 * *
9202 ******************************************************************************/
DCset_hosts_availability(zbx_vector_ptr_t * availabilities)9203 int DCset_hosts_availability(zbx_vector_ptr_t *availabilities)
9204 {
9205 int i;
9206 ZBX_DC_HOST *dc_host;
9207 zbx_host_availability_t *ha;
9208 int ret = FAIL, now;
9209
9210 now = time(NULL);
9211
9212 WRLOCK_CACHE;
9213
9214 for (i = 0; i < availabilities->values_num; i++)
9215 {
9216 ha = (zbx_host_availability_t *)availabilities->values[i];
9217
9218 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &ha->hostid)))
9219 {
9220 int j;
9221
9222 /* reset availability flags so this host is ignored when saving availability diff to DB */
9223 for (j = 0; j < ZBX_AGENT_MAX; j++)
9224 ha->agents[j].flags = ZBX_FLAGS_AGENT_STATUS_NONE;
9225
9226 continue;
9227 }
9228
9229 if (SUCCEED == DChost_set_availability(dc_host, now, ha))
9230 ret = SUCCEED;
9231 }
9232
9233 UNLOCK_CACHE;
9234
9235 return ret;
9236 }
9237
9238 /******************************************************************************
9239 * *
9240 * Comments: helper function for trigger dependency checking *
9241 * *
9242 * Parameters: trigdep - [IN] the trigger dependency data *
9243 * level - [IN] the trigger dependency level *
9244 * triggerids - [IN] the currently processing trigger ids *
9245 * for bulk trigger operations *
9246 * (optional, can be NULL) *
9247 * master_triggerids - [OUT] unresolved master trigger ids *
9248 * for bulk trigger operations *
9249 * (optional together with triggerids *
9250 * parameter) *
9251 * *
9252 * Return value: SUCCEED - trigger dependency check succeed / was unresolved *
9253 * FAIL - otherwise *
9254 * *
9255 * Comments: With bulk trigger processing a master trigger can be in the same *
9256 * batch as dependent trigger. In this case it might be impossible *
9257 * to perform dependency check based on cashed trigger values. The *
9258 * unresolved master trigger ids will be added to master_triggerids *
9259 * vector, so the dependency check can be performed after a new *
9260 * master trigger value has been calculated. *
9261 * *
9262 ******************************************************************************/
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)9263 static int DCconfig_check_trigger_dependencies_rec(const ZBX_DC_TRIGGER_DEPLIST *trigdep, int level,
9264 const zbx_vector_uint64_t *triggerids, zbx_vector_uint64_t *master_triggerids)
9265 {
9266 int i;
9267 const ZBX_DC_TRIGGER *next_trigger;
9268 const ZBX_DC_TRIGGER_DEPLIST *next_trigdep;
9269
9270 if (ZBX_TRIGGER_DEPENDENCY_LEVELS_MAX < level)
9271 {
9272 zabbix_log(LOG_LEVEL_CRIT, "recursive trigger dependency is too deep (triggerid:" ZBX_FS_UI64 ")",
9273 trigdep->triggerid);
9274 return SUCCEED;
9275 }
9276
9277 if (0 != trigdep->dependencies.values_num)
9278 {
9279 for (i = 0; i < trigdep->dependencies.values_num; i++)
9280 {
9281 next_trigdep = (const ZBX_DC_TRIGGER_DEPLIST *)trigdep->dependencies.values[i];
9282
9283 if (NULL != (next_trigger = next_trigdep->trigger) &&
9284 TRIGGER_STATUS_ENABLED == next_trigger->status &&
9285 TRIGGER_FUNCTIONAL_TRUE == next_trigger->functional)
9286 {
9287
9288 if (NULL == triggerids || FAIL == zbx_vector_uint64_bsearch(triggerids,
9289 next_trigger->triggerid, ZBX_DEFAULT_UINT64_COMPARE_FUNC))
9290 {
9291 if (TRIGGER_VALUE_PROBLEM == next_trigger->value)
9292 return FAIL;
9293 }
9294 else
9295 zbx_vector_uint64_append(master_triggerids, next_trigger->triggerid);
9296 }
9297
9298 if (FAIL == DCconfig_check_trigger_dependencies_rec(next_trigdep, level + 1, triggerids,
9299 master_triggerids))
9300 {
9301 return FAIL;
9302 }
9303 }
9304 }
9305
9306 return SUCCEED;
9307 }
9308
9309 /******************************************************************************
9310 * *
9311 * Function: DCconfig_check_trigger_dependencies *
9312 * *
9313 * Purpose: check whether any of trigger dependencies have value PROBLEM *
9314 * *
9315 * Return value: SUCCEED - trigger can change its value *
9316 * FAIL - otherwise *
9317 * *
9318 * Author: Alexei Vladishev, Aleksandrs Saveljevs *
9319 * *
9320 ******************************************************************************/
DCconfig_check_trigger_dependencies(zbx_uint64_t triggerid)9321 int DCconfig_check_trigger_dependencies(zbx_uint64_t triggerid)
9322 {
9323 int ret = SUCCEED;
9324 const ZBX_DC_TRIGGER_DEPLIST *trigdep;
9325
9326 RDLOCK_CACHE;
9327
9328 if (NULL != (trigdep = (const ZBX_DC_TRIGGER_DEPLIST *)zbx_hashset_search(&config->trigdeps, &triggerid)))
9329 ret = DCconfig_check_trigger_dependencies_rec(trigdep, 0, NULL, NULL);
9330
9331 UNLOCK_CACHE;
9332
9333 return ret;
9334 }
9335
9336 /******************************************************************************
9337 * *
9338 * Comments: helper function for DCconfig_sort_triggers_topologically() *
9339 * *
9340 ******************************************************************************/
DCconfig_sort_triggers_topologically_rec(const ZBX_DC_TRIGGER_DEPLIST * trigdep,int level)9341 static unsigned char DCconfig_sort_triggers_topologically_rec(const ZBX_DC_TRIGGER_DEPLIST *trigdep, int level)
9342 {
9343 int i;
9344 unsigned char topoindex = 2, next_topoindex;
9345 const ZBX_DC_TRIGGER_DEPLIST *next_trigdep;
9346
9347 if (32 < level)
9348 {
9349 zabbix_log(LOG_LEVEL_CRIT, "recursive trigger dependency is too deep (triggerid:" ZBX_FS_UI64 ")",
9350 trigdep->triggerid);
9351 goto exit;
9352 }
9353
9354 if (0 == trigdep->trigger->topoindex)
9355 {
9356 zabbix_log(LOG_LEVEL_CRIT, "trigger dependencies contain a cycle (triggerid:" ZBX_FS_UI64 ")",
9357 trigdep->triggerid);
9358 goto exit;
9359 }
9360
9361 trigdep->trigger->topoindex = 0;
9362
9363 for (i = 0; i < trigdep->dependencies.values_num; i++)
9364 {
9365 next_trigdep = (const ZBX_DC_TRIGGER_DEPLIST *)trigdep->dependencies.values[i];
9366
9367 if (1 < (next_topoindex = next_trigdep->trigger->topoindex))
9368 goto next;
9369
9370 if (0 == next_trigdep->dependencies.values_num)
9371 continue;
9372
9373 next_topoindex = DCconfig_sort_triggers_topologically_rec(next_trigdep, level + 1);
9374 next:
9375 if (topoindex < next_topoindex + 1)
9376 topoindex = next_topoindex + 1;
9377 }
9378
9379 trigdep->trigger->topoindex = topoindex;
9380 exit:
9381 return topoindex;
9382 }
9383
9384 /******************************************************************************
9385 * *
9386 * Function: DCconfig_sort_triggers_topologically *
9387 * *
9388 * Purpose: assign each trigger an index based on trigger dependency topology *
9389 * *
9390 * Author: Aleksandrs Saveljevs *
9391 * *
9392 ******************************************************************************/
DCconfig_sort_triggers_topologically(void)9393 static void DCconfig_sort_triggers_topologically(void)
9394 {
9395 zbx_hashset_iter_t iter;
9396 ZBX_DC_TRIGGER *trigger;
9397 const ZBX_DC_TRIGGER_DEPLIST *trigdep;
9398
9399 zbx_hashset_iter_reset(&config->trigdeps, &iter);
9400
9401 while (NULL != (trigdep = (ZBX_DC_TRIGGER_DEPLIST *)zbx_hashset_iter_next(&iter)))
9402 {
9403 trigger = trigdep->trigger;
9404
9405 if (NULL == trigger || 1 < trigger->topoindex || 0 == trigdep->dependencies.values_num)
9406 continue;
9407
9408 DCconfig_sort_triggers_topologically_rec(trigdep, 0);
9409 }
9410 }
9411
9412 /******************************************************************************
9413 * *
9414 * Function: DCconfig_triggers_apply_changes *
9415 * *
9416 * Purpose: apply trigger value,state,lastchange or error changes to *
9417 * configuration cache after committed to database *
9418 * *
9419 ******************************************************************************/
DCconfig_triggers_apply_changes(zbx_vector_ptr_t * trigger_diff)9420 void DCconfig_triggers_apply_changes(zbx_vector_ptr_t *trigger_diff)
9421 {
9422 int i;
9423 zbx_trigger_diff_t *diff;
9424 ZBX_DC_TRIGGER *dc_trigger;
9425
9426 if (0 == trigger_diff->values_num)
9427 return;
9428
9429 WRLOCK_CACHE;
9430
9431 for (i = 0; i < trigger_diff->values_num; i++)
9432 {
9433 diff = (zbx_trigger_diff_t *)trigger_diff->values[i];
9434
9435 if (NULL == (dc_trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&config->triggers, &diff->triggerid)))
9436 continue;
9437
9438 if (0 != (diff->flags & ZBX_FLAGS_TRIGGER_DIFF_UPDATE_LASTCHANGE))
9439 dc_trigger->lastchange = diff->lastchange;
9440
9441 if (0 != (diff->flags & ZBX_FLAGS_TRIGGER_DIFF_UPDATE_VALUE))
9442 dc_trigger->value = diff->value;
9443
9444 if (0 != (diff->flags & ZBX_FLAGS_TRIGGER_DIFF_UPDATE_STATE))
9445 dc_trigger->state = diff->state;
9446
9447 if (0 != (diff->flags & ZBX_FLAGS_TRIGGER_DIFF_UPDATE_ERROR))
9448 DCstrpool_replace(1, &dc_trigger->error, diff->error);
9449 }
9450
9451 UNLOCK_CACHE;
9452 }
9453
9454 /******************************************************************************
9455 * *
9456 * Function: DCconfig_get_stats *
9457 * *
9458 * Purpose: get statistics of the database cache *
9459 * *
9460 * Author: Alexander Vladishev, Aleksandrs Saveljevs *
9461 * *
9462 ******************************************************************************/
DCconfig_get_stats(int request)9463 void *DCconfig_get_stats(int request)
9464 {
9465 static zbx_uint64_t value_uint;
9466 static double value_double;
9467
9468 switch (request)
9469 {
9470 case ZBX_CONFSTATS_BUFFER_TOTAL:
9471 value_uint = config_mem->orig_size;
9472 return &value_uint;
9473 case ZBX_CONFSTATS_BUFFER_USED:
9474 value_uint = config_mem->orig_size - config_mem->free_size;
9475 return &value_uint;
9476 case ZBX_CONFSTATS_BUFFER_FREE:
9477 value_uint = config_mem->free_size;
9478 return &value_uint;
9479 case ZBX_CONFSTATS_BUFFER_PUSED:
9480 value_double = 100 * (double)(config_mem->orig_size - config_mem->free_size) /
9481 config_mem->orig_size;
9482 return &value_double;
9483 case ZBX_CONFSTATS_BUFFER_PFREE:
9484 value_double = 100 * (double)config_mem->free_size / config_mem->orig_size;
9485 return &value_double;
9486 default:
9487 return NULL;
9488 }
9489 }
9490
DCget_proxy(DC_PROXY * dst_proxy,const ZBX_DC_PROXY * src_proxy)9491 static void DCget_proxy(DC_PROXY *dst_proxy, const ZBX_DC_PROXY *src_proxy)
9492 {
9493 const ZBX_DC_HOST *host;
9494 ZBX_DC_INTERFACE_HT *interface_ht, interface_ht_local;
9495
9496 dst_proxy->hostid = src_proxy->hostid;
9497 dst_proxy->proxy_config_nextcheck = src_proxy->proxy_config_nextcheck;
9498 dst_proxy->proxy_data_nextcheck = src_proxy->proxy_data_nextcheck;
9499 dst_proxy->proxy_tasks_nextcheck = src_proxy->proxy_tasks_nextcheck;
9500 dst_proxy->last_cfg_error_time = src_proxy->last_cfg_error_time;
9501 dst_proxy->version = src_proxy->version;
9502 dst_proxy->lastaccess = src_proxy->lastaccess;
9503 dst_proxy->auto_compress = src_proxy->auto_compress;
9504 dst_proxy->last_version_error_time = src_proxy->last_version_error_time;
9505
9506 if (NULL != (host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &src_proxy->hostid)))
9507 {
9508 strscpy(dst_proxy->host, host->host);
9509 strscpy(dst_proxy->proxy_address, src_proxy->proxy_address);
9510
9511 dst_proxy->tls_connect = host->tls_connect;
9512 dst_proxy->tls_accept = host->tls_accept;
9513 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
9514 strscpy(dst_proxy->tls_issuer, host->tls_issuer);
9515 strscpy(dst_proxy->tls_subject, host->tls_subject);
9516
9517 if (NULL == host->tls_dc_psk)
9518 {
9519 *dst_proxy->tls_psk_identity = '\0';
9520 *dst_proxy->tls_psk = '\0';
9521 }
9522 else
9523 {
9524 strscpy(dst_proxy->tls_psk_identity, host->tls_dc_psk->tls_psk_identity);
9525 strscpy(dst_proxy->tls_psk, host->tls_dc_psk->tls_psk);
9526 }
9527 #endif
9528 }
9529 else
9530 {
9531 /* DCget_proxy() is called only from DCconfig_get_proxypoller_hosts(), which is called only from */
9532 /* process_proxy(). So, this branch should never happen. */
9533 *dst_proxy->host = '\0';
9534 *dst_proxy->proxy_address = '\0';
9535 dst_proxy->tls_connect = ZBX_TCP_SEC_TLS_PSK; /* set PSK to deliberately fail in this case */
9536 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
9537 *dst_proxy->tls_psk_identity = '\0';
9538 *dst_proxy->tls_psk = '\0';
9539 #endif
9540 THIS_SHOULD_NEVER_HAPPEN;
9541 }
9542
9543 interface_ht_local.hostid = src_proxy->hostid;
9544 interface_ht_local.type = INTERFACE_TYPE_UNKNOWN;
9545
9546 if (NULL != (interface_ht = (ZBX_DC_INTERFACE_HT *)zbx_hashset_search(&config->interfaces_ht, &interface_ht_local)))
9547 {
9548 const ZBX_DC_INTERFACE *interface = interface_ht->interface_ptr;
9549
9550 strscpy(dst_proxy->addr_orig, interface->useip ? interface->ip : interface->dns);
9551 strscpy(dst_proxy->port_orig, interface->port);
9552 }
9553 else
9554 {
9555 *dst_proxy->addr_orig = '\0';
9556 *dst_proxy->port_orig = '\0';
9557 }
9558
9559 dst_proxy->addr = NULL;
9560 dst_proxy->port = 0;
9561 }
9562
DCconfig_get_last_sync_time(void)9563 int DCconfig_get_last_sync_time(void)
9564 {
9565 return config->sync_ts;
9566 }
9567
DCconfig_wait_sync(void)9568 void DCconfig_wait_sync(void)
9569 {
9570 struct timespec ts = {0, 1e8};
9571
9572 while (0 == config->sync_ts)
9573 nanosleep(&ts, NULL);
9574 }
9575
9576 /******************************************************************************
9577 * *
9578 * Function: DCconfig_get_proxypoller_hosts *
9579 * *
9580 * Purpose: Get array of proxies for proxy poller *
9581 * *
9582 * Parameters: hosts - [OUT] array of hosts *
9583 * max_hosts - [IN] elements in hosts array *
9584 * *
9585 * Return value: number of proxies in hosts array *
9586 * *
9587 * Author: Alexander Vladishev *
9588 * *
9589 * Comments: Proxies leave the queue only through this function. Pollers must *
9590 * always return the proxies they have taken using DCrequeue_proxy. *
9591 * *
9592 ******************************************************************************/
DCconfig_get_proxypoller_hosts(DC_PROXY * proxies,int max_hosts)9593 int DCconfig_get_proxypoller_hosts(DC_PROXY *proxies, int max_hosts)
9594 {
9595 int now, num = 0;
9596 zbx_binary_heap_t *queue;
9597
9598 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
9599
9600 now = time(NULL);
9601
9602 queue = &config->pqueue;
9603
9604 WRLOCK_CACHE;
9605
9606 while (num < max_hosts && FAIL == zbx_binary_heap_empty(queue))
9607 {
9608 const zbx_binary_heap_elem_t *min;
9609 ZBX_DC_PROXY *dc_proxy;
9610
9611 min = zbx_binary_heap_find_min(queue);
9612 dc_proxy = (ZBX_DC_PROXY *)min->data;
9613
9614 if (dc_proxy->nextcheck > now)
9615 break;
9616
9617 zbx_binary_heap_remove_min(queue);
9618 dc_proxy->location = ZBX_LOC_POLLER;
9619
9620 DCget_proxy(&proxies[num], dc_proxy);
9621 num++;
9622 }
9623
9624 UNLOCK_CACHE;
9625
9626 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __func__, num);
9627
9628 return num;
9629 }
9630
9631 /******************************************************************************
9632 * *
9633 * Function: DCconfig_get_proxypoller_nextcheck *
9634 * *
9635 * Purpose: Get nextcheck for passive proxies *
9636 * *
9637 * Return value: nextcheck or FAIL if no passive proxies in queue *
9638 * *
9639 * Author: Alexander Vladishev *
9640 * *
9641 ******************************************************************************/
DCconfig_get_proxypoller_nextcheck(void)9642 int DCconfig_get_proxypoller_nextcheck(void)
9643 {
9644 int nextcheck;
9645 zbx_binary_heap_t *queue;
9646
9647 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
9648
9649 queue = &config->pqueue;
9650
9651 RDLOCK_CACHE;
9652
9653 if (FAIL == zbx_binary_heap_empty(queue))
9654 {
9655 const zbx_binary_heap_elem_t *min;
9656 const ZBX_DC_PROXY *dc_proxy;
9657
9658 min = zbx_binary_heap_find_min(queue);
9659 dc_proxy = (const ZBX_DC_PROXY *)min->data;
9660
9661 nextcheck = dc_proxy->nextcheck;
9662 }
9663 else
9664 nextcheck = FAIL;
9665
9666 UNLOCK_CACHE;
9667
9668 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __func__, nextcheck);
9669
9670 return nextcheck;
9671 }
9672
DCrequeue_proxy(zbx_uint64_t hostid,unsigned char update_nextcheck,int proxy_conn_err)9673 void DCrequeue_proxy(zbx_uint64_t hostid, unsigned char update_nextcheck, int proxy_conn_err)
9674 {
9675 time_t now;
9676 ZBX_DC_HOST *dc_host;
9677 ZBX_DC_PROXY *dc_proxy;
9678
9679 zabbix_log(LOG_LEVEL_DEBUG, "In %s() update_nextcheck:%d", __func__, (int)update_nextcheck);
9680
9681 now = time(NULL);
9682
9683 WRLOCK_CACHE;
9684
9685 if (NULL != (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)) &&
9686 NULL != (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &hostid)))
9687 {
9688 if (ZBX_LOC_POLLER == dc_proxy->location)
9689 dc_proxy->location = ZBX_LOC_NOWHERE;
9690
9691 /* set or clear passive proxy misconfiguration error timestamp */
9692 if (SUCCEED == proxy_conn_err)
9693 dc_proxy->last_cfg_error_time = 0;
9694 else if (CONFIG_ERROR == proxy_conn_err)
9695 dc_proxy->last_cfg_error_time = (int)now;
9696
9697 if (HOST_STATUS_PROXY_PASSIVE == dc_host->status)
9698 {
9699 if (0 != (update_nextcheck & ZBX_PROXY_CONFIG_NEXTCHECK))
9700 {
9701 dc_proxy->proxy_config_nextcheck = (int)calculate_proxy_nextcheck(
9702 hostid, CONFIG_PROXYCONFIG_FREQUENCY, now);
9703 }
9704
9705 if (0 != (update_nextcheck & ZBX_PROXY_DATA_NEXTCHECK))
9706 {
9707 dc_proxy->proxy_data_nextcheck = (int)calculate_proxy_nextcheck(
9708 hostid, CONFIG_PROXYDATA_FREQUENCY, now);
9709 }
9710 if (0 != (update_nextcheck & ZBX_PROXY_TASKS_NEXTCHECK))
9711 {
9712 dc_proxy->proxy_tasks_nextcheck = (int)calculate_proxy_nextcheck(
9713 hostid, ZBX_TASK_UPDATE_FREQUENCY, now);
9714 }
9715
9716 DCupdate_proxy_queue(dc_proxy);
9717 }
9718 }
9719
9720 UNLOCK_CACHE;
9721
9722 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
9723 }
9724
dc_get_host_macro_value(const ZBX_DC_HMACRO * macro,char ** value)9725 static void dc_get_host_macro_value(const ZBX_DC_HMACRO *macro, char **value)
9726 {
9727 if (ZBX_MACRO_ENV_NONSECURE == macro_env && ZBX_MACRO_VALUE_SECRET == macro->type)
9728 *value = zbx_strdup(*value, ZBX_MACRO_SECRET_MASK);
9729 else
9730 *value = zbx_strdup(*value, macro->value);
9731 }
9732
dc_match_macro_context(const char * context,const char * pattern,unsigned char op)9733 static int dc_match_macro_context(const char *context, const char *pattern, unsigned char op)
9734 {
9735 switch (op)
9736 {
9737 case CONDITION_OPERATOR_EQUAL:
9738 return 0 == zbx_strcmp_null(context, pattern) ? SUCCEED : FAIL;
9739 case CONDITION_OPERATOR_REGEXP:
9740 if (NULL == context)
9741 return FAIL;
9742 return NULL != zbx_regexp_match(context, pattern, NULL) ? SUCCEED : FAIL;
9743 default:
9744 THIS_SHOULD_NEVER_HAPPEN;
9745 return FAIL;
9746 }
9747 }
9748
dc_get_host_macro(const zbx_uint64_t * hostids,int host_num,const char * macro,const char * context,char ** value,char ** value_default)9749 static void dc_get_host_macro(const zbx_uint64_t *hostids, int host_num, const char *macro, const char *context,
9750 char **value, char **value_default)
9751 {
9752 int i, j;
9753 const ZBX_DC_HMACRO_HM *hmacro_hm;
9754 ZBX_DC_HMACRO_HM hmacro_hm_local;
9755 const ZBX_DC_HTMPL *htmpl;
9756 zbx_vector_uint64_t templateids;
9757 const ZBX_DC_HMACRO *hmacro;
9758
9759 if (0 == host_num)
9760 return;
9761
9762 hmacro_hm_local.macro = macro;
9763
9764 for (i = 0; i < host_num; i++)
9765 {
9766 hmacro_hm_local.hostid = hostids[i];
9767
9768 if (NULL != (hmacro_hm = (const ZBX_DC_HMACRO_HM *)zbx_hashset_search(&config->hmacros_hm, &hmacro_hm_local)))
9769 {
9770 for (j = 0; j < hmacro_hm->hmacros.values_num; j++)
9771 {
9772 hmacro = (const ZBX_DC_HMACRO *)hmacro_hm->hmacros.values[j];
9773
9774 if (SUCCEED == dc_match_macro_context(context, hmacro->context, hmacro->context_op))
9775 {
9776 dc_get_host_macro_value(hmacro, value);
9777 return;
9778 }
9779 }
9780 /* Check for the default (without context) macro value. If macro has a value without */
9781 /* context it will be the first element in the macro index vector. */
9782 hmacro = (const ZBX_DC_HMACRO *)hmacro_hm->hmacros.values[0];
9783 if (NULL == *value_default && NULL != context && NULL == hmacro->context)
9784 dc_get_host_macro_value(hmacro, value_default);
9785 }
9786 }
9787
9788 zbx_vector_uint64_create(&templateids);
9789 zbx_vector_uint64_reserve(&templateids, 32);
9790
9791 for (i = 0; i < host_num; i++)
9792 {
9793 if (NULL != (htmpl = (const ZBX_DC_HTMPL *)zbx_hashset_search(&config->htmpls, &hostids[i])))
9794 {
9795 for (j = 0; j < htmpl->templateids.values_num; j++)
9796 zbx_vector_uint64_append(&templateids, htmpl->templateids.values[j]);
9797 }
9798 }
9799
9800 if (0 != templateids.values_num)
9801 {
9802 zbx_vector_uint64_sort(&templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
9803 dc_get_host_macro(templateids.values, templateids.values_num, macro, context, value, value_default);
9804 }
9805
9806 zbx_vector_uint64_destroy(&templateids);
9807 }
9808
dc_get_global_macro_value(const ZBX_DC_GMACRO * macro,char ** value)9809 static void dc_get_global_macro_value(const ZBX_DC_GMACRO *macro, char **value)
9810 {
9811 if (ZBX_MACRO_ENV_NONSECURE == macro_env && ZBX_MACRO_VALUE_SECRET == macro->type)
9812 *value = zbx_strdup(*value, ZBX_MACRO_SECRET_MASK);
9813 else
9814 *value = zbx_strdup(*value, macro->value);
9815 }
9816
dc_get_global_macro(const char * macro,const char * context,char ** value,char ** value_default)9817 static void dc_get_global_macro(const char *macro, const char *context, char **value, char **value_default)
9818 {
9819 int i;
9820 const ZBX_DC_GMACRO_M *gmacro_m;
9821 ZBX_DC_GMACRO_M gmacro_m_local;
9822 const ZBX_DC_GMACRO *gmacro;
9823
9824 gmacro_m_local.macro = macro;
9825
9826 if (NULL != (gmacro_m = (const ZBX_DC_GMACRO_M *)zbx_hashset_search(&config->gmacros_m, &gmacro_m_local)))
9827 {
9828 for (i = 0; i < gmacro_m->gmacros.values_num; i++)
9829 {
9830 gmacro = (const ZBX_DC_GMACRO *)gmacro_m->gmacros.values[i];
9831
9832 if (SUCCEED == dc_match_macro_context(context, gmacro->context, gmacro->context_op))
9833 {
9834 dc_get_global_macro_value(gmacro, value);
9835 break;
9836 }
9837 }
9838
9839 /* Check for the default (without context) macro value. If macro has a value without */
9840 /* context it will be the first element in the macro index vector. */
9841 gmacro = (const ZBX_DC_GMACRO *)gmacro_m->gmacros.values[0];
9842 if (NULL == *value_default && NULL != context && NULL == gmacro->context)
9843 dc_get_global_macro_value(gmacro, value_default);
9844 }
9845 }
9846
dc_get_user_macro(const zbx_uint64_t * hostids,int hostids_num,const char * macro,const char * context,char ** replace_to)9847 static void dc_get_user_macro(const zbx_uint64_t *hostids, int hostids_num, const char *macro, const char *context,
9848 char **replace_to)
9849 {
9850 char *value = NULL, *value_default = NULL;
9851
9852 /* User macros should be expanded according to the following priority: */
9853 /* */
9854 /* 1) host context macro */
9855 /* 2) global context macro */
9856 /* 3) host base (default) macro */
9857 /* 4) global base (default) macro */
9858 /* */
9859 /* We try to expand host macros first. If there is no perfect match on */
9860 /* the host level, we try to expand global macros, passing the default */
9861 /* macro value found on the host level, if any. */
9862
9863 dc_get_host_macro(hostids, hostids_num, macro, context, &value, &value_default);
9864
9865 if (NULL == value)
9866 dc_get_global_macro(macro, context, &value, &value_default);
9867
9868 if (NULL != value)
9869 {
9870 zbx_free(*replace_to);
9871 *replace_to = value;
9872
9873 zbx_free(value_default);
9874 }
9875 else if (NULL != value_default)
9876 {
9877 zbx_free(*replace_to);
9878 *replace_to = value_default;
9879 }
9880 }
9881
DCget_user_macro(const zbx_uint64_t * hostids,int hostids_num,const char * macro,char ** replace_to)9882 void DCget_user_macro(const zbx_uint64_t *hostids, int hostids_num, const char *macro, char **replace_to)
9883 {
9884 char *name = NULL, *context = NULL;
9885
9886 zabbix_log(LOG_LEVEL_DEBUG, "In %s() macro:'%s'", __func__, macro);
9887
9888 if (SUCCEED != zbx_user_macro_parse_dyn(macro, &name, &context, NULL, NULL))
9889 goto out;
9890
9891 RDLOCK_CACHE;
9892
9893 dc_get_user_macro(hostids, hostids_num, name, context, replace_to);
9894
9895 UNLOCK_CACHE;
9896
9897 zbx_free(context);
9898 zbx_free(name);
9899 out:
9900 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
9901 }
9902
9903 /******************************************************************************
9904 * *
9905 * Function: dc_expand_user_macros *
9906 * *
9907 * Purpose: expand user macros in the specified text value *
9908 * WARNING - DO NOT USE FOR TRIGGERS, for triggers use the dedicated function *
9909 * *
9910 * Parameters: text - [IN] the text value to expand *
9911 * hostids - [IN] an array of related hostids *
9912 * hostids_num - [IN] the number of hostids *
9913 * *
9914 * Return value: The text value with expanded user macros. Unknown or invalid *
9915 * macros will be left unresolved. *
9916 * *
9917 * Comments: The returned value must be freed by the caller. *
9918 * This function must be used only by configuration syncer *
9919 * *
9920 ******************************************************************************/
dc_expand_user_macros(const char * text,zbx_uint64_t * hostids,int hostids_num)9921 char *dc_expand_user_macros(const char *text, zbx_uint64_t *hostids, int hostids_num)
9922 {
9923 zbx_token_t token;
9924 int pos = 0, len, last_pos = 0;
9925 char *str = NULL, *name = NULL, *context = NULL, *value = NULL;
9926 size_t str_alloc = 0, str_offset = 0;
9927
9928 if ('\0' == *text)
9929 return zbx_strdup(NULL, text);
9930
9931 for (; SUCCEED == zbx_token_find(text, pos, &token, ZBX_TOKEN_SEARCH_BASIC); pos++)
9932 {
9933 if (ZBX_TOKEN_USER_MACRO != token.type)
9934 continue;
9935
9936 if (SUCCEED != zbx_user_macro_parse_dyn(text + token.loc.l, &name, &context, &len, NULL))
9937 continue;
9938
9939 zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + last_pos, token.loc.l - last_pos);
9940 dc_get_user_macro(hostids, hostids_num, name, context, &value);
9941
9942 if (NULL != value)
9943 {
9944 zbx_strcpy_alloc(&str, &str_alloc, &str_offset, value);
9945 zbx_free(value);
9946
9947 }
9948 else
9949 {
9950 zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + token.loc.l,
9951 token.loc.r - token.loc.l + 1);
9952 }
9953
9954 zbx_free(name);
9955 zbx_free(context);
9956
9957 pos = token.loc.r;
9958 last_pos = pos + 1;
9959 }
9960
9961 zbx_strcpy_alloc(&str, &str_alloc, &str_offset, text + last_pos);
9962
9963 return str;
9964 }
9965
9966 /******************************************************************************
9967 * *
9968 * Function: dc_expand_user_macros_in_expression *
9969 * *
9970 * Purpose: expand user macros for triggers and calculated items in the *
9971 * specified text value and autoquote macros that are not already *
9972 * quoted that cannot be casted to a double *
9973 * *
9974 * Parameters: text - [IN] the text value to expand *
9975 * hostids - [IN] an array of related hostids *
9976 * hostids_num - [IN] the number of hostids *
9977 * *
9978 * Return value: The text value with expanded user macros. Unknown or invalid *
9979 * macros will be left unresolved. *
9980 * *
9981 * Comments: The returned value must be freed by the caller. *
9982 * *
9983 ******************************************************************************/
dc_expand_user_macros_in_expression(const char * text,zbx_uint64_t * hostids,int hostids_num)9984 char *dc_expand_user_macros_in_expression(const char *text, zbx_uint64_t *hostids, int hostids_num)
9985 {
9986 zbx_token_t token;
9987 int pos = 0, last_pos = 0, cur_token_inside_quote = 0, prev_token_loc_r = -1, len;
9988 char *str = NULL, *name = NULL, *context = NULL, *value = NULL;
9989 size_t str_alloc = 0, str_offset = 0, i;
9990
9991 if ('\0' == *text)
9992 return zbx_strdup(NULL, text);
9993
9994 for (; SUCCEED == zbx_token_find(text, pos, &token, ZBX_TOKEN_SEARCH_BASIC); pos++)
9995 {
9996 for (i = prev_token_loc_r + 1; i < token.loc.l; i++)
9997 {
9998 switch (text[i])
9999 {
10000 case '\\':
10001 if (0 != cur_token_inside_quote)
10002 i++;
10003 break;
10004 case '"':
10005 cur_token_inside_quote = !cur_token_inside_quote;
10006 break;
10007 }
10008 }
10009
10010 if (ZBX_TOKEN_USER_MACRO != token.type)
10011 {
10012 prev_token_loc_r = token.loc.r;
10013 continue;
10014 }
10015
10016 if (SUCCEED != zbx_user_macro_parse_dyn(text + token.loc.l, &name, &context, &len, NULL))
10017 {
10018 prev_token_loc_r = token.loc.r;
10019 continue;
10020 }
10021
10022 zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + last_pos, token.loc.l - last_pos);
10023 dc_get_user_macro(hostids, hostids_num, name, context, &value);
10024
10025 if (NULL != value)
10026 {
10027 size_t sz;
10028 char *tmp;
10029
10030 sz = zbx_get_escape_string_len(value, "\"\\");
10031
10032 if (0 == cur_token_inside_quote && ZBX_INFINITY == evaluate_string_to_double(value))
10033 {
10034 /* autoquote */
10035 tmp = zbx_malloc(NULL, sz + 3);
10036 tmp[0] = '\"';
10037 zbx_escape_string(tmp + 1, sz + 1, value, "\"\\");
10038 tmp[sz + 1] = '\"';
10039 tmp[sz + 2] = '\0';
10040 zbx_free(value);
10041 value = tmp;
10042 }
10043 else
10044 {
10045 if (sz != strlen(value))
10046 {
10047 tmp = zbx_malloc(NULL, sz + 1);
10048 zbx_escape_string(tmp, sz + 1, value, "\"\\");
10049 tmp[sz] = '\0';
10050 zbx_free(value);
10051 value = tmp;
10052 }
10053 }
10054 }
10055
10056 if (NULL != value)
10057 {
10058 zbx_strcpy_alloc(&str, &str_alloc, &str_offset, value);
10059 zbx_free(value);
10060 }
10061 else
10062 {
10063 zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + token.loc.l,
10064 token.loc.r - token.loc.l + 1);
10065 }
10066
10067 zbx_free(name);
10068 zbx_free(context);
10069
10070 pos = token.loc.r;
10071 last_pos = pos + 1;
10072 prev_token_loc_r = token.loc.r;
10073 }
10074
10075 zbx_strcpy_alloc(&str, &str_alloc, &str_offset, text + last_pos);
10076
10077 return str;
10078 }
10079
10080 /******************************************************************************
10081 * *
10082 * Function: dc_expression_expand_user_macros *
10083 * *
10084 * Purpose: expand user macros in trigger expression *
10085 * *
10086 * Parameters: expression - [IN] the expression to expand *
10087 * error - [OUT] the error message *
10088 * *
10089 * Return value: The expanded expression or NULL in the case of error. *
10090 * If NULL is returned the error message is set. *
10091 * *
10092 * Comments: The returned expression must be freed by the caller. *
10093 * *
10094 ******************************************************************************/
dc_expression_expand_user_macros(const char * expression)10095 static char *dc_expression_expand_user_macros(const char *expression)
10096 {
10097 zbx_vector_uint64_t functionids, hostids;
10098 char *out;
10099
10100 zbx_vector_uint64_create(&functionids);
10101 zbx_vector_uint64_create(&hostids);
10102
10103 get_functionids(&functionids, expression);
10104 dc_get_hostids_by_functionids(functionids.values, functionids.values_num, &hostids);
10105
10106 out = dc_expand_user_macros_in_expression(expression, hostids.values, hostids.values_num);
10107
10108 if (NULL != strstr(out, "{$"))
10109 {
10110 zabbix_log(LOG_LEVEL_DEBUG, "cannot evaluate expression: invalid macro value");
10111 zbx_free(out);
10112 }
10113
10114 zbx_vector_uint64_destroy(&hostids);
10115 zbx_vector_uint64_destroy(&functionids);
10116
10117 return out;
10118 }
10119
10120 /******************************************************************************
10121 * *
10122 * Function: DCexpression_expand_user_macros *
10123 * *
10124 * Purpose: expand user macros in trigger expression *
10125 * *
10126 * Parameters: expression - [IN] the expression to expand *
10127 * *
10128 * Return value: The expanded expression or NULL in the case of error. *
10129 * If NULL is returned the error message is set. *
10130 * *
10131 * Comments: The returned expression must be freed by the caller. *
10132 * This function is a locking wrapper of *
10133 * dc_expression_expand_user_macros() function for external usage. *
10134 * *
10135 ******************************************************************************/
DCexpression_expand_user_macros(const char * expression)10136 char *DCexpression_expand_user_macros(const char *expression)
10137 {
10138 char *expression_ex;
10139
10140 RDLOCK_CACHE;
10141
10142 expression_ex = dc_expression_expand_user_macros(expression);
10143
10144 UNLOCK_CACHE;
10145
10146 return expression_ex;
10147 }
10148
10149 /******************************************************************************
10150 * *
10151 * Function: DCfree_item_queue *
10152 * *
10153 * Purpose: frees the item queue data vector created by DCget_item_queue() *
10154 * *
10155 * Parameters: queue - [IN] the item queue data vector to free *
10156 * *
10157 ******************************************************************************/
DCfree_item_queue(zbx_vector_ptr_t * queue)10158 void DCfree_item_queue(zbx_vector_ptr_t *queue)
10159 {
10160 int i;
10161
10162 for (i = 0; i < queue->values_num; i++)
10163 zbx_free(queue->values[i]);
10164 }
10165
10166 /******************************************************************************
10167 * *
10168 * Function: DCget_item_queue *
10169 * *
10170 * Purpose: retrieves vector of delayed items *
10171 * *
10172 * Parameters: queue - [OUT] the vector of delayed items (optional) *
10173 * from - [IN] the minimum delay time in seconds (non-negative) *
10174 * to - [IN] the maximum delay time in seconds or *
10175 * ZBX_QUEUE_TO_INFINITY if there is no limit *
10176 * *
10177 * Return value: the number of delayed items *
10178 * *
10179 ******************************************************************************/
DCget_item_queue(zbx_vector_ptr_t * queue,int from,int to)10180 int DCget_item_queue(zbx_vector_ptr_t *queue, int from, int to)
10181 {
10182 zbx_hashset_iter_t iter;
10183 const ZBX_DC_ITEM *dc_item;
10184 int now, nitems = 0, data_expected_from, delay;
10185 zbx_queue_item_t *queue_item;
10186
10187 now = time(NULL);
10188
10189 RDLOCK_CACHE;
10190
10191 zbx_hashset_iter_reset(&config->items, &iter);
10192
10193 while (NULL != (dc_item = (const ZBX_DC_ITEM *)zbx_hashset_iter_next(&iter)))
10194 {
10195 const ZBX_DC_HOST *dc_host;
10196
10197 if (ITEM_STATUS_ACTIVE != dc_item->status)
10198 continue;
10199
10200 if (SUCCEED != zbx_is_counted_in_item_queue(dc_item->type, dc_item->key))
10201 continue;
10202
10203 if (NULL == (dc_host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
10204 continue;
10205
10206 if (HOST_STATUS_MONITORED != dc_host->status)
10207 continue;
10208
10209 if (SUCCEED == DCin_maintenance_without_data_collection(dc_host, dc_item))
10210 continue;
10211
10212 switch (dc_item->type)
10213 {
10214 case ITEM_TYPE_ZABBIX:
10215 if (HOST_AVAILABLE_TRUE != dc_host->available)
10216 continue;
10217 break;
10218 case ITEM_TYPE_ZABBIX_ACTIVE:
10219 if (dc_host->data_expected_from > (data_expected_from = dc_item->data_expected_from))
10220 data_expected_from = dc_host->data_expected_from;
10221 if (SUCCEED != zbx_interval_preproc(dc_item->delay, &delay, NULL, NULL))
10222 continue;
10223 if (data_expected_from + delay > now)
10224 continue;
10225 break;
10226 case ITEM_TYPE_SNMP:
10227 if (HOST_AVAILABLE_TRUE != dc_host->snmp_available)
10228 continue;
10229 break;
10230 case ITEM_TYPE_IPMI:
10231 if (HOST_AVAILABLE_TRUE != dc_host->ipmi_available)
10232 continue;
10233 break;
10234 case ITEM_TYPE_JMX:
10235 if (HOST_AVAILABLE_TRUE != dc_host->jmx_available)
10236 continue;
10237 break;
10238 }
10239
10240 if (now - dc_item->nextcheck < from || (ZBX_QUEUE_TO_INFINITY != to && now - dc_item->nextcheck >= to))
10241 continue;
10242
10243 if (NULL != queue)
10244 {
10245 queue_item = (zbx_queue_item_t *)zbx_malloc(NULL, sizeof(zbx_queue_item_t));
10246 queue_item->itemid = dc_item->itemid;
10247 queue_item->type = dc_item->type;
10248 queue_item->nextcheck = dc_item->nextcheck;
10249 queue_item->proxy_hostid = dc_host->proxy_hostid;
10250
10251 zbx_vector_ptr_append(queue, queue_item);
10252 }
10253 nitems++;
10254 }
10255
10256 UNLOCK_CACHE;
10257
10258 return nitems;
10259 }
10260
10261 /******************************************************************************
10262 * *
10263 * Function: dc_trigger_items_hosts_enabled *
10264 * *
10265 * Purpose: check that functionids in trigger (recovery) expression *
10266 * correspond to enabled items and hosts *
10267 * *
10268 * Parameters: expression - [IN] trigger (recovery) expression *
10269 * *
10270 * Return value: SUCCEED - all functionids correspond to enabled items and *
10271 * enabled hosts *
10272 * FAIL - at least one item or host is disabled *
10273 * *
10274 ******************************************************************************/
dc_trigger_items_hosts_enabled(const char * expression)10275 static int dc_trigger_items_hosts_enabled(const char *expression)
10276 {
10277 zbx_uint64_t functionid;
10278 const ZBX_DC_ITEM *dc_item;
10279 const ZBX_DC_FUNCTION *dc_function;
10280 const ZBX_DC_HOST *dc_host;
10281 const char *p, *q;
10282
10283 for (p = expression; '\0' != *p; p++)
10284 {
10285 if ('{' != *p)
10286 continue;
10287
10288 if ('$' == p[1])
10289 {
10290 int macro_r, context_l, context_r;
10291
10292 if (SUCCEED == zbx_user_macro_parse(p, ¯o_r, &context_l, &context_r, NULL))
10293 p += macro_r;
10294 else
10295 p++;
10296
10297 continue;
10298 }
10299
10300 if (NULL == (q = strchr(p + 1, '}')))
10301 return FAIL;
10302
10303 if (SUCCEED != is_uint64_n(p + 1, q - p - 1, &functionid))
10304 continue;
10305
10306 if (NULL == (dc_function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &functionid)) ||
10307 NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &dc_function->itemid)) ||
10308 ITEM_STATUS_ACTIVE != dc_item->status ||
10309 NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)) ||
10310 HOST_STATUS_MONITORED != dc_host->status)
10311 {
10312 return FAIL;
10313 }
10314
10315 p = q;
10316 }
10317
10318 return SUCCEED;
10319 }
10320
10321 /******************************************************************************
10322 * *
10323 * Function: dc_status_update *
10324 * *
10325 * Purpose: check when status information stored in configuration cache was *
10326 * updated last time and update it if necessary *
10327 * *
10328 * Comments: This function gathers the following information: *
10329 * - number of enabled hosts (total and per proxy) *
10330 * - number of disabled hosts (total and per proxy) *
10331 * - number of enabled and supported items (total, per host and *
10332 * per proxy) *
10333 * - number of enabled and not supported items (total, per host *
10334 * and per proxy) *
10335 * - number of disabled items (total and per proxy) *
10336 * - number of enabled triggers with value OK *
10337 * - number of enabled triggers with value PROBLEM *
10338 * - number of disabled triggers *
10339 * - required performance (total and per proxy) *
10340 * Gathered information can then be displayed in the frontend (see *
10341 * "status.get" request) and used in calculation of zabbix[] items. *
10342 * *
10343 * NOTE: Always call this function before accessing information stored in *
10344 * config->status as well as host and required performance counters *
10345 * stored in elements of config->proxies and item counters in elements *
10346 * of config->hosts. *
10347 * *
10348 ******************************************************************************/
dc_status_update(void)10349 static void dc_status_update(void)
10350 {
10351 #define ZBX_STATUS_LIFETIME SEC_PER_MIN
10352
10353 zbx_hashset_iter_t iter;
10354 ZBX_DC_PROXY *dc_proxy;
10355 ZBX_DC_HOST *dc_host, *dc_proxy_host;
10356 const ZBX_DC_ITEM *dc_item;
10357 const ZBX_DC_TRIGGER *dc_trigger;
10358
10359 if (0 != config->status->last_update && config->status->last_update + ZBX_STATUS_LIFETIME > time(NULL))
10360 return;
10361
10362 /* reset global counters */
10363
10364 config->status->hosts_monitored = 0;
10365 config->status->hosts_not_monitored = 0;
10366 config->status->items_active_normal = 0;
10367 config->status->items_active_notsupported = 0;
10368 config->status->items_disabled = 0;
10369 config->status->triggers_enabled_ok = 0;
10370 config->status->triggers_enabled_problem = 0;
10371 config->status->triggers_disabled = 0;
10372 config->status->required_performance = 0.0;
10373
10374 /* loop over proxies to reset per-proxy host and required performance counters */
10375
10376 zbx_hashset_iter_reset(&config->proxies, &iter);
10377
10378 while (NULL != (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_iter_next(&iter)))
10379 {
10380 dc_proxy->hosts_monitored = 0;
10381 dc_proxy->hosts_not_monitored = 0;
10382 dc_proxy->required_performance = 0.0;
10383 }
10384
10385 /* loop over hosts */
10386
10387 zbx_hashset_iter_reset(&config->hosts, &iter);
10388
10389 while (NULL != (dc_host = (ZBX_DC_HOST *)zbx_hashset_iter_next(&iter)))
10390 {
10391 /* reset per-host/per-proxy item counters */
10392
10393 dc_host->items_active_normal = 0;
10394 dc_host->items_active_notsupported = 0;
10395 dc_host->items_disabled = 0;
10396
10397 /* gather per-proxy statistics of enabled and disabled hosts */
10398 switch (dc_host->status)
10399 {
10400 case HOST_STATUS_MONITORED:
10401 config->status->hosts_monitored++;
10402 if (0 == dc_host->proxy_hostid)
10403 break;
10404 if (NULL == (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &dc_host->proxy_hostid)))
10405 break;
10406 dc_proxy->hosts_monitored++;
10407 break;
10408 case HOST_STATUS_NOT_MONITORED:
10409 config->status->hosts_not_monitored++;
10410 if (0 == dc_host->proxy_hostid)
10411 break;
10412 if (NULL == (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &dc_host->proxy_hostid)))
10413 break;
10414 dc_proxy->hosts_not_monitored++;
10415 break;
10416 }
10417 }
10418
10419 /* loop over items to gather per-host and per-proxy statistics */
10420
10421 zbx_hashset_iter_reset(&config->items, &iter);
10422
10423 while (NULL != (dc_item = (ZBX_DC_ITEM *)zbx_hashset_iter_next(&iter)))
10424 {
10425 dc_proxy = NULL;
10426 dc_proxy_host = NULL;
10427
10428 if (ZBX_FLAG_DISCOVERY_NORMAL != dc_item->flags && ZBX_FLAG_DISCOVERY_CREATED != dc_item->flags)
10429 continue;
10430
10431 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
10432 continue;
10433
10434 if (0 != dc_host->proxy_hostid)
10435 {
10436 dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &dc_host->proxy_hostid);
10437 dc_proxy_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_host->proxy_hostid);
10438 }
10439
10440 switch (dc_item->status)
10441 {
10442 case ITEM_STATUS_ACTIVE:
10443 if (HOST_STATUS_MONITORED == dc_host->status)
10444 {
10445 int delay;
10446
10447 if (SUCCEED == zbx_interval_preproc(dc_item->delay, &delay, NULL, NULL) &&
10448 0 != delay)
10449 {
10450 config->status->required_performance += 1.0 / delay;
10451
10452 if (NULL != dc_proxy)
10453 dc_proxy->required_performance += 1.0 / delay;
10454 }
10455
10456 switch (dc_item->state)
10457 {
10458 case ITEM_STATE_NORMAL:
10459 config->status->items_active_normal++;
10460 dc_host->items_active_normal++;
10461 if (NULL != dc_proxy_host)
10462 dc_proxy_host->items_active_normal++;
10463 break;
10464 case ITEM_STATE_NOTSUPPORTED:
10465 config->status->items_active_notsupported++;
10466 dc_host->items_active_notsupported++;
10467 if (NULL != dc_proxy_host)
10468 dc_proxy_host->items_active_notsupported++;
10469 break;
10470 default:
10471 THIS_SHOULD_NEVER_HAPPEN;
10472 }
10473
10474 break;
10475 }
10476 ZBX_FALLTHROUGH;
10477 case ITEM_STATUS_DISABLED:
10478 config->status->items_disabled++;
10479 if (NULL != dc_proxy_host)
10480 dc_proxy_host->items_disabled++;
10481 break;
10482 default:
10483 THIS_SHOULD_NEVER_HAPPEN;
10484 }
10485 }
10486
10487 /* loop over triggers to gather enabled and disabled trigger statistics */
10488
10489 zbx_hashset_iter_reset(&config->triggers, &iter);
10490
10491 while (NULL != (dc_trigger = (ZBX_DC_TRIGGER *)zbx_hashset_iter_next(&iter)))
10492 {
10493 switch (dc_trigger->status)
10494 {
10495 case TRIGGER_STATUS_ENABLED:
10496 if (SUCCEED == dc_trigger_items_hosts_enabled(dc_trigger->expression) &&
10497 (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION != dc_trigger->recovery_mode ||
10498 SUCCEED == dc_trigger_items_hosts_enabled(dc_trigger->recovery_expression)))
10499 {
10500 switch (dc_trigger->value)
10501 {
10502 case TRIGGER_VALUE_OK:
10503 config->status->triggers_enabled_ok++;
10504 break;
10505 case TRIGGER_VALUE_PROBLEM:
10506 config->status->triggers_enabled_problem++;
10507 break;
10508 default:
10509 THIS_SHOULD_NEVER_HAPPEN;
10510 }
10511
10512 break;
10513 }
10514 ZBX_FALLTHROUGH;
10515 case TRIGGER_STATUS_DISABLED:
10516 config->status->triggers_disabled++;
10517 break;
10518 default:
10519 THIS_SHOULD_NEVER_HAPPEN;
10520 }
10521 }
10522
10523 config->status->last_update = time(NULL);
10524
10525 #undef ZBX_STATUS_LIFETIME
10526 }
10527
10528 /******************************************************************************
10529 * *
10530 * Function: DCget_item_count *
10531 * *
10532 * Purpose: return the number of active items *
10533 * *
10534 * Parameters: hostid - [IN] the host id, pass 0 to specify all hosts *
10535 * *
10536 * Return value: the number of active items *
10537 * *
10538 ******************************************************************************/
DCget_item_count(zbx_uint64_t hostid)10539 zbx_uint64_t DCget_item_count(zbx_uint64_t hostid)
10540 {
10541 zbx_uint64_t count;
10542 const ZBX_DC_HOST *dc_host;
10543
10544 WRLOCK_CACHE;
10545
10546 dc_status_update();
10547
10548 if (0 == hostid)
10549 count = config->status->items_active_normal + config->status->items_active_notsupported;
10550 else if (NULL != (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)))
10551 count = dc_host->items_active_normal + dc_host->items_active_notsupported;
10552 else
10553 count = 0;
10554
10555 UNLOCK_CACHE;
10556
10557 return count;
10558 }
10559
10560 /******************************************************************************
10561 * *
10562 * Function: DCget_item_unsupported_count *
10563 * *
10564 * Purpose: return the number of active unsupported items *
10565 * *
10566 * Parameters: hostid - [IN] the host id, pass 0 to specify all hosts *
10567 * *
10568 * Return value: the number of active unsupported items *
10569 * *
10570 ******************************************************************************/
DCget_item_unsupported_count(zbx_uint64_t hostid)10571 zbx_uint64_t DCget_item_unsupported_count(zbx_uint64_t hostid)
10572 {
10573 zbx_uint64_t count;
10574 const ZBX_DC_HOST *dc_host;
10575
10576 WRLOCK_CACHE;
10577
10578 dc_status_update();
10579
10580 if (0 == hostid)
10581 count = config->status->items_active_notsupported;
10582 else if (NULL != (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)))
10583 count = dc_host->items_active_notsupported;
10584 else
10585 count = 0;
10586
10587 UNLOCK_CACHE;
10588
10589 return count;
10590 }
10591
10592 /******************************************************************************
10593 * *
10594 * Function: DCget_trigger_count *
10595 * *
10596 * Purpose: count active triggers *
10597 * *
10598 ******************************************************************************/
DCget_trigger_count(void)10599 zbx_uint64_t DCget_trigger_count(void)
10600 {
10601 zbx_uint64_t count;
10602
10603 WRLOCK_CACHE;
10604
10605 dc_status_update();
10606
10607 count = config->status->triggers_enabled_ok + config->status->triggers_enabled_problem;
10608
10609 UNLOCK_CACHE;
10610
10611 return count;
10612 }
10613
10614 /******************************************************************************
10615 * *
10616 * Function: DCget_host_count *
10617 * *
10618 * Purpose: count monitored and not monitored hosts *
10619 * *
10620 ******************************************************************************/
DCget_host_count(void)10621 zbx_uint64_t DCget_host_count(void)
10622 {
10623 zbx_uint64_t nhosts;
10624
10625 WRLOCK_CACHE;
10626
10627 dc_status_update();
10628
10629 nhosts = config->status->hosts_monitored;
10630
10631 UNLOCK_CACHE;
10632
10633 return nhosts;
10634 }
10635
10636 /******************************************************************************
10637 * *
10638 * Function: DCget_required_performance *
10639 * *
10640 * Return value: the required nvps number *
10641 * *
10642 ******************************************************************************/
DCget_required_performance(void)10643 double DCget_required_performance(void)
10644 {
10645 double nvps;
10646
10647 WRLOCK_CACHE;
10648
10649 dc_status_update();
10650
10651 nvps = config->status->required_performance;
10652
10653 UNLOCK_CACHE;
10654
10655 return nvps;
10656 }
10657
10658 /******************************************************************************
10659 * *
10660 * Function: DCget_count_stats_all *
10661 * *
10662 * Purpose: retrieves all internal metrics of the configuration cache *
10663 * *
10664 * Parameters: stats - [OUT] the configuration cache statistics *
10665 * *
10666 ******************************************************************************/
DCget_count_stats_all(zbx_config_cache_info_t * stats)10667 void DCget_count_stats_all(zbx_config_cache_info_t *stats)
10668 {
10669 WRLOCK_CACHE;
10670
10671 dc_status_update();
10672
10673 stats->hosts = config->status->hosts_monitored;
10674 stats->items = config->status->items_active_normal + config->status->items_active_notsupported;
10675 stats->items_unsupported = config->status->items_active_notsupported;
10676 stats->requiredperformance = config->status->required_performance;
10677
10678 UNLOCK_CACHE;
10679 }
10680
proxy_counter_ui64_push(zbx_vector_ptr_t * vector,zbx_uint64_t proxyid,zbx_uint64_t counter)10681 static void proxy_counter_ui64_push(zbx_vector_ptr_t *vector, zbx_uint64_t proxyid, zbx_uint64_t counter)
10682 {
10683 zbx_proxy_counter_t *proxy_counter;
10684
10685 proxy_counter = (zbx_proxy_counter_t *)zbx_malloc(NULL, sizeof(zbx_proxy_counter_t));
10686 proxy_counter->proxyid = proxyid;
10687 proxy_counter->counter_value.ui64 = counter;
10688 zbx_vector_ptr_append(vector, proxy_counter);
10689 }
10690
proxy_counter_dbl_push(zbx_vector_ptr_t * vector,zbx_uint64_t proxyid,double counter)10691 static void proxy_counter_dbl_push(zbx_vector_ptr_t *vector, zbx_uint64_t proxyid, double counter)
10692 {
10693 zbx_proxy_counter_t *proxy_counter;
10694
10695 proxy_counter = (zbx_proxy_counter_t *)zbx_malloc(NULL, sizeof(zbx_proxy_counter_t));
10696 proxy_counter->proxyid = proxyid;
10697 proxy_counter->counter_value.dbl = counter;
10698 zbx_vector_ptr_append(vector, proxy_counter);
10699 }
10700
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)10701 void DCget_status(zbx_vector_ptr_t *hosts_monitored, zbx_vector_ptr_t *hosts_not_monitored,
10702 zbx_vector_ptr_t *items_active_normal, zbx_vector_ptr_t *items_active_notsupported,
10703 zbx_vector_ptr_t *items_disabled, zbx_uint64_t *triggers_enabled_ok,
10704 zbx_uint64_t *triggers_enabled_problem, zbx_uint64_t *triggers_disabled,
10705 zbx_vector_ptr_t *required_performance)
10706 {
10707 zbx_hashset_iter_t iter;
10708 const ZBX_DC_PROXY *dc_proxy;
10709 const ZBX_DC_HOST *dc_proxy_host;
10710
10711 WRLOCK_CACHE;
10712
10713 dc_status_update();
10714
10715 proxy_counter_ui64_push(hosts_monitored, 0, config->status->hosts_monitored);
10716 proxy_counter_ui64_push(hosts_not_monitored, 0, config->status->hosts_not_monitored);
10717 proxy_counter_ui64_push(items_active_normal, 0, config->status->items_active_normal);
10718 proxy_counter_ui64_push(items_active_notsupported, 0, config->status->items_active_notsupported);
10719 proxy_counter_ui64_push(items_disabled, 0, config->status->items_disabled);
10720 *triggers_enabled_ok = config->status->triggers_enabled_ok;
10721 *triggers_enabled_problem = config->status->triggers_enabled_problem;
10722 *triggers_disabled = config->status->triggers_disabled;
10723 proxy_counter_dbl_push(required_performance, 0, config->status->required_performance);
10724
10725 zbx_hashset_iter_reset(&config->proxies, &iter);
10726
10727 while (NULL != (dc_proxy = (ZBX_DC_PROXY *)zbx_hashset_iter_next(&iter)))
10728 {
10729 proxy_counter_ui64_push(hosts_monitored, dc_proxy->hostid, dc_proxy->hosts_monitored);
10730 proxy_counter_ui64_push(hosts_not_monitored, dc_proxy->hostid, dc_proxy->hosts_not_monitored);
10731
10732 if (NULL != (dc_proxy_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_proxy->hostid)))
10733 {
10734 proxy_counter_ui64_push(items_active_normal, dc_proxy->hostid,
10735 dc_proxy_host->items_active_normal);
10736 proxy_counter_ui64_push(items_active_notsupported, dc_proxy->hostid,
10737 dc_proxy_host->items_active_notsupported);
10738 proxy_counter_ui64_push(items_disabled, dc_proxy->hostid, dc_proxy_host->items_disabled);
10739 }
10740
10741 proxy_counter_dbl_push(required_performance, dc_proxy->hostid, dc_proxy->required_performance);
10742 }
10743
10744 UNLOCK_CACHE;
10745 }
10746
10747 /******************************************************************************
10748 * *
10749 * Function: DCget_expressions_by_names *
10750 * *
10751 * Purpose: retrieves global expression data from cache *
10752 * *
10753 * Parameters: expressions - [OUT] a vector of expression data pointers *
10754 * names - [IN] a vector containing expression names *
10755 * names_num - [IN] the number of items in names vector *
10756 * *
10757 * Comment: The expressions vector contains allocated data, which must be *
10758 * freed afterwards with zbx_regexp_clean_expressions() function. *
10759 * *
10760 ******************************************************************************/
DCget_expressions_by_names(zbx_vector_ptr_t * expressions,const char * const * names,int names_num)10761 void DCget_expressions_by_names(zbx_vector_ptr_t *expressions, const char * const *names, int names_num)
10762 {
10763 int i, iname;
10764 const ZBX_DC_EXPRESSION *expression;
10765 const ZBX_DC_REGEXP *regexp;
10766 ZBX_DC_REGEXP search_regexp;
10767
10768 RDLOCK_CACHE;
10769
10770 for (iname = 0; iname < names_num; iname++)
10771 {
10772 search_regexp.name = names[iname];
10773
10774 if (NULL != (regexp = (const ZBX_DC_REGEXP *)zbx_hashset_search(&config->regexps, &search_regexp)))
10775 {
10776 for (i = 0; i < regexp->expressionids.values_num; i++)
10777 {
10778 zbx_uint64_t expressionid = regexp->expressionids.values[i];
10779 zbx_expression_t *rxp;
10780
10781 if (NULL == (expression = (const ZBX_DC_EXPRESSION *)zbx_hashset_search(&config->expressions, &expressionid)))
10782 continue;
10783
10784 rxp = (zbx_expression_t *)zbx_malloc(NULL, sizeof(zbx_expression_t));
10785 rxp->name = zbx_strdup(NULL, regexp->name);
10786 rxp->expression = zbx_strdup(NULL, expression->expression);
10787 rxp->exp_delimiter = expression->delimiter;
10788 rxp->case_sensitive = expression->case_sensitive;
10789 rxp->expression_type = expression->type;
10790
10791 zbx_vector_ptr_append(expressions, rxp);
10792 }
10793 }
10794 }
10795
10796 UNLOCK_CACHE;
10797 }
10798
10799 /******************************************************************************
10800 * *
10801 * Function: DCget_expression *
10802 * *
10803 * Purpose: retrieves regular expression data from cache *
10804 * *
10805 * Parameters: expressions - [OUT] a vector of expression data pointers *
10806 * name - [IN] the regular expression name *
10807 * *
10808 * Comment: The expressions vector contains allocated data, which must be *
10809 * freed afterwards with zbx_regexp_clean_expressions() function. *
10810 * *
10811 ******************************************************************************/
DCget_expressions_by_name(zbx_vector_ptr_t * expressions,const char * name)10812 void DCget_expressions_by_name(zbx_vector_ptr_t *expressions, const char *name)
10813 {
10814 DCget_expressions_by_names(expressions, &name, 1);
10815 }
10816
10817 /******************************************************************************
10818 * *
10819 * Function: DCget_data_expected_from *
10820 * *
10821 * Purpose: Returns time since which data is expected for the given item. We *
10822 * would not mind not having data for the item before that time, but *
10823 * since that time we expect data to be coming. *
10824 * *
10825 * Parameters: itemid - [IN] the item id *
10826 * seconds - [OUT] the time data is expected as a Unix timestamp *
10827 * *
10828 ******************************************************************************/
DCget_data_expected_from(zbx_uint64_t itemid,int * seconds)10829 int DCget_data_expected_from(zbx_uint64_t itemid, int *seconds)
10830 {
10831 const ZBX_DC_ITEM *dc_item;
10832 const ZBX_DC_HOST *dc_host;
10833 int ret = FAIL;
10834
10835 RDLOCK_CACHE;
10836
10837 if (NULL == (dc_item = (const ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemid)))
10838 goto unlock;
10839
10840 if (ITEM_STATUS_ACTIVE != dc_item->status)
10841 goto unlock;
10842
10843 if (NULL == (dc_host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
10844 goto unlock;
10845
10846 if (HOST_STATUS_MONITORED != dc_host->status)
10847 goto unlock;
10848
10849 *seconds = MAX(dc_item->data_expected_from, dc_host->data_expected_from);
10850
10851 ret = SUCCEED;
10852 unlock:
10853 UNLOCK_CACHE;
10854
10855 return ret;
10856 }
10857
10858 /******************************************************************************
10859 * *
10860 * Function: dc_get_hostids_by_functionids *
10861 * *
10862 * Purpose: get host identifiers for the specified list of functions *
10863 * *
10864 * Parameters: functionids - [IN] the function ids *
10865 * functionids_num - [IN] the number of function ids *
10866 * hostids - [OUT] the host ids *
10867 * *
10868 * Comments: this function must be used only by configuration syncer *
10869 * *
10870 ******************************************************************************/
dc_get_hostids_by_functionids(const zbx_uint64_t * functionids,int functionids_num,zbx_vector_uint64_t * hostids)10871 void dc_get_hostids_by_functionids(const zbx_uint64_t *functionids, int functionids_num,
10872 zbx_vector_uint64_t *hostids)
10873 {
10874 const ZBX_DC_FUNCTION *function;
10875 const ZBX_DC_ITEM *item;
10876 int i;
10877
10878 for (i = 0; i < functionids_num; i++)
10879 {
10880 if (NULL == (function = (const ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &functionids[i])))
10881 continue;
10882
10883 if (NULL != (item = (const ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &function->itemid)))
10884 zbx_vector_uint64_append(hostids, item->hostid);
10885 }
10886
10887 zbx_vector_uint64_sort(hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
10888 zbx_vector_uint64_uniq(hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
10889 }
10890
10891 /******************************************************************************
10892 * *
10893 * Function: DCget_hostids_by_functionids *
10894 * *
10895 * Purpose: get function host ids grouped by an object (trigger) id *
10896 * *
10897 * Parameters: functionids - [IN] the function ids *
10898 * hostids - [OUT] the host ids *
10899 * *
10900 ******************************************************************************/
DCget_hostids_by_functionids(zbx_vector_uint64_t * functionids,zbx_vector_uint64_t * hostids)10901 void DCget_hostids_by_functionids(zbx_vector_uint64_t *functionids, zbx_vector_uint64_t *hostids)
10902 {
10903 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
10904
10905 RDLOCK_CACHE;
10906
10907 dc_get_hostids_by_functionids(functionids->values, functionids->values_num, hostids);
10908
10909 UNLOCK_CACHE;
10910
10911 zabbix_log(LOG_LEVEL_DEBUG, "End of %s(): found %d hosts", __func__, hostids->values_num);
10912 }
10913
10914 /******************************************************************************
10915 * *
10916 * Function: dc_get_hosts_by_functionids *
10917 * *
10918 * Purpose: get hosts for the specified list of functions *
10919 * *
10920 * Parameters: functionids - [IN] the function ids *
10921 * functionids_num - [IN] the number of function ids *
10922 * hosts - [OUT] hosts *
10923 * *
10924 ******************************************************************************/
dc_get_hosts_by_functionids(const zbx_uint64_t * functionids,int functionids_num,zbx_hashset_t * hosts)10925 static void dc_get_hosts_by_functionids(const zbx_uint64_t *functionids, int functionids_num, zbx_hashset_t *hosts)
10926 {
10927 const ZBX_DC_FUNCTION *dc_function;
10928 const ZBX_DC_ITEM *dc_item;
10929 const ZBX_DC_HOST *dc_host;
10930 DC_HOST host;
10931 int i;
10932
10933 for (i = 0; i < functionids_num; i++)
10934 {
10935 if (NULL == (dc_function = (const ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions, &functionids[i])))
10936 continue;
10937
10938 if (NULL == (dc_item = (const ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &dc_function->itemid)))
10939 continue;
10940
10941 if (NULL == (dc_host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
10942 continue;
10943
10944 DCget_host(&host, dc_host, ZBX_ITEM_GET_ALL);
10945 zbx_hashset_insert(hosts, &host, sizeof(host));
10946 }
10947 }
10948
10949 /******************************************************************************
10950 * *
10951 * Function: DCget_hosts_by_functionids *
10952 * *
10953 * Purpose: get hosts for the specified list of functions *
10954 * *
10955 * Parameters: functionids - [IN] the function ids *
10956 * hosts - [OUT] hosts *
10957 * *
10958 ******************************************************************************/
DCget_hosts_by_functionids(const zbx_vector_uint64_t * functionids,zbx_hashset_t * hosts)10959 void DCget_hosts_by_functionids(const zbx_vector_uint64_t *functionids, zbx_hashset_t *hosts)
10960 {
10961 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
10962
10963 RDLOCK_CACHE;
10964
10965 dc_get_hosts_by_functionids(functionids->values, functionids->values_num, hosts);
10966
10967 UNLOCK_CACHE;
10968
10969 zabbix_log(LOG_LEVEL_DEBUG, "End of %s(): found %d hosts", __func__, hosts->num_data);
10970 }
10971
10972 /******************************************************************************
10973 * *
10974 * Function: DCget_internal_action_count *
10975 * *
10976 * Purpose: get number of enabled internal actions *
10977 * *
10978 * Return value: number of enabled internal actions *
10979 * *
10980 ******************************************************************************/
DCget_internal_action_count(void)10981 unsigned int DCget_internal_action_count(void)
10982 {
10983 unsigned int count;
10984
10985 RDLOCK_CACHE;
10986
10987 count = config->internal_actions;
10988
10989 UNLOCK_CACHE;
10990
10991 return count;
10992 }
10993
10994 /******************************************************************************
10995 * *
10996 * Function: zbx_config_get *
10997 * *
10998 * Purpose: get global configuration data *
10999 * *
11000 * Parameters: cfg - [OUT] the global configuration data *
11001 * flags - [IN] the flags specifying fields to get, *
11002 * see ZBX_CONFIG_FLAGS_ defines *
11003 * *
11004 * Comments: It's recommended to cleanup 'cfg' structure after use with *
11005 * zbx_config_clean() function even if only simple fields were *
11006 * requested. *
11007 * *
11008 ******************************************************************************/
zbx_config_get(zbx_config_t * cfg,zbx_uint64_t flags)11009 void zbx_config_get(zbx_config_t *cfg, zbx_uint64_t flags)
11010 {
11011 RDLOCK_CACHE;
11012
11013 if (0 != (flags & ZBX_CONFIG_FLAGS_SEVERITY_NAME))
11014 {
11015 int i;
11016
11017 cfg->severity_name = (char **)zbx_malloc(NULL, TRIGGER_SEVERITY_COUNT * sizeof(char *));
11018
11019 for (i = 0; i < TRIGGER_SEVERITY_COUNT; i++)
11020 cfg->severity_name[i] = zbx_strdup(NULL, config->config->severity_name[i]);
11021 }
11022
11023 if (0 != (flags & ZBX_CONFIG_FLAGS_DISCOVERY_GROUPID))
11024 cfg->discovery_groupid = config->config->discovery_groupid;
11025
11026 if (0 != (flags & ZBX_CONFIG_FLAGS_DEFAULT_INVENTORY_MODE))
11027 cfg->default_inventory_mode = config->config->default_inventory_mode;
11028
11029 if (0 != (flags & ZBX_CONFIG_FLAGS_REFRESH_UNSUPPORTED))
11030 cfg->refresh_unsupported = config->config->refresh_unsupported;
11031
11032 if (0 != (flags & ZBX_CONFIG_FLAGS_SNMPTRAP_LOGGING))
11033 cfg->snmptrap_logging = config->config->snmptrap_logging;
11034
11035 if (0 != (flags & ZBX_CONFIG_FLAGS_HOUSEKEEPER))
11036 cfg->hk = config->config->hk;
11037
11038 if (0 != (flags & ZBX_CONFIG_FLAGS_DB_EXTENSION))
11039 {
11040 cfg->db.extension = zbx_strdup(NULL, config->config->db.extension);
11041 cfg->db.history_compression_status = config->config->db.history_compression_status;
11042 cfg->db.history_compression_availability = config->config->db.history_compression_availability;
11043 cfg->db.history_compress_older = config->config->db.history_compress_older;
11044 }
11045
11046 if (0 != (flags & ZBX_CONFIG_FLAGS_AUTOREG_TLS_ACCEPT))
11047 cfg->autoreg_tls_accept = config->config->autoreg_tls_accept;
11048
11049 UNLOCK_CACHE;
11050
11051 cfg->flags = flags;
11052 }
11053
11054 /******************************************************************************
11055 * *
11056 * Function: zbx_config_get_hk_mode *
11057 * *
11058 * Purpose: get housekeeping mode for history and trends tables *
11059 * *
11060 * Parameters: history_mode - [OUT] history housekeeping mode, can be either *
11061 * disabled, enabled or partitioning *
11062 * trends_mode - [OUT] trends housekeeping mode, can be either *
11063 * disabled, enabled or partitioning *
11064 * *
11065 ******************************************************************************/
zbx_config_get_hk_mode(unsigned char * history_mode,unsigned char * trends_mode)11066 void zbx_config_get_hk_mode(unsigned char *history_mode, unsigned char *trends_mode)
11067 {
11068 RDLOCK_CACHE;
11069 *history_mode = config->config->hk.history_mode;
11070 *trends_mode = config->config->hk.trends_mode;
11071 UNLOCK_CACHE;
11072 }
11073
11074 /******************************************************************************
11075 * *
11076 * Function: zbx_config_clean *
11077 * *
11078 * Purpose: cleans global configuration data structure filled *
11079 * by zbx_config_get() function *
11080 * *
11081 * Parameters: cfg - [IN] the global configuration data *
11082 * *
11083 ******************************************************************************/
zbx_config_clean(zbx_config_t * cfg)11084 void zbx_config_clean(zbx_config_t *cfg)
11085 {
11086 if (0 != (cfg->flags & ZBX_CONFIG_FLAGS_SEVERITY_NAME))
11087 {
11088 int i;
11089
11090 for (i = 0; i < TRIGGER_SEVERITY_COUNT; i++)
11091 zbx_free(cfg->severity_name[i]);
11092
11093 zbx_free(cfg->severity_name);
11094 }
11095
11096 if (0 != (cfg->flags & ZBX_CONFIG_FLAGS_DB_EXTENSION))
11097 zbx_free(cfg->db.extension);
11098 }
11099
11100 /******************************************************************************
11101 * *
11102 * Function: DCreset_hosts_availability *
11103 * *
11104 * Purpose: resets host availability for disabled hosts and hosts without *
11105 * enabled items for the corresponding interface *
11106 * *
11107 * Parameters: hosts - [OUT] changed host availability data *
11108 * *
11109 * Return value: SUCCEED - host availability was reset for at least one host *
11110 * FAIL - no hosts required availability reset *
11111 * *
11112 * Comments: This function resets host availability in configuration cache. *
11113 * The caller must perform corresponding database updates based *
11114 * on returned host availability reset data. On server the function *
11115 * skips hosts handled by proxies. *
11116 * *
11117 ******************************************************************************/
DCreset_hosts_availability(zbx_vector_ptr_t * hosts)11118 int DCreset_hosts_availability(zbx_vector_ptr_t *hosts)
11119 {
11120 ZBX_DC_HOST *host;
11121 zbx_hashset_iter_t iter;
11122 zbx_host_availability_t *ha = NULL;
11123 int now;
11124
11125 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
11126
11127 now = time(NULL);
11128
11129 WRLOCK_CACHE;
11130
11131 zbx_hashset_iter_reset(&config->hosts, &iter);
11132
11133 while (NULL != (host = (ZBX_DC_HOST *)zbx_hashset_iter_next(&iter)))
11134 {
11135 int items_num = 0, snmp_items_num = 0, ipmi_items_num = 0, jmx_items_num = 0;
11136
11137 /* On server skip hosts handled by proxies. They are handled directly */
11138 /* when receiving hosts' availability data from proxies. */
11139 /* Unless a host was just (re)assigned to a proxy or the proxy has */
11140 /* not updated its status during the maximum proxy heartbeat period. */
11141 /* In this case reset all interfaces to unknown status. */
11142 if (0 == host->reset_availability &&
11143 0 != (program_type & ZBX_PROGRAM_TYPE_SERVER) && 0 != host->proxy_hostid)
11144 {
11145 ZBX_DC_PROXY *proxy;
11146
11147 if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &host->proxy_hostid)))
11148 {
11149 /* SEC_PER_MIN is a tolerance interval, it was chosen arbitrarily */
11150 if (ZBX_PROXY_HEARTBEAT_FREQUENCY_MAX + SEC_PER_MIN >= now - proxy->lastaccess)
11151 continue;
11152 }
11153
11154 host->reset_availability = 1;
11155 }
11156
11157 if (NULL == ha)
11158 ha = (zbx_host_availability_t *)zbx_malloc(NULL, sizeof(zbx_host_availability_t));
11159
11160 zbx_host_availability_init(ha, host->hostid);
11161
11162 if (0 == host->reset_availability)
11163 {
11164 items_num = host->items_num;
11165 snmp_items_num = host->snmp_items_num;
11166 ipmi_items_num = host->ipmi_items_num;
11167 jmx_items_num = host->jmx_items_num;
11168 }
11169
11170 if (0 == items_num && HOST_AVAILABLE_UNKNOWN != host->available)
11171 zbx_agent_availability_init(&ha->agents[ZBX_AGENT_ZABBIX], HOST_AVAILABLE_UNKNOWN, "", 0, 0);
11172
11173 if (0 == snmp_items_num && HOST_AVAILABLE_UNKNOWN != host->snmp_available)
11174 zbx_agent_availability_init(&ha->agents[ZBX_AGENT_SNMP], HOST_AVAILABLE_UNKNOWN, "", 0, 0);
11175
11176 if (0 == ipmi_items_num && HOST_AVAILABLE_UNKNOWN != host->ipmi_available)
11177 zbx_agent_availability_init(&ha->agents[ZBX_AGENT_IPMI], HOST_AVAILABLE_UNKNOWN, "", 0, 0);
11178
11179 if (0 == jmx_items_num && HOST_AVAILABLE_UNKNOWN != host->jmx_available)
11180 zbx_agent_availability_init(&ha->agents[ZBX_AGENT_JMX], HOST_AVAILABLE_UNKNOWN, "", 0, 0);
11181
11182 if (SUCCEED == zbx_host_availability_is_set(ha))
11183 {
11184 if (SUCCEED == DChost_set_availability(host, now, ha))
11185 {
11186 zbx_vector_ptr_append(hosts, ha);
11187 ha = NULL;
11188 }
11189 else
11190 zbx_host_availability_clean(ha);
11191 }
11192
11193 host->reset_availability = 0;
11194 }
11195 UNLOCK_CACHE;
11196
11197 zbx_free(ha);
11198
11199 zbx_vector_ptr_sort(hosts, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
11200
11201 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() hosts:%d", __func__, hosts->values_num);
11202
11203 return 0 == hosts->values_num ? FAIL : SUCCEED;
11204 }
11205
11206 /******************************************************************************
11207 * *
11208 * Function: DCget_hosts_availability *
11209 * *
11210 * Purpose: gets availability data for hosts with availability data changed *
11211 * in period from last availability update to the specified *
11212 * timestamp *
11213 * *
11214 * Parameters: hosts - [OUT] changed host availability data *
11215 * ts - [OUT] the availability diff timestamp *
11216 * *
11217 * Return value: SUCCEED - availability was changed for at least one host *
11218 * FAIL - no host availability was changed *
11219 * *
11220 ******************************************************************************/
DCget_hosts_availability(zbx_vector_ptr_t * hosts,int * ts)11221 int DCget_hosts_availability(zbx_vector_ptr_t *hosts, int *ts)
11222 {
11223 const ZBX_DC_HOST *host;
11224 zbx_hashset_iter_t iter;
11225 zbx_host_availability_t *ha = NULL;
11226
11227 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
11228
11229 RDLOCK_CACHE;
11230
11231 *ts = time(NULL);
11232
11233 zbx_hashset_iter_reset(&config->hosts, &iter);
11234
11235 while (NULL != (host = (const ZBX_DC_HOST *)zbx_hashset_iter_next(&iter)))
11236 {
11237 if (config->availability_diff_ts <= host->availability_ts && host->availability_ts < *ts)
11238 {
11239 ha = (zbx_host_availability_t *)zbx_malloc(NULL, sizeof(zbx_host_availability_t));
11240 zbx_host_availability_init(ha, host->hostid);
11241
11242 zbx_agent_availability_init(&ha->agents[ZBX_AGENT_ZABBIX], host->available, host->error,
11243 host->errors_from, host->disable_until);
11244 zbx_agent_availability_init(&ha->agents[ZBX_AGENT_SNMP], host->snmp_available, host->snmp_error,
11245 host->snmp_errors_from, host->snmp_disable_until);
11246 zbx_agent_availability_init(&ha->agents[ZBX_AGENT_IPMI], host->ipmi_available, host->ipmi_error,
11247 host->ipmi_errors_from, host->ipmi_disable_until);
11248 zbx_agent_availability_init(&ha->agents[ZBX_AGENT_JMX], host->jmx_available, host->jmx_error,
11249 host->jmx_errors_from, host->jmx_disable_until);
11250
11251 zbx_vector_ptr_append(hosts, ha);
11252 }
11253 }
11254
11255 UNLOCK_CACHE;
11256
11257 zbx_vector_ptr_sort(hosts, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
11258
11259 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() hosts:%d", __func__, hosts->values_num);
11260
11261 return 0 == hosts->values_num ? FAIL : SUCCEED;
11262 }
11263
11264 /******************************************************************************
11265 * *
11266 * Function: DCtouch_hosts_availability *
11267 * *
11268 * Purpose: sets availability timestamp to current time for the specified *
11269 * hosts *
11270 * *
11271 * Parameters: hostids - [IN] the host identifiers *
11272 * *
11273 ******************************************************************************/
DCtouch_hosts_availability(const zbx_vector_uint64_t * hostids)11274 void DCtouch_hosts_availability(const zbx_vector_uint64_t *hostids)
11275 {
11276 ZBX_DC_HOST *dc_host;
11277 int i, now;
11278
11279 zabbix_log(LOG_LEVEL_DEBUG, "In %s() hostids:%d", __func__, hostids->values_num);
11280
11281 now = time(NULL);
11282
11283 WRLOCK_CACHE;
11284
11285 for (i = 0; i < hostids->values_num; i++)
11286 {
11287 if (NULL != (dc_host = zbx_hashset_search(&config->hosts, &hostids->values[i])))
11288 dc_host->availability_ts = now;
11289 }
11290
11291 UNLOCK_CACHE;
11292
11293 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
11294 }
11295
11296 /******************************************************************************
11297 * *
11298 * Function: dc_action_copy_conditions *
11299 * *
11300 * Purpose: copies configuration cache action conditions to the specified *
11301 * vector *
11302 * *
11303 * Parameters: dc_action - [IN] the source action *
11304 * conditions - [OUT] the conditions vector *
11305 * *
11306 ******************************************************************************/
dc_action_copy_conditions(const zbx_dc_action_t * dc_action,zbx_vector_ptr_t * conditions)11307 static void dc_action_copy_conditions(const zbx_dc_action_t *dc_action, zbx_vector_ptr_t *conditions)
11308 {
11309 int i;
11310 zbx_condition_t *condition;
11311 zbx_dc_action_condition_t *dc_condition;
11312
11313 zbx_vector_ptr_reserve(conditions, dc_action->conditions.values_num);
11314
11315 for (i = 0; i < dc_action->conditions.values_num; i++)
11316 {
11317 dc_condition = (zbx_dc_action_condition_t *)dc_action->conditions.values[i];
11318
11319 condition = (zbx_condition_t *)zbx_malloc(NULL, sizeof(zbx_condition_t));
11320
11321 condition->conditionid = dc_condition->conditionid;
11322 condition->actionid = dc_action->actionid;
11323 condition->conditiontype = dc_condition->conditiontype;
11324 condition->op = dc_condition->op;
11325 condition->value = zbx_strdup(NULL, dc_condition->value);
11326 condition->value2 = zbx_strdup(NULL, dc_condition->value2);
11327 zbx_vector_uint64_create(&condition->eventids);
11328
11329 zbx_vector_ptr_append(conditions, condition);
11330 }
11331 }
11332
11333 /******************************************************************************
11334 * *
11335 * Function: dc_action_eval_create *
11336 * *
11337 * Purpose: creates action evaluation data from configuration cache action *
11338 * *
11339 * Parameters: dc_action - [IN] the source action *
11340 * *
11341 * Return value: the action evaluation data *
11342 * *
11343 * Comments: The returned value must be freed with zbx_action_eval_free() *
11344 * function later. *
11345 * *
11346 ******************************************************************************/
dc_action_eval_create(const zbx_dc_action_t * dc_action)11347 static zbx_action_eval_t *dc_action_eval_create(const zbx_dc_action_t *dc_action)
11348 {
11349 zbx_action_eval_t *action;
11350
11351 action = (zbx_action_eval_t *)zbx_malloc(NULL, sizeof(zbx_action_eval_t));
11352
11353 action->actionid = dc_action->actionid;
11354 action->eventsource = dc_action->eventsource;
11355 action->evaltype = dc_action->evaltype;
11356 action->opflags = dc_action->opflags;
11357 action->formula = zbx_strdup(NULL, dc_action->formula);
11358 zbx_vector_ptr_create(&action->conditions);
11359
11360 dc_action_copy_conditions(dc_action, &action->conditions);
11361
11362 return action;
11363 }
11364
11365 /******************************************************************************
11366 * *
11367 * Function: zbx_dc_get_actions_eval *
11368 * *
11369 * Purpose: gets action evaluation data *
11370 * *
11371 * Parameters: actions - [OUT] the action evaluation data *
11372 * uniq_conditions - [OUT] unique conditions that actions *
11373 * point to (several sources) *
11374 * opflags - [IN] flags specifying which actions to get *
11375 * based on their operation classes *
11376 * (see ZBX_ACTION_OPCLASS_* defines) *
11377 * *
11378 * Comments: The returned actions and conditions must be freed with *
11379 * zbx_action_eval_free() function later. *
11380 * *
11381 ******************************************************************************/
zbx_dc_get_actions_eval(zbx_vector_ptr_t * actions,unsigned char opflags)11382 void zbx_dc_get_actions_eval(zbx_vector_ptr_t *actions, unsigned char opflags)
11383 {
11384 const zbx_dc_action_t *dc_action;
11385 zbx_hashset_iter_t iter;
11386
11387 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
11388
11389 RDLOCK_CACHE;
11390
11391 zbx_hashset_iter_reset(&config->actions, &iter);
11392
11393 while (NULL != (dc_action = (const zbx_dc_action_t *)zbx_hashset_iter_next(&iter)))
11394 {
11395 if (0 != (opflags & dc_action->opflags))
11396 zbx_vector_ptr_append(actions, dc_action_eval_create(dc_action));
11397 }
11398
11399 UNLOCK_CACHE;
11400
11401 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() actions:%d", __func__, actions->values_num);
11402 }
11403
11404 /******************************************************************************
11405 * *
11406 * Function: zbx_set_availability_update_ts *
11407 * *
11408 * Purpose: sets timestamp of the last availability update *
11409 * *
11410 * Parameter: ts - [IN] the last availability update timestamp *
11411 * *
11412 * Comments: This function is used only by proxies when preparing host *
11413 * availability data to be sent to server. *
11414 * *
11415 ******************************************************************************/
zbx_set_availability_diff_ts(int ts)11416 void zbx_set_availability_diff_ts(int ts)
11417 {
11418 /* this data can't be accessed simultaneously from multiple processes - locking is not necessary */
11419 config->availability_diff_ts = ts;
11420 }
11421
11422 /******************************************************************************
11423 * *
11424 * Function: corr_condition_clean *
11425 * *
11426 * Purpose: frees correlation condition *
11427 * *
11428 * Parameter: condition - [IN] the condition to free *
11429 * *
11430 ******************************************************************************/
corr_condition_clean(zbx_corr_condition_t * condition)11431 static void corr_condition_clean(zbx_corr_condition_t *condition)
11432 {
11433 switch (condition->type)
11434 {
11435 case ZBX_CORR_CONDITION_OLD_EVENT_TAG:
11436 /* break; is not missing here */
11437 case ZBX_CORR_CONDITION_NEW_EVENT_TAG:
11438 zbx_free(condition->data.tag.tag);
11439 break;
11440 case ZBX_CORR_CONDITION_EVENT_TAG_PAIR:
11441 zbx_free(condition->data.tag_pair.oldtag);
11442 zbx_free(condition->data.tag_pair.newtag);
11443 break;
11444 case ZBX_CORR_CONDITION_OLD_EVENT_TAG_VALUE:
11445 /* break; is not missing here */
11446 case ZBX_CORR_CONDITION_NEW_EVENT_TAG_VALUE:
11447 zbx_free(condition->data.tag_value.tag);
11448 zbx_free(condition->data.tag_value.value);
11449 break;
11450 }
11451 }
11452
11453 /******************************************************************************
11454 * *
11455 * Function: dc_correlation_free *
11456 * *
11457 * Purpose: frees global correlation rule *
11458 * *
11459 * Parameter: condition - [IN] the condition to free *
11460 * *
11461 ******************************************************************************/
dc_correlation_free(zbx_correlation_t * correlation)11462 static void dc_correlation_free(zbx_correlation_t *correlation)
11463 {
11464 zbx_free(correlation->name);
11465 zbx_free(correlation->formula);
11466
11467 zbx_vector_ptr_clear_ext(&correlation->operations, zbx_ptr_free);
11468 zbx_vector_ptr_destroy(&correlation->operations);
11469 zbx_vector_ptr_destroy(&correlation->conditions);
11470
11471 zbx_free(correlation);
11472 }
11473
11474 /******************************************************************************
11475 * *
11476 * Function: dc_corr_condition_copy *
11477 * *
11478 * Purpose: copies cached correlation condition to memory *
11479 * *
11480 * Parameter: dc_condition - [IN] the condition to copy *
11481 * condition - [OUT] the destination condition *
11482 * *
11483 * Return value: The cloned correlation condition. *
11484 * *
11485 ******************************************************************************/
dc_corr_condition_copy(const zbx_dc_corr_condition_t * dc_condition,zbx_corr_condition_t * condition)11486 static void dc_corr_condition_copy(const zbx_dc_corr_condition_t *dc_condition, zbx_corr_condition_t *condition)
11487 {
11488 condition->type = dc_condition->type;
11489
11490 switch (condition->type)
11491 {
11492 case ZBX_CORR_CONDITION_OLD_EVENT_TAG:
11493 /* break; is not missing here */
11494 case ZBX_CORR_CONDITION_NEW_EVENT_TAG:
11495 condition->data.tag.tag = zbx_strdup(NULL, dc_condition->data.tag.tag);
11496 break;
11497 case ZBX_CORR_CONDITION_EVENT_TAG_PAIR:
11498 condition->data.tag_pair.oldtag = zbx_strdup(NULL, dc_condition->data.tag_pair.oldtag);
11499 condition->data.tag_pair.newtag = zbx_strdup(NULL, dc_condition->data.tag_pair.newtag);
11500 break;
11501 case ZBX_CORR_CONDITION_OLD_EVENT_TAG_VALUE:
11502 /* break; is not missing here */
11503 case ZBX_CORR_CONDITION_NEW_EVENT_TAG_VALUE:
11504 condition->data.tag_value.tag = zbx_strdup(NULL, dc_condition->data.tag_value.tag);
11505 condition->data.tag_value.value = zbx_strdup(NULL, dc_condition->data.tag_value.value);
11506 condition->data.tag_value.op = dc_condition->data.tag_value.op;
11507 break;
11508 case ZBX_CORR_CONDITION_NEW_EVENT_HOSTGROUP:
11509 condition->data.group.groupid = dc_condition->data.group.groupid;
11510 condition->data.group.op = dc_condition->data.group.op;
11511 break;
11512 }
11513 }
11514
11515 /******************************************************************************
11516 * *
11517 * Function: zbx_dc_corr_operation_dup *
11518 * *
11519 * Purpose: clones cached correlation operation to memory *
11520 * *
11521 * Parameter: operation - [IN] the operation to clone *
11522 * *
11523 * Return value: The cloned correlation operation. *
11524 * *
11525 ******************************************************************************/
zbx_dc_corr_operation_dup(const zbx_dc_corr_operation_t * dc_operation)11526 static zbx_corr_operation_t *zbx_dc_corr_operation_dup(const zbx_dc_corr_operation_t *dc_operation)
11527 {
11528 zbx_corr_operation_t *operation;
11529
11530 operation = (zbx_corr_operation_t *)zbx_malloc(NULL, sizeof(zbx_corr_operation_t));
11531 operation->type = dc_operation->type;
11532
11533 return operation;
11534 }
11535
11536 /******************************************************************************
11537 * *
11538 * Function: dc_correlation_formula_dup *
11539 * *
11540 * Purpose: clones cached correlation formula, generating it if necessary *
11541 * *
11542 * Parameter: correlation - [IN] the correlation *
11543 * *
11544 * Return value: The cloned correlation formula. *
11545 * *
11546 ******************************************************************************/
dc_correlation_formula_dup(const zbx_dc_correlation_t * dc_correlation)11547 static char *dc_correlation_formula_dup(const zbx_dc_correlation_t *dc_correlation)
11548 {
11549 #define ZBX_OPERATION_TYPE_UNKNOWN 0
11550 #define ZBX_OPERATION_TYPE_OR 1
11551 #define ZBX_OPERATION_TYPE_AND 2
11552
11553 char *formula = NULL;
11554 const char *op = NULL;
11555 size_t formula_alloc = 0, formula_offset = 0;
11556 int i, last_type = -1, last_op = ZBX_OPERATION_TYPE_UNKNOWN;
11557 const zbx_dc_corr_condition_t *dc_condition;
11558 zbx_uint64_t last_id;
11559
11560 if (CONDITION_EVAL_TYPE_EXPRESSION == dc_correlation->evaltype || 0 == dc_correlation->conditions.values_num)
11561 return zbx_strdup(NULL, dc_correlation->formula);
11562
11563 dc_condition = (const zbx_dc_corr_condition_t *)dc_correlation->conditions.values[0];
11564
11565 switch (dc_correlation->evaltype)
11566 {
11567 case CONDITION_EVAL_TYPE_OR:
11568 op = " or";
11569 break;
11570 case CONDITION_EVAL_TYPE_AND:
11571 op = " and";
11572 break;
11573 }
11574
11575 if (NULL != op)
11576 {
11577 zbx_snprintf_alloc(&formula, &formula_alloc, &formula_offset, "{" ZBX_FS_UI64 "}",
11578 dc_condition->corr_conditionid);
11579
11580 for (i = 1; i < dc_correlation->conditions.values_num; i++)
11581 {
11582 dc_condition = (const zbx_dc_corr_condition_t *)dc_correlation->conditions.values[i];
11583
11584 zbx_strcpy_alloc(&formula, &formula_alloc, &formula_offset, op);
11585 zbx_snprintf_alloc(&formula, &formula_alloc, &formula_offset, " {" ZBX_FS_UI64 "}",
11586 dc_condition->corr_conditionid);
11587 }
11588
11589 return formula;
11590 }
11591
11592 last_id = dc_condition->corr_conditionid;
11593 last_type = dc_condition->type;
11594
11595 for (i = 1; i < dc_correlation->conditions.values_num; i++)
11596 {
11597 dc_condition = (const zbx_dc_corr_condition_t *)dc_correlation->conditions.values[i];
11598
11599 if (last_type == dc_condition->type)
11600 {
11601 if (last_op != ZBX_OPERATION_TYPE_OR)
11602 zbx_chrcpy_alloc(&formula, &formula_alloc, &formula_offset, '(');
11603
11604 zbx_snprintf_alloc(&formula, &formula_alloc, &formula_offset, "{" ZBX_FS_UI64 "} or ", last_id);
11605 last_op = ZBX_OPERATION_TYPE_OR;
11606 }
11607 else
11608 {
11609 zbx_snprintf_alloc(&formula, &formula_alloc, &formula_offset, "{" ZBX_FS_UI64 "}", last_id);
11610
11611 if (last_op == ZBX_OPERATION_TYPE_OR)
11612 zbx_chrcpy_alloc(&formula, &formula_alloc, &formula_offset, ')');
11613
11614 zbx_strcpy_alloc(&formula, &formula_alloc, &formula_offset, " and ");
11615
11616 last_op = ZBX_OPERATION_TYPE_AND;
11617 }
11618
11619 last_type = dc_condition->type;
11620 last_id = dc_condition->corr_conditionid;
11621 }
11622
11623 zbx_snprintf_alloc(&formula, &formula_alloc, &formula_offset, "{" ZBX_FS_UI64 "}", last_id);
11624
11625 if (last_op == ZBX_OPERATION_TYPE_OR)
11626 zbx_chrcpy_alloc(&formula, &formula_alloc, &formula_offset, ')');
11627
11628 return formula;
11629
11630 #undef ZBX_OPERATION_TYPE_UNKNOWN
11631 #undef ZBX_OPERATION_TYPE_OR
11632 #undef ZBX_OPERATION_TYPE_AND
11633 }
11634
zbx_dc_correlation_rules_init(zbx_correlation_rules_t * rules)11635 void zbx_dc_correlation_rules_init(zbx_correlation_rules_t *rules)
11636 {
11637 zbx_vector_ptr_create(&rules->correlations);
11638 zbx_hashset_create_ext(&rules->conditions, 0, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC,
11639 (zbx_clean_func_t)corr_condition_clean, ZBX_DEFAULT_MEM_MALLOC_FUNC,
11640 ZBX_DEFAULT_MEM_REALLOC_FUNC, ZBX_DEFAULT_MEM_FREE_FUNC);
11641
11642 rules->sync_ts = 0;
11643 }
11644
zbx_dc_correlation_rules_clean(zbx_correlation_rules_t * rules)11645 void zbx_dc_correlation_rules_clean(zbx_correlation_rules_t *rules)
11646 {
11647 zbx_vector_ptr_clear_ext(&rules->correlations, (zbx_clean_func_t)dc_correlation_free);
11648 zbx_hashset_clear(&rules->conditions);
11649 }
11650
zbx_dc_correlation_rules_free(zbx_correlation_rules_t * rules)11651 void zbx_dc_correlation_rules_free(zbx_correlation_rules_t *rules)
11652 {
11653 zbx_dc_correlation_rules_clean(rules);
11654 zbx_vector_ptr_destroy(&rules->correlations);
11655 zbx_hashset_destroy(&rules->conditions);
11656 }
11657
11658 /******************************************************************************
11659 * *
11660 * Function: zbx_dc_correlation_get_rules *
11661 * *
11662 * Purpose: gets correlation rules from configuration cache *
11663 * *
11664 * Parameter: rules - [IN/OUT] the correlation rules *
11665 * *
11666 ******************************************************************************/
zbx_dc_correlation_rules_get(zbx_correlation_rules_t * rules)11667 void zbx_dc_correlation_rules_get(zbx_correlation_rules_t *rules)
11668 {
11669 int i;
11670 zbx_hashset_iter_t iter;
11671 const zbx_dc_correlation_t *dc_correlation;
11672 const zbx_dc_corr_condition_t *dc_condition;
11673 zbx_correlation_t *correlation;
11674 zbx_corr_condition_t *condition, condition_local;
11675
11676 RDLOCK_CACHE;
11677
11678 /* The correlation rules are refreshed only if the sync timestamp */
11679 /* does not match current configuration cache sync timestamp. This */
11680 /* allows to locally cache the correlation rules. */
11681 if (config->sync_ts == rules->sync_ts)
11682 {
11683 UNLOCK_CACHE;
11684 return;
11685 }
11686
11687 zbx_dc_correlation_rules_clean(rules);
11688
11689 zbx_hashset_iter_reset(&config->correlations, &iter);
11690 while (NULL != (dc_correlation = (const zbx_dc_correlation_t *)zbx_hashset_iter_next(&iter)))
11691 {
11692 correlation = (zbx_correlation_t *)zbx_malloc(NULL, sizeof(zbx_correlation_t));
11693 correlation->correlationid = dc_correlation->correlationid;
11694 correlation->evaltype = dc_correlation->evaltype;
11695 correlation->name = zbx_strdup(NULL, dc_correlation->name);
11696 correlation->formula = dc_correlation_formula_dup(dc_correlation);
11697 zbx_vector_ptr_create(&correlation->conditions);
11698 zbx_vector_ptr_create(&correlation->operations);
11699
11700 for (i = 0; i < dc_correlation->conditions.values_num; i++)
11701 {
11702 dc_condition = (const zbx_dc_corr_condition_t *)dc_correlation->conditions.values[i];
11703 condition_local.corr_conditionid = dc_condition->corr_conditionid;
11704 condition = (zbx_corr_condition_t *)zbx_hashset_insert(&rules->conditions, &condition_local, sizeof(condition_local));
11705 dc_corr_condition_copy(dc_condition, condition);
11706 zbx_vector_ptr_append(&correlation->conditions, condition);
11707 }
11708
11709 for (i = 0; i < dc_correlation->operations.values_num; i++)
11710 {
11711 zbx_vector_ptr_append(&correlation->operations,
11712 zbx_dc_corr_operation_dup((const zbx_dc_corr_operation_t *)dc_correlation->operations.values[i]));
11713 }
11714
11715 zbx_vector_ptr_append(&rules->correlations, correlation);
11716 }
11717
11718 rules->sync_ts = config->sync_ts;
11719
11720 UNLOCK_CACHE;
11721
11722 zbx_vector_ptr_sort(&rules->correlations, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
11723 }
11724
11725 /******************************************************************************
11726 * *
11727 * Function: dc_hostgroup_cache_nested_groupids *
11728 * *
11729 * Purpose: cache nested group identifiers *
11730 * *
11731 ******************************************************************************/
dc_hostgroup_cache_nested_groupids(zbx_dc_hostgroup_t * parent_group)11732 void dc_hostgroup_cache_nested_groupids(zbx_dc_hostgroup_t *parent_group)
11733 {
11734 zbx_dc_hostgroup_t *group;
11735
11736 if (0 == (parent_group->flags & ZBX_DC_HOSTGROUP_FLAGS_NESTED_GROUPIDS))
11737 {
11738 int index, len;
11739
11740 zbx_vector_uint64_create_ext(&parent_group->nested_groupids, __config_mem_malloc_func,
11741 __config_mem_realloc_func, __config_mem_free_func);
11742
11743 index = zbx_vector_ptr_bsearch(&config->hostgroups_name, parent_group, dc_compare_hgroups);
11744 len = strlen(parent_group->name);
11745
11746 while (++index < config->hostgroups_name.values_num)
11747 {
11748 group = (zbx_dc_hostgroup_t *)config->hostgroups_name.values[index];
11749
11750 if (0 != strncmp(group->name, parent_group->name, len))
11751 break;
11752
11753 if ('\0' == group->name[len] || '/' == group->name[len])
11754 zbx_vector_uint64_append(&parent_group->nested_groupids, group->groupid);
11755 }
11756
11757 parent_group->flags |= ZBX_DC_HOSTGROUP_FLAGS_NESTED_GROUPIDS;
11758 }
11759 }
11760
11761 /******************************************************************************
11762 * *
11763 * Function: dc_maintenance_precache_nested_groups *
11764 * *
11765 * Purpose: pre-caches nested groups for groups used in running maintenances *
11766 * *
11767 ******************************************************************************/
dc_maintenance_precache_nested_groups(void)11768 static void dc_maintenance_precache_nested_groups(void)
11769 {
11770 zbx_hashset_iter_t iter;
11771 zbx_dc_maintenance_t *maintenance;
11772 zbx_vector_uint64_t groupids;
11773 int i;
11774 zbx_dc_hostgroup_t *group;
11775
11776 if (0 == config->maintenances.num_data)
11777 return;
11778
11779 zbx_vector_uint64_create(&groupids);
11780 zbx_hashset_iter_reset(&config->maintenances, &iter);
11781 while (NULL != (maintenance = (zbx_dc_maintenance_t *)zbx_hashset_iter_next(&iter)))
11782 {
11783 if (ZBX_MAINTENANCE_RUNNING != maintenance->state)
11784 continue;
11785
11786 zbx_vector_uint64_append_array(&groupids, maintenance->groupids.values,
11787 maintenance->groupids.values_num);
11788 }
11789
11790 zbx_vector_uint64_sort(&groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
11791 zbx_vector_uint64_uniq(&groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
11792
11793 for (i = 0; i < groupids.values_num; i++)
11794 {
11795 if (NULL != (group = (zbx_dc_hostgroup_t *)zbx_hashset_search(&config->hostgroups,
11796 &groupids.values[i])))
11797 {
11798 dc_hostgroup_cache_nested_groupids(group);
11799 }
11800 }
11801
11802 zbx_vector_uint64_destroy(&groupids);
11803 }
11804
11805 /******************************************************************************
11806 * *
11807 * Function: dc_get_nested_hostgroupids *
11808 * *
11809 * Purpose: gets nested group ids for the specified host group *
11810 * (including the target group id) *
11811 * *
11812 * Parameter: groupid - [IN] the parent group identifier *
11813 * nested_groupids - [OUT] the nested + parent group ids *
11814 * *
11815 ******************************************************************************/
dc_get_nested_hostgroupids(zbx_uint64_t groupid,zbx_vector_uint64_t * nested_groupids)11816 void dc_get_nested_hostgroupids(zbx_uint64_t groupid, zbx_vector_uint64_t *nested_groupids)
11817 {
11818 zbx_dc_hostgroup_t *parent_group;
11819
11820 zbx_vector_uint64_append(nested_groupids, groupid);
11821
11822 /* The target group id will not be found in the configuration cache if target group was removed */
11823 /* between call to this function and the configuration cache look-up below. The target group id */
11824 /* is nevertheless returned so that the SELECT statements of the callers work even if no group */
11825 /* was found. */
11826
11827 if (NULL != (parent_group = (zbx_dc_hostgroup_t *)zbx_hashset_search(&config->hostgroups, &groupid)))
11828 {
11829 dc_hostgroup_cache_nested_groupids(parent_group);
11830
11831 if (0 != parent_group->nested_groupids.values_num)
11832 {
11833 zbx_vector_uint64_append_array(nested_groupids, parent_group->nested_groupids.values,
11834 parent_group->nested_groupids.values_num);
11835 }
11836 }
11837 }
11838
11839 /******************************************************************************
11840 * *
11841 * Function: zbx_dc_get_nested_hostgroupids *
11842 * *
11843 * Purpose: gets nested group ids for the specified host groups *
11844 * *
11845 * Parameter: groupids - [IN] the parent group identifiers *
11846 * groupids_num - [IN] the number of parent groups *
11847 * nested_groupids - [OUT] the nested + parent group ids *
11848 * *
11849 ******************************************************************************/
zbx_dc_get_nested_hostgroupids(zbx_uint64_t * groupids,int groupids_num,zbx_vector_uint64_t * nested_groupids)11850 void zbx_dc_get_nested_hostgroupids(zbx_uint64_t *groupids, int groupids_num, zbx_vector_uint64_t *nested_groupids)
11851 {
11852 int i;
11853
11854 WRLOCK_CACHE;
11855
11856 for (i = 0; i < groupids_num; i++)
11857 dc_get_nested_hostgroupids(groupids[i], nested_groupids);
11858
11859 UNLOCK_CACHE;
11860
11861 zbx_vector_uint64_sort(nested_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
11862 zbx_vector_uint64_uniq(nested_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
11863 }
11864
11865 /******************************************************************************
11866 * *
11867 * Function: zbx_dc_get_nested_hostgroupids_by_names *
11868 * *
11869 * Purpose: gets nested group ids for the specified host groups *
11870 * *
11871 * Parameter: groups - [IN] the parent group names *
11872 * nested_groupids - [OUT] the nested + parent group ids *
11873 * *
11874 ******************************************************************************/
zbx_dc_get_nested_hostgroupids_by_names(zbx_vector_str_t * groups,zbx_vector_uint64_t * nested_groupids)11875 void zbx_dc_get_nested_hostgroupids_by_names(zbx_vector_str_t *groups, zbx_vector_uint64_t *nested_groupids)
11876 {
11877 int i, index;
11878
11879 WRLOCK_CACHE;
11880
11881 for (i = 0; i < groups->values_num; i++)
11882 {
11883 zbx_dc_hostgroup_t group_local, *group;
11884
11885 group_local.name = groups->values[i];
11886
11887 if (FAIL != (index = zbx_vector_ptr_bsearch(&config->hostgroups_name, &group_local,
11888 dc_compare_hgroups)))
11889 {
11890 group = (zbx_dc_hostgroup_t *)config->hostgroups_name.values[index];
11891 dc_get_nested_hostgroupids(group->groupid, nested_groupids);
11892 }
11893 }
11894
11895 UNLOCK_CACHE;
11896
11897 zbx_vector_uint64_sort(nested_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
11898 zbx_vector_uint64_uniq(nested_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
11899 }
11900
11901 /******************************************************************************
11902 * *
11903 * Function: zbx_dc_get_active_proxy_by_name *
11904 * *
11905 * Purpose: gets active proxy data by its name from configuration cache *
11906 * *
11907 * Parameters: *
11908 * name - [IN] the proxy name *
11909 * proxy - [OUT] the proxy data *
11910 * error - [OUT] error message *
11911 * *
11912 * Return value: *
11913 * SUCCEED - proxy data were retrieved successfully *
11914 * FAIL - failed to retrieve proxy data, error message is set *
11915 * *
11916 ******************************************************************************/
zbx_dc_get_active_proxy_by_name(const char * name,DC_PROXY * proxy,char ** error)11917 int zbx_dc_get_active_proxy_by_name(const char *name, DC_PROXY *proxy, char **error)
11918 {
11919 int ret = FAIL;
11920 const ZBX_DC_HOST *dc_host;
11921 const ZBX_DC_PROXY *dc_proxy;
11922
11923 RDLOCK_CACHE;
11924
11925 if (NULL == (dc_host = DCfind_proxy(name)))
11926 {
11927 *error = zbx_dsprintf(*error, "proxy \"%s\" not found", name);
11928 goto out;
11929 }
11930
11931 if (HOST_STATUS_PROXY_ACTIVE != dc_host->status)
11932 {
11933 *error = zbx_dsprintf(*error, "proxy \"%s\" is configured for passive mode", name);
11934 goto out;
11935 }
11936
11937 if (NULL == (dc_proxy = (const ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &dc_host->hostid)))
11938 {
11939 *error = zbx_dsprintf(*error, "proxy \"%s\" not found in configuration cache", name);
11940 goto out;
11941 }
11942
11943 DCget_proxy(proxy, dc_proxy);
11944 ret = SUCCEED;
11945 out:
11946 UNLOCK_CACHE;
11947
11948 return ret;
11949 }
11950
11951 /******************************************************************************
11952 * *
11953 * Function: zbx_dc_items_update_nextcheck *
11954 * *
11955 * Purpose: updates item nextcheck values in configuration cache *
11956 * *
11957 * Parameters: items - [IN] the items to update *
11958 * values - [IN] the items values containing new properties *
11959 * errcodes - [IN] item error codes. Update only items with *
11960 * SUCCEED code *
11961 * values_num - [IN] the number of elements in items,values and *
11962 * errcodes arrays *
11963 * *
11964 ******************************************************************************/
zbx_dc_items_update_nextcheck(DC_ITEM * items,zbx_agent_value_t * values,int * errcodes,size_t values_num)11965 void zbx_dc_items_update_nextcheck(DC_ITEM *items, zbx_agent_value_t *values, int *errcodes, size_t values_num)
11966 {
11967 size_t i;
11968 ZBX_DC_ITEM *dc_item;
11969 ZBX_DC_HOST *dc_host;
11970
11971 RDLOCK_CACHE;
11972
11973 for (i = 0; i < values_num; i++)
11974 {
11975 if (FAIL == errcodes[i])
11976 continue;
11977
11978 /* update nextcheck for items that are counted in queue for monitoring purposes */
11979 if (FAIL == zbx_is_counted_in_item_queue(items[i].type, items[i].key_orig))
11980 continue;
11981
11982 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &items[i].itemid)))
11983 continue;
11984
11985 if (ITEM_STATUS_ACTIVE != dc_item->status)
11986 continue;
11987
11988 if (NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
11989 continue;
11990
11991 if (HOST_STATUS_MONITORED != dc_host->status)
11992 continue;
11993
11994 if (ZBX_LOC_NOWHERE != dc_item->location)
11995 continue;
11996
11997 DCitem_nextcheck_update(dc_item, dc_host, items[i].state, ZBX_ITEM_COLLECTED, values[i].ts.sec, NULL);
11998 }
11999
12000 UNLOCK_CACHE;
12001 }
12002
12003 /******************************************************************************
12004 * *
12005 * Function: zbx_dc_get_host_interfaces *
12006 * *
12007 * Purpose: get data of all network interfaces for a host in configuration *
12008 * cache *
12009 * *
12010 * Parameter: hostid - [IN] the host identifier *
12011 * interfaces - [OUT] array with interface data *
12012 * n - [OUT] number of allocated 'interfaces' elements *
12013 * *
12014 * Return value: SUCCEED - interface data retrieved successfully *
12015 * FAIL - host not found *
12016 * *
12017 * Comments: if host is found but has no interfaces (should not happen) this *
12018 * function sets 'n' to 0 and no memory is allocated for *
12019 * 'interfaces'. It is a caller responsibility to deallocate *
12020 * memory of 'interfaces' and its components. *
12021 * *
12022 ******************************************************************************/
zbx_dc_get_host_interfaces(zbx_uint64_t hostid,DC_INTERFACE2 ** interfaces,int * n)12023 int zbx_dc_get_host_interfaces(zbx_uint64_t hostid, DC_INTERFACE2 **interfaces, int *n)
12024 {
12025 const ZBX_DC_HOST *host;
12026 int i, ret = FAIL;
12027
12028 if (0 == hostid)
12029 return FAIL;
12030
12031 RDLOCK_CACHE;
12032
12033 /* find host entry in 'config->hosts' hashset */
12034
12035 if (NULL == (host = (const ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &hostid)))
12036 goto unlock;
12037
12038 /* allocate memory for results */
12039
12040 if (0 < (*n = host->interfaces_v.values_num))
12041 *interfaces = (DC_INTERFACE2 *)zbx_malloc(NULL, sizeof(DC_INTERFACE2) * (size_t)*n);
12042
12043 /* copy data about all host interfaces */
12044
12045 for (i = 0; i < *n; i++)
12046 {
12047 const ZBX_DC_INTERFACE *src = (const ZBX_DC_INTERFACE *)host->interfaces_v.values[i];
12048 DC_INTERFACE2 *dst = *interfaces + i;
12049
12050 dst->interfaceid = src->interfaceid;
12051 dst->type = src->type;
12052 dst->main = src->main;
12053 dst->useip = src->useip;
12054 strscpy(dst->ip_orig, src->ip);
12055 strscpy(dst->dns_orig, src->dns);
12056 strscpy(dst->port_orig, src->port);
12057 dst->addr = (1 == src->useip ? dst->ip_orig : dst->dns_orig);
12058
12059 if (INTERFACE_TYPE_SNMP == dst->type)
12060 {
12061 ZBX_DC_SNMPINTERFACE *snmp;
12062
12063 if (NULL == (snmp = (ZBX_DC_SNMPINTERFACE *)zbx_hashset_search(&config->interfaces_snmp,
12064 &dst->interfaceid)))
12065 {
12066 zbx_free(*interfaces);
12067 goto unlock;
12068 }
12069
12070 dst->bulk = snmp->bulk;
12071 dst->snmp_version= snmp->version;
12072 }
12073 }
12074
12075 ret = SUCCEED;
12076 unlock:
12077 UNLOCK_CACHE;
12078
12079 return ret;
12080 }
12081
12082 /******************************************************************************
12083 * *
12084 * Function: DCconfig_items_apply_changes *
12085 * *
12086 * Purpose: apply item state, error, mtime, lastlogsize changes to *
12087 * configuration cache *
12088 * *
12089 ******************************************************************************/
DCconfig_items_apply_changes(const zbx_vector_ptr_t * item_diff)12090 void DCconfig_items_apply_changes(const zbx_vector_ptr_t *item_diff)
12091 {
12092 int i;
12093 const zbx_item_diff_t *diff;
12094 ZBX_DC_ITEM *dc_item;
12095
12096 if (0 == item_diff->values_num)
12097 return;
12098
12099 WRLOCK_CACHE;
12100
12101 for (i = 0; i < item_diff->values_num; i++)
12102 {
12103 diff = (const zbx_item_diff_t *)item_diff->values[i];
12104
12105 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &diff->itemid)))
12106 continue;
12107
12108 if (0 != (ZBX_FLAGS_ITEM_DIFF_UPDATE_LASTLOGSIZE & diff->flags))
12109 dc_item->lastlogsize = diff->lastlogsize;
12110
12111 if (0 != (ZBX_FLAGS_ITEM_DIFF_UPDATE_MTIME & diff->flags))
12112 dc_item->mtime = diff->mtime;
12113
12114 if (0 != (ZBX_FLAGS_ITEM_DIFF_UPDATE_ERROR & diff->flags))
12115 DCstrpool_replace(1, &dc_item->error, diff->error);
12116
12117 if (0 != (ZBX_FLAGS_ITEM_DIFF_UPDATE_STATE & diff->flags))
12118 dc_item->state = diff->state;
12119
12120 if (0 != (ZBX_FLAGS_ITEM_DIFF_UPDATE_LASTCLOCK & diff->flags))
12121 dc_item->lastclock = diff->lastclock;
12122 }
12123
12124 UNLOCK_CACHE;
12125 }
12126
12127 /******************************************************************************
12128 * *
12129 * Function: DCconfig_update_inventory_values *
12130 * *
12131 * Purpose: update automatic inventory in configuration cache *
12132 * *
12133 ******************************************************************************/
DCconfig_update_inventory_values(const zbx_vector_ptr_t * inventory_values)12134 void DCconfig_update_inventory_values(const zbx_vector_ptr_t *inventory_values)
12135 {
12136 ZBX_DC_HOST_INVENTORY *host_inventory = NULL;
12137 int i;
12138
12139 WRLOCK_CACHE;
12140
12141 for (i = 0; i < inventory_values->values_num; i++)
12142 {
12143 const zbx_inventory_value_t *inventory_value = (zbx_inventory_value_t *)inventory_values->values[i];
12144 const char **value;
12145
12146 if (NULL == host_inventory || inventory_value->hostid != host_inventory->hostid)
12147 {
12148 host_inventory = (ZBX_DC_HOST_INVENTORY *)zbx_hashset_search(&config->host_inventories_auto, &inventory_value->hostid);
12149
12150 if (NULL == host_inventory)
12151 continue;
12152 }
12153
12154 value = &host_inventory->values[inventory_value->idx];
12155
12156 DCstrpool_replace((NULL != *value ? 1 : 0), value, inventory_value->value);
12157 }
12158
12159 UNLOCK_CACHE;
12160 }
12161
12162 /******************************************************************************
12163 * *
12164 * Function: dc_get_host_inventory_value_by_hostid *
12165 * *
12166 * Purpose: find inventory value in automatically populated cache, if not *
12167 * found then look in main inventory cache *
12168 * *
12169 * Comments: This function must be called inside configuration cache read *
12170 * (or write) lock. *
12171 * *
12172 ******************************************************************************/
dc_get_host_inventory_value_by_hostid(zbx_uint64_t hostid,char ** replace_to,int value_idx)12173 static int dc_get_host_inventory_value_by_hostid(zbx_uint64_t hostid, char **replace_to, int value_idx)
12174 {
12175 const ZBX_DC_HOST_INVENTORY *dc_inventory;
12176
12177 if (NULL != (dc_inventory = (const ZBX_DC_HOST_INVENTORY *)zbx_hashset_search(&config->host_inventories_auto,
12178 &hostid)) && NULL != dc_inventory->values[value_idx])
12179 {
12180 *replace_to = zbx_strdup(*replace_to, dc_inventory->values[value_idx]);
12181 return SUCCEED;
12182 }
12183
12184 if (NULL != (dc_inventory = (const ZBX_DC_HOST_INVENTORY *)zbx_hashset_search(&config->host_inventories,
12185 &hostid)))
12186 {
12187 *replace_to = zbx_strdup(*replace_to, dc_inventory->values[value_idx]);
12188 return SUCCEED;
12189 }
12190
12191 return FAIL;
12192 }
12193
12194 /******************************************************************************
12195 * *
12196 * Function: DCget_host_inventory_value_by_itemid *
12197 * *
12198 * Purpose: find inventory value in automatically populated cache, if not *
12199 * found then look in main inventory cache *
12200 * *
12201 ******************************************************************************/
DCget_host_inventory_value_by_itemid(zbx_uint64_t itemid,char ** replace_to,int value_idx)12202 int DCget_host_inventory_value_by_itemid(zbx_uint64_t itemid, char **replace_to, int value_idx)
12203 {
12204 const ZBX_DC_ITEM *dc_item;
12205 int ret = FAIL;
12206
12207 RDLOCK_CACHE;
12208
12209 if (NULL != (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemid)))
12210 ret = dc_get_host_inventory_value_by_hostid(dc_item->hostid, replace_to, value_idx);
12211
12212 UNLOCK_CACHE;
12213
12214 return ret;
12215 }
12216
12217 /******************************************************************************
12218 * *
12219 * Function: DCget_host_inventory_value_by_hostid *
12220 * *
12221 * Purpose: find inventory value in automatically populated cache, if not *
12222 * found then look in main inventory cache *
12223 * *
12224 ******************************************************************************/
DCget_host_inventory_value_by_hostid(zbx_uint64_t hostid,char ** replace_to,int value_idx)12225 int DCget_host_inventory_value_by_hostid(zbx_uint64_t hostid, char **replace_to, int value_idx)
12226 {
12227 int ret;
12228
12229 RDLOCK_CACHE;
12230
12231 ret = dc_get_host_inventory_value_by_hostid(hostid, replace_to, value_idx);
12232
12233 UNLOCK_CACHE;
12234
12235 return ret;
12236 }
12237
12238 /******************************************************************************
12239 * *
12240 * Function: zbx_dc_get_trigger_dependencies *
12241 * *
12242 * Purpose: checks/returns trigger dependencies for a set of triggers *
12243 * *
12244 * Parameter: triggerids - [IN] the currently processing trigger ids *
12245 * deps - [OUT] list of dependency check results for failed *
12246 * or unresolved dependencies *
12247 * *
12248 * Comments: This function returns list of zbx_trigger_dep_t structures *
12249 * for failed or unresolved dependency checks. *
12250 * Dependency check is failed if any of the master triggers that *
12251 * are not being processed in this batch (present in triggerids *
12252 * vector) has a problem value. *
12253 * Dependency check is unresolved if a master trigger is being *
12254 * processed in this batch (present in triggerids vector) and no *
12255 * other master triggers have problem value. *
12256 * Dependency check is successful if all master triggers (if any) *
12257 * have OK value and are not being processed in this batch. *
12258 * *
12259 ******************************************************************************/
zbx_dc_get_trigger_dependencies(const zbx_vector_uint64_t * triggerids,zbx_vector_ptr_t * deps)12260 void zbx_dc_get_trigger_dependencies(const zbx_vector_uint64_t *triggerids, zbx_vector_ptr_t *deps)
12261 {
12262 int i, ret;
12263 const ZBX_DC_TRIGGER_DEPLIST *trigdep;
12264 zbx_vector_uint64_t masterids;
12265 zbx_trigger_dep_t *dep;
12266
12267 zbx_vector_uint64_create(&masterids);
12268 zbx_vector_uint64_reserve(&masterids, 64);
12269
12270 RDLOCK_CACHE;
12271
12272 for (i = 0; i < triggerids->values_num; i++)
12273 {
12274 if (NULL == (trigdep = (ZBX_DC_TRIGGER_DEPLIST *)zbx_hashset_search(&config->trigdeps, &triggerids->values[i])))
12275 continue;
12276
12277 if (FAIL == (ret = DCconfig_check_trigger_dependencies_rec(trigdep, 0, triggerids, &masterids)) ||
12278 0 != masterids.values_num)
12279 {
12280 dep = (zbx_trigger_dep_t *)zbx_malloc(NULL, sizeof(zbx_trigger_dep_t));
12281 dep->triggerid = triggerids->values[i];
12282 zbx_vector_uint64_create(&dep->masterids);
12283
12284 if (SUCCEED == ret)
12285 {
12286 dep->status = ZBX_TRIGGER_DEPENDENCY_UNRESOLVED;
12287 zbx_vector_uint64_append_array(&dep->masterids, masterids.values, masterids.values_num);
12288 }
12289 else
12290 dep->status = ZBX_TRIGGER_DEPENDENCY_FAIL;
12291
12292 zbx_vector_ptr_append(deps, dep);
12293 }
12294
12295 zbx_vector_uint64_clear(&masterids);
12296 }
12297
12298 UNLOCK_CACHE;
12299
12300 zbx_vector_uint64_destroy(&masterids);
12301 }
12302
12303 /******************************************************************************
12304 * *
12305 * Function: zbx_dc_reschedule_items *
12306 * *
12307 * Purpose: reschedules items that are processed by the target daemon *
12308 * *
12309 * Parameter: itemids - [IN] the item identifiers *
12310 * nextcheck - [IN] the schedueld time *
12311 * proxy_hostids - [OUT] the proxy_hostids of the given itemids *
12312 * (optional, can be NULL) *
12313 * *
12314 * Comments: On server this function reschedules items monitored by server. *
12315 * On proxy only items monitored by the proxy is accessible, so *
12316 * all items can be safely rescheduled. *
12317 * *
12318 ******************************************************************************/
zbx_dc_reschedule_items(const zbx_vector_uint64_t * itemids,int nextcheck,zbx_uint64_t * proxy_hostids)12319 void zbx_dc_reschedule_items(const zbx_vector_uint64_t *itemids, int nextcheck, zbx_uint64_t *proxy_hostids)
12320 {
12321 int i;
12322 ZBX_DC_ITEM *dc_item;
12323 ZBX_DC_HOST *dc_host;
12324 zbx_uint64_t proxy_hostid;
12325
12326 WRLOCK_CACHE;
12327
12328 for (i = 0; i < itemids->values_num; i++)
12329 {
12330 if (NULL == (dc_item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemids->values[i])) ||
12331 NULL == (dc_host = (ZBX_DC_HOST *)zbx_hashset_search(&config->hosts, &dc_item->hostid)))
12332 {
12333 zabbix_log(LOG_LEVEL_WARNING, "cannot perform check now for itemid [" ZBX_FS_UI64 "]"
12334 ": item is not in cache", itemids->values[i]);
12335
12336 proxy_hostid = 0;
12337 }
12338 else if (0 == dc_item->schedulable)
12339 {
12340 zabbix_log(LOG_LEVEL_WARNING, "cannot perform check now for item \"%s\" on host \"%s\""
12341 ": item configuration error", dc_item->key, dc_host->host);
12342
12343 proxy_hostid = 0;
12344 }
12345 else if (0 == (proxy_hostid = dc_host->proxy_hostid) ||
12346 SUCCEED == is_item_processed_by_server(dc_item->type, dc_item->key))
12347 {
12348 dc_requeue_item_at(dc_item, dc_host, nextcheck);
12349 proxy_hostid = 0;
12350 }
12351
12352 if (NULL != proxy_hostids)
12353 proxy_hostids[i] = proxy_hostid;
12354 }
12355
12356 UNLOCK_CACHE;
12357 }
12358
12359 /******************************************************************************
12360 * *
12361 * Function: zbx_dc_proxy_update_nodata *
12362 * *
12363 * Purpose: stop suppress mode of the nodata() trigger *
12364 * *
12365 * Parameter: subscriptions - [IN] the array of trigger id and time of values *
12366 * *
12367 ******************************************************************************/
zbx_dc_proxy_update_nodata(zbx_vector_uint64_pair_t * subscriptions)12368 void zbx_dc_proxy_update_nodata(zbx_vector_uint64_pair_t *subscriptions)
12369 {
12370 ZBX_DC_PROXY *proxy = NULL;
12371 int i;
12372 zbx_uint64_pair_t p;
12373
12374 WRLOCK_CACHE;
12375
12376 for (i = 0; i < subscriptions->values_num; i++)
12377 {
12378 p = subscriptions->values[i];
12379
12380 if ((NULL == proxy || p.first != proxy->hostid) &&
12381 NULL == (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &p.first)))
12382 {
12383 continue;
12384 }
12385
12386 if (0 == (proxy->nodata_win.flags & ZBX_PROXY_SUPPRESS_ACTIVE))
12387 continue;
12388
12389 if (0 != (proxy->nodata_win.flags & ZBX_PROXY_SUPPRESS_MORE) &&
12390 (int)p.second > proxy->nodata_win.period_end)
12391 {
12392 continue;
12393 }
12394
12395 proxy->nodata_win.values_num --;
12396
12397 if (0 < proxy->nodata_win.values_num || 0 != (proxy->nodata_win.flags & ZBX_PROXY_SUPPRESS_MORE))
12398 continue;
12399
12400 proxy->nodata_win.flags = ZBX_PROXY_SUPPRESS_DISABLE;
12401 proxy->nodata_win.period_end = 0;
12402 proxy->nodata_win.values_num = 0;
12403 }
12404
12405 UNLOCK_CACHE;
12406 }
12407
12408 /******************************************************************************
12409 * *
12410 * Function: zbx_dc_update_proxy *
12411 * *
12412 * Purpose: updates changed proxy data in configuration cache and updates *
12413 * diff flags to reflect the updated data *
12414 * *
12415 * Parameter: diff - [IN/OUT] the properties to update *
12416 * *
12417 ******************************************************************************/
zbx_dc_update_proxy(zbx_proxy_diff_t * diff)12418 void zbx_dc_update_proxy(zbx_proxy_diff_t *diff)
12419 {
12420 ZBX_DC_PROXY *proxy;
12421
12422 WRLOCK_CACHE;
12423
12424 if (diff->lastaccess < config->proxy_lastaccess_ts)
12425 diff->lastaccess = config->proxy_lastaccess_ts;
12426
12427 if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &diff->hostid)))
12428 {
12429 if (0 != (diff->flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_LASTACCESS))
12430 {
12431 int lost = 0; /* communication lost */
12432
12433 if (0 != (diff->flags &
12434 (ZBX_FLAGS_PROXY_DIFF_UPDATE_HEARTBEAT | ZBX_FLAGS_PROXY_DIFF_UPDATE_CONFIG)))
12435 {
12436 int delay = diff->lastaccess - proxy->lastaccess;
12437
12438 if (NET_DELAY_MAX < delay)
12439 lost = 1;
12440 }
12441
12442 if (0 == lost && proxy->lastaccess != diff->lastaccess)
12443 proxy->lastaccess = diff->lastaccess;
12444
12445 /* proxy last access in database is updated separately in */
12446 /* every ZBX_PROXY_LASTACCESS_UPDATE_FREQUENCY seconds */
12447 diff->flags &= (~ZBX_FLAGS_PROXY_DIFF_UPDATE_LASTACCESS);
12448 }
12449
12450 if (0 != (diff->flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_VERSION))
12451 {
12452 if (proxy->version != diff->version)
12453 proxy->version = diff->version;
12454 else
12455 diff->flags &= (~ZBX_FLAGS_PROXY_DIFF_UPDATE_VERSION);
12456 }
12457
12458 if (0 != (diff->flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_COMPRESS))
12459 {
12460 if (proxy->auto_compress == diff->compress)
12461 diff->flags &= (~ZBX_FLAGS_PROXY_DIFF_UPDATE_COMPRESS);
12462 proxy->auto_compress = diff->compress;
12463 }
12464 if (0 != (diff->flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_LASTERROR))
12465 {
12466 proxy->last_version_error_time = diff->last_version_error_time;
12467 diff->flags &= (~ZBX_FLAGS_PROXY_DIFF_UPDATE_LASTERROR);
12468 }
12469
12470 if (0 != (diff->flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_PROXYDELAY))
12471 {
12472 proxy->proxy_delay = diff->proxy_delay;
12473 diff->flags &= (~ZBX_FLAGS_PROXY_DIFF_UPDATE_PROXYDELAY);
12474 }
12475
12476 if (0 != (diff->flags & ZBX_FLAGS_PROXY_DIFF_UPDATE_SUPPRESS_WIN))
12477 {
12478 zbx_proxy_suppress_t *ps_win = &proxy->nodata_win, *ds_win = &diff->nodata_win;
12479
12480 if ((ps_win->flags & ZBX_PROXY_SUPPRESS_ACTIVE) != (ds_win->flags & ZBX_PROXY_SUPPRESS_ACTIVE))
12481 {
12482 ps_win->period_end = ds_win->period_end;
12483 }
12484
12485 if (ps_win->flags != ds_win->flags)
12486 ps_win->flags = ds_win->flags;
12487
12488 if (0 > ps_win->values_num) /* some new values was processed faster than old */
12489 ps_win->values_num = 0; /* we will suppress more */
12490
12491 ps_win->values_num += ds_win->values_num;
12492 diff->flags &= (~ZBX_FLAGS_PROXY_DIFF_UPDATE_SUPPRESS_WIN);
12493 }
12494 }
12495
12496 UNLOCK_CACHE;
12497 }
12498
12499 /******************************************************************************
12500 * *
12501 * Function: zbx_dc_get_proxy_lastaccess *
12502 * *
12503 * Purpose: returns proxy lastaccess changes since last lastaccess request *
12504 * *
12505 * Parameter: lastaccess - [OUT] last access updates for proxies that need *
12506 * to be synced with database, sorted by *
12507 * hostid *
12508 * *
12509 ******************************************************************************/
zbx_dc_get_proxy_lastaccess(zbx_vector_uint64_pair_t * lastaccess)12510 void zbx_dc_get_proxy_lastaccess(zbx_vector_uint64_pair_t *lastaccess)
12511 {
12512 ZBX_DC_PROXY *proxy;
12513 int now;
12514
12515 if (ZBX_PROXY_LASTACCESS_UPDATE_FREQUENCY < (now = time(NULL)) - config->proxy_lastaccess_ts)
12516 {
12517 zbx_hashset_iter_t iter;
12518
12519 WRLOCK_CACHE;
12520
12521 zbx_hashset_iter_reset(&config->proxies, &iter);
12522
12523 while (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_iter_next(&iter)))
12524 {
12525 if (proxy->lastaccess >= config->proxy_lastaccess_ts)
12526 {
12527 zbx_uint64_pair_t pair = {proxy->hostid, proxy->lastaccess};
12528
12529 zbx_vector_uint64_pair_append(lastaccess, pair);
12530 }
12531 }
12532
12533 config->proxy_lastaccess_ts = now;
12534
12535 UNLOCK_CACHE;
12536
12537 zbx_vector_uint64_pair_sort(lastaccess, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
12538 }
12539 }
12540
12541 /******************************************************************************
12542 * *
12543 * Function: zbx_dc_get_session_token *
12544 * *
12545 * Purpose: returns session token *
12546 * *
12547 * Return value: pointer to session token (NULL for server). *
12548 * *
12549 * Comments: The session token is generated during configuration cache *
12550 * initialization and is not changed later. Therefore no locking *
12551 * is required. *
12552 * *
12553 ******************************************************************************/
zbx_dc_get_session_token(void)12554 const char *zbx_dc_get_session_token(void)
12555 {
12556 return config->session_token;
12557 }
12558
12559 /******************************************************************************
12560 * *
12561 * Function: zbx_dc_get_or_create_data_session *
12562 * *
12563 * Purpose: returns data session, creates a new session if none found *
12564 * *
12565 * Parameter: hostid - [IN] the host (proxy) identifier *
12566 * token - [IN] the session token (not NULL) *
12567 * *
12568 * Return value: pointer to data session. *
12569 * *
12570 * Comments: The last_valueid property of the returned session object can be *
12571 * updated directly without locking cache because only one data *
12572 * session is updated at the same time and after retrieving the *
12573 * session object will not be deleted for 24 hours. *
12574 * *
12575 ******************************************************************************/
zbx_dc_get_or_create_data_session(zbx_uint64_t hostid,const char * token)12576 zbx_data_session_t *zbx_dc_get_or_create_data_session(zbx_uint64_t hostid, const char *token)
12577 {
12578 zbx_data_session_t *session, session_local;
12579 time_t now;
12580
12581 now = time(NULL);
12582 session_local.hostid = hostid;
12583 session_local.token = token;
12584
12585 RDLOCK_CACHE;
12586 session = (zbx_data_session_t *)zbx_hashset_search(&config->data_sessions, &session_local);
12587 UNLOCK_CACHE;
12588
12589 if (NULL == session)
12590 {
12591 WRLOCK_CACHE;
12592 session = (zbx_data_session_t *)zbx_hashset_insert(&config->data_sessions, &session_local,
12593 sizeof(session_local));
12594 session->token = dc_strdup(token);
12595 UNLOCK_CACHE;
12596
12597 session->last_valueid = 0;
12598 }
12599
12600 session->lastaccess = now;
12601
12602 return session;
12603 }
12604
12605 /******************************************************************************
12606 * *
12607 * Function: zbx_dc_cleanup_data_sessions *
12608 * *
12609 * Purpose: removes data sessions not accessed for 24 hours *
12610 * *
12611 ******************************************************************************/
zbx_dc_cleanup_data_sessions(void)12612 void zbx_dc_cleanup_data_sessions(void)
12613 {
12614 zbx_data_session_t *session;
12615 zbx_hashset_iter_t iter;
12616 time_t now;
12617
12618 now = time(NULL);
12619
12620 WRLOCK_CACHE;
12621
12622 zbx_hashset_iter_reset(&config->data_sessions, &iter);
12623 while (NULL != (session = (zbx_data_session_t *)zbx_hashset_iter_next(&iter)))
12624 {
12625 if (session->lastaccess + SEC_PER_DAY <= now)
12626 {
12627 __config_mem_free_func((char *)session->token);
12628 zbx_hashset_iter_remove(&iter);
12629 }
12630 }
12631
12632 UNLOCK_CACHE;
12633 }
12634
zbx_gather_tags_from_host(zbx_uint64_t hostid,zbx_vector_ptr_t * item_tags)12635 static void zbx_gather_tags_from_host(zbx_uint64_t hostid, zbx_vector_ptr_t *item_tags)
12636 {
12637 zbx_dc_host_tag_index_t *dc_tag_index;
12638 zbx_dc_host_tag_t *dc_tag;
12639 zbx_item_tag_t *tag;
12640 int i;
12641
12642 if (NULL != (dc_tag_index = zbx_hashset_search(&config->host_tags_index, &hostid)))
12643 {
12644 for (i = 0; i < dc_tag_index->tags.values_num; i++)
12645 {
12646 dc_tag = (zbx_dc_host_tag_t *)dc_tag_index->tags.values[i];
12647 tag = (zbx_item_tag_t *) zbx_malloc(NULL, sizeof(zbx_item_tag_t));
12648 tag->tag.tag = zbx_strdup(NULL, dc_tag->tag);
12649 tag->tag.value = zbx_strdup(NULL, dc_tag->value);
12650 zbx_vector_ptr_append(item_tags, tag);
12651 }
12652 }
12653 }
12654
zbx_gather_tags_from_template_chain(zbx_uint64_t itemid,zbx_vector_ptr_t * item_tags)12655 static void zbx_gather_tags_from_template_chain(zbx_uint64_t itemid, zbx_vector_ptr_t *item_tags)
12656 {
12657 ZBX_DC_TEMPLATE_ITEM *item;
12658
12659 if (NULL != (item = (ZBX_DC_TEMPLATE_ITEM *)zbx_hashset_search(&config->template_items, &itemid)))
12660 {
12661 zbx_gather_tags_from_host(item->hostid, item_tags);
12662
12663 if (0 != item->templateid)
12664 zbx_gather_tags_from_template_chain(item->templateid, item_tags);
12665 }
12666 }
12667
zbx_get_item_tags(zbx_uint64_t itemid,zbx_vector_ptr_t * item_tags)12668 static void zbx_get_item_tags(zbx_uint64_t itemid, zbx_vector_ptr_t *item_tags)
12669 {
12670 ZBX_DC_ITEM *item;
12671 ZBX_DC_PROTOTYPE_ITEM *lld_item;
12672 zbx_item_tag_t *tag;
12673 int n, i;
12674
12675 if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&config->items, &itemid)))
12676 return;
12677
12678 n = item_tags->values_num;
12679
12680 zbx_gather_tags_from_host(item->hostid, item_tags);
12681
12682 if (0 != item->templateid)
12683 zbx_gather_tags_from_template_chain(item->templateid, item_tags);
12684
12685 /* check for discovered item */
12686 if (0 != item->parent_itemid && 4 == item->flags)
12687 {
12688 if (NULL != (lld_item = (ZBX_DC_PROTOTYPE_ITEM *)zbx_hashset_search(&config->prototype_items,
12689 &item->parent_itemid)))
12690 {
12691 if (0 != lld_item->templateid)
12692 zbx_gather_tags_from_template_chain(lld_item->templateid, item_tags);
12693 }
12694 }
12695
12696 /* assign hostid and itemid values to newly gathered tags */
12697 for (i = n; i < item_tags->values_num; i++)
12698 {
12699 tag = (zbx_item_tag_t *)item_tags->values[i];
12700 tag->hostid = item->hostid;
12701 tag->itemid = item->itemid;
12702 }
12703 }
12704
zbx_dc_get_item_tags_by_functionids(const zbx_uint64_t * functionids,size_t functionids_num,zbx_vector_ptr_t * item_tags)12705 void zbx_dc_get_item_tags_by_functionids(const zbx_uint64_t *functionids, size_t functionids_num,
12706 zbx_vector_ptr_t *item_tags)
12707 {
12708 const ZBX_DC_FUNCTION *dc_function;
12709 size_t i;
12710
12711 RDLOCK_CACHE;
12712
12713 for (i = 0; i < functionids_num; i++)
12714 {
12715 if (NULL == (dc_function = (const ZBX_DC_FUNCTION *)zbx_hashset_search(&config->functions,
12716 &functionids[i])))
12717 {
12718 continue;
12719 }
12720
12721 zbx_get_item_tags(dc_function->itemid, item_tags);
12722 }
12723
12724 UNLOCK_CACHE;
12725 }
12726
12727 /******************************************************************************
12728 * *
12729 * Function: DCget_proxy_nodata_win *
12730 * *
12731 * Purpose: retrieves proxy suppress window data from the cache *
12732 * *
12733 * Parameters: hostid - [IN] proxy host id *
12734 * nodata_win - [OUT] suppress window data *
12735 * lastaccess - [OUT] proxy last access time *
12736 * *
12737 * Return value: SUCCEED - the data is retrieved *
12738 * FAIL - the data cannot be retrieved, proxy not found in *
12739 * configuration cache *
12740 * *
12741 ******************************************************************************/
DCget_proxy_nodata_win(zbx_uint64_t hostid,zbx_proxy_suppress_t * nodata_win,int * lastaccess)12742 int DCget_proxy_nodata_win(zbx_uint64_t hostid, zbx_proxy_suppress_t *nodata_win, int *lastaccess)
12743 {
12744 const ZBX_DC_PROXY *dc_proxy;
12745 int ret;
12746
12747 RDLOCK_CACHE;
12748
12749 if (NULL != (dc_proxy = (const ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &hostid)))
12750 {
12751 const zbx_proxy_suppress_t *proxy_nodata_win = &dc_proxy->nodata_win;
12752
12753 nodata_win->period_end = proxy_nodata_win->period_end;
12754 nodata_win->values_num = proxy_nodata_win->values_num;
12755 nodata_win->flags = proxy_nodata_win->flags;
12756 *lastaccess = dc_proxy->lastaccess;
12757 ret = SUCCEED;
12758 }
12759 else
12760 ret = FAIL;
12761
12762 UNLOCK_CACHE;
12763
12764 return ret;
12765 }
12766
12767 /******************************************************************************
12768 * *
12769 * Function: DCget_proxy_delay *
12770 * *
12771 * Purpose: retrieves proxy delay from the cache *
12772 * *
12773 * Parameters: hostid - [IN] proxy host id *
12774 * delay - [OUT] proxy delay *
12775 * *
12776 * Return value: SUCCEED - the delay is retrieved *
12777 * FAIL - the delay cannot be retrieved, proxy not found in *
12778 * configuration cache *
12779 * *
12780 ******************************************************************************/
DCget_proxy_delay(zbx_uint64_t hostid,int * delay)12781 int DCget_proxy_delay(zbx_uint64_t hostid, int *delay)
12782 {
12783 const ZBX_DC_PROXY *dc_proxy;
12784 int ret;
12785
12786 RDLOCK_CACHE;
12787
12788 if (NULL != (dc_proxy = (const ZBX_DC_PROXY *)zbx_hashset_search(&config->proxies, &hostid)))
12789 {
12790 *delay = dc_proxy->proxy_delay;
12791 ret = SUCCEED;
12792 }
12793 else
12794 ret = FAIL;
12795
12796 UNLOCK_CACHE;
12797
12798 return ret;
12799 }
12800
12801 /******************************************************************************
12802 * *
12803 * Function: DCget_proxy_delay_by_name *
12804 * *
12805 * Purpose: retrieves proxy delay from the cache *
12806 * *
12807 * Parameters: name - [IN] proxy host name *
12808 * delay - [OUT] proxy delay *
12809 * error - [OUT] error *
12810 * *
12811 * Return value: SUCCEED - proxy delay is retrieved *
12812 * FAIL - proxy delay cannot be retrieved *
12813 * *
12814 ******************************************************************************/
DCget_proxy_delay_by_name(const char * name,int * delay,char ** error)12815 int DCget_proxy_delay_by_name(const char *name, int *delay, char **error)
12816 {
12817 const ZBX_DC_HOST *dc_host;
12818
12819 RDLOCK_CACHE;
12820 dc_host = DCfind_proxy(name);
12821 UNLOCK_CACHE;
12822
12823 if (NULL == dc_host)
12824 {
12825 *error = zbx_dsprintf(*error, "Proxy \"%s\" not found.", name);
12826 return FAIL;
12827 }
12828
12829 if (SUCCEED != DCget_proxy_delay(dc_host->hostid, delay))
12830 {
12831 *error = zbx_dsprintf(*error, "Proxy \"%s\" not found in configuration cache.", name);
12832 return FAIL;
12833 }
12834
12835 return SUCCEED;
12836 }
12837
12838 /******************************************************************************
12839 * *
12840 * Function: zbx_dc_set_macro_env *
12841 * *
12842 * Purpose: sets user macro environment security level *
12843 * *
12844 * Parameter: env - [IN] the security level (see ZBX_MACRO_ENV_* defines) *
12845 * *
12846 * Comments: The security level affects how the secret macros are resolved - *
12847 * as they values or '******'. *
12848 * *
12849 ******************************************************************************/
zbx_dc_set_macro_env(unsigned char env)12850 unsigned char zbx_dc_set_macro_env(unsigned char env)
12851 {
12852 unsigned char old_env = macro_env;
12853 macro_env = env;
12854 return old_env;
12855 }
12856
12857 /******************************************************************************
12858 * *
12859 * Function: zbx_dc_get_instanceid *
12860 * *
12861 * Purpose: returns server/proxy instance id *
12862 * *
12863 * Return value: the instance id *
12864 * *
12865 ******************************************************************************/
zbx_dc_get_instanceid(void)12866 const char *zbx_dc_get_instanceid(void)
12867 {
12868 /* instanceid is initialized during the first configuration cache synchronization */
12869 /* and is never updated - so it can be accessed without locking cache */
12870 return config->config->instanceid;
12871 }
12872
12873 /******************************************************************************
12874 * *
12875 * Function: dc_expand_user_macros_in_func_params *
12876 * *
12877 * Purpose: expand user macros in trigger function parameters *
12878 * *
12879 * Parameters: params - [IN] the function parameters *
12880 * hostid - [IN] host of the item used in function *
12881 * *
12882 * Return value: The function parameters with expanded user macros. *
12883 * *
12884 ******************************************************************************/
dc_expand_user_macros_in_func_params(const char * params,zbx_uint64_t hostid)12885 char *dc_expand_user_macros_in_func_params(const char *params, zbx_uint64_t hostid)
12886 {
12887 const char *ptr;
12888 size_t params_len;
12889 char *buf;
12890 size_t buf_alloc, buf_offset = 0, sep_pos;
12891
12892 if ('\0' == *params)
12893 return zbx_strdup(NULL, params);
12894
12895 buf_alloc = params_len = strlen(params);
12896 buf = zbx_malloc(NULL, buf_alloc);
12897
12898 for (ptr = params; ptr < params + params_len; ptr += sep_pos + 1)
12899 {
12900 size_t param_pos, param_len;
12901 int quoted;
12902 char *param, *resolved_param;
12903
12904 zbx_function_param_parse(ptr, ¶m_pos, ¶m_len, &sep_pos);
12905
12906 param = zbx_function_param_unquote_dyn(ptr + param_pos, param_len, "ed);
12907 resolved_param = dc_expand_user_macros(param, &hostid, 1);
12908
12909 if (SUCCEED == zbx_function_param_quote(&resolved_param, quoted))
12910 zbx_strcpy_alloc(&buf, &buf_alloc, &buf_offset, resolved_param);
12911 else
12912 zbx_strncpy_alloc(&buf, &buf_alloc, &buf_offset, ptr + param_pos, param_len);
12913
12914 if (',' == ptr[sep_pos])
12915 zbx_chrcpy_alloc(&buf, &buf_alloc, &buf_offset, ',');
12916
12917 zbx_free(resolved_param);
12918 zbx_free(param);
12919 }
12920
12921 return buf;
12922 }
12923
zbx_dc_expand_user_macros_in_func_params(const char * params,zbx_uint64_t hostid)12924 char *zbx_dc_expand_user_macros_in_func_params(const char *params, zbx_uint64_t hostid)
12925 {
12926 char *resolved_params;
12927
12928 RDLOCK_CACHE;
12929 resolved_params = dc_expand_user_macros_in_func_params(params, hostid);
12930 UNLOCK_CACHE;
12931
12932 return resolved_params;
12933 }
12934
dc_expand_user_macros_in_calcitem(const char * formula,zbx_uint64_t hostid)12935 char *dc_expand_user_macros_in_calcitem(const char *formula, zbx_uint64_t hostid)
12936 {
12937 char *exp, *tmp,*expanded, error[128];
12938 const char *e;
12939 size_t exp_alloc = 128, exp_offset = 0, tmp_alloc = 128, tmp_offset = 0, f_pos, par_l, par_r;
12940 ZBX_DC_HOST *dc_host;
12941
12942 zabbix_log(LOG_LEVEL_DEBUG, "In %s() formula:%s", __func__, formula);
12943
12944 exp = (char *)zbx_malloc(NULL, exp_alloc);
12945 tmp = (char *)zbx_malloc(NULL, tmp_alloc);
12946
12947 for (e = formula; SUCCEED == zbx_function_find(e, &f_pos, &par_l, &par_r, error, sizeof(error)); e += par_r + 1)
12948 {
12949 size_t param_pos, param_len, sep_pos;
12950 int quoted;
12951 char *hostkey, *host = NULL, *key = NULL;
12952 zbx_uint64_t func_hostid = 0;
12953
12954 /* substitute user macros in the part of the string preceding function parameters */
12955
12956 zbx_strncpy_alloc(&tmp, &tmp_alloc, &tmp_offset, e, par_l + 1);
12957 expanded = dc_expand_user_macros_in_expression(tmp, &hostid, 1);
12958 zbx_strcpy_alloc(&exp, &exp_alloc, &exp_offset, expanded);
12959 zbx_free(expanded);
12960 tmp_offset = 0;
12961
12962 /* substitute user macros in function parameters */
12963
12964 zbx_function_param_parse(e + par_l + 1, ¶m_pos, ¶m_len, &sep_pos);
12965
12966 /* convert relative offset to absolute */
12967 param_pos += par_l + 1;
12968 sep_pos += par_l + 1;
12969
12970 zbx_strncpy_alloc(&exp, &exp_alloc, &exp_offset, e + par_l + 1, sep_pos - par_l);
12971
12972 /* calculated function has only fist parameter - host:key */
12973 if (sep_pos == par_r)
12974 continue;
12975
12976 /* extract host:key parameter to find the function hostid */
12977 hostkey = zbx_function_param_unquote_dyn(e + param_pos, param_len, "ed);
12978 if (SUCCEED == parse_host_key(hostkey, &host, &key))
12979 {
12980 if (NULL != host)
12981 {
12982 if (NULL != (dc_host = DCfind_host(host)))
12983 func_hostid = dc_host->hostid;
12984 }
12985 else
12986 func_hostid = hostid;
12987 }
12988 zbx_free(host);
12989 zbx_free(key);
12990 zbx_free(hostkey);
12991
12992 if (0 == func_hostid)
12993 {
12994 /* couldn't obtain target host, copy the rest of the function as it is */
12995 zbx_strncpy_alloc(&exp, &exp_alloc, &exp_offset, e + sep_pos + 1, par_r - sep_pos);
12996 continue;
12997 }
12998
12999 /* extract remaining parameters and expand user macros */
13000 zbx_strncpy_alloc(&tmp, &tmp_alloc, &tmp_offset, e + sep_pos + 1, par_r - sep_pos - 1);
13001 expanded = dc_expand_user_macros_in_func_params(tmp, func_hostid);
13002 zbx_strcpy_alloc(&exp, &exp_alloc, &exp_offset, expanded);
13003 zbx_free(expanded);
13004 tmp_offset = 0;
13005
13006 zbx_strcpy_alloc(&exp, &exp_alloc, &exp_offset, ")");
13007 }
13008
13009 if (par_l <= par_r)
13010 {
13011 /* substitute user macros in the remaining part */
13012 zbx_strcpy_alloc(&tmp, &tmp_alloc, &tmp_offset, e);
13013 expanded = dc_expand_user_macros_in_expression(tmp, &hostid, 1);
13014 zbx_strcpy_alloc(&exp, &exp_alloc, &exp_offset, expanded);
13015 zbx_free(expanded);
13016 }
13017
13018 zbx_free(tmp);
13019
13020 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() formula:%s", __func__, exp);
13021
13022 return exp;
13023 }
13024
zbx_dc_maintenance_has_tags(void)13025 int zbx_dc_maintenance_has_tags(void)
13026 {
13027 int ret;
13028
13029 RDLOCK_CACHE;
13030 ret = config->maintenance_tags.num_data != 0 ? SUCCEED : FAIL;
13031 UNLOCK_CACHE;
13032
13033 return ret;
13034 }
13035
13036 #ifdef HAVE_TESTS
13037 # include "../../../tests/libs/zbxdbcache/dc_item_poller_type_update_test.c"
13038 #endif
13039