4756 Pekka Nousiainen 2011-12-19 [merge]
merge 7.0 into wl#4124
modified:
mysql-test/suite/ndb/r/ndb_alter_table_online2.result
mysql-test/suite/ndb/t/ndb_alter_table_online2.test
storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
storage/ndb/src/mgmsrv/MgmtSrvr.cpp
storage/ndb/test/include/NDBT_Test.hpp
storage/ndb/test/include/NdbRestarts.hpp
storage/ndb/test/ndbapi/testDict.cpp
storage/ndb/test/ndbapi/testNodeRestart.cpp
storage/ndb/test/run-test/atrt.hpp
storage/ndb/test/run-test/daily-basic-tests.txt
storage/ndb/test/run-test/daily-perf-tests.txt
storage/ndb/test/run-test/db.cpp
storage/ndb/test/run-test/main.cpp
storage/ndb/test/run-test/test-tests.txt
storage/ndb/test/src/NDBT_Test.cpp
storage/ndb/test/src/NdbRestarts.cpp
=== modified file 'sql/ha_ndb_index_stat.cc'
--- a/sql/ha_ndb_index_stat.cc 2011-12-08 09:20:22 +0000
+++ b/sql/ha_ndb_index_stat.cc 2011-12-18 12:21:39 +0000
@@ -57,7 +57,6 @@ Ndb_index_stat_thread::Ndb_index_stat_th
pthread_mutex_init(&LOCK, MY_MUTEX_INIT_FAST);
pthread_cond_init(&COND, NULL);
pthread_cond_init(&COND_ready, NULL);
- pthread_mutex_init(&list_mutex, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&stat_mutex, MY_MUTEX_INIT_FAST);
pthread_cond_init(&stat_cond, NULL);
}
@@ -67,7 +66,6 @@ Ndb_index_stat_thread::~Ndb_index_stat_t
pthread_mutex_destroy(&LOCK);
pthread_cond_destroy(&COND);
pthread_cond_destroy(&COND_ready);
- pthread_mutex_destroy(&list_mutex);
pthread_mutex_destroy(&stat_mutex);
pthread_cond_destroy(&stat_cond);
}
@@ -97,9 +95,12 @@ struct Ndb_index_stat {
time_t check_time; /* when checked for updated stats (>= read_time) */
uint query_bytes; /* cache query bytes in use */
uint clean_bytes; /* cache clean bytes waiting to be deleted */
+ uint drop_bytes; /* cache bytes waiting for drop */
+ uint evict_bytes; /* cache bytes waiting for evict */
bool force_update; /* one-time force update from analyze table */
bool no_stats; /* have detected that no stats exist */
NdbIndexStat::Error error;
+ NdbIndexStat::Error client_error;
time_t error_time;
uint error_count;
struct Ndb_index_stat *share_next; /* per-share list */
@@ -108,7 +109,9 @@ struct Ndb_index_stat {
struct Ndb_index_stat *list_next;
struct Ndb_index_stat *list_prev;
struct NDB_SHARE *share;
+ uint ref_count; /* from client requests */
bool to_delete; /* detached from share and marked for delete */
+ bool abort_request; /* abort all requests and allow no more */
Ndb_index_stat();
};
@@ -563,12 +566,16 @@ struct Ndb_index_stat_glob {
uint event_ok; /* Events received for known index */
uint event_miss; /* Events received for unknown index */
uint refresh_count; /* Successful cache refreshes */
+ uint clean_count; /* Times old caches (1 or more) cleaned */
+ uint pinned_count; /* Times not cleaned due to old cache ref count */
uint drop_count; /* From index drop */
uint evict_count; /* From LRU cleanup */
/* Cache */
uint cache_query_bytes; /* In use */
uint cache_clean_bytes; /* Obsolete versions not yet removed */
uint cache_high_bytes; /* Max ever of above */
+ uint cache_drop_bytes; /* Part of above waiting to be evicted */
+ uint cache_evict_bytes; /* Part of above waiting to be evicted */
char status[2][512];
uint status_i;
@@ -595,11 +602,15 @@ Ndb_index_stat_glob::Ndb_index_stat_glob
event_ok= 0;
event_miss= 0;
refresh_count= 0;
+ clean_count= 0;
+ pinned_count= 0;
drop_count= 0;
evict_count= 0;
cache_query_bytes= 0;
cache_clean_bytes= 0;
cache_high_bytes= 0;
+ cache_drop_bytes= 0;
+ cache_evict_bytes= 0;
memset(status, 0, sizeof(status));
status_i= 0;
}
@@ -608,6 +619,8 @@ Ndb_index_stat_glob::Ndb_index_stat_glob
void
Ndb_index_stat_glob::set_status()
{
+ safe_mutex_assert_owner(&ndb_index_stat_thread.stat_mutex);
+
const Ndb_index_stat_opt &opt= ndb_index_stat_opt;
char* p= status[status_i];
@@ -642,11 +655,13 @@ Ndb_index_stat_glob::set_status()
p+= strlen(p);
sprintf(p, "analyze:(all:%u,error:%u)", analyze_count, analyze_error);
p+= strlen(p);
- sprintf(p, ",query:(all:%u,nostats:%u,error:%u)", query_count, query_no_stats, query_error);
+ sprintf(p, ",query:(all:%u,nostats:%u,error:%u)",
+ query_count, query_no_stats, query_error);
p+= strlen(p);
sprintf(p, ",event:(ok:%u,miss:%u)", event_ok, event_miss);
p+= strlen(p);
- sprintf(p, ",cache:(refresh:%u,drop:%u,evict:%u)", refresh_count, drop_count, evict_count);
+ sprintf(p, ",cache:(refresh:%u,clean:%u,pinned:%u,drop:%u,evict:%u)",
+ refresh_count, clean_count, pinned_count, drop_count, evict_count);
p+= strlen(p);
sprintf(p, ")");
p+= strlen(p);
@@ -661,8 +676,12 @@ Ndb_index_stat_glob::set_status()
cache_pct= (double)100.0 * (double)cache_total / (double)cache_limit;
cache_high_pct= (double)100.0 * (double)cache_high_bytes / (double)cache_limit;
}
- sprintf(p, ",cache:(query:%u,clean:%u,usedpct:%.2f,highpct:%.2f)",
- cache_query_bytes, cache_clean_bytes, cache_pct, cache_high_pct);
+ sprintf(p, ",cache:(query:%u,clean:%u"
+ ",drop:%u,evict:%u"
+ ",usedpct:%.2f,highpct:%.2f)",
+ cache_query_bytes, cache_clean_bytes,
+ cache_drop_bytes, cache_evict_bytes,
+ cache_pct, cache_high_pct);
p+= strlen(p);
// alternating status buffers to keep this lock short
@@ -686,6 +705,8 @@ Ndb_index_stat_glob::zero_total()
event_ok= 0;
event_miss= 0;
refresh_count= 0;
+ clean_count= 0;
+ pinned_count= 0;
drop_count= 0;
evict_count= 0;
/* Reset highest use seen to current */
@@ -711,6 +732,8 @@ Ndb_index_stat::Ndb_index_stat()
check_time= 0;
query_bytes= 0;
clean_bytes= 0;
+ drop_bytes= 0;
+ evict_bytes= 0;
force_update= false;
no_stats= false;
error_time= 0;
@@ -721,24 +744,40 @@ Ndb_index_stat::Ndb_index_stat()
list_next= 0;
list_prev= 0;
share= 0;
+ ref_count= 0;
to_delete= false;
+ abort_request= false;
}
+/*
+ Called by stats thread and (rarely) by client. Caller must hold
+ stat_mutex. Client errors currently have no effect on execution
+ since they are probably local e.g. bad range (internal error).
+ Argument "from" is 0=stats thread 1=client.
+*/
void
-ndb_index_stat_error(Ndb_index_stat *st, const char* place, int line)
+ndb_index_stat_error(Ndb_index_stat *st,
+ int from, const char* place, int line)
{
+ safe_mutex_assert_owner(&ndb_index_stat_thread.stat_mutex);
+
time_t now= ndb_index_stat_time();
NdbIndexStat::Error error= st->is->getNdbError();
if (error.code == 0)
{
- // XXX why this if
+ /* Make sure code is not 0 */
NdbIndexStat::Error error2;
error= error2;
error.code= NdbIndexStat::InternalError;
error.status= NdbError::TemporaryError;
}
- st->error= error;
- st->error_time= now;
+ if (from == 0)
+ {
+ st->error= error;
+ st->error_time= now; /* Controls proc_error */
+ }
+ else
+ st->client_error= error;
st->error_count++;
DBUG_PRINT("index_stat", ("%s line %d: error %d line %d extra %d",
@@ -846,6 +885,8 @@ ndb_index_stat_list_move(Ndb_index_stat
void
ndb_index_stat_force_update(Ndb_index_stat *st, bool onoff)
{
+ safe_mutex_assert_owner(&ndb_index_stat_thread.stat_mutex);
+
Ndb_index_stat_glob &glob= ndb_index_stat_glob;
if (onoff)
{
@@ -871,6 +912,8 @@ ndb_index_stat_force_update(Ndb_index_st
void
ndb_index_stat_no_stats(Ndb_index_stat *st, bool flag)
{
+ safe_mutex_assert_owner(&ndb_index_stat_thread.stat_mutex);
+
Ndb_index_stat_glob &glob= ndb_index_stat_glob;
if (st->no_stats != flag)
{
@@ -889,8 +932,36 @@ ndb_index_stat_no_stats(Ndb_index_stat *
}
}
+void
+ndb_index_stat_ref_count(Ndb_index_stat *st, bool flag)
+{
+ safe_mutex_assert_owner(&ndb_index_stat_thread.stat_mutex);
+
+ uint old_count= st->ref_count;
+ (void)old_count; // USED
+ if (flag)
+ {
+ st->ref_count++;
+ }
+ else
+ {
+ assert(st->ref_count != 0);
+ st->ref_count--;
+ }
+ DBUG_PRINT("index_stat", ("st %s ref_count:%u->%u",
+ st->id, old_count, st->ref_count));
+}
+
/* Find or add entry under the share */
+/* Saved in get_share() under stat_mutex */
+struct Ndb_index_stat_snap {
+ time_t load_time;
+ uint sample_version;
+ Ndb_index_stat_snap() { load_time= 0; sample_version= 0; }
+};
+
+/* Subroutine, have lock */
Ndb_index_stat*
ndb_index_stat_alloc(const NDBINDEX *index,
const NDBTAB *table,
@@ -909,8 +980,8 @@ ndb_index_stat_alloc(const NDBINDEX *ind
#endif
if (is->set_index(*index, *table) == 0)
return st;
- ndb_index_stat_error(st, "set_index", __LINE__);
- err_out= st->error.code;
+ ndb_index_stat_error(st, 1, "set_index", __LINE__);
+ err_out= st->client_error.code;
}
else
{
@@ -963,6 +1034,7 @@ Ndb_index_stat*
ndb_index_stat_get_share(NDB_SHARE *share,
const NDBINDEX *index,
const NDBTAB *table,
+ Ndb_index_stat_snap &snap,
int &err_out,
bool allow_add,
bool force_update)
@@ -970,7 +1042,6 @@ ndb_index_stat_get_share(NDB_SHARE *shar
Ndb_index_stat_glob &glob= ndb_index_stat_glob;
pthread_mutex_lock(&share->mutex);
- pthread_mutex_lock(&ndb_index_stat_thread.list_mutex);
pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
time_t now= ndb_index_stat_time();
err_out= 0;
@@ -981,7 +1052,7 @@ ndb_index_stat_get_share(NDB_SHARE *shar
{
if (unlikely(!ndb_index_stat_allow()))
{
- err_out= Ndb_index_stat_error_NOT_ALLOW;
+ err_out= NdbIndexStat::MyNotAllow;
break;
}
st= ndb_index_stat_find_share(share, index, st_last);
@@ -989,7 +1060,7 @@ ndb_index_stat_get_share(NDB_SHARE *shar
{
if (!allow_add)
{
- err_out= Ndb_index_stat_error_NOT_FOUND;
+ err_out= NdbIndexStat::MyNotFound;
break;
}
st= ndb_index_stat_alloc(index, table, err_out);
@@ -1002,14 +1073,28 @@ ndb_index_stat_get_share(NDB_SHARE *shar
ndb_index_stat_list_add(st, Ndb_index_stat::LT_New);
glob.set_status();
}
+ else if (unlikely(st->abort_request))
+ {
+ err_out= NdbIndexStat::MyAbortReq;
+ break;
+ }
if (force_update)
ndb_index_stat_force_update(st, true);
+ snap.load_time= st->load_time;
+ snap.sample_version= st->sample_version;
st->access_time= now;
}
while (0);
+
+ if (err_out == 0)
+ {
+ assert(st != 0);
+ ndb_index_stat_ref_count(st, true);
+ }
+ else
+ st= 0;
pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
- pthread_mutex_unlock(&ndb_index_stat_thread.list_mutex);
pthread_mutex_unlock(&share->mutex);
return st;
}
@@ -1019,10 +1104,12 @@ ndb_index_stat_get_share(NDB_SHARE *shar
list and set "to_delete" flag. Stats thread does real delete.
*/
-/* caller must hold list_mutex */
+/* caller must hold stat_mutex */
void
ndb_index_stat_free(Ndb_index_stat *st)
{
+ safe_mutex_assert_owner(&ndb_index_stat_thread.stat_mutex);
+
DBUG_ENTER("ndb_index_stat_free");
Ndb_index_stat_glob &glob= ndb_index_stat_glob;
NDB_SHARE *share= st->share;
@@ -1044,6 +1131,7 @@ ndb_index_stat_free(Ndb_index_stat *st)
assert(st->lt != Ndb_index_stat::LT_Delete);
assert(!st->to_delete);
st->to_delete= true;
+ st->abort_request= true;
found++;
}
else
@@ -1060,9 +1148,7 @@ ndb_index_stat_free(Ndb_index_stat *st)
assert(found == 1);
share->index_stat_list= st_head;
- pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
glob.set_status();
- pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
DBUG_VOID_RETURN;
}
@@ -1074,7 +1160,7 @@ ndb_index_stat_free(NDB_SHARE *share, in
DBUG_PRINT("index_stat", ("(index_id:%d index_version:%d",
index_id, index_version));
Ndb_index_stat_glob &glob= ndb_index_stat_glob;
- pthread_mutex_lock(&ndb_index_stat_thread.list_mutex);
+ pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
uint found= 0;
Ndb_index_stat *st= share->index_stat_list;
@@ -1085,16 +1171,17 @@ ndb_index_stat_free(NDB_SHARE *share, in
{
ndb_index_stat_free(st);
found++;
+ glob.drop_count++;
+ assert(st->drop_bytes == 0);
+ st->drop_bytes= st->query_bytes + st->clean_bytes;
+ glob.cache_drop_bytes+= st->drop_bytes;
break;
}
st= st->share_next;
}
- pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
- glob.drop_count+= found;
glob.set_status();
pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
- pthread_mutex_unlock(&ndb_index_stat_thread.list_mutex);
DBUG_VOID_RETURN;
}
@@ -1103,7 +1190,8 @@ ndb_index_stat_free(NDB_SHARE *share)
{
DBUG_ENTER("ndb_index_stat_free");
Ndb_index_stat_glob &glob= ndb_index_stat_glob;
- pthread_mutex_lock(&ndb_index_stat_thread.list_mutex);
+ pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
+
uint found= 0;
Ndb_index_stat *st;
while ((st= share->index_stat_list) != 0)
@@ -1116,13 +1204,16 @@ ndb_index_stat_free(NDB_SHARE *share)
assert(st->lt != Ndb_index_stat::LT_Delete);
assert(!st->to_delete);
st->to_delete= true;
+ st->abort_request= true;
found++;
+ glob.drop_count++;
+ assert(st->drop_bytes == 0);
+ st->drop_bytes+= st->query_bytes + st->clean_bytes;
+ glob.cache_drop_bytes+= st->drop_bytes;
}
- pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
- glob.drop_count+= found;
+
glob.set_status();
pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
- pthread_mutex_unlock(&ndb_index_stat_thread.list_mutex);
DBUG_VOID_RETURN;
}
@@ -1133,7 +1224,7 @@ ndb_index_stat_find_entry(int index_id,
{
DBUG_ENTER("ndb_index_stat_find_entry");
pthread_mutex_lock(&ndbcluster_mutex);
- pthread_mutex_lock(&ndb_index_stat_thread.list_mutex);
+ pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
DBUG_PRINT("index_stat", ("find index:%d version:%d table:%d",
index_id, index_version, table_id));
@@ -1146,7 +1237,7 @@ ndb_index_stat_find_entry(int index_id,
if (st->index_id == index_id &&
st->index_version == index_version)
{
- pthread_mutex_unlock(&ndb_index_stat_thread.list_mutex);
+ pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
pthread_mutex_unlock(&ndbcluster_mutex);
DBUG_RETURN(st);
}
@@ -1154,7 +1245,7 @@ ndb_index_stat_find_entry(int index_id,
}
}
- pthread_mutex_unlock(&ndb_index_stat_thread.list_mutex);
+ pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
pthread_mutex_unlock(&ndbcluster_mutex);
DBUG_RETURN(0);
}
@@ -1186,7 +1277,7 @@ ndb_index_stat_cache_move(Ndb_index_stat
glob.cache_high_bytes= cache_total;
}
-void
+bool
ndb_index_stat_cache_clean(Ndb_index_stat *st)
{
Ndb_index_stat_glob &glob= ndb_index_stat_glob;
@@ -1194,12 +1285,46 @@ ndb_index_stat_cache_clean(Ndb_index_sta
st->is->get_cache_info(infoClean, NdbIndexStat::CacheClean);
const uint old_clean_bytes= infoClean.m_totalBytes;
- DBUG_PRINT("index_stat", ("st %s cache clean: clean:%u",
- st->id, old_clean_bytes));
+ const uint ref_count= infoClean.m_ref_count;
+ DBUG_PRINT("index_stat", ("st %s cache clean: clean:%u ref_count:%u",
+ st->id, old_clean_bytes, ref_count));
+ if (ref_count != 0)
+ return false;
st->is->clean_cache();
st->clean_bytes= 0;
assert(glob.cache_clean_bytes >= old_clean_bytes);
glob.cache_clean_bytes-= old_clean_bytes;
+ return true;
+}
+
+void
+ndb_index_stat_cache_evict(Ndb_index_stat *st)
+{
+ NdbIndexStat::Head head;
+ NdbIndexStat::CacheInfo infoBuild;
+ NdbIndexStat::CacheInfo infoQuery;
+ NdbIndexStat::CacheInfo infoClean;
+ st->is->get_head(head);
+ st->is->get_cache_info(infoBuild, NdbIndexStat::CacheBuild);
+ st->is->get_cache_info(infoQuery, NdbIndexStat::CacheQuery);
+ st->is->get_cache_info(infoClean, NdbIndexStat::CacheClean);
+
+ DBUG_PRINT("index_stat",
+ ("evict table: %u index: %u version: %u"
+ " sample version: %u"
+ " cache bytes build:%u query:%u clean:%u",
+ head.m_tableId, head.m_indexId, head.m_indexVersion,
+ head.m_sampleVersion,
+ infoBuild.m_totalBytes, infoQuery.m_totalBytes, infoClean.m_totalBytes));
+
+ /* Twice to move all caches to clean */
+ ndb_index_stat_cache_move(st);
+ ndb_index_stat_cache_move(st);
+ /* Unused variable release vs debug nonsense */
+ bool ok= false;
+ (void)ok; // USED
+ ok= ndb_index_stat_cache_clean(st);
+ assert(ok);
}
/* Misc in/out parameters for process steps */
@@ -1238,7 +1363,7 @@ 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_thread.list_mutex);
+ pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
const int lt= Ndb_index_stat::LT_New;
Ndb_index_stat_list &list= ndb_index_stat_list[lt];
@@ -1252,10 +1377,8 @@ ndb_index_stat_proc_new(Ndb_index_stat_p
assert(pr.lt != lt);
ndb_index_stat_list_move(st, pr.lt);
}
- pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
glob.set_status();
pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
- pthread_mutex_unlock(&ndb_index_stat_thread.list_mutex);
}
void
@@ -1263,8 +1386,8 @@ ndb_index_stat_proc_update(Ndb_index_sta
{
if (st->is->update_stat(pr.ndb) == -1)
{
- ndb_index_stat_error(st, "update_stat", __LINE__);
pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
+ ndb_index_stat_error(st, 0, "update_stat", __LINE__);
/*
Turn off force update or else proc_error() thinks
@@ -1318,7 +1441,7 @@ ndb_index_stat_proc_read(Ndb_index_stat_
if (st->is->read_stat(pr.ndb) == -1)
{
pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
- ndb_index_stat_error(st, "read_stat", __LINE__);
+ ndb_index_stat_error(st, 0, "read_stat", __LINE__);
const bool force_update= st->force_update;
ndb_index_stat_force_update(st, false);
@@ -1391,6 +1514,7 @@ ndb_index_stat_proc_read(Ndb_index_stat_
void
ndb_index_stat_proc_idle(Ndb_index_stat_proc &pr, Ndb_index_stat *st)
{
+ Ndb_index_stat_glob &glob= ndb_index_stat_glob;
const Ndb_index_stat_opt &opt= ndb_index_stat_opt;
const longlong clean_delay= opt.get(Ndb_index_stat_opt::Iclean_delay);
const longlong check_delay= opt.get(Ndb_index_stat_opt::Icheck_delay);
@@ -1415,7 +1539,10 @@ ndb_index_stat_proc_idle(Ndb_index_stat_
if (st->clean_bytes != 0 && clean_wait <= 0)
{
- ndb_index_stat_cache_clean(st);
+ if (ndb_index_stat_cache_clean(st))
+ glob.clean_count++;
+ else
+ glob.pinned_count++;
}
if (st->force_update)
{
@@ -1489,7 +1616,8 @@ ndb_index_stat_proc_check(Ndb_index_stat
NdbIndexStat::Head head;
if (st->is->read_head(pr.ndb) == -1)
{
- ndb_index_stat_error(st, "read_head", __LINE__);
+ pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
+ ndb_index_stat_error(st, 0, "read_head", __LINE__);
/* no stats is not unexpected error */
if (st->is->getNdbError().code == NdbIndexStat::NoIndexStats)
{
@@ -1500,6 +1628,8 @@ ndb_index_stat_proc_check(Ndb_index_stat
{
pr.lt= Ndb_index_stat::LT_Error;
}
+ pthread_cond_broadcast(&ndb_index_stat_thread.stat_cond);
+ pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
return;
}
st->is->get_head(head);
@@ -1544,39 +1674,6 @@ ndb_index_stat_proc_check(Ndb_index_stat
pr.busy= true;
}
-/* Only evict the caches */
-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;
- NdbIndexStat::CacheInfo infoClean;
- st->is->get_head(head);
- st->is->get_cache_info(infoBuild, NdbIndexStat::CacheBuild);
- st->is->get_cache_info(infoQuery, NdbIndexStat::CacheQuery);
- st->is->get_cache_info(infoClean, NdbIndexStat::CacheClean);
-
- DBUG_PRINT("index_stat",
- ("evict table: %u index: %u version: %u"
- " sample version: %u"
- " cache bytes build:%u query:%u clean:%u",
- head.m_tableId, head.m_indexId, head.m_indexVersion,
- head.m_sampleVersion,
- infoBuild.m_totalBytes, infoQuery.m_totalBytes, infoClean.m_totalBytes));
-
- /* Twice to move all caches to clean */
- ndb_index_stat_cache_move(st);
- ndb_index_stat_cache_move(st);
- ndb_index_stat_cache_clean(st);
-
- pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
- glob.set_status();
- pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
-}
-
/* Check if need to evict more */
bool
ndb_index_stat_proc_evict()
@@ -1584,6 +1681,11 @@ ndb_index_stat_proc_evict()
const Ndb_index_stat_opt &opt= ndb_index_stat_opt;
Ndb_index_stat_glob &glob= ndb_index_stat_glob;
uint curr_size= glob.cache_query_bytes + glob.cache_clean_bytes;
+
+ /* Subtract bytes already scheduled for evict */
+ assert(curr_size >= glob.cache_evict_bytes);
+ curr_size-= glob.cache_evict_bytes;
+
const uint cache_lowpct= opt.get(Ndb_index_stat_opt::Icache_lowpct);
const uint cache_limit= opt.get(Ndb_index_stat_opt::Icache_limit);
if (100 * curr_size <= cache_lowpct * cache_limit)
@@ -1619,6 +1721,9 @@ ndb_index_stat_proc_evict(Ndb_index_stat
if (!ndb_index_stat_proc_evict())
return;
+ /* Mutex entire routine (protect access_time) */
+ pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
+
/* Create a LRU batch */
Ndb_index_stat* st_lru_arr[ndb_index_stat_max_evict_batch + 1];
uint st_lru_cnt= 0;
@@ -1697,19 +1802,19 @@ ndb_index_stat_proc_evict(Ndb_index_stat
Ndb_index_stat *st= st_lru_arr[cnt];
DBUG_PRINT("index_stat", ("st %s proc evict %s", st->id, list.name));
- ndb_index_stat_proc_evict(pr, st);
- pthread_mutex_lock(&ndb_index_stat_thread.list_mutex);
+
+ /* Entry may have requests. Cache is evicted at delete. */
ndb_index_stat_free(st);
- pthread_mutex_unlock(&ndb_index_stat_thread.list_mutex);
+ assert(st->evict_bytes == 0);
+ st->evict_bytes= st->query_bytes + st->clean_bytes;
+ glob.cache_evict_bytes+= st->evict_bytes;
cnt++;
}
+ if (cnt == batch)
+ pr.busy= true;
- pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
glob.evict_count+= cnt;
pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
-
- if (cnt == batch)
- pr.busy= true;
}
void
@@ -1729,6 +1834,9 @@ ndb_index_stat_proc_delete(Ndb_index_sta
const uint delete_batch= opt.get(Ndb_index_stat_opt::Idelete_batch);
const uint batch= !pr.end ? delete_batch : ~(uint)0;
+ /* Mutex entire routine */
+ pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
+
Ndb_index_stat *st_loop= list.head;
uint cnt= 0;
while (st_loop != 0 && cnt < batch)
@@ -1738,12 +1846,26 @@ ndb_index_stat_proc_delete(Ndb_index_sta
DBUG_PRINT("index_stat", ("st %s proc %s", st->id, list.name));
// adjust global counters at drop
- pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
ndb_index_stat_force_update(st, false);
ndb_index_stat_no_stats(st, false);
- pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
- ndb_index_stat_proc_evict(pr, st);
+ /*
+ Do not wait for requests to terminate since this could
+ risk stats thread hanging. Instead try again next time.
+ Presumably clients will eventually notice abort_request.
+ */
+ if (st->ref_count != 0)
+ {
+ DBUG_PRINT("index_stat", ("st %s proc %s: ref_count:%u",
+ st->id, list.name, st->ref_count));
+ continue;
+ }
+
+ ndb_index_stat_cache_evict(st);
+ assert(glob.cache_drop_bytes >= st->drop_bytes);
+ glob.cache_drop_bytes-= st->drop_bytes;
+ assert(glob.cache_evict_bytes >= st->evict_bytes);
+ glob.cache_evict_bytes-= st->evict_bytes;
ndb_index_stat_list_remove(st);
delete st->is;
delete st;
@@ -1752,7 +1874,6 @@ ndb_index_stat_proc_delete(Ndb_index_sta
if (cnt == batch)
pr.busy= true;
- pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
glob.set_status();
pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
}
@@ -2011,7 +2132,7 @@ void
ndb_index_stat_list_verify(Ndb_index_stat_proc &pr)
{
const Ndb_index_stat_glob &glob= ndb_index_stat_glob;
- pthread_mutex_lock(&ndb_index_stat_thread.list_mutex);
+ pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
pr.cache_query_bytes= 0;
pr.cache_clean_bytes= 0;
@@ -2020,7 +2141,7 @@ ndb_index_stat_list_verify(Ndb_index_sta
assert(glob.cache_query_bytes == pr.cache_query_bytes);
assert(glob.cache_clean_bytes == pr.cache_clean_bytes);
- pthread_mutex_unlock(&ndb_index_stat_thread.list_mutex);
+ pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
}
void
@@ -2505,12 +2626,16 @@ ndb_index_stat_round(double x)
return n;
}
+/*
+ Client waits for query or analyze. The routines are
+ similar but separated for clarity.
+*/
+
int
-ndb_index_stat_wait(Ndb_index_stat *st,
- uint sample_version,
- bool from_analyze)
+ndb_index_stat_wait_query(Ndb_index_stat *st,
+ const Ndb_index_stat_snap &snap)
{
- DBUG_ENTER("ndb_index_stat_wait");
+ DBUG_ENTER("ndb_index_stat_wait_query");
Ndb_index_stat_glob &glob= ndb_index_stat_glob;
pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
@@ -2522,24 +2647,16 @@ ndb_index_stat_wait(Ndb_index_stat *st,
int ret= 0;
if (count == 0)
{
- if (!from_analyze)
- {
- glob.wait_stats++;
- glob.query_count++;
- }
- else
+ glob.wait_stats++;
+ glob.query_count++;
+ if (st->lt == Ndb_index_stat::LT_Error)
{
- glob.wait_update++;
- glob.analyze_count++;
- }
- if (st->lt == Ndb_index_stat::LT_Error && !from_analyze)
- {
- err= Ndb_index_stat_error_HAS_ERROR;
+ err= NdbIndexStat::MyHasError;
break;
}
ndb_index_stat_clear_error(st);
}
- if (st->no_stats && !from_analyze)
+ if (st->no_stats)
{
/* Have detected no stats now or before */
err= NdbIndexStat::NoIndexStats;
@@ -2550,16 +2667,29 @@ ndb_index_stat_wait(Ndb_index_stat *st,
{
/* A new error has occured */
err= st->error.code;
- if (!from_analyze)
- glob.query_error++;
- else
- glob.analyze_error++;
+ glob.query_error++;
+ break;
+ }
+ /* Query waits for any samples */
+ if (st->sample_version > 0)
+ break;
+ /*
+ Try to detect changes behind our backs. Should really not
+ happen but make sure.
+ */
+ if (st->load_time != snap.load_time ||
+ st->sample_version != snap.sample_version)
+ {
+ err= NdbIndexStat::NoIndexStats;
break;
}
- if (st->sample_version > sample_version)
+ if (st->abort_request)
+ {
+ err= NdbIndexStat::MyAbortReq;
break;
+ }
count++;
- DBUG_PRINT("index_stat", ("st %s wait count:%u",
+ DBUG_PRINT("index_stat", ("st %s wait_query count:%u",
st->id, count));
pthread_mutex_lock(&ndb_index_stat_thread.LOCK);
ndb_index_stat_waiter= true;
@@ -2575,25 +2705,93 @@ ndb_index_stat_wait(Ndb_index_stat *st,
break;
}
}
- if (!from_analyze)
+ assert(glob.wait_stats != 0);
+ glob.wait_stats--;
+ pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
+ if (err != 0)
{
- assert(glob.wait_stats != 0);
- glob.wait_stats--;
+ DBUG_PRINT("index_stat", ("st %s wait_query error: %d",
+ st->id, err));
+ DBUG_RETURN(err);
}
- else
+ DBUG_PRINT("index_stat", ("st %s wait_query ok: sample_version %u -> %u",
+ st->id, snap.sample_version, st->sample_version));
+ DBUG_RETURN(0);
+}
+
+int
+ndb_index_stat_wait_analyze(Ndb_index_stat *st,
+ const Ndb_index_stat_snap &snap)
+{
+ DBUG_ENTER("ndb_index_stat_wait_analyze");
+
+ Ndb_index_stat_glob &glob= ndb_index_stat_glob;
+ pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
+ int err= 0;
+ uint count= 0;
+ struct timespec abstime;
+ while (true)
{
- assert(glob.wait_update != 0);
- glob.wait_update--;
+ int ret= 0;
+ if (count == 0)
+ {
+ glob.wait_update++;
+ glob.analyze_count++;
+ ndb_index_stat_clear_error(st);
+ }
+ if (st->error.code != 0)
+ {
+ /* A new error has occured */
+ err= st->error.code;
+ glob.analyze_error++;
+ break;
+ }
+ /* Analyze waits for newer samples */
+ if (st->sample_version > snap.sample_version)
+ break;
+ /*
+ Try to detect changes behind our backs. If another process
+ deleted stats, an analyze here could wait forever.
+ */
+ if (st->load_time != snap.load_time ||
+ st->sample_version != snap.sample_version)
+ {
+ err= NdbIndexStat::AlienUpdate;
+ break;
+ }
+ if (st->abort_request)
+ {
+ err= NdbIndexStat::MyAbortReq;
+ break;
+ }
+ count++;
+ DBUG_PRINT("index_stat", ("st %s wait_analyze count:%u",
+ st->id, count));
+ pthread_mutex_lock(&ndb_index_stat_thread.LOCK);
+ ndb_index_stat_waiter= true;
+ pthread_cond_signal(&ndb_index_stat_thread.COND);
+ pthread_mutex_unlock(&ndb_index_stat_thread.LOCK);
+ set_timespec(abstime, 1);
+ ret= pthread_cond_timedwait(&ndb_index_stat_thread.stat_cond,
+ &ndb_index_stat_thread.stat_mutex,
+ &abstime);
+ if (ret != 0 && ret != ETIMEDOUT)
+ {
+ err= ret;
+ break;
+ }
}
+ assert(glob.wait_update != 0);
+ glob.wait_update--;
pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
if (err != 0)
{
- DBUG_PRINT("index_stat", ("st %s wait error: %d",
+ DBUG_PRINT("index_stat", ("st %s wait_analyze error: %d",
st->id, err));
DBUG_RETURN(err);
}
- DBUG_PRINT("index_stat", ("st %s wait ok: sample_version %u -> %u",
- st->id, sample_version, st->sample_version));
+ DBUG_PRINT("index_stat", ("st %s wait_analyze ok: sample_version %u -> %u",
+ st->id, snap.sample_version, st->sample_version));
DBUG_RETURN(0);
}
@@ -2618,37 +2816,51 @@ ha_ndbcluster::ndb_index_stat_query(uint
compute_index_bounds(ib, key_info, min_key, max_key, from);
ib.range_no= 0;
+ Ndb_index_stat_snap snap;
Ndb_index_stat *st=
- ndb_index_stat_get_share(m_share, index, m_table, err, true, false);
+ ndb_index_stat_get_share(m_share, index, m_table, snap, err, true, false);
if (st == 0)
DBUG_RETURN(err);
+ /* Now holding reference to st */
- /* 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);
- assert(st->sample_version != 0);
-
- uint8 bound_lo_buffer[NdbIndexStat::BoundBufferBytes];
- uint8 bound_hi_buffer[NdbIndexStat::BoundBufferBytes];
- NdbIndexStat::Bound bound_lo(st->is, bound_lo_buffer);
- NdbIndexStat::Bound bound_hi(st->is, bound_hi_buffer);
- NdbIndexStat::Range range(bound_lo, bound_hi);
-
- const NdbRecord* key_record= data.ndb_record_key;
- if (st->is->convert_range(range, key_record, &ib) == -1)
- {
- ndb_index_stat_error(st, "convert_range", __LINE__);
- DBUG_RETURN(st->error.code);
- }
- if (st->is->query_stat(range, stat) == -1)
+ do
{
- /* Invalid cache - should remove the entry */
- ndb_index_stat_error(st, "query_stat", __LINE__);
- DBUG_RETURN(st->error.code);
+ err= ndb_index_stat_wait_query(st, snap);
+ if (err != 0)
+ break;
+ assert(st->sample_version != 0);
+ uint8 bound_lo_buffer[NdbIndexStat::BoundBufferBytes];
+ uint8 bound_hi_buffer[NdbIndexStat::BoundBufferBytes];
+ NdbIndexStat::Bound bound_lo(st->is, bound_lo_buffer);
+ NdbIndexStat::Bound bound_hi(st->is, bound_hi_buffer);
+ NdbIndexStat::Range range(bound_lo, bound_hi);
+
+ const NdbRecord* key_record= data.ndb_record_key;
+ if (st->is->convert_range(range, key_record, &ib) == -1)
+ {
+ pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
+ ndb_index_stat_error(st, 1, "convert_range", __LINE__);
+ err= st->client_error.code;
+ pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
+ break;
+ }
+ if (st->is->query_stat(range, stat) == -1)
+ {
+ /* Invalid cache - should remove the entry */
+ pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
+ ndb_index_stat_error(st, 1, "query_stat", __LINE__);
+ err= st->client_error.code;
+ pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
+ break;
+ }
}
+ while (0);
- DBUG_RETURN(0);
+ /* Release reference to st */
+ pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
+ ndb_index_stat_ref_count(st, false);
+ pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
+ DBUG_RETURN(err);
}
int
@@ -2720,50 +2932,62 @@ ha_ndbcluster::ndb_index_stat_analyze(Nd
{
DBUG_ENTER("ha_ndbcluster::ndb_index_stat_analyze");
- struct {
- uint sample_version;
- uint error_count;
- } old[MAX_INDEXES];
-
- int err= 0;
- uint i;
+ struct Req {
+ Ndb_index_stat *st;
+ Ndb_index_stat_snap snap;
+ int err;
+ Req() { st= 0; err= 0; }
+ };
+ Req req[MAX_INDEXES];
/* Force stats update on each index */
- for (i= 0; i < inx_count; i++)
+ for (uint i= 0; i < inx_count; i++)
{
+ Req &r= req[i];
uint inx= inx_list[i];
const NDB_INDEX_DATA &data= m_index[inx];
const NDBINDEX *index= data.index;
DBUG_PRINT("index_stat", ("force update: %s", index->getName()));
- Ndb_index_stat *st=
- ndb_index_stat_get_share(m_share, index, m_table, err, true, true);
- if (st == 0)
- DBUG_RETURN(err);
-
- old[i].sample_version= st->sample_version;
- old[i].error_count= st->error_count;
+ r.st=
+ ndb_index_stat_get_share(m_share, index, m_table, r.snap, r.err, true, true);
+ assert((r.st != 0) == (r.err == 0));
+ /* Now holding reference to r.st if r.err == 0 */
}
- /* Wait for each update (or error) */
- for (i = 0; i < inx_count; i++)
+ /* Wait for each update */
+ for (uint i = 0; i < inx_count; i++)
{
+ Req &r= req[i];
uint inx= inx_list[i];
const NDB_INDEX_DATA &data= m_index[inx];
const NDBINDEX *index= data.index;
- DBUG_PRINT("index_stat", ("wait for update: %s", index->getName()));
+ (void)index; // USED
- Ndb_index_stat *st=
- ndb_index_stat_get_share(m_share, index, m_table, err, false, false);
- if (st == 0)
- DBUG_RETURN(err);
+ if (r.err == 0)
+ {
+ DBUG_PRINT("index_stat", ("wait for update: %s", index->getName()));
+ r.err=ndb_index_stat_wait_analyze(r.st, r.snap);
+ /* Release reference to r.st */
+ pthread_mutex_lock(&ndb_index_stat_thread.stat_mutex);
+ ndb_index_stat_ref_count(r.st, false);
+ pthread_mutex_unlock(&ndb_index_stat_thread.stat_mutex);
+ }
+ }
- err= ndb_index_stat_wait(st, old[i].sample_version, true);
- if (err != 0)
- DBUG_RETURN(err);
+ /* Return first error if any */
+ int err= 0;
+ for (uint i= 0; i < inx_count; i++)
+ {
+ Req &r= req[i];
+ if (r.err != 0)
+ {
+ err= r.err;
+ break;
+ }
}
- DBUG_RETURN(0);
+ DBUG_RETURN(err);
}
#endif
=== modified file 'sql/ha_ndb_index_stat.h'
--- a/sql/ha_ndb_index_stat.h 2011-11-22 08:56:11 +0000
+++ b/sql/ha_ndb_index_stat.h 2011-12-18 12:20:44 +0000
@@ -40,10 +40,10 @@ public:
pthread_cond_t COND;
pthread_cond_t COND_ready;
- /* protect entry lists where needed */
- pthread_mutex_t list_mutex;
-
- /* protect and signal changes in stats entries */
+ /*
+ protect stats entry lists where needed
+ protect and signal changes in stats entries
+ */
pthread_mutex_t stat_mutex;
pthread_cond_t stat_cond;
@@ -82,5 +82,8 @@ compute_index_bounds(NdbIndexScanOperati
/* request on stats entry with recent error was ignored */
#define Ndb_index_stat_error_HAS_ERROR 9003
+
+/* stats thread aborted request on stats entry */
+#define Ndb_index_stat_error_ABORT_REQUEST 9004
#endif
=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc 2011-12-09 19:42:02 +0000
+++ b/sql/ha_ndbcluster.cc 2011-12-18 12:19:55 +0000
@@ -1240,7 +1240,9 @@ void ha_ndbcluster::set_rec_per_key()
/* no stats is not unexpected error */
err != NdbIndexStat::NoIndexStats &&
/* warning was printed at first error */
- err != Ndb_index_stat_error_HAS_ERROR)
+ err != NdbIndexStat::MyHasError &&
+ /* stats thread aborted request */
+ err != NdbIndexStat::MyAbortReq)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_CANT_GET_STAT, /* pun? */
@@ -12698,7 +12700,9 @@ ha_ndbcluster::records_in_range(uint inx
/* no stats is not unexpected error */
err != NdbIndexStat::NoIndexStats &&
/* warning was printed at first error */
- err != Ndb_index_stat_error_HAS_ERROR)
+ err != NdbIndexStat::MyHasError &&
+ /* stats thread aborted request */
+ err != NdbIndexStat::MyAbortReq)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_CANT_GET_STAT, /* pun? */
=== modified file 'storage/ndb/include/ndbapi/NdbIndexStat.hpp'
--- a/storage/ndb/include/ndbapi/NdbIndexStat.hpp 2011-08-11 17:11:30 +0000
+++ b/storage/ndb/include/ndbapi/NdbIndexStat.hpp 2011-12-18 12:19:55 +0000
@@ -103,7 +103,16 @@ public:
HaveSysTables = 4244, // create error if all sys tables exist
NoSysEvents = 4710,
BadSysEvents = BadSysTables,
- HaveSysEvents = 746
+ HaveSysEvents = 746,
+ /*
+ * Following are for mysqld. Most are consumed by mysqld itself
+ * and should therefore not be seen by clients.
+ */
+ MyNotAllow = 4721, // stats thread not open for requests
+ MyNotFound = 4722, // stats entry unexpectedly not found
+ MyHasError = 4723, // request ignored due to recent error
+ MyAbortReq = 4724, // request aborted by stats thread
+ AlienUpdate = 4725 // somebody else messed with stats
};
/*
@@ -179,6 +188,7 @@ public:
Uint32 m_totalBytes; // total bytes memory used
Uint64 m_save_time; // microseconds to read stats into cache
Uint64 m_sort_time; // microseconds to sort the cache
+ Uint32 m_ref_count; // in use by query_stat
// end v4 fields
};
=== modified file 'storage/ndb/src/ndbapi/NdbIndexStat.cpp'
--- a/storage/ndb/src/ndbapi/NdbIndexStat.cpp 2011-08-31 10:53:27 +0000
+++ b/storage/ndb/src/ndbapi/NdbIndexStat.cpp 2011-12-15 12:19:18 +0000
@@ -369,6 +369,7 @@ NdbIndexStat::clean_cache()
void
NdbIndexStat::get_cache_info(CacheInfo& info, CacheType type) const
{
+ NdbMutex_Lock(m_impl.m_query_mutex);
const NdbIndexStatImpl::Cache* c = 0;
switch (type) {
case CacheBuild:
@@ -387,6 +388,7 @@ NdbIndexStat::get_cache_info(CacheInfo&
info.m_totalBytes = 0;
info.m_save_time = 0;
info.m_sort_time = 0;
+ info.m_ref_count = 0;
while (c != 0)
{
info.m_count += 1;
@@ -395,10 +397,12 @@ NdbIndexStat::get_cache_info(CacheInfo&
info.m_totalBytes += c->m_keyBytes + c->m_valueBytes + c->m_addrBytes;
info.m_save_time += c->m_save_time;
info.m_sort_time += c->m_sort_time;
+ info.m_ref_count += c->m_ref_count;
c = c->m_nextClean;
}
// build and query cache have at most one instance
require(type == CacheClean || info.m_count <= 1);
+ NdbMutex_Unlock(m_impl.m_query_mutex);
}
// read
=== modified file 'storage/ndb/src/ndbapi/NdbIndexStatImpl.cpp'
--- a/storage/ndb/src/ndbapi/NdbIndexStatImpl.cpp 2011-12-10 18:51:37 +0000
+++ b/storage/ndb/src/ndbapi/NdbIndexStatImpl.cpp 2011-12-18 12:21:13 +0000
@@ -23,6 +23,7 @@
#include <NdbSqlUtil.hpp>
#include <NdbRecord.hpp>
#include <NdbEventOperation.hpp>
+#include <NdbSleep.h>
#include "NdbIndexStatImpl.hpp"
#undef min
@@ -1460,6 +1461,8 @@ NdbIndexStatImpl::Cache::Cache()
// performance
m_save_time = 0;
m_sort_time = 0;
+ // in use by query_stat
+ m_ref_count = 0;
}
int
@@ -2002,6 +2005,21 @@ NdbIndexStatImpl::convert_range(Range& r
return -1;
}
}
+
+#ifdef VM_TRACE
+ {
+ const char* p = NdbEnv_GetEnv("NDB_INDEX_STAT_RANGE_ERROR", (char*)0, 0);
+ if (p != 0 && strchr("1Y", p[0]) != 0)
+ {
+ if (rand() % 10 == 0)
+ {
+ setError(InternalError, __LINE__, NdbIndexStat::InternalError);
+ return -1;
+ }
+ }
+ }
+#endif
+
return 0;
}
@@ -2033,23 +2051,41 @@ int
NdbIndexStatImpl::query_stat(const Range& range, Stat& stat)
{
NdbMutex_Lock(m_query_mutex);
- const Cache* cacheTmp = m_cacheQuery;
- NdbMutex_Unlock(m_query_mutex);
-
- if (unlikely(cacheTmp == 0))
+ if (unlikely(m_cacheQuery == 0))
{
+ NdbMutex_Unlock(m_query_mutex);
setError(UsageError, __LINE__);
return -1;
}
- const Cache& c = *cacheTmp;
+ const Cache& c = *m_cacheQuery;
if (unlikely(!c.m_valid))
{
+ NdbMutex_Unlock(m_query_mutex);
setError(InvalidCache, __LINE__);
return -1;
}
+ c.m_ref_count++;
+ NdbMutex_Unlock(m_query_mutex);
+
+#ifdef VM_TRACE
+ {
+ const char* p = NdbEnv_GetEnv("NDB_INDEX_STAT_SLOW_QUERY", (char*)0, 0);
+ if (p != 0 && strchr("1Y", p[0]) != 0)
+ {
+ int ms = 1 + rand() % 20;
+ NdbSleep_MilliSleep(ms);
+ }
+ }
+#endif
+ // clients run these in parallel
query_interpolate(c, range, stat);
query_normalize(c, stat.m_value);
+
+ NdbMutex_Lock(m_query_mutex);
+ assert(c.m_ref_count != 0);
+ c.m_ref_count--;
+ NdbMutex_Unlock(m_query_mutex);
return 0;
}
=== modified file 'storage/ndb/src/ndbapi/NdbIndexStatImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbIndexStatImpl.hpp 2011-09-19 08:13:58 +0000
+++ b/storage/ndb/src/ndbapi/NdbIndexStatImpl.hpp 2011-12-15 12:19:18 +0000
@@ -70,7 +70,7 @@ public:
Cache* m_cacheBuild;
Cache* m_cacheQuery;
Cache* m_cacheClean;
- // mutex for query cache switch, memory barrier would do
+ // mutex for query cache switch and reference count
NdbMutex* m_query_mutex;
NdbEventOperation* m_eventOp;
Mem* m_mem_handler;
@@ -185,6 +185,8 @@ public:
// performance
mutable Uint64 m_save_time;
mutable Uint64 m_sort_time;
+ // in use by query_stat
+ mutable uint m_ref_count;
Cache();
// pos is index < sampleCount, addr is offset in keyArray
uint get_keyaddr(uint pos) const;
=== modified file 'storage/ndb/src/ndbapi/ndberror.c'
--- a/storage/ndb/src/ndbapi/ndberror.c 2011-11-25 12:18:23 +0000
+++ b/storage/ndb/src/ndbapi/ndberror.c 2011-12-18 12:19:55 +0000
@@ -552,6 +552,11 @@ ErrorBundle ErrorCodes[] = {
{ 4718, DMEC, IE, "Index stats samples data or memory cache is invalid" },
{ 4719, DMEC, IE, "Index stats internal error" },
{ 4720, DMEC, AE, "Index stats sys tables " NDB_INDEX_STAT_PREFIX " partly missing or invalid" },
+ { 4721, DMEC, IE, "Mysqld: index stats thread not open for requests" },
+ { 4722, DMEC, IE, "Mysqld: index stats entry unexpectedly not found" },
+ { 4723, DMEC, AE, "Mysqld: index stats request ignored due to recent error" },
+ { 4724, DMEC, AE, "Mysqld: index stats request aborted by stats thread" },
+ { 4725, DMEC, AE, "Index stats were deleted by another process" },
/**
* Still uncategorized
=== modified file 'storage/ndb/tools/ndb_index_stat.cpp'
--- a/storage/ndb/tools/ndb_index_stat.cpp 2011-08-11 17:11:30 +0000
+++ b/storage/ndb/tools/ndb_index_stat.cpp 2011-12-15 15:13:59 +0000
@@ -211,7 +211,6 @@ doquery()
{
NdbIndexStat::Bound& b = (i == 0 ? b_lo : b_hi);
- bool strict = false;
if (ndb_rand() % 3 != 0)
{
if (ndb_rand() % 3 != 0)
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-5.1-telco-7.0 branch (pekka.nousiainen:4756) WL#4124 | Pekka Nousiainen | 19 Dec |