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[] = { ...@@ -44,6 +44,28 @@ static const char *ha_tokudb_exts[] = {
NullS 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 // 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) ...@@ -157,6 +179,8 @@ static TOKUDB_SHARE *get_share(const char *table_name, TABLE_SHARE* table_share)
} }
thr_lock_init(&share->lock); thr_lock_init(&share->lock);
pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST); 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); my_rwlock_init(&share->num_DBs_lock, 0);
} }
...@@ -5583,6 +5607,7 @@ void ha_tokudb::position(const uchar * record) { ...@@ -5583,6 +5607,7 @@ void ha_tokudb::position(const uchar * record) {
int ha_tokudb::info(uint flag) { int ha_tokudb::info(uint flag) {
TOKUDB_DBUG_ENTER("ha_tokudb::info %p %d %lld", this, flag, (long long) share->rows); TOKUDB_DBUG_ENTER("ha_tokudb::info %p %d %lld", this, flag, (long long) share->rows);
int error; int error;
bool key_file_lock_taken = false;
DB_TXN* txn = NULL; DB_TXN* txn = NULL;
uint curr_num_DBs = table->s->keys + test(hidden_primary_key); uint curr_num_DBs = table->s->keys + test(hidden_primary_key);
DB_BTREE_STAT64 dict_stats; DB_BTREE_STAT64 dict_stats;
...@@ -5601,6 +5626,12 @@ int ha_tokudb::info(uint flag) { ...@@ -5601,6 +5626,12 @@ int ha_tokudb::info(uint flag) {
error = db_env->txn_begin(db_env, NULL, &txn, DB_READ_UNCOMMITTED); error = db_env->txn_begin(db_env, NULL, &txn, DB_READ_UNCOMMITTED);
if (error) { goto cleanup; } 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); error = estimate_num_rows(share->file,&num_rows, txn);
if (error == 0) { if (error == 0) {
share->rows = num_rows; share->rows = num_rows;
...@@ -5648,8 +5679,20 @@ int ha_tokudb::info(uint flag) { ...@@ -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.mean_rec_length = stats.records ? (ulong)(stats.data_file_length/stats.records) : 0;
stats.index_file_length = 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++) { 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; continue;
} }
error = share->key_file[i]->stat64( error = share->key_file[i]->stat64(
...@@ -5686,6 +5729,10 @@ int ha_tokudb::info(uint flag) { ...@@ -5686,6 +5729,10 @@ int ha_tokudb::info(uint flag) {
} }
error = 0; error = 0;
cleanup: 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) { if (txn != NULL) {
commit_txn(txn, DB_TXN_NOSYNC); commit_txn(txn, DB_TXN_NOSYNC);
txn = NULL; txn = NULL;
...@@ -7564,10 +7611,12 @@ volatile int ha_tokudb_drop_indexes_wait = 0; // debug ...@@ -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) { 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"); 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 while (ha_tokudb_drop_indexes_wait) sleep(1); // debug
int error = 0; int error = 0;
for (uint i = 0; i < num_of_keys; i++) { for (uint i = 0; i < num_of_keys; i++) {
uint curr_index = key_num[i]; uint curr_index = key_num[i];
error = share->key_file[curr_index]->pre_acquire_fileops_lock(share->key_file[curr_index],txn); error = share->key_file[curr_index]->pre_acquire_fileops_lock(share->key_file[curr_index],txn);
...@@ -7594,6 +7643,8 @@ cleanup: ...@@ -7594,6 +7643,8 @@ cleanup:
another transaction has accessed the table. \ another transaction has accessed the table. \
To drop indexes, make sure no transactions touch the table.", share->table_name); 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); TOKUDB_DBUG_RETURN(error);
} }
...@@ -7602,6 +7653,9 @@ To drop indexes, make sure no transactions touch the table.", share->table_name) ...@@ -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 // 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) { 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 // reopen closed dictionaries
// //
...@@ -7619,6 +7673,8 @@ void ha_tokudb::restore_drop_indexes(TABLE *table_arg, uint *key_num, uint num_o ...@@ -7619,6 +7673,8 @@ void ha_tokudb::restore_drop_indexes(TABLE *table_arg, uint *key_num, uint num_o
assert(!r); assert(!r);
} }
} }
// XXX 4530 unlock the key file lock
share_key_file_unlock(share);
} }
volatile int ha_tokudb_prepare_drop_index_wait = 0; //debug volatile int ha_tokudb_prepare_drop_index_wait = 0; //debug
...@@ -7878,6 +7934,9 @@ int ha_tokudb::delete_all_rows() { ...@@ -7878,6 +7934,9 @@ int ha_tokudb::delete_all_rows() {
uint curr_num_DBs = 0; uint curr_num_DBs = 0;
DB_TXN* txn = NULL; 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); error = db_env->txn_begin(db_env, 0, &txn, 0);
if (error) { goto cleanup; } if (error) { goto cleanup; }
...@@ -7921,11 +7980,11 @@ cleanup: ...@@ -7921,11 +7980,11 @@ cleanup:
} }
} }
if (error == DB_LOCK_NOTGRANTED && ((tokudb_debug & TOKUDB_DEBUG_HIDE_DDL_LOCK_ERRORS) == 0)) { if (error == DB_LOCK_NOTGRANTED && ((tokudb_debug & TOKUDB_DEBUG_HIDE_DDL_LOCK_ERRORS) == 0)) {
sql_print_error("Could not truncate table %s because \ sql_print_error("Could not truncate table %s because another transaction has accessed the \
another transaction has accessed the table. \ table. To truncate the table, make sure no transactions touch the table.",
To truncate the table, make sure no transactions touch the table.", share->table_name); share->table_name);
} }
// //
// regardless of errors, need to reopen the DB's // 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 ...@@ -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); TOKUDB_DBUG_RETURN(error);
} }
......
...@@ -64,6 +64,7 @@ typedef struct st_tokudb_share { ...@@ -64,6 +64,7 @@ typedef struct st_tokudb_share {
// key is hidden // key is hidden
// //
DB *key_file[MAX_KEY +1]; DB *key_file[MAX_KEY +1];
rw_lock_t key_file_lock;
uint status, version, capabilities; uint status, version, capabilities;
uint ref_length; 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