/** * This is the "real" main which is called both on Windows and UNIX platforms. * For the Windows service case, this will also handle the notifications and set * up the logging support appropriately. */ int main_cmdline(int argc, char **argv) { chassis *srv = NULL; #ifdef HAVE_SIGACTION static struct sigaction sigsegv_sa; #endif /* read the command-line options */ GOptionContext *option_ctx = NULL; GOptionEntry *main_entries = NULL; chassis_frontend_t *frontend = NULL; chassis_options_t *opts = NULL; GError *gerr = NULL; chassis_log *log = NULL; /* a little helper macro to set the src-location that we stepped out at to exit */ #define GOTO_EXIT(status) \ exit_code = status; \ exit_location = G_STRLOC; \ goto exit_nicely; int exit_code = EXIT_SUCCESS; const gchar *exit_location = G_STRLOC; if (chassis_frontend_init_glib()) { /* init the thread, module, ... system */ GOTO_EXIT(EXIT_FAILURE); } /* start the logging ... to stderr */ log = chassis_log_new(); log->min_lvl = G_LOG_LEVEL_MESSAGE; /* display messages while parsing or loading plugins */ g_log_set_default_handler(chassis_log_func, log); #ifdef _WIN32 if (chassis_win32_is_service() && chassis_log_set_event_log(log, g_get_prgname())) { GOTO_EXIT(EXIT_FAILURE); } if (chassis_frontend_init_win32()) { /* setup winsock */ GOTO_EXIT(EXIT_FAILURE); } #endif /* may fail on library mismatch */ if (NULL == (srv = chassis_new())) { GOTO_EXIT(EXIT_FAILURE); } srv->log = log; /* we need the log structure for the log-rotation */ frontend = chassis_frontend_new(); option_ctx = g_option_context_new("- MySQL Proxy"); /** * parse once to get the basic options like --defaults-file and --version * * leave the unknown options in the list */ if (chassis_frontend_init_base_options(option_ctx, &argc, &argv, &(frontend->print_version), &(frontend->default_file), &gerr)) { g_critical("%s: %s", G_STRLOC, gerr->message); g_clear_error(&gerr); GOTO_EXIT(EXIT_FAILURE); } #ifndef _WIN32 signal(SIGPIPE, SIG_IGN); srv->daemon_mode = frontend->daemon_mode; /* add by vinchen/CFR */ srv->auto_restart = frontend->auto_restart; if (frontend->daemon_mode) { chassis_unix_daemonize(); } if (frontend->auto_restart) { int child_exit_status = EXIT_SUCCESS; /* forward the exit-status of the child */ int ret = chassis_unix_proc_keepalive(&child_exit_status); if (ret > 0) { /* the agent stopped */ exit_code = child_exit_status; goto exit_nicely; } else if (ret < 0) { GOTO_EXIT(EXIT_FAILURE); } else { /* we are the child, go on */ } } #endif if (frontend->default_file) { srv->default_file = g_strdup(frontend->default_file); //add by vinchen/CFR if (!(frontend->keyfile = chassis_frontend_open_config_file(frontend->default_file, &gerr))) { g_critical("%s: loading config from '%s' failed: %s", G_STRLOC, frontend->default_file, gerr->message); g_clear_error(&gerr); GOTO_EXIT(EXIT_FAILURE); } } /* print the main version number here, but don't exit * we check for print_version again, after loading the plugins (if any) * and print their version numbers, too. then we exit cleanly. */ if (frontend->print_version) { #ifndef CHASSIS_BUILD_TAG #define CHASSIS_BUILD_TAG PACKAGE_STRING #endif g_print("%s" CHASSIS_NEWLINE, CHASSIS_BUILD_TAG); chassis_frontend_print_version(); } /* add the other options which can also appear in the configfile */ opts = chassis_options_new(); chassis_frontend_set_chassis_options(frontend, opts); main_entries = chassis_options_to_g_option_entries(opts); g_option_context_add_main_entries(option_ctx, main_entries, NULL); /** * parse once to get the basic options * * leave the unknown options in the list */ if (FALSE == g_option_context_parse(option_ctx, &argc, &argv, &gerr)) { g_critical("%s", gerr->message); GOTO_EXIT(EXIT_FAILURE); } if (frontend->keyfile) { if (chassis_keyfile_to_options(frontend->keyfile, "mysql-proxy", main_entries)) { GOTO_EXIT(EXIT_FAILURE); } } //add by vinchen/CFR if (frontend->base_dir != NULL) srv->base_dir_org = g_strdup(frontend->base_dir); if (chassis_frontend_init_basedir(argv[0], &(frontend->base_dir))) { GOTO_EXIT(EXIT_FAILURE); } /* basic setup is done, base-dir is known, ... */ frontend->lua_subdirs = g_new(char *, 2); frontend->lua_subdirs[0] = g_strdup("mysql-proxy"); frontend->lua_subdirs[1] = NULL; if (chassis_frontend_init_lua_path(frontend->lua_path, frontend->base_dir, frontend->lua_subdirs)) { GOTO_EXIT(EXIT_FAILURE); } if (chassis_frontend_init_lua_cpath(frontend->lua_cpath, frontend->base_dir, frontend->lua_subdirs)) { GOTO_EXIT(EXIT_FAILURE); } /* assign the mysqld part to the */ network_mysqld_init(srv); /* starts the also the lua-scope, LUA_PATH and LUA_CPATH have to be set before this being called */ #ifdef HAVE_SIGACTION /* register the sigsegv interceptor */ memset(&sigsegv_sa, 0, sizeof(sigsegv_sa)); sigsegv_sa.sa_handler = sigsegv_handler; sigemptyset(&sigsegv_sa.sa_mask); srv->invoke_dbg_on_crash = frontend->invoke_dbg_on_crash; //add by vinchen/CFR if (frontend->invoke_dbg_on_crash && !(RUNNING_ON_VALGRIND)) { sigaction(SIGSEGV, &sigsegv_sa, NULL); } #endif /* * some plugins cannot see the chassis struct from the point * where they open files, hence we must make it available */ srv->base_dir = g_strdup(frontend->base_dir); if (frontend->plugin_dir) //vinchen/CFR srv->plugin_dir_org = g_strdup(frontend->plugin_dir); if (frontend->pid_file) srv->pid_file_org = g_strdup(frontend->pid_file); if (frontend->log_filename) srv->log_file_name_org = g_strdup(frontend->log_filename); if (frontend->lua_path) srv->lua_path_org = g_strdup(frontend->lua_path); if (frontend->lua_cpath) srv->lua_cpath_org = g_strdup(frontend->lua_cpath); srv->max_files_number = frontend->max_files_number; srv->conn_log = frontend->conn_log; //add by huibohuang srv->query_response_time_stats = frontend->query_response_time_stats; srv->ignore_user = g_strdupv(frontend->ignore_user); chassis_frontend_init_plugin_dir(&frontend->plugin_dir, srv->base_dir); /* * these are used before we gathered all the options * from the plugins, thus we need to fix them up before * dealing with all the rest. */ chassis_resolve_path(srv->base_dir, &frontend->log_filename); chassis_resolve_path(srv->base_dir, &frontend->pid_file); chassis_resolve_path(srv->base_dir, &frontend->plugin_dir); /* * start the logging */ if (frontend->log_filename) { log->log_filename = g_strdup(frontend->log_filename); } log->use_syslog = frontend->use_syslog; if (log->log_filename && log->use_syslog) { g_critical("%s: log-file and log-use-syslog were given, but only one is allowed", G_STRLOC); GOTO_EXIT(EXIT_FAILURE); } if (log->log_filename && FALSE == chassis_log_open(log)) { g_critical("can't open log-file '%s': %s", log->log_filename, g_strerror(errno)); GOTO_EXIT(EXIT_FAILURE); } /* handle log-level after the config-file is read, just in case it is specified in the file */ if (frontend->log_level) { if (0 != chassis_log_set_level(log, frontend->log_level)) { g_critical("--log-level=... failed, level '%s' is unknown ", frontend->log_level); GOTO_EXIT(EXIT_FAILURE); } } else { /* if it is not set, use "critical" as default */ log->min_lvl = G_LOG_LEVEL_CRITICAL; } /* * the MySQL Proxy should load 'admin' and 'proxy' plugins */ if (!frontend->plugin_names) { frontend->plugin_names = g_new(char *, 2); frontend->plugin_names[0] = g_strdup("proxy"); frontend->plugin_names[1] = NULL; }
/** * This is the "real" main which is called both on Windows and UNIX platforms. * For the Windows service case, this will also handle the notifications and set * up the logging support appropriately. */ int main_cmdline(int argc, char **argv) { chassis *srv = NULL; #ifdef HAVE_SIGACTION static struct sigaction sigsegv_sa; #endif /* read the command-line options */ GOptionContext *option_ctx = NULL; GOptionEntry *main_entries = NULL; chassis_frontend_t *frontend = NULL; chassis_options_t *opts = NULL; GError *gerr = NULL; chassis_log_t *log = NULL; /* a little helper macro to set the src-location that we stepped out at to exit */ #define GOTO_EXIT(status) \ exit_code = status; \ exit_location = G_STRLOC; \ goto exit_nicely; int exit_code = EXIT_SUCCESS; const gchar *exit_location = G_STRLOC; if (chassis_frontend_init_glib()) { /* init the thread, module, ... system */ GOTO_EXIT(EXIT_FAILURE); } log = chassis_log_new(); chassis_log_set_default(log, NULL, G_LOG_LEVEL_CRITICAL); /* default to stderr for everything that is critical */ g_log_set_default_handler(chassis_log_func, log); #ifdef _WIN32 if (chassis_frontend_init_win32()) { /* setup winsock */ GOTO_EXIT(EXIT_FAILURE); } #endif /* may fail on library mismatch */ if (NULL == (srv = chassis_new())) { GOTO_EXIT(EXIT_FAILURE); } srv->log = log; /* we need the log structure for the log-rotation */ frontend = chassis_frontend_new(); option_ctx = g_option_context_new("- MySQL Proxy"); /** * parse once to get the basic options like --defaults-file and --version * * leave the unknown options in the list */ if (chassis_frontend_init_base_options(option_ctx, &argc, &argv, &(frontend->print_version), &(frontend->default_file), &gerr)) { g_critical("%s: %s", G_STRLOC, gerr->message); g_clear_error(&gerr); GOTO_EXIT(EXIT_FAILURE); } if (frontend->default_file) { if (!(frontend->keyfile = chassis_frontend_open_config_file(frontend->default_file, &gerr))) { g_critical("%s: loading config from '%s' failed: %s", G_STRLOC, frontend->default_file, gerr->message); g_clear_error(&gerr); GOTO_EXIT(EXIT_FAILURE); } } /* print the main version number here, but don't exit * we check for print_version again, after loading the plugins (if any) * and print their version numbers, too. then we exit cleanly. */ if (frontend->print_version) { #ifndef CHASSIS_BUILD_TAG #define CHASSIS_BUILD_TAG PACKAGE_STRING #endif g_print("%s" CHASSIS_NEWLINE, CHASSIS_BUILD_TAG); chassis_frontend_print_version(); } /* add the other options which can also appear in the configfile */ opts = chassis_options_new(); chassis_frontend_set_chassis_options(frontend, opts); main_entries = chassis_options_to_g_option_entries(opts); g_option_context_add_main_entries(option_ctx, main_entries, NULL); /** * parse once to get the basic options * * leave the unknown options in the list */ if (FALSE == g_option_context_parse(option_ctx, &argc, &argv, &gerr)) { g_critical("%s", gerr->message); GOTO_EXIT(EXIT_FAILURE); } if (frontend->keyfile) { if (chassis_keyfile_to_options(frontend->keyfile, "mysql-proxy", main_entries)) { GOTO_EXIT(EXIT_FAILURE); } } if (chassis_frontend_init_basedir(argv[0], &(frontend->base_dir))) { GOTO_EXIT(EXIT_FAILURE); } /* basic setup is done, base-dir is known, ... */ frontend->lua_subdirs = g_new(char *, 2); frontend->lua_subdirs[0] = g_strdup("mysql-proxy"); frontend->lua_subdirs[1] = NULL; if (chassis_frontend_init_lua_path(frontend->lua_path, frontend->base_dir, frontend->lua_subdirs)) { GOTO_EXIT(EXIT_FAILURE); } if (chassis_frontend_init_lua_cpath(frontend->lua_cpath, frontend->base_dir, frontend->lua_subdirs)) { GOTO_EXIT(EXIT_FAILURE); } /* assign the mysqld part to the */ network_mysqld_init(srv); /* starts the also the lua-scope, LUA_PATH and LUA_CPATH have to be set before this being called */ #ifdef HAVE_SIGACTION /* register the sigsegv interceptor */ memset(&sigsegv_sa, 0, sizeof(sigsegv_sa)); sigsegv_sa.sa_handler = sigsegv_handler; sigemptyset(&sigsegv_sa.sa_mask); if (frontend->invoke_dbg_on_crash && !(RUNNING_ON_VALGRIND)) { sigaction(SIGSEGV, &sigsegv_sa, NULL); } #endif /* * some plugins cannot see the chassis struct from the point * where they open files, hence we must make it available */ srv->base_dir = g_strdup(frontend->base_dir); chassis_frontend_init_plugin_dir(&frontend->plugin_dir, srv->base_dir); /* * these are used before we gathered all the options * from the plugins, thus we need to fix them up before * dealing with all the rest. */ chassis_resolve_path(srv->base_dir, &frontend->log_config_filename); chassis_resolve_path(srv->base_dir, &frontend->log_filename); chassis_resolve_path(srv->base_dir, &frontend->pid_file); chassis_resolve_path(srv->base_dir, &frontend->plugin_dir); /* * start the logging * * If we have a log config file, it takes precendence before the simple other log-* options. */ if (frontend->log_filename && frontend->use_syslog) { g_critical("%s: log-file and log-use-syslog were given, but only one is allowed", G_STRLOC); GOTO_EXIT(EXIT_FAILURE); } if (frontend->log_config_filename) { if (FALSE == chassis_log_load_config(log, frontend->log_config_filename, &gerr)) { g_critical("%s: reading log-config from %s failed: %s", G_STRLOC, frontend->log_config_filename, gerr->message); g_clear_error(&gerr); GOTO_EXIT(EXIT_FAILURE); } /* the system should now be set up, let's try to log something */ g_message("this should go to the root logger on level message"); } else { /* set a default config */ chassis_log_backend_t *backend; chassis_log_domain_t *domain; GLogLevelFlags log_lvl = G_LOG_LEVEL_CRITICAL; /* handle log-level after the config-file is read, just in case it is specified in the file */ if (frontend->log_level) { log_lvl = chassis_log_level_string_to_level(frontend->log_level); if (0 == log_lvl) { g_critical("--log-level=... failed, level '%s' is unknown ", frontend->log_level); GOTO_EXIT(EXIT_FAILURE); } } if (frontend->log_filename) { backend = chassis_log_backend_file_new(frontend->log_filename); } else if (frontend->use_syslog) { backend = chassis_log_backend_syslog_new(); #ifdef _WIN32 } else if (chassis_win32_is_service()) { backend = chassis_log_backend_eventlog_new(); #endif } else { backend = chassis_log_backend_stderr_new(); } chassis_log_register_backend(log, backend); domain = chassis_log_domain_new(CHASSIS_LOG_DEFAULT_DOMAIN, log_lvl, backend); chassis_log_register_domain(log, domain); } /* * the MySQL Proxy should load 'admin' and 'proxy' plugins */ if (!frontend->plugin_names) { frontend->plugin_names = g_new(char *, 3); frontend->plugin_names[0] = g_strdup("admin"); frontend->plugin_names[1] = g_strdup("proxy"); frontend->plugin_names[2] = NULL; }