diff options
author | Sergei Golubchik <serg@mariadb.org> | 2015-05-04 22:13:46 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2015-05-04 22:13:46 +0200 |
commit | 085297a1214814cd7eacbab2afb24c7a08bfc40e (patch) | |
tree | 37258971c18a8a50cded86bf84546b67f67fbaec /storage | |
parent | 6d06fbbd1dc25b3c12568f9038060dfdb69f9683 (diff) | |
download | mariadb-git-085297a1214814cd7eacbab2afb24c7a08bfc40e.tar.gz |
5.6.24
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/api/api0api.cc | 208 | ||||
-rw-r--r-- | storage/innobase/dict/dict0dict.cc | 89 | ||||
-rw-r--r-- | storage/innobase/dict/dict0mem.cc | 12 | ||||
-rw-r--r-- | storage/innobase/fsp/fsp0fsp.cc | 40 | ||||
-rw-r--r-- | storage/innobase/fts/fts0fts.cc | 109 | ||||
-rw-r--r-- | storage/innobase/fts/fts0opt.cc | 9 | ||||
-rw-r--r-- | storage/innobase/fts/fts0que.cc | 5 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 15 | ||||
-rw-r--r-- | storage/innobase/handler/i_s.cc | 11 | ||||
-rw-r--r-- | storage/innobase/include/dict0mem.h | 122 | ||||
-rw-r--r-- | storage/innobase/lock/lock0lock.cc | 4 | ||||
-rw-r--r-- | storage/innobase/log/log0recv.cc | 4 | ||||
-rw-r--r-- | storage/innobase/os/os0sync.cc | 20 | ||||
-rw-r--r-- | storage/innobase/page/page0zip.cc | 4 | ||||
-rw-r--r-- | storage/innobase/que/que0que.cc | 28 | ||||
-rw-r--r-- | storage/innobase/row/row0log.cc | 23 | ||||
-rw-r--r-- | storage/innobase/row/row0merge.cc | 149 | ||||
-rw-r--r-- | storage/innobase/row/row0mysql.cc | 71 | ||||
-rw-r--r-- | storage/innobase/sync/sync0sync.cc | 6 |
19 files changed, 438 insertions, 491 deletions
diff --git a/storage/innobase/api/api0api.cc b/storage/innobase/api/api0api.cc index 2f5999e9a3a..d5dd9ca0081 100644 --- a/storage/innobase/api/api0api.cc +++ b/storage/innobase/api/api0api.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2008, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2008, 2015, 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 @@ -318,35 +318,6 @@ ib_wake_master_thread(void) } } -/*********************************************************************//** -Calculate the max row size of the columns in a cluster index. -@return max row length */ -UNIV_INLINE -ulint -ib_get_max_row_len( -/*===============*/ - dict_index_t* cluster) /*!< in: cluster index */ -{ - ulint i; - ulint max_len = 0; - ulint n_fields = cluster->n_fields; - - /* Add the size of the ordering columns in the - clustered index. */ - for (i = 0; i < n_fields; ++i) { - const dict_col_t* col; - - col = dict_index_get_nth_col(cluster, i); - - /* Use the maximum output size of - mach_write_compressed(), although the encoded - length should always fit in 2 bytes. */ - max_len += dict_col_get_max_size(col); - } - - return(max_len); -} - /*****************************************************************//** Read the columns from a rec into a tuple. */ static @@ -710,120 +681,6 @@ ib_trx_rollback( return(err); } -/*****************************************************************//** -Find an index definition from the index vector using index name. -@return index def. if found else NULL */ -UNIV_INLINE -const ib_index_def_t* -ib_table_find_index( -/*================*/ - ib_vector_t* indexes, /*!< in: vector of indexes */ - const char* name) /*!< in: index name */ -{ - ulint i; - - for (i = 0; i < ib_vector_size(indexes); ++i) { - const ib_index_def_t* index_def; - - index_def = (ib_index_def_t*) ib_vector_get(indexes, i); - - if (innobase_strcasecmp(name, index_def->name) == 0) { - return(index_def); - } - } - - return(NULL); -} - -/*****************************************************************//** -Get the InnoDB internal precise type from the schema column definition. -@return precise type in api format */ -UNIV_INLINE -ulint -ib_col_get_prtype( -/*==============*/ - const ib_col_t* ib_col) /*!< in: column definition */ -{ - ulint prtype = 0; - - if (ib_col->ib_col_attr & IB_COL_UNSIGNED) { - prtype |= DATA_UNSIGNED; - - ut_a(ib_col->ib_col_type == IB_INT); - } - - if (ib_col->ib_col_attr & IB_COL_NOT_NULL) { - prtype |= DATA_NOT_NULL; - } - - return(prtype); -} - -/*****************************************************************//** -Get the InnoDB internal main type from the schema column definition. -@return column main type */ -UNIV_INLINE -ulint -ib_col_get_mtype( -/*==============*/ - const ib_col_t* ib_col) /*!< in: column definition */ -{ - /* Note: The api0api.h types should map directly to - the internal numeric codes. */ - return(ib_col->ib_col_type); -} - -/*****************************************************************//** -Find a column in the the column vector with the same name. -@return col. def. if found else NULL */ -UNIV_INLINE -const ib_col_t* -ib_table_find_col( -/*==============*/ - const ib_vector_t* cols, /*!< in: column list head */ - const char* name) /*!< in: column name to find */ -{ - ulint i; - - for (i = 0; i < ib_vector_size(cols); ++i) { - const ib_col_t* ib_col; - - ib_col = static_cast<const ib_col_t*>( - ib_vector_get((ib_vector_t*) cols, i)); - - if (innobase_strcasecmp(ib_col->name, name) == 0) { - return(ib_col); - } - } - - return(NULL); -} - -/*****************************************************************//** -Find a column in the the column list with the same name. -@return col. def. if found else NULL */ -UNIV_INLINE -const ib_key_col_t* -ib_index_find_col( -/*==============*/ - ib_vector_t* cols, /*!< in: column list head */ - const char* name) /*!< in: column name to find */ -{ - ulint i; - - for (i = 0; i < ib_vector_size(cols); ++i) { - const ib_key_col_t* ib_col; - - ib_col = static_cast<ib_key_col_t*>(ib_vector_get(cols, i)); - - if (innobase_strcasecmp(ib_col->name, name) == 0) { - return(ib_col); - } - } - - return(NULL); -} - #ifdef __WIN__ /*****************************************************************//** Convert a string to lower case. */ @@ -947,34 +804,6 @@ ib_table_name_check( /*****************************************************************//** -Get an index definition that is tagged as a clustered index. -@return cluster index schema */ -UNIV_INLINE -ib_index_def_t* -ib_find_clustered_index( -/*====================*/ - ib_vector_t* indexes) /*!< in: index defs. to search */ -{ - ulint i; - ulint n_indexes; - - n_indexes = ib_vector_size(indexes); - - for (i = 0; i < n_indexes; ++i) { - ib_index_def_t* ib_index_def; - - ib_index_def = static_cast<ib_index_def_t*>( - ib_vector_get(indexes, i)); - - if (ib_index_def->clustered) { - return(ib_index_def); - } - } - - return(NULL); -} - -/*****************************************************************//** Get a table id. The caller must have acquired the dictionary mutex. @return DB_SUCCESS if found */ static @@ -3552,41 +3381,6 @@ ib_cursor_set_cluster_access( prebuilt->need_to_access_clustered = TRUE; } -/*************************************************************//** -Convert and write an INT column value to an InnoDB tuple. -@return DB_SUCCESS or error */ -UNIV_INLINE -ib_err_t -ib_tuple_write_int( -/*===============*/ - ib_tpl_t ib_tpl, /*!< in/out: tuple to write to */ - ulint col_no, /*!< in: column number */ - const void* value, /*!< in: integer value */ - ulint value_len) /*!< in: sizeof value type */ -{ - const dfield_t* dfield; - ulint data_len; - ulint type_len; - ib_tuple_t* tuple = (ib_tuple_t*) ib_tpl; - - ut_a(col_no < ib_tuple_get_n_cols(ib_tpl)); - - dfield = ib_col_get_dfield(tuple, col_no); - - data_len = dfield_get_len(dfield); - type_len = dtype_get_len(dfield_get_type(dfield)); - - if (dtype_get_mtype(dfield_get_type(dfield)) != DATA_INT - || value_len != data_len) { - - return(DB_DATA_MISMATCH); - } - - return(ib_col_set_value( - ib_tpl, static_cast<ib_ulint_t>(col_no), - value, static_cast<ib_ulint_t>(type_len), true)); -} - /*****************************************************************//** Write an integer value to a column. Integers are stored in big-endian format and will need to be converted from the host format. diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 80453898a23..d8787e4c291 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. This program is free software; you can redistribute it and/or modify it under @@ -644,6 +644,33 @@ dict_table_get_col_name( } #ifndef UNIV_HOTBACKUP +/** 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 */ +void +dict_table_autoinc_alloc( + void* table_void) +{ + dict_table_t* table = static_cast<dict_table_t*>(table_void); + table->autoinc_mutex = new (std::nothrow) ib_mutex_t(); + ut_a(table->autoinc_mutex != NULL); + mutex_create(autoinc_mutex_key, + table->autoinc_mutex, SYNC_DICT_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 */ +void +dict_index_zip_pad_alloc( + void* index_void) +{ + dict_index_t* index = static_cast<dict_index_t*>(index_void); + index->zip_pad.mutex = new (std::nothrow) os_fast_mutex_t; + ut_a(index->zip_pad.mutex != NULL); + os_fast_mutex_init(zip_pad_mutex_key, index->zip_pad.mutex); +} + /********************************************************************//** Acquire the autoinc lock. */ UNIV_INTERN @@ -652,7 +679,32 @@ dict_table_autoinc_lock( /*====================*/ dict_table_t* table) /*!< in/out: table */ { - mutex_enter(&table->autoinc_mutex); +#ifdef HAVE_ATOMIC_BUILTINS + os_once::do_or_wait_for_done( + &table->autoinc_mutex_created, + dict_table_autoinc_alloc, table); +#else /* HAVE_ATOMIC_BUILTINS */ + ut_ad(table->autoinc_mutex_created == os_once::DONE); +#endif /* HAVE_ATOMIC_BUILTINS */ + + mutex_enter(table->autoinc_mutex); +} + +/** Acquire the zip_pad_mutex latch. +@param[in,out] index the index whose zip_pad_mutex to acquire.*/ +void +dict_index_zip_pad_lock( + dict_index_t* index) +{ +#ifdef HAVE_ATOMIC_BUILTINS + os_once::do_or_wait_for_done( + &index->zip_pad.mutex_created, + dict_index_zip_pad_alloc, index); +#else /* HAVE_ATOMIC_BUILTINS */ + ut_ad(index->zip_pad.mutex_created == os_once::DONE); +#endif /* HAVE_ATOMIC_BUILTINS */ + + os_fast_mutex_lock(index->zip_pad.mutex); } /********************************************************************//** @@ -664,7 +716,7 @@ dict_table_autoinc_initialize( dict_table_t* table, /*!< in/out: table */ ib_uint64_t value) /*!< in: next value to assign to a row */ { - ut_ad(mutex_own(&table->autoinc_mutex)); + ut_ad(dict_table_autoinc_own(table)); table->autoinc = value; } @@ -706,7 +758,7 @@ dict_table_autoinc_read( /*====================*/ const dict_table_t* table) /*!< in: table */ { - ut_ad(mutex_own(&table->autoinc_mutex)); + ut_ad(dict_table_autoinc_own(table)); return(table->autoinc); } @@ -722,7 +774,7 @@ dict_table_autoinc_update_if_greater( dict_table_t* table, /*!< in/out: table */ ib_uint64_t value) /*!< in: value which was assigned to a row */ { - ut_ad(mutex_own(&table->autoinc_mutex)); + ut_ad(dict_table_autoinc_own(table)); if (value > table->autoinc) { @@ -738,7 +790,7 @@ dict_table_autoinc_unlock( /*======================*/ dict_table_t* table) /*!< in/out: table */ { - mutex_exit(&table->autoinc_mutex); + mutex_exit(table->autoinc_mutex); } #endif /* !UNIV_HOTBACKUP */ @@ -1578,15 +1630,18 @@ dict_table_rename_in_cache( } else if (table->space != TRX_SYS_SPACE) { char* new_path = NULL; - if (table->dir_path_of_temp_table != NULL) { + if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: trying to rename a" " TEMPORARY TABLE ", stderr); ut_print_name(stderr, NULL, TRUE, old_name); - fputs(" (", stderr); - ut_print_filename(stderr, - table->dir_path_of_temp_table); - fputs(" )\n", stderr); + if (table->dir_path_of_temp_table != NULL) { + fputs(" (", stderr); + ut_print_filename( + stderr, table->dir_path_of_temp_table); + fputs(" )\n", stderr); + } + return(DB_ERROR); } else if (DICT_TF_HAS_DATA_DIR(table->flags)) { @@ -6608,10 +6663,10 @@ dict_index_zip_success( return; } - os_fast_mutex_lock(&index->zip_pad.mutex); + dict_index_zip_pad_lock(index); ++index->zip_pad.success; dict_index_zip_pad_update(&index->zip_pad, zip_threshold); - os_fast_mutex_unlock(&index->zip_pad.mutex); + dict_index_zip_pad_unlock(index); } /*********************************************************************//** @@ -6631,10 +6686,10 @@ dict_index_zip_failure( return; } - os_fast_mutex_lock(&index->zip_pad.mutex); + dict_index_zip_pad_lock(index); ++index->zip_pad.failure; dict_index_zip_pad_update(&index->zip_pad, zip_threshold); - os_fast_mutex_unlock(&index->zip_pad.mutex); + dict_index_zip_pad_unlock(index); } @@ -6666,9 +6721,9 @@ dict_index_zip_pad_optimal_page_size( #ifdef HAVE_ATOMIC_BUILTINS pad = os_atomic_increment_ulint(&index->zip_pad.pad, 0); #else /* HAVE_ATOMIC_BUILTINS */ - os_fast_mutex_lock(&index->zip_pad.mutex); + dict_index_zip_pad_lock(index); pad = index->zip_pad.pad; - os_fast_mutex_unlock(&index->zip_pad.mutex); + dict_index_zip_pad_unlock(index); #endif /* HAVE_ATOMIC_BUILTINS */ ut_ad(pad < UNIV_PAGE_SIZE); diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index 9ef878bd870..846ce302b08 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. This program is free software; you can redistribute it and/or modify it under @@ -109,8 +109,7 @@ dict_mem_table_create( table->autoinc_lock = static_cast<ib_lock_t*>( mem_heap_alloc(heap, lock_get_size())); - mutex_create(autoinc_mutex_key, - &table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX); + dict_table_autoinc_create_lazy(table); table->autoinc = 0; @@ -160,7 +159,7 @@ dict_mem_table_free( } } #ifndef UNIV_HOTBACKUP - mutex_free(&(table->autoinc_mutex)); + dict_table_autoinc_destroy(table); #endif /* UNIV_HOTBACKUP */ dict_table_stats_latch_destroy(table); @@ -525,8 +524,7 @@ dict_mem_index_create( dict_mem_fill_index_struct(index, heap, table_name, index_name, space, type, n_fields); - os_fast_mutex_init(zip_pad_mutex_key, &index->zip_pad.mutex); - + dict_index_zip_pad_mutex_create_lazy(index); return(index); } @@ -659,7 +657,7 @@ dict_mem_index_free( } #endif /* UNIV_BLOB_DEBUG */ - os_fast_mutex_free(&index->zip_pad.mutex); + dict_index_zip_pad_mutex_destroy(index); mem_heap_free(index->heap); } diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index d1bb22ed7a9..6ecf97aaeb6 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2015, 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 @@ -301,44 +301,6 @@ xdes_find_bit( } /**********************************************************************//** -Looks for a descriptor bit having the desired value. Scans the extent in -a direction opposite to xdes_find_bit. -@return bit index of the bit, ULINT_UNDEFINED if not found */ -UNIV_INLINE -ulint -xdes_find_bit_downward( -/*===================*/ - xdes_t* descr, /*!< in: descriptor */ - ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */ - ibool val, /*!< in: desired bit value */ - ulint hint, /*!< in: hint of which bit position would - be desirable */ - mtr_t* mtr) /*!< in/out: mini-transaction */ -{ - ulint i; - - ut_ad(descr && mtr); - ut_ad(val <= TRUE); - ut_ad(hint < FSP_EXTENT_SIZE); - ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX)); - for (i = hint + 1; i > 0; i--) { - if (val == xdes_mtr_get_bit(descr, bit, i - 1, mtr)) { - - return(i - 1); - } - } - - for (i = FSP_EXTENT_SIZE - 1; i > hint; i--) { - if (val == xdes_mtr_get_bit(descr, bit, i, mtr)) { - - return(i); - } - } - - return(ULINT_UNDEFINED); -} - -/**********************************************************************//** Returns the number of used pages in a descriptor. @return number of pages used */ UNIV_INLINE diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index ef940ca78aa..5d6d5ae7cf9 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2015, 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 @@ -81,11 +81,13 @@ ulint n_nodes = 0; /** Error condition reported by fts_utf8_decode() */ const ulint UTF8_ERROR = 0xFFFFFFFF; +#ifdef FTS_CACHE_SIZE_DEBUG /** The cache size permissible lower limit (1K) */ static const ulint FTS_CACHE_SIZE_LOWER_LIMIT_IN_MB = 1; /** The cache size permissible upper limit (1G) */ static const ulint FTS_CACHE_SIZE_UPPER_LIMIT_IN_MB = 1024; +#endif /* FTS_CACHE_SIZE_DEBUG */ /** Time to sleep after DEADLOCK error before retrying operation. */ static const ulint FTS_DEADLOCK_RETRY_WAIT = 100000; @@ -191,7 +193,7 @@ static const char* fts_create_common_tables_sql = { "" "CREATE TABLE \"%s_CONFIG\" (\n" " key CHAR(50),\n" - " value CHAR(50) NOT NULL\n" + " value CHAR(200) NOT NULL\n" ") COMPACT;\n" "CREATE UNIQUE CLUSTERED INDEX IND ON \"%s_CONFIG\"(key);\n" }; @@ -329,27 +331,6 @@ fts_update_sync_doc_id( doc_id_t doc_id, /*!< in: last document id */ trx_t* trx) /*!< in: update trx, or NULL */ __attribute__((nonnull(1))); -/******************************************************************** -Check if we should stop. */ -UNIV_INLINE -ibool -fts_is_stop_signalled( -/*==================*/ - fts_t* fts) /*!< in: fts instance */ -{ - ibool stop_signalled = FALSE; - - mutex_enter(&fts->bg_threads_mutex); - - if (fts->fts_status & BG_THREAD_STOP) { - - stop_signalled = TRUE; - } - - mutex_exit(&fts->bg_threads_mutex); - - return(stop_signalled); -} /****************************************************************//** This function loads the default InnoDB stopword list */ @@ -3408,7 +3389,7 @@ fts_fetch_doc_from_rec( doc->charset = get_doc->index_cache->charset; /* Null Field */ - if (doc->text.f_len == UNIV_SQL_NULL) { + if (doc->text.f_len == UNIV_SQL_NULL || doc->text.f_len == 0) { continue; } @@ -5544,7 +5525,7 @@ fts_savepoint_lookup( /*********************************************************************//** Release the savepoint data identified by name. All savepoints created -after the named savepoint are also released. +after the named savepoint are kept. @return DB_SUCCESS or error code */ UNIV_INTERN void @@ -5553,81 +5534,37 @@ fts_savepoint_release( trx_t* trx, /*!< in: transaction */ const char* name) /*!< in: savepoint name */ { - ulint i; - ib_vector_t* savepoints; - ulint top_of_stack = 0; - ut_a(name != NULL); - savepoints = trx->fts_trx->savepoints; + ib_vector_t* savepoints = trx->fts_trx->savepoints; ut_a(ib_vector_size(savepoints) > 0); - /* Skip the implied savepoint (first element). */ - for (i = 1; i < ib_vector_size(savepoints); ++i) { - fts_savepoint_t* savepoint; + ulint i = fts_savepoint_lookup(savepoints, name); + if (i != ULINT_UNDEFINED) { + ut_a(i >= 1); + fts_savepoint_t* savepoint; savepoint = static_cast<fts_savepoint_t*>( ib_vector_get(savepoints, i)); - /* Even though we release the resources that are part - of the savepoint, we don't (always) actually delete the - entry. We simply set the savepoint name to NULL. Therefore - we have to skip deleted/released entries. */ - if (savepoint->name != NULL - && strcmp(name, savepoint->name) == 0) { - break; + if (i == ib_vector_size(savepoints) - 1) { + /* If the savepoint is the last, we save its + tables to the previous savepoint. */ + fts_savepoint_t* prev_savepoint; + prev_savepoint = static_cast<fts_savepoint_t*>( + ib_vector_get(savepoints, i - 1)); - /* Track the previous savepoint instance that will - be at the top of the stack after the release. */ - } else if (savepoint->name != NULL) { - /* We need to delete all entries - greater than this element. */ - top_of_stack = i; + ib_rbt_t* tables = savepoint->tables; + savepoint->tables = prev_savepoint->tables; + prev_savepoint->tables = tables; } - } - - /* Only if we found and element to release. */ - if (i < ib_vector_size(savepoints)) { - fts_savepoint_t* last_savepoint; - fts_savepoint_t* top_savepoint; - ib_rbt_t* tables; - - ut_a(top_of_stack < ib_vector_size(savepoints)); - /* Exchange tables between last savepoint and top savepoint */ - last_savepoint = static_cast<fts_savepoint_t*>( - ib_vector_last(trx->fts_trx->savepoints)); - top_savepoint = static_cast<fts_savepoint_t*>( - ib_vector_get(savepoints, top_of_stack)); - tables = top_savepoint->tables; - top_savepoint->tables = last_savepoint->tables; - last_savepoint->tables = tables; - - /* Skip the implied savepoint. */ - for (i = ib_vector_size(savepoints) - 1; - i > top_of_stack; - --i) { - - fts_savepoint_t* savepoint; - - savepoint = static_cast<fts_savepoint_t*>( - ib_vector_get(savepoints, i)); - - /* Skip savepoints that were released earlier. */ - if (savepoint->name != NULL) { - savepoint->name = NULL; - fts_savepoint_free(savepoint); - } - - ib_vector_pop(savepoints); - } + fts_savepoint_free(savepoint); + ib_vector_remove(savepoints, *(void**)savepoint); /* Make sure we don't delete the implied savepoint. */ ut_a(ib_vector_size(savepoints) > 0); - - /* This must hold. */ - ut_a(ib_vector_size(savepoints) == (top_of_stack + 1)); } } @@ -6329,7 +6266,7 @@ fts_fake_hex_to_dec( { ib_id_t dec_id = 0; char tmp_id[FTS_AUX_MIN_TABLE_ID_LENGTH]; - int ret; + int ret __attribute__((unused)); ret = sprintf(tmp_id, UINT64PFx, id); ut_ad(ret == 16); diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index 5891b53a6e2..e096b8bf6d6 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2015, 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 @@ -42,9 +42,6 @@ Completed 2011/7/10 Sunny and Jimmy Yang /** The FTS optimize thread's work queue. */ static ib_wqueue_t* fts_optimize_wq; -/** The number of document ids to delete in one statement. */ -static const ulint FTS_MAX_DELETE_DOC_IDS = 1000; - /** Time to wait for a message. */ static const ulint FTS_QUEUE_WAIT_IN_USECS = 5000000; @@ -1154,6 +1151,7 @@ fts_optimize_encode_node( } /* Calculate the space required to store the ilist. */ + ut_ad(doc_id > node->last_doc_id); doc_id_delta = doc_id - node->last_doc_id; enc_len = fts_get_encoded_len(static_cast<ulint>(doc_id_delta)); @@ -1396,7 +1394,8 @@ fts_optimize_word( src_node = (fts_node_t*) ib_vector_get(word->nodes, i); - if (!dst_node) { + if (dst_node == NULL + || dst_node->last_doc_id > src_node->first_doc_id) { dst_node = static_cast<fts_node_t*>( ib_vector_push(nodes, NULL)); diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc index 4629e3b7e91..fcae6561764 100644 --- a/storage/innobase/fts/fts0que.cc +++ b/storage/innobase/fts/fts0que.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2015, 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 @@ -57,9 +57,6 @@ Completed 2011/7/10 Sunny and Jimmy Yang /*Initial byte length for 'words' in fts_ranking_t */ #define RANKING_WORDS_INIT_LEN 4 -/* Coeffecient to use for normalize relevance ranking. */ -static const double FTS_NORMALIZE_COEFF = 0.0115F; - // FIXME: Need to have a generic iterator that traverses the ilist. typedef std::vector<fts_string_t> word_vector_t; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b8f6351ae27..691d4373054 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. @@ -2696,19 +2696,6 @@ trx_is_strict( return(trx && trx->mysql_thd && THDVAR(trx->mysql_thd, strict_mode)); } -/**********************************************************************//** -Determines if the current MySQL thread is running in strict mode. -If thd==NULL, THDVAR returns the global value of innodb-strict-mode. -@return TRUE if strict */ -UNIV_INLINE -ibool -thd_is_strict( -/*==========*/ - THD* thd) /*!< in: MySQL thread descriptor */ -{ - return(THDVAR(thd, strict_mode)); -} - /**************************************************************//** Resets some fields of a prebuilt struct. The template is used in fast retrieval of just those column values MySQL needs in its processing. */ diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index cfe69274e8e..192003a19d2 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2015, 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 @@ -3312,8 +3312,6 @@ i_s_fts_index_cache_fill_one_index( for (rbt_node = rbt_first(index_cache->words); rbt_node; rbt_node = rbt_next(index_cache->words, rbt_node)) { - doc_id_t doc_id = 0; - fts_tokenizer_word_t* word; word = rbt_value(fts_tokenizer_word_t, rbt_node); @@ -3339,6 +3337,7 @@ i_s_fts_index_cache_fill_one_index( fts_node_t* node; byte* ptr; ulint decoded = 0; + doc_id_t doc_id = 0; node = static_cast<fts_node_t*> (ib_vector_get( word->nodes, i)); @@ -4020,10 +4019,14 @@ i_s_fts_config_fill( if (!user_table) { DBUG_RETURN(0); + } else if (!dict_table_has_fts_index(user_table)) { + dict_table_close(user_table, FALSE, FALSE); + + DBUG_RETURN(0); } trx = trx_allocate_for_background(); - trx->op_info = "Select for FTS DELETE TABLE"; + trx->op_info = "Select for FTS CONFIG TABLE"; FTS_INIT_FTS_TABLE(&fts_table, "CONFIG", FTS_COMMON_TABLE, user_table); diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 460a7e125ad..6f9dd75ee10 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. This program is free software; you can redistribute it and/or modify it under @@ -540,11 +540,12 @@ extern ulong zip_failure_threshold_pct; compression failures */ extern ulong zip_pad_max; -/** Data structure to hold information about about how much space in +/** Data structure to hold information about how much space in 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 { - os_fast_mutex_t mutex; /*!< mutex protecting the info */ + os_fast_mutex_t* + mutex; /*!< mutex protecting the info */ ulint pad; /*!< number of bytes used as pad */ ulint success;/*!< successful compression ops during current round */ @@ -552,6 +553,9 @@ 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 */ }; /** Data structure for an index. Most fields will be @@ -1142,9 +1146,14 @@ struct dict_table_t{ space from the lock heap of the trx: otherwise the lock heap would grow rapidly if we do a large insert from a select */ - ib_mutex_t autoinc_mutex; + ib_mutex_t* autoinc_mutex; /*!< mutex protecting the autoincrement counter */ + + /** Creation state of autoinc_mutex member */ + volatile os_once::state_t + autoinc_mutex_created; + ib_uint64_t autoinc;/*!< autoinc counter value to give to the next inserted row */ ulong n_waiting_or_granted_auto_inc_locks; @@ -1207,6 +1216,111 @@ 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); + delete table->autoinc_mutex; + } +} + +/** 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 */ +void +dict_table_autoinc_alloc( + void* table_void); + +/** 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 */ +void +dict_index_zip_pad_alloc( + void* index_void); + +/** 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) +{ +#ifdef HAVE_ATOMIC_BUILTINS + table->autoinc_mutex = NULL; + table->autoinc_mutex_created = os_once::NEVER_DONE; +#else /* HAVE_ATOMIC_BUILTINS */ + dict_table_autoinc_alloc(table); + table->autoinc_mutex_created = os_once::DONE; +#endif /* HAVE_ATOMIC_BUILTINS */ +} + +/** 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) +{ +#ifdef HAVE_ATOMIC_BUILTINS + index->zip_pad.mutex = NULL; + index->zip_pad.mutex_created = os_once::NEVER_DONE; +#else /* HAVE_ATOMIC_BUILTINS */ + dict_index_zip_pad_alloc(index); + index->zip_pad.mutex_created = os_once::DONE; +#endif /* HAVE_ATOMIC_BUILTINS */ +} + +/** 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) { + os_fast_mutex_free(index->zip_pad.mutex); + 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 +void +dict_index_zip_pad_unlock( + dict_index_t* index) +{ + os_fast_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 */ + #ifndef UNIV_NONINL #include "dict0mem.ic" #endif diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index bf7ca1607d1..9d047c4cc3b 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2015, 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 @@ -378,8 +378,10 @@ because there is no parallel deadlock check. This stack is protected by the lock_sys_t::mutex. */ static lock_stack_t* lock_stack; +#ifdef UNIV_DEBUG /** The count of the types of locks. */ static const ulint lock_types = UT_ARR_SIZE(lock_compatibility_matrix); +#endif /* UNIV_DEBUG */ #ifdef UNIV_PFS_MUTEX /* Key to register mutex with performance schema */ diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index aa6c81483d7..9affec63252 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. This program is free software; you can redistribute it and/or modify it under @@ -1862,7 +1862,7 @@ loop: goto loop; } - ut_ad(!allow_ibuf == mutex_own(&log_sys->mutex)); + ut_ad((!allow_ibuf) == mutex_own(&log_sys->mutex)); if (!allow_ibuf) { recv_no_ibuf_operations = TRUE; diff --git a/storage/innobase/os/os0sync.cc b/storage/innobase/os/os0sync.cc index e42c5900c0c..cd57abd0623 100644 --- a/storage/innobase/os/os0sync.cc +++ b/storage/innobase/os/os0sync.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2015, 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 @@ -234,24 +234,6 @@ os_cond_broadcast( } /*********************************************************//** -Wakes one thread waiting for condition variable */ -UNIV_INLINE -void -os_cond_signal( -/*==========*/ - os_cond_t* cond) /*!< in: condition variable. */ -{ - ut_a(cond); - -#ifdef __WIN__ - ut_a(wake_condition_variable != NULL); - wake_condition_variable(cond); -#else - ut_a(pthread_cond_signal(cond) == 0); -#endif -} - -/*********************************************************//** Destroys condition variable */ UNIV_INLINE void diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index 4fcf38e9a8c..dd1dc763b90 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. This program is free software; you can redistribute it and/or modify it under @@ -1572,7 +1572,7 @@ page_zip_fields_free( { if (index) { dict_table_t* table = index->table; - os_fast_mutex_free(&index->zip_pad.mutex); + dict_index_zip_pad_mutex_destroy(index); mem_heap_free(index->heap); dict_mem_table_free(table); diff --git a/storage/innobase/que/que0que.cc b/storage/innobase/que/que0que.cc index fb185959d56..957a90e71b3 100644 --- a/storage/innobase/que/que0que.cc +++ b/storage/innobase/que/que0que.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2015, 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 @@ -380,32 +380,6 @@ que_fork_start_command( return(thr); } -/****************************************************************//** -Tests if all the query threads in the same fork have a given state. -@return TRUE if all the query threads in the same fork were in the -given state */ -UNIV_INLINE -ibool -que_fork_all_thrs_in_state( -/*=======================*/ - que_fork_t* fork, /*!< in: query fork */ - ulint state) /*!< in: state */ -{ - que_thr_t* thr_node; - - for (thr_node = UT_LIST_GET_FIRST(fork->thrs); - thr_node != NULL; - thr_node = UT_LIST_GET_NEXT(thrs, thr_node)) { - - if (thr_node->state != state) { - - return(FALSE); - } - } - - return(TRUE); -} - /**********************************************************************//** Calls que_graph_free_recursive for statements in a statement list. */ static diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 48b5dd36cb9..f88baa42d58 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2015, 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 @@ -1381,6 +1381,27 @@ blob_done: dfield_set_data(dfield, data, len); } + if (len != UNIV_SQL_NULL && col->mtype == DATA_MYSQL + && col->len != len && !dict_table_is_comp(log->table)) { + + ut_ad(col->len >= len); + if (dict_table_is_comp(index->table)) { + byte* buf = (byte*) mem_heap_alloc(heap, + col->len); + memcpy(buf, dfield->data, len); + memset(buf + len, 0x20, col->len - len); + + dfield_set_data(dfield, buf, col->len); + } else { + /* field length mismatch should not happen + when rebuilding the redundant row format + table. */ + ut_ad(0); + *error = DB_CORRUPTION; + return(NULL); + } + } + /* See if any columns were changed to NULL or NOT NULL. */ const dict_col_t* new_col = dict_table_get_nth_col(log->table, col_no); diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index c4224424fdb..93d57fa8e57 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2005, 2015, 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 @@ -235,22 +235,86 @@ row_merge_buf_free( mem_heap_free(buf->heap); } -/******************************************************//** -Insert a data tuple into a sort buffer. -@return number of rows added, 0 if out of space */ +/** Convert the field data from compact to redundant format. +@param[in] row_field field to copy from +@param[out] field field to copy to +@param[in] len length of the field data +@param[in] zip_size compressed BLOB page size, + zero for uncompressed BLOBs +@param[in,out] heap memory heap where to allocate data when + converting to ROW_FORMAT=REDUNDANT, or NULL + when not to invoke + row_merge_buf_redundant_convert(). */ +static +void +row_merge_buf_redundant_convert( + const dfield_t* row_field, + dfield_t* field, + ulint len, + ulint zip_size, + mem_heap_t* heap) +{ + ut_ad(DATA_MBMINLEN(field->type.mbminmaxlen) == 1); + ut_ad(DATA_MBMAXLEN(field->type.mbminmaxlen) > 1); + + byte* buf = (byte*) mem_heap_alloc(heap, len); + ulint field_len = row_field->len; + ut_ad(field_len <= len); + + if (row_field->ext) { + const byte* field_data = static_cast<byte*>( + dfield_get_data(row_field)); + ulint ext_len; + + ut_a(field_len >= BTR_EXTERN_FIELD_REF_SIZE); + ut_a(memcmp(field_data + field_len - BTR_EXTERN_FIELD_REF_SIZE, + field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE)); + + byte* data = btr_copy_externally_stored_field( + &ext_len, field_data, zip_size, field_len, heap); + + ut_ad(ext_len < len); + + memcpy(buf, data, ext_len); + field_len = ext_len; + } else { + memcpy(buf, row_field->data, field_len); + } + + memset(buf + field_len, 0x20, len - field_len); + + dfield_set_data(field, buf, len); +} + +/** Insert a data tuple into a sort buffer. +@param[in,out] buf sort buffer +@param[in] fts_index fts index to be created +@param[in] old_table original table +@param[in,out] psort_info parallel sort info +@param[in] row table row +@param[in] ext cache of externally stored + column prefixes, or NULL +@param[in,out] doc_id Doc ID if we are creating + FTS index +@param[in,out] conv_heap memory heap where to allocate data when + converting to ROW_FORMAT=REDUNDANT, or NULL + when not to invoke + row_merge_buf_redundant_convert() +@param[in,out] exceed_page set if the record size exceeds the page size + when converting to ROW_FORMAT=REDUNDANT +@return number of rows added, 0 if out of space */ static ulint row_merge_buf_add( -/*==============*/ - row_merge_buf_t* buf, /*!< in/out: sort buffer */ - dict_index_t* fts_index,/*!< in: fts index to be created */ - const dict_table_t* old_table,/*!< in: original table */ - fts_psort_t* psort_info, /*!< in: parallel sort info */ - const dtuple_t* row, /*!< in: table row */ - const row_ext_t* ext, /*!< in: cache of externally stored - column prefixes, or NULL */ - doc_id_t* doc_id) /*!< in/out: Doc ID if we are - creating FTS index */ + row_merge_buf_t* buf, + dict_index_t* fts_index, + const dict_table_t* old_table, + fts_psort_t* psort_info, + const dtuple_t* row, + const row_ext_t* ext, + doc_id_t* doc_id, + mem_heap_t* conv_heap, + bool* exceed_page) { ulint i; const dict_index_t* index; @@ -400,6 +464,23 @@ row_merge_buf_add( n_row_added = 1; continue; } + + if (field->len != UNIV_SQL_NULL + && col->mtype == DATA_MYSQL + && col->len != field->len) { + + if (conv_heap != NULL) { + row_merge_buf_redundant_convert( + row_field, field, col->len, + dict_table_zip_size(old_table), + conv_heap); + } else { + /* Field length mismatch should not + happen when rebuilding redundant row + format table. */ + ut_ad(dict_table_is_comp(index->table)); + } + } } len = dfield_get_len(field); @@ -508,6 +589,14 @@ row_merge_buf_add( of extra_size. */ data_size += (extra_size + 1) + ((extra_size + 1) >= 0x80); + /* Record size can exceed page size while converting to + redundant row format. But there is assert + ut_ad(size < UNIV_PAGE_SIZE) in rec_offs_data_size(). + It may hit the assert before attempting to insert the row. */ + if (conv_heap != NULL && data_size > UNIV_PAGE_SIZE) { + *exceed_page = true; + } + ut_ad(data_size < srv_sort_buf_size); /* Reserve one byte for the end marker of row_merge_block_t. */ @@ -527,6 +616,10 @@ row_merge_buf_add( dfield_dup(field++, buf->heap); } while (--n_fields); + if (conv_heap != NULL) { + mem_heap_empty(conv_heap); + } + DBUG_RETURN(n_row_added); } @@ -1208,6 +1301,7 @@ row_merge_read_clustered_index( os_event_t fts_parallel_sort_event = NULL; ibool fts_pll_sort = FALSE; ib_int64_t sig_count = 0; + mem_heap_t* conv_heap = NULL; DBUG_ENTER("row_merge_read_clustered_index"); ut_ad((old_table == new_table) == !col_map); @@ -1303,6 +1397,11 @@ row_merge_read_clustered_index( row_heap = mem_heap_create(sizeof(mrec_buf_t)); + if (dict_table_is_comp(old_table) + && !dict_table_is_comp(new_table)) { + conv_heap = mem_heap_create(sizeof(mrec_buf_t)); + } + /* Scan the clustered index. */ for (;;) { const rec_t* rec; @@ -1581,16 +1680,24 @@ write_buffers: row_merge_buf_t* buf = merge_buf[i]; merge_file_t* file = &files[i]; ulint rows_added = 0; + bool exceed_page = false; if (UNIV_LIKELY (row && (rows_added = row_merge_buf_add( buf, fts_index, old_table, - psort_info, row, ext, &doc_id)))) { + psort_info, row, ext, &doc_id, + conv_heap, &exceed_page)))) { /* If we are creating FTS index, a single row can generate more records for tokenized word */ file->n_rec += rows_added; + + if (exceed_page) { + err = DB_TOO_BIG_RECORD; + break; + } + if (doc_id > max_doc_id) { max_doc_id = doc_id; } @@ -1691,12 +1798,18 @@ write_buffers: (!(rows_added = row_merge_buf_add( buf, fts_index, old_table, psort_info, row, ext, - &doc_id)))) { + &doc_id, conv_heap, + &exceed_page)))) { /* An empty buffer should have enough room for at least one record. */ ut_error; } + if (exceed_page) { + err = DB_TOO_BIG_RECORD; + break; + } + file->n_rec += rows_added; } } @@ -1721,6 +1834,10 @@ func_exit: } all_done: + if (conv_heap != NULL) { + mem_heap_free(conv_heap); + } + #ifdef FTS_INTERNAL_DIAG_PRINT DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Scan Table\n"); #endif diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index bf17673a036..c53fa530b42 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -3411,13 +3411,11 @@ row_truncate_table_for_mysql( goto funct_exit; } - if (table->space && !table->dir_path_of_temp_table) { + if (table->space && !DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)) { /* Discard and create the single-table tablespace. */ ulint space = table->space; ulint flags = fil_space_get_flags(space); - ut_a(!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)); - dict_get_and_save_data_dir_path(table, true); if (flags != ULINT_UNDEFINED @@ -4217,8 +4215,9 @@ row_drop_table_for_mysql( is_temp = DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY); /* If there is a temp path then the temp flag is set. - However, during recovery, we might have a temp flag but - not know the temp path */ + However, during recovery or reloading the table object + after eviction from data dictionary cache, we might + have a temp flag but not know the temp path */ ut_a(table->dir_path_of_temp_table == NULL || is_temp); if (dict_table_is_discarded(table) || table->ibd_file_missing) { @@ -4786,6 +4785,7 @@ row_rename_table_for_mysql( ibool old_is_tmp, new_is_tmp; pars_info_t* info = NULL; int retry; + bool aux_fts_rename = false; ut_a(old_name != NULL); ut_a(new_name != NULL); @@ -5072,34 +5072,8 @@ row_rename_table_for_mysql( if (dict_table_has_fts_index(table) && !dict_tables_have_same_db(old_name, new_name)) { err = fts_rename_aux_tables(table, new_name, trx); - - if (err != DB_SUCCESS && (table->space != 0)) { - char* orig_name = table->name; - trx_t* trx_bg = trx_allocate_for_background(); - - /* If the first fts_rename fails, the trx would - be rolled back and committed, we can't use it any more, - so we have to start a new background trx here. */ - ut_a(trx_state_eq(trx, TRX_STATE_NOT_STARTED)); - trx_bg->op_info = "Revert the failing rename " - "for fts aux tables"; - trx_bg->dict_operation_lock_mode = RW_X_LATCH; - trx_start_for_ddl(trx_bg, TRX_DICT_OP_TABLE); - - /* If rename fails and table has its own tablespace, - we need to call fts_rename_aux_tables again to - revert the ibd file rename, which is not under the - control of trx. Also notice the parent table name - in cache is not changed yet. If the reverting fails, - the ibd data may be left in the new database, which - can be fixed only manually. */ - table->name = const_cast<char*>(new_name); - fts_rename_aux_tables(table, old_name, trx_bg); - table->name = orig_name; - - trx_bg->dict_operation_lock_mode = 0; - trx_commit_for_mysql(trx_bg); - trx_free_for_background(trx_bg); + if (err != DB_TABLE_NOT_FOUND) { + aux_fts_rename = true; } } @@ -5200,6 +5174,37 @@ end: } funct_exit: + if (aux_fts_rename && err != DB_SUCCESS + && table != NULL && (table->space != 0)) { + + char* orig_name = table->name; + trx_t* trx_bg = trx_allocate_for_background(); + + /* If the first fts_rename fails, the trx would + be rolled back and committed, we can't use it any more, + so we have to start a new background trx here. */ + ut_a(trx_state_eq(trx_bg, TRX_STATE_NOT_STARTED)); + trx_bg->op_info = "Revert the failing rename " + "for fts aux tables"; + trx_bg->dict_operation_lock_mode = RW_X_LATCH; + trx_start_for_ddl(trx_bg, TRX_DICT_OP_TABLE); + + /* If rename fails and table has its own tablespace, + we need to call fts_rename_aux_tables again to + revert the ibd file rename, which is not under the + control of trx. Also notice the parent table name + in cache is not changed yet. If the reverting fails, + the ibd data may be left in the new database, which + can be fixed only manually. */ + table->name = const_cast<char*>(new_name); + fts_rename_aux_tables(table, old_name, trx_bg); + table->name = orig_name; + + trx_bg->dict_operation_lock_mode = 0; + trx_commit_for_mysql(trx_bg); + trx_free_for_background(trx_bg); + } + if (table != NULL) { dict_table_close(table, dict_locked, FALSE); } diff --git a/storage/innobase/sync/sync0sync.cc b/storage/innobase/sync/sync0sync.cc index 60b1798fb0d..3ca495aaa8c 100644 --- a/storage/innobase/sync/sync0sync.cc +++ b/storage/innobase/sync/sync0sync.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -298,9 +298,9 @@ mutex_create_func( /* NOTE! The very first mutexes are not put to the mutex list */ - if ((mutex == &mutex_list_mutex) + if (mutex == &mutex_list_mutex #ifdef UNIV_SYNC_DEBUG - || (mutex == &sync_thread_mutex) + || mutex == &sync_thread_mutex #endif /* UNIV_SYNC_DEBUG */ ) { |