summaryrefslogtreecommitdiff
path: root/sql/sql_connect.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_connect.cc')
-rw-r--r--sql/sql_connect.cc164
1 files changed, 141 insertions, 23 deletions
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index 7821b96b9bb..c02db1b3947 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -827,14 +827,17 @@ bool thd_init_client_charset(THD *thd, uint cs_number)
Initialize connection threads
*/
+#ifndef EMBEDDED_LIBRARY
bool init_new_connection_handler_thread()
{
pthread_detach_this_thread();
if (my_thread_init())
{
+ statistic_increment(aborted_connects,&LOCK_status);
statistic_increment(connection_errors_internal, &LOCK_status);
return 1;
}
+ DBUG_EXECUTE_IF("simulate_failed_connection_1", return(1); );
return 0;
}
@@ -850,7 +853,6 @@ bool init_new_connection_handler_thread()
1 error
*/
-#ifndef EMBEDDED_LIBRARY
static int check_connection(THD *thd)
{
uint connect_errors= 0;
@@ -951,6 +953,7 @@ static int check_connection(THD *thd)
this is treated as a global server OOM error.
TODO: remove the need for my_strdup.
*/
+ statistic_increment(aborted_connects,&LOCK_status);
statistic_increment(connection_errors_internal, &LOCK_status);
return 1; /* The error is set by my_strdup(). */
}
@@ -968,7 +971,7 @@ static int check_connection(THD *thd)
if (thd->main_security_ctx.host)
{
if (thd->main_security_ctx.host != my_localhost)
- thd->main_security_ctx.host[MY_MIN(strlen(thd->main_security_ctx.host),
+ ((char*) thd->main_security_ctx.host)[MY_MIN(strlen(thd->main_security_ctx.host),
HOSTNAME_LENGTH)]= 0;
thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
}
@@ -1016,6 +1019,7 @@ static int check_connection(THD *thd)
Hence, there is no reason to account on OOM conditions per client IP,
we count failures in the global server status instead.
*/
+ statistic_increment(aborted_connects,&LOCK_status);
statistic_increment(connection_errors_internal, &LOCK_status);
return 1; /* The error is set by alloc(). */
}
@@ -1054,7 +1058,8 @@ bool setup_connection_thread_globals(THD *thd)
{
close_connection(thd, ER_OUT_OF_RESOURCES);
statistic_increment(aborted_connects,&LOCK_status);
- MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0));
+ statistic_increment(connection_errors_internal, &LOCK_status);
+ thd->scheduler->end_thread(thd, 0);
return 1; // Error
}
return 0;
@@ -1082,7 +1087,7 @@ bool login_connection(THD *thd)
int error= 0;
DBUG_ENTER("login_connection");
DBUG_PRINT("info", ("login_connection called by thread %lu",
- thd->thread_id));
+ (ulong) thd->thread_id));
/* Use "connect_timeout" value during connection phase */
my_net_set_read_timeout(net, connect_timeout);
@@ -1254,11 +1259,11 @@ void prepare_new_connection_state(THD* thd)
pthread_handler_t handle_one_connection(void *arg)
{
- THD *thd= (THD*) arg;
+ CONNECT *connect= (CONNECT*) arg;
- mysql_thread_set_psi_id(thd->thread_id);
+ mysql_thread_set_psi_id(connect->thread_id);
- do_handle_one_connection(thd);
+ do_handle_one_connection(connect);
return 0;
}
@@ -1290,19 +1295,17 @@ bool thd_is_connection_alive(THD *thd)
return FALSE;
}
-void do_handle_one_connection(THD *thd_arg)
-{
- THD *thd= thd_arg;
-
- thd->thr_create_utime= microsecond_interval_timer();
- /* We need to set this because of time_out_user_resource_limits */
- thd->start_utime= thd->thr_create_utime;
- if (MYSQL_CALLBACK_ELSE(thd->scheduler, init_new_connection_thread, (), 0))
+void do_handle_one_connection(CONNECT *connect)
+{
+ ulonglong thr_create_utime= microsecond_interval_timer();
+ THD *thd;
+ if (connect->scheduler->init_new_connection_thread() ||
+ !(thd= connect->create_thd()))
{
- close_connection(thd, ER_OUT_OF_RESOURCES);
- statistic_increment(aborted_connects,&LOCK_status);
- MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0));
+ scheduler_functions *scheduler= connect->scheduler;
+ connect->close_with_error(0, 0, ER_OUT_OF_RESOURCES);
+ scheduler->end_thread(0, 0);
return;
}
@@ -1311,14 +1314,22 @@ void do_handle_one_connection(THD *thd_arg)
increment slow_launch_threads counter if it took more than
slow_launch_time seconds to create the thread.
*/
- if (thd->prior_thr_create_utime)
+
+ if (connect->prior_thr_create_utime)
{
- ulong launch_time= (ulong) (thd->thr_create_utime -
- thd->prior_thr_create_utime);
+ ulong launch_time= (ulong) (thr_create_utime -
+ connect->prior_thr_create_utime);
if (launch_time >= slow_launch_time*1000000L)
statistic_increment(slow_launch_threads, &LOCK_status);
- thd->prior_thr_create_utime= 0;
}
+ delete connect;
+
+ /* Make THD visible in show processlist */
+ add_to_active_threads(thd);
+
+ thd->thr_create_utime= thr_create_utime;
+ /* We need to set this because of time_out_user_resource_limits */
+ thd->start_utime= thr_create_utime;
/*
handle_one_connection() is normally the only way a thread would
@@ -1365,7 +1376,7 @@ end_thread:
if (thd->userstat_running)
update_global_user_stats(thd, create_user, time(NULL));
- if (MYSQL_CALLBACK_ELSE(thd->scheduler, end_thread, (thd, 1), 0))
+ if (thd->scheduler->end_thread(thd, 1))
return; // Probably no-threads
/*
@@ -1377,3 +1388,110 @@ end_thread:
}
}
#endif /* EMBEDDED_LIBRARY */
+
+
+/* Handling of CONNECT objects */
+
+/*
+ Close connection without error and delete the connect object
+ This and close_with_error are only called if we didn't manage to
+ create a new thd object.
+*/
+
+void CONNECT::close_and_delete()
+{
+ DBUG_ENTER("close_and_delete");
+
+ if (vio)
+ vio_close(vio);
+ if (thread_count_incremented)
+ {
+ /*
+ Normally this is handled by THD::unlink. As we haven't yet created
+ a THD and put it in the thread list, we have to manage counting here.
+ */
+ dec_thread_count();
+ dec_connection_count(scheduler);
+ }
+ statistic_increment(connection_errors_internal, &LOCK_status);
+ statistic_increment(aborted_connects,&LOCK_status);
+
+ delete this;
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Close a connection with a possible error to the end user
+ Alse deletes the connection object, like close_and_delete()
+*/
+
+void CONNECT::close_with_error(uint sql_errno,
+ const char *message, uint close_error)
+{
+ THD *thd= create_thd();
+ if (thd)
+ {
+ if (sql_errno)
+ net_send_error(thd, sql_errno, message, NULL);
+ close_connection(thd, close_error);
+ delete thd;
+ set_current_thd(0);
+ if (thread_count_incremented)
+ {
+ dec_thread_count();
+ dec_connection_count(scheduler);
+ }
+ delete this;
+ statistic_increment(connection_errors_internal, &LOCK_status);
+ statistic_increment(aborted_connects,&LOCK_status);
+ }
+ else
+ {
+ /*
+ Out of memory; We can't generate an error, just close the connection
+ close_and_delete() will increment statistics.
+ */
+ close_and_delete();
+ }
+}
+
+
+CONNECT::~CONNECT()
+{
+ if (vio)
+ vio_delete(vio);
+}
+
+/* Create a THD based on a CONNECT object */
+
+THD *CONNECT::create_thd()
+{
+ my_bool res;
+ THD *thd;
+ DBUG_ENTER("create_thd");
+
+ DBUG_EXECUTE_IF("simulate_failed_connection_2", DBUG_RETURN(0); );
+
+ if (!(thd= new THD))
+ DBUG_RETURN(0);
+
+ set_current_thd(thd);
+ res= my_net_init(&thd->net, vio, thd, MYF(MY_THREAD_SPECIFIC));
+ vio= 0; // Vio now handled by thd
+
+ if (res)
+ {
+ delete thd;
+ set_current_thd(0);
+ DBUG_RETURN(0);
+ }
+
+ init_net_server_extension(thd);
+
+ thd->security_ctx->host= host;
+ thd->extra_port= extra_port;
+ thd->scheduler= scheduler;
+ thd->thread_id= thd->variables.pseudo_thread_id= thread_id;
+ thd->real_id= real_id;
+ DBUG_RETURN(thd);
+}