diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index a4e7c6f2ef2..77c1353843c 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2016, 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 @@ -3216,8 +3216,6 @@ fil_create_link_file( const char* tablename, /*!< in: tablename */ const char* filepath) /*!< in: pathname of tablespace */ { - os_file_t file; - ibool success; dberr_t err = DB_SUCCESS; char* link_filepath; char* prev_filepath = fil_read_link_file(tablename); @@ -3236,13 +3234,24 @@ fil_create_link_file( link_filepath = fil_make_isl_name(tablename); - file = os_file_create_simple_no_error_handling( - innodb_file_data_key, link_filepath, - OS_FILE_CREATE, OS_FILE_READ_WRITE, &success); + /** Check if the file already exists. */ + FILE* file = NULL; + ibool exists; + os_file_type_t ftype; - if (!success) { - /* The following call will print an error message */ - ulint error = os_file_get_last_error(true); + bool success = os_file_status(link_filepath, &exists, &ftype); + + ulint error = 0; + if (success && !exists) { + file = fopen(link_filepath, "w"); + if (file == NULL) { + /* This call will print its own error message */ + error = os_file_get_last_error(true); + } + } else { + error = OS_FILE_ALREADY_EXISTS; + } + if (error != 0) { ut_print_timestamp(stderr); fputs(" InnoDB: Cannot create file ", stderr); @@ -3267,13 +3276,17 @@ fil_create_link_file( return(err); } - if (!os_file_write(link_filepath, file, filepath, 0, - strlen(filepath))) { + ulint rbytes = fwrite(filepath, 1, strlen(filepath), file); + if (rbytes != strlen(filepath)) { + os_file_get_last_error(true); + ib_logf(IB_LOG_LEVEL_ERROR, + "cannot write link file " + "%s",filepath); err = DB_ERROR; } /* Close the file, we only need it at startup */ - os_file_close(file); + fclose(file); mem_free(link_filepath); diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 5d6d5ae7cf9..25047b38b9d 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2016, 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 @@ -260,16 +260,18 @@ static const char* fts_config_table_insert_values_sql = "INSERT INTO \"%s\" VALUES ('" FTS_TABLE_STATE "', '0');\n"; -/****************************************************************//** -Run SYNC on the table, i.e., write out data from the cache to the +/** 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. -@return DB_SUCCESS if all OK */ +@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) /*!< in: sync state */ - __attribute__((nonnull)); + fts_sync_t* sync, + bool unlock_cache, + bool wait); /****************************************************************//** Release all resources help by the words rb tree e.g., the node ilist. */ @@ -653,6 +655,7 @@ fts_cache_create( mem_heap_zalloc(heap, sizeof(fts_sync_t))); cache->sync->table = table; + cache->sync->event = os_event_create(); /* Create the index cache vector that will hold the inverted indexes. */ cache->indexes = ib_vector_create( @@ -1207,6 +1210,7 @@ fts_cache_destroy( mutex_free(&cache->optimize_lock); mutex_free(&cache->deleted_lock); mutex_free(&cache->doc_id_lock); + os_event_free(cache->sync->event); if (cache->stopword_info.cached_stopword) { rbt_free(cache->stopword_info.cached_stopword); @@ -1435,7 +1439,7 @@ fts_cache_add_doc( ib_vector_last(word->nodes)); } - if (fts_node == NULL + if (fts_node == NULL || fts_node->synced || fts_node->ilist_size > FTS_ILIST_MAX_SIZE || doc_id < fts_node->last_doc_id) { @@ -2886,35 +2890,28 @@ fts_doc_ids_free( } /*********************************************************************//** -Do commit-phase steps necessary for the insertion of a new row. -@return DB_SUCCESS or error code */ -static __attribute__((nonnull, warn_unused_result)) -dberr_t +Do commit-phase steps necessary for the insertion of a new row. */ +void fts_add( /*====*/ fts_trx_table_t*ftt, /*!< in: FTS trx table */ fts_trx_row_t* row) /*!< in: row */ { dict_table_t* table = ftt->table; - dberr_t error = DB_SUCCESS; doc_id_t doc_id = row->doc_id; ut_a(row->state == FTS_INSERT || row->state == FTS_MODIFY); fts_add_doc_by_id(ftt, doc_id, row->fts_indexes); - if (error == DB_SUCCESS) { - mutex_enter(&table->fts->cache->deleted_lock); - ++table->fts->cache->added; - mutex_exit(&table->fts->cache->deleted_lock); + mutex_enter(&table->fts->cache->deleted_lock); + ++table->fts->cache->added; + mutex_exit(&table->fts->cache->deleted_lock); - if (!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID) - && doc_id >= table->fts->cache->next_doc_id) { - table->fts->cache->next_doc_id = doc_id + 1; - } + if (!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID) + && doc_id >= table->fts->cache->next_doc_id) { + table->fts->cache->next_doc_id = doc_id + 1; } - - return(error); } /*********************************************************************//** @@ -3025,7 +3022,7 @@ fts_modify( error = fts_delete(ftt, row); if (error == DB_SUCCESS) { - error = fts_add(ftt, row); + fts_add(ftt, row); } return(error); @@ -3114,7 +3111,7 @@ fts_commit_table( switch (row->state) { case FTS_INSERT: - error = fts_add(ftt, row); + fts_add(ftt, row); break; case FTS_MODIFY: @@ -3553,16 +3550,34 @@ fts_add_doc_by_id( get_doc->index_cache, doc_id, doc.tokens); + bool need_sync = false; + if ((cache->total_size > fts_max_cache_size / 10 + || fts_need_sync) + && !cache->sync->in_progress) { + need_sync = true; + } + rw_lock_x_unlock(&table->fts->cache->lock); DBUG_EXECUTE_IF( "fts_instrument_sync", - fts_sync(cache->sync); + fts_optimize_request_sync_table(table); + os_event_wait(cache->sync->event); ); - if (cache->total_size > fts_max_cache_size - || fts_need_sync) { - fts_sync(cache->sync); + DBUG_EXECUTE_IF( + "fts_instrument_sync_debug", + fts_sync(cache->sync, true, true); + ); + + DEBUG_SYNC_C("fts_instrument_sync_request"); + DBUG_EXECUTE_IF( + "fts_instrument_sync_request", + fts_optimize_request_sync_table(table); + ); + + if (need_sync) { + fts_optimize_request_sync_table(table); } mtr_start(&mtr); @@ -3933,16 +3948,17 @@ fts_sync_add_deleted_cache( return(error); } -/*********************************************************************//** -Write the words and ilist to disk. +/** Write the words and ilist to disk. +@param[in,out] trx transaction +@param[in] index_cache index cache +@param[in] unlock_cache whether unlock cache when write node @return DB_SUCCESS if all went well else error code */ static __attribute__((nonnull, warn_unused_result)) dberr_t fts_sync_write_words( -/*=================*/ - trx_t* trx, /*!< in: transaction */ - fts_index_cache_t* - index_cache) /*!< in: index cache */ + trx_t* trx, + fts_index_cache_t* index_cache, + bool unlock_cache) { fts_table_t fts_table; ulint n_nodes = 0; @@ -3950,8 +3966,8 @@ fts_sync_write_words( const ib_rbt_node_t* rbt_node; dberr_t error = DB_SUCCESS; ibool print_error = FALSE; -#ifdef FTS_DOC_STATS_DEBUG dict_table_t* table = index_cache->index->table; +#ifdef FTS_DOC_STATS_DEBUG ulint n_new_words = 0; #endif /* FTS_DOC_STATS_DEBUG */ @@ -3964,7 +3980,7 @@ fts_sync_write_words( since we want to free the memory used during caching. */ for (rbt_node = rbt_first(index_cache->words); rbt_node; - rbt_node = rbt_first(index_cache->words)) { + rbt_node = rbt_next(index_cache->words, rbt_node)) { ulint i; ulint selected; @@ -3997,27 +4013,47 @@ fts_sync_write_words( } #endif /* FTS_DOC_STATS_DEBUG */ - n_nodes += ib_vector_size(word->nodes); - - /* We iterate over all the nodes even if there was an error, - this is to free the memory of the fts_node_t elements. */ + /* 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( 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) { + rw_lock_x_unlock( + &table->fts->cache->lock); + } error = fts_write_node( trx, &index_cache->ins_graph[selected], &fts_table, &word->text, fts_node); - } - ut_free(fts_node->ilist); - fts_node->ilist = NULL; + DEBUG_SYNC_C("fts_write_node"); + DBUG_EXECUTE_IF("fts_write_node_crash", + DBUG_SUICIDE();); + + DBUG_EXECUTE_IF("fts_instrument_sync_sleep", + os_thread_sleep(1000000); + ); + + if (unlock_cache) { + rw_lock_x_lock( + &table->fts->cache->lock); + } + } } + n_nodes += ib_vector_size(word->nodes); + if (error != DB_SUCCESS && !print_error) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Error (%s) writing " @@ -4026,9 +4062,6 @@ fts_sync_write_words( print_error = TRUE; } - - /* NOTE: We are responsible for free'ing the node */ - ut_free(rbt_remove_node(index_cache->words, rbt_node)); } #ifdef FTS_DOC_STATS_DEBUG @@ -4329,7 +4362,7 @@ fts_sync_index( ut_ad(rbt_validate(index_cache->words)); - error = fts_sync_write_words(trx, index_cache); + error = fts_sync_write_words(sync->trx, index_cache, sync->unlock_cache); #ifdef FTS_DOC_STATS_DEBUG /* FTS_RESOLVE: the word counter info in auxiliary table "DOC_ID" @@ -4345,6 +4378,36 @@ fts_sync_index( return(error); } +/** Check if index cache has been synced completely +@param[in,out] sync sync state +@param[in,out] index_cache index cache +@return true if index is synced, otherwise false. */ +static +bool +fts_sync_index_check( + fts_sync_t* sync, + 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(ib_vector_last(word->nodes)); + + if (!fts_node->synced) { + return(false); + } + } + + return(true); +} + /*********************************************************************//** Commit the SYNC, change state of processed doc ids etc. @return DB_SUCCESS if all OK */ @@ -4421,21 +4484,53 @@ fts_sync_rollback( trx_t* trx = sync->trx; fts_cache_t* cache = sync->table->fts->cache; + for (ulint i = 0; i < ib_vector_size(cache->indexes); ++i) { + ulint j; + fts_index_cache_t* index_cache; + + index_cache = static_cast( + ib_vector_get(cache->indexes, i)); + + for (j = 0; fts_index_selector[j].value; ++j) { + + if (index_cache->ins_graph[j] != NULL) { + + fts_que_graph_free_check_lock( + NULL, index_cache, + index_cache->ins_graph[j]); + + index_cache->ins_graph[j] = NULL; + } + + if (index_cache->sel_graph[j] != NULL) { + + fts_que_graph_free_check_lock( + NULL, index_cache, + index_cache->sel_graph[j]); + + index_cache->sel_graph[j] = NULL; + } + } + } + rw_lock_x_unlock(&cache->lock); fts_sql_rollback(trx); trx_free_for_background(trx); } -/****************************************************************//** -Run SYNC on the table, i.e., write out data from the cache to the +/** 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) /*!< in: sync state */ + fts_sync_t* sync, + bool unlock_cache, + bool wait) { ulint i; dberr_t error = DB_SUCCESS; @@ -4443,8 +4538,35 @@ fts_sync( rw_lock_x_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. */ + while (sync->in_progress) { + rw_lock_x_unlock(&cache->lock); + + if (wait) { + os_event_wait(sync->event); + } else { + return(DB_SUCCESS); + } + + rw_lock_x_lock(&cache->lock); + } + + sync->unlock_cache = unlock_cache; + sync->in_progress = true; + + DEBUG_SYNC_C("fts_sync_begin"); fts_sync_begin(sync); +begin_sync: + if (cache->total_size > fts_max_cache_size) { + /* Avoid the case: sync never finish when + insert/update keeps comming. */ + ut_ad(sync->unlock_cache); + sync->unlock_cache = false; + } + for (i = 0; i < ib_vector_size(cache->indexes); ++i) { fts_index_cache_t* index_cache; @@ -4459,21 +4581,43 @@ fts_sync( if (error != DB_SUCCESS && !sync->interrupted) { - break; + goto end_sync; } } DBUG_EXECUTE_IF("fts_instrument_sync_interrupted", sync->interrupted = true; error = DB_INTERRUPTED; + goto end_sync; ); + /* 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( + ib_vector_get(cache->indexes, i)); + + if (index_cache->index->to_be_dropped + || fts_sync_index_check(sync, index_cache)) { + continue; + } + + goto begin_sync; + } + +end_sync: if (error == DB_SUCCESS && !sync->interrupted) { error = fts_sync_commit(sync); } else { fts_sync_rollback(sync); } + rw_lock_x_lock(&cache->lock); + sync->in_progress = false; + os_event_set(sync->event); + rw_lock_x_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 @@ -4488,21 +4632,25 @@ fts_sync( return(error); } -/****************************************************************//** -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. */ +/** 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] table fts table +@param[in] unlock_cache whether unlock cache when write node +@param[in] wait whether wait for existing sync to finish +@return DB_SUCCESS on success, error code on failure. */ UNIV_INTERN dberr_t fts_sync_table( -/*===========*/ - dict_table_t* table) /*!< in: table */ + dict_table_t* table, + bool unlock_cache, + bool wait) { dberr_t err = DB_SUCCESS; ut_ad(table->fts); if (!dict_table_is_discarded(table) && table->fts->cache) { - err = fts_sync(table->fts->cache->sync); + err = fts_sync(table->fts->cache->sync, unlock_cache, wait); } return(err); diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index 2a0aa4daf12..711c5f53d01 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2016, 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 @@ -87,6 +87,7 @@ enum fts_msg_type_t { FTS_MSG_DEL_TABLE, /*!< Remove a table from the optimize threads work queue */ + FTS_MSG_SYNC_TABLE /*!< Sync fts cache of a table */ }; /** Compressed list of words that have been read from FTS INDEX @@ -2652,6 +2653,39 @@ fts_optimize_remove_table( os_event_free(event); } +/** Send sync fts cache for the table. +@param[in] table table to sync */ +UNIV_INTERN +void +fts_optimize_request_sync_table( + dict_table_t* table) +{ + fts_msg_t* msg; + table_id_t* table_id; + + /* if the optimize system not yet initialized, return */ + if (!fts_optimize_wq) { + return; + } + + /* FTS optimizer thread is already exited */ + if (fts_opt_start_shutdown) { + ib_logf(IB_LOG_LEVEL_INFO, + "Try to sync table %s after FTS optimize" + " thread exiting.", table->name); + return; + } + + msg = fts_optimize_create_msg(FTS_MSG_SYNC_TABLE, NULL); + + table_id = static_cast( + mem_heap_alloc(msg->heap, sizeof(table_id_t))); + *table_id = table->id; + msg->ptr = table_id; + + ib_wqueue_add(fts_optimize_wq, msg, msg->heap); +} + /**********************************************************************//** Find the slot for a particular table. @return slot if found else NULL. */ @@ -2932,6 +2966,25 @@ fts_optimize_need_sync( } #endif +/** Sync fts cache of a table +@param[in] table_id table id */ +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) { + fts_sync_table(table, true, false); + } + + dict_table_close(table, FALSE, FALSE); + } +} + /**********************************************************************//** Optimize all FTS tables. @return Dummy return */ @@ -3053,6 +3106,11 @@ fts_optimize_thread( ((fts_msg_del_t*) msg->ptr)->event); break; + case FTS_MSG_SYNC_TABLE: + fts_optimize_sync_table( + *static_cast(msg->ptr)); + break; + default: ut_error; } @@ -3079,26 +3137,7 @@ fts_optimize_thread( ib_vector_get(tables, i)); if (slot->state != FTS_STATE_EMPTY) { - dict_table_t* table = NULL; - - /*slot->table may be freed, so we try to open - table by slot->table_id.*/ - table = dict_table_open_on_id( - slot->table_id, FALSE, - DICT_TABLE_OP_NORMAL); - - if (table) { - - if (dict_table_has_fts_index(table)) { - fts_sync_table(table); - } - - if (table->fts) { - fts_free(table); - } - - dict_table_close(table, FALSE, FALSE); - } + fts_optimize_sync_table(slot->table_id); } } } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 53a60bb341a..3a9c3a44e73 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. @@ -3344,6 +3344,16 @@ innobase_change_buffering_inited_ok: innobase_open_files = table_cache_size; } } + + if (innobase_open_files > (long) open_files_limit) { + fprintf(stderr, + "innodb_open_files should not be greater" + " than the open_files_limit.\n"); + if (innobase_open_files > (long) table_cache_size) { + innobase_open_files = table_cache_size; + } + } + srv_max_n_open_files = (ulint) innobase_open_files; srv_innodb_status = (ibool) innobase_create_status_file; @@ -11363,7 +11373,7 @@ ha_innobase::optimize( if (innodb_optimize_fulltext_only) { if (prebuilt->table->fts && prebuilt->table->fts->cache && !dict_table_is_discarded(prebuilt->table)) { - fts_sync_table(prebuilt->table); + fts_sync_table(prebuilt->table, false, true); fts_optimize_table(prebuilt->table); } return(HA_ADMIN_OK); diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h index d54ed281d9a..9f7b0216d9b 100644 --- a/storage/innobase/include/fts0fts.h +++ b/storage/innobase/include/fts0fts.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2016, 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 @@ -724,6 +724,13 @@ fts_optimize_remove_table( /*======================*/ dict_table_t* table); /*!< in: table to remove */ +/** Send sync fts cache for the table. +@param[in] table table to sync */ +UNIV_INTERN +void +fts_optimize_request_sync_table( + dict_table_t* table); + /**********************************************************************//** Signal the optimize thread to prepare for shutdown. */ UNIV_INTERN @@ -826,15 +833,18 @@ fts_drop_index_split_tables( dict_index_t* index) /*!< in: fts instance */ __attribute__((nonnull, warn_unused_result)); -/****************************************************************//** -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. */ +/** 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] table fts table +@param[in] unlock_cache whether unlock cache when write node +@param[in] wait whether wait for existing sync to finish +@return DB_SUCCESS on success, error code on failure. */ UNIV_INTERN dberr_t fts_sync_table( -/*===========*/ - dict_table_t* table) /*!< in: table */ - __attribute__((nonnull)); + dict_table_t* table, + bool unlock_cache, + bool wait); /****************************************************************//** Free the query graph but check whether dict_sys->mutex is already diff --git a/storage/innobase/include/fts0types.h b/storage/innobase/include/fts0types.h index 64677428331..e495fe72a60 100644 --- a/storage/innobase/include/fts0types.h +++ b/storage/innobase/include/fts0types.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2016, 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 @@ -122,7 +122,11 @@ struct fts_sync_t { doc_id_t max_doc_id; /*!< The doc id at which the cache was noted as being full, we use this to set the upper_limit field */ - ib_time_t start_time; /*!< SYNC start time */ + ib_time_t start_time; /*!< SYNC start time */ + bool in_progress; /*!< flag whether sync is in progress.*/ + bool unlock_cache; /*!< flag whether unlock cache when + write fts node */ + os_event_t event; /*!< sync finish event */ }; /** The cache for the FTS system. It is a memory-based inverted index @@ -165,7 +169,6 @@ struct fts_cache_t { objects, they are recreated after a SYNC is completed */ - ib_alloc_t* self_heap; /*!< This heap is the heap out of which an instance of the cache itself was created. Objects created using @@ -212,6 +215,7 @@ struct fts_node_t { ulint ilist_size_alloc; /*!< Allocated size of ilist in bytes */ + bool synced; /*!< flag whether the node is synced */ }; /** A tokenizer word. Contains information about one word. */ diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h index 9329a0effb4..367c2a31924 100644 --- a/storage/innobase/include/os0sync.h +++ b/storage/innobase/include/os0sync.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -449,28 +449,7 @@ amount to decrement. */ # define os_atomic_decrement_uint64(ptr, amount) \ os_atomic_decrement(ptr, amount) -# if defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET) - -/** Do an atomic test-and-set. -@param[in,out] ptr Memory location to set to non-zero -@return the previous value */ -inline -lock_word_t -os_atomic_test_and_set(volatile lock_word_t* ptr) -{ - return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE)); -} - -/** Do an atomic clear. -@param[in,out] ptr Memory location to set to zero */ -inline -void -os_atomic_clear(volatile lock_word_t* ptr) -{ - __atomic_clear(ptr, __ATOMIC_RELEASE); -} - -# elif defined(IB_STRONG_MEMORY_MODEL) +# if defined(IB_STRONG_MEMORY_MODEL) /** Do an atomic test and set. @param[in,out] ptr Memory location to set to non-zero @@ -499,6 +478,27 @@ os_atomic_clear(volatile lock_word_t* ptr) return(__sync_lock_test_and_set(ptr, 0)); } +# elif defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET) + +/** Do an atomic test-and-set. +@param[in,out] ptr Memory location to set to non-zero +@return the previous value */ +inline +lock_word_t +os_atomic_test_and_set(volatile lock_word_t* ptr) +{ + return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE)); +} + +/** Do an atomic clear. +@param[in,out] ptr Memory location to set to zero */ +inline +void +os_atomic_clear(volatile lock_word_t* ptr) +{ + __atomic_clear(ptr, __ATOMIC_RELEASE); +} + # else # error "Unsupported platform" diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index e9be0b1157c..20a73a9ba33 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2005, 2016, 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 @@ -1986,7 +1986,8 @@ wait_again: if (max_doc_id && err == DB_SUCCESS) { /* Sync fts cache for other fts indexes to keep all fts indexes consistent in sync_doc_id. */ - err = fts_sync_table(const_cast(new_table)); + err = fts_sync_table(const_cast(new_table), + false, true); if (err == DB_SUCCESS) { fts_update_next_doc_id(