#include #include #include #include #include #include #include #include "logo.h" #include "times.h" #include "config.h" #include "id_generator.h" #include "stellar_priv.h" static const char *log_config_file = "./conf/log.toml"; static const char *stellar_config_file = "./conf/stellar.toml"; static void signal_handler(int signo) { if (signo == SIGINT) { STELLAR_LOG_STATE("SIGINT received, notify threads to exit !!!"); ATOMIC_SET(&runtime->need_exit, 1); } if (signo == SIGQUIT) { STELLAR_LOG_STATE("SIGQUIT received, notify threads to exit !!!"); ATOMIC_SET(&runtime->need_exit, 1); } if (signo == SIGTERM) { STELLAR_LOG_STATE("SIGTERM received, notify threads to exit !!!"); ATOMIC_SET(&runtime->need_exit, 1); } if (signo == SIGHUP) { STELLAR_LOG_STATE("SIGHUP received, reload log level !!!"); log_reload_level(log_config_file); } } static int all_session_have_freed(void) { for (int i = 0; i < config->io_opts.nr_threads; i++) { struct session_manager *sess_mgr = runtime->threads[i].sess_mgr; struct session_manager_stat *sess_stat = session_manager_stat(sess_mgr); if (ATOMIC_READ(&sess_stat->curr_nr_tcp_sess_used) != 0) { return 0; } if (ATOMIC_READ(&sess_stat->curr_nr_udp_sess_used) != 0) { return 0; } } return 1; } static int all_stat_have_output(void) { static int count = 0; if (runtime->stat_last_output_ts == stellar_get_monotonic_time_msec()) { count++; } return count == 2; } int main(int argc, char **argv) { struct stellar st = {runtime}; stellar_update_time_cache(); signal(SIGINT, signal_handler); signal(SIGQUIT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGHUP, signal_handler); if (log_init(log_config_file) != 0) { STELLAR_LOG_ERROR("unable to init log"); goto error_out; } STELLAR_LOG_STATE("start stellar (version: %s)\n %s", __stellar_version, logo_str); if (stellar_load_config(stellar_config_file, config) != 0) { STELLAR_LOG_ERROR("unable to load config file"); goto error_out; } stellar_print_config(config); STELLAR_LOG_DEBUG("sizeof(struct session) = %lu bytes", sizeof(struct session)); if (id_generator_init(config->dev_opts.base, config->dev_opts.offset) != 0) { STELLAR_LOG_ERROR("unable to init id generator"); goto error_out; } runtime->stat = stellar_stat_new(config->io_opts.nr_threads); if (runtime->stat == NULL) { STELLAR_LOG_ERROR("unable to create stellar stat"); goto error_out; } runtime->plug_mgr = plugin_manager_init(&st, "./stellar_plugin/spec.toml"); if (runtime->plug_mgr == NULL) { STELLAR_LOG_ERROR("unable to create plugin manager"); goto error_out; } runtime->packet_io = packet_io_new(&config->io_opts); if (runtime->packet_io == NULL) { STELLAR_LOG_ERROR("unable to create packet io"); goto error_out; } if (stellar_thread_init(runtime, config) != 0) { STELLAR_LOG_ERROR("unable to init thread context"); goto error_out; } if (stellar_thread_run(runtime, config) != 0) { STELLAR_LOG_ERROR("unable to create worker thread"); goto error_out; } runtime->stat_last_output_ts = stellar_get_monotonic_time_msec(); while (!ATOMIC_READ(&runtime->need_exit)) { stellar_update_time_cache(); if (stellar_get_monotonic_time_msec() - runtime->stat_last_output_ts > 2000) { runtime->stat_last_output_ts = stellar_get_monotonic_time_msec(); stellar_stat_output(runtime->stat); } usleep(1000); // 1ms // Only available in dump file mode, automatically exits when all sessions have been released if (packet_io_wait_exit(runtime->packet_io) && all_session_have_freed() && all_stat_have_output()) { STELLAR_LOG_STATE("all sessions have been released and all stat have been output, notify threads to exit !!!"); ATOMIC_SET(&runtime->need_exit, 1); } } error_out: stellar_thread_join(runtime, config); stellar_thread_clean(runtime, config); packet_io_free(runtime->packet_io); plugin_manager_exit(runtime->plug_mgr); stellar_stat_free(runtime->stat); STELLAR_LOG_STATE("stellar exit !!!\n"); log_free(); return 0; }