/****************************************************************************** * * * Function: process_pinger_hosts * * * * Purpose: * * * * Parameters: * * * * Return value: * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ static void process_pinger_hosts(icmpitem_t *items, int items_count) { const char *__function_name = "process_pinger_hosts"; int i, first_index = 0, ping_result; char error[ITEM_ERROR_LEN_MAX]; static ZBX_FPING_HOST *hosts = NULL; static int hosts_alloc = 4; int hosts_count = 0; zbx_timespec_t ts; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (NULL == hosts) hosts = zbx_malloc(hosts, sizeof(ZBX_FPING_HOST) * hosts_alloc); for (i = 0; i < items_count; i++) { add_pinger_host(&hosts, &hosts_alloc, &hosts_count, items[i].addr); if (i == items_count - 1 || items[i].count != items[i + 1].count || items[i].interval != items[i + 1].interval || items[i].size != items[i + 1].size || items[i].timeout != items[i + 1].timeout) { zbx_setproctitle("%s #%d [pinging hosts]", get_process_type_string(process_type), process_num); zbx_timespec(&ts); ping_result = do_ping(hosts, hosts_count, items[i].count, items[i].interval, items[i].size, items[i].timeout, error, sizeof(error)); process_values(items, first_index, i + 1, hosts, hosts_count, &ts, ping_result, error); hosts_count = 0; first_index = i + 1; } } zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
void main_housekeeper_loop() { int now, d_history_and_trends, d_cleanup, d_events, d_alerts, d_sessions; for (;;) { zabbix_log(LOG_LEVEL_WARNING, "executing housekeeper"); now = time(NULL); zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type)); DBconnect(ZBX_DB_CONNECT_NORMAL); zbx_setproctitle("%s [removing old history and trends]", get_process_type_string(process_type)); d_history_and_trends = housekeeping_history_and_trends(now); zbx_setproctitle("%s [removing deleted items data]", get_process_type_string(process_type)); d_cleanup = housekeeping_cleanup(); zbx_setproctitle("%s [removing old events]", get_process_type_string(process_type)); d_events = housekeeping_events(now); zbx_setproctitle("%s [removing old alerts]", get_process_type_string(process_type)); d_alerts = housekeeping_alerts(now); zbx_setproctitle("%s [removing old sessions]", get_process_type_string(process_type)); d_sessions = housekeeping_sessions(now); zabbix_log(LOG_LEVEL_WARNING, "housekeeper deleted: %d records from history and trends," " %d records of deleted items, %d events, %d alerts, %d sessions", d_history_and_trends, d_cleanup, d_events, d_alerts, d_sessions); DBclose(); zbx_sleep_loop(CONFIG_HOUSEKEEPING_FREQUENCY * SEC_PER_HOUR); } }
/****************************************************************************** * * * Function: user1_signal_handler * * * * Purpose: handle user signal SIGUSR1 * * * ******************************************************************************/ static void user1_signal_handler(int sig, siginfo_t *siginfo, void *context) { #ifdef HAVE_SIGQUEUE int flags, process_num, found = 0, i; union sigval s; unsigned char process_type; #endif SIG_CHECK_PARAMS(sig, siginfo, context); zabbix_log(LOG_LEVEL_DEBUG, "Got signal [signal:%d(%s),sender_pid:%d,sender_uid:%d,value_int:%d(0x%08x)].", sig, get_signal_name(sig), SIG_CHECKED_FIELD(siginfo, si_pid), SIG_CHECKED_FIELD(siginfo, si_uid), SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT), SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT)); #ifdef HAVE_SIGQUEUE flags = SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT); if (!SIG_PARENT_PROCESS) { common_sigusr_handler(flags); } else if (NULL == threads) { zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: shutdown in progress"); } else if (ZBX_RTC_CONFIG_CACHE_RELOAD == ZBX_RTC_GET_MSG(flags)) { extern unsigned char daemon_type; if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE)) { zabbix_log(LOG_LEVEL_WARNING, "forced reloading of the configuration cache" " cannot be performed for a passive proxy"); return; } for (i = 0; i < threads_num; i++) { if (FAIL == get_process_info_by_thread(i + 1, &process_type, &process_num)) continue; if (ZBX_PROCESS_TYPE_CONFSYNCER == process_type) break; } if (i != threads_num) { s.ZBX_SIVAL_INT = flags; if (-1 != sigqueue(threads[i], SIGUSR1, s)) zabbix_log(LOG_LEVEL_DEBUG, "the signal was redirected to the configuration syncer"); else zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: %s", zbx_strerror(errno)); } else zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal to configuration syncer: process not found"); } else if (ZBX_RTC_LOG_LEVEL_INCREASE == ZBX_RTC_GET_MSG(flags) || ZBX_RTC_LOG_LEVEL_DECREASE == ZBX_RTC_GET_MSG(flags)) { s.ZBX_SIVAL_INT = flags; if ((ZBX_RTC_LOG_SCOPE_FLAG | ZBX_RTC_LOG_SCOPE_PID) == ZBX_RTC_GET_SCOPE(flags)) { for (i = 0; i < threads_num; i++) { if (0 != ZBX_RTC_GET_DATA(flags) && threads[i] != ZBX_RTC_GET_DATA(flags)) continue; found = 1; if (-1 != sigqueue(threads[i], SIGUSR1, s)) { zabbix_log(LOG_LEVEL_DEBUG, "the signal was redirected to process pid:%d", threads[i]); } else zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: %s", zbx_strerror(errno)); } if (0 != ZBX_RTC_GET_DATA(flags) && 0 == found) { zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: process pid:%d is not a Zabbix child" " process", ZBX_RTC_GET_DATA(flags)); } } else { for (i = 0; i < threads_num; i++) { if (FAIL == get_process_info_by_thread(i + 1, &process_type, &process_num)) break; if (ZBX_RTC_GET_SCOPE(flags) != process_type) { /* check if we have already checked processes of target type */ if (1 == found) break; continue; } if (0 != ZBX_RTC_GET_DATA(flags) && ZBX_RTC_GET_DATA(flags) != process_num) continue; found = 1; if (-1 != sigqueue(threads[i], SIGUSR1, s)) { zabbix_log(LOG_LEVEL_DEBUG, "the signal was redirected to \"%s\" process" " pid:%d", get_process_type_string(process_type), threads[i]); } else zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: %s", zbx_strerror(errno)); } if (0 == found) { if (0 == ZBX_RTC_GET_DATA(flags)) { zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal:" " \"%s\" process does not exist", get_process_type_string(ZBX_RTC_GET_SCOPE(flags))); } else { zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal:" " \"%s #%d\" process does not exist", get_process_type_string(ZBX_RTC_GET_SCOPE(flags)), ZBX_RTC_GET_DATA(flags)); } } } } #endif }
/****************************************************************************** * * * Function: main_alerter_loop * * * * Purpose: periodically check table alerts and send notifications if needed * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: never returns * * * ******************************************************************************/ void main_alerter_loop() { char error[MAX_STRING_LEN], *error_esc; int res, now; DB_RESULT result; DB_ROW row; DB_ALERT alert; DB_MEDIATYPE mediatype; set_child_signal_handler(); 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)); now = time(NULL); 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,a.retries from alerts a,media_type mt" " where a.status=%d and a.mediatypeid=mt.mediatypeid and a.alerttype=%d" DB_NODE " order by a.clock", ALERT_STATUS_NOT_SENT, ALERT_TYPE_MESSAGE, DBnode_local("mt.mediatypeid")); while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(alert.alertid, row[0]); alert.mediatypeid = atoi(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]; alert.retries = atoi(row[16]); *error = '\0'; res = execute_action(&alert, &mediatype, error, sizeof(error)); if (res == SUCCEED) { 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); } else { zabbix_log(LOG_LEVEL_DEBUG, "Error sending alert ID [" ZBX_FS_UI64 "]", alert.alertid); zabbix_syslog("Error sending alert ID [" ZBX_FS_UI64 "]", alert.alertid); error_esc = DBdyn_escape_string_len(error, ALERT_ERROR_LEN); alert.retries++; if (alert.retries < ALERT_MAX_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); } } DBfree_result(result); zbx_sleep_loop(CONFIG_SENDER_FREQUENCY); } }
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_dbsyncer_loop * * * * Purpose: periodically synchronises data in memory cache with database * * * * Author: Alexei Vladishev * * * * Comments: never returns * * * ******************************************************************************/ void main_dbsyncer_loop() { int sleeptime, last_sleeptime = -1, num; double sec; int retry_up = 0, retry_dn = 0; zabbix_log(LOG_LEVEL_DEBUG, "In main_dbsyncer_loop() process_num:%d", process_num); zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type)); DBconnect(ZBX_DB_CONNECT_NORMAL); for (;;) { zbx_setproctitle("%s [syncing history]", get_process_type_string(process_type)); zabbix_log(LOG_LEVEL_DEBUG, "Syncing ..."); sec = zbx_time(); num = DCsync_history(ZBX_SYNC_PARTIAL); sec = zbx_time() - sec; zabbix_log(LOG_LEVEL_DEBUG, "%s #%d spent " ZBX_FS_DBL " seconds while processing %d items", get_process_type_string(process_type), process_num, sec, num); if (-1 == last_sleeptime) { sleeptime = num ? ZBX_SYNC_MAX / num : CONFIG_HISTSYNCER_FREQUENCY; } else { sleeptime = last_sleeptime; if (ZBX_SYNC_MAX < num) { retry_up = 0; retry_dn++; } else if (ZBX_SYNC_MAX / 2 > num) { retry_up++; retry_dn = 0; } else retry_up = retry_dn = 0; if (2 < retry_dn) { sleeptime--; retry_dn = 0; } if (2 < retry_up) { sleeptime++; retry_up = 0; } } if (0 > sleeptime) sleeptime = 0; else if (CONFIG_HISTSYNCER_FREQUENCY < sleeptime) sleeptime = CONFIG_HISTSYNCER_FREQUENCY; last_sleeptime = sleeptime; zbx_sleep_loop(sleeptime); } }
/****************************************************************************** * * * Function: main_timer_loop * * * * Purpose: periodically updates time-related triggers * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: does update once per 30 seconds (hardcoded) * * * ******************************************************************************/ void main_timer_loop(void) { 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; #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 maint.periods 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 maint.periods 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 maint.periods 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 maint.periods 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 }
/****************************************************************************** * * * 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: get_value_internal * * * * Purpose: retrieve data from Zabbix server (internally supported items) * * * * Parameters: item - item we are interested in * * * * Return value: SUCCEED - data successfully retrieved and stored in result * * NOTSUPPORTED - requested item is not supported * * * * Author: Alexei Vladishev * * * ******************************************************************************/ int get_value_internal(DC_ITEM *item, AGENT_RESULT *result) { int nparams; char params[MAX_STRING_LEN], *error = NULL; char tmp[MAX_STRING_LEN], tmp1[HOST_HOST_LEN_MAX]; init_result(result); if (0 != strncmp(item->key, "zabbix[", 7)) goto notsupported; if (2 != parse_command(item->key, NULL, 0, params, sizeof(params))) goto notsupported; if (0 != get_param(params, 1, tmp, sizeof(tmp))) goto notsupported; nparams = num_param(params); if (0 == strcmp(tmp, "triggers")) /* zabbix["triggers"] */ { if (1 != nparams) goto notsupported; SET_UI64_RESULT(result, DBget_row_count("triggers")); } else if (0 == strcmp(tmp, "items")) /* zabbix["items"] */ { if (1 != nparams) goto notsupported; SET_UI64_RESULT(result, DBget_row_count("items")); } else if (0 == strcmp(tmp, "items_unsupported")) /* zabbix["items_unsupported"] */ { if (1 != nparams) goto notsupported; SET_UI64_RESULT(result, DBget_items_unsupported_count()); } else if (0 == strcmp(tmp, "history") || /* zabbix["history"] */ 0 == strcmp(tmp, "history_log") || /* zabbix["history_log"] */ 0 == strcmp(tmp, "history_str") || /* zabbix["history_str"] */ 0 == strcmp(tmp, "history_text") || /* zabbix["history_text"] */ 0 == strcmp(tmp, "history_uint")) /* zabbix["history_uint"] */ { if (1 != nparams) goto notsupported; SET_UI64_RESULT(result, DBget_row_count(tmp)); } else if (0 == strcmp(tmp, "trends") || /* zabbix["trends"] */ 0 == strcmp(tmp, "trends_uint")) /* zabbix["trends_uint"] */ { if (1 != nparams) goto notsupported; SET_UI64_RESULT(result, DBget_row_count(tmp)); } else if (0 == strcmp(tmp, "queue")) /* zabbix["queue",<from>,<to>] */ { unsigned int from = 6, to = (unsigned int)-1; if (3 < nparams) { error = zbx_strdup(error, "Invalid number of parameters"); goto notsupported; } if (2 <= nparams) { if (0 != get_param(params, 2, tmp, sizeof(tmp))) goto notsupported; if ('\0' != *tmp && FAIL == is_uint_suffix(tmp, &from)) { error = zbx_strdup(error, "Invalid second parameter"); goto notsupported; } } if (3 <= nparams) { if (0 != get_param(params, 3, tmp, sizeof(tmp))) goto notsupported; if ('\0' != *tmp && FAIL == is_uint_suffix(tmp, &to)) { error = zbx_strdup(error, "Invalid third parameter"); goto notsupported; } } if ((unsigned int)-1 != to && from > to) { error = zbx_strdup(error, "Parameters represent an invalid interval"); goto notsupported; } SET_UI64_RESULT(result, DBget_queue_count((int)from, (int)to)); } else if (0 == strcmp(tmp, "requiredperformance")) /* zabbix["requiredperformance"] */ { if (1 != nparams) goto notsupported; SET_DBL_RESULT(result, DBget_requiredperformance()); } else if (0 == strcmp(tmp, "uptime")) /* zabbix["uptime"] */ { if (1 != nparams) goto notsupported; SET_UI64_RESULT(result, time(NULL) - CONFIG_SERVER_STARTUP_TIME); } else if (0 == strcmp(tmp, "boottime")) /* zabbix["boottime"] */ { if (1 != nparams) goto notsupported; SET_UI64_RESULT(result, CONFIG_SERVER_STARTUP_TIME); } else if (0 == strcmp(tmp, "host")) /* zabbix["host",<type>,"available"] */ { if (3 != nparams) goto notsupported; if (0 != get_param(params, 3, tmp, sizeof(tmp)) || 0 != strcmp(tmp, "available")) goto notsupported; if (0 != get_param(params, 2, tmp, sizeof(tmp))) goto notsupported; if (0 == strcmp(tmp, "agent")) SET_UI64_RESULT(result, item->host.available); else if (0 == strcmp(tmp, "snmp")) SET_UI64_RESULT(result, item->host.snmp_available); else if (0 == strcmp(tmp, "ipmi")) SET_UI64_RESULT(result, item->host.ipmi_available); else if (0 == strcmp(tmp, "jmx")) SET_UI64_RESULT(result, item->host.jmx_available); else goto notsupported; result->ui64 = 2 - result->ui64; } else if (0 == strcmp(tmp, "proxy")) /* zabbix["proxy",<hostname>,"lastaccess"] */ { int lastaccess; if (3 != nparams) goto notsupported; if (0 != get_param(params, 2, tmp1, sizeof(tmp1))) goto notsupported; if (0 != get_param(params, 3, tmp, sizeof(tmp)) || 0 != strcmp(tmp, "lastaccess")) goto notsupported; if (FAIL == DBget_proxy_lastaccess(tmp1, &lastaccess, &error)) goto notsupported; SET_UI64_RESULT(result, lastaccess); } else if (0 == strcmp(tmp, "java")) /* zabbix["java",...] */ { int res; alarm(CONFIG_TIMEOUT); res = get_value_java(ZBX_JAVA_GATEWAY_REQUEST_INTERNAL, item, result); alarm(0); if (SUCCEED != res) goto notsupported; } else if (0 == strcmp(tmp, "process")) /* zabbix["process",<type>,<mode>,<state>] */ { unsigned char process_type; int process_forks; double value; if (4 < nparams) { error = zbx_strdup(error, "Invalid number of parameters"); goto notsupported; } if (0 != get_param(params, 2, tmp, sizeof(tmp))) { error = zbx_strdup(error, "Required second parameter missing"); goto notsupported; } for (process_type = 0; process_type < ZBX_PROCESS_TYPE_COUNT; process_type++) if (0 == strcmp(tmp, get_process_type_string(process_type))) break; if (ZBX_PROCESS_TYPE_COUNT == process_type) { error = zbx_strdup(error, "Invalid second parameter"); goto notsupported; } process_forks = get_process_type_forks(process_type); if (0 != get_param(params, 3, tmp, sizeof(tmp))) *tmp = '\0'; if (0 == strcmp(tmp, "count")) { if (3 < nparams) { error = zbx_strdup(error, "Invalid number of parameters"); goto notsupported; } SET_UI64_RESULT(result, process_forks); } else { unsigned char aggr_func, state; unsigned short process_num = 0; if ('\0' == *tmp || 0 == strcmp(tmp, "avg")) aggr_func = ZBX_AGGR_FUNC_AVG; else if (0 == strcmp(tmp, "max")) aggr_func = ZBX_AGGR_FUNC_MAX; else if (0 == strcmp(tmp, "min")) aggr_func = ZBX_AGGR_FUNC_MIN; else if (SUCCEED == is_ushort(tmp, &process_num) && 0 < process_num) aggr_func = ZBX_AGGR_FUNC_ONE; else { error = zbx_strdup(error, "Invalid third parameter"); goto notsupported; } if (0 == process_forks) { error = zbx_dsprintf(error, "No \"%s\" processes started", get_process_type_string(process_type)); goto notsupported; } else if (process_num > process_forks) { error = zbx_dsprintf(error, "\"%s\" #%d is not started", get_process_type_string(process_type), process_num); goto notsupported; } if (0 != get_param(params, 4, tmp, sizeof(tmp))) *tmp = '\0'; if ('\0' == *tmp || 0 == strcmp(tmp, "busy")) state = ZBX_PROCESS_STATE_BUSY; else if (0 == strcmp(tmp, "idle")) state = ZBX_PROCESS_STATE_IDLE; else { error = zbx_strdup(error, "Invalid fourth parameter"); goto notsupported; } get_selfmon_stats(process_type, aggr_func, process_num, state, &value); SET_DBL_RESULT(result, value); } } else if (0 == strcmp(tmp, "wcache")) /* zabbix[wcache,<cache>,<mode>] */ { if (3 < nparams) goto notsupported; if (0 != get_param(params, 2, tmp, sizeof(tmp))) goto notsupported; if (0 != get_param(params, 3, tmp1, sizeof(tmp1))) *tmp1 = '\0'; if (0 == strcmp(tmp, "values")) { if ('\0' == *tmp1 || 0 == strcmp(tmp1, "all")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_COUNTER)); else if (0 == strcmp(tmp1, "float")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_FLOAT_COUNTER)); else if (0 == strcmp(tmp1, "uint")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_UINT_COUNTER)); else if (0 == strcmp(tmp1, "str")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_STR_COUNTER)); else if (0 == strcmp(tmp1, "log")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_LOG_COUNTER)); else if (0 == strcmp(tmp1, "text")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_TEXT_COUNTER)); else if (0 == strcmp(tmp1, "not supported")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_NOTSUPPORTED_COUNTER)); else goto notsupported; } else if (0 == strcmp(tmp, "history")) { if ('\0' == *tmp1 || 0 == strcmp(tmp1, "pfree")) SET_DBL_RESULT(result, *(double *)DCget_stats(ZBX_STATS_HISTORY_PFREE)); else if (0 == strcmp(tmp1, "total")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_TOTAL)); else if (0 == strcmp(tmp1, "used")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_USED)); else if (0 == strcmp(tmp1, "free")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_FREE)); else goto notsupported; } else if (0 == strcmp(tmp, "trend")) { if ('\0' == *tmp1 || 0 == strcmp(tmp1, "pfree")) SET_DBL_RESULT(result, *(double *)DCget_stats(ZBX_STATS_TREND_PFREE)); else if (0 == strcmp(tmp1, "total")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_TREND_TOTAL)); else if (0 == strcmp(tmp1, "used")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_TREND_USED)); else if (0 == strcmp(tmp1, "free")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_TREND_FREE)); else goto notsupported; } else if (0 == strcmp(tmp, "text")) { if ('\0' == *tmp1 || 0 == strcmp(tmp1, "pfree")) SET_DBL_RESULT(result, *(double *)DCget_stats(ZBX_STATS_TEXT_PFREE)); else if (0 == strcmp(tmp1, "total")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_TEXT_TOTAL)); else if (0 == strcmp(tmp1, "used")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_TEXT_USED)); else if (0 == strcmp(tmp1, "free")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_TEXT_FREE)); else goto notsupported; } else goto notsupported; } else if (0 == strcmp(tmp, "rcache")) /* zabbix[rcache,<cache>,<mode>] */ { if (3 < nparams) goto notsupported; if (0 != get_param(params, 2, tmp, sizeof(tmp))) goto notsupported; if (0 != get_param(params, 3, tmp1, sizeof(tmp1))) *tmp1 = '\0'; if (0 == strcmp(tmp, "buffer")) { if ('\0' == *tmp1 || 0 == strcmp(tmp1, "pfree")) SET_DBL_RESULT(result, *(double *)DCconfig_get_stats(ZBX_CONFSTATS_BUFFER_PFREE)); else if (0 == strcmp(tmp1, "total")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCconfig_get_stats(ZBX_CONFSTATS_BUFFER_TOTAL)); else if (0 == strcmp(tmp1, "used")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCconfig_get_stats(ZBX_CONFSTATS_BUFFER_USED)); else if (0 == strcmp(tmp1, "free")) SET_UI64_RESULT(result, *(zbx_uint64_t *)DCconfig_get_stats(ZBX_CONFSTATS_BUFFER_FREE)); else goto notsupported; } else goto notsupported; } else goto notsupported; return SUCCEED; notsupported: if (!ISSET_MSG(result)) { if (NULL == error) error = zbx_strdup(error, "Internal check is not supported"); SET_MSG_RESULT(result, error); } return NOTSUPPORTED; }
ZBX_THREAD_ENTRY(listener_thread, args) { #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) char *msg = NULL; #endif int ret; zbx_socket_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_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); memcpy(&s, (zbx_socket_t *)((zbx_thread_args_t *)args)->args, sizeof(zbx_socket_t)); zbx_free(args); #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) zbx_tls_init_child(); #endif while (ZBX_IS_RUNNING()) { zbx_setproctitle("listener #%d [waiting for connection]", process_num); ret = zbx_tcp_accept(&s, configured_tls_accept_modes); zbx_update_env(zbx_time()); if (SUCCEED == ret) { zbx_setproctitle("listener #%d [processing request]", process_num); if ('\0' != *CONFIG_HOSTS_ALLOWED && SUCCEED == (ret = zbx_tcp_check_allowed_peers(&s, CONFIG_HOSTS_ALLOWED))) { #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) if (ZBX_TCP_SEC_TLS_CERT != s.connection_type || SUCCEED == (ret = zbx_check_server_issuer_subject(&s, &msg))) #endif { process_listener(&s); } } zbx_tcp_unaccept(&s); } if (SUCCEED == ret || EINTR == zbx_socket_last_error()) continue; #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) if (NULL != msg) { zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming connection: %s", msg); zbx_free(msg); } else #endif { zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming connection: %s", zbx_socket_strerror()); } if (ZBX_IS_RUNNING()) zbx_sleep(1); } #ifdef _WINDOWS ZBX_DO_EXIT(); zbx_thread_exit(EXIT_SUCCESS); #endif }
/****************************************************************************** * * * Function: timer_thread * * * * Purpose: periodically processes maintenance * * * ******************************************************************************/ ZBX_THREAD_ENTRY(timer_thread, args) { double sec = 0.0; int maintenance_time = 0, update_time = 0, idle = 1, events_num, hosts_num, update; char *info = NULL; size_t info_alloc = 0, info_offset = 0; 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_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num); zbx_strcpy_alloc(&info, &info_alloc, &info_offset, "started"); DBconnect(ZBX_DB_CONNECT_NORMAL); for (;;) { sec = zbx_time(); zbx_update_env(sec); if (1 == process_num) { /* start update process only when all timers have finished their updates */ if (sec - maintenance_time >= ZBX_TIMER_DELAY && FAIL == zbx_dc_maintenance_check_update_flags()) { zbx_setproctitle("%s #%d [%s, processing maintenances]", get_process_type_string(process_type), process_num, info); update = zbx_dc_update_maintenances(); /* force maintenance updates at server startup */ if (0 == maintenance_time) update = SUCCEED; /* update hosts if there are modified (stopped, started, changed) maintenances */ if (SUCCEED == update) hosts_num = update_host_maintenances(); else hosts_num = 0; db_remove_expired_event_suppress_data((int)sec); if (SUCCEED == update) { zbx_dc_maintenance_set_update_flags(); db_update_event_suppress_data(&events_num); zbx_dc_maintenance_reset_update_flag(process_num); } else events_num = 0; info_offset = 0; zbx_snprintf_alloc(&info, &info_alloc, &info_offset, "updated %d hosts, suppressed %d events in " ZBX_FS_DBL " sec", hosts_num, events_num, zbx_time() - sec); update_time = (int)sec; } } else if (SUCCEED == zbx_dc_maintenance_check_update_flag(process_num)) { zbx_setproctitle("%s #%d [%s, processing maintenances]", get_process_type_string(process_type), process_num, info); db_update_event_suppress_data(&events_num); info_offset = 0; zbx_snprintf_alloc(&info, &info_alloc, &info_offset, "suppressed %d events in " ZBX_FS_DBL " sec", events_num, zbx_time() - sec); update_time = (int)sec; zbx_dc_maintenance_reset_update_flag(process_num); } if (maintenance_time != update_time) { maintenance_time = (int)sec; if (0 > (idle = ZBX_TIMER_DELAY - (zbx_time() - sec))) idle = 0; zbx_setproctitle("%s #%d [%s, idle %d sec]", get_process_type_string(process_type), process_num, info, idle); } if (0 != idle) zbx_sleep_loop(1); idle = 1; } }
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 }