List:Commits« Previous MessageNext Message »
From:Rohit Kalhans Date:April 19 2012 11:02am
Subject:bzr push into mysql-trunk-wl5597 branch (rohit.kalhans:3676 to 3677) WL#5597
View as plain text  
 3677 Rohit Kalhans	2012-04-19
      WL#5597:
      
      Changes handling review comments from Luis and Nuno.

    modified:
      sql/handler.h
      sql/log_event.cc
      sql/log_event.h
      sql/rpl_utility.cc
      sql/rpl_utility.h
 3676 Rohit Kalhans	2012-04-17
      WL#5597:
      Code cleanup (removed trailing spaces)
      Removed DBUG_ASSERT(crc > 0) from make_hash_key() as 0
      has become a valid value of hash_key.

    modified:
      sql/rpl_utility.cc
=== modified file 'sql/handler.h'
--- a/sql/handler.h	2012-04-16 15:31:21 +0000
+++ b/sql/handler.h	2012-04-19 10:02:15 +0000
@@ -178,7 +178,6 @@ enum enum_alter_inplace_result {
 */
 #define HA_CAN_REPAIR                    (LL(1) << 37)
 
-
 /*
   Set of all binlog flags. Currently only contain the capabilities
   flags.

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2012-04-16 15:31:21 +0000
+++ b/sql/log_event.cc	2012-04-19 10:02:15 +0000
@@ -9083,16 +9083,8 @@ search_key_in_table(TABLE *table, MY_BIT
 void
 Rows_log_event::decide_row_lookup_algorithm_and_key()
 {
-  DBUG_ENTER("decide_row_lookup_algorithm_and_key");
-
-  TABLE *table= this->m_table;
-  uint event_type= this->get_type_code();
-  MY_BITMAP *cols= &this->m_cols;
-  this->m_rows_lookup_algorithm= ROW_LOOKUP_NOT_NEEDED;
-  this->m_key_index= MAX_KEY;
 
-  if (event_type == WRITE_ROWS_EVENT)  // Not needed
-    DBUG_VOID_RETURN;
+  DBUG_ENTER("decide_row_lookup_algorithm_and_key");
 
   /*
     Decision table:
@@ -9111,6 +9103,15 @@ Rows_log_event::decide_row_lookup_algori
 
   */
 
+  TABLE *table= this->m_table;
+  uint event_type= this->get_type_code();
+  MY_BITMAP *cols= &this->m_cols;
+  this->m_rows_lookup_algorithm= ROW_LOOKUP_NOT_NEEDED;
+  this->m_key_index= MAX_KEY;
+
+  if (event_type == WRITE_ROWS_EVENT)  // row lookup not needed
+    DBUG_VOID_RETURN;
+
   if (!(slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN))
     goto TABLE_OR_INDEX_HASH_SCAN;
 
@@ -9169,10 +9170,99 @@ end:
   DBUG_PRINT("debug", ("Row lookup method: %s", s));
 #endif
 
-  /* allocate memory and initialize hash */
+  DBUG_VOID_RETURN;
+}
 
