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