List:Internals« Previous MessageNext Message »
From:Sergei Golubchik Date:March 16 2005 8:40am
Subject:bk commit into 5.0 tree (serg:1.1814)
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of serg. When serg does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.1814 05/03/16 08:40:19 serg@stripped +6 -0
  global read lock code now uses a dedicated mutex
  (otherwise a deadlock when ALTER writes to
  binlog holding LOCK_open, it causes binlog rotation,
  binlog waits for prepared transactions to commit, and commit
  needs LOCK_open to check for global read lock)

  sql/sql_table.cc
    1.225 05/03/16 08:40:11 serg@stripped +10 -11
    global read lock code now uses a dedicated mutex

  sql/mysqld.cc
    1.446 05/03/16 08:40:10 serg@stripped +3 -1
    global read lock code now uses a dedicated mutex

  sql/mysql_priv.h
    1.276 05/03/16 08:40:10 serg@stripped +1 -1
    global read lock code now uses a dedicated mutex

  sql/lock.cc
    1.62 05/03/16 08:40:10 serg@stripped +15 -15
    global read lock code now uses a dedicated mutex

  mysql-test/t/flush.test
    1.15 05/03/16 08:40:10 serg@stripped +1 -1
    global read lock code now uses a dedicated mutex

  mysql-test/r/flush.result
    1.12 05/03/16 08:40:10 serg@stripped +1 -1
    global read lock code now uses a dedicated mutex

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	serg
# Host:	serg.mylan
# Root:	/usr/home/serg/Abk/mysql-5.0

