Merge tulin@bk-internal.mysql.com:/home/bk/mysql-5.0

into dl145b.mysql.com:/home/ndbdev/tomas/mysql-5.1
This commit is contained in:
tulin@dl145b.mysql.com 2005-06-21 08:49:21 +02:00
commit a6d0581275
80 changed files with 1844 additions and 1692 deletions

View file

@ -20,6 +20,7 @@ Created 6/2/1994 Heikki Tuuri
#include "rem0cmp.h"
#include "lock0lock.h"
#include "ibuf0ibuf.h"
#include "trx0trx.h"
/*
Latching strategy of the InnoDB B-tree
@ -137,13 +138,13 @@ btr_root_get(
ulint space;
ulint root_page_no;
page_t* root;
ibool comp = UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp;
space = dict_tree_get_space(tree);
root_page_no = dict_tree_get_page(tree);
root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr);
ut_a(page_is_comp(root) == comp);
ut_a(!!page_is_comp(root) ==
UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp);
return(root);
}
@ -163,21 +164,19 @@ btr_get_prev_user_rec(
page_t* page;
page_t* prev_page;
ulint prev_page_no;
rec_t* prev_rec;
ulint space;
page = buf_frame_align(rec);
if (page_get_infimum_rec(page) != rec) {
if (!page_rec_is_infimum(rec)) {
prev_rec = page_rec_get_prev(rec);
rec_t* prev_rec = page_rec_get_prev(rec);
if (page_get_infimum_rec(page) != prev_rec) {
if (!page_rec_is_infimum(prev_rec)) {
return(prev_rec);
}
}
page = buf_frame_align(rec);
prev_page_no = btr_page_get_prev(page, mtr);
space = buf_frame_get_space_id(page);
@ -192,9 +191,7 @@ btr_get_prev_user_rec(
MTR_MEMO_PAGE_X_FIX)));
ut_a(page_is_comp(prev_page) == page_is_comp(page));
prev_rec = page_rec_get_prev(page_get_supremum_rec(prev_page));
return(prev_rec);
return(page_rec_get_prev(page_get_supremum_rec(prev_page)));
}
return(NULL);
@ -215,21 +212,19 @@ btr_get_next_user_rec(
page_t* page;
page_t* next_page;
ulint next_page_no;
rec_t* next_rec;
ulint space;
page = buf_frame_align(rec);
if (page_get_supremum_rec(page) != rec) {
if (!page_rec_is_supremum(rec)) {
next_rec = page_rec_get_next(rec);
rec_t* next_rec = page_rec_get_next(rec);
if (page_get_supremum_rec(page) != next_rec) {
if (!page_rec_is_supremum(next_rec)) {
return(next_rec);
}
}
page = buf_frame_align(rec);
next_page_no = btr_page_get_next(page, mtr);
space = buf_frame_get_space_id(page);
@ -244,9 +239,7 @@ btr_get_next_user_rec(
MTR_MEMO_PAGE_X_FIX)));
ut_a(page_is_comp(next_page) == page_is_comp(page));
next_rec = page_rec_get_next(page_get_infimum_rec(next_page));
return(next_rec);
return(page_rec_get_next(page_get_infimum_rec(next_page)));
}
return(NULL);
@ -573,8 +566,7 @@ btr_page_get_father_for_rec(
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
ut_a(user_rec != page_get_supremum_rec(page));
ut_a(user_rec != page_get_infimum_rec(page));
ut_a(page_rec_is_user_rec(user_rec));
ut_ad(dict_tree_get_page(tree) != buf_frame_get_page_no(page));
@ -598,6 +590,7 @@ btr_page_get_father_for_rec(
if (btr_node_ptr_get_child_page_no(node_ptr, offsets) !=
buf_frame_get_page_no(page)) {
rec_t* print_rec;
fputs("InnoDB: Dump of the child page:\n", stderr);
buf_page_print(buf_frame_align(page));
fputs("InnoDB: Dump of the parent page:\n", stderr);
@ -612,11 +605,10 @@ btr_page_get_father_for_rec(
(ulong)
btr_node_ptr_get_child_page_no(node_ptr, offsets),
(ulong) buf_frame_get_page_no(page));
offsets = rec_get_offsets(page_rec_get_next(
page_get_infimum_rec(page)), index,
print_rec = page_rec_get_next(page_get_infimum_rec(page));
offsets = rec_get_offsets(print_rec, index,
offsets, ULINT_UNDEFINED, &heap);
page_rec_print(page_rec_get_next(page_get_infimum_rec(page)),
offsets);
page_rec_print(print_rec, offsets);
offsets = rec_get_offsets(node_ptr, index, offsets,
ULINT_UNDEFINED, &heap);
page_rec_print(node_ptr, offsets);
@ -663,7 +655,7 @@ btr_create(
ulint type, /* in: type of the index */
ulint space, /* in: space where created */
dulint index_id,/* in: index id */
ibool comp, /* in: TRUE=compact page format */
ulint comp, /* in: nonzero=compact page format */
mtr_t* mtr) /* in: mini-transaction handle */
{
ulint page_no;
@ -854,11 +846,12 @@ btr_page_reorganize_low(
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
ut_ad(!!page_is_comp(page) == index->table->comp);
data_size1 = page_get_data_size(page);
max_ins_size1 = page_get_max_insert_size_after_reorganize(page, 1);
/* Write the log record */
mlog_open_and_write_index(mtr, page, index, index->table->comp
mlog_open_and_write_index(mtr, page, index, page_is_comp(page)
? MLOG_COMP_PAGE_REORGANIZE
: MLOG_PAGE_REORGANIZE, 0);
@ -877,7 +870,7 @@ btr_page_reorganize_low(
/* Recreate the page: note that global data on page (possible
segment headers, next page-field, etc.) is preserved intact */
page_create(page, mtr, index->table->comp);
page_create(page, mtr, page_is_comp(page));
buf_block_align(page)->check_index_page_at_flush = TRUE;
/* Copy the records from the temporary space to the recreated page;
@ -1070,7 +1063,7 @@ btr_root_raise_and_insert(
as there is no lower alphabetical limit to records in the leftmost
node of a level: */
btr_set_min_rec_mark(node_ptr_rec, cursor->index->table->comp, mtr);
btr_set_min_rec_mark(node_ptr_rec, page_is_comp(root), mtr);
/* Free the memory heap */
mem_heap_free(heap);
@ -1151,7 +1144,6 @@ btr_page_get_split_rec_to_right(
{
page_t* page;
rec_t* insert_point;
rec_t* supremum;
page = btr_cur_get_page(cursor);
insert_point = btr_cur_get_rec(cursor);
@ -1160,13 +1152,23 @@ btr_page_get_split_rec_to_right(
the previous insert on the same page, we assume that there is a
pattern of sequential inserts here. */
if (page_header_get_ptr(page, PAGE_LAST_INSERT) == insert_point) {
if (UNIV_LIKELY(page_header_get_ptr(page, PAGE_LAST_INSERT)
== insert_point)) {
supremum = page_get_supremum_rec(page);
if (page_rec_get_next(insert_point) != supremum
&& page_rec_get_next(page_rec_get_next(insert_point))
!= supremum) {
rec_t* next_rec;
next_rec = page_rec_get_next(insert_point);
if (page_rec_is_supremum(next_rec)) {
split_at_new:
/* Split at the new record to insert */
*split_rec = NULL;
} else {
rec_t* next_next_rec = page_rec_get_next(next_rec);
if (page_rec_is_supremum(next_next_rec)) {
goto split_at_new;
}
/* If there are >= 2 user records up from the insert
point, split all but 1 off. We want to keep one because
@ -1175,12 +1177,8 @@ btr_page_get_split_rec_to_right(
search position just by looking at the records on this
page. */
*split_rec = page_rec_get_next(
page_rec_get_next(insert_point));
} else {
/* Else split at the new record to insert */
*split_rec = NULL;
}
*split_rec = next_next_rec;
}
return(TRUE);
}
@ -1220,7 +1218,7 @@ btr_page_get_sure_split_rec(
page = btr_cur_get_page(cursor);
insert_size = rec_get_converted_size(cursor->index, tuple);
free_space = page_get_free_space_of_empty(cursor->index->table->comp);
free_space = page_get_free_space_of_empty(page_is_comp(page));
/* free_space is now the free space of a created new page */
@ -1276,21 +1274,22 @@ btr_page_get_sure_split_rec(
supremum record of page */
if (rec == ins_rec) {
next_rec = NULL;
rec = NULL;
goto func_exit;
} else if (rec == NULL) {
next_rec = page_rec_get_next(ins_rec);
} else {
next_rec = page_rec_get_next(rec);
}
if (next_rec != page_get_supremum_rec(page)) {
if (heap) {
mem_heap_free(heap);
}
return(next_rec);
ut_ad(next_rec);
if (!page_rec_is_supremum(next_rec)) {
rec = next_rec;
}
}
if (heap) {
func_exit:
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(rec);
@ -1329,13 +1328,12 @@ btr_page_insert_fits(
ut_ad(!split_rec == !offsets);
ut_ad(!offsets
|| cursor->index->table->comp == rec_offs_comp(offsets));
|| !page_is_comp(page) == !rec_offs_comp(offsets));
ut_ad(!offsets
|| rec_offs_validate(split_rec, cursor->index, offsets));
ut_ad(page_is_comp(page) == cursor->index->table->comp);
insert_size = rec_get_converted_size(cursor->index, tuple);
free_space = page_get_free_space_of_empty(cursor->index->table->comp);
free_space = page_get_free_space_of_empty(page_is_comp(page));
/* free_space is now the free space of a created new page */
@ -1832,14 +1830,15 @@ void
btr_set_min_rec_mark_log(
/*=====================*/
rec_t* rec, /* in: record */
ibool comp, /* TRUE=compact record format */
ulint comp, /* nonzero=compact record format */
mtr_t* mtr) /* in: mtr */
{
mlog_write_initial_log_record(rec,
comp ? MLOG_COMP_REC_MIN_MARK : MLOG_REC_MIN_MARK, mtr);
/* Write rec offset as a 2-byte ulint */
mlog_catenate_ulint(mtr, rec - buf_frame_align(rec), MLOG_2BYTES);
mlog_catenate_ulint(mtr, ut_align_offset(rec, UNIV_PAGE_SIZE),
MLOG_2BYTES);
}
/********************************************************************
@ -1852,7 +1851,7 @@ btr_parse_set_min_rec_mark(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
ibool comp, /* in: TRUE=compact page format */
ulint comp, /* in: nonzero=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
{
@ -1864,6 +1863,8 @@ btr_parse_set_min_rec_mark(
}
if (page) {
ut_a(!page_is_comp(page) == !comp);
rec = page + mach_read_from_2(ptr);
btr_set_min_rec_mark(rec, comp, mtr);
@ -1879,7 +1880,7 @@ void
btr_set_min_rec_mark(
/*=================*/
rec_t* rec, /* in: record */
ibool comp, /* in: TRUE=compact page format */
ulint comp, /* in: nonzero=compact page format */
mtr_t* mtr) /* in: mtr */
{
ulint info_bits;
@ -2008,11 +2009,12 @@ btr_compress(
ulint max_ins_size;
ulint max_ins_size_reorg;
ulint level;
ibool comp = cursor->index->table->comp;
ulint comp;
page = btr_cur_get_page(cursor);
tree = btr_cur_get_tree(cursor);
ut_a(comp == page_is_comp(page));
comp = page_is_comp(page);
ut_a(!!comp == cursor->index->table->comp);
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
@ -2055,7 +2057,7 @@ btr_compress(
n_recs = page_get_n_recs(page);
data_size = page_get_data_size(page);
ut_a(page_is_comp(merge_page) == page_is_comp(page));
ut_a(page_is_comp(merge_page) == comp);
max_ins_size_reorg = page_get_max_insert_size_after_reorganize(
merge_page, n_recs);
@ -2108,7 +2110,7 @@ btr_compress(
rec_get_offsets(node_ptr, cursor->index,
offsets_, ULINT_UNDEFINED, &heap),
right_page_no, mtr);
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
btr_node_ptr_delete(tree, merge_page, mtr);
@ -2250,10 +2252,9 @@ btr_discard_page(
node_ptr = page_rec_get_next(page_get_infimum_rec(merge_page));
ut_ad(node_ptr != page_get_supremum_rec(merge_page));
ut_ad(page_rec_is_user_rec(node_ptr));
btr_set_min_rec_mark(node_ptr,
cursor->index->table->comp, mtr);
btr_set_min_rec_mark(node_ptr, page_is_comp(merge_page), mtr);
}
btr_node_ptr_delete(tree, page, mtr);
@ -2274,6 +2275,7 @@ btr_discard_page(
ut_ad(btr_check_node_ptr(tree, merge_page, mtr));
}
#ifdef UNIV_BTR_PRINT
/*****************************************************************
Prints size info of a B-tree. */
@ -2401,14 +2403,15 @@ btr_print_tree(
root = btr_root_get(tree, &mtr);
btr_print_recursive(tree, root, width, &heap, &offsets, &mtr);
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
mtr_commit(&mtr);
btr_validate_tree(tree);
btr_validate_tree(tree, NULL);
}
#endif /* UNIV_BTR_PRINT */
/****************************************************************
Checks that the node pointer to a page is appropriate. */
@ -2496,8 +2499,8 @@ btr_index_rec_validate(
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
page = buf_frame_align(rec);
if (index->type & DICT_UNIVERSAL) {
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
/* The insert buffer index tree can contain records from any
other index: we cannot check the number of fields or
their length */
@ -2505,9 +2508,18 @@ btr_index_rec_validate(
return(TRUE);
}
if (UNIV_UNLIKELY(!!page_is_comp(page) != index->table->comp)) {
btr_index_rec_validate_report(page, rec, index);
fprintf(stderr, "InnoDB: compact flag=%lu, should be %lu\n",
(ulong) !!page_is_comp(page),
(ulong) index->table->comp);
return(FALSE);
}
n = dict_index_get_n_fields(index);
if (!index->table->comp && rec_get_n_fields_old(rec) != n) {
if (!page_is_comp(page)
&& UNIV_UNLIKELY(rec_get_n_fields_old(rec) != n)) {
btr_index_rec_validate_report(page, rec, index);
fprintf(stderr, "InnoDB: has %lu fields, should have %lu\n",
(ulong) rec_get_n_fields_old(rec), (ulong) n);
@ -2554,14 +2566,14 @@ btr_index_rec_validate(
rec_print_new(stderr, rec, offsets);
putc('\n', stderr);
}
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(FALSE);
}
}
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(TRUE);
@ -2649,6 +2661,7 @@ btr_validate_level(
/*===============*/
/* out: TRUE if ok */
dict_tree_t* tree, /* in: index tree */
trx_t* trx, /* in: transaction or NULL */
ulint level) /* in: level number */
{
ulint space;
@ -2696,6 +2709,11 @@ btr_validate_level(
/* Now we are on the desired level. Loop through the pages on that
level. */
loop:
if (trx_is_interrupted(trx)) {
mtr_commit(&mtr);
mem_heap_free(heap);
return(ret);
}
mem_heap_empty(heap);
offsets = offsets2 = NULL;
mtr_x_lock(dict_tree_get_lock(tree), &mtr);
@ -2765,7 +2783,7 @@ loop:
if (level > 0 && left_page_no == FIL_NULL) {
ut_a(REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
page_rec_get_next(page_get_infimum_rec(page)),
index->table->comp));
page_is_comp(page)));
}
if (buf_frame_get_page_no(page) != dict_tree_get_page(tree)) {
@ -2921,7 +2939,7 @@ node_ptr_fails:
mtr_commit(&mtr);
if (right_page_no != FIL_NULL) {
ibool comp = page_is_comp(page);
ulint comp = page_is_comp(page);
mtr_start(&mtr);
page = btr_page_get(space, right_page_no, RW_X_LATCH, &mtr);
@ -2941,7 +2959,8 @@ ibool
btr_validate_tree(
/*==============*/
/* out: TRUE if ok */
dict_tree_t* tree) /* in: tree */
dict_tree_t* tree, /* in: tree */
trx_t* trx) /* in: transaction or NULL */
{
mtr_t mtr;
page_t* root;
@ -2954,9 +2973,8 @@ btr_validate_tree(
root = btr_root_get(tree, &mtr);
n = btr_page_get_level(root, &mtr);
for (i = 0; i <= n; i++) {
if (!btr_validate_level(tree, n - i)) {
for (i = 0; i <= n && !trx_is_interrupted(trx); i++) {
if (!btr_validate_level(tree, trx, n - i)) {
mtr_commit(&mtr);

View file

@ -36,11 +36,11 @@ Created 10/16/1994 Heikki Tuuri
#include "ibuf0ibuf.h"
#include "lock0lock.h"
#ifdef UNIV_DEBUG
/* If the following is set to TRUE, this module prints a lot of
trace information of individual record operations */
ibool btr_cur_print_record_ops = FALSE;
ulint btr_cur_rnd = 0;
#endif /* UNIV_DEBUG */
ulint btr_cur_n_non_sea = 0;
ulint btr_cur_n_sea = 0;
@ -431,7 +431,7 @@ retry_page_get:
cursor->thr)) {
/* Insertion to the insert buffer succeeded */
cursor->flag = BTR_CUR_INSERT_TO_IBUF;
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return;
@ -505,8 +505,9 @@ retry_page_get:
if (level > 0) {
/* x-latch the page */
ut_a(page_is_comp(btr_page_get(space,
page_no, RW_X_LATCH, mtr))
page = btr_page_get(space,
page_no, RW_X_LATCH, mtr);
ut_a(!!page_is_comp(page)
== index->table->comp);
}
@ -525,7 +526,7 @@ retry_page_get:
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
}
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@ -681,7 +682,7 @@ btr_cur_open_at_index_side(
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
}
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@ -762,7 +763,7 @@ btr_cur_open_at_rnd_pos(
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
}
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@ -879,6 +880,7 @@ btr_cur_ins_lock_and_undo(
return(DB_SUCCESS);
}
#ifdef UNIV_DEBUG
/*****************************************************************
Report information about a transaction. */
static
@ -896,6 +898,7 @@ btr_cur_trx_report(
dict_index_name_print(stderr, trx, index);
putc('\n', stderr);
}
#endif /* UNIV_DEBUG */
/*****************************************************************
Tries to perform an insert to a page in an index tree, next to cursor.
@ -945,12 +948,13 @@ btr_cur_optimistic_insert(
fputs("InnoDB: Error in a tuple to insert into ", stderr);
dict_index_name_print(stderr, thr_get_trx(thr), index);
}
#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(thr_get_trx(thr), index, "insert into ");
dtuple_print(stderr, entry);
}
#endif /* UNIV_DEBUG */
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
max_size = page_get_max_insert_size_after_reorganize(page, 1);
@ -961,7 +965,7 @@ calculate_sizes_again:
rec_size = rec_get_converted_size(index, entry);
if (rec_size >=
ut_min(page_get_free_space_of_empty(index->table->comp) / 2,
ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2,
REC_MAX_DATA_SIZE)) {
/* The record is so big that we have to store some fields
@ -1027,7 +1031,7 @@ calculate_sizes_again:
*rec = page_cur_insert_rec_low(page_cursor, entry, index,
NULL, NULL, mtr);
if (!(*rec)) {
if (UNIV_UNLIKELY(!(*rec))) {
/* If the record did not fit, reorganize */
btr_page_reorganize(page, index, mtr);
@ -1039,7 +1043,7 @@ calculate_sizes_again:
*rec = page_cur_tuple_insert(page_cursor, entry, index, mtr);
if (!*rec) {
if (UNIV_UNLIKELY(!*rec)) {
fputs("InnoDB: Error: cannot insert tuple ", stderr);
dtuple_print(stderr, entry);
fputs(" into ", stderr);
@ -1166,7 +1170,7 @@ btr_cur_pessimistic_insert(
}
if (rec_get_converted_size(index, entry) >=
ut_min(page_get_free_space_of_empty(index->table->comp) / 2,
ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2,
REC_MAX_DATA_SIZE)) {
/* The record is so big that we have to store some fields
@ -1261,7 +1265,7 @@ btr_cur_upd_lock_and_undo(
err = lock_clust_rec_modify_check_and_lock(flags, rec, index,
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap), thr);
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
if (err != DB_SUCCESS) {
@ -1293,9 +1297,11 @@ btr_cur_update_in_place_log(
mtr_t* mtr) /* in: mtr */
{
byte* log_ptr;
page_t* page = ut_align_down(rec, UNIV_PAGE_SIZE);
ut_ad(flags < 256);
ut_ad(!!page_is_comp(page) == index->table->comp);
log_ptr = mlog_open_and_write_index(mtr, rec, index, index->table->comp
log_ptr = mlog_open_and_write_index(mtr, rec, index, page_is_comp(page)
? MLOG_COMP_REC_UPDATE_IN_PLACE
: MLOG_REC_UPDATE_IN_PLACE,
1 + DATA_ROLL_PTR_LEN + 14 + 2 + MLOG_BUF_MARGIN);
@ -1317,7 +1323,7 @@ btr_cur_update_in_place_log(
log_ptr = row_upd_write_sys_vals_to_log(index, trx, roll_ptr, log_ptr,
mtr);
mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
log_ptr += 2;
row_upd_index_write_log(update, log_ptr, mtr);
@ -1374,18 +1380,12 @@ btr_cur_parse_update_in_place(
ptr = row_upd_index_parse(ptr, end_ptr, heap, &update);
if (ptr == NULL) {
mem_heap_free(heap);
return(NULL);
if (!ptr || !page) {
goto func_exit;
}
if (!page) {
mem_heap_free(heap);
return(ptr);
}
ut_a(!!page_is_comp(page) == index->table->comp);
rec = page + rec_offset;
/* We do not need to reserve btr_search_latch, as the page is only
@ -1400,6 +1400,7 @@ btr_cur_parse_update_in_place(
row_upd_rec_in_place(rec, offsets, update);
func_exit:
mem_heap_free(heap);
return(ptr);
@ -1429,7 +1430,7 @@ btr_cur_update_in_place(
rec_t* rec;
dulint roll_ptr = ut_dulint_zero;
trx_t* trx;
ibool was_delete_marked;
ulint was_delete_marked;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
@ -1437,27 +1438,30 @@ btr_cur_update_in_place(
rec = btr_cur_get_rec(cursor);
index = cursor->index;
ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
trx = thr_get_trx(thr);
heap = mem_heap_create(100);
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(trx, index, "update ");
rec_print_new(stderr, rec, offsets);
}
#endif /* UNIV_DEBUG */
/* Do lock checking and undo logging */
err = btr_cur_upd_lock_and_undo(flags, cursor, update, cmpl_info,
thr, &roll_ptr);
if (err != DB_SUCCESS) {
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(err);
}
block = buf_block_align(rec);
ut_ad(!!page_is_comp(buf_block_get_frame(block))
== index->table->comp);
if (block->is_hashed) {
/* The function row_upd_changes_ord_field_binary works only
@ -1481,7 +1485,8 @@ btr_cur_update_in_place(
/* FIXME: in a mixed tree, all records may not have enough ordering
fields for btr search: */
was_delete_marked = rec_get_deleted_flag(rec, index->table->comp);
was_delete_marked = rec_get_deleted_flag(rec,
page_is_comp(buf_block_get_frame(block)));
row_upd_rec_in_place(rec, offsets, update);
@ -1491,14 +1496,15 @@ btr_cur_update_in_place(
btr_cur_update_in_place_log(flags, rec, index, update, trx, roll_ptr,
mtr);
if (was_delete_marked && !rec_get_deleted_flag(rec, index->table->comp)) {
if (was_delete_marked && !rec_get_deleted_flag(rec,
page_is_comp(buf_block_get_frame(block)))) {
/* The new updated record owns its possible externally
stored fields */
btr_cur_unmark_extern_fields(rec, mtr, offsets);
}
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(DB_SUCCESS);
@ -1547,14 +1553,17 @@ btr_cur_optimistic_update(
page = btr_cur_get_page(cursor);
rec = btr_cur_get_rec(cursor);
index = cursor->index;
ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
heap = mem_heap_create(1024);
offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(thr_get_trx(thr), index, "update ");
rec_print_new(stderr, rec, offsets);
}
#endif /* UNIV_DEBUG */
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
@ -1596,8 +1605,8 @@ btr_cur_optimistic_update(
old_rec_size = rec_offs_size(offsets);
new_rec_size = rec_get_converted_size(index, new_entry);
if (new_rec_size >=
page_get_free_space_of_empty(index->table->comp) / 2) {
if (UNIV_UNLIKELY(new_rec_size >= page_get_free_space_of_empty(
page_is_comp(page)) / 2)) {
mem_heap_free(heap);
@ -1607,8 +1616,9 @@ btr_cur_optimistic_update(
max_size = old_rec_size
+ page_get_max_insert_size_after_reorganize(page, 1);
if (page_get_data_size(page) - old_rec_size + new_rec_size
< BTR_CUR_PAGE_COMPRESS_LIMIT) {
if (UNIV_UNLIKELY(page_get_data_size(page)
- old_rec_size + new_rec_size
< BTR_CUR_PAGE_COMPRESS_LIMIT)) {
/* The page would become too empty */
@ -1644,7 +1654,7 @@ btr_cur_optimistic_update(
explicit locks on rec, before deleting rec (see the comment in
.._pessimistic_update). */
lock_rec_store_on_page_infimum(rec);
lock_rec_store_on_page_infimum(page, rec);
btr_search_update_hash_on_delete(cursor);
@ -1665,7 +1675,7 @@ btr_cur_optimistic_update(
ut_a(rec); /* <- We calculated above the insert would fit */
if (!rec_get_deleted_flag(rec, index->table->comp)) {
if (!rec_get_deleted_flag(rec, page_is_comp(page))) {
/* The new inserted record owns its possible externally
stored fields */
@ -1814,7 +1824,7 @@ btr_cur_pessimistic_update(
}
success = fsp_reserve_free_extents(&n_reserved,
cursor->index->space,
index->space,
n_extents, reserve_flag, mtr);
if (!success) {
err = DB_OUT_OF_FILE_SPACE;
@ -1858,14 +1868,14 @@ btr_cur_pessimistic_update(
ext_vect = mem_heap_alloc(heap, sizeof(ulint)
* dict_index_get_n_fields(index));
ut_ad(!cursor->index->table->comp || !rec_get_node_ptr_flag(rec));
ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec));
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
n_ext_vect = btr_push_update_extern_fields(ext_vect, offsets, update);
if (rec_get_converted_size(index, new_entry) >=
ut_min(page_get_free_space_of_empty(index->table->comp) / 2,
REC_MAX_DATA_SIZE)) {
if (UNIV_UNLIKELY(rec_get_converted_size(index, new_entry) >=
ut_min(page_get_free_space_of_empty(page_is_comp(page)) / 2,
REC_MAX_DATA_SIZE))) {
big_rec_vec = dtuple_convert_big_rec(index, new_entry,
ext_vect, n_ext_vect);
@ -1887,7 +1897,7 @@ btr_cur_pessimistic_update(
delete the lock structs set on the root page even if the root
page carries just node pointers. */
lock_rec_store_on_page_infimum(rec);
lock_rec_store_on_page_infimum(buf_frame_align(rec), rec);
btr_search_update_hash_on_delete(cursor);
@ -1965,8 +1975,7 @@ return_after_reservations:
mem_heap_free(heap);
if (n_extents > 0) {
fil_space_release_free_extents(cursor->index->space,
n_reserved);
fil_space_release_free_extents(index->space, n_reserved);
}
*big_rec = big_rec_vec;
@ -1995,7 +2004,10 @@ btr_cur_del_mark_set_clust_rec_log(
ut_ad(flags < 256);
ut_ad(val <= 1);
log_ptr = mlog_open_and_write_index(mtr, rec, index, index->table->comp
ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
log_ptr = mlog_open_and_write_index(mtr, rec, index,
page_rec_is_comp(rec)
? MLOG_COMP_REC_CLUST_DELETE_MARK
: MLOG_REC_CLUST_DELETE_MARK,
1 + 1 + DATA_ROLL_PTR_LEN + 14 + 2);
@ -2012,7 +2024,7 @@ btr_cur_del_mark_set_clust_rec_log(
log_ptr = row_upd_write_sys_vals_to_log(index, trx, roll_ptr, log_ptr,
mtr);
mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
log_ptr += 2;
mlog_close(mtr, log_ptr);
@ -2032,13 +2044,15 @@ btr_cur_parse_del_mark_set_clust_rec(
page_t* page) /* in: page or NULL */
{
ulint flags;
ibool val;
ulint val;
ulint pos;
dulint trx_id;
dulint roll_ptr;
ulint offset;
rec_t* rec;
ut_ad(!page || !!page_is_comp(page) == index->table->comp);
if (end_ptr < ptr + 2) {
return(NULL);
@ -2078,7 +2092,7 @@ btr_cur_parse_del_mark_set_clust_rec(
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
pos, trx_id, roll_ptr);
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@ -2087,7 +2101,7 @@ btr_cur_parse_del_mark_set_clust_rec(
is only being recovered, and there cannot be a hash index to
it. */
rec_set_deleted_flag(rec, index->table->comp, val);
rec_set_deleted_flag(rec, page_is_comp(page), val);
}
return(ptr);
@ -2123,22 +2137,25 @@ btr_cur_del_mark_set_clust_rec(
rec = btr_cur_get_rec(cursor);
index = cursor->index;
ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(thr_get_trx(thr), index, "del mark ");
rec_print_new(stderr, rec, offsets);
}
#endif /* UNIV_DEBUG */
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(rec_get_deleted_flag(rec, index->table->comp) == FALSE);
ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
err = lock_clust_rec_modify_check_and_lock(flags,
rec, index, offsets, thr);
if (err != DB_SUCCESS) {
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(err);
@ -2149,7 +2166,7 @@ btr_cur_del_mark_set_clust_rec(
&roll_ptr);
if (err != DB_SUCCESS) {
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(err);
@ -2161,7 +2178,7 @@ btr_cur_del_mark_set_clust_rec(
rw_lock_x_lock(&btr_search_latch);
}
rec_set_deleted_flag(rec, index->table->comp, val);
rec_set_deleted_flag(rec, rec_offs_comp(offsets), val);
trx = thr_get_trx(thr);
@ -2175,7 +2192,7 @@ btr_cur_del_mark_set_clust_rec(
btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx,
roll_ptr, mtr);
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(DB_SUCCESS);
@ -2189,17 +2206,13 @@ void
btr_cur_del_mark_set_sec_rec_log(
/*=============================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: record descriptor */
ibool val, /* in: value to set */
mtr_t* mtr) /* in: mtr */
{
byte* log_ptr;
ut_ad(val <= 1);
log_ptr = mlog_open_and_write_index(mtr, rec, index, index->table->comp
? MLOG_COMP_REC_SEC_DELETE_MARK
: MLOG_REC_SEC_DELETE_MARK,
1 + 2);
log_ptr = mlog_open(mtr, 11 + 1 + 2);
if (!log_ptr) {
/* Logging in mtr is switched off during crash recovery:
@ -2207,10 +2220,12 @@ btr_cur_del_mark_set_sec_rec_log(
return;
}
log_ptr = mlog_write_initial_log_record_fast(
rec, MLOG_REC_SEC_DELETE_MARK, log_ptr, mtr);
mach_write_to_1(log_ptr, val);
log_ptr++;
mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
log_ptr += 2;
mlog_close(mtr, log_ptr);
@ -2226,10 +2241,9 @@ btr_cur_parse_del_mark_set_sec_rec(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
dict_index_t* index, /* in: record descriptor */
page_t* page) /* in: page or NULL */
{
ibool val;
ulint val;
ulint offset;
rec_t* rec;
@ -2253,7 +2267,7 @@ btr_cur_parse_del_mark_set_sec_rec(
is only being recovered, and there cannot be a hash index to
it. */
rec_set_deleted_flag(rec, index->table->comp, val);
rec_set_deleted_flag(rec, page_is_comp(page), val);
}
return(ptr);
@ -2279,11 +2293,13 @@ btr_cur_del_mark_set_sec_rec(
rec = btr_cur_get_rec(cursor);
#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(thr_get_trx(thr), cursor->index,
"del mark ");
rec_print(stderr, rec, cursor->index);
}
#endif /* UNIV_DEBUG */
err = lock_sec_rec_modify_check_and_lock(flags, rec, cursor->index,
thr);
@ -2293,18 +2309,21 @@ btr_cur_del_mark_set_sec_rec(
}
block = buf_block_align(rec);
ut_ad(!!page_is_comp(buf_block_get_frame(block))
== cursor->index->table->comp);
if (block->is_hashed) {
rw_lock_x_lock(&btr_search_latch);
}
rec_set_deleted_flag(rec, cursor->index->table->comp, val);
rec_set_deleted_flag(rec, page_is_comp(buf_block_get_frame(block)),
val);
if (block->is_hashed) {
rw_lock_x_unlock(&btr_search_latch);
}
btr_cur_del_mark_set_sec_rec_log(rec, cursor->index, val, mtr);
btr_cur_del_mark_set_sec_rec_log(rec, val, mtr);
return(DB_SUCCESS);
}
@ -2317,15 +2336,14 @@ void
btr_cur_del_unmark_for_ibuf(
/*========================*/
rec_t* rec, /* in: record to delete unmark */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mtr */
{
/* We do not need to reserve btr_search_latch, as the page has just
been read to the buffer pool and there cannot be a hash index to it. */
rec_set_deleted_flag(rec, index->table->comp, FALSE);
rec_set_deleted_flag(rec, page_is_comp(buf_frame_align(rec)), FALSE);
btr_cur_del_mark_set_sec_rec_log(rec, index, FALSE, mtr);
btr_cur_del_mark_set_sec_rec_log(rec, FALSE, mtr);
}
/*==================== B-TREE RECORD REMOVE =========================*/
@ -2444,7 +2462,7 @@ btr_cur_optimistic_delete(
mtr);
}
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@ -2487,6 +2505,7 @@ btr_cur_pessimistic_delete(
ulint n_reserved;
ibool success;
ibool ret = FALSE;
ulint level;
mem_heap_t* heap;
ulint* offsets;
@ -2523,15 +2542,15 @@ btr_cur_pessimistic_delete(
/* Free externally stored fields if the record is neither
a node pointer nor in two-byte format.
This avoids an unnecessary loop. */
if (cursor->index->table->comp
if (page_is_comp(page)
? !rec_get_node_ptr_flag(rec)
: !rec_get_1byte_offs_flag(rec)) {
btr_rec_free_externally_stored_fields(cursor->index,
rec, offsets, in_rollback, mtr);
}
if ((page_get_n_recs(page) < 2)
&& (dict_tree_get_page(btr_cur_get_tree(cursor))
if (UNIV_UNLIKELY(page_get_n_recs(page) < 2)
&& UNIV_UNLIKELY(dict_tree_get_page(btr_cur_get_tree(cursor))
!= buf_frame_get_page_no(page))) {
/* If there is only one record, drop the whole page in
@ -2546,9 +2565,13 @@ btr_cur_pessimistic_delete(
}
lock_update_delete(rec);
level = btr_page_get_level(page, mtr);
if ((btr_page_get_level(page, mtr) > 0)
&& (page_rec_get_next(page_get_infimum_rec(page)) == rec)) {
if (level > 0
&& UNIV_UNLIKELY(rec == page_rec_get_next(
page_get_infimum_rec(page)))) {
rec_t* next_rec = page_rec_get_next(rec);
if (btr_page_get_prev(page, mtr) == FIL_NULL) {
@ -2556,8 +2579,8 @@ btr_cur_pessimistic_delete(
non-leaf level, we must mark the new leftmost node
pointer as the predefined minimum record */
btr_set_min_rec_mark(page_rec_get_next(rec),
cursor->index->table->comp, mtr);
btr_set_min_rec_mark(next_rec, page_is_comp(page),
mtr);
} else {
/* Otherwise, if we delete the leftmost node pointer
on a page, we have to change the father node pointer
@ -2567,13 +2590,12 @@ btr_cur_pessimistic_delete(
btr_node_ptr_delete(tree, page, mtr);
node_ptr = dict_tree_build_node_ptr(
tree, page_rec_get_next(rec),
tree, next_rec,
buf_frame_get_page_no(page),
heap, btr_page_get_level(page, mtr));
heap, level);
btr_insert_on_non_leaf_level(tree,
btr_page_get_level(page, mtr) + 1,
node_ptr, mtr);
level + 1, node_ptr, mtr);
}
}
@ -2813,12 +2835,13 @@ btr_estimate_number_of_different_key_vals(
ulint add_on;
mtr_t mtr;
mem_heap_t* heap = NULL;
ulint offsets1_[REC_OFFS_NORMAL_SIZE];
ulint offsets2_[REC_OFFS_NORMAL_SIZE];
ulint* offsets1 = offsets1_;
ulint* offsets2 = offsets2_;
*offsets1_ = (sizeof offsets1_) / sizeof *offsets1_;
*offsets2_ = (sizeof offsets2_) / sizeof *offsets2_;
ulint offsets_rec_[REC_OFFS_NORMAL_SIZE];
ulint offsets_next_rec_[REC_OFFS_NORMAL_SIZE];
ulint* offsets_rec = offsets_rec_;
ulint* offsets_next_rec= offsets_next_rec_;
*offsets_rec_ = (sizeof offsets_rec_) / sizeof *offsets_rec_;
*offsets_next_rec_ =
(sizeof offsets_next_rec_) / sizeof *offsets_next_rec_;
n_cols = dict_index_get_n_unique(index);
@ -2831,6 +2854,7 @@ btr_estimate_number_of_different_key_vals(
/* We sample some pages in the index to get an estimate */
for (i = 0; i < BTR_KEY_VAL_ESTIMATE_N_PAGES; i++) {
rec_t* supremum;
mtr_start(&mtr);
btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr);
@ -2843,26 +2867,29 @@ btr_estimate_number_of_different_key_vals(
page = btr_cur_get_page(&cursor);
rec = page_get_infimum_rec(page);
rec = page_rec_get_next(rec);
supremum = page_get_supremum_rec(page);
rec = page_rec_get_next(page_get_infimum_rec(page));
if (rec != page_get_supremum_rec(page)) {
if (rec != supremum) {
not_empty_flag = 1;
offsets_rec = rec_get_offsets(rec, index, offsets_rec,
ULINT_UNDEFINED, &heap);
}
while (rec != page_get_supremum_rec(page)
&& page_rec_get_next(rec)
!= page_get_supremum_rec(page)) {
while (rec != supremum) {
rec_t* next_rec = page_rec_get_next(rec);
if (next_rec == supremum) {
break;
}
matched_fields = 0;
matched_bytes = 0;
offsets1 = rec_get_offsets(rec, index, offsets1,
ULINT_UNDEFINED, &heap);
offsets2 = rec_get_offsets(next_rec, index, offsets2,
offsets_next_rec = rec_get_offsets(next_rec, index,
offsets_next_rec,
n_cols, &heap);
cmp_rec_rec_with_match(rec, next_rec,
offsets1, offsets2,
offsets_rec, offsets_next_rec,
index, &matched_fields,
&matched_bytes);
@ -2875,9 +2902,17 @@ btr_estimate_number_of_different_key_vals(
total_external_size +=
btr_rec_get_externally_stored_len(
rec, offsets1);
rec, offsets_rec);
rec = page_rec_get_next(rec);
rec = next_rec;
/* Initialize offsets_rec for the next round
and assign the old offsets_rec buffer to
offsets_next_rec. */
{
ulint* offsets_tmp = offsets_rec;
offsets_rec = offsets_next_rec;
offsets_next_rec = offsets_tmp;
}
}
@ -2899,11 +2934,11 @@ btr_estimate_number_of_different_key_vals(
}
}
offsets1 = rec_get_offsets(rec, index, offsets1,
offsets_rec = rec_get_offsets(rec, index, offsets_rec,
ULINT_UNDEFINED, &heap);
total_external_size +=
btr_rec_get_externally_stored_len(rec,
offsets1);
offsets_rec);
mtr_commit(&mtr);
}
@ -2944,7 +2979,7 @@ btr_estimate_number_of_different_key_vals(
}
mem_free(n_diff);
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@ -3599,7 +3634,7 @@ btr_rec_free_externally_stored_fields(
MTR_MEMO_PAGE_X_FIX));
/* Free possible externally stored fields in the record */
ut_ad(index->table->comp == rec_offs_comp(offsets));
ut_ad(index->table->comp == !!rec_offs_comp(offsets));
n_fields = rec_offs_n_fields(offsets);
for (i = 0; i < n_fields; i++) {

View file

@ -78,6 +78,7 @@ btr_pcur_store_position(
rec_t* rec;
dict_tree_t* tree;
page_t* page;
ulint offs;
ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
@ -87,7 +88,8 @@ btr_pcur_store_position(
page_cursor = btr_pcur_get_page_cur(cursor);
rec = page_cur_get_rec(page_cursor);
page = buf_frame_align(rec);
page = ut_align_down(rec, UNIV_PAGE_SIZE);
offs = ut_align_offset(rec, UNIV_PAGE_SIZE);
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_S_FIX)
@ -95,35 +97,33 @@ btr_pcur_store_position(
MTR_MEMO_PAGE_X_FIX));
ut_a(cursor->latch_mode != BTR_NO_LATCHES);
if (page_get_n_recs(page) == 0) {
if (UNIV_UNLIKELY(page_get_n_recs(page) == 0)) {
/* It must be an empty index tree; NOTE that in this case
we do not store the modify_clock, but always do a search
if we restore the cursor position */
ut_a(btr_page_get_next(page, mtr) == FIL_NULL
&& btr_page_get_prev(page, mtr) == FIL_NULL);
ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
ut_a(btr_page_get_prev(page, mtr) == FIL_NULL);
if (rec == page_get_supremum_rec(page)) {
cursor->old_stored = BTR_PCUR_OLD_STORED;
if (page_rec_is_supremum_low(offs)) {
cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE;
cursor->old_stored = BTR_PCUR_OLD_STORED;
return;
} else {
cursor->rel_pos = BTR_PCUR_BEFORE_FIRST_IN_TREE;
}
cursor->rel_pos = BTR_PCUR_BEFORE_FIRST_IN_TREE;
cursor->old_stored = BTR_PCUR_OLD_STORED;
return;
}
if (rec == page_get_supremum_rec(page)) {
if (page_rec_is_supremum_low(offs)) {
rec = page_rec_get_prev(rec);
cursor->rel_pos = BTR_PCUR_AFTER;
} else if (rec == page_get_infimum_rec(page)) {
} else if (page_rec_is_infimum_low(offs)) {
rec = page_rec_get_next(rec);
@ -139,7 +139,8 @@ btr_pcur_store_position(
&cursor->buf_size);
cursor->block_when_stored = buf_block_align(page);
cursor->modify_clock = buf_frame_get_modify_clock(page);
cursor->modify_clock = buf_block_get_modify_clock(
cursor->block_when_stored);
}
/******************************************************************
@ -202,33 +203,27 @@ btr_pcur_restore_position(
dtuple_t* tuple;
ulint mode;
ulint old_mode;
ibool from_left;
mem_heap_t* heap;
ut_a(cursor->pos_state == BTR_PCUR_WAS_POSITIONED
|| cursor->pos_state == BTR_PCUR_IS_POSITIONED);
if (cursor->old_stored != BTR_PCUR_OLD_STORED) {
if (UNIV_UNLIKELY(cursor->old_stored != BTR_PCUR_OLD_STORED)
|| UNIV_UNLIKELY(cursor->pos_state != BTR_PCUR_WAS_POSITIONED
&& cursor->pos_state != BTR_PCUR_IS_POSITIONED)) {
ut_print_buf(stderr, (const byte*)cursor, sizeof(btr_pcur_t));
if (cursor->trx_if_known) {
trx_print(stderr, cursor->trx_if_known);
}
ut_a(0);
ut_error;
}
if (cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
|| cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) {
if (UNIV_UNLIKELY(cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
|| cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE)) {
/* In these cases we do not try an optimistic restoration,
but always do a search */
if (cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) {
from_left = TRUE;
} else {
from_left = FALSE;
}
btr_cur_open_at_index_side(from_left,
btr_cur_open_at_index_side(
cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
btr_pcur_get_btr_cur(cursor)->index, latch_mode,
btr_pcur_get_btr_cur(cursor), mtr);
@ -243,12 +238,13 @@ btr_pcur_restore_position(
page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor));
if (latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF) {
if (UNIV_LIKELY(latch_mode == BTR_SEARCH_LEAF)
|| UNIV_LIKELY(latch_mode == BTR_MODIFY_LEAF)) {
/* Try optimistic restoration */
if (buf_page_optimistic_get(latch_mode,
if (UNIV_LIKELY(buf_page_optimistic_get(latch_mode,
cursor->block_when_stored, page,
cursor->modify_clock, mtr)) {
cursor->modify_clock, mtr))) {
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
#ifdef UNIV_SYNC_DEBUG
buf_page_dbg_add_level(page, SYNC_TREE_NODE);
@ -297,7 +293,7 @@ btr_pcur_restore_position(
/* Save the old search mode of the cursor */
old_mode = cursor->search_mode;
if (cursor->rel_pos == BTR_PCUR_ON) {
if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) {
mode = PAGE_CUR_LE;
} else if (cursor->rel_pos == BTR_PCUR_AFTER) {
mode = PAGE_CUR_G;
@ -323,12 +319,10 @@ btr_pcur_restore_position(
the cursor can now be on a different page! But we can retain
the value of old_rec */
cursor->modify_clock =
buf_frame_get_modify_clock(btr_pcur_get_page(cursor));
cursor->block_when_stored =
buf_block_align(btr_pcur_get_page(cursor));
cursor->modify_clock =
buf_block_get_modify_clock(cursor->block_when_stored);
cursor->old_stored = BTR_PCUR_OLD_STORED;
mem_heap_free(heap);

View file

@ -435,7 +435,7 @@ btr_search_update_hash_ref(
offsets_, ULINT_UNDEFINED, &heap),
block->curr_n_fields,
block->curr_n_bytes, tree_id);
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
#ifdef UNIV_SYNC_DEBUG
@ -544,10 +544,7 @@ btr_search_check_guess(
or PAGE_CUR_GE */
mtr_t* mtr) /* in: mtr */
{
page_t* page;
rec_t* rec;
rec_t* prev_rec;
rec_t* next_rec;
ulint n_unique;
ulint match;
ulint bytes;
@ -561,7 +558,6 @@ btr_search_check_guess(
n_unique = dict_index_get_n_unique_in_tree(cursor->index);
rec = btr_cur_get_rec(cursor);
page = buf_frame_align(rec);
ut_ad(page_rec_is_user_rec(rec));
@ -611,13 +607,16 @@ btr_search_check_guess(
bytes = 0;
if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)) {
rec_t* prev_rec;
ut_ad(rec != page_get_infimum_rec(page));
ut_ad(!page_rec_is_infimum(rec));
prev_rec = page_rec_get_prev(rec);
if (prev_rec == page_get_infimum_rec(page)) {
success = btr_page_get_prev(page, mtr) == FIL_NULL;
if (page_rec_is_infimum(prev_rec)) {
success = btr_page_get_prev(
buf_frame_align(prev_rec), mtr) == FIL_NULL;
goto exit_func;
}
@ -632,34 +631,37 @@ btr_search_check_guess(
}
goto exit_func;
}
ut_ad(rec != page_get_supremum_rec(page));
} else {
rec_t* next_rec;
ut_ad(!page_rec_is_supremum(rec));
next_rec = page_rec_get_next(rec);
next_rec = page_rec_get_next(rec);
if (next_rec == page_get_supremum_rec(page)) {
if (btr_page_get_next(page, mtr) == FIL_NULL) {
if (page_rec_is_supremum(next_rec)) {
if (btr_page_get_next(
buf_frame_align(next_rec), mtr) == FIL_NULL) {
cursor->up_match = 0;
success = TRUE;
cursor->up_match = 0;
success = TRUE;
}
goto exit_func;
}
goto exit_func;
}
offsets = rec_get_offsets(next_rec, cursor->index, offsets,
offsets = rec_get_offsets(next_rec, cursor->index, offsets,
n_unique, &heap);
cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec,
offsets, &match, &bytes);
if (mode == PAGE_CUR_LE) {
success = cmp == -1;
cursor->up_match = match;
} else {
success = cmp != 1;
cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec,
offsets, &match, &bytes);
if (mode == PAGE_CUR_LE) {
success = cmp == -1;
cursor->up_match = match;
} else {
success = cmp != 1;
}
}
exit_func:
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(success);
@ -694,7 +696,6 @@ btr_search_guess_on_hash(
buf_block_t* block;
rec_t* rec;
page_t* page;
ibool success;
ulint fold;
ulint tuple_n_fields;
dulint tree_id;
@ -710,7 +711,7 @@ btr_search_guess_on_hash(
/* Note that, for efficiency, the struct info may not be protected by
any latch here! */
if (info->n_hash_potential == 0) {
if (UNIV_UNLIKELY(info->n_hash_potential == 0)) {
return(FALSE);
}
@ -720,12 +721,13 @@ btr_search_guess_on_hash(
tuple_n_fields = dtuple_get_n_fields(tuple);
if (tuple_n_fields < cursor->n_fields) {
if (UNIV_UNLIKELY(tuple_n_fields < cursor->n_fields)) {
return(FALSE);
}
if ((cursor->n_bytes > 0) && (tuple_n_fields <= cursor->n_fields)) {
if (UNIV_UNLIKELY(tuple_n_fields == cursor->n_fields)
&& (cursor->n_bytes > 0)) {
return(FALSE);
}
@ -740,39 +742,31 @@ btr_search_guess_on_hash(
cursor->fold = fold;
cursor->flag = BTR_CUR_HASH;
if (!has_search_latch) {
if (UNIV_LIKELY(!has_search_latch)) {
rw_lock_s_lock(&btr_search_latch);
}
ut_a(btr_search_latch.writer != RW_LOCK_EX);
ut_a(btr_search_latch.reader_count > 0);
ut_ad(btr_search_latch.writer != RW_LOCK_EX);
ut_ad(btr_search_latch.reader_count > 0);
rec = ha_search_and_get_data(btr_search_sys->hash_index, fold);
if (!rec) {
if (!has_search_latch) {
rw_lock_s_unlock(&btr_search_latch);
}
goto failure;
if (UNIV_UNLIKELY(!rec)) {
goto failure_unlock;
}
page = buf_frame_align(rec);
if (!has_search_latch) {
if (UNIV_LIKELY(!has_search_latch)) {
success = buf_page_get_known_nowait(latch_mode, page,
if (UNIV_UNLIKELY(!buf_page_get_known_nowait(latch_mode, page,
BUF_MAKE_YOUNG,
__FILE__, __LINE__,
mtr);
rw_lock_s_unlock(&btr_search_latch);
if (!success) {
goto failure;
mtr))) {
goto failure_unlock;
}
rw_lock_s_unlock(&btr_search_latch);
can_only_compare_to_cursor_rec = FALSE;
#ifdef UNIV_SYNC_DEBUG
@ -782,8 +776,8 @@ btr_search_guess_on_hash(
block = buf_block_align(page);
if (block->state == BUF_BLOCK_REMOVE_HASH) {
if (!has_search_latch) {
if (UNIV_UNLIKELY(block->state == BUF_BLOCK_REMOVE_HASH)) {
if (UNIV_LIKELY(!has_search_latch)) {
btr_leaf_page_release(page, latch_mode, mtr);
}
@ -791,51 +785,33 @@ btr_search_guess_on_hash(
goto failure;
}
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_a(page_rec_is_user_rec(rec));
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
ut_ad(page_rec_is_user_rec(rec));
btr_cur_position(index, rec, cursor);
/* Check the validity of the guess within the page */
if (0 != ut_dulint_cmp(tree_id, btr_page_get_index_id(page))) {
success = FALSE;
/*
fprintf(stderr, "Tree id %lu, page index id %lu fold %lu\n",
ut_dulint_get_low(tree_id),
ut_dulint_get_low(btr_page_get_index_id(page)),
fold);
*/
} else {
/* If we only have the latch on btr_search_latch, not on the
page, it only protects the columns of the record the cursor
is positioned on. We cannot look at the next of the previous
record to determine if our guess for the cursor position is
right. */
success = btr_search_check_guess(cursor,
can_only_compare_to_cursor_rec,
tuple, mode, mtr);
}
if (!success) {
if (!has_search_latch) {
/* If we only have the latch on btr_search_latch, not on the
page, it only protects the columns of the record the cursor
is positioned on. We cannot look at the next of the previous
record to determine if our guess for the cursor position is
right. */
if (UNIV_EXPECT(ut_dulint_cmp(tree_id, btr_page_get_index_id(page)), 0)
|| !btr_search_check_guess(cursor, can_only_compare_to_cursor_rec,
tuple, mode, mtr)) {
if (UNIV_LIKELY(!has_search_latch)) {
btr_leaf_page_release(page, latch_mode, mtr);
}
goto failure;
}
if (info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5) {
if (UNIV_LIKELY(info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5)) {
info->n_hash_potential++;
}
if (info->last_hash_succ != TRUE) {
info->last_hash_succ = TRUE;
}
#ifdef notdefined
/* These lines of code can be used in a debug version to check
the correctness of the searched cursor position: */
@ -843,15 +819,14 @@ btr_search_guess_on_hash(
info->last_hash_succ = FALSE;
/* Currently, does not work if the following fails: */
ut_a(!has_search_latch);
ut_ad(!has_search_latch);
btr_leaf_page_release(page, latch_mode, mtr);
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
&cursor2, 0, mtr);
if (mode == PAGE_CUR_GE
&& btr_cur_get_rec(&cursor2) == page_get_supremum_rec(
buf_frame_align(btr_cur_get_rec(&cursor2)))) {
&& page_rec_is_supremum(btr_cur_get_rec(&cursor2))) {
/* If mode is PAGE_CUR_GE, then the binary search
in the index tree may actually take us to the supremum
@ -861,22 +836,22 @@ btr_search_guess_on_hash(
btr_pcur_open_on_user_rec(index, tuple, mode, latch_mode,
&pcur, mtr);
ut_a(btr_pcur_get_rec(&pcur) == btr_cur_get_rec(cursor));
ut_ad(btr_pcur_get_rec(&pcur) == btr_cur_get_rec(cursor));
} else {
ut_a(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor));
ut_ad(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor));
}
/* NOTE that it is theoretically possible that the above assertions
fail if the page of the cursor gets removed from the buffer pool
meanwhile! Thus it might not be a bug. */
info->last_hash_succ = TRUE;
#endif
info->last_hash_succ = TRUE;
#ifdef UNIV_SEARCH_PERF_STAT
btr_search_n_succ++;
#endif
if (!has_search_latch && buf_block_peek_if_too_old(block)) {
if (UNIV_LIKELY(!has_search_latch)
&& buf_block_peek_if_too_old(block)) {
buf_page_make_young(page);
}
@ -889,6 +864,10 @@ btr_search_guess_on_hash(
return(TRUE);
/*-------------------------------------------*/
failure_unlock:
if (UNIV_LIKELY(!has_search_latch)) {
rw_lock_s_unlock(&btr_search_latch);
}
failure:
info->n_hash_fail++;
@ -917,7 +896,6 @@ btr_search_drop_page_hash_index(
ulint n_fields;
ulint n_bytes;
rec_t* rec;
rec_t* sup;
ulint fold;
ulint prev_fold;
dulint tree_id;
@ -968,12 +946,10 @@ btr_search_drop_page_hash_index(
n_cached = 0;
sup = page_get_supremum_rec(page);
rec = page_get_infimum_rec(page);
rec = page_rec_get_next(rec);
if (rec != sup) {
if (!page_rec_is_supremum(rec)) {
ut_a(n_fields <= rec_get_n_fields(rec, block->index));
if (n_bytes > 0) {
@ -988,7 +964,7 @@ btr_search_drop_page_hash_index(
heap = NULL;
offsets = NULL;
while (rec != sup) {
while (!page_rec_is_supremum(rec)) {
/* FIXME: in a mixed tree, not all records may have enough
ordering fields: */
offsets = rec_get_offsets(rec, block->index,
@ -1010,7 +986,7 @@ next_rec:
prev_fold = fold;
}
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@ -1090,7 +1066,6 @@ btr_search_build_page_hash_index(
buf_block_t* block;
rec_t* rec;
rec_t* next_rec;
rec_t* sup;
ulint fold;
ulint next_fold;
dulint tree_id;
@ -1158,15 +1133,13 @@ btr_search_build_page_hash_index(
tree_id = btr_page_get_index_id(page);
sup = page_get_supremum_rec(page);
rec = page_get_infimum_rec(page);
rec = page_rec_get_next(rec);
offsets = rec_get_offsets(rec, index, offsets,
n_fields + (n_bytes > 0), &heap);
if (rec != sup) {
if (!page_rec_is_supremum(rec)) {
ut_a(n_fields <= rec_offs_n_fields(offsets));
if (n_bytes > 0) {
@ -1188,7 +1161,7 @@ btr_search_build_page_hash_index(
for (;;) {
next_rec = page_rec_get_next(rec);
if (next_rec == sup) {
if (page_rec_is_supremum(next_rec)) {
if (side == BTR_SEARCH_RIGHT_SIDE) {
@ -1252,7 +1225,7 @@ exit_func:
mem_free(folds);
mem_free(recs);
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
}
@ -1370,7 +1343,7 @@ btr_search_update_hash_on_delete(
fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_,
ULINT_UNDEFINED, &heap), block->curr_n_fields,
block->curr_n_bytes, tree_id);
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
rw_lock_x_lock(&btr_search_latch);
@ -1443,7 +1416,6 @@ btr_search_update_hash_on_insert(
{
hash_table_t* table;
buf_block_t* block;
page_t* page;
rec_t* rec;
rec_t* ins_rec;
rec_t* next_rec;
@ -1488,19 +1460,18 @@ btr_search_update_hash_on_insert(
ins_rec = page_rec_get_next(rec);
next_rec = page_rec_get_next(ins_rec);
page = buf_frame_align(rec);
offsets = rec_get_offsets(ins_rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap);
ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, tree_id);
if (next_rec != page_get_supremum_rec(page)) {
if (!page_rec_is_supremum(next_rec)) {
offsets = rec_get_offsets(next_rec, cursor->index, offsets,
n_fields + (n_bytes > 0), &heap);
next_fold = rec_fold(next_rec, offsets, n_fields,
n_bytes, tree_id);
}
if (rec != page_get_infimum_rec(page)) {
if (!page_rec_is_infimum(rec)) {
offsets = rec_get_offsets(rec, cursor->index, offsets,
n_fields + (n_bytes > 0), &heap);
fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id);
@ -1534,7 +1505,7 @@ btr_search_update_hash_on_insert(
}
check_next_rec:
if (next_rec == page_get_supremum_rec(page)) {
if (page_rec_is_supremum(next_rec)) {
if (side == BTR_SEARCH_RIGHT_SIDE) {
@ -1573,7 +1544,7 @@ check_next_rec:
}
function_exit:
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
if (locked) {
@ -1662,7 +1633,7 @@ btr_search_validate(void)
}
rw_lock_x_unlock(&btr_search_latch);
if (heap) {
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}