From: Andrei Elkin Date: December 21 2010 7:31pm Subject: bzr commit into mysql-next-mr-wl5569 branch (andrei.elkin:3254) WL#5569 List-Archive: http://lists.mysql.com/commits/127469 Message-Id: <201012211931.oBLJVbtB018486@mysql1000.dsl.inet.fi> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============2125780340==" --===============2125780340== 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 3254 Andrei Elkin 2010-12-21 wl#5569 MTS Recovery routine part I: gathering the group recovery bitmap. @ sql/log_event.h Introducing a typedef for getting frequently used struct. @ sql/rpl_rli_pdb.cc checkpoint_seqno is added to the Worker table to index of the last committed group in the bitmap; Init, read, write, propagation of its value are addressed. @ sql/rpl_rli_pdb.h Worker class gets checkpoint_seqno members. @ sql/rpl_slave.cc mts_recovery_groups() is refined to follow a simpler design scheme. Checkpoint info that Worker must have at recovery consists of seqno, bitmap and the master binlog coordinates. modified: sql/log_event.h sql/rpl_rli_pdb.cc sql/rpl_rli_pdb.h sql/rpl_slave.cc === modified file 'sql/log_event.h' --- a/sql/log_event.h 2010-12-16 21:41:45 +0000 +++ b/sql/log_event.h 2010-12-21 19:31:29 +0000 @@ -757,11 +757,11 @@ typedef struct st_print_event_info Such identifier is not yet unique generally as the event originating master is resetable. Also the crashed master can be replaced with some other. */ -struct event_coordinates +typedef struct event_coordinates { char * file_name; // binlog file name (directories stripped) my_off_t pos; // event's position in the binlog file -}; +} LOG_POS_COORD; /** @class Log_event === modified file 'sql/rpl_rli_pdb.cc' --- a/sql/rpl_rli_pdb.cc 2010-12-20 22:18:33 +0000 +++ b/sql/rpl_rli_pdb.cc 2010-12-21 19:31:29 +0000 @@ -15,10 +15,14 @@ const char *info_slave_worker_fields []= "relay_log_pos", "master_log_name", "master_log_pos", + + // todo: remove the next four "checkpoint_relay_log_name", "checkpoint_relay_log_pos", "checkpoint_master_log_name", "checkpoint_master_log_pos", + + "checkpoint_seqno", // index of the last committed group in the bitmap "checkpoint_group_size", "checkpoint_group_bitmap" }; @@ -27,7 +31,7 @@ Slave_worker::Slave_worker(const char* t Relay_log_info *rli) : Rpl_info_worker(type, pfs), c_rli(rli), curr_group_exec_parts(0), group_relay_log_pos(0), group_master_log_pos(0), - checkpoint_relay_log_pos(0), checkpoint_master_log_pos(0), + checkpoint_relay_log_pos(0), checkpoint_master_log_pos(0), checkpoint_seqno(0), inited_group_execed(0) { group_relay_log_name[0]= 0; @@ -133,6 +137,7 @@ bool Slave_worker::read_info(Rpl_info_ha ulong temp_group_master_log_pos= 0; ulong temp_checkpoint_relay_log_pos= 0; ulong temp_checkpoint_master_log_pos= 0; + ulong temp_checkpoint_seqno= 0; ulong nbytes= 0; uchar *buffer= (uchar *) group_execed.bitmap; @@ -159,6 +164,8 @@ bool Slave_worker::read_info(Rpl_info_ha (char *) "") || from->get_info((ulong *) &temp_checkpoint_master_log_pos, (ulong) 0) || + from->get_info((ulong *) &temp_checkpoint_seqno, + (ulong) 0) || from->get_info(&nbytes, (ulong) 0) || from->get_info(buffer, (size_t) nbytes, (uchar *) 0)) @@ -168,6 +175,7 @@ bool Slave_worker::read_info(Rpl_info_ha group_master_log_pos= temp_group_master_log_pos; checkpoint_relay_log_pos= temp_checkpoint_relay_log_pos; checkpoint_master_log_pos= temp_checkpoint_master_log_pos; + checkpoint_seqno= temp_checkpoint_seqno; DBUG_RETURN(FALSE); } @@ -188,6 +196,7 @@ bool Slave_worker::write_info(Rpl_info_h to->set_info((ulong) checkpoint_relay_log_pos) || to->set_info(checkpoint_master_log_name) || to->set_info((ulong) checkpoint_master_log_pos) || + to->set_info((ulong) checkpoint_seqno) || to->set_info(nbytes) || to->set_info(buffer, (size_t) nbytes)) DBUG_RETURN(TRUE); @@ -224,7 +233,7 @@ bool Slave_worker::commit_positions(Log_ } bitmap_set_bit(&group_execed, ptr_g->checkpoint_seqno); - + checkpoint_seqno= ptr_g->checkpoint_seqno; 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(), === modified file 'sql/rpl_rli_pdb.h' --- a/sql/rpl_rli_pdb.h 2010-12-20 22:18:33 +0000 +++ b/sql/rpl_rli_pdb.h 2010-12-21 19:31:29 +0000 @@ -139,6 +139,7 @@ typedef struct st_slave_job_group do \ { \ to.worker_id= from->id; \ + to.checkpoint_seqno= from->checkpoint_seqno; \ to.group_master_log_pos= from->checkpoint_master_log_pos; \ to.group_master_log_name= from->checkpoint_master_log_name; \ to.group_relay_log_pos= from->checkpoint_relay_log_pos; \ @@ -253,10 +254,14 @@ public: ulonglong group_relay_log_pos; char group_master_log_name[FN_REFLEN]; ulonglong group_master_log_pos; + + // todo: remove char checkpoint_relay_log_name[FN_REFLEN]; ulonglong checkpoint_relay_log_pos; + char checkpoint_master_log_name[FN_REFLEN]; ulonglong checkpoint_master_log_pos; + ulong checkpoint_seqno; int init_info(); void end_info(); === modified file 'sql/rpl_slave.cc' --- a/sql/rpl_slave.cc 2010-12-20 22:18:33 +0000 +++ b/sql/rpl_slave.cc 2010-12-21 19:31:29 +0000 @@ -3788,41 +3788,62 @@ err: /** Orders jobs by comparing relay log information. */ +#if 0 int mts_recovery_cmp(Slave_job_group *id1, Slave_job_group *id2) +#endif + +int mts_event_coord_cmp(LOG_POS_COORD *id1, LOG_POS_COORD *id2) { - longlong filecmp= strcmp(id1->group_relay_log_name, id2->group_relay_log_name); - longlong poscmp= id1->group_relay_log_pos - id2->group_relay_log_pos; + longlong filecmp= strcmp(id1->file_name, id2->file_name); + longlong poscmp= id1->pos - id2->pos; return (filecmp < 0 ? -1 : (filecmp > 0 ? 1 : (poscmp < 0 ? -1 : (poscmp > 0 ? 1 : 0)))); } bool mts_recovery_groups(Relay_log_info *rli, MY_BITMAP *groups) { - Log_event *ev= NULL, *desc= NULL; - char *log_name= NULL; + Log_event *ev= NULL; // , *desc= NULL; + const char *log_name= NULL; const char *errmsg= NULL; bool error= FALSE; - DYNAMIC_ARRAY jobs; - uint group_worker_counter; - uint group_lwm_counter; + DYNAMIC_ARRAY above_lwm_jobs; bool curr_group_seen_begin= FALSE; Slave_job_group job_worker; Slave_job_group job_file; IO_CACHE log; File file; MY_STAT s; - longlong filecmp= 0; - longlong poscmp= 0; + + LOG_POS_COORD cp= + { + (char *) rli->get_group_master_log_name(), + rli->get_group_master_log_pos() + }; DBUG_ENTER("mts_recovery_groups"); DBUG_ASSERT(rli->slave_parallel_workers > 0); /* - Gathers information on workers and stores it in jobs ordered by - relay log information. + Gathers information on valuable workers and stores it in + above_lwm_jobs in asc ordered by the master binlog coordinates. */ - my_init_dynamic_array(&jobs, sizeof(Slave_job_group), + my_init_dynamic_array(&above_lwm_jobs, sizeof(Slave_job_group), rli->slave_parallel_workers, rli->slave_parallel_workers); + + for (uint id= 0; id < rli->slave_parallel_workers; id++) + { + Slave_worker *worker= + Rpl_info_factory::create_worker(opt_worker_repository_id, id, rli); + worker->init_info(); + retrieve_job(worker, job_file); + LOG_POS_COORD w_last= {worker->group_master_log_name, worker->group_master_log_pos}; + if (mts_event_coord_cmp(&w_last, &cp) > 0) + insert_dynamic(&above_lwm_jobs, (uchar*) &job_file); + else + delete worker; + }; + +#if 0 for (uint id= 0; id < rli->slave_parallel_workers; id++) { Slave_worker *worker= @@ -3833,24 +3854,119 @@ bool mts_recovery_groups(Relay_log_info This avoids gathering information on workers that haven't processed anything. */ + + // TODO: disregard W_i | W_i->coord < LWM + if (job_file.group_relay_log_name != NULL && strcmp(job_file.group_relay_log_name, "") && job_file.group_master_log_name != NULL && strcmp(job_file.group_master_log_name, "")) - insert_dynamic(&jobs, (uchar*) &job_file); + insert_dynamic(&above_lwm_jobs, (uchar*) &job_file); } - sort_dynamic(&jobs, (qsort_cmp) mts_recovery_cmp); +#endif + sort_dynamic(&above_lwm_jobs, (qsort_cmp) mts_event_coord_cmp); /* - In what follows, the group bitmap is constructed. + In what follows, the group Recovery Bitmap is constructed. + + seek(lwm); + + while(w= next(above_lwm_w)) + do + read G + if G == w->last_comm + w.B << group_cnt++; + RB |= w.B; + break; + else + group_cnt++; + while(!eof); + continue; */ Format_description_log_event fdle(BINLOG_VERSION); if (!fdle.is_valid()) - goto end; + { + error= TRUE; + goto err; + } + + log_name= const_cast(rli)->get_group_relay_log_name(); + if ((file= open_binlog(&log, log_name, &errmsg)) < 0) + { + error= TRUE; + sql_print_error("%s", errmsg); + goto err; + } + DBUG_ASSERT(my_stat(log_name, &s, MYF(0))); // TODO: Alfranio, why my_stat? - for (uint it_job= 0; it_job < jobs.elements; it_job++) + my_b_seek(&log, (my_off_t) rli->get_group_relay_log_pos()); + + bitmap_clear_all(groups); + + for (uint it_job= 0, group_worker_counter= 0; it_job < above_lwm_jobs.elements; it_job++) + { + Slave_worker *w= ((Slave_job_group *) + dynamic_array_ptr(&above_lwm_jobs, it_job))->worker; + LOG_POS_COORD w_last= { w->group_master_log_name, w->group_master_log_pos }; + + sql_print_information("Recoverying relay log info based on Worker-Id %lu, " + "group_relay_log_name %s, group_relay_log_pos %lu " + "group_master_log_name %s, group_master_log_pos %lu", + w->id, + w->group_relay_log_name, + (ulong) w->group_relay_log_pos, + w->group_master_log_name, + (ulong) w->group_master_log_pos); + + // TODO: extend to handle sequence of relay logs (read(ev) -> EOF) + + while ((ev= Log_event::read_log_event(&log, 0, &fdle, + opt_master_verify_checksum))) + { + DBUG_ASSERT(ev->is_valid()); + DBUG_ASSERT(group_worker_counter < rli->checkpoint_group); + + // TODO: relax condition to allow --mts_exp_run_query_in_parallel= 1 + if (ev->starts_group()) + curr_group_seen_begin= TRUE; + else + if (ev->ends_group()) + { + int ret; + LOG_POS_COORD ev_coord= { (char *) rli->get_group_master_log_name(), + ev->log_pos }; + if ((ret= mts_event_coord_cmp(&ev_coord, &w_last)) == 0) + { + // hit it + // w.B << group_cnt++; + // RB |= w.B; + for (uint i= w->checkpoint_seqno - group_worker_counter, j= 0; + i <= w->checkpoint_seqno; i++, j++) + { + //bitmap_intersect(&rli->groups, &w->group_execed); + if (_bitmap_is_set(&w->group_execed, i)) + bitmap_fast_test_and_set(groups, j); + } + group_worker_counter++; + delete ev; + ev= NULL; + break; + } + else + { + DBUG_ASSERT(ret < 0); + group_worker_counter++; + } + } + delete ev; + ev= NULL; + } + } + +#if 0 + for (uint it_job= 0; it_job < above_lwm_jobs.elements; it_job++) { group_worker_counter= 0; group_lwm_counter= 0; - get_dynamic(&jobs, (uchar *) &job_worker, it_job); + get_dynamic(&above_lwm_jobs, (uchar *) &job_worker, it_job); sql_print_information("Recoverying relay log info based on Worker-Id %lu, " "group_relay_log_name %s, group_relay_log_pos %lu " @@ -3861,9 +3977,9 @@ bool mts_recovery_groups(Relay_log_info job_worker.group_master_log_name, (ulong) job_worker.group_master_log_pos); - for (uint it_file= 0; it_file < jobs.elements; it_file++) + for (uint it_file= 0; it_file < above_lwm_jobs.elements; it_file++) { - get_dynamic(&jobs, (uchar *) &job_file, it_file); + get_dynamic(&above_lwm_jobs, (uchar *) &job_file, it_file); /* Either the current relay log file was already processed by the @@ -3956,21 +4072,29 @@ end: desc= NULL; } + if (log_name) { end_io_cache(&log); mysql_file_close(file, MYF(MY_WME)); log_name= NULL; } +#endif - for (uint it_job= 0; it_job < jobs.elements; it_job++) + end_io_cache(&log); + mysql_file_close(file, MYF(MY_WME)); + log_name= NULL; + +err: + + for (uint it_job= 0; it_job < above_lwm_jobs.elements; it_job++) { - get_dynamic(&jobs, (uchar *) &job_worker, it_job); + get_dynamic(&above_lwm_jobs, (uchar *) &job_worker, it_job); job_worker.worker->end_info(); delete job_worker.worker; } - delete_dynamic(&jobs); + delete_dynamic(&above_lwm_jobs); DBUG_RETURN(error); } --===============2125780340== 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: 7419ddb0802e2bc384c53bf970193b1bdbb434aa # timestamp: 2010-12-21 21:31:37 +0200 # base_revision_id: alfranio.correia@stripped\ # ji1s836rsw09wq42 # # Begin bundle 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 --===============2125780340==--