From: Pekka Nousiainen Date: October 11 2011 3:17pm Subject: bzr push into mysql-5.1-telco-7.0 branch (pekka.nousiainen:4590) List-Archive: http://lists.mysql.com/commits/141387 Message-Id: <20111011151715.C75FF5781A@cuda.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 4590 Pekka Nousiainen 2011-10-11 [merge] merge 7.0 to wl4124 added: mysql-test/suite/ndb_big/bug37983-master.opt mysql-test/suite/ndb_big/disabled.def modified: mysql-test/mysql-test-run.pl mysql-test/suite/ndb/r/ndbinfo.result storage/ndb/include/ndb_constants.h storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp storage/ndb/src/kernel/vm/Ndbinfo.hpp storage/ndb/src/kernel/vm/NdbinfoTables.cpp === modified file 'mysql-test/suite/ndb/r/ndb_basic.result' --- a/mysql-test/suite/ndb/r/ndb_basic.result 2011-09-07 22:50:01 +0000 +++ b/mysql-test/suite/ndb/r/ndb_basic.result 2011-10-08 16:56:43 +0000 @@ -88,6 +88,7 @@ Ndb_connect_count # Ndb_execute_count # Ndb_index_stat_cache_clean # Ndb_index_stat_cache_query # +Ndb_index_stat_status # Ndb_number_of_data_nodes # Ndb_number_of_ready_data_nodes # Ndb_pruned_scan_count # === modified file 'mysql-test/suite/ndb/r/ndb_index_stat.result' --- a/mysql-test/suite/ndb/r/ndb_index_stat.result 2011-09-02 06:43:38 +0000 +++ b/mysql-test/suite/ndb/r/ndb_index_stat.result 2011-10-08 16:56:43 +0000 @@ -21,18 +21,18 @@ Variable_name Value ndb_index_stat_enable ON show global variables like 'ndb_index_stat_option'; Variable_name Value -ndb_index_stat_option loop_checkon=1000ms,loop_idle=1000ms,loop_busy=100ms,update_batch=1,read_batch=4,idle_batch=32,check_batch=32,check_delay=1m,delete_batch=8,clean_delay=0,error_batch=4,error_delay=1m,evict_batch=8,evict_delay=1m,cache_limit=32M,cache_lowpct=90 +ndb_index_stat_option loop_enable=1000ms,loop_idle=1000ms,loop_busy=100ms,update_batch=1,read_batch=4,idle_batch=32,check_batch=8,check_delay=10m,delete_batch=8,clean_delay=1m,error_batch=4,error_delay=1m,evict_batch=8,evict_delay=1m,cache_limit=32M,cache_lowpct=90 set @save_option = @@global.ndb_index_stat_option; set @@global.ndb_index_stat_option = 'loop_idle=3333,cache_limit=44M'; set @@global.ndb_index_stat_option = 'cache_lowpct=85,evict_delay=55'; set @@global.ndb_index_stat_option = 'check_delay=234s'; show global variables like 'ndb_index_stat_option'; Variable_name Value -ndb_index_stat_option loop_checkon=1000ms,loop_idle=3333ms,loop_busy=100ms,update_batch=1,read_batch=4,idle_batch=32,check_batch=32,check_delay=234s,delete_batch=8,clean_delay=0,error_batch=4,error_delay=1m,evict_batch=8,evict_delay=55s,cache_limit=44M,cache_lowpct=85 +ndb_index_stat_option loop_enable=1000ms,loop_idle=3333ms,loop_busy=100ms,update_batch=1,read_batch=4,idle_batch=32,check_batch=8,check_delay=234s,delete_batch=8,clean_delay=1m,error_batch=4,error_delay=1m,evict_batch=8,evict_delay=55s,cache_limit=44M,cache_lowpct=85 set @@global.ndb_index_stat_option = @save_option; show global variables like 'ndb_index_stat_option'; Variable_name Value -ndb_index_stat_option loop_checkon=1000ms,loop_idle=1000ms,loop_busy=100ms,update_batch=1,read_batch=4,idle_batch=32,check_batch=32,check_delay=1m,delete_batch=8,clean_delay=0,error_batch=4,error_delay=1m,evict_batch=8,evict_delay=1m,cache_limit=32M,cache_lowpct=90 +ndb_index_stat_option loop_enable=1000ms,loop_idle=1000ms,loop_busy=100ms,update_batch=1,read_batch=4,idle_batch=32,check_batch=8,check_delay=10m,delete_batch=8,clean_delay=1m,error_batch=4,error_delay=1m,evict_batch=8,evict_delay=1m,cache_limit=32M,cache_lowpct=90 create table t1 ( a1 int unsigned not null, b1 int unsigned not null, === modified file 'sql/ha_ndb_index_stat.cc' --- a/sql/ha_ndb_index_stat.cc 2011-09-19 09:26:42 +0000 +++ b/sql/ha_ndb_index_stat.cc 2011-10-08 16:56:43 +0000 @@ -64,7 +64,7 @@ struct Ndb_index_stat { uint sample_version; /* goes with read_time */ time_t check_time; /* when checked for updated stats (>= read_time) */ bool cache_clean; /* old caches have been deleted */ - uint force_update; /* one-time force update from analyze table */ + bool force_update; /* one-time force update from analyze table */ bool no_stats; /* have detected that no stats exist */ NdbIndexStat::Error error; time_t error_time; @@ -115,11 +115,8 @@ bool ndb_index_stat_allow_flag= false; bool ndb_index_stat_allow(int flag= -1) { - if (flag != -1) { - pthread_mutex_lock(&ndb_index_stat_list_mutex); + if (flag != -1) ndb_index_stat_allow_flag= (bool)flag; - pthread_mutex_unlock(&ndb_index_stat_list_mutex); - } return ndb_index_stat_allow_flag; } @@ -148,7 +145,7 @@ struct Ndb_index_stat_opt { uint flag; }; enum Idx { - Iloop_checkon = 0, + Iloop_enable = 0, Iloop_idle = 1, Iloop_busy = 2, Iupdate_batch = 3, @@ -186,15 +183,15 @@ Ndb_index_stat_opt::Ndb_index_stat_opt(c val[I##aname].maxval = amaxval; \ val[I##aname].unit = aunit; \ val[I##aname].flag = aflag - ival(loop_checkon, 1000, 0, ~0, Umsec, 0); + ival(loop_enable, 1000, 0, ~0, Umsec, 0); ival(loop_idle, 1000, 0, ~0, Umsec, 0); ival(loop_busy, 100, 0, ~0, Umsec, 0); ival(update_batch, 1, 1, ~0, Usize, 0); ival(read_batch, 4, 1, ~0, Usize, 0); ival(idle_batch, 32, 1, ~0, Usize, 0); - ival(check_batch, 32, 1, ~0, Usize, 0); - ival(check_delay, 60, 0, ~0, Utime, 0); - ival(clean_delay, 0, 0, ~0, Utime, 0); + ival(check_batch, 8, 1, ~0, Usize, 0); + ival(check_delay, 600, 0, ~0, Utime, 0); + ival(clean_delay, 60, 0, ~0, Utime, 0); ival(delete_batch, 8, 1, ~0, Usize, 0); ival(error_batch, 4, 1, ~0, Usize, 0); ival(error_delay, 60, 0, ~0, Utime, 0); @@ -498,40 +495,99 @@ ndb_index_stat_option_update(MYSQL_THD, /* Global stuff */ struct Ndb_index_stat_glob { - uint list_count[Ndb_index_stat::LT_Count]; /* Temporary use */ - uint total_count; + bool th_allow; /* Queries allowed */ + bool th_enable; /* Stats thread idea of ndb_index_stat_enable */ + bool th_busy; /* Stats thread is busy-looping */ + uint th_loop; /* Stats thread current loop wait in ms */ uint force_update; uint wait_update; uint no_stats; + uint wait_stats; + uint event_ok; /* Events received for known index */ + uint event_miss; /* Events received for unknown index */ + char status[2][512]; + uint status_i; uint cache_query_bytes; /* In use */ uint cache_clean_bytes; /* Obsolete versions not yet removed */ - Ndb_index_stat_glob() : - total_count(0), - force_update(0), - wait_update(0), - no_stats(0), - cache_query_bytes(0), - cache_clean_bytes(0) - { - } - void set_list_count() - { - total_count= 0; - int lt; - for (lt= 0; lt < Ndb_index_stat::LT_Count; lt++) - { - const Ndb_index_stat_list &list= ndb_index_stat_list[lt]; - list_count[lt]= list.count; - total_count++; - } - } - void set_status_variables() - { - g_ndb_status_index_stat_cache_query= cache_query_bytes; - g_ndb_status_index_stat_cache_clean= cache_clean_bytes; - } + + Ndb_index_stat_glob(); + void set_status(); }; +Ndb_index_stat_glob::Ndb_index_stat_glob() +{ + th_allow= false; + th_enable= false; + th_busy= false; + th_loop= 0; + force_update= 0; + wait_update= 0; + no_stats= 0; + wait_stats= 0; + event_ok= 0; + event_miss= 0; + memset(status, 0, sizeof(status)); + status_i= 0; + cache_query_bytes= 0; + cache_clean_bytes= 0; +} + +/* Update status variable (must hold stat_mutex) */ +void +Ndb_index_stat_glob::set_status() +{ + const Ndb_index_stat_opt &opt= ndb_index_stat_opt; + char* p= status[status_i]; + + // stats thread + th_allow= ndb_index_stat_allow(); + sprintf(p, "allow:%d,enable:%d,busy:%d,loop:%ums", + th_allow, th_enable, th_busy, th_loop); + p+= strlen(p); + + // entry lists + strcpy(p, ",list:("); + p+= strlen(p); + uint list_count= 0; + for (int lt= 1; lt < Ndb_index_stat::LT_Count; lt++) + { + const Ndb_index_stat_list &list= ndb_index_stat_list[lt]; + sprintf(p, "%s:%u,", list.name, list.count); + p+= strlen(p); + list_count+= list.count; + } + sprintf(p, "%s:%u)", "total", list_count); + p+= strlen(p); + + // special counters + sprintf(p, ",analyze:(queue:%u,wait:%u)", force_update, wait_update); + p+= strlen(p); + sprintf(p, ",stats:(none:%u,wait:%u)", no_stats, wait_stats); + p+= strlen(p); + + // events + sprintf(p, ",events:(ok:%u,miss:%u)", event_ok, event_miss); + p+= strlen(p); + + // cache size + const uint cache_limit= opt.get(Ndb_index_stat_opt::Icache_limit); + const uint cache_total= cache_query_bytes + cache_clean_bytes; + double cache_pct= (double)0.0; + if (cache_limit != 0) + cache_pct= (double)100.0 * (double)cache_total / (double)cache_limit; + sprintf(p, ",cache:(query:%u,clean:%u,total:%.2f%%)", + cache_query_bytes, cache_clean_bytes, cache_pct); + p+= strlen(p); + + // alternating status buffers to keep this lock short + pthread_mutex_lock(&LOCK_global_system_variables); + g_ndb_status_index_stat_status= status[status_i]; + status_i= (status_i + 1) % 2; + g_ndb_status_index_stat_cache_query= cache_query_bytes; + g_ndb_status_index_stat_cache_clean= cache_clean_bytes; + pthread_mutex_unlock(&LOCK_global_system_variables); +} + Ndb_index_stat_glob ndb_index_stat_glob; /* Shared index entries */ @@ -550,7 +606,7 @@ Ndb_index_stat::Ndb_index_stat() sample_version= 0; check_time= 0; cache_clean= false; - force_update= 0; + force_update= false; no_stats= false; error_time= 0; error_count= 0; @@ -603,13 +659,13 @@ Ndb_index_stat_list::Ndb_index_stat_list Ndb_index_stat_list ndb_index_stat_list[Ndb_index_stat::LT_Count] = { Ndb_index_stat_list(0, 0), - Ndb_index_stat_list(Ndb_index_stat::LT_New, "New"), - Ndb_index_stat_list(Ndb_index_stat::LT_Update, "Update"), - Ndb_index_stat_list(Ndb_index_stat::LT_Read, "Read"), - Ndb_index_stat_list(Ndb_index_stat::LT_Idle, "Idle"), - Ndb_index_stat_list(Ndb_index_stat::LT_Check, "Check"), - Ndb_index_stat_list(Ndb_index_stat::LT_Delete, "Delete"), - Ndb_index_stat_list(Ndb_index_stat::LT_Error, "Error") + Ndb_index_stat_list(Ndb_index_stat::LT_New, "new"), + Ndb_index_stat_list(Ndb_index_stat::LT_Update, "update"), + Ndb_index_stat_list(Ndb_index_stat::LT_Read, "read"), + Ndb_index_stat_list(Ndb_index_stat::LT_Idle, "idle"), + Ndb_index_stat_list(Ndb_index_stat::LT_Check, "check"), + Ndb_index_stat_list(Ndb_index_stat::LT_Delete, "delete"), + Ndb_index_stat_list(Ndb_index_stat::LT_Error, "error") }; void @@ -687,16 +743,22 @@ ndb_index_stat_force_update(Ndb_index_st Ndb_index_stat_glob &glob= ndb_index_stat_glob; if (onoff) { - /* One more request */ - glob.force_update++; - st->force_update++; + if (!st->force_update) + { + glob.force_update++; + st->force_update= true; + glob.set_status(); + } } else { - /* All done */ - assert(glob.force_update >= st->force_update); - glob.force_update-= st->force_update; - st->force_update= 0; + if (st->force_update) + { + assert(glob.force_update != 0); + glob.force_update--; + st->force_update= false; + glob.set_status(); + } } } @@ -717,6 +779,7 @@ ndb_index_stat_no_stats(Ndb_index_stat * glob.no_stats-= 1; st->no_stats= false; } + glob.set_status(); } } @@ -798,6 +861,8 @@ ndb_index_stat_get_share(NDB_SHARE *shar bool allow_add, bool force_update) { + Ndb_index_stat_glob &glob= ndb_index_stat_glob; + pthread_mutex_lock(&share->mutex); pthread_mutex_lock(&ndb_index_stat_list_mutex); pthread_mutex_lock(&ndb_index_stat_stat_mutex); @@ -829,6 +894,7 @@ ndb_index_stat_get_share(NDB_SHARE *shar } ndb_index_stat_add_share(share, st, st_last); ndb_index_stat_list_add(st, Ndb_index_stat::LT_New); + glob.set_status(); } if (force_update) ndb_index_stat_force_update(st, true); @@ -845,6 +911,7 @@ ndb_index_stat_get_share(NDB_SHARE *shar void ndb_index_stat_free(Ndb_index_stat *st) { + Ndb_index_stat_glob &glob= ndb_index_stat_glob; pthread_mutex_lock(&ndb_index_stat_list_mutex); NDB_SHARE *share= st->share; assert(share != 0); @@ -853,8 +920,10 @@ ndb_index_stat_free(Ndb_index_stat *st) Ndb_index_stat *st_tail= 0; Ndb_index_stat *st_loop= share->index_stat_list; bool found= false; - while (st_loop != 0) { - if (st == st_loop) { + while (st_loop != 0) + { + if (st == st_loop) + { st->share= 0; assert(st->lt != 0); assert(st->lt != Ndb_index_stat::LT_Delete); @@ -862,7 +931,9 @@ ndb_index_stat_free(Ndb_index_stat *st) st_loop= st_loop->share_next; assert(!found); found++; - } else { + } + else + { if (st_head == 0) st_head= st_loop; else @@ -874,12 +945,17 @@ ndb_index_stat_free(Ndb_index_stat *st) } assert(found); share->index_stat_list= st_head; + + pthread_mutex_lock(&ndb_index_stat_stat_mutex); + glob.set_status(); + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); pthread_mutex_unlock(&ndb_index_stat_list_mutex); } void ndb_index_stat_free(NDB_SHARE *share) { + Ndb_index_stat_glob &glob= ndb_index_stat_glob; pthread_mutex_lock(&ndb_index_stat_list_mutex); Ndb_index_stat *st; while ((st= share->index_stat_list) != 0) @@ -890,6 +966,9 @@ ndb_index_stat_free(NDB_SHARE *share) assert(st->lt != Ndb_index_stat::LT_Delete); ndb_index_stat_list_move(st, Ndb_index_stat::LT_Delete); } + pthread_mutex_lock(&ndb_index_stat_stat_mutex); + glob.set_status(); + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); pthread_mutex_unlock(&ndb_index_stat_list_mutex); } @@ -946,7 +1025,6 @@ ndb_index_stat_cache_move(Ndb_index_stat glob.cache_query_bytes-= old_query_bytes; glob.cache_query_bytes+= new_query_bytes; glob.cache_clean_bytes+= old_query_bytes; - glob.set_status_variables(); } void @@ -962,7 +1040,6 @@ ndb_index_stat_cache_clean(Ndb_index_sta st->is->clean_cache(); assert(glob.cache_clean_bytes >= old_clean_bytes); glob.cache_clean_bytes-= old_clean_bytes; - glob.set_status_variables(); } /* Misc in/out parameters for process steps */ @@ -986,9 +1063,8 @@ struct Ndb_index_stat_proc { void ndb_index_stat_proc_new(Ndb_index_stat_proc &pr, Ndb_index_stat *st) { - if (st->error.code != 0) - pr.lt= Ndb_index_stat::LT_Error; - else if (st->force_update) + assert(st->error.code == 0); + if (st->force_update) pr.lt= Ndb_index_stat::LT_Update; else pr.lt= Ndb_index_stat::LT_Read; @@ -997,6 +1073,7 @@ ndb_index_stat_proc_new(Ndb_index_stat_p void ndb_index_stat_proc_new(Ndb_index_stat_proc &pr) { + Ndb_index_stat_glob &glob= ndb_index_stat_glob; pthread_mutex_lock(&ndb_index_stat_list_mutex); const int lt= Ndb_index_stat::LT_New; Ndb_index_stat_list &list= ndb_index_stat_list[lt]; @@ -1008,8 +1085,12 @@ ndb_index_stat_proc_new(Ndb_index_stat_p st_loop= st_loop->list_next; DBUG_PRINT("index_stat", ("st %s proc %s", st->id, list.name)); ndb_index_stat_proc_new(pr, st); + assert(pr.lt != lt); ndb_index_stat_list_move(st, pr.lt); } + pthread_mutex_lock(&ndb_index_stat_stat_mutex); + glob.set_status(); + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); pthread_mutex_unlock(&ndb_index_stat_list_mutex); } @@ -1028,6 +1109,7 @@ ndb_index_stat_proc_update(Ndb_index_sta void ndb_index_stat_proc_update(Ndb_index_stat_proc &pr) { + Ndb_index_stat_glob &glob= ndb_index_stat_glob; const int lt= Ndb_index_stat::LT_Update; Ndb_index_stat_list &list= ndb_index_stat_list[lt]; const Ndb_index_stat_opt &opt= ndb_index_stat_opt; @@ -1041,7 +1123,12 @@ ndb_index_stat_proc_update(Ndb_index_sta st_loop= st_loop->list_next; DBUG_PRINT("index_stat", ("st %s proc %s", st->id, list.name)); ndb_index_stat_proc_update(pr, st); + assert(pr.lt != lt); ndb_index_stat_list_move(st, pr.lt); + // db op so update status after each + pthread_mutex_lock(&ndb_index_stat_stat_mutex); + glob.set_status(); + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); cnt++; } if (cnt == batch) @@ -1056,12 +1143,12 @@ ndb_index_stat_proc_read(Ndb_index_stat_ { pthread_mutex_lock(&ndb_index_stat_stat_mutex); ndb_index_stat_error(st, "read_stat", __LINE__); - const uint force_update= st->force_update; + const bool force_update= st->force_update; ndb_index_stat_force_update(st, false); /* no stats is not unexpected error, unless analyze was done */ if (st->is->getNdbError().code == NdbIndexStat::NoIndexStats && - force_update == 0) + !force_update) { ndb_index_stat_no_stats(st, true); pr.lt= Ndb_index_stat::LT_Idle; @@ -1096,6 +1183,7 @@ ndb_index_stat_proc_read(Ndb_index_stat_ void ndb_index_stat_proc_read(Ndb_index_stat_proc &pr) { + Ndb_index_stat_glob &glob= ndb_index_stat_glob; const int lt= Ndb_index_stat::LT_Read; Ndb_index_stat_list &list= ndb_index_stat_list[lt]; const Ndb_index_stat_opt &opt= ndb_index_stat_opt; @@ -1109,14 +1197,18 @@ ndb_index_stat_proc_read(Ndb_index_stat_ st_loop= st_loop->list_next; DBUG_PRINT("index_stat", ("st %s proc %s", st->id, list.name)); ndb_index_stat_proc_read(pr, st); + assert(pr.lt != lt); ndb_index_stat_list_move(st, pr.lt); + // db op so update status after each + pthread_mutex_lock(&ndb_index_stat_stat_mutex); + glob.set_status(); + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); cnt++; } if (cnt == batch) pr.busy= true; } -// wl4124_todo detect force_update faster void ndb_index_stat_proc_idle(Ndb_index_stat_proc &pr, Ndb_index_stat *st) { @@ -1141,12 +1233,20 @@ ndb_index_stat_proc_idle(Ndb_index_stat_ if (st->force_update) { pr.lt= Ndb_index_stat::LT_Update; + pr.busy= true; return; } if (check_wait <= 0) { - pr.lt= Ndb_index_stat::LT_Check; - return; + // avoid creating "idle" entries on Check list + const int lt_check= Ndb_index_stat::LT_Check; + const Ndb_index_stat_list &list_check= ndb_index_stat_list[lt_check]; + const uint check_batch= opt.get(Ndb_index_stat_opt::Icheck_batch); + if (list_check.count < check_batch) + { + pr.lt= Ndb_index_stat::LT_Check; + return; + } } pr.lt= Ndb_index_stat::LT_Idle; } @@ -1154,10 +1254,26 @@ ndb_index_stat_proc_idle(Ndb_index_stat_ void ndb_index_stat_proc_idle(Ndb_index_stat_proc &pr) { + Ndb_index_stat_glob &glob= ndb_index_stat_glob; const int lt= Ndb_index_stat::LT_Idle; Ndb_index_stat_list &list= ndb_index_stat_list[lt]; const Ndb_index_stat_opt &opt= ndb_index_stat_opt; - const uint batch= opt.get(Ndb_index_stat_opt::Iidle_batch); + uint batch= opt.get(Ndb_index_stat_opt::Iidle_batch); + { + pthread_mutex_lock(&ndb_index_stat_stat_mutex); + const Ndb_index_stat_glob &glob= ndb_index_stat_glob; + const int lt_update= Ndb_index_stat::LT_Update; + const Ndb_index_stat_list &list_update= ndb_index_stat_list[lt_update]; + if (glob.force_update > list_update.count) + { + // probably there is a force update waiting on Idle list + batch= ~0; + } + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); + } + // entry may be moved to end of this list + if (batch > list.count) + batch= list.count; pr.now= ndb_index_stat_time(); Ndb_index_stat *st_loop= list.head; @@ -1172,8 +1288,10 @@ ndb_index_stat_proc_idle(Ndb_index_stat_ ndb_index_stat_list_move(st, pr.lt); cnt++; } - if (cnt == batch) - pr.busy= true; + // full batch does not set pr.busy + pthread_mutex_lock(&ndb_index_stat_stat_mutex); + glob.set_status(); + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); } void @@ -1213,6 +1331,7 @@ ndb_index_stat_proc_check(Ndb_index_stat void ndb_index_stat_proc_check(Ndb_index_stat_proc &pr) { + Ndb_index_stat_glob &glob= ndb_index_stat_glob; const int lt= Ndb_index_stat::LT_Check; Ndb_index_stat_list &list= ndb_index_stat_list[lt]; const Ndb_index_stat_opt &opt= ndb_index_stat_opt; @@ -1226,7 +1345,12 @@ ndb_index_stat_proc_check(Ndb_index_stat st_loop= st_loop->list_next; DBUG_PRINT("index_stat", ("st %s proc %s", st->id, list.name)); ndb_index_stat_proc_check(pr, st); + assert(pr.lt != lt); ndb_index_stat_list_move(st, pr.lt); + // db op so update status after each + pthread_mutex_lock(&ndb_index_stat_stat_mutex); + glob.set_status(); + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); cnt++; } if (cnt == batch) @@ -1236,6 +1360,8 @@ ndb_index_stat_proc_check(Ndb_index_stat void ndb_index_stat_proc_evict(Ndb_index_stat_proc &pr, Ndb_index_stat *st) { + Ndb_index_stat_glob &glob= ndb_index_stat_glob; + NdbIndexStat::Head head; NdbIndexStat::CacheInfo infoBuild; NdbIndexStat::CacheInfo infoQuery; @@ -1257,6 +1383,10 @@ ndb_index_stat_proc_evict(Ndb_index_stat ndb_index_stat_cache_move(st); ndb_index_stat_cache_move(st); ndb_index_stat_cache_clean(st); + + pthread_mutex_lock(&ndb_index_stat_stat_mutex); + glob.set_status(); + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); } bool @@ -1349,6 +1479,7 @@ ndb_index_stat_proc_evict(Ndb_index_stat void ndb_index_stat_proc_delete(Ndb_index_stat_proc &pr) { + Ndb_index_stat_glob &glob= ndb_index_stat_glob; const int lt= Ndb_index_stat::LT_Delete; Ndb_index_stat_list &list= ndb_index_stat_list[lt]; const Ndb_index_stat_opt &opt= ndb_index_stat_opt; @@ -1370,6 +1501,10 @@ ndb_index_stat_proc_delete(Ndb_index_sta } if (cnt == batch) pr.busy= true; + + pthread_mutex_lock(&ndb_index_stat_stat_mutex); + glob.set_status(); + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); } void @@ -1400,10 +1535,14 @@ ndb_index_stat_proc_error(Ndb_index_stat void ndb_index_stat_proc_error(Ndb_index_stat_proc &pr) { + Ndb_index_stat_glob &glob= ndb_index_stat_glob; const int lt= Ndb_index_stat::LT_Error; Ndb_index_stat_list &list= ndb_index_stat_list[lt]; const Ndb_index_stat_opt &opt= ndb_index_stat_opt; - const uint batch= opt.get(Ndb_index_stat_opt::Ierror_batch); + uint batch= opt.get(Ndb_index_stat_opt::Ierror_batch); + // entry may be moved to end of this list + if (batch > list.count) + batch= list.count; pr.now= ndb_index_stat_time(); Ndb_index_stat *st_loop= list.head; @@ -1414,11 +1553,14 @@ ndb_index_stat_proc_error(Ndb_index_stat st_loop= st_loop->list_next; DBUG_PRINT("index_stat", ("st %s proc %s", st->id, list.name)); ndb_index_stat_proc_error(pr, st); + // rotates list if entry remains LT_Error ndb_index_stat_list_move(st, pr.lt); cnt++; } - if (cnt == batch) - pr.busy= true; + // full batch does not set pr.busy + pthread_mutex_lock(&ndb_index_stat_stat_mutex); + glob.set_status(); + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); } void @@ -1437,6 +1579,7 @@ ndb_index_stat_proc_event(Ndb_index_stat void ndb_index_stat_proc_event(Ndb_index_stat_proc &pr) { + Ndb_index_stat_glob &glob= ndb_index_stat_glob; NdbIndexStat *is= pr.is_util; Ndb *ndb= pr.ndb; int ret; @@ -1482,75 +1625,90 @@ ndb_index_stat_proc_event(Ndb_index_stat ndb_index_stat_proc_event(pr, st); if (pr.lt != st->lt) ndb_index_stat_list_move(st, pr.lt); + glob.event_ok++; } else { DBUG_PRINT("index_stat", ("entry not found in this mysqld")); + glob.event_miss++; } } + pthread_mutex_lock(&ndb_index_stat_stat_mutex); + glob.set_status(); + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); } #ifndef DBUG_OFF void -ndb_index_stat_report(const Ndb_index_stat_glob& old_glob) +ndb_index_stat_list_verify(int lt) { - Ndb_index_stat_glob new_glob= ndb_index_stat_glob; - new_glob.set_list_count(); - - /* List counts */ + const Ndb_index_stat_list &list= ndb_index_stat_list[lt]; + const Ndb_index_stat *st= list.head; + uint count= 0; + while (st != 0) { - const uint (&old_count)[Ndb_index_stat::LT_Count]= old_glob.list_count; - const uint (&new_count)[Ndb_index_stat::LT_Count]= new_glob.list_count; - bool any= false; - int lt; - for (lt=1; lt < Ndb_index_stat::LT_Count; lt++) - { - const Ndb_index_stat_list &list= ndb_index_stat_list[lt]; - const char* name= list.name; - if (old_count[lt] != new_count[lt]) - { - DBUG_PRINT("index_stat", ("%s: %u -> %u", - name, old_count[lt], new_count[lt])); - any= true; - } + count++; + assert(count <= list.count); + if (st->list_prev != 0) + { + assert(st->list_prev->list_next == st); } - if (any) + if (st->list_next != 0) { - const uint bufsz= 20 * Ndb_index_stat::LT_Count; - char buf[bufsz]; - char *ptr= buf; - for (lt= 1; lt < Ndb_index_stat::LT_Count; lt++) - { - const Ndb_index_stat_list &list= ndb_index_stat_list[lt]; - const char* name= list.name; - sprintf(ptr, " %s:%u", name, new_count[lt]); - ptr+= strlen(ptr); - } - DBUG_PRINT("index_stat", ("list:%s", buf)); + assert(st->list_next->list_prev == st); + } + if (count == 1) + { + assert(st == list.head); + } + if (count == list.count) + { + assert(st == list.tail); + } + if (st == list.head) + { + assert(count == 1); + assert(st->list_prev == 0); + } + if (st == list.tail) + { + assert(count == list.count); + assert(st->list_next == 0); } + const Ndb_index_stat *st2= st->list_next; + uint guard= 0; + while (st2 != 0) + { + assert(st != st2); + guard++; + assert(guard <= list.count); + st2= st2->list_next; + } + st= st->list_next; } + assert(count == list.count); +} + +void +ndb_index_stat_list_verify() +{ + pthread_mutex_lock(&ndb_index_stat_list_mutex); + for (int lt= 1; lt < Ndb_index_stat::LT_Count; lt++) + ndb_index_stat_list_verify(lt); + pthread_mutex_unlock(&ndb_index_stat_list_mutex); +} - /* Cache summary */ +void +ndb_index_stat_report(const Ndb_index_stat_glob& old_glob) +{ + const Ndb_index_stat_glob &new_glob= ndb_index_stat_glob; + const char *old_status= old_glob.status[old_glob.status_i]; + const char *new_status= new_glob.status[new_glob.status_i]; + + if (strcmp(old_status, new_status) != 0) { - const Ndb_index_stat_opt &opt= ndb_index_stat_opt; - uint query_size= new_glob.cache_query_bytes; - uint clean_size= new_glob.cache_clean_bytes; - uint total_size= query_size + clean_size; - const uint limit= opt.get(Ndb_index_stat_opt::Icache_limit); - double pct= 100.0; - if (limit != 0) - pct= 100.0 * (double)total_size / (double)limit; - DBUG_PRINT("index_stat", ("cache query:%u clean:%u (%.2f pct)", - query_size, clean_size, pct)); - } - - /* Updates waited for and forced updates */ - { - uint wait_update= new_glob.wait_update; - uint force_update= new_glob.force_update; - uint no_stats= new_glob.no_stats; - DBUG_PRINT("index_stat", ("wait update:%u force update:%u no stats:%u", - wait_update, force_update, no_stats)); + DBUG_PRINT("index_stat", ("old_status: %s", old_status)); + DBUG_PRINT("index_stat", ("new_status: %s", new_status)); } } #endif @@ -1558,13 +1716,12 @@ ndb_index_stat_report(const Ndb_index_st void ndb_index_stat_proc(Ndb_index_stat_proc &pr) { + DBUG_ENTER("ndb_index_stat_proc"); #ifndef DBUG_OFF + ndb_index_stat_list_verify(); Ndb_index_stat_glob old_glob= ndb_index_stat_glob; - old_glob.set_list_count(); #endif - DBUG_ENTER("ndb_index_stat_proc"); - ndb_index_stat_proc_new(pr); ndb_index_stat_proc_update(pr); ndb_index_stat_proc_read(pr); @@ -1576,6 +1733,7 @@ ndb_index_stat_proc(Ndb_index_stat_proc ndb_index_stat_proc_event(pr); #ifndef DBUG_OFF + ndb_index_stat_list_verify(); ndb_index_stat_report(old_glob); #endif DBUG_VOID_RETURN; @@ -1593,7 +1751,9 @@ ndb_index_stat_end() * in LT_Delete. The first two steps here should be unnecessary. */ + pthread_mutex_lock(&ndb_index_stat_stat_mutex); ndb_index_stat_allow(0); + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); int lt; for (lt= 1; lt < Ndb_index_stat::LT_Count; lt++) @@ -1739,6 +1899,7 @@ ndb_index_stat_thread_func(void *arg __a my_thread_init(); DBUG_ENTER("ndb_index_stat_thread_func"); + Ndb_index_stat_glob &glob= ndb_index_stat_glob; Ndb_index_stat_proc pr; bool have_listener; @@ -1840,7 +2001,15 @@ ndb_index_stat_thread_func(void *arg __a } pr.ndb= thd_ndb->ndb; + pthread_mutex_lock(&ndb_index_stat_stat_mutex); ndb_index_stat_allow(1); + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); + + /* Fill in initial status variable */ + pthread_mutex_lock(&ndb_index_stat_stat_mutex); + glob.set_status(); + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); + bool enable_ok; enable_ok= false; @@ -1907,7 +2076,7 @@ ndb_index_stat_thread_func(void *arg __a const Ndb_index_stat_opt &opt= ndb_index_stat_opt; uint msecs= 0; if (!enable_ok) - msecs= opt.get(Ndb_index_stat_opt::Iloop_checkon); + msecs= opt.get(Ndb_index_stat_opt::Iloop_enable); else if (!pr.busy) msecs= opt.get(Ndb_index_stat_opt::Iloop_idle); else @@ -1915,6 +2084,14 @@ ndb_index_stat_thread_func(void *arg __a DBUG_PRINT("index_stat", ("sleep %dms", msecs)); set_timespec_nsec(abstime, msecs * 1000000ULL); + + /* Update status variable */ + glob.th_enable= enable_ok; + glob.th_busy= pr.busy; + glob.th_loop= msecs; + pthread_mutex_lock(&ndb_index_stat_stat_mutex); + glob.set_status(); + pthread_mutex_unlock(&ndb_index_stat_stat_mutex); } ndb_index_stat_thread_end: @@ -1973,6 +2150,7 @@ ndb_index_stat_wait(Ndb_index_stat *st, { DBUG_ENTER("ndb_index_stat_wait"); + Ndb_index_stat_glob &glob= ndb_index_stat_glob; pthread_mutex_lock(&ndb_index_stat_stat_mutex); int err= 0; uint count= 0; @@ -1982,6 +2160,10 @@ ndb_index_stat_wait(Ndb_index_stat *st, int ret= 0; if (count == 0) { + if (!from_analyze) + glob.wait_stats++; + else + glob.wait_update++; if (st->lt == Ndb_index_stat::LT_Error && !from_analyze) { err= Ndb_index_stat_error_HAS_ERROR; @@ -2019,6 +2201,16 @@ ndb_index_stat_wait(Ndb_index_stat *st, break; } } + if (!from_analyze) + { + assert(glob.wait_stats != 0); + glob.wait_stats--; + } + else + { + assert(glob.wait_update != 0); + glob.wait_update--; + } pthread_mutex_unlock(&ndb_index_stat_stat_mutex); if (err != 0) { === modified file 'sql/ha_ndb_index_stat.h' --- a/sql/ha_ndb_index_stat.h 2011-08-31 10:53:27 +0000 +++ b/sql/ha_ndb_index_stat.h 2011-10-08 16:54:19 +0000 @@ -34,6 +34,7 @@ extern pthread_cond_t ndb_index_stat_sta /* these have to live in ha_ndbcluster.cc */ extern bool ndb_index_stat_get_enable(THD *thd); +extern const char* g_ndb_status_index_stat_status; extern long g_ndb_status_index_stat_cache_query; extern long g_ndb_status_index_stat_cache_clean; === modified file 'sql/ha_ndbcluster.cc' --- a/sql/ha_ndbcluster.cc 2011-09-22 14:43:45 +0000 +++ b/sql/ha_ndbcluster.cc 2011-10-08 16:54:19 +0000 @@ -446,6 +446,7 @@ extern void ndb_index_stat_end(); struct st_ndb_status g_ndb_status; +const char *g_ndb_status_index_stat_status = ""; long g_ndb_status_index_stat_cache_query = 0; long g_ndb_status_index_stat_cache_clean = 0; @@ -781,6 +782,7 @@ static int show_ndb_server_api_stats(THD } SHOW_VAR ndb_status_index_stat_variables[]= { + {"status", (char*) &g_ndb_status_index_stat_status, SHOW_CHAR_PTR}, {"cache_query", (char*) &g_ndb_status_index_stat_cache_query, SHOW_LONG}, {"cache_clean", (char*) &g_ndb_status_index_stat_cache_clean, SHOW_LONG}, {NullS, NullS, SHOW_LONG} No bundle (reason: useless for push emails).