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
22 #include "cfg.h"
23 #include "pid.h"
24 #include "db.h"
25 #include "log.h"
26 #include "dbcache.h"
27 #include "zbxserver.h"
28 #include "daemon.h"
29 #include "zbxself.h"
30 #include "db.h"
31
32 #include "timer.h"
33
34 #define ZBX_TIMER_DELAY SEC_PER_MIN
35
36 extern unsigned char process_type, program_type;
37 extern int server_num, process_num;
38 extern int CONFIG_TIMER_FORKS;
39
40 /* trigger -> functions cache */
41 typedef struct
42 {
43 zbx_uint64_t triggerid;
44 zbx_vector_uint64_t functionids;
45 }
46 zbx_trigger_functions_t;
47
48 /* addition data for event maintenance calculations to pair with zbx_event_suppress_query_t */
49 typedef struct
50 {
51 zbx_uint64_t eventid;
52 zbx_vector_uint64_pair_t maintenances;
53 }
54 zbx_event_suppress_data_t;
55
56 /******************************************************************************
57 * *
58 * Function: log_host_maintenance_update *
59 * *
60 * Purpose: log host maintenance changes *
61 * *
62 ******************************************************************************/
log_host_maintenance_update(const zbx_host_maintenance_diff_t * diff)63 static void log_host_maintenance_update(const zbx_host_maintenance_diff_t* diff)
64 {
65 char *msg = NULL;
66 size_t msg_alloc = 0, msg_offset = 0;
67 int maintenance_off = 0;
68
69 if (0 != (diff->flags & ZBX_FLAG_HOST_MAINTENANCE_UPDATE_MAINTENANCE_STATUS))
70 {
71 if (HOST_MAINTENANCE_STATUS_ON == diff->maintenance_status)
72 {
73 zbx_snprintf_alloc(&msg, &msg_alloc, &msg_offset, "putting host (" ZBX_FS_UI64 ") into",
74 diff->hostid);
75 }
76 else
77 {
78 maintenance_off = 1;
79 zbx_snprintf_alloc(&msg, &msg_alloc, &msg_offset, "taking host (" ZBX_FS_UI64 ") out of",
80 diff->hostid);
81 }
82 }
83 else
84 zbx_snprintf_alloc(&msg, &msg_alloc, &msg_offset, "changing host (" ZBX_FS_UI64 ")", diff->hostid);
85
86 zbx_strcpy_alloc(&msg, &msg_alloc, &msg_offset, " maintenance");
87
88 if (0 != (diff->flags & ZBX_FLAG_HOST_MAINTENANCE_UPDATE_MAINTENANCEID) && 0 != diff->maintenanceid)
89 zbx_snprintf_alloc(&msg, &msg_alloc, &msg_offset, "(" ZBX_FS_UI64 ")", diff->maintenanceid);
90
91
92 if (0 != (diff->flags & ZBX_FLAG_HOST_MAINTENANCE_UPDATE_MAINTENANCE_TYPE) && 0 == maintenance_off)
93 {
94 const char *description[] = {"with data collection", "without data collection"};
95
96 zbx_snprintf_alloc(&msg, &msg_alloc, &msg_offset, " %s", description[diff->maintenance_type]);
97 }
98
99 zabbix_log(LOG_LEVEL_DEBUG, "%s", msg);
100 zbx_free(msg);
101 }
102
103 /******************************************************************************
104 * *
105 * Function: db_update_host_maintenances *
106 * *
107 * Purpose: update host maintenance properties in database *
108 * *
109 ******************************************************************************/
db_update_host_maintenances(const zbx_vector_ptr_t * updates)110 static void db_update_host_maintenances(const zbx_vector_ptr_t *updates)
111 {
112 int i;
113 const zbx_host_maintenance_diff_t *diff;
114 char *sql = NULL;
115 size_t sql_alloc = 0, sql_offset = 0;
116
117 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
118
119 for (i = 0; i < updates->values_num; i++)
120 {
121 char delim = ' ';
122
123 diff = (const zbx_host_maintenance_diff_t *)updates->values[i];
124
125 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update hosts set");
126
127 if (0 != (diff->flags & ZBX_FLAG_HOST_MAINTENANCE_UPDATE_MAINTENANCEID))
128 {
129 if (0 != diff->maintenanceid)
130 {
131 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%cmaintenanceid=" ZBX_FS_UI64, delim,
132 diff->maintenanceid);
133 }
134 else
135 {
136 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%cmaintenanceid=null", delim);
137 }
138
139 delim = ',';
140 }
141
142 if (0 != (diff->flags & ZBX_FLAG_HOST_MAINTENANCE_UPDATE_MAINTENANCE_TYPE))
143 {
144 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%cmaintenance_type=%u", delim,
145 diff->maintenance_type);
146 delim = ',';
147 }
148
149 if (0 != (diff->flags & ZBX_FLAG_HOST_MAINTENANCE_UPDATE_MAINTENANCE_STATUS))
150 {
151 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%cmaintenance_status=%u", delim,
152 diff->maintenance_status);
153 delim = ',';
154 }
155
156 if (0 != (diff->flags & ZBX_FLAG_HOST_MAINTENANCE_UPDATE_MAINTENANCE_FROM))
157 {
158 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%cmaintenance_from=%d", delim,
159 diff->maintenance_from);
160 }
161
162 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where hostid=" ZBX_FS_UI64 ";\n", diff->hostid);
163
164 if (SUCCEED != DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset))
165 break;
166
167 if (SUCCEED == ZBX_CHECK_LOG_LEVEL(LOG_LEVEL_DEBUG))
168 log_host_maintenance_update(diff);
169 }
170
171 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
172
173 if (16 < sql_offset)
174 DBexecute("%s", sql);
175
176 zbx_free(sql);
177 }
178
179 /******************************************************************************
180 * *
181 * Function: db_remove_expired_event_suppress_data *
182 * *
183 * Purpose: remove expired event_suppress records *
184 * *
185 ******************************************************************************/
db_remove_expired_event_suppress_data(int now)186 static void db_remove_expired_event_suppress_data(int now)
187 {
188 DBbegin();
189 DBexecute("delete from event_suppress where suppress_until<%d", now);
190 DBcommit();
191 }
192
193 /******************************************************************************
194 * *
195 * Function: event_suppress_data_free *
196 * *
197 * Purpose: free event suppress data structure *
198 * *
199 ******************************************************************************/
event_suppress_data_free(zbx_event_suppress_data_t * data)200 static void event_suppress_data_free(zbx_event_suppress_data_t *data)
201 {
202 zbx_vector_uint64_pair_destroy(&data->maintenances);
203 zbx_free(data);
204 }
205
206 /******************************************************************************
207 * *
208 * Function: event_queries_fetch *
209 * *
210 * Purpose: fetch events that need to be queried for maintenance *
211 * *
212 ******************************************************************************/
event_queries_fetch(DB_RESULT result,zbx_vector_ptr_t * event_queries)213 static void event_queries_fetch(DB_RESULT result, zbx_vector_ptr_t *event_queries)
214 {
215 DB_ROW row;
216 zbx_uint64_t eventid;
217 zbx_event_suppress_query_t *query = NULL;
218
219 while (NULL != (row = DBfetch(result)))
220 {
221 ZBX_STR2UINT64(eventid, row[0]);
222
223 if (NULL == query || eventid != query->eventid)
224 {
225 query = (zbx_event_suppress_query_t *)zbx_malloc(NULL, sizeof(zbx_event_suppress_query_t));
226
227 query->eventid = eventid;
228 ZBX_STR2UINT64(query->triggerid, row[1]);
229 ZBX_DBROW2UINT64(query->r_eventid, row[2]);
230 zbx_vector_uint64_create(&query->functionids);
231 zbx_vector_ptr_create(&query->tags);
232 zbx_vector_uint64_pair_create(&query->maintenances);
233 zbx_vector_ptr_append(event_queries, query);
234 }
235
236 if (FAIL == DBis_null(row[3]))
237 {
238 zbx_tag_t *tag;
239
240 tag = (zbx_tag_t *)zbx_malloc(NULL, sizeof(zbx_tag_t));
241 tag->tag = zbx_strdup(NULL, row[3]);
242 tag->value = zbx_strdup(NULL, row[4]);
243 zbx_vector_ptr_append(&query->tags, tag);
244
245 }
246 }
247 }
248
249 /******************************************************************************
250 * *
251 * Function: db_get_query_events *
252 * *
253 * Purpose: get open, recently resolved and resolved problems with suppress *
254 * data from database and prepare event query, event data structures *
255 * *
256 ******************************************************************************/
db_get_query_events(zbx_vector_ptr_t * event_queries,zbx_vector_ptr_t * event_data)257 static void db_get_query_events(zbx_vector_ptr_t *event_queries, zbx_vector_ptr_t *event_data)
258 {
259 DB_ROW row;
260 DB_RESULT result;
261 zbx_event_suppress_data_t *data = NULL;
262 zbx_uint64_t eventid;
263 zbx_uint64_pair_t pair;
264 zbx_vector_uint64_t eventids;
265
266 /* get open or recently closed problems */
267
268 result = DBselect("select p.eventid,p.objectid,p.r_eventid,t.tag,t.value"
269 " from problem p"
270 " left join problem_tag t"
271 " on p.eventid=t.eventid"
272 " where p.source=%d"
273 " and p.object=%d"
274 " and " ZBX_SQL_MOD(p.eventid, %d) "=%d"
275 " order by p.eventid",
276 EVENT_SOURCE_TRIGGERS, EVENT_OBJECT_TRIGGER, CONFIG_TIMER_FORKS, process_num - 1);
277
278 event_queries_fetch(result, event_queries);
279 DBfree_result(result);
280
281 /* get event suppress data */
282
283 zbx_vector_uint64_create(&eventids);
284
285 result = DBselect("select eventid,maintenanceid,suppress_until"
286 " from event_suppress"
287 " where " ZBX_SQL_MOD(eventid, %d) "=%d"
288 " order by eventid",
289 CONFIG_TIMER_FORKS, process_num - 1);
290
291 while (NULL != (row = DBfetch(result)))
292 {
293 ZBX_STR2UINT64(eventid, row[0]);
294
295 if (FAIL == zbx_vector_ptr_bsearch(event_queries, &eventid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC))
296 zbx_vector_uint64_append(&eventids, eventid);
297
298 if (NULL == data || data->eventid != eventid)
299 {
300 data = (zbx_event_suppress_data_t *)zbx_malloc(NULL, sizeof(zbx_event_suppress_data_t));
301 data->eventid = eventid;
302 zbx_vector_uint64_pair_create(&data->maintenances);
303 zbx_vector_ptr_append(event_data, data);
304 }
305
306 ZBX_DBROW2UINT64(pair.first, row[1]);
307 pair.second = atoi(row[2]);
308 zbx_vector_uint64_pair_append(&data->maintenances, pair);
309 }
310 DBfree_result(result);
311
312 /* get missing event data */
313
314 if (0 != eventids.values_num)
315 {
316 char *sql = NULL;
317 size_t sql_alloc = 0, sql_offset = 0;
318
319 zbx_vector_uint64_uniq(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
320
321 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
322 "select e.eventid,e.objectid,er.r_eventid,t.tag,t.value"
323 " from events e"
324 " left join event_recovery er"
325 " on e.eventid=er.eventid"
326 " left join problem_tag t"
327 " on e.eventid=t.eventid"
328 " where");
329 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "e.eventid", eventids.values, eventids.values_num);
330 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by e.eventid");
331
332 result = DBselect("%s", sql);
333 zbx_free(sql);
334
335 event_queries_fetch(result, event_queries);
336 DBfree_result(result);
337
338 zbx_vector_ptr_sort(event_queries, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
339 }
340
341 zbx_vector_uint64_destroy(&eventids);
342 }
343
344 /******************************************************************************
345 * *
346 * Function: db_get_query_functions *
347 * *
348 * Purpose: get event query functionids from database *
349 * *
350 ******************************************************************************/
db_get_query_functions(zbx_vector_ptr_t * event_queries)351 static void db_get_query_functions(zbx_vector_ptr_t *event_queries)
352 {
353 DB_ROW row;
354 DB_RESULT result;
355 int i;
356 zbx_vector_uint64_t triggerids;
357 zbx_hashset_t triggers;
358 zbx_hashset_iter_t iter;
359 char *sql = NULL;
360 size_t sql_alloc = 0, sql_offset = 0;
361 zbx_trigger_functions_t *trigger = NULL, trigger_local;
362 zbx_uint64_t triggerid, functionid;
363 zbx_event_suppress_query_t *query;
364
365 /* cache functionids by triggerids */
366
367 zbx_hashset_create(&triggers, 100, ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
368
369 zbx_vector_uint64_create(&triggerids);
370
371 for (i = 0; i < event_queries->values_num; i++)
372 {
373 query = (zbx_event_suppress_query_t *)event_queries->values[i];
374 zbx_vector_uint64_append(&triggerids, query->triggerid);
375 }
376
377 zbx_vector_uint64_sort(&triggerids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
378 zbx_vector_uint64_uniq(&triggerids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
379
380 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select functionid,triggerid from functions where");
381 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "triggerid", triggerids.values,
382 triggerids.values_num);
383 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by triggerid");
384
385 result = DBselect("%s", sql);
386 zbx_free(sql);
387
388 while (NULL != (row = DBfetch(result)))
389 {
390 ZBX_STR2UINT64(functionid, row[0]);
391 ZBX_STR2UINT64(triggerid, row[1]);
392
393 if (NULL == trigger || trigger->triggerid != triggerid)
394 {
395 trigger_local.triggerid = triggerid;
396 trigger = (zbx_trigger_functions_t *)zbx_hashset_insert(&triggers, &trigger_local,
397 sizeof(trigger_local));
398 zbx_vector_uint64_create(&trigger->functionids);
399 }
400 zbx_vector_uint64_append(&trigger->functionids, functionid);
401 }
402 DBfree_result(result);
403
404 /* copy functionids to event queries */
405
406 for (i = 0; i < event_queries->values_num; i++)
407 {
408 query = (zbx_event_suppress_query_t *)event_queries->values[i];
409
410 if (NULL == (trigger = (zbx_trigger_functions_t *)zbx_hashset_search(&triggers, &query->triggerid)))
411 continue;
412
413 zbx_vector_uint64_append_array(&query->functionids, trigger->functionids.values,
414 trigger->functionids.values_num);
415 }
416
417 zbx_hashset_iter_reset(&triggers, &iter);
418 while (NULL != (trigger = (zbx_trigger_functions_t *)zbx_hashset_iter_next(&iter)))
419 zbx_vector_uint64_destroy(&trigger->functionids);
420 zbx_hashset_destroy(&triggers);
421
422 zbx_vector_uint64_destroy(&triggerids);
423 }
424
425 /******************************************************************************
426 * *
427 * Function: db_update_event_suppress_data *
428 * *
429 * Purpose: create/update event suppress data to reflect latest maintenance *
430 * changes in cache *
431 * *
432 * Parameters: suppressed_num - [OUT] the number of suppressed events *
433 * *
434 ******************************************************************************/
db_update_event_suppress_data(int * suppressed_num)435 static void db_update_event_suppress_data(int *suppressed_num)
436 {
437 zbx_vector_ptr_t event_queries, event_data;
438
439 *suppressed_num = 0;
440
441 zbx_vector_ptr_create(&event_queries);
442 zbx_vector_ptr_create(&event_data);
443
444 db_get_query_events(&event_queries, &event_data);
445
446 if (0 != event_queries.values_num)
447 {
448 zbx_db_insert_t db_insert;
449 char *sql = NULL;
450 size_t sql_alloc = 0, sql_offset = 0;
451 int i, j, k;
452 zbx_event_suppress_query_t *query;
453 zbx_event_suppress_data_t *data;
454 zbx_vector_uint64_pair_t del_event_maintenances;
455 zbx_vector_uint64_t maintenanceids;
456 zbx_uint64_pair_t pair;
457
458 zbx_vector_uint64_create(&maintenanceids);
459 zbx_vector_uint64_pair_create(&del_event_maintenances);
460
461 db_get_query_functions(&event_queries);
462
463 zbx_dc_get_running_maintenanceids(&maintenanceids);
464
465 DBbegin();
466
467 if (0 != maintenanceids.values_num && SUCCEED == zbx_db_lock_maintenanceids(&maintenanceids))
468 zbx_dc_get_event_maintenances(&event_queries, &maintenanceids);
469
470 zbx_db_insert_prepare(&db_insert, "event_suppress", "event_suppressid", "eventid", "maintenanceid",
471 "suppress_until", NULL);
472 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
473
474 for (i = 0; i < event_queries.values_num; i++)
475 {
476 query = (zbx_event_suppress_query_t *)event_queries.values[i];
477 zbx_vector_uint64_pair_sort(&query->maintenances, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
478
479 k = 0;
480
481 if (FAIL != (j = zbx_vector_ptr_bsearch(&event_data, &query->eventid,
482 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
483 {
484 data = (zbx_event_suppress_data_t *)event_data.values[j];
485 zbx_vector_uint64_pair_sort(&data->maintenances, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
486
487 j = 0;
488
489 while (j < data->maintenances.values_num && k < query->maintenances.values_num)
490 {
491 if (data->maintenances.values[j].first < query->maintenances.values[k].first)
492 {
493 pair.first = query->eventid;
494 pair.second = data->maintenances.values[j].first;
495 zbx_vector_uint64_pair_append(&del_event_maintenances, pair);
496
497 j++;
498 continue;
499 }
500
501 if (data->maintenances.values[j].first > query->maintenances.values[k].first)
502 {
503 if (0 == query->r_eventid)
504 {
505 zbx_db_insert_add_values(&db_insert, __UINT64_C(0),
506 query->eventid,
507 query->maintenances.values[k].first,
508 (int)query->maintenances.values[k].second);
509
510 (*suppressed_num)++;
511 }
512
513 k++;
514 continue;
515 }
516
517 if (data->maintenances.values[j].second != query->maintenances.values[k].second)
518 {
519 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
520 "update event_suppress"
521 " set suppress_until=%d"
522 " where eventid=" ZBX_FS_UI64
523 " and maintenanceid=" ZBX_FS_UI64 ";\n",
524 (int)query->maintenances.values[k].second,
525 query->eventid,
526 query->maintenances.values[k].first);
527
528 if (FAIL == DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset))
529 goto cleanup;
530 }
531 j++;
532 k++;
533 }
534
535 for (;j < data->maintenances.values_num; j++)
536 {
537 pair.first = query->eventid;
538 pair.second = data->maintenances.values[j].first;
539 zbx_vector_uint64_pair_append(&del_event_maintenances, pair);
540 }
541 }
542
543 if (0 == query->r_eventid)
544 {
545 for (;k < query->maintenances.values_num; k++)
546 {
547 zbx_db_insert_add_values(&db_insert, __UINT64_C(0), query->eventid,
548 query->maintenances.values[k].first,
549 (int)query->maintenances.values[k].second);
550
551 (*suppressed_num)++;
552 }
553 }
554 }
555
556 for (i = 0; i < del_event_maintenances.values_num; i++)
557 {
558 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
559 "delete from event_suppress"
560 " where eventid=" ZBX_FS_UI64
561 " and maintenanceid=" ZBX_FS_UI64 ";\n",
562 del_event_maintenances.values[i].first,
563 del_event_maintenances.values[i].second);
564
565 if (FAIL == DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset))
566 goto cleanup;
567 }
568
569 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
570
571 if (16 < sql_offset)
572 {
573 if (ZBX_DB_OK > DBexecute("%s", sql))
574 goto cleanup;
575 }
576
577 zbx_db_insert_autoincrement(&db_insert, "event_suppressid");
578 zbx_db_insert_execute(&db_insert);
579 cleanup:
580 DBcommit();
581
582 zbx_db_insert_clean(&db_insert);
583 zbx_free(sql);
584
585 zbx_vector_uint64_pair_destroy(&del_event_maintenances);
586 zbx_vector_uint64_destroy(&maintenanceids);
587 }
588
589 zbx_vector_ptr_clear_ext(&event_data, (zbx_clean_func_t)event_suppress_data_free);
590 zbx_vector_ptr_destroy(&event_data);
591
592 zbx_vector_ptr_clear_ext(&event_queries, (zbx_clean_func_t)zbx_event_suppress_query_free);
593 zbx_vector_ptr_destroy(&event_queries);
594 }
595
596 /******************************************************************************
597 * *
598 * Function: db_update_host_maintenances *
599 * *
600 * Purpose: update host maintenance parameters in cache and database *
601 * *
602 ******************************************************************************/
update_host_maintenances(void)603 static int update_host_maintenances(void)
604 {
605 zbx_vector_uint64_t maintenanceids;
606 zbx_vector_ptr_t updates;
607 int hosts_num = 0;
608 int tnx_error;
609
610 zbx_vector_uint64_create(&maintenanceids);
611 zbx_vector_ptr_create(&updates);
612 zbx_vector_ptr_reserve(&updates, 100);
613
614 do
615 {
616 DBbegin();
617
618 if (SUCCEED == zbx_dc_get_running_maintenanceids(&maintenanceids))
619 zbx_db_lock_maintenanceids(&maintenanceids);
620
621 /* host maintenance update must be called even with no maintenances running */
622 /* to reset host maintenance status if necessary */
623 zbx_dc_get_host_maintenance_updates(&maintenanceids, &updates);
624
625 if (0 != updates.values_num)
626 db_update_host_maintenances(&updates);
627
628 if (ZBX_DB_OK == (tnx_error = DBcommit()) && 0 != (hosts_num = updates.values_num))
629 zbx_dc_flush_host_maintenance_updates(&updates);
630
631 zbx_vector_ptr_clear_ext(&updates, (zbx_clean_func_t)zbx_ptr_free);
632 zbx_vector_uint64_clear(&maintenanceids);
633 }
634 while (ZBX_DB_DOWN == tnx_error);
635
636 zbx_vector_ptr_destroy(&updates);
637 zbx_vector_uint64_destroy(&maintenanceids);
638
639 return hosts_num;
640 }
641
642 /******************************************************************************
643 * *
644 * Function: timer_thread *
645 * *
646 * Purpose: periodically processes maintenance *
647 * *
648 ******************************************************************************/
ZBX_THREAD_ENTRY(timer_thread,args)649 ZBX_THREAD_ENTRY(timer_thread, args)
650 {
651 double sec = 0.0;
652 int maintenance_time = 0, update_time = 0, idle = 1, events_num, hosts_num, update;
653 char *info = NULL;
654 size_t info_alloc = 0, info_offset = 0;
655
656 process_type = ((zbx_thread_args_t *)args)->process_type;
657 server_num = ((zbx_thread_args_t *)args)->server_num;
658 process_num = ((zbx_thread_args_t *)args)->process_num;
659
660 zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type),
661 server_num, get_process_type_string(process_type), process_num);
662
663 update_selfmon_counter(ZBX_PROCESS_STATE_BUSY);
664
665 zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num);
666 zbx_strcpy_alloc(&info, &info_alloc, &info_offset, "started");
667
668 DBconnect(ZBX_DB_CONNECT_NORMAL);
669
670 while (ZBX_IS_RUNNING())
671 {
672 sec = zbx_time();
673 zbx_update_env(sec);
674
675 if (1 == process_num)
676 {
677 /* start update process only when all timers have finished their updates */
678 if (sec - maintenance_time >= ZBX_TIMER_DELAY && FAIL == zbx_dc_maintenance_check_update_flags())
679 {
680 zbx_setproctitle("%s #%d [%s, processing maintenances]",
681 get_process_type_string(process_type), process_num, info);
682
683 update = zbx_dc_update_maintenances();
684
685 /* force maintenance updates at server startup */
686 if (0 == maintenance_time)
687 update = SUCCEED;
688
689 /* update hosts if there are modified (stopped, started, changed) maintenances */
690 if (SUCCEED == update)
691 hosts_num = update_host_maintenances();
692 else
693 hosts_num = 0;
694
695 db_remove_expired_event_suppress_data((int)sec);
696
697 if (SUCCEED == update)
698 {
699 zbx_dc_maintenance_set_update_flags();
700 db_update_event_suppress_data(&events_num);
701 zbx_dc_maintenance_reset_update_flag(process_num);
702 }
703 else
704 events_num = 0;
705
706 info_offset = 0;
707 zbx_snprintf_alloc(&info, &info_alloc, &info_offset,
708 "updated %d hosts, suppressed %d events in " ZBX_FS_DBL " sec",
709 hosts_num, events_num, zbx_time() - sec);
710
711 update_time = (int)sec;
712 }
713 }
714 else if (SUCCEED == zbx_dc_maintenance_check_update_flag(process_num))
715 {
716 zbx_setproctitle("%s #%d [%s, processing maintenances]", get_process_type_string(process_type),
717 process_num, info);
718
719 db_update_event_suppress_data(&events_num);
720
721 info_offset = 0;
722 zbx_snprintf_alloc(&info, &info_alloc, &info_offset, "suppressed %d events in " ZBX_FS_DBL
723 " sec", events_num, zbx_time() - sec);
724
725 update_time = (int)sec;
726 zbx_dc_maintenance_reset_update_flag(process_num);
727 }
728
729 if (maintenance_time != update_time)
730 {
731 update_time -= update_time % 60;
732 maintenance_time = update_time;
733
734 if (0 > (idle = ZBX_TIMER_DELAY - (zbx_time() - maintenance_time)))
735 idle = 0;
736
737 zbx_setproctitle("%s #%d [%s, idle %d sec]",
738 get_process_type_string(process_type), process_num, info, idle);
739 }
740
741 if (0 != idle)
742 zbx_sleep_loop(1);
743
744 idle = 1;
745 }
746
747 zbx_setproctitle("%s #%d [terminated]", get_process_type_string(process_type), process_num);
748
749 while (1)
750 zbx_sleep(SEC_PER_MIN);
751 }
752