summaryrefslogtreecommitdiff
path: root/innobase/dict/dict0dict.c
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/dict/dict0dict.c')
-rw-r--r--innobase/dict/dict0dict.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index b8d9f362b06..b0d95597153 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -1556,6 +1556,8 @@ dict_index_remove_from_cache(
dict_field_t* field;
ulint size;
ulint i;
+ ulint retries = 0;
+ btr_search_t* info;
ut_ad(table && index);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
@@ -1564,6 +1566,51 @@ dict_index_remove_from_cache(
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
+ /* We always create search info whether or not adaptive
+ hash index is enabled or not. */
+ info = index->search_info;
+ ut_ad(info);
+
+ /* We are not allowed to free the in-memory index struct
+ dict_index_t until all entries in the adaptive hash index
+ that point to any of the page belonging to his b-tree index
+ are dropped. This is so because dropping of these entries
+ require access to dict_index_t struct. To avoid such scenario
+ We keep a count of number of such pages in the search_info and
+ only free the dict_index_t struct when this count drops to
+ zero. */
+
+ for (;;) {
+ ulint ref_count = btr_search_info_get_ref_count(info);
+ if (ref_count == 0) {
+ break;
+ }
+
+ /* Sleep for 10ms before trying again. */
+ os_thread_sleep(10000);
+ ++retries;
+
+ if (retries % 500 == 0) {
+ /* No luck after 5 seconds of wait. */
+ fprintf(stderr, "InnoDB: Error: Waited for"
+ " %lu secs for hash index"
+ " ref_count (%lu) to drop"
+ " to 0.\n"
+ "index: \"%s\""
+ " table: \"%s\"\n",
+ retries/100,
+ ref_count,
+ index->name,
+ table->name);
+ }
+
+ /* To avoid a hang here we commit suicide if the
+ ref_count doesn't drop to zero in 600 seconds. */
+ if (retries >= 60000) {
+ ut_error;
+ }
+ }
+
ut_ad(UT_LIST_GET_LEN((index->tree)->tree_indexes) == 1);
dict_tree_free(index->tree);