1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21 #include "db.h"
22 #include "log.h"
23 #include "zbxserver.h"
24
25 #include "actions.h"
26 #include "operations.h"
27 #include "events.h"
28 #include "zbxregexp.h"
29
30 /******************************************************************************
31 * *
32 * Function: compare_events *
33 * *
34 * Purpose: compare events by objectid *
35 * *
36 * Parameters: d1 - [IN] event structure to compare to d2 *
37 * d2 - [IN] event structure to compare to d1 *
38 * *
39 * Return value: 0 - equal *
40 * not 0 - otherwise *
41 * *
42 ******************************************************************************/
compare_events(const void * d1,const void * d2)43 static int compare_events(const void *d1, const void *d2)
44 {
45 const DB_EVENT *p1 = *(const DB_EVENT **)d1;
46 const DB_EVENT *p2 = *(const DB_EVENT **)d2;
47
48 ZBX_RETURN_IF_NOT_EQUAL(p1->objectid, p2->objectid);
49 ZBX_RETURN_IF_NOT_EQUAL(p1->object, p2->object);
50
51 return 0;
52 }
53
54 /******************************************************************************
55 * *
56 * Function: add_condition_match *
57 * *
58 * Purpose: save eventids that match condition *
59 * *
60 * Parameters: esc_events - [IN] events to check *
61 * condition - [IN/OUT] condition for matching, outputs *
62 * event ids that match condition *
63 * objectid - [IN] object id, for example trigger or item id *
64 * object - [IN] object, for example EVENT_OBJECT_TRIGGER *
65 ******************************************************************************/
add_condition_match(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition,zbx_uint64_t objectid,int object)66 static void add_condition_match(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition,
67 zbx_uint64_t objectid, int object)
68 {
69 int index;
70 const DB_EVENT event_search = {.objectid = objectid, .object = object};
71
72 if (FAIL != (index = zbx_vector_ptr_bsearch(esc_events, &event_search, compare_events)))
73 {
74 const DB_EVENT *event = (DB_EVENT *)esc_events->values[index];
75 int i;
76
77 zbx_vector_uint64_append(&condition->eventids, event->eventid);
78
79 for (i = index - 1; 0 <= i; i--)
80 {
81 event = esc_events->values[i];
82
83 if (event->objectid != objectid || event->object != object)
84 break;
85
86 zbx_vector_uint64_append(&condition->eventids, event->eventid);
87 }
88
89 for (i = index + 1; i < esc_events->values_num; i++)
90 {
91 event = (DB_EVENT *)esc_events->values[i];
92
93 if (event->objectid != objectid || event->object != object)
94 break;
95
96 zbx_vector_uint64_append(&condition->eventids, event->eventid);
97 }
98 }
99 }
100
101 /******************************************************************************
102 * *
103 * Function: get_object_ids *
104 * *
105 * Purpose: get objectids of escalation events *
106 * *
107 * Parameters: esc_events [IN] - events to check *
108 * objectids [OUT] - event objectids to be used in condition *
109 * allocation *
110 * *
111 ******************************************************************************/
get_object_ids(const zbx_vector_ptr_t * esc_events,zbx_vector_uint64_t * objectids)112 static void get_object_ids(const zbx_vector_ptr_t *esc_events, zbx_vector_uint64_t *objectids)
113 {
114 int i;
115
116 zbx_vector_uint64_reserve(objectids, esc_events->values_num);
117
118 for (i = 0; i < esc_events->values_num; i++)
119 {
120 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
121
122 zbx_vector_uint64_append(objectids, event->objectid);
123 }
124
125 zbx_vector_uint64_uniq(objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
126 }
127
128 /******************************************************************************
129 * *
130 * Function: check_host_group_condition *
131 * *
132 * Purpose: check host group condition *
133 * *
134 * Parameters: esc_events - [IN] events to check *
135 * condition - [IN/OUT] condition for matching, outputs *
136 * event ids that match condition *
137 * *
138 * Return value: SUCCEED - supported operator *
139 * NOTSUPPORTED - not supported operator *
140 * *
141 ******************************************************************************/
check_host_group_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)142 static int check_host_group_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
143 {
144 char *sql = NULL;
145 size_t sql_alloc = 0, sql_offset = 0;
146 DB_RESULT result;
147 DB_ROW row;
148 zbx_vector_uint64_t objectids, groupids;
149 zbx_uint64_t condition_value;
150
151 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
152 return NOTSUPPORTED;
153
154 ZBX_STR2UINT64(condition_value, condition->value);
155
156 zbx_vector_uint64_create(&objectids);
157 zbx_vector_uint64_create(&groupids);
158
159 get_object_ids(esc_events, &objectids);
160 zbx_dc_get_nested_hostgroupids(&condition_value, 1, &groupids);
161
162 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
163 "select distinct f.triggerid"
164 " from hosts_groups hg,hosts h,items i,functions f"
165 " where hg.hostid=h.hostid"
166 " and h.hostid=i.hostid"
167 " and i.itemid=f.itemid"
168 " and");
169
170 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "f.triggerid",
171 objectids.values, objectids.values_num);
172
173 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and");
174 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hg.groupid", groupids.values, groupids.values_num);
175
176 result = DBselect("%s", sql);
177
178 while (NULL != (row = DBfetch(result)))
179 {
180 zbx_uint64_t objectid;
181
182 ZBX_STR2UINT64(objectid, row[0]);
183 if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
184 {
185 int index;
186
187 if (FAIL != (index = zbx_vector_uint64_search(&objectids, objectid,
188 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
189 {
190 zbx_vector_uint64_remove_noorder(&objectids, index);
191 }
192 }
193 else
194 add_condition_match(esc_events, condition, objectid, EVENT_OBJECT_TRIGGER);
195
196 }
197 DBfree_result(result);
198
199 if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
200 {
201 int i;
202
203 for (i = 0; i < objectids.values_num; i++)
204 add_condition_match(esc_events, condition, objectids.values[i], EVENT_OBJECT_TRIGGER);
205 }
206
207 zbx_vector_uint64_destroy(&groupids);
208 zbx_vector_uint64_destroy(&objectids);
209 zbx_free(sql);
210
211 return SUCCEED;
212 }
213
214 /******************************************************************************
215 * *
216 * Function: trigger_parents_sql_alloc *
217 * *
218 * Purpose: mapping between discovered triggers and their prototypes *
219 * *
220 * Parameters: sql [IN/OUT] - allocated sql query *
221 * sql_alloc [IN/OUT] - how much bytes allocated *
222 * objectids_tmp [IN/OUT] - uses to allocate query *
223 * *
224 * *
225 ******************************************************************************/
trigger_parents_sql_alloc(char ** sql,size_t * sql_alloc,zbx_vector_uint64_t * objectids_tmp)226 static void trigger_parents_sql_alloc(char **sql, size_t *sql_alloc, zbx_vector_uint64_t *objectids_tmp)
227 {
228 size_t sql_offset = 0;
229
230 zbx_snprintf_alloc(sql, sql_alloc, &sql_offset,
231 "select triggerid,parent_triggerid"
232 " from trigger_discovery"
233 " where");
234
235 DBadd_condition_alloc(sql, sql_alloc, &sql_offset, "triggerid", objectids_tmp->values,
236 objectids_tmp->values_num);
237 }
238
239 /******************************************************************************
240 * *
241 * Function: objectids_to_pair *
242 * *
243 * Purpose: copy objects to pair, for hierarchy checks *
244 * *
245 * Parameters: objectids [IN] - objects *
246 * objectids_pair [OUT] - objectids will be copied here *
247 * *
248 ******************************************************************************/
objectids_to_pair(zbx_vector_uint64_t * objectids,zbx_vector_uint64_pair_t * objectids_pair)249 static void objectids_to_pair(zbx_vector_uint64_t *objectids, zbx_vector_uint64_pair_t *objectids_pair)
250 {
251 int i;
252
253 zbx_vector_uint64_pair_reserve(objectids_pair, objectids->values_num);
254
255 for (i = 0; i < objectids->values_num; i++)
256 {
257 zbx_uint64_pair_t pair = {objectids->values[i], objectids->values[i]};
258
259 zbx_vector_uint64_pair_append(objectids_pair, pair);
260 }
261 }
262
263 /******************************************************************************
264 * *
265 * Function: check_object_hierarchy *
266 * *
267 * Purpose: there can be multiple levels of templates, that need *
268 * resolving in order to compare to condition *
269 * *
270 * Parameters: object - [IN] type of the object that generated event *
271 * Parameters: esc_events - [IN] events being checked *
272 * objectids - [IN] object ids of the esc_events *
273 * (contents can be changed by processing *
274 * and should not be used by caller) *
275 * objectids_pair - [IN] pairs of (objectid, source objectid) *
276 * where objectid are ids of the esc_events*
277 * and source objectid is object id for *
278 * normal objects and prototype id for *
279 * discovered objects *
280 * (contents can be changed by processing *
281 * and should not be used by caller) *
282 * condition - [IN/OUT] condition to evaluate, matched *
283 * events will be added to condition *
284 * eventids vector *
285 * condition_value - [IN] condition value for matching *
286 * sql_str - [IN] custom sql query, must obtain object, *
287 * template object id and value *
288 * sql_field - [IN] field name that is added to the sql *
289 * query condition *
290 * *
291 ******************************************************************************/
check_object_hierarchy(int object,const zbx_vector_ptr_t * esc_events,zbx_vector_uint64_t * objectids,zbx_vector_uint64_pair_t * objectids_pair,zbx_condition_t * condition,zbx_uint64_t condition_value,char * sql_str,char * sql_field)292 static void check_object_hierarchy(int object, const zbx_vector_ptr_t *esc_events, zbx_vector_uint64_t *objectids,
293 zbx_vector_uint64_pair_t *objectids_pair, zbx_condition_t *condition, zbx_uint64_t condition_value,
294 char *sql_str, char *sql_field)
295 {
296 int i;
297 zbx_vector_uint64_t objectids_tmp;
298 zbx_vector_uint64_pair_t objectids_pair_tmp;
299 char *sql = NULL;
300 size_t sql_alloc = 0;
301
302 zbx_vector_uint64_pair_create(&objectids_pair_tmp);
303 zbx_vector_uint64_create(&objectids_tmp);
304 zbx_vector_uint64_reserve(&objectids_tmp, objectids_pair->values_num);
305
306 while (0 != objectids_pair->values_num)
307 {
308 DB_RESULT result;
309 DB_ROW row;
310 size_t sql_offset = 0;
311
312 /* objectids that need parents to be determined */
313 for (i = 0; i < objectids_pair->values_num; i++)
314 zbx_vector_uint64_append(&objectids_tmp, objectids_pair->values[i].second);
315
316 zbx_vector_uint64_sort(&objectids_tmp, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
317 /* multiple hosts can share trigger from same template, don't allocate duplicate ids */
318 zbx_vector_uint64_uniq(&objectids_tmp, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
319
320 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, sql_str);
321
322 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, sql_field, objectids_tmp.values,
323 objectids_tmp.values_num);
324
325 zbx_vector_uint64_clear(&objectids_tmp);
326
327 result = DBselect("%s", sql);
328
329 while (NULL != (row = DBfetch(result)))
330 {
331 zbx_uint64_t objectid, parent_objectid, value;
332
333 ZBX_STR2UINT64(objectid, row[0]);
334 ZBX_STR2UINT64(parent_objectid, row[1]);
335 ZBX_STR2UINT64(value, row[2]);
336
337 /* find all templates or trigger ids that match our condition and get original id */
338 for (i = 0; i < objectids_pair->values_num; i++)
339 {
340 /* objectid is id that has template id, that match condition */
341 /* second are those that we did select on */
342 if (objectids_pair->values[i].second != objectid)
343 continue;
344
345 if (value == condition_value)
346 {
347 if (CONDITION_OPERATOR_EQUAL != condition->op)
348 {
349 int j;
350
351 /* remove equals from result set, leaving only not equals */
352 if (FAIL != (j = zbx_vector_uint64_search(objectids,
353 objectids_pair->values[i].first,
354 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
355 {
356 zbx_vector_uint64_remove_noorder(objectids, j);
357 }
358 }
359 else
360 {
361 add_condition_match(esc_events, condition,
362 objectids_pair->values[i].first, object);
363 }
364 }
365 else
366 {
367 /* update template id to next level, to compare to condition in next select */
368
369 objectids_pair->values[i].second = parent_objectid;
370 zbx_vector_uint64_pair_append(&objectids_pair_tmp, objectids_pair->values[i]);
371 }
372
373 objectids_pair->values[i].second = 0;
374 }
375 }
376 zbx_free(sql);
377 DBfree_result(result);
378
379 /* resolve in next select only those triggerids that have template id and not equal to condition */
380 zbx_vector_uint64_pair_clear(objectids_pair);
381
382 if (0 != objectids_pair_tmp.values_num)
383 {
384 zbx_vector_uint64_pair_append_array(objectids_pair, objectids_pair_tmp.values,
385 objectids_pair_tmp.values_num);
386 }
387
388 zbx_vector_uint64_pair_clear(&objectids_pair_tmp);
389 }
390
391 /* equals are deleted so copy to result those that are left (not equals) */
392 if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
393 {
394 for (i = 0; i < objectids->values_num; i++)
395 add_condition_match(esc_events, condition, objectids->values[i], object);
396 }
397
398 zbx_vector_uint64_pair_destroy(&objectids_pair_tmp);
399 zbx_vector_uint64_destroy(&objectids_tmp);
400 }
401
402 /******************************************************************************
403 * *
404 * Function: check_host_template_condition *
405 * *
406 * Purpose: check host template condition *
407 * *
408 * Parameters: esc_events - [IN] events to check *
409 * condition - [IN/OUT] condition for matching, outputs *
410 * event ids that match condition *
411 * *
412 * Return value: SUCCEED - supported operator *
413 * NOTSUPPORTED - not supported operator *
414 * *
415 ******************************************************************************/
check_host_template_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)416 static int check_host_template_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
417 {
418 char *sql = NULL;
419 size_t sql_alloc = 0;
420 DB_RESULT result;
421 DB_ROW row;
422 zbx_uint64_t condition_value;
423 zbx_vector_uint64_t objectids;
424 zbx_vector_uint64_pair_t objectids_pair;
425
426 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
427 return NOTSUPPORTED;
428
429 zbx_vector_uint64_create(&objectids);
430 zbx_vector_uint64_pair_create(&objectids_pair);
431
432 get_object_ids(esc_events, &objectids);
433 objectids_to_pair(&objectids, &objectids_pair);
434
435 ZBX_STR2UINT64(condition_value, condition->value);
436
437 trigger_parents_sql_alloc(&sql, &sql_alloc, &objectids);
438
439 result = DBselect("%s", sql);
440
441 while (NULL != (row = DBfetch(result)))
442 {
443 zbx_uint64_pair_t pair;
444 int i;
445
446 ZBX_STR2UINT64(pair.first, row[0]);
447
448 if (FAIL != (i = zbx_vector_uint64_pair_search(&objectids_pair, pair, ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
449 ZBX_STR2UINT64(objectids_pair.values[i].second, row[1]);
450 }
451 DBfree_result(result);
452
453 check_object_hierarchy(EVENT_OBJECT_TRIGGER, esc_events, &objectids, &objectids_pair, condition, condition_value,
454 "select distinct t.triggerid,t.templateid,i.hostid"
455 " from items i,functions f,triggers t"
456 " where i.itemid=f.itemid"
457 " and f.triggerid=t.templateid"
458 " and",
459 "t.triggerid");
460
461 zbx_vector_uint64_destroy(&objectids);
462 zbx_vector_uint64_pair_destroy(&objectids_pair);
463 zbx_free(sql);
464
465 return SUCCEED;
466 }
467
468 /******************************************************************************
469 * *
470 * Function: check_host_condition *
471 * *
472 * Purpose: check host condition *
473 * *
474 * Parameters: esc_events - [IN] events to check *
475 * condition - [IN/OUT] condition for matching, outputs *
476 * event ids that match condition *
477 * *
478 * Return value: SUCCEED - supported operator *
479 * NOTSUPPORTED - not supported operator *
480 * *
481 ******************************************************************************/
check_host_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)482 static int check_host_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
483 {
484 char *sql = NULL, *operation;
485 size_t sql_alloc = 0, sql_offset = 0;
486 DB_RESULT result;
487 DB_ROW row;
488 zbx_vector_uint64_t objectids;
489 zbx_uint64_t condition_value;
490
491 if (CONDITION_OPERATOR_EQUAL == condition->op)
492 operation = " and";
493 else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
494 operation = " and not";
495 else
496 return NOTSUPPORTED;
497
498 ZBX_STR2UINT64(condition_value, condition->value);
499
500 zbx_vector_uint64_create(&objectids);
501
502 get_object_ids(esc_events, &objectids);
503
504 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
505 "select distinct f.triggerid"
506 " from items i,functions f"
507 " where i.itemid=f.itemid"
508 "%s i.hostid=" ZBX_FS_UI64
509 " and",
510 operation,
511 condition_value);
512
513 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "f.triggerid", objectids.values, objectids.values_num);
514
515 result = DBselect("%s", sql);
516
517 while (NULL != (row = DBfetch(result)))
518 {
519 zbx_uint64_t objectid;
520
521 ZBX_STR2UINT64(objectid, row[0]);
522 add_condition_match(esc_events, condition, objectid, EVENT_OBJECT_TRIGGER);
523 }
524 DBfree_result(result);
525
526 zbx_vector_uint64_destroy(&objectids);
527 zbx_free(sql);
528
529 return SUCCEED;
530 }
531
532 /******************************************************************************
533 * *
534 * Function: check_trigger_id_condition *
535 * *
536 * Purpose: check trigger id condition *
537 * *
538 * Parameters: esc_events - [IN] events to check *
539 * condition - [IN/OUT] condition for matching, outputs *
540 * event ids that match condition *
541 * *
542 * Return value: SUCCEED - supported operator *
543 * NOTSUPPORTED - not supported operator *
544 * *
545 ******************************************************************************/
check_trigger_id_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)546 static int check_trigger_id_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
547 {
548 zbx_uint64_t condition_value;
549 zbx_vector_uint64_t objectids;
550 zbx_vector_uint64_pair_t objectids_pair;
551 int i;
552
553 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
554 return NOTSUPPORTED;
555
556 ZBX_STR2UINT64(condition_value, condition->value);
557
558 zbx_vector_uint64_create(&objectids);
559 zbx_vector_uint64_pair_create(&objectids_pair);
560
561 for (i = 0; i < esc_events->values_num; i++)
562 {
563 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
564
565 if (event->objectid == condition_value)
566 {
567 if (CONDITION_OPERATOR_EQUAL == condition->op)
568 zbx_vector_uint64_append(&condition->eventids, event->eventid);
569 }
570 else
571 zbx_vector_uint64_append(&objectids, event->objectid);
572 }
573
574 if (0 != objectids.values_num)
575 {
576 zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
577 objectids_to_pair(&objectids, &objectids_pair);
578
579 check_object_hierarchy(EVENT_OBJECT_TRIGGER, esc_events, &objectids, &objectids_pair, condition, condition_value,
580 "select triggerid,templateid,templateid"
581 " from triggers"
582 " where templateid is not null and",
583 "triggerid");
584 }
585
586 zbx_vector_uint64_destroy(&objectids);
587 zbx_vector_uint64_pair_destroy(&objectids_pair);
588
589 return SUCCEED;
590 }
591
592 /******************************************************************************
593 * *
594 * Function: check_trigger_name_condition *
595 * *
596 * Purpose: check trigger name condition *
597 * *
598 * Parameters: esc_events - [IN] events to check *
599 * condition - [IN/OUT] condition for matching, outputs *
600 * event ids that match condition *
601 * *
602 * Return value: SUCCEED - supported operator *
603 * NOTSUPPORTED - not supported operator *
604 * *
605 ******************************************************************************/
check_trigger_name_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)606 static int check_trigger_name_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
607 {
608 int i;
609
610 if (CONDITION_OPERATOR_LIKE != condition->op && CONDITION_OPERATOR_NOT_LIKE != condition->op)
611 return NOTSUPPORTED;
612
613 for (i = 0; i < esc_events->values_num; i++)
614 {
615 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
616
617 switch (condition->op)
618 {
619 case CONDITION_OPERATOR_LIKE:
620 if (NULL != strstr(event->name, condition->value))
621 zbx_vector_uint64_append(&condition->eventids, event->eventid);
622 break;
623 case CONDITION_OPERATOR_NOT_LIKE:
624 if (NULL == strstr(event->name, condition->value))
625 zbx_vector_uint64_append(&condition->eventids, event->eventid);
626 break;
627 }
628 }
629
630 return SUCCEED;
631 }
632
633 /******************************************************************************
634 * *
635 * Function: check_trigger_severity_condition *
636 * *
637 * Purpose: check trigger severity condition *
638 * *
639 * Parameters: esc_events - [IN] events to check *
640 * condition - [IN/OUT] condition for matching, outputs *
641 * event ids that match condition *
642 * *
643 * Return value: SUCCEED - supported operator *
644 * NOTSUPPORTED - not supported operator *
645 * *
646 ******************************************************************************/
check_trigger_severity_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)647 static int check_trigger_severity_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
648 {
649 unsigned char condition_value;
650 int i;
651
652 condition_value = (unsigned char)atoi(condition->value);
653
654 for (i = 0; i < esc_events->values_num; i++)
655 {
656 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
657
658 switch (condition->op)
659 {
660 case CONDITION_OPERATOR_EQUAL:
661 if (event->trigger.priority == condition_value)
662 zbx_vector_uint64_append(&condition->eventids, event->eventid);
663 break;
664 case CONDITION_OPERATOR_NOT_EQUAL:
665 if (event->trigger.priority != condition_value)
666 zbx_vector_uint64_append(&condition->eventids, event->eventid);
667 break;
668 case CONDITION_OPERATOR_MORE_EQUAL:
669 if (event->trigger.priority >= condition_value)
670 zbx_vector_uint64_append(&condition->eventids, event->eventid);
671 break;
672 case CONDITION_OPERATOR_LESS_EQUAL:
673 if (event->trigger.priority <= condition_value)
674 zbx_vector_uint64_append(&condition->eventids, event->eventid);
675 break;
676 default:
677 return NOTSUPPORTED;
678 }
679 }
680
681 return SUCCEED;
682 }
683
684 /******************************************************************************
685 * *
686 * Function: check_time_period_condition *
687 * *
688 * Purpose: check time period condition *
689 * *
690 * Parameters: esc_events - [IN] events to check *
691 * condition - [IN/OUT] condition for matching, outputs *
692 * event ids that match condition *
693 * *
694 * Return value: SUCCEED - supported operator *
695 * NOTSUPPORTED - not supported operator *
696 * *
697 ******************************************************************************/
check_time_period_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)698 static int check_time_period_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
699 {
700 char *period;
701 int i;
702
703 if (CONDITION_OPERATOR_IN != condition->op && CONDITION_OPERATOR_NOT_IN != condition->op)
704 return NOTSUPPORTED;
705
706 period = zbx_strdup(NULL, condition->value);
707 substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &period,
708 MACRO_TYPE_COMMON, NULL, 0);
709
710 for (i = 0; i < esc_events->values_num; i++)
711 {
712 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
713 int res;
714
715 if (SUCCEED == zbx_check_time_period(period, (time_t)event->clock, &res))
716 {
717 switch (condition->op)
718 {
719 case CONDITION_OPERATOR_IN:
720 if (SUCCEED == res)
721 zbx_vector_uint64_append(&condition->eventids, event->eventid);
722 break;
723 case CONDITION_OPERATOR_NOT_IN:
724 if (FAIL == res)
725 zbx_vector_uint64_append(&condition->eventids, event->eventid);
726 break;
727 }
728 }
729 else
730 {
731 zabbix_log(LOG_LEVEL_WARNING, "Invalid time period \"%s\" for condition id [" ZBX_FS_UI64 "]",
732 period, condition->conditionid);
733 }
734 }
735
736 zbx_free(period);
737
738 return SUCCEED;
739 }
740
check_suppressed_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)741 static int check_suppressed_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
742 {
743 int i;
744
745 for (i = 0; i < esc_events->values_num; i++)
746 {
747 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
748
749 switch (condition->op)
750 {
751 case CONDITION_OPERATOR_YES:
752 if (ZBX_PROBLEM_SUPPRESSED_TRUE == event->suppressed)
753 zbx_vector_uint64_append(&condition->eventids, event->eventid);
754 break;
755 case CONDITION_OPERATOR_NO:
756 if (ZBX_PROBLEM_SUPPRESSED_FALSE == event->suppressed)
757 zbx_vector_uint64_append(&condition->eventids, event->eventid);
758 break;
759 default:
760 return NOTSUPPORTED;
761 }
762 }
763
764 return SUCCEED;
765 }
766
check_acknowledged_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)767 static int check_acknowledged_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
768 {
769 int i;
770 zbx_vector_uint64_t eventids;
771 char *sql = NULL;
772 size_t sql_alloc = 0, sql_offset = 0;
773 DB_RESULT result;
774 DB_ROW row;
775 int ret = SUCCEED;
776
777 zbx_vector_uint64_create(&eventids);
778 zbx_vector_uint64_reserve(&eventids, esc_events->values_num);
779
780 for (i = 0; i < esc_events->values_num; i++)
781 {
782 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
783
784 zbx_vector_uint64_append(&eventids, event->eventid);
785 }
786
787 zbx_vector_uint64_sort(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
788
789 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
790 "select eventid"
791 " from events"
792 " where acknowledged=%d"
793 " and",
794 atoi(condition->value));
795
796 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "eventid", eventids.values, eventids.values_num);
797
798 result = DBselect("%s", sql);
799 while (NULL != (row = DBfetch(result)))
800 {
801 zbx_uint64_t eventid;
802
803 ZBX_STR2UINT64(eventid, row[0]);
804 switch (condition->op)
805 {
806 case CONDITION_OPERATOR_EQUAL:
807 zbx_vector_uint64_append(&condition->eventids, eventid);
808 break;
809 default:
810 ret = NOTSUPPORTED;
811 }
812
813 }
814 DBfree_result(result);
815 zbx_free(sql);
816
817 zbx_vector_uint64_destroy(&eventids);
818
819 return ret;
820 }
821
822 /******************************************************************************
823 * *
824 * Function: check_application_condition *
825 * *
826 * Purpose: check application condition *
827 * *
828 * Parameters: esc_events - [IN] events to check *
829 * condition - [IN/OUT] condition for matching, outputs *
830 * event ids that match condition *
831 * *
832 * Return value: SUCCEED - supported operator *
833 * NOTSUPPORTED - not supported operator *
834 * *
835 ******************************************************************************/
check_application_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)836 static int check_application_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
837 {
838 char *sql = NULL;
839 size_t sql_alloc = 0, sql_offset = 0;
840 DB_RESULT result;
841 DB_ROW row;
842 zbx_vector_uint64_t objectids;
843 zbx_uint64_t objectid;
844 int i;
845
846 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_LIKE != condition->op &&
847 CONDITION_OPERATOR_NOT_LIKE != condition->op)
848 {
849 return NOTSUPPORTED;
850 }
851
852 zbx_vector_uint64_create(&objectids);
853
854 get_object_ids(esc_events, &objectids);
855
856 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
857 "select distinct t.triggerid,a.name"
858 " from applications a,items_applications i,functions f,triggers t"
859 " where a.applicationid=i.applicationid"
860 " and i.itemid=f.itemid"
861 " and f.triggerid=t.triggerid"
862 " and");
863
864 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.triggerid", objectids.values, objectids.values_num);
865
866 result = DBselect("%s", sql);
867
868 switch (condition->op)
869 {
870 case CONDITION_OPERATOR_EQUAL:
871 while (NULL != (row = DBfetch(result)))
872 {
873 if (0 == strcmp(row[1], condition->value))
874 {
875 ZBX_STR2UINT64(objectid, row[0]);
876 add_condition_match(esc_events, condition, objectid, EVENT_OBJECT_TRIGGER);
877 }
878 }
879 break;
880 case CONDITION_OPERATOR_LIKE:
881 while (NULL != (row = DBfetch(result)))
882 {
883 if (NULL != strstr(row[1], condition->value))
884 {
885 ZBX_STR2UINT64(objectid, row[0]);
886 add_condition_match(esc_events, condition, objectid, EVENT_OBJECT_TRIGGER);
887 }
888 }
889 break;
890 case CONDITION_OPERATOR_NOT_LIKE:
891 while (NULL != (row = DBfetch(result)))
892 {
893 if (NULL != strstr(row[1], condition->value))
894 {
895 ZBX_STR2UINT64(objectid, row[0]);
896
897 if (FAIL != (i = zbx_vector_uint64_search(&objectids, objectid,
898 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
899 {
900 zbx_vector_uint64_remove_noorder(&objectids, i);
901 }
902 }
903 }
904
905 for (i = 0; i < objectids.values_num; i++)
906 add_condition_match(esc_events, condition, objectids.values[i], EVENT_OBJECT_TRIGGER);
907 break;
908 }
909 DBfree_result(result);
910
911 zbx_vector_uint64_destroy(&objectids);
912 zbx_free(sql);
913
914 return SUCCEED;
915 }
916
917 /******************************************************************************
918 * *
919 * Function: check_condition_event_tag *
920 * *
921 * Purpose: check condition event tag *
922 * *
923 * Parameters: esc_events - [IN] events to check *
924 * condition - [IN/OUT] condition for matching, outputs *
925 * event ids that match condition *
926 * *
927 ******************************************************************************/
check_condition_event_tag(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)928 static void check_condition_event_tag(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
929 {
930 int i, ret, ret_continue;
931
932 if (CONDITION_OPERATOR_NOT_EQUAL == condition->op || CONDITION_OPERATOR_NOT_LIKE == condition->op)
933 ret_continue = SUCCEED;
934 else
935 ret_continue = FAIL;
936
937 for (i = 0; i < esc_events->values_num; i++)
938 {
939 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
940 int j;
941
942 ret = ret_continue;
943
944 for (j = 0; j < event->tags.values_num && ret == ret_continue; j++)
945 {
946 const zbx_tag_t *tag = (zbx_tag_t *)event->tags.values[j];
947
948 ret = zbx_strmatch_condition(tag->tag, condition->value, condition->op);
949 }
950
951 if (SUCCEED == ret)
952 zbx_vector_uint64_append(&condition->eventids, event->eventid);
953 }
954 }
955
956 /******************************************************************************
957 * *
958 * Function: check_condition_event_tag_value *
959 * *
960 * Purpose: check condition event tag value *
961 * *
962 * Parameters: esc_events - [IN] events to check *
963 * condition - [IN/OUT] condition for matching, outputs *
964 * event ids that match condition *
965 * *
966 ******************************************************************************/
check_condition_event_tag_value(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)967 static void check_condition_event_tag_value(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
968 {
969 int i, ret, ret_continue;
970
971 if (CONDITION_OPERATOR_NOT_EQUAL == condition->op || CONDITION_OPERATOR_NOT_LIKE == condition->op)
972 ret_continue = SUCCEED;
973 else
974 ret_continue = FAIL;
975
976 for (i = 0; i < esc_events->values_num; i++)
977 {
978 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
979 int j;
980
981 ret = ret_continue;
982
983 for (j = 0; j < event->tags.values_num && ret == ret_continue; j++)
984 {
985 zbx_tag_t *tag = (zbx_tag_t *)event->tags.values[j];
986
987 if (0 == strcmp(condition->value2, tag->tag))
988 ret = zbx_strmatch_condition(tag->value, condition->value, condition->op);
989 }
990
991 if (SUCCEED == ret)
992 zbx_vector_uint64_append(&condition->eventids, event->eventid);
993 }
994 }
995
996 /******************************************************************************
997 * *
998 * Function: check_trigger_condition *
999 * *
1000 * Purpose: check if event matches single condition *
1001 * *
1002 * Parameters: event - trigger event to check *
1003 * (event->source == EVENT_SOURCE_TRIGGERS) *
1004 * condition - condition for matching *
1005 * *
1006 * Return value: SUCCEED - matches, FAIL - otherwise *
1007 * *
1008 * Author: Alexei Vladishev *
1009 * *
1010 ******************************************************************************/
check_trigger_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1011 static void check_trigger_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1012 {
1013 int ret;
1014
1015 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1016
1017 switch (condition->conditiontype)
1018 {
1019 case CONDITION_TYPE_HOST_GROUP:
1020 ret = check_host_group_condition(esc_events, condition);
1021 break;
1022 case CONDITION_TYPE_HOST_TEMPLATE:
1023 ret = check_host_template_condition(esc_events, condition);
1024 break;
1025 case CONDITION_TYPE_HOST:
1026 ret = check_host_condition(esc_events, condition);
1027 break;
1028 case CONDITION_TYPE_TRIGGER:
1029 ret = check_trigger_id_condition(esc_events, condition);
1030 break;
1031 case CONDITION_TYPE_TRIGGER_NAME:
1032 ret = check_trigger_name_condition(esc_events, condition);
1033 break;
1034 case CONDITION_TYPE_TRIGGER_SEVERITY:
1035 ret = check_trigger_severity_condition(esc_events, condition);
1036 break;
1037 case CONDITION_TYPE_TIME_PERIOD:
1038 ret = check_time_period_condition(esc_events, condition);
1039 break;
1040 case CONDITION_TYPE_SUPPRESSED:
1041 ret = check_suppressed_condition(esc_events, condition);
1042 break;
1043 case CONDITION_TYPE_EVENT_ACKNOWLEDGED:
1044 ret = check_acknowledged_condition(esc_events, condition);
1045 break;
1046 case CONDITION_TYPE_APPLICATION:
1047 ret = check_application_condition(esc_events, condition);
1048 break;
1049 case CONDITION_TYPE_EVENT_TAG:
1050 check_condition_event_tag(esc_events, condition);
1051 ret = SUCCEED;
1052 break;
1053 case CONDITION_TYPE_EVENT_TAG_VALUE:
1054 check_condition_event_tag_value(esc_events,condition);
1055 ret = SUCCEED;
1056 break;
1057 default:
1058 zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
1059 (int)condition->conditiontype, condition->conditionid);
1060 ret = FAIL;
1061 }
1062
1063 if (NOTSUPPORTED == ret)
1064 {
1065 zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
1066 (int)condition->op, condition->conditionid);
1067 }
1068
1069 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
1070 }
1071
1072 /******************************************************************************
1073 * *
1074 * Function: get_object_ids_discovery *
1075 * *
1076 * Purpose: get objectids for dhost *
1077 * *
1078 * Parameters: esc_events - [IN] events to check *
1079 * objectids - [OUT] event objectids to be used in condition *
1080 * allocation 2 vectors where first one is *
1081 * dhost ids, second is dservice *
1082 * *
1083 ******************************************************************************/
get_object_ids_discovery(const zbx_vector_ptr_t * esc_events,zbx_vector_uint64_t * objectids)1084 static void get_object_ids_discovery(const zbx_vector_ptr_t *esc_events, zbx_vector_uint64_t *objectids)
1085 {
1086 int i;
1087
1088 for (i = 0; i < esc_events->values_num; i++)
1089 {
1090 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
1091
1092 if (event->object == EVENT_OBJECT_DHOST)
1093 zbx_vector_uint64_append(&objectids[0], event->objectid);
1094 else
1095 zbx_vector_uint64_append(&objectids[1], event->objectid);
1096 }
1097
1098 zbx_vector_uint64_uniq(&objectids[0], ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1099 zbx_vector_uint64_uniq(&objectids[1], ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1100 }
1101 /******************************************************************************
1102 * *
1103 * Function: check_drule_condition *
1104 * *
1105 * Purpose: check discovery rule condition *
1106 * *
1107 * Parameters: esc_events - [IN] events to check *
1108 * condition - [IN/OUT] condition for matching, outputs *
1109 * event ids that match condition *
1110 * *
1111 * Return value: SUCCEED - supported operator *
1112 * NOTSUPPORTED - not supported operator *
1113 * *
1114 ******************************************************************************/
check_drule_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1115 static int check_drule_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1116 {
1117 char *sql = NULL, *operation_and, *operation_where;
1118 size_t sql_alloc = 0, i;
1119 DB_RESULT result;
1120 DB_ROW row;
1121 int objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE};
1122 zbx_vector_uint64_t objectids[2];
1123 zbx_uint64_t condition_value;
1124
1125 if (CONDITION_OPERATOR_EQUAL == condition->op)
1126 {
1127 operation_and = " and";
1128 operation_where = " where";
1129 }
1130 else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
1131 {
1132 operation_and = " and not";
1133 operation_where = " where not";
1134 }
1135 else
1136 return NOTSUPPORTED;
1137
1138 ZBX_STR2UINT64(condition_value, condition->value);
1139
1140 zbx_vector_uint64_create(&objectids[0]);
1141 zbx_vector_uint64_create(&objectids[1]);
1142
1143 get_object_ids_discovery(esc_events, objectids);
1144
1145 for (i = 0; i < (int)ARRSIZE(objects); i++)
1146 {
1147 size_t sql_offset = 0;
1148
1149 if (0 == objectids[i].values_num)
1150 continue;
1151
1152 if (EVENT_OBJECT_DHOST == objects[i])
1153 {
1154 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1155 "select dhostid"
1156 " from dhosts"
1157 "%s druleid=" ZBX_FS_UI64
1158 " and",
1159 operation_where,
1160 condition_value);
1161
1162 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dhostid",
1163 objectids[i].values, objectids[i].values_num);
1164 }
1165 else /* EVENT_OBJECT_DSERVICE */
1166 {
1167 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1168 "select s.dserviceid"
1169 " from dhosts h,dservices s"
1170 " where h.dhostid=s.dhostid"
1171 "%s h.druleid=" ZBX_FS_UI64
1172 " and",
1173 operation_and,
1174 condition_value);
1175
1176 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "s.dserviceid",
1177 objectids[i].values, objectids[i].values_num);
1178 }
1179
1180 result = DBselect("%s", sql);
1181
1182 while (NULL != (row = DBfetch(result)))
1183 {
1184 zbx_uint64_t objectid;
1185
1186 ZBX_STR2UINT64(objectid, row[0]);
1187 add_condition_match(esc_events, condition, objectid, objects[i]);
1188 }
1189 DBfree_result(result);
1190 }
1191
1192 zbx_vector_uint64_destroy(&objectids[0]);
1193 zbx_vector_uint64_destroy(&objectids[1]);
1194 zbx_free(sql);
1195
1196 return SUCCEED;
1197 }
1198
1199 /******************************************************************************
1200 * *
1201 * Function: check_dcheck_condition *
1202 * *
1203 * Purpose: check discovery check condition *
1204 * *
1205 * Parameters: esc_events - [IN] events to check *
1206 * condition - [IN/OUT] condition for matching, outputs *
1207 * event ids that match condition *
1208 * *
1209 * Return value: SUCCEED - supported operator *
1210 * NOTSUPPORTED - not supported operator *
1211 * *
1212 ******************************************************************************/
check_dcheck_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1213 static int check_dcheck_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1214 {
1215 char *sql = NULL, *operation_where;
1216 size_t sql_alloc = 0, sql_offset = 0;
1217 DB_RESULT result;
1218 DB_ROW row;
1219 int object = EVENT_OBJECT_DSERVICE, i;
1220 zbx_vector_uint64_t objectids;
1221 zbx_uint64_t condition_value;
1222
1223 if (CONDITION_OPERATOR_EQUAL == condition->op)
1224 operation_where = " where";
1225 else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
1226 operation_where = " where not";
1227 else
1228 return NOTSUPPORTED;
1229
1230 ZBX_STR2UINT64(condition_value, condition->value);
1231
1232 zbx_vector_uint64_create(&objectids);
1233
1234 for (i = 0; i < esc_events->values_num; i++)
1235 {
1236 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
1237
1238 if (object == event->object)
1239 zbx_vector_uint64_append(&objectids, event->objectid);
1240 }
1241
1242 if (0 != objectids.values_num)
1243 {
1244 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1245 "select dserviceid"
1246 " from dservices"
1247 "%s dcheckid=" ZBX_FS_UI64
1248 " and",
1249 operation_where,
1250 condition_value);
1251
1252 zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1253 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid", objectids.values,
1254 objectids.values_num);
1255
1256 result = DBselect("%s", sql);
1257
1258 while (NULL != (row = DBfetch(result)))
1259 {
1260 zbx_uint64_t objectid;
1261
1262 ZBX_STR2UINT64(objectid, row[0]);
1263 add_condition_match(esc_events, condition, objectid, object);
1264 }
1265 DBfree_result(result);
1266 }
1267
1268 zbx_vector_uint64_destroy(&objectids);
1269 zbx_free(sql);
1270
1271 return SUCCEED;
1272 }
1273
1274 /******************************************************************************
1275 * *
1276 * Function: check_dobject_condition *
1277 * *
1278 * Purpose: check discovery object condition *
1279 * *
1280 * Parameters: esc_events - [IN] events to check *
1281 * condition - [IN/OUT] condition for matching, outputs *
1282 * event ids that match condition *
1283 * *
1284 * Return value: SUCCEED - supported operator *
1285 * NOTSUPPORTED - not supported operator *
1286 * *
1287 ******************************************************************************/
check_dobject_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1288 static int check_dobject_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1289 {
1290 int i, condition_value_i = atoi(condition->value);
1291
1292 if (CONDITION_OPERATOR_EQUAL != condition->op)
1293 return NOTSUPPORTED;
1294
1295 for (i = 0; i < esc_events->values_num; i++)
1296 {
1297 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
1298
1299 if (event->object == condition_value_i)
1300 zbx_vector_uint64_append(&condition->eventids, event->eventid);
1301 }
1302
1303 return SUCCEED;
1304 }
1305
1306 /******************************************************************************
1307 * *
1308 * Function: check_proxy_condition *
1309 * *
1310 * Purpose: check proxy condition for discovery event *
1311 * *
1312 * Parameters: esc_events - [IN] events to check *
1313 * condition - [IN/OUT] condition for matching, outputs *
1314 * event ids that match condition *
1315 * *
1316 * Return value: SUCCEED - supported operator *
1317 * NOTSUPPORTED - not supported operator *
1318 * *
1319 ******************************************************************************/
check_proxy_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1320 static int check_proxy_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1321 {
1322 char *sql = NULL, *operation_and;
1323 size_t sql_alloc = 0, i;
1324 DB_RESULT result;
1325 DB_ROW row;
1326 int objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE};
1327 zbx_vector_uint64_t objectids[2];
1328 zbx_uint64_t condition_value;
1329
1330 if (CONDITION_OPERATOR_EQUAL == condition->op)
1331 operation_and = " and";
1332 else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
1333 operation_and = " and not";
1334 else
1335 return NOTSUPPORTED;
1336
1337 ZBX_STR2UINT64(condition_value, condition->value);
1338
1339 zbx_vector_uint64_create(&objectids[0]);
1340 zbx_vector_uint64_create(&objectids[1]);
1341
1342 get_object_ids_discovery(esc_events, objectids);
1343
1344 for (i = 0; i < (int)ARRSIZE(objects); i++)
1345 {
1346 size_t sql_offset = 0;
1347
1348 if (0 == objectids[i].values_num)
1349 continue;
1350
1351 if (EVENT_OBJECT_DHOST == objects[i])
1352 {
1353 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1354 "select h.dhostid"
1355 " from drules r,dhosts h"
1356 " where r.druleid=h.druleid"
1357 "%s r.proxy_hostid=" ZBX_FS_UI64
1358 " and",
1359 operation_and,
1360 condition_value);
1361
1362 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "h.dhostid", objectids[i].values,
1363 objectids[i].values_num);
1364 }
1365 else /* EVENT_OBJECT_DSERVICE */
1366 {
1367 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1368 "select s.dserviceid"
1369 " from drules r,dhosts h,dservices s"
1370 " where r.druleid=h.druleid"
1371 " and h.dhostid=s.dhostid"
1372 "%s r.proxy_hostid=" ZBX_FS_UI64
1373 " and",
1374 operation_and,
1375 condition_value);
1376
1377 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "s.dserviceid",
1378 objectids[i].values, objectids[i].values_num);
1379 }
1380
1381 result = DBselect("%s", sql);
1382
1383 while (NULL != (row = DBfetch(result)))
1384 {
1385 zbx_uint64_t objectid;
1386
1387 ZBX_STR2UINT64(objectid, row[0]);
1388 add_condition_match(esc_events, condition, objectid, objects[i]);
1389 }
1390 DBfree_result(result);
1391 }
1392
1393 zbx_vector_uint64_destroy(&objectids[0]);
1394 zbx_vector_uint64_destroy(&objectids[1]);
1395 zbx_free(sql);
1396
1397 return SUCCEED;
1398 }
1399
1400 /******************************************************************************
1401 * *
1402 * Function: check_dvalue_condition *
1403 * *
1404 * Purpose: check discovery value condition *
1405 * *
1406 * Parameters: esc_events - [IN] events to check *
1407 * condition - [IN/OUT] condition for matching, outputs *
1408 * event ids that match condition *
1409 * *
1410 * Return value: SUCCEED - supported operator *
1411 * NOTSUPPORTED - not supported operator *
1412 * *
1413 ******************************************************************************/
check_dvalue_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1414 static int check_dvalue_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1415 {
1416 char *sql = NULL;
1417 size_t sql_alloc = 0, sql_offset = 0;
1418 DB_RESULT result;
1419 DB_ROW row;
1420 int object = EVENT_OBJECT_DSERVICE;
1421 zbx_vector_uint64_t objectids;
1422 int i;
1423
1424 switch (condition->op)
1425 {
1426 case CONDITION_OPERATOR_EQUAL:
1427 case CONDITION_OPERATOR_NOT_EQUAL:
1428 case CONDITION_OPERATOR_MORE_EQUAL:
1429 case CONDITION_OPERATOR_LESS_EQUAL:
1430 case CONDITION_OPERATOR_LIKE:
1431 case CONDITION_OPERATOR_NOT_LIKE:
1432 break;
1433 default:
1434 return NOTSUPPORTED;
1435 }
1436
1437 zbx_vector_uint64_create(&objectids);
1438
1439 for (i = 0; i < esc_events->values_num; i++)
1440 {
1441 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
1442
1443 if (object == event->object)
1444 zbx_vector_uint64_append(&objectids, event->objectid);
1445 }
1446
1447 if (0 != objectids.values_num)
1448 {
1449 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1450 "select dserviceid,value"
1451 " from dservices"
1452 " where");
1453
1454 zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1455 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid", objectids.values,
1456 objectids.values_num);
1457
1458 result = DBselect("%s", sql);
1459
1460 while (NULL != (row = DBfetch(result)))
1461 {
1462 zbx_uint64_t objectid;
1463
1464 ZBX_STR2UINT64(objectid, row[0]);
1465
1466 switch (condition->op)
1467 {
1468 case CONDITION_OPERATOR_EQUAL:
1469 if (0 == strcmp(condition->value, row[1]))
1470 add_condition_match(esc_events, condition, objectid, object);
1471 break;
1472 case CONDITION_OPERATOR_NOT_EQUAL:
1473 if (0 != strcmp(condition->value, row[1]))
1474 add_condition_match(esc_events, condition, objectid, object);
1475 break;
1476 case CONDITION_OPERATOR_MORE_EQUAL:
1477 if (0 <= strcmp(row[1], condition->value))
1478 add_condition_match(esc_events, condition, objectid, object);
1479 break;
1480 case CONDITION_OPERATOR_LESS_EQUAL:
1481 if (0 >= strcmp(row[1], condition->value))
1482 add_condition_match(esc_events, condition, objectid, object);
1483 break;
1484 case CONDITION_OPERATOR_LIKE:
1485 if (NULL != strstr(row[1], condition->value))
1486 add_condition_match(esc_events, condition, objectid, object);
1487 break;
1488 case CONDITION_OPERATOR_NOT_LIKE:
1489 if (NULL == strstr(row[1], condition->value))
1490 add_condition_match(esc_events, condition, objectid, object);
1491 break;
1492 }
1493 }
1494 DBfree_result(result);
1495 }
1496
1497 zbx_vector_uint64_destroy(&objectids);
1498 zbx_free(sql);
1499
1500 return SUCCEED;
1501 }
1502
1503 /******************************************************************************
1504 * *
1505 * Function: check_dhost_ip_condition *
1506 * *
1507 * Purpose: check host ip condition for discovery event *
1508 * *
1509 * Parameters: esc_events - [IN] events to check *
1510 * condition - [IN/OUT] condition for matching, outputs *
1511 * event ids that match condition *
1512 * *
1513 * Return value: SUCCEED - supported operator *
1514 * NOTSUPPORTED - not supported operator *
1515 * *
1516 ******************************************************************************/
check_dhost_ip_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1517 static int check_dhost_ip_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1518 {
1519 char *sql = NULL;
1520 size_t sql_alloc = 0, i;
1521 DB_RESULT result;
1522 DB_ROW row;
1523 int objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE};
1524 zbx_vector_uint64_t objectids[2];
1525 zbx_uint64_t condition_value;
1526
1527 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
1528 return NOTSUPPORTED;
1529
1530 ZBX_STR2UINT64(condition_value, condition->value);
1531
1532 zbx_vector_uint64_create(&objectids[0]);
1533 zbx_vector_uint64_create(&objectids[1]);
1534
1535 get_object_ids_discovery(esc_events, objectids);
1536
1537 for (i = 0; i < (int)ARRSIZE(objects); i++)
1538 {
1539 size_t sql_offset = 0;
1540
1541 if (0 == objectids[i].values_num)
1542 continue;
1543
1544 if (EVENT_OBJECT_DHOST == objects[i])
1545 {
1546 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1547 "select distinct dhostid,ip"
1548 " from dservices"
1549 " where");
1550
1551 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dhostid", objectids[i].values,
1552 objectids[i].values_num);
1553 }
1554 else /* EVENT_OBJECT_DSERVICE */
1555 {
1556 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1557 "select distinct dserviceid,ip"
1558 " from dservices"
1559 " where");
1560
1561 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid",
1562 objectids[i].values, objectids[i].values_num);
1563 }
1564
1565 result = DBselect("%s", sql);
1566
1567 while (NULL != (row = DBfetch(result)))
1568 {
1569 zbx_uint64_t objectid;
1570
1571 ZBX_STR2UINT64(objectid, row[0]);
1572 switch (condition->op)
1573 {
1574 case CONDITION_OPERATOR_EQUAL:
1575 if (SUCCEED == ip_in_list(condition->value, row[1]))
1576 add_condition_match(esc_events, condition, objectid, objects[i]);
1577 break;
1578 case CONDITION_OPERATOR_NOT_EQUAL:
1579 if (SUCCEED != ip_in_list(condition->value, row[1]))
1580 add_condition_match(esc_events, condition, objectid, objects[i]);
1581 break;
1582 }
1583 }
1584 DBfree_result(result);
1585 }
1586
1587 zbx_vector_uint64_destroy(&objectids[0]);
1588 zbx_vector_uint64_destroy(&objectids[1]);
1589 zbx_free(sql);
1590
1591 return SUCCEED;
1592 }
1593
1594 /******************************************************************************
1595 * *
1596 * Function: check_dservice_type_condition *
1597 * *
1598 * Purpose: check service type condition for discovery event *
1599 * *
1600 * Parameters: esc_events - [IN] events to check *
1601 * condition - [IN/OUT] condition for matching, outputs *
1602 * event ids that match condition *
1603 * *
1604 * Return value: SUCCEED - supported operator *
1605 * NOTSUPPORTED - not supported operator *
1606 * *
1607 ******************************************************************************/
check_dservice_type_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1608 static int check_dservice_type_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1609 {
1610 char *sql = NULL;
1611 size_t sql_alloc = 0, sql_offset = 0;
1612 DB_RESULT result;
1613 DB_ROW row;
1614 int object = EVENT_OBJECT_DSERVICE;
1615 zbx_vector_uint64_t objectids;
1616 int i, condition_value_i;
1617
1618 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
1619 return NOTSUPPORTED;
1620
1621 condition_value_i = atoi(condition->value);
1622
1623 zbx_vector_uint64_create(&objectids);
1624
1625 for (i = 0; i < esc_events->values_num; i++)
1626 {
1627 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
1628
1629 if (object == event->object)
1630 zbx_vector_uint64_append(&objectids, event->objectid);
1631 }
1632
1633 if (0 != objectids.values_num)
1634 {
1635 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1636 "select ds.dserviceid,dc.type"
1637 " from dservices ds,dchecks dc"
1638 " where ds.dcheckid=dc.dcheckid"
1639 " and");
1640
1641 zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1642 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ds.dserviceid", objectids.values,
1643 objectids.values_num);
1644
1645 result = DBselect("%s", sql);
1646
1647 while (NULL != (row = DBfetch(result)))
1648 {
1649 zbx_uint64_t objectid;
1650 int tmp_int;
1651
1652 ZBX_STR2UINT64(objectid, row[0]);
1653 tmp_int = atoi(row[1]);
1654
1655 switch (condition->op)
1656 {
1657 case CONDITION_OPERATOR_EQUAL:
1658 if (condition_value_i == tmp_int)
1659 add_condition_match(esc_events, condition, objectid, object);
1660 break;
1661 case CONDITION_OPERATOR_NOT_EQUAL:
1662 if (condition_value_i != tmp_int)
1663 add_condition_match(esc_events, condition, objectid, object);
1664 break;
1665 }
1666 }
1667 DBfree_result(result);
1668 }
1669
1670 zbx_vector_uint64_destroy(&objectids);
1671 zbx_free(sql);
1672
1673 return SUCCEED;
1674 }
1675
1676 /******************************************************************************
1677 * *
1678 * Function: check_dstatus_condition *
1679 * *
1680 * Purpose: check discovery status condition *
1681 * *
1682 * Parameters: esc_events - [IN] events to check *
1683 * condition - [IN/OUT] condition for matching, outputs *
1684 * event ids that match condition *
1685 * *
1686 * Return value: SUCCEED - supported operator *
1687 * NOTSUPPORTED - not supported operator *
1688 * *
1689 ******************************************************************************/
check_dstatus_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1690 static int check_dstatus_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1691 {
1692 int i, condition_value_i = atoi(condition->value);
1693
1694 for (i = 0; i < esc_events->values_num; i++)
1695 {
1696 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
1697
1698 switch (condition->op)
1699 {
1700 case CONDITION_OPERATOR_EQUAL:
1701 if (condition_value_i == event->value)
1702 zbx_vector_uint64_append(&condition->eventids, event->eventid);
1703 break;
1704 case CONDITION_OPERATOR_NOT_EQUAL:
1705 if (condition_value_i != event->value)
1706 zbx_vector_uint64_append(&condition->eventids, event->eventid);
1707 break;
1708 default:
1709 return NOTSUPPORTED;
1710 }
1711 }
1712
1713 return SUCCEED;
1714 }
1715
1716 /******************************************************************************
1717 * *
1718 * Function: check_duptime_condition *
1719 * *
1720 * Purpose: check uptime condition for discovery *
1721 * *
1722 * Parameters: esc_events - [IN] events to check *
1723 * condition - [IN/OUT] condition for matching, outputs *
1724 * event ids that match condition *
1725 * *
1726 * Return value: SUCCEED - supported operator *
1727 * NOTSUPPORTED - not supported operator *
1728 * *
1729 ******************************************************************************/
check_duptime_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1730 static int check_duptime_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1731 {
1732 char *sql = NULL;
1733 size_t sql_alloc = 0, i;
1734 DB_RESULT result;
1735 DB_ROW row;
1736 int objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE};
1737 zbx_vector_uint64_t objectids[2];
1738 int condition_value_i;
1739
1740 if (CONDITION_OPERATOR_LESS_EQUAL != condition->op && CONDITION_OPERATOR_MORE_EQUAL != condition->op)
1741 return NOTSUPPORTED;
1742
1743 condition_value_i = atoi(condition->value);
1744
1745 zbx_vector_uint64_create(&objectids[0]);
1746 zbx_vector_uint64_create(&objectids[1]);
1747
1748 get_object_ids_discovery(esc_events, objectids);
1749
1750 for (i = 0; i < (int)ARRSIZE(objects); i++)
1751 {
1752 size_t sql_offset = 0;
1753
1754 if (0 == objectids[i].values_num)
1755 continue;
1756
1757 if (EVENT_OBJECT_DHOST == objects[i])
1758 {
1759 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1760 "select dhostid,status,lastup,lastdown"
1761 " from dhosts"
1762 " where");
1763
1764 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dhostid",
1765 objectids[i].values, objectids[i].values_num);
1766 }
1767 else /* EVENT_OBJECT_DSERVICE */
1768 {
1769 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1770 "select dserviceid,status,lastup,lastdown"
1771 " from dservices"
1772 " where");
1773
1774 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid",
1775 objectids[i].values, objectids[i].values_num);
1776 }
1777
1778 result = DBselect("%s", sql);
1779
1780 while (NULL != (row = DBfetch(result)))
1781 {
1782 zbx_uint64_t objectid;
1783 int now, tmp_int;
1784
1785 ZBX_STR2UINT64(objectid, row[0]);
1786
1787 now = time(NULL);
1788 tmp_int = DOBJECT_STATUS_UP == atoi(row[1]) ? atoi(row[2]) : atoi(row[3]);
1789
1790 switch (condition->op)
1791 {
1792 case CONDITION_OPERATOR_LESS_EQUAL:
1793 if (0 != tmp_int && (now - tmp_int) <= condition_value_i)
1794 add_condition_match(esc_events, condition, objectid, objects[i]);
1795 break;
1796 case CONDITION_OPERATOR_MORE_EQUAL:
1797 if (0 != tmp_int && (now - tmp_int) >= condition_value_i)
1798 add_condition_match(esc_events, condition, objectid, objects[i]);
1799 break;
1800 }
1801 }
1802 DBfree_result(result);
1803 }
1804
1805 zbx_vector_uint64_destroy(&objectids[0]);
1806 zbx_vector_uint64_destroy(&objectids[1]);
1807 zbx_free(sql);
1808
1809 return SUCCEED;
1810 }
1811
1812 /******************************************************************************
1813 * *
1814 * Function: check_dservice_port_condition *
1815 * *
1816 * Purpose: check service port condition for discovery *
1817 * *
1818 * Parameters: esc_events - [IN] events to check *
1819 * condition - [IN/OUT] condition for matching, outputs *
1820 * event ids that match condition *
1821 * *
1822 * Return value: SUCCEED - supported operator *
1823 * NOTSUPPORTED - not supported operator *
1824 * *
1825 ******************************************************************************/
check_dservice_port_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1826 static int check_dservice_port_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1827 {
1828 char *sql = NULL;
1829 size_t sql_alloc = 0, sql_offset = 0;
1830 DB_RESULT result;
1831 DB_ROW row;
1832 int object = EVENT_OBJECT_DSERVICE;
1833 zbx_vector_uint64_t objectids;
1834 int i;
1835
1836 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
1837 return NOTSUPPORTED;
1838
1839 zbx_vector_uint64_create(&objectids);
1840
1841 for (i = 0; i < esc_events->values_num; i++)
1842 {
1843 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
1844
1845 if (object == event->object)
1846 zbx_vector_uint64_append(&objectids, event->objectid);
1847 }
1848
1849 if (0 != objectids.values_num)
1850 {
1851 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1852 "select dserviceid,port"
1853 " from dservices"
1854 " where");
1855
1856 zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1857 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid", objectids.values,
1858 objectids.values_num);
1859
1860 result = DBselect("%s", sql);
1861
1862 while (NULL != (row = DBfetch(result)))
1863 {
1864 zbx_uint64_t objectid;
1865
1866 ZBX_STR2UINT64(objectid, row[0]);
1867 switch (condition->op)
1868 {
1869 case CONDITION_OPERATOR_EQUAL:
1870 if (SUCCEED == int_in_list(condition->value, atoi(row[1])))
1871 add_condition_match(esc_events, condition, objectid, object);
1872 break;
1873 case CONDITION_OPERATOR_NOT_EQUAL:
1874 if (SUCCEED != int_in_list(condition->value, atoi(row[1])))
1875 add_condition_match(esc_events, condition, objectid, object);
1876 break;
1877 }
1878 }
1879 DBfree_result(result);
1880 }
1881
1882 zbx_vector_uint64_destroy(&objectids);
1883 zbx_free(sql);
1884
1885 return SUCCEED;
1886 }
1887
1888 /******************************************************************************
1889 * *
1890 * Function: check_discovery_condition *
1891 * *
1892 * Purpose: check if event matches single condition *
1893 * *
1894 * Parameters: event - discovery event to check *
1895 * (event->source == EVENT_SOURCE_DISCOVERY) *
1896 * condition - condition for matching *
1897 * *
1898 * Return value: SUCCEED - matches, FAIL - otherwise *
1899 * *
1900 * Author: Alexei Vladishev *
1901 * *
1902 ******************************************************************************/
check_discovery_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1903 static void check_discovery_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1904 {
1905 int ret;
1906
1907 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1908
1909 switch (condition->conditiontype)
1910 {
1911 case CONDITION_TYPE_DRULE:
1912 ret = check_drule_condition(esc_events, condition);
1913 break;
1914 case CONDITION_TYPE_DCHECK:
1915 ret = check_dcheck_condition(esc_events, condition);
1916 break;
1917 case CONDITION_TYPE_DOBJECT:
1918 ret = check_dobject_condition(esc_events, condition);
1919 break;
1920 case CONDITION_TYPE_PROXY:
1921 ret = check_proxy_condition(esc_events, condition);
1922 break;
1923 case CONDITION_TYPE_DVALUE:
1924 ret = check_dvalue_condition(esc_events, condition);
1925 break;
1926 case CONDITION_TYPE_DHOST_IP:
1927 ret = check_dhost_ip_condition(esc_events, condition);
1928 break;
1929 case CONDITION_TYPE_DSERVICE_TYPE:
1930 ret = check_dservice_type_condition(esc_events, condition);
1931 break;
1932 case CONDITION_TYPE_DSTATUS:
1933 ret = check_dstatus_condition(esc_events, condition);
1934 break;
1935 case CONDITION_TYPE_DUPTIME:
1936 ret = check_duptime_condition(esc_events, condition);
1937 break;
1938 case CONDITION_TYPE_DSERVICE_PORT:
1939 ret = check_dservice_port_condition(esc_events, condition);
1940 break;
1941 default:
1942 ret = FAIL;
1943 zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
1944 (int)condition->conditiontype, condition->conditionid);
1945 }
1946
1947 if (NOTSUPPORTED == ret)
1948 {
1949 zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
1950 (int)condition->op, condition->conditionid);
1951 }
1952
1953 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
1954 }
1955
1956 /******************************************************************************
1957 * *
1958 * Function: check_hostname_metadata_condition *
1959 * *
1960 * Purpose: check metadata or host condition for auto registration *
1961 * *
1962 * Parameters: esc_events - [IN] events to check *
1963 * condition - [IN/OUT] condition for matching, outputs *
1964 * event ids that match condition *
1965 * *
1966 * Return value: SUCCEED - supported operator *
1967 * NOTSUPPORTED - not supported operator *
1968 * *
1969 ******************************************************************************/
check_hostname_metadata_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1970 static int check_hostname_metadata_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1971 {
1972 char *sql = NULL;
1973 size_t sql_alloc = 0, sql_offset = 0;
1974 DB_RESULT result;
1975 DB_ROW row;
1976 int object = EVENT_OBJECT_ZABBIX_ACTIVE;
1977 zbx_vector_uint64_t objectids;
1978 const char *condition_field;
1979
1980 switch(condition->op)
1981 {
1982 case CONDITION_OPERATOR_LIKE:
1983 case CONDITION_OPERATOR_NOT_LIKE:
1984 case CONDITION_OPERATOR_REGEXP:
1985 case CONDITION_OPERATOR_NOT_REGEXP:
1986 break;
1987 default:
1988 return NOTSUPPORTED;
1989 }
1990
1991 if (CONDITION_TYPE_HOST_NAME == condition->conditiontype)
1992 condition_field = "host";
1993 else
1994 condition_field = "host_metadata";
1995
1996 zbx_vector_uint64_create(&objectids);
1997 get_object_ids(esc_events, &objectids);
1998
1999 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2000 "select autoreg_hostid,%s"
2001 " from autoreg_host"
2002 " where",
2003 condition_field);
2004
2005 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "autoreg_hostid", objectids.values, objectids.values_num);
2006
2007 result = DBselect("%s", sql);
2008
2009 while (NULL != (row = DBfetch(result)))
2010 {
2011 zbx_uint64_t objectid;
2012
2013 ZBX_STR2UINT64(objectid, row[0]);
2014
2015 switch (condition->op)
2016 {
2017 case CONDITION_OPERATOR_LIKE:
2018 if (NULL != strstr(row[1], condition->value))
2019 add_condition_match(esc_events, condition, objectid, object);
2020 break;
2021 case CONDITION_OPERATOR_NOT_LIKE:
2022 if (NULL == strstr(row[1], condition->value))
2023 add_condition_match(esc_events, condition, objectid, object);
2024 break;
2025 case CONDITION_OPERATOR_REGEXP:
2026 if (NULL != zbx_regexp_match(row[1], condition->value, NULL))
2027 add_condition_match(esc_events, condition, objectid, object);
2028 break;
2029 case CONDITION_OPERATOR_NOT_REGEXP:
2030 if (NULL == zbx_regexp_match(row[1], condition->value, NULL))
2031 add_condition_match(esc_events, condition, objectid, object);
2032 break;
2033 }
2034 }
2035 DBfree_result(result);
2036
2037 zbx_vector_uint64_destroy(&objectids);
2038 zbx_free(sql);
2039
2040 return SUCCEED;
2041 }
2042
2043 /******************************************************************************
2044 * *
2045 * Function: check_areg_proxy_condition *
2046 * *
2047 * Purpose: check proxy condition for auto registration *
2048 * *
2049 * Parameters: esc_events - [IN] events to check *
2050 * condition - [IN/OUT] condition for matching, outputs *
2051 * event ids that match condition *
2052 * *
2053 * Return value: SUCCEED - supported operator *
2054 * NOTSUPPORTED - not supported operator *
2055 * *
2056 ******************************************************************************/
check_areg_proxy_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2057 static int check_areg_proxy_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2058 {
2059 char *sql = NULL;
2060 size_t sql_alloc = 0, sql_offset = 0;
2061 DB_RESULT result;
2062 DB_ROW row;
2063 int object = EVENT_OBJECT_ZABBIX_ACTIVE;
2064 zbx_vector_uint64_t objectids;
2065 zbx_uint64_t condition_value;
2066
2067 ZBX_STR2UINT64(condition_value, condition->value);
2068
2069 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
2070 return NOTSUPPORTED;
2071
2072 zbx_vector_uint64_create(&objectids);
2073 get_object_ids(esc_events, &objectids);
2074
2075 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2076 "select autoreg_hostid,proxy_hostid"
2077 " from autoreg_host"
2078 " where");
2079
2080 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "autoreg_hostid",
2081 objectids.values, objectids.values_num);
2082
2083 result = DBselect("%s", sql);
2084
2085 while (NULL != (row = DBfetch(result)))
2086 {
2087 zbx_uint64_t id;
2088 zbx_uint64_t objectid;
2089
2090 ZBX_STR2UINT64(objectid, row[0]);
2091 ZBX_DBROW2UINT64(id, row[1]);
2092
2093 switch (condition->op)
2094 {
2095 case CONDITION_OPERATOR_EQUAL:
2096 if (id == condition_value)
2097 add_condition_match(esc_events, condition, objectid, object);
2098 break;
2099 case CONDITION_OPERATOR_NOT_EQUAL:
2100 if (id != condition_value)
2101 add_condition_match(esc_events, condition, objectid, object);
2102 break;
2103 }
2104 }
2105 DBfree_result(result);
2106
2107 zbx_vector_uint64_destroy(&objectids);
2108 zbx_free(sql);
2109
2110 return SUCCEED;
2111 }
2112
2113 /******************************************************************************
2114 * *
2115 * Function: check_autoregistration_condition *
2116 * *
2117 * Purpose: check if event matches single condition *
2118 * *
2119 * Parameters: event - autoregistration event to check *
2120 * (event->source == EVENT_SOURCE_AUTOREGISTRATION) *
2121 * condition - condition for matching *
2122 * *
2123 * Return value: SUCCEED - matches, FAIL - otherwise *
2124 * *
2125 * Author: Alexei Vladishev *
2126 * *
2127 ******************************************************************************/
check_autoregistration_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2128 static void check_autoregistration_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2129 {
2130 const char *__function_name = "check_auto_registration_condition";
2131 int ret;
2132
2133 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2134
2135 switch (condition->conditiontype)
2136 {
2137 case CONDITION_TYPE_HOST_NAME:
2138 case CONDITION_TYPE_HOST_METADATA:
2139 ret = check_hostname_metadata_condition(esc_events, condition);
2140 break;
2141 case CONDITION_TYPE_PROXY:
2142 ret = check_areg_proxy_condition(esc_events, condition);
2143 break;
2144 default:
2145 zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
2146 (int)condition->conditiontype, condition->conditionid);
2147 ret = FAIL;
2148 }
2149
2150 if (NOTSUPPORTED == ret)
2151 {
2152 zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
2153 (int)condition->op, condition->conditionid);
2154 }
2155
2156 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2157 }
2158
2159 /******************************************************************************
2160 * *
2161 * Function: is_supported_event_object *
2162 * *
2163 * Purpose: not all event objects are supported for internal events *
2164 * *
2165 * Parameters: events - [IN] events to check *
2166 * *
2167 * Return value: SUCCEED - supported *
2168 * FAIL - not supported *
2169 * *
2170 ******************************************************************************/
is_supported_event_object(const DB_EVENT * event)2171 static int is_supported_event_object(const DB_EVENT *event)
2172 {
2173 return (EVENT_OBJECT_TRIGGER == event->object || EVENT_OBJECT_ITEM == event->object ||
2174 EVENT_OBJECT_LLDRULE == event->object) ? SUCCEED : FAIL;
2175 }
2176
2177 /******************************************************************************
2178 * *
2179 * Function: check_intern_event_type_condition *
2180 * *
2181 * Purpose: check event type condition for internal events *
2182 * *
2183 * Parameters: esc_events - [IN] events to check *
2184 * condition - [IN/OUT] condition for matching, outputs *
2185 * event ids that match condition *
2186 * *
2187 * Return value: SUCCEED - supported operator *
2188 * NOTSUPPORTED - not supported operator *
2189 * *
2190 ******************************************************************************/
check_intern_event_type_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2191 static int check_intern_event_type_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2192 {
2193 int i;
2194 zbx_uint64_t condition_value;
2195
2196 condition_value = atoi(condition->value);
2197
2198 for (i = 0; i < esc_events->values_num; i++)
2199 {
2200 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
2201
2202 if (FAIL == is_supported_event_object(event))
2203 {
2204 zabbix_log(LOG_LEVEL_ERR, "unsupported event object [%d] for condition id [" ZBX_FS_UI64 "]",
2205 event->object, condition->conditionid);
2206 continue;
2207 }
2208
2209 switch (condition_value)
2210 {
2211 case EVENT_TYPE_ITEM_NOTSUPPORTED:
2212 if (EVENT_OBJECT_ITEM == event->object && ITEM_STATE_NOTSUPPORTED == event->value)
2213 zbx_vector_uint64_append(&condition->eventids, event->eventid);
2214 break;
2215 case EVENT_TYPE_TRIGGER_UNKNOWN:
2216 if (EVENT_OBJECT_TRIGGER == event->object && TRIGGER_STATE_UNKNOWN == event->value)
2217 zbx_vector_uint64_append(&condition->eventids, event->eventid);
2218 break;
2219 case EVENT_TYPE_LLDRULE_NOTSUPPORTED:
2220 if (EVENT_OBJECT_LLDRULE == event->object && ITEM_STATE_NOTSUPPORTED == event->value)
2221 zbx_vector_uint64_append(&condition->eventids, event->eventid);
2222 break;
2223 default:
2224 return NOTSUPPORTED;
2225 }
2226 }
2227
2228 return SUCCEED;
2229 }
2230
2231 /******************************************************************************
2232 * *
2233 * Function: get_object_ids_internal *
2234 * *
2235 * Purpose: get objectids of escalation internal events *
2236 * *
2237 * Parameters: esc_events - [IN] events to check *
2238 * objectids - [OUT] event objectids to be used in condition *
2239 * allocation 2 vectors where first one is *
2240 * trigger object ids, second is rest *
2241 * objects - [IN] the array of event objects *
2242 * objects_num - [IN] the number of objects in objects array *
2243 * *
2244 ******************************************************************************/
get_object_ids_internal(const zbx_vector_ptr_t * esc_events,zbx_vector_uint64_t * objectids,const int * objects,const int objects_num)2245 static void get_object_ids_internal(const zbx_vector_ptr_t *esc_events, zbx_vector_uint64_t *objectids,
2246 const int *objects, const int objects_num)
2247 {
2248 int i, j;
2249
2250 for (i = 0; i < esc_events->values_num; i++)
2251 {
2252 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
2253
2254 for (j = 0; j < objects_num; j++)
2255 {
2256 if (event->object == objects[j])
2257 {
2258 zbx_vector_uint64_append(&objectids[j], event->objectid);
2259 break;
2260 }
2261 }
2262
2263 if (j == objects_num)
2264 zabbix_log(LOG_LEVEL_ERR, "unsupported event object [%d]", event->object);
2265 }
2266
2267 for (i = 0; i < objects_num; i++)
2268 zbx_vector_uint64_uniq(&objectids[i], ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2269 }
2270
2271 /******************************************************************************
2272 * *
2273 * Function: check_intern_host_group_condition *
2274 * *
2275 * Purpose: check host group condition for internal events *
2276 * *
2277 * Parameters: esc_events - [IN] events to check *
2278 * condition - [IN/OUT] condition for matching, outputs *
2279 * event ids that match condition *
2280 * *
2281 * Return value: SUCCEED - supported operator *
2282 * NOTSUPPORTED - not supported operator *
2283 * *
2284 ******************************************************************************/
check_intern_host_group_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2285 static int check_intern_host_group_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2286 {
2287 char *sql = NULL;
2288 size_t sql_alloc = 0, i;
2289 DB_RESULT result;
2290 DB_ROW row;
2291 int objects[3] = {EVENT_OBJECT_TRIGGER, EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE};
2292 zbx_vector_uint64_t objectids[3], groupids;
2293 zbx_uint64_t condition_value;
2294
2295 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
2296 return NOTSUPPORTED;
2297
2298 ZBX_STR2UINT64(condition_value, condition->value);
2299
2300 for (i = 0; i < (int)ARRSIZE(objects); i++)
2301 zbx_vector_uint64_create(&objectids[i]);
2302
2303 zbx_vector_uint64_create(&groupids);
2304
2305 get_object_ids_internal(esc_events, objectids, objects, (int)ARRSIZE(objects));
2306
2307 zbx_dc_get_nested_hostgroupids(&condition_value, 1, &groupids);
2308
2309 for (i = 0; i < (int)ARRSIZE(objects); i++)
2310 {
2311 size_t sql_offset = 0;
2312
2313 if (0 == objectids[i].values_num)
2314 continue;
2315
2316 if (EVENT_OBJECT_TRIGGER == objects[i])
2317 {
2318 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2319 "select distinct f.triggerid"
2320 " from hosts_groups hg,hosts h,items i,functions f"
2321 " where hg.hostid=h.hostid"
2322 " and h.hostid=i.hostid"
2323 " and i.itemid=f.itemid"
2324 " and");
2325
2326 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "f.triggerid", objectids[i].values,
2327 objectids[i].values_num);
2328 }
2329 else /* EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE */
2330 {
2331 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2332 "select distinct i.itemid"
2333 " from hosts_groups hg,hosts h,items i"
2334 " where hg.hostid=h.hostid"
2335 " and h.hostid=i.hostid"
2336 " and");
2337
2338 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.itemid",
2339 objectids[i].values, objectids[i].values_num);
2340 }
2341
2342 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and");
2343 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hg.groupid", groupids.values,
2344 groupids.values_num);
2345
2346 result = DBselect("%s", sql);
2347
2348 while (NULL != (row = DBfetch(result)))
2349 {
2350 zbx_uint64_t objectid;
2351
2352 ZBX_STR2UINT64(objectid, row[0]);
2353 if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
2354 {
2355 int index;
2356
2357 if (FAIL != (index = zbx_vector_uint64_search(&objectids[i], objectid,
2358 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2359 {
2360 zbx_vector_uint64_remove_noorder(&objectids[i], index);
2361 }
2362 }
2363 else
2364 add_condition_match(esc_events, condition, objectid, objects[i]);
2365 }
2366 DBfree_result(result);
2367 }
2368
2369 for (i = 0; i < (int)ARRSIZE(objects); i++)
2370 {
2371 if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
2372 {
2373 int j;
2374
2375 for (j = 0; j < objectids[i].values_num; j++)
2376 add_condition_match(esc_events, condition, objectids[i].values[j], objects[i]);
2377 }
2378
2379 zbx_vector_uint64_destroy(&objectids[i]);
2380 }
2381
2382 zbx_vector_uint64_destroy(&groupids);
2383 zbx_free(sql);
2384
2385 return SUCCEED;
2386 }
2387
2388 /******************************************************************************
2389 * *
2390 * Function: item_parents_sql_alloc *
2391 * *
2392 * Purpose: get parent id from item discovery *
2393 * *
2394 * Parameters: sql [IN/OUT] - allocated sql query *
2395 * sql_alloc [IN/OUT] - how much bytes allocated *
2396 * objectids_tmp [IN/OUT] - uses to allocate query, removes *
2397 * duplicates *
2398 * *
2399 ******************************************************************************/
item_parents_sql_alloc(char ** sql,size_t * sql_alloc,zbx_vector_uint64_t * objectids_tmp)2400 static void item_parents_sql_alloc(char **sql, size_t *sql_alloc, zbx_vector_uint64_t *objectids_tmp)
2401 {
2402 size_t sql_offset = 0;
2403
2404 zbx_snprintf_alloc(sql, sql_alloc, &sql_offset,
2405 "select i.itemid,id.parent_itemid"
2406 " from item_discovery id,items i"
2407 " where id.itemid=i.itemid"
2408 " and i.flags=%d"
2409 " and",
2410 ZBX_FLAG_DISCOVERY_CREATED);
2411
2412 DBadd_condition_alloc(sql, sql_alloc, &sql_offset, "i.itemid",
2413 objectids_tmp->values, objectids_tmp->values_num);
2414 }
2415
2416
2417
2418 /******************************************************************************
2419 * *
2420 * Function: check_intern_host_template_condition *
2421 * *
2422 * Purpose: check host template condition for internal events *
2423 * *
2424 * Parameters: esc_events - [IN] events to check *
2425 * condition - [IN/OUT] condition for matching, outputs *
2426 * event ids that match condition *
2427 * *
2428 * Return value: SUCCEED - supported operator *
2429 * NOTSUPPORTED - not supported operator *
2430 * *
2431 ******************************************************************************/
check_intern_host_template_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2432 static int check_intern_host_template_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2433 {
2434 char *sql = NULL;
2435 size_t sql_alloc = 0;
2436 DB_RESULT result;
2437 DB_ROW row;
2438 zbx_uint64_t condition_value;
2439 int i, j;
2440 int objects[3] = {EVENT_OBJECT_TRIGGER, EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE};
2441 zbx_vector_uint64_t objectids[3];
2442 zbx_vector_uint64_pair_t objectids_pair[3];
2443
2444 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
2445 return NOTSUPPORTED;
2446
2447 for (i = 0; i < (int)ARRSIZE(objects); i++)
2448 {
2449 zbx_vector_uint64_create(&objectids[i]);
2450 zbx_vector_uint64_pair_create(&objectids_pair[i]);
2451 }
2452
2453 get_object_ids_internal(esc_events, objectids, objects, (int)ARRSIZE(objects));
2454
2455 ZBX_STR2UINT64(condition_value, condition->value);
2456
2457 for (i = 0; i < (int)ARRSIZE(objects); i++)
2458 {
2459 zbx_vector_uint64_t *objectids_ptr = &objectids[i];
2460 zbx_vector_uint64_pair_t *objectids_pair_ptr = &objectids_pair[i];
2461
2462 if (0 == objectids_ptr->values_num)
2463 continue;
2464
2465 objectids_to_pair(objectids_ptr, objectids_pair_ptr);
2466
2467 if (EVENT_OBJECT_TRIGGER == objects[i])
2468 trigger_parents_sql_alloc(&sql, &sql_alloc, objectids_ptr);
2469 else /* EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE */
2470 item_parents_sql_alloc(&sql, &sql_alloc, objectids_ptr);
2471
2472 result = DBselect("%s", sql);
2473
2474 while (NULL != (row = DBfetch(result)))
2475 {
2476 zbx_uint64_pair_t pair;
2477
2478 ZBX_STR2UINT64(pair.first, row[0]);
2479
2480 if (FAIL != (j = zbx_vector_uint64_pair_search(objectids_pair_ptr, pair,
2481 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2482 {
2483 ZBX_STR2UINT64(objectids_pair_ptr->values[j].second, row[1]);
2484 }
2485 }
2486 DBfree_result(result);
2487
2488 check_object_hierarchy(objects[i], esc_events, objectids_ptr, objectids_pair_ptr, condition, condition_value,
2489 0 == i ?
2490 "select distinct t.triggerid,t.templateid,i.hostid"
2491 " from items i,functions f,triggers t"
2492 " where i.itemid=f.itemid"
2493 " and f.triggerid=t.templateid"
2494 " and" :
2495 "select distinct h.itemid,t.itemid,t.hostid"
2496 " from items t,items h"
2497 " where t.itemid=h.templateid"
2498 " and",
2499 0 == i ? "t.triggerid" : "h.itemid");
2500 }
2501
2502 for (i = 0; i < (int)ARRSIZE(objects); i++)
2503 {
2504 zbx_vector_uint64_destroy(&objectids[i]);
2505 zbx_vector_uint64_pair_destroy(&objectids_pair[i]);
2506 }
2507
2508 zbx_free(sql);
2509
2510 return SUCCEED;
2511 }
2512
2513 /******************************************************************************
2514 * *
2515 * Function: check_intern_host_condition *
2516 * *
2517 * Purpose: check host condition for internal events *
2518 * *
2519 * Parameters: esc_events - [IN] events to check *
2520 * condition - [IN/OUT] condition for matching, outputs *
2521 * event ids that match condition *
2522 * *
2523 * Return value: SUCCEED - supported operator *
2524 * NOTSUPPORTED - not supported operator *
2525 * *
2526 ******************************************************************************/
check_intern_host_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2527 static int check_intern_host_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2528 {
2529 char *sql = NULL, *operation, *operation_item;
2530 size_t sql_alloc = 0, i;
2531 DB_RESULT result;
2532 DB_ROW row;
2533 int objects[3] = {EVENT_OBJECT_TRIGGER, EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE};
2534 zbx_vector_uint64_t objectids[3];
2535 zbx_uint64_t condition_value;
2536
2537 if (CONDITION_OPERATOR_EQUAL == condition->op)
2538 {
2539 operation = " and";
2540 operation_item = " where";
2541 }
2542 else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
2543 {
2544 operation = " and not";
2545 operation_item = " where not";
2546 }
2547 else
2548 return NOTSUPPORTED;
2549
2550 ZBX_STR2UINT64(condition_value, condition->value);
2551
2552 for (i = 0; i < (int)ARRSIZE(objects); i++)
2553 zbx_vector_uint64_create(&objectids[i]);
2554
2555 get_object_ids_internal(esc_events, objectids, objects, (int)ARRSIZE(objects));
2556
2557 for (i = 0; i < (int)ARRSIZE(objects); i++)
2558 {
2559 size_t sql_offset = 0;
2560
2561 if (0 == objectids[i].values_num)
2562 continue;
2563
2564 if (EVENT_OBJECT_TRIGGER == objects[i])
2565 {
2566 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2567 "select distinct f.triggerid"
2568 " from items i,functions f"
2569 " where i.itemid=f.itemid"
2570 "%s i.hostid=" ZBX_FS_UI64
2571 " and",
2572 operation,
2573 condition_value);
2574
2575 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "f.triggerid",
2576 objectids[i].values, objectids[i].values_num);
2577 }
2578 else /* EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE */
2579 {
2580 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2581 "select itemid"
2582 " from items"
2583 "%s hostid=" ZBX_FS_UI64
2584 " and",
2585 operation_item,
2586 condition_value);
2587
2588 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
2589 objectids[i].values, objectids[i].values_num);
2590 }
2591
2592 result = DBselect("%s", sql);
2593
2594 while (NULL != (row = DBfetch(result)))
2595 {
2596 zbx_uint64_t objectid;
2597
2598 ZBX_STR2UINT64(objectid, row[0]);
2599 add_condition_match(esc_events, condition, objectid, objects[i]);
2600 }
2601 DBfree_result(result);
2602 }
2603
2604 for (i = 0; i < (int)ARRSIZE(objects); i++)
2605 zbx_vector_uint64_destroy(&objectids[i]);
2606
2607 zbx_free(sql);
2608
2609 return SUCCEED;
2610 }
2611
2612 /******************************************************************************
2613 * *
2614 * Function: check_intern_application_condition *
2615 * *
2616 * Purpose: check application condition for internal events *
2617 * *
2618 * Parameters: esc_events - [IN] events to check *
2619 * condition - [IN/OUT] condition for matching, outputs *
2620 * event ids that match condition *
2621 * *
2622 * Return value: SUCCEED - supported operator *
2623 * NOTSUPPORTED - not supported operator *
2624 * *
2625 ******************************************************************************/
check_intern_application_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2626 static int check_intern_application_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2627 {
2628 char *sql = NULL;
2629 size_t sql_alloc = 0;
2630 DB_RESULT result;
2631 DB_ROW row;
2632 int objects[3] = {EVENT_OBJECT_TRIGGER, EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE}, i, j;
2633 zbx_vector_uint64_t objectids[3];
2634 zbx_uint64_t objectid;
2635
2636 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_LIKE != condition->op &&
2637 CONDITION_OPERATOR_NOT_LIKE != condition->op)
2638 return NOTSUPPORTED;
2639
2640 for (i = 0; i < (int)ARRSIZE(objects); i++)
2641 zbx_vector_uint64_create(&objectids[i]);
2642
2643 get_object_ids_internal(esc_events, objectids, objects, (int)ARRSIZE(objects));
2644
2645 for (i = 0; i < (int)ARRSIZE(objects); i++)
2646 {
2647 size_t sql_offset = 0;
2648
2649 if (0 == objectids[i].values_num)
2650 continue;
2651
2652 if (EVENT_OBJECT_TRIGGER == objects[i])
2653 {
2654 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2655 "select distinct t.triggerid,a.name"
2656 " from applications a,items_applications i,functions f,triggers t"
2657 " where a.applicationid=i.applicationid"
2658 " and i.itemid=f.itemid"
2659 " and f.triggerid=t.triggerid"
2660 " and");
2661
2662 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.triggerid",
2663 objectids[i].values, objectids[i].values_num);
2664 }
2665 else /* EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE */
2666 {
2667 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2668 "select distinct i.itemid,a.name"
2669 " from applications a,items_applications i"
2670 " where a.applicationid=i.applicationid"
2671 " and");
2672
2673 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.itemid",
2674 objectids[i].values, objectids[i].values_num);
2675 }
2676
2677 result = DBselect("%s", sql);
2678
2679 switch (condition->op)
2680 {
2681 case CONDITION_OPERATOR_EQUAL:
2682 while (NULL != (row = DBfetch(result)))
2683 {
2684 if (0 == strcmp(row[1], condition->value))
2685 {
2686 ZBX_STR2UINT64(objectid, row[0]);
2687 add_condition_match(esc_events, condition, objectid, objects[i]);
2688 }
2689 }
2690 break;
2691 case CONDITION_OPERATOR_LIKE:
2692 while (NULL != (row = DBfetch(result)))
2693 {
2694 if (NULL != strstr(row[1], condition->value))
2695 {
2696 ZBX_STR2UINT64(objectid, row[0]);
2697 add_condition_match(esc_events, condition, objectid, objects[i]);
2698 }
2699 }
2700 break;
2701 case CONDITION_OPERATOR_NOT_LIKE:
2702 while (NULL != (row = DBfetch(result)))
2703 {
2704 if (NULL != strstr(row[1], condition->value))
2705 {
2706 ZBX_STR2UINT64(objectid, row[0]);
2707 if (FAIL != (j = zbx_vector_uint64_search(&objectids[i], objectid,
2708 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2709 {
2710 zbx_vector_uint64_remove_noorder(&objectids[i], j);
2711 }
2712 }
2713 }
2714
2715 for (j = 0; j < objectids[i].values_num; j++)
2716 add_condition_match(esc_events, condition, objectids[i].values[j], objects[i]);
2717 break;
2718 }
2719 DBfree_result(result);
2720 }
2721
2722 for (i = 0; i < (int)ARRSIZE(objects); i++)
2723 zbx_vector_uint64_destroy(&objectids[i]);
2724
2725 zbx_free(sql);
2726
2727 return SUCCEED;
2728 }
2729
2730 /******************************************************************************
2731 * *
2732 * Function: check_internal_condition *
2733 * *
2734 * Purpose: check if internal event matches single condition *
2735 * *
2736 * Parameters: event - [IN] trigger event to check *
2737 * condition - [IN] condition for matching *
2738 * *
2739 * Return value: SUCCEED - matches, FAIL - otherwise *
2740 * *
2741 ******************************************************************************/
check_internal_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2742 static void check_internal_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2743 {
2744 int ret;
2745
2746 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
2747
2748 switch (condition->conditiontype)
2749 {
2750 case CONDITION_TYPE_EVENT_TYPE:
2751 ret = check_intern_event_type_condition(esc_events, condition);
2752 break;
2753 case CONDITION_TYPE_HOST_GROUP:
2754 ret = check_intern_host_group_condition(esc_events, condition);
2755 break;
2756 case CONDITION_TYPE_HOST_TEMPLATE:
2757 ret = check_intern_host_template_condition(esc_events, condition);
2758 break;
2759 case CONDITION_TYPE_HOST:
2760 ret = check_intern_host_condition(esc_events, condition);
2761 break;
2762 case CONDITION_TYPE_APPLICATION:
2763 ret = check_intern_application_condition(esc_events, condition);
2764 break;
2765 default:
2766 ret = FAIL;
2767 zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
2768 (int)condition->conditiontype, condition->conditionid);
2769 }
2770
2771 if (NOTSUPPORTED == ret)
2772 {
2773 zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
2774 (int)condition->op, condition->conditionid);
2775 }
2776
2777
2778 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
2779 }
2780
2781 /******************************************************************************
2782 * *
2783 * Function: check_events_condition *
2784 * *
2785 * Purpose: check if multiple events matches single condition *
2786 * *
2787 * Parameters: esc_events - [IN] events to check *
2788 * source - [IN] specific event source that need checking *
2789 * condition - [IN/OUT] condition for matching, outputs *
2790 * event ids that match condition *
2791 * Author: Alexei Vladishev *
2792 * *
2793 ******************************************************************************/
check_events_condition(const zbx_vector_ptr_t * esc_events,unsigned char source,zbx_condition_t * condition)2794 static void check_events_condition(const zbx_vector_ptr_t *esc_events, unsigned char source, zbx_condition_t *condition)
2795 {
2796 zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " conditionid:" ZBX_FS_UI64 " cond.value:'%s'"
2797 " cond.value2:'%s'", __func__, condition->actionid, condition->conditionid,
2798 condition->value, condition->value2);
2799
2800 switch (source)
2801 {
2802 case EVENT_SOURCE_TRIGGERS:
2803 check_trigger_condition(esc_events, condition);
2804 break;
2805 case EVENT_SOURCE_DISCOVERY:
2806 check_discovery_condition(esc_events, condition);
2807 break;
2808 case EVENT_SOURCE_AUTOREGISTRATION:
2809 check_autoregistration_condition(esc_events, condition);
2810 break;
2811 case EVENT_SOURCE_INTERNAL:
2812 check_internal_condition(esc_events, condition);
2813 break;
2814 default:
2815 zabbix_log(LOG_LEVEL_ERR, "unsupported event source [%d] for condition id [" ZBX_FS_UI64 "]",
2816 source, condition->conditionid);
2817 }
2818
2819 zbx_vector_uint64_sort(&condition->eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2820 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
2821 }
2822
2823 /******************************************************************************
2824 * *
2825 * Function: check_action_condition *
2826 * *
2827 * Purpose: check if event matches single condition *
2828 * *
2829 * Parameters: event - event to check *
2830 * condition - condition for matching *
2831 * *
2832 * Return value: SUCCEED - matches, FAIL - otherwise *
2833 * *
2834 * Author: Alexei Vladishev *
2835 * *
2836 ******************************************************************************/
check_action_condition(const DB_EVENT * event,zbx_condition_t * condition)2837 int check_action_condition(const DB_EVENT *event, zbx_condition_t *condition)
2838 {
2839 int ret;
2840 zbx_vector_ptr_t esc_events;
2841
2842 zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " conditionid:" ZBX_FS_UI64 " cond.value:'%s'"
2843 " cond.value2:'%s'", __func__, condition->actionid, condition->conditionid,
2844 ZBX_NULL2STR(condition->value), ZBX_NULL2STR(condition->value2));
2845
2846 zbx_vector_ptr_create(&esc_events);
2847
2848 zbx_vector_ptr_append(&esc_events, (DB_EVENT *)event);
2849
2850 check_events_condition(&esc_events, event->source, condition);
2851
2852 ret = 0 != condition->eventids.values_num ? SUCCEED : FAIL;
2853
2854 zbx_vector_ptr_destroy(&esc_events);
2855
2856 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
2857
2858 return ret;
2859 }
2860
2861 /******************************************************************************
2862 * *
2863 * Function: check_action_conditions *
2864 * *
2865 * Purpose: check if action have to be processed for the event *
2866 * (check all conditions of the action) *
2867 * *
2868 * Parameters: eventid - [IN] the id of event that will be checked *
2869 * action - [IN] action for matching *
2870 * *
2871 * Return value: SUCCEED - matches, FAIL - otherwise *
2872 * *
2873 ******************************************************************************/
check_action_conditions(zbx_uint64_t eventid,const zbx_action_eval_t * action)2874 static int check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t *action)
2875 {
2876 zbx_condition_t *condition;
2877 int condition_result, ret = SUCCEED, id_len, i;
2878 unsigned char old_type = 0xff;
2879 char *expression = NULL, tmp[ZBX_MAX_UINT64_LEN + 2], *ptr, error[256];
2880 double eval_result;
2881
2882 zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " eventsource:%d", __func__,
2883 action->actionid, (int)action->eventsource);
2884
2885 if (CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype)
2886 expression = zbx_strdup(expression, action->formula);
2887
2888 for (i = 0; i < action->conditions.values_num; i++)
2889 {
2890 condition = (zbx_condition_t *)action->conditions.values[i];
2891
2892 if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype && old_type == condition->conditiontype &&
2893 SUCCEED == ret)
2894 {
2895 continue; /* short-circuit true OR condition block to the next AND condition */
2896 }
2897
2898 condition_result = FAIL == zbx_vector_uint64_bsearch(&condition->eventids, eventid,
2899 ZBX_DEFAULT_UINT64_COMPARE_FUNC) ? FAIL : SUCCEED;
2900
2901 zabbix_log(LOG_LEVEL_DEBUG, " conditionid:" ZBX_FS_UI64 " conditiontype:%d cond.value:'%s' "
2902 "cond.value2:'%s' result:%s", condition->conditionid, (int)condition->conditiontype,
2903 condition->value, condition->value2, zbx_result_string(condition_result));
2904
2905 switch (action->evaltype)
2906 {
2907 case CONDITION_EVAL_TYPE_AND_OR:
2908 if (old_type == condition->conditiontype) /* assume conditions are sorted by type */
2909 {
2910 if (SUCCEED == condition_result)
2911 ret = SUCCEED;
2912 }
2913 else
2914 {
2915 if (FAIL == ret)
2916 goto clean;
2917
2918 ret = condition_result;
2919 old_type = condition->conditiontype;
2920 }
2921
2922 break;
2923 case CONDITION_EVAL_TYPE_AND:
2924 if (FAIL == condition_result) /* break if any AND condition is FALSE */
2925 {
2926 ret = FAIL;
2927 goto clean;
2928 }
2929
2930 break;
2931 case CONDITION_EVAL_TYPE_OR:
2932 if (SUCCEED == condition_result) /* break if any OR condition is TRUE */
2933 {
2934 ret = SUCCEED;
2935 goto clean;
2936 }
2937 ret = FAIL;
2938
2939 break;
2940 case CONDITION_EVAL_TYPE_EXPRESSION:
2941 zbx_snprintf(tmp, sizeof(tmp), "{" ZBX_FS_UI64 "}", condition->conditionid);
2942 id_len = strlen(tmp);
2943
2944 for (ptr = expression; NULL != (ptr = strstr(ptr, tmp)); ptr += id_len)
2945 {
2946 *ptr = (SUCCEED == condition_result ? '1' : '0');
2947 memset(ptr + 1, ' ', id_len - 1);
2948 }
2949
2950 break;
2951 default:
2952 ret = FAIL;
2953 goto clean;
2954 }
2955 }
2956
2957 if (CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype)
2958 {
2959 if (SUCCEED == evaluate(&eval_result, expression, error, sizeof(error), NULL))
2960 ret = (SUCCEED != zbx_double_compare(eval_result, 0) ? SUCCEED : FAIL);
2961
2962 zbx_free(expression);
2963 }
2964 clean:
2965 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
2966
2967 return ret;
2968 }
2969
2970 /******************************************************************************
2971 * *
2972 * Function: execute_operations *
2973 * *
2974 * Purpose: execute host, group, template operations linked to the action *
2975 * *
2976 * Parameters: action - action to execute operations for *
2977 * *
2978 * Author: Alexei Vladishev *
2979 * *
2980 * Comments: for message, command operations see *
2981 * escalation_execute_operations(), *
2982 * escalation_execute_recovery_operations(). *
2983 * *
2984 ******************************************************************************/
execute_operations(const DB_EVENT * event,zbx_uint64_t actionid)2985 static void execute_operations(const DB_EVENT *event, zbx_uint64_t actionid)
2986 {
2987 DB_RESULT result;
2988 DB_ROW row;
2989 zbx_uint64_t groupid, templateid;
2990 zbx_vector_uint64_t lnk_templateids, del_templateids,
2991 new_groupids, del_groupids;
2992 int i;
2993
2994 zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64, __func__, actionid);
2995
2996 zbx_vector_uint64_create(&lnk_templateids);
2997 zbx_vector_uint64_create(&del_templateids);
2998 zbx_vector_uint64_create(&new_groupids);
2999 zbx_vector_uint64_create(&del_groupids);
3000
3001 result = DBselect(
3002 "select o.operationtype,g.groupid,t.templateid,oi.inventory_mode"
3003 " from operations o"
3004 " left join opgroup g on g.operationid=o.operationid"
3005 " left join optemplate t on t.operationid=o.operationid"
3006 " left join opinventory oi on oi.operationid=o.operationid"
3007 " where o.actionid=" ZBX_FS_UI64
3008 " order by o.operationid",
3009 actionid);
3010
3011 while (NULL != (row = DBfetch(result)))
3012 {
3013 int inventory_mode;
3014 unsigned char operationtype;
3015
3016 operationtype = (unsigned char)atoi(row[0]);
3017 ZBX_DBROW2UINT64(groupid, row[1]);
3018 ZBX_DBROW2UINT64(templateid, row[2]);
3019 inventory_mode = (SUCCEED == DBis_null(row[3]) ? 0 : atoi(row[3]));
3020
3021 switch (operationtype)
3022 {
3023 case OPERATION_TYPE_HOST_ADD:
3024 op_host_add(event);
3025 break;
3026 case OPERATION_TYPE_HOST_REMOVE:
3027 op_host_del(event);
3028 break;
3029 case OPERATION_TYPE_HOST_ENABLE:
3030 op_host_enable(event);
3031 break;
3032 case OPERATION_TYPE_HOST_DISABLE:
3033 op_host_disable(event);
3034 break;
3035 case OPERATION_TYPE_GROUP_ADD:
3036 if (0 != groupid)
3037 zbx_vector_uint64_append(&new_groupids, groupid);
3038 break;
3039 case OPERATION_TYPE_GROUP_REMOVE:
3040 if (0 != groupid)
3041 zbx_vector_uint64_append(&del_groupids, groupid);
3042 break;
3043 case OPERATION_TYPE_TEMPLATE_ADD:
3044 if (0 != templateid)
3045 {
3046 if (FAIL != (i = zbx_vector_uint64_search(&del_templateids, templateid,
3047 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
3048 {
3049 zbx_vector_uint64_remove(&del_templateids, i);
3050 }
3051
3052 zbx_vector_uint64_append(&lnk_templateids, templateid);
3053 }
3054 break;
3055 case OPERATION_TYPE_TEMPLATE_REMOVE:
3056 if (0 != templateid)
3057 {
3058 if (FAIL != (i = zbx_vector_uint64_search(&lnk_templateids, templateid,
3059 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
3060 {
3061 zbx_vector_uint64_remove(&lnk_templateids, i);
3062 }
3063
3064 zbx_vector_uint64_append(&del_templateids, templateid);
3065 }
3066 break;
3067 case OPERATION_TYPE_HOST_INVENTORY:
3068 op_host_inventory_mode(event, inventory_mode);
3069 break;
3070 default:
3071 ;
3072 }
3073 }
3074 DBfree_result(result);
3075
3076 if (0 != del_templateids.values_num)
3077 {
3078 zbx_vector_uint64_sort(&del_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3079 zbx_vector_uint64_uniq(&del_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3080 op_template_del(event, &del_templateids);
3081 }
3082
3083 if (0 != lnk_templateids.values_num)
3084 {
3085 zbx_vector_uint64_sort(&lnk_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3086 zbx_vector_uint64_uniq(&lnk_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3087 op_template_add(event, &lnk_templateids);
3088 }
3089
3090 if (0 != new_groupids.values_num)
3091 {
3092 zbx_vector_uint64_sort(&new_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3093 zbx_vector_uint64_uniq(&new_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3094 op_groups_add(event, &new_groupids);
3095 }
3096
3097 if (0 != del_groupids.values_num)
3098 {
3099 zbx_vector_uint64_sort(&del_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3100 zbx_vector_uint64_uniq(&del_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3101 op_groups_del(event, &del_groupids);
3102 }
3103
3104 zbx_vector_uint64_destroy(&del_groupids);
3105 zbx_vector_uint64_destroy(&new_groupids);
3106 zbx_vector_uint64_destroy(&del_templateids);
3107 zbx_vector_uint64_destroy(&lnk_templateids);
3108
3109 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3110 }
3111
3112 /* data structures used to create new and recover existing escalations */
3113
3114 typedef struct
3115 {
3116 zbx_uint64_t actionid;
3117 const DB_EVENT *event;
3118 }
3119 zbx_escalation_new_t;
3120
3121 /******************************************************************************
3122 * *
3123 * Function: is_recovery_event *
3124 * *
3125 * Purpose: checks if the event is recovery event *
3126 * *
3127 * Parameters: event - [IN] the event to check *
3128 * *
3129 * Return value: SUCCEED - the event is recovery event *
3130 * FAIL - otherwise *
3131 * *
3132 ******************************************************************************/
is_recovery_event(const DB_EVENT * event)3133 static int is_recovery_event(const DB_EVENT *event)
3134 {
3135 if (EVENT_SOURCE_TRIGGERS == event->source)
3136 {
3137 if (EVENT_OBJECT_TRIGGER == event->object && TRIGGER_VALUE_OK == event->value)
3138 return SUCCEED;
3139 }
3140 else if (EVENT_SOURCE_INTERNAL == event->source)
3141 {
3142 switch (event->object)
3143 {
3144 case EVENT_OBJECT_TRIGGER:
3145 if (TRIGGER_STATE_NORMAL == event->value)
3146 return SUCCEED;
3147 break;
3148 case EVENT_OBJECT_ITEM:
3149 if (ITEM_STATE_NORMAL == event->value)
3150 return SUCCEED;
3151 break;
3152 case EVENT_OBJECT_LLDRULE:
3153 if (ITEM_STATE_NORMAL == event->value)
3154 return SUCCEED;
3155 break;
3156 }
3157 }
3158
3159 return FAIL;
3160 }
3161
3162 /******************************************************************************
3163 * *
3164 * Function: is_escalation_event *
3165 * *
3166 * Purpose: to determine if event needs condition checks *
3167 * *
3168 * Parameters: event - [IN] event to validate *
3169 * *
3170 * Return value: SUCCEED - escalations possible for event *
3171 * FAIL - escalations not possible for event *
3172 * *
3173 ******************************************************************************/
is_escalation_event(const DB_EVENT * event)3174 static int is_escalation_event(const DB_EVENT *event)
3175 {
3176 /* OK events can't start escalations - skip them */
3177 if (SUCCEED == is_recovery_event(event))
3178 return FAIL;
3179
3180 if (0 != (event->flags & ZBX_FLAGS_DB_EVENT_NO_ACTION))
3181 return FAIL;
3182
3183 if (0 == (event->flags & ZBX_FLAGS_DB_EVENT_CREATE))
3184 return FAIL;
3185
3186 return SUCCEED;
3187 }
3188
3189 /******************************************************************************
3190 * *
3191 * Function: uniq_conditions_compare_func *
3192 * *
3193 * Purpose: compare to find equal conditions *
3194 * *
3195 * Parameters: d1 - [IN] condition structure to compare to d2 *
3196 * d2 - [IN] condition structure to compare to d1 *
3197 * *
3198 * Return value: 0 - equal *
3199 * not 0 - otherwise *
3200 * *
3201 ******************************************************************************/
uniq_conditions_compare_func(const void * d1,const void * d2)3202 static int uniq_conditions_compare_func(const void *d1, const void *d2)
3203 {
3204 const zbx_condition_t *condition1 = (const zbx_condition_t *)d1, *condition2 = (const zbx_condition_t *)d2;
3205 int ret;
3206
3207 ZBX_RETURN_IF_NOT_EQUAL(condition1->conditiontype, condition2->conditiontype);
3208 ZBX_RETURN_IF_NOT_EQUAL(condition1->op, condition2->op);
3209
3210 if (0 != (ret = strcmp(condition1->value, condition2->value)))
3211 return ret;
3212
3213 if (0 != (ret = strcmp(condition1->value2, condition2->value2)))
3214 return ret;
3215
3216 return 0;
3217 }
3218
3219 /******************************************************************************
3220 * *
3221 * Function: uniq_conditions_hash_func *
3222 * *
3223 * Purpose: generate hash based on condition values *
3224 * *
3225 * Parameters: data - [IN] condition structure *
3226 * *
3227 * *
3228 * Return value: hash is generated *
3229 * *
3230 ******************************************************************************/
uniq_conditions_hash_func(const void * data)3231 static zbx_hash_t uniq_conditions_hash_func(const void *data)
3232 {
3233 const zbx_condition_t *condition = (const zbx_condition_t *)data;
3234 zbx_hash_t hash;
3235
3236 hash = ZBX_DEFAULT_STRING_HASH_ALGO(condition->value, strlen(condition->value), ZBX_DEFAULT_HASH_SEED);
3237 hash = ZBX_DEFAULT_STRING_HASH_ALGO(condition->value2, strlen(condition->value2), hash);
3238 hash = ZBX_DEFAULT_STRING_HASH_ALGO((char *)&condition->conditiontype, 1, hash);
3239 hash = ZBX_DEFAULT_STRING_HASH_ALGO((char *)&condition->op, 1, hash);
3240
3241 return hash;
3242 }
3243
3244 /******************************************************************************
3245 * *
3246 * Function: get_escalation_events *
3247 * *
3248 * Purpose: add events that have escalation possible and skip others, also *
3249 * adds according to source *
3250 * *
3251 * Parameters: events - [IN] events to apply actions for *
3252 * events_num - [IN] number of events *
3253 * esc_events - [OUT] events that need condition checks *
3254 * *
3255 ******************************************************************************/
get_escalation_events(const zbx_vector_ptr_t * events,zbx_vector_ptr_t * esc_events)3256 static void get_escalation_events(const zbx_vector_ptr_t *events, zbx_vector_ptr_t *esc_events)
3257 {
3258 const DB_EVENT *event;
3259 int i;
3260
3261 for (i = 0; i < events->values_num; i++)
3262 {
3263 event = (DB_EVENT *)events->values[i];
3264 if (SUCCEED == is_escalation_event(event) && EVENT_SOURCE_COUNT > (size_t)event->source)
3265 zbx_vector_ptr_append(&esc_events[event->source], (void*)event);
3266 }
3267 }
3268
3269 /******************************************************************************
3270 * *
3271 * Function: db_condition_clean *
3272 * *
3273 * Purpose: cleans condition data structure *
3274 * *
3275 * Parameters: condition - [IN] the condition data to free *
3276 * *
3277 ******************************************************************************/
db_condition_clean(zbx_condition_t * condition)3278 static void db_condition_clean(zbx_condition_t *condition)
3279 {
3280 zbx_free(condition->value2);
3281 zbx_free(condition->value);
3282 zbx_vector_uint64_destroy(&condition->eventids);
3283 }
3284
3285 /******************************************************************************
3286 * *
3287 * Function: zbx_conditions_eval_clean *
3288 * *
3289 * Purpose: cleans condition data structures from hashset *
3290 * *
3291 * Parameters: uniq_conditions - [IN] hashset with data structures to clean *
3292 * *
3293 ******************************************************************************/
conditions_eval_clean(zbx_hashset_t * uniq_conditions)3294 static void conditions_eval_clean(zbx_hashset_t *uniq_conditions)
3295 {
3296 zbx_hashset_iter_t iter;
3297 zbx_condition_t *condition;
3298
3299 zbx_hashset_iter_reset(uniq_conditions, &iter);
3300
3301 while (NULL != (condition = (zbx_condition_t *)zbx_hashset_iter_next(&iter)))
3302 db_condition_clean(condition);
3303 }
3304
3305 /******************************************************************************
3306 * *
3307 * Function: zbx_action_eval_free *
3308 * *
3309 * Purpose: frees action evaluation data structure *
3310 * *
3311 * Parameters: action - [IN] the action evaluation to free *
3312 * *
3313 ******************************************************************************/
zbx_action_eval_free(zbx_action_eval_t * action)3314 static void zbx_action_eval_free(zbx_action_eval_t *action)
3315 {
3316 zbx_free(action->formula);
3317
3318 zbx_vector_ptr_destroy(&action->conditions);
3319
3320 zbx_free(action);
3321 }
3322
3323 /******************************************************************************
3324 * *
3325 * Function: prepare_actions_conditions_eval *
3326 * *
3327 * Purpose: make actions to point, to conditions from hashset, where all *
3328 * conditions are unique, this ensures that we don't double check *
3329 * same conditions. *
3330 * *
3331 * Parameters: actions - [IN/OUT] all conditions are added to hashset *
3332 * then cleaned, actions will now *
3333 * point to conditions from hashset. *
3334 * for custom expression also *
3335 * replaces formula *
3336 * uniq_conditions - [OUT] unique conditions that actions *
3337 * point to (several sources) *
3338 * *
3339 * Comments: The returned conditions must be freed with *
3340 * conditions_eval_clean() function later. *
3341 * *
3342 ******************************************************************************/
prepare_actions_conditions_eval(zbx_vector_ptr_t * actions,zbx_hashset_t * uniq_conditions)3343 static void prepare_actions_conditions_eval(zbx_vector_ptr_t *actions, zbx_hashset_t *uniq_conditions)
3344 {
3345 int i, j;
3346
3347 for (i = 0; i < actions->values_num; i++)
3348 {
3349 zbx_action_eval_t *action = actions->values[i];
3350
3351 for (j = 0; j < action->conditions.values_num; j++)
3352 {
3353 zbx_condition_t *uniq_condition = NULL, *condition = action->conditions.values[j];
3354
3355 if (EVENT_SOURCE_COUNT <= action->eventsource)
3356 {
3357 db_condition_clean(condition);
3358 }
3359 else if (NULL == (uniq_condition = zbx_hashset_search(&uniq_conditions[action->eventsource],
3360 condition)))
3361 {
3362 uniq_condition = zbx_hashset_insert(&uniq_conditions[action->eventsource],
3363 condition, sizeof(zbx_condition_t));
3364 }
3365 else
3366 {
3367 if (CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype)
3368 {
3369 char search[ZBX_MAX_UINT64_LEN + 2];
3370 char replace[ZBX_MAX_UINT64_LEN + 2];
3371 char *old_formula;
3372
3373 zbx_snprintf(search, sizeof(search), "{" ZBX_FS_UI64 "}",
3374 condition->conditionid);
3375 zbx_snprintf(replace, sizeof(replace), "{" ZBX_FS_UI64 "}",
3376 uniq_condition->conditionid);
3377
3378 old_formula = action->formula;
3379 action->formula = string_replace(action->formula, search, replace);
3380 zbx_free(old_formula);
3381 }
3382
3383 db_condition_clean(condition);
3384 }
3385
3386 zbx_free(action->conditions.values[j]);
3387 action->conditions.values[j] = uniq_condition;
3388 }
3389 }
3390 }
3391
3392 /******************************************************************************
3393 * *
3394 * Function: process_actions *
3395 * *
3396 * Purpose: process all actions of each event in a list *
3397 * *
3398 * Parameters: events - [IN] events to apply actions for *
3399 * closed_events - [IN] a vector of closed event data - *
3400 * (PROBLEM eventid, OK eventid) pairs. *
3401 * *
3402 ******************************************************************************/
process_actions(const zbx_vector_ptr_t * events,const zbx_vector_uint64_pair_t * closed_events)3403 void process_actions(const zbx_vector_ptr_t *events, const zbx_vector_uint64_pair_t *closed_events)
3404 {
3405 int i;
3406 zbx_vector_ptr_t actions;
3407 zbx_vector_ptr_t new_escalations;
3408 zbx_vector_uint64_pair_t rec_escalations;
3409 zbx_hashset_t uniq_conditions[EVENT_SOURCE_COUNT];
3410 zbx_vector_ptr_t esc_events[EVENT_SOURCE_COUNT];
3411 zbx_hashset_iter_t iter;
3412 zbx_condition_t *condition;
3413
3414 zabbix_log(LOG_LEVEL_DEBUG, "In %s() events_num:" ZBX_FS_SIZE_T, __func__, (zbx_fs_size_t)events->values_num);
3415
3416 zbx_vector_ptr_create(&new_escalations);
3417 zbx_vector_uint64_pair_create(&rec_escalations);
3418
3419 for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3420 {
3421 zbx_hashset_create(&uniq_conditions[i], 0, uniq_conditions_hash_func, uniq_conditions_compare_func);
3422 zbx_vector_ptr_create(&esc_events[i]);
3423 }
3424
3425 zbx_vector_ptr_create(&actions);
3426 zbx_dc_get_actions_eval(&actions, ZBX_ACTION_OPCLASS_NORMAL | ZBX_ACTION_OPCLASS_RECOVERY);
3427 prepare_actions_conditions_eval(&actions, uniq_conditions);
3428 get_escalation_events(events, esc_events);
3429
3430 for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3431 {
3432 if (0 == esc_events[i].values_num)
3433 continue;
3434
3435 zbx_vector_ptr_sort(&esc_events[i], compare_events);
3436
3437 zbx_hashset_iter_reset(&uniq_conditions[i], &iter);
3438
3439 while (NULL != (condition = (zbx_condition_t *)zbx_hashset_iter_next(&iter)))
3440 check_events_condition(&esc_events[i], i, condition);
3441 }
3442
3443 /* 1. All event sources: match PROBLEM events to action conditions, add them to 'new_escalations' list. */
3444 /* 2. EVENT_SOURCE_DISCOVERY, EVENT_SOURCE_AUTOREGISTRATION: execute operations (except command and message */
3445 /* operations) for events that match action conditions. */
3446 for (i = 0; i < events->values_num; i++)
3447 {
3448 int j;
3449 const DB_EVENT *event;
3450
3451 if (FAIL == is_escalation_event((event = (const DB_EVENT *)events->values[i])))
3452 continue;
3453
3454 for (j = 0; j < actions.values_num; j++)
3455 {
3456 zbx_action_eval_t *action = (zbx_action_eval_t *)actions.values[j];
3457
3458 if (action->eventsource != event->source)
3459 continue;
3460
3461 if (SUCCEED == check_action_conditions(event->eventid, action))
3462 {
3463 zbx_escalation_new_t *new_escalation;
3464
3465 /* command and message operations handled by escalators even for */
3466 /* EVENT_SOURCE_DISCOVERY and EVENT_SOURCE_AUTOREGISTRATION events */
3467 new_escalation = (zbx_escalation_new_t *)zbx_malloc(NULL, sizeof(zbx_escalation_new_t));
3468 new_escalation->actionid = action->actionid;
3469 new_escalation->event = event;
3470 zbx_vector_ptr_append(&new_escalations, new_escalation);
3471
3472 if (EVENT_SOURCE_DISCOVERY == event->source ||
3473 EVENT_SOURCE_AUTOREGISTRATION == event->source)
3474 {
3475 execute_operations(event, action->actionid);
3476 }
3477 }
3478 }
3479 }
3480
3481 for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3482 {
3483 zbx_vector_ptr_destroy(&esc_events[i]);
3484 conditions_eval_clean(&uniq_conditions[i]);
3485 zbx_hashset_destroy(&uniq_conditions[i]);
3486 }
3487
3488 zbx_vector_ptr_clear_ext(&actions, (zbx_clean_func_t)zbx_action_eval_free);
3489 zbx_vector_ptr_destroy(&actions);
3490
3491 /* 3. Find recovered escalations and store escalationids in 'rec_escalation' by OK eventids. */
3492 if (0 != closed_events->values_num)
3493 {
3494 char *sql = NULL;
3495 size_t sql_alloc = 0, sql_offset = 0;
3496 zbx_vector_uint64_t eventids;
3497 DB_ROW row;
3498 DB_RESULT result;
3499 int j, index;
3500
3501 zbx_vector_uint64_create(&eventids);
3502
3503 /* 3.1. Store PROBLEM eventids of recovered events in 'eventids'. */
3504 for (j = 0; j < closed_events->values_num; j++)
3505 zbx_vector_uint64_append(&eventids, closed_events->values[j].first);
3506
3507 /* 3.2. Select escalations that must be recovered. */
3508 zbx_vector_uint64_sort(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3509 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
3510 "select eventid,escalationid"
3511 " from escalations"
3512 " where");
3513
3514 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "eventid", eventids.values, eventids.values_num);
3515 result = DBselect("%s", sql);
3516
3517 zbx_vector_uint64_pair_reserve(&rec_escalations, eventids.values_num);
3518
3519 /* 3.3. Store the escalationids corresponding to the OK events in 'rec_escalations'. */
3520 while (NULL != (row = DBfetch(result)))
3521 {
3522 zbx_uint64_pair_t pair;
3523
3524 ZBX_STR2UINT64(pair.first, row[0]);
3525
3526 if (FAIL == (index = zbx_vector_uint64_pair_bsearch(closed_events, pair,
3527 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
3528 {
3529 THIS_SHOULD_NEVER_HAPPEN;
3530 continue;
3531 }
3532
3533 pair.second = closed_events->values[index].second;
3534 ZBX_DBROW2UINT64(pair.first, row[1]);
3535 zbx_vector_uint64_pair_append(&rec_escalations, pair);
3536 }
3537
3538 DBfree_result(result);
3539 zbx_free(sql);
3540 zbx_vector_uint64_destroy(&eventids);
3541 }
3542
3543 /* 4. Create new escalations in DB. */
3544 if (0 != new_escalations.values_num)
3545 {
3546 zbx_db_insert_t db_insert;
3547 int j;
3548
3549 zbx_db_insert_prepare(&db_insert, "escalations", "escalationid", "actionid", "status", "triggerid",
3550 "itemid", "eventid", "r_eventid", "acknowledgeid", NULL);
3551
3552 for (j = 0; j < new_escalations.values_num; j++)
3553 {
3554 zbx_uint64_t triggerid = 0, itemid = 0;
3555 zbx_escalation_new_t *new_escalation;
3556
3557 new_escalation = (zbx_escalation_new_t *)new_escalations.values[j];
3558
3559 switch (new_escalation->event->object)
3560 {
3561 case EVENT_OBJECT_TRIGGER:
3562 triggerid = new_escalation->event->objectid;
3563 break;
3564 case EVENT_OBJECT_ITEM:
3565 case EVENT_OBJECT_LLDRULE:
3566 itemid = new_escalation->event->objectid;
3567 break;
3568 }
3569
3570 zbx_db_insert_add_values(&db_insert, __UINT64_C(0), new_escalation->actionid,
3571 (int)ESCALATION_STATUS_ACTIVE, triggerid, itemid,
3572 new_escalation->event->eventid, __UINT64_C(0), __UINT64_C(0));
3573
3574 zbx_free(new_escalation);
3575 }
3576
3577 zbx_db_insert_autoincrement(&db_insert, "escalationid");
3578 zbx_db_insert_execute(&db_insert);
3579 zbx_db_insert_clean(&db_insert);
3580 }
3581
3582 /* 5. Modify recovered escalations in DB. */
3583 if (0 != rec_escalations.values_num)
3584 {
3585 char *sql = NULL;
3586 size_t sql_alloc = 0, sql_offset = 0;
3587 int j;
3588
3589 zbx_vector_uint64_pair_sort(&rec_escalations, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3590
3591 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
3592
3593 for (j = 0; j < rec_escalations.values_num; j++)
3594 {
3595 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3596 "update escalations set r_eventid=" ZBX_FS_UI64 ",nextcheck=0"
3597 " where escalationid=" ZBX_FS_UI64 ";\n",
3598 rec_escalations.values[j].second, rec_escalations.values[j].first);
3599
3600 DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
3601 }
3602
3603 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
3604
3605 if (16 < sql_offset) /* in ORACLE always present begin..end; */
3606 DBexecute("%s", sql);
3607
3608 zbx_free(sql);
3609 }
3610
3611 zbx_vector_uint64_pair_destroy(&rec_escalations);
3612 zbx_vector_ptr_destroy(&new_escalations);
3613
3614 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3615 }
3616
3617 /******************************************************************************
3618 * *
3619 * Function: process_actions_by_acknowledgements *
3620 * *
3621 * Purpose: process actions for each acknowledgement in the array *
3622 * *
3623 * Parameters: event_ack - [IN] vector for eventid/ackid pairs *
3624 * *
3625 ******************************************************************************/
process_actions_by_acknowledgements(const zbx_vector_ptr_t * ack_tasks)3626 int process_actions_by_acknowledgements(const zbx_vector_ptr_t *ack_tasks)
3627 {
3628 zbx_vector_ptr_t actions;
3629 zbx_hashset_t uniq_conditions[EVENT_SOURCE_COUNT];
3630 int i, j, k, processed_num = 0, knext = 0;
3631 zbx_vector_uint64_t eventids;
3632 zbx_ack_task_t *ack_task;
3633 zbx_vector_ptr_t ack_escalations, events;
3634 zbx_ack_escalation_t *ack_escalation;
3635 zbx_vector_ptr_t esc_events[EVENT_SOURCE_COUNT];
3636 zbx_hashset_iter_t iter;
3637 zbx_condition_t *condition;
3638
3639 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3640
3641 zbx_vector_ptr_create(&ack_escalations);
3642
3643 for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3644 {
3645 zbx_hashset_create(&uniq_conditions[i], 0, uniq_conditions_hash_func, uniq_conditions_compare_func);
3646 zbx_vector_ptr_create(&esc_events[i]);
3647 }
3648
3649 zbx_vector_ptr_create(&actions);
3650 zbx_dc_get_actions_eval(&actions, ZBX_ACTION_OPCLASS_ACKNOWLEDGE);
3651 prepare_actions_conditions_eval(&actions, uniq_conditions);
3652
3653 if (0 == actions.values_num)
3654 goto out;
3655
3656 zbx_vector_uint64_create(&eventids);
3657
3658 for (i = 0; i < ack_tasks->values_num; i++)
3659 {
3660 ack_task = (zbx_ack_task_t *)ack_tasks->values[i];
3661 zbx_vector_uint64_append(&eventids, ack_task->eventid);
3662 }
3663
3664 zbx_vector_uint64_sort(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3665 zbx_vector_uint64_uniq(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3666
3667 zbx_vector_ptr_create(&events);
3668
3669 zbx_db_get_events_by_eventids(&eventids, &events);
3670
3671 for (i = 0; i < events.values_num; i++)
3672 {
3673 DB_EVENT *event = (DB_EVENT *)events.values[i];
3674
3675 zbx_vector_ptr_append(&esc_events[event->source], (void*)event);
3676 }
3677
3678 for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3679 {
3680 if (0 == esc_events[i].values_num)
3681 continue;
3682
3683 zbx_vector_ptr_sort(&esc_events[i], compare_events);
3684
3685 zbx_hashset_iter_reset(&uniq_conditions[i], &iter);
3686
3687 while (NULL != (condition = (zbx_condition_t *)zbx_hashset_iter_next(&iter)))
3688 check_events_condition(&esc_events[i], i, condition);
3689 }
3690
3691 for (i = 0; i < eventids.values_num; i++)
3692 {
3693 int kcurr = knext;
3694 DB_EVENT *event = (DB_EVENT *)events.values[i];
3695
3696 while (knext < ack_tasks->values_num)
3697 {
3698 ack_task = (zbx_ack_task_t *)ack_tasks->values[knext];
3699 if (ack_task->eventid != event->eventid)
3700 break;
3701 knext++;
3702 }
3703
3704 if (0 == event->eventid || 0 == event->trigger.triggerid)
3705 continue;
3706
3707 for (j = 0; j < actions.values_num; j++)
3708 {
3709 zbx_action_eval_t *action = (zbx_action_eval_t *)actions.values[j];
3710
3711 if (action->eventsource != event->source)
3712 continue;
3713
3714 if (SUCCEED != check_action_conditions(event->eventid, action))
3715 continue;
3716
3717 for (k = kcurr; k < knext; k++)
3718 {
3719 ack_task = (zbx_ack_task_t *)ack_tasks->values[k];
3720
3721 ack_escalation = (zbx_ack_escalation_t *)zbx_malloc(NULL, sizeof(zbx_ack_escalation_t));
3722 ack_escalation->taskid = ack_task->taskid;
3723 ack_escalation->acknowledgeid = ack_task->acknowledgeid;
3724 ack_escalation->actionid = action->actionid;
3725 ack_escalation->eventid = event->eventid;
3726 ack_escalation->triggerid = event->trigger.triggerid;
3727 zbx_vector_ptr_append(&ack_escalations, ack_escalation);
3728 }
3729 }
3730 }
3731
3732 if (0 != ack_escalations.values_num)
3733 {
3734 zbx_db_insert_t db_insert;
3735
3736 zbx_db_insert_prepare(&db_insert, "escalations", "escalationid", "actionid", "status", "triggerid",
3737 "itemid", "eventid", "r_eventid", "acknowledgeid", NULL);
3738
3739 zbx_vector_ptr_sort(&ack_escalations, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
3740
3741 for (i = 0; i < ack_escalations.values_num; i++)
3742 {
3743 ack_escalation = (zbx_ack_escalation_t *)ack_escalations.values[i];
3744
3745 zbx_db_insert_add_values(&db_insert, __UINT64_C(0), ack_escalation->actionid,
3746 (int)ESCALATION_STATUS_ACTIVE, ack_escalation->triggerid, __UINT64_C(0),
3747 ack_escalation->eventid, __UINT64_C(0), ack_escalation->acknowledgeid);
3748 }
3749
3750 zbx_db_insert_autoincrement(&db_insert, "escalationid");
3751 zbx_db_insert_execute(&db_insert);
3752 zbx_db_insert_clean(&db_insert);
3753
3754 processed_num = ack_escalations.values_num;
3755 }
3756
3757 zbx_vector_ptr_clear_ext(&events, (zbx_clean_func_t)zbx_db_free_event);
3758 zbx_vector_ptr_destroy(&events);
3759
3760 zbx_vector_uint64_destroy(&eventids);
3761 out:
3762 for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3763 {
3764 zbx_vector_ptr_destroy(&esc_events[i]);
3765 conditions_eval_clean(&uniq_conditions[i]);
3766 zbx_hashset_destroy(&uniq_conditions[i]);
3767 }
3768
3769 zbx_vector_ptr_clear_ext(&actions, (zbx_clean_func_t)zbx_action_eval_free);
3770 zbx_vector_ptr_destroy(&actions);
3771
3772 zbx_vector_ptr_clear_ext(&ack_escalations, zbx_ptr_free);
3773 zbx_vector_ptr_destroy(&ack_escalations);
3774
3775 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() processed_num:%d", __func__, processed_num);
3776
3777 return processed_num;
3778 }
3779
3780 /******************************************************************************
3781 * *
3782 * Function: get_actions_info *
3783 * *
3784 * Purpose: reads actions from database *
3785 * *
3786 * Parameters: actionids - [IN] requested action ids *
3787 * actions - [OUT] the array of actions *
3788 * *
3789 * Comments: use 'free_db_action' function to release allocated memory *
3790 * *
3791 ******************************************************************************/
get_db_actions_info(zbx_vector_uint64_t * actionids,zbx_vector_ptr_t * actions)3792 void get_db_actions_info(zbx_vector_uint64_t *actionids, zbx_vector_ptr_t *actions)
3793 {
3794 DB_RESULT result;
3795 DB_ROW row;
3796 char *filter = NULL;
3797 size_t filter_alloc = 0, filter_offset = 0;
3798 DB_ACTION *action;
3799
3800 zbx_vector_uint64_sort(actionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3801 zbx_vector_uint64_uniq(actionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3802
3803 DBadd_condition_alloc(&filter, &filter_alloc, &filter_offset, "actionid", actionids->values,
3804 actionids->values_num);
3805
3806 result = DBselect("select actionid,name,status,eventsource,esc_period,pause_suppressed"
3807 " from actions"
3808 " where%s order by actionid", filter);
3809
3810 while (NULL != (row = DBfetch(result)))
3811 {
3812 char *tmp;
3813
3814 action = (DB_ACTION *)zbx_malloc(NULL, sizeof(DB_ACTION));
3815 ZBX_STR2UINT64(action->actionid, row[0]);
3816 ZBX_STR2UCHAR(action->status, row[2]);
3817 ZBX_STR2UCHAR(action->eventsource, row[3]);
3818
3819 tmp = zbx_strdup(NULL, row[4]);
3820 substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &tmp, MACRO_TYPE_COMMON,
3821 NULL, 0);
3822 if (SUCCEED != is_time_suffix(tmp, &action->esc_period, ZBX_LENGTH_UNLIMITED))
3823 {
3824 zabbix_log(LOG_LEVEL_WARNING, "Invalid default operation step duration \"%s\" for action"
3825 " \"%s\", using default value of 1 hour", tmp, row[1]);
3826 action->esc_period = SEC_PER_HOUR;
3827 }
3828 zbx_free(tmp);
3829
3830 ZBX_STR2UCHAR(action->pause_suppressed, row[5]);
3831 action->name = zbx_strdup(NULL, row[1]);
3832 action->recovery = ZBX_ACTION_RECOVERY_NONE;
3833
3834 zbx_vector_ptr_append(actions, action);
3835 }
3836 DBfree_result(result);
3837
3838 result = DBselect("select actionid from operations where recovery=%d and%s",
3839 ZBX_OPERATION_MODE_RECOVERY, filter);
3840
3841 while (NULL != (row = DBfetch(result)))
3842 {
3843 zbx_uint64_t actionid;
3844 int index;
3845
3846 ZBX_STR2UINT64(actionid, row[0]);
3847 if (FAIL != (index = zbx_vector_ptr_bsearch(actions, &actionid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
3848 {
3849 action = (DB_ACTION *)actions->values[index];
3850 action->recovery = ZBX_ACTION_RECOVERY_OPERATIONS;
3851 }
3852 }
3853 DBfree_result(result);
3854
3855 zbx_free(filter);
3856 }
3857
free_db_action(DB_ACTION * action)3858 void free_db_action(DB_ACTION *action)
3859 {
3860 zbx_free(action->name);
3861 zbx_free(action);
3862 }
3863