mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 13:02:28 +01:00
f77c05cb23
git-svn-id: file:///svn/mysql/tokudb-engine/tokudb-engine@48967 c7de825b-a66e-492c-adef-691d508d4ae1
196 lines
6.7 KiB
C++
196 lines
6.7 KiB
C++
#if TOKU_INCLUDE_ALTER_55
|
|
|
|
class ha_tokudb_add_index : public handler_add_index {
|
|
public:
|
|
DB_TXN *txn;
|
|
bool incremented_numDBs;
|
|
bool modified_DBs;
|
|
ha_tokudb_add_index(TABLE* table, KEY* key_info, uint num_of_keys, DB_TXN *txn, bool incremented_numDBs, bool modified_DBs) :
|
|
handler_add_index(table, key_info, num_of_keys), txn(txn), incremented_numDBs(incremented_numDBs), modified_DBs(modified_DBs) {
|
|
}
|
|
~ha_tokudb_add_index() {
|
|
}
|
|
};
|
|
|
|
volatile int ha_tokudb_add_index_wait = 0;
|
|
|
|
int
|
|
ha_tokudb::add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys, handler_add_index **add) {
|
|
TOKUDB_DBUG_ENTER("ha_tokudb::add_index");
|
|
while (ha_tokudb_add_index_wait) sleep(1); // debug
|
|
|
|
int error;
|
|
bool incremented_numDBs = false;
|
|
bool modified_DBs = false;
|
|
|
|
// transaction is created in prepare_for_alter
|
|
DB_TXN* txn = transaction;
|
|
|
|
error = tokudb_add_index(
|
|
table_arg,
|
|
key_info,
|
|
num_of_keys,
|
|
txn,
|
|
&incremented_numDBs,
|
|
&modified_DBs
|
|
);
|
|
if (error) { goto cleanup; }
|
|
|
|
cleanup:
|
|
DBUG_EXECUTE_IF("add_index_fail", {
|
|
error = 1;
|
|
});
|
|
if (error) {
|
|
if (txn) {
|
|
restore_add_index(table_arg, num_of_keys, incremented_numDBs, modified_DBs);
|
|
}
|
|
} else {
|
|
*add = new ha_tokudb_add_index(table_arg, key_info, num_of_keys, txn, incremented_numDBs, modified_DBs);
|
|
}
|
|
TOKUDB_DBUG_RETURN(error);
|
|
}
|
|
|
|
volatile int ha_tokudb_final_add_index_wait = 0;
|
|
|
|
int
|
|
ha_tokudb::final_add_index(handler_add_index *add_arg, bool commit) {
|
|
TOKUDB_DBUG_ENTER("ha_tokudb::final_add_index");
|
|
while (ha_tokudb_final_add_index_wait) sleep(1); // debug
|
|
|
|
// extract the saved state variables
|
|
ha_tokudb_add_index *add = static_cast<class ha_tokudb_add_index*>(add_arg);
|
|
bool incremented_numDBs = add->incremented_numDBs;
|
|
bool modified_DBs = add->modified_DBs;
|
|
TABLE *table = add->table;
|
|
uint num_of_keys = add->num_of_keys;
|
|
delete add;
|
|
|
|
int error = 0;
|
|
|
|
DBUG_EXECUTE_IF("final_add_index_fail", {
|
|
error = 1;
|
|
});
|
|
// at this point, the metadata lock ensures that the
|
|
// newly created indexes cannot be modified,
|
|
// regardless of whether the add index was hot.
|
|
// Because a subsequent drop index may cause an
|
|
// error requireing us to abort the transaction,
|
|
// we prematurely close the added indexes, regardless
|
|
// of whether we are committing or aborting.
|
|
restore_add_index(table, num_of_keys, incremented_numDBs, modified_DBs);
|
|
// transaction does not need to be committed,
|
|
// we depend on MySQL to rollback the transaction
|
|
// by calling tokudb_rollback
|
|
|
|
TOKUDB_DBUG_RETURN(error);
|
|
}
|
|
|
|
volatile int ha_tokudb_prepare_drop_index_wait = 0; //debug
|
|
|
|
//
|
|
// Prepares to drop indexes to the table. For each value, i, in the array key_num,
|
|
// table->key_info[i] is a key that is to be dropped.
|
|
// ***********NOTE*******************
|
|
// Although prepare_drop_index is supposed to just get the DB's ready for removal,
|
|
// and not actually do the removal, we are doing it here and not in final_drop_index
|
|
// For the flags we expose in alter_table_flags, namely xxx_NO_WRITES, this is allowed
|
|
// Changes for "future-proofing" this so that it works when we have the equivalent flags
|
|
// that are not NO_WRITES are not worth it at the moments
|
|
// Parameters:
|
|
// [in] table_arg - table that is being modified, seems to be identical to this->table
|
|
// [in] key_num - array of indexes that specify which keys of the array table->key_info
|
|
// are to be dropped
|
|
// num_of_keys - size of array, key_num
|
|
// Returns:
|
|
// 0 on success, error otherwise
|
|
//
|
|
int
|
|
ha_tokudb::prepare_drop_index(TABLE *table_arg, uint *key_num, uint num_of_keys) {
|
|
TOKUDB_DBUG_ENTER("ha_tokudb::prepare_drop_index");
|
|
while (ha_tokudb_prepare_drop_index_wait) sleep(1); // debug
|
|
|
|
DB_TXN *txn = transaction;
|
|
assert(txn);
|
|
int error = drop_indexes(table_arg, key_num, num_of_keys, table_arg->key_info, txn);
|
|
DBUG_EXECUTE_IF("prepare_drop_index_fail", {
|
|
error = 1;
|
|
});
|
|
|
|
TOKUDB_DBUG_RETURN(error);
|
|
}
|
|
|
|
volatile int ha_tokudb_final_drop_index_wait = 0; // debug
|
|
|
|
// ***********NOTE*******************
|
|
// Although prepare_drop_index is supposed to just get the DB's ready for removal,
|
|
// and not actually do the removal, we are doing it here and not in final_drop_index
|
|
// For the flags we expose in alter_table_flags, namely xxx_NO_WRITES, this is allowed
|
|
// Changes for "future-proofing" this so that it works when we have the equivalent flags
|
|
// that are not NO_WRITES are not worth it at the moments, therefore, we can make
|
|
// this function just return
|
|
int
|
|
ha_tokudb::final_drop_index(TABLE *table_arg) {
|
|
TOKUDB_DBUG_ENTER("ha_tokudb::final_drop_index");
|
|
while (ha_tokudb_final_drop_index_wait) sleep(1); // debug
|
|
|
|
int error = 0;
|
|
DBUG_EXECUTE_IF("final_drop_index_fail", {
|
|
error = 1;
|
|
});
|
|
TOKUDB_DBUG_RETURN(error);
|
|
}
|
|
|
|
bool
|
|
ha_tokudb::is_alter_table_hot() {
|
|
TOKUDB_DBUG_ENTER("is_alter_table_hot");
|
|
bool is_hot = false;
|
|
THD *thd = ha_thd();
|
|
if (get_create_index_online(thd) && thd_sql_command(thd)== SQLCOM_CREATE_INDEX) {
|
|
// this code must match the logic in ::store_lock for hot indexing
|
|
rw_rdlock(&share->num_DBs_lock);
|
|
if (share->num_DBs == (table->s->keys + test(hidden_primary_key))) {
|
|
is_hot = true;
|
|
}
|
|
rw_unlock(&share->num_DBs_lock);
|
|
}
|
|
TOKUDB_DBUG_RETURN(is_hot);
|
|
}
|
|
|
|
int
|
|
ha_tokudb::new_alter_table_frm_data(const uchar *frm_data, size_t frm_len) {
|
|
return write_frm_data(frm_data, frm_len);
|
|
}
|
|
|
|
void
|
|
ha_tokudb::prepare_for_alter() {
|
|
TOKUDB_DBUG_ENTER("prepare_for_alter");
|
|
|
|
// this is here because mysql commits the transaction before prepare_for_alter is called.
|
|
// we need a transaction to add indexes, drop indexes, and write the new frm data, so we
|
|
// create one. this transaction will be retired by mysql alter table when it commits
|
|
//
|
|
// if we remove the commit before prepare_for_alter, then this is not needed.
|
|
transaction = NULL;
|
|
THD *thd = ha_thd();
|
|
tokudb_trx_data *trx = (tokudb_trx_data *) thd_data_get(thd, tokudb_hton->slot);
|
|
assert(trx);
|
|
// for partitioned tables, a transaction may already exist,
|
|
// as we call prepare_for_alter on all partitions
|
|
if (!trx->sub_sp_level) {
|
|
int error = create_txn(thd, trx);
|
|
assert(error == 0);
|
|
assert(thd->in_sub_stmt == 0);
|
|
}
|
|
transaction = trx->sub_sp_level;
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
bool
|
|
ha_tokudb::try_hot_alter_table() {
|
|
TOKUDB_DBUG_ENTER("try_hot_alter_table");
|
|
THD *thd = ha_thd();
|
|
bool disable_hot_alter = get_disable_hot_alter(thd);
|
|
DBUG_RETURN(!disable_hot_alter);
|
|
}
|
|
|
|
#endif
|