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