merge Percona-Server-5.5.32-rel31.0.tar.gz

This commit is contained in:
Sergei Golubchik 2013-07-16 19:30:39 +02:00
commit a5b534a08e
48 changed files with 1256 additions and 656 deletions

0
sql-bench/myisam.cnf Normal file → Executable file
View file

View file

@ -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. Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by Portions of this file contain modifications contributed and copyrighted by
@ -1349,27 +1349,13 @@ btr_cur_optimistic_insert(
Subtract one byte for the encoded heap_no in the Subtract one byte for the encoded heap_no in the
modification log. */ modification log. */
ulint free_space_zip = page_zip_empty_size( 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); ulint n_uniq = dict_index_get_n_unique_in_tree(index);
ut_ad(dict_table_is_comp(index->table)); ut_ad(dict_table_is_comp(index->table));
/* There should be enough room for two node pointer if (free_space_zip == 0) {
records on an empty non-leaf page. This prevents too_big:
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 (big_rec_vec) { if (big_rec_vec) {
dtuple_convert_back_big_rec( dtuple_convert_back_big_rec(
index, entry, big_rec_vec); index, entry, big_rec_vec);
@ -1377,6 +1363,27 @@ btr_cur_optimistic_insert(
return(DB_TOO_BIG_RECORD); 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), LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page),

View file

@ -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. Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by Portions of this file contain modifications contributed and copyrighted by
@ -581,6 +581,8 @@ UNIV_INTERN
ibool ibool
buf_page_is_corrupted( buf_page_is_corrupted(
/*==================*/ /*==================*/
ibool check_lsn, /*!< in: TRUE if we need to check
and complain about the LSN */
const byte* read_buf, /*!< in: a database page */ const byte* read_buf, /*!< in: a database page */
ulint zip_size) /*!< in: size of compressed page; ulint zip_size) /*!< in: size of compressed page;
0 for uncompressed pages */ 0 for uncompressed pages */
@ -600,7 +602,7 @@ buf_page_is_corrupted(
} }
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
if (recv_lsn_checks_on) { if (check_lsn && recv_lsn_checks_on) {
ib_uint64_t current_lsn; ib_uint64_t current_lsn;
if (log_peek_lsn(&current_lsn) if (log_peek_lsn(&current_lsn)
@ -1998,7 +2000,7 @@ lookup:
buf_read_page(space, zip_size, offset, trx); buf_read_page(space, zip_size, offset, trx);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(++buf_dbg_counter % 37 || buf_validate()); ut_a(++buf_dbg_counter % 5771 || buf_validate());
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
} }
@ -2556,6 +2558,10 @@ loop2:
retries = 0; retries = 0;
} else if (retries < BUF_PAGE_READ_MAX_RETRIES) { } else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
++retries; ++retries;
DBUG_EXECUTE_IF(
"innodb_page_corruption_retries",
retries = BUF_PAGE_READ_MAX_RETRIES;
);
} else { } else {
fprintf(stderr, "InnoDB: Error: Unable" fprintf(stderr, "InnoDB: Error: Unable"
" to read tablespace %lu page no" " to read tablespace %lu page no"
@ -2577,7 +2583,7 @@ loop2:
} }
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(++buf_dbg_counter % 37 || buf_validate()); ut_a(++buf_dbg_counter % 5771 || buf_validate());
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
goto loop; goto loop;
} }
@ -2593,6 +2599,7 @@ got_block:
/* The page is being read to buffer pool, /* The page is being read to buffer pool,
but we cannot wait around for the read to but we cannot wait around for the read to
complete. */ complete. */
null_exit:
//buf_pool_mutex_exit(buf_pool); //buf_pool_mutex_exit(buf_pool);
mutex_exit(block_mutex); mutex_exit(block_mutex);
@ -2603,7 +2610,6 @@ got_block:
srv_pass_corrupt_table <= 1)) { srv_pass_corrupt_table <= 1)) {
mutex_exit(block_mutex); mutex_exit(block_mutex);
return(NULL); return(NULL);
} }
@ -2622,6 +2628,14 @@ got_block:
case BUF_BLOCK_ZIP_PAGE: case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY: case BUF_BLOCK_ZIP_DIRTY:
ut_ad(block_mutex == &buf_pool->zip_mutex); ut_ad(block_mutex == &buf_pool->zip_mutex);
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; bpage = &block->page;
/* Protect bpage->buf_fix_count. */ /* Protect bpage->buf_fix_count. */
//mutex_enter(&buf_pool->zip_mutex); //mutex_enter(&buf_pool->zip_mutex);
@ -3779,7 +3793,7 @@ buf_page_create(
memset(frame + FIL_PAGE_FILE_FLUSH_LSN, 0, 8); memset(frame + FIL_PAGE_FILE_FLUSH_LSN, 0, 8);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(++buf_dbg_counter % 357 || buf_validate()); ut_a(++buf_dbg_counter % 5771 || buf_validate());
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
#ifdef UNIV_IBUF_COUNT_DEBUG #ifdef UNIV_IBUF_COUNT_DEBUG
ut_a(ibuf_count_get(buf_block_get_space(block), ut_a(ibuf_count_get(buf_block_get_space(block),
@ -3933,7 +3947,7 @@ buf_page_io_complete(
/* From version 3.23.38 up we store the page checksum /* From version 3.23.38 up we store the page checksum
to the 4 first bytes of the page end lsn field */ to the 4 first bytes of the page end lsn field */
if (buf_page_is_corrupted(frame, if (buf_page_is_corrupted(TRUE, frame,
buf_page_get_zip_size(bpage))) { buf_page_get_zip_size(bpage))) {
corrupt: corrupt:
fprintf(stderr, fprintf(stderr,

View file

@ -220,7 +220,7 @@ not_to_recover:
ut_ad(buf_page_in_file(bpage)); ut_ad(buf_page_in_file(bpage));
if(sync) { if (sync) {
thd_wait_begin(NULL, THD_WAIT_DISKIO); thd_wait_begin(NULL, THD_WAIT_DISKIO);
} }

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2011, 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 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 the terms of the GNU General Public License as published by the Free Software
@ -42,6 +42,22 @@ Created 1/8/1996 Heikki Tuuri
#include "trx0roll.h" #include "trx0roll.h"
#include "usr0sess.h" #include "usr0sess.h"
#include "ut0vec.h" #include "ut0vec.h"
#include "ha_prototypes.h"
/*************************************************************************
Checks if a table name contains the string TEMP_TABLE_PATH_PREFIX which
denotes temporary tables in MySQL. */
static
ibool
row_is_mysql_tmp_table_name(
/*========================*/
/* out: TRUE if temporary table */
const char* name) /* in: table name in the form
'database/tablename' */
{
return(strstr(name, TEMP_TABLE_PATH_PREFIX) != NULL);
}
/*****************************************************************//** /*****************************************************************//**
Based on a table object, this function builds the entry to be inserted Based on a table object, this function builds the entry to be inserted
@ -1630,18 +1646,46 @@ dict_create_add_foreign_to_dictionary(
{ {
ulint error; ulint error;
ulint i; ulint i;
pars_info_t* info;
pars_info_t* info = pars_info_create();
if (foreign->id == NULL) { if (foreign->id == NULL) {
/* Generate a new constraint id */ /* Generate a new constraint id */
ulint namelen = strlen(table->name); ulint namelen = strlen(table->name);
char* id = mem_heap_alloc(foreign->heap, namelen + 20); char* id = mem_heap_alloc(foreign->heap, namelen + 20);
/* no overflow if number < 1e13 */
sprintf(id, "%s_ibfk_%lu", table->name, (ulong) (*id_nr)++); if (row_is_mysql_tmp_table_name(table->name)) {
sprintf(id, "%s_ibfk_%lu", table->name,
(ulong) (*id_nr)++);
} else {
char table_name[MAX_TABLE_NAME_LEN + 20] = "";
uint errors = 0;
strncpy(table_name, table->name,
MAX_TABLE_NAME_LEN + 20);
innobase_convert_to_system_charset(
strchr(table_name, '/') + 1,
strchr(table->name, '/') + 1,
MAX_TABLE_NAME_LEN, &errors);
if (errors) {
strncpy(table_name, table->name,
MAX_TABLE_NAME_LEN + 20);
}
sprintf(id, "%s_ibfk_%lu", table_name,
(ulong) (*id_nr)++);
if (innobase_check_identifier_length(
strchr(id,'/') + 1)) {
return(DB_IDENTIFIER_TOO_LONG);
}
}
foreign->id = id; foreign->id = id;
} }
info = pars_info_create();
pars_info_add_str_literal(info, "id", foreign->id); pars_info_add_str_literal(info, "id", foreign->id);
pars_info_add_str_literal(info, "for_name", table->name); pars_info_add_str_literal(info, "for_name", table->name);

View file

@ -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 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 the terms of the GNU General Public License as published by the Free Software
@ -775,8 +775,11 @@ dict_table_get(
/* If table->ibd_file_missing == TRUE, this will /* If table->ibd_file_missing == TRUE, this will
print an error message and return without doing print an error message and return without doing
anything. */ anything. */
dict_update_statistics(table, TRUE /* only update stats dict_update_statistics(
if they have not been initialized */, FALSE); table,
TRUE, /* only update stats if not initialized */
FALSE,
FALSE /* update even if not changed too much */);
} }
return(table); return(table);
@ -1119,22 +1122,78 @@ dict_table_rename_in_cache(
dict_mem_foreign_table_name_lookup_set(foreign, FALSE); dict_mem_foreign_table_name_lookup_set(foreign, FALSE);
} }
if (strchr(foreign->id, '/')) { if (strchr(foreign->id, '/')) {
/* This is a >= 4.0.18 format id */
ulint db_len; ulint db_len;
char* old_id; char* old_id;
char old_name_cs_filename[MAX_TABLE_NAME_LEN+20];
uint errors = 0;
/* This is a >= 4.0.18 format id */ /* All table names are internally stored in charset
my_charset_filename (except the temp tables and the
partition identifier suffix in partition tables). The
foreign key constraint names are internally stored
in UTF-8 charset. The variable fkid here is used
to store foreign key constraint name in charset
my_charset_filename for comparison further below. */
char fkid[MAX_TABLE_NAME_LEN+20];
ibool on_tmp = FALSE;
/* The old table name in my_charset_filename is stored
in old_name_cs_filename */
strncpy(old_name_cs_filename, old_name,
MAX_TABLE_NAME_LEN);
if (strstr(old_name, TEMP_TABLE_PATH_PREFIX) == NULL) {
innobase_convert_to_system_charset(
strchr(old_name_cs_filename, '/') + 1,
strchr(old_name, '/') + 1,
MAX_TABLE_NAME_LEN, &errors);
if (errors) {
/* There has been an error to convert
old table into UTF-8. This probably
means that the old table name is
actually in UTF-8. */
innobase_convert_to_filename_charset(
strchr(old_name_cs_filename,
'/') + 1,
strchr(old_name, '/') + 1,
MAX_TABLE_NAME_LEN);
} else {
/* Old name already in
my_charset_filename */
strncpy(old_name_cs_filename, old_name,
MAX_TABLE_NAME_LEN);
}
}
strncpy(fkid, foreign->id, MAX_TABLE_NAME_LEN);
if (strstr(fkid, TEMP_TABLE_PATH_PREFIX) == NULL) {
innobase_convert_to_filename_charset(
strchr(fkid, '/') + 1,
strchr(foreign->id, '/') + 1,
MAX_TABLE_NAME_LEN+20);
} else {
on_tmp = TRUE;
}
old_id = mem_strdup(foreign->id); old_id = mem_strdup(foreign->id);
if (ut_strlen(foreign->id) > ut_strlen(old_name) if (ut_strlen(fkid) > ut_strlen(old_name_cs_filename)
+ ((sizeof dict_ibfk) - 1) + ((sizeof dict_ibfk) - 1)
&& !memcmp(foreign->id, old_name, && !memcmp(fkid, old_name_cs_filename,
ut_strlen(old_name)) ut_strlen(old_name_cs_filename))
&& !memcmp(foreign->id + ut_strlen(old_name), && !memcmp(fkid + ut_strlen(old_name_cs_filename),
dict_ibfk, (sizeof dict_ibfk) - 1)) { dict_ibfk, (sizeof dict_ibfk) - 1)) {
/* This is a generated >= 4.0.18 format id */ /* This is a generated >= 4.0.18 format id */
char table_name[MAX_TABLE_NAME_LEN] = "";
uint errors = 0;
if (strlen(table->name) > strlen(old_name)) { if (strlen(table->name) > strlen(old_name)) {
foreign->id = mem_heap_alloc( foreign->id = mem_heap_alloc(
foreign->heap, foreign->heap,
@ -1142,11 +1201,36 @@ dict_table_rename_in_cache(
+ strlen(old_id) + 1); + strlen(old_id) + 1);
} }
/* Convert the table name to UTF-8 */
strncpy(table_name, table->name,
MAX_TABLE_NAME_LEN);
innobase_convert_to_system_charset(
strchr(table_name, '/') + 1,
strchr(table->name, '/') + 1,
MAX_TABLE_NAME_LEN, &errors);
if (errors) {
/* Table name could not be converted
from charset my_charset_filename to
UTF-8. This means that the table name
is already in UTF-8 (#mysql#50). */
strncpy(table_name, table->name,
MAX_TABLE_NAME_LEN);
}
/* Replace the prefix 'databasename/tablename' /* Replace the prefix 'databasename/tablename'
with the new names */ with the new names */
strcpy(foreign->id, table->name); strcpy(foreign->id, table_name);
if (on_tmp) {
strcat(foreign->id, strcat(foreign->id,
old_id + ut_strlen(old_name)); old_id + ut_strlen(old_name));
} else {
sprintf(strchr(foreign->id, '/') + 1,
"%s%s",
strchr(table_name, '/') +1,
strstr(old_id, "_ibfk_") );
}
} else { } else {
/* This is a >= 4.0.18 format id where the user /* This is a >= 4.0.18 format id where the user
gave the id name */ gave the id name */
@ -1529,6 +1613,10 @@ dict_index_too_big_for_tree(
/* maximum allowed size of a node pointer record */ /* maximum allowed size of a node pointer record */
ulint page_ptr_max; ulint page_ptr_max;
DBUG_EXECUTE_IF(
"ib_force_create_table",
return(FALSE););
comp = dict_table_is_comp(table); comp = dict_table_is_comp(table);
zip_size = dict_table_zip_size(table); zip_size = dict_table_zip_size(table);
@ -1543,7 +1631,10 @@ dict_index_too_big_for_tree(
number in the page modification log. The maximum number in the page modification log. The maximum
allowed node pointer size is half that. */ allowed node pointer size is half that. */
page_rec_max = page_zip_empty_size(new_index->n_fields, 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; page_ptr_max = page_rec_max / 2;
/* On a compressed page, there is a two-byte entry in /* On a compressed page, there is a two-byte entry in
the dense page directory for every record. But there the dense page directory for every record. But there
@ -4707,7 +4798,12 @@ dict_update_statistics(
update/recalc the stats if they have update/recalc the stats if they have
not been initialized yet, otherwise not been initialized yet, otherwise
do nothing */ do nothing */
ibool sync) /*!< in: TRUE if must update SYS_STATS */ ibool sync, /*!< in: TRUE if must update
SYS_STATS */
ibool only_calc_if_changed_too_much)/*!< in: only
update/recalc the stats if the table
has been changed too much since the
last stats update/recalc */
{ {
dict_index_t* index; dict_index_t* index;
ulint sum_of_index_sizes = 0; ulint sum_of_index_sizes = 0;
@ -4758,7 +4854,10 @@ dict_update_statistics(
dict_table_stats_lock(table, RW_X_LATCH); dict_table_stats_lock(table, RW_X_LATCH);
if (only_calc_if_missing_stats && table->stat_initialized) { if ((only_calc_if_missing_stats && table->stat_initialized)
|| (only_calc_if_changed_too_much
&& !DICT_TABLE_CHANGED_TOO_MUCH(table))) {
dict_table_stats_unlock(table, RW_X_LATCH); dict_table_stats_unlock(table, RW_X_LATCH);
return; return;
} }
@ -5000,8 +5099,14 @@ dict_table_print_low(
ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(mutex_own(&(dict_sys->mutex)));
if (srv_stats_auto_update) if (srv_stats_auto_update) {
dict_update_statistics(table, FALSE /* update even if initialized */, FALSE);
dict_update_statistics(
table,
FALSE /* update even if initialized */,
FALSE,
FALSE /* update even if not changed too much */);
}
dict_table_stats_lock(table, RW_S_LATCH); dict_table_stats_lock(table, RW_S_LATCH);

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved. Copyright (c) 1996, 2013, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@ -354,8 +354,11 @@ dict_process_sys_tables_rec(
/* Update statistics if DICT_TABLE_UPDATE_STATS /* Update statistics if DICT_TABLE_UPDATE_STATS
is set */ is set */
dict_update_statistics(*table, FALSE /* update even if dict_update_statistics(
initialized */, FALSE); *table,
FALSE, /* update even if initialized */
FALSE,
FALSE /* update even if not changed too much */);
} }
return(NULL); return(NULL);

View file

@ -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 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 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. 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 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 this program; if not, write to the Free Software Foundation, Inc.,
Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/ *****************************************************************************/
@ -35,7 +35,7 @@ UNIV_INTERN
dyn_block_t* dyn_block_t*
dyn_array_add_block( dyn_array_add_block(
/*================*/ /*================*/
dyn_array_t* arr) /*!< in: dyn array */ dyn_array_t* arr) /*!< in/out: dyn array */
{ {
mem_heap_t* heap; mem_heap_t* heap;
dyn_block_t* block; dyn_block_t* block;

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2010, Innobase Oy. 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 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 the terms of the GNU General Public License as published by the Free Software
@ -681,7 +681,7 @@ fil_node_open_file(
fil_system_t* system, /*!< in: tablespace memory cache */ fil_system_t* system, /*!< in: tablespace memory cache */
fil_space_t* space) /*!< in: space */ fil_space_t* space) /*!< in: space */
{ {
ib_uint64_t size_bytes; ib_int64_t size_bytes;
ulint size_low; ulint size_low;
ulint size_high; ulint size_high;
ibool ret; ibool ret;
@ -723,8 +723,8 @@ fil_node_open_file(
os_file_get_size(node->handle, &size_low, &size_high); os_file_get_size(node->handle, &size_low, &size_high);
size_bytes = (((ib_uint64_t)size_high) << 32) size_bytes = (((ib_int64_t)size_high) << 32)
+ (ib_uint64_t)size_low; + (ib_int64_t)size_low;
#ifdef UNIV_HOTBACKUP #ifdef UNIV_HOTBACKUP
if (trx_sys_sys_space(space->id)) { if (trx_sys_sys_space(space->id)) {
node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE); node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
@ -735,7 +735,7 @@ fil_node_open_file(
ut_a(space->purpose != FIL_LOG); ut_a(space->purpose != FIL_LOG);
ut_a(!trx_sys_sys_space(space->id)); ut_a(!trx_sys_sys_space(space->id));
if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) { if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Error: the size of single-table" "InnoDB: Error: the size of single-table"
" tablespace file %s\n" " tablespace file %s\n"
@ -1883,11 +1883,63 @@ fil_write_flushed_lsn_to_data_files(
return(DB_SUCCESS); return(DB_SUCCESS);
} }
/*******************************************************************//**
Checks the consistency of the first data page of a data file
at database startup.
@retval NULL on success, or if innodb_force_recovery is set
@return pointer to an error message string */
static __attribute__((warn_unused_result))
const char*
fil_check_first_page(
/*=================*/
const page_t* page, /*!< in: data page */
ibool first_page) /*!< in: TRUE if this is the
first page of the tablespace */
{
ulint space_id;
ulint flags;
if (srv_force_recovery >= SRV_FORCE_IGNORE_CORRUPT) {
return(NULL);
}
space_id = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page);
flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page);
if (first_page && !space_id && !flags) {
ulint nonzero_bytes = UNIV_PAGE_SIZE;
const byte* b = page;
while (!*b && --nonzero_bytes) {
b++;
}
if (!nonzero_bytes) {
return("space header page consists of zero bytes");
}
}
if (buf_page_is_corrupted(
FALSE, page, dict_table_flags_to_zip_size(flags))) {
return("checksum mismatch");
}
if (!first_page
|| (page_get_space_id(page) == space_id
&& page_get_page_no(page) == 0)) {
return(NULL);
}
return("inconsistent data in space header");
}
/*******************************************************************//** /*******************************************************************//**
Reads the flushed lsn, arch no, and tablespace flag fields from a data Reads the flushed lsn, arch no, and tablespace flag fields from a data
file at database startup. */ file at database startup.
@retval NULL on success, or if innodb_force_recovery is set
@return pointer to an error message string */
UNIV_INTERN UNIV_INTERN
void const char*
fil_read_first_page( fil_read_first_page(
/*================*/ /*================*/
os_file_t data_file, /*!< in: open data file */ os_file_t data_file, /*!< in: open data file */
@ -1909,6 +1961,7 @@ fil_read_first_page(
byte* buf; byte* buf;
page_t* page; page_t* page;
ib_uint64_t flushed_lsn; ib_uint64_t flushed_lsn;
const char* check_msg;
buf = ut_malloc(2 * UNIV_PAGE_SIZE); buf = ut_malloc(2 * UNIV_PAGE_SIZE);
/* Align the memory for a possible read from a raw device */ /* Align the memory for a possible read from a raw device */
@ -1916,13 +1969,18 @@ fil_read_first_page(
os_file_read(data_file, page, 0, 0, UNIV_PAGE_SIZE); os_file_read(data_file, page, 0, 0, UNIV_PAGE_SIZE);
*flags = mach_read_from_4(page + *flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page);
FSP_HEADER_OFFSET + FSP_SPACE_FLAGS);
flushed_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN); flushed_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN);
check_msg = fil_check_first_page(page, !one_read_already);
ut_free(buf); ut_free(buf);
if (check_msg) {
return(check_msg);
}
if (!one_read_already) { if (!one_read_already) {
*min_flushed_lsn = flushed_lsn; *min_flushed_lsn = flushed_lsn;
*max_flushed_lsn = flushed_lsn; *max_flushed_lsn = flushed_lsn;
@ -1930,7 +1988,7 @@ fil_read_first_page(
*min_arch_log_no = arch_log_no; *min_arch_log_no = arch_log_no;
*max_arch_log_no = arch_log_no; *max_arch_log_no = arch_log_no;
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
return; return(NULL);
} }
if (*min_flushed_lsn > flushed_lsn) { if (*min_flushed_lsn > flushed_lsn) {
@ -1947,6 +2005,8 @@ fil_read_first_page(
*max_arch_log_no = arch_log_no; *max_arch_log_no = arch_log_no;
} }
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
return(NULL);
} }
/*================ SINGLE-TABLE TABLESPACES ==========================*/ /*================ SINGLE-TABLE TABLESPACES ==========================*/
@ -3271,6 +3331,7 @@ fil_open_single_table_tablespace(
os_file_t file; os_file_t file;
char* filepath; char* filepath;
ibool success; ibool success;
const char* check_msg;
byte* buf2; byte* buf2;
byte* page; byte* page;
ulint space_id; ulint space_id;
@ -3331,6 +3392,8 @@ fil_open_single_table_tablespace(
success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE); success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE);
check_msg = fil_check_first_page(page, TRUE);
/* We have to read the tablespace id and flags from the file. */ /* We have to read the tablespace id and flags from the file. */
space_id = fsp_header_get_space_id(page); space_id = fsp_header_get_space_id(page);
@ -3366,7 +3429,7 @@ fil_open_single_table_tablespace(
current_lsn = log_get_lsn(); current_lsn = log_get_lsn();
/* check the header page's consistency */ /* check the header page's consistency */
if (buf_page_is_corrupted(page, if (buf_page_is_corrupted(TRUE, page,
dict_table_flags_to_zip_size(space_flags))) { dict_table_flags_to_zip_size(space_flags))) {
fprintf(stderr, "InnoDB: page 0 of %s seems corrupt.\n", filepath); fprintf(stderr, "InnoDB: page 0 of %s seems corrupt.\n", filepath);
file_is_corrupt = TRUE; file_is_corrupt = TRUE;
@ -3788,8 +3851,20 @@ skip_write:
ut_free(buf2); ut_free(buf2);
if (UNIV_UNLIKELY(space_id != id if (check_msg) {
|| space_flags != (flags & ~(~0 << DICT_TF_BITS)))) { ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Error: %s in file ", check_msg);
ut_print_filename(stderr, filepath);
fprintf(stderr, " (tablespace id=%lu, flags=%lu)\n"
"InnoDB: Please refer to " REFMAN
"innodb-troubleshooting-datadict.html\n",
(ulong) id, (ulong) flags);
success = FALSE;
goto func_exit;
}
if (space_id != id
|| space_flags != (flags & ~(~0 << DICT_TF_BITS))) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fputs(" InnoDB: Error: tablespace id and flags in file ", fputs(" InnoDB: Error: tablespace id and flags in file ",
@ -4136,7 +4211,7 @@ fil_load_single_table_tablespace(
ulint flags; ulint flags;
ulint size_low; ulint size_low;
ulint size_high; ulint size_high;
ib_uint64_t size; ib_int64_t size;
#ifdef UNIV_HOTBACKUP #ifdef UNIV_HOTBACKUP
fil_space_t* space; fil_space_t* space;
#endif #endif
@ -4257,9 +4332,9 @@ fil_load_single_table_tablespace(
/* Every .ibd file is created >= 4 pages in size. Smaller files /* Every .ibd file is created >= 4 pages in size. Smaller files
cannot be ok. */ cannot be ok. */
size = (((ib_uint64_t)size_high) << 32) + (ib_uint64_t)size_low; size = (((ib_int64_t)size_high) << 32) + (ib_int64_t)size_low;
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
if (size < (ib_uint64_t)FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) { if (size < FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Error: the size of single-table tablespace" "InnoDB: Error: the size of single-table tablespace"
" file %s\n" " file %s\n"
@ -4279,11 +4354,22 @@ fil_load_single_table_tablespace(
/* Align the memory for file i/o if we might have O_DIRECT set */ /* Align the memory for file i/o if we might have O_DIRECT set */
page = ut_align(buf2, UNIV_PAGE_SIZE); page = ut_align(buf2, UNIV_PAGE_SIZE);
if (size >= FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) { if (size >= FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) {
const char* check_msg;
success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE); success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE);
/* We have to read the tablespace id from the file */ /* We have to read the tablespace id from the file */
check_msg = fil_check_first_page(page, TRUE);
if (check_msg) {
fprintf(stderr,
"InnoDB: Error: %s in file %s",
check_msg, filepath);
goto func_exit;
}
space_id = fsp_header_get_space_id(page); space_id = fsp_header_get_space_id(page);
flags = fsp_header_get_flags(page); flags = fsp_header_get_flags(page);
} else { } else {
@ -4863,8 +4949,10 @@ fil_extend_space_to_desired_size(
#ifdef HAVE_POSIX_FALLOCATE #ifdef HAVE_POSIX_FALLOCATE
if (srv_use_posix_fallocate) { if (srv_use_posix_fallocate) {
offset_high = size_after_extend * page_size / (4ULL*1024*1024*1024); offset_high = (size_after_extend - file_start_page_no)
offset_low = size_after_extend * page_size % (4ULL*1024*1024*1024); * page_size / (4ULL * 1024 * 1024 * 1024);
offset_low = (size_after_extend - file_start_page_no)
* page_size % (4ULL * 1024 * 1024 * 1024);
mutex_exit(&fil_system->mutex); mutex_exit(&fil_system->mutex);
success = os_file_set_size(node->name, node->handle, success = os_file_set_size(node->name, node->handle,
@ -4935,12 +5023,12 @@ fil_extend_space_to_desired_size(
mem_free(buf2); mem_free(buf2);
fil_node_complete_io(node, fil_system, OS_FILE_WRITE);
#ifdef HAVE_POSIX_FALLOCATE #ifdef HAVE_POSIX_FALLOCATE
complete_io: complete_io:
#endif #endif
fil_node_complete_io(node, fil_system, OS_FILE_WRITE);
*actual_size = space->size; *actual_size = space->size;
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP

View file

@ -2910,15 +2910,15 @@ fsp_reserve_free_pages(
ulint space, /*!< in: space id, must be != 0 */ ulint space, /*!< in: space id, must be != 0 */
fsp_header_t* space_header, /*!< in: header of that space, fsp_header_t* space_header, /*!< in: header of that space,
x-latched */ x-latched */
ulint size, /*!< in: size of the tablespace in pages, ulint size, /*!< in: size of the tablespace in
must be < FSP_EXTENT_SIZE / 2 */ pages, must be < FSP_EXTENT_SIZE */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
{ {
xdes_t* descr; xdes_t* descr;
ulint n_used; ulint n_used;
ut_a(space != 0); ut_a(space != 0);
ut_a(size < FSP_EXTENT_SIZE / 2); ut_a(size < FSP_EXTENT_SIZE);
descr = xdes_get_descriptor_with_space_hdr(space_header, space, 0, descr = xdes_get_descriptor_with_space_hdr(space_header, space, 0,
mtr); mtr);
@ -3001,7 +3001,7 @@ fsp_reserve_free_extents(
try_again: try_again:
size = mtr_read_ulint(space_header + FSP_SIZE, MLOG_4BYTES, mtr); size = mtr_read_ulint(space_header + FSP_SIZE, MLOG_4BYTES, mtr);
if (size < FSP_EXTENT_SIZE / 2) { if (size < FSP_EXTENT_SIZE) {
/* Use different rules for small single-table tablespaces */ /* Use different rules for small single-table tablespaces */
*n_reserved = 0; *n_reserved = 0;
return(fsp_reserve_free_pages(space, space_header, size, mtr)); return(fsp_reserve_free_pages(space, space_header, size, mtr));
@ -3016,11 +3016,8 @@ try_again:
some of them will contain extent descriptor pages, and therefore some of them will contain extent descriptor pages, and therefore
will not be free extents */ will not be free extents */
if (size <= free_limit) { ut_ad(size >= free_limit);
n_free_up = 0;
} else {
n_free_up = (size - free_limit) / FSP_EXTENT_SIZE; n_free_up = (size - free_limit) / FSP_EXTENT_SIZE;
}
if (n_free_up > 0) { if (n_free_up > 0) {
n_free_up--; n_free_up--;

View file

@ -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) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc. Copyright (c) 2009, Percona Inc.
@ -124,7 +124,6 @@ static mysql_cond_t commit_cond;
static mysql_mutex_t commit_cond_m; static mysql_mutex_t commit_cond_m;
static bool innodb_inited = 0; static bool innodb_inited = 0;
#define INSIDE_HA_INNOBASE_CC #define INSIDE_HA_INNOBASE_CC
/* In the Windows plugin, the return value of current_thd is /* In the Windows plugin, the return value of current_thd is
@ -206,7 +205,6 @@ static uint innobase_buffer_pool_shm_key = 0;
static ulint srv_lazy_drop_table = 0; static ulint srv_lazy_drop_table = 0;
static char* internal_innobase_data_file_path = NULL; static char* internal_innobase_data_file_path = NULL;
static char* innodb_version_str = (char*) INNODB_VERSION_STR; static char* innodb_version_str = (char*) INNODB_VERSION_STR;
@ -874,6 +872,10 @@ static SHOW_VAR innodb_status_variables[]= {
(char*) &export_vars.innodb_rows_read, SHOW_LONG}, (char*) &export_vars.innodb_rows_read, SHOW_LONG},
{"rows_updated", {"rows_updated",
(char*) &export_vars.innodb_rows_updated, SHOW_LONG}, (char*) &export_vars.innodb_rows_updated, SHOW_LONG},
{"read_views_memory",
(char*) &export_vars.innodb_read_views_memory, SHOW_LONG},
{"descriptors_memory",
(char*) &export_vars.innodb_descriptors_memory, SHOW_LONG},
{"s_lock_os_waits", {"s_lock_os_waits",
(char*) &export_vars.innodb_s_lock_os_waits, SHOW_LONGLONG}, (char*) &export_vars.innodb_s_lock_os_waits, SHOW_LONGLONG},
{"s_lock_spin_rounds", {"s_lock_spin_rounds",
@ -1300,6 +1302,8 @@ convert_error_code_to_mysql(
return(HA_ERR_UNDO_REC_TOO_BIG); return(HA_ERR_UNDO_REC_TOO_BIG);
case DB_OUT_OF_MEMORY: case DB_OUT_OF_MEMORY:
return(HA_ERR_OUT_OF_MEM); return(HA_ERR_OUT_OF_MEM);
case DB_IDENTIFIER_TOO_LONG:
return(HA_ERR_INTERNAL_ERROR);
} }
} }
@ -1380,6 +1384,31 @@ innobase_convert_from_table_id(
strconvert(cs, from, &my_charset_filename, to, (uint) len, &errors); strconvert(cs, from, &my_charset_filename, to, (uint) len, &errors);
} }
/**********************************************************************
Check if the length of the identifier exceeds the maximum allowed.
return true when length of identifier is too long. */
extern "C"
my_bool
innobase_check_identifier_length(
/*=============================*/
const char* id) /* in: FK identifier to check excluding the
database portion. */
{
int well_formed_error = 0;
CHARSET_INFO *cs = system_charset_info;
DBUG_ENTER("innobase_check_identifier_length");
uint res = cs->cset->well_formed_len(cs, id, id + strlen(id),
NAME_CHAR_LEN,
&well_formed_error);
if (well_formed_error || res == NAME_CHAR_LEN) {
my_error(ER_TOO_LONG_IDENT, MYF(0), id);
DBUG_RETURN(true);
}
DBUG_RETURN(false);
}
/******************************************************************//** /******************************************************************//**
Converts an identifier to UTF-8. */ Converts an identifier to UTF-8. */
extern "C" UNIV_INTERN extern "C" UNIV_INTERN
@ -3076,25 +3105,29 @@ innobase_change_buffering_inited_ok:
/* Force doublewrite buffer off, atomic writes replace it. */ /* Force doublewrite buffer off, atomic writes replace it. */
if (srv_use_doublewrite_buf) { if (srv_use_doublewrite_buf) {
fprintf(stderr, "InnoDB: Switching off doublewrite buffer " fprintf(stderr,
"InnoDB: Switching off doublewrite buffer "
"because of atomic writes.\n"); "because of atomic writes.\n");
innobase_use_doublewrite = srv_use_doublewrite_buf = FALSE; innobase_use_doublewrite = FALSE;
srv_use_doublewrite_buf = FALSE;
} }
/* Force O_DIRECT on Unixes (on Windows writes are always unbuffered)*/ /* Force O_DIRECT on Unixes (on Windows writes are always
unbuffered)*/
#ifndef _WIN32 #ifndef _WIN32
if(!innobase_file_flush_method || if(!innobase_file_flush_method ||
!strstr(innobase_file_flush_method, "O_DIRECT")) { !strstr(innobase_file_flush_method, "O_DIRECT")) {
innobase_file_flush_method = innobase_file_flush_method =
srv_file_flush_method_str = (char*)"O_DIRECT"; srv_file_flush_method_str = (char*)"O_DIRECT";
fprintf(stderr, "InnoDB: using O_DIRECT due to atomic writes.\n"); fprintf(stderr,
"InnoDB: using O_DIRECT due to atomic "
"writes.\n");
} }
#endif #endif
#ifdef HAVE_POSIX_FALLOCATE #ifdef HAVE_POSIX_FALLOCATE
/* Due to a bug in directFS, using atomics needs /* Due to a bug in directFS, using atomics needs
* posix_fallocate to extend the file posix_fallocate() to extend the file, because pwrite() past the
* pwrite() past end of the file won't work end of the file won't work */
*/
srv_use_posix_fallocate = TRUE; srv_use_posix_fallocate = TRUE;
#endif #endif
} }
@ -4544,7 +4577,6 @@ ha_innobase::open(
dict_table_t* ib_table; dict_table_t* ib_table;
char norm_name[1000]; char norm_name[1000];
THD* thd; THD* thd;
ulint retries = 0;
char* is_part = NULL; char* is_part = NULL;
ibool par_case_name_set = FALSE; ibool par_case_name_set = FALSE;
char par_case_name[MAX_FULL_NAME_LEN + 1]; char par_case_name[MAX_FULL_NAME_LEN + 1];
@ -4584,17 +4616,13 @@ ha_innobase::open(
upd_buf_size = 0; upd_buf_size = 0;
/* We look for pattern #P# to see if the table is partitioned /* We look for pattern #P# to see if the table is partitioned
MySQL table. The retry logic for partitioned tables is a MySQL table. */
workaround for http://bugs.mysql.com/bug.php?id=33349. Look
at support issue https://support.mysql.com/view.php?id=21080
for more details. */
#ifdef __WIN__ #ifdef __WIN__
is_part = strstr(norm_name, "#p#"); is_part = strstr(norm_name, "#p#");
#else #else
is_part = strstr(norm_name, "#P#"); is_part = strstr(norm_name, "#P#");
#endif /* __WIN__ */ #endif /* __WIN__ */
retry:
/* Get pointer to a table object in InnoDB dictionary cache */ /* Get pointer to a table object in InnoDB dictionary cache */
ib_table = dict_table_get(norm_name, TRUE); ib_table = dict_table_get(norm_name, TRUE);
@ -4611,7 +4639,7 @@ retry:
share->ib_table = ib_table; share->ib_table = ib_table;
if (NULL == ib_table) { if (NULL == ib_table) {
if (is_part && retries < 10) { if (is_part) {
/* MySQL partition engine hard codes the file name /* MySQL partition engine hard codes the file name
separator as "#P#". The text case is fixed even if separator as "#P#". The text case is fixed even if
lower_case_table_names is set to 1 or 2. This is true lower_case_table_names is set to 1 or 2. This is true
@ -4654,11 +4682,7 @@ retry:
ib_table = dict_table_get( ib_table = dict_table_get(
par_case_name, FALSE); par_case_name, FALSE);
} }
if (!ib_table) { if (ib_table) {
++retries;
os_thread_sleep(100000);
goto retry;
} else {
#ifndef __WIN__ #ifndef __WIN__
sql_print_warning("Partition table %s opened " sql_print_warning("Partition table %s opened "
"after converting to lower " "after converting to lower "
@ -4684,9 +4708,8 @@ retry:
} }
if (is_part) { if (is_part) {
sql_print_error("Failed to open table %s after " sql_print_error("Failed to open table %s.\n",
"%lu attempts.\n", norm_name, norm_name);
retries);
} }
sql_print_error("Cannot find or open table %s from\n" sql_print_error("Cannot find or open table %s from\n"
@ -6663,6 +6686,8 @@ ha_innobase::unlock_row(void)
{ {
DBUG_ENTER("ha_innobase::unlock_row"); DBUG_ENTER("ha_innobase::unlock_row");
ut_ad(prebuilt->trx->state == TRX_ACTIVE);
/* Consistent read does not take any locks, thus there is /* Consistent read does not take any locks, thus there is
nothing to unlock. */ nothing to unlock. */
@ -8710,12 +8735,18 @@ innobase_rename_table(
DEBUG_SYNC_C("innodb_rename_table_ready"); DEBUG_SYNC_C("innodb_rename_table_ready");
/* Serialize data dictionary operations with dictionary mutex: /* 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) { if (lock_and_commit) {
row_mysql_lock_data_dictionary(trx); 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( error = row_rename_table_for_mysql(
norm_from, norm_to, trx, lock_and_commit); norm_from, norm_to, trx, lock_and_commit);
@ -9268,9 +9299,11 @@ ha_innobase::info_low(
prebuilt->trx->op_info = "updating table statistics"; prebuilt->trx->op_info = "updating table statistics";
dict_update_statistics(ib_table, dict_update_statistics(
FALSE /* update even if stats ib_table,
are initialized */, called_from_analyze); FALSE, /* update even if initialized */
called_from_analyze,
FALSE /* update even if not changed too much */);
prebuilt->trx->op_info = "returning various info to MySQL"; prebuilt->trx->op_info = "returning various info to MySQL";
} }
@ -12503,6 +12536,63 @@ innodb_change_buffering_update(
*static_cast<const char*const*>(save); *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);
mutex_enter(&buf_pool->LRU_list_mutex);
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, FALSE);
mutex_exit(&block->mutex);
block = prev_block;
}
mutex_exit(&buf_pool->LRU_list_mutex);
//buf_pool_mutex_exit(buf_pool);
}
}
}
}
#endif /* !DBUG_OFF */
static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff) static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff)
{ {
innodb_export_status(); innodb_export_status();
@ -12666,9 +12756,9 @@ static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
static MYSQL_SYSVAR_BOOL(use_atomic_writes, innobase_use_atomic_writes, static MYSQL_SYSVAR_BOOL(use_atomic_writes, innobase_use_atomic_writes,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Prevent partial page writes, via atomic writes." "Prevent partial page writes, via atomic writes (beta). "
"The option is used to prevent partial writes in case of a crash/poweroff, " "The option is used to prevent partial writes in case of a crash/poweroff, "
"as faster alternative to doublewrite buffer." "as faster alternative to doublewrite buffer. "
"Currently this option works only " "Currently this option works only "
"on Linux only with FusionIO device, and directFS filesystem.", "on Linux only with FusionIO device, and directFS filesystem.",
NULL, NULL, FALSE); NULL, NULL, FALSE);
@ -12890,6 +12980,13 @@ static MYSQL_SYSVAR_ULONG(autoextend_increment, srv_auto_extend_increment,
"Data file autoextend increment in megabytes", "Data file autoextend increment in megabytes",
NULL, NULL, 8L, 1L, 1000L, 0); 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, static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
@ -13307,6 +13404,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(log_block_size), MYSQL_SYSVAR(log_block_size),
MYSQL_SYSVAR(additional_mem_pool_size), MYSQL_SYSVAR(additional_mem_pool_size),
MYSQL_SYSVAR(autoextend_increment), MYSQL_SYSVAR(autoextend_increment),
#ifndef DBUG_OFF
MYSQL_SYSVAR(buffer_pool_evict),
#endif /* !DBUG_OFF */
MYSQL_SYSVAR(buffer_pool_size), MYSQL_SYSVAR(buffer_pool_size),
MYSQL_SYSVAR(buffer_pool_populate), MYSQL_SYSVAR(buffer_pool_populate),
MYSQL_SYSVAR(buffer_pool_instances), MYSQL_SYSVAR(buffer_pool_instances),
@ -13607,6 +13707,58 @@ test_innobase_convert_name()
#endif /* UNIV_COMPILE_TEST_FUNCS */ #endif /* UNIV_COMPILE_TEST_FUNCS */
/**********************************************************************
Converts an identifier from my_charset_filename to UTF-8 charset. */
extern "C"
uint
innobase_convert_to_filename_charset(
/*=================================*/
char* to, /* out: converted identifier */
const char* from, /* in: identifier to convert */
ulint len) /* in: length of 'to', in bytes */
{
uint errors;
uint rlen;
CHARSET_INFO* cs_to = &my_charset_filename;
CHARSET_INFO* cs_from = system_charset_info;
rlen = strconvert(cs_from, from, cs_to, to, len, &errors);
if (errors) {
fprintf(stderr, "InnoDB: There was a problem in converting"
"'%s' in charset %s to charset %s", from, cs_from->name,
cs_to->name);
}
return(rlen);
}
/**********************************************************************
Converts an identifier from my_charset_filename to UTF-8 charset. */
extern "C"
uint
innobase_convert_to_system_charset(
/*===============================*/
char* to, /* out: converted identifier */
const char* from, /* in: identifier to convert */
ulint len, /* in: length of 'to', in bytes */
uint* errors) /* out: error return */
{
uint rlen;
CHARSET_INFO* cs1 = &my_charset_filename;
CHARSET_INFO* cs2 = system_charset_info;
rlen = strconvert(cs1, from, cs2, to, len, errors);
if (*errors) {
fprintf(stderr, "InnoDB: There was a problem in converting"
"'%s' in charset %s to charset %s", from, cs1->name,
cs2->name);
}
return(rlen);
}
/**************************************************************************** /****************************************************************************
* DS-MRR implementation * DS-MRR implementation

View file

@ -53,7 +53,7 @@ extern "C" {
#include "dict0mem.h" #include "dict0mem.h"
#include "dict0types.h" #include "dict0types.h"
#include "ha_prototypes.h" /* for innobase_convert_name() */ #include "ha_prototypes.h" /* for innobase_convert_name() */
#include "srv0srv.h" /* for srv_track_changed_pages */ #include "srv0srv.h" /* for srv_max_changed_pages */
#include "srv0start.h" /* for srv_was_started */ #include "srv0start.h" /* for srv_was_started */
#include "trx0i_s.h" #include "trx0i_s.h"
#include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */ #include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
@ -2273,6 +2273,7 @@ i_s_innodb_buffer_stats_fill_table(
buf_pool_info_t* pool_info; buf_pool_info_t* pool_info;
DBUG_ENTER("i_s_innodb_buffer_fill_general"); 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 */ /* Only allow the PROCESS privilege holder to access the stats */
if (check_global_access(thd, PROCESS_ACL, true)) { if (check_global_access(thd, PROCESS_ACL, true)) {
@ -2883,6 +2884,7 @@ i_s_innodb_fill_buffer_pool(
mem_heap_t* heap; mem_heap_t* heap;
DBUG_ENTER("i_s_innodb_fill_buffer_pool"); DBUG_ENTER("i_s_innodb_fill_buffer_pool");
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
heap = mem_heap_create(10000); heap = mem_heap_create(10000);
@ -2923,6 +2925,7 @@ i_s_innodb_fill_buffer_pool(
i_s_innodb_buffer_page_get_info( i_s_innodb_buffer_page_get_info(
&block->page, pool_id, block_id, &block->page, pool_id, block_id,
info_buffer + num_page); info_buffer + num_page);
if (block_mutex)
mutex_exit(block_mutex); mutex_exit(block_mutex);
block_id++; block_id++;
num_page++; num_page++;
@ -3443,7 +3446,6 @@ i_s_innodb_fill_buffer_lru(
mutex_t* block_mutex; mutex_t* block_mutex;
DBUG_ENTER("i_s_innodb_fill_buffer_lru"); DBUG_ENTER("i_s_innodb_fill_buffer_lru");
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
/* Obtain buf_pool mutex before allocate info_buffer, since /* Obtain buf_pool mutex before allocate info_buffer, since
@ -7332,6 +7334,7 @@ i_s_innodb_changed_pages_fill(
ib_uint64_t output_rows_num = 0UL; ib_uint64_t output_rows_num = 0UL;
ib_uint64_t max_lsn = IB_ULONGLONG_MAX; ib_uint64_t max_lsn = IB_ULONGLONG_MAX;
ib_uint64_t min_lsn = 0ULL; ib_uint64_t min_lsn = 0ULL;
int ret = 0;
DBUG_ENTER("i_s_innodb_changed_pages_fill"); DBUG_ENTER("i_s_innodb_changed_pages_fill");
@ -7343,10 +7346,6 @@ i_s_innodb_changed_pages_fill(
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
if (!srv_track_changed_pages) {
DBUG_RETURN(0);
}
if (cond) { if (cond) {
limit_lsn_range_from_condition(table, cond, &min_lsn, limit_lsn_range_from_condition(table, cond, &min_lsn,
&max_lsn); &max_lsn);
@ -7422,8 +7421,13 @@ i_s_innodb_changed_pages_fill(
++output_rows_num; ++output_rows_num;
} }
if (i.failed) {
my_error(ER_CANT_FIND_SYSTEM_REC, MYF(0));
ret = 1;
}
log_online_bitmap_iterator_release(&i); log_online_bitmap_iterator_release(&i);
DBUG_RETURN(0); DBUG_RETURN(ret);
} }
static static

View file

@ -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 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 the terms of the GNU General Public License as published by the Free Software
@ -4319,7 +4319,7 @@ Deletes from ibuf the record on which pcur is positioned. If we have to
resort to a pessimistic delete, this function commits mtr and closes resort to a pessimistic delete, this function commits mtr and closes
the cursor. the cursor.
@return TRUE if mtr was committed and pcur closed in this operation */ @return TRUE if mtr was committed and pcur closed in this operation */
static static __attribute__((warn_unused_result))
ibool ibool
ibuf_delete_rec( ibuf_delete_rec(
/*============*/ /*============*/
@ -4625,6 +4625,12 @@ ibuf_merge_or_delete_for_page(
loop: loop:
ibuf_mtr_start(&mtr); ibuf_mtr_start(&mtr);
/* Position pcur in the insert buffer at the first entry for this
index page */
btr_pcur_open_on_user_rec(
ibuf->index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF,
&pcur, &mtr);
if (block) { if (block) {
ibool success; ibool success;
@ -4643,12 +4649,6 @@ loop:
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE); buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
} }
/* Position pcur in the insert buffer at the first entry for this
index page */
btr_pcur_open_on_user_rec(
ibuf->index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF,
&pcur, &mtr);
if (!btr_pcur_is_on_user_rec(&pcur)) { if (!btr_pcur_is_on_user_rec(&pcur)) {
ut_ad(btr_pcur_is_after_last_in_tree(&pcur, &mtr)); ut_ad(btr_pcur_is_after_last_in_tree(&pcur, &mtr));
@ -4733,6 +4733,16 @@ loop:
== page_no); == page_no);
ut_ad(ibuf_rec_get_space(&mtr, rec) == space); 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); btr_pcur_store_position(&pcur, &mtr);
ibuf_btr_pcur_commit_specify_mtr(&pcur, &mtr); ibuf_btr_pcur_commit_specify_mtr(&pcur, &mtr);
@ -4781,6 +4791,7 @@ loop:
/* Deletion was pessimistic and mtr was committed: /* Deletion was pessimistic and mtr was committed:
we start from the beginning again */ we start from the beginning again */
ut_ad(mtr.state == MTR_COMMITTED);
goto loop; goto loop;
} else if (btr_pcur_is_after_last_on_page(&pcur)) { } else if (btr_pcur_is_after_last_on_page(&pcur)) {
ibuf_mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
@ -4911,6 +4922,7 @@ loop:
/* Deletion was pessimistic and mtr was committed: /* Deletion was pessimistic and mtr was committed:
we start from the beginning again */ we start from the beginning again */
ut_ad(mtr.state == MTR_COMMITTED);
goto loop; goto loop;
} }

View file

@ -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 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 the terms of the GNU General Public License as published by the Free Software
@ -684,9 +684,12 @@ UNIV_INTERN
ibool ibool
buf_page_is_corrupted( buf_page_is_corrupted(
/*==================*/ /*==================*/
ibool check_lsn, /*!< in: TRUE if we need to check
and complain about the LSN */
const byte* read_buf, /*!< in: a database page */ const byte* read_buf, /*!< in: a database page */
ulint zip_size); /*!< in: size of compressed page; ulint zip_size) /*!< in: size of compressed page;
0 for uncompressed pages */ 0 for uncompressed pages */
__attribute__((warn_unused_result));
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
/**********************************************************************//** /**********************************************************************//**
Gets the space id, page offset, and byte offset within page of a Gets the space id, page offset, and byte offset within page of a

View file

@ -114,6 +114,7 @@ enum db_err {
DB_UNDO_RECORD_TOO_BIG, /* the undo log record is too big */ DB_UNDO_RECORD_TOO_BIG, /* the undo log record is too big */
DB_TABLE_IN_FK_CHECK, /* table is being used in foreign DB_TABLE_IN_FK_CHECK, /* table is being used in foreign
key check */ key check */
DB_IDENTIFIER_TOO_LONG, /* Identifier name too long */
/* The following are partial failure codes */ /* The following are partial failure codes */
DB_FAIL = 1000, DB_FAIL = 1000,

View file

@ -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 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 the terms of the GNU General Public License as published by the Free Software
@ -1124,6 +1124,18 @@ ulint
dict_index_calc_min_rec_len( dict_index_calc_min_rec_len(
/*========================*/ /*========================*/
const dict_index_t* index); /*!< in: index */ const dict_index_t* index); /*!< in: index */
/** Calculate new statistics if 1 / 16 of table has been modified
since the last time a statistics batch was run.
We calculate statistics at most every 16th round, since we may have
a counter table which is very small and updated very often.
@param t table
@return true if the table has changed too much and stats need to be
recalculated
*/
#define DICT_TABLE_CHANGED_TOO_MUCH(t) \
((ib_int64_t) (t)->stat_modified_counter > 16 + (t)->stat_n_rows / 16)
/*********************************************************************//** /*********************************************************************//**
Calculates new estimates for table and index statistics. The statistics Calculates new estimates for table and index statistics. The statistics
are used in query optimization. */ are used in query optimization. */
@ -1132,11 +1144,15 @@ void
dict_update_statistics( dict_update_statistics(
/*===================*/ /*===================*/
dict_table_t* table, /*!< in/out: table */ dict_table_t* table, /*!< in/out: table */
ibool only_calc_if_missing_stats, /*!< in: only ibool only_calc_if_missing_stats,/*!< in: only
update/recalc the stats if they have update/recalc the stats if they have
not been initialized yet, otherwise not been initialized yet, otherwise
do nothing */ do nothing */
ibool sync); ibool sync,
ibool only_calc_if_changed_too_much);/*!< in: only
update/recalc the stats if the table
has been changed too much since the
last stats update/recalc */
/*********************************************************************//** /*********************************************************************//**
*/ */
UNIV_INTERN UNIV_INTERN

View file

@ -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 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 the terms of the GNU General Public License as published by the Free Software
@ -127,7 +127,7 @@ This could result in rescursive calls and out of stack error eventually.
DICT_FK_MAX_RECURSIVE_LOAD defines the maximum number of recursive loads, DICT_FK_MAX_RECURSIVE_LOAD defines the maximum number of recursive loads,
when exceeded, the child table will not be loaded. It will be loaded when when exceeded, the child table will not be loaded. It will be loaded when
the foreign constraint check needs to be run. */ the foreign constraint check needs to be run. */
#define DICT_FK_MAX_RECURSIVE_LOAD 255 #define DICT_FK_MAX_RECURSIVE_LOAD 20
/** Similarly, when tables are chained together with foreign key constraints /** Similarly, when tables are chained together with foreign key constraints
with on cascading delete/update clause, delete from parent table could with on cascading delete/update clause, delete from parent table could
@ -607,7 +607,13 @@ struct dict_table_struct{
/*!< flag: TRUE if the maximum length of /*!< flag: TRUE if the maximum length of
a single row exceeds BIG_ROW_SIZE; a single row exceeds BIG_ROW_SIZE;
initialized in dict_table_add_to_cache() */ initialized in dict_table_add_to_cache() */
/** Statistics for query optimization */ /** Statistics for query optimization.
The following stat_* members are usually
protected by dict_table_stats_lock(). In
some exceptional cases (performance critical
code paths) we access or modify stat_n_rows
and stat_modified_counter without any
protection. */
/* @{ */ /* @{ */
unsigned stat_initialized:1; /*!< TRUE if statistics have unsigned stat_initialized:1; /*!< TRUE if statistics have
been calculated the first time been calculated the first time

View file

@ -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 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 the terms of the GNU General Public License as published by the Free Software
@ -58,4 +58,7 @@ enum dict_err_ignore {
typedef enum dict_err_ignore dict_err_ignore_t; typedef enum dict_err_ignore dict_err_ignore_t;
#define TEMP_TABLE_PREFIX "#sql"
#define TEMP_TABLE_PATH_PREFIX "/" TEMP_TABLE_PREFIX
#endif #endif

View file

@ -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 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 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. 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 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 this program; if not, write to the Free Software Foundation, Inc.,
Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/ *****************************************************************************/
@ -47,15 +47,17 @@ UNIV_INLINE
dyn_array_t* dyn_array_t*
dyn_array_create( 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) */ size sizeof(dyn_array_t) */
__attribute__((nonnull));
/************************************************************//** /************************************************************//**
Frees a dynamic array. */ Frees a dynamic array. */
UNIV_INLINE UNIV_INLINE
void void
dyn_array_free( 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. 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 After copying the elements, the caller must close the buffer using
@ -66,8 +68,9 @@ byte*
dyn_array_open( dyn_array_open(
/*===========*/ /*===========*/
dyn_array_t* arr, /*!< in: dynamic array */ 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! */ smaller than DYN_ARRAY_DATA_SIZE! */
__attribute__((nonnull, warn_unused_result));
/*********************************************************************//** /*********************************************************************//**
Closes the buffer returned by dyn_array_open. */ Closes the buffer returned by dyn_array_open. */
UNIV_INLINE UNIV_INLINE
@ -75,7 +78,8 @@ void
dyn_array_close( dyn_array_close(
/*============*/ /*============*/
dyn_array_t* arr, /*!< in: dynamic array */ 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 Makes room on top of a dyn array and returns a pointer to
the added element. The caller must copy the element to the added element. The caller must copy the element to
@ -85,8 +89,9 @@ UNIV_INLINE
void* void*
dyn_array_push( 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 */ ulint size) /*!< in: size in bytes of the element */
__attribute__((nonnull, warn_unused_result));
/************************************************************//** /************************************************************//**
Returns pointer to an element in dyn array. Returns pointer to an element in dyn array.
@return pointer to element */ @return pointer to element */
@ -94,9 +99,10 @@ UNIV_INLINE
void* void*
dyn_array_get_element( dyn_array_get_element(
/*==================*/ /*==================*/
dyn_array_t* arr, /*!< in: dyn array */ const dyn_array_t* arr, /*!< in: dyn array */
ulint pos); /*!< in: position of element as bytes ulint pos) /*!< in: position of element
from array start */ in bytes from array start */
__attribute__((nonnull, warn_unused_result));
/************************************************************//** /************************************************************//**
Returns the size of stored data in a dyn array. Returns the size of stored data in a dyn array.
@return data size in bytes */ @return data size in bytes */
@ -104,30 +110,33 @@ UNIV_INLINE
ulint ulint
dyn_array_get_data_size( 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. */ Gets the first block in a dyn array.
UNIV_INLINE @param arr dyn array
dyn_block_t* @return first block */
dyn_array_get_first_block( #define dyn_array_get_first_block(arr) (arr)
/*======================*/
dyn_array_t* arr); /*!< in: dyn array */
/************************************************************//** /************************************************************//**
Gets the last block in a dyn array. */ Gets the last block in a dyn array.
UNIV_INLINE @param arr dyn array
dyn_block_t* @return last block */
dyn_array_get_last_block( #define dyn_array_get_last_block(arr) \
/*=====================*/ ((arr)->heap ? UT_LIST_GET_LAST((arr)->base) : (arr))
dyn_array_t* arr); /*!< in: dyn array */
/********************************************************************//** /********************************************************************//**
Gets the next block in a dyn array. Gets the next block in a dyn array.
@param arr dyn array
@param block dyn array block
@return pointer to next, NULL if end of list */ @return pointer to next, NULL if end of list */
UNIV_INLINE #define dyn_array_get_next_block(arr, block) \
dyn_block_t* ((arr)->heap ? UT_LIST_GET_NEXT(list, block) : NULL)
dyn_array_get_next_block( /********************************************************************//**
/*=====================*/ Gets the previous block in a dyn array.
dyn_array_t* arr, /*!< in: dyn array */ @param arr dyn array
dyn_block_t* block); /*!< in: dyn array block */ @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. Gets the number of used bytes in a dyn array block.
@return number of bytes used */ @return number of bytes used */
@ -135,7 +144,8 @@ UNIV_INLINE
ulint ulint
dyn_block_get_used( 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. Gets pointer to the start of data in a dyn array block.
@return pointer to data */ @return pointer to data */
@ -143,16 +153,18 @@ UNIV_INLINE
byte* byte*
dyn_block_get_data( 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. */ Pushes n bytes to a dyn array. */
UNIV_INLINE UNIV_INLINE
void void
dyn_push_string( 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 */ const byte* str, /*!< in: string to write */
ulint len); /*!< in: string length */ ulint len) /*!< in: string length */
__attribute__((nonnull));
/*#################################################################*/ /*#################################################################*/

View file

@ -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 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 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. 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 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 this program; if not, write to the Free Software Foundation, Inc.,
Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/ *****************************************************************************/
@ -35,56 +35,8 @@ UNIV_INTERN
dyn_block_t* dyn_block_t*
dyn_array_add_block( dyn_array_add_block(
/*================*/ /*================*/
dyn_array_t* arr); /*!< in: dyn array */ dyn_array_t* arr) /*!< in/out: dyn array */
__attribute__((nonnull, warn_unused_result));
/************************************************************//**
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));
}
/********************************************************************//** /********************************************************************//**
Gets the number of used bytes in a dyn array block. Gets the number of used bytes in a dyn array block.
@ -93,7 +45,7 @@ UNIV_INLINE
ulint ulint
dyn_block_get_used( dyn_block_get_used(
/*===============*/ /*===============*/
dyn_block_t* block) /*!< in: dyn array block */ const dyn_block_t* block) /*!< in: dyn array block */
{ {
ut_ad(block); ut_ad(block);
@ -107,11 +59,11 @@ UNIV_INLINE
byte* byte*
dyn_block_get_data( dyn_block_get_data(
/*===============*/ /*===============*/
dyn_block_t* block) /*!< in: dyn array block */ const dyn_block_t* block) /*!< in: dyn array block */
{ {
ut_ad(block); ut_ad(block);
return(block->data); return((byte*) block->data);
} }
/*********************************************************************//** /*********************************************************************//**
@ -121,7 +73,7 @@ UNIV_INLINE
dyn_array_t* dyn_array_t*
dyn_array_create( 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) */ size sizeof(dyn_array_t) */
{ {
ut_ad(arr); ut_ad(arr);
@ -132,10 +84,9 @@ dyn_array_create(
arr->heap = NULL; arr->heap = NULL;
arr->used = 0; arr->used = 0;
#ifdef UNIV_DEBUG ut_d(arr->buf_end = 0);
arr->buf_end = 0; ut_d(arr->magic_n = DYN_BLOCK_MAGIC_N);
arr->magic_n = DYN_BLOCK_MAGIC_N;
#endif
return(arr); return(arr);
} }
@ -151,9 +102,7 @@ dyn_array_free(
mem_heap_free(arr->heap); mem_heap_free(arr->heap);
} }
#ifdef UNIV_DEBUG ut_d(arr->magic_n = 0);
arr->magic_n = 0;
#endif
} }
/*********************************************************************//** /*********************************************************************//**
@ -164,7 +113,7 @@ UNIV_INLINE
void* void*
dyn_array_push( 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 */ ulint size) /*!< in: size in bytes of the element */
{ {
dyn_block_t* block; dyn_block_t* block;
@ -176,24 +125,23 @@ dyn_array_push(
ut_ad(size); ut_ad(size);
block = arr; 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 */ /* Get the last array block */
block = dyn_array_get_last_block(arr); 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); block = dyn_array_add_block(arr);
}
}
used = block->used; used = block->used;
}
}
block->used = used + size; block->used = used + size;
ut_ad(block->used <= DYN_ARRAY_DATA_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! */ smaller than DYN_ARRAY_DATA_SIZE! */
{ {
dyn_block_t* block; dyn_block_t* block;
ulint used;
ut_ad(arr); ut_ad(arr);
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N); ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
@ -218,28 +165,23 @@ dyn_array_open(
ut_ad(size); ut_ad(size);
block = arr; 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 */ /* Get the last array block */
block = dyn_array_get_last_block(arr); 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); block = dyn_array_add_block(arr);
used = block->used;
ut_a(size <= DYN_ARRAY_DATA_SIZE); ut_a(size <= DYN_ARRAY_DATA_SIZE);
} }
} }
ut_ad(block->used <= DYN_ARRAY_DATA_SIZE); ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
#ifdef UNIV_DEBUG
ut_ad(arr->buf_end == 0); ut_ad(arr->buf_end == 0);
ut_d(arr->buf_end = block->used + size);
arr->buf_end = used + size; return(block->data + block->used);
#endif
return((block->data) + used);
} }
/*********************************************************************//** /*********************************************************************//**
@ -248,8 +190,8 @@ UNIV_INLINE
void void
dyn_array_close( dyn_array_close(
/*============*/ /*============*/
dyn_array_t* arr, /*!< in: dynamic array */ dyn_array_t* arr, /*!< in/out: dynamic array */
byte* ptr) /*!< in: buffer space from ptr up was not used */ const byte* ptr) /*!< in: end of used space */
{ {
dyn_block_t* block; dyn_block_t* block;
@ -264,9 +206,7 @@ dyn_array_close(
ut_ad(block->used <= DYN_ARRAY_DATA_SIZE); ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
#ifdef UNIV_DEBUG ut_d(arr->buf_end = 0);
arr->buf_end = 0;
#endif
} }
/************************************************************//** /************************************************************//**
@ -276,12 +216,11 @@ UNIV_INLINE
void* void*
dyn_array_get_element( dyn_array_get_element(
/*==================*/ /*==================*/
dyn_array_t* arr, /*!< in: dyn array */ const dyn_array_t* arr, /*!< in: dyn array */
ulint pos) /*!< in: position of element as bytes ulint pos) /*!< in: position of element
from array start */ in bytes from array start */
{ {
dyn_block_t* block; const dyn_block_t* block;
ulint used;
ut_ad(arr); ut_ad(arr);
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N); ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
@ -290,21 +229,23 @@ dyn_array_get_element(
block = dyn_array_get_first_block(arr); block = dyn_array_get_first_block(arr);
if (arr->heap != NULL) { 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; pos -= used;
block = UT_LIST_GET_NEXT(list, block); block = UT_LIST_GET_NEXT(list, block);
ut_ad(block); ut_ad(block);
used = dyn_block_get_used(block);
} }
} }
ut_ad(block); ut_ad(block);
ut_ad(dyn_block_get_used(block) >= pos); ut_ad(dyn_block_get_used(block) >= pos);
return(block->data + pos); return((byte*) block->data + pos);
} }
/************************************************************//** /************************************************************//**
@ -314,9 +255,9 @@ UNIV_INLINE
ulint ulint
dyn_array_get_data_size( dyn_array_get_data_size(
/*====================*/ /*====================*/
dyn_array_t* arr) /*!< in: dyn array */ const dyn_array_t* arr) /*!< in: dyn array */
{ {
dyn_block_t* block; const dyn_block_t* block;
ulint sum = 0; ulint sum = 0;
ut_ad(arr); ut_ad(arr);
@ -344,7 +285,7 @@ UNIV_INLINE
void void
dyn_push_string( 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 */ const byte* str, /*!< in: string to write */
ulint len) /*!< in: string length */ ulint len) /*!< in: string length */
{ {

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2010, Innobase Oy. 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 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 the terms of the GNU General Public License as published by the Free Software
@ -328,10 +328,12 @@ fil_write_flushed_lsn_to_data_files(
ulint arch_log_no); /*!< in: latest archived log ulint arch_log_no); /*!< in: latest archived log
file number */ file number */
/*******************************************************************//** /*******************************************************************//**
Reads the flushed lsn and arch no fields from a data file at database Reads the flushed lsn, arch no, and tablespace flag fields from a data
startup. */ file at database startup.
@retval NULL on success, or if innodb_force_recovery is set
@return pointer to an error message string */
UNIV_INTERN UNIV_INTERN
void const char*
fil_read_first_page( fil_read_first_page(
/*================*/ /*================*/
os_file_t data_file, /*!< in: open data file */ os_file_t data_file, /*!< in: open data file */
@ -347,8 +349,9 @@ fil_read_first_page(
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
ib_uint64_t* min_flushed_lsn, /*!< out: min of flushed ib_uint64_t* min_flushed_lsn, /*!< out: min of flushed
lsn values in data files */ lsn values in data files */
ib_uint64_t* max_flushed_lsn); /*!< out: max of flushed ib_uint64_t* max_flushed_lsn) /*!< out: max of flushed
lsn values in data files */ lsn values in data files */
__attribute__((warn_unused_result));
/*******************************************************************//** /*******************************************************************//**
Increments the count of pending operation, if space is not being deleted. Increments the count of pending operation, if space is not being deleted.
@return TRUE if being deleted, and operation should be skipped */ @return TRUE if being deleted, and operation should be skipped */

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 2006, 2010, Innobase Oy. All Rights Reserved. Copyright (c) 2000, 2013, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@ -323,4 +323,35 @@ thd_merge_sort_block_size(
void* thd); /*!< in: thread handle (THD*), or NULL to query void* thd); /*!< in: thread handle (THD*), or NULL to query
the global merge_sort_block_size */ the global merge_sort_block_size */
/**********************************************************************
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 */
/**********************************************************************
Converts an identifier from my_charset_filename to UTF-8 charset. */
uint
innobase_convert_to_system_charset(
/*===============================*/
char* to, /* out: converted identifier */
const char* from, /* in: identifier to convert */
ulint len, /* in: length of 'to', in bytes */
uint* errors); /* out: error return */
/**********************************************************************
Converts an identifier from my_charset_filename to UTF-8 charset. */
uint
innobase_convert_to_filename_charset(
/*=================================*/
char* to, /* out: converted identifier */
const char* from, /* in: identifier to convert */
ulint len); /* in: length of 'to', in bytes */
#endif #endif

View file

@ -415,7 +415,9 @@ log_group_read_log_seg(
byte* buf, /*!< in: buffer where to read */ byte* buf, /*!< in: buffer where to read */
log_group_t* group, /*!< in: log group */ log_group_t* group, /*!< in: log group */
ib_uint64_t start_lsn, /*!< in: read area start */ ib_uint64_t start_lsn, /*!< in: read area start */
ib_uint64_t end_lsn); /*!< in: read area end */ ib_uint64_t end_lsn, /*!< in: read area end */
ibool release_mutex); /*!< in: whether the log_sys->mutex
should be released before the read */
/******************************************************//** /******************************************************//**
Writes a buffer to a log file group. */ Writes a buffer to a log file group. */
UNIV_INTERN UNIV_INTERN

View file

@ -159,6 +159,8 @@ struct log_online_bitmap_file_range_struct {
/** Struct for an iterator through all bits of changed pages bitmap blocks */ /** Struct for an iterator through all bits of changed pages bitmap blocks */
struct log_bitmap_iterator_struct struct log_bitmap_iterator_struct
{ {
ibool failed; /*!< Has the iteration
stopped prematurely */
log_online_bitmap_file_range_t in_files; /*!< The bitmap files log_online_bitmap_file_range_t in_files; /*!< The bitmap files
for this iterator */ for this iterator */
size_t in_i; /*!< Currently read size_t in_i; /*!< Currently read

View file

@ -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 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 the terms of the GNU General Public License as published by the Free Software
@ -295,9 +295,10 @@ UNIV_INTERN
void void
mtr_memo_release( mtr_memo_release(
/*=============*/ /*=============*/
mtr_t* mtr, /*!< in: mtr */ mtr_t* mtr, /*!< in/out: mini-transaction */
void* object, /*!< in: object */ 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 #ifdef UNIV_DEBUG
# ifndef UNIV_HOTBACKUP # ifndef UNIV_HOTBACKUP
/**********************************************************//** /**********************************************************//**
@ -309,7 +310,8 @@ mtr_memo_contains(
/*==============*/ /*==============*/
mtr_t* mtr, /*!< in: mtr */ mtr_t* mtr, /*!< in: mtr */
const void* object, /*!< in: object to search */ 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. Checks if memo contains the given page.

View file

@ -21,7 +21,7 @@ Public License for more details.
You should have received a copy of the GNU General Public License along 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., with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
***********************************************************************/ ***********************************************************************/
@ -76,15 +76,19 @@ extern ulint os_n_pending_writes;
#endif #endif
#ifdef __WIN__ #ifdef __WIN__
#define SRV_PATH_SEPARATOR '\\'
/** File handle */ /** File handle */
# define os_file_t HANDLE # define os_file_t HANDLE
# define os_file_invalid INVALID_HANDLE_VALUE
/** Convert a C file descriptor to a native file handle /** Convert a C file descriptor to a native file handle
@param fd file descriptor @param fd file descriptor
@return native file handle */ @return native file handle */
# define OS_FILE_FROM_FD(fd) (HANDLE) _get_osfhandle(fd) # define OS_FILE_FROM_FD(fd) (HANDLE) _get_osfhandle(fd)
#else #else
#define SRV_PATH_SEPARATOR '/'
/** File handle */ /** File handle */
typedef int os_file_t; typedef int os_file_t;
# define os_file_invalid (-1)
/** Convert a C file descriptor to a native file handle /** Convert a C file descriptor to a native file handle
@param fd file descriptor @param fd file descriptor
@return native file handle */ @return native file handle */
@ -819,7 +823,6 @@ pfs_os_file_rename_func(
ulint src_line);/*!< in: line where the func invoked */ ulint src_line);/*!< in: line where the func invoked */
#endif /* UNIV_PFS_IO */ #endif /* UNIV_PFS_IO */
#ifdef UNIV_HOTBACKUP
/***********************************************************************//** /***********************************************************************//**
Closes a file handle. Closes a file handle.
@return TRUE if success */ @return TRUE if success */
@ -828,7 +831,6 @@ ibool
os_file_close_no_error_handling( os_file_close_no_error_handling(
/*============================*/ /*============================*/
os_file_t file); /*!< in, own: handle to a file */ os_file_t file); /*!< in, own: handle to a file */
#endif /* UNIV_HOTBACKUP */
/***********************************************************************//** /***********************************************************************//**
Gets a file size. Gets a file size.
@return TRUE if success */ @return TRUE if success */

View file

@ -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 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 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 one record on an empty leaf page. Subtract 1 byte for
the encoded heap number. Check also the available space the encoded heap number. Check also the available space
on the uncompressed page. */ on the uncompressed page. */
return(rec_size - (REC_N_NEW_EXTRA_BYTES - 2) return(rec_size - (REC_N_NEW_EXTRA_BYTES - 2 - 1)
>= (page_zip_empty_size(n_fields, zip_size) - 1) >= page_zip_empty_size(n_fields, zip_size)
|| rec_size >= page_get_free_space_of_empty(TRUE) / 2); || rec_size >= page_get_free_space_of_empty(TRUE) / 2);
} }
@ -229,9 +229,7 @@ ibool
page_zip_get_trailer_len( page_zip_get_trailer_len(
/*=====================*/ /*=====================*/
const page_zip_des_t* page_zip,/*!< in: compressed page */ const page_zip_des_t* page_zip,/*!< in: compressed page */
ibool is_clust,/*!< in: TRUE if clustered index */ ibool is_clust)/*!< in: TRUE if clustered index */
ulint* entry_size)/*!< out: size of the uncompressed
portion of a user record */
{ {
ulint uncompressed_size; ulint uncompressed_size;
@ -250,10 +248,6 @@ page_zip_get_trailer_len(
ut_ad(!page_zip->n_blobs); ut_ad(!page_zip->n_blobs);
} }
if (entry_size) {
*entry_size = uncompressed_size;
}
return((page_dir_get_n_heap(page_zip->data) - 2) return((page_dir_get_n_heap(page_zip->data) - 2)
* uncompressed_size * uncompressed_size
+ page_zip->n_blobs * BTR_EXTERN_FIELD_REF_SIZE); + page_zip->n_blobs * BTR_EXTERN_FIELD_REF_SIZE);
@ -270,11 +264,9 @@ page_zip_max_ins_size(
const page_zip_des_t* page_zip,/*!< in: compressed page */ const page_zip_des_t* page_zip,/*!< in: compressed page */
ibool is_clust)/*!< in: TRUE if clustered index */ ibool is_clust)/*!< in: TRUE if clustered index */
{ {
ulint uncompressed_size;
ulint trailer_len; ulint trailer_len;
trailer_len = page_zip_get_trailer_len(page_zip, is_clust, trailer_len = page_zip_get_trailer_len(page_zip, is_clust);
&uncompressed_size);
/* When a record is created, a pointer may be added to /* When a record is created, a pointer may be added to
the dense directory. the dense directory.
@ -283,7 +275,7 @@ page_zip_max_ins_size(
Also the BLOB pointers will be allocated from there, but Also the BLOB pointers will be allocated from there, but
we may as well count them in the length of the record. */ we may as well count them in the length of the record. */
trailer_len += uncompressed_size; trailer_len += PAGE_ZIP_DIR_SLOT_SIZE;
return((lint) page_zip_get_size(page_zip) return((lint) page_zip_get_size(page_zip)
- trailer_len - page_zip->m_end - trailer_len - page_zip->m_end
@ -303,13 +295,11 @@ page_zip_available(
ulint create) /*!< in: nonzero=add the record to ulint create) /*!< in: nonzero=add the record to
the heap */ the heap */
{ {
ulint uncompressed_size;
ulint trailer_len; ulint trailer_len;
ut_ad(length > REC_N_NEW_EXTRA_BYTES); ut_ad(length > REC_N_NEW_EXTRA_BYTES);
trailer_len = page_zip_get_trailer_len(page_zip, is_clust, trailer_len = page_zip_get_trailer_len(page_zip, is_clust);
&uncompressed_size);
/* Subtract the fixed extra bytes and add the maximum /* Subtract the fixed extra bytes and add the maximum
space needed for identifying the record (encoded heap_no). */ space needed for identifying the record (encoded heap_no). */
@ -323,7 +313,7 @@ page_zip_available(
Also the BLOB pointers will be allocated from there, but Also the BLOB pointers will be allocated from there, but
we may as well count them in the length of the record. */ we may as well count them in the length of the record. */
trailer_len += uncompressed_size; trailer_len += PAGE_ZIP_DIR_SLOT_SIZE;
} }
return(UNIV_LIKELY(length return(UNIV_LIKELY(length

View file

@ -297,6 +297,9 @@ extern ulint srv_n_rows_updated;
extern ulint srv_n_rows_deleted; extern ulint srv_n_rows_deleted;
extern ulint srv_n_rows_read; extern ulint srv_n_rows_read;
extern ulint srv_read_views_memory;
extern ulint srv_descriptors_memory;
extern ibool srv_print_innodb_monitor; extern ibool srv_print_innodb_monitor;
extern ibool srv_print_innodb_lock_monitor; extern ibool srv_print_innodb_lock_monitor;
extern ibool srv_print_innodb_tablespace_monitor; extern ibool srv_print_innodb_tablespace_monitor;
@ -901,6 +904,8 @@ struct export_var_struct{
ulint innodb_rows_updated; /*!< srv_n_rows_updated */ ulint innodb_rows_updated; /*!< srv_n_rows_updated */
ulint innodb_rows_deleted; /*!< srv_n_rows_deleted */ ulint innodb_rows_deleted; /*!< srv_n_rows_deleted */
ulint innodb_truncated_status_writes; /*!< srv_truncated_status_writes */ ulint innodb_truncated_status_writes; /*!< srv_truncated_status_writes */
ulint innodb_read_views_memory; /*!< srv_read_views_memory */
ulint innodb_descriptors_memory; /*!< srv_descriptors_memory */
ib_int64_t innodb_s_lock_os_waits; ib_int64_t innodb_s_lock_os_waits;
ib_int64_t innodb_s_lock_spin_rounds; ib_int64_t innodb_s_lock_spin_rounds;
ib_int64_t innodb_s_lock_spin_waits; ib_int64_t innodb_s_lock_spin_waits;

View file

@ -55,49 +55,8 @@ ut_dbg_assertion_failed(
ulint line) /*!< in: line number of the assertion */ ulint line) /*!< in: line number of the assertion */
UNIV_COLD __attribute__((nonnull(2))); 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. */ /** Abort the execution. */
#ifdef _WIN32
# define UT_DBG_PANIC __debugbreak()
#else
# define UT_DBG_PANIC abort() # 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. /** Abort execution if EXPR does not evaluate to nonzero.
@param EXPR assertion expression that should hold */ @param EXPR assertion expression that should hold */
@ -107,7 +66,6 @@ ut_dbg_stop_thread(
__FILE__, (ulint) __LINE__); \ __FILE__, (ulint) __LINE__); \
UT_DBG_PANIC; \ UT_DBG_PANIC; \
} \ } \
UT_DBG_STOP; \
} while (0) } while (0)
/** Abort execution. */ /** Abort execution. */

View file

@ -2005,6 +2005,8 @@ lock_rec_lock_fast(
|| mode - (LOCK_MODE_MASK & mode) == 0 || mode - (LOCK_MODE_MASK & mode) == 0
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); || 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); lock = lock_rec_get_first_on_page(block);
trx = thr_get_trx(thr); trx = thr_get_trx(thr);
@ -2082,6 +2084,8 @@ lock_rec_lock_slow(
trx = thr_get_trx(thr); trx = thr_get_trx(thr);
DBUG_EXECUTE_IF("innodb_report_deadlock", return(DB_DEADLOCK););
lock = lock_rec_has_expl(mode, block, heap_no, trx); lock = lock_rec_has_expl(mode, block, heap_no, trx);
if (lock) { if (lock) {
if (lock->type_mode & LOCK_CONV_BY_OTHER) { if (lock->type_mode & LOCK_CONV_BY_OTHER) {
@ -4145,6 +4149,7 @@ lock_rec_unlock(
ut_ad(trx && rec); ut_ad(trx && rec);
ut_ad(block->frame == page_align(rec)); ut_ad(block->frame == page_align(rec));
ut_ad(trx->state == TRX_ACTIVE);
heap_no = page_rec_get_heap_no(rec); heap_no = page_rec_get_heap_no(rec);
@ -5002,6 +5007,7 @@ lock_rec_validate_page(
{ {
const lock_t* lock; const lock_t* lock;
const rec_t* rec; const rec_t* rec;
dict_index_t* index;
ulint nth_lock = 0; ulint nth_lock = 0;
ulint nth_bit = 0; ulint nth_bit = 0;
ulint i; ulint i;
@ -5051,6 +5057,7 @@ loop:
if (i == 1 || lock_rec_get_nth_bit(lock, i)) { if (i == 1 || lock_rec_get_nth_bit(lock, i)) {
index = lock->index;
rec = page_find_rec_with_heap_no(block->frame, i); rec = page_find_rec_with_heap_no(block->frame, i);
ut_a(rec); ut_a(rec);
offsets = rec_get_offsets(rec, lock->index, offsets, offsets = rec_get_offsets(rec, lock->index, offsets,
@ -5067,7 +5074,7 @@ loop:
check WILL break the latching order and may check WILL break the latching order and may
cause a deadlock of threads. */ cause a deadlock of threads. */
lock_rec_queue_validate(block, rec, lock->index, lock_rec_queue_validate(block, rec, index,
offsets); offsets);
lock_mutex_enter_kernel(); lock_mutex_enter_kernel();

View file

@ -2390,7 +2390,8 @@ loop:
} }
/******************************************************//** /******************************************************//**
Reads a specified log segment to a buffer. */ Reads a specified log segment to a buffer. Optionally releases the log mutex
before the I/O. */
UNIV_INTERN UNIV_INTERN
void void
log_group_read_log_seg( log_group_read_log_seg(
@ -2399,7 +2400,9 @@ log_group_read_log_seg(
byte* buf, /*!< in: buffer where to read */ byte* buf, /*!< in: buffer where to read */
log_group_t* group, /*!< in: log group */ log_group_t* group, /*!< in: log group */
ib_uint64_t start_lsn, /*!< in: read area start */ ib_uint64_t start_lsn, /*!< in: read area start */
ib_uint64_t end_lsn) /*!< in: read area end */ ib_uint64_t end_lsn, /*!< in: read area end */
ibool release_mutex) /*!< in: whether the log_sys->mutex
should be released before the read */
{ {
ulint len; ulint len;
ulint source_offset; ulint source_offset;
@ -2429,6 +2432,10 @@ loop:
log_sys->n_log_ios++; log_sys->n_log_ios++;
if (release_mutex) {
mutex_exit(&(log_sys->mutex));
}
fil_io(OS_FILE_READ | OS_FILE_LOG, sync, group->space_id, 0, fil_io(OS_FILE_READ | OS_FILE_LOG, sync, group->space_id, 0,
source_offset / UNIV_PAGE_SIZE, source_offset % UNIV_PAGE_SIZE, source_offset / UNIV_PAGE_SIZE, source_offset % UNIV_PAGE_SIZE,
len, buf, NULL); len, buf, NULL);
@ -2438,6 +2445,9 @@ loop:
if (start_lsn != end_lsn) { if (start_lsn != end_lsn) {
if (release_mutex) {
mutex_enter(&(log_sys->mutex));
}
goto loop; goto loop;
} }
} }
@ -2929,7 +2939,7 @@ arch_none:
log_group_read_log_seg(LOG_ARCHIVE, log_sys->archive_buf, log_group_read_log_seg(LOG_ARCHIVE, log_sys->archive_buf,
UT_LIST_GET_FIRST(log_sys->log_groups), UT_LIST_GET_FIRST(log_sys->log_groups),
start_lsn, limit_lsn); start_lsn, limit_lsn, FALSE);
mutex_exit(&(log_sys->mutex)); mutex_exit(&(log_sys->mutex));

View file

@ -43,8 +43,8 @@ UNIV_INTERN mysql_pfs_key_t log_bmp_sys_mutex_key;
/** Log parsing and bitmap output data structure */ /** Log parsing and bitmap output data structure */
struct log_bitmap_struct { struct log_bitmap_struct {
byte read_buf[FOLLOW_SCAN_SIZE]; byte* read_buf_ptr; /*!< Unaligned log read buffer */
/*!< log read buffer */ byte* read_buf; /*!< log read buffer */
byte parse_buf[RECV_PARSING_BUF_SIZE]; byte parse_buf[RECV_PARSING_BUF_SIZE];
/*!< log parse buffer */ /*!< log parse buffer */
byte* parse_buf_end; /*!< parse buffer position where the byte* parse_buf_end; /*!< parse buffer position where the
@ -53,6 +53,8 @@ struct log_bitmap_struct {
parsed, it points to the start, parsed, it points to the start,
otherwise points immediatelly past the otherwise points immediatelly past the
end of the incomplete log record. */ end of the incomplete log record. */
char bmp_file_home[FN_REFLEN];
/*!< directory for bitmap files */
log_online_bitmap_file_t out; /*!< The current bitmap file */ log_online_bitmap_file_t out; /*!< The current bitmap file */
ulint out_seq_num; /*!< the bitmap file sequence number */ ulint out_seq_num; /*!< the bitmap file sequence number */
ib_uint64_t start_lsn; /*!< the LSN of the next unparsed ib_uint64_t start_lsn; /*!< the LSN of the next unparsed
@ -490,9 +492,8 @@ log_online_make_bitmap_name(
ib_uint64_t start_lsn) /*!< in: the start LSN name part */ ib_uint64_t start_lsn) /*!< in: the start LSN name part */
{ {
ut_snprintf(log_bmp_sys->out.name, FN_REFLEN, bmp_file_name_template, ut_snprintf(log_bmp_sys->out.name, FN_REFLEN, bmp_file_name_template,
srv_data_home, bmp_file_name_stem, log_bmp_sys->bmp_file_home, bmp_file_name_stem,
log_bmp_sys->out_seq_num, start_lsn); log_bmp_sys->out_seq_num, start_lsn);
} }
/*********************************************************************//** /*********************************************************************//**
@ -509,7 +510,8 @@ log_online_should_overwrite(
/* Currently, it's OK to overwrite 0-sized files only */ /* Currently, it's OK to overwrite 0-sized files only */
success = os_file_get_status(path, &file_info); success = os_file_get_status(path, &file_info);
return success && file_info.size == 0LL; return success && file_info.type == OS_FILE_TYPE_FILE
&& file_info.size == 0LL;
} }
/*********************************************************************//** /*********************************************************************//**
@ -525,7 +527,7 @@ log_online_start_bitmap_file(void)
/* Check for an old file that should be deleted first */ /* Check for an old file that should be deleted first */
if (log_online_should_overwrite(log_bmp_sys->out.name)) { if (log_online_should_overwrite(log_bmp_sys->out.name)) {
success = os_file_delete(log_bmp_sys->out.name); success = os_file_delete_if_exists(log_bmp_sys->out.name);
} }
if (UNIV_LIKELY(success)) { if (UNIV_LIKELY(success)) {
@ -544,7 +546,6 @@ log_online_start_bitmap_file(void)
fprintf(stderr, fprintf(stderr,
"InnoDB: Error: Cannot create \'%s\'\n", "InnoDB: Error: Cannot create \'%s\'\n",
log_bmp_sys->out.name); log_bmp_sys->out.name);
log_bmp_sys->out.file = -1;
return FALSE; return FALSE;
} }
@ -563,9 +564,9 @@ log_online_rotate_bitmap_file(
ib_uint64_t next_file_start_lsn) /*!<in: the start LSN name ib_uint64_t next_file_start_lsn) /*!<in: the start LSN name
part */ part */
{ {
if (log_bmp_sys->out.file != -1) { if (log_bmp_sys->out.file != os_file_invalid) {
os_file_close(log_bmp_sys->out.file); os_file_close(log_bmp_sys->out.file);
log_bmp_sys->out.file = -1; log_bmp_sys->out.file = os_file_invalid;
} }
log_bmp_sys->out_seq_num++; log_bmp_sys->out_seq_num++;
log_online_make_bitmap_name(next_file_start_lsn); log_online_make_bitmap_name(next_file_start_lsn);
@ -613,6 +614,7 @@ log_online_read_init(void)
os_file_dir_t bitmap_dir; os_file_dir_t bitmap_dir;
os_file_stat_t bitmap_dir_file_info; os_file_stat_t bitmap_dir_file_info;
ib_uint64_t last_file_start_lsn = MIN_TRACKED_LSN; ib_uint64_t last_file_start_lsn = MIN_TRACKED_LSN;
size_t srv_data_home_len;
/* Bitmap data start and end in a bitmap block must be 8-byte /* Bitmap data start and end in a bitmap block must be 8-byte
aligned. */ aligned. */
@ -620,20 +622,39 @@ log_online_read_init(void)
compile_time_assert(MODIFIED_PAGE_BLOCK_BITMAP_LEN % 8 == 0); compile_time_assert(MODIFIED_PAGE_BLOCK_BITMAP_LEN % 8 == 0);
log_bmp_sys = ut_malloc(sizeof(*log_bmp_sys)); log_bmp_sys = ut_malloc(sizeof(*log_bmp_sys));
log_bmp_sys->read_buf_ptr = ut_malloc(FOLLOW_SCAN_SIZE
+ OS_FILE_LOG_BLOCK_SIZE);
log_bmp_sys->read_buf = ut_align(log_bmp_sys->read_buf_ptr,
OS_FILE_LOG_BLOCK_SIZE);
mutex_create(log_bmp_sys_mutex_key, &log_bmp_sys->mutex, mutex_create(log_bmp_sys_mutex_key, &log_bmp_sys->mutex,
SYNC_LOG_ONLINE); SYNC_LOG_ONLINE);
/* Initialize bitmap file directory from srv_data_home and add a path
separator if needed. */
srv_data_home_len = strlen(srv_data_home);
ut_a (srv_data_home_len < FN_REFLEN);
strcpy(log_bmp_sys->bmp_file_home, srv_data_home);
if (srv_data_home_len
&& log_bmp_sys->bmp_file_home[srv_data_home_len - 1]
!= SRV_PATH_SEPARATOR) {
ut_a (srv_data_home_len < FN_REFLEN - 1);
log_bmp_sys->bmp_file_home[srv_data_home_len]
= SRV_PATH_SEPARATOR;
log_bmp_sys->bmp_file_home[srv_data_home_len + 1] = '\0';
}
/* Enumerate existing bitmap files to either open the last one to get /* Enumerate existing bitmap files to either open the last one to get
the last tracked LSN either to find that there are none and start the last tracked LSN either to find that there are none and start
tracking from scratch. */ tracking from scratch. */
log_bmp_sys->out.name[0] = '\0'; log_bmp_sys->out.name[0] = '\0';
log_bmp_sys->out_seq_num = 0; log_bmp_sys->out_seq_num = 0;
bitmap_dir = os_file_opendir(srv_data_home, TRUE); bitmap_dir = os_file_opendir(log_bmp_sys->bmp_file_home, TRUE);
ut_a(bitmap_dir); ut_a(bitmap_dir);
while (!os_file_readdir_next_file(srv_data_home, bitmap_dir, while (!os_file_readdir_next_file(log_bmp_sys->bmp_file_home,
&bitmap_dir_file_info)) { bitmap_dir, &bitmap_dir_file_info)) {
ulong file_seq_num; ulong file_seq_num;
ib_uint64_t file_start_lsn; ib_uint64_t file_start_lsn;
@ -648,8 +669,8 @@ log_online_read_init(void)
&& bitmap_dir_file_info.size > 0) { && bitmap_dir_file_info.size > 0) {
log_bmp_sys->out_seq_num = file_seq_num; log_bmp_sys->out_seq_num = file_seq_num;
last_file_start_lsn = file_start_lsn; last_file_start_lsn = file_start_lsn;
/* No dir component (srv_data_home) here, because /* No dir component (log_bmp_sys->bmp_file_home) here,
that's the cwd */ because that's the cwd */
strncpy(log_bmp_sys->out.name, strncpy(log_bmp_sys->out.name,
bitmap_dir_file_info.name, FN_REFLEN - 1); bitmap_dir_file_info.name, FN_REFLEN - 1);
log_bmp_sys->out.name[FN_REFLEN - 1] = '\0'; log_bmp_sys->out.name[FN_REFLEN - 1] = '\0';
@ -659,7 +680,7 @@ log_online_read_init(void)
if (os_file_closedir(bitmap_dir)) { if (os_file_closedir(bitmap_dir)) {
os_file_get_last_error(TRUE); os_file_get_last_error(TRUE);
fprintf(stderr, "InnoDB: Error: cannot close \'%s\'\n", fprintf(stderr, "InnoDB: Error: cannot close \'%s\'\n",
srv_data_home); log_bmp_sys->bmp_file_home);
exit(1); exit(1);
} }
@ -762,9 +783,9 @@ log_online_read_shutdown(void)
{ {
ib_rbt_node_t *free_list_node = log_bmp_sys->page_free_list; ib_rbt_node_t *free_list_node = log_bmp_sys->page_free_list;
if (log_bmp_sys->out.file != -1) { if (log_bmp_sys->out.file != os_file_invalid) {
os_file_close(log_bmp_sys->out.file); os_file_close(log_bmp_sys->out.file);
log_bmp_sys->out.file = -1; log_bmp_sys->out.file = os_file_invalid;
} }
rbt_free(log_bmp_sys->modified_pages); rbt_free(log_bmp_sys->modified_pages);
@ -777,6 +798,7 @@ log_online_read_shutdown(void)
mutex_free(&log_bmp_sys->mutex); mutex_free(&log_bmp_sys->mutex);
ut_free(log_bmp_sys->read_buf_ptr);
ut_free(log_bmp_sys); ut_free(log_bmp_sys);
} }
@ -978,8 +1000,8 @@ log_online_follow_log_seg(
mutex_enter(&log_sys->mutex); mutex_enter(&log_sys->mutex);
log_group_read_log_seg(LOG_RECOVER, log_bmp_sys->read_buf, log_group_read_log_seg(LOG_RECOVER, log_bmp_sys->read_buf,
group, block_start_lsn, block_end_lsn); group, block_start_lsn, block_end_lsn, TRUE);
mutex_exit(&log_sys->mutex); /* log_group_read_log_seg will release the log_sys->mutex for us */
while (log_block < log_block_end while (log_block < log_block_end
&& log_bmp_sys->next_parse_lsn < log_bmp_sys->end_lsn) { && log_bmp_sys->next_parse_lsn < log_bmp_sys->end_lsn) {
@ -1256,15 +1278,18 @@ log_online_setup_bitmap_file_range(
os_file_dir_t bitmap_dir; os_file_dir_t bitmap_dir;
os_file_stat_t bitmap_dir_file_info; os_file_stat_t bitmap_dir_file_info;
ulong first_file_seq_num = ULONG_MAX; ulong first_file_seq_num = ULONG_MAX;
ulong last_file_seq_num = 0;
ib_uint64_t first_file_start_lsn = IB_ULONGLONG_MAX; ib_uint64_t first_file_start_lsn = IB_ULONGLONG_MAX;
ut_ad(range_end >= range_start);
bitmap_files->count = 0; bitmap_files->count = 0;
bitmap_files->files = NULL; bitmap_files->files = NULL;
/* 1st pass: size the info array */ /* 1st pass: size the info array */
bitmap_dir = os_file_opendir(srv_data_home, FALSE); bitmap_dir = os_file_opendir(srv_data_home, FALSE);
if (!bitmap_dir) { if (UNIV_UNLIKELY(!bitmap_dir)) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Error: " "InnoDB: Error: "
"failed to open bitmap directory \'%s\'\n", "failed to open bitmap directory \'%s\'\n",
@ -1286,12 +1311,17 @@ log_online_setup_bitmap_file_range(
continue; continue;
} }
if (file_seq_num > last_file_seq_num) {
last_file_seq_num = file_seq_num;
}
if (file_start_lsn >= range_start if (file_start_lsn >= range_start
|| file_start_lsn == first_file_start_lsn || file_start_lsn == first_file_start_lsn
|| first_file_start_lsn > range_start) { || first_file_start_lsn > range_start) {
/* A file that falls into the range */ /* A file that falls into the range */
bitmap_files->count++;
if (file_start_lsn < first_file_start_lsn) { if (file_start_lsn < first_file_start_lsn) {
first_file_start_lsn = file_start_lsn; first_file_start_lsn = file_start_lsn;
@ -1309,23 +1339,27 @@ log_online_setup_bitmap_file_range(
} }
} }
ut_a(first_file_seq_num != ULONG_MAX || bitmap_files->count == 0); if (UNIV_UNLIKELY(os_file_closedir(bitmap_dir))) {
if (os_file_closedir(bitmap_dir)) {
os_file_get_last_error(TRUE); os_file_get_last_error(TRUE);
fprintf(stderr, "InnoDB: Error: cannot close \'%s\'\n", fprintf(stderr, "InnoDB: Error: cannot close \'%s\'\n",
srv_data_home); srv_data_home);
return FALSE; return FALSE;
} }
if (!bitmap_files->count) { if (first_file_seq_num == ULONG_MAX && last_file_seq_num == 0) {
bitmap_files->count = 0;
return TRUE; return TRUE;
} }
bitmap_files->count = last_file_seq_num - first_file_seq_num + 1;
/* 2nd pass: get the file names in the file_seq_num order */ /* 2nd pass: get the file names in the file_seq_num order */
bitmap_dir = os_file_opendir(srv_data_home, FALSE); bitmap_dir = os_file_opendir(srv_data_home, FALSE);
if (!bitmap_dir) { if (UNIV_UNLIKELY(!bitmap_dir)) {
fprintf(stderr, "InnoDB: Error: " fprintf(stderr, "InnoDB: Error: "
"failed to open bitmap directory \'%s\'\n", "failed to open bitmap directory \'%s\'\n",
srv_data_home); srv_data_home);
@ -1349,11 +1383,25 @@ log_online_setup_bitmap_file_range(
&file_start_lsn) &file_start_lsn)
|| file_start_lsn >= range_end || file_start_lsn >= range_end
|| file_start_lsn < first_file_start_lsn) { || file_start_lsn < first_file_start_lsn) {
continue; continue;
} }
array_pos = file_seq_num - first_file_seq_num; array_pos = file_seq_num - first_file_seq_num;
if (UNIV_UNLIKELY(array_pos >= bitmap_files->count)) {
fprintf(stderr,
"InnoDB: Error: inconsistent bitmap file "
"directory for a "
"INFORMATION_SCHEMA.INNODB_CHANGED_PAGES query"
"\n");
free(bitmap_files->files);
return FALSE;
}
if (file_seq_num > bitmap_files->files[array_pos].seq_num) { if (file_seq_num > bitmap_files->files[array_pos].seq_num) {
bitmap_files->files[array_pos].seq_num = file_seq_num; bitmap_files->files[array_pos].seq_num = file_seq_num;
strncpy(bitmap_files->files[array_pos].name, strncpy(bitmap_files->files[array_pos].name,
bitmap_dir_file_info.name, FN_REFLEN); bitmap_dir_file_info.name, FN_REFLEN);
@ -1364,7 +1412,8 @@ log_online_setup_bitmap_file_range(
} }
} }
if (os_file_closedir(bitmap_dir)) { if (UNIV_UNLIKELY(os_file_closedir(bitmap_dir))) {
os_file_get_last_error(TRUE); os_file_get_last_error(TRUE);
fprintf(stderr, "InnoDB: Error: cannot close \'%s\'\n", fprintf(stderr, "InnoDB: Error: cannot close \'%s\'\n",
srv_data_home); srv_data_home);
@ -1411,6 +1460,8 @@ log_online_open_bitmap_file_read_only(
ulint size_low; ulint size_low;
ulint size_high; ulint size_high;
ut_ad(name[0] != '\0');
ut_snprintf(bitmap_file->name, FN_REFLEN, "%s%s", srv_data_home, name); ut_snprintf(bitmap_file->name, FN_REFLEN, "%s%s", srv_data_home, name);
bitmap_file->file bitmap_file->file
= os_file_create_simple_no_error_handling(innodb_file_bmp_key, = os_file_create_simple_no_error_handling(innodb_file_bmp_key,
@ -1418,7 +1469,8 @@ log_online_open_bitmap_file_read_only(
OS_FILE_OPEN, OS_FILE_OPEN,
OS_FILE_READ_ONLY, OS_FILE_READ_ONLY,
&success); &success);
if (!success) { if (UNIV_UNLIKELY(!success)) {
/* Here and below assume that bitmap file names do not /* Here and below assume that bitmap file names do not
contain apostrophes, thus no need for ut_print_filename(). */ contain apostrophes, thus no need for ut_print_filename(). */
fprintf(stderr, fprintf(stderr,
@ -1461,7 +1513,8 @@ log_online_diagnose_bitmap_eof(
|| (bitmap_file->offset || (bitmap_file->offset
> bitmap_file->size - MODIFIED_PAGE_BLOCK_SIZE)) { > bitmap_file->size - MODIFIED_PAGE_BLOCK_SIZE)) {
if (bitmap_file->offset != bitmap_file->size) { if (UNIV_UNLIKELY(bitmap_file->offset != bitmap_file->size)) {
/* If we are not at EOF and we have less than one page /* If we are not at EOF and we have less than one page
to read, it's junk. This error is not fatal in to read, it's junk. This error is not fatal in
itself. */ itself. */
@ -1472,7 +1525,8 @@ log_online_diagnose_bitmap_eof(
bitmap_file->name); bitmap_file->name);
} }
if (!last_page_in_run) { if (UNIV_UNLIKELY(!last_page_in_run)) {
/* We are at EOF but the last read page did not finish /* We are at EOF but the last read page did not finish
a run */ a run */
/* It's a "Warning" here because it's not a fatal error /* It's a "Warning" here because it's not a fatal error
@ -1512,18 +1566,29 @@ log_online_bitmap_iterator_init(
if (!log_online_setup_bitmap_file_range(&i->in_files, min_lsn, if (!log_online_setup_bitmap_file_range(&i->in_files, min_lsn,
max_lsn)) { max_lsn)) {
i->failed = TRUE;
return FALSE; return FALSE;
} }
ut_a(i->in_files.count > 0); i->in_i = 0;
if (i->in_files.count == 0) {
/* Empty range */
i->in.file = os_file_invalid;
i->page = NULL;
i->failed = FALSE;
return TRUE;
}
/* Open the 1st bitmap file */ /* Open the 1st bitmap file */
i->in_i = 0; if (UNIV_UNLIKELY(!log_online_open_bitmap_file_read_only(
if (!log_online_open_bitmap_file_read_only(i->in_files.files[i->in_i]. i->in_files.files[i->in_i].name,
name, &i->in))) {
&i->in)) {
i->in_i = i->in_files.count; i->in_i = i->in_files.count;
free(i->in_files.files); free(i->in_files.files);
i->failed = TRUE;
return FALSE; return FALSE;
} }
@ -1534,6 +1599,7 @@ log_online_bitmap_iterator_init(
i->first_page_id = 0; i->first_page_id = 0;
i->last_page_in_run = TRUE; i->last_page_in_run = TRUE;
i->changed = FALSE; i->changed = FALSE;
i->failed = FALSE;
return TRUE; return TRUE;
} }
@ -1548,11 +1614,20 @@ log_online_bitmap_iterator_release(
{ {
ut_a(i); ut_a(i);
if (i->in_i < i->in_files.count) { if (i->in.file != os_file_invalid) {
os_file_close(i->in.file); os_file_close(i->in.file);
i->in.file = os_file_invalid;
} }
if (i->in_files.files) {
ut_free(i->in_files.files); ut_free(i->in_files.files);
}
if (i->page) {
ut_free(i->page); ut_free(i->page);
}
i->failed = TRUE;
} }
/*********************************************************************//** /*********************************************************************//**
@ -1567,10 +1642,16 @@ log_online_bitmap_iterator_next(
log_bitmap_iterator_t *i) /*!<in/out: iterator */ log_bitmap_iterator_t *i) /*!<in/out: iterator */
{ {
ibool checksum_ok = FALSE; ibool checksum_ok = FALSE;
ibool success;
ut_a(i); ut_a(i);
if (i->bit_offset < MODIFIED_PAGE_BLOCK_BITMAP_LEN) if (UNIV_UNLIKELY(i->in_files.count == 0)) {
return FALSE;
}
if (UNIV_LIKELY(i->bit_offset < MODIFIED_PAGE_BLOCK_BITMAP_LEN))
{ {
++i->bit_offset; ++i->bit_offset;
i->changed = i->changed =
@ -1587,29 +1668,56 @@ log_online_bitmap_iterator_next(
/* Advance file */ /* Advance file */
i->in_i++; i->in_i++;
os_file_close(i->in.file); success = os_file_close_no_error_handling(i->in.file);
log_online_diagnose_bitmap_eof(&i->in, i->in.file = os_file_invalid;
i->last_page_in_run); if (UNIV_UNLIKELY(!success)) {
if (i->in_i == i->in_files.count
|| i->in_files.files[i->in_i].seq_num == 0) { os_file_get_last_error(TRUE);
i->failed = TRUE;
return FALSE;
}
success = log_online_diagnose_bitmap_eof(
&i->in, i->last_page_in_run);
if (UNIV_UNLIKELY(!success)) {
i->failed = TRUE;
return FALSE;
}
if (i->in_i == i->in_files.count) {
return FALSE; return FALSE;
} }
if (!log_online_open_bitmap_file_read_only( if (UNIV_UNLIKELY(i->in_files.files[i->in_i].seq_num
== 0)) {
i->failed = TRUE;
return FALSE;
}
success = log_online_open_bitmap_file_read_only(
i->in_files.files[i->in_i].name, i->in_files.files[i->in_i].name,
&i->in)) { &i->in);
if (UNIV_UNLIKELY(!success)) {
i->failed = TRUE;
return FALSE; return FALSE;
} }
} }
if (!log_online_read_bitmap_page(&i->in, i->page, success = log_online_read_bitmap_page(&i->in, i->page,
&checksum_ok)) { &checksum_ok);
if (UNIV_UNLIKELY(!success)) {
os_file_get_last_error(TRUE); os_file_get_last_error(TRUE);
fprintf(stderr, fprintf(stderr,
"InnoDB: Warning: failed reading " "InnoDB: Warning: failed reading "
"changed page bitmap file \'%s\'\n", "changed page bitmap file \'%s\'\n",
i->in_files.files[i->in_i].name); i->in_files.files[i->in_i].name);
i->failed = TRUE;
return FALSE; return FALSE;
} }
} }
@ -1666,7 +1774,7 @@ log_online_purge_changed_page_bitmaps(
/* If we have to delete the current output file, close it /* If we have to delete the current output file, close it
first. */ first. */
os_file_close(log_bmp_sys->out.file); os_file_close(log_bmp_sys->out.file);
log_bmp_sys->out.file = -1; log_bmp_sys->out.file = os_file_invalid;
} }
for (i = 0; i < bitmap_files.count; i++) { for (i = 0; i < bitmap_files.count; i++) {

View file

@ -553,7 +553,8 @@ recv_copy_group(
} }
log_group_read_log_seg(LOG_RECOVER, log_sys->buf, log_group_read_log_seg(LOG_RECOVER, log_sys->buf,
up_to_date_group, start_lsn, end_lsn); up_to_date_group, start_lsn, end_lsn,
FALSE);
len = (ulint) (end_lsn - start_lsn); len = (ulint) (end_lsn - start_lsn);
@ -597,7 +598,7 @@ recv_synchronize_groups(
ut_a(start_lsn != end_lsn); ut_a(start_lsn != end_lsn);
log_group_read_log_seg(LOG_RECOVER, recv_sys->last_block, log_group_read_log_seg(LOG_RECOVER, recv_sys->last_block,
up_to_date_group, start_lsn, end_lsn); up_to_date_group, start_lsn, end_lsn, FALSE);
group = UT_LIST_GET_FIRST(log_sys->log_groups); group = UT_LIST_GET_FIRST(log_sys->log_groups);
@ -1716,19 +1717,6 @@ recv_recover_page_func(
} }
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
mutex_enter(&(recv_sys->mutex));
if (recv_max_page_lsn < page_lsn) {
recv_max_page_lsn = page_lsn;
}
recv_addr->state = RECV_PROCESSED;
ut_a(recv_sys->n_addrs);
recv_sys->n_addrs--;
mutex_exit(&(recv_sys->mutex));
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
if (modification_to_page) { if (modification_to_page) {
ut_a(block); ut_a(block);
@ -1745,6 +1733,20 @@ recv_recover_page_func(
mtr.modifications = FALSE; mtr.modifications = FALSE;
mtr_commit(&mtr); mtr_commit(&mtr);
mutex_enter(&(recv_sys->mutex));
if (recv_max_page_lsn < page_lsn) {
recv_max_page_lsn = page_lsn;
}
recv_addr->state = RECV_PROCESSED;
ut_a(recv_sys->n_addrs);
recv_sys->n_addrs--;
mutex_exit(&(recv_sys->mutex));
} }
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
@ -2894,7 +2896,7 @@ recv_group_scan_log_recs(
end_lsn = start_lsn + RECV_SCAN_SIZE; end_lsn = start_lsn + RECV_SCAN_SIZE;
log_group_read_log_seg(LOG_RECOVER, log_sys->buf, log_group_read_log_seg(LOG_RECOVER, log_sys->buf,
group, start_lsn, end_lsn); group, start_lsn, end_lsn, FALSE);
finished = recv_scan_log_recs( finished = recv_scan_log_recs(
(buf_pool_get_n_pages() (buf_pool_get_n_pages()

View file

@ -353,7 +353,13 @@ mem_heap_create_block(
block = (mem_block_t*) buf_block->frame; block = (mem_block_t*) buf_block->frame;
} }
ut_ad(block); if(!block) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Unable to allocate memory of size %lu.\n",
len);
ut_error;
}
block->buf_block = buf_block; block->buf_block = buf_block;
block->free_block = NULL; block->free_block = NULL;
#else /* !UNIV_HOTBACKUP */ #else /* !UNIV_HOTBACKUP */

View file

@ -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 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 the terms of the GNU General Public License as published by the Free Software
@ -59,73 +59,82 @@ mtr_block_dirtied(
/*****************************************************************//** /*****************************************************************//**
Releases the item in the slot given. */ Releases the item in the slot given. */
static static __attribute__((nonnull))
void void
mtr_memo_slot_release( mtr_memo_slot_release_func(
/*==================*/ /*=======================*/
mtr_t* mtr, /*!< in: mtr */ #ifdef UNIV_DEBUG
mtr_t* mtr, /*!< in/out: mini-transaction */
#endif /* UNIV_DEBUG */
mtr_memo_slot_t* slot) /*!< in: memo slot */ mtr_memo_slot_t* slot) /*!< in: memo slot */
{ {
void* object; void* object = slot->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;
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);
#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));
#endif /* UNIV_DEBUG */
} else {
rw_lock_x_unlock((rw_lock_t*)object);
}
}
slot->object = NULL; slot->object = NULL;
/* 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
default:
ut_ad(slot->type == MTR_MEMO_MODIFY);
ut_ad(mtr_memo_contains(mtr, object, MTR_MEMO_PAGE_X_FIX));
#endif /* UNIV_DEBUG */
}
} }
#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. Releases the mlocks and other objects stored in an mtr memo.
They are released in the order opposite to which they were pushed They are released in the order opposite to which they were pushed
to the memo. */ to the memo. */
static static __attribute__((nonnull))
void void
mtr_memo_pop_all( mtr_memo_pop_all(
/*=============*/ /*=============*/
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in/out: mini-transaction */
{ {
mtr_memo_slot_t* slot; const dyn_block_t* block;
dyn_array_t* memo;
ulint offset;
ut_ad(mtr);
ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->magic_n == MTR_MAGIC_N);
ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in
commit */ commit */
memo = &(mtr->memo);
offset = dyn_array_get_data_size(memo); 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));
while (offset > 0) { ut_ad(!(dyn_block_get_used(block) % sizeof(mtr_memo_slot_t)));
offset -= sizeof(mtr_memo_slot_t);
slot = dyn_array_get_element(memo, offset);
while (slot-- != start) {
if (slot->object != NULL) {
mtr_memo_slot_release(mtr, slot); mtr_memo_slot_release(mtr, slot);
} }
}
}
} }
/*****************************************************************//** /*****************************************************************//**
@ -320,42 +329,36 @@ UNIV_INTERN
void void
mtr_memo_release( mtr_memo_release(
/*=============*/ /*=============*/
mtr_t* mtr, /*!< in: mtr */ mtr_t* mtr, /*!< in/out: mini-transaction */
void* object, /*!< in: object */ void* object, /*!< in: object */
ulint type) /*!< in: object type: MTR_MEMO_S_LOCK, ... */ ulint type) /*!< in: object type: MTR_MEMO_S_LOCK, ... */
{ {
mtr_memo_slot_t* slot; const dyn_block_t* block;
dyn_array_t* memo;
ulint offset;
ut_ad(mtr);
ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->magic_n == MTR_MAGIC_N);
ut_ad(mtr->state == MTR_ACTIVE); ut_ad(mtr->state == MTR_ACTIVE);
/* 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);
memo = &(mtr->memo); 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));
offset = dyn_array_get_data_size(memo); ut_ad(!(dyn_block_get_used(block) % sizeof(mtr_memo_slot_t)));
log_flush_order_mutex_enter();
while (offset > 0) {
offset -= sizeof(mtr_memo_slot_t);
slot = dyn_array_get_element(memo, offset);
while (slot-- != start) {
if (object == slot->object && type == slot->type) { 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); mtr_memo_slot_release(mtr, slot);
return;
break; }
} }
} }
log_flush_order_mutex_exit();
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */

View file

@ -21,7 +21,7 @@ Public License for more details.
You should have received a copy of the GNU General Public License along 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., with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
***********************************************************************/ ***********************************************************************/
@ -66,6 +66,13 @@ Created 10/21/1995 Heikki Tuuri
#define IOCP_SHUTDOWN_KEY (ULONG_PTR)-1 #define IOCP_SHUTDOWN_KEY (ULONG_PTR)-1
#endif #endif
#if defined(UNIV_LINUX) && defined(HAVE_SYS_IOCTL_H)
# include <sys/ioctl.h>
# ifndef DFS_IOCTL_ATOMIC_WRITE_SET
# define DFS_IOCTL_ATOMIC_WRITE_SET _IOW(0x95, 2, uint)
# endif
#endif
/* This specifies the file permissions InnoDB uses when it creates files in /* This specifies the file permissions InnoDB uses when it creates files in
Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to
my_umask */ my_umask */
@ -1455,40 +1462,37 @@ os_file_set_nocache(
} }
#ifdef __linux__ /****************************************************************//**
#include <sys/ioctl.h> Tries to enable the atomic write feature, if available, for the specified file
#ifndef DFS_IOCTL_ATOMIC_WRITE_SET handle.
#define DFS_IOCTL_ATOMIC_WRITE_SET _IOW(0x95, 2, uint) @return TRUE if success */
#endif static __attribute__((warn_unused_result))
static int os_file_set_atomic_writes(os_file_t file, const char *name) ibool
os_file_set_atomic_writes(
/*======================*/
const char* name /*!< in: name of the file */
__attribute__((unused)),
os_file_t file /*!< in: handle to the file */
__attribute__((unused)))
{ {
#ifdef DFS_IOCTL_ATOMIC_WRITE_SET
int atomic_option = 1; int atomic_option = 1;
int ret = ioctl (file, DFS_IOCTL_ATOMIC_WRITE_SET, &atomic_option); if (ioctl(file, DFS_IOCTL_ATOMIC_WRITE_SET, &atomic_option)) {
if (ret) { os_file_handle_error_no_exit(name, "ioctl");
fprintf(stderr, return(FALSE);
"InnoDB : can't use atomic write on %s, errno %d\n",
name, errno);
return ret;
} }
return ret;
} return(TRUE);
#else #else
static int os_file_set_atomic_writes(os_file_t file, const char *name) fprintf(stderr, "InnoDB: Error: trying to enable atomic writes on "
{ "non-supported platform! Please restart with "
fprintf(stderr, "innodb_use_atomic_writes disabled.\n");
"InnoDB : can't use atomic writes on %s - not implemented on this platform." return(FALSE);
"innodb_use_atomic_writes needs to be 0.\n",
name);
#ifdef _WIN32
SetLastError(ERROR_INVALID_FUNCTION);
#else
errno = EINVAL;
#endif #endif
return -1;
} }
#endif
/****************************************************************//** /****************************************************************//**
NOTE! Use the corresponding macro os_file_create(), not directly NOTE! Use the corresponding macro os_file_create(), not directly
@ -1780,10 +1784,12 @@ try_again:
file = -1; file = -1;
} }
#endif /* USE_FILE_LOCK */ #endif /* USE_FILE_LOCK */
if (srv_use_atomic_writes && type == OS_DATA_FILE if (srv_use_atomic_writes && type == OS_DATA_FILE
&& os_file_set_atomic_writes(file, name)) { && os_file_set_atomic_writes(name, file)) {
close(file);
*success = FALSE; *success = FALSE;
close(file);
file = -1; file = -1;
} }
@ -1996,7 +2002,6 @@ os_file_close_func(
#endif #endif
} }
#ifdef UNIV_HOTBACKUP
/***********************************************************************//** /***********************************************************************//**
Closes a file handle. Closes a file handle.
@return TRUE if success */ @return TRUE if success */
@ -2031,7 +2036,6 @@ os_file_close_no_error_handling(
return(TRUE); return(TRUE);
#endif #endif
} }
#endif /* UNIV_HOTBACKUP */
/***********************************************************************//** /***********************************************************************//**
Gets a file size. Gets a file size.
@ -2132,23 +2136,17 @@ os_file_set_size(
#ifdef HAVE_POSIX_FALLOCATE #ifdef HAVE_POSIX_FALLOCATE
if (srv_use_posix_fallocate) { if (srv_use_posix_fallocate) {
if (posix_fallocate(file, current_size, desired_size) == -1) {
fprintf(stderr,
"InnoDB: Error: preallocating data for"
" file %s failed at\n"
"InnoDB: offset 0 size %lld %lld. Operating system"
" error number %d.\n"
"InnoDB: Check that the disk is not full"
" or a disk quota exceeded.\n"
"InnoDB: Some operating system error numbers"
" are described at\n"
"InnoDB: "
REFMAN "operating-system-error-codes.html\n",
name, (long long)size_high, (long long)size, errno);
return (FALSE); if (posix_fallocate(file, current_size, desired_size) == -1) {
fprintf(stderr, "InnoDB: Error: preallocating file "
"space for file \'%s\' failed. Current size "
"%lld, desired size %lld\n",
name, current_size, desired_size);
os_file_handle_error_no_exit(name, "posix_fallocate");
return(FALSE);
} }
return (TRUE); return(TRUE);
} }
#endif #endif

View file

@ -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 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 the terms of the GNU General Public License as published by the Free Software
@ -837,12 +837,13 @@ page_zip_compress_node_ptrs(
c_stream->next_in = (byte*) rec; c_stream->next_in = (byte*) rec;
c_stream->avail_in = rec_offs_data_size(offsets) c_stream->avail_in = rec_offs_data_size(offsets)
- REC_NODE_PTR_SIZE; - REC_NODE_PTR_SIZE;
ut_ad(c_stream->avail_in);
if (c_stream->avail_in) {
err = deflate(c_stream, Z_NO_FLUSH); err = deflate(c_stream, Z_NO_FLUSH);
if (UNIV_UNLIKELY(err != Z_OK)) { if (UNIV_UNLIKELY(err != Z_OK)) {
break; break;
} }
}
ut_ad(!c_stream->avail_in); ut_ad(!c_stream->avail_in);
@ -2274,13 +2275,12 @@ zlib_done:
if (UNIV_UNLIKELY if (UNIV_UNLIKELY
(page_zip_get_trailer_len(page_zip, (page_zip_get_trailer_len(page_zip,
dict_index_is_clust(index), NULL) dict_index_is_clust(index))
+ page_zip->m_end >= page_zip_get_size(page_zip))) { + page_zip->m_end >= page_zip_get_size(page_zip))) {
page_zip_fail(("page_zip_decompress_node_ptrs:" page_zip_fail(("page_zip_decompress_node_ptrs:"
" %lu + %lu >= %lu, %lu\n", " %lu + %lu >= %lu, %lu\n",
(ulong) page_zip_get_trailer_len( (ulong) page_zip_get_trailer_len(
page_zip, dict_index_is_clust(index), page_zip, dict_index_is_clust(index)),
NULL),
(ulong) page_zip->m_end, (ulong) page_zip->m_end,
(ulong) page_zip_get_size(page_zip), (ulong) page_zip_get_size(page_zip),
(ulong) dict_index_is_clust(index))); (ulong) dict_index_is_clust(index)));
@ -2431,12 +2431,12 @@ zlib_done:
page_zip->m_nonempty = mod_log_ptr != d_stream->next_in; page_zip->m_nonempty = mod_log_ptr != d_stream->next_in;
} }
if (UNIV_UNLIKELY(page_zip_get_trailer_len(page_zip, FALSE, NULL) if (UNIV_UNLIKELY(page_zip_get_trailer_len(page_zip, FALSE)
+ page_zip->m_end >= page_zip_get_size(page_zip))) { + page_zip->m_end >= page_zip_get_size(page_zip))) {
page_zip_fail(("page_zip_decompress_sec: %lu + %lu >= %lu\n", page_zip_fail(("page_zip_decompress_sec: %lu + %lu >= %lu\n",
(ulong) page_zip_get_trailer_len( (ulong) page_zip_get_trailer_len(
page_zip, FALSE, NULL), page_zip, FALSE),
(ulong) page_zip->m_end, (ulong) page_zip->m_end,
(ulong) page_zip_get_size(page_zip))); (ulong) page_zip_get_size(page_zip)));
return(FALSE); return(FALSE);
@ -2762,12 +2762,12 @@ zlib_done:
page_zip->m_nonempty = mod_log_ptr != d_stream->next_in; page_zip->m_nonempty = mod_log_ptr != d_stream->next_in;
} }
if (UNIV_UNLIKELY(page_zip_get_trailer_len(page_zip, TRUE, NULL) if (UNIV_UNLIKELY(page_zip_get_trailer_len(page_zip, TRUE)
+ page_zip->m_end >= page_zip_get_size(page_zip))) { + page_zip->m_end >= page_zip_get_size(page_zip))) {
page_zip_fail(("page_zip_decompress_clust: %lu + %lu >= %lu\n", page_zip_fail(("page_zip_decompress_clust: %lu + %lu >= %lu\n",
(ulong) page_zip_get_trailer_len( (ulong) page_zip_get_trailer_len(
page_zip, TRUE, NULL), page_zip, TRUE),
(ulong) page_zip->m_end, (ulong) page_zip->m_end,
(ulong) page_zip_get_size(page_zip))); (ulong) page_zip_get_size(page_zip)));
return(FALSE); return(FALSE);
@ -4642,8 +4642,7 @@ page_zip_copy_recs(
memcpy(page_zip, src_zip, sizeof *page_zip); memcpy(page_zip, src_zip, sizeof *page_zip);
page_zip->data = data; page_zip->data = data;
} }
ut_ad(page_zip_get_trailer_len(page_zip, ut_ad(page_zip_get_trailer_len(page_zip, dict_index_is_clust(index))
dict_index_is_clust(index), NULL)
+ page_zip->m_end < page_zip_get_size(page_zip)); + page_zip->m_end < page_zip_get_size(page_zip));
if (!page_is_leaf(src) if (!page_is_leaf(src)

View file

@ -150,6 +150,7 @@ read_view_create_low(
{ {
if (view == NULL) { if (view == NULL) {
view = ut_malloc(sizeof(read_view_t)); view = ut_malloc(sizeof(read_view_t));
srv_read_views_memory += sizeof(read_view_t);
view->max_descr = 0; view->max_descr = 0;
view->descriptors = NULL; view->descriptors = NULL;
} }
@ -159,6 +160,8 @@ read_view_create_low(
/* avoid frequent re-allocations by extending the array to the /* avoid frequent re-allocations by extending the array to the
desired size + 10% */ desired size + 10% */
srv_read_views_memory += (n + n / 10 - view->max_descr) *
sizeof(trx_id_t);
view->max_descr = n + n / 10; view->max_descr = n + n / 10;
view->descriptors = ut_realloc(view->descriptors, view->descriptors = ut_realloc(view->descriptors,
view->max_descr * view->max_descr *
@ -370,6 +373,9 @@ read_view_free(
{ {
ut_ad(mutex_own(&kernel_mutex)); ut_ad(mutex_own(&kernel_mutex));
srv_read_views_memory -= sizeof(read_view_t) +
view->max_descr * sizeof(trx_id_t);
if (view->descriptors != NULL) { if (view->descriptors != NULL) {
ut_free(view->descriptors); ut_free(view->descriptors);
} }

View file

@ -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 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 the terms of the GNU General Public License as published by the Free Software
@ -1710,6 +1710,7 @@ row_ins_scan_sec_index_for_duplicate(
do { do {
const rec_t* rec = btr_pcur_get_rec(&pcur); const rec_t* rec = btr_pcur_get_rec(&pcur);
const buf_block_t* block = btr_pcur_get_block(&pcur); const buf_block_t* block = btr_pcur_get_block(&pcur);
ulint lock_type;
if (page_rec_is_infimum(rec)) { if (page_rec_is_infimum(rec)) {
@ -1719,6 +1720,16 @@ row_ins_scan_sec_index_for_duplicate(
offsets = rec_get_offsets(rec, index, offsets, offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
/* If the transaction isolation level is no stronger than
READ COMMITTED, then avoid gap locks. */
if (!page_rec_is_supremum(rec)
&& thr_get_trx(thr)->isolation_level
<= TRX_ISO_READ_COMMITTED) {
lock_type = LOCK_REC_NOT_GAP;
} else {
lock_type = LOCK_ORDINARY;
}
if (allow_duplicates) { if (allow_duplicates) {
/* If the SQL-query will update or replace /* If the SQL-query will update or replace
@ -1727,13 +1738,11 @@ row_ins_scan_sec_index_for_duplicate(
INSERT ON DUPLICATE KEY UPDATE). */ INSERT ON DUPLICATE KEY UPDATE). */
err = row_ins_set_exclusive_rec_lock( err = row_ins_set_exclusive_rec_lock(
LOCK_ORDINARY, block, lock_type, block, rec, index, offsets, thr);
rec, index, offsets, thr);
} else { } else {
err = row_ins_set_shared_rec_lock( err = row_ins_set_shared_rec_lock(
LOCK_ORDINARY, block, lock_type, block, rec, index, offsets, thr);
rec, index, offsets, thr);
} }
switch (err) { switch (err) {

View file

@ -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.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@ -55,6 +55,7 @@ Created 9/17/2000 Heikki Tuuri
#include "ha_prototypes.h" #include "ha_prototypes.h"
#include "m_string.h" #include "m_string.h"
#include "my_sys.h" #include "my_sys.h"
#include "ha_prototypes.h"
/** Provide optional 4.x backwards compatibility for 5.0 and above */ /** Provide optional 4.x backwards compatibility for 5.0 and above */
UNIV_INTERN ibool row_rollback_on_timeout = FALSE; UNIV_INTERN ibool row_rollback_on_timeout = FALSE;
@ -966,17 +967,13 @@ row_update_statistics_if_needed(
if (!srv_stats_auto_update) if (!srv_stats_auto_update)
return; return;
/* Calculate new statistics if 1 / 16 of table has been modified if (DICT_TABLE_CHANGED_TOO_MUCH(table)) {
since the last time a statistics batch was run, or if
stat_modified_counter > 2 000 000 000 (to avoid wrap-around).
We calculate statistics at most every 16th round, since we may have
a counter table which is very small and updated very often. */
if (counter > 2000000000 dict_update_statistics(
|| ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) { table,
FALSE, /* update even if stats are initialized */
dict_update_statistics(table, FALSE /* update even if stats TRUE,
are initialized */, TRUE); TRUE /* only update if stats changed too much */);
} }
} }
@ -3181,8 +3178,11 @@ next_rec:
dict_table_autoinc_lock(table); dict_table_autoinc_lock(table);
dict_table_autoinc_initialize(table, 1); dict_table_autoinc_initialize(table, 1);
dict_table_autoinc_unlock(table); dict_table_autoinc_unlock(table);
dict_update_statistics(table, FALSE /* update even if stats are dict_update_statistics(
initialized */, TRUE); table,
FALSE, /* update even if stats are initialized */
TRUE,
FALSE /* update even if not changed too much */);
trx_commit_for_mysql(trx); trx_commit_for_mysql(trx);
@ -3973,6 +3973,7 @@ row_rename_table_for_mysql(
ut_a(old_name != NULL); ut_a(old_name != NULL);
ut_a(new_name != NULL); ut_a(new_name != NULL);
ut_ad(trx->state == TRX_ACTIVE);
if (srv_created_new_raw || srv_force_recovery) { if (srv_created_new_raw || srv_force_recovery) {
fputs("InnoDB: A new raw disk partition was initialized or\n" fputs("InnoDB: A new raw disk partition was initialized or\n"
@ -3997,7 +3998,6 @@ row_rename_table_for_mysql(
} }
trx->op_info = "renaming table"; trx->op_info = "renaming table";
trx_start_if_not_started(trx);
old_is_tmp = row_is_mysql_tmp_table_name(old_name); old_is_tmp = row_is_mysql_tmp_table_name(old_name);
new_is_tmp = row_is_mysql_tmp_table_name(new_name); new_is_tmp = row_is_mysql_tmp_table_name(new_name);
@ -4092,12 +4092,29 @@ row_rename_table_for_mysql(
goto end; goto end;
} else if (!new_is_tmp) { } else if (!new_is_tmp) {
/* Rename all constraints. */ /* Rename all constraints. */
char new_table_name[MAX_TABLE_NAME_LEN] = "";
uint errors = 0;
info = pars_info_create(); info = pars_info_create();
pars_info_add_str_literal(info, "new_table_name", new_name); pars_info_add_str_literal(info, "new_table_name", new_name);
pars_info_add_str_literal(info, "old_table_name", old_name); pars_info_add_str_literal(info, "old_table_name", old_name);
strncpy(new_table_name, new_name, MAX_TABLE_NAME_LEN);
innobase_convert_to_system_charset(
strchr(new_table_name, '/') + 1,
strchr(new_name, '/') +1,
MAX_TABLE_NAME_LEN, &errors);
if (errors) {
/* Table name could not be converted from charset
my_charset_filename to UTF-8. This means that the
table name is already in UTF-8 (#mysql#50). */
strncpy(new_table_name, new_name, MAX_TABLE_NAME_LEN);
}
pars_info_add_str_literal(info, "new_table_utf8", new_table_name);
err = que_eval_sql( err = que_eval_sql(
info, info,
"PROCEDURE RENAME_CONSTRAINT_IDS () IS\n" "PROCEDURE RENAME_CONSTRAINT_IDS () IS\n"
@ -4109,6 +4126,7 @@ row_rename_table_for_mysql(
"old_t_name_len INT;\n" "old_t_name_len INT;\n"
"new_db_name_len INT;\n" "new_db_name_len INT;\n"
"id_len INT;\n" "id_len INT;\n"
"offset INT;\n"
"found INT;\n" "found INT;\n"
"BEGIN\n" "BEGIN\n"
"found := 1;\n" "found := 1;\n"
@ -4117,8 +4135,6 @@ row_rename_table_for_mysql(
"new_db_name := SUBSTR(:new_table_name, 0,\n" "new_db_name := SUBSTR(:new_table_name, 0,\n"
" new_db_name_len);\n" " new_db_name_len);\n"
"old_t_name_len := LENGTH(:old_table_name);\n" "old_t_name_len := LENGTH(:old_table_name);\n"
"gen_constr_prefix := CONCAT(:old_table_name,\n"
" '_ibfk_');\n"
"WHILE found = 1 LOOP\n" "WHILE found = 1 LOOP\n"
" SELECT ID INTO foreign_id\n" " SELECT ID INTO foreign_id\n"
" FROM SYS_FOREIGN\n" " FROM SYS_FOREIGN\n"
@ -4135,12 +4151,13 @@ row_rename_table_for_mysql(
" id_len := LENGTH(foreign_id);\n" " id_len := LENGTH(foreign_id);\n"
" IF (INSTR(foreign_id, '/') > 0) THEN\n" " IF (INSTR(foreign_id, '/') > 0) THEN\n"
" IF (INSTR(foreign_id,\n" " IF (INSTR(foreign_id,\n"
" gen_constr_prefix) > 0)\n" " '_ibfk_') > 0)\n"
" THEN\n" " THEN\n"
" offset := INSTR(foreign_id, '_ibfk_') - 1;\n"
" new_foreign_id :=\n" " new_foreign_id :=\n"
" CONCAT(:new_table_name,\n" " CONCAT(:new_table_utf8,\n"
" SUBSTR(foreign_id, old_t_name_len,\n" " SUBSTR(foreign_id, offset,\n"
" id_len - old_t_name_len));\n" " id_len - offset));\n"
" ELSE\n" " ELSE\n"
" new_foreign_id :=\n" " new_foreign_id :=\n"
" CONCAT(new_db_name,\n" " CONCAT(new_db_name,\n"

View file

@ -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. Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by Portions of this file contain modifications contributed and copyrighted by
@ -57,6 +57,8 @@ Created 12/19/1997 Heikki Tuuri
#include "read0read.h" #include "read0read.h"
#include "buf0lru.h" #include "buf0lru.h"
#include "ha_prototypes.h" #include "ha_prototypes.h"
#include "m_string.h" /* for my_sys.h */
#include "my_sys.h" /* DEBUG_SYNC_C */
#include "my_compare.h" /* enum icp_result */ #include "my_compare.h" /* enum icp_result */
@ -4127,7 +4129,9 @@ wait_table_again:
} }
rec_loop: rec_loop:
DEBUG_SYNC_C("row_search_rec_loop");
if (trx_is_interrupted(trx)) { if (trx_is_interrupted(trx)) {
btr_pcur_store_position(pcur, &mtr);
err = DB_INTERRUPTED; err = DB_INTERRUPTED;
goto normal_return; goto normal_return;
} }
@ -5095,8 +5099,8 @@ row_search_check_if_query_cache_permitted(
trx->read_view = trx->read_view =
read_view_open_now(trx->id, read_view_open_now(trx->id,
NULL, TRUE); trx->prebuilt_view, TRUE);
trx->prebuilt_view = trx->read_view;
trx->global_read_view = trx->read_view; trx->global_read_view = trx->read_view;
} }
} }

View file

@ -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) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc. Copyright (c) 2009, Percona Inc.
@ -317,7 +317,7 @@ UNIV_INTERN ulong srv_rollback_segments = TRX_SYS_N_RSEGS;
/* Internal setting for "innodb_stats_method". Decides how InnoDB treats /* Internal setting for "innodb_stats_method". Decides how InnoDB treats
NULL value when collecting statistics. By default, it is set to NULL value when collecting statistics. By default, it is set to
SRV_STATS_NULLS_EQUAL(0), ie. all NULL value are treated equal */ 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;
/** Time in seconds between automatic buffer pool dumps */ /** Time in seconds between automatic buffer pool dumps */
UNIV_INTERN uint srv_auto_lru_dump = 0; UNIV_INTERN uint srv_auto_lru_dump = 0;
@ -411,8 +411,9 @@ UNIV_INTERN ulong srv_sys_stats_root_page = 0;
UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE; UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE;
UNIV_INTERN ibool srv_use_atomic_writes = FALSE; UNIV_INTERN ibool srv_use_atomic_writes = FALSE;
#ifdef HAVE_POSIX_FALLOCATE #ifdef HAVE_POSIX_FALLOCATE
UNIV_INTERN ibool srv_use_posix_fallocate = TRUE; UNIV_INTERN ibool srv_use_posix_fallocate = FALSE;
#endif #endif
UNIV_INTERN ibool srv_use_checksums = TRUE; UNIV_INTERN ibool srv_use_checksums = TRUE;
UNIV_INTERN ibool srv_fast_checksum = FALSE; UNIV_INTERN ibool srv_fast_checksum = FALSE;
@ -467,6 +468,9 @@ UNIV_INTERN ulint srv_n_rows_updated CACHE_ALIGNED = 0;
UNIV_INTERN ulint srv_n_rows_deleted CACHE_ALIGNED = 0; UNIV_INTERN ulint srv_n_rows_deleted CACHE_ALIGNED = 0;
UNIV_INTERN ulint srv_n_rows_read CACHE_ALIGNED = 0; UNIV_INTERN ulint srv_n_rows_read CACHE_ALIGNED = 0;
UNIV_INTERN ulint srv_read_views_memory CACHE_ALIGNED = 0;
UNIV_INTERN ulint srv_descriptors_memory CACHE_ALIGNED = 0;
UNIV_INTERN ulint srv_n_lock_deadlock_count CACHE_ALIGNED = 0; UNIV_INTERN ulint srv_n_lock_deadlock_count CACHE_ALIGNED = 0;
UNIV_INTERN ulint srv_n_lock_wait_count CACHE_ALIGNED = 0; UNIV_INTERN ulint srv_n_lock_wait_count CACHE_ALIGNED = 0;
UNIV_INTERN ulint srv_n_lock_wait_current_count CACHE_ALIGNED = 0; UNIV_INTERN ulint srv_n_lock_wait_current_count CACHE_ALIGNED = 0;
@ -1925,7 +1929,8 @@ srv_suspend_mysql_thread(
finish_time = (ib_int64_t) sec * 1000000 + ms; finish_time = (ib_int64_t) sec * 1000000 + ms;
} }
diff_time = (ulint) (finish_time - start_time); diff_time = (finish_time > start_time) ?
(ulint) (finish_time - start_time) : 0;
srv_n_lock_wait_current_count--; srv_n_lock_wait_current_count--;
srv_n_lock_wait_time = srv_n_lock_wait_time + diff_time; srv_n_lock_wait_time = srv_n_lock_wait_time + diff_time;
@ -2136,6 +2141,9 @@ srv_printf_innodb_monitor(
"; in additional pool allocated " ULINTPF "\n", "; in additional pool allocated " ULINTPF "\n",
ut_total_allocated_memory, ut_total_allocated_memory,
mem_pool_get_reserved(mem_comm_pool)); mem_pool_get_reserved(mem_comm_pool));
fprintf(file,
"Total memory allocated by read views " ULINTPF "\n",
srv_read_views_memory);
/* Calcurate reserved memories */ /* Calcurate reserved memories */
if (btr_search_sys && btr_search_sys->hash_index[0]->heap) { if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index[0]->heap); btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index[0]->heap);
@ -2222,6 +2230,12 @@ srv_printf_innodb_monitor(
fprintf(file, "%lu read views open inside InnoDB\n", fprintf(file, "%lu read views open inside InnoDB\n",
UT_LIST_GET_LEN(trx_sys->view_list)); UT_LIST_GET_LEN(trx_sys->view_list));
fprintf(file, "%lu transactions active inside InnoDB\n",
UT_LIST_GET_LEN(trx_sys->trx_list));
fprintf(file, "%lu out of %lu descriptors used\n",
trx_sys->descr_n_used, trx_sys->descr_n_max);
if (UT_LIST_GET_LEN(trx_sys->view_list)) { if (UT_LIST_GET_LEN(trx_sys->view_list)) {
read_view_t* view = UT_LIST_GET_LAST(trx_sys->view_list); read_view_t* view = UT_LIST_GET_LAST(trx_sys->view_list);
@ -2531,21 +2545,35 @@ srv_export_innodb_status(void)
export_vars.innodb_rows_updated = srv_n_rows_updated; export_vars.innodb_rows_updated = srv_n_rows_updated;
export_vars.innodb_rows_deleted = srv_n_rows_deleted; export_vars.innodb_rows_deleted = srv_n_rows_deleted;
export_vars.innodb_truncated_status_writes = srv_truncated_status_writes; export_vars.innodb_truncated_status_writes = srv_truncated_status_writes;
export_vars.innodb_read_views_memory = srv_read_views_memory;
export_vars.innodb_descriptors_memory = srv_descriptors_memory;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
if (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; export_vars.innodb_purge_trx_id_age = 0;
} else { } else {
export_vars.innodb_purge_trx_id_age = export_vars.innodb_purge_trx_id_age =
trx_sys->max_trx_id - purge_sys->done_trx_no; trx_sys->max_trx_id - done_trx_no;
} }
if (!purge_sys->view if (!up_limit_id
|| trx_sys->max_trx_id < purge_sys->view->up_limit_id) { || trx_sys->max_trx_id < up_limit_id) {
export_vars.innodb_purge_view_trx_id_age = 0; export_vars.innodb_purge_view_trx_id_age = 0;
} else { } else {
export_vars.innodb_purge_view_trx_id_age = export_vars.innodb_purge_view_trx_id_age =
trx_sys->max_trx_id - purge_sys->view->up_limit_id; trx_sys->max_trx_id - up_limit_id;
}
} }
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved. Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, Google Inc. Copyright (c) 2008, Google Inc.
Copyright (c) 2009, Percona Inc. Copyright (c) 2009, Percona Inc.
@ -496,12 +496,6 @@ io_handler_thread(
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
#ifdef __WIN__
#define SRV_PATH_SEPARATOR '\\'
#else
#define SRV_PATH_SEPARATOR '/'
#endif
/*********************************************************************//** /*********************************************************************//**
Normalizes a directory path for Windows: converts slashes to backslashes. */ Normalizes a directory path for Windows: converts slashes to backslashes. */
UNIV_INTERN UNIV_INTERN
@ -823,6 +817,7 @@ open_or_create_data_files(
} }
if (ret == FALSE) { if (ret == FALSE) {
const char* check_msg;
/* We open the data file */ /* We open the data file */
if (one_created) { if (one_created) {
@ -920,13 +915,20 @@ open_or_create_data_files(
return(DB_ERROR); return(DB_ERROR);
} }
skip_size_check: skip_size_check:
fil_read_first_page( check_msg = fil_read_first_page(
files[i], one_opened, &flags, files[i], one_opened, &flags,
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
min_arch_log_no, max_arch_log_no, min_arch_log_no, max_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
min_flushed_lsn, max_flushed_lsn); min_flushed_lsn, max_flushed_lsn);
if (check_msg) {
fprintf(stderr,
"InnoDB: Error: %s in data file %s\n",
check_msg, name);
return(DB_ERROR);
}
if (!one_opened if (!one_opened
&& UNIV_PAGE_SIZE && UNIV_PAGE_SIZE
!= fsp_flags_get_page_size(flags)) { != fsp_flags_get_page_size(flags)) {
@ -1047,6 +1049,9 @@ skip_size_check:
} }
if (ret == FALSE) { if (ret == FALSE) {
const char* check_msg;
/* We open the data file */ /* We open the data file */
files[i] = os_file_create(innodb_file_data_key, files[i] = os_file_create(innodb_file_data_key,
@ -1083,12 +1088,20 @@ skip_size_check:
(ulong) TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9); (ulong) TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9);
} }
fil_read_first_page( check_msg = fil_read_first_page(
files[i], one_opened, &flags, files[i], one_opened, &flags,
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
min_arch_log_no, max_arch_log_no, min_arch_log_no, max_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
min_flushed_lsn, max_flushed_lsn); min_flushed_lsn, max_flushed_lsn);
if (check_msg) {
fprintf(stderr,
"InnoDB: Error: %s in doublewrite "
"buffer file %s\n", check_msg, name);
return(DB_ERROR);
}
one_opened = TRUE; one_opened = TRUE;
} else { } else {
/* We created the data file and now write it full of /* We created the data file and now write it full of

View file

@ -602,10 +602,6 @@ sync_array_deadlock_step(
new = sync_array_find_thread(arr, thread); new = sync_array_find_thread(arr, thread);
if (UNIV_UNLIKELY(new == start)) { if (UNIV_UNLIKELY(new == start)) {
/* Stop running of other threads */
ut_dbg_stop_threads = TRUE;
/* Deadlock */ /* Deadlock */
fputs("########################################\n" fputs("########################################\n"
"DEADLOCK of threads detected!\n", stderr); "DEADLOCK of threads detected!\n", stderr);
@ -943,6 +939,8 @@ sync_array_print_long_waits(
# define SYNC_ARRAY_TIMEOUT 240 # define SYNC_ARRAY_TIMEOUT 240
#endif #endif
sync_array_enter(sync_primary_wait_array);
for (i = 0; i < sync_primary_wait_array->n_cells; i++) { for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
double diff; double diff;
@ -977,6 +975,8 @@ sync_array_print_long_waits(
} }
} }
sync_array_exit(sync_primary_wait_array);
if (noticed) { if (noticed) {
fprintf(stderr, fprintf(stderr,
"InnoDB: ###### Starts InnoDB Monitor" "InnoDB: ###### Starts InnoDB Monitor"

View file

@ -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 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 the terms of the GNU General Public License as published by the Free Software
@ -140,7 +140,7 @@ UNIV_INTERN mysql_pfs_key_t file_format_max_mutex_key;
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/* Flag to control TRX_RSEG_N_SLOTS behavior debugging. */ /* 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 #endif
/** This is used to track the maximum file format id known to InnoDB. It's /** This is used to track the maximum file format id known to InnoDB. It's
@ -726,7 +726,8 @@ trx_sys_doublewrite_init_or_restore_pages(
/* Check if the page is corrupt */ /* Check if the page is corrupt */
if (UNIV_UNLIKELY if (UNIV_UNLIKELY
(buf_page_is_corrupted(read_buf, zip_size))) { (buf_page_is_corrupted(
TRUE, read_buf, zip_size))) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Warning: database page" "InnoDB: Warning: database page"
@ -737,7 +738,8 @@ trx_sys_doublewrite_init_or_restore_pages(
" the doublewrite buffer.\n", " the doublewrite buffer.\n",
(ulong) space_id, (ulong) page_no); (ulong) space_id, (ulong) page_no);
if (buf_page_is_corrupted(page, zip_size)) { if (buf_page_is_corrupted(
TRUE, page, zip_size)) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Dump of the page:\n"); "InnoDB: Dump of the page:\n");
buf_page_print( buf_page_print(
@ -1324,6 +1326,8 @@ trx_sys_init_at_db_start(void)
TRX_DESCR_ARRAY_INITIAL_SIZE); TRX_DESCR_ARRAY_INITIAL_SIZE);
trx_sys->descr_n_max = TRX_DESCR_ARRAY_INITIAL_SIZE; trx_sys->descr_n_max = TRX_DESCR_ARRAY_INITIAL_SIZE;
trx_sys->descr_n_used = 0; trx_sys->descr_n_used = 0;
srv_descriptors_memory = TRX_DESCR_ARRAY_INITIAL_SIZE *
sizeof(trx_id_t);
sys_header = trx_sysf_get(&mtr); sys_header = trx_sysf_get(&mtr);

View file

@ -135,6 +135,7 @@ trx_reserve_descriptor(
n_max * sizeof(trx_id_t)); n_max * sizeof(trx_id_t));
trx_sys->descr_n_max = n_max; trx_sys->descr_n_max = n_max;
srv_descriptors_memory = n_max * sizeof(trx_id_t);
} }
descr = trx_sys->descriptors + n_used - 1; descr = trx_sys->descriptors + n_used - 1;
@ -219,7 +220,7 @@ trx_create(
ut_ad(mutex_own(&kernel_mutex)); ut_ad(mutex_own(&kernel_mutex));
ut_ad(sess); ut_ad(sess);
trx = mem_alloc(sizeof(trx_t)); trx = ut_malloc(sizeof(trx_t));
trx->magic_n = TRX_MAGIC_N; trx->magic_n = TRX_MAGIC_N;
@ -487,7 +488,7 @@ trx_free(
trx_release_descriptor(trx); trx_release_descriptor(trx);
mem_free(trx); ut_free(trx);
} }
/********************************************************************//** /********************************************************************//**
@ -545,7 +546,7 @@ trx_free_prepared(
ut_ad(trx_sys->descr_n_used <= UT_LIST_GET_LEN(trx_sys->trx_list)); ut_ad(trx_sys->descr_n_used <= UT_LIST_GET_LEN(trx_sys->trx_list));
mem_free(trx); ut_free(trx);
} }
/********************************************************************//** /********************************************************************//**
@ -1091,6 +1092,18 @@ trx_write_serialisation_history(
trx->mysql_master_log_pos, trx->mysql_master_log_pos,
TRX_SYS_COMMIT_MASTER_LOG_INFO, &mtr); TRX_SYS_COMMIT_MASTER_LOG_INFO, &mtr);
trx_sys_update_mysql_binlog_offset(
sys_header,
trx->mysql_relay_log_file_name,
trx->mysql_relay_log_pos,
TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
trx_sys_update_mysql_binlog_offset(
sys_header,
trx->mysql_master_log_file_name,
trx->mysql_master_log_pos,
TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
trx->mysql_master_log_file_name = ""; trx->mysql_master_log_file_name = "";
} }

View file

@ -35,16 +35,6 @@ Created 1/30/1994 Heikki Tuuri
UNIV_INTERN ulint ut_dbg_zero = 0; UNIV_INTERN ulint ut_dbg_zero = 0;
#endif #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. */ Report a failed assertion. */
UNIV_INTERN UNIV_INTERN
@ -80,30 +70,8 @@ ut_dbg_assertion_failed(
"InnoDB: corruption in the InnoDB tablespace. Please refer to\n" "InnoDB: corruption in the InnoDB tablespace. Please refer to\n"
"InnoDB: " REFMAN "forcing-innodb-recovery.html\n" "InnoDB: " REFMAN "forcing-innodb-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr); "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 #ifdef UNIV_COMPILE_TEST_FUNCS
#include <sys/types.h> #include <sys/types.h>

View file

@ -730,6 +730,8 @@ ut_strerr(
return("Operation was interrupted by end user"); return("Operation was interrupted by end user");
case DB_TABLE_IN_FK_CHECK: case DB_TABLE_IN_FK_CHECK:
return("Table is being used in foreign key 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 /* do not add default: in order to produce a warning if new code
is added to the enum but not added here */ is added to the enum but not added here */
} }