From: Pekka Nousiainen Date: July 23 2011 4:25pm Subject: bzr push into mysql-5.1-telco-7.0-wl4124-new1 branch (pekka.nousiainen:4414 to 4416) WL#4124 List-Archive: http://lists.mysql.com/commits/140444 Message-Id: <20110723162500.3920255875@sama.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 4416 Pekka Nousiainen 2011-07-23 wl#4124 e04_error.diff allow "no stats" (error 4715) modified: mysql-test/suite/ndb/r/ndb_index_stat.result mysql-test/suite/ndb/r/ndb_statistics1.result sql/ha_ndb_index_stat.cc sql/ha_ndbcluster.cc 4415 Pekka Nousiainen 2011-07-23 wl#4124 e03_error.diff error handling cleanups modified: mysql-test/suite/ndb/r/ndb_index_stat.result mysql-test/suite/ndb/r/ndb_statistics1.result mysql-test/suite/ndb/t/ndb_index_stat.test sql/ha_ndb_index_stat.cc sql/ha_ndb_index_stat.h sql/ha_ndbcluster.cc sql/ha_ndbcluster.h 4414 Pekka Nousiainen 2011-07-23 wl#4124 e02_error.diff mutex cleanups modified: sql/ha_ndb_index_stat.cc sql/ha_ndb_index_stat.h sql/ha_ndbcluster.cc === modified file 'mysql-test/suite/ndb/r/ndb_index_stat.result' --- a/mysql-test/suite/ndb/r/ndb_index_stat.result 2011-07-19 16:04:38 +0000 +++ b/mysql-test/suite/ndb/r/ndb_index_stat.result 2011-07-23 14:38:08 +0000 @@ -230,6 +230,11 @@ a b 1 11 2 22 3 33 +select * from t1 order by a; +a b +1 11 +2 22 +3 33 analyze table t1; Table Op Msg_type Msg_text test.t1 analyze status OK === modified file 'mysql-test/suite/ndb/t/ndb_index_stat.test' --- a/mysql-test/suite/ndb/t/ndb_index_stat.test 2011-07-19 16:04:38 +0000 +++ b/mysql-test/suite/ndb/t/ndb_index_stat.test 2011-07-23 14:35:37 +0000 @@ -158,13 +158,16 @@ drop table t1; # bug#XXXXX # autocreate=false,enable=1 is now acceptable -# following hangs for error_delay (60s) if "no stats" is counted as error +# following gives warning while "no stats" is counted as error create table t1 (a int, b int, primary key using hash (a), index x1 (b)) engine=ndb; insert into t1 values (1,11),(2,22),(3,33); # make_join_statistics() -> info() -> ndb_index_stat_set_rpk() +# error 4715 - no stats select * from t1 order by a; -# index stat entry would now wait 60s on error list +# error 9003 suppressed - previous recent error +select * from t1 order by a; +# analyze clears previous error at once analyze table t1; drop table t1; === modified file 'sql/ha_ndb_index_stat.cc' --- a/sql/ha_ndb_index_stat.cc 2011-07-23 13:01:57 +0000 +++ b/sql/ha_ndb_index_stat.cc 2011-07-23 14:38:08 +0000 @@ -62,6 +62,7 @@ struct Ndb_index_stat { 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 no_stats; /* have detected that no stats exist */ NdbIndexStat::Error error; time_t error_time; int error_count; @@ -497,6 +498,7 @@ struct Ndb_index_stat_glob { uint list_count[Ndb_index_stat::LT_Count]; /* Temporary use */ uint total_count; uint force_update; + uint no_stats; uint wait_update; uint cache_query_bytes; /* In use */ uint cache_clean_bytes; /* Obsolete versions not yet removed */ @@ -504,6 +506,7 @@ struct Ndb_index_stat_glob { total_count(0), force_update(0), wait_update(0), + no_stats(0), cache_query_bytes(0), cache_clean_bytes(0) { @@ -545,6 +548,7 @@ Ndb_index_stat::Ndb_index_stat() check_time= 0; cache_clean= false; force_update= 0; + no_stats= false; error_time= 0; error_count= 0; share_next= 0; @@ -695,20 +699,57 @@ ndb_index_stat_force_update(Ndb_index_st } } +void +ndb_index_stat_no_stats(Ndb_index_stat *st, bool flag) +{ + Ndb_index_stat_glob &glob= ndb_index_stat_glob; + if (st->no_stats != flag) + { + if (flag) + { + glob.no_stats++; + st->no_stats= true; + } + else + { + assert(glob.no_stats >= 1); + glob.no_stats-= 1; + st->no_stats= false; + } + } +} + /* Find or add entry under the share */ Ndb_index_stat* -ndb_index_stat_alloc() +ndb_index_stat_alloc(const NDBINDEX *index, + const NDBTAB *table, + int &err_out) { + err_out= 0; Ndb_index_stat *st= new Ndb_index_stat; NdbIndexStat *is= new NdbIndexStat; if (st != 0 && is != 0) { st->is= is; - return st; + st->index_id= index->getObjectId(); + st->index_version= index->getObjectVersion(); +#ifndef DBUG_OFF + my_snprintf(st->id, sizeof(st->id), "%d.%d", st->index_id, st->index_version); +#endif + if (is->set_index(*index, *table) == 0) + return st; + ndb_index_stat_error(st, "set_index", __LINE__); + err_out= st->error.code; + } + else + { + err_out= NdbIndexStat::NoMemError; } - delete is; - delete st; + if (is != 0) + delete is; + if (st != 0) + delete st; return 0; } @@ -738,36 +779,21 @@ ndb_index_stat_find_share(NDB_SHARE *sha /* Subroutine, have lock */ Ndb_index_stat* ndb_index_stat_add_share(NDB_SHARE *share, - const NDBINDEX *index, - const NDBTAB *table, + Ndb_index_stat *st, Ndb_index_stat *st_last) { - struct Ndb_index_stat *st= ndb_index_stat_alloc(); - if (st != 0) - { - st->share= share; - if (st_last == 0) - share->index_stat_list= st; - else - st_last->share_next= st; - st->index_id= index->getObjectId(); - st->index_version= index->getObjectVersion(); -#ifndef DBUG_OFF - my_snprintf(st->id, sizeof(st->id), "%d.%d", st->index_id, st->index_version); -#endif - if (st->is->set_index(*index, *table) == -1) - { - ndb_index_stat_error(st, "set_index", __LINE__); - /* Caller assigns list */ - } - } - return st; + st->share= share; + if (st_last == 0) + share->index_stat_list= st; + else + st_last->share_next= st; } Ndb_index_stat* ndb_index_stat_get_share(NDB_SHARE *share, const NDBINDEX *index, const NDBTAB *table, + int &err_out, bool allow_add, bool force_update) { @@ -775,27 +801,39 @@ ndb_index_stat_get_share(NDB_SHARE *shar pthread_mutex_lock(&ndb_index_stat_list_mutex); pthread_mutex_lock(&ndb_index_stat_stat_mutex); time_t now= ndb_index_stat_time(); + err_out= 0; struct Ndb_index_stat *st= 0; struct Ndb_index_stat *st_last= 0; - if (ndb_index_stat_allow()) + do { - st= ndb_index_stat_find_share(share, index, st_last); - if (st == 0 && allow_add) + if (unlikely(!ndb_index_stat_allow())) { - st= ndb_index_stat_add_share(share, index, table, st_last); - if (st != 0) - ndb_index_stat_list_add(st, Ndb_index_stat::LT_New); + err_out= Ndb_index_stat_error_NOT_ALLOW; + break; } - if (st != 0) + st= ndb_index_stat_find_share(share, index, st_last); + if (st == 0) { - if (force_update) + if (!allow_add) { - ndb_index_stat_force_update(st, true); + err_out= Ndb_index_stat_error_NOT_FOUND; + break; + } + st= ndb_index_stat_alloc(index, table, err_out); + if (st == 0) + { + assert(err_out != 0); + break; } - st->access_time= now; + ndb_index_stat_add_share(share, st, st_last); + ndb_index_stat_list_add(st, Ndb_index_stat::LT_New); } + if (force_update) + ndb_index_stat_force_update(st, true); + st->access_time= now; } + while (0); pthread_mutex_unlock(&ndb_index_stat_stat_mutex); pthread_mutex_unlock(&ndb_index_stat_list_mutex); @@ -982,8 +1020,21 @@ ndb_index_stat_proc_read(Ndb_index_stat_ { pthread_mutex_lock(&ndb_index_stat_stat_mutex); ndb_index_stat_error(st, "read_stat", __LINE__); - pr.lt= Ndb_index_stat::LT_Error; + const uint 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) + { + ndb_index_stat_no_stats(st, true); + pr.lt= Ndb_index_stat::LT_Idle; + } + else + { + pr.lt= Ndb_index_stat::LT_Error; + } + pthread_cond_broadcast(&ndb_index_stat_stat_cond); pthread_mutex_unlock(&ndb_index_stat_stat_mutex); return; @@ -997,6 +1048,7 @@ ndb_index_stat_proc_read(Ndb_index_stat_ st->sample_version= head.m_sampleVersion; ndb_index_stat_force_update(st, false); + ndb_index_stat_no_stats(st, false); ndb_index_stat_cache_move(st); st->cache_clean= false; @@ -1097,7 +1149,16 @@ ndb_index_stat_proc_check(Ndb_index_stat if (st->is->read_head(pr.ndb) == -1) { ndb_index_stat_error(st, "read_head", __LINE__); - pr.lt= Ndb_index_stat::LT_Error; + /* no stats is not unexpected error */ + if (st->is->getNdbError().code == NdbIndexStat::NoIndexStats) + { + ndb_index_stat_no_stats(st, true); + pr.lt= Ndb_index_stat::LT_Idle; + } + else + { + pr.lt= Ndb_index_stat::LT_Error; + } return; } st->is->get_head(head); @@ -1380,15 +1441,11 @@ ndb_index_stat_report(const Ndb_index_st /* Updates waited for and forced updates */ { - pthread_mutex_lock(&ndb_index_stat_list_mutex); uint wait_update= new_glob.wait_update; uint force_update= new_glob.force_update; - pthread_mutex_unlock(&ndb_index_stat_list_mutex); - if (wait_update != 0 || force_update != 0) - { - DBUG_PRINT("index_stat", ("wait update:%u force update:%u", - wait_update, 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)); } } #endif @@ -1692,22 +1749,37 @@ ndb_index_stat_round(double x) } int -ha_ndbcluster::ndb_index_stat_wait(Ndb_index_stat *st, - uint sample_version) +ndb_index_stat_wait(Ndb_index_stat *st, + uint sample_version, + bool from_analyze) { - DBUG_ENTER("ha_ndbcluster::ndb_index_stat_wait"); + DBUG_ENTER("ndb_index_stat_wait"); pthread_mutex_lock(&ndb_index_stat_stat_mutex); int err= 0; uint count= 0; - (void)count; // USED struct timespec abstime; - while (true) { + while (true) + { int ret= 0; - if (st->error.code != 0 && - (st->error.code != NdbIndexStat::NoIndexStats || - st->force_update == 0)) + if (count == 0) + { + if (st->lt == Ndb_index_stat::LT_Error && !from_analyze) + { + err= Ndb_index_stat_error_HAS_ERROR; + break; + } + ndb_index_stat_clear_error(st); + } + if (st->no_stats && !from_analyze) + { + /* Have detected no stats now or before */ + err= NdbIndexStat::NoIndexStats; + break; + } + if (st->error.code != 0) { + /* A new error has occured */ err= st->error.code; break; } @@ -1729,7 +1801,8 @@ ha_ndbcluster::ndb_index_stat_wait(Ndb_i } } pthread_mutex_unlock(&ndb_index_stat_stat_mutex); - if (err != 0) { + if (err != 0) + { DBUG_PRINT("index_stat", ("st %s wait error: %d", st->id, err)); DBUG_RETURN(err); @@ -1760,14 +1833,12 @@ ha_ndbcluster::ndb_index_stat_query(uint ib.range_no= 0; Ndb_index_stat *st= - ndb_index_stat_get_share(m_share, index, m_table, true, false); + ndb_index_stat_get_share(m_share, index, m_table, err, true, false); if (st == 0) - { - DBUG_PRINT("index_stat", ("failed to add index stat share")); - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } + DBUG_RETURN(err); - err= ndb_index_stat_wait(st, 0); + /* Pass old version 0 so existing stats terminates wait at once */ + err= ndb_index_stat_wait(st, 0, false); if (err != 0) DBUG_RETURN(err); @@ -1881,10 +1952,9 @@ ha_ndbcluster::ndb_index_stat_analyze(Nd DBUG_PRINT("index_stat", ("force update: %s", index->getName())); Ndb_index_stat *st= - ndb_index_stat_get_share(m_share, index, m_table, true, true); - + ndb_index_stat_get_share(m_share, index, m_table, err, true, true); if (st == 0) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); + DBUG_RETURN(err); old[i].sample_version= st->sample_version; old[i].error_count= st->error_count; @@ -1899,11 +1969,11 @@ ha_ndbcluster::ndb_index_stat_analyze(Nd DBUG_PRINT("index_stat", ("wait for update: %s", index->getName())); Ndb_index_stat *st= - ndb_index_stat_get_share(m_share, index, m_table, false, false); + ndb_index_stat_get_share(m_share, index, m_table, err, false, false); if (st == 0) - DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); + DBUG_RETURN(err); - err= ndb_index_stat_wait(st, old[i].sample_version); + err= ndb_index_stat_wait(st, old[i].sample_version, true); if (err != 0) DBUG_RETURN(err); } === modified file 'sql/ha_ndb_index_stat.h' --- a/sql/ha_ndb_index_stat.h 2011-07-23 13:01:57 +0000 +++ b/sql/ha_ndb_index_stat.h 2011-07-23 14:35:37 +0000 @@ -39,3 +39,14 @@ void compute_index_bounds(NdbIndexScanOperation::IndexBound & bound, const KEY *key_info, const key_range *start_key, const key_range *end_key); + +/* error codes local to ha_ndb */ + +/* stats thread is not open for requests (should not happen) */ +#define Ndb_index_stat_error_NOT_ALLOW 9001 + +/* stats entry for existing index not found (should not happen) */ +#define Ndb_index_stat_error_NOT_FOUND 9002 + +/* request on stats entry with recent error was ignored */ +#define Ndb_index_stat_error_HAS_ERROR 9003 === modified file 'sql/ha_ndbcluster.cc' --- a/sql/ha_ndbcluster.cc 2011-07-23 13:01:57 +0000 +++ b/sql/ha_ndbcluster.cc 2011-07-23 14:38:08 +0000 @@ -40,6 +40,7 @@ #include "ha_ndbcluster_binlog.h" #include "ha_ndbcluster_tables.h" #include "ha_ndbcluster_connection.h" +#include "ha_ndb_index_stat.h" #include #include @@ -1352,6 +1353,7 @@ void ha_ndbcluster::set_rec_per_key() */ for (uint i=0 ; i < table_share->keys ; i++) { + KEY* key_info= table->key_info + i; switch (get_index_type(i)) { case UNIQUE_ORDERED_INDEX: @@ -1361,7 +1363,6 @@ void ha_ndbcluster::set_rec_per_key() { // Index is unique when all 'key_parts' are specified, // else distribution is unknown and not specified here. - KEY* key_info= table->key_info + i; key_info->rec_per_key[key_info->key_parts-1]= 1; break; } @@ -1375,8 +1376,18 @@ void ha_ndbcluster::set_rec_per_key() if (index_stat_enable) { int err= ndb_index_stat_set_rpk(i); - if (err == 0) - break; + if (err != 0 && + /* no stats is not unexpected error */ + err != NdbIndexStat::NoIndexStats && + /* warning was printed at first error */ + err != Ndb_index_stat_error_HAS_ERROR) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_CANT_GET_STAT, /* pun? */ + "index stats (RPK) for key %s:" + " unexpected error %d", + key_info->name, err); + } } // no fallback method... break; @@ -11817,6 +11828,18 @@ ha_ndbcluster::records_in_range(uint inx rows = 2; DBUG_RETURN(rows); } + if (err != 0 && + /* no stats is not unexpected error */ + err != NdbIndexStat::NoIndexStats && + /* warning was printed at first error */ + err != Ndb_index_stat_error_HAS_ERROR) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_CANT_GET_STAT, /* pun? */ + "index stats (RIR) for key %s:" + " unexpected error %d", + key_info->name, err); + } /*fall through*/ } === modified file 'sql/ha_ndbcluster.h' --- a/sql/ha_ndbcluster.h 2011-07-07 14:48:06 +0000 +++ b/sql/ha_ndbcluster.h 2011-07-23 14:35:37 +0000 @@ -858,17 +858,15 @@ private: void no_uncommitted_rows_reset(THD *); /* Ordered index statistics v4 */ + int ndb_index_stat_query(uint inx, + const key_range *min_key, + const key_range *max_key, + NdbIndexStat::Stat& stat); int ndb_index_stat_get_rir(uint inx, key_range *min_key, key_range *max_key, ha_rows *rows_out); int ndb_index_stat_set_rpk(uint inx); - int ndb_index_stat_wait(struct Ndb_index_stat *st, - uint sample_version); - int ndb_index_stat_query(uint inx, - const key_range *min_key, - const key_range *max_key, - NdbIndexStat::Stat& stat); int ndb_index_stat_analyze(Ndb *ndb, uint *inx_list, uint inx_count); No bundle (reason: useless for push emails).