ZBX_THREAD_ENTRY(trapper_thread, args) { double sec = 0.0; zbx_socket_t s; 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)); #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) zbx_tls_init_child(); find_psk_in_cache = DCget_psk_by_identity; #endif zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num); DBconnect(ZBX_DB_CONNECT_NORMAL); for (;;) { zbx_handle_log(); zbx_setproctitle("%s #%d [processed data in " ZBX_FS_DBL " sec, waiting for connection]", get_process_type_string(process_type), process_num, sec); update_selfmon_counter(ZBX_PROCESS_STATE_IDLE); /* Trapper has to accept all types of connections it can accept with the specified configuration. */ /* Only after receiving data it is known who has sent them and one can decide to accept or discard */ /* the data. */ if (SUCCEED == zbx_tcp_accept(&s, ZBX_TCP_SEC_TLS_CERT | ZBX_TCP_SEC_TLS_PSK | ZBX_TCP_SEC_UNENCRYPTED)) { zbx_timespec_t ts; /* get connection timestamp */ zbx_timespec(&ts); update_selfmon_counter(ZBX_PROCESS_STATE_BUSY); zbx_setproctitle("%s #%d [processing data]", get_process_type_string(process_type), process_num); sec = zbx_time(); process_trapper_child(&s, &ts); sec = zbx_time() - sec; zbx_tcp_unaccept(&s); } else if (EINTR != zbx_socket_last_error()) { zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming connection: %s", zbx_socket_strerror()); } } }
ZBX_THREAD_ENTRY(taskmanager_thread, args) { static int cleanup_time = 0; double sec1, sec2; int tasks_num, sleeptime, nextcheck; 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); #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) zbx_tls_init_child(); #endif zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type)); DBconnect(ZBX_DB_CONNECT_NORMAL); sec1 = zbx_time(); sleeptime = ZBX_TM_PROCESS_PERIOD - (int)sec1 % ZBX_TM_PROCESS_PERIOD; zbx_setproctitle("%s [started, idle %d sec]", get_process_type_string(process_type), sleeptime); for (;;) { zbx_sleep_loop(sleeptime); sec1 = zbx_time(); zbx_update_env(sec1); zbx_setproctitle("%s [processing tasks]", get_process_type_string(process_type)); tasks_num = tm_process_tasks((int)sec1); if (ZBX_TM_CLEANUP_PERIOD <= sec1 - cleanup_time) { tm_remove_old_tasks((int)sec1); cleanup_time = sec1; } sec2 = zbx_time(); nextcheck = (int)sec1 - (int)sec1 % ZBX_TM_PROCESS_PERIOD + ZBX_TM_PROCESS_PERIOD; if (0 > (sleeptime = nextcheck - (int)sec2)) sleeptime = 0; zbx_setproctitle("%s [processed %d task(s) in " ZBX_FS_DBL " sec, idle %d sec]", get_process_type_string(process_type), tasks_num, sec2 - sec1, sleeptime); } }
/****************************************************************************** * * * 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_program_type_string(program_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_handle_log(); 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_dbconfig_loop * * * * Purpose: periodically synchronises database data with memory cache * * * * Parameters: * * * * Return value: * * * * Author: Alexander Vladishev * * * * Comments: never returns * * * ******************************************************************************/ ZBX_THREAD_ENTRY(dbconfig_thread, args) { double sec = 0.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 [waiting %d sec for processes]", get_process_type_string(process_type), CONFIG_CONFSYNCER_FREQUENCY); zbx_set_sigusr_handler(zbx_dbconfig_sigusr_handler); /* the initial configuration sync is done by server before worker processes are forked */ zbx_sleep_loop(CONFIG_CONFSYNCER_FREQUENCY); zbx_setproctitle("%s [connecting to the database]", get_process_type_string(process_type)); DBconnect(ZBX_DB_CONNECT_NORMAL); for (;;) { zbx_handle_log(); zbx_setproctitle("%s [synced configuration in " ZBX_FS_DBL " sec, syncing configuration]", get_process_type_string(process_type), sec); sec = zbx_time(); DCsync_configuration(); DCupdate_hosts_availability(); sec = zbx_time() - sec; zbx_setproctitle("%s [synced configuration in " ZBX_FS_DBL " sec, idle %d sec]", get_process_type_string(process_type), sec, CONFIG_CONFSYNCER_FREQUENCY); zbx_sleep_loop(CONFIG_CONFSYNCER_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_program_type_string(program_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); zbx_handle_log(); 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(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; } }
int DBcheck_version(void) { const char *__function_name = "DBcheck_version"; const char *dbversion_table_name = "dbversion"; int db_mandatory, db_optional, required, ret = FAIL, i; zbx_db_version_t *dbversion; zbx_dbpatch_t *patches; #ifndef HAVE_SQLITE3 int total = 0, current = 0, completed, last_completed = -1, optional_num = 0; #endif zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); required = ZBX_FIRST_DB_VERSION; /* find out the required version number by getting the last mandatory version */ /* of the last version patch array */ for (dbversion = dbversions; NULL != dbversion->patches; dbversion++) ; patches = (--dbversion)->patches; for (i = 0; 0 != patches[i].version; i++) { if (0 != patches[i].mandatory) required = patches[i].version; } DBconnect(ZBX_DB_CONNECT_NORMAL); if (SUCCEED != DBtable_exists(dbversion_table_name)) { #ifndef HAVE_SQLITE3 zabbix_log(LOG_LEVEL_DEBUG, "%s() \"%s\" does not exist", __function_name, dbversion_table_name); if (SUCCEED != DBfield_exists("config", "server_check_interval")) { zabbix_log(LOG_LEVEL_CRIT, "Cannot upgrade database: the database must" " correspond to version 2.0 or later. Exiting ..."); goto out; } if (SUCCEED != DBcreate_dbversion_table()) goto out; #else zabbix_log(LOG_LEVEL_CRIT, "The %s does not match Zabbix database." " Current database version (mandatory/optional): UNKNOWN." " Required mandatory version: %08d.", get_program_type_string(program_type), required); zabbix_log(LOG_LEVEL_CRIT, "Zabbix does not support SQLite3 database upgrade."); goto out; #endif } DBget_version(&db_mandatory, &db_optional); #ifndef HAVE_SQLITE3 for (dbversion = dbversions; NULL != (patches = dbversion->patches); dbversion++) { for (i = 0; 0 != patches[i].version; i++) { if (0 != patches[i].mandatory) optional_num = 0; else optional_num++; if (db_optional < patches[i].version) total++; } } if (required < db_mandatory) #else if (required != db_mandatory) #endif { zabbix_log(LOG_LEVEL_CRIT, "The %s does not match Zabbix database." " Current database version (mandatory/optional): %08d/%08d." " Required mandatory version: %08d.", get_program_type_string(program_type), db_mandatory, db_optional, required); #ifdef HAVE_SQLITE3 if (required > db_mandatory) zabbix_log(LOG_LEVEL_CRIT, "Zabbix does not support SQLite3 database upgrade."); #endif goto out; } zabbix_log(LOG_LEVEL_INFORMATION, "current database version (mandatory/optional): %08d/%08d", db_mandatory, db_optional); zabbix_log(LOG_LEVEL_INFORMATION, "required mandatory version: %08d", required); ret = SUCCEED; #ifndef HAVE_SQLITE3 if (0 == total) goto out; if (0 != optional_num) zabbix_log(LOG_LEVEL_INFORMATION, "optional patches were found"); zabbix_log(LOG_LEVEL_WARNING, "starting automatic database upgrade"); for (dbversion = dbversions; NULL != dbversion->patches; dbversion++) { zbx_dbpatch_t *patches = dbversion->patches; for (i = 0; 0 != patches[i].version; i++) { if (db_optional >= patches[i].version) continue; DBbegin(); /* skipping the duplicated patches */ if ((0 != patches[i].duplicates && patches[i].duplicates <= db_optional) || SUCCEED == (ret = patches[i].function())) { ret = DBset_version(patches[i].version, patches[i].mandatory); } DBend(ret); if (SUCCEED != ret) break; current++; completed = (int)(100.0 * current / total); if (last_completed != completed) { zabbix_log(LOG_LEVEL_WARNING, "completed %d%% of database upgrade", completed); last_completed = completed; } } if (SUCCEED != ret) break; } if (SUCCEED == ret) zabbix_log(LOG_LEVEL_WARNING, "database upgrade fully completed"); else zabbix_log(LOG_LEVEL_CRIT, "database upgrade failed"); #endif /* not HAVE_SQLITE3 */ out: DBclose(); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }