summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorunknown <knielsen@knielsen-hq.org>2012-02-15 15:37:38 +0100
committerunknown <knielsen@knielsen-hq.org>2012-02-15 15:37:38 +0100
commit4917073305801822e1a6afbebcf6fc177a6a3d63 (patch)
tree266a7623c3a80abbcefa7d944a71419889578ab1 /storage
parent47a54a2e087a7c1fc861bcbc114c14987f492cfe (diff)
parent452a59e09c9ae415d46b5900efd567a9fcb61267 (diff)
downloadmariadb-git-4917073305801822e1a6afbebcf6fc177a6a3d63.tar.gz
Merge XtraDB from Percona-Server-5.5.20-24.1 into MariaDB 5.5.
Diffstat (limited to 'storage')
-rw-r--r--storage/xtradb/btr/btr0btr.c16
-rw-r--r--storage/xtradb/btr/btr0cur.c31
-rw-r--r--storage/xtradb/btr/btr0pcur.c2
-rw-r--r--storage/xtradb/btr/btr0sea.c304
-rw-r--r--storage/xtradb/buf/buf0buf.c208
-rw-r--r--storage/xtradb/buf/buf0flu.c66
-rw-r--r--storage/xtradb/buf/buf0lru.c186
-rw-r--r--storage/xtradb/dict/dict0dict.c5
-rw-r--r--storage/xtradb/dict/dict0load.c4
-rw-r--r--storage/xtradb/fil/fil0fil.c49
-rw-r--r--storage/xtradb/fsp/fsp0fsp.c67
-rw-r--r--storage/xtradb/ha/ha0ha.c70
-rw-r--r--storage/xtradb/handler/ha_innodb.cc95
-rw-r--r--storage/xtradb/handler/i_s.cc2
-rw-r--r--storage/xtradb/ibuf/ibuf0ibuf.c317
-rw-r--r--storage/xtradb/include/btr0cur.h18
-rw-r--r--storage/xtradb/include/btr0pcur.h8
-rw-r--r--storage/xtradb/include/btr0pcur.ic32
-rw-r--r--storage/xtradb/include/btr0sea.h42
-rw-r--r--storage/xtradb/include/btr0types.h29
-rw-r--r--storage/xtradb/include/buf0buf.h68
-rw-r--r--storage/xtradb/include/buf0buf.ic44
-rw-r--r--storage/xtradb/include/buf0types.h5
-rw-r--r--storage/xtradb/include/fil0fil.h23
-rw-r--r--storage/xtradb/include/fsp0fsp.h102
-rw-r--r--storage/xtradb/include/fsp0fsp.ic34
-rw-r--r--storage/xtradb/include/ha0ha.h23
-rw-r--r--storage/xtradb/include/ha0ha.ic54
-rw-r--r--storage/xtradb/include/page0page.h4
-rw-r--r--storage/xtradb/include/row0upd.ic1
-rw-r--r--storage/xtradb/include/srv0srv.h3
-rw-r--r--storage/xtradb/include/sync0rw.h5
-rw-r--r--storage/xtradb/include/sync0rw.ic1
-rw-r--r--storage/xtradb/include/sync0sync.h1
-rw-r--r--storage/xtradb/include/trx0trx.h1
-rw-r--r--storage/xtradb/include/univ.i2
-rw-r--r--storage/xtradb/log/log0log.c45
-rw-r--r--storage/xtradb/page/page0page.c16
-rw-r--r--storage/xtradb/page/page0zip.c2
-rw-r--r--storage/xtradb/row/row0ins.c23
-rw-r--r--storage/xtradb/row/row0mysql.c13
-rw-r--r--storage/xtradb/srv/srv0srv.c29
-rw-r--r--storage/xtradb/srv/srv0start.c28
-rw-r--r--storage/xtradb/sync/sync0rw.c9
-rw-r--r--storage/xtradb/sync/sync0sync.c1
45 files changed, 1100 insertions, 988 deletions
diff --git a/storage/xtradb/btr/btr0btr.c b/storage/xtradb/btr/btr0btr.c
index ca98afc04ad..433b062bcec 100644
--- a/storage/xtradb/btr/btr0btr.c
+++ b/storage/xtradb/btr/btr0btr.c
@@ -1523,7 +1523,7 @@ btr_free_root(
}
ut_a(block);
- btr_search_drop_page_hash_index(block, NULL);
+ btr_search_drop_page_hash_index(block);
header = buf_block_get_frame(block) + PAGE_HEADER + PAGE_BTR_SEG_TOP;
#ifdef UNIV_BTR_DEBUG
@@ -1592,7 +1592,7 @@ btr_page_reorganize_low(
#ifndef UNIV_HOTBACKUP
if (UNIV_LIKELY(!recovery)) {
- btr_search_drop_page_hash_index(block, index);
+ btr_search_drop_page_hash_index(block);
}
block->check_index_page_at_flush = TRUE;
@@ -1760,7 +1760,7 @@ btr_page_empty(
ut_a(!page_zip || page_zip_validate(page_zip, page));
#endif /* UNIV_ZIP_DEBUG */
- btr_search_drop_page_hash_index(block, index);
+ btr_search_drop_page_hash_index(block);
btr_blob_dbg_remove(page, index, "btr_page_empty");
/* Recreate the page: note that global data on page (possible
@@ -3093,7 +3093,7 @@ btr_lift_page_up(
mem_heap_free(heap);
}
- btr_search_drop_page_hash_index(block, index);
+ btr_search_drop_page_hash_index(block);
/* Make the father empty */
btr_page_empty(father_block, father_page_zip, index, page_level, mtr);
@@ -3317,7 +3317,7 @@ err_exit:
goto err_exit;
}
- btr_search_drop_page_hash_index(block, index);
+ btr_search_drop_page_hash_index(block);
/* Remove the page from the level list */
btr_level_list_remove(space, zip_size, page, index, mtr);
@@ -3358,7 +3358,7 @@ err_exit:
goto err_exit;
}
- btr_search_drop_page_hash_index(block, index);
+ btr_search_drop_page_hash_index(block);
#ifdef UNIV_BTR_DEBUG
if (UNIV_LIKELY_NULL(merge_page_zip)) {
@@ -3473,7 +3473,7 @@ btr_discard_only_page_on_level(
ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
- btr_search_drop_page_hash_index(block, index);
+ btr_search_drop_page_hash_index(block);
btr_page_get_father(index, block, mtr, &cursor);
father = btr_cur_get_block(&cursor);
@@ -3578,7 +3578,7 @@ btr_discard_page(
page = buf_block_get_frame(block);
ut_a(page_is_comp(merge_page) == page_is_comp(page));
- btr_search_drop_page_hash_index(block, index);
+ btr_search_drop_page_hash_index(block);
if (left_page_no == FIL_NULL && !page_is_leaf(page)) {
diff --git a/storage/xtradb/btr/btr0cur.c b/storage/xtradb/btr/btr0cur.c
index 717663a123a..43313474071 100644
--- a/storage/xtradb/btr/btr0cur.c
+++ b/storage/xtradb/btr/btr0cur.c
@@ -488,8 +488,6 @@ btr_cur_search_to_nth_level(
cursor->flag = BTR_CUR_BINARY;
cursor->index = index;
- cursor->ibuf_cnt = ULINT_UNDEFINED;
-
#ifndef BTR_CUR_ADAPT
guess = NULL;
#else
@@ -800,21 +798,8 @@ retry_page_get:
/* We're doing a search on an ibuf tree and we're one
level above the leaf page. */
- ulint is_min_rec;
-
ut_ad(level == 0);
- is_min_rec = rec_get_info_bits(node_ptr, 0)
- & REC_INFO_MIN_REC_FLAG;
-
- if (!is_min_rec) {
- cursor->ibuf_cnt
- = ibuf_rec_get_counter(node_ptr);
-
- ut_a(cursor->ibuf_cnt <= 0xFFFF
- || cursor->ibuf_cnt == ULINT_UNDEFINED);
- }
-
buf_mode = BUF_GET;
rw_latch = RW_NO_LATCH;
goto retry_page_get;
@@ -2007,7 +1992,7 @@ btr_cur_update_in_place(
was_delete_marked = rec_get_deleted_flag(
rec, page_is_comp(buf_block_get_frame(block)));
- is_hashed = block->is_hashed;
+ is_hashed = (block->index != NULL);
if (is_hashed) {
/* TO DO: Can we skip this if none of the fields
@@ -3683,16 +3668,11 @@ btr_record_not_null_field_in_rec(
}
for (i = 0; i < n_unique; i++) {
- ulint rec_len;
-
- rec_get_nth_field_offs(offsets, i, &rec_len);
-
- if (rec_len != UNIV_SQL_NULL) {
- n_not_null[i]++;
- } else {
- /* Break if we hit the first NULL value */
+ if (rec_offs_nth_sql_null(offsets, i)) {
break;
}
+
+ n_not_null[i]++;
}
}
@@ -3840,8 +3820,7 @@ btr_estimate_number_of_different_key_vals(
if (n_not_null) {
btr_record_not_null_field_in_rec(
- n_cols, offsets_next_rec,
- n_not_null);
+ n_cols, offsets_next_rec, n_not_null);
}
total_external_size
diff --git a/storage/xtradb/btr/btr0pcur.c b/storage/xtradb/btr/btr0pcur.c
index 081ef9c9457..e6a9ddcf43e 100644
--- a/storage/xtradb/btr/btr0pcur.c
+++ b/storage/xtradb/btr/btr0pcur.c
@@ -253,6 +253,8 @@ btr_pcur_restore_position_func(
cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
index, latch_mode, btr_pcur_get_btr_cur(cursor), mtr);
+ cursor->latch_mode = latch_mode;
+ cursor->pos_state = BTR_PCUR_IS_POSITIONED;
cursor->block_when_stored = btr_pcur_get_block(cursor);
return(FALSE);
diff --git a/storage/xtradb/btr/btr0sea.c b/storage/xtradb/btr/btr0sea.c
index f27afe216ec..bddbcc79dd6 100644
--- a/storage/xtradb/btr/btr0sea.c
+++ b/storage/xtradb/btr/btr0sea.c
@@ -44,15 +44,11 @@ Created 2/17/1996 Heikki Tuuri
#include "ha0ha.h"
#include "srv0srv.h"
/** Flag: has the search system been enabled?
-Protected by btr_search_latch and btr_search_enabled_mutex. */
+Protected by btr_search_latch. */
UNIV_INTERN char btr_search_enabled = TRUE;
-UNIV_INTERN ibool btr_search_fully_disabled = FALSE;
UNIV_INTERN ulint btr_search_index_num = 1;
-/** Mutex protecting btr_search_enabled */
-static mutex_t btr_search_enabled_mutex;
-
#ifdef UNIV_PFS_MUTEX
/* Key to register btr_search_enabled_mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t btr_search_enabled_mutex_key;
@@ -186,8 +182,6 @@ btr_search_sys_create(
//rw_lock_create(btr_search_latch_key, &btr_search_latch,
// SYNC_SEARCH_SYS);
- mutex_create(btr_search_enabled_mutex_key,
- &btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF);
btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
@@ -238,27 +232,40 @@ void
btr_search_disable(void)
/*====================*/
{
- mutex_enter(&btr_search_enabled_mutex);
+ dict_table_t* table;
+ ulint i;
+
+ mutex_enter(&dict_sys->mutex);
btr_search_x_lock_all();
- /* Disable access to hash index, also tell ha_insert_for_fold()
- stop adding new nodes to hash index, but still allow updating
- existing nodes */
btr_search_enabled = FALSE;
- /* Clear all block->is_hashed flags and remove all entries
- from btr_search_sys->hash_index. */
- buf_pool_drop_hash_index();
+ /* Clear the index->search_info->ref_count of every index in
+ the data dictionary cache. */
+ for (table = UT_LIST_GET_FIRST(dict_sys->table_LRU); table;
+ table = UT_LIST_GET_NEXT(table_LRU, table)) {
+
+ dict_index_t* index;
+
+ for (index = dict_table_get_first_index(table); index;
+ index = dict_table_get_next_index(index)) {
- /* hash index has been cleaned up, disallow any operation to
- the hash index */
- btr_search_fully_disabled = TRUE;
+ index->search_info->ref_count = 0;
+ }
+ }
+
+ mutex_exit(&dict_sys->mutex);
- /* btr_search_enabled_mutex should guarantee this. */
- ut_ad(!btr_search_enabled);
+ /* Set all block->index = NULL. */
+ buf_pool_clear_hash_index();
+
+ /* Clear the adaptive hash index. */
+ for (i = 0; i < btr_search_index_num; i++) {
+ hash_table_clear(btr_search_sys->hash_index[i]);
+ mem_heap_empty(btr_search_sys->hash_index[i]->heap);
+ }
btr_search_x_unlock_all();
- mutex_exit(&btr_search_enabled_mutex);
}
/********************************************************************//**
@@ -268,14 +275,11 @@ void
btr_search_enable(void)
/*====================*/
{
- mutex_enter(&btr_search_enabled_mutex);
btr_search_x_lock_all();
btr_search_enabled = TRUE;
- btr_search_fully_disabled = FALSE;
btr_search_x_unlock_all();
- mutex_exit(&btr_search_enabled_mutex);
}
/*****************************************************************//**
@@ -499,7 +503,7 @@ btr_search_update_block_hash_info(
&& (block->n_bytes == info->n_bytes)
&& (block->left_side == info->left_side)) {
- if ((block->is_hashed)
+ if ((block->index)
&& (block->curr_n_fields == info->n_fields)
&& (block->curr_n_bytes == info->n_bytes)
&& (block->curr_left_side == info->left_side)) {
@@ -528,7 +532,7 @@ btr_search_update_block_hash_info(
/ BTR_SEARCH_PAGE_BUILD_LIMIT)
&& (info->n_hash_potential >= BTR_SEARCH_BUILD_LIMIT)) {
- if ((!block->is_hashed)
+ if ((!block->index)
|| (block->n_hash_helps
> 2 * page_get_n_recs(block->frame))
|| (block->n_fields != block->curr_n_fields)
@@ -560,9 +564,9 @@ btr_search_update_hash_ref(
buf_block_t* block, /*!< in: buffer block where cursor positioned */
btr_cur_t* cursor) /*!< in: cursor */
{
+ dict_index_t* index;
ulint fold;
- rec_t* rec;
- index_id_t index_id;
+ const rec_t* rec;
ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
#ifdef UNIV_SYNC_DEBUG
@@ -573,13 +577,15 @@ btr_search_update_hash_ref(
ut_ad(page_align(btr_cur_get_rec(cursor))
== buf_block_get_frame(block));
- if (!block->is_hashed) {
+ index = block->index;
+
+ if (!index) {
return;
}
- ut_a(block->index == cursor->index);
- ut_a(!dict_index_is_ibuf(cursor->index));
+ ut_a(index == cursor->index);
+ ut_a(!dict_index_is_ibuf(index));
if ((info->n_hash_potential > 0)
&& (block->curr_n_fields == info->n_fields)
@@ -596,12 +602,11 @@ btr_search_update_hash_ref(
return;
}
- index_id = cursor->index->id;
fold = rec_fold(rec,
- rec_get_offsets(rec, cursor->index, offsets_,
+ rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
block->curr_n_fields,
- block->curr_n_bytes, index_id);
+ block->curr_n_bytes, index->id);
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -870,7 +875,7 @@ btr_search_guess_on_hash(
{
buf_pool_t* buf_pool;
buf_block_t* block;
- rec_t* rec;
+ const rec_t* rec;
ulint fold;
index_id_t index_id;
#ifdef notdefined
@@ -956,7 +961,7 @@ btr_search_guess_on_hash(
ut_ad(page_rec_is_user_rec(rec));
- btr_cur_position(index, rec, block, cursor);
+ btr_cur_position(index, (rec_t*) rec, block, cursor);
/* Check the validity of the guess within the page */
@@ -1058,11 +1063,10 @@ UNIV_INTERN
void
btr_search_drop_page_hash_index(
/*============================*/
- buf_block_t* block, /*!< in: block containing index page,
+ buf_block_t* block) /*!< in: block containing index page,
s- or x-latched, or an index page
for which we know that
block->buf_fix_count == 0 */
- dict_index_t* index_in)
{
hash_table_t* table;
ulint n_fields;
@@ -1080,24 +1084,14 @@ btr_search_drop_page_hash_index(
const dict_index_t* index;
ulint* offsets;
-#ifdef UNIV_SYNC_DEBUG
- if (index_in) {
- ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_SHARED));
- ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_EX));
- }
-#endif /* UNIV_SYNC_DEBUG */
-
retry:
- if (index_in) {
- index = index_in;
- rw_lock_s_lock(btr_search_get_latch(index->id));
- } else if (btr_search_index_num > 1) {
+ if (btr_search_index_num > 1) {
rw_lock_t* btr_search_latch;
/* FIXME: This may be optimistic implementation still. */
btr_search_latch = (rw_lock_t*)(block->btr_search_latch);
if (UNIV_LIKELY(!btr_search_latch)) {
- if (block->is_hashed) {
+ if (block->index) {
goto retry;
}
return;
@@ -1107,7 +1101,7 @@ retry:
rw_lock_s_unlock(btr_search_latch);
goto retry;
}
- if (UNIV_LIKELY(!block->is_hashed)) {
+ if (UNIV_LIKELY(!block->index)) {
rw_lock_s_unlock(btr_search_latch);
goto retry;
}
@@ -1116,18 +1110,16 @@ retry:
} else {
/* btr_search_index_num == 1 */
/* btr_search_latch is only one and able to obtain
- before evaluating block->is_hashed. */
+ before evaluating block->index. */
rw_lock_s_lock(btr_search_latch_part[0]);
- if (UNIV_LIKELY(!block->is_hashed)) {
+ if (UNIV_LIKELY(!block->index)) {
rw_lock_s_unlock(btr_search_latch_part[0]);
return;
}
index = block->index;
}
- page = block->frame;
-
- if (UNIV_LIKELY(!block->is_hashed)) {
+ if (UNIV_LIKELY(!index)) {
rw_lock_s_unlock(btr_search_get_latch(index->id));
@@ -1155,6 +1147,7 @@ retry:
ut_a(n_fields + n_bytes > 0);
+ page = block->frame;
n_recs = page_get_n_recs(page);
/* Calculate and cache fold values into an array for fast deletion
@@ -1203,7 +1196,7 @@ next_rec:
rw_lock_x_lock(btr_search_get_latch(index->id));
- if (UNIV_UNLIKELY(!block->is_hashed)) {
+ if (UNIV_UNLIKELY(!block->index)) {
/* Someone else has meanwhile dropped the hash index */
goto cleanup;
@@ -1231,10 +1224,9 @@ next_rec:
ut_a(index->search_info->ref_count > 0);
index->search_info->ref_count--;
- block->is_hashed = FALSE;
block->index = NULL;
block->btr_search_latch = NULL;
-
+
cleanup:
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
if (UNIV_UNLIKELY(block->n_pointers)) {
@@ -1309,7 +1301,7 @@ retry:
if (buf_block_get_state(block)
!= BUF_BLOCK_FILE_PAGE
|| block->index != index
- || !block->is_hashed) {
+ || !block->index) {
continue;
}
@@ -1375,7 +1367,7 @@ next_rec:
rw_lock_x_lock(btr_search_get_latch(index->id));
- if (UNIV_UNLIKELY(!block->is_hashed)) {
+ if (UNIV_UNLIKELY(!block->index)) {
goto cleanup;
}
@@ -1400,7 +1392,6 @@ next_rec:
ut_a(index->search_info->ref_count > 0);
index->search_info->ref_count--;
- block->is_hashed = FALSE;
block->index = NULL;
block->btr_search_latch = NULL;
@@ -1434,8 +1425,8 @@ cleanup:
}
/********************************************************************//**
-Drops a page hash index when a page is freed from a fseg to the file system.
-Drops possible hash index if the page happens to be in the buffer pool. */
+Drops a possible page hash index when a page is evicted from the buffer pool
+or freed in a file segment. */
UNIV_INTERN
void
btr_search_drop_page_hash_when_freed(
@@ -1448,32 +1439,23 @@ btr_search_drop_page_hash_when_freed(
buf_block_t* block;
mtr_t mtr;
- if (!buf_page_peek_if_search_hashed(space, page_no)) {
-
- return;
- }
-
mtr_start(&mtr);
- /* We assume that if the caller has a latch on the page, then the
- caller has already dropped the hash index for the page, and we never
- get here. Therefore we can acquire the s-latch to the page without
- having to fear a deadlock. */
+ /* If the caller has a latch on the page, then the caller must
+ have a x-latch on the page and it must have already dropped
+ the hash index for the page. Because of the x-latch that we
+ are possibly holding, we cannot s-latch the page, but must
+ (recursively) x-latch it, even though we are only reading. */
- block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH, NULL,
+ block = buf_page_get_gen(space, zip_size, page_no, RW_X_LATCH, NULL,
BUF_PEEK_IF_IN_POOL, __FILE__, __LINE__,
&mtr);
- /* Because the buffer pool mutex was released by
- buf_page_peek_if_search_hashed(), it is possible that the
- block was removed from the buffer pool by another thread
- before buf_page_get_gen() got a chance to acquire the buffer
- pool mutex again. Thus, we must check for a NULL return. */
- if (UNIV_LIKELY(block != NULL)) {
+ if (block && block->index) {
buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
- btr_search_drop_page_hash_index(block, NULL);
+ btr_search_drop_page_hash_index(block);
}
mtr_commit(&mtr);
@@ -1501,7 +1483,6 @@ btr_search_build_page_hash_index(
rec_t* next_rec;
ulint fold;
ulint next_fold;
- index_id_t index_id;
ulint n_cached;
ulint n_recs;
ulint* folds;
@@ -1526,13 +1507,13 @@ btr_search_build_page_hash_index(
rw_lock_s_lock(btr_search_get_latch(index->id));
- if (block->is_hashed && ((block->curr_n_fields != n_fields)
+ if (block->index && ((block->curr_n_fields != n_fields)
|| (block->curr_n_bytes != n_bytes)
|| (block->curr_left_side != left_side))) {
rw_lock_s_unlock(btr_search_get_latch(index->id));
- btr_search_drop_page_hash_index(block, index);
+ btr_search_drop_page_hash_index(block);
} else {
rw_lock_s_unlock(btr_search_get_latch(index->id));
}
@@ -1565,7 +1546,7 @@ btr_search_build_page_hash_index(
n_cached = 0;
- index_id = btr_page_get_index_id(page);
+ ut_a(index->id == btr_page_get_index_id(page));
rec = page_rec_get_next(page_get_infimum_rec(page));
@@ -1580,7 +1561,7 @@ btr_search_build_page_hash_index(
}
}
- fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
+ fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id);
if (left_side) {
@@ -1607,7 +1588,7 @@ btr_search_build_page_hash_index(
offsets = rec_get_offsets(next_rec, index, offsets,
n_fields + (n_bytes > 0), &heap);
next_fold = rec_fold(next_rec, offsets, n_fields,
- n_bytes, index_id);
+ n_bytes, index->id);
if (fold != next_fold) {
/* Insert an entry into the hash index */
@@ -1632,13 +1613,13 @@ btr_search_build_page_hash_index(
rw_lock_x_lock(btr_search_get_latch(index->id));
- if (UNIV_UNLIKELY(btr_search_fully_disabled)) {
+ if (UNIV_UNLIKELY(!btr_search_enabled)) {
goto exit_func;
}
- if (block->is_hashed && ((block->curr_n_fields != n_fields)
- || (block->curr_n_bytes != n_bytes)
- || (block->curr_left_side != left_side))) {
+ if (block->index && ((block->curr_n_fields != n_fields)
+ || (block->curr_n_bytes != n_bytes)
+ || (block->curr_left_side != left_side))) {
goto exit_func;
}
@@ -1647,11 +1628,10 @@ btr_search_build_page_hash_index(
rebuild hash index for a page that is already hashed, we
have to take care not to increment the counter in that
case. */
- if (!block->is_hashed) {
+ if (!block->index) {
index->search_info->ref_count++;
}
- block->is_hashed = TRUE;
block->n_hash_helps = 0;
block->curr_n_fields = n_fields;
@@ -1700,23 +1680,24 @@ btr_search_move_or_delete_hash_entries(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- ut_a(!new_block->is_hashed || new_block->index == index);
- ut_a(!block->is_hashed || block->index == index);
- ut_a(!(new_block->is_hashed || block->is_hashed)
- || !dict_index_is_ibuf(index));
rw_lock_s_lock(btr_search_get_latch(index->id));
- if (new_block->is_hashed) {
+ ut_a(!new_block->index || new_block->index == index);
+ ut_a(!block->index || block->index == index);
+ ut_a(!(new_block->index || block->index)
+ || !dict_index_is_ibuf(index));
+
+ if (new_block->index) {
rw_lock_s_unlock(btr_search_get_latch(index->id));
- btr_search_drop_page_hash_index(block, index);
+ btr_search_drop_page_hash_index(block);
return;
}
- if (block->is_hashed) {
+ if (block->index) {
n_fields = block->curr_n_fields;
n_bytes = block->curr_n_bytes;
@@ -1753,42 +1734,48 @@ btr_search_update_hash_on_delete(
{
hash_table_t* table;
buf_block_t* block;
- rec_t* rec;
+ const rec_t* rec;
ulint fold;
- index_id_t index_id;
+ dict_index_t* index;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
mem_heap_t* heap = NULL;
rec_offs_init(offsets_);
- rec = btr_cur_get_rec(cursor);
-
block = btr_cur_get_block(cursor);
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- if (!block->is_hashed) {
+ index = block->index;
+
+ if (!index) {
return;
}
- ut_a(block->index == cursor->index);
+ ut_a(index == cursor->index);
ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
- ut_a(!dict_index_is_ibuf(cursor->index));
+ ut_a(!dict_index_is_ibuf(index));
table = btr_search_get_hash_index(cursor->index->id);
- index_id = cursor->index->id;
- fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_,
+ rec = btr_cur_get_rec(cursor);
+
+ fold = rec_fold(rec, rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
- block->curr_n_fields, block->curr_n_bytes, index_id);
+ block->curr_n_fields, block->curr_n_bytes, index->id);
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
+
rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
- ha_search_and_delete_if_found(table, fold, rec);
+ if (block->index) {
+ ut_a(block->index == index);
+
+ ha_search_and_delete_if_found(table, fold, rec);
+ }
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
}
@@ -1806,6 +1793,7 @@ btr_search_update_hash_node_on_insert(
{
hash_table_t* table;
buf_block_t* block;
+ dict_index_t* index;
rec_t* rec;
rec = btr_cur_get_rec(cursor);
@@ -1816,16 +1804,25 @@ btr_search_update_hash_node_on_insert(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- if (!block->is_hashed) {
+ index = block->index;
+
+ if (!index) {
return;
}
- ut_a(block->index == cursor->index);
- ut_a(!dict_index_is_ibuf(cursor->index));
+ ut_a(cursor->index == index);
+ ut_a(!dict_index_is_ibuf(index));
rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
+ if (!block->index) {
+
+ goto func_exit;
+ }
+
+ ut_a(block->index == index);
+
if ((cursor->flag == BTR_CUR_HASH)
&& (cursor->n_fields == block->curr_n_fields)
&& (cursor->n_bytes == block->curr_n_bytes)
@@ -1836,6 +1833,7 @@ btr_search_update_hash_node_on_insert(
ha_search_and_update_if_found(table, cursor->fold, rec,
block, page_rec_get_next(rec));
+func_exit:
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
} else {
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
@@ -1857,10 +1855,10 @@ btr_search_update_hash_on_insert(
{
hash_table_t* table;
buf_block_t* block;
+ dict_index_t* index;
rec_t* rec;
rec_t* ins_rec;
rec_t* next_rec;
- index_id_t index_id;
ulint fold;
ulint ins_fold;
ulint next_fold = 0; /* remove warning (??? bug ???) */
@@ -1885,15 +1883,15 @@ btr_search_update_hash_on_insert(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- if (!block->is_hashed) {
+ index = block->index;
+
+ if (!index) {
return;
}
- ut_a(block->index == cursor->index);
- ut_a(!dict_index_is_ibuf(cursor->index));
-
- index_id = cursor->index->id;
+ ut_a(index == cursor->index);
+ ut_a(!dict_index_is_ibuf(index));
n_fields = block->curr_n_fields;
n_bytes = block->curr_n_bytes;
@@ -1902,28 +1900,32 @@ btr_search_update_hash_on_insert(
ins_rec = page_rec_get_next(rec);
next_rec = page_rec_get_next(ins_rec);
- offsets = rec_get_offsets(ins_rec, cursor->index, offsets,
+ offsets = rec_get_offsets(ins_rec, index, offsets,
ULINT_UNDEFINED, &heap);
- ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index_id);
+ ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index->id);
if (!page_rec_is_supremum(next_rec)) {
- offsets = rec_get_offsets(next_rec, cursor->index, offsets,
+ offsets = rec_get_offsets(next_rec, index, offsets,
n_fields + (n_bytes > 0), &heap);
next_fold = rec_fold(next_rec, offsets, n_fields,
- n_bytes, index_id);
+ n_bytes, index->id);
}
if (!page_rec_is_infimum(rec)) {
- offsets = rec_get_offsets(rec, cursor->index, offsets,
+ offsets = rec_get_offsets(rec, index, offsets,
n_fields + (n_bytes > 0), &heap);
- fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
+ fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id);
} else {
if (left_side) {
- rw_lock_x_lock(btr_search_get_latch(index_id));
+ rw_lock_x_lock(btr_search_get_latch(index->id));
locked = TRUE;
+ if (!btr_search_enabled) {
+ goto function_exit;
+ }
+
ha_insert_for_fold(table, ins_fold, block, ins_rec);
}
@@ -1934,9 +1936,13 @@ btr_search_update_hash_on_insert(
if (!locked) {
- rw_lock_x_lock(btr_search_get_latch(index_id));
+ rw_lock_x_lock(btr_search_get_latch(index->id));
locked = TRUE;
+
+ if (!btr_search_enabled) {
+ goto function_exit;
+ }
}
if (!left_side) {
@@ -1952,9 +1958,13 @@ check_next_rec:
if (!left_side) {
if (!locked) {
- rw_lock_x_lock(btr_search_get_latch(index_id));
+ rw_lock_x_lock(btr_search_get_latch(index->id));
locked = TRUE;
+
+ if (!btr_search_enabled) {
+ goto function_exit;
+ }
}
ha_insert_for_fold(table, ins_fold, block, ins_rec);
@@ -1967,9 +1977,13 @@ check_next_rec:
if (!locked) {
- rw_lock_x_lock(btr_search_get_latch(index_id));
+ rw_lock_x_lock(btr_search_get_latch(index->id));
locked = TRUE;
+
+ if (!btr_search_enabled) {
+ goto function_exit;
+ }
}
if (!left_side) {
@@ -1977,7 +1991,7 @@ check_next_rec:
ha_insert_for_fold(table, ins_fold, block, ins_rec);
/*
fputs("Hash insert for ", stderr);
- dict_index_name_print(stderr, cursor->index);
+ dict_index_name_print(stderr, index);
fprintf(stderr, " fold %lu\n", ins_fold);
*/
} else {
@@ -1990,7 +2004,7 @@ function_exit:
mem_heap_free(heap);
}
if (locked) {
- rw_lock_x_unlock(btr_search_get_latch(index_id));
+ rw_lock_x_unlock(btr_search_get_latch(index->id));
}
}
@@ -2082,21 +2096,20 @@ btr_search_validate(void)
ut_a(!dict_index_is_ibuf(block->index));
- offsets = rec_get_offsets((const rec_t*) node->data,
+ page_index_id = btr_page_get_index_id(block->frame);
+
+ offsets = rec_get_offsets(node->data,
block->index, offsets,
block->curr_n_fields
+ (block->curr_n_bytes > 0),
&heap);
- page_index_id = btr_page_get_index_id(block->frame);
-
- if (UNIV_UNLIKELY
- (!block->is_hashed || node->fold
- != rec_fold((rec_t*)(node->data),
- offsets,
- block->curr_n_fields,
- block->curr_n_bytes,
- page_index_id))) {
+ if (!block->index || node->fold
+ != rec_fold(node->data,
+ offsets,
+ block->curr_n_fields,
+ block->curr_n_bytes,
+ page_index_id)) {
const page_t* page = block->frame;
ok = FALSE;
@@ -2112,20 +2125,19 @@ btr_search_validate(void)
node->data,
(ullint) page_index_id,
(ulong) node->fold,
- (ulong) rec_fold((rec_t*)(node->data),
+ (ulong) rec_fold(node->data,
offsets,
block->curr_n_fields,
block->curr_n_bytes,
page_index_id));
fputs("InnoDB: Record ", stderr);
- rec_print_new(stderr, (rec_t*)node->data,
- offsets);
+ rec_print_new(stderr, node->data, offsets);
fprintf(stderr, "\nInnoDB: on that page."
- " Page mem address %p, is hashed %lu,"
+ " Page mem address %p, is hashed %p,"
" n fields %lu, n bytes %lu\n"
"InnoDB: side %lu\n",
- (void*) page, (ulong) block->is_hashed,
+ (void*) page, (void*) block->index,
(ulong) block->curr_n_fields,
(ulong) block->curr_n_bytes,
(ulong) block->curr_left_side);
diff --git a/storage/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c
index 4bc2c26cde2..11b079dd0ef 100644
--- a/storage/xtradb/buf/buf0buf.c
+++ b/storage/xtradb/buf/buf0buf.c
@@ -917,6 +917,16 @@ pfs_register_buffer_block(
rwlock->pfs_psi = (PSI_server)
? PSI_server->init_rwlock(buf_block_lock_key, rwlock)
: NULL;
+
+# ifdef UNIV_SYNC_DEBUG
+ rwlock = &block->debug_latch;
+ ut_a(!rwlock->pfs_psi);
+ rwlock->pfs_psi = (PSI_server)
+ ? PSI_server->init_rwlock(buf_block_debug_latch_key,
+ rwlock)
+ : NULL;
+# endif /* UNIV_SYNC_DEBUG */
+
# endif /* UNIV_PFS_RWLOCK */
block++;
}
@@ -952,8 +962,6 @@ buf_block_init(
block->index = NULL;
block->btr_search_latch = NULL;
- block->is_hashed = FALSE;
-
#ifdef UNIV_DEBUG
block->page.in_page_hash = FALSE;
block->page.in_zip_hash = FALSE;
@@ -980,17 +988,24 @@ buf_block_init(
mutex_create(PFS_NOT_INSTRUMENTED, &block->mutex, SYNC_BUF_BLOCK);
rw_lock_create(PFS_NOT_INSTRUMENTED, &block->lock, SYNC_LEVEL_VARYING);
+
+# ifdef UNIV_SYNC_DEBUG
+ rw_lock_create(PFS_NOT_INSTRUMENTED,
+ &block->debug_latch, SYNC_NO_ORDER_CHECK);
+# endif /* UNIV_SYNC_DEBUG */
+
#else /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
mutex_create(buffer_block_mutex_key, &block->mutex, SYNC_BUF_BLOCK);
rw_lock_create(buf_block_lock_key, &block->lock, SYNC_LEVEL_VARYING);
+
+# ifdef UNIV_SYNC_DEBUG
+ rw_lock_create(buf_block_debug_latch_key,
+ &block->debug_latch, SYNC_NO_ORDER_CHECK);
+# endif /* UNIV_SYNC_DEBUG */
#endif /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
ut_ad(rw_lock_validate(&(block->lock)));
-#ifdef UNIV_SYNC_DEBUG
- rw_lock_create(buf_block_debug_latch_key,
- &block->debug_latch, SYNC_NO_ORDER_CHECK);
-#endif /* UNIV_SYNC_DEBUG */
}
/********************************************************************//**
@@ -1317,6 +1332,26 @@ buf_pool_free_instance(
{
buf_chunk_t* chunk;
buf_chunk_t* chunks;
+ buf_page_t* bpage;
+
+ bpage = UT_LIST_GET_LAST(buf_pool->LRU);
+ while (bpage != NULL) {
+ buf_page_t* prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
+ enum buf_page_state state = buf_page_get_state(bpage);
+
+ ut_ad(buf_page_in_file(bpage));
+ ut_ad(bpage->in_LRU_list);
+
+ if (state != BUF_BLOCK_FILE_PAGE) {
+ /* We must not have any dirty block except
+ when doing a fast shutdown. */
+ ut_ad(state == BUF_BLOCK_ZIP_PAGE
+ || srv_fast_shutdown == 2);
+ buf_page_free_descriptor(bpage);
+ }
+
+ bpage = prev_bpage;
+ }
chunks = buf_pool->chunks;
chunk = chunks + buf_pool->n_chunks;
@@ -1392,87 +1427,13 @@ buf_pool_free(
}
/********************************************************************//**
-Drops adaptive hash index for a buffer pool instance. */
-static
-void
-buf_pool_drop_hash_index_instance(
-/*==============================*/
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
- ibool* released_search_latch) /*!< out: flag for signalling
- whether the search latch was
- released */
-{
- buf_chunk_t* chunks = buf_pool->chunks;
- buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
-
- while (--chunk >= chunks) {
- ulint i;
- buf_block_t* block = chunk->blocks;
-
- for (i = chunk->size; i--; block++) {
- /* block->is_hashed cannot be modified
- when we have an x-latch on btr_search_latch;
- see the comment in buf0buf.h */
-
- if (!block->is_hashed) {
- continue;
- }
-
- /* To follow the latching order, we
- have to release btr_search_latch
- before acquiring block->latch. */
- btr_search_x_unlock_all();
- /* When we release the search latch,
- we must rescan all blocks, because
- some may become hashed again. */
- *released_search_latch = TRUE;
-
- rw_lock_x_lock(&block->lock);
-
- /* This should be guaranteed by the
- callers, which will be holding
- btr_search_enabled_mutex. */
- ut_ad(!btr_search_enabled);
-
- /* Because we did not buffer-fix the
- block by calling buf_block_get_gen(),
- it is possible that the block has been
- allocated for some other use after
- btr_search_latch was released above.
- We do not care which file page the
- block is mapped to. All we want to do
- is to drop any hash entries referring
- to the page. */
-
- /* It is possible that
- block->page.state != BUF_FILE_PAGE.
- Even that does not matter, because
- btr_search_drop_page_hash_index() will
- check block->is_hashed before doing
- anything. block->is_hashed can only
- be set on uncompressed file pages. */
-
- btr_search_drop_page_hash_index(block, NULL);
-
- rw_lock_x_unlock(&block->lock);
-
- btr_search_x_lock_all();
-
- ut_ad(!btr_search_enabled);
- }
- }
-}
-
-/********************************************************************//**
-Drops the adaptive hash index. To prevent a livelock, this function
-is only to be called while holding btr_search_latch and while
-btr_search_enabled == FALSE. */
+Clears the adaptive hash index on all pages in the buffer pool. */
UNIV_INTERN
void
-buf_pool_drop_hash_index(void)
-/*==========================*/
+buf_pool_clear_hash_index(void)
+/*===========================*/
{
- ibool released_search_latch;
+ ulint p;
#ifdef UNIV_SYNC_DEBUG
ulint j;
@@ -1483,21 +1444,34 @@ buf_pool_drop_hash_index(void)
#endif /* UNIV_SYNC_DEBUG */
ut_ad(!btr_search_enabled);
- do {
- ulint i;
+ for (p = 0; p < srv_buf_pool_instances; p++) {
+ buf_pool_t* buf_pool = buf_pool_from_array(p);
+ buf_chunk_t* chunks = buf_pool->chunks;
+ buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
- released_search_latch = FALSE;
+ while (--chunk >= chunks) {
+ buf_block_t* block = chunk->blocks;
+ ulint i = chunk->size;
- for (i = 0; i < srv_buf_pool_instances; i++) {
- buf_pool_t* buf_pool;
+ for (; i--; block++) {
+ dict_index_t* index = block->index;
- buf_pool = buf_pool_from_array(i);
+ /* We can set block->index = NULL
+ when we have an x-latch on btr_search_latch;
+ see the comment in buf0buf.h */
- buf_pool_drop_hash_index_instance(
- buf_pool, &released_search_latch);
- }
+ if (!index) {
+ /* Not hashed */
+ continue;
+ }
- } while (released_search_latch);
+ block->index = NULL;
+# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ block->n_pointers = 0;
+# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+ }
+ }
+ }
}
/********************************************************************//**
@@ -1638,12 +1612,12 @@ buf_pool_watch_set(
rw_lock_x_lock(&buf_pool->page_hash_latch);
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
- if (bpage) {
+
+ if (UNIV_LIKELY_NULL(bpage)) {
+
block_mutex = buf_page_get_mutex_enter(bpage);
ut_a(block_mutex);
- }
- if (UNIV_LIKELY_NULL(bpage)) {
if (!buf_pool_watch_is_sentinel(buf_pool, bpage)) {
/* The page was loaded meanwhile. */
rw_lock_x_unlock(&buf_pool->page_hash_latch);
@@ -1895,40 +1869,6 @@ buf_reset_check_index_page_at_flush(
rw_lock_s_unlock(&buf_pool->page_hash_latch);
}
-/********************************************************************//**
-Returns the current state of is_hashed of a page. FALSE if the page is
-not in the pool. NOTE that this operation does not fix the page in the
-pool if it is found there.
-@return TRUE if page hash index is built in search system */
-UNIV_INTERN
-ibool
-buf_page_peek_if_search_hashed(
-/*===========================*/
- ulint space, /*!< in: space id */
- ulint offset) /*!< in: page number */
-{
- buf_block_t* block;
- ibool is_hashed;
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
-
- //buf_pool_mutex_enter(buf_pool);
- rw_lock_s_lock(&buf_pool->page_hash_latch);
-
- block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
-
- if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
- is_hashed = FALSE;
- } else {
- ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
- is_hashed = block->is_hashed;
- }
-
- //buf_pool_mutex_exit(buf_pool);
- rw_lock_s_unlock(&buf_pool->page_hash_latch);
-
- return(is_hashed);
-}
-
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
/********************************************************************//**
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
@@ -2218,7 +2158,6 @@ buf_block_init_low(
block->btr_search_latch = NULL;
block->n_hash_helps = 0;
- block->is_hashed = FALSE;
block->n_fields = 1;
block->n_bytes = 0;
block->left_side = TRUE;
@@ -4473,6 +4412,9 @@ buf_pool_validate_instance(
ut_a(rw_lock_is_locked(&block->lock,
RW_LOCK_EX));
break;
+
+ case BUF_IO_PIN:
+ break;
}
n_lru++;
@@ -4502,6 +4444,7 @@ buf_pool_validate_instance(
ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
switch (buf_page_get_io_fix(b)) {
case BUF_IO_NONE:
+ case BUF_IO_PIN:
/* All clean blocks should be I/O-unfixed. */
break;
case BUF_IO_READ:
@@ -4541,6 +4484,7 @@ buf_pool_validate_instance(
switch (buf_page_get_io_fix(b)) {
case BUF_IO_NONE:
case BUF_IO_READ:
+ case BUF_IO_PIN:
break;
case BUF_IO_WRITE:
switch (buf_page_get_flush_type(b)) {
diff --git a/storage/xtradb/buf/buf0flu.c b/storage/xtradb/buf/buf0flu.c
index 73a9ff96289..d776a274d14 100644
--- a/storage/xtradb/buf/buf0flu.c
+++ b/storage/xtradb/buf/buf0flu.c
@@ -1399,6 +1399,7 @@ buf_flush_try_neighbors(
ulint high;
ulint count = 0;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
+ ibool is_forward_scan;
ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST);
@@ -1429,7 +1430,32 @@ buf_flush_try_neighbors(
high = fil_space_get_size(space);
}
- for (i = low; i < high; i++) {
+ if (srv_flush_neighbor_pages == 2) {
+
+ /* In the case of contiguous flush where the requested page
+ does not fall at the start of flush area, first scan backward
+ from the page and later forward from it. */
+ is_forward_scan = (offset == low);
+ }
+ else {
+ is_forward_scan = TRUE;
+ }
+
+scan:
+ if (srv_flush_neighbor_pages == 2) {
+ if (is_forward_scan) {
+ i = offset;
+ }
+ else {
+ i = offset - 1;
+ }
+ }
+ else {
+ i = low;
+ }
+
+ for (; is_forward_scan ? (i < high) : (i >= low);
+ is_forward_scan ? i++ : i--) {
buf_page_t* bpage;
@@ -1460,6 +1486,12 @@ buf_flush_try_neighbors(
//buf_pool_mutex_exit(buf_pool);
rw_lock_s_unlock(&buf_pool->page_hash_latch);
+ if (srv_flush_neighbor_pages == 2) {
+
+ /* This is contiguous neighbor page flush and
+ the pages here are not contiguous. */
+ break;
+ }
continue;
}
@@ -1495,6 +1527,22 @@ buf_flush_try_neighbors(
}
//buf_pool_mutex_exit(buf_pool);
rw_lock_s_unlock(&buf_pool->page_hash_latch);
+
+ if (srv_flush_neighbor_pages == 2) {
+
+ /* We are trying to do the contiguous neighbor page
+ flush, but the last page we checked was unflushable,
+ making a "hole" in the flush, so stop this attempt. */
+ break;
+ }
+ }
+
+ if (!is_forward_scan) {
+
+ /* Backward scan done, now do the forward scan */
+ ut_a (srv_flush_neighbor_pages == 2);
+ is_forward_scan = TRUE;
+ goto scan;
}
return(count);
@@ -1988,6 +2036,22 @@ 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
diff --git a/storage/xtradb/buf/buf0lru.c b/storage/xtradb/buf/buf0lru.c
index a5a811f7afe..ecad1cf1e64 100644
--- a/storage/xtradb/buf/buf0lru.c
+++ b/storage/xtradb/buf/buf0lru.c
@@ -68,8 +68,12 @@ allowed to point to either end of the LRU list. */
/** When dropping the search hash index entries before deleting an ibd
file, we build a local array of pages belonging to that tablespace
-in the buffer pool. Following is the size of that array. */
-#define BUF_LRU_DROP_SEARCH_HASH_SIZE 1024
+in the buffer pool. Following is the size of that array.
+We also release buf_pool->mutex after scanning this many pages of the
+flush_list when dropping a table. This is to ensure that other threads
+are not blocked for extended period of time when using very large
+buffer pools. */
+#define BUF_LRU_DROP_SEARCH_SIZE 1024
/** If we switch on the InnoDB monitor because there are too few available
frames in the buffer pool, we set this to TRUE */
@@ -222,7 +226,7 @@ buf_LRU_drop_page_hash_batch(
ulint i;
ut_ad(arr != NULL);
- ut_ad(count <= BUF_LRU_DROP_SEARCH_HASH_SIZE);
+ ut_ad(count <= BUF_LRU_DROP_SEARCH_SIZE);
for (i = 0; i < count; ++i) {
btr_search_drop_page_hash_when_freed(space_id, zip_size,
@@ -256,7 +260,7 @@ buf_LRU_drop_page_hash_for_tablespace(
}
page_arr = ut_malloc(
- sizeof(ulint) * BUF_LRU_DROP_SEARCH_HASH_SIZE);
+ sizeof(ulint) * BUF_LRU_DROP_SEARCH_SIZE);
//buf_pool_mutex_enter(buf_pool);
mutex_enter(&buf_pool->LRU_list_mutex);
@@ -293,7 +297,7 @@ next_page:
//mutex_enter(&((buf_block_t*) bpage)->mutex);
is_fixed = bpage->buf_fix_count > 0
- || !((buf_block_t*) bpage)->is_hashed;
+ || !((buf_block_t*) bpage)->index;
//mutex_exit(&((buf_block_t*) bpage)->mutex);
if (is_fixed) {
@@ -304,12 +308,14 @@ next_page:
/* Store the page number so that we can drop the hash
index in a batch later. */
page_arr[num_entries] = bpage->offset;
+
mutex_exit(block_mutex);
- ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE);
+ ut_a(num_entries < BUF_LRU_DROP_SEARCH_SIZE);
+
++num_entries;
- if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) {
+ if (num_entries < BUF_LRU_DROP_SEARCH_SIZE) {
goto next_page;
}
@@ -366,39 +372,42 @@ next_page:
}
/******************************************************************//**
-Invalidates all pages belonging to a given tablespace inside a specific
+Remove all dirty pages belonging to a given tablespace inside a specific
buffer pool instance when we are deleting the data file(s) of that
-tablespace. */
+tablespace. The pages still remain a part of LRU and are evicted from
+the list as they age towards the tail of the LRU. */
static
void
-buf_LRU_invalidate_tablespace_buf_pool_instance(
-/*============================================*/
+buf_LRU_remove_dirty_pages_for_tablespace(
+/*======================================*/
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint id) /*!< in: space id */
{
buf_page_t* bpage;
ibool all_freed;
+ ulint i;
scan_again:
//buf_pool_mutex_enter(buf_pool);
mutex_enter(&buf_pool->LRU_list_mutex);
rw_lock_x_lock(&buf_pool->page_hash_latch);
+ buf_flush_list_mutex_enter(buf_pool);
all_freed = TRUE;
- bpage = UT_LIST_GET_LAST(buf_pool->LRU);
+ for (bpage = UT_LIST_GET_LAST(buf_pool->flush_list), i = 0;
+ bpage != NULL; ++i) {
- while (bpage != NULL) {
buf_page_t* prev_bpage;
mutex_t* block_mutex = NULL;
ut_a(buf_page_in_file(bpage));
- prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
+ prev_bpage = UT_LIST_GET_PREV(flush_list, bpage);
/* bpage->space and bpage->io_fix are protected by
- buf_pool_mutex and block_mutex. It is safe to check
- them while holding buf_pool_mutex only. */
+ buf_pool->mutex and block_mutex. It is safe to check
+ them while holding buf_pool->mutex only. */
if (buf_page_get_space(bpage) != id) {
/* Skip this block, as it does not belong to
@@ -411,90 +420,97 @@ scan_again:
all_freed = FALSE;
goto next_page;
- } else {
- block_mutex = buf_page_get_mutex_enter(bpage);
-
- if (!block_mutex) {
- /* It may be impossible case...
- Something wrong, so will be scan_again */
+ }
- all_freed = FALSE;
- goto next_page;
- }
+ /* We have to release the flush_list_mutex to obey the
+ latching order. We are however guaranteed that the page
+ will stay in the flush_list because buf_flush_remove()
+ needs buf_pool->mutex as well. */
+ buf_flush_list_mutex_exit(buf_pool);
+ block_mutex = buf_page_get_mutex_enter(bpage);
- if (bpage->buf_fix_count > 0) {
+ if (!block_mutex) {
+ /* It may be impossible case...
+ Something wrong, so will be scan_again */
+ all_freed = FALSE;
+ goto next_page;
+ }
- mutex_exit(block_mutex);
- /* We cannot remove this page during
- this scan yet; maybe the system is
- currently reading it in, or flushing
- the modifications to the file */
+ if (bpage->buf_fix_count > 0) {
+ mutex_exit(block_mutex);
+ buf_flush_list_mutex_enter(buf_pool);
- all_freed = FALSE;
+ /* We cannot remove this page during
+ this scan yet; maybe the system is
+ currently reading it in, or flushing
+ the modifications to the file */
- goto next_page;
- }
+ all_freed = FALSE;
+ goto next_page;
}
- ut_ad(mutex_own(block_mutex));
+ ut_ad(bpage->oldest_modification != 0);
-#ifdef UNIV_DEBUG
- if (buf_debug_prints) {
- fprintf(stderr,
- "Dropping space %lu page %lu\n",
- (ulong) buf_page_get_space(bpage),
- (ulong) buf_page_get_page_no(bpage));
+ buf_flush_remove(bpage);
+
+ mutex_exit(block_mutex);
+ buf_flush_list_mutex_enter(buf_pool);
+next_page:
+ bpage = prev_bpage;
+
+ if (!bpage) {
+ break;
}
-#endif
- if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
- /* This is a compressed-only block
- descriptor. Do nothing. */
- } else if (((buf_block_t*) bpage)->is_hashed) {
- ulint page_no;
- ulint zip_size;
- //buf_pool_mutex_exit(buf_pool);
- mutex_exit(&buf_pool->LRU_list_mutex);
- rw_lock_x_unlock(&buf_pool->page_hash_latch);
+ /* Every BUF_LRU_DROP_SEARCH_SIZE iterations in the
+ loop we release buf_pool->mutex to let other threads
+ do their job. */
+ if (i < BUF_LRU_DROP_SEARCH_SIZE) {
+ continue;
+ }
- zip_size = buf_page_get_zip_size(bpage);
- page_no = buf_page_get_page_no(bpage);
+ /* We IO-fix the block to make sure that the block
+ stays in its position in the flush_list. */
+ if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
+ /* Block is already IO-fixed. We don't
+ want to change the value. Lets leave
+ this block alone. */
+ continue;
+ }
- mutex_exit(block_mutex);
+ buf_flush_list_mutex_exit(buf_pool);
+ block_mutex = buf_page_get_mutex(bpage);
+ mutex_enter(block_mutex);
+ buf_page_set_sticky(bpage);
+ mutex_exit(block_mutex);
- /* Note that the following call will acquire
- an S-latch on the page */
+ /* Now it is safe to release the buf_pool->mutex. */
+ //buf_pool_mutex_exit(buf_pool);
+ mutex_exit(&buf_pool->LRU_list_mutex);
+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
- btr_search_drop_page_hash_when_freed(
- id, zip_size, page_no);
- goto scan_again;
- }
+ os_thread_yield();
+ //buf_pool_mutex_enter(buf_pool);
+ mutex_enter(&buf_pool->LRU_list_mutex);
+ rw_lock_x_lock(&buf_pool->page_hash_latch);
- if (bpage->oldest_modification != 0) {
- buf_flush_remove(bpage);
- }
+ mutex_enter(block_mutex);
+ buf_page_unset_sticky(bpage);
+ mutex_exit(block_mutex);
- /* Remove from the LRU list. */
+ buf_flush_list_mutex_enter(buf_pool);
+ ut_ad(bpage->in_flush_list);
- if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
- != BUF_BLOCK_ZIP_FREE) {
- buf_LRU_block_free_hashed_page((buf_block_t*) bpage, TRUE);
- mutex_exit(block_mutex);
- } else {
- /* The block_mutex should have been released
- by buf_LRU_block_remove_hashed_page() when it
- returns BUF_BLOCK_ZIP_FREE. */
- ut_ad(block_mutex == &buf_pool->zip_mutex);
- ut_ad(!mutex_own(block_mutex));
- }
-next_page:
- bpage = prev_bpage;
+ i = 0;
}
- //buf_pool_mutex_exit(buf_pool);
+// buf_pool_mutex_exit(buf_pool);
mutex_exit(&buf_pool->LRU_list_mutex);
rw_lock_x_unlock(&buf_pool->page_hash_latch);
+ buf_flush_list_mutex_exit(buf_pool);
+
+ ut_ad(buf_flush_validate(buf_pool));
if (!all_freed) {
os_thread_sleep(20000);
@@ -525,7 +541,7 @@ buf_LRU_invalidate_tablespace(
buf_pool = buf_pool_from_array(i);
buf_LRU_drop_page_hash_for_tablespace(buf_pool, id);
- buf_LRU_invalidate_tablespace_buf_pool_instance(buf_pool, id);
+ buf_LRU_remove_dirty_pages_for_tablespace(buf_pool, id);
}
}
@@ -567,7 +583,7 @@ buf_LRU_mark_space_was_deleted(
for (k = chunk->size; k--; block++) {
if (buf_block_get_state(block)
!= BUF_BLOCK_FILE_PAGE
- || !block->is_hashed
+ || !block->index
|| buf_page_get_space(&block->page) != id) {
continue;
}
@@ -575,7 +591,7 @@ buf_LRU_mark_space_was_deleted(
btr_search_s_unlock_all();
rw_lock_x_lock(&block->lock);
- btr_search_drop_page_hash_index(block, NULL);
+ btr_search_drop_page_hash_index(block);
rw_lock_x_unlock(&block->lock);
btr_search_s_lock_all();
@@ -1726,8 +1742,7 @@ not_freed:
/* Prevent buf_page_get_gen() from
decompressing the block while we release
buf_pool->mutex and block_mutex. */
- b->buf_fix_count++;
- b->io_fix = BUF_IO_READ;
+ buf_page_set_sticky(b);
mutex_exit(&buf_pool->zip_mutex);
}
@@ -1744,7 +1759,7 @@ not_freed:
UNIV_MEM_VALID(((buf_block_t*) bpage)->frame,
UNIV_PAGE_SIZE);
- btr_search_drop_page_hash_index((buf_block_t*) bpage, NULL);
+ btr_search_drop_page_hash_index((buf_block_t*) bpage);
UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame,
UNIV_PAGE_SIZE);
@@ -1772,8 +1787,7 @@ not_freed:
if (b) {
mutex_enter(&buf_pool->zip_mutex);
- b->buf_fix_count--;
- buf_page_set_io_fix(b, BUF_IO_NONE);
+ buf_page_unset_sticky(b);
mutex_exit(&buf_pool->zip_mutex);
}
diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c
index 07f22e4d1d6..98cf88455bd 100644
--- a/storage/xtradb/dict/dict0dict.c
+++ b/storage/xtradb/dict/dict0dict.c
@@ -919,6 +919,11 @@ dict_index_find_on_id_low(
dict_table_t* table;
dict_index_t* index;
+ /* This can happen if the system tablespace is the wrong page size */
+ if (dict_sys == NULL) {
+ return(NULL);
+ }
+
table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
while (table) {
diff --git a/storage/xtradb/dict/dict0load.c b/storage/xtradb/dict/dict0load.c
index 47f969727fb..5303557548b 100644
--- a/storage/xtradb/dict/dict0load.c
+++ b/storage/xtradb/dict/dict0load.c
@@ -849,7 +849,7 @@ loop:
object and check that the .ibd file exists. */
fil_open_single_table_tablespace(FALSE, space_id,
- flags, name);
+ flags, name, NULL);
}
mem_free(name);
@@ -1904,7 +1904,7 @@ err_exit:
if (!fil_open_single_table_tablespace(
TRUE, table->space,
table->flags == DICT_TF_COMPACT ? 0 :
- table->flags & ~(~0 << DICT_TF_BITS), name)) {
+ table->flags & ~(~0 << DICT_TF_BITS), name, NULL)) {
/* We failed to find a sensible
tablespace file */
diff --git a/storage/xtradb/fil/fil0fil.c b/storage/xtradb/fil/fil0fil.c
index 41b61be0b5b..8cabf13e2c4 100644
--- a/storage/xtradb/fil/fil0fil.c
+++ b/storage/xtradb/fil/fil0fil.c
@@ -1827,36 +1827,44 @@ fil_write_flushed_lsn_to_data_files(
}
/*******************************************************************//**
-Reads the flushed lsn and arch no fields from a data file at database
-startup. */
+Reads the flushed lsn, arch no, and tablespace flag fields from a data
+file at database startup. */
UNIV_INTERN
void
-fil_read_flushed_lsn_and_arch_log_no(
-/*=================================*/
+fil_read_first_page(
+/*================*/
os_file_t data_file, /*!< in: open data file */
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
+ ulint* flags, /*!< out: tablespace flags */
#ifdef UNIV_LOG_ARCHIVE
- ulint* min_arch_log_no, /*!< in/out: */
- ulint* max_arch_log_no, /*!< in/out: */
+ ulint* min_arch_log_no, /*!< out: min of archived
+ log numbers in data files */
+ ulint* max_arch_log_no, /*!< out: max of archived
+ log numbers in data files */
#endif /* UNIV_LOG_ARCHIVE */
- ib_uint64_t* min_flushed_lsn, /*!< in/out: */
- ib_uint64_t* max_flushed_lsn) /*!< in/out: */
+ ib_uint64_t* min_flushed_lsn, /*!< out: min of flushed
+ lsn values in data files */
+ ib_uint64_t* max_flushed_lsn) /*!< out: max of flushed
+ lsn values in data files */
{
byte* buf;
- byte* buf2;
+ page_t* page;
ib_uint64_t flushed_lsn;
- buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
+ buf = ut_malloc(2 * UNIV_PAGE_SIZE);
/* Align the memory for a possible read from a raw device */
- buf = ut_align(buf2, UNIV_PAGE_SIZE);
+ page = ut_align(buf, UNIV_PAGE_SIZE);
- os_file_read(data_file, buf, 0, 0, UNIV_PAGE_SIZE);
+ os_file_read(data_file, page, 0, 0, UNIV_PAGE_SIZE);
- flushed_lsn = mach_read_from_8(buf + FIL_PAGE_FILE_FLUSH_LSN);
+ *flags = mach_read_from_4(page +
+ FSP_HEADER_OFFSET + FSP_SPACE_FLAGS);
- ut_free(buf2);
+ flushed_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN);
+
+ ut_free(buf);
if (!one_read_already) {
*min_flushed_lsn = flushed_lsn;
@@ -3174,8 +3182,11 @@ fil_open_single_table_tablespace(
accessing the first page of the file */
ulint id, /*!< in: space id */
ulint flags, /*!< in: tablespace flags */
- const char* name) /*!< in: table name in the
+ const char* name, /*!< in: table name in the
databasename/tablename format */
+ trx_t* trx) /*!< in: transaction. This is only used
+ for IMPORT TABLESPACE, must be NULL
+ otherwise */
{
os_file_t file;
char* filepath;
@@ -3393,6 +3404,11 @@ skip_info:
/* over write space id of all pages */
rec_offs_init(offsets_);
+ /* Unlock the data dictionary to not block queries
+ accessing other tables */
+ ut_a(trx);
+ row_mysql_unlock_data_dictionary(trx);
+
fprintf(stderr, "InnoDB: Progress in %%:");
for (offset = 0; offset < free_limit_bytes;
@@ -3594,6 +3610,9 @@ skip_write:
fprintf(stderr, " done.\n");
+ /* Reacquire the data dictionary lock */
+ row_mysql_lock_data_dictionary(trx);
+
/* update SYS_INDEXES set root page */
index = dict_table_get_first_index(table);
while (index) {
diff --git a/storage/xtradb/fsp/fsp0fsp.c b/storage/xtradb/fsp/fsp0fsp.c
index 5e3959a3c7f..6102c5decd8 100644
--- a/storage/xtradb/fsp/fsp0fsp.c
+++ b/storage/xtradb/fsp/fsp0fsp.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, 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
*****************************************************************************/
@@ -50,67 +50,6 @@ Created 11/29/1995 Heikki Tuuri
#include "dict0mem.h"
#include "trx0sys.h"
-#define FSP_HEADER_OFFSET FIL_PAGE_DATA /* Offset of the space header
- within a file page */
-
-/* The data structures in files are defined just as byte strings in C */
-typedef byte fsp_header_t;
-typedef byte xdes_t;
-
-/* SPACE HEADER
- ============
-
-File space header data structure: this data structure is contained in the
-first page of a space. The space for this header is reserved in every extent
-descriptor page, but used only in the first. */
-
-/*-------------------------------------*/
-#define FSP_SPACE_ID 0 /* space id */
-#define FSP_NOT_USED 4 /* this field contained a value up to
- which we know that the modifications
- in the database have been flushed to
- the file space; not used now */
-#define FSP_SIZE 8 /* Current size of the space in
- pages */
-#define FSP_FREE_LIMIT 12 /* Minimum page number for which the
- free list has not been initialized:
- the pages >= this limit are, by
- definition, free; note that in a
- single-table tablespace where size
- < 64 pages, this number is 64, i.e.,
- we have initialized the space
- about the first extent, but have not
- physically allocted those pages to the
- file */
-#define FSP_SPACE_FLAGS 16 /* table->flags & ~DICT_TF_COMPACT */
-#define FSP_FRAG_N_USED 20 /* number of used pages in the
- FSP_FREE_FRAG list */
-#define FSP_FREE 24 /* list of free extents */
-#define FSP_FREE_FRAG (24 + FLST_BASE_NODE_SIZE)
- /* list of partially free extents not
- belonging to any segment */
-#define FSP_FULL_FRAG (24 + 2 * FLST_BASE_NODE_SIZE)
- /* list of full extents not belonging
- to any segment */
-#define FSP_SEG_ID (24 + 3 * FLST_BASE_NODE_SIZE)
- /* 8 bytes which give the first unused
- segment id */
-#define FSP_SEG_INODES_FULL (32 + 3 * FLST_BASE_NODE_SIZE)
- /* list of pages containing segment
- headers, where all the segment inode
- slots are reserved */
-#define FSP_SEG_INODES_FREE (32 + 4 * FLST_BASE_NODE_SIZE)
- /* list of pages containing segment
- headers, where not all the segment
- header slots are reserved */
-/*-------------------------------------*/
-/* File space header size */
-#define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE)
-
-#define FSP_FREE_ADD 4 /* this many free extents are added
- to the free list from above
- FSP_FREE_LIMIT at a time */
-
/* FILE SEGMENT INODE
==================
diff --git a/storage/xtradb/ha/ha0ha.c b/storage/xtradb/ha/ha0ha.c
index b28995553e0..2f5051e541f 100644
--- a/storage/xtradb/ha/ha0ha.c
+++ b/storage/xtradb/ha/ha0ha.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, 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
@@ -89,41 +89,6 @@ ha_create_func(
}
/*************************************************************//**
-Empties a hash table and frees the memory heaps. */
-UNIV_INTERN
-void
-ha_clear(
-/*=====*/
- hash_table_t* table) /*!< in, own: hash table */
-{
- ulint i;
- ulint n;
-
- ut_ad(table);
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
-#ifdef UNIV_SYNC_DEBUG
- /* cannot identificate which btr_search_latch[i] for now */
- //ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
-#endif /* UNIV_SYNC_DEBUG */
-
-#ifndef UNIV_HOTBACKUP
- /* Free the memory heaps. */
- n = table->n_mutexes;
-
- for (i = 0; i < n; i++) {
- mem_heap_free(table->heaps[i]);
- }
-#endif /* !UNIV_HOTBACKUP */
-
- /* Clear the hash table. */
- n = hash_get_n_cells(table);
-
- for (i = 0; i < n; i++) {
- hash_get_nth_cell(table, i)->node = NULL;
- }
-}
-
-/*************************************************************//**
Inserts an entry into a hash table. If an entry with the same fold number
is found, its node is updated to point to the new data, and no new node
is inserted. If btr_search_enabled is set to FALSE, we will only allow
@@ -141,7 +106,7 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block, /*!< in: buffer block containing the data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* data) /*!< in: data, must not be NULL */
+ const rec_t* data) /*!< in: data, must not be NULL */
{
hash_cell_t* cell;
ha_node_t* node;
@@ -154,7 +119,11 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ut_a(block->frame == page_align(data));
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(block->btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
ASSERT_HASH_MUTEX_OWN(table, fold);
+ ut_ad(btr_search_enabled);
hash = hash_calc_hash(fold, table);
@@ -174,7 +143,6 @@ ha_insert_for_fold_func(
prev_block->n_pointers--;
block->n_pointers++;
}
- ut_ad(!btr_search_fully_disabled);
# endif /* !UNIV_HOTBACKUP */
prev_node->block = block;
@@ -187,13 +155,6 @@ ha_insert_for_fold_func(
prev_node = prev_node->next;
}
- /* We are in the process of disabling hash index, do not add
- new chain node */
- if (!btr_search_enabled) {
- ut_ad(!btr_search_fully_disabled);
- return(TRUE);
- }
-
/* We have to allocate a new chain node */
node = mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t));
@@ -251,6 +212,10 @@ ha_delete_hash_node(
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
+#ifdef UNIV_SYNC_DEBUG
+ // ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+ ut_ad(btr_search_enabled);
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
# ifndef UNIV_HOTBACKUP
if (table->adaptive) {
@@ -273,11 +238,11 @@ ha_search_and_update_if_found_func(
/*===============================*/
hash_table_t* table, /*!< in/out: hash table */
ulint fold, /*!< in: folded value of the searched data */
- void* data, /*!< in: pointer to the data */
+ const rec_t* data, /*!< in: pointer to the data */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* new_block,/*!< in: block containing new_data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* new_data)/*!< in: new pointer to the data */
+ const rec_t* new_data)/*!< in: new pointer to the data */
{
ha_node_t* node;
@@ -287,6 +252,13 @@ ha_search_and_update_if_found_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ut_a(new_block->frame == page_align(new_data));
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+#ifdef UNIV_SYNC_DEBUG
+ // ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
+ if (!btr_search_enabled) {
+ return;
+ }
node = ha_search_with_data(table, fold, data);
@@ -323,6 +295,10 @@ ha_remove_all_nodes_to_page(
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ASSERT_HASH_MUTEX_OWN(table, fold);
+#ifdef UNIV_SYNC_DEBUG
+ // ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+ ut_ad(btr_search_enabled);
node = ha_chain_get_first(table, fold);
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 3aa5ff1622d..504595b1448 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -3035,7 +3035,6 @@ skip_overwrite:
/* Get the current high water mark format. */
innobase_file_format_max = (char*) trx_sys_file_format_max_get();
- btr_search_fully_disabled = (!btr_search_enabled);
DBUG_RETURN(FALSE);
error:
DBUG_RETURN(TRUE);
@@ -5839,8 +5838,7 @@ no_commit:
switch (sql_command) {
case SQLCOM_LOAD:
- if ((trx->duplicates
- & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
+ if (trx->duplicates) {
goto set_max_autoinc;
}
@@ -6128,8 +6126,7 @@ ha_innobase::update_row(
&& table->next_number_field
&& new_row == table->record[0]
&& thd_sql_command(user_thd) == SQLCOM_INSERT
- && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
- == TRX_DUP_IGNORE) {
+ && trx->duplicates) {
ulonglong auto_inc;
ulonglong col_max_value;
@@ -6515,6 +6512,7 @@ ha_innobase::index_read(
(byte*) key_ptr,
(ulint) key_len,
prebuilt->trx);
+ DBUG_ASSERT(prebuilt->search_tuple->n_fields > 0);
} else {
/* We position the cursor to the last or the first entry
in the index */
@@ -6616,7 +6614,6 @@ ha_innobase::innobase_get_index(
dict_index_t* index = 0;
DBUG_ENTER("innobase_get_index");
- ha_statistic_increment(&SSV::ha_read_key_count);
if (keynr != MAX_KEY && table->s->keys > 0) {
key = table->key_info + keynr;
@@ -6630,13 +6627,13 @@ ha_innobase::innobase_get_index(
table. Only print message if the index translation
table exists */
if (share->idx_trans_tbl.index_mapping) {
- sql_print_error("InnoDB could not find "
- "index %s key no %u for "
- "table %s through its "
- "index translation table",
- key ? key->name : "NULL",
- keynr,
- prebuilt->table->name);
+ sql_print_warning("InnoDB could not find "
+ "index %s key no %u for "
+ "table %s through its "
+ "index translation table",
+ key ? key->name : "NULL",
+ keynr,
+ prebuilt->table->name);
}
index = dict_table_get_index_on_name(prebuilt->table,
@@ -8465,6 +8462,9 @@ ha_innobase::records_in_range(
(const uchar*) 0),
(ulint) (min_key ? min_key->length : 0),
prebuilt->trx);
+ DBUG_ASSERT(min_key
+ ? range_start->n_fields > 0
+ : range_start->n_fields == 0);
row_sel_convert_mysql_key_to_innobase(
range_end, (byte*) key_val_buff2,
@@ -8473,6 +8473,9 @@ ha_innobase::records_in_range(
(const uchar*) 0),
(ulint) (max_key ? max_key->length : 0),
prebuilt->trx);
+ DBUG_ASSERT(max_key
+ ? range_end->n_fields > 0
+ : range_end->n_fields == 0);
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
HA_READ_KEY_EXACT);
@@ -9217,7 +9220,10 @@ ha_innobase::check(
putc('\n', stderr);
#endif
- if (!btr_validate_index(index, prebuilt->trx)) {
+ /* If this is an index being created, break */
+ if (*index->name == TEMP_INDEX_PREFIX) {
+ break;
+ } else if (!btr_validate_index(index, prebuilt->trx)) {
is_ok = FALSE;
innobase_format_name(
@@ -9770,6 +9776,7 @@ ha_innobase::extra(
break;
case HA_EXTRA_RESET_STATE:
reset_template();
+ thd_to_trx(ha_thd())->duplicates = 0;
break;
case HA_EXTRA_NO_KEYREAD:
prebuilt->read_just_key = 0;
@@ -9787,19 +9794,18 @@ ha_innobase::extra(
parameters below. We must not invoke update_thd()
either, because the calling threads may change.
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
- case HA_EXTRA_IGNORE_DUP_KEY:
+ case HA_EXTRA_INSERT_WITH_UPDATE:
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
break;
+ case HA_EXTRA_NO_IGNORE_DUP_KEY:
+ thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_IGNORE;
+ break;
case HA_EXTRA_WRITE_CAN_REPLACE:
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
break;
case HA_EXTRA_WRITE_CANNOT_REPLACE:
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
break;
- case HA_EXTRA_NO_IGNORE_DUP_KEY:
- thd_to_trx(ha_thd())->duplicates &=
- ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
- break;
default:/* Do nothing */
;
}
@@ -12549,10 +12555,42 @@ static MYSQL_SYSVAR_ULINT(checkpoint_age_target, srv_checkpoint_age_target,
"Control soft limit of checkpoint age. (0 : not control)",
NULL, NULL, 0, 0, ~0UL, 0);
-static MYSQL_SYSVAR_ULINT(flush_neighbor_pages, srv_flush_neighbor_pages,
- PLUGIN_VAR_RQCMDARG,
- "Enable/Disable flushing also neighbor pages. 0:disable 1:enable",
- NULL, NULL, 1, 0, 1, 0);
+static
+void
+innodb_flush_neighbor_pages_update(
+ THD* thd,
+ struct st_mysql_sys_var* var,
+ void* var_ptr,
+ const void* save)
+{
+ *(long *)var_ptr = (*(long *)save) % 3;
+}
+
+const char *flush_neighbor_pages_names[]=
+{
+ "none", /* 0 */
+ "area",
+ "cont", /* 2 */
+ /* For compatibility with the older patch */
+ "0", /* "none" + 3 */
+ "1", /* "area" + 3 */
+ "2", /* "cont" + 3 */
+ NullS
+};
+
+TYPELIB flush_neighbor_pages_typelib=
+{
+ array_elements(flush_neighbor_pages_names) - 1,
+ "flush_neighbor_pages_typelib",
+ flush_neighbor_pages_names,
+ NULL
+};
+
+static MYSQL_SYSVAR_ENUM(flush_neighbor_pages, srv_flush_neighbor_pages,
+ PLUGIN_VAR_RQCMDARG, "Neighbor page flushing behaviour: none: do not flush, "
+ "[area]: flush selected pages one-by-one, "
+ "cont: flush a contiguous block of pages", NULL,
+ innodb_flush_neighbor_pages_update, 1, &flush_neighbor_pages_typelib);
static
void
@@ -12618,6 +12656,14 @@ static MYSQL_SYSVAR_ENUM(adaptive_flushing_method, srv_adaptive_flushing_method,
"Choose method of innodb_adaptive_flushing. (native, [estimate], keep_average)",
NULL, innodb_adaptive_flushing_method_update, 1, &adaptive_flushing_method_typelib);
+#ifdef UNIV_DEBUG
+static MYSQL_SYSVAR_ULONG(flush_checkpoint_debug, srv_flush_checkpoint_debug,
+ PLUGIN_VAR_RQCMDARG,
+ "Debug flags for InnoDB flushing and checkpointing (0=none,"
+ "1=stop preflush and checkpointing)",
+ NULL, NULL, 0, 0, 1, 0);
+#endif
+
static MYSQL_SYSVAR_ULONG(import_table_from_xtrabackup, srv_expand_import,
PLUGIN_VAR_RQCMDARG,
"Enable/Disable converting automatically *.ibd files when import tablespace.",
@@ -12764,6 +12810,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(purge_threads),
MYSQL_SYSVAR(purge_batch_size),
MYSQL_SYSVAR(rollback_segments),
+#ifdef UNIV_DEBUG
+ MYSQL_SYSVAR(flush_checkpoint_debug),
+#endif
MYSQL_SYSVAR(corrupt_table_action),
MYSQL_SYSVAR(lazy_drop_table),
MYSQL_SYSVAR(fake_changes),
diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc
index 72ff5f7198b..3b87b860a4a 100644
--- a/storage/xtradb/handler/i_s.cc
+++ b/storage/xtradb/handler/i_s.cc
@@ -3916,7 +3916,7 @@ i_s_innodb_buffer_pool_pages_index_fill(
table->field[2]->store(block->page.offset, TRUE);
table->field[3]->store(page_get_n_recs(frame), TRUE);
table->field[4]->store(page_get_data_size(frame), TRUE);
- table->field[5]->store(block->is_hashed, TRUE);
+ table->field[5]->store(block->index != NULL, TRUE);
table->field[6]->store(block->page.access_time, TRUE);
table->field[7]->store(block->page.newest_modification != 0, TRUE);
table->field[8]->store(block->page.oldest_modification != 0, TRUE);
diff --git a/storage/xtradb/ibuf/ibuf0ibuf.c b/storage/xtradb/ibuf/ibuf0ibuf.c
index 7def360867d..00b7ea7347d 100644
--- a/storage/xtradb/ibuf/ibuf0ibuf.c
+++ b/storage/xtradb/ibuf/ibuf0ibuf.c
@@ -254,11 +254,20 @@ ibuf_count_check(
list of the ibuf */
/* @} */
+#define IBUF_REC_FIELD_SPACE 0 /*!< in the pre-4.1 format,
+ the page number. later, the space_id */
+#define IBUF_REC_FIELD_MARKER 1 /*!< starting with 4.1, a marker
+ consisting of 1 byte that is 0 */
+#define IBUF_REC_FIELD_PAGE 2 /*!< starting with 4.1, the
+ page number */
+#define IBUF_REC_FIELD_METADATA 3 /* the metadata field */
+#define IBUF_REC_FIELD_USER 4 /* first user field */
+
/* Various constants for checking the type of an ibuf record and extracting
data from it. For details, see the description of the record format at the
top of this file. */
-/** @name Format of the fourth column of an insert buffer record
+/** @name Format of the IBUF_REC_FIELD_METADATA of an insert buffer record
The fourth column in the MySQL 5.5 format contains an operation
type, counter, and some flags. */
/* @{ */
@@ -1275,13 +1284,13 @@ ibuf_rec_get_page_no_func(
ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(rec) > 2);
- field = rec_get_nth_field_old(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_MARKER, &len);
if (len == 1) {
/* This is of the >= 4.1.x record format */
ut_a(trx_sys_multiple_tablespace_format);
- field = rec_get_nth_field_old(rec, 2, &len);
+ field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_PAGE, &len);
} else {
ut_a(trx_doublewrite_must_reset_space_ids);
ut_a(!trx_sys_multiple_tablespace_format);
@@ -1321,13 +1330,13 @@ ibuf_rec_get_space_func(
ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(rec) > 2);
- field = rec_get_nth_field_old(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_MARKER, &len);
if (len == 1) {
/* This is of the >= 4.1.x record format */
ut_a(trx_sys_multiple_tablespace_format);
- field = rec_get_nth_field_old(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_SPACE, &len);
ut_a(len == 4);
return(mach_read_from_4(field));
@@ -1377,9 +1386,9 @@ ibuf_rec_get_info_func(
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(ibuf_inside(mtr));
fields = rec_get_n_fields_old(rec);
- ut_a(fields > 4);
+ ut_a(fields > IBUF_REC_FIELD_USER);
- types = rec_get_nth_field_old(rec, 3, &len);
+ types = rec_get_nth_field_old(rec, IBUF_REC_FIELD_METADATA, &len);
info_len_local = len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE;
@@ -1405,7 +1414,8 @@ ibuf_rec_get_info_func(
ut_a(op_local < IBUF_OP_COUNT);
ut_a((len - info_len_local) ==
- (fields - 4) * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+ (fields - IBUF_REC_FIELD_USER)
+ * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
if (op) {
*op = op_local;
@@ -1449,7 +1459,7 @@ ibuf_rec_get_op_type_func(
ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(rec) > 2);
- (void) rec_get_nth_field_old(rec, 1, &len);
+ (void) rec_get_nth_field_old(rec, IBUF_REC_FIELD_MARKER, &len);
if (len > 1) {
/* This is a < 4.1.x format record */
@@ -1478,12 +1488,12 @@ ibuf_rec_get_counter(
const byte* ptr;
ulint len;
- if (rec_get_n_fields_old(rec) < 4) {
+ if (rec_get_n_fields_old(rec) <= IBUF_REC_FIELD_METADATA) {
return(ULINT_UNDEFINED);
}
- ptr = rec_get_nth_field_old(rec, 3, &len);
+ ptr = rec_get_nth_field_old(rec, IBUF_REC_FIELD_METADATA, &len);
if (len >= 2) {
@@ -1708,7 +1718,7 @@ ibuf_build_entry_from_ibuf_rec_func(
|| mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(ibuf_inside(mtr));
- data = rec_get_nth_field_old(ibuf_rec, 1, &len);
+ data = rec_get_nth_field_old(ibuf_rec, IBUF_REC_FIELD_MARKER, &len);
if (len > 1) {
/* This a < 4.1.x format record */
@@ -1720,13 +1730,13 @@ ibuf_build_entry_from_ibuf_rec_func(
ut_a(trx_sys_multiple_tablespace_format);
ut_a(*data == 0);
- ut_a(rec_get_n_fields_old(ibuf_rec) > 4);
+ ut_a(rec_get_n_fields_old(ibuf_rec) > IBUF_REC_FIELD_USER);
- n_fields = rec_get_n_fields_old(ibuf_rec) - 4;
+ n_fields = rec_get_n_fields_old(ibuf_rec) - IBUF_REC_FIELD_USER;
tuple = dtuple_create(heap, n_fields);
- types = rec_get_nth_field_old(ibuf_rec, 3, &len);
+ types = rec_get_nth_field_old(ibuf_rec, IBUF_REC_FIELD_METADATA, &len);
ibuf_rec_get_info(mtr, ibuf_rec, NULL, &comp, &info_len, NULL);
@@ -1740,7 +1750,8 @@ ibuf_build_entry_from_ibuf_rec_func(
for (i = 0; i < n_fields; i++) {
field = dtuple_get_nth_field(tuple, i);
- data = rec_get_nth_field_old(ibuf_rec, i + 4, &len);
+ data = rec_get_nth_field_old(
+ ibuf_rec, i + IBUF_REC_FIELD_USER, &len);
dfield_set_data(field, data, len);
@@ -1787,7 +1798,7 @@ ibuf_rec_get_size(
field_offset = 2;
types_offset = DATA_ORDER_NULL_TYPE_BUF_SIZE;
} else {
- field_offset = 4;
+ field_offset = IBUF_REC_FIELD_USER;
types_offset = DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE;
}
@@ -1848,7 +1859,7 @@ ibuf_rec_get_volume_func(
ut_ad(ibuf_inside(mtr));
ut_ad(rec_get_n_fields_old(ibuf_rec) > 2);
- data = rec_get_nth_field_old(ibuf_rec, 1, &len);
+ data = rec_get_nth_field_old(ibuf_rec, IBUF_REC_FIELD_MARKER, &len);
pre_4_1 = (len > 1);
if (pre_4_1) {
@@ -1871,7 +1882,8 @@ ibuf_rec_get_volume_func(
ut_a(trx_sys_multiple_tablespace_format);
ut_a(*data == 0);
- types = rec_get_nth_field_old(ibuf_rec, 3, &len);
+ types = rec_get_nth_field_old(
+ ibuf_rec, IBUF_REC_FIELD_METADATA, &len);
ibuf_rec_get_info(mtr, ibuf_rec, &op, &comp, &info_len, NULL);
@@ -1901,7 +1913,8 @@ ibuf_rec_get_volume_func(
}
types += info_len;
- n_fields = rec_get_n_fields_old(ibuf_rec) - 4;
+ n_fields = rec_get_n_fields_old(ibuf_rec)
+ - IBUF_REC_FIELD_USER;
}
data_size = ibuf_rec_get_size(ibuf_rec, types, n_fields, pre_4_1, comp);
@@ -1956,11 +1969,11 @@ ibuf_entry_build(
n_fields = dtuple_get_n_fields(entry);
- tuple = dtuple_create(heap, n_fields + 4);
+ tuple = dtuple_create(heap, n_fields + IBUF_REC_FIELD_USER);
/* 1) Space Id */
- field = dtuple_get_nth_field(tuple, 0);
+ field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_SPACE);
buf = mem_heap_alloc(heap, 4);
@@ -1970,7 +1983,7 @@ ibuf_entry_build(
/* 2) Marker byte */
- field = dtuple_get_nth_field(tuple, 1);
+ field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_MARKER);
buf = mem_heap_alloc(heap, 1);
@@ -1982,7 +1995,7 @@ ibuf_entry_build(
/* 3) Page number */
- field = dtuple_get_nth_field(tuple, 2);
+ field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_PAGE);
buf = mem_heap_alloc(heap, 4);
@@ -2030,10 +2043,7 @@ ibuf_entry_build(
ulint fixed_len;
const dict_field_t* ifield;
- /* We add 4 below because we have the 4 extra fields at the
- start of an ibuf record */
-
- field = dtuple_get_nth_field(tuple, i + 4);
+ field = dtuple_get_nth_field(tuple, i + IBUF_REC_FIELD_USER);
entry_field = dtuple_get_nth_field(entry, i);
dfield_copy(field, entry_field);
@@ -2066,13 +2076,13 @@ ibuf_entry_build(
/* 4) Type info, part #2 */
- field = dtuple_get_nth_field(tuple, 3);
+ field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_METADATA);
dfield_set_data(field, type_info, ti - type_info);
/* Set all the types in the new tuple binary */
- dtuple_set_types_binary(tuple, n_fields + 4);
+ dtuple_set_types_binary(tuple, n_fields + IBUF_REC_FIELD_USER);
return(tuple);
}
@@ -2132,11 +2142,11 @@ ibuf_new_search_tuple_build(
ut_a(trx_sys_multiple_tablespace_format);
- tuple = dtuple_create(heap, 3);
+ tuple = dtuple_create(heap, IBUF_REC_FIELD_METADATA);
/* Store the space id in tuple */
- field = dtuple_get_nth_field(tuple, 0);
+ field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_SPACE);
buf = mem_heap_alloc(heap, 4);
@@ -2146,7 +2156,7 @@ ibuf_new_search_tuple_build(
/* Store the new format record marker byte */
- field = dtuple_get_nth_field(tuple, 1);
+ field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_MARKER);
buf = mem_heap_alloc(heap, 1);
@@ -2156,7 +2166,7 @@ ibuf_new_search_tuple_build(
/* Store the page number in tuple */
- field = dtuple_get_nth_field(tuple, 2);
+ field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_PAGE);
buf = mem_heap_alloc(heap, 4);
@@ -2164,7 +2174,7 @@ ibuf_new_search_tuple_build(
dfield_set_data(field, buf, 4);
- dtuple_set_types_binary(tuple, 3);
+ dtuple_set_types_binary(tuple, IBUF_REC_FIELD_METADATA);
return(tuple);
}
@@ -2833,8 +2843,10 @@ ibuf_get_volume_buffered_hash(
ulint fold;
ulint bitmask;
- len = ibuf_rec_get_size(rec, types, rec_get_n_fields_old(rec) - 4,
- FALSE, comp);
+ len = ibuf_rec_get_size(
+ rec, types,
+ rec_get_n_fields_old(rec) - IBUF_REC_FIELD_USER,
+ FALSE, comp);
fold = ut_fold_binary(data, len);
hash += (fold / (CHAR_BIT * sizeof *hash)) % size;
@@ -2886,8 +2898,8 @@ ibuf_get_volume_buffered_count_func(
ut_ad(ibuf_inside(mtr));
n_fields = rec_get_n_fields_old(rec);
- ut_ad(n_fields > 4);
- n_fields -= 4;
+ ut_ad(n_fields > IBUF_REC_FIELD_USER);
+ n_fields -= IBUF_REC_FIELD_USER;
rec_get_nth_field_offs_old(rec, 1, &len);
/* This function is only invoked when buffering new
@@ -2896,7 +2908,7 @@ ibuf_get_volume_buffered_count_func(
ut_a(len == 1);
ut_ad(trx_sys_multiple_tablespace_format);
- types = rec_get_nth_field_old(rec, 3, &len);
+ types = rec_get_nth_field_old(rec, IBUF_REC_FIELD_METADATA, &len);
switch (UNIV_EXPECT(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE,
IBUF_REC_INFO_SIZE)) {
@@ -3208,7 +3220,7 @@ ibuf_update_max_tablespace_id(void)
} else {
rec = btr_pcur_get_rec(&pcur);
- field = rec_get_nth_field_old(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_SPACE, &len);
ut_a(len == 4);
@@ -3230,10 +3242,12 @@ ibuf_update_max_tablespace_id(void)
ibuf_get_entry_counter_low_func(rec,space,page_no)
#endif
/****************************************************************//**
-Helper function for ibuf_set_entry_counter. Checks if rec is for (space,
-page_no), and if so, reads counter value from it and returns that + 1.
-Otherwise, returns 0.
-@return new counter value, or 0 */
+Helper function for ibuf_get_entry_counter_func. Checks if rec is for
+(space, page_no), and if so, reads counter value from it and returns
+that + 1.
+@retval ULINT_UNDEFINED if the record does not contain any counter
+@retval 0 if the record is not for (space, page_no)
+@retval 1 + previous counter value, otherwise */
static
ulint
ibuf_get_entry_counter_low_func(
@@ -3254,7 +3268,7 @@ ibuf_get_entry_counter_low_func(
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
ut_ad(rec_get_n_fields_old(rec) > 2);
- field = rec_get_nth_field_old(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_MARKER, &len);
if (UNIV_UNLIKELY(len != 1)) {
/* pre-4.1 format */
@@ -3267,7 +3281,7 @@ ibuf_get_entry_counter_low_func(
ut_a(trx_sys_multiple_tablespace_format);
/* Check the tablespace identifier. */
- field = rec_get_nth_field_old(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_SPACE, &len);
ut_a(len == 4);
if (mach_read_from_4(field) != space) {
@@ -3276,7 +3290,7 @@ ibuf_get_entry_counter_low_func(
}
/* Check the page offset. */
- field = rec_get_nth_field_old(rec, 2, &len);
+ field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_PAGE, &len);
ut_a(len == 4);
if (mach_read_from_4(field) != page_no) {
@@ -3285,7 +3299,7 @@ ibuf_get_entry_counter_low_func(
}
/* Check if the record contains a counter field. */
- field = rec_get_nth_field_old(rec, 3, &len);
+ field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_METADATA, &len);
switch (len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE) {
default:
@@ -3301,147 +3315,61 @@ ibuf_get_entry_counter_low_func(
}
}
+#ifdef UNIV_DEBUG
+# define ibuf_get_entry_counter(space,page_no,rec,mtr,exact_leaf) \
+ ibuf_get_entry_counter_func(space,page_no,rec,mtr,exact_leaf)
+#else /* UNIV_DEBUG */
+# define ibuf_get_entry_counter(space,page_no,rec,mtr,exact_leaf) \
+ ibuf_get_entry_counter_func(space,page_no,rec,exact_leaf)
+#endif
+
/****************************************************************//**
-Set the counter field in entry to the correct value based on the current
+Calculate the counter field for an entry based on the current
last record in ibuf for (space, page_no).
-@return FALSE if we should abort this insertion to ibuf */
+@return the counter field, or ULINT_UNDEFINED
+if we should abort this insertion to ibuf */
static
-ibool
-ibuf_set_entry_counter(
-/*===================*/
- dtuple_t* entry, /*!< in/out: entry to patch */
+ulint
+ibuf_get_entry_counter_func(
+/*========================*/
ulint space, /*!< in: space id of entry */
ulint page_no, /*!< in: page number of entry */
- btr_pcur_t* pcur, /*!< in: pcur positioned on the record
- found by btr_pcur_open(.., entry,
- PAGE_CUR_LE, ..., pcur, ...) */
- ibool is_optimistic, /*!< in: is this an optimistic insert */
- mtr_t* mtr) /*!< in: mtr */
+ const rec_t* rec, /*!< in: the record preceding the
+ insertion point */
+#ifdef UNIV_DEBUG
+ mtr_t* mtr, /*!< in: mini-transaction */
+#endif /* UNIV_DEBUG */
+ ibool only_leaf) /*!< in: TRUE if this is the only
+ leaf page that can contain entries
+ for (space,page_no), that is, there
+ was no exact match for (space,page_no)
+ in the node pointer */
{
- dfield_t* field;
- byte* data;
- ulint counter = 0;
-
- /* pcur points to either a user rec or to a page's infimum record. */
ut_ad(ibuf_inside(mtr));
- ut_ad(mtr_memo_contains(mtr, btr_pcur_get_block(pcur),
- MTR_MEMO_PAGE_X_FIX));
- ut_ad(page_validate(btr_pcur_get_page(pcur), ibuf->index));
-
- if (btr_pcur_is_on_user_rec(pcur)) {
-
- counter = ibuf_get_entry_counter_low(
- mtr, btr_pcur_get_rec(pcur), space, page_no);
-
- if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) {
- /* The record lacks a counter field.
- Such old records must be merged before
- new records can be buffered. */
-
- return(FALSE);
- }
- } else if (btr_pcur_is_before_first_in_tree(pcur, mtr)) {
- /* Ibuf tree is either completely empty, or the insert
- position is at the very first record of a non-empty tree. In
- either case we have no previous records for (space,
- page_no). */
-
- counter = 0;
- } else if (btr_pcur_is_before_first_on_page(pcur)) {
- btr_cur_t* cursor = btr_pcur_get_btr_cur(pcur);
-
- if (cursor->low_match < 3) {
- /* If low_match < 3, we know that the father node
- pointer did not contain the searched for (space,
- page_no), which means that the search ended on the
- right page regardless of the counter value, and
- since we're at the infimum record, there are no
- existing records. */
-
- counter = 0;
- } else {
- rec_t* rec;
- const page_t* page;
- buf_block_t* block;
- page_t* prev_page;
- ulint prev_page_no;
-
- ut_a(cursor->ibuf_cnt != ULINT_UNDEFINED);
-
- page = btr_pcur_get_page(pcur);
- prev_page_no = btr_page_get_prev(page, mtr);
-
- ut_a(prev_page_no != FIL_NULL);
-
- block = buf_page_get(
- IBUF_SPACE_ID, 0, prev_page_no,
- RW_X_LATCH, mtr);
+ ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX));
+ ut_ad(page_validate(page_align(rec), ibuf->index));
- buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
-
- prev_page = buf_block_get_frame(block);
-
- rec = page_rec_get_prev(
- page_get_supremum_rec(prev_page));
-
- ut_ad(page_rec_is_user_rec(rec));
-
- counter = ibuf_get_entry_counter_low(
- mtr, rec, space, page_no);
-
- if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) {
- /* The record lacks a counter field.
- Such old records must be merged before
- new records can be buffered. */
-
- return(FALSE);
- }
-
- if (counter < cursor->ibuf_cnt) {
- /* Search ended on the wrong page. */
-
- if (is_optimistic) {
- /* In an optimistic insert, we can
- shift the insert position to the left
- page, since it only needs an X-latch
- on the page itself, which the
- original search acquired for us. */
-
- btr_cur_position(
- ibuf->index, rec, block,
- btr_pcur_get_btr_cur(pcur));
- } else {
- /* We can't shift the insert
- position to the left page in a
- pessimistic insert since it would
- require an X-latch on the left
- page's left page, so we have to
- abort. */
-
- return(FALSE);
- }
- } else {
- /* The counter field in the father node is
- the same as we would insert; we don't know
- whether the insert should go to this page or
- the left page (the later fields can differ),
- so refuse the insert. */
-
- return(FALSE);
- }
- }
+ if (page_rec_is_supremum(rec)) {
+ /* This is just for safety. The record should be a
+ page infimum or a user record. */
+ ut_ad(0);
+ return(ULINT_UNDEFINED);
+ } else if (!page_rec_is_infimum(rec)) {
+ return(ibuf_get_entry_counter_low(mtr, rec, space, page_no));
+ } else if (only_leaf
+ || fil_page_get_prev(page_align(rec)) == FIL_NULL) {
+ /* The parent node pointer did not contain the
+ searched for (space, page_no), which means that the
+ search ended on the correct page regardless of the
+ counter value, and since we're at the infimum record,
+ there are no existing records. */
+ return(0);
} else {
- /* The cursor is not positioned at or before a user record. */
- return(FALSE);
+ /* We used to read the previous page here. It would
+ break the latching order, because the caller has
+ buffer-fixed an insert buffer bitmap page. */
+ return(ULINT_UNDEFINED);
}
-
- /* Patch counter value in already built entry. */
- field = dtuple_get_nth_field(entry, 3);
- data = dfield_get_data(field);
-
- mach_write_to_2(data + IBUF_REC_OFFSET_COUNTER, counter);
-
- return(TRUE);
}
/*********************************************************************//**
@@ -3650,16 +3578,27 @@ fail_exit:
}
}
- /* Patch correct counter value to the entry to insert. This can
- change the insert position, which can result in the need to abort in
- some cases. */
- if (!no_counter
- && !ibuf_set_entry_counter(ibuf_entry, space, page_no, &pcur,
- mode == BTR_MODIFY_PREV, &mtr)) {
+ if (!no_counter) {
+ /* Patch correct counter value to the entry to
+ insert. This can change the insert position, which can
+ result in the need to abort in some cases. */
+ ulint counter = ibuf_get_entry_counter(
+ space, page_no, btr_pcur_get_rec(&pcur), &mtr,
+ btr_pcur_get_btr_cur(&pcur)->low_match
+ < IBUF_REC_FIELD_METADATA);
+ dfield_t* field;
+
+ if (counter == ULINT_UNDEFINED) {
bitmap_fail:
- ibuf_mtr_commit(&bitmap_mtr);
+ ibuf_mtr_commit(&bitmap_mtr);
+ goto fail_exit;
+ }
- goto fail_exit;
+ field = dtuple_get_nth_field(
+ ibuf_entry, IBUF_REC_FIELD_METADATA);
+ mach_write_to_2(
+ (byte*) dfield_get_data(field)
+ + IBUF_REC_OFFSET_COUNTER, counter);
}
/* Set the bitmap bit denoting that the insert buffer contains
@@ -4003,7 +3942,7 @@ ibuf_insert_to_index_page(
ut_ad(ibuf_inside(mtr));
ut_ad(dtuple_check_typed(entry));
- ut_ad(!buf_block_align(page)->is_hashed);
+ ut_ad(!buf_block_align(page)->index);
if (UNIV_UNLIKELY(dict_table_is_comp(index->table)
!= (ibool)!!page_is_comp(page))) {
diff --git a/storage/xtradb/include/btr0cur.h b/storage/xtradb/include/btr0cur.h
index be918439f59..4f33aacc48e 100644
--- a/storage/xtradb/include/btr0cur.h
+++ b/storage/xtradb/include/btr0cur.h
@@ -743,24 +743,6 @@ struct btr_cur_struct {
NULL */
ulint fold; /*!< fold value used in the search if
flag is BTR_CUR_HASH */
- /*----- Delete buffering -------*/
- ulint ibuf_cnt; /* in searches done on insert buffer
- trees, this contains the "counter"
- value (the first two bytes of the
- fourth field) extracted from the
- page above the leaf page, from the
- father node pointer that pointed to
- the leaf page. in other words, it
- contains the minimum counter value
- for records to be inserted on the
- chosen leaf page. If for some reason
- this can't be read, or if the search
- ended on the leftmost leaf page in
- the tree (in which case the father
- node pointer had the 'minimum
- record' flag set), this is
- ULINT_UNDEFINED. */
- /*------------------------------*/
/* @} */
btr_path_t* path_arr; /*!< in estimating the number of
rows in range, we store in this array
diff --git a/storage/xtradb/include/btr0pcur.h b/storage/xtradb/include/btr0pcur.h
index f605c476844..140f94466db 100644
--- a/storage/xtradb/include/btr0pcur.h
+++ b/storage/xtradb/include/btr0pcur.h
@@ -263,14 +263,6 @@ btr_pcur_commit_specify_mtr(
/*========================*/
btr_pcur_t* pcur, /*!< in: persistent cursor */
mtr_t* mtr); /*!< in: mtr to commit */
-/**************************************************************//**
-Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES.
-@return TRUE if detached */
-UNIV_INLINE
-ibool
-btr_pcur_is_detached(
-/*=================*/
- btr_pcur_t* pcur); /*!< in: persistent cursor */
/*********************************************************//**
Moves the persistent cursor to the next record in the tree. If no records are
left, the cursor stays 'after last in tree'.
diff --git a/storage/xtradb/include/btr0pcur.ic b/storage/xtradb/include/btr0pcur.ic
index d86601e5a32..054ce753c7d 100644
--- a/storage/xtradb/include/btr0pcur.ic
+++ b/storage/xtradb/include/btr0pcur.ic
@@ -389,38 +389,6 @@ btr_pcur_commit_specify_mtr(
}
/**************************************************************//**
-Sets the pcur latch mode to BTR_NO_LATCHES. */
-UNIV_INLINE
-void
-btr_pcur_detach(
-/*============*/
- btr_pcur_t* pcur) /*!< in: persistent cursor */
-{
- ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
-
- pcur->latch_mode = BTR_NO_LATCHES;
-
- pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
-}
-
-/**************************************************************//**
-Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES.
-@return TRUE if detached */
-UNIV_INLINE
-ibool
-btr_pcur_is_detached(
-/*=================*/
- btr_pcur_t* pcur) /*!< in: persistent cursor */
-{
- if (pcur->latch_mode == BTR_NO_LATCHES) {
-
- return(TRUE);
- }
-
- return(FALSE);
-}
-
-/**************************************************************//**
Sets the old_rec_buf field to NULL. */
UNIV_INLINE
void
diff --git a/storage/xtradb/include/btr0sea.h b/storage/xtradb/include/btr0sea.h
index 9e82602934e..d9f2cf9c81b 100644
--- a/storage/xtradb/include/btr0sea.h
+++ b/storage/xtradb/include/btr0sea.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, 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
@@ -137,11 +137,10 @@ UNIV_INTERN
void
btr_search_drop_page_hash_index(
/*============================*/
- buf_block_t* block, /*!< in: block containing index page,
+ buf_block_t* block); /*!< in: block containing index page,
s- or x-latched, or an index page
for which we know that
block->buf_fix_count == 0 */
- dict_index_t* index_in);
/************************************************************************
Drops a page hash index based on index */
UNIV_INTERN
@@ -150,8 +149,8 @@ btr_search_drop_page_hash_index_on_index(
/*=====================================*/
dict_index_t* index); /* in: record descriptor */
/********************************************************************//**
-Drops a page hash index when a page is freed from a fseg to the file system.
-Drops possible hash index if the page happens to be in the buffer pool. */
+Drops a possible page hash index when a page is evicted from the buffer pool
+or freed in a file segment. */
UNIV_INTERN
void
btr_search_drop_page_hash_when_freed(
@@ -235,19 +234,6 @@ void
btr_search_s_unlock_all(void);
/*==========================*/
-
-/** Flag: has the search system been enabled?
-Protected by btr_search_latch and btr_search_enabled_mutex. */
-extern char btr_search_enabled;
-
-extern ulint btr_search_index_num;
-
-/** Flag: whether the search system has completed its disabling process,
-It is set to TRUE right after buf_pool_drop_hash_index() in
-btr_search_disable(), indicating hash index entries are cleaned up.
-Protected by btr_search_latch and btr_search_enabled_mutex. */
-extern ibool btr_search_fully_disabled;
-
/** The search info struct in an index */
struct btr_search_struct{
ulint ref_count; /*!< Number of blocks in this index tree
@@ -316,26 +302,6 @@ struct btr_search_sys_struct{
/** The adaptive hash index */
extern btr_search_sys_t* btr_search_sys;
-/** @brief The latch protecting the adaptive search system
-
-This latch protects the
-(1) hash index;
-(2) columns of a record to which we have a pointer in the hash index;
-
-but does NOT protect:
-
-(3) next record offset field in a record;
-(4) next or previous records on the same page.
-
-Bear in mind (3) and (4) when using the hash index.
-*/
-//extern rw_lock_t* btr_search_latch_temp;
-
-extern rw_lock_t** btr_search_latch_part;
-
-/** The latch protecting the adaptive search system */
-//#define btr_search_latch (*btr_search_latch_temp)
-
#ifdef UNIV_SEARCH_PERF_STAT
/** Number of successful adaptive hash index lookups */
extern ulint btr_search_n_succ;
diff --git a/storage/xtradb/include/btr0types.h b/storage/xtradb/include/btr0types.h
index 07c06fb18d7..6f515c3f58c 100644
--- a/storage/xtradb/include/btr0types.h
+++ b/storage/xtradb/include/btr0types.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, 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
@@ -30,6 +30,7 @@ Created 2/17/1996 Heikki Tuuri
#include "rem0types.h"
#include "page0types.h"
+#include "sync0rw.h"
/** Persistent cursor */
typedef struct btr_pcur_struct btr_pcur_t;
@@ -38,6 +39,32 @@ typedef struct btr_cur_struct btr_cur_t;
/** B-tree search information for the adaptive hash index */
typedef struct btr_search_struct btr_search_t;
+/** @brief The latch protecting the adaptive search system
+
+This latch protects the
+(1) hash index;
+(2) columns of a record to which we have a pointer in the hash index;
+
+but does NOT protect:
+
+(3) next record offset field in a record;
+(4) next or previous records on the same page.
+
+Bear in mind (3) and (4) when using the hash index.
+*/
+//extern rw_lock_t* btr_search_latch_temp;
+
+extern rw_lock_t** btr_search_latch_part;
+
+/** The latch protecting the adaptive search system */
+//#define btr_search_latch (*btr_search_latch_temp)
+
+/** Flag: has the search system been enabled?
+Protected by btr_search_latch. */
+extern char btr_search_enabled;
+
+extern ulint btr_search_index_num;
+
#ifdef UNIV_BLOB_DEBUG
# include "buf0types.h"
/** An index->blobs entry for keeping track of off-page column references */
diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h
index d85dac5cc91..0ea74fb9eb2 100644
--- a/storage/xtradb/include/buf0buf.h
+++ b/storage/xtradb/include/buf0buf.h
@@ -244,13 +244,11 @@ buf_pool_free(
ulint n_instances); /*!< in: numbere of instances to free */
/********************************************************************//**
-Drops the adaptive hash index. To prevent a livelock, this function
-is only to be called while holding btr_search_latch and while
-btr_search_enabled == FALSE. */
+Clears the adaptive hash index on all pages in the buffer pool. */
UNIV_INTERN
void
-buf_pool_drop_hash_index(void);
-/*==========================*/
+buf_pool_clear_hash_index(void);
+/*===========================*/
/********************************************************************//**
Relocate a buffer control block. Relocates the block on the LRU list
@@ -583,17 +581,6 @@ buf_page_peek_if_too_old(
/*=====================*/
const buf_page_t* bpage); /*!< in: block to make younger */
/********************************************************************//**
-Returns the current state of is_hashed of a page. FALSE if the page is
-not in the pool. NOTE that this operation does not fix the page in the
-pool if it is found there.
-@return TRUE if page hash index is built in search system */
-UNIV_INTERN
-ibool
-buf_page_peek_if_search_hashed(
-/*===========================*/
- ulint space, /*!< in: space id */
- ulint offset);/*!< in: page number */
-/********************************************************************//**
Gets the youngest modification log sequence number for a frame.
Returns zero if not file page or no modification occurred yet.
@return newest modification to page */
@@ -952,7 +939,27 @@ buf_block_set_io_fix(
/*=================*/
buf_block_t* block, /*!< in/out: control block */
enum buf_io_fix io_fix);/*!< in: io_fix state */
-
+/*********************************************************************//**
+Makes a block sticky. A sticky block implies that even after we release
+the buf_pool->mutex and the block->mutex:
+* it cannot be removed from the flush_list
+* the block descriptor cannot be relocated
+* it cannot be removed from the LRU list
+Note that:
+* the block can still change its position in the LRU list
+* the next and previous pointers can change. */
+UNIV_INLINE
+void
+buf_page_set_sticky(
+/*================*/
+ buf_page_t* bpage); /*!< in/out: control block */
+/*********************************************************************//**
+Removes stickiness of a block. */
+UNIV_INLINE
+void
+buf_page_unset_sticky(
+/*==================*/
+ buf_page_t* bpage); /*!< in/out: control block */
/********************************************************************//**
Determine if a buffer block can be relocated in memory. The block
can be dirty, but it must not be I/O-fixed or bufferfixed. */
@@ -1569,13 +1576,16 @@ struct buf_block_struct{
/* @} */
/** @name Hash search fields
- These 6 fields may only be modified when we have
+ These 5 fields may only be modified when we have
an x-latch on btr_search_latch AND
- we are holding an s-latch or x-latch on buf_block_struct::lock or
- we know that buf_block_struct::buf_fix_count == 0.
An exception to this is when we init or create a page
- in the buffer pool in buf0buf.c. */
+ in the buffer pool in buf0buf.c.
+
+ Another exception is that assigning block->index = NULL
+ is allowed whenever holding an x-latch on btr_search_latch. */
/* @{ */
@@ -1584,21 +1594,21 @@ struct buf_block_struct{
pointers in the adaptive hash index
pointing to this frame */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- volatile unsigned is_hashed:1; /*!< TRUE if hash index has
- already been built on this
- page; note that it does not
- guarantee that the index is
- complete, though: there may
- have been hash collisions,
- record deletions, etc. */
unsigned curr_n_fields:10;/*!< prefix length for hash indexing:
number of full fields */
unsigned curr_n_bytes:15;/*!< number of bytes in hash
indexing */
unsigned curr_left_side:1;/*!< TRUE or FALSE in hash indexing */
- dict_index_t* index; /*!< Index for which the adaptive
- hash index has been created. */
- volatile rw_lock_t* btr_search_latch;
+ dict_index_t* index; /*!< Index for which the
+ adaptive hash index has been
+ created, or NULL if the page
+ does not exist in the
+ index. Note that it does not
+ guarantee that the index is
+ complete, though: there may
+ have been hash collisions,
+ record deletions, etc. */
+ volatile rw_lock_t* btr_search_latch;
/* @} */
# ifdef UNIV_SYNC_DEBUG
/** @name Debug fields */
diff --git a/storage/xtradb/include/buf0buf.ic b/storage/xtradb/include/buf0buf.ic
index 98d575075ba..55d89b66375 100644
--- a/storage/xtradb/include/buf0buf.ic
+++ b/storage/xtradb/include/buf0buf.ic
@@ -444,6 +444,7 @@ buf_page_get_io_fix(
case BUF_IO_NONE:
case BUF_IO_READ:
case BUF_IO_WRITE:
+ case BUF_IO_PIN:
return(io_fix);
}
ut_error;
@@ -494,6 +495,49 @@ buf_block_set_io_fix(
buf_page_set_io_fix(&block->page, io_fix);
}
+/*********************************************************************//**
+Makes a block sticky. A sticky block implies that even after we release
+the buf_pool->mutex and the block->mutex:
+* it cannot be removed from the flush_list
+* the block descriptor cannot be relocated
+* it cannot be removed from the LRU list
+Note that:
+* the block can still change its position in the LRU list
+* the next and previous pointers can change. */
+UNIV_INLINE
+void
+buf_page_set_sticky(
+/*================*/
+ buf_page_t* bpage) /*!< in/out: control block */
+{
+#ifdef UNIV_DEBUG
+ buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
+#endif
+ ut_ad(mutex_own(buf_page_get_mutex(bpage)));
+ ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
+
+ bpage->io_fix = BUF_IO_PIN;
+}
+
+/*********************************************************************//**
+Removes stickiness of a block. */
+UNIV_INLINE
+void
+buf_page_unset_sticky(
+/*==================*/
+ buf_page_t* bpage) /*!< in/out: control block */
+{
+#ifdef UNIV_DEBUG
+ buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
+#endif
+ ut_ad(mutex_own(buf_page_get_mutex(bpage)));
+ ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_PIN);
+
+ bpage->io_fix = BUF_IO_NONE;
+}
+
/********************************************************************//**
Determine if a buffer block can be relocated in memory. The block
can be dirty, but it must not be I/O-fixed or bufferfixed. */
diff --git a/storage/xtradb/include/buf0types.h b/storage/xtradb/include/buf0types.h
index 156093aad01..d140936a886 100644
--- a/storage/xtradb/include/buf0types.h
+++ b/storage/xtradb/include/buf0types.h
@@ -57,7 +57,10 @@ enum buf_flush {
enum buf_io_fix {
BUF_IO_NONE = 0, /**< no pending I/O */
BUF_IO_READ, /**< read pending */
- BUF_IO_WRITE /**< write pending */
+ BUF_IO_WRITE, /**< write pending */
+ BUF_IO_PIN /**< disallow relocation of
+ block and its removal of from
+ the flush_list */
};
/** Parameters of binary buddy system for compressed pages (buf0buddy.h) */
diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h
index 840a9fbb13a..92fdca0db1b 100644
--- a/storage/xtradb/include/fil0fil.h
+++ b/storage/xtradb/include/fil0fil.h
@@ -34,6 +34,7 @@ Created 10/25/1995 Heikki Tuuri
#include "sync0rw.h"
#include "ibuf0types.h"
#endif /* !UNIV_HOTBACKUP */
+#include "trx0types.h"
/** When mysqld is run, the default directory "." is the mysqld datadir,
but in the MySQL Embedded Server Library and ibbackup it is not the default
@@ -329,18 +330,23 @@ Reads the flushed lsn and arch no fields from a data file at database
startup. */
UNIV_INTERN
void
-fil_read_flushed_lsn_and_arch_log_no(
-/*=================================*/
+fil_read_first_page(
+/*================*/
os_file_t data_file, /*!< in: open data file */
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
+ ulint* flags, /*!< out: tablespace flags */
#ifdef UNIV_LOG_ARCHIVE
- ulint* min_arch_log_no, /*!< in/out: */
- ulint* max_arch_log_no, /*!< in/out: */
+ ulint* min_arch_log_no, /*!< out: min of archived
+ log numbers in data files */
+ ulint* max_arch_log_no, /*!< out: max of archived
+ log numbers in data files */
#endif /* UNIV_LOG_ARCHIVE */
- ib_uint64_t* min_flushed_lsn, /*!< in/out: */
- ib_uint64_t* max_flushed_lsn); /*!< in/out: */
+ ib_uint64_t* min_flushed_lsn, /*!< out: min of flushed
+ lsn values in data files */
+ ib_uint64_t* max_flushed_lsn); /*!< out: max of flushed
+ lsn values in data files */
/*******************************************************************//**
Increments the count of pending insert buffer page merges, if space is not
being deleted.
@@ -474,8 +480,11 @@ fil_open_single_table_tablespace(
accessing the first page of the file */
ulint id, /*!< in: space id */
ulint flags, /*!< in: tablespace flags */
- const char* name); /*!< in: table name in the
+ const char* name, /*!< in: table name in the
databasename/tablename format */
+ trx_t* trx); /*!< in: transaction. This is only used
+ for IMPORT TABLESPACE, must be NULL
+ otherwise */
/********************************************************************//**
It is possible, though very improbable, that the lsn's in the tablespace to be
imported have risen above the current system lsn, if a lengthy purge, ibuf
diff --git a/storage/xtradb/include/fsp0fsp.h b/storage/xtradb/include/fsp0fsp.h
index 7abd3914eda..d5e235aa870 100644
--- a/storage/xtradb/include/fsp0fsp.h
+++ b/storage/xtradb/include/fsp0fsp.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, 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
*****************************************************************************/
@@ -34,6 +34,90 @@ Created 12/18/1995 Heikki Tuuri
#include "page0types.h"
#include "fsp0types.h"
+/* @defgroup fsp_flags InnoDB Tablespace Flag Constants @{ */
+
+/** Number of flag bits used to indicate the tablespace page size */
+#define FSP_FLAGS_WIDTH_PAGE_SSIZE 4
+/** Zero relative shift position of the PAGE_SSIZE field */
+#define FSP_FLAGS_POS_PAGE_SSIZE 6
+/** Bit mask of the PAGE_SSIZE field */
+#define FSP_FLAGS_MASK_PAGE_SSIZE \
+ ((~(~0 << FSP_FLAGS_WIDTH_PAGE_SSIZE)) \
+ << FSP_FLAGS_POS_PAGE_SSIZE)
+/** Return the value of the PAGE_SSIZE field */
+#define FSP_FLAGS_GET_PAGE_SSIZE(flags) \
+ ((flags & FSP_FLAGS_MASK_PAGE_SSIZE) \
+ >> FSP_FLAGS_POS_PAGE_SSIZE)
+
+/* @} */
+
+/* @defgroup Tablespace Header Constants (moved from fsp0fsp.c) @{ */
+
+/** Offset of the space header within a file page */
+#define FSP_HEADER_OFFSET FIL_PAGE_DATA
+
+/* The data structures in files are defined just as byte strings in C */
+typedef byte fsp_header_t;
+typedef byte xdes_t;
+
+/* SPACE HEADER
+ ============
+
+File space header data structure: this data structure is contained in the
+first page of a space. The space for this header is reserved in every extent
+descriptor page, but used only in the first. */
+
+/*-------------------------------------*/
+#define FSP_SPACE_ID 0 /* space id */
+#define FSP_NOT_USED 4 /* this field contained a value up to
+ which we know that the modifications
+ in the database have been flushed to
+ the file space; not used now */
+#define FSP_SIZE 8 /* Current size of the space in
+ pages */
+#define FSP_FREE_LIMIT 12 /* Minimum page number for which the
+ free list has not been initialized:
+ the pages >= this limit are, by
+ definition, free; note that in a
+ single-table tablespace where size
+ < 64 pages, this number is 64, i.e.,
+ we have initialized the space
+ about the first extent, but have not
+ physically allocted those pages to the
+ file */
+#define FSP_SPACE_FLAGS 16 /* fsp_space_t.flags, similar to
+ dict_table_t::flags */
+#define FSP_FRAG_N_USED 20 /* number of used pages in the
+ FSP_FREE_FRAG list */
+#define FSP_FREE 24 /* list of free extents */
+#define FSP_FREE_FRAG (24 + FLST_BASE_NODE_SIZE)
+ /* list of partially free extents not
+ belonging to any segment */
+#define FSP_FULL_FRAG (24 + 2 * FLST_BASE_NODE_SIZE)
+ /* list of full extents not belonging
+ to any segment */
+#define FSP_SEG_ID (24 + 3 * FLST_BASE_NODE_SIZE)
+ /* 8 bytes which give the first unused
+ segment id */
+#define FSP_SEG_INODES_FULL (32 + 3 * FLST_BASE_NODE_SIZE)
+ /* list of pages containing segment
+ headers, where all the segment inode
+ slots are reserved */
+#define FSP_SEG_INODES_FREE (32 + 4 * FLST_BASE_NODE_SIZE)
+ /* list of pages containing segment
+ headers, where not all the segment
+ header slots are reserved */
+/*-------------------------------------*/
+/* File space header size */
+#define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE)
+
+#define FSP_FREE_ADD 4 /* this many free extents are added
+ to the free list from above
+ FSP_FREE_LIMIT at a time */
+/* @} */
+
+/* @} */
+
/**********************************************************************//**
Initializes the file space system. */
UNIV_INTERN
@@ -352,6 +436,18 @@ fseg_print(
mtr_t* mtr); /*!< in: mtr */
#endif /* UNIV_BTR_PRINT */
+/********************************************************************//**
+Extract the page size from tablespace flags.
+This feature, storing the page_ssize into the tablespace flags, is added
+to InnoDB 5.6.4. This is here only to protect against a crash if a newer
+database is opened with this code branch.
+@return page size of the tablespace in bytes */
+UNIV_INLINE
+ulint
+fsp_flags_get_page_size(
+/*====================*/
+ ulint flags); /*!< in: tablespace flags */
+
#ifndef UNIV_NONINL
#include "fsp0fsp.ic"
#endif
diff --git a/storage/xtradb/include/fsp0fsp.ic b/storage/xtradb/include/fsp0fsp.ic
index 434c370b527..c92111a9d89 100644
--- a/storage/xtradb/include/fsp0fsp.ic
+++ b/storage/xtradb/include/fsp0fsp.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, 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
*****************************************************************************/
@@ -43,3 +43,31 @@ fsp_descr_page(
return(UNIV_UNLIKELY((page_no & (zip_size - 1)) == FSP_XDES_OFFSET));
}
+/********************************************************************//**
+Extract the page size from tablespace flags.
+This feature, storing the page_ssize into the tablespace flags, is added
+to InnoDB 5.6.4. This is here only to protect against a crash if a newer
+database is opened with this code branch.
+@return page size of the tablespace in bytes */
+UNIV_INLINE
+ulint
+fsp_flags_get_page_size(
+/*====================*/
+ ulint flags) /*!< in: tablespace flags */
+{
+ ulint page_size = 0;
+ ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
+
+ /* Convert from a 'log2 minus 9' to a page size in bytes. */
+ if (UNIV_UNLIKELY(ssize)) {
+ page_size = (512 << ssize);
+
+ ut_ad(page_size <= UNIV_PAGE_SIZE);
+ } else {
+ /* If the page size was not stored, then it is the
+ original 16k. */
+ page_size = UNIV_PAGE_SIZE;
+ }
+
+ return(page_size);
+}
diff --git a/storage/xtradb/include/ha0ha.h b/storage/xtradb/include/ha0ha.h
index 3299000bf3c..8bba564d153 100644
--- a/storage/xtradb/include/ha0ha.h
+++ b/storage/xtradb/include/ha0ha.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, 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
@@ -31,13 +31,14 @@ Created 8/18/1994 Heikki Tuuri
#include "hash0hash.h"
#include "page0types.h"
#include "buf0types.h"
+#include "rem0types.h"
/*************************************************************//**
Looks for an element in a hash table.
@return pointer to the data of the first hash table node in chain
having the fold number, NULL if not found */
UNIV_INLINE
-void*
+const rec_t*
ha_search_and_get_data(
/*===================*/
hash_table_t* table, /*!< in: hash table */
@@ -51,11 +52,11 @@ ha_search_and_update_if_found_func(
/*===============================*/
hash_table_t* table, /*!< in/out: hash table */
ulint fold, /*!< in: folded value of the searched data */
- void* data, /*!< in: pointer to the data */
+ const rec_t* data, /*!< in: pointer to the data */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* new_block,/*!< in: block containing new_data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* new_data);/*!< in: new pointer to the data */
+ const rec_t* new_data);/*!< in: new pointer to the data */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
/** Looks for an element when we know the pointer to the data and
@@ -114,14 +115,6 @@ chosen to be a slightly bigger prime number.
#endif /* UNIV_SYNC_DEBUG */
/*************************************************************//**
-Empties a hash table and frees the memory heaps. */
-UNIV_INTERN
-void
-ha_clear(
-/*=====*/
- hash_table_t* table); /*!< in, own: hash table */
-
-/*************************************************************//**
Inserts an entry into a hash table. If an entry with the same fold number
is found, its node is updated to point to the new data, and no new node
is inserted.
@@ -138,7 +131,7 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block, /*!< in: buffer block containing the data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* data); /*!< in: data, must not be NULL */
+ const rec_t* data); /*!< in: data, must not be NULL */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
/**
@@ -174,7 +167,7 @@ ha_search_and_delete_if_found(
/*==========================*/
hash_table_t* table, /*!< in: hash table */
ulint fold, /*!< in: folded value of the searched data */
- void* data); /*!< in: pointer to the data */
+ const rec_t* data); /*!< in: pointer to the data */
#ifndef UNIV_HOTBACKUP
/*****************************************************************//**
Removes from the chain determined by fold all nodes whose data pointer
@@ -217,7 +210,7 @@ struct ha_node_struct {
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block; /*!< buffer block containing the data, or NULL */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* data; /*!< pointer to the data */
+ const rec_t* data; /*!< pointer to the data */
ulint fold; /*!< fold value for the data */
};
diff --git a/storage/xtradb/include/ha0ha.ic b/storage/xtradb/include/ha0ha.ic
index 734403c4cd9..f224776c134 100644
--- a/storage/xtradb/include/ha0ha.ic
+++ b/storage/xtradb/include/ha0ha.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, 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
@@ -25,6 +25,7 @@ Created 8/18/1994 Heikki Tuuri
#include "ut0rnd.h"
#include "mem0mem.h"
+#include "btr0types.h"
/***********************************************************//**
Deletes a hash node. */
@@ -39,10 +40,10 @@ ha_delete_hash_node(
Gets a hash node data.
@return pointer to the data */
UNIV_INLINE
-void*
+const rec_t*
ha_node_get_data(
/*=============*/
- ha_node_t* node) /*!< in: hash chain node */
+ const ha_node_t* node) /*!< in: hash chain node */
{
return(node->data);
}
@@ -57,7 +58,7 @@ ha_node_set_data_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block, /*!< in: buffer block containing the data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* data) /*!< in: pointer to the data */
+ const rec_t* data) /*!< in: pointer to the data */
{
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
node->block = block;
@@ -107,39 +108,10 @@ ha_chain_get_first(
/*************************************************************//**
Looks for an element in a hash table.
-@return pointer to the first hash table node in chain having the fold
-number, NULL if not found */
-UNIV_INLINE
-ha_node_t*
-ha_search(
-/*======*/
- hash_table_t* table, /*!< in: hash table */
- ulint fold) /*!< in: folded value of the searched data */
-{
- ha_node_t* node;
-
- ASSERT_HASH_MUTEX_OWN(table, fold);
-
- node = ha_chain_get_first(table, fold);
-
- while (node) {
- if (node->fold == fold) {
-
- return(node);
- }
-
- node = ha_chain_get_next(node);
- }
-
- return(NULL);
-}
-
-/*************************************************************//**
-Looks for an element in a hash table.
@return pointer to the data of the first hash table node in chain
having the fold number, NULL if not found */
UNIV_INLINE
-void*
+const rec_t*
ha_search_and_get_data(
/*===================*/
hash_table_t* table, /*!< in: hash table */
@@ -148,6 +120,10 @@ ha_search_and_get_data(
ha_node_t* node;
ASSERT_HASH_MUTEX_OWN(table, fold);
+#ifdef UNIV_SYNC_DEBUG
+// ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
+ ut_ad(btr_search_enabled);
node = ha_chain_get_first(table, fold);
@@ -172,12 +148,14 @@ ha_search_with_data(
/*================*/
hash_table_t* table, /*!< in: hash table */
ulint fold, /*!< in: folded value of the searched data */
- void* data) /*!< in: pointer to the data */
+ const rec_t* data) /*!< in: pointer to the data */
{
ha_node_t* node;
ASSERT_HASH_MUTEX_OWN(table, fold);
+ ut_ad(btr_search_enabled);
+
node = ha_chain_get_first(table, fold);
while (node) {
@@ -202,11 +180,15 @@ ha_search_and_delete_if_found(
/*==========================*/
hash_table_t* table, /*!< in: hash table */
ulint fold, /*!< in: folded value of the searched data */
- void* data) /*!< in: pointer to the data */
+ const rec_t* data) /*!< in: pointer to the data */
{
ha_node_t* node;
ASSERT_HASH_MUTEX_OWN(table, fold);
+#ifdef UNIV_SYNC_DEBUG
+// ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+ ut_ad(btr_search_enabled);
node = ha_search_with_data(table, fold, data);
diff --git a/storage/xtradb/include/page0page.h b/storage/xtradb/include/page0page.h
index c1c659e2b70..1b9f9c84225 100644
--- a/storage/xtradb/include/page0page.h
+++ b/storage/xtradb/include/page0page.h
@@ -893,6 +893,7 @@ page_parse_create(
ulint comp, /*!< in: nonzero=compact page format */
buf_block_t* block, /*!< in: block or NULL */
mtr_t* mtr); /*!< in: mtr or NULL */
+#ifndef UNIV_HOTBACKUP
/************************************************************//**
Prints record contents including the data relevant only in
the index page context. */
@@ -902,6 +903,7 @@ page_rec_print(
/*===========*/
const rec_t* rec, /*!< in: physical record */
const ulint* offsets);/*!< in: record descriptor */
+# ifdef UNIV_BTR_PRINT
/***************************************************************//**
This is used to print the contents of the directory for
debugging purposes. */
@@ -941,6 +943,8 @@ page_print(
in directory */
ulint rn); /*!< in: print rn first and last records
in directory */
+# endif /* UNIV_BTR_PRINT */
+#endif /* !UNIV_HOTBACKUP */
/***************************************************************//**
The following is used to validate a record on a page. This function
differs from rec_validate as it can also check the n_owned field and
diff --git a/storage/xtradb/include/row0upd.ic b/storage/xtradb/include/row0upd.ic
index 11db82f64da..10646241125 100644
--- a/storage/xtradb/include/row0upd.ic
+++ b/storage/xtradb/include/row0upd.ic
@@ -28,7 +28,6 @@ Created 12/27/1996 Heikki Tuuri
# include "trx0trx.h"
# include "trx0undo.h"
# include "row0row.h"
-# include "btr0sea.h"
#endif /* !UNIV_HOTBACKUP */
#include "page0zip.h"
diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h
index 6f985eacdf3..65b341c0f13 100644
--- a/storage/xtradb/include/srv0srv.h
+++ b/storage/xtradb/include/srv0srv.h
@@ -288,6 +288,9 @@ extern ibool srv_print_lock_waits;
extern ibool srv_print_buf_io;
extern ibool srv_print_log_io;
extern ibool srv_print_latch_waits;
+
+extern ulint srv_flush_checkpoint_debug;
+
#else /* UNIV_DEBUG */
# define srv_print_thread_releases FALSE
# define srv_print_lock_waits FALSE
diff --git a/storage/xtradb/include/sync0rw.h b/storage/xtradb/include/sync0rw.h
index 6420bc5d3bf..971099c91f5 100644
--- a/storage/xtradb/include/sync0rw.h
+++ b/storage/xtradb/include/sync0rw.h
@@ -543,7 +543,7 @@ mutex. */
UNIV_INTERN
void
rw_lock_debug_mutex_enter(void);
-/*==========================*/
+/*===========================*/
/******************************************************************//**
Releases the debug mutex. */
UNIV_INTERN
@@ -634,7 +634,8 @@ struct rw_lock_struct {
};
#ifdef UNIV_SYNC_DEBUG
-/** The structure for storing debug info of an rw-lock */
+/** The structure for storing debug info of an rw-lock. All access to this
+structure must be protected by rw_lock_debug_mutex_enter(). */
struct rw_lock_debug_struct {
os_thread_id_t thread_id; /*!< The thread id of the thread which
diff --git a/storage/xtradb/include/sync0rw.ic b/storage/xtradb/include/sync0rw.ic
index a6dfa603c59..3eaa6172631 100644
--- a/storage/xtradb/include/sync0rw.ic
+++ b/storage/xtradb/include/sync0rw.ic
@@ -406,6 +406,7 @@ rw_lock_s_lock_func(
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
+ ut_ad(!rw_lock_own(lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
/* TODO: study performance of UNIV_LIKELY branch prediction hints. */
diff --git a/storage/xtradb/include/sync0sync.h b/storage/xtradb/include/sync0sync.h
index 6440a670f14..f9434ed54be 100644
--- a/storage/xtradb/include/sync0sync.h
+++ b/storage/xtradb/include/sync0sync.h
@@ -674,7 +674,6 @@ or row lock! */
#define SYNC_LOG_FLUSH_ORDER 156
#define SYNC_RECV 168
#define SYNC_WORK_QUEUE 162
-#define SYNC_SEARCH_SYS_CONF 161 /* for assigning btr_search_enabled */
#define SYNC_SEARCH_SYS 160 /* NOTE that if we have a memory
heap that can be extended to the
buffer pool, its logical level is
diff --git a/storage/xtradb/include/trx0trx.h b/storage/xtradb/include/trx0trx.h
index a03f7aceafa..eded5c303fa 100644
--- a/storage/xtradb/include/trx0trx.h
+++ b/storage/xtradb/include/trx0trx.h
@@ -494,6 +494,7 @@ struct trx_struct{
this is set to 1 then registered should
also be set to 1. This is used in the
XA code */
+ unsigned called_commit_ordered:1;/* 1 if innobase_commit_ordered has run. */
/*------------------------------*/
ulint isolation_level;/* TRX_ISO_REPEATABLE_READ, ... */
ulint check_foreigns; /* normally TRUE, but if the user
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index 0287ea40509..1a48d68d0d7 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -54,7 +54,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_BUGFIX 8
#ifndef PERCONA_INNODB_VERSION
-#define PERCONA_INNODB_VERSION 20.1
+#define PERCONA_INNODB_VERSION 24.1
#endif
/* The following is the InnoDB version as shown in
diff --git a/storage/xtradb/log/log0log.c b/storage/xtradb/log/log0log.c
index d9676707cfd..af0c801a4ec 100644
--- a/storage/xtradb/log/log0log.c
+++ b/storage/xtradb/log/log0log.c
@@ -1693,10 +1693,13 @@ log_preflush_pool_modified_pages(
recv_apply_hashed_log_recs(TRUE);
}
+ retry:
n_pages = buf_flush_list(ULINT_MAX, new_oldest);
- if (sync) {
- buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
+ if (sync && n_pages != 0) {
+ //buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
+ os_thread_sleep(100000);
+ goto retry;
}
if (n_pages == ULINT_UNDEFINED) {
@@ -2020,6 +2023,13 @@ log_checkpoint(
{
ib_uint64_t oldest_lsn;
+#ifdef UNIV_DEBUG
+ if (srv_flush_checkpoint_debug == 1) {
+
+ return TRUE;
+ }
+#endif
+
if (recv_recovery_is_on()) {
recv_apply_hashed_log_recs(TRUE);
}
@@ -2124,7 +2134,11 @@ log_make_checkpoint_at(
physical write will always be made to
log files */
{
- /* Preflush pages synchronously */
+#ifdef UNIV_DEBUG
+ if (srv_flush_checkpoint_debug == 1)
+ return;
+#endif
+/* Preflush pages synchronously */
while (!log_preflush_pool_modified_pages(lsn, TRUE));
@@ -2216,7 +2230,13 @@ log_checkpoint_margin(void)
ibool checkpoint_sync;
ibool do_checkpoint;
ibool success;
-loop:
+
+#ifdef UNIV_DEBUG
+ if (srv_flush_checkpoint_debug == 1)
+ return;
+#endif
+
+ loop:
sync = FALSE;
checkpoint_sync = FALSE;
do_checkpoint = FALSE;
@@ -2239,13 +2259,15 @@ loop:
/* A flush is urgent: we have to do a synchronous preflush */
sync = TRUE;
- advance = 2 * (age - log->max_modified_age_sync);
+ advance = age - log->max_modified_age_sync;
} else if (age > log_max_modified_age_async()) {
/* A flush is not urgent: we do an asynchronous preflush */
advance = age - log_max_modified_age_async();
+ log->check_flush_or_checkpoint = FALSE;
} else {
advance = 0;
+ log->check_flush_or_checkpoint = FALSE;
}
checkpoint_age = log->lsn - log->last_checkpoint_lsn;
@@ -2262,9 +2284,9 @@ loop:
do_checkpoint = TRUE;
- log->check_flush_or_checkpoint = FALSE;
+ //log->check_flush_or_checkpoint = FALSE;
} else {
- log->check_flush_or_checkpoint = FALSE;
+ //log->check_flush_or_checkpoint = FALSE;
}
mutex_exit(&(log->mutex));
@@ -2272,6 +2294,7 @@ loop:
if (advance) {
ib_uint64_t new_oldest = oldest_lsn + advance;
+retry:
success = log_preflush_pool_modified_pages(new_oldest, sync);
/* If the flush succeeded, this thread has done its part
@@ -2286,7 +2309,7 @@ loop:
log->check_flush_or_checkpoint = TRUE;
mutex_exit(&(log->mutex));
- goto loop;
+ goto retry;
}
}
@@ -3164,7 +3187,11 @@ void
log_check_margins(void)
/*===================*/
{
-loop:
+#ifdef UNIV_DEBUG
+ if (srv_flush_checkpoint_debug == 1)
+ return;
+#endif
+ loop:
log_flush_margin();
log_checkpoint_margin();
diff --git a/storage/xtradb/page/page0page.c b/storage/xtradb/page/page0page.c
index 17f6c6bbc36..4858929082a 100644
--- a/storage/xtradb/page/page0page.c
+++ b/storage/xtradb/page/page0page.c
@@ -215,12 +215,6 @@ page_set_max_trx_id(
{
page_t* page = buf_block_get_frame(block);
#ifndef UNIV_HOTBACKUP
- const ibool is_hashed = block->is_hashed;
-
- if (is_hashed) {
- rw_lock_x_lock(btr_search_get_latch(block->index->id));
- }
-
ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
#endif /* !UNIV_HOTBACKUP */
@@ -241,12 +235,6 @@ page_set_max_trx_id(
} else {
mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id);
}
-
-#ifndef UNIV_HOTBACKUP
- if (is_hashed) {
- rw_lock_x_unlock(btr_search_get_latch(block->index->id));
- }
-#endif /* !UNIV_HOTBACKUP */
}
/************************************************************//**
@@ -1603,13 +1591,14 @@ page_rec_print(
" n_owned: %lu; heap_no: %lu; next rec: %lu\n",
(ulong) rec_get_n_owned_old(rec),
(ulong) rec_get_heap_no_old(rec),
- (ulong) rec_get_next_offs(rec, TRUE));
+ (ulong) rec_get_next_offs(rec, FALSE));
}
page_rec_check(rec);
rec_validate(rec, offsets);
}
+# ifdef UNIV_BTR_PRINT
/***************************************************************//**
This is used to print the contents of the directory for
debugging purposes. */
@@ -1770,6 +1759,7 @@ page_print(
page_dir_print(page, dn);
page_print_list(block, index, rn);
}
+# endif /* UNIV_BTR_PRINT */
#endif /* !UNIV_HOTBACKUP */
/***************************************************************//**
diff --git a/storage/xtradb/page/page0zip.c b/storage/xtradb/page/page0zip.c
index fc9f30ed94e..d4b0dd8339d 100644
--- a/storage/xtradb/page/page0zip.c
+++ b/storage/xtradb/page/page0zip.c
@@ -4456,7 +4456,7 @@ page_zip_reorganize(
#ifndef UNIV_HOTBACKUP
temp_block = buf_block_alloc(buf_pool);
- btr_search_drop_page_hash_index(block, index);
+ btr_search_drop_page_hash_index(block);
block->check_index_page_at_flush = TRUE;
#else /* !UNIV_HOTBACKUP */
ut_ad(block == back_block1);
diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c
index 9bda27e4b1f..adc75bd5760 100644
--- a/storage/xtradb/row/row0ins.c
+++ b/storage/xtradb/row/row0ins.c
@@ -437,11 +437,9 @@ row_ins_cascade_calc_update_vec(
dict_table_t* table = foreign->foreign_table;
dict_index_t* index = foreign->foreign_index;
upd_t* update;
- upd_field_t* ufield;
dict_table_t* parent_table;
dict_index_t* parent_index;
upd_t* parent_update;
- upd_field_t* parent_ufield;
ulint n_fields_updated;
ulint parent_field_no;
ulint i;
@@ -477,13 +475,15 @@ row_ins_cascade_calc_update_vec(
dict_index_get_nth_col_no(parent_index, i));
for (j = 0; j < parent_update->n_fields; j++) {
- parent_ufield = parent_update->fields + j;
+ const upd_field_t* parent_ufield
+ = &parent_update->fields[j];
if (parent_ufield->field_no == parent_field_no) {
ulint min_size;
const dict_col_t* col;
ulint ufield_len;
+ upd_field_t* ufield;
col = dict_index_get_nth_col(index, i);
@@ -985,10 +985,9 @@ row_ins_foreign_check_on_constraint(
goto nonstandard_exit_func;
}
- if ((node->is_delete
- && (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL))
- || (!node->is_delete
- && (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL))) {
+ if (node->is_delete
+ ? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
+ : (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)) {
/* Build the appropriate update vector which sets
foreign->n_fields first fields in rec to SQL NULL */
@@ -997,6 +996,8 @@ row_ins_foreign_check_on_constraint(
update->info_bits = 0;
update->n_fields = foreign->n_fields;
+ UNIV_MEM_INVALID(update->fields,
+ update->n_fields * sizeof *update->fields);
for (i = 0; i < foreign->n_fields; i++) {
upd_field_t* ufield = &update->fields[i];
@@ -1665,7 +1666,7 @@ row_ins_scan_sec_index_for_duplicate(
ulint n_fields_cmp;
btr_pcur_t pcur;
ulint err = DB_SUCCESS;
- unsigned allow_duplicates;
+ ulint allow_duplicates;
mtr_t mtr;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
@@ -1696,7 +1697,7 @@ row_ins_scan_sec_index_for_duplicate(
btr_pcur_open(index, entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr);
- allow_duplicates = thr_get_trx(thr)->duplicates & TRX_DUP_IGNORE;
+ allow_duplicates = thr_get_trx(thr)->duplicates;
/* Scan index records and check if there is a duplicate */
@@ -1830,7 +1831,7 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate
errors as in original execution */
- if (trx->duplicates & TRX_DUP_IGNORE) {
+ if (trx->duplicates) {
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
@@ -1874,7 +1875,7 @@ row_ins_duplicate_error_in_clust(
offsets = rec_get_offsets(rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap);
- if (trx->duplicates & TRX_DUP_IGNORE) {
+ if (trx->duplicates) {
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
diff --git a/storage/xtradb/row/row0mysql.c b/storage/xtradb/row/row0mysql.c
index ac424ded6cb..63252ed01b3 100644
--- a/storage/xtradb/row/row0mysql.c
+++ b/storage/xtradb/row/row0mysql.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 2000, 2011, 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
@@ -291,21 +291,21 @@ row_mysql_pad_col(
/* space=0x0020 */
pad_end = pad + len;
ut_a(!(len % 2));
- do {
+ while (pad < pad_end) {
*pad++ = 0x00;
*pad++ = 0x20;
- } while (pad < pad_end);
+ };
break;
case 4:
/* space=0x00000020 */
pad_end = pad + len;
ut_a(!(len % 4));
- do {
+ while (pad < pad_end) {
*pad++ = 0x00;
*pad++ = 0x00;
*pad++ = 0x00;
*pad++ = 0x20;
- } while (pad < pad_end);
+ }
break;
}
}
@@ -2736,7 +2736,7 @@ row_import_tablespace_for_mysql(
success = fil_open_single_table_tablespace(
TRUE, table->space,
table->flags == DICT_TF_COMPACT ? 0 : table->flags,
- table->name);
+ table->name, trx);
if (success) {
table->ibd_file_missing = FALSE;
table->tablespace_discarded = FALSE;
@@ -4119,6 +4119,7 @@ end:
trx->error_state = DB_SUCCESS;
trx_general_rollback_for_mysql(trx, NULL);
trx->error_state = DB_SUCCESS;
+ err = DB_ERROR;
goto funct_exit;
}
diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c
index 0c07d75b39a..2a4fc183c92 100644
--- a/storage/xtradb/srv/srv0srv.c
+++ b/storage/xtradb/srv/srv0srv.c
@@ -446,7 +446,7 @@ UNIV_INTERN ulong srv_ibuf_accel_rate = 100;
#define PCT_IBUF_IO(pct) ((ulint) (srv_io_capacity * srv_ibuf_accel_rate * ((double) pct / 10000.0)))
UNIV_INTERN ulint srv_checkpoint_age_target = 0;
-UNIV_INTERN ulint srv_flush_neighbor_pages = 1; /* 0:disable 1:enable */
+UNIV_INTERN ulint srv_flush_neighbor_pages = 1; /* 0:disable 1:area 2:contiguous */
UNIV_INTERN ulint srv_deprecated_enable_unsafe_group_commit = 0;
UNIV_INTERN ulong srv_read_ahead = 3; /* 1: random 2: linear 3: Both */
@@ -471,6 +471,9 @@ UNIV_INTERN ibool srv_print_lock_waits = FALSE;
UNIV_INTERN ibool srv_print_buf_io = FALSE;
UNIV_INTERN ibool srv_print_log_io = FALSE;
UNIV_INTERN ibool srv_print_latch_waits = FALSE;
+
+UNIV_INTERN ulong srv_flush_checkpoint_debug = 0;
+
#endif /* UNIV_DEBUG */
UNIV_INTERN ulint srv_n_rows_inserted = 0;
@@ -1253,7 +1256,7 @@ retry:
static void
srv_conc_exit_innodb_timer_based(trx_t* trx)
{
- (void) os_atomic_increment_lint(&srv_conc_n_threads, -1);
+ (void) os_atomic_increment_lint(&srv_conc_n_threads, -1);
trx->declared_to_be_inside_innodb = FALSE;
trx->n_tickets_to_enter_innodb = 0;
return;
@@ -1475,7 +1478,7 @@ srv_conc_force_enter_innodb(
ut_ad(srv_conc_n_threads >= 0);
#ifdef HAVE_ATOMIC_BUILTINS
if (srv_thread_concurrency_timer_based) {
- (void) os_atomic_increment_lint(&srv_conc_n_threads, 1);
+ (void) os_atomic_increment_lint(&srv_conc_n_threads, 1);
trx->declared_to_be_inside_innodb = TRUE;
trx->n_tickets_to_enter_innodb = 1;
return;
@@ -3625,11 +3628,18 @@ retry_flush_batch:
PCT_IO(10), IB_ULONGLONG_MAX);
}
- srv_main_thread_op_info = "making checkpoint";
+#ifdef UNIV_DEBUG
+ if (srv_flush_checkpoint_debug != 1) {
+#endif
- /* Make a new checkpoint about once in 10 seconds */
+ srv_main_thread_op_info = "making checkpoint";
- log_checkpoint(TRUE, FALSE, TRUE);
+ /* Make a new checkpoint about once in 10 seconds */
+
+ log_checkpoint(TRUE, FALSE, TRUE);
+#ifdef UNIV_DEBUG
+ }
+#endif
srv_main_thread_op_info = "reserving kernel mutex";
@@ -3708,6 +3718,10 @@ background_loop:
}
mutex_exit(&kernel_mutex);
+#ifdef UNIV_DEBUG
+ if (srv_flush_checkpoint_debug == 1)
+ goto skip_flush;
+#endif
flush_loop:
srv_main_thread_op_info = "flushing buffer pool pages";
srv_main_flush_loops++;
@@ -3748,6 +3762,9 @@ flush_loop:
goto flush_loop;
}
+#ifdef UNIV_DEBUG
+skip_flush:
+#endif
srv_main_thread_op_info = "reserving kernel mutex";
mutex_enter(&kernel_mutex);
diff --git a/storage/xtradb/srv/srv0start.c b/storage/xtradb/srv/srv0start.c
index 4083eb75b83..99916610c21 100644
--- a/storage/xtradb/srv/srv0start.c
+++ b/storage/xtradb/srv/srv0start.c
@@ -735,6 +735,7 @@ open_or_create_data_files(
ibool one_created = FALSE;
ulint size;
ulint size_high;
+ ulint flags;
ulint rounded_size_pages;
char name[10000];
@@ -917,12 +918,31 @@ open_or_create_data_files(
return(DB_ERROR);
}
skip_size_check:
- fil_read_flushed_lsn_and_arch_log_no(
- files[i], one_opened,
+ fil_read_first_page(
+ files[i], one_opened, &flags,
#ifdef UNIV_LOG_ARCHIVE
min_arch_log_no, max_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */
min_flushed_lsn, max_flushed_lsn);
+
+ if (UNIV_PAGE_SIZE
+ != fsp_flags_get_page_size(flags)) {
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Error: data file %s"
+ " uses page size %lu,\n",
+ name,
+ fsp_flags_get_page_size(flags));
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: but the only supported"
+ " page size in this release is=%lu\n",
+ (ulong) UNIV_PAGE_SIZE);
+
+ return(DB_ERROR);
+ }
+
one_opened = TRUE;
} else {
/* We created the data file and now write it full of
@@ -1060,8 +1080,8 @@ skip_size_check:
(ulong) TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9);
}
- fil_read_flushed_lsn_and_arch_log_no(
- files[i], one_opened,
+ fil_read_first_page(
+ files[i], one_opened, &flags,
#ifdef UNIV_LOG_ARCHIVE
min_arch_log_no, max_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */
diff --git a/storage/xtradb/sync/sync0rw.c b/storage/xtradb/sync/sync0rw.c
index e561ae319a5..8884812d84d 100644
--- a/storage/xtradb/sync/sync0rw.c
+++ b/storage/xtradb/sync/sync0rw.c
@@ -623,6 +623,9 @@ rw_lock_x_lock_func(
ibool spinning = FALSE;
ut_ad(rw_lock_validate(lock));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
i = 0;
@@ -710,7 +713,7 @@ mutex. */
UNIV_INTERN
void
rw_lock_debug_mutex_enter(void)
-/*==========================*/
+/*===========================*/
{
loop:
if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
@@ -937,11 +940,13 @@ rw_lock_list_print_info(
putc('\n', file);
}
+ rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
rw_lock_debug_print(file, info);
info = UT_LIST_GET_NEXT(list, info);
}
+ rw_lock_debug_mutex_exit();
}
#ifndef INNODB_RW_LOCKS_USE_ATOMICS
mutex_exit(&(lock->mutex));
@@ -985,11 +990,13 @@ rw_lock_print(
putc('\n', stderr);
}
+ rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
rw_lock_debug_print(stderr, info);
info = UT_LIST_GET_NEXT(list, info);
}
+ rw_lock_debug_mutex_exit();
}
}
diff --git a/storage/xtradb/sync/sync0sync.c b/storage/xtradb/sync/sync0sync.c
index b38e2183b0f..d2c4617d65c 100644
--- a/storage/xtradb/sync/sync0sync.c
+++ b/storage/xtradb/sync/sync0sync.c
@@ -1222,7 +1222,6 @@ sync_thread_add_level(
case SYNC_OUTER_ANY_LATCH:
case SYNC_FILE_FORMAT_TAG:
case SYNC_DOUBLEWRITE:
- case SYNC_SEARCH_SYS_CONF:
case SYNC_TRX_LOCK_HEAP:
case SYNC_KERNEL:
case SYNC_IBUF_BITMAP_MUTEX: