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], &macro, &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], &macro, &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