Commit 5b3f7c0c authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-18220: Remove some redundant data structures

fts_state_t, fts_slot_t::state: Remove. Replaced by fts_slot_t::running
and fts_slot_t::table_id as follows.

FTS_STATE_SUSPENDED: Removed (unused).

FTS_STATE_EMPTY: Removed. table_id=0 will denote empty slots.

FTS_STATE_RUNNING: Equivalent to running=true.

FTS_STATE_LOADED, FTS_STATE_DONE: Equivalent to running=false.

fts_slot_t::table: Remove. Tables will be identified by table_id.
After opening a table, we will check fil_table_accessible() before
accessing the data.

fts_optimize_new_table(), fts_optimize_del_table(),
fts_optimize_how_many(), fts_is_sync_needed():
Remove the parameter tables, and use the static variable fts_slots
(which was introduced in MariaDB 10.2) instead.
parent 06442e3e
......@@ -2773,6 +2773,29 @@ fil_close_tablespace(
return(err);
}
/** Determine whether a table can be accessed in operations that are
not (necessarily) protected by meta-data locks.
(Rollback would generally be protected, but rollback of
FOREIGN KEY CASCADE/SET NULL is not protected by meta-data locks
but only by InnoDB table locks, which may be broken by
lock_remove_all_on_table().)
@param[in] table persistent table
checked @return whether the table is accessible */
UNIV_INTERN bool fil_table_accessible(const dict_table_t* table)
{
if (UNIV_UNLIKELY(!table->is_readable() || table->corrupted)) {
return(false);
}
if (fil_space_t* space = fil_space_acquire(table->space)) {
bool accessible = !space->is_stopping();
fil_space_release(space);
return(accessible);
} else {
return(false);
}
}
/** Delete a tablespace and associated .ibd file.
@param[in] id tablespace identifier
@param[in] drop_ahi whether to drop the adaptive hash index
......
......@@ -43,6 +43,9 @@ Completed 2011/7/10 Sunny and Jimmy Yang
/** The FTS optimize thread's work queue. */
static ib_wqueue_t* fts_optimize_wq;
/** The FTS vector to store fts_slot_t */
static ib_vector_t* fts_slots;
/** Time to wait for a message. */
static const ulint FTS_QUEUE_WAIT_IN_USECS = 5000000;
......@@ -58,15 +61,6 @@ static const ulint FTS_WORD_NODES_INIT_SIZE = 64;
/** Last time we did check whether system need a sync */
static ib_time_t last_check_sync_time;
/** State of a table within the optimization sub system. */
enum fts_state_t {
FTS_STATE_LOADED,
FTS_STATE_RUNNING,
FTS_STATE_SUSPENDED,
FTS_STATE_DONE,
FTS_STATE_EMPTY
};
/** FTS optimize thread message types. */
enum fts_msg_type_t {
FTS_MSG_STOP, /*!< Stop optimizing and exit thread */
......@@ -175,11 +169,11 @@ struct fts_encode_t {
/** We use this information to determine when to start the optimize
cycle for a table. */
struct fts_slot_t {
dict_table_t* table; /*!< Table to optimize */
/** table identifier, or 0 if the slot is empty */
table_id_t table_id;
table_id_t table_id; /*!< Table id */
fts_state_t state; /*!< State of this slot */
/** whether this slot is being processed */
bool running;
ulint added; /*!< Number of doc ids added since the
last time this table was optimized */
......@@ -2404,31 +2398,35 @@ fts_optimize_table_bk(
fts_slot_t* slot) /*!< in: table to optimiza */
{
dberr_t error;
dict_table_t* table = slot->table;
fts_t* fts = table->fts;
/* Avoid optimizing tables that were optimized recently. */
if (slot->last_run > 0
&& (ut_time() - slot->last_run) < slot->interval_time) {
return(DB_SUCCESS);
}
} else if (fts && fts->cache
&& fts->cache->deleted >= FTS_OPTIMIZE_THRESHOLD) {
dict_table_t* table = dict_table_open_on_id(
slot->table_id, FALSE, DICT_TABLE_OP_NORMAL);
if (table && fil_table_accessible(table)
&& table->fts && table->fts->cache
&& table->fts->cache->deleted >= FTS_OPTIMIZE_THRESHOLD) {
error = fts_optimize_table(table);
slot->last_run = ut_time();
if (error == DB_SUCCESS) {
slot->state = FTS_STATE_DONE;
slot->last_run = 0;
slot->completed = ut_time();
slot->running = false;
slot->completed = slot->last_run;
}
} else {
/* Note time this run completed. */
slot->last_run = ut_time();
error = DB_SUCCESS;
}
/* Note time this run completed. */
slot->last_run = ut_time();
dict_table_close(table, FALSE, FALSE);
return(error);
}
......@@ -2647,85 +2645,60 @@ fts_optimize_request_sync_table(
ib_wqueue_add(fts_optimize_wq, msg, msg->heap);
}
/**********************************************************************//**
Add the table to the vector if it doesn't already exist. */
static
ibool
fts_optimize_new_table(
/*===================*/
ib_vector_t* tables, /*!< in/out: vector of tables */
dict_table_t* table) /*!< in: table to add */
/** Add a table to fts_slots if it doesn't already exist. */
static bool fts_optimize_new_table(dict_table_t* table)
{
ulint i;
fts_slot_t* slot;
ulint empty_slot = ULINT_UNDEFINED;
fts_slot_t* empty = NULL;
const table_id_t table_id = table->id;
ut_ad(table_id);
/* Search for duplicates, also find a free slot if one exists. */
for (i = 0; i < ib_vector_size(tables); ++i) {
for (i = 0; i < ib_vector_size(fts_slots); ++i) {
slot = static_cast<fts_slot_t*>(
ib_vector_get(tables, i));
slot = static_cast<fts_slot_t*>(ib_vector_get(fts_slots, i));
if (slot->state == FTS_STATE_EMPTY) {
empty_slot = i;
} else if (slot->table->id == table->id) {
if (!slot->table_id) {
empty = slot;
} else if (slot->table_id == table_id) {
/* Already exists in our optimize queue. */
ut_ad(slot->table_id = table->id);
return(FALSE);
}
}
/* Reuse old slot. */
if (empty_slot != ULINT_UNDEFINED) {
slot = static_cast<fts_slot_t*>(
ib_vector_get(tables, empty_slot));
ut_a(slot->state == FTS_STATE_EMPTY);
} else { /* Create a new slot. */
slot = static_cast<fts_slot_t*>(ib_vector_push(tables, NULL));
}
slot = empty ? empty : static_cast<fts_slot_t*>(
ib_vector_push(fts_slots, NULL));
memset(slot, 0x0, sizeof(*slot));
slot->table = table;
slot->table_id = table->id;
slot->state = FTS_STATE_LOADED;
slot->running = false;
slot->interval_time = FTS_OPTIMIZE_INTERVAL_IN_SECS;
return(TRUE);
}
/**********************************************************************//**
Remove the table from the vector if it exists. */
static
ibool
fts_optimize_del_table(
/*===================*/
ib_vector_t* tables, /*!< in/out: vector of tables */
fts_msg_del_t* msg) /*!< in: table to delete */
/** Remove a table from fts_slots if it exists.
@param[in,out] table table to be removed from fts_slots */
static bool fts_optimize_del_table(const dict_table_t* table)
{
ulint i;
dict_table_t* table = msg->table;
const table_id_t table_id = table->id;
ut_ad(table_id);
for (i = 0; i < ib_vector_size(tables); ++i) {
for (ulint i = 0; i < ib_vector_size(fts_slots); ++i) {
fts_slot_t* slot;
slot = static_cast<fts_slot_t*>(ib_vector_get(tables, i));
/* FIXME: Should we assert on this ? */
if (slot->state != FTS_STATE_EMPTY
&& slot->table->id == table->id) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: FTS Optimize Removing "
"table %s\n", table->name);
slot = static_cast<fts_slot_t*>(ib_vector_get(fts_slots, i));
slot->table = NULL;
slot->state = FTS_STATE_EMPTY;
if (slot->table_id == table_id) {
if (fts_enable_diag_print) {
ib_logf(IB_LOG_LEVEL_INFO,
"FTS Optimize Removing table %s",
table->name);
}
slot->table_id = 0;
return(TRUE);
}
}
......@@ -2734,14 +2707,9 @@ fts_optimize_del_table(
}
/**********************************************************************//**
Calculate how many of the registered tables need to be optimized.
Calculate how many tables in fts_slots need to be optimized.
@return no. of tables to optimize */
static
ulint
fts_optimize_how_many(
/*==================*/
const ib_vector_t* tables) /*!< in: registered tables
vector*/
static ulint fts_optimize_how_many()
{
ulint i;
ib_time_t delta;
......@@ -2750,15 +2718,14 @@ fts_optimize_how_many(
current_time = ut_time();
for (i = 0; i < ib_vector_size(tables); ++i) {
const fts_slot_t* slot;
slot = static_cast<const fts_slot_t*>(
ib_vector_get_const(tables, i));
for (i = 0; i < ib_vector_size(fts_slots); ++i) {
const fts_slot_t* slot = static_cast<const fts_slot_t*>(
ib_vector_get_const(fts_slots, i));
if (slot->table_id == 0) {
continue;
}
switch (slot->state) {
case FTS_STATE_DONE:
case FTS_STATE_LOADED:
if (!slot->running) {
ut_a(slot->completed <= current_time);
delta = current_time - slot->completed;
......@@ -2767,9 +2734,7 @@ fts_optimize_how_many(
if (delta >= slot->interval_time) {
++n_tables;
}
break;
case FTS_STATE_RUNNING:
} else {
ut_a(slot->last_run <= current_time);
delta = current_time - slot->last_run;
......@@ -2777,15 +2742,7 @@ fts_optimize_how_many(
if (delta > slot->interval_time) {
++n_tables;
}
break;
/* Slots in a state other than the above
are ignored. */
case FTS_STATE_EMPTY:
case FTS_STATE_SUSPENDED:
break;
}
}
return(n_tables);
......@@ -2794,12 +2751,7 @@ fts_optimize_how_many(
/**********************************************************************//**
Check if the total memory used by all FTS table exceeds the maximum limit.
@return true if a sync is needed, false otherwise */
static
bool
fts_is_sync_needed(
/*===============*/
const ib_vector_t* tables) /*!< in: registered tables
vector*/
static bool fts_is_sync_needed()
{
ulint total_memory = 0;
double time_diff = difftime(ut_time(), last_check_sync_time);
......@@ -2810,17 +2762,26 @@ fts_is_sync_needed(
last_check_sync_time = ut_time();
for (ulint i = 0; i < ib_vector_size(tables); ++i) {
const fts_slot_t* slot;
for (ulint i = 0; i < ib_vector_size(fts_slots); ++i) {
const fts_slot_t* slot = static_cast<const fts_slot_t*>(
ib_vector_get_const(fts_slots, i));
if (slot->table_id == 0) {
continue;
}
slot = static_cast<const fts_slot_t*>(
ib_vector_get_const(tables, i));
dict_table_t* table = dict_table_open_on_id(
slot->table_id, FALSE, DICT_TABLE_OP_NORMAL);
if (!table) {
continue;
}
if (slot->state != FTS_STATE_EMPTY && slot->table
&& slot->table->fts) {
total_memory += slot->table->fts->cache->total_size;
if (table->fts && table->fts->cache) {
total_memory += table->fts->cache->total_size;
}
dict_table_close(table, FALSE, FALSE);
if (total_memory > fts_max_total_cache_size) {
return(true);
}
......@@ -2831,16 +2792,12 @@ fts_is_sync_needed(
/** Sync fts cache of a table
@param[in] table_id table id */
void
fts_optimize_sync_table(
table_id_t table_id)
static void fts_optimize_sync_table(table_id_t table_id)
{
dict_table_t* table = NULL;
table = dict_table_open_on_id(table_id, FALSE, DICT_TABLE_OP_NORMAL);
if (table) {
if (dict_table_has_fts_index(table) && table->fts->cache) {
if (dict_table_t* table = dict_table_open_on_id(
table_id, FALSE, DICT_TABLE_OP_NORMAL)) {
if (fil_table_accessible(table)
&& table->fts && table->fts->cache) {
fts_sync_table(table, true, false, false);
}
......@@ -2858,7 +2815,6 @@ fts_optimize_thread(
void* arg) /*!< in: work queue*/
{
mem_heap_t* heap;
ib_vector_t* tables;
ib_alloc_t* heap_alloc;
ulint current = 0;
ibool done = FALSE;
......@@ -2873,7 +2829,7 @@ fts_optimize_thread(
heap = mem_heap_create(sizeof(dict_table_t*) * 64);
heap_alloc = ib_heap_allocator_create(heap);
tables = ib_vector_create(heap_alloc, sizeof(fts_slot_t), 4);
fts_slots = ib_vector_create(heap_alloc, sizeof(fts_slot_t), 4);
while(!done && srv_shutdown_state == SRV_SHUTDOWN_NONE) {
......@@ -2884,28 +2840,18 @@ fts_optimize_thread(
&& ib_wqueue_is_empty(wq)
&& n_tables > 0
&& n_optimize > 0) {
fts_slot_t* slot;
ut_a(ib_vector_size(tables) > 0);
slot = static_cast<fts_slot_t*>(
ib_vector_get(tables, current));
fts_slot_t* slot = static_cast<fts_slot_t*>(
ib_vector_get(fts_slots, current));
/* Handle the case of empty slots. */
if (slot->state != FTS_STATE_EMPTY) {
slot->state = FTS_STATE_RUNNING;
if (slot->table_id) {
slot->running = true;
fts_optimize_table_bk(slot);
}
++current;
/* Wrap around the counter. */
if (current >= ib_vector_size(tables)) {
n_optimize = fts_optimize_how_many(tables);
if (++current >= ib_vector_size(fts_slots)) {
n_optimize = fts_optimize_how_many();
current = 0;
}
......@@ -2917,7 +2863,7 @@ fts_optimize_thread(
/* Timeout ? */
if (msg == NULL) {
if (fts_is_sync_needed(tables)) {
if (fts_is_sync_needed()) {
fts_need_sync = true;
}
......@@ -2933,17 +2879,16 @@ fts_optimize_thread(
case FTS_MSG_ADD_TABLE:
ut_a(!done);
if (fts_optimize_new_table(
tables,
static_cast<dict_table_t*>(
msg->ptr))) {
static_cast<dict_table_t*>(
msg->ptr))) {
++n_tables;
}
break;
case FTS_MSG_DEL_TABLE:
if (fts_optimize_del_table(
tables, static_cast<fts_msg_del_t*>(
msg->ptr))) {
static_cast<fts_msg_del_t*>(
msg->ptr)->table)) {
--n_tables;
}
......@@ -2967,33 +2912,25 @@ fts_optimize_thread(
}
mem_heap_free(msg->heap);
if (!done) {
n_optimize = fts_optimize_how_many(tables);
} else {
n_optimize = 0;
}
n_optimize = done ? 0 : fts_optimize_how_many();
}
}
/* Server is being shutdown, sync the data from FTS cache to disk
if needed */
if (n_tables > 0) {
ulint i;
for (i = 0; i < ib_vector_size(tables); i++) {
fts_slot_t* slot;
slot = static_cast<fts_slot_t*>(
ib_vector_get(tables, i));
for (ulint i = 0; i < ib_vector_size(fts_slots); i++) {
fts_slot_t* slot = static_cast<fts_slot_t*>(
ib_vector_get(fts_slots, i));
if (slot->state != FTS_STATE_EMPTY) {
fts_optimize_sync_table(slot->table_id);
if (table_id_t table_id = slot->table_id) {
fts_optimize_sync_table(table_id);
}
}
}
ib_vector_free(tables);
ib_vector_free(fts_slots);
fts_slots = NULL;
ib_logf(IB_LOG_LEVEL_INFO, "FTS optimize thread exiting.");
......
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2018, MariaDB Corporation.
Copyright (c) 2013, 2019, MariaDB Corporation.
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
......@@ -843,6 +843,18 @@ fil_op_log_parse_or_replay(
only be parsed but not replayed */
ulint log_flags); /*!< in: redo log flags
(stored in the page number parameter) */
/** Determine whether a table can be accessed in operations that are
not (necessarily) protected by meta-data locks.
(Rollback would generally be protected, but rollback of
FOREIGN KEY CASCADE/SET NULL is not protected by meta-data locks
but only by InnoDB table locks, which may be broken by
lock_remove_all_on_table().)
@param[in] table persistent table
checked @return whether the table is accessible */
UNIV_INTERN bool fil_table_accessible(const dict_table_t* table)
MY_ATTRIBUTE((warn_unused_result, nonnull));
/** Delete a tablespace and associated .ibd file.
@param[in] id tablespace identifier
@param[in] drop_ahi whether to drop the adaptive hash index
......
......@@ -2819,6 +2819,29 @@ fil_close_tablespace(
return(err);
}
/** Determine whether a table can be accessed in operations that are
not (necessarily) protected by meta-data locks.
(Rollback would generally be protected, but rollback of
FOREIGN KEY CASCADE/SET NULL is not protected by meta-data locks
but only by InnoDB table locks, which may be broken by
lock_remove_all_on_table().)
@param[in] table persistent table
checked @return whether the table is accessible */
UNIV_INTERN bool fil_table_accessible(const dict_table_t* table)
{
if (UNIV_UNLIKELY(!table->is_readable() || table->corrupted)) {
return(false);
}
if (fil_space_t* space = fil_space_acquire(table->space)) {
bool accessible = !space->is_stopping();
fil_space_release(space);
return(accessible);
} else {
return(false);
}
}
/** Delete a tablespace and associated .ibd file.
@param[in] id tablespace identifier
@param[in] drop_ahi whether to drop the adaptive hash index
......
......@@ -43,6 +43,9 @@ Completed 2011/7/10 Sunny and Jimmy Yang
/** The FTS optimize thread's work queue. */
static ib_wqueue_t* fts_optimize_wq;
/** The FTS vector to store fts_slot_t */
static ib_vector_t* fts_slots;
/** Time to wait for a message. */
static const ulint FTS_QUEUE_WAIT_IN_USECS = 5000000;
......@@ -58,15 +61,6 @@ static const ulint FTS_WORD_NODES_INIT_SIZE = 64;
/** Last time we did check whether system need a sync */
static ib_time_t last_check_sync_time;
/** State of a table within the optimization sub system. */
enum fts_state_t {
FTS_STATE_LOADED,
FTS_STATE_RUNNING,
FTS_STATE_SUSPENDED,
FTS_STATE_DONE,
FTS_STATE_EMPTY
};
/** FTS optimize thread message types. */
enum fts_msg_type_t {
FTS_MSG_STOP, /*!< Stop optimizing and exit thread */
......@@ -175,11 +169,11 @@ struct fts_encode_t {
/** We use this information to determine when to start the optimize
cycle for a table. */
struct fts_slot_t {
dict_table_t* table; /*!< Table to optimize */
/** table identifier, or 0 if the slot is empty */
table_id_t table_id;
table_id_t table_id; /*!< Table id */
fts_state_t state; /*!< State of this slot */
/** whether this slot is being processed */
bool running;
ulint added; /*!< Number of doc ids added since the
last time this table was optimized */
......@@ -2404,31 +2398,35 @@ fts_optimize_table_bk(
fts_slot_t* slot) /*!< in: table to optimiza */
{
dberr_t error;
dict_table_t* table = slot->table;
fts_t* fts = table->fts;
/* Avoid optimizing tables that were optimized recently. */
if (slot->last_run > 0
&& (ut_time() - slot->last_run) < slot->interval_time) {
return(DB_SUCCESS);
}
} else if (fts && fts->cache
&& fts->cache->deleted >= FTS_OPTIMIZE_THRESHOLD) {
dict_table_t* table = dict_table_open_on_id(
slot->table_id, FALSE, DICT_TABLE_OP_NORMAL);
if (table && fil_table_accessible(table)
&& table->fts && table->fts->cache
&& table->fts->cache->deleted >= FTS_OPTIMIZE_THRESHOLD) {
error = fts_optimize_table(table);
slot->last_run = ut_time();
if (error == DB_SUCCESS) {
slot->state = FTS_STATE_DONE;
slot->last_run = 0;
slot->completed = ut_time();
slot->running = false;
slot->completed = slot->last_run;
}
} else {
/* Note time this run completed. */
slot->last_run = ut_time();
error = DB_SUCCESS;
}
/* Note time this run completed. */
slot->last_run = ut_time();
dict_table_close(table, FALSE, FALSE);
return(error);
}
......@@ -2647,85 +2645,60 @@ fts_optimize_request_sync_table(
ib_wqueue_add(fts_optimize_wq, msg, msg->heap);
}
/**********************************************************************//**
Add the table to the vector if it doesn't already exist. */
static
ibool
fts_optimize_new_table(
/*===================*/
ib_vector_t* tables, /*!< in/out: vector of tables */
dict_table_t* table) /*!< in: table to add */
/** Add a table to fts_slots if it doesn't already exist. */
static bool fts_optimize_new_table(dict_table_t* table)
{
ulint i;
fts_slot_t* slot;
ulint empty_slot = ULINT_UNDEFINED;
fts_slot_t* empty = NULL;
const table_id_t table_id = table->id;
ut_ad(table_id);
/* Search for duplicates, also find a free slot if one exists. */
for (i = 0; i < ib_vector_size(tables); ++i) {
for (i = 0; i < ib_vector_size(fts_slots); ++i) {
slot = static_cast<fts_slot_t*>(
ib_vector_get(tables, i));
slot = static_cast<fts_slot_t*>(ib_vector_get(fts_slots, i));
if (slot->state == FTS_STATE_EMPTY) {
empty_slot = i;
} else if (slot->table->id == table->id) {
if (!slot->table_id) {
empty = slot;
} else if (slot->table_id == table_id) {
/* Already exists in our optimize queue. */
ut_ad(slot->table_id = table->id);
return(FALSE);
}
}
/* Reuse old slot. */
if (empty_slot != ULINT_UNDEFINED) {
slot = static_cast<fts_slot_t*>(
ib_vector_get(tables, empty_slot));
ut_a(slot->state == FTS_STATE_EMPTY);
} else { /* Create a new slot. */
slot = static_cast<fts_slot_t*>(ib_vector_push(tables, NULL));
}
slot = empty ? empty : static_cast<fts_slot_t*>(
ib_vector_push(fts_slots, NULL));
memset(slot, 0x0, sizeof(*slot));
slot->table = table;
slot->table_id = table->id;
slot->state = FTS_STATE_LOADED;
slot->running = false;
slot->interval_time = FTS_OPTIMIZE_INTERVAL_IN_SECS;
return(TRUE);
}
/**********************************************************************//**
Remove the table from the vector if it exists. */
static
ibool
fts_optimize_del_table(
/*===================*/
ib_vector_t* tables, /*!< in/out: vector of tables */
fts_msg_del_t* msg) /*!< in: table to delete */
/** Remove a table from fts_slots if it exists.
@param[in,out] table table to be removed from fts_slots */
static bool fts_optimize_del_table(const dict_table_t* table)
{
ulint i;
dict_table_t* table = msg->table;
const table_id_t table_id = table->id;
ut_ad(table_id);
for (i = 0; i < ib_vector_size(tables); ++i) {
for (ulint i = 0; i < ib_vector_size(fts_slots); ++i) {
fts_slot_t* slot;
slot = static_cast<fts_slot_t*>(ib_vector_get(tables, i));
/* FIXME: Should we assert on this ? */
if (slot->state != FTS_STATE_EMPTY
&& slot->table->id == table->id) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: FTS Optimize Removing "
"table %s\n", table->name);
slot = static_cast<fts_slot_t*>(ib_vector_get(fts_slots, i));
slot->table = NULL;
slot->state = FTS_STATE_EMPTY;
if (slot->table_id == table_id) {
if (fts_enable_diag_print) {
ib_logf(IB_LOG_LEVEL_INFO,
"FTS Optimize Removing table %s",
table->name);
}
slot->table_id = 0;
return(TRUE);
}
}
......@@ -2734,14 +2707,9 @@ fts_optimize_del_table(
}
/**********************************************************************//**
Calculate how many of the registered tables need to be optimized.
Calculate how many tables in fts_slots need to be optimized.
@return no. of tables to optimize */
static
ulint
fts_optimize_how_many(
/*==================*/
const ib_vector_t* tables) /*!< in: registered tables
vector*/
static ulint fts_optimize_how_many()
{
ulint i;
ib_time_t delta;
......@@ -2750,15 +2718,14 @@ fts_optimize_how_many(
current_time = ut_time();
for (i = 0; i < ib_vector_size(tables); ++i) {
const fts_slot_t* slot;
slot = static_cast<const fts_slot_t*>(
ib_vector_get_const(tables, i));
for (i = 0; i < ib_vector_size(fts_slots); ++i) {
const fts_slot_t* slot = static_cast<const fts_slot_t*>(
ib_vector_get_const(fts_slots, i));
if (slot->table_id == 0) {
continue;
}
switch (slot->state) {
case FTS_STATE_DONE:
case FTS_STATE_LOADED:
if (!slot->running) {
ut_a(slot->completed <= current_time);
delta = current_time - slot->completed;
......@@ -2767,9 +2734,7 @@ fts_optimize_how_many(
if (delta >= slot->interval_time) {
++n_tables;
}
break;
case FTS_STATE_RUNNING:
} else {
ut_a(slot->last_run <= current_time);
delta = current_time - slot->last_run;
......@@ -2777,15 +2742,7 @@ fts_optimize_how_many(
if (delta > slot->interval_time) {
++n_tables;
}
break;
/* Slots in a state other than the above
are ignored. */
case FTS_STATE_EMPTY:
case FTS_STATE_SUSPENDED:
break;
}
}
return(n_tables);
......@@ -2794,12 +2751,7 @@ fts_optimize_how_many(
/**********************************************************************//**
Check if the total memory used by all FTS table exceeds the maximum limit.
@return true if a sync is needed, false otherwise */
static
bool
fts_is_sync_needed(
/*===============*/
const ib_vector_t* tables) /*!< in: registered tables
vector*/
static bool fts_is_sync_needed()
{
ulint total_memory = 0;
double time_diff = difftime(ut_time(), last_check_sync_time);
......@@ -2810,17 +2762,26 @@ fts_is_sync_needed(
last_check_sync_time = ut_time();
for (ulint i = 0; i < ib_vector_size(tables); ++i) {
const fts_slot_t* slot;
for (ulint i = 0; i < ib_vector_size(fts_slots); ++i) {
const fts_slot_t* slot = static_cast<const fts_slot_t*>(
ib_vector_get_const(fts_slots, i));
if (slot->table_id == 0) {
continue;
}
slot = static_cast<const fts_slot_t*>(
ib_vector_get_const(tables, i));
dict_table_t* table = dict_table_open_on_id(
slot->table_id, FALSE, DICT_TABLE_OP_NORMAL);
if (!table) {
continue;
}
if (slot->state != FTS_STATE_EMPTY && slot->table
&& slot->table->fts) {
total_memory += slot->table->fts->cache->total_size;
if (table->fts && table->fts->cache) {
total_memory += table->fts->cache->total_size;
}
dict_table_close(table, FALSE, FALSE);
if (total_memory > fts_max_total_cache_size) {
return(true);
}
......@@ -2831,16 +2792,12 @@ fts_is_sync_needed(
/** Sync fts cache of a table
@param[in] table_id table id */
void
fts_optimize_sync_table(
table_id_t table_id)
static void fts_optimize_sync_table(table_id_t table_id)
{
dict_table_t* table = NULL;
table = dict_table_open_on_id(table_id, FALSE, DICT_TABLE_OP_NORMAL);
if (table) {
if (dict_table_has_fts_index(table) && table->fts->cache) {
if (dict_table_t* table = dict_table_open_on_id(
table_id, FALSE, DICT_TABLE_OP_NORMAL)) {
if (fil_table_accessible(table)
&& table->fts && table->fts->cache) {
fts_sync_table(table, true, false, false);
}
......@@ -2858,7 +2815,6 @@ fts_optimize_thread(
void* arg) /*!< in: work queue*/
{
mem_heap_t* heap;
ib_vector_t* tables;
ib_alloc_t* heap_alloc;
ulint current = 0;
ibool done = FALSE;
......@@ -2873,7 +2829,7 @@ fts_optimize_thread(
heap = mem_heap_create(sizeof(dict_table_t*) * 64);
heap_alloc = ib_heap_allocator_create(heap);
tables = ib_vector_create(heap_alloc, sizeof(fts_slot_t), 4);
fts_slots = ib_vector_create(heap_alloc, sizeof(fts_slot_t), 4);
while(!done && srv_shutdown_state == SRV_SHUTDOWN_NONE) {
......@@ -2884,28 +2840,18 @@ fts_optimize_thread(
&& ib_wqueue_is_empty(wq)
&& n_tables > 0
&& n_optimize > 0) {
fts_slot_t* slot;
ut_a(ib_vector_size(tables) > 0);
slot = static_cast<fts_slot_t*>(
ib_vector_get(tables, current));
fts_slot_t* slot = static_cast<fts_slot_t*>(
ib_vector_get(fts_slots, current));
/* Handle the case of empty slots. */
if (slot->state != FTS_STATE_EMPTY) {
slot->state = FTS_STATE_RUNNING;
if (slot->table_id) {
slot->running = true;
fts_optimize_table_bk(slot);
}
++current;
/* Wrap around the counter. */
if (current >= ib_vector_size(tables)) {
n_optimize = fts_optimize_how_many(tables);
if (++current >= ib_vector_size(fts_slots)) {
n_optimize = fts_optimize_how_many();
current = 0;
}
......@@ -2917,7 +2863,7 @@ fts_optimize_thread(
/* Timeout ? */
if (msg == NULL) {
if (fts_is_sync_needed(tables)) {
if (fts_is_sync_needed()) {
fts_need_sync = true;
}
......@@ -2933,17 +2879,16 @@ fts_optimize_thread(
case FTS_MSG_ADD_TABLE:
ut_a(!done);
if (fts_optimize_new_table(
tables,
static_cast<dict_table_t*>(
msg->ptr))) {
static_cast<dict_table_t*>(
msg->ptr))) {
++n_tables;
}
break;
case FTS_MSG_DEL_TABLE:
if (fts_optimize_del_table(
tables, static_cast<fts_msg_del_t*>(
msg->ptr))) {
static_cast<fts_msg_del_t*>(
msg->ptr)->table)) {
--n_tables;
}
......@@ -2967,33 +2912,25 @@ fts_optimize_thread(
}
mem_heap_free(msg->heap);
if (!done) {
n_optimize = fts_optimize_how_many(tables);
} else {
n_optimize = 0;
}
n_optimize = done ? 0 : fts_optimize_how_many();
}
}
/* Server is being shutdown, sync the data from FTS cache to disk
if needed */
if (n_tables > 0) {
ulint i;
for (i = 0; i < ib_vector_size(tables); i++) {
fts_slot_t* slot;
slot = static_cast<fts_slot_t*>(
ib_vector_get(tables, i));
for (ulint i = 0; i < ib_vector_size(fts_slots); i++) {
fts_slot_t* slot = static_cast<fts_slot_t*>(
ib_vector_get(fts_slots, i));
if (slot->state != FTS_STATE_EMPTY) {
fts_optimize_sync_table(slot->table_id);
if (table_id_t table_id = slot->table_id) {
fts_optimize_sync_table(table_id);
}
}
}
ib_vector_free(tables);
ib_vector_free(fts_slots);
fts_slots = NULL;
ib_logf(IB_LOG_LEVEL_INFO, "FTS optimize thread exiting.");
......
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2018, MariaDB Corporation.
Copyright (c) 2013, 2019, MariaDB Corporation.
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
......@@ -841,6 +841,18 @@ fil_op_log_parse_or_replay(
only be parsed but not replayed */
ulint log_flags); /*!< in: redo log flags
(stored in the page number parameter) */
/** Determine whether a table can be accessed in operations that are
not (necessarily) protected by meta-data locks.
(Rollback would generally be protected, but rollback of
FOREIGN KEY CASCADE/SET NULL is not protected by meta-data locks
but only by InnoDB table locks, which may be broken by
lock_remove_all_on_table().)
@param[in] table persistent table
checked @return whether the table is accessible */
UNIV_INTERN bool fil_table_accessible(const dict_table_t* table)
MY_ATTRIBUTE((warn_unused_result, nonnull));
/** Delete a tablespace and associated .ibd file.
@param[in] id tablespace identifier
@param[in] drop_ahi whether to drop the adaptive hash index
......
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