From: Andrei Elkin Date: December 4 2010 5:14pm Subject: bzr commit into mysql-next-mr-wl5569 branch (andrei.elkin:3229) List-Archive: http://lists.mysql.com/commits/126046 Message-Id: <201012041714.oB4HExxC011057@mysql1000.dsl.inet.fi> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============2032961495==" --===============2032961495== 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 3229 Andrei Elkin 2010-12-04 merging from the repo wl5569 modified: mysql-test/extra/rpl_tests/rpl_parallel_load.test sql/log_event.cc sql/rpl_rli.cc sql/rpl_rli_pdb.cc sql/rpl_rli_pdb.h sql/rpl_slave.cc sql/share/errmsg-utf8.txt === modified file 'mysql-test/extra/rpl_tests/rpl_parallel_load.test' --- a/mysql-test/extra/rpl_tests/rpl_parallel_load.test 2010-12-02 17:46:46 +0000 +++ b/mysql-test/extra/rpl_tests/rpl_parallel_load.test 2010-12-04 17:14:50 +0000 @@ -91,6 +91,11 @@ while($i) # Exec log position is not accurate in the prototype --sleep 2 +--disable_query_log +--disable_result_log +###select sleep(300); +--enable_result_log +--enable_query_log sync_slave_with_master; === modified file 'sql/log_event.cc' --- a/sql/log_event.cc 2010-12-02 18:13:12 +0000 +++ b/sql/log_event.cc 2010-12-04 17:14:50 +0000 @@ -2211,6 +2211,7 @@ Slave_worker *Log_event::get_slave_worke if ((is_b_event= starts_group()) || !rli->curr_group_seen_begin) { g.master_log_pos= log_pos; + g.group_master_log_pos= g.group_relay_log_pos= 0; g.group_relay_log_name= NULL; g.worker_id= (ulong) -1; g.total_seqno= const_cast(rli)->mts_total_groups++; @@ -2284,6 +2285,8 @@ Slave_worker *Log_event::get_slave_worke uint i; mts_group_cnt= rli->gaq->assigned_group_index; + // TODO: throw an error when relay-log reading starts from inside of a group!! + if (!worker->relay_log_change_notified) { /* @@ -2300,8 +2303,10 @@ Slave_worker *Log_event::get_slave_worke DBUG_ASSERT(ptr_g->group_relay_log_name == NULL); ptr_g->group_relay_log_name= (char *) - my_malloc(strlen(const_cast(rli)->get_group_relay_log_name()) + 1, MYF(MY_WME)); - strcpy(ptr_g->group_relay_log_name, const_cast(rli)->get_group_relay_log_name()); + my_malloc(strlen(const_cast(rli)-> + get_group_relay_log_name()) + 1, MYF(MY_WME)); + strcpy(ptr_g->group_relay_log_name, + const_cast(rli)->get_group_relay_log_name()); DBUG_ASSERT(ptr_g->group_relay_log_name != NULL); @@ -2416,15 +2421,15 @@ void append_item_to_jobs(slave_job_item Slave_worker *w, Relay_log_info *rli) { THD *thd= rli->info_thd; - int ret= -1; - ulonglong new_pend_size= rli->mts_pending_jobs_size + - ((Log_event*) (job_item->data))->data_written; + int ret; + ulong ev_size= ((Log_event*) (job_item->data))->data_written; + ulonglong new_pend_size; DBUG_ASSERT(thd == current_thd); thd_proc_info(thd, "Feeding an event to a worker thread"); mysql_mutex_lock(&rli->pending_jobs_lock); - + new_pend_size= rli->mts_pending_jobs_size + ev_size; // C waits basing on *data* sizes in the queues while (new_pend_size > rli->mts_pending_jobs_size_max) { @@ -2440,11 +2445,12 @@ void append_item_to_jobs(slave_job_item wait_info); mysql_cond_wait(&rli->pending_jobs_cond, &rli->pending_jobs_lock); thd->exit_cond(old_msg); - mysql_mutex_lock(&rli->pending_jobs_lock); if (thd->killed) return; - new_pend_size= rli->mts_pending_jobs_size + - ((Log_event*) (job_item->data))->data_written; + + mysql_mutex_lock(&rli->pending_jobs_lock); + + new_pend_size= rli->mts_pending_jobs_size + ev_size; } rli->pending_jobs++; rli->mts_pending_jobs_size= new_pend_size; @@ -2463,6 +2469,8 @@ void append_item_to_jobs(slave_job_item my_sleep(nap_weight * rli->mts_coordinator_basic_nap); } + ret= -1; + mysql_mutex_lock(&w->jobs_lock); // possible WQ overfill @@ -2495,9 +2503,10 @@ void append_item_to_jobs(slave_job_item else { mysql_mutex_unlock(&w->jobs_lock); + mysql_mutex_lock(&rli->pending_jobs_lock); rli->pending_jobs--; // roll back of the prev incr - rli->mts_pending_jobs_size -= new_pend_size; + rli->mts_pending_jobs_size -= ev_size; mysql_mutex_unlock(&rli->pending_jobs_lock); } } @@ -2651,6 +2660,7 @@ int slave_worker_exec_job(Slave_worker * job_item= pop_jobs_item(w, job_item); if (thd->killed) { + // de-queueing and decrement counters is in the caller's exit branch error= -1; goto err; } @@ -2701,9 +2711,7 @@ int slave_worker_exec_job(Slave_worker * { DBUG_PRINT("slave_worker_exec_job:", (" commits GAQ index %lu, last committed %lu", ev->mts_group_cnt, w->last_group_done_index)); - w->slave_worker_ends_group(ev->mts_group_cnt, error); /* last done sets post exec */ - if (!(ev->get_type_code() == XID_EVENT && w->is_transactional())) - w->commit_positions(ev); + w->slave_worker_ends_group(ev, error); /* last done sets post exec */ } mysql_mutex_lock(&w->jobs_lock); @@ -2720,6 +2728,7 @@ int slave_worker_exec_job(Slave_worker * preserving signatures of existing methods. todo: convert update_pos(w->w_rli) -> update_pos(w) to remove w_rli w/a + TODO: remove ? */ if (!error) ev->update_pos(w->w_rli); @@ -2769,16 +2778,13 @@ int slave_worker_exec_job(Slave_worker * mysql_cond_signal(&rli->pending_jobs_cond); } - //DBUG_ASSERT(rli->pending_jobs < rli->slave_pending_jobs_max); - // if (rli->pending_jobs == rli->slave_pending_jobs_max - 1 || - // rli->pending_jobs == 0) - // mysql_cond_signal(&rli->pending_jobs_cond); - mysql_mutex_unlock(&rli->pending_jobs_lock); w->stmt_jobs++; + err: + // TODO!!! ANDREI to RESTORE // if (!ev) // delete ev; // after ev->update_pos() event is garbage === modified file 'sql/rpl_rli.cc' --- a/sql/rpl_rli.cc 2010-12-03 16:56:11 +0000 +++ b/sql/rpl_rli.cc 2010-12-04 17:14:50 +0000 @@ -152,7 +152,6 @@ void Relay_log_info::init_workers(ulong { uint wi= 0; - slave_parallel_workers= n; /* Parallel slave parameters initialization is done regardless whether the feature is or going to be active or not. === modified file 'sql/rpl_rli_pdb.cc' --- a/sql/rpl_rli_pdb.cc 2010-12-03 10:15:45 +0000 +++ b/sql/rpl_rli_pdb.cc 2010-12-04 17:14:50 +0000 @@ -138,7 +138,8 @@ bool Slave_worker::write_info(Rpl_info_h */ if (to->prepare_info_for_write() || - to->set_info(curr_group_exec_parts) || + //to->set_info(curr_group_exec_parts) || + to->set_info("") || to->set_info(group_relay_log_name) || to->set_info((ulong)group_relay_log_pos) || to->set_info(group_master_log_name) || @@ -474,9 +475,10 @@ Slave_worker *get_least_occupied_worker( TODO: reclaim space if the actual size exceeds the limit. */ -void Slave_worker::slave_worker_ends_group(ulong gaq_idx, int error) +void Slave_worker::slave_worker_ends_group(Log_event* ev, int error) { int i; + ulong gaq_idx= ev->mts_group_cnt; if (!error) { @@ -495,12 +497,27 @@ void Slave_worker::slave_worker_ends_gro <= sizeof(group_relay_log_name)); strcpy(group_relay_log_name, ptr_g->group_relay_log_name); - delete ptr_g->group_relay_log_name; // C allocated - ptr_g->group_relay_log_name= NULL; // mark freed } - last_group_done_index = gaq_idx; + + // 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); + + ptr_g->group_master_log_pos= group_master_log_pos; + ptr_g->group_relay_log_pos= group_relay_log_pos; + + last_group_done_index = gaq_idx; // GAQ index is available to C now } + // cleanup relating to the last executed group regardless of error + for (i= curr_group_exec_parts->dynamic_ids.elements; i > 0; i--) { db_worker *entry= NULL; @@ -531,12 +548,6 @@ void Slave_worker::slave_worker_ends_gro } else DBUG_ASSERT(usage_partition != 0); - /* - TODO: - if U == 0 \and count(APH) > max - delete from APH where U = 0; - delete entry; - */ mysql_mutex_unlock(&slave_worker_hash_lock); @@ -659,13 +670,14 @@ bool circular_buffer_queue::gt(ulong i, It's compared first against the polled to break out of the loop at once if no progress. - - The caller is expected to be the checkpoint handler. + The caller is supposed to be the checkpoint handler. A copy of the last discarded item containing the refreshed value of the committed low-water-mark is stored - into @c lwm member for further caller's processing. + into @c lwm container member for further caller's processing. + @note dyn-allocated members of Slave_job_group such as + group_relay_log_name as freed here. @return number of discarded items */ @@ -675,12 +687,15 @@ ulong Slave_committed_queue::move_queue_ for (i= e; i != a && !empty();) { Slave_worker *w_i; - Slave_job_group g; + Slave_job_group *ptr_g; ulong l; - get_dynamic(&Q, (uchar *) &g, i); - if (g.worker_id == (ulong) -1) + char grl_name[FN_REFLEN]; + + grl_name[0]= 0; + ptr_g= (Slave_job_group *) dynamic_array_ptr(&Q, i); + if (ptr_g->worker_id == (ulong) -1) break; /* the head is not even assigned */ - get_dynamic(ws, (uchar *) &w_i, g.worker_id); + get_dynamic(ws, (uchar *) &w_i, ptr_g->worker_id); get_dynamic(&last_done, (uchar *) &l, w_i->id); DBUG_ASSERT(l <= s); @@ -691,9 +706,29 @@ ulong Slave_committed_queue::move_queue_ DBUG_ASSERT(w_i->last_group_done_index >= i || (((i > a && e > a) || a == s) && (w_i->last_group_done_index < a))); + // memorize the last met group_relay_log_name + if (ptr_g->group_relay_log_name) + { + strcpy(grl_name, ptr_g->group_relay_log_name); + my_free(ptr_g->group_relay_log_name); + ptr_g->group_relay_log_name= NULL; // mark freed + } + if (w_i->last_group_done_index == i || gt(w_i->last_group_done_index, i)) { - ulong ind= de_queue((uchar*) &lwm); + Slave_job_group g; + ulong ind= de_queue((uchar*) &g); + + // stored the memorized name into result struct + if (grl_name[0] != 0) + strcpy(lwm.group_relay_log_name, grl_name); + else + lwm.group_relay_log_name[0]= 0; + + DBUG_ASSERT(!ptr_g->group_relay_log_name); + + g.group_relay_log_name= lwm.group_relay_log_name; + lwm= g; // the result struct is done for the current iteration /* todo/fixme: the least occupied sorting out can be triggered here */ /* e.g @@ -706,7 +741,7 @@ ulong Slave_committed_queue::move_queue_ } */ DBUG_ASSERT(ind == i); - DBUG_ASSERT(g.total_seqno == lwm.total_seqno); + DBUG_ASSERT(ptr_g->total_seqno == lwm.total_seqno); set_dynamic(&last_done, (uchar*) &i, w_i->id); } @@ -751,7 +786,7 @@ int wait_for_workers_to_finish(Relay_log thd->exit_cond(proc_info); ret++; - DBUG_ASSERT(entry->usage == 0); + DBUG_ASSERT(entry->usage == 0 || thd->killed); } else { === modified file 'sql/rpl_rli_pdb.h' --- a/sql/rpl_rli_pdb.h 2010-12-01 19:15:08 +0000 +++ b/sql/rpl_rli_pdb.h 2010-12-04 17:14:50 +0000 @@ -91,7 +91,9 @@ public: typedef struct st_slave_job_group { - my_off_t master_log_pos; + my_off_t master_log_pos; // B-event log_pos + my_off_t group_master_log_pos; // T-event lop_pos filled by W for CheckPoint + my_off_t group_relay_log_pos; // filled by W /* When RL name changes C allocates and fill in a new name of RL, @@ -99,11 +101,10 @@ typedef struct st_slave_job_group C keeps track of each Worker has been notified on the updating to make sure the routine runs once per change. - W checks the value at commit and memoriezes a not-NULL - with prior freeing old one's allocation. The memorized value - plays its role at commit until a new has arrived. + W checks the value at commit and memoriezes a not-NULL. + Freeing unless NULL is left to C at CheckPoint. */ - char *group_relay_log_name; + char *group_relay_log_name; // The value is last seen relay-log ulong worker_id; ulonglong total_seqno; } Slave_job_group; @@ -139,11 +140,14 @@ public: my_init_dynamic_array(&last_done, sizeof(s), n, 0); for (k= 0; k < n; k++) insert_dynamic(&last_done, (uchar*) &s); // empty for each Worker + lwm.group_relay_log_name= (char *) my_malloc(FN_REFLEN + 1, MYF(0)); + lwm.group_relay_log_name[0]= 0; } ~Slave_committed_queue () { delete_dynamic(&last_done); + my_free(lwm.group_relay_log_name); } /* Checkpoint routine refreshes the queue */ @@ -216,7 +220,7 @@ public: size_t get_number_worker_fields(); - void slave_worker_ends_group(ulong, int); // CGEP walk through to upd APH + void slave_worker_ends_group(Log_event*, int); // CGEP walk through to upd APH bool commit_positions(Log_event *evt); === modified file 'sql/rpl_slave.cc' --- a/sql/rpl_slave.cc 2010-12-04 15:45:02 +0000 +++ b/sql/rpl_slave.cc 2010-12-04 17:14:50 +0000 @@ -168,7 +168,7 @@ static int terminate_slave_thread(THD *t bool skip_lock); static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info); int slave_worker_exec_job(Slave_worker * w, Relay_log_info *rli); -bool checkpoint_routine(Relay_log_info *rli); +bool mts_checkpoint_routine(Relay_log_info *rli); /* Find out which replications threads are running @@ -3571,6 +3571,8 @@ pthread_handler_t handle_slave_worker(vo mysql_mutex_lock(&rli->pending_jobs_lock); rli->pending_jobs -= purge_cnt; rli->mts_pending_jobs_size -= purge_size; + DBUG_ASSERT(rli->mts_pending_jobs_size < rli->mts_pending_jobs_size_max); + mysql_mutex_unlock(&rli->pending_jobs_lock); mysql_mutex_lock(&w->jobs_lock); @@ -3593,22 +3595,27 @@ err: DBUG_RETURN(0); } -bool checkpoint_routine(Relay_log_info *rli) +/** + Processing rli->gaq to find out the low-water-mark coordinates + stored into the cental recovery table. + + + @return FALSE success, TRUE otherwise +*/ +bool mts_checkpoint_routine(Relay_log_info *rli) { bool error= FALSE; + ulong cnt; DBUG_ENTER("checkpoint_routine"); - mysql_mutex_lock(&rli->data_lock); - - uint i; - rli->gaq->move_queue_head(&rli->workers); + if (!(cnt= rli->gaq->move_queue_head(&rli->workers))) + DBUG_RETURN(error); /* TODO: - the least occupied sorting out needs moving to the actual - checkpoint location - next_event() + to turn the least occupied selection in terms of jobs pieces */ - for (i= 0; i < rli->workers.elements; i++) + for (uint i= 0; i < rli->workers.elements; i++) { Slave_worker *w_i; get_dynamic(&rli->workers, (uchar *) &w_i, i); @@ -3616,6 +3623,21 @@ bool checkpoint_routine(Relay_log_info * }; sort_dynamic(&rli->least_occupied_workers, (qsort_cmp) ulong_cmp); + // Coordinator::commit_positions() { + + // Alfranio, rli->gaq->lwm contains all but rli->group_master_log_name + + // group_master_log_name is updated only by Coordinator and it can't change + // within checkpoint interval because Coordinator flushes the updated value + // at once. + + mysql_mutex_lock(&rli->data_lock); + + rli->set_group_master_log_pos(rli->gaq->lwm.group_master_log_pos); + rli->set_group_relay_log_pos(rli->gaq->lwm.group_relay_log_pos); + if (rli->gaq->lwm.group_relay_log_name[0] != 0) + rli->set_group_relay_log_name(rli->gaq->lwm.group_relay_log_name); + error= rli->flush_info(TRUE); mysql_mutex_unlock(&rli->data_lock); @@ -3766,7 +3788,7 @@ void slave_stop_workers(Relay_log_info * int i; THD *thd= rli->info_thd; - if (rli->workers.elements == 0) + if (rli->slave_parallel_workers == 0) return; for (i= rli->workers.elements - 1; i >= 0; i--) @@ -3875,7 +3897,7 @@ pthread_handler_t handle_slave_sql(void pthread_detach_this_thread(); /* mts-II: starting the worker pool */ - if (slave_start_workers(rli, opt_slave_parallel_workers) != 0) + if (slave_start_workers(rli, rli->slave_parallel_workers) != 0) goto err; if (init_slave_thread(thd, SLAVE_THD_SQL)) @@ -5321,7 +5343,7 @@ static Log_event* next_event(Relay_log_i ulong diff= diff_timespec(rli->curr_clock, rli->last_clock); if (diff > period) { - checkpoint_routine(rli); + mts_checkpoint_routine(rli); set_timespec_nsec(rli->last_clock, 0); } set_timespec_nsec(waittime, period); @@ -5707,6 +5729,12 @@ int start_slave(THD* thd , Master_info* */ if (thread_mask & SLAVE_SQL) { + /* + To cache the system var value and used it in the following. + The system var can change but not the cached. + */ + mi->rli->slave_parallel_workers= opt_slave_parallel_workers; + mysql_mutex_lock(&mi->rli->data_lock); if (thd->lex->mi.pos) @@ -5759,6 +5787,13 @@ int start_slave(THD* thd , Master_info* push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_MISSING_SKIP_SLAVE, ER(ER_MISSING_SKIP_SLAVE)); + if (mi->rli->slave_parallel_workers != 0) + { + mi->rli->slave_parallel_workers= 0; + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_NO_UNTIL_COND_WITH_PARALLEL_SLAVE, + ER(ER_NO_UNTIL_COND_WITH_PARALLEL_SLAVE)); + } } mysql_mutex_unlock(&mi->rli->data_lock); === modified file 'sql/share/errmsg-utf8.txt' --- a/sql/share/errmsg-utf8.txt 2010-10-25 10:39:01 +0000 +++ b/sql/share/errmsg-utf8.txt 2010-12-04 17:14:50 +0000 @@ -6399,3 +6399,6 @@ ER_RPL_INFO_DATA_TOO_LONG eng "Data for column '%s' too long" ER_CANT_LOCK_RPL_INFO_TABLE eng "You can't use locks with rpl info tables." + +ER_NO_UNTIL_COND_WITH_PARALLEL_SLAVE + eng "Until condition is not supported in Parallel Slave. Slave is started in the sequential mode." --===============2032961495== 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: 6a0a252c1d155b71ba141a90759aa119775f9503 # timestamp: 2010-12-04 19:14:59 +0200 # base_revision_id: alfranio.correia@stripped\ # 8f1ybcd943rzi3oh # # Begin bundle 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 --===============2032961495==--