MySQL Lists are EOL. Please join:

List:Internals« Previous MessageNext Message »
From:mikael Date:August 23 2005 6:22pm
Subject:bk commit into 5.1 tree (mronstrom:1.1895)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of mikron. When mikron 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.1895 05/08/23 20:21:52 mronstrom@stripped +6 -0
  WL 2602, 2603, 2604: Partition Management
  Generalised partition management, first step

  sql/sql_table.cc
    1.266 05/08/23 20:21:42 mronstrom@stripped +203 -103
    Lots of new routines for generalised partition management
    Tried to accomplish short code for each variant of partition
    management using lots of support routines to place common code
    to avoid code duplication. The variants are similar but sufficiently
    different to not really benefit from a common code path.

  sql/mysql_priv.h
    1.326 05/08/23 20:21:41 mronstrom@stripped +2 -0
    New method to downgrade write locks on table

  sql/lock.cc
    1.76 05/08/23 20:21:41 mronstrom@stripped +16 -0
    New method to downgrade write locks on table

  sql/handler.h
    1.155 05/08/23 20:21:41 mronstrom@stripped +13 -1
    New routine to copy partitions, no need of table object in call to
    add partitions (already part of the handler)

  mysys/thr_lock.c
    1.48 05/08/23 20:21:41 mronstrom@stripped +15 -0
    New routine to downgrade write locks

  include/thr_lock.h
    1.18 05/08/23 20:21:41 mronstrom@stripped +2 -0
    New routine to downgrade write locks

# 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:	mronstrom
# Host:	c-6109e253.1238-1-64736c10.cust.bredbandsbolaget.se
# Root:	/Users/mikron/wl2602

--- 1.17/include/thr_lock.h	2005-07-28 15:12:32 +02:00
+++ 1.18/include/thr_lock.h	2005-08-23 20:21:41 +02:00
@@ -147,6 +147,8 @@
 my_bool thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread);
 void thr_print_locks(void);		/* For debugging */
 my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data);
+void    thr_downgrade_write_lock(THR_LOCK_DATA *data,
+                                 enum thr_lock_type new_lock_type);
 my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data);
 #ifdef	__cplusplus
 }

--- 1.47/mysys/thr_lock.c	2005-07-31 11:49:46 +02:00
+++ 1.48/mysys/thr_lock.c	2005-08-23 20:21:41 +02:00
@@ -1088,6 +1088,21 @@
 }
 
 
+/* Downgrade a WRITE_* to a lower WRITE level */
+
+void thr_downgrade_write_lock(THR_LOCK_DATA *data,
+                              enum thr_lock_type new_lock_type)
+{
+  THR_LOCK *lock=data->lock;
+  DBUG_ENTER("thr_downgrade_write_only_lock");
+
+  pthread_mutex_lock(&lock->mutex);
+  DBUG_ASSERT(data->type > new_lock_type);
+  data->type= new_lock_type;
+  check_locks(lock,"after downgrading lock",0);
+  pthread_mutex_unlock(&lock->mutex);
+  DBUG_VOID_RETURN;
+}
 
 /* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */
 

--- 1.154/sql/handler.h	2005-08-22 17:56:50 +02:00
+++ 1.155/sql/handler.h	2005-08-23 20:21:41 +02:00
@@ -1252,7 +1252,7 @@
       is ongoing in the server. This is used by ADD PARTITION all types
       as well as by REORGANISE PARTITION.
   */
-  virtual int add_partitions(TABLE *table, HA_CREATE_INFO *create_info,
+  virtual int add_partitions(HA_CREATE_INFO *create_info,
                              const char *path)
   { return HA_ERR_WRONG_COMMAND; }
 
@@ -1269,6 +1269,18 @@
   */
   virtual int drop_partitions(const char *path)
   { return HA_ERR_WRONG_COMMAND; }
+
+  /*
+    SYNOPSIS
+      copy_partitions()
+    RETURN VALUES
+      TRUE                        Failure
+      FALSE                       Success
+    DESCRIPTION
+      Copy from reorged partitions to the new partitions
+  */
+  virtual int copy_partitions() { return HA_ERR_WRONG_COMMAND; }
+
   /* lock_count() can be more than one if the table is a MERGE */
   virtual uint lock_count(void) const { return 1; }
   virtual THR_LOCK_DATA **store_lock(THD *thd,

--- 1.75/sql/lock.cc	2005-08-05 23:50:36 +02:00
+++ 1.76/sql/lock.cc	2005-08-23 20:21:41 +02:00
@@ -333,6 +333,22 @@
   }
 }
 
+/* Downgrade all locks on a table to new WRITE level from WRITE_ONLY */
+
+void mysql_lock_downgrade_write(THD *thd, TABLE *table,
+                                thr_lock_type new_lock_type)
+{
+  MYSQL_LOCK *locked;
+  TABLE *write_lock_used;
+  if ((locked = get_lock_data(thd,&table,1,1,&write_lock_used)))
+  {
+    for (uint i=0; i < locked->lock_count; i++)
+      thr_downgrade_write_lock(locked->locks[i], new_lock_type);
+    my_free((gptr) locked,MYF(0));
+  }
+}
+
+
 /* abort all other threads waiting to get lock in table */
 
 void mysql_lock_abort(THD *thd, TABLE *table)

--- 1.325/sql/mysql_priv.h	2005-08-19 16:25:28 +02:00
+++ 1.326/sql/mysql_priv.h	2005-08-23 20:21:41 +02:00
@@ -1251,6 +1251,8 @@
 void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count);
 void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table);
 void mysql_lock_abort(THD *thd, TABLE *table);
+void mysql_lock_downgrade_write(THD *thd, TABLE *table,
+                                thr_lock_type new_lock_type);
 bool mysql_lock_abort_for_thread(THD *thd, TABLE *table);
 MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b);
 bool lock_global_read_lock(THD *thd);

--- 1.265/sql/sql_table.cc	2005-08-22 18:03:09 +02:00
+++ 1.266/sql/sql_table.cc	2005-08-23 20:21:42 +02:00
@@ -43,7 +43,39 @@
 				    ha_rows *copied,ha_rows *deleted);
 static bool prepare_blob_field(THD *thd, create_field *sql_field);
 static bool check_engine(THD *thd, const char *table_name,
-                         enum db_type *new_engine);                          
+                         enum db_type *new_engine);                         static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
+                               List<create_field> *fields,
+                               List<Key> *keys, bool tmp_table,
+                               uint *db_options,
+                               handler *file, KEY **key_info_buffer,
+                               uint *key_count, int select_field_count);
+ 
+
+/*
+ Build the path to a file for a table (or the base path that can
+ then have various extensions stuck on to it).
+
+  SYNOPSIS
+   build_table_path()
+   buff                 Buffer to build the path into
+   bufflen              sizeof(buff)
+   db                   Name of database
+   table                Name of table
+   ext                  Filename extension
+
+  RETURN
+    0                   Error
+    #                   Size of path
+ */
+
+static uint build_table_path(char *buff, size_t bufflen, const char *db,
+                             const char *table, const char *ext)
+{
+  strxnmov(buff, bufflen-1, mysql_data_home, "/", db, "/", table, ext,
+           NullS);
+  return unpack_filename(buff,buff);
+}
+
 
 class write_frm_type
 {
@@ -56,11 +88,19 @@
   TABLE *table;
   KEY *key_info_buffer;
   uint key_count;
-  uint syntax_len;
   char *db;
   char *table_name;
-}
+};
 
