summaryrefslogtreecommitdiff
path: root/storage/innobase/fts/fts0fts.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/fts/fts0fts.cc')
-rw-r--r--storage/innobase/fts/fts0fts.cc265
1 files changed, 58 insertions, 207 deletions
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index b73dd4cde03..3cb48765791 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -38,6 +38,22 @@ Full Text Search interface
#include "dict0stats.h"
#include "btr0pcur.h"
+/** The SYNC state of the cache. There is one instance of this struct
+associated with each ADD thread. */
+struct fts_sync_t {
+ /** Transaction used for SYNCing the cache to disk */
+ trx_t *trx;
+ /** Table with FTS index(es) */
+ dict_table_t *table;
+ /** Max size in bytes of the cache */
+ ulint max_cache_size;
+ /** The doc id at which the cache was noted as being
+ full, we use this to set the upper_limit field */
+ doc_id_t max_doc_id;
+ /** SYNC start time; only used if fts_enable_diag_print */
+ time_t start_time;
+};
+
static const ulint FTS_MAX_ID_LEN = 32;
/** Column name from the FTS config table */
@@ -185,15 +201,8 @@ struct fts_tokenize_param_t {
/** Run SYNC on the table, i.e., write out data from the cache to the
FTS auxiliary INDEX table and clear the cache at the end.
@param[in,out] sync sync state
-@param[in] unlock_cache whether unlock cache lock when write node
-@param[in] wait whether wait when a sync is in progress
@return DB_SUCCESS if all OK */
-static
-dberr_t
-fts_sync(
- fts_sync_t* sync,
- bool unlock_cache,
- bool wait);
+static dberr_t fts_sync(fts_sync_t *sync);
/****************************************************************//**
Release all resources help by the words rb tree e.g., the node ilist. */
@@ -266,7 +275,6 @@ fts_cache_destroy(fts_cache_t* cache)
mysql_mutex_destroy(&cache->init_lock);
mysql_mutex_destroy(&cache->deleted_lock);
mysql_mutex_destroy(&cache->doc_id_lock);
- pthread_cond_destroy(&cache->sync->cond);
if (cache->stopword_info.cached_stopword) {
rbt_free(cache->stopword_info.cached_stopword);
@@ -540,7 +548,6 @@ fts_index_cache_init(
for (i = 0; i < FTS_NUM_AUX_INDEX; ++i) {
ut_a(index_cache->ins_graph[i] == NULL);
- ut_a(index_cache->sel_graph[i] == NULL);
}
}
@@ -610,7 +617,6 @@ fts_cache_create(
mem_heap_zalloc(heap, sizeof(fts_sync_t)));
cache->sync->table = table;
- pthread_cond_init(&cache->sync->cond, nullptr);
/* Create the index cache vector that will hold the inverted indexes. */
cache->indexes = ib_vector_create(
@@ -935,10 +941,6 @@ fts_cache_index_cache_create(
mem_heap_zalloc(static_cast<mem_heap_t*>(
cache->self_heap->arg), n_bytes));
- index_cache->sel_graph = static_cast<que_t**>(
- mem_heap_zalloc(static_cast<mem_heap_t*>(
- cache->self_heap->arg), n_bytes));
-
fts_index_cache_init(cache->sync_heap, index_cache);
if (cache->get_docs) {
@@ -1012,13 +1014,6 @@ fts_cache_clear(
index_cache->ins_graph[j] = NULL;
}
-
- if (index_cache->sel_graph[j] != NULL) {
-
- que_graph_free(index_cache->sel_graph[j]);
-
- index_cache->sel_graph[j] = NULL;
- }
}
index_cache->doc_stats = NULL;
@@ -1311,8 +1306,7 @@ fts_cache_add_doc(
ib_vector_last(word->nodes));
}
- if (fts_node == NULL || fts_node->synced
- || fts_node->ilist_size > FTS_ILIST_MAX_SIZE
+ if (!fts_node || fts_node->ilist_size > FTS_ILIST_MAX_SIZE
|| doc_id < fts_node->last_doc_id) {
fts_node = static_cast<fts_node_t*>(
@@ -3284,7 +3278,7 @@ fts_add_doc_from_tuple(
if (cache->total_size > fts_max_cache_size / 5
|| fts_need_sync) {
- fts_sync(cache->sync, true, false);
+ fts_sync(cache->sync);
}
mtr_start(&mtr);
@@ -3444,42 +3438,34 @@ fts_add_doc_by_id(
get_doc->index_cache,
doc_id, doc.tokens);
- bool need_sync = !cache->sync->in_progress
- && (fts_need_sync
- || (cache->total_size
- - cache->total_size_at_sync)
- > fts_max_cache_size / 10);
- if (need_sync) {
- cache->total_size_at_sync =
- cache->total_size;
- }
+ /** FTS cache sync should happen
+ frequently. Because user thread
+ shouldn't hold the cache lock for
+ longer time. So cache should sync
+ whenever cache size exceeds 512 KB */
+ bool need_sync =
+ cache->total_size > 512*1024;
mysql_mutex_unlock(&table->fts->cache->lock);
DBUG_EXECUTE_IF(
"fts_instrument_sync",
- fts_optimize_request_sync_table(table);
- mysql_mutex_lock(&cache->lock);
- if (cache->sync->in_progress)
- my_cond_wait(
- &cache->sync->cond,
- &cache->lock.m_mutex);
- mysql_mutex_unlock(&cache->lock);
+ fts_sync_table(table);
);
DBUG_EXECUTE_IF(
"fts_instrument_sync_debug",
- fts_sync(cache->sync, true, true);
+ fts_sync(cache->sync);
);
DEBUG_SYNC_C("fts_instrument_sync_request");
DBUG_EXECUTE_IF(
"fts_instrument_sync_request",
- fts_optimize_request_sync_table(table);
+ need_sync= true;
);
if (need_sync) {
- fts_optimize_request_sync_table(table);
+ fts_sync_table(table);
}
mtr_start(&mtr);
@@ -3846,15 +3832,13 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t
fts_sync_write_words(
trx_t* trx,
- fts_index_cache_t* index_cache,
- bool unlock_cache)
+ fts_index_cache_t* index_cache)
{
fts_table_t fts_table;
ulint n_nodes = 0;
ulint n_words = 0;
const ib_rbt_node_t* rbt_node;
dberr_t error = DB_SUCCESS;
- ibool print_error = FALSE;
dict_table_t* table = index_cache->index->table;
FTS_INIT_INDEX_TABLE(
@@ -3885,53 +3869,35 @@ fts_sync_write_words(
fts_table.suffix = fts_get_suffix(selected);
- /* We iterate over all the nodes even if there was an error */
for (i = 0; i < ib_vector_size(word->nodes); ++i) {
fts_node_t* fts_node = static_cast<fts_node_t*>(
ib_vector_get(word->nodes, i));
- if (fts_node->synced) {
- continue;
- } else {
- fts_node->synced = true;
- }
-
- /*FIXME: we need to handle the error properly. */
- if (error == DB_SUCCESS) {
- if (unlock_cache) {
- mysql_mutex_unlock(
- &table->fts->cache->lock);
- }
-
- error = fts_write_node(
- trx,
- &index_cache->ins_graph[selected],
- &fts_table, &word->text, fts_node);
+ error = fts_write_node(
+ trx, &index_cache->ins_graph[selected],
+ &fts_table, &word->text, fts_node);
- DEBUG_SYNC_C("fts_write_node");
- DBUG_EXECUTE_IF("fts_write_node_crash",
+ DEBUG_SYNC_C("fts_write_node");
+ DBUG_EXECUTE_IF("fts_write_node_crash",
DBUG_SUICIDE(););
- DBUG_EXECUTE_IF(
- "fts_instrument_sync_sleep",
+ DBUG_EXECUTE_IF("fts_instrument_sync_sleep",
std::this_thread::sleep_for(
std::chrono::seconds(1)););
- if (unlock_cache) {
- mysql_mutex_lock(
- &table->fts->cache->lock);
- }
+ if (error != DB_SUCCESS) {
+ goto err_exit;
}
}
n_nodes += ib_vector_size(word->nodes);
- if (UNIV_UNLIKELY(error != DB_SUCCESS) && !print_error) {
+ if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
+err_exit:
ib::error() << "(" << error << ") writing"
" word node to FTS auxiliary index table "
<< table->name;
- print_error = TRUE;
}
}
@@ -3990,58 +3956,7 @@ fts_sync_index(
ut_ad(rbt_validate(index_cache->words));
- return(fts_sync_write_words(trx, index_cache, sync->unlock_cache));
-}
-
-/** Check if index cache has been synced completely
-@param[in,out] index_cache index cache
-@return true if index is synced, otherwise false. */
-static
-bool
-fts_sync_index_check(
- fts_index_cache_t* index_cache)
-{
- const ib_rbt_node_t* rbt_node;
-
- for (rbt_node = rbt_first(index_cache->words);
- rbt_node != NULL;
- rbt_node = rbt_next(index_cache->words, rbt_node)) {
-
- fts_tokenizer_word_t* word;
- word = rbt_value(fts_tokenizer_word_t, rbt_node);
-
- fts_node_t* fts_node;
- fts_node = static_cast<fts_node_t*>(ib_vector_last(word->nodes));
-
- if (!fts_node->synced) {
- return(false);
- }
- }
-
- return(true);
-}
-
-/** Reset synced flag in index cache when rollback
-@param[in,out] index_cache index cache */
-static
-void
-fts_sync_index_reset(
- fts_index_cache_t* index_cache)
-{
- const ib_rbt_node_t* rbt_node;
-
- for (rbt_node = rbt_first(index_cache->words);
- rbt_node != NULL;
- rbt_node = rbt_next(index_cache->words, rbt_node)) {
-
- fts_tokenizer_word_t* word;
- word = rbt_value(fts_tokenizer_word_t, rbt_node);
-
- fts_node_t* fts_node;
- fts_node = static_cast<fts_node_t*>(ib_vector_last(word->nodes));
-
- fts_node->synced = false;
- }
+ return(fts_sync_write_words(trx, index_cache));
}
/** Commit the SYNC, change state of processed doc ids etc.
@@ -4074,14 +3989,14 @@ fts_sync_commit(
sync, cache->deleted_doc_ids);
}
- /* We need to do this within the deleted lock since fts_delete() can
- attempt to add a deleted doc id to the cache deleted id array. */
- fts_cache_clear(cache);
- DEBUG_SYNC_C("fts_deleted_doc_ids_clear");
- fts_cache_init(cache);
- mysql_mutex_unlock(&cache->lock);
-
if (UNIV_LIKELY(error == DB_SUCCESS)) {
+ /* We need to do this within the deleted lock
+ since fts_delete() can attempt to add a deleted
+ doc id to the cache deleted id array. */
+ fts_cache_clear(cache);
+ DEBUG_SYNC_C("fts_deleted_doc_ids_clear");
+ fts_cache_init(cache);
+ mysql_mutex_unlock(&cache->lock);
fts_sql_commit(trx);
} else {
fts_sql_rollback(trx);
@@ -4123,10 +4038,6 @@ fts_sync_rollback(
index_cache = static_cast<fts_index_cache_t*>(
ib_vector_get(cache->indexes, i));
- /* Reset synced flag so nodes will not be skipped
- in the next sync, see fts_sync_write_words(). */
- fts_sync_index_reset(index_cache);
-
for (j = 0; fts_index_selector[j].value; ++j) {
if (index_cache->ins_graph[j] != NULL) {
@@ -4135,13 +4046,6 @@ fts_sync_rollback(
index_cache->ins_graph[j] = NULL;
}
-
- if (index_cache->sel_graph[j] != NULL) {
-
- que_graph_free(index_cache->sel_graph[j]);
-
- index_cache->sel_graph[j] = NULL;
- }
}
}
@@ -4160,12 +4064,7 @@ FTS auxiliary INDEX table and clear the cache at the end.
@param[in] unlock_cache whether unlock cache lock when write node
@param[in] wait whether wait when a sync is in progress
@return DB_SUCCESS if all OK */
-static
-dberr_t
-fts_sync(
- fts_sync_t* sync,
- bool unlock_cache,
- bool wait)
+static dberr_t fts_sync(fts_sync_t *sync)
{
if (srv_read_only_mode) {
return DB_READ_ONLY;
@@ -4176,33 +4075,13 @@ fts_sync(
fts_cache_t* cache = sync->table->fts->cache;
mysql_mutex_lock(&cache->lock);
-
- /* Check if cache is being synced.
- Note: we release cache lock in fts_sync_write_words() to
- avoid long wait for the lock by other threads. */
- if (sync->in_progress) {
- if (!wait) {
- mysql_mutex_unlock(&cache->lock);
- return(DB_SUCCESS);
- }
- do {
- my_cond_wait(&sync->cond, &cache->lock.m_mutex);
- } while (sync->in_progress);
- }
-
- sync->unlock_cache = unlock_cache;
- sync->in_progress = true;
-
DEBUG_SYNC_C("fts_sync_begin");
fts_sync_begin(sync);
-begin_sync:
const size_t fts_cache_size= fts_max_cache_size;
if (cache->total_size > fts_cache_size) {
/* Avoid the case: sync never finish when
insert/update keeps comming. */
- ut_ad(sync->unlock_cache);
- sync->unlock_cache = false;
ib::warn() << "Total InnoDB FTS size "
<< cache->total_size << " for the table "
<< cache->sync->table->name
@@ -4226,52 +4105,23 @@ begin_sync:
error = fts_sync_index(sync, index_cache);
if (error != DB_SUCCESS) {
- goto end_sync;
- }
-
- if (!sync->unlock_cache
- && cache->total_size < fts_max_cache_size) {
- /* Reset the unlock cache if the value
- is less than innodb_ft_cache_size */
- sync->unlock_cache = true;
+ goto err_exit;
}
}
DBUG_EXECUTE_IF("fts_instrument_sync_interrupted",
- sync->interrupted = true;
error = DB_INTERRUPTED;
- goto end_sync;
+ goto err_exit;
);
- /* Make sure all the caches are synced. */
- for (i = 0; i < ib_vector_size(cache->indexes); ++i) {
- fts_index_cache_t* index_cache;
-
- index_cache = static_cast<fts_index_cache_t*>(
- ib_vector_get(cache->indexes, i));
-
- if (index_cache->index->to_be_dropped
- || fts_sync_index_check(index_cache)) {
- continue;
- }
-
- goto begin_sync;
- }
-
-end_sync:
- if (error == DB_SUCCESS && !sync->interrupted) {
+ if (error == DB_SUCCESS) {
error = fts_sync_commit(sync);
} else {
+err_exit:
fts_sync_rollback(sync);
+ return error;
}
- mysql_mutex_lock(&cache->lock);
- ut_ad(sync->in_progress);
- sync->interrupted = false;
- sync->in_progress = false;
- pthread_cond_broadcast(&sync->cond);
- mysql_mutex_unlock(&cache->lock);
-
/* We need to check whether an optimize is required, for that
we make copies of the two variables that control the trigger. These
variables can change behind our back and we don't want to hold the
@@ -4283,6 +4133,7 @@ end_sync:
mysql_mutex_unlock(&cache->deleted_lock);
+ DEBUG_SYNC_C("fts_sync_end");
return(error);
}
@@ -4291,12 +4142,12 @@ FTS auxiliary INDEX table and clear the cache at the end.
@param[in,out] table fts table
@param[in] wait whether wait for existing sync to finish
@return DB_SUCCESS on success, error code on failure. */
-dberr_t fts_sync_table(dict_table_t* table, bool wait)
+dberr_t fts_sync_table(dict_table_t* table)
{
ut_ad(table->fts);
return table->space && !table->corrupted && table->fts->cache
- ? fts_sync(table->fts->cache->sync, !wait, wait)
+ ? fts_sync(table->fts->cache->sync)
: DB_SUCCESS;
}