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 "common.h"
21 #include "log.h"
22 #include "dbcache.h"
23 #include "zbxserialize.h"
24 #include "base64.h"
25 #include "zbxeval.h"
26
27 #define ZBX_DBCONFIG_IMPL
28 #include "dbconfig.h"
29 #include "dbsync.h"
30
31 typedef struct
32 {
33 zbx_hashset_t strpool;
34 ZBX_DC_CONFIG *cache;
35 }
36 zbx_dbsync_env_t;
37
38 static zbx_dbsync_env_t dbsync_env;
39
40 /* string pool support */
41
42 #define REFCOUNT_FIELD_SIZE sizeof(zbx_uint32_t)
43
dbsync_strpool_hash_func(const void * data)44 static zbx_hash_t dbsync_strpool_hash_func(const void *data)
45 {
46 return ZBX_DEFAULT_STRING_HASH_FUNC((char *)data + REFCOUNT_FIELD_SIZE);
47 }
48
dbsync_strpool_compare_func(const void * d1,const void * d2)49 static int dbsync_strpool_compare_func(const void *d1, const void *d2)
50 {
51 return strcmp((char *)d1 + REFCOUNT_FIELD_SIZE, (char *)d2 + REFCOUNT_FIELD_SIZE);
52 }
53
dbsync_strdup(const char * str)54 static char *dbsync_strdup(const char *str)
55 {
56 void *ptr;
57
58 ptr = zbx_hashset_search(&dbsync_env.strpool, str - REFCOUNT_FIELD_SIZE);
59
60 if (NULL == ptr)
61 {
62 ptr = zbx_hashset_insert_ext(&dbsync_env.strpool, str - REFCOUNT_FIELD_SIZE,
63 REFCOUNT_FIELD_SIZE + strlen(str) + 1, REFCOUNT_FIELD_SIZE);
64
65 *(zbx_uint32_t *)ptr = 0;
66 }
67
68 (*(zbx_uint32_t *)ptr)++;
69
70 return (char *)ptr + REFCOUNT_FIELD_SIZE;
71 }
72
dbsync_strfree(char * str)73 static void dbsync_strfree(char *str)
74 {
75 if (NULL != str)
76 {
77 void *ptr = str - REFCOUNT_FIELD_SIZE;
78
79 if (0 == --(*(zbx_uint32_t *)ptr))
80 zbx_hashset_remove_direct(&dbsync_env.strpool, ptr);
81 }
82 }
83
84 /* macro value validators */
85
86 /******************************************************************************
87 * *
88 * Function: dbsync_compare_uint64 *
89 * *
90 * Purpose: compares 64 bit unsigned integer with a raw database value *
91 * *
92 ******************************************************************************/
dbsync_compare_uint64(const char * value_raw,zbx_uint64_t value)93 static int dbsync_compare_uint64(const char *value_raw, zbx_uint64_t value)
94 {
95 zbx_uint64_t value_ui64;
96
97 ZBX_DBROW2UINT64(value_ui64, value_raw);
98
99 return (value_ui64 == value ? SUCCEED : FAIL);
100 }
101
102 /******************************************************************************
103 * *
104 * Function: dbsync_compare_int *
105 * *
106 * Purpose: compares 32 bit signed integer with a raw database value *
107 * *
108 ******************************************************************************/
dbsync_compare_int(const char * value_raw,int value)109 static int dbsync_compare_int(const char *value_raw, int value)
110 {
111 return (atoi(value_raw) == value ? SUCCEED : FAIL);
112 }
113
114 /******************************************************************************
115 * *
116 * Function: dbsync_compare_uchar *
117 * *
118 * Purpose: compares unsigned character with a raw database value *
119 * *
120 ******************************************************************************/
121
dbsync_compare_uchar(const char * value_raw,unsigned char value)122 static int dbsync_compare_uchar(const char *value_raw, unsigned char value)
123 {
124 unsigned char value_uchar;
125
126 ZBX_STR2UCHAR(value_uchar, value_raw);
127 return (value_uchar == value ? SUCCEED : FAIL);
128 }
129
130 /******************************************************************************
131 * *
132 * Function: dbsync_compare_str *
133 * *
134 * Purpose: compares string with a raw database value *
135 * *
136 ******************************************************************************/
137
dbsync_compare_str(const char * value_raw,const char * value)138 static int dbsync_compare_str(const char *value_raw, const char *value)
139 {
140 return (0 == strcmp(value_raw, value) ? SUCCEED : FAIL);
141 }
142
143 /******************************************************************************
144 * *
145 * Function: dbsync_add_row *
146 * *
147 * Purpose: adds a new row to the changeset *
148 * *
149 * Parameter: sync - [IN] the changeset *
150 * rowid - [IN] the row identifier *
151 * tag - [IN] the row tag (see ZBX_DBSYNC_ROW_ defines) *
152 * dbrow - [IN] the row contents (depending on configuration cache *
153 * removal logic for the specific object it can be *
154 * NULL when used with ZBX_DBSYNC_ROW_REMOVE tag) *
155 * *
156 ******************************************************************************/
dbsync_add_row(zbx_dbsync_t * sync,zbx_uint64_t rowid,unsigned char tag,const DB_ROW dbrow)157 static void dbsync_add_row(zbx_dbsync_t *sync, zbx_uint64_t rowid, unsigned char tag, const DB_ROW dbrow)
158 {
159 int i;
160 zbx_dbsync_row_t *row;
161
162 row = (zbx_dbsync_row_t *)zbx_malloc(NULL, sizeof(zbx_dbsync_row_t));
163 row->rowid = rowid;
164 row->tag = tag;
165
166 if (NULL != dbrow)
167 {
168 row->row = (char **)zbx_malloc(NULL, sizeof(char *) * sync->columns_num);
169
170 for (i = 0; i < sync->columns_num; i++)
171 row->row[i] = (NULL == dbrow[i] ? NULL : dbsync_strdup(dbrow[i]));
172 }
173 else
174 row->row = NULL;
175
176 zbx_vector_ptr_append(&sync->rows, row);
177
178 switch (tag)
179 {
180 case ZBX_DBSYNC_ROW_ADD:
181 sync->add_num++;
182 break;
183 case ZBX_DBSYNC_ROW_UPDATE:
184 sync->update_num++;
185 break;
186 case ZBX_DBSYNC_ROW_REMOVE:
187 sync->remove_num++;
188 break;
189 }
190 }
191
192 /******************************************************************************
193 * *
194 * Function: dbsync_prepare *
195 * *
196 * Purpose: prepares changeset *
197 * *
198 * Parameter: sync - [IN] the changeset *
199 * columns_num - [IN] the number of columns in the changeset *
200 * preproc_row_func - [IN] the callback function used to retrieve *
201 * associated hostids (can be NULL if *
202 * user macros are not resolved during *
203 * synchronization process) *
204 * *
205 ******************************************************************************/
dbsync_prepare(zbx_dbsync_t * sync,int columns_num,zbx_dbsync_preproc_row_func_t preproc_row_func)206 static void dbsync_prepare(zbx_dbsync_t *sync, int columns_num, zbx_dbsync_preproc_row_func_t preproc_row_func)
207 {
208 sync->columns_num = columns_num;
209 sync->preproc_row_func = preproc_row_func;
210
211 sync->row = (char **)zbx_malloc(NULL, sizeof(char *) * columns_num);
212 memset(sync->row, 0, sizeof(char *) * columns_num);
213 }
214
215 /******************************************************************************
216 * *
217 * Function: dbsync_check_row_macros *
218 * *
219 * Purpose: checks if the specified column in the row contains user macros *
220 * *
221 * Parameter: row - [IN] the row to check *
222 * column - [IN] the column index *
223 * *
224 * Comments: While not definite, this check is used to filter out rows before *
225 * doing more precise (and resource intense) checks. *
226 * *
227 ******************************************************************************/
dbsync_check_row_macros(char ** row,int column)228 static int dbsync_check_row_macros(char **row, int column)
229 {
230 if (NULL != strstr(row[column], "{$"))
231 return SUCCEED;
232
233 return FAIL;
234 }
235
236 /******************************************************************************
237 * *
238 * Function: dbsync_preproc_row *
239 * *
240 * Purpose: applies necessary pre-processing before row is compared/used *
241 * *
242 * Parameter: sync - [IN] the changeset *
243 * row - [IN/OUT] the data row *
244 * *
245 * Return value: the resulting row *
246 * *
247 ******************************************************************************/
dbsync_preproc_row(zbx_dbsync_t * sync,char ** row)248 static char **dbsync_preproc_row(zbx_dbsync_t *sync, char **row)
249 {
250 int i;
251
252 if (NULL == sync->preproc_row_func)
253 return row;
254
255 /* free the resources allocated by last preprocessing call */
256 zbx_vector_ptr_clear_ext(&sync->columns, zbx_ptr_free);
257
258 /* copy the original data */
259 memcpy(sync->row, row, sizeof(char *) * sync->columns_num);
260
261 sync->row = sync->preproc_row_func(sync->row);
262
263 for (i = 0; i < sync->columns_num; i++)
264 {
265 if (sync->row[i] != row[i])
266 zbx_vector_ptr_append(&sync->columns, sync->row[i]);
267 }
268
269 return sync->row;
270 }
271
272 /******************************************************************************
273 * *
274 * Function: zbx_dbsync_init_env *
275 * *
276 ******************************************************************************/
zbx_dbsync_init_env(ZBX_DC_CONFIG * cache)277 void zbx_dbsync_init_env(ZBX_DC_CONFIG *cache)
278 {
279 dbsync_env.cache = cache;
280 zbx_hashset_create(&dbsync_env.strpool, 100, dbsync_strpool_hash_func, dbsync_strpool_compare_func);
281 }
282
283 /******************************************************************************
284 * *
285 * Function: dbsync_env_release *
286 * *
287 ******************************************************************************/
zbx_dbsync_free_env(void)288 void zbx_dbsync_free_env(void)
289 {
290 zbx_hashset_destroy(&dbsync_env.strpool);
291 }
292
293 /******************************************************************************
294 * *
295 * Function: zbx_dbsync_init *
296 * *
297 * Purpose: initializes changeset *
298 * *
299 ******************************************************************************/
zbx_dbsync_init(zbx_dbsync_t * sync,unsigned char mode)300 void zbx_dbsync_init(zbx_dbsync_t *sync, unsigned char mode)
301 {
302 sync->columns_num = 0;
303 sync->mode = mode;
304
305 sync->add_num = 0;
306 sync->update_num = 0;
307 sync->remove_num = 0;
308
309 sync->row = NULL;
310 sync->preproc_row_func = NULL;
311 zbx_vector_ptr_create(&sync->columns);
312
313 if (ZBX_DBSYNC_UPDATE == sync->mode)
314 {
315 zbx_vector_ptr_create(&sync->rows);
316 sync->row_index = 0;
317 }
318 else
319 sync->dbresult = NULL;
320 }
321
322 /******************************************************************************
323 * *
324 * Function: zbx_dbsync_clear *
325 * *
326 * Purpose: frees resources allocated by changeset *
327 * *
328 ******************************************************************************/
zbx_dbsync_clear(zbx_dbsync_t * sync)329 void zbx_dbsync_clear(zbx_dbsync_t *sync)
330 {
331 /* free the resources allocated by row pre-processing */
332 zbx_vector_ptr_clear_ext(&sync->columns, zbx_ptr_free);
333 zbx_vector_ptr_destroy(&sync->columns);
334
335 zbx_free(sync->row);
336
337 if (ZBX_DBSYNC_UPDATE == sync->mode)
338 {
339 int i, j;
340 zbx_dbsync_row_t *row;
341
342 for (i = 0; i < sync->rows.values_num; i++)
343 {
344 row = (zbx_dbsync_row_t *)sync->rows.values[i];
345
346 if (NULL != row->row)
347 {
348 for (j = 0; j < sync->columns_num; j++)
349 dbsync_strfree(row->row[j]);
350
351 zbx_free(row->row);
352 }
353
354 zbx_free(row);
355 }
356
357 zbx_vector_ptr_destroy(&sync->rows);
358 }
359 else
360 {
361 DBfree_result(sync->dbresult);
362 sync->dbresult = NULL;
363 }
364 }
365
366 /******************************************************************************
367 * *
368 * Function: zbx_dbsync_next *
369 * *
370 * Purpose: gets the next row from the changeset *
371 * *
372 * Parameters: sync - [IN] the changeset *
373 * rowid - [OUT] the row identifier (required for row removal, *
374 * optional for new/updated rows) *
375 * row - [OUT] the row data *
376 * tag - [OUT] the row tag, identifying changes *
377 * (see ZBX_DBSYNC_ROW_* defines) *
378 * *
379 * Return value: SUCCEED - the next row was successfully retrieved *
380 * FAIL - no more data to retrieve *
381 * *
382 ******************************************************************************/
zbx_dbsync_next(zbx_dbsync_t * sync,zbx_uint64_t * rowid,char *** row,unsigned char * tag)383 int zbx_dbsync_next(zbx_dbsync_t *sync, zbx_uint64_t *rowid, char ***row, unsigned char *tag)
384 {
385 if (ZBX_DBSYNC_UPDATE == sync->mode)
386 {
387 zbx_dbsync_row_t *sync_row;
388
389 if (sync->row_index == sync->rows.values_num)
390 {
391 return FAIL;
392 }
393
394 sync_row = (zbx_dbsync_row_t *)sync->rows.values[sync->row_index++];
395 *rowid = sync_row->rowid;
396 *row = sync_row->row;
397 *tag = sync_row->tag;
398 }
399 else
400 {
401 char **dbrow;
402
403 if (NULL == (dbrow = DBfetch(sync->dbresult)))
404 {
405 *row = NULL;
406 return FAIL;
407 }
408
409 *row = dbsync_preproc_row(sync, dbrow);
410
411 *rowid = 0;
412 *tag = ZBX_DBSYNC_ROW_ADD;
413
414 sync->add_num++;
415 }
416
417 return SUCCEED;
418 }
419
420 /******************************************************************************
421 * *
422 * Function: encode_expression *
423 * *
424 * Purpose: encode serialized expression to be returned as db field *
425 * *
426 * Parameter: sync - [OUT] the changeset *
427 * *
428 * Return value: SUCCEED - the changeset was successfully calculated *
429 * FAIL - otherwise *
430 * *
431 ******************************************************************************/
encode_expression(const zbx_eval_context_t * ctx)432 static char *encode_expression(const zbx_eval_context_t *ctx)
433 {
434 unsigned char *data;
435 size_t len;
436 char *str = NULL;
437
438 len = zbx_eval_serialize(ctx, NULL, &data);
439 str_base64_encode_dyn((const char *)data, &str, len);
440 zbx_free(data);
441
442 return str;
443 }
444
445
446 /******************************************************************************
447 * *
448 * Function: dbsync_compare_serialized_expression *
449 * *
450 * Purpose: compare serialized expression *
451 * *
452 * Parameter: col - [IN] the base64 encoded expression *
453 * data2 - [IN] the serialized expression in cache *
454 * *
455 * Return value: SUCCEED - the expressions are identical *
456 * FAIL - otherwise *
457 * *
458 ******************************************************************************/
dbsync_compare_serialized_expression(const char * col,const unsigned char * data2)459 static int dbsync_compare_serialized_expression(const char *col, const unsigned char *data2)
460 {
461 zbx_uint32_t offset1, len1, offset2, len2;
462 unsigned char *data1;
463 int col_len, data1_len, ret = FAIL;
464
465 if (NULL == data2)
466 {
467 if (NULL == col || '\0' == *col)
468 return SUCCEED;
469 return FAIL;
470 }
471
472 if (NULL == col || '\0' == *col)
473 return FAIL;
474
475 col_len = strlen(col);
476 data1 = zbx_malloc(NULL, col_len);
477
478 str_base64_decode(col, (char *)data1, col_len, &data1_len);
479
480 offset1 = zbx_deserialize_uint31_compact((const unsigned char *)data1, &len1);
481 offset2 = zbx_deserialize_uint31_compact((const unsigned char *)data2, &len2);
482
483 if (offset1 != offset2 || len1 != len2)
484 goto out;
485
486 if (0 != memcmp(data1 + offset1, data2 + offset2, len1))
487 goto out;
488
489 ret = SUCCEED;
490 out:
491 zbx_free(data1);
492
493 return ret;
494 }
495
496 /******************************************************************************
497 * *
498 * Function: zbx_dbsync_compare_config *
499 * *
500 * Purpose: compares config table with cached configuration data *
501 * *
502 * Parameter: sync - [OUT] the changeset *
503 * *
504 * Return value: SUCCEED - the changeset was successfully calculated *
505 * FAIL - otherwise *
506 * *
507 ******************************************************************************/
zbx_dbsync_compare_config(zbx_dbsync_t * sync)508 int zbx_dbsync_compare_config(zbx_dbsync_t *sync)
509 {
510 DB_RESULT result;
511
512 #define SELECTED_CONFIG_FIELD_COUNT 32 /* number of columns in the following DBselect() */
513
514 if (NULL == (result = DBselect("select discovery_groupid,snmptrap_logging,"
515 "severity_name_0,severity_name_1,severity_name_2,"
516 "severity_name_3,severity_name_4,severity_name_5,"
517 "hk_events_mode,hk_events_trigger,hk_events_internal,"
518 "hk_events_discovery,hk_events_autoreg,hk_services_mode,"
519 "hk_services,hk_audit_mode,hk_audit,hk_sessions_mode,hk_sessions,"
520 "hk_history_mode,hk_history_global,hk_history,hk_trends_mode,"
521 "hk_trends_global,hk_trends,default_inventory_mode,db_extension,autoreg_tls_accept,"
522 "compression_status,compress_older,instanceid,default_timezone"
523 " from config"
524 " order by configid"))) /* if you change number of columns in DBselect(), */
525 /* adjust SELECTED_CONFIG_FIELD_COUNT */
526 {
527 return FAIL;
528 }
529
530 dbsync_prepare(sync, SELECTED_CONFIG_FIELD_COUNT, NULL);
531
532 if (ZBX_DBSYNC_INIT == sync->mode)
533 {
534 sync->dbresult = result;
535 return SUCCEED;
536 }
537
538 DBfree_result(result);
539
540 /* global configuration will be always synchronized directly with database */
541 THIS_SHOULD_NEVER_HAPPEN;
542
543 return FAIL;
544 #undef SELECTED_CONFIG_FIELD_COUNT
545 }
546
547 /******************************************************************************
548 * *
549 * Function: zbx_dbsync_compare_autoreg_psk *
550 * *
551 * Purpose: compares 'config_autoreg_tls' table with cached configuration *
552 * data *
553 * *
554 * Parameter: sync - [OUT] the changeset *
555 * *
556 * Return value: SUCCEED - the changeset was successfully calculated *
557 * FAIL - otherwise *
558 * *
559 * Comments: *
560 * On success this function produces a changeset with 0 or 1 record *
561 * because 'config_autoreg_tls' table can have no more than 1 record. *
562 * If in future you want to support multiple autoregistration PSKs and/or *
563 * select more columns in DBselect() then do not forget to sync changes *
564 * with DCsync_autoreg_config() !!! *
565 * *
566 ******************************************************************************/
zbx_dbsync_compare_autoreg_psk(zbx_dbsync_t * sync)567 int zbx_dbsync_compare_autoreg_psk(zbx_dbsync_t *sync)
568 {
569 DB_RESULT result;
570 DB_ROW dbrow;
571 int num_records = 0;
572
573 #define CONFIG_AUTOREG_TLS_FIELD_COUNT 2 /* number of columns in the following DBselect() */
574
575 if (NULL == (result = DBselect("select tls_psk_identity,tls_psk"
576 " from config_autoreg_tls"
577 " order by autoreg_tlsid"))) /* if you change number of columns in DBselect(), */
578 /* adjust CONFIG_AUTOREG_TLS_FIELD_COUNT */
579 {
580 return FAIL;
581 }
582
583 dbsync_prepare(sync, CONFIG_AUTOREG_TLS_FIELD_COUNT, NULL);
584
585 if (ZBX_DBSYNC_INIT == sync->mode)
586 {
587 sync->dbresult = result;
588 return SUCCEED;
589 }
590
591 /* 0 or 1 records are expected */
592
593 if (NULL != (dbrow = DBfetch(result)))
594 {
595 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
596
597 if ('\0' == dbsync_env.cache->autoreg_psk_identity[0]) /* no autoregistration PSK in cache */
598 {
599 tag = ZBX_DBSYNC_ROW_ADD;
600 }
601 else if (FAIL == dbsync_compare_str(dbrow[0], dbsync_env.cache->autoreg_psk_identity) ||
602 FAIL == dbsync_compare_str(dbrow[1], dbsync_env.cache->autoreg_psk))
603 {
604 tag = ZBX_DBSYNC_ROW_UPDATE;
605 }
606
607 if (ZBX_DBSYNC_ROW_NONE != tag)
608 dbsync_add_row(sync, 0, tag, dbrow); /* fictitious rowid 0 is used, there is only 1 record */
609
610 num_records = 1;
611 }
612 else if ('\0' != dbsync_env.cache->autoreg_psk_identity[0])
613 dbsync_add_row(sync, 0, ZBX_DBSYNC_ROW_REMOVE, NULL);
614
615 if (1 == num_records && NULL != DBfetch(result))
616 zabbix_log(LOG_LEVEL_ERR, "table 'config_autoreg_tls' has multiple records");
617
618 DBfree_result(result);
619
620 return SUCCEED;
621 #undef CONFIG_AUTOREG_TLS_FIELD_COUNT
622 }
623
624 /******************************************************************************
625 * *
626 * Function: dbsync_compare_host *
627 * *
628 * Purpose: compares hosts table row with cached configuration data *
629 * *
630 * Parameter: host - [IN] the cached host *
631 * dbrow - [IN] the database row *
632 * *
633 * Return value: SUCCEED - the row matches configuration data *
634 * FAIL - otherwise *
635 * *
636 ******************************************************************************/
dbsync_compare_host(ZBX_DC_HOST * host,const DB_ROW dbrow)637 static int dbsync_compare_host(ZBX_DC_HOST *host, const DB_ROW dbrow)
638 {
639 signed char ipmi_authtype;
640 unsigned char ipmi_privilege;
641 ZBX_DC_IPMIHOST *ipmihost;
642 ZBX_DC_PROXY *proxy;
643
644 if (FAIL == dbsync_compare_uint64(dbrow[1], host->proxy_hostid))
645 {
646 host->update_items = 1;
647 return FAIL;
648 }
649
650 if (FAIL == dbsync_compare_uchar(dbrow[10], host->status))
651 {
652 host->update_items = 1;
653 return FAIL;
654 }
655
656 host->update_items = 0;
657
658 if (FAIL == dbsync_compare_str(dbrow[2], host->host))
659 return FAIL;
660
661 if (FAIL == dbsync_compare_str(dbrow[11], host->name))
662 return FAIL;
663
664 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
665 if (FAIL == dbsync_compare_str(dbrow[15], host->tls_issuer))
666 return FAIL;
667
668 if (FAIL == dbsync_compare_str(dbrow[16], host->tls_subject))
669 return FAIL;
670
671 if ('\0' == *dbrow[17] || '\0' == *dbrow[18])
672 {
673 if (NULL != host->tls_dc_psk)
674 return FAIL;
675 }
676 else
677 {
678 if (NULL == host->tls_dc_psk)
679 return FAIL;
680
681 if (FAIL == dbsync_compare_str(dbrow[17], host->tls_dc_psk->tls_psk_identity))
682 return FAIL;
683
684 if (FAIL == dbsync_compare_str(dbrow[18], host->tls_dc_psk->tls_psk))
685 return FAIL;
686 }
687
688 #endif
689 if (FAIL == dbsync_compare_uchar(dbrow[13], host->tls_connect))
690 return FAIL;
691
692 if (FAIL == dbsync_compare_uchar(dbrow[14], host->tls_accept))
693 return FAIL;
694
695 /* IPMI hosts */
696
697 ipmi_authtype = (signed char)atoi(dbrow[3]);
698 ipmi_privilege = (unsigned char)atoi(dbrow[4]);
699
700 if (ZBX_IPMI_DEFAULT_AUTHTYPE != ipmi_authtype || ZBX_IPMI_DEFAULT_PRIVILEGE != ipmi_privilege ||
701 '\0' != *dbrow[5] || '\0' != *dbrow[6]) /* useipmi */
702 {
703 if (NULL == (ipmihost = (ZBX_DC_IPMIHOST *)zbx_hashset_search(&dbsync_env.cache->ipmihosts,
704 &host->hostid)))
705 {
706 return FAIL;
707 }
708
709 if (ipmihost->ipmi_authtype != ipmi_authtype)
710 return FAIL;
711
712 if (ipmihost->ipmi_privilege != ipmi_privilege)
713 return FAIL;
714
715 if (FAIL == dbsync_compare_str(dbrow[5], ipmihost->ipmi_username))
716 return FAIL;
717
718 if (FAIL == dbsync_compare_str(dbrow[6], ipmihost->ipmi_password))
719 return FAIL;
720 }
721 else if (NULL != zbx_hashset_search(&dbsync_env.cache->ipmihosts, &host->hostid))
722 return FAIL;
723
724 /* proxies */
725 if (NULL != (proxy = (ZBX_DC_PROXY *)zbx_hashset_search(&dbsync_env.cache->proxies, &host->hostid)))
726 {
727 if (FAIL == dbsync_compare_str(dbrow[15 + ZBX_HOST_TLS_OFFSET], proxy->proxy_address))
728 return FAIL;
729
730 if (FAIL == dbsync_compare_uchar(dbrow[16 + ZBX_HOST_TLS_OFFSET], proxy->auto_compress))
731 return FAIL;
732 }
733
734 return SUCCEED;
735 }
736
737 /******************************************************************************
738 * *
739 * Function: zbx_dbsync_compare_hosts *
740 * *
741 * Purpose: compares hosts table with cached configuration data *
742 * and populates the changeset *
743 * *
744 * Parameter: sync - [OUT] the changeset *
745 * *
746 * Return value: SUCCEED - the changeset was successfully calculated *
747 * FAIL - otherwise *
748 * *
749 ******************************************************************************/
zbx_dbsync_compare_hosts(zbx_dbsync_t * sync)750 int zbx_dbsync_compare_hosts(zbx_dbsync_t *sync)
751 {
752 DB_ROW dbrow;
753 DB_RESULT result;
754 zbx_hashset_t ids;
755 zbx_hashset_iter_t iter;
756 zbx_uint64_t rowid;
757 ZBX_DC_HOST *host;
758
759 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
760 if (NULL == (result = DBselect(
761 "select hostid,proxy_hostid,host,ipmi_authtype,ipmi_privilege,ipmi_username,"
762 "ipmi_password,maintenance_status,maintenance_type,maintenance_from,"
763 "status,name,lastaccess,tls_connect,tls_accept,tls_issuer,tls_subject,"
764 "tls_psk_identity,tls_psk,proxy_address,auto_compress,maintenanceid"
765 " from hosts"
766 " where status in (%d,%d,%d,%d)"
767 " and flags<>%d",
768 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
769 HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE,
770 ZBX_FLAG_DISCOVERY_PROTOTYPE)))
771 {
772 return FAIL;
773 }
774
775 dbsync_prepare(sync, 22, NULL);
776 #else
777 if (NULL == (result = DBselect(
778 "select hostid,proxy_hostid,host,ipmi_authtype,ipmi_privilege,ipmi_username,"
779 "ipmi_password,maintenance_status,maintenance_type,maintenance_from,"
780 "status,name,lastaccess,tls_connect,tls_accept,"
781 "proxy_address,auto_compress,maintenanceid"
782 " from hosts"
783 " where status in (%d,%d,%d,%d)"
784 " and flags<>%d",
785 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
786 HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE,
787 ZBX_FLAG_DISCOVERY_PROTOTYPE)))
788 {
789 return FAIL;
790 }
791
792 dbsync_prepare(sync, 18, NULL);
793 #endif
794
795 if (ZBX_DBSYNC_INIT == sync->mode)
796 {
797 sync->dbresult = result;
798 return SUCCEED;
799 }
800
801 zbx_hashset_create(&ids, dbsync_env.cache->hosts.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
802 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
803
804 while (NULL != (dbrow = DBfetch(result)))
805 {
806 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
807
808 ZBX_STR2UINT64(rowid, dbrow[0]);
809 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
810
811 if (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&dbsync_env.cache->hosts, &rowid)))
812 tag = ZBX_DBSYNC_ROW_ADD;
813 else if (FAIL == dbsync_compare_host(host, dbrow))
814 tag = ZBX_DBSYNC_ROW_UPDATE;
815
816 if (ZBX_DBSYNC_ROW_NONE != tag)
817 dbsync_add_row(sync, rowid, tag, dbrow);
818 }
819
820 zbx_hashset_iter_reset(&dbsync_env.cache->hosts, &iter);
821 while (NULL != (host = (ZBX_DC_HOST *)zbx_hashset_iter_next(&iter)))
822 {
823 if (NULL == zbx_hashset_search(&ids, &host->hostid))
824 dbsync_add_row(sync, host->hostid, ZBX_DBSYNC_ROW_REMOVE, NULL);
825 }
826
827 zbx_hashset_destroy(&ids);
828 DBfree_result(result);
829
830 return SUCCEED;
831 }
832
833 /******************************************************************************
834 * *
835 * Function: dbsync_compare_host_inventory *
836 * *
837 * Purpose: compares host inventory table row with cached configuration data *
838 * *
839 * Parameter: hi - [IN] the cached host inventory data *
840 * dbrow - [IN] the database row *
841 * *
842 * Return value: SUCCEED - the row matches configuration data *
843 * FAIL - otherwise *
844 * *
845 ******************************************************************************/
dbsync_compare_host_inventory(const ZBX_DC_HOST_INVENTORY * hi,const DB_ROW dbrow)846 static int dbsync_compare_host_inventory(const ZBX_DC_HOST_INVENTORY *hi, const DB_ROW dbrow)
847 {
848 int i;
849
850 if (SUCCEED != dbsync_compare_uchar(dbrow[1], hi->inventory_mode))
851 return FAIL;
852
853 for (i = 0; i < HOST_INVENTORY_FIELD_COUNT; i++)
854 {
855 if (FAIL == dbsync_compare_str(dbrow[i + 2], hi->values[i]))
856 return FAIL;
857 }
858
859 return SUCCEED;
860 }
861
862 /******************************************************************************
863 * *
864 * Function: zbx_dbsync_compare_host_inventory *
865 * *
866 * Purpose: compares host_inventory table with cached configuration data *
867 * *
868 * Parameter: sync - [OUT] the changeset *
869 * *
870 * Return value: SUCCEED - the changeset was successfully calculated *
871 * FAIL - otherwise *
872 * *
873 ******************************************************************************/
zbx_dbsync_compare_host_inventory(zbx_dbsync_t * sync)874 int zbx_dbsync_compare_host_inventory(zbx_dbsync_t *sync)
875 {
876 DB_ROW dbrow;
877 DB_RESULT result;
878 zbx_hashset_t ids;
879 zbx_hashset_iter_t iter;
880 zbx_uint64_t rowid;
881 ZBX_DC_HOST_INVENTORY *hi;
882 const char *sql;
883
884 sql = "select hostid,inventory_mode,type,type_full,name,alias,os,os_full,os_short,serialno_a,"
885 "serialno_b,tag,asset_tag,macaddress_a,macaddress_b,hardware,hardware_full,software,"
886 "software_full,software_app_a,software_app_b,software_app_c,software_app_d,"
887 "software_app_e,contact,location,location_lat,location_lon,notes,chassis,model,"
888 "hw_arch,vendor,contract_number,installer_name,deployment_status,url_a,url_b,"
889 "url_c,host_networks,host_netmask,host_router,oob_ip,oob_netmask,oob_router,"
890 "date_hw_purchase,date_hw_install,date_hw_expiry,date_hw_decomm,site_address_a,"
891 "site_address_b,site_address_c,site_city,site_state,site_country,site_zip,site_rack,"
892 "site_notes,poc_1_name,poc_1_email,poc_1_phone_a,poc_1_phone_b,poc_1_cell,"
893 "poc_1_screen,poc_1_notes,poc_2_name,poc_2_email,poc_2_phone_a,poc_2_phone_b,"
894 "poc_2_cell,poc_2_screen,poc_2_notes"
895 " from host_inventory";
896
897 if (NULL == (result = DBselect("%s", sql)))
898 return FAIL;
899
900 dbsync_prepare(sync, 72, NULL);
901
902 if (ZBX_DBSYNC_INIT == sync->mode)
903 {
904 sync->dbresult = result;
905 return SUCCEED;
906 }
907
908 zbx_hashset_create(&ids, dbsync_env.cache->host_inventories.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
909 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
910
911 while (NULL != (dbrow = DBfetch(result)))
912 {
913 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
914
915 ZBX_STR2UINT64(rowid, dbrow[0]);
916 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
917
918 if (NULL == (hi = (ZBX_DC_HOST_INVENTORY *)zbx_hashset_search(&dbsync_env.cache->host_inventories,
919 &rowid)))
920 {
921 tag = ZBX_DBSYNC_ROW_ADD;
922 }
923 else if (FAIL == dbsync_compare_host_inventory(hi, dbrow))
924 tag = ZBX_DBSYNC_ROW_UPDATE;
925
926 if (ZBX_DBSYNC_ROW_NONE != tag)
927 dbsync_add_row(sync, rowid, tag, dbrow);
928
929 }
930
931 zbx_hashset_iter_reset(&dbsync_env.cache->host_inventories, &iter);
932 while (NULL != (hi = (ZBX_DC_HOST_INVENTORY *)zbx_hashset_iter_next(&iter)))
933 {
934 if (NULL == zbx_hashset_search(&ids, &hi->hostid))
935 dbsync_add_row(sync, hi->hostid, ZBX_DBSYNC_ROW_REMOVE, NULL);
936 }
937
938 zbx_hashset_destroy(&ids);
939 DBfree_result(result);
940
941 return SUCCEED;
942 }
943
944 /******************************************************************************
945 * *
946 * Function: zbx_dbsync_compare_host_templates *
947 * *
948 * Purpose: compares hosts_templates table with cached configuration data *
949 * *
950 * Parameter: sync - [OUT] the changeset *
951 * *
952 * Return value: SUCCEED - the changeset was successfully calculated *
953 * FAIL - otherwise *
954 * *
955 ******************************************************************************/
zbx_dbsync_compare_host_templates(zbx_dbsync_t * sync)956 int zbx_dbsync_compare_host_templates(zbx_dbsync_t *sync)
957 {
958 DB_ROW dbrow;
959 DB_RESULT result;
960 zbx_hashset_iter_t iter;
961 ZBX_DC_HTMPL *htmpl;
962 zbx_hashset_t htmpls;
963 int i;
964 zbx_uint64_pair_t ht_local, *ht;
965 char hostid_s[MAX_ID_LEN + 1], templateid_s[MAX_ID_LEN + 1];
966 char *del_row[2] = {hostid_s, templateid_s};
967
968 if (NULL == (result = DBselect(
969 "select hostid,templateid"
970 " from hosts_templates"
971 " order by hostid")))
972 {
973 return FAIL;
974 }
975
976 dbsync_prepare(sync, 2, NULL);
977
978 if (ZBX_DBSYNC_INIT == sync->mode)
979 {
980 sync->dbresult = result;
981 return SUCCEED;
982 }
983
984 zbx_hashset_create(&htmpls, 100, ZBX_DEFAULT_UINT64_PAIR_HASH_FUNC, ZBX_DEFAULT_UINT64_PAIR_COMPARE_FUNC);
985
986 /* index all host->template links */
987 zbx_hashset_iter_reset(&dbsync_env.cache->htmpls, &iter);
988 while (NULL != (htmpl = (ZBX_DC_HTMPL *)zbx_hashset_iter_next(&iter)))
989 {
990 ht_local.first = htmpl->hostid;
991
992 for (i = 0; i < htmpl->templateids.values_num; i++)
993 {
994 ht_local.second = htmpl->templateids.values[i];
995 zbx_hashset_insert(&htmpls, &ht_local, sizeof(ht_local));
996 }
997 }
998
999 /* add new rows, remove existing rows from index */
1000 while (NULL != (dbrow = DBfetch(result)))
1001 {
1002 ZBX_STR2UINT64(ht_local.first, dbrow[0]);
1003 ZBX_STR2UINT64(ht_local.second, dbrow[1]);
1004
1005 if (NULL == (ht = (zbx_uint64_pair_t *)zbx_hashset_search(&htmpls, &ht_local)))
1006 dbsync_add_row(sync, 0, ZBX_DBSYNC_ROW_ADD, dbrow);
1007 else
1008 zbx_hashset_remove_direct(&htmpls, ht);
1009 }
1010
1011 /* add removed rows */
1012 zbx_hashset_iter_reset(&htmpls, &iter);
1013 while (NULL != (ht = (zbx_uint64_pair_t *)zbx_hashset_iter_next(&iter)))
1014 {
1015 zbx_snprintf(hostid_s, sizeof(hostid_s), ZBX_FS_UI64, ht->first);
1016 zbx_snprintf(templateid_s, sizeof(templateid_s), ZBX_FS_UI64, ht->second);
1017 dbsync_add_row(sync, 0, ZBX_DBSYNC_ROW_REMOVE, del_row);
1018 }
1019
1020 DBfree_result(result);
1021 zbx_hashset_destroy(&htmpls);
1022
1023 return SUCCEED;
1024 }
1025
1026 /******************************************************************************
1027 * *
1028 * Function: dbsync_compare_global_macro *
1029 * *
1030 * Purpose: compares global macro table row with cached configuration data *
1031 * *
1032 * Parameter: gmacro - [IN] the cached global macro data *
1033 * dbrow - [IN] the database row *
1034 * *
1035 * Return value: SUCCEED - the row matches configuration data *
1036 * FAIL - otherwise *
1037 * *
1038 ******************************************************************************/
dbsync_compare_global_macro(const ZBX_DC_GMACRO * gmacro,const DB_ROW dbrow)1039 static int dbsync_compare_global_macro(const ZBX_DC_GMACRO *gmacro, const DB_ROW dbrow)
1040 {
1041 char *macro = NULL, *context = NULL;
1042 int ret = FAIL;
1043
1044 if (FAIL == dbsync_compare_uchar(dbrow[3], gmacro->type))
1045 return FAIL;
1046
1047 if (FAIL == dbsync_compare_str(dbrow[2], gmacro->value))
1048 return FAIL;
1049
1050 if (SUCCEED != zbx_user_macro_parse_dyn(dbrow[1], ¯o, &context, NULL, NULL))
1051 return FAIL;
1052
1053 if (0 != strcmp(gmacro->macro, macro))
1054 goto out;
1055
1056 if (NULL == context)
1057 {
1058 if (NULL != gmacro->context)
1059 goto out;
1060
1061 ret = SUCCEED;
1062 goto out;
1063 }
1064
1065 if (NULL == gmacro->context)
1066 goto out;
1067
1068 if (0 == strcmp(gmacro->context, context))
1069 ret = SUCCEED;
1070 out:
1071 zbx_free(macro);
1072 zbx_free(context);
1073
1074 return ret;
1075 }
1076
1077 /******************************************************************************
1078 * *
1079 * Function: zbx_dbsync_compare_global_macros *
1080 * *
1081 * Purpose: compares global macros table with cached configuration data *
1082 * *
1083 * Parameter: sync - [OUT] the changeset *
1084 * *
1085 * Return value: SUCCEED - the changeset was successfully calculated *
1086 * FAIL - otherwise *
1087 * *
1088 ******************************************************************************/
zbx_dbsync_compare_global_macros(zbx_dbsync_t * sync)1089 int zbx_dbsync_compare_global_macros(zbx_dbsync_t *sync)
1090 {
1091 DB_ROW dbrow;
1092 DB_RESULT result;
1093 zbx_hashset_t ids;
1094 zbx_hashset_iter_t iter;
1095 zbx_uint64_t rowid;
1096 ZBX_DC_GMACRO *macro;
1097
1098 if (NULL == (result = DBselect(
1099 "select globalmacroid,macro,value,type"
1100 " from globalmacro")))
1101 {
1102 return FAIL;
1103 }
1104
1105 dbsync_prepare(sync, 4, NULL);
1106
1107 if (ZBX_DBSYNC_INIT == sync->mode)
1108 {
1109 sync->dbresult = result;
1110 return SUCCEED;
1111 }
1112
1113 zbx_hashset_create(&ids, dbsync_env.cache->gmacros.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
1114 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1115
1116 while (NULL != (dbrow = DBfetch(result)))
1117 {
1118 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
1119
1120 ZBX_STR2UINT64(rowid, dbrow[0]);
1121 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
1122
1123 if (NULL == (macro = (ZBX_DC_GMACRO *)zbx_hashset_search(&dbsync_env.cache->gmacros, &rowid)))
1124 tag = ZBX_DBSYNC_ROW_ADD;
1125 else if (FAIL == dbsync_compare_global_macro(macro, dbrow))
1126 tag = ZBX_DBSYNC_ROW_UPDATE;
1127
1128 if (ZBX_DBSYNC_ROW_NONE != tag)
1129 dbsync_add_row(sync, rowid, tag, dbrow);
1130 }
1131
1132 zbx_hashset_iter_reset(&dbsync_env.cache->gmacros, &iter);
1133 while (NULL != (macro = (ZBX_DC_GMACRO *)zbx_hashset_iter_next(&iter)))
1134 {
1135 if (NULL == zbx_hashset_search(&ids, ¯o->globalmacroid))
1136 dbsync_add_row(sync, macro->globalmacroid, ZBX_DBSYNC_ROW_REMOVE, NULL);
1137 }
1138
1139 zbx_hashset_destroy(&ids);
1140 DBfree_result(result);
1141
1142 return SUCCEED;
1143 }
1144
1145 /******************************************************************************
1146 * *
1147 * Function: dbsync_compare_host_macro *
1148 * *
1149 * Purpose: compares host macro table row with cached configuration data *
1150 * *
1151 * Parameter: hmacro - [IN] the cached host macro data *
1152 * dbrow - [IN] the database row *
1153 * *
1154 * Return value: SUCCEED - the row matches configuration data *
1155 * FAIL - otherwise *
1156 * *
1157 ******************************************************************************/
dbsync_compare_host_macro(const ZBX_DC_HMACRO * hmacro,const DB_ROW dbrow)1158 static int dbsync_compare_host_macro(const ZBX_DC_HMACRO *hmacro, const DB_ROW dbrow)
1159 {
1160 char *macro = NULL, *context = NULL;
1161 int ret = FAIL;
1162
1163 if (FAIL == dbsync_compare_uchar(dbrow[4], hmacro->type))
1164 return FAIL;
1165
1166 if (FAIL == dbsync_compare_str(dbrow[3], hmacro->value))
1167 return FAIL;
1168
1169 if (FAIL == dbsync_compare_uint64(dbrow[1], hmacro->hostid))
1170 return FAIL;
1171
1172 if (SUCCEED != zbx_user_macro_parse_dyn(dbrow[2], ¯o, &context, NULL, NULL))
1173 return FAIL;
1174
1175 if (0 != strcmp(hmacro->macro, macro))
1176 goto out;
1177
1178 if (NULL == context)
1179 {
1180 if (NULL != hmacro->context)
1181 goto out;
1182
1183 ret = SUCCEED;
1184 goto out;
1185 }
1186
1187 if (NULL == hmacro->context)
1188 goto out;
1189
1190 if (0 == strcmp(hmacro->context, context))
1191 ret = SUCCEED;
1192 out:
1193 zbx_free(macro);
1194 zbx_free(context);
1195
1196 return ret;
1197 }
1198
1199 /******************************************************************************
1200 * *
1201 * Function: zbx_dbsync_compare_host_macros *
1202 * *
1203 * Purpose: compares global macros table with cached configuration data *
1204 * *
1205 * Parameter: sync - [OUT] the changeset *
1206 * *
1207 * Return value: SUCCEED - the changeset was successfully calculated *
1208 * FAIL - otherwise *
1209 * *
1210 ******************************************************************************/
zbx_dbsync_compare_host_macros(zbx_dbsync_t * sync)1211 int zbx_dbsync_compare_host_macros(zbx_dbsync_t *sync)
1212 {
1213 DB_ROW dbrow;
1214 DB_RESULT result;
1215 zbx_hashset_t ids;
1216 zbx_hashset_iter_t iter;
1217 zbx_uint64_t rowid;
1218 ZBX_DC_HMACRO *macro;
1219
1220 if (NULL == (result = DBselect(
1221 "select m.hostmacroid,m.hostid,m.macro,m.value,m.type"
1222 " from hostmacro m"
1223 " inner join hosts h on m.hostid=h.hostid"
1224 " where h.flags<>%d", ZBX_FLAG_DISCOVERY_PROTOTYPE)))
1225 {
1226 return FAIL;
1227 }
1228
1229 dbsync_prepare(sync, 5, NULL);
1230
1231 if (ZBX_DBSYNC_INIT == sync->mode)
1232 {
1233 sync->dbresult = result;
1234 return SUCCEED;
1235 }
1236
1237 zbx_hashset_create(&ids, dbsync_env.cache->hmacros.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
1238 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1239
1240 while (NULL != (dbrow = DBfetch(result)))
1241 {
1242 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
1243
1244 ZBX_STR2UINT64(rowid, dbrow[0]);
1245 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
1246
1247 if (NULL == (macro = (ZBX_DC_HMACRO *)zbx_hashset_search(&dbsync_env.cache->hmacros, &rowid)))
1248 tag = ZBX_DBSYNC_ROW_ADD;
1249 else if (FAIL == dbsync_compare_host_macro(macro, dbrow))
1250 tag = ZBX_DBSYNC_ROW_UPDATE;
1251
1252 if (ZBX_DBSYNC_ROW_NONE != tag)
1253 dbsync_add_row(sync, rowid, tag, dbrow);
1254 }
1255
1256 zbx_hashset_iter_reset(&dbsync_env.cache->hmacros, &iter);
1257 while (NULL != (macro = (ZBX_DC_HMACRO *)zbx_hashset_iter_next(&iter)))
1258 {
1259 if (NULL == zbx_hashset_search(&ids, ¯o->hostmacroid))
1260 dbsync_add_row(sync, macro->hostmacroid, ZBX_DBSYNC_ROW_REMOVE, NULL);
1261 }
1262
1263 zbx_hashset_destroy(&ids);
1264 DBfree_result(result);
1265
1266 return SUCCEED;
1267 }
1268
1269 /******************************************************************************
1270 * *
1271 * Function: dbsync_compare_interface *
1272 * *
1273 * Purpose: compares interface table row with cached configuration data *
1274 * *
1275 * Parameter: interface - [IN] the cached interface data *
1276 * dbrow - [IN] the database row *
1277 * *
1278 * Return value: SUCCEED - the row matches configuration data *
1279 * FAIL - otherwise *
1280 * *
1281 * Comments: User macros used in ip, dns fields will always make compare to *
1282 * fail. *
1283 * *
1284 ******************************************************************************/
dbsync_compare_interface(const ZBX_DC_INTERFACE * interface,const DB_ROW dbrow)1285 static int dbsync_compare_interface(const ZBX_DC_INTERFACE *interface, const DB_ROW dbrow)
1286 {
1287 ZBX_DC_SNMPINTERFACE *snmp;
1288
1289 if (FAIL == dbsync_compare_uint64(dbrow[1], interface->hostid))
1290 return FAIL;
1291
1292 if (FAIL == dbsync_compare_uchar(dbrow[2], interface->type))
1293 return FAIL;
1294
1295 if (FAIL == dbsync_compare_uchar(dbrow[3], interface->main))
1296 return FAIL;
1297
1298 if (FAIL == dbsync_compare_uchar(dbrow[4], interface->useip))
1299 return FAIL;
1300
1301 if (NULL != strstr(dbrow[5], "{$"))
1302 return FAIL;
1303
1304 if (FAIL == dbsync_compare_str(dbrow[5], interface->ip))
1305 return FAIL;
1306
1307 if (NULL != strstr(dbrow[6], "{$"))
1308 return FAIL;
1309
1310 if (FAIL == dbsync_compare_str(dbrow[6], interface->dns))
1311 return FAIL;
1312
1313 if (FAIL == dbsync_compare_str(dbrow[7], interface->port))
1314 return FAIL;
1315
1316 if (FAIL == dbsync_compare_uchar(dbrow[8], interface->available))
1317 return FAIL;
1318
1319 if (FAIL == dbsync_compare_int(dbrow[9], interface->disable_until))
1320 return FAIL;
1321
1322 if (FAIL == dbsync_compare_str(dbrow[10], interface->error))
1323 return FAIL;
1324
1325 if (FAIL == dbsync_compare_int(dbrow[11], interface->errors_from))
1326 return FAIL;
1327 /* reset_availability, items_num and availability_ts are excluded from the comparison */
1328
1329 snmp = (ZBX_DC_SNMPINTERFACE *)zbx_hashset_search(&dbsync_env.cache->interfaces_snmp,
1330 &interface->interfaceid);
1331
1332 if (INTERFACE_TYPE_SNMP == interface->type)
1333 {
1334 if (NULL == snmp || SUCCEED == DBis_null(dbrow[12])) /* should never happen */
1335 return FAIL;
1336
1337 if (FAIL == dbsync_compare_uchar(dbrow[12], snmp->version))
1338 return FAIL;
1339
1340 if (FAIL == dbsync_compare_uchar(dbrow[13], snmp->bulk))
1341 return FAIL;
1342
1343 if (FAIL == dbsync_compare_str(dbrow[14], snmp->community))
1344 return FAIL;
1345
1346 if (FAIL == dbsync_compare_str(dbrow[15], snmp->securityname))
1347 return FAIL;
1348
1349 if (FAIL == dbsync_compare_uchar(dbrow[16], snmp->securitylevel))
1350 return FAIL;
1351
1352 if (FAIL == dbsync_compare_str(dbrow[17], snmp->authpassphrase))
1353 return FAIL;
1354
1355 if (FAIL == dbsync_compare_str(dbrow[18], snmp->privpassphrase))
1356 return FAIL;
1357
1358 if (FAIL == dbsync_compare_uchar(dbrow[19], snmp->authprotocol))
1359 return FAIL;
1360
1361 if (FAIL == dbsync_compare_uchar(dbrow[20], snmp->privprotocol))
1362 return FAIL;
1363
1364 if (FAIL == dbsync_compare_str(dbrow[21], snmp->contextname))
1365 return FAIL;
1366 }
1367 else if (NULL != snmp)
1368 return FAIL;
1369
1370 return SUCCEED;
1371 }
1372
1373 /******************************************************************************
1374 * *
1375 * Function: zbx_dbsync_compare_interfaces *
1376 * *
1377 * Purpose: compares interfaces table with cached configuration data *
1378 * *
1379 * Parameter: sync - [OUT] the changeset *
1380 * *
1381 * Return value: SUCCEED - the changeset was successfully calculated *
1382 * FAIL - otherwise *
1383 * *
1384 ******************************************************************************/
zbx_dbsync_compare_interfaces(zbx_dbsync_t * sync)1385 int zbx_dbsync_compare_interfaces(zbx_dbsync_t *sync)
1386 {
1387 DB_ROW dbrow;
1388 DB_RESULT result;
1389 zbx_hashset_t ids;
1390 zbx_hashset_iter_t iter;
1391 zbx_uint64_t rowid;
1392 ZBX_DC_INTERFACE *interface;
1393
1394 if (NULL == (result = DBselect(
1395 "select i.interfaceid,i.hostid,i.type,i.main,i.useip,i.ip,i.dns,i.port,"
1396 "i.available,i.disable_until,i.error,i.errors_from,"
1397 "s.version,s.bulk,s.community,s.securityname,s.securitylevel,s.authpassphrase,s.privpassphrase,"
1398 "s.authprotocol,s.privprotocol,s.contextname"
1399 " from interface i"
1400 " left join interface_snmp s on i.interfaceid=s.interfaceid")))
1401 {
1402 return FAIL;
1403 }
1404
1405 dbsync_prepare(sync, 22, NULL);
1406
1407 if (ZBX_DBSYNC_INIT == sync->mode)
1408 {
1409 sync->dbresult = result;
1410 return SUCCEED;
1411 }
1412
1413 zbx_hashset_create(&ids, dbsync_env.cache->interfaces.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
1414 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1415
1416 while (NULL != (dbrow = DBfetch(result)))
1417 {
1418 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
1419
1420 ZBX_STR2UINT64(rowid, dbrow[0]);
1421 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
1422
1423 if (NULL == (interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&dbsync_env.cache->interfaces, &rowid)))
1424 tag = ZBX_DBSYNC_ROW_ADD;
1425 else if (FAIL == dbsync_compare_interface(interface, dbrow))
1426 tag = ZBX_DBSYNC_ROW_UPDATE;
1427
1428 if (ZBX_DBSYNC_ROW_NONE != tag)
1429 dbsync_add_row(sync, rowid, tag, dbrow);
1430 }
1431
1432 zbx_hashset_iter_reset(&dbsync_env.cache->interfaces, &iter);
1433 while (NULL != (interface = (ZBX_DC_INTERFACE *)zbx_hashset_iter_next(&iter)))
1434 {
1435 if (NULL == zbx_hashset_search(&ids, &interface->interfaceid))
1436 dbsync_add_row(sync, interface->interfaceid, ZBX_DBSYNC_ROW_REMOVE, NULL);
1437 }
1438
1439 zbx_hashset_destroy(&ids);
1440 DBfree_result(result);
1441
1442 return SUCCEED;
1443 }
1444
1445 /******************************************************************************
1446 * *
1447 * Function: dbsync_compare_item *
1448 * *
1449 * Purpose: compares items table row with cached configuration data *
1450 * *
1451 * Parameter: item - [IN] the cached item *
1452 * dbrow - [IN] the database row *
1453 * *
1454 * Return value: SUCCEED - the row matches configuration data *
1455 * FAIL - otherwise *
1456 * *
1457 ******************************************************************************/
dbsync_compare_item(const ZBX_DC_ITEM * item,const DB_ROW dbrow)1458 static int dbsync_compare_item(const ZBX_DC_ITEM *item, const DB_ROW dbrow)
1459 {
1460 ZBX_DC_NUMITEM *numitem;
1461 ZBX_DC_SNMPITEM *snmpitem;
1462 ZBX_DC_IPMIITEM *ipmiitem;
1463 ZBX_DC_TRAPITEM *trapitem;
1464 ZBX_DC_LOGITEM *logitem;
1465 ZBX_DC_DBITEM *dbitem;
1466 ZBX_DC_SSHITEM *sshitem;
1467 ZBX_DC_TELNETITEM *telnetitem;
1468 ZBX_DC_SIMPLEITEM *simpleitem;
1469 ZBX_DC_JMXITEM *jmxitem;
1470 ZBX_DC_CALCITEM *calcitem;
1471 ZBX_DC_DEPENDENTITEM *depitem;
1472 ZBX_DC_HOST *host;
1473 ZBX_DC_HTTPITEM *httpitem;
1474 ZBX_DC_SCRIPTITEM *scriptitem;
1475 unsigned char value_type, type;
1476 int history_sec, trends_sec;
1477
1478 if (FAIL == dbsync_compare_uint64(dbrow[1], item->hostid))
1479 return FAIL;
1480
1481 if (FAIL == dbsync_compare_uint64(dbrow[48], item->templateid))
1482 return FAIL;
1483
1484 if (FAIL == dbsync_compare_uint64(dbrow[49], item->parent_itemid))
1485 return FAIL;
1486
1487 if (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&dbsync_env.cache->hosts, &item->hostid)))
1488 return FAIL;
1489
1490 if (0 != host->update_items)
1491 return FAIL;
1492
1493 if (FAIL == dbsync_compare_uchar(dbrow[2], item->status))
1494 return FAIL;
1495
1496 ZBX_STR2UCHAR(type, dbrow[3]);
1497 if (item->type != type)
1498 return FAIL;
1499
1500 if (FAIL == dbsync_compare_uchar(dbrow[18], item->flags))
1501 return FAIL;
1502
1503 if (FAIL == dbsync_compare_uint64(dbrow[19], item->interfaceid))
1504 return FAIL;
1505
1506 if (SUCCEED != is_time_suffix(dbrow[22], &history_sec, ZBX_LENGTH_UNLIMITED))
1507 history_sec = ZBX_HK_PERIOD_MAX;
1508
1509 if (0 != history_sec && ZBX_HK_OPTION_ENABLED == dbsync_env.cache->config->hk.history_global)
1510 history_sec = dbsync_env.cache->config->hk.history;
1511
1512 if (item->history != (0 != history_sec))
1513 return FAIL;
1514
1515 if (history_sec != item->history_sec)
1516 return FAIL;
1517
1518 if (FAIL == dbsync_compare_uchar(dbrow[24], item->inventory_link))
1519 return FAIL;
1520
1521 if (FAIL == dbsync_compare_uint64(dbrow[25], item->valuemapid))
1522 return FAIL;
1523
1524 ZBX_STR2UCHAR(value_type, dbrow[4]);
1525 if (item->value_type != value_type)
1526 return FAIL;
1527
1528 if (FAIL == dbsync_compare_str(dbrow[5], item->key))
1529 return FAIL;
1530
1531 if (FAIL == dbsync_compare_str(dbrow[8], item->delay))
1532 return FAIL;
1533
1534 numitem = (ZBX_DC_NUMITEM *)zbx_hashset_search(&dbsync_env.cache->numitems, &item->itemid);
1535 if (ITEM_VALUE_TYPE_FLOAT == value_type || ITEM_VALUE_TYPE_UINT64 == value_type)
1536 {
1537 if (NULL == numitem)
1538 return FAIL;
1539
1540 if (SUCCEED != is_time_suffix(dbrow[23], &trends_sec, ZBX_LENGTH_UNLIMITED))
1541 trends_sec = ZBX_HK_PERIOD_MAX;
1542
1543 if (0 != trends_sec && ZBX_HK_OPTION_ENABLED == dbsync_env.cache->config->hk.trends_global)
1544 trends_sec = dbsync_env.cache->config->hk.trends;
1545
1546 if (numitem->trends != (0 != trends_sec))
1547 return FAIL;
1548
1549 if (numitem->trends_sec != trends_sec)
1550 return FAIL;
1551
1552 if (FAIL == dbsync_compare_str(dbrow[26], numitem->units))
1553 return FAIL;
1554 }
1555 else if (NULL != numitem)
1556 return FAIL;
1557
1558 snmpitem = (ZBX_DC_SNMPITEM *)zbx_hashset_search(&dbsync_env.cache->snmpitems, &item->itemid);
1559 if (ITEM_TYPE_SNMP == type)
1560 {
1561 if (NULL == snmpitem)
1562 return FAIL;
1563
1564 if (FAIL == dbsync_compare_str(dbrow[6], snmpitem->snmp_oid))
1565 return FAIL;
1566 }
1567 else if (NULL != snmpitem)
1568 return FAIL;
1569
1570 ipmiitem = (ZBX_DC_IPMIITEM *)zbx_hashset_search(&dbsync_env.cache->ipmiitems, &item->itemid);
1571 if (ITEM_TYPE_IPMI == item->type)
1572 {
1573 if (NULL == ipmiitem)
1574 return FAIL;
1575
1576 if (FAIL == dbsync_compare_str(dbrow[7], ipmiitem->ipmi_sensor))
1577 return FAIL;
1578 }
1579 else if (NULL != ipmiitem)
1580 return FAIL;
1581
1582 trapitem = (ZBX_DC_TRAPITEM *)zbx_hashset_search(&dbsync_env.cache->trapitems, &item->itemid);
1583 if (ITEM_TYPE_TRAPPER == item->type && '\0' != *dbrow[9])
1584 {
1585 zbx_trim_str_list(dbrow[9], ',');
1586
1587 if (NULL == trapitem)
1588 return FAIL;
1589
1590 if (FAIL == dbsync_compare_str(dbrow[9], trapitem->trapper_hosts))
1591 return FAIL;
1592 }
1593 else if (NULL != trapitem)
1594 return FAIL;
1595
1596 logitem = (ZBX_DC_LOGITEM *)zbx_hashset_search(&dbsync_env.cache->logitems, &item->itemid);
1597 if (ITEM_VALUE_TYPE_LOG == item->value_type && '\0' != *dbrow[10])
1598 {
1599 if (NULL == logitem)
1600 return FAIL;
1601
1602 if (FAIL == dbsync_compare_str(dbrow[10], logitem->logtimefmt))
1603 return FAIL;
1604 }
1605 else if (NULL != logitem)
1606 return FAIL;
1607
1608 dbitem = (ZBX_DC_DBITEM *)zbx_hashset_search(&dbsync_env.cache->dbitems, &item->itemid);
1609 if (ITEM_TYPE_DB_MONITOR == item->type && '\0' != *dbrow[11])
1610 {
1611 if (NULL == dbitem)
1612 return FAIL;
1613
1614 if (FAIL == dbsync_compare_str(dbrow[11], dbitem->params))
1615 return FAIL;
1616
1617 if (FAIL == dbsync_compare_str(dbrow[14], dbitem->username))
1618 return FAIL;
1619
1620 if (FAIL == dbsync_compare_str(dbrow[15], dbitem->password))
1621 return FAIL;
1622 }
1623 else if (NULL != dbitem)
1624 return FAIL;
1625
1626 sshitem = (ZBX_DC_SSHITEM *)zbx_hashset_search(&dbsync_env.cache->sshitems, &item->itemid);
1627 if (ITEM_TYPE_SSH == item->type)
1628 {
1629 if (NULL == sshitem)
1630 return FAIL;
1631
1632 if (FAIL == dbsync_compare_uchar(dbrow[13], sshitem->authtype))
1633 return FAIL;
1634
1635 if (FAIL == dbsync_compare_str(dbrow[14], sshitem->username))
1636 return FAIL;
1637
1638 if (FAIL == dbsync_compare_str(dbrow[15], sshitem->password))
1639 return FAIL;
1640
1641 if (FAIL == dbsync_compare_str(dbrow[16], sshitem->publickey))
1642 return FAIL;
1643
1644 if (FAIL == dbsync_compare_str(dbrow[17], sshitem->privatekey))
1645 return FAIL;
1646
1647 if (FAIL == dbsync_compare_str(dbrow[13], sshitem->params))
1648 return FAIL;
1649 }
1650 else if (NULL != sshitem)
1651 return FAIL;
1652
1653 telnetitem = (ZBX_DC_TELNETITEM *)zbx_hashset_search(&dbsync_env.cache->telnetitems, &item->itemid);
1654 if (ITEM_TYPE_TELNET == item->type)
1655 {
1656 if (NULL == telnetitem)
1657 return FAIL;
1658
1659 if (FAIL == dbsync_compare_str(dbrow[14], telnetitem->username))
1660 return FAIL;
1661
1662 if (FAIL == dbsync_compare_str(dbrow[15], telnetitem->password))
1663 return FAIL;
1664
1665 if (FAIL == dbsync_compare_str(dbrow[11], telnetitem->params))
1666 return FAIL;
1667 }
1668 else if (NULL != telnetitem)
1669 return FAIL;
1670
1671 scriptitem = (ZBX_DC_SCRIPTITEM *)zbx_hashset_search(&dbsync_env.cache->scriptitems, &item->itemid);
1672 if (ITEM_TYPE_SCRIPT == item->type)
1673 {
1674 if (NULL == scriptitem)
1675 return FAIL;
1676
1677 if (FAIL == dbsync_compare_str(dbrow[14], scriptitem->timeout))
1678 return FAIL;
1679
1680 if (FAIL == dbsync_compare_str(dbrow[11], scriptitem->script))
1681 return FAIL;
1682 }
1683 else if (NULL != scriptitem)
1684 return FAIL;
1685
1686 simpleitem = (ZBX_DC_SIMPLEITEM *)zbx_hashset_search(&dbsync_env.cache->simpleitems, &item->itemid);
1687 if (ITEM_TYPE_SIMPLE == item->type)
1688 {
1689 if (NULL == simpleitem)
1690 return FAIL;
1691
1692 if (FAIL == dbsync_compare_str(dbrow[14], simpleitem->username))
1693 return FAIL;
1694
1695 if (FAIL == dbsync_compare_str(dbrow[15], simpleitem->password))
1696 return FAIL;
1697 }
1698 else if (NULL != simpleitem)
1699 return FAIL;
1700
1701 jmxitem = (ZBX_DC_JMXITEM *)zbx_hashset_search(&dbsync_env.cache->jmxitems, &item->itemid);
1702 if (ITEM_TYPE_JMX == item->type)
1703 {
1704 if (NULL == jmxitem)
1705 return FAIL;
1706
1707 if (FAIL == dbsync_compare_str(dbrow[14], jmxitem->username))
1708 return FAIL;
1709
1710 if (FAIL == dbsync_compare_str(dbrow[15], jmxitem->password))
1711 return FAIL;
1712
1713 if (FAIL == dbsync_compare_str(dbrow[28], jmxitem->jmx_endpoint))
1714 return FAIL;
1715 }
1716 else if (NULL != jmxitem)
1717 return FAIL;
1718
1719 calcitem = (ZBX_DC_CALCITEM *)zbx_hashset_search(&dbsync_env.cache->calcitems, &item->itemid);
1720 if (ITEM_TYPE_CALCULATED == item->type)
1721 {
1722 if (NULL == calcitem)
1723 return FAIL;
1724
1725 if (FAIL == dbsync_compare_str(dbrow[11], calcitem->params))
1726 return FAIL;
1727
1728 if (FAIL == dbsync_compare_serialized_expression(dbrow[50], calcitem->formula_bin))
1729 return FAIL;
1730 }
1731 else if (NULL != calcitem)
1732 return FAIL;
1733
1734 depitem = (ZBX_DC_DEPENDENTITEM *)zbx_hashset_search(&dbsync_env.cache->dependentitems, &item->itemid);
1735 if (ITEM_TYPE_DEPENDENT == item->type)
1736 {
1737 if (NULL == depitem)
1738 return FAIL;
1739
1740 if (FAIL == dbsync_compare_uint64(dbrow[29], depitem->master_itemid))
1741 return FAIL;
1742 }
1743 else if (NULL != depitem)
1744 return FAIL;
1745
1746 httpitem = (ZBX_DC_HTTPITEM *)zbx_hashset_search(&dbsync_env.cache->httpitems, &item->itemid);
1747 if (ITEM_TYPE_HTTPAGENT == item->type)
1748 {
1749 zbx_trim_str_list(dbrow[9], ',');
1750
1751 if (NULL == httpitem)
1752 return FAIL;
1753
1754 if (FAIL == dbsync_compare_str(dbrow[30], httpitem->timeout))
1755 return FAIL;
1756
1757 if (FAIL == dbsync_compare_str(dbrow[31], httpitem->url))
1758 return FAIL;
1759
1760 if (FAIL == dbsync_compare_str(dbrow[32], httpitem->query_fields))
1761 return FAIL;
1762
1763 if (FAIL == dbsync_compare_str(dbrow[33], httpitem->posts))
1764 return FAIL;
1765
1766 if (FAIL == dbsync_compare_str(dbrow[34], httpitem->status_codes))
1767 return FAIL;
1768
1769 if (FAIL == dbsync_compare_uchar(dbrow[35], httpitem->follow_redirects))
1770 return FAIL;
1771
1772 if (FAIL == dbsync_compare_uchar(dbrow[36], httpitem->post_type))
1773 return FAIL;
1774
1775 if (FAIL == dbsync_compare_str(dbrow[37], httpitem->http_proxy))
1776 return FAIL;
1777
1778 if (FAIL == dbsync_compare_str(dbrow[38], httpitem->headers))
1779 return FAIL;
1780
1781 if (FAIL == dbsync_compare_uchar(dbrow[39], httpitem->retrieve_mode))
1782 return FAIL;
1783
1784 if (FAIL == dbsync_compare_uchar(dbrow[40], httpitem->request_method))
1785 return FAIL;
1786
1787 if (FAIL == dbsync_compare_uchar(dbrow[41], httpitem->output_format))
1788 return FAIL;
1789
1790 if (FAIL == dbsync_compare_str(dbrow[42], httpitem->ssl_cert_file))
1791 return FAIL;
1792
1793 if (FAIL == dbsync_compare_str(dbrow[43], httpitem->ssl_key_file))
1794 return FAIL;
1795
1796 if (FAIL == dbsync_compare_str(dbrow[44], httpitem->ssl_key_password))
1797 return FAIL;
1798
1799 if (FAIL == dbsync_compare_uchar(dbrow[45], httpitem->verify_peer))
1800 return FAIL;
1801
1802 if (FAIL == dbsync_compare_uchar(dbrow[46], httpitem->verify_host))
1803 return FAIL;
1804
1805 if (FAIL == dbsync_compare_uchar(dbrow[13], httpitem->authtype))
1806 return FAIL;
1807
1808 if (FAIL == dbsync_compare_str(dbrow[14], httpitem->username))
1809 return FAIL;
1810
1811 if (FAIL == dbsync_compare_str(dbrow[15], httpitem->password))
1812 return FAIL;
1813
1814 if (FAIL == dbsync_compare_uchar(dbrow[47], httpitem->allow_traps))
1815 return FAIL;
1816
1817 if (FAIL == dbsync_compare_str(dbrow[10], httpitem->trapper_hosts))
1818 return FAIL;
1819 }
1820 else if (NULL != httpitem)
1821 return FAIL;
1822
1823 return SUCCEED;
1824 }
1825
1826 /******************************************************************************
1827 * *
1828 * Function: dbsync_item_preproc_row *
1829 * *
1830 * Purpose: applies necessary preprocessing before row is compared/used *
1831 * *
1832 * Parameter: row - [IN] the row to preprocess *
1833 * *
1834 * Return value: the preprocessed row *
1835 * *
1836 * Comments: The row preprocessing can be used to expand user macros in *
1837 * some columns. *
1838 * *
1839 ******************************************************************************/
dbsync_item_preproc_row(char ** row)1840 static char **dbsync_item_preproc_row(char **row)
1841 {
1842 #define ZBX_DBSYNC_ITEM_COLUMN_DELAY 0x01
1843 #define ZBX_DBSYNC_ITEM_COLUMN_HISTORY 0x02
1844 #define ZBX_DBSYNC_ITEM_COLUMN_TRENDS 0x04
1845 #define ZBX_DBSYNC_ITEM_COLUMN_CALCITEM 0x08
1846
1847 zbx_uint64_t hostid;
1848 unsigned char flags = 0, type;
1849
1850 /* return the original row if user macros are not used in target columns */
1851
1852 ZBX_STR2UCHAR(type, row[3]);
1853
1854 if (SUCCEED == dbsync_check_row_macros(row, 8))
1855 flags |= ZBX_DBSYNC_ITEM_COLUMN_DELAY;
1856
1857 if (SUCCEED == dbsync_check_row_macros(row, 23))
1858 flags |= ZBX_DBSYNC_ITEM_COLUMN_HISTORY;
1859
1860 if (SUCCEED == dbsync_check_row_macros(row, 24))
1861 flags |= ZBX_DBSYNC_ITEM_COLUMN_TRENDS;
1862
1863 if (ITEM_TYPE_CALCULATED == type)
1864 flags |= ZBX_DBSYNC_ITEM_COLUMN_CALCITEM;
1865
1866 if (0 == flags)
1867 return row;
1868
1869 /* get associated host identifier */
1870 ZBX_STR2UINT64(hostid, row[1]);
1871
1872 /* expand user macros */
1873
1874 if (0 != (flags & ZBX_DBSYNC_ITEM_COLUMN_DELAY))
1875 row[8] = dc_expand_user_macros(row[8], &hostid, 1);
1876
1877 if (0 != (flags & ZBX_DBSYNC_ITEM_COLUMN_HISTORY))
1878 row[22] = dc_expand_user_macros(row[22], &hostid, 1);
1879
1880 if (0 != (flags & ZBX_DBSYNC_ITEM_COLUMN_TRENDS))
1881 row[23] = dc_expand_user_macros(row[23], &hostid, 1);
1882
1883 if (ITEM_TYPE_CALCULATED == type)
1884 {
1885 zbx_eval_context_t ctx;
1886 char *error = NULL;
1887
1888 if (FAIL == zbx_eval_parse_expression(&ctx, row[11], ZBX_EVAL_PARSE_CALC_EXPRESSSION, &error))
1889 {
1890 zbx_eval_set_exception(&ctx, zbx_dsprintf(NULL, "Cannot parse formula: %s", error));
1891 zbx_free(error);
1892 }
1893 else
1894 {
1895 if (SUCCEED != zbx_eval_expand_user_macros(&ctx, &hostid, 1, dc_expand_user_macros_len, &error))
1896 {
1897 zbx_eval_clear(&ctx);
1898 zbx_eval_set_exception(&ctx, zbx_dsprintf(NULL, "Cannot evaluate formula: %s", error));
1899 zbx_free(error);
1900 }
1901 }
1902
1903 row[50] = encode_expression(&ctx);
1904 zbx_eval_clear(&ctx);
1905 }
1906
1907 return row;
1908
1909 #undef ZBX_DBSYNC_ITEM_COLUMN_DELAY
1910 #undef ZBX_DBSYNC_ITEM_COLUMN_HISTORY
1911 #undef ZBX_DBSYNC_ITEM_COLUMN_TRENDS
1912 }
1913
1914 /******************************************************************************
1915 * *
1916 * Function: zbx_dbsync_compare_items *
1917 * *
1918 * Purpose: compares items table with cached configuration data *
1919 * *
1920 * Return value: SUCCEED - the changeset was successfully calculated *
1921 * FAIL - otherwise *
1922 * *
1923 ******************************************************************************/
zbx_dbsync_compare_items(zbx_dbsync_t * sync)1924 int zbx_dbsync_compare_items(zbx_dbsync_t *sync)
1925 {
1926 DB_ROW dbrow;
1927 DB_RESULT result;
1928 zbx_hashset_t ids;
1929 zbx_hashset_iter_t iter;
1930 zbx_uint64_t rowid;
1931 ZBX_DC_ITEM *item;
1932 char **row;
1933
1934 if (NULL == (result = DBselect(
1935 "select i.itemid,i.hostid,i.status,i.type,i.value_type,i.key_,i.snmp_oid,i.ipmi_sensor,i.delay,"
1936 "i.trapper_hosts,i.logtimefmt,i.params,ir.state,i.authtype,i.username,i.password,"
1937 "i.publickey,i.privatekey,i.flags,i.interfaceid,ir.lastlogsize,ir.mtime,"
1938 "i.history,i.trends,i.inventory_link,i.valuemapid,i.units,ir.error,i.jmx_endpoint,"
1939 "i.master_itemid,i.timeout,i.url,i.query_fields,i.posts,i.status_codes,"
1940 "i.follow_redirects,i.post_type,i.http_proxy,i.headers,i.retrieve_mode,"
1941 "i.request_method,i.output_format,i.ssl_cert_file,i.ssl_key_file,i.ssl_key_password,"
1942 "i.verify_peer,i.verify_host,i.allow_traps,i.templateid,id.parent_itemid,null"
1943 " from items i"
1944 " inner join hosts h on i.hostid=h.hostid"
1945 " left join item_discovery id on i.itemid=id.itemid"
1946 " join item_rtdata ir on i.itemid=ir.itemid"
1947 " where h.status in (%d,%d) and i.flags<>%d",
1948 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED, ZBX_FLAG_DISCOVERY_PROTOTYPE)))
1949
1950 {
1951 return FAIL;
1952 }
1953
1954 dbsync_prepare(sync, 51, dbsync_item_preproc_row);
1955
1956 if (ZBX_DBSYNC_INIT == sync->mode)
1957 {
1958 sync->dbresult = result;
1959 return SUCCEED;
1960 }
1961
1962 zbx_hashset_create(&ids, dbsync_env.cache->items.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
1963 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1964
1965 while (NULL != (dbrow = DBfetch(result)))
1966 {
1967 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
1968
1969 ZBX_STR2UINT64(rowid, dbrow[0]);
1970 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
1971
1972 row = dbsync_preproc_row(sync, dbrow);
1973
1974 if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&dbsync_env.cache->items, &rowid)))
1975 tag = ZBX_DBSYNC_ROW_ADD;
1976 else if (FAIL == dbsync_compare_item(item, row))
1977 tag = ZBX_DBSYNC_ROW_UPDATE;
1978
1979 if (ZBX_DBSYNC_ROW_NONE != tag)
1980 dbsync_add_row(sync, rowid, tag, row);
1981 }
1982
1983 zbx_hashset_iter_reset(&dbsync_env.cache->items, &iter);
1984 while (NULL != (item = (ZBX_DC_ITEM *)zbx_hashset_iter_next(&iter)))
1985 {
1986 if (NULL == zbx_hashset_search(&ids, &item->itemid))
1987 dbsync_add_row(sync, item->itemid, ZBX_DBSYNC_ROW_REMOVE, NULL);
1988 }
1989
1990 zbx_hashset_destroy(&ids);
1991 DBfree_result(result);
1992
1993 return SUCCEED;
1994 }
1995
dbsync_compare_template_item(const ZBX_DC_TEMPLATE_ITEM * item,const DB_ROW dbrow)1996 static int dbsync_compare_template_item(const ZBX_DC_TEMPLATE_ITEM *item, const DB_ROW dbrow)
1997 {
1998 if (FAIL == dbsync_compare_uint64(dbrow[1], item->hostid))
1999 return FAIL;
2000
2001 if (FAIL == dbsync_compare_uint64(dbrow[2], item->templateid))
2002 return FAIL;
2003
2004 return SUCCEED;
2005 }
2006
2007 /******************************************************************************
2008 * *
2009 * Function: zbx_dbsync_compare_template_items *
2010 * *
2011 * Purpose: compares items that belong to templates with configuration cache *
2012 * *
2013 * Return value: SUCCEED - the changeset was successfully calculated *
2014 * FAIL - otherwise *
2015 * *
2016 ******************************************************************************/
zbx_dbsync_compare_template_items(zbx_dbsync_t * sync)2017 int zbx_dbsync_compare_template_items(zbx_dbsync_t *sync)
2018 {
2019 DB_ROW dbrow;
2020 DB_RESULT result;
2021 zbx_hashset_t ids;
2022 zbx_hashset_iter_t iter;
2023 zbx_uint64_t rowid;
2024 ZBX_DC_TEMPLATE_ITEM *item;
2025 char **row;
2026
2027 if (NULL == (result = DBselect(
2028 "select i.itemid,i.hostid,i.templateid from items i inner join hosts h on i.hostid=h.hostid"
2029 " where h.status=%d", HOST_STATUS_TEMPLATE)))
2030 {
2031 return FAIL;
2032 }
2033
2034 dbsync_prepare(sync, 3, NULL);
2035
2036 if (ZBX_DBSYNC_INIT == sync->mode)
2037 {
2038 sync->dbresult = result;
2039 return SUCCEED;
2040 }
2041
2042 zbx_hashset_create(&ids, dbsync_env.cache->template_items.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
2043 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2044
2045 while (NULL != (dbrow = DBfetch(result)))
2046 {
2047 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
2048
2049 ZBX_STR2UINT64(rowid, dbrow[0]);
2050 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
2051
2052 row = dbsync_preproc_row(sync, dbrow);
2053
2054 if (NULL == (item = (ZBX_DC_TEMPLATE_ITEM *)zbx_hashset_search(&dbsync_env.cache->template_items,
2055 &rowid)))
2056 {
2057 tag = ZBX_DBSYNC_ROW_ADD;
2058 }
2059 else if (FAIL == dbsync_compare_template_item(item, row))
2060 tag = ZBX_DBSYNC_ROW_UPDATE;
2061
2062 if (ZBX_DBSYNC_ROW_NONE != tag)
2063 dbsync_add_row(sync, rowid, tag, row);
2064 }
2065
2066 zbx_hashset_iter_reset(&dbsync_env.cache->template_items, &iter);
2067 while (NULL != (item = (ZBX_DC_TEMPLATE_ITEM *)zbx_hashset_iter_next(&iter)))
2068 {
2069 if (NULL == zbx_hashset_search(&ids, &item->itemid))
2070 dbsync_add_row(sync, item->itemid, ZBX_DBSYNC_ROW_REMOVE, NULL);
2071 }
2072
2073 zbx_hashset_destroy(&ids);
2074 DBfree_result(result);
2075
2076 return SUCCEED;
2077 }
2078
dbsync_compare_prototype_item(const ZBX_DC_PROTOTYPE_ITEM * item,const DB_ROW dbrow)2079 static int dbsync_compare_prototype_item(const ZBX_DC_PROTOTYPE_ITEM *item, const DB_ROW dbrow)
2080 {
2081 if (FAIL == dbsync_compare_uint64(dbrow[1], item->hostid))
2082 return FAIL;
2083
2084 if (FAIL == dbsync_compare_uint64(dbrow[2], item->templateid))
2085 return FAIL;
2086
2087 return SUCCEED;
2088 }
2089
2090 /******************************************************************************
2091 * *
2092 * Function: zbx_dbsync_compare_prototype_items *
2093 * *
2094 * Purpose: compares lld item prototypes with configuration cache *
2095 * *
2096 * Return value: SUCCEED - the changeset was successfully calculated *
2097 * FAIL - otherwise *
2098 * *
2099 ******************************************************************************/
zbx_dbsync_compare_prototype_items(zbx_dbsync_t * sync)2100 int zbx_dbsync_compare_prototype_items(zbx_dbsync_t *sync)
2101 {
2102 DB_ROW dbrow;
2103 DB_RESULT result;
2104 zbx_hashset_t ids;
2105 zbx_hashset_iter_t iter;
2106 zbx_uint64_t rowid;
2107 ZBX_DC_PROTOTYPE_ITEM *item;
2108 char **row;
2109
2110 if (NULL == (result = DBselect(
2111 "select i.itemid,i.hostid,i.templateid from items i where i.flags=%d",
2112 ZBX_FLAG_DISCOVERY_PROTOTYPE)))
2113 {
2114 return FAIL;
2115 }
2116
2117 dbsync_prepare(sync, 3, NULL);
2118
2119 if (ZBX_DBSYNC_INIT == sync->mode)
2120 {
2121 sync->dbresult = result;
2122 return SUCCEED;
2123 }
2124
2125 zbx_hashset_create(&ids, dbsync_env.cache->prototype_items.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
2126 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2127
2128 while (NULL != (dbrow = DBfetch(result)))
2129 {
2130 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
2131
2132 ZBX_STR2UINT64(rowid, dbrow[0]);
2133 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
2134
2135 row = dbsync_preproc_row(sync, dbrow);
2136
2137 if (NULL == (item = (ZBX_DC_PROTOTYPE_ITEM *)zbx_hashset_search(&dbsync_env.cache->prototype_items,
2138 &rowid)))
2139 {
2140 tag = ZBX_DBSYNC_ROW_ADD;
2141 }
2142 else if (FAIL == dbsync_compare_prototype_item(item, row))
2143 tag = ZBX_DBSYNC_ROW_UPDATE;
2144
2145 if (ZBX_DBSYNC_ROW_NONE != tag)
2146 dbsync_add_row(sync, rowid, tag, row);
2147 }
2148
2149 zbx_hashset_iter_reset(&dbsync_env.cache->prototype_items, &iter);
2150 while (NULL != (item = (ZBX_DC_PROTOTYPE_ITEM *)zbx_hashset_iter_next(&iter)))
2151 {
2152 if (NULL == zbx_hashset_search(&ids, &item->itemid))
2153 dbsync_add_row(sync, item->itemid, ZBX_DBSYNC_ROW_REMOVE, NULL);
2154 }
2155
2156 zbx_hashset_destroy(&ids);
2157 DBfree_result(result);
2158
2159 return SUCCEED;
2160 }
2161
2162 /******************************************************************************
2163 * *
2164 * Function: dbsync_compare_trigger *
2165 * *
2166 * Purpose: compares triggers table row with cached configuration data *
2167 * *
2168 * Parameter: trigger - [IN] the cached trigger *
2169 * dbrow - [IN] the database row *
2170 * *
2171 * Return value: SUCCEED - the row matches configuration data *
2172 * FAIL - otherwise *
2173 * *
2174 ******************************************************************************/
dbsync_compare_trigger(const ZBX_DC_TRIGGER * trigger,const DB_ROW dbrow)2175 static int dbsync_compare_trigger(const ZBX_DC_TRIGGER *trigger, const DB_ROW dbrow)
2176 {
2177 if (FAIL == dbsync_compare_str(dbrow[1], trigger->description))
2178 return FAIL;
2179
2180 if (FAIL == dbsync_compare_str(dbrow[2], trigger->expression))
2181 return FAIL;
2182
2183 if (FAIL == dbsync_compare_uchar(dbrow[4], trigger->priority))
2184 return FAIL;
2185
2186 if (FAIL == dbsync_compare_uchar(dbrow[5], trigger->type))
2187 return FAIL;
2188
2189 if (FAIL == dbsync_compare_uchar(dbrow[9], trigger->status))
2190 return FAIL;
2191
2192 if (FAIL == dbsync_compare_uchar(dbrow[10], trigger->recovery_mode))
2193 return FAIL;
2194
2195 if (FAIL == dbsync_compare_str(dbrow[11], trigger->recovery_expression))
2196 return FAIL;
2197
2198 if (FAIL == dbsync_compare_uchar(dbrow[12], trigger->correlation_mode))
2199 return FAIL;
2200
2201 if (FAIL == dbsync_compare_str(dbrow[13], trigger->correlation_tag))
2202 return FAIL;
2203
2204 if (FAIL == dbsync_compare_str(dbrow[14], trigger->opdata))
2205 return FAIL;
2206
2207 if (FAIL == dbsync_compare_str(dbrow[15], trigger->event_name))
2208 return FAIL;
2209
2210 if (FAIL == dbsync_compare_serialized_expression(dbrow[16], trigger->expression_bin))
2211 return FAIL;
2212
2213 if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == atoi(dbrow[10]) &&
2214 FAIL == dbsync_compare_serialized_expression(dbrow[17], trigger->recovery_expression_bin))
2215 {
2216 return FAIL;
2217 }
2218
2219 return SUCCEED;
2220 }
2221
2222 /******************************************************************************
2223 * *
2224 * Function: dbsync_trigger_preproc_row *
2225 * *
2226 * Purpose: applies necessary preprocessing before row is compared/used *
2227 * *
2228 * Parameter: row - [IN] the row to preprocess *
2229 * *
2230 * Return value: the preprocessed row *
2231 * *
2232 * Comments: The row preprocessing can be used to expand user macros in *
2233 * some columns. *
2234 * During preprocessing trigger expression/recovery expression are *
2235 * parsed, serialized and stored as base64 strings into 16,17 *
2236 * columns. *
2237 * *
2238 ******************************************************************************/
dbsync_trigger_preproc_row(char ** row)2239 static char **dbsync_trigger_preproc_row(char **row)
2240 {
2241 zbx_vector_uint64_t hostids, functionids;
2242 zbx_eval_context_t ctx, ctx_r;
2243 char *error = NULL;
2244 unsigned char mode, timer = ZBX_TRIGGER_TIMER_DEFAULT;
2245
2246 zbx_vector_uint64_create(&hostids);
2247 zbx_vector_uint64_create(&functionids);
2248
2249 if (FAIL == zbx_eval_parse_expression(&ctx, row[2], ZBX_EVAL_TRIGGER_EXPRESSION, &error))
2250 {
2251 zbx_eval_set_exception(&ctx, zbx_dsprintf(NULL, "cannot parse trigger expression: %s", error));
2252 zbx_free(error);
2253 }
2254 else
2255 {
2256 zbx_eval_get_functionids(&ctx, &functionids);
2257
2258 if (SUCCEED == zbx_eval_check_timer_functions(&ctx))
2259 timer |= ZBX_TRIGGER_TIMER_EXPRESSION;
2260 }
2261
2262 ZBX_STR2UCHAR(mode, row[10]);
2263
2264 if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == mode)
2265 {
2266 if (FAIL == zbx_eval_parse_expression(&ctx_r, row[11], ZBX_EVAL_TRIGGER_EXPRESSION, &error))
2267 {
2268 zbx_eval_set_exception(&ctx_r, zbx_dsprintf(NULL, "cannot parse trigger recovery"
2269 " expression: %s", error));
2270 zbx_free(error);
2271 }
2272 else
2273 {
2274 zbx_eval_get_functionids(&ctx_r, &functionids);
2275
2276 if (SUCCEED == zbx_eval_check_timer_functions(&ctx_r))
2277 timer |= ZBX_TRIGGER_TIMER_RECOVERY_EXPRESSION;
2278 }
2279 }
2280
2281 zbx_vector_uint64_sort(&functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2282 zbx_vector_uint64_uniq(&functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2283
2284 dc_get_hostids_by_functionids(functionids.values, functionids.values_num, &hostids);
2285
2286 if (NULL != ctx.expression)
2287 {
2288 if (SUCCEED != zbx_eval_expand_user_macros(&ctx, hostids.values, hostids.values_num,
2289 dc_expand_user_macros_len, &error))
2290 {
2291 zbx_eval_clear(&ctx);
2292 zbx_eval_set_exception(&ctx, zbx_dsprintf(NULL, "cannot evaluate expression: %s", error));
2293 zbx_free(error);
2294 }
2295 }
2296
2297 row[16] = encode_expression(&ctx);
2298 zbx_eval_clear(&ctx);
2299
2300 if (TRIGGER_RECOVERY_MODE_RECOVERY_EXPRESSION == mode)
2301 {
2302 if (NULL != ctx_r.expression)
2303 {
2304 if (SUCCEED != zbx_eval_expand_user_macros(&ctx_r, hostids.values, hostids.values_num,
2305 dc_expand_user_macros_len, &error))
2306 {
2307 zbx_eval_clear(&ctx_r);
2308 zbx_eval_set_exception(&ctx_r, zbx_dsprintf(NULL, "cannot evaluate recovery"
2309 " expression: %s", error));
2310 zbx_free(error);
2311 }
2312 }
2313 row[17] = encode_expression(&ctx_r);
2314 zbx_eval_clear(&ctx_r);
2315 }
2316
2317 row[18] = zbx_dsprintf(NULL, "%d", timer);
2318
2319 zbx_vector_uint64_destroy(&functionids);
2320 zbx_vector_uint64_destroy(&hostids);
2321
2322 return row;
2323 }
2324
2325 /******************************************************************************
2326 * *
2327 * Function: zbx_dbsync_compare_triggers *
2328 * *
2329 * Purpose: compares triggers table with cached configuration data *
2330 * *
2331 * Parameter: sync - [OUT] the changeset *
2332 * *
2333 * Return value: SUCCEED - the changeset was successfully calculated *
2334 * FAIL - otherwise *
2335 * *
2336 * Comment: The 16th and 17th fields (starting with 0) are placeholders for *
2337 * serialized expression/recovery expression. *
2338 * The 18th field is placeholder for trigger timer flag (set if *
2339 * expression/recovery expression contains timer functions). *
2340 * *
2341 ******************************************************************************/
zbx_dbsync_compare_triggers(zbx_dbsync_t * sync)2342 int zbx_dbsync_compare_triggers(zbx_dbsync_t *sync)
2343 {
2344 DB_ROW dbrow;
2345 DB_RESULT result;
2346 zbx_hashset_t ids;
2347 zbx_hashset_iter_t iter;
2348 zbx_uint64_t rowid;
2349 ZBX_DC_TRIGGER *trigger;
2350 char **row;
2351
2352 if (NULL == (result = DBselect(
2353 "select distinct t.triggerid,t.description,t.expression,t.error,t.priority,t.type,t.value,"
2354 "t.state,t.lastchange,t.status,t.recovery_mode,t.recovery_expression,"
2355 "t.correlation_mode,t.correlation_tag,t.opdata,t.event_name,null,null,null"
2356 " from hosts h,items i,functions f,triggers t"
2357 " where h.hostid=i.hostid"
2358 " and i.itemid=f.itemid"
2359 " and f.triggerid=t.triggerid"
2360 " and h.status in (%d,%d)"
2361 " and t.flags<>%d",
2362 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
2363 ZBX_FLAG_DISCOVERY_PROTOTYPE)))
2364 {
2365 return FAIL;
2366 }
2367
2368 dbsync_prepare(sync, 19, dbsync_trigger_preproc_row);
2369
2370 if (ZBX_DBSYNC_INIT == sync->mode)
2371 {
2372 sync->dbresult = result;
2373 return SUCCEED;
2374 }
2375
2376 zbx_hashset_create(&ids, dbsync_env.cache->triggers.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
2377 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2378
2379 while (NULL != (dbrow = DBfetch(result)))
2380 {
2381 ZBX_STR2UINT64(rowid, dbrow[0]);
2382 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
2383
2384 row = dbsync_preproc_row(sync, dbrow);
2385
2386 if (NULL == (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&dbsync_env.cache->triggers, &rowid)))
2387 {
2388 dbsync_add_row(sync, rowid, ZBX_DBSYNC_ROW_ADD, row);
2389 }
2390 else
2391 {
2392 if (FAIL == dbsync_compare_trigger(trigger, row))
2393 dbsync_add_row(sync, rowid, ZBX_DBSYNC_ROW_UPDATE, row);
2394 }
2395 }
2396
2397 zbx_hashset_iter_reset(&dbsync_env.cache->triggers, &iter);
2398 while (NULL != (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_iter_next(&iter)))
2399 {
2400 if (NULL == zbx_hashset_search(&ids, &trigger->triggerid))
2401 dbsync_add_row(sync, trigger->triggerid, ZBX_DBSYNC_ROW_REMOVE, NULL);
2402 }
2403
2404 zbx_hashset_destroy(&ids);
2405 DBfree_result(result);
2406
2407 return SUCCEED;
2408 }
2409
2410 /******************************************************************************
2411 * *
2412 * Function: zbx_dbsync_compare_trigger_dependency *
2413 * *
2414 * Purpose: compares trigger_depends table with cached configuration data *
2415 * *
2416 * Parameter: sync - [OUT] the changeset *
2417 * *
2418 * Return value: SUCCEED - the changeset was successfully calculated *
2419 * FAIL - otherwise *
2420 * *
2421 ******************************************************************************/
zbx_dbsync_compare_trigger_dependency(zbx_dbsync_t * sync)2422 int zbx_dbsync_compare_trigger_dependency(zbx_dbsync_t *sync)
2423 {
2424 DB_ROW dbrow;
2425 DB_RESULT result;
2426 zbx_hashset_t deps;
2427 zbx_hashset_iter_t iter;
2428 ZBX_DC_TRIGGER_DEPLIST *dep_down, *dep_up;
2429 zbx_uint64_pair_t *dep, dep_local;
2430 char down_s[MAX_ID_LEN + 1], up_s[MAX_ID_LEN + 1];
2431 char *del_row[2] = {down_s, up_s};
2432 int i;
2433
2434 if (NULL == (result = DBselect(
2435 "select distinct d.triggerid_down,d.triggerid_up"
2436 " from trigger_depends d,triggers t,hosts h,items i,functions f"
2437 " where t.triggerid=d.triggerid_down"
2438 " and t.flags<>%d"
2439 " and h.hostid=i.hostid"
2440 " and i.itemid=f.itemid"
2441 " and f.triggerid=d.triggerid_down"
2442 " and h.status in (%d,%d)",
2443 ZBX_FLAG_DISCOVERY_PROTOTYPE, HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED)))
2444 {
2445 return FAIL;
2446 }
2447
2448 dbsync_prepare(sync, 2, NULL);
2449
2450 if (ZBX_DBSYNC_INIT == sync->mode)
2451 {
2452 sync->dbresult = result;
2453 return SUCCEED;
2454 }
2455
2456 zbx_hashset_create(&deps, 100, ZBX_DEFAULT_UINT64_PAIR_HASH_FUNC, ZBX_DEFAULT_UINT64_PAIR_COMPARE_FUNC);
2457
2458 /* index all host->template links */
2459 zbx_hashset_iter_reset(&dbsync_env.cache->trigdeps, &iter);
2460 while (NULL != (dep_down = (ZBX_DC_TRIGGER_DEPLIST *)zbx_hashset_iter_next(&iter)))
2461 {
2462 dep_local.first = dep_down->triggerid;
2463
2464 for (i = 0; i < dep_down->dependencies.values_num; i++)
2465 {
2466 dep_up = (ZBX_DC_TRIGGER_DEPLIST *)dep_down->dependencies.values[i];
2467 dep_local.second = dep_up->triggerid;
2468 zbx_hashset_insert(&deps, &dep_local, sizeof(dep_local));
2469 }
2470 }
2471
2472 /* add new rows, remove existing rows from index */
2473 while (NULL != (dbrow = DBfetch(result)))
2474 {
2475 ZBX_STR2UINT64(dep_local.first, dbrow[0]);
2476 ZBX_STR2UINT64(dep_local.second, dbrow[1]);
2477
2478 if (NULL == (dep = (zbx_uint64_pair_t *)zbx_hashset_search(&deps, &dep_local)))
2479 dbsync_add_row(sync, 0, ZBX_DBSYNC_ROW_ADD, dbrow);
2480 else
2481 zbx_hashset_remove_direct(&deps, dep);
2482 }
2483
2484 /* add removed rows */
2485 zbx_hashset_iter_reset(&deps, &iter);
2486 while (NULL != (dep = (zbx_uint64_pair_t *)zbx_hashset_iter_next(&iter)))
2487 {
2488 zbx_snprintf(down_s, sizeof(down_s), ZBX_FS_UI64, dep->first);
2489 zbx_snprintf(up_s, sizeof(up_s), ZBX_FS_UI64, dep->second);
2490 dbsync_add_row(sync, 0, ZBX_DBSYNC_ROW_REMOVE, del_row);
2491 }
2492
2493 DBfree_result(result);
2494 zbx_hashset_destroy(&deps);
2495
2496 return SUCCEED;
2497 }
2498
2499 /******************************************************************************
2500 * *
2501 * Function: dbsync_compare_function *
2502 * *
2503 * Purpose: compares functions table row with cached configuration data *
2504 * *
2505 * Parameter: function - [IN] the cached function *
2506 * dbrow - [IN] the database row *
2507 * *
2508 * Return value: SUCCEED - the row matches configuration data *
2509 * FAIL - otherwise *
2510 * *
2511 ******************************************************************************/
dbsync_compare_function(const ZBX_DC_FUNCTION * function,const DB_ROW dbrow)2512 static int dbsync_compare_function(const ZBX_DC_FUNCTION *function, const DB_ROW dbrow)
2513 {
2514 if (FAIL == dbsync_compare_uint64(dbrow[0], function->itemid))
2515 return FAIL;
2516
2517 if (FAIL == dbsync_compare_uint64(dbrow[4], function->triggerid))
2518 return FAIL;
2519
2520 if (FAIL == dbsync_compare_str(dbrow[2], function->function))
2521 return FAIL;
2522
2523 if (FAIL == dbsync_compare_str(dbrow[3], function->parameter))
2524 return FAIL;
2525
2526 return SUCCEED;
2527 }
2528
2529 /******************************************************************************
2530 * *
2531 * Function: dbsync_function_preproc_row *
2532 * *
2533 * Purpose: applies necessary preprocessing before row is compared/used *
2534 * *
2535 * Parameter: row - [IN] the row to preprocess *
2536 * *
2537 * Return value: the preprocessed row *
2538 * *
2539 * Comments: The row preprocessing can be used to expand user macros in *
2540 * some columns. *
2541 * *
2542 ******************************************************************************/
dbsync_function_preproc_row(char ** row)2543 static char **dbsync_function_preproc_row(char **row)
2544 {
2545 zbx_uint64_t hostid;
2546 const char *row3;
2547
2548 /* first parameter is /host/key placeholder $, don't cache it */
2549 if (NULL == (row3 = strchr(row[3], ',')))
2550 row3 = "";
2551 else
2552 row3++;
2553
2554 /* return the original row if user macros are not used in target columns */
2555 if (SUCCEED == dbsync_check_row_macros(row, 3))
2556 {
2557 /* get associated host identifier */
2558 ZBX_STR2UINT64(hostid, row[5]);
2559
2560 row[3] = dc_expand_user_macros_in_func_params(row3, hostid);
2561 }
2562 else
2563 row[3] = zbx_strdup(NULL, row3);
2564
2565 return row;
2566 }
2567
2568 /******************************************************************************
2569 * *
2570 * Function: zbx_dbsync_compare_functions *
2571 * *
2572 * Purpose: compares functions table with cached configuration data *
2573 * *
2574 * Parameter: sync - [OUT] the changeset *
2575 * *
2576 * Return value: SUCCEED - the changeset was successfully calculated *
2577 * FAIL - otherwise *
2578 * *
2579 ******************************************************************************/
zbx_dbsync_compare_functions(zbx_dbsync_t * sync)2580 int zbx_dbsync_compare_functions(zbx_dbsync_t *sync)
2581 {
2582 DB_ROW dbrow;
2583 DB_RESULT result;
2584 zbx_hashset_t ids;
2585 zbx_hashset_iter_t iter;
2586 zbx_uint64_t rowid;
2587 ZBX_DC_FUNCTION *function;
2588 char **row;
2589
2590 if (NULL == (result = DBselect(
2591 "select i.itemid,f.functionid,f.name,f.parameter,t.triggerid,i.hostid"
2592 " from hosts h,items i,functions f,triggers t"
2593 " where h.hostid=i.hostid"
2594 " and i.itemid=f.itemid"
2595 " and f.triggerid=t.triggerid"
2596 " and h.status in (%d,%d)"
2597 " and t.flags<>%d",
2598 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
2599 ZBX_FLAG_DISCOVERY_PROTOTYPE)))
2600 {
2601 return FAIL;
2602 }
2603
2604 dbsync_prepare(sync, 6, dbsync_function_preproc_row);
2605
2606 if (ZBX_DBSYNC_INIT == sync->mode)
2607 {
2608 sync->dbresult = result;
2609 return SUCCEED;
2610 }
2611
2612 zbx_hashset_create(&ids, dbsync_env.cache->functions.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
2613 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2614
2615 while (NULL != (dbrow = DBfetch(result)))
2616 {
2617 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
2618
2619 ZBX_STR2UINT64(rowid, dbrow[1]);
2620 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
2621
2622 row = dbsync_preproc_row(sync, dbrow);
2623
2624 if (NULL == (function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&dbsync_env.cache->functions, &rowid)))
2625 tag = ZBX_DBSYNC_ROW_ADD;
2626 else if (FAIL == dbsync_compare_function(function, row))
2627 tag = ZBX_DBSYNC_ROW_UPDATE;
2628
2629 if (ZBX_DBSYNC_ROW_NONE != tag)
2630 dbsync_add_row(sync, rowid, tag, row);
2631 }
2632
2633 zbx_hashset_iter_reset(&dbsync_env.cache->functions, &iter);
2634 while (NULL != (function = (ZBX_DC_FUNCTION *)zbx_hashset_iter_next(&iter)))
2635 {
2636 if (NULL == zbx_hashset_search(&ids, &function->functionid))
2637 dbsync_add_row(sync, function->functionid, ZBX_DBSYNC_ROW_REMOVE, NULL);
2638 }
2639
2640 zbx_hashset_destroy(&ids);
2641 DBfree_result(result);
2642
2643 return SUCCEED;
2644 }
2645
2646 /******************************************************************************
2647 * *
2648 * Function: dbsync_compare_expression *
2649 * *
2650 * Purpose: compares expressions table row with cached configuration data *
2651 * *
2652 * Parameter: expression - [IN] the cached expression *
2653 * dbrow - [IN] the database row *
2654 * *
2655 * Return value: SUCCEED - the row matches configuration data *
2656 * FAIL - otherwise *
2657 * *
2658 ******************************************************************************/
dbsync_compare_expression(const ZBX_DC_EXPRESSION * expression,const DB_ROW dbrow)2659 static int dbsync_compare_expression(const ZBX_DC_EXPRESSION *expression, const DB_ROW dbrow)
2660 {
2661 if (FAIL == dbsync_compare_str(dbrow[0], expression->regexp))
2662 return FAIL;
2663
2664 if (FAIL == dbsync_compare_str(dbrow[2], expression->expression))
2665 return FAIL;
2666
2667 if (FAIL == dbsync_compare_uchar(dbrow[3], expression->type))
2668 return FAIL;
2669
2670 if (*dbrow[4] != expression->delimiter)
2671 return FAIL;
2672
2673 if (FAIL == dbsync_compare_uchar(dbrow[5], expression->case_sensitive))
2674 return FAIL;
2675
2676 return SUCCEED;
2677 }
2678
2679 /******************************************************************************
2680 * *
2681 * Function: zbx_dbsync_compare_exprssions *
2682 * *
2683 * Purpose: compares expressions, regexps tables with cached configuration *
2684 * data *
2685 * *
2686 * Parameter: sync - [OUT] the changeset *
2687 * *
2688 * Return value: SUCCEED - the changeset was successfully calculated *
2689 * FAIL - otherwise *
2690 * *
2691 ******************************************************************************/
zbx_dbsync_compare_expressions(zbx_dbsync_t * sync)2692 int zbx_dbsync_compare_expressions(zbx_dbsync_t *sync)
2693 {
2694 DB_ROW dbrow;
2695 DB_RESULT result;
2696 zbx_hashset_t ids;
2697 zbx_hashset_iter_t iter;
2698 zbx_uint64_t rowid;
2699 ZBX_DC_EXPRESSION *expression;
2700
2701 if (NULL == (result = DBselect(
2702 "select r.name,e.expressionid,e.expression,e.expression_type,e.exp_delimiter,e.case_sensitive"
2703 " from regexps r,expressions e"
2704 " where r.regexpid=e.regexpid")))
2705 {
2706 return FAIL;
2707 }
2708
2709 dbsync_prepare(sync, 6, NULL);
2710
2711 if (ZBX_DBSYNC_INIT == sync->mode)
2712 {
2713 sync->dbresult = result;
2714 return SUCCEED;
2715 }
2716
2717 zbx_hashset_create(&ids, dbsync_env.cache->expressions.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
2718 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2719
2720 while (NULL != (dbrow = DBfetch(result)))
2721 {
2722 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
2723
2724 ZBX_STR2UINT64(rowid, dbrow[1]);
2725 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
2726
2727 if (NULL == (expression = (ZBX_DC_EXPRESSION *)zbx_hashset_search(&dbsync_env.cache->expressions,
2728 &rowid)))
2729 {
2730 tag = ZBX_DBSYNC_ROW_ADD;
2731 }
2732 else if (FAIL == dbsync_compare_expression(expression, dbrow))
2733 tag = ZBX_DBSYNC_ROW_UPDATE;
2734
2735 if (ZBX_DBSYNC_ROW_NONE != tag)
2736 dbsync_add_row(sync, rowid, tag, dbrow);
2737 }
2738
2739 zbx_hashset_iter_reset(&dbsync_env.cache->expressions, &iter);
2740 while (NULL != (expression = (ZBX_DC_EXPRESSION *)zbx_hashset_iter_next(&iter)))
2741 {
2742 if (NULL == zbx_hashset_search(&ids, &expression->expressionid))
2743 dbsync_add_row(sync, expression->expressionid, ZBX_DBSYNC_ROW_REMOVE, NULL);
2744 }
2745
2746 zbx_hashset_destroy(&ids);
2747 DBfree_result(result);
2748
2749 return SUCCEED;
2750 }
2751
2752 /******************************************************************************
2753 * *
2754 * Function: dbsync_compare_action *
2755 * *
2756 * Purpose: compares actions table row with cached configuration data *
2757 * *
2758 * Parameter: action - [IN] the cached action *
2759 * dbrow - [IN] the database row *
2760 * *
2761 * Return value: SUCCEED - the row matches configuration data *
2762 * FAIL - otherwise *
2763 * *
2764 ******************************************************************************/
dbsync_compare_action(const zbx_dc_action_t * action,const DB_ROW dbrow)2765 static int dbsync_compare_action(const zbx_dc_action_t *action, const DB_ROW dbrow)
2766 {
2767
2768 if (FAIL == dbsync_compare_uchar(dbrow[1], action->eventsource))
2769 return FAIL;
2770
2771 if (FAIL == dbsync_compare_uchar(dbrow[2], action->evaltype))
2772 return FAIL;
2773
2774 if (FAIL == dbsync_compare_str(dbrow[3], action->formula))
2775 return FAIL;
2776
2777 return SUCCEED;
2778 }
2779
2780 /******************************************************************************
2781 * *
2782 * Function: zbx_dbsync_compare_actions *
2783 * *
2784 * Purpose: compares actions table with cached configuration data *
2785 * *
2786 * Parameter: sync - [OUT] the changeset *
2787 * *
2788 * Return value: SUCCEED - the changeset was successfully calculated *
2789 * FAIL - otherwise *
2790 * *
2791 ******************************************************************************/
zbx_dbsync_compare_actions(zbx_dbsync_t * sync)2792 int zbx_dbsync_compare_actions(zbx_dbsync_t *sync)
2793 {
2794 DB_ROW dbrow;
2795 DB_RESULT result;
2796 zbx_hashset_t ids;
2797 zbx_hashset_iter_t iter;
2798 zbx_uint64_t rowid;
2799 zbx_dc_action_t *action;
2800
2801 if (NULL == (result = DBselect(
2802 "select actionid,eventsource,evaltype,formula"
2803 " from actions"
2804 " where status=%d",
2805 ACTION_STATUS_ACTIVE)))
2806 {
2807 return FAIL;
2808 }
2809
2810 dbsync_prepare(sync, 4, NULL);
2811
2812 if (ZBX_DBSYNC_INIT == sync->mode)
2813 {
2814 sync->dbresult = result;
2815 return SUCCEED;
2816 }
2817
2818 zbx_hashset_create(&ids, dbsync_env.cache->actions.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
2819 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2820
2821 while (NULL != (dbrow = DBfetch(result)))
2822 {
2823 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
2824
2825 ZBX_STR2UINT64(rowid, dbrow[0]);
2826 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
2827
2828 if (NULL == (action = (zbx_dc_action_t *)zbx_hashset_search(&dbsync_env.cache->actions, &rowid)))
2829 tag = ZBX_DBSYNC_ROW_ADD;
2830 else if (FAIL == dbsync_compare_action(action, dbrow))
2831 tag = ZBX_DBSYNC_ROW_UPDATE;
2832
2833 if (ZBX_DBSYNC_ROW_NONE != tag)
2834 dbsync_add_row(sync, rowid, tag, dbrow);
2835 }
2836
2837 zbx_hashset_iter_reset(&dbsync_env.cache->actions, &iter);
2838 while (NULL != (action = (zbx_dc_action_t *)zbx_hashset_iter_next(&iter)))
2839 {
2840 if (NULL == zbx_hashset_search(&ids, &action->actionid))
2841 dbsync_add_row(sync, action->actionid, ZBX_DBSYNC_ROW_REMOVE, NULL);
2842 }
2843
2844 zbx_hashset_destroy(&ids);
2845 DBfree_result(result);
2846
2847 return SUCCEED;
2848 }
2849
2850 /******************************************************************************
2851 * *
2852 * Function: dbsync_compare_action_op *
2853 * *
2854 * Purpose: compares action operation class and flushes update row if *
2855 * necessary *
2856 * *
2857 * Parameter: sync - [OUT] the changeset *
2858 * actionid - [IN] the action identifier *
2859 * opflags - [IN] the action operation class flags *
2860 * *
2861 ******************************************************************************/
dbsync_compare_action_op(zbx_dbsync_t * sync,zbx_uint64_t actionid,unsigned char opflags)2862 static void dbsync_compare_action_op(zbx_dbsync_t *sync, zbx_uint64_t actionid, unsigned char opflags)
2863 {
2864 zbx_dc_action_t *action;
2865
2866 if (0 == actionid)
2867 return;
2868
2869 if (NULL == (action = (zbx_dc_action_t *)zbx_hashset_search(&dbsync_env.cache->actions, &actionid)) ||
2870 opflags != action->opflags)
2871 {
2872 char actionid_s[MAX_ID_LEN], opflags_s[MAX_ID_LEN];
2873 char *row[] = {actionid_s, opflags_s};
2874
2875 zbx_snprintf(actionid_s, sizeof(actionid_s), ZBX_FS_UI64, actionid);
2876 zbx_snprintf(opflags_s, sizeof(opflags_s), "%d", opflags);
2877
2878 dbsync_add_row(sync, actionid, ZBX_DBSYNC_ROW_UPDATE, (DB_ROW)row);
2879 }
2880 }
2881
2882 /******************************************************************************
2883 * *
2884 * Function: zbx_dbsync_compare_action_ops *
2885 * *
2886 * Purpose: compares actions by operation class *
2887 * *
2888 * Parameter: sync - [OUT] the changeset *
2889 * *
2890 * Return value: SUCCEED - the changeset was successfully calculated *
2891 * FAIL - otherwise *
2892 * *
2893 ******************************************************************************/
zbx_dbsync_compare_action_ops(zbx_dbsync_t * sync)2894 int zbx_dbsync_compare_action_ops(zbx_dbsync_t *sync)
2895 {
2896 DB_ROW dbrow;
2897 DB_RESULT result;
2898 zbx_uint64_t rowid, actionid = 0;
2899 unsigned char opflags = ZBX_ACTION_OPCLASS_NONE;
2900
2901 if (NULL == (result = DBselect(
2902 "select a.actionid,o.recovery"
2903 " from actions a"
2904 " left join operations o"
2905 " on a.actionid=o.actionid"
2906 " where a.status=%d"
2907 " group by a.actionid,o.recovery"
2908 " order by a.actionid",
2909 ACTION_STATUS_ACTIVE)))
2910 {
2911 return FAIL;
2912 }
2913
2914 dbsync_prepare(sync, 2, NULL);
2915
2916 while (NULL != (dbrow = DBfetch(result)))
2917 {
2918 ZBX_STR2UINT64(rowid, dbrow[0]);
2919
2920 if (actionid != rowid)
2921 {
2922 dbsync_compare_action_op(sync, actionid, opflags);
2923 actionid = rowid;
2924 opflags = ZBX_ACTION_OPCLASS_NONE;
2925 }
2926
2927 if (SUCCEED == DBis_null(dbrow[1]))
2928 continue;
2929
2930 switch (atoi(dbrow[1]))
2931 {
2932 case 0:
2933 opflags |= ZBX_ACTION_OPCLASS_NORMAL;
2934 break;
2935 case 1:
2936 opflags |= ZBX_ACTION_OPCLASS_RECOVERY;
2937 break;
2938 case 2:
2939 opflags |= ZBX_ACTION_OPCLASS_ACKNOWLEDGE;
2940 break;
2941 }
2942 }
2943
2944 dbsync_compare_action_op(sync, actionid, opflags);
2945
2946 DBfree_result(result);
2947
2948 return SUCCEED;
2949 }
2950
2951
2952 /******************************************************************************
2953 * *
2954 * Function: dbsync_compare_action_condition *
2955 * *
2956 * Purpose: compares conditions table row with cached configuration data *
2957 * *
2958 * Parameter: condition - [IN] the cached action condition *
2959 * dbrow - [IN] the database row *
2960 * *
2961 * Return value: SUCCEED - the row matches configuration data *
2962 * FAIL - otherwise *
2963 * *
2964 ******************************************************************************/
dbsync_compare_action_condition(const zbx_dc_action_condition_t * condition,const DB_ROW dbrow)2965 static int dbsync_compare_action_condition(const zbx_dc_action_condition_t *condition, const DB_ROW dbrow)
2966 {
2967 if (FAIL == dbsync_compare_uchar(dbrow[2], condition->conditiontype))
2968 return FAIL;
2969
2970 if (FAIL == dbsync_compare_uchar(dbrow[3], condition->op))
2971 return FAIL;
2972
2973 if (FAIL == dbsync_compare_str(dbrow[4], condition->value))
2974 return FAIL;
2975
2976 if (FAIL == dbsync_compare_str(dbrow[5], condition->value2))
2977 return FAIL;
2978
2979 return SUCCEED;
2980 }
2981
2982 /******************************************************************************
2983 * *
2984 * Function: zbx_dbsync_compare_action_conditions *
2985 * *
2986 * Purpose: compares conditions table with cached configuration data *
2987 * *
2988 * Parameter: sync - [OUT] the changeset *
2989 * *
2990 * Return value: SUCCEED - the changeset was successfully calculated *
2991 * FAIL - otherwise *
2992 * *
2993 ******************************************************************************/
zbx_dbsync_compare_action_conditions(zbx_dbsync_t * sync)2994 int zbx_dbsync_compare_action_conditions(zbx_dbsync_t *sync)
2995 {
2996 DB_ROW dbrow;
2997 DB_RESULT result;
2998 zbx_hashset_t ids;
2999 zbx_hashset_iter_t iter;
3000 zbx_uint64_t rowid;
3001 zbx_dc_action_condition_t *condition;
3002
3003 if (NULL == (result = DBselect(
3004 "select c.conditionid,c.actionid,c.conditiontype,c.operator,c.value,c.value2"
3005 " from conditions c,actions a"
3006 " where c.actionid=a.actionid"
3007 " and a.status=%d",
3008 ACTION_STATUS_ACTIVE)))
3009 {
3010 return FAIL;
3011 }
3012
3013 dbsync_prepare(sync, 6, NULL);
3014
3015 if (ZBX_DBSYNC_INIT == sync->mode)
3016 {
3017 sync->dbresult = result;
3018 return SUCCEED;
3019 }
3020
3021 zbx_hashset_create(&ids, dbsync_env.cache->action_conditions.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
3022 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3023
3024 while (NULL != (dbrow = DBfetch(result)))
3025 {
3026 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
3027
3028 ZBX_STR2UINT64(rowid, dbrow[0]);
3029 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
3030
3031 if (NULL == (condition = (zbx_dc_action_condition_t *)zbx_hashset_search(
3032 &dbsync_env.cache->action_conditions, &rowid)))
3033 {
3034 tag = ZBX_DBSYNC_ROW_ADD;
3035 }
3036 else if (FAIL == dbsync_compare_action_condition(condition, dbrow))
3037 tag = ZBX_DBSYNC_ROW_UPDATE;
3038
3039 if (ZBX_DBSYNC_ROW_NONE != tag)
3040 dbsync_add_row(sync, rowid, tag, dbrow);
3041 }
3042
3043 zbx_hashset_iter_reset(&dbsync_env.cache->action_conditions, &iter);
3044 while (NULL != (condition = (zbx_dc_action_condition_t *)zbx_hashset_iter_next(&iter)))
3045 {
3046 if (NULL == zbx_hashset_search(&ids, &condition->conditionid))
3047 dbsync_add_row(sync, condition->conditionid, ZBX_DBSYNC_ROW_REMOVE, NULL);
3048 }
3049
3050 zbx_hashset_destroy(&ids);
3051 DBfree_result(result);
3052
3053 return SUCCEED;
3054 }
3055
3056 /******************************************************************************
3057 * *
3058 * Function: dbsync_compare_trigger_tag *
3059 * *
3060 * Purpose: compares trigger tags table row with cached configuration data *
3061 * *
3062 * Parameter: tag - [IN] the cached trigger tag *
3063 * dbrow - [IN] the database row *
3064 * *
3065 * Return value: SUCCEED - the row matches configuration data *
3066 * FAIL - otherwise *
3067 * *
3068 ******************************************************************************/
dbsync_compare_trigger_tag(const zbx_dc_trigger_tag_t * tag,const DB_ROW dbrow)3069 static int dbsync_compare_trigger_tag(const zbx_dc_trigger_tag_t *tag, const DB_ROW dbrow)
3070 {
3071 if (FAIL == dbsync_compare_uint64(dbrow[1], tag->triggerid))
3072 return FAIL;
3073
3074 if (FAIL == dbsync_compare_str(dbrow[2], tag->tag))
3075 return FAIL;
3076
3077 if (FAIL == dbsync_compare_str(dbrow[3], tag->value))
3078 return FAIL;
3079
3080 return SUCCEED;
3081 }
3082
3083 /******************************************************************************
3084 * *
3085 * Function: zbx_dbsync_compare_trigger_tags *
3086 * *
3087 * Purpose: compares trigger tags table with cached configuration data *
3088 * *
3089 * Parameter: sync - [OUT] the changeset *
3090 * *
3091 * Return value: SUCCEED - the changeset was successfully calculated *
3092 * FAIL - otherwise *
3093 * *
3094 ******************************************************************************/
zbx_dbsync_compare_trigger_tags(zbx_dbsync_t * sync)3095 int zbx_dbsync_compare_trigger_tags(zbx_dbsync_t *sync)
3096 {
3097 DB_ROW dbrow;
3098 DB_RESULT result;
3099 zbx_hashset_t ids;
3100 zbx_hashset_iter_t iter;
3101 zbx_uint64_t rowid;
3102 zbx_dc_trigger_tag_t *trigger_tag;
3103
3104 if (NULL == (result = DBselect(
3105 "select distinct tt.triggertagid,tt.triggerid,tt.tag,tt.value"
3106 " from trigger_tag tt,triggers t,hosts h,items i,functions f"
3107 " where t.triggerid=tt.triggerid"
3108 " and t.flags<>%d"
3109 " and h.hostid=i.hostid"
3110 " and i.itemid=f.itemid"
3111 " and f.triggerid=tt.triggerid"
3112 " and h.status in (%d,%d)",
3113 ZBX_FLAG_DISCOVERY_PROTOTYPE, HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED)))
3114 {
3115 return FAIL;
3116 }
3117
3118 dbsync_prepare(sync, 4, NULL);
3119
3120 if (ZBX_DBSYNC_INIT == sync->mode)
3121 {
3122 sync->dbresult = result;
3123 return SUCCEED;
3124 }
3125
3126 zbx_hashset_create(&ids, dbsync_env.cache->trigger_tags.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
3127 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3128
3129 while (NULL != (dbrow = DBfetch(result)))
3130 {
3131 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
3132
3133 ZBX_STR2UINT64(rowid, dbrow[0]);
3134 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
3135
3136 if (NULL == (trigger_tag = (zbx_dc_trigger_tag_t *)zbx_hashset_search(&dbsync_env.cache->trigger_tags,
3137 &rowid)))
3138 {
3139 tag = ZBX_DBSYNC_ROW_ADD;
3140 }
3141 else if (FAIL == dbsync_compare_trigger_tag(trigger_tag, dbrow))
3142 tag = ZBX_DBSYNC_ROW_UPDATE;
3143
3144 if (ZBX_DBSYNC_ROW_NONE != tag)
3145 dbsync_add_row(sync, rowid, tag, dbrow);
3146 }
3147
3148 zbx_hashset_iter_reset(&dbsync_env.cache->trigger_tags, &iter);
3149 while (NULL != (trigger_tag = (zbx_dc_trigger_tag_t *)zbx_hashset_iter_next(&iter)))
3150 {
3151 if (NULL == zbx_hashset_search(&ids, &trigger_tag->triggertagid))
3152 dbsync_add_row(sync, trigger_tag->triggertagid, ZBX_DBSYNC_ROW_REMOVE, NULL);
3153 }
3154
3155 zbx_hashset_destroy(&ids);
3156 DBfree_result(result);
3157
3158 return SUCCEED;
3159 }
3160
3161 /******************************************************************************
3162 * *
3163 * Function: dbsync_compare_item_tag *
3164 * *
3165 * Purpose: compares item tags table row with cached configuration data *
3166 * *
3167 * Parameter: tag - [IN] the cached item tag *
3168 * dbrow - [IN] the database row *
3169 * *
3170 * Return value: SUCCEED - the row matches configuration data *
3171 * FAIL - otherwise *
3172 * *
3173 ******************************************************************************/
dbsync_compare_item_tag(const zbx_dc_item_tag_t * tag,const DB_ROW dbrow)3174 static int dbsync_compare_item_tag(const zbx_dc_item_tag_t *tag, const DB_ROW dbrow)
3175 {
3176 if (FAIL == dbsync_compare_uint64(dbrow[1], tag->itemid))
3177 return FAIL;
3178
3179 if (FAIL == dbsync_compare_str(dbrow[2], tag->tag))
3180 return FAIL;
3181
3182 if (FAIL == dbsync_compare_str(dbrow[3], tag->value))
3183 return FAIL;
3184
3185 return SUCCEED;
3186 }
3187
3188 /******************************************************************************
3189 * *
3190 * Function: zbx_dbsync_compare_item_tags *
3191 * *
3192 * Purpose: compares item tags table with cached configuration data *
3193 * *
3194 * Parameter: sync - [OUT] the changeset *
3195 * *
3196 * Return value: SUCCEED - the changeset was successfully calculated *
3197 * FAIL - otherwise *
3198 * *
3199 ******************************************************************************/
zbx_dbsync_compare_item_tags(zbx_dbsync_t * sync)3200 int zbx_dbsync_compare_item_tags(zbx_dbsync_t *sync)
3201 {
3202 DB_ROW dbrow;
3203 DB_RESULT result;
3204 zbx_hashset_t ids;
3205 zbx_hashset_iter_t iter;
3206 zbx_uint64_t rowid;
3207 zbx_dc_item_tag_t *item_tag;
3208
3209 if (NULL == (result = DBselect(
3210 "select distinct it.itemtagid,it.itemid,it.tag,it.value"
3211 " from item_tag it,items i,hosts h"
3212 " where i.itemid=it.itemid"
3213 " and i.flags in (%d,%d)"
3214 " and h.hostid=i.hostid"
3215 " and h.status in (%d,%d)",
3216 ZBX_FLAG_DISCOVERY_NORMAL, ZBX_FLAG_DISCOVERY_CREATED,
3217 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED)))
3218 {
3219 return FAIL;
3220 }
3221
3222 dbsync_prepare(sync, 4, NULL);
3223
3224 if (ZBX_DBSYNC_INIT == sync->mode)
3225 {
3226 sync->dbresult = result;
3227 return SUCCEED;
3228 }
3229
3230 zbx_hashset_create(&ids, dbsync_env.cache->item_tags.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
3231 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3232
3233 while (NULL != (dbrow = DBfetch(result)))
3234 {
3235 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
3236
3237 ZBX_STR2UINT64(rowid, dbrow[0]);
3238 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
3239
3240 if (NULL == (item_tag = (zbx_dc_item_tag_t *)zbx_hashset_search(&dbsync_env.cache->item_tags,
3241 &rowid)))
3242 {
3243 tag = ZBX_DBSYNC_ROW_ADD;
3244 }
3245 else if (FAIL == dbsync_compare_item_tag(item_tag, dbrow))
3246 tag = ZBX_DBSYNC_ROW_UPDATE;
3247
3248 if (ZBX_DBSYNC_ROW_NONE != tag)
3249 dbsync_add_row(sync, rowid, tag, dbrow);
3250 }
3251 DBfree_result(result);
3252
3253 zbx_hashset_iter_reset(&dbsync_env.cache->item_tags, &iter);
3254 while (NULL != (item_tag = (zbx_dc_item_tag_t *)zbx_hashset_iter_next(&iter)))
3255 {
3256 if (NULL == zbx_hashset_search(&ids, &item_tag->itemtagid))
3257 dbsync_add_row(sync, item_tag->itemtagid, ZBX_DBSYNC_ROW_REMOVE, NULL);
3258 }
3259
3260 zbx_hashset_destroy(&ids);
3261
3262 return SUCCEED;
3263 }
3264
3265 /******************************************************************************
3266 * *
3267 * Function: dbsync_compare_host_tag *
3268 * *
3269 * Purpose: compares host tags table row with cached configuration data *
3270 * *
3271 * Parameter: tag - [IN] the cached host tag *
3272 * dbrow - [IN] the database row *
3273 * *
3274 * Return value: SUCCEED - the row matches configuration data *
3275 * FAIL - otherwise *
3276 * *
3277 ******************************************************************************/
dbsync_compare_host_tag(const zbx_dc_host_tag_t * tag,const DB_ROW dbrow)3278 static int dbsync_compare_host_tag(const zbx_dc_host_tag_t *tag, const DB_ROW dbrow)
3279 {
3280 if (FAIL == dbsync_compare_uint64(dbrow[1], tag->hostid))
3281 return FAIL;
3282
3283 if (FAIL == dbsync_compare_str(dbrow[2], tag->tag))
3284 return FAIL;
3285
3286 if (FAIL == dbsync_compare_str(dbrow[3], tag->value))
3287 return FAIL;
3288
3289 return SUCCEED;
3290 }
3291
3292 /******************************************************************************
3293 * *
3294 * Function: zbx_dbsync_compare_host_tags *
3295 * *
3296 * Purpose: compares host tags table with cached configuration data *
3297 * *
3298 * Parameter: sync - [OUT] the changeset *
3299 * *
3300 * Return value: SUCCEED - the changeset was successfully calculated *
3301 * FAIL - otherwise *
3302 * *
3303 ******************************************************************************/
zbx_dbsync_compare_host_tags(zbx_dbsync_t * sync)3304 int zbx_dbsync_compare_host_tags(zbx_dbsync_t *sync)
3305 {
3306 DB_ROW dbrow;
3307 DB_RESULT result;
3308 zbx_hashset_t ids;
3309 zbx_hashset_iter_t iter;
3310 zbx_uint64_t rowid;
3311 zbx_dc_host_tag_t *host_tag;
3312
3313 if (NULL == (result = DBselect(
3314 "select * from host_tag")))
3315 {
3316 printf("db query failed!\n");
3317 return FAIL;
3318 }
3319
3320 dbsync_prepare(sync, 4, NULL);
3321
3322 if (ZBX_DBSYNC_INIT == sync->mode)
3323 {
3324 sync->dbresult = result;
3325 return SUCCEED;
3326 }
3327
3328 zbx_hashset_create(&ids, dbsync_env.cache->host_tags.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
3329 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3330
3331 while (NULL != (dbrow = DBfetch(result)))
3332 {
3333 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
3334
3335 ZBX_STR2UINT64(rowid, dbrow[0]);
3336 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
3337
3338 if (NULL == (host_tag = (zbx_dc_host_tag_t *)zbx_hashset_search(&dbsync_env.cache->host_tags,
3339 &rowid)))
3340 {
3341 tag = ZBX_DBSYNC_ROW_ADD;
3342 }
3343 else if (FAIL == dbsync_compare_host_tag(host_tag, dbrow))
3344 tag = ZBX_DBSYNC_ROW_UPDATE;
3345
3346 if (ZBX_DBSYNC_ROW_NONE != tag)
3347 dbsync_add_row(sync, rowid, tag, dbrow);
3348 }
3349
3350 zbx_hashset_iter_reset(&dbsync_env.cache->host_tags, &iter);
3351 while (NULL != (host_tag = (zbx_dc_host_tag_t *)zbx_hashset_iter_next(&iter)))
3352 {
3353 if (NULL == zbx_hashset_search(&ids, &host_tag->hosttagid))
3354 dbsync_add_row(sync, host_tag->hosttagid, ZBX_DBSYNC_ROW_REMOVE, NULL);
3355 }
3356
3357 zbx_hashset_destroy(&ids);
3358 DBfree_result(result);
3359
3360 return SUCCEED;
3361 }
3362
3363 /******************************************************************************
3364 * *
3365 * Function: dbsync_compare_correlation *
3366 * *
3367 * Purpose: compares correlation table row with cached configuration data *
3368 * *
3369 * Parameter: correlation - [IN] the cached correlation rule *
3370 * dbrow - [IN] the database row *
3371 * *
3372 * Return value: SUCCEED - the row matches configuration data *
3373 * FAIL - otherwise *
3374 * *
3375 ******************************************************************************/
dbsync_compare_correlation(const zbx_dc_correlation_t * correlation,const DB_ROW dbrow)3376 static int dbsync_compare_correlation(const zbx_dc_correlation_t *correlation, const DB_ROW dbrow)
3377 {
3378 if (FAIL == dbsync_compare_str(dbrow[1], correlation->name))
3379 return FAIL;
3380
3381 if (FAIL == dbsync_compare_uchar(dbrow[2], correlation->evaltype))
3382 return FAIL;
3383
3384 if (FAIL == dbsync_compare_str(dbrow[3], correlation->formula))
3385 return FAIL;
3386
3387 return SUCCEED;
3388 }
3389
3390 /******************************************************************************
3391 * *
3392 * Function: zbx_dbsync_compare_correlations *
3393 * *
3394 * Purpose: compares correlation table with cached configuration data *
3395 * *
3396 * Parameter: sync - [OUT] the changeset *
3397 * *
3398 * Return value: SUCCEED - the changeset was successfully calculated *
3399 * FAIL - otherwise *
3400 * *
3401 ******************************************************************************/
zbx_dbsync_compare_correlations(zbx_dbsync_t * sync)3402 int zbx_dbsync_compare_correlations(zbx_dbsync_t *sync)
3403 {
3404 DB_ROW dbrow;
3405 DB_RESULT result;
3406 zbx_hashset_t ids;
3407 zbx_hashset_iter_t iter;
3408 zbx_uint64_t rowid;
3409 zbx_dc_correlation_t *correlation;
3410
3411 if (NULL == (result = DBselect(
3412 "select correlationid,name,evaltype,formula"
3413 " from correlation"
3414 " where status=%d",
3415 ZBX_CORRELATION_ENABLED)))
3416 {
3417 return FAIL;
3418 }
3419
3420 dbsync_prepare(sync, 4, NULL);
3421
3422 if (ZBX_DBSYNC_INIT == sync->mode)
3423 {
3424 sync->dbresult = result;
3425 return SUCCEED;
3426 }
3427
3428 zbx_hashset_create(&ids, dbsync_env.cache->correlations.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
3429 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3430
3431 while (NULL != (dbrow = DBfetch(result)))
3432 {
3433 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
3434
3435 ZBX_STR2UINT64(rowid, dbrow[0]);
3436 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
3437
3438 if (NULL == (correlation = (zbx_dc_correlation_t *)zbx_hashset_search(&dbsync_env.cache->correlations,
3439 &rowid)))
3440 {
3441 tag = ZBX_DBSYNC_ROW_ADD;
3442 }
3443 else if (FAIL == dbsync_compare_correlation(correlation, dbrow))
3444 tag = ZBX_DBSYNC_ROW_UPDATE;
3445
3446 if (ZBX_DBSYNC_ROW_NONE != tag)
3447 dbsync_add_row(sync, rowid, tag, dbrow);
3448 }
3449
3450 zbx_hashset_iter_reset(&dbsync_env.cache->correlations, &iter);
3451 while (NULL != (correlation = (zbx_dc_correlation_t *)zbx_hashset_iter_next(&iter)))
3452 {
3453 if (NULL == zbx_hashset_search(&ids, &correlation->correlationid))
3454 dbsync_add_row(sync, correlation->correlationid, ZBX_DBSYNC_ROW_REMOVE, NULL);
3455 }
3456
3457 zbx_hashset_destroy(&ids);
3458 DBfree_result(result);
3459
3460 return SUCCEED;
3461 }
3462
3463 /******************************************************************************
3464 * *
3465 * Function: dbsync_compare_corr_condition *
3466 * *
3467 * Purpose: compares correlation condition tables dbrow with cached *
3468 * configuration data *
3469 * *
3470 * Parameter: corr_condition - [IN] the cached correlation condition *
3471 * dbrow - [IN] the database row *
3472 * *
3473 * Return value: SUCCEED - the row matches configuration data *
3474 * FAIL - otherwise *
3475 * *
3476 ******************************************************************************/
dbsync_compare_corr_condition(const zbx_dc_corr_condition_t * corr_condition,const DB_ROW dbrow)3477 static int dbsync_compare_corr_condition(const zbx_dc_corr_condition_t *corr_condition, const DB_ROW dbrow)
3478 {
3479 if (FAIL == dbsync_compare_uint64(dbrow[1], corr_condition->correlationid))
3480 return FAIL;
3481
3482 if (FAIL == dbsync_compare_uchar(dbrow[2], corr_condition->type))
3483 return FAIL;
3484
3485 switch (corr_condition->type)
3486 {
3487 case ZBX_CORR_CONDITION_OLD_EVENT_TAG:
3488 /* break; is not missing here */
3489 case ZBX_CORR_CONDITION_NEW_EVENT_TAG:
3490 if (FAIL == dbsync_compare_str(dbrow[3], corr_condition->data.tag.tag))
3491 return FAIL;
3492 break;
3493 case ZBX_CORR_CONDITION_OLD_EVENT_TAG_VALUE:
3494 /* break; is not missing here */
3495 case ZBX_CORR_CONDITION_NEW_EVENT_TAG_VALUE:
3496 if (FAIL == dbsync_compare_str(dbrow[4], corr_condition->data.tag_value.tag))
3497 return FAIL;
3498 if (FAIL == dbsync_compare_str(dbrow[5], corr_condition->data.tag_value.value))
3499 return FAIL;
3500 if (FAIL == dbsync_compare_uchar(dbrow[6], corr_condition->data.tag_value.op))
3501 return FAIL;
3502 break;
3503 case ZBX_CORR_CONDITION_NEW_EVENT_HOSTGROUP:
3504 if (FAIL == dbsync_compare_uint64(dbrow[7], corr_condition->data.group.groupid))
3505 return FAIL;
3506 if (FAIL == dbsync_compare_uchar(dbrow[8], corr_condition->data.group.op))
3507 return FAIL;
3508 break;
3509 case ZBX_CORR_CONDITION_EVENT_TAG_PAIR:
3510 if (FAIL == dbsync_compare_str(dbrow[9], corr_condition->data.tag_pair.oldtag))
3511 return FAIL;
3512 if (FAIL == dbsync_compare_str(dbrow[10], corr_condition->data.tag_pair.newtag))
3513 return FAIL;
3514 break;
3515 }
3516 return SUCCEED;
3517 }
3518
3519 /******************************************************************************
3520 * *
3521 * Function: zbx_dbsync_compare_corr_conditions *
3522 * *
3523 * Purpose: compares correlation condition tables with cached configuration *
3524 * data *
3525 * *
3526 * Parameter: sync - [OUT] the changeset *
3527 * *
3528 * Return value: SUCCEED - the changeset was successfully calculated *
3529 * FAIL - otherwise *
3530 * *
3531 ******************************************************************************/
zbx_dbsync_compare_corr_conditions(zbx_dbsync_t * sync)3532 int zbx_dbsync_compare_corr_conditions(zbx_dbsync_t *sync)
3533 {
3534 DB_ROW dbrow;
3535 DB_RESULT result;
3536 zbx_hashset_t ids;
3537 zbx_hashset_iter_t iter;
3538 zbx_uint64_t rowid;
3539 zbx_dc_corr_condition_t *corr_condition;
3540
3541 if (NULL == (result = DBselect(
3542 "select cc.corr_conditionid,cc.correlationid,cc.type,cct.tag,cctv.tag,cctv.value,cctv.operator,"
3543 " ccg.groupid,ccg.operator,cctp.oldtag,cctp.newtag"
3544 " from correlation c,corr_condition cc"
3545 " left join corr_condition_tag cct"
3546 " on cct.corr_conditionid=cc.corr_conditionid"
3547 " left join corr_condition_tagvalue cctv"
3548 " on cctv.corr_conditionid=cc.corr_conditionid"
3549 " left join corr_condition_group ccg"
3550 " on ccg.corr_conditionid=cc.corr_conditionid"
3551 " left join corr_condition_tagpair cctp"
3552 " on cctp.corr_conditionid=cc.corr_conditionid"
3553 " where c.correlationid=cc.correlationid"
3554 " and c.status=%d",
3555 ZBX_CORRELATION_ENABLED)))
3556 {
3557 return FAIL;
3558 }
3559
3560 dbsync_prepare(sync, 11, NULL);
3561
3562 if (ZBX_DBSYNC_INIT == sync->mode)
3563 {
3564 sync->dbresult = result;
3565 return SUCCEED;
3566 }
3567
3568 zbx_hashset_create(&ids, dbsync_env.cache->corr_conditions.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
3569 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3570
3571 while (NULL != (dbrow = DBfetch(result)))
3572 {
3573 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
3574
3575 ZBX_STR2UINT64(rowid, dbrow[0]);
3576 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
3577
3578 if (NULL == (corr_condition = (zbx_dc_corr_condition_t *)zbx_hashset_search(
3579 &dbsync_env.cache->corr_conditions, &rowid)))
3580 {
3581 tag = ZBX_DBSYNC_ROW_ADD;
3582 }
3583 else if (FAIL == dbsync_compare_corr_condition(corr_condition, dbrow))
3584 tag = ZBX_DBSYNC_ROW_UPDATE;
3585
3586 if (ZBX_DBSYNC_ROW_NONE != tag)
3587 dbsync_add_row(sync, rowid, tag, dbrow);
3588 }
3589
3590 zbx_hashset_iter_reset(&dbsync_env.cache->corr_conditions, &iter);
3591 while (NULL != (corr_condition = (zbx_dc_corr_condition_t *)zbx_hashset_iter_next(&iter)))
3592 {
3593 if (NULL == zbx_hashset_search(&ids, &corr_condition->corr_conditionid))
3594 dbsync_add_row(sync, corr_condition->corr_conditionid, ZBX_DBSYNC_ROW_REMOVE, NULL);
3595 }
3596
3597 zbx_hashset_destroy(&ids);
3598 DBfree_result(result);
3599
3600 return SUCCEED;
3601 }
3602
3603
3604 /******************************************************************************
3605 * *
3606 * Function: dbsync_compare_corr_operation *
3607 * *
3608 * Purpose: compares correlation operation tables dbrow with cached *
3609 * configuration data *
3610 * *
3611 * Parameter: corr_operation - [IN] the cached correlation operation *
3612 * dbrow - [IN] the database row *
3613 * *
3614 * Return value: SUCCEED - the row matches configuration data *
3615 * FAIL - otherwise *
3616 * *
3617 ******************************************************************************/
dbsync_compare_corr_operation(const zbx_dc_corr_operation_t * corr_operation,const DB_ROW dbrow)3618 static int dbsync_compare_corr_operation(const zbx_dc_corr_operation_t *corr_operation, const DB_ROW dbrow)
3619 {
3620 if (FAIL == dbsync_compare_uint64(dbrow[1], corr_operation->correlationid))
3621 return FAIL;
3622
3623 if (FAIL == dbsync_compare_uchar(dbrow[2], corr_operation->type))
3624 return FAIL;
3625
3626 return SUCCEED;
3627 }
3628
3629 /******************************************************************************
3630 * *
3631 * Function: zbx_dbsync_compare_corr_operations *
3632 * *
3633 * Purpose: compares correlation operation tables with cached configuration *
3634 * data *
3635 * *
3636 * Parameter: sync - [OUT] the changeset *
3637 * *
3638 * Return value: SUCCEED - the changeset was successfully calculated *
3639 * FAIL - otherwise *
3640 * *
3641 ******************************************************************************/
zbx_dbsync_compare_corr_operations(zbx_dbsync_t * sync)3642 int zbx_dbsync_compare_corr_operations(zbx_dbsync_t *sync)
3643 {
3644 DB_ROW dbrow;
3645 DB_RESULT result;
3646 zbx_hashset_t ids;
3647 zbx_hashset_iter_t iter;
3648 zbx_uint64_t rowid;
3649 zbx_dc_corr_operation_t *corr_operation;
3650
3651 if (NULL == (result = DBselect(
3652 "select co.corr_operationid,co.correlationid,co.type"
3653 " from correlation c,corr_operation co"
3654 " where c.correlationid=co.correlationid"
3655 " and c.status=%d",
3656 ZBX_CORRELATION_ENABLED)))
3657 {
3658 return FAIL;
3659 }
3660
3661 dbsync_prepare(sync, 3, NULL);
3662
3663 if (ZBX_DBSYNC_INIT == sync->mode)
3664 {
3665 sync->dbresult = result;
3666 return SUCCEED;
3667 }
3668
3669 zbx_hashset_create(&ids, dbsync_env.cache->corr_operations.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
3670 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3671
3672 while (NULL != (dbrow = DBfetch(result)))
3673 {
3674 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
3675
3676 ZBX_STR2UINT64(rowid, dbrow[0]);
3677 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
3678
3679 if (NULL == (corr_operation = (zbx_dc_corr_operation_t *)zbx_hashset_search(
3680 &dbsync_env.cache->corr_operations, &rowid)))
3681 {
3682 tag = ZBX_DBSYNC_ROW_ADD;
3683 }
3684 else if (FAIL == dbsync_compare_corr_operation(corr_operation, dbrow))
3685 tag = ZBX_DBSYNC_ROW_UPDATE;
3686
3687 if (ZBX_DBSYNC_ROW_NONE != tag)
3688 dbsync_add_row(sync, rowid, tag, dbrow);
3689 }
3690
3691 zbx_hashset_iter_reset(&dbsync_env.cache->corr_operations, &iter);
3692 while (NULL != (corr_operation = (zbx_dc_corr_operation_t *)zbx_hashset_iter_next(&iter)))
3693 {
3694 if (NULL == zbx_hashset_search(&ids, &corr_operation->corr_operationid))
3695 dbsync_add_row(sync, corr_operation->corr_operationid, ZBX_DBSYNC_ROW_REMOVE, NULL);
3696 }
3697
3698 zbx_hashset_destroy(&ids);
3699 DBfree_result(result);
3700
3701 return SUCCEED;
3702 }
3703
3704 /******************************************************************************
3705 * *
3706 * Function: dbsync_compare_host_group *
3707 * *
3708 * Purpose: compares host group table row with cached configuration data *
3709 * *
3710 * Parameter: group - [IN] the cached host group *
3711 * dbrow - [IN] the database row *
3712 * *
3713 * Return value: SUCCEED - the row matches configuration data *
3714 * FAIL - otherwise *
3715 * *
3716 ******************************************************************************/
dbsync_compare_host_group(const zbx_dc_hostgroup_t * group,const DB_ROW dbrow)3717 static int dbsync_compare_host_group(const zbx_dc_hostgroup_t *group, const DB_ROW dbrow)
3718 {
3719 if (FAIL == dbsync_compare_str(dbrow[1], group->name))
3720 return FAIL;
3721
3722 return SUCCEED;
3723 }
3724
3725 /******************************************************************************
3726 * *
3727 * Function: zbx_dbsync_compare_host_groups *
3728 * *
3729 * Purpose: compares host groups table with cached configuration data *
3730 * *
3731 * Parameter: sync - [OUT] the changeset *
3732 * *
3733 * Return value: SUCCEED - the changeset was successfully calculated *
3734 * FAIL - otherwise *
3735 * *
3736 ******************************************************************************/
zbx_dbsync_compare_host_groups(zbx_dbsync_t * sync)3737 int zbx_dbsync_compare_host_groups(zbx_dbsync_t *sync)
3738 {
3739 DB_ROW dbrow;
3740 DB_RESULT result;
3741 zbx_hashset_t ids;
3742 zbx_hashset_iter_t iter;
3743 zbx_uint64_t rowid;
3744 zbx_dc_hostgroup_t *group;
3745
3746 if (NULL == (result = DBselect("select groupid,name from hstgrp")))
3747 return FAIL;
3748
3749 dbsync_prepare(sync, 2, NULL);
3750
3751 if (ZBX_DBSYNC_INIT == sync->mode)
3752 {
3753 sync->dbresult = result;
3754 return SUCCEED;
3755 }
3756
3757 zbx_hashset_create(&ids, dbsync_env.cache->hostgroups.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
3758 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3759
3760 while (NULL != (dbrow = DBfetch(result)))
3761 {
3762 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
3763
3764 ZBX_STR2UINT64(rowid, dbrow[0]);
3765 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
3766
3767 if (NULL == (group = (zbx_dc_hostgroup_t *)zbx_hashset_search(&dbsync_env.cache->hostgroups, &rowid)))
3768 tag = ZBX_DBSYNC_ROW_ADD;
3769 else if (FAIL == dbsync_compare_host_group(group, dbrow))
3770 tag = ZBX_DBSYNC_ROW_UPDATE;
3771
3772 if (ZBX_DBSYNC_ROW_NONE != tag)
3773 dbsync_add_row(sync, rowid, tag, dbrow);
3774 }
3775
3776 zbx_hashset_iter_reset(&dbsync_env.cache->hostgroups, &iter);
3777 while (NULL != (group = (zbx_dc_hostgroup_t *)zbx_hashset_iter_next(&iter)))
3778 {
3779 if (NULL == zbx_hashset_search(&ids, &group->groupid))
3780 dbsync_add_row(sync, group->groupid, ZBX_DBSYNC_ROW_REMOVE, NULL);
3781 }
3782
3783 zbx_hashset_destroy(&ids);
3784 DBfree_result(result);
3785
3786 return SUCCEED;
3787 }
3788
3789 /******************************************************************************
3790 * *
3791 * Function: dbsync_item_pp_preproc_row *
3792 * *
3793 * Purpose: applies necessary preprocessing before row is compared/used *
3794 * *
3795 * Parameter: row - [IN] the row to preprocess *
3796 * *
3797 * Return value: the preprocessed row of item_preproc table *
3798 * *
3799 * Comments: The row preprocessing can be used to expand user macros in *
3800 * some columns. *
3801 * *
3802 ******************************************************************************/
dbsync_item_pp_preproc_row(char ** row)3803 static char **dbsync_item_pp_preproc_row(char **row)
3804 {
3805 #define ZBX_DBSYNC_ITEM_PP_COLUMN_PARAM 0x01
3806 #define ZBX_DBSYNC_ITEM_PP_COLUMN_ERR_PARAM 0x02
3807
3808 zbx_uint64_t hostid;
3809 unsigned int flags = 0;
3810
3811 if (SUCCEED == dbsync_check_row_macros(row, 3))
3812 flags |= ZBX_DBSYNC_ITEM_PP_COLUMN_PARAM;
3813
3814 if (SUCCEED == dbsync_check_row_macros(row, 7))
3815 flags |= ZBX_DBSYNC_ITEM_PP_COLUMN_ERR_PARAM;
3816
3817 if (0 != flags)
3818 {
3819 ZBX_STR2UINT64(hostid, row[5]);
3820
3821 if (0 != (flags & ZBX_DBSYNC_ITEM_PP_COLUMN_PARAM))
3822 row[3] = dc_expand_user_macros(row[3], &hostid, 1);
3823
3824 if (0 != (flags & ZBX_DBSYNC_ITEM_PP_COLUMN_ERR_PARAM))
3825 row[7] = dc_expand_user_macros(row[7], &hostid, 1);
3826 }
3827
3828 return row;
3829
3830 #undef ZBX_DBSYNC_ITEM_PP_COLUMN_PARAM
3831 #undef ZBX_DBSYNC_ITEM_PP_COLUMN_ERR_PARAM
3832 }
3833
3834 /******************************************************************************
3835 * *
3836 * Function: dbsync_compare_item_preproc *
3837 * *
3838 * Purpose: compares item preproc table row with cached configuration data *
3839 * *
3840 * Parameter: preproc - [IN] the cached item preprocessing operation *
3841 * dbrow - [IN] the database row *
3842 * *
3843 * Return value: SUCCEED - the row matches configuration data *
3844 * FAIL - otherwise *
3845 * *
3846 ******************************************************************************/
dbsync_compare_item_preproc(const zbx_dc_preproc_op_t * preproc,const DB_ROW dbrow)3847 static int dbsync_compare_item_preproc(const zbx_dc_preproc_op_t *preproc, const DB_ROW dbrow)
3848 {
3849 if (FAIL == dbsync_compare_uint64(dbrow[1], preproc->itemid))
3850 return FAIL;
3851
3852 if (FAIL == dbsync_compare_uchar(dbrow[2], preproc->type))
3853 return FAIL;
3854
3855 if (FAIL == dbsync_compare_str(dbrow[3], preproc->params))
3856 return FAIL;
3857
3858 if (FAIL == dbsync_compare_int(dbrow[4], preproc->step))
3859 return FAIL;
3860
3861 if (FAIL == dbsync_compare_int(dbrow[6], preproc->error_handler))
3862 return FAIL;
3863
3864 if (FAIL == dbsync_compare_str(dbrow[7], preproc->error_handler_params))
3865 return FAIL;
3866
3867 return SUCCEED;
3868 }
3869
3870 /******************************************************************************
3871 * *
3872 * Function: zbx_dbsync_compare_item_preprocessing *
3873 * *
3874 * Purpose: compares item preproc tables with cached configuration data *
3875 * *
3876 * Parameter: sync - [OUT] the changeset *
3877 * *
3878 * Return value: SUCCEED - the changeset was successfully calculated *
3879 * FAIL - otherwise *
3880 * *
3881 ******************************************************************************/
zbx_dbsync_compare_item_preprocs(zbx_dbsync_t * sync)3882 int zbx_dbsync_compare_item_preprocs(zbx_dbsync_t *sync)
3883 {
3884 DB_ROW dbrow;
3885 DB_RESULT result;
3886 zbx_hashset_t ids;
3887 zbx_hashset_iter_t iter;
3888 zbx_uint64_t rowid;
3889 zbx_dc_preproc_op_t *preproc;
3890 char **row;
3891
3892 if (NULL == (result = DBselect(
3893 "select pp.item_preprocid,pp.itemid,pp.type,pp.params,pp.step,i.hostid,pp.error_handler,"
3894 "pp.error_handler_params,i.type,i.key_,h.proxy_hostid"
3895 " from item_preproc pp,items i,hosts h"
3896 " where pp.itemid=i.itemid"
3897 " and i.hostid=h.hostid"
3898 " and (h.proxy_hostid is null"
3899 " or i.type in (%d,%d,%d))"
3900 " and h.status in (%d,%d)"
3901 " and i.flags<>%d"
3902 " order by pp.itemid",
3903 ITEM_TYPE_INTERNAL, ITEM_TYPE_CALCULATED, ITEM_TYPE_DEPENDENT,
3904 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
3905 ZBX_FLAG_DISCOVERY_PROTOTYPE)))
3906 {
3907 return FAIL;
3908 }
3909
3910 dbsync_prepare(sync, 8, dbsync_item_pp_preproc_row);
3911
3912 if (ZBX_DBSYNC_INIT == sync->mode)
3913 {
3914 sync->dbresult = result;
3915 return SUCCEED;
3916 }
3917
3918 zbx_hashset_create(&ids, dbsync_env.cache->hostgroups.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
3919 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3920
3921 while (NULL != (dbrow = DBfetch(result)))
3922 {
3923 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
3924 unsigned char type;
3925
3926 ZBX_STR2UCHAR(type, dbrow[8]);
3927
3928 /* Sync preproccessing for all dependent items as they can depend on item processed by Zabbx server, */
3929 /* avoid syncing preprocessing for internal items monitored by Zabbix proxy */
3930 if (type != ITEM_TYPE_DEPENDENT && SUCCEED != DBis_null(dbrow[10]) &&
3931 SUCCEED != is_item_processed_by_server(type, dbrow[9]))
3932 {
3933 continue;
3934 }
3935
3936 ZBX_STR2UINT64(rowid, dbrow[0]);
3937 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
3938
3939 row = dbsync_preproc_row(sync, dbrow);
3940
3941 if (NULL == (preproc = (zbx_dc_preproc_op_t *)zbx_hashset_search(&dbsync_env.cache->preprocops,
3942 &rowid)))
3943 {
3944 tag = ZBX_DBSYNC_ROW_ADD;
3945 }
3946 else if (FAIL == dbsync_compare_item_preproc(preproc, row))
3947 tag = ZBX_DBSYNC_ROW_UPDATE;
3948
3949 if (ZBX_DBSYNC_ROW_NONE != tag)
3950 dbsync_add_row(sync, rowid, tag, row);
3951 }
3952
3953 zbx_hashset_iter_reset(&dbsync_env.cache->preprocops, &iter);
3954
3955 while (NULL != (preproc = (zbx_dc_preproc_op_t *)zbx_hashset_iter_next(&iter)))
3956 {
3957 if (NULL == zbx_hashset_search(&ids, &preproc->item_preprocid))
3958 dbsync_add_row(sync, preproc->item_preprocid, ZBX_DBSYNC_ROW_REMOVE, NULL);
3959 }
3960
3961 zbx_hashset_destroy(&ids);
3962 DBfree_result(result);
3963
3964 return SUCCEED;
3965 }
3966
3967 /******************************************************************************
3968 * *
3969 * Function: dbsync_compare_maintenance *
3970 * *
3971 * Purpose: compares maintenance table row with cached configuration data *
3972 * *
3973 * Parameter: maintenance - [IN] the cached maintenance data *
3974 * dbrow - [IN] the database row *
3975 * *
3976 * Return value: SUCCEED - the row matches configuration data *
3977 * FAIL - otherwise *
3978 * *
3979 ******************************************************************************/
dbsync_compare_maintenance(const zbx_dc_maintenance_t * maintenance,const DB_ROW dbrow)3980 static int dbsync_compare_maintenance(const zbx_dc_maintenance_t *maintenance, const DB_ROW dbrow)
3981 {
3982 if (FAIL == dbsync_compare_uchar(dbrow[1], maintenance->type))
3983 return FAIL;
3984
3985 if (FAIL == dbsync_compare_int(dbrow[2], maintenance->active_since))
3986 return FAIL;
3987
3988 if (FAIL == dbsync_compare_int(dbrow[3], maintenance->active_until))
3989 return FAIL;
3990
3991 if (FAIL == dbsync_compare_uchar(dbrow[4], maintenance->tags_evaltype))
3992 return FAIL;
3993
3994 return SUCCEED;
3995 }
3996
3997 /******************************************************************************
3998 * *
3999 * Function: dbsync_compare_itemscript_param *
4000 * *
4001 * Purpose: compares item script params table row with cached configuration *
4002 * data *
4003 * *
4004 * Parameter: script - [IN] the cached item script *
4005 * dbrow - [IN] the database row *
4006 * *
4007 * Return value: SUCCEED - the row matches configuration data *
4008 * FAIL - otherwise *
4009 * *
4010 ******************************************************************************/
dbsync_compare_itemscript_param(const zbx_dc_scriptitem_param_t * scriptitem_param,const DB_ROW dbrow)4011 static int dbsync_compare_itemscript_param(const zbx_dc_scriptitem_param_t *scriptitem_param, const DB_ROW dbrow)
4012 {
4013 if (FAIL == dbsync_compare_uint64(dbrow[1], scriptitem_param->itemid))
4014 return FAIL;
4015
4016 if (FAIL == dbsync_compare_str(dbrow[2], scriptitem_param->name))
4017 return FAIL;
4018
4019 if (FAIL == dbsync_compare_str(dbrow[3], scriptitem_param->value))
4020 return FAIL;
4021
4022 return SUCCEED;
4023 }
4024
4025 /******************************************************************************
4026 * *
4027 * Function: zbx_dbsync_compare_item_script_param *
4028 * *
4029 * Purpose: compares item_parameter table with cached configuration data *
4030 * *
4031 * Parameter: sync - [OUT] the changeset *
4032 * *
4033 * Return value: SUCCEED - the changeset was successfully calculated *
4034 * FAIL - otherwise *
4035 * *
4036 ******************************************************************************/
zbx_dbsync_compare_item_script_param(zbx_dbsync_t * sync)4037 int zbx_dbsync_compare_item_script_param(zbx_dbsync_t *sync)
4038 {
4039 DB_ROW dbrow;
4040 DB_RESULT result;
4041 zbx_hashset_t ids;
4042 zbx_hashset_iter_t iter;
4043 zbx_uint64_t rowid;
4044 zbx_dc_scriptitem_param_t *itemscript_params;
4045 char **row;
4046
4047 if (NULL == (result = DBselect(
4048 "select p.item_parameterid,p.itemid,p.name,p.value,i.hostid"
4049 " from item_parameter p,items i,hosts h"
4050 " where p.itemid=i.itemid"
4051 " and i.hostid=h.hostid"
4052 " and h.status in (%d,%d)"
4053 " and i.flags<>%d"
4054 " order by p.itemid",
4055 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
4056 ZBX_FLAG_DISCOVERY_PROTOTYPE)))
4057 {
4058 return FAIL;
4059 }
4060
4061 dbsync_prepare(sync, 5, NULL);
4062
4063 if (ZBX_DBSYNC_INIT == sync->mode)
4064 {
4065 sync->dbresult = result;
4066 return SUCCEED;
4067 }
4068
4069 zbx_hashset_create(&ids, dbsync_env.cache->itemscript_params.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
4070 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
4071
4072 while (NULL != (dbrow = DBfetch(result)))
4073 {
4074 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
4075
4076 ZBX_STR2UINT64(rowid, dbrow[0]);
4077 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
4078
4079 row = dbsync_preproc_row(sync, dbrow);
4080
4081 if (NULL == (itemscript_params = (zbx_dc_scriptitem_param_t *)
4082 zbx_hashset_search(&dbsync_env.cache->itemscript_params, &rowid)))
4083 {
4084 tag = ZBX_DBSYNC_ROW_ADD;
4085 }
4086 else if (FAIL == dbsync_compare_itemscript_param(itemscript_params, row))
4087 {
4088 tag = ZBX_DBSYNC_ROW_UPDATE;
4089 }
4090
4091 if (ZBX_DBSYNC_ROW_NONE != tag)
4092 dbsync_add_row(sync, rowid, tag, row);
4093 }
4094
4095 zbx_hashset_iter_reset(&dbsync_env.cache->itemscript_params, &iter);
4096
4097 while (NULL != (itemscript_params = (zbx_dc_scriptitem_param_t *)zbx_hashset_iter_next(&iter)))
4098 {
4099 if (NULL == zbx_hashset_search(&ids, &itemscript_params->item_script_paramid))
4100 dbsync_add_row(sync, itemscript_params->item_script_paramid, ZBX_DBSYNC_ROW_REMOVE, NULL);
4101 }
4102
4103 zbx_hashset_destroy(&ids);
4104 DBfree_result(result);
4105
4106 return SUCCEED;
4107 }
4108
4109 /******************************************************************************
4110 * *
4111 * Function: zbx_dbsync_compare_maintenances *
4112 * *
4113 * Purpose: compares maintenances table with cached configuration data *
4114 * *
4115 * Parameter: sync - [OUT] the changeset *
4116 * *
4117 * Return value: SUCCEED - the changeset was successfully calculated *
4118 * FAIL - otherwise *
4119 * *
4120 ******************************************************************************/
zbx_dbsync_compare_maintenances(zbx_dbsync_t * sync)4121 int zbx_dbsync_compare_maintenances(zbx_dbsync_t *sync)
4122 {
4123 DB_ROW dbrow;
4124 DB_RESULT result;
4125 zbx_hashset_t ids;
4126 zbx_hashset_iter_t iter;
4127 zbx_uint64_t rowid;
4128 zbx_dc_maintenance_t *maintenance;
4129
4130 if (NULL == (result = DBselect("select maintenanceid,maintenance_type,active_since,active_till,tags_evaltype"
4131 " from maintenances")))
4132 {
4133 return FAIL;
4134 }
4135
4136 dbsync_prepare(sync, 5, NULL);
4137
4138 if (ZBX_DBSYNC_INIT == sync->mode)
4139 {
4140 sync->dbresult = result;
4141 return SUCCEED;
4142 }
4143
4144 zbx_hashset_create(&ids, dbsync_env.cache->maintenances.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
4145 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
4146
4147 while (NULL != (dbrow = DBfetch(result)))
4148 {
4149 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
4150
4151 ZBX_STR2UINT64(rowid, dbrow[0]);
4152 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
4153
4154 maintenance = (zbx_dc_maintenance_t *)zbx_hashset_search(&dbsync_env.cache->maintenances, &rowid);
4155
4156 if (NULL == maintenance)
4157 tag = ZBX_DBSYNC_ROW_ADD;
4158 else if (FAIL == dbsync_compare_maintenance(maintenance, dbrow))
4159 tag = ZBX_DBSYNC_ROW_UPDATE;
4160
4161 if (ZBX_DBSYNC_ROW_NONE != tag)
4162 dbsync_add_row(sync, rowid, tag, dbrow);
4163 }
4164
4165 zbx_hashset_iter_reset(&dbsync_env.cache->maintenances, &iter);
4166 while (NULL != (maintenance = (zbx_dc_maintenance_t *)zbx_hashset_iter_next(&iter)))
4167 {
4168 if (NULL == zbx_hashset_search(&ids, &maintenance->maintenanceid))
4169 dbsync_add_row(sync, maintenance->maintenanceid, ZBX_DBSYNC_ROW_REMOVE, NULL);
4170 }
4171
4172 zbx_hashset_destroy(&ids);
4173 DBfree_result(result);
4174
4175 return SUCCEED;
4176 }
4177
4178 /******************************************************************************
4179 * *
4180 * Function: dbsync_compare_maintenance_tag *
4181 * *
4182 * Purpose: compares maintenance_tag table row with cached configuration data *
4183 * *
4184 * Parameter: maintenance_tag - [IN] the cached maintenance tag *
4185 * dbrow - [IN] the database row *
4186 * *
4187 * Return value: SUCCEED - the row matches configuration data *
4188 * FAIL - otherwise *
4189 * *
4190 ******************************************************************************/
dbsync_compare_maintenance_tag(const zbx_dc_maintenance_tag_t * maintenance_tag,const DB_ROW dbrow)4191 static int dbsync_compare_maintenance_tag(const zbx_dc_maintenance_tag_t *maintenance_tag, const DB_ROW dbrow)
4192 {
4193 if (FAIL == dbsync_compare_int(dbrow[2], maintenance_tag->op))
4194 return FAIL;
4195
4196 if (FAIL == dbsync_compare_str(dbrow[3], maintenance_tag->tag))
4197 return FAIL;
4198
4199 if (FAIL == dbsync_compare_str(dbrow[4], maintenance_tag->value))
4200 return FAIL;
4201
4202 return SUCCEED;
4203 }
4204
4205 /******************************************************************************
4206 * *
4207 * Function: zbx_dbsync_compare_maintenance_tags *
4208 * *
4209 * Purpose: compares maintenances table with cached configuration data *
4210 * *
4211 * Parameter: sync - [OUT] the changeset *
4212 * *
4213 * Return value: SUCCEED - the changeset was successfully calculated *
4214 * FAIL - otherwise *
4215 * *
4216 ******************************************************************************/
zbx_dbsync_compare_maintenance_tags(zbx_dbsync_t * sync)4217 int zbx_dbsync_compare_maintenance_tags(zbx_dbsync_t *sync)
4218 {
4219 DB_ROW dbrow;
4220 DB_RESULT result;
4221 zbx_hashset_t ids;
4222 zbx_hashset_iter_t iter;
4223 zbx_uint64_t rowid;
4224 zbx_dc_maintenance_tag_t *maintenance_tag;
4225
4226 if (NULL == (result = DBselect("select maintenancetagid,maintenanceid,operator,tag,value"
4227 " from maintenance_tag")))
4228 {
4229 return FAIL;
4230 }
4231
4232 dbsync_prepare(sync, 5, NULL);
4233
4234 if (ZBX_DBSYNC_INIT == sync->mode)
4235 {
4236 sync->dbresult = result;
4237 return SUCCEED;
4238 }
4239
4240 zbx_hashset_create(&ids, dbsync_env.cache->maintenance_tags.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
4241 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
4242
4243 while (NULL != (dbrow = DBfetch(result)))
4244 {
4245 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
4246
4247 ZBX_STR2UINT64(rowid, dbrow[0]);
4248 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
4249
4250 maintenance_tag = (zbx_dc_maintenance_tag_t *)zbx_hashset_search(&dbsync_env.cache->maintenance_tags,
4251 &rowid);
4252
4253 if (NULL == maintenance_tag)
4254 tag = ZBX_DBSYNC_ROW_ADD;
4255 else if (FAIL == dbsync_compare_maintenance_tag(maintenance_tag, dbrow))
4256 tag = ZBX_DBSYNC_ROW_UPDATE;
4257
4258 if (ZBX_DBSYNC_ROW_NONE != tag)
4259 dbsync_add_row(sync, rowid, tag, dbrow);
4260 }
4261
4262 zbx_hashset_iter_reset(&dbsync_env.cache->maintenance_tags, &iter);
4263 while (NULL != (maintenance_tag = (zbx_dc_maintenance_tag_t *)zbx_hashset_iter_next(&iter)))
4264 {
4265 if (NULL == zbx_hashset_search(&ids, &maintenance_tag->maintenancetagid))
4266 dbsync_add_row(sync, maintenance_tag->maintenancetagid, ZBX_DBSYNC_ROW_REMOVE, NULL);
4267 }
4268
4269 zbx_hashset_destroy(&ids);
4270 DBfree_result(result);
4271
4272 return SUCCEED;
4273 }
4274
4275 /******************************************************************************
4276 * *
4277 * Function: dbsync_compare_maintenance_period *
4278 * *
4279 * Purpose: compares maintenance_period table row with cached configuration *
4280 * dat *
4281 * *
4282 * Parameter: period - [IN] the cached maintenance period *
4283 * dbrow - [IN] the database row *
4284 * *
4285 * Return value: SUCCEED - the row matches configuration data *
4286 * FAIL - otherwise *
4287 * *
4288 ******************************************************************************/
dbsync_compare_maintenance_period(const zbx_dc_maintenance_period_t * period,const DB_ROW dbrow)4289 static int dbsync_compare_maintenance_period(const zbx_dc_maintenance_period_t *period, const DB_ROW dbrow)
4290 {
4291 if (FAIL == dbsync_compare_uchar(dbrow[1], period->type))
4292 return FAIL;
4293
4294 if (FAIL == dbsync_compare_int(dbrow[2], period->every))
4295 return FAIL;
4296
4297 if (FAIL == dbsync_compare_int(dbrow[3], period->month))
4298 return FAIL;
4299
4300 if (FAIL == dbsync_compare_int(dbrow[4], period->dayofweek))
4301 return FAIL;
4302
4303 if (FAIL == dbsync_compare_int(dbrow[5], period->day))
4304 return FAIL;
4305
4306 if (FAIL == dbsync_compare_int(dbrow[6], period->start_time))
4307 return FAIL;
4308
4309 if (FAIL == dbsync_compare_int(dbrow[7], period->period))
4310 return FAIL;
4311
4312 if (FAIL == dbsync_compare_int(dbrow[8], period->start_date))
4313 return FAIL;
4314
4315 return SUCCEED;
4316 }
4317
4318 /******************************************************************************
4319 * *
4320 * Function: zbx_dbsync_compare_maintenance_periods *
4321 * *
4322 * Purpose: compares timeperiods table with cached configuration data *
4323 * *
4324 * Parameter: sync - [OUT] the changeset *
4325 * *
4326 * Return value: SUCCEED - the changeset was successfully calculated *
4327 * FAIL - otherwise *
4328 * *
4329 ******************************************************************************/
zbx_dbsync_compare_maintenance_periods(zbx_dbsync_t * sync)4330 int zbx_dbsync_compare_maintenance_periods(zbx_dbsync_t *sync)
4331 {
4332 DB_ROW dbrow;
4333 DB_RESULT result;
4334 zbx_hashset_t ids;
4335 zbx_hashset_iter_t iter;
4336 zbx_uint64_t rowid;
4337 zbx_dc_maintenance_period_t *period;
4338
4339 if (NULL == (result = DBselect("select t.timeperiodid,t.timeperiod_type,t.every,t.month,t.dayofweek,t.day,"
4340 "t.start_time,t.period,t.start_date,m.maintenanceid"
4341 " from maintenances_windows m,timeperiods t"
4342 " where t.timeperiodid=m.timeperiodid")))
4343 {
4344 return FAIL;
4345 }
4346
4347 dbsync_prepare(sync, 10, NULL);
4348
4349 if (ZBX_DBSYNC_INIT == sync->mode)
4350 {
4351 sync->dbresult = result;
4352 return SUCCEED;
4353 }
4354
4355 zbx_hashset_create(&ids, dbsync_env.cache->maintenance_periods.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
4356 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
4357
4358 while (NULL != (dbrow = DBfetch(result)))
4359 {
4360 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
4361
4362 ZBX_STR2UINT64(rowid, dbrow[0]);
4363 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
4364
4365 period = (zbx_dc_maintenance_period_t *)zbx_hashset_search(&dbsync_env.cache->maintenance_periods,
4366 &rowid);
4367
4368 if (NULL == period)
4369 tag = ZBX_DBSYNC_ROW_ADD;
4370 else if (FAIL == dbsync_compare_maintenance_period(period, dbrow))
4371 tag = ZBX_DBSYNC_ROW_UPDATE;
4372
4373 if (ZBX_DBSYNC_ROW_NONE != tag)
4374 dbsync_add_row(sync, rowid, tag, dbrow);
4375 }
4376
4377 zbx_hashset_iter_reset(&dbsync_env.cache->maintenance_periods, &iter);
4378 while (NULL != (period = (zbx_dc_maintenance_period_t *)zbx_hashset_iter_next(&iter)))
4379 {
4380 if (NULL == zbx_hashset_search(&ids, &period->timeperiodid))
4381 dbsync_add_row(sync, period->timeperiodid, ZBX_DBSYNC_ROW_REMOVE, NULL);
4382 }
4383
4384 zbx_hashset_destroy(&ids);
4385 DBfree_result(result);
4386
4387 return SUCCEED;
4388 }
4389
4390 /******************************************************************************
4391 * *
4392 * Function: zbx_dbsync_compare_maintenance_groups *
4393 * *
4394 * Purpose: compares maintenances_groups table with cached configuration data *
4395 * *
4396 * Parameter: sync - [OUT] the changeset *
4397 * *
4398 * Return value: SUCCEED - the changeset was successfully calculated *
4399 * FAIL - otherwise *
4400 * *
4401 ******************************************************************************/
zbx_dbsync_compare_maintenance_groups(zbx_dbsync_t * sync)4402 int zbx_dbsync_compare_maintenance_groups(zbx_dbsync_t *sync)
4403 {
4404 DB_ROW dbrow;
4405 DB_RESULT result;
4406 zbx_hashset_iter_t iter;
4407 zbx_dc_maintenance_t *maintenance;
4408 zbx_hashset_t mgroups;
4409 int i;
4410 zbx_uint64_pair_t mg_local, *mg;
4411 char maintenanceid_s[MAX_ID_LEN + 1], groupid_s[MAX_ID_LEN + 1];
4412 char *del_row[2] = {maintenanceid_s, groupid_s};
4413
4414 if (NULL == (result = DBselect("select maintenanceid,groupid from maintenances_groups order by maintenanceid")))
4415 return FAIL;
4416
4417 dbsync_prepare(sync, 2, NULL);
4418
4419 if (ZBX_DBSYNC_INIT == sync->mode)
4420 {
4421 sync->dbresult = result;
4422 return SUCCEED;
4423 }
4424
4425 zbx_hashset_create(&mgroups, 100, ZBX_DEFAULT_UINT64_PAIR_HASH_FUNC, ZBX_DEFAULT_UINT64_PAIR_COMPARE_FUNC);
4426
4427 /* index all maintenance->group links */
4428 zbx_hashset_iter_reset(&dbsync_env.cache->maintenances, &iter);
4429 while (NULL != (maintenance = (zbx_dc_maintenance_t *)zbx_hashset_iter_next(&iter)))
4430 {
4431 mg_local.first = maintenance->maintenanceid;
4432
4433 for (i = 0; i < maintenance->groupids.values_num; i++)
4434 {
4435 mg_local.second = maintenance->groupids.values[i];
4436 zbx_hashset_insert(&mgroups, &mg_local, sizeof(mg_local));
4437 }
4438 }
4439
4440 /* add new rows, remove existing rows from index */
4441 while (NULL != (dbrow = DBfetch(result)))
4442 {
4443 ZBX_STR2UINT64(mg_local.first, dbrow[0]);
4444 ZBX_STR2UINT64(mg_local.second, dbrow[1]);
4445
4446 if (NULL == (mg = (zbx_uint64_pair_t *)zbx_hashset_search(&mgroups, &mg_local)))
4447 dbsync_add_row(sync, 0, ZBX_DBSYNC_ROW_ADD, dbrow);
4448 else
4449 zbx_hashset_remove_direct(&mgroups, mg);
4450 }
4451
4452 /* add removed rows */
4453 zbx_hashset_iter_reset(&mgroups, &iter);
4454 while (NULL != (mg = (zbx_uint64_pair_t *)zbx_hashset_iter_next(&iter)))
4455 {
4456 zbx_snprintf(maintenanceid_s, sizeof(maintenanceid_s), ZBX_FS_UI64, mg->first);
4457 zbx_snprintf(groupid_s, sizeof(groupid_s), ZBX_FS_UI64, mg->second);
4458 dbsync_add_row(sync, 0, ZBX_DBSYNC_ROW_REMOVE, del_row);
4459 }
4460
4461 DBfree_result(result);
4462 zbx_hashset_destroy(&mgroups);
4463
4464 return SUCCEED;
4465 }
4466
4467 /******************************************************************************
4468 * *
4469 * Function: zbx_dbsync_compare_maintenance_hosts *
4470 * *
4471 * Purpose: compares maintenances_hosts table with cached configuration data *
4472 * *
4473 * Parameter: sync - [OUT] the changeset *
4474 * *
4475 * Return value: SUCCEED - the changeset was successfully calculated *
4476 * FAIL - otherwise *
4477 * *
4478 ******************************************************************************/
zbx_dbsync_compare_maintenance_hosts(zbx_dbsync_t * sync)4479 int zbx_dbsync_compare_maintenance_hosts(zbx_dbsync_t *sync)
4480 {
4481 DB_ROW dbrow;
4482 DB_RESULT result;
4483 zbx_hashset_iter_t iter;
4484 zbx_dc_maintenance_t *maintenance;
4485 zbx_hashset_t mhosts;
4486 int i;
4487 zbx_uint64_pair_t mh_local, *mh;
4488 char maintenanceid_s[MAX_ID_LEN + 1], hostid_s[MAX_ID_LEN + 1];
4489 char *del_row[2] = {maintenanceid_s, hostid_s};
4490
4491 if (NULL == (result = DBselect("select maintenanceid,hostid from maintenances_hosts order by maintenanceid")))
4492 return FAIL;
4493
4494 dbsync_prepare(sync, 2, NULL);
4495
4496 if (ZBX_DBSYNC_INIT == sync->mode)
4497 {
4498 sync->dbresult = result;
4499 return SUCCEED;
4500 }
4501
4502 zbx_hashset_create(&mhosts, 100, ZBX_DEFAULT_UINT64_PAIR_HASH_FUNC, ZBX_DEFAULT_UINT64_PAIR_COMPARE_FUNC);
4503
4504 /* index all maintenance->host links */
4505 zbx_hashset_iter_reset(&dbsync_env.cache->maintenances, &iter);
4506 while (NULL != (maintenance = (zbx_dc_maintenance_t *)zbx_hashset_iter_next(&iter)))
4507 {
4508 mh_local.first = maintenance->maintenanceid;
4509
4510 for (i = 0; i < maintenance->hostids.values_num; i++)
4511 {
4512 mh_local.second = maintenance->hostids.values[i];
4513 zbx_hashset_insert(&mhosts, &mh_local, sizeof(mh_local));
4514 }
4515 }
4516
4517 /* add new rows, remove existing rows from index */
4518 while (NULL != (dbrow = DBfetch(result)))
4519 {
4520 ZBX_STR2UINT64(mh_local.first, dbrow[0]);
4521 ZBX_STR2UINT64(mh_local.second, dbrow[1]);
4522
4523 if (NULL == (mh = (zbx_uint64_pair_t *)zbx_hashset_search(&mhosts, &mh_local)))
4524 dbsync_add_row(sync, 0, ZBX_DBSYNC_ROW_ADD, dbrow);
4525 else
4526 zbx_hashset_remove_direct(&mhosts, mh);
4527 }
4528
4529 /* add removed rows */
4530 zbx_hashset_iter_reset(&mhosts, &iter);
4531 while (NULL != (mh = (zbx_uint64_pair_t *)zbx_hashset_iter_next(&iter)))
4532 {
4533 zbx_snprintf(maintenanceid_s, sizeof(maintenanceid_s), ZBX_FS_UI64, mh->first);
4534 zbx_snprintf(hostid_s, sizeof(hostid_s), ZBX_FS_UI64, mh->second);
4535 dbsync_add_row(sync, 0, ZBX_DBSYNC_ROW_REMOVE, del_row);
4536 }
4537
4538 DBfree_result(result);
4539 zbx_hashset_destroy(&mhosts);
4540
4541 return SUCCEED;
4542 }
4543
4544 /******************************************************************************
4545 * *
4546 * Function: zbx_dbsync_compare_host_group_hosts *
4547 * *
4548 * Purpose: compares hosts_groups table with cached configuration data *
4549 * *
4550 * Parameter: sync - [OUT] the changeset *
4551 * *
4552 * Return value: SUCCEED - the changeset was successfully calculated *
4553 * FAIL - otherwise *
4554 * *
4555 ******************************************************************************/
zbx_dbsync_compare_host_group_hosts(zbx_dbsync_t * sync)4556 int zbx_dbsync_compare_host_group_hosts(zbx_dbsync_t *sync)
4557 {
4558 DB_ROW dbrow;
4559 DB_RESULT result;
4560 zbx_hashset_iter_t iter, iter_hosts;
4561 zbx_dc_hostgroup_t *group;
4562 zbx_hashset_t groups;
4563 zbx_uint64_t *phostid;
4564 zbx_uint64_pair_t gh_local, *gh;
4565 char groupid_s[MAX_ID_LEN + 1], hostid_s[MAX_ID_LEN + 1];
4566 char *del_row[2] = {groupid_s, hostid_s};
4567
4568 if (NULL == (result = DBselect(
4569 "select hg.groupid,hg.hostid"
4570 " from hosts_groups hg,hosts h"
4571 " where hg.hostid=h.hostid"
4572 " and h.status in (%d,%d)"
4573 " and h.flags<>%d"
4574 " order by hg.groupid",
4575 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED, ZBX_FLAG_DISCOVERY_PROTOTYPE)))
4576 {
4577 return FAIL;
4578 }
4579
4580 dbsync_prepare(sync, 2, NULL);
4581
4582 if (ZBX_DBSYNC_INIT == sync->mode)
4583 {
4584 sync->dbresult = result;
4585 return SUCCEED;
4586 }
4587
4588 zbx_hashset_create(&groups, 100, ZBX_DEFAULT_UINT64_PAIR_HASH_FUNC, ZBX_DEFAULT_UINT64_PAIR_COMPARE_FUNC);
4589
4590 /* index all group->host links */
4591 zbx_hashset_iter_reset(&dbsync_env.cache->hostgroups, &iter);
4592 while (NULL != (group = (zbx_dc_hostgroup_t *)zbx_hashset_iter_next(&iter)))
4593 {
4594 gh_local.first = group->groupid;
4595
4596 zbx_hashset_iter_reset(&group->hostids, &iter_hosts);
4597 while (NULL != (phostid = (zbx_uint64_t *)zbx_hashset_iter_next(&iter_hosts)))
4598 {
4599 gh_local.second = *phostid;
4600 zbx_hashset_insert(&groups, &gh_local, sizeof(gh_local));
4601 }
4602 }
4603
4604 /* add new rows, remove existing rows from index */
4605 while (NULL != (dbrow = DBfetch(result)))
4606 {
4607 ZBX_STR2UINT64(gh_local.first, dbrow[0]);
4608 ZBX_STR2UINT64(gh_local.second, dbrow[1]);
4609
4610 if (NULL == (gh = (zbx_uint64_pair_t *)zbx_hashset_search(&groups, &gh_local)))
4611 dbsync_add_row(sync, 0, ZBX_DBSYNC_ROW_ADD, dbrow);
4612 else
4613 zbx_hashset_remove_direct(&groups, gh);
4614 }
4615
4616 /* add removed rows */
4617 zbx_hashset_iter_reset(&groups, &iter);
4618 while (NULL != (gh = (zbx_uint64_pair_t *)zbx_hashset_iter_next(&iter)))
4619 {
4620 zbx_snprintf(groupid_s, sizeof(groupid_s), ZBX_FS_UI64, gh->first);
4621 zbx_snprintf(hostid_s, sizeof(hostid_s), ZBX_FS_UI64, gh->second);
4622 dbsync_add_row(sync, 0, ZBX_DBSYNC_ROW_REMOVE, del_row);
4623 }
4624
4625 DBfree_result(result);
4626 zbx_hashset_destroy(&groups);
4627
4628 return SUCCEED;
4629 }
4630