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