--- 1.61/sql/lock.cc	Wed Feb 23 18:52:09 2005
+++ 1.62/sql/lock.cc	Wed Mar 16 08:40:10 2005
@@ -800,8 +800,8 @@
 
   if (!thd->global_read_lock)
   {
-    (void) pthread_mutex_lock(&LOCK_open);
-    const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
+    (void) pthread_mutex_lock(&LOCK_global_read_lock);
+    const char *old_message=thd->enter_cond(&COND_refresh,
&LOCK_global_read_lock,
 					    "Waiting to get readlock");
     DBUG_PRINT("info",
 	       ("waiting_for: %d  protect_against: %d",
@@ -809,7 +809,7 @@
 
     waiting_for_read_lock++;
     while (protect_against_global_read_lock && !thd->killed)
-      pthread_cond_wait(&COND_refresh, &LOCK_open);
+      pthread_cond_wait(&COND_refresh, &LOCK_global_read_lock);
     waiting_for_read_lock--;
     if (thd->killed)
     {
@@ -834,11 +834,11 @@
 void unlock_global_read_lock(THD *thd)
 {
   uint tmp;
-  pthread_mutex_lock(&LOCK_open);
+  pthread_mutex_lock(&LOCK_global_read_lock);
   tmp= --global_read_lock;
   if (thd->global_read_lock == MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT)
     --global_read_lock_blocks_commit;
-  pthread_mutex_unlock(&LOCK_open);
+  pthread_mutex_unlock(&LOCK_global_read_lock);
   /* Send the signal outside the mutex to avoid a context switch */
   if (!tmp)
     pthread_cond_broadcast(&COND_refresh);
@@ -857,7 +857,7 @@
   DBUG_ENTER("wait_if_global_read_lock");
 
   LINT_INIT(old_message);
-  (void) pthread_mutex_lock(&LOCK_open);
+  (void) pthread_mutex_lock(&LOCK_global_read_lock);
   if ((need_exit_cond= must_wait))
   {
     if (thd->global_read_lock)		// This thread had the read locks
@@ -865,7 +865,7 @@
       if (is_not_commit)
         my_message(ER_CANT_UPDATE_WITH_READLOCK,
                    ER(ER_CANT_UPDATE_WITH_READLOCK), MYF(0));
-      (void) pthread_mutex_unlock(&LOCK_open);
+      (void) pthread_mutex_unlock(&LOCK_global_read_lock);
       /*
         We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does.
         This allowance is needed to not break existing versions of innobackup
@@ -873,11 +873,11 @@
       */
       DBUG_RETURN(is_not_commit);
     }
-    old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
+    old_message=thd->enter_cond(&COND_refresh, &LOCK_global_read_lock,
 				"Waiting for release of readlock");
     while (must_wait && ! thd->killed &&
 	   (!abort_on_refresh || thd->version == refresh_version))
-      (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
+      (void) pthread_cond_wait(&COND_refresh,&LOCK_global_read_lock);
     if (thd->killed)
       result=1;
   }
@@ -890,7 +890,7 @@
   if (unlikely(need_exit_cond)) 
     thd->exit_cond(old_message);
   else
-    pthread_mutex_unlock(&LOCK_open);
+    pthread_mutex_unlock(&LOCK_global_read_lock);
   DBUG_RETURN(result);
 }
 
@@ -901,10 +901,10 @@
   DBUG_ENTER("start_waiting_global_read_lock");
   if (unlikely(thd->global_read_lock))
     DBUG_VOID_RETURN;
-  (void) pthread_mutex_lock(&LOCK_open);
+  (void) pthread_mutex_lock(&LOCK_global_read_lock);
   tmp= (!--protect_against_global_read_lock &&
         (waiting_for_read_lock || global_read_lock_blocks_commit));
-  (void) pthread_mutex_unlock(&LOCK_open);
+  (void) pthread_mutex_unlock(&LOCK_global_read_lock);
   if (tmp)
     pthread_cond_broadcast(&COND_refresh);
   DBUG_VOID_RETURN;
@@ -922,16 +922,16 @@
   */
   if (thd->global_read_lock != GOT_GLOBAL_READ_LOCK)
     DBUG_RETURN(1);
-  pthread_mutex_lock(&LOCK_open);
+  pthread_mutex_lock(&LOCK_global_read_lock);
   /* increment this BEFORE waiting on cond (otherwise race cond) */
   global_read_lock_blocks_commit++;
   /* For testing we set up some blocking, to see if we can be killed */
   DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
                   protect_against_global_read_lock++;);
-  old_message= thd->enter_cond(&COND_refresh, &LOCK_open,
+  old_message= thd->enter_cond(&COND_refresh, &LOCK_global_read_lock,
                                "Waiting for all running commits to finish");
   while (protect_against_global_read_lock && !thd->killed)
-    pthread_cond_wait(&COND_refresh, &LOCK_open);
+    pthread_cond_wait(&COND_refresh, &LOCK_global_read_lock);
   DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
                   protect_against_global_read_lock--;);
   if (error= thd->killed)

--- 1.275/sql/mysql_priv.h	Mon Mar 14 14:47:37 2005
+++ 1.276/sql/mysql_priv.h	Wed Mar 16 08:40:10 2005
@@ -1099,7 +1099,7 @@
        LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status,
        LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator,
        LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
-       LOCK_slave_list, LOCK_active_mi, LOCK_manager,
+       LOCK_slave_list, LOCK_active_mi, LOCK_manager, LOCK_global_read_lock,
        LOCK_global_system_variables, LOCK_user_conn;
 extern rw_lock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
 extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager;

--- 1.445/sql/mysqld.cc	Tue Mar 15 15:11:40 2005
+++ 1.446/sql/mysqld.cc	Wed Mar 16 08:40:10 2005
@@ -426,7 +426,7 @@
 pthread_key(MEM_ROOT**,THR_MALLOC);
 pthread_key(THD*, THR_THD);
 pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
-		LOCK_mapped_file, LOCK_status,
+		LOCK_mapped_file, LOCK_status, LOCK_global_read_lock,
 		LOCK_error_log, LOCK_uuid_generator,
 		LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
 		LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
@@ -1102,6 +1102,7 @@
   (void) rwlock_destroy(&LOCK_sys_init_connect);
   (void) rwlock_destroy(&LOCK_sys_init_slave);
   (void) pthread_mutex_destroy(&LOCK_global_system_variables);
+  (void) pthread_mutex_destroy(&LOCK_global_read_lock);
   (void) pthread_cond_destroy(&COND_thread_count);
   (void) pthread_cond_destroy(&COND_refresh);
   (void) pthread_cond_destroy(&COND_thread_cache);
@@ -2594,6 +2595,7 @@
   (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
   (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
   (void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
+  (void) pthread_mutex_init(&LOCK_global_read_lock, MY_MUTEX_INIT_FAST);
   (void) pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST);
   (void) my_rwlock_init(&LOCK_sys_init_connect, NULL);
   (void) my_rwlock_init(&LOCK_sys_init_slave, NULL);

--- 1.224/sql/sql_table.cc	Fri Mar 11 21:37:41 2005
+++ 1.225/sql/sql_table.cc	Wed Mar 16 08:40:11 2005
@@ -65,7 +65,7 @@
 bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
                     my_bool drop_temporary)
 {
-  bool error= FALSE;
+  bool error= FALSE, need_start_waiters= FALSE;
   DBUG_ENTER("mysql_rm_table");
 
   /* mark for close and remove all cached entries */
@@ -74,23 +74,19 @@
   thd->mysys_var->current_cond= &COND_refresh;
   VOID(pthread_mutex_lock(&LOCK_open));
 
-  if (!drop_temporary && global_read_lock)
+  if (!drop_temporary)
   {
-    if (thd->global_read_lock)
+    if ((error= wait_if_global_read_lock(thd, 0, 1)))
     {
       my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->table_name);
-      error= TRUE;
       goto err;
     }
-    while (global_read_lock && ! thd->killed)
-    {
-      (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
-    }
-
+    else
+      need_start_waiters= TRUE;
   }
   error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
 
- err:
+err:
   pthread_mutex_unlock(&LOCK_open);
 
   pthread_mutex_lock(&thd->mysys_var->mutex);
@@ -98,6 +94,9 @@
   thd->mysys_var->current_cond= 0;
   pthread_mutex_unlock(&thd->mysys_var->mutex);
 
+  if (need_start_waiters)
+    start_waiting_global_read_lock(thd);
+
   if (error)
     DBUG_RETURN(TRUE);
   send_ok(thd);
@@ -114,7 +113,7 @@
     tables		List of tables to delete
     if_exists		If 1, don't give error if one table doesn't exists
     dont_log_query	Don't write query to log files. This will also not
-			generate warnings if the handler files doesn't exists  
+                        generate warnings if the handler files doesn't exists
 
  NOTES
    Works like documented in mysql_rm_table(), but don't check

--- 1.11/mysql-test/r/flush.result	Thu Aug  7 20:17:21 2003
+++ 1.12/mysql-test/r/flush.result	Wed Mar 16 08:40:10 2005
@@ -8,7 +8,7 @@
 3
 flush tables with read lock;
 drop table t2;
-ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
+ERROR HY000: Can't execute the query because you have a conflicting read lock
  drop table t2;
 unlock tables;
 create database mysqltest;

--- 1.14/mysql-test/t/flush.test	Mon Aug 11 21:28:01 2003
+++ 1.15/mysql-test/t/flush.test	Wed Mar 16 08:40:10 2005
@@ -37,7 +37,7 @@
 select * from t1;
 connection con2;
 flush tables with read lock;
---error 1099;
+--error 1223
 drop table t2;
 connection con1;
 send drop table t2;
Thread
bk commit into 5.0 tree (serg:1.1814)Sergei Golubchik16 Mar