Task ID 499:Add a new settable string variable(init_connect, init_slave)

to mysqld that is executed for all new connections.
(Similar to the client command: mysql_options(... MYSQL_INIT_COMMAND ...).
parent 333bddb3
...@@ -499,6 +499,8 @@ bool wait_for_tables(THD *thd); ...@@ -499,6 +499,8 @@ bool wait_for_tables(THD *thd);
bool table_is_used(TABLE *table, bool wait_for_name_lock); bool table_is_used(TABLE *table, bool wait_for_name_lock);
bool drop_locked_tables(THD *thd,const char *db, const char *table_name); bool drop_locked_tables(THD *thd,const char *db, const char *table_name);
void abort_locked_tables(THD *thd,const char *db, const char *table_name); void abort_locked_tables(THD *thd,const char *db, const char *table_name);
void execute_init_command(THD *thd, sys_var_str *init_command_var,
rw_lock_t *var_mutex);
extern const Field *not_found_field; extern const Field *not_found_field;
Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
TABLE_LIST **where, bool report_error); TABLE_LIST **where, bool report_error);
......
...@@ -3655,10 +3655,10 @@ Disable with --skip-bdb (will save memory).", ...@@ -3655,10 +3655,10 @@ Disable with --skip-bdb (will save memory).",
#endif /* End HAVE_INNOBASE_DB */ #endif /* End HAVE_INNOBASE_DB */
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
0, 0, 0, 0, 0}, 0, 0, 0, 0, 0},
{"init-connect", OPT_INIT_CONNECT, "Command what executes for all new connections", {"init-connect", OPT_INIT_CONNECT, "Command(s) that are executed for each new connection",
(gptr*) &opt_init_connect, (gptr*) &opt_init_connect, 0, GET_STR_ALLOC, REQUIRED_ARG, (gptr*) &opt_init_connect, (gptr*) &opt_init_connect, 0, GET_STR_ALLOC, REQUIRED_ARG,
0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0},
{"init-slave", OPT_INIT_SLAVE, "Command what is executed when replication is starting", {"init-slave", OPT_INIT_SLAVE, "Command(s) that are executed when a slave connects to this master",
(gptr*) &opt_init_slave, (gptr*) &opt_init_slave, 0, GET_STR_ALLOC, REQUIRED_ARG, (gptr*) &opt_init_slave, (gptr*) &opt_init_slave, 0, GET_STR_ALLOC, REQUIRED_ARG,
0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0},
{"init-file", OPT_INIT_FILE, "Read SQL commands from this file at startup.", {"init-file", OPT_INIT_FILE, "Read SQL commands from this file at startup.",
......
...@@ -92,7 +92,6 @@ void send_error(THD *thd, uint sql_errno, const char *err) ...@@ -92,7 +92,6 @@ void send_error(THD *thd, uint sql_errno, const char *err)
/* In bootstrap it's ok to print on stderr */ /* In bootstrap it's ok to print on stderr */
fprintf(stderr,"ERROR: %d %s\n",sql_errno,err); fprintf(stderr,"ERROR: %d %s\n",sql_errno,err);
} }
thd->init_connect_error= 1;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -211,7 +210,6 @@ net_printf(THD *thd, uint errcode, ...) ...@@ -211,7 +210,6 @@ net_printf(THD *thd, uint errcode, ...)
fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos); fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos);
thd->fatal_error(); thd->fatal_error();
} }
thd->init_connect_error= 1;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -674,14 +674,23 @@ struct show_var_st init_vars[]= { ...@@ -674,14 +674,23 @@ struct show_var_st init_vars[]= {
*/ */
static bool sys_update_init_connect(THD *thd, set_var *var) /*
Update variables 'init_connect, init_slave'.
In case of 'DEFAULT' value
(for example: 'set GLOBAL init_connect=DEFAULT')
'var' parameter is NULL pointer.
*/
bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex,
set_var *var)
{ {
char *res= 0, *old_value; char *res= 0, *old_value;
uint new_length; uint new_length= 0;
/* If the string is "", delete old init command */ /* If the string is "", delete old init command */
if ((new_length= var->value->str_value.length())) if (var && (new_length= var->value->str_value.length()))
{ {
if (!(res= my_strdup_with_length(var->value->str_value.c_ptr(), if (!(res= my_strdup_with_length(var->value->str_value.ptr(),
new_length, new_length,
MYF(0)))) MYF(0))))
return 1; return 1;
...@@ -690,63 +699,37 @@ static bool sys_update_init_connect(THD *thd, set_var *var) ...@@ -690,63 +699,37 @@ static bool sys_update_init_connect(THD *thd, set_var *var)
Replace the old value in such a way that the any thread using Replace the old value in such a way that the any thread using
the value will work. the value will work.
*/ */
rw_wrlock(&LOCK_sys_init_connect); rw_wrlock(var_mutex);
old_value= sys_init_connect.value; old_value= var_str->value;
sys_init_connect.value= res; var_str->value= res;
sys_init_connect.value_length= new_length; var_str->value_length= new_length;
rw_unlock(&LOCK_sys_init_connect); rw_unlock(var_mutex);
my_free(old_value, MYF(MY_ALLOW_ZERO_PTR)); my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
return 0; return 0;
} }
static bool sys_update_init_connect(THD *thd, set_var *var)
{
return update_sys_var_str(&sys_init_connect, &LOCK_sys_init_connect, var);
}
static void sys_default_init_connect(THD* thd, enum_var_type type) static void sys_default_init_connect(THD* thd, enum_var_type type)
{ {
char *old_value; update_sys_var_str(&sys_init_connect, &LOCK_sys_init_connect, 0);
rw_wrlock(&LOCK_sys_init_connect);
old_value= sys_init_connect.value;
sys_init_connect.value= 0;
sys_init_connect.value_length= 0;
rw_unlock(&LOCK_sys_init_connect);
my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
} }
static bool sys_update_init_slave(THD *thd, set_var *var) static bool sys_update_init_slave(THD *thd, set_var *var)
{ {
char *res= 0, *old_value; return update_sys_var_str(&sys_init_slave, &LOCK_sys_init_slave, var);
uint new_length;
/* If the string is "", delete old init command */
if ((new_length= var->value->str_value.length()))
{
if (!(res= my_strdup_with_length(var->value->str_value.c_ptr(),
new_length,
MYF(0))))
return 1;
}
/*
Replace the old value in such a way that the any thread using
the value will work.
*/
rw_wrlock(&LOCK_sys_init_slave);
old_value= sys_init_slave.value;
sys_init_slave.value= res;
sys_init_slave.value_length= new_length;
rw_unlock(&LOCK_sys_init_slave);
my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
return 0;
} }
static void sys_default_init_slave(THD* thd, enum_var_type type) static void sys_default_init_slave(THD* thd, enum_var_type type)
{ {
char *old_value; update_sys_var_str(&sys_init_slave, &LOCK_sys_init_slave, 0);
rw_wrlock(&LOCK_sys_init_slave);
old_value= sys_init_slave.value;
sys_init_slave.value= 0;
sys_init_slave.value_length= 0;
rw_unlock(&LOCK_sys_init_slave);
my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
} }
......
...@@ -2448,24 +2448,6 @@ log space"); ...@@ -2448,24 +2448,6 @@ log space");
} }
void init_slave_execute(THD *thd, sys_var_str *init_slave_var)
{
Vio* save_vio;
ulong save_client_capabilities;
thd->proc_info= "Execution of init_slave";
thd->query= init_slave_var->value;
thd->query_length= init_slave_var->value_length;
save_client_capabilities= thd->client_capabilities;
thd->client_capabilities|= CLIENT_MULTI_QUERIES;
save_vio= thd->net.vio;
thd->net.vio= 0;
dispatch_command(COM_QUERY, thd, thd->query, thd->query_length+1);
thd->client_capabilities= save_client_capabilities;
thd->net.vio= save_vio;
}
/* Slave SQL Thread entry point */ /* Slave SQL Thread entry point */
extern "C" pthread_handler_decl(handle_slave_sql,arg) extern "C" pthread_handler_decl(handle_slave_sql,arg)
...@@ -2551,9 +2533,7 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME, ...@@ -2551,9 +2533,7 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
/* execute init_slave variable */ /* execute init_slave variable */
if (sys_init_slave.value) if (sys_init_slave.value)
{ {
rw_wrlock(&LOCK_sys_init_slave); execute_init_command(thd, &sys_init_slave, &LOCK_sys_init_slave);
init_slave_execute(thd, &sys_init_slave);
rw_unlock(&LOCK_sys_init_slave);
if (thd->query_error) if (thd->query_error)
{ {
sql_print_error("\ sql_print_error("\
......
...@@ -121,7 +121,6 @@ THD::THD():user_time(0), is_fatal_error(0), ...@@ -121,7 +121,6 @@ THD::THD():user_time(0), is_fatal_error(0),
system_thread=cleanup_done=0; system_thread=cleanup_done=0;
peer_port= 0; // For SHOW PROCESSLIST peer_port= 0; // For SHOW PROCESSLIST
transaction.changed_tables = 0; transaction.changed_tables = 0;
init_connect_error= 0;
#ifdef __WIN__ #ifdef __WIN__
real_id = 0; real_id = 0;
#endif #endif
......
...@@ -560,7 +560,6 @@ class THD :public ilink ...@@ -560,7 +560,6 @@ class THD :public ilink
bool prepare_command; bool prepare_command;
bool tmp_table_used; bool tmp_table_used;
bool init_connect_error;
/* /*
If we do a purge of binary logs, log index info of the threads If we do a purge of binary logs, log index info of the threads
that are currently reading it needs to be adjusted. To do that that are currently reading it needs to be adjusted. To do that
......
...@@ -794,19 +794,31 @@ check_connections(THD *thd) ...@@ -794,19 +794,31 @@ check_connections(THD *thd)
} }
void init_connect_execute(THD *thd, sys_var_str *init_connect_var) void execute_init_command(THD *thd, sys_var_str *init_command_var,
rw_lock_t *var_mutex)
{ {
Vio* save_vio; Vio* save_vio;
ulong save_client_capabilities; ulong save_client_capabilities;
thd->proc_info= "Execution of init_connect"; thd->proc_info= "Execution of init_command";
thd->query= init_connect_var->value; /*
thd->query_length= init_connect_var->value_length; We need to lock init_command_var because
during execution of init_command_var query
values of init_command_var can't be changed
*/
rw_rdlock(var_mutex);
thd->query= init_command_var->value;
thd->query_length= init_command_var->value_length;
save_client_capabilities= thd->client_capabilities; save_client_capabilities= thd->client_capabilities;
thd->client_capabilities|= CLIENT_MULTI_QUERIES; thd->client_capabilities|= CLIENT_MULTI_QUERIES;
/*
We don't need return result of execution to client side.
To forbid this we should set thd->net.vio to 0.
*/
save_vio= thd->net.vio; save_vio= thd->net.vio;
thd->net.vio= 0; thd->net.vio= 0;
dispatch_command(COM_QUERY, thd, thd->query, thd->query_length+1); dispatch_command(COM_QUERY, thd, thd->query, thd->query_length+1);
rw_unlock(var_mutex);
thd->client_capabilities= save_client_capabilities; thd->client_capabilities= save_client_capabilities;
thd->net.vio= save_vio; thd->net.vio= save_vio;
} }
...@@ -887,29 +899,9 @@ pthread_handler_decl(handle_one_connection,arg) ...@@ -887,29 +899,9 @@ pthread_handler_decl(handle_one_connection,arg)
thd->version= refresh_version; thd->version= refresh_version;
if (sys_init_connect.value && !(thd->master_access & SUPER_ACL)) if (sys_init_connect.value && !(thd->master_access & SUPER_ACL))
{ {
rw_wrlock(&LOCK_sys_init_connect); execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
init_connect_execute(thd, &sys_init_connect); if (thd->query_error)
rw_unlock(&LOCK_sys_init_connect); thd->killed= 1;
if (thd->init_connect_error)
{
if (thd->user_connect)
decrease_user_connections(thd->user_connect);
free_root(&thd->mem_root,MYF(0));
if (!thd->killed && thd->variables.log_warnings)
{
sql_print_error(ER(ER_NEW_ABORTING_CONNECTION),
thd->thread_id,(thd->db ? thd->db : "unconnected"),
thd->user ? thd->user : "unauthenticated",
thd->host_or_ip,
"Can't execute init_connect query");
statistic_increment(aborted_threads,&LOCK_status);
}
else if (thd->killed)
{
statistic_increment(aborted_threads,&LOCK_status);
}
goto end_thread;
}
} }
thd->proc_info=0; thd->proc_info=0;
......
...@@ -1618,10 +1618,10 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, ...@@ -1618,10 +1618,10 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
break; break;
case SHOW_CHAR_PTR: case SHOW_CHAR_PTR:
{ {
if (!(pos= *(char**) value)) if (!(pos= *(char**) value))
pos= ""; pos= "";
end= strend(pos); end= strend(pos);
break; break;
} }
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
/* First group - functions relying on CTX */ /* First group - functions relying on CTX */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment