mirror of
https://github.com/MariaDB/server.git
synced 2026-05-16 20:07:13 +02:00
MDEV-23370 innodb_fts.innodb_fts_misc failed in buildbot, server crashed in dict_table_autoinc_destroy
This issue is caused by MDEV-22456ad6171b91c. Fix involves the backported version of 10.4 patch MDEV-227785f2628d1eeand few parts of MDEV-17441 (e9a5f288f2). dict_table_t::stats_latch_created: Removed dict_table_t::stats_latch: make value member and always lock it for simplicity even for stats cloned table. zip_pad_info_t::mutex_created: Removed zip_pad_info_t::mutex: make member value instead of pointer os0once.h: Removed dict_table_remove_from_cache_low(): Ensure that fts_free() is always called, even if dict_mem_table_free() is deferred until btr_search_lazy_free(). InnoDB would always zip_pad_info_t::mutex and dict_table_t::autoinc_mutex, even for tables are not in ROW_FORMAT=COMPRESSED nor include any AUTO_INCREMENT column.
This commit is contained in:
parent
987df9b37a
commit
3ba8f619e4
8 changed files with 68 additions and 399 deletions
|
|
@ -60,7 +60,6 @@ extern uint ibuf_debug;
|
|||
#include "lock0lock.h"
|
||||
#include "mach0data.h"
|
||||
#include "mem0mem.h"
|
||||
#include "os0once.h"
|
||||
#include "page0page.h"
|
||||
#include "page0zip.h"
|
||||
#include "pars0pars.h"
|
||||
|
|
@ -268,76 +267,6 @@ dict_mutex_exit_for_mysql(void)
|
|||
mutex_exit(&dict_sys->mutex);
|
||||
}
|
||||
|
||||
/** 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 */
|
||||
|
|
@ -349,23 +278,12 @@ dict_table_stats_lock(
|
|||
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);
|
||||
rw_lock_s_lock(&table->stats_latch);
|
||||
break;
|
||||
case RW_X_LATCH:
|
||||
rw_lock_x_lock(table->stats_latch);
|
||||
rw_lock_x_lock(&table->stats_latch);
|
||||
break;
|
||||
case RW_NO_LATCH:
|
||||
/* fall through */
|
||||
|
|
@ -385,19 +303,12 @@ dict_table_stats_unlock(
|
|||
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);
|
||||
rw_lock_s_unlock(&table->stats_latch);
|
||||
break;
|
||||
case RW_X_LATCH:
|
||||
rw_lock_x_unlock(table->stats_latch);
|
||||
rw_lock_x_unlock(&table->stats_latch);
|
||||
break;
|
||||
case RW_NO_LATCH:
|
||||
/* fall through */
|
||||
|
|
@ -737,34 +648,6 @@ dict_table_get_nth_v_col_mysql(
|
|||
return(dict_table_get_nth_v_col(table, i));
|
||||
}
|
||||
|
||||
/** Allocate and init the autoinc latch of a given table.
|
||||
This function must not be called concurrently on the same table object.
|
||||
@param[in,out] table_void table whose autoinc latch to create */
|
||||
static
|
||||
void
|
||||
dict_table_autoinc_alloc(
|
||||
void* table_void)
|
||||
{
|
||||
dict_table_t* table = static_cast<dict_table_t*>(table_void);
|
||||
table->autoinc_mutex = UT_NEW_NOKEY(ib_mutex_t());
|
||||
ut_a(table->autoinc_mutex != NULL);
|
||||
mutex_create(LATCH_ID_AUTOINC, table->autoinc_mutex);
|
||||
}
|
||||
|
||||
/** Allocate and init the zip_pad_mutex of a given index.
|
||||
This function must not be called concurrently on the same index object.
|
||||
@param[in,out] index_void index whose zip_pad_mutex to create */
|
||||
static
|
||||
void
|
||||
dict_index_zip_pad_alloc(
|
||||
void* index_void)
|
||||
{
|
||||
dict_index_t* index = static_cast<dict_index_t*>(index_void);
|
||||
index->zip_pad.mutex = UT_NEW_NOKEY(SysMutex());
|
||||
ut_a(index->zip_pad.mutex != NULL);
|
||||
mutex_create(LATCH_ID_ZIP_PAD_MUTEX, index->zip_pad.mutex);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Acquire the autoinc lock. */
|
||||
void
|
||||
|
|
@ -772,11 +655,7 @@ dict_table_autoinc_lock(
|
|||
/*====================*/
|
||||
dict_table_t* table) /*!< in/out: table */
|
||||
{
|
||||
os_once::do_or_wait_for_done(
|
||||
&table->autoinc_mutex_created,
|
||||
dict_table_autoinc_alloc, table);
|
||||
|
||||
mutex_enter(table->autoinc_mutex);
|
||||
mysql_mutex_lock(&table->autoinc_mutex);
|
||||
}
|
||||
|
||||
/** Acquire the zip_pad_mutex latch.
|
||||
|
|
@ -786,11 +665,7 @@ void
|
|||
dict_index_zip_pad_lock(
|
||||
dict_index_t* index)
|
||||
{
|
||||
os_once::do_or_wait_for_done(
|
||||
&index->zip_pad.mutex_created,
|
||||
dict_index_zip_pad_alloc, index);
|
||||
|
||||
mutex_enter(index->zip_pad.mutex);
|
||||
mysql_mutex_lock(&index->zip_pad.mutex);
|
||||
}
|
||||
|
||||
/** Get all the FTS indexes on a table.
|
||||
|
|
@ -825,7 +700,7 @@ dict_table_autoinc_unlock(
|
|||
/*======================*/
|
||||
dict_table_t* table) /*!< in/out: table */
|
||||
{
|
||||
mutex_exit(table->autoinc_mutex);
|
||||
mysql_mutex_unlock(&table->autoinc_mutex);
|
||||
}
|
||||
|
||||
/** Looks for column n in an index.
|
||||
|
|
@ -1276,6 +1151,8 @@ dict_table_add_to_cache(
|
|||
|
||||
dict_table_add_system_columns(table, heap);
|
||||
|
||||
mysql_mutex_init(0, &table->autoinc_mutex, NULL);
|
||||
|
||||
table->cached = TRUE;
|
||||
|
||||
fold = ut_fold_string(table->name.m_name);
|
||||
|
|
@ -1419,7 +1296,7 @@ dict_index_t *dict_index_t::clone() const
|
|||
(mem_heap_zalloc(heap, n_uniq * sizeof *stat_n_sample_sizes));
|
||||
index->stat_n_non_null_key_vals= static_cast<ib_uint64_t*>
|
||||
(mem_heap_zalloc(heap, n_uniq * sizeof *stat_n_non_null_key_vals));
|
||||
memset(&index->zip_pad, 0, sizeof index->zip_pad);
|
||||
mysql_mutex_init(0, &index->zip_pad.mutex, NULL);
|
||||
return index;
|
||||
}
|
||||
|
||||
|
|
@ -2133,8 +2010,15 @@ dict_table_remove_from_cache_low(
|
|||
UT_DELETE(table->vc_templ);
|
||||
}
|
||||
|
||||
mysql_mutex_destroy(&table->autoinc_mutex);
|
||||
#ifdef BTR_CUR_HASH_ADAPT
|
||||
if (UNIV_UNLIKELY(UT_LIST_GET_LEN(table->freed_indexes) != 0)) {
|
||||
if (table->fts) {
|
||||
fts_optimize_remove_table(table);
|
||||
fts_free(table);
|
||||
table->fts = NULL;
|
||||
}
|
||||
|
||||
table->vc_templ = NULL;
|
||||
table->id = 0;
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -118,20 +118,15 @@ static bool dict_mem_table_is_system(char *name)
|
|||
}
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Creates a table memory object.
|
||||
@return own: table object */
|
||||
dict_table_t*
|
||||
dict_mem_table_create(
|
||||
/*==================*/
|
||||
const char* name, /*!< in: table name */
|
||||
ulint space, /*!< in: space where the clustered index of
|
||||
the table is placed */
|
||||
ulint n_cols, /*!< in: total number of columns including
|
||||
virtual and non-virtual columns */
|
||||
ulint n_v_cols,/*!< in: number of virtual columns */
|
||||
ulint flags, /*!< in: table flags */
|
||||
ulint flags2) /*!< in: table flags2 */
|
||||
const char* name,
|
||||
ulint space,
|
||||
ulint n_cols,
|
||||
ulint n_v_cols,
|
||||
ulint flags,
|
||||
ulint flags2,
|
||||
bool init_stats_latch)
|
||||
{
|
||||
dict_table_t* table;
|
||||
mem_heap_t* heap;
|
||||
|
|
@ -170,16 +165,9 @@ dict_mem_table_create(
|
|||
table->v_cols = static_cast<dict_v_col_t*>(
|
||||
mem_heap_alloc(heap, n_v_cols * sizeof(*table->v_cols)));
|
||||
|
||||
/* 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()));
|
||||
|
||||
/* lazy creation of table autoinc latch */
|
||||
dict_table_autoinc_create_lazy(table);
|
||||
|
||||
/* If the table has an FTS index or we are in the process
|
||||
of building one, create the table->fts */
|
||||
if (dict_table_has_fts_index(table)
|
||||
|
|
@ -194,6 +182,12 @@ dict_mem_table_create(
|
|||
new(&table->foreign_set) dict_foreign_set();
|
||||
new(&table->referenced_set) dict_foreign_set();
|
||||
|
||||
if (init_stats_latch) {
|
||||
rw_lock_create(dict_table_stats_key, &table->stats_latch,
|
||||
SYNC_INDEX_TREE);
|
||||
table->stats_latch_inited = true;
|
||||
}
|
||||
|
||||
return(table);
|
||||
}
|
||||
|
||||
|
|
@ -222,9 +216,7 @@ dict_mem_table_free(
|
|||
}
|
||||
}
|
||||
|
||||
dict_table_autoinc_destroy(table);
|
||||
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();
|
||||
|
|
@ -245,6 +237,10 @@ dict_mem_table_free(
|
|||
UT_DELETE(table->s_cols);
|
||||
}
|
||||
|
||||
if (table->stats_latch_inited) {
|
||||
rw_lock_free(&table->stats_latch);
|
||||
}
|
||||
|
||||
mem_heap_free(table->heap);
|
||||
}
|
||||
|
||||
|
|
@ -767,7 +763,7 @@ dict_mem_index_create(
|
|||
dict_mem_fill_index_struct(index, heap, table_name, index_name,
|
||||
space, type, n_fields);
|
||||
|
||||
dict_index_zip_pad_mutex_create_lazy(index);
|
||||
mysql_mutex_init(0, &index->zip_pad.mutex, NULL);
|
||||
|
||||
if (type & DICT_SPATIAL) {
|
||||
index->rtr_track = static_cast<rtr_info_track_t*>(
|
||||
|
|
@ -1082,7 +1078,7 @@ dict_mem_index_free(
|
|||
ut_ad(index);
|
||||
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
|
||||
|
||||
dict_index_zip_pad_mutex_destroy(index);
|
||||
mysql_mutex_destroy(&index->zip_pad.mutex);
|
||||
|
||||
if (dict_index_is_spatial(index)) {
|
||||
rtr_info_active::iterator it;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -418,11 +419,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);
|
||||
#ifdef BTR_CUR_HASH_ADAPT
|
||||
UT_LIST_INIT(t->freed_indexes, &dict_index_t::indexes);
|
||||
|
|
@ -490,6 +486,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);
|
||||
}
|
||||
|
||||
|
|
@ -502,7 +500,7 @@ 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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1447,7 +1447,7 @@ ibuf_dummy_index_create(
|
|||
|
||||
table = dict_mem_table_create("IBUF_DUMMY",
|
||||
DICT_HDR_SPACE, n, 0,
|
||||
comp ? DICT_TF_COMPACT : 0, 0);
|
||||
comp ? DICT_TF_COMPACT : 0, 0, false);
|
||||
|
||||
index = dict_mem_index_create("IBUF_DUMMY", "IBUF_DUMMY",
|
||||
DICT_HDR_SPACE, 0, n);
|
||||
|
|
|
|||
|
|
@ -302,7 +302,7 @@ UNIV_INLINE
|
|||
void
|
||||
dict_table_autoinc_initialize(dict_table_t* table, ib_uint64_t value)
|
||||
{
|
||||
ut_ad(dict_table_autoinc_own(table));
|
||||
mysql_mutex_assert_owner(&table->autoinc_mutex);
|
||||
table->autoinc = value;
|
||||
}
|
||||
|
||||
|
|
@ -315,7 +315,7 @@ UNIV_INLINE
|
|||
ib_uint64_t
|
||||
dict_table_autoinc_read(const dict_table_t* table)
|
||||
{
|
||||
ut_ad(dict_table_autoinc_own(table));
|
||||
mysql_mutex_assert_owner(&table->autoinc_mutex);
|
||||
return(table->autoinc);
|
||||
}
|
||||
|
||||
|
|
@ -329,7 +329,7 @@ UNIV_INLINE
|
|||
bool
|
||||
dict_table_autoinc_update_if_greater(dict_table_t* table, ib_uint64_t value)
|
||||
{
|
||||
ut_ad(dict_table_autoinc_own(table));
|
||||
mysql_mutex_assert_owner(&table->autoinc_mutex);
|
||||
|
||||
if (value > table->autoinc) {
|
||||
|
||||
|
|
@ -1524,25 +1524,6 @@ void
|
|||
dict_mutex_exit_for_mysql(void);
|
||||
/*===========================*/
|
||||
|
||||
/** 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 */
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ Created 1/8/1996 Heikki Tuuri
|
|||
#include "fts0fts.h"
|
||||
#include "buf0buf.h"
|
||||
#include "gis0type.h"
|
||||
#include "os0once.h"
|
||||
#include "fil0fil.h"
|
||||
#include <my_crypt.h>
|
||||
#include "fil0crypt.h"
|
||||
|
|
@ -299,21 +298,27 @@ parent table will fail, and user has to drop excessive foreign constraint
|
|||
before proceeds. */
|
||||
#define FK_MAX_CASCADE_DEL 15
|
||||
|
||||
/**********************************************************************//**
|
||||
Creates a table memory object.
|
||||
/** Creates a table memory object.
|
||||
@param[in] name table name
|
||||
@param[in] space space where the clustered index
|
||||
of the table is placed
|
||||
@param[in] n_cols total number of columns including
|
||||
virtual and non-virtual columns
|
||||
@param[in] n_v_cols number of virtual columns
|
||||
@param[in] flags table flags
|
||||
@param[in] flags2 table flags2
|
||||
@param[in] init_stats_latch whether to init the stats latch
|
||||
@return own: table object */
|
||||
dict_table_t*
|
||||
dict_mem_table_create(
|
||||
/*==================*/
|
||||
const char* name, /*!< in: table name */
|
||||
ulint space, /*!< in: space where the clustered index
|
||||
of the table is placed */
|
||||
ulint n_cols, /*!< in: total number of columns
|
||||
including virtual and non-virtual
|
||||
columns */
|
||||
ulint n_v_cols, /*!< in: number of virtual columns */
|
||||
ulint flags, /*!< in: table flags */
|
||||
ulint flags2); /*!< in: table flags2 */
|
||||
const char* name,
|
||||
ulint space,
|
||||
ulint n_cols,
|
||||
ulint n_v_cols,
|
||||
ulint flags,
|
||||
ulint flags2,
|
||||
bool init_stats_latch=true);
|
||||
|
||||
/****************************************************************//**
|
||||
Free a table memory object. */
|
||||
void
|
||||
|
|
@ -792,7 +797,7 @@ extern ulong zip_pad_max;
|
|||
an uncompressed page should be left as padding to avoid compression
|
||||
failures. This estimate is based on a self-adapting heuristic. */
|
||||
struct zip_pad_info_t {
|
||||
SysMutex* mutex; /*!< mutex protecting the info */
|
||||
mysql_mutex_t mutex; /*!< mutex protecting the info */
|
||||
ulint pad; /*!< number of bytes used as pad */
|
||||
ulint success;/*!< successful compression ops during
|
||||
current round */
|
||||
|
|
@ -800,9 +805,6 @@ struct zip_pad_info_t {
|
|||
current round */
|
||||
ulint n_rounds;/*!< number of currently successful
|
||||
rounds */
|
||||
volatile os_once::state_t
|
||||
mutex_created;
|
||||
/*!< Creation state of mutex member */
|
||||
};
|
||||
|
||||
/** Number of samples of data size kept when page compression fails for
|
||||
|
|
@ -1692,7 +1694,7 @@ struct dict_table_t {
|
|||
/** Statistics for query optimization. @{ */
|
||||
|
||||
/** Creation state of 'stats_latch'. */
|
||||
volatile os_once::state_t stats_latch_created;
|
||||
bool stats_latch_inited;
|
||||
|
||||
/** This latch protects:
|
||||
dict_table_t::stat_initialized,
|
||||
|
|
@ -1705,7 +1707,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. */
|
||||
|
|
@ -1829,11 +1831,8 @@ struct dict_table_t {
|
|||
from a select. */
|
||||
lock_t* autoinc_lock;
|
||||
|
||||
/** Creation state of autoinc_mutex member */
|
||||
volatile os_once::state_t autoinc_mutex_created;
|
||||
|
||||
/** Mutex protecting the autoincrement counter. */
|
||||
ib_mutex_t* autoinc_mutex;
|
||||
mysql_mutex_t autoinc_mutex;
|
||||
|
||||
/** Autoinc counter value to give to the next inserted row. */
|
||||
ib_uint64_t autoinc;
|
||||
|
|
@ -1927,64 +1926,6 @@ struct dict_foreign_add_to_referenced_table {
|
|||
}
|
||||
};
|
||||
|
||||
/** Destroy the autoinc latch of the given table.
|
||||
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 */
|
||||
inline
|
||||
void
|
||||
dict_table_autoinc_destroy(
|
||||
dict_table_t* table)
|
||||
{
|
||||
if (table->autoinc_mutex_created == os_once::DONE
|
||||
&& table->autoinc_mutex != NULL) {
|
||||
mutex_free(table->autoinc_mutex);
|
||||
UT_DELETE(table->autoinc_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/** Request for lazy creation of the autoinc latch of a given table.
|
||||
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 autoinc latch is to be created. */
|
||||
inline
|
||||
void
|
||||
dict_table_autoinc_create_lazy(
|
||||
dict_table_t* table)
|
||||
{
|
||||
table->autoinc_mutex = NULL;
|
||||
table->autoinc_mutex_created = os_once::NEVER_DONE;
|
||||
}
|
||||
|
||||
/** Request a lazy creation of dict_index_t::zip_pad::mutex.
|
||||
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] index index whose zip_pad mutex is to be created */
|
||||
inline
|
||||
void
|
||||
dict_index_zip_pad_mutex_create_lazy(
|
||||
dict_index_t* index)
|
||||
{
|
||||
index->zip_pad.mutex = NULL;
|
||||
index->zip_pad.mutex_created = os_once::NEVER_DONE;
|
||||
}
|
||||
|
||||
/** Destroy the zip_pad_mutex of the given index.
|
||||
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 */
|
||||
inline
|
||||
void
|
||||
dict_index_zip_pad_mutex_destroy(
|
||||
dict_index_t* index)
|
||||
{
|
||||
if (index->zip_pad.mutex_created == os_once::DONE
|
||||
&& index->zip_pad.mutex != NULL) {
|
||||
mutex_free(index->zip_pad.mutex);
|
||||
UT_DELETE(index->zip_pad.mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/** Release the zip_pad_mutex of a given index.
|
||||
@param[in,out] index index whose zip_pad_mutex is to be released */
|
||||
inline
|
||||
|
|
@ -1992,22 +1933,9 @@ void
|
|||
dict_index_zip_pad_unlock(
|
||||
dict_index_t* index)
|
||||
{
|
||||
mutex_exit(index->zip_pad.mutex);
|
||||
mysql_mutex_unlock(&index->zip_pad.mutex);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/** Check if the current thread owns the autoinc_mutex of a given table.
|
||||
@param[in] table the autoinc_mutex belongs to this table
|
||||
@return true, if the current thread owns the autoinc_mutex, false otherwise.*/
|
||||
inline
|
||||
bool
|
||||
dict_table_autoinc_own(
|
||||
const dict_table_t* table)
|
||||
{
|
||||
return(mutex_own(table->autoinc_mutex));
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/** Check whether the col is used in spatial index or regular index.
|
||||
@param[in] col column to check
|
||||
@return spatial status */
|
||||
|
|
|
|||
|
|
@ -1,118 +0,0 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file include/os0once.h
|
||||
A class that aids executing a given function exactly once in a multi-threaded
|
||||
environment.
|
||||
|
||||
Created Feb 20, 2014 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#ifndef os0once_h
|
||||
#define os0once_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "ut0ut.h"
|
||||
|
||||
/** Execute a given function exactly once in a multi-threaded environment
|
||||
or wait for the function to be executed by another thread.
|
||||
|
||||
Example usage:
|
||||
First the user must create a control variable of type os_once::state_t and
|
||||
assign it os_once::NEVER_DONE.
|
||||
Then the user must pass this variable, together with a function to be
|
||||
executed to os_once::do_or_wait_for_done().
|
||||
|
||||
Multiple threads can call os_once::do_or_wait_for_done() simultaneously with
|
||||
the same (os_once::state_t) control variable. The provided function will be
|
||||
called exactly once and when os_once::do_or_wait_for_done() returns then this
|
||||
function has completed execution, by this or another thread. In other words
|
||||
os_once::do_or_wait_for_done() will either execute the provided function or
|
||||
will wait for its execution to complete if it is already called by another
|
||||
thread or will do nothing if the function has already completed its execution
|
||||
earlier.
|
||||
|
||||
This mimics pthread_once(3), but unfortunatelly pthread_once(3) does not
|
||||
support passing arguments to the init_routine() function. We should use
|
||||
std::call_once() when we start compiling with C++11 enabled. */
|
||||
class os_once {
|
||||
public:
|
||||
/** Control variables' state type */
|
||||
typedef ib_uint32_t state_t;
|
||||
|
||||
/** Not yet executed. */
|
||||
static const state_t NEVER_DONE = 0;
|
||||
|
||||
/** Currently being executed by this or another thread. */
|
||||
static const state_t IN_PROGRESS = 1;
|
||||
|
||||
/** Finished execution. */
|
||||
static const state_t DONE = 2;
|
||||
|
||||
/** Call a given function or wait its execution to complete if it is
|
||||
already called by another thread.
|
||||
@param[in,out] state control variable
|
||||
@param[in] do_func function to call
|
||||
@param[in,out] do_func_arg an argument to pass to do_func(). */
|
||||
static
|
||||
void
|
||||
do_or_wait_for_done(
|
||||
volatile state_t* state,
|
||||
void (*do_func)(void*),
|
||||
void* do_func_arg)
|
||||
{
|
||||
int32 oldval = NEVER_DONE;
|
||||
|
||||
/* Avoid calling my_atomic_cas32() in the most common case. */
|
||||
if (*state == DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (my_atomic_cas32((int32*) state, &oldval, IN_PROGRESS)) {
|
||||
/* We are the first. Call the function. */
|
||||
|
||||
do_func(do_func_arg);
|
||||
|
||||
my_atomic_store32((int32*) state, DONE);
|
||||
} else {
|
||||
/* The state is not NEVER_DONE, so either it is
|
||||
IN_PROGRESS (somebody is calling the function right
|
||||
now or DONE (it has already been called and completed).
|
||||
Wait for it to become DONE. */
|
||||
for (;;) {
|
||||
const state_t s = *state;
|
||||
|
||||
switch (s) {
|
||||
case DONE:
|
||||
return;
|
||||
case IN_PROGRESS:
|
||||
break;
|
||||
case NEVER_DONE:
|
||||
/* fall through */
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
UT_RELAX_CPU();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* os0once_h */
|
||||
|
|
@ -1656,7 +1656,7 @@ page_zip_fields_free(
|
|||
{
|
||||
if (index) {
|
||||
dict_table_t* table = index->table;
|
||||
dict_index_zip_pad_mutex_destroy(index);
|
||||
mysql_mutex_destroy(&index->zip_pad.mutex);
|
||||
mem_heap_free(index->heap);
|
||||
|
||||
dict_mem_table_free(table);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue