diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-06-06 17:51:28 +0200 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-06-06 17:51:28 +0200 |
commit | 4749d40c635634e25e07d28ce1a04e9263bcc375 (patch) | |
tree | c5bb3287675cd8676d76c8ee42ef2d79cc599e25 /storage | |
parent | 1ff1cb10fc236010b5969058cab934c2b306c931 (diff) | |
parent | 33ef993773449cb3917665b188f6b6575d399bd0 (diff) | |
download | mariadb-git-4749d40c635634e25e07d28ce1a04e9263bcc375.tar.gz |
5.5 merge
Diffstat (limited to 'storage')
100 files changed, 1726 insertions, 1315 deletions
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index 872eecff9cd..996dee5dce8 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -587,7 +587,7 @@ static int parse_url_error(FEDERATED_SHARE *share, TABLE *table, int error_num) buf_len= min(table->s->connect_string.length, FEDERATED_QUERY_BUFFER_SIZE-1); strmake(buf, table->s->connect_string.str, buf_len); - my_error(error_num, MYF(0), buf); + my_error(error_num, MYF(0), buf, 14); DBUG_RETURN(error_num); } @@ -3225,7 +3225,7 @@ int ha_federated::stash_remote_error() if (!mysql) DBUG_RETURN(remote_error_number); remote_error_number= mysql_errno(mysql); - strmake(remote_error_buf, mysql_error(mysql), sizeof(remote_error_buf)-1); + strmake_buf(remote_error_buf, mysql_error(mysql)); if (remote_error_number == ER_DUP_ENTRY || remote_error_number == ER_DUP_KEY) DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY); diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index c3f5e6add73..a7f2d887952 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -527,7 +527,7 @@ static int parse_url_error(FEDERATEDX_SHARE *share, TABLE_SHARE *table_s, buf_len= min(table_s->connect_string.length, FEDERATEDX_QUERY_BUFFER_SIZE-1); strmake(buf, table_s->connect_string.str, buf_len); - my_error(error_num, MYF(0), buf); + my_error(error_num, MYF(0), buf, 14); DBUG_RETURN(error_num); } @@ -587,9 +587,8 @@ int get_connection(MEM_ROOT *mem_root, FEDERATEDX_SHARE *share) DBUG_RETURN(0); error: - sprintf(error_buffer, "server name: '%s' doesn't exist!", - share->connection_string); - my_error(error_num, MYF(0), error_buffer); + my_printf_error(error_num, "server name: '%s' doesn't exist!", + MYF(0), share->connection_string); DBUG_RETURN(error_num); } @@ -3423,7 +3422,7 @@ int ha_federatedx::stash_remote_error() if (!io) DBUG_RETURN(remote_error_number); remote_error_number= io->error_code(); - strmake(remote_error_buf, io->error_str(), sizeof(remote_error_buf)-1); + strmake_buf(remote_error_buf, io->error_str()); if (remote_error_number == ER_DUP_ENTRY || remote_error_number == ER_DUP_KEY) DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY); diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c index 955be01f032..b48fb705cd8 100644 --- a/storage/innobase/btr/btr0cur.c +++ b/storage/innobase/btr/btr0cur.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -1248,27 +1248,13 @@ btr_cur_optimistic_insert( Subtract one byte for the encoded heap_no in the modification log. */ ulint free_space_zip = page_zip_empty_size( - cursor->index->n_fields, zip_size) - 1; + cursor->index->n_fields, zip_size); ulint n_uniq = dict_index_get_n_unique_in_tree(index); ut_ad(dict_table_is_comp(index->table)); - /* There should be enough room for two node pointer - records on an empty non-leaf page. This prevents - infinite page splits. */ - - if (UNIV_LIKELY(entry->n_fields >= n_uniq) - && UNIV_UNLIKELY(REC_NODE_PTR_SIZE - + rec_get_converted_size_comp_prefix( - index, entry->fields, n_uniq, - NULL) - /* On a compressed page, there is - a two-byte entry in the dense - page directory for every record. - But there is no record header. */ - - (REC_N_NEW_EXTRA_BYTES - 2) - > free_space_zip / 2)) { - + if (free_space_zip == 0) { +too_big: if (big_rec_vec) { dtuple_convert_back_big_rec( index, entry, big_rec_vec); @@ -1276,6 +1262,27 @@ btr_cur_optimistic_insert( return(DB_TOO_BIG_RECORD); } + + /* Subtract one byte for the encoded heap_no in the + modification log. */ + free_space_zip--; + + /* There should be enough room for two node pointer + records on an empty non-leaf page. This prevents + infinite page splits. */ + + if (entry->n_fields >= n_uniq + && (REC_NODE_PTR_SIZE + + rec_get_converted_size_comp_prefix( + index, entry->fields, n_uniq, NULL) + /* On a compressed page, there is + a two-byte entry in the dense + page directory for every record. + But there is no record header. */ + - (REC_N_NEW_EXTRA_BYTES - 2) + > free_space_zip / 2)) { + goto too_big; + } } LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page), diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index 2406980196e..31be914afa0 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -2322,6 +2322,10 @@ loop2: retries = 0; } else if (retries < BUF_PAGE_READ_MAX_RETRIES) { ++retries; + DBUG_EXECUTE_IF( + "innodb_page_corruption_retries", + retries = BUF_PAGE_READ_MAX_RETRIES; + ); } else { fprintf(stderr, "InnoDB: Error: Unable" " to read tablespace %lu page no" @@ -2359,6 +2363,7 @@ got_block: /* The page is being read to buffer pool, but we cannot wait around for the read to complete. */ +null_exit: buf_pool_mutex_exit(buf_pool); return(NULL); @@ -2373,6 +2378,14 @@ got_block: case BUF_BLOCK_ZIP_PAGE: case BUF_BLOCK_ZIP_DIRTY: + if (mode == BUF_PEEK_IF_IN_POOL) { + /* This mode is only used for dropping an + adaptive hash index. There cannot be an + adaptive hash index for a compressed-only + page, so do not bother decompressing the page. */ + goto null_exit; + } + bpage = &block->page; /* Protect bpage->buf_fix_count. */ mutex_enter(&buf_pool->zip_mutex); diff --git a/storage/innobase/buf/buf0rea.c b/storage/innobase/buf/buf0rea.c index 40550186191..d12fd3fce31 100644 --- a/storage/innobase/buf/buf0rea.c +++ b/storage/innobase/buf/buf0rea.c @@ -177,7 +177,10 @@ buf_read_page_low( ut_ad(buf_page_in_file(bpage)); - thd_wait_begin(NULL, THD_WAIT_DISKIO); + if (sync) { + thd_wait_begin(NULL, THD_WAIT_DISKIO); + } + if (zip_size) { *err = fil_io(OS_FILE_READ | wake_later, sync, space, zip_size, offset, 0, zip_size, @@ -189,7 +192,10 @@ buf_read_page_low( sync, space, 0, offset, 0, UNIV_PAGE_SIZE, ((buf_block_t*) bpage)->frame, bpage); } - thd_wait_end(NULL); + + if (sync) { + thd_wait_end(NULL); + } if (*err == DB_TABLESPACE_DELETED) { buf_read_page_handle_error(bpage); diff --git a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c index d7373a4b8ef..cb3dbcbe4ac 100644 --- a/storage/innobase/dict/dict0crea.c +++ b/storage/innobase/dict/dict0crea.c @@ -42,6 +42,7 @@ Created 1/8/1996 Heikki Tuuri #include "trx0roll.h" #include "usr0sess.h" #include "ut0vec.h" +#include "ha_prototypes.h" /*****************************************************************//** Based on a table object, this function builds the entry to be inserted @@ -1427,12 +1428,20 @@ dict_create_add_foreign_to_dictionary( pars_info_t* info = pars_info_create(); if (foreign->id == NULL) { + char* stripped_name; /* Generate a new constraint id */ ulint namelen = strlen(table->name); char* id = mem_heap_alloc(foreign->heap, namelen + 20); /* no overflow if number < 1e13 */ sprintf(id, "%s_ibfk_%lu", table->name, (ulong) (*id_nr)++); foreign->id = id; + + stripped_name = strchr(foreign->id, '/') + 1; + if (innobase_check_identifier_length(stripped_name)) { + fprintf(stderr, "InnoDB: Generated foreign key " + "name (%s) is too long\n", foreign->id); + return(DB_IDENTIFIER_TOO_LONG); + } } pars_info_add_str_literal(info, "id", foreign->id); diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index d5b16d419f1..a887ff0b1ca 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2013, 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 @@ -1466,6 +1466,10 @@ dict_index_too_big_for_tree( /* maximum allowed size of a node pointer record */ ulint page_ptr_max; + DBUG_EXECUTE_IF( + "ib_force_create_table", + return(FALSE);); + comp = dict_table_is_comp(table); zip_size = dict_table_zip_size(table); @@ -1480,7 +1484,10 @@ dict_index_too_big_for_tree( number in the page modification log. The maximum allowed node pointer size is half that. */ page_rec_max = page_zip_empty_size(new_index->n_fields, - zip_size) - 1; + zip_size); + if (page_rec_max) { + page_rec_max--; + } page_ptr_max = page_rec_max / 2; /* On a compressed page, there is a two-byte entry in the dense page directory for every record. But there @@ -4672,6 +4679,7 @@ dict_print_info_on_foreign_key_in_create_format( dict_foreign_t* foreign, /*!< in: foreign key constraint */ ibool add_newline) /*!< in: whether to add a newline */ { + char constraint_name[MAX_TABLE_NAME_LEN]; const char* stripped_id; ulint i; @@ -4693,7 +4701,9 @@ dict_print_info_on_foreign_key_in_create_format( } fputs(" CONSTRAINT ", file); - ut_print_name(file, trx, FALSE, stripped_id); + innobase_convert_from_id(&my_charset_filename, constraint_name, + stripped_id, MAX_TABLE_NAME_LEN); + ut_print_name(file, trx, FALSE, constraint_name); fputs(" FOREIGN KEY (", file); for (i = 0;;) { diff --git a/storage/innobase/dyn/dyn0dyn.c b/storage/innobase/dyn/dyn0dyn.c index e1275f040f3..d0f50ad0c32 100644 --- a/storage/innobase/dyn/dyn0dyn.c +++ b/storage/innobase/dyn/dyn0dyn.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2013, 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 @@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -35,7 +35,7 @@ UNIV_INTERN dyn_block_t* dyn_array_add_block( /*================*/ - dyn_array_t* arr) /*!< in: dyn array */ + dyn_array_t* arr) /*!< in/out: dyn array */ { mem_heap_t* heap; dyn_block_t* block; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 4d8f1c7398e..4b77936550b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. @@ -1082,6 +1082,8 @@ convert_error_code_to_mysql( return(HA_ERR_UNDO_REC_TOO_BIG); case DB_OUT_OF_MEMORY: return(HA_ERR_OUT_OF_MEM); + case DB_IDENTIFIER_TOO_LONG: + return(HA_ERR_INTERNAL_ERROR); } } @@ -1162,6 +1164,37 @@ innobase_convert_from_table_id( strconvert(cs, from, &my_charset_filename, to, (uint) len, &errors); } +/********************************************************************** +Check if the length of the identifier exceeds the maximum allowed. +The input to this function is an identifier in charset my_charset_filename. +return true when length of identifier is too long. */ +extern "C" UNIV_INTERN +my_bool +innobase_check_identifier_length( +/*=============================*/ + const char* id) /* in: identifier to check. it must belong + to charset my_charset_filename */ +{ + char tmp[MAX_TABLE_NAME_LEN + 10]; + uint errors; + uint len; + int well_formed_error = 0; + CHARSET_INFO* cs1 = &my_charset_filename; + CHARSET_INFO* cs2 = thd_charset(current_thd); + + len = strconvert(cs1, id, cs2, tmp, MAX_TABLE_NAME_LEN + 10, &errors); + + uint res = cs2->cset->well_formed_len(cs2, tmp, tmp + len, + NAME_CHAR_LEN, + &well_formed_error); + + if (well_formed_error || res != len) { + my_error(ER_TOO_LONG_IDENT, MYF(0), tmp); + return(true); + } + return(false); +} + /******************************************************************//** Converts an identifier to UTF-8. */ extern "C" UNIV_INTERN @@ -5846,6 +5879,8 @@ ha_innobase::unlock_row(void) { DBUG_ENTER("ha_innobase::unlock_row"); + ut_ad(prebuilt->trx->conc_state == TRX_ACTIVE); + /* Consistent read does not take any locks, thus there is nothing to unlock. */ @@ -7815,12 +7850,18 @@ innobase_rename_table( DEBUG_SYNC_C("innodb_rename_table_ready"); /* Serialize data dictionary operations with dictionary mutex: - no deadlocks can occur then in these operations */ + no deadlocks can occur then in these operations. Start the + transaction first to avoid a possible deadlock in the server. */ + trx_start_if_not_started(trx); if (lock_and_commit) { row_mysql_lock_data_dictionary(trx); } + /* Flag this transaction as a dictionary operation, so that + the data dictionary will be locked in crash recovery. */ + trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); + error = row_rename_table_for_mysql( norm_from, norm_to, trx, lock_and_commit); @@ -11478,6 +11519,61 @@ innodb_change_buffering_update( *static_cast<const char*const*>(save); } +#ifndef DBUG_OFF +static char* srv_buffer_pool_evict; + +/****************************************************************//** +Called on SET GLOBAL innodb_buffer_pool_evict=... +Handles some values specially, to evict pages from the buffer pool. +SET GLOBAL innodb_buffer_pool_evict='uncompressed' +evicts all uncompressed page frames of compressed tablespaces. */ +static +void +innodb_buffer_pool_evict_update( +/*============================*/ + THD* thd, /*!< in: thread handle */ + struct st_mysql_sys_var*var, /*!< in: pointer to system variable */ + void* var_ptr,/*!< out: ignored */ + const void* save) /*!< in: immediate result + from check function */ +{ + if (const char* op = *static_cast<const char*const*>(save)) { + if (!strcmp(op, "uncompressed")) { + /* Evict all uncompressed pages of compressed + tables from the buffer pool. Keep the compressed + pages in the buffer pool. */ + + for (ulint i = 0; i < srv_buf_pool_instances; i++) { + buf_pool_t* buf_pool = &buf_pool_ptr[i]; + + buf_pool_mutex_enter(buf_pool); + + for (buf_block_t* block = UT_LIST_GET_LAST( + buf_pool->unzip_LRU); + block != NULL; ) { + + buf_block_t* prev_block + = UT_LIST_GET_PREV(unzip_LRU, + block); + ut_ad(buf_block_get_state(block) + == BUF_BLOCK_FILE_PAGE); + ut_ad(block->in_unzip_LRU_list); + ut_ad(block->page.in_LRU_list); + + mutex_enter(&block->mutex); + buf_LRU_free_block(&block->page, + FALSE); + mutex_exit(&block->mutex); + block = prev_block; + } + + buf_pool_mutex_exit(buf_pool); + } + } + } +} +#endif /* !DBUG_OFF */ + static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff) { innodb_export_status(); @@ -11740,6 +11836,13 @@ static MYSQL_SYSVAR_ULONG(autoextend_increment, srv_auto_extend_increment, "Data file autoextend increment in megabytes", NULL, NULL, 8L, 1L, 1000L, 0); +#ifndef DBUG_OFF +static MYSQL_SYSVAR_STR(buffer_pool_evict, srv_buffer_pool_evict, + PLUGIN_VAR_RQCMDARG, + "Evict pages from the InnoDB buffer pool.", + NULL, innodb_buffer_pool_evict_update, ""); +#endif /* !DBUG_OFF */ + static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", @@ -11927,6 +12030,9 @@ static MYSQL_SYSVAR_BOOL(print_all_deadlocks, srv_print_all_deadlocks, static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(additional_mem_pool_size), MYSQL_SYSVAR(autoextend_increment), +#ifndef DBUG_OFF + MYSQL_SYSVAR(buffer_pool_evict), +#endif /* !DBUG_OFF */ MYSQL_SYSVAR(buffer_pool_size), MYSQL_SYSVAR(buffer_pool_instances), MYSQL_SYSVAR(checksums), diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 59ea065c5c7..38596bc69b5 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -2295,6 +2295,7 @@ i_s_innodb_buffer_stats_fill_table( buf_pool_info_t* pool_info; DBUG_ENTER("i_s_innodb_buffer_fill_general"); + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); /* Only allow the PROCESS privilege holder to access the stats */ if (check_global_access(thd, PROCESS_ACL)) { @@ -2911,6 +2912,7 @@ i_s_innodb_fill_buffer_pool( mem_heap_t* heap; DBUG_ENTER("i_s_innodb_fill_buffer_pool"); + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); heap = mem_heap_create(10000); @@ -3480,6 +3482,7 @@ i_s_innodb_fill_buffer_lru( ulint lru_len; DBUG_ENTER("i_s_innodb_fill_buffer_lru"); + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); /* Obtain buf_pool mutex before allocate info_buffer, since UT_LIST_GET_LEN(buf_pool->LRU) could change */ diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c index 70af56b99f2..11505121fa2 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.c +++ b/storage/innobase/ibuf/ibuf0ibuf.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2013, 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 @@ -4685,6 +4685,16 @@ loop: == page_no); ut_ad(ibuf_rec_get_space(&mtr, rec) == space); + /* Mark the change buffer record processed, + so that it will not be merged again in case + the server crashes between the following + mtr_commit() and the subsequent mtr_commit() + of deleting the change buffer record. */ + + btr_cur_set_deleted_flag_for_ibuf( + btr_pcur_get_rec(&pcur), NULL, + TRUE, &mtr); + btr_pcur_store_position(&pcur, &mtr); ibuf_btr_pcur_commit_specify_mtr(&pcur, &mtr); diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h index 95ccef16be0..b27bc954940 100644 --- a/storage/innobase/include/db0err.h +++ b/storage/innobase/include/db0err.h @@ -114,6 +114,7 @@ enum db_err { DB_UNDO_RECORD_TOO_BIG, /* the undo log record is too big */ DB_TABLE_IN_FK_CHECK, /* table is being used in foreign key check */ + DB_IDENTIFIER_TOO_LONG, /* Identifier name too long */ /* The following are partial failure codes */ DB_FAIL = 1000, diff --git a/storage/innobase/include/dyn0dyn.h b/storage/innobase/include/dyn0dyn.h index 121a5946ac7..62ed862e82c 100644 --- a/storage/innobase/include/dyn0dyn.h +++ b/storage/innobase/include/dyn0dyn.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2013, 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 @@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -47,15 +47,17 @@ UNIV_INLINE dyn_array_t* dyn_array_create( /*=============*/ - dyn_array_t* arr); /*!< in: pointer to a memory buffer of + dyn_array_t* arr) /*!< in/out memory buffer of size sizeof(dyn_array_t) */ + __attribute__((nonnull)); /************************************************************//** Frees a dynamic array. */ UNIV_INLINE void dyn_array_free( /*===========*/ - dyn_array_t* arr); /*!< in: dyn array */ + dyn_array_t* arr) /*!< in,own: dyn array */ + __attribute__((nonnull)); /*********************************************************************//** Makes room on top of a dyn array and returns a pointer to a buffer in it. After copying the elements, the caller must close the buffer using @@ -66,8 +68,9 @@ byte* dyn_array_open( /*===========*/ dyn_array_t* arr, /*!< in: dynamic array */ - ulint size); /*!< in: size in bytes of the buffer; MUST be + ulint size) /*!< in: size in bytes of the buffer; MUST be smaller than DYN_ARRAY_DATA_SIZE! */ + __attribute__((nonnull, warn_unused_result)); /*********************************************************************//** Closes the buffer returned by dyn_array_open. */ UNIV_INLINE @@ -75,7 +78,8 @@ void dyn_array_close( /*============*/ dyn_array_t* arr, /*!< in: dynamic array */ - byte* ptr); /*!< in: buffer space from ptr up was not used */ + const byte* ptr) /*!< in: end of used space */ + __attribute__((nonnull)); /*********************************************************************//** Makes room on top of a dyn array and returns a pointer to the added element. The caller must copy the element to @@ -85,8 +89,9 @@ UNIV_INLINE void* dyn_array_push( /*===========*/ - dyn_array_t* arr, /*!< in: dynamic array */ - ulint size); /*!< in: size in bytes of the element */ + dyn_array_t* arr, /*!< in/out: dynamic array */ + ulint size) /*!< in: size in bytes of the element */ + __attribute__((nonnull, warn_unused_result)); /************************************************************//** Returns pointer to an element in dyn array. @return pointer to element */ @@ -94,9 +99,10 @@ UNIV_INLINE void* dyn_array_get_element( /*==================*/ - dyn_array_t* arr, /*!< in: dyn array */ - ulint pos); /*!< in: position of element as bytes - from array start */ + const dyn_array_t* arr, /*!< in: dyn array */ + ulint pos) /*!< in: position of element + in bytes from array start */ + __attribute__((nonnull, warn_unused_result)); /************************************************************//** Returns the size of stored data in a dyn array. @return data size in bytes */ @@ -104,30 +110,33 @@ UNIV_INLINE ulint dyn_array_get_data_size( /*====================*/ - dyn_array_t* arr); /*!< in: dyn array */ + const dyn_array_t* arr) /*!< in: dyn array */ + __attribute__((nonnull, warn_unused_result, pure)); /************************************************************//** -Gets the first block in a dyn array. */ -UNIV_INLINE -dyn_block_t* -dyn_array_get_first_block( -/*======================*/ - dyn_array_t* arr); /*!< in: dyn array */ +Gets the first block in a dyn array. +@param arr dyn array +@return first block */ +#define dyn_array_get_first_block(arr) (arr) /************************************************************//** -Gets the last block in a dyn array. */ -UNIV_INLINE -dyn_block_t* -dyn_array_get_last_block( -/*=====================*/ - dyn_array_t* arr); /*!< in: dyn array */ +Gets the last block in a dyn array. +@param arr dyn array +@return last block */ +#define dyn_array_get_last_block(arr) \ + ((arr)->heap ? UT_LIST_GET_LAST((arr)->base) : (arr)) /********************************************************************//** Gets the next block in a dyn array. -@return pointer to next, NULL if end of list */ -UNIV_INLINE -dyn_block_t* -dyn_array_get_next_block( -/*=====================*/ - dyn_array_t* arr, /*!< in: dyn array */ - dyn_block_t* block); /*!< in: dyn array block */ +@param arr dyn array +@param block dyn array block +@return pointer to next, NULL if end of list */ +#define dyn_array_get_next_block(arr, block) \ + ((arr)->heap ? UT_LIST_GET_NEXT(list, block) : NULL) +/********************************************************************//** +Gets the previous block in a dyn array. +@param arr dyn array +@param block dyn array block +@return pointer to previous, NULL if end of list */ +#define dyn_array_get_prev_block(arr, block) \ + ((arr)->heap ? UT_LIST_GET_PREV(list, block) : NULL) /********************************************************************//** Gets the number of used bytes in a dyn array block. @return number of bytes used */ @@ -135,7 +144,8 @@ UNIV_INLINE ulint dyn_block_get_used( /*===============*/ - dyn_block_t* block); /*!< in: dyn array block */ + const dyn_block_t* block) /*!< in: dyn array block */ + __attribute__((nonnull, warn_unused_result, pure)); /********************************************************************//** Gets pointer to the start of data in a dyn array block. @return pointer to data */ @@ -143,16 +153,18 @@ UNIV_INLINE byte* dyn_block_get_data( /*===============*/ - dyn_block_t* block); /*!< in: dyn array block */ + const dyn_block_t* block) /*!< in: dyn array block */ + __attribute__((nonnull, warn_unused_result, pure)); /********************************************************//** Pushes n bytes to a dyn array. */ UNIV_INLINE void dyn_push_string( /*============*/ - dyn_array_t* arr, /*!< in: dyn array */ + dyn_array_t* arr, /*!< in/out: dyn array */ const byte* str, /*!< in: string to write */ - ulint len); /*!< in: string length */ + ulint len) /*!< in: string length */ + __attribute__((nonnull)); /*#################################################################*/ diff --git a/storage/innobase/include/dyn0dyn.ic b/storage/innobase/include/dyn0dyn.ic index 110e674abff..177877ed1fd 100644 --- a/storage/innobase/include/dyn0dyn.ic +++ b/storage/innobase/include/dyn0dyn.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2013, 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 @@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -35,56 +35,8 @@ UNIV_INTERN dyn_block_t* dyn_array_add_block( /*================*/ - dyn_array_t* arr); /*!< in: dyn array */ - - -/************************************************************//** -Gets the first block in a dyn array. */ -UNIV_INLINE -dyn_block_t* -dyn_array_get_first_block( -/*======================*/ - dyn_array_t* arr) /*!< in: dyn array */ -{ - return(arr); -} - -/************************************************************//** -Gets the last block in a dyn array. */ -UNIV_INLINE -dyn_block_t* -dyn_array_get_last_block( -/*=====================*/ - dyn_array_t* arr) /*!< in: dyn array */ -{ - if (arr->heap == NULL) { - - return(arr); - } - - return(UT_LIST_GET_LAST(arr->base)); -} - -/********************************************************************//** -Gets the next block in a dyn array. -@return pointer to next, NULL if end of list */ -UNIV_INLINE -dyn_block_t* -dyn_array_get_next_block( -/*=====================*/ - dyn_array_t* arr, /*!< in: dyn array */ - dyn_block_t* block) /*!< in: dyn array block */ -{ - ut_ad(arr && block); - - if (arr->heap == NULL) { - ut_ad(arr == block); - - return(NULL); - } - - return(UT_LIST_GET_NEXT(list, block)); -} + dyn_array_t* arr) /*!< in/out: dyn array */ + __attribute__((nonnull, warn_unused_result)); /********************************************************************//** Gets the number of used bytes in a dyn array block. @@ -93,7 +45,7 @@ UNIV_INLINE ulint dyn_block_get_used( /*===============*/ - dyn_block_t* block) /*!< in: dyn array block */ + const dyn_block_t* block) /*!< in: dyn array block */ { ut_ad(block); @@ -107,11 +59,11 @@ UNIV_INLINE byte* dyn_block_get_data( /*===============*/ - dyn_block_t* block) /*!< in: dyn array block */ + const dyn_block_t* block) /*!< in: dyn array block */ { ut_ad(block); - return(block->data); + return((byte*) block->data); } /*********************************************************************//** @@ -121,7 +73,7 @@ UNIV_INLINE dyn_array_t* dyn_array_create( /*=============*/ - dyn_array_t* arr) /*!< in: pointer to a memory buffer of + dyn_array_t* arr) /*!< in/out: memory buffer of size sizeof(dyn_array_t) */ { ut_ad(arr); @@ -132,10 +84,9 @@ dyn_array_create( arr->heap = NULL; arr->used = 0; -#ifdef UNIV_DEBUG - arr->buf_end = 0; - arr->magic_n = DYN_BLOCK_MAGIC_N; -#endif + ut_d(arr->buf_end = 0); + ut_d(arr->magic_n = DYN_BLOCK_MAGIC_N); + return(arr); } @@ -151,9 +102,7 @@ dyn_array_free( mem_heap_free(arr->heap); } -#ifdef UNIV_DEBUG - arr->magic_n = 0; -#endif + ut_d(arr->magic_n = 0); } /*********************************************************************//** @@ -164,7 +113,7 @@ UNIV_INLINE void* dyn_array_push( /*===========*/ - dyn_array_t* arr, /*!< in: dynamic array */ + dyn_array_t* arr, /*!< in/out: dynamic array */ ulint size) /*!< in: size in bytes of the element */ { dyn_block_t* block; @@ -176,24 +125,23 @@ dyn_array_push( ut_ad(size); block = arr; - used = block->used; - if (used + size > DYN_ARRAY_DATA_SIZE) { + if (block->used + size > DYN_ARRAY_DATA_SIZE) { /* Get the last array block */ block = dyn_array_get_last_block(arr); - used = block->used; - if (used + size > DYN_ARRAY_DATA_SIZE) { + if (block->used + size > DYN_ARRAY_DATA_SIZE) { block = dyn_array_add_block(arr); - used = block->used; } } + used = block->used; + block->used = used + size; ut_ad(block->used <= DYN_ARRAY_DATA_SIZE); - return((block->data) + used); + return(block->data + used); } /*********************************************************************//** @@ -210,7 +158,6 @@ dyn_array_open( smaller than DYN_ARRAY_DATA_SIZE! */ { dyn_block_t* block; - ulint used; ut_ad(arr); ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N); @@ -218,28 +165,23 @@ dyn_array_open( ut_ad(size); block = arr; - used = block->used; - if (used + size > DYN_ARRAY_DATA_SIZE) { + if (block->used + size > DYN_ARRAY_DATA_SIZE) { /* Get the last array block */ block = dyn_array_get_last_block(arr); - used = block->used; - if (used + size > DYN_ARRAY_DATA_SIZE) { + if (block->used + size > DYN_ARRAY_DATA_SIZE) { block = dyn_array_add_block(arr); - used = block->used; ut_a(size <= DYN_ARRAY_DATA_SIZE); } } ut_ad(block->used <= DYN_ARRAY_DATA_SIZE); -#ifdef UNIV_DEBUG ut_ad(arr->buf_end == 0); + ut_d(arr->buf_end = block->used + size); - arr->buf_end = used + size; -#endif - return((block->data) + used); + return(block->data + block->used); } /*********************************************************************//** @@ -248,8 +190,8 @@ UNIV_INLINE void dyn_array_close( /*============*/ - dyn_array_t* arr, /*!< in: dynamic array */ - byte* ptr) /*!< in: buffer space from ptr up was not used */ + dyn_array_t* arr, /*!< in/out: dynamic array */ + const byte* ptr) /*!< in: end of used space */ { dyn_block_t* block; @@ -264,9 +206,7 @@ dyn_array_close( ut_ad(block->used <= DYN_ARRAY_DATA_SIZE); -#ifdef UNIV_DEBUG - arr->buf_end = 0; -#endif + ut_d(arr->buf_end = 0); } /************************************************************//** @@ -276,12 +216,11 @@ UNIV_INLINE void* dyn_array_get_element( /*==================*/ - dyn_array_t* arr, /*!< in: dyn array */ - ulint pos) /*!< in: position of element as bytes - from array start */ + const dyn_array_t* arr, /*!< in: dyn array */ + ulint pos) /*!< in: position of element + in bytes from array start */ { - dyn_block_t* block; - ulint used; + const dyn_block_t* block; ut_ad(arr); ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N); @@ -290,21 +229,23 @@ dyn_array_get_element( block = dyn_array_get_first_block(arr); if (arr->heap != NULL) { - used = dyn_block_get_used(block); + for (;;) { + ulint used = dyn_block_get_used(block); + + if (pos < used) { + break; + } - while (pos >= used) { pos -= used; block = UT_LIST_GET_NEXT(list, block); ut_ad(block); - - used = dyn_block_get_used(block); } } ut_ad(block); ut_ad(dyn_block_get_used(block) >= pos); - return(block->data + pos); + return((byte*) block->data + pos); } /************************************************************//** @@ -314,10 +255,10 @@ UNIV_INLINE ulint dyn_array_get_data_size( /*====================*/ - dyn_array_t* arr) /*!< in: dyn array */ + const dyn_array_t* arr) /*!< in: dyn array */ { - dyn_block_t* block; - ulint sum = 0; + const dyn_block_t* block; + ulint sum = 0; ut_ad(arr); ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N); @@ -344,7 +285,7 @@ UNIV_INLINE void dyn_push_string( /*============*/ - dyn_array_t* arr, /*!< in: dyn array */ + dyn_array_t* arr, /*!< in/out: dyn array */ const byte* str, /*!< in: string to write */ ulint len) /*!< in: string length */ { diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index a0ec09c892f..4ffc64df238 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -307,4 +307,15 @@ ulint innobase_get_lower_case_table_names(void); /*=====================================*/ +/********************************************************************** +Check if the length of the identifier exceeds the maximum allowed. +The input to this function is an identifier in charset my_charset_filename. +return true when length of identifier is too long. */ +UNIV_INTERN +my_bool +innobase_check_identifier_length( +/*=============================*/ + const char* id); /* in: identifier to check. it must belong + to charset my_charset_filename */ + #endif diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 46f1ff9310c..88ac3c138de 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2013, 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 @@ -295,9 +295,10 @@ UNIV_INTERN void mtr_memo_release( /*=============*/ - mtr_t* mtr, /*!< in: mtr */ + mtr_t* mtr, /*!< in/out: mini-transaction */ void* object, /*!< in: object */ - ulint type); /*!< in: object type: MTR_MEMO_S_LOCK, ... */ + ulint type) /*!< in: object type: MTR_MEMO_S_LOCK, ... */ + __attribute__((nonnull)); #ifdef UNIV_DEBUG # ifndef UNIV_HOTBACKUP /**********************************************************//** @@ -309,7 +310,8 @@ mtr_memo_contains( /*==============*/ mtr_t* mtr, /*!< in: mtr */ const void* object, /*!< in: object to search */ - ulint type); /*!< in: type of object */ + ulint type) /*!< in: type of object */ + __attribute__((warn_unused_result, nonnull)); /**********************************************************//** Checks if memo contains the given page. diff --git a/storage/innobase/include/page0zip.ic b/storage/innobase/include/page0zip.ic index 75cc7a9fcc4..b5480604bdf 100644 --- a/storage/innobase/include/page0zip.ic +++ b/storage/innobase/include/page0zip.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 2005, 2013, 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 @@ -188,8 +188,8 @@ page_zip_rec_needs_ext( one record on an empty leaf page. Subtract 1 byte for the encoded heap number. Check also the available space on the uncompressed page. */ - return(rec_size - (REC_N_NEW_EXTRA_BYTES - 2) - >= (page_zip_empty_size(n_fields, zip_size) - 1) + return(rec_size - (REC_N_NEW_EXTRA_BYTES - 2 - 1) + >= page_zip_empty_size(n_fields, zip_size) || rec_size >= page_get_free_space_of_empty(TRUE) / 2); } diff --git a/storage/innobase/include/ut0dbg.h b/storage/innobase/include/ut0dbg.h index ce6dcb63049..4913b357768 100644 --- a/storage/innobase/include/ut0dbg.h +++ b/storage/innobase/include/ut0dbg.h @@ -55,49 +55,8 @@ ut_dbg_assertion_failed( ulint line) /*!< in: line number of the assertion */ UNIV_COLD __attribute__((nonnull(2))); - -#define UT_DBG_USE_ABORT - - -#ifndef UT_DBG_USE_ABORT -/** A null pointer that will be dereferenced to trigger a memory trap */ -extern ulint* ut_dbg_null_ptr; -#endif - -#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT) -/** If this is set to TRUE by ut_dbg_assertion_failed(), all threads -will stop at the next ut_a() or ut_ad(). */ -extern ibool ut_dbg_stop_threads; - -/*************************************************************//** -Stop a thread after assertion failure. */ -UNIV_INTERN -void -ut_dbg_stop_thread( -/*===============*/ - const char* file, - ulint line); -#endif - -#ifdef UT_DBG_USE_ABORT /** Abort the execution. */ -#ifdef _WIN32 -# define UT_DBG_PANIC __debugbreak() -#else # define UT_DBG_PANIC abort() -#endif -/** Stop threads (null operation) */ -# define UT_DBG_STOP do {} while (0) -#else /* UT_DBG_USE_ABORT */ -/** Abort the execution. */ -# define UT_DBG_PANIC \ - if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL -/** Stop threads in ut_a(). */ -# define UT_DBG_STOP do \ - if (UNIV_UNLIKELY(ut_dbg_stop_threads)) { \ - ut_dbg_stop_thread(__FILE__, (ulint) __LINE__); \ - } while (0) -#endif /* UT_DBG_USE_ABORT */ /** Abort execution if EXPR does not evaluate to nonzero. @param EXPR assertion expression that should hold */ @@ -107,7 +66,6 @@ ut_dbg_stop_thread( __FILE__, (ulint) __LINE__); \ UT_DBG_PANIC; \ } \ - UT_DBG_STOP; \ } while (0) /** Abort execution. */ diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index a72be540c1b..a5ce43496af 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -1997,6 +1997,8 @@ lock_rec_lock_fast( || mode - (LOCK_MODE_MASK & mode) == 0 || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); + DBUG_EXECUTE_IF("innodb_report_deadlock", return(LOCK_REC_FAIL);); + lock = lock_rec_get_first_on_page(block); trx = thr_get_trx(thr); @@ -2074,6 +2076,8 @@ lock_rec_lock_slow( trx = thr_get_trx(thr); + DBUG_EXECUTE_IF("innodb_report_deadlock", return(DB_DEADLOCK);); + lock = lock_rec_has_expl(mode, block, heap_no, trx); if (lock) { if (lock->type_mode & LOCK_CONV_BY_OTHER) { @@ -4124,6 +4128,7 @@ lock_rec_unlock( ut_ad(trx && rec); ut_ad(block->frame == page_align(rec)); + ut_ad(trx->conc_state == TRX_ACTIVE); heap_no = page_rec_get_heap_no(rec); diff --git a/storage/innobase/mtr/mtr0mtr.c b/storage/innobase/mtr/mtr0mtr.c index d852ed6f496..a5c98761523 100644 --- a/storage/innobase/mtr/mtr0mtr.c +++ b/storage/innobase/mtr/mtr0mtr.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2013, 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 @@ -39,72 +39,81 @@ Created 11/26/1995 Heikki Tuuri # include "log0recv.h" /*****************************************************************//** Releases the item in the slot given. */ -static +static __attribute__((nonnull)) void -mtr_memo_slot_release( -/*==================*/ - mtr_t* mtr, /*!< in: mtr */ +mtr_memo_slot_release_func( +/*=======================*/ +#ifdef UNIV_DEBUG + mtr_t* mtr, /*!< in/out: mini-transaction */ +#endif /* UNIV_DEBUG */ mtr_memo_slot_t* slot) /*!< in: memo slot */ { - void* object; - ulint type; - - ut_ad(mtr); - ut_ad(slot); - -#ifndef UNIV_DEBUG - UT_NOT_USED(mtr); -#endif /* UNIV_DEBUG */ - - object = slot->object; - type = slot->type; + void* object = slot->object; + slot->object = NULL; - if (UNIV_LIKELY(object != NULL)) { - if (type <= MTR_MEMO_BUF_FIX) { - buf_page_release((buf_block_t*)object, type); - } else if (type == MTR_MEMO_S_LOCK) { - rw_lock_s_unlock((rw_lock_t*)object); + /* slot release is a local operation for the current mtr. + We must not be holding the flush_order mutex while + doing this. */ + ut_ad(!log_flush_order_mutex_own()); + + switch (slot->type) { + case MTR_MEMO_PAGE_S_FIX: + case MTR_MEMO_PAGE_X_FIX: + case MTR_MEMO_BUF_FIX: + buf_page_release((buf_block_t*) object, slot->type); + break; + case MTR_MEMO_S_LOCK: + rw_lock_s_unlock((rw_lock_t*) object); + break; + case MTR_MEMO_X_LOCK: + rw_lock_x_unlock((rw_lock_t*) object); + break; #ifdef UNIV_DEBUG - } else if (type != MTR_MEMO_X_LOCK) { - ut_ad(type == MTR_MEMO_MODIFY); - ut_ad(mtr_memo_contains(mtr, object, - MTR_MEMO_PAGE_X_FIX)); + default: + ut_ad(slot->type == MTR_MEMO_MODIFY); + ut_ad(mtr_memo_contains(mtr, object, MTR_MEMO_PAGE_X_FIX)); #endif /* UNIV_DEBUG */ - } else { - rw_lock_x_unlock((rw_lock_t*)object); - } } - - slot->object = NULL; } +#ifdef UNIV_DEBUG +# define mtr_memo_slot_release(mtr, slot) mtr_memo_slot_release_func(mtr, slot) +#else /* UNIV_DEBUG */ +# define mtr_memo_slot_release(mtr, slot) mtr_memo_slot_release_func(slot) +#endif /* UNIV_DEBUG */ + /**********************************************************//** Releases the mlocks and other objects stored in an mtr memo. They are released in the order opposite to which they were pushed to the memo. */ -static +static __attribute__((nonnull)) void mtr_memo_pop_all( /*=============*/ - mtr_t* mtr) /*!< in: mtr */ + mtr_t* mtr) /*!< in/out: mini-transaction */ { - mtr_memo_slot_t* slot; - dyn_array_t* memo; - ulint offset; + const dyn_block_t* block; - ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in commit */ - memo = &(mtr->memo); - - offset = dyn_array_get_data_size(memo); - while (offset > 0) { - offset -= sizeof(mtr_memo_slot_t); - slot = dyn_array_get_element(memo, offset); - - mtr_memo_slot_release(mtr, slot); + for (block = dyn_array_get_last_block(&mtr->memo); + block; + block = dyn_array_get_prev_block(&mtr->memo, block)) { + const mtr_memo_slot_t* start + = (mtr_memo_slot_t*) dyn_block_get_data(block); + mtr_memo_slot_t* slot + = (mtr_memo_slot_t*) (dyn_block_get_data(block) + + dyn_block_get_used(block)); + + ut_ad(!(dyn_block_get_used(block) % sizeof(mtr_memo_slot_t))); + + while (slot-- != start) { + if (slot->object != NULL) { + mtr_memo_slot_release(mtr, slot); + } + } } } @@ -288,42 +297,36 @@ UNIV_INTERN void mtr_memo_release( /*=============*/ - mtr_t* mtr, /*!< in: mtr */ + mtr_t* mtr, /*!< in/out: mini-transaction */ void* object, /*!< in: object */ ulint type) /*!< in: object type: MTR_MEMO_S_LOCK, ... */ { - mtr_memo_slot_t* slot; - dyn_array_t* memo; - ulint offset; + const dyn_block_t* block; - ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->state == MTR_ACTIVE); - - memo = &(mtr->memo); - - offset = dyn_array_get_data_size(memo); - - log_flush_order_mutex_enter(); - while (offset > 0) { - offset -= sizeof(mtr_memo_slot_t); - - slot = dyn_array_get_element(memo, offset); - - if (object == slot->object && type == slot->type) { - - /* We cannot release a page that has been written - to in the middle of a mini-transaction. */ - - ut_ad(!(mtr->modifications - && slot->type == MTR_MEMO_PAGE_X_FIX)); - - mtr_memo_slot_release(mtr, slot); - - break; + /* We cannot release a page that has been written to in the + middle of a mini-transaction. */ + ut_ad(!mtr->modifications || type != MTR_MEMO_PAGE_X_FIX); + + for (block = dyn_array_get_last_block(&mtr->memo); + block; + block = dyn_array_get_prev_block(&mtr->memo, block)) { + const mtr_memo_slot_t* start + = (mtr_memo_slot_t*) dyn_block_get_data(block); + mtr_memo_slot_t* slot + = (mtr_memo_slot_t*) (dyn_block_get_data(block) + + dyn_block_get_used(block)); + + ut_ad(!(dyn_block_get_used(block) % sizeof(mtr_memo_slot_t))); + + while (slot-- != start) { + if (object == slot->object && type == slot->type) { + mtr_memo_slot_release(mtr, slot); + return; + } } } - log_flush_order_mutex_exit(); } #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innobase/page/page0zip.c b/storage/innobase/page/page0zip.c index 9f895e60803..f9338da079e 100644 --- a/storage/innobase/page/page0zip.c +++ b/storage/innobase/page/page0zip.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2005, 2013, 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 @@ -837,11 +837,12 @@ page_zip_compress_node_ptrs( c_stream->next_in = (byte*) rec; c_stream->avail_in = rec_offs_data_size(offsets) - REC_NODE_PTR_SIZE; - ut_ad(c_stream->avail_in); - err = deflate(c_stream, Z_NO_FLUSH); - if (UNIV_UNLIKELY(err != Z_OK)) { - break; + if (c_stream->avail_in) { + err = deflate(c_stream, Z_NO_FLUSH); + if (UNIV_UNLIKELY(err != Z_OK)) { + break; + } } ut_ad(!c_stream->avail_in); diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 73da6215f0d..77fa6518b35 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -3840,6 +3840,7 @@ row_rename_table_for_mysql( ut_a(old_name != NULL); ut_a(new_name != NULL); + ut_ad(trx->conc_state == TRX_ACTIVE); if (srv_created_new_raw || srv_force_recovery) { fputs("InnoDB: A new raw disk partition was initialized or\n" @@ -3864,7 +3865,6 @@ row_rename_table_for_mysql( } trx->op_info = "renaming table"; - trx_start_if_not_started(trx); old_is_tmp = row_is_mysql_tmp_table_name(old_name); new_is_tmp = row_is_mysql_tmp_table_name(new_name); diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index b46b2eacd9d..76c1f01d63a 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -57,6 +57,8 @@ Created 12/19/1997 Heikki Tuuri #include "read0read.h" #include "buf0lru.h" #include "ha_prototypes.h" +#include "m_string.h" /* for my_sys.h */ +#include "my_sys.h" /* DEBUG_SYNC_C */ /* Maximum number of rows to prefetch; MySQL interface has another parameter */ #define SEL_MAX_N_PREFETCH 16 @@ -3918,7 +3920,9 @@ wait_table_again: } rec_loop: + DEBUG_SYNC_C("row_search_rec_loop"); if (trx_is_interrupted(trx)) { + btr_pcur_store_position(pcur, &mtr); err = DB_INTERRUPTED; goto normal_return; } diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index c0b2f6cb700..86caf9d4243 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. @@ -279,7 +279,7 @@ UNIV_INTERN ulint srv_data_read = 0; /* Internal setting for "innodb_stats_method". Decides how InnoDB treats NULL value when collecting statistics. By default, it is set to SRV_STATS_NULLS_EQUAL(0), ie. all NULL value are treated equal */ -ulong srv_innodb_stats_method = SRV_STATS_NULLS_EQUAL; +UNIV_INTERN ulong srv_innodb_stats_method = SRV_STATS_NULLS_EQUAL; /* here we count the amount of data written in total (in bytes) */ UNIV_INTERN ulint srv_data_written = 0; @@ -2109,19 +2109,31 @@ srv_export_innodb_status(void) export_vars.innodb_truncated_status_writes = srv_truncated_status_writes; #ifdef UNIV_DEBUG - if (trx_sys->max_trx_id < purge_sys->done_trx_no) { - export_vars.innodb_purge_trx_id_age = 0; - } else { - export_vars.innodb_purge_trx_id_age = - trx_sys->max_trx_id - purge_sys->done_trx_no; - } + { + trx_id_t done_trx_no; + trx_id_t up_limit_id; + + rw_lock_s_lock(&purge_sys->latch); + done_trx_no = purge_sys->done_trx_no; + up_limit_id = purge_sys->view + ? purge_sys->view->up_limit_id + : 0; + rw_lock_s_unlock(&purge_sys->latch); + + if (trx_sys->max_trx_id < done_trx_no) { + export_vars.innodb_purge_trx_id_age = 0; + } else { + export_vars.innodb_purge_trx_id_age = + trx_sys->max_trx_id - done_trx_no; + } - if (!purge_sys->view - || trx_sys->max_trx_id < purge_sys->view->up_limit_id) { - export_vars.innodb_purge_view_trx_id_age = 0; - } else { - export_vars.innodb_purge_view_trx_id_age = - trx_sys->max_trx_id - purge_sys->view->up_limit_id; + if (!up_limit_id + || trx_sys->max_trx_id < up_limit_id) { + export_vars.innodb_purge_view_trx_id_age = 0; + } else { + export_vars.innodb_purge_view_trx_id_age = + trx_sys->max_trx_id - up_limit_id; + } } #endif /* UNIV_DEBUG */ diff --git a/storage/innobase/sync/sync0arr.c b/storage/innobase/sync/sync0arr.c index c6cbfc94dca..b2778184335 100644 --- a/storage/innobase/sync/sync0arr.c +++ b/storage/innobase/sync/sync0arr.c @@ -604,10 +604,6 @@ sync_array_deadlock_step( new = sync_array_find_thread(arr, thread); if (UNIV_UNLIKELY(new == start)) { - /* Stop running of other threads */ - - ut_dbg_stop_threads = TRUE; - /* Deadlock */ fputs("########################################\n" "DEADLOCK of threads detected!\n", stderr); @@ -945,6 +941,8 @@ sync_array_print_long_waits( # define SYNC_ARRAY_TIMEOUT 240 #endif + sync_array_enter(sync_primary_wait_array); + for (i = 0; i < sync_primary_wait_array->n_cells; i++) { double diff; @@ -979,6 +977,8 @@ sync_array_print_long_waits( } } + sync_array_exit(sync_primary_wait_array); + if (noticed) { fprintf(stderr, "InnoDB: ###### Starts InnoDB Monitor" diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c index 0c5e367ac30..bc51dc43032 100644 --- a/storage/innobase/trx/trx0sys.c +++ b/storage/innobase/trx/trx0sys.c @@ -137,7 +137,7 @@ UNIV_INTERN mysql_pfs_key_t file_format_max_mutex_key; #ifndef UNIV_HOTBACKUP #ifdef UNIV_DEBUG /* Flag to control TRX_RSEG_N_SLOTS behavior debugging. */ -uint trx_rseg_n_slots_debug = 0; +UNIV_INTERN uint trx_rseg_n_slots_debug = 0; #endif /** This is used to track the maximum file format id known to InnoDB. It's diff --git a/storage/innobase/ut/ut0dbg.c b/storage/innobase/ut/ut0dbg.c index 53ed4a53044..a440b72d32a 100644 --- a/storage/innobase/ut/ut0dbg.c +++ b/storage/innobase/ut/ut0dbg.c @@ -35,16 +35,6 @@ Created 1/30/1994 Heikki Tuuri UNIV_INTERN ulint ut_dbg_zero = 0; #endif -#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT) -/** If this is set to TRUE by ut_dbg_assertion_failed(), all threads -will stop at the next ut_a() or ut_ad(). */ -UNIV_INTERN ibool ut_dbg_stop_threads = FALSE; -#endif -#ifndef UT_DBG_USE_ABORT -/** A null pointer that will be dereferenced to trigger a memory trap */ -UNIV_INTERN ulint* ut_dbg_null_ptr = NULL; -#endif - /*************************************************************//** Report a failed assertion. */ UNIV_INTERN @@ -80,30 +70,8 @@ ut_dbg_assertion_failed( "InnoDB: corruption in the InnoDB tablespace. Please refer to\n" "InnoDB: " REFMAN "forcing-innodb-recovery.html\n" "InnoDB: about forcing recovery.\n", stderr); -#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT) - ut_dbg_stop_threads = TRUE; -#endif } -#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT) -/*************************************************************//** -Stop a thread after assertion failure. */ -UNIV_INTERN -void -ut_dbg_stop_thread( -/*===============*/ - const char* file, - ulint line) -{ -#ifndef UNIV_HOTBACKUP - fprintf(stderr, "InnoDB: Thread %lu stopped in file %s line %lu\n", - os_thread_pf(os_thread_get_curr_id()), - innobase_basename(file), line); - os_thread_sleep(1000000000); -#endif /* !UNIV_HOTBACKUP */ -} -#endif - #ifdef UNIV_COMPILE_TEST_FUNCS #include <sys/types.h> diff --git a/storage/innobase/ut/ut0ut.c b/storage/innobase/ut/ut0ut.c index 2fe45aad2a7..699af1fcaa1 100644 --- a/storage/innobase/ut/ut0ut.c +++ b/storage/innobase/ut/ut0ut.c @@ -728,6 +728,8 @@ ut_strerr( return("End of index"); case DB_TABLE_IN_FK_CHECK: return("Table is being used in foreign key check"); + case DB_IDENTIFIER_TOO_LONG: + return("Identifier name is too long"); /* do not add default: in order to produce a warning if new code is added to the enum but not added here */ } diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 6561bec5f22..f215b04b68f 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -1304,8 +1304,9 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt) old_proc_info= thd_proc_info(thd, "Checking status"); thd_progress_init(thd, 3); - (void) maria_chk_status(¶m, file); // Not fatal - error= maria_chk_size(¶m, file); + error= maria_chk_status(¶m, file); // Not fatal + if (maria_chk_size(¶m, file)) + error= 1; if (!error) error|= maria_chk_del(¶m, file, param.testflag); thd_proc_info(thd, "Checking keys"); @@ -1669,6 +1670,11 @@ int ha_maria::repair(THD *thd, HA_CHECK *param, bool do_optimize) } } thd_proc_info(thd, "Saving state"); + if (optimize_done && !error && !(param->testflag & T_NO_CREATE_RENAME_LSN)) + { + /* Set trid (needed if the table was moved from another system) */ + share->state.create_trid= trnman_get_min_safe_trid(); + } mysql_mutex_lock(&share->intern_lock); if (!error) { @@ -1684,6 +1690,7 @@ int ha_maria::repair(THD *thd, HA_CHECK *param, bool do_optimize) */ if (file->state != &share->state.state) *file->state= share->state.state; + if (share->base.auto_key) _ma_update_auto_increment_key(param, file, 1); if (optimize_done) @@ -1691,6 +1698,9 @@ int ha_maria::repair(THD *thd, HA_CHECK *param, bool do_optimize) UPDATE_TIME | UPDATE_OPEN_COUNT | (local_testflag & T_STATISTICS ? UPDATE_STAT : 0)); + /* File is repaired; Mark the file as moved to this system */ + (void) _ma_set_uuid(share, 0); + info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE | HA_STATUS_CONST); if (rows != file->state->records && !(param->testflag & T_VERY_SILENT)) @@ -2411,7 +2421,9 @@ int ha_maria::remember_rnd_pos() int ha_maria::restart_rnd_next(uchar *buf) { - (*file->s->scan_restore_pos)(file, remember_pos); + int error; + if ((error= (*file->s->scan_restore_pos)(file, remember_pos))) + return error; return rnd_next(buf); } @@ -2644,23 +2656,6 @@ int ha_maria::external_lock(THD *thd, int lock_type) /* Transactional table */ if (lock_type != F_UNLCK) { - if (!file->s->lock_key_trees) // If we don't use versioning - { - /* - We come here in the following cases: - - The table is a temporary table - - It's a table which is crash safe but not yet versioned, for - example a table with fulltext or rtree keys - - Set the current state to point to save_state so that the - block_format code don't count the same record twice. - Copy also the current state. This may have been wrong if the - same file was used several times in the last statement - */ - file->state= file->state_start; - *file->state= file->s->state.state; - } - if (file->trn) { /* This can only happen with tables created with clone() */ diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index 16657ba80ae..03fd0200d18 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -4007,6 +4007,8 @@ static int delete_dir_entry(uchar *buff, uint block_size, uint record_number, uint length, empty_space; uchar *dir; DBUG_ENTER("delete_dir_entry"); + DBUG_PRINT("enter", ("record_number: %u number_of_records: %u", + record_number, number_of_records)); #ifdef SANITY_CHECKS if (record_number >= number_of_records || @@ -4023,7 +4025,8 @@ static int delete_dir_entry(uchar *buff, uint block_size, uint record_number, check_directory(buff, block_size, 0, (uint) -1); empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET); dir= dir_entry_pos(buff, block_size, record_number); - length= uint2korr(dir + 2); + length= uint2korr(dir + 2); /* Length of entry we just deleted */ + DBUG_ASSERT(uint2korr(dir) != 0 && length < block_size); if (record_number == number_of_records - 1) { @@ -5240,11 +5243,6 @@ void _ma_scan_end_block_record(MARIA_HA *info) For the moment we can only remember one position, but this is good enough for MySQL usage - @Warning - When this function is called, we assume that the thread is not deleting - or updating the current row before ma_scan_restore_block_record() - is called! - @return @retval 0 ok @retval HA_ERR_WRONG_IN_RECORD Could not allocate memory to hold position @@ -5264,15 +5262,18 @@ int _ma_scan_remember_block_record(MARIA_HA *info, info->scan_save->bitmap_buff= ((uchar*) info->scan_save + ALIGN_SIZE(sizeof(*info->scan_save))); } - /* Point to the last read row */ - *lastpos= info->cur_row.nextpos - 1; - info->scan.dir+= DIR_ENTRY_SIZE; + /* For checking if pages have changed since we last read it */ + info->scan.row_changes= info->row_changes; /* Remember used bitmap and used head page */ bitmap_buff= info->scan_save->bitmap_buff; memcpy(info->scan_save, &info->scan, sizeof(*info->scan_save)); info->scan_save->bitmap_buff= bitmap_buff; memcpy(bitmap_buff, info->scan.bitmap_buff, info->s->block_size * 2); + + /* Point to the last read row */ + *lastpos= info->cur_row.nextpos - 1; + info->scan_save->dir+= DIR_ENTRY_SIZE; DBUG_RETURN(0); } @@ -5280,15 +5281,22 @@ int _ma_scan_remember_block_record(MARIA_HA *info, /** @brief restore scan block it's original values + @return + 0 ok + # error + @note In theory we could swap bitmap buffers instead of copy them. For the moment we don't do that because there are variables pointing inside the buffers and it's a bit of hassle to either make them relative or repoint them. + + If the data file has changed, we will re-read the new block record + to ensure that when we continue scanning we can ignore any deleted rows. */ -void _ma_scan_restore_block_record(MARIA_HA *info, - MARIA_RECORD_POS lastpos) +int _ma_scan_restore_block_record(MARIA_HA *info, + MARIA_RECORD_POS lastpos) { uchar *bitmap_buff; DBUG_ENTER("_ma_scan_restore_block_record"); @@ -5299,7 +5307,26 @@ void _ma_scan_restore_block_record(MARIA_HA *info, info->scan.bitmap_buff= bitmap_buff; memcpy(bitmap_buff, info->scan_save->bitmap_buff, info->s->block_size * 2); - DBUG_VOID_RETURN; + if (info->scan.row_changes != info->row_changes) + { + /* + Table has been changed. We have to re-read the current page block as + data may have changed on it that we have to see. + */ + if (!(pagecache_read(info->s->pagecache, + &info->dfile, + ma_recordpos_to_page(info->scan.row_base_page), + 0, info->scan.page_buff, + info->s->page_type, + PAGECACHE_LOCK_LEFT_UNLOCKED, 0))) + DBUG_RETURN(my_errno); + info->scan.number_of_rows= + (uint) (uchar) info->scan.page_buff[DIR_COUNT_OFFSET]; + info->scan.dir_end= (info->scan.page_buff + info->s->block_size - + PAGE_SUFFIX_SIZE - + info->scan.number_of_rows * DIR_ENTRY_SIZE); + } + DBUG_RETURN(0); } @@ -5326,7 +5353,7 @@ void _ma_scan_restore_block_record(MARIA_HA *info, RETURN 0 ok - # Error code + # Error code (Normally HA_ERR_END_OF_FILE) */ int _ma_scan_block_record(MARIA_HA *info, uchar *record, @@ -5345,6 +5372,12 @@ restart_record_read: uchar *data, *end_of_data; int error; + /* Ensure that scan.dir and record_pos are in sync */ + DBUG_ASSERT(info->scan.dir == dir_entry_pos(info->scan.page_buff, + share->block_size, + record_pos)); + + /* Search for a valid directory entry (not 0) */ while (!(offset= uint2korr(info->scan.dir))) { info->scan.dir-= DIR_ENTRY_SIZE; @@ -5357,13 +5390,19 @@ restart_record_read: } #endif } + /* + This should always be true as the directory should always start with + a valid entry. + */ + DBUG_ASSERT(info->scan.dir >= info->scan.dir_end); + /* found row */ info->cur_row.lastpos= info->scan.row_base_page + record_pos; info->cur_row.nextpos= record_pos + 1; data= info->scan.page_buff + offset; length= uint2korr(info->scan.dir + 2); end_of_data= data + length; - info->scan.dir-= DIR_ENTRY_SIZE; /* Point to previous row */ + info->scan.dir-= DIR_ENTRY_SIZE; /* Point to next row to process */ #ifdef SANITY_CHECKS if (end_of_data > info->scan.dir_end || offset < PAGE_HEADER_SIZE || length < share->base.min_block_length) @@ -6937,6 +6976,7 @@ my_bool _ma_apply_undo_row_insert(MARIA_HA *info, LSN undo_lsn, res= 0; end: + /* The following is true only if _ma_bitmap_flushable() was called earlier */ if (info->non_flushable_state) _ma_bitmap_flushable(info, -1); _ma_unpin_all_pages_and_finalize_row(info, lsn); @@ -6946,6 +6986,11 @@ err: DBUG_ASSERT(!maria_assert_if_crashed_table); res= 1; _ma_mark_file_crashed(share); + /* + Don't write a new LSN on the used pages. Not important as the file is + marked as crashed and need to be repaired before it can be used. + */ + lsn= LSN_IMPOSSIBLE; goto end; } diff --git a/storage/maria/ma_blockrec.h b/storage/maria/ma_blockrec.h index 45f5613bb60..40ca2591236 100644 --- a/storage/maria/ma_blockrec.h +++ b/storage/maria/ma_blockrec.h @@ -167,8 +167,8 @@ my_bool _ma_scan_init_block_record(MARIA_HA *info); void _ma_scan_end_block_record(MARIA_HA *info); int _ma_scan_remember_block_record(MARIA_HA *info, MARIA_RECORD_POS *lastpos); -void _ma_scan_restore_block_record(MARIA_HA *info, - MARIA_RECORD_POS lastpos); +int _ma_scan_restore_block_record(MARIA_HA *info, + MARIA_RECORD_POS lastpos); MARIA_RECORD_POS _ma_write_init_block_record(MARIA_HA *info, const uchar *record); diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 6bcb9c21a71..fdb2bae3d8c 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -140,13 +140,22 @@ void maria_chk_init_for_check(HA_CHECK *param, MARIA_HA *info) Set up transaction handler so that we can see all rows. When rows is read we will check the found id against param->max_tried */ - if (param->max_trid == 0) + if (!info->s->base.born_transactional) + { + /* + There are no trids. Howver we want to set max_trid to make test of + create_trid simpler. + */ + param->max_trid= ~(TrID) 0; + } + else if (param->max_trid == 0) { if (!ma_control_file_inited()) param->max_trid= 0; /* Give warning for first trid found */ else param->max_trid= max_trid_in_system(); } + maria_ignore_trids(info); } @@ -179,6 +188,13 @@ int maria_chk_status(HA_CHECK *param, MARIA_HA *info) if (param->testflag & T_UPDATE_STATE) param->warning_printed=save; } + if (share->state.create_trid > param->max_trid) + { + _ma_check_print_warning(param, + "Table create_trd (%llu) > current max_transaction id (%llu). Table needs to be repaired or zerofilled to be usable", + share->state.create_trid, param->max_trid); + return 1; + } return 0; } @@ -2424,11 +2440,10 @@ static void restore_table_state_after_repair(MARIA_HA *info, { maria_versioning(info, info->s->have_versioning); info->s->lock_key_trees= org_share->lock_key_trees; + DBUG_ASSERT(!info->s->have_versioning || info->s->lock_key_trees); } - - /** @brief Drop all indexes @@ -3553,7 +3568,10 @@ int maria_zerofill(HA_CHECK *param, MARIA_HA *info, const char *name) /* Ensure state is later flushed to disk, if within maria_chk */ info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - /* Reset create_trid to make file comparable */ + /* + Reset create_trid to make file comparable and to ensure that new + trid's in the file starts from 0. + */ share->state.create_trid= 0; } if (reenable_logging) diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c index 5b8d0e01677..22f7341098d 100644 --- a/storage/maria/ma_delete.c +++ b/storage/maria/ma_delete.c @@ -112,6 +112,7 @@ int maria_delete(MARIA_HA *info,const uchar *record) info->state->checksum-= info->cur_row.checksum; info->state->records--; info->update= HA_STATE_CHANGED+HA_STATE_DELETED+HA_STATE_ROW_CHANGED; + info->row_changes++; share->state.changed|= (STATE_NOT_OPTIMIZED_ROWS | STATE_NOT_MOVABLE | STATE_NOT_ZEROFILLED); info->state->changed=1; diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 5233e57594c..f0ade217341 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -7472,9 +7472,8 @@ static void translog_force_current_buffer_to_finish() struct st_translog_buffer *old_buffer= log_descriptor.bc.buffer; uchar *data= log_descriptor.bc.ptr - log_descriptor.bc.current_page_fill; uint16 left= TRANSLOG_PAGE_SIZE - log_descriptor.bc.current_page_fill; - uint16 current_page_fill, write_counter, previous_offset; + uint16 UNINIT_VAR(current_page_fill), write_counter, previous_offset; DBUG_ENTER("translog_force_current_buffer_to_finish"); - LINT_INIT(current_page_fill); DBUG_PRINT("enter", ("Buffer #%u 0x%lx " "Buffer addr: (%lu,0x%lx) " diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 88422e3dc5f..d2ae10ccb18 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -437,15 +437,23 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) share->open_count_not_zero_on_open= 1; /* + A transactional table is not usable on this system if: + - share->state.create_trid > trnman_get_max_trid() + - Critical as trid as stored releativel to create_trid. + - uuid is different + + STATE_NOT_MOVABLE is reset when a table is zerofilled + (has no LSN's and no trids) + We can ignore testing uuid if STATE_NOT_MOVABLE is set, as in this - case the uuid will be set in _ma_mark_file_changed() + case the uuid will be set in _ma_mark_file_changed(). */ - if ((share->state.changed & STATE_NOT_MOVABLE) && - share->base.born_transactional && - ((!(open_flags & HA_OPEN_IGNORE_MOVED_STATE) && - memcmp(share->base.uuid, maria_uuid, MY_UUID_SIZE)) || - (share->state.create_trid > trnman_get_max_trid() && - !maria_in_recovery))) + if (share->base.born_transactional && + ((share->state.create_trid > trnman_get_max_trid() && + !maria_in_recovery) || + ((share->state.changed & STATE_NOT_MOVABLE) && + ((!(open_flags & HA_OPEN_IGNORE_MOVED_STATE) && + memcmp(share->base.uuid, maria_uuid, MY_UUID_SIZE)))))) { DBUG_PRINT("warning", ("table is moved from another system. uuid_diff: %d create_trid: %lu max_trid: %lu", memcmp(share->base.uuid, maria_uuid, @@ -756,7 +764,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE); goto err; } - else + else if (!(open_flags & HA_OPEN_FOR_REPAIR)) { /* create_rename_lsn != LSN_NEEDS_NEW_STATE_LSNS */ share->state.changed|= STATE_NOT_MOVABLE; @@ -894,8 +902,10 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) &share->keyinfo[i].root_lock); mysql_rwlock_init(key_SHARE_mmap_lock, &share->mmap_lock); - share->row_is_visible= _ma_row_visible_always; - share->lock.get_status= _ma_reset_update_flag; + share->row_is_visible= _ma_row_visible_always; + share->lock.get_status= _ma_reset_update_flag; + share->lock.start_trans= _ma_start_trans; + if (!thr_lock_inited) { /* Probably a single threaded program; Don't use concurrent inserts */ diff --git a/storage/maria/ma_pagecrc.c b/storage/maria/ma_pagecrc.c index 58e3b4b203d..a79f34016c1 100644 --- a/storage/maria/ma_pagecrc.c +++ b/storage/maria/ma_pagecrc.c @@ -358,8 +358,7 @@ my_bool maria_flush_log_for_page(uchar *page, MARIA_SHARE *share= (MARIA_SHARE*) data_ptr; DBUG_ENTER("maria_flush_log_for_page"); /* share is 0 here only in unittest */ - DBUG_ASSERT(!share || (share->page_type == PAGECACHE_LSN_PAGE && - share->now_transactional)); + DBUG_ASSERT(!share || share->page_type == PAGECACHE_LSN_PAGE); lsn= lsn_korr(page); if (translog_flush(lsn)) DBUG_RETURN(1); diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index aeeda26b791..bd2bde1c89a 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -3304,7 +3304,7 @@ static LSN parse_checkpoint_record(LSN lsn) first_log_write_lsn= lsn_korr(ptr); ptr+= LSN_STORE_SIZE; name_len= strlen((char *)ptr) + 1; - strmake(name, (char *)ptr, sizeof(name)-1); + strmake_buf(name, (char *)ptr); ptr+= name_len; if (new_table(sid, name, first_log_write_lsn)) return LSN_ERROR; diff --git a/storage/maria/ma_scan.c b/storage/maria/ma_scan.c index cbac463a2c8..ad526211615 100644 --- a/storage/maria/ma_scan.c +++ b/storage/maria/ma_scan.c @@ -68,7 +68,8 @@ int _ma_def_scan_remember_pos(MARIA_HA *info, MARIA_RECORD_POS *lastpos) } -void _ma_def_scan_restore_pos(MARIA_HA *info, MARIA_RECORD_POS lastpos) +int _ma_def_scan_restore_pos(MARIA_HA *info, MARIA_RECORD_POS lastpos) { info->cur_row.nextpos= lastpos; + return 0; } diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c index ccb4bf77717..d38bc7af26c 100644 --- a/storage/maria/ma_search.c +++ b/storage/maria/ma_search.c @@ -424,9 +424,9 @@ int _ma_prefix_search(const MARIA_KEY *key, const MARIA_PAGE *ma_page, flag is the value returned by ha_key_cmp and as treated as final */ int flag=0, my_flag=-1; - uint nod_flag, length, len, matched, cmplen, kseg_len; - uint page_flag, prefix_len,suffix_len; - int key_len_skip, seg_len_pack, key_len_left; + uint nod_flag, UNINIT_VAR(length), len, matched, cmplen, kseg_len; + uint page_flag, UNINIT_VAR(prefix_len),suffix_len; + int key_len_skip, UNINIT_VAR(seg_len_pack), key_len_left; uchar *end, *vseg, *UNINIT_VAR(saved_vseg), *UNINIT_VAR(saved_from); uchar *page; uchar tt_buff[MARIA_MAX_KEY_BUFF+2], *t_buff=tt_buff+2; @@ -439,10 +439,6 @@ int _ma_prefix_search(const MARIA_KEY *key, const MARIA_PAGE *ma_page, const uchar *sort_order= keyinfo->seg->charset->sort_order; DBUG_ENTER("_ma_prefix_search"); - LINT_INIT(seg_len_pack); - LINT_INIT(prefix_len); - LINT_INIT(length); - t_buff[0]=0; /* Avoid bugs */ page_flag= ma_page->flag; nod_flag= ma_page->node; diff --git a/storage/maria/ma_state.c b/storage/maria/ma_state.c index 1f4a7504c56..f130da21d07 100644 --- a/storage/maria/ma_state.c +++ b/storage/maria/ma_state.c @@ -59,6 +59,8 @@ my_bool _ma_setup_live_state(MARIA_HA *info) MARIA_STATE_HISTORY *history; DBUG_ENTER("_ma_setup_live_state"); + DBUG_ASSERT(share->lock_key_trees); + if (maria_create_trn_hook(info)) DBUG_RETURN(1); @@ -377,6 +379,17 @@ void _ma_reset_update_flag(void *param, info->state->changed= 0; } +my_bool _ma_start_trans(void* param) +{ + MARIA_HA *info=(MARIA_HA*) param; + if (!info->s->lock_key_trees) + { + info->state= info->state_start; + *info->state= info->s->state.state; + } + return 0; +} + /** @brief Check if should allow concurrent inserts @@ -622,6 +635,22 @@ my_bool _ma_block_start_trans(void* param) */ return _ma_setup_live_state(info); } + else + { + /* + We come here in the following cases: + - The table is a temporary table + - It's a table which is crash safe but not yet versioned, for + example a table with fulltext or rtree keys + + Set the current state to point to save_state so that the + block_format code don't count the same record twice. + Copy also the current state. This may have been wrong if the + same file was used several times in the last statement + */ + info->state= info->state_start; + *info->state= info->s->state.state; + } /* Info->trn is set if this table is already handled and we are @@ -668,9 +697,11 @@ my_bool _ma_block_start_trans_no_versioning(void* param) { MARIA_HA *info=(MARIA_HA*) param; DBUG_ENTER("_ma_block_get_status_no_version"); - DBUG_ASSERT(info->s->base.born_transactional); + DBUG_ASSERT(info->s->base.born_transactional && !info->s->lock_key_trees); info->state->changed= 0; /* from _ma_reset_update_flag() */ + info->state= info->state_start; + *info->state= info->s->state.state; if (!info->trn) { /* @@ -689,18 +720,22 @@ my_bool _ma_block_start_trans_no_versioning(void* param) void maria_versioning(MARIA_HA *info, my_bool versioning) { + MARIA_SHARE *share= info->s; /* For now, this is a hack */ - if (info->s->have_versioning) + if (share->have_versioning) { enum thr_lock_type save_lock_type; - /* Assume is a non threaded application (for now) */ - info->s->lock_key_trees= 0; + share->lock_key_trees= versioning; /* Set up info->lock.type temporary for _ma_block_get_status() */ save_lock_type= info->lock.type; info->lock.type= versioning ? TL_WRITE_CONCURRENT_INSERT : TL_WRITE; _ma_block_get_status((void*) info, versioning); info->lock.type= save_lock_type; - info->state= info->state_start= &info->s->state.common; + if (versioning) + info->state= &share->state.common; + else + info->state= &share->state.state; /* Change global values by default */ + info->state_start= info->state; /* Initial values */ } } diff --git a/storage/maria/ma_state.h b/storage/maria/ma_state.h index 03ce5c2ea8c..2903986e32a 100644 --- a/storage/maria/ma_state.h +++ b/storage/maria/ma_state.h @@ -66,6 +66,7 @@ void _ma_update_status_with_lock(MARIA_HA *info); void _ma_restore_status(void *param); void _ma_copy_status(void* to, void *from); void _ma_reset_update_flag(void *param, my_bool concurrent_insert); +my_bool _ma_start_trans(void* param); my_bool _ma_check_status(void *param); void _ma_block_get_status(void* param, my_bool concurrent_insert); void _ma_block_update_status(void *param); diff --git a/storage/maria/ma_test1.c b/storage/maria/ma_test1.c index 945654a0bbe..5a655d4412a 100644 --- a/storage/maria/ma_test1.c +++ b/storage/maria/ma_test1.c @@ -55,7 +55,6 @@ static void create_key(uchar *key,uint rownr); static void create_record(uchar *record,uint rownr); static void update_record(uchar *record); - /* These are here only for testing of recovery with undo. We are not including maria_def.h here as this test is also to be an example of @@ -506,6 +505,7 @@ end: break; } printf("Dying on request without maria_commit()/maria_close()\n"); + sf_leaking_memory= 1; exit(0); } @@ -514,6 +514,7 @@ end: if (maria_close(file)) goto err; maria_end(); + my_uuid_end(); my_end(MY_CHECK_ERROR); return (0); diff --git a/storage/maria/ma_test2.c b/storage/maria/ma_test2.c index ea1978b4ee5..a3b7a2a9e98 100644 --- a/storage/maria/ma_test2.c +++ b/storage/maria/ma_test2.c @@ -971,6 +971,7 @@ end: break; } printf("Dying on request without maria_commit()/maria_close()\n"); + sf_leaking_memory= 1; /* no memory leak reports here */ exit(0); } if (maria_commit(file)) @@ -1017,6 +1018,7 @@ reads: %10lu\n", } maria_end(); my_free(blob_buffer); + my_uuid_end(); my_end(silent ? MY_CHECK_ERROR : MY_CHECK_ERROR | MY_GIVE_INFO); return(0); err: @@ -1029,6 +1031,8 @@ err2: maria_close(file); } maria_end(); + my_uuid_end(); + my_end(0); return(1); } /* main */ diff --git a/storage/maria/ma_update.c b/storage/maria/ma_update.c index 0a726c1b7f9..e0e804ca655 100644 --- a/storage/maria/ma_update.c +++ b/storage/maria/ma_update.c @@ -173,6 +173,7 @@ int maria_update(register MARIA_HA *info, const uchar *oldrec, uchar *newrec) We can't yet have HA_STATE_AKTIV here, as block_record dosn't support it */ info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | key_changed); + info->row_changes++; share->state.changed|= STATE_NOT_MOVABLE | STATE_NOT_ZEROFILLED; info->state->changed= 1; diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index 752741d0a5e..09d42a9be72 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -298,6 +298,7 @@ int maria_write(MARIA_HA *info, uchar *record) info->state->records++; info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_WRITTEN | HA_STATE_ROW_CHANGED); + info->row_changes++; share->state.changed|= STATE_NOT_MOVABLE | STATE_NOT_ZEROFILLED; info->state->changed= 1; diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c index 8a7ba30eb08..065063fcb07 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/maria_chk.c @@ -88,9 +88,22 @@ static int sort_record_index(MARIA_SORT_PARAM *sort_param, MARIA_PAGE *page, uint sortkey, File new_file, my_bool update_index); static my_bool write_log_record(HA_CHECK *param); +static void my_exit(int exit_code) __attribute__ ((noreturn)); HA_CHECK check_param; +/* Free memory and exit */ + +static void my_exit(int exit_code) +{ + free_tmpdir(&maria_chk_tmpdir); + free_defaults(default_argv); + my_end(check_param.testflag & T_INFO ? + MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR); + exit(exit_code); +} + + /* Main program */ int main(int argc, char **argv) @@ -178,12 +191,8 @@ end: printf("\nTotal of all %d Aria-files:\nData records: %9s Deleted blocks: %9s\n",check_param.total_files,llstr(check_param.total_records,buff), llstr(check_param.total_deleted,buff2)); } - free_defaults(default_argv); - free_tmpdir(&maria_chk_tmpdir); maria_end(); - my_end(check_param.testflag & T_INFO ? - MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR); - exit(error); + my_exit(error); #ifndef _lint return 0; /* No compiler warning */ #endif @@ -257,10 +266,10 @@ static struct my_option my_long_options[] = "Restart with -r if there are any errors in the table. States will be updated as with --update-state.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"HELP", 'H', - "Display this help and exit.", + "Print all argument options sorted alphabetically and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"help", '?', - "Display this help and exit.", + "Print all options by groups and exit. See also --HELP", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"information", 'i', "Print statistics information about table that is checked.", @@ -410,7 +419,7 @@ static struct my_option my_long_options[] = (char**) &maria_stats_method_str, (char**) &maria_stats_method_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { "zerofill", 'z', - "Fill empty space in data and index files with zeroes,", + "Fill empty space in data and index files with zeroes. This makes the data file movable between different servers.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, { "zerofill-keep-lsn", OPT_ZEROFILL_KEEP_LSN, "Like --zerofill but does not zero out LSN of data/index pages;" @@ -422,7 +431,7 @@ static struct my_option my_long_options[] = static void print_version(void) { - printf("%s Ver 1.1 for %s at %s\n", my_progname, SYSTEM_TYPE, + printf("%s Ver 1.2 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE); } @@ -441,8 +450,8 @@ static void usage(void) -#, --debug=... Output debug log. Often this is 'd:t:o,filename'.\n"); #endif printf("\ - -H, --HELP Display this help and exit.\n\ - -?, --help Display this help and exit.\n\ + -H, --HELP Print all argument options sorted alphabetically.\n\ + -?, --help Print all options by groups\n\ --datadir=path Path for control file (and logs if --logdir not used)\n\ --logdir=path Path for log files\n\ --ignore-control-file Don't open the control file. Only use this if you\n\ @@ -566,7 +575,9 @@ Recover (repair)/ options (When using '--recover' or '--safe-recover'):\n\ (It may be VERY slow to do a sort the first time!).\n\ -b, --block-search=#\n\ Find a record, a block at given offset belongs to.\n\ - -z, --zerofill Fill empty space in data and index files with zeroes\n\ + -z, --zerofill Fill empty space in data and index files with zeroes.\n\ + This makes the data file movable between different \n\ + servers.\n\ --zerofill-keep-lsn Like --zerofill but does not zero out LSN of\n\ data/index pages."); @@ -790,7 +801,7 @@ get_one_option(int optid, fprintf(stderr, "The value of the sort key is bigger than max key: %d.\n", MARIA_MAX_KEY); - exit(1); + my_exit(1); } } break; @@ -818,7 +829,7 @@ get_one_option(int optid, break; case 'V': print_version(); - exit(0); + my_exit(0); case OPT_CORRECT_CHECKSUM: if (argument == disabled_my_option) check_param.testflag&= ~T_CALC_CHECKSUM; @@ -833,7 +844,7 @@ get_one_option(int optid, if ((method=find_type(argument, &maria_stats_method_typelib, 2)) <= 0) { fprintf(stderr, "Invalid value of stats_method: %s.\n", argument); - exit(1); + my_exit(1); } switch (method-1) { case 0: @@ -869,10 +880,11 @@ get_one_option(int optid, break; case 'H': my_print_help(my_long_options); - exit(0); + my_print_variables(my_long_options); + my_exit(0); case '?': usage(); - exit(0); + my_exit(0); } return 0; } @@ -889,7 +901,7 @@ static void get_options(register int *argc,register char ***argv) check_param.testflag|=T_WRITE_LOOP; if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) - exit(ho_error); + my_exit(ho_error); /* If using repair, then update checksum if one uses --update-state */ if ((check_param.testflag & T_UPDATE_STATE) && @@ -899,7 +911,7 @@ static void get_options(register int *argc,register char ***argv) if (*argc == 0) { usage(); - exit(-1); + my_exit(-1); } if ((check_param.testflag & T_UNPACK) && @@ -907,7 +919,7 @@ static void get_options(register int *argc,register char ***argv) { fprintf(stderr, "%s: --unpack can't be used with --quick or --sort-records\n", my_progname_short); - exit(1); + my_exit(1); } if ((check_param.testflag & T_READONLY) && (check_param.testflag & @@ -916,7 +928,7 @@ static void get_options(register int *argc,register char ***argv) { fprintf(stderr, "%s: Can't use --readonly when repairing or sorting\n", my_progname_short); - exit(1); + my_exit(1); } if (!opt_debug) @@ -924,20 +936,26 @@ static void get_options(register int *argc,register char ***argv) DEBUGGER_OFF; /* Speed up things a bit */ } if (init_tmpdir(&maria_chk_tmpdir, opt_tmpdir)) - exit(1); + my_exit(1); check_param.tmpdir=&maria_chk_tmpdir; if (set_collation_name) if (!(set_collation= get_charset_by_name(set_collation_name, MYF(MY_WME)))) - exit(1); + my_exit(1); if (maria_data_root != default_log_dir && opt_log_dir == default_log_dir) { /* --datadir was used and --log-dir was not. Set log-dir to datadir */ opt_log_dir= maria_data_root; } + + /* If we are using zerofill, then we don't need to read the control file */ + if ((check_param.testflag & (T_ZEROFILL_KEEP_LSN | T_ZEROFILL)) && + !(check_param.testflag & ~(T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX | T_STATISTICS | T_CHECK | T_FAST | T_CHECK_ONLY_CHANGED))) + opt_ignore_control_file= 1; + return; } /* get options */ @@ -1220,8 +1238,11 @@ static int maria_chk(HA_CHECK *param, char *filename) ((param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX | T_ZEROFILL | T_ZEROFILL_KEEP_LSN)) != (T_ZEROFILL | T_ZEROFILL_KEEP_LSN))) + { share->state.create_rename_lsn= share->state.is_of_horizon= share->state.skip_redo_lsn= LSN_NEEDS_NEW_STATE_LSNS; + share->state.create_trid= 0; + } } if (!error && (param->testflag & T_REP_ANY)) { @@ -1508,6 +1529,8 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name) LSN_IN_PARTS(share->state.create_rename_lsn), LSN_IN_PARTS(share->state.is_of_horizon), LSN_IN_PARTS(share->state.skip_redo_lsn)); + printf("create_trid: %s\n", + llstr(share->state.create_trid, llbuff)); } compile_time_assert((MY_UUID_STRING_LENGTH + 1) <= sizeof(buff)); buff[MY_UUID_STRING_LENGTH]= 0; diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index a1275e7ccd2..8c19d0f18f3 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -389,7 +389,7 @@ typedef struct st_maria_share /* End scan */ void (*scan_end)(MARIA_HA *); int (*scan_remember_pos)(MARIA_HA *, MARIA_RECORD_POS*); - void (*scan_restore_pos)(MARIA_HA *, MARIA_RECORD_POS); + int (*scan_restore_pos)(MARIA_HA *, MARIA_RECORD_POS); /* Pre-write of row (some handlers may do the actual write here) */ MARIA_RECORD_POS (*write_record_init)(MARIA_HA *, const uchar *); /* Write record (or accept write_record_init) */ @@ -564,6 +564,7 @@ typedef struct st_maria_block_scan ulonglong bits; uint number_of_rows, bit_pos; MARIA_RECORD_POS row_base_page; + ulonglong row_changes; } MARIA_BLOCK_SCAN; //typedef ICP_RESULT (*index_cond_func_t)(void *param); @@ -606,6 +607,7 @@ struct st_maria_handler int (*read_record)(MARIA_HA *, uchar*, MARIA_RECORD_POS); invalidator_by_filename invalidator; /* query cache invalidator */ ulonglong last_auto_increment; /* auto value at start of statement */ + ulonglong row_changes; /* Incremented for each change */ ulong this_unique; /* uniq filenumber or thread */ ulong last_unique; /* last unique number */ ulong this_loop; /* counter for this open */ @@ -1297,7 +1299,7 @@ my_bool _ma_check_status(void *param); void _ma_restore_status(void *param); void _ma_reset_status(MARIA_HA *maria); int _ma_def_scan_remember_pos(MARIA_HA *info, MARIA_RECORD_POS *lastpos); -void _ma_def_scan_restore_pos(MARIA_HA *info, MARIA_RECORD_POS lastpos); +int _ma_def_scan_restore_pos(MARIA_HA *info, MARIA_RECORD_POS lastpos); #include "ma_commit.h" diff --git a/storage/maria/unittest/ma_test_recovery.expected b/storage/maria/unittest/ma_test_recovery.expected index 6a6051735c5..6aaff86e6cf 100644 --- a/storage/maria/unittest/ma_test_recovery.expected +++ b/storage/maria/unittest/ma_test_recovery.expected @@ -69,8 +69,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -78,8 +78,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -87,8 +87,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -98,8 +98,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -107,8 +107,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -116,8 +116,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -166,8 +166,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -175,8 +175,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -184,8 +184,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -195,8 +195,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -204,8 +204,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -213,8 +213,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -263,8 +263,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -272,8 +272,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -281,8 +281,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -292,8 +292,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -301,8 +301,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -310,8 +310,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -360,8 +360,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -369,8 +369,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -378,8 +378,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -389,8 +389,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -398,8 +398,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -407,8 +407,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -457,8 +457,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -466,8 +466,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -475,8 +475,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -486,8 +486,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -495,8 +495,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -504,8 +504,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -554,8 +554,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -563,8 +563,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -572,8 +572,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -583,8 +583,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -592,8 +592,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -601,8 +601,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -651,8 +651,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -660,8 +660,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -669,8 +669,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -680,8 +680,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -689,8 +689,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -698,8 +698,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -748,8 +748,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -757,8 +757,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -766,8 +766,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -777,8 +777,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -786,8 +786,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -795,8 +795,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -845,8 +845,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -854,8 +854,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -863,8 +863,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -874,8 +874,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -883,8 +883,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -892,8 +892,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -942,8 +942,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -951,8 +951,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -960,8 +960,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -971,8 +971,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -980,8 +980,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -989,8 +989,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1039,8 +1039,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1048,8 +1048,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1057,8 +1057,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1068,8 +1068,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1077,8 +1077,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1086,8 +1086,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1136,8 +1136,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1145,8 +1145,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1154,8 +1154,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1165,8 +1165,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1174,8 +1174,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1183,8 +1183,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1233,8 +1233,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1242,8 +1242,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1251,8 +1251,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1262,8 +1262,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1271,8 +1271,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1280,8 +1280,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1330,8 +1330,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1339,8 +1339,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1348,8 +1348,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1359,8 +1359,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1368,8 +1368,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1377,8 +1377,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1427,8 +1427,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1436,8 +1436,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1445,8 +1445,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1456,8 +1456,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1465,8 +1465,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1474,8 +1474,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1524,8 +1524,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1533,8 +1533,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1542,8 +1542,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1553,8 +1553,8 @@ Dying on request without maria_commit()/maria_close() applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1562,8 +1562,8 @@ testing idempotency applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= @@ -1571,8 +1571,8 @@ testing applying of CLRs to recreate table applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled +7c7 +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable --- > Status: changed ========DIFF END======= diff --git a/storage/myisam/mi_write.c b/storage/myisam/mi_write.c index 60ea7757827..011df5e8eb9 100644 --- a/storage/myisam/mi_write.c +++ b/storage/myisam/mi_write.c @@ -85,9 +85,10 @@ int mi_write(MI_INFO *info, uchar *record) /* Calculate and check all unique constraints */ for (i=0 ; i < share->state.header.uniques ; i++) { - if (mi_check_unique(info,share->uniqueinfo+i,record, - mi_unique_hash(share->uniqueinfo+i,record), - HA_OFFSET_ERROR)) + MI_UNIQUEDEF *def= share->uniqueinfo + i; + if (mi_is_key_active(share->state.key_map, def->key) && + mi_check_unique(info, def, record, mi_unique_hash(def, record), + HA_OFFSET_ERROR)) goto err2; } diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c index 1985a53acf8..74be8b99d87 100644 --- a/storage/myisam/myisampack.c +++ b/storage/myisam/myisampack.c @@ -2144,7 +2144,8 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees) */ if (!(packed_tree=(uint*) my_alloca(sizeof(uint)*length*2))) { - my_error(EE_OUTOFMEMORY,MYF(ME_BELL),sizeof(uint)*length*2); + my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_FATALERROR), + sizeof(uint)*length*2); return 0; } diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index 5d9b5b5808b..481ca41ba9d 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -1460,7 +1460,7 @@ static void split_file_name(const char *file_name, char buff[FN_REFLEN]; db->length= 0; - strmake(buff, file_name, sizeof(buff)-1); + strmake_buf(buff, file_name); dir_length= dirname_length(buff); if (dir_length > 1) { diff --git a/storage/perfschema/pfs_engine_table.cc b/storage/perfschema/pfs_engine_table.cc index 38f6df3003d..2c9951e3f46 100644 --- a/storage/perfschema/pfs_engine_table.cc +++ b/storage/perfschema/pfs_engine_table.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2013, 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 @@ -512,7 +512,7 @@ bool pfs_show_status(handlerton *hton, THD *thd, uint buflen; const char *name; int i; - uint size; + size_t size; DBUG_ENTER("pfs_show_status"); @@ -526,7 +526,7 @@ bool pfs_show_status(handlerton *hton, THD *thd, if (stat != HA_ENGINE_STATUS) DBUG_RETURN(false); - uint total_memory= 0; + size_t total_memory= 0; for (i=0; /* empty */; i++) { @@ -763,7 +763,7 @@ bool pfs_show_status(handlerton *hton, THD *thd, break; } - buflen= int10_to_str(size, buf, 10) - buf; + buflen= longlong10_to_str(size, buf, 10) - buf; if (print(thd, PERFORMANCE_SCHEMA_str.str, PERFORMANCE_SCHEMA_str.length, name, strlen(name), diff --git a/storage/perfschema/pfs_global.cc b/storage/perfschema/pfs_global.cc index fa57f335325..335f57c69c6 100644 --- a/storage/perfschema/pfs_global.cc +++ b/storage/perfschema/pfs_global.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2013, 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 @@ -26,7 +26,7 @@ #include <string.h> bool pfs_initialized= false; -ulonglong pfs_allocated_memory= 0; +size_t pfs_allocated_memory= 0; /** Memory allocation for the performance schema. diff --git a/storage/perfschema/pfs_global.h b/storage/perfschema/pfs_global.h index c0c0490a380..5a3cc342b7d 100644 --- a/storage/perfschema/pfs_global.h +++ b/storage/perfschema/pfs_global.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2013, 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 @@ -22,7 +22,7 @@ */ extern bool pfs_initialized; -extern ulonglong pfs_allocated_memory; +extern size_t pfs_allocated_memory; void *pfs_malloc(size_t size, myf flags); #define PFS_MALLOC_ARRAY(n, T, f) \ diff --git a/storage/sphinx/CMakeLists.txt b/storage/sphinx/CMakeLists.txt index d9320d10cf7..3e26637218f 100644 --- a/storage/sphinx/CMakeLists.txt +++ b/storage/sphinx/CMakeLists.txt @@ -3,3 +3,12 @@ IF(MSVC) LINK_LIBRARIES(ws2_32) ENDIF(MSVC) MYSQL_ADD_PLUGIN(sphinx ha_sphinx.cc STORAGE_ENGINE) + +IF(NOT WITHOUT_SPHINX_STORAGE_ENGINE) + ADD_LIBRARY(snippets_udf MODULE snippets_udf.cc) + TARGET_LINK_LIBRARIES(snippets_udf mysys) # my_error + ADD_DEPENDENCIES(snippets_udf GenError) # uses generated error constants + SET_TARGET_PROPERTIES(snippets_udf PROPERTIES OUTPUT_NAME sphinx PREFIX "") + INSTALL(TARGETS snippets_udf COMPONENT Server DESTINATION ${INSTALL_PLUGINDIR}) +ENDIF() + diff --git a/storage/sphinx/snippets_udf.cc b/storage/sphinx/snippets_udf.cc index 85fb66ab793..5318592ab5f 100644 --- a/storage/sphinx/snippets_udf.cc +++ b/storage/sphinx/snippets_udf.cc @@ -1,5 +1,5 @@ // -// $Id: snippets_udf.cc 3087 2012-01-30 23:07:35Z shodan $ +// $Id: snippets_udf.cc 3508 2012-11-05 11:48:48Z kevg $ // // @@ -17,12 +17,19 @@ #include <string.h> #include <assert.h> +#ifndef __WIN__ #include <sys/un.h> #include <netdb.h> +#else +#include <winsock2.h> +#endif #include <mysql_version.h> -#if MYSQL_VERSION_ID>50100 +#if MYSQL_VERSION_ID>=50515 +#include "sql_class.h" +#include "sql_array.h" +#elif MYSQL_VERSION_ID>50100 #include "mysql_priv.h" #include <mysql/plugin.h> #else @@ -84,9 +91,9 @@ void sphUnalignedWrite ( void * pPtr, const T & tVal ) #define SafeDeleteArray(_arg) { if ( _arg ) delete [] ( _arg ); (_arg) = NULL; } #define Min(a,b) ((a)<(b)?(a):(b)) - +#ifndef __WIN__ typedef unsigned int DWORD; - +#endif inline DWORD sphF2DW ( float f ) { union { float f; uint32 d; } u; u.f = f; return u.d; } static char * sphDup ( const char * sSrc, int iLen=-1 ) @@ -158,7 +165,7 @@ enum SEARCHD_COMMAND_EXCERPT = 1, - VER_COMMAND_EXCERPT = 0x103, + VER_COMMAND_EXCERPT = 0x104, }; /// known answers @@ -380,23 +387,44 @@ int CSphUrl::Connect() else { int tmp_errno; + bool bError = false; + +#if MYSQL_VERSION_ID>=50515 + struct addrinfo *hp = NULL; + tmp_errno = getaddrinfo ( m_sHost, NULL, NULL, &hp ); + if ( !tmp_errno || !hp || !hp->ai_addr ) + { + bError = true; + if ( hp ) + freeaddrinfo ( hp ); + } +#else struct hostent tmp_hostent, *hp; char buff2 [ GETHOSTBYNAME_BUFF_SIZE ]; - hp = my_gethostbyname_r ( m_sHost, &tmp_hostent, buff2, sizeof(buff2), &tmp_errno ); if ( !hp ) { my_gethostbyname_r_free(); + bError = true; + } +#endif + if ( bError ) + { char sError[256]; - snprintf ( sError, sizeof(sError), "failed to resolve searchd host (name=%s)", m_sHost ); + my_snprintf ( sError, sizeof(sError), "failed to resolve searchd host (name=%s)", m_sHost ); my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), sError ); return -1; } +#if MYSQL_VERSION_ID>=50515 + memcpy ( &sin.sin_addr, hp->ai_addr, Min ( sizeof(sin.sin_addr), (size_t)hp->ai_addrlen ) ); + freeaddrinfo ( hp ); +#else memcpy ( &sin.sin_addr, hp->h_addr, Min ( sizeof(sin.sin_addr), (size_t)hp->h_length ) ); my_gethostbyname_r_free(); +#endif } } else { @@ -534,12 +562,16 @@ CSphResponse::Read ( int iSocket, int iClientVersion ) } /// udf - +#ifdef _MSC_VER +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT +#endif extern "C" { - my_bool sphinx_snippets_init ( UDF_INIT * pUDF, UDF_ARGS * pArgs, char * sMessage ); - void sphinx_snippets_deinit ( UDF_INIT * pUDF ); - char * sphinx_snippets ( UDF_INIT * pUDF, UDF_ARGS * pArgs, char * sResult, unsigned long * pLength, char * pIsNull, char * sError ); + DLLEXPORT my_bool sphinx_snippets_init ( UDF_INIT * pUDF, UDF_ARGS * pArgs, char * sMessage ); + DLLEXPORT void sphinx_snippets_deinit ( UDF_INIT * pUDF ); + DLLEXPORT char * sphinx_snippets ( UDF_INIT * pUDF, UDF_ARGS * pArgs, char * sResult, unsigned long * pLength, char * pIsNull, char * sError ); }; #define MAX_MESSAGE_LENGTH 255 @@ -608,7 +640,7 @@ struct CSphSnippets } #define STRING CHECK_TYPE(STRING_RESULT) -#define INT CHECK_TYPE(INT_RESULT); int iValue = *(long long *)pArgs->args[i] +#define INT CHECK_TYPE(INT_RESULT); int iValue =(int) *(long long *)pArgs->args[i] my_bool sphinx_snippets_init ( UDF_INIT * pUDF, UDF_ARGS * pArgs, char * sMessage ) { @@ -662,6 +694,7 @@ my_bool sphinx_snippets_init ( UDF_INIT * pUDF, UDF_ARGS * pArgs, char * sMessag KEYWORD("load_files") { INT; if ( iValue ) pOpts->m_iFlags |= 128; } KEYWORD("allow_empty") { INT; if ( iValue ) pOpts->m_iFlags |= 256; } KEYWORD("emit_zones") { INT; if ( iValue ) pOpts->m_iFlags |= 512; } + KEYWORD("load_files_scattered") { INT; if ( iValue ) pOpts->m_iFlags |= 1024; } else { snprintf ( sMessage, MAX_MESSAGE_LENGTH, "unrecognized argument: %.*s", @@ -787,5 +820,5 @@ void sphinx_snippets_deinit ( UDF_INIT * pUDF ) } // -// $Id: snippets_udf.cc 3087 2012-01-30 23:07:35Z shodan $ +// $Id: snippets_udf.cc 3508 2012-11-05 11:48:48Z kevg $ // diff --git a/storage/xtradb/btr/btr0btr.c b/storage/xtradb/btr/btr0btr.c index a3e57d632a0..79a8eb9dcc6 100644 --- a/storage/xtradb/btr/btr0btr.c +++ b/storage/xtradb/btr/btr0btr.c @@ -688,7 +688,7 @@ btr_root_fseg_validate( { ulint offset = mach_read_from_2(seg_header + FSEG_HDR_OFFSET); - if (UNIV_UNLIKELY(srv_pass_corrupt_table)) { + if (UNIV_UNLIKELY(srv_pass_corrupt_table != 0)) { return (mach_read_from_4(seg_header + FSEG_HDR_SPACE) == space) && (offset >= FIL_PAGE_DATA) && (offset <= UNIV_PAGE_SIZE - FIL_PAGE_DATA_END); @@ -723,17 +723,14 @@ btr_root_block_get( block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, index, mtr); - if (srv_pass_corrupt_table && !block) { - return(0); - } - ut_a(block); + SRV_CORRUPT_TABLE_CHECK(block, return(0);); btr_assert_not_corrupted(block, index); #ifdef UNIV_BTR_DEBUG if (!dict_index_is_ibuf(index)) { const page_t* root = buf_block_get_frame(block); - if (UNIV_UNLIKELY(srv_pass_corrupt_table)) { + if (UNIV_UNLIKELY(srv_pass_corrupt_table != 0)) { if (!btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF + root, space)) @@ -1063,11 +1060,11 @@ btr_get_size( root = btr_root_get(index, mtr); - if (srv_pass_corrupt_table && !root) { + SRV_CORRUPT_TABLE_CHECK(root, + { mtr_commit(mtr); return(0); - } - ut_a(root); + }); if (flag == BTR_N_LEAF_PAGES) { seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; @@ -1525,11 +1522,11 @@ leaf_loop: root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, NULL, &mtr); - if (srv_pass_corrupt_table && !root) { + SRV_CORRUPT_TABLE_CHECK(root, + { mtr_commit(&mtr); return; - } - ut_a(root); + }); #ifdef UNIV_BTR_DEBUG ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF @@ -1555,11 +1552,12 @@ top_loop: root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, NULL, &mtr); - if (srv_pass_corrupt_table && !root) { + SRV_CORRUPT_TABLE_CHECK(root, + { mtr_commit(&mtr); return; - } - ut_a(root); + }); + #ifdef UNIV_BTR_DEBUG ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP + root, space)); @@ -1593,10 +1591,7 @@ btr_free_root( block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, NULL, mtr); - if (srv_pass_corrupt_table && !block) { - return; - } - ut_a(block); + SRV_CORRUPT_TABLE_CHECK(block, return;); btr_search_drop_page_hash_index(block); @@ -4565,10 +4560,11 @@ btr_validate_index( root = btr_root_get(index, &mtr); - if (UNIV_UNLIKELY(srv_pass_corrupt_table && !root)) { + SRV_CORRUPT_TABLE_CHECK(root, + { mtr_commit(&mtr); return(FALSE); - } + }); n = btr_page_get_level(root, &mtr); diff --git a/storage/xtradb/btr/btr0cur.c b/storage/xtradb/btr/btr0cur.c index d089fb5ad22..488212f087c 100644 --- a/storage/xtradb/btr/btr0cur.c +++ b/storage/xtradb/btr/btr0cur.c @@ -258,10 +258,8 @@ btr_cur_latch_leaves( get_block = btr_block_get( space, zip_size, page_no, mode, cursor->index, mtr); - if (srv_pass_corrupt_table && !get_block) { - return; - } - ut_a(get_block); + SRV_CORRUPT_TABLE_CHECK(get_block, return;); + #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); #endif /* UNIV_BTR_DEBUG */ @@ -283,10 +281,8 @@ btr_cur_latch_leaves( space, zip_size, left_page_no, sibling_mode, cursor->index, mtr); - if (srv_pass_corrupt_table && !get_block) { - return; - } - ut_a(get_block); + SRV_CORRUPT_TABLE_CHECK(get_block, return;); + #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); @@ -309,10 +305,8 @@ btr_cur_latch_leaves( space, zip_size, page_no, mode, cursor->index, mtr); - if (srv_pass_corrupt_table && !get_block) { - return; - } - ut_a(get_block); + SRV_CORRUPT_TABLE_CHECK(get_block, return;); + #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); #endif /* UNIV_BTR_DEBUG */ @@ -325,10 +319,8 @@ btr_cur_latch_leaves( space, zip_size, right_page_no, sibling_mode, cursor->index, mtr); - if (srv_pass_corrupt_table && !get_block) { - return; - } - ut_a(get_block); + SRV_CORRUPT_TABLE_CHECK(get_block, return;); + #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); @@ -357,10 +349,8 @@ btr_cur_latch_leaves( left_page_no, mode, cursor->index, mtr); cursor->left_block = get_block; - if (srv_pass_corrupt_table && !get_block) { - return; - } - ut_a(get_block); + SRV_CORRUPT_TABLE_CHECK(get_block, return;); + #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); @@ -373,10 +363,8 @@ btr_cur_latch_leaves( get_block = btr_block_get( space, zip_size, page_no, mode, cursor->index, mtr); - if (srv_pass_corrupt_table && !get_block) { - return; - } - ut_a(get_block); + SRV_CORRUPT_TABLE_CHECK(get_block, return;); + #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); #endif /* UNIV_BTR_DEBUG */ @@ -652,18 +640,19 @@ retry_page_get: file, line, mtr); if (block == NULL) { - if (srv_pass_corrupt_table - && buf_mode != BUF_GET_IF_IN_POOL - && buf_mode != BUF_GET_IF_IN_POOL_OR_WATCH) { - page_cursor->block = 0; - page_cursor->rec = 0; - if (estimate) { - cursor->path_arr->nth_rec = ULINT_UNDEFINED; - } - goto func_exit; - } - ut_a(buf_mode == BUF_GET_IF_IN_POOL - || buf_mode == BUF_GET_IF_IN_POOL_OR_WATCH); + SRV_CORRUPT_TABLE_CHECK(buf_mode == BUF_GET_IF_IN_POOL || + buf_mode == BUF_GET_IF_IN_POOL_OR_WATCH, + { + page_cursor->block = 0; + page_cursor->rec = 0; + if (estimate) { + + cursor->path_arr->nth_rec = + ULINT_UNDEFINED; + } + + goto func_exit; + }); /* This must be a search to perform an insert/delete mark/ delete; try using the insert/delete buffer */ @@ -739,15 +728,18 @@ retry_page_get: block->check_index_page_at_flush = TRUE; page = buf_block_get_frame(block); - if (srv_pass_corrupt_table && !page) { + SRV_CORRUPT_TABLE_CHECK(page, + { page_cursor->block = 0; page_cursor->rec = 0; + if (estimate) { + cursor->path_arr->nth_rec = ULINT_UNDEFINED; } + goto func_exit; - } - ut_a(page); + }); if (rw_latch != RW_NO_LATCH) { #ifdef UNIV_ZIP_DEBUG @@ -943,15 +935,19 @@ btr_cur_open_at_index_side_func( file, line, mtr); page = buf_block_get_frame(block); - if (srv_pass_corrupt_table && !page) { + SRV_CORRUPT_TABLE_CHECK(page, + { page_cursor->block = 0; page_cursor->rec = 0; + if (estimate) { - cursor->path_arr->nth_rec = ULINT_UNDEFINED; + + cursor->path_arr->nth_rec = + ULINT_UNDEFINED; } - break; - } - ut_a(page); + /* Can't use break with the macro */ + goto exit_loop; + }); ut_ad(index->id == btr_page_get_index_id(page)); @@ -1021,6 +1017,7 @@ btr_cur_open_at_index_side_func( page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets); } +exit_loop: if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -1074,12 +1071,13 @@ btr_cur_open_at_rnd_pos_func( file, line, mtr); page = buf_block_get_frame(block); - if (srv_pass_corrupt_table && !page) { + SRV_CORRUPT_TABLE_CHECK(page, + { page_cursor->block = 0; page_cursor->rec = 0; - break; - } - ut_a(page); + + goto exit_loop; + }); ut_ad(index->id == btr_page_get_index_id(page)); @@ -1112,6 +1110,7 @@ btr_cur_open_at_rnd_pos_func( page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets); } +exit_loop: if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -1300,10 +1299,7 @@ btr_cur_optimistic_insert( block = btr_cur_get_block(cursor); - if (srv_pass_corrupt_table && !block) { - return(DB_CORRUPTION); - } - ut_a(block); + SRV_CORRUPT_TABLE_CHECK(block, return(DB_CORRUPTION);); page = buf_block_get_frame(block); index = cursor->index; @@ -3149,10 +3145,7 @@ btr_cur_optimistic_delete( block = btr_cur_get_block(cursor); - if (srv_pass_corrupt_table && !block) { - return(DB_CORRUPTION); - } - ut_a(block); + SRV_CORRUPT_TABLE_CHECK(block, return(DB_CORRUPTION);); ut_ad(page_is_leaf(buf_block_get_frame(block))); @@ -3868,10 +3861,7 @@ btr_estimate_number_of_different_key_vals( page = btr_cur_get_page(&cursor); - if (srv_pass_corrupt_table && !page) { - break; - } - ut_a(page); + SRV_CORRUPT_TABLE_CHECK(page, goto exit_loop;); rec = page_rec_get_next(page_get_infimum_rec(page)); @@ -3957,6 +3947,7 @@ btr_estimate_number_of_different_key_vals( mtr_commit(&mtr); } +exit_loop: /* If we saw k borders between different key values on n_sample_pages leaf pages, we can estimate how many there will be in index->stat_n_leaf_pages */ diff --git a/storage/xtradb/btr/btr0pcur.c b/storage/xtradb/btr/btr0pcur.c index a1b7affdeb7..7c4ec2dd1ac 100644 --- a/storage/xtradb/btr/btr0pcur.c +++ b/storage/xtradb/btr/btr0pcur.c @@ -116,10 +116,7 @@ btr_pcur_store_position( block = btr_pcur_get_block(cursor); - if (srv_pass_corrupt_table && !block) { - return; - } - ut_a(block); + SRV_CORRUPT_TABLE_CHECK(block, return;); index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor)); @@ -439,14 +436,16 @@ btr_pcur_move_to_next_page( btr_pcur_get_btr_cur(cursor)->index, mtr); next_page = buf_block_get_frame(next_block); - if (srv_pass_corrupt_table && !next_page) { + SRV_CORRUPT_TABLE_CHECK(next_page, + { btr_leaf_page_release(btr_pcur_get_block(cursor), cursor->latch_mode, mtr); btr_pcur_get_page_cur(cursor)->block = 0; btr_pcur_get_page_cur(cursor)->rec = 0; + return; - } - ut_a(next_page); + }); + #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(next_page) == page_is_comp(page)); ut_a(btr_page_get_prev(next_page, mtr) diff --git a/storage/xtradb/btr/btr0sea.c b/storage/xtradb/btr/btr0sea.c index 7e9449a6474..d53452bb959 100644 --- a/storage/xtradb/btr/btr0sea.c +++ b/storage/xtradb/btr/btr0sea.c @@ -649,10 +649,7 @@ btr_search_info_update_slow( block = btr_cur_get_block(cursor); - if (srv_pass_corrupt_table && !block) { - return; - } - ut_a(block); + SRV_CORRUPT_TABLE_CHECK(block, return;); /* NOTE that the following two function calls do NOT protect info or block->n_fields etc. with any semaphore, to save CPU time! diff --git a/storage/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c index 5bcfb0f51b9..ae4b2fba98d 100644 --- a/storage/xtradb/buf/buf0buf.c +++ b/storage/xtradb/buf/buf0buf.c @@ -2002,27 +2002,6 @@ lookup: #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ } - if (UNIV_UNLIKELY(bpage->space_was_being_deleted)) { - /* This page is obsoleted, should discard and retry */ - rw_lock_s_unlock(&buf_pool->page_hash_latch); - - mutex_enter(&buf_pool->LRU_list_mutex); - block_mutex = buf_page_get_mutex_enter(bpage); - - if (UNIV_UNLIKELY(!block_mutex)) { - mutex_exit(&buf_pool->LRU_list_mutex); - goto lookup; - } - - buf_LRU_free_block(bpage, TRUE, TRUE); - - mutex_exit(&buf_pool->LRU_list_mutex); - mutex_exit(block_mutex); - block_mutex = NULL; - - goto lookup; - } - if (UNIV_UNLIKELY(!bpage->zip.data)) { /* There is no compressed page. */ err_exit: @@ -2031,11 +2010,11 @@ err_exit: return(NULL); } - if (srv_pass_corrupt_table <= 1) { - if (bpage->is_corrupt) { - rw_lock_s_unlock(&buf_pool->page_hash_latch); - return(NULL); - } + if (UNIV_UNLIKELY(bpage->is_corrupt && srv_pass_corrupt_table <= 1)) { + + rw_lock_s_unlock(&buf_pool->page_hash_latch); + + return(NULL); } block_mutex = buf_page_get_mutex_enter(bpage); @@ -2533,26 +2512,6 @@ loop: block = (buf_block_t*) buf_page_hash_get_low( buf_pool, space, offset, fold); if (block) { - if (UNIV_UNLIKELY(block->page.space_was_being_deleted)) { - /* This page is obsoleted, should discard and retry */ - rw_lock_s_unlock(&buf_pool->page_hash_latch); - - mutex_enter(&buf_pool->LRU_list_mutex); - block_mutex = buf_page_get_mutex_enter((buf_page_t*)block); - - if (UNIV_UNLIKELY(!block_mutex)) { - mutex_exit(&buf_pool->LRU_list_mutex); - goto loop; - } - - buf_LRU_free_block((buf_page_t*)block, TRUE, TRUE); - - mutex_exit(&buf_pool->LRU_list_mutex); - mutex_exit(block_mutex); - block_mutex = NULL; - - goto loop; - } block_mutex = buf_page_get_mutex_enter((buf_page_t*)block); ut_a(block_mutex); @@ -2640,11 +2599,12 @@ got_block: return(NULL); } - if (srv_pass_corrupt_table <= 1) { - if (block->page.is_corrupt) { - mutex_exit(block_mutex); - return(NULL); - } + if (UNIV_UNLIKELY(block->page.is_corrupt && + srv_pass_corrupt_table <= 1)) { + + mutex_exit(block_mutex); + + return(NULL); } switch (buf_block_get_state(block)) { @@ -3487,28 +3447,12 @@ buf_page_init_for_read( fold = buf_page_address_fold(space, offset); -retry: //buf_pool_mutex_enter(buf_pool); mutex_enter(&buf_pool->LRU_list_mutex); rw_lock_x_lock(&buf_pool->page_hash_latch); watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold); - if (UNIV_UNLIKELY(watch_page && watch_page->space_was_being_deleted)) { - mutex_t* block_mutex = buf_page_get_mutex_enter(watch_page); - - /* This page is obsoleted, should discard and retry */ - rw_lock_x_unlock(&buf_pool->page_hash_latch); - ut_a(block_mutex); - - buf_LRU_free_block(watch_page, TRUE, TRUE); - - mutex_exit(&buf_pool->LRU_list_mutex); - mutex_exit(block_mutex); - - goto retry; - } - if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) { /* The page is already in the buffer pool. */ watch_page = NULL; @@ -3637,7 +3581,6 @@ err_exit: bpage->state = BUF_BLOCK_ZIP_PAGE; bpage->space = space; bpage->offset = offset; - bpage->space_was_being_deleted = FALSE; #ifdef UNIV_DEBUG bpage->in_page_hash = FALSE; @@ -3722,7 +3665,6 @@ buf_page_create( fold = buf_page_address_fold(space, offset); -retry: //buf_pool_mutex_enter(buf_pool); mutex_enter(&buf_pool->LRU_list_mutex); rw_lock_x_lock(&buf_pool->page_hash_latch); @@ -3730,21 +3672,6 @@ retry: block = (buf_block_t*) buf_page_hash_get_low( buf_pool, space, offset, fold); - if (UNIV_UNLIKELY(block && block->page.space_was_being_deleted)) { - mutex_t* block_mutex = buf_page_get_mutex_enter((buf_page_t*)block); - - /* This page is obsoleted, should discard and retry */ - rw_lock_x_unlock(&buf_pool->page_hash_latch); - ut_a(block_mutex); - - buf_LRU_free_block((buf_page_t*)block, TRUE, TRUE); - - mutex_exit(&buf_pool->LRU_list_mutex); - mutex_exit(block_mutex); - - goto retry; - } - if (block && buf_page_in_file(&block->page) && !buf_pool_watch_is_sentinel(buf_pool, &block->page)) { @@ -4001,7 +3928,8 @@ buf_page_io_complete( (ulong) bpage->offset); } - if (!srv_pass_corrupt_table || !bpage->is_corrupt) { + if (UNIV_LIKELY(!bpage->is_corrupt || + !srv_pass_corrupt_table)) { /* From version 3.23.38 up we store the page checksum to the 4 first bytes of the page end lsn field */ @@ -4086,13 +4014,26 @@ corrupt: } if (uncompressed && !recv_no_ibuf_operations) { + + buf_block_t* block; + ibool update_ibuf_bitmap; + + if (UNIV_UNLIKELY(bpage->is_corrupt && + srv_pass_corrupt_table)) { + + block = NULL; + update_ibuf_bitmap = FALSE; + + } else { + + block = (buf_block_t *) bpage; + update_ibuf_bitmap = TRUE; + } + ibuf_merge_or_delete_for_page( - /* Delete possible entries, if bpage is_corrupt */ - (srv_pass_corrupt_table && bpage->is_corrupt) ? NULL : - (buf_block_t*) bpage, bpage->space, + block, bpage->space, bpage->offset, buf_page_get_zip_size(bpage), - (srv_pass_corrupt_table && bpage->is_corrupt) ? FALSE : - TRUE); + update_ibuf_bitmap); } } diff --git a/storage/xtradb/buf/buf0flu.c b/storage/xtradb/buf/buf0flu.c index 663e2d8f537..9452b53df38 100644 --- a/storage/xtradb/buf/buf0flu.c +++ b/storage/xtradb/buf/buf0flu.c @@ -459,7 +459,7 @@ buf_flush_ready_for_replace( if (UNIV_LIKELY(bpage->in_LRU_list && buf_page_in_file(bpage))) { - return((bpage->oldest_modification == 0 || bpage->space_was_being_deleted) + return(bpage->oldest_modification == 0 && buf_page_get_io_fix(bpage) == BUF_IO_NONE && bpage->buf_fix_count == 0); } @@ -501,13 +501,6 @@ buf_flush_ready_for_flush( && buf_page_get_io_fix(bpage) == BUF_IO_NONE) { ut_ad(bpage->in_flush_list); - if (bpage->space_was_being_deleted) { - /* should be removed from flush_list here */ - /* because buf_flush_try_neighbors() cannot flush without fil_space_get_size(space) */ - buf_flush_remove(bpage); - return(FALSE); - } - if (flush_type != BUF_FLUSH_LRU) { return(TRUE); diff --git a/storage/xtradb/buf/buf0lru.c b/storage/xtradb/buf/buf0lru.c index cd99d3e4e13..8a35c87c92f 100644 --- a/storage/xtradb/buf/buf0lru.c +++ b/storage/xtradb/buf/buf0lru.c @@ -884,42 +884,6 @@ buf_LRU_flush_or_remove_pages( } } -/******************************************************************//** -*/ -UNIV_INTERN -void -buf_LRU_mark_space_was_deleted( -/*===========================*/ - ulint id) /*!< in: space id */ -{ - ulint i; - - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - buf_page_t* bpage; - - buf_pool = buf_pool_from_array(i); - - mutex_enter(&buf_pool->LRU_list_mutex); - - bpage = UT_LIST_GET_FIRST(buf_pool->LRU); - - while (bpage != NULL) { - if (buf_page_get_space(bpage) == id) { - bpage->space_was_being_deleted = TRUE; - } - bpage = UT_LIST_GET_NEXT(LRU, bpage); - } - - mutex_exit(&buf_pool->LRU_list_mutex); - - /* The AHI entries for the tablespace being deleted should be - removed by now. */ - ut_ad(buf_LRU_drop_page_hash_for_tablespace(buf_pool, id) - == 0); - } -} - #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /********************************************************************//** Insert a compressed block into buf_pool->zip_clean in the LRU order. */ @@ -1891,10 +1855,6 @@ buf_LRU_free_block( return(FALSE); } - if (bpage->space_was_being_deleted && bpage->oldest_modification != 0) { - buf_flush_remove(bpage); - } - #ifdef UNIV_IBUF_COUNT_DEBUG ut_a(ibuf_count_get(bpage->space, bpage->offset) == 0); #endif /* UNIV_IBUF_COUNT_DEBUG */ diff --git a/storage/xtradb/buf/buf0rea.c b/storage/xtradb/buf/buf0rea.c index cf0a029df92..5edbeadb64e 100644 --- a/storage/xtradb/buf/buf0rea.c +++ b/storage/xtradb/buf/buf0rea.c @@ -245,13 +245,7 @@ not_to_recover: return(0); } - if (srv_pass_corrupt_table) { - if (*err != DB_SUCCESS) { - bpage->is_corrupt = TRUE; - } - } else { - ut_a(*err == DB_SUCCESS); - } + SRV_CORRUPT_TABLE_CHECK(*err == DB_SUCCESS, bpage->is_corrupt = TRUE;); if (sync) { /* The i/o is already completed when we arrive from diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c index 29063f028f1..817da6e6074 100644 --- a/storage/xtradb/dict/dict0dict.c +++ b/storage/xtradb/dict/dict0dict.c @@ -4419,7 +4419,7 @@ dict_reload_statistics( while (index) { mtr_t mtr; - if (table->is_corrupt) { + if (UNIV_UNLIKELY(table->is_corrupt)) { ut_a(srv_pass_corrupt_table); mem_heap_free(heap); return(FALSE); @@ -4577,7 +4577,7 @@ dict_store_statistics( heap = mem_heap_create(1000); while (index) { - if (table->is_corrupt) { + if (UNIV_UNLIKELY(table->is_corrupt)) { ut_a(srv_pass_corrupt_table); mem_heap_free(heap); return; @@ -4771,7 +4771,7 @@ dict_update_statistics( mtr_t mtr; ulint size; - if (table->is_corrupt) { + if (UNIV_UNLIKELY(table->is_corrupt)) { ut_a(srv_pass_corrupt_table); dict_table_stats_unlock(table, RW_X_LATCH); return; diff --git a/storage/xtradb/fil/fil0fil.c b/storage/xtradb/fil/fil0fil.c index 397c4de4b6e..ff4e5b1b033 100644 --- a/storage/xtradb/fil/fil0fil.c +++ b/storage/xtradb/fil/fil0fil.c @@ -2426,15 +2426,11 @@ try_again: To deal with potential read requests by checking the ::stop_new_ops flag in fil_io() */ - if (srv_lazy_drop_table) { - buf_LRU_mark_space_was_deleted(id); - } else { buf_LRU_flush_or_remove_pages( id, evict_all ? BUF_REMOVE_ALL_NO_WRITE : BUF_REMOVE_FLUSH_NO_WRITE); - } #endif /* printf("Deleting tablespace %s id %lu\n", space->name, id); */ @@ -5326,22 +5322,6 @@ _fil_io( srv_data_written+= len; } - /* if the table space was already deleted, space might not exist already. */ - if (message - && space_id < SRV_LOG_SPACE_FIRST_ID - && ((buf_page_t*)message)->space_was_being_deleted) { - - if (mode == OS_AIO_NORMAL) { - buf_page_io_complete(message); - return(DB_SUCCESS); /*fake*/ - } - if (type == OS_FILE_READ) { - return(DB_TABLESPACE_DELETED); - } else { - return(DB_SUCCESS); /*fake*/ - } - } - /* Reserve the fil_system mutex and make sure that we can open at least one file while holding it, if the file is not already open */ @@ -5445,35 +5425,38 @@ _fil_io( ut_a(byte_offset % OS_MIN_LOG_BLOCK_SIZE == 0); ut_a((len % OS_MIN_LOG_BLOCK_SIZE) == 0); - if (srv_pass_corrupt_table == 1 && space->is_corrupt) { +#ifndef UNIV_HOTBACKUP + if (UNIV_UNLIKELY(space->is_corrupt && srv_pass_corrupt_table)) { + /* should ignore i/o for the crashed space */ - mutex_enter(&fil_system->mutex); - fil_node_complete_io(node, fil_system, type); - mutex_exit(&fil_system->mutex); - if (mode == OS_AIO_NORMAL) { - ut_a(space->purpose == FIL_TABLESPACE); - buf_page_io_complete(message); + if (srv_pass_corrupt_table == 1 || + type == OS_FILE_WRITE) { + + mutex_enter(&fil_system->mutex); + fil_node_complete_io(node, fil_system, type); + mutex_exit(&fil_system->mutex); + if (mode == OS_AIO_NORMAL) { + ut_a(space->purpose == FIL_TABLESPACE); + buf_page_io_complete(message); + } } - if (type == OS_FILE_READ) { + + if (srv_pass_corrupt_table == 1 && type == OS_FILE_READ) { + return(DB_TABLESPACE_DELETED); - } else { + + } else if (type == OS_FILE_WRITE) { + return(DB_SUCCESS); } - } else { - if (srv_pass_corrupt_table > 1 && space->is_corrupt) { - /* should ignore write i/o for the crashed space */ - if (type == OS_FILE_WRITE) { - mutex_enter(&fil_system->mutex); - fil_node_complete_io(node, fil_system, type); - mutex_exit(&fil_system->mutex); - if (mode == OS_AIO_NORMAL) { - ut_a(space->purpose == FIL_TABLESPACE); - buf_page_io_complete(message); - } - return(DB_SUCCESS); - } - } -#ifdef UNIV_HOTBACKUP + } /**/ + + /* Queue the aio request */ + ret = os_aio(type, mode | wake_later, node->name, node->handle, buf, + offset_low, offset_high, len, node, message, space_id, + trx); + +#else /* In ibbackup do normal i/o, not aio */ if (type == OS_FILE_READ) { ret = os_file_read(node->handle, buf, offset_low, offset_high, @@ -5482,26 +5465,7 @@ _fil_io( ret = os_file_write(node->name, node->handle, buf, offset_low, offset_high, len); } -#else - /* Queue the aio request */ - ret = os_aio(type, mode | wake_later, node->name, node->handle, buf, - offset_low, offset_high, len, node, message, space_id, trx); #endif - } /**/ - - /* if the table space was already deleted, space might not exist already. */ - if (message - && space_id < SRV_LOG_SPACE_FIRST_ID - && ((buf_page_t*)message)->space_was_being_deleted) { - - if (mode == OS_AIO_SYNC) { - if (type == OS_FILE_READ) { - return(DB_TABLESPACE_DELETED); - } else { - return(DB_SUCCESS); /*fake*/ - } - } - } ut_a(ret); @@ -5625,21 +5589,6 @@ fil_aio_wait( &message, &type, &space_id); } - /* if the table space was already deleted, fil_node might not exist already. */ - if (message - && space_id < SRV_LOG_SPACE_FIRST_ID - && ((buf_page_t*)message)->space_was_being_deleted) { - - /* intended not to be uncompress read page */ - ut_a(buf_page_get_io_fix_unlocked(message) == BUF_IO_WRITE - || !buf_page_get_zip_size(message) - || buf_page_get_state(message) != BUF_BLOCK_FILE_PAGE); - - srv_set_io_thread_op_info(segment, "complete io for buf page"); - buf_page_io_complete(message); - return; - } - ut_a(ret); if (UNIV_UNLIKELY(fil_node == NULL)) { ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS); diff --git a/storage/xtradb/fsp/fsp0fsp.c b/storage/xtradb/fsp/fsp0fsp.c index 5cbc74b0862..d5717638f29 100644 --- a/storage/xtradb/fsp/fsp0fsp.c +++ b/storage/xtradb/fsp/fsp0fsp.c @@ -317,10 +317,7 @@ fsp_get_space_header( block = buf_page_get(id, zip_size, 0, RW_X_LATCH, mtr); - if (srv_pass_corrupt_table && !block) { - return(0); - } - ut_a(block); + SRV_CORRUPT_TABLE_CHECK(block, return(0);); header = FSP_HEADER_OFFSET + buf_block_get_frame(block); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); @@ -728,10 +725,7 @@ xdes_get_descriptor( block = buf_page_get(space, zip_size, 0, RW_X_LATCH, mtr); - if (srv_pass_corrupt_table && !block) { - return(0); - } - ut_a(block); + SRV_CORRUPT_TABLE_CHECK(block, return(0);); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); @@ -1879,10 +1873,7 @@ fsp_seg_inode_page_find_free( { fseg_inode_t* inode; - if (srv_pass_corrupt_table && !page) { - return(ULINT_UNDEFINED); - } - ut_a(page); + SRV_CORRUPT_TABLE_CHECK(page, return(ULINT_UNDEFINED);); for (; i < FSP_SEG_INODES_PER_PAGE(zip_size); i++) { @@ -1996,10 +1987,7 @@ fsp_alloc_seg_inode( page = buf_block_get_frame(block); - if (srv_pass_corrupt_table && !page) { - return(0); - } - ut_a(page); + SRV_CORRUPT_TABLE_CHECK(page, return(0);); n = fsp_seg_inode_page_find_free(page, 0, zip_size, mtr); @@ -2094,10 +2082,7 @@ fseg_inode_try_get( inode = fut_get_ptr(space, zip_size, inode_addr, RW_X_LATCH, mtr); - if (srv_pass_corrupt_table && !inode) { - return(0); - } - ut_a(inode); + SRV_CORRUPT_TABLE_CHECK(inode, return(0);); if (UNIV_UNLIKELY(!mach_read_from_8(inode + FSEG_ID))) { @@ -2125,7 +2110,7 @@ fseg_inode_get( { fseg_inode_t* inode = fseg_inode_try_get(header, space, zip_size, mtr); - ut_a(srv_pass_corrupt_table || inode); + SRV_CORRUPT_TABLE_CHECK(inode, ; /* do nothing */); return(inode); } @@ -3317,12 +3302,12 @@ fseg_free_page_low( descr = xdes_get_descriptor(space, zip_size, page, mtr); - if (srv_pass_corrupt_table && !descr) { + SRV_CORRUPT_TABLE_CHECK(descr, + { /* The page may be corrupt. pass it. */ return; - } + }); - ut_a(descr); if (xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)) { fputs("InnoDB: Dump of the tablespace extent descriptor: ", stderr); @@ -3571,15 +3556,15 @@ fseg_free_step( descr = xdes_get_descriptor(space, zip_size, header_page, mtr); - if (srv_pass_corrupt_table && !descr) { + SRV_CORRUPT_TABLE_CHECK(descr, + { /* The page may be corrupt. pass it. */ return(TRUE); - } + }); /* Check that the header resides on a page which has not been freed yet */ - ut_a(descr); ut_a(xdes_get_bit(descr, XDES_FREE_BIT, header_page % FSP_EXTENT_SIZE, mtr) == FALSE); inode = fseg_inode_try_get(header, space, zip_size, mtr); @@ -3660,11 +3645,11 @@ fseg_free_step_not_header( inode = fseg_inode_get(header, space, zip_size, mtr); - if (srv_pass_corrupt_table && !inode) { + SRV_CORRUPT_TABLE_CHECK(inode, + { /* ignore the corruption */ return(TRUE); - } - ut_a(inode); + }); descr = fseg_get_first_extent(inode, space, zip_size, mtr); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index a25a3b8679f..f7507a04412 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -204,6 +204,8 @@ static ulong innobase_sys_stats_root_page = 0; #endif static my_bool innobase_buffer_pool_shm_checksum = TRUE; static uint innobase_buffer_pool_shm_key = 0; +static ulint srv_lazy_drop_table = 0; + static char* internal_innobase_data_file_path = NULL; @@ -1896,7 +1898,7 @@ trx_is_started( /*===========*/ trx_t* trx) /* in: transaction */ { - return(trx->conc_state != TRX_NOT_STARTED); + return(trx->state != TRX_NOT_STARTED); } /*********************************************************************//** @@ -3016,6 +3018,12 @@ innobase_change_buffering_inited_ok: "InnoDB: innodb_buffer_pool_shm_key was ignored.\n"); } + if (srv_lazy_drop_table) { + fprintf(stderr, + "InnoDB: Warning: " + "innodb_lazy_drop_table is deprecated and ignored.\n"); + } + srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size; srv_n_file_io_threads = (ulint) innobase_file_io_threads; @@ -4725,7 +4733,8 @@ ha_innobase::open( DBUG_RETURN(1); } - if (srv_pass_corrupt_table <= 1 && share->ib_table && share->ib_table->is_corrupt) { + if (UNIV_UNLIKELY(share->ib_table && share->ib_table->is_corrupt && + srv_pass_corrupt_table <= 1)) { free_share(share); DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); @@ -4750,7 +4759,8 @@ retry: /* Get pointer to a table object in InnoDB dictionary cache */ ib_table = dict_table_get(norm_name, TRUE); - if (srv_pass_corrupt_table <= 1 && ib_table && ib_table->is_corrupt) { + if (UNIV_UNLIKELY(ib_table && ib_table->is_corrupt && + srv_pass_corrupt_table <= 1)) { free_share(share); my_free(upd_buf); upd_buf = NULL; @@ -7037,7 +7047,8 @@ ha_innobase::index_read( ha_statistic_increment(&SSV::ha_read_key_count); - if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) { + if (UNIV_UNLIKELY(share->ib_table->is_corrupt && + srv_pass_corrupt_table <= 1)) { DBUG_RETURN(HA_ERR_CRASHED); } @@ -7108,7 +7119,8 @@ ha_innobase::index_read( ret = DB_UNSUPPORTED; } - if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) { + if (UNIV_UNLIKELY(share->ib_table->is_corrupt && + srv_pass_corrupt_table <= 1)) { DBUG_RETURN(HA_ERR_CRASHED); } @@ -7226,7 +7238,8 @@ ha_innobase::change_active_index( { DBUG_ENTER("change_active_index"); - if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) { + if (UNIV_UNLIKELY(share->ib_table->is_corrupt && + srv_pass_corrupt_table <= 1)) { DBUG_RETURN(HA_ERR_CRASHED); } @@ -7344,7 +7357,8 @@ ha_innobase::general_fetch( DBUG_ENTER("general_fetch"); - if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) { + if (UNIV_UNLIKELY(share->ib_table->is_corrupt && + srv_pass_corrupt_table <= 1)) { DBUG_RETURN(HA_ERR_CRASHED); } @@ -7357,7 +7371,8 @@ ha_innobase::general_fetch( innodb_srv_conc_exit_innodb(prebuilt->trx); - if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) { + if (UNIV_UNLIKELY(share->ib_table->is_corrupt && + srv_pass_corrupt_table <= 1)) { DBUG_RETURN(HA_ERR_CRASHED); } @@ -9390,7 +9405,7 @@ ha_innobase::info_low( prebuilt->trx->op_info = "confirming rows of SYS_STATS to store statistics"; - ut_a(prebuilt->trx->conc_state == TRX_NOT_STARTED); + ut_a(!trx_is_started(prebuilt->trx)); for (index = dict_table_get_first_index(ib_table); index != NULL; @@ -9403,7 +9418,7 @@ ha_innobase::info_low( innobase_commit_low(prebuilt->trx); } - ut_a(prebuilt->trx->conc_state == TRX_NOT_STARTED); + ut_a(!trx_is_started(prebuilt->trx)); } prebuilt->trx->op_info = "updating table statistics"; @@ -13428,8 +13443,7 @@ static MYSQL_SYSVAR_ENUM(corrupt_table_action, srv_pass_corrupt_table, static MYSQL_SYSVAR_ULINT(lazy_drop_table, srv_lazy_drop_table, PLUGIN_VAR_RQCMDARG, - "At deleting tablespace, only miminum needed processes at the time are done. " - "e.g. for http://bugs.mysql.com/51325", + "[Deprecated option] no effect", NULL, NULL, 0, 0, 1, 0); static MYSQL_SYSVAR_BOOL(locking_fake_changes, srv_fake_changes_locks, diff --git a/storage/xtradb/include/btr0btr.ic b/storage/xtradb/include/btr0btr.ic index 53c8159c448..798107628d7 100644 --- a/storage/xtradb/include/btr0btr.ic +++ b/storage/xtradb/include/btr0btr.ic @@ -59,7 +59,7 @@ btr_block_get_func( block = buf_page_get_gen(space, zip_size, page_no, mode, NULL, BUF_GET, file, line, mtr); - ut_a(srv_pass_corrupt_table || block); + SRV_CORRUPT_TABLE_CHECK(block, ; /* do nothing */); if (block && mode != RW_NO_LATCH) { diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h index e0d7a974fc3..f00a06c8805 100644 --- a/storage/xtradb/include/buf0buf.h +++ b/storage/xtradb/include/buf0buf.h @@ -1589,7 +1589,6 @@ struct buf_page_struct{ 0 if the block was never accessed in the buffer pool. Protected by block mutex */ - ibool space_was_being_deleted; ibool is_corrupt; # if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG ibool file_page_was_freed; diff --git a/storage/xtradb/include/buf0buf.ic b/storage/xtradb/include/buf0buf.ic index 8d5c3edeef8..18c46b6412e 100644 --- a/storage/xtradb/include/buf0buf.ic +++ b/storage/xtradb/include/buf0buf.ic @@ -430,7 +430,6 @@ buf_block_set_file_page( buf_block_set_state(block, BUF_BLOCK_FILE_PAGE); block->page.space = space; block->page.offset = page_no; - block->page.space_was_being_deleted = FALSE; } /*********************************************************************//** @@ -712,13 +711,7 @@ buf_block_get_frame( /*================*/ const buf_block_t* block) /*!< in: pointer to the control block */ { - ut_a(srv_pass_corrupt_table || block); - - if (srv_pass_corrupt_table && !block) { - return(0); - } - - ut_ad(block); + SRV_CORRUPT_TABLE_CHECK(block, return(0);); switch (buf_block_get_state(block)) { case BUF_BLOCK_ZIP_FREE: diff --git a/storage/xtradb/include/buf0flu.ic b/storage/xtradb/include/buf0flu.ic index 30e2cc8efe8..8228c025d23 100644 --- a/storage/xtradb/include/buf0flu.ic +++ b/storage/xtradb/include/buf0flu.ic @@ -70,7 +70,7 @@ buf_flush_note_modification( ut_ad(!buf_pool_mutex_own(buf_pool)); ut_ad(!buf_flush_list_mutex_own(buf_pool)); - ut_ad(log_flush_order_mutex_own()); + ut_ad(!mtr->made_dirty || log_flush_order_mutex_own()); ut_ad(mtr->start_lsn != 0); ut_ad(mtr->modifications); diff --git a/storage/xtradb/include/buf0lru.h b/storage/xtradb/include/buf0lru.h index 2ea4f9b1ecf..8bb3aed4059 100644 --- a/storage/xtradb/include/buf0lru.h +++ b/storage/xtradb/include/buf0lru.h @@ -73,13 +73,6 @@ buf_LRU_flush_or_remove_pages( enum buf_remove_t buf_remove);/*!< in: remove or flush strategy */ -/******************************************************************//** -*/ -UNIV_INTERN -void -buf_LRU_mark_space_was_deleted( -/*===========================*/ - ulint id); /*!< in: space id */ #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /********************************************************************//** Insert a compressed block into buf_pool->zip_clean in the LRU order. */ diff --git a/storage/xtradb/include/fut0fut.ic b/storage/xtradb/include/fut0fut.ic index 529f2a516d3..63e5736d99e 100644 --- a/storage/xtradb/include/fut0fut.ic +++ b/storage/xtradb/include/fut0fut.ic @@ -50,10 +50,7 @@ fut_get_ptr( block = buf_page_get(space, zip_size, addr.page, rw_latch, mtr); - if (srv_pass_corrupt_table && !block) { - return(0); - } - ut_a(block); + SRV_CORRUPT_TABLE_CHECK(block, return(0);); ptr = buf_block_get_frame(block) + addr.boffset; diff --git a/storage/xtradb/include/log0log.h b/storage/xtradb/include/log0log.h index 4f017e01dfd..59dfb457d56 100644 --- a/storage/xtradb/include/log0log.h +++ b/storage/xtradb/include/log0log.h @@ -122,14 +122,22 @@ UNIV_INLINE void log_free_check(void); /*================*/ +/**************************************************************************//** +Locks the log mutex and opens the log for log_write_low. The log must be closed +with log_close and released with log_release. +@return start lsn of the log record */ +UNIV_INLINE +ib_uint64_t +log_reserve_and_open( +/*=================*/ + ulint len); /*!< in: length of data to be catenated */ /************************************************************//** -Opens the log for log_write_low. The log must be closed with log_close and -released with log_release. +Opens the log for log_write_low. The log must be closed with log_close. @return start lsn of the log record */ UNIV_INTERN ib_uint64_t -log_reserve_and_open( -/*=================*/ +log_open( +/*=====*/ ulint len); /*!< in: length of data to be catenated */ /************************************************************//** Writes to the log the string given. It is assumed that the caller holds the diff --git a/storage/xtradb/include/log0log.ic b/storage/xtradb/include/log0log.ic index b54697637b0..5b864f3d7d4 100644 --- a/storage/xtradb/include/log0log.ic +++ b/storage/xtradb/include/log0log.ic @@ -332,10 +332,10 @@ log_reserve_and_write_fast( if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) { - /* The string does not fit within the current log block - or the log block would become full */ - - mutex_exit(&log_sys->mutex); + /* The string does not fit within the current log block or the + log block would become full. Do not release the log mutex, + because it has to be reacquired immediately for the "slow" write + procedure via log_write_low(). */ return(0); } @@ -382,6 +382,21 @@ log_reserve_and_write_fast( return(log_sys->lsn); } +/**************************************************************************//** +Locks the log mutex and opens the log for log_write_low. The log must be closed +with log_close and released with log_release. +@return start lsn of the log record */ +UNIV_INLINE +ib_uint64_t +log_reserve_and_open( +/*=================*/ + ulint len) /*!< in: length of data to be catenated */ +{ + mutex_enter(&(log_sys->mutex)); + + return log_open(len); +} + /***********************************************************************//** Releases the log mutex. */ UNIV_INLINE diff --git a/storage/xtradb/include/mtr0mtr.h b/storage/xtradb/include/mtr0mtr.h index 46f1ff9310c..c51632e0ed5 100644 --- a/storage/xtradb/include/mtr0mtr.h +++ b/storage/xtradb/include/mtr0mtr.h @@ -375,6 +375,8 @@ struct mtr_struct{ ibool modifications; /* TRUE if the mtr made modifications to buffer pool pages */ + ibool made_dirty;/*!< TRUE if mtr has made at least + one buffer pool page dirty */ ulint n_log_recs; /* count of how many page initial log records have been written to the mtr log */ diff --git a/storage/xtradb/include/mtr0mtr.ic b/storage/xtradb/include/mtr0mtr.ic index a03a0271535..7b5d268b70f 100644 --- a/storage/xtradb/include/mtr0mtr.ic +++ b/storage/xtradb/include/mtr0mtr.ic @@ -29,6 +29,17 @@ Created 11/26/1995 Heikki Tuuri #endif /* !UNIV_HOTBACKUP */ #include "mach0data.h" +/***************************************************//** +Checks if a mini-transaction is dirtying a clean page. +@return TRUE if the mtr is dirtying a clean page. */ +UNIV_INTERN +ibool +mtr_block_dirtied( +/*==============*/ + const buf_block_t* block) /*!< in: block being x-fixed */ + __attribute__((nonnull,warn_unused_result)); + + /***************************************************************//** Starts a mini-transaction. */ UNIV_INLINE @@ -47,6 +58,7 @@ mtr_start( mtr->inside_ibuf = FALSE; mtr->n_log_recs = 0; mtr->n_freed_pages = 0; + mtr->made_dirty = FALSE; ut_d(mtr->state = MTR_ACTIVE); ut_d(mtr->magic_n = MTR_MAGIC_N); @@ -65,6 +77,15 @@ mtr_memo_push( dyn_array_t* memo; mtr_memo_slot_t* slot; + /* If this mtr has x-fixed a clean page then we set + the made_dirty flag. This tells us if we need to + grab log_flush_order_mutex at mtr_commit so that we + can insert the dirtied page to the flush list. */ + if (type == MTR_MEMO_PAGE_X_FIX && !mtr->made_dirty) { + mtr->made_dirty = + mtr_block_dirtied((const buf_block_t *)object); + } + ut_ad(object); ut_ad(type >= MTR_MEMO_PAGE_S_FIX); ut_ad(type <= MTR_MEMO_X_LOCK); diff --git a/storage/xtradb/include/read0read.h b/storage/xtradb/include/read0read.h index 0c9468d985e..dd378ecc997 100644 --- a/storage/xtradb/include/read0read.h +++ b/storage/xtradb/include/read0read.h @@ -32,6 +32,7 @@ Created 2/16/1997 Heikki Tuuri #include "ut0byte.h" #include "ut0lst.h" #include "trx0trx.h" +#include "trx0sys.h" #include "read0types.h" /*********************************************************************//** @@ -44,8 +45,11 @@ read_view_open_now( /*===============*/ trx_id_t cr_trx_id, /*!< in: trx_id of creating transaction, or 0 used in purge */ - mem_heap_t* heap); /*!< in: memory heap from which - allocated */ + read_view_t* view, /*!< in: current read view or NULL if it + doesn't exist yet */ + ibool exclude_self); /*!< in: TRUE, if cr_trx_id should be + excluded from the resulting view */ + /*********************************************************************//** Makes a copy of the oldest existing read view, or opens a new. The view must be closed with ..._close. @@ -56,8 +60,8 @@ read_view_oldest_copy_or_open_new( /*==============================*/ trx_id_t cr_trx_id, /*!< in: trx_id of creating transaction, or 0 used in purge */ - mem_heap_t* heap); /*!< in: memory heap from which - allocated */ + read_view_t* view); /*!< in: pre-allocated view array or + NULL if a new one needs to be created */ /*********************************************************************//** Closes a read view. */ UNIV_INTERN @@ -66,6 +70,13 @@ read_view_close( /*============*/ read_view_t* view); /*!< in: read view */ /*********************************************************************//** +Frees memory allocated by a read view. */ +UNIV_INTERN +void +read_view_free( +/*===========*/ + read_view_t* view); /*< in: read view */ +/*********************************************************************//** Closes a consistent read view for MySQL. This function is called at an SQL statement end if the trx isolation level is <= TRX_ISO_READ_COMMITTED. */ UNIV_INTERN @@ -143,16 +154,20 @@ struct read_view_struct{ are strictly smaller (<) than this value. In other words, this is the "low water mark". */ - ulint n_trx_ids; + ulint n_descr; /*!< Number of cells in the trx_ids array */ - trx_id_t* trx_ids;/*!< Additional trx ids which the read should - not see: typically, these are the active + ulint max_descr; + /*!< Maximum number of cells in the trx_ids + array */ + trx_id_t* descriptors; + /*!< Array of trx descriptors which the read + should not see: typically, these are the active transactions at the time when the read is serialized, except the reading transaction itself; the trx ids in this array are in a descending order. These trx_ids should be - between the "low" and "high" water marks, - that is, up_limit_id and low_limit_id. */ + between the "low" and "high" water marks, that + is, up_limit_id and low_limit_id. */ trx_id_t creator_trx_id; /*!< trx id of creating transaction, or 0 used in purge */ diff --git a/storage/xtradb/include/read0read.ic b/storage/xtradb/include/read0read.ic index 5bb5249b591..ebcdb767406 100644 --- a/storage/xtradb/include/read0read.ic +++ b/storage/xtradb/include/read0read.ic @@ -25,6 +25,11 @@ Created 2/16/1997 Heikki Tuuri /*********************************************************************//** Gets the nth trx id in a read view. + +Upstream code stores array of trx_ids in the descending order. Percona Server +keeps it in the ascending order for performance reasons. Let us keep the +semantics. + @return trx id */ UNIV_INLINE trx_id_t @@ -33,13 +38,17 @@ read_view_get_nth_trx_id( const read_view_t* view, /*!< in: read view */ ulint n) /*!< in: position */ { - ut_ad(n < view->n_trx_ids); + ut_ad(n < view->n_descr); - return(*(view->trx_ids + n)); + return(view->descriptors[view->n_descr - 1 - n]); } /*********************************************************************//** -Sets the nth trx id in a read view. */ +Sets the nth trx id in a read view. + +Upstream code stores array of trx_ids in the descending order. Percona Server +keeps it in the ascending order for performance reasons. Let us keep the +semantics. */ UNIV_INLINE void read_view_set_nth_trx_id( @@ -48,9 +57,9 @@ read_view_set_nth_trx_id( ulint n, /*!< in: position */ trx_id_t trx_id) /*!< in: trx id to set */ { - ut_ad(n < view->n_trx_ids); + ut_ad(n < view->n_descr); - *(view->trx_ids + n) = trx_id; + view->descriptors[view->n_descr - 1 - n] = trx_id; } /*********************************************************************//** @@ -63,9 +72,6 @@ read_view_sees_trx_id( const read_view_t* view, /*!< in: read view */ trx_id_t trx_id) /*!< in: trx id */ { - ulint n_ids; - ulint i; - if (trx_id < view->up_limit_id) { return(TRUE); @@ -76,21 +82,8 @@ read_view_sees_trx_id( return(FALSE); } - /* We go through the trx ids in the array smallest first: this order - may save CPU time, because if there was a very long running - transaction in the trx id array, its trx id is looked at first, and - the first two comparisons may well decide the visibility of trx_id. */ - - n_ids = view->n_trx_ids; - - for (i = 0; i < n_ids; i++) { - trx_id_t view_trx_id - = read_view_get_nth_trx_id(view, n_ids - i - 1); - - if (trx_id <= view_trx_id) { - return(trx_id != view_trx_id); - } - } + /* Do a binary search over this view's descriptors array */ - return(TRUE); + return(trx_find_descriptor(view->descriptors, view->n_descr, + trx_id) == NULL); } diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index 586c1e73879..53dbf21e455 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -274,9 +274,22 @@ extern ulong srv_adaptive_flushing_method; extern ulong srv_expand_import; extern ulong srv_pass_corrupt_table; -extern ulint srv_dict_size_limit; +/* Helper macro to support srv_pass_corrupt_table checks. If 'cond' is FALSE, +execute 'code' if srv_pass_corrupt_table is non-zero, or trigger a fatal error +otherwise. The break statement in 'code' will obviously not work as expected. */ + +#define SRV_CORRUPT_TABLE_CHECK(cond,code) \ + do { \ + if (UNIV_UNLIKELY(!(cond))) { \ + if (srv_pass_corrupt_table) { \ + code \ + } else { \ + ut_error; \ + } \ + } \ + } while(0) -extern ulint srv_lazy_drop_table; +extern ulint srv_dict_size_limit; /*-------------------------------------------*/ extern ulint srv_n_rows_inserted; diff --git a/storage/xtradb/include/trx0purge.h b/storage/xtradb/include/trx0purge.h index 1e8acd65e01..1ddc9068b8e 100644 --- a/storage/xtradb/include/trx0purge.h +++ b/storage/xtradb/include/trx0purge.h @@ -143,6 +143,7 @@ struct trx_purge_struct{ obtaining an s-latch here. */ read_view_t* view; /*!< The purge will not remove undo logs which are >= this view (purge view) */ + read_view_t* prebuilt_view; /*!< Pre-built view array */ ulonglong n_pages_handled;/*!< Approximate number of undo log pages processed in purge */ ulonglong handle_limit; /*!< Target of how many pages to get diff --git a/storage/xtradb/include/trx0sys.h b/storage/xtradb/include/trx0sys.h index cba21ae97a9..75a3b0fb4fd 100644 --- a/storage/xtradb/include/trx0sys.h +++ b/storage/xtradb/include/trx0sys.h @@ -249,6 +249,17 @@ trx_id_t trx_sys_get_new_trx_id(void); /*========================*/ +/*************************************************************//** +Find a slot for a given trx ID in a descriptors array. +@return: slot pointer */ +UNIV_INLINE +trx_id_t* +trx_find_descriptor( +/*================*/ + const trx_id_t* descriptors, /*!< in: descriptors array */ + ulint n_descr, /*!< in: array size */ + trx_id_t trx_id); /*!< in: trx pointer */ + #ifdef UNIV_DEBUG /* Flag to control TRX_RSEG_N_SLOTS behavior debugging. */ extern uint trx_rseg_n_slots_debug; @@ -633,6 +644,8 @@ identifier is added to this 64-bit constant. */ | TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_LOW) /* @} */ +#define TRX_DESCR_ARRAY_INITIAL_SIZE 1000 + #ifndef UNIV_HOTBACKUP /** Doublewrite control struct */ struct trx_doublewrite_struct{ @@ -660,16 +673,41 @@ struct trx_sys_struct{ trx_id_t max_trx_id; /*!< The smallest number not yet assigned as a transaction id or transaction number */ + char pad1[64]; /*!< Ensure max_trx_id does not share + cache line with other fields. */ + trx_id_t* descriptors; /*!< Array of trx descriptors */ + ulint descr_n_max; /*!< The current size of the descriptors + array. */ + char pad2[64]; /*!< Ensure static descriptor fields + do not share cache lines with + descr_n_used */ + ulint descr_n_used; /*!< Number of used elements in the + descriptors array. */ + char pad3[64]; /*!< Ensure descriptors do not share + cache line with other fields */ UT_LIST_BASE_NODE_T(trx_t) trx_list; /*!< List of active and committed in memory transactions, sorted on trx id, biggest first */ + char pad4[64]; /*!< Ensure list base nodes do not + share cache line with other fields */ UT_LIST_BASE_NODE_T(trx_t) mysql_trx_list; /*!< List of transactions created for MySQL */ + char pad5[64]; /*!< Ensure list base nodes do not + share cache line with other fields */ + UT_LIST_BASE_NODE_T(trx_t) trx_serial_list; + /*!< trx->no ordered List of + transactions in either TRX_PREPARED or + TRX_ACTIVE which have already been + assigned a serialization number */ + char pad6[64]; /*!< Ensure trx_serial_list does not + share cache line with other fields */ UT_LIST_BASE_NODE_T(trx_rseg_t) rseg_list; /*!< List of rollback segment objects */ + char pad7[64]; /*!< Ensure list base nodes do not + share cache line with other fields */ trx_rseg_t* latest_rseg; /*!< Latest rollback segment in the round-robin assignment of rollback segments to transactions */ diff --git a/storage/xtradb/include/trx0sys.ic b/storage/xtradb/include/trx0sys.ic index af05ab2f5ed..3af98cdf98b 100644 --- a/storage/xtradb/include/trx0sys.ic +++ b/storage/xtradb/include/trx0sys.ic @@ -367,28 +367,11 @@ trx_is_active( /*==========*/ trx_id_t trx_id) /*!< in: trx id of the transaction */ { - trx_t* trx; - ut_ad(mutex_own(&(kernel_mutex))); - if (trx_id < trx_list_get_min_trx_id()) { - - return(FALSE); - } - - if (UNIV_UNLIKELY(trx_id >= trx_sys->max_trx_id)) { - - /* There must be corruption: we return TRUE because this - function is only called by lock_clust_rec_some_has_impl() - and row_vers_impl_x_locked_off_kernel() and they have - diagnostic prints in this case */ - - return(TRUE); - } - - trx = trx_get_on_id(trx_id); - if (trx && (trx->conc_state == TRX_ACTIVE - || trx->conc_state == TRX_PREPARED)) { + if (trx_find_descriptor(trx_sys->descriptors, + trx_sys->descr_n_used, + trx_id)) { return(TRUE); } @@ -425,4 +408,27 @@ trx_sys_get_new_trx_id(void) return(id); } + +/*************************************************************//** +Find a slot for a given trx ID in a descriptors array. +@return: slot pointer */ +UNIV_INLINE +trx_id_t* +trx_find_descriptor( +/*================*/ + const trx_id_t* descriptors, /*!< in: descriptors array */ + ulint n_descr, /*!< in: array size */ + trx_id_t trx_id) /*!< in: trx pointer */ +{ + ut_ad(descriptors != trx_sys->descriptors || + mutex_own(&kernel_mutex)); + + if (UNIV_UNLIKELY(n_descr == 0)) { + + return(NULL); + } + + return((trx_id_t *) bsearch(&trx_id, descriptors, n_descr, + sizeof(trx_id_t), trx_descr_cmp)); +} #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/xtradb/include/trx0trx.h b/storage/xtradb/include/trx0trx.h index a03f7aceafa..40f441295b0 100644 --- a/storage/xtradb/include/trx0trx.h +++ b/storage/xtradb/include/trx0trx.h @@ -447,6 +447,23 @@ trx_get_que_state_str( /*==================*/ const trx_t* trx); /*!< in: transaction */ +/*************************************************************//** +Callback function for trx_find_descriptor() to compare trx IDs. */ +UNIV_INTERN +int +trx_descr_cmp( +/*==========*/ + const void *a, /*!< in: pointer to first comparison argument */ + const void *b); /*!< in: pointer to second comparison argument */ + +/*************************************************************//** +Release a slot for a given trx in the global descriptors array. */ +UNIV_INTERN +void +trx_release_descriptor( +/*===================*/ + trx_t* trx); /*!< in: trx pointer */ + /* Signal to a transaction */ struct trx_sig_struct{ unsigned type:3; /*!< signal type */ @@ -477,10 +494,18 @@ struct trx_struct{ const char* op_info; /*!< English text describing the current operation, or an empty string */ - ulint conc_state; /*!< state of the trx from the point - of view of concurrency control: - TRX_ACTIVE, TRX_COMMITTED_IN_MEMORY, - ... */ + ulint state; /*!< state of the trx from the point of + view of concurrency control: TRX_ACTIVE, + TRX_COMMITTED_IN_MEMORY, ... This was + called 'conc_state' in the upstream and + has been renamed in Percona Server, + because changing it's value to/from + either TRX_ACTIVE or TRX_PREPARED + requires calling + trx_reserve_descriptor() / + trx_release_descriptor(). Different name + ensures we notice any new code changing + the state. */ /*------------------------------*/ /* MySQL has a transaction coordinator to coordinate two phase commit between multiple storage engines and the binary log. When @@ -494,6 +519,9 @@ struct trx_struct{ this is set to 1 then registered should also be set to 1. This is used in the XA code */ + unsigned is_in_trx_serial_list:1; + /* Set when transaction is in the + trx_serial_list */ /*------------------------------*/ ulint isolation_level;/* TRX_ISO_REPEATABLE_READ, ... */ ulint check_foreigns; /* normally TRUE, but if the user @@ -627,6 +655,9 @@ struct trx_struct{ UT_LIST_NODE_T(trx_t) mysql_trx_list; /*!< list of transactions created for MySQL */ + UT_LIST_NODE_T(trx_t) + trx_serial_list;/*!< list node for + trx_sys->trx_serial_list */ /*------------------------------*/ ulint error_state; /*!< 0 if no error, otherwise error number; NOTE That ONLY the thread @@ -685,9 +716,6 @@ struct trx_struct{ UT_LIST_BASE_NODE_T(lock_t) trx_locks; /*!< locks reserved by the transaction */ /*------------------------------*/ - mem_heap_t* global_read_view_heap; - /* memory heap for the global read - view */ read_view_t* global_read_view; /* consistent read view associated to a transaction or NULL */ @@ -697,6 +725,7 @@ struct trx_struct{ associated to a transaction (i.e. same as global_read_view) or read view associated to a cursor */ + read_view_t* prebuilt_view; /* pre-built view array */ /*------------------------------*/ UT_LIST_BASE_NODE_T(trx_named_savept_t) trx_savepoints; /*!< savepoints set with SAVEPOINT ..., diff --git a/storage/xtradb/include/trx0trx.ic b/storage/xtradb/include/trx0trx.ic index 4a1d3bcde0b..1a1fc91eac5 100644 --- a/storage/xtradb/include/trx0trx.ic +++ b/storage/xtradb/include/trx0trx.ic @@ -31,9 +31,9 @@ trx_start_if_not_started( /*=====================*/ trx_t* trx) /*!< in: transaction */ { - ut_ad(trx->conc_state != TRX_COMMITTED_IN_MEMORY); + ut_ad(trx->state != TRX_COMMITTED_IN_MEMORY); - if (trx->conc_state == TRX_NOT_STARTED) { + if (trx->state == TRX_NOT_STARTED) { trx_start(trx, ULINT_UNDEFINED); } @@ -48,9 +48,9 @@ trx_start_if_not_started_low( /*=========================*/ trx_t* trx) /*!< in: transaction */ { - ut_ad(trx->conc_state != TRX_COMMITTED_IN_MEMORY); + ut_ad(trx->state != TRX_COMMITTED_IN_MEMORY); - if (trx->conc_state == TRX_NOT_STARTED) { + if (trx->state == TRX_NOT_STARTED) { trx_start_low(trx, ULINT_UNDEFINED); } diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 60c5cc79852..0fefdbaeb9a 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -64,7 +64,7 @@ component, i.e. we show M.N.P as M.N */ (INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR) #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 30.1 +#define PERCONA_INNODB_VERSION 30.2 #endif #define INNODB_VERSION_STR MYSQL_SERVER_VERSION "-" IB_TO_STR(PERCONA_INNODB_VERSION) diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c index 47d082ed49f..f4c991d4fe9 100644 --- a/storage/xtradb/lock/lock0lock.c +++ b/storage/xtradb/lock/lock0lock.c @@ -4652,7 +4652,7 @@ lock_print_info_all_transactions( trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list); while (trx) { - if (trx->conc_state == TRX_NOT_STARTED) { + if (trx->state == TRX_NOT_STARTED) { fputs("---", file); trx_print(file, trx, 600); } @@ -4820,9 +4820,9 @@ lock_table_queue_validate( lock = UT_LIST_GET_FIRST(table->locks); while (lock) { - ut_a(((lock->trx)->conc_state == TRX_ACTIVE) - || ((lock->trx)->conc_state == TRX_PREPARED) - || ((lock->trx)->conc_state == TRX_COMMITTED_IN_MEMORY)); + ut_a(((lock->trx)->state == TRX_ACTIVE) + || ((lock->trx)->state == TRX_PREPARED) + || ((lock->trx)->state == TRX_COMMITTED_IN_MEMORY)); if (!lock_get_wait(lock)) { @@ -4870,7 +4870,7 @@ lock_rec_queue_validate( lock = lock_rec_get_first(block, heap_no); while (lock) { - switch(lock->trx->conc_state) { + switch(lock->trx->state) { case TRX_ACTIVE: case TRX_PREPARED: case TRX_COMMITTED_IN_MEMORY: @@ -4957,9 +4957,9 @@ lock_rec_queue_validate( lock = lock_rec_get_first(block, heap_no); while (lock) { - ut_a(lock->trx->conc_state == TRX_ACTIVE - || lock->trx->conc_state == TRX_PREPARED - || lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY); + ut_a(lock->trx->state == TRX_ACTIVE + || lock->trx->state == TRX_PREPARED + || lock->trx->state == TRX_COMMITTED_IN_MEMORY); ut_a(trx_in_trx_list(lock->trx)); if (index) { @@ -5036,9 +5036,9 @@ loop: } ut_a(trx_in_trx_list(lock->trx)); - ut_a(lock->trx->conc_state == TRX_ACTIVE - || lock->trx->conc_state == TRX_PREPARED - || lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY); + ut_a(lock->trx->state == TRX_ACTIVE + || lock->trx->state == TRX_PREPARED + || lock->trx->state == TRX_COMMITTED_IN_MEMORY); # ifdef UNIV_SYNC_DEBUG /* Only validate the record queues when this thread is not diff --git a/storage/xtradb/log/log0log.c b/storage/xtradb/log/log0log.c index e7c7a165b9c..a5243d22e8d 100644 --- a/storage/xtradb/log/log0log.c +++ b/storage/xtradb/log/log0log.c @@ -265,13 +265,12 @@ log_check_tracking_margin( } /************************************************************//** -Opens the log for log_write_low. The log must be closed with log_close and -released with log_release. +Opens the log for log_write_low. The log must be closed with log_close. @return start lsn of the log record */ UNIV_INTERN ib_uint64_t -log_reserve_and_open( -/*=================*/ +log_open( +/*=====*/ ulint len) /*!< in: length of data to be catenated */ { log_t* log = log_sys; @@ -284,7 +283,6 @@ log_reserve_and_open( ut_a(len < log->buf_size / 2); loop: - mutex_enter(&(log->mutex)); ut_ad(!recv_no_log_write); /* Calculate an upper limit for the space the string may take in the @@ -305,6 +303,8 @@ loop: ut_ad(++count < 50); + mutex_enter(&(log->mutex)); + goto loop; } @@ -318,6 +318,8 @@ loop: os_thread_sleep(10000); + mutex_enter(&(log->mutex)); + goto loop; } @@ -338,6 +340,8 @@ loop: ut_ad(++count < 50); + mutex_enter(&(log->mutex)); + goto loop; } } @@ -494,9 +498,12 @@ log_close(void) if (tracked_lsn_age >= log->log_group_capacity) { - fprintf(stderr, " InnoDB: Error: the age of the " + fprintf(stderr, "InnoDB: Error: the age of the " "oldest untracked record exceeds the log " "group capacity!\n"); + fprintf(stderr, "InnoDB: Error: stopping the log " + "tracking thread at LSN %llu\n", tracked_lsn); + srv_track_changed_pages = FALSE; } } diff --git a/storage/xtradb/mtr/mtr0mtr.c b/storage/xtradb/mtr/mtr0mtr.c index 092bd702115..9eb7b18f301 100644 --- a/storage/xtradb/mtr/mtr0mtr.c +++ b/storage/xtradb/mtr/mtr0mtr.c @@ -38,6 +38,25 @@ Created 11/26/1995 Heikki Tuuri #ifndef UNIV_HOTBACKUP # include "log0recv.h" + +/***************************************************//** +Checks if a mini-transaction is dirtying a clean page. +@return TRUE if the mtr is dirtying a clean page. */ +UNIV_INTERN +ibool +mtr_block_dirtied( +/*==============*/ + const buf_block_t* block) /*!< in: block being x-fixed */ +{ + ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); + ut_ad(block->page.buf_fix_count > 0); + + /* It is OK to read oldest_modification because no + other thread can be performing a write of it and it + is only during write that the value is reset to 0. */ + return(block->page.oldest_modification == 0); +} + /*****************************************************************//** Releases the item in the slot given. */ static @@ -126,7 +145,7 @@ mtr_memo_slot_note_modification( buf_block_t* block = (buf_block_t*) slot->object; #ifdef UNIV_DEBUG - ut_ad(log_flush_order_mutex_own()); + ut_ad(!mtr->made_dirty || log_flush_order_mutex_own()); #endif /* UNIV_DEBUG */ buf_flush_note_modification(block, mtr); } @@ -202,12 +221,14 @@ mtr_log_reserve_and_write( Add pages to flush list and exit */ goto func_exit; } + } else { + mutex_enter(&log_sys->mutex); } data_size = dyn_array_get_data_size(mlog); /* Open the database log for log_write_low */ - mtr->start_lsn = log_reserve_and_open(data_size); + mtr->start_lsn = log_open(data_size); if (mtr->log_mode == MTR_LOG_ALL) { @@ -226,7 +247,15 @@ mtr_log_reserve_and_write( mtr->end_lsn = log_close(); func_exit: - log_flush_order_mutex_enter(); + + /* No need to acquire log_flush_order_mutex if this mtr has + not dirtied a clean page. log_flush_order_mutex is used to + ensure ordered insertions in the flush_list. We need to + insert in the flush_list iff the page in question was clean + before modifications. */ + if (mtr->made_dirty) { + log_flush_order_mutex_enter(); + } /* It is now safe to release the log mutex because the flush_order mutex will ensure that we are the first one @@ -237,7 +266,9 @@ func_exit: mtr_memo_note_modifications(mtr); } - log_flush_order_mutex_exit(); + if (mtr->made_dirty) { + log_flush_order_mutex_exit(); + } } #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/xtradb/read/read0read.c b/storage/xtradb/read/read0read.c index f049dd21e8d..c04dae51ff5 100644 --- a/storage/xtradb/read/read0read.c +++ b/storage/xtradb/read/read0read.c @@ -145,14 +145,27 @@ read_view_t* read_view_create_low( /*=================*/ ulint n, /*!< in: number of cells in the trx_ids array */ - mem_heap_t* heap) /*!< in: memory heap from which allocated */ + read_view_t* view) /*!< in: pre-allocated view array or NULL if a + new one needs to be created */ { - read_view_t* view; + if (view == NULL) { + view = ut_malloc(sizeof(read_view_t)); + view->max_descr = 0; + view->descriptors = NULL; + } + + if (UNIV_UNLIKELY(view->max_descr < n)) { - view = mem_heap_alloc(heap, sizeof(read_view_t)); + /* avoid frequent re-allocations by extending the array to the + desired size + 10% */ + + view->max_descr = n + n / 10; + view->descriptors = ut_realloc(view->descriptors, + view->max_descr * + sizeof(trx_id_t)); + } - view->n_trx_ids = n; - view->trx_ids = mem_heap_alloc(heap, n * sizeof *view->trx_ids); + view->n_descr = n; return(view); } @@ -169,8 +182,8 @@ read_view_oldest_copy_or_open_new( /*==============================*/ trx_id_t cr_trx_id, /*!< in: trx_id of creating transaction, or 0 used in purge */ - mem_heap_t* heap) /*!< in: memory heap from which - allocated */ + read_view_t* view) /*!< in: pre-allocated view array or + NULL if a new one needs to be created */ { read_view_t* old_view; read_view_t* view_copy; @@ -185,10 +198,10 @@ read_view_oldest_copy_or_open_new( if (old_view == NULL) { - return(read_view_open_now(cr_trx_id, heap)); + return(read_view_open_now(cr_trx_id, view, TRUE)); } - n = old_view->n_trx_ids; + n = old_view->n_descr; if (old_view->creator_trx_id) { n++; @@ -196,7 +209,7 @@ read_view_oldest_copy_or_open_new( needs_insert = FALSE; } - view_copy = read_view_create_low(n, heap); + view_copy = read_view_create_low(n, view); /* Insert the id of the creator in the right place of the descending array of ids, if needs_insert is TRUE: */ @@ -204,7 +217,7 @@ read_view_oldest_copy_or_open_new( i = 0; while (i < n) { if (needs_insert - && (i >= old_view->n_trx_ids + && (i >= old_view->n_descr || old_view->creator_trx_id > read_view_get_nth_trx_id(old_view, i))) { @@ -251,16 +264,17 @@ read_view_open_now( /*===============*/ trx_id_t cr_trx_id, /*!< in: trx_id of creating transaction, or 0 used in purge */ - mem_heap_t* heap) /*!< in: memory heap from which - allocated */ + read_view_t* view, /*!< in: current read view or NULL if it + doesn't exist yet */ + ibool exclude_self) /*!< in: TRUE, if cr_trx_id should be + excluded from the resulting view */ { - read_view_t* view; - trx_t* trx; - ulint n; + trx_id_t* descr; + ulint i; ut_ad(mutex_own(&kernel_mutex)); - view = read_view_create_low(UT_LIST_GET_LEN(trx_sys->trx_list), heap); + view = read_view_create_low(trx_sys->descr_n_used, view); view->creator_trx_id = cr_trx_id; view->type = VIEW_NORMAL; @@ -271,40 +285,58 @@ read_view_open_now( view->low_limit_no = trx_sys->max_trx_id; view->low_limit_id = view->low_limit_no; - n = 0; - trx = UT_LIST_GET_FIRST(trx_sys->trx_list); + /* No active transaction should be visible */ - /* No active transaction should be visible, except cr_trx */ + descr = trx_find_descriptor(trx_sys->descriptors, + trx_sys->descr_n_used, + cr_trx_id); - while (trx) { - if (trx->id != cr_trx_id - && (trx->conc_state == TRX_ACTIVE - || trx->conc_state == TRX_PREPARED)) { + if (UNIV_LIKELY(exclude_self && descr != NULL)) { - read_view_set_nth_trx_id(view, n, trx->id); + ut_ad(trx_sys->descr_n_used > 0); + ut_ad(view->n_descr > 0); - n++; + view->n_descr--; - /* NOTE that a transaction whose trx number is < - trx_sys->max_trx_id can still be active, if it is - in the middle of its commit! Note that when a - transaction starts, we initialize trx->no to - IB_ULONGLONG_MAX. */ + i = descr - trx_sys->descriptors; + } else { + i = trx_sys->descr_n_used; + } - if (view->low_limit_no > trx->no) { + if (UNIV_LIKELY(i > 0)) { - view->low_limit_no = trx->no; - } - } + /* Copy the [0; i-1] range */ + memcpy(view->descriptors, trx_sys->descriptors, + i * sizeof(trx_id_t)); + } - trx = UT_LIST_GET_NEXT(trx_list, trx); + if (UNIV_UNLIKELY(i + 1 < trx_sys->descr_n_used)) { + + /* Copy the [i+1; descr_n_used-1] range */ + memcpy(view->descriptors + i, + trx_sys->descriptors + i + 1, + (trx_sys->descr_n_used - i - 1) * + sizeof(trx_id_t)); } - view->n_trx_ids = n; + /* NOTE that a transaction whose trx number is < trx_sys->max_trx_id can + still be active, if it is in the middle of its commit! Note that when a + transaction starts, we initialize trx->no to IB_ULONGLONG_MAX. */ - if (n > 0) { + if (UT_LIST_GET_LEN(trx_sys->trx_serial_list) > 0) { + + trx_id_t trx_no; + + trx_no = UT_LIST_GET_FIRST(trx_sys->trx_serial_list)->no; + + if (trx_no < view->low_limit_no) { + view->low_limit_no = trx_no; + } + } + + if (UNIV_LIKELY(view->n_descr > 0)) { /* The last active transaction has the smallest id: */ - view->up_limit_id = read_view_get_nth_trx_id(view, n - 1); + view->up_limit_id = view->descriptors[0]; } else { view->up_limit_id = view->low_limit_id; } @@ -329,6 +361,23 @@ read_view_close( } /*********************************************************************//** +Frees resource allocated by a read view. */ +UNIV_INTERN +void +read_view_free( +/*===========*/ + read_view_t* view) /*< in: read view */ +{ + ut_ad(mutex_own(&kernel_mutex)); + + if (view->descriptors != NULL) { + ut_free(view->descriptors); + } + + ut_free(view); +} + +/*********************************************************************//** Closes a consistent read view for MySQL. This function is called at an SQL statement end if the trx isolation level is <= TRX_ISO_READ_COMMITTED. */ UNIV_INTERN @@ -343,8 +392,6 @@ read_view_close_for_mysql( read_view_close(trx->global_read_view); - mem_heap_empty(trx->global_read_view_heap); - trx->read_view = NULL; trx->global_read_view = NULL; @@ -382,7 +429,7 @@ read_view_print( fprintf(file, "Read view individually stored trx ids:\n"); - n_ids = view->n_trx_ids; + n_ids = view->n_descr; for (i = 0; i < n_ids; i++) { fprintf(file, "Read view trx id " TRX_ID_FMT "\n", @@ -404,8 +451,6 @@ read_cursor_view_create_for_mysql( cursor_view_t* curview; read_view_t* view; mem_heap_t* heap; - trx_t* trx; - ulint n; ut_a(cr_trx); @@ -424,61 +469,14 @@ read_cursor_view_create_for_mysql( mutex_enter(&kernel_mutex); - curview->read_view = read_view_create_low( - UT_LIST_GET_LEN(trx_sys->trx_list), curview->heap); + curview->read_view = read_view_open_now(cr_trx->id, NULL, FALSE); + + mutex_exit(&kernel_mutex); view = curview->read_view; - view->creator_trx_id = cr_trx->id; view->type = VIEW_HIGH_GRANULARITY; view->undo_no = cr_trx->undo_no; - /* No future transactions should be visible in the view */ - - view->low_limit_no = trx_sys->max_trx_id; - view->low_limit_id = view->low_limit_no; - - n = 0; - trx = UT_LIST_GET_FIRST(trx_sys->trx_list); - - /* No active transaction should be visible */ - - while (trx) { - - if (trx->conc_state == TRX_ACTIVE - || trx->conc_state == TRX_PREPARED) { - - read_view_set_nth_trx_id(view, n, trx->id); - - n++; - - /* NOTE that a transaction whose trx number is < - trx_sys->max_trx_id can still be active, if it is - in the middle of its commit! Note that when a - transaction starts, we initialize trx->no to - IB_ULONGLONG_MAX. */ - - if (view->low_limit_no > trx->no) { - - view->low_limit_no = trx->no; - } - } - - trx = UT_LIST_GET_NEXT(trx_list, trx); - } - - view->n_trx_ids = n; - - if (n > 0) { - /* The last active transaction has the smallest id: */ - view->up_limit_id = read_view_get_nth_trx_id(view, n - 1); - } else { - view->up_limit_id = view->low_limit_id; - } - - UT_LIST_ADD_FIRST(view_list, trx_sys->view_list, view); - - mutex_exit(&kernel_mutex); - return(curview); } @@ -503,6 +501,8 @@ read_cursor_view_close_for_mysql( mutex_enter(&kernel_mutex); read_view_close(curview->read_view); + read_view_free(curview->read_view); + trx->read_view = trx->global_read_view; mutex_exit(&kernel_mutex); diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c index fda0c55b5c7..0002f4410d6 100644 --- a/storage/xtradb/row/row0ins.c +++ b/storage/xtradb/row/row0ins.c @@ -1346,11 +1346,11 @@ run_again: const rec_t* rec = btr_pcur_get_rec(&pcur); const buf_block_t* block = btr_pcur_get_block(&pcur); - if (srv_pass_corrupt_table && !block) { + SRV_CORRUPT_TABLE_CHECK(block, + { err = DB_CORRUPTION; - break; - } - ut_a(block); + goto exit_loop; + }); if (page_rec_is_infimum(rec)) { @@ -1474,6 +1474,7 @@ run_again: } } while (btr_pcur_move_to_next(&pcur, &mtr)); +exit_loop: if (check_ref) { row_ins_foreign_report_add_err( trx, foreign, btr_pcur_get_rec(&pcur), entry); diff --git a/storage/xtradb/row/row0merge.c b/storage/xtradb/row/row0merge.c index 0b6a6302854..40e7d99b839 100644 --- a/storage/xtradb/row/row0merge.c +++ b/storage/xtradb/row/row0merge.c @@ -1298,11 +1298,11 @@ row_merge_read_clustered_index( if (UNIV_LIKELY(has_next)) { rec = btr_pcur_get_rec(&pcur); - if (srv_pass_corrupt_table && !rec) { + SRV_CORRUPT_TABLE_CHECK(rec, + { err = DB_CORRUPTION; goto err_exit; - } - ut_a(rec); + }); offsets = rec_get_offsets(rec, clust_index, NULL, ULINT_UNDEFINED, &row_heap); diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c index 858d50fd5a6..dec192585ce 100644 --- a/storage/xtradb/row/row0sel.c +++ b/storage/xtradb/row/row0sel.c @@ -3952,9 +3952,9 @@ release_search_latch_if_needed: trx->has_search_latch = FALSE; } - ut_ad(prebuilt->sql_stat_start || trx->conc_state == TRX_ACTIVE); - ut_ad(trx->conc_state == TRX_NOT_STARTED - || trx->conc_state == TRX_ACTIVE); + ut_ad(prebuilt->sql_stat_start || trx->state == TRX_ACTIVE); + ut_ad(trx->state == TRX_NOT_STARTED + || trx->state == TRX_ACTIVE); ut_ad(prebuilt->sql_stat_start || prebuilt->select_lock_type != LOCK_NONE || trx->read_view); @@ -4137,11 +4137,11 @@ rec_loop: rec = btr_pcur_get_rec(pcur); - if (srv_pass_corrupt_table && !rec) { + SRV_CORRUPT_TABLE_CHECK(rec, + { err = DB_CORRUPTION; goto lock_wait_or_error; - } - ut_a(rec); + }); ut_ad(!!page_rec_is_comp(rec) == comp); #ifdef UNIV_SEARCH_DEBUG @@ -4278,8 +4278,9 @@ wrong_offs: offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); - if (UNIV_UNLIKELY(srv_force_recovery > 0) - || (srv_pass_corrupt_table == 2 && index->table->is_corrupt)) { + if (UNIV_UNLIKELY(srv_force_recovery > 0 + || (index->table->is_corrupt && + srv_pass_corrupt_table == 2))) { if (!rec_validate(rec, offsets) || !btr_index_rec_validate(rec, index, FALSE)) { fprintf(stderr, @@ -5092,8 +5093,10 @@ row_search_check_if_query_cache_permitted( if (trx->isolation_level >= TRX_ISO_REPEATABLE_READ && !trx->read_view) { - trx->read_view = read_view_open_now( - trx->id, trx->global_read_view_heap); + trx->read_view = + read_view_open_now(trx->id, + NULL, TRUE); + trx->global_read_view = trx->read_view; } } diff --git a/storage/xtradb/row/row0vers.c b/storage/xtradb/row/row0vers.c index 6d83dbaf8ee..3fd13b829a2 100644 --- a/storage/xtradb/row/row0vers.c +++ b/storage/xtradb/row/row0vers.c @@ -667,9 +667,9 @@ row_vers_build_for_semi_consistent_read( mutex_enter(&kernel_mutex); version_trx = trx_get_on_id(version_trx_id); - if (version_trx - && (version_trx->conc_state == TRX_COMMITTED_IN_MEMORY - || version_trx->conc_state == TRX_NOT_STARTED)) { + if (version_trx && + (version_trx->state == TRX_COMMITTED_IN_MEMORY + || version_trx->state == TRX_NOT_STARTED)) { version_trx = NULL; } diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c index 6edfbaa7755..3119c870d2c 100644 --- a/storage/xtradb/srv/srv0srv.c +++ b/storage/xtradb/srv/srv0srv.c @@ -434,8 +434,6 @@ UNIV_INTERN ulong srv_expand_import = 0; /* 0:disable 1:enable */ UNIV_INTERN ulong srv_pass_corrupt_table = 0; /* 0:disable 1:enable */ UNIV_INTERN ulint srv_dict_size_limit = 0; - -UNIV_INTERN ulint srv_lazy_drop_table = 0; /*-------------------------------------------*/ UNIV_INTERN ulong srv_n_spin_wait_rounds = 30; UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500; @@ -2932,7 +2930,7 @@ rescan_idle: mutex_enter(&kernel_mutex); trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list); while (trx) { - if (trx->conc_state == TRX_ACTIVE + if (trx->state == TRX_ACTIVE && trx->mysql_thd && innobase_thd_is_idle(trx->mysql_thd)) { ib_int64_t start_time = innobase_thd_get_start_time(trx->mysql_thd); diff --git a/storage/xtradb/trx/trx0purge.c b/storage/xtradb/trx/trx0purge.c index b048dc66efe..1e119c6828b 100644 --- a/storage/xtradb/trx/trx0purge.c +++ b/storage/xtradb/trx/trx0purge.c @@ -263,8 +263,9 @@ trx_purge_sys_create( purge_sys->query = trx_purge_graph_build(); - purge_sys->view = read_view_oldest_copy_or_open_new(0, - purge_sys->heap); + purge_sys->prebuilt_view = + read_view_oldest_copy_or_open_new(0, NULL); + purge_sys->view = purge_sys->prebuilt_view; } /************************************************************************ @@ -279,7 +280,12 @@ trx_purge_sys_close(void) que_graph_free(purge_sys->query); ut_a(purge_sys->sess->trx->is_purge); - purge_sys->sess->trx->conc_state = TRX_NOT_STARTED; + purge_sys->sess->trx->state = TRX_NOT_STARTED; + + mutex_enter(&kernel_mutex); + trx_release_descriptor(purge_sys->sess->trx); + mutex_exit(&kernel_mutex); + sess_close(purge_sys->sess); purge_sys->sess = NULL; @@ -289,6 +295,8 @@ trx_purge_sys_close(void) mutex_enter(&kernel_mutex); read_view_close(purge_sys->view); + read_view_free(purge_sys->prebuilt_view); + purge_sys->prebuilt_view = NULL; purge_sys->view = NULL; mutex_exit(&kernel_mutex); @@ -1177,7 +1185,7 @@ trx_purge( } purge_sys->view = read_view_oldest_copy_or_open_new( - 0, purge_sys->heap); + 0, purge_sys->prebuilt_view); mutex_exit(&kernel_mutex); diff --git a/storage/xtradb/trx/trx0roll.c b/storage/xtradb/trx/trx0roll.c index b55471959ce..ae42623a1d9 100644 --- a/storage/xtradb/trx/trx0roll.c +++ b/storage/xtradb/trx/trx0roll.c @@ -132,7 +132,7 @@ trx_rollback_for_mysql( { int err; - if (trx->conc_state == TRX_NOT_STARTED) { + if (trx->state == TRX_NOT_STARTED) { return(DB_SUCCESS); } @@ -161,7 +161,7 @@ trx_rollback_last_sql_stat_for_mysql( { int err; - if (trx->conc_state == TRX_NOT_STARTED) { + if (trx->state == TRX_NOT_STARTED) { return(DB_SUCCESS); } @@ -263,7 +263,7 @@ trx_rollback_to_savepoint_for_mysql( return(DB_NO_SAVEPOINT); } - if (trx->conc_state == TRX_NOT_STARTED) { + if (trx->state == TRX_NOT_STARTED) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: transaction has a savepoint ", stderr); ut_print_name(stderr, trx, FALSE, savep->name); @@ -560,7 +560,7 @@ loop: continue; } - switch (trx->conc_state) { + switch (trx->state) { case TRX_NOT_STARTED: case TRX_PREPARED: continue; diff --git a/storage/xtradb/trx/trx0sys.c b/storage/xtradb/trx/trx0sys.c index c40bf02a7a2..2c44cee60fe 100644 --- a/storage/xtradb/trx/trx0sys.c +++ b/storage/xtradb/trx/trx0sys.c @@ -1319,6 +1319,12 @@ trx_sys_init_at_db_start(void) trx_sys = mem_zalloc(sizeof(*trx_sys)); + /* Allocate the trx descriptors array */ + trx_sys->descriptors = ut_malloc(sizeof(trx_id_t) * + TRX_DESCR_ARRAY_INITIAL_SIZE); + trx_sys->descr_n_max = TRX_DESCR_ARRAY_INITIAL_SIZE; + trx_sys->descr_n_used = 0; + sys_header = trx_sysf_get(&mtr); trx_rseg_list_and_array_init(sys_header, ib_bh, &mtr); @@ -1346,7 +1352,7 @@ trx_sys_init_at_db_start(void) for (;;) { - if (trx->conc_state != TRX_PREPARED) { + if (trx->state != TRX_PREPARED) { rows_to_undo += trx->undo_no; } @@ -2028,6 +2034,9 @@ trx_sys_close(void) ut_a(UT_LIST_GET_LEN(trx_sys->view_list) == 0); ut_a(UT_LIST_GET_LEN(trx_sys->mysql_trx_list) == 0); + ut_ad(trx_sys->descr_n_used == 0); + ut_free(trx_sys->descriptors); + mem_free(trx_sys); trx_sys = NULL; diff --git a/storage/xtradb/trx/trx0trx.c b/storage/xtradb/trx/trx0trx.c index a17f8abdad0..a2a41ef006f 100644 --- a/storage/xtradb/trx/trx0trx.c +++ b/storage/xtradb/trx/trx0trx.c @@ -85,6 +85,126 @@ trx_set_detailed_error_from_file( sizeof(trx->detailed_error)); } +/*************************************************************//** +Callback function for trx_find_descriptor() to compare trx IDs. */ +UNIV_INTERN +int +trx_descr_cmp( +/*==========*/ + const void *a, /*!< in: pointer to first comparison argument */ + const void *b) /*!< in: pointer to second comparison argument */ +{ + const trx_id_t* da = (const trx_id_t*) a; + const trx_id_t* db = (const trx_id_t*) b; + + if (*da < *db) { + return -1; + } else if (*da > *db) { + return 1; + } + + return 0; +} + +/*************************************************************//** +Reserve a slot for a given trx in the global descriptors array. */ +UNIV_INLINE +void +trx_reserve_descriptor( +/*===================*/ + const trx_t* trx) /*!< in: trx pointer */ +{ + ulint n_used; + ulint n_max; + trx_id_t* descr; + + ut_ad(mutex_own(&kernel_mutex)); + ut_ad(!trx_find_descriptor(trx_sys->descriptors, + trx_sys->descr_n_used, + trx->id)); + + n_used = trx_sys->descr_n_used + 1; + n_max = trx_sys->descr_n_max; + + if (UNIV_UNLIKELY(n_used > n_max)) { + + n_max = n_max * 2; + + trx_sys->descriptors = + ut_realloc(trx_sys->descriptors, + n_max * sizeof(trx_id_t)); + + trx_sys->descr_n_max = n_max; + } + + descr = trx_sys->descriptors + n_used - 1; + + if (UNIV_UNLIKELY(n_used > 1 && trx->id < descr[-1])) { + + /* Find the slot where it should be inserted. We could use a + binary search, but in reality linear search should be faster, + because the slot we are looking for is near the array end. */ + + trx_id_t* tdescr; + + for (tdescr = descr - 1; + tdescr >= trx_sys->descriptors && *tdescr > trx->id; + tdescr--) { + } + + tdescr++; + + ut_memmove(tdescr + 1, tdescr, (descr - tdescr) * + sizeof(trx_id_t)); + + descr = tdescr; + } + + *descr = trx->id; + + trx_sys->descr_n_used = n_used; +} + +/*************************************************************//** +Release a slot for a given trx in the global descriptors array. */ +UNIV_INTERN +void +trx_release_descriptor( +/*===================*/ + trx_t* trx) /*!< in: trx pointer */ +{ + ulint size; + trx_id_t* descr; + + ut_ad(mutex_own(&kernel_mutex)); + + if (UNIV_LIKELY(trx->is_in_trx_serial_list)) { + + UT_LIST_REMOVE(trx_serial_list, trx_sys->trx_serial_list, + trx); + trx->is_in_trx_serial_list = 0; + } + + descr = trx_find_descriptor(trx_sys->descriptors, + trx_sys->descr_n_used, + trx->id); + + if (UNIV_UNLIKELY(descr == NULL)) { + + return; + } + + size = (trx_sys->descriptors + trx_sys->descr_n_used - 1 - descr) * + sizeof(trx_id_t); + + if (UNIV_LIKELY(size > 0)) { + + ut_memmove(descr, descr + 1, size); + } + + trx_sys->descr_n_used--; +} + /****************************************************************//** Creates and initializes a transaction object. @return own: the transaction */ @@ -107,7 +227,7 @@ trx_create( trx->is_purge = 0; trx->is_recovered = 0; - trx->conc_state = TRX_NOT_STARTED; + trx->state = TRX_NOT_STARTED; trx->is_registered = 0; trx->active_commit_ordered = 0; @@ -118,6 +238,7 @@ trx_create( trx->id = 0; trx->no = IB_ULONGLONG_MAX; + trx->is_in_trx_serial_list = 0; trx->support_xa = TRUE; @@ -189,9 +310,9 @@ trx_create( trx->declared_to_be_inside_innodb = FALSE; trx->n_tickets_to_enter_innodb = 0; - trx->global_read_view_heap = mem_heap_create(256); trx->global_read_view = NULL; trx->read_view = NULL; + trx->prebuilt_view = NULL; trx->io_reads = 0; trx->io_read = 0; @@ -327,7 +448,7 @@ trx_free( trx->magic_n = 11112222; - ut_a(trx->conc_state == TRX_NOT_STARTED); + ut_a(trx->state == TRX_NOT_STARTED); mutex_free(&(trx->undo_mutex)); @@ -354,18 +475,18 @@ trx_free( ut_a(UT_LIST_GET_LEN(trx->trx_locks) == 0); - if (trx->global_read_view_heap) { - mem_heap_free(trx->global_read_view_heap); + if (trx->prebuilt_view != NULL) { + read_view_free(trx->prebuilt_view); } - trx->global_read_view = NULL; - ut_a(trx->read_view == NULL); ut_a(ib_vector_is_empty(trx->autoinc_locks)); /* We allocated a dedicated heap for the vector. */ ib_vector_free(trx->autoinc_locks); + trx_release_descriptor(trx); + mem_free(trx); } @@ -378,7 +499,7 @@ trx_free_prepared( trx_t* trx) /*!< in, own: trx object */ { ut_ad(mutex_own(&kernel_mutex)); - ut_a(trx->conc_state == TRX_PREPARED); + ut_a(trx->state == TRX_PREPARED); ut_a(trx->magic_n == TRX_MAGIC_N); /* Prepared transactions are sort of active; they allow @@ -411,15 +532,19 @@ trx_free_prepared( mem_heap_free(trx->lock_heap); } - if (trx->global_read_view_heap) { - mem_heap_free(trx->global_read_view_heap); - } - ut_a(ib_vector_is_empty(trx->autoinc_locks)); ib_vector_free(trx->autoinc_locks); + trx_release_descriptor(trx); + + if (trx->prebuilt_view != NULL) { + read_view_free(trx->prebuilt_view); + } + UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx); + ut_ad(trx_sys->descr_n_used <= UT_LIST_GET_LEN(trx_sys->trx_list)); + mem_free(trx); } @@ -528,6 +653,7 @@ trx_lists_init_at_db_start(void) ut_ad(mutex_own(&kernel_mutex)); UT_LIST_INIT(trx_sys->trx_list); + UT_LIST_INIT(trx_sys->trx_serial_list); /* Look from the rollback segments if there exist undo logs for transactions */ @@ -564,7 +690,7 @@ trx_lists_init_at_db_start(void) if (srv_force_recovery == 0) { - trx->conc_state = TRX_PREPARED; + trx->state = TRX_PREPARED; trx_n_prepared++; } else { fprintf(stderr, @@ -574,11 +700,12 @@ trx_lists_init_at_db_start(void) " rollback it" " anyway.\n"); - trx->conc_state = TRX_ACTIVE; + trx->state = TRX_ACTIVE; } + + trx_reserve_descriptor(trx); } else { - trx->conc_state - = TRX_COMMITTED_IN_MEMORY; + trx->state = TRX_COMMITTED_IN_MEMORY; } /* We give a dummy value for the trx no; @@ -590,12 +717,15 @@ trx_lists_init_at_db_start(void) trx->no = trx->id; } else { - trx->conc_state = TRX_ACTIVE; + trx->state = TRX_ACTIVE; /* A running transaction always has the number field inited to IB_ULONGLONG_MAX */ trx->no = IB_ULONGLONG_MAX; + + trx_reserve_descriptor(trx); + } if (undo->dict_operation) { @@ -640,7 +770,7 @@ trx_lists_init_at_db_start(void) if (srv_force_recovery == 0) { - trx->conc_state + trx->state = TRX_PREPARED; trx_n_prepared++; } else { @@ -651,11 +781,12 @@ trx_lists_init_at_db_start(void) " rollback it" " anyway.\n"); - trx->conc_state - = TRX_ACTIVE; + trx->state = TRX_ACTIVE; + trx_reserve_descriptor( + trx); } } else { - trx->conc_state + trx->state = TRX_COMMITTED_IN_MEMORY; } @@ -664,13 +795,14 @@ trx_lists_init_at_db_start(void) trx->no = trx->id; } else { - trx->conc_state = TRX_ACTIVE; - + trx->state = TRX_ACTIVE; /* A running transaction always has the number field inited to IB_ULONGLONG_MAX */ trx->no = IB_ULONGLONG_MAX; + + trx_reserve_descriptor(trx); } trx->rseg = rseg; @@ -741,13 +873,15 @@ trx_start_low( if (trx->is_purge) { trx->id = 0; - trx->conc_state = TRX_ACTIVE; + /* Don't reserve a descriptor, since this trx is not added to + trx_list. */ + trx->state = TRX_ACTIVE; trx->start_time = time(NULL); return(TRUE); } - ut_ad(trx->conc_state != TRX_ACTIVE); + ut_ad(trx->state != TRX_ACTIVE); ut_a(rseg_id == ULINT_UNDEFINED); @@ -762,7 +896,10 @@ trx_start_low( trx->rseg = rseg; - trx->conc_state = TRX_ACTIVE; + trx->state = TRX_ACTIVE; + + trx_reserve_descriptor(trx); + trx->start_time = time(NULL); UT_LIST_ADD_FIRST(trx_list, trx_sys->trx_list, trx); @@ -819,6 +956,14 @@ trx_serialisation_number_get( trx->no = trx_sys_get_new_trx_id(); + if (UNIV_LIKELY(trx->is_in_trx_serial_list == 0)) { + + UT_LIST_ADD_LAST(trx_serial_list, trx_sys->trx_serial_list, + trx); + + trx->is_in_trx_serial_list = 1; + } + /* If the rollack segment is not empty then the new trx_t::no can't be less than any trx_t::no already in the rollback segment. User threads only @@ -1000,10 +1145,10 @@ trx_commit_off_kernel( lsn = 0; } - ut_ad(trx->conc_state == TRX_ACTIVE || trx->conc_state == TRX_PREPARED); + ut_ad(trx->state == TRX_ACTIVE || trx->state == TRX_PREPARED); ut_ad(mutex_own(&kernel_mutex)); - if (UNIV_UNLIKELY(trx->conc_state == TRX_PREPARED)) { + if (UNIV_UNLIKELY(trx->state == TRX_PREPARED)) { ut_a(trx_n_prepared > 0); trx_n_prepared--; } @@ -1023,7 +1168,9 @@ trx_commit_off_kernel( committed. */ /*--------------------------------------*/ - trx->conc_state = TRX_COMMITTED_IN_MEMORY; + trx->state = TRX_COMMITTED_IN_MEMORY; + /* The following also removes trx from trx_serial_list */ + trx_release_descriptor(trx); /*--------------------------------------*/ /* If we release kernel_mutex below and we are still doing @@ -1044,7 +1191,6 @@ trx_commit_off_kernel( if (trx->global_read_view) { read_view_close(trx->global_read_view); - mem_heap_empty(trx->global_read_view_heap); trx->global_read_view = NULL; } @@ -1131,7 +1277,7 @@ trx_commit_off_kernel( /* Free all savepoints */ trx_roll_free_all_savepoints(trx); - trx->conc_state = TRX_NOT_STARTED; + trx->state = TRX_NOT_STARTED; trx->rseg = NULL; trx->undo_no = 0; trx->last_sql_stat_start.least_undo_no = 0; @@ -1141,6 +1287,8 @@ trx_commit_off_kernel( UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx); + ut_ad(trx_sys->descr_n_used <= UT_LIST_GET_LEN(trx_sys->trx_list)); + trx->error_state = DB_SUCCESS; } @@ -1159,12 +1307,15 @@ trx_cleanup_at_db_startup( trx_undo_insert_cleanup(trx); } - trx->conc_state = TRX_NOT_STARTED; + trx->state = TRX_NOT_STARTED; + trx_release_descriptor(trx); trx->rseg = NULL; trx->undo_no = 0; trx->last_sql_stat_start.least_undo_no = 0; UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx); + + ut_ad(trx_sys->descr_n_used <= UT_LIST_GET_LEN(trx_sys->trx_list)); } /********************************************************************//** @@ -1178,7 +1329,7 @@ trx_assign_read_view( /*=================*/ trx_t* trx) /*!< in: active transaction */ { - ut_ad(trx->conc_state == TRX_ACTIVE); + ut_ad(trx->state == TRX_ACTIVE); if (trx->read_view) { return(trx->read_view); @@ -1186,11 +1337,9 @@ trx_assign_read_view( mutex_enter(&kernel_mutex); - if (!trx->read_view) { - trx->read_view = read_view_open_now( - trx->id, trx->global_read_view_heap); - trx->global_read_view = trx->read_view; - } + trx->read_view = read_view_open_now(trx->id, trx->prebuilt_view, TRUE); + trx->prebuilt_view = trx->read_view; + trx->global_read_view = trx->read_view; mutex_exit(&kernel_mutex); @@ -1555,7 +1704,7 @@ loop: return; } - if (trx->conc_state == TRX_NOT_STARTED) { + if (trx->state == TRX_NOT_STARTED) { trx_start_low(trx, ULINT_UNDEFINED); } @@ -1851,7 +2000,7 @@ trx_mark_sql_stat_end( { ut_a(trx); - if (trx->conc_state == TRX_NOT_STARTED) { + if (trx->state == TRX_NOT_STARTED) { trx->undo_no = 0; } @@ -1874,7 +2023,7 @@ trx_print( fprintf(f, "TRANSACTION " TRX_ID_FMT, (ullint) trx->id); - switch (trx->conc_state) { + switch (trx->state) { case TRX_NOT_STARTED: fputs(", not started", f); break; @@ -1890,7 +2039,7 @@ trx_print( fputs(", COMMITTED IN MEMORY", f); break; default: - fprintf(f, " state %lu", (ulong) trx->conc_state); + fprintf(f, " state %lu", (ulong) trx->state); } if (*trx->op_info) { @@ -2085,7 +2234,11 @@ trx_prepare_off_kernel( ut_ad(mutex_own(&kernel_mutex)); /*--------------------------------------*/ - trx->conc_state = TRX_PREPARED; + if (UNIV_UNLIKELY(trx->state != TRX_ACTIVE)) { + + trx_reserve_descriptor(trx); + } + trx->state = TRX_PREPARED; trx_n_prepared++; /*--------------------------------------*/ @@ -2199,7 +2352,7 @@ trx_recover_for_mysql( trx = UT_LIST_GET_FIRST(trx_sys->trx_list); while (trx) { - if (trx->conc_state == TRX_PREPARED) { + if (trx->state == TRX_PREPARED) { xid_list[count] = trx->xid; if (count == 0) { @@ -2272,7 +2425,7 @@ trx_get_trx_by_xid( the same */ if (trx->is_recovered - && trx->conc_state == TRX_PREPARED + && trx->state == TRX_PREPARED && xid->gtrid_length == trx->xid.gtrid_length && xid->bqual_length == trx->xid.bqual_length && memcmp(xid->data, trx->xid.data, |