From 90849456d794aa6df32554a588da5db8cb15f5aa Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 16 Jun 2015 11:04:40 +0200 Subject: 5.6.24-72.2 --- storage/xtradb/api/api0api.cc | 208 +------------------------------- storage/xtradb/dict/dict0boot.cc | 12 +- storage/xtradb/dict/dict0dict.cc | 94 ++++++++++++--- storage/xtradb/dict/dict0load.cc | 3 +- storage/xtradb/dict/dict0mem.cc | 31 ++--- storage/xtradb/fsp/fsp0fsp.cc | 40 +----- storage/xtradb/fts/fts0fts.cc | 111 ++++------------- storage/xtradb/fts/fts0opt.cc | 9 +- storage/xtradb/fts/fts0que.cc | 5 +- storage/xtradb/handler/ha_innodb.cc | 21 +--- storage/xtradb/handler/handler0alter.cc | 2 +- storage/xtradb/handler/i_s.cc | 11 +- storage/xtradb/ibuf/ibuf0ibuf.cc | 5 +- storage/xtradb/include/dict0mem.h | 136 ++++++++++++++++++--- storage/xtradb/include/univ.i | 2 +- storage/xtradb/lock/lock0lock.cc | 4 +- storage/xtradb/log/log0recv.cc | 4 +- storage/xtradb/mtr/mtr0log.cc | 2 +- storage/xtradb/os/os0sync.cc | 20 +-- storage/xtradb/page/page0zip.cc | 6 +- storage/xtradb/pars/pars0pars.cc | 2 +- storage/xtradb/que/que0que.cc | 28 +---- storage/xtradb/row/row0log.cc | 23 +++- storage/xtradb/row/row0merge.cc | 149 ++++++++++++++++++++--- storage/xtradb/row/row0mysql.cc | 71 ++++++----- storage/xtradb/sync/sync0sync.cc | 6 +- 26 files changed, 463 insertions(+), 542 deletions(-) (limited to 'storage') diff --git a/storage/xtradb/api/api0api.cc b/storage/xtradb/api/api0api.cc index 2f5999e9a3a..d5dd9ca0081 100644 --- a/storage/xtradb/api/api0api.cc +++ b/storage/xtradb/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( - 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_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. */ @@ -946,34 +803,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_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 */ @@ -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(col_no), - value, static_cast(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/xtradb/dict/dict0boot.cc b/storage/xtradb/dict/dict0boot.cc index b57a8873bd5..94a3af2852b 100644 --- a/storage/xtradb/dict/dict0boot.cc +++ b/storage/xtradb/dict/dict0boot.cc @@ -302,8 +302,7 @@ dict_boot(void) /* Insert into the dictionary cache the descriptions of the basic system tables */ /*-------------------------*/ - table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, 0, 0, - false); + table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, 0, 0); dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0); dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0); @@ -357,8 +356,7 @@ dict_boot(void) ut_a(error == DB_SUCCESS); /*-------------------------*/ - table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, 0, 0, - false); + table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, 0, 0); dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0); dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4); @@ -391,8 +389,7 @@ dict_boot(void) ut_a(error == DB_SUCCESS); /*-------------------------*/ - table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, 0, 0, - false); + table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, 0, 0); dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0); dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0); @@ -425,8 +422,7 @@ dict_boot(void) ut_a(error == DB_SUCCESS); /*-------------------------*/ - table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, 0, 0, - false); + table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, 0, 0); dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0); dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4); diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc index 99e49fda615..fbf9bd22e20 100644 --- a/storage/xtradb/dict/dict0dict.cc +++ b/storage/xtradb/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(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(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)) { @@ -5821,8 +5876,7 @@ dict_ind_init(void) dict_table_t* table; /* create dummy table and index for REDUNDANT infimum and supremum */ - table = dict_mem_table_create("SYS_DUMMY1", DICT_HDR_SPACE, 1, 0, 0, - true); + table = dict_mem_table_create("SYS_DUMMY1", DICT_HDR_SPACE, 1, 0, 0); dict_mem_table_add_col(table, NULL, NULL, DATA_CHAR, DATA_ENGLISH | DATA_NOT_NULL, 8); @@ -5835,7 +5889,7 @@ dict_ind_init(void) /* create dummy table and index for COMPACT infimum and supremum */ table = dict_mem_table_create("SYS_DUMMY2", DICT_HDR_SPACE, 1, - DICT_TF_COMPACT, 0, true); + DICT_TF_COMPACT, 0); dict_mem_table_add_col(table, NULL, NULL, DATA_CHAR, DATA_ENGLISH | DATA_NOT_NULL, 8); dict_ind_compact = dict_mem_index_create("SYS_DUMMY2", "SYS_DUMMY2", @@ -6651,10 +6705,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); } /*********************************************************************//** @@ -6674,10 +6728,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); } @@ -6709,9 +6763,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/xtradb/dict/dict0load.cc b/storage/xtradb/dict/dict0load.cc index 874614bfb5c..ef8a2896b28 100644 --- a/storage/xtradb/dict/dict0load.cc +++ b/storage/xtradb/dict/dict0load.cc @@ -2176,8 +2176,7 @@ err_len: /* See if the tablespace is available. */ *table = dict_mem_table_create( - name, space, n_cols & ~DICT_N_COLS_COMPACT, flags, flags2, - false); + name, space, n_cols & ~DICT_N_COLS_COMPACT, flags, flags2); field = rec_get_nth_field_old(rec, DICT_FLD__SYS_TABLES__ID, &len); ut_ad(len == 8); /* this was checked earlier */ diff --git a/storage/xtradb/dict/dict0mem.cc b/storage/xtradb/dict/dict0mem.cc index 05d11ebb72b..58876d15f1d 100644 --- a/storage/xtradb/dict/dict0mem.cc +++ b/storage/xtradb/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 @@ -71,10 +71,7 @@ dict_mem_table_create( the table is placed */ ulint n_cols, /*!< in: number of columns */ ulint flags, /*!< in: table flags */ - ulint flags2, /*!< in: table flags2 */ - bool nonshared)/*!< in: whether the table object is a dummy - one that does not need the initialization of - locking-related fields. */ + ulint flags2) /*!< in: table flags2 */ { dict_table_t* table; mem_heap_t* heap; @@ -109,18 +106,10 @@ dict_mem_table_create( dict_table_stats_latch_create(table, true); #ifndef UNIV_HOTBACKUP + table->autoinc_lock = static_cast( + mem_heap_alloc(heap, lock_get_size())); - if (!nonshared) { - - table->autoinc_lock = static_cast( - mem_heap_alloc(heap, lock_get_size())); - - mutex_create(autoinc_mutex_key, - &table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX); - } else { - - table->autoinc_lock = NULL; - } + dict_table_autoinc_create_lazy(table); table->autoinc = 0; @@ -173,10 +162,7 @@ dict_mem_table_free( } } #ifndef UNIV_HOTBACKUP - if (table->autoinc_lock) { - - mutex_free(&(table->autoinc_mutex)); - } + dict_table_autoinc_destroy(table); #endif /* UNIV_HOTBACKUP */ dict_table_stats_latch_destroy(table); @@ -541,8 +527,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); } @@ -675,7 +660,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/xtradb/fsp/fsp0fsp.cc b/storage/xtradb/fsp/fsp0fsp.cc index 1993cdf2b7c..b96f2c1bb7a 100644 --- a/storage/xtradb/fsp/fsp0fsp.cc +++ b/storage/xtradb/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 @@ -303,44 +303,6 @@ xdes_find_bit( return(ULINT_UNDEFINED); } -/**********************************************************************//** -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 */ diff --git a/storage/xtradb/fts/fts0fts.cc b/storage/xtradb/fts/fts0fts.cc index c2d3f154075..5d6d5ae7cf9 100644 --- a/storage/xtradb/fts/fts0fts.cc +++ b/storage/xtradb/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 */ @@ -1971,7 +1952,7 @@ fts_create_one_index_table( flags2 = DICT_TF2_USE_TABLESPACE; } - new_table = dict_mem_table_create(table_name, 0, 5, 1, flags2, false); + new_table = dict_mem_table_create(table_name, 0, 5, 1, flags2); field = dict_index_get_nth_field(index, 0); charset = innobase_get_fts_charset( @@ -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( 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( + 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( - ib_vector_last(trx->fts_trx->savepoints)); - top_savepoint = static_cast( - 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( - 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/xtradb/fts/fts0opt.cc b/storage/xtradb/fts/fts0opt.cc index 5891b53a6e2..e096b8bf6d6 100644 --- a/storage/xtradb/fts/fts0opt.cc +++ b/storage/xtradb/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(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( ib_vector_push(nodes, NULL)); diff --git a/storage/xtradb/fts/fts0que.cc b/storage/xtradb/fts/fts0que.cc index 4629e3b7e91..fcae6561764 100644 --- a/storage/xtradb/fts/fts0que.cc +++ b/storage/xtradb/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 word_vector_t; diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 9591c58fbe4..84f33db6832 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/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. @@ -3068,19 +3068,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. */ @@ -9284,18 +9271,18 @@ create_table_def( /* Adjust for the FTS hidden field */ if (!has_doc_id_col) { table = dict_mem_table_create(table_name, 0, n_cols + 1, - flags, flags2, false); + flags, flags2); /* Set the hidden doc_id column. */ table->fts->doc_col = n_cols; } else { table = dict_mem_table_create(table_name, 0, n_cols, - flags, flags2, false); + flags, flags2); table->fts->doc_col = doc_id_col; } } else { table = dict_mem_table_create(table_name, 0, n_cols, - flags, flags2, false); + flags, flags2); } if (flags2 & DICT_TF2_TEMPORARY) { diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index c9847d2c24e..ad81b0ce938 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -2740,7 +2740,7 @@ prepare_inplace_alter_table_dict( /* The initial space id 0 may be overridden later. */ ctx->new_table = dict_mem_table_create( - new_table_name, 0, n_cols, flags, flags2, false); + new_table_name, 0, n_cols, flags, flags2); /* The rebuilt indexed_table will use the renamed column names. */ ctx->col_names = NULL; diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc index 2f9d123f1d6..4bc834479fe 100644 --- a/storage/xtradb/handler/i_s.cc +++ b/storage/xtradb/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 @@ -3324,8 +3324,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); @@ -3351,6 +3349,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 (ib_vector_get( word->nodes, i)); @@ -4031,11 +4030,15 @@ i_s_fts_config_fill( fts_internal_tbl_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE); 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/xtradb/ibuf/ibuf0ibuf.cc b/storage/xtradb/ibuf/ibuf0ibuf.cc index e4122287d2c..0695aa69652 100644 --- a/storage/xtradb/ibuf/ibuf0ibuf.cc +++ b/storage/xtradb/ibuf/ibuf0ibuf.cc @@ -611,8 +611,7 @@ ibuf_init_at_db_start(void) heap = mem_heap_create(450); /* Use old-style record format for the insert buffer. */ - table = dict_mem_table_create(IBUF_TABLE_NAME, IBUF_SPACE_ID, 1, 0, 0, - false); + table = dict_mem_table_create(IBUF_TABLE_NAME, IBUF_SPACE_ID, 1, 0, 0); dict_mem_table_add_col(table, heap, "DUMMY_COLUMN", DATA_BINARY, 0, 0); @@ -1573,7 +1572,7 @@ ibuf_dummy_index_create( table = dict_mem_table_create("IBUF_DUMMY", DICT_HDR_SPACE, n, - comp ? DICT_TF_COMPACT : 0, 0, true); + comp ? DICT_TF_COMPACT : 0, 0); index = dict_mem_index_create("IBUF_DUMMY", "IBUF_DUMMY", DICT_HDR_SPACE, 0, n); diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h index 500bd3dfc18..754c3810a84 100644 --- a/storage/xtradb/include/dict0mem.h +++ b/storage/xtradb/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 @@ -263,10 +263,7 @@ dict_mem_table_create( of the table is placed */ ulint n_cols, /*!< in: number of columns */ ulint flags, /*!< in: table flags */ - ulint flags2, /*!< in: table flags2 */ - bool nonshared);/*!< in: whether the table object is a dummy - one that does not need the initialization of - locking-related fields. */ + ulint flags2); /*!< in: table flags2 */ /****************************************************************//** Free a table memory object. */ UNIV_INTERN @@ -550,11 +547,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 */ @@ -562,6 +560,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 @@ -1033,8 +1034,7 @@ struct dict_table_t{ dict_table_t::indexes*::stat_index_size dict_table_t::indexes*::stat_n_leaf_pages (*) those are not always protected for - performance reasons. NULL for dumy table - objects. */ + performance reasons. */ unsigned stat_initialized:1; /*!< TRUE if statistics have been calculated the first time after database startup or table creation */ @@ -1156,12 +1156,15 @@ struct dict_table_t{ and release it without a need to allocate space from the lock heap of the trx: otherwise the lock heap would grow rapidly - if we do a large insert from a select. NULL - for dummy table objects. */ - ib_mutex_t autoinc_mutex; + if we do a large insert from a select */ + ib_mutex_t* autoinc_mutex; /*!< mutex protecting the autoincrement - counter. Not initialized for dummy table - objects */ + 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; @@ -1225,6 +1228,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/xtradb/include/univ.i b/storage/xtradb/include/univ.i index db187f15a5f..9ec58cf1e42 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -47,7 +47,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_BUGFIX MYSQL_VERSION_PATCH #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 72.1 +#define PERCONA_INNODB_VERSION 72.2 #endif /* Enable UNIV_LOG_ARCHIVE in XtraDB */ diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc index d3e6666cb2c..f03bd04b92e 100644 --- a/storage/xtradb/lock/lock0lock.cc +++ b/storage/xtradb/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/xtradb/log/log0recv.cc b/storage/xtradb/log/log0recv.cc index a77e7439b5d..38d9215ce39 100644 --- a/storage/xtradb/log/log0recv.cc +++ b/storage/xtradb/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 @@ -1926,7 +1926,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/xtradb/mtr/mtr0log.cc b/storage/xtradb/mtr/mtr0log.cc index 0660c819240..5335cb4c9ef 100644 --- a/storage/xtradb/mtr/mtr0log.cc +++ b/storage/xtradb/mtr/mtr0log.cc @@ -560,7 +560,7 @@ mlog_parse_index( n = n_uniq = 1; } table = dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n, - comp ? DICT_TF_COMPACT : 0, 0, true); + comp ? DICT_TF_COMPACT : 0, 0); ind = dict_mem_index_create("LOG_DUMMY", "LOG_DUMMY", DICT_HDR_SPACE, 0, n); ind->table = table; diff --git a/storage/xtradb/os/os0sync.cc b/storage/xtradb/os/os0sync.cc index e42c5900c0c..cd57abd0623 100644 --- a/storage/xtradb/os/os0sync.cc +++ b/storage/xtradb/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 @@ -233,24 +233,6 @@ os_cond_broadcast( #endif } -/*********************************************************//** -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 diff --git a/storage/xtradb/page/page0zip.cc b/storage/xtradb/page/page0zip.cc index 67dca183c6d..aa5c99339e2 100644 --- a/storage/xtradb/page/page0zip.cc +++ b/storage/xtradb/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 @@ -1576,7 +1576,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); @@ -1627,7 +1627,7 @@ page_zip_fields_decode( } table = dict_mem_table_create("ZIP_DUMMY", DICT_HDR_SPACE, n, - DICT_TF_COMPACT, 0, true); + DICT_TF_COMPACT, 0); index = dict_mem_index_create("ZIP_DUMMY", "ZIP_DUMMY", DICT_HDR_SPACE, 0, n); index->table = table; diff --git a/storage/xtradb/pars/pars0pars.cc b/storage/xtradb/pars/pars0pars.cc index f051481184b..655e5ba1324 100644 --- a/storage/xtradb/pars/pars0pars.cc +++ b/storage/xtradb/pars/pars0pars.cc @@ -1997,7 +1997,7 @@ pars_create_table( n_cols = que_node_list_get_len(column_defs); table = dict_mem_table_create( - table_sym->name, 0, n_cols, flags, flags2, false); + table_sym->name, 0, n_cols, flags, flags2); #ifdef UNIV_DEBUG if (not_fit_in_memory != NULL) { diff --git a/storage/xtradb/que/que0que.cc b/storage/xtradb/que/que0que.cc index 8d9b8fac776..e2dc0239e13 100644 --- a/storage/xtradb/que/que0que.cc +++ b/storage/xtradb/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 @@ -390,32 +390,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/xtradb/row/row0log.cc b/storage/xtradb/row/row0log.cc index 1240cf7fcc5..609c166c77b 100644 --- a/storage/xtradb/row/row0log.cc +++ b/storage/xtradb/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 @@ -1382,6 +1382,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/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc index 53a144c47a7..ab97a514282 100644 --- a/storage/xtradb/row/row0merge.cc +++ b/storage/xtradb/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( + 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; @@ -1587,16 +1686,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; } @@ -1697,12 +1804,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; } } @@ -1727,6 +1840,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/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc index 0168928c9f0..e167bb45d96 100644 --- a/storage/xtradb/row/row0mysql.cc +++ b/storage/xtradb/row/row0mysql.cc @@ -3427,13 +3427,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 @@ -4233,8 +4231,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) { @@ -4802,6 +4801,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); @@ -5088,34 +5088,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(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; } } @@ -5216,6 +5190,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(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/xtradb/sync/sync0sync.cc b/storage/xtradb/sync/sync0sync.cc index 35e96908f6a..d6a7f569b4a 100644 --- a/storage/xtradb/sync/sync0sync.cc +++ b/storage/xtradb/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 @@ -305,9 +305,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 */ ) { -- cgit v1.2.1