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 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
...@@ -52,12 +52,13 @@ btr_pcur_create_for_mysql(void) ...@@ -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 UNIV_INTERN
void void
btr_pcur_free_for_mysql( btr_pcur_reset(
/*====================*/ /*===========*/
btr_pcur_t* cursor) /*!< in, own: persistent cursor */ btr_pcur_t* cursor) /*!< in, out: persistent cursor */
{ {
if (cursor->old_rec_buf != NULL) { if (cursor->old_rec_buf != NULL) {
...@@ -66,6 +67,7 @@ btr_pcur_free_for_mysql( ...@@ -66,6 +67,7 @@ btr_pcur_free_for_mysql(
cursor->old_rec_buf = NULL; cursor->old_rec_buf = NULL;
} }
cursor->btr_cur.index = NULL;
cursor->btr_cur.page_cur.rec = NULL; cursor->btr_cur.page_cur.rec = NULL;
cursor->old_rec = NULL; cursor->old_rec = NULL;
cursor->old_n_fields = 0; cursor->old_n_fields = 0;
...@@ -73,7 +75,17 @@ btr_pcur_free_for_mysql( ...@@ -73,7 +75,17 @@ btr_pcur_free_for_mysql(
cursor->latch_mode = BTR_NO_LATCHES; cursor->latch_mode = BTR_NO_LATCHES;
cursor->pos_state = BTR_PCUR_NOT_POSITIONED; 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); mem_free(cursor);
} }
...@@ -127,6 +139,8 @@ btr_pcur_store_position( ...@@ -127,6 +139,8 @@ btr_pcur_store_position(
ut_a(btr_page_get_next(page, mtr) == FIL_NULL); ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
ut_a(btr_page_get_prev(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; cursor->old_stored = BTR_PCUR_OLD_STORED;
...@@ -319,13 +333,19 @@ btr_pcur_restore_position_func( ...@@ -319,13 +333,19 @@ btr_pcur_restore_position_func(
/* Save the old search mode of the cursor */ /* Save the old search mode of the cursor */
old_mode = cursor->search_mode; 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; mode = PAGE_CUR_LE;
} else if (cursor->rel_pos == BTR_PCUR_AFTER) { break;
case BTR_PCUR_AFTER:
mode = PAGE_CUR_G; mode = PAGE_CUR_G;
} else { break;
ut_ad(cursor->rel_pos == BTR_PCUR_BEFORE); case BTR_PCUR_BEFORE:
mode = PAGE_CUR_L; mode = PAGE_CUR_L;
break;
default:
ut_error;
mode = 0;
} }
btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode, btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode,
...@@ -334,25 +354,44 @@ btr_pcur_restore_position_func( ...@@ -334,25 +354,44 @@ btr_pcur_restore_position_func(
/* Restore the old search mode */ /* Restore the old search mode */
cursor->search_mode = old_mode; cursor->search_mode = old_mode;
if (cursor->rel_pos == BTR_PCUR_ON if (btr_pcur_is_on_user_rec(cursor)) {
&& btr_pcur_is_on_user_rec(cursor) switch (cursor->rel_pos) {
&& 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor), case BTR_PCUR_ON:
rec_get_offsets( if (!cmp_dtuple_rec(
btr_pcur_get_rec(cursor), index, tuple, btr_pcur_get_rec(cursor),
NULL, ULINT_UNDEFINED, &heap))) { rec_get_offsets(btr_pcur_get_rec(cursor),
index, NULL,
/* We have to store the NEW value for the modify clock, since ULINT_UNDEFINED, &heap))) {
the cursor can now be on a different page! But we can retain
the value of old_rec */ /* 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); mem_heap_free(heap);
cursor->modify_clock = buf_block_get_modify_clock(
cursor->block_when_stored);
cursor->old_stored = BTR_PCUR_OLD_STORED;
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); 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. 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
...@@ -1240,7 +1240,7 @@ cleanup: ...@@ -1240,7 +1240,7 @@ cleanup:
index->name, (ulong) block->n_pointers); index->name, (ulong) block->n_pointers);
rw_lock_x_unlock(btr_search_get_latch(index->id)); rw_lock_x_unlock(btr_search_get_latch(index->id));
btr_search_validate(); ut_ad(btr_search_validate());
} else { } else {
rw_lock_x_unlock(btr_search_get_latch(index->id)); rw_lock_x_unlock(btr_search_get_latch(index->id));
} }
...@@ -2143,7 +2143,9 @@ btr_search_validate(void) ...@@ -2143,7 +2143,9 @@ btr_search_validate(void)
(ulong) block->curr_left_side); (ulong) block->curr_left_side);
if (n_page_dumps < 20) { if (n_page_dumps < 20) {
buf_page_print(page, 0); buf_page_print(
page, 0,
BUF_PAGE_PRINT_NO_CRASH);
n_page_dumps++; 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. 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,7 +57,9 @@ Created 11/5/1995 Heikki Tuuri ...@@ -57,7 +57,9 @@ Created 11/5/1995 Heikki Tuuri
/* prototypes for new functions added to ha_innodb.cc */ /* prototypes for new functions added to ha_innodb.cc */
trx_t* innobase_get_trx(); 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;
ulint block_hash_byte; ulint block_hash_byte;
...@@ -680,8 +682,12 @@ void ...@@ -680,8 +682,12 @@ void
buf_page_print( buf_page_print(
/*===========*/ /*===========*/
const byte* read_buf, /*!< in: a database page */ const byte* read_buf, /*!< in: a database page */
ulint zip_size) /*!< in: compressed page size, or ulint zip_size, /*!< in: compressed page size, or
0 for uncompressed pages */ 0 for uncompressed pages */
ulint flags) /*!< in: 0 or
BUF_PAGE_PRINT_NO_CRASH or
BUF_PAGE_PRINT_NO_FULL */
{ {
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
dict_index_t* index; dict_index_t* index;
...@@ -695,11 +701,14 @@ buf_page_print( ...@@ -695,11 +701,14 @@ buf_page_print(
size = UNIV_PAGE_SIZE; size = UNIV_PAGE_SIZE;
} }
ut_print_timestamp(stderr); if (!(flags & BUF_PAGE_PRINT_NO_FULL)) {
fprintf(stderr, " InnoDB: Page dump in ascii and hex (%lu bytes):\n", ut_print_timestamp(stderr);
(ulong) size); fprintf(stderr,
ut_print_buf(stderr, read_buf, size); " InnoDB: Page dump in ascii and hex (%lu bytes):\n",
fputs("\nInnoDB: End of page dump\n", stderr); (ulong) size);
ut_print_buf(stderr, read_buf, size);
fputs("\nInnoDB: End of page dump\n", stderr);
}
if (zip_size) { if (zip_size) {
/* Print compressed page. */ /* Print compressed page. */
...@@ -873,6 +882,8 @@ buf_page_print( ...@@ -873,6 +882,8 @@ buf_page_print(
stderr); stderr);
break; break;
} }
ut_ad(flags & BUF_PAGE_PRINT_NO_CRASH);
} }
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
...@@ -1078,11 +1089,8 @@ buf_chunk_init( ...@@ -1078,11 +1089,8 @@ buf_chunk_init(
for (i = chunk->size; i--; ) { for (i = chunk->size; i--; ) {
buf_block_init(buf_pool, block, frame); 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 */ /* Add the block to the free list */
mutex_enter(&buf_pool->free_list_mutex); mutex_enter(&buf_pool->free_list_mutex);
UT_LIST_ADD_LAST(free, buf_pool->free, (&block->page)); UT_LIST_ADD_LAST(free, buf_pool->free, (&block->page));
...@@ -2768,7 +2776,7 @@ wait_until_unfixed: ...@@ -2768,7 +2776,7 @@ wait_until_unfixed:
block->page.buf_fix_count = 1; block->page.buf_fix_count = 1;
buf_block_set_io_fix(block, BUF_IO_READ); 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); UNIV_MEM_INVALID(bpage, sizeof *bpage);
...@@ -2931,14 +2939,14 @@ wait_until_unfixed: ...@@ -2931,14 +2939,14 @@ wait_until_unfixed:
break; break;
case RW_S_LATCH: 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; fix_type = MTR_MEMO_PAGE_S_FIX;
break; break;
default: default:
ut_ad(rw_latch == RW_X_LATCH); 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; fix_type = MTR_MEMO_PAGE_X_FIX;
break; break;
...@@ -3023,8 +3031,8 @@ buf_page_optimistic_get( ...@@ -3023,8 +3031,8 @@ buf_page_optimistic_get(
file, line); file, line);
fix_type = MTR_MEMO_PAGE_S_FIX; fix_type = MTR_MEMO_PAGE_S_FIX;
} else { } else {
success = rw_lock_x_lock_func_nowait(&(block->lock), success = rw_lock_x_lock_func_nowait_inline(&(block->lock),
file, line); file, line);
fix_type = MTR_MEMO_PAGE_X_FIX; fix_type = MTR_MEMO_PAGE_X_FIX;
} }
...@@ -3165,8 +3173,8 @@ buf_page_get_known_nowait( ...@@ -3165,8 +3173,8 @@ buf_page_get_known_nowait(
file, line); file, line);
fix_type = MTR_MEMO_PAGE_S_FIX; fix_type = MTR_MEMO_PAGE_S_FIX;
} else { } else {
success = rw_lock_x_lock_func_nowait(&(block->lock), success = rw_lock_x_lock_func_nowait_inline(&(block->lock),
file, line); file, line);
fix_type = MTR_MEMO_PAGE_X_FIX; fix_type = MTR_MEMO_PAGE_X_FIX;
} }
...@@ -3186,7 +3194,7 @@ buf_page_get_known_nowait( ...@@ -3186,7 +3194,7 @@ buf_page_get_known_nowait(
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_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 #endif
#ifdef UNIV_IBUF_COUNT_DEBUG #ifdef UNIV_IBUF_COUNT_DEBUG
...@@ -3261,8 +3269,8 @@ buf_page_try_get_func( ...@@ -3261,8 +3269,8 @@ buf_page_try_get_func(
S-latch. */ S-latch. */
fix_type = MTR_MEMO_PAGE_X_FIX; fix_type = MTR_MEMO_PAGE_X_FIX;
success = rw_lock_x_lock_func_nowait(&block->lock, success = rw_lock_x_lock_func_nowait_inline(&block->lock,
file, line); file, line);
} }
if (!success) { if (!success) {
...@@ -3997,7 +4005,8 @@ corrupt: ...@@ -3997,7 +4005,8 @@ corrupt:
"InnoDB: You may have to recover" "InnoDB: You may have to recover"
" from a backup.\n", " from a backup.\n",
(ulong) bpage->offset); (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, fprintf(stderr,
"InnoDB: Database page corruption on disk" "InnoDB: Database page corruption on disk"
" or a failed\n" " or a failed\n"
...@@ -5285,34 +5294,32 @@ buf_all_freed(void) ...@@ -5285,34 +5294,32 @@ buf_all_freed(void)
/*********************************************************************//** /*********************************************************************//**
Checks that there currently are no pending i/o-operations for the buffer Checks that there currently are no pending i/o-operations for the buffer
pool. pool.
@return TRUE if there is no pending i/o */ @return number of pending i/o */
UNIV_INTERN UNIV_INTERN
ibool ulint
buf_pool_check_no_pending_io(void) buf_pool_check_num_pending_io(void)
/*==============================*/ /*===============================*/
{ {
ulint i; ulint i;
ibool ret = TRUE; ulint pending_io = 0;
buf_pool_mutex_enter_all(); 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; const buf_pool_t* buf_pool;
buf_pool = buf_pool_from_array(i); buf_pool = buf_pool_from_array(i);
if (buf_pool->n_pend_reads pending_io += buf_pool->n_pend_reads
+ buf_pool->n_flush[BUF_FLUSH_LRU] + buf_pool->n_flush[BUF_FLUSH_LRU]
+ buf_pool->n_flush[BUF_FLUSH_LIST] + buf_pool->n_flush[BUF_FLUSH_LIST]
+ buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) { + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE];
ret = FALSE;
}
} }
buf_pool_mutex_exit_all(); buf_pool_mutex_exit_all();
return(ret); return(pending_io);
} }
#if 0 #if 0
......
...@@ -767,7 +767,8 @@ buf_flush_buffered_writes(void) ...@@ -767,7 +767,8 @@ buf_flush_buffered_writes(void)
if (UNIV_UNLIKELY if (UNIV_UNLIKELY
(!page_simple_validate_new(block->frame))) { (!page_simple_validate_new(block->frame))) {
corrupted_page: corrupted_page:
buf_page_print(block->frame, 0); buf_page_print(block->frame, 0,
BUF_PAGE_PRINT_NO_CRASH);
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
...@@ -2036,22 +2037,6 @@ buf_flush_list( ...@@ -2036,22 +2037,6 @@ buf_flush_list(
buf_pool = buf_pool_from_array(i); 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)) { if (!buf_flush_start(buf_pool, BUF_FLUSH_LIST)) {
/* We have two choices here. If lsn_limit was /* We have two choices here. If lsn_limit was
specified then skipping an instance of buffer specified then skipping an instance of buffer
......
This diff is collapsed.
...@@ -239,6 +239,166 @@ dict_hdr_create( ...@@ -239,6 +239,166 @@ dict_hdr_create(
return(TRUE); 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 Initializes the data dictionary memory structures when the database is
started. This function is also called when the data dictionary is created. */ started. This function is also called when the data dictionary is created. */
...@@ -254,13 +414,13 @@ dict_boot(void) ...@@ -254,13 +414,13 @@ dict_boot(void)
mtr_t mtr; mtr_t mtr;
ulint error; ulint error;
heap = mem_heap_create(450);
mtr_start(&mtr); mtr_start(&mtr);
/* Create the hash tables etc. */ /* Create the hash tables etc. */
dict_init(); dict_init();
heap = mem_heap_create(450);
mutex_enter(&(dict_sys->mutex)); mutex_enter(&(dict_sys->mutex));
/* Get the dictionary header */ /* Get the dictionary header */
...@@ -268,25 +428,9 @@ dict_boot(void) ...@@ -268,25 +428,9 @@ dict_boot(void)
if (mach_read_from_8(dict_hdr + DICT_HDR_XTRADB_MARK) if (mach_read_from_8(dict_hdr + DICT_HDR_XTRADB_MARK)
!= DICT_HDR_XTRADB_FLAG) { != DICT_HDR_XTRADB_FLAG) {
/* not extended yet by XtraDB, need to be extended */ /* not extended yet by XtraDB, need to be extended */
ulint root_page_no; dict_create_xtradb_sys_stats(&dict_hdr, &mtr);
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);
} }
/* Because we only write new row ids to disk-based data structure /* Because we only write new row ids to disk-based data structure
...@@ -465,42 +609,7 @@ dict_boot(void) ...@@ -465,42 +609,7 @@ dict_boot(void)
FALSE); FALSE);
ut_a(error == DB_SUCCESS); ut_a(error == DB_SUCCESS);
/*-------------------------*/ dict_add_to_cache_xtradb_sys_stats(TRUE, heap, dict_hdr, &mtr);
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);
mem_heap_free(heap); 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 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 ...@@ -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
*****************************************************************************/ *****************************************************************************/
...@@ -56,6 +56,8 @@ UNIV_INTERN dict_index_t* dict_ind_compact; ...@@ -56,6 +56,8 @@ UNIV_INTERN dict_index_t* dict_ind_compact;
#include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str()*/ #include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str()*/
#include "row0upd.h" #include "row0upd.h"
#include "srv0start.h" /* SRV_LOG_SPACE_FIRST_ID */ #include "srv0start.h" /* SRV_LOG_SPACE_FIRST_ID */
#include "m_string.h"
#include "my_sys.h"
#include <ctype.h> #include <ctype.h>
...@@ -2397,6 +2399,8 @@ dict_foreign_free( ...@@ -2397,6 +2399,8 @@ dict_foreign_free(
/*==============*/ /*==============*/
dict_foreign_t* foreign) /*!< in, own: foreign key struct */ 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); mem_heap_free(foreign->heap);
} }
...@@ -4378,25 +4382,32 @@ dict_reload_statistics( ...@@ -4378,25 +4382,32 @@ dict_reload_statistics(
heap = mem_heap_create(1000); heap = mem_heap_create(1000);
while (index) { while (index) {
mtr_t mtr;
if (table->is_corrupt) { if (table->is_corrupt) {
ut_a(srv_pass_corrupt_table); ut_a(srv_pass_corrupt_table);
mem_heap_free(heap); mem_heap_free(heap);
return(FALSE); 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; index->stat_index_size = size;
*sum_of_index_sizes += 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) { if (size == 0) {
/* The root node of the tree is a leaf */ /* The root node of the tree is a leaf */
size = 1; size = 1;
} }
mtr_commit(&mtr);
index->stat_n_leaf_pages = size; index->stat_n_leaf_pages = size;
/*===========================================*/ /*===========================================*/
...@@ -4728,6 +4739,7 @@ dict_update_statistics( ...@@ -4728,6 +4739,7 @@ dict_update_statistics(
(srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE
|| (srv_force_recovery < SRV_FORCE_NO_LOG_REDO || (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
&& dict_index_is_clust(index)))) { && dict_index_is_clust(index)))) {
mtr_t mtr;
ulint size; ulint size;
if (table->is_corrupt) { if (table->is_corrupt) {
...@@ -4736,15 +4748,24 @@ dict_update_statistics( ...@@ -4736,15 +4748,24 @@ dict_update_statistics(
return; 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 */ /* The root node of the tree is a leaf */
size = 1; size = 1;
} }
...@@ -4761,6 +4782,7 @@ dict_update_statistics( ...@@ -4761,6 +4782,7 @@ dict_update_statistics(
various means, also via secondary indexes. */ various means, also via secondary indexes. */
ulint i; ulint i;
fake_statistics:
sum_of_index_sizes++; sum_of_index_sizes++;
index->stat_index_size = index->stat_n_leaf_pages = 1; index->stat_index_size = index->stat_n_leaf_pages = 1;
......
...@@ -2138,8 +2138,9 @@ static ...@@ -2138,8 +2138,9 @@ static
void void
dict_load_foreign_cols( dict_load_foreign_cols(
/*===================*/ /*===================*/
const char* id, /*!< in: foreign constraint id as a const char* id, /*!< in: foreign constraint id, not
null-terminated string */ necessary '\0'-terminated */
ulint id_len, /*!< in: id length */
dict_foreign_t* foreign)/*!< in: foreign constraint object */ dict_foreign_t* foreign)/*!< in: foreign constraint object */
{ {
dict_table_t* sys_foreign_cols; dict_table_t* sys_foreign_cols;
...@@ -2169,7 +2170,7 @@ dict_load_foreign_cols( ...@@ -2169,7 +2170,7 @@ dict_load_foreign_cols(
tuple = dtuple_create(foreign->heap, 1); tuple = dtuple_create(foreign->heap, 1);
dfield = dtuple_get_nth_field(tuple, 0); 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); dict_index_copy_types(tuple, sys_index, 1);
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
...@@ -2182,7 +2183,7 @@ dict_load_foreign_cols( ...@@ -2182,7 +2183,7 @@ dict_load_foreign_cols(
ut_a(!rec_get_deleted_flag(rec, 0)); ut_a(!rec_get_deleted_flag(rec, 0));
field = rec_get_nth_field_old(rec, 0, &len); 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); ut_a(ut_memcmp(id, field, len) == 0);
field = rec_get_nth_field_old(rec, 1, &len); field = rec_get_nth_field_old(rec, 1, &len);
...@@ -2211,8 +2212,9 @@ static ...@@ -2211,8 +2212,9 @@ static
ulint ulint
dict_load_foreign( dict_load_foreign(
/*==============*/ /*==============*/
const char* id, /*!< in: foreign constraint id as a const char* id, /*!< in: foreign constraint id, not
null-terminated string */ necessary '\0'-terminated */
ulint id_len, /*!< in: id length */
ibool check_charsets, ibool check_charsets,
/*!< in: TRUE=check charset compatibility */ /*!< in: TRUE=check charset compatibility */
ibool check_recursive) ibool check_recursive)
...@@ -2248,7 +2250,7 @@ dict_load_foreign( ...@@ -2248,7 +2250,7 @@ dict_load_foreign(
tuple = dtuple_create(heap2, 1); tuple = dtuple_create(heap2, 1);
dfield = dtuple_get_nth_field(tuple, 0); 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); dict_index_copy_types(tuple, sys_index, 1);
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
...@@ -2260,8 +2262,8 @@ dict_load_foreign( ...@@ -2260,8 +2262,8 @@ dict_load_foreign(
/* Not found */ /* Not found */
fprintf(stderr, fprintf(stderr,
"InnoDB: Error A: cannot load foreign constraint %s\n", "InnoDB: Error A: cannot load foreign constraint "
id); "%.*s\n", (int) id_len, id);
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
mtr_commit(&mtr); mtr_commit(&mtr);
...@@ -2273,11 +2275,11 @@ dict_load_foreign( ...@@ -2273,11 +2275,11 @@ dict_load_foreign(
field = rec_get_nth_field_old(rec, 0, &len); field = rec_get_nth_field_old(rec, 0, &len);
/* Check if the id in record is the searched one */ /* 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, fprintf(stderr,
"InnoDB: Error B: cannot load foreign constraint %s\n", "InnoDB: Error B: cannot load foreign constraint "
id); "%.*s\n", (int) id_len, id);
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
mtr_commit(&mtr); mtr_commit(&mtr);
...@@ -2303,7 +2305,7 @@ dict_load_foreign( ...@@ -2303,7 +2305,7 @@ dict_load_foreign(
foreign->type = (unsigned int) (n_fields_and_type >> 24); foreign->type = (unsigned int) (n_fields_and_type >> 24);
foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL); 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); field = rec_get_nth_field_old(rec, 3, &len);
...@@ -2319,7 +2321,7 @@ dict_load_foreign( ...@@ -2319,7 +2321,7 @@ dict_load_foreign(
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
mtr_commit(&mtr); 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( ref_table = dict_table_check_if_in_cache_low(
foreign->referenced_table_name_lookup); foreign->referenced_table_name_lookup);
...@@ -2398,8 +2400,8 @@ dict_load_foreigns( ...@@ -2398,8 +2400,8 @@ dict_load_foreigns(
ibool check_charsets) /*!< in: TRUE=check charset ibool check_charsets) /*!< in: TRUE=check charset
compatibility */ compatibility */
{ {
char tuple_buf[DTUPLE_EST_ALLOC(1)];
btr_pcur_t pcur; btr_pcur_t pcur;
mem_heap_t* heap;
dtuple_t* tuple; dtuple_t* tuple;
dfield_t* dfield; dfield_t* dfield;
dict_index_t* sec_index; dict_index_t* sec_index;
...@@ -2407,7 +2409,6 @@ dict_load_foreigns( ...@@ -2407,7 +2409,6 @@ dict_load_foreigns(
const rec_t* rec; const rec_t* rec;
const byte* field; const byte* field;
ulint len; ulint len;
char* id ;
ulint err; ulint err;
mtr_t mtr; mtr_t mtr;
...@@ -2434,9 +2435,8 @@ dict_load_foreigns( ...@@ -2434,9 +2435,8 @@ dict_load_foreigns(
sec_index = dict_table_get_next_index( sec_index = dict_table_get_next_index(
dict_table_get_first_index(sys_foreign)); dict_table_get_first_index(sys_foreign));
start_load: 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 = dtuple_get_nth_field(tuple, 0);
dfield_set_data(dfield, table_name, ut_strlen(table_name)); dfield_set_data(dfield, table_name, ut_strlen(table_name));
...@@ -2490,7 +2490,6 @@ loop: ...@@ -2490,7 +2490,6 @@ loop:
/* Now we get a foreign key constraint id */ /* Now we get a foreign key constraint id */
field = rec_get_nth_field_old(rec, 1, &len); field = rec_get_nth_field_old(rec, 1, &len);
id = mem_heap_strdupl(heap, (char*) field, len);
btr_pcur_store_position(&pcur, &mtr); btr_pcur_store_position(&pcur, &mtr);
...@@ -2498,11 +2497,11 @@ loop: ...@@ -2498,11 +2497,11 @@ loop:
/* Load the foreign constraint definition to the dictionary cache */ /* 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) { if (err != DB_SUCCESS) {
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
mem_heap_free(heap);
return(err); return(err);
} }
...@@ -2518,7 +2517,6 @@ next_rec: ...@@ -2518,7 +2517,6 @@ next_rec:
load_next_index: load_next_index:
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
mtr_commit(&mtr); mtr_commit(&mtr);
mem_heap_free(heap);
sec_index = dict_table_get_next_index(sec_index); sec_index = dict_table_get_next_index(sec_index);
......
...@@ -193,7 +193,7 @@ struct fil_space_struct { ...@@ -193,7 +193,7 @@ struct fil_space_struct {
.ibd file of tablespace and want to .ibd file of tablespace and want to
stop temporarily posting of new i/o stop temporarily posting of new i/o
requests on the file */ requests on the file */
ibool stop_ibuf_merges; ibool stop_new_ops;
/*!< we set this TRUE when we start /*!< we set this TRUE when we start
deleting a single-table tablespace */ deleting a single-table tablespace */
ibool is_being_deleted; ibool is_being_deleted;
...@@ -218,12 +218,13 @@ struct fil_space_struct { ...@@ -218,12 +218,13 @@ struct fil_space_struct {
ulint n_pending_flushes; /*!< this is positive when flushing ulint n_pending_flushes; /*!< this is positive when flushing
the tablespace to disk; dropping of the the tablespace to disk; dropping of the
tablespace is forbidden if this is positive */ tablespace is forbidden if this is positive */
ulint n_pending_ibuf_merges;/*!< this is positive ulint n_pending_ops;/*!< this is positive when we
when merging insert buffer entries to have pending operations against this
a page so that we may need to access tablespace. The pending operations can
the ibuf bitmap page in the be ibuf merges or lock validation code
tablespade: dropping of the tablespace trying to read a block.
is forbidden if this is positive */ Dropping of the tablespace is forbidden
if this is positive */
hash_node_t hash; /*!< hash chain node */ hash_node_t hash; /*!< hash chain node */
hash_node_t name_hash;/*!< hash chain the name_hash table */ hash_node_t name_hash;/*!< hash chain the name_hash table */
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
...@@ -974,11 +975,6 @@ retry: ...@@ -974,11 +975,6 @@ retry:
return; return;
} }
if (fil_system->n_open < fil_system->max_n_open) {
return;
}
space = fil_space_get_by_id(space_id); space = fil_space_get_by_id(space_id);
if (space != NULL && space->stop_ios) { if (space != NULL && space->stop_ios) {
...@@ -995,6 +991,25 @@ retry: ...@@ -995,6 +991,25 @@ retry:
mutex_exit(&fil_system->mutex); 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); os_thread_sleep(20000);
count2++; count2++;
...@@ -1002,6 +1017,11 @@ retry: ...@@ -1002,6 +1017,11 @@ retry:
goto 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 /* 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 does not exist, we handle the situation in the function which called
this function */ this function */
...@@ -1274,7 +1294,7 @@ try_again: ...@@ -1274,7 +1294,7 @@ try_again:
} }
space->stop_ios = FALSE; space->stop_ios = FALSE;
space->stop_ibuf_merges = FALSE; space->stop_new_ops = FALSE;
space->is_being_deleted = FALSE; space->is_being_deleted = FALSE;
space->purpose = purpose; space->purpose = purpose;
space->size = 0; space->size = 0;
...@@ -1283,7 +1303,7 @@ try_again: ...@@ -1283,7 +1303,7 @@ try_again:
space->n_reserved_extents = 0; space->n_reserved_extents = 0;
space->n_pending_flushes = 0; space->n_pending_flushes = 0;
space->n_pending_ibuf_merges = 0; space->n_pending_ops = 0;
UT_LIST_INIT(space->chain); UT_LIST_INIT(space->chain);
space->magic_n = FIL_SPACE_MAGIC_N; space->magic_n = FIL_SPACE_MAGIC_N;
...@@ -1896,13 +1916,12 @@ fil_read_first_page( ...@@ -1896,13 +1916,12 @@ fil_read_first_page(
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
/*******************************************************************//** /*******************************************************************//**
Increments the count of pending insert buffer page merges, if space is not Increments the count of pending operation, if space is not being deleted.
being deleted. @return TRUE if being deleted, and operation should be skipped */
@return TRUE if being deleted, and ibuf merges should be skipped */
UNIV_INTERN UNIV_INTERN
ibool ibool
fil_inc_pending_ibuf_merges( fil_inc_pending_ops(
/*========================*/ /*================*/
ulint id) /*!< in: space id */ ulint id) /*!< in: space id */
{ {
fil_space_t* space; fil_space_t* space;
...@@ -1918,13 +1937,13 @@ fil_inc_pending_ibuf_merges( ...@@ -1918,13 +1937,13 @@ fil_inc_pending_ibuf_merges(
(ulong) id); (ulong) id);
} }
if (space == NULL || space->stop_ibuf_merges) { if (space == NULL || space->stop_new_ops) {
mutex_exit(&fil_system->mutex); mutex_exit(&fil_system->mutex);
return(TRUE); return(TRUE);
} }
space->n_pending_ibuf_merges++; space->n_pending_ops++;
mutex_exit(&fil_system->mutex); mutex_exit(&fil_system->mutex);
...@@ -1932,11 +1951,11 @@ fil_inc_pending_ibuf_merges( ...@@ -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 UNIV_INTERN
void void
fil_decr_pending_ibuf_merges( fil_decr_pending_ops(
/*=========================*/ /*=================*/
ulint id) /*!< in: space id */ ulint id) /*!< in: space id */
{ {
fil_space_t* space; fil_space_t* space;
...@@ -1947,13 +1966,13 @@ fil_decr_pending_ibuf_merges( ...@@ -1947,13 +1966,13 @@ fil_decr_pending_ibuf_merges(
if (space == NULL) { if (space == NULL) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Error: decrementing ibuf merge of a" "InnoDB: Error: decrementing pending operation"
" dropped tablespace %lu\n", " of a dropped tablespace %lu\n",
(ulong) id); (ulong) id);
} }
if (space != NULL) { if (space != NULL) {
space->n_pending_ibuf_merges--; space->n_pending_ops--;
} }
mutex_exit(&fil_system->mutex); mutex_exit(&fil_system->mutex);
...@@ -2164,7 +2183,7 @@ fil_op_log_parse_or_replay( ...@@ -2164,7 +2183,7 @@ fil_op_log_parse_or_replay(
switch (type) { switch (type) {
case MLOG_FILE_DELETE: case MLOG_FILE_DELETE:
if (fil_tablespace_exists_in_mem(space_id)) { if (fil_tablespace_exists_in_mem(space_id)) {
ut_a(fil_delete_tablespace(space_id)); ut_a(fil_delete_tablespace(space_id, TRUE));
} }
break; break;
...@@ -2234,7 +2253,9 @@ UNIV_INTERN ...@@ -2234,7 +2253,9 @@ UNIV_INTERN
ibool ibool
fil_delete_tablespace( 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; ibool success;
fil_space_t* space; fil_space_t* space;
...@@ -2243,15 +2264,15 @@ fil_delete_tablespace( ...@@ -2243,15 +2264,15 @@ fil_delete_tablespace(
char* path; char* path;
ut_a(id != 0); ut_a(id != 0);
stop_ibuf_merges: stop_new_ops:
mutex_enter(&fil_system->mutex); mutex_enter(&fil_system->mutex);
space = fil_space_get_by_id(id); space = fil_space_get_by_id(id);
if (space != NULL) { 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); mutex_exit(&fil_system->mutex);
count = 0; count = 0;
...@@ -2265,9 +2286,10 @@ stop_ibuf_merges: ...@@ -2265,9 +2286,10 @@ stop_ibuf_merges:
ut_print_filename(stderr, space->name); ut_print_filename(stderr, space->name);
fprintf(stderr, ",\n" fprintf(stderr, ",\n"
"InnoDB: but there are %lu pending" "InnoDB: but there are %lu pending"
" ibuf merges on it.\n" " operations (most likely ibuf merges)"
" on it.\n"
"InnoDB: Loop %lu.\n", "InnoDB: Loop %lu.\n",
(ulong) space->n_pending_ibuf_merges, (ulong) space->n_pending_ops,
(ulong) count); (ulong) count);
} }
...@@ -2276,7 +2298,7 @@ stop_ibuf_merges: ...@@ -2276,7 +2298,7 @@ stop_ibuf_merges:
os_thread_sleep(20000); os_thread_sleep(20000);
count++; count++;
goto stop_ibuf_merges; goto stop_new_ops;
} }
} }
...@@ -2302,7 +2324,7 @@ try_again: ...@@ -2302,7 +2324,7 @@ try_again:
} }
ut_a(space); ut_a(space);
ut_a(space->n_pending_ibuf_merges == 0); ut_a(space->n_pending_ops == 0);
space->is_being_deleted = TRUE; space->is_being_deleted = TRUE;
...@@ -2358,7 +2380,11 @@ try_again: ...@@ -2358,7 +2380,11 @@ try_again:
if (srv_lazy_drop_table) { if (srv_lazy_drop_table) {
buf_LRU_mark_space_was_deleted(id); buf_LRU_mark_space_was_deleted(id);
} else { } 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 #endif
/* printf("Deleting tablespace %s id %lu\n", space->name, id); */ /* printf("Deleting tablespace %s id %lu\n", space->name, id); */
...@@ -2447,7 +2473,7 @@ fil_discard_tablespace( ...@@ -2447,7 +2473,7 @@ fil_discard_tablespace(
{ {
ibool success; ibool success;
success = fil_delete_tablespace(id); success = fil_delete_tablespace(id, TRUE);
if (!success) { if (!success) {
fprintf(stderr, fprintf(stderr,
...@@ -2579,7 +2605,7 @@ fil_rename_tablespace( ...@@ -2579,7 +2605,7 @@ fil_rename_tablespace(
retry: retry:
count++; count++;
if (count > 1000) { if (!(count % 1000)) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fputs(" InnoDB: Warning: problems renaming ", stderr); fputs(" InnoDB: Warning: problems renaming ", stderr);
ut_print_filename(stderr, old_name); ut_print_filename(stderr, old_name);
...@@ -3905,7 +3931,7 @@ convert_err_exit: ...@@ -3905,7 +3931,7 @@ convert_err_exit:
level = btr_page_get_level(page, &mtr); 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 = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block); new_page_zip = buf_block_get_page_zip(new_block);
btr_page_create(new_block, new_page_zip, index, level, &mtr); btr_page_create(new_block, new_page_zip, index, level, &mtr);
...@@ -3953,7 +3979,7 @@ convert_err_exit: ...@@ -3953,7 +3979,7 @@ convert_err_exit:
split_rec = page_get_middle_rec(page); split_rec = page_get_middle_rec(page);
new_block = btr_page_alloc(index, page_no + 1, FSP_UP, 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 = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block); new_page_zip = buf_block_get_page_zip(new_block);
btr_page_create(new_block, new_page_zip, index, 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 ...@@ -79,13 +79,14 @@ class ha_innobase: public handler
INNOBASE_SHARE* share; /*!< information for MySQL INNOBASE_SHARE* share; /*!< information for MySQL
table locking */ table locking */
uchar* upd_buff; /*!< buffer used in updates */ uchar* upd_buf; /*!< buffer used in updates */
uchar* key_val_buff; /*!< buffer used in converting 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 search key values from MySQL format
to Innodb format */ to InnoDB format. "+ 2" for the two
ulong upd_and_key_val_buff_len; bytes where the length is stored */
/* the length of each of the previous
two buffers */
Table_flags int_table_flags; Table_flags int_table_flags;
uint primary_key; uint primary_key;
ulong start_of_scan; /*!< this is set to 1 when we are 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 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 ...@@ -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
*****************************************************************************/ *****************************************************************************/
...@@ -877,6 +877,8 @@ ha_innobase::add_index( ...@@ -877,6 +877,8 @@ ha_innobase::add_index(
prebuilt->table, indexed_table, prebuilt->table, indexed_table,
index, num_of_idx, table); index, num_of_idx, table);
DBUG_EXECUTE_IF("crash_innodb_add_index_after", DBUG_SUICIDE(););
error_handling: error_handling:
/* After an error, remove all those index definitions from the /* After an error, remove all those index definitions from the
dictionary which were defined. */ dictionary which were defined. */
...@@ -1019,7 +1021,12 @@ ha_innobase::final_add_index( ...@@ -1019,7 +1021,12 @@ ha_innobase::final_add_index(
row_prebuilt_free(prebuilt, TRUE); row_prebuilt_free(prebuilt, TRUE);
error = row_merge_drop_table(trx, old_table); error = row_merge_drop_table(trx, old_table);
add->indexed_table->n_mysql_handles_opened++; 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( err = convert_error_code_to_mysql(
...@@ -1153,7 +1160,9 @@ ha_innobase::prepare_drop_index( ...@@ -1153,7 +1160,9 @@ ha_innobase::prepare_drop_index(
goto func_exit; goto func_exit;
} }
rw_lock_x_lock(dict_index_get_lock(index));
index->to_be_dropped = TRUE; 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 /* If FOREIGN_KEY_CHECKS = 1 you may not drop an index defined
...@@ -1272,7 +1281,9 @@ func_exit: ...@@ -1272,7 +1281,9 @@ func_exit:
= dict_table_get_first_index(prebuilt->table); = dict_table_get_first_index(prebuilt->table);
do { do {
rw_lock_x_lock(dict_index_get_lock(index));
index->to_be_dropped = FALSE; index->to_be_dropped = FALSE;
rw_lock_x_unlock(dict_index_get_lock(index));
index = dict_table_get_next_index(index); index = dict_table_get_next_index(index);
} while (index); } while (index);
} }
...@@ -1338,7 +1349,9 @@ ha_innobase::final_drop_index( ...@@ -1338,7 +1349,9 @@ ha_innobase::final_drop_index(
for (index = dict_table_get_first_index(prebuilt->table); for (index = dict_table_get_first_index(prebuilt->table);
index; index = dict_table_get_next_index(index)) { index; index = dict_table_get_next_index(index)) {
rw_lock_x_lock(dict_index_get_lock(index));
index->to_be_dropped = FALSE; index->to_be_dropped = FALSE;
rw_lock_x_unlock(dict_index_get_lock(index));
} }
goto func_exit; 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 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 ...@@ -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
*****************************************************************************/ *****************************************************************************/
...@@ -1523,7 +1523,7 @@ ibuf_add_ops( ...@@ -1523,7 +1523,7 @@ ibuf_add_ops(
for (i = 0; i < IBUF_OP_COUNT; i++) { for (i = 0; i < IBUF_OP_COUNT; i++) {
#ifdef HAVE_ATOMIC_BUILTINS #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 */ #else /* HAVE_ATOMIC_BUILTINS */
arr[i] += ops[i]; arr[i] += ops[i];
#endif /* HAVE_ATOMIC_BUILTINS */ #endif /* HAVE_ATOMIC_BUILTINS */
...@@ -2222,14 +2222,14 @@ ibool ...@@ -2222,14 +2222,14 @@ ibool
ibuf_add_free_page(void) ibuf_add_free_page(void)
/*====================*/ /*====================*/
{ {
mtr_t mtr; mtr_t mtr;
page_t* header_page; page_t* header_page;
ulint flags; ulint flags;
ulint zip_size; ulint zip_size;
ulint page_no; buf_block_t* block;
page_t* page; page_t* page;
page_t* root; page_t* root;
page_t* bitmap_page; page_t* bitmap_page;
mtr_start(&mtr); mtr_start(&mtr);
...@@ -2250,28 +2250,23 @@ ibuf_add_free_page(void) ...@@ -2250,28 +2250,23 @@ ibuf_add_free_page(void)
of a deadlock. This is the reason why we created a special ibuf of a deadlock. This is the reason why we created a special ibuf
header page apart from the ibuf tree. */ 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, header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 0, FSP_UP,
&mtr); &mtr);
if (UNIV_UNLIKELY(page_no == FIL_NULL)) { if (block == NULL) {
mtr_commit(&mtr); mtr_commit(&mtr);
return(FALSE); 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 */ /* Add the page to the free list and update the ibuf size data */
...@@ -2288,12 +2283,13 @@ ibuf_add_free_page(void) ...@@ -2288,12 +2283,13 @@ ibuf_add_free_page(void)
(level 2 page) */ (level 2 page) */
bitmap_page = ibuf_bitmap_get_map_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); mutex_exit(&ibuf_mutex);
ibuf_bitmap_page_set_bits( 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); ibuf_mtr_commit(&mtr);
...@@ -2588,7 +2584,15 @@ ibuf_get_merge_page_nos_func( ...@@ -2588,7 +2584,15 @@ ibuf_get_merge_page_nos_func(
} else { } else {
rec_page_no = ibuf_rec_get_page_no(mtr, rec); rec_page_no = ibuf_rec_get_page_no(mtr, rec);
rec_space_id = ibuf_rec_get_space(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 #ifdef UNIV_IBUF_DEBUG
...@@ -3920,6 +3924,7 @@ ibuf_insert_to_index_page_low( ...@@ -3920,6 +3924,7 @@ ibuf_insert_to_index_page_low(
fputs("InnoDB: Submit a detailed bug report" fputs("InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n", stderr); " to http://bugs.mysql.com\n", stderr);
ut_ad(0);
} }
/************************************************************************ /************************************************************************
...@@ -3970,9 +3975,10 @@ ibuf_insert_to_index_page( ...@@ -3970,9 +3975,10 @@ ibuf_insert_to_index_page(
"InnoDB: but the number of fields does not match!\n", "InnoDB: but the number of fields does not match!\n",
stderr); stderr);
dump: dump:
buf_page_print(page, 0); buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH);
dtuple_print(stderr, entry); dtuple_print(stderr, entry);
ut_ad(0);
fputs("InnoDB: The table where where" fputs("InnoDB: The table where where"
" this index record belongs\n" " this index record belongs\n"
...@@ -4113,6 +4119,11 @@ ibuf_set_del_mark( ...@@ -4113,6 +4119,11 @@ ibuf_set_del_mark(
TRUE, mtr); TRUE, mtr);
} }
} else { } 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); ut_print_timestamp(stderr);
fputs(" InnoDB: unable to find a record to delete-mark\n", fputs(" InnoDB: unable to find a record to delete-mark\n",
stderr); stderr);
...@@ -4121,10 +4132,14 @@ ibuf_set_del_mark( ...@@ -4121,10 +4132,14 @@ ibuf_set_del_mark(
fputs("\n" fputs("\n"
"InnoDB: record ", stderr); "InnoDB: record ", stderr);
rec_print(stderr, page_cur_get_rec(&page_cur), index); rec_print(stderr, page_cur_get_rec(&page_cur), index);
putc('\n', stderr); fprintf(stderr, "\nspace %u offset %u"
fputs("\n" " (%u records, index id %llu)\n"
"InnoDB: Submit a detailed bug report" "InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n", stderr); " 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); ut_ad(0);
} }
} }
...@@ -4168,12 +4183,31 @@ ibuf_delete( ...@@ -4168,12 +4183,31 @@ ibuf_delete(
offsets = rec_get_offsets( offsets = rec_get_offsets(
rec, index, offsets, ULINT_UNDEFINED, &heap); rec, index, offsets, ULINT_UNDEFINED, &heap);
/* Refuse to delete the last record. */ if (page_get_n_recs(page) <= 1
ut_a(page_get_n_recs(page) > 1); || !(REC_INFO_DELETED_FLAG
& rec_get_info_bits(rec, page_is_comp(page)))) {
/* The record should have been marked for deletion. */ /* Refuse to purge the last record or a
ut_ad(REC_INFO_DELETED_FLAG record that has not been marked for deletion. */
& rec_get_info_bits(rec, page_is_comp(page))); 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); lock_update_delete(block, rec);
...@@ -4259,6 +4293,7 @@ ibuf_restore_pos( ...@@ -4259,6 +4293,7 @@ ibuf_restore_pos(
fprintf(stderr, "InnoDB: ibuf tree ok\n"); fprintf(stderr, "InnoDB: ibuf tree ok\n");
fflush(stderr); fflush(stderr);
ut_ad(0);
} }
return(FALSE); return(FALSE);
...@@ -4441,7 +4476,7 @@ ibuf_merge_or_delete_for_page( ...@@ -4441,7 +4476,7 @@ ibuf_merge_or_delete_for_page(
function. When the counter is > 0, that prevents tablespace function. When the counter is > 0, that prevents tablespace
from being dropped. */ 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)) { if (UNIV_UNLIKELY(tablespace_being_deleted)) {
/* Do not try to read the bitmap page from space; /* Do not try to read the bitmap page from space;
...@@ -4467,7 +4502,7 @@ ibuf_merge_or_delete_for_page( ...@@ -4467,7 +4502,7 @@ ibuf_merge_or_delete_for_page(
/* No inserts buffered for this page */ /* No inserts buffered for this page */
if (!tablespace_being_deleted) { if (!tablespace_being_deleted) {
fil_decr_pending_ibuf_merges(space); fil_decr_pending_ops(space);
} }
return; return;
...@@ -4516,12 +4551,14 @@ ibuf_merge_or_delete_for_page( ...@@ -4516,12 +4551,14 @@ ibuf_merge_or_delete_for_page(
bitmap_page = ibuf_bitmap_get_map_page(space, page_no, bitmap_page = ibuf_bitmap_get_map_page(space, page_no,
zip_size, &mtr); zip_size, &mtr);
buf_page_print(bitmap_page, 0); buf_page_print(bitmap_page, 0,
BUF_PAGE_PRINT_NO_CRASH);
ibuf_mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
fputs("\nInnoDB: Dump of the page:\n", stderr); 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, fprintf(stderr,
"InnoDB: Error: corruption in the tablespace." "InnoDB: Error: corruption in the tablespace."
...@@ -4541,6 +4578,7 @@ ibuf_merge_or_delete_for_page( ...@@ -4541,6 +4578,7 @@ ibuf_merge_or_delete_for_page(
(ulong) page_no, (ulong) page_no,
(ulong) (ulong)
fil_page_get_type(block->frame)); fil_page_get_type(block->frame));
ut_ad(0);
} }
} }
...@@ -4747,7 +4785,7 @@ reset_bit: ...@@ -4747,7 +4785,7 @@ reset_bit:
mem_heap_free(heap); mem_heap_free(heap);
#ifdef HAVE_ATOMIC_BUILTINS #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_merged_ops, mops);
ibuf_add_ops(ibuf->n_discarded_ops, dops); ibuf_add_ops(ibuf->n_discarded_ops, dops);
#else /* HAVE_ATOMIC_BUILTINS */ #else /* HAVE_ATOMIC_BUILTINS */
...@@ -4763,7 +4801,7 @@ reset_bit: ...@@ -4763,7 +4801,7 @@ reset_bit:
if (update_ibuf_bitmap && !tablespace_being_deleted) { if (update_ibuf_bitmap && !tablespace_being_deleted) {
fil_decr_pending_ibuf_merges(space); fil_decr_pending_ops(space);
} }
#ifdef UNIV_IBUF_COUNT_DEBUG #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 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 ...@@ -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
*****************************************************************************/ *****************************************************************************/
...@@ -92,6 +92,26 @@ insert/delete buffer when the record is not in the buffer pool. */ ...@@ -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. */ buffer when the record is not in the buffer pool. */
#define BTR_DELETE 8192 #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 #ifdef UNIV_BLOB_DEBUG
# include "ut0rbt.h" # include "ut0rbt.h"
/** An index->blobs entry for keeping track of off-page column references */ /** An index->blobs entry for keeping track of off-page column references */
...@@ -569,11 +589,14 @@ UNIV_INTERN ...@@ -569,11 +589,14 @@ UNIV_INTERN
ibool ibool
btr_compress( btr_compress(
/*=========*/ /*=========*/
btr_cur_t* cursor, /*!< in: cursor on the page to merge or lift; btr_cur_t* cursor, /*!< in/out: cursor on the page to merge
the page must not be empty: in record delete or lift; the page must not be empty:
use btr_discard_page if the page would become when deleting records, use btr_discard_page()
empty */ if the page would become empty */
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));
/*************************************************************//** /*************************************************************//**
Discards a page from a B-tree. This is used to remove the last record from 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 a B-tree page: the whole page must be removed at the same time. This cannot
...@@ -614,17 +637,23 @@ btr_parse_page_reorganize( ...@@ -614,17 +637,23 @@ btr_parse_page_reorganize(
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
/**************************************************************//** /**************************************************************//**
Gets the number of pages in a B-tree. 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 UNIV_INTERN
ulint ulint
btr_get_size( btr_get_size(
/*=========*/ /*=========*/
dict_index_t* index, /*!< in: index */ 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 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! 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 UNIV_INTERN
buf_block_t* buf_block_t*
btr_page_alloc( btr_page_alloc(
...@@ -635,7 +664,12 @@ btr_page_alloc( ...@@ -635,7 +664,12 @@ btr_page_alloc(
page split is made */ page split is made */
ulint level, /*!< in: level where the page is placed ulint level, /*!< in: level where the page is placed
in the tree */ 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 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. */ storage pages because the page must contain info on its level. */
......
...@@ -279,7 +279,7 @@ btr_node_ptr_get_child_page_no( ...@@ -279,7 +279,7 @@ btr_node_ptr_get_child_page_no(
"InnoDB: a nonsensical page number 0" "InnoDB: a nonsensical page number 0"
" in a node ptr record at offset %lu\n", " in a node ptr record at offset %lu\n",
(ulong) page_offset(rec)); (ulong) page_offset(rec));
buf_page_print(page_align(rec), 0); buf_page_print(page_align(rec), 0, 0);
} }
return(page_no); 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 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 ...@@ -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
*****************************************************************************/ *****************************************************************************/
...@@ -36,6 +36,9 @@ Created 10/16/1994 Heikki Tuuri ...@@ -36,6 +36,9 @@ Created 10/16/1994 Heikki Tuuri
#define BTR_NO_LOCKING_FLAG 2 /* do no record lock checking */ #define BTR_NO_LOCKING_FLAG 2 /* do no record lock checking */
#define BTR_KEEP_SYS_FLAG 4 /* sys fields will be found from the #define BTR_KEEP_SYS_FLAG 4 /* sys fields will be found from the
update vector or inserted entry */ 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 #ifndef UNIV_HOTBACKUP
#include "que0types.h" #include "que0types.h"
...@@ -310,7 +313,9 @@ btr_cur_pessimistic_update( ...@@ -310,7 +313,9 @@ btr_cur_pessimistic_update(
/*=======================*/ /*=======================*/
ulint flags, /*!< in: undo logging, locking, and rollback ulint flags, /*!< in: undo logging, locking, and rollback
flags */ 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 */ 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 big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
be stored externally by the caller, or NULL */ be stored externally by the caller, or NULL */
...@@ -364,10 +369,13 @@ UNIV_INTERN ...@@ -364,10 +369,13 @@ UNIV_INTERN
ibool ibool
btr_cur_compress_if_useful( 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 cursor does not stay valid if compression
occurs */ 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 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, that the mtr has an x-latch on the page where the cursor is positioned,
...@@ -492,6 +500,27 @@ btr_cur_disown_inherited_fields( ...@@ -492,6 +500,27 @@ btr_cur_disown_inherited_fields(
const upd_t* update, /*!< in: update vector */ const upd_t* update, /*!< in: update vector */
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in/out: mini-transaction */
__attribute__((nonnull(2,3,4,5,6))); __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 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. 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 ...@@ -499,52 +528,23 @@ The fields are stored on pages allocated from leaf node
file segment of the index tree. file segment of the index tree.
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN UNIV_INTERN
ulint enum db_err
btr_store_big_rec_extern_fields_func( btr_store_big_rec_extern_fields(
/*=================================*/ /*============================*/
dict_index_t* index, /*!< in: index of rec; the index tree dict_index_t* index, /*!< in: index of rec; the index tree
MUST be X-latched */ MUST be X-latched */
buf_block_t* rec_block, /*!< in/out: block containing rec */ 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); const ulint* offsets, /*!< in: rec_get_offsets(rec, index);
the "external storage" flags in offsets the "external storage" flags in offsets
will not correspond to rec when will not correspond to rec when
this function returns */ this function returns */
#ifdef UNIV_DEBUG const big_rec_t*big_rec_vec, /*!< in: vector containing fields
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
to be stored externally */ to be stored externally */
__attribute__((nonnull)); mtr_t* btr_mtr, /*!< in: mtr containing the
latches to the clustered index */
/** Stores the fields in big_rec_vec to the tablespace and puts pointers to enum blob_op op) /*! in: operation code */
them in rec. The extern flags in rec will have to be set beforehand. __attribute__((nonnull, warn_unused_result));
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
/*******************************************************************//** /*******************************************************************//**
Frees the space in an externally stored field to the file space Frees the space in an externally stored field to the file space
......
This diff is collapsed.
...@@ -53,6 +53,16 @@ UNIV_INTERN ...@@ -53,6 +53,16 @@ UNIV_INTERN
btr_pcur_t* btr_pcur_t*
btr_pcur_create_for_mysql(void); 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. */ Frees the memory for a persistent cursor object. */
UNIV_INTERN UNIV_INTERN
......
This diff is collapsed.
This diff is collapsed.
...@@ -64,15 +64,14 @@ These are low-level functions ...@@ -64,15 +64,14 @@ These are low-level functions
#define BUF_LRU_FREE_SEARCH_LEN(b) (5 + 2 * BUF_READ_AHEAD_AREA(b)) #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 Removes all pages belonging to a given tablespace. */
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? */
UNIV_INTERN UNIV_INTERN
void 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( ...@@ -208,10 +208,6 @@ mem_heap_alloc(
caller */ caller */
buf = (byte*)buf + MEM_FIELD_HEADER_SIZE; buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
#endif
#ifdef UNIV_SET_MEM_TO_ZERO
UNIV_MEM_ALLOC(buf, n);
memset(buf, '\0', n);
#endif #endif
UNIV_MEM_ALLOC(buf, n); UNIV_MEM_ALLOC(buf, n);
return(buf); 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