+static bool mysql_add_partitions(TABLE *table, HA_CREATE_INFO *create_info,
+                                 const char *db, const char *table_name)
+{
+  char path[FN_REFLEN+1];
+  DBUG_ENTER("mysql_add_partitions");
+
+  build_table_path(path, sizeof(path), db, table_name, "");
+  DBUG_RETURN(table->file->add_partitions(create_info, path));
+}
 
 static bool mysql_write_frm(write_frm_type *wft,
                             bool initial_write,
@@ -71,15 +111,17 @@
     partitions in add/drop state have temporarily changed their state
   */
   partition_info *part_info= wft->table->s->part_info;
-  char path[FN_REFLEN+1];
+  char path[FN_REFLEN+1], *part_syntax_buf;
+  uint syntax_len;
   DBUG_ENTER("mysql_write_frm");
 
-  if (initial_write)
+  if (initial_write && 
+      (mysql_prepare_table(wft->thd, wft->create_info, wft->create_list,
+                           wft->key_list,/*tmp_table*/ 0, &wft->db_options,
+                           wft->table->file, &wft->key_info_buffer,
+                           &wft->key_count, /*select_field_count*/ 0)))
   {
-    mysql_prepare_table(wft->thd, wft->create_info, &wft->create_list,
-                        &wft->key_list, /*tmp_table*/ 0, &wft->db_options,
-                        wft->table->file, &wft->key_info_buffer,
-                        &wft->key_count, /*select_field_count*/ 0);
+    DBUG_RETURN(TRUE);
   }
   if (!(part_syntax_buf= generate_partition_syntax(part_info,
                                                    &syntax_len,
@@ -90,10 +132,11 @@
   part_info->part_info_string= part_syntax_buf;
   part_info->part_info_len= syntax_len;
   build_table_path(path, sizeof(path), wft->db, wft->table_name, reg_ext);
-  if (mysql_create_frm(wft->thd, path, wft->db, wft->table_name,
-                       wft->create_info, wft->create_list, wft->key_count,
-                       wft->key_info_buffer, wft->table->file) ||
-      (create_handler_files && table->file->create_handler_files(path)))
+  if ((mysql_create_frm(wft->thd, path, wft->db, wft->table_name,
+                        wft->create_info, *wft->create_list, wft->key_count,
+                        wft->key_info_buffer, wft->table->file)) ||
+      (create_handler_files &&
+       wft->table->file->create_handler_files(path)))
   {
     DBUG_RETURN(TRUE);
   }
@@ -145,7 +188,7 @@
 
 static bool abort_and_upgrade_lock(THD *thd, TABLE *table, const char *db,
                                    const char *table_name,
-                                   uint *old_lock_level)
+                                   thr_lock_type *old_lock_level)
 {
   uint flags= RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG;
   int error= FALSE;
@@ -165,31 +208,102 @@
 }
 
 /*
- Build the path to a file for a table (or the base path that can
- then have various extensions stuck on to it).
-
   SYNOPSIS
-   build_table_path()
-   buff                 Buffer to build the path into
-   bufflen              sizeof(buff)
-   db                   Name of database
-   table                Name of table
-   ext                  Filename extension
+    mysql_drop_partitions()
+    thd                         Thread object
+    table                       Table object
+    db                          Database name
+    table_name                  Table name
+  RETURN VALUES
+    TRUE                          Failure
+    FALSE                         Success
+  DESCRIPTION
+    Drop the partitions marked with PART_TO_BE_DROPPED state and remove
+    those partitions from the list.
+*/
 
-  RETURN
-    0                   Error
-    #                   Size of path
- */
+static bool mysql_drop_partitions(TABLE *table, const char *db,
+                                  const char *table_name)
+{
+  char path[FN_REFLEN+1];
+  partition_info *part_info= table->s->part_info;
+  List_iterator<partition_element> part_it(part_info->partitions);
+  uint i= 0, remove_count= 0;
+  DBUG_ENTER("mysql_drop_partitions");
 
-static uint build_table_path(char *buff, size_t bufflen, const char *db,
-                             const char *table, const char *ext)
+  build_table_path(path, sizeof(path), db, table_name, "");
+  if (table->file->drop_partitions(path))
+  {
+    DBUG_RETURN(TRUE);
+  }
+  do
+  {
+    partition_element *part_elem= part_it++;
+    if (part_elem->part_state == PART_IS_DROPPED)
+    {
+      part_it.remove();
+      remove_count++;
+    }
+  } while (++i < part_info->no_parts);
+  part_info->no_parts-= remove_count;
+  DBUG_RETURN(FALSE);
+}
+
+
+/*
+  SYNOPSIS
+    close_open_tables_and_downgrade()
+    thd                              Thread object
+    table                            Table object
+    db                               Database name
+    table_name                       Table name
+    old_lock_type                    Lock type to downgrade to
+  RESULT VALUES
+    NONE
+  DESCRIPTION
+    We need to ensure that any thread that has managed to open the table
+    but not yet encountered our lock on the table is also thrown out to
+    ensure that no threads see our frm changes premature to the final
+    version. The intermediate versions are only meant for use after a
+    crash and later REPAIR TABLE.
+    We also downgrade locks after the upgrade to WRITE_ONLY
+*/
+
+void close_open_tables_and_downgrade(THD *thd, TABLE *table, const char *db,
+                                     const char *table_name,
+                                     enum thr_lock_type old_lock_type)
 {
-  strxnmov(buff, bufflen-1, mysql_data_home, "/", db, "/", table, ext,
-           NullS);
-  return unpack_filename(buff,buff);
+  VOID(pthread_mutex_lock(&LOCK_open));
+  remove_table_from_cache(thd, db, table_name,
+                          RTFC_WAIT_OTHER_THREAD_FLAG);
+  VOID(pthread_mutex_unlock(&LOCK_open));
+  mysql_lock_downgrade_write(thd, table, old_lock_type);
 }
 
 
+/*
+  SYNOPSIS
+    mysql_wait_completed_table()
+    thd                           Thread object
+    table                         Table object
+    db                            Database name
+    table_name                    Table name
+  RETURN VALUES
+    NONE
+  DESCRIPTION
+    We have changed the frm file and now we want to wait for all users of
+    the old frm to complete before proceeding to ensure that no one
+    remains that uses the old frm definition.
+*/
+
+bool mysql_wait_completed_table(THD *thd, TABLE *table, const char *db,
+                                const char *table_name)
+{
+  /* TODO RONM: Write this routine */
+  DBUG_ENTER("mysql_wait_completed_table");
+  DBUG_RETURN(FALSE);
+}
+
 
 /*
  delete (drop) tables.
@@ -3410,8 +3524,8 @@
   enum db_type old_db_type,new_db_type;
   uint need_copy_table= 0;
 #ifdef HAVE_PARTITION_DB
-  bool online_add_empty_partition= FALSE;
-  bool online_drop_partition= FALSE;
+  bool online_drop_partition= FALSE, online_add_empty_partition= FALSE;
+  bool online_add_hash_partition= FALSE, online_reorg_partition= FALSE;
   bool partition_changed= FALSE;
   enum db_type default_engine_type;
 #endif
@@ -4255,20 +4369,21 @@
 
 #ifdef HAVE_PARTITION_DB
   if (partition_changed &&
-      (online_drop_partition || online_add_partition))
+      (online_drop_partition || online_add_empty_partition ||
+       online_add_hash_partition || online_reorg_partition))
   {
     /* Set-up struct used to write frm files */
     partition_info *part_info= table->s->part_info;
+    thr_lock_type old_lock_type;
     write_frm_type wft;
     wft.thd= thd;
     wft.create_info= create_info;
-    wft.create_list= create_list;
-    wft.key_list= key_list;
+    wft.create_list= &create_list;
+    wft.key_list= &key_list;
     wft.db_options= 0;
     wft.table= table;
-    wft.key_info_buffer= key_info_buffer;
-    wft.key_count= key_count;
-    wft.syntax_len= 0;
+    wft.key_info_buffer= wft.key_info_buffer;
+    wft.key_count= wft.key_count;
     wft.db= db;
     wft.table_name= table_name;
     thd->lex->part_info= part_info;
@@ -4293,72 +4408,24 @@
         6) Write binlog and return from statement (including releasing all
            remaining locks).
       */
-      uint old_lock_type;
 
-      if (abort_and_upgrade_lock(thd, table, db,
-                                 table_name, &old_lock_type))
-      {
-        DBUG_RETURN(TRUE);
-      }
-      /*
-        Prepare table to prepare for writing a new frm file where the
-        partitions in add/drop state have temporarily changed their state
-      */
-      if (mysql_write_frm(&wft, TRUE, FALSE))
+      if ((abort_and_upgrade_lock(thd, table, db,
+                                  table_name, &old_lock_type)) ||
+          (mysql_write_frm(&wft, TRUE, FALSE)) ||
+          (mysql_drop_partitions(table, db, table_name)) ||
+          (mysql_write_frm(&wft, FALSE, TRUE)))
       {
         DBUG_RETURN(TRUE);
       }
-
-      /*
-        Frm file have been updated to reflect the change about to happen.
-        Now perform the change
-      */
-      {
-        char path[FN_REFLEN+1];
-        List_iterator<partition_element> part_it(part_info->partitions);
-        uint i= 0, remove_count= 0;
-
-        build_table_path(path, sizeof(path), db, table_name, "");
-        if (table->file->drop_partitions(path))
-        {
-          DBUG_RETURN(TRUE);
-        }
-        do
-        {
-          partition_element *part_elem= part_it++;
-          if (part_elem->part_state == PART_IS_DROPPED)
-          {
-            part_it.remove();
-            remove_count++;
-          }
-        } while (++i < part_info->no_parts);
-        part_info->no_parts-= remove_count;
-      }
-      /*
-        Now we write the final version of the frm file to reflect the
-        new partitioning after the change.
-      */
-      if (mysql_write_frm(&wft, FALSE, TRUE))
-      {
-        DBUG_RETURN(TRUE);
-      }
-      VOID(pthread_mutex_lock(&LOCK_open));
-      /*
-        We need to ensure that any thread that has managed to open the table
-        but not yet encountered our lock on the table is also thrown out to
-        ensure that no threads see our frm changes premature to the final
-        version. The intermediate versions are only meant for use after a
-        crash and later REPAIR TABLE.
-      */
-      remove_table_from_cache(thd, db, table_name,
-                              RTFC_WAIT_OTHER_THREAD_FLAG);
-      VOID(pthread_mutex_unlock(&LOCK_open));
+      close_open_tables_and_downgrade(thd, table,
+                                      db, table_name, old_lock_type);
     }
-    else if (online_add_partition)
+    else if (online_add_empty_partition)
     {
       /*
         ADD RANGE/LIST PARTITIONS
-        1) Downgrade all locks to TL_WRITE_ALLOW_WRITE
+        1) Downgrade all locks to TL_WRITE_ALLOW_WRITE unless the user have
+           used lock table before starting ALTER TABLE.
         2) Write the new frm file where state of added partitions is
            changed to PART_TO_BE_ADDED
         3) Add the new partitions
@@ -4370,8 +4437,20 @@
         6) Write binlog and return from statement (including releasing all
            remaining locks).
       */
+      if (table->reginfo.lock_type == TL_WRITE_ALLOW_READ)
+        mysql_lock_downgrade_write(thd, table, TL_WRITE_ALLOW_WRITE);
+      if ((mysql_write_frm(&wft, TRUE, FALSE)) ||
+          (mysql_add_partitions(table, create_info, db, table_name)) ||
+          (abort_and_upgrade_lock(thd, table, db,
+                                  table_name, &old_lock_type)) ||
+          (mysql_write_frm(&wft, FALSE, TRUE)))
+      {
+        DBUG_RETURN(TRUE);
+      }
+      close_open_tables_and_downgrade(thd, table,
+                                      db, table_name, old_lock_type);
     }
-    else if (TRUE)
+    else if (online_add_hash_partition || online_reorg_partition)
     {
       /*
         ADD HASH PARTITION/
@@ -4389,6 +4468,19 @@
         7) Write binlog and return from statement (including releasing all
            remaining locks).
       */
+      if ((mysql_write_frm(&wft, TRUE, FALSE)) ||
+          (mysql_add_partitions(table, create_info, db, table_name)) ||
+          (table->file->copy_partitions()) ||
+          (abort_and_upgrade_lock(thd, table, db,
+                                  table_name, &old_lock_type)) ||
+          (mysql_drop_partitions(table, db, table_name)) ||
+          (mysql_write_frm(&wft, FALSE, TRUE)))
+      {
+        DBUG_RETURN(TRUE);
+      }
+      close_open_tables_and_downgrade(thd, table,
+                                      db, table_name, old_lock_type);
+
     }
     else
     {
@@ -4410,6 +4502,18 @@
         9) Write binlog and return from statement (including releasing all
            remaining locks).
       */
+      if (table->reginfo.lock_type == TL_WRITE_ALLOW_READ)
+        mysql_lock_downgrade_write(thd, table, TL_WRITE_ALLOW_WRITE);
+      if ((mysql_write_frm(&wft, TRUE, FALSE)) ||
+          (mysql_add_partitions(table, create_info, db, table_name)) ||
+          (table->file->copy_partitions()) ||
+          (mysql_write_frm(&wft, FALSE, TRUE)) ||
+          (mysql_wait_completed_table(thd, table, db, table_name)) ||
+          (mysql_drop_partitions(table, db, table_name)) ||
+          (mysql_wait_completed_table(thd, table, db, table_name)))
+      {
+        DBUG_RETURN(TRUE);
+      }
     }
     /*
       A final step is to write the query to the binlog and send ok to the
@@ -4422,10 +4526,6 @@
   }
 #endif
 
-        if (table->file->add_partitions(table, create_info, path))
-        {
-          DBUG_RETURN(TRUE);
-        }
   /*
     Handling of symlinked tables:
     If no rename:
Thread
bk commit into 5.1 tree (mronstrom:1.1895)mikael24 Aug