Commit 1274bb77 authored by Eugene Kosov's avatar Eugene Kosov

MDEV-25223 change fil_system_t::space_list and fil_system_t::named_spaces from UT_LIST to ilist

Mostly a refactoring. Also, debug functions were added for ease of life while debugging
parent cb545f11
......@@ -588,36 +588,20 @@ static dberr_t enumerate_ibd_files(process_single_tablespace_func_t callback);
/* ======== Datafiles iterator ======== */
struct datafiles_iter_t {
fil_space_t *space;
fil_node_t *node;
ibool started;
pthread_mutex_t mutex;
space_list_t::iterator space = fil_system.space_list.end();
fil_node_t *node = nullptr;
bool started = false;
std::mutex mutex;
};
/* ======== Datafiles iterator ======== */
static
datafiles_iter_t *
datafiles_iter_new()
{
datafiles_iter_t *it;
it = static_cast<datafiles_iter_t *>(malloc(sizeof(datafiles_iter_t)));
pthread_mutex_init(&it->mutex, NULL);
it->space = NULL;
it->node = NULL;
it->started = FALSE;
return it;
}
static
fil_node_t *
datafiles_iter_next(datafiles_iter_t *it)
{
fil_node_t *new_node;
pthread_mutex_lock(&it->mutex);
std::lock_guard<std::mutex> _(it->mutex);
if (it->node == NULL) {
if (it->started)
......@@ -629,34 +613,25 @@ datafiles_iter_next(datafiles_iter_t *it)
goto end;
}
it->space = (it->space == NULL) ?
UT_LIST_GET_FIRST(fil_system.space_list) :
UT_LIST_GET_NEXT(space_list, it->space);
it->space = (it->space == fil_system.space_list.end()) ?
fil_system.space_list.begin() :
std::next(it->space);
while (it->space != NULL &&
while (it->space != fil_system.space_list.end() &&
(it->space->purpose != FIL_TYPE_TABLESPACE ||
UT_LIST_GET_LEN(it->space->chain) == 0))
it->space = UT_LIST_GET_NEXT(space_list, it->space);
if (it->space == NULL)
++it->space;
if (it->space == fil_system.space_list.end())
goto end;
it->node = UT_LIST_GET_FIRST(it->space->chain);
end:
new_node = it->node;
pthread_mutex_unlock(&it->mutex);
return new_node;
}
static
void
datafiles_iter_free(datafiles_iter_t *it)
{
pthread_mutex_destroy(&it->mutex);
free(it);
}
#ifndef DBUG_OFF
struct dbug_thread_param_t
{
......@@ -750,18 +725,15 @@ static void dbug_start_query_thread(
void mdl_lock_all()
{
mdl_lock_init();
datafiles_iter_t *it = datafiles_iter_new();
if (!it)
return;
datafiles_iter_t it;
while (fil_node_t *node = datafiles_iter_next(it)){
while (fil_node_t *node = datafiles_iter_next(&it)) {
if (fil_is_user_tablespace_id(node->space->id)
&& check_if_skip_table(node->space->name))
continue;
mdl_lock_table(node->space->id);
}
datafiles_iter_free(it);
}
......@@ -4441,11 +4413,7 @@ static bool xtrabackup_backup_func()
"Waiting for table metadata lock", 0, 0););
}
datafiles_iter_t *it = datafiles_iter_new();
if (it == NULL) {
msg("mariabackup: Error: datafiles_iter_new() failed.");
goto fail;
}
datafiles_iter_t it;
/* Create data copying threads */
data_threads = (data_thread_ctxt_t *)
......@@ -4454,7 +4422,7 @@ static bool xtrabackup_backup_func()
pthread_mutex_init(&count_mutex, NULL);
for (i = 0; i < (uint) xtrabackup_parallel; i++) {
data_threads[i].it = it;
data_threads[i].it = &it;
data_threads[i].num = i+1;
data_threads[i].count = &count;
data_threads[i].count_mutex = &count_mutex;
......@@ -4475,7 +4443,6 @@ static bool xtrabackup_backup_func()
pthread_mutex_destroy(&count_mutex);
free(data_threads);
datafiles_iter_free(it);
}
bool ok = backup_start(corrupted_pages);
......@@ -4629,10 +4596,8 @@ void backup_fix_ddl(CorruptedPages &corrupted_pages)
// Load and copy new tables.
// Close all datanodes first, reload only new tables.
std::vector<fil_node_t *> all_nodes;
datafiles_iter_t *it = datafiles_iter_new();
if (!it)
return;
while (fil_node_t *node = datafiles_iter_next(it)) {
datafiles_iter_t it;
while (fil_node_t *node = datafiles_iter_next(&it)) {
all_nodes.push_back(node);
}
for (size_t i = 0; i < all_nodes.size(); i++) {
......@@ -4646,7 +4611,6 @@ void backup_fix_ddl(CorruptedPages &corrupted_pages)
}
fil_space_free(n->space->id, false);
}
datafiles_iter_free(it);
DBUG_EXECUTE_IF("check_mdl_lock_works", DBUG_ASSERT(new_tables.size() == 0););
for (std::set<std::string>::iterator iter = new_tables.begin();
......@@ -4657,11 +4621,9 @@ void backup_fix_ddl(CorruptedPages &corrupted_pages)
xb_load_single_table_tablespace(*iter, false);
}
it = datafiles_iter_new();
if (!it)
return;
datafiles_iter_t it2;
while (fil_node_t *node = datafiles_iter_next(it)) {
while (fil_node_t *node = datafiles_iter_next(&it2)) {
fil_space_t * space = node->space;
if (!fil_is_user_tablespace_id(space->id))
continue;
......@@ -4670,8 +4632,6 @@ void backup_fix_ddl(CorruptedPages &corrupted_pages)
xtrabackup_copy_datafile(node, 0, dest_name.c_str(), wf_write_through,
corrupted_pages);
}
datafiles_iter_free(it);
}
/* ================= prepare ================= */
......@@ -4787,10 +4747,8 @@ xb_space_create_file(
static fil_space_t* fil_space_get_by_name(const char* name)
{
mysql_mutex_assert_owner(&fil_system.mutex);
for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list);
space != NULL;
space = UT_LIST_GET_NEXT(space_list, space))
if (!strcmp(space->name, name)) return space;
for (fil_space_t& space :fil_system.space_list)
if (!strcmp(space.name, name)) return &space;
return NULL;
}
......
......@@ -75,8 +75,10 @@ template <class T, class Tag= void> class ilist
typedef T *pointer;
typedef T &reference;
Iterator(ListNode *node) noexcept : node_(node)
{ DBUG_ASSERT(node_ != nullptr); }
explicit Iterator(ListNode *node) noexcept : node_(node)
{
DBUG_ASSERT(node_ != nullptr);
}
Iterator &operator++() noexcept
{
......@@ -193,7 +195,7 @@ template <class T, class Tag= void> class ilist
curr->next= nullptr;
#endif
return next;
return Iterator(next);
}
void push_back(reference value) noexcept { insert(end(), value); }
......
......@@ -114,7 +114,6 @@ void fil_space_crypt_init()
{
pthread_cond_init(&fil_crypt_throttle_sleep_cond, nullptr);
mysql_mutex_init(0, &crypt_stat_mutex, nullptr);
memset(&crypt_stat, 0, sizeof crypt_stat);
}
/*********************************************************************
......@@ -1121,25 +1120,21 @@ static bool fil_crypt_start_encrypting_space(fil_space_t* space)
/** State of a rotation thread */
struct rotate_thread_t {
explicit rotate_thread_t(uint no) {
memset(this, 0, sizeof(* this));
thread_no = no;
first = true;
estimated_max_iops = 20;
}
uint thread_no;
bool first; /*!< is position before first space */
fil_space_t* space; /*!< current space or NULL */
uint32_t offset; /*!< current page number */
ulint batch; /*!< #pages to rotate */
uint min_key_version_found;/*!< min key version found but not rotated */
lsn_t end_lsn; /*!< max lsn when rotating this space */
uint estimated_max_iops; /*!< estimation of max iops */
uint allocated_iops; /*!< allocated iops */
ulint cnt_waited; /*!< #times waited during this slot */
uintmax_t sum_waited_us; /*!< wait time during this slot */
explicit rotate_thread_t(uint no) : thread_no(no) {}
uint thread_no;
bool first = true; /*!< is position before first space */
space_list_t::iterator space
= fil_system.space_list.end();/*!< current space or .end() */
uint32_t offset = 0; /*!< current page number */
ulint batch = 0; /*!< #pages to rotate */
uint min_key_version_found = 0; /*!< min key version found but not rotated */
lsn_t end_lsn = 0; /*!< max lsn when rotating this space */
uint estimated_max_iops = 20;/*!< estimation of max iops */
uint allocated_iops = 0; /*!< allocated iops */
ulint cnt_waited = 0; /*!< #times waited during this slot */
uintmax_t sum_waited_us = 0; /*!< wait time during this slot */
fil_crypt_stat_t crypt_stat; // statistics
......@@ -1177,7 +1172,7 @@ fil_crypt_space_needs_rotation(
{
mysql_mutex_assert_not_owner(&fil_crypt_threads_mutex);
fil_space_t* space = state->space;
fil_space_t* space = &*state->space;
ut_ad(space->referenced());
ut_ad(space->purpose == FIL_TYPE_TABLESPACE);
......@@ -1268,7 +1263,10 @@ fil_crypt_update_total_stat(
mysql_mutex_unlock(&crypt_stat_mutex);
// make new estimate "current" estimate
memset(&state->crypt_stat, 0, sizeof(state->crypt_stat));
state->crypt_stat.pages_read_from_cache = 0;
state->crypt_stat.pages_read_from_disk = 0;
state->crypt_stat.pages_modified = 0;
state->crypt_stat.pages_flushed = 0;
// record our old (current) estimate
state->crypt_stat.estimated_iops = state->estimated_max_iops;
}
......@@ -1432,10 +1430,10 @@ inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space,
{
mysql_mutex_assert_owner(&mutex);
sized_ilist<fil_space_t, rotation_list_tag_t>::iterator it=
space && space->is_in_rotation_list ? space : rotation_list.begin();
const sized_ilist<fil_space_t, rotation_list_tag_t>::iterator end=
rotation_list.end();
auto it= space && space->is_in_rotation_list
? sized_ilist<fil_space_t, rotation_list_tag_t>::iterator(space)
: rotation_list.begin();
const auto end= rotation_list.end();
if (space)
{
......@@ -1485,25 +1483,29 @@ encryption parameters were changed
@return the next tablespace
@retval fil_system.temp_space if there is no work to do
@retval nullptr upon reaching the end of the iteration */
inline fil_space_t *fil_space_t::next(fil_space_t *space, bool recheck,
bool encrypt)
space_list_t::iterator fil_space_t::next(space_list_t::iterator space,
bool recheck, bool encrypt)
{
mysql_mutex_lock(&fil_system.mutex);
if (!srv_fil_crypt_rotate_key_age)
space= fil_system.keyrotate_next(space, recheck, encrypt);
{
space= space_list_t::iterator(fil_system.keyrotate_next(
space != fil_system.space_list.end() ? &*space : nullptr, recheck,
encrypt));
}
else
{
if (!space)
space= UT_LIST_GET_FIRST(fil_system.space_list);
if (space == fil_system.space_list.end())
space= fil_system.space_list.begin();
else
{
/* Move on to the next fil_space_t */
space->release();
space= UT_LIST_GET_NEXT(space_list, space);
++space;
}
for (; space; space= UT_LIST_GET_NEXT(space_list, space))
for (; space != fil_system.space_list.end(); ++space)
{
if (space->purpose != FIL_TYPE_TABLESPACE)
continue;
......@@ -1533,9 +1535,9 @@ static bool fil_crypt_find_space_to_rotate(
/* we need iops to start rotating */
do {
if (state->should_shutdown()) {
if (state->space) {
if (state->space != fil_system.space_list.end()) {
state->space->release();
state->space = NULL;
state->space = fil_system.space_list.end();
}
return false;
}
......@@ -1543,18 +1545,19 @@ static bool fil_crypt_find_space_to_rotate(
if (state->first) {
state->first = false;
if (state->space) {
if (state->space != fil_system.space_list.end()) {
state->space->release();
}
state->space = NULL;
state->space = fil_system.space_list.end();
}
state->space = fil_space_t::next(state->space, *recheck,
key_state->key_version != 0);
bool wake = true;
while (state->space) {
if (state->space == fil_system.temp_space) {
while (state->space != fil_system.space_list.end()) {
if (state->space
== space_list_t::iterator(fil_system.temp_space)) {
wake = false;
goto done;
}
......@@ -1562,7 +1565,7 @@ static bool fil_crypt_find_space_to_rotate(
if (state->should_shutdown()) {
state->space->release();
done:
state->space = nullptr;
state->space = fil_system.space_list.end();
break;
}
......@@ -1571,7 +1574,7 @@ static bool fil_crypt_find_space_to_rotate(
page 0 for this tablespace, we need to read it before
we can continue. */
if (!state->space->crypt_data) {
fil_crypt_read_crypt_data(state->space);
fil_crypt_read_crypt_data(&*state->space);
}
if (fil_crypt_space_needs_rotation(state, key_state, recheck)) {
......@@ -1654,16 +1657,17 @@ fil_crypt_find_page_to_rotate(
rotate_thread_t* state)
{
ulint batch = srv_alloc_time * state->allocated_iops;
fil_space_t* space = state->space;
ut_ad(!space || space->referenced());
ut_ad(state->space == fil_system.space_list.end()
|| state->space->referenced());
/* If space is marked to be dropped stop rotation. */
if (!space || space->is_stopping()) {
if (state->space == fil_system.space_list.end()
|| state->space->is_stopping()) {
return false;
}
fil_space_crypt_t *crypt_data = space->crypt_data;
fil_space_crypt_t *crypt_data = state->space->crypt_data;
mysql_mutex_lock(&crypt_data->mutex);
ut_ad(key_state->key_id == crypt_data->key_id);
......@@ -1703,7 +1707,7 @@ fil_crypt_get_page_throttle(
mtr_t* mtr,
ulint* sleeptime_ms)
{
fil_space_t* space = state->space;
fil_space_t* space = &*state->space;
const ulint zip_size = space->zip_size();
const page_id_t page_id(space->id, offset);
ut_ad(space->referenced());
......@@ -1773,7 +1777,7 @@ fil_crypt_rotate_page(
const key_state_t* key_state,
rotate_thread_t* state)
{
fil_space_t*space = state->space;
fil_space_t *space = &*state->space;
ulint space_id = space->id;
uint32_t offset = state->offset;
ulint sleeptime_ms = 0;
......@@ -1944,7 +1948,7 @@ void
fil_crypt_flush_space(
rotate_thread_t* state)
{
fil_space_t* space = state->space;
fil_space_t* space = &*state->space;
fil_space_crypt_t *crypt_data = space->crypt_data;
ut_ad(space->referenced());
......@@ -2092,7 +2096,7 @@ static void fil_crypt_thread()
/* iterate all spaces searching for those needing rotation */
while (fil_crypt_find_space_to_rotate(&new_state, &thr,
&recheck)) {
if (!thr.space) {
if (thr.space == fil_system.space_list.end()) {
goto wait_for_work;
}
......@@ -2108,7 +2112,7 @@ static void fil_crypt_thread()
if (thr.space->is_stopping()) {
fil_crypt_complete_rotate_space(&thr);
thr.space->release();
thr.space = nullptr;
thr.space = fil_system.space_list.end();
break;
}
......@@ -2120,7 +2124,7 @@ static void fil_crypt_thread()
}
/* complete rotation */
if (thr.space) {
if (thr.space != fil_system.space_list.end()) {
fil_crypt_complete_rotate_space(&thr);
}
......@@ -2132,9 +2136,9 @@ static void fil_crypt_thread()
fil_crypt_return_iops(&thr);
}
if (thr.space) {
if (thr.space != fil_system.space_list.end()) {
thr.space->release();
thr.space = nullptr;
thr.space = fil_system.space_list.end();
}
}
......@@ -2196,45 +2200,43 @@ static void fil_crypt_rotation_list_fill()
{
mysql_mutex_assert_owner(&fil_system.mutex);
for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list);
space != NULL;
space = UT_LIST_GET_NEXT(space_list, space)) {
if (space->purpose != FIL_TYPE_TABLESPACE
|| space->is_in_rotation_list
|| UT_LIST_GET_LEN(space->chain) == 0
|| !space->acquire_if_not_stopped()) {
for (fil_space_t& space : fil_system.space_list) {
if (space.purpose != FIL_TYPE_TABLESPACE
|| space.is_in_rotation_list
|| UT_LIST_GET_LEN(space.chain) == 0
|| !space.acquire_if_not_stopped()) {
continue;
}
/* Ensure that crypt_data has been initialized. */
ut_ad(space->size);
ut_ad(space.size);
/* Skip ENCRYPTION!=DEFAULT tablespaces. */
if (space->crypt_data
&& !space->crypt_data->is_default_encryption()) {
if (space.crypt_data
&& !space.crypt_data->is_default_encryption()) {
goto next;
}
if (srv_encrypt_tables) {
/* Skip encrypted tablespaces if
innodb_encrypt_tables!=OFF */
if (space->crypt_data
&& space->crypt_data->min_key_version) {
if (space.crypt_data
&& space.crypt_data->min_key_version) {
goto next;
}
} else {
/* Skip unencrypted tablespaces if
innodb_encrypt_tables=OFF */
if (!space->crypt_data
|| !space->crypt_data->min_key_version) {
if (!space.crypt_data
|| !space.crypt_data->min_key_version) {
goto next;
}
}
fil_system.rotation_list.push_back(*space);
space->is_in_rotation_list = true;
fil_system.rotation_list.push_back(space);
space.is_in_rotation_list = true;
next:
space->release();
space.release();
}
}
......
......@@ -68,16 +68,15 @@ inline bool fil_is_user_tablespace_id(ulint space_id)
bool fil_space_t::try_to_close(bool print_info)
{
mysql_mutex_assert_owner(&fil_system.mutex);
for (fil_space_t *space= UT_LIST_GET_FIRST(fil_system.space_list); space;
space= UT_LIST_GET_NEXT(space_list, space))
for (fil_space_t &space : fil_system.space_list)
{
switch (space->purpose) {
switch (space.purpose) {
case FIL_TYPE_TEMPORARY:
continue;
case FIL_TYPE_IMPORT:
break;
case FIL_TYPE_TABLESPACE:
if (!fil_is_user_tablespace_id(space->id))
if (!fil_is_user_tablespace_id(space.id))
continue;
}
......@@ -85,14 +84,14 @@ bool fil_space_t::try_to_close(bool print_info)
fil_node_open_file_low(), newly opened files are moved to the end
of fil_system.space_list, so that they would be less likely to be
closed here. */
fil_node_t *node= UT_LIST_GET_FIRST(space->chain);
fil_node_t *node= UT_LIST_GET_FIRST(space.chain);
ut_ad(node);
ut_ad(!UT_LIST_GET_NEXT(chain, node));
if (!node->is_open())
continue;
if (const auto n= space->set_closing())
if (const auto n= space.set_closing())
{
if (print_info)
ib::info() << "Cannot close file " << node->name
......@@ -399,8 +398,8 @@ static bool fil_node_open_file_low(fil_node_t *node)
{
/* Move the file last in fil_system.space_list, so that
fil_space_t::try_to_close() should close it as a last resort. */
UT_LIST_REMOVE(fil_system.space_list, node->space);
UT_LIST_ADD_LAST(fil_system.space_list, node->space);
fil_system.space_list.erase(space_list_t::iterator(node->space));
fil_system.space_list.push_back(*node->space);
}
fil_system.n_open++;
......@@ -779,7 +778,7 @@ std::vector<pfs_os_file_t> fil_system_t::detach(fil_space_t *space,
space->is_in_rotation_list= false;
rotation_list.remove(*space);
}
UT_LIST_REMOVE(space_list, space);
space_list.erase(space_list_t::iterator(space));
if (space == sys_space)
sys_space= nullptr;
else if (space == temp_space)
......@@ -882,7 +881,7 @@ fil_space_free(
if (space->max_lsn != 0) {
ut_d(space->max_lsn = 0);
UT_LIST_REMOVE(fil_system.named_spaces, space);
fil_system.named_spaces.remove(*space);
}
if (!recv_recovery_is_on()) {
......@@ -972,7 +971,7 @@ fil_space_t *fil_space_t::create(const char *name, ulint id, ulint flags,
HASH_INSERT(fil_space_t, hash, &fil_system.spaces, id, space);
UT_LIST_ADD_LAST(fil_system.space_list, space);
fil_system.space_list.push_back(*space);
switch (id) {
case 0:
......@@ -1272,7 +1271,7 @@ void fil_system_t::close()
{
ut_ad(this == &fil_system);
ut_a(unflushed_spaces.empty());
ut_a(!UT_LIST_GET_LEN(space_list));
ut_a(space_list.empty());
ut_ad(!sys_space);
ut_ad(!temp_space);
......@@ -1297,23 +1296,22 @@ ATTRIBUTE_COLD void fil_system_t::extend_to_recv_size()
{
ut_ad(is_initialised());
mysql_mutex_lock(&mutex);
for (fil_space_t *space= UT_LIST_GET_FIRST(fil_system.space_list); space;
space= UT_LIST_GET_NEXT(space_list, space))
for (fil_space_t &space : fil_system.space_list)
{
const uint32_t size= space->recv_size;
const uint32_t size= space.recv_size;
if (size > space->size)
if (size > space.size)
{
if (space->is_closing())
if (space.is_closing())
continue;
space->reacquire();
space.reacquire();
bool success;
while (fil_space_extend_must_retry(space, UT_LIST_GET_LAST(space->chain),
while (fil_space_extend_must_retry(&space, UT_LIST_GET_LAST(space.chain),
size, &success))
mysql_mutex_lock(&mutex);
/* Crash recovery requires the file extension to succeed. */
ut_a(success);
space->release();
space.release();
}
}
mysql_mutex_unlock(&mutex);
......@@ -1322,64 +1320,58 @@ ATTRIBUTE_COLD void fil_system_t::extend_to_recv_size()
/** Close all tablespace files at shutdown */
void fil_space_t::close_all()
{
if (!fil_system.is_initialised()) {
return;
}
fil_space_t* space;
/* At shutdown, we should not have any files in this list. */
ut_ad(srv_fast_shutdown == 2
|| !srv_was_started
|| UT_LIST_GET_LEN(fil_system.named_spaces) == 0);
fil_flush_file_spaces();
mysql_mutex_lock(&fil_system.mutex);
if (!fil_system.is_initialised())
return;
for (space = UT_LIST_GET_FIRST(fil_system.space_list); space; ) {
fil_node_t* node;
fil_space_t* prev_space = space;
/* At shutdown, we should not have any files in this list. */
ut_ad(srv_fast_shutdown == 2 || !srv_was_started ||
fil_system.named_spaces.empty());
fil_flush_file_spaces();
for (node = UT_LIST_GET_FIRST(space->chain);
node != NULL;
node = UT_LIST_GET_NEXT(chain, node)) {
mysql_mutex_lock(&fil_system.mutex);
if (!node->is_open()) {
next:
continue;
}
while (!fil_system.space_list.empty())
{
fil_space_t &space= fil_system.space_list.front();
for (ulint count = 10000; count--; ) {
if (!space->set_closing()) {
node->close();
goto next;
}
mysql_mutex_unlock(&fil_system.mutex);
std::this_thread::sleep_for(
std::chrono::microseconds(100));
mysql_mutex_lock(&fil_system.mutex);
if (!node->is_open()) {
goto next;
}
}
for (fil_node_t *node= UT_LIST_GET_FIRST(space.chain); node != NULL;
node= UT_LIST_GET_NEXT(chain, node))
{
ib::error() << "File '" << node->name
<< "' has " << space->referenced()
<< " operations";
}
if (!node->is_open())
{
next:
continue;
}
for (ulint count= 10000; count--;)
{
if (!space.set_closing())
{
node->close();
goto next;
}
mysql_mutex_unlock(&fil_system.mutex);
std::this_thread::sleep_for(std::chrono::microseconds(100));
mysql_mutex_lock(&fil_system.mutex);
if (!node->is_open())
goto next;
}
ib::error() << "File '" << node->name << "' has " << space.referenced()
<< " operations";
}
space = UT_LIST_GET_NEXT(space_list, space);
fil_system.detach(prev_space);
mysql_mutex_unlock(&fil_system.mutex);
fil_space_free_low(prev_space);
mysql_mutex_lock(&fil_system.mutex);
}
fil_system.detach(&space);
mysql_mutex_unlock(&fil_system.mutex);
fil_space_free_low(&space);
mysql_mutex_lock(&fil_system.mutex);
}
mysql_mutex_unlock(&fil_system.mutex);
mysql_mutex_unlock(&fil_system.mutex);
ut_ad(srv_fast_shutdown == 2
|| !srv_was_started
|| UT_LIST_GET_LEN(fil_system.named_spaces) == 0);
ut_ad(srv_fast_shutdown == 2 || !srv_was_started ||
fil_system.named_spaces.empty());
}
/*******************************************************************//**
......@@ -1858,7 +1850,7 @@ dberr_t fil_delete_tablespace(ulint id, bool if_exists,
if (space->max_lsn != 0) {
ut_d(space->max_lsn = 0);
UT_LIST_REMOVE(fil_system.named_spaces, space);
fil_system.named_spaces.remove(*space);
}
mysql_mutex_unlock(&log_sys.mutex);
......@@ -2041,13 +2033,12 @@ fil_rename_tablespace_check(
new tablespace file. */
retry:
mysql_mutex_lock(&fil_system.mutex);
for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list);
space; space = UT_LIST_GET_NEXT(space_list, space)) {
ulint id = space->id;
for (fil_space_t& space : fil_system.space_list) {
ulint id = space.id;
if (id
&& space->purpose == FIL_TYPE_TABLESPACE
&& space.purpose == FIL_TYPE_TABLESPACE
&& !strcmp(new_path,
UT_LIST_GET_FIRST(space->chain)->name)) {
UT_LIST_GET_FIRST(space.chain)->name)) {
ib::info() << "TRUNCATE rollback: " << id
<< "," << new_path;
mysql_mutex_unlock(&fil_system.mutex);
......@@ -3403,10 +3394,8 @@ bool fil_validate()
mysql_mutex_lock(&fil_system.mutex);
for (fil_space_t *space = UT_LIST_GET_FIRST(fil_system.space_list);
space != NULL;
space = UT_LIST_GET_NEXT(space_list, space)) {
n_open += Check::validate(space);
for (fil_space_t &space : fil_system.space_list) {
n_open += Check::validate(&space);
}
ut_a(fil_system.n_open == n_open);
......@@ -3501,7 +3490,7 @@ fil_names_dirty(
ut_ad(space->max_lsn == 0);
ut_d(fil_space_validate_for_mtr_commit(space));
UT_LIST_ADD_LAST(fil_system.named_spaces, space);
fil_system.named_spaces.push_back(*space);
space->max_lsn = log_sys.get_lsn();
}
......@@ -3515,7 +3504,7 @@ void fil_names_dirty_and_write(fil_space_t* space)
ut_d(fil_space_validate_for_mtr_commit(space));
ut_ad(space->max_lsn == log_sys.get_lsn());
UT_LIST_ADD_LAST(fil_system.named_spaces, space);
fil_system.named_spaces.push_back(*space);
mtr_t mtr;
mtr.start();
fil_names_write(space, &mtr);
......@@ -3557,27 +3546,27 @@ fil_names_clear(
mtr.start();
for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.named_spaces);
space != NULL; ) {
for (auto it = fil_system.named_spaces.begin();
it != fil_system.named_spaces.end(); ) {
if (mtr.get_log()->size()
+ (3 + 5 + 1) + strlen(space->chain.start->name)
+ (3 + 5 + 1) + strlen(it->chain.start->name)
>= mtr_checkpoint_size) {
/* Prevent log parse buffer overflow */
mtr.commit_files();
mtr.start();
}
fil_space_t* next = UT_LIST_GET_NEXT(named_spaces, space);
auto next = std::next(it);
ut_ad(space->max_lsn > 0);
if (space->max_lsn < lsn) {
ut_ad(it->max_lsn > 0);
if (it->max_lsn < lsn) {
/* The tablespace was last dirtied before the
checkpoint LSN. Remove it from the list, so
that if the tablespace is not going to be
modified any more, subsequent checkpoints will
avoid calling fil_names_write() on it. */
space->max_lsn = 0;
UT_LIST_REMOVE(fil_system.named_spaces, space);
it->max_lsn = 0;
fil_system.named_spaces.erase(it);
}
/* max_lsn is the last LSN where fil_names_dirty_and_write()
......@@ -3585,10 +3574,10 @@ fil_names_clear(
where max_lsn turned nonzero), we could avoid the
fil_names_write() call if min_lsn > lsn. */
fil_names_write(space, &mtr);
fil_names_write(&*it, &mtr);
do_write = true;
space = next;
it = next;
}
if (do_write) {
......@@ -3676,3 +3665,45 @@ fil_space_get_block_size(const fil_space_t* space, unsigned offset)
return block_size;
}
#ifdef UNIV_DEBUG
fil_space_t *fil_space_t::next_in_space_list()
{
space_list_t::iterator it(this);
auto end= fil_system.space_list.end();
if (it == end)
return nullptr;
++it;
return it == end ? nullptr : &*it;
}
fil_space_t *fil_space_t::prev_in_space_list()
{
space_list_t::iterator it(this);
if (it == fil_system.space_list.begin())
return nullptr;
--it;
return &*it;
}
fil_space_t *fil_space_t::next_in_unflushed_spaces()
{
sized_ilist<fil_space_t, unflushed_spaces_tag_t>::iterator it(this);
auto end= fil_system.unflushed_spaces.end();
if (it == end)
return nullptr;
++it;
return it == end ? nullptr : &*it;
}
fil_space_t *fil_space_t::prev_in_unflushed_spaces()
{
sized_ilist<fil_space_t, unflushed_spaces_tag_t>::iterator it(this);
if (it == fil_system.unflushed_spaces.begin())
return nullptr;
--it;
return &*it;
}
#endif
......@@ -5735,15 +5735,13 @@ static void fil_get_fts_spaces(fts_space_set_t& fts_space_set)
{
mysql_mutex_lock(&fil_system.mutex);
for (fil_space_t *space= UT_LIST_GET_FIRST(fil_system.space_list);
space;
space= UT_LIST_GET_NEXT(space_list, space))
for (fil_space_t &space : fil_system.space_list)
{
index_id_t index_id= 0;
table_id_t table_id= 0;
if (space->purpose == FIL_TYPE_TABLESPACE
&& fts_check_aux_table(space->name, &table_id, &index_id))
if (space.purpose == FIL_TYPE_TABLESPACE
&& fts_check_aux_table(space.name, &table_id, &index_id))
fts_space_set.insert(std::make_pair(table_id, index_id));
}
......
......@@ -6552,17 +6552,16 @@ static int i_s_sys_tablespaces_fill_table(THD *thd, TABLE_LIST *tables, Item*)
mysql_mutex_lock(&fil_system.mutex);
fil_system.freeze_space_list++;
for (fil_space_t *space= UT_LIST_GET_FIRST(fil_system.space_list);
space; space= UT_LIST_GET_NEXT(space_list, space))
for (fil_space_t &space : fil_system.space_list)
{
if (space->purpose == FIL_TYPE_TABLESPACE && !space->is_stopping() &&
space->chain.start)
if (space.purpose == FIL_TYPE_TABLESPACE && !space.is_stopping() &&
space.chain.start)
{
space->reacquire();
space.reacquire();
mysql_mutex_unlock(&fil_system.mutex);
err= i_s_sys_tablespaces_fill(thd, *space, tables->table);
err= i_s_sys_tablespaces_fill(thd, space, tables->table);
mysql_mutex_lock(&fil_system.mutex);
space->release();
space.release();
if (err)
break;
}
......@@ -6772,16 +6771,15 @@ i_s_tablespaces_encryption_fill_table(
mysql_mutex_lock(&fil_system.mutex);
fil_system.freeze_space_list++;
for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list);
space; space = UT_LIST_GET_NEXT(space_list, space)) {
if (space->purpose == FIL_TYPE_TABLESPACE
&& !space->is_stopping()) {
space->reacquire();
for (fil_space_t& space : fil_system.space_list) {
if (space.purpose == FIL_TYPE_TABLESPACE
&& !space.is_stopping()) {
space.reacquire();
mysql_mutex_unlock(&fil_system.mutex);
err = i_s_dict_fill_tablespaces_encryption(
thd, space, tables->table);
thd, &space, tables->table);
mysql_mutex_lock(&fil_system.mutex);
space->release();
space.release();
if (err) {
break;
}
......
......@@ -213,12 +213,13 @@ struct fil_space_crypt_status_t {
};
/** Statistics about encryption key rotation */
struct fil_crypt_stat_t {
ulint pages_read_from_cache;
ulint pages_read_from_disk;
ulint pages_modified;
ulint pages_flushed;
ulint estimated_iops;
struct fil_crypt_stat_t
{
ulint pages_read_from_cache= 0;
ulint pages_read_from_disk= 0;
ulint pages_modified= 0;
ulint pages_flushed= 0;
ulint estimated_iops= 0;
};
/*********************************************************************
......
......@@ -44,6 +44,10 @@ Created 10/25/1995 Heikki Tuuri
struct unflushed_spaces_tag_t;
struct rotation_list_tag_t;
struct space_list_tag_t;
struct named_spaces_tag_t;
using space_list_t= ilist<fil_space_t, space_list_tag_t>;
// Forward declaration
extern my_bool srv_use_doublewrite_buf;
......@@ -331,8 +335,10 @@ enum fil_encryption_t
FIL_ENCRYPTION_OFF
};
struct fil_space_t final :
ilist_node<unflushed_spaces_tag_t>, ilist_node<rotation_list_tag_t>
struct fil_space_t final : ilist_node<unflushed_spaces_tag_t>,
ilist_node<rotation_list_tag_t>,
ilist_node<space_list_tag_t>,
ilist_node<named_spaces_tag_t>
#else
struct fil_space_t final
#endif
......@@ -377,6 +383,14 @@ struct fil_space_t final
/*!< number of reserved free extents for
ongoing operations like B-tree page split */
private:
#ifdef UNIV_DEBUG
fil_space_t *next_in_space_list();
fil_space_t *prev_in_space_list();
fil_space_t *next_in_unflushed_spaces();
fil_space_t *prev_in_unflushed_spaces();
#endif
/** the committed size of the tablespace in pages */
Atomic_relaxed<uint32_t> committed_size;
/** Number of pending operations on the file.
......@@ -399,12 +413,6 @@ struct fil_space_t final
os_thread_id_t latch_owner;
ut_d(Atomic_relaxed<uint32_t> latch_count;)
public:
UT_LIST_NODE_T(fil_space_t) named_spaces;
/*!< list of spaces for which FILE_MODIFY
records have been issued */
UT_LIST_NODE_T(fil_space_t) space_list;
/*!< list of all spaces */
/** MariaDB encryption data */
fil_space_crypt_t* crypt_data;
......@@ -989,8 +997,8 @@ struct fil_space_t final
@param encrypt expected state of innodb_encrypt_tables
@return the next tablespace
@retval nullptr upon reaching the end of the iteration */
static inline fil_space_t *next(fil_space_t *space, bool recheck,
bool encrypt);
static space_list_t::iterator next(space_list_t::iterator space,
bool recheck, bool encrypt);
#ifdef UNIV_DEBUG
bool is_latched() const { return latch_count != 0; }
......@@ -1371,11 +1379,7 @@ struct fil_system_t {
Some members may require late initialisation, thus we just mark object as
uninitialised. Real initialisation happens in create().
*/
fil_system_t(): m_initialised(false)
{
UT_LIST_INIT(space_list, &fil_space_t::space_list);
UT_LIST_INIT(named_spaces, &fil_space_t::named_spaces);
}
fil_system_t() : m_initialised(false) {}
bool is_initialised() const { return m_initialised; }
......@@ -1434,9 +1438,9 @@ struct fil_system_t {
/** nonzero if fil_node_open_file_low() should avoid moving the tablespace
to the end of space_list, for FIFO policy of try_to_close() */
ulint freeze_space_list;
UT_LIST_BASE_NODE_T(fil_space_t) space_list;
ilist<fil_space_t, space_list_tag_t> space_list;
/*!< list of all file spaces */
UT_LIST_BASE_NODE_T(fil_space_t) named_spaces;
ilist<fil_space_t, named_spaces_tag_t> named_spaces;
/*!< list of all file spaces
for which a FILE_MODIFY
record has been written since
......@@ -1458,11 +1462,10 @@ struct fil_system_t {
@param encrypt expected state of innodb_encrypt_tables
@return the next tablespace to process (n_pending_ops incremented)
@retval NULL if this was the last */
inline fil_space_t* keyrotate_next(fil_space_t *space, bool recheck,
bool encrypt);
fil_space_t* keyrotate_next(fil_space_t* space, bool recheck, bool encrypt);
/** Extend all open data files to the recovered size */
ATTRIBUTE_COLD void extend_to_recv_size();
/** Extend all open data files to the recovered size */
ATTRIBUTE_COLD void extend_to_recv_size();
};
/** The tablespace memory cache. */
......
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