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