List:Commits« Previous MessageNext Message »
From:Alexey Botchkov Date:September 8 2010 7:09am
Subject:bzr commit into mysql-trunk-bugfixing branch (holyfoot:3259)
View as plain text  
#At file:///home/hf/work/tb-mrg/ based on revid:mats.kindahl@stripped

 3259 Alexey Botchkov	2010-09-08 [merge]
      merging.

    modified:
      client/mysqltest.cc
      libmysqld/lib_sql.cc
      sql/derror.cc
      sql/mysqld.cc
      sql/set_var.cc
      sql/set_var.h
      sql/sys_vars.h
=== modified file 'client/mysqltest.cc'
--- a/client/mysqltest.cc	2010-08-27 12:17:32 +0000
+++ b/client/mysqltest.cc	2010-09-08 07:09:13 +0000
@@ -248,10 +248,14 @@ struct st_connection
   my_bool pending;
 
 #ifdef EMBEDDED_LIBRARY
+  pthread_t tid;
   const char *cur_query;
   int cur_query_len;
-  pthread_mutex_t mutex;
-  pthread_cond_t cond;
+  int command, result;
+  pthread_mutex_t query_mutex;
+  pthread_cond_t query_cond;
+  pthread_mutex_t result_mutex;
+  pthread_cond_t result_cond;
   int query_done;
 #endif /*EMBEDDED_LIBRARY*/
 };
@@ -703,67 +707,148 @@ void handle_no_error(struct st_command*)
 
 #ifdef EMBEDDED_LIBRARY
 
+#define EMB_SEND_QUERY 1
+#define EMB_READ_QUERY_RESULT 2
+#define EMB_END_CONNECTION 3
+
 /* attributes of the query thread */
 pthread_attr_t cn_thd_attrib;
 
+
 /*
-  send_one_query executes query in separate thread, which is
-  necessary in embedded library to run 'send' in proper way.
-  This implementation doesn't handle errors returned
-  by mysql_send_query. It's technically possible, though
-  I don't see where it is needed.
+  This procedure represents the connection and actually
+  runs queries when in the EMBEDDED-SERVER mode.
+  The run_query_normal() just sends request for running
+  mysql_send_query and mysql_read_query_result() here.
 */
-pthread_handler_t send_one_query(void *arg)
+
+pthread_handler_t connection_thread(void *arg)
 {
   struct st_connection *cn= (struct st_connection*)arg;
 
   mysql_thread_init();
-  (void) mysql_send_query(&cn->mysql, cn->cur_query, cn->cur_query_len);
+  while (cn->command != EMB_END_CONNECTION)
+  {
+    if (!cn->command)
+    {
+      pthread_mutex_lock(&cn->query_mutex);
+      while (!cn->command)
+        pthread_cond_wait(&cn->query_cond, &cn->query_mutex);
+      pthread_mutex_unlock(&cn->query_mutex);
+    }
+    switch (cn->command)
+    {
+      case EMB_END_CONNECTION:
+        goto end_thread;
+      case EMB_SEND_QUERY:
+        cn->result= mysql_send_query(&cn->mysql, cn->cur_query, cn->cur_query_len);
+        break;
+      case EMB_READ_QUERY_RESULT:
+        cn->result= mysql_read_query_result(&cn->mysql);
+        break;
+      default:
+        DBUG_ASSERT(0);
+    }
+    cn->command= 0;
+    pthread_mutex_lock(&cn->result_mutex);
+    cn->query_done= 1;
+    pthread_cond_signal(&cn->result_cond);
+    pthread_mutex_unlock(&cn->result_mutex);
+  }
 
-  mysql_thread_end();
-  pthread_mutex_lock(&cn->mutex);
+end_thread:
   cn->query_done= 1;
-  pthread_cond_signal(&cn->cond);
-  pthread_mutex_unlock(&cn->mutex);
+  mysql_thread_end();
   pthread_exit(0);
   return 0;
 }
 
-static int do_send_query(struct st_connection *cn, const char *q, int q_len,
-                         int flags)
+
+static void wait_query_thread_done(struct st_connection *con)
+{
+  DBUG_ASSERT(con->tid);
+  if (!con->query_done)
+  {
+    pthread_mutex_lock(&con->result_mutex);
+    while (!con->query_done)
+      pthread_cond_wait(&con->result_cond, &con->result_mutex);
+    pthread_mutex_unlock(&con->result_mutex);
+  }
+}
+
+
+static void signal_connection_thd(struct st_connection *cn, int command)
 {
-  pthread_t tid;
+  DBUG_ASSERT(cn->tid);
+  cn->query_done= 0;
+  cn->command= command;
+  pthread_mutex_lock(&cn->query_mutex);
+  pthread_cond_signal(&cn->query_cond);
+  pthread_mutex_unlock(&cn->query_mutex);
+}
 
