Commit 52a50977 authored by Eugene Kosov's avatar Eugene Kosov

MDEV-17441 InnoDB transition to C++11 atomics

dict_table_t::stats_latch_created: remove along with related stuff

dict_table_t::stats_latch: make value member, not pointer. And always lock this
for simplicity, even to stats cloned table.

based on the work of Sergey Vojtovich
parent e9a5f288
......@@ -226,145 +226,6 @@ dict_get_db_name_len(
return ulint(s - name);
}
/** Allocate and init a dict_table_t's stats latch.
This function must not be called concurrently on the same table object.
@param[in,out] table_void table whose stats latch to create */
static
void
dict_table_stats_latch_alloc(
void* table_void)
{
dict_table_t* table = static_cast<dict_table_t*>(table_void);
/* Note: rw_lock_create() will call the constructor */
table->stats_latch = static_cast<rw_lock_t*>(
ut_malloc_nokey(sizeof(rw_lock_t)));
ut_a(table->stats_latch != NULL);
rw_lock_create(dict_table_stats_key, table->stats_latch,
SYNC_INDEX_TREE);
}
/** Deinit and free a dict_table_t's stats latch.
This function must not be called concurrently on the same table object.
@param[in,out] table table whose stats latch to free */
static
void
dict_table_stats_latch_free(
dict_table_t* table)
{
rw_lock_free(table->stats_latch);
ut_free(table->stats_latch);
}
/** Create a dict_table_t's stats latch or delay for lazy creation.
This function is only called from either single threaded environment
or from a thread that has not shared the table object with other threads.
@param[in,out] table table whose stats latch to create
@param[in] enabled if false then the latch is disabled
and dict_table_stats_lock()/unlock() become noop on this table. */
void
dict_table_stats_latch_create(
dict_table_t* table,
bool enabled)
{
if (!enabled) {
table->stats_latch = NULL;
table->stats_latch_created = os_once::DONE;
return;
}
/* We create this lazily the first time it is used. */
table->stats_latch = NULL;
table->stats_latch_created = os_once::NEVER_DONE;
}
/** Destroy a dict_table_t's stats latch.
This function is only called from either single threaded environment
or from a thread that has not shared the table object with other threads.
@param[in,out] table table whose stats latch to destroy */
void
dict_table_stats_latch_destroy(
dict_table_t* table)
{
if (table->stats_latch_created == os_once::DONE
&& table->stats_latch != NULL) {
dict_table_stats_latch_free(table);
}
}
/** Lock the appropriate latch to protect a given table's statistics.
@param[in] table table whose stats to lock
@param[in] latch_mode RW_S_LATCH or RW_X_LATCH */
void
dict_table_stats_lock(
dict_table_t* table,
ulint latch_mode)
{
ut_ad(table != NULL);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
os_once::do_or_wait_for_done(
&table->stats_latch_created,
dict_table_stats_latch_alloc, table);
if (table->stats_latch == NULL) {
/* This is a dummy table object that is private in the current
thread and is not shared between multiple threads, thus we
skip any locking. */
return;
}
switch (latch_mode) {
case RW_S_LATCH:
rw_lock_s_lock(table->stats_latch);
break;
case RW_X_LATCH:
rw_lock_x_lock(table->stats_latch);
break;
case RW_NO_LATCH:
/* fall through */
default:
ut_error;
}
}
/** Unlock the latch that has been locked by dict_table_stats_lock().
@param[in] table table whose stats to unlock
@param[in] latch_mode RW_S_LATCH or RW_X_LATCH */
void
dict_table_stats_unlock(
dict_table_t* table,
ulint latch_mode)
{
ut_ad(table != NULL);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
if (table->stats_latch == NULL) {
/* This is a dummy table object that is private in the current
thread and is not shared between multiple threads, thus we
skip any locking. */
return;
}
switch (latch_mode) {
case RW_S_LATCH:
rw_lock_s_unlock(table->stats_latch);
break;
case RW_X_LATCH:
rw_lock_x_unlock(table->stats_latch);
break;
case RW_NO_LATCH:
/* fall through */
default:
ut_error;
}
}
/** Open a persistent table.
@param[in] table_id persistent table identifier
@param[in] ignore_err errors to ignore
......
......@@ -171,10 +171,6 @@ dict_mem_table_create(
new (&table->v_cols[i]) dict_v_col_t();
}
/* true means that the stats latch will be enabled -
dict_table_stats_lock() will not be noop. */
dict_table_stats_latch_create(table, true);
table->autoinc_lock = static_cast<ib_lock_t*>(
mem_heap_alloc(heap, lock_get_size()));
......@@ -190,6 +186,9 @@ dict_mem_table_create(
new(&table->foreign_set) dict_foreign_set();
new(&table->referenced_set) dict_foreign_set();
rw_lock_create(dict_table_stats_key, &table->stats_latch,
SYNC_INDEX_TREE);
return(table);
}
......@@ -215,7 +214,6 @@ dict_mem_table_free(
}
dict_mem_table_free_foreign_vcol_set(table);
dict_table_stats_latch_destroy(table);
table->foreign_set.~dict_foreign_set();
table->referenced_set.~dict_foreign_set();
......@@ -231,6 +229,8 @@ dict_mem_table_free(
UT_DELETE(table->s_cols);
rw_lock_free(&table->stats_latch);
mem_heap_free(table->heap);
}
......
......@@ -33,6 +33,7 @@ Created Jan 06, 2010 Vasil Dimov
#include "pars0pars.h"
#include <mysql_com.h>
#include "btr0btr.h"
#include "sync0sync.h"
#include <algorithm>
#include <map>
......@@ -417,11 +418,6 @@ dict_stats_table_clone_create(
t->corrupted = table->corrupted;
/* This private object "t" is not shared with other threads, so
we do not need the stats_latch (thus we pass false below). The
dict_table_stats_lock()/unlock() routines will do nothing. */
dict_table_stats_latch_create(t, false);
UT_LIST_INIT(t->indexes, &dict_index_t::indexes);
for (index = dict_table_get_first_index(table);
......@@ -484,6 +480,8 @@ dict_stats_table_clone_create(
ut_d(t->magic_n = DICT_TABLE_MAGIC_N);
rw_lock_create(dict_table_stats_key, &t->stats_latch, SYNC_INDEX_TREE);
return(t);
}
......@@ -496,15 +494,13 @@ dict_stats_table_clone_free(
/*========================*/
dict_table_t* t) /*!< in: dummy table object to free */
{
dict_table_stats_latch_destroy(t);
rw_lock_free(&t->stats_latch);
mem_heap_free(t->heap);
}
/*********************************************************************//**
Write all zeros (or 1 where it makes sense) into an index
statistics members. The resulting stats correspond to an empty index.
The caller must own index's table stats latch in X mode
(dict_table_stats_lock(table, RW_X_LATCH)) */
statistics members. The resulting stats correspond to an empty index. */
static
void
dict_stats_empty_index(
......@@ -515,6 +511,7 @@ dict_stats_empty_index(
{
ut_ad(!(index->type & DICT_FTS));
ut_ad(!dict_index_is_ibuf(index));
ut_ad(rw_lock_own(&index->table->stats_latch, RW_LOCK_X));
ulint n_uniq = index->n_uniq;
......@@ -546,7 +543,7 @@ dict_stats_empty_table(
{
/* Zero the stats members */
dict_table_stats_lock(table, RW_X_LATCH);
rw_lock_x_lock(&table->stats_latch);
table->stat_n_rows = 0;
table->stat_clustered_index_size = 1;
......@@ -572,7 +569,7 @@ dict_stats_empty_table(
table->stat_initialized = TRUE;
dict_table_stats_unlock(table, RW_X_LATCH);
rw_lock_x_unlock(&table->stats_latch);
}
/*********************************************************************//**
......@@ -788,7 +785,7 @@ dict_stats_snapshot_create(
{
mutex_enter(&dict_sys.mutex);
dict_table_stats_lock(table, RW_S_LATCH);
rw_lock_s_lock(&table->stats_latch);
dict_stats_assert_initialized(table);
......@@ -803,7 +800,7 @@ dict_stats_snapshot_create(
t->stats_sample_pages = table->stats_sample_pages;
t->stats_bg_flag = table->stats_bg_flag;
dict_table_stats_unlock(table, RW_S_LATCH);
rw_lock_s_unlock(&table->stats_latch);
mutex_exit(&dict_sys.mutex);
......@@ -2215,7 +2212,7 @@ dict_stats_update_persistent(
DEBUG_PRINTF("%s(table=%s)\n", __func__, table->name);
dict_table_stats_lock(table, RW_X_LATCH);
rw_lock_x_lock(&table->stats_latch);
/* analyze the clustered index first */
......@@ -2226,7 +2223,7 @@ dict_stats_update_persistent(
|| (index->type | DICT_UNIQUE) != (DICT_CLUSTERED | DICT_UNIQUE)) {
/* Table definition is corrupt */
dict_table_stats_unlock(table, RW_X_LATCH);
rw_lock_x_unlock(&table->stats_latch);
dict_stats_empty_table(table, true);
return(DB_CORRUPTION);
......@@ -2278,7 +2275,7 @@ dict_stats_update_persistent(
dict_stats_assert_initialized(table);
dict_table_stats_unlock(table, RW_X_LATCH);
rw_lock_x_unlock(&table->stats_latch);
return(DB_SUCCESS);
}
......@@ -3097,11 +3094,11 @@ dict_stats_update_for_index(
if (dict_stats_is_persistent_enabled(index->table)) {
if (dict_stats_persistent_storage_check(false)) {
dict_table_stats_lock(index->table, RW_X_LATCH);
rw_lock_x_lock(&index->table->stats_latch);
dict_stats_analyze_index(index);
index->table->stat_sum_of_other_index_sizes
+= index->stat_index_size;
dict_table_stats_unlock(index->table, RW_X_LATCH);
rw_lock_x_unlock(&index->table->stats_latch);
dict_stats_save(index->table, &index->id);
DBUG_VOID_RETURN;
}
......@@ -3122,9 +3119,9 @@ dict_stats_update_for_index(
}
}
dict_table_stats_lock(index->table, RW_X_LATCH);
rw_lock_x_lock(&index->table->stats_latch);
dict_stats_update_transient_for_index(index);
dict_table_stats_unlock(index->table, RW_X_LATCH);
rw_lock_x_unlock(&index->table->stats_latch);
DBUG_VOID_RETURN;
}
......@@ -3278,7 +3275,7 @@ dict_stats_update(
switch (err) {
case DB_SUCCESS:
dict_table_stats_lock(table, RW_X_LATCH);
rw_lock_x_lock(&table->stats_latch);
/* Pass reset_ignored_indexes=true as parameter
to dict_stats_copy. This will cause statictics
......@@ -3287,7 +3284,7 @@ dict_stats_update(
dict_stats_assert_initialized(table);
dict_table_stats_unlock(table, RW_X_LATCH);
rw_lock_x_unlock(&table->stats_latch);
dict_stats_table_clone_free(t);
......@@ -3342,11 +3339,11 @@ dict_stats_update(
transient:
dict_table_stats_lock(table, RW_X_LATCH);
rw_lock_x_lock(&table->stats_latch);
dict_stats_update_transient(table);
dict_table_stats_unlock(table, RW_X_LATCH);
rw_lock_x_unlock(&table->stats_latch);
return(DB_SUCCESS);
}
......
......@@ -14000,7 +14000,7 @@ ha_innobase::info_low(
ulint stat_sum_of_other_index_sizes;
if (!(flag & HA_STATUS_NO_LOCK)) {
dict_table_stats_lock(ib_table, RW_S_LATCH);
rw_lock_s_lock(&ib_table->stats_latch);
}
ut_a(ib_table->stat_initialized);
......@@ -14014,7 +14014,7 @@ ha_innobase::info_low(
= ib_table->stat_sum_of_other_index_sizes;
if (!(flag & HA_STATUS_NO_LOCK)) {
dict_table_stats_unlock(ib_table, RW_S_LATCH);
rw_lock_s_unlock(&ib_table->stats_latch);
}
/*
......@@ -14118,7 +14118,7 @@ ha_innobase::info_low(
}
if (!(flag & HA_STATUS_NO_LOCK)) {
dict_table_stats_lock(ib_table, RW_S_LATCH);
rw_lock_s_lock(&ib_table->stats_latch);
}
ut_a(ib_table->stat_initialized);
......@@ -14200,7 +14200,7 @@ ha_innobase::info_low(
}
if (!(flag & HA_STATUS_NO_LOCK)) {
dict_table_stats_unlock(ib_table, RW_S_LATCH);
rw_lock_s_unlock(&ib_table->stats_latch);
}
snprintf(path, sizeof(path), "%s/%s%s",
......
......@@ -6263,7 +6263,7 @@ i_s_dict_fill_sys_tablestats(
OK(field_store_string(fields[SYS_TABLESTATS_NAME],
table->name.m_name));
dict_table_stats_lock(table, RW_S_LATCH);
rw_lock_s_lock(&table->stats_latch);
if (table->stat_initialized) {
OK(field_store_string(fields[SYS_TABLESTATS_INIT],
......@@ -6293,7 +6293,7 @@ i_s_dict_fill_sys_tablestats(
OK(fields[SYS_TABLESTATS_MODIFIED]->store(0, true));
}
dict_table_stats_unlock(table, RW_S_LATCH);
rw_lock_s_unlock(&table->stats_latch);
OK(fields[SYS_TABLESTATS_AUTONINC]->store(table->autoinc, true));
......
......@@ -1341,41 +1341,6 @@ dict_index_calc_min_rec_len(
#define dict_mutex_enter_for_mysql() mutex_enter(&dict_sys.mutex)
#define dict_mutex_exit_for_mysql() mutex_exit(&dict_sys.mutex)
/** Create a dict_table_t's stats latch or delay for lazy creation.
This function is only called from either single threaded environment
or from a thread that has not shared the table object with other threads.
@param[in,out] table table whose stats latch to create
@param[in] enabled if false then the latch is disabled
and dict_table_stats_lock()/unlock() become noop on this table. */
void
dict_table_stats_latch_create(
dict_table_t* table,
bool enabled);
/** Destroy a dict_table_t's stats latch.
This function is only called from either single threaded environment
or from a thread that has not shared the table object with other threads.
@param[in,out] table table whose stats latch to destroy */
void
dict_table_stats_latch_destroy(
dict_table_t* table);
/** Lock the appropriate latch to protect a given table's statistics.
@param[in] table table whose stats to lock
@param[in] latch_mode RW_S_LATCH or RW_X_LATCH */
void
dict_table_stats_lock(
dict_table_t* table,
ulint latch_mode);
/** Unlock the latch that has been locked by dict_table_stats_lock().
@param[in] table table whose stats to unlock
@param[in] latch_mode RW_S_LATCH or RW_X_LATCH */
void
dict_table_stats_unlock(
dict_table_t* table,
ulint latch_mode);
/********************************************************************//**
Checks if the database name in two table names is the same.
@return TRUE if same db name */
......
......@@ -1965,9 +1965,6 @@ struct dict_table_t {
/** Statistics for query optimization. @{ */
/** Creation state of 'stats_latch'. */
volatile os_once::state_t stats_latch_created;
/** This latch protects:
dict_table_t::stat_initialized,
dict_table_t::stat_n_rows (*),
......@@ -1979,7 +1976,7 @@ struct dict_table_t {
dict_table_t::indexes*::stat_n_leaf_pages.
(*) Those are not always protected for
performance reasons. */
rw_lock_t* stats_latch;
rw_lock_t stats_latch;
/** TRUE if statistics have been calculated the first time after
database startup or table creation. */
......
......@@ -75,7 +75,7 @@ dict_stats_is_persistent_enabled(const dict_table_t* table)
+ dict_stats_update(DICT_STATS_RECALC_TRANSIENT) on a table that has
just been PS-enabled.
This is acceptable. Avoiding this would mean that we would have to
protect the ::stat_persistent with dict_table_stats_lock() like the
protect the ::stat_persistent with dict_table_t::stats_latch like the
other ::stat_ members which would be too big performance penalty,
especially when this function is called from
dict_stats_update_if_needed(). */
......@@ -178,10 +178,10 @@ dict_stats_deinit(
ut_a(table->get_ref_count() == 0);
dict_table_stats_lock(table, RW_X_LATCH);
rw_lock_x_lock(&table->stats_latch);
if (!table->stat_initialized) {
dict_table_stats_unlock(table, RW_X_LATCH);
rw_lock_x_unlock(&table->stats_latch);
return;
}
......@@ -223,5 +223,5 @@ dict_stats_deinit(
}
#endif /* UNIV_DEBUG_VALGRIND */
dict_table_stats_unlock(table, RW_X_LATCH);
rw_lock_x_unlock(&table->stats_latch);
}
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