List:Commits« Previous MessageNext Message »
From:Alfranio Correia Date:November 11 2010 11:53am
Subject:bzr commit into mysql-next-mr.crash-safe branch (alfranio.correia:3208)
WL#5599
View as plain text  
#At file:///home/acorreia/workspace.sun/repository.mysql.new/bzrwork/wl-5569/mysql-next-mr-wl5569/ based on revid:alfranio.correia@stripped

 3208 Alfranio Correia	2010-11-11
      WL#5599
      
      The patch changed the handler's functions, i.e. init_info, check_info,
      flush_info, remove_info and end_info and the related private member
      functions, in both file and table handlers, to accept an index that
      identifies the information that will be read or written.
      
      This is necessary now because the handlers will be used by the workers
      to read and write information from file(s) and table and there may be
      several workers running at the same time and thus an index is used to
      identify the worker that is accessing information.
      
      This change is also necessary for the multi-master replication as
      information from each master must be uniquely identified.
     @ sql/binlog.cc
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.
     @ sql/log_event.cc
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.
     @ sql/rpl_constants.h
        Introduced an array and a variable that states the array's size
        and are used as parameters to init_info, check_info, flush_info,
        remove_info and end_info.
        
        This is ok for now as we assume a single master and uses slave's
        id to identify entries in a system table, if there is any. However,
        this code needs to be changed when we start handling multi-master
        replication.
     @ sql/rpl_info.cc
        Introduced an array and a variable that states the array's size
        and are used as parameters to init_info, check_info, flush_info,
        remove_info and end_info.
        
        This is ok for now as we assume a single master and uses slave's
        id to identify entries in a system table, if there is any. However,
        this code needs to be changed when we start handling multi-master
        replication.
     @ sql/rpl_info.h
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.
     @ sql/rpl_info_factory.cc
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.
        
        Removed static references to field indexes used as primary key.
     @ sql/rpl_info_factory.h
        Removed static references to field indexes used as primary key.
     @ sql/rpl_info_file.cc
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.
     @ sql/rpl_info_file.h
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.
     @ sql/rpl_info_handler.h
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.
     @ sql/rpl_info_table.cc
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.
        
        Changed the calls to find_info_for_server_id.
     @ sql/rpl_info_table.h
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.
     @ sql/rpl_info_table_access.cc
        Changed the funciton find_info_server_id in order to put the
        cursor at a row identified by uidx which is an array of fields
        that composes a primary key.
        
        The name of the function was also changed to reflect the new
        behavior.
     @ sql/rpl_info_table_access.h
        Changed the funciton find_info_server_id in order to put the
        cursor at a row identified by uidx which is an array of fields
        that composes a primary key.
        
        The name of the function was also changed to reflect the new
        behavior.
     @ sql/rpl_mi.cc
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.
        
        Moved the call to handler->flush_info from write_info to flush_info in
        order to avoid passing uidx and idx as parameters.
     @ sql/rpl_mi.h
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.
     @ sql/rpl_rli.cc
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.
     @ sql/rpl_rli.h
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.
     @ sql/rpl_rli_pdb.cc
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.
        
        Moved the call to handler->flush_info from write_info to flush_info in
        order to avoid passing uidx and idx as parameters.
     @ sql/rpl_rli_pdb.h
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.
     @ sql/rpl_slave.cc
        Changed the calls to init_info, check_info, flush_info, remove_info and
        end_info and the related private member functions.

    modified:
      sql/binlog.cc
      sql/log_event.cc
      sql/rpl_constants.h
      sql/rpl_info.cc
      sql/rpl_info.h
      sql/rpl_info_factory.cc
      sql/rpl_info_factory.h
      sql/rpl_info_file.cc
      sql/rpl_info_file.h
      sql/rpl_info_handler.h
      sql/rpl_info_table.cc
      sql/rpl_info_table.h
      sql/rpl_info_table_access.cc
      sql/rpl_info_table_access.h
      sql/rpl_mi.cc
      sql/rpl_mi.h
      sql/rpl_rli.cc
      sql/rpl_rli.h
      sql/rpl_rli_pdb.cc
      sql/rpl_rli_pdb.h
      sql/rpl_slave.cc
=== modified file 'sql/binlog.cc'
--- a/sql/binlog.cc	2010-10-08 14:35:24 +0000
+++ b/sql/binlog.cc	2010-11-11 11:53:01 +0000
@@ -2140,7 +2140,8 @@ int MYSQL_BIN_LOG::purge_first_log(Relay
   }
 
   /* Store where we are in the new file for the execution thread */
-  rli->flush_info(TRUE);
+  /* Andrei needs to guarantee that there is no worker using the current relay log. */
+  rli->flush_info(key_info_idx, key_info_size, TRUE);
 
   DBUG_EXECUTE_IF("crash_before_purge_logs", DBUG_ABORT(););
 

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2010-11-10 10:57:13 +0000
+++ b/sql/log_event.cc	2010-11-11 11:53:01 +0000
@@ -3888,7 +3888,8 @@ int Query_log_event::do_update_pos(Relay
   DBUG_EXECUTE_IF("crash_after_commit_and_update_pos",
        if (!strcmp("COMMIT", query))
        {
-         rli->flush_info(TRUE);
+         /* Alfranio needs to update the coordinator and workers. */
+         rli->flush_info(key_info_idx, key_info_size, TRUE);
          DBUG_ABORT();
        }
   );
@@ -5538,7 +5539,11 @@ int Rotate_log_event::do_update_pos(Rela
                         rli->get_group_master_log_name(),
                         (ulong) rli->get_group_master_log_pos()));
     mysql_mutex_unlock(&rli->data_lock);
-    rli->flush_info(TRUE);
+    /*
+       Andrei to investigate if it is necessary to guarantee that
+       this done in sequential mode.
+    */
+    rli->flush_info(key_info_idx, key_info_size, TRUE);
     
     /*
       Reset thd->variables.option_bits and sql_mode etc, because this could be the signal of
@@ -5901,7 +5906,6 @@ void Xid_log_event::print(FILE* file, PR
 int Xid_log_event::do_apply_event(Relay_log_info const *rli)
 {
   int error= 0;
-
   Relay_log_info *rli_ptr= const_cast<Relay_log_info *>(rli);
 
   /*
@@ -5946,8 +5950,9 @@ int Xid_log_event::do_apply_event(Relay_
     {
       rli_ptr->set_group_master_log_pos(log_pos);
     }
-  
-    if ((error= rli_ptr->flush_info(TRUE)))
+
+    /* Alfranio needs to update the coordinator and workers. */ 
+    if ((error= rli_ptr->flush_info(key_info_idx, key_info_size, TRUE)))
       goto err;
   }
 
@@ -6618,7 +6623,11 @@ int Stop_log_event::do_update_pos(Relay_
   else
   {
     rli->inc_group_relay_log_pos(0);
-    rli->flush_info(TRUE);
+    /*
+       Andrei to investigate if it is necessary to guarantee that
+       this done in sequential mode.
+    */
+    rli->flush_info(key_info_idx, key_info_size, TRUE);
   }
   return 0;
 }

=== modified file 'sql/rpl_constants.h'
--- a/sql/rpl_constants.h	2008-12-29 16:04:10 +0000
+++ b/sql/rpl_constants.h	2010-11-11 11:53:01 +0000
@@ -15,4 +15,14 @@ enum Incident {
   INCIDENT_COUNT
 };
 
+#define NUMBER_OF_FIELDS_TO_IDENTIFY_MASTER 1
+#define NUMBER_OF_MASTERS 1
+/*
+  We assume here a single master and uses slave's id to identify
+  entries in a system table, if there is any. This code needs to
+  be changed when we start handling multi-master replication.
+*/
+extern ulong key_info_idx[];
+extern uint key_info_size;
+
 #endif /* RPL_CONSTANTS_H */

=== modified file 'sql/rpl_info.cc'
--- a/sql/rpl_info.cc	2010-11-10 10:57:13 +0000
+++ b/sql/rpl_info.cc	2010-11-11 11:53:01 +0000
@@ -17,6 +17,17 @@
 #include <sql_priv.h>
 #include "rpl_info.h"
 
+/*
+  We assume here a single master and uses slave's id to identify
+  entries in a system table, if there is any. This code needs to
+  be changed when we start handling multi-master replication.
+
+  Most likely, server_id is zero when key_info_idx is defined.
+  For that reason, it is reset in Rpl_info_factory.
+*/
+ulong key_info_idx[]= { server_id };
+uint key_info_size= NUMBER_OF_FIELDS_TO_IDENTIFY_MASTER;
+
 Rpl_info::Rpl_info(const char* type)
   : Slave_reporting_capability(type),
   info_thd(0), inited(0), abort_slave(0),

=== modified file 'sql/rpl_info.h'
--- a/sql/rpl_info.h	2010-11-10 10:57:13 +0000
+++ b/sql/rpl_info.h	2010-11-11 11:53:01 +0000
@@ -20,6 +20,7 @@
 #include "sql_class.h"
 #include "rpl_info_handler.h"
 #include "rpl_reporting.h"
+#include "rpl_constants.h"
 
 class Rpl_info : public Slave_reporting_capability
 {
@@ -34,14 +35,14 @@ public:
   Rpl_info(const char *type);
   virtual ~Rpl_info();
 
-  int check_info()
+  int check_info(const ulong *uidx, const uint nidx)
   {
-    return (handler->check_info());
+    return (handler->check_info(uidx, nidx));
   }
 
-  int remove_info()
+  int remove_info(const ulong *uidx, const uint nidx)
   {
-    return (handler->remove_info());
+    return (handler->remove_info(uidx, nidx));
   }
 
   bool is_transactional()
@@ -56,7 +57,7 @@ public:
 
   bool copy_info(Rpl_info_handler *from, Rpl_info_handler *to)
   {
-    if (read_info(from) || write_info(to, TRUE))
+    if (read_info(from) || write_info(to))
       return(TRUE);
 
     return(FALSE);
@@ -74,7 +75,7 @@ protected:
 
 private:
   virtual bool read_info(Rpl_info_handler *from)= 0;
-  virtual bool write_info(Rpl_info_handler *to, bool force)= 0;
+  virtual bool write_info(Rpl_info_handler *to)= 0;
 
   Rpl_info& operator=(const Rpl_info& info);
   Rpl_info(const Rpl_info& info);

=== modified file 'sql/rpl_info_factory.cc'
--- a/sql/rpl_info_factory.cc	2010-11-10 10:57:13 +0000
+++ b/sql/rpl_info_factory.cc	2010-11-11 11:53:01 +0000
@@ -104,13 +104,19 @@ Master_info *Rpl_info_factory::create_mi
     goto err;
 
   if (!(mi_table= new Rpl_info_table(mi->get_number_info_mi_fields() + 1,
-                                     MI_FIELD_ID, MI_SCHEMA, MI_TABLE)))
+                                     MI_SCHEMA, MI_TABLE)))
     goto err;
 
   DBUG_ASSERT(mi_option == MI_REPOSITORY_FILE ||
               mi_option == MI_REPOSITORY_TABLE);
 
-  if (decide_repository(mi, &mi_table, &mi_file,
+  /*
+    In a multi-master envinroment, we need to make sure that both master
+    info and relay log info are prepared to handle events from all
+    masters. In such case, we need to execute the code below for each
+    master and correctly set the key_info_idx. /Alfranio
+  */
+  if (decide_repository(mi, key_info_idx, key_info_size, &mi_table, &mi_file,
                         mi_option == MI_REPOSITORY_TABLE, &msg))
     goto err;
 
@@ -181,13 +187,20 @@ Relay_log_info *Rpl_info_factory::create
     goto err;
 
   if (!(rli_table= new Rpl_info_table(rli->get_number_info_rli_fields() + 1,
-                                      RLI_FIELD_ID, RLI_SCHEMA, RLI_TABLE)))
+                                      RLI_SCHEMA, RLI_TABLE)))
     goto err;
 
   DBUG_ASSERT(rli_option == RLI_REPOSITORY_FILE ||
               rli_option == RLI_REPOSITORY_TABLE);
 
-  if (decide_repository(rli, &rli_table, &rli_file,
+  /*
+    In a multi-master envinroment, we need to make sure that both master
+    info and relay log info are prepared to handle events from all
+    masters. In such case, we need to execute the code below for each
+    master and correctly set the key_info_idx. /Alfranio
+  */
+  if (decide_repository(rli, key_info_idx, key_info_size,
+                        &rli_table, &rli_file,
                         rli_option == RLI_REPOSITORY_TABLE, &msg))
     goto err;
 
@@ -251,7 +264,9 @@ err:
   @retval FALSE No error
   @retval TRUE  Failure
 */
-bool Rpl_info_factory::decide_repository(Rpl_info *info, Rpl_info_table **table,
+bool Rpl_info_factory::decide_repository(Rpl_info *info,
+                                         ulong *uidx, uint nidx,
+                                         Rpl_info_table **table,
                                          Rpl_info_file **file, bool is_table,
                                          const char **msg)
 {
@@ -259,8 +274,8 @@ bool Rpl_info_factory::decide_repository
   DBUG_ENTER("Rpl_info_factory::decide_repository");
  
   bool error= TRUE;
-  bool is_t= !((*table)->check_info());
-  bool is_f= !((*file)->check_info());
+  bool is_t= !((*table)->check_info(uidx, nidx));
+  bool is_f= !((*file)->check_info(uidx, nidx));
 
   if (is_t && is_f)
   {
@@ -274,7 +289,7 @@ bool Rpl_info_factory::decide_repository
   {
     if (!is_t && is_f)
     {
-      if ((*table)->init_info() || (*file)->init_info())
+      if ((*table)->init_info(uidx, nidx) || (*file)->init_info(uidx, nidx))
       {
         *msg= "Error transfering information from a file to a table.";
         goto err;
@@ -282,8 +297,12 @@ bool Rpl_info_factory::decide_repository
       /*
         Transfer the information from the file to the table and delete the
         file, i.e. Update the table (T) and delete the file (F).
+    
+        This process is not atomic and if the server crashes before removing
+        the file, the user needs to manualy remove it.
       */
-      if (info->copy_info(*file, *table) || (*file)->remove_info())
+      if (info->copy_info(*file, *table) || (*table)->flush_info(uidx, nidx) ||
+         (*file)->remove_info(uidx, nidx))
       {
         *msg= "Error transfering information from a file to a table.";
         goto err;
@@ -298,7 +317,7 @@ bool Rpl_info_factory::decide_repository
   {
     if (is_t && !is_f)
     {
-      if ((*table)->init_info() || (*file)->init_info())
+      if ((*table)->init_info(uidx, nidx) || (*file)->init_info(uidx, nidx))
       {
         *msg= "Error transfering information from a file to a table.";
         goto err;
@@ -307,8 +326,14 @@ bool Rpl_info_factory::decide_repository
         Transfer the information from the table to the file and delete 
         entries in the table, i.e. Update the file (F) and delete the
         table (T).
+
+        This process is not atomic and if the server crashes before deleting
+        entry in the table, the user needs to manualy remove the file and
+        repeat the process. Note that we assuming here single master rep.
+        This process needs to be changed if there are multi-masters.
       */
-      if (info->copy_info(*table, *file) || (*table)->remove_info())
+      if (info->copy_info(*table, *file) || (*file)->flush_info(uidx, nidx) ||
+         (*table)->remove_info(uidx, nidx))
       {
         *msg= "Error transfering information from a table to a file.";
         goto err;
@@ -357,6 +382,7 @@ Slave_worker *Rpl_info_factory::create_w
   Rpl_info_file*  w_file= NULL;
   Rpl_info_table* w_table= NULL;
   Slave_worker *worker= NULL;
+  ulong idx[]= {server_id, worker_id};
   
   const char *msg= "Failed to allocate memory for the Slave worker info "
                    "structure";
@@ -381,13 +407,18 @@ Slave_worker *Rpl_info_factory::create_w
     goto err;
 
   if (!(w_table= new Rpl_info_table(worker->get_number_worker_fields() + 1,
-                                    WORKER_FIELD_ID, WORKER_SCHEMA, WORKER_TABLE)))
+                                    WORKER_SCHEMA, WORKER_TABLE)))
     goto err;
 
   DBUG_ASSERT(rli_option == RLI_REPOSITORY_FILE ||
               rli_option == RLI_REPOSITORY_TABLE);
 
-  if (decide_repository(worker, &w_table, &w_file,
+  /*
+   Check if this is conceptually right and what happens in case of
+   partial failures. Problems will not happen if we decide to use
+   only TABLES as repositories. /Alfranio
+  */
+  if (decide_repository(worker, idx, sizeof(idx), &w_table, &w_file,
                         rli_option == MI_REPOSITORY_TABLE, &msg))
     goto err;
 

=== modified file 'sql/rpl_info_factory.h'
--- a/sql/rpl_info_factory.h	2010-11-10 10:57:13 +0000
+++ b/sql/rpl_info_factory.h	2010-11-11 11:53:01 +0000
@@ -38,18 +38,12 @@ enum enum_rli_repository
 };
 extern ulong opt_rli_repository_id;
 
-#define MI_FIELD_ID 0
-
 #define MI_SCHEMA "mysql"
 #define MI_TABLE  "slave_master_info"
 
-#define RLI_FIELD_ID 0
-
 #define RLI_SCHEMA "mysql"
 #define RLI_TABLE  "slave_relay_log_info"
 
-#define WORKER_FIELD_ID 0
-
 #define WORKER_SCHEMA "mysql"
 #define WORKER_TABLE  "slave_worker_info"
 
@@ -63,7 +57,9 @@ class Rpl_info_factory
                                      uint worker_id);
   static Master_info *create_mi(uint rli_option);
   static Relay_log_info *create_rli(uint rli_option, bool is_slave_recovery);
-  static bool decide_repository(Rpl_info *info, Rpl_info_table **table,
+  static bool decide_repository(Rpl_info *info,
+                                ulong *uidx, uint nidx,
+                                Rpl_info_table **table,
                                 Rpl_info_file **file, bool is_table,
                                 const char **msg);
   static bool change_engine(Rpl_info_table *table, const char *engine,

=== modified file 'sql/rpl_info_file.cc'
--- a/sql/rpl_info_file.cc	2010-10-29 09:07:21 +0000
+++ b/sql/rpl_info_file.cc	2010-11-11 11:53:01 +0000
@@ -39,7 +39,8 @@ Rpl_info_file::Rpl_info_file(const int n
   DBUG_VOID_RETURN;
 }
 
-int Rpl_info_file::do_init_info()
+int Rpl_info_file::do_init_info(const ulong *uidx __attribute__((unused)),
+                                const uint nidx __attribute__((unused)))
 {
   int error= 0;
 
@@ -47,7 +48,7 @@ int Rpl_info_file::do_init_info()
   DBUG_ENTER("Rpl_info_file::do_init_info");
 
   /* does info file exist ? */
-  if (do_check_info())
+  if (do_check_info(uidx, nidx))
   {
     /*
       If someone removed the file from underneath our feet, just close
@@ -120,12 +121,15 @@ int Rpl_info_file::do_prepare_info_for_w
   return (reinit_io_cache(&info_file, WRITE_CACHE, 0L, 0, 1));
 }
 
-int Rpl_info_file::do_check_info()
+int Rpl_info_file::do_check_info(const ulong *uidx __attribute__((unused)),
+                                 const uint nidx __attribute__((unused)))
 {
   return (access(info_fname,F_OK));
 }
 
-int Rpl_info_file::do_flush_info(const bool force)
+int Rpl_info_file::do_flush_info(const ulong *uidx,
+                                 const uint nidx,
+                                 const bool force)
 {
   int error= 0;
 
@@ -145,7 +149,8 @@ int Rpl_info_file::do_flush_info(const b
   DBUG_RETURN(error);
 }
 
-void Rpl_info_file::do_end_info()
+void Rpl_info_file::do_end_info(const ulong *uidx __attribute__((unused)),
+                                const uint nidx __attribute__((unused)))
 {
   DBUG_ENTER("Rpl_info_file::do_end_info");
 
@@ -159,7 +164,8 @@ void Rpl_info_file::do_end_info()
   DBUG_VOID_RETURN;
 }
 
-int Rpl_info_file::do_remove_info()
+int Rpl_info_file::do_remove_info(const ulong *uidx __attribute__((unused)),
+                                  const uint nidx __attribute__((unused)))
 {
   MY_STAT stat_area;
   int error= 0;

=== modified file 'sql/rpl_info_file.h'
--- a/sql/rpl_info_file.h	2010-10-25 10:39:01 +0000
+++ b/sql/rpl_info_file.h	2010-11-11 11:53:01 +0000
@@ -41,11 +41,12 @@ private:
   /* IO_CACHE of the info file - set only during init or end */
   IO_CACHE info_file;
 
-  int do_init_info();
-  int do_check_info();
-  void do_end_info();
-  int do_flush_info(const bool force);
-  int do_remove_info();
+  int do_init_info(const ulong *uidx, const uint nidx);
+  int do_check_info(const ulong *uidx, const uint nidx);
+  void do_end_info(const ulong *uidx, const uint nidx);
+  int do_flush_info(const ulong *uidx, const uint nidx,
+                    const bool force);
+  int do_remove_info(const ulong *uidx, const uint nidx);
 
   int do_prepare_info_for_read();
   int do_prepare_info_for_write();

=== modified file 'sql/rpl_info_handler.h'
--- a/sql/rpl_info_handler.h	2010-10-25 10:39:01 +0000
+++ b/sql/rpl_info_handler.h	2010-11-11 11:53:01 +0000
@@ -30,26 +30,32 @@ public:
     After creating an object and assembling components, this method is
     used to initialize internal structures. Everything that does not
     depend on other components (e.g. mutexes) should be placed in the
-    object's constructor though. 
+    object's constructor though.
+
+    @param[in] uidx Array of fields that identifies an object
+    @param[in] nidx Number of fields in the array
 
     @retval FALSE success,
     @retval TRUE  otherwise error.
   */
-  int init_info()
+  int init_info(const ulong *uidx, const uint nidx)
   {
-    return do_init_info();
+    return do_init_info(uidx, nidx);
   }
 
   /**
     Checks if any necessary dependency is satisfied such as a
     file exists.
 
+    @param[in] uidx Array of fields that identifies an object
+    @param[in] nidx Number of fields in the array
+
     @retval FALSE success,
     @retval TRUE  otherwise error.
   */
-  int check_info()
+  int check_info(const ulong *uidx, const uint nidx)
   {
-    return do_check_info();
+    return do_check_info(uidx, nidx);
   }
 
   /**
@@ -65,36 +71,44 @@ public:
     system, it may happen that the changes will only end up in the
     operating system's cache and a crash may lead to inconsistencies.
 
+    @param[in] uidx  Array of fields that identifies an object
+    @param[in] nidx  Number of fields in the array
     @param[in] force Always sync the information.
 
     @retval FALSE No error
     @retval TRUE  Failure
   */
-  int flush_info(const bool force)
+  int flush_info(const ulong *uidx, const uint nidx, const bool force)
   {
-    return do_flush_info(force);
+    return do_flush_info(uidx, nidx, force);
   }
 
   /**
     Deletes any information in the repository.
 
+    @param[in] uidx Array of fields that identifies an object
+    @param[in] nidx Number of fields in the array
+
     @retval FALSE No error
     @retval TRUE  Failure
   */
-  int remove_info()
+  int remove_info(const ulong *uidx, const uint nidx)
   {
-    return do_remove_info();
+    return do_remove_info(uidx, nidx);
   }
 
   /**
     Closes access to the repository.
 
+    @param[in] uidx Array of fields that identifies an object
+    @param[in] nidx Number of fields in the array
+
     @retval FALSE No error
     @retval TRUE  Failure
   */
-  void end_info()
+  void end_info(const ulong *uidx, const uint nidx)
   {
-    do_end_info();
+    do_end_info(uidx, nidx);
   }
 
   /**
@@ -290,11 +304,12 @@ protected:
   uint sync_period;
 
 private:
-  virtual int do_init_info()= 0;
-  virtual int do_check_info()= 0;
-  virtual int do_flush_info(const bool force)= 0;
-  virtual int do_remove_info()= 0;
-  virtual void do_end_info()= 0;
+  virtual int do_init_info(const ulong *uidx, const uint nidx)= 0;
+  virtual int do_check_info(const ulong *uidx, const uint nidx)= 0;
+  virtual int do_flush_info(const ulong *uidx, const uint nidx,
+                            const bool force)= 0;
+  virtual int do_remove_info(const ulong *uidx, const uint nidx)= 0;
+  virtual void do_end_info(const ulong *uidx, const uint nidx)= 0;
   virtual int do_prepare_info_for_read()= 0;
   virtual int do_prepare_info_for_write()= 0;
 

=== modified file 'sql/rpl_info_table.cc'
--- a/sql/rpl_info_table.cc	2010-10-27 09:04:21 +0000
+++ b/sql/rpl_info_table.cc	2010-11-11 11:53:01 +0000
@@ -17,10 +17,10 @@
 #include "rpl_utility.h"
 #include "sql_parse.h"
 
-Rpl_info_table::Rpl_info_table(uint nparam, uint param_field_idx,
+Rpl_info_table::Rpl_info_table(uint nparam,
                                const char* param_schema,
                                const char *param_table)
-:Rpl_info_handler(nparam), field_idx(param_field_idx)
+:Rpl_info_handler(nparam)
 {
   str_schema.str= str_table.str= NULL;
   str_schema.length= str_table.length= 0;
@@ -65,7 +65,7 @@ Rpl_info_table::~Rpl_info_table()
     delete str_schema.str;
 }
 
-int Rpl_info_table::do_init_info()
+int Rpl_info_table::do_init_info(const ulong *uidx, const uint nidx)
 {
   int error= 1;
   enum enum_return_id res= FOUND_ID;
@@ -89,11 +89,10 @@ int Rpl_info_table::do_init_info()
     goto end;
 
   /*
-    Points the cursor at the row to be read where the master_id equals to
-    the server_id.
+    Points the cursor at the row to be read.
   */
-  if ((res= access->find_info_for_server_id(server_id, field_idx,
-                                            field_values, table)) == FOUND_ID)
+  if ((res= access->find_info(uidx, nidx, field_values,
+                              table)) == FOUND_ID)
   {
     /*
       Reads the information stored in the rpl_info table into a
@@ -116,7 +115,8 @@ end:
   DBUG_RETURN(error);
 }
 
-int Rpl_info_table::do_flush_info(const bool force)
+int Rpl_info_table::do_flush_info(const ulong *uidx, const uint nidx,
+                                  const bool force)
 {
   int error= 1;
   enum enum_return_id res= FOUND_ID;
@@ -145,12 +145,11 @@ int Rpl_info_table::do_flush_info(const 
     goto end;
 
   /*
-    Points the cursor at the row to be read where the master_id
-    equals to the server_id. If the row is not found an error is
-    reported.
+    Points the cursor at the row to be read. If the row is not found
+    an error is reported.
   */
-  if ((res= access->find_info_for_server_id(server_id, field_idx,
-                                            field_values, table)) == NOT_FOUND_ID)
+  if ((res= access->find_info(uidx, nidx, field_values,
+                              table)) == NOT_FOUND_ID)
   {
     /*
       Prepares the information to be stored before calling ha_write_row.
@@ -214,7 +213,7 @@ end:
   DBUG_RETURN(error);
 }
 
-int Rpl_info_table::do_remove_info()
+int Rpl_info_table::do_remove_info(const ulong *uidx, const uint nidx)
 {
   int error= 1;
   enum enum_return_id res= FOUND_ID;
@@ -238,12 +237,11 @@ int Rpl_info_table::do_remove_info()
     goto end;
 
   /*
-    Points the cursor at the row to be deleted where the the master_id
-    equals to the server_id. If the row is not found, the execution
-    proceeds normally.
+    Points the cursor at the row to be deleted. If the row is not
+    found, the execution proceeds normally.
   */
-  if ((res= access->find_info_for_server_id(server_id, field_idx,
-                                            field_values, table)) == FOUND_ID)
+  if ((res= access->find_info(uidx, nidx, field_values,
+                              table)) == FOUND_ID)
   {
     /*
       Deletes a row in the rpl_info table.
@@ -266,7 +264,7 @@ end:
   DBUG_RETURN(error);
 }
 
-int Rpl_info_table::do_check_info()
+int Rpl_info_table::do_check_info(const ulong *uidx, const uint nidx)
 {
   int error= 1;
   TABLE *table= NULL;
@@ -288,12 +286,11 @@ int Rpl_info_table::do_check_info()
     goto end;
 
   /*
-    Points the cursor at the row to be deleted where the the master_id
-    equals to the server_id. If the row is not found, an error is
-    reported.
+    Points the cursor at the row to be cheked. If the row is not
+    found, the execution proceeds normally.
   */
-  if (access->find_info_for_server_id(server_id, field_idx,
-                                      field_values, table) != FOUND_ID)
+  if (access->find_info(uidx, nidx, field_values,
+                        table) != FOUND_ID)
   {
     /* 
        We cannot simply call my_error here because it does not
@@ -314,7 +311,7 @@ end:
   DBUG_RETURN(error);
 }
 
-void Rpl_info_table::do_end_info()
+void Rpl_info_table::do_end_info(const ulong *uidx, const uint nidx)
 {
 }
 
@@ -477,7 +474,7 @@ bool Rpl_info_table::change_engine(const
   bool error= TRUE;
   ulong saved_mode;
 
-  DBUG_ENTER("Rpl_info_table::do_check_info");
+  DBUG_ENTER("Rpl_info_table::do_change_engine");
 
   THD *thd= access->create_thd();
 

=== modified file 'sql/rpl_info_table.h'
--- a/sql/rpl_info_table.h	2010-10-25 10:39:01 +0000
+++ b/sql/rpl_info_table.h	2010-11-11 11:53:01 +0000
@@ -22,7 +22,7 @@
 class Rpl_info_table : public Rpl_info_handler
 {
 public:
-  Rpl_info_table(uint nparam, uint param_field_id, const char* param_schema,
+  Rpl_info_table(uint nparam, const char* param_schema,
                  const char *param_table);
   virtual ~Rpl_info_table();
   /*
@@ -49,11 +49,6 @@ private:
   LEX_STRING str_table;
 
   /*
-    This property indentifies the id/position of the field that is
-    used as primary key.
-  */
-  uint field_idx;
-  /*
     This property represents a description of the repository.
     Speciffically, "schema"."table".
   */
@@ -65,11 +60,12 @@ private:
   */
   Rpl_info_table_access *access;
 
-  int do_init_info();
-  int do_check_info();
-  void do_end_info();
-  int do_flush_info(const bool force);
-  int do_remove_info();
+  int do_init_info(const ulong *uidx, const uint nidx);
+  int do_check_info(const ulong *uidx, const uint nidx);
+  void do_end_info(const ulong *uidx, const uint nidx);
+  int do_flush_info(const ulong *uidx, const uint nidx,
+                    const bool force);
+  int do_remove_info(const ulong *uidx, const uint nidx);
 
   int do_prepare_info_for_read();
   int do_prepare_info_for_write();

=== modified file 'sql/rpl_info_table_access.cc'
--- a/sql/rpl_info_table_access.cc	2010-10-27 11:20:32 +0000
+++ b/sql/rpl_info_table_access.cc	2010-11-11 11:53:01 +0000
@@ -160,8 +160,8 @@ bool Rpl_info_table_access::close_table(
 
   In case search succeeded, the table cursor points to the found row.
 
-  @param[in]      server_id    Server id
-  @param[in]      idx          Index field
+  @param[in]      uidx         Array of fields in pk
+  @param[in]      nidx         Number of fields in pk
   @param[in,out]  field_values The sequence of values
   @param[in,out]  table        Table
 
@@ -170,34 +170,53 @@ bool Rpl_info_table_access::close_table(
     @retval NOT_FOUND The row was not found.
     @retval ERROR     There was a failure.
 */
-enum enum_return_id Rpl_info_table_access::find_info_for_server_id(ulong server_id,
-                                                                   uint idx,
-                                                                   Rpl_info_values *field_values,
-                                                                   TABLE *table)
+enum enum_return_id Rpl_info_table_access::find_info(const ulong *uidx,
+                                                     const uint nidx,
+                                                     Rpl_info_values *field_values,
+                                                     TABLE *table)
 {
   uchar key[MAX_KEY_LENGTH];
-  DBUG_ENTER("Rpl_info_table_access::find_info_for_server_id");
+  DBUG_ENTER("Rpl_info_table_access::find_info");
 
-  field_values->value[idx].set_int(server_id, TRUE, &my_charset_bin);
-
-  if (field_values->value[idx].length() > table->field[idx]->field_length)
+  /* 
+     There is a primary key which is the first key among the
+     set of keys and it is enabled.
+  */
+  if (!(table->s->primary_key == 0 &&
+      table->s->keys_in_use.is_set(table->s->primary_key) &&
+      table->key_info->key_parts == nidx))
     DBUG_RETURN(ERROR_ID);
 
-  table->field[idx]->store(field_values->value[idx].c_ptr_safe(),
-                           field_values->value[idx].length(),
-                           &my_charset_bin);
-
-  if (!(table->field[idx]->flags & PRI_KEY_FLAG) &&
-      table->s->keys_in_use.is_set(0))
-    DBUG_RETURN(ERROR_ID);
+  uint offset_idx= table->s->primary_key;
 
+  for (uint idx= 0; idx < nidx; idx++)
+  {
+    /*
+      Fields that are part of a primary key are contiguous in
+      table's definition. If we want to release this we need
+      to iterate through the keyinfo.
+    */
+    if (!(table->field[idx + offset_idx]->flags & PRI_KEY_FLAG))
+      DBUG_RETURN(ERROR_ID);
+
+    /*
+      The size of the field must be great to store data.
+    */
+    if (field_values->value[idx + offset_idx].length() >
+        table->field[idx + offset_idx]->field_length)
+      DBUG_RETURN(ERROR_ID);
+
+    field_values->value[idx + offset_idx].set_int(uidx[idx], TRUE, &my_charset_bin);
+
+    table->field[idx + offset_idx]->store(field_values->value[idx + offset_idx].c_ptr_safe(),
+                             field_values->value[idx + offset_idx].length(),
+                             &my_charset_bin);
+  }
   key_copy(key, table->record[0], table->key_info, table->key_info->key_length);
 
   if (table->file->ha_index_read_idx_map(table->record[0], 0, key, HA_WHOLE_KEY,
                                          HA_READ_KEY_EXACT))
-  {
     DBUG_RETURN(NOT_FOUND_ID);
-  }
 
   DBUG_RETURN(FOUND_ID);
 }

=== modified file 'sql/rpl_info_table_access.h'
--- a/sql/rpl_info_table_access.h	2010-10-25 10:39:01 +0000
+++ b/sql/rpl_info_table_access.h	2010-11-11 11:53:01 +0000
@@ -36,8 +36,8 @@ public:
                   TABLE** table, Open_tables_backup* backup);
   bool close_table(THD* thd, TABLE* table, Open_tables_backup* backup,
                    bool error);
-  enum enum_return_id find_info_for_server_id(ulong server_id, uint idx, Rpl_info_values *,
-                                              TABLE *table);
+  enum enum_return_id find_info(const ulong *uidx, const uint nidx,
+                                Rpl_info_values *, TABLE *table);
   bool load_info_values(uint max_num_field, Field **fields,
                         Rpl_info_values *field_values);
   bool store_info_values(uint max_num_field, Field **fields,

=== modified file 'sql/rpl_mi.cc'
--- a/sql/rpl_mi.cc	2010-11-10 10:57:13 +0000
+++ b/sql/rpl_mi.cc	2010-11-11 11:53:01 +0000
@@ -163,14 +163,14 @@ void Master_info::init_master_log_pos()
   DBUG_VOID_RETURN;
 }
 
-void Master_info::end_info()
+void Master_info::end_info(ulong *uidx, uint nidx)
 {
   DBUG_ENTER("Master_info::end_info");
 
   if (!inited)
     DBUG_VOID_RETURN;
 
-  handler->end_info();
+  handler->end_info(uidx, nidx);
 
   inited = 0;
 
@@ -206,7 +206,7 @@ void Master_info::end_info()
   @todo Change the log file information to a binary format to avoid
   calling longlong2str.
 */
-int Master_info::flush_info(bool force)
+int Master_info::flush_info(ulong *uidx, uint nidx, bool force)
 {
   DBUG_ENTER("Master_info::flush_info");
   DBUG_PRINT("enter",("master_pos: %lu", (ulong) master_log_pos));
@@ -219,7 +219,10 @@ int Master_info::flush_info(bool force)
   */
   handler->set_sync_period(sync_masterinfo_period);
 
-  if (write_info(handler, force))
+  if (write_info(handler))
+    goto err;
+
+  if (handler->flush_info(uidx, nidx, force))
     goto err;
 
   DBUG_RETURN(0);
@@ -234,7 +237,7 @@ void Master_info::set_relay_log_info(Rel
   rli= info;
 }
 
-int Master_info::init_info()
+int Master_info::init_info(ulong *uidx, uint nidx)
 {
   DBUG_ENTER("Master_info::init_info");
 
@@ -246,9 +249,9 @@ int Master_info::init_info()
     from the repository, in order to initialize the Master_info.
   */
   mysql= 0; file_id= 1;
-  int necessary_to_configure= check_info();
+  int necessary_to_configure= check_info(uidx, nidx);
   
-  if (handler->init_info())
+  if (handler->init_info(uidx, nidx))
     goto err;
 
   if (necessary_to_configure)
@@ -260,7 +263,7 @@ int Master_info::init_info()
     goto err;
 
 end:
-  if (flush_info(TRUE))
+  if (flush_info(uidx, nidx, TRUE))
     goto err;
 
   inited= 1;
@@ -419,7 +422,7 @@ bool Master_info::read_info(Rpl_info_han
   DBUG_RETURN(FALSE);
 }
 
-bool Master_info::write_info(Rpl_info_handler *to, bool force)
+bool Master_info::write_info(Rpl_info_handler *to)
 {
   DBUG_ENTER("Master_info::write_info");
 
@@ -459,9 +462,6 @@ bool Master_info::write_info(Rpl_info_ha
       to->set_info(retry_count))
     DBUG_RETURN(TRUE);
 
-  if (to->flush_info(force))
-    DBUG_RETURN(TRUE);
-
   DBUG_RETURN(FALSE);
 }
 #endif /* HAVE_REPLICATION */

=== modified file 'sql/rpl_mi.h'
--- a/sql/rpl_mi.h	2010-11-10 10:57:13 +0000
+++ b/sql/rpl_mi.h	2010-11-11 11:53:01 +0000
@@ -101,9 +101,9 @@ class Master_info : public Rpl_info_coor
   ulong retry_count;
   char master_uuid[UUID_LENGTH+1];
 
-  int init_info();
-  void end_info();
-  int flush_info(bool force= FALSE);
+  int init_info(ulong *uidx, uint nidx);
+  void end_info(ulong *uidx, uint nidx);
+  int flush_info(ulong *uidx, uint nidx, bool force= FALSE);
   void set_relay_log_info(Relay_log_info *info);
 
   bool shall_ignore_server_id(ulong s_id);
@@ -132,7 +132,7 @@ public:
 
 private:
   bool read_info(Rpl_info_handler *from);
-  bool write_info(Rpl_info_handler *to, bool force);
+  bool write_info(Rpl_info_handler *to);
 
   Master_info& operator=(const Master_info& info);
   Master_info(const Master_info& info);

=== modified file 'sql/rpl_rli.cc'
--- a/sql/rpl_rli.cc	2010-11-10 10:57:13 +0000
+++ b/sql/rpl_rli.cc	2010-11-11 11:53:01 +0000
@@ -1002,7 +1002,8 @@ void Relay_log_info::stmt_done(my_off_t 
   else
   {
     inc_group_relay_log_pos(event_master_log_pos);
-    flush_info(is_transactional() ? TRUE : FALSE);
+    /* Alfranio needs to update the coordinator and workers. */
+    flush_info(key_info_idx, key_info_size, is_transactional() ? TRUE : FALSE);
   }
 }
 
@@ -1126,7 +1127,7 @@ bool mysql_show_relaylog_events(THD* thd
 
 #endif
 
-int Relay_log_info::init_info()
+int Relay_log_info::init_info(ulong *uidx, uint nidx)
 {
   int error= 0;
   const char *msg= NULL;
@@ -1272,8 +1273,8 @@ a file name for --relay-log-index option
     will be values to be read. Please, do not move this call after
     the handler->init_info().
   */
-  int necessary_to_configure= check_info();
-  if ((error= handler->init_info()))
+  int necessary_to_configure= check_info(uidx, nidx);
+  if ((error= handler->init_info(uidx, nidx)))
   {
     msg= "Error reading relay log configuration";
     error= 1;
@@ -1332,7 +1333,7 @@ a file name for --relay-log-index option
 #endif
   }
 
-  if ((error= flush_info(TRUE)))
+  if ((error= flush_info(uidx, nidx, TRUE)))
   {
     msg= "Error reading relay log configuration";
     error= 1;
@@ -1356,14 +1357,14 @@ err:
   DBUG_RETURN(error);
 }
 
-void Relay_log_info::end_info()
+void Relay_log_info::end_info(ulong *uidx, uint nidx)
 {
   DBUG_ENTER("Relay_log_info::end_info");
 
   if (!inited)
     DBUG_VOID_RETURN;
 
-  handler->end_info();
+  handler->end_info(uidx, nidx);
 
   if (cur_log_fd >= 0)
   {
@@ -1456,7 +1457,7 @@ void Relay_log_info::set_master_info(Mas
 
   @return 0 on success, 1 on error.
 */
-int Relay_log_info::flush_info(bool force)
+int Relay_log_info::flush_info(ulong *uidx, uint nidx, const bool force)
 {
   DBUG_ENTER("Relay_log_info::flush_info");
 
@@ -1468,7 +1469,10 @@ int Relay_log_info::flush_info(bool forc
   */
   handler->set_sync_period(sync_relayloginfo_period);
 
-  if (write_info(handler, force))
+  if (write_info(handler))
+    goto err;
+
+  if (handler->flush_info(uidx, nidx, force))
     goto err;
 
   DBUG_RETURN(0);
@@ -1568,7 +1572,7 @@ bool Relay_log_info::read_info(Rpl_info_
   DBUG_RETURN(FALSE);
 }
 
-bool Relay_log_info::write_info(Rpl_info_handler *to, bool force)
+bool Relay_log_info::write_info(Rpl_info_handler *to)
 {
   DBUG_ENTER("Relay_log_info::write_info");
 
@@ -1587,8 +1591,5 @@ bool Relay_log_info::write_info(Rpl_info
       to->set_info((int) sql_delay))
     DBUG_RETURN(TRUE);
 
-  if (to->flush_info(force))
-    DBUG_RETURN(TRUE);
-
   DBUG_RETURN(FALSE);
 }

=== modified file 'sql/rpl_rli.h'
--- a/sql/rpl_rli.h	2010-11-10 10:57:13 +0000
+++ b/sql/rpl_rli.h	2010-11-11 11:53:01 +0000
@@ -500,9 +500,9 @@ public:
 
   int count_relay_log_space();
 
-  int init_info();
-  void end_info();
-  int flush_info(bool force= FALSE);
+  int init_info(ulong *uidx, uint nidx);
+  void end_info(ulong *uidx, uint nidx);
+  int flush_info(ulong *uidx, uint nidx, bool force= FALSE);
   int flush_current_log();
   void set_master_info(Master_info *info);
 
@@ -643,7 +643,7 @@ private:
   static const int LINES_IN_RELAY_LOG_INFO_WITH_DELAY= 5;
 
   bool read_info(Rpl_info_handler *from);
-  bool write_info(Rpl_info_handler *to, bool force);
+  bool write_info(Rpl_info_handler *to);
 
   Relay_log_info& operator=(const Relay_log_info& info);
   Relay_log_info(const Relay_log_info& info);

=== modified file 'sql/rpl_rli_pdb.cc'
--- a/sql/rpl_rli_pdb.cc	2010-11-10 10:57:13 +0000
+++ b/sql/rpl_rli_pdb.cc	2010-11-11 11:53:01 +0000
@@ -28,7 +28,7 @@ Slave_worker::~Slave_worker() 
 
 }
 
-int Slave_worker::init_info()
+int Slave_worker::init_info(ulong *uidx, uint nidx)
 {
   DBUG_ENTER("Slave_worker::init_info");
 
@@ -39,15 +39,15 @@ int Slave_worker::init_info()
     The init_info() is used to either create or read information
     from the repository, in order to initialize the Slave_worker.
   */
-  int necessary_to_configure= check_info();
+  int necessary_to_configure= check_info(uidx, nidx);
 
-  if (handler->init_info())
+  if (handler->init_info(uidx, nidx))
     goto err;
 
   if (!necessary_to_configure && read_info(handler))
     goto err;
 
-  if (flush_info(TRUE))
+  if (flush_info(uidx, nidx, TRUE))
     goto err;
 
   inited= 1;
@@ -58,21 +58,21 @@ err:
   DBUG_RETURN(1);
 }
 
-void Slave_worker::end_info()
+void Slave_worker::end_info(ulong *uidx, uint nidx)
 {
   DBUG_ENTER("Slave_worker::end_info");
 
   if (!inited)
     DBUG_VOID_RETURN;
 
-  handler->end_info();
+  handler->end_info(uidx, nidx);
 
   inited = 0;
 
   DBUG_VOID_RETURN;
 }
 
-int Slave_worker::flush_info(bool force)
+int Slave_worker::flush_info(ulong *uidx, uint nidx, const bool force)
 {
   DBUG_ENTER("Slave_worker::flush_info");
 
@@ -84,7 +84,10 @@ int Slave_worker::flush_info(bool force)
   */
   handler->set_sync_period(sync_relayloginfo_period);
 
-  if (write_info(handler, force))
+  if (write_info(handler))
+    goto err;
+
+  if (handler->flush_info(uidx, nidx, force))
     goto err;
 
   DBUG_RETURN(0);
@@ -98,15 +101,14 @@ bool Slave_worker::read_info(Rpl_info_ha
 {
   DBUG_ENTER("Slave_worker::read_info");
 
-  ulong nline= 0;
   ulong temp_group_relay_log_pos= 0;
   ulong temp_group_master_log_pos= 0;
 
   if (from->prepare_info_for_read())
     DBUG_RETURN(TRUE);
 
-  if (from->get_info(partition,
-                     sizeof(partition), "") ||
+  if (from->get_info(partitions,
+                     sizeof(partitions), "") ||
       from->get_info(group_relay_log_name,
                      sizeof(group_relay_log_name), "") ||
       from->get_info((ulong *) &temp_group_relay_log_pos,
@@ -123,7 +125,7 @@ bool Slave_worker::read_info(Rpl_info_ha
   DBUG_RETURN(FALSE);
 }
 
-bool Slave_worker::write_info(Rpl_info_handler *to, bool force)
+bool Slave_worker::write_info(Rpl_info_handler *to)
 {
   DBUG_ENTER("Master_info::write_info");
 
@@ -142,9 +144,6 @@ bool Slave_worker::write_info(Rpl_info_h
       to->set_info((ulong)group_master_log_pos))
     DBUG_RETURN(TRUE);
 
-  if (to->flush_info(force))
-    DBUG_RETURN(TRUE);
-
   DBUG_RETURN(FALSE);
 }
 

=== modified file 'sql/rpl_rli_pdb.h'
--- a/sql/rpl_rli_pdb.h	2010-11-10 10:57:13 +0000
+++ b/sql/rpl_rli_pdb.h	2010-11-11 11:53:01 +0000
@@ -61,21 +61,24 @@ public:
   volatile int curr_jobs; // the current assignments
   ulong usage_partition; // number of different partitions handled by this worker
 
-  char *partition;
+  /*
+    We need to make this a dynamic field. /Alfranio
+  */
+  char partitions[FN_REFLEN];
   char group_relay_log_name[FN_REFLEN];
   ulonglong group_relay_log_pos;
   char group_master_log_name[FN_REFLEN];
   ulonglong group_master_log_pos;
 
-  int init_info();
-  void end_info();
-  int flush_info(bool force= FALSE);
+  int init_info(ulong *uidx, uint nidx);
+  void end_info(ulong *uidx, uint nidx);
+  int flush_info(ulong *uidx, uint nidx, bool force= FALSE);
 
   size_t get_number_worker_fields();
 
 private:
   bool read_info(Rpl_info_handler *from);
-  bool write_info(Rpl_info_handler *to, bool force);
+  bool write_info(Rpl_info_handler *to);
 
   Slave_worker& operator=(const Slave_worker& info);
   Slave_worker(const Slave_worker& info);

=== modified file 'sql/rpl_slave.cc'
--- a/sql/rpl_slave.cc	2010-11-10 10:57:13 +0000
+++ b/sql/rpl_slave.cc	2010-11-11 11:53:01 +0000
@@ -403,19 +403,25 @@ int init_info(Master_info* mi, bool igno
     thread is being started and the relay log info if either the
     SLAVE_SQL thread is being started or was not initialized as it is
     required by the SLAVE_IO thread.
+
+    In a multi-master envinroment, we need to make sure that both master
+    info and relay log info are prepared to handle events from all
+    masters. In such case, we need to execute the code below for each
+    master and correctly set the key_info_idx.
   */
-  necessary_to_configure= mi->check_info();
+  necessary_to_configure= mi->check_info(key_info_idx, key_info_size);
   if (!(ignore_if_no_info && necessary_to_configure))
   {
-    if ((thread_mask & SLAVE_IO) != 0 && mi->init_info())
+    if ((thread_mask & SLAVE_IO) != 0 &&
+        mi->init_info(key_info_idx, key_info_size))
       error= 1;
   }
 
-  necessary_to_configure= mi->rli->check_info();
+  necessary_to_configure= mi->rli->check_info(key_info_idx, key_info_size);
   if (!(ignore_if_no_info && necessary_to_configure))
   {
      if (((thread_mask & SLAVE_SQL) != 0 || !(mi->rli->inited))
-         && mi->rli->init_info())
+         && mi->rli->init_info(key_info_idx, key_info_size))
     error= 1;
   }
 
@@ -431,11 +437,16 @@ void end_info(Master_info* mi)
   DBUG_ASSERT(mi != NULL && mi->rli != NULL);
 
   /*
-    The previous implementation was not acquiring locks.
-    We do the same here. However, this is quite strange.
+    The previous implementation was not acquiring locks.  We do the same here.
+    However, this is quite strange.
+
+    In a multi-master envinroment, we need to make sure that both master
+    info and relay log info are prepared to handle events from all
+    masters. In such case, we need to execute the code below for each
+    master and correctly set the key_info_idx. /Alfranio
   */
-  mi->end_info();
-  mi->rli->end_info();
+  mi->end_info(key_info_idx, key_info_size);
+  mi->rli->end_info(key_info_idx, key_info_size);
 
   DBUG_VOID_RETURN;
 }
@@ -459,10 +470,17 @@ int remove_info(Master_info* mi)
   mi->rli->clear_until_condition();
   mi->rli->clear_sql_delay();
 
-  mi->end_info();
-  mi->rli->end_info();
+  /*
+    In a multi-master envinroment, we need to make sure that both master
+    info and relay log info are prepared to handle events from all
+    masters. In such case, we need to execute the code below for each
+    master and correctly set the key_info_idx. /Alfranio
+  */
+  mi->end_info(key_info_idx, key_info_size);
+  mi->rli->end_info(key_info_idx, key_info_size);
 
-  if (mi->remove_info() || mi->rli->remove_info())
+  if (mi->remove_info(key_info_idx, key_info_size) ||
+      mi->rli->remove_info(key_info_idx, key_info_size))
     error= 1;
 
   DBUG_RETURN(error);
@@ -496,7 +514,14 @@ int flush_master_info(Master_info* mi, b
 
   mysql_mutex_lock(log_lock);
 
-  int err=  (mi->rli->flush_current_log() ||  mi->flush_info(force));
+  /*
+    In a multi-master envinroment, we need to make sure that both master
+    info and relay log info are prepared to handle events from all
+    masters. In such case, we need to execute the code below for each
+    master and correctly set the key_info_idx. /Alfranio
+  */
+  int err=  (mi->rli->flush_current_log() ||
+             mi->flush_info(key_info_idx, key_info_size, force));
 
   mysql_mutex_unlock(log_lock);
 
@@ -646,8 +671,13 @@ int terminate_slave_threads(Master_info*
 
     /*
       Flushes the master info regardles of the sync_master_info option.
+
+      In a multi-master envinroment, we need to make sure that both master
+      info and relay log info are prepared to handle events from all
+      masters. In such case, we need to execute the code below for each
+      master and correctly set the key_info_idx. /Alfranio
     */
-    if (mi->flush_info(TRUE))
+    if (mi->flush_info(key_info_idx, key_info_size, TRUE))
       DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
 
     /*
@@ -677,8 +707,13 @@ int terminate_slave_threads(Master_info*
 
     /*
       Flushes the relay log info regardles of the sync_relay_log_info option.
+
+      In a multi-master envinroment, we need to make sure that both master
+      info and relay log info are prepared to handle events from all
+      masters. In such case, we need to execute the code below for each
+      master and correctly set the key_info_idx. /Alfranio
     */
-    if (mi->rli->flush_info(TRUE))
+    if (mi->rli->flush_info(key_info_idx, key_info_size, TRUE))
       DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS);
 
     mysql_mutex_unlock(log_lock);
@@ -4880,6 +4915,7 @@ static Log_event* next_event(Relay_log_i
   mysql_mutex_t *log_lock = rli->relay_log.get_log_lock();
   const char* errmsg=0;
   THD* thd = rli->info_thd;
+
   DBUG_ENTER("next_event");
 
   DBUG_ASSERT(thd != 0);
@@ -5158,7 +5194,11 @@ static Log_event* next_event(Relay_log_i
         }
         rli->set_event_relay_log_pos(BIN_LOG_HEADER_SIZE);
         rli->set_event_relay_log_name(rli->linfo.log_file_name);
-        rli->flush_info();
+        /*
+          We may update the worker here but this is not extremlly
+          necessary. /Alfranio
+        */
+        rli->flush_info(key_info_idx, key_info_size);
       }
 
       /*
@@ -5649,7 +5689,11 @@ int reset_slave(THD *thd, Master_info* m
     goto err;
   }
 
-  /* Clear master's log coordinates */
+  /* 
+    Clear master's log coordinates 
+
+    Andrei needs to guarantee that this done in sequential mode.
+  */
   mi->init_master_log_pos();
 
   if (remove_info(mi))
@@ -5961,8 +6005,15 @@ bool change_master(THD* thd, Master_info
     before START SLAVE, then old will remain in relay-log.info, and will be the
     in-memory value at restart (thus causing errors, as the old relay log does
     not exist anymore).
+
+    In a multi-master envinroment, we need to make sure that both master
+    info and relay log info are prepared to handle events from all
+    masters. In such case, we need to execute the code below for each
+    master and correctly set the key_info_idx. /Alfranio
+
+    Andrei needs to guarantee that this done in sequential mode.
   */
-  ret= mi->rli->flush_info(TRUE);
+  ret= mi->rli->flush_info(key_info_idx, key_info_size, TRUE);
   mysql_cond_broadcast(&mi->data_cond);
   mysql_mutex_unlock(&mi->rli->data_lock);
 


Attachment: [text/bzr-bundle] bzr/alfranio.correia@oracle.com-20101111115301-f11cw4m2gzcs5419.bundle
Thread
bzr commit into mysql-next-mr.crash-safe branch (alfranio.correia:3208)WL#5599Alfranio Correia11 Nov