+/*
+  Encapsulates the  operations to be done before applying
+  row events for update and delete.
 
-  DBUG_VOID_RETURN;
+  @ret value error code
+             0 success
+*/
+int
+Rows_log_event::init_row_update_or_delete()
+{
+  int error= 0;
+  DBUG_ENTER("Row_log_event::init_update_or_delete");
+
+  /*
+     Prepare memory structures for search operations. If
+     search is performed:
+
+     1. using hash search => initialize the hash
+     2. using key => decide on key to use and allocate mem structures
+     3. using table scan => do nothing
+   */
+  decide_row_lookup_algorithm_and_key();
+
+  switch (m_rows_lookup_algorithm)
+  {
+  case ROW_LOOKUP_HASH_SCAN:
+    {
+      if (m_hash.init())
+        error= HA_ERR_OUT_OF_MEM;
+      goto err;
+    }
+  case ROW_LOOKUP_INDEX_SCAN:
+    {
+      DBUG_ASSERT (m_key_index < MAX_KEY);
+      // Allocate buffer for key searches
+      m_key= (uchar*)my_malloc(MAX_KEY_LENGTH, MYF(MY_WME));
+      if (!m_key)
+        error= HA_ERR_OUT_OF_MEM;
+      goto err;
+    }
+  case ROW_LOOKUP_TABLE_SCAN:
+  default: break;
+  }
+err:
+  DBUG_RETURN(error);
+}
+
+/*
+  Encapsulates the  operations to be done afetr applying
+  row events for update and delete.
+
+  @ret value error code
+             0 success
+*/
+
+int
+Rows_log_event::finish_row_update_or_delete(int error)
+{
+
+  DBUG_ENTER("Rows_log_event::finish_row_update_or_delete");
+
+  if (m_table->file->inited)
+    m_table->file->ha_index_or_rnd_end();
+
+  switch (m_rows_lookup_algorithm)
+  {
+  case ROW_LOOKUP_HASH_SCAN:
+    {
+      m_hash.deinit(); // we don't need the hash anymore.
+      goto err;
+    }
+
+  case ROW_LOOKUP_INDEX_SCAN:
+    {
+      if (m_table->s->keys > 0)
+      {
+        my_free(m_key); // Free for multi_malloc
+        m_key= NULL;
+        m_key_index= MAX_KEY;
+      }
+     goto err;
+    }
+
+  case ROW_LOOKUP_TABLE_SCAN:
+  default: break;
+  }
+
+err:
+  m_rows_lookup_algorithm= ROW_LOOKUP_UNDEFINED;
+  DBUG_RETURN(error);
 }
 
 /*
@@ -9394,7 +9484,8 @@ Rows_log_event::close_record_scan()
     }
   }
   else
-    error= m_table->file->ha_rnd_end();
+    if (m_table->file->inited)
+      error= m_table->file->ha_rnd_end();
 
   DBUG_RETURN(error);
 }
@@ -9474,7 +9565,7 @@ Rows_log_event::next_record_scan(bool fi
 }
 
 /**
-  Initializes scanning of rows. Opens an index and initailizes an iterator
+  Initializes scanning of rows. Opens an index and initializes an iterator
   over a list of distinct keys (m_distinct_key_list) if it is a HASH_SCAN
   over an index or the table if its a HASH_SCAN over the table.
 */
@@ -9548,20 +9639,19 @@ end:
                 -Err_code
 */
 int