-  if (flags & QUERY_REAP_FLAG)
-    return mysql_send_query(&cn->mysql, q, q_len);
 
-  if (pthread_mutex_init(&cn->mutex, NULL) ||
-      pthread_cond_init(&cn->cond, NULL))
-    die("Error in the thread library");
+/*
+  Sometimes we try to execute queries when the connection is closed.
+  It's done to make sure it was closed completely.
+  So that if our connection is closed (cn->tid == 0), we just return
+  the mysql_send_query() result which is an error in this case.
+*/
 
+static int do_send_query(struct st_connection *cn, const char *q, int q_len)
+{
+  if (!cn->tid)
+    return mysql_send_query(&cn->mysql, q, q_len);
   cn->cur_query= q;
   cn->cur_query_len= q_len;
-  cn->query_done= 0;
-  if (pthread_create(&tid, &cn_thd_attrib, send_one_query, (void*)cn))
-    die("Cannot start new thread for query");
-
+  signal_connection_thd(cn, EMB_SEND_QUERY);
   return 0;
 }
 
-static void wait_query_thread_end(struct st_connection *con)
+
+static int do_read_query_result(struct st_connection *cn)
 {
-  if (!con->query_done)
-  {
-    pthread_mutex_lock(&con->mutex);
-    while (!con->query_done)
-      pthread_cond_wait(&con->cond, &con->mutex);
-    pthread_mutex_unlock(&con->mutex);
-  }
+  DBUG_ASSERT(cn->tid);
+  wait_query_thread_done(cn);
+  signal_connection_thd(cn, EMB_READ_QUERY_RESULT);
+  wait_query_thread_done(cn);
+
+  return cn->result;
+}
+
+
+static void emb_close_connection(struct st_connection *cn)
+{
+  if (!cn->tid)
+    return;
+  wait_query_thread_done(cn);
+  signal_connection_thd(cn, EMB_END_CONNECTION);
+  pthread_join(cn->tid, NULL);
+  cn->tid= 0;
+  pthread_mutex_destroy(&cn->query_mutex);
+  pthread_cond_destroy(&cn->query_cond);
+  pthread_mutex_destroy(&cn->result_mutex);
+  pthread_cond_destroy(&cn->result_cond);
 }
 
+
+static void init_connection_thd(struct st_connection *cn)
+{
+  cn->query_done= 1;
+  cn->command= 0;
+  if (pthread_mutex_init(&cn->query_mutex, NULL) ||
+      pthread_cond_init(&cn->query_cond, NULL) ||
+      pthread_mutex_init(&cn->result_mutex, NULL) ||
+      pthread_cond_init(&cn->result_cond, NULL) ||
+      pthread_create(&cn->tid, &cn_thd_attrib, connection_thread, (void*)cn))
+    die("Error in the thread library");
+}
+
+
 #else /*EMBEDDED_LIBRARY*/
 
-#define do_send_query(cn,q,q_len,flags) mysql_send_query(&cn->mysql, q, q_len)
+#define do_send_query(cn,q,q_len) mysql_send_query(&cn->mysql, q, q_len)
+#define do_read_query_result(cn) mysql_read_query_result(&cn->mysql)
 
 #endif /*EMBEDDED_LIBRARY*/
 
