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