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 "lld.h"
21 #include "db.h"
22 #include "log.h"
23 #include "zbxalgo.h"
24 #include "zbxserver.h"
25 
26 typedef struct
27 {
28 	zbx_uint64_t		triggerid;
29 	char			*description;
30 	char			*comments;
31 	char			*url;
32 	char			*correlation_tag;
33 	char			*opdata;
34 	char			*event_name;
35 	char			*expression_orig;
36 	char			*recovery_expression_orig;
37 	unsigned char		status;
38 	unsigned char		type;
39 	unsigned char		priority;
40 	unsigned char		recovery_mode;
41 	unsigned char		correlation_mode;
42 	unsigned char		manual_close;
43 	unsigned char		discover;
44 	zbx_vector_ptr_t	functions;
45 	zbx_vector_ptr_t	dependencies;
46 	zbx_vector_ptr_t	tags;
47 	zbx_eval_context_t	eval_ctx;
48 	zbx_eval_context_t	eval_ctx_r;
49 }
50 zbx_lld_trigger_prototype_t;
51 
52 typedef struct
53 {
54 	zbx_uint64_t		triggerid;
55 	zbx_uint64_t		parent_triggerid;
56 	char			*description;
57 	char			*description_orig;
58 	char			*expression;
59 	char			*expression_orig;
60 	char			*recovery_expression;
61 	char			*recovery_expression_orig;
62 	char			*comments;
63 	char			*comments_orig;
64 	char			*url;
65 	char			*url_orig;
66 	char			*correlation_tag;
67 	char			*correlation_tag_orig;
68 	char			*opdata;
69 	char			*opdata_orig;
70 	char			*event_name;
71 	char			*event_name_orig;
72 	zbx_vector_ptr_t	functions;
73 	zbx_vector_ptr_t	dependencies;
74 	zbx_vector_ptr_t	dependents;
75 	zbx_vector_ptr_t	tags;
76 	zbx_vector_db_tag_ptr_t	override_tags;
77 #define ZBX_FLAG_LLD_TRIGGER_UNSET			__UINT64_C(0x0000)
78 #define ZBX_FLAG_LLD_TRIGGER_DISCOVERED			__UINT64_C(0x0001)
79 #define ZBX_FLAG_LLD_TRIGGER_UPDATE_DESCRIPTION		__UINT64_C(0x0002)
80 #define ZBX_FLAG_LLD_TRIGGER_UPDATE_EXPRESSION		__UINT64_C(0x0004)
81 #define ZBX_FLAG_LLD_TRIGGER_UPDATE_TYPE		__UINT64_C(0x0008)
82 #define ZBX_FLAG_LLD_TRIGGER_UPDATE_PRIORITY		__UINT64_C(0x0010)
83 #define ZBX_FLAG_LLD_TRIGGER_UPDATE_COMMENTS		__UINT64_C(0x0020)
84 #define ZBX_FLAG_LLD_TRIGGER_UPDATE_URL			__UINT64_C(0x0040)
85 #define ZBX_FLAG_LLD_TRIGGER_UPDATE_RECOVERY_EXPRESSION	__UINT64_C(0x0080)
86 #define ZBX_FLAG_LLD_TRIGGER_UPDATE_RECOVERY_MODE	__UINT64_C(0x0100)
87 #define ZBX_FLAG_LLD_TRIGGER_UPDATE_CORRELATION_MODE	__UINT64_C(0x0200)
88 #define ZBX_FLAG_LLD_TRIGGER_UPDATE_CORRELATION_TAG	__UINT64_C(0x0400)
89 #define ZBX_FLAG_LLD_TRIGGER_UPDATE_MANUAL_CLOSE	__UINT64_C(0x0800)
90 #define ZBX_FLAG_LLD_TRIGGER_UPDATE_OPDATA		__UINT64_C(0x1000)
91 #define ZBX_FLAG_LLD_TRIGGER_UPDATE_EVENT_NAME		__UINT64_C(0x2000)
92 #define ZBX_FLAG_LLD_TRIGGER_UPDATE										\
93 		(ZBX_FLAG_LLD_TRIGGER_UPDATE_DESCRIPTION | ZBX_FLAG_LLD_TRIGGER_UPDATE_EXPRESSION |		\
94 		ZBX_FLAG_LLD_TRIGGER_UPDATE_TYPE | ZBX_FLAG_LLD_TRIGGER_UPDATE_PRIORITY |			\
95 		ZBX_FLAG_LLD_TRIGGER_UPDATE_COMMENTS | ZBX_FLAG_LLD_TRIGGER_UPDATE_URL |			\
96 		ZBX_FLAG_LLD_TRIGGER_UPDATE_RECOVERY_EXPRESSION | ZBX_FLAG_LLD_TRIGGER_UPDATE_RECOVERY_MODE |	\
97 		ZBX_FLAG_LLD_TRIGGER_UPDATE_CORRELATION_MODE | ZBX_FLAG_LLD_TRIGGER_UPDATE_CORRELATION_TAG |	\
98 		ZBX_FLAG_LLD_TRIGGER_UPDATE_MANUAL_CLOSE | ZBX_FLAG_LLD_TRIGGER_UPDATE_OPDATA |			\
99 		ZBX_FLAG_LLD_TRIGGER_UPDATE_EVENT_NAME)
100 	zbx_uint64_t		flags;
101 	int			lastcheck;
102 	int			ts_delete;
103 	unsigned char		status;
104 	unsigned char		priority;
105 }
106 zbx_lld_trigger_t;
107 
108 typedef struct
109 {
110 	zbx_uint64_t	functionid;
111 	zbx_uint64_t	index;
112 	zbx_uint64_t	itemid;
113 	zbx_uint64_t	itemid_orig;
114 	char		*function;
115 	char		*function_orig;
116 	char		*parameter;
117 	char		*parameter_orig;
118 #define ZBX_FLAG_LLD_FUNCTION_UNSET			__UINT64_C(0x00)
119 #define ZBX_FLAG_LLD_FUNCTION_DISCOVERED		__UINT64_C(0x01)
120 #define ZBX_FLAG_LLD_FUNCTION_UPDATE_ITEMID		__UINT64_C(0x02)
121 #define ZBX_FLAG_LLD_FUNCTION_UPDATE_FUNCTION		__UINT64_C(0x04)
122 #define ZBX_FLAG_LLD_FUNCTION_UPDATE_PARAMETER		__UINT64_C(0x08)
123 #define ZBX_FLAG_LLD_FUNCTION_UPDATE								\
124 		(ZBX_FLAG_LLD_FUNCTION_UPDATE_ITEMID | ZBX_FLAG_LLD_FUNCTION_UPDATE_FUNCTION |	\
125 		ZBX_FLAG_LLD_FUNCTION_UPDATE_PARAMETER)
126 #define ZBX_FLAG_LLD_FUNCTION_DELETE			__UINT64_C(0x10)
127 	zbx_uint64_t	flags;
128 }
129 zbx_lld_function_t;
130 
131 typedef struct
132 {
133 	zbx_uint64_t		triggerdepid;
134 	zbx_uint64_t		triggerid_up;	/* generic trigger */
135 	zbx_lld_trigger_t	*trigger_up;	/* lld-created trigger; (null) if trigger depends on generic trigger */
136 #define ZBX_FLAG_LLD_DEPENDENCY_UNSET			__UINT64_C(0x00)
137 #define ZBX_FLAG_LLD_DEPENDENCY_DISCOVERED		__UINT64_C(0x01)
138 #define ZBX_FLAG_LLD_DEPENDENCY_DELETE			__UINT64_C(0x02)
139 	zbx_uint64_t		flags;
140 }
141 zbx_lld_dependency_t;
142 
143 typedef struct
144 {
145 	zbx_uint64_t	triggertagid;
146 	char		*tag;
147 	char		*value;
148 #define ZBX_FLAG_LLD_TAG_UNSET				__UINT64_C(0x00)
149 #define ZBX_FLAG_LLD_TAG_DISCOVERED			__UINT64_C(0x01)
150 #define ZBX_FLAG_LLD_TAG_UPDATE_TAG			__UINT64_C(0x02)
151 #define ZBX_FLAG_LLD_TAG_UPDATE_VALUE			__UINT64_C(0x04)
152 #define ZBX_FLAG_LLD_TAG_UPDATE							\
153 		(ZBX_FLAG_LLD_TAG_UPDATE_TAG | ZBX_FLAG_LLD_TAG_UPDATE_VALUE)
154 #define ZBX_FLAG_LLD_TAG_DELETE				__UINT64_C(0x08)
155 	zbx_uint64_t	flags;
156 }
157 zbx_lld_tag_t;
158 
159 typedef struct
160 {
161 	zbx_uint64_t		parent_triggerid;
162 	zbx_uint64_t		itemid;
163 	zbx_lld_trigger_t	*trigger;
164 }
165 zbx_lld_item_trigger_t;
166 
167 typedef struct
168 {
169 	zbx_uint64_t	itemid;
170 	unsigned char	flags;
171 }
172 zbx_lld_item_t;
173 
174 /* a reference to trigger which could be either existing trigger in database or */
175 /* a just discovered trigger stored in memory                                   */
176 typedef struct
177 {
178 	/* trigger id, 0 for newly discovered triggers */
179 	zbx_uint64_t		triggerid;
180 
181 	/* trigger data, NULL for non-discovered triggers */
182 	zbx_lld_trigger_t	*trigger;
183 
184 	/* flags to mark trigger dependencies during trigger dependency validation */
185 #define ZBX_LLD_TRIGGER_DEPENDENCY_NORMAL	0
186 #define ZBX_LLD_TRIGGER_DEPENDENCY_NEW		1
187 #define ZBX_LLD_TRIGGER_DEPENDENCY_DELETE	2
188 
189 	/* flags used to mark dependencies when trigger reference is use to store dependency links */
190 	int			flags;
191 }
192 zbx_lld_trigger_ref_t;
193 
194 /* a trigger node used to build trigger tree for dependency validation */
195 typedef struct
196 {
197 	/* trigger reference */
198 	zbx_lld_trigger_ref_t	trigger_ref;
199 
200 	/* the current iteration number, used during dependency validation */
201 	int			iter_num;
202 
203 	/* the number of dependents */
204 	int			parents;
205 
206 	/* trigger dependency list */
207 	zbx_vector_ptr_t	dependencies;
208 }
209 zbx_lld_trigger_node_t;
210 
211 /* a structure to keep information about current iteration during trigger dependencies validation */
212 typedef struct
213 {
214 	/* iteration number */
215 	int			iter_num;
216 
217 	/* the dependency (from->to) that should be removed in the case of recursive loop */
218 	zbx_lld_trigger_ref_t	*ref_from;
219 	zbx_lld_trigger_ref_t	*ref_to;
220 }
221 zbx_lld_trigger_node_iter_t;
222 
223 
224 static void	lld_tag_free(zbx_lld_tag_t *tag)
225 {
226 	zbx_free(tag->tag);
227 	zbx_free(tag->value);
228 	zbx_free(tag);
229 }
230 
231 static void	lld_item_free(zbx_lld_item_t *item)
232 {
233 	zbx_free(item);
234 }
235 
236 static void	lld_function_free(zbx_lld_function_t *function)
237 {
238 	zbx_free(function->parameter_orig);
239 	zbx_free(function->parameter);
240 	zbx_free(function->function_orig);
241 	zbx_free(function->function);
242 	zbx_free(function);
243 }
244 
245 static void	lld_trigger_prototype_free(zbx_lld_trigger_prototype_t *trigger_prototype)
246 {
247 	zbx_eval_clear(&trigger_prototype->eval_ctx);
248 	zbx_eval_clear(&trigger_prototype->eval_ctx_r);
249 
250 	zbx_vector_ptr_clear_ext(&trigger_prototype->tags, (zbx_clean_func_t)lld_tag_free);
251 	zbx_vector_ptr_destroy(&trigger_prototype->tags);
252 	zbx_vector_ptr_clear_ext(&trigger_prototype->dependencies, zbx_ptr_free);
253 	zbx_vector_ptr_destroy(&trigger_prototype->dependencies);
254 	zbx_vector_ptr_clear_ext(&trigger_prototype->functions, (zbx_mem_free_func_t)lld_function_free);
255 	zbx_vector_ptr_destroy(&trigger_prototype->functions);
256 	zbx_free(trigger_prototype->event_name);
257 	zbx_free(trigger_prototype->opdata);
258 	zbx_free(trigger_prototype->correlation_tag);
259 	zbx_free(trigger_prototype->url);
260 	zbx_free(trigger_prototype->comments);
261 	zbx_free(trigger_prototype->recovery_expression_orig);
262 	zbx_free(trigger_prototype->expression_orig);
263 	zbx_free(trigger_prototype->description);
264 	zbx_free(trigger_prototype);
265 }
266 
267 static void	lld_trigger_free(zbx_lld_trigger_t *trigger)
268 {
269 	zbx_vector_ptr_clear_ext(&trigger->tags, (zbx_clean_func_t)lld_tag_free);
270 	zbx_vector_db_tag_ptr_destroy(&trigger->override_tags);
271 	zbx_vector_ptr_destroy(&trigger->tags);
272 	zbx_vector_ptr_destroy(&trigger->dependents);
273 	zbx_vector_ptr_clear_ext(&trigger->dependencies, zbx_ptr_free);
274 	zbx_vector_ptr_destroy(&trigger->dependencies);
275 	zbx_vector_ptr_clear_ext(&trigger->functions, (zbx_clean_func_t)lld_function_free);
276 	zbx_vector_ptr_destroy(&trigger->functions);
277 	zbx_free(trigger->event_name_orig);
278 	zbx_free(trigger->event_name);
279 	zbx_free(trigger->opdata_orig);
280 	zbx_free(trigger->opdata);
281 	zbx_free(trigger->correlation_tag_orig);
282 	zbx_free(trigger->correlation_tag);
283 	zbx_free(trigger->url_orig);
284 	zbx_free(trigger->url);
285 	zbx_free(trigger->comments_orig);
286 	zbx_free(trigger->comments);
287 	zbx_free(trigger->recovery_expression_orig);
288 	zbx_free(trigger->recovery_expression);
289 	zbx_free(trigger->expression_orig);
290 	zbx_free(trigger->expression);
291 	zbx_free(trigger->description_orig);
292 	zbx_free(trigger->description);
293 	zbx_free(trigger);
294 }
295 
296 /******************************************************************************
297  *                                                                            *
298  * Function: lld_trigger_prototypes_get                                       *
299  *                                                                            *
300  * Purpose: retrieve trigger prototypes which are inherited from the          *
301  *          discovery rule                                                    *
302  *                                                                            *
303  * Parameters: lld_ruleid         - [IN] discovery rule id                    *
304  *             trigger_prototypes - [OUT] sorted list of trigger prototypes   *
305  *                                                                            *
306  ******************************************************************************/
307 static void	lld_trigger_prototypes_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *trigger_prototypes, char **error)
308 {
309 	DB_RESULT			result;
310 	DB_ROW				row;
311 	zbx_lld_trigger_prototype_t	*trigger_prototype;
312 	char				*errmsg = NULL;
313 
314 	result = DBselect(
315 			"select distinct t.triggerid,t.description,t.expression,t.status,t.type,t.priority,t.comments,"
316 				"t.url,t.recovery_expression,t.recovery_mode,t.correlation_mode,t.correlation_tag,"
317 				"t.manual_close,t.opdata,t.discover,t.event_name"
318 			" from triggers t,functions f,items i,item_discovery id"
319 			" where t.triggerid=f.triggerid"
320 				" and f.itemid=i.itemid"
321 				" and i.itemid=id.itemid"
322 				" and id.parent_itemid=" ZBX_FS_UI64,
323 			lld_ruleid);
324 
325 	/* run through trigger prototypes */
326 	while (NULL != (row = DBfetch(result)))
327 	{
328 		trigger_prototype = (zbx_lld_trigger_prototype_t *)zbx_malloc(NULL, sizeof(zbx_lld_trigger_prototype_t));
329 
330 		ZBX_STR2UINT64(trigger_prototype->triggerid, row[0]);
331 		trigger_prototype->description = zbx_strdup(NULL, row[1]);
332 		trigger_prototype->expression_orig = zbx_strdup(NULL, row[2]);
333 		trigger_prototype->recovery_expression_orig = zbx_strdup(NULL, row[8]);
334 		ZBX_STR2UCHAR(trigger_prototype->status, row[3]);
335 		ZBX_STR2UCHAR(trigger_prototype->type, row[4]);
336 		ZBX_STR2UCHAR(trigger_prototype->priority, row[5]);
337 		ZBX_STR2UCHAR(trigger_prototype->recovery_mode, row[9]);
338 		trigger_prototype->comments = zbx_strdup(NULL, row[6]);
339 		trigger_prototype->url = zbx_strdup(NULL, row[7]);
340 		ZBX_STR2UCHAR(trigger_prototype->correlation_mode, row[10]);
341 		trigger_prototype->correlation_tag = zbx_strdup(NULL, row[11]);
342 		ZBX_STR2UCHAR(trigger_prototype->manual_close, row[12]);
343 		trigger_prototype->opdata = zbx_strdup(NULL, row[13]);
344 		ZBX_STR2UCHAR(trigger_prototype->discover, row[14]);
345 		trigger_prototype->event_name = zbx_strdup(NULL, row[15]);
346 
347 		zbx_vector_ptr_create(&trigger_prototype->functions);
348 		zbx_vector_ptr_create(&trigger_prototype->dependencies);
349 		zbx_vector_ptr_create(&trigger_prototype->tags);
350 
351 		zbx_eval_init(&trigger_prototype->eval_ctx);
352 		zbx_eval_init(&trigger_prototype->eval_ctx_r);
353 
354 		if (SUCCEED != zbx_eval_parse_expression(&trigger_prototype->eval_ctx,
355 				trigger_prototype->expression_orig, ZBX_EVAL_TRIGGER_EXPRESSION_LLD, &errmsg))
356 		{
357 			*error = zbx_strdcatf(*error, "Invalid trigger prototype \"%s\" expression: %s\n",
358 					trigger_prototype->description, errmsg);
359 			zbx_free(errmsg);
360 			lld_trigger_prototype_free(trigger_prototype);
361 			continue;
362 		}
363 
364 		if ('\0' != *trigger_prototype->recovery_expression_orig &&
365 				SUCCEED != zbx_eval_parse_expression(&trigger_prototype->eval_ctx_r,
366 				trigger_prototype->recovery_expression_orig, ZBX_EVAL_TRIGGER_EXPRESSION_LLD, &errmsg))
367 		{
368 			*error = zbx_strdcatf(*error, "Invalid trigger prototype \"%s\" recovery expression: %s\n",
369 					trigger_prototype->description, errmsg);
370 			zbx_free(errmsg);
371 			lld_trigger_prototype_free(trigger_prototype);
372 			continue;
373 		}
374 
375 		zbx_vector_ptr_append(trigger_prototypes, trigger_prototype);
376 	}
377 	DBfree_result(result);
378 
379 	zbx_vector_ptr_sort(trigger_prototypes, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
380 }
381 
382 /******************************************************************************
383  *                                                                            *
384  * Function: lld_triggers_get                                                 *
385  *                                                                            *
386  * Purpose: retrieve triggers which were created by the specified trigger     *
387  *          prototypes                                                        *
388  *                                                                            *
389  * Parameters: trigger_prototypes - [IN] sorted list of trigger prototypes    *
390  *             triggers           - [OUT] sorted list of triggers             *
391  *                                                                            *
392  ******************************************************************************/
393 static void	lld_triggers_get(const zbx_vector_ptr_t *trigger_prototypes, zbx_vector_ptr_t *triggers)
394 {
395 	DB_RESULT		result;
396 	DB_ROW			row;
397 	zbx_vector_uint64_t	parent_triggerids;
398 	char			*sql = NULL;
399 	size_t			sql_alloc = 256, sql_offset = 0;
400 	int			i;
401 
402 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
403 
404 	zbx_vector_uint64_create(&parent_triggerids);
405 	zbx_vector_uint64_reserve(&parent_triggerids, trigger_prototypes->values_num);
406 
407 	for (i = 0; i < trigger_prototypes->values_num; i++)
408 	{
409 		const zbx_lld_trigger_prototype_t	*trigger_prototype;
410 
411 		trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[i];
412 
413 		zbx_vector_uint64_append(&parent_triggerids, trigger_prototype->triggerid);
414 	}
415 
416 	sql = (char *)zbx_malloc(sql, sql_alloc);
417 
418 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
419 			"select td.parent_triggerid,t.triggerid,t.description,t.expression,t.type,t.priority,"
420 				"t.comments,t.url,t.recovery_expression,t.recovery_mode,t.correlation_mode,"
421 				"t.correlation_tag,t.manual_close,t.opdata,td.lastcheck,td.ts_delete,t.event_name"
422 			" from triggers t,trigger_discovery td"
423 			" where t.triggerid=td.triggerid"
424 				" and");
425 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "td.parent_triggerid",
426 			parent_triggerids.values, parent_triggerids.values_num);
427 
428 	zbx_vector_uint64_destroy(&parent_triggerids);
429 
430 	result = DBselect("%s", sql);
431 
432 	zbx_free(sql);
433 
434 	while (NULL != (row = DBfetch(result)))
435 	{
436 		zbx_uint64_t				parent_triggerid;
437 		const zbx_lld_trigger_prototype_t	*trigger_prototype;
438 		zbx_lld_trigger_t			*trigger;
439 		int					index;
440 
441 		ZBX_STR2UINT64(parent_triggerid, row[0]);
442 
443 		if (FAIL == (index = zbx_vector_ptr_bsearch(trigger_prototypes, &parent_triggerid,
444 					ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
445 		{
446 			THIS_SHOULD_NEVER_HAPPEN;
447 			continue;
448 		}
449 
450 		trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[index];
451 
452 		trigger = (zbx_lld_trigger_t *)zbx_malloc(NULL, sizeof(zbx_lld_trigger_t));
453 
454 		ZBX_STR2UINT64(trigger->triggerid, row[1]);
455 		trigger->parent_triggerid = parent_triggerid;
456 		trigger->description = zbx_strdup(NULL, row[2]);
457 		trigger->description_orig = NULL;
458 		trigger->expression = zbx_strdup(NULL, row[3]);
459 		trigger->expression_orig = NULL;
460 		trigger->recovery_expression = zbx_strdup(NULL, row[8]);
461 		trigger->recovery_expression_orig = NULL;
462 
463 		trigger->flags = ZBX_FLAG_LLD_TRIGGER_UNSET;
464 
465 		if ((unsigned char)atoi(row[4]) != trigger_prototype->type)
466 			trigger->flags |= ZBX_FLAG_LLD_TRIGGER_UPDATE_TYPE;
467 
468 		trigger->priority = (unsigned char)atoi(row[5]);
469 
470 		if ((unsigned char)atoi(row[9]) != trigger_prototype->recovery_mode)
471 			trigger->flags |= ZBX_FLAG_LLD_TRIGGER_UPDATE_RECOVERY_MODE;
472 
473 		if ((unsigned char)atoi(row[10]) != trigger_prototype->correlation_mode)
474 			trigger->flags |= ZBX_FLAG_LLD_TRIGGER_UPDATE_CORRELATION_MODE;
475 
476 		if ((unsigned char)atoi(row[12]) != trigger_prototype->manual_close)
477 			trigger->flags |= ZBX_FLAG_LLD_TRIGGER_UPDATE_MANUAL_CLOSE;
478 
479 		trigger->comments = zbx_strdup(NULL, row[6]);
480 		trigger->comments_orig = NULL;
481 		trigger->url = zbx_strdup(NULL, row[7]);
482 		trigger->url_orig = NULL;
483 		trigger->correlation_tag = zbx_strdup(NULL, row[11]);
484 		trigger->correlation_tag_orig = NULL;
485 		trigger->opdata = zbx_strdup(NULL, row[13]);
486 		trigger->opdata_orig = NULL;
487 		trigger->event_name = zbx_strdup(NULL, row[16]);
488 		trigger->event_name_orig = NULL;
489 		trigger->lastcheck = atoi(row[14]);
490 		trigger->ts_delete = atoi(row[15]);
491 
492 		zbx_vector_ptr_create(&trigger->functions);
493 		zbx_vector_ptr_create(&trigger->dependencies);
494 		zbx_vector_ptr_create(&trigger->dependents);
495 		zbx_vector_ptr_create(&trigger->tags);
496 		zbx_vector_db_tag_ptr_create(&trigger->override_tags);
497 
498 		zbx_vector_ptr_append(triggers, trigger);
499 	}
500 	DBfree_result(result);
501 
502 	zbx_vector_ptr_sort(triggers, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
503 
504 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
505 }
506 
507 /******************************************************************************
508  *                                                                            *
509  * Function: lld_functions_get                                                *
510  *                                                                            *
511  * Purpose: retrieve functions which are used by all triggers in the host of  *
512  *          the trigger prototype                                             *
513  *                                                                            *
514  ******************************************************************************/
515 static void	lld_functions_get(zbx_vector_ptr_t *trigger_prototypes, zbx_vector_ptr_t *triggers)
516 {
517 	int				i;
518 	zbx_lld_trigger_prototype_t	*trigger_prototype;
519 	zbx_lld_trigger_t		*trigger;
520 	zbx_vector_uint64_t		triggerids;
521 
522 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
523 
524 	zbx_vector_uint64_create(&triggerids);
525 
526 	if (NULL != trigger_prototypes)
527 	{
528 		for (i = 0; i < trigger_prototypes->values_num; i++)
529 		{
530 			trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[i];
531 
532 			zbx_vector_uint64_append(&triggerids, trigger_prototype->triggerid);
533 		}
534 	}
535 
536 	for (i = 0; i < triggers->values_num; i++)
537 	{
538 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
539 
540 		zbx_vector_uint64_append(&triggerids, trigger->triggerid);
541 	}
542 
543 	if (0 != triggerids.values_num)
544 	{
545 		DB_RESULT		result;
546 		DB_ROW			row;
547 		zbx_lld_function_t	*function;
548 		zbx_uint64_t		triggerid;
549 		char			*sql = NULL;
550 		size_t			sql_alloc = 256, sql_offset = 0;
551 		int			index;
552 
553 		zbx_vector_uint64_sort(&triggerids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
554 
555 		sql = (char *)zbx_malloc(sql, sql_alloc);
556 
557 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
558 				"select functionid,triggerid,itemid,name,parameter"
559 				" from functions"
560 				" where");
561 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "triggerid",
562 				triggerids.values, triggerids.values_num);
563 
564 		result = DBselect("%s", sql);
565 
566 		zbx_free(sql);
567 
568 		while (NULL != (row = DBfetch(result)))
569 		{
570 			function = (zbx_lld_function_t *)zbx_malloc(NULL, sizeof(zbx_lld_function_t));
571 
572 			function->index = 0;
573 			ZBX_STR2UINT64(function->functionid, row[0]);
574 			ZBX_STR2UINT64(triggerid, row[1]);
575 			ZBX_STR2UINT64(function->itemid, row[2]);
576 			function->itemid_orig = 0;
577 			function->function = zbx_strdup(NULL, row[3]);
578 			function->function_orig = NULL;
579 			function->parameter = zbx_strdup(NULL, row[4]);
580 			function->parameter_orig = NULL;
581 			function->flags = ZBX_FLAG_LLD_FUNCTION_UNSET;
582 
583 			if (NULL != trigger_prototypes && FAIL != (index = zbx_vector_ptr_bsearch(trigger_prototypes,
584 					&triggerid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
585 			{
586 				trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[index];
587 
588 				zbx_vector_ptr_append(&trigger_prototype->functions, function);
589 			}
590 			else if (FAIL != (index = zbx_vector_ptr_bsearch(triggers, &triggerid,
591 					ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
592 			{
593 				trigger = (zbx_lld_trigger_t *)triggers->values[index];
594 
595 				zbx_vector_ptr_append(&trigger->functions, function);
596 			}
597 			else
598 			{
599 				THIS_SHOULD_NEVER_HAPPEN;
600 				lld_function_free(function);
601 			}
602 		}
603 		DBfree_result(result);
604 
605 		if (NULL != trigger_prototypes)
606 		{
607 			for (i = 0; i < trigger_prototypes->values_num; i++)
608 			{
609 				trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[i];
610 
611 				zbx_vector_ptr_sort(&trigger_prototype->functions, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
612 			}
613 		}
614 
615 		for (i = 0; i < triggers->values_num; i++)
616 		{
617 			trigger = (zbx_lld_trigger_t *)triggers->values[i];
618 
619 			zbx_vector_ptr_sort(&trigger->functions, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
620 		}
621 	}
622 
623 	zbx_vector_uint64_destroy(&triggerids);
624 
625 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
626 }
627 
628 /******************************************************************************
629  *                                                                            *
630  * Function: lld_dependencies_get                                             *
631  *                                                                            *
632  * Purpose: retrieve trigger dependencies                                     *
633  *                                                                            *
634  ******************************************************************************/
635 static void	lld_dependencies_get(zbx_vector_ptr_t *trigger_prototypes, zbx_vector_ptr_t *triggers)
636 {
637 	DB_RESULT			result;
638 	DB_ROW				row;
639 	zbx_lld_trigger_prototype_t	*trigger_prototype;
640 	zbx_lld_trigger_t		*trigger;
641 	zbx_lld_dependency_t		*dependency;
642 	zbx_vector_uint64_t		triggerids;
643 	zbx_uint64_t			triggerid_down;
644 	char				*sql = NULL;
645 	size_t				sql_alloc = 256, sql_offset = 0;
646 	int				i, index;
647 
648 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
649 
650 	zbx_vector_uint64_create(&triggerids);
651 
652 	for (i = 0; i < trigger_prototypes->values_num; i++)
653 	{
654 		trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[i];
655 
656 		zbx_vector_uint64_append(&triggerids, trigger_prototype->triggerid);
657 	}
658 
659 	for (i = 0; i < triggers->values_num; i++)
660 	{
661 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
662 
663 		zbx_vector_uint64_append(&triggerids, trigger->triggerid);
664 	}
665 
666 	zbx_vector_uint64_sort(&triggerids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
667 
668 	sql = (char *)zbx_malloc(sql, sql_alloc);
669 
670 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
671 			"select triggerdepid,triggerid_down,triggerid_up"
672 			" from trigger_depends"
673 			" where");
674 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "triggerid_down",
675 			triggerids.values, triggerids.values_num);
676 
677 	zbx_vector_uint64_destroy(&triggerids);
678 
679 	result = DBselect("%s", sql);
680 
681 	zbx_free(sql);
682 
683 	while (NULL != (row = DBfetch(result)))
684 	{
685 		dependency = (zbx_lld_dependency_t *)zbx_malloc(NULL, sizeof(zbx_lld_dependency_t));
686 
687 		ZBX_STR2UINT64(dependency->triggerdepid, row[0]);
688 		ZBX_STR2UINT64(triggerid_down, row[1]);
689 		ZBX_STR2UINT64(dependency->triggerid_up, row[2]);
690 		dependency->trigger_up = NULL;
691 		dependency->flags = ZBX_FLAG_LLD_DEPENDENCY_UNSET;
692 
693 		if (FAIL != (index = zbx_vector_ptr_bsearch(trigger_prototypes, &triggerid_down,
694 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
695 		{
696 			trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[index];
697 
698 			zbx_vector_ptr_append(&trigger_prototype->dependencies, dependency);
699 		}
700 		else if (FAIL != (index = zbx_vector_ptr_bsearch(triggers, &triggerid_down,
701 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
702 		{
703 			trigger = (zbx_lld_trigger_t *)triggers->values[index];
704 
705 			zbx_vector_ptr_append(&trigger->dependencies, dependency);
706 		}
707 		else
708 		{
709 			THIS_SHOULD_NEVER_HAPPEN;
710 			zbx_ptr_free(dependency);
711 		}
712 	}
713 	DBfree_result(result);
714 
715 	for (i = 0; i < trigger_prototypes->values_num; i++)
716 	{
717 		trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[i];
718 
719 		zbx_vector_ptr_sort(&trigger_prototype->dependencies, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
720 	}
721 
722 	for (i = 0; i < triggers->values_num; i++)
723 	{
724 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
725 
726 		zbx_vector_ptr_sort(&trigger->dependencies, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
727 	}
728 
729 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
730 }
731 
732 /******************************************************************************
733  *                                                                            *
734  * Function: lld_tags_get                                                     *
735  *                                                                            *
736  * Purpose: retrieve trigger tags                                             *
737  *                                                                            *
738  ******************************************************************************/
739 static void	lld_tags_get(zbx_vector_ptr_t *trigger_prototypes, zbx_vector_ptr_t *triggers)
740 {
741 	DB_RESULT			result;
742 	DB_ROW				row;
743 	zbx_vector_uint64_t		triggerids;
744 	int				i, index;
745 	zbx_lld_trigger_prototype_t	*trigger_prototype;
746 	zbx_lld_trigger_t		*trigger;
747 	zbx_lld_tag_t			*tag;
748 	char				*sql = NULL;
749 	size_t				sql_alloc = 256, sql_offset = 0;
750 	zbx_uint64_t			triggerid;
751 
752 	zbx_vector_uint64_create(&triggerids);
753 
754 	for (i = 0; i < trigger_prototypes->values_num; i++)
755 	{
756 		trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[i];
757 
758 		zbx_vector_uint64_append(&triggerids, trigger_prototype->triggerid);
759 	}
760 
761 	for (i = 0; i < triggers->values_num; i++)
762 	{
763 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
764 
765 		zbx_vector_uint64_append(&triggerids, trigger->triggerid);
766 	}
767 
768 	zbx_vector_uint64_sort(&triggerids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
769 
770 	sql = (char *)zbx_malloc(sql, sql_alloc);
771 
772 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
773 			"select triggertagid,triggerid,tag,value"
774 			" from trigger_tag"
775 			" where");
776 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "triggerid",
777 			triggerids.values, triggerids.values_num);
778 
779 	zbx_vector_uint64_destroy(&triggerids);
780 
781 	result = DBselect("%s", sql);
782 
783 	zbx_free(sql);
784 
785 	while (NULL != (row = DBfetch(result)))
786 	{
787 		tag = (zbx_lld_tag_t *)zbx_malloc(NULL, sizeof(zbx_lld_tag_t));
788 
789 		ZBX_STR2UINT64(tag->triggertagid, row[0]);
790 		ZBX_STR2UINT64(triggerid, row[1]);
791 		tag->tag = zbx_strdup(NULL, row[2]);
792 		tag->value = zbx_strdup(NULL, row[3]);
793 		tag->flags = ZBX_FLAG_LLD_DEPENDENCY_UNSET;
794 
795 		if (FAIL != (index = zbx_vector_ptr_bsearch(trigger_prototypes, &triggerid,
796 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
797 		{
798 			trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[index];
799 
800 			zbx_vector_ptr_append(&trigger_prototype->tags, tag);
801 		}
802 		else if (FAIL != (index = zbx_vector_ptr_bsearch(triggers, &triggerid,
803 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
804 		{
805 			trigger = (zbx_lld_trigger_t *)triggers->values[index];
806 
807 			zbx_vector_ptr_append(&trigger->tags, tag);
808 		}
809 		else
810 		{
811 			THIS_SHOULD_NEVER_HAPPEN;
812 			zbx_ptr_free(tag);
813 		}
814 
815 	}
816 	DBfree_result(result);
817 
818 	for (i = 0; i < trigger_prototypes->values_num; i++)
819 	{
820 		trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[i];
821 
822 		zbx_vector_ptr_sort(&trigger_prototype->tags, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
823 	}
824 
825 	for (i = 0; i < triggers->values_num; i++)
826 	{
827 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
828 
829 		zbx_vector_ptr_sort(&trigger->tags, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
830 	}
831 
832 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
833 }
834 
835 /******************************************************************************
836  *                                                                            *
837  * Function: lld_items_get                                                    *
838  *                                                                            *
839  * Purpose: returns the list of items which are related to the trigger        *
840  *          prototypes                                                        *
841  *                                                                            *
842  * Parameters: trigger_prototypes - [IN] a vector of trigger prototypes       *
843  *             items              - [OUT] sorted list of items                *
844  *                                                                            *
845  ******************************************************************************/
846 static void	lld_items_get(zbx_vector_ptr_t *trigger_prototypes, zbx_vector_ptr_t *items)
847 {
848 	DB_RESULT		result;
849 	DB_ROW			row;
850 	zbx_lld_item_t		*item;
851 	zbx_vector_uint64_t	parent_triggerids;
852 	char			*sql = NULL;
853 	size_t			sql_alloc = 256, sql_offset = 0;
854 	int			i;
855 
856 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
857 
858 	zbx_vector_uint64_create(&parent_triggerids);
859 	zbx_vector_uint64_reserve(&parent_triggerids, trigger_prototypes->values_num);
860 
861 	for (i = 0; i < trigger_prototypes->values_num; i++)
862 	{
863 		zbx_lld_trigger_prototype_t	*trigger_prototype;
864 
865 		trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[i];
866 
867 		zbx_vector_uint64_append(&parent_triggerids, trigger_prototype->triggerid);
868 	}
869 	sql = (char *)zbx_malloc(sql, sql_alloc);
870 
871 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
872 			"select distinct i.itemid,i.flags"
873 			" from items i,functions f"
874 			" where i.itemid=f.itemid"
875 				" and");
876 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "f.triggerid",
877 			parent_triggerids.values, parent_triggerids.values_num);
878 
879 	zbx_vector_uint64_destroy(&parent_triggerids);
880 
881 	result = DBselect("%s", sql);
882 
883 	zbx_free(sql);
884 
885 	while (NULL != (row = DBfetch(result)))
886 	{
887 		item = (zbx_lld_item_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_t));
888 
889 		ZBX_STR2UINT64(item->itemid, row[0]);
890 		ZBX_STR2UCHAR(item->flags, row[1]);
891 
892 		zbx_vector_ptr_append(items, item);
893 	}
894 	DBfree_result(result);
895 
896 	zbx_vector_ptr_sort(items, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
897 
898 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
899 }
900 
901 /******************************************************************************
902  *                                                                            *
903  * Function: lld_trigger_get                                                  *
904  *                                                                            *
905  * Purpose: finds already existing trigger, using an item prototype and items *
906  *          already created by it                                             *
907  *                                                                            *
908  * Return value: upon successful completion return pointer to the trigger     *
909  *                                                                            *
910  ******************************************************************************/
911 static zbx_lld_trigger_t	*lld_trigger_get(zbx_uint64_t parent_triggerid, zbx_hashset_t *items_triggers,
912 		const zbx_vector_ptr_t *item_links)
913 {
914 	int	i;
915 
916 	for (i = 0; i < item_links->values_num; i++)
917 	{
918 		zbx_lld_item_trigger_t		*item_trigger, item_trigger_local;
919 		const zbx_lld_item_link_t	*item_link = (zbx_lld_item_link_t *)item_links->values[i];
920 
921 		item_trigger_local.parent_triggerid = parent_triggerid;
922 		item_trigger_local.itemid = item_link->itemid;
923 
924 		if (NULL != (item_trigger = (zbx_lld_item_trigger_t *)zbx_hashset_search(items_triggers, &item_trigger_local)))
925 			return item_trigger->trigger;
926 	}
927 
928 	return NULL;
929 }
930 
931 /******************************************************************************
932  *                                                                            *
933  * Function: lld_eval_expression_index_functions                              *
934  *                                                                            *
935  * Purpose: set indexes for functionid tokens {<functionid>} from the         *
936  *          specified function vector                                         *
937  *                                                                            *
938  ******************************************************************************/
939 static void	lld_eval_expression_index_functions(zbx_eval_context_t *ctx, zbx_vector_ptr_t *functions)
940 {
941 	int			i, index;
942 	zbx_uint64_t		functionid;
943 	zbx_lld_function_t	*function;
944 
945 	for (i = 0; i < ctx->stack.values_num; i++)
946 	{
947 		zbx_eval_token_t	*token = &ctx->stack.values[i];
948 
949 		if (ZBX_EVAL_TOKEN_FUNCTIONID != token->type)
950 			continue;
951 
952 		if (SUCCEED != is_uint64_n(ctx->expression + token->loc.l + 1, token->loc.r - token->loc.l - 1,
953 				&functionid))
954 		{
955 			THIS_SHOULD_NEVER_HAPPEN;
956 			continue;
957 		}
958 
959 		if (FAIL != (index = zbx_vector_ptr_bsearch(functions, &functionid,
960 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
961 		{
962 			function = (zbx_lld_function_t *)functions->values[index];
963 
964 			function->index = index + 1;
965 			zbx_variant_set_ui64(&token->value, function->index);
966 		}
967 	}
968 }
969 
970 /******************************************************************************
971  *                                                                            *
972  * Function: lld_eval_expression_simplify                                     *
973  *                                                                            *
974  * Purpose: simplify parsed expression by replacing {<functionid>} with       *
975  *          {<function index>}                                                *
976  *                                                                            *
977  ******************************************************************************/
978 static void	lld_eval_expression_simplify(zbx_eval_context_t *ctx, char **expression, zbx_vector_ptr_t *functions)
979 {
980 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() expression:'%s'", __func__, (NULL != expression ? *expression : ""));
981 
982 	if (SUCCEED == zbx_eval_status(ctx))
983 	{
984 		lld_eval_expression_index_functions(ctx, functions);
985 
986 		if (NULL != expression)
987 		{
988 			char	*new_expression = NULL;
989 
990 			zbx_eval_compose_expression(ctx, &new_expression);
991 			zbx_free(*expression);
992 			*expression = new_expression;
993 		}
994 	}
995 
996 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() expression:'%s'", __func__, (NULL != expression ? *expression : ""));
997 }
998 
999 /******************************************************************************
1000  *                                                                            *
1001  * Function: lld_trigger_expression_simplify                                  *
1002  *                                                                            *
1003  * Purpose: simplify trigger expression by replacing {<functionid>} with      *
1004  *          {<function index>}                                                *
1005  *                                                                            *
1006  ******************************************************************************/
1007 static void	lld_trigger_expression_simplify(const zbx_lld_trigger_t *trigger, char **expression,
1008 		zbx_vector_ptr_t *functions)
1009 {
1010 	zbx_eval_context_t	ctx;
1011 	char			*errmsg = NULL;
1012 
1013 	if ('\0' == **expression)
1014 		return;
1015 
1016 	if (SUCCEED != zbx_eval_parse_expression(&ctx, *expression, ZBX_EVAL_TRIGGER_EXPRESSION_LLD,
1017 			&errmsg))
1018 	{
1019 		const char	*type;
1020 
1021 		type = (*expression == trigger->expression ? "" : " recovery");
1022 		zabbix_log(LOG_LEVEL_DEBUG, "Invalid trigger \"%s\"%s expression: %s", trigger->description, type,
1023 				errmsg);
1024 		zbx_free(errmsg);
1025 
1026 		/* set empty expression so it's replaced with discovered one */
1027 		*expression = zbx_strdup(*expression, "");
1028 		return;
1029 	}
1030 
1031 	lld_eval_expression_simplify(&ctx, expression, functions);
1032 	zbx_eval_clear(&ctx);
1033 }
1034 
1035 /******************************************************************************
1036  *                                                                            *
1037  * Function: lld_eval_expression_expand                                       *
1038  *                                                                            *
1039  * Purpose: expand parsed expression function indexes with function strings   *
1040  *          in format itemid:func(params)                                     *
1041  *                                                                            *
1042  ******************************************************************************/
1043 static char	*lld_eval_expression_expand(zbx_eval_context_t *ctx, const zbx_vector_ptr_t *functions)
1044 {
1045 	int		i, j;
1046 	char		*expression = NULL;
1047 	zbx_uint64_t	index;
1048 
1049 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() expression:'%s'", __func__, ctx->expression);
1050 
1051 	for (i = 0; i < ctx->stack.values_num; i++)
1052 	{
1053 		zbx_eval_token_t	*token = &ctx->stack.values[i];
1054 
1055 		if (ZBX_EVAL_TOKEN_FUNCTIONID != token->type)
1056 			continue;
1057 
1058 		if (ZBX_VARIANT_UI64 != token->value.type)
1059 		{
1060 			if (SUCCEED != is_uint64_n(ctx->expression + token->loc.l + 1, token->loc.r - token->loc.l - 1,
1061 					&index))
1062 			{
1063 				THIS_SHOULD_NEVER_HAPPEN;
1064 				continue;
1065 			}
1066 		}
1067 		else
1068 			index = token->value.data.ui64;
1069 
1070 		for (j = 0; j < functions->values_num; j++)
1071 		{
1072 			const zbx_lld_function_t	*function = (zbx_lld_function_t *)functions->values[j];
1073 
1074 			if (function->index == index)
1075 			{
1076 				char	*value;
1077 
1078 				value = zbx_dsprintf(NULL, ZBX_FS_UI64 ":%s(%s)", function->itemid,
1079 						function->function, function->parameter);
1080 				zbx_variant_clear(&token->value);
1081 				zbx_variant_set_str(&token->value, value);
1082 				break;
1083 			}
1084 		}
1085 	}
1086 
1087 	zbx_eval_compose_expression(ctx, &expression);
1088 
1089 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() expression:'%s'", __func__, expression);
1090 
1091 	return expression;
1092 }
1093 
1094 /******************************************************************************
1095  *                                                                            *
1096  * Function: lld_trigger_expression_expand                                    *
1097  *                                                                            *
1098  * Purpose: expand trigger expression function indexes with function strings  *
1099  *          in format itemid:func(params)                                     *
1100  *                                                                            *
1101  ******************************************************************************/
1102 static char	*lld_trigger_expression_expand(const zbx_lld_trigger_t *trigger, const char *expression,
1103 		const zbx_vector_ptr_t *functions)
1104 {
1105 	zbx_eval_context_t	ctx;
1106 	char			*errmsg = NULL, *new_expression;
1107 
1108 	if ('\0' == *expression)
1109 		return zbx_strdup(NULL, "");
1110 
1111 	if (SUCCEED != zbx_eval_parse_expression(&ctx, expression,
1112 			ZBX_EVAL_TRIGGER_EXPRESSION_LLD & (~ZBX_EVAL_COMPOSE_FUNCTIONID), &errmsg))
1113 	{
1114 		const char	*type;
1115 
1116 		type = (expression == trigger->expression ? "" : " recovery");
1117 		zabbix_log(LOG_LEVEL_DEBUG, "Invalid trigger \"%s\"%s expression: %s", trigger->description, type,
1118 				errmsg);
1119 		zbx_free(errmsg);
1120 
1121 		return zbx_strdup(NULL, "");
1122 	}
1123 
1124 	new_expression = lld_eval_expression_expand(&ctx, functions);
1125 	zbx_eval_clear(&ctx);
1126 
1127 	return new_expression;
1128 }
1129 
1130 /******************************************************************************
1131  *                                                                            *
1132  * Function: lld_trigger_expression_simplify_and_expand                       *
1133  *                                                                            *
1134  * Purpose: set function indexes and expand them to function strings in       *
1135  *          format itemid:func(params)                                        *
1136  *                                                                            *
1137  ******************************************************************************/
1138 static void	lld_trigger_expression_simplify_and_expand(const zbx_lld_trigger_t *trigger, char **expression,
1139 		zbx_vector_ptr_t *functions)
1140 {
1141 	zbx_eval_context_t	ctx;
1142 	char			*errmsg = NULL, *new_expression;
1143 
1144 	if ('\0' == **expression)
1145 		return;
1146 
1147 	if (SUCCEED != zbx_eval_parse_expression(&ctx, *expression,
1148 			ZBX_EVAL_TRIGGER_EXPRESSION_LLD & (~ZBX_EVAL_COMPOSE_FUNCTIONID), &errmsg))
1149 	{
1150 		const char	*type;
1151 
1152 		type = (*expression == trigger->expression ? "" : " recovery");
1153 		zabbix_log(LOG_LEVEL_DEBUG, "Invalid trigger \"%s\"%s expression: %s", trigger->description, type,
1154 				errmsg);
1155 		zbx_free(errmsg);
1156 
1157 		/* reset expression so it's replaced with discovered one */
1158 		*expression = zbx_strdup(*expression, "");
1159 		return;
1160 	}
1161 
1162 	lld_eval_expression_index_functions(&ctx, functions);
1163 	new_expression = lld_eval_expression_expand(&ctx, functions);
1164 	zbx_eval_clear(&ctx);
1165 	zbx_free(*expression);
1166 	*expression = new_expression;
1167 }
1168 
1169 static int	lld_parameter_make(const char *e, char **exp, const struct zbx_json_parse *jp_row,
1170 		const zbx_vector_ptr_t *lld_macros, char **error)
1171 {
1172 	int	ret;
1173 	size_t	exp_alloc = 0, exp_offset = 0;
1174 	size_t	length;
1175 	char	err[64];
1176 
1177 	if (FAIL == zbx_function_validate_parameters(e, &length))
1178 	{
1179 		*error = zbx_dsprintf(*error, "Invalid parameter \"%s\"", e);
1180 		return FAIL;
1181 	}
1182 
1183 	if (FAIL == (ret = substitute_function_lld_param(e, length, 0, exp, &exp_alloc, &exp_offset, jp_row, lld_macros,
1184 			err, sizeof(err))))
1185 	{
1186 		*error = zbx_strdup(*error, err);
1187 	}
1188 
1189 	return ret;
1190 }
1191 
1192 static int	lld_function_make(const zbx_lld_function_t *function_proto, zbx_vector_ptr_t *functions,
1193 		zbx_uint64_t itemid, const struct zbx_json_parse *jp_row, const zbx_vector_ptr_t *lld_macros,
1194 		char **error)
1195 {
1196 	int			i, ret, function_found = 0;
1197 	zbx_lld_function_t	*function = NULL;
1198 	char			*proto_parameter = NULL;
1199 
1200 	for (i = 0; i < functions->values_num; i++)
1201 	{
1202 		function = (zbx_lld_function_t *)functions->values[i];
1203 
1204 		if (0 != (function->flags & ZBX_FLAG_LLD_FUNCTION_DISCOVERED))
1205 			continue;
1206 
1207 		if (function->index == function_proto->index)
1208 		{
1209 			function_found = 1;
1210 			break;
1211 		}
1212 	}
1213 
1214 	if (FAIL == (ret = lld_parameter_make(function_proto->parameter, &proto_parameter, jp_row, lld_macros, error)))
1215 		goto clean;
1216 
1217 	if (0 == function_found)
1218 	{
1219 		function = (zbx_lld_function_t *)zbx_malloc(NULL, sizeof(zbx_lld_function_t));
1220 
1221 		function->index = function_proto->index;
1222 		function->functionid = 0;
1223 		function->itemid = itemid;
1224 		function->itemid_orig = 0;
1225 		function->function = zbx_strdup(NULL, function_proto->function);
1226 		function->function_orig = NULL;
1227 		function->parameter = proto_parameter;
1228 		proto_parameter = NULL;
1229 		function->parameter_orig = NULL;
1230 		function->flags = ZBX_FLAG_LLD_FUNCTION_DISCOVERED;
1231 
1232 		zbx_vector_ptr_append(functions, function);
1233 	}
1234 	else
1235 	{
1236 		if (function->itemid != itemid)
1237 		{
1238 			function->itemid_orig = function->itemid;
1239 			function->itemid = itemid;
1240 			function->flags |= ZBX_FLAG_LLD_FUNCTION_UPDATE_ITEMID;
1241 		}
1242 
1243 		if (0 != strcmp(function->function, function_proto->function))
1244 		{
1245 			function->function_orig = function->function;
1246 			function->function = zbx_strdup(NULL, function_proto->function);
1247 			function->flags |= ZBX_FLAG_LLD_FUNCTION_UPDATE_FUNCTION;
1248 		}
1249 
1250 		if (0 != strcmp(function->parameter, proto_parameter))
1251 		{
1252 			function->parameter_orig = function->parameter;
1253 			function->parameter = proto_parameter;
1254 			proto_parameter = NULL;
1255 			function->flags |= ZBX_FLAG_LLD_FUNCTION_UPDATE_PARAMETER;
1256 		}
1257 
1258 		function->flags |= ZBX_FLAG_LLD_FUNCTION_DISCOVERED;
1259 	}
1260 clean:
1261 	zbx_free(proto_parameter);
1262 
1263 	return ret;
1264 }
1265 
1266 static void	lld_functions_delete(zbx_vector_ptr_t *functions)
1267 {
1268 	int	i;
1269 
1270 	for (i = 0; i < functions->values_num; i++)
1271 	{
1272 		zbx_lld_function_t	*function = (zbx_lld_function_t *)functions->values[i];
1273 
1274 		if (0 != (function->flags & ZBX_FLAG_LLD_FUNCTION_DISCOVERED))
1275 			continue;
1276 
1277 		function->flags |= ZBX_FLAG_LLD_FUNCTION_DELETE;
1278 	}
1279 }
1280 
1281 static int	lld_functions_make(const zbx_vector_ptr_t *functions_proto, zbx_vector_ptr_t *functions,
1282 		const zbx_vector_ptr_t *items, const zbx_vector_ptr_t *item_links, const struct zbx_json_parse *jp_row,
1283 		const zbx_vector_ptr_t *lld_macros, char **error)
1284 {
1285 	int				i, index, ret = FAIL;
1286 	const zbx_lld_function_t	*function_proto;
1287 	const zbx_lld_item_t		*item_proto;
1288 	const zbx_lld_item_link_t	*item_link;
1289 	zbx_uint64_t			itemid;
1290 
1291 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1292 
1293 	for (i = 0; i < functions_proto->values_num; i++)
1294 	{
1295 		function_proto = (zbx_lld_function_t *)functions_proto->values[i];
1296 
1297 		index = zbx_vector_ptr_bsearch(items, &function_proto->itemid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
1298 
1299 		if (FAIL == index)
1300 			goto out;
1301 
1302 		item_proto = (zbx_lld_item_t *)items->values[index];
1303 
1304 		if (0 != (item_proto->flags & ZBX_FLAG_DISCOVERY_PROTOTYPE))
1305 		{
1306 			index = zbx_vector_ptr_bsearch(item_links, &item_proto->itemid,
1307 					ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
1308 
1309 			if (FAIL == index)
1310 				goto out;
1311 
1312 			item_link = (zbx_lld_item_link_t *)item_links->values[index];
1313 
1314 			itemid = item_link->itemid;
1315 		}
1316 		else
1317 			itemid = item_proto->itemid;
1318 
1319 		if (FAIL == lld_function_make(function_proto, functions, itemid, jp_row, lld_macros, error))
1320 			goto out;
1321 	}
1322 
1323 	lld_functions_delete(functions);
1324 
1325 	ret = SUCCEED;
1326 out:
1327 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
1328 
1329 	return ret;
1330 }
1331 
1332 /******************************************************************************
1333  *                                                                            *
1334  * Function: lld_eval_get_expanded_expression                                 *
1335  *                                                                            *
1336  * Purpose: return copy of the expression with expanded LLD macros            *
1337  *                                                                            *
1338  ******************************************************************************/
1339 static char	*lld_eval_get_expanded_expression(const zbx_eval_context_t *src, const struct zbx_json_parse *jp_row,
1340 		const zbx_vector_ptr_t *lld_macros, char *err, size_t err_len)
1341 {
1342 	zbx_eval_context_t	ctx;
1343 	int			i;
1344 	char			*expression = NULL;
1345 
1346 	/* empty expression will not be parsed */
1347 	if (SUCCEED != zbx_eval_status(src))
1348 		return zbx_strdup(NULL, "");
1349 
1350 	zbx_eval_copy(&ctx, src, src->expression);
1351 
1352 	for (i = 0; i < ctx.stack.values_num; i++)
1353 	{
1354 		zbx_eval_token_t	*token = &ctx.stack.values[i];
1355 		char			*value;
1356 
1357 		switch(token->type)
1358 		{
1359 			case ZBX_EVAL_TOKEN_VAR_LLDMACRO:
1360 			case ZBX_EVAL_TOKEN_VAR_USERMACRO:
1361 			case ZBX_EVAL_TOKEN_VAR_STR:
1362 				break;
1363 			default:
1364 				continue;
1365 		}
1366 
1367 		value = zbx_substr_unquote(ctx.expression, token->loc.l, token->loc.r);
1368 
1369 		if (FAIL == substitute_lld_macros(&value, jp_row, lld_macros, ZBX_MACRO_ANY, err, err_len))
1370 		{
1371 			zbx_free(value);
1372 			goto out;
1373 		}
1374 
1375 		zbx_variant_clear(&token->value);
1376 		zbx_variant_set_str(&token->value, value);
1377 	}
1378 
1379 	zbx_eval_compose_expression(&ctx, &expression);
1380 out:
1381 	zbx_eval_clear(&ctx);
1382 
1383 	return expression;
1384 }
1385 
1386 /******************************************************************************
1387  *                                                                            *
1388  * Function: lld_trigger_make                                                 *
1389  *                                                                            *
1390  * Purpose: create a trigger based on lld rule and add it to the list         *
1391  *                                                                            *
1392  ******************************************************************************/
1393 static void 	lld_trigger_make(const zbx_lld_trigger_prototype_t *trigger_prototype, zbx_vector_ptr_t *triggers,
1394 		const zbx_vector_ptr_t *items, zbx_hashset_t *items_triggers, const zbx_lld_row_t *lld_row,
1395 		const zbx_vector_ptr_t *lld_macros, char **error)
1396 {
1397 	zbx_lld_trigger_t		*trigger;
1398 	char				*buffer = NULL, *expression = NULL, *recovery_expression = NULL, err[64];
1399 	char				*err_msg = NULL;
1400 	const char			*operation_msg;
1401 	const struct zbx_json_parse	*jp_row = &lld_row->jp_row;
1402 	unsigned char			discover;
1403 
1404 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1405 
1406 	trigger = lld_trigger_get(trigger_prototype->triggerid, items_triggers, &lld_row->item_links);
1407 	operation_msg = NULL != trigger ? "update" : "create";
1408 
1409 	if (NULL == (expression = lld_eval_get_expanded_expression(&trigger_prototype->eval_ctx, jp_row, lld_macros,
1410 			err, sizeof(err))) ||
1411 			NULL == (recovery_expression = lld_eval_get_expanded_expression(&trigger_prototype->eval_ctx_r,
1412 					jp_row, lld_macros, err, sizeof(err))))
1413 	{
1414 		*error = zbx_strdcatf(*error, "Cannot %s trigger: failed to expand LLD macros in %s expression: %s.\n",
1415 				operation_msg, (NULL == expression ? "" : " recovery"), err);
1416 		goto out;
1417 	}
1418 
1419 	discover = trigger_prototype->discover;
1420 
1421 	if (NULL != trigger)
1422 	{
1423 		unsigned char	priority;
1424 
1425 		buffer = zbx_strdup(buffer, trigger_prototype->description);
1426 		substitute_lld_macros(&buffer, jp_row, lld_macros, ZBX_MACRO_FUNC, NULL, 0);
1427 		zbx_lrtrim(buffer, ZBX_WHITESPACE);
1428 		priority = trigger_prototype->priority;
1429 
1430 		lld_override_trigger(&lld_row->overrides, buffer, &priority, &trigger->override_tags, NULL, &discover);
1431 
1432 		if (ZBX_PROTOTYPE_NO_DISCOVER == discover)
1433 			goto out;
1434 
1435 		if (0 != strcmp(trigger->description, buffer))
1436 		{
1437 			trigger->description_orig = trigger->description;
1438 			trigger->description = buffer;
1439 			buffer = NULL;
1440 			trigger->flags |= ZBX_FLAG_LLD_TRIGGER_UPDATE_DESCRIPTION;
1441 		}
1442 
1443 		if (trigger->priority != priority)
1444 		{
1445 			trigger->priority = priority;
1446 			trigger->flags |= ZBX_FLAG_LLD_TRIGGER_UPDATE_PRIORITY;
1447 		}
1448 
1449 		if (0 != strcmp(trigger->expression, expression))
1450 		{
1451 			trigger->expression_orig = trigger->expression;
1452 			trigger->expression = expression;
1453 			expression = NULL;
1454 			trigger->flags |= ZBX_FLAG_LLD_TRIGGER_UPDATE_EXPRESSION;
1455 		}
1456 
1457 		if (0 != strcmp(trigger->recovery_expression, recovery_expression))
1458 		{
1459 			trigger->recovery_expression_orig = trigger->recovery_expression;
1460 			trigger->recovery_expression = recovery_expression;
1461 			recovery_expression = NULL;
1462 			trigger->flags |= ZBX_FLAG_LLD_TRIGGER_UPDATE_RECOVERY_EXPRESSION;
1463 		}
1464 
1465 		buffer = zbx_strdup(buffer, trigger_prototype->comments);
1466 		substitute_lld_macros(&buffer, jp_row, lld_macros, ZBX_MACRO_FUNC, NULL, 0);
1467 		zbx_lrtrim(buffer, ZBX_WHITESPACE);
1468 		if (0 != strcmp(trigger->comments, buffer))
1469 		{
1470 			trigger->comments_orig = trigger->comments;
1471 			trigger->comments = buffer;
1472 			buffer = NULL;
1473 			trigger->flags |= ZBX_FLAG_LLD_TRIGGER_UPDATE_COMMENTS;
1474 		}
1475 
1476 		buffer = zbx_strdup(buffer, trigger_prototype->url);
1477 		substitute_lld_macros(&buffer, jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
1478 		zbx_lrtrim(buffer, ZBX_WHITESPACE);
1479 		if (0 != strcmp(trigger->url, buffer))
1480 		{
1481 			trigger->url_orig = trigger->url;
1482 			trigger->url = buffer;
1483 			buffer = NULL;
1484 			trigger->flags |= ZBX_FLAG_LLD_TRIGGER_UPDATE_URL;
1485 		}
1486 
1487 		buffer = zbx_strdup(buffer, trigger_prototype->correlation_tag);
1488 		substitute_lld_macros(&buffer, jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
1489 		zbx_lrtrim(buffer, ZBX_WHITESPACE);
1490 		if (0 != strcmp(trigger->correlation_tag, buffer))
1491 		{
1492 			trigger->correlation_tag_orig = trigger->correlation_tag;
1493 			trigger->correlation_tag = buffer;
1494 			buffer = NULL;
1495 			trigger->flags |= ZBX_FLAG_LLD_TRIGGER_UPDATE_CORRELATION_TAG;
1496 		}
1497 
1498 		buffer = zbx_strdup(buffer, trigger_prototype->opdata);
1499 		substitute_lld_macros(&buffer, jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
1500 		zbx_lrtrim(buffer, ZBX_WHITESPACE);
1501 		if (0 != strcmp(trigger->opdata, buffer))
1502 		{
1503 			trigger->opdata_orig = trigger->opdata;
1504 			trigger->opdata = buffer;
1505 			buffer = NULL;
1506 			trigger->flags |= ZBX_FLAG_LLD_TRIGGER_UPDATE_OPDATA;
1507 		}
1508 
1509 		buffer = zbx_strdup(buffer, trigger_prototype->event_name);
1510 		substitute_lld_macros(&buffer, jp_row, lld_macros,
1511 				ZBX_MACRO_ANY | ZBX_TOKEN_EXPRESSION_MACRO | ZBX_MACRO_FUNC, NULL, 0);
1512 		zbx_lrtrim(buffer, ZBX_WHITESPACE);
1513 		if (0 != strcmp(trigger->event_name, buffer))
1514 		{
1515 			trigger->event_name_orig = trigger->event_name;
1516 			trigger->event_name = buffer;
1517 			buffer = NULL;
1518 			trigger->flags |= ZBX_FLAG_LLD_TRIGGER_UPDATE_EVENT_NAME;
1519 		}
1520 	}
1521 	else
1522 	{
1523 		trigger = (zbx_lld_trigger_t *)zbx_malloc(NULL, sizeof(zbx_lld_trigger_t));
1524 
1525 		trigger->triggerid = 0;
1526 		trigger->lastcheck = 0;
1527 		trigger->ts_delete = 0;
1528 		trigger->parent_triggerid = trigger_prototype->triggerid;
1529 
1530 		trigger->description = zbx_strdup(NULL, trigger_prototype->description);
1531 		trigger->description_orig = NULL;
1532 		substitute_lld_macros(&trigger->description, jp_row, lld_macros, ZBX_MACRO_FUNC, NULL, 0);
1533 		zbx_lrtrim(trigger->description, ZBX_WHITESPACE);
1534 
1535 		trigger->status = trigger_prototype->status;
1536 		trigger->priority = trigger_prototype->priority;
1537 
1538 		zbx_vector_db_tag_ptr_create(&trigger->override_tags);
1539 
1540 		lld_override_trigger(&lld_row->overrides, trigger->description, &trigger->priority,
1541 				&trigger->override_tags, &trigger->status, &discover);
1542 
1543 		if (ZBX_PROTOTYPE_NO_DISCOVER == discover)
1544 		{
1545 			zbx_vector_db_tag_ptr_destroy(&trigger->override_tags);
1546 			zbx_free(trigger->description);
1547 			zbx_free(trigger);
1548 			goto out;
1549 		}
1550 
1551 		trigger->expression = expression;
1552 		trigger->expression_orig = NULL;
1553 		expression = NULL;
1554 
1555 		trigger->recovery_expression = recovery_expression;
1556 		trigger->recovery_expression_orig = NULL;
1557 		recovery_expression = NULL;
1558 
1559 		trigger->comments = zbx_strdup(NULL, trigger_prototype->comments);
1560 		trigger->comments_orig = NULL;
1561 		substitute_lld_macros(&trigger->comments, jp_row, lld_macros, ZBX_MACRO_FUNC, NULL, 0);
1562 		zbx_lrtrim(trigger->comments, ZBX_WHITESPACE);
1563 
1564 		trigger->url = zbx_strdup(NULL, trigger_prototype->url);
1565 		trigger->url_orig = NULL;
1566 		substitute_lld_macros(&trigger->url, jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
1567 		zbx_lrtrim(trigger->url, ZBX_WHITESPACE);
1568 
1569 		trigger->correlation_tag = zbx_strdup(NULL, trigger_prototype->correlation_tag);
1570 		trigger->correlation_tag_orig = NULL;
1571 		substitute_lld_macros(&trigger->correlation_tag, jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
1572 		zbx_lrtrim(trigger->correlation_tag, ZBX_WHITESPACE);
1573 
1574 		trigger->opdata = zbx_strdup(NULL, trigger_prototype->opdata);
1575 		trigger->opdata_orig = NULL;
1576 		substitute_lld_macros(&trigger->opdata, jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
1577 		zbx_lrtrim(trigger->opdata, ZBX_WHITESPACE);
1578 
1579 		trigger->event_name = zbx_strdup(NULL, trigger_prototype->event_name);
1580 		trigger->event_name_orig = NULL;
1581 		substitute_lld_macros(&trigger->event_name, jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
1582 		zbx_lrtrim(trigger->event_name, ZBX_WHITESPACE);
1583 
1584 		zbx_vector_ptr_create(&trigger->functions);
1585 		zbx_vector_ptr_create(&trigger->dependencies);
1586 		zbx_vector_ptr_create(&trigger->dependents);
1587 		zbx_vector_ptr_create(&trigger->tags);
1588 
1589 		trigger->flags = ZBX_FLAG_LLD_TRIGGER_UNSET;
1590 
1591 		zbx_vector_ptr_append(triggers, trigger);
1592 	}
1593 
1594 	if (SUCCEED != lld_functions_make(&trigger_prototype->functions, &trigger->functions, items,
1595 			&lld_row->item_links, jp_row, lld_macros, &err_msg))
1596 	{
1597 		if (err_msg)
1598 		{
1599 			*error = zbx_strdcatf(*error, "Cannot %s trigger: %s.\n", operation_msg, err_msg);
1600 			zbx_free(err_msg);
1601 		}
1602 		goto out;
1603 	}
1604 
1605 	trigger->flags |= ZBX_FLAG_LLD_TRIGGER_DISCOVERED;
1606 out:
1607 	zbx_free(recovery_expression);
1608 	zbx_free(expression);
1609 	zbx_free(buffer);
1610 
1611 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1612 }
1613 
1614 static zbx_hash_t	items_triggers_hash_func(const void *data)
1615 {
1616 	const zbx_lld_item_trigger_t	*item_trigger = (zbx_lld_item_trigger_t *)data;
1617 	zbx_hash_t			hash;
1618 
1619 	hash = ZBX_DEFAULT_UINT64_HASH_FUNC(&item_trigger->parent_triggerid);
1620 	hash = ZBX_DEFAULT_UINT64_HASH_ALGO(&item_trigger->itemid, sizeof(zbx_uint64_t), hash);
1621 
1622 	return hash;
1623 }
1624 
1625 static int	items_triggers_compare_func(const void *d1, const void *d2)
1626 {
1627 	const zbx_lld_item_trigger_t	*item_trigger1 = (zbx_lld_item_trigger_t *)d1, *item_trigger2 = (zbx_lld_item_trigger_t *)d2;
1628 
1629 	ZBX_RETURN_IF_NOT_EQUAL(item_trigger1->parent_triggerid, item_trigger2->parent_triggerid);
1630 	ZBX_RETURN_IF_NOT_EQUAL(item_trigger1->itemid, item_trigger2->itemid);
1631 
1632 	return 0;
1633 }
1634 
1635 static void	lld_triggers_make(const zbx_vector_ptr_t *trigger_prototypes, zbx_vector_ptr_t *triggers,
1636 		const zbx_vector_ptr_t *items, const zbx_vector_ptr_t *lld_rows,
1637 		const zbx_vector_ptr_t *lld_macro_paths, char **error)
1638 {
1639 	const zbx_lld_trigger_prototype_t	*trigger_prototype;
1640 	int					i, j;
1641 	zbx_hashset_t				items_triggers;
1642 	zbx_lld_trigger_t			*trigger;
1643 	const zbx_lld_function_t		*function;
1644 	zbx_lld_item_trigger_t			item_trigger;
1645 
1646 	/* used for fast search of trigger by item prototype */
1647 	zbx_hashset_create(&items_triggers, 512, items_triggers_hash_func, items_triggers_compare_func);
1648 
1649 	for (i = 0; i < triggers->values_num; i++)
1650 	{
1651 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
1652 
1653 		for (j = 0; j < trigger->functions.values_num; j++)
1654 		{
1655 			function = (zbx_lld_function_t *)trigger->functions.values[j];
1656 
1657 			item_trigger.parent_triggerid = trigger->parent_triggerid;
1658 			item_trigger.itemid = function->itemid;
1659 			item_trigger.trigger = trigger;
1660 			zbx_hashset_insert(&items_triggers, &item_trigger, sizeof(item_trigger));
1661 		}
1662 	}
1663 
1664 	for (i = 0; i < trigger_prototypes->values_num; i++)
1665 	{
1666 		trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[i];
1667 
1668 		for (j = 0; j < lld_rows->values_num; j++)
1669 		{
1670 			zbx_lld_row_t	*lld_row = (zbx_lld_row_t *)lld_rows->values[j];
1671 
1672 			lld_trigger_make(trigger_prototype, triggers, items, &items_triggers, lld_row, lld_macro_paths,
1673 					error);
1674 		}
1675 	}
1676 
1677 	zbx_hashset_destroy(&items_triggers);
1678 
1679 	zbx_vector_ptr_sort(triggers, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
1680 }
1681 
1682 /******************************************************************************
1683  *                                                                            *
1684  * Function: lld_trigger_dependency_make                                      *
1685  *                                                                            *
1686  * Purpose: create a trigger dependencies                                     *
1687  *                                                                            *
1688  ******************************************************************************/
1689 static void 	lld_trigger_dependency_make(const zbx_lld_trigger_prototype_t *trigger_prototype,
1690 		const zbx_vector_ptr_t *trigger_prototypes, zbx_hashset_t *items_triggers, const zbx_lld_row_t *lld_row,
1691 		char **error)
1692 {
1693 	zbx_lld_trigger_t			*trigger, *dep_trigger;
1694 	const zbx_lld_trigger_prototype_t	*dep_trigger_prototype;
1695 	zbx_lld_dependency_t			*dependency;
1696 	zbx_uint64_t				triggerid_up;
1697 	int					i, j, index;
1698 
1699 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1700 
1701 	if (NULL == (trigger = lld_trigger_get(trigger_prototype->triggerid, items_triggers, &lld_row->item_links)))
1702 		goto out;
1703 
1704 	for (i = 0; i < trigger_prototype->dependencies.values_num; i++)
1705 	{
1706 		triggerid_up = ((zbx_lld_dependency_t *)trigger_prototype->dependencies.values[i])->triggerid_up;
1707 
1708 		index = zbx_vector_ptr_bsearch(trigger_prototypes, &triggerid_up, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
1709 
1710 		if (FAIL != index)
1711 		{
1712 			/* creating trigger dependency based on trigger prototype */
1713 
1714 			dep_trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[index];
1715 
1716 			dep_trigger = lld_trigger_get(dep_trigger_prototype->triggerid, items_triggers,
1717 					&lld_row->item_links);
1718 
1719 			if (NULL != dep_trigger)
1720 			{
1721 				if (0 == dep_trigger->triggerid)
1722 				{
1723 					dependency = (zbx_lld_dependency_t *)zbx_malloc(NULL, sizeof(zbx_lld_dependency_t));
1724 
1725 					dependency->triggerdepid = 0;
1726 					dependency->triggerid_up = 0;
1727 
1728 					zbx_vector_ptr_append(&trigger->dependencies, dependency);
1729 				}
1730 				else
1731 				{
1732 					int	dependency_found = 0;
1733 
1734 					for (j = 0; j < trigger->dependencies.values_num; j++)
1735 					{
1736 						dependency = (zbx_lld_dependency_t *)trigger->dependencies.values[j];
1737 
1738 						if (0 != (dependency->flags & ZBX_FLAG_LLD_DEPENDENCY_DISCOVERED))
1739 							continue;
1740 
1741 						if (dependency->triggerid_up == dep_trigger->triggerid)
1742 						{
1743 							dependency_found = 1;
1744 							break;
1745 						}
1746 					}
1747 
1748 					if (0 == dependency_found)
1749 					{
1750 						dependency = (zbx_lld_dependency_t *)zbx_malloc(NULL, sizeof(zbx_lld_dependency_t));
1751 
1752 						dependency->triggerdepid = 0;
1753 						dependency->triggerid_up = dep_trigger->triggerid;
1754 
1755 						zbx_vector_ptr_append(&trigger->dependencies, dependency);
1756 					}
1757 				}
1758 
1759 				zbx_vector_ptr_append(&dep_trigger->dependents, trigger);
1760 
1761 				dependency->trigger_up = dep_trigger;
1762 				dependency->flags = ZBX_FLAG_LLD_DEPENDENCY_DISCOVERED;
1763 			}
1764 			else
1765 			{
1766 				*error = zbx_strdcatf(*error, "Cannot create dependency on trigger \"%s\".\n",
1767 						trigger->description);
1768 			}
1769 		}
1770 		else
1771 		{
1772 			/* creating trigger dependency based on generic trigger */
1773 
1774 			for (j = 0; j < trigger->dependencies.values_num; j++)
1775 			{
1776 				dependency = (zbx_lld_dependency_t *)trigger->dependencies.values[j];
1777 
1778 				if (0 != (dependency->flags & ZBX_FLAG_LLD_DEPENDENCY_DISCOVERED))
1779 					continue;
1780 
1781 				if (dependency->triggerid_up == triggerid_up)
1782 					break;
1783 			}
1784 
1785 			if (j == trigger->dependencies.values_num)
1786 			{
1787 				dependency = (zbx_lld_dependency_t *)zbx_malloc(NULL, sizeof(zbx_lld_dependency_t));
1788 
1789 				dependency->triggerdepid = 0;
1790 				dependency->triggerid_up = triggerid_up;
1791 				dependency->trigger_up = NULL;
1792 
1793 				zbx_vector_ptr_append(&trigger->dependencies, dependency);
1794 			}
1795 
1796 			dependency->flags = ZBX_FLAG_LLD_DEPENDENCY_DISCOVERED;
1797 		}
1798 	}
1799 out:
1800 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1801 }
1802 
1803 static void	lld_trigger_dependencies_make(const zbx_vector_ptr_t *trigger_prototypes, zbx_vector_ptr_t *triggers,
1804 		const zbx_vector_ptr_t *lld_rows, char **error)
1805 {
1806 	const zbx_lld_trigger_prototype_t	*trigger_prototype;
1807 	int				i, j;
1808 	zbx_hashset_t			items_triggers;
1809 	zbx_lld_trigger_t		*trigger;
1810 	zbx_lld_function_t		*function;
1811 	zbx_lld_item_trigger_t		item_trigger;
1812 	zbx_lld_dependency_t		*dependency;
1813 
1814 	for (i = 0; i < trigger_prototypes->values_num; i++)
1815 	{
1816 		trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[i];
1817 
1818 		if (0 != trigger_prototype->dependencies.values_num)
1819 			break;
1820 	}
1821 
1822 	for (j = 0; j < triggers->values_num; j++)
1823 	{
1824 		trigger = (zbx_lld_trigger_t *)triggers->values[j];
1825 
1826 		if (0 != trigger->dependencies.values_num)
1827 			break;
1828 	}
1829 
1830 	/* all trigger prototypes and triggers have no dependencies */
1831 	if (i == trigger_prototypes->values_num && j == triggers->values_num)
1832 		return;
1833 
1834 	/* used for fast search of trigger by item prototype */
1835 	zbx_hashset_create(&items_triggers, 512, items_triggers_hash_func, items_triggers_compare_func);
1836 
1837 	for (i = 0; i < triggers->values_num; i++)
1838 	{
1839 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
1840 
1841 		if (0 == (trigger->flags & ZBX_FLAG_LLD_TRIGGER_DISCOVERED))
1842 			continue;
1843 
1844 		for (j = 0; j < trigger->functions.values_num; j++)
1845 		{
1846 			function = (zbx_lld_function_t *)trigger->functions.values[j];
1847 
1848 			item_trigger.parent_triggerid = trigger->parent_triggerid;
1849 			item_trigger.itemid = function->itemid;
1850 			item_trigger.trigger = trigger;
1851 			zbx_hashset_insert(&items_triggers, &item_trigger, sizeof(item_trigger));
1852 		}
1853 	}
1854 
1855 	for (i = 0; i < trigger_prototypes->values_num; i++)
1856 	{
1857 		trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[i];
1858 
1859 		for (j = 0; j < lld_rows->values_num; j++)
1860 		{
1861 			zbx_lld_row_t	*lld_row = (zbx_lld_row_t *)lld_rows->values[j];
1862 
1863 			lld_trigger_dependency_make(trigger_prototype, trigger_prototypes,
1864 					&items_triggers, lld_row, error);
1865 		}
1866 	}
1867 
1868 	/* marking dependencies which will be deleted */
1869 	for (i = 0; i < triggers->values_num; i++)
1870 	{
1871 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
1872 
1873 		if (0 == (trigger->flags & ZBX_FLAG_LLD_TRIGGER_DISCOVERED))
1874 			continue;
1875 
1876 		for (j = 0; j < trigger->dependencies.values_num; j++)
1877 		{
1878 			dependency = (zbx_lld_dependency_t *)trigger->dependencies.values[j];
1879 
1880 			if (0 == (dependency->flags & ZBX_FLAG_LLD_DEPENDENCY_DISCOVERED))
1881 				dependency->flags = ZBX_FLAG_LLD_DEPENDENCY_DELETE;
1882 		}
1883 	}
1884 
1885 	zbx_hashset_destroy(&items_triggers);
1886 
1887 	zbx_vector_ptr_sort(triggers, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
1888 }
1889 
1890 /******************************************************************************
1891  *                                                                            *
1892  * Function: lld_trigger_tag_make                                             *
1893  *                                                                            *
1894  * Purpose: create a trigger tag                                              *
1895  *                                                                            *
1896  ******************************************************************************/
1897 static void 	lld_trigger_tag_make(zbx_lld_trigger_prototype_t *trigger_prototype,
1898 		zbx_hashset_t *items_triggers, zbx_lld_row_t *lld_row, const zbx_vector_ptr_t *lld_macro_paths)
1899 {
1900 	zbx_lld_trigger_t	*trigger;
1901 	int			i;
1902 	zbx_lld_tag_t		*tag;
1903 	char			*buffer = NULL;
1904 	const char		*key, *value;
1905 
1906 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1907 
1908 	if (NULL == (trigger = lld_trigger_get(trigger_prototype->triggerid, items_triggers, &lld_row->item_links)))
1909 		goto out;
1910 
1911 	zbx_vector_db_tag_ptr_sort(&trigger->override_tags, zbx_db_tag_compare_func);
1912 
1913 	for (i = 0; i < trigger_prototype->tags.values_num + trigger->override_tags.values_num; i++)
1914 	{
1915 		if (i < trigger_prototype->tags.values_num)
1916 		{
1917 			zbx_lld_tag_t	*tag_proto;
1918 
1919 			tag_proto = (zbx_lld_tag_t *)trigger_prototype->tags.values[i];
1920 			key = tag_proto->tag;
1921 			value = tag_proto->value;
1922 		}
1923 		else
1924 		{
1925 			zbx_db_tag_t	*dbtag;
1926 
1927 			dbtag = trigger->override_tags.values[i - trigger_prototype->tags.values_num];
1928 			key = dbtag->tag;
1929 			value = dbtag->value;
1930 		}
1931 
1932 		if (i < trigger->tags.values_num)
1933 		{
1934 			tag = (zbx_lld_tag_t *)trigger->tags.values[i];
1935 
1936 			buffer = zbx_strdup(buffer, key);
1937 			substitute_lld_macros(&buffer, &lld_row->jp_row, lld_macro_paths, ZBX_MACRO_FUNC, NULL, 0);
1938 			zbx_lrtrim(buffer, ZBX_WHITESPACE);
1939 			if (0 != strcmp(buffer, tag->tag))
1940 			{
1941 				zbx_free(tag->tag);
1942 				tag->tag = buffer;
1943 				buffer = NULL;
1944 				tag->flags |= ZBX_FLAG_LLD_TAG_UPDATE_TAG;
1945 			}
1946 
1947 			buffer = zbx_strdup(buffer, value);
1948 			substitute_lld_macros(&buffer, &lld_row->jp_row, lld_macro_paths, ZBX_MACRO_FUNC, NULL, 0);
1949 			zbx_lrtrim(buffer, ZBX_WHITESPACE);
1950 			if (0 != strcmp(buffer, tag->value))
1951 			{
1952 				zbx_free(tag->value);
1953 				tag->value = buffer;
1954 				buffer = NULL;
1955 				tag->flags |= ZBX_FLAG_LLD_TAG_UPDATE_VALUE;
1956 			}
1957 		}
1958 		else
1959 		{
1960 			tag = (zbx_lld_tag_t *)zbx_malloc(NULL, sizeof(zbx_lld_tag_t));
1961 
1962 			tag->triggertagid = 0;
1963 
1964 			tag->tag = zbx_strdup(NULL, key);
1965 			substitute_lld_macros(&tag->tag, &lld_row->jp_row, lld_macro_paths, ZBX_MACRO_FUNC, NULL, 0);
1966 			zbx_lrtrim(tag->tag, ZBX_WHITESPACE);
1967 
1968 			tag->value = zbx_strdup(NULL, value);
1969 			substitute_lld_macros(&tag->value, &lld_row->jp_row, lld_macro_paths, ZBX_MACRO_FUNC, NULL, 0);
1970 			zbx_lrtrim(tag->value, ZBX_WHITESPACE);
1971 
1972 			tag->flags = ZBX_FLAG_LLD_TAG_UNSET;
1973 
1974 			zbx_vector_ptr_append(&trigger->tags, tag);
1975 
1976 		}
1977 
1978 		tag->flags |= ZBX_FLAG_LLD_TAG_DISCOVERED;
1979 	}
1980 out:
1981 	zbx_free(buffer);
1982 
1983 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1984 }
1985 
1986 /******************************************************************************
1987  *                                                                            *
1988  * Function: lld_trigger_tags_make                                            *
1989  *                                                                            *
1990  * Purpose: create a trigger tags                                             *
1991  *                                                                            *
1992  ******************************************************************************/
1993 static void	lld_trigger_tags_make(zbx_vector_ptr_t *trigger_prototypes, zbx_vector_ptr_t *triggers,
1994 		const zbx_vector_ptr_t *lld_rows, const zbx_vector_ptr_t *lld_macro_paths)
1995 {
1996 	zbx_lld_trigger_prototype_t	*trigger_prototype;
1997 	int				i, j;
1998 	zbx_hashset_t			items_triggers;
1999 	zbx_lld_trigger_t		*trigger;
2000 	zbx_lld_function_t		*function;
2001 	zbx_lld_item_trigger_t		item_trigger;
2002 	zbx_lld_tag_t			*tag;
2003 
2004 	/* used for fast search of trigger by item prototype */
2005 	zbx_hashset_create(&items_triggers, 512, items_triggers_hash_func, items_triggers_compare_func);
2006 
2007 	for (i = 0; i < triggers->values_num; i++)
2008 	{
2009 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
2010 
2011 		if (0 == (trigger->flags & ZBX_FLAG_LLD_TRIGGER_DISCOVERED))
2012 			continue;
2013 
2014 		for (j = 0; j < trigger->functions.values_num; j++)
2015 		{
2016 			function = (zbx_lld_function_t *)trigger->functions.values[j];
2017 
2018 			item_trigger.parent_triggerid = trigger->parent_triggerid;
2019 			item_trigger.itemid = function->itemid;
2020 			item_trigger.trigger = trigger;
2021 			zbx_hashset_insert(&items_triggers, &item_trigger, sizeof(item_trigger));
2022 		}
2023 	}
2024 
2025 	for (i = 0; i < trigger_prototypes->values_num; i++)
2026 	{
2027 		trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[i];
2028 
2029 		for (j = 0; j < lld_rows->values_num; j++)
2030 		{
2031 			zbx_lld_row_t	*lld_row = (zbx_lld_row_t *)lld_rows->values[j];
2032 
2033 			lld_trigger_tag_make(trigger_prototype, &items_triggers, lld_row, lld_macro_paths);
2034 		}
2035 	}
2036 
2037 	/* marking tags which will be deleted */
2038 	for (i = 0; i < triggers->values_num; i++)
2039 	{
2040 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
2041 
2042 		if (0 == (trigger->flags & ZBX_FLAG_LLD_TRIGGER_DISCOVERED))
2043 			continue;
2044 
2045 		for (j = 0; j < trigger->tags.values_num; j++)
2046 		{
2047 			tag = (zbx_lld_tag_t *)trigger->tags.values[j];
2048 
2049 			if (0 == (tag->flags & ZBX_FLAG_LLD_TAG_DISCOVERED))
2050 				tag->flags = ZBX_FLAG_LLD_TAG_DELETE;
2051 		}
2052 	}
2053 
2054 	zbx_hashset_destroy(&items_triggers);
2055 
2056 	zbx_vector_ptr_sort(triggers, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
2057 }
2058 
2059 /******************************************************************************
2060  *                                                                            *
2061  * Function: lld_validate_trigger_field                                       *
2062  *                                                                            *
2063  ******************************************************************************/
2064 static void	lld_validate_trigger_field(zbx_lld_trigger_t *trigger, char **field, char **field_orig,
2065 		zbx_uint64_t flag, size_t field_len, char **error)
2066 {
2067 	if (0 == (trigger->flags & ZBX_FLAG_LLD_TRIGGER_DISCOVERED))
2068 		return;
2069 
2070 	/* only new triggers or triggers with changed data will be validated */
2071 	if (0 != trigger->triggerid && 0 == (trigger->flags & flag))
2072 		return;
2073 
2074 	if (SUCCEED != zbx_is_utf8(*field))
2075 	{
2076 		zbx_replace_invalid_utf8(*field);
2077 		*error = zbx_strdcatf(*error, "Cannot %s trigger: value \"%s\" has invalid UTF-8 sequence.\n",
2078 				(0 != trigger->triggerid ? "update" : "create"), *field);
2079 	}
2080 	else if (zbx_strlen_utf8(*field) > field_len)
2081 	{
2082 		*error = zbx_strdcatf(*error, "Cannot %s trigger: value \"%s\" is too long.\n",
2083 				(0 != trigger->triggerid ? "update" : "create"), *field);
2084 	}
2085 	else if (ZBX_FLAG_LLD_TRIGGER_UPDATE_DESCRIPTION == flag && '\0' == **field)
2086 	{
2087 		*error = zbx_strdcatf(*error, "Cannot %s trigger: name is empty.\n",
2088 				(0 != trigger->triggerid ? "update" : "create"));
2089 	}
2090 	else
2091 		return;
2092 
2093 	if (0 != trigger->triggerid)
2094 		lld_field_str_rollback(field, field_orig, &trigger->flags, flag);
2095 	else
2096 		trigger->flags &= ~ZBX_FLAG_LLD_TRIGGER_DISCOVERED;
2097 }
2098 
2099 /******************************************************************************
2100  *                                                                            *
2101  * Function: lld_trigger_changed                                              *
2102  *                                                                            *
2103  * Return value: returns SUCCEED if a trigger description or expression has   *
2104  *               been changed; FAIL - otherwise                               *
2105  *                                                                            *
2106  ******************************************************************************/
2107 static int	lld_trigger_changed(const zbx_lld_trigger_t *trigger)
2108 {
2109 	int			i;
2110 	zbx_lld_function_t	*function;
2111 
2112 	if (0 == trigger->triggerid)
2113 		return SUCCEED;
2114 
2115 	if (0 != (trigger->flags & (ZBX_FLAG_LLD_TRIGGER_UPDATE_DESCRIPTION | ZBX_FLAG_LLD_TRIGGER_UPDATE_EXPRESSION |
2116 			ZBX_FLAG_LLD_TRIGGER_UPDATE_RECOVERY_EXPRESSION)))
2117 	{
2118 		return SUCCEED;
2119 	}
2120 
2121 	for (i = 0; i < trigger->functions.values_num; i++)
2122 	{
2123 		function = (zbx_lld_function_t *)trigger->functions.values[i];
2124 
2125 		if (0 == function->functionid)
2126 		{
2127 			THIS_SHOULD_NEVER_HAPPEN;
2128 			return SUCCEED;
2129 		}
2130 
2131 		if (0 != (function->flags & ZBX_FLAG_LLD_FUNCTION_UPDATE))
2132 			return SUCCEED;
2133 	}
2134 
2135 	return FAIL;
2136 }
2137 
2138 /******************************************************************************
2139  *                                                                            *
2140  * Function: lld_triggers_equal                                               *
2141  *                                                                            *
2142  * Return value: returns SUCCEED if descriptions and expressions of           *
2143  *               the triggers are identical; FAIL - otherwise                 *
2144  *                                                                            *
2145  ******************************************************************************/
2146 static int	lld_triggers_equal(const zbx_lld_trigger_t *trigger, const zbx_lld_trigger_t *db_trigger)
2147 {
2148 	int	ret = FAIL;
2149 	char	*expression = NULL;
2150 
2151 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
2152 
2153 	if (0 != strcmp(trigger->description, db_trigger->description))
2154 		goto out;
2155 
2156 	expression = lld_trigger_expression_expand(trigger, trigger->expression, &trigger->functions);
2157 
2158 	if (0 != strcmp(expression, db_trigger->expression))
2159 		goto out;
2160 
2161 	zbx_free(expression);
2162 	expression = lld_trigger_expression_expand(trigger, trigger->recovery_expression, &trigger->functions);
2163 
2164 	if (0 == strcmp(expression, db_trigger->recovery_expression))
2165 		ret = SUCCEED;
2166 out:
2167 	zbx_free(expression);
2168 
2169 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
2170 
2171 	return ret;
2172 }
2173 
2174 /******************************************************************************
2175  *                                                                            *
2176  * Function: lld_triggers_validate                                            *
2177  *                                                                            *
2178  * Parameters: triggers - [IN] sorted list of triggers                        *
2179  *                                                                            *
2180  ******************************************************************************/
2181 static void	lld_triggers_validate(zbx_uint64_t hostid, zbx_vector_ptr_t *triggers, char **error)
2182 {
2183 	int			i, j, k;
2184 	zbx_lld_trigger_t	*trigger;
2185 	zbx_lld_function_t	*function;
2186 	zbx_vector_uint64_t	triggerids;
2187 	zbx_vector_str_t	descriptions;
2188 
2189 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
2190 
2191 	zbx_vector_uint64_create(&triggerids);
2192 	zbx_vector_str_create(&descriptions);
2193 
2194 	/* checking a validity of the fields */
2195 
2196 	for (i = 0; i < triggers->values_num; i++)
2197 	{
2198 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
2199 
2200 		lld_validate_trigger_field(trigger, &trigger->description, &trigger->description_orig,
2201 				ZBX_FLAG_LLD_TRIGGER_UPDATE_DESCRIPTION, TRIGGER_DESCRIPTION_LEN, error);
2202 		lld_validate_trigger_field(trigger, &trigger->comments, &trigger->comments_orig,
2203 				ZBX_FLAG_LLD_TRIGGER_UPDATE_COMMENTS, TRIGGER_COMMENTS_LEN, error);
2204 		lld_validate_trigger_field(trigger, &trigger->url, &trigger->url_orig,
2205 				ZBX_FLAG_LLD_TRIGGER_UPDATE_URL, TRIGGER_URL_LEN, error);
2206 		lld_validate_trigger_field(trigger, &trigger->correlation_tag, &trigger->correlation_tag_orig,
2207 				ZBX_FLAG_LLD_TRIGGER_UPDATE_CORRELATION_TAG, TAG_NAME_LEN, error);
2208 		lld_validate_trigger_field(trigger, &trigger->opdata, &trigger->opdata_orig,
2209 				ZBX_FLAG_LLD_TRIGGER_UPDATE_OPDATA, TRIGGER_OPDATA_LEN, error);
2210 		lld_validate_trigger_field(trigger, &trigger->event_name, &trigger->event_name_orig,
2211 				ZBX_FLAG_LLD_TRIGGER_UPDATE_EVENT_NAME, TRIGGER_EVENT_NAME_LEN, error);
2212 	}
2213 
2214 	/* checking duplicated triggers in DB */
2215 
2216 	for (i = 0; i < triggers->values_num; i++)
2217 	{
2218 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
2219 
2220 		if (0 == (trigger->flags & ZBX_FLAG_LLD_TRIGGER_DISCOVERED))
2221 			continue;
2222 
2223 		if (0 != trigger->triggerid)
2224 		{
2225 			zbx_vector_uint64_append(&triggerids, trigger->triggerid);
2226 
2227 			if (SUCCEED != lld_trigger_changed(trigger))
2228 				continue;
2229 		}
2230 
2231 		zbx_vector_str_append(&descriptions, trigger->description);
2232 	}
2233 
2234 	if (0 != descriptions.values_num)
2235 	{
2236 		char			*sql = NULL;
2237 		size_t			sql_alloc = 256, sql_offset = 0;
2238 		DB_RESULT		result;
2239 		DB_ROW			row;
2240 		zbx_vector_ptr_t	db_triggers;
2241 		zbx_lld_trigger_t	*db_trigger;
2242 
2243 		zbx_vector_ptr_create(&db_triggers);
2244 
2245 		zbx_vector_str_sort(&descriptions, ZBX_DEFAULT_STR_COMPARE_FUNC);
2246 		zbx_vector_str_uniq(&descriptions, ZBX_DEFAULT_STR_COMPARE_FUNC);
2247 
2248 		sql = (char *)zbx_malloc(sql, sql_alloc);
2249 
2250 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2251 				"select distinct t.triggerid,t.description,t.expression,t.recovery_expression"
2252 				" from triggers t,functions f,items i"
2253 				" where t.triggerid=f.triggerid"
2254 					" and f.itemid=i.itemid"
2255 					" and i.hostid=" ZBX_FS_UI64
2256 					" and",
2257 				hostid);
2258 		DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.description",
2259 				(const char **)descriptions.values, descriptions.values_num);
2260 
2261 		if (0 != triggerids.values_num)
2262 		{
2263 			zbx_vector_uint64_sort(&triggerids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2264 			zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and not");
2265 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.triggerid",
2266 					triggerids.values, triggerids.values_num);
2267 		}
2268 
2269 		result = DBselect("%s", sql);
2270 
2271 		while (NULL != (row = DBfetch(result)))
2272 		{
2273 			db_trigger = (zbx_lld_trigger_t *)zbx_malloc(NULL, sizeof(zbx_lld_trigger_t));
2274 
2275 			ZBX_STR2UINT64(db_trigger->triggerid, row[0]);
2276 			db_trigger->description = zbx_strdup(NULL, row[1]);
2277 			db_trigger->description_orig = NULL;
2278 			db_trigger->expression = zbx_strdup(NULL, row[2]);
2279 			db_trigger->expression_orig = NULL;
2280 			db_trigger->recovery_expression = zbx_strdup(NULL, row[3]);
2281 			db_trigger->recovery_expression_orig = NULL;
2282 			db_trigger->comments = NULL;
2283 			db_trigger->comments_orig = NULL;
2284 			db_trigger->url = NULL;
2285 			db_trigger->url_orig = NULL;
2286 			db_trigger->correlation_tag = NULL;
2287 			db_trigger->correlation_tag_orig = NULL;
2288 			db_trigger->opdata = NULL;
2289 			db_trigger->opdata_orig = NULL;
2290 			db_trigger->event_name = NULL;
2291 			db_trigger->event_name_orig = NULL;
2292 			db_trigger->flags = ZBX_FLAG_LLD_TRIGGER_UNSET;
2293 
2294 			zbx_vector_ptr_create(&db_trigger->functions);
2295 			zbx_vector_ptr_create(&db_trigger->dependencies);
2296 			zbx_vector_ptr_create(&db_trigger->dependents);
2297 			zbx_vector_ptr_create(&db_trigger->tags);
2298 			zbx_vector_db_tag_ptr_create(&db_trigger->override_tags);
2299 
2300 			zbx_vector_ptr_append(&db_triggers, db_trigger);
2301 		}
2302 		DBfree_result(result);
2303 
2304 		zbx_vector_ptr_sort(&db_triggers, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
2305 
2306 		lld_functions_get(NULL, &db_triggers);
2307 
2308 		for (i = 0; i < db_triggers.values_num; i++)
2309 		{
2310 			db_trigger = (zbx_lld_trigger_t *)db_triggers.values[i];
2311 
2312 			lld_trigger_expression_simplify_and_expand(db_trigger, &db_trigger->expression,
2313 					&db_trigger->functions);
2314 			lld_trigger_expression_simplify_and_expand(db_trigger, &db_trigger->recovery_expression,
2315 					&db_trigger->functions);
2316 
2317 			for (j = 0; j < triggers->values_num; j++)
2318 			{
2319 				trigger = (zbx_lld_trigger_t *)triggers->values[j];
2320 
2321 				if (0 == (trigger->flags & ZBX_FLAG_LLD_TRIGGER_DISCOVERED))
2322 					continue;
2323 
2324 				if (SUCCEED != lld_triggers_equal(trigger, db_trigger))
2325 					continue;
2326 
2327 				*error = zbx_strdcatf(*error, "Cannot %s trigger: trigger \"%s\" already exists.\n",
2328 						(0 != trigger->triggerid ? "update" : "create"), trigger->description);
2329 
2330 				if (0 != trigger->triggerid)
2331 				{
2332 					lld_field_str_rollback(&trigger->description, &trigger->description_orig,
2333 							&trigger->flags, ZBX_FLAG_LLD_TRIGGER_UPDATE_DESCRIPTION);
2334 
2335 					lld_field_str_rollback(&trigger->expression, &trigger->expression_orig,
2336 							&trigger->flags, ZBX_FLAG_LLD_TRIGGER_UPDATE_EXPRESSION);
2337 
2338 					lld_field_str_rollback(&trigger->recovery_expression,
2339 							&trigger->recovery_expression_orig, &trigger->flags,
2340 							ZBX_FLAG_LLD_TRIGGER_UPDATE_RECOVERY_EXPRESSION);
2341 
2342 					for (k = 0; k < trigger->functions.values_num; k++)
2343 					{
2344 						function = (zbx_lld_function_t *)trigger->functions.values[k];
2345 
2346 						if (0 != function->functionid)
2347 						{
2348 							lld_field_uint64_rollback(&function->itemid,
2349 									&function->itemid_orig,
2350 									&function->flags,
2351 									ZBX_FLAG_LLD_FUNCTION_UPDATE_ITEMID);
2352 
2353 							lld_field_str_rollback(&function->function,
2354 									&function->function_orig,
2355 									&function->flags,
2356 									ZBX_FLAG_LLD_FUNCTION_UPDATE_FUNCTION);
2357 
2358 							lld_field_str_rollback(&function->parameter,
2359 									&function->parameter_orig,
2360 									&function->flags,
2361 									ZBX_FLAG_LLD_FUNCTION_UPDATE_PARAMETER);
2362 
2363 							function->flags &= ~ZBX_FLAG_LLD_FUNCTION_DELETE;
2364 						}
2365 						else
2366 							function->flags &= ~ZBX_FLAG_LLD_FUNCTION_DISCOVERED;
2367 					}
2368 				}
2369 				else
2370 					trigger->flags &= ~ZBX_FLAG_LLD_TRIGGER_DISCOVERED;
2371 
2372 				break;	/* only one same trigger can be here */
2373 			}
2374 		}
2375 
2376 		zbx_vector_ptr_clear_ext(&db_triggers, (zbx_clean_func_t)lld_trigger_free);
2377 		zbx_vector_ptr_destroy(&db_triggers);
2378 
2379 		zbx_free(sql);
2380 	}
2381 
2382 	zbx_vector_str_destroy(&descriptions);
2383 	zbx_vector_uint64_destroy(&triggerids);
2384 
2385 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
2386 }
2387 
2388 /******************************************************************************
2389  *                                                                            *
2390  * Function: lld_validate_trigger_tag_field                                   *
2391  *                                                                            *
2392  ******************************************************************************/
2393 static void	lld_validate_trigger_tag_field(zbx_lld_tag_t *tag, const char *field, zbx_uint64_t flag,
2394 		size_t field_len, char **error)
2395 {
2396 	size_t	len;
2397 
2398 	if (0 == (tag->flags & ZBX_FLAG_LLD_TAG_DISCOVERED))
2399 		return;
2400 
2401 	/* only new trigger tags or tags with changed data will be validated */
2402 	if (0 != tag->triggertagid && 0 == (tag->flags & flag))
2403 		return;
2404 
2405 	if (SUCCEED != zbx_is_utf8(field))
2406 	{
2407 		char	*field_utf8;
2408 
2409 		field_utf8 = zbx_strdup(NULL, field);
2410 		zbx_replace_invalid_utf8(field_utf8);
2411 		*error = zbx_strdcatf(*error, "Cannot create trigger tag: value \"%s\" has invalid UTF-8 sequence.\n",
2412 				field_utf8);
2413 		zbx_free(field_utf8);
2414 	}
2415 	else if ((len = zbx_strlen_utf8(field)) > field_len)
2416 		*error = zbx_strdcatf(*error, "Cannot create trigger tag: value \"%s\" is too long.\n", field);
2417 	else if (0 != (flag & ZBX_FLAG_LLD_TAG_UPDATE_TAG) && 0 == len)
2418 		*error = zbx_strdcatf(*error, "Cannot create trigger tag: empty tag name.\n");
2419 	else
2420 		return;
2421 
2422 	if (0 != tag->triggertagid)
2423 		tag->flags = ZBX_FLAG_LLD_TAG_DELETE;
2424 	else
2425 		tag->flags &= ~ZBX_FLAG_LLD_TAG_DISCOVERED;
2426 }
2427 
2428 /******************************************************************************
2429  *                                                                            *
2430  * Function: lld_trigger_tags_validate                                        *
2431  *                                                                            *
2432  * Purpose: validate created or updated trigger tags                          *
2433  *                                                                            *
2434  ******************************************************************************/
2435 static void	lld_trigger_tags_validate(zbx_vector_ptr_t *triggers, char **error)
2436 {
2437 	int			i, j, k;
2438 	zbx_lld_trigger_t	*trigger;
2439 	zbx_lld_tag_t		*tag, *tag_tmp;
2440 
2441 	for (i = 0; i < triggers->values_num; i++)
2442 	{
2443 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
2444 
2445 		if (0 == (trigger->flags & ZBX_FLAG_LLD_TRIGGER_DISCOVERED))
2446 			continue;
2447 
2448 		for (j = 0; j < trigger->tags.values_num; j++)
2449 		{
2450 			tag = (zbx_lld_tag_t *)trigger->tags.values[j];
2451 
2452 			lld_validate_trigger_tag_field(tag, tag->tag, ZBX_FLAG_LLD_TAG_UPDATE_TAG,
2453 					TAG_NAME_LEN, error);
2454 			lld_validate_trigger_tag_field(tag, tag->value, ZBX_FLAG_LLD_TAG_UPDATE_VALUE,
2455 					TAG_VALUE_LEN, error);
2456 
2457 			if (0 == (tag->flags & ZBX_FLAG_LLD_TAG_DISCOVERED))
2458 				continue;
2459 
2460 			/* check for duplicated tag,values pairs */
2461 			for (k = 0; k < j; k++)
2462 			{
2463 				tag_tmp = (zbx_lld_tag_t *)trigger->tags.values[k];
2464 
2465 				if (0 == strcmp(tag->tag, tag_tmp->tag) && 0 == strcmp(tag->value, tag_tmp->value))
2466 				{
2467 					*error = zbx_strdcatf(*error, "Cannot create trigger tag: tag \"%s\","
2468 						"\"%s\" already exists.\n", tag->tag, tag->value);
2469 
2470 					if (0 != tag->triggertagid)
2471 						tag->flags = ZBX_FLAG_LLD_TAG_DELETE;
2472 					else
2473 						tag->flags &= ~ZBX_FLAG_LLD_TAG_DISCOVERED;
2474 				}
2475 			}
2476 
2477 			/* reset trigger discovery flags for new trigger if tag discovery failed */
2478 			if (0 == trigger->triggerid && 0 == (tag->flags & ZBX_FLAG_LLD_TAG_DISCOVERED))
2479 			{
2480 				trigger->flags &= ~ZBX_FLAG_LLD_TRIGGER_DISCOVERED;
2481 				break;
2482 			}
2483 		}
2484 	}
2485 }
2486 
2487 /******************************************************************************
2488  *                                                                            *
2489  * Function: lld_expression_create                                            *
2490  *                                                                            *
2491  * Purpose: transforms the simple trigger expression to the DB format         *
2492  *                                                                            *
2493  * Example:                                                                   *
2494  *                                                                            *
2495  *     "{1} > 5" => "{84756} > 5"                                             *
2496  *       ^            ^                                                       *
2497  *       |            functionid from the database                            *
2498  *       internal function index                                              *
2499  *                                                                            *
2500  ******************************************************************************/
2501 static int	lld_expression_create(const zbx_lld_trigger_t *trigger, char **expression,
2502 		const zbx_vector_ptr_t *functions)
2503 {
2504 	int			i, j, ret = FAIL;
2505 	zbx_uint64_t		function_index;
2506 	zbx_eval_context_t	ctx;
2507 	char			*errmsg = NULL, *new_expression = NULL;
2508 
2509 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() expression:'%s'", __func__, *expression);
2510 
2511 	if ('\0' == **expression)
2512 	{
2513 		ret = SUCCEED;
2514 		goto out;
2515 	}
2516 
2517 	if (SUCCEED != zbx_eval_parse_expression(&ctx, *expression, ZBX_EVAL_TRIGGER_EXPRESSION_LLD, &errmsg))
2518 	{
2519 		const char	*type;
2520 
2521 		type = (*expression == trigger->expression ? "" : " recovery");
2522 		zabbix_log(LOG_LEVEL_DEBUG, "Invalid trigger \"%s\"%s expression: %s", trigger->description, type,
2523 				errmsg);
2524 		zbx_free(errmsg);
2525 
2526 		THIS_SHOULD_NEVER_HAPPEN;
2527 
2528 		goto out;
2529 	}
2530 
2531 	for (i = 0; i < ctx.stack.values_num; i++)
2532 	{
2533 		zbx_eval_token_t	*token = &ctx.stack.values[i];
2534 
2535 		if (ZBX_EVAL_TOKEN_FUNCTIONID != token->type)
2536 			continue;
2537 
2538 		if (SUCCEED != is_uint64_n(ctx.expression + token->loc.l + 1, token->loc.r - token->loc.l - 1,
2539 				&function_index))
2540 		{
2541 			THIS_SHOULD_NEVER_HAPPEN;
2542 			continue;
2543 		}
2544 
2545 		for (j = 0; j < functions->values_num; j++)
2546 		{
2547 			const zbx_lld_function_t	*function = (zbx_lld_function_t *)functions->values[j];
2548 
2549 			if (function->index == function_index)
2550 			{
2551 				zbx_variant_set_ui64(&token->value, function->functionid);
2552 				break;
2553 			}
2554 		}
2555 	}
2556 
2557 	zbx_eval_compose_expression(&ctx, &new_expression);
2558 	zbx_free(*expression);
2559 	*expression = new_expression;
2560 
2561 	zbx_eval_clear(&ctx);
2562 
2563 	ret = SUCCEED;
2564 out:
2565 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() expression:'%s'", __func__, *expression);
2566 
2567 	return ret;
2568 }
2569 
2570 /******************************************************************************
2571  *                                                                            *
2572  * Function: lld_triggers_save                                                *
2573  *                                                                            *
2574  * Purpose: add or update triggers in database based on discovery rule        *
2575  *                                                                            *
2576  * Parameters: hostid            - [IN] parent host id                        *
2577  *             lld_triggers_save - [IN] trigger prototypes                    *
2578  *             triggers          - [IN/OUT] triggers to save                  *
2579  *                                                                            *
2580  * Return value: SUCCEED - if triggers was successfully saved or saving       *
2581  *                         was not necessary                                  *
2582  *               FAIL    - triggers cannot be saved                           *
2583  *                                                                            *
2584  ******************************************************************************/
2585 static int	lld_triggers_save(zbx_uint64_t hostid, const zbx_vector_ptr_t *trigger_prototypes,
2586 		const zbx_vector_ptr_t *triggers)
2587 {
2588 	int					ret = SUCCEED, i, j, new_triggers = 0, upd_triggers = 0, new_functions = 0,
2589 						new_dependencies = 0, new_tags = 0, upd_tags = 0;
2590 	const zbx_lld_trigger_prototype_t	*trigger_prototype;
2591 	zbx_lld_trigger_t			*trigger;
2592 	zbx_lld_function_t			*function;
2593 	zbx_lld_dependency_t			*dependency;
2594 	zbx_lld_tag_t				*tag;
2595 	zbx_vector_ptr_t			upd_functions;	/* the ordered list of functions which will be updated */
2596 	zbx_vector_uint64_t			del_functionids, del_triggerdepids, del_triggertagids, trigger_protoids;
2597 	zbx_uint64_t				triggerid = 0, functionid = 0, triggerdepid = 0, triggerid_up, triggertagid;
2598 	char					*sql = NULL, *function_esc, *parameter_esc;
2599 	size_t					sql_alloc = 8 * ZBX_KIBIBYTE, sql_offset = 0;
2600 	zbx_db_insert_t				db_insert, db_insert_tdiscovery, db_insert_tfunctions, db_insert_tdepends,
2601 						db_insert_ttags;
2602 
2603 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
2604 
2605 	zbx_vector_ptr_create(&upd_functions);
2606 	zbx_vector_uint64_create(&del_functionids);
2607 	zbx_vector_uint64_create(&del_triggerdepids);
2608 	zbx_vector_uint64_create(&del_triggertagids);
2609 	zbx_vector_uint64_create(&trigger_protoids);
2610 
2611 	for (i = 0; i < triggers->values_num; i++)
2612 	{
2613 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
2614 
2615 		if (0 == (trigger->flags & ZBX_FLAG_LLD_TRIGGER_DISCOVERED))
2616 			continue;
2617 
2618 		if (0 == trigger->triggerid)
2619 			new_triggers++;
2620 		else if (0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE))
2621 			upd_triggers++;
2622 
2623 		for (j = 0; j < trigger->functions.values_num; j++)
2624 		{
2625 			function = (zbx_lld_function_t *)trigger->functions.values[j];
2626 
2627 			if (0 != (function->flags & ZBX_FLAG_LLD_FUNCTION_DELETE))
2628 			{
2629 				zbx_vector_uint64_append(&del_functionids, function->functionid);
2630 				continue;
2631 			}
2632 
2633 			if (0 == (function->flags & ZBX_FLAG_LLD_FUNCTION_DISCOVERED))
2634 				continue;
2635 
2636 			if (0 == function->functionid)
2637 				new_functions++;
2638 			else if (0 != (function->flags & ZBX_FLAG_LLD_FUNCTION_UPDATE))
2639 				zbx_vector_ptr_append(&upd_functions, function);
2640 		}
2641 
2642 		for (j = 0; j < trigger->dependencies.values_num; j++)
2643 		{
2644 			dependency = (zbx_lld_dependency_t *)trigger->dependencies.values[j];
2645 
2646 			if (0 != (dependency->flags & ZBX_FLAG_LLD_DEPENDENCY_DELETE))
2647 			{
2648 				zbx_vector_uint64_append(&del_triggerdepids, dependency->triggerdepid);
2649 				continue;
2650 			}
2651 
2652 			if (0 == (dependency->flags & ZBX_FLAG_LLD_DEPENDENCY_DISCOVERED))
2653 				continue;
2654 
2655 			if (0 == dependency->triggerdepid)
2656 				new_dependencies++;
2657 		}
2658 
2659 		for (j = 0; j < trigger->tags.values_num; j++)
2660 		{
2661 			tag = (zbx_lld_tag_t *)trigger->tags.values[j];
2662 
2663 			if (0 != (tag->flags & ZBX_FLAG_LLD_TAG_DELETE))
2664 			{
2665 				zbx_vector_uint64_append(&del_triggertagids, tag->triggertagid);
2666 				continue;
2667 			}
2668 
2669 			if (0 == (tag->flags & ZBX_FLAG_LLD_TAG_DISCOVERED))
2670 				continue;
2671 
2672 			if (0 == tag->triggertagid)
2673 				new_tags++;
2674 			else if (0 != (tag->flags & ZBX_FLAG_LLD_TAG_UPDATE))
2675 				upd_tags++;
2676 		}
2677 	}
2678 
2679 	if (0 == new_triggers && 0 == new_functions && 0 == new_dependencies && 0 == upd_triggers &&
2680 			0 == upd_functions.values_num && 0 == del_functionids.values_num &&
2681 			0 == del_triggerdepids.values_num && 0 == new_tags && 0 == upd_tags &&
2682 			0 == del_triggertagids.values_num)
2683 	{
2684 		goto out;
2685 	}
2686 
2687 	DBbegin();
2688 
2689 	for (i = 0; i < trigger_prototypes->values_num; i++)
2690 	{
2691 		trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[i];
2692 		zbx_vector_uint64_append(&trigger_protoids, trigger_prototype->triggerid);
2693 	}
2694 
2695 	if (SUCCEED != DBlock_hostid(hostid) || SUCCEED != DBlock_triggerids(&trigger_protoids))
2696 	{
2697 		/* the host or trigger prototype was removed while processing lld rule */
2698 		DBrollback();
2699 		ret = FAIL;
2700 		goto out;
2701 	}
2702 
2703 	if (0 != new_triggers)
2704 	{
2705 		triggerid = DBget_maxid_num("triggers", new_triggers);
2706 
2707 		zbx_db_insert_prepare(&db_insert, "triggers", "triggerid", "description", "expression", "priority",
2708 				"status", "comments", "url", "type", "value", "state", "flags", "recovery_mode",
2709 				"recovery_expression", "correlation_mode", "correlation_tag", "manual_close", "opdata",
2710 				"event_name", NULL);
2711 
2712 		zbx_db_insert_prepare(&db_insert_tdiscovery, "trigger_discovery", "triggerid", "parent_triggerid",
2713 				NULL);
2714 	}
2715 
2716 	if (0 != new_functions)
2717 	{
2718 		functionid = DBget_maxid_num("functions", new_functions);
2719 
2720 		zbx_db_insert_prepare(&db_insert_tfunctions, "functions", "functionid", "itemid", "triggerid",
2721 				"name", "parameter", NULL);
2722 	}
2723 
2724 	if (0 != new_dependencies)
2725 	{
2726 		triggerdepid = DBget_maxid_num("trigger_depends", new_dependencies);
2727 
2728 		zbx_db_insert_prepare(&db_insert_tdepends, "trigger_depends", "triggerdepid", "triggerid_down",
2729 				"triggerid_up", NULL);
2730 	}
2731 
2732 	if (0 != new_tags)
2733 	{
2734 		triggertagid = DBget_maxid_num("trigger_tag", new_tags);
2735 
2736 		zbx_db_insert_prepare(&db_insert_ttags, "trigger_tag", "triggertagid", "triggerid", "tag", "value",
2737 				NULL);
2738 	}
2739 
2740 	if (0 != upd_triggers || 0 != upd_functions.values_num || 0 != del_functionids.values_num ||
2741 			0 != del_triggerdepids.values_num || 0 != upd_tags || 0 != del_triggertagids.values_num)
2742 	{
2743 		sql = (char *)zbx_malloc(sql, sql_alloc);
2744 		DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
2745 	}
2746 
2747 	for (i = 0; i < triggers->values_num; i++)
2748 	{
2749 		int	index;
2750 
2751 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
2752 
2753 		if (0 == (trigger->flags & ZBX_FLAG_LLD_TRIGGER_DISCOVERED))
2754 			continue;
2755 
2756 		index = zbx_vector_ptr_bsearch(trigger_prototypes, &trigger->parent_triggerid,
2757 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
2758 
2759 		trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes->values[index];
2760 
2761 		for (j = 0; j < trigger->functions.values_num; j++)
2762 		{
2763 			function = (zbx_lld_function_t *)trigger->functions.values[j];
2764 
2765 			if (0 != (function->flags & ZBX_FLAG_LLD_FUNCTION_DELETE))
2766 				continue;
2767 
2768 			if (0 == (function->flags & ZBX_FLAG_LLD_FUNCTION_DISCOVERED))
2769 				continue;
2770 
2771 			if (0 == function->functionid)
2772 			{
2773 				zbx_db_insert_add_values(&db_insert_tfunctions, functionid, function->itemid,
2774 						(0 == trigger->triggerid ? triggerid : trigger->triggerid),
2775 						function->function, function->parameter);
2776 
2777 				function->functionid = functionid++;
2778 			}
2779 		}
2780 
2781 		if (0 == trigger->triggerid || 0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE_EXPRESSION))
2782 		{
2783 			if (FAIL == lld_expression_create(trigger, &trigger->expression, &trigger->functions))
2784 			{
2785 				/* further updates will fail, so there is unnecessary overhead, */
2786 				/* but lld_expression_create() can fail only because of bugs,   */
2787 				/* so better to leave unoptimized handling of 'impossible'      */
2788 				/* errors than unnecessary complicate code                      */
2789 				ret = FAIL;
2790 				goto cleanup;
2791 			}
2792 		}
2793 
2794 		if (0 == trigger->triggerid || 0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE_RECOVERY_EXPRESSION))
2795 		{
2796 			if (FAIL == lld_expression_create(trigger, &trigger->recovery_expression, &trigger->functions))
2797 			{
2798 				ret = FAIL;
2799 				goto cleanup;
2800 			}
2801 		}
2802 
2803 		if (0 == trigger->triggerid)
2804 		{
2805 			zbx_db_insert_add_values(&db_insert, triggerid, trigger->description, trigger->expression,
2806 					(int)trigger->priority, (int)trigger->status,
2807 					trigger->comments, trigger->url, (int)trigger_prototype->type,
2808 					(int)TRIGGER_VALUE_OK, (int)TRIGGER_STATE_NORMAL,
2809 					(int)ZBX_FLAG_DISCOVERY_CREATED, (int)trigger_prototype->recovery_mode,
2810 					trigger->recovery_expression, (int)trigger_prototype->correlation_mode,
2811 					trigger->correlation_tag, (int)trigger_prototype->manual_close,
2812 					trigger->opdata, trigger->event_name);
2813 
2814 			zbx_db_insert_add_values(&db_insert_tdiscovery, triggerid, trigger->parent_triggerid);
2815 
2816 			trigger->triggerid = triggerid++;
2817 		}
2818 		else if (0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE))
2819 		{
2820 			const char	*d = "";
2821 			char		*description_esc, *expression_esc, *comments_esc, *url_esc, *value_esc,
2822 					*opdata_esc, *event_name_esc;
2823 
2824 			zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update triggers set ");
2825 
2826 			if (0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE_DESCRIPTION))
2827 			{
2828 				description_esc = DBdyn_escape_string(trigger->description);
2829 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "description='%s'",
2830 						description_esc);
2831 				zbx_free(description_esc);
2832 				d = ",";
2833 			}
2834 
2835 			if (0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE_EXPRESSION))
2836 			{
2837 				expression_esc = DBdyn_escape_string(trigger->expression);
2838 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sexpression='%s'", d,
2839 						expression_esc);
2840 				zbx_free(expression_esc);
2841 				d = ",";
2842 			}
2843 
2844 			if (0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE_RECOVERY_EXPRESSION))
2845 			{
2846 				expression_esc = DBdyn_escape_string(trigger->recovery_expression);
2847 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%srecovery_expression='%s'", d,
2848 						expression_esc);
2849 				zbx_free(expression_esc);
2850 				d = ",";
2851 			}
2852 
2853 			if (0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE_RECOVERY_MODE))
2854 			{
2855 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%srecovery_mode=%d", d,
2856 						(int)trigger_prototype->recovery_mode);
2857 				d = ",";
2858 			}
2859 
2860 			if (0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE_TYPE))
2861 			{
2862 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%stype=%d", d,
2863 						(int)trigger_prototype->type);
2864 				d = ",";
2865 			}
2866 
2867 			if (0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE_PRIORITY))
2868 			{
2869 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%spriority=%d", d,
2870 						(int)trigger->priority);
2871 				d = ",";
2872 			}
2873 
2874 			if (0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE_COMMENTS))
2875 			{
2876 				comments_esc = DBdyn_escape_string(trigger->comments);
2877 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%scomments='%s'", d, comments_esc);
2878 				zbx_free(comments_esc);
2879 				d = ",";
2880 			}
2881 
2882 			if (0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE_URL))
2883 			{
2884 				url_esc = DBdyn_escape_string(trigger->url);
2885 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%surl='%s'", d, url_esc);
2886 				zbx_free(url_esc);
2887 				d = ",";
2888 			}
2889 
2890 			if (0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE_CORRELATION_MODE))
2891 			{
2892 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%scorrelation_mode=%d", d,
2893 						(int)trigger_prototype->correlation_mode);
2894 				d = ",";
2895 			}
2896 
2897 			if (0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE_CORRELATION_TAG))
2898 			{
2899 				value_esc = DBdyn_escape_string(trigger->correlation_tag);
2900 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%scorrelation_tag='%s'", d,
2901 						value_esc);
2902 				zbx_free(value_esc);
2903 				d = ",";
2904 			}
2905 
2906 			if (0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE_MANUAL_CLOSE))
2907 			{
2908 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%smanual_close=%d", d,
2909 						(int)trigger_prototype->manual_close);
2910 				d = ",";
2911 			}
2912 
2913 			if (0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE_OPDATA))
2914 			{
2915 				opdata_esc = DBdyn_escape_string(trigger->opdata);
2916 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sopdata='%s'", d, opdata_esc);
2917 				zbx_free(opdata_esc);
2918 				d = ",";
2919 			}
2920 
2921 			if (0 != (trigger->flags & ZBX_FLAG_LLD_TRIGGER_UPDATE_EVENT_NAME))
2922 			{
2923 				event_name_esc = DBdyn_escape_string(trigger->event_name);
2924 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sevent_name='%s'", d, event_name_esc);
2925 				zbx_free(event_name_esc);
2926 			}
2927 
2928 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2929 					" where triggerid=" ZBX_FS_UI64 ";\n", trigger->triggerid);
2930 		}
2931 	}
2932 
2933 	for (i = 0; i < triggers->values_num; i++)
2934 	{
2935 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
2936 
2937 		if (0 == (trigger->flags & ZBX_FLAG_LLD_TRIGGER_DISCOVERED))
2938 			continue;
2939 
2940 		for (j = 0; j < trigger->dependencies.values_num; j++)
2941 		{
2942 			dependency = (zbx_lld_dependency_t *)trigger->dependencies.values[j];
2943 
2944 			if (0 != (dependency->flags & ZBX_FLAG_LLD_DEPENDENCY_DELETE))
2945 				continue;
2946 
2947 			if (0 == (dependency->flags & ZBX_FLAG_LLD_DEPENDENCY_DISCOVERED))
2948 				continue;
2949 
2950 			if (0 == dependency->triggerdepid)
2951 			{
2952 				triggerid_up = (NULL == dependency->trigger_up ? dependency->triggerid_up :
2953 						dependency->trigger_up->triggerid);
2954 
2955 				zbx_db_insert_add_values(&db_insert_tdepends, triggerdepid, trigger->triggerid,
2956 						triggerid_up);
2957 
2958 				dependency->triggerdepid = triggerdepid++;
2959 			}
2960 		}
2961 	}
2962 
2963 	/* create/update trigger tags */
2964 	for (i = 0; i < triggers->values_num; i++)
2965 	{
2966 		trigger = (zbx_lld_trigger_t *)triggers->values[i];
2967 
2968 		if (0 == (trigger->flags & ZBX_FLAG_LLD_TRIGGER_DISCOVERED))
2969 			continue;
2970 
2971 		for (j = 0; j < trigger->tags.values_num; j++)
2972 		{
2973 			char	*value_esc;
2974 
2975 			tag = (zbx_lld_tag_t *)trigger->tags.values[j];
2976 
2977 			if (0 != (tag->flags & ZBX_FLAG_LLD_TAG_DELETE))
2978 				continue;
2979 
2980 			if (0 == (tag->flags & ZBX_FLAG_LLD_TAG_DISCOVERED))
2981 				continue;
2982 
2983 			if (0 == tag->triggertagid)
2984 			{
2985 				tag->triggertagid = triggertagid++;
2986 				zbx_db_insert_add_values(&db_insert_ttags, tag->triggertagid, trigger->triggerid,
2987 						tag->tag, tag->value);
2988 			}
2989 			else if (0 != (tag->flags & ZBX_FLAG_LLD_TAG_UPDATE))
2990 			{
2991 				const char	*d = "";
2992 
2993 				zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update trigger_tag set ");
2994 
2995 				if (0 != (tag->flags & ZBX_FLAG_LLD_TAG_UPDATE_TAG))
2996 				{
2997 					value_esc = DBdyn_escape_string(tag->tag);
2998 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "tag='%s'", value_esc);
2999 					zbx_free(value_esc);
3000 					d = ",";
3001 				}
3002 
3003 				if (0 != (tag->flags & ZBX_FLAG_LLD_TAG_UPDATE_VALUE))
3004 				{
3005 					value_esc = DBdyn_escape_string(tag->value);
3006 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%svalue='%s'", d, value_esc);
3007 					zbx_free(value_esc);
3008 				}
3009 
3010 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3011 						" where triggertagid=" ZBX_FS_UI64 ";\n", tag->triggertagid);
3012 			}
3013 		}
3014 	}
3015 
3016 	zbx_vector_ptr_sort(&upd_functions, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
3017 
3018 	for (i = 0; i < upd_functions.values_num; i++)
3019 	{
3020 		const char	*d = "";
3021 
3022 		function = (zbx_lld_function_t *)upd_functions.values[i];
3023 
3024 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update functions set ");
3025 
3026 		if (0 != (function->flags & ZBX_FLAG_LLD_FUNCTION_UPDATE_ITEMID))
3027 		{
3028 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "itemid=" ZBX_FS_UI64,
3029 					function->itemid);
3030 			d = ",";
3031 		}
3032 
3033 		if (0 != (function->flags & ZBX_FLAG_LLD_FUNCTION_UPDATE_FUNCTION))
3034 		{
3035 			function_esc = DBdyn_escape_string(function->function);
3036 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sname='%s'", d,
3037 					function_esc);
3038 			zbx_free(function_esc);
3039 			d = ",";
3040 		}
3041 
3042 		if (0 != (function->flags & ZBX_FLAG_LLD_FUNCTION_UPDATE_PARAMETER))
3043 		{
3044 			parameter_esc = DBdyn_escape_string(function->parameter);
3045 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sparameter='%s'", d,
3046 					parameter_esc);
3047 			zbx_free(parameter_esc);
3048 		}
3049 
3050 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3051 				" where functionid=" ZBX_FS_UI64 ";\n", function->functionid);
3052 	}
3053 
3054 	if (0 != del_functionids.values_num)
3055 	{
3056 		zbx_vector_uint64_sort(&del_functionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3057 
3058 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from functions where");
3059 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "functionid",
3060 				del_functionids.values, del_functionids.values_num);
3061 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
3062 	}
3063 
3064 	if (0 != del_triggerdepids.values_num)
3065 	{
3066 		zbx_vector_uint64_sort(&del_triggerdepids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3067 
3068 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from trigger_depends where");
3069 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "triggerdepid",
3070 				del_triggerdepids.values, del_triggerdepids.values_num);
3071 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
3072 	}
3073 
3074 	if (0 != del_triggertagids.values_num)
3075 	{
3076 		zbx_vector_uint64_sort(&del_triggertagids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3077 
3078 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from trigger_tag where");
3079 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "triggertagid",
3080 				del_triggertagids.values, del_triggertagids.values_num);
3081 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
3082 	}
3083 
3084 	if (0 != upd_triggers || 0 != upd_functions.values_num || 0 != del_functionids.values_num ||
3085 			0 != del_triggerdepids.values_num || 0 != upd_tags || 0 != del_triggertagids.values_num)
3086 	{
3087 		DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
3088 		DBexecute("%s", sql);
3089 	}
3090 cleanup:
3091 	zbx_free(sql);
3092 
3093 	if (0 != new_triggers)
3094 	{
3095 		if (ret == SUCCEED)
3096 			zbx_db_insert_execute(&db_insert);
3097 		zbx_db_insert_clean(&db_insert);
3098 
3099 		if (ret == SUCCEED)
3100 			zbx_db_insert_execute(&db_insert_tdiscovery);
3101 		zbx_db_insert_clean(&db_insert_tdiscovery);
3102 	}
3103 
3104 	if (0 != new_functions)
3105 	{
3106 		if (ret == SUCCEED)
3107 			zbx_db_insert_execute(&db_insert_tfunctions);
3108 		zbx_db_insert_clean(&db_insert_tfunctions);
3109 	}
3110 
3111 	if (0 != new_dependencies)
3112 	{
3113 		if (ret == SUCCEED)
3114 			zbx_db_insert_execute(&db_insert_tdepends);
3115 		zbx_db_insert_clean(&db_insert_tdepends);
3116 	}
3117 
3118 	if (0 != new_tags)
3119 	{
3120 		if (ret == SUCCEED)
3121 			zbx_db_insert_execute(&db_insert_ttags);
3122 		zbx_db_insert_clean(&db_insert_ttags);
3123 	}
3124 
3125 	if (ret == SUCCEED)
3126 		DBcommit();
3127 	else
3128 		DBrollback();
3129 out:
3130 	zbx_vector_uint64_destroy(&trigger_protoids);
3131 	zbx_vector_uint64_destroy(&del_triggertagids);
3132 	zbx_vector_uint64_destroy(&del_triggerdepids);
3133 	zbx_vector_uint64_destroy(&del_functionids);
3134 	zbx_vector_ptr_destroy(&upd_functions);
3135 
3136 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3137 
3138 	return ret;
3139 }
3140 
3141 /* hash/comparison functions to support cache/vector lookups by trigger reference */
3142 static zbx_hash_t	zbx_lld_trigger_ref_hash_func(const void *data)
3143 {
3144 	zbx_hash_t			hash;
3145 	const zbx_lld_trigger_node_t	*trigger_node = (const zbx_lld_trigger_node_t *)data;
3146 	void				*ptr = NULL;
3147 
3148 	hash = ZBX_DEFAULT_UINT64_HASH_ALGO(&trigger_node->trigger_ref.triggerid,
3149 			sizeof(trigger_node->trigger_ref.triggerid), ZBX_DEFAULT_HASH_SEED);
3150 
3151 	if (0 == trigger_node->trigger_ref.triggerid)
3152 		ptr = trigger_node->trigger_ref.trigger;
3153 
3154 	return ZBX_DEFAULT_PTR_HASH_ALGO(&ptr, sizeof(trigger_node->trigger_ref.trigger), hash);
3155 }
3156 
3157 static int	zbx_lld_trigger_ref_compare_func(const void *d1, const void *d2)
3158 {
3159 	const zbx_lld_trigger_node_t	*n1 = (const zbx_lld_trigger_node_t *)d1;
3160 	const zbx_lld_trigger_node_t	*n2 = (const zbx_lld_trigger_node_t *)d2;
3161 
3162 	ZBX_RETURN_IF_NOT_EQUAL(n1->trigger_ref.triggerid, n2->trigger_ref.triggerid);
3163 
3164 	/* Don't check pointer if id matches. If the reference was loaded from database it will not have pointer. */
3165 	if (0 != n1->trigger_ref.triggerid)
3166 		return 0;
3167 
3168 	ZBX_RETURN_IF_NOT_EQUAL(n1->trigger_ref.trigger, n2->trigger_ref.trigger);
3169 
3170 	return 0;
3171 }
3172 
3173 /* comparison function to determine trigger dependency validation order */
3174 static int	zbx_lld_trigger_node_compare_func(const void *d1, const void *d2)
3175 {
3176 	const zbx_lld_trigger_node_t	*n1 = *(const zbx_lld_trigger_node_t **)d1;
3177 	const zbx_lld_trigger_node_t	*n2 = *(const zbx_lld_trigger_node_t **)d2;
3178 
3179 	/* sort in ascending order, but ensure that existing triggers are first */
3180 	if (0 != n1->trigger_ref.triggerid && 0 == n2->trigger_ref.triggerid)
3181 		return -1;
3182 
3183 	/* give priority to nodes with less parents */
3184 	ZBX_RETURN_IF_NOT_EQUAL(n1->parents, n2->parents);
3185 
3186 	/* compare ids */
3187 	ZBX_RETURN_IF_NOT_EQUAL(n1->trigger_ref.triggerid, n2->trigger_ref.triggerid);
3188 
3189 	/* Don't check pointer if id matches. If the reference was loaded from database it will not have pointer. */
3190 	if (0 != n1->trigger_ref.triggerid)
3191 		return 0;
3192 
3193 	ZBX_RETURN_IF_NOT_EQUAL(n1->trigger_ref.trigger, n2->trigger_ref.trigger);
3194 
3195 	return 0;
3196 }
3197 
3198 /******************************************************************************
3199  *                                                                            *
3200  * Function: lld_trigger_cache_append                                         *
3201  *                                                                            *
3202  * Purpose: adds a node to trigger cache                                      *
3203  *                                                                            *
3204  * Parameters: cache     - [IN] the trigger cache                             *
3205  *             triggerid - [IN] the trigger id                                *
3206  *             trigger   - [IN] the trigger data for new triggers             *
3207  *                                                                            *
3208  * Return value: the added node                                               *
3209  *                                                                            *
3210  ******************************************************************************/
3211 static zbx_lld_trigger_node_t	*lld_trigger_cache_append(zbx_hashset_t *cache, zbx_uint64_t triggerid,
3212 		zbx_lld_trigger_t *trigger)
3213 {
3214 	zbx_lld_trigger_node_t	node_local;
3215 
3216 	node_local.trigger_ref.triggerid = triggerid;
3217 	node_local.trigger_ref.trigger = trigger;
3218 	node_local.trigger_ref.flags = 0;
3219 	node_local.iter_num = 0;
3220 	node_local.parents = 0;
3221 
3222 	zbx_vector_ptr_create(&node_local.dependencies);
3223 
3224 	return (zbx_lld_trigger_node_t *)zbx_hashset_insert(cache, &node_local, sizeof(node_local));
3225 }
3226 
3227 /******************************************************************************
3228  *                                                                            *
3229  * Function: lld_trigger_cache_add_trigger_node                               *
3230  *                                                                            *
3231  * Purpose: add trigger and all triggers related to it to trigger dependency  *
3232  *          validation cache.                                                 *
3233  *                                                                            *
3234  * Parameters: cache           - [IN] the trigger cache                       *
3235  *             trigger         - [IN] the trigger to add                      *
3236  *             triggerids_up   - [OUT] identifiers of generic trigger         *
3237  *                                     dependents                             *
3238  *             triggerids_down - [OUT] identifiers of generic trigger         *
3239  *                                     dependencies                           *
3240  *                                                                            *
3241  ******************************************************************************/
3242 static void	lld_trigger_cache_add_trigger_node(zbx_hashset_t *cache, zbx_lld_trigger_t *trigger,
3243 		zbx_vector_uint64_t *triggerids_up, zbx_vector_uint64_t *triggerids_down)
3244 {
3245 	zbx_lld_trigger_ref_t	*trigger_ref;
3246 	zbx_lld_trigger_node_t	*trigger_node, trigger_node_local;
3247 	zbx_lld_dependency_t	*dependency;
3248 	int			i;
3249 
3250 	trigger_node_local.trigger_ref.triggerid = trigger->triggerid;
3251 	trigger_node_local.trigger_ref.trigger = trigger;
3252 
3253 	if (NULL != zbx_hashset_search(cache, &trigger_node_local))
3254 		return;
3255 
3256 	trigger_node = lld_trigger_cache_append(cache, trigger->triggerid, trigger);
3257 
3258 	for (i = 0; i < trigger->dependencies.values_num; i++)
3259 	{
3260 		dependency = (zbx_lld_dependency_t *)trigger->dependencies.values[i];
3261 
3262 		if (0 == (dependency->flags & ZBX_FLAG_LLD_DEPENDENCY_DISCOVERED))
3263 			continue;
3264 
3265 		trigger_ref = (zbx_lld_trigger_ref_t *)zbx_malloc(NULL, sizeof(zbx_lld_trigger_ref_t));
3266 
3267 		trigger_ref->triggerid = dependency->triggerid_up;
3268 		trigger_ref->trigger = dependency->trigger_up;
3269 		trigger_ref->flags = (0 == dependency->triggerdepid ? ZBX_LLD_TRIGGER_DEPENDENCY_NEW :
3270 				ZBX_LLD_TRIGGER_DEPENDENCY_NORMAL);
3271 
3272 		zbx_vector_ptr_append(&trigger_node->dependencies, trigger_ref);
3273 
3274 		if (NULL == trigger_ref->trigger)
3275 		{
3276 			trigger_node_local.trigger_ref.triggerid = trigger_ref->triggerid;
3277 			trigger_node_local.trigger_ref.trigger = NULL;
3278 
3279 			if (NULL == zbx_hashset_search(cache, &trigger_node_local))
3280 			{
3281 				zbx_vector_uint64_append(triggerids_up, trigger_ref->triggerid);
3282 				zbx_vector_uint64_append(triggerids_down, trigger_ref->triggerid);
3283 
3284 				lld_trigger_cache_append(cache, trigger_ref->triggerid, NULL);
3285 			}
3286 		}
3287 	}
3288 
3289 	if (0 != trigger->triggerid)
3290 		zbx_vector_uint64_append(triggerids_up, trigger->triggerid);
3291 
3292 	for (i = 0; i < trigger->dependents.values_num; i++)
3293 	{
3294 		lld_trigger_cache_add_trigger_node(cache, (zbx_lld_trigger_t *)trigger->dependents.values[i], triggerids_up,
3295 				triggerids_down);
3296 	}
3297 
3298 	for (i = 0; i < trigger->dependencies.values_num; i++)
3299 	{
3300 		dependency = (zbx_lld_dependency_t *)trigger->dependencies.values[i];
3301 
3302 		if (NULL != dependency->trigger_up)
3303 		{
3304 			lld_trigger_cache_add_trigger_node(cache, dependency->trigger_up, triggerids_up,
3305 					triggerids_down);
3306 		}
3307 	}
3308 }
3309 
3310 /******************************************************************************
3311  *                                                                            *
3312  * Function: lld_trigger_cache_init                                           *
3313  *                                                                            *
3314  * Purpose: initializes trigger cache used to perform trigger dependency      *
3315  *          validation                                                        *
3316  *                                                                            *
3317  * Parameters: cache    - [IN] the trigger cache                              *
3318  *             triggers - [IN] the discovered triggers                        *
3319  *                                                                            *
3320  * Comments: Triggers with new dependencies and.all triggers related to them  *
3321  *           are added to cache.                                              *
3322  *                                                                            *
3323  ******************************************************************************/
3324 static void	lld_trigger_cache_init(zbx_hashset_t *cache, zbx_vector_ptr_t *triggers)
3325 {
3326 	zbx_vector_uint64_t	triggerids_up, triggerids_down;
3327 	int			i, j;
3328 	char			*sql = NULL;
3329 	size_t			sql_alloc = 0, sql_offset;
3330 	DB_RESULT		result;
3331 	DB_ROW			row;
3332 	zbx_lld_trigger_ref_t	*trigger_ref;
3333 	zbx_lld_trigger_node_t	*trigger_node, trigger_node_local;
3334 
3335 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3336 
3337 	zbx_hashset_create(cache, triggers->values_num, zbx_lld_trigger_ref_hash_func,
3338 			zbx_lld_trigger_ref_compare_func);
3339 
3340 	zbx_vector_uint64_create(&triggerids_down);
3341 	zbx_vector_uint64_create(&triggerids_up);
3342 
3343 	/* add all triggers with new dependencies to trigger cache */
3344 	for (i = 0; i < triggers->values_num; i++)
3345 	{
3346 		zbx_lld_trigger_t	*trigger = (zbx_lld_trigger_t *)triggers->values[i];
3347 
3348 		for (j = 0; j < trigger->dependencies.values_num; j++)
3349 		{
3350 			zbx_lld_dependency_t	*dependency = (zbx_lld_dependency_t *)trigger->dependencies.values[j];
3351 
3352 			if (0 == dependency->triggerdepid)
3353 				break;
3354 		}
3355 
3356 		if (j != trigger->dependencies.values_num)
3357 			lld_trigger_cache_add_trigger_node(cache, trigger, &triggerids_up, &triggerids_down);
3358 	}
3359 
3360 	/* keep trying to load generic dependents/dependencies until there are nothing to load */
3361 	while (0 != triggerids_up.values_num || 0 != triggerids_down.values_num)
3362 	{
3363 		/* load dependents */
3364 		if (0 != triggerids_down.values_num)
3365 		{
3366 			sql_offset = 0;
3367 			zbx_vector_uint64_sort(&triggerids_down, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3368 			zbx_vector_uint64_uniq(&triggerids_down, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3369 
3370 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3371 					"select td.triggerid_down,td.triggerid_up"
3372 					" from trigger_depends td"
3373 						" left join triggers t"
3374 							" on td.triggerid_up=t.triggerid"
3375 					" where t.flags<>%d"
3376 						" and", ZBX_FLAG_DISCOVERY_PROTOTYPE);
3377 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "td.triggerid_down",
3378 					triggerids_down.values, triggerids_down.values_num);
3379 
3380 			zbx_vector_uint64_clear(&triggerids_down);
3381 
3382 			result = DBselect("%s", sql);
3383 
3384 			while (NULL != (row = DBfetch(result)))
3385 			{
3386 				int			new_node = 0;
3387 				zbx_lld_trigger_node_t	*trigger_node_up;
3388 
3389 				ZBX_STR2UINT64(trigger_node_local.trigger_ref.triggerid, row[1]);
3390 
3391 				if (NULL == (trigger_node_up = (zbx_lld_trigger_node_t *)zbx_hashset_search(cache, &trigger_node_local)))
3392 				{
3393 					trigger_node_up = lld_trigger_cache_append(cache,
3394 							trigger_node_local.trigger_ref.triggerid, NULL);
3395 					new_node = 1;
3396 				}
3397 
3398 				ZBX_STR2UINT64(trigger_node_local.trigger_ref.triggerid, row[0]);
3399 
3400 				if (NULL == (trigger_node = (zbx_lld_trigger_node_t *)zbx_hashset_search(cache, &trigger_node_local)))
3401 				{
3402 					THIS_SHOULD_NEVER_HAPPEN;
3403 					continue;
3404 				}
3405 
3406 				/* check if the dependency is not already registered in cache */
3407 				for (i = 0; i < trigger_node->dependencies.values_num; i++)
3408 				{
3409 					trigger_ref = (zbx_lld_trigger_ref_t *)trigger_node->dependencies.values[i];
3410 
3411 					/* references to generic triggers will always have valid id value */
3412 					if (trigger_ref->triggerid == trigger_node_up->trigger_ref.triggerid)
3413 						break;
3414 				}
3415 
3416 				/* if the dependency was not found - add it */
3417 				if (i == trigger_node->dependencies.values_num)
3418 				{
3419 					trigger_ref = (zbx_lld_trigger_ref_t *)zbx_malloc(NULL,
3420 							sizeof(zbx_lld_trigger_ref_t));
3421 
3422 					trigger_ref->triggerid = trigger_node_up->trigger_ref.triggerid;
3423 					trigger_ref->trigger = NULL;
3424 					trigger_ref->flags = ZBX_LLD_TRIGGER_DEPENDENCY_NORMAL;
3425 
3426 					zbx_vector_ptr_append(&trigger_node->dependencies, trigger_ref);
3427 
3428 					trigger_node_up->parents++;
3429 				}
3430 
3431 				if (1 == new_node)
3432 				{
3433 					/* if the trigger was added to cache, we must check its dependencies */
3434 					zbx_vector_uint64_append(&triggerids_up,
3435 							trigger_node_up->trigger_ref.triggerid);
3436 					zbx_vector_uint64_append(&triggerids_down,
3437 							trigger_node_up->trigger_ref.triggerid);
3438 				}
3439 			}
3440 
3441 			DBfree_result(result);
3442 		}
3443 
3444 		/* load dependencies */
3445 		if (0 != triggerids_up.values_num)
3446 		{
3447 			sql_offset = 0;
3448 			zbx_vector_uint64_sort(&triggerids_up, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3449 			zbx_vector_uint64_uniq(&triggerids_up, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3450 
3451 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3452 					"select td.triggerid_down"
3453 					" from trigger_depends td"
3454 						" left join triggers t"
3455 							" on t.triggerid=td.triggerid_down"
3456 					" where t.flags<>%d"
3457 						" and", ZBX_FLAG_DISCOVERY_PROTOTYPE);
3458 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "td.triggerid_up", triggerids_up.values,
3459 					triggerids_up.values_num);
3460 
3461 			zbx_vector_uint64_clear(&triggerids_up);
3462 
3463 			result = DBselect("%s", sql);
3464 
3465 			while (NULL != (row = DBfetch(result)))
3466 			{
3467 				ZBX_STR2UINT64(trigger_node_local.trigger_ref.triggerid, row[0]);
3468 
3469 				if (NULL != zbx_hashset_search(cache, &trigger_node_local))
3470 					continue;
3471 
3472 				lld_trigger_cache_append(cache, trigger_node_local.trigger_ref.triggerid, NULL);
3473 
3474 				zbx_vector_uint64_append(&triggerids_up, trigger_node_local.trigger_ref.triggerid);
3475 				zbx_vector_uint64_append(&triggerids_down, trigger_node_local.trigger_ref.triggerid);
3476 			}
3477 
3478 			DBfree_result(result);
3479 		}
3480 
3481 	}
3482 
3483 	zbx_free(sql);
3484 
3485 	zbx_vector_uint64_destroy(&triggerids_up);
3486 	zbx_vector_uint64_destroy(&triggerids_down);
3487 
3488 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3489 }
3490 
3491 /******************************************************************************
3492  *                                                                            *
3493  * Function: zbx_trigger_cache_clean                                          *
3494  *                                                                            *
3495  * Purpose: releases resources allocated by trigger cache                     *
3496  *          validation                                                        *
3497  *                                                                            *
3498  * Parameters: cache - [IN] the trigger cache                                 *
3499  *                                                                            *
3500  ******************************************************************************/
3501 static void	zbx_trigger_cache_clean(zbx_hashset_t *cache)
3502 {
3503 	zbx_hashset_iter_t	iter;
3504 	zbx_lld_trigger_node_t	*trigger_node;
3505 
3506 	zbx_hashset_iter_reset(cache, &iter);
3507 	while (NULL != (trigger_node = (zbx_lld_trigger_node_t *)zbx_hashset_iter_next(&iter)))
3508 	{
3509 		zbx_vector_ptr_clear_ext(&trigger_node->dependencies, zbx_ptr_free);
3510 		zbx_vector_ptr_destroy(&trigger_node->dependencies);
3511 	}
3512 
3513 	zbx_hashset_destroy(cache);
3514 }
3515 
3516 /******************************************************************************
3517  *                                                                            *
3518  * Function: lld_trigger_dependency_delete                                    *
3519  *                                                                            *
3520  * Purpose: removes trigger dependency                                        *
3521  *                                                                            *
3522  * Parameters: from  - [IN] the reference to dependent trigger                *
3523  *             to    - [IN] the reference to trigger the from depends on      *
3524  *             error - [OUT] the error message                                *
3525  *                                                                            *
3526  * Comments: If possible (the dependency loop was introduced by discovered    *
3527  *           dependencies) the last dependency in the loop will be removed.   *
3528  *           Otherwise (the triggers in database already had dependency loop) *
3529  *           the last dependency in the loop will be marked as removed,       *
3530  *           however the dependency in database will be left intact.          *
3531  *                                                                            *
3532  ******************************************************************************/
3533 static void	lld_trigger_dependency_delete(zbx_lld_trigger_ref_t *from, zbx_lld_trigger_ref_t *to, char **error)
3534 {
3535 	zbx_lld_trigger_t	*trigger;
3536 	int			i;
3537 	char			*trigger_desc;
3538 
3539 	if (ZBX_LLD_TRIGGER_DEPENDENCY_NORMAL == to->flags)
3540 	{
3541 		/* When old dependency loop has been detected mark it as deleted to avoid   */
3542 		/* infinite recursion during dependency validation, but don't really delete */
3543 		/* it because only new dependencies can be deleted.                         */
3544 
3545 		/* in old dependency loop there are no new triggers, so all involved */
3546 		/* triggers have valid identifiers                                   */
3547 		zabbix_log(LOG_LEVEL_CRIT, "existing recursive dependency loop detected for trigger \""
3548 				ZBX_FS_UI64 "\"", to->triggerid);
3549 		return;
3550 	}
3551 
3552 	trigger = from->trigger;
3553 
3554 	/* remove the dependency */
3555 	for (i = 0; i < trigger->dependencies.values_num; i++)
3556 	{
3557 		zbx_lld_dependency_t	*dependency = (zbx_lld_dependency_t *)trigger->dependencies.values[i];
3558 
3559 		if ((NULL != dependency->trigger_up && dependency->trigger_up == to->trigger) ||
3560 				(0 != dependency->triggerid_up && dependency->triggerid_up == to->triggerid))
3561 		{
3562 			zbx_free(dependency);
3563 			zbx_vector_ptr_remove(&trigger->dependencies, i);
3564 
3565 			break;
3566 		}
3567 	}
3568 
3569 	if (0 != from->triggerid)
3570 		trigger_desc = zbx_dsprintf(NULL, ZBX_FS_UI64, from->triggerid);
3571 	else
3572 		trigger_desc = zbx_strdup(NULL, from->trigger->description);
3573 
3574 	*error = zbx_strdcatf(*error, "Cannot create all trigger \"%s\" dependencies:"
3575 			" recursion too deep.\n", trigger_desc);
3576 
3577 	zbx_free(trigger_desc);
3578 }
3579 
3580 /******************************************************************************
3581  *                                                                            *
3582  * Function: lld_trigger_dependencies_iter                                    *
3583  *                                                                            *
3584  * Purpose: iterates through trigger dependencies to find dependency loops    *
3585  *                                                                            *
3586  * Parameters: cache         - [IN] the trigger cache                         *
3587  *             triggers      - [IN] the discovered triggers                   *
3588  *             trigger_node  - [IN] the trigger to check                      *
3589  *             iter          - [IN] the dependency iterator                   *
3590  *             level         - [IN] the dependency level                      *
3591  *             error         - [OUT] the error message                        *
3592  *                                                                            *
3593  * Return value: SUCCEED - the trigger's dependency chain in valid            *
3594  *               FAIL    - a dependency loop was detected                     *
3595  *                                                                            *
3596  * Comments: If the validation fails the offending dependency is removed.     *
3597  *                                                                            *
3598  ******************************************************************************/
3599 static int	lld_trigger_dependencies_iter(zbx_hashset_t *cache, zbx_vector_ptr_t *triggers,
3600 		zbx_lld_trigger_node_t *trigger_node, zbx_lld_trigger_node_iter_t *iter, int level, char **error)
3601 {
3602 	int				i;
3603 	zbx_lld_trigger_ref_t		*trigger_ref;
3604 	zbx_lld_trigger_node_t		*trigger_node_up;
3605 	zbx_lld_trigger_node_iter_t	child_iter, *piter;
3606 
3607 	if (trigger_node->iter_num == iter->iter_num || ZBX_TRIGGER_DEPENDENCY_LEVELS_MAX < level)
3608 	{
3609 		/* dependency loop detected, resolve it by deleting corresponding dependency */
3610 		lld_trigger_dependency_delete(iter->ref_from, iter->ref_to, error);
3611 
3612 		/* mark the dependency as removed */
3613 		iter->ref_to->flags = ZBX_LLD_TRIGGER_DEPENDENCY_DELETE;
3614 
3615 		return FAIL;
3616 	}
3617 
3618 	trigger_node->iter_num = iter->iter_num;
3619 
3620 	for (i = 0; i < trigger_node->dependencies.values_num; i++)
3621 	{
3622 		trigger_ref = (zbx_lld_trigger_ref_t *)trigger_node->dependencies.values[i];
3623 
3624 		/* skip dependencies marked as deleted */
3625 		if (ZBX_LLD_TRIGGER_DEPENDENCY_DELETE == trigger_ref->flags)
3626 			continue;
3627 
3628 		if (NULL == (trigger_node_up = (zbx_lld_trigger_node_t *)zbx_hashset_search(cache, trigger_ref)))
3629 		{
3630 			THIS_SHOULD_NEVER_HAPPEN;
3631 			continue;
3632 		}
3633 
3634 		/* Remember last dependency that could be cut.                         */
3635 		/* It should be either a last new dependency or just a last dependency */
3636 		/* if no new dependencies were encountered.                            */
3637 		if (ZBX_LLD_TRIGGER_DEPENDENCY_NEW == trigger_ref->flags || NULL == iter->ref_to ||
3638 				ZBX_LLD_TRIGGER_DEPENDENCY_NORMAL == iter->ref_to->flags)
3639 		{
3640 			child_iter.ref_from = &trigger_node->trigger_ref;
3641 			child_iter.ref_to = trigger_ref;
3642 			child_iter.iter_num = iter->iter_num;
3643 
3644 			piter = &child_iter;
3645 		}
3646 		else
3647 			piter = iter;
3648 
3649 		if (FAIL == lld_trigger_dependencies_iter(cache, triggers, trigger_node_up, piter, level + 1, error))
3650 			return FAIL;
3651 	}
3652 
3653 	trigger_node->iter_num = 0;
3654 
3655 	return SUCCEED;
3656 }
3657 
3658 /******************************************************************************
3659  *                                                                            *
3660  * Function: lld_trigger_dependencies_validate                                *
3661  *                                                                            *
3662  * Purpose: validate discovered trigger dependencies                          *
3663  *                                                                            *
3664  * Parameters: triggers - [IN] the discovered triggers                        *
3665  *             error    - [OUT] the error message                             *
3666  *             triggers - [IN] the discovered triggers                        *
3667  *             trigger  - [IN] the trigger to check                           *
3668  *             iter     - [IN] the dependency iterator                        *
3669  *             level    - [IN] the dependency level                           *
3670  *                                                                            *
3671  * Comments: During validation the dependency loops will be resolved by       *
3672  *           removing offending dependencies.                                 *
3673  *                                                                            *
3674  ******************************************************************************/
3675 static void	lld_trigger_dependencies_validate(zbx_vector_ptr_t *triggers, char **error)
3676 {
3677 	zbx_hashset_t			cache;
3678 	zbx_hashset_iter_t		iter;
3679 	zbx_lld_trigger_node_t		*trigger_node, *trigger_node_up;
3680 	zbx_lld_trigger_node_iter_t	node_iter = {0};
3681 	zbx_vector_ptr_t		nodes;
3682 	int				i;
3683 
3684 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3685 
3686 	lld_trigger_cache_init(&cache, triggers);
3687 
3688 	/* Perform dependency validation in the order of trigger ids and starting with parentless triggers. */
3689 	/* This will give some consistency in choosing what dependencies should be deleted in the case of   */
3690 	/* recursion.                                                                                       */
3691 	zbx_vector_ptr_create(&nodes);
3692 	zbx_vector_ptr_reserve(&nodes, cache.num_data);
3693 
3694 	zbx_hashset_iter_reset(&cache, &iter);
3695 	while (NULL != (trigger_node = (zbx_lld_trigger_node_t *)zbx_hashset_iter_next(&iter)))
3696 	{
3697 		for (i = 0; i < trigger_node->dependencies.values_num; i++)
3698 		{
3699 			if (NULL == (trigger_node_up = (zbx_lld_trigger_node_t *)zbx_hashset_search(&cache,
3700 					trigger_node->dependencies.values[i])))
3701 			{
3702 				THIS_SHOULD_NEVER_HAPPEN;
3703 				continue;
3704 			}
3705 
3706 			trigger_node_up->parents++;
3707 		}
3708 		zbx_vector_ptr_append(&nodes, trigger_node);
3709 	}
3710 
3711 	zbx_vector_ptr_sort(&nodes, zbx_lld_trigger_node_compare_func);
3712 
3713 	for (i = 0; i < nodes.values_num; i++)
3714 	{
3715 		if (NULL == (trigger_node = (zbx_lld_trigger_node_t *)zbx_hashset_search(&cache, (zbx_lld_trigger_node_t *)nodes.values[i])))
3716 		{
3717 			THIS_SHOULD_NEVER_HAPPEN;
3718 			continue;
3719 		}
3720 
3721 		/* If dependency iterator returns false it means that dependency loop was detected */
3722 		/* (and resolved). In this case we have to validate dependencies for this trigger  */
3723 		/* again.                                                                          */
3724 		do
3725 		{
3726 			node_iter.iter_num++;
3727 			node_iter.ref_from = NULL;
3728 			node_iter.ref_to = NULL;
3729 		}
3730 		while (SUCCEED != lld_trigger_dependencies_iter(&cache, triggers, trigger_node, &node_iter, 0, error));
3731 	}
3732 
3733 	zbx_vector_ptr_destroy(&nodes);
3734 	zbx_trigger_cache_clean(&cache);
3735 
3736 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3737 }
3738 
3739 static	void	get_trigger_info(const void *object, zbx_uint64_t *id, int *discovery_flag, int *lastcheck,
3740 		int *ts_delete)
3741 {
3742 	zbx_lld_trigger_t	*trigger;
3743 
3744 	trigger = (zbx_lld_trigger_t *)object;
3745 
3746 	*id = trigger->triggerid;
3747 	*discovery_flag = trigger->flags & ZBX_FLAG_LLD_TRIGGER_DISCOVERED;
3748 	*lastcheck = trigger->lastcheck;
3749 	*ts_delete = trigger->ts_delete;
3750 }
3751 
3752 /******************************************************************************
3753  *                                                                            *
3754  * Function: lld_update_triggers                                              *
3755  *                                                                            *
3756  * Purpose: add or update triggers for discovered items                       *
3757  *                                                                            *
3758  * Return value: SUCCEED - if triggers were successfully added/updated or     *
3759  *                         adding/updating was not necessary                  *
3760  *               FAIL    - triggers cannot be added/updated                   *
3761  *                                                                            *
3762  ******************************************************************************/
3763 int	lld_update_triggers(zbx_uint64_t hostid, zbx_uint64_t lld_ruleid, const zbx_vector_ptr_t *lld_rows,
3764 		const zbx_vector_ptr_t *lld_macro_paths, char **error, int lifetime, int lastcheck)
3765 {
3766 	zbx_vector_ptr_t		trigger_prototypes;
3767 	zbx_vector_ptr_t		triggers;
3768 	zbx_vector_ptr_t		items;
3769 	zbx_lld_trigger_t		*trigger;
3770 	zbx_lld_trigger_prototype_t	*trigger_prototype;
3771 	int				ret = SUCCEED, i;
3772 
3773 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3774 
3775 	zbx_vector_ptr_create(&trigger_prototypes);
3776 
3777 	lld_trigger_prototypes_get(lld_ruleid, &trigger_prototypes, error);
3778 
3779 	if (0 == trigger_prototypes.values_num)
3780 		goto out;
3781 
3782 	zbx_vector_ptr_create(&triggers);	/* list of triggers which were created or will be created or */
3783 						/* updated by the trigger prototype */
3784 	zbx_vector_ptr_create(&items);		/* list of items which are related to the trigger prototypes */
3785 
3786 	lld_triggers_get(&trigger_prototypes, &triggers);
3787 	lld_functions_get(&trigger_prototypes, &triggers);
3788 	lld_dependencies_get(&trigger_prototypes, &triggers);
3789 	lld_tags_get(&trigger_prototypes, &triggers);
3790 	lld_items_get(&trigger_prototypes, &items);
3791 
3792 	/* simplifying trigger expressions */
3793 
3794 	for (i = 0; i < trigger_prototypes.values_num; i++)
3795 	{
3796 		trigger_prototype = (zbx_lld_trigger_prototype_t *)trigger_prototypes.values[i];
3797 
3798 		lld_eval_expression_simplify(&trigger_prototype->eval_ctx, NULL, &trigger_prototype->functions);
3799 		lld_eval_expression_simplify(&trigger_prototype->eval_ctx_r, NULL, &trigger_prototype->functions);
3800 	}
3801 
3802 	for (i = 0; i < triggers.values_num; i++)
3803 	{
3804 		trigger = (zbx_lld_trigger_t *)triggers.values[i];
3805 
3806 		lld_trigger_expression_simplify(trigger, &trigger->expression, &trigger->functions);
3807 		lld_trigger_expression_simplify(trigger, &trigger->recovery_expression, &trigger->functions);
3808 	}
3809 
3810 	/* making triggers */
3811 
3812 	lld_triggers_make(&trigger_prototypes, &triggers, &items, lld_rows, lld_macro_paths, error);
3813 	lld_triggers_validate(hostid, &triggers, error);
3814 	lld_trigger_dependencies_make(&trigger_prototypes, &triggers, lld_rows, error);
3815 	lld_trigger_dependencies_validate(&triggers, error);
3816 	lld_trigger_tags_make(&trigger_prototypes, &triggers, lld_rows, lld_macro_paths);
3817 	lld_trigger_tags_validate(&triggers, error);
3818 	ret = lld_triggers_save(hostid, &trigger_prototypes, &triggers);
3819 
3820 	lld_remove_lost_objects("trigger_discovery", "triggerid", &triggers, lifetime, lastcheck, DBdelete_triggers,
3821 			get_trigger_info);
3822 	/* cleaning */
3823 
3824 	zbx_vector_ptr_clear_ext(&items, (zbx_mem_free_func_t)lld_item_free);
3825 	zbx_vector_ptr_clear_ext(&triggers, (zbx_mem_free_func_t)lld_trigger_free);
3826 	zbx_vector_ptr_destroy(&items);
3827 	zbx_vector_ptr_destroy(&triggers);
3828 out:
3829 	zbx_vector_ptr_clear_ext(&trigger_prototypes, (zbx_mem_free_func_t)lld_trigger_prototype_free);
3830 	zbx_vector_ptr_destroy(&trigger_prototypes);
3831 
3832 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3833 
3834 	return ret;
3835 }
3836