ZBX_THREAD_ENTRY(listener_thread, args) { int ret, local_request_failed = 0; zbx_sock_t s; assert(args); assert(((zbx_thread_args_t *)args)->args); process_type = ((zbx_thread_args_t *)args)->process_type; server_num = ((zbx_thread_args_t *)args)->server_num; process_num = ((zbx_thread_args_t *)args)->process_num; zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_daemon_type_string(daemon_type), server_num, get_process_type_string(process_type), process_num); memcpy(&s, (zbx_sock_t *)((zbx_thread_args_t *)args)->args, sizeof(zbx_sock_t)); zbx_free(args); while (ZBX_IS_RUNNING()) { zbx_setproctitle("listener #%d [waiting for connection]", process_num); if (SUCCEED == (ret = zbx_tcp_accept(&s))) { local_request_failed = 0; /* reset consecutive errors counter */ zbx_setproctitle("listener #%d [processing request]", process_num); if (SUCCEED == (ret = zbx_tcp_check_security(&s, CONFIG_HOSTS_ALLOWED, 0))) process_listener(&s); zbx_tcp_unaccept(&s); } if (SUCCEED == ret || EINTR == zbx_sock_last_error()) continue; zabbix_log(LOG_LEVEL_DEBUG, "failed to accept an incoming connection: %s", zbx_tcp_strerror()); if (local_request_failed++ > 1000) { zabbix_log(LOG_LEVEL_WARNING, "too many failures to accept an incoming connection"); local_request_failed = 0; } if (ZBX_IS_RUNNING()) zbx_sleep(1); } #ifdef _WINDOWS ZBX_DO_EXIT(); zbx_thread_exit(EXIT_SUCCESS); #endif }
/****************************************************************************** * * * Function: main_watchdog_loop * * * * Purpose: check database availability every DB_PING_FREQUENCY seconds and * * alert admins if it is down * * * * Author: Alexei Vladishev, Rudolfs Kreicbergs * * * ******************************************************************************/ ZBX_THREAD_ENTRY(watchdog_thread, args) { int now, nextsync = 0, action; double sec; process_type = ((zbx_thread_args_t *)args)->process_type; server_num = ((zbx_thread_args_t *)args)->server_num; process_num = ((zbx_thread_args_t *)args)->process_num; zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_daemon_type_string(daemon_type), server_num, get_process_type_string(process_type), process_num); zbx_vector_ptr_create(&recipients); for (;;) { zbx_setproctitle("%s [pinging database]", get_process_type_string(process_type)); sec = zbx_time(); action = 0; if (ZBX_DB_OK != DBconnect(ZBX_DB_CONNECT_ONCE)) { zabbix_log(LOG_LEVEL_WARNING, "watchdog: database is down"); send_alerts(); action = 1; } else if (nextsync <= (now = (int)time(NULL))) { zbx_setproctitle("%s [syncing configuration]", get_process_type_string(process_type)); sync_config(); nextsync = now + CONFIG_CONFSYNCER_FREQUENCY; action = 2; } DBclose(); sec = zbx_time() - sec; if (1 == action) { zbx_setproctitle("%s [database is down, checking took " ZBX_FS_DBL " sec, idle %d sec]", get_process_type_string(process_type), sec, (int)DB_PING_FREQUENCY); } else if (2 == action) { zbx_setproctitle("%s [synced alerts config in " ZBX_FS_DBL " sec, idle %d sec]", get_process_type_string(process_type), sec, (int)DB_PING_FREQUENCY); } zbx_sleep_loop(DB_PING_FREQUENCY); } }
/****************************************************************************** * * * Function: main_snmptrapper_loop * * * * Purpose: SNMP trap reader's entry point * * * * Author: Rudolfs Kreicbergs * * * ******************************************************************************/ ZBX_THREAD_ENTRY(snmptrapper_thread, args) { const char *__function_name = "main_snmptrapper_loop"; double sec; process_type = ((zbx_thread_args_t *)args)->process_type; server_num = ((zbx_thread_args_t *)args)->server_num; process_num = ((zbx_thread_args_t *)args)->process_num; zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_daemon_type_string(daemon_type), server_num, get_process_type_string(process_type), process_num); zabbix_log(LOG_LEVEL_DEBUG, "In %s() trapfile:'%s'", __function_name, CONFIG_SNMPTRAP_FILE); zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type)); DBconnect(ZBX_DB_CONNECT_NORMAL); DBget_lastsize(); buffer = zbx_malloc(buffer, MAX_BUFFER_LEN); *buffer = '\0'; for (;;) { zbx_setproctitle("%s [processing data]", get_process_type_string(process_type)); sec = zbx_time(); while (SUCCEED == get_latest_data()) read_traps(); sec = zbx_time() - sec; zbx_setproctitle("%s [processed data in " ZBX_FS_DBL " sec, idle 1 sec]", get_process_type_string(process_type), sec); zbx_sleep_loop(1); } zbx_free(buffer); if (-1 != trap_fd) close(trap_fd); }
/****************************************************************************** * * * Function: main_pinger_loop * * * * Purpose: periodically perform ICMP pings * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: never returns * * * ******************************************************************************/ ZBX_THREAD_ENTRY(pinger_thread, args) { int nextcheck, sleeptime, items_count = 0, itc; double sec; static icmpitem_t *items = NULL; static int items_alloc = 4; process_type = ((zbx_thread_args_t *)args)->process_type; server_num = ((zbx_thread_args_t *)args)->server_num; process_num = ((zbx_thread_args_t *)args)->process_num; zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_daemon_type_string(daemon_type), server_num, get_process_type_string(process_type), process_num); if (NULL == items) items = zbx_malloc(items, sizeof(icmpitem_t) * items_alloc); for (;;) { zbx_setproctitle("%s #%d [getting values]", get_process_type_string(process_type), process_num); sec = zbx_time(); get_pinger_hosts(&items, &items_alloc, &items_count); process_pinger_hosts(items, items_count); sec = zbx_time() - sec; itc = items_count; free_hosts(&items, &items_count); nextcheck = DCconfig_get_poller_nextcheck(ZBX_POLLER_TYPE_PINGER); sleeptime = calculate_sleeptime(nextcheck, POLLER_DELAY); zbx_setproctitle("%s #%d [got %d values in " ZBX_FS_DBL " sec, idle %d sec]", get_process_type_string(process_type), process_num, itc, sec, sleeptime); zbx_sleep_loop(sleeptime); } }
ZBX_THREAD_ENTRY(housekeeper_thread, args) { int records, start, sleeptime; double sec, time_slept; char sleeptext[25]; process_type = ((zbx_thread_args_t *)args)->process_type; server_num = ((zbx_thread_args_t *)args)->server_num; process_num = ((zbx_thread_args_t *)args)->process_num; zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_daemon_type_string(daemon_type), server_num, get_process_type_string(process_type), process_num); if (0 == CONFIG_HOUSEKEEPING_FREQUENCY) { zbx_setproctitle("%s [waiting for user command]", get_process_type_string(process_type)); zbx_snprintf(sleeptext, sizeof(sleeptext), "waiting for user command"); } else { sleeptime = HOUSEKEEPER_STARTUP_DELAY * SEC_PER_MIN; zbx_setproctitle("%s [startup idle for %d minutes]", get_process_type_string(process_type), HOUSEKEEPER_STARTUP_DELAY); zbx_snprintf(sleeptext, sizeof(sleeptext), "idle for %d hour(s)", CONFIG_HOUSEKEEPING_FREQUENCY); } zbx_set_sigusr_handler(zbx_housekeeper_sigusr_handler); for (;;) { sec = zbx_time(); if (0 == CONFIG_HOUSEKEEPING_FREQUENCY) zbx_sleep_forever(); else zbx_sleep_loop(sleeptime); time_slept = zbx_time() - sec; hk_period = get_housekeeper_period(time_slept); start = time(NULL); zabbix_log(LOG_LEVEL_WARNING, "executing housekeeper"); zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type)); DBconnect(ZBX_DB_CONNECT_NORMAL); zbx_setproctitle("%s [removing old history]", get_process_type_string(process_type)); sec = zbx_time(); records = housekeeping_history(start); sec = zbx_time() - sec; DBclose(); zabbix_log(LOG_LEVEL_WARNING, "%s [deleted %d records in " ZBX_FS_DBL " sec, %s]", get_process_type_string(process_type), records, sec, sleeptext); zbx_setproctitle("%s [deleted %d records in " ZBX_FS_DBL " sec, %s]", get_process_type_string(process_type), records, sec, sleeptext); if (0 != CONFIG_HOUSEKEEPING_FREQUENCY) sleeptime = CONFIG_HOUSEKEEPING_FREQUENCY * SEC_PER_HOUR; } }
/****************************************************************************** * * * Function: main_alerter_loop * * * * Purpose: periodically check table alerts and send notifications if needed * * * * Author: Alexei Vladishev * * * ******************************************************************************/ ZBX_THREAD_ENTRY(alerter_thread, args) { char error[MAX_STRING_LEN], *error_esc; int res, alerts_success, alerts_fail; double sec; DB_RESULT result; DB_ROW row; DB_ALERT alert; DB_MEDIATYPE mediatype; process_type = ((zbx_thread_args_t *)args)->process_type; server_num = ((zbx_thread_args_t *)args)->server_num; process_num = ((zbx_thread_args_t *)args)->process_num; zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_daemon_type_string(daemon_type), server_num, get_process_type_string(process_type), process_num); zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type)); DBconnect(ZBX_DB_CONNECT_NORMAL); for (;;) { zbx_setproctitle("%s [sending alerts]", get_process_type_string(process_type)); sec = zbx_time(); alerts_success = alerts_fail = 0; result = DBselect( "select a.alertid,a.mediatypeid,a.sendto,a.subject,a.message,a.status,mt.mediatypeid," "mt.type,mt.description,mt.smtp_server,mt.smtp_helo,mt.smtp_email,mt.exec_path," "mt.gsm_modem,mt.username,mt.passwd,mt.smtp_port,mt.smtp_security," "mt.smtp_verify_peer,mt.smtp_verify_host,mt.smtp_authentication,a.retries" " from alerts a,media_type mt" " where a.mediatypeid=mt.mediatypeid" " and a.status=%d" " and a.alerttype=%d" " order by a.alertid", ALERT_STATUS_NOT_SENT, ALERT_TYPE_MESSAGE); while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(alert.alertid, row[0]); ZBX_STR2UINT64(alert.mediatypeid, row[1]); alert.sendto = row[2]; alert.subject = row[3]; alert.message = row[4]; alert.status = atoi(row[5]); ZBX_STR2UINT64(mediatype.mediatypeid, row[6]); mediatype.type = atoi(row[7]); mediatype.description = row[8]; mediatype.smtp_server = row[9]; mediatype.smtp_helo = row[10]; mediatype.smtp_email = row[11]; mediatype.exec_path = row[12]; mediatype.gsm_modem = row[13]; mediatype.username = row[14]; mediatype.passwd = row[15]; mediatype.smtp_port = (unsigned short)atoi(row[16]); ZBX_STR2UCHAR(mediatype.smtp_security, row[17]); ZBX_STR2UCHAR(mediatype.smtp_verify_peer, row[18]); ZBX_STR2UCHAR(mediatype.smtp_verify_host, row[19]); ZBX_STR2UCHAR(mediatype.smtp_authentication, row[20]); alert.retries = atoi(row[21]); *error = '\0'; res = execute_action(&alert, &mediatype, error, sizeof(error)); if (SUCCEED == res) { zabbix_log(LOG_LEVEL_DEBUG, "alert ID [" ZBX_FS_UI64 "] was sent successfully", alert.alertid); DBexecute("update alerts set status=%d,error='' where alertid=" ZBX_FS_UI64, ALERT_STATUS_SENT, alert.alertid); alerts_success++; } else { zabbix_log(LOG_LEVEL_DEBUG, "error sending alert ID [" ZBX_FS_UI64 "]", alert.alertid); error_esc = DBdyn_escape_string_len(error, ALERT_ERROR_LEN); alert.retries++; if (ALERT_MAX_RETRIES > alert.retries) { DBexecute("update alerts set retries=%d,error='%s' where alertid=" ZBX_FS_UI64, alert.retries, error_esc, alert.alertid); } else { DBexecute("update alerts set status=%d,retries=%d,error='%s' where alertid=" ZBX_FS_UI64, ALERT_STATUS_FAILED, alert.retries, error_esc, alert.alertid); } zbx_free(error_esc); alerts_fail++; } } DBfree_result(result); sec = zbx_time() - sec; zbx_setproctitle("%s [sent alerts: %d success, %d fail in " ZBX_FS_DBL " sec, idle %d sec]", get_process_type_string(process_type), alerts_success, alerts_fail, sec, CONFIG_SENDER_FREQUENCY); zbx_sleep_loop(CONFIG_SENDER_FREQUENCY); } }
/****************************************************************************** * * * Function: main_timer_loop * * * * Purpose: periodically updates time-related triggers * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: does update once per 30 seconds (hardcoded) * * * ******************************************************************************/ ZBX_THREAD_ENTRY(timer_thread, args) { int now, nextcheck, sleeptime = -1, triggers_count = 0, events_count = 0, hm_count = 0, old_triggers_count = 0, old_events_count = 0, old_hm_count = 0, tr_count, ev_count; double sec = 0.0, sec_maint = 0.0, total_sec = 0.0, total_sec_maint = 0.0, old_total_sec = 0.0, old_total_sec_maint = 0.0; time_t last_stat_time; process_type = ((zbx_thread_args_t *)args)->process_type; server_num = ((zbx_thread_args_t *)args)->server_num; process_num = ((zbx_thread_args_t *)args)->process_num; zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_daemon_type_string(daemon_type), server_num, get_process_type_string(process_type), process_num); #define STAT_INTERVAL 5 /* if a process is busy and does not sleep then update status not faster than */ /* once in STAT_INTERVAL seconds */ zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num); last_stat_time = time(NULL); DBconnect(ZBX_DB_CONNECT_NORMAL); for (;;) { now = time(NULL); nextcheck = now + TIMER_DELAY - (now % TIMER_DELAY); sleeptime = nextcheck - now; if (0 != sleeptime || STAT_INTERVAL <= time(NULL) - last_stat_time) { if (0 == sleeptime) { if (1 != process_num) { zbx_setproctitle("%s #%d [processed %d triggers, %d events in " ZBX_FS_DBL " sec, processing time functions]", get_process_type_string(process_type), process_num, triggers_count, events_count, total_sec); } else { zbx_setproctitle("%s #1 [processed %d triggers, %d events in " ZBX_FS_DBL " sec, %d maintenances in " ZBX_FS_DBL " sec, processing time " "functions]", get_process_type_string(process_type), triggers_count, events_count, total_sec, hm_count, total_sec_maint); } } else { if (1 != process_num) { zbx_setproctitle("%s #%d [processed %d triggers, %d events in " ZBX_FS_DBL " sec, idle %d sec]", get_process_type_string(process_type), process_num, triggers_count, events_count, total_sec, sleeptime); } else { zbx_setproctitle("%s #1 [processed %d triggers, %d events in " ZBX_FS_DBL " sec, %d maintenances in " ZBX_FS_DBL " sec, idle %d sec]", get_process_type_string(process_type), triggers_count, events_count, total_sec, hm_count, total_sec_maint, sleeptime); old_hm_count = hm_count; old_total_sec_maint = total_sec_maint; } old_triggers_count = triggers_count; old_events_count = events_count; old_total_sec = total_sec; } triggers_count = 0; events_count = 0; hm_count = 0; total_sec = 0.0; total_sec_maint = 0.0; last_stat_time = time(NULL); } zbx_sleep_loop(sleeptime); if (0 != sleeptime) { if (1 != process_num) { zbx_setproctitle("%s #%d [processed %d triggers, %d events in " ZBX_FS_DBL " sec, processing time functions]", get_process_type_string(process_type), process_num, old_triggers_count, old_events_count, old_total_sec); } else { zbx_setproctitle("%s #1 [processed %d triggers, %d events in " ZBX_FS_DBL " sec, %d maintenances in " ZBX_FS_DBL " sec, processing time " "functions]", get_process_type_string(process_type), old_triggers_count, old_events_count, old_total_sec, old_hm_count, old_total_sec_maint); } } sec = zbx_time(); tr_count = 0; ev_count = 0; process_time_functions(&tr_count, &ev_count); triggers_count += tr_count; events_count += ev_count; total_sec += zbx_time() - sec; /* only the "timer #1" process evaluates the maintenance periods */ if (1 != process_num) continue; /* we process maintenance at every 00 sec */ /* process time functions can take long time */ if (0 == nextcheck % SEC_PER_MIN || nextcheck + SEC_PER_MIN - (nextcheck % SEC_PER_MIN) <= time(NULL)) { zbx_setproctitle("%s #1 [processed %d triggers, %d events in " ZBX_FS_DBL " sec, %d maintenances in " ZBX_FS_DBL " sec, processing maintenance periods]", get_process_type_string(process_type), triggers_count, events_count, total_sec, old_hm_count, old_total_sec_maint); sec_maint = zbx_time(); hm_count += process_maintenance(); total_sec_maint += zbx_time() - sec_maint; } } #undef STAT_INTERVAL }
ZBX_THREAD_ENTRY(proxypoller_thread, args) { int nextcheck, sleeptime = -1, processed = 0, old_processed = 0; double sec, total_sec = 0.0, old_total_sec = 0.0; time_t last_stat_time; process_type = ((zbx_thread_args_t *)args)->process_type; server_num = ((zbx_thread_args_t *)args)->server_num; process_num = ((zbx_thread_args_t *)args)->process_num; zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_daemon_type_string(daemon_type), server_num, get_process_type_string(process_type), process_num); #define STAT_INTERVAL 5 /* if a process is busy and does not sleep then update status not faster than */ /* once in STAT_INTERVAL seconds */ zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num); last_stat_time = time(NULL); DBconnect(ZBX_DB_CONNECT_NORMAL); for (;;) { if (0 != sleeptime) { zbx_setproctitle("%s #%d [exchanged data with %d proxies in " ZBX_FS_DBL " sec," " exchanging data]", get_process_type_string(process_type), process_num, old_processed, old_total_sec); } sec = zbx_time(); processed += process_proxy(); total_sec += zbx_time() - sec; nextcheck = DCconfig_get_proxypoller_nextcheck(); sleeptime = calculate_sleeptime(nextcheck, POLLER_DELAY); if (0 != sleeptime || STAT_INTERVAL <= time(NULL) - last_stat_time) { if (0 == sleeptime) { zbx_setproctitle("%s #%d [exchanged data with %d proxies in " ZBX_FS_DBL " sec," " exchanging data]", get_process_type_string(process_type), process_num, processed, total_sec); } else { zbx_setproctitle("%s #%d [exchanged data with %d proxies in " ZBX_FS_DBL " sec," " idle %d sec]", get_process_type_string(process_type), process_num, processed, total_sec, sleeptime); old_processed = processed; old_total_sec = total_sec; } processed = 0; total_sec = 0.0; last_stat_time = time(NULL); } zbx_sleep_loop(sleeptime); } #undef STAT_INTERVAL }