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