Commit 6767c9a3 authored by Inaam Rana's avatar Inaam Rana

Revert original fix for Bug 12612184 and the follow up fix for

Bug 12704861.

Bug 12704861 fix was revno: 3504.1.1 (rb://693)
Bug 12612184 fix was revno: 3445.1.10 (rb://678)
parent b4514d6d
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -906,29 +906,28 @@ btr_page_alloc_for_ibuf( ...@@ -906,29 +906,28 @@ btr_page_alloc_for_ibuf(
/**************************************************************//** /**************************************************************//**
Allocates a new file page to be used in an index tree. NOTE: we assume Allocates a new file page to be used in an index tree. NOTE: we assume
that the caller has made the reservation for free extents! that the caller has made the reservation for free extents!
@return allocated page number, FIL_NULL if out of space */ @return new allocated block, x-latched; NULL if out of space */
static __attribute__((nonnull(1,5), warn_unused_result)) UNIV_INTERN
ulint buf_block_t*
btr_page_alloc_low( btr_page_alloc(
/*===============*/ /*===========*/
dict_index_t* index, /*!< in: index */ dict_index_t* index, /*!< in: index */
ulint hint_page_no, /*!< in: hint of a good page */ ulint hint_page_no, /*!< in: hint of a good page */
byte file_direction, /*!< in: direction where a possible byte file_direction, /*!< in: direction where a possible
page split is made */ page split is made */
ulint level, /*!< in: level where the page is placed ulint level, /*!< in: level where the page is placed
in the tree */ in the tree */
mtr_t* mtr, /*!< in/out: mini-transaction mtr_t* mtr) /*!< in: mtr */
for the allocation */
mtr_t* init_mtr) /*!< in/out: mini-transaction
in which the page should be
initialized (may be the same
as mtr), or NULL if it should
not be initialized (the page
at hint was previously freed
in mtr) */
{ {
fseg_header_t* seg_header; fseg_header_t* seg_header;
page_t* root; page_t* root;
buf_block_t* new_block;
ulint new_page_no;
if (dict_index_is_ibuf(index)) {
return(btr_page_alloc_for_ibuf(index, mtr));
}
root = btr_root_get(index, mtr); root = btr_root_get(index, mtr);
...@@ -942,42 +941,8 @@ btr_page_alloc_low( ...@@ -942,42 +941,8 @@ btr_page_alloc_low(
reservation for free extents, and thus we know that a page can reservation for free extents, and thus we know that a page can
be allocated: */ be allocated: */
return(fseg_alloc_free_page_general( new_page_no = fseg_alloc_free_page_general(seg_header, hint_page_no,
seg_header, hint_page_no, file_direction, file_direction, TRUE, mtr);
TRUE, mtr, init_mtr));
}
/**************************************************************//**
Allocates a new file page to be used in an index tree. NOTE: we assume
that the caller has made the reservation for free extents!
@return new allocated block, x-latched; NULL if out of space */
UNIV_INTERN
buf_block_t*
btr_page_alloc(
/*===========*/
dict_index_t* index, /*!< in: index */
ulint hint_page_no, /*!< in: hint of a good page */
byte file_direction, /*!< in: direction where a possible
page split is made */
ulint level, /*!< in: level where the page is placed
in the tree */
mtr_t* mtr, /*!< in/out: mini-transaction
for the allocation */
mtr_t* init_mtr) /*!< in/out: mini-transaction
for x-latching and initializing
the page */
{
buf_block_t* new_block;
ulint new_page_no;
if (dict_index_is_ibuf(index)) {
return(btr_page_alloc_for_ibuf(index, mtr));
}
new_page_no = btr_page_alloc_low(
index, hint_page_no, file_direction, level, mtr, init_mtr);
if (new_page_no == FIL_NULL) { if (new_page_no == FIL_NULL) {
return(NULL); return(NULL);
...@@ -985,16 +950,9 @@ btr_page_alloc( ...@@ -985,16 +950,9 @@ btr_page_alloc(
new_block = buf_page_get(dict_index_get_space(index), new_block = buf_page_get(dict_index_get_space(index),
dict_table_zip_size(index->table), dict_table_zip_size(index->table),
new_page_no, RW_X_LATCH, init_mtr); new_page_no, RW_X_LATCH, mtr);
buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW); buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW);
if (mtr->freed_clust_leaf) {
mtr_memo_release(mtr, new_block, MTR_MEMO_FREE_CLUST_LEAF);
ut_ad(!mtr_memo_contains(mtr, new_block,
MTR_MEMO_FREE_CLUST_LEAF));
}
ut_ad(btr_freed_leaves_validate(mtr));
return(new_block); return(new_block);
} }
...@@ -1107,15 +1065,6 @@ btr_page_free_low( ...@@ -1107,15 +1065,6 @@ btr_page_free_low(
fseg_free_page(seg_header, fseg_free_page(seg_header,
buf_block_get_space(block), buf_block_get_space(block),
buf_block_get_page_no(block), mtr); buf_block_get_page_no(block), mtr);
/* The page was marked free in the allocation bitmap, but it
should remain buffer-fixed until mtr_commit(mtr) or until it
is explicitly freed from the mini-transaction. */
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
/* TODO: Discard any operations on the page from the redo log
and remove the block from the flush list and the buffer pool.
This would free up buffer pool earlier and reduce writes to
both the tablespace and the redo log. */
} }
/**************************************************************//** /**************************************************************//**
...@@ -1129,139 +1078,12 @@ btr_page_free( ...@@ -1129,139 +1078,12 @@ btr_page_free(
buf_block_t* block, /*!< in: block to be freed, x-latched */ buf_block_t* block, /*!< in: block to be freed, x-latched */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
{ {
const page_t* page = buf_block_get_frame(block); ulint level;
ulint level = btr_page_get_level(page, mtr);
ut_ad(fil_page_get_type(block->frame) == FIL_PAGE_INDEX);
btr_page_free_low(index, block, level, mtr);
/* The handling of MTR_MEMO_FREE_CLUST_LEAF assumes this. */
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
if (level == 0 && dict_index_is_clust(index)) {
/* We may have to call btr_mark_freed_leaves() to
temporarily mark the block nonfree for invoking
btr_store_big_rec_extern_fields_func() after an
update. Remember that the block was freed. */
mtr->freed_clust_leaf = TRUE;
mtr_memo_push(mtr, block, MTR_MEMO_FREE_CLUST_LEAF);
}
ut_ad(btr_freed_leaves_validate(mtr));
}
/**************************************************************//**
Marks all MTR_MEMO_FREE_CLUST_LEAF pages nonfree or free.
For invoking btr_store_big_rec_extern_fields() after an update,
we must temporarily mark freed clustered index pages allocated, so
that off-page columns will not be allocated from them. Between the
btr_store_big_rec_extern_fields() and mtr_commit() we have to
mark the pages free again, so that no pages will be leaked. */
UNIV_INTERN
void
btr_mark_freed_leaves(
/*==================*/
dict_index_t* index, /*!< in/out: clustered index */
mtr_t* mtr, /*!< in/out: mini-transaction */
ibool nonfree)/*!< in: TRUE=mark nonfree, FALSE=mark freed */
{
/* This is loosely based on mtr_memo_release(). */
ulint offset;
ut_ad(dict_index_is_clust(index));
ut_ad(mtr->magic_n == MTR_MAGIC_N);
ut_ad(mtr->state == MTR_ACTIVE);
if (!mtr->freed_clust_leaf) {
return;
}
offset = dyn_array_get_data_size(&mtr->memo);
while (offset > 0) {
mtr_memo_slot_t* slot;
buf_block_t* block;
offset -= sizeof *slot;
slot = dyn_array_get_element(&mtr->memo, offset);
if (slot->type != MTR_MEMO_FREE_CLUST_LEAF) {
continue;
}
/* Because btr_page_alloc() does invoke
mtr_memo_release on MTR_MEMO_FREE_CLUST_LEAF, all
blocks tagged with MTR_MEMO_FREE_CLUST_LEAF in the
memo must still be clustered index leaf tree pages. */
block = slot->object;
ut_a(buf_block_get_space(block)
== dict_index_get_space(index));
ut_a(fil_page_get_type(buf_block_get_frame(block))
== FIL_PAGE_INDEX);
ut_a(page_is_leaf(buf_block_get_frame(block)));
if (nonfree) {
/* Allocate the same page again. */
ulint page_no;
page_no = btr_page_alloc_low(
index, buf_block_get_page_no(block),
FSP_NO_DIR, 0, mtr, NULL);
ut_a(page_no == buf_block_get_page_no(block));
} else {
/* Assert that the page is allocated and free it. */
btr_page_free_low(index, block, 0, mtr);
}
}
ut_ad(btr_freed_leaves_validate(mtr));
}
#ifdef UNIV_DEBUG
/**************************************************************//**
Validates all pages marked MTR_MEMO_FREE_CLUST_LEAF.
@see btr_mark_freed_leaves()
@return TRUE */
UNIV_INTERN
ibool
btr_freed_leaves_validate(
/*======================*/
mtr_t* mtr) /*!< in: mini-transaction */
{
ulint offset;
ut_ad(mtr->magic_n == MTR_MAGIC_N);
ut_ad(mtr->state == MTR_ACTIVE);
offset = dyn_array_get_data_size(&mtr->memo);
while (offset > 0) {
const mtr_memo_slot_t* slot;
const buf_block_t* block;
offset -= sizeof *slot;
slot = dyn_array_get_element(&mtr->memo, offset);
if (slot->type != MTR_MEMO_FREE_CLUST_LEAF) {
continue;
}
ut_a(mtr->freed_clust_leaf); level = btr_page_get_level(buf_block_get_frame(block), mtr);
/* Because btr_page_alloc() does invoke
mtr_memo_release on MTR_MEMO_FREE_CLUST_LEAF, all
blocks tagged with MTR_MEMO_FREE_CLUST_LEAF in the
memo must still be clustered index leaf tree pages. */
block = slot->object;
ut_a(fil_page_get_type(buf_block_get_frame(block))
== FIL_PAGE_INDEX);
ut_a(page_is_leaf(buf_block_get_frame(block)));
}
return(TRUE); btr_page_free_low(index, block, level, mtr);
} }
#endif /* UNIV_DEBUG */
/**************************************************************//** /**************************************************************//**
Sets the child node file address in a node pointer. */ Sets the child node file address in a node pointer. */
...@@ -1987,7 +1809,7 @@ btr_root_raise_and_insert( ...@@ -1987,7 +1809,7 @@ btr_root_raise_and_insert(
level = btr_page_get_level(root, mtr); level = btr_page_get_level(root, mtr);
new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr); new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr);
new_page = buf_block_get_frame(new_block); new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block); new_page_zip = buf_block_get_page_zip(new_block);
ut_a(!new_page_zip == !root_page_zip); ut_a(!new_page_zip == !root_page_zip);
...@@ -2458,7 +2280,7 @@ btr_attach_half_pages( ...@@ -2458,7 +2280,7 @@ btr_attach_half_pages(
/*==================*/ /*==================*/
dict_index_t* index, /*!< in: the index tree */ dict_index_t* index, /*!< in: the index tree */
buf_block_t* block, /*!< in/out: page to be split */ buf_block_t* block, /*!< in/out: page to be split */
const rec_t* split_rec, /*!< in: first record on upper rec_t* split_rec, /*!< in: first record on upper
half page */ half page */
buf_block_t* new_block, /*!< in/out: the new half page */ buf_block_t* new_block, /*!< in/out: the new half page */
ulint direction, /*!< in: FSP_UP or FSP_DOWN */ ulint direction, /*!< in: FSP_UP or FSP_DOWN */
...@@ -2723,7 +2545,7 @@ btr_page_split_and_insert( ...@@ -2723,7 +2545,7 @@ btr_page_split_and_insert(
/* 2. Allocate a new page to the index */ /* 2. Allocate a new page to the index */
new_block = btr_page_alloc(cursor->index, hint_page_no, direction, new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
btr_page_get_level(page, mtr), mtr, mtr); btr_page_get_level(page, mtr), mtr);
new_page = buf_block_get_frame(new_block); new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block); new_page_zip = buf_block_get_page_zip(new_block);
btr_page_create(new_block, new_page_zip, cursor->index, btr_page_create(new_block, new_page_zip, cursor->index,
...@@ -3173,16 +2995,15 @@ btr_node_ptr_delete( ...@@ -3173,16 +2995,15 @@ btr_node_ptr_delete(
ut_a(err == DB_SUCCESS); ut_a(err == DB_SUCCESS);
if (!compressed) { if (!compressed) {
btr_cur_compress_if_useful(&cursor, FALSE, mtr); btr_cur_compress_if_useful(&cursor, mtr);
} }
} }
/*************************************************************//** /*************************************************************//**
If page is the only on its level, this function moves its records to the If page is the only on its level, this function moves its records to the
father page, thus reducing the tree height. father page, thus reducing the tree height. */
@return father block */
static static
buf_block_t* void
btr_lift_page_up( btr_lift_page_up(
/*=============*/ /*=============*/
dict_index_t* index, /*!< in: index tree */ dict_index_t* index, /*!< in: index tree */
...@@ -3299,8 +3120,6 @@ btr_lift_page_up( ...@@ -3299,8 +3120,6 @@ btr_lift_page_up(
} }
ut_ad(page_validate(father_page, index)); ut_ad(page_validate(father_page, index));
ut_ad(btr_check_node_ptr(index, father_block, mtr)); ut_ad(btr_check_node_ptr(index, father_block, mtr));
return(father_block);
} }
/*************************************************************//** /*************************************************************//**
...@@ -3317,13 +3136,11 @@ UNIV_INTERN ...@@ -3317,13 +3136,11 @@ UNIV_INTERN
ibool ibool
btr_compress( btr_compress(
/*=========*/ /*=========*/
btr_cur_t* cursor, /*!< in/out: cursor on the page to merge btr_cur_t* cursor, /*!< in: cursor on the page to merge or lift;
or lift; the page must not be empty: the page must not be empty: in record delete
when deleting records, use btr_discard_page() use btr_discard_page if the page would become
if the page would become empty */ empty */
ibool adjust, /*!< in: TRUE if should adjust the mtr_t* mtr) /*!< in: mtr */
cursor position even if compression occurs */
mtr_t* mtr) /*!< in/out: mini-transaction */
{ {
dict_index_t* index; dict_index_t* index;
ulint space; ulint space;
...@@ -3341,14 +3158,12 @@ btr_compress( ...@@ -3341,14 +3158,12 @@ btr_compress(
ulint* offsets; ulint* offsets;
ulint data_size; ulint data_size;
ulint n_recs; ulint n_recs;
ulint nth_rec = 0; /* remove bogus warning */
ulint max_ins_size; ulint max_ins_size;
ulint max_ins_size_reorg; ulint max_ins_size_reorg;
block = btr_cur_get_block(cursor); block = btr_cur_get_block(cursor);
page = btr_cur_get_page(cursor); page = btr_cur_get_page(cursor);
index = btr_cur_get_index(cursor); index = btr_cur_get_index(cursor);
ut_a((ibool) !!page_is_comp(page) == dict_table_is_comp(index->table)); ut_a((ibool) !!page_is_comp(page) == dict_table_is_comp(index->table));
ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index), ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
...@@ -3369,10 +3184,6 @@ btr_compress( ...@@ -3369,10 +3184,6 @@ btr_compress(
offsets = btr_page_get_father_block(NULL, heap, index, block, mtr, offsets = btr_page_get_father_block(NULL, heap, index, block, mtr,
&father_cursor); &father_cursor);
if (adjust) {
nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor));
}
/* Decide the page to which we try to merge and which will inherit /* Decide the page to which we try to merge and which will inherit
the locks */ the locks */
...@@ -3399,9 +3210,9 @@ btr_compress( ...@@ -3399,9 +3210,9 @@ btr_compress(
} else { } else {
/* The page is the only one on the level, lift the records /* The page is the only one on the level, lift the records
to the father */ to the father */
btr_lift_page_up(index, block, mtr);
merge_block = btr_lift_page_up(index, block, mtr); mem_heap_free(heap);
goto func_exit; return(TRUE);
} }
n_recs = page_get_n_recs(page); n_recs = page_get_n_recs(page);
...@@ -3483,10 +3294,6 @@ btr_compress( ...@@ -3483,10 +3294,6 @@ btr_compress(
btr_node_ptr_delete(index, block, mtr); btr_node_ptr_delete(index, block, mtr);
lock_update_merge_left(merge_block, orig_pred, block); lock_update_merge_left(merge_block, orig_pred, block);
if (adjust) {
nth_rec += page_rec_get_n_recs_before(orig_pred);
}
} else { } else {
rec_t* orig_succ; rec_t* orig_succ;
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
...@@ -3551,6 +3358,7 @@ btr_compress( ...@@ -3551,6 +3358,7 @@ btr_compress(
} }
btr_blob_dbg_remove(page, index, "btr_compress"); btr_blob_dbg_remove(page, index, "btr_compress");
mem_heap_free(heap);
if (!dict_index_is_clust(index) && page_is_leaf(merge_page)) { if (!dict_index_is_clust(index) && page_is_leaf(merge_page)) {
/* Update the free bits of the B-tree page in the /* Update the free bits of the B-tree page in the
...@@ -3602,16 +3410,6 @@ btr_compress( ...@@ -3602,16 +3410,6 @@ btr_compress(
btr_page_free(index, block, mtr); btr_page_free(index, block, mtr);
ut_ad(btr_check_node_ptr(index, merge_block, mtr)); ut_ad(btr_check_node_ptr(index, merge_block, mtr));
func_exit:
mem_heap_free(heap);
if (adjust) {
btr_cur_position(
index,
page_rec_get_nth(merge_block->frame, nth_rec),
merge_block, cursor);
}
return(TRUE); return(TRUE);
} }
......
...@@ -1985,6 +1985,7 @@ btr_cur_optimistic_update( ...@@ -1985,6 +1985,7 @@ btr_cur_optimistic_update(
ulint old_rec_size; ulint old_rec_size;
dtuple_t* new_entry; dtuple_t* new_entry;
roll_ptr_t roll_ptr; roll_ptr_t roll_ptr;
trx_t* trx;
mem_heap_t* heap; mem_heap_t* heap;
ulint i; ulint i;
ulint n_ext; ulint n_ext;
...@@ -2001,10 +2002,9 @@ btr_cur_optimistic_update( ...@@ -2001,10 +2002,9 @@ btr_cur_optimistic_update(
heap = mem_heap_create(1024); heap = mem_heap_create(1024);
offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG #ifdef UNIV_BLOB_NULL_DEBUG
ut_a(!rec_offs_any_null_extern(rec, offsets) ut_a(!rec_offs_any_null_extern(rec, offsets));
|| trx_is_recv(thr_get_trx(thr))); #endif /* UNIV_BLOB_NULL_DEBUG */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) { if (btr_cur_print_record_ops && thr) {
...@@ -2127,11 +2127,13 @@ btr_cur_optimistic_update( ...@@ -2127,11 +2127,13 @@ btr_cur_optimistic_update(
page_cur_move_to_prev(page_cursor); page_cur_move_to_prev(page_cursor);
trx = thr_get_trx(thr);
if (!(flags & BTR_KEEP_SYS_FLAG)) { if (!(flags & BTR_KEEP_SYS_FLAG)) {
row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR, row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
roll_ptr); roll_ptr);
row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID, row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID,
thr_get_trx(thr)->id); trx->id);
} }
/* There are no externally stored columns in new_entry */ /* There are no externally stored columns in new_entry */
...@@ -2217,9 +2219,7 @@ btr_cur_pessimistic_update( ...@@ -2217,9 +2219,7 @@ btr_cur_pessimistic_update(
/*=======================*/ /*=======================*/
ulint flags, /*!< in: undo logging, locking, and rollback ulint flags, /*!< in: undo logging, locking, and rollback
flags */ flags */
btr_cur_t* cursor, /*!< in/out: cursor on the record to update; btr_cur_t* cursor, /*!< in: cursor on the record to update */
cursor may become invalid if *big_rec == NULL
|| !(flags & BTR_KEEP_POS_FLAG) */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
be stored externally by the caller, or NULL */ be stored externally by the caller, or NULL */
...@@ -2358,7 +2358,7 @@ btr_cur_pessimistic_update( ...@@ -2358,7 +2358,7 @@ btr_cur_pessimistic_update(
record to be inserted: we have to remember which fields were such */ record to be inserted: we have to remember which fields were such */
ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec)); ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec));
ut_ad(rec_offs_validate(rec, index, offsets)); offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, heap);
n_ext += btr_push_update_extern_fields(new_entry, update, *heap); n_ext += btr_push_update_extern_fields(new_entry, update, *heap);
if (UNIV_LIKELY_NULL(page_zip)) { if (UNIV_LIKELY_NULL(page_zip)) {
...@@ -2381,10 +2381,6 @@ btr_cur_pessimistic_update( ...@@ -2381,10 +2381,6 @@ btr_cur_pessimistic_update(
err = DB_TOO_BIG_RECORD; err = DB_TOO_BIG_RECORD;
goto return_after_reservations; goto return_after_reservations;
} }
ut_ad(page_is_leaf(page));
ut_ad(dict_index_is_clust(index));
ut_ad(flags & BTR_KEEP_POS_FLAG);
} }
/* Store state of explicit locks on rec on the page infimum record, /* Store state of explicit locks on rec on the page infimum record,
...@@ -2412,8 +2408,6 @@ btr_cur_pessimistic_update( ...@@ -2412,8 +2408,6 @@ btr_cur_pessimistic_update(
rec = btr_cur_insert_if_possible(cursor, new_entry, n_ext, mtr); rec = btr_cur_insert_if_possible(cursor, new_entry, n_ext, mtr);
if (rec) { if (rec) {
page_cursor->rec = rec;
lock_rec_restore_from_page_infimum(btr_cur_get_block(cursor), lock_rec_restore_from_page_infimum(btr_cur_get_block(cursor),
rec, block); rec, block);
...@@ -2427,10 +2421,7 @@ btr_cur_pessimistic_update( ...@@ -2427,10 +2421,7 @@ btr_cur_pessimistic_update(
rec, index, offsets, mtr); rec, index, offsets, mtr);
} }
btr_cur_compress_if_useful( btr_cur_compress_if_useful(cursor, mtr);
cursor,
big_rec_vec != NULL && (flags & BTR_KEEP_POS_FLAG),
mtr);
if (page_zip && !dict_index_is_clust(index) if (page_zip && !dict_index_is_clust(index)
&& page_is_leaf(page)) { && page_is_leaf(page)) {
...@@ -2450,21 +2441,6 @@ btr_cur_pessimistic_update( ...@@ -2450,21 +2441,6 @@ btr_cur_pessimistic_update(
} }
} }
if (big_rec_vec) {
ut_ad(page_is_leaf(page));
ut_ad(dict_index_is_clust(index));
ut_ad(flags & BTR_KEEP_POS_FLAG);
/* btr_page_split_and_insert() in
btr_cur_pessimistic_insert() invokes
mtr_memo_release(mtr, index->lock, MTR_MEMO_X_LOCK).
We must keep the index->lock when we created a
big_rec, so that row_upd_clust_rec() can store the
big_rec in the same mini-transaction. */
mtr_x_lock(dict_index_get_lock(index), mtr);
}
/* Was the record to be updated positioned as the first user /* Was the record to be updated positioned as the first user
record on its page? */ record on its page? */
was_first = page_cur_is_before_first(page_cursor); was_first = page_cur_is_before_first(page_cursor);
...@@ -2480,7 +2456,6 @@ btr_cur_pessimistic_update( ...@@ -2480,7 +2456,6 @@ btr_cur_pessimistic_update(
ut_a(rec); ut_a(rec);
ut_a(err == DB_SUCCESS); ut_a(err == DB_SUCCESS);
ut_a(dummy_big_rec == NULL); ut_a(dummy_big_rec == NULL);
page_cursor->rec = rec;
if (dict_index_is_sec_or_ibuf(index)) { if (dict_index_is_sec_or_ibuf(index)) {
/* Update PAGE_MAX_TRX_ID in the index page header. /* Update PAGE_MAX_TRX_ID in the index page header.
...@@ -2915,12 +2890,10 @@ UNIV_INTERN ...@@ -2915,12 +2890,10 @@ UNIV_INTERN
ibool ibool
btr_cur_compress_if_useful( btr_cur_compress_if_useful(
/*=======================*/ /*=======================*/
btr_cur_t* cursor, /*!< in/out: cursor on the page to compress; btr_cur_t* cursor, /*!< in: cursor on the page to compress;
cursor does not stay valid if !adjust and cursor does not stay valid if compression
compression occurs */ occurs */
ibool adjust, /*!< in: TRUE if should adjust the mtr_t* mtr) /*!< in: mtr */
cursor position even if compression occurs */
mtr_t* mtr) /*!< in/out: mini-transaction */
{ {
ut_ad(mtr_memo_contains(mtr, ut_ad(mtr_memo_contains(mtr,
dict_index_get_lock(btr_cur_get_index(cursor)), dict_index_get_lock(btr_cur_get_index(cursor)),
...@@ -2929,7 +2902,7 @@ btr_cur_compress_if_useful( ...@@ -2929,7 +2902,7 @@ btr_cur_compress_if_useful(
MTR_MEMO_PAGE_X_FIX)); MTR_MEMO_PAGE_X_FIX));
return(btr_cur_compress_recommendation(cursor, mtr) return(btr_cur_compress_recommendation(cursor, mtr)
&& btr_compress(cursor, adjust, mtr)); && btr_compress(cursor, mtr));
} }
/*******************************************************//** /*******************************************************//**
...@@ -3171,7 +3144,7 @@ btr_cur_pessimistic_delete( ...@@ -3171,7 +3144,7 @@ btr_cur_pessimistic_delete(
mem_heap_free(heap); mem_heap_free(heap);
if (ret == FALSE) { if (ret == FALSE) {
ret = btr_cur_compress_if_useful(cursor, FALSE, mtr); ret = btr_cur_compress_if_useful(cursor, mtr);
} }
if (n_extents > 0) { if (n_extents > 0) {
...@@ -4160,9 +4133,6 @@ btr_store_big_rec_extern_fields_func( ...@@ -4160,9 +4133,6 @@ btr_store_big_rec_extern_fields_func(
the "external storage" flags in offsets the "external storage" flags in offsets
will not correspond to rec when will not correspond to rec when
this function returns */ this function returns */
const big_rec_t*big_rec_vec, /*!< in: vector containing fields
to be stored externally */
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
mtr_t* local_mtr, /*!< in: mtr containing the mtr_t* local_mtr, /*!< in: mtr containing the
latch to rec and to the tree */ latch to rec and to the tree */
...@@ -4171,11 +4141,9 @@ btr_store_big_rec_extern_fields_func( ...@@ -4171,11 +4141,9 @@ btr_store_big_rec_extern_fields_func(
ibool update_in_place,/*! in: TRUE if the record is updated ibool update_in_place,/*! in: TRUE if the record is updated
in place (not delete+insert) */ in place (not delete+insert) */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ #endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
mtr_t* alloc_mtr) /*!< in/out: in an insert, NULL; const big_rec_t*big_rec_vec) /*!< in: vector containing fields
in an update, local_mtr for to be stored externally */
allocating BLOB pages and
updating BLOB pointers; alloc_mtr
must not have freed any leaf pages */
{ {
ulint rec_page_no; ulint rec_page_no;
byte* field_ref; byte* field_ref;
...@@ -4194,9 +4162,6 @@ btr_store_big_rec_extern_fields_func( ...@@ -4194,9 +4162,6 @@ btr_store_big_rec_extern_fields_func(
ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(rec_offs_any_extern(offsets)); ut_ad(rec_offs_any_extern(offsets));
ut_ad(local_mtr);
ut_ad(!alloc_mtr || alloc_mtr == local_mtr);
ut_ad(!update_in_place || alloc_mtr);
ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index), ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index),
MTR_MEMO_X_LOCK)); MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains(local_mtr, rec_block, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr_memo_contains(local_mtr, rec_block, MTR_MEMO_PAGE_X_FIX));
...@@ -4212,25 +4177,6 @@ btr_store_big_rec_extern_fields_func( ...@@ -4212,25 +4177,6 @@ btr_store_big_rec_extern_fields_func(
rec_page_no = buf_block_get_page_no(rec_block); rec_page_no = buf_block_get_page_no(rec_block);
ut_a(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX); ut_a(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX);
if (alloc_mtr) {
/* Because alloc_mtr will be committed after
mtr, it is possible that the tablespace has been
extended when the B-tree record was updated or
inserted, or it will be extended while allocating
pages for big_rec.
TODO: In mtr (not alloc_mtr), write a redo log record
about extending the tablespace to its current size,
and remember the current size. Whenever the tablespace
grows as pages are allocated, write further redo log
records to mtr. (Currently tablespace extension is not
covered by the redo log. If it were, the record would
only be written to alloc_mtr, which is committed after
mtr.) */
} else {
alloc_mtr = &mtr;
}
if (UNIV_LIKELY_NULL(page_zip)) { if (UNIV_LIKELY_NULL(page_zip)) {
int err; int err;
...@@ -4307,7 +4253,7 @@ btr_store_big_rec_extern_fields_func( ...@@ -4307,7 +4253,7 @@ btr_store_big_rec_extern_fields_func(
} }
block = btr_page_alloc(index, hint_page_no, block = btr_page_alloc(index, hint_page_no,
FSP_NO_DIR, 0, alloc_mtr, &mtr); FSP_NO_DIR, 0, &mtr);
if (UNIV_UNLIKELY(block == NULL)) { if (UNIV_UNLIKELY(block == NULL)) {
mtr_commit(&mtr); mtr_commit(&mtr);
...@@ -4434,15 +4380,11 @@ btr_store_big_rec_extern_fields_func( ...@@ -4434,15 +4380,11 @@ btr_store_big_rec_extern_fields_func(
goto next_zip_page; goto next_zip_page;
} }
if (alloc_mtr == &mtr) { rec_block = buf_page_get(space_id, zip_size,
rec_block = buf_page_get(
space_id, zip_size,
rec_page_no, rec_page_no,
RW_X_LATCH, &mtr); RW_X_LATCH, &mtr);
buf_block_dbg_add_level( buf_block_dbg_add_level(rec_block,
rec_block,
SYNC_NO_ORDER_CHECK); SYNC_NO_ORDER_CHECK);
}
if (err == Z_STREAM_END) { if (err == Z_STREAM_END) {
mach_write_to_4(field_ref mach_write_to_4(field_ref
...@@ -4476,8 +4418,7 @@ btr_store_big_rec_extern_fields_func( ...@@ -4476,8 +4418,7 @@ btr_store_big_rec_extern_fields_func(
page_zip_write_blob_ptr( page_zip_write_blob_ptr(
page_zip, rec, index, offsets, page_zip, rec, index, offsets,
big_rec_vec->fields[i].field_no, big_rec_vec->fields[i].field_no, &mtr);
alloc_mtr);
next_zip_page: next_zip_page:
prev_page_no = page_no; prev_page_no = page_no;
...@@ -4522,23 +4463,19 @@ btr_store_big_rec_extern_fields_func( ...@@ -4522,23 +4463,19 @@ btr_store_big_rec_extern_fields_func(
extern_len -= store_len; extern_len -= store_len;
if (alloc_mtr == &mtr) { rec_block = buf_page_get(space_id, zip_size,
rec_block = buf_page_get(
space_id, zip_size,
rec_page_no, rec_page_no,
RW_X_LATCH, &mtr); RW_X_LATCH, &mtr);
buf_block_dbg_add_level( buf_block_dbg_add_level(rec_block,
rec_block,
SYNC_NO_ORDER_CHECK); SYNC_NO_ORDER_CHECK);
}
mlog_write_ulint(field_ref + BTR_EXTERN_LEN, 0, mlog_write_ulint(field_ref + BTR_EXTERN_LEN, 0,
MLOG_4BYTES, alloc_mtr); MLOG_4BYTES, &mtr);
mlog_write_ulint(field_ref mlog_write_ulint(field_ref
+ BTR_EXTERN_LEN + 4, + BTR_EXTERN_LEN + 4,
big_rec_vec->fields[i].len big_rec_vec->fields[i].len
- extern_len, - extern_len,
MLOG_4BYTES, alloc_mtr); MLOG_4BYTES, &mtr);
if (prev_page_no == FIL_NULL) { if (prev_page_no == FIL_NULL) {
btr_blob_dbg_add_blob( btr_blob_dbg_add_blob(
...@@ -4548,19 +4485,18 @@ btr_store_big_rec_extern_fields_func( ...@@ -4548,19 +4485,18 @@ btr_store_big_rec_extern_fields_func(
mlog_write_ulint(field_ref mlog_write_ulint(field_ref
+ BTR_EXTERN_SPACE_ID, + BTR_EXTERN_SPACE_ID,
space_id, MLOG_4BYTES, space_id,
alloc_mtr); MLOG_4BYTES, &mtr);
mlog_write_ulint(field_ref mlog_write_ulint(field_ref
+ BTR_EXTERN_PAGE_NO, + BTR_EXTERN_PAGE_NO,
page_no, MLOG_4BYTES, page_no,
alloc_mtr); MLOG_4BYTES, &mtr);
mlog_write_ulint(field_ref mlog_write_ulint(field_ref
+ BTR_EXTERN_OFFSET, + BTR_EXTERN_OFFSET,
FIL_PAGE_DATA, FIL_PAGE_DATA,
MLOG_4BYTES, MLOG_4BYTES, &mtr);
alloc_mtr);
} }
prev_page_no = page_no; prev_page_no = page_no;
......
...@@ -1715,6 +1715,31 @@ buf_page_set_accessed_make_young( ...@@ -1715,6 +1715,31 @@ buf_page_set_accessed_make_young(
} }
} }
/********************************************************************//**
Resets the check_index_page_at_flush field of a page if found in the buffer
pool. */
UNIV_INTERN
void
buf_reset_check_index_page_at_flush(
/*================================*/
ulint space, /*!< in: space id */
ulint offset) /*!< in: page number */
{
buf_block_t* block;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
buf_pool_mutex_enter(buf_pool);
block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
if (block && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE) {
ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
block->check_index_page_at_flush = FALSE;
}
buf_pool_mutex_exit(buf_pool);
}
/********************************************************************//** /********************************************************************//**
Returns the current state of is_hashed of a page. FALSE if the page is 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 not in the pool. NOTE that this operation does not fix the page in the
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -311,9 +311,8 @@ fsp_fill_free_list( ...@@ -311,9 +311,8 @@ fsp_fill_free_list(
descriptor page and ibuf bitmap page; descriptor page and ibuf bitmap page;
then we do not allocate more extents */ then we do not allocate more extents */
ulint space, /*!< in: space */ ulint space, /*!< in: space */
fsp_header_t* header, /*!< in/out: space header */ fsp_header_t* header, /*!< in: space header */
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr); /*!< in: mtr */
UNIV_COLD __attribute__((nonnull));
/**********************************************************************//** /**********************************************************************//**
Allocates a single free page from a segment. This function implements Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space the intelligent allocation strategy which tries to minimize file space
...@@ -326,20 +325,14 @@ fseg_alloc_free_page_low( ...@@ -326,20 +325,14 @@ fseg_alloc_free_page_low(
ulint space, /*!< in: space */ ulint space, /*!< in: space */
ulint zip_size,/*!< in: compressed page size in bytes ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */ or 0 for uncompressed pages */
fseg_inode_t* seg_inode, /*!< in/out: segment inode */ fseg_inode_t* seg_inode, /*!< in: segment inode */
ulint hint, /*!< in: hint of which page would be desirable */ ulint hint, /*!< in: hint of which page would be desirable */
byte direction, /*!< in: if the new page is needed because byte direction, /*!< in: if the new page is needed because
of an index page split, and records are of an index page split, and records are
inserted there in order, into which inserted there in order, into which
direction they go alphabetically: FSP_DOWN, direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR */ FSP_UP, FSP_NO_DIR */
mtr_t* mtr, /*!< in/out: mini-transaction */ mtr_t* mtr); /*!< in: mtr handle */
mtr_t* init_mtr)/*!< in/out: mini-transaction in which the
page should be initialized
(may be the same as mtr), or NULL if it
should not be initialized (the page at hint
was previously freed in mtr) */
__attribute__((warn_unused_result, nonnull(3,6)));
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/**********************************************************************//** /**********************************************************************//**
...@@ -707,18 +700,17 @@ list, if not free limit == space size. This adding is necessary to make the ...@@ -707,18 +700,17 @@ list, if not free limit == space size. This adding is necessary to make the
descriptor defined, as they are uninitialized above the free limit. descriptor defined, as they are uninitialized above the free limit.
@return pointer to the extent descriptor, NULL if the page does not @return pointer to the extent descriptor, NULL if the page does not
exist in the space or if the offset exceeds the free limit */ exist in the space or if the offset exceeds the free limit */
UNIV_INLINE __attribute__((nonnull, warn_unused_result)) UNIV_INLINE
xdes_t* xdes_t*
xdes_get_descriptor_with_space_hdr( xdes_get_descriptor_with_space_hdr(
/*===============================*/ /*===============================*/
fsp_header_t* sp_header, /*!< in/out: space header, x-latched fsp_header_t* sp_header,/*!< in/out: space header, x-latched */
in mtr */
ulint space, /*!< in: space id */ ulint space, /*!< in: space id */
ulint offset, /*!< in: page offset; if equal ulint offset, /*!< in: page offset;
to the free limit, we try to if equal to the free limit,
add new extents to the space we try to add new extents to
free list */ the space free list */
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in: mtr handle */
{ {
ulint limit; ulint limit;
ulint size; ulint size;
...@@ -726,9 +718,11 @@ xdes_get_descriptor_with_space_hdr( ...@@ -726,9 +718,11 @@ xdes_get_descriptor_with_space_hdr(
ulint descr_page_no; ulint descr_page_no;
page_t* descr_page; page_t* descr_page;
ut_ad(mtr);
ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL), ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
MTR_MEMO_X_LOCK)); MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_S_FIX)
|| mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET); ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET);
/* Read free limit and space size */ /* Read free limit and space size */
limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT); limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT);
...@@ -778,7 +772,7 @@ is necessary to make the descriptor defined, as they are uninitialized ...@@ -778,7 +772,7 @@ is necessary to make the descriptor defined, as they are uninitialized
above the free limit. above the free limit.
@return pointer to the extent descriptor, NULL if the page does not @return pointer to the extent descriptor, NULL if the page does not
exist in the space or if the offset exceeds the free limit */ exist in the space or if the offset exceeds the free limit */
static __attribute__((nonnull, warn_unused_result)) static
xdes_t* xdes_t*
xdes_get_descriptor( xdes_get_descriptor(
/*================*/ /*================*/
...@@ -787,7 +781,7 @@ xdes_get_descriptor( ...@@ -787,7 +781,7 @@ xdes_get_descriptor(
or 0 for uncompressed pages */ or 0 for uncompressed pages */
ulint offset, /*!< in: page offset; if equal to the free limit, ulint offset, /*!< in: page offset; if equal to the free limit,
we try to add new extents to the space free list */ we try to add new extents to the space free list */
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in: mtr handle */
{ {
buf_block_t* block; buf_block_t* block;
fsp_header_t* sp_header; fsp_header_t* sp_header;
...@@ -1165,14 +1159,14 @@ fsp_header_get_tablespace_size(void) ...@@ -1165,14 +1159,14 @@ fsp_header_get_tablespace_size(void)
Tries to extend a single-table tablespace so that a page would fit in the Tries to extend a single-table tablespace so that a page would fit in the
data file. data file.
@return TRUE if success */ @return TRUE if success */
static UNIV_COLD __attribute__((nonnull, warn_unused_result)) static
ibool ibool
fsp_try_extend_data_file_with_pages( fsp_try_extend_data_file_with_pages(
/*================================*/ /*================================*/
ulint space, /*!< in: space */ ulint space, /*!< in: space */
ulint page_no, /*!< in: page number */ ulint page_no, /*!< in: page number */
fsp_header_t* header, /*!< in/out: space header */ fsp_header_t* header, /*!< in: space header */
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in: mtr */
{ {
ibool success; ibool success;
ulint actual_size; ulint actual_size;
...@@ -1197,7 +1191,7 @@ fsp_try_extend_data_file_with_pages( ...@@ -1197,7 +1191,7 @@ fsp_try_extend_data_file_with_pages(
/***********************************************************************//** /***********************************************************************//**
Tries to extend the last data file of a tablespace if it is auto-extending. Tries to extend the last data file of a tablespace if it is auto-extending.
@return FALSE if not auto-extending */ @return FALSE if not auto-extending */
static UNIV_COLD __attribute__((nonnull)) static
ibool ibool
fsp_try_extend_data_file( fsp_try_extend_data_file(
/*=====================*/ /*=====================*/
...@@ -1207,8 +1201,8 @@ fsp_try_extend_data_file( ...@@ -1207,8 +1201,8 @@ fsp_try_extend_data_file(
the actual file size rounded down to the actual file size rounded down to
megabyte */ megabyte */
ulint space, /*!< in: space */ ulint space, /*!< in: space */
fsp_header_t* header, /*!< in/out: space header */ fsp_header_t* header, /*!< in: space header */
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in: mtr */
{ {
ulint size; ulint size;
ulint zip_size; ulint zip_size;
...@@ -1344,7 +1338,7 @@ fsp_fill_free_list( ...@@ -1344,7 +1338,7 @@ fsp_fill_free_list(
then we do not allocate more extents */ then we do not allocate more extents */
ulint space, /*!< in: space */ ulint space, /*!< in: space */
fsp_header_t* header, /*!< in/out: space header */ fsp_header_t* header, /*!< in/out: space header */
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in: mtr */
{ {
ulint limit; ulint limit;
ulint size; ulint size;
...@@ -1542,47 +1536,10 @@ fsp_alloc_free_extent( ...@@ -1542,47 +1536,10 @@ fsp_alloc_free_extent(
return(descr); return(descr);
} }
/**********************************************************************//**
Allocates a single free page from a space. */
static __attribute__((nonnull))
void
fsp_alloc_from_free_frag(
/*=====================*/
fsp_header_t* header, /*!< in/out: tablespace header */
xdes_t* descr, /*!< in/out: extent descriptor */
ulint bit, /*!< in: slot to allocate in the extent */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint frag_n_used;
ut_ad(xdes_get_state(descr, mtr) == XDES_FREE_FRAG);
ut_a(xdes_get_bit(descr, XDES_FREE_BIT, bit, mtr));
xdes_set_bit(descr, XDES_FREE_BIT, bit, FALSE, mtr);
/* Update the FRAG_N_USED field */
frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
mtr);
frag_n_used++;
mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
mtr);
if (xdes_is_full(descr, mtr)) {
/* The fragment is full: move it to another list */
flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
mtr);
xdes_set_state(descr, XDES_FULL_FRAG, mtr);
flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
mtr);
mlog_write_ulint(header + FSP_FRAG_N_USED,
frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
mtr);
}
}
/**********************************************************************//** /**********************************************************************//**
Allocates a single free page from a space. The page is marked as used. Allocates a single free page from a space. The page is marked as used.
@return the page offset, FIL_NULL if no page could be allocated */ @return the page offset, FIL_NULL if no page could be allocated */
static __attribute__((nonnull, warn_unused_result)) static
ulint ulint
fsp_alloc_free_page( fsp_alloc_free_page(
/*================*/ /*================*/
...@@ -1590,22 +1547,19 @@ fsp_alloc_free_page( ...@@ -1590,22 +1547,19 @@ fsp_alloc_free_page(
ulint zip_size,/*!< in: compressed page size in bytes ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */ or 0 for uncompressed pages */
ulint hint, /*!< in: hint of which page would be desirable */ ulint hint, /*!< in: hint of which page would be desirable */
mtr_t* mtr, /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in: mtr handle */
mtr_t* init_mtr)/*!< in/out: mini-transaction in which the
page should be initialized
(may be the same as mtr) */
{ {
fsp_header_t* header; fsp_header_t* header;
fil_addr_t first; fil_addr_t first;
xdes_t* descr; xdes_t* descr;
buf_block_t* block; buf_block_t* block;
ulint free; ulint free;
ulint frag_n_used;
ulint page_no; ulint page_no;
ulint space_size; ulint space_size;
ibool success; ibool success;
ut_ad(mtr); ut_ad(mtr);
ut_ad(init_mtr);
header = fsp_get_space_header(space, zip_size, mtr); header = fsp_get_space_header(space, zip_size, mtr);
...@@ -1687,19 +1641,38 @@ fsp_alloc_free_page( ...@@ -1687,19 +1641,38 @@ fsp_alloc_free_page(
} }
} }
fsp_alloc_from_free_frag(header, descr, free, mtr); xdes_set_bit(descr, XDES_FREE_BIT, free, FALSE, mtr);
/* Update the FRAG_N_USED field */
frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
mtr);
frag_n_used++;
mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
mtr);
if (xdes_is_full(descr, mtr)) {
/* The fragment is full: move it to another list */
flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
mtr);
xdes_set_state(descr, XDES_FULL_FRAG, mtr);
flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
mtr);
mlog_write_ulint(header + FSP_FRAG_N_USED,
frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
mtr);
}
/* Initialize the allocated page to the buffer pool, so that it can /* Initialize the allocated page to the buffer pool, so that it can
be obtained immediately with buf_page_get without need for a disk be obtained immediately with buf_page_get without need for a disk
read. */ read. */
buf_page_create(space, page_no, zip_size, init_mtr); buf_page_create(space, page_no, zip_size, mtr);
block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, init_mtr); block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE); buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
/* Prior contents of the page should be ignored */ /* Prior contents of the page should be ignored */
fsp_init_file_page(block, init_mtr); fsp_init_file_page(block, mtr);
return(page_no); return(page_no);
} }
...@@ -1935,7 +1908,7 @@ fsp_alloc_seg_inode_page( ...@@ -1935,7 +1908,7 @@ fsp_alloc_seg_inode_page(
zip_size = dict_table_flags_to_zip_size( zip_size = dict_table_flags_to_zip_size(
mach_read_from_4(FSP_SPACE_FLAGS + space_header)); mach_read_from_4(FSP_SPACE_FLAGS + space_header));
page_no = fsp_alloc_free_page(space, zip_size, 0, mtr, mtr); page_no = fsp_alloc_free_page(space, zip_size, 0, mtr);
if (page_no == FIL_NULL) { if (page_no == FIL_NULL) {
...@@ -2347,7 +2320,7 @@ fseg_create_general( ...@@ -2347,7 +2320,7 @@ fseg_create_general(
if (page == 0) { if (page == 0) {
page = fseg_alloc_free_page_low(space, zip_size, page = fseg_alloc_free_page_low(space, zip_size,
inode, 0, FSP_UP, mtr, mtr); inode, 0, FSP_UP, mtr);
if (page == FIL_NULL) { if (page == FIL_NULL) {
...@@ -2596,19 +2569,14 @@ fseg_alloc_free_page_low( ...@@ -2596,19 +2569,14 @@ fseg_alloc_free_page_low(
ulint space, /*!< in: space */ ulint space, /*!< in: space */
ulint zip_size,/*!< in: compressed page size in bytes ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */ or 0 for uncompressed pages */
fseg_inode_t* seg_inode, /*!< in/out: segment inode */ fseg_inode_t* seg_inode, /*!< in: segment inode */
ulint hint, /*!< in: hint of which page would be desirable */ ulint hint, /*!< in: hint of which page would be desirable */
byte direction, /*!< in: if the new page is needed because byte direction, /*!< in: if the new page is needed because
of an index page split, and records are of an index page split, and records are
inserted there in order, into which inserted there in order, into which
direction they go alphabetically: FSP_DOWN, direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR */ FSP_UP, FSP_NO_DIR */
mtr_t* mtr, /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in: mtr handle */
mtr_t* init_mtr)/*!< in/out: mini-transaction in which the
page should be initialized
(may be the same as mtr), or NULL if it
should not be initialized (the page at hint
was previously freed in mtr) */
{ {
fsp_header_t* space_header; fsp_header_t* space_header;
ulint space_size; ulint space_size;
...@@ -2619,6 +2587,7 @@ fseg_alloc_free_page_low( ...@@ -2619,6 +2587,7 @@ fseg_alloc_free_page_low(
ulint ret_page; /*!< the allocated page offset, FIL_NULL ulint ret_page; /*!< the allocated page offset, FIL_NULL
if could not be allocated */ if could not be allocated */
xdes_t* ret_descr; /*!< the extent of the allocated page */ xdes_t* ret_descr; /*!< the extent of the allocated page */
ibool frag_page_allocated = FALSE;
ibool success; ibool success;
ulint n; ulint n;
...@@ -2640,8 +2609,6 @@ fseg_alloc_free_page_low( ...@@ -2640,8 +2609,6 @@ fseg_alloc_free_page_low(
if (descr == NULL) { if (descr == NULL) {
/* Hint outside space or too high above free limit: reset /* Hint outside space or too high above free limit: reset
hint */ hint */
ut_a(init_mtr);
/* The file space header page is always allocated. */
hint = 0; hint = 0;
descr = xdes_get_descriptor(space, zip_size, hint, mtr); descr = xdes_get_descriptor(space, zip_size, hint, mtr);
} }
...@@ -2652,20 +2619,15 @@ fseg_alloc_free_page_low( ...@@ -2652,20 +2619,15 @@ fseg_alloc_free_page_low(
&& mach_read_from_8(descr + XDES_ID) == seg_id && mach_read_from_8(descr + XDES_ID) == seg_id
&& (xdes_get_bit(descr, XDES_FREE_BIT, && (xdes_get_bit(descr, XDES_FREE_BIT,
hint % FSP_EXTENT_SIZE, mtr) == TRUE)) { hint % FSP_EXTENT_SIZE, mtr) == TRUE)) {
take_hinted_page:
/* 1. We can take the hinted page /* 1. We can take the hinted page
=================================*/ =================================*/
ret_descr = descr; ret_descr = descr;
ret_page = hint; ret_page = hint;
/* Skip the check for extending the tablespace. If the
page hint were not within the size of the tablespace,
we would have got (descr == NULL) above and reset the hint. */
goto got_hinted_page;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
} else if (xdes_get_state(descr, mtr) == XDES_FREE } else if ((xdes_get_state(descr, mtr) == XDES_FREE)
&& (!init_mtr && ((reserved - used) < reserved / FSEG_FILLFACTOR)
|| ((reserved - used < reserved / FSEG_FILLFACTOR) && (used >= FSEG_FRAG_LIMIT)) {
&& used >= FSEG_FRAG_LIMIT))) {
/* 2. We allocate the free extent from space and can take /* 2. We allocate the free extent from space and can take
========================================================= =========================================================
...@@ -2683,20 +2645,8 @@ fseg_alloc_free_page_low( ...@@ -2683,20 +2645,8 @@ fseg_alloc_free_page_low(
/* Try to fill the segment free list */ /* Try to fill the segment free list */
fseg_fill_free_list(seg_inode, space, zip_size, fseg_fill_free_list(seg_inode, space, zip_size,
hint + FSP_EXTENT_SIZE, mtr); hint + FSP_EXTENT_SIZE, mtr);
goto take_hinted_page;
/*-----------------------------------------------------------*/
} else if (!init_mtr) {
ut_a(xdes_get_state(descr, mtr) == XDES_FREE_FRAG);
fsp_alloc_from_free_frag(space_header, descr,
hint % FSP_EXTENT_SIZE, mtr);
ret_page = hint; ret_page = hint;
ret_descr = NULL; /*-----------------------------------------------------------*/
/* Put the page in the fragment page array of the segment */
n = fseg_find_free_frag_page_slot(seg_inode, mtr);
ut_a(n != FIL_NULL);
fseg_set_nth_frag_page_no(seg_inode, n, ret_page, mtr);
goto got_hinted_page;
} else if ((direction != FSP_NO_DIR) } else if ((direction != FSP_NO_DIR)
&& ((reserved - used) < reserved / FSEG_FILLFACTOR) && ((reserved - used) < reserved / FSEG_FILLFACTOR)
&& (used >= FSEG_FRAG_LIMIT) && (used >= FSEG_FRAG_LIMIT)
...@@ -2755,10 +2705,11 @@ fseg_alloc_free_page_low( ...@@ -2755,10 +2705,11 @@ fseg_alloc_free_page_low(
} else if (used < FSEG_FRAG_LIMIT) { } else if (used < FSEG_FRAG_LIMIT) {
/* 6. We allocate an individual page from the space /* 6. We allocate an individual page from the space
===================================================*/ ===================================================*/
ret_page = fsp_alloc_free_page(space, zip_size, hint, ret_page = fsp_alloc_free_page(space, zip_size, hint, mtr);
mtr, init_mtr);
ret_descr = NULL; ret_descr = NULL;
frag_page_allocated = TRUE;
if (ret_page != FIL_NULL) { if (ret_page != FIL_NULL) {
/* Put the page in the fragment page array of the /* Put the page in the fragment page array of the
segment */ segment */
...@@ -2768,10 +2719,6 @@ fseg_alloc_free_page_low( ...@@ -2768,10 +2719,6 @@ fseg_alloc_free_page_low(
fseg_set_nth_frag_page_no(seg_inode, n, ret_page, fseg_set_nth_frag_page_no(seg_inode, n, ret_page,
mtr); mtr);
} }
/* fsp_alloc_free_page() invoked fsp_init_file_page()
already. */
return(ret_page);
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
} else { } else {
/* 7. We allocate a new extent and take its first page /* 7. We allocate a new extent and take its first page
...@@ -2819,34 +2766,26 @@ fseg_alloc_free_page_low( ...@@ -2819,34 +2766,26 @@ fseg_alloc_free_page_low(
} }
} }
got_hinted_page: if (!frag_page_allocated) {
{
/* Initialize the allocated page to buffer pool, so that it /* Initialize the allocated page to buffer pool, so that it
can be obtained immediately with buf_page_get without need can be obtained immediately with buf_page_get without need
for a disk read */ for a disk read */
buf_block_t* block; buf_block_t* block;
ulint zip_size = dict_table_flags_to_zip_size( ulint zip_size = dict_table_flags_to_zip_size(
mach_read_from_4(FSP_SPACE_FLAGS + space_header)); mach_read_from_4(FSP_SPACE_FLAGS + space_header));
mtr_t* block_mtr = init_mtr ? init_mtr : mtr;
block = buf_page_create(space, ret_page, zip_size, block_mtr); block = buf_page_create(space, ret_page, zip_size, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE); buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
if (UNIV_UNLIKELY(block != buf_page_get(space, zip_size, if (UNIV_UNLIKELY(block != buf_page_get(space, zip_size,
ret_page, RW_X_LATCH, ret_page, RW_X_LATCH,
block_mtr))) { mtr))) {
ut_error; ut_error;
} }
if (init_mtr) {
/* The prior contents of the page should be ignored */ /* The prior contents of the page should be ignored */
fsp_init_file_page(block, init_mtr); fsp_init_file_page(block, mtr);
}
}
/* ret_descr == NULL if the block was allocated from free_frag
(XDES_FREE_FRAG) */
if (ret_descr != NULL) {
/* At this point we know the extent and the page offset. /* At this point we know the extent and the page offset.
The extent is still in the appropriate list (FSEG_NOT_FULL The extent is still in the appropriate list (FSEG_NOT_FULL
or FSEG_FREE), and the page is not yet marked as used. */ or FSEG_FREE), and the page is not yet marked as used. */
...@@ -2859,6 +2798,8 @@ fseg_alloc_free_page_low( ...@@ -2859,6 +2798,8 @@ fseg_alloc_free_page_low(
fseg_mark_page_used(seg_inode, space, zip_size, ret_page, mtr); fseg_mark_page_used(seg_inode, space, zip_size, ret_page, mtr);
} }
buf_reset_check_index_page_at_flush(space, ret_page);
return(ret_page); return(ret_page);
} }
...@@ -2871,7 +2812,7 @@ UNIV_INTERN ...@@ -2871,7 +2812,7 @@ UNIV_INTERN
ulint ulint
fseg_alloc_free_page_general( fseg_alloc_free_page_general(
/*=========================*/ /*=========================*/
fseg_header_t* seg_header,/*!< in/out: segment header */ fseg_header_t* seg_header,/*!< in: segment header */
ulint hint, /*!< in: hint of which page would be desirable */ ulint hint, /*!< in: hint of which page would be desirable */
byte direction,/*!< in: if the new page is needed because byte direction,/*!< in: if the new page is needed because
of an index page split, and records are of an index page split, and records are
...@@ -2883,11 +2824,7 @@ fseg_alloc_free_page_general( ...@@ -2883,11 +2824,7 @@ fseg_alloc_free_page_general(
with fsp_reserve_free_extents, then there with fsp_reserve_free_extents, then there
is no need to do the check for this individual is no need to do the check for this individual
page */ page */
mtr_t* mtr, /*!< in/out: mini-transaction handle */ mtr_t* mtr) /*!< in: mtr handle */
mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
in which the page should be initialized,
or NULL if this is a "fake allocation" of
a page that was previously freed in mtr */
{ {
fseg_inode_t* inode; fseg_inode_t* inode;
ulint space; ulint space;
...@@ -2929,8 +2866,7 @@ fseg_alloc_free_page_general( ...@@ -2929,8 +2866,7 @@ fseg_alloc_free_page_general(
} }
page_no = fseg_alloc_free_page_low(space, zip_size, page_no = fseg_alloc_free_page_low(space, zip_size,
inode, hint, direction, inode, hint, direction, mtr);
mtr, init_mtr);
if (!has_done_reservation) { if (!has_done_reservation) {
fil_space_release_free_extents(space, n_reserved); fil_space_release_free_extents(space, n_reserved);
} }
...@@ -2938,6 +2874,28 @@ fseg_alloc_free_page_general( ...@@ -2938,6 +2874,28 @@ fseg_alloc_free_page_general(
return(page_no); return(page_no);
} }
/**********************************************************************//**
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
fragmentation.
@return allocated page offset, FIL_NULL if no page could be allocated */
UNIV_INTERN
ulint
fseg_alloc_free_page(
/*=================*/
fseg_header_t* seg_header,/*!< in: segment header */
ulint hint, /*!< in: hint of which page would be desirable */
byte direction,/*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR */
mtr_t* mtr) /*!< in: mtr handle */
{
return(fseg_alloc_free_page_general(seg_header, hint, direction,
FALSE, mtr));
}
/**********************************************************************//** /**********************************************************************//**
Checks that we have at least 2 frag pages free in the first extent of a Checks that we have at least 2 frag pages free in the first extent of a
single-table tablespace, and they are also physically initialized to the data single-table tablespace, and they are also physically initialized to the data
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -499,14 +499,11 @@ UNIV_INTERN ...@@ -499,14 +499,11 @@ UNIV_INTERN
ibool ibool
btr_compress( btr_compress(
/*=========*/ /*=========*/
btr_cur_t* cursor, /*!< in/out: cursor on the page to merge btr_cur_t* cursor, /*!< in: cursor on the page to merge or lift;
or lift; the page must not be empty: the page must not be empty: in record delete
when deleting records, use btr_discard_page() use btr_discard_page if the page would become
if the page would become empty */ empty */
ibool adjust, /*!< in: TRUE if should adjust the mtr_t* mtr); /*!< in: mtr */
cursor position even if compression occurs */
mtr_t* mtr) /*!< in/out: mini-transaction */
__attribute__((nonnull));
/*************************************************************//** /*************************************************************//**
Discards a page from a B-tree. This is used to remove the last record from Discards a page from a B-tree. This is used to remove the last record from
a B-tree page: the whole page must be removed at the same time. This cannot a B-tree page: the whole page must be removed at the same time. This cannot
...@@ -568,12 +565,7 @@ btr_page_alloc( ...@@ -568,12 +565,7 @@ btr_page_alloc(
page split is made */ page split is made */
ulint level, /*!< in: level where the page is placed ulint level, /*!< in: level where the page is placed
in the tree */ in the tree */
mtr_t* mtr, /*!< in/out: mini-transaction mtr_t* mtr); /*!< in: mtr */
for the allocation */
mtr_t* init_mtr) /*!< in/out: mini-transaction
for x-latching and initializing
the page */
__attribute__((nonnull, warn_unused_result));
/**************************************************************//** /**************************************************************//**
Frees a file page used in an index tree. NOTE: cannot free field external Frees a file page used in an index tree. NOTE: cannot free field external
storage pages because the page must contain info on its level. */ storage pages because the page must contain info on its level. */
...@@ -596,33 +588,6 @@ btr_page_free_low( ...@@ -596,33 +588,6 @@ btr_page_free_low(
buf_block_t* block, /*!< in: block to be freed, x-latched */ buf_block_t* block, /*!< in: block to be freed, x-latched */
ulint level, /*!< in: page level */ ulint level, /*!< in: page level */
mtr_t* mtr); /*!< in: mtr */ mtr_t* mtr); /*!< in: mtr */
/**************************************************************//**
Marks all MTR_MEMO_FREE_CLUST_LEAF pages nonfree or free.
For invoking btr_store_big_rec_extern_fields() after an update,
we must temporarily mark freed clustered index pages allocated, so
that off-page columns will not be allocated from them. Between the
btr_store_big_rec_extern_fields() and mtr_commit() we have to
mark the pages free again, so that no pages will be leaked. */
UNIV_INTERN
void
btr_mark_freed_leaves(
/*==================*/
dict_index_t* index, /*!< in/out: clustered index */
mtr_t* mtr, /*!< in/out: mini-transaction */
ibool nonfree)/*!< in: TRUE=mark nonfree, FALSE=mark freed */
UNIV_COLD __attribute__((nonnull));
#ifdef UNIV_DEBUG
/**************************************************************//**
Validates all pages marked MTR_MEMO_FREE_CLUST_LEAF.
@see btr_mark_freed_leaves()
@return TRUE */
UNIV_INTERN
ibool
btr_freed_leaves_validate(
/*======================*/
mtr_t* mtr) /*!< in: mini-transaction */
__attribute__((nonnull, warn_unused_result));
#endif /* UNIV_DEBUG */
#ifdef UNIV_BTR_PRINT #ifdef UNIV_BTR_PRINT
/*************************************************************//** /*************************************************************//**
Prints size info of a B-tree. */ Prints size info of a B-tree. */
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -36,9 +36,6 @@ Created 10/16/1994 Heikki Tuuri ...@@ -36,9 +36,6 @@ Created 10/16/1994 Heikki Tuuri
#define BTR_NO_LOCKING_FLAG 2 /* do no record lock checking */ #define BTR_NO_LOCKING_FLAG 2 /* do no record lock checking */
#define BTR_KEEP_SYS_FLAG 4 /* sys fields will be found from the #define BTR_KEEP_SYS_FLAG 4 /* sys fields will be found from the
update vector or inserted entry */ update vector or inserted entry */
#define BTR_KEEP_POS_FLAG 8 /* btr_cur_pessimistic_update()
must keep cursor position when
moving columns to big_rec */
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
#include "que0types.h" #include "que0types.h"
...@@ -313,9 +310,7 @@ btr_cur_pessimistic_update( ...@@ -313,9 +310,7 @@ btr_cur_pessimistic_update(
/*=======================*/ /*=======================*/
ulint flags, /*!< in: undo logging, locking, and rollback ulint flags, /*!< in: undo logging, locking, and rollback
flags */ flags */
btr_cur_t* cursor, /*!< in/out: cursor on the record to update; btr_cur_t* cursor, /*!< in: cursor on the record to update */
cursor may become invalid if *big_rec == NULL
|| !(flags & BTR_KEEP_POS_FLAG) */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
be stored externally by the caller, or NULL */ be stored externally by the caller, or NULL */
...@@ -369,13 +364,10 @@ UNIV_INTERN ...@@ -369,13 +364,10 @@ UNIV_INTERN
ibool ibool
btr_cur_compress_if_useful( btr_cur_compress_if_useful(
/*=======================*/ /*=======================*/
btr_cur_t* cursor, /*!< in/out: cursor on the page to compress; btr_cur_t* cursor, /*!< in: cursor on the page to compress;
cursor does not stay valid if compression cursor does not stay valid if compression
occurs */ occurs */
ibool adjust, /*!< in: TRUE if should adjust the mtr_t* mtr); /*!< in: mtr */
cursor position even if compression occurs */
mtr_t* mtr) /*!< in/out: mini-transaction */
__attribute__((nonnull));
/*******************************************************//** /*******************************************************//**
Removes the record on which the tree cursor is positioned. It is assumed Removes the record on which the tree cursor is positioned. It is assumed
that the mtr has an x-latch on the page where the cursor is positioned, that the mtr has an x-latch on the page where the cursor is positioned,
...@@ -518,8 +510,6 @@ btr_store_big_rec_extern_fields_func( ...@@ -518,8 +510,6 @@ btr_store_big_rec_extern_fields_func(
the "external storage" flags in offsets the "external storage" flags in offsets
will not correspond to rec when will not correspond to rec when
this function returns */ this function returns */
const big_rec_t*big_rec_vec, /*!< in: vector containing fields
to be stored externally */
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
mtr_t* local_mtr, /*!< in: mtr containing the mtr_t* local_mtr, /*!< in: mtr containing the
latch to rec and to the tree */ latch to rec and to the tree */
...@@ -528,12 +518,9 @@ btr_store_big_rec_extern_fields_func( ...@@ -528,12 +518,9 @@ btr_store_big_rec_extern_fields_func(
ibool update_in_place,/*! in: TRUE if the record is updated ibool update_in_place,/*! in: TRUE if the record is updated
in place (not delete+insert) */ in place (not delete+insert) */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ #endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
mtr_t* alloc_mtr) /*!< in/out: in an insert, NULL; const big_rec_t*big_rec_vec) /*!< in: vector containing fields
in an update, local_mtr for to be stored externally */
allocating BLOB pages and __attribute__((nonnull));
updating BLOB pointers; alloc_mtr
must not have freed any leaf pages */
__attribute__((nonnull(1,2,3,4,5), warn_unused_result));
/** Stores the fields in big_rec_vec to the tablespace and puts pointers to /** Stores the fields in big_rec_vec to the tablespace and puts pointers to
them in rec. The extern flags in rec will have to be set beforehand. them in rec. The extern flags in rec will have to be set beforehand.
...@@ -542,22 +529,21 @@ file segment of the index tree. ...@@ -542,22 +529,21 @@ file segment of the index tree.
@param index in: clustered index; MUST be X-latched by mtr @param index in: clustered index; MUST be X-latched by mtr
@param b in/out: block containing rec; MUST be X-latched by mtr @param b in/out: block containing rec; MUST be X-latched by mtr
@param rec in/out: clustered index record @param rec in/out: clustered index record
@param offs in: rec_get_offsets(rec, index); @param offsets in: rec_get_offsets(rec, index);
the "external storage" flags in offsets will not be adjusted the "external storage" flags in offsets will not be adjusted
@param big in: vector containing fields to be stored externally
@param mtr in: mini-transaction that holds x-latch on index and b @param mtr in: mini-transaction that holds x-latch on index and b
@param upd in: TRUE if the record is updated in place (not delete+insert) @param upd in: TRUE if the record is updated in place (not delete+insert)
@param rmtr in/out: in updates, the mini-transaction that holds rec @param big in: vector containing fields to be stored externally
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
# define btr_store_big_rec_extern_fields(index,b,rec,offs,big,mtr,upd,rmtr) \ # define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
btr_store_big_rec_extern_fields_func(index,b,rec,offs,big,mtr,upd,rmtr) btr_store_big_rec_extern_fields_func(index,b,rec,offsets,mtr,upd,big)
#elif defined UNIV_BLOB_LIGHT_DEBUG #elif defined UNIV_BLOB_LIGHT_DEBUG
# define btr_store_big_rec_extern_fields(index,b,rec,offs,big,mtr,upd,rmtr) \ # define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
btr_store_big_rec_extern_fields_func(index,b,rec,offs,big,upd,rmtr) btr_store_big_rec_extern_fields_func(index,b,rec,offsets,upd,big)
#else #else
# define btr_store_big_rec_extern_fields(index,b,rec,offs,big,mtr,upd,rmtr) \ # define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
btr_store_big_rec_extern_fields_func(index,b,rec,offs,big,rmtr) btr_store_big_rec_extern_fields_func(index,b,rec,offsets,big)
#endif #endif
/*******************************************************************//** /*******************************************************************//**
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -139,7 +139,7 @@ btr_cur_compress_recommendation( ...@@ -139,7 +139,7 @@ btr_cur_compress_recommendation(
btr_cur_t* cursor, /*!< in: btr cursor */ btr_cur_t* cursor, /*!< in: btr cursor */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
{ {
const page_t* page; page_t* page;
ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
MTR_MEMO_PAGE_X_FIX)); MTR_MEMO_PAGE_X_FIX));
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -491,6 +491,15 @@ buf_page_peek( ...@@ -491,6 +491,15 @@ buf_page_peek(
/*==========*/ /*==========*/
ulint space, /*!< in: space id */ ulint space, /*!< in: space id */
ulint offset);/*!< in: page number */ ulint offset);/*!< in: page number */
/********************************************************************//**
Resets the check_index_page_at_flush field of a page if found in the buffer
pool. */
UNIV_INTERN
void
buf_reset_check_index_page_at_flush(
/*================================*/
ulint space, /*!< in: space id */
ulint offset);/*!< in: page number */
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
/********************************************************************//** /********************************************************************//**
Sets file_page_was_freed TRUE if the page is found in the buffer pool. Sets file_page_was_freed TRUE if the page is found in the buffer pool.
...@@ -600,31 +609,6 @@ buf_block_get_modify_clock( ...@@ -600,31 +609,6 @@ buf_block_get_modify_clock(
#else /* !UNIV_HOTBACKUP */ #else /* !UNIV_HOTBACKUP */
# define buf_block_modify_clock_inc(block) ((void) 0) # define buf_block_modify_clock_inc(block) ((void) 0)
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/*******************************************************************//**
Increments the bufferfix count. */
UNIV_INLINE
void
buf_block_buf_fix_inc_func(
/*=======================*/
#ifdef UNIV_SYNC_DEBUG
const char* file, /*!< in: file name */
ulint line, /*!< in: line */
#endif /* UNIV_SYNC_DEBUG */
buf_block_t* block) /*!< in/out: block to bufferfix */
__attribute__((nonnull));
#ifdef UNIV_SYNC_DEBUG
/** Increments the bufferfix count.
@param b in/out: block to bufferfix
@param f in: file name where requested
@param l in: line number where requested */
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
#else /* UNIV_SYNC_DEBUG */
/** Increments the bufferfix count.
@param b in/out: block to bufferfix
@param f in: file name where requested
@param l in: line number where requested */
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
#endif /* UNIV_SYNC_DEBUG */
/********************************************************************//** /********************************************************************//**
Calculates a page checksum which is stored to the page when it is written Calculates a page checksum which is stored to the page when it is written
to a file. Note that we must be careful to calculate the same value to a file. Note that we must be careful to calculate the same value
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, Google Inc. Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by Portions of this file contain modifications contributed and copyrighted by
...@@ -944,6 +944,19 @@ buf_block_buf_fix_inc_func( ...@@ -944,6 +944,19 @@ buf_block_buf_fix_inc_func(
block->page.buf_fix_count++; block->page.buf_fix_count++;
} }
#ifdef UNIV_SYNC_DEBUG
/** Increments the bufferfix count.
@param b in/out: block to bufferfix
@param f in: file name where requested
@param l in: line number where requested */
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
#else /* UNIV_SYNC_DEBUG */
/** Increments the bufferfix count.
@param b in/out: block to bufferfix
@param f in: file name where requested
@param l in: line number where requested */
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
#endif /* UNIV_SYNC_DEBUG */
/*******************************************************************//** /*******************************************************************//**
Decrements the bufferfix count. */ Decrements the bufferfix count. */
...@@ -1194,7 +1207,7 @@ buf_block_dbg_add_level( ...@@ -1194,7 +1207,7 @@ buf_block_dbg_add_level(
where we have acquired latch */ where we have acquired latch */
ulint level) /*!< in: latching order level */ ulint level) /*!< in: latching order level */
{ {
sync_thread_add_level(&block->lock, level, FALSE); sync_thread_add_level(&block->lock, level);
} }
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
/********************************************************************//** /********************************************************************//**
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -176,18 +176,19 @@ fseg_n_reserved_pages( ...@@ -176,18 +176,19 @@ fseg_n_reserved_pages(
Allocates a single free page from a segment. This function implements Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize the intelligent allocation strategy which tries to minimize
file space fragmentation. file space fragmentation.
@param[in/out] seg_header segment header @return the allocated page offset FIL_NULL if no page could be allocated */
@param[in] hint hint of which page would be desirable UNIV_INTERN
@param[in] direction if the new page is needed because ulint
fseg_alloc_free_page(
/*=================*/
fseg_header_t* seg_header, /*!< in: segment header */
ulint hint, /*!< in: hint of which page would be desirable */
byte direction, /*!< in: if the new page is needed because
of an index page split, and records are of an index page split, and records are
inserted there in order, into which inserted there in order, into which
direction they go alphabetically: FSP_DOWN, direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR FSP_UP, FSP_NO_DIR */
@param[in/out] mtr mini-transaction mtr_t* mtr); /*!< in: mtr handle */
@return the allocated page offset FIL_NULL if no page could be allocated */
#define fseg_alloc_free_page(seg_header, hint, direction, mtr) \
fseg_alloc_free_page_general(seg_header, hint, direction, \
FALSE, mtr, mtr)
/**********************************************************************//** /**********************************************************************//**
Allocates a single free page from a segment. This function implements Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space the intelligent allocation strategy which tries to minimize file space
...@@ -197,7 +198,7 @@ UNIV_INTERN ...@@ -197,7 +198,7 @@ UNIV_INTERN
ulint ulint
fseg_alloc_free_page_general( fseg_alloc_free_page_general(
/*=========================*/ /*=========================*/
fseg_header_t* seg_header,/*!< in/out: segment header */ fseg_header_t* seg_header,/*!< in: segment header */
ulint hint, /*!< in: hint of which page would be desirable */ ulint hint, /*!< in: hint of which page would be desirable */
byte direction,/*!< in: if the new page is needed because byte direction,/*!< in: if the new page is needed because
of an index page split, and records are of an index page split, and records are
...@@ -209,12 +210,7 @@ fseg_alloc_free_page_general( ...@@ -209,12 +210,7 @@ fseg_alloc_free_page_general(
with fsp_reserve_free_extents, then there with fsp_reserve_free_extents, then there
is no need to do the check for this individual is no need to do the check for this individual
page */ page */
mtr_t* mtr, /*!< in/out: mini-transaction */ mtr_t* mtr); /*!< in: mtr handle */
mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
in which the page should be initialized,
or NULL if this is a "fake allocation" of
a page that was previously freed in mtr */
__attribute__((warn_unused_result, nonnull(1,5)));
/**********************************************************************//** /**********************************************************************//**
Reserves free pages from a tablespace. All mini-transactions which may Reserves free pages from a tablespace. All mini-transactions which may
use several pages from the tablespace should call this function beforehand use several pages from the tablespace should call this function beforehand
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -53,8 +53,6 @@ first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */ ...@@ -53,8 +53,6 @@ first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
#define MTR_MEMO_MODIFY 54 #define MTR_MEMO_MODIFY 54
#define MTR_MEMO_S_LOCK 55 #define MTR_MEMO_S_LOCK 55
#define MTR_MEMO_X_LOCK 56 #define MTR_MEMO_X_LOCK 56
/** The mini-transaction freed a clustered index leaf page. */
#define MTR_MEMO_FREE_CLUST_LEAF 57
/** @name Log item types /** @name Log item types
The log items are declared 'byte' so that the compiler can warn if val The log items are declared 'byte' so that the compiler can warn if val
...@@ -370,14 +368,11 @@ struct mtr_struct{ ...@@ -370,14 +368,11 @@ struct mtr_struct{
#endif #endif
dyn_array_t memo; /*!< memo stack for locks etc. */ dyn_array_t memo; /*!< memo stack for locks etc. */
dyn_array_t log; /*!< mini-transaction log */ dyn_array_t log; /*!< mini-transaction log */
unsigned inside_ibuf:1; ibool inside_ibuf;
/*!< TRUE if inside ibuf changes */ /*!< TRUE if inside ibuf changes */
unsigned modifications:1; ibool modifications;
/*!< TRUE if the mini-transaction /* TRUE if the mtr made modifications to
modified buffer pool pages */ buffer pool pages */
unsigned freed_clust_leaf:1;
/*!< TRUE if MTR_MEMO_FREE_CLUST_LEAF
was logged in the mini-transaction */
ulint n_log_recs; ulint n_log_recs;
/* count of how many page initial log records /* count of how many page initial log records
have been written to the mtr log */ have been written to the mtr log */
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -43,9 +43,8 @@ mtr_start( ...@@ -43,9 +43,8 @@ mtr_start(
dyn_array_create(&(mtr->log)); dyn_array_create(&(mtr->log));
mtr->log_mode = MTR_LOG_ALL; mtr->log_mode = MTR_LOG_ALL;
mtr->inside_ibuf = FALSE;
mtr->modifications = FALSE; mtr->modifications = FALSE;
mtr->freed_clust_leaf = FALSE; mtr->inside_ibuf = FALSE;
mtr->n_log_recs = 0; mtr->n_log_recs = 0;
ut_d(mtr->state = MTR_ACTIVE); ut_d(mtr->state = MTR_ACTIVE);
...@@ -67,8 +66,7 @@ mtr_memo_push( ...@@ -67,8 +66,7 @@ mtr_memo_push(
ut_ad(object); ut_ad(object);
ut_ad(type >= MTR_MEMO_PAGE_S_FIX); ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
ut_ad(type <= MTR_MEMO_FREE_CLUST_LEAF); ut_ad(type <= MTR_MEMO_X_LOCK);
ut_ad(type != MTR_MEMO_FREE_CLUST_LEAF || mtr->freed_clust_leaf);
ut_ad(mtr); ut_ad(mtr);
ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->magic_n == MTR_MAGIC_N);
ut_ad(mtr->state == MTR_ACTIVE); ut_ad(mtr->state == MTR_ACTIVE);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -27,8 +27,6 @@ Created 10/4/1994 Heikki Tuuri ...@@ -27,8 +27,6 @@ Created 10/4/1994 Heikki Tuuri
#include "buf0types.h" #include "buf0types.h"
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
# include "rem0cmp.h"
/*********************************************************//** /*********************************************************//**
Gets pointer to the page frame where the cursor is positioned. Gets pointer to the page frame where the cursor is positioned.
@return page */ @return page */
...@@ -270,7 +268,6 @@ page_cur_tuple_insert( ...@@ -270,7 +268,6 @@ page_cur_tuple_insert(
index, rec, offsets, mtr); index, rec, offsets, mtr);
} }
ut_ad(!rec || !cmp_dtuple_rec(tuple, rec, offsets));
mem_heap_free(heap); mem_heap_free(heap);
return(rec); return(rec);
} }
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -281,42 +281,16 @@ page_get_supremum_offset( ...@@ -281,42 +281,16 @@ page_get_supremum_offset(
const page_t* page); /*!< in: page which must have record(s) */ const page_t* page); /*!< in: page which must have record(s) */
#define page_get_infimum_rec(page) ((page) + page_get_infimum_offset(page)) #define page_get_infimum_rec(page) ((page) + page_get_infimum_offset(page))
#define page_get_supremum_rec(page) ((page) + page_get_supremum_offset(page)) #define page_get_supremum_rec(page) ((page) + page_get_supremum_offset(page))
/************************************************************//**
Returns the nth record of the record list.
This is the inverse function of page_rec_get_n_recs_before().
@return nth record */
UNIV_INTERN
const rec_t*
page_rec_get_nth_const(
/*===================*/
const page_t* page, /*!< in: page */
ulint nth) /*!< in: nth record */
__attribute__((nonnull, warn_unused_result));
/************************************************************//** /************************************************************//**
Returns the nth record of the record list. Returns the middle record of record list. If there are an even number
This is the inverse function of page_rec_get_n_recs_before(). of records in the list, returns the first record of upper half-list.
@return nth record */
UNIV_INLINE
rec_t*
page_rec_get_nth(
/*=============*/
page_t* page, /*< in: page */
ulint nth) /*!< in: nth record */
__attribute__((nonnull, warn_unused_result));
#ifndef UNIV_HOTBACKUP
/************************************************************//**
Returns the middle record of the records on the page. If there is an
even number of records in the list, returns the first record of the
upper half-list.
@return middle record */ @return middle record */
UNIV_INLINE UNIV_INTERN
rec_t* rec_t*
page_get_middle_rec( page_get_middle_rec(
/*================*/ /*================*/
page_t* page) /*!< in: page */ page_t* page); /*!< in: page */
__attribute__((nonnull, warn_unused_result)); #ifndef UNIV_HOTBACKUP
/*************************************************************//** /*************************************************************//**
Compares a data tuple to a physical record. Differs from the function Compares a data tuple to a physical record. Differs from the function
cmp_dtuple_rec_with_match in the way that the record must reside on an cmp_dtuple_rec_with_match in the way that the record must reside on an
...@@ -371,7 +345,6 @@ page_get_n_recs( ...@@ -371,7 +345,6 @@ page_get_n_recs(
/***************************************************************//** /***************************************************************//**
Returns the number of records before the given record in chain. Returns the number of records before the given record in chain.
The number includes infimum and supremum records. The number includes infimum and supremum records.
This is the inverse function of page_rec_get_nth().
@return number of records */ @return number of records */
UNIV_INTERN UNIV_INTERN
ulint ulint
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -419,37 +419,7 @@ page_rec_is_infimum( ...@@ -419,37 +419,7 @@ page_rec_is_infimum(
return(page_rec_is_infimum_low(page_offset(rec))); return(page_rec_is_infimum_low(page_offset(rec)));
} }
/************************************************************//**
Returns the nth record of the record list.
This is the inverse function of page_rec_get_n_recs_before().
@return nth record */
UNIV_INLINE
rec_t*
page_rec_get_nth(
/*=============*/
page_t* page, /*!< in: page */
ulint nth) /*!< in: nth record */
{
return((rec_t*) page_rec_get_nth_const(page, nth));
}
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
/************************************************************//**
Returns the middle record of the records on the page. If there is an
even number of records in the list, returns the first record of the
upper half-list.
@return middle record */
UNIV_INLINE
rec_t*
page_get_middle_rec(
/*================*/
page_t* page) /*!< in: page */
{
ulint middle = (page_get_n_recs(page) + PAGE_HEAP_NO_USER_LOW) / 2;
return(page_rec_get_nth(page, middle));
}
/*************************************************************//** /*************************************************************//**
Compares a data tuple to a physical record. Differs from the function Compares a data tuple to a physical record. Differs from the function
cmp_dtuple_rec_with_match in the way that the record must reside on an cmp_dtuple_rec_with_match in the way that the record must reside on an
......
...@@ -480,7 +480,7 @@ ulint ...@@ -480,7 +480,7 @@ ulint
rec_offs_any_extern( rec_offs_any_extern(
/*================*/ /*================*/
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */ const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG #ifdef UNIV_BLOB_NULL_DEBUG
/******************************************************//** /******************************************************//**
Determine if the offsets are for a record containing null BLOB pointers. Determine if the offsets are for a record containing null BLOB pointers.
@return first field containing a null BLOB pointer, or NULL if none found */ @return first field containing a null BLOB pointer, or NULL if none found */
...@@ -491,7 +491,7 @@ rec_offs_any_null_extern( ...@@ -491,7 +491,7 @@ rec_offs_any_null_extern(
const rec_t* rec, /*!< in: record */ const rec_t* rec, /*!< in: record */
const ulint* offsets) /*!< in: rec_get_offsets(rec) */ const ulint* offsets) /*!< in: rec_get_offsets(rec) */
__attribute__((nonnull, warn_unused_result)); __attribute__((nonnull, warn_unused_result));
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ #endif /* UNIV_BLOB_NULL_DEBUG */
/******************************************************//** /******************************************************//**
Returns nonzero if the extern bit is set in nth field of rec. Returns nonzero if the extern bit is set in nth field of rec.
@return nonzero if externally stored */ @return nonzero if externally stored */
......
...@@ -1088,7 +1088,7 @@ rec_offs_any_extern( ...@@ -1088,7 +1088,7 @@ rec_offs_any_extern(
return(UNIV_UNLIKELY(*rec_offs_base(offsets) & REC_OFFS_EXTERNAL)); return(UNIV_UNLIKELY(*rec_offs_base(offsets) & REC_OFFS_EXTERNAL));
} }
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG #ifdef UNIV_BLOB_NULL_DEBUG
/******************************************************//** /******************************************************//**
Determine if the offsets are for a record containing null BLOB pointers. Determine if the offsets are for a record containing null BLOB pointers.
@return first field containing a null BLOB pointer, or NULL if none found */ @return first field containing a null BLOB pointer, or NULL if none found */
...@@ -1124,7 +1124,7 @@ rec_offs_any_null_extern( ...@@ -1124,7 +1124,7 @@ rec_offs_any_null_extern(
return(NULL); return(NULL);
} }
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ #endif /* UNIV_BLOB_NULL_DEBUG */
/******************************************************//** /******************************************************//**
Returns nonzero if the extern bit is set in nth field of rec. Returns nonzero if the extern bit is set in nth field of rec.
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, Google Inc. Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by Portions of this file contain modifications contributed and copyrighted by
...@@ -603,16 +603,16 @@ rw_lock_x_unlock_direct( ...@@ -603,16 +603,16 @@ rw_lock_x_unlock_direct(
ut_ad((lock->lock_word % X_LOCK_DECR) == 0); ut_ad((lock->lock_word % X_LOCK_DECR) == 0);
#ifdef UNIV_SYNC_DEBUG
rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
#endif
if (lock->lock_word == 0) { if (lock->lock_word == 0) {
lock->recursive = FALSE; lock->recursive = FALSE;
UNIV_MEM_INVALID(&lock->writer_thread, UNIV_MEM_INVALID(&lock->writer_thread,
sizeof lock->writer_thread); sizeof lock->writer_thread);
} }
#ifdef UNIV_SYNC_DEBUG
rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
#endif
lock->lock_word += X_LOCK_DECR; lock->lock_word += X_LOCK_DECR;
ut_ad(!lock->waiters); ut_ad(!lock->waiters);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, Google Inc. Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by Portions of this file contain modifications contributed and copyrighted by
...@@ -400,10 +400,8 @@ void ...@@ -400,10 +400,8 @@ void
sync_thread_add_level( sync_thread_add_level(
/*==================*/ /*==================*/
void* latch, /*!< in: pointer to a mutex or an rw-lock */ void* latch, /*!< in: pointer to a mutex or an rw-lock */
ulint level, /*!< in: level in the latching order; if ulint level); /*!< in: level in the latching order; if
SYNC_LEVEL_VARYING, nothing is done */ SYNC_LEVEL_VARYING, nothing is done */
ibool relock) /*!< in: TRUE if re-entering an x-lock */
__attribute__((nonnull));
/******************************************************************//** /******************************************************************//**
Removes a latch from the thread level array if it is found there. Removes a latch from the thread level array if it is found there.
@return TRUE if found in the array; it is no error if the latch is @return TRUE if found in the array; it is no error if the latch is
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, Google Inc. Copyright (c) 2008, Google Inc.
Copyright (c) 2009, Sun Microsystems, Inc.
Portions of this file contain modifications contributed and copyrighted by Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described Google, Inc. Those modifications are gratefully acknowledged and are described
...@@ -185,6 +186,8 @@ command. Not tested on Windows. */ ...@@ -185,6 +186,8 @@ command. Not tested on Windows. */
debugging without UNIV_DEBUG */ debugging without UNIV_DEBUG */
#define UNIV_BLOB_LIGHT_DEBUG /* Enable off-page column #define UNIV_BLOB_LIGHT_DEBUG /* Enable off-page column
debugging without UNIV_DEBUG */ debugging without UNIV_DEBUG */
#define UNIV_BLOB_NULL_DEBUG /* Enable deep off-page
column debugging */
#define UNIV_DEBUG /* Enable ut_ad() assertions #define UNIV_DEBUG /* Enable ut_ad() assertions
and disable UNIV_INLINE */ and disable UNIV_INLINE */
#define UNIV_DEBUG_LOCK_VALIDATE /* Enable #define UNIV_DEBUG_LOCK_VALIDATE /* Enable
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -64,11 +64,12 @@ mtr_memo_slot_release( ...@@ -64,11 +64,12 @@ mtr_memo_slot_release(
buf_page_release((buf_block_t*)object, type); buf_page_release((buf_block_t*)object, type);
} else if (type == MTR_MEMO_S_LOCK) { } else if (type == MTR_MEMO_S_LOCK) {
rw_lock_s_unlock((rw_lock_t*)object); rw_lock_s_unlock((rw_lock_t*)object);
#ifdef UNIV_DEBUG
} else if (type != MTR_MEMO_X_LOCK) { } else if (type != MTR_MEMO_X_LOCK) {
ut_ad(type == MTR_MEMO_MODIFY ut_ad(type == MTR_MEMO_MODIFY);
|| type == MTR_MEMO_FREE_CLUST_LEAF);
ut_ad(mtr_memo_contains(mtr, object, ut_ad(mtr_memo_contains(mtr, object,
MTR_MEMO_PAGE_X_FIX)); MTR_MEMO_PAGE_X_FIX));
#endif /* UNIV_DEBUG */
} else { } else {
rw_lock_x_unlock((rw_lock_t*)object); rw_lock_x_unlock((rw_lock_t*)object);
} }
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -1180,15 +1180,14 @@ page_cur_insert_rec_zip_reorg( ...@@ -1180,15 +1180,14 @@ page_cur_insert_rec_zip_reorg(
/* Before trying to reorganize the page, /* Before trying to reorganize the page,
store the number of preceding records on the page. */ store the number of preceding records on the page. */
pos = page_rec_get_n_recs_before(rec); pos = page_rec_get_n_recs_before(rec);
ut_ad(pos > 0);
if (page_zip_reorganize(block, index, mtr)) { if (page_zip_reorganize(block, index, mtr)) {
/* The page was reorganized: Find rec by seeking to pos, /* The page was reorganized: Find rec by seeking to pos,
and update *current_rec. */ and update *current_rec. */
if (pos > 1) {
rec = page_rec_get_nth(page, pos - 1);
} else {
rec = page + PAGE_NEW_INFIMUM; rec = page + PAGE_NEW_INFIMUM;
while (--pos) {
rec = page + rec_get_next_offs(rec, TRUE);
} }
*current_rec = rec; *current_rec = rec;
...@@ -1284,12 +1283,6 @@ page_cur_insert_rec_zip( ...@@ -1284,12 +1283,6 @@ page_cur_insert_rec_zip(
insert_rec = page_cur_insert_rec_zip_reorg( insert_rec = page_cur_insert_rec_zip_reorg(
current_rec, block, index, insert_rec, current_rec, block, index, insert_rec,
page, page_zip, mtr); page, page_zip, mtr);
#ifdef UNIV_DEBUG
if (insert_rec) {
rec_offs_make_valid(
insert_rec, index, offsets);
}
#endif /* UNIV_DEBUG */
} }
return(insert_rec); return(insert_rec);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -1465,54 +1465,55 @@ page_dir_balance_slot( ...@@ -1465,54 +1465,55 @@ page_dir_balance_slot(
} }
} }
#ifndef UNIV_HOTBACKUP
/************************************************************//** /************************************************************//**
Returns the nth record of the record list. Returns the middle record of the record list. If there are an even number
This is the inverse function of page_rec_get_n_recs_before(). of records in the list, returns the first record of the upper half-list.
@return nth record */ @return middle record */
UNIV_INTERN UNIV_INTERN
const rec_t* rec_t*
page_rec_get_nth_const( page_get_middle_rec(
/*===================*/ /*================*/
const page_t* page, /*!< in: page */ page_t* page) /*!< in: page */
ulint nth) /*!< in: nth record */
{ {
const page_dir_slot_t* slot; page_dir_slot_t* slot;
ulint middle;
ulint i; ulint i;
ulint n_owned; ulint n_owned;
const rec_t* rec; ulint count;
rec_t* rec;
ut_ad(nth < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1)); /* This many records we must leave behind */
middle = (page_get_n_recs(page) + PAGE_HEAP_NO_USER_LOW) / 2;
count = 0;
for (i = 0;; i++) { for (i = 0;; i++) {
slot = page_dir_get_nth_slot(page, i); slot = page_dir_get_nth_slot(page, i);
n_owned = page_dir_slot_get_n_owned(slot); n_owned = page_dir_slot_get_n_owned(slot);
if (n_owned > nth) { if (count + n_owned > middle) {
break; break;
} else { } else {
nth -= n_owned; count += n_owned;
} }
} }
ut_ad(i > 0); ut_ad(i > 0);
slot = page_dir_get_nth_slot(page, i - 1); slot = page_dir_get_nth_slot(page, i - 1);
rec = page_dir_slot_get_rec(slot); rec = (rec_t*) page_dir_slot_get_rec(slot);
rec = page_rec_get_next(rec);
if (page_is_comp(page)) { /* There are now count records behind rec */
do {
rec = page_rec_get_next_low(rec, TRUE); for (i = 0; i < middle - count; i++) {
ut_ad(rec); rec = page_rec_get_next(rec);
} while (nth--);
} else {
do {
rec = page_rec_get_next_low(rec, FALSE);
ut_ad(rec);
} while (nth--);
} }
return(rec); return(rec);
} }
#endif /* !UNIV_HOTBACKUP */
/***************************************************************//** /***************************************************************//**
Returns the number of records before the given record in chain. Returns the number of records before the given record in chain.
...@@ -1574,7 +1575,6 @@ page_rec_get_n_recs_before( ...@@ -1574,7 +1575,6 @@ page_rec_get_n_recs_before(
n--; n--;
ut_ad(n >= 0); ut_ad(n >= 0);
ut_ad(n < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1));
return((ulint) n); return((ulint) n);
} }
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -348,8 +348,8 @@ row_ins_clust_index_entry_by_modify( ...@@ -348,8 +348,8 @@ row_ins_clust_index_entry_by_modify(
return(DB_LOCK_TABLE_FULL); return(DB_LOCK_TABLE_FULL);
} }
err = btr_cur_pessimistic_update( err = btr_cur_pessimistic_update(0, cursor,
BTR_KEEP_POS_FLAG, cursor, heap, big_rec, update, heap, big_rec, update,
0, thr, mtr); 0, thr, mtr);
} }
...@@ -1976,7 +1976,6 @@ row_ins_index_entry_low( ...@@ -1976,7 +1976,6 @@ row_ins_index_entry_low(
ulint modify = 0; /* remove warning */ ulint modify = 0; /* remove warning */
rec_t* insert_rec; rec_t* insert_rec;
rec_t* rec; rec_t* rec;
ulint* offsets;
ulint err; ulint err;
ulint n_unique; ulint n_unique;
big_rec_t* big_rec = NULL; big_rec_t* big_rec = NULL;
...@@ -2084,51 +2083,6 @@ row_ins_index_entry_low( ...@@ -2084,51 +2083,6 @@ row_ins_index_entry_low(
err = row_ins_clust_index_entry_by_modify( err = row_ins_clust_index_entry_by_modify(
mode, &cursor, &heap, &big_rec, entry, mode, &cursor, &heap, &big_rec, entry,
thr, &mtr); thr, &mtr);
if (big_rec) {
ut_a(err == DB_SUCCESS);
/* Write out the externally stored
columns, but allocate the pages and
write the pointers using the
mini-transaction of the record update.
If any pages were freed in the update,
temporarily mark them allocated so
that off-page columns will not
overwrite them. We must do this,
because we will write the redo log for
the BLOB writes before writing the
redo log for the record update. Thus,
redo log application at crash recovery
will see BLOBs being written to free pages. */
btr_mark_freed_leaves(index, &mtr, TRUE);
rec = btr_cur_get_rec(&cursor);
offsets = rec_get_offsets(
rec, index, NULL,
ULINT_UNDEFINED, &heap);
err = btr_store_big_rec_extern_fields(
index, btr_cur_get_block(&cursor),
rec, offsets, big_rec, &mtr,
FALSE, &mtr);
/* If writing big_rec fails (for
example, because of DB_OUT_OF_FILE_SPACE),
the record will be corrupted. Even if
we did not update any externally
stored columns, our update could cause
the record to grow so that a
non-updated column was selected for
external storage. This non-update
would not have been written to the
undo log, and thus the record cannot
be rolled back. */
ut_a(err == DB_SUCCESS);
/* Free the pages again
in order to avoid a leak. */
btr_mark_freed_leaves(index, &mtr, FALSE);
goto stored_big_rec;
}
} else { } else {
ut_ad(!n_ext); ut_ad(!n_ext);
err = row_ins_sec_index_entry_by_modify( err = row_ins_sec_index_entry_by_modify(
...@@ -2157,6 +2111,8 @@ row_ins_index_entry_low( ...@@ -2157,6 +2111,8 @@ row_ins_index_entry_low(
mtr_commit(&mtr); mtr_commit(&mtr);
if (UNIV_LIKELY_NULL(big_rec)) { if (UNIV_LIKELY_NULL(big_rec)) {
rec_t* rec;
ulint* offsets;
mtr_start(&mtr); mtr_start(&mtr);
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
...@@ -2168,9 +2124,8 @@ row_ins_index_entry_low( ...@@ -2168,9 +2124,8 @@ row_ins_index_entry_low(
err = btr_store_big_rec_extern_fields( err = btr_store_big_rec_extern_fields(
index, btr_cur_get_block(&cursor), index, btr_cur_get_block(&cursor),
rec, offsets, big_rec, &mtr, FALSE, NULL); rec, offsets, &mtr, FALSE, big_rec);
stored_big_rec:
if (modify) { if (modify) {
dtuple_big_rec_free(big_rec); dtuple_big_rec_free(big_rec);
} else { } else {
...@@ -2443,7 +2398,7 @@ row_ins( ...@@ -2443,7 +2398,7 @@ row_ins(
node->index = dict_table_get_next_index(node->index); node->index = dict_table_get_next_index(node->index);
node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry); node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry);
/* Skip corrupted secondary index and its entry */ /* Skip corrupted secondar index and its entry */
while (node->index && dict_index_is_corrupted(node->index)) { while (node->index && dict_index_is_corrupted(node->index)) {
node->index = dict_table_get_next_index(node->index); node->index = dict_table_get_next_index(node->index);
......
...@@ -233,7 +233,6 @@ row_build( ...@@ -233,7 +233,6 @@ row_build(
ut_ad(index && rec && heap); ut_ad(index && rec && heap);
ut_ad(dict_index_is_clust(index)); ut_ad(dict_index_is_clust(index));
ut_ad(!mutex_own(&kernel_mutex));
if (!offsets) { if (!offsets) {
offsets = rec_get_offsets(rec, index, offsets_, offsets = rec_get_offsets(rec, index, offsets_,
...@@ -242,22 +241,13 @@ row_build( ...@@ -242,22 +241,13 @@ row_build(
ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_validate(rec, index, offsets));
} }
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG #if 0 && defined UNIV_BLOB_NULL_DEBUG
if (rec_offs_any_null_extern(rec, offsets)) { /* This one can fail in trx_rollback_active() if
/* This condition can occur during crash recovery the server crashed during an insert before the
before trx_rollback_active() has completed execution. btr_store_big_rec_extern_fields() did mtr_commit()
all BLOB pointers to the clustered index record. */
This condition is possible if the server crashed ut_a(!rec_offs_any_null_extern(rec, offsets));
during an insert or update-by-delete-and-insert before #endif /* 0 && UNIV_BLOB_NULL_DEBUG */
btr_store_big_rec_extern_fields() did mtr_commit() all
BLOB pointers to the freshly inserted clustered index
record. */
ut_a(trx_assert_recovered(
row_get_rec_trx_id(rec, index, offsets)));
ut_a(trx_undo_roll_ptr_is_insert(
row_get_rec_roll_ptr(rec, index, offsets)));
}
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
if (type != ROW_COPY_POINTERS) { if (type != ROW_COPY_POINTERS) {
/* Take a copy of rec to heap */ /* Take a copy of rec to heap */
...@@ -442,10 +432,10 @@ row_rec_to_index_entry( ...@@ -442,10 +432,10 @@ row_rec_to_index_entry(
rec = rec_copy(buf, rec, offsets); rec = rec_copy(buf, rec, offsets);
/* Avoid a debug assertion in rec_offs_validate(). */ /* Avoid a debug assertion in rec_offs_validate(). */
rec_offs_make_valid(rec, index, offsets); rec_offs_make_valid(rec, index, offsets);
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG #ifdef UNIV_BLOB_NULL_DEBUG
} else { } else {
ut_a(!rec_offs_any_null_extern(rec, offsets)); ut_a(!rec_offs_any_null_extern(rec, offsets));
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ #endif /* UNIV_BLOB_NULL_DEBUG */
} }
entry = row_rec_to_index_entry_low(rec, index, offsets, n_ext, heap); entry = row_rec_to_index_entry_low(rec, index, offsets, n_ext, heap);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -1999,45 +1999,27 @@ row_upd_clust_rec( ...@@ -1999,45 +1999,27 @@ row_upd_clust_rec(
ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur), ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
dict_table_is_comp(index->table))); dict_table_is_comp(index->table)));
err = btr_cur_pessimistic_update( err = btr_cur_pessimistic_update(BTR_NO_LOCKING_FLAG, btr_cur,
BTR_NO_LOCKING_FLAG | BTR_KEEP_POS_FLAG, btr_cur, &heap, &big_rec, node->update,
&heap, &big_rec, node->update, node->cmpl_info, thr, mtr); node->cmpl_info, thr, mtr);
if (big_rec) { mtr_commit(mtr);
if (err == DB_SUCCESS && big_rec) {
ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint offsets_[REC_OFFS_NORMAL_SIZE];
rec_t* rec; rec_t* rec;
rec_offs_init(offsets_); rec_offs_init(offsets_);
ut_a(err == DB_SUCCESS); mtr_start(mtr);
/* Write out the externally stored columns, but
allocate the pages and write the pointers using the ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
mini-transaction of the record update. If any pages
were freed in the update, temporarily mark them
allocated so that off-page columns will not overwrite
them. We must do this, because we write the redo log
for the BLOB writes before writing the redo log for
the record update. */
btr_mark_freed_leaves(index, mtr, TRUE);
rec = btr_cur_get_rec(btr_cur); rec = btr_cur_get_rec(btr_cur);
err = btr_store_big_rec_extern_fields( err = btr_store_big_rec_extern_fields(
index, btr_cur_get_block(btr_cur), rec, index, btr_cur_get_block(btr_cur), rec,
rec_get_offsets(rec, index, offsets_, rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap), ULINT_UNDEFINED, &heap),
big_rec, mtr, TRUE, mtr); mtr, TRUE, big_rec);
/* If writing big_rec fails (for example, because of
DB_OUT_OF_FILE_SPACE), the record will be corrupted.
Even if we did not update any externally stored
columns, our update could cause the record to grow so
that a non-updated column was selected for external
storage. This non-update would not have been written
to the undo log, and thus the record cannot be rolled
back. */
ut_a(err == DB_SUCCESS);
/* Free the pages again in order to avoid a leak. */
btr_mark_freed_leaves(index, mtr, FALSE);
}
mtr_commit(mtr); mtr_commit(mtr);
}
if (UNIV_LIKELY_NULL(heap)) { if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap); mem_heap_free(heap);
......
...@@ -550,10 +550,10 @@ row_vers_build_for_consistent_read( ...@@ -550,10 +550,10 @@ row_vers_build_for_consistent_read(
/* The view already sees this version: we can /* The view already sees this version: we can
copy it to in_heap and return */ copy it to in_heap and return */
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG #ifdef UNIV_BLOB_NULL_DEBUG
ut_a(!rec_offs_any_null_extern( ut_a(!rec_offs_any_null_extern(
version, *offsets)); version, *offsets));
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ #endif /* UNIV_BLOB_NULL_DEBUG */
buf = mem_heap_alloc(in_heap, buf = mem_heap_alloc(in_heap,
rec_offs_size(*offsets)); rec_offs_size(*offsets));
...@@ -588,9 +588,9 @@ row_vers_build_for_consistent_read( ...@@ -588,9 +588,9 @@ row_vers_build_for_consistent_read(
*offsets = rec_get_offsets(prev_version, index, *offsets, *offsets = rec_get_offsets(prev_version, index, *offsets,
ULINT_UNDEFINED, offset_heap); ULINT_UNDEFINED, offset_heap);
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG #ifdef UNIV_BLOB_NULL_DEBUG
ut_a(!rec_offs_any_null_extern(prev_version, *offsets)); ut_a(!rec_offs_any_null_extern(prev_version, *offsets));
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ #endif /* UNIV_BLOB_NULL_DEBUG */
trx_id = row_get_rec_trx_id(prev_version, index, *offsets); trx_id = row_get_rec_trx_id(prev_version, index, *offsets);
...@@ -691,9 +691,9 @@ row_vers_build_for_semi_consistent_read( ...@@ -691,9 +691,9 @@ row_vers_build_for_semi_consistent_read(
/* We found a version that belongs to a /* We found a version that belongs to a
committed transaction: return it. */ committed transaction: return it. */
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG #ifdef UNIV_BLOB_NULL_DEBUG
ut_a(!rec_offs_any_null_extern(version, *offsets)); ut_a(!rec_offs_any_null_extern(version, *offsets));
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ #endif /* UNIV_BLOB_NULL_DEBUG */
if (rec == version) { if (rec == version) {
*old_vers = rec; *old_vers = rec;
...@@ -752,9 +752,9 @@ row_vers_build_for_semi_consistent_read( ...@@ -752,9 +752,9 @@ row_vers_build_for_semi_consistent_read(
version = prev_version; version = prev_version;
*offsets = rec_get_offsets(version, index, *offsets, *offsets = rec_get_offsets(version, index, *offsets,
ULINT_UNDEFINED, offset_heap); ULINT_UNDEFINED, offset_heap);
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG #ifdef UNIV_BLOB_NULL_DEBUG
ut_a(!rec_offs_any_null_extern(version, *offsets)); ut_a(!rec_offs_any_null_extern(version, *offsets));
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ #endif /* UNIV_BLOB_NULL_DEBUG */
}/* for (;;) */ }/* for (;;) */
if (heap) { if (heap) {
......
...@@ -782,9 +782,7 @@ rw_lock_add_debug_info( ...@@ -782,9 +782,7 @@ rw_lock_add_debug_info(
rw_lock_debug_mutex_exit(); rw_lock_debug_mutex_exit();
if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) { if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) {
sync_thread_add_level(lock, lock->level, sync_thread_add_level(lock, lock->level);
lock_type == RW_LOCK_EX
&& lock->lock_word < 0);
} }
} }
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, Google Inc. Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by Portions of this file contain modifications contributed and copyrighted by
...@@ -690,7 +690,7 @@ mutex_set_debug_info( ...@@ -690,7 +690,7 @@ mutex_set_debug_info(
ut_ad(mutex); ut_ad(mutex);
ut_ad(file_name); ut_ad(file_name);
sync_thread_add_level(mutex, mutex->level, FALSE); sync_thread_add_level(mutex, mutex->level);
mutex->file_name = file_name; mutex->file_name = file_name;
mutex->line = line; mutex->line = line;
...@@ -1133,9 +1133,8 @@ void ...@@ -1133,9 +1133,8 @@ void
sync_thread_add_level( sync_thread_add_level(
/*==================*/ /*==================*/
void* latch, /*!< in: pointer to a mutex or an rw-lock */ void* latch, /*!< in: pointer to a mutex or an rw-lock */
ulint level, /*!< in: level in the latching order; if ulint level) /*!< in: level in the latching order; if
SYNC_LEVEL_VARYING, nothing is done */ SYNC_LEVEL_VARYING, nothing is done */
ibool relock) /*!< in: TRUE if re-entering an x-lock */
{ {
ulint i; ulint i;
sync_level_t* slot; sync_level_t* slot;
...@@ -1186,10 +1185,6 @@ sync_thread_add_level( ...@@ -1186,10 +1185,6 @@ sync_thread_add_level(
array = thread_slot->levels; array = thread_slot->levels;
if (relock) {
goto levels_ok;
}
/* NOTE that there is a problem with _NODE and _LEAF levels: if the /* NOTE that there is a problem with _NODE and _LEAF levels: if the
B-tree height changes, then a leaf can change to an internal node B-tree height changes, then a leaf can change to an internal node
or the other way around. We do not know at present if this can cause or the other way around. We do not know at present if this can cause
...@@ -1366,7 +1361,6 @@ sync_thread_add_level( ...@@ -1366,7 +1361,6 @@ sync_thread_add_level(
ut_error; ut_error;
} }
levels_ok:
if (array->next_free == ULINT_UNDEFINED) { if (array->next_free == ULINT_UNDEFINED) {
ut_a(array->n_elems < array->max_elems); ut_a(array->n_elems < array->max_elems);
......
...@@ -1621,9 +1621,9 @@ trx_undo_prev_version_build( ...@@ -1621,9 +1621,9 @@ trx_undo_prev_version_build(
return(DB_ERROR); return(DB_ERROR);
} }
# if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG # ifdef UNIV_BLOB_NULL_DEBUG
ut_a(!rec_offs_any_null_extern(rec, offsets)); ut_a(!rec_offs_any_null_extern(rec, offsets));
# endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ # endif /* UNIV_BLOB_NULL_DEBUG */
if (row_upd_changes_field_size_or_external(index, offsets, update)) { if (row_upd_changes_field_size_or_external(index, offsets, update)) {
ulint n_ext; ulint n_ext;
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -918,7 +918,7 @@ trx_undo_add_page( ...@@ -918,7 +918,7 @@ trx_undo_add_page(
page_no = fseg_alloc_free_page_general(header_page + TRX_UNDO_SEG_HDR page_no = fseg_alloc_free_page_general(header_page + TRX_UNDO_SEG_HDR
+ TRX_UNDO_FSEG_HEADER, + TRX_UNDO_FSEG_HEADER,
undo->top_page_no + 1, FSP_UP, undo->top_page_no + 1, FSP_UP,
TRUE, mtr, mtr); TRUE, mtr);
fil_space_release_free_extents(undo->space, n_reserved); fil_space_release_free_extents(undo->space, n_reserved);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment