Commit 1e3cee75 authored by John Esmet's avatar John Esmet Committed by Yoni Fogel

close[t:4530] merging 4530 to main


git-svn-id: file:///svn/mysql/tokudb-engine/tokudb-engine@41124 c7de825b-a66e-492c-adef-691d508d4ae1
parent 88392312
......@@ -44,6 +44,28 @@ static const char *ha_tokudb_exts[] = {
NullS
};
// XXX 4530 get read or write locks on the key file array,
// so that functions not synchronized by mysql table locks
// don't race.
//
// ha_tokudb::info() does not take any table locks
// so it needs to grab a read lock. any other function writing
// to the key file array needs to grab a write lock.
static void share_key_file_rdlock(TOKUDB_SHARE * share)
{
rw_rdlock(&share->key_file_lock);
}
static void share_key_file_wrlock(TOKUDB_SHARE * share)
{
rw_wrlock(&share->key_file_lock);
}
static void share_key_file_unlock(TOKUDB_SHARE * share)
{
rw_unlock(&share->key_file_lock);
}
//
// This offset is calculated starting from AFTER the NULL bytes
//
......@@ -157,6 +179,8 @@ static TOKUDB_SHARE *get_share(const char *table_name, TABLE_SHARE* table_share)
}
thr_lock_init(&share->lock);
pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST);
// XXX 4530 initialize the key file lock
my_rwlock_init(&share->key_file_lock, 0);
my_rwlock_init(&share->num_DBs_lock, 0);
}
......@@ -5583,6 +5607,7 @@ void ha_tokudb::position(const uchar * record) {
int ha_tokudb::info(uint flag) {
TOKUDB_DBUG_ENTER("ha_tokudb::info %p %d %lld", this, flag, (long long) share->rows);
int error;
bool key_file_lock_taken = false;
DB_TXN* txn = NULL;
uint curr_num_DBs = table->s->keys + test(hidden_primary_key);
DB_BTREE_STAT64 dict_stats;
......@@ -5601,6 +5626,12 @@ int ha_tokudb::info(uint flag) {
error = db_env->txn_begin(db_env, NULL, &txn, DB_READ_UNCOMMITTED);
if (error) { goto cleanup; }
// XXX 4530 lock the key file lock for reading
share_key_file_rdlock(share);
key_file_lock_taken = true;
// we should always have a primary key
assert(share->file != NULL);
error = estimate_num_rows(share->file,&num_rows, txn);
if (error == 0) {
share->rows = num_rows;
......@@ -5648,8 +5679,20 @@ int ha_tokudb::info(uint flag) {
stats.mean_rec_length = stats.records ? (ulong)(stats.data_file_length/stats.records) : 0;
stats.index_file_length = 0;
// curr_num_DBs is the number of keys we have, according
// to the mysql layer. if drop index is running concurrently
// with info() (it can, because info does not take table locks),
// then it could be the case that one of the dbs was dropped
// and set to NULL before mysql was able to set table->s->keys
// accordingly.
//
// we should just ignore any DB * that is NULL.
//
// this solution is much simpler than trying to maintain an
// accurate number of valid keys at the handlerton layer.
for (uint i = 0; i < curr_num_DBs; i++) {
if (i == primary_key) {
// skip the primary key, skip dropped indexes
if (i == primary_key || share->key_file[i] == NULL) {
continue;
}
error = share->key_file[i]->stat64(
......@@ -5686,6 +5729,10 @@ int ha_tokudb::info(uint flag) {
}
error = 0;
cleanup:
// XXX 4530 unlock the key file lock if it was taken
if (key_file_lock_taken) {
share_key_file_unlock(share);
}
if (txn != NULL) {
commit_txn(txn, DB_TXN_NOSYNC);
txn = NULL;
......@@ -7564,10 +7611,12 @@ volatile int ha_tokudb_drop_indexes_wait = 0; // debug
int ha_tokudb::drop_indexes(TABLE *table_arg, uint *key_num, uint num_of_keys, DB_TXN* txn) {
TOKUDB_DBUG_ENTER("ha_tokudb::drop_indexes");
// XXX 4530 lock the key file lock for writing.
share_key_file_wrlock(share);
while (ha_tokudb_drop_indexes_wait) sleep(1); // debug
int error = 0;
for (uint i = 0; i < num_of_keys; i++) {
uint curr_index = key_num[i];
error = share->key_file[curr_index]->pre_acquire_fileops_lock(share->key_file[curr_index],txn);
......@@ -7594,6 +7643,8 @@ cleanup:
another transaction has accessed the table. \
To drop indexes, make sure no transactions touch the table.", share->table_name);
}
// XXX 4530 unlock the key file lock
share_key_file_unlock(share);
TOKUDB_DBUG_RETURN(error);
}
......@@ -7602,6 +7653,9 @@ To drop indexes, make sure no transactions touch the table.", share->table_name)
// Restores dropped indexes in case of error in error path of prepare_drop_index and alter_table_phase2
//
void ha_tokudb::restore_drop_indexes(TABLE *table_arg, uint *key_num, uint num_of_keys) {
// XXX 4530 lock the key file lock for writing
share_key_file_wrlock(share);
//
// reopen closed dictionaries
//
......@@ -7619,6 +7673,8 @@ void ha_tokudb::restore_drop_indexes(TABLE *table_arg, uint *key_num, uint num_o
assert(!r);
}
}
// XXX 4530 unlock the key file lock
share_key_file_unlock(share);
}
volatile int ha_tokudb_prepare_drop_index_wait = 0; //debug
......@@ -7878,6 +7934,9 @@ int ha_tokudb::delete_all_rows() {
uint curr_num_DBs = 0;
DB_TXN* txn = NULL;
// XXX 4530 lock the key file array for writing
share_key_file_wrlock(share);
error = db_env->txn_begin(db_env, 0, &txn, 0);
if (error) { goto cleanup; }
......@@ -7922,9 +7981,9 @@ cleanup:
}
if (error == DB_LOCK_NOTGRANTED && ((tokudb_debug & TOKUDB_DEBUG_HIDE_DDL_LOCK_ERRORS) == 0)) {
sql_print_error("Could not truncate table %s because \
another transaction has accessed the table. \
To truncate the table, make sure no transactions touch the table.", share->table_name);
sql_print_error("Could not truncate table %s because another transaction has accessed the \
table. To truncate the table, make sure no transactions touch the table.",
share->table_name);
}
//
// regardless of errors, need to reopen the DB's
......@@ -7952,6 +8011,8 @@ To truncate the table, make sure no transactions touch the table.", share->table
}
}
}
// XXX 4530 unlock the key file lock
share_key_file_unlock(share);
TOKUDB_DBUG_RETURN(error);
}
......
......@@ -64,6 +64,7 @@ typedef struct st_tokudb_share {
// key is hidden
//
DB *key_file[MAX_KEY +1];
rw_lock_t key_file_lock;
uint status, version, capabilities;
uint ref_length;
//
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment