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
24 #define ZBX_DBCONFIG_IMPL
25 #include "dbconfig.h"
26 #include "dbsync.h"
27
28 typedef struct
29 {
30 zbx_hashset_t strpool;
31 ZBX_DC_CONFIG *cache;
32 }
33 zbx_dbsync_env_t;
34
35 static zbx_dbsync_env_t dbsync_env;
36
37 /* string pool support */
38
39 #define REFCOUNT_FIELD_SIZE sizeof(zbx_uint32_t)
40
dbsync_strpool_hash_func(const void * data)41 static zbx_hash_t dbsync_strpool_hash_func(const void *data)
42 {
43 return ZBX_DEFAULT_STRING_HASH_FUNC((char *)data + REFCOUNT_FIELD_SIZE);
44 }
45
dbsync_strpool_compare_func(const void * d1,const void * d2)46 static int dbsync_strpool_compare_func(const void *d1, const void *d2)
47 {
48 return strcmp((char *)d1 + REFCOUNT_FIELD_SIZE, (char *)d2 + REFCOUNT_FIELD_SIZE);
49 }
50
dbsync_strdup(const char * str)51 static char *dbsync_strdup(const char *str)
52 {
53 void *ptr;
54
55 ptr = zbx_hashset_search(&dbsync_env.strpool, str - REFCOUNT_FIELD_SIZE);
56
57 if (NULL == ptr)
58 {
59 ptr = zbx_hashset_insert_ext(&dbsync_env.strpool, str - REFCOUNT_FIELD_SIZE,
60 REFCOUNT_FIELD_SIZE + strlen(str) + 1, REFCOUNT_FIELD_SIZE);
61
62 *(zbx_uint32_t *)ptr = 0;
63 }
64
65 (*(zbx_uint32_t *)ptr)++;
66
67 return (char *)ptr + REFCOUNT_FIELD_SIZE;
68 }
69
dbsync_strfree(char * str)70 static void dbsync_strfree(char *str)
71 {
72 if (NULL != str)
73 {
74 void *ptr = str - REFCOUNT_FIELD_SIZE;
75
76 if (0 == --(*(zbx_uint32_t *)ptr))
77 zbx_hashset_remove_direct(&dbsync_env.strpool, ptr);
78 }
79 }
80
81 /* zbx_uint64_pair_t hashset support */
uint64_pair_hash_func(const void * data)82 static zbx_hash_t uint64_pair_hash_func(const void *data)
83 {
84 const zbx_uint64_pair_t *pair = (const zbx_uint64_pair_t *)data;
85
86 zbx_hash_t hash;
87
88 hash = ZBX_DEFAULT_UINT64_HASH_FUNC(&pair->first);
89 hash = ZBX_DEFAULT_UINT64_HASH_ALGO(&pair->second, sizeof(pair->second), hash);
90
91 return hash;
92 }
93
uint64_pair_compare_func(const void * d1,const void * d2)94 static int uint64_pair_compare_func(const void *d1, const void *d2)
95 {
96 const zbx_uint64_pair_t *p1 = (const zbx_uint64_pair_t *)d1;
97 const zbx_uint64_pair_t *p2 = (const zbx_uint64_pair_t *)d2;
98
99 ZBX_RETURN_IF_NOT_EQUAL(p1->first, p2->first);
100 ZBX_RETURN_IF_NOT_EQUAL(p1->second, p2->second);
101
102 return 0;
103 }
104
105 /******************************************************************************
106 * *
107 * Function: zbx_dbsync_init_env *
108 * *
109 ******************************************************************************/
zbx_dbsync_init_env(ZBX_DC_CONFIG * cache)110 void zbx_dbsync_init_env(ZBX_DC_CONFIG *cache)
111 {
112 dbsync_env.cache = cache;
113 zbx_hashset_create(&dbsync_env.strpool, 100, dbsync_strpool_hash_func, dbsync_strpool_compare_func);
114 }
115
116 /******************************************************************************
117 * *
118 * Function: dbsync_env_release *
119 * *
120 ******************************************************************************/
zbx_dbsync_free_env(void)121 void zbx_dbsync_free_env(void)
122 {
123 zbx_hashset_destroy(&dbsync_env.strpool);
124 }
125
126 /******************************************************************************
127 * *
128 * Function: dbsync_compare_uint64 *
129 * *
130 * Purpose: compares 64 bit unsigned integer with a raw database value *
131 * *
132 ******************************************************************************/
dbsync_compare_uint64(const char * value_raw,zbx_uint64_t value)133 static int dbsync_compare_uint64(const char *value_raw, zbx_uint64_t value)
134 {
135 zbx_uint64_t value_ui64;
136
137 ZBX_DBROW2UINT64(value_ui64, value_raw);
138
139 return (value_ui64 == value ? SUCCEED : FAIL);
140 }
141
142 /******************************************************************************
143 * *
144 * Function: dbsync_compare_int *
145 * *
146 * Purpose: compares 32 bit signed integer with a raw database value *
147 * *
148 ******************************************************************************/
dbsync_compare_int(const char * value_raw,int value)149 static int dbsync_compare_int(const char *value_raw, int value)
150 {
151 return (atoi(value_raw) == value ? SUCCEED : FAIL);
152 }
153
154 /******************************************************************************
155 * *
156 * Function: dbsync_compare_uchar *
157 * *
158 * Purpose: compares unsigned character with a raw database value *
159 * *
160 ******************************************************************************/
161
dbsync_compare_uchar(const char * value_raw,unsigned char value)162 static int dbsync_compare_uchar(const char *value_raw, unsigned char value)
163 {
164 unsigned char value_uchar;
165
166 ZBX_STR2UCHAR(value_uchar, value_raw);
167 return (value_uchar == value ? SUCCEED : FAIL);
168 }
169
170 /******************************************************************************
171 * *
172 * Function: dbsync_compare_str *
173 * *
174 * Purpose: compares string with a raw database value *
175 * *
176 ******************************************************************************/
177
dbsync_compare_str(const char * value_raw,const char * value)178 static int dbsync_compare_str(const char *value_raw, const char *value)
179 {
180 return (0 == strcmp(value_raw, value) ? SUCCEED : FAIL);
181 }
182
183 /******************************************************************************
184 * *
185 * Function: dbsync_add_row *
186 * *
187 * Purpose: adds a new row to the changeset *
188 * *
189 * Parameter: sync - [IN] the changeset *
190 * rowid - [IN] the row identifier *
191 * tag - [IN] the row tag (see ZBX_DBSYNC_ROW_ defines) *
192 * row - [IN] the row contents (NULL for ZBX_DBSYNC_ROW_REMOVE) *
193 * *
194 ******************************************************************************/
dbsync_add_row(zbx_dbsync_t * sync,zbx_uint64_t rowid,unsigned char tag,const DB_ROW dbrow)195 static void dbsync_add_row(zbx_dbsync_t *sync, zbx_uint64_t rowid, unsigned char tag, const DB_ROW dbrow)
196 {
197 int i;
198 zbx_dbsync_row_t *row;
199
200 row = (zbx_dbsync_row_t *)zbx_malloc(NULL, sizeof(zbx_dbsync_row_t));
201 row->rowid = rowid;
202 row->tag = tag;
203
204 if (NULL != dbrow)
205 {
206 row->row = (char **)zbx_malloc(NULL, sizeof(char *) * sync->columns_num);
207
208 for (i = 0; i < sync->columns_num; i++)
209 row->row[i] = (NULL == dbrow[i] ? NULL : dbsync_strdup(dbrow[i]));
210 }
211 else
212 row->row = NULL;
213
214 zbx_vector_ptr_append(&sync->rows, row);
215
216 switch (tag)
217 {
218 case ZBX_DBSYNC_ROW_ADD:
219 sync->add_num++;
220 break;
221 case ZBX_DBSYNC_ROW_UPDATE:
222 sync->update_num++;
223 break;
224 case ZBX_DBSYNC_ROW_REMOVE:
225 sync->remove_num++;
226 break;
227 }
228 }
229
230 /******************************************************************************
231 * *
232 * Function: zbx_dbsync_init *
233 * *
234 * Purpose: initializes changeset *
235 * *
236 ******************************************************************************/
zbx_dbsync_init(zbx_dbsync_t * sync,unsigned char mode)237 void zbx_dbsync_init(zbx_dbsync_t *sync, unsigned char mode)
238 {
239 sync->columns_num = 0;
240 sync->mode = mode;
241
242 sync->add_num = 0;
243 sync->update_num = 0;
244 sync->remove_num = 0;
245
246 if (ZBX_DBSYNC_UPDATE == sync->mode)
247 {
248 zbx_vector_ptr_create(&sync->rows);
249 sync->row_index = 0;
250 }
251 else
252 sync->dbresult = NULL;
253 }
254
255 /******************************************************************************
256 * *
257 * Function: zbx_dbsync_clear *
258 * *
259 * Purpose: frees resources allocated by changeset *
260 * *
261 ******************************************************************************/
zbx_dbsync_clear(zbx_dbsync_t * sync)262 void zbx_dbsync_clear(zbx_dbsync_t *sync)
263 {
264 if (ZBX_DBSYNC_UPDATE == sync->mode)
265 {
266 int i, j;
267 zbx_dbsync_row_t *row;
268
269 for (i = 0; i < sync->rows.values_num; i++)
270 {
271 row = (zbx_dbsync_row_t *)sync->rows.values[i];
272
273 if (NULL != row->row)
274 {
275 for (j = 0; j < sync->columns_num; j++)
276 dbsync_strfree(row->row[j]);
277
278 zbx_free(row->row);
279 }
280
281 zbx_free(row);
282 }
283
284 zbx_vector_ptr_destroy(&sync->rows);
285 }
286 else
287 {
288 DBfree_result(sync->dbresult);
289 sync->dbresult = NULL;
290 }
291 }
292
293 /******************************************************************************
294 * *
295 * Function: zbx_dbsync_next *
296 * *
297 * Purpose: gets the next row from the changeset *
298 * *
299 * Parameters: sync - [IN] the changeset *
300 * rowid - [OUT] the row identifier (required for row removal, *
301 * optional for new/updated rows) *
302 * row - [OUT] the row data *
303 * tag - [OUT] the row tag, identifying changes *
304 * (see ZBX_DBSYNC_ROW_* defines) *
305 * *
306 * Return value: SUCCEED - the next row was successfully retrieved *
307 * FAIL - no more data to retrieve *
308 * *
309 ******************************************************************************/
zbx_dbsync_next(zbx_dbsync_t * sync,zbx_uint64_t * rowid,char *** row,unsigned char * tag)310 int zbx_dbsync_next(zbx_dbsync_t *sync, zbx_uint64_t *rowid, char ***row, unsigned char *tag)
311 {
312 if (ZBX_DBSYNC_UPDATE == sync->mode)
313 {
314 zbx_dbsync_row_t *sync_row;
315
316 if (sync->row_index == sync->rows.values_num)
317 return FAIL;
318
319 sync_row = (zbx_dbsync_row_t *)sync->rows.values[sync->row_index++];
320 *rowid = sync_row->rowid;
321 *row = sync_row->row;
322 *tag = sync_row->tag;
323 }
324 else
325 {
326 if (NULL == (*row = DBfetch(sync->dbresult)))
327 return FAIL;
328
329 *rowid = 0;
330 *tag = ZBX_DBSYNC_ROW_ADD;
331
332 sync->add_num++;
333 }
334
335 return SUCCEED;
336 }
337
338 /******************************************************************************
339 * *
340 * Function: zbx_dbsync_compare_config *
341 * *
342 * Purpose: compares config table with cached configuration data *
343 * *
344 * Parameter: cache - [IN] the configuration cache *
345 * sync - [OUT] the changeset *
346 * *
347 * Return value: SUCCEED - the changeset was successfully calculated *
348 * FAIL - otherwise *
349 * *
350 ******************************************************************************/
zbx_dbsync_compare_config(zbx_dbsync_t * sync)351 int zbx_dbsync_compare_config(zbx_dbsync_t *sync)
352 {
353 DB_RESULT result;
354
355 sync->columns_num = 27;
356
357 if (NULL == (result = DBselect(
358 "select refresh_unsupported,discovery_groupid,snmptrap_logging,"
359 "severity_name_0,severity_name_1,severity_name_2,"
360 "severity_name_3,severity_name_4,severity_name_5,"
361 "hk_events_mode,hk_events_trigger,hk_events_internal,"
362 "hk_events_discovery,hk_events_autoreg,hk_services_mode,"
363 "hk_services,hk_audit_mode,hk_audit,hk_sessions_mode,hk_sessions,"
364 "hk_history_mode,hk_history_global,hk_history,hk_trends_mode,"
365 "hk_trends_global,hk_trends,default_inventory_mode"
366 " from config"
367 " order by configid")))
368 {
369 return FAIL;
370 }
371
372 if (ZBX_DBSYNC_INIT == sync->mode)
373 {
374 sync->dbresult = result;
375 return SUCCEED;
376 }
377
378 DBfree_result(result);
379
380 /* global configuration will be always synchronized directly with database */
381 THIS_SHOULD_NEVER_HAPPEN;
382
383 return FAIL;
384 }
385
386 /******************************************************************************
387 * *
388 * Function: dbsync_compare_host *
389 * *
390 * Purpose: compares hosts table row with cached configuration data *
391 * *
392 * Parameter: cache - [IN] the configuration cache *
393 * host - [IN] the cached host *
394 * row - [IN] the database row *
395 * *
396 * Return value: SUCCEED - the row matches configuration data *
397 * FAIL - otherwise *
398 * *
399 ******************************************************************************/
dbsync_compare_host(ZBX_DC_HOST * host,const DB_ROW row)400 static int dbsync_compare_host(ZBX_DC_HOST *host, const DB_ROW row)
401 {
402 signed char ipmi_authtype;
403 unsigned char ipmi_privilege;
404 ZBX_DC_IPMIHOST *ipmihost;
405
406 if (FAIL == dbsync_compare_uint64(row[1], host->proxy_hostid))
407 {
408 host->update_items = 1;
409 return FAIL;
410 }
411
412 if (FAIL == dbsync_compare_uchar(row[22], host->status))
413 {
414 host->update_items = 1;
415 return FAIL;
416 }
417
418 host->update_items = 0;
419
420 if (FAIL == dbsync_compare_str(row[2], host->host))
421 return FAIL;
422
423 if (FAIL == dbsync_compare_str(row[23], host->name))
424 return FAIL;
425
426 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
427 if (FAIL == dbsync_compare_str(row[31], host->tls_issuer))
428 return FAIL;
429
430 if (FAIL == dbsync_compare_str(row[32], host->tls_subject))
431 return FAIL;
432
433 if ('\0' == *row[33] || '\0' == *row[34])
434 {
435 if (NULL != host->tls_dc_psk)
436 return FAIL;
437 }
438 else
439 {
440 if (NULL == host->tls_dc_psk)
441 return FAIL;
442
443 if (FAIL == dbsync_compare_str(row[33], host->tls_dc_psk->tls_psk_identity))
444 return FAIL;
445
446 if (FAIL == dbsync_compare_str(row[34], host->tls_dc_psk->tls_psk))
447 return FAIL;
448 }
449 #endif
450 if (FAIL == dbsync_compare_uchar(row[29], host->tls_connect))
451 return FAIL;
452
453 if (FAIL == dbsync_compare_uchar(row[30], host->tls_accept))
454 return FAIL;
455
456 /* IPMI hosts */
457
458 ipmi_authtype = (signed char)atoi(row[3]);
459 ipmi_privilege = (unsigned char)atoi(row[4]);
460
461 if (0 != ipmi_authtype || 2 != ipmi_privilege || '\0' != *row[5] || '\0' != *row[6]) /* useipmi */
462 {
463 if (NULL == (ipmihost = (ZBX_DC_IPMIHOST *)zbx_hashset_search(&dbsync_env.cache->ipmihosts, &host->hostid)))
464 return FAIL;
465
466 if (ipmihost->ipmi_authtype != ipmi_authtype)
467 return FAIL;
468
469 if (ipmihost->ipmi_privilege != ipmi_privilege)
470 return FAIL;
471
472 if (FAIL == dbsync_compare_str(row[5], ipmihost->ipmi_username))
473 return FAIL;
474
475 if (FAIL == dbsync_compare_str(row[6], ipmihost->ipmi_password))
476 return FAIL;
477 }
478 else if (NULL != zbx_hashset_search(&dbsync_env.cache->ipmihosts, &host->hostid))
479 return FAIL;
480
481 return SUCCEED;
482 }
483
484 /******************************************************************************
485 * *
486 * Function: zbx_dbsync_compare_hosts *
487 * *
488 * Purpose: compares hosts table with cached configuration data *
489 * *
490 * Parameter: cache - [IN] the configuration cache *
491 * sync - [OUT] the changeset *
492 * *
493 * Return value: SUCCEED - the changeset was successfully calculated *
494 * FAIL - otherwise *
495 * *
496 ******************************************************************************/
zbx_dbsync_compare_hosts(zbx_dbsync_t * sync)497 int zbx_dbsync_compare_hosts(zbx_dbsync_t *sync)
498 {
499 DB_ROW row;
500 DB_RESULT result;
501 zbx_hashset_t ids;
502 zbx_hashset_iter_t iter;
503 zbx_uint64_t rowid;
504 ZBX_DC_HOST *host;
505
506 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
507 if (NULL == (result = DBselect(
508 "select hostid,proxy_hostid,host,ipmi_authtype,ipmi_privilege,ipmi_username,"
509 "ipmi_password,maintenance_status,maintenance_type,maintenance_from,"
510 "errors_from,available,disable_until,snmp_errors_from,"
511 "snmp_available,snmp_disable_until,ipmi_errors_from,ipmi_available,"
512 "ipmi_disable_until,jmx_errors_from,jmx_available,jmx_disable_until,"
513 "status,name,lastaccess,error,snmp_error,ipmi_error,jmx_error,tls_connect,tls_accept"
514 ",tls_issuer,tls_subject,tls_psk_identity,tls_psk"
515 " from hosts"
516 " where status in (%d,%d,%d,%d)"
517 " and flags<>%d",
518 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
519 HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE,
520 ZBX_FLAG_DISCOVERY_PROTOTYPE)))
521 {
522 return FAIL;
523 }
524
525 sync->columns_num = 35;
526 #else
527 if (NULL == (result = DBselect(
528 "select hostid,proxy_hostid,host,ipmi_authtype,ipmi_privilege,ipmi_username,"
529 "ipmi_password,maintenance_status,maintenance_type,maintenance_from,"
530 "errors_from,available,disable_until,snmp_errors_from,"
531 "snmp_available,snmp_disable_until,ipmi_errors_from,ipmi_available,"
532 "ipmi_disable_until,jmx_errors_from,jmx_available,jmx_disable_until,"
533 "status,name,lastaccess,error,snmp_error,ipmi_error,jmx_error,tls_connect,tls_accept"
534 " from hosts"
535 " where status in (%d,%d,%d,%d)"
536 " and flags<>%d",
537 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
538 HOST_STATUS_PROXY_ACTIVE, HOST_STATUS_PROXY_PASSIVE,
539 ZBX_FLAG_DISCOVERY_PROTOTYPE)))
540 {
541 return FAIL;
542 }
543
544 sync->columns_num = 31;
545 #endif
546
547 if (ZBX_DBSYNC_INIT == sync->mode)
548 {
549 sync->dbresult = result;
550 return SUCCEED;
551 }
552
553 zbx_hashset_create(&ids, dbsync_env.cache->hosts.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
554
555 while (NULL != (row = DBfetch(result)))
556 {
557 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
558
559 ZBX_STR2UINT64(rowid, row[0]);
560 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
561
562 if (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&dbsync_env.cache->hosts, &rowid)))
563 tag = ZBX_DBSYNC_ROW_ADD;
564 else if (FAIL == dbsync_compare_host(host, row))
565 tag = ZBX_DBSYNC_ROW_UPDATE;
566
567 if (ZBX_DBSYNC_ROW_NONE != tag)
568 dbsync_add_row(sync, rowid, tag, row);
569 }
570
571 zbx_hashset_iter_reset(&dbsync_env.cache->hosts, &iter);
572 while (NULL != (host = (ZBX_DC_HOST *)zbx_hashset_iter_next(&iter)))
573 {
574 if (NULL == zbx_hashset_search(&ids, &host->hostid))
575 dbsync_add_row(sync, host->hostid, ZBX_DBSYNC_ROW_REMOVE, NULL);
576 }
577
578 zbx_hashset_destroy(&ids);
579 DBfree_result(result);
580
581 return SUCCEED;
582 }
583
584 /******************************************************************************
585 * *
586 * Function: dbsync_compare_host_inventory *
587 * *
588 * Purpose: compares host inventory table row with cached configuration data *
589 * *
590 * Parameter: hi - [IN] the cached host inventory data *
591 * row - [IN] the database row *
592 * *
593 * Return value: SUCCEED - the row matches configuration data *
594 * FAIL - otherwise *
595 * *
596 ******************************************************************************/
dbsync_compare_host_inventory(const ZBX_DC_HOST_INVENTORY * hi,const DB_ROW row)597 static int dbsync_compare_host_inventory(const ZBX_DC_HOST_INVENTORY *hi, const DB_ROW row)
598 {
599 return dbsync_compare_uchar(row[1], hi->inventory_mode);
600 }
601
602 /******************************************************************************
603 * *
604 * Function: zbx_dbsync_compare_host_inventory *
605 * *
606 * Purpose: compares host_inventory table with cached configuration data *
607 * *
608 * Parameter: cache - [IN] the configuration cache *
609 * sync - [OUT] the changeset *
610 * *
611 * Return value: SUCCEED - the changeset was successfully calculated *
612 * FAIL - otherwise *
613 * *
614 ******************************************************************************/
zbx_dbsync_compare_host_inventory(zbx_dbsync_t * sync)615 int zbx_dbsync_compare_host_inventory(zbx_dbsync_t *sync)
616 {
617 DB_ROW row;
618 DB_RESULT result;
619 zbx_hashset_t ids;
620 zbx_hashset_iter_t iter;
621 zbx_uint64_t rowid;
622 ZBX_DC_HOST_INVENTORY *hi;
623
624 if (NULL == (result = DBselect(
625 "select hostid,inventory_mode"
626 " from host_inventory")))
627 {
628 return FAIL;
629 }
630
631 sync->columns_num = 2;
632
633 if (ZBX_DBSYNC_INIT == sync->mode)
634 {
635 sync->dbresult = result;
636 return SUCCEED;
637 }
638
639 zbx_hashset_create(&ids, dbsync_env.cache->host_inventories.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
640 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
641
642 while (NULL != (row = DBfetch(result)))
643 {
644 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
645
646 ZBX_STR2UINT64(rowid, row[0]);
647 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
648
649 if (NULL == (hi = (ZBX_DC_HOST_INVENTORY *)zbx_hashset_search(&dbsync_env.cache->host_inventories, &rowid)))
650 tag = ZBX_DBSYNC_ROW_ADD;
651 else if (FAIL == dbsync_compare_host_inventory(hi, row))
652 tag = ZBX_DBSYNC_ROW_UPDATE;
653
654 if (ZBX_DBSYNC_ROW_NONE != tag)
655 dbsync_add_row(sync, rowid, tag, row);
656 }
657
658 zbx_hashset_iter_reset(&dbsync_env.cache->host_inventories, &iter);
659 while (NULL != (hi = (ZBX_DC_HOST_INVENTORY *)zbx_hashset_iter_next(&iter)))
660 {
661 if (NULL == zbx_hashset_search(&ids, &hi->hostid))
662 dbsync_add_row(sync, hi->hostid, ZBX_DBSYNC_ROW_REMOVE, NULL);
663 }
664
665 zbx_hashset_destroy(&ids);
666 DBfree_result(result);
667
668 return SUCCEED;
669 }
670
671 /******************************************************************************
672 * *
673 * Function: zbx_dbsync_compare_host_templates *
674 * *
675 * Purpose: compares hosts_templates table with cached configuration data *
676 * *
677 * Parameter: cache - [IN] the configuration cache *
678 * sync - [OUT] the changeset *
679 * *
680 * Return value: SUCCEED - the changeset was successfully calculated *
681 * FAIL - otherwise *
682 * *
683 ******************************************************************************/
zbx_dbsync_compare_host_templates(zbx_dbsync_t * sync)684 int zbx_dbsync_compare_host_templates(zbx_dbsync_t *sync)
685 {
686 DB_ROW row;
687 DB_RESULT result;
688 zbx_hashset_iter_t iter;
689 ZBX_DC_HTMPL *htmpl;
690 zbx_hashset_t htmpls;
691 int i;
692 zbx_uint64_pair_t ht_local, *ht;
693 char hostid_s[MAX_ID_LEN + 1], templateid_s[MAX_ID_LEN + 1];
694 char *del_row[2] = {hostid_s, templateid_s};
695
696 if (NULL == (result = DBselect(
697 "select hostid,templateid"
698 " from hosts_templates"
699 " order by hostid")))
700 {
701 return FAIL;
702 }
703
704 sync->columns_num = 2;
705
706 if (ZBX_DBSYNC_INIT == sync->mode)
707 {
708 sync->dbresult = result;
709 return SUCCEED;
710 }
711
712 zbx_hashset_create(&htmpls, dbsync_env.cache->htmpls.num_data * 5, uint64_pair_hash_func, uint64_pair_compare_func);
713
714 /* index all host->template links */
715 zbx_hashset_iter_reset(&dbsync_env.cache->htmpls, &iter);
716 while (NULL != (htmpl = (ZBX_DC_HTMPL *)zbx_hashset_iter_next(&iter)))
717 {
718 ht_local.first = htmpl->hostid;
719
720 for (i = 0; i < htmpl->templateids.values_num; i++)
721 {
722 ht_local.second = htmpl->templateids.values[i];
723 zbx_hashset_insert(&htmpls, &ht_local, sizeof(ht_local));
724 }
725 }
726
727 /* add new rows, remove existing rows from index */
728 while (NULL != (row = DBfetch(result)))
729 {
730 ZBX_STR2UINT64(ht_local.first, row[0]);
731 ZBX_STR2UINT64(ht_local.second, row[1]);
732
733 if (NULL == (ht = (zbx_uint64_pair_t *)zbx_hashset_search(&htmpls, &ht_local)))
734 dbsync_add_row(sync, 0, ZBX_DBSYNC_ROW_ADD, row);
735 else
736 zbx_hashset_remove_direct(&htmpls, ht);
737 }
738
739 /* add removed rows */
740 zbx_hashset_iter_reset(&htmpls, &iter);
741 while (NULL != (ht = (zbx_uint64_pair_t *)zbx_hashset_iter_next(&iter)))
742 {
743 zbx_snprintf(hostid_s, sizeof(hostid_s), ZBX_FS_UI64, ht->first);
744 zbx_snprintf(templateid_s, sizeof(templateid_s), ZBX_FS_UI64, ht->second);
745 dbsync_add_row(sync, 0, ZBX_DBSYNC_ROW_REMOVE, del_row);
746 }
747
748 DBfree_result(result);
749 zbx_hashset_destroy(&htmpls);
750
751 return SUCCEED;
752 }
753
754 /******************************************************************************
755 * *
756 * Function: dbsync_compare_global_macro *
757 * *
758 * Purpose: compares global macro table row with cached configuration data *
759 * *
760 * Parameter: gmacro - [IN] the cached global macro data *
761 * row - [IN] the database row *
762 * *
763 * Return value: SUCCEED - the row matches configuration data *
764 * FAIL - otherwise *
765 * *
766 ******************************************************************************/
dbsync_compare_global_macro(const ZBX_DC_GMACRO * gmacro,const DB_ROW row)767 static int dbsync_compare_global_macro(const ZBX_DC_GMACRO *gmacro, const DB_ROW row)
768 {
769 char *macro = NULL, *context = NULL;
770 int ret = FAIL;
771
772 if (FAIL == dbsync_compare_str(row[2], gmacro->value))
773 return FAIL;
774
775 if (SUCCEED != zbx_user_macro_parse_dyn(row[1], ¯o, &context, NULL))
776 return FAIL;
777
778 if (0 != strcmp(gmacro->macro, macro))
779 goto out;
780
781 if (NULL == context)
782 {
783 if (NULL != gmacro->context)
784 goto out;
785
786 ret = SUCCEED;
787 goto out;
788 }
789
790 if (NULL == gmacro->context)
791 goto out;
792
793 if (0 == strcmp(gmacro->context, context))
794 ret = SUCCEED;
795 out:
796 zbx_free(macro);
797 zbx_free(context);
798
799 return ret;
800 }
801
802 /******************************************************************************
803 * *
804 * Function: zbx_dbsync_compare_global_macros *
805 * *
806 * Purpose: compares global macros table with cached configuration data *
807 * *
808 * Parameter: cache - [IN] the configuration cache *
809 * sync - [OUT] the changeset *
810 * *
811 * Return value: SUCCEED - the changeset was successfully calculated *
812 * FAIL - otherwise *
813 * *
814 ******************************************************************************/
zbx_dbsync_compare_global_macros(zbx_dbsync_t * sync)815 int zbx_dbsync_compare_global_macros(zbx_dbsync_t *sync)
816 {
817 DB_ROW row;
818 DB_RESULT result;
819 zbx_hashset_t ids;
820 zbx_hashset_iter_t iter;
821 zbx_uint64_t rowid;
822 ZBX_DC_GMACRO *gmacro;
823
824 if (NULL == (result = DBselect(
825 "select globalmacroid,macro,value"
826 " from globalmacro")))
827 {
828 return FAIL;
829 }
830
831 sync->columns_num = 3;
832
833 if (ZBX_DBSYNC_INIT == sync->mode)
834 {
835 sync->dbresult = result;
836 return SUCCEED;
837 }
838
839 zbx_hashset_create(&ids, dbsync_env.cache->gmacros.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
840 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
841
842 while (NULL != (row = DBfetch(result)))
843 {
844 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
845
846 ZBX_STR2UINT64(rowid, row[0]);
847 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
848
849 if (NULL == (gmacro = (ZBX_DC_GMACRO *)zbx_hashset_search(&dbsync_env.cache->gmacros, &rowid)))
850 tag = ZBX_DBSYNC_ROW_ADD;
851 else if (FAIL == dbsync_compare_global_macro(gmacro, row))
852 tag = ZBX_DBSYNC_ROW_UPDATE;
853
854 if (ZBX_DBSYNC_ROW_NONE != tag)
855 dbsync_add_row(sync, rowid, tag, row);
856 }
857
858 zbx_hashset_iter_reset(&dbsync_env.cache->gmacros, &iter);
859 while (NULL != (gmacro = (ZBX_DC_GMACRO *)zbx_hashset_iter_next(&iter)))
860 {
861 if (NULL == zbx_hashset_search(&ids, &gmacro->globalmacroid))
862 dbsync_add_row(sync, gmacro->globalmacroid, ZBX_DBSYNC_ROW_REMOVE, NULL);
863 }
864
865 zbx_hashset_destroy(&ids);
866 DBfree_result(result);
867
868 return SUCCEED;
869 }
870
871 /******************************************************************************
872 * *
873 * Function: dbsync_compare_host_macro *
874 * *
875 * Purpose: compares host macro table row with cached configuration data *
876 * *
877 * Parameter: hmacro - [IN] the cached host macro data *
878 * row - [IN] the database row *
879 * *
880 * Return value: SUCCEED - the row matches configuration data *
881 * FAIL - otherwise *
882 * *
883 ******************************************************************************/
dbsync_compare_host_macro(const ZBX_DC_HMACRO * hmacro,const DB_ROW row)884 static int dbsync_compare_host_macro(const ZBX_DC_HMACRO *hmacro, const DB_ROW row)
885 {
886 char *macro = NULL, *context = NULL;
887 int ret = FAIL;
888
889 if (FAIL == dbsync_compare_str(row[3], hmacro->value))
890 return FAIL;
891
892 if (FAIL == dbsync_compare_uint64(row[1], hmacro->hostid))
893 return FAIL;
894
895 if (SUCCEED != zbx_user_macro_parse_dyn(row[2], ¯o, &context, NULL))
896 return FAIL;
897
898 if (0 != strcmp(hmacro->macro, macro))
899 goto out;
900
901 if (NULL == context)
902 {
903 if (NULL != hmacro->context)
904 goto out;
905
906 ret = SUCCEED;
907 goto out;
908 }
909
910 if (NULL == hmacro->context)
911 goto out;
912
913 if (0 == strcmp(hmacro->context, context))
914 ret = SUCCEED;
915 out:
916 zbx_free(macro);
917 zbx_free(context);
918
919 return ret;
920 }
921
922 /******************************************************************************
923 * *
924 * Function: zbx_dbsync_compare_host_macros *
925 * *
926 * Purpose: compares global macros table with cached configuration data *
927 * *
928 * Parameter: cache - [IN] the configuration cache *
929 * sync - [OUT] the changeset *
930 * *
931 * Return value: SUCCEED - the changeset was successfully calculated *
932 * FAIL - otherwise *
933 * *
934 ******************************************************************************/
zbx_dbsync_compare_host_macros(zbx_dbsync_t * sync)935 int zbx_dbsync_compare_host_macros(zbx_dbsync_t *sync)
936 {
937 DB_ROW row;
938 DB_RESULT result;
939 zbx_hashset_t ids;
940 zbx_hashset_iter_t iter;
941 zbx_uint64_t rowid;
942 ZBX_DC_HMACRO *hmacro;
943
944 if (NULL == (result = DBselect(
945 "select hostmacroid,hostid,macro,value"
946 " from hostmacro")))
947 {
948 return FAIL;
949 }
950
951 sync->columns_num = 4;
952
953 if (ZBX_DBSYNC_INIT == sync->mode)
954 {
955 sync->dbresult = result;
956 return SUCCEED;
957 }
958
959 zbx_hashset_create(&ids, dbsync_env.cache->hmacros.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
960 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
961
962 while (NULL != (row = DBfetch(result)))
963 {
964 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
965
966 ZBX_STR2UINT64(rowid, row[0]);
967 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
968
969 if (NULL == (hmacro = (ZBX_DC_HMACRO *)zbx_hashset_search(&dbsync_env.cache->hmacros, &rowid)))
970 tag = ZBX_DBSYNC_ROW_ADD;
971 else if (FAIL == dbsync_compare_host_macro(hmacro, row))
972 tag = ZBX_DBSYNC_ROW_UPDATE;
973
974 if (ZBX_DBSYNC_ROW_NONE != tag)
975 dbsync_add_row(sync, rowid, tag, row);
976 }
977
978 zbx_hashset_iter_reset(&dbsync_env.cache->hmacros, &iter);
979 while (NULL != (hmacro = (ZBX_DC_HMACRO *)zbx_hashset_iter_next(&iter)))
980 {
981 if (NULL == zbx_hashset_search(&ids, &hmacro->hostmacroid))
982 dbsync_add_row(sync, hmacro->hostmacroid, ZBX_DBSYNC_ROW_REMOVE, NULL);
983 }
984
985 zbx_hashset_destroy(&ids);
986 DBfree_result(result);
987
988 return SUCCEED;
989 }
990
991 /******************************************************************************
992 * *
993 * Function: dbsync_compare_interface *
994 * *
995 * Purpose: compares interface table row with cached configuration data *
996 * *
997 * Parameter: interface - [IN] the cached interface data *
998 * row - [IN] the database row *
999 * *
1000 * Return value: SUCCEED - the row matches configuration data *
1001 * FAIL - otherwise *
1002 * *
1003 * Comments: User macros used in ip, dns fields will always make compare to *
1004 * fail. *
1005 * *
1006 ******************************************************************************/
dbsync_compare_interface(const ZBX_DC_INTERFACE * interface,const DB_ROW row)1007 static int dbsync_compare_interface(const ZBX_DC_INTERFACE *interface, const DB_ROW row)
1008 {
1009 if (FAIL == dbsync_compare_uint64(row[1], interface->hostid))
1010 return FAIL;
1011
1012 if (FAIL == dbsync_compare_uchar(row[2], interface->type))
1013 return FAIL;
1014
1015 if (FAIL == dbsync_compare_uchar(row[3], interface->main))
1016 return FAIL;
1017
1018 if (FAIL == dbsync_compare_uchar(row[4], interface->useip))
1019 return FAIL;
1020
1021 if (FAIL == dbsync_compare_uchar(row[8], interface->bulk))
1022 return FAIL;
1023
1024 if (NULL != strstr(row[5], "{$"))
1025 return FAIL;
1026
1027 if (FAIL == dbsync_compare_str(row[5], interface->ip))
1028 return FAIL;
1029
1030 if (NULL != strstr(row[6], "{$"))
1031 return FAIL;
1032
1033 if (FAIL == dbsync_compare_str(row[6], interface->dns))
1034 return FAIL;
1035
1036 if (FAIL == dbsync_compare_str(row[7], interface->port))
1037 return FAIL;
1038
1039 return SUCCEED;
1040 }
1041
1042 /******************************************************************************
1043 * *
1044 * Function: zbx_dbsync_compare_interfaces *
1045 * *
1046 * Purpose: compares interfaces table with cached configuration data *
1047 * *
1048 * Parameter: cache - [IN] the configuration cache *
1049 * sync - [OUT] the changeset *
1050 * *
1051 * Return value: SUCCEED - the changeset was successfully calculated *
1052 * FAIL - otherwise *
1053 * *
1054 ******************************************************************************/
zbx_dbsync_compare_interfaces(zbx_dbsync_t * sync)1055 int zbx_dbsync_compare_interfaces(zbx_dbsync_t *sync)
1056 {
1057 DB_ROW row;
1058 DB_RESULT result;
1059 zbx_hashset_t ids;
1060 zbx_hashset_iter_t iter;
1061 zbx_uint64_t rowid;
1062 ZBX_DC_INTERFACE *interface;
1063
1064 if (NULL == (result = DBselect(
1065 "select interfaceid,hostid,type,main,useip,ip,dns,port,bulk"
1066 " from interface")))
1067 {
1068 return FAIL;
1069 }
1070
1071 sync->columns_num = 9;
1072
1073 if (ZBX_DBSYNC_INIT == sync->mode)
1074 {
1075 sync->dbresult = result;
1076 return SUCCEED;
1077 }
1078
1079 zbx_hashset_create(&ids, dbsync_env.cache->interfaces.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
1080 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1081
1082 while (NULL != (row = DBfetch(result)))
1083 {
1084 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
1085
1086 ZBX_STR2UINT64(rowid, row[0]);
1087 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
1088
1089 if (NULL == (interface = (ZBX_DC_INTERFACE *)zbx_hashset_search(&dbsync_env.cache->interfaces, &rowid)))
1090 tag = ZBX_DBSYNC_ROW_ADD;
1091 else if (FAIL == dbsync_compare_interface(interface, row))
1092 tag = ZBX_DBSYNC_ROW_UPDATE;
1093
1094 if (ZBX_DBSYNC_ROW_NONE != tag)
1095 dbsync_add_row(sync, rowid, tag, row);
1096 }
1097
1098 zbx_hashset_iter_reset(&dbsync_env.cache->interfaces, &iter);
1099 while (NULL != (interface = (ZBX_DC_INTERFACE *)zbx_hashset_iter_next(&iter)))
1100 {
1101 if (NULL == zbx_hashset_search(&ids, &interface->interfaceid))
1102 dbsync_add_row(sync, interface->interfaceid, ZBX_DBSYNC_ROW_REMOVE, NULL);
1103 }
1104
1105 zbx_hashset_destroy(&ids);
1106 DBfree_result(result);
1107
1108 return SUCCEED;
1109 }
1110
1111 /******************************************************************************
1112 * *
1113 * Function: dbsync_compare_item *
1114 * *
1115 * Purpose: compares items table row with cached configuration data *
1116 * *
1117 * Parameter: cache - [IN] the configuration cache *
1118 * item - [IN] the cached item *
1119 * row - [IN] the database row *
1120 * *
1121 * Return value: SUCCEED - the row matches configuration data *
1122 * FAIL - otherwise *
1123 * *
1124 ******************************************************************************/
dbsync_compare_item(const ZBX_DC_ITEM * item,const DB_ROW row)1125 static int dbsync_compare_item(const ZBX_DC_ITEM *item, const DB_ROW row)
1126 {
1127 ZBX_DC_NUMITEM *numitem;
1128 ZBX_DC_SNMPITEM *snmpitem;
1129 ZBX_DC_IPMIITEM *ipmiitem;
1130 ZBX_DC_FLEXITEM *flexitem;
1131 ZBX_DC_TRAPITEM *trapitem;
1132 ZBX_DC_LOGITEM *logitem;
1133 ZBX_DC_DBITEM *dbitem;
1134 ZBX_DC_SSHITEM *sshitem;
1135 ZBX_DC_TELNETITEM *telnetitem;
1136 ZBX_DC_SIMPLEITEM *simpleitem;
1137 ZBX_DC_JMXITEM *jmxitem;
1138 ZBX_DC_CALCITEM *calcitem;
1139 ZBX_DC_HOST *host;
1140 unsigned char value_type, type;
1141
1142 if (FAIL == dbsync_compare_uint64(row[1], item->hostid))
1143 return FAIL;
1144
1145 if (NULL == (host = (ZBX_DC_HOST *)zbx_hashset_search(&dbsync_env.cache->hosts, &item->hostid)))
1146 return FAIL;
1147
1148 if (0 != host->update_items)
1149 return FAIL;
1150
1151 if (FAIL == dbsync_compare_uchar(row[2], item->status))
1152 return FAIL;
1153
1154 ZBX_STR2UCHAR(type, row[3]);
1155 if (item->type != type)
1156 return FAIL;
1157
1158 if (FAIL == dbsync_compare_uchar(row[4], item->data_type))
1159 return FAIL;
1160
1161 if (FAIL == dbsync_compare_str(row[9], item->port))
1162 return FAIL;
1163
1164 if (FAIL == dbsync_compare_uchar(row[26], item->flags))
1165 return FAIL;
1166
1167 if (FAIL == dbsync_compare_uint64(row[27], item->interfaceid))
1168 return FAIL;
1169
1170 if (ZBX_HK_OPTION_ENABLED == dbsync_env.cache->config->hk.history_global)
1171 {
1172 if (item->history != dbsync_env.cache->config->hk.history)
1173 return FAIL;
1174 }
1175 else
1176 {
1177 if (FAIL == dbsync_compare_int(row[36], item->history))
1178 return FAIL;
1179 }
1180
1181 if (FAIL == dbsync_compare_uchar(row[38], item->inventory_link))
1182 return FAIL;
1183
1184 if (FAIL == dbsync_compare_uint64(row[39], item->valuemapid))
1185 return FAIL;
1186
1187 ZBX_STR2UCHAR(value_type, row[5]);
1188 if (item->value_type != value_type)
1189 return FAIL;
1190
1191 if (FAIL == dbsync_compare_str(row[6], item->key))
1192 return FAIL;
1193
1194 if (FAIL == dbsync_compare_int(row[15], item->delay))
1195 return FAIL;
1196
1197 flexitem = (ZBX_DC_FLEXITEM *)zbx_hashset_search(&dbsync_env.cache->flexitems, &item->itemid);
1198 if ('\0' != *row[16])
1199 {
1200 if (NULL == flexitem)
1201 return FAIL;
1202
1203 if (FAIL == dbsync_compare_str(row[16], flexitem->delay_flex))
1204 return FAIL;
1205 }
1206 else if (NULL != flexitem)
1207 return FAIL;
1208
1209 numitem = (ZBX_DC_NUMITEM *)zbx_hashset_search(&dbsync_env.cache->numitems, &item->itemid);
1210 if (ITEM_VALUE_TYPE_FLOAT == value_type || ITEM_VALUE_TYPE_UINT64 == value_type)
1211 {
1212 if (NULL == numitem)
1213 return FAIL;
1214
1215 if (FAIL == dbsync_compare_uchar(row[33], numitem->delta))
1216 return FAIL;
1217
1218 if (FAIL == dbsync_compare_uchar(row[34], numitem->multiplier))
1219 return FAIL;
1220
1221 if (FAIL == dbsync_compare_str(row[35], numitem->formula))
1222 return FAIL;
1223
1224 if (ZBX_HK_OPTION_ENABLED == dbsync_env.cache->config->hk.trends_global)
1225 {
1226 if (numitem->trends != dbsync_env.cache->config->hk.trends)
1227 return FAIL;
1228 }
1229 else
1230 {
1231 if (FAIL == dbsync_compare_int(row[37], numitem->trends))
1232 return FAIL;
1233 }
1234
1235 if (FAIL == dbsync_compare_str(row[40], numitem->units))
1236 return FAIL;
1237 }
1238 else if (NULL != numitem)
1239 return FAIL;
1240
1241 snmpitem = (ZBX_DC_SNMPITEM *)zbx_hashset_search(&dbsync_env.cache->snmpitems, &item->itemid);
1242 if (SUCCEED == is_snmp_type(type))
1243 {
1244 if (NULL == snmpitem)
1245 return FAIL;
1246
1247 if (FAIL == dbsync_compare_str(row[7], snmpitem->snmp_community))
1248 return FAIL;
1249
1250 if (FAIL == dbsync_compare_str(row[10], snmpitem->snmpv3_securityname))
1251 return FAIL;
1252
1253 if (FAIL == dbsync_compare_uchar(row[11], snmpitem->snmpv3_securitylevel))
1254 return FAIL;
1255
1256 if (FAIL == dbsync_compare_str(row[12], snmpitem->snmpv3_authpassphrase))
1257 return FAIL;
1258
1259 if (FAIL == dbsync_compare_str(row[13], snmpitem->snmpv3_privpassphrase))
1260 return FAIL;
1261
1262 if (FAIL == dbsync_compare_uchar(row[28], snmpitem->snmpv3_authprotocol))
1263 return FAIL;
1264
1265 if (FAIL == dbsync_compare_uchar(row[29], snmpitem->snmpv3_privprotocol))
1266 return FAIL;
1267
1268 if (FAIL == dbsync_compare_str(row[30], snmpitem->snmpv3_contextname))
1269 return FAIL;
1270
1271 if (FAIL == dbsync_compare_str(row[8], snmpitem->snmp_oid))
1272 return FAIL;
1273 }
1274 else if (NULL != snmpitem)
1275 return FAIL;
1276
1277 ipmiitem = (ZBX_DC_IPMIITEM *)zbx_hashset_search(&dbsync_env.cache->ipmiitems, &item->itemid);
1278 if (ITEM_TYPE_IPMI == item->type)
1279 {
1280 if (NULL == ipmiitem)
1281 return FAIL;
1282
1283 if (FAIL == dbsync_compare_str(row[14], ipmiitem->ipmi_sensor))
1284 return FAIL;
1285 }
1286 else if (NULL != ipmiitem)
1287 return FAIL;
1288
1289 trapitem = (ZBX_DC_TRAPITEM *)zbx_hashset_search(&dbsync_env.cache->trapitems, &item->itemid);
1290 if (ITEM_TYPE_TRAPPER == item->type && '\0' != *row[17])
1291 {
1292 if (NULL == trapitem)
1293 return FAIL;
1294
1295 zbx_trim_str_list(row[17], ',');
1296
1297 if (FAIL == dbsync_compare_str(row[17], trapitem->trapper_hosts))
1298 return FAIL;
1299 }
1300 else if (NULL != trapitem)
1301 return FAIL;
1302
1303 logitem = (ZBX_DC_LOGITEM *)zbx_hashset_search(&dbsync_env.cache->logitems, &item->itemid);
1304 if (ITEM_VALUE_TYPE_LOG == item->value_type && '\0' != *row[18])
1305 {
1306 if (NULL == logitem)
1307 return FAIL;
1308
1309 if (FAIL == dbsync_compare_str(row[18], logitem->logtimefmt))
1310 return FAIL;
1311 }
1312 else if (NULL != logitem)
1313 return FAIL;
1314
1315 dbitem = (ZBX_DC_DBITEM *)zbx_hashset_search(&dbsync_env.cache->dbitems, &item->itemid);
1316 if (ITEM_TYPE_DB_MONITOR == item->type && '\0' != *row[19])
1317 {
1318 if (NULL == dbitem)
1319 return FAIL;
1320
1321 if (FAIL == dbsync_compare_str(row[19], dbitem->params))
1322 return FAIL;
1323
1324 if (FAIL == dbsync_compare_str(row[22], dbitem->username))
1325 return FAIL;
1326
1327 if (FAIL == dbsync_compare_str(row[23], dbitem->password))
1328 return FAIL;
1329 }
1330 else if (NULL != dbitem)
1331 return FAIL;
1332
1333 sshitem = (ZBX_DC_SSHITEM *)zbx_hashset_search(&dbsync_env.cache->sshitems, &item->itemid);
1334 if (ITEM_TYPE_SSH == item->type)
1335 {
1336 if (NULL == sshitem)
1337 return FAIL;
1338
1339 if (FAIL == dbsync_compare_uchar(row[21], sshitem->authtype))
1340 return FAIL;
1341
1342 if (FAIL == dbsync_compare_str(row[22], sshitem->username))
1343 return FAIL;
1344
1345 if (FAIL == dbsync_compare_str(row[23], sshitem->password))
1346 return FAIL;
1347
1348 if (FAIL == dbsync_compare_str(row[24], sshitem->publickey))
1349 return FAIL;
1350
1351 if (FAIL == dbsync_compare_str(row[25], sshitem->privatekey))
1352 return FAIL;
1353
1354 if (FAIL == dbsync_compare_str(row[19], sshitem->params))
1355 return FAIL;
1356 }
1357 else if (NULL != sshitem)
1358 return FAIL;
1359
1360 telnetitem = (ZBX_DC_TELNETITEM *)zbx_hashset_search(&dbsync_env.cache->telnetitems, &item->itemid);
1361 if (ITEM_TYPE_TELNET == item->type)
1362 {
1363 if (NULL == telnetitem)
1364 return FAIL;
1365
1366 if (FAIL == dbsync_compare_str(row[22], telnetitem->username))
1367 return FAIL;
1368
1369 if (FAIL == dbsync_compare_str(row[23], telnetitem->password))
1370 return FAIL;
1371
1372 if (FAIL == dbsync_compare_str(row[19], telnetitem->params))
1373 return FAIL;
1374 }
1375 else if (NULL != telnetitem)
1376 return FAIL;
1377
1378 simpleitem = (ZBX_DC_SIMPLEITEM *)zbx_hashset_search(&dbsync_env.cache->simpleitems, &item->itemid);
1379 if (ITEM_TYPE_SIMPLE == item->type)
1380 {
1381 if (NULL == simpleitem)
1382 return FAIL;
1383
1384 if (FAIL == dbsync_compare_str(row[22], simpleitem->username))
1385 return FAIL;
1386
1387 if (FAIL == dbsync_compare_str(row[23], simpleitem->password))
1388 return FAIL;
1389 }
1390 else if (NULL != simpleitem)
1391 return FAIL;
1392
1393 jmxitem = (ZBX_DC_JMXITEM *)zbx_hashset_search(&dbsync_env.cache->jmxitems, &item->itemid);
1394 if (ITEM_TYPE_JMX == item->type)
1395 {
1396 if (NULL == jmxitem)
1397 return FAIL;
1398
1399 if (FAIL == dbsync_compare_str(row[22], jmxitem->username))
1400 return FAIL;
1401
1402 if (FAIL == dbsync_compare_str(row[23], jmxitem->password))
1403 return FAIL;
1404 }
1405 else if (NULL != jmxitem)
1406 return FAIL;
1407
1408 calcitem = (ZBX_DC_CALCITEM *)zbx_hashset_search(&dbsync_env.cache->calcitems, &item->itemid);
1409 if (ITEM_TYPE_CALCULATED == item->type)
1410 {
1411 if (NULL == calcitem)
1412 return FAIL;
1413
1414 if (FAIL == dbsync_compare_str(row[19], calcitem->params))
1415 return FAIL;
1416 }
1417 else if (NULL != calcitem)
1418 return FAIL;
1419
1420 return SUCCEED;
1421 }
1422
1423 /******************************************************************************
1424 * *
1425 * Function: zbx_dbsync_compare_items *
1426 * *
1427 * Purpose: compares items table with cached configuration data *
1428 * *
1429 * Parameter: cache - [IN] the configuration cache *
1430 * sync - [OUT] the changeset *
1431 * *
1432 * Return value: SUCCEED - the changeset was successfully calculated *
1433 * FAIL - otherwise *
1434 * *
1435 ******************************************************************************/
zbx_dbsync_compare_items(zbx_dbsync_t * sync)1436 int zbx_dbsync_compare_items(zbx_dbsync_t *sync)
1437 {
1438 DB_ROW row;
1439 DB_RESULT result;
1440 zbx_hashset_t ids;
1441 zbx_hashset_iter_t iter;
1442 zbx_uint64_t rowid;
1443 ZBX_DC_ITEM *item;
1444
1445 if (NULL == (result = DBselect(
1446 "select i.itemid,i.hostid,i.status,i.type,i.data_type,i.value_type,i.key_,"
1447 "i.snmp_community,i.snmp_oid,i.port,i.snmpv3_securityname,i.snmpv3_securitylevel,"
1448 "i.snmpv3_authpassphrase,i.snmpv3_privpassphrase,i.ipmi_sensor,i.delay,i.delay_flex,"
1449 "i.trapper_hosts,i.logtimefmt,i.params,i.state,i.authtype,i.username,i.password,"
1450 "i.publickey,i.privatekey,i.flags,i.interfaceid,i.snmpv3_authprotocol,"
1451 "i.snmpv3_privprotocol,i.snmpv3_contextname,i.lastlogsize,i.mtime,i.delta,i.multiplier,"
1452 "i.formula,i.history,i.trends,i.inventory_link,i.valuemapid,i.units,i.error"
1453 " from items i,hosts h"
1454 " where i.hostid=h.hostid"
1455 " and h.status in (%d,%d)"
1456 " and i.flags<>%d",
1457 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
1458 ZBX_FLAG_DISCOVERY_PROTOTYPE)))
1459 {
1460 return FAIL;
1461 }
1462
1463 sync->columns_num = 42;
1464
1465 if (ZBX_DBSYNC_INIT == sync->mode)
1466 {
1467 sync->dbresult = result;
1468 return SUCCEED;
1469 }
1470
1471 zbx_hashset_create(&ids, dbsync_env.cache->items.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
1472 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1473
1474 while (NULL != (row = DBfetch(result)))
1475 {
1476 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
1477
1478 ZBX_STR2UINT64(rowid, row[0]);
1479 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
1480
1481 if (NULL == (item = (ZBX_DC_ITEM *)zbx_hashset_search(&dbsync_env.cache->items, &rowid)))
1482 tag = ZBX_DBSYNC_ROW_ADD;
1483 else if (FAIL == dbsync_compare_item(item, row))
1484 tag = ZBX_DBSYNC_ROW_UPDATE;
1485
1486 if (ZBX_DBSYNC_ROW_NONE != tag)
1487 dbsync_add_row(sync, rowid, tag, row);
1488 }
1489
1490 zbx_hashset_iter_reset(&dbsync_env.cache->items, &iter);
1491 while (NULL != (item = (ZBX_DC_ITEM *)zbx_hashset_iter_next(&iter)))
1492 {
1493 if (NULL == zbx_hashset_search(&ids, &item->itemid))
1494 dbsync_add_row(sync, item->itemid, ZBX_DBSYNC_ROW_REMOVE, NULL);
1495 }
1496
1497 zbx_hashset_destroy(&ids);
1498 DBfree_result(result);
1499
1500 return SUCCEED;
1501 }
1502
1503 /******************************************************************************
1504 * *
1505 * Function: dbsync_compare_trigger *
1506 * *
1507 * Purpose: compares triggers table row with cached configuration data *
1508 * *
1509 * Parameter: trigger - [IN] the cached trigger *
1510 * row - [IN] the database row *
1511 * *
1512 * Return value: SUCCEED - the row matches configuration data *
1513 * FAIL - otherwise *
1514 * *
1515 ******************************************************************************/
dbsync_compare_trigger(const ZBX_DC_TRIGGER * trigger,const DB_ROW row)1516 static int dbsync_compare_trigger(const ZBX_DC_TRIGGER *trigger, const DB_ROW row)
1517 {
1518 if (FAIL == dbsync_compare_str(row[1], trigger->description))
1519 return FAIL;
1520
1521 if (FAIL == dbsync_compare_str(row[2], trigger->expression))
1522 return FAIL;
1523
1524 if (FAIL == dbsync_compare_uchar(row[4], trigger->priority))
1525 return FAIL;
1526
1527 if (FAIL == dbsync_compare_uchar(row[5], trigger->type))
1528 return FAIL;
1529
1530 if (FAIL == dbsync_compare_uchar(row[9], trigger->status))
1531 return FAIL;
1532
1533 return SUCCEED;
1534 }
1535
1536 /******************************************************************************
1537 * *
1538 * Function: zbx_dbsync_compare_triggers *
1539 * *
1540 * Purpose: compares triggers table with cached configuration data *
1541 * *
1542 * Parameter: cache - [IN] the configuration cache *
1543 * sync - [OUT] the changeset *
1544 * *
1545 * Return value: SUCCEED - the changeset was successfully calculated *
1546 * FAIL - otherwise *
1547 * *
1548 ******************************************************************************/
zbx_dbsync_compare_triggers(zbx_dbsync_t * sync)1549 int zbx_dbsync_compare_triggers(zbx_dbsync_t *sync)
1550 {
1551 DB_ROW row;
1552 DB_RESULT result;
1553 zbx_hashset_t ids;
1554 zbx_hashset_iter_t iter;
1555 zbx_uint64_t rowid;
1556 ZBX_DC_TRIGGER *trigger;
1557
1558 if (NULL == (result = DBselect(
1559 "select distinct t.triggerid,t.description,t.expression,t.error,"
1560 "t.priority,t.type,t.value,t.state,t.lastchange,t.status"
1561 " from hosts h,items i,functions f,triggers t"
1562 " where h.hostid=i.hostid"
1563 " and i.itemid=f.itemid"
1564 " and f.triggerid=t.triggerid"
1565 " and h.status in (%d,%d)"
1566 " and t.flags<>%d",
1567 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
1568 ZBX_FLAG_DISCOVERY_PROTOTYPE)))
1569 {
1570 return FAIL;
1571 }
1572
1573 sync->columns_num = 10;
1574
1575 if (ZBX_DBSYNC_INIT == sync->mode)
1576 {
1577 sync->dbresult = result;
1578 return SUCCEED;
1579 }
1580
1581 zbx_hashset_create(&ids, dbsync_env.cache->triggers.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
1582 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1583
1584 while (NULL != (row = DBfetch(result)))
1585 {
1586 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
1587
1588 ZBX_STR2UINT64(rowid, row[0]);
1589 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
1590
1591 if (NULL == (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_search(&dbsync_env.cache->triggers, &rowid)))
1592 tag = ZBX_DBSYNC_ROW_ADD;
1593 else if (FAIL == dbsync_compare_trigger(trigger, row))
1594 tag = ZBX_DBSYNC_ROW_UPDATE;
1595
1596 if (ZBX_DBSYNC_ROW_NONE != tag)
1597 dbsync_add_row(sync, rowid, tag, row);
1598 }
1599
1600 zbx_hashset_iter_reset(&dbsync_env.cache->triggers, &iter);
1601 while (NULL != (trigger = (ZBX_DC_TRIGGER *)zbx_hashset_iter_next(&iter)))
1602 {
1603 if (NULL == zbx_hashset_search(&ids, &trigger->triggerid))
1604 dbsync_add_row(sync, trigger->triggerid, ZBX_DBSYNC_ROW_REMOVE, NULL);
1605 }
1606
1607 zbx_hashset_destroy(&ids);
1608 DBfree_result(result);
1609
1610 return SUCCEED;
1611 }
1612
1613 /******************************************************************************
1614 * *
1615 * Function: zbx_dbsync_compare_trigger_dependency *
1616 * *
1617 * Purpose: compares trigger_depends table with cached configuration data *
1618 * *
1619 * Parameter: cache - [IN] the configuration cache *
1620 * sync - [OUT] the changeset *
1621 * *
1622 * Return value: SUCCEED - the changeset was successfully calculated *
1623 * FAIL - otherwise *
1624 * *
1625 ******************************************************************************/
zbx_dbsync_compare_trigger_dependency(zbx_dbsync_t * sync)1626 int zbx_dbsync_compare_trigger_dependency(zbx_dbsync_t *sync)
1627 {
1628 DB_ROW row;
1629 DB_RESULT result;
1630 zbx_hashset_t deps;
1631 zbx_hashset_iter_t iter;
1632 ZBX_DC_TRIGGER_DEPLIST *dep_down, *dep_up;
1633 zbx_uint64_pair_t *dep, dep_local;
1634 char down_s[MAX_ID_LEN + 1], up_s[MAX_ID_LEN + 1];
1635 char *del_row[2] = {down_s, up_s};
1636 int i;
1637
1638 if (NULL == (result = DBselect(
1639 "select distinct d.triggerid_down,d.triggerid_up"
1640 " from trigger_depends d,triggers t,hosts h,items i,functions f"
1641 " where t.triggerid=d.triggerid_down"
1642 " and t.flags<>%d"
1643 " and h.hostid=i.hostid"
1644 " and i.itemid=f.itemid"
1645 " and f.triggerid=d.triggerid_down"
1646 " and h.status in (%d,%d)",
1647 ZBX_FLAG_DISCOVERY_PROTOTYPE, HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED)))
1648 {
1649 return FAIL;
1650 }
1651
1652 sync->columns_num = 2;
1653
1654 if (ZBX_DBSYNC_INIT == sync->mode)
1655 {
1656 sync->dbresult = result;
1657 return SUCCEED;
1658 }
1659
1660 zbx_hashset_create(&deps, dbsync_env.cache->trigdeps.num_data * 5, uint64_pair_hash_func, uint64_pair_compare_func);
1661
1662 /* index all host->template links */
1663 zbx_hashset_iter_reset(&dbsync_env.cache->trigdeps, &iter);
1664 while (NULL != (dep_down = (ZBX_DC_TRIGGER_DEPLIST *)zbx_hashset_iter_next(&iter)))
1665 {
1666 dep_local.first = dep_down->triggerid;
1667
1668 for (i = 0; i < dep_down->dependencies.values_num; i++)
1669 {
1670 dep_up = (ZBX_DC_TRIGGER_DEPLIST *)dep_down->dependencies.values[i];
1671 dep_local.second = dep_up->triggerid;
1672 zbx_hashset_insert(&deps, &dep_local, sizeof(dep_local));
1673 }
1674 }
1675
1676 /* add new rows, remove existing rows from index */
1677 while (NULL != (row = DBfetch(result)))
1678 {
1679 ZBX_STR2UINT64(dep_local.first, row[0]);
1680 ZBX_STR2UINT64(dep_local.second, row[1]);
1681
1682 if (NULL == (dep = (zbx_uint64_pair_t *)zbx_hashset_search(&deps, &dep_local)))
1683 dbsync_add_row(sync, 0, ZBX_DBSYNC_ROW_ADD, row);
1684 else
1685 zbx_hashset_remove_direct(&deps, dep);
1686 }
1687
1688 /* add removed rows */
1689 zbx_hashset_iter_reset(&deps, &iter);
1690 while (NULL != (dep = (zbx_uint64_pair_t *)zbx_hashset_iter_next(&iter)))
1691 {
1692 zbx_snprintf(down_s, sizeof(down_s), ZBX_FS_UI64, dep->first);
1693 zbx_snprintf(up_s, sizeof(up_s), ZBX_FS_UI64, dep->second);
1694 dbsync_add_row(sync, 0, ZBX_DBSYNC_ROW_REMOVE, del_row);
1695 }
1696
1697 DBfree_result(result);
1698 zbx_hashset_destroy(&deps);
1699
1700 return SUCCEED;
1701 }
1702
1703 /******************************************************************************
1704 * *
1705 * Function: dbsync_compare_function *
1706 * *
1707 * Purpose: compares functions table row with cached configuration data *
1708 * *
1709 * Parameter: function - [IN] the cached function *
1710 * row - [IN] the database row *
1711 * *
1712 * Return value: SUCCEED - the row matches configuration data *
1713 * FAIL - otherwise *
1714 * *
1715 ******************************************************************************/
dbsync_compare_function(const ZBX_DC_FUNCTION * function,const DB_ROW row)1716 static int dbsync_compare_function(const ZBX_DC_FUNCTION *function, const DB_ROW row)
1717 {
1718 if (FAIL == dbsync_compare_uint64(row[0], function->itemid))
1719 return FAIL;
1720
1721 if (FAIL == dbsync_compare_uint64(row[4], function->triggerid))
1722 return FAIL;
1723
1724 if (FAIL == dbsync_compare_str(row[2], function->function))
1725 return FAIL;
1726
1727 if (FAIL == dbsync_compare_str(row[3], function->parameter))
1728 return FAIL;
1729
1730 return SUCCEED;
1731 }
1732
1733 /******************************************************************************
1734 * *
1735 * Function: zbx_dbsync_compare_functions *
1736 * *
1737 * Purpose: compares functions table with cached configuration data *
1738 * *
1739 * Parameter: cache - [IN] the configuration cache *
1740 * sync - [OUT] the changeset *
1741 * *
1742 * Return value: SUCCEED - the changeset was successfully calculated *
1743 * FAIL - otherwise *
1744 * *
1745 ******************************************************************************/
zbx_dbsync_compare_functions(zbx_dbsync_t * sync)1746 int zbx_dbsync_compare_functions(zbx_dbsync_t *sync)
1747 {
1748 DB_ROW row;
1749 DB_RESULT result;
1750 zbx_hashset_t ids;
1751 zbx_hashset_iter_t iter;
1752 zbx_uint64_t rowid;
1753 ZBX_DC_FUNCTION *function;
1754
1755 if (NULL == (result = DBselect(
1756 "select i.itemid,f.functionid,f.function,f.parameter,t.triggerid"
1757 " from hosts h,items i,functions f,triggers t"
1758 " where h.hostid=i.hostid"
1759 " and i.itemid=f.itemid"
1760 " and f.triggerid=t.triggerid"
1761 " and h.status in (%d,%d)"
1762 " and t.flags<>%d",
1763 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
1764 ZBX_FLAG_DISCOVERY_PROTOTYPE)))
1765 {
1766 return FAIL;
1767 }
1768
1769 sync->columns_num = 5;
1770
1771 if (ZBX_DBSYNC_INIT == sync->mode)
1772 {
1773 sync->dbresult = result;
1774 return SUCCEED;
1775 }
1776
1777 zbx_hashset_create(&ids, dbsync_env.cache->functions.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
1778 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1779
1780 while (NULL != (row = DBfetch(result)))
1781 {
1782 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
1783
1784 ZBX_STR2UINT64(rowid, row[1]);
1785 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
1786
1787 if (NULL == (function = (ZBX_DC_FUNCTION *)zbx_hashset_search(&dbsync_env.cache->functions, &rowid)))
1788 tag = ZBX_DBSYNC_ROW_ADD;
1789 else if (FAIL == dbsync_compare_function(function, row))
1790 tag = ZBX_DBSYNC_ROW_UPDATE;
1791
1792 if (ZBX_DBSYNC_ROW_NONE != tag)
1793 dbsync_add_row(sync, rowid, tag, row);
1794 }
1795
1796 zbx_hashset_iter_reset(&dbsync_env.cache->functions, &iter);
1797 while (NULL != (function = (ZBX_DC_FUNCTION *)zbx_hashset_iter_next(&iter)))
1798 {
1799 if (NULL == zbx_hashset_search(&ids, &function->functionid))
1800 dbsync_add_row(sync, function->functionid, ZBX_DBSYNC_ROW_REMOVE, NULL);
1801 }
1802
1803 zbx_hashset_destroy(&ids);
1804 DBfree_result(result);
1805
1806 return SUCCEED;
1807 }
1808
1809 /******************************************************************************
1810 * *
1811 * Function: dbsync_compare_expression *
1812 * *
1813 * Purpose: compares expressions table row with cached configuration data *
1814 * *
1815 * Parameter: expression - [IN] the cached expression *
1816 * row - [IN] the database row *
1817 * *
1818 * Return value: SUCCEED - the row matches configuration data *
1819 * FAIL - otherwise *
1820 * *
1821 ******************************************************************************/
dbsync_compare_expression(const ZBX_DC_EXPRESSION * expression,const DB_ROW row)1822 static int dbsync_compare_expression(const ZBX_DC_EXPRESSION *expression, const DB_ROW row)
1823 {
1824 if (FAIL == dbsync_compare_str(row[0], expression->regexp))
1825 return FAIL;
1826
1827 if (FAIL == dbsync_compare_str(row[2], expression->expression))
1828 return FAIL;
1829
1830 if (FAIL == dbsync_compare_uchar(row[3], expression->type))
1831 return FAIL;
1832
1833 if (*row[4] != expression->delimiter)
1834 return FAIL;
1835
1836 if (FAIL == dbsync_compare_uchar(row[5], expression->case_sensitive))
1837 return FAIL;
1838
1839 return SUCCEED;
1840 }
1841
1842 /******************************************************************************
1843 * *
1844 * Function: zbx_dbsync_compare_exprssions *
1845 * *
1846 * Purpose: compares expressions, regexps tables with cached configuration *
1847 * data *
1848 * *
1849 * Parameter: cache - [IN] the configuration cache *
1850 * sync - [OUT] the changeset *
1851 * *
1852 * Return value: SUCCEED - the changeset was successfully calculated *
1853 * FAIL - otherwise *
1854 * *
1855 ******************************************************************************/
zbx_dbsync_compare_expressions(zbx_dbsync_t * sync)1856 int zbx_dbsync_compare_expressions(zbx_dbsync_t *sync)
1857 {
1858 DB_ROW row;
1859 DB_RESULT result;
1860 zbx_hashset_t ids;
1861 zbx_hashset_iter_t iter;
1862 zbx_uint64_t rowid;
1863 ZBX_DC_EXPRESSION *expression;
1864
1865 if (NULL == (result = DBselect(
1866 "select r.name,e.expressionid,e.expression,e.expression_type,e.exp_delimiter,e.case_sensitive"
1867 " from regexps r,expressions e"
1868 " where r.regexpid=e.regexpid")))
1869 {
1870 return FAIL;
1871 }
1872
1873 sync->columns_num = 6;
1874
1875 if (ZBX_DBSYNC_INIT == sync->mode)
1876 {
1877 sync->dbresult = result;
1878 return SUCCEED;
1879 }
1880
1881 zbx_hashset_create(&ids, dbsync_env.cache->expressions.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
1882 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1883
1884 while (NULL != (row = DBfetch(result)))
1885 {
1886 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
1887
1888 ZBX_STR2UINT64(rowid, row[1]);
1889 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
1890
1891 if (NULL == (expression = (ZBX_DC_EXPRESSION *)zbx_hashset_search(&dbsync_env.cache->expressions, &rowid)))
1892 tag = ZBX_DBSYNC_ROW_ADD;
1893 else if (FAIL == dbsync_compare_expression(expression, row))
1894 tag = ZBX_DBSYNC_ROW_UPDATE;
1895
1896 if (ZBX_DBSYNC_ROW_NONE != tag)
1897 dbsync_add_row(sync, rowid, tag, row);
1898 }
1899
1900 zbx_hashset_iter_reset(&dbsync_env.cache->expressions, &iter);
1901 while (NULL != (expression = (ZBX_DC_EXPRESSION *)zbx_hashset_iter_next(&iter)))
1902 {
1903 if (NULL == zbx_hashset_search(&ids, &expression->expressionid))
1904 dbsync_add_row(sync, expression->expressionid, ZBX_DBSYNC_ROW_REMOVE, NULL);
1905 }
1906
1907 zbx_hashset_destroy(&ids);
1908 DBfree_result(result);
1909
1910 return SUCCEED;
1911 }
1912
1913 /******************************************************************************
1914 * *
1915 * Function: dbsync_compare_action *
1916 * *
1917 * Purpose: compares actions table row with cached configuration data *
1918 * *
1919 * Parameter: action - [IN] the cached action *
1920 * row - [IN] the database row *
1921 * *
1922 * Return value: SUCCEED - the row matches configuration data *
1923 * FAIL - otherwise *
1924 * *
1925 ******************************************************************************/
dbsync_compare_action(const zbx_dc_action_t * action,const DB_ROW row)1926 static int dbsync_compare_action(const zbx_dc_action_t *action, const DB_ROW row)
1927 {
1928
1929 if (FAIL == dbsync_compare_uchar(row[1], action->eventsource))
1930 return FAIL;
1931
1932 if (FAIL == dbsync_compare_uchar(row[2], action->evaltype))
1933 return FAIL;
1934
1935 if (FAIL == dbsync_compare_str(row[3], action->formula))
1936 return FAIL;
1937
1938 return SUCCEED;
1939 }
1940
1941 /******************************************************************************
1942 * *
1943 * Function: zbx_dbsync_compare_actions *
1944 * *
1945 * Purpose: compares actions table with cached configuration data *
1946 * *
1947 * Parameter: cache - [IN] the configuration cache *
1948 * sync - [OUT] the changeset *
1949 * *
1950 * Return value: SUCCEED - the changeset was successfully calculated *
1951 * FAIL - otherwise *
1952 * *
1953 ******************************************************************************/
zbx_dbsync_compare_actions(zbx_dbsync_t * sync)1954 int zbx_dbsync_compare_actions(zbx_dbsync_t *sync)
1955 {
1956 DB_ROW row;
1957 DB_RESULT result;
1958 zbx_hashset_t ids;
1959 zbx_hashset_iter_t iter;
1960 zbx_uint64_t rowid;
1961 zbx_dc_action_t *action;
1962
1963 if (NULL == (result = DBselect(
1964 "select actionid,eventsource,evaltype,formula"
1965 " from actions"
1966 " where status=%d",
1967 ACTION_STATUS_ACTIVE)))
1968 {
1969 return FAIL;
1970 }
1971
1972 sync->columns_num = 4;
1973
1974 if (ZBX_DBSYNC_INIT == sync->mode)
1975 {
1976 sync->dbresult = result;
1977 return SUCCEED;
1978 }
1979
1980 zbx_hashset_create(&ids, dbsync_env.cache->actions.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
1981 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1982
1983 while (NULL != (row = DBfetch(result)))
1984 {
1985 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
1986
1987 ZBX_STR2UINT64(rowid, row[0]);
1988 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
1989
1990 if (NULL == (action = (zbx_dc_action_t *)zbx_hashset_search(&dbsync_env.cache->actions, &rowid)))
1991 tag = ZBX_DBSYNC_ROW_ADD;
1992 else if (FAIL == dbsync_compare_action(action, row))
1993 tag = ZBX_DBSYNC_ROW_UPDATE;
1994
1995 if (ZBX_DBSYNC_ROW_NONE != tag)
1996 dbsync_add_row(sync, rowid, tag, row);
1997 }
1998
1999 zbx_hashset_iter_reset(&dbsync_env.cache->actions, &iter);
2000 while (NULL != (action = (zbx_dc_action_t *)zbx_hashset_iter_next(&iter)))
2001 {
2002 if (NULL == zbx_hashset_search(&ids, &action->actionid))
2003 dbsync_add_row(sync, action->actionid, ZBX_DBSYNC_ROW_REMOVE, NULL);
2004 }
2005
2006 zbx_hashset_destroy(&ids);
2007 DBfree_result(result);
2008
2009 return SUCCEED;
2010 }
2011
2012 /******************************************************************************
2013 * *
2014 * Function: dbsync_compare_action_condition *
2015 * *
2016 * Purpose: compares conditions table row with cached configuration data *
2017 * *
2018 * Parameter: action - [IN] the cached action *
2019 * row - [IN] the database row *
2020 * *
2021 * Return value: SUCCEED - the row matches configuration data *
2022 * FAIL - otherwise *
2023 * *
2024 ******************************************************************************/
dbsync_compare_action_condition(const zbx_dc_action_condition_t * condition,const DB_ROW row)2025 static int dbsync_compare_action_condition(const zbx_dc_action_condition_t *condition, const DB_ROW row)
2026 {
2027 if (FAIL == dbsync_compare_uchar(row[2], condition->conditiontype))
2028 return FAIL;
2029
2030 if (FAIL == dbsync_compare_uchar(row[3], condition->operator))
2031 return FAIL;
2032
2033 if (FAIL == dbsync_compare_str(row[4], condition->value))
2034 return FAIL;
2035
2036 return SUCCEED;
2037 }
2038
2039 /******************************************************************************
2040 * *
2041 * Function: zbx_dbsync_compare_action_conditions *
2042 * *
2043 * Purpose: compares conditions table with cached configuration data *
2044 * *
2045 * Parameter: cache - [IN] the configuration cache *
2046 * sync - [OUT] the changeset *
2047 * *
2048 * Return value: SUCCEED - the changeset was successfully calculated *
2049 * FAIL - otherwise *
2050 * *
2051 ******************************************************************************/
zbx_dbsync_compare_action_conditions(zbx_dbsync_t * sync)2052 int zbx_dbsync_compare_action_conditions(zbx_dbsync_t *sync)
2053 {
2054 DB_ROW row;
2055 DB_RESULT result;
2056 zbx_hashset_t ids;
2057 zbx_hashset_iter_t iter;
2058 zbx_uint64_t rowid;
2059 zbx_dc_action_condition_t *condition;
2060
2061 if (NULL == (result = DBselect(
2062 "select c.conditionid,c.actionid,c.conditiontype,c.operator,c.value"
2063 " from conditions c,actions a"
2064 " where c.actionid=a.actionid"
2065 " and a.status=%d",
2066 ACTION_STATUS_ACTIVE)))
2067 {
2068 return FAIL;
2069 }
2070
2071 sync->columns_num = 5;
2072
2073 if (ZBX_DBSYNC_INIT == sync->mode)
2074 {
2075 sync->dbresult = result;
2076 return SUCCEED;
2077 }
2078
2079 zbx_hashset_create(&ids, dbsync_env.cache->action_conditions.num_data, ZBX_DEFAULT_UINT64_HASH_FUNC,
2080 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2081
2082 while (NULL != (row = DBfetch(result)))
2083 {
2084 unsigned char tag = ZBX_DBSYNC_ROW_NONE;
2085
2086 ZBX_STR2UINT64(rowid, row[0]);
2087 zbx_hashset_insert(&ids, &rowid, sizeof(rowid));
2088
2089 if (NULL == (condition = (zbx_dc_action_condition_t *)zbx_hashset_search(&dbsync_env.cache->action_conditions,
2090 &rowid)))
2091 {
2092 tag = ZBX_DBSYNC_ROW_ADD;
2093 }
2094 else if (FAIL == dbsync_compare_action_condition(condition, row))
2095 tag = ZBX_DBSYNC_ROW_UPDATE;
2096
2097 if (ZBX_DBSYNC_ROW_NONE != tag)
2098 dbsync_add_row(sync, rowid, tag, row);
2099 }
2100
2101 zbx_hashset_iter_reset(&dbsync_env.cache->action_conditions, &iter);
2102 while (NULL != (condition = (zbx_dc_action_condition_t *)zbx_hashset_iter_next(&iter)))
2103 {
2104 if (NULL == zbx_hashset_search(&ids, &condition->conditionid))
2105 dbsync_add_row(sync, condition->conditionid, ZBX_DBSYNC_ROW_REMOVE, NULL);
2106 }
2107
2108 zbx_hashset_destroy(&ids);
2109 DBfree_result(result);
2110
2111 return SUCCEED;
2112 }
2113
2114