Commit 6de57924 authored by Sergei Golubchik's avatar Sergei Golubchik

XtraDB 1.1.8-20.1 from

Percona-Server 5.5.24-rel26.0
parent 452a59e0
This diff is collapsed.
This diff is collapsed.
/*****************************************************************************
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -52,12 +52,13 @@ btr_pcur_create_for_mysql(void)
}
/**************************************************************//**
Frees the memory for a persistent cursor object. */
Resets a persistent cursor object, freeing ::old_rec_buf if it is
allocated and resetting the other members to their initial values. */
UNIV_INTERN
void
btr_pcur_free_for_mysql(
/*====================*/
btr_pcur_t* cursor) /*!< in, own: persistent cursor */
btr_pcur_reset(
/*===========*/
btr_pcur_t* cursor) /*!< in, out: persistent cursor */
{
if (cursor->old_rec_buf != NULL) {
......@@ -66,6 +67,7 @@ btr_pcur_free_for_mysql(
cursor->old_rec_buf = NULL;
}
cursor->btr_cur.index = NULL;
cursor->btr_cur.page_cur.rec = NULL;
cursor->old_rec = NULL;
cursor->old_n_fields = 0;
......@@ -73,7 +75,17 @@ btr_pcur_free_for_mysql(
cursor->latch_mode = BTR_NO_LATCHES;
cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
}
/**************************************************************//**
Frees the memory for a persistent cursor object. */
UNIV_INTERN
void
btr_pcur_free_for_mysql(
/*====================*/
btr_pcur_t* cursor) /*!< in, own: persistent cursor */
{
btr_pcur_reset(cursor);
mem_free(cursor);
}
......@@ -127,6 +139,8 @@ btr_pcur_store_position(
ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
ut_a(btr_page_get_prev(page, mtr) == FIL_NULL);
ut_ad(page_is_leaf(page));
ut_ad(page_get_page_no(page) == index->page);
cursor->old_stored = BTR_PCUR_OLD_STORED;
......@@ -319,13 +333,19 @@ btr_pcur_restore_position_func(
/* Save the old search mode of the cursor */
old_mode = cursor->search_mode;
if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) {
switch (cursor->rel_pos) {
case BTR_PCUR_ON:
mode = PAGE_CUR_LE;
} else if (cursor->rel_pos == BTR_PCUR_AFTER) {
break;
case BTR_PCUR_AFTER:
mode = PAGE_CUR_G;
} else {
ut_ad(cursor->rel_pos == BTR_PCUR_BEFORE);
break;
case BTR_PCUR_BEFORE:
mode = PAGE_CUR_L;
break;
default:
ut_error;
mode = 0;
}
btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode,
......@@ -334,25 +354,44 @@ btr_pcur_restore_position_func(
/* Restore the old search mode */
cursor->search_mode = old_mode;
if (cursor->rel_pos == BTR_PCUR_ON
&& btr_pcur_is_on_user_rec(cursor)
&& 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor),
rec_get_offsets(
btr_pcur_get_rec(cursor), index,
NULL, ULINT_UNDEFINED, &heap))) {
/* We have to store the NEW value for the modify clock, since
the cursor can now be on a different page! But we can retain
the value of old_rec */
if (btr_pcur_is_on_user_rec(cursor)) {
switch (cursor->rel_pos) {
case BTR_PCUR_ON:
if (!cmp_dtuple_rec(
tuple, btr_pcur_get_rec(cursor),
rec_get_offsets(btr_pcur_get_rec(cursor),
index, NULL,
ULINT_UNDEFINED, &heap))) {
/* We have to store the NEW value for
the modify clock, since the cursor can
now be on a different page! But we can
retain the value of old_rec */
cursor->block_when_stored =
btr_pcur_get_block(cursor);
cursor->modify_clock =
buf_block_get_modify_clock(
cursor->block_when_stored);
cursor->old_stored = BTR_PCUR_OLD_STORED;
cursor->block_when_stored = btr_pcur_get_block(cursor);
cursor->modify_clock = buf_block_get_modify_clock(
cursor->block_when_stored);
cursor->old_stored = BTR_PCUR_OLD_STORED;
mem_heap_free(heap);
mem_heap_free(heap);
return(TRUE);
}
return(TRUE);
break;
case BTR_PCUR_BEFORE:
page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
break;
case BTR_PCUR_AFTER:
page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
break;
#ifdef UNIV_DEBUG
default:
ut_error;
#endif /* UNIV_DEBUG */
}
}
mem_heap_free(heap);
......
/*****************************************************************************
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
......@@ -1240,7 +1240,7 @@ cleanup:
index->name, (ulong) block->n_pointers);
rw_lock_x_unlock(btr_search_get_latch(index->id));
btr_search_validate();
ut_ad(btr_search_validate());
} else {
rw_lock_x_unlock(btr_search_get_latch(index->id));
}
......@@ -2143,7 +2143,9 @@ btr_search_validate(void)
(ulong) block->curr_left_side);
if (n_page_dumps < 20) {
buf_page_print(page, 0);
buf_page_print(
page, 0,
BUF_PAGE_PRINT_NO_CRASH);
n_page_dumps++;
}
}
......
/*****************************************************************************
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
......@@ -57,7 +57,9 @@ Created 11/5/1995 Heikki Tuuri
/* prototypes for new functions added to ha_innodb.cc */
trx_t* innobase_get_trx();
inline void _increment_page_get_statistics(buf_block_t* block, trx_t* trx)
static inline
void
_increment_page_get_statistics(buf_block_t* block, trx_t* trx)
{
ulint block_hash;
ulint block_hash_byte;
......@@ -680,8 +682,12 @@ void
buf_page_print(
/*===========*/
const byte* read_buf, /*!< in: a database page */
ulint zip_size) /*!< in: compressed page size, or
0 for uncompressed pages */
ulint zip_size, /*!< in: compressed page size, or
0 for uncompressed pages */
ulint flags) /*!< in: 0 or
BUF_PAGE_PRINT_NO_CRASH or
BUF_PAGE_PRINT_NO_FULL */
{
#ifndef UNIV_HOTBACKUP
dict_index_t* index;
......@@ -695,11 +701,14 @@ buf_page_print(
size = UNIV_PAGE_SIZE;
}
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Page dump in ascii and hex (%lu bytes):\n",
(ulong) size);
ut_print_buf(stderr, read_buf, size);
fputs("\nInnoDB: End of page dump\n", stderr);
if (!(flags & BUF_PAGE_PRINT_NO_FULL)) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Page dump in ascii and hex (%lu bytes):\n",
(ulong) size);
ut_print_buf(stderr, read_buf, size);
fputs("\nInnoDB: End of page dump\n", stderr);
}
if (zip_size) {
/* Print compressed page. */
......@@ -873,6 +882,8 @@ buf_page_print(
stderr);
break;
}
ut_ad(flags & BUF_PAGE_PRINT_NO_CRASH);
}
#ifndef UNIV_HOTBACKUP
......@@ -1078,11 +1089,8 @@ buf_chunk_init(
for (i = chunk->size; i--; ) {
buf_block_init(buf_pool, block, frame);
UNIV_MEM_INVALID(block->frame, UNIV_PAGE_SIZE);
#ifdef HAVE_purify
/* Wipe contents of frame to eliminate a Purify warning */
memset(block->frame, '\0', UNIV_PAGE_SIZE);
#endif
/* Add the block to the free list */
mutex_enter(&buf_pool->free_list_mutex);
UT_LIST_ADD_LAST(free, buf_pool->free, (&block->page));
......@@ -2768,7 +2776,7 @@ wait_until_unfixed:
block->page.buf_fix_count = 1;
buf_block_set_io_fix(block, BUF_IO_READ);
rw_lock_x_lock_func(&block->lock, 0, file, line);
rw_lock_x_lock_inline(&block->lock, 0, file, line);
UNIV_MEM_INVALID(bpage, sizeof *bpage);
......@@ -2931,14 +2939,14 @@ wait_until_unfixed:
break;
case RW_S_LATCH:
rw_lock_s_lock_func(&(block->lock), 0, file, line);
rw_lock_s_lock_inline(&(block->lock), 0, file, line);
fix_type = MTR_MEMO_PAGE_S_FIX;
break;
default:
ut_ad(rw_latch == RW_X_LATCH);
rw_lock_x_lock_func(&(block->lock), 0, file, line);
rw_lock_x_lock_inline(&(block->lock), 0, file, line);
fix_type = MTR_MEMO_PAGE_X_FIX;
break;
......@@ -3023,8 +3031,8 @@ buf_page_optimistic_get(
file, line);
fix_type = MTR_MEMO_PAGE_S_FIX;
} else {
success = rw_lock_x_lock_func_nowait(&(block->lock),
file, line);
success = rw_lock_x_lock_func_nowait_inline(&(block->lock),
file, line);
fix_type = MTR_MEMO_PAGE_X_FIX;
}
......@@ -3165,8 +3173,8 @@ buf_page_get_known_nowait(
file, line);
fix_type = MTR_MEMO_PAGE_S_FIX;
} else {
success = rw_lock_x_lock_func_nowait(&(block->lock),
file, line);
success = rw_lock_x_lock_func_nowait_inline(&(block->lock),
file, line);
fix_type = MTR_MEMO_PAGE_X_FIX;
}
......@@ -3186,7 +3194,7 @@ buf_page_get_known_nowait(
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(block->page.file_page_was_freed == FALSE);
ut_a(mode == BUF_KEEP_OLD || !block->page.file_page_was_freed);
#endif
#ifdef UNIV_IBUF_COUNT_DEBUG
......@@ -3261,8 +3269,8 @@ buf_page_try_get_func(
S-latch. */
fix_type = MTR_MEMO_PAGE_X_FIX;
success = rw_lock_x_lock_func_nowait(&block->lock,
file, line);
success = rw_lock_x_lock_func_nowait_inline(&block->lock,
file, line);
}
if (!success) {
......@@ -3997,7 +4005,8 @@ corrupt:
"InnoDB: You may have to recover"
" from a backup.\n",
(ulong) bpage->offset);
buf_page_print(frame, buf_page_get_zip_size(bpage));
buf_page_print(frame, buf_page_get_zip_size(bpage),
BUF_PAGE_PRINT_NO_CRASH);
fprintf(stderr,
"InnoDB: Database page corruption on disk"
" or a failed\n"
......@@ -5285,34 +5294,32 @@ buf_all_freed(void)
/*********************************************************************//**
Checks that there currently are no pending i/o-operations for the buffer
pool.
@return TRUE if there is no pending i/o */
@return number of pending i/o */
UNIV_INTERN
ibool
buf_pool_check_no_pending_io(void)
/*==============================*/
ulint
buf_pool_check_num_pending_io(void)
/*===============================*/
{
ulint i;
ibool ret = TRUE;
ulint pending_io = 0;
buf_pool_mutex_enter_all();
for (i = 0; i < srv_buf_pool_instances && ret; i++) {
for (i = 0; i < srv_buf_pool_instances; i++) {
const buf_pool_t* buf_pool;
buf_pool = buf_pool_from_array(i);
if (buf_pool->n_pend_reads
+ buf_pool->n_flush[BUF_FLUSH_LRU]
+ buf_pool->n_flush[BUF_FLUSH_LIST]
+ buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
pending_io += buf_pool->n_pend_reads
+ buf_pool->n_flush[BUF_FLUSH_LRU]
+ buf_pool->n_flush[BUF_FLUSH_LIST]
+ buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE];
ret = FALSE;
}
}
buf_pool_mutex_exit_all();
return(ret);
return(pending_io);
}
#if 0
......
......@@ -767,7 +767,8 @@ buf_flush_buffered_writes(void)
if (UNIV_UNLIKELY
(!page_simple_validate_new(block->frame))) {
corrupted_page:
buf_page_print(block->frame, 0);
buf_page_print(block->frame, 0,
BUF_PAGE_PRINT_NO_CRASH);
ut_print_timestamp(stderr);
fprintf(stderr,
......@@ -2036,22 +2037,6 @@ buf_flush_list(
buf_pool = buf_pool_from_array(i);
if (lsn_limit != IB_ULONGLONG_MAX) {
buf_page_t* bpage;
buf_flush_list_mutex_enter(buf_pool);
bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
if (!bpage
|| bpage->oldest_modification >= lsn_limit) {
buf_flush_list_mutex_exit(buf_pool);
continue;
} else {
buf_flush_list_mutex_exit(buf_pool);
}
}
if (!buf_flush_start(buf_pool, BUF_FLUSH_LIST)) {
/* We have two choices here. If lsn_limit was
specified then skipping an instance of buffer
......
This diff is collapsed.
......@@ -239,6 +239,166 @@ dict_hdr_create(
return(TRUE);
}
/*****************************************************************//**
Verifies the SYS_STATS table by scanning its clustered index. This
function may only be called at InnoDB startup time.
@return TRUE if SYS_STATS was verified successfully */
UNIV_INTERN
ibool
dict_verify_xtradb_sys_stats(void)
/*==============================*/
{
dict_index_t* sys_stats_index;
ulint saved_srv_pass_corrupt_table = srv_pass_corrupt_table;
ibool result;
sys_stats_index = dict_table_get_first_index(dict_sys->sys_stats);
/* Since this may be called only during server startup, avoid hitting
various asserts by using XtraDB pass_corrupt_table option. */
srv_pass_corrupt_table = 1;
result = btr_validate_index(sys_stats_index, NULL);
srv_pass_corrupt_table = saved_srv_pass_corrupt_table;
return result;
}
/*****************************************************************//**
Creates the B-tree for the SYS_STATS clustered index, adds the XtraDB
mark and the id of the index to the dictionary header page. Rewrites
both passed args. */
static
void
dict_create_xtradb_sys_stats(
/*=========================*/
dict_hdr_t** dict_hdr, /*!< in/out: dictionary header */
mtr_t* mtr) /*!< in/out: mtr */
{
ulint root_page_no;
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
DICT_HDR_SPACE, 0, DICT_STATS_ID,
dict_ind_redundant, mtr);
if (root_page_no == FIL_NULL) {
fprintf(stderr, "InnoDB: Warning: failed to create SYS_STATS btr.\n");
srv_use_sys_stats_table = FALSE;
} else {
mlog_write_ulint(*dict_hdr + DICT_HDR_STATS, root_page_no,
MLOG_4BYTES, mtr);
mlog_write_ull(*dict_hdr + DICT_HDR_XTRADB_MARK,
DICT_HDR_XTRADB_FLAG, mtr);
}
mtr_commit(mtr);
/* restart mtr */
mtr_start(mtr);
*dict_hdr = dict_hdr_get(mtr);
}
/*****************************************************************//**
Create the table and index structure of SYS_STATS for the dictionary
cache and add it there. If called for the first time, also support
wrong root page id injection for testing purposes. */
static
void
dict_add_to_cache_xtradb_sys_stats(
/*===============================*/
ibool first_time __attribute__((unused)),
/*!< in: first invocation flag. If
TRUE, optionally inject wrong root page
id */
mem_heap_t* heap, /*!< in: memory heap for table/index
allocation */
dict_hdr_t* dict_hdr, /*!< in: dictionary header */
mtr_t* mtr) /*!< in: mtr */
{
dict_table_t* table;
dict_index_t* index;
ulint root_page_id;
ulint error;
table = dict_mem_table_create("SYS_STATS", DICT_HDR_SPACE, 4, 0);
table->n_mysql_handles_opened = 1; /* for pin */
dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
dict_mem_table_add_col(table, heap, "KEY_COLS", DATA_INT, 0, 4);
dict_mem_table_add_col(table, heap, "DIFF_VALS", DATA_BINARY, 0, 0);
dict_mem_table_add_col(table, heap, "NON_NULL_VALS", DATA_BINARY, 0, 0);
/* The '+ 2' below comes from the fields DB_TRX_ID, DB_ROLL_PTR */
#if DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2
#error "DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2"
#endif
#if DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2
#error "DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2"
#endif
table->id = DICT_STATS_ID;
dict_table_add_to_cache(table, heap);
dict_sys->sys_stats = table;
mem_heap_empty(heap);
index = dict_mem_index_create("SYS_STATS", "CLUST_IND",
DICT_HDR_SPACE,
DICT_UNIQUE | DICT_CLUSTERED, 2);
dict_mem_index_add_field(index, "INDEX_ID", 0);
dict_mem_index_add_field(index, "KEY_COLS", 0);
index->id = DICT_STATS_ID;
root_page_id = mtr_read_ulint(dict_hdr + DICT_HDR_STATS, MLOG_4BYTES,
mtr);
#ifdef UNIV_DEBUG
if ((srv_sys_stats_root_page != 0) && first_time)
root_page_id = srv_sys_stats_root_page;
#endif
error = dict_index_add_to_cache(table, index, root_page_id, FALSE);
ut_a(error == DB_SUCCESS);
mem_heap_empty(heap);
}
/*****************************************************************//**
Discard the existing dictionary cache SYS_STATS information, create and
add it there anew. Does not touch the old SYS_STATS tablespace page
under the assumption that they are corrupted or overwritten for other
purposes. */
UNIV_INTERN
void
dict_recreate_xtradb_sys_stats(void)
/*================================*/
{
mtr_t mtr;
dict_hdr_t* dict_hdr;
dict_index_t* sys_stats_clust_idx;
mem_heap_t* heap;
heap = mem_heap_create(450);
mutex_enter(&(dict_sys->mutex));
sys_stats_clust_idx = dict_table_get_first_index(dict_sys->sys_stats);
dict_index_remove_from_cache(dict_sys->sys_stats, sys_stats_clust_idx);
dict_table_remove_from_cache(dict_sys->sys_stats);
dict_sys->sys_stats = NULL;
mtr_start(&mtr);
dict_hdr = dict_hdr_get(&mtr);
dict_create_xtradb_sys_stats(&dict_hdr, &mtr);
dict_add_to_cache_xtradb_sys_stats(FALSE, heap, dict_hdr, &mtr);
mem_heap_free(heap);
mtr_commit(&mtr);
mutex_exit(&(dict_sys->mutex));
}
/*****************************************************************//**
Initializes the data dictionary memory structures when the database is
started. This function is also called when the data dictionary is created. */
......@@ -254,13 +414,13 @@ dict_boot(void)
mtr_t mtr;
ulint error;
heap = mem_heap_create(450);
mtr_start(&mtr);
/* Create the hash tables etc. */
dict_init();
heap = mem_heap_create(450);
mutex_enter(&(dict_sys->mutex));
/* Get the dictionary header */
......@@ -268,25 +428,9 @@ dict_boot(void)
if (mach_read_from_8(dict_hdr + DICT_HDR_XTRADB_MARK)
!= DICT_HDR_XTRADB_FLAG) {
/* not extended yet by XtraDB, need to be extended */
ulint root_page_no;
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
DICT_HDR_SPACE, 0, DICT_STATS_ID,
dict_ind_redundant, &mtr);
if (root_page_no == FIL_NULL) {
fprintf(stderr, "InnoDB: Warning: failed to create SYS_STATS btr.\n");
srv_use_sys_stats_table = FALSE;
} else {
mlog_write_ulint(dict_hdr + DICT_HDR_STATS, root_page_no,
MLOG_4BYTES, &mtr);
mlog_write_ull(dict_hdr + DICT_HDR_XTRADB_MARK,
DICT_HDR_XTRADB_FLAG, &mtr);
}
mtr_commit(&mtr);
/* restart mtr */
mtr_start(&mtr);
dict_hdr = dict_hdr_get(&mtr);
dict_create_xtradb_sys_stats(&dict_hdr, &mtr);
}
/* Because we only write new row ids to disk-based data structure
......@@ -465,42 +609,7 @@ dict_boot(void)
FALSE);
ut_a(error == DB_SUCCESS);
/*-------------------------*/
table = dict_mem_table_create("SYS_STATS", DICT_HDR_SPACE, 4, 0);
table->n_mysql_handles_opened = 1; /* for pin */
dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
dict_mem_table_add_col(table, heap, "KEY_COLS", DATA_INT, 0, 4);
dict_mem_table_add_col(table, heap, "DIFF_VALS", DATA_BINARY, 0, 0);
dict_mem_table_add_col(table, heap, "NON_NULL_VALS", DATA_BINARY, 0, 0);
/* The '+ 2' below comes from the fields DB_TRX_ID, DB_ROLL_PTR */
#if DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2
#error "DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2"
#endif
#if DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2
#error "DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2"
#endif
table->id = DICT_STATS_ID;
dict_table_add_to_cache(table, heap);
dict_sys->sys_stats = table;
mem_heap_empty(heap);
index = dict_mem_index_create("SYS_STATS", "CLUST_IND",
DICT_HDR_SPACE,
DICT_UNIQUE | DICT_CLUSTERED, 2);
dict_mem_index_add_field(index, "INDEX_ID", 0);
dict_mem_index_add_field(index, "KEY_COLS", 0);
index->id = DICT_STATS_ID;
error = dict_index_add_to_cache(table, index,
mtr_read_ulint(dict_hdr
+ DICT_HDR_STATS,
MLOG_4BYTES, &mtr),
FALSE);
ut_a(error == DB_SUCCESS);
dict_add_to_cache_xtradb_sys_stats(TRUE, heap, dict_hdr, &mtr);
mem_heap_free(heap);
......
/*****************************************************************************
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
......@@ -56,6 +56,8 @@ UNIV_INTERN dict_index_t* dict_ind_compact;
#include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str()*/
#include "row0upd.h"
#include "srv0start.h" /* SRV_LOG_SPACE_FIRST_ID */
#include "m_string.h"
#include "my_sys.h"
#include <ctype.h>
......@@ -2397,6 +2399,8 @@ dict_foreign_free(
/*==============*/
dict_foreign_t* foreign) /*!< in, own: foreign key struct */
{
ut_a(foreign->foreign_table->n_foreign_key_checks_running == 0);
mem_heap_free(foreign->heap);
}
......@@ -4378,25 +4382,32 @@ dict_reload_statistics(
heap = mem_heap_create(1000);
while (index) {
mtr_t mtr;
if (table->is_corrupt) {
ut_a(srv_pass_corrupt_table);
mem_heap_free(heap);
return(FALSE);
}
size = btr_get_size(index, BTR_TOTAL_SIZE);
mtr_start(&mtr);
mtr_s_lock(dict_index_get_lock(index), &mtr);
size = btr_get_size(index, BTR_TOTAL_SIZE, &mtr);
index->stat_index_size = size;
*sum_of_index_sizes += size;
size = btr_get_size(index, BTR_N_LEAF_PAGES);
size = btr_get_size(index, BTR_N_LEAF_PAGES, &mtr);
if (size == 0) {
/* The root node of the tree is a leaf */
size = 1;
}
mtr_commit(&mtr);
index->stat_n_leaf_pages = size;
/*===========================================*/
......@@ -4728,6 +4739,7 @@ dict_update_statistics(
(srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE
|| (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
&& dict_index_is_clust(index)))) {
mtr_t mtr;
ulint size;
if (table->is_corrupt) {
......@@ -4736,15 +4748,24 @@ dict_update_statistics(
return;
}
size = btr_get_size(index, BTR_TOTAL_SIZE);
mtr_start(&mtr);
mtr_s_lock(dict_index_get_lock(index), &mtr);
index->stat_index_size = size;
size = btr_get_size(index, BTR_TOTAL_SIZE, &mtr);
sum_of_index_sizes += size;
if (size != ULINT_UNDEFINED) {
sum_of_index_sizes += size;
index->stat_index_size = size;
size = btr_get_size(
index, BTR_N_LEAF_PAGES, &mtr);
}
size = btr_get_size(index, BTR_N_LEAF_PAGES);
mtr_commit(&mtr);
if (size == 0) {
switch (size) {
case ULINT_UNDEFINED:
goto fake_statistics;
case 0:
/* The root node of the tree is a leaf */
size = 1;
}
......@@ -4761,6 +4782,7 @@ dict_update_statistics(
various means, also via secondary indexes. */
ulint i;
fake_statistics:
sum_of_index_sizes++;
index->stat_index_size = index->stat_n_leaf_pages = 1;
......
......@@ -2138,8 +2138,9 @@ static
void
dict_load_foreign_cols(
/*===================*/
const char* id, /*!< in: foreign constraint id as a
null-terminated string */
const char* id, /*!< in: foreign constraint id, not
necessary '\0'-terminated */
ulint id_len, /*!< in: id length */
dict_foreign_t* foreign)/*!< in: foreign constraint object */
{
dict_table_t* sys_foreign_cols;
......@@ -2169,7 +2170,7 @@ dict_load_foreign_cols(
tuple = dtuple_create(foreign->heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
dfield_set_data(dfield, id, ut_strlen(id));
dfield_set_data(dfield, id, id_len);
dict_index_copy_types(tuple, sys_index, 1);
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
......@@ -2182,7 +2183,7 @@ dict_load_foreign_cols(
ut_a(!rec_get_deleted_flag(rec, 0));
field = rec_get_nth_field_old(rec, 0, &len);
ut_a(len == ut_strlen(id));
ut_a(len == id_len);
ut_a(ut_memcmp(id, field, len) == 0);
field = rec_get_nth_field_old(rec, 1, &len);
......@@ -2211,8 +2212,9 @@ static
ulint
dict_load_foreign(
/*==============*/
const char* id, /*!< in: foreign constraint id as a
null-terminated string */
const char* id, /*!< in: foreign constraint id, not
necessary '\0'-terminated */
ulint id_len, /*!< in: id length */
ibool check_charsets,
/*!< in: TRUE=check charset compatibility */
ibool check_recursive)
......@@ -2248,7 +2250,7 @@ dict_load_foreign(
tuple = dtuple_create(heap2, 1);
dfield = dtuple_get_nth_field(tuple, 0);
dfield_set_data(dfield, id, ut_strlen(id));
dfield_set_data(dfield, id, id_len);
dict_index_copy_types(tuple, sys_index, 1);
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
......@@ -2260,8 +2262,8 @@ dict_load_foreign(
/* Not found */
fprintf(stderr,
"InnoDB: Error A: cannot load foreign constraint %s\n",
id);
"InnoDB: Error A: cannot load foreign constraint "
"%.*s\n", (int) id_len, id);
btr_pcur_close(&pcur);
mtr_commit(&mtr);
......@@ -2273,11 +2275,11 @@ dict_load_foreign(
field = rec_get_nth_field_old(rec, 0, &len);
/* Check if the id in record is the searched one */
if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) {
if (len != id_len || ut_memcmp(id, field, len) != 0) {
fprintf(stderr,
"InnoDB: Error B: cannot load foreign constraint %s\n",
id);
"InnoDB: Error B: cannot load foreign constraint "
"%.*s\n", (int) id_len, id);
btr_pcur_close(&pcur);
mtr_commit(&mtr);
......@@ -2303,7 +2305,7 @@ dict_load_foreign(
foreign->type = (unsigned int) (n_fields_and_type >> 24);
foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL);
foreign->id = mem_heap_strdup(foreign->heap, id);
foreign->id = mem_heap_strdupl(foreign->heap, id, id_len);
field = rec_get_nth_field_old(rec, 3, &len);
......@@ -2319,7 +2321,7 @@ dict_load_foreign(
btr_pcur_close(&pcur);
mtr_commit(&mtr);
dict_load_foreign_cols(id, foreign);
dict_load_foreign_cols(id, id_len, foreign);
ref_table = dict_table_check_if_in_cache_low(
foreign->referenced_table_name_lookup);
......@@ -2398,8 +2400,8 @@ dict_load_foreigns(
ibool check_charsets) /*!< in: TRUE=check charset
compatibility */
{
char tuple_buf[DTUPLE_EST_ALLOC(1)];
btr_pcur_t pcur;
mem_heap_t* heap;
dtuple_t* tuple;
dfield_t* dfield;
dict_index_t* sec_index;
......@@ -2407,7 +2409,6 @@ dict_load_foreigns(
const rec_t* rec;
const byte* field;
ulint len;
char* id ;
ulint err;
mtr_t mtr;
......@@ -2434,9 +2435,8 @@ dict_load_foreigns(
sec_index = dict_table_get_next_index(
dict_table_get_first_index(sys_foreign));
start_load:
heap = mem_heap_create(256);
tuple = dtuple_create(heap, 1);
tuple = dtuple_create_from_mem(tuple_buf, sizeof(tuple_buf), 1);
dfield = dtuple_get_nth_field(tuple, 0);
dfield_set_data(dfield, table_name, ut_strlen(table_name));
......@@ -2490,7 +2490,6 @@ loop:
/* Now we get a foreign key constraint id */
field = rec_get_nth_field_old(rec, 1, &len);
id = mem_heap_strdupl(heap, (char*) field, len);
btr_pcur_store_position(&pcur, &mtr);
......@@ -2498,11 +2497,11 @@ loop:
/* Load the foreign constraint definition to the dictionary cache */
err = dict_load_foreign(id, check_charsets, check_recursive);
err = dict_load_foreign((char*) field, len, check_charsets,
check_recursive);
if (err != DB_SUCCESS) {
btr_pcur_close(&pcur);
mem_heap_free(heap);
return(err);
}
......@@ -2518,7 +2517,6 @@ next_rec:
load_next_index:
btr_pcur_close(&pcur);
mtr_commit(&mtr);
mem_heap_free(heap);
sec_index = dict_table_get_next_index(sec_index);
......
......@@ -193,7 +193,7 @@ struct fil_space_struct {
.ibd file of tablespace and want to
stop temporarily posting of new i/o
requests on the file */
ibool stop_ibuf_merges;
ibool stop_new_ops;
/*!< we set this TRUE when we start
deleting a single-table tablespace */
ibool is_being_deleted;
......@@ -218,12 +218,13 @@ struct fil_space_struct {
ulint n_pending_flushes; /*!< this is positive when flushing
the tablespace to disk; dropping of the
tablespace is forbidden if this is positive */
ulint n_pending_ibuf_merges;/*!< this is positive
when merging insert buffer entries to
a page so that we may need to access
the ibuf bitmap page in the
tablespade: dropping of the tablespace
is forbidden if this is positive */
ulint n_pending_ops;/*!< this is positive when we
have pending operations against this
tablespace. The pending operations can
be ibuf merges or lock validation code
trying to read a block.
Dropping of the tablespace is forbidden
if this is positive */
hash_node_t hash; /*!< hash chain node */
hash_node_t name_hash;/*!< hash chain the name_hash table */
#ifndef UNIV_HOTBACKUP
......@@ -974,11 +975,6 @@ retry:
return;
}
if (fil_system->n_open < fil_system->max_n_open) {
return;
}
space = fil_space_get_by_id(space_id);
if (space != NULL && space->stop_ios) {
......@@ -995,6 +991,25 @@ retry:
mutex_exit(&fil_system->mutex);
#ifndef UNIV_HOTBACKUP
/* Wake the i/o-handler threads to make sure pending
i/o's are performed */
os_aio_simulated_wake_handler_threads();
/* The sleep here is just to give IO helper threads a
bit of time to do some work. It is not required that
all IO related to the tablespace being renamed must
be flushed here as we do fil_flush() in
fil_rename_tablespace() as well. */
os_thread_sleep(20000);
#endif /* UNIV_HOTBACKUP */
/* Flush tablespaces so that we can close modified
files in the LRU list */
fil_flush_file_spaces(FIL_TABLESPACE);
os_thread_sleep(20000);
count2++;
......@@ -1002,6 +1017,11 @@ retry:
goto retry;
}
if (fil_system->n_open < fil_system->max_n_open) {
return;
}
/* If the file is already open, no need to do anything; if the space
does not exist, we handle the situation in the function which called
this function */
......@@ -1274,7 +1294,7 @@ try_again:
}
space->stop_ios = FALSE;
space->stop_ibuf_merges = FALSE;
space->stop_new_ops = FALSE;
space->is_being_deleted = FALSE;
space->purpose = purpose;
space->size = 0;
......@@ -1283,7 +1303,7 @@ try_again:
space->n_reserved_extents = 0;
space->n_pending_flushes = 0;
space->n_pending_ibuf_merges = 0;
space->n_pending_ops = 0;
UT_LIST_INIT(space->chain);
space->magic_n = FIL_SPACE_MAGIC_N;
......@@ -1896,13 +1916,12 @@ fil_read_first_page(
#ifndef UNIV_HOTBACKUP
/*******************************************************************//**
Increments the count of pending insert buffer page merges, if space is not
being deleted.
@return TRUE if being deleted, and ibuf merges should be skipped */
Increments the count of pending operation, if space is not being deleted.
@return TRUE if being deleted, and operation should be skipped */
UNIV_INTERN
ibool
fil_inc_pending_ibuf_merges(
/*========================*/
fil_inc_pending_ops(
/*================*/
ulint id) /*!< in: space id */
{
fil_space_t* space;
......@@ -1918,13 +1937,13 @@ fil_inc_pending_ibuf_merges(
(ulong) id);
}
if (space == NULL || space->stop_ibuf_merges) {
if (space == NULL || space->stop_new_ops) {
mutex_exit(&fil_system->mutex);
return(TRUE);
}
space->n_pending_ibuf_merges++;
space->n_pending_ops++;
mutex_exit(&fil_system->mutex);
......@@ -1932,11 +1951,11 @@ fil_inc_pending_ibuf_merges(
}
/*******************************************************************//**
Decrements the count of pending insert buffer page merges. */
Decrements the count of pending operations. */
UNIV_INTERN
void
fil_decr_pending_ibuf_merges(
/*=========================*/
fil_decr_pending_ops(
/*=================*/
ulint id) /*!< in: space id */
{
fil_space_t* space;
......@@ -1947,13 +1966,13 @@ fil_decr_pending_ibuf_merges(
if (space == NULL) {
fprintf(stderr,
"InnoDB: Error: decrementing ibuf merge of a"
" dropped tablespace %lu\n",
"InnoDB: Error: decrementing pending operation"
" of a dropped tablespace %lu\n",
(ulong) id);
}
if (space != NULL) {
space->n_pending_ibuf_merges--;
space->n_pending_ops--;
}
mutex_exit(&fil_system->mutex);
......@@ -2164,7 +2183,7 @@ fil_op_log_parse_or_replay(
switch (type) {
case MLOG_FILE_DELETE:
if (fil_tablespace_exists_in_mem(space_id)) {
ut_a(fil_delete_tablespace(space_id));
ut_a(fil_delete_tablespace(space_id, TRUE));
}
break;
......@@ -2234,7 +2253,9 @@ UNIV_INTERN
ibool
fil_delete_tablespace(
/*==================*/
ulint id) /*!< in: space id */
ulint id, /*!< in: space id */
ibool evict_all) /*!< in: TRUE if we want all pages
evicted from LRU. */
{
ibool success;
fil_space_t* space;
......@@ -2243,15 +2264,15 @@ fil_delete_tablespace(
char* path;
ut_a(id != 0);
stop_ibuf_merges:
stop_new_ops:
mutex_enter(&fil_system->mutex);
space = fil_space_get_by_id(id);
if (space != NULL) {
space->stop_ibuf_merges = TRUE;
space->stop_new_ops = TRUE;
if (space->n_pending_ibuf_merges == 0) {
if (space->n_pending_ops == 0) {
mutex_exit(&fil_system->mutex);
count = 0;
......@@ -2265,9 +2286,10 @@ stop_ibuf_merges:
ut_print_filename(stderr, space->name);
fprintf(stderr, ",\n"
"InnoDB: but there are %lu pending"
" ibuf merges on it.\n"
" operations (most likely ibuf merges)"
" on it.\n"
"InnoDB: Loop %lu.\n",
(ulong) space->n_pending_ibuf_merges,
(ulong) space->n_pending_ops,
(ulong) count);
}
......@@ -2276,7 +2298,7 @@ stop_ibuf_merges:
os_thread_sleep(20000);
count++;
goto stop_ibuf_merges;
goto stop_new_ops;
}
}
......@@ -2302,7 +2324,7 @@ try_again:
}
ut_a(space);
ut_a(space->n_pending_ibuf_merges == 0);
ut_a(space->n_pending_ops == 0);
space->is_being_deleted = TRUE;
......@@ -2358,7 +2380,11 @@ try_again:
if (srv_lazy_drop_table) {
buf_LRU_mark_space_was_deleted(id);
} else {
buf_LRU_invalidate_tablespace(id);
buf_LRU_flush_or_remove_pages(
id, evict_all
? BUF_REMOVE_ALL_NO_WRITE
: BUF_REMOVE_FLUSH_NO_WRITE);
}
#endif
/* printf("Deleting tablespace %s id %lu\n", space->name, id); */
......@@ -2447,7 +2473,7 @@ fil_discard_tablespace(
{
ibool success;
success = fil_delete_tablespace(id);
success = fil_delete_tablespace(id, TRUE);
if (!success) {
fprintf(stderr,
......@@ -2579,7 +2605,7 @@ fil_rename_tablespace(
retry:
count++;
if (count > 1000) {
if (!(count % 1000)) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Warning: problems renaming ", stderr);
ut_print_filename(stderr, old_name);
......@@ -3905,7 +3931,7 @@ convert_err_exit:
level = btr_page_get_level(page, &mtr);
new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, &mtr);
new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, &mtr, &mtr);
new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block);
btr_page_create(new_block, new_page_zip, index, level, &mtr);
......@@ -3953,7 +3979,7 @@ convert_err_exit:
split_rec = page_get_middle_rec(page);
new_block = btr_page_alloc(index, page_no + 1, FSP_UP,
btr_page_get_level(page, &mtr), &mtr);
btr_page_get_level(page, &mtr), &mtr, &mtr);
new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block);
btr_page_create(new_block, new_page_zip, index,
......
This diff is collapsed.
This diff is collapsed.
......@@ -79,13 +79,14 @@ class ha_innobase: public handler
INNOBASE_SHARE* share; /*!< information for MySQL
table locking */
uchar* upd_buff; /*!< buffer used in updates */
uchar* key_val_buff; /*!< buffer used in converting
uchar* upd_buf; /*!< buffer used in updates */
ulint upd_buf_size; /*!< the size of upd_buf in bytes */
uchar srch_key_val1[REC_VERSION_56_MAX_INDEX_COL_LEN + 2];
uchar srch_key_val2[REC_VERSION_56_MAX_INDEX_COL_LEN + 2];
/*!< buffers used in converting
search key values from MySQL format
to Innodb format */
ulong upd_and_key_val_buff_len;
/* the length of each of the previous
two buffers */
to InnoDB format. "+ 2" for the two
bytes where the length is stored */
Table_flags int_table_flags;
uint primary_key;
ulong start_of_scan; /*!< this is set to 1 when we are
......
/*****************************************************************************
Copyright (c) 2005, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 2005, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
......@@ -877,6 +877,8 @@ ha_innobase::add_index(
prebuilt->table, indexed_table,
index, num_of_idx, table);
DBUG_EXECUTE_IF("crash_innodb_add_index_after", DBUG_SUICIDE(););
error_handling:
/* After an error, remove all those index definitions from the
dictionary which were defined. */
......@@ -1019,7 +1021,12 @@ ha_innobase::final_add_index(
row_prebuilt_free(prebuilt, TRUE);
error = row_merge_drop_table(trx, old_table);
add->indexed_table->n_mysql_handles_opened++;
prebuilt = row_create_prebuilt(add->indexed_table);
prebuilt = row_create_prebuilt(add->indexed_table,
0 /* XXX Do we know the mysql_row_len here?
Before the addition of this parameter to
row_create_prebuilt() the mysql_row_len
member was left 0 (from zalloc) in the
prebuilt object. */);
}
err = convert_error_code_to_mysql(
......@@ -1153,7 +1160,9 @@ ha_innobase::prepare_drop_index(
goto func_exit;
}
rw_lock_x_lock(dict_index_get_lock(index));
index->to_be_dropped = TRUE;
rw_lock_x_unlock(dict_index_get_lock(index));
}
/* If FOREIGN_KEY_CHECKS = 1 you may not drop an index defined
......@@ -1272,7 +1281,9 @@ func_exit:
= dict_table_get_first_index(prebuilt->table);
do {
rw_lock_x_lock(dict_index_get_lock(index));
index->to_be_dropped = FALSE;
rw_lock_x_unlock(dict_index_get_lock(index));
index = dict_table_get_next_index(index);
} while (index);
}
......@@ -1338,7 +1349,9 @@ ha_innobase::final_drop_index(
for (index = dict_table_get_first_index(prebuilt->table);
index; index = dict_table_get_next_index(index)) {
rw_lock_x_lock(dict_index_get_lock(index));
index->to_be_dropped = FALSE;
rw_lock_x_unlock(dict_index_get_lock(index));
}
goto func_exit;
......
/*****************************************************************************
Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
......@@ -1523,7 +1523,7 @@ ibuf_add_ops(
for (i = 0; i < IBUF_OP_COUNT; i++) {
#ifdef HAVE_ATOMIC_BUILTINS
os_atomic_increment_ulint(&arr[i], ops[i]);
(void) os_atomic_increment_ulint(&arr[i], ops[i]);
#else /* HAVE_ATOMIC_BUILTINS */
arr[i] += ops[i];
#endif /* HAVE_ATOMIC_BUILTINS */
......@@ -2222,14 +2222,14 @@ ibool
ibuf_add_free_page(void)
/*====================*/
{
mtr_t mtr;
page_t* header_page;
ulint flags;
ulint zip_size;
ulint page_no;
page_t* page;
page_t* root;
page_t* bitmap_page;
mtr_t mtr;
page_t* header_page;
ulint flags;
ulint zip_size;
buf_block_t* block;
page_t* page;
page_t* root;
page_t* bitmap_page;
mtr_start(&mtr);
......@@ -2250,28 +2250,23 @@ ibuf_add_free_page(void)
of a deadlock. This is the reason why we created a special ibuf
header page apart from the ibuf tree. */
page_no = fseg_alloc_free_page(
block = fseg_alloc_free_page(
header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 0, FSP_UP,
&mtr);
if (UNIV_UNLIKELY(page_no == FIL_NULL)) {
if (block == NULL) {
mtr_commit(&mtr);
return(FALSE);
} else {
buf_block_t* block = buf_page_get(
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
ibuf_enter(&mtr);
mutex_enter(&ibuf_mutex);
root = ibuf_tree_root_get(&mtr);
}
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
ibuf_enter(&mtr);
mutex_enter(&ibuf_mutex);
root = ibuf_tree_root_get(&mtr);
page = buf_block_get_frame(block);
}
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
page = buf_block_get_frame(block);
/* Add the page to the free list and update the ibuf size data */
......@@ -2288,12 +2283,13 @@ ibuf_add_free_page(void)
(level 2 page) */
bitmap_page = ibuf_bitmap_get_map_page(
IBUF_SPACE_ID, page_no, zip_size, &mtr);
IBUF_SPACE_ID, buf_block_get_page_no(block), zip_size, &mtr);
mutex_exit(&ibuf_mutex);
ibuf_bitmap_page_set_bits(
bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, TRUE, &mtr);
bitmap_page, buf_block_get_page_no(block), zip_size,
IBUF_BITMAP_IBUF, TRUE, &mtr);
ibuf_mtr_commit(&mtr);
......@@ -2588,7 +2584,15 @@ ibuf_get_merge_page_nos_func(
} else {
rec_page_no = ibuf_rec_get_page_no(mtr, rec);
rec_space_id = ibuf_rec_get_space(mtr, rec);
ut_ad(rec_page_no > IBUF_TREE_ROOT_PAGE_NO);
/* In the system tablespace, the smallest
possible secondary index leaf page number is
bigger than IBUF_TREE_ROOT_PAGE_NO (4). In
other tablespaces, the clustered index tree is
created at page 3, which makes page 4 the
smallest possible secondary index leaf page
(and that only after DROP INDEX). */
ut_ad(rec_page_no
> IBUF_TREE_ROOT_PAGE_NO - (rec_space_id != 0));
}
#ifdef UNIV_IBUF_DEBUG
......@@ -3920,6 +3924,7 @@ ibuf_insert_to_index_page_low(
fputs("InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n", stderr);
ut_ad(0);
}
/************************************************************************
......@@ -3970,9 +3975,10 @@ ibuf_insert_to_index_page(
"InnoDB: but the number of fields does not match!\n",
stderr);
dump:
buf_page_print(page, 0);
buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH);
dtuple_print(stderr, entry);
ut_ad(0);
fputs("InnoDB: The table where where"
" this index record belongs\n"
......@@ -4113,6 +4119,11 @@ ibuf_set_del_mark(
TRUE, mtr);
}
} else {
const page_t* page
= page_cur_get_page(&page_cur);
const buf_block_t* block
= page_cur_get_block(&page_cur);
ut_print_timestamp(stderr);
fputs(" InnoDB: unable to find a record to delete-mark\n",
stderr);
......@@ -4121,10 +4132,14 @@ ibuf_set_del_mark(
fputs("\n"
"InnoDB: record ", stderr);
rec_print(stderr, page_cur_get_rec(&page_cur), index);
putc('\n', stderr);
fputs("\n"
"InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n", stderr);
fprintf(stderr, "\nspace %u offset %u"
" (%u records, index id %llu)\n"
"InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n",
(unsigned) buf_block_get_space(block),
(unsigned) buf_block_get_page_no(block),
(unsigned) page_get_n_recs(page),
(ulonglong) btr_page_get_index_id(page));
ut_ad(0);
}
}
......@@ -4168,12 +4183,31 @@ ibuf_delete(
offsets = rec_get_offsets(
rec, index, offsets, ULINT_UNDEFINED, &heap);
/* Refuse to delete the last record. */
ut_a(page_get_n_recs(page) > 1);
/* The record should have been marked for deletion. */
ut_ad(REC_INFO_DELETED_FLAG
& rec_get_info_bits(rec, page_is_comp(page)));
if (page_get_n_recs(page) <= 1
|| !(REC_INFO_DELETED_FLAG
& rec_get_info_bits(rec, page_is_comp(page)))) {
/* Refuse to purge the last record or a
record that has not been marked for deletion. */
ut_print_timestamp(stderr);
fputs(" InnoDB: unable to purge a record\n",
stderr);
fputs("InnoDB: tuple ", stderr);
dtuple_print(stderr, entry);
fputs("\n"
"InnoDB: record ", stderr);
rec_print_new(stderr, rec, offsets);
fprintf(stderr, "\nspace %u offset %u"
" (%u records, index id %llu)\n"
"InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n",
(unsigned) buf_block_get_space(block),
(unsigned) buf_block_get_page_no(block),
(unsigned) page_get_n_recs(page),
(ulonglong) btr_page_get_index_id(page));
ut_ad(0);
return;
}
lock_update_delete(block, rec);
......@@ -4259,6 +4293,7 @@ ibuf_restore_pos(
fprintf(stderr, "InnoDB: ibuf tree ok\n");
fflush(stderr);
ut_ad(0);
}
return(FALSE);
......@@ -4441,7 +4476,7 @@ ibuf_merge_or_delete_for_page(
function. When the counter is > 0, that prevents tablespace
from being dropped. */
tablespace_being_deleted = fil_inc_pending_ibuf_merges(space);
tablespace_being_deleted = fil_inc_pending_ops(space);
if (UNIV_UNLIKELY(tablespace_being_deleted)) {
/* Do not try to read the bitmap page from space;
......@@ -4467,7 +4502,7 @@ ibuf_merge_or_delete_for_page(
/* No inserts buffered for this page */
if (!tablespace_being_deleted) {
fil_decr_pending_ibuf_merges(space);
fil_decr_pending_ops(space);
}
return;
......@@ -4516,12 +4551,14 @@ ibuf_merge_or_delete_for_page(
bitmap_page = ibuf_bitmap_get_map_page(space, page_no,
zip_size, &mtr);
buf_page_print(bitmap_page, 0);
buf_page_print(bitmap_page, 0,
BUF_PAGE_PRINT_NO_CRASH);
ibuf_mtr_commit(&mtr);
fputs("\nInnoDB: Dump of the page:\n", stderr);
buf_page_print(block->frame, 0);
buf_page_print(block->frame, 0,
BUF_PAGE_PRINT_NO_CRASH);
fprintf(stderr,
"InnoDB: Error: corruption in the tablespace."
......@@ -4541,6 +4578,7 @@ ibuf_merge_or_delete_for_page(
(ulong) page_no,
(ulong)
fil_page_get_type(block->frame));
ut_ad(0);
}
}
......@@ -4747,7 +4785,7 @@ reset_bit:
mem_heap_free(heap);
#ifdef HAVE_ATOMIC_BUILTINS
os_atomic_increment_ulint(&ibuf->n_merges, 1);
(void) os_atomic_increment_ulint(&ibuf->n_merges, 1);
ibuf_add_ops(ibuf->n_merged_ops, mops);
ibuf_add_ops(ibuf->n_discarded_ops, dops);
#else /* HAVE_ATOMIC_BUILTINS */
......@@ -4763,7 +4801,7 @@ reset_bit:
if (update_ibuf_bitmap && !tablespace_being_deleted) {
fil_decr_pending_ibuf_merges(space);
fil_decr_pending_ops(space);
}
#ifdef UNIV_IBUF_COUNT_DEBUG
......
/*****************************************************************************
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
......@@ -92,6 +92,26 @@ insert/delete buffer when the record is not in the buffer pool. */
buffer when the record is not in the buffer pool. */
#define BTR_DELETE 8192
/**************************************************************//**
Report that an index page is corrupted. */
UNIV_INTERN
void
btr_corruption_report(
/*==================*/
const buf_block_t* block, /*!< in: corrupted block */
const dict_index_t* index) /*!< in: index tree */
UNIV_COLD __attribute__((nonnull));
/** Assert that a B-tree page is not corrupted.
@param block buffer block containing a B-tree page
@param index the B-tree index */
#define btr_assert_not_corrupted(block, index) \
if ((ibool) !!page_is_comp(buf_block_get_frame(block)) \
!= dict_table_is_comp((index)->table)) { \
btr_corruption_report(block, index); \
ut_error; \
}
#ifdef UNIV_BLOB_DEBUG
# include "ut0rbt.h"
/** An index->blobs entry for keeping track of off-page column references */
......@@ -569,11 +589,14 @@ UNIV_INTERN
ibool
btr_compress(
/*=========*/
btr_cur_t* cursor, /*!< in: cursor on the page to merge or lift;
the page must not be empty: in record delete
use btr_discard_page if the page would become
empty */
mtr_t* mtr); /*!< in: mtr */
btr_cur_t* cursor, /*!< in/out: cursor on the page to merge
or lift; the page must not be empty:
when deleting records, use btr_discard_page()
if the page would become empty */
ibool adjust, /*!< in: TRUE if should adjust the
cursor position even if compression occurs */
mtr_t* mtr) /*!< in/out: mini-transaction */
__attribute__((nonnull));
/*************************************************************//**
Discards a page from a B-tree. This is used to remove the last record from
a B-tree page: the whole page must be removed at the same time. This cannot
......@@ -614,17 +637,23 @@ btr_parse_page_reorganize(
#ifndef UNIV_HOTBACKUP
/**************************************************************//**
Gets the number of pages in a B-tree.
@return number of pages */
@return number of pages, or ULINT_UNDEFINED if the index is unavailable */
UNIV_INTERN
ulint
btr_get_size(
/*=========*/
dict_index_t* index, /*!< in: index */
ulint flag); /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
mtr_t* mtr) /*!< in/out: mini-transaction where index
is s-latched */
__attribute__((nonnull, warn_unused_result));
/**************************************************************//**
Allocates a new file page to be used in an index tree. NOTE: we assume
that the caller has made the reservation for free extents!
@return new allocated block, x-latched; NULL if out of space */
@retval NULL if no page could be allocated
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
(init_mtr == mtr, or the page was not previously freed in mtr)
@retval block (not allocated or initialized) otherwise */
UNIV_INTERN
buf_block_t*
btr_page_alloc(
......@@ -635,7 +664,12 @@ btr_page_alloc(
page split is made */
ulint level, /*!< in: level where the page is placed
in the tree */
mtr_t* mtr); /*!< in: mtr */
mtr_t* mtr, /*!< in/out: mini-transaction
for the allocation */
mtr_t* init_mtr) /*!< in/out: mini-transaction
for x-latching and initializing
the page */
__attribute__((nonnull, warn_unused_result));
/**************************************************************//**
Frees a file page used in an index tree. NOTE: cannot free field external
storage pages because the page must contain info on its level. */
......
......@@ -279,7 +279,7 @@ btr_node_ptr_get_child_page_no(
"InnoDB: a nonsensical page number 0"
" in a node ptr record at offset %lu\n",
(ulong) page_offset(rec));
buf_page_print(page_align(rec), 0);
buf_page_print(page_align(rec), 0, 0);
}
return(page_no);
......
/*****************************************************************************
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
......@@ -36,6 +36,9 @@ Created 10/16/1994 Heikki Tuuri
#define BTR_NO_LOCKING_FLAG 2 /* do no record lock checking */
#define BTR_KEEP_SYS_FLAG 4 /* sys fields will be found from the
update vector or inserted entry */
#define BTR_KEEP_POS_FLAG 8 /* btr_cur_pessimistic_update()
must keep cursor position when
moving columns to big_rec */
#ifndef UNIV_HOTBACKUP
#include "que0types.h"
......@@ -310,7 +313,9 @@ btr_cur_pessimistic_update(
/*=======================*/
ulint flags, /*!< in: undo logging, locking, and rollback
flags */
btr_cur_t* cursor, /*!< in: cursor on the record to update */
btr_cur_t* cursor, /*!< in/out: cursor on the record to update;
cursor may become invalid if *big_rec == NULL
|| !(flags & BTR_KEEP_POS_FLAG) */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
be stored externally by the caller, or NULL */
......@@ -364,10 +369,13 @@ UNIV_INTERN
ibool
btr_cur_compress_if_useful(
/*=======================*/
btr_cur_t* cursor, /*!< in: cursor on the page to compress;
btr_cur_t* cursor, /*!< in/out: cursor on the page to compress;
cursor does not stay valid if compression
occurs */
mtr_t* mtr); /*!< in: mtr */
ibool adjust, /*!< in: TRUE if should adjust the
cursor position even if compression occurs */
mtr_t* mtr) /*!< in/out: mini-transaction */
__attribute__((nonnull));
/*******************************************************//**
Removes the record on which the tree cursor is positioned. It is assumed
that the mtr has an x-latch on the page where the cursor is positioned,
......@@ -492,6 +500,27 @@ btr_cur_disown_inherited_fields(
const upd_t* update, /*!< in: update vector */
mtr_t* mtr) /*!< in/out: mini-transaction */
__attribute__((nonnull(2,3,4,5,6)));
/** Operation code for btr_store_big_rec_extern_fields(). */
enum blob_op {
/** Store off-page columns for a freshly inserted record */
BTR_STORE_INSERT = 0,
/** Store off-page columns for an insert by update */
BTR_STORE_INSERT_UPDATE,
/** Store off-page columns for an update */
BTR_STORE_UPDATE
};
/*******************************************************************//**
Determine if an operation on off-page columns is an update.
@return TRUE if op != BTR_STORE_INSERT */
UNIV_INLINE
ibool
btr_blob_op_is_update(
/*==================*/
enum blob_op op) /*!< in: operation */
__attribute__((warn_unused_result));
/*******************************************************************//**
Stores the fields in big_rec_vec to the tablespace and puts pointers to
them in rec. The extern flags in rec will have to be set beforehand.
......@@ -499,52 +528,23 @@ The fields are stored on pages allocated from leaf node
file segment of the index tree.
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN
ulint
btr_store_big_rec_extern_fields_func(
/*=================================*/
enum db_err
btr_store_big_rec_extern_fields(
/*============================*/
dict_index_t* index, /*!< in: index of rec; the index tree
MUST be X-latched */
buf_block_t* rec_block, /*!< in/out: block containing rec */
rec_t* rec, /*!< in: record */
rec_t* rec, /*!< in/out: record */
const ulint* offsets, /*!< in: rec_get_offsets(rec, index);
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
#ifdef UNIV_DEBUG
mtr_t* local_mtr, /*!< in: mtr containing the
latch to rec and to the tree */
#endif /* UNIV_DEBUG */
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ibool update_in_place,/*! in: TRUE if the record is updated
in place (not delete+insert) */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
const big_rec_t*big_rec_vec) /*!< in: vector containing fields
const big_rec_t*big_rec_vec, /*!< in: vector containing fields
to be stored externally */
__attribute__((nonnull));
/** Stores the fields in big_rec_vec to the tablespace and puts pointers to
them in rec. The extern flags in rec will have to be set beforehand.
The fields are stored on pages allocated from leaf node
file segment of the index tree.
@param index in: clustered index; MUST be X-latched by mtr
@param b in/out: block containing rec; MUST be X-latched by mtr
@param rec in/out: clustered index record
@param offsets in: rec_get_offsets(rec, index);
the "external storage" flags in offsets will not be adjusted
@param mtr in: mini-transaction that holds x-latch on index and b
@param upd in: TRUE if the record is updated in place (not delete+insert)
@param big in: vector containing fields to be stored externally
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
#ifdef UNIV_DEBUG
# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
btr_store_big_rec_extern_fields_func(index,b,rec,offsets,mtr,upd,big)
#elif defined UNIV_BLOB_LIGHT_DEBUG
# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
btr_store_big_rec_extern_fields_func(index,b,rec,offsets,upd,big)
#else
# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
btr_store_big_rec_extern_fields_func(index,b,rec,offsets,big)
#endif
mtr_t* btr_mtr, /*!< in: mtr containing the
latches to the clustered index */
enum blob_op op) /*! in: operation code */
__attribute__((nonnull, warn_unused_result));
/*******************************************************************//**
Frees the space in an externally stored field to the file space
......
This diff is collapsed.
......@@ -53,6 +53,16 @@ UNIV_INTERN
btr_pcur_t*
btr_pcur_create_for_mysql(void);
/*============================*/
/**************************************************************//**
Resets a persistent cursor object, freeing ::old_rec_buf if it is
allocated and resetting the other members to their initial values. */
UNIV_INTERN
void
btr_pcur_reset(
/*===========*/
btr_pcur_t* cursor);/*!< in, out: persistent cursor */
/**************************************************************//**
Frees the memory for a persistent cursor object. */
UNIV_INTERN
......
This diff is collapsed.
This diff is collapsed.
......@@ -64,15 +64,14 @@ These are low-level functions
#define BUF_LRU_FREE_SEARCH_LEN(b) (5 + 2 * BUF_READ_AHEAD_AREA(b))
/******************************************************************//**
Invalidates all pages belonging to a given tablespace when we are deleting
the data file(s) of that tablespace. A PROBLEM: if readahead is being started,
what guarantees that it will not try to read in pages after this operation has
completed? */
Removes all pages belonging to a given tablespace. */
UNIV_INTERN
void
buf_LRU_invalidate_tablespace(
buf_LRU_flush_or_remove_pages(
/*==========================*/
ulint id); /*!< in: space id */
ulint id, /*!< in: space id */
enum buf_remove_t buf_remove);/*!< in: remove or flush
strategy */
/******************************************************************//**
*/
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -208,10 +208,6 @@ mem_heap_alloc(
caller */
buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
#endif
#ifdef UNIV_SET_MEM_TO_ZERO
UNIV_MEM_ALLOC(buf, n);
memset(buf, '\0', n);
#endif
UNIV_MEM_ALLOC(buf, n);
return(buf);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment