From: Andrei Elkin Date: December 9 2010 5:45pm Subject: bzr commit into mysql-next-mr-wl5569 branch (andrei.elkin:3237) WL#5569 List-Archive: http://lists.mysql.com/commits/126472 Message-Id: <201012091745.oB9Hj8tg014358@mysql1000.dsl.inet.fi> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0843880549==" --===============0843880549== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/andrei/MySQL/BZR/2a-23May/WL/mysql-next-mr-wl5569/ based on revid:alfranio.correia@stripped 3237 Andrei Elkin 2010-12-09 wl#5569 MTS Integration with wl#5599 recovery for MTS and fixing two asserts. One is due to missed cleanup of errored-out rows-events; the other is a work-around on w->curr_group_exec_parts->dynamic_ids is initialized to have one partition on the Worker startup, but it should not. @ sql/log_event.cc Propagating CP related info from C to W. @ sql/rpl_rli.cc Added a part of CP info from C to W propagation. @ sql/rpl_rli.h New members to RLI due to CP info from C to W propagation. @ sql/rpl_rli_pdb.cc Worker stores the new CP to mention it in flush_info() along with (todo) a bitmap of the executed groups within the checkpoint interval. @ sql/rpl_rli_pdb.h New members to a transport and the Worker class due to CP info. @ sql/rpl_slave.cc missed cleanup of errored-out rows-events; work-around on w->curr_group_exec_parts->dynamic_ids is initialized to have one partition on the Worker startup, but it should not. modified: sql/log_event.cc 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/log_event.cc' --- a/sql/log_event.cc 2010-12-08 00:33:48 +0000 +++ b/sql/log_event.cc 2010-12-09 17:45:02 +0000 @@ -2418,9 +2418,13 @@ Slave_worker *Log_event::get_slave_worke { g.master_log_pos= log_pos; g.group_master_log_pos= g.group_relay_log_pos= 0; + g.group_master_log_name= NULL; // todo: remove g.group_relay_log_name= NULL; g.worker_id= (ulong) -1; g.total_seqno= const_cast(rli)->mts_total_groups++; + g.checkpoint_log_name= NULL; + g.checkpoint_log_pos= 0; + g.checkpoint_seqno= (uint) -1; // the last occupied GAQ's array index rli->gaq->assigned_group_index= rli->gaq->en_queue((void *) &g); @@ -2490,6 +2494,10 @@ Slave_worker *Log_event::get_slave_worke { uint i; mts_group_cnt= rli->gaq->assigned_group_index; + Slave_job_group *ptr_g= + (Slave_job_group *) + dynamic_array_ptr(&rli->gaq->Q, rli->gaq->assigned_group_index); + // TODO: throw an error when relay-log reading starts from inside of a group!! @@ -2501,11 +2509,6 @@ Slave_worker *Log_event::get_slave_worke Now group terminating event initiates the new name delivery through the current group relaylog slot in GAQ. */ - - Slave_job_group *ptr_g= - (Slave_job_group *) - dynamic_array_ptr(&rli->gaq->Q, rli->gaq->assigned_group_index); - DBUG_ASSERT(ptr_g->group_relay_log_name == NULL); ptr_g->group_relay_log_name= (char *) @@ -2519,6 +2522,20 @@ Slave_worker *Log_event::get_slave_worke worker->relay_log_change_notified= TRUE; } + if (!worker->checkpoint_notified) + { + // Worker dealloc + ptr_g->checkpoint_log_name= (char *) + my_malloc(strlen(const_cast(rli)-> + get_group_master_log_name()) + 1, MYF(MY_WME)); + strcpy(ptr_g->checkpoint_log_name, + const_cast(rli)->get_group_master_log_name()); + ptr_g->checkpoint_log_pos= const_cast(rli)->get_group_master_log_pos(); + worker->checkpoint_notified= TRUE; + } + ptr_g->checkpoint_seqno= rli->checkpoint_seqno; + const_cast(rli)->checkpoint_seqno++; + DBUG_ASSERT(worker == rli->last_assigned_worker); if (!worker) @@ -6641,7 +6658,11 @@ int Xid_log_event::do_apply_event(Relay_ } else if (is_trans_repo && is_parallel) { - if ((error= w->commit_positions(this))) + ulong gaq_idx= mts_group_cnt; + Slave_job_group *ptr_g= + (Slave_job_group *) dynamic_array_ptr(&w->c_rli->gaq->Q, gaq_idx); + + if ((error= w->commit_positions(this, ptr_g))) goto err; } === modified file 'sql/rpl_rli.cc' --- a/sql/rpl_rli.cc 2010-12-08 01:30:32 +0000 +++ b/sql/rpl_rli.cc 2010-12-09 17:45:02 +0000 @@ -82,9 +82,9 @@ Relay_log_info::Relay_log_info(bool is_s We need to decide if you are going to use an option and store it in a storage. - 100 msec. + 500 msec. */ - lwm_period= 0.100; + lwm_period= 0.500; set_timespec_nsec(last_clock, 0); bzero((char*) &cache_buf, sizeof(cache_buf)); @@ -241,6 +241,27 @@ void Relay_log_info::reset_notified_rela } /** + Method is called in mts_checkpoint_routine() + to marks each Worker as requiring to adapt to a new checkpoint interval + whose coordinates is passed to it through GAQ index. + + Worker notices the new checkpoint value at the group commit + to reset the current bitmap and set ON a bit number put by C into GAQ index + as the first group committed after the new checkpoint. +*/ +void Relay_log_info::reset_notified_checkpoint() +{ + if (!is_parallel_exec()) + return; + for (uint i= 0; i < workers.elements; i++) + { + Slave_worker *w= *(Slave_worker **) dynamic_array_ptr(&workers, i); + w->checkpoint_notified= FALSE; + } + checkpoint_seqno= 0; +} + +/** The method can be run both by C having the Main (coord) rli context and by W having both the main and the Local (worker) rli context. Decision matrix: @@ -1113,7 +1134,16 @@ void Relay_log_info::stmt_done(my_off_t /* Alfranio needs to update the coordinator and workers. */ if ((w= get_current_worker()) == NULL) + { flush_info(is_transactional() ? TRUE : FALSE); + + /* + The central recovery commit run in sequential mode forces + notification on the defacto new checkpoint. + */ + if (is_parallel_exec()) + reset_notified_checkpoint(); + } } } === modified file 'sql/rpl_rli.h' --- a/sql/rpl_rli.h 2010-12-08 00:33:48 +0000 +++ b/sql/rpl_rli.h 2010-12-09 17:45:02 +0000 @@ -471,6 +471,7 @@ public: a new partition. Is updated at checkpoint commit to the main RLI. */ DYNAMIC_ARRAY least_occupied_workers; + uint checkpoint_seqno; // counter of groups executed after the most recent CP /* most of allocation in the coordinator rli is there */ void init_workers(ulong); @@ -490,9 +491,21 @@ public: return ret; } + /** + While a group is executed by a Worker the relay log can change. + Coordinator notifies Workers about this event. Worker is supposed + to commit to the recovery table with the new info. + */ void reset_notified_relay_log_change(); /** + While a group is executed by a Worker the relay log can change. + Coordinator notifies Workers about this event. Coordinator and Workers + maintain a bitmap of executed group that is reset with a new checkpoint. + */ + void reset_notified_checkpoint(); + + /** Helper function to do after statement completion. This function is called from an event to complete the group by === modified file 'sql/rpl_rli_pdb.cc' --- a/sql/rpl_rli_pdb.cc 2010-12-08 13:59:07 +0000 +++ b/sql/rpl_rli_pdb.cc 2010-12-09 17:45:02 +0000 @@ -20,10 +20,11 @@ const char *info_slave_worker_fields []= Slave_worker::Slave_worker(const char* type, const char* pfs) : Rpl_info_worker(type, pfs), group_relay_log_pos(0), - group_master_log_pos(0) + group_master_log_pos(0), checkpoint_log_pos(0) { group_relay_log_name[0]= 0; group_master_log_name[0]= 0; + checkpoint_log_name[0]= 0; curr_group_exec_parts= new Database_ids(NAME_LEN); } @@ -157,12 +158,24 @@ size_t Slave_worker::get_number_worker_f return sizeof(info_slave_worker_fields)/sizeof(info_slave_worker_fields[0]); } -bool Slave_worker::commit_positions(Log_event *ev) +bool Slave_worker::commit_positions(Log_event *ev, Slave_job_group* ptr_g) { DBUG_ENTER("Slave_worker::checkpoint_positions"); bool error= FALSE; + if (ptr_g->checkpoint_log_name != NULL) + { + strmake(checkpoint_log_name, ptr_g->checkpoint_log_name, + sizeof(checkpoint_log_name) - 1); + checkpoint_log_pos= ptr_g->checkpoint_log_pos; + + my_free(ptr_g->checkpoint_log_name); + ptr_g->checkpoint_log_name= NULL; + } + + // TODO: update the group bitmap ptr_g->checkpoint_seqno 'th bit + group_relay_log_pos= ev->future_event_relay_log_pos; group_master_log_pos= ev->log_pos; strmake(group_master_log_name, c_rli->get_group_master_log_name(), @@ -502,16 +515,10 @@ void Slave_worker::slave_worker_ends_gro strcpy(group_relay_log_name, ptr_g->group_relay_log_name); } - // GAQ is updated with the checkpoint info - - // delete ptr_g->group_relay_log_name; // C allocated - // ptr_g->group_relay_log_name= NULL; // mark freed - - - // TODO: as it's same as ev->update_pos(w_rli) remove the latter. - if (!(ev->get_type_code() == XID_EVENT && is_transactional())) - commit_positions(ev); + { + commit_positions(ev, ptr_g); + } ptr_g->group_master_log_pos= group_master_log_pos; ptr_g->group_relay_log_pos= group_relay_log_pos; @@ -536,7 +543,7 @@ void Slave_worker::slave_worker_ends_gro my_hash_search_using_hash_value(&mapping_db_to_worker, hash_value, (uchar*) key + 1, key[0]); - DBUG_ASSERT(entry && entry->usage != 0); + DBUG_ASSERT(entry && entry->usage != 0); // was used to break DBUG_ASSERT(strlen(key + 1) == (uchar) key[0]); entry->usage--; === modified file 'sql/rpl_rli_pdb.h' --- a/sql/rpl_rli_pdb.h 2010-12-08 01:30:32 +0000 +++ b/sql/rpl_rli_pdb.h 2010-12-09 17:45:02 +0000 @@ -95,7 +95,7 @@ public: typedef struct st_slave_job_group { - char *group_master_log_name; // This is used upon recovery. + char *group_master_log_name; // (actually redundant) Dynamic_ids *db_ids; // This is used upon recovery. my_off_t master_log_pos; // B-event log_pos @@ -114,6 +114,11 @@ typedef struct st_slave_job_group char *group_relay_log_name; // The value is last seen relay-log ulong worker_id; ulonglong total_seqno; + + /* checkpoint coord are reset by CP and rotate:s */ + uint checkpoint_seqno; + my_off_t checkpoint_log_pos; // T-event lop_pos filled by W for CheckPoint + char* checkpoint_log_name; } Slave_job_group; #define copy_job(from, to) \ @@ -274,6 +279,7 @@ public: volatile int curr_jobs; // the current assignments ulong usage_partition; // number of different partitions handled by this worker volatile bool relay_log_change_notified; // Coord sets and resets, W can read + volatile bool checkpoint_notified; // Coord sets and resets, W can read bool wq_overrun_set; // W monitors its queue usage to incr/decr rli->mts_wqs_overrun /* We need to make this a dynamic field. /Alfranio @@ -283,6 +289,8 @@ public: ulonglong group_relay_log_pos; char group_master_log_name[FN_REFLEN]; ulonglong group_master_log_pos; + char checkpoint_log_name[FN_REFLEN]; + ulonglong checkpoint_log_pos; int init_info(); void end_info(); @@ -292,7 +300,7 @@ public: void slave_worker_ends_group(Log_event*, int); // CGEP walk through to upd APH - bool commit_positions(Log_event *evt); + bool commit_positions(Log_event *evt, Slave_job_group *ptr_g); private: bool read_info(Rpl_info_handler *from); === modified file 'sql/rpl_slave.cc' --- a/sql/rpl_slave.cc 2010-12-08 13:59:07 +0000 +++ b/sql/rpl_slave.cc 2010-12-09 17:45:02 +0000 @@ -3751,6 +3751,8 @@ pthread_handler_t handle_slave_worker(vo mysql_mutex_lock(&rli->info_thd->LOCK_thd_data); rli->info_thd->awake(THD::KILL_QUERY); // notify Crdn mysql_mutex_unlock(&rli->info_thd->LOCK_thd_data); + // Todo: add necessary stuff to clean up after Q-log-event, a Q trans + rli->cleanup_context(thd, error); } mysql_mutex_lock(&w->jobs_lock); @@ -3932,6 +3934,8 @@ bool mts_checkpoint_routine(Relay_log_in error= rli->flush_info(TRUE); // end of commit_positions + rli->reset_notified_checkpoint(); + end: set_timespec_nsec(rli->last_clock, 0); @@ -3962,9 +3966,13 @@ int slave_start_single_worker(Relay_log_ Rpl_info_dummy *dummy_handler= new Rpl_info_dummy(); w->w_rli->set_rpl_info_handler(dummy_handler); w->init_info(); + + // TODO: remove after dynamic_ids will be sorted out (removed/refined) otherwise + // entry->usage assert + w->curr_group_exec_parts->dynamic_ids.elements= 0; w->relay_log_change_notified= FALSE; // the 1st group to contain relaylog name - + w->checkpoint_notified= FALSE; w->w_rli->workers= rli->workers; // shallow copying is sufficient w->w_rli->this_worker= w; @@ -4053,6 +4061,8 @@ int slave_start_workers(Relay_log_info * rli->mts_total_groups= 0; rli->curr_group_seen_begin= 0; rli->run_query_in_parallel= opt_slave_run_query_in_parallel; + rli->checkpoint_seqno= 0; + for (i= 0; i < n; i++) { if ((error= slave_start_single_worker(rli, i))) --===============0843880549== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/andrei.elkin@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: andrei.elkin@stripped # target_branch: file:///home/andrei/MySQL/BZR/2a-23May/WL/mysql-next-\ # mr-wl5569/ # testament_sha1: c6d7e42dee6872476a1b8b7846ab762b70a86d38 # timestamp: 2010-12-09 19:45:08 +0200 # base_revision_id: alfranio.correia@stripped\ # ms9cjfbgwpax0xcu # # Begin bundle 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 yj3AFmJyiVO+5MTrzkHAQuP+LuSKcKEhtOV4Xg== --===============0843880549==--