Example #1
0
/**
 * 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;
	}
Example #2
0
int
load_sql_filter_from_file(sql_filter *cur_filter)
{
    GKeyFile *blacklist_config = NULL;
    GError *gerr = NULL;
    gsize length = 0;
    int i = 0;
    gchar **groups = NULL;

    g_assert(cur_filter != NULL);

    g_rw_lock_reader_lock(&cur_filter->sql_filter_lock);
    if (!(blacklist_config = chassis_frontend_open_config_file(cur_filter->blacklist_file, &gerr)))
    {
        g_debug("[filter][load from file][failed][%s]", gerr->message);
        g_error_free(gerr);
        gerr = NULL;
        g_rw_lock_reader_unlock(&cur_filter->sql_filter_lock);
        return 1;
    }
    g_rw_lock_reader_unlock(&cur_filter->sql_filter_lock);

    groups = g_key_file_get_groups(blacklist_config, &length);
    for (i = 0; groups[i] != NULL; i++)
    {
        gchar *sql_rewrite_md5 = NULL;
        int is_enabled = 0;
        int filter_status = 0;

        gchar *filter = g_key_file_get_value(blacklist_config, groups[i], "filter", &gerr);
        if (gerr != NULL) { goto next; }

        is_enabled = g_key_file_get_integer(blacklist_config, groups[i], "is_enabled", &gerr);
        if (gerr != NULL) { goto next; }

        filter_status = g_key_file_get_integer(blacklist_config, groups[i], "filter_status", &gerr);
        if (gerr != NULL) { goto next; }

        sql_rewrite_md5 = g_compute_checksum_for_string(G_CHECKSUM_MD5, C_S(filter));
        g_rw_lock_writer_lock(&cur_filter->sql_filter_lock);
        sql_filter_hval *hval = sql_filter_lookup(cur_filter, sql_rewrite_md5);
        if (hval != NULL)
        {
            hval->flag = is_enabled;
            hval->filter_status = filter_status;
        }
        else
        {
            sql_filter_insert(cur_filter, filter, sql_rewrite_md5, is_enabled, filter_status);
        }
        g_rw_lock_writer_unlock(&cur_filter->sql_filter_lock);

next:
        if (filter !=NULL) { g_free(filter); }
        if (sql_rewrite_md5 != NULL) { g_free(sql_rewrite_md5); }

        if (gerr != NULL)
        {
            g_debug("[filter][load from file][failed][%s]", gerr->message);
            g_error_free(gerr);
            gerr = NULL;
        }
        else
            g_message("[filter][load from file %s][success]", cur_filter->blacklist_file);
    }
    g_strfreev(groups);

    g_key_file_free(blacklist_config);
    return 0;
}
Example #3
0
/**
 * 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;
	}
Example #4
0
/**
 * 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_log_dbproxy(g_critical, "%s", 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_log_dbproxy(g_critical, "loading config from '%s' failed: %s", 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) {
        g_print("%s" CHASSIS_NEWLINE, CHASSIS_BUILD_TAG); 
        g_print("  glib2: %d.%d.%d" CHASSIS_NEWLINE, GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
        g_print("  libevent: %s" CHASSIS_NEWLINE, event_get_version());
        GOTO_EXIT(EXIT_SUCCESS);
    }

    /* 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);

    srv->opts = opts;

    /**
     * parse once to get the basic options 
     *
     * leave the unknown options in the list
     */

    g_option_context_set_help_enabled(option_ctx, TRUE);
    if (FALSE == g_option_context_parse(option_ctx, &argc, &argv, &gerr)) {
        g_log_dbproxy(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);
    }

    /* make sure that he max-thread-count isn't negative */
    if (frontend->event_thread_count < 1) {
        g_log_dbproxy(g_critical, "--event-threads has to be >= 1, is %d", frontend->event_thread_count);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->event_thread_count = frontend->event_thread_count;

    if (frontend->wait_timeout < 0) {
        g_log_dbproxy(g_critical, "--wait-timeout has to be >= 0, is %d", frontend->wait_timeout);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->wait_timeout = frontend->wait_timeout;

    if (frontend->shutdown_timeout < 1) {
        g_log_dbproxy(g_critical, "--shutdown-timeout has to be >= 1, is %d", frontend->shutdown_timeout);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->shutdown_timeout = frontend->shutdown_timeout;

    if (frontend->db_connection_idle_timeout < 0) {
        g_log_dbproxy(g_critical, "--db-connection-idle-timeout has to be >= 0, is %d", frontend->db_connection_idle_timeout);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->db_connection_idle_timeout = frontend->db_connection_idle_timeout;

    if (frontend->db_connection_max_age < 0) {
        g_log_dbproxy(g_critical, "--db-connection-max-age has to be >= 0, is %d", frontend->db_connection_max_age);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->db_connection_max_age = frontend->db_connection_max_age;

    if (frontend->mysql_version == NULL
            || strcmp(frontend->mysql_version, "5.5") == 0) {
        srv->my_version = MYSQL_55;
    } else if (frontend->mysql_version == NULL
            || strcmp(frontend->mysql_version, "5.6") == 0) {
        srv->my_version = MYSQL_56;
    } else {
        g_log_dbproxy(g_critical, "--mysql-version has to be 5.6 or 5.5, is %s", frontend->mysql_version);
        GOTO_EXIT(EXIT_FAILURE);
    }

    if (frontend->max_connections < 0) {
        g_log_dbproxy(g_critical, "--max-connections has to be >= 0, is %d", frontend->max_connections);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->proxy_max_connections = frontend->max_connections;

    if (frontend->long_wait_time < 0) {
        g_log_dbproxy(g_critical, "--long-wait-time has to be >= 0, is %d", frontend->long_wait_time);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->long_wait_time = frontend->long_wait_time;

    if (frontend->long_query_time < 0) {
        g_log_dbproxy(g_critical, "--long-query-time has to be >= 0, is %d", frontend->long_query_time);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->long_query_time = frontend->long_query_time;


    if (frontend->query_response_time_stats < 0) {
        g_log_dbproxy(g_critical, "--query-response-time-stats has to be >= 0, is %d", frontend->query_response_time_stats);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->query_response_time_stats = frontend->query_response_time_stats;

    if (frontend->query_response_time_stats > 1 && frontend->query_response_time_range_base < 2) {
        g_log_dbproxy(g_critical, "--query-response-time-range-base has to be >= 2, is %d", frontend->query_response_time_range_base);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->query_response_time_range_base = frontend->query_response_time_range_base;

    if (frontend->lastest_query_num < 0) {
        g_log_dbproxy(g_critical, "--lastest-query-num has to be >= 0, is %d", frontend->lastest_query_num);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->proxy_reserved->lastest_query_num = frontend->lastest_query_num;

    if (frontend->query_filter_time_threshold < -1) {
        g_log_dbproxy(g_critical, "--query-filter-time-threshold has to be >= -1, is %d", frontend->query_filter_time_threshold);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->proxy_reserved->query_filter_time_threshold = frontend->query_filter_time_threshold;

    if (frontend->query_filter_frequent_threshold < 0) {
        g_log_dbproxy(g_critical, "--query-filter-frequent-threshold has to be >= 0, is %f", frontend->query_filter_frequent_threshold);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->proxy_reserved->query_filter_frequent_threshold = frontend->query_filter_frequent_threshold;

    if (frontend->access_num_per_time_window < 1) {
        g_log_dbproxy(g_critical, "--freq-access-num-threshold has to be >= 1, is %d", frontend->access_num_per_time_window);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->proxy_reserved->access_num_per_time_window = frontend->access_num_per_time_window;

    int flag = 0;
    if (frontend->auto_filter_flag == NULL || strcasecmp(frontend->auto_filter_flag, "OFF") == 0)
        flag = 0;
    else if (strcasecmp(frontend->auto_filter_flag, "ON") == 0)
        flag = 1;
    else
    {
        g_log_dbproxy(g_critical, "--auto-filter-flag has to be on or off, is %s", frontend->auto_filter_flag);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->proxy_filter->auto_filter_flag = flag;

    if (frontend->manual_filter_flag == NULL || strcasecmp(frontend->manual_filter_flag, "OFF") == 0)
        flag = 0;
    else if (strcasecmp(frontend->manual_filter_flag, "ON") == 0)
        flag = 1;
    else
    {
        g_log_dbproxy(g_critical, "--manual-filter-flag has to be on or off, is %s", frontend->manual_filter_flag);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->proxy_filter->manual_filter_flag = flag;

    if (frontend->max_backend_tr < 0) {
        g_log_dbproxy(g_critical, "--backend-max-thread-running has to be >= 0, is %d", frontend->max_backend_tr);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->max_backend_tr = frontend->max_backend_tr;

    if (frontend->thread_running_sleep_delay < 1) {
        g_log_dbproxy(g_critical, "--thread-running-sleep-delay has to be >= 1, is %d", frontend->thread_running_sleep_delay);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->thread_running_sleep_delay = frontend->thread_running_sleep_delay;

    if (frontend->remove_backend_timeout < 0) {
        g_log_dbproxy(g_critical, "--remove-backend-timeout has to be >= 0, is %d", frontend->remove_backend_timeout);
        GOTO_EXIT(EXIT_FAILURE);
    }

    /* assign the mysqld part to the */
    network_mysqld_init(srv, frontend->default_file, frontend->remove_backend_timeout); /* 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);

    sigaction(SIGSEGV, &sigsegv_sa, NULL);
#ifdef SIGBUS
    sigaction(SIGBUS, &sigsegv_sa, NULL);
#endif
    sigaction(SIGILL, &sigsegv_sa, NULL);
    sigaction(SIGFPE, &sigsegv_sa, NULL);

    /*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.
     */
    if (chassis_frontend_init_logdir(frontend->log_path)) {
        GOTO_EXIT(EXIT_FAILURE);
    }
    chassis_resolve_path(srv->base_dir, &frontend->log_path);
    chassis_resolve_path(srv->base_dir, &frontend->plugin_dir);

    /*
     * start the logging and pid
     */
    if (frontend->log_path) {
        if (frontend->instance_name == NULL) {
            gchar *default_file = frontend->default_file;

            gchar *slash = strrchr(default_file, '/');
            if (slash != NULL) ++slash;
            else slash = default_file;

            gchar *dot = strrchr(default_file, '.');
            if (dot != NULL && dot >= slash) frontend->instance_name = g_strndup(slash, dot-slash);
            else frontend->instance_name = g_strdup(slash);
        }
        log->log_filename = g_strdup_printf("%s/%s.log", frontend->log_path, frontend->instance_name);
        frontend->pid_file = g_strdup_printf("%s/%s.pid", frontend->log_path, frontend->instance_name);
        srv->log_path = g_strdup(frontend->log_path);
    }

    log->use_syslog = frontend->use_syslog;

    if (log->log_filename && log->use_syslog) {
        g_log_dbproxy(g_critical, "log-file and log-use-syslog were given, but only one is allowed");
        GOTO_EXIT(EXIT_FAILURE);
    }

    /*
     * we have to drop root privileges in chassis_mainloop() after
     * the plugins opened the ports, so we need the user there
     */
    if (frontend->user) {
    srv->user = g_strdup(frontend->user);
    }

    /**
     * create the path of sql and its parents path if it is necessary
     */
    gchar *sql_path = g_strdup_printf("%s/%s", srv->log_path, SQL_LOG_DIR);
    if(g_mkdir_with_parents(sql_path, S_IRWXU|S_IRWXG|S_IRWXO) != 0) {
        g_log_dbproxy(g_critical, "g_mkdir_with_parents(%s) failed: %s", sql_path, g_strerror(errno));
        g_free(sql_path);
        GOTO_EXIT(EXIT_FAILURE);
    }
    g_free(sql_path);
    
    /*
     * check whether we should drop root privileges
     */
#ifndef _win32
    if (srv->user) {
        struct passwd *user_info;
        uid_t user_id= geteuid();
        /* Don't bother if we aren't superuser */
        if (user_id) {
            g_log_dbproxy(g_warning, "current user is not root, --user is ignored");
        } else {
            if (NULL == (user_info = getpwnam(srv->user))) {
                g_log_dbproxy(g_critical, "unknown user: %s", srv->user);
                return -1;
            }

            /* chown log-path */
            if (-1 == chown_recursion(srv->log_path, user_info->pw_uid, user_info->pw_gid)) {
                g_log_dbproxy(g_critical, "chown_recursion(%s) failed: %s", srv->log_path, g_strerror(errno));
                GOTO_EXIT(EXIT_FAILURE);
            }

            setgid(user_info->pw_gid);
            setuid(user_info->pw_uid);
            g_log_dbproxy(g_debug, "running as user: %s (%d/%d)", srv->user, user_info->pw_uid, user_info->pw_gid);

            /*check the config file can read or write, and the config file dir can execute*/
            gchar *config_file = frontend->default_file;

            /*if the config_file is relative get the real path */
            char resolved_path[PATH_MAX];
            if (g_path_is_absolute(config_file) == FALSE) {
                realpath(config_file, resolved_path);
                config_file = resolved_path;
            }

            gchar *config_dir = g_path_get_dirname(config_file);

            if (-1 == faccessat(0, config_file, R_OK | W_OK, AT_EACCESS)
                    || -1 == faccessat(0, config_dir, X_OK | W_OK, AT_EACCESS)) {
                g_free(config_dir);
                g_log_dbproxy(g_critical, "%s don't have correct privilege for the user %s set in the config file, config file should have read write privileges and the config file dir should have execute and write privilege.", config_file, srv->user);
                GOTO_EXIT(EXIT_FAILURE);
            }

            g_free(config_dir);

            g_log_dbproxy(g_message, "running as user: %s (%d/%d)", srv->user, user_info->pw_uid, user_info->pw_gid);
        } 
    }
#endif  

    if (log->log_filename && FALSE == chassis_log_open(log)) {
        g_log_dbproxy(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_log_dbproxy(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;
    }

    if (frontend->log_trace_modules < 0) {
        g_log_dbproxy(g_critical, "log-trace-modules has to be >= 0, is %d", frontend->log_trace_modules);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->log->log_trace_modules = frontend->log_trace_modules;

    if(frontend->db_connect_timeout < 0) {
        g_log_dbproxy(g_critical, "db_connect_timeout has to be >= 0.0, is %lf", frontend->db_connect_timeout);
        GOTO_EXIT(EXIT_FAILURE);
    }
    srv->db_connect_timeout = frontend->db_connect_timeout;

    /*
     * 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;
    }