@@ -1106,6 +1191,9 @@ void close_connections()
   DBUG_ENTER("close_connections");
   for (--next_con; next_con >= connections; --next_con)
   {
+#ifdef EMBEDDED_LIBRARY
+    emb_close_connection(next_con);
+#endif
     if (next_con->stmt)
       mysql_stmt_close(next_con->stmt);
     next_con->stmt= 0;
@@ -4868,7 +4956,7 @@ void do_close_connection(struct st_comma
     we need to check if the query's thread was finished and probably wait
     (embedded-server specific)
   */
-  wait_query_thread_end(con);
+  emb_close_connection(con);
 #endif /*EMBEDDED_LIBRARY*/
   if (con->stmt)
     mysql_stmt_close(con->stmt);
@@ -5218,8 +5306,9 @@ void do_connect(struct st_command *comma
   }
 
 #ifdef EMBEDDED_LIBRARY
-  con_slot->query_done= 1;
-#endif
+  init_connection_thd(con_slot);
+#endif /*EMBEDDED_LIBRARY*/
+
   if (!mysql_init(&con_slot->mysql))
     die("Failed on mysql_init()");
 
@@ -6770,21 +6859,13 @@ void run_query_normal(struct st_connecti
     /*
       Send the query
     */
-    if (do_send_query(cn, query, query_len, flags))
+    if (do_send_query(cn, query, query_len))
     {
       handle_error(command, mysql_errno(mysql), mysql_error(mysql),
 		   mysql_sqlstate(mysql), ds);
       goto end;
     }
   }
-#ifdef EMBEDDED_LIBRARY
-  /*
-    Here we handle 'reap' command, so we need to check if the
-    query's thread was finished and probably wait
-  */
-  else if (flags & QUERY_REAP_FLAG)
-    wait_query_thread_end(cn);
-#endif /*EMBEDDED_LIBRARY*/
   if (!(flags & QUERY_REAP_FLAG))
   {
     cn->pending= TRUE;
@@ -6797,7 +6878,7 @@ void run_query_normal(struct st_connecti
       When  on first result set, call mysql_read_query_result to retrieve
       answer to the query sent earlier
     */
-    if ((counter==0) && mysql_read_query_result(mysql))
+    if ((counter==0) && do_read_query_result(cn))
     {
       handle_error(command, mysql_errno(mysql), mysql_error(mysql),
 		   mysql_sqlstate(mysql), ds);
@@ -7975,6 +8056,9 @@ int main(int argc, char **argv)
     ps_protocol_enabled= 1;
 
   st_connection *con= connections;
+#ifdef EMBEDDED_LIBRARY
+  init_connection_thd(con);
+#endif /*EMBEDDED_LIBRARY*/
   if (!( mysql_init(&con->mysql)))
     die("Failed in mysql_init()");
   if (opt_connect_timeout)

=== modified file 'libmysqld/lib_sql.cc'
--- a/libmysqld/lib_sql.cc	2010-07-19 16:09:51 +0000
+++ b/libmysqld/lib_sql.cc	2010-09-08 07:09:13 +0000
@@ -481,6 +481,10 @@ int init_embedded_server(int argc, char 
   char *fake_argv[] = { (char *)"", 0 };
   const char *fake_groups[] = { "server", "embedded", 0 };
   my_bool acl_error;
+
+  if (my_thread_init())
+    return 1;
+
   if (argc)
   {
     argcp= &argc;

=== modified file 'sql/derror.cc'
--- a/sql/derror.cc	2010-07-08 21:42:23 +0000
+++ b/sql/derror.cc	2010-09-08 07:09:13 +0000
@@ -35,6 +35,8 @@ static void init_myfunc_errs(void);
 C_MODE_START
 static const char **get_server_errmsgs()
 {
+  if (!current_thd)
+    return DEFAULT_ERRMSGS;
   return CURRENT_THD_ERRMSGS;
 }
 C_MODE_END

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2010-09-01 13:05:01 +0000
+++ b/sql/mysqld.cc	2010-09-08 07:09:13 +0000
@@ -1486,6 +1486,7 @@ void clean_up(bool print_message)
   cleanup_errmsgs();
   MYSQL_CALLBACK(thread_scheduler, end, ());
   finish_client_errs();
+  (void) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST); // finish server errs
   DBUG_PRINT("quit", ("Error messages freed"));
   /* Tell main we are ready */
   logger.cleanup_end();

=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc	2010-08-26 14:54:39 +0000
+++ b/sql/set_var.cc	2010-09-08 07:09:13 +0000
@@ -108,7 +108,7 @@ void sys_var_end()
   my_hash_free(&system_variable_hash);
 
   for (sys_var *var=all_sys_vars.first; var; var= var->next)
-    var->~sys_var();
+    var->cleanup();
 
   DBUG_VOID_RETURN;
 }

=== modified file 'sql/set_var.h'
--- a/sql/set_var.h	2010-07-23 20:59:42 +0000
+++ b/sql/set_var.h	2010-09-08 07:09:13 +0000
@@ -92,10 +92,9 @@ public:
           on_check_function on_check_func, on_update_function on_update_func,
           uint deprecated_version, const char *substitute, int parse_flag);
   /**
-    The instance should only be destroyed on shutdown, as it doesn't unlink
-    itself from the chain.
+    All the cleanup procedures should be performed here
   */
-  virtual ~sys_var() {}
+  virtual void cleanup() {}
   /**
     downcast for sys_var_pluginvar. Returns this if it's an instance
     of sys_var_pluginvar, and 0 otherwise.

=== modified file 'sql/sys_vars.h'
--- a/sql/sys_vars.h	2010-08-12 14:08:21 +0000
+++ b/sql/sys_vars.h	2010-09-08 07:09:13 +0000
@@ -385,7 +385,7 @@ public:
     DBUG_ASSERT(scope() == GLOBAL);
     DBUG_ASSERT(size == sizeof(char *));
   }
-  ~Sys_var_charptr()
+  void cleanup()
   {
     if (flags & ALLOCATED)
       my_free(global_var(char*));


Attachment: [text/bzr-bundle] bzr/holyfoot@mysql.com-20100908070913-qlzfbfaabz3jcxqh.bundle
Thread
bzr commit into mysql-trunk-bugfixing branch (holyfoot:3259)Alexey Botchkov9 Sep