-Rows_log_event::add_distinct_keys()
+Rows_log_event::add_key_to_distinct_keyset()
 {
   int error= 0;
-  uint distinct= 0;
-  DBUG_ENTER("Rows_log_event::add_distinct_keys");
+  bool distinct= true;
+  DBUG_ENTER("Rows_log_event::add_key_to_distinct_keyset");
   DBUG_ASSERT(m_key_index < MAX_KEY);
   KEY *cur_key_info= m_table->key_info + m_key_index;
+
   if ((last_hashed_key))
     distinct= key_cmp(cur_key_info->key_part, last_hashed_key,
                       cur_key_info->key_length);
-    else //first row
-      distinct= 1;
 
-  if (distinct != 0)
+  if (distinct)
   {
     uchar *cur_key= (uchar *)my_malloc(cur_key_info->key_length,
                                        MYF(MY_WME));
@@ -9601,8 +9691,6 @@ int Rows_log_event::do_index_scan_and_up
   if ((error= unpack_current_row(rli, &m_cols)))
     goto end;
 
-  saved_m_curr_row= m_curr_row;
-
   // Temporary fix to find out why it fails [/Matz]
   memcpy(m_table->read_set->bitmap, m_cols.bitmap, (m_table->read_set->n_bits + 7) / 8);
 
@@ -9793,7 +9881,7 @@ int Rows_log_event::do_hash_scan_and_upd
   const uchar *bi_ends= NULL;
   const uchar *ai_start= NULL;
   const uchar *ai_ends= NULL;
-  HASH_ROW_POS_ENTRY* entry;
+  HASH_ROW_ENTRY* entry;
   int idempotent_errors= 0;
 
   DBUG_ENTER("Rows_log_event::do_hash_scan_and_update");
@@ -9831,7 +9919,7 @@ int Rows_log_event::do_hash_scan_and_upd
   /* add it to the hash table */
   m_hash.put(m_table, &m_cols, entry);
   if (m_key_index < MAX_KEY)
-    add_distinct_keys();
+    add_key_to_distinct_keyset();
 
   /*
     Last row hashed. We are handling the last (pair of) row(s).  So
@@ -9875,8 +9963,8 @@ int Rows_log_event::do_hash_scan_and_upd
            */
           while(entry)
           {
-            m_curr_row= entry->bi_start;
-            m_curr_row_end= entry->bi_ends;
+            m_curr_row= entry->positions->bi_start;
+            m_curr_row_end= entry->positions->bi_ends;
 
             if ((error= unpack_current_row(rli, &m_cols)))
               goto close_table;
@@ -9906,8 +9994,8 @@ int Rows_log_event::do_hash_scan_and_upd
                unpacked correctly to table->record[0] in UPDATE
                implementation of do_exec_row().
             */
-            m_curr_row= entry->bi_start;
-            m_curr_row_end= entry->bi_ends;
+            m_curr_row= entry->positions->bi_start;
+            m_curr_row_end= entry->positions->bi_ends;
 
             /* we don't need this entry anymore, just delete it */
             if ((error= m_hash.del(entry)))
@@ -9947,7 +10035,7 @@ int Rows_log_event::do_hash_scan_and_upd
      be empty. In such cases we count the number of idempotent errors and check
      if it is equal to or greater than the number of rows left in the hash.
     */
-    while (((idempotent_errors < m_hash.size()) && !m_hash.is_empty()) && 
+    while (((idempotent_errors < m_hash.size()) && !m_hash.is_empty()) &&
            (!error || (error == HA_ERR_RECORD_DELETED)));
 
 close_table:
@@ -10058,10 +10146,7 @@ end:
   else
     error= do_apply_row(rli);
 
-  /* close the index */
-  if (table->file->inited)
-    table->file->ha_rnd_end();
-
+  error= close_record_scan();
   if ((get_type_code() == UPDATE_ROWS_EVENT) &&
       (saved_m_curr_row == m_curr_row)) // we need to unpack the AI
   {
@@ -10293,37 +10378,29 @@ int Rows_log_event::do_apply_event(Relay
      if ( m_width == table->s->fields && bitmap_is_set_all(&m_cols))
       set_flags(COMPLETE_ROWS_F);
 
-    /* 
+    /*
       Set tables write and read sets.
-      
+
       Read_set contains all slave columns (in case we are going to fetch
       a complete record from slave)
-      
-      Write_set equals the m_cols bitmap sent from master but it can be 
-      longer if slave has extra columns. 
-     */ 
+
+      Write_set equals the m_cols bitmap sent from master but it can be
+      longer if slave has extra columns.
+     */
 
     DBUG_PRINT_BITSET("debug", "Setting table's read_set from: %s", &m_cols);
-    
+
     bitmap_set_all(table->read_set);
     if (get_type_code() == DELETE_ROWS_EVENT ||
         get_type_code() == UPDATE_ROWS_EVENT)
         bitmap_intersect(table->read_set,&m_cols);
 
     bitmap_set_all(table->write_set);
-    if (!get_flags(COMPLETE_ROWS_F))
-    {
-      if (get_type_code() == UPDATE_ROWS_EVENT)
-      {
-        DBUG_PRINT_BITSET("debug", "Setting table's write_set from: %s", &m_cols_ai);
-        bitmap_intersect(table->write_set,&m_cols_ai);
-      }
-      else /* WRITE ROWS EVENTS store the bitmap in m_cols instead of m_cols_ai */     
-      {
-        DBUG_PRINT_BITSET("debug", "Setting table's write_set from: %s", &m_cols);
-        bitmap_intersect(table->write_set,&m_cols);
-      }
-    }
+
+    /* WRITE ROWS EVENTS store the bitmap in m_cols instead of m_cols_ai */
+    MY_BITMAP *after_image= ((get_type_code() == UPDATE_ROWS_EVENT) ?
+                             &m_cols_ai : &m_cols);
+    bitmap_intersect(table->write_set, after_image);
 
     this->slave_exec_mode= slave_exec_mode_options; // fix the mode
 
@@ -11665,8 +11742,8 @@ Write_rows_log_event::write_row(const Re
      */
 
     /*
-      If row is incomplete we will use the record found to fill 
-      missing columns.  
+      If row is incomplete we will use the record found to fill
+      missing columns.
     */
     if (!get_flags(COMPLETE_ROWS_F))
     {
@@ -11793,55 +11870,22 @@ Delete_rows_log_event::Delete_rows_log_e
 
 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
 
-int 
+int
 Delete_rows_log_event::do_before_row_operations(const Slave_reporting_capability *const)
 {
-  /* 
-     Prepare memory structures for search operations. If
-     search is performed:
-    
-     1. using hash search => initialize the hash
-     2. using key => decide on key to use and allocate mem structures
-     3. using table scan => do nothing
-   */
-  decide_row_lookup_algorithm_and_key();
-
-  if (m_rows_lookup_algorithm == ROW_LOOKUP_HASH_SCAN)
-  {
-    if (m_hash.init())
-      return HA_ERR_OUT_OF_MEM;
-  }
-
-  if ((m_rows_lookup_algorithm == ROW_LOOKUP_INDEX_SCAN) &&
-      (m_key_index < MAX_KEY))
-  {
-    // Allocate buffer for key searches
-    m_key= (uchar*)my_malloc(MAX_KEY_LENGTH, MYF(MY_WME));
-    if (!m_key)
-      return HA_ERR_OUT_OF_MEM;
-  }
-  return 0;
+  int error= 0;
+  DBUG_ENTER("Delete_rows_log_event::do_before_row_operations");
+  error= init_row_update_or_delete();
+  DBUG_RETURN(error);
 }
 
-int 
-Delete_rows_log_event::do_after_row_operations(const Slave_reporting_capability *const, 
+int
+Delete_rows_log_event::do_after_row_operations(const Slave_reporting_capability *const,
                                                int error)
 {
-  /*error= ToDo:find out what this should really be, this triggers close_scan in nbd, returning error?*/
-  m_table->file->ha_index_or_rnd_end();
-  if ((m_rows_lookup_algorithm == ROW_LOOKUP_INDEX_SCAN) &&
-      (m_key_index < MAX_KEY))
-  {
-    my_free(m_key); // Free for multi_malloc
-    m_key= NULL; 
-    m_key_index= MAX_KEY;
-  }
-
-  /* we don't need the hash anymore, free it */
-  if (m_rows_lookup_algorithm == ROW_LOOKUP_HASH_SCAN)
-    m_hash.deinit();
-  m_rows_lookup_algorithm= ROW_LOOKUP_UNDEFINED;
-  return error;
+  DBUG_ENTER("Delete_rows_log_event::do_after_row_operations");
+  error= finish_row_update_or_delete(error);
+  DBUG_RETURN(error);
 }
 
 int Delete_rows_log_event::do_exec_row(const Relay_log_info *const rli)
@@ -11924,60 +11968,25 @@ Update_rows_log_event::Update_rows_log_e
 
 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
 
-int 
+int
 Update_rows_log_event::do_before_row_operations(const Slave_reporting_capability *const)
 {
-  /* 
-     Prepare memory structures for search operations. If
-     search is performed:
-    
-     1. using hash search => initialize the hash
-     2. using key => decide on key to use and allocate mem structures
-     3. using table scan => do nothing
-   */
-  decide_row_lookup_algorithm_and_key();
-
-  if (m_rows_lookup_algorithm == ROW_LOOKUP_HASH_SCAN)
-  {
-    if (m_hash.init())
-      return HA_ERR_OUT_OF_MEM;
-  }
-
-  if ((m_rows_lookup_algorithm == ROW_LOOKUP_INDEX_SCAN) &&
-      (m_key_index < MAX_KEY))
-  {
-    // Allocate buffer for key searches
-    m_key= (uchar*)my_malloc(MAX_KEY_LENGTH, MYF(MY_WME));
-    if (!m_key)
-      return HA_ERR_OUT_OF_MEM;
-  }
-  return 0;
+  int error= 0;
+  DBUG_ENTER("Update_rows_log_event::do_before_row_operations");
+  error= init_row_update_or_delete();
+  DBUG_RETURN(error);
 }
 
-int 
-Update_rows_log_event::do_after_row_operations(const Slave_reporting_capability *const, 
+int
+Update_rows_log_event::do_after_row_operations(const Slave_reporting_capability *const,
                                                int error)
 {
-  /*error= ToDo:find out what this should really be, this triggers close_scan in nbd, returning error?*/
-  m_table->file->ha_index_or_rnd_end();
-
-  if ((m_table->s->keys > 0) &&
-      (m_rows_lookup_algorithm == ROW_LOOKUP_INDEX_SCAN))
-  {
-    my_free(m_key); // Free for multi_malloc
-    m_key= NULL;
-    m_key_index= MAX_KEY;
-  }
-
-  /* we don't need the hash anymore, free it */
-  if (m_rows_lookup_algorithm == ROW_LOOKUP_HASH_SCAN)  
-    m_hash.deinit();
-  m_rows_lookup_algorithm= ROW_LOOKUP_UNDEFINED;
-
-  return error;
+  DBUG_ENTER("Update_rows_log_event::do_after_row_operations");
+  error= finish_row_update_or_delete(error);
+  DBUG_RETURN(error);
 }
 
-int 
+int
 Update_rows_log_event::do_exec_row(const Relay_log_info *const rli)
 {
   DBUG_ASSERT(m_table != NULL);

=== modified file 'sql/log_event.h'
--- a/sql/log_event.h	2012-04-09 13:43:35 +0000
+++ b/sql/log_event.h	2012-04-19 10:02:15 +0000
@@ -3833,7 +3833,7 @@ public:
        ROW_LOOKUP_NOT_NEEDED= 1,
        ROW_LOOKUP_INDEX_SCAN= 2,
        ROW_LOOKUP_TABLE_SCAN= 3,
-       ROW_LOOKUP_HASH_SCAN= 4,
+       ROW_LOOKUP_HASH_SCAN= 4
   };
 
   /**
@@ -4073,7 +4073,27 @@ protected:
     return result;
   }
 
+  /*
+    This member function is called when deciding the algorithm to be used to
+    find the rows to be updated on the slave during row based replication.
+    This this functions sets the m_rows_lookup_algorithm and also the
+    m_key_index with the key index to be used if the algorithm is dependent on
+    an index.
+   */
   void decide_row_lookup_algorithm_and_key();
+
+  /*
+    Encapsulates the  operations to be done before applying
+    row event for update and delete.
+   */
+  int init_row_update_or_delete();
+
+  /*
+   Encapsulates the  operations to be done after applying
+   row event for update and delete.
+  */
+  int finish_row_update_or_delete(int error);
+
 #endif
 
 private:
@@ -4183,10 +4203,42 @@ private:
    */
   int do_table_scan_and_update(Relay_log_info const *rli);
 
+/**
+  Initializes scanning of rows. Opens an index and initailizes an iterator
+  over a list of distinct keys (m_distinct_key_list) if it is a HASH_SCAN
+  over an index or the table if its a HASH_SCAN over the table.
+*/
   int open_record_scan();
+
+/**
+   Does the cleanup
+     -  deallocates all the elements in m_distinct_key_list if any
+     -  closes the index if opened by open_record_scan
+     -  closes the table if opened for scanning.
+*/
   int close_record_scan();
+
+/**
+  Fetches next row. If it is a HASH_SCAN over an index, it populates
+  table->record[0] with the next row corresponding to the index. If
+  the indexes are in non-contigous ranges it fetches record corresponding
+  to the key value in the next range.
+
+  @parms: bool first_read : signifying if this is the first time we are reading a row
+          over an index.
+  @return_value: -  error code when there are no more reeords to be fetched or some other
+                    error occured,
+                 -  0 otherwise.
+*/
   int next_record_scan(bool first_read);
-  int add_distinct_keys();
+
+/**
+  Populates the m_distinct_key_list with unique keys to be modified
+  during HASH_SCAN over keys.
+  @return_value -0 success
+                -Err_code
+*/
+  int add_key_to_distinct_keyset();
 #endif /* defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) */
 
   friend class Old_rows_log_event;

=== modified file 'sql/rpl_utility.cc'
--- a/sql/rpl_utility.cc	2012-04-17 10:37:22 +0000
+++ b/sql/rpl_utility.cc	2012-04-19 10:02:15 +0000
@@ -1171,91 +1171,6 @@ bool event_checksum_test(uchar *event_bu
   Utility methods for handling row based operations.
  */
 
-/**
-
-   Internal structure that acts as a preamble for HASH_ROW_POS_ENTRY
-   in memory structure. Allocation in make_entry is done as follows:
-
-   preamble_ptr= malloc (sizeof(preamble)+sizeof(entry));
-   entry_ptr= preamble_ptr+1;
-
-   preamble_ptr  -----> |-HASH_ROWS_POS_PREAMBLE--|
-                        | - hash_value            |
-                        | - length                |
-                        | - is_search_state_inited|
-                        | - search_state          |
-                        |                         |
-   entry_ptr     -----> |-HASH_ROW_POS_ENTRY------|
-                        | - bi_start              |
-                        | - bi_ends               |
-                        | - ai_start              |
-                        | - ai_ends               |
-                        |                         |
-                        |-------------------------|
-
-
-   return entry_ptr;
-
-   When iterating over an entry with multiple records, we can just use
-   pointer arithmetic to retrieve the preamble pointer. This way we
-   hide from the hash table user the gory details of key bookeeping
-   for the hash (including collision handling).
-
-*/
-typedef struct hash_row_pos_preamble
-{
-
-  /**
-     The actual key.
-  */
-  my_hash_value_type hash_value;
-
-  /**
-     Length of the key.
-  */
-  uint length;
-
-  /**
-     The search state used to iterate over multiple entries for a
-     given key.
-  */
-  HASH_SEARCH_STATE search_state;
-
-  /**
-     Wether this search_state is usable or not.
-   */
-  bool is_search_state_inited;
-
-} HASH_ROW_POS_PREAMBLE;
-
-
-/**
-  Auxiliar and internal member function used to get the pointer for
-  an entry preamble. Dual of @c get_entry.
-
-  @param the entry from which we are calculating the preamble pointer.
-  @returns a pointer to the preamble.
- */
-static
-HASH_ROW_POS_PREAMBLE* get_preamble(HASH_ROW_POS_ENTRY* entry)
-{
-  return ((HASH_ROW_POS_PREAMBLE*)entry)-1;
-}
-
-/**
-  Auxiliar and internal member function used to get the entry when
-  given a pointer to a preamble. Dual of @c get_preamble.
-
-  @param the preamble from which we are calculating the entry pointer.
-  @returns a pointer to the entry.
-*/
-static
-HASH_ROW_POS_ENTRY* get_entry(HASH_ROW_POS_PREAMBLE* preamble)
-{
-  return (HASH_ROW_POS_ENTRY*) (preamble+1);
-}
-
-
 static uchar*
 hash_slave_rows_get_key(const uchar *record,
                         size_t *length,
@@ -1263,18 +1178,25 @@ hash_slave_rows_get_key(const uchar *rec
 {
   DBUG_ENTER("get_key");
 
-  HASH_ROW_POS_PREAMBLE *preamble=(HASH_ROW_POS_PREAMBLE *) record;
+  HASH_ROW_ENTRY *entry=(HASH_ROW_ENTRY *) record;
+  HASH_ROW_PREAMBLE *preamble= entry->preamble;
   *length= preamble->length;
 
   DBUG_RETURN((uchar*) &preamble->hash_value);
 }
 
 static void
-hash_slave_rows_free_entry(HASH_ROW_POS_PREAMBLE *preamble)
+hash_slave_rows_free_entry(HASH_ROW_ENTRY *entry)
 {
   DBUG_ENTER("free_entry");
-  if (preamble)
-    my_free(preamble);
+  if (entry)
+  {
+    if (entry->preamble)
+      my_free(entry->preamble);
+    if (entry->positions)
+      my_free(entry->positions);
+    my_free(entry);
+  }
   DBUG_VOID_RETURN;
 }
 
@@ -1314,21 +1236,17 @@ int Hash_slave_rows::size()
   return m_hash.records;
 }
 
-HASH_ROW_POS_ENTRY* Hash_slave_rows::make_entry(const uchar* bi_start, const uchar* bi_ends,
-                                                const uchar* ai_start, const uchar* ai_ends)
+HASH_ROW_ENTRY* Hash_slave_rows::make_entry(const uchar* bi_start, const uchar* bi_ends,
+                                            const uchar* ai_start, const uchar* ai_ends)
 {
   DBUG_ENTER("Hash_slave_rows::make_entry");
 
-  size_t size= sizeof(struct hash_row_pos_preamble) +
-               sizeof(struct hash_row_pos_entry);
-
-  HASH_ROW_POS_PREAMBLE *preamble=
-    (HASH_ROW_POS_PREAMBLE*) my_malloc(size, MYF(0));
+  HASH_ROW_ENTRY *entry= (HASH_ROW_ENTRY*) my_malloc(sizeof(HASH_ROW_ENTRY), MYF(0));
+  HASH_ROW_PREAMBLE *preamble= (HASH_ROW_PREAMBLE *) my_malloc(sizeof(HASH_ROW_PREAMBLE), MYF(0));
+  HASH_ROW_POS *pos= (HASH_ROW_POS *) my_malloc(sizeof(HASH_ROW_POS), MYF(0));
 
-  if (!preamble)
-    DBUG_RETURN(NULL);
-
-  HASH_ROW_POS_ENTRY* entry= get_entry(preamble);
+  if (!entry || !preamble || !pos)
+    goto err;
 
   /**
      Filling in the preamble.
@@ -1339,31 +1257,40 @@ HASH_ROW_POS_ENTRY* Hash_slave_rows::mak
   preamble->is_search_state_inited= false;
 
   /**
-     Filling in the values.
+     Filling in the positions.
    */
-  entry->bi_start= (const uchar *) bi_start;
-  entry->bi_ends= (const uchar *) bi_ends;
-  entry->ai_start= (const uchar *) ai_start;
-  entry->ai_ends= (const uchar *) ai_ends;
-
-  DBUG_PRINT("debug", ("Added record to hash with key=%u", preamble->hash_value));
+  pos->bi_start= (const uchar *) bi_start;
+  pos->bi_ends= (const uchar *) bi_ends;
+  pos->ai_start= (const uchar *) ai_start;
+  pos->ai_ends= (const uchar *) ai_ends;
 
   /**
-     Return the pointer to the entry. The caller should not
-     be exposed to the internal preamble.
+    Filling in the entry
    */
+  entry->preamble= preamble;
+  entry->positions= pos;
+
   DBUG_RETURN(entry);
+
+err:
+  if (entry)
+    my_free(entry);
+  if (preamble)
+    my_free(entry);
+  if (pos)
+    my_free(pos);
+  DBUG_RETURN(NULL);
 }
 
 bool
 Hash_slave_rows::put(TABLE *table,
                      MY_BITMAP *cols,
-                     HASH_ROW_POS_ENTRY* entry)
+                     HASH_ROW_ENTRY* entry)
 {
 
   DBUG_ENTER("Hash_slave_rows::put");
 
-  HASH_ROW_POS_PREAMBLE* preamble= get_preamble(entry);
+  HASH_ROW_PREAMBLE* preamble= entry->preamble;
 
   /**
      Skip blobs and BIT fields from key calculation.
@@ -1373,29 +1300,28 @@ Hash_slave_rows::put(TABLE *table,
   */
   preamble->hash_value= make_hash_key(table, cols);
 
-  my_hash_insert(&m_hash, (uchar *) preamble);
+  my_hash_insert(&m_hash, (uchar *) entry);
   DBUG_PRINT("debug", ("Added record to hash with key=%u", preamble->hash_value));
   DBUG_RETURN(false);
 }
 
-HASH_ROW_POS_ENTRY*
+HASH_ROW_ENTRY*
 Hash_slave_rows::get(TABLE *table, MY_BITMAP *cols)
 {
   DBUG_ENTER("Hash_slave_rows::get");
   HASH_SEARCH_STATE state;
-  HASH_ROW_POS_PREAMBLE* preamble;
   my_hash_value_type key;
-  HASH_ROW_POS_ENTRY* res= NULL;
+  HASH_ROW_ENTRY *entry= NULL;
 
   key= make_hash_key(table, cols);
 
   DBUG_PRINT("debug", ("Looking for record with key=%u in the hash.", key));
 
-  preamble= (HASH_ROW_POS_PREAMBLE*) my_hash_first(&m_hash,
-                                                   (const uchar*) &key,
-                                                   sizeof(my_hash_value_type),
-                                                   &state);
-  if (preamble)
+  entry= (HASH_ROW_ENTRY*) my_hash_first(&m_hash,
+                                         (const uchar*) &key,
+                                         sizeof(my_hash_value_type),
+                                         &state);
+  if (entry)
   {
     DBUG_PRINT("debug", ("Found record with key=%u in the hash.", key));
 
@@ -1403,16 +1329,14 @@ Hash_slave_rows::get(TABLE *table, MY_BI
        Save the search state in case we need to go through entries for
        the given key.
     */
-    preamble->search_state= state;
-    preamble->is_search_state_inited= true;
-
-    res= get_entry(preamble);
+    entry->preamble->search_state= state;
+    entry->preamble->is_search_state_inited= true;
   }
 
-  DBUG_RETURN(res);
+  DBUG_RETURN(entry);
 }
 
-bool Hash_slave_rows::next(HASH_ROW_POS_ENTRY** entry)
+bool Hash_slave_rows::next(HASH_ROW_ENTRY** entry)
 {
   DBUG_ENTER("Hash_slave_rows::next");
   DBUG_ASSERT(*entry);
@@ -1420,7 +1344,7 @@ bool Hash_slave_rows::next(HASH_ROW_POS_
   if (*entry == NULL)
     DBUG_RETURN(true);
 
-  HASH_ROW_POS_PREAMBLE* preamble= get_preamble(*entry);
+  HASH_ROW_PREAMBLE *preamble= (*entry)->preamble;
 
   if (!preamble->is_search_state_inited)
     DBUG_RETURN(true);
@@ -1441,20 +1365,20 @@ bool Hash_slave_rows::next(HASH_ROW_POS_
   /**
      Do the actual search in the hash table.
    */
-  preamble= (HASH_ROW_POS_PREAMBLE*) my_hash_next(&m_hash,
-                                                  (const uchar*) &key,
-                                                  sizeof(my_hash_value_type),
-                                                  &state);
-  if (preamble)
+  *entry= (HASH_ROW_ENTRY*) my_hash_next(&m_hash,
+                                         (const uchar*) &key,
+                                         sizeof(my_hash_value_type),
+                                         &state);
+  if (*entry)
   {
     DBUG_PRINT("debug", ("Found record with key=%u in the hash (next).", key));
+    preamble= (*entry)->preamble;
 
     /**
        Save the search state for next iteration (if any).
      */
     preamble->search_state= state;
     preamble->is_search_state_inited= true;
-    *entry= get_entry(preamble);
   }
   else
     *entry= NULL;
@@ -1463,12 +1387,12 @@ bool Hash_slave_rows::next(HASH_ROW_POS_
 }
 
 bool
-Hash_slave_rows::del(HASH_ROW_POS_ENTRY* entry)
+Hash_slave_rows::del(HASH_ROW_ENTRY *entry)
 {
   DBUG_ENTER("Hash_slave_rows::del");
   DBUG_ASSERT(entry);
 
-  if (my_hash_delete(&m_hash, (uchar *) get_preamble(entry)))
+  if (my_hash_delete(&m_hash, (uchar *) entry))
     DBUG_RETURN(true);
   DBUG_RETURN(false);
 }

=== modified file 'sql/rpl_utility.h'
--- a/sql/rpl_utility.h	2012-04-09 13:43:35 +0000
+++ b/sql/rpl_utility.h	2012-04-19 10:02:15 +0000
@@ -38,7 +38,7 @@ class Relay_log_info;
    no index on the slave's table.
  */
 
-typedef struct hash_row_pos_entry
+typedef struct hash_row_pos_st
 {
   /** 
       Points at the position where the row starts in the
@@ -51,9 +51,47 @@ typedef struct hash_row_pos_entry
   const uchar *ai_start;
   const uchar *ai_ends;
 
-} HASH_ROW_POS_ENTRY;
+} HASH_ROW_POS;
 
 
+/**
+   Internal structure that acts as a preamble for HASH_ROW_POS
+   in memory structure. 
+   
+   Allocation is done in Hash_slave_rows::make_entry as part of 
+   the entry allocation.
+ */
+typedef struct hash_row_preamble_st
+{
+  /*
+    The actual key.
+   */
+  my_hash_value_type hash_value;
+
+  /**  
+    Length of the key.
+   */
+  uint length;
+
+  /**  
+    The search state used to iterate over multiple entries for a
+    given key.
+   */
+  HASH_SEARCH_STATE search_state;
+
+  /**  
+    Wether this search_state is usable or not.
+   */
+  bool is_search_state_inited;
+
+} HASH_ROW_PREAMBLE;
+
+typedef struct hash_row_entry_st
+{
+  HASH_ROW_PREAMBLE *preamble;
+  HASH_ROW_POS *positions;
+} HASH_ROW_ENTRY;
+
 class Hash_slave_rows 
 {
 public:
@@ -72,8 +110,8 @@ public:
                      after image ends (if any).
      @returns NULL if a problem occured, a valid pointer otherwise.
    */
-  HASH_ROW_POS_ENTRY* make_entry(const uchar *bi_start, const uchar *bi_ends,
-                                 const uchar *ai_start, const uchar *ai_ends);
+  HASH_ROW_ENTRY* make_entry(const uchar *bi_start, const uchar *bi_ends,
+                             const uchar *ai_start, const uchar *ai_ends);
 
   /**
      Puts data into the hash table.
@@ -85,7 +123,7 @@ public:
 
      @returns true if something went wrong, false otherwise.
    */
-  bool put(TABLE* table, MY_BITMAP *cols, HASH_ROW_POS_ENTRY* entry);
+  bool put(TABLE* table, MY_BITMAP *cols, HASH_ROW_ENTRY* entry);
 
   /**
      Gets the entry, from the hash table, that matches the data in
@@ -100,7 +138,7 @@ public:
               found. If the entry is not found then NULL shall be
               returned.
    */
-  HASH_ROW_POS_ENTRY* get(TABLE *table, MY_BITMAP *cols);
+  HASH_ROW_ENTRY* get(TABLE *table, MY_BITMAP *cols);
 
   /**
      Gets the entry that stands next to the one pointed to by
@@ -118,7 +156,7 @@ public:
               operation this member function returns true and does not
               update the pointer.
    */
-  bool next(HASH_ROW_POS_ENTRY** entry);
+  bool next(HASH_ROW_ENTRY** entry);
 
   /**
      Deletes the entry pointed by entry. It also frees memory used
@@ -129,7 +167,7 @@ public:
      @param entry  Pointer to the entry to be deleted.
      @returns true if something went wrong, false otherwise.
    */
-  bool del(HASH_ROW_POS_ENTRY* entry);
+  bool del(HASH_ROW_ENTRY* entry);
 
   /**
      Initializes the hash table.

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk-wl5597 branch (rohit.kalhans:3676 to 3677) WL#5597Rohit Kalhans20 Apr