mirror of https://github.com/sysown/proxysql
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
558 lines
26 KiB
558 lines
26 KiB
#include "proxysql.h"
|
|
|
|
|
|
|
|
//static int init_global_variables(GKeyFile *, int);
|
|
|
|
//global_variables glovars;
|
|
/*
|
|
static global_variable_entry_t glo_entries[]= {
|
|
#ifdef DEBUG
|
|
{"proxysql", "debug", 1, G_OPTION_ARG_INT, &GloVars.global.gdbg, "debugging messages", 0, 1, 0, 0, 0, NULL, NULL, NULL},
|
|
#endif // DEBUG
|
|
{"proxysql", "no-start", 0, G_OPTION_ARG_INT, &glovars.nostart, "Don't start proxysql", 0, 1 , 0, 0, 0, NULL, NULL, NULL},
|
|
{"proxysql", "no-start", 0, G_OPTION_ARG_INT, &GloVars.global.foreground, "Run proxysql in foreground", 0, 1 , 0, 0, 0, NULL, NULL, NULL},
|
|
{"proxysql", "datadir", 0, G_OPTION_ARG_STRING, &glovars.proxy_datadir, "Path to datadir", 0, 0, 0, 0, 0, "/var/run/proxysql", NULL, NULL},
|
|
{"proxysql", "admin_pathdb", 0, G_OPTION_ARG_STRING, &glovars.proxy_admin_pathdb, "Path to internal DB for ProxySQL", 0, 0, 0, 0, 0, "proxysql.db", NULL, NULL},
|
|
{"proxysql", "admin_socket", 0, G_OPTION_ARG_STRING, &glovars.proxy_admin_socket, "ProxySQL admin socket", 0, 0, 0, 0, 0, "proxysql.sock", NULL, NULL},
|
|
//{"global", "core_dump_file_size", 0, G_OPTION_ARG_INT, &glovars.core_dump_file_size, "core dump file size", 0, INT_MAX, 0, 0, 0, NULL, NULL, post_variable_core_dump_file_size},
|
|
{"global", "stack_size", 0, G_OPTION_ARG_INT, &glovars.stack_size, "stack size", 64*1024, 32*1024*1024 , 1024, 0, 512*1024, NULL, NULL, NULL},
|
|
// {"global", "net_buffer_size", 0, G_OPTION_ARG_INT, &glovars.net_buffer_size, "net buffer size", 1024, 16*1024*1024 , 1024, 0, 8*1024, NULL, NULL, NULL},
|
|
{"global", "backlog", 0, G_OPTION_ARG_INT, &glovars.backlog, "backlog for listen()", 50, 10000 , 0, 0, 2000, NULL, NULL, NULL},
|
|
{"global", "merge_configfile_db", 0, G_OPTION_ARG_INT, &glovars.merge_configfile_db, "merge users, hosts and debugs from config file to DB, without replacing DB content", 0, 1, 0, 0, 1, NULL, NULL, NULL},
|
|
{"global", "pid_file", 0, G_OPTION_ARG_STRING, &glovars.proxy_pidfile, "Path to pidfile", 0, 0, 0, 0, 0, "proxysql.pid", NULL, NULL},
|
|
{"global", "error_log", 0, G_OPTION_ARG_STRING, &glovars.proxy_errorlog, "Path to error log", 0, 0, 0, 0, 0, "proxysql.log", NULL, NULL},
|
|
{"global", "debug_log", 0, G_OPTION_ARG_STRING, &glovars.proxy_debuglog, "Path to debug log", 0, 0, 0, 0, 0, "debug.log", NULL, NULL},
|
|
{"global", "restart_on_error", 0, G_OPTION_ARG_INT, &glovars.proxy_restart_on_error, "Restart proxysql in case of crash or error", 0, 1 , 0, 0, 1, NULL, NULL, NULL},
|
|
{"global", "restart_delay", 0, G_OPTION_ARG_INT, &glovars.proxy_restart_delay, "delay between restart", 0, 600 , 0, 0, 5, NULL, NULL, NULL},
|
|
|
|
{"admin", "proxy_admin_pathdb", 0, G_OPTION_ARG_STRING, &glovars.proxy_admin_pathdb, "Path to internal DB for ProxySQL", 0, 0, 0, 0, 0, "proxysql.db", NULL, NULL},
|
|
{"admin", "proxy_admin_bind", 0, G_OPTION_ARG_STRING, &glovars.proxy_admin_bind, "admin bind IP address", 0, 0, 0, 0, 0, "0.0.0.0", NULL, NULL},
|
|
{"admin", "proxy_admin_port", 0, G_OPTION_ARG_INT, &glovars.proxy_admin_port, "administrative port", 0, 65535, 0, 0, 6032, NULL, NULL, NULL},
|
|
{"admin", "proxy_admin_user", 0, G_OPTION_ARG_STRING, &glovars.proxy_admin_user, "proxy admin user", 0, 0, 0, 0, 0, "admin", NULL, NULL},
|
|
{"admin", "proxy_admin_password", 0, G_OPTION_ARG_STRING, &glovars.proxy_admin_password, "proxy admin password", 0, 0, 0, 0, 0, "admin", NULL, NULL},
|
|
{"admin", "proxy_admin_refresh_status_interval", 0, G_OPTION_ARG_INT, &glovars.proxy_admin_refresh_status_interval, "interval to update status variables", 0, 3600, 0, 0, 600, NULL, NULL, NULL},
|
|
|
|
{"admin", "proxy_monitor_bind", 0, G_OPTION_ARG_STRING, &glovars.proxy_monitor_bind, "monitor bind IP address", 0, 0, 0, 0, 0, "0.0.0.0", NULL, NULL},
|
|
{"admin", "proxy_monitor_port", 0, G_OPTION_ARG_INT, &glovars.proxy_monitor_port, "monitoring port", 0, 65535, 0, 0, 6031, NULL, NULL, NULL},
|
|
{"admin", "proxy_monitor_user", 0, G_OPTION_ARG_STRING, &glovars.proxy_monitor_user, "proxy monitoring user", 0, 0, 0, 0, 0, "monitor", NULL, NULL},
|
|
{"admin", "proxy_monitor_password", 0, G_OPTION_ARG_STRING, &glovars.proxy_monitor_password, "proxy monitoring password", 0, 0, 0, 0, 0, "monitor", NULL, NULL},
|
|
{"admin", "proxy_monitor_refresh_status_interval", 0, G_OPTION_ARG_INT, &glovars.proxy_monitor_refresh_status_interval, "interval to update status variables", 0, 3600, 0, 0, 10, NULL, NULL, NULL},
|
|
{"admin", "sync_to_disk_on_flush_command", 0, G_OPTION_ARG_INT, &glovars.admin_sync_disk_on_flush, "sync configuration to disk after every FLUSH command", 0, 1 , 0, 0, 1, NULL, NULL, NULL},
|
|
{"admin", "sync_to_disk_on_shutdown", 0, G_OPTION_ARG_INT, &glovars.admin_sync_disk_on_shutdown, "sync configuration to disk during graceful shutdown", 0, 1 , 0, 0, 1, NULL, NULL, NULL},
|
|
|
|
{"admin", "persistent_statistics_pathdb", 0, G_OPTION_ARG_STRING, &glovars.persistent_statistics_pathdb, "Path to internal DB used for persistent statistics", 0, 0, 0, 0, 0, "querystats.db", NULL, NULL},
|
|
{"admin", "debug_pathdb", 0, G_OPTION_ARG_STRING, &glovars.debug_pathdb, "Path to internal DB used for debugging logging", 0, 0, 0, 0, 0, "debug.db", NULL, NULL},
|
|
|
|
{"http", "http_start", 0, G_OPTION_ARG_INT, &glovars.http_start, "start HTTP server", 0, 1 , 0, 0, 0, NULL, NULL, NULL},
|
|
|
|
{"mysql", "proxy_mysql_bind", 0, G_OPTION_ARG_STRING, &glovars.proxy_mysql_bind, "mysql bind IP address", 0, 0, 0, 0, 0, "0.0.0.0", NULL, NULL},
|
|
{"mysql", "proxy_mysql_port", 0, G_OPTION_ARG_INT, &glovars.proxy_mysql_port, "mysql port", 0, 65535, 0, 0, 6033, NULL, NULL, NULL},
|
|
{"mysql", "mysql_server_version", 0, G_OPTION_ARG_STRING, &glovars.mysql_server_version, "mysql server version", 0, 0, 0, 0, 0, "5.1.30", NULL, NULL},
|
|
{"mysql", "mysql_socket", 0, G_OPTION_ARG_STRING, &glovars.mysql_socket, "mysql socket", 0, 0, 0, 0, 0, "/tmp/proxysql.sock", NULL, NULL},
|
|
{"mysql", "mysql_default_schema", 0, G_OPTION_ARG_STRING, &glovars.mysql_default_schema, "mysql default schema", 0, 0, 0, 0, 0, "information_schema", NULL, NULL},
|
|
// {"mysql", "mysql_connection_pool_enabled", 0, G_OPTION_ARG_INT, &gloconnpool.enabled, "enable/disable connection pool", 0, 1, 0, 0, 1, NULL, NULL, mysql_connpool_init},
|
|
{"mysql", "mysql_parse_trx_cmds", 0, G_OPTION_ARG_INT, &glovars.mysql_parse_trx_cmds, "parse and filter unnecessary transaction commands", 0, 1, 0, 0, 0, NULL, NULL, NULL},
|
|
{"mysql", "mysql_share_connections", 0, G_OPTION_ARG_INT, &glovars.mysql_share_connections, "share mysql connections among clients", 0, 1, 0, 0, 0, NULL, NULL, NULL},
|
|
{"mysql", "mysql_query_cache_enabled", 0, G_OPTION_ARG_INT, &glovars.mysql_query_cache_enabled, "enable/disable query cache", 0, 1, 0, 0, 1, NULL, NULL, NULL},
|
|
{"mysql", "mysql_query_cache_partitions", 0, G_OPTION_ARG_INT, &glovars.mysql_query_cache_partitions, "number of mysql query cache", 1, 128, 0, 0, 16, NULL, NULL, NULL},
|
|
{"mysql", "mysql_query_cache_size", 1, G_OPTION_ARG_INT64, &glovars.mysql_query_cache_size, "mysql query cache size", 1024*1024, LLONG_MAX, 0, 0, 1024*1024, NULL, NULL, NULL},
|
|
{"mysql", "mysql_query_cache_default_timeout", 0, G_OPTION_ARG_INT, &glovars.mysql_query_cache_default_timeout, "default timeout for query cache", 0, 3600*24*365*10, 0, 0, 1, NULL, NULL, NULL},
|
|
{"mysql", "mysql_query_cache_precheck", 1, G_OPTION_ARG_INT, &glovars.mysql_query_cache_precheck, "enable/disable query cache precheck", 0, 1, 0, 0, 1, NULL, NULL, NULL},
|
|
{"mysql", "mysql_query_statistics_enabled", 1, G_OPTION_ARG_INT, &glovars.mysql_query_statistics, "enable/disable the tracker for query statistics", 0, 1, 0, 0, 0, NULL, NULL, NULL},
|
|
{"mysql", "mysql_query_statistics_interval", 1, G_OPTION_ARG_INT, &glovars.mysql_query_statistics_interval, "interval to update query_statistics", 5, 600, 0, 0, 10, NULL, NULL, NULL},
|
|
{"mysql", "mysql_auto_reconnect_enabled", 0, G_OPTION_ARG_INT, &glovars.mysql_auto_reconnect_enabled, "enable/disable auto-reconnect", 0, 1, 0, 0, 0, NULL, NULL, NULL},
|
|
{"mysql", "mysql_usage_user", 0, G_OPTION_ARG_STRING, &glovars.mysql_usage_user, "mysql usage user", 0, 0, 0, 0, 0, "proxy", NULL, NULL},
|
|
{"mysql", "mysql_usage_password", 0, G_OPTION_ARG_STRING, &glovars.mysql_usage_password, "mysql usage password", 0, 0, 0, 0, 0, "proxy", NULL, NULL},
|
|
{"mysql", "mysql_threads", 0, G_OPTION_ARG_INT, &glovars.mysql_threads, "number of threads to handle mysql connections", 1, 128, 0, 0, 2, NULL, NULL, NULL},
|
|
{"mysql", "mysql_threads", 0, G_OPTION_ARG_INT, &glovars.mysql_threads, "number of threads to handle mysql connections", 1, 128, 0, 0, 2, NULL, pre_variable_mysql_threads, NULL},
|
|
{"mysql", "mysql_max_query_size", 1, G_OPTION_ARG_INT, &glovars.mysql_max_query_size, "mysql max size of a COM_QUERY command", 0, 16777210, 0, 0, 1024*1024, NULL, NULL, NULL},
|
|
{"mysql", "mysql_max_resultset_size", 0, G_OPTION_ARG_INT64, &glovars.mysql_max_resultset_size, "mysql max resultset size", 0, INT_MAX, 0, 0, 1024*1024, NULL, NULL, NULL},
|
|
{"mysql", "mysql_poll_timeout", 1, G_OPTION_ARG_INT, &glovars.mysql_poll_timeout, "poll() timeout (in millisecond)", 100, INT_MAX, 0, 0, 10000, NULL, NULL, NULL},
|
|
{"mysql", "mysql_poll_timeout_maintenance", 1, G_OPTION_ARG_INT, &glovars.mysql_poll_timeout_maintenance, "poll() timeout (in millisecond) during maintenance", 100, 1000, 0, 0, 100, NULL, NULL, NULL},
|
|
{"mysql", "mysql_maintenance_timeout", 1, G_OPTION_ARG_INT, &glovars.mysql_maintenance_timeout, "max time to remove mysql servers (in millisecond)", 1000, 60000, 0, 0, 10000, NULL, NULL, NULL},
|
|
{"mysql", "mysql_wait_timeout", 1, G_OPTION_ARG_INT64, &glovars.mysql_wait_timeout, "timeout to drop unused connection", 1, 3600*24*7, 0, 1000000, 3600*8, NULL, NULL, NULL},
|
|
// {"mysql", "mysql_hostgroups", 0, G_OPTION_ARG_INT, &glovars.mysql_hostgroups, "total number of hostgroups", 2, 64, 0, 0, 8, NULL, NULL, init_glomysrvs},
|
|
{"mysql", "mysql_hostgroups", 0, G_OPTION_ARG_INT, &glovars.mysql_hostgroups, "total number of hostgroups", 2, 64, 0, 0, 8, NULL, NULL, NULL},
|
|
// {"fundadb", "fundadb_hash_purge_time", 1, G_OPTION_ARG_INT64, &fdb_system_var.hash_purge_time, "fundadb hash purge time (in millisecond): total time to purge a hash", 100, 600000, 0, 1000, 10000, NULL, NULL, NULL},
|
|
// {"fundadb", "fundadb_hash_purge_loop", 1, G_OPTION_ARG_INT64, &fdb_system_var.hash_purge_loop, "fundadb hash purge loop (in millisecond): time to purge a chunk", 100, 600000, 0, 100, 100, NULL, NULL, NULL},
|
|
// {"fundadb", "fundadb_hash_expire_default", 0, G_OPTION_ARG_INT, &fdb_system_var.hash_expire_default, "fundadb hash default expire (in second)", 1, 3600*24*365*10, 0, 0, 10, NULL, NULL, NULL},
|
|
// {"fundadb", "fundadb_hash_purge_threshold_pct_min", 1, G_OPTION_ARG_INT, &fdb_system_var.purge_threshold_pct_min, "PCT of memory usage to trigger normal purge", 0, 90, 0, 0, 50, NULL, NULL, NULL},
|
|
// {"fundadb", "fundadb_hash_purge_threshold_pct_max", 1, G_OPTION_ARG_INT, &fdb_system_var.purge_threshold_pct_max, "PCT of memory usage to trigger aggressive purge", 50, 100, 0, 0, 90, NULL, NULL, NULL},
|
|
};
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
* Process each group and key defined in glo_entries[]
|
|
* input variable "dyn" defines if this function is called at startup (dyn==0) or during runtime (dyn==1)
|
|
*
|
|
*/
|
|
/*
|
|
void process_global_variables_from_file(GKeyFile *gkf, int dyn) {
|
|
unsigned int i;
|
|
GError *error;
|
|
for (i=0;i<sizeof(glo_entries)/sizeof(global_variable_entry_t);i++) {
|
|
global_variable_entry_t *gve=glo_entries+i;
|
|
// removing the dynamic clause
|
|
// if (dyn > gve->dynamic) {
|
|
// continue;
|
|
// }
|
|
|
|
|
|
// process only [proxysql] section . This is a big and important change from previous version
|
|
if (strcmp(gve->group_name,"proxysql")!=0) {
|
|
continue;
|
|
}
|
|
proxy_debug(PROXY_DEBUG_GENERIC, 4, "Parsing variable %s in [%s] : %s\n", gve->key_name, gve->group_name, gve->description);
|
|
|
|
if (gve->func_pre) {
|
|
// initialize the function via a call to func_pre
|
|
proxy_debug(PROXY_DEBUG_GENERIC, 5, "Variable %s is initialized via function\n", gve->key_name);
|
|
gve->func_pre(gve);
|
|
}
|
|
if ((gkf) && (g_key_file_has_key(gkf, gve->group_name, gve->key_name, NULL))) {
|
|
if (gve->arg == G_OPTION_ARG_STRING) {
|
|
*(char **)gve->arg_data=g_key_file_get_string(gkf, gve->group_name, gve->key_name, &error);
|
|
}
|
|
if (gve->arg == G_OPTION_ARG_INT || gve->arg == G_OPTION_ARG_INT64) {
|
|
*(int *)gve->arg_data=gve->int_default;
|
|
gint r=g_key_file_get_integer(gkf, gve->group_name, gve->key_name, &error);
|
|
if (r < gve->value_min ) { r=gve->value_min; }
|
|
if (r > gve->value_max ) { r=gve->value_max; }
|
|
if ( gve->value_round ) { r=r/gve->value_round; r=r*gve->value_round; }
|
|
if (gve->arg == G_OPTION_ARG_INT) {
|
|
*(int *)gve->arg_data=r*(gve->value_multiplier > 0 ? gve->value_multiplier : 1 );
|
|
} else {
|
|
long long nr=(long long) r*(gve->value_multiplier > 0 ? gve->value_multiplier : 1 );
|
|
memcpy(gve->arg_data,&nr,sizeof(long long));
|
|
}
|
|
}
|
|
} else {
|
|
if (gve->func_pre == NULL) {
|
|
// set defaults
|
|
if (gve->arg == G_OPTION_ARG_STRING) {
|
|
*(char **)gve->arg_data=strdup(gve->char_default);
|
|
}
|
|
if (gve->arg == G_OPTION_ARG_INT) {
|
|
*(int *)gve->arg_data=gve->int_default*(gve->value_multiplier > 0 ? gve->value_multiplier : 1 );
|
|
}
|
|
if (gve->arg == G_OPTION_ARG_INT64) {
|
|
// *(long long *)gve->arg_data= (long long) gve->int_default*(gve->value_multiplier > 0 ? gve->value_multiplier : 1 );
|
|
long long r=(long long) gve->int_default*(gve->value_multiplier > 0 ? gve->value_multiplier : 1 );
|
|
memcpy(gve->arg_data,&r,sizeof(long long));
|
|
}
|
|
}
|
|
}
|
|
|
|
// after setting the variable, a post function is executed
|
|
if (gve->func_post) {
|
|
proxy_debug(PROXY_DEBUG_GENERIC, 5, "Variable %s has post function\n", gve->key_name);
|
|
gve->func_post(gve);
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
/*
|
|
void init_signal_handlers() {
|
|
signal(SIGSEGV, crash_handler);
|
|
signal(SIGABRT, crash_handler);
|
|
signal(SIGTERM, term_handler);
|
|
// signal(SIGHUP, sighup_handler);
|
|
}
|
|
*/
|
|
|
|
/*
|
|
int config_file_is_readable(char *config_file) {
|
|
// check if file exists and is readable
|
|
if (!g_file_test(config_file,(GFileTest)(G_FILE_TEST_EXISTS|G_FILE_TEST_IS_REGULAR))) {
|
|
g_print("Config file %s does not exist\n", config_file);
|
|
return 0;
|
|
}
|
|
if (access(config_file, R_OK)) {
|
|
g_print("Config file %s is not readable\n", config_file);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
*/
|
|
|
|
|
|
/*
|
|
void main_opts(gint *argc, gchar ***argv) {
|
|
|
|
|
|
// Prepare the processing of config file
|
|
GKeyFile *keyfile=NULL;
|
|
int rc;
|
|
GError *error = NULL;
|
|
GOptionContext *context;
|
|
|
|
// TODO NEW: init_signal_handlers();
|
|
|
|
GloVars.__cmd_proxysql_gdbg=-1; // fake setting
|
|
GloVars.__cmd_proxysql_foreground=-1; // fake setting
|
|
GloVars.__cmd_proxysql_nostart=-1; // fake setting
|
|
GloVars.__cmd_proxysql_admin_socket=NULL;
|
|
GloVars.__cmd_proxysql_admin_pathdb=NULL;
|
|
GloVars.__cmd_proxysql_datadir=NULL;
|
|
|
|
context = g_option_context_new ("- High Performance Advanced Proxy for MySQL");
|
|
g_option_context_add_main_entries (context, cmd_option_entries, NULL);
|
|
// g_option_context_add_group (context, gtk_get_option_group (TRUE));
|
|
//if (!g_option_context_parse (context, &argc, &argv, &error))
|
|
if (!g_option_context_parse (context, argc, argv, &error))
|
|
{
|
|
g_print ("option parsing failed: %s\n", error->message);
|
|
exit (1);
|
|
}
|
|
|
|
if (GloVars.__cmd_proxysql_print_version==1) {
|
|
fprintf(stderr,"ProxySQL version %s, codename %s\n", PROXYSQL_VERSION, PROXYSQL_CODENAME);
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
init_debug_struct();
|
|
#endif
|
|
|
|
proxy_debug(PROXY_DEBUG_GENERIC, 4, "processing opts\n");
|
|
|
|
//gchar *config_file=*config_file_ptr;
|
|
gchar *config_file=GloVars.__cmd_proxysql_config_file;
|
|
|
|
if (config_file==NULL) {
|
|
config_file=(char *)"proxysql.cnf";
|
|
if (!g_file_test(config_file,(GFileTest)(G_FILE_TEST_EXISTS|G_FILE_TEST_IS_REGULAR))) {
|
|
config_file=(char *)"/etc/proxysql.cnf";
|
|
}
|
|
}
|
|
|
|
rc=config_file_is_readable(config_file);
|
|
if (rc==0) {
|
|
proxy_error("Config file does not exist, using defaults\n");
|
|
init_global_variables(keyfile, 0);
|
|
// exit(EXIT_FAILURE);
|
|
} else {
|
|
//
|
|
// keyfile = g_key_file_new();
|
|
// if (!g_key_file_load_from_file(keyfile, config_file, G_KEY_FILE_NONE, &error)) {
|
|
// g_print ("Error loading config file %s: %s\n", config_file, error->message);
|
|
// exit(EXIT_FAILURE);
|
|
// }
|
|
//
|
|
// // initialize variables and process config file
|
|
// init_global_variables(keyfile, 0);
|
|
//
|
|
// g_key_file_free(keyfile);
|
|
// glovars.proxy_configfile=config_file;
|
|
//
|
|
}
|
|
g_option_context_free(context);
|
|
|
|
|
|
// apply settings from cmdline, that have priority over config file
|
|
#ifdef DEBUG
|
|
if (GloVars.__cmd_proxysql_gdbg>=0) { GloVars.global.gdbg=GloVars.__cmd_proxysql_gdbg; }
|
|
#endif
|
|
if (GloVars.__cmd_proxysql_foreground>=0) { foreground=GloVars.__cmd_proxysql_foreground; }
|
|
if (GloVars.__cmd_proxysql_nostart>=0) { glovars.nostart=GloVars.__cmd_proxysql_nostart; }
|
|
if (GloVars.__cmd_proxysql_datadir) {
|
|
g_free(glovars.proxy_datadir);
|
|
glovars.proxy_datadir=strdup(GloVars.__cmd_proxysql_datadir);
|
|
}
|
|
if (GloVars.__cmd_proxysql_admin_pathdb) {
|
|
g_free(glovars.proxy_admin_pathdb);
|
|
glovars.proxy_admin_pathdb=strdup(GloVars.__cmd_proxysql_admin_pathdb);
|
|
}
|
|
if (GloVars.__cmd_proxysql_admin_socket) {
|
|
g_free(glovars.proxy_admin_socket);
|
|
glovars.proxy_admin_socket=strdup(GloVars.__cmd_proxysql_admin_socket);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if (GloVars.global.gdbg) {
|
|
fprintf(stderr,"ProxySQL version %s, codename %s\n", PROXYSQL_VERSION, PROXYSQL_CODENAME);
|
|
fprintf(stderr,"Options:\n gdbg: %d\n version: %d\n foreground: %d\n no-start: %d\n config: %s\n datadir: %s\n admin_pathdb: %s\n admin_socket: %s\n", GloVars.global.gdbg, GloVars.__cmd_proxysql_print_version, foreground, glovars.nostart, glovars.proxy_configfile, glovars.proxy_datadir, glovars.proxy_admin_pathdb, glovars.proxy_admin_socket);
|
|
}
|
|
#endif
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
static int init_global_variables(GKeyFile *gkf, int runtime) {
|
|
//int i;
|
|
//GError *error=NULL;
|
|
|
|
// open the file and verify it has [proxysql] section
|
|
if (gkf) {
|
|
proxy_debug(PROXY_DEBUG_GENERIC, 1, "Checking [proxysql] section\n");
|
|
if (g_key_file_has_group(gkf,"proxysql")==FALSE) {
|
|
//g_print("[proxysql] section not found\n");
|
|
proxy_error("[proxysql] section not found in config file, using defaults\n");
|
|
*/
|
|
/* if (runtime==0) {
|
|
exit(EXIT_FAILURE);
|
|
} else {
|
|
return -1;
|
|
}
|
|
*/
|
|
// }
|
|
// }
|
|
|
|
/* Stop reading [global] from config file
|
|
// open the file and verify it has [global] section
|
|
proxy_debug(PROXY_DEBUG_GENERIC, 1, "Checking [global]\n");
|
|
if (g_key_file_has_group(gkf,"global")==FALSE) {
|
|
g_print("[global] section not found\n");
|
|
if (runtime==0) {
|
|
exit(EXIT_FAILURE);
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
*/
|
|
/* stop reading [mysql users] from config file
|
|
// open the file and verify it has [mysql users] section
|
|
proxy_debug(PROXY_DEBUG_GENERIC, 1, "Checking [mysql users]\n");
|
|
if (g_key_file_has_group(gkf,"mysql users")==FALSE) {
|
|
g_print("[mysql users] section not found\n");
|
|
if (runtime==0) {
|
|
exit(EXIT_FAILURE);
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
*/
|
|
/* stop reading [debug] from config file
|
|
// processing [debug] section
|
|
proxy_debug(PROXY_DEBUG_GENERIC, 1, "Processing [debug]\n");
|
|
if (g_key_file_has_group(gkf,"debug")==FALSE) {
|
|
proxy_debug(PROXY_DEBUG_GENERIC, 1, "[debug] missing\n");
|
|
memset(gdbg_lvl,0,sizeof(int)*PROXY_DEBUG_UNKNOWN);
|
|
} else {
|
|
int i;
|
|
for (i=0; i<PROXY_DEBUG_UNKNOWN; i++) {
|
|
gdbg_lvl[i].verbosity=0;
|
|
if (g_key_file_has_key(gkf, "debug", gdbg_lvl[i].name, NULL)) {
|
|
gint r=g_key_file_get_integer(gkf, "debug", gdbg_lvl[i].name, &error);
|
|
if (r >= 0 ) { gdbg_lvl[i].verbosity=r; }
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
/*
|
|
if (runtime==0) {
|
|
//pthread_rwlock_init(&glovars.rwlock_global, NULL);
|
|
pthread_rwlock_init(&glovars.rwlock_usernames, NULL);
|
|
glovars.protocol_version=10;
|
|
//glovars.server_version="5.0.15";
|
|
glovars.server_capabilities= CLIENT_FOUND_ROWS | CLIENT_PROTOCOL_41 | CLIENT_IGNORE_SIGPIPE | CLIENT_TRANSACTIONS | CLIENT_SECURE_CONNECTION | CLIENT_CONNECT_WITH_DB;
|
|
// glovars.server_capabilities=0xffff;
|
|
glovars.server_language=33;
|
|
glovars.server_status=2;
|
|
glovars.thread_id=1;
|
|
glovars.shutdown=0;
|
|
//fdb_system_var.hash_expire_max=3600*24*365*10;
|
|
|
|
}
|
|
|
|
|
|
// init gloQR
|
|
// if (runtime==0) {
|
|
// init_gloQR();
|
|
// }
|
|
|
|
//pthread_rwlock_wrlock(&glovars.rwlock_global);
|
|
|
|
|
|
|
|
// create the connection pool
|
|
//mysql_connpool_init();
|
|
|
|
|
|
|
|
|
|
|
|
//pthread_rwlock_unlock(&glovars.rwlock_global);
|
|
process_global_variables_from_file(gkf, 0);
|
|
|
|
if (runtime==0) {
|
|
// load_mysql_servers_list_from_file(gkf);
|
|
// load_mysql_users_from_file(gkf);
|
|
}
|
|
|
|
// if (fdb_system_var.hash_purge_loop > fdb_system_var.hash_purge_time) {
|
|
// fdb_system_var.hash_purge_loop=fdb_system_var.hash_purge_time;
|
|
// }
|
|
|
|
return 0;
|
|
}
|
|
*/
|
|
/*
|
|
mysql_server * new_server_master() {
|
|
pthread_rwlock_wrlock(&glomysrvs.rwlock);
|
|
if ( glomysrvs.count_masters==0 ) return NULL;
|
|
int i=rand()%glomysrvs.count_masters;
|
|
mysql_server *ms=l_ptr_array_index(glomysrvs.servers_masters,i);
|
|
proxy_debug(PROXY_DEBUG_MYSQL_SERVER, 4, "Using master %s port %d , index %d from a pool of %d servers\n", ms->address, ms->port, i, glomysrvs.count_masters);
|
|
pthread_rwlock_unlock(&glomysrvs.rwlock);
|
|
return ms;
|
|
}
|
|
|
|
mysql_server * new_server_slave() {
|
|
pthread_rwlock_wrlock(&glomysrvs.rwlock);
|
|
if ( glomysrvs.count_slaves==0 ) return NULL;
|
|
int i=rand()%glomysrvs.count_slaves;
|
|
mysql_server *ms=l_ptr_array_index(glomysrvs.servers_slaves,i);
|
|
proxy_debug(PROXY_DEBUG_MYSQL_SERVER, 4, "Using slave %s port %d , index %d from a pool of %d servers\n", ms->address, ms->port, i, glomysrvs.count_slaves);
|
|
pthread_rwlock_unlock(&glomysrvs.rwlock);
|
|
return ms;
|
|
}
|
|
|
|
|
|
void init_glomysrvs(global_variable_entry_t *gve) {
|
|
pthread_rwlock_init(&glomysrvs.rwlock, NULL);
|
|
glomysrvs.mysql_connections_max=10000; // hardcoded for now , theorically no limit : NOT USED YET
|
|
glomysrvs.mysql_connections_cur=0; // hardcoded for now
|
|
glomysrvs.mysql_connections=g_ptr_array_sized_new(glomysrvs.mysql_connections_max/10+4);
|
|
glomysrvs.servers=g_ptr_array_new();
|
|
glomysrvs.servers_masters=g_ptr_array_new();
|
|
glomysrvs.servers_slaves=g_ptr_array_new();
|
|
glomysrvs.servers_count=0;
|
|
glomysrvs.count_masters=0;
|
|
glomysrvs.count_slaves=0;
|
|
proxy_debug(PROXY_DEBUG_MYSQL_SERVER, 5, "Creating %d hostgroups for MySQL\n", glovars.mysql_hostgroups);
|
|
glomysrvs.mysql_hostgroups=g_ptr_array_sized_new(glovars.mysql_hostgroups);
|
|
int i;
|
|
for(i=0;i<glovars.mysql_hostgroups;i++) {
|
|
GPtrArray *sl=g_ptr_array_new();
|
|
g_ptr_array_add(glomysrvs.mysql_hostgroups,sl);
|
|
}
|
|
}
|
|
|
|
void load_mysql_users_from_file(GKeyFile *gkf) {
|
|
GError *error;
|
|
// load usernames and password
|
|
pthread_rwlock_wrlock(&glovars.rwlock_usernames);
|
|
glovars.mysql_users_name=g_ptr_array_new();
|
|
glovars.mysql_users_pass=g_ptr_array_new();
|
|
glovars.usernames = g_hash_table_new(g_str_hash, g_str_equal);
|
|
//gchar **users_keys=NULL;
|
|
gsize l=0;
|
|
gchar **mysql_users_name=NULL;
|
|
gchar **mysql_users_pass=NULL;
|
|
mysql_users_name=g_key_file_get_keys(gkf, "mysql users", &l, &error);
|
|
if (l==0) {
|
|
g_print("No mysql users defined in [mysql users]\n"); exit(EXIT_FAILURE);
|
|
} else {
|
|
mysql_users_pass=g_strdupv(mysql_users_name);
|
|
int i;
|
|
for (i=0; i<l; i++) {
|
|
g_free(mysql_users_pass[i]);
|
|
mysql_users_pass[i]=g_key_file_get_string(gkf, "mysql users", mysql_users_name[i], &error);
|
|
if (mysql_users_pass[i]==NULL) {
|
|
g_print("Error in password for user %s\n", mysql_users_name[i]); exit(EXIT_FAILURE);
|
|
}
|
|
proxy_debug(PROXY_DEBUG_MYSQL_AUTH, 4, "Adding user %s password _OMITTED_ (%d)\n", mysql_users_name[i], strlen(mysql_users_pass[i]));
|
|
g_ptr_array_add(glovars.mysql_users_name,g_strdup(mysql_users_name[i]));
|
|
g_ptr_array_add(glovars.mysql_users_pass,g_strdup(mysql_users_pass[i]));
|
|
g_hash_table_insert(glovars.usernames, l_ptr_array_index(glovars.mysql_users_name,i), l_ptr_array_index(glovars.mysql_users_pass,i));
|
|
|
|
}
|
|
}
|
|
g_strfreev(mysql_users_name);
|
|
g_strfreev(mysql_users_pass);
|
|
pthread_rwlock_unlock(&glovars.rwlock_usernames);
|
|
}
|
|
|
|
void load_mysql_servers_list_from_file(GKeyFile *gkf) {
|
|
GError *error;
|
|
// this needs to be deprecated
|
|
glomysrvs.mysql_use_masters_for_reads=1;
|
|
if (g_key_file_has_key(gkf, "mysql", "mysql_use_masters_for_reads", NULL)) {
|
|
gint r=g_key_file_get_integer(gkf, "mysql", "mysql_use_masters_for_reads", &error);
|
|
if (r == 0 ) {
|
|
glomysrvs.mysql_use_masters_for_reads=0;
|
|
}
|
|
}
|
|
|
|
|
|
pthread_rwlock_wrlock(&glomysrvs.rwlock);
|
|
// load all servers
|
|
if (g_key_file_has_key(gkf, "mysql", "mysql_servers", NULL)) {
|
|
gsize l=0;
|
|
glomysrvs.mysql_servers_name=g_key_file_get_string_list(gkf, "mysql", "mysql_servers", &l, &error);
|
|
int i;
|
|
for (i=0; i<l; i++) {
|
|
char *c;
|
|
c=index(glomysrvs.mysql_servers_name[i],':');
|
|
mysql_server *ms=g_slice_alloc0(sizeof(mysql_server));
|
|
if (ms==NULL) { exit(EXIT_FAILURE); }
|
|
if (c) {
|
|
int sl=strlen(glomysrvs.mysql_servers_name[i]);
|
|
char *s=g_malloc0(sl);
|
|
// if ((s=malloc(sl))==NULL) { exit(EXIT_FAILURE); }
|
|
char *p=g_malloc0(sl);
|
|
// if ((p=malloc(sl))==NULL) { exit(EXIT_FAILURE); }
|
|
*c=' ';
|
|
sscanf(glomysrvs.mysql_servers_name[i],"%s %s",s,p);
|
|
ms->address=g_strdup(s);
|
|
ms->port=atoi(p);
|
|
g_free(s);
|
|
g_free(p);
|
|
} else {
|
|
ms->address=g_strdup(glomysrvs.mysql_servers_name[i]);
|
|
ms->port=3306;
|
|
}
|
|
//char *buff=g_malloc0(strlen(ms->address)+10);
|
|
//sprintf(buff,"%s_%d",ms->address,ms->port);
|
|
//ms->name=g_strdup(buff);
|
|
//g_free(buff);
|
|
proxy_debug(PROXY_DEBUG_MYSQL_SERVER, 3, "Configuring server %s:%d from config file\n", ms->address, ms->port);
|
|
mysql_server *mst=find_server_ptr(ms->address,ms->port);
|
|
if (mst==NULL) {
|
|
int ro=mysql_check_alive_and_read_only(ms->address, ms->port);
|
|
if ( ro>=0 ) ms->read_only=ro;
|
|
if ( ro>=0 ) {
|
|
ms->status=MYSQL_SERVER_STATUS_ONLINE;
|
|
} else {
|
|
ms->status=MYSQL_SERVER_STATUS_OFFLINE_HARD;
|
|
}
|
|
mysql_server_entry_add(ms);
|
|
} else {
|
|
g_free(ms->address);
|
|
g_slice_free1(sizeof(mysql_server),ms);
|
|
}
|
|
}
|
|
} else {
|
|
// This needs to go away. Servers can be configured in sqlite, or added alter on
|
|
g_print("mysql_servers not defined in [mysql]\n"); exit(EXIT_FAILURE);
|
|
}
|
|
pthread_rwlock_unlock(&glomysrvs.rwlock);
|
|
}
|
|
*/
|
|
|
|
// configure the number of threads as number of cores times 2
|
|
void pre_variable_mysql_threads(global_variable_entry_t *gve) {
|
|
int rc=sysconf(_SC_NPROCESSORS_ONLN)*2;
|
|
assert(rc>0);
|
|
*(int *)gve->arg_data=rc;
|
|
}
|
|
|
|
|
|
/*
|
|
void post_variable_core_dump_file_size(global_variable_entry_t *gve) {
|
|
int r=*(int *)gve->arg_data;
|
|
struct rlimit rlim;
|
|
rlim.rlim_cur=r;
|
|
rlim.rlim_max=r;
|
|
int rc;
|
|
rc=setrlimit(RLIMIT_CORE,&rlim);
|
|
assert(rc==0);
|
|
}
|
|
*/
|