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
lld_tag_free(zbx_lld_tag_t * tag)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
lld_item_free(zbx_lld_item_t * item)231 static void lld_item_free(zbx_lld_item_t *item)
232 {
233 zbx_free(item);
234 }
235
lld_function_free(zbx_lld_function_t * function)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
lld_trigger_prototype_free(zbx_lld_trigger_prototype_t * trigger_prototype)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
lld_trigger_free(zbx_lld_trigger_t * trigger)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 ******************************************************************************/
lld_trigger_prototypes_get(zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * trigger_prototypes,char ** error)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 ******************************************************************************/
lld_triggers_get(const zbx_vector_ptr_t * trigger_prototypes,zbx_vector_ptr_t * triggers)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 ******************************************************************************/
lld_functions_get(zbx_vector_ptr_t * trigger_prototypes,zbx_vector_ptr_t * triggers)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 ******************************************************************************/
lld_dependencies_get(zbx_vector_ptr_t * trigger_prototypes,zbx_vector_ptr_t * triggers)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 ******************************************************************************/
lld_tags_get(zbx_vector_ptr_t * trigger_prototypes,zbx_vector_ptr_t * triggers)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 ******************************************************************************/
lld_items_get(zbx_vector_ptr_t * trigger_prototypes,zbx_vector_ptr_t * items)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 ******************************************************************************/
lld_trigger_get(zbx_uint64_t parent_triggerid,zbx_hashset_t * items_triggers,const zbx_vector_ptr_t * item_links)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 ******************************************************************************/
lld_eval_expression_index_functions(zbx_eval_context_t * ctx,zbx_vector_ptr_t * functions)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 ******************************************************************************/
lld_eval_expression_simplify(zbx_eval_context_t * ctx,char ** expression,zbx_vector_ptr_t * functions)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 ******************************************************************************/
lld_trigger_expression_simplify(const zbx_lld_trigger_t * trigger,char ** expression,zbx_vector_ptr_t * functions)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 ******************************************************************************/
lld_eval_expression_expand(zbx_eval_context_t * ctx,const zbx_vector_ptr_t * functions)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 ******************************************************************************/
lld_trigger_expression_expand(const zbx_lld_trigger_t * trigger,const char * expression,const zbx_vector_ptr_t * functions)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 ******************************************************************************/
lld_trigger_expression_simplify_and_expand(const zbx_lld_trigger_t * trigger,char ** expression,zbx_vector_ptr_t * functions)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
lld_parameter_make(const char * e,char ** exp,const struct zbx_json_parse * jp_row,const zbx_vector_ptr_t * lld_macros,char ** error)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
lld_function_make(const zbx_lld_function_t * function_proto,zbx_vector_ptr_t * functions,zbx_uint64_t itemid,const struct zbx_json_parse * jp_row,const zbx_vector_ptr_t * lld_macros,char ** error)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
lld_functions_delete(zbx_vector_ptr_t * functions)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
lld_functions_make(const zbx_vector_ptr_t * functions_proto,zbx_vector_ptr_t * functions,const zbx_vector_ptr_t * items,const zbx_vector_ptr_t * item_links,const struct zbx_json_parse * jp_row,const zbx_vector_ptr_t * lld_macros,char ** error)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 ******************************************************************************/
lld_eval_get_expanded_expression(const zbx_eval_context_t * src,const struct zbx_json_parse * jp_row,const zbx_vector_ptr_t * lld_macros,char * err,size_t err_len)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 ******************************************************************************/
lld_trigger_make(const zbx_lld_trigger_prototype_t * trigger_prototype,zbx_vector_ptr_t * triggers,const zbx_vector_ptr_t * items,zbx_hashset_t * items_triggers,const zbx_lld_row_t * lld_row,const zbx_vector_ptr_t * lld_macros,char ** error)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
items_triggers_hash_func(const void * data)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
items_triggers_compare_func(const void * d1,const void * d2)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
lld_triggers_make(const zbx_vector_ptr_t * trigger_prototypes,zbx_vector_ptr_t * triggers,const zbx_vector_ptr_t * items,const zbx_vector_ptr_t * lld_rows,const zbx_vector_ptr_t * lld_macro_paths,char ** error)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 ******************************************************************************/
lld_trigger_dependency_make(const zbx_lld_trigger_prototype_t * trigger_prototype,const zbx_vector_ptr_t * trigger_prototypes,zbx_hashset_t * items_triggers,const zbx_lld_row_t * lld_row,char ** error)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
lld_trigger_dependencies_make(const zbx_vector_ptr_t * trigger_prototypes,zbx_vector_ptr_t * triggers,const zbx_vector_ptr_t * lld_rows,char ** error)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 ******************************************************************************/
lld_trigger_tag_make(zbx_lld_trigger_prototype_t * trigger_prototype,zbx_hashset_t * items_triggers,zbx_lld_row_t * lld_row,const zbx_vector_ptr_t * lld_macro_paths)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 ******************************************************************************/
lld_trigger_tags_make(zbx_vector_ptr_t * trigger_prototypes,zbx_vector_ptr_t * triggers,const zbx_vector_ptr_t * lld_rows,const zbx_vector_ptr_t * lld_macro_paths)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 ******************************************************************************/
lld_validate_trigger_field(zbx_lld_trigger_t * trigger,char ** field,char ** field_orig,zbx_uint64_t flag,size_t field_len,char ** error)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 ******************************************************************************/
lld_trigger_changed(const zbx_lld_trigger_t * trigger)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 ******************************************************************************/
lld_triggers_equal(const zbx_lld_trigger_t * trigger,const zbx_lld_trigger_t * db_trigger)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 ******************************************************************************/
lld_triggers_validate(zbx_uint64_t hostid,zbx_vector_ptr_t * triggers,char ** error)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 ******************************************************************************/
lld_validate_trigger_tag_field(zbx_lld_tag_t * tag,const char * field,zbx_uint64_t flag,size_t field_len,char ** error)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 ******************************************************************************/
lld_trigger_tags_validate(zbx_vector_ptr_t * triggers,char ** error)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 ******************************************************************************/
lld_expression_create(const zbx_lld_trigger_t * trigger,char ** expression,const zbx_vector_ptr_t * functions)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 ******************************************************************************/
lld_triggers_save(zbx_uint64_t hostid,const zbx_vector_ptr_t * trigger_prototypes,const zbx_vector_ptr_t * triggers)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 */
zbx_lld_trigger_ref_hash_func(const void * data)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
zbx_lld_trigger_ref_compare_func(const void * d1,const void * d2)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 */
zbx_lld_trigger_node_compare_func(const void * d1,const void * d2)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 ******************************************************************************/
lld_trigger_cache_append(zbx_hashset_t * cache,zbx_uint64_t triggerid,zbx_lld_trigger_t * trigger)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 ******************************************************************************/
lld_trigger_cache_add_trigger_node(zbx_hashset_t * cache,zbx_lld_trigger_t * trigger,zbx_vector_uint64_t * triggerids_up,zbx_vector_uint64_t * triggerids_down)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 ******************************************************************************/
lld_trigger_cache_init(zbx_hashset_t * cache,zbx_vector_ptr_t * triggers)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 ******************************************************************************/
zbx_trigger_cache_clean(zbx_hashset_t * cache)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 ******************************************************************************/
lld_trigger_dependency_delete(zbx_lld_trigger_ref_t * from,zbx_lld_trigger_ref_t * to,char ** error)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 ******************************************************************************/
lld_trigger_dependencies_iter(zbx_hashset_t * cache,zbx_vector_ptr_t * triggers,zbx_lld_trigger_node_t * trigger_node,zbx_lld_trigger_node_iter_t * iter,int level,char ** error)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 ******************************************************************************/
lld_trigger_dependencies_validate(zbx_vector_ptr_t * triggers,char ** error)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
get_trigger_info(const void * object,zbx_uint64_t * id,int * discovery_flag,int * lastcheck,int * ts_delete)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 ******************************************************************************/
lld_update_triggers(zbx_uint64_t hostid,zbx_uint64_t lld_ruleid,const zbx_vector_ptr_t * lld_rows,const zbx_vector_ptr_t * lld_macro_paths,char ** error,int lifetime,int lastcheck)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