mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 05:22:25 +01:00
Merge mskold@bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/usr/local/home/marty/MySQL/mysql-5.0
This commit is contained in:
commit
981e845d8f
94 changed files with 2091 additions and 1894 deletions
|
@ -303,6 +303,10 @@ SOURCE=..\mysys\mulalloc.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mysys\my_access.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\mysys\my_alloc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -1011,7 +1011,8 @@ static int read_lines(bool execute_commands)
|
|||
a nil, it still needs the space in the linebuffer for it. This is,
|
||||
naturally, undocumented.
|
||||
*/
|
||||
} while (linebuffer[0] <= linebuffer[1] + 1);
|
||||
} while ((unsigned char)linebuffer[0] <=
|
||||
(unsigned char)linebuffer[1] + 1);
|
||||
line= buffer.c_ptr();
|
||||
#endif /* __NETWARE__ */
|
||||
#else
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -223,13 +223,14 @@ in the free list to the frames.
|
|||
|
||||
buf_pool_t* buf_pool = NULL; /* The buffer buf_pool of the database */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint buf_dbg_counter = 0; /* This is used to insert validation
|
||||
operations in excution in the
|
||||
debug version */
|
||||
ibool buf_debug_prints = FALSE; /* If this is set TRUE,
|
||||
the program prints info whenever
|
||||
read-ahead or flush occurs */
|
||||
|
||||
#endif /* UNIV_DEBUG */
|
||||
/************************************************************************
|
||||
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 on
|
||||
|
@ -1286,8 +1287,9 @@ buf_page_optimistic_get_func(
|
|||
|
||||
/* If AWE is used, block may have a different frame now, e.g., NULL */
|
||||
|
||||
if (block->state != BUF_BLOCK_FILE_PAGE || block->frame != guess) {
|
||||
|
||||
if (UNIV_UNLIKELY(block->state != BUF_BLOCK_FILE_PAGE)
|
||||
|| UNIV_UNLIKELY(block->frame != guess)) {
|
||||
exit_func:
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
|
||||
return(FALSE);
|
||||
|
@ -1320,19 +1322,17 @@ buf_page_optimistic_get_func(
|
|||
fix_type = MTR_MEMO_PAGE_X_FIX;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
if (UNIV_UNLIKELY(!success)) {
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
block->buf_fix_count--;
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
rw_lock_s_unlock(&(block->debug_latch));
|
||||
#endif
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
|
||||
return(FALSE);
|
||||
#endif
|
||||
goto exit_func;
|
||||
}
|
||||
|
||||
if (!UT_DULINT_EQ(modify_clock, block->modify_clock)) {
|
||||
if (UNIV_UNLIKELY(!UT_DULINT_EQ(modify_clock, block->modify_clock))) {
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
buf_page_dbg_add_level(block->frame, SYNC_NO_ORDER_CHECK);
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
@ -1347,10 +1347,8 @@ buf_page_optimistic_get_func(
|
|||
block->buf_fix_count--;
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
rw_lock_s_unlock(&(block->debug_latch));
|
||||
#endif
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
|
||||
return(FALSE);
|
||||
#endif
|
||||
goto exit_func;
|
||||
}
|
||||
|
||||
mtr_memo_push(mtr, block, fix_type);
|
||||
|
@ -1368,7 +1366,7 @@ buf_page_optimistic_get_func(
|
|||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
ut_a(block->file_page_was_freed == FALSE);
|
||||
#endif
|
||||
if (!accessed) {
|
||||
if (UNIV_UNLIKELY(!accessed)) {
|
||||
/* In the case of a first access, try to apply linear
|
||||
read-ahead */
|
||||
|
||||
|
@ -1742,10 +1740,12 @@ buf_page_create(
|
|||
|
||||
/* If we get here, the page was not in buf_pool: init it there */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fprintf(stderr, "Creating space %lu page %lu to buffer\n",
|
||||
(ulong) space, (ulong) offset);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
block = free_block;
|
||||
|
||||
|
@ -1896,9 +1896,11 @@ buf_page_io_complete(
|
|||
|
||||
rw_lock_x_unlock_gen(&(block->lock), BUF_IO_READ);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fputs("Has read ", stderr);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
} else {
|
||||
ut_ad(io_type == BUF_IO_WRITE);
|
||||
|
||||
|
@ -1911,17 +1913,21 @@ buf_page_io_complete(
|
|||
|
||||
buf_pool->n_pages_written++;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fputs("Has written ", stderr);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
}
|
||||
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fprintf(stderr, "page space %lu page no %lu\n",
|
||||
(ulong) block->space, (ulong) block->offset);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -1950,6 +1956,7 @@ buf_pool_invalidate(void)
|
|||
mutex_exit(&(buf_pool->mutex));
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/*************************************************************************
|
||||
Validates the buffer buf_pool data structure. */
|
||||
|
||||
|
@ -2149,6 +2156,7 @@ buf_print(void)
|
|||
|
||||
ut_a(buf_validate());
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/*************************************************************************
|
||||
Returns the number of latched pages in the buffer pool. */
|
||||
|
|
|
@ -586,11 +586,13 @@ buf_flush_try_page(
|
|||
rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fprintf(stderr,
|
||||
"Flushing page space %lu, page no %lu \n",
|
||||
(ulong) block->space, (ulong) block->offset);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
buf_flush_write_block_low(block);
|
||||
|
||||
|
@ -674,12 +676,14 @@ buf_flush_try_page(
|
|||
|
||||
rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fprintf(stderr,
|
||||
"Flushing single page space %lu, page no %lu \n",
|
||||
(ulong) block->space,
|
||||
(ulong) block->offset);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
buf_flush_write_block_low(block);
|
||||
|
||||
|
@ -906,6 +910,7 @@ buf_flush_batch(
|
|||
|
||||
buf_flush_buffered_writes();
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints && page_count > 0) {
|
||||
ut_a(flush_type == BUF_FLUSH_LRU
|
||||
|| flush_type == BUF_FLUSH_LIST);
|
||||
|
@ -914,6 +919,7 @@ buf_flush_batch(
|
|||
: "Flushed %lu pages in flush list flush\n",
|
||||
(ulong) page_count);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
if (page_count != ULINT_UNDEFINED)
|
||||
srv_buf_pool_flushed+= page_count;
|
||||
|
|
|
@ -213,12 +213,14 @@ buf_LRU_search_and_free_block(
|
|||
ut_a(block->in_LRU_list);
|
||||
if (buf_flush_ready_for_replace(block)) {
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fprintf(stderr,
|
||||
"Putting space %lu page %lu to free list\n",
|
||||
(ulong) block->space,
|
||||
(ulong) block->offset);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
buf_LRU_block_remove_hashed_page(block);
|
||||
|
||||
|
@ -919,7 +921,8 @@ buf_LRU_block_free_hashed_page(
|
|||
|
||||
buf_LRU_block_free_non_file_page(block);
|
||||
}
|
||||
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/**************************************************************************
|
||||
Validates the LRU list. */
|
||||
|
||||
|
@ -1050,3 +1053,4 @@ buf_LRU_print(void)
|
|||
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
|
|
@ -288,12 +288,14 @@ buf_read_ahead_random(
|
|||
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints && (count > 0)) {
|
||||
fprintf(stderr,
|
||||
"Random read-ahead space %lu offset %lu pages %lu\n",
|
||||
(ulong) space, (ulong) offset,
|
||||
(ulong) count);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
++srv_read_ahead_rnd;
|
||||
return(count);
|
||||
|
@ -575,11 +577,13 @@ buf_read_ahead_linear(
|
|||
/* Flush pages from the end of the LRU list if necessary */
|
||||
buf_flush_free_margin();
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints && (count > 0)) {
|
||||
fprintf(stderr,
|
||||
"LINEAR read-ahead space %lu offset %lu pages %lu\n",
|
||||
(ulong) space, (ulong) offset, (ulong) count);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
++srv_read_ahead_seq;
|
||||
return(count);
|
||||
|
@ -641,11 +645,13 @@ buf_read_ibuf_merge_pages(
|
|||
/* Flush pages from the end of the LRU list if necessary */
|
||||
buf_flush_free_margin();
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fprintf(stderr,
|
||||
"Ibuf merge read-ahead space %lu pages %lu\n",
|
||||
(ulong) space_ids[0], (ulong) n_stored);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
@ -711,8 +717,10 @@ buf_read_recv_pages(
|
|||
/* Flush pages from the end of the LRU list if necessary */
|
||||
buf_flush_free_margin();
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fprintf(stderr,
|
||||
"Recovery applies read-ahead pages %lu\n", (ulong) n_stored);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
}
|
||||
|
|
|
@ -502,7 +502,7 @@ dtuple_convert_big_rec(
|
|||
|
||||
size = rec_get_converted_size(index, entry);
|
||||
|
||||
if (size > 1000000000) {
|
||||
if (UNIV_UNLIKELY(size > 1000000000)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Warning: tuple size very big: %lu\n", (ulong) size);
|
||||
fputs("InnoDB: Tuple contents: ", stderr);
|
||||
|
|
|
@ -39,7 +39,6 @@ column definitions, or records in the insert buffer, we use this
|
|||
charset-collation code for them. */
|
||||
|
||||
ulint data_mysql_default_charset_coll = 99999999;
|
||||
ulint data_mysql_latin1_swedish_charset_coll = 99999999;
|
||||
|
||||
dtype_t dtype_binary_val = {DATA_BINARY, 0, 0, 0, 0, 0};
|
||||
dtype_t* dtype_binary = &dtype_binary_val;
|
||||
|
@ -64,9 +63,10 @@ dtype_get_at_most_n_mbchars(
|
|||
{
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ut_a(data_len != UNIV_SQL_NULL);
|
||||
ut_a(!(prefix_len % dtype->mbmaxlen));
|
||||
ut_ad(!dtype->mbmaxlen || !(prefix_len % dtype->mbmaxlen));
|
||||
|
||||
if (dtype->mbminlen != dtype->mbmaxlen) {
|
||||
ut_a(!(prefix_len % dtype->mbmaxlen));
|
||||
return(innobase_get_at_most_n_mbchars(
|
||||
dtype_get_charset_coll(dtype->prtype),
|
||||
prefix_len, data_len, str));
|
||||
|
|
|
@ -66,15 +66,6 @@ dict_hdr_get_new_id(
|
|||
dict_hdr = dict_hdr_get(&mtr);
|
||||
|
||||
id = mtr_read_dulint(dict_hdr + type, &mtr);
|
||||
|
||||
/* Add some dummy code here because otherwise pgcc seems to
|
||||
compile wrong */
|
||||
|
||||
if (0 == ut_dulint_cmp(id, ut_dulint_max)) {
|
||||
/* TO DO: remove this code, or make it conditional */
|
||||
ut_dbg_null_ptr = 0;
|
||||
}
|
||||
|
||||
id = ut_dulint_add(id, 1);
|
||||
|
||||
mlog_write_dulint(dict_hdr + type, id, &mtr);
|
||||
|
|
|
@ -736,7 +736,7 @@ dict_truncate_index_tree(
|
|||
dulint index_id;
|
||||
byte* ptr;
|
||||
ulint len;
|
||||
ibool comp;
|
||||
ulint comp;
|
||||
dict_index_t* index;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
|
|
|
@ -1453,7 +1453,7 @@ dict_index_add_to_cache(
|
|||
|
||||
/* Increment the ord_part counts in columns which are ordering */
|
||||
|
||||
if (index->type & DICT_UNIVERSAL) {
|
||||
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
|
||||
n_ord = new_index->n_fields;
|
||||
} else {
|
||||
n_ord = dict_index_get_n_unique(new_index);
|
||||
|
@ -1482,7 +1482,7 @@ dict_index_add_to_cache(
|
|||
new_index->tree = tree;
|
||||
}
|
||||
|
||||
if (!(new_index->type & DICT_UNIVERSAL)) {
|
||||
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
|
||||
|
||||
new_index->stat_n_diff_key_vals =
|
||||
mem_heap_alloc(new_index->heap,
|
||||
|
@ -1683,7 +1683,7 @@ dict_index_copy_types(
|
|||
dtype_t* type;
|
||||
ulint i;
|
||||
|
||||
if (index->type & DICT_UNIVERSAL) {
|
||||
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
|
||||
dtuple_set_types_binary(tuple, n_fields);
|
||||
|
||||
return;
|
||||
|
@ -1779,7 +1779,7 @@ dict_index_build_internal_clust(
|
|||
dict_index_copy(new_index, index, 0, index->n_fields);
|
||||
}
|
||||
|
||||
if (index->type & DICT_UNIVERSAL) {
|
||||
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
|
||||
/* No fixed number of fields determines an entry uniquely */
|
||||
|
||||
new_index->n_uniq = ULINT_MAX;
|
||||
|
@ -3682,7 +3682,7 @@ dict_tree_find_index_low(
|
|||
table = index->table;
|
||||
|
||||
if ((index->type & DICT_CLUSTERED)
|
||||
&& (table->type != DICT_TABLE_ORDINARY)) {
|
||||
&& UNIV_UNLIKELY(table->type != DICT_TABLE_ORDINARY)) {
|
||||
|
||||
/* Get the mix id of the record */
|
||||
ut_a(!table->comp);
|
||||
|
@ -3838,7 +3838,7 @@ dict_tree_build_node_ptr(
|
|||
|
||||
ind = dict_tree_find_index_low(tree, rec);
|
||||
|
||||
if (tree->type & DICT_UNIVERSAL) {
|
||||
if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) {
|
||||
/* In a universal index tree, we take the whole record as
|
||||
the node pointer if the reord is on the leaf level,
|
||||
on non-leaf levels we remove the last field, which
|
||||
|
@ -3903,9 +3903,10 @@ dict_tree_copy_rec_order_prefix(
|
|||
dict_index_t* index;
|
||||
ulint n;
|
||||
|
||||
UNIV_PREFETCH_R(rec);
|
||||
index = dict_tree_find_index_low(tree, rec);
|
||||
|
||||
if (tree->type & DICT_UNIVERSAL) {
|
||||
if (UNIV_UNLIKELY(tree->type & DICT_UNIVERSAL)) {
|
||||
ut_a(!index->table->comp);
|
||||
n = rec_get_n_fields_old(rec);
|
||||
} else {
|
||||
|
@ -3957,7 +3958,7 @@ dict_index_calc_min_rec_len(
|
|||
ulint sum = 0;
|
||||
ulint i;
|
||||
|
||||
if (index->table->comp) {
|
||||
if (UNIV_LIKELY(index->table->comp)) {
|
||||
ulint nullable = 0;
|
||||
sum = REC_N_NEW_EXTRA_BYTES;
|
||||
for (i = 0; i < dict_index_get_n_fields(index); i++) {
|
||||
|
@ -4277,9 +4278,11 @@ dict_index_print_low(
|
|||
|
||||
putc('\n', stderr);
|
||||
|
||||
/* btr_print_size(tree); */
|
||||
#ifdef UNIV_BTR_PRINT
|
||||
btr_print_size(tree);
|
||||
|
||||
/* btr_print_tree(tree, 7); */
|
||||
btr_print_tree(tree, 7);
|
||||
#endif /* UNIV_BTR_PRINT */
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
|
|
@ -42,6 +42,7 @@ dict_mem_table_create(
|
|||
mem_heap_t* heap;
|
||||
|
||||
ut_ad(name);
|
||||
ut_ad(comp == FALSE || comp == TRUE);
|
||||
|
||||
heap = mem_heap_create(DICT_HEAP_SIZE);
|
||||
|
||||
|
|
|
@ -99,7 +99,6 @@ ulint fil_n_pending_tablespace_flushes = 0;
|
|||
fil_addr_t fil_addr_null = {FIL_NULL, 0};
|
||||
|
||||
/* File node of a tablespace or the log data space */
|
||||
typedef struct fil_node_struct fil_node_t;
|
||||
struct fil_node_struct {
|
||||
fil_space_t* space; /* backpointer to the space where this node
|
||||
belongs */
|
||||
|
@ -4046,7 +4045,7 @@ fil_aio_wait(
|
|||
} else {
|
||||
srv_set_io_thread_op_info(segment, "simulated aio handle");
|
||||
|
||||
ret = os_aio_simulated_handle(segment, (void**) &fil_node,
|
||||
ret = os_aio_simulated_handle(segment, &fil_node,
|
||||
&message, &type);
|
||||
}
|
||||
|
||||
|
|
|
@ -2325,7 +2325,6 @@ fseg_alloc_free_page_low(
|
|||
dulint seg_id;
|
||||
ulint used;
|
||||
ulint reserved;
|
||||
fil_addr_t first;
|
||||
xdes_t* descr; /* extent of the hinted page */
|
||||
ulint ret_page; /* the allocated page offset, FIL_NULL
|
||||
if could not be allocated */
|
||||
|
@ -2428,6 +2427,8 @@ fseg_alloc_free_page_low(
|
|||
} else if (reserved - used > 0) {
|
||||
/* 5. We take any unused page from the segment
|
||||
==============================================*/
|
||||
fil_addr_t first;
|
||||
|
||||
if (flst_get_len(seg_inode + FSEG_NOT_FULL, mtr) > 0) {
|
||||
first = flst_get_first(seg_inode + FSEG_NOT_FULL,
|
||||
mtr);
|
||||
|
@ -2435,6 +2436,7 @@ fseg_alloc_free_page_low(
|
|||
first = flst_get_first(seg_inode + FSEG_FREE, mtr);
|
||||
} else {
|
||||
ut_error;
|
||||
return(FIL_NULL);
|
||||
}
|
||||
|
||||
ret_descr = xdes_lst_get_descriptor(space, first, mtr);
|
||||
|
|
|
@ -1889,7 +1889,7 @@ ibuf_get_merge_page_nos(
|
|||
contract the tree, FALSE if this is called
|
||||
when a single page becomes full and we look
|
||||
if it pays to read also nearby pages */
|
||||
rec_t* first_rec,/* in: record from which we read up and down
|
||||
rec_t* rec, /* in: record from which we read up and down
|
||||
in the chain of records */
|
||||
ulint* space_ids,/* in/out: space id's of the pages */
|
||||
ib_longlong* space_versions,/* in/out: tablespace version
|
||||
|
@ -1907,47 +1907,42 @@ ibuf_get_merge_page_nos(
|
|||
ulint first_space_id;
|
||||
ulint rec_page_no;
|
||||
ulint rec_space_id;
|
||||
rec_t* rec;
|
||||
ulint sum_volumes;
|
||||
ulint volume_for_page;
|
||||
ulint rec_volume;
|
||||
ulint limit;
|
||||
page_t* page;
|
||||
ulint n_pages;
|
||||
|
||||
*n_stored = 0;
|
||||
|
||||
limit = ut_min(IBUF_MAX_N_PAGES_MERGED, buf_pool->curr_size / 4);
|
||||
|
||||
page = buf_frame_align(first_rec);
|
||||
|
||||
if (first_rec == page_get_supremum_rec(page)) {
|
||||
if (page_rec_is_supremum(rec)) {
|
||||
|
||||
first_rec = page_rec_get_prev(first_rec);
|
||||
rec = page_rec_get_prev(rec);
|
||||
}
|
||||
|
||||
if (first_rec == page_get_infimum_rec(page)) {
|
||||
if (page_rec_is_infimum(rec)) {
|
||||
|
||||
first_rec = page_rec_get_next(first_rec);
|
||||
rec = page_rec_get_next(rec);
|
||||
}
|
||||
|
||||
if (first_rec == page_get_supremum_rec(page)) {
|
||||
if (page_rec_is_supremum(rec)) {
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
rec = first_rec;
|
||||
first_page_no = ibuf_rec_get_page_no(first_rec);
|
||||
first_space_id = ibuf_rec_get_space(first_rec);
|
||||
first_page_no = ibuf_rec_get_page_no(rec);
|
||||
first_space_id = ibuf_rec_get_space(rec);
|
||||
n_pages = 0;
|
||||
prev_page_no = 0;
|
||||
prev_space_id = 0;
|
||||
|
||||
/* Go backwards from the first_rec until we reach the border of the
|
||||
/* Go backwards from the first rec until we reach the border of the
|
||||
'merge area', or the page start or the limit of storeable pages is
|
||||
reached */
|
||||
|
||||
while ((rec != page_get_infimum_rec(page)) && (n_pages < limit)) {
|
||||
while (!page_rec_is_infimum(rec) && UNIV_LIKELY(n_pages < limit)) {
|
||||
|
||||
rec_page_no = ibuf_rec_get_page_no(rec);
|
||||
rec_space_id = ibuf_rec_get_space(rec);
|
||||
|
@ -1982,7 +1977,7 @@ ibuf_get_merge_page_nos(
|
|||
volume_for_page = 0;
|
||||
|
||||
while (*n_stored < limit) {
|
||||
if (rec == page_get_supremum_rec(page)) {
|
||||
if (page_rec_is_supremum(rec)) {
|
||||
/* When no more records available, mark this with
|
||||
another 'impossible' pair of space id, page no */
|
||||
rec_page_no = 1;
|
||||
|
@ -2311,12 +2306,12 @@ ibuf_get_volume_buffered(
|
|||
|
||||
page = buf_frame_align(rec);
|
||||
|
||||
if (rec == page_get_supremum_rec(page)) {
|
||||
if (page_rec_is_supremum(rec)) {
|
||||
rec = page_rec_get_prev(rec);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (rec == page_get_infimum_rec(page)) {
|
||||
if (page_rec_is_infimum(rec)) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -2351,7 +2346,7 @@ ibuf_get_volume_buffered(
|
|||
rec = page_rec_get_prev(rec);
|
||||
|
||||
for (;;) {
|
||||
if (rec == page_get_infimum_rec(prev_page)) {
|
||||
if (page_rec_is_infimum(rec)) {
|
||||
|
||||
/* We cannot go to yet a previous page, because we
|
||||
do not have the x-latch on it, and cannot acquire one
|
||||
|
@ -2374,12 +2369,12 @@ ibuf_get_volume_buffered(
|
|||
count_later:
|
||||
rec = btr_pcur_get_rec(pcur);
|
||||
|
||||
if (rec != page_get_supremum_rec(page)) {
|
||||
if (!page_rec_is_supremum(rec)) {
|
||||
rec = page_rec_get_next(rec);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (rec == page_get_supremum_rec(page)) {
|
||||
if (page_rec_is_supremum(rec)) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -2414,7 +2409,7 @@ count_later:
|
|||
rec = page_rec_get_next(rec);
|
||||
|
||||
for (;;) {
|
||||
if (rec == page_get_supremum_rec(next_page)) {
|
||||
if (page_rec_is_supremum(rec)) {
|
||||
|
||||
/* We give up */
|
||||
|
||||
|
@ -2815,7 +2810,7 @@ ibuf_insert_to_index_page(
|
|||
ut_ad(ibuf_inside());
|
||||
ut_ad(dtuple_check_typed(entry));
|
||||
|
||||
if (index->table->comp != page_is_comp(page)) {
|
||||
if (UNIV_UNLIKELY(index->table->comp != !!page_is_comp(page))) {
|
||||
fputs(
|
||||
"InnoDB: Trying to insert a record from the insert buffer to an index page\n"
|
||||
"InnoDB: but the 'compact' flag does not match!\n", stderr);
|
||||
|
@ -2824,7 +2819,8 @@ ibuf_insert_to_index_page(
|
|||
|
||||
rec = page_rec_get_next(page_get_infimum_rec(page));
|
||||
|
||||
if (rec_get_n_fields(rec, index) != dtuple_get_n_fields(entry)) {
|
||||
if (UNIV_UNLIKELY(rec_get_n_fields(rec, index)
|
||||
!= dtuple_get_n_fields(entry))) {
|
||||
fputs(
|
||||
"InnoDB: Trying to insert a record from the insert buffer to an index page\n"
|
||||
"InnoDB: but the number of fields does not match!\n", stderr);
|
||||
|
@ -2848,7 +2844,7 @@ ibuf_insert_to_index_page(
|
|||
if (low_match == dtuple_get_n_fields(entry)) {
|
||||
rec = page_cur_get_rec(&page_cur);
|
||||
|
||||
btr_cur_del_unmark_for_ibuf(rec, index, mtr);
|
||||
btr_cur_del_unmark_for_ibuf(rec, mtr);
|
||||
} else {
|
||||
rec = page_cur_tuple_insert(&page_cur, entry, index, mtr);
|
||||
|
||||
|
@ -2861,8 +2857,8 @@ ibuf_insert_to_index_page(
|
|||
PAGE_CUR_LE, &page_cur);
|
||||
|
||||
/* This time the record must fit */
|
||||
if (!page_cur_tuple_insert(&page_cur, entry,
|
||||
index, mtr)) {
|
||||
if (UNIV_UNLIKELY(!page_cur_tuple_insert(
|
||||
&page_cur, entry, index, mtr))) {
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
|
@ -2969,7 +2965,9 @@ ibuf_delete_rec(
|
|||
btr_pcur_commit_specify_mtr(pcur, mtr);
|
||||
|
||||
fputs("InnoDB: Validating insert buffer tree:\n", stderr);
|
||||
ut_a(btr_validate_tree(ibuf_data->index->tree));
|
||||
if (!btr_validate_tree(ibuf_data->index->tree, NULL)) {
|
||||
ut_error;
|
||||
}
|
||||
|
||||
fprintf(stderr, "InnoDB: ibuf tree ok\n");
|
||||
fflush(stderr);
|
||||
|
|
|
@ -168,7 +168,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 */
|
||||
/****************************************************************
|
||||
Frees a B-tree except the root page, which MUST be freed after this
|
||||
|
@ -276,7 +276,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 */
|
||||
/*****************************************************************
|
||||
Deletes on the upper level the node pointer to a page. */
|
||||
|
@ -336,7 +336,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 */
|
||||
/***************************************************************
|
||||
|
@ -398,6 +398,7 @@ btr_page_free_low(
|
|||
page_t* page, /* in: page to be freed, x-latched */
|
||||
ulint level, /* in: page level */
|
||||
mtr_t* mtr); /* in: mtr */
|
||||
#ifdef UNIV_BTR_PRINT
|
||||
/*****************************************************************
|
||||
Prints size info of a B-tree. */
|
||||
|
||||
|
@ -414,6 +415,7 @@ btr_print_tree(
|
|||
dict_tree_t* tree, /* in: tree */
|
||||
ulint width); /* in: print this many entries from start
|
||||
and end */
|
||||
#endif /* UNIV_BTR_PRINT */
|
||||
/****************************************************************
|
||||
Checks the size and number of fields in a record based on the definition of
|
||||
the index. */
|
||||
|
@ -434,7 +436,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 */
|
||||
|
||||
#define BTR_N_LEAF_PAGES 1
|
||||
#define BTR_TOTAL_SIZE 2
|
||||
|
|
|
@ -200,10 +200,10 @@ btr_node_ptr_get_child_page_no(
|
|||
|
||||
page_no = mach_read_from_4(field);
|
||||
|
||||
if (page_no == 0) {
|
||||
if (UNIV_UNLIKELY(page_no == 0)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: a nonsensical page number 0 in a node ptr record at offset %lu\n",
|
||||
(unsigned long)(rec - buf_frame_align(rec)));
|
||||
(ulong) ut_align_offset(rec, UNIV_PAGE_SIZE));
|
||||
buf_page_print(buf_frame_align(rec));
|
||||
}
|
||||
|
||||
|
|
|
@ -284,7 +284,6 @@ 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 */
|
||||
/*****************************************************************
|
||||
Tries to compress a page of the tree on the leaf level. It is assumed
|
||||
|
@ -389,7 +388,6 @@ 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: index corresponding to page */
|
||||
page_t* page); /* in: page or NULL */
|
||||
/***********************************************************************
|
||||
Estimates the number of rows in a given index range. */
|
||||
|
|
|
@ -52,7 +52,9 @@ btr_cur_get_page(
|
|||
/* out: pointer to page */
|
||||
btr_cur_t* cursor) /* in: tree cursor */
|
||||
{
|
||||
return(buf_frame_align(page_cur_get_rec(&(cursor->page_cur))));
|
||||
page_t* page = buf_frame_align(page_cur_get_rec(&(cursor->page_cur)));
|
||||
ut_ad(!!page_is_comp(page) == cursor->index->table->comp);
|
||||
return(page);
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
|
|
|
@ -56,9 +56,11 @@ Created 11/5/1995 Heikki Tuuri
|
|||
#define BUF_NO_CHECKSUM_MAGIC 0xDEADBEEFUL
|
||||
|
||||
extern buf_pool_t* buf_pool; /* The buffer pool of the database */
|
||||
#ifdef UNIV_DEBUG
|
||||
extern ibool buf_debug_prints;/* If this is set TRUE, the program
|
||||
prints info whenever read or flush
|
||||
occurs */
|
||||
#endif /* UNIV_DEBUG */
|
||||
extern ulint srv_buf_pool_write_requests; /* variable to count write request
|
||||
issued */
|
||||
|
||||
|
@ -382,10 +384,10 @@ Returns the value of the modify clock. The caller must have an s-lock
|
|||
or x-lock on the block. */
|
||||
UNIV_INLINE
|
||||
dulint
|
||||
buf_frame_get_modify_clock(
|
||||
buf_block_get_modify_clock(
|
||||
/*=======================*/
|
||||
/* out: value */
|
||||
buf_frame_t* frame); /* in: pointer to a frame */
|
||||
buf_block_t* block); /* in: block */
|
||||
/************************************************************************
|
||||
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
|
||||
|
@ -480,12 +482,20 @@ buf_pool_is_block(
|
|||
/*==============*/
|
||||
/* out: TRUE if pointer to block */
|
||||
void* ptr); /* in: pointer to memory */
|
||||
#ifdef UNIV_DEBUG
|
||||
/*************************************************************************
|
||||
Validates the buffer pool data structure. */
|
||||
|
||||
ibool
|
||||
buf_validate(void);
|
||||
/*==============*/
|
||||
/*************************************************************************
|
||||
Prints info of the buffer pool data structure. */
|
||||
|
||||
void
|
||||
buf_print(void);
|
||||
/*============*/
|
||||
#endif /* UNIV_DEBUG */
|
||||
/************************************************************************
|
||||
Prints a page to stderr. */
|
||||
|
||||
|
@ -494,12 +504,6 @@ buf_page_print(
|
|||
/*===========*/
|
||||
byte* read_buf); /* in: a database page */
|
||||
/*************************************************************************
|
||||
Prints info of the buffer pool data structure. */
|
||||
|
||||
void
|
||||
buf_print(void);
|
||||
/*============*/
|
||||
/*************************************************************************
|
||||
Returns the number of latched pages in the buffer pool. */
|
||||
|
||||
ulint
|
||||
|
|
|
@ -11,10 +11,11 @@ Created 11/5/1995 Heikki Tuuri
|
|||
#include "buf0rea.h"
|
||||
#include "mtr0mtr.h"
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
extern ulint buf_dbg_counter; /* This is used to insert validation
|
||||
operations in execution in the
|
||||
debug version */
|
||||
|
||||
#endif /* UNIV_DEBUG */
|
||||
/************************************************************************
|
||||
Recommends a move of a block to the start of the LRU list if there is danger
|
||||
of dropping from the buffer pool. NOTE: does not reserve the buffer pool
|
||||
|
@ -26,12 +27,8 @@ buf_block_peek_if_too_old(
|
|||
/* out: TRUE if should be made younger */
|
||||
buf_block_t* block) /* in: block to make younger */
|
||||
{
|
||||
if (buf_pool->freed_page_clock >= block->freed_page_clock
|
||||
+ 1 + (buf_pool->curr_size / 1024)) {
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
return(buf_pool->freed_page_clock >= block->freed_page_clock
|
||||
+ 1 + (buf_pool->curr_size / 1024));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -210,8 +207,8 @@ buf_block_align(
|
|||
|
||||
frame_zero = buf_pool->frame_zero;
|
||||
|
||||
if ((ulint)ptr < (ulint)frame_zero
|
||||
|| (ulint)ptr > (ulint)(buf_pool->high_end)) {
|
||||
if (UNIV_UNLIKELY((ulint)ptr < (ulint)frame_zero)
|
||||
|| UNIV_UNLIKELY((ulint)ptr > (ulint)(buf_pool->high_end))) {
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
|
@ -246,8 +243,8 @@ buf_frame_align(
|
|||
|
||||
frame = ut_align_down(ptr, UNIV_PAGE_SIZE);
|
||||
|
||||
if (((ulint)frame < (ulint)(buf_pool->frame_zero))
|
||||
|| (ulint)frame >= (ulint)(buf_pool->high_end)) {
|
||||
if (UNIV_UNLIKELY((ulint)frame < (ulint)(buf_pool->frame_zero))
|
||||
|| UNIV_UNLIKELY((ulint)frame >= (ulint)(buf_pool->high_end))) {
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
|
@ -485,17 +482,11 @@ Returns the value of the modify clock. The caller must have an s-lock
|
|||
or x-lock on the block. */
|
||||
UNIV_INLINE
|
||||
dulint
|
||||
buf_frame_get_modify_clock(
|
||||
buf_block_get_modify_clock(
|
||||
/*=======================*/
|
||||
/* out: value */
|
||||
buf_frame_t* frame) /* in: pointer to a frame */
|
||||
buf_block_t* block) /* in: block */
|
||||
{
|
||||
buf_block_t* block;
|
||||
|
||||
ut_ad(frame);
|
||||
|
||||
block = buf_block_align(frame);
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
|
||||
|| rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
|
||||
|
|
|
@ -122,6 +122,7 @@ void
|
|||
buf_LRU_make_block_old(
|
||||
/*===================*/
|
||||
buf_block_t* block); /* in: control block */
|
||||
#ifdef UNIV_DEBUG
|
||||
/**************************************************************************
|
||||
Validates the LRU list. */
|
||||
|
||||
|
@ -134,6 +135,7 @@ Prints the LRU list. */
|
|||
void
|
||||
buf_LRU_print(void);
|
||||
/*===============*/
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "buf0lru.ic"
|
||||
|
|
|
@ -12,7 +12,7 @@ Created 1/16/1996 Heikki Tuuri
|
|||
#include "univ.i"
|
||||
|
||||
extern ulint data_mysql_default_charset_coll;
|
||||
extern ulint data_mysql_latin1_swedish_charset_coll;
|
||||
#define DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL 8
|
||||
|
||||
/* SQL data type struct */
|
||||
typedef struct dtype_struct dtype_t;
|
||||
|
|
|
@ -388,8 +388,8 @@ dtype_get_fixed_size(
|
|||
dtype_get_charset_coll(type->prtype),
|
||||
&mbminlen, &mbmaxlen);
|
||||
|
||||
if (type->mbminlen != mbminlen
|
||||
|| type->mbmaxlen != mbmaxlen) {
|
||||
if (UNIV_UNLIKELY(type->mbminlen != mbminlen)
|
||||
|| UNIV_UNLIKELY(type->mbmaxlen != mbmaxlen)) {
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB: "
|
||||
|
|
|
@ -132,7 +132,7 @@ void
|
|||
dyn_push_string(
|
||||
/*============*/
|
||||
dyn_array_t* arr, /* in: dyn array */
|
||||
byte* str, /* in: string to write */
|
||||
const byte* str, /* in: string to write */
|
||||
ulint len); /* in: string length */
|
||||
|
||||
/*#################################################################*/
|
||||
|
|
|
@ -324,10 +324,9 @@ void
|
|||
dyn_push_string(
|
||||
/*============*/
|
||||
dyn_array_t* arr, /* in: dyn array */
|
||||
byte* str, /* in: string to write */
|
||||
const byte* str, /* in: string to write */
|
||||
ulint len) /* in: string length */
|
||||
{
|
||||
byte* ptr;
|
||||
ulint n_copied;
|
||||
|
||||
while (len > 0) {
|
||||
|
@ -337,9 +336,7 @@ dyn_push_string(
|
|||
n_copied = len;
|
||||
}
|
||||
|
||||
ptr = (byte*) dyn_array_push(arr, n_copied);
|
||||
|
||||
ut_memcpy(ptr, str, n_copied);
|
||||
memcpy(dyn_array_push(arr, n_copied), str, n_copied);
|
||||
|
||||
str += n_copied;
|
||||
len -= n_copied;
|
||||
|
|
|
@ -19,7 +19,9 @@ Created 5/7/1996 Heikki Tuuri
|
|||
#include "read0types.h"
|
||||
#include "hash0hash.h"
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
extern ibool lock_print_waits;
|
||||
#endif /* UNIV_DEBUG */
|
||||
/* Buffer for storing information about the most recent deadlock error */
|
||||
extern FILE* lock_latest_err_file;
|
||||
|
||||
|
@ -216,6 +218,7 @@ actual record is being moved. */
|
|||
void
|
||||
lock_rec_store_on_page_infimum(
|
||||
/*===========================*/
|
||||
page_t* page, /* in: page containing the record */
|
||||
rec_t* rec); /* in: record whose lock state is stored
|
||||
on the infimum record of the same page; lock
|
||||
bits are reset on the record */
|
||||
|
@ -412,9 +415,7 @@ lock_table(
|
|||
/* out: DB_SUCCESS, DB_LOCK_WAIT,
|
||||
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
|
||||
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
|
||||
does nothing;
|
||||
if LOCK_TABLE_EXP bits are set,
|
||||
creates an explicit table lock */
|
||||
does nothing */
|
||||
dict_table_t* table, /* in: database table in dictionary cache */
|
||||
ulint mode, /* in: lock mode */
|
||||
que_thr_t* thr); /* in: query thread */
|
||||
|
@ -451,15 +452,6 @@ lock_release_off_kernel(
|
|||
/*====================*/
|
||||
trx_t* trx); /* in: transaction */
|
||||
/*************************************************************************
|
||||
Releases table locks explicitly requested with LOCK TABLES (indicated by
|
||||
lock type LOCK_TABLE_EXP), and releases possible other transactions waiting
|
||||
because of these locks. */
|
||||
|
||||
void
|
||||
lock_release_tables_off_kernel(
|
||||
/*===========================*/
|
||||
trx_t* trx); /* in: transaction */
|
||||
/*************************************************************************
|
||||
Cancels a waiting lock request and releases possible other transactions
|
||||
waiting behind it. */
|
||||
|
||||
|
@ -618,9 +610,6 @@ extern lock_sys_t* lock_sys;
|
|||
/* Lock types */
|
||||
#define LOCK_TABLE 16 /* these type values should be so high that */
|
||||
#define LOCK_REC 32 /* they can be ORed to the lock mode */
|
||||
#define LOCK_TABLE_EXP 80 /* explicit table lock (80 = 16 + 64) */
|
||||
#define LOCK_TABLE_TRANSACTIONAL 144
|
||||
/* transactional table lock (144 = 16 + 128)*/
|
||||
#define LOCK_TYPE_MASK 0xF0UL /* mask used to extract lock type from the
|
||||
type_mode field in a lock */
|
||||
/* Waiting lock flag */
|
||||
|
|
|
@ -17,8 +17,12 @@ Created 12/9/1995 Heikki Tuuri
|
|||
typedef struct log_struct log_t;
|
||||
typedef struct log_group_struct log_group_t;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
extern ibool log_do_write;
|
||||
extern ibool log_debug_writes;
|
||||
#else /* UNIV_DEBUG */
|
||||
# define log_do_write TRUE
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/* Wait modes for log_write_up_to */
|
||||
#define LOG_NO_WAIT 91
|
||||
|
|
|
@ -52,6 +52,27 @@ mach_read_from_2(
|
|||
/*=============*/
|
||||
/* out: ulint integer, >= 0, < 64k */
|
||||
byte* b); /* in: pointer to two bytes */
|
||||
|
||||
/************************************************************
|
||||
The following function is used to convert a 16-bit data item
|
||||
to the canonical format, for fast bytewise equality test
|
||||
against memory. */
|
||||
UNIV_INLINE
|
||||
uint16
|
||||
mach_encode_2(
|
||||
/*==========*/
|
||||
/* out: 16-bit integer in canonical format */
|
||||
ulint n); /* in: integer in machine-dependent format */
|
||||
/************************************************************
|
||||
The following function is used to convert a 16-bit data item
|
||||
from the canonical format, for fast bytewise equality test
|
||||
against memory. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_decode_2(
|
||||
/*==========*/
|
||||
/* out: integer in machine-dependent format */
|
||||
uint16 n); /* in: 16-bit integer in canonical format */
|
||||
/***********************************************************
|
||||
The following function is used to store data in 3 consecutive
|
||||
bytes. We store the most significant byte to the lowest address. */
|
||||
|
|
|
@ -68,6 +68,37 @@ mach_read_from_2(
|
|||
);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
The following function is used to convert a 16-bit data item
|
||||
to the canonical format, for fast bytewise equality test
|
||||
against memory. */
|
||||
UNIV_INLINE
|
||||
uint16
|
||||
mach_encode_2(
|
||||
/*==========*/
|
||||
/* out: 16-bit integer in canonical format */
|
||||
ulint n) /* in: integer in machine-dependent format */
|
||||
{
|
||||
uint16 ret;
|
||||
ut_ad(2 == sizeof ret);
|
||||
mach_write_to_2((byte*) &ret, n);
|
||||
return(ret);
|
||||
}
|
||||
/************************************************************
|
||||
The following function is used to convert a 16-bit data item
|
||||
from the canonical format, for fast bytewise equality test
|
||||
against memory. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
mach_decode_2(
|
||||
/*==========*/
|
||||
/* out: integer in machine-dependent format */
|
||||
uint16 n) /* in: 16-bit integer in canonical format */
|
||||
{
|
||||
ut_ad(2 == sizeof n);
|
||||
return(mach_read_from_2((byte*) &n));
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
The following function is used to store data in 3 consecutive
|
||||
bytes. We store the most significant byte to the lowest address. */
|
||||
|
|
|
@ -623,7 +623,7 @@ mem_strdupq(
|
|||
}
|
||||
*d++ = q;
|
||||
*d++ = '\0';
|
||||
ut_ad(len == d - dst);
|
||||
ut_ad((ssize_t) len == d - dst);
|
||||
return(dst);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,10 +41,10 @@ corresponding log record to the mini-transaction log. */
|
|||
void
|
||||
mlog_write_string(
|
||||
/*==============*/
|
||||
byte* ptr, /* in: pointer where to write */
|
||||
byte* str, /* in: string to write */
|
||||
ulint len, /* in: string length */
|
||||
mtr_t* mtr); /* in: mini-transaction handle */
|
||||
byte* ptr, /* in: pointer where to write */
|
||||
const byte* str, /* in: string to write */
|
||||
ulint len, /* in: string length */
|
||||
mtr_t* mtr); /* in: mini-transaction handle */
|
||||
/************************************************************
|
||||
Writes initial part of a log record consisting of one-byte item
|
||||
type and four-byte space and page numbers. */
|
||||
|
@ -85,9 +85,9 @@ Catenates n bytes to the mtr log. */
|
|||
void
|
||||
mlog_catenate_string(
|
||||
/*=================*/
|
||||
mtr_t* mtr, /* in: mtr */
|
||||
byte* str, /* in: string to write */
|
||||
ulint len); /* in: string length */
|
||||
mtr_t* mtr, /* in: mtr */
|
||||
const byte* str, /* in: string to write */
|
||||
ulint len); /* in: string length */
|
||||
/************************************************************
|
||||
Catenates a compressed ulint to mlog. */
|
||||
UNIV_INLINE
|
||||
|
|
|
@ -112,7 +112,11 @@ flag value must give the length also! */
|
|||
/* mark compact clustered index
|
||||
record deleted */
|
||||
#define MLOG_COMP_REC_SEC_DELETE_MARK ((byte)40)/* mark compact secondary index
|
||||
record deleted */
|
||||
record deleted; this log
|
||||
record type is redundant, as
|
||||
MLOG_REC_SEC_DELETE_MARK is
|
||||
independent of the record
|
||||
format. */
|
||||
#define MLOG_COMP_REC_UPDATE_IN_PLACE ((byte)41)/* update of a compact record,
|
||||
preserves record field sizes */
|
||||
#define MLOG_COMP_REC_DELETE ((byte)42) /* delete a compact record
|
||||
|
|
|
@ -17,6 +17,8 @@ Created 10/21/1995 Heikki Tuuri
|
|||
#include <time.h>
|
||||
#endif
|
||||
|
||||
typedef struct fil_node_struct fil_node_t;
|
||||
|
||||
extern ibool os_do_not_call_flush_at_each_write;
|
||||
extern ibool os_has_said_disk_full;
|
||||
extern ibool os_aio_print_debug;
|
||||
|
@ -563,7 +565,7 @@ os_aio(
|
|||
ulint offset_high, /* in: most significant 32 bits of
|
||||
offset */
|
||||
ulint n, /* in: number of bytes to read or write */
|
||||
void* message1,/* in: messages for the aio handler (these
|
||||
fil_node_t* message1,/* in: messages for the aio handler (these
|
||||
can be used to identify a completed aio
|
||||
operation); if mode is OS_AIO_SYNC, these
|
||||
are ignored */
|
||||
|
@ -621,7 +623,7 @@ os_aio_windows_handle(
|
|||
ignored */
|
||||
ulint pos, /* this parameter is used only in sync aio:
|
||||
wait for the aio slot at this position */
|
||||
void** message1, /* out: the messages passed with the aio
|
||||
fil_node_t**message1, /* out: the messages passed with the aio
|
||||
request; note that also in the case where
|
||||
the aio operation failed, these output
|
||||
parameters are valid and can be used to
|
||||
|
@ -641,7 +643,7 @@ os_aio_posix_handle(
|
|||
/*================*/
|
||||
/* out: TRUE if the aio operation succeeded */
|
||||
ulint array_no, /* in: array number 0 - 3 */
|
||||
void** message1, /* out: the messages passed with the aio
|
||||
fil_node_t**message1, /* out: the messages passed with the aio
|
||||
request; note that also in the case where
|
||||
the aio operation failed, these output
|
||||
parameters are valid and can be used to
|
||||
|
@ -661,7 +663,7 @@ os_aio_simulated_handle(
|
|||
i/o thread, segment 1 the log i/o thread,
|
||||
then follow the non-ibuf read threads, and as
|
||||
the last are the non-ibuf write threads */
|
||||
void** message1, /* out: the messages passed with the aio
|
||||
fil_node_t**message1, /* out: the messages passed with the aio
|
||||
request; note that also in the case where
|
||||
the aio operation failed, these output
|
||||
parameters are valid and can be used to
|
||||
|
@ -688,6 +690,8 @@ Refreshes the statistics used to print per-second averages. */
|
|||
void
|
||||
os_aio_refresh_stats(void);
|
||||
/*======================*/
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/**************************************************************************
|
||||
Checks that all slots in the system have been freed, that is, there are
|
||||
no pending io operations. */
|
||||
|
@ -695,6 +699,7 @@ no pending io operations. */
|
|||
ibool
|
||||
os_aio_all_slots_free(void);
|
||||
/*=======================*/
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/***********************************************************************
|
||||
This function returns information about the specified file */
|
||||
|
|
|
@ -78,16 +78,16 @@ UNIV_INLINE
|
|||
ibool
|
||||
page_cur_is_before_first(
|
||||
/*=====================*/
|
||||
/* out: TRUE if at start */
|
||||
page_cur_t* cur); /* in: cursor */
|
||||
/* out: TRUE if at start */
|
||||
const page_cur_t* cur); /* in: cursor */
|
||||
/*************************************************************
|
||||
Returns TRUE if the cursor is after last user record. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
page_cur_is_after_last(
|
||||
/*===================*/
|
||||
/* out: TRUE if at end */
|
||||
page_cur_t* cur); /* in: cursor */
|
||||
/* out: TRUE if at end */
|
||||
const page_cur_t* cur); /* in: cursor */
|
||||
/**************************************************************
|
||||
Positions the cursor on the given record. */
|
||||
UNIV_INLINE
|
||||
|
|
|
@ -69,15 +69,10 @@ UNIV_INLINE
|
|||
ibool
|
||||
page_cur_is_before_first(
|
||||
/*=====================*/
|
||||
/* out: TRUE if at start */
|
||||
page_cur_t* cur) /* in: cursor */
|
||||
/* out: TRUE if at start */
|
||||
const page_cur_t* cur) /* in: cursor */
|
||||
{
|
||||
if (page_get_infimum_rec(page_cur_get_page(cur)) == cur->rec) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
return(page_rec_is_infimum(cur->rec));
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
|
@ -86,15 +81,10 @@ UNIV_INLINE
|
|||
ibool
|
||||
page_cur_is_after_last(
|
||||
/*===================*/
|
||||
/* out: TRUE if at end */
|
||||
page_cur_t* cur) /* in: cursor */
|
||||
/* out: TRUE if at end */
|
||||
const page_cur_t* cur) /* in: cursor */
|
||||
{
|
||||
if (page_get_supremum_rec(page_cur_get_page(cur)) == cur->rec) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
return(page_rec_is_supremum(cur->rec));
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
|
|
|
@ -373,13 +373,21 @@ page_dir_find_owner_slot(
|
|||
/****************************************************************
|
||||
Determine whether the page is in new-style compact format. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ulint
|
||||
page_is_comp(
|
||||
/*=========*/
|
||||
/* out: TRUE if the page is in compact format
|
||||
FALSE if it is in old-style format */
|
||||
/* out: nonzero if the page is in compact
|
||||
format, zero if it is in old-style format */
|
||||
page_t* page); /* in: index page */
|
||||
/****************************************************************
|
||||
TRUE if the record is on a page in compact format. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
page_rec_is_comp(
|
||||
/*=============*/
|
||||
/* out: nonzero if in compact format */
|
||||
const rec_t* rec); /* in: record */
|
||||
/****************************************************************
|
||||
Gets the pointer to the next record on the page. */
|
||||
UNIV_INLINE
|
||||
rec_t*
|
||||
|
@ -407,6 +415,30 @@ page_rec_get_prev(
|
|||
/* out: pointer to previous record */
|
||||
rec_t* rec); /* in: pointer to record,
|
||||
must not be page infimum */
|
||||
/****************************************************************
|
||||
TRUE if the record is a user record on the page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
page_rec_is_user_rec_low(
|
||||
/*=====================*/
|
||||
/* out: TRUE if a user record */
|
||||
ulint offset);/* in: record offset on page */
|
||||
/****************************************************************
|
||||
TRUE if the record is the supremum record on a page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
page_rec_is_supremum_low(
|
||||
/*=====================*/
|
||||
/* out: TRUE if the supremum record */
|
||||
ulint offset);/* in: record offset on page */
|
||||
/****************************************************************
|
||||
TRUE if the record is the infimum record on a page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
page_rec_is_infimum_low(
|
||||
/*=====================*/
|
||||
/* out: TRUE if the infimum record */
|
||||
ulint offset);/* in: record offset on page */
|
||||
|
||||
/****************************************************************
|
||||
TRUE if the record is a user record on the page. */
|
||||
|
@ -414,40 +446,24 @@ UNIV_INLINE
|
|||
ibool
|
||||
page_rec_is_user_rec(
|
||||
/*=================*/
|
||||
/* out: TRUE if a user record */
|
||||
rec_t* rec); /* in: record */
|
||||
/* out: TRUE if a user record */
|
||||
const rec_t* rec); /* in: record */
|
||||
/****************************************************************
|
||||
TRUE if the record is the supremum record on a page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
page_rec_is_supremum(
|
||||
/*=================*/
|
||||
/* out: TRUE if the supremum record */
|
||||
rec_t* rec); /* in: record */
|
||||
/* out: TRUE if the supremum record */
|
||||
const rec_t* rec); /* in: record */
|
||||
/****************************************************************
|
||||
TRUE if the record is the infimum record on a page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
page_rec_is_infimum(
|
||||
/*================*/
|
||||
/* out: TRUE if the infimum record */
|
||||
rec_t* rec); /* in: record */
|
||||
/****************************************************************
|
||||
TRUE if the record is the first user record on the page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
page_rec_is_first_user_rec(
|
||||
/*=======================*/
|
||||
/* out: TRUE if first user record */
|
||||
rec_t* rec); /* in: record */
|
||||
/****************************************************************
|
||||
TRUE if the record is the last user record on the page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
page_rec_is_last_user_rec(
|
||||
/*======================*/
|
||||
/* out: TRUE if last user record */
|
||||
rec_t* rec); /* in: record */
|
||||
/* out: TRUE if the infimum record */
|
||||
const rec_t* rec); /* in: record */
|
||||
/*******************************************************************
|
||||
Looks for the record which owns the given record. */
|
||||
UNIV_INLINE
|
||||
|
@ -495,7 +511,7 @@ ulint
|
|||
page_get_free_space_of_empty(
|
||||
/*=========================*/
|
||||
/* out: free space */
|
||||
ibool comp) /* in: TRUE=compact page format */
|
||||
ulint comp) /* in: nonzero=compact page format */
|
||||
__attribute__((const));
|
||||
/****************************************************************
|
||||
Returns the sum of the sizes of the records in the record list
|
||||
|
@ -539,7 +555,7 @@ page_create(
|
|||
buf_frame_t* frame, /* in: a buffer frame where the page is
|
||||
created */
|
||||
mtr_t* mtr, /* in: mini-transaction handle */
|
||||
ibool comp); /* in: TRUE=compact page format */
|
||||
ulint comp); /* in: nonzero=compact page format */
|
||||
/*****************************************************************
|
||||
Differs from page_copy_rec_list_end, because this function does not
|
||||
touch the lock table and max trx id on page. */
|
||||
|
@ -673,7 +689,7 @@ page_parse_create(
|
|||
/* 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 */
|
||||
/****************************************************************
|
||||
|
|
|
@ -155,14 +155,27 @@ page_header_reset_last_insert(
|
|||
/****************************************************************
|
||||
Determine whether the page is in new-style compact format. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ulint
|
||||
page_is_comp(
|
||||
/*=========*/
|
||||
/* out: TRUE if the page is in compact format
|
||||
FALSE if it is in old-style format */
|
||||
page_t* page) /* in: index page */
|
||||
/* out: nonzero if the page is in compact
|
||||
format, zero if it is in old-style format */
|
||||
page_t* page) /* in: index page */
|
||||
{
|
||||
return(!!(page_header_get_field(page, PAGE_N_HEAP) & 0x8000));
|
||||
return(UNIV_EXPECT(page_header_get_field(page, PAGE_N_HEAP) & 0x8000,
|
||||
0x8000));
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
TRUE if the record is on a page in compact format. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
page_rec_is_comp(
|
||||
/*=============*/
|
||||
/* out: nonzero if in compact format */
|
||||
const rec_t* rec) /* in: record */
|
||||
{
|
||||
return(page_is_comp(ut_align_down((rec_t*) rec, UNIV_PAGE_SIZE)));
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
|
@ -201,28 +214,85 @@ page_get_supremum_rec(
|
|||
}
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
TRUE if the record is a user record on the page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
page_rec_is_user_rec_low(
|
||||
/*=====================*/
|
||||
/* out: TRUE if a user record */
|
||||
ulint offset) /* in: record offset on page */
|
||||
{
|
||||
ut_ad(offset >= PAGE_NEW_INFIMUM);
|
||||
#if PAGE_OLD_INFIMUM < PAGE_NEW_INFIMUM
|
||||
# error "PAGE_OLD_INFIMUM < PAGE_NEW_INFIMUM"
|
||||
#endif
|
||||
#if PAGE_OLD_SUPREMUM < PAGE_NEW_SUPREMUM
|
||||
# error "PAGE_OLD_SUPREMUM < PAGE_NEW_SUPREMUM"
|
||||
#endif
|
||||
#if PAGE_NEW_INFIMUM > PAGE_OLD_SUPREMUM
|
||||
# error "PAGE_NEW_INFIMUM > PAGE_OLD_SUPREMUM"
|
||||
#endif
|
||||
#if PAGE_OLD_INFIMUM > PAGE_NEW_SUPREMUM
|
||||
# error "PAGE_OLD_INFIMUM > PAGE_NEW_SUPREMUM"
|
||||
#endif
|
||||
#if PAGE_NEW_SUPREMUM > PAGE_OLD_SUPREMUM_END
|
||||
# error "PAGE_NEW_SUPREMUM > PAGE_OLD_SUPREMUM_END"
|
||||
#endif
|
||||
#if PAGE_OLD_SUPREMUM > PAGE_NEW_SUPREMUM_END
|
||||
# error "PAGE_OLD_SUPREMUM > PAGE_NEW_SUPREMUM_END"
|
||||
#endif
|
||||
ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START);
|
||||
|
||||
return(UNIV_LIKELY(offset != PAGE_NEW_SUPREMUM)
|
||||
&& UNIV_LIKELY(offset != PAGE_NEW_INFIMUM)
|
||||
&& UNIV_LIKELY(offset != PAGE_OLD_INFIMUM)
|
||||
&& UNIV_LIKELY(offset != PAGE_OLD_SUPREMUM));
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
TRUE if the record is the supremum record on a page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
page_rec_is_supremum_low(
|
||||
/*=====================*/
|
||||
/* out: TRUE if the supremum record */
|
||||
ulint offset) /* in: record offset on page */
|
||||
{
|
||||
ut_ad(offset >= PAGE_NEW_INFIMUM);
|
||||
ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START);
|
||||
|
||||
return(UNIV_UNLIKELY(offset == PAGE_NEW_SUPREMUM)
|
||||
|| UNIV_UNLIKELY(offset == PAGE_OLD_SUPREMUM));
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
TRUE if the record is the infimum record on a page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
page_rec_is_infimum_low(
|
||||
/*=====================*/
|
||||
/* out: TRUE if the infimum record */
|
||||
ulint offset) /* in: record offset on page */
|
||||
{
|
||||
ut_ad(offset >= PAGE_NEW_INFIMUM);
|
||||
ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START);
|
||||
|
||||
return(UNIV_UNLIKELY(offset == PAGE_NEW_INFIMUM)
|
||||
|| UNIV_UNLIKELY(offset == PAGE_OLD_INFIMUM));
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
TRUE if the record is a user record on the page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
page_rec_is_user_rec(
|
||||
/*=================*/
|
||||
/* out: TRUE if a user record */
|
||||
rec_t* rec) /* in: record */
|
||||
/* out: TRUE if a user record */
|
||||
const rec_t* rec) /* in: record */
|
||||
{
|
||||
ut_ad(rec);
|
||||
|
||||
if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (rec == page_get_infimum_rec(buf_frame_align(rec))) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
return(page_rec_is_user_rec_low(
|
||||
ut_align_offset(rec, UNIV_PAGE_SIZE)));
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
|
@ -231,17 +301,11 @@ UNIV_INLINE
|
|||
ibool
|
||||
page_rec_is_supremum(
|
||||
/*=================*/
|
||||
/* out: TRUE if the supremum record */
|
||||
rec_t* rec) /* in: record */
|
||||
/* out: TRUE if the supremum record */
|
||||
const rec_t* rec) /* in: record */
|
||||
{
|
||||
ut_ad(rec);
|
||||
|
||||
if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
return(page_rec_is_supremum_low(
|
||||
ut_align_offset(rec, UNIV_PAGE_SIZE)));
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
|
@ -250,67 +314,11 @@ UNIV_INLINE
|
|||
ibool
|
||||
page_rec_is_infimum(
|
||||
/*================*/
|
||||
/* out: TRUE if the infimum record */
|
||||
rec_t* rec) /* in: record */
|
||||
/* out: TRUE if the infimum record */
|
||||
const rec_t* rec) /* in: record */
|
||||
{
|
||||
ut_ad(rec);
|
||||
|
||||
if (rec == page_get_infimum_rec(buf_frame_align(rec))) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
TRUE if the record is the first user record on the page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
page_rec_is_first_user_rec(
|
||||
/*=======================*/
|
||||
/* out: TRUE if first user record */
|
||||
rec_t* rec) /* in: record */
|
||||
{
|
||||
ut_ad(rec);
|
||||
|
||||
if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (rec == page_rec_get_next(
|
||||
page_get_infimum_rec(buf_frame_align(rec)))) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
TRUE if the record is the last user record on the page. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
page_rec_is_last_user_rec(
|
||||
/*======================*/
|
||||
/* out: TRUE if last user record */
|
||||
rec_t* rec) /* in: record */
|
||||
{
|
||||
ut_ad(rec);
|
||||
|
||||
if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (page_rec_get_next(rec)
|
||||
== page_get_supremum_rec(buf_frame_align(rec))) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
return(page_rec_is_infimum_low(
|
||||
ut_align_offset(rec, UNIV_PAGE_SIZE)));
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
|
@ -340,22 +348,26 @@ page_cmp_dtuple_rec_with_match(
|
|||
matched; when function returns contains the
|
||||
value for current comparison */
|
||||
{
|
||||
page_t* page;
|
||||
ulint rec_offset;
|
||||
|
||||
ut_ad(dtuple_check_typed(dtuple));
|
||||
ut_ad(rec_offs_validate(rec, NULL, offsets));
|
||||
ut_ad(!rec_offs_comp(offsets) == !page_rec_is_comp(rec));
|
||||
|
||||
page = buf_frame_align(rec);
|
||||
rec_offset = ut_align_offset(rec, UNIV_PAGE_SIZE);
|
||||
|
||||
if (rec == page_get_infimum_rec(page)) {
|
||||
if (UNIV_UNLIKELY(rec_offset == PAGE_NEW_INFIMUM)
|
||||
|| UNIV_UNLIKELY(rec_offset == PAGE_OLD_INFIMUM)) {
|
||||
return(1);
|
||||
} else if (rec == page_get_supremum_rec(page)) {
|
||||
}
|
||||
if (UNIV_UNLIKELY(rec_offset == PAGE_NEW_SUPREMUM)
|
||||
|| UNIV_UNLIKELY(rec_offset == PAGE_OLD_SUPREMUM)) {
|
||||
return(-1);
|
||||
} else {
|
||||
return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
|
||||
}
|
||||
|
||||
return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
|
||||
matched_fields,
|
||||
matched_bytes));
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
|
@ -482,7 +494,7 @@ page_dir_slot_set_rec(
|
|||
{
|
||||
ut_ad(page_rec_check(rec));
|
||||
|
||||
mach_write_to_2(slot, rec - buf_frame_align(rec));
|
||||
mach_write_to_2(slot, ut_align_offset(rec, UNIV_PAGE_SIZE));
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
@ -494,8 +506,8 @@ page_dir_slot_get_n_owned(
|
|||
/* out: number of records */
|
||||
page_dir_slot_t* slot) /* in: page directory slot */
|
||||
{
|
||||
return(rec_get_n_owned(page_dir_slot_get_rec(slot),
|
||||
page_is_comp(buf_frame_align(slot))));
|
||||
rec_t* rec = page_dir_slot_get_rec(slot);
|
||||
return(rec_get_n_owned(rec, page_rec_is_comp(rec)));
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
@ -508,8 +520,8 @@ page_dir_slot_set_n_owned(
|
|||
ulint n) /* in: number of records owned
|
||||
by the slot */
|
||||
{
|
||||
rec_set_n_owned(page_dir_slot_get_rec(slot),
|
||||
page_is_comp(buf_frame_align(slot)), n);
|
||||
rec_t* rec = page_dir_slot_get_rec(slot);
|
||||
rec_set_n_owned(rec, page_rec_is_comp(rec), n);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
|
@ -540,26 +552,25 @@ page_rec_get_next(
|
|||
|
||||
ut_ad(page_rec_check(rec));
|
||||
|
||||
page = buf_frame_align(rec);
|
||||
page = ut_align_down(rec, UNIV_PAGE_SIZE);
|
||||
|
||||
offs = rec_get_next_offs(rec, page_is_comp(page));
|
||||
|
||||
if (offs >= UNIV_PAGE_SIZE) {
|
||||
if (UNIV_UNLIKELY(offs >= UNIV_PAGE_SIZE)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Next record offset is nonsensical %lu in record at offset %lu\n",
|
||||
(ulong)offs, (ulong)(rec - page));
|
||||
fprintf(stderr,
|
||||
"\nInnoDB: rec address %p, first buffer frame %p\n"
|
||||
"InnoDB: Next record offset is nonsensical %lu in record at offset %lu\n"
|
||||
"InnoDB: rec address %p, first buffer frame %p\n"
|
||||
"InnoDB: buffer pool high end %p, buf fix count %lu\n",
|
||||
(ulong)offs, (ulong)(rec - page),
|
||||
rec, buf_pool->frame_zero,
|
||||
buf_pool->high_end,
|
||||
(ulong)buf_block_align(rec)->buf_fix_count);
|
||||
buf_page_print(page);
|
||||
|
||||
ut_a(0);
|
||||
ut_error;
|
||||
}
|
||||
|
||||
if (offs == 0) {
|
||||
if (UNIV_UNLIKELY(offs == 0)) {
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
@ -581,15 +592,12 @@ page_rec_set_next(
|
|||
ulint offs;
|
||||
|
||||
ut_ad(page_rec_check(rec));
|
||||
ut_a((next == NULL)
|
||||
|| (buf_frame_align(rec) == buf_frame_align(next)));
|
||||
|
||||
page = buf_frame_align(rec);
|
||||
|
||||
ut_ad(rec != page_get_supremum_rec(page));
|
||||
ut_ad(next != page_get_infimum_rec(page));
|
||||
ut_ad(!page_rec_is_supremum(rec));
|
||||
page = ut_align_down(rec, UNIV_PAGE_SIZE);
|
||||
|
||||
if (next) {
|
||||
ut_ad(!page_rec_is_infimum(next));
|
||||
ut_ad(page == ut_align_down(next, UNIV_PAGE_SIZE));
|
||||
offs = (ulint) (next - page);
|
||||
} else {
|
||||
offs = 0;
|
||||
|
@ -613,13 +621,12 @@ page_rec_get_prev(
|
|||
rec_t* rec2;
|
||||
rec_t* prev_rec = NULL;
|
||||
page_t* page;
|
||||
ibool comp;
|
||||
|
||||
ut_ad(page_rec_check(rec));
|
||||
|
||||
page = buf_frame_align(rec);
|
||||
page = ut_align_down(rec, UNIV_PAGE_SIZE);
|
||||
|
||||
ut_ad(rec != page_get_infimum_rec(page));
|
||||
ut_ad(!page_rec_is_infimum(rec));
|
||||
|
||||
slot_no = page_dir_find_owner_slot(rec);
|
||||
|
||||
|
@ -628,7 +635,6 @@ page_rec_get_prev(
|
|||
slot = page_dir_get_nth_slot(page, slot_no - 1);
|
||||
|
||||
rec2 = page_dir_slot_get_rec(slot);
|
||||
comp = page_is_comp(page);
|
||||
|
||||
while (rec != rec2) {
|
||||
prev_rec = rec2;
|
||||
|
@ -649,13 +655,16 @@ page_rec_find_owner_rec(
|
|||
/* out: the owner record */
|
||||
rec_t* rec) /* in: the physical record */
|
||||
{
|
||||
ibool comp;
|
||||
|
||||
ut_ad(page_rec_check(rec));
|
||||
comp = page_is_comp(buf_frame_align(rec));
|
||||
|
||||
while (rec_get_n_owned(rec, comp) == 0) {
|
||||
rec = page_rec_get_next(rec);
|
||||
if (page_rec_is_comp(rec)) {
|
||||
while (rec_get_n_owned(rec, TRUE) == 0) {
|
||||
rec = page_rec_get_next(rec);
|
||||
}
|
||||
} else {
|
||||
while (rec_get_n_owned(rec, FALSE) == 0) {
|
||||
rec = page_rec_get_next(rec);
|
||||
}
|
||||
}
|
||||
|
||||
return(rec);
|
||||
|
@ -691,10 +700,17 @@ ulint
|
|||
page_get_free_space_of_empty(
|
||||
/*=========================*/
|
||||
/* out: free space */
|
||||
ibool comp) /* in: TRUE=compact page layout */
|
||||
ulint comp) /* in: nonzero=compact page layout */
|
||||
{
|
||||
if (UNIV_LIKELY(comp)) {
|
||||
return((ulint)(UNIV_PAGE_SIZE
|
||||
- PAGE_NEW_SUPREMUM_END
|
||||
- PAGE_DIR
|
||||
- 2 * PAGE_DIR_SLOT_SIZE));
|
||||
}
|
||||
|
||||
return((ulint)(UNIV_PAGE_SIZE
|
||||
- (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END)
|
||||
- PAGE_OLD_SUPREMUM_END
|
||||
- PAGE_DIR
|
||||
- 2 * PAGE_DIR_SLOT_SIZE));
|
||||
}
|
||||
|
@ -716,17 +732,21 @@ page_get_max_insert_size(
|
|||
{
|
||||
ulint occupied;
|
||||
ulint free_space;
|
||||
ibool comp;
|
||||
|
||||
comp = page_is_comp(page);
|
||||
|
||||
occupied = page_header_get_field(page, PAGE_HEAP_TOP)
|
||||
- (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END)
|
||||
+ page_dir_calc_reserved_space(
|
||||
if (page_is_comp(page)) {
|
||||
occupied = page_header_get_field(page, PAGE_HEAP_TOP)
|
||||
- PAGE_NEW_SUPREMUM_END + page_dir_calc_reserved_space(
|
||||
n_recs + page_dir_get_n_heap(page) - 2);
|
||||
|
||||
free_space = page_get_free_space_of_empty(comp);
|
||||
|
||||
free_space = page_get_free_space_of_empty(TRUE);
|
||||
} else {
|
||||
occupied = page_header_get_field(page, PAGE_HEAP_TOP)
|
||||
- PAGE_OLD_SUPREMUM_END + page_dir_calc_reserved_space(
|
||||
n_recs + page_dir_get_n_heap(page) - 2);
|
||||
|
||||
free_space = page_get_free_space_of_empty(FALSE);
|
||||
}
|
||||
|
||||
/* Above the 'n_recs +' part reserves directory space for the new
|
||||
inserted records; the '- 2' excludes page infimum and supremum
|
||||
records */
|
||||
|
@ -752,14 +772,11 @@ page_get_max_insert_size_after_reorganize(
|
|||
{
|
||||
ulint occupied;
|
||||
ulint free_space;
|
||||
ibool comp;
|
||||
|
||||
comp = page_is_comp(page);
|
||||
|
||||
occupied = page_get_data_size(page)
|
||||
+ page_dir_calc_reserved_space(n_recs + page_get_n_recs(page));
|
||||
|
||||
free_space = page_get_free_space_of_empty(comp);
|
||||
free_space = page_get_free_space_of_empty(page_is_comp(page));
|
||||
|
||||
if (occupied > free_space) {
|
||||
|
||||
|
@ -783,6 +800,7 @@ page_mem_free(
|
|||
ulint garbage;
|
||||
|
||||
ut_ad(rec_offs_validate(rec, NULL, offsets));
|
||||
ut_ad(!rec_offs_comp(offsets) == !page_rec_is_comp(rec));
|
||||
free = page_header_get_ptr(page, PAGE_FREE);
|
||||
|
||||
page_rec_set_next(rec, free);
|
||||
|
|
|
@ -71,13 +71,8 @@ read_view_sees_trx_id(
|
|||
|
||||
cmp = ut_dulint_cmp(trx_id,
|
||||
read_view_get_nth_trx_id(view, n_ids - i - 1));
|
||||
if (0 == cmp) {
|
||||
|
||||
return(FALSE);
|
||||
|
||||
} else if (cmp < 0) {
|
||||
|
||||
return(TRUE);
|
||||
if (cmp <= 0) {
|
||||
return(cmp < 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ rec_get_next_offs(
|
|||
/* out: the page offset of the next
|
||||
chained record */
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp); /* in: TRUE=compact page format */
|
||||
ulint comp); /* in: nonzero=compact page format */
|
||||
/**********************************************************
|
||||
The following function is used to set the next record offset field
|
||||
of the record. */
|
||||
|
@ -60,7 +60,7 @@ void
|
|||
rec_set_next_offs(
|
||||
/*==============*/
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp, /* in: TRUE=compact page format */
|
||||
ulint comp, /* in: nonzero=compact page format */
|
||||
ulint next); /* in: offset of the next record */
|
||||
/**********************************************************
|
||||
The following function is used to get the number of fields
|
||||
|
@ -90,7 +90,7 @@ rec_get_n_owned(
|
|||
/*============*/
|
||||
/* out: number of owned records */
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp); /* in: TRUE=compact page format */
|
||||
ulint comp); /* in: nonzero=compact page format */
|
||||
/**********************************************************
|
||||
The following function is used to set the number of owned
|
||||
records. */
|
||||
|
@ -99,7 +99,7 @@ void
|
|||
rec_set_n_owned(
|
||||
/*============*/
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp, /* in: TRUE=compact page format */
|
||||
ulint comp, /* in: nonzero=compact page format */
|
||||
ulint n_owned); /* in: the number of owned */
|
||||
/**********************************************************
|
||||
The following function is used to retrieve the info bits of
|
||||
|
@ -110,7 +110,7 @@ rec_get_info_bits(
|
|||
/*==============*/
|
||||
/* out: info bits */
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp); /* in: TRUE=compact page format */
|
||||
ulint comp); /* in: nonzero=compact page format */
|
||||
/**********************************************************
|
||||
The following function is used to set the info bits of a record. */
|
||||
UNIV_INLINE
|
||||
|
@ -118,7 +118,7 @@ void
|
|||
rec_set_info_bits(
|
||||
/*==============*/
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp, /* in: TRUE=compact page format */
|
||||
ulint comp, /* in: nonzero=compact page format */
|
||||
ulint bits); /* in: info bits */
|
||||
/**********************************************************
|
||||
The following function retrieves the status bits of a new-style record. */
|
||||
|
@ -147,7 +147,7 @@ rec_get_info_and_status_bits(
|
|||
/*=========================*/
|
||||
/* out: info bits */
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp); /* in: TRUE=compact page format */
|
||||
ulint comp); /* in: nonzero=compact page format */
|
||||
/**********************************************************
|
||||
The following function is used to set the info and status
|
||||
bits of a record. (Only compact records have status bits.) */
|
||||
|
@ -156,18 +156,18 @@ void
|
|||
rec_set_info_and_status_bits(
|
||||
/*=========================*/
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp, /* in: TRUE=compact page format */
|
||||
ulint comp, /* in: nonzero=compact page format */
|
||||
ulint bits); /* in: info bits */
|
||||
|
||||
/**********************************************************
|
||||
The following function tells if record is delete marked. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ulint
|
||||
rec_get_deleted_flag(
|
||||
/*=================*/
|
||||
/* out: TRUE if delete marked */
|
||||
/* out: nonzero if delete marked */
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp); /* in: TRUE=compact page format */
|
||||
ulint comp); /* in: nonzero=compact page format */
|
||||
/**********************************************************
|
||||
The following function is used to set the deleted bit. */
|
||||
UNIV_INLINE
|
||||
|
@ -175,8 +175,8 @@ void
|
|||
rec_set_deleted_flag(
|
||||
/*=================*/
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp, /* in: TRUE=compact page format */
|
||||
ibool flag); /* in: TRUE if delete marked */
|
||||
ulint comp, /* in: nonzero=compact page format */
|
||||
ulint flag); /* in: nonzero if delete marked */
|
||||
/**********************************************************
|
||||
The following function tells if a new-style record is a node pointer. */
|
||||
UNIV_INLINE
|
||||
|
@ -186,14 +186,6 @@ rec_get_node_ptr_flag(
|
|||
/* out: TRUE if node pointer */
|
||||
rec_t* rec); /* in: physical record */
|
||||
/**********************************************************
|
||||
The following function is used to flag a record as a node pointer. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
rec_set_node_ptr_flag(
|
||||
/*=================*/
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool flag); /* in: TRUE if the record is a node pointer */
|
||||
/**********************************************************
|
||||
The following function is used to get the order number
|
||||
of the record in the heap of the index page. */
|
||||
UNIV_INLINE
|
||||
|
@ -202,7 +194,7 @@ rec_get_heap_no(
|
|||
/*=============*/
|
||||
/* out: heap order number */
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp); /* in: TRUE=compact page format */
|
||||
ulint comp); /* in: nonzero=compact page format */
|
||||
/**********************************************************
|
||||
The following function is used to set the heap number
|
||||
field in the record. */
|
||||
|
@ -211,7 +203,7 @@ void
|
|||
rec_set_heap_no(
|
||||
/*=============*/
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp, /* in: TRUE=compact page format */
|
||||
ulint comp, /* in: nonzero=compact page format */
|
||||
ulint heap_no);/* in: the heap number */
|
||||
/**********************************************************
|
||||
The following function is used to test whether the data offsets
|
||||
|
@ -305,27 +297,18 @@ rec_get_nth_field(
|
|||
Determine if the offsets are for a record in the new
|
||||
compact format. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ulint
|
||||
rec_offs_comp(
|
||||
/*==========*/
|
||||
/* out: TRUE if compact format */
|
||||
/* out: nonzero if compact format */
|
||||
const ulint* offsets);/* in: array returned by rec_get_offsets() */
|
||||
/**********************************************************
|
||||
Returns TRUE if the nth field of rec is SQL NULL. */
|
||||
Returns nonzero if the extern bit is set in nth field of rec. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
rec_offs_nth_null(
|
||||
/*==============*/
|
||||
/* out: TRUE if SQL NULL */
|
||||
const ulint* offsets,/* in: array returned by rec_get_offsets() */
|
||||
ulint n); /* in: nth field */
|
||||
/**********************************************************
|
||||
Returns TRUE if the extern bit is set in nth field of rec. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ulint
|
||||
rec_offs_nth_extern(
|
||||
/*================*/
|
||||
/* out: TRUE if externally stored */
|
||||
/* out: nonzero if externally stored */
|
||||
const ulint* offsets,/* in: array returned by rec_get_offsets() */
|
||||
ulint n); /* in: nth field */
|
||||
/**********************************************************
|
||||
|
|
|
@ -265,7 +265,7 @@ rec_get_next_offs(
|
|||
/* out: the page offset of the next chained record, or
|
||||
0 if none */
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp) /* in: TRUE=compact page format */
|
||||
ulint comp) /* in: nonzero=compact page format */
|
||||
{
|
||||
ulint field_value;
|
||||
|
||||
|
@ -312,7 +312,7 @@ void
|
|||
rec_set_next_offs(
|
||||
/*==============*/
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp, /* in: TRUE=compact page format */
|
||||
ulint comp, /* in: nonzero=compact page format */
|
||||
ulint next) /* in: offset of the next record, or 0 if none */
|
||||
{
|
||||
ut_ad(rec);
|
||||
|
@ -414,7 +414,7 @@ rec_get_n_fields(
|
|||
{
|
||||
ut_ad(rec);
|
||||
ut_ad(index);
|
||||
if (!index->table->comp) {
|
||||
if (UNIV_UNLIKELY(!index->table->comp)) {
|
||||
return(rec_get_n_fields_old(rec));
|
||||
}
|
||||
switch (rec_get_status(rec)) {
|
||||
|
@ -440,7 +440,7 @@ rec_get_n_owned(
|
|||
/*============*/
|
||||
/* out: number of owned records */
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp) /* in: TRUE=compact page format */
|
||||
ulint comp) /* in: nonzero=compact page format */
|
||||
{
|
||||
ulint ret;
|
||||
|
||||
|
@ -461,7 +461,7 @@ void
|
|||
rec_set_n_owned(
|
||||
/*============*/
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp, /* in: TRUE=compact page format */
|
||||
ulint comp, /* in: nonzero=compact page format */
|
||||
ulint n_owned) /* in: the number of owned */
|
||||
{
|
||||
ut_ad(rec);
|
||||
|
@ -480,7 +480,7 @@ rec_get_info_bits(
|
|||
/*==============*/
|
||||
/* out: info bits */
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp) /* in: TRUE=compact page format */
|
||||
ulint comp) /* in: nonzero=compact page format */
|
||||
{
|
||||
ulint ret;
|
||||
|
||||
|
@ -501,7 +501,7 @@ void
|
|||
rec_set_info_bits(
|
||||
/*==============*/
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp, /* in: TRUE=compact page format */
|
||||
ulint comp, /* in: nonzero=compact page format */
|
||||
ulint bits) /* in: info bits */
|
||||
{
|
||||
ut_ad(rec);
|
||||
|
@ -537,14 +537,14 @@ rec_get_info_and_status_bits(
|
|||
/*=========================*/
|
||||
/* out: info bits */
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp) /* in: TRUE=compact page format */
|
||||
ulint comp) /* in: nonzero=compact page format */
|
||||
{
|
||||
ulint bits;
|
||||
#if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \
|
||||
& (REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT)
|
||||
# error "REC_NEW_STATUS_MASK and REC_INFO_BITS_MASK overlap"
|
||||
#endif
|
||||
if (comp) {
|
||||
if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) {
|
||||
bits = rec_get_info_bits(rec, TRUE) | rec_get_status(rec);
|
||||
} else {
|
||||
bits = rec_get_info_bits(rec, FALSE);
|
||||
|
@ -560,7 +560,7 @@ void
|
|||
rec_set_info_and_status_bits(
|
||||
/*=========================*/
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp, /* in: TRUE=compact page format */
|
||||
ulint comp, /* in: nonzero=compact page format */
|
||||
ulint bits) /* in: info bits */
|
||||
{
|
||||
#if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \
|
||||
|
@ -578,19 +578,22 @@ rec_set_info_and_status_bits(
|
|||
/**********************************************************
|
||||
The following function tells if record is delete marked. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ulint
|
||||
rec_get_deleted_flag(
|
||||
/*=================*/
|
||||
/* out: TRUE if delete marked */
|
||||
/* out: nonzero if delete marked */
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp) /* in: TRUE=compact page format */
|
||||
ulint comp) /* in: nonzero=compact page format */
|
||||
{
|
||||
if (REC_INFO_DELETED_FLAG & rec_get_info_bits(rec, comp)) {
|
||||
|
||||
return(TRUE);
|
||||
if (UNIV_EXPECT(comp, REC_OFFS_COMPACT)) {
|
||||
return(UNIV_UNLIKELY(rec_get_bit_field_1(rec,
|
||||
REC_NEW_INFO_BITS, REC_INFO_DELETED_FLAG,
|
||||
REC_INFO_BITS_SHIFT)));
|
||||
} else {
|
||||
return(UNIV_UNLIKELY(rec_get_bit_field_1(rec,
|
||||
REC_OLD_INFO_BITS, REC_INFO_DELETED_FLAG,
|
||||
REC_INFO_BITS_SHIFT)));
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
|
@ -600,24 +603,20 @@ void
|
|||
rec_set_deleted_flag(
|
||||
/*=================*/
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp, /* in: TRUE=compact page format */
|
||||
ibool flag) /* in: TRUE if delete marked */
|
||||
ulint comp, /* in: nonzero=compact page format */
|
||||
ulint flag) /* in: nonzero if delete marked */
|
||||
{
|
||||
ulint old_val;
|
||||
ulint new_val;
|
||||
ulint val;
|
||||
|
||||
ut_ad(TRUE == 1);
|
||||
ut_ad(flag <= TRUE);
|
||||
|
||||
old_val = rec_get_info_bits(rec, comp);
|
||||
val = rec_get_info_bits(rec, comp);
|
||||
|
||||
if (flag) {
|
||||
new_val = REC_INFO_DELETED_FLAG | old_val;
|
||||
val |= REC_INFO_DELETED_FLAG;
|
||||
} else {
|
||||
new_val = ~REC_INFO_DELETED_FLAG & old_val;
|
||||
val &= ~REC_INFO_DELETED_FLAG;
|
||||
}
|
||||
|
||||
rec_set_info_bits(rec, comp, new_val);
|
||||
rec_set_info_bits(rec, comp, val);
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
|
@ -632,26 +631,6 @@ rec_get_node_ptr_flag(
|
|||
return(REC_STATUS_NODE_PTR == rec_get_status(rec));
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
The following function is used to flag a record as a node pointer. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
rec_set_node_ptr_flag(
|
||||
/*=================*/
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool flag) /* in: TRUE if the record is a node pointer */
|
||||
{
|
||||
ulint status;
|
||||
ut_ad(flag <= TRUE);
|
||||
ut_ad(REC_STATUS_NODE_PTR >= rec_get_status(rec));
|
||||
if (flag) {
|
||||
status = REC_STATUS_NODE_PTR;
|
||||
} else {
|
||||
status = REC_STATUS_ORDINARY;
|
||||
}
|
||||
rec_set_status(rec, status);
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
The following function is used to get the order number of the record in the
|
||||
heap of the index page. */
|
||||
|
@ -661,7 +640,7 @@ rec_get_heap_no(
|
|||
/*=============*/
|
||||
/* out: heap order number */
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp) /* in: TRUE=compact page format */
|
||||
ulint comp) /* in: nonzero=compact page format */
|
||||
{
|
||||
ulint ret;
|
||||
|
||||
|
@ -682,7 +661,7 @@ void
|
|||
rec_set_heap_no(
|
||||
/*=============*/
|
||||
rec_t* rec, /* in: physical record */
|
||||
ibool comp, /* in: TRUE=compact page format */
|
||||
ulint comp, /* in: nonzero=compact page format */
|
||||
ulint heap_no)/* in: the heap number */
|
||||
{
|
||||
ut_ad(heap_no <= REC_MAX_HEAP_NO);
|
||||
|
@ -843,7 +822,7 @@ rec_offs_validate(
|
|||
{
|
||||
ulint i = rec_offs_n_fields(offsets);
|
||||
ulint last = ULINT_MAX;
|
||||
ibool comp = (*rec_offs_base(offsets) & REC_OFFS_COMPACT) != 0;
|
||||
ulint comp = *rec_offs_base(offsets) & REC_OFFS_COMPACT;
|
||||
|
||||
if (rec) {
|
||||
ut_ad((ulint) rec == offsets[2]);
|
||||
|
@ -926,7 +905,7 @@ rec_get_nth_field(
|
|||
ut_ad(n < rec_offs_n_fields(offsets));
|
||||
ut_ad(len);
|
||||
|
||||
if (n == 0) {
|
||||
if (UNIV_UNLIKELY(n == 0)) {
|
||||
field = rec;
|
||||
} else {
|
||||
field = rec + (rec_offs_base(offsets)[n] & REC_OFFS_MASK);
|
||||
|
@ -949,43 +928,30 @@ rec_get_nth_field(
|
|||
Determine if the offsets are for a record in the new
|
||||
compact format. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ulint
|
||||
rec_offs_comp(
|
||||
/*==========*/
|
||||
/* out: TRUE if compact format */
|
||||
/* out: nonzero if compact format */
|
||||
const ulint* offsets)/* in: array returned by rec_get_offsets() */
|
||||
{
|
||||
ut_ad(rec_offs_validate(NULL, NULL, offsets));
|
||||
return((*rec_offs_base(offsets) & REC_OFFS_COMPACT) != 0);
|
||||
return(*rec_offs_base(offsets) & REC_OFFS_COMPACT);
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
Returns TRUE if the nth field of rec is SQL NULL. */
|
||||
Returns nonzero if the extern bit is set in nth field of rec. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
rec_offs_nth_null(
|
||||
/*==============*/
|
||||
/* out: TRUE if SQL NULL */
|
||||
const ulint* offsets,/* in: array returned by rec_get_offsets() */
|
||||
ulint n) /* in: nth field */
|
||||
{
|
||||
ut_ad(rec_offs_validate(NULL, NULL, offsets));
|
||||
ut_ad(n < rec_offs_n_fields(offsets));
|
||||
return((rec_offs_base(offsets)[1 + n] & REC_OFFS_SQL_NULL) != 0);
|
||||
}
|
||||
/**********************************************************
|
||||
Returns TRUE if the extern bit is set in nth field of rec. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
ulint
|
||||
rec_offs_nth_extern(
|
||||
/*================*/
|
||||
/* out: TRUE if externally stored */
|
||||
/* out: nonzero if externally stored */
|
||||
const ulint* offsets,/* in: array returned by rec_get_offsets() */
|
||||
ulint n) /* in: nth field */
|
||||
{
|
||||
ut_ad(rec_offs_validate(NULL, NULL, offsets));
|
||||
ut_ad(n < rec_offs_n_fields(offsets));
|
||||
return((rec_offs_base(offsets)[1 + n] & REC_OFFS_EXTERNAL) != 0);
|
||||
return(UNIV_UNLIKELY(rec_offs_base(offsets)[1 + n]
|
||||
& REC_OFFS_EXTERNAL));
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
|
@ -1037,7 +1003,7 @@ rec_set_nth_field_extern_bit(
|
|||
where rec is, or NULL; in the NULL case
|
||||
we do not write to log about the change */
|
||||
{
|
||||
if (index->table->comp) {
|
||||
if (UNIV_LIKELY(index->table->comp)) {
|
||||
rec_set_nth_field_extern_bit_new(rec, index, i, val, mtr);
|
||||
} else {
|
||||
rec_set_nth_field_extern_bit_old(rec, i, val, mtr);
|
||||
|
@ -1048,7 +1014,7 @@ rec_set_nth_field_extern_bit(
|
|||
Returns the offset of n - 1th field end if the record is stored in the 1-byte
|
||||
offsets form. If the field is SQL null, the flag is ORed in the returned
|
||||
value. This function and the 2-byte counterpart are defined here because the
|
||||
C-compilerwas not able to sum negative and positive constant offsets, and
|
||||
C-compiler was not able to sum negative and positive constant offsets, and
|
||||
warned of constant arithmetic overflow within the compiler. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
|
@ -1452,7 +1418,7 @@ rec_get_converted_size(
|
|||
? dict_index_get_n_unique_in_tree(index) + 1
|
||||
: dict_index_get_n_fields(index)));
|
||||
|
||||
if (index->table->comp) {
|
||||
if (UNIV_LIKELY(index->table->comp)) {
|
||||
return(rec_get_converted_size_new(index, dtuple));
|
||||
}
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ row_mysql_store_col_in_innobase_format(
|
|||
necessarily the length of the actual
|
||||
payload data; if the column is a true
|
||||
VARCHAR then this is irrelevant */
|
||||
ibool comp); /* in: TRUE = compact format */
|
||||
ulint comp); /* in: nonzero=compact format */
|
||||
/********************************************************************
|
||||
Handles user errors and lock waits detected by the database engine. */
|
||||
|
||||
|
@ -172,14 +172,6 @@ row_lock_table_autoinc_for_mysql(
|
|||
row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL
|
||||
table handle */
|
||||
/*************************************************************************
|
||||
Unlocks all table locks explicitly requested by trx (with LOCK TABLES,
|
||||
lock type LOCK_TABLE_EXP). */
|
||||
|
||||
void
|
||||
row_unlock_tables_for_mysql(
|
||||
/*========================*/
|
||||
trx_t* trx); /* in: transaction */
|
||||
/*************************************************************************
|
||||
Sets a table lock on the table mentioned in prebuilt. */
|
||||
|
||||
int
|
||||
|
@ -190,9 +182,10 @@ row_lock_table_for_mysql(
|
|||
table handle */
|
||||
dict_table_t* table, /* in: table to lock, or NULL
|
||||
if prebuilt->table should be
|
||||
locked as LOCK_TABLE_EXP |
|
||||
locked as
|
||||
prebuilt->select_lock_type */
|
||||
ulint mode); /* in: lock mode of table */
|
||||
ulint mode); /* in: lock mode of table
|
||||
(ignored if table==NULL) */
|
||||
|
||||
/*************************************************************************
|
||||
Does an insert for MySQL. */
|
||||
|
@ -599,6 +592,8 @@ struct row_prebuilt_struct {
|
|||
that was decided in ha_innodb.cc,
|
||||
::store_lock(), ::external_lock(),
|
||||
etc. */
|
||||
ulint mysql_prefix_len;/* byte offset of the end of
|
||||
the last requested column */
|
||||
ulint mysql_row_len; /* length in bytes of a row in the
|
||||
MySQL format */
|
||||
ulint n_rows_fetched; /* number of rows fetched after
|
||||
|
|
|
@ -75,7 +75,7 @@ open_step(
|
|||
}
|
||||
}
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
if (UNIV_EXPECT(err, DB_SUCCESS) != DB_SUCCESS) {
|
||||
/* SQL error detected */
|
||||
fprintf(stderr, "SQL error %lu\n", (ulong) err);
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ upd_field_set_field_no(
|
|||
{
|
||||
upd_field->field_no = field_no;
|
||||
|
||||
if (field_no >= dict_index_get_n_fields(index)) {
|
||||
if (UNIV_UNLIKELY(field_no >= dict_index_get_n_fields(index))) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to access field %lu in ",
|
||||
(ulong) field_no);
|
||||
|
|
|
@ -138,7 +138,7 @@ rw_lock_s_lock_low(
|
|||
#endif /* UNIV_SYNC_DEBUG */
|
||||
/* Check if the writer field is free */
|
||||
|
||||
if (lock->writer == RW_LOCK_NOT_LOCKED) {
|
||||
if (UNIV_LIKELY(lock->writer == RW_LOCK_NOT_LOCKED)) {
|
||||
/* Set the shared lock by incrementing the reader count */
|
||||
lock->reader_count++;
|
||||
|
||||
|
@ -243,7 +243,7 @@ rw_lock_s_lock_func(
|
|||
|
||||
mutex_enter(rw_lock_get_mutex(lock));
|
||||
|
||||
if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
|
||||
if (UNIV_LIKELY(rw_lock_s_lock_low(lock, pass, file_name, line))) {
|
||||
mutex_exit(rw_lock_get_mutex(lock));
|
||||
|
||||
return; /* Success */
|
||||
|
@ -307,21 +307,18 @@ rw_lock_x_lock_func_nowait(
|
|||
const char* file_name,/* in: file name where lock requested */
|
||||
ulint line) /* in: line where requested */
|
||||
{
|
||||
ibool success = FALSE;
|
||||
|
||||
ibool success = FALSE;
|
||||
os_thread_id_t curr_thread = os_thread_get_curr_id();
|
||||
mutex_enter(rw_lock_get_mutex(lock));
|
||||
|
||||
if ((rw_lock_get_reader_count(lock) == 0)
|
||||
&& ((rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)
|
||||
|| ((rw_lock_get_writer(lock) == RW_LOCK_EX)
|
||||
&& (lock->pass == 0)
|
||||
&& os_thread_eq(lock->writer_thread,
|
||||
os_thread_get_curr_id())))) {
|
||||
|
||||
if (UNIV_UNLIKELY(rw_lock_get_reader_count(lock) != 0)) {
|
||||
} else if (UNIV_LIKELY(rw_lock_get_writer(lock)
|
||||
== RW_LOCK_NOT_LOCKED)) {
|
||||
rw_lock_set_writer(lock, RW_LOCK_EX);
|
||||
lock->writer_thread = os_thread_get_curr_id();
|
||||
lock->writer_count++;
|
||||
lock->writer_thread = curr_thread;
|
||||
lock->pass = 0;
|
||||
relock:
|
||||
lock->writer_count++;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
|
||||
|
@ -331,6 +328,10 @@ rw_lock_x_lock_func_nowait(
|
|||
lock->last_x_line = line;
|
||||
|
||||
success = TRUE;
|
||||
} else if (rw_lock_get_writer(lock) == RW_LOCK_EX
|
||||
&& lock->pass == 0
|
||||
&& os_thread_eq(lock->writer_thread, curr_thread)) {
|
||||
goto relock;
|
||||
}
|
||||
|
||||
mutex_exit(rw_lock_get_mutex(lock));
|
||||
|
@ -361,7 +362,7 @@ rw_lock_s_unlock_func(
|
|||
|
||||
/* Reset the shared lock by decrementing the reader count */
|
||||
|
||||
ut_a(lock->reader_count > 0);
|
||||
ut_ad(lock->reader_count > 0);
|
||||
lock->reader_count--;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
|
@ -371,7 +372,8 @@ rw_lock_s_unlock_func(
|
|||
/* If there may be waiters and this was the last s-lock,
|
||||
signal the object */
|
||||
|
||||
if (lock->waiters && (lock->reader_count == 0)) {
|
||||
if (UNIV_UNLIKELY(lock->waiters)
|
||||
&& lock->reader_count == 0) {
|
||||
sg = TRUE;
|
||||
|
||||
rw_lock_set_waiters(lock, 0);
|
||||
|
@ -379,7 +381,7 @@ rw_lock_s_unlock_func(
|
|||
|
||||
mutex_exit(mutex);
|
||||
|
||||
if (sg == TRUE) {
|
||||
if (UNIV_UNLIKELY(sg)) {
|
||||
sync_array_signal_object(sync_primary_wait_array, lock);
|
||||
}
|
||||
|
||||
|
@ -450,7 +452,8 @@ rw_lock_x_unlock_func(
|
|||
#endif
|
||||
|
||||
/* If there may be waiters, signal the lock */
|
||||
if (lock->waiters && (lock->writer_count == 0)) {
|
||||
if (UNIV_UNLIKELY(lock->waiters)
|
||||
&& lock->writer_count == 0) {
|
||||
|
||||
sg = TRUE;
|
||||
rw_lock_set_waiters(lock, 0);
|
||||
|
@ -458,7 +461,7 @@ rw_lock_x_unlock_func(
|
|||
|
||||
mutex_exit(&(lock->mutex));
|
||||
|
||||
if (sg == TRUE) {
|
||||
if (UNIV_UNLIKELY(sg)) {
|
||||
sync_array_signal_object(sync_primary_wait_array, lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ trx_rsegf_get_nth_undo(
|
|||
ulint n, /* in: index of slot */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
if (n >= TRX_RSEG_N_SLOTS) {
|
||||
if (UNIV_UNLIKELY(n >= TRX_RSEG_N_SLOTS)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to get slot %lu of rseg\n", (unsigned long) n);
|
||||
ut_error;
|
||||
|
@ -86,7 +86,7 @@ trx_rsegf_set_nth_undo(
|
|||
ulint page_no,/* in: page number of the undo log segment */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
if (n >= TRX_RSEG_N_SLOTS) {
|
||||
if (UNIV_UNLIKELY(n >= TRX_RSEG_N_SLOTS)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to set slot %lu of rseg\n", (unsigned long) n);
|
||||
ut_error;
|
||||
|
|
|
@ -312,6 +312,19 @@ trx_print(
|
|||
FILE* f, /* in: output stream */
|
||||
trx_t* trx); /* in: transaction */
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/**************************************************************************
|
||||
Determines if the currently running transaction has been interrupted. */
|
||||
|
||||
ibool
|
||||
trx_is_interrupted(
|
||||
/*===============*/
|
||||
/* out: TRUE if interrupted */
|
||||
trx_t* trx); /* in: transaction */
|
||||
#else /* !UNIV_HOTBACKUP */
|
||||
#define trx_is_interrupted(trx) FALSE
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
|
||||
/* Signal to a transaction */
|
||||
struct trx_sig_struct{
|
||||
|
@ -484,13 +497,6 @@ struct trx_struct{
|
|||
in the lock list trx_locks */
|
||||
ibool trx_create_lock;/* this is TRUE if we have created a
|
||||
new lock for a record accessed */
|
||||
ulint n_lock_table_exp;/* number of explicit table locks
|
||||
(LOCK TABLES) reserved by the
|
||||
transaction, stored in trx_locks */
|
||||
ulint n_lock_table_transactional;
|
||||
/* number of transactional table locks
|
||||
(LOCK TABLES..WHERE ENGINE) reserved by
|
||||
the transaction, stored in trx_locks */
|
||||
UT_LIST_NODE_T(trx_t)
|
||||
trx_list; /* list of transactions */
|
||||
UT_LIST_NODE_T(trx_t)
|
||||
|
|
|
@ -181,7 +181,7 @@ management to ensure correct alignment for doubles etc. */
|
|||
/* Another basic type we use is unsigned long integer which should be equal to
|
||||
the word size of the machine, that is on a 32-bit platform 32 bits, and on a
|
||||
64-bit platform 64 bits. We also give the printf format for the type as a
|
||||
macro PRULINT. */
|
||||
macro ULINTPF. */
|
||||
|
||||
#ifdef _WIN64
|
||||
typedef unsigned __int64 ulint;
|
||||
|
@ -243,6 +243,30 @@ contains the sum of the following flag and the locally stored len. */
|
|||
|
||||
#define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE)
|
||||
|
||||
/* Some macros to improve branch prediction and reduce cache misses */
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2)
|
||||
/* Tell the compiler that 'expr' probably evaluates to 'constant'. */
|
||||
# define UNIV_EXPECT(expr,constant) __builtin_expect(expr, constant)
|
||||
/* Tell the compiler that a pointer is likely to be NULL */
|
||||
# define UNIV_LIKELY_NULL(ptr) __builtin_expect((ulint) ptr, 0)
|
||||
/* Minimize cache-miss latency by moving data at addr into a cache before
|
||||
it is read. */
|
||||
# define UNIV_PREFETCH_R(addr) __builtin_prefetch(addr, 0, 3)
|
||||
/* Minimize cache-miss latency by moving data at addr into a cache before
|
||||
it is read or written. */
|
||||
# define UNIV_PREFETCH_RW(addr) __builtin_prefetch(addr, 1, 3)
|
||||
#else
|
||||
/* Dummy versions of the macros */
|
||||
# define UNIV_EXPECT(expr,value) (expr)
|
||||
# define UNIV_LIKELY_NULL(expr) (expr)
|
||||
# define UNIV_PREFETCH_R(addr) ((void) 0)
|
||||
# define UNIV_PREFETCH_RW(addr) ((void) 0)
|
||||
#endif
|
||||
/* Tell the compiler that cond is likely to hold */
|
||||
#define UNIV_LIKELY(cond) UNIV_EXPECT(cond, TRUE)
|
||||
/* Tell the compiler that cond is unlikely to hold */
|
||||
#define UNIV_UNLIKELY(cond) UNIV_EXPECT(cond, FALSE)
|
||||
|
||||
#include <stdio.h>
|
||||
#include "ut0dbg.h"
|
||||
#include "ut0ut.h"
|
||||
|
|
|
@ -13,74 +13,75 @@ Created 1/30/1994 Heikki Tuuri
|
|||
#include <stdlib.h>
|
||||
#include "os0thread.h"
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2)
|
||||
# define UT_DBG_FAIL(EXPR) UNIV_UNLIKELY(!((ulint)(EXPR)))
|
||||
#else
|
||||
extern ulint ut_dbg_zero; /* This is used to eliminate
|
||||
compiler warnings */
|
||||
# define UT_DBG_FAIL(EXPR) !((ulint)(EXPR) + ut_dbg_zero)
|
||||
#endif
|
||||
|
||||
/*****************************************************************
|
||||
Report a failed assertion. */
|
||||
|
||||
void
|
||||
ut_dbg_assertion_failed(
|
||||
/*====================*/
|
||||
const char* expr, /* in: the failed assertion */
|
||||
const char* file, /* in: source file containing the assertion */
|
||||
ulint line); /* in: line number of the assertion */
|
||||
|
||||
#ifdef __NETWARE__
|
||||
/* Flag for ignoring further assertion failures.
|
||||
On NetWare, have a graceful exit rather than a segfault to avoid abends. */
|
||||
extern ibool panic_shutdown;
|
||||
/* Abort the execution. */
|
||||
void ut_dbg_panic(void);
|
||||
# define UT_DBG_PANIC ut_dbg_panic()
|
||||
/* Stop threads in ut_a(). */
|
||||
# define UT_DBG_STOP while (0) /* We do not do this on NetWare */
|
||||
#else /* __NETWARE__ */
|
||||
/* Flag for indicating that all threads should stop. This will be set
|
||||
by ut_dbg_assertion_failed(). */
|
||||
extern ibool ut_dbg_stop_threads;
|
||||
|
||||
/* A null pointer that will be dereferenced to trigger a memory trap */
|
||||
extern ulint* ut_dbg_null_ptr;
|
||||
|
||||
extern const char* ut_dbg_msg_assert_fail;
|
||||
extern const char* ut_dbg_msg_trap;
|
||||
extern const char* ut_dbg_msg_stop;
|
||||
/* Have a graceful exit on NetWare rather than a segfault to avoid abends */
|
||||
#ifdef __NETWARE__
|
||||
extern ibool panic_shutdown;
|
||||
#define ut_a(EXPR) do {\
|
||||
if (!((ulint)(EXPR) + ut_dbg_zero)) {\
|
||||
ut_print_timestamp(stderr);\
|
||||
fprintf(stderr, ut_dbg_msg_assert_fail,\
|
||||
os_thread_pf(os_thread_get_curr_id()), __FILE__,\
|
||||
(ulint)__LINE__);\
|
||||
fputs("InnoDB: Failing assertion: " #EXPR "\n", stderr);\
|
||||
fputs(ut_dbg_msg_trap, stderr);\
|
||||
ut_dbg_stop_threads = TRUE;\
|
||||
if (ut_dbg_stop_threads) {\
|
||||
fprintf(stderr, ut_dbg_msg_stop,\
|
||||
os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\
|
||||
}\
|
||||
if(!panic_shutdown){\
|
||||
panic_shutdown = TRUE;\
|
||||
innobase_shutdown_for_mysql();}\
|
||||
exit(1);\
|
||||
}\
|
||||
} while (0)
|
||||
#define ut_error do {\
|
||||
ut_print_timestamp(stderr);\
|
||||
fprintf(stderr, ut_dbg_msg_assert_fail,\
|
||||
os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\
|
||||
fprintf(stderr, ut_dbg_msg_trap);\
|
||||
ut_dbg_stop_threads = TRUE;\
|
||||
if(!panic_shutdown){panic_shutdown = TRUE;\
|
||||
innobase_shutdown_for_mysql();}\
|
||||
} while (0)
|
||||
#else
|
||||
#define ut_a(EXPR) do {\
|
||||
if (!((ulint)(EXPR) + ut_dbg_zero)) {\
|
||||
ut_print_timestamp(stderr);\
|
||||
fprintf(stderr, ut_dbg_msg_assert_fail,\
|
||||
os_thread_pf(os_thread_get_curr_id()), __FILE__,\
|
||||
(ulint)__LINE__);\
|
||||
fputs("InnoDB: Failing assertion: " #EXPR "\n", stderr);\
|
||||
fputs(ut_dbg_msg_trap, stderr);\
|
||||
ut_dbg_stop_threads = TRUE;\
|
||||
if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL;\
|
||||
}\
|
||||
if (ut_dbg_stop_threads) {\
|
||||
fprintf(stderr, ut_dbg_msg_stop,\
|
||||
os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\
|
||||
os_thread_sleep(1000000000);\
|
||||
}\
|
||||
/*****************************************************************
|
||||
Stop a thread after assertion failure. */
|
||||
|
||||
void
|
||||
ut_dbg_stop_thread(
|
||||
/*===============*/
|
||||
const char* file,
|
||||
ulint line);
|
||||
|
||||
/* Abort the execution. */
|
||||
# define UT_DBG_PANIC \
|
||||
if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL
|
||||
/* Stop threads in ut_a(). */
|
||||
# define UT_DBG_STOP do \
|
||||
if (UNIV_UNLIKELY(ut_dbg_stop_threads)) { \
|
||||
ut_dbg_stop_thread(__FILE__, (ulint) __LINE__); \
|
||||
} while (0)
|
||||
#endif /* __NETWARE__ */
|
||||
|
||||
/* Abort execution if EXPR does not evaluate to nonzero. */
|
||||
#define ut_a(EXPR) do { \
|
||||
if (UT_DBG_FAIL(EXPR)) { \
|
||||
ut_dbg_assertion_failed(#EXPR, \
|
||||
__FILE__, (ulint) __LINE__); \
|
||||
UT_DBG_PANIC; \
|
||||
} \
|
||||
UT_DBG_STOP; \
|
||||
} while (0)
|
||||
|
||||
#define ut_error do {\
|
||||
ut_print_timestamp(stderr);\
|
||||
fprintf(stderr, ut_dbg_msg_assert_fail,\
|
||||
os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\
|
||||
fprintf(stderr, ut_dbg_msg_trap);\
|
||||
ut_dbg_stop_threads = TRUE;\
|
||||
if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL;\
|
||||
/* Abort execution. */
|
||||
#define ut_error do { \
|
||||
ut_dbg_assertion_failed(0, __FILE__, (ulint) __LINE__); \
|
||||
UT_DBG_PANIC; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
#define ut_ad(EXPR) ut_a(EXPR)
|
||||
|
|
|
@ -207,12 +207,12 @@ ut_fold_binary(
|
|||
const byte* str, /* in: string of bytes */
|
||||
ulint len) /* in: length */
|
||||
{
|
||||
ulint i;
|
||||
ulint fold = 0;
|
||||
const byte* str_end = str + len;
|
||||
ulint fold = 0;
|
||||
|
||||
ut_ad(str);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
while (str < str_end) {
|
||||
fold = ut_fold_ulint_pair(fold, (ulint)(*str));
|
||||
|
||||
str++;
|
||||
|
|
|
@ -292,7 +292,25 @@ waiting, in its lock queue. Solution: We can copy the locks as gap type
|
|||
locks, so that also the waiting locks are transformed to granted gap type
|
||||
locks on the inserted record. */
|
||||
|
||||
/* LOCK COMPATIBILITY MATRIX
|
||||
* IS IX S X AI
|
||||
* IS + + + - +
|
||||
* IX + + - - +
|
||||
* S + - + - -
|
||||
* X - - - - -
|
||||
* AI + + - - -
|
||||
*
|
||||
* Note that for rows, InnoDB only acquires S or X locks.
|
||||
* For tables, InnoDB normally acquires IS or IX locks.
|
||||
* S or X table locks are only acquired for LOCK TABLES.
|
||||
* Auto-increment (AI) locks are needed because of
|
||||
* statement-level MySQL binlog.
|
||||
* See also lock_mode_compatible().
|
||||
*/
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
ibool lock_print_waits = FALSE;
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/* The lock system */
|
||||
lock_sys_t* lock_sys = NULL;
|
||||
|
@ -348,17 +366,26 @@ static
|
|||
ibool
|
||||
lock_deadlock_occurs(
|
||||
/*=================*/
|
||||
/* out: TRUE if a deadlock was detected */
|
||||
/* out: TRUE if a deadlock was detected and we
|
||||
chose trx as a victim; FALSE if no deadlock, or
|
||||
there was a deadlock, but we chose other
|
||||
transaction(s) as victim(s) */
|
||||
lock_t* lock, /* in: lock the transaction is requesting */
|
||||
trx_t* trx); /* in: transaction */
|
||||
/************************************************************************
|
||||
Looks recursively for a deadlock. */
|
||||
static
|
||||
ibool
|
||||
ulint
|
||||
lock_deadlock_recursive(
|
||||
/*====================*/
|
||||
/* out: TRUE if a deadlock was detected
|
||||
or the calculation took too long */
|
||||
/* out: 0 if no deadlock found,
|
||||
LOCK_VICTIM_IS_START if there was a deadlock
|
||||
and we chose 'start' as the victim,
|
||||
LOCK_VICTIM_IS_OTHER if a deadlock
|
||||
was found and we chose some other trx as a
|
||||
victim: we must do the search again in this
|
||||
last case because there may be another
|
||||
deadlock! */
|
||||
trx_t* start, /* in: recursion starting point */
|
||||
trx_t* trx, /* in: a transaction waiting for a lock */
|
||||
lock_t* wait_lock, /* in: the lock trx is waiting to be granted */
|
||||
|
@ -492,12 +519,7 @@ lock_clust_rec_cons_read_sees(
|
|||
|
||||
trx_id = row_get_rec_trx_id(rec, index, offsets);
|
||||
|
||||
if (read_view_sees_trx_id(view, trx_id)) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
return(read_view_sees_trx_id(view, trx_id));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -1261,7 +1283,6 @@ lock_rec_get_next(
|
|||
/*==============*/
|
||||
/* out: next lock, NULL if none exists */
|
||||
rec_t* rec, /* in: record on a page */
|
||||
ibool comp, /* in: TRUE=compact page format */
|
||||
lock_t* lock) /* in: lock */
|
||||
{
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
|
@ -1269,19 +1290,19 @@ lock_rec_get_next(
|
|||
#endif /* UNIV_SYNC_DEBUG */
|
||||
ut_ad(lock_get_type(lock) == LOCK_REC);
|
||||
|
||||
for (;;) {
|
||||
lock = lock_rec_get_next_on_page(lock);
|
||||
|
||||
if (lock == NULL) {
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec, comp))) {
|
||||
|
||||
return(lock);
|
||||
}
|
||||
if (page_rec_is_comp(rec)) {
|
||||
do {
|
||||
lock = lock_rec_get_next_on_page(lock);
|
||||
} while (lock && !lock_rec_get_nth_bit(lock,
|
||||
rec_get_heap_no(rec, TRUE)));
|
||||
} else {
|
||||
do {
|
||||
lock = lock_rec_get_next_on_page(lock);
|
||||
} while (lock && !lock_rec_get_nth_bit(lock,
|
||||
rec_get_heap_no(rec, FALSE)));
|
||||
}
|
||||
|
||||
return(lock);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -1294,22 +1315,18 @@ lock_rec_get_first(
|
|||
rec_t* rec) /* in: record on a page */
|
||||
{
|
||||
lock_t* lock;
|
||||
ibool comp;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
lock = lock_rec_get_first_on_page(rec);
|
||||
comp = page_is_comp(buf_frame_align(rec));
|
||||
if (UNIV_LIKELY_NULL(lock)) {
|
||||
ulint heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
|
||||
|
||||
while (lock) {
|
||||
if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec, comp))) {
|
||||
|
||||
break;
|
||||
while (lock && !lock_rec_get_nth_bit(lock, heap_no)) {
|
||||
lock = lock_rec_get_next_on_page(lock);
|
||||
}
|
||||
|
||||
lock = lock_rec_get_next_on_page(lock);
|
||||
}
|
||||
|
||||
return(lock);
|
||||
|
@ -1471,7 +1488,6 @@ lock_rec_has_expl(
|
|||
for a supremum record we regard this always a gap
|
||||
type request */
|
||||
rec_t* rec, /* in: record */
|
||||
ibool comp, /* in: TRUE=compact page format */
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
lock_t* lock;
|
||||
|
@ -1501,7 +1517,7 @@ lock_rec_has_expl(
|
|||
return(lock);
|
||||
}
|
||||
|
||||
lock = lock_rec_get_next(rec, comp, lock);
|
||||
lock = lock_rec_get_next(rec, lock);
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
|
@ -1520,7 +1536,6 @@ lock_rec_other_has_expl_req(
|
|||
ulint wait, /* in: LOCK_WAIT if also waiting locks are
|
||||
taken into account, or 0 if not */
|
||||
rec_t* rec, /* in: record to look at */
|
||||
ibool comp, /* in: TRUE=compact record format */
|
||||
trx_t* trx) /* in: transaction, or NULL if requests by all
|
||||
transactions are taken into account */
|
||||
{
|
||||
|
@ -1545,7 +1560,7 @@ lock_rec_other_has_expl_req(
|
|||
return(lock);
|
||||
}
|
||||
|
||||
lock = lock_rec_get_next(rec, comp, lock);
|
||||
lock = lock_rec_get_next(rec, lock);
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
|
@ -1566,13 +1581,11 @@ lock_rec_other_has_conflicting(
|
|||
trx_t* trx) /* in: our transaction */
|
||||
{
|
||||
lock_t* lock;
|
||||
ibool comp;
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
lock = lock_rec_get_first(rec);
|
||||
comp = page_is_comp(buf_frame_align(rec));
|
||||
|
||||
while (lock) {
|
||||
if (lock_rec_has_to_wait(trx, mode, lock,
|
||||
|
@ -1581,7 +1594,7 @@ lock_rec_other_has_conflicting(
|
|||
return(lock);
|
||||
}
|
||||
|
||||
lock = lock_rec_get_next(rec, comp, lock);
|
||||
lock = lock_rec_get_next(rec, lock);
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
|
@ -1607,7 +1620,7 @@ lock_rec_find_similar_on_page(
|
|||
ut_ad(mutex_own(&kernel_mutex));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
heap_no = rec_get_heap_no(rec, page_is_comp(buf_frame_align(rec)));
|
||||
heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
|
||||
lock = lock_rec_get_first_on_page(rec);
|
||||
|
||||
while (lock != NULL) {
|
||||
|
@ -1709,6 +1722,8 @@ lock_rec_create(
|
|||
page_no = buf_frame_get_page_no(page);
|
||||
heap_no = rec_get_heap_no(rec, page_is_comp(page));
|
||||
|
||||
ut_ad(!!page_is_comp(page) == index->table->comp);
|
||||
|
||||
/* If rec is the supremum record, then we reset the gap and
|
||||
LOCK_REC_NOT_GAP bits, as all locks on the supremum are
|
||||
automatically of the gap type */
|
||||
|
@ -1725,7 +1740,7 @@ lock_rec_create(
|
|||
|
||||
lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t) + n_bytes);
|
||||
|
||||
if (lock == NULL) {
|
||||
if (UNIV_UNLIKELY(lock == NULL)) {
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
@ -1826,7 +1841,7 @@ lock_rec_enqueue_waiting(
|
|||
|
||||
lock_reset_lock_and_trx_wait(lock);
|
||||
lock_rec_reset_nth_bit(lock, rec_get_heap_no(rec,
|
||||
page_is_comp(buf_frame_align(rec))));
|
||||
page_rec_is_comp(rec)));
|
||||
|
||||
return(DB_DEADLOCK);
|
||||
}
|
||||
|
@ -1845,11 +1860,13 @@ lock_rec_enqueue_waiting(
|
|||
|
||||
ut_a(que_thr_stop(thr));
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (lock_print_waits) {
|
||||
fprintf(stderr, "Lock wait for trx %lu in index ",
|
||||
(ulong) ut_dulint_get_low(trx->id));
|
||||
ut_print_name(stderr, trx, index->name);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
return(DB_LOCK_WAIT);
|
||||
}
|
||||
|
@ -1876,7 +1893,6 @@ lock_rec_add_to_queue(
|
|||
lock_t* lock;
|
||||
lock_t* similar_lock = NULL;
|
||||
ulint heap_no;
|
||||
page_t* page = buf_frame_align(rec);
|
||||
ibool somebody_waits = FALSE;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
|
@ -1885,11 +1901,11 @@ lock_rec_add_to_queue(
|
|||
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
|
||||
|| ((type_mode & LOCK_MODE_MASK) != LOCK_S)
|
||||
|| !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT,
|
||||
rec, page_is_comp(page), trx));
|
||||
rec, trx));
|
||||
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
|
||||
|| ((type_mode & LOCK_MODE_MASK) != LOCK_X)
|
||||
|| !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
|
||||
rec, page_is_comp(page), trx));
|
||||
rec, trx));
|
||||
|
||||
type_mode = type_mode | LOCK_REC;
|
||||
|
||||
|
@ -1898,7 +1914,7 @@ lock_rec_add_to_queue(
|
|||
try to avoid unnecessary memory consumption of a new record lock
|
||||
struct for a gap type lock */
|
||||
|
||||
if (rec == page_get_supremum_rec(page)) {
|
||||
if (page_rec_is_supremum(rec)) {
|
||||
ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
|
||||
|
||||
/* There should never be LOCK_REC_NOT_GAP on a supremum
|
||||
|
@ -1909,7 +1925,7 @@ lock_rec_add_to_queue(
|
|||
|
||||
/* Look for a waiting lock request on the same record or on a gap */
|
||||
|
||||
heap_no = rec_get_heap_no(rec, page_is_comp(page));
|
||||
heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
|
||||
lock = lock_rec_get_first_on_page(rec);
|
||||
|
||||
while (lock != NULL) {
|
||||
|
@ -1984,7 +2000,7 @@ lock_rec_lock_fast(
|
|||
|| mode - (LOCK_MODE_MASK & mode) == 0
|
||||
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
|
||||
|
||||
heap_no = rec_get_heap_no(rec, page_is_comp(buf_frame_align(rec)));
|
||||
heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
|
||||
|
||||
lock = lock_rec_get_first_on_page(rec);
|
||||
|
||||
|
@ -2065,8 +2081,7 @@ lock_rec_lock_slow(
|
|||
|
||||
trx = thr_get_trx(thr);
|
||||
|
||||
if (lock_rec_has_expl(mode, rec,
|
||||
page_is_comp(buf_frame_align(rec)), trx)) {
|
||||
if (lock_rec_has_expl(mode, rec, trx)) {
|
||||
/* The trx already has a strong enough lock on rec: do
|
||||
nothing */
|
||||
|
||||
|
@ -2207,16 +2222,14 @@ lock_grant(
|
|||
release it at the end of the SQL statement */
|
||||
|
||||
lock->trx->auto_inc_lock = lock;
|
||||
} else if (lock_get_type(lock) == LOCK_TABLE_EXP ||
|
||||
lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL) {
|
||||
ut_a(lock_get_mode(lock) == LOCK_S
|
||||
|| lock_get_mode(lock) == LOCK_X);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (lock_print_waits) {
|
||||
fprintf(stderr, "Lock wait for trx %lu ends\n",
|
||||
(ulong) ut_dulint_get_low(lock->trx->id));
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/* If we are resolving a deadlock by choosing another transaction
|
||||
as a victim, then our original transaction may not be in the
|
||||
|
@ -2383,14 +2396,12 @@ lock_rec_reset_and_release_wait(
|
|||
{
|
||||
lock_t* lock;
|
||||
ulint heap_no;
|
||||
ibool comp;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
comp = page_is_comp(buf_frame_align(rec));
|
||||
heap_no = rec_get_heap_no(rec, comp);
|
||||
heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
|
||||
|
||||
lock = lock_rec_get_first(rec);
|
||||
|
||||
|
@ -2401,7 +2412,7 @@ lock_rec_reset_and_release_wait(
|
|||
lock_rec_reset_nth_bit(lock, heap_no);
|
||||
}
|
||||
|
||||
lock = lock_rec_get_next(rec, comp, lock);
|
||||
lock = lock_rec_get_next(rec, lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2419,13 +2430,11 @@ lock_rec_inherit_to_gap(
|
|||
the locks on this record */
|
||||
{
|
||||
lock_t* lock;
|
||||
ibool comp;
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
lock = lock_rec_get_first(rec);
|
||||
comp = page_is_comp(buf_frame_align(rec));
|
||||
|
||||
while (lock != NULL) {
|
||||
if (!lock_rec_get_insert_intention(lock)) {
|
||||
|
@ -2435,7 +2444,7 @@ lock_rec_inherit_to_gap(
|
|||
heir, lock->index, lock->trx);
|
||||
}
|
||||
|
||||
lock = lock_rec_get_next(rec, comp, lock);
|
||||
lock = lock_rec_get_next(rec, lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2452,13 +2461,11 @@ lock_rec_inherit_to_gap_if_gap_lock(
|
|||
the locks on this record */
|
||||
{
|
||||
lock_t* lock;
|
||||
ibool comp;
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
lock = lock_rec_get_first(rec);
|
||||
comp = page_is_comp(buf_frame_align(rec));
|
||||
|
||||
while (lock != NULL) {
|
||||
if (!lock_rec_get_insert_intention(lock)
|
||||
|
@ -2470,7 +2477,7 @@ lock_rec_inherit_to_gap_if_gap_lock(
|
|||
heir, lock->index, lock->trx);
|
||||
}
|
||||
|
||||
lock = lock_rec_get_next(rec, comp, lock);
|
||||
lock = lock_rec_get_next(rec, lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2484,7 +2491,7 @@ lock_rec_move(
|
|||
rec_t* receiver, /* in: record which gets locks; this record
|
||||
must have no lock requests on it! */
|
||||
rec_t* donator, /* in: record which gives locks */
|
||||
ibool comp) /* in: TRUE=compact page format */
|
||||
ulint comp) /* in: nonzero=compact page format */
|
||||
{
|
||||
lock_t* lock;
|
||||
ulint heap_no;
|
||||
|
@ -2514,7 +2521,7 @@ lock_rec_move(
|
|||
|
||||
lock_rec_add_to_queue(type_mode, receiver, lock->index,
|
||||
lock->trx);
|
||||
lock = lock_rec_get_next(donator, comp, lock);
|
||||
lock = lock_rec_get_next(donator, lock);
|
||||
}
|
||||
|
||||
ut_ad(lock_rec_get_first(donator) == NULL);
|
||||
|
@ -2540,7 +2547,7 @@ lock_move_reorganize_page(
|
|||
UT_LIST_BASE_NODE_T(lock_t) old_locks;
|
||||
mem_heap_t* heap = NULL;
|
||||
rec_t* sup;
|
||||
ibool comp;
|
||||
ulint comp;
|
||||
|
||||
lock_mutex_enter_kernel();
|
||||
|
||||
|
@ -2659,8 +2666,9 @@ lock_move_rec_list_end(
|
|||
ulint heap_no;
|
||||
rec_t* sup;
|
||||
ulint type_mode;
|
||||
ibool comp;
|
||||
|
||||
ulint comp;
|
||||
ut_ad(page == buf_frame_align(rec));
|
||||
|
||||
lock_mutex_enter_kernel();
|
||||
|
||||
/* Note: when we move locks from record to record, waiting locks
|
||||
|
@ -2745,7 +2753,7 @@ lock_move_rec_list_start(
|
|||
page_cur_t cur2;
|
||||
ulint heap_no;
|
||||
ulint type_mode;
|
||||
ibool comp;
|
||||
ulint comp;
|
||||
|
||||
ut_a(new_page);
|
||||
|
||||
|
@ -2754,6 +2762,7 @@ lock_move_rec_list_start(
|
|||
lock = lock_rec_get_first_on_page(page);
|
||||
comp = page_is_comp(page);
|
||||
ut_ad(comp == page_is_comp(new_page));
|
||||
ut_ad(page == buf_frame_align(rec));
|
||||
|
||||
while (lock != NULL) {
|
||||
|
||||
|
@ -2812,7 +2821,7 @@ lock_update_split_right(
|
|||
page_t* right_page, /* in: right page */
|
||||
page_t* left_page) /* in: left page */
|
||||
{
|
||||
ibool comp;
|
||||
ulint comp;
|
||||
lock_mutex_enter_kernel();
|
||||
comp = page_is_comp(left_page);
|
||||
ut_ad(comp == page_is_comp(right_page));
|
||||
|
@ -2875,7 +2884,7 @@ lock_update_root_raise(
|
|||
page_t* new_page, /* in: index page to which copied */
|
||||
page_t* root) /* in: root page */
|
||||
{
|
||||
ibool comp;
|
||||
ulint comp;
|
||||
lock_mutex_enter_kernel();
|
||||
comp = page_is_comp(root);
|
||||
ut_ad(comp == page_is_comp(new_page));
|
||||
|
@ -2898,7 +2907,7 @@ lock_update_copy_and_discard(
|
|||
page_t* new_page, /* in: index page to which copied */
|
||||
page_t* page) /* in: index page; NOT the root! */
|
||||
{
|
||||
ibool comp;
|
||||
ulint comp;
|
||||
lock_mutex_enter_kernel();
|
||||
comp = page_is_comp(page);
|
||||
ut_ad(comp == page_is_comp(new_page));
|
||||
|
@ -2945,31 +2954,34 @@ lock_update_merge_left(
|
|||
page_t* right_page) /* in: merged index page which will be
|
||||
discarded */
|
||||
{
|
||||
ibool comp;
|
||||
rec_t* left_next_rec;
|
||||
rec_t* left_supremum;
|
||||
ulint comp;
|
||||
lock_mutex_enter_kernel();
|
||||
comp = page_is_comp(left_page);
|
||||
ut_ad(comp == page_is_comp(right_page));
|
||||
ut_ad(left_page == buf_frame_align(orig_pred));
|
||||
|
||||
if (page_rec_get_next(orig_pred) != page_get_supremum_rec(left_page)) {
|
||||
left_next_rec = page_rec_get_next(orig_pred);
|
||||
left_supremum = page_get_supremum_rec(left_page);
|
||||
|
||||
if (UNIV_LIKELY(left_next_rec != left_supremum)) {
|
||||
|
||||
/* Inherit the locks on the supremum of the left page to the
|
||||
first record which was moved from the right page */
|
||||
|
||||
lock_rec_inherit_to_gap(page_rec_get_next(orig_pred),
|
||||
page_get_supremum_rec(left_page));
|
||||
lock_rec_inherit_to_gap(left_next_rec, left_supremum);
|
||||
|
||||
/* Reset the locks on the supremum of the left page,
|
||||
releasing waiting transactions */
|
||||
|
||||
lock_rec_reset_and_release_wait(page_get_supremum_rec(
|
||||
left_page));
|
||||
lock_rec_reset_and_release_wait(left_supremum);
|
||||
}
|
||||
|
||||
/* Move the locks from the supremum of right page to the supremum
|
||||
of the left page */
|
||||
|
||||
lock_rec_move(page_get_supremum_rec(left_page),
|
||||
page_get_supremum_rec(right_page), comp);
|
||||
lock_rec_move(left_supremum, page_get_supremum_rec(right_page), comp);
|
||||
|
||||
lock_rec_free_all_from_discard_page(right_page);
|
||||
|
||||
|
@ -3028,7 +3040,7 @@ lock_update_discard(
|
|||
|
||||
lock_rec_reset_and_release_wait(rec);
|
||||
|
||||
if (rec == page_get_supremum_rec(page)) {
|
||||
if (page_rec_is_supremum(rec)) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -3091,19 +3103,16 @@ actual record is being moved. */
|
|||
void
|
||||
lock_rec_store_on_page_infimum(
|
||||
/*===========================*/
|
||||
page_t* page, /* in: page containing the record */
|
||||
rec_t* rec) /* in: record whose lock state is stored
|
||||
on the infimum record of the same page; lock
|
||||
bits are reset on the record */
|
||||
{
|
||||
page_t* page;
|
||||
ibool comp;
|
||||
|
||||
page = buf_frame_align(rec);
|
||||
comp = page_is_comp(page);
|
||||
ut_ad(page == buf_frame_align(rec));
|
||||
|
||||
lock_mutex_enter_kernel();
|
||||
|
||||
lock_rec_move(page_get_infimum_rec(page), rec, comp);
|
||||
lock_rec_move(page_get_infimum_rec(page), rec, page_is_comp(page));
|
||||
|
||||
lock_mutex_exit_kernel();
|
||||
}
|
||||
|
@ -3120,10 +3129,10 @@ lock_rec_restore_from_page_infimum(
|
|||
whose infimum stored the lock state; lock bits are
|
||||
reset on the infimum */
|
||||
{
|
||||
ibool comp;
|
||||
ulint comp;
|
||||
lock_mutex_enter_kernel();
|
||||
comp = page_is_comp(page);
|
||||
ut_ad(comp == page_is_comp(buf_frame_align(rec)));
|
||||
ut_ad(!comp == !page_rec_is_comp(rec));
|
||||
|
||||
lock_rec_move(rec, page_get_infimum_rec(page), comp);
|
||||
|
||||
|
@ -3316,11 +3325,11 @@ lock_deadlock_recursive(
|
|||
} else {
|
||||
lock_table_print(ef, start->wait_lock);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (lock_print_waits) {
|
||||
fputs("Deadlock detected\n", stderr);
|
||||
}
|
||||
|
||||
#endif /* UNIV_DEBUG */
|
||||
if (ut_dulint_cmp(wait_lock->trx->undo_no,
|
||||
start->undo_no) >= 0) {
|
||||
/* Our recursion starting point
|
||||
|
@ -3418,14 +3427,6 @@ lock_table_create(
|
|||
lock->type_mode = type_mode | LOCK_TABLE;
|
||||
lock->trx = trx;
|
||||
|
||||
if (lock_get_type(lock) == LOCK_TABLE_EXP) {
|
||||
lock->trx->n_lock_table_exp++;
|
||||
}
|
||||
|
||||
if (lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL) {
|
||||
lock->trx->n_lock_table_transactional++;
|
||||
}
|
||||
|
||||
lock->un_member.tab_lock.table = table;
|
||||
|
||||
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
|
||||
|
@ -3462,14 +3463,6 @@ lock_table_remove_low(
|
|||
trx->auto_inc_lock = NULL;
|
||||
}
|
||||
|
||||
if (lock_get_type(lock) == LOCK_TABLE_EXP) {
|
||||
trx->n_lock_table_exp--;
|
||||
}
|
||||
|
||||
if (lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL) {
|
||||
trx->n_lock_table_transactional--;
|
||||
}
|
||||
|
||||
UT_LIST_REMOVE(trx_locks, trx->trx_locks, lock);
|
||||
UT_LIST_REMOVE(un_member.tab_lock.locks, table->locks, lock);
|
||||
}
|
||||
|
@ -3600,10 +3593,7 @@ lock_table(
|
|||
/* out: DB_SUCCESS, DB_LOCK_WAIT,
|
||||
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
|
||||
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
|
||||
does nothing;
|
||||
if LOCK_TABLE_EXP|LOCK_TABLE_TRANSACTIONAL
|
||||
bits are set,
|
||||
creates an explicit table lock */
|
||||
does nothing */
|
||||
dict_table_t* table, /* in: database table in dictionary cache */
|
||||
ulint mode, /* in: lock mode */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
|
@ -3618,8 +3608,7 @@ lock_table(
|
|||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
ut_a(flags == 0 || flags == LOCK_TABLE_EXP ||
|
||||
flags == LOCK_TABLE_TRANSACTIONAL);
|
||||
ut_a(flags == 0);
|
||||
|
||||
trx = thr_get_trx(thr);
|
||||
|
||||
|
@ -3732,9 +3721,7 @@ lock_table_dequeue(
|
|||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
ut_a(lock_get_type(in_lock) == LOCK_TABLE ||
|
||||
lock_get_type(in_lock) == LOCK_TABLE_EXP ||
|
||||
lock_get_type(in_lock) == LOCK_TABLE_TRANSACTIONAL);
|
||||
ut_a(lock_get_type(in_lock) == LOCK_TABLE);
|
||||
|
||||
lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock);
|
||||
|
||||
|
@ -3838,12 +3825,6 @@ lock_release_off_kernel(
|
|||
}
|
||||
|
||||
lock_table_dequeue(lock);
|
||||
|
||||
if (lock_get_type(lock) == LOCK_TABLE_EXP ||
|
||||
lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL) {
|
||||
ut_a(lock_get_mode(lock) == LOCK_S
|
||||
|| lock_get_mode(lock) == LOCK_X);
|
||||
}
|
||||
}
|
||||
|
||||
if (count == LOCK_RELEASE_KERNEL_INTERVAL) {
|
||||
|
@ -3863,74 +3844,6 @@ lock_release_off_kernel(
|
|||
mem_heap_empty(trx->lock_heap);
|
||||
|
||||
ut_a(trx->auto_inc_lock == NULL);
|
||||
ut_a(trx->n_lock_table_exp == 0);
|
||||
ut_a(trx->n_lock_table_transactional == 0);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Releases table locks explicitly requested with LOCK TABLES (indicated by
|
||||
lock type LOCK_TABLE_EXP), and releases possible other transactions waiting
|
||||
because of these locks. */
|
||||
|
||||
void
|
||||
lock_release_tables_off_kernel(
|
||||
/*===========================*/
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
dict_table_t* table;
|
||||
ulint count;
|
||||
lock_t* lock;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
lock = UT_LIST_GET_LAST(trx->trx_locks);
|
||||
|
||||
count = 0;
|
||||
|
||||
while (lock != NULL) {
|
||||
|
||||
count++;
|
||||
|
||||
if (lock_get_type(lock) == LOCK_TABLE_EXP) {
|
||||
ut_a(lock_get_mode(lock) == LOCK_S
|
||||
|| lock_get_mode(lock) == LOCK_X);
|
||||
if (trx->insert_undo || trx->update_undo) {
|
||||
|
||||
/* The trx may have modified the table.
|
||||
We block the use of the MySQL query
|
||||
cache for all currently active
|
||||
transactions. */
|
||||
|
||||
table = lock->un_member.tab_lock.table;
|
||||
|
||||
table->query_cache_inv_trx_id =
|
||||
trx_sys->max_trx_id;
|
||||
}
|
||||
|
||||
lock_table_dequeue(lock);
|
||||
|
||||
lock = UT_LIST_GET_LAST(trx->trx_locks);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (count == LOCK_RELEASE_KERNEL_INTERVAL) {
|
||||
/* Release the kernel mutex for a while, so that we
|
||||
do not monopolize it */
|
||||
|
||||
lock_mutex_exit_kernel();
|
||||
|
||||
lock_mutex_enter_kernel();
|
||||
|
||||
count = 0;
|
||||
}
|
||||
|
||||
lock = UT_LIST_GET_PREV(trx_locks, lock);
|
||||
}
|
||||
|
||||
ut_a(trx->n_lock_table_exp == 0);
|
||||
ut_a(trx->n_lock_table_transactional == 0);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -4043,15 +3956,7 @@ lock_table_print(
|
|||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
ut_a(lock_get_type(lock) == LOCK_TABLE ||
|
||||
lock_get_type(lock) == LOCK_TABLE_EXP ||
|
||||
lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL);
|
||||
|
||||
if (lock_get_type(lock) == LOCK_TABLE_EXP) {
|
||||
fputs("EXPLICIT ", file);
|
||||
} else if (lock_get_type(lock) == LOCK_TABLE_TRANSACTIONAL) {
|
||||
fputs("TRANSACTIONAL ", file);
|
||||
}
|
||||
ut_a(lock_get_type(lock) == LOCK_TABLE);
|
||||
|
||||
fputs("TABLE LOCK table ", file);
|
||||
ut_print_name(file, lock->trx, lock->un_member.tab_lock.table->name);
|
||||
|
@ -4187,7 +4092,7 @@ lock_rec_print(
|
|||
}
|
||||
|
||||
mtr_commit(&mtr);
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
@ -4483,15 +4388,14 @@ lock_rec_queue_validate(
|
|||
{
|
||||
trx_t* impl_trx;
|
||||
lock_t* lock;
|
||||
ibool comp;
|
||||
|
||||
ut_a(rec);
|
||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||
comp = page_is_comp(buf_frame_align(rec));
|
||||
ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
|
||||
|
||||
lock_mutex_enter_kernel();
|
||||
|
||||
if (page_rec_is_supremum(rec) || page_rec_is_infimum(rec)) {
|
||||
if (!page_rec_is_user_rec(rec)) {
|
||||
|
||||
lock = lock_rec_get_first(rec);
|
||||
|
||||
|
@ -4511,7 +4415,7 @@ lock_rec_queue_validate(
|
|||
ut_a(lock->index == index);
|
||||
}
|
||||
|
||||
lock = lock_rec_get_next(rec, comp, lock);
|
||||
lock = lock_rec_get_next(rec, lock);
|
||||
}
|
||||
|
||||
lock_mutex_exit_kernel();
|
||||
|
@ -4524,10 +4428,10 @@ lock_rec_queue_validate(
|
|||
impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets);
|
||||
|
||||
if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0,
|
||||
LOCK_WAIT, rec, comp, impl_trx)) {
|
||||
LOCK_WAIT, rec, impl_trx)) {
|
||||
|
||||
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
|
||||
comp, impl_trx));
|
||||
impl_trx));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4541,10 +4445,10 @@ lock_rec_queue_validate(
|
|||
rec, index, offsets);
|
||||
|
||||
if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0,
|
||||
LOCK_WAIT, rec, comp, impl_trx)) {
|
||||
LOCK_WAIT, rec, impl_trx)) {
|
||||
|
||||
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
|
||||
rec, comp, impl_trx));
|
||||
rec, impl_trx));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4561,21 +4465,23 @@ lock_rec_queue_validate(
|
|||
}
|
||||
|
||||
if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) {
|
||||
|
||||
ulint mode;
|
||||
|
||||
if (lock_get_mode(lock) == LOCK_S) {
|
||||
ut_a(!lock_rec_other_has_expl_req(LOCK_X,
|
||||
0, 0, rec, comp, lock->trx));
|
||||
mode = LOCK_X;
|
||||
} else {
|
||||
ut_a(!lock_rec_other_has_expl_req(LOCK_S,
|
||||
0, 0, rec, comp, lock->trx));
|
||||
mode = LOCK_S;
|
||||
}
|
||||
ut_a(!lock_rec_other_has_expl_req(mode,
|
||||
0, 0, rec, lock->trx));
|
||||
|
||||
} else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) {
|
||||
|
||||
ut_a(lock_rec_has_to_wait_in_queue(lock));
|
||||
}
|
||||
|
||||
lock = lock_rec_get_next(rec, comp, lock);
|
||||
lock = lock_rec_get_next(rec, lock);
|
||||
}
|
||||
|
||||
lock_mutex_exit_kernel();
|
||||
|
@ -4673,7 +4579,7 @@ function_exit:
|
|||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(TRUE);
|
||||
|
@ -4859,7 +4765,7 @@ lock_rec_insert_check_and_lock(
|
|||
offsets = rec_get_offsets(next_rec, index, offsets_,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
ut_ad(lock_rec_queue_validate(next_rec, index, offsets));
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
@ -4887,7 +4793,7 @@ lock_rec_convert_impl_to_expl(
|
|||
#endif /* UNIV_SYNC_DEBUG */
|
||||
ut_ad(page_rec_is_user_rec(rec));
|
||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||
ut_ad(page_is_comp(buf_frame_align(rec)) == index->table->comp);
|
||||
ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
|
||||
|
||||
if (index->type & DICT_CLUSTERED) {
|
||||
impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets);
|
||||
|
@ -4901,7 +4807,7 @@ lock_rec_convert_impl_to_expl(
|
|||
record, set one for it */
|
||||
|
||||
if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
|
||||
index->table->comp, impl_trx)) {
|
||||
impl_trx)) {
|
||||
|
||||
lock_rec_add_to_queue(LOCK_REC | LOCK_X
|
||||
| LOCK_REC_NOT_GAP, rec, index,
|
||||
|
@ -5008,7 +4914,7 @@ lock_sec_rec_modify_check_and_lock(
|
|||
offsets = rec_get_offsets(rec, index, offsets_,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
ut_ad(lock_rec_queue_validate(rec, index, offsets));
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,10 +57,11 @@ ulint log_fsp_current_free_limit = 0;
|
|||
/* Global log system variable */
|
||||
log_t* log_sys = NULL;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
ibool log_do_write = TRUE;
|
||||
|
||||
ibool log_debug_writes = FALSE;
|
||||
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/* These control how often we print warnings if the last checkpoint is too
|
||||
old */
|
||||
|
@ -974,22 +975,24 @@ log_group_check_flush_completion(
|
|||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
if (!log_sys->one_flushed && group->n_pending_writes == 0) {
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"Log flushed first to group %lu\n", (ulong) group->id);
|
||||
}
|
||||
|
||||
#endif /* UNIV_DEBUG */
|
||||
log_sys->written_to_some_lsn = log_sys->write_lsn;
|
||||
log_sys->one_flushed = TRUE;
|
||||
|
||||
return(LOG_UNLOCK_NONE_FLUSHED_LOCK);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes && (group->n_pending_writes == 0)) {
|
||||
|
||||
fprintf(stderr, "Log flushed to group %lu\n", (ulong) group->id);
|
||||
}
|
||||
|
||||
#endif /* UNIV_DEBUG */
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -1066,12 +1069,13 @@ log_io_complete(
|
|||
fil_flush(group->space_id);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"Checkpoint info written to group %lu\n",
|
||||
group->id);
|
||||
}
|
||||
|
||||
#endif /* UNIV_DEBUG */
|
||||
log_io_complete_checkpoint();
|
||||
|
||||
return;
|
||||
|
@ -1133,12 +1137,13 @@ log_group_file_header_flush(
|
|||
|
||||
dest_offset = nth_file * group->file_size;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"Writing log file header to group %lu file %lu\n",
|
||||
(ulong) group->id, (ulong) nth_file);
|
||||
}
|
||||
|
||||
#endif /* UNIV_DEBUG */
|
||||
if (log_do_write) {
|
||||
log_sys->n_log_ios++;
|
||||
|
||||
|
@ -1226,7 +1231,8 @@ loop:
|
|||
} else {
|
||||
write_len = len;
|
||||
}
|
||||
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
|
||||
fprintf(stderr,
|
||||
|
@ -1250,7 +1256,7 @@ loop:
|
|||
+ i * OS_FILE_LOG_BLOCK_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* UNIV_DEBUG */
|
||||
/* Calculate the checksums for each log block and write them to
|
||||
the trailer fields of the log blocks */
|
||||
|
||||
|
@ -1384,6 +1390,7 @@ loop:
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"Writing log from %lu %lu up to lsn %lu %lu\n",
|
||||
|
@ -1392,7 +1399,7 @@ loop:
|
|||
(ulong) ut_dulint_get_high(log_sys->lsn),
|
||||
(ulong) ut_dulint_get_low(log_sys->lsn));
|
||||
}
|
||||
|
||||
#endif /* UNIV_DEBUG */
|
||||
log_sys->n_pending_writes++;
|
||||
|
||||
group = UT_LIST_GET_FIRST(log_sys->log_groups);
|
||||
|
@ -1961,12 +1968,14 @@ log_checkpoint(
|
|||
|
||||
log_sys->next_checkpoint_lsn = oldest_lsn;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr, "Making checkpoint no %lu at lsn %lu %lu\n",
|
||||
(ulong) ut_dulint_get_low(log_sys->next_checkpoint_no),
|
||||
(ulong) ut_dulint_get_high(oldest_lsn),
|
||||
(ulong) ut_dulint_get_low(oldest_lsn));
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
log_groups_write_checkpoint_info();
|
||||
|
||||
|
@ -2029,8 +2038,6 @@ log_checkpoint_margin(void)
|
|||
ulint checkpoint_age;
|
||||
ulint advance;
|
||||
dulint oldest_lsn;
|
||||
dulint new_oldest;
|
||||
ibool do_preflush;
|
||||
ibool sync;
|
||||
ibool checkpoint_sync;
|
||||
ibool do_checkpoint;
|
||||
|
@ -2038,7 +2045,6 @@ log_checkpoint_margin(void)
|
|||
loop:
|
||||
sync = FALSE;
|
||||
checkpoint_sync = FALSE;
|
||||
do_preflush = FALSE;
|
||||
do_checkpoint = FALSE;
|
||||
|
||||
mutex_enter(&(log->mutex));
|
||||
|
@ -2058,21 +2064,13 @@ loop:
|
|||
/* A flush is urgent: we have to do a synchronous preflush */
|
||||
|
||||
sync = TRUE;
|
||||
|
||||
advance = 2 * (age - log->max_modified_age_sync);
|
||||
|
||||
new_oldest = ut_dulint_add(oldest_lsn, advance);
|
||||
|
||||
do_preflush = TRUE;
|
||||
|
||||
advance = 2 * (age - log->max_modified_age_async);
|
||||
} else if (age > log->max_modified_age_async) {
|
||||
|
||||
/* A flush is not urgent: we do an asynchronous preflush */
|
||||
advance = age - log->max_modified_age_async;
|
||||
|
||||
new_oldest = ut_dulint_add(oldest_lsn, advance);
|
||||
|
||||
do_preflush = TRUE;
|
||||
} else {
|
||||
advance = 0;
|
||||
}
|
||||
|
||||
checkpoint_age = ut_dulint_minus(log->lsn, log->last_checkpoint_lsn);
|
||||
|
@ -2096,7 +2094,9 @@ loop:
|
|||
|
||||
mutex_exit(&(log->mutex));
|
||||
|
||||
if (do_preflush) {
|
||||
if (advance) {
|
||||
dulint new_oldest = ut_dulint_add(oldest_lsn, advance);
|
||||
|
||||
success = log_preflush_pool_modified_pages(new_oldest, sync);
|
||||
|
||||
/* If the flush succeeded, this thread has done its part
|
||||
|
@ -2347,9 +2347,11 @@ loop:
|
|||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr, "Created archive file %s\n", name);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
ret = os_file_close(file_handle);
|
||||
|
||||
|
@ -2375,7 +2377,8 @@ loop:
|
|||
|
||||
len = group->file_size - (next_offset % group->file_size);
|
||||
}
|
||||
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"Archiving starting at lsn %lu %lu, len %lu to group %lu\n",
|
||||
|
@ -2383,6 +2386,7 @@ loop:
|
|||
(ulong) ut_dulint_get_low(start_lsn),
|
||||
(ulong) len, (ulong) group->id);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
log_sys->n_pending_archive_ios++;
|
||||
|
||||
|
@ -2473,11 +2477,13 @@ log_archive_write_complete_groups(void)
|
|||
trunc_files = n_files - 1;
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes && trunc_files) {
|
||||
fprintf(stderr,
|
||||
"Complete file(s) archived to group %lu\n",
|
||||
(ulong) group->id);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/* Calculate the archive file space start lsn */
|
||||
start_lsn = ut_dulint_subtract(log_sys->next_archived_lsn,
|
||||
|
@ -2500,9 +2506,11 @@ log_archive_write_complete_groups(void)
|
|||
fil_space_truncate_start(group->archive_space_id,
|
||||
trunc_files * group->file_size);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fputs("Archiving writes completed\n", stderr);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
|
@ -2519,9 +2527,11 @@ log_archive_check_completion_low(void)
|
|||
if (log_sys->n_pending_archive_ios == 0
|
||||
&& log_sys->archiving_phase == LOG_ARCHIVE_READ) {
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fputs("Archiving read completed\n", stderr);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/* Archive buffer has now been read in: start archive writes */
|
||||
|
||||
|
@ -2665,6 +2675,7 @@ loop:
|
|||
|
||||
log_sys->next_archived_lsn = limit_lsn;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"Archiving from lsn %lu %lu to lsn %lu %lu\n",
|
||||
|
@ -2673,6 +2684,7 @@ loop:
|
|||
(ulong) ut_dulint_get_high(limit_lsn),
|
||||
(ulong) ut_dulint_get_low(limit_lsn));
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/* Read the log segment to the archive buffer */
|
||||
|
||||
|
@ -2775,12 +2787,14 @@ log_archive_close_groups(
|
|||
group->archived_file_no += 2;
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"Incrementing arch file no to %lu in log group %lu\n",
|
||||
(ulong) group->archived_file_no + 2,
|
||||
(ulong) group->id);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -489,6 +489,7 @@ recv_find_max_checkpoint(
|
|||
log_group_read_checkpoint_info(group, field);
|
||||
|
||||
if (!recv_check_cp_is_consistent(buf)) {
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Checkpoint in group %lu at %lu invalid, %lu\n",
|
||||
|
@ -498,7 +499,7 @@ recv_find_max_checkpoint(
|
|||
+ LOG_CHECKPOINT_CHECKSUM_1));
|
||||
|
||||
}
|
||||
|
||||
#endif /* UNIV_DEBUG */
|
||||
goto not_consistent;
|
||||
}
|
||||
|
||||
|
@ -511,13 +512,15 @@ recv_find_max_checkpoint(
|
|||
checkpoint_no =
|
||||
mach_read_from_8(buf + LOG_CHECKPOINT_NO);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Checkpoint number %lu found in group %lu\n",
|
||||
(ulong) ut_dulint_get_low(checkpoint_no),
|
||||
(ulong) group->id);
|
||||
}
|
||||
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
if (ut_dulint_cmp(checkpoint_no, max_no) >= 0) {
|
||||
*max_group = group;
|
||||
*max_field = field;
|
||||
|
@ -540,7 +543,7 @@ recv_find_max_checkpoint(
|
|||
"InnoDB: to create the InnoDB data files, but log file creation failed.\n"
|
||||
"InnoDB: If that is the case, please refer to\n"
|
||||
"InnoDB: http://dev.mysql.com/doc/mysql/en/Error_creating_InnoDB.html\n");
|
||||
|
||||
*max_field = 0;
|
||||
return(DB_ERROR);
|
||||
}
|
||||
|
||||
|
@ -765,6 +768,7 @@ recv_parse_or_apply_log_rec_body(
|
|||
case MLOG_REC_INSERT: case MLOG_COMP_REC_INSERT:
|
||||
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
|
||||
type == MLOG_COMP_REC_INSERT, &index))) {
|
||||
ut_a(!page||!!page_is_comp(page)==index->table->comp);
|
||||
ptr = page_cur_parse_insert_rec(FALSE, ptr, end_ptr,
|
||||
index, page, mtr);
|
||||
}
|
||||
|
@ -772,20 +776,27 @@ recv_parse_or_apply_log_rec_body(
|
|||
case MLOG_REC_CLUST_DELETE_MARK: case MLOG_COMP_REC_CLUST_DELETE_MARK:
|
||||
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
|
||||
type == MLOG_COMP_REC_CLUST_DELETE_MARK, &index))) {
|
||||
ut_a(!page||!!page_is_comp(page)==index->table->comp);
|
||||
ptr = btr_cur_parse_del_mark_set_clust_rec(ptr,
|
||||
end_ptr, index, page);
|
||||
}
|
||||
break;
|
||||
case MLOG_REC_SEC_DELETE_MARK: case MLOG_COMP_REC_SEC_DELETE_MARK:
|
||||
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
|
||||
type == MLOG_COMP_REC_SEC_DELETE_MARK, &index))) {
|
||||
ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr,
|
||||
index, page);
|
||||
case MLOG_COMP_REC_SEC_DELETE_MARK:
|
||||
/* This log record type is obsolete, but we process it for
|
||||
backward compatibility with MySQL 5.0.3 and 5.0.4. */
|
||||
ut_a(!page || page_is_comp(page));
|
||||
ptr = mlog_parse_index(ptr, end_ptr, TRUE, &index);
|
||||
if (!ptr) {
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
case MLOG_REC_SEC_DELETE_MARK:
|
||||
ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr, page);
|
||||
break;
|
||||
case MLOG_REC_UPDATE_IN_PLACE: case MLOG_COMP_REC_UPDATE_IN_PLACE:
|
||||
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
|
||||
type == MLOG_COMP_REC_UPDATE_IN_PLACE, &index))) {
|
||||
ut_a(!page||!!page_is_comp(page)==index->table->comp);
|
||||
ptr = btr_cur_parse_update_in_place(ptr, end_ptr,
|
||||
page, index);
|
||||
}
|
||||
|
@ -795,6 +806,7 @@ recv_parse_or_apply_log_rec_body(
|
|||
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
|
||||
type == MLOG_COMP_LIST_END_DELETE
|
||||
|| type == MLOG_COMP_LIST_START_DELETE, &index))) {
|
||||
ut_a(!page||!!page_is_comp(page)==index->table->comp);
|
||||
ptr = page_parse_delete_rec_list(type, ptr, end_ptr,
|
||||
index, page, mtr);
|
||||
}
|
||||
|
@ -802,6 +814,7 @@ recv_parse_or_apply_log_rec_body(
|
|||
case MLOG_LIST_END_COPY_CREATED: case MLOG_COMP_LIST_END_COPY_CREATED:
|
||||
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
|
||||
type == MLOG_COMP_LIST_END_COPY_CREATED, &index))) {
|
||||
ut_a(!page||!!page_is_comp(page)==index->table->comp);
|
||||
ptr = page_parse_copy_rec_list_to_created_page(ptr,
|
||||
end_ptr, index, page, mtr);
|
||||
}
|
||||
|
@ -809,6 +822,7 @@ recv_parse_or_apply_log_rec_body(
|
|||
case MLOG_PAGE_REORGANIZE: case MLOG_COMP_PAGE_REORGANIZE:
|
||||
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
|
||||
type == MLOG_COMP_PAGE_REORGANIZE, &index))) {
|
||||
ut_a(!page||!!page_is_comp(page)==index->table->comp);
|
||||
ptr = btr_parse_page_reorganize(ptr, end_ptr, index,
|
||||
page, mtr);
|
||||
}
|
||||
|
@ -841,6 +855,7 @@ recv_parse_or_apply_log_rec_body(
|
|||
case MLOG_REC_DELETE: case MLOG_COMP_REC_DELETE:
|
||||
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
|
||||
type == MLOG_COMP_REC_DELETE, &index))) {
|
||||
ut_a(!page||!!page_is_comp(page)==index->table->comp);
|
||||
ptr = page_cur_parse_delete_rec(ptr, end_ptr,
|
||||
index, page, mtr);
|
||||
}
|
||||
|
@ -1186,6 +1201,7 @@ recv_recover_page(
|
|||
start_lsn = recv->start_lsn;
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Applying log rec type %lu len %lu to space %lu page no %lu\n",
|
||||
|
@ -1193,6 +1209,7 @@ recv_recover_page(
|
|||
(ulong) recv_addr->space,
|
||||
(ulong) recv_addr->page_no);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
recv_parse_or_apply_log_rec_body(recv->type, buf,
|
||||
buf + recv->len, page, &mtr);
|
||||
|
@ -1801,25 +1818,25 @@ recv_parse_log_rec(
|
|||
|
||||
new_ptr = mlog_parse_initial_log_record(ptr, end_ptr, type, space,
|
||||
page_no);
|
||||
if (!new_ptr) {
|
||||
*body = new_ptr;
|
||||
|
||||
if (UNIV_UNLIKELY(!new_ptr)) {
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Check that page_no is sensible */
|
||||
|
||||
if (*page_no > 0x8FFFFFFFUL) {
|
||||
if (UNIV_UNLIKELY(*page_no > 0x8FFFFFFFUL)) {
|
||||
|
||||
recv_sys->found_corrupt_log = TRUE;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
*body = new_ptr;
|
||||
|
||||
new_ptr = recv_parse_or_apply_log_rec_body(*type, new_ptr, end_ptr,
|
||||
NULL, NULL);
|
||||
if (new_ptr == NULL) {
|
||||
if (UNIV_UNLIKELY(new_ptr == NULL)) {
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
@ -2013,12 +2030,14 @@ loop:
|
|||
recv_sys->recovered_offset += len;
|
||||
recv_sys->recovered_lsn = new_recovered_lsn;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Parsed a single log rec type %lu len %lu space %lu page no %lu\n",
|
||||
(ulong) type, (ulong) len, (ulong) space,
|
||||
(ulong) page_no);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
if (type == MLOG_DUMMY_RECORD) {
|
||||
/* Do nothing */
|
||||
|
@ -2101,13 +2120,15 @@ loop:
|
|||
body, ptr + len);
|
||||
#endif /* UNIV_LOG_REPLICATE */
|
||||
}
|
||||
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Parsed a multi log rec type %lu len %lu space %lu page no %lu\n",
|
||||
(ulong) type, (ulong) len, (ulong) space,
|
||||
(ulong) page_no);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
total_len += len;
|
||||
n_recs++;
|
||||
|
@ -2514,6 +2535,7 @@ recv_group_scan_log_recs(
|
|||
start_lsn = end_lsn;
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Scanned group %lu up to log sequence number %lu %lu\n",
|
||||
|
@ -2521,6 +2543,7 @@ recv_group_scan_log_recs(
|
|||
(ulong) ut_dulint_get_high(*group_scanned_lsn),
|
||||
(ulong) ut_dulint_get_low(*group_scanned_lsn));
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
|
@ -2906,10 +2929,12 @@ recv_recovery_from_checkpoint_finish(void)
|
|||
recv_apply_hashed_log_recs(TRUE);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Log records applied to the database\n");
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
if (recv_needed_recovery) {
|
||||
trx_sys_print_mysql_master_log_pos();
|
||||
|
@ -3246,6 +3271,7 @@ ask_again:
|
|||
break;
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (log_debug_writes) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Archive read starting at lsn %lu %lu, len %lu from file %s\n",
|
||||
|
@ -3253,6 +3279,7 @@ ask_again:
|
|||
(ulong) ut_dulint_get_low(start_lsn),
|
||||
(ulong) len, name);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
fil_io(OS_FILE_READ | OS_FILE_LOG, TRUE,
|
||||
group->archive_space_id, read_offset / UNIV_PAGE_SIZE,
|
||||
|
|
|
@ -15,6 +15,7 @@ Created 12/7/1995 Heikki Tuuri
|
|||
#include "buf0buf.h"
|
||||
#include "dict0boot.h"
|
||||
#include "log0recv.h"
|
||||
#include "page0page.h"
|
||||
|
||||
/************************************************************
|
||||
Catenates n bytes to the mtr log. */
|
||||
|
@ -22,9 +23,9 @@ Catenates n bytes to the mtr log. */
|
|||
void
|
||||
mlog_catenate_string(
|
||||
/*=================*/
|
||||
mtr_t* mtr, /* in: mtr */
|
||||
byte* str, /* in: string to write */
|
||||
ulint len) /* in: string length */
|
||||
mtr_t* mtr, /* in: mtr */
|
||||
const byte* str, /* in: string to write */
|
||||
ulint len) /* in: string length */
|
||||
{
|
||||
dyn_array_t* mlog;
|
||||
|
||||
|
@ -301,14 +302,15 @@ corresponding log record to the mini-transaction log. */
|
|||
void
|
||||
mlog_write_string(
|
||||
/*==============*/
|
||||
byte* ptr, /* in: pointer where to write */
|
||||
byte* str, /* in: string to write */
|
||||
ulint len, /* in: string length */
|
||||
mtr_t* mtr) /* in: mini-transaction handle */
|
||||
byte* ptr, /* in: pointer where to write */
|
||||
const byte* str, /* in: string to write */
|
||||
ulint len, /* in: string length */
|
||||
mtr_t* mtr) /* in: mini-transaction handle */
|
||||
{
|
||||
byte* log_ptr;
|
||||
|
||||
if (ptr < buf_pool->frame_zero || ptr >= buf_pool->high_end) {
|
||||
if (UNIV_UNLIKELY(ptr < buf_pool->frame_zero)
|
||||
|| UNIV_UNLIKELY(ptr >= buf_pool->high_end)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to write to a stray memory location %p\n", ptr);
|
||||
ut_error;
|
||||
|
@ -405,7 +407,9 @@ mlog_open_and_write_index(
|
|||
const byte* log_start;
|
||||
const byte* log_end;
|
||||
|
||||
if (!index->table->comp) {
|
||||
ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
|
||||
|
||||
if (!page_rec_is_comp(rec)) {
|
||||
log_start = log_ptr = mlog_open(mtr, 11 + size);
|
||||
if (!log_ptr) {
|
||||
return(NULL); /* logging is disabled */
|
||||
|
@ -498,6 +502,8 @@ mlog_parse_index(
|
|||
dict_table_t* table;
|
||||
dict_index_t* ind;
|
||||
|
||||
ut_ad(comp == FALSE || comp == TRUE);
|
||||
|
||||
if (comp) {
|
||||
if (end_ptr < ptr + 4) {
|
||||
return(NULL);
|
||||
|
|
|
@ -48,16 +48,11 @@ mtr_memo_slot_release(
|
|||
object = slot->object;
|
||||
type = slot->type;
|
||||
|
||||
if (object != NULL) {
|
||||
if (UNIV_LIKELY(object != NULL)) {
|
||||
if (type <= MTR_MEMO_BUF_FIX) {
|
||||
buf_page_release((buf_block_t*)object, type, mtr);
|
||||
} else if (type == MTR_MEMO_S_LOCK) {
|
||||
rw_lock_s_unlock((rw_lock_t*)object);
|
||||
#ifndef UNIV_DEBUG
|
||||
} else {
|
||||
rw_lock_x_unlock((rw_lock_t*)object);
|
||||
}
|
||||
#endif
|
||||
#ifdef UNIV_DEBUG
|
||||
} else if (type == MTR_MEMO_X_LOCK) {
|
||||
rw_lock_x_unlock((rw_lock_t*)object);
|
||||
|
@ -65,8 +60,11 @@ mtr_memo_slot_release(
|
|||
ut_ad(type == MTR_MEMO_MODIFY);
|
||||
ut_ad(mtr_memo_contains(mtr, object,
|
||||
MTR_MEMO_PAGE_X_FIX));
|
||||
}
|
||||
#else
|
||||
} else {
|
||||
rw_lock_x_unlock((rw_lock_t*)object);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
slot->object = NULL;
|
||||
|
|
|
@ -83,7 +83,7 @@ struct os_aio_slot_struct{
|
|||
made and only the slot message
|
||||
needs to be passed to the caller
|
||||
of os_aio_simulated_handle */
|
||||
void* message1; /* message which is given by the */
|
||||
fil_node_t* message1; /* message which is given by the */
|
||||
void* message2; /* the requester of an aio operation
|
||||
and which can be used to identify
|
||||
which pending aio operation was
|
||||
|
@ -133,17 +133,17 @@ os_event_t* os_aio_segment_wait_events = NULL;
|
|||
|
||||
/* The aio arrays for non-ibuf i/o and ibuf i/o, as well as sync aio. These
|
||||
are NULL when the module has not yet been initialized. */
|
||||
os_aio_array_t* os_aio_read_array = NULL;
|
||||
os_aio_array_t* os_aio_write_array = NULL;
|
||||
os_aio_array_t* os_aio_ibuf_array = NULL;
|
||||
os_aio_array_t* os_aio_log_array = NULL;
|
||||
os_aio_array_t* os_aio_sync_array = NULL;
|
||||
static os_aio_array_t* os_aio_read_array = NULL;
|
||||
static os_aio_array_t* os_aio_write_array = NULL;
|
||||
static os_aio_array_t* os_aio_ibuf_array = NULL;
|
||||
static os_aio_array_t* os_aio_log_array = NULL;
|
||||
static os_aio_array_t* os_aio_sync_array = NULL;
|
||||
|
||||
ulint os_aio_n_segments = ULINT_UNDEFINED;
|
||||
static ulint os_aio_n_segments = ULINT_UNDEFINED;
|
||||
|
||||
/* If the following is TRUE, read i/o handler threads try to
|
||||
wait until a batch of new read requests have been posted */
|
||||
ibool os_aio_recommend_sleep_for_read_threads = FALSE;
|
||||
static ibool os_aio_recommend_sleep_for_read_threads = FALSE;
|
||||
|
||||
ulint os_n_file_reads = 0;
|
||||
ulint os_bytes_read_since_printout = 0;
|
||||
|
@ -158,7 +158,7 @@ ibool os_has_said_disk_full = FALSE;
|
|||
|
||||
/* The mutex protecting the following counts of pending pread and pwrite
|
||||
operations */
|
||||
os_mutex_t os_file_count_mutex;
|
||||
static os_mutex_t os_file_count_mutex;
|
||||
ulint os_file_n_pending_preads = 0;
|
||||
ulint os_file_n_pending_pwrites = 0;
|
||||
|
||||
|
@ -3025,7 +3025,7 @@ os_aio_array_reserve_slot(
|
|||
/* out: pointer to slot */
|
||||
ulint type, /* in: OS_FILE_READ or OS_FILE_WRITE */
|
||||
os_aio_array_t* array, /* in: aio array */
|
||||
void* message1,/* in: message to be passed along with
|
||||
fil_node_t* message1,/* in: message to be passed along with
|
||||
the aio operation */
|
||||
void* message2,/* in: message to be passed along with
|
||||
the aio operation */
|
||||
|
@ -3287,7 +3287,7 @@ os_aio(
|
|||
ulint offset_high, /* in: most significant 32 bits of
|
||||
offset */
|
||||
ulint n, /* in: number of bytes to read or write */
|
||||
void* message1,/* in: messages for the aio handler (these
|
||||
fil_node_t* message1,/* in: messages for the aio handler (these
|
||||
can be used to identify a completed aio
|
||||
operation); if mode is OS_AIO_SYNC, these
|
||||
are ignored */
|
||||
|
@ -3472,7 +3472,7 @@ os_aio_windows_handle(
|
|||
ignored */
|
||||
ulint pos, /* this parameter is used only in sync aio:
|
||||
wait for the aio slot at this position */
|
||||
void** message1, /* out: the messages passed with the aio
|
||||
fil_node_t**message1, /* out: the messages passed with the aio
|
||||
request; note that also in the case where
|
||||
the aio operation failed, these output
|
||||
parameters are valid and can be used to
|
||||
|
@ -3563,7 +3563,7 @@ os_aio_posix_handle(
|
|||
/*================*/
|
||||
/* out: TRUE if the aio operation succeeded */
|
||||
ulint array_no, /* in: array number 0 - 3 */
|
||||
void** message1, /* out: the messages passed with the aio
|
||||
fil_node_t**message1, /* out: the messages passed with the aio
|
||||
request; note that also in the case where
|
||||
the aio operation failed, these output
|
||||
parameters are valid and can be used to
|
||||
|
@ -3644,7 +3644,7 @@ os_aio_simulated_handle(
|
|||
i/o thread, segment 1 the log i/o thread,
|
||||
then follow the non-ibuf read threads, and as
|
||||
the last are the non-ibuf write threads */
|
||||
void** message1, /* out: the messages passed with the aio
|
||||
fil_node_t**message1, /* out: the messages passed with the aio
|
||||
request; note that also in the case where
|
||||
the aio operation failed, these output
|
||||
parameters are valid and can be used to
|
||||
|
@ -4182,6 +4182,7 @@ os_aio_refresh_stats(void)
|
|||
os_last_printout = time(NULL);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/**************************************************************************
|
||||
Checks that all slots in the system have been freed, that is, there are
|
||||
no pending io operations. */
|
||||
|
@ -4241,3 +4242,4 @@ os_aio_all_slots_free(void)
|
|||
|
||||
return(FALSE);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
|
|
@ -129,7 +129,7 @@ page_cur_try_search_shortcut(
|
|||
#endif
|
||||
success = TRUE;
|
||||
exit_func:
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(success);
|
||||
|
@ -451,7 +451,7 @@ page_cur_search_with_match(
|
|||
*iup_matched_bytes = up_matched_bytes;
|
||||
*ilow_matched_fields = low_matched_fields;
|
||||
*ilow_matched_bytes = low_matched_bytes;
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
@ -515,8 +515,12 @@ page_cur_insert_rec_write_log(
|
|||
byte* log_ptr;
|
||||
byte* log_end;
|
||||
ulint i;
|
||||
ulint comp;
|
||||
|
||||
ut_a(rec_size < UNIV_PAGE_SIZE);
|
||||
ut_ad(buf_frame_align(insert_rec) == buf_frame_align(cursor_rec));
|
||||
ut_ad(!page_rec_is_comp(insert_rec) == !index->table->comp);
|
||||
comp = page_rec_is_comp(insert_rec);
|
||||
|
||||
{
|
||||
mem_heap_t* heap = NULL;
|
||||
|
@ -539,7 +543,7 @@ page_cur_insert_rec_write_log(
|
|||
ut_ad(rec_size == rec_offs_size(ins_offs));
|
||||
cur_rec_size = rec_offs_size(cur_offs);
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
@ -565,7 +569,7 @@ page_cur_insert_rec_write_log(
|
|||
ins_ptr++;
|
||||
cur_ptr++;
|
||||
} else if ((i < extra_size)
|
||||
&& (i >= extra_size - (index->table->comp
|
||||
&& (i >= extra_size - (comp
|
||||
? REC_N_NEW_EXTRA_BYTES
|
||||
: REC_N_OLD_EXTRA_BYTES))) {
|
||||
i = extra_size;
|
||||
|
@ -580,7 +584,7 @@ page_cur_insert_rec_write_log(
|
|||
if (mtr_get_log_mode(mtr) != MTR_LOG_SHORT_INSERTS) {
|
||||
|
||||
log_ptr = mlog_open_and_write_index(mtr, insert_rec, index,
|
||||
index->table->comp
|
||||
comp
|
||||
? MLOG_COMP_REC_INSERT : MLOG_REC_INSERT,
|
||||
2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN);
|
||||
|
||||
|
@ -605,8 +609,8 @@ page_cur_insert_rec_write_log(
|
|||
log_end = &log_ptr[5 + 1 + 5 + 5 + MLOG_BUF_MARGIN];
|
||||
}
|
||||
|
||||
if ((rec_get_info_and_status_bits(insert_rec, index->table->comp) !=
|
||||
rec_get_info_and_status_bits(cursor_rec, index->table->comp))
|
||||
if ((rec_get_info_and_status_bits(insert_rec, comp) !=
|
||||
rec_get_info_and_status_bits(cursor_rec, comp))
|
||||
|| (extra_size != cur_extra_size)
|
||||
|| (rec_size != cur_rec_size)) {
|
||||
|
||||
|
@ -622,8 +626,7 @@ page_cur_insert_rec_write_log(
|
|||
if (extra_info_yes) {
|
||||
/* Write the info bits */
|
||||
mach_write_to_1(log_ptr,
|
||||
rec_get_info_and_status_bits(insert_rec,
|
||||
index->table->comp));
|
||||
rec_get_info_and_status_bits(insert_rec, comp));
|
||||
log_ptr++;
|
||||
|
||||
/* Write the record origin offset */
|
||||
|
@ -757,6 +760,8 @@ page_cur_parse_insert_rec(
|
|||
return(ptr + end_seg_len);
|
||||
}
|
||||
|
||||
ut_ad(!!page_is_comp(page) == index->table->comp);
|
||||
|
||||
/* Read from the log the inserted index record end segment which
|
||||
differs from the cursor record */
|
||||
|
||||
|
@ -771,7 +776,7 @@ page_cur_parse_insert_rec(
|
|||
|
||||
if (extra_info_yes == 0) {
|
||||
info_and_status_bits = rec_get_info_and_status_bits(
|
||||
cursor_rec, index->table->comp);
|
||||
cursor_rec, page_is_comp(page));
|
||||
origin_offset = rec_offs_extra_size(offsets);
|
||||
mismatch_index = rec_offs_size(offsets) - end_seg_len;
|
||||
}
|
||||
|
@ -807,7 +812,7 @@ page_cur_parse_insert_rec(
|
|||
ut_memcpy(buf, rec_get_start(cursor_rec, offsets), mismatch_index);
|
||||
ut_memcpy(buf + mismatch_index, ptr, end_seg_len);
|
||||
|
||||
rec_set_info_and_status_bits(buf + origin_offset, index->table->comp,
|
||||
rec_set_info_and_status_bits(buf + origin_offset, page_is_comp(page),
|
||||
info_and_status_bits);
|
||||
|
||||
page_cur_position(cursor_rec, &cursor);
|
||||
|
@ -821,7 +826,7 @@ page_cur_parse_insert_rec(
|
|||
mem_free(buf);
|
||||
}
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
|
@ -861,7 +866,7 @@ page_cur_insert_rec_low(
|
|||
rec_t* owner_rec;
|
||||
ulint n_owned;
|
||||
mem_heap_t* heap = NULL;
|
||||
ibool comp = index->table->comp;
|
||||
ulint comp;
|
||||
|
||||
ut_ad(cursor && mtr);
|
||||
ut_ad(tuple || rec);
|
||||
|
@ -869,8 +874,8 @@ page_cur_insert_rec_low(
|
|||
ut_ad(rec || dtuple_check_typed(tuple));
|
||||
|
||||
page = page_cur_get_page(cursor);
|
||||
|
||||
ut_ad(page_is_comp(page) == comp);
|
||||
comp = page_is_comp(page);
|
||||
ut_ad(index->table->comp == !!comp);
|
||||
|
||||
ut_ad(cursor->rec != page_get_supremum_rec(page));
|
||||
|
||||
|
@ -890,7 +895,7 @@ page_cur_insert_rec_low(
|
|||
insert_buf = page_mem_alloc(page, rec_size, index, &heap_no);
|
||||
|
||||
if (insert_buf == NULL) {
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(NULL);
|
||||
|
@ -980,7 +985,7 @@ page_cur_insert_rec_low(
|
|||
page_cur_insert_rec_write_log(insert_rec, rec_size, current_rec,
|
||||
index, mtr);
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(insert_rec);
|
||||
|
@ -1000,8 +1005,10 @@ page_copy_rec_list_to_created_page_write_log(
|
|||
{
|
||||
byte* log_ptr;
|
||||
|
||||
ut_ad(!!page_is_comp(page) == index->table->comp);
|
||||
|
||||
log_ptr = mlog_open_and_write_index(mtr, page, index,
|
||||
index->table->comp
|
||||
page_is_comp(page)
|
||||
? MLOG_COMP_LIST_END_COPY_CREATED
|
||||
: MLOG_LIST_END_COPY_CREATED, 4);
|
||||
ut_a(log_ptr);
|
||||
|
@ -1084,7 +1091,7 @@ page_copy_rec_list_end_to_created_page(
|
|||
ulint log_mode;
|
||||
byte* log_ptr;
|
||||
ulint log_data_len;
|
||||
ibool comp = page_is_comp(page);
|
||||
ulint comp = page_is_comp(page);
|
||||
mem_heap_t* heap = NULL;
|
||||
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
||||
ulint* offsets = offsets_;
|
||||
|
@ -1186,7 +1193,7 @@ page_copy_rec_list_end_to_created_page(
|
|||
slot_index--;
|
||||
}
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
|
@ -1230,8 +1237,10 @@ page_cur_delete_rec_write_log(
|
|||
{
|
||||
byte* log_ptr;
|
||||
|
||||
ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
|
||||
|
||||
log_ptr = mlog_open_and_write_index(mtr, rec, index,
|
||||
index->table->comp
|
||||
page_rec_is_comp(rec)
|
||||
? MLOG_COMP_REC_DELETE
|
||||
: MLOG_REC_DELETE, 2);
|
||||
|
||||
|
@ -1242,7 +1251,7 @@ page_cur_delete_rec_write_log(
|
|||
}
|
||||
|
||||
/* Write the cursor rec offset as a 2-byte ulint */
|
||||
mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
|
||||
mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
|
||||
|
||||
mlog_close(mtr, log_ptr + 2);
|
||||
}
|
||||
|
@ -1285,7 +1294,7 @@ page_cur_parse_delete_rec(
|
|||
page_cur_delete_rec(&cursor, index,
|
||||
rec_get_offsets(rec, index, offsets_,
|
||||
ULINT_UNDEFINED, &heap), mtr);
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
@ -1320,6 +1329,7 @@ page_cur_delete_rec(
|
|||
page = page_cur_get_page(cursor);
|
||||
current_rec = cursor->rec;
|
||||
ut_ad(rec_offs_validate(current_rec, index, offsets));
|
||||
ut_ad(!!page_is_comp(page) == index->table->comp);
|
||||
|
||||
/* The record must not be the supremum or infimum record. */
|
||||
ut_ad(current_rec != page_get_supremum_rec(page));
|
||||
|
|
|
@ -72,65 +72,70 @@ page_dir_find_owner_slot(
|
|||
/* out: the directory slot number */
|
||||
rec_t* rec) /* in: the physical record */
|
||||
{
|
||||
ulint i;
|
||||
ulint steps = 0;
|
||||
page_t* page;
|
||||
page_dir_slot_t* slot;
|
||||
rec_t* original_rec = rec;
|
||||
ibool comp;
|
||||
|
||||
page_t* page;
|
||||
register uint16 rec_offs_bytes;
|
||||
register page_dir_slot_t* slot;
|
||||
register const page_dir_slot_t* first_slot;
|
||||
register rec_t* r = rec;
|
||||
|
||||
ut_ad(page_rec_check(rec));
|
||||
|
||||
page = buf_frame_align(rec);
|
||||
comp = page_is_comp(page);
|
||||
first_slot = page_dir_get_nth_slot(page, 0);
|
||||
slot = page_dir_get_nth_slot(page, page_dir_get_n_slots(page) - 1);
|
||||
|
||||
while (rec_get_n_owned(rec, comp) == 0) {
|
||||
steps++;
|
||||
rec = page_rec_get_next(rec);
|
||||
if (page_is_comp(page)) {
|
||||
while (rec_get_n_owned(r, TRUE) == 0) {
|
||||
r = page + rec_get_next_offs(r, TRUE);
|
||||
ut_ad(r >= page + PAGE_NEW_SUPREMUM);
|
||||
ut_ad(r < page + (UNIV_PAGE_SIZE - PAGE_DIR));
|
||||
}
|
||||
} else {
|
||||
while (rec_get_n_owned(r, FALSE) == 0) {
|
||||
r = page + rec_get_next_offs(r, FALSE);
|
||||
ut_ad(r >= page + PAGE_OLD_SUPREMUM);
|
||||
ut_ad(r < page + (UNIV_PAGE_SIZE - PAGE_DIR));
|
||||
}
|
||||
}
|
||||
|
||||
page = buf_frame_align(rec);
|
||||
|
||||
i = page_dir_get_n_slots(page) - 1;
|
||||
slot = page_dir_get_nth_slot(page, i);
|
||||
rec_offs_bytes = mach_encode_2(r - page);
|
||||
|
||||
while (page_dir_slot_get_rec(slot) != rec) {
|
||||
while (UNIV_LIKELY(*(uint16*) slot != rec_offs_bytes)) {
|
||||
|
||||
if (i == 0) {
|
||||
if (UNIV_UNLIKELY(slot == first_slot)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Probable data corruption on page %lu\n"
|
||||
"InnoDB: Original record ",
|
||||
(ulong) buf_frame_get_page_no(page));
|
||||
|
||||
if (comp) {
|
||||
fputs("(compact record)", stderr);
|
||||
} else {
|
||||
rec_print_old(stderr, original_rec);
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n"
|
||||
"InnoDB: on that page. Steps %lu.\n", (ulong) steps);
|
||||
fputs(
|
||||
"InnoDB: Cannot find the dir slot for record ",
|
||||
stderr);
|
||||
if (comp) {
|
||||
if (page_is_comp(page)) {
|
||||
fputs("(compact record)", stderr);
|
||||
} else {
|
||||
rec_print_old(stderr, rec);
|
||||
}
|
||||
|
||||
fputs("\n"
|
||||
"InnoDB: on that page.\n"
|
||||
"InnoDB: Cannot find the dir slot for record ",
|
||||
stderr);
|
||||
if (page_is_comp(page)) {
|
||||
fputs("(compact record)", stderr);
|
||||
} else {
|
||||
rec_print_old(stderr, page
|
||||
+ mach_decode_2(rec_offs_bytes));
|
||||
}
|
||||
fputs("\n"
|
||||
"InnoDB: on that page!\n", stderr);
|
||||
|
||||
buf_page_print(page);
|
||||
|
||||
ut_error;
|
||||
}
|
||||
ut_error;
|
||||
}
|
||||
|
||||
i--;
|
||||
slot = page_dir_get_nth_slot(page, i);
|
||||
slot += PAGE_DIR_SLOT_SIZE;
|
||||
}
|
||||
|
||||
return(i);
|
||||
return(((ulint) (first_slot - slot)) / PAGE_DIR_SLOT_SIZE);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
@ -252,13 +257,13 @@ page_mem_alloc(
|
|||
*heap_no = rec_get_heap_no(rec, page_is_comp(page));
|
||||
|
||||
block = rec_get_start(rec, offsets);
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(block);
|
||||
}
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
@ -290,7 +295,7 @@ page_create_write_log(
|
|||
buf_frame_t* frame, /* in: a buffer frame where the page is
|
||||
created */
|
||||
mtr_t* mtr, /* in: mini-transaction handle */
|
||||
ibool comp) /* in: TRUE=compact page format */
|
||||
ulint comp) /* in: nonzero=compact page format */
|
||||
{
|
||||
mlog_write_initial_log_record(frame,
|
||||
comp ? MLOG_COMP_PAGE_CREATE : MLOG_PAGE_CREATE, mtr);
|
||||
|
@ -305,7 +310,7 @@ page_parse_create(
|
|||
/* out: end of log record or NULL */
|
||||
byte* ptr, /* in: buffer */
|
||||
byte* end_ptr __attribute__((unused)), /* 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 */
|
||||
{
|
||||
|
@ -330,7 +335,7 @@ page_create(
|
|||
buf_frame_t* frame, /* in: a buffer frame where the page is
|
||||
created */
|
||||
mtr_t* mtr, /* in: mini-transaction handle */
|
||||
ibool comp) /* in: TRUE=compact page format */
|
||||
ulint comp) /* in: nonzero=compact page format */
|
||||
{
|
||||
page_dir_slot_t* slot;
|
||||
mem_heap_t* heap;
|
||||
|
@ -396,9 +401,9 @@ page_create(
|
|||
dtuple_set_info_bits(tuple, REC_STATUS_SUPREMUM);
|
||||
field = dtuple_get_nth_field(tuple, 0);
|
||||
|
||||
dfield_set_data(field, "supremum", 9 - comp);
|
||||
dfield_set_data(field, "supremum", comp ? 8 : 9);
|
||||
dtype_set(dfield_get_type(field),
|
||||
DATA_VARCHAR, DATA_ENGLISH | DATA_NOT_NULL, 9 - comp, 0);
|
||||
DATA_VARCHAR, DATA_ENGLISH | DATA_NOT_NULL, comp ? 8 : 9, 0);
|
||||
|
||||
supremum_rec = rec_convert_dtuple_to_rec(heap_top, index, tuple);
|
||||
|
||||
|
@ -478,10 +483,11 @@ page_copy_rec_list_end_no_locks(
|
|||
page_cur_move_to_next(&cur1);
|
||||
}
|
||||
|
||||
ut_a(index->table->comp == page_is_comp(page));
|
||||
ut_a(index->table->comp == page_is_comp(new_page));
|
||||
ut_a(!!page_is_comp(new_page) == index->table->comp);
|
||||
ut_a(page_is_comp(new_page) == page_is_comp(page));
|
||||
ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10) == (ulint)
|
||||
(index->table->comp ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM));
|
||||
(page_is_comp(new_page)
|
||||
? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM));
|
||||
|
||||
page_cur_set_before_first(new_page, &cur2);
|
||||
|
||||
|
@ -489,12 +495,15 @@ page_copy_rec_list_end_no_locks(
|
|||
|
||||
sup = page_get_supremum_rec(page);
|
||||
|
||||
while (sup != page_cur_get_rec(&cur1)) {
|
||||
for (;;) {
|
||||
rec_t* cur1_rec = page_cur_get_rec(&cur1);
|
||||
if (cur1_rec == sup) {
|
||||
break;
|
||||
}
|
||||
offsets = rec_get_offsets(cur1_rec, index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
if (!page_cur_rec_insert(&cur2, cur1_rec, index,
|
||||
offsets, mtr)) {
|
||||
if (UNIV_UNLIKELY(!page_cur_rec_insert(&cur2, cur1_rec, index,
|
||||
offsets, mtr))) {
|
||||
/* Track an assertion failure reported on the mailing
|
||||
list on June 18th, 2003 */
|
||||
|
||||
|
@ -514,7 +523,7 @@ page_copy_rec_list_end_no_locks(
|
|||
page_cur_move_to_next(&cur2);
|
||||
}
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
@ -608,7 +617,7 @@ page_copy_rec_list_start(
|
|||
|
||||
btr_search_move_or_delete_hash_entries(new_page, page, index);
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
@ -619,7 +628,6 @@ UNIV_INLINE
|
|||
void
|
||||
page_delete_rec_list_write_log(
|
||||
/*===========================*/
|
||||
page_t* page, /* in: index page */
|
||||
rec_t* rec, /* in: record on page */
|
||||
dict_index_t* index, /* in: record descriptor */
|
||||
byte type, /* in: operation type:
|
||||
|
@ -632,10 +640,10 @@ page_delete_rec_list_write_log(
|
|||
|| type == MLOG_COMP_LIST_END_DELETE
|
||||
|| type == MLOG_COMP_LIST_START_DELETE);
|
||||
|
||||
log_ptr = mlog_open_and_write_index(mtr, page, index, type, 2);
|
||||
log_ptr = mlog_open_and_write_index(mtr, rec, index, type, 2);
|
||||
if (log_ptr) {
|
||||
/* Write the parameter as a 2-byte ulint */
|
||||
mach_write_to_2(log_ptr, rec - page);
|
||||
mach_write_to_2(log_ptr, ut_align_offset(rec, UNIV_PAGE_SIZE));
|
||||
mlog_close(mtr, log_ptr + 2);
|
||||
}
|
||||
}
|
||||
|
@ -679,6 +687,8 @@ page_parse_delete_rec_list(
|
|||
return(ptr);
|
||||
}
|
||||
|
||||
ut_ad(!!page_is_comp(page) == index->table->comp);
|
||||
|
||||
if (type == MLOG_LIST_END_DELETE
|
||||
|| type == MLOG_COMP_LIST_END_DELETE) {
|
||||
page_delete_rec_list_end(page, page + offset, index,
|
||||
|
@ -716,7 +726,7 @@ page_delete_rec_list_end(
|
|||
ulint count;
|
||||
ulint n_owned;
|
||||
rec_t* sup;
|
||||
ibool comp;
|
||||
ulint comp;
|
||||
|
||||
/* Reset the last insert info in the page header and increment
|
||||
the modify clock for the frame */
|
||||
|
@ -731,12 +741,12 @@ page_delete_rec_list_end(
|
|||
|
||||
sup = page_get_supremum_rec(page);
|
||||
|
||||
if (rec == page_get_infimum_rec(page)) {
|
||||
comp = page_is_comp(page);
|
||||
if (page_rec_is_infimum_low(rec - page)) {
|
||||
rec = page_rec_get_next(rec);
|
||||
}
|
||||
|
||||
comp = page_is_comp(page);
|
||||
page_delete_rec_list_write_log(page, rec, index,
|
||||
page_delete_rec_list_write_log(rec, index,
|
||||
comp ? MLOG_COMP_LIST_END_DELETE : MLOG_LIST_END_DELETE, mtr);
|
||||
|
||||
if (rec == sup) {
|
||||
|
@ -772,7 +782,7 @@ page_delete_rec_list_end(
|
|||
rec2 = page_rec_get_next(rec2);
|
||||
}
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
@ -841,13 +851,15 @@ page_delete_rec_list_start(
|
|||
byte type;
|
||||
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
|
||||
|
||||
if (index->table->comp) {
|
||||
ut_ad(!!page_is_comp(page) == index->table->comp);
|
||||
|
||||
if (page_is_comp(page)) {
|
||||
type = MLOG_COMP_LIST_START_DELETE;
|
||||
} else {
|
||||
type = MLOG_LIST_START_DELETE;
|
||||
}
|
||||
|
||||
page_delete_rec_list_write_log(page, rec, index, type, mtr);
|
||||
page_delete_rec_list_write_log(rec, index, type, mtr);
|
||||
|
||||
page_cur_set_before_first(page, &cur1);
|
||||
|
||||
|
@ -868,7 +880,7 @@ page_delete_rec_list_start(
|
|||
page_cur_delete_rec(&cur1, index, offsets, mtr);
|
||||
}
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
|
@ -1221,7 +1233,7 @@ page_rec_get_n_recs_before(
|
|||
rec_t* slot_rec;
|
||||
page_t* page;
|
||||
ulint i;
|
||||
ibool comp;
|
||||
ulint comp;
|
||||
lint n = 0;
|
||||
|
||||
ut_ad(page_rec_check(rec));
|
||||
|
@ -1264,9 +1276,9 @@ page_rec_print(
|
|||
rec_t* rec, /* in: physical record */
|
||||
const ulint* offsets)/* in: record descriptor */
|
||||
{
|
||||
ibool comp = page_is_comp(buf_frame_align(rec));
|
||||
ulint comp = page_is_comp(buf_frame_align(rec));
|
||||
|
||||
ut_a(comp == rec_offs_comp(offsets));
|
||||
ut_a(!comp == !rec_offs_comp(offsets));
|
||||
rec_print_new(stderr, rec, offsets);
|
||||
fprintf(stderr,
|
||||
" n_owned: %lu; heap_no: %lu; next rec: %lu\n",
|
||||
|
@ -1335,7 +1347,7 @@ page_print_list(
|
|||
ulint* offsets = offsets_;
|
||||
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
|
||||
|
||||
ut_a(page_is_comp(page) == index->table->comp);
|
||||
ut_a(!!page_is_comp(page) == index->table->comp);
|
||||
|
||||
fprintf(stderr,
|
||||
"--------------------------------\n"
|
||||
|
@ -1381,7 +1393,7 @@ page_print_list(
|
|||
"--------------------------------\n",
|
||||
(ulong) (count + 1));
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
@ -1447,11 +1459,11 @@ page_rec_validate(
|
|||
ulint n_owned;
|
||||
ulint heap_no;
|
||||
page_t* page;
|
||||
ibool comp;
|
||||
ulint comp;
|
||||
|
||||
page = buf_frame_align(rec);
|
||||
comp = page_is_comp(page);
|
||||
ut_a(comp == rec_offs_comp(offsets));
|
||||
ut_a(!comp == !rec_offs_comp(offsets));
|
||||
|
||||
page_rec_check(rec);
|
||||
rec_validate(rec, offsets);
|
||||
|
@ -1528,7 +1540,7 @@ page_simple_validate(
|
|||
ulint count;
|
||||
ulint own_count;
|
||||
ibool ret = FALSE;
|
||||
ibool comp = page_is_comp(page);
|
||||
ulint comp = page_is_comp(page);
|
||||
|
||||
/* Check first that the record heap and the directory do not
|
||||
overlap. */
|
||||
|
@ -1725,11 +1737,11 @@ page_validate(
|
|||
ulint n_slots;
|
||||
ibool ret = FALSE;
|
||||
ulint i;
|
||||
ibool comp = page_is_comp(page);
|
||||
ulint comp = page_is_comp(page);
|
||||
ulint* offsets = NULL;
|
||||
ulint* old_offsets = NULL;
|
||||
|
||||
if (comp != index->table->comp) {
|
||||
if (!!comp != index->table->comp) {
|
||||
fputs("InnoDB: 'compact format' flag mismatch\n", stderr);
|
||||
goto func_exit2;
|
||||
}
|
||||
|
@ -1810,8 +1822,7 @@ page_validate(
|
|||
}
|
||||
}
|
||||
|
||||
if ((rec != page_get_supremum_rec(page))
|
||||
&& (rec != page_get_infimum_rec(page))) {
|
||||
if (page_rec_is_user_rec(rec)) {
|
||||
|
||||
data_size += rec_offs_size(offsets);
|
||||
}
|
||||
|
|
|
@ -320,7 +320,7 @@ cmp_data_data_slow(
|
|||
|| (cur_type->mtype == DATA_BLOB
|
||||
&& 0 == (cur_type->prtype & DATA_BINARY_TYPE)
|
||||
&& dtype_get_charset_coll(cur_type->prtype) !=
|
||||
data_mysql_latin1_swedish_charset_coll)) {
|
||||
DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
|
||||
|
||||
return(cmp_whole_field(cur_type,
|
||||
data1, (unsigned) len1,
|
||||
|
@ -451,6 +451,20 @@ cmp_dtuple_rec_with_match(
|
|||
ut_ad(cur_field <= dtuple_get_n_fields_cmp(dtuple));
|
||||
ut_ad(cur_field <= rec_offs_n_fields(offsets));
|
||||
|
||||
if (cur_bytes == 0 && cur_field == 0) {
|
||||
ulint rec_info = rec_get_info_bits(rec,
|
||||
rec_offs_comp(offsets));
|
||||
ulint tup_info = dtuple_get_info_bits(dtuple);
|
||||
|
||||
if (rec_info & REC_INFO_MIN_REC_FLAG) {
|
||||
ret = !(tup_info & REC_INFO_MIN_REC_FLAG);
|
||||
goto order_resolved;
|
||||
} else if (tup_info & REC_INFO_MIN_REC_FLAG) {
|
||||
ret = -1;
|
||||
goto order_resolved;
|
||||
}
|
||||
}
|
||||
|
||||
/* Match fields in a loop; stop if we run out of fields in dtuple
|
||||
or find an externally stored field */
|
||||
|
||||
|
@ -469,32 +483,7 @@ cmp_dtuple_rec_with_match(
|
|||
the predefined minimum record, or the field is externally
|
||||
stored */
|
||||
|
||||
if (cur_bytes == 0) {
|
||||
if (cur_field == 0) {
|
||||
|
||||
if (rec_get_info_bits(rec,
|
||||
rec_offs_comp(offsets))
|
||||
& REC_INFO_MIN_REC_FLAG) {
|
||||
|
||||
if (dtuple_get_info_bits(dtuple)
|
||||
& REC_INFO_MIN_REC_FLAG) {
|
||||
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
goto order_resolved;
|
||||
}
|
||||
|
||||
if (dtuple_get_info_bits(dtuple)
|
||||
& REC_INFO_MIN_REC_FLAG) {
|
||||
ret = -1;
|
||||
|
||||
goto order_resolved;
|
||||
}
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY(cur_bytes == 0)) {
|
||||
if (rec_offs_nth_extern(offsets, cur_field)) {
|
||||
/* We do not compare to an externally
|
||||
stored field */
|
||||
|
@ -504,24 +493,20 @@ cmp_dtuple_rec_with_match(
|
|||
goto order_resolved;
|
||||
}
|
||||
|
||||
if (dtuple_f_len == UNIV_SQL_NULL
|
||||
|| rec_f_len == UNIV_SQL_NULL) {
|
||||
|
||||
if (dtuple_f_len == rec_f_len) {
|
||||
if (dtuple_f_len == UNIV_SQL_NULL) {
|
||||
if (rec_f_len == UNIV_SQL_NULL) {
|
||||
|
||||
goto next_field;
|
||||
}
|
||||
|
||||
if (rec_f_len == UNIV_SQL_NULL) {
|
||||
/* We define the SQL null to be the
|
||||
smallest possible value of a field
|
||||
in the alphabetical order */
|
||||
|
||||
ret = 1;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
ret = -1;
|
||||
goto order_resolved;
|
||||
} else if (rec_f_len == UNIV_SQL_NULL) {
|
||||
/* We define the SQL null to be the
|
||||
smallest possible value of a field
|
||||
in the alphabetical order */
|
||||
|
||||
ret = 1;
|
||||
goto order_resolved;
|
||||
}
|
||||
}
|
||||
|
@ -530,7 +515,7 @@ cmp_dtuple_rec_with_match(
|
|||
|| (cur_type->mtype == DATA_BLOB
|
||||
&& 0 == (cur_type->prtype & DATA_BINARY_TYPE)
|
||||
&& dtype_get_charset_coll(cur_type->prtype) !=
|
||||
data_mysql_latin1_swedish_charset_coll)) {
|
||||
DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
|
||||
|
||||
ret = cmp_whole_field(
|
||||
cur_type,
|
||||
|
@ -555,7 +540,7 @@ cmp_dtuple_rec_with_match(
|
|||
/* Compare then the fields */
|
||||
|
||||
for (;;) {
|
||||
if (rec_f_len <= cur_bytes) {
|
||||
if (UNIV_UNLIKELY(rec_f_len <= cur_bytes)) {
|
||||
if (dtuple_f_len <= cur_bytes) {
|
||||
|
||||
goto next_field;
|
||||
|
@ -572,7 +557,7 @@ cmp_dtuple_rec_with_match(
|
|||
rec_byte = *rec_b_ptr;
|
||||
}
|
||||
|
||||
if (dtuple_f_len <= cur_bytes) {
|
||||
if (UNIV_UNLIKELY(dtuple_f_len <= cur_bytes)) {
|
||||
dtuple_byte = dtype_get_pad_char(cur_type);
|
||||
|
||||
if (dtuple_byte == ULINT_UNDEFINED) {
|
||||
|
@ -600,14 +585,16 @@ cmp_dtuple_rec_with_match(
|
|||
rec_byte = cmp_collate(rec_byte);
|
||||
dtuple_byte = cmp_collate(dtuple_byte);
|
||||
}
|
||||
|
||||
if (dtuple_byte > rec_byte) {
|
||||
ret = 1;
|
||||
goto order_resolved;
|
||||
|
||||
} else if (dtuple_byte < rec_byte) {
|
||||
ret = -1;
|
||||
goto order_resolved;
|
||||
ret = dtuple_byte - rec_byte;
|
||||
if (UNIV_UNLIKELY(ret)) {
|
||||
if (ret < 0) {
|
||||
ret = -1;
|
||||
goto order_resolved;
|
||||
} else {
|
||||
ret = 1;
|
||||
goto order_resolved;
|
||||
}
|
||||
}
|
||||
next_byte:
|
||||
/* Next byte */
|
||||
|
@ -740,7 +727,7 @@ cmp_rec_rec_with_match(
|
|||
ulint cur_bytes; /* number of already matched bytes in current
|
||||
field */
|
||||
int ret = 3333; /* return value */
|
||||
ibool comp;
|
||||
ulint comp;
|
||||
|
||||
ut_ad(rec1 && rec2 && index);
|
||||
ut_ad(rec_offs_validate(rec1, index, offsets1));
|
||||
|
@ -832,7 +819,7 @@ cmp_rec_rec_with_match(
|
|||
|| (cur_type->mtype == DATA_BLOB
|
||||
&& 0 == (cur_type->prtype & DATA_BINARY_TYPE)
|
||||
&& dtype_get_charset_coll(cur_type->prtype) !=
|
||||
data_mysql_latin1_swedish_charset_coll)) {
|
||||
DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
|
||||
|
||||
ret = cmp_whole_field(cur_type,
|
||||
rec1_b_ptr, (unsigned) rec1_f_len,
|
||||
|
@ -983,12 +970,8 @@ cmp_debug_dtuple_rec_with_match(
|
|||
if (rec_get_info_bits(rec, rec_offs_comp(offsets))
|
||||
& REC_INFO_MIN_REC_FLAG) {
|
||||
|
||||
if (dtuple_get_info_bits(dtuple)
|
||||
& REC_INFO_MIN_REC_FLAG) {
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
ret = !(dtuple_get_info_bits(dtuple)
|
||||
& REC_INFO_MIN_REC_FLAG);
|
||||
|
||||
goto order_resolved;
|
||||
}
|
||||
|
|
|
@ -159,22 +159,20 @@ rec_init_offsets(
|
|||
ulint* offsets)/* in/out: array of offsets;
|
||||
in: n=rec_offs_n_fields(offsets) */
|
||||
{
|
||||
ulint n_fields = rec_offs_n_fields(offsets);
|
||||
ulint i = 0;
|
||||
ulint offs;
|
||||
|
||||
rec_offs_make_valid(rec, index, offsets);
|
||||
|
||||
if (index->table->comp) {
|
||||
if (UNIV_LIKELY(index->table->comp)) {
|
||||
const byte* nulls;
|
||||
const byte* lens;
|
||||
dict_field_t* field;
|
||||
dtype_t* type;
|
||||
ulint null_mask;
|
||||
ulint status = rec_get_status(rec);
|
||||
ulint n_node_ptr_field = ULINT_UNDEFINED;
|
||||
|
||||
switch (status) {
|
||||
switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
|
||||
case REC_STATUS_INFIMUM:
|
||||
case REC_STATUS_SUPREMUM:
|
||||
/* the field is 8 bytes long */
|
||||
|
@ -196,56 +194,69 @@ rec_init_offsets(
|
|||
null_mask = 1;
|
||||
|
||||
/* read the lengths of fields 0..n */
|
||||
for (; i < n_fields; i++) {
|
||||
ibool is_null = FALSE, is_external = FALSE;
|
||||
do {
|
||||
ulint len;
|
||||
if (i == n_node_ptr_field) {
|
||||
len = 4;
|
||||
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
|
||||
len = offs += 4;
|
||||
goto resolved;
|
||||
}
|
||||
|
||||
field = dict_index_get_nth_field(index, i);
|
||||
type = dict_col_get_type(dict_field_get_col(field));
|
||||
if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
|
||||
if (!(dtype_get_prtype(dict_col_get_type(
|
||||
dict_field_get_col(field)))
|
||||
& DATA_NOT_NULL)) {
|
||||
/* nullable field => read the null flag */
|
||||
is_null = (*nulls & null_mask) != 0;
|
||||
null_mask <<= 1;
|
||||
if (null_mask == 0x100) {
|
||||
|
||||
if (UNIV_UNLIKELY(!(byte) null_mask)) {
|
||||
nulls--;
|
||||
null_mask = 1;
|
||||
}
|
||||
|
||||
if (*nulls & null_mask) {
|
||||
null_mask <<= 1;
|
||||
/* No length is stored for NULL fields.
|
||||
We do not advance offs, and we set
|
||||
the length to zero and enable the
|
||||
SQL NULL flag in offsets[]. */
|
||||
len = offs | REC_OFFS_SQL_NULL;
|
||||
goto resolved;
|
||||
}
|
||||
null_mask <<= 1;
|
||||
}
|
||||
|
||||
if (is_null) {
|
||||
/* No length is stored for NULL fields. */
|
||||
len = 0;
|
||||
} else if (!field->fixed_len) {
|
||||
if (UNIV_UNLIKELY(!field->fixed_len)) {
|
||||
/* Variable-length field: read the length */
|
||||
dtype_t* type = dict_col_get_type(
|
||||
dict_field_get_col(field));
|
||||
len = *lens--;
|
||||
if (dtype_get_len(type) > 255
|
||||
|| dtype_get_mtype(type) == DATA_BLOB) {
|
||||
if (UNIV_UNLIKELY(dtype_get_len(type) > 255)
|
||||
|| UNIV_UNLIKELY(dtype_get_mtype(type)
|
||||
== DATA_BLOB)) {
|
||||
if (len & 0x80) {
|
||||
/* 1exxxxxxx xxxxxxxx */
|
||||
is_external = !!(len & 0x40);
|
||||
len &= 0x3f;
|
||||
len <<= 8;
|
||||
len |= *lens--;
|
||||
|
||||
offs += len & 0x3fff;
|
||||
if (UNIV_UNLIKELY(len
|
||||
& 0x4000)) {
|
||||
len = offs
|
||||
| REC_OFFS_EXTERNAL;
|
||||
} else {
|
||||
len = offs;
|
||||
}
|
||||
|
||||
goto resolved;
|
||||
}
|
||||
}
|
||||
|
||||
len = offs += len;
|
||||
} else {
|
||||
len = field->fixed_len;
|
||||
len = offs += field->fixed_len;
|
||||
}
|
||||
resolved:
|
||||
offs += len;
|
||||
len = offs;
|
||||
if (is_external) {
|
||||
len |= REC_OFFS_EXTERNAL;
|
||||
}
|
||||
if (is_null) {
|
||||
len |= REC_OFFS_SQL_NULL;
|
||||
}
|
||||
rec_offs_base(offsets)[i + 1] = len;
|
||||
}
|
||||
} while (++i < rec_offs_n_fields(offsets));
|
||||
|
||||
*rec_offs_base(offsets) =
|
||||
(rec - (lens + 1)) | REC_OFFS_COMPACT;
|
||||
|
@ -253,22 +264,22 @@ rec_init_offsets(
|
|||
/* Old-style record: determine extra size and end offsets */
|
||||
offs = REC_N_OLD_EXTRA_BYTES;
|
||||
if (rec_get_1byte_offs_flag(rec)) {
|
||||
offs += n_fields;
|
||||
offs += rec_offs_n_fields(offsets);
|
||||
*rec_offs_base(offsets) = offs;
|
||||
/* Determine offsets to fields */
|
||||
for (; i < n_fields; i++) {
|
||||
do {
|
||||
offs = rec_1_get_field_end_info(rec, i);
|
||||
if (offs & REC_1BYTE_SQL_NULL_MASK) {
|
||||
offs &= ~REC_1BYTE_SQL_NULL_MASK;
|
||||
offs |= REC_OFFS_SQL_NULL;
|
||||
}
|
||||
rec_offs_base(offsets)[1 + i] = offs;
|
||||
}
|
||||
} while (++i < rec_offs_n_fields(offsets));
|
||||
} else {
|
||||
offs += 2 * n_fields;
|
||||
offs += 2 * rec_offs_n_fields(offsets);
|
||||
*rec_offs_base(offsets) = offs;
|
||||
/* Determine offsets to fields */
|
||||
for (; i < n_fields; i++) {
|
||||
do {
|
||||
offs = rec_2_get_field_end_info(rec, i);
|
||||
if (offs & REC_2BYTE_SQL_NULL_MASK) {
|
||||
offs &= ~REC_2BYTE_SQL_NULL_MASK;
|
||||
|
@ -279,7 +290,7 @@ rec_init_offsets(
|
|||
offs |= REC_OFFS_EXTERNAL;
|
||||
}
|
||||
rec_offs_base(offsets)[1 + i] = offs;
|
||||
}
|
||||
} while (++i < rec_offs_n_fields(offsets));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -310,8 +321,9 @@ rec_get_offsets_func(
|
|||
ut_ad(index);
|
||||
ut_ad(heap);
|
||||
|
||||
if (index->table->comp) {
|
||||
switch (rec_get_status(rec)) {
|
||||
if (UNIV_LIKELY(index->table->comp)) {
|
||||
switch (UNIV_EXPECT(rec_get_status(rec),
|
||||
REC_STATUS_ORDINARY)) {
|
||||
case REC_STATUS_ORDINARY:
|
||||
n = dict_index_get_n_fields(index);
|
||||
break;
|
||||
|
@ -331,13 +343,14 @@ rec_get_offsets_func(
|
|||
n = rec_get_n_fields_old(rec);
|
||||
}
|
||||
|
||||
if (n_fields < n) {
|
||||
if (UNIV_UNLIKELY(n_fields < n)) {
|
||||
n = n_fields;
|
||||
}
|
||||
|
||||
size = n + (1 + REC_OFFS_HEADER_SIZE);
|
||||
|
||||
if (!offsets || rec_offs_get_n_alloc(offsets) < size) {
|
||||
if (UNIV_UNLIKELY(!offsets) ||
|
||||
UNIV_UNLIKELY(rec_offs_get_n_alloc(offsets) < size)) {
|
||||
if (!*heap) {
|
||||
*heap = mem_heap_create_func(size * sizeof(ulint),
|
||||
NULL, MEM_HEAP_DYNAMIC, file, line);
|
||||
|
@ -652,9 +665,17 @@ rec_set_field_extern_bits(
|
|||
to log about the change */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
rec_set_nth_field_extern_bit(rec, index, vec[i], TRUE, mtr);
|
||||
|
||||
if (UNIV_LIKELY(index->table->comp)) {
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
rec_set_nth_field_extern_bit_new(rec, index, vec[i],
|
||||
TRUE, mtr);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
rec_set_nth_field_extern_bit_old(rec, vec[i],
|
||||
TRUE, mtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -949,7 +970,7 @@ rec_convert_dtuple_to_rec(
|
|||
ut_ad(dtuple_validate(dtuple));
|
||||
ut_ad(dtuple_check_typed(dtuple));
|
||||
|
||||
if (index->table->comp) {
|
||||
if (UNIV_LIKELY(index->table->comp)) {
|
||||
rec = rec_convert_dtuple_to_rec_new(buf, index, dtuple);
|
||||
} else {
|
||||
rec = rec_convert_dtuple_to_rec_old(buf, dtuple);
|
||||
|
@ -965,7 +986,7 @@ rec_convert_dtuple_to_rec(
|
|||
offsets = rec_get_offsets(rec, index,
|
||||
offsets_, ULINT_UNDEFINED, &heap);
|
||||
ut_ad(rec_validate(rec, offsets));
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
@ -1078,17 +1099,19 @@ rec_copy_prefix_to_buf(
|
|||
for the copied prefix, or NULL */
|
||||
ulint* buf_size) /* in/out: buffer size */
|
||||
{
|
||||
byte* nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
|
||||
byte* lens = nulls - (index->n_nullable + 7) / 8;
|
||||
byte* nulls;
|
||||
byte* lens;
|
||||
dict_field_t* field;
|
||||
dtype_t* type;
|
||||
ulint i;
|
||||
ulint prefix_len = 0;
|
||||
ulint prefix_len;
|
||||
ibool is_null;
|
||||
ulint null_mask = 1;
|
||||
ulint null_mask;
|
||||
ulint status;
|
||||
|
||||
if (!index->table->comp) {
|
||||
UNIV_PREFETCH_RW(*buf);
|
||||
|
||||
if (UNIV_UNLIKELY(!index->table->comp)) {
|
||||
ut_ad(rec_validate_old(rec));
|
||||
return(rec_copy_prefix_to_buf_old(rec, n_fields,
|
||||
rec_get_field_start_offs(rec, n_fields),
|
||||
|
@ -1109,10 +1132,16 @@ rec_copy_prefix_to_buf(
|
|||
case REC_STATUS_SUPREMUM:
|
||||
/* infimum or supremum record: no sense to copy anything */
|
||||
default:
|
||||
ut_a(0);
|
||||
ut_error;
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
|
||||
lens = nulls - (index->n_nullable + 7) / 8;
|
||||
UNIV_PREFETCH_R(lens);
|
||||
prefix_len = 0;
|
||||
null_mask = 1;
|
||||
|
||||
/* read the lengths of fields 0..n */
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
field = dict_index_get_nth_field(index, i);
|
||||
|
@ -1122,8 +1151,11 @@ rec_copy_prefix_to_buf(
|
|||
/* nullable field => read the null flag */
|
||||
is_null = !!(*nulls & null_mask);
|
||||
null_mask <<= 1;
|
||||
if (null_mask == 0x100)
|
||||
nulls--, null_mask = 1;
|
||||
if (null_mask == 0x100) {
|
||||
--nulls;
|
||||
UNIV_PREFETCH_R(nulls);
|
||||
null_mask = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_null) {
|
||||
|
@ -1138,12 +1170,15 @@ rec_copy_prefix_to_buf(
|
|||
len &= 0x3f;
|
||||
len <<= 8;
|
||||
len |= *lens--;
|
||||
UNIV_PREFETCH_R(lens);
|
||||
}
|
||||
}
|
||||
prefix_len += len;
|
||||
}
|
||||
}
|
||||
|
||||
UNIV_PREFETCH_R(rec + prefix_len);
|
||||
|
||||
prefix_len += rec - (lens + 1);
|
||||
|
||||
if ((*buf == NULL) || (*buf_size < prefix_len)) {
|
||||
|
@ -1412,7 +1447,7 @@ rec_print(
|
|||
|
||||
rec_print_new(file, rec, rec_get_offsets(rec, index, offsets_,
|
||||
ULINT_UNDEFINED, &heap));
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -478,7 +478,7 @@ row_ins_cascade_calc_update_vec(
|
|||
|
||||
if (parent_ufield->field_no == parent_field_no) {
|
||||
|
||||
ulint fixed_size;
|
||||
ulint min_size;
|
||||
|
||||
/* A field in the parent index record is
|
||||
updated. Let us make the update vector
|
||||
|
@ -508,10 +508,13 @@ row_ins_cascade_calc_update_vec(
|
|||
column, do not allow the update */
|
||||
|
||||
if (ufield->new_val.len != UNIV_SQL_NULL
|
||||
&& ufield->new_val.len
|
||||
> dtype_get_len(type)) {
|
||||
&& dtype_get_at_most_n_mbchars(
|
||||
type, dtype_get_len(type),
|
||||
ufield->new_val.len,
|
||||
ufield->new_val.data)
|
||||
< ufield->new_val.len) {
|
||||
|
||||
return(ULINT_UNDEFINED);
|
||||
return(ULINT_UNDEFINED);
|
||||
}
|
||||
|
||||
/* If the parent column type has a different
|
||||
|
@ -519,29 +522,46 @@ row_ins_cascade_calc_update_vec(
|
|||
need to pad with spaces the new value of the
|
||||
child column */
|
||||
|
||||
fixed_size = dtype_get_fixed_size(type);
|
||||
min_size = dtype_get_min_size(type);
|
||||
|
||||
/* TODO: pad in UCS-2 with 0x0020.
|
||||
TODO: How does the special truncation of
|
||||
UTF-8 CHAR cols affect this? */
|
||||
|
||||
if (fixed_size
|
||||
if (min_size
|
||||
&& ufield->new_val.len != UNIV_SQL_NULL
|
||||
&& ufield->new_val.len < fixed_size) {
|
||||
&& ufield->new_val.len < min_size) {
|
||||
|
||||
char* pad_start;
|
||||
const char* pad_end;
|
||||
ufield->new_val.data =
|
||||
mem_heap_alloc(heap,
|
||||
fixed_size);
|
||||
ufield->new_val.len = fixed_size;
|
||||
ut_a(dtype_get_pad_char(type)
|
||||
!= ULINT_UNDEFINED);
|
||||
|
||||
memset(ufield->new_val.data,
|
||||
(byte)dtype_get_pad_char(type),
|
||||
fixed_size);
|
||||
min_size);
|
||||
pad_start = ufield->new_val.data
|
||||
+ ufield->new_val.len;
|
||||
pad_end = ufield->new_val.data
|
||||
+ min_size;
|
||||
ufield->new_val.len = min_size;
|
||||
ut_memcpy(ufield->new_val.data,
|
||||
parent_ufield->new_val.data,
|
||||
parent_ufield->new_val.len);
|
||||
|
||||
switch (UNIV_EXPECT(
|
||||
dtype_get_mbminlen(type), 1)) {
|
||||
default:
|
||||
ut_error;
|
||||
case 1:
|
||||
/* space=0x20 */
|
||||
memset(pad_start, 0x20,
|
||||
pad_end - pad_start);
|
||||
break;
|
||||
case 2:
|
||||
/* space=0x0020 */
|
||||
ut_a(!(ufield->new_val.len
|
||||
% 2));
|
||||
ut_a(!(min_size % 2));
|
||||
do {
|
||||
*pad_start++ = 0x00;
|
||||
*pad_start++ = 0x20;
|
||||
} while (pad_start < pad_end);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ufield->extern_storage = FALSE;
|
||||
|
@ -1255,9 +1275,11 @@ run_again:
|
|||
/* Scan index records and check if there is a matching record */
|
||||
|
||||
for (;;) {
|
||||
page_t* page;
|
||||
rec = btr_pcur_get_rec(&pcur);
|
||||
page = buf_frame_align(rec);
|
||||
|
||||
if (rec == page_get_infimum_rec(buf_frame_align(rec))) {
|
||||
if (rec == page_get_infimum_rec(page)) {
|
||||
|
||||
goto next_rec;
|
||||
}
|
||||
|
@ -1265,7 +1287,7 @@ run_again:
|
|||
offsets = rec_get_offsets(rec, check_index,
|
||||
offsets, ULINT_UNDEFINED, &heap);
|
||||
|
||||
if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
|
||||
if (rec == page_get_supremum_rec(page)) {
|
||||
|
||||
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, rec,
|
||||
check_index, offsets, thr);
|
||||
|
@ -1392,7 +1414,7 @@ do_possible_lock_wait:
|
|||
}
|
||||
|
||||
exit_func:
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(err);
|
||||
|
@ -1529,12 +1551,7 @@ row_ins_dupl_error_with_rec(
|
|||
}
|
||||
}
|
||||
|
||||
if (!rec_get_deleted_flag(rec, index->table->comp)) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
return(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
@ -1629,7 +1646,7 @@ row_ins_scan_sec_index_for_duplicate(
|
|||
break;
|
||||
}
|
||||
|
||||
if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
|
||||
if (page_rec_is_supremum(rec)) {
|
||||
|
||||
goto next_rec;
|
||||
}
|
||||
|
@ -1660,7 +1677,7 @@ next_rec:
|
|||
}
|
||||
}
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
mtr_commit(&mtr);
|
||||
|
@ -1697,7 +1714,6 @@ row_ins_duplicate_error_in_clust(
|
|||
#ifndef UNIV_HOTBACKUP
|
||||
ulint err;
|
||||
rec_t* rec;
|
||||
page_t* page;
|
||||
ulint n_unique;
|
||||
trx_t* trx = thr_get_trx(thr);
|
||||
mem_heap_t*heap = NULL;
|
||||
|
@ -1728,9 +1744,8 @@ row_ins_duplicate_error_in_clust(
|
|||
if (cursor->low_match >= n_unique) {
|
||||
|
||||
rec = btr_cur_get_rec(cursor);
|
||||
page = buf_frame_align(rec);
|
||||
|
||||
if (rec != page_get_infimum_rec(page)) {
|
||||
if (!page_rec_is_infimum(rec)) {
|
||||
offsets = rec_get_offsets(rec, cursor->index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
||||
|
@ -1772,9 +1787,8 @@ row_ins_duplicate_error_in_clust(
|
|||
if (cursor->up_match >= n_unique) {
|
||||
|
||||
rec = page_rec_get_next(btr_cur_get_rec(cursor));
|
||||
page = buf_frame_align(rec);
|
||||
|
||||
if (rec != page_get_supremum_rec(page)) {
|
||||
if (!page_rec_is_supremum(rec)) {
|
||||
offsets = rec_get_offsets(rec, cursor->index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
||||
|
@ -1842,7 +1856,6 @@ row_ins_must_modify(
|
|||
{
|
||||
ulint enough_match;
|
||||
rec_t* rec;
|
||||
page_t* page;
|
||||
|
||||
/* NOTE: (compare to the note in row_ins_duplicate_error) Because node
|
||||
pointers on upper levels of the B-tree may match more to entry than
|
||||
|
@ -1856,9 +1869,8 @@ row_ins_must_modify(
|
|||
if (cursor->low_match >= enough_match) {
|
||||
|
||||
rec = btr_cur_get_rec(cursor);
|
||||
page = buf_frame_align(rec);
|
||||
|
||||
if (rec != page_get_infimum_rec(page)) {
|
||||
if (!page_rec_is_infimum(rec)) {
|
||||
|
||||
return(ROW_INS_PREV);
|
||||
}
|
||||
|
@ -1897,7 +1909,6 @@ row_ins_index_entry_low(
|
|||
ulint modify = 0; /* remove warning */
|
||||
rec_t* insert_rec;
|
||||
rec_t* rec;
|
||||
rec_t* first_rec;
|
||||
ulint err;
|
||||
ulint n_unique;
|
||||
big_rec_t* big_rec = NULL;
|
||||
|
@ -1932,16 +1943,21 @@ row_ins_index_entry_low(
|
|||
err = DB_SUCCESS;
|
||||
|
||||
goto function_exit;
|
||||
}
|
||||
|
||||
first_rec = page_rec_get_next(page_get_infimum_rec(
|
||||
buf_frame_align(btr_cur_get_rec(&cursor))));
|
||||
|
||||
if (!page_rec_is_supremum(first_rec)) {
|
||||
ut_a(rec_get_n_fields(first_rec, index)
|
||||
== dtuple_get_n_fields(entry));
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
{
|
||||
page_t* page = btr_cur_get_page(&cursor);
|
||||
rec_t* first_rec = page_rec_get_next(
|
||||
page_get_infimum_rec(page));
|
||||
|
||||
if (UNIV_LIKELY(first_rec != page_get_supremum_rec(page))) {
|
||||
ut_a(rec_get_n_fields(first_rec, index)
|
||||
== dtuple_get_n_fields(entry));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
n_unique = dict_index_get_n_unique(index);
|
||||
|
||||
if (index->type & DICT_UNIQUE && (cursor.up_match >= n_unique
|
||||
|
@ -2048,7 +2064,7 @@ function_exit:
|
|||
mtr_commit(&mtr);
|
||||
}
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(err);
|
||||
|
|
|
@ -265,7 +265,7 @@ row_mysql_store_col_in_innobase_format(
|
|||
necessarily the length of the actual
|
||||
payload data; if the column is a true
|
||||
VARCHAR then this is irrelevant */
|
||||
ibool comp) /* in: TRUE = compact format */
|
||||
ulint comp) /* in: nonzero=compact format */
|
||||
{
|
||||
byte* ptr = mysql_data;
|
||||
dtype_t* dtype;
|
||||
|
@ -970,25 +970,6 @@ run_again:
|
|||
return((int) err);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Unlocks all table locks explicitly requested by trx (with LOCK TABLES,
|
||||
lock type LOCK_TABLE_EXP). */
|
||||
|
||||
void
|
||||
row_unlock_tables_for_mysql(
|
||||
/*========================*/
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
if (!trx->n_lock_table_exp) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
lock_release_tables_off_kernel(trx);
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Sets a table lock on the table mentioned in prebuilt. */
|
||||
|
||||
|
@ -1000,9 +981,10 @@ row_lock_table_for_mysql(
|
|||
table handle */
|
||||
dict_table_t* table, /* in: table to lock, or NULL
|
||||
if prebuilt->table should be
|
||||
locked or a
|
||||
locked as
|
||||
prebuilt->select_lock_type */
|
||||
ulint mode) /* in: lock mode of table */
|
||||
ulint mode) /* in: lock mode of table
|
||||
(ignored if table==NULL) */
|
||||
{
|
||||
trx_t* trx = prebuilt->trx;
|
||||
que_thr_t* thr;
|
||||
|
@ -1038,14 +1020,8 @@ run_again:
|
|||
if (table) {
|
||||
err = lock_table(0, table, mode, thr);
|
||||
} else {
|
||||
if (mode == LOCK_TABLE_TRANSACTIONAL) {
|
||||
err = lock_table(LOCK_TABLE_TRANSACTIONAL,
|
||||
prebuilt->table,
|
||||
prebuilt->select_lock_type, thr);
|
||||
} else {
|
||||
err = lock_table(LOCK_TABLE_EXP, prebuilt->table,
|
||||
prebuilt->select_lock_type, thr);
|
||||
}
|
||||
err = lock_table(0, prebuilt->table,
|
||||
prebuilt->select_lock_type, thr);
|
||||
}
|
||||
|
||||
trx->error_state = err;
|
||||
|
@ -3858,7 +3834,7 @@ funct_exit:
|
|||
que_graph_free(graph);
|
||||
}
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
|
@ -3893,6 +3869,7 @@ row_scan_and_check_index(
|
|||
int cmp;
|
||||
ibool contains_null;
|
||||
ulint i;
|
||||
ulint cnt;
|
||||
mem_heap_t* heap = NULL;
|
||||
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
||||
ulint* offsets = offsets_;
|
||||
|
@ -3915,11 +3892,19 @@ row_scan_and_check_index(
|
|||
dtuple_set_n_fields(prebuilt->search_tuple, 0);
|
||||
|
||||
prebuilt->select_lock_type = LOCK_NONE;
|
||||
cnt = 1000;
|
||||
|
||||
ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
|
||||
loop:
|
||||
/* Check thd->killed every 1,000 scanned rows */
|
||||
if (--cnt == 0) {
|
||||
if (trx_is_interrupted(prebuilt->trx)) {
|
||||
goto func_exit;
|
||||
}
|
||||
cnt = 1000;
|
||||
}
|
||||
if (ret != DB_SUCCESS) {
|
||||
|
||||
func_exit:
|
||||
mem_free(buf);
|
||||
mem_heap_free(heap);
|
||||
|
||||
|
@ -4046,7 +4031,7 @@ row_check_table_for_mysql(
|
|||
ut_print_name(stderr, index->name);
|
||||
putc('\n', stderr); */
|
||||
|
||||
if (!btr_validate_tree(index->tree)) {
|
||||
if (!btr_validate_tree(index->tree, prebuilt->trx)) {
|
||||
ret = DB_ERROR;
|
||||
} else {
|
||||
if (!row_scan_and_check_index(prebuilt,
|
||||
|
@ -4054,6 +4039,10 @@ row_check_table_for_mysql(
|
|||
ret = DB_ERROR;
|
||||
}
|
||||
|
||||
if (trx_is_interrupted(prebuilt->trx)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* fprintf(stderr, "%lu entries in index %s\n", n_rows,
|
||||
index->name); */
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ row_purge_remove_clust_if_poss_low(
|
|||
if (0 != ut_dulint_cmp(node->roll_ptr,
|
||||
row_get_rec_roll_ptr(rec, index, rec_get_offsets(
|
||||
rec, index, offsets_, ULINT_UNDEFINED, &heap)))) {
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
/* Someone else has modified the record later: do not remove */
|
||||
|
@ -135,7 +135,7 @@ row_purge_remove_clust_if_poss_low(
|
|||
return(TRUE);
|
||||
}
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
|
|
|
@ -535,7 +535,7 @@ row_build_row_ref_in_tuple(
|
|||
}
|
||||
|
||||
ut_ad(dtuple_check_typed(ref));
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
@ -616,7 +616,6 @@ row_search_on_row_ref(
|
|||
ulint low_match;
|
||||
rec_t* rec;
|
||||
dict_index_t* index;
|
||||
page_t* page;
|
||||
|
||||
ut_ad(dtuple_check_typed(ref));
|
||||
|
||||
|
@ -629,9 +628,8 @@ row_search_on_row_ref(
|
|||
low_match = btr_pcur_get_low_match(pcur);
|
||||
|
||||
rec = btr_pcur_get_rec(pcur);
|
||||
page = buf_frame_align(rec);
|
||||
|
||||
if (rec == page_get_infimum_rec(page)) {
|
||||
if (page_rec_is_infimum(rec)) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
@ -702,7 +700,6 @@ row_search_index_entry(
|
|||
{
|
||||
ulint n_fields;
|
||||
ulint low_match;
|
||||
page_t* page;
|
||||
rec_t* rec;
|
||||
|
||||
ut_ad(dtuple_check_typed(entry));
|
||||
|
@ -711,11 +708,10 @@ row_search_index_entry(
|
|||
low_match = btr_pcur_get_low_match(pcur);
|
||||
|
||||
rec = btr_pcur_get_rec(pcur);
|
||||
page = buf_frame_align(rec);
|
||||
|
||||
n_fields = dtuple_get_n_fields(entry);
|
||||
|
||||
if (rec == page_get_infimum_rec(page)) {
|
||||
if (page_rec_is_infimum(rec)) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ row_sel_sec_rec_is_for_clust_rec(
|
|||
}
|
||||
|
||||
func_exit:
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(is_equal);
|
||||
|
@ -630,6 +630,8 @@ row_sel_get_clust_rec(
|
|||
ulint* offsets = offsets_;
|
||||
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
|
||||
|
||||
*out_rec = NULL;
|
||||
|
||||
offsets = rec_get_offsets(rec,
|
||||
btr_pcur_get_btr_cur(&plan->pcur)->index,
|
||||
offsets, ULINT_UNDEFINED, &heap);
|
||||
|
@ -663,8 +665,6 @@ row_sel_get_clust_rec(
|
|||
clustered index record did not exist in the read view of
|
||||
trx. */
|
||||
|
||||
clust_rec = NULL;
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
|
@ -733,7 +733,6 @@ row_sel_get_clust_rec(
|
|||
if ((old_vers || rec_get_deleted_flag(rec, plan->table->comp))
|
||||
&& !row_sel_sec_rec_is_for_clust_rec(rec, plan->index,
|
||||
clust_rec, index)) {
|
||||
clust_rec = NULL;
|
||||
goto func_exit;
|
||||
}
|
||||
}
|
||||
|
@ -742,11 +741,11 @@ row_sel_get_clust_rec(
|
|||
|
||||
row_sel_fetch_columns(index, clust_rec, offsets,
|
||||
UT_LIST_GET_FIRST(plan->columns));
|
||||
func_exit:
|
||||
*out_rec = clust_rec;
|
||||
func_exit:
|
||||
err = DB_SUCCESS;
|
||||
err_exit:
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(err);
|
||||
|
@ -1066,7 +1065,7 @@ row_sel_try_search_shortcut(
|
|||
|
||||
plan->n_rows_fetched++;
|
||||
func_exit:
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(SEL_FOUND);
|
||||
|
@ -1261,7 +1260,7 @@ rec_loop:
|
|||
/* PHASE 1: Set a lock if specified */
|
||||
|
||||
if (!node->asc && cursor_just_opened
|
||||
&& (rec != page_get_supremum_rec(buf_frame_align(rec)))) {
|
||||
&& !page_rec_is_supremum(rec)) {
|
||||
|
||||
/* When we open a cursor for a descending search, we must set
|
||||
a next-key lock on the successor record: otherwise it would
|
||||
|
@ -1299,7 +1298,7 @@ rec_loop:
|
|||
}
|
||||
}
|
||||
|
||||
if (rec == page_get_infimum_rec(buf_frame_align(rec))) {
|
||||
if (page_rec_is_infimum(rec)) {
|
||||
|
||||
/* The infimum record on a page cannot be in the result set,
|
||||
and neither can a record lock be placed on it: we skip such
|
||||
|
@ -1337,7 +1336,7 @@ rec_loop:
|
|||
}
|
||||
}
|
||||
|
||||
if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
|
||||
if (page_rec_is_supremum(rec)) {
|
||||
|
||||
/* A page supremum record cannot be in the result set: skip
|
||||
it now when we have placed a possible lock on it */
|
||||
|
@ -1780,7 +1779,7 @@ lock_wait_or_error:
|
|||
ut_ad(sync_thread_levels_empty_gen(TRUE));
|
||||
|
||||
func_exit:
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(err);
|
||||
|
@ -2416,14 +2415,12 @@ row_sel_store_mysql_rec(
|
|||
mem_heap_t* extern_field_heap = NULL;
|
||||
byte* data;
|
||||
ulint len;
|
||||
byte* blob_buf;
|
||||
int pad_char;
|
||||
ulint i;
|
||||
|
||||
ut_ad(prebuilt->mysql_template);
|
||||
ut_ad(rec_offs_validate(rec, NULL, offsets));
|
||||
|
||||
if (prebuilt->blob_heap != NULL) {
|
||||
if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) {
|
||||
mem_heap_free(prebuilt->blob_heap);
|
||||
prebuilt->blob_heap = NULL;
|
||||
}
|
||||
|
@ -2435,7 +2432,8 @@ row_sel_store_mysql_rec(
|
|||
data = rec_get_nth_field(rec, offsets,
|
||||
templ->rec_field_no, &len);
|
||||
|
||||
if (rec_offs_nth_extern(offsets, templ->rec_field_no)) {
|
||||
if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
|
||||
templ->rec_field_no))) {
|
||||
|
||||
/* Copy an externally stored field to the temporary
|
||||
heap */
|
||||
|
@ -2456,7 +2454,7 @@ row_sel_store_mysql_rec(
|
|||
}
|
||||
|
||||
if (len != UNIV_SQL_NULL) {
|
||||
if (templ->type == DATA_BLOB) {
|
||||
if (UNIV_UNLIKELY(templ->type == DATA_BLOB)) {
|
||||
|
||||
ut_a(prebuilt->templ_contains_blob);
|
||||
|
||||
|
@ -2465,8 +2463,9 @@ row_sel_store_mysql_rec(
|
|||
of 1000000 bytes. Since the test takes some
|
||||
CPU time, we do not use it for small BLOBs. */
|
||||
|
||||
if (len > 2000000
|
||||
&& !ut_test_malloc(len + 1000000)) {
|
||||
if (UNIV_UNLIKELY(len > 2000000)
|
||||
&& UNIV_UNLIKELY(!ut_test_malloc(
|
||||
len + 1000000))) {
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
|
@ -2492,11 +2491,9 @@ row_sel_store_mysql_rec(
|
|||
mem_heap_create(len);
|
||||
}
|
||||
|
||||
blob_buf = mem_heap_alloc(prebuilt->blob_heap,
|
||||
len);
|
||||
ut_memcpy(blob_buf, data, len);
|
||||
|
||||
data = blob_buf;
|
||||
data = memcpy(mem_heap_alloc(
|
||||
prebuilt->blob_heap, len),
|
||||
data, len);
|
||||
}
|
||||
|
||||
row_sel_field_store_in_mysql_format(
|
||||
|
@ -2521,41 +2518,45 @@ row_sel_store_mysql_rec(
|
|||
account caused seg faults with NULL BLOB fields, and
|
||||
bug number 154 in the MySQL bug database: GROUP BY
|
||||
and DISTINCT could treat NULL values inequal. */
|
||||
int pad_char;
|
||||
|
||||
mysql_rec[templ->mysql_null_byte_offset] |=
|
||||
(byte) (templ->mysql_null_bit_mask);
|
||||
if (templ->type == DATA_VARCHAR
|
||||
|| templ->type == DATA_CHAR
|
||||
|| templ->type == DATA_BINARY
|
||||
|| templ->type == DATA_FIXBINARY
|
||||
|| templ->type == DATA_MYSQL
|
||||
|| templ->type == DATA_VARMYSQL) {
|
||||
switch (templ->type) {
|
||||
case DATA_VARCHAR:
|
||||
case DATA_CHAR:
|
||||
case DATA_BINARY:
|
||||
case DATA_FIXBINARY:
|
||||
case DATA_MYSQL:
|
||||
case DATA_VARMYSQL:
|
||||
/* MySQL pads all non-BLOB and non-TEXT
|
||||
string types with space ' ' */
|
||||
|
||||
pad_char = ' ';
|
||||
} else {
|
||||
pad_char = '\0';
|
||||
if (UNIV_UNLIKELY(templ->mbminlen == 2)) {
|
||||
/* Treat UCS2 as a special case. */
|
||||
data = mysql_rec
|
||||
+ templ->mysql_col_offset;
|
||||
len = templ->mysql_col_len;
|
||||
/* There are two UCS2 bytes per char,
|
||||
so the length has to be even. */
|
||||
ut_a(!(len & 1));
|
||||
/* Pad with 0x0020. */
|
||||
while (len) {
|
||||
*data++ = 0x00;
|
||||
*data++ = 0x20;
|
||||
len -= 2;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
pad_char = 0x20;
|
||||
break;
|
||||
default:
|
||||
pad_char = 0x00;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Handle UCS2 strings differently. */
|
||||
if (pad_char != '\0' && templ->mbminlen == 2) {
|
||||
/* There are two bytes per char, so the length
|
||||
has to be an even number. */
|
||||
ut_a(!(templ->mysql_col_len & 1));
|
||||
data = mysql_rec + templ->mysql_col_offset;
|
||||
len = templ->mysql_col_len;
|
||||
/* Pad with 0x0020. */
|
||||
while (len >= 2) {
|
||||
*data++ = 0x00;
|
||||
*data++ = 0x20;
|
||||
len -= 2;
|
||||
}
|
||||
} else {
|
||||
ut_ad(!pad_char || templ->mbminlen == 1);
|
||||
memset(mysql_rec + templ->mysql_col_offset,
|
||||
ut_ad(!pad_char || templ->mbminlen == 1);
|
||||
memset(mysql_rec + templ->mysql_col_offset,
|
||||
pad_char, templ->mysql_col_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2849,8 +2850,9 @@ row_sel_pop_cached_row_for_mysql(
|
|||
mysql_row_templ_t* templ;
|
||||
byte* cached_rec;
|
||||
ut_ad(prebuilt->n_fetch_cached > 0);
|
||||
ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
|
||||
|
||||
if (prebuilt->keep_other_fields_on_keyread)
|
||||
if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread))
|
||||
{
|
||||
/* Copy cache record field by field, don't touch fields that
|
||||
are not covered by current key */
|
||||
|
@ -2877,7 +2879,7 @@ row_sel_pop_cached_row_for_mysql(
|
|||
else
|
||||
{
|
||||
ut_memcpy(buf, prebuilt->fetch_cache[prebuilt->fetch_cache_first],
|
||||
prebuilt->mysql_row_len);
|
||||
prebuilt->mysql_prefix_len);
|
||||
}
|
||||
prebuilt->n_fetch_cached--;
|
||||
prebuilt->fetch_cache_first++;
|
||||
|
@ -2925,9 +2927,9 @@ row_sel_push_cache_row_for_mysql(
|
|||
|
||||
ut_ad(prebuilt->fetch_cache_first == 0);
|
||||
|
||||
if (!row_sel_store_mysql_rec(
|
||||
if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
|
||||
prebuilt->fetch_cache[prebuilt->n_fetch_cached],
|
||||
prebuilt, rec, offsets)) {
|
||||
prebuilt, rec, offsets))) {
|
||||
ut_error;
|
||||
}
|
||||
|
||||
|
@ -3048,11 +3050,7 @@ row_search_for_mysql(
|
|||
rec_t* index_rec;
|
||||
rec_t* clust_rec;
|
||||
rec_t* old_vers;
|
||||
ulint err = DB_SUCCESS;
|
||||
ibool moved;
|
||||
ibool cons_read_requires_clust_rec;
|
||||
ibool was_lock_wait;
|
||||
ulint shortcut;
|
||||
ulint err = DB_SUCCESS;
|
||||
ibool unique_search = FALSE;
|
||||
ibool unique_search_from_clust_index = FALSE;
|
||||
ibool mtr_has_extra_clust_latch = FALSE;
|
||||
|
@ -3062,9 +3060,9 @@ row_search_for_mysql(
|
|||
locking SELECT, and the isolation
|
||||
level is <= TRX_ISO_READ_COMMITTED,
|
||||
then this is set to FALSE */
|
||||
ibool success;
|
||||
ibool comp;
|
||||
#ifdef UNIV_SEARCH_DEBUG
|
||||
ulint cnt = 0;
|
||||
#endif /* UNIV_SEARCH_DEBUG */
|
||||
ulint next_offs;
|
||||
mtr_t mtr;
|
||||
mem_heap_t* heap = NULL;
|
||||
|
@ -3075,7 +3073,7 @@ row_search_for_mysql(
|
|||
ut_ad(index && pcur && search_tuple);
|
||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||
|
||||
if (prebuilt->table->ibd_file_missing) {
|
||||
if (UNIV_UNLIKELY(prebuilt->table->ibd_file_missing)) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB: Error:\n"
|
||||
"InnoDB: MySQL is trying to use a table handle but the .ibd file for\n"
|
||||
|
@ -3089,7 +3087,7 @@ row_search_for_mysql(
|
|||
return(DB_ERROR);
|
||||
}
|
||||
|
||||
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
|
||||
if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to free a corrupt\n"
|
||||
"InnoDB: table handle. Magic n %lu, table name ",
|
||||
|
@ -3103,7 +3101,7 @@ row_search_for_mysql(
|
|||
}
|
||||
|
||||
if (trx->n_mysql_tables_in_use == 0
|
||||
&& prebuilt->select_lock_type == LOCK_NONE) {
|
||||
&& UNIV_UNLIKELY(prebuilt->select_lock_type == LOCK_NONE)) {
|
||||
/* Note that if MySQL uses an InnoDB temp table that it
|
||||
created inside LOCK TABLES, then n_mysql_tables_in_use can
|
||||
be zero; in that case select_lock_type is set to LOCK_X in
|
||||
|
@ -3126,8 +3124,8 @@ row_search_for_mysql(
|
|||
/* PHASE 0: Release a possible s-latch we are holding on the
|
||||
adaptive hash index latch if there is someone waiting behind */
|
||||
|
||||
if (trx->has_search_latch
|
||||
&& btr_search_latch.writer != RW_LOCK_NOT_LOCKED) {
|
||||
if (UNIV_UNLIKELY(btr_search_latch.writer != RW_LOCK_NOT_LOCKED)
|
||||
&& trx->has_search_latch) {
|
||||
|
||||
/* There is an x-latch request on the adaptive hash index:
|
||||
release the s-latch to reduce starvation and wait for
|
||||
|
@ -3143,7 +3141,7 @@ row_search_for_mysql(
|
|||
/*-------------------------------------------------------------*/
|
||||
/* PHASE 1: Try to pop the row from the prefetch cache */
|
||||
|
||||
if (direction == 0) {
|
||||
if (UNIV_UNLIKELY(direction == 0)) {
|
||||
trx->op_info = "starting index read";
|
||||
|
||||
prebuilt->n_rows_fetched = 0;
|
||||
|
@ -3161,8 +3159,8 @@ row_search_for_mysql(
|
|||
prebuilt->fetch_direction = direction;
|
||||
}
|
||||
|
||||
if (direction != prebuilt->fetch_direction) {
|
||||
if (prebuilt->n_fetch_cached > 0) {
|
||||
if (UNIV_UNLIKELY(direction != prebuilt->fetch_direction)) {
|
||||
if (UNIV_UNLIKELY(prebuilt->n_fetch_cached > 0)) {
|
||||
ut_error;
|
||||
/* TODO: scrollable cursor: restore cursor to
|
||||
the place of the latest returned row,
|
||||
|
@ -3174,7 +3172,7 @@ row_search_for_mysql(
|
|||
prebuilt->n_fetch_cached = 0;
|
||||
prebuilt->fetch_cache_first = 0;
|
||||
|
||||
} else if (prebuilt->n_fetch_cached > 0) {
|
||||
} else if (UNIV_LIKELY(prebuilt->n_fetch_cached > 0)) {
|
||||
row_sel_pop_cached_row_for_mysql(buf, prebuilt);
|
||||
|
||||
prebuilt->n_rows_fetched++;
|
||||
|
@ -3234,7 +3232,8 @@ row_search_for_mysql(
|
|||
1 column. Return immediately if this is not a HANDLER
|
||||
command. */
|
||||
|
||||
if (direction != 0 && !prebuilt->used_in_HANDLER) {
|
||||
if (UNIV_UNLIKELY(direction != 0 &&
|
||||
!prebuilt->used_in_HANDLER)) {
|
||||
|
||||
err = DB_RECORD_NOT_FOUND;
|
||||
goto func_exit;
|
||||
|
@ -3252,9 +3251,9 @@ row_search_for_mysql(
|
|||
cannot use the adaptive hash index in a search in the case the row
|
||||
may be long and there may be externally stored fields */
|
||||
|
||||
if (unique_search
|
||||
if (UNIV_UNLIKELY(direction == 0)
|
||||
&& unique_search
|
||||
&& index->type & DICT_CLUSTERED
|
||||
&& direction == 0
|
||||
&& !prebuilt->templ_contains_blob
|
||||
&& !prebuilt->used_in_HANDLER
|
||||
&& (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) {
|
||||
|
@ -3286,9 +3285,9 @@ row_search_for_mysql(
|
|||
trx->has_search_latch = TRUE;
|
||||
}
|
||||
#endif
|
||||
shortcut = row_sel_try_search_shortcut_for_mysql(&rec,
|
||||
prebuilt, &offsets, &heap, &mtr);
|
||||
if (shortcut == SEL_FOUND) {
|
||||
switch (row_sel_try_search_shortcut_for_mysql(&rec,
|
||||
prebuilt, &offsets, &heap, &mtr)) {
|
||||
case SEL_FOUND:
|
||||
#ifdef UNIV_SEARCH_DEBUG
|
||||
ut_a(0 == cmp_dtuple_rec(search_tuple,
|
||||
rec, offsets));
|
||||
|
@ -3322,9 +3321,8 @@ row_search_for_mysql(
|
|||
position */
|
||||
err = DB_SUCCESS;
|
||||
goto func_exit;
|
||||
|
||||
} else if (shortcut == SEL_EXHAUSTED) {
|
||||
|
||||
case SEL_EXHAUSTED:
|
||||
mtr_commit(&mtr);
|
||||
|
||||
/* ut_print_name(stderr, index->name);
|
||||
|
@ -3367,6 +3365,7 @@ shortcut_fails_too_big_rec:
|
|||
|
||||
/* Scan the MySQL query string; check if SELECT is the first
|
||||
word there */
|
||||
ibool success;
|
||||
|
||||
dict_accept(*trx->mysql_query_str, "SELECT", &success);
|
||||
|
||||
|
@ -3382,7 +3381,7 @@ shortcut_fails_too_big_rec:
|
|||
naturally moves upward (in fetch next) in alphabetical order,
|
||||
otherwise downward */
|
||||
|
||||
if (direction == 0) {
|
||||
if (UNIV_UNLIKELY(direction == 0)) {
|
||||
if (mode == PAGE_CUR_GE || mode == PAGE_CUR_G) {
|
||||
moves_up = TRUE;
|
||||
}
|
||||
|
@ -3396,10 +3395,9 @@ shortcut_fails_too_big_rec:
|
|||
|
||||
clust_index = dict_table_get_first_index(index->table);
|
||||
|
||||
if (direction != 0) {
|
||||
moved = sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur,
|
||||
moves_up, &mtr);
|
||||
if (!moved) {
|
||||
if (UNIV_LIKELY(direction != 0)) {
|
||||
if (!sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur,
|
||||
moves_up, &mtr)) {
|
||||
goto next_rec;
|
||||
}
|
||||
|
||||
|
@ -3440,11 +3438,13 @@ shortcut_fails_too_big_rec:
|
|||
trx_assign_read_view(trx);
|
||||
prebuilt->sql_stat_start = FALSE;
|
||||
} else {
|
||||
ulint lock_mode;
|
||||
if (prebuilt->select_lock_type == LOCK_S) {
|
||||
err = lock_table(0, index->table, LOCK_IS, thr);
|
||||
lock_mode = LOCK_IS;
|
||||
} else {
|
||||
err = lock_table(0, index->table, LOCK_IX, thr);
|
||||
lock_mode = LOCK_IX;
|
||||
}
|
||||
err = lock_table(0, index->table, lock_mode, thr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
|
@ -3458,8 +3458,8 @@ rec_loop:
|
|||
/* PHASE 4: Look for matching records in a loop */
|
||||
|
||||
rec = btr_pcur_get_rec(pcur);
|
||||
comp = index->table->comp;
|
||||
ut_ad(comp == page_is_comp(buf_frame_align(rec)));
|
||||
ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
|
||||
#ifdef UNIV_SEARCH_DEBUG
|
||||
/*
|
||||
fputs("Using ", stderr);
|
||||
dict_index_name_print(stderr, index);
|
||||
|
@ -3467,7 +3467,9 @@ rec_loop:
|
|||
buf_frame_get_page_no(buf_frame_align(rec)));
|
||||
rec_print(rec);
|
||||
*/
|
||||
if (rec == page_get_infimum_rec(buf_frame_align(rec))) {
|
||||
#endif /* UNIV_SEARCH_DEBUG */
|
||||
|
||||
if (page_rec_is_infimum(rec)) {
|
||||
|
||||
/* The infimum record on a page cannot be in the result set,
|
||||
and neither can a record lock be placed on it: we skip such
|
||||
|
@ -3476,10 +3478,11 @@ rec_loop:
|
|||
goto next_rec;
|
||||
}
|
||||
|
||||
if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
|
||||
if (page_rec_is_supremum(rec)) {
|
||||
|
||||
if (prebuilt->select_lock_type != LOCK_NONE
|
||||
&& set_also_gap_locks) {
|
||||
if (set_also_gap_locks
|
||||
&& !srv_locks_unsafe_for_binlog
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
|
||||
/* Try to place a lock on the index record */
|
||||
|
||||
|
@ -3487,18 +3490,16 @@ rec_loop:
|
|||
we do not lock gaps. Supremum record is really
|
||||
a gap and therefore we do not set locks there. */
|
||||
|
||||
if (!srv_locks_unsafe_for_binlog) {
|
||||
offsets = rec_get_offsets(rec, index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
err = sel_set_rec_lock(rec, index, offsets,
|
||||
prebuilt->select_lock_type,
|
||||
LOCK_ORDINARY, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
offsets = rec_get_offsets(rec, index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
err = sel_set_rec_lock(rec, index, offsets,
|
||||
prebuilt->select_lock_type,
|
||||
LOCK_ORDINARY, thr);
|
||||
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
|
||||
}
|
||||
/* A page supremum record cannot be in the result set: skip
|
||||
it now that we have placed a possible lock on it */
|
||||
|
@ -3510,12 +3511,19 @@ rec_loop:
|
|||
/* Do sanity checks in case our cursor has bumped into page
|
||||
corruption */
|
||||
|
||||
next_offs = rec_get_next_offs(rec, comp);
|
||||
|
||||
if (next_offs >= UNIV_PAGE_SIZE
|
||||
|| next_offs <
|
||||
(ulint) (comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM)) {
|
||||
|
||||
if (page_rec_is_comp(rec)) {
|
||||
next_offs = rec_get_next_offs(rec, TRUE);
|
||||
if (UNIV_UNLIKELY(next_offs < PAGE_NEW_SUPREMUM)) {
|
||||
goto wrong_offs;
|
||||
}
|
||||
} else {
|
||||
next_offs = rec_get_next_offs(rec, FALSE);
|
||||
if (UNIV_UNLIKELY(next_offs < PAGE_OLD_SUPREMUM)) {
|
||||
goto wrong_offs;
|
||||
}
|
||||
}
|
||||
if (UNIV_UNLIKELY(next_offs >= UNIV_PAGE_SIZE - PAGE_DIR)) {
|
||||
wrong_offs:
|
||||
if (srv_force_recovery == 0 || moves_up == FALSE) {
|
||||
ut_print_timestamp(stderr);
|
||||
buf_page_print(buf_frame_align(rec));
|
||||
|
@ -3528,7 +3536,7 @@ rec_loop:
|
|||
fprintf(stderr,
|
||||
"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
|
||||
"InnoDB: ",
|
||||
(ulong) (rec - buf_frame_align(rec)),
|
||||
(ulong) ut_align_offset(rec, UNIV_PAGE_SIZE),
|
||||
(ulong) next_offs,
|
||||
(ulong) buf_frame_get_page_no(rec));
|
||||
dict_index_name_print(stderr, trx, index);
|
||||
|
@ -3546,7 +3554,7 @@ rec_loop:
|
|||
fprintf(stderr,
|
||||
"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
|
||||
"InnoDB: ",
|
||||
(ulong) (rec - buf_frame_align(rec)),
|
||||
(ulong) ut_align_offset(rec, UNIV_PAGE_SIZE),
|
||||
(ulong) next_offs,
|
||||
(ulong) buf_frame_get_page_no(rec));
|
||||
dict_index_name_print(stderr, trx, index);
|
||||
|
@ -3561,13 +3569,13 @@ rec_loop:
|
|||
|
||||
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
|
||||
|
||||
if (srv_force_recovery > 0) {
|
||||
if (UNIV_UNLIKELY(srv_force_recovery > 0)) {
|
||||
if (!rec_validate(rec, offsets)
|
||||
|| !btr_index_rec_validate(rec, index, FALSE)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
|
||||
"InnoDB: ",
|
||||
(ulong) (rec - buf_frame_align(rec)),
|
||||
(ulong) ut_align_offset(rec, UNIV_PAGE_SIZE),
|
||||
(ulong) next_offs,
|
||||
(ulong) buf_frame_get_page_no(rec));
|
||||
dict_index_name_print(stderr, trx, index);
|
||||
|
@ -3593,25 +3601,22 @@ rec_loop:
|
|||
|
||||
if (0 != cmp_dtuple_rec(search_tuple, rec, offsets)) {
|
||||
|
||||
if (prebuilt->select_lock_type != LOCK_NONE
|
||||
&& set_also_gap_locks) {
|
||||
if (set_also_gap_locks
|
||||
&& !srv_locks_unsafe_for_binlog
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
|
||||
/* Try to place a gap lock on the index
|
||||
record only if innodb_locks_unsafe_for_binlog
|
||||
option is not set */
|
||||
|
||||
if (srv_locks_unsafe_for_binlog == FALSE) {
|
||||
|
||||
err = sel_set_rec_lock(rec, index,
|
||||
offsets,
|
||||
err = sel_set_rec_lock(rec, index, offsets,
|
||||
prebuilt->select_lock_type,
|
||||
LOCK_GAP, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
btr_pcur_store_position(pcur, &mtr);
|
||||
|
@ -3627,25 +3632,22 @@ rec_loop:
|
|||
|
||||
if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec, offsets)) {
|
||||
|
||||
if (prebuilt->select_lock_type != LOCK_NONE
|
||||
&& set_also_gap_locks) {
|
||||
if (set_also_gap_locks
|
||||
&& !srv_locks_unsafe_for_binlog
|
||||
&& prebuilt->select_lock_type != LOCK_NONE) {
|
||||
|
||||
/* Try to place a gap lock on the index
|
||||
record only if innodb_locks_unsafe_for_binlog
|
||||
option is not set */
|
||||
|
||||
if (srv_locks_unsafe_for_binlog == FALSE) {
|
||||
|
||||
err = sel_set_rec_lock(rec, index,
|
||||
offsets,
|
||||
err = sel_set_rec_lock(rec, index, offsets,
|
||||
prebuilt->select_lock_type,
|
||||
LOCK_GAP, thr);
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
btr_pcur_store_position(pcur, &mtr);
|
||||
|
@ -3661,29 +3663,25 @@ rec_loop:
|
|||
/* We are ready to look at a possible new index entry in the result
|
||||
set: the cursor is now placed on a user record */
|
||||
|
||||
cons_read_requires_clust_rec = FALSE;
|
||||
|
||||
if (prebuilt->select_lock_type != LOCK_NONE) {
|
||||
/* Try to place a lock on the index record; note that delete
|
||||
marked records are a special case in a unique search. If there
|
||||
is a non-delete marked record, then it is enough to lock its
|
||||
existence with LOCK_REC_NOT_GAP. */
|
||||
|
||||
/* If innodb_locks_unsafe_for_binlog option is used,
|
||||
we lock only the record, i.e., next-key locking is
|
||||
not used. */
|
||||
|
||||
ulint lock_type;
|
||||
|
||||
if (!set_also_gap_locks
|
||||
|| (unique_search && !rec_get_deleted_flag(rec, comp))) {
|
||||
lock_type = LOCK_REC_NOT_GAP;
|
||||
|| srv_locks_unsafe_for_binlog
|
||||
|| (unique_search && !UNIV_UNLIKELY(rec_get_deleted_flag(
|
||||
rec, page_rec_is_comp(rec))))) {
|
||||
goto no_gap_lock;
|
||||
} else {
|
||||
/* If innodb_locks_unsafe_for_binlog option is used,
|
||||
we lock only the record, i.e., next-key locking is
|
||||
not used. */
|
||||
|
||||
if (srv_locks_unsafe_for_binlog) {
|
||||
lock_type = LOCK_REC_NOT_GAP;
|
||||
} else {
|
||||
lock_type = LOCK_ORDINARY;
|
||||
}
|
||||
lock_type = LOCK_ORDINARY;
|
||||
}
|
||||
|
||||
/* If we are doing a 'greater or equal than a primary key
|
||||
|
@ -3703,7 +3701,7 @@ rec_loop:
|
|||
&& dtuple_get_n_fields_cmp(search_tuple)
|
||||
== dict_index_get_n_unique(index)
|
||||
&& 0 == cmp_dtuple_rec(search_tuple, rec, offsets)) {
|
||||
|
||||
no_gap_lock:
|
||||
lock_type = LOCK_REC_NOT_GAP;
|
||||
}
|
||||
|
||||
|
@ -3731,7 +3729,7 @@ rec_loop:
|
|||
high force recovery level set, we try to avoid crashes
|
||||
by skipping this lookup */
|
||||
|
||||
if (srv_force_recovery < 5
|
||||
if (UNIV_LIKELY(srv_force_recovery < 5)
|
||||
&& !lock_clust_rec_cons_read_sees(rec, index,
|
||||
offsets, trx->read_view)) {
|
||||
|
||||
|
@ -3762,13 +3760,15 @@ rec_loop:
|
|||
have to look also into the clustered index: this
|
||||
is necessary, because we can only get the undo
|
||||
information via the clustered index record. */
|
||||
|
||||
cons_read_requires_clust_rec = TRUE;
|
||||
|
||||
/* Get the clustered index record if needed */
|
||||
index_rec = rec;
|
||||
ut_ad(index != clust_index);
|
||||
goto requires_clust_rec;
|
||||
}
|
||||
}
|
||||
|
||||
if (rec_get_deleted_flag(rec, comp)
|
||||
&& !cons_read_requires_clust_rec) {
|
||||
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, page_rec_is_comp(rec)))) {
|
||||
|
||||
/* The record is delete-marked: we can skip it if this is
|
||||
not a consistent read which might see an earlier version
|
||||
|
@ -3782,14 +3782,14 @@ rec_loop:
|
|||
|
||||
index_rec = rec;
|
||||
|
||||
/* Before and after the following "if" block, "offsets" will be
|
||||
related to "rec", which may be in "index", a secondary index or
|
||||
the clustered index ("clust_index"). However, after this "if" block,
|
||||
"rec" may be pointing to "clust_rec" of "clust_index". */
|
||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||
|
||||
if (index != clust_index && (cons_read_requires_clust_rec
|
||||
|| prebuilt->need_to_access_clustered)) {
|
||||
if (index != clust_index && prebuilt->need_to_access_clustered) {
|
||||
requires_clust_rec:
|
||||
/* Before and after this "if" block, "offsets" will be
|
||||
related to "rec", which may be in a secondary index "index" or
|
||||
the clustered index ("clust_index"). However, after this
|
||||
"if" block, "rec" may be pointing to
|
||||
"clust_rec" of "clust_index". */
|
||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||
|
||||
/* It was a non-clustered index and we must fetch also the
|
||||
clustered index record */
|
||||
|
@ -3811,7 +3811,8 @@ rec_loop:
|
|||
goto next_rec;
|
||||
}
|
||||
|
||||
if (rec_get_deleted_flag(clust_rec, comp)) {
|
||||
if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec,
|
||||
page_rec_is_comp(clust_rec)))) {
|
||||
|
||||
/* The record is delete marked: we can skip it */
|
||||
|
||||
|
@ -3832,7 +3833,8 @@ rec_loop:
|
|||
rec == clust_rec ? clust_index : index,
|
||||
offsets));
|
||||
|
||||
if (prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD
|
||||
if ((match_mode == ROW_SEL_EXACT
|
||||
|| prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD)
|
||||
&& prebuilt->select_lock_type == LOCK_NONE
|
||||
&& !prebuilt->templ_contains_blob
|
||||
&& !prebuilt->clust_index_was_generated
|
||||
|
@ -3907,7 +3909,7 @@ next_rec:
|
|||
/*-------------------------------------------------------------*/
|
||||
/* PHASE 5: Move the cursor to the next index record */
|
||||
|
||||
if (mtr_has_extra_clust_latch) {
|
||||
if (UNIV_UNLIKELY(mtr_has_extra_clust_latch)) {
|
||||
/* We must commit mtr if we are moving to the next
|
||||
non-clustered index record, because we could break the
|
||||
latching order if we would access a different clustered
|
||||
|
@ -3919,34 +3921,38 @@ next_rec:
|
|||
mtr_has_extra_clust_latch = FALSE;
|
||||
|
||||
mtr_start(&mtr);
|
||||
moved = sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur,
|
||||
moves_up, &mtr);
|
||||
if (moved) {
|
||||
if (sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur,
|
||||
moves_up, &mtr)) {
|
||||
#ifdef UNIV_SEARCH_DEBUG
|
||||
cnt++;
|
||||
#endif /* UNIV_SEARCH_DEBUG */
|
||||
|
||||
goto rec_loop;
|
||||
}
|
||||
}
|
||||
|
||||
if (moves_up) {
|
||||
moved = btr_pcur_move_to_next(pcur, &mtr);
|
||||
} else {
|
||||
moved = btr_pcur_move_to_prev(pcur, &mtr);
|
||||
}
|
||||
if (UNIV_UNLIKELY(!btr_pcur_move_to_next(pcur, &mtr))) {
|
||||
not_moved:
|
||||
btr_pcur_store_position(pcur, &mtr);
|
||||
|
||||
if (!moved) {
|
||||
btr_pcur_store_position(pcur, &mtr);
|
||||
if (match_mode != 0) {
|
||||
err = DB_RECORD_NOT_FOUND;
|
||||
} else {
|
||||
err = DB_END_OF_INDEX;
|
||||
}
|
||||
|
||||
if (match_mode != 0) {
|
||||
err = DB_RECORD_NOT_FOUND;
|
||||
} else {
|
||||
err = DB_END_OF_INDEX;
|
||||
goto normal_return;
|
||||
}
|
||||
} else {
|
||||
if (UNIV_UNLIKELY(!btr_pcur_move_to_prev(pcur, &mtr))) {
|
||||
goto not_moved;
|
||||
}
|
||||
|
||||
goto normal_return;
|
||||
}
|
||||
|
||||
#ifdef UNIV_SEARCH_DEBUG
|
||||
cnt++;
|
||||
#endif /* UNIV_SEARCH_DEBUG */
|
||||
|
||||
goto rec_loop;
|
||||
|
||||
|
@ -3964,11 +3970,10 @@ lock_wait_or_error:
|
|||
|
||||
que_thr_stop_for_mysql(thr);
|
||||
|
||||
thr->lock_state= QUE_THR_LOCK_ROW;
|
||||
was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL);
|
||||
thr->lock_state= QUE_THR_LOCK_NOLOCK;
|
||||
thr->lock_state = QUE_THR_LOCK_ROW;
|
||||
|
||||
if (was_lock_wait) {
|
||||
if (row_mysql_handle_errors(&err, trx, thr, NULL)) {
|
||||
thr->lock_state = QUE_THR_LOCK_NOLOCK;
|
||||
mtr_start(&mtr);
|
||||
|
||||
sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur,
|
||||
|
@ -3978,9 +3983,13 @@ lock_wait_or_error:
|
|||
goto rec_loop;
|
||||
}
|
||||
|
||||
thr->lock_state = QUE_THR_LOCK_NOLOCK;
|
||||
|
||||
#ifdef UNIV_SEARCH_DEBUG
|
||||
/* fputs("Using ", stderr);
|
||||
dict_index_name_print(stderr, index);
|
||||
fprintf(stderr, " cnt %lu ret value %lu err\n", cnt, err); */
|
||||
#endif /* UNIV_SEARCH_DEBUG */
|
||||
goto func_exit;
|
||||
|
||||
normal_return:
|
||||
|
@ -3995,16 +4004,18 @@ normal_return:
|
|||
err = DB_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef UNIV_SEARCH_DEBUG
|
||||
/* fputs("Using ", stderr);
|
||||
dict_index_name_print(stderr, index);
|
||||
fprintf(stderr, " cnt %lu ret value %lu err\n", cnt, err); */
|
||||
#endif /* UNIV_SEARCH_DEBUG */
|
||||
if (err == DB_SUCCESS) {
|
||||
srv_n_rows_read++;
|
||||
}
|
||||
|
||||
func_exit:
|
||||
trx->op_info = "";
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(err);
|
||||
|
|
|
@ -190,7 +190,7 @@ row_undo_search_clust_to_pcur(
|
|||
|
||||
btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(ret);
|
||||
|
|
|
@ -815,9 +815,10 @@ row_upd_build_difference_binary(
|
|||
goto skip_compare;
|
||||
}
|
||||
|
||||
extern_bit = rec_offs_nth_extern(offsets, i);
|
||||
extern_bit = upd_ext_vec_contains(ext_vec, n_ext_vec, i);
|
||||
|
||||
if (extern_bit != upd_ext_vec_contains(ext_vec, n_ext_vec, i)
|
||||
if (UNIV_UNLIKELY(extern_bit ==
|
||||
!rec_offs_nth_extern(offsets, i))
|
||||
|| !dfield_data_is_binary_equal(dfield, len, data)) {
|
||||
|
||||
upd_field = upd_get_nth_field(update, n_diff);
|
||||
|
@ -826,12 +827,8 @@ row_upd_build_difference_binary(
|
|||
|
||||
upd_field_set_field_no(upd_field, i, index, trx);
|
||||
|
||||
if (upd_ext_vec_contains(ext_vec, n_ext_vec, i)) {
|
||||
upd_field->extern_storage = TRUE;
|
||||
} else {
|
||||
upd_field->extern_storage = FALSE;
|
||||
}
|
||||
|
||||
upd_field->extern_storage = extern_bit;
|
||||
|
||||
n_diff++;
|
||||
}
|
||||
skip_compare:
|
||||
|
@ -1224,7 +1221,7 @@ row_upd_store_row(
|
|||
|
||||
node->n_ext_vec = btr_push_update_extern_fields(node->ext_vec,
|
||||
offsets, update);
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
@ -1270,7 +1267,7 @@ row_upd_sec_index_entry(
|
|||
|
||||
rec = btr_cur_get_rec(btr_cur);
|
||||
|
||||
if (!found) {
|
||||
if (UNIV_UNLIKELY(!found)) {
|
||||
fputs("InnoDB: error in sec index entry update in\n"
|
||||
"InnoDB: ", stderr);
|
||||
dict_index_name_print(stderr, trx, index);
|
||||
|
@ -1423,7 +1420,7 @@ row_upd_clust_rec_by_insert(
|
|||
index, thr, mtr);
|
||||
if (err != DB_SUCCESS) {
|
||||
mtr_commit(mtr);
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(err);
|
||||
|
@ -1549,7 +1546,7 @@ row_upd_clust_rec(
|
|||
rec_get_offsets(rec, index, offsets_,
|
||||
ULINT_UNDEFINED, &heap),
|
||||
big_rec, mtr);
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
mtr_commit(mtr);
|
||||
|
@ -1719,7 +1716,7 @@ row_upd_clust_step(
|
|||
node->index = dict_table_get_next_index(index);
|
||||
}
|
||||
exit_func:
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(err);
|
||||
|
@ -1736,7 +1733,7 @@ row_upd_clust_step(
|
|||
row_upd_eval_new_vals(node->update);
|
||||
}
|
||||
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
|
@ -2016,7 +2013,7 @@ row_upd_in_place_in_select(
|
|||
btr_pcur_get_rec(pcur), btr_cur->index, offsets_,
|
||||
ULINT_UNDEFINED, &heap),
|
||||
UT_LIST_GET_FIRST(node->columns));
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
row_upd_eval_new_vals(node->update);
|
||||
|
|
|
@ -57,11 +57,11 @@ row_vers_impl_x_locked_off_kernel(
|
|||
dtuple_t* entry = NULL; /* assignment to eliminate compiler
|
||||
warning */
|
||||
trx_t* trx;
|
||||
ibool vers_del;
|
||||
ibool rec_del;
|
||||
ulint vers_del;
|
||||
ulint rec_del;
|
||||
ulint err;
|
||||
mtr_t mtr;
|
||||
ibool comp;
|
||||
ulint comp;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
@ -121,10 +121,10 @@ row_vers_impl_x_locked_off_kernel(
|
|||
goto exit_func;
|
||||
}
|
||||
|
||||
comp = index->table->comp;
|
||||
comp = page_rec_is_comp(rec);
|
||||
ut_ad(index->table == clust_index->table);
|
||||
ut_ad(comp == page_is_comp(buf_frame_align(rec)));
|
||||
ut_ad(comp == page_is_comp(buf_frame_align(clust_rec)));
|
||||
ut_ad(!!comp == index->table->comp);
|
||||
ut_ad(!comp == !page_rec_is_comp(clust_rec));
|
||||
|
||||
/* We look up if some earlier version, which was modified by the trx_id
|
||||
transaction, of the clustered index record would require rec to be in
|
||||
|
@ -310,7 +310,7 @@ row_vers_old_has_index_entry(
|
|||
dtuple_t* row;
|
||||
dtuple_t* entry;
|
||||
ulint err;
|
||||
ibool comp;
|
||||
ulint comp;
|
||||
|
||||
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)
|
||||
|| mtr_memo_contains(mtr, buf_block_align(rec),
|
||||
|
@ -322,8 +322,8 @@ row_vers_old_has_index_entry(
|
|||
|
||||
clust_index = dict_table_get_first_index(index->table);
|
||||
|
||||
comp = index->table->comp;
|
||||
ut_ad(comp == page_is_comp(buf_frame_align(rec)));
|
||||
comp = page_rec_is_comp(rec);
|
||||
ut_ad(!index->table->comp == !comp);
|
||||
heap = mem_heap_create(1024);
|
||||
clust_offsets = rec_get_offsets(rec, clust_index, NULL,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
|
|
@ -1040,7 +1040,9 @@ innobase_start_or_create_for_mysql(void)
|
|||
|
||||
srv_start_has_been_called = TRUE;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
log_do_write = TRUE;
|
||||
#endif /* UNIV_DEBUG */
|
||||
/* yydebug = TRUE; */
|
||||
|
||||
srv_is_being_started = TRUE;
|
||||
|
@ -1554,8 +1556,9 @@ NetWare. */
|
|||
|
||||
os_thread_create(&srv_master_thread, NULL, thread_ids + 1 +
|
||||
SRV_MAX_N_IO_THREADS);
|
||||
#ifdef UNIV_DEBUG
|
||||
/* buf_debug_prints = TRUE; */
|
||||
|
||||
#endif /* UNIV_DEBUG */
|
||||
sum_of_data_file_sizes = 0;
|
||||
|
||||
for (i = 0; i < srv_n_data_files; i++) {
|
||||
|
|
|
@ -1136,8 +1136,12 @@ sync_thread_add_level(
|
|||
} else if (level == SYNC_DICT_HEADER) {
|
||||
ut_a(sync_thread_levels_g(array, SYNC_DICT_HEADER));
|
||||
} else if (level == SYNC_DICT) {
|
||||
#ifdef UNIV_DEBUG
|
||||
ut_a(buf_debug_prints
|
||||
|| sync_thread_levels_g(array, SYNC_DICT));
|
||||
#else /* UNIV_DEBUG */
|
||||
ut_a(sync_thread_levels_g(array, SYNC_DICT));
|
||||
#endif /* UNIV_DEBUG */
|
||||
} else {
|
||||
ut_error;
|
||||
}
|
||||
|
|
|
@ -1134,7 +1134,7 @@ trx_undo_report_row_operation(
|
|||
|
||||
mutex_exit(&(trx->undo_mutex));
|
||||
mtr_commit(&mtr);
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(DB_OUT_OF_FILE_SPACE);
|
||||
|
@ -1153,7 +1153,7 @@ trx_undo_report_row_operation(
|
|||
|
||||
*roll_ptr = trx_undo_build_roll_ptr(is_insert, rseg->id, page_no,
|
||||
offset);
|
||||
if (heap) {
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
return(DB_SUCCESS);
|
||||
|
|
|
@ -1237,10 +1237,12 @@ trx_finish_rollback_off_kernel(
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (lock_print_waits) {
|
||||
fprintf(stderr, "Trx %lu rollback finished\n",
|
||||
(ulong) ut_dulint_get_low(trx->id));
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
trx_commit_off_kernel(trx);
|
||||
|
||||
|
|
|
@ -158,8 +158,6 @@ trx_create(
|
|||
trx->n_tickets_to_enter_innodb = 0;
|
||||
|
||||
trx->auto_inc_lock = NULL;
|
||||
trx->n_lock_table_exp = 0;
|
||||
trx->n_lock_table_transactional = 0;
|
||||
|
||||
trx->read_view_heap = mem_heap_create(256);
|
||||
trx->read_view = NULL;
|
||||
|
@ -309,8 +307,6 @@ trx_free(
|
|||
|
||||
ut_a(!trx->has_search_latch);
|
||||
ut_a(!trx->auto_inc_lock);
|
||||
ut_a(!trx->n_lock_table_exp);
|
||||
ut_a(!trx->n_lock_table_transactional);
|
||||
|
||||
ut_a(trx->dict_operation_lock_mode == 0);
|
||||
|
||||
|
@ -1711,12 +1707,6 @@ trx_print(
|
|||
(ulong) trx->mysql_n_tables_locked);
|
||||
}
|
||||
|
||||
if (trx->n_lock_table_transactional > 0 || trx->n_lock_table_exp > 0) {
|
||||
fprintf(f, "mysql explicit table locks %lu, transactional table locks %lu\n",
|
||||
(ulong) trx->n_lock_table_exp,
|
||||
(ulong) trx->n_lock_table_transactional);
|
||||
}
|
||||
|
||||
newline = TRUE;
|
||||
|
||||
switch (trx->que_state) {
|
||||
|
|
|
@ -8,8 +8,11 @@ Created 1/30/1994 Heikki Tuuri
|
|||
|
||||
#include "univ.i"
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2)
|
||||
#else
|
||||
/* This is used to eliminate compiler warnings */
|
||||
ulint ut_dbg_zero = 0;
|
||||
#endif
|
||||
|
||||
/* If this is set to TRUE all threads will stop into the next assertion
|
||||
and assert */
|
||||
|
@ -19,21 +22,69 @@ ibool panic_shutdown = FALSE; /* This is set to TRUE when on NetWare there
|
|||
happens an InnoDB assertion failure or other
|
||||
fatal error condition that requires an
|
||||
immediate shutdown. */
|
||||
#endif
|
||||
#else /* __NETWARE__ */
|
||||
/* Null pointer used to generate memory trap */
|
||||
|
||||
ulint* ut_dbg_null_ptr = NULL;
|
||||
#endif /* __NETWARE__ */
|
||||
|
||||
const char* ut_dbg_msg_assert_fail =
|
||||
"InnoDB: Assertion failure in thread %lu in file %s line %lu\n";
|
||||
const char* ut_dbg_msg_trap =
|
||||
/*****************************************************************
|
||||
Report a failed assertion. */
|
||||
|
||||
void
|
||||
ut_dbg_assertion_failed(
|
||||
/*====================*/
|
||||
const char* expr, /* in: the failed assertion (optional) */
|
||||
const char* file, /* in: source file containing the assertion */
|
||||
ulint line) /* in: line number of the assertion */
|
||||
{
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Assertion failure in thread %lu"
|
||||
" in file %s line %lu\n",
|
||||
os_thread_pf(os_thread_get_curr_id()), file, line);
|
||||
if (expr) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Failing assertion: %s\n", expr);
|
||||
}
|
||||
|
||||
fputs(
|
||||
"InnoDB: We intentionally generate a memory trap.\n"
|
||||
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com.\n"
|
||||
"InnoDB: If you get repeated assertion failures or crashes, even\n"
|
||||
"InnoDB: immediately after the mysqld startup, there may be\n"
|
||||
"InnoDB: corruption in the InnoDB tablespace. Please refer to\n"
|
||||
"InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n"
|
||||
"InnoDB: about forcing recovery.\n";
|
||||
"InnoDB: about forcing recovery.\n", stderr);
|
||||
ut_dbg_stop_threads = TRUE;
|
||||
}
|
||||
|
||||
const char* ut_dbg_msg_stop =
|
||||
"InnoDB: Thread %lu stopped in file %s line %lu\n";
|
||||
#ifdef __NETWARE__
|
||||
/*****************************************************************
|
||||
Shut down MySQL/InnoDB after assertion failure. */
|
||||
|
||||
void
|
||||
ut_dbg_panic(void)
|
||||
/*==============*/
|
||||
{
|
||||
if (!panic_shutdown) {
|
||||
panic_shutdown = TRUE;
|
||||
innobase_shutdown_for_mysql();
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
#else /* __NETWARE__ */
|
||||
/*****************************************************************
|
||||
Stop a thread after assertion failure. */
|
||||
|
||||
void
|
||||
ut_dbg_stop_thread(
|
||||
/*===============*/
|
||||
const char* file,
|
||||
ulint line)
|
||||
{
|
||||
fprintf(stderr, "InnoDB: Thread %lu stopped in file %s line %lu\n",
|
||||
os_thread_pf(os_thread_get_curr_id()), file, line);
|
||||
os_thread_sleep(1000000000);
|
||||
}
|
||||
#endif /* __NETWARE__ */
|
||||
|
|
|
@ -410,7 +410,7 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query,
|
|||
Hack: instead of init_queue, we'll use reinit queue to be able
|
||||
to alloc queue with alloc_root()
|
||||
*/
|
||||
res=ftb->queue.max_elements=1+query_len/(min(ft_min_word_len,2)+1);
|
||||
res=ftb->queue.max_elements=1+query_len/2;
|
||||
if (!(ftb->queue.root=
|
||||
(byte **)alloc_root(&ftb->mem_root, (res+1)*sizeof(void*))))
|
||||
goto err;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
# and is part of the translation of the Bourne shell script with the
|
||||
# same name.
|
||||
|
||||
use File::Basename;
|
||||
use strict;
|
||||
|
||||
sub collect_test_cases ($);
|
||||
|
@ -39,6 +40,7 @@ sub collect_test_cases ($) {
|
|||
if ( @::opt_cases )
|
||||
{
|
||||
foreach my $tname ( @::opt_cases ) { # Run in specified order, no sort
|
||||
$tname= basename($tname, ".test");
|
||||
my $elem= "$tname.test";
|
||||
if ( ! -f "$testdir/$elem")
|
||||
{
|
||||
|
@ -161,52 +163,73 @@ sub collect_one_test_case($$$$$) {
|
|||
my $slave_sh= "$testdir/$tname-slave.sh";
|
||||
my $disabled= "$testdir/$tname.disabled";
|
||||
|
||||
$tinfo->{'master_opt'}= ["--default-time-zone=+3:00"];
|
||||
$tinfo->{'slave_opt'}= ["--default-time-zone=+3:00"];
|
||||
$tinfo->{'master_opt'}= $::glob_win32 ? ["--default-time-zone=+3:00"] : [];
|
||||
$tinfo->{'slave_opt'}= $::glob_win32 ? ["--default-time-zone=+3:00"] : [];
|
||||
$tinfo->{'slave_mi'}= [];
|
||||
|
||||
if ( -f $master_opt_file )
|
||||
{
|
||||
$tinfo->{'master_restart'}= 1; # We think so for now
|
||||
# This is a dirty hack from old mysql-test-run, we use the opt file
|
||||
# to flag other things as well, it is not a opt list at all
|
||||
$tinfo->{'master_opt'}= mtr_get_opts_from_file($master_opt_file);
|
||||
|
||||
foreach my $opt (@{$tinfo->{'master_opt'}})
|
||||
MASTER_OPT:
|
||||
{
|
||||
my $value;
|
||||
my $master_opt= mtr_get_opts_from_file($master_opt_file);
|
||||
|
||||
$value= mtr_match_prefix($opt, "--timezone=");
|
||||
|
||||
if ( defined $value )
|
||||
foreach my $opt ( @$master_opt )
|
||||
{
|
||||
$tinfo->{'timezone'}= $value;
|
||||
$tinfo->{'master_opt'}= [];
|
||||
$tinfo->{'master_restart'}= 0;
|
||||
last;
|
||||
}
|
||||
my $value;
|
||||
|
||||
$value= mtr_match_prefix($opt, "--result-file=");
|
||||
# This is a dirty hack from old mysql-test-run, we use the opt
|
||||
# file to flag other things as well, it is not a opt list at
|
||||
# all
|
||||
|
||||
if ( defined $value )
|
||||
{
|
||||
$tinfo->{'result_file'}= "r/$value.result";
|
||||
if ( $::opt_result_ext and $::opt_record or
|
||||
-f "$tinfo->{'result_file'}$::opt_result_ext")
|
||||
$value= mtr_match_prefix($opt, "--timezone=");
|
||||
if ( defined $value )
|
||||
{
|
||||
$tinfo->{'result_file'}.= $::opt_result_ext;
|
||||
$tinfo->{'timezone'}= $value;
|
||||
$tinfo->{'skip'}= 1 if $::glob_win32; # FIXME server unsets TZ
|
||||
last MASTER_OPT;
|
||||
}
|
||||
$tinfo->{'master_opt'}= [];
|
||||
$tinfo->{'master_restart'}= 0;
|
||||
last;
|
||||
|
||||
$value= mtr_match_prefix($opt, "--result-file=");
|
||||
if ( defined $value )
|
||||
{
|
||||
$tinfo->{'result_file'}= "r/$value.result";
|
||||
if ( $::opt_result_ext and $::opt_record or
|
||||
-f "$tinfo->{'result_file'}$::opt_result_ext")
|
||||
{
|
||||
$tinfo->{'result_file'}.= $::opt_result_ext;
|
||||
}
|
||||
$tinfo->{'master_restart'}= 0;
|
||||
last MASTER_OPT;
|
||||
}
|
||||
|
||||
# If we set default time zone, remove the one we have
|
||||
$value= mtr_match_prefix($opt, "--default-time-zone=");
|
||||
if ( defined $value )
|
||||
{
|
||||
$tinfo->{'master_opt'}= [];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Ok, this was a real option list, add it
|
||||
push(@{$tinfo->{'master_opt'}}, @$master_opt);
|
||||
}
|
||||
}
|
||||
|
||||
if ( -f $slave_opt_file )
|
||||
{
|
||||
$tinfo->{'slave_opt'}= mtr_get_opts_from_file($slave_opt_file);
|
||||
$tinfo->{'slave_restart'}= 1;
|
||||
my $slave_opt= mtr_get_opts_from_file($slave_opt_file);
|
||||
|
||||
foreach my $opt ( @$slave_opt )
|
||||
{
|
||||
# If we set default time zone, remove the one we have
|
||||
my $value= mtr_match_prefix($opt, "--default-time-zone=");
|
||||
$tinfo->{'slave_opt'}= [] if defined $value;
|
||||
}
|
||||
push(@{$tinfo->{'slave_opt'}}, @$slave_opt);
|
||||
}
|
||||
|
||||
if ( -f $slave_mi_file )
|
||||
|
|
|
@ -9,6 +9,9 @@ use strict;
|
|||
sub mtr_full_hostname ();
|
||||
sub mtr_init_args ($);
|
||||
sub mtr_add_arg ($$);
|
||||
sub mtr_path_exists(@);
|
||||
sub mtr_script_exists(@);
|
||||
sub mtr_exe_exists(@);
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
|
@ -47,4 +50,53 @@ sub mtr_add_arg ($$) {
|
|||
push(@$args, sprintf($format, @fargs));
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
|
||||
sub mtr_path_exists (@) {
|
||||
foreach my $path ( @_ )
|
||||
{
|
||||
return $path if -e $path;
|
||||
}
|
||||
if ( @_ == 1 )
|
||||
{
|
||||
mtr_error("Could not find $_[0]");
|
||||
}
|
||||
else
|
||||
{
|
||||
mtr_error("Could not find any of " . join(" ", @_));
|
||||
}
|
||||
}
|
||||
|
||||
sub mtr_script_exists (@) {
|
||||
foreach my $path ( @_ )
|
||||
{
|
||||
return $path if -x $path;
|
||||
}
|
||||
if ( @_ == 1 )
|
||||
{
|
||||
mtr_error("Could not find $_[0]");
|
||||
}
|
||||
else
|
||||
{
|
||||
mtr_error("Could not find any of " . join(" ", @_));
|
||||
}
|
||||
}
|
||||
|
||||
sub mtr_exe_exists (@) {
|
||||
foreach my $path ( @_ )
|
||||
{
|
||||
$path.= ".exe" if $::opt_win32;
|
||||
return $path if -x $path;
|
||||
}
|
||||
if ( @_ == 1 )
|
||||
{
|
||||
mtr_error("Could not find $_[0]");
|
||||
}
|
||||
else
|
||||
{
|
||||
mtr_error("Could not find any of " . join(" ", @_));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
|
|
@ -38,6 +38,13 @@ sub mtr_show_failed_diff ($) {
|
|||
my $result_file= "r/$tname.result";
|
||||
my $eval_file= "r/$tname.eval";
|
||||
|
||||
if ( $::opt_suite ne "main" )
|
||||
{
|
||||
$reject_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$reject_file";
|
||||
$result_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$result_file";
|
||||
$eval_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$eval_file";
|
||||
}
|
||||
|
||||
if ( -f $eval_file )
|
||||
{
|
||||
$result_file= $eval_file;
|
||||
|
|
|
@ -264,6 +264,7 @@ our $opt_warnings;
|
|||
|
||||
our $opt_udiff;
|
||||
|
||||
our $opt_skip_ndbcluster;
|
||||
our $opt_with_ndbcluster;
|
||||
our $opt_with_openssl;
|
||||
|
||||
|
@ -463,6 +464,7 @@ sub command_line_setup () {
|
|||
# Control what test suites or cases to run
|
||||
'force' => \$opt_force,
|
||||
'with-ndbcluster' => \$opt_with_ndbcluster,
|
||||
'skip-ndbcluster|skip-ndb' => \$opt_skip_ndbcluster,
|
||||
'do-test=s' => \$opt_do_test,
|
||||
'suite=s' => \$opt_suite,
|
||||
'skip-rpl' => \$opt_skip_rpl,
|
||||
|
@ -662,6 +664,11 @@ sub command_line_setup () {
|
|||
$opt_ndbconnectstring= "host=localhost:$opt_ndbcluster_port";
|
||||
}
|
||||
|
||||
if ( $opt_skip_ndbcluster )
|
||||
{
|
||||
$opt_with_ndbcluster= 0;
|
||||
}
|
||||
|
||||
# FIXME
|
||||
|
||||
#if ( $opt_valgrind or $opt_valgrind_all )
|
||||
|
@ -763,146 +770,83 @@ sub executable_setup () {
|
|||
|
||||
if ( $opt_source_dist )
|
||||
{
|
||||
if ( $glob_win32 )
|
||||
{
|
||||
$path_client_bindir= mtr_path_exists("$glob_basedir/client_release");
|
||||
$exe_mysqld= mtr_exe_exists ("$path_client_bindir/mysqld-nt");
|
||||
$path_language= mtr_path_exists("$glob_basedir/share/english/");
|
||||
$path_charsetsdir= mtr_path_exists("$glob_basedir/share/charsets");
|
||||
}
|
||||
else
|
||||
{
|
||||
$path_client_bindir= mtr_path_exists("$glob_basedir/client");
|
||||
$exe_mysqld= mtr_exe_exists ("$glob_basedir/sql/mysqld");
|
||||
$path_language= mtr_path_exists("$glob_basedir/sql/share/english/");
|
||||
$path_charsetsdir= mtr_path_exists("$glob_basedir/sql/share/charsets");
|
||||
}
|
||||
|
||||
if ( $glob_use_embedded_server )
|
||||
{
|
||||
if ( -f "$glob_basedir/libmysqld/examples/mysqltest" )
|
||||
{
|
||||
$exe_mysqltest= "$glob_basedir/libmysqld/examples/mysqltest";
|
||||
}
|
||||
else
|
||||
{
|
||||
mtr_error("Can't find embedded server 'mysqltest'");
|
||||
}
|
||||
my $path_examples= "$glob_basedir/libmysqld/examples";
|
||||
$exe_mysqltest= mtr_exe_exists("$path_examples/mysqltest");
|
||||
$exe_mysql_client_test=
|
||||
"$glob_basedir/libmysqld/examples/mysql_client_test_embedded";
|
||||
mtr_exe_exists("$path_examples/mysql_client_test_embedded");
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( -f "$glob_basedir/client/.libs/lt-mysqltest" )
|
||||
{
|
||||
$exe_mysqltest= "$glob_basedir/client/.libs/lt-mysqltest";
|
||||
}
|
||||
elsif ( -f "$glob_basedir/client/.libs/mysqltest" )
|
||||
{
|
||||
$exe_mysqltest= "$glob_basedir/client/.libs/mysqltest";
|
||||
}
|
||||
else
|
||||
{
|
||||
$exe_mysqltest= "$glob_basedir/client/mysqltest";
|
||||
}
|
||||
$exe_mysqltest= mtr_exe_exists("$glob_basedir/client/mysqltest");
|
||||
$exe_mysql_client_test=
|
||||
"$glob_basedir/tests/mysql_client_test";
|
||||
mtr_exe_exists("$glob_basedir/tests/mysql_client_test");
|
||||
}
|
||||
if ( -f "$glob_basedir/client/.libs/mysqldump" )
|
||||
{
|
||||
$exe_mysqldump= "$glob_basedir/client/.libs/mysqldump";
|
||||
}
|
||||
else
|
||||
{
|
||||
$exe_mysqldump= "$glob_basedir/client/mysqldump";
|
||||
}
|
||||
if ( -f "$glob_basedir/client/.libs/mysqlshow" )
|
||||
{
|
||||
$exe_mysqlshow= "$glob_basedir/client/.libs/mysqlshow";
|
||||
}
|
||||
else
|
||||
{
|
||||
$exe_mysqlshow= "$glob_basedir/client/mysqlshow";
|
||||
}
|
||||
if ( -f "$glob_basedir/client/.libs/mysqlbinlog" )
|
||||
{
|
||||
$exe_mysqlbinlog= "$glob_basedir/client/.libs/mysqlbinlog";
|
||||
}
|
||||
else
|
||||
{
|
||||
$exe_mysqlbinlog= "$glob_basedir/client/mysqlbinlog";
|
||||
}
|
||||
|
||||
$path_client_bindir= "$glob_basedir/client";
|
||||
$exe_mysqld= "$glob_basedir/sql/mysqld";
|
||||
$exe_mysqladmin= "$path_client_bindir/mysqladmin";
|
||||
$exe_mysql= "$path_client_bindir/mysql";
|
||||
$exe_mysql_fix_system_tables= "$glob_basedir/scripts/mysql_fix_privilege_tables";
|
||||
$path_language= "$glob_basedir/sql/share/english/";
|
||||
$path_charsetsdir= "$glob_basedir/sql/share/charsets";
|
||||
|
||||
$path_ndb_tools_dir= "$glob_basedir/ndb/tools";
|
||||
$exe_ndb_mgm= "$glob_basedir/ndb/src/mgmclient/ndb_mgm";
|
||||
$exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump");
|
||||
$exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow");
|
||||
$exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
|
||||
$exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin");
|
||||
$exe_mysql= mtr_exe_exists("$path_client_bindir/mysql");
|
||||
$exe_mysql_fix_system_tables=
|
||||
mtr_script_exists("$glob_basedir/scripts/mysql_fix_privilege_tables");
|
||||
$path_ndb_tools_dir= mtr_path_exists("$glob_basedir/ndb/tools");
|
||||
$exe_ndb_mgm= "$glob_basedir/ndb/src/mgmclient/ndb_mgm";
|
||||
}
|
||||
else
|
||||
{
|
||||
my $path_tests_bindir= "$glob_basedir/tests";
|
||||
$path_client_bindir= mtr_path_exists("$glob_basedir/bin");
|
||||
$exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest");
|
||||
$exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump");
|
||||
$exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow");
|
||||
$exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
|
||||
$exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin");
|
||||
$exe_mysql= mtr_exe_exists("$path_client_bindir/mysql");
|
||||
$exe_mysql_fix_system_tables=
|
||||
mtr_script_exists("$path_client_bindir/mysql_fix_privilege_tables");
|
||||
|
||||
$path_client_bindir= "$glob_basedir/bin";
|
||||
$exe_mysqltest= "$path_client_bindir/mysqltest";
|
||||
$exe_mysqldump= "$path_client_bindir/mysqldump";
|
||||
$exe_mysqlshow= "$path_client_bindir/mysqlshow";
|
||||
$exe_mysqlbinlog= "$path_client_bindir/mysqlbinlog";
|
||||
$exe_mysqladmin= "$path_client_bindir/mysqladmin";
|
||||
$exe_mysql= "$path_client_bindir/mysql";
|
||||
$exe_mysql_fix_system_tables= "$path_client_bindir/mysql_fix_privilege_tables";
|
||||
|
||||
if ( -d "$glob_basedir/share/mysql/english" )
|
||||
{
|
||||
$path_language ="$glob_basedir/share/mysql/english/";
|
||||
$path_charsetsdir ="$glob_basedir/share/mysql/charsets";
|
||||
}
|
||||
else
|
||||
{
|
||||
$path_language ="$glob_basedir/share/english/";
|
||||
$path_charsetsdir ="$glob_basedir/share/charsets";
|
||||
}
|
||||
|
||||
if ( -x "$glob_basedir/libexec/mysqld" )
|
||||
{
|
||||
$exe_mysqld= "$glob_basedir/libexec/mysqld";
|
||||
}
|
||||
else
|
||||
{
|
||||
$exe_mysqld= "$glob_basedir/bin/mysqld";
|
||||
}
|
||||
$path_language= mtr_path_exists("$glob_basedir/share/mysql/english/",
|
||||
"$glob_basedir/share/english/");
|
||||
$path_charsetsdir= mtr_path_exists("$glob_basedir/share/mysql/charsets",
|
||||
"$glob_basedir/share/charsets");
|
||||
$exe_mysqld= mtr_exe_exists ("$glob_basedir/libexec/mysqld",
|
||||
"$glob_basedir/bin/mysqld");
|
||||
|
||||
if ( $glob_use_embedded_server )
|
||||
{
|
||||
if ( -f "$path_client_bindir/mysqltest_embedded" )
|
||||
{
|
||||
# FIXME valgrind?
|
||||
$exe_mysqltest="$path_client_bindir/mysqltest_embedded";
|
||||
}
|
||||
else
|
||||
{
|
||||
mtr_error("Cannot find embedded server 'mysqltest_embedded'");
|
||||
}
|
||||
if ( -d "$path_tests_bindir/mysql_client_test_embedded" )
|
||||
{
|
||||
$exe_mysql_client_test=
|
||||
"$path_tests_bindir/mysql_client_test_embedded";
|
||||
}
|
||||
else
|
||||
{
|
||||
$exe_mysql_client_test=
|
||||
"$path_client_bindir/mysql_client_test_embedded";
|
||||
}
|
||||
$exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest_embedded");
|
||||
$exe_mysql_client_test=
|
||||
mtr_exe_exists("$glob_basedir/tests/mysql_client_test_embedded",
|
||||
"$path_client_bindir/mysql_client_test_embedded");
|
||||
}
|
||||
else
|
||||
{
|
||||
$exe_mysqltest="$path_client_bindir/mysqltest";
|
||||
$exe_mysql_client_test="$path_client_bindir/mysql_client_test";
|
||||
$exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest");
|
||||
$exe_mysql_client_test=
|
||||
mtr_exe_exists("$path_client_bindir/mysql_client_test");
|
||||
}
|
||||
|
||||
$path_ndb_tools_dir= "$glob_basedir/bin";
|
||||
$exe_ndb_mgm= "$glob_basedir/bin/ndb_mgm";
|
||||
}
|
||||
|
||||
if ( ! $exe_master_mysqld )
|
||||
{
|
||||
$exe_master_mysqld= $exe_mysqld;
|
||||
}
|
||||
|
||||
if ( ! $exe_slave_mysqld )
|
||||
{
|
||||
$exe_slave_mysqld= $exe_mysqld;
|
||||
}
|
||||
$exe_master_mysqld= $exe_master_mysqld || $exe_mysqld;
|
||||
$exe_slave_mysqld= $exe_slave_mysqld || $exe_mysqld;
|
||||
|
||||
$path_ndb_backup_dir=
|
||||
"$opt_vardir/ndbcluster-$opt_ndbcluster_port";
|
||||
|
@ -921,15 +865,19 @@ sub executable_setup () {
|
|||
sub environment_setup () {
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Set LD_LIBRARY_PATH if we are using shared libraries
|
||||
# We might not use a standard installation directory, like /usr/lib.
|
||||
# Set LD_LIBRARY_PATH to make sure we find our installed libraries.
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
$ENV{'LD_LIBRARY_PATH'}=
|
||||
"$glob_basedir/lib:$glob_basedir/libmysql/.libs" .
|
||||
($ENV{'LD_LIBRARY_PATH'} ? ":$ENV{'LD_LIBRARY_PATH'}" : "");
|
||||
$ENV{'DYLD_LIBRARY_PATH'}=
|
||||
"$glob_basedir/lib:$glob_basedir/libmysql/.libs" .
|
||||
($ENV{'DYLD_LIBRARY_PATH'} ? ":$ENV{'DYLD_LIBRARY_PATH'}" : "");
|
||||
unless ( $opt_source_dist )
|
||||
{
|
||||
$ENV{'LD_LIBRARY_PATH'}=
|
||||
"$glob_basedir/lib" .
|
||||
($ENV{'LD_LIBRARY_PATH'} ? ":$ENV{'LD_LIBRARY_PATH'}" : "");
|
||||
$ENV{'DYLD_LIBRARY_PATH'}=
|
||||
"$glob_basedir/lib" .
|
||||
($ENV{'DYLD_LIBRARY_PATH'} ? ":$ENV{'DYLD_LIBRARY_PATH'}" : "");
|
||||
}
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Also command lines in .opt files may contain env vars
|
||||
|
@ -1020,11 +968,6 @@ sub kill_and_cleanup () {
|
|||
|
||||
mtr_report("Removing Stale Files");
|
||||
|
||||
if ( -l $opt_vardir and ! unlink($opt_vardir) )
|
||||
{
|
||||
mtr_error("Can't remove soft link \"$opt_vardir\"");
|
||||
}
|
||||
|
||||
rmtree("$opt_vardir/log");
|
||||
rmtree("$opt_vardir/ndbcluster-$opt_ndbcluster_port");
|
||||
rmtree("$opt_vardir/run");
|
||||
|
@ -1719,6 +1662,11 @@ sub mysqld_arguments ($$$$$) {
|
|||
mtr_add_arg($args, "%s--local-infile", $prefix);
|
||||
mtr_add_arg($args, "%s--datadir=%s", $prefix,
|
||||
$master->[$idx]->{'path_myddir'});
|
||||
|
||||
if ( $opt_skip_ndbcluster )
|
||||
{
|
||||
mtr_add_arg($args, "%s--skip-ndbcluster", $prefix);
|
||||
}
|
||||
}
|
||||
|
||||
if ( $type eq 'slave' )
|
||||
|
@ -1860,19 +1808,11 @@ sub mysqld_arguments ($$$$$) {
|
|||
mtr_add_arg($args, "%s--rpl-recovery-rank=1", $prefix);
|
||||
mtr_add_arg($args, "%s--init-rpl-role=master", $prefix);
|
||||
}
|
||||
else
|
||||
elsif ( $type eq 'master' )
|
||||
{
|
||||
mtr_add_arg($args, "%s--exit-info=256", $prefix);
|
||||
mtr_add_arg($args, "%s--open-files-limit=1024", $prefix);
|
||||
|
||||
if ( $type eq 'master' )
|
||||
{
|
||||
mtr_add_arg($args, "%s--log=%s", $prefix, $master->[0]->{'path_mylog'});
|
||||
}
|
||||
if ( $type eq 'slave' )
|
||||
{
|
||||
mtr_add_arg($args, "%s--log=%s", $prefix, $slave->[0]->{'path_mylog'});
|
||||
}
|
||||
mtr_add_arg($args, "%s--log=%s", $prefix, $master->[0]->{'path_mylog'});
|
||||
}
|
||||
|
||||
return $args;
|
||||
|
|
|
@ -339,7 +339,7 @@ insert into t2 values (3, 1, 'xxbuz');
|
|||
select * from t1 join t2 using(`t1_id`) where match (t1.name, t2.name) against('xxfoo' in boolean mode);
|
||||
t1_id name t2_id t1_id name
|
||||
1 data1 1 1 xxfoo
|
||||
select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode);
|
||||
select * from t2 where match name against ('*a*b*c*d*e*f*' in boolean mode);
|
||||
t2_id t1_id name
|
||||
drop table t1,t2;
|
||||
create table t1 (a text, fulltext key (a));
|
||||
|
|
|
@ -753,3 +753,12 @@ SELECT DISTINCT a, b FROM t1 GROUP BY 'const';
|
|||
a b
|
||||
1 2
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (id INT, dt DATETIME);
|
||||
INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
|
||||
INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
|
||||
INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
|
||||
INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
|
||||
SELECT dt DIV 1 AS f, id FROM t1 GROUP BY f;
|
||||
f id
|
||||
20050501123000 1
|
||||
DROP TABLE t1;
|
||||
|
|
|
@ -1779,7 +1779,7 @@ Variable_name Value
|
|||
innodb_sync_spin_loops 20
|
||||
show variables like "innodb_thread_concurrency";
|
||||
Variable_name Value
|
||||
innodb_thread_concurrency 8
|
||||
innodb_thread_concurrency 20
|
||||
set global innodb_thread_concurrency=1000;
|
||||
show variables like "innodb_thread_concurrency";
|
||||
Variable_name Value
|
||||
|
|
|
@ -253,9 +253,9 @@ insert into t2 values (3, 1, 'xxbuz');
|
|||
select * from t1 join t2 using(`t1_id`) where match (t1.name, t2.name) against('xxfoo' in boolean mode);
|
||||
|
||||
#
|
||||
# bug with many short (< ft_min_word_len) words in boolean search
|
||||
# Bug #7858: bug with many short (< ft_min_word_len) words in boolean search
|
||||
#
|
||||
select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode);
|
||||
select * from t2 where match name against ('*a*b*c*d*e*f*' in boolean mode);
|
||||
drop table t1,t2;
|
||||
|
||||
#
|
||||
|
|
|
@ -567,7 +567,7 @@ show warnings;
|
|||
drop table t1, t2;
|
||||
|
||||
#
|
||||
# Test for bug #8614: GROUP BY 'const with DISTINCT
|
||||
# Test for bug #8614: GROUP BY 'const' with DISTINCT
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (a int, b int);
|
||||
|
@ -576,3 +576,16 @@ SELECT a, b FROM t1 GROUP BY 'const';
|
|||
SELECT DISTINCT a, b FROM t1 GROUP BY 'const';
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Test for bug #11385: GROUP BY for datetime converted to decimals
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (id INT, dt DATETIME);
|
||||
INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
|
||||
INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
|
||||
INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
|
||||
INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' );
|
||||
SELECT dt DIV 1 AS f, id FROM t1 GROUP BY f;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
|
|
@ -111,8 +111,8 @@ DEFS = -DMYSQL_SERVER \
|
|||
-DDATADIR="\"$(MYSQLDATAdir)\"" \
|
||||
-DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
|
||||
@DEFS@
|
||||
# Don't put lex_hash.h in BUILT_SOURCES as this will give infinite recursion
|
||||
BUILT_SOURCES = sql_yacc.cc sql_yacc.h
|
||||
|
||||
BUILT_SOURCES = sql_yacc.cc sql_yacc.h lex_hash.h
|
||||
EXTRA_DIST = udf_example.cc $(BUILT_SOURCES)
|
||||
DISTCLEANFILES = lex_hash.h
|
||||
AM_YFLAGS = -d
|
||||
|
@ -131,9 +131,6 @@ link_sources: mysql_tzinfo_to_sql.cc
|
|||
rm -f my_time.c
|
||||
@LN_CP_F@ ../sql-common/my_time.c my_time.c
|
||||
|
||||
gen_lex_hash.o: gen_lex_hash.cc lex.h
|
||||
$(CXXCOMPILE) -c $(INCLUDES) $<
|
||||
|
||||
mysql_tzinfo_to_sql.o: $(mysql_tzinfo_to_sql_SOURCES)
|
||||
$(CXXCOMPILE) -c $(INCLUDES) -DTZINFO2SQL $<
|
||||
|
||||
|
@ -148,13 +145,9 @@ sql_yacc.o: sql_yacc.cc sql_yacc.h $(HEADERS)
|
|||
@echo "If it fails, re-run configure with --with-low-memory"
|
||||
$(CXXCOMPILE) $(LM_CFLAGS) -c $<
|
||||
|
||||
lex_hash.h: lex.h gen_lex_hash.cc sql_yacc.h
|
||||
$(MAKE) gen_lex_hash$(EXEEXT)
|
||||
lex_hash.h: gen_lex_hash$(EXEEXT)
|
||||
./gen_lex_hash$(EXEEXT) > $@
|
||||
|
||||
# Hack to ensure that lex_hash.h is built early
|
||||
sql_lex.o: lex_hash.h
|
||||
|
||||
# For testing of udf_example.so; Works on platforms with gcc
|
||||
# (This is not part of our build process but only provided as an example)
|
||||
udf_example.so: udf_example.cc
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#endif
|
||||
|
||||
#define NOT_FIXED_DEC 31
|
||||
#define DATETIME_DEC 6
|
||||
|
||||
class Send_field;
|
||||
class Protocol;
|
||||
|
@ -941,6 +942,7 @@ public:
|
|||
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; }
|
||||
#endif
|
||||
enum Item_result cmp_type () const { return INT_RESULT; }
|
||||
uint decimals() const { return DATETIME_DEC; }
|
||||
int store(const char *to,uint length,CHARSET_INFO *charset);
|
||||
int store(double nr);
|
||||
int store(longlong nr);
|
||||
|
|
|
@ -146,8 +146,7 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group,
|
|||
innobase_buffer_pool_awe_mem_mb,
|
||||
innobase_buffer_pool_size, innobase_additional_mem_pool_size,
|
||||
innobase_file_io_threads, innobase_lock_wait_timeout,
|
||||
innobase_thread_concurrency, innobase_force_recovery,
|
||||
innobase_open_files;
|
||||
innobase_force_recovery, innobase_open_files;
|
||||
|
||||
/* The default values for the following char* start-up parameters
|
||||
are determined in innobase_init below: */
|
||||
|
@ -327,7 +326,7 @@ innodb_srv_conc_enter_innodb(
|
|||
/*=========================*/
|
||||
trx_t* trx) /* in: transaction handle */
|
||||
{
|
||||
if (srv_thread_concurrency >= 500) {
|
||||
if (UNIV_LIKELY(srv_thread_concurrency >= 20)) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -344,7 +343,7 @@ innodb_srv_conc_exit_innodb(
|
|||
/*========================*/
|
||||
trx_t* trx) /* in: transaction handle */
|
||||
{
|
||||
if (srv_thread_concurrency >= 500) {
|
||||
if (UNIV_LIKELY(srv_thread_concurrency >= 20)) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1044,6 +1043,18 @@ mysql_get_identifier_quote_char(
|
|||
name, (int) namelen));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Determines if the currently running transaction has been interrupted. */
|
||||
extern "C"
|
||||
ibool
|
||||
trx_is_interrupted(
|
||||
/*===============*/
|
||||
/* out: TRUE if interrupted */
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
return(trx && trx->mysql_thd && ((THD*) trx->mysql_thd)->killed);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Obtain a pointer to the MySQL THD object, as in current_thd(). This
|
||||
definition must match the one in sql/ha_innodb.cc! */
|
||||
|
@ -1302,8 +1313,8 @@ innobase_init(void)
|
|||
|
||||
data_mysql_default_charset_coll = (ulint)default_charset_info->number;
|
||||
|
||||
data_mysql_latin1_swedish_charset_coll =
|
||||
(ulint)my_charset_latin1.number;
|
||||
ut_a(DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL ==
|
||||
my_charset_latin1.number);
|
||||
|
||||
/* Store the latin1_swedish_ci character ordering table to InnoDB. For
|
||||
non-latin1_swedish_ci charsets we use the MySQL comparison functions,
|
||||
|
@ -2867,6 +2878,8 @@ build_template(
|
|||
ibool fetch_all_in_key = FALSE;
|
||||
ibool fetch_primary_key_cols = FALSE;
|
||||
ulint i;
|
||||
/* byte offset of the end of last requested column */
|
||||
ulint mysql_prefix_len = 0;
|
||||
|
||||
if (prebuilt->select_lock_type == LOCK_X) {
|
||||
/* We always retrieve the whole clustered index record if we
|
||||
|
@ -2987,6 +3000,11 @@ build_template(
|
|||
get_field_offset(table, field);
|
||||
|
||||
templ->mysql_col_len = (ulint) field->pack_length();
|
||||
if (mysql_prefix_len < templ->mysql_col_offset
|
||||
+ templ->mysql_col_len) {
|
||||
mysql_prefix_len = templ->mysql_col_offset
|
||||
+ templ->mysql_col_len;
|
||||
}
|
||||
templ->type = index->table->cols[i].type.mtype;
|
||||
templ->mysql_type = (ulint)field->type();
|
||||
|
||||
|
@ -3009,6 +3027,7 @@ skip_field:
|
|||
}
|
||||
|
||||
prebuilt->n_template = n_requested_fields;
|
||||
prebuilt->mysql_prefix_len = mysql_prefix_len;
|
||||
|
||||
if (index != clust_index && prebuilt->need_to_access_clustered) {
|
||||
/* Change rec_field_no's to correspond to the clustered index
|
||||
|
@ -3080,7 +3099,7 @@ ha_innobase::write_row(
|
|||
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
|
||||
|
||||
dict_table_t* src_table;
|
||||
ibool mode;
|
||||
ulint mode;
|
||||
|
||||
num_write_row = 0;
|
||||
|
||||
|
@ -5991,7 +6010,7 @@ ha_innobase::external_lock(
|
|||
|
||||
ulint error;
|
||||
error = row_lock_table_for_mysql(prebuilt,
|
||||
NULL, LOCK_TABLE_EXP);
|
||||
NULL, 0);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
error = convert_error_code_to_mysql(
|
||||
|
@ -6011,9 +6030,6 @@ ha_innobase::external_lock(
|
|||
trx->n_mysql_tables_in_use--;
|
||||
prebuilt->mysql_has_locked = FALSE;
|
||||
|
||||
if (trx->n_lock_table_exp) {
|
||||
row_unlock_tables_for_mysql(trx);
|
||||
}
|
||||
|
||||
/* If the MySQL lock count drops to zero we know that the current SQL
|
||||
statement has ended */
|
||||
|
@ -6055,7 +6071,7 @@ user issued query LOCK TABLES..WHERE ENGINE = InnoDB. */
|
|||
int
|
||||
ha_innobase::transactional_table_lock(
|
||||
/*==================================*/
|
||||
/* out: 0 */
|
||||
/* out: error code */
|
||||
THD* thd, /* in: handle to the user thread */
|
||||
int lock_type) /* in: lock type */
|
||||
{
|
||||
|
@ -6119,8 +6135,7 @@ ha_innobase::transactional_table_lock(
|
|||
if (thd->in_lock_tables && thd->variables.innodb_table_locks) {
|
||||
ulint error = DB_SUCCESS;
|
||||
|
||||
error = row_lock_table_for_mysql(prebuilt,NULL,
|
||||
LOCK_TABLE_TRANSACTIONAL);
|
||||
error = row_lock_table_for_mysql(prebuilt, NULL, 0);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
error = convert_error_code_to_mysql((int) error, user_thd);
|
||||
|
|
|
@ -218,7 +218,7 @@ extern long innobase_log_file_size, innobase_log_buffer_size;
|
|||
extern long innobase_buffer_pool_size, innobase_additional_mem_pool_size;
|
||||
extern long innobase_buffer_pool_awe_mem_mb;
|
||||
extern long innobase_file_io_threads, innobase_lock_wait_timeout;
|
||||
extern long innobase_force_recovery, innobase_thread_concurrency;
|
||||
extern long innobase_force_recovery;
|
||||
extern long innobase_open_files;
|
||||
extern char *innobase_data_home_dir, *innobase_data_file_path;
|
||||
extern char *innobase_log_group_home_dir, *innobase_log_arch_dir;
|
||||
|
|
|
@ -5238,7 +5238,7 @@ log and this option does nothing anymore.",
|
|||
{"innodb_thread_concurrency", OPT_INNODB_THREAD_CONCURRENCY,
|
||||
"Helps in performance tuning in heavily concurrent environments.",
|
||||
(gptr*) &srv_thread_concurrency, (gptr*) &srv_thread_concurrency,
|
||||
0, GET_LONG, REQUIRED_ARG, 8, 1, 1000, 0, 1, 0},
|
||||
0, GET_LONG, REQUIRED_ARG, 20, 1, 1000, 0, 1, 0},
|
||||
{"innodb_thread_sleep_delay", OPT_INNODB_THREAD_SLEEP_DELAY,
|
||||
"Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0"
|
||||
" disable a sleep",
|
||||
|
|
|
@ -425,6 +425,7 @@ int vio_close_pipe(Vio * vio)
|
|||
|
||||
|
||||
void vio_ignore_timeout(Vio *vio __attribute__((unused)),
|
||||
uint which __attribute__((unused)),
|
||||
uint timeout __attribute__((unused)))
|
||||
{
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue