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 <mysql/plugin.h>
#include <ndb_version.h>
@@ -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).
| Thread |
|---|
| • bzr push into mysql-5.1-telco-7.0-wl4124-new1 branch (pekka.nousiainen:4414to 4416) WL#4124 | Pekka Nousiainen | 25 Jul |