List:Commits« Previous MessageNext Message »
From:Manish Kumar Date:August 21 2012 8:53am
Subject:bzr push into mysql-5.6 branch (manish.4.kumar:4135 to 4136) Bug#14381701
View as plain text  
 4136 Manish Kumar	2012-08-21
      BUG#14381701 - DELETING FROM A HASH WHILE ITERATING OVER IT IS WRONG
      
      Problem - The problem is that in sql/rpl_rli_pdb.cc file we delete
                from a hash while iterating over it. This is wrong since 
                delete operation might rearrange elements in hash, 
                so "iterator" will become invalid and, unless extra steps
                are taken, such iteration is likely to miss elements which 
                should have been deleted otherwise.
      
      Fix - The problem is fixed by storing the address of the Hash elements 
            that needs to be deleted based on the usage, in the Dynamic array
            of pointers in a for loop. In a second iteration we pop the 
            elements of the dynamic array and delete the Hash element from 
            that address. This will not cause any inconsistency.
     @ sql/rpl_rli_pdb.cc
        Added the new Dynamic array " hash_element "  which is used to store the
        hash entries that need to be deleted.

    modified:
      sql/rpl_rli_pdb.cc
 4135 Marko Mäkelä	2012-08-21 [merge]
      Merge mysql-5.5 to mysql-5.6.

    modified:
      storage/innobase/ibuf/ibuf0ibuf.cc
      storage/innobase/row/row0ins.cc
=== modified file 'sql/rpl_rli_pdb.cc'
--- a/sql/rpl_rli_pdb.cc	2012-08-09 10:05:01 +0000
+++ b/sql/rpl_rli_pdb.cc	2012-08-21 08:50:39 +0000
@@ -11,6 +11,9 @@
   uint mts_debug_concurrent_access= 0;
 #endif
 
+#define HASH_DYNAMIC_INIT 4
+#define HASH_DYNAMIC_INCR 1
+
 /*
   Please every time you add a new field to the worker slave info, update
   what follows. For now, this is just used to get the number of fields.
@@ -709,6 +712,13 @@ Slave_worker *map_db_to_worker(const cha
 {
   uint i;
   DYNAMIC_ARRAY *workers= &rli->workers;
+
+  /*
+    A dynamic array to store the mapping_db_to_worker hash elements 
+    that needs to be deleted, since deleting the hash entires while 
+    iterating over it is wrong.
+  */
+  DYNAMIC_ARRAY hash_element;
   THD *thd= rli->info_thd;
 
   DBUG_ENTER("get_slave_worker");
@@ -791,21 +801,39 @@ Slave_worker *map_db_to_worker(const cha
     entry->worker->usage_partition++;
     if (mapping_db_to_worker.records > mts_partition_hash_soft_max)
     {
-      /* remove zero-usage (todo: rare or long ago scheduled) records */
+      /*
+        remove zero-usage (todo: rare or long ago scheduled) records.
+        Store the element of the hash in a dynamic array after checking whether
+        the usage of the hash entry is 0 or not. We later free it from the HASH.
+      */
+      my_init_dynamic_array(&hash_element, sizeof(db_worker_hash_entry *),
+                            HASH_DYNAMIC_INIT, HASH_DYNAMIC_INCR);
       for (uint i= 0; i < mapping_db_to_worker.records; i++)
       {
+        DBUG_ASSERT(!entry->temporary_tables || !entry->temporary_tables->prev);
+        DBUG_ASSERT(!thd->temporary_tables || !thd->temporary_tables->prev);
+
         db_worker_hash_entry *entry=
           (db_worker_hash_entry*) my_hash_element(&mapping_db_to_worker, i);
+
         if (entry->usage == 0)
         {
-          DBUG_ASSERT(!entry->temporary_tables || !entry->temporary_tables->prev);
-          DBUG_ASSERT(!thd->temporary_tables || !thd->temporary_tables->prev);
-          
           mts_move_temp_tables_to_thd(thd, entry->temporary_tables);
           entry->temporary_tables= NULL;
-          my_hash_delete(&mapping_db_to_worker, (uchar*) entry);
+
+          /* Push the element in the dynamic array*/
+          push_dynamic(&hash_element, (uchar*) &entry);
         }
       }
+
+      /* Delete the hash element based on the usage */
+      for (uint i=0; i < hash_element.elements; i++)
+      {
+        db_worker_hash_entry *temp_entry= *(db_worker_hash_entry **) dynamic_array_ptr(&hash_element, i);
+        my_hash_delete(&mapping_db_to_worker, (uchar*) temp_entry);        
+      }
+        /* Deleting the dynamic array */
+      delete_dynamic(&hash_element);
     }
 
     ret= my_hash_insert(&mapping_db_to_worker, (uchar*) entry);

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.6 branch (manish.4.kumar:4135 to 4136) Bug#14381701Manish Kumar21 Aug