28 #include "page0cur.ic"
35 #ifndef UNIV_HOTBACKUP
39 # ifdef UNIV_SEARCH_PERF_STAT
40 static ulint page_cur_short_succ = 0;
57 page_cur_lcg_prng(
void)
60 #define LCG_a 1103515245
62 static ib_uint64_t lcg_current = 0;
63 static ibool initialized = FALSE;
72 lcg_current = LCG_a * lcg_current + LCG_c;
82 page_cur_try_search_shortcut(
87 ulint* iup_matched_fields,
90 ulint* iup_matched_bytes,
94 ulint* ilow_matched_fields,
97 ulint* ilow_matched_bytes,
104 const rec_t* next_rec;
109 #ifdef UNIV_SEARCH_DEBUG
112 ibool success = FALSE;
113 const page_t* page = buf_block_get_frame(block);
115 ulint offsets_[REC_OFFS_NORMAL_SIZE];
116 ulint* offsets = offsets_;
117 rec_offs_init(offsets_);
122 offsets = rec_get_offsets(rec, index, offsets,
129 *ilow_matched_fields, *ilow_matched_bytes,
130 *iup_matched_fields, *iup_matched_bytes);
132 up_match = low_match;
133 up_bytes = low_bytes;
136 &low_match, &low_bytes) < 0) {
141 offsets = rec_get_offsets(next_rec, index, offsets,
145 &up_match, &up_bytes) >= 0) {
151 #ifdef UNIV_SEARCH_DEBUG
162 ut_a(*iup_matched_fields == up_match);
163 ut_a(*iup_matched_bytes == up_bytes);
166 ut_a(*ilow_matched_fields == low_match);
167 ut_a(*ilow_matched_bytes == low_bytes);
171 *iup_matched_fields = up_match;
172 *iup_matched_bytes = up_bytes;
175 *ilow_matched_fields = low_match;
176 *ilow_matched_bytes = low_bytes;
178 #ifdef UNIV_SEARCH_PERF_STAT
179 page_cur_short_succ++;
183 if (UNIV_LIKELY_NULL(heap)) {
191 #ifdef PAGE_CUR_LE_OR_EXTENDS
199 page_cur_rec_field_extends(
203 const ulint* offsets,
212 dfield = dtuple_get_nth_field(tuple, n);
214 type = dfield_get_type(dfield);
216 rec_f = rec_get_nth_field(rec, offsets, n, &rec_f_len);
218 if (type->
mtype == DATA_VARCHAR
219 || type->
mtype == DATA_CHAR
220 || type->
mtype == DATA_FIXBINARY
221 || type->
mtype == DATA_BINARY
222 || type->
mtype == DATA_BLOB
223 || type->
mtype == DATA_VARMYSQL
224 || type->
mtype == DATA_MYSQL) {
227 && rec_f_len != UNIV_SQL_NULL
230 dfield_get_data(dfield),
254 ulint* iup_matched_fields,
257 ulint* iup_matched_bytes,
261 ulint* ilow_matched_fields,
264 ulint* ilow_matched_bytes,
274 const page_dir_slot_t* slot;
276 const rec_t* low_rec;
277 const rec_t* mid_rec;
278 ulint up_matched_fields;
279 ulint up_matched_bytes;
280 ulint low_matched_fields;
281 ulint low_matched_bytes;
282 ulint cur_matched_fields;
283 ulint cur_matched_bytes;
285 #ifdef UNIV_SEARCH_DEBUG
287 ulint dbg_matched_fields;
288 ulint dbg_matched_bytes;
290 #ifdef UNIV_ZIP_DEBUG
294 ulint offsets_[REC_OFFS_NORMAL_SIZE];
295 ulint* offsets = offsets_;
296 rec_offs_init(offsets_);
298 ut_ad(block && tuple && iup_matched_fields && iup_matched_bytes
299 && ilow_matched_fields && ilow_matched_bytes && cursor);
300 ut_ad(dtuple_validate(tuple));
303 if (mode != PAGE_CUR_DBG)
305 # ifdef PAGE_CUR_LE_OR_EXTENDS
306 if (mode != PAGE_CUR_LE_OR_EXTENDS)
308 ut_ad(mode == PAGE_CUR_L || mode == PAGE_CUR_LE
309 || mode == PAGE_CUR_G || mode == PAGE_CUR_GE);
311 page = buf_block_get_frame(block);
312 #ifdef UNIV_ZIP_DEBUG
313 ut_a(!page_zip || page_zip_validate(page_zip, page));
318 #ifdef PAGE_CUR_ADAPT
320 && (mode == PAGE_CUR_LE)
325 if (page_cur_try_search_shortcut(
327 iup_matched_fields, iup_matched_bytes,
328 ilow_matched_fields, ilow_matched_bytes,
334 if (mode == PAGE_CUR_DBG) {
342 #ifdef PAGE_CUR_LE_OR_EXTENDS
343 ut_a(mode != PAGE_CUR_LE_OR_EXTENDS);
352 up_matched_fields = *iup_matched_fields;
353 up_matched_bytes = *iup_matched_bytes;
354 low_matched_fields = *ilow_matched_fields;
355 low_matched_bytes = *ilow_matched_bytes;
367 while (up - low > 1) {
368 mid = (low + up) / 2;
369 slot = page_dir_get_nth_slot(page, mid);
372 ut_pair_min(&cur_matched_fields, &cur_matched_bytes,
373 low_matched_fields, low_matched_bytes,
374 up_matched_fields, up_matched_bytes);
376 offsets = rec_get_offsets(mid_rec, index, offsets,
383 if (UNIV_LIKELY(cmp > 0)) {
386 low_matched_fields = cur_matched_fields;
387 low_matched_bytes = cur_matched_bytes;
389 }
else if (UNIV_EXPECT(cmp, -1)) {
390 #ifdef PAGE_CUR_LE_OR_EXTENDS
391 if (mode == PAGE_CUR_LE_OR_EXTENDS
392 && page_cur_rec_field_extends(
393 tuple, mid_rec, offsets,
394 cur_matched_fields)) {
401 up_matched_fields = cur_matched_fields;
402 up_matched_bytes = cur_matched_bytes;
404 }
else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE
405 #ifdef PAGE_CUR_LE_OR_EXTENDS
406 || mode == PAGE_CUR_LE_OR_EXTENDS
417 slot = page_dir_get_nth_slot(page, low);
419 slot = page_dir_get_nth_slot(page, up);
429 ut_pair_min(&cur_matched_fields, &cur_matched_bytes,
430 low_matched_fields, low_matched_bytes,
431 up_matched_fields, up_matched_bytes);
433 offsets = rec_get_offsets(mid_rec, index, offsets,
440 if (UNIV_LIKELY(cmp > 0)) {
443 low_matched_fields = cur_matched_fields;
444 low_matched_bytes = cur_matched_bytes;
446 }
else if (UNIV_EXPECT(cmp, -1)) {
447 #ifdef PAGE_CUR_LE_OR_EXTENDS
448 if (mode == PAGE_CUR_LE_OR_EXTENDS
449 && page_cur_rec_field_extends(
450 tuple, mid_rec, offsets,
451 cur_matched_fields)) {
458 up_matched_fields = cur_matched_fields;
459 up_matched_bytes = cur_matched_bytes;
460 }
else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE
461 #ifdef PAGE_CUR_LE_OR_EXTENDS
462 || mode == PAGE_CUR_LE_OR_EXTENDS
473 #ifdef UNIV_SEARCH_DEBUG
477 dbg_matched_fields = 0;
478 dbg_matched_bytes = 0;
480 offsets = rec_get_offsets(low_rec, index, offsets,
481 ULINT_UNDEFINED, &heap);
485 if (mode == PAGE_CUR_G) {
487 }
else if (mode == PAGE_CUR_GE) {
489 }
else if (mode == PAGE_CUR_L) {
491 }
else if (mode == PAGE_CUR_LE) {
497 ut_a(low_matched_fields == dbg_matched_fields);
498 ut_a(low_matched_bytes == dbg_matched_bytes);
501 dbg_matched_fields = 0;
502 dbg_matched_bytes = 0;
504 offsets = rec_get_offsets(up_rec, index, offsets,
505 ULINT_UNDEFINED, &heap);
509 if (mode == PAGE_CUR_G) {
511 }
else if (mode == PAGE_CUR_GE) {
513 }
else if (mode == PAGE_CUR_L) {
515 }
else if (mode == PAGE_CUR_LE) {
521 ut_a(up_matched_fields == dbg_matched_fields);
522 ut_a(up_matched_bytes == dbg_matched_bytes);
525 if (mode <= PAGE_CUR_GE) {
531 *iup_matched_fields = up_matched_fields;
532 *iup_matched_bytes = up_matched_bytes;
533 *ilow_matched_fields = low_matched_fields;
534 *ilow_matched_bytes = low_matched_bytes;
535 if (UNIV_LIKELY_NULL(heap)) {
555 if (UNIV_UNLIKELY(n_recs == 0)) {
560 rnd = (ulint) (page_cur_lcg_prng() % n_recs);
571 page_cur_insert_rec_write_log(
582 ulint cur_extra_size;
588 ut_a(rec_size < UNIV_PAGE_SIZE);
595 ulint cur_offs_[REC_OFFS_NORMAL_SIZE];
596 ulint ins_offs_[REC_OFFS_NORMAL_SIZE];
601 rec_offs_init(cur_offs_);
602 rec_offs_init(ins_offs_);
604 cur_offs = rec_get_offsets(cursor_rec, index, cur_offs_,
605 ULINT_UNDEFINED, &heap);
606 ins_offs = rec_get_offsets(insert_rec, index, ins_offs_,
607 ULINT_UNDEFINED, &heap);
614 if (UNIV_LIKELY_NULL(heap)) {
619 ins_ptr = insert_rec - extra_size;
623 if (cur_extra_size == extra_size) {
624 ulint min_rec_size =
ut_min(cur_rec_size, rec_size);
626 const byte* cur_ptr = cursor_rec - cur_extra_size;
632 if (*ins_ptr == *cur_ptr) {
636 }
else if ((i < extra_size)
641 ins_ptr = insert_rec;
642 cur_ptr = cursor_rec;
646 }
while (i < min_rec_size);
654 2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN);
655 if (UNIV_UNLIKELY(!log_ptr)) {
665 if (UNIV_UNLIKELY(!log_ptr)) {
676 log_end = &log_ptr[2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN];
681 log_ptr =
mlog_open(mtr, 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN);
687 log_end = &log_ptr[5 + 1 + 5 + 5 + MLOG_BUF_MARGIN];
695 goto need_extra_info;
702 goto need_extra_info;
706 if (extra_size != cur_extra_size || rec_size != cur_rec_size) {
711 2 * (rec_size - i) + 1);
726 ut_a(i < UNIV_PAGE_SIZE);
727 ut_a(extra_size < UNIV_PAGE_SIZE);
739 if (log_ptr + rec_size <= log_end) {
740 memcpy(log_ptr, ins_ptr, rec_size);
744 ut_a(rec_size < UNIV_PAGE_SIZE);
749 # define page_cur_insert_rec_write_log(ins_rec,size,cur,index,mtr) ((void) 0)
768 ulint mismatch_index;
774 ulint info_and_status_bits = 0;
777 ulint offsets_[REC_OFFS_NORMAL_SIZE];
778 ulint* offsets = offsets_;
779 rec_offs_init(offsets_);
781 page = block ? buf_block_get_frame(block) : NULL;
790 if (UNIV_UNLIKELY(end_ptr < ptr + 2)) {
798 cursor_rec = page + offset;
800 if (UNIV_UNLIKELY(offset >= UNIV_PAGE_SIZE)) {
815 if (UNIV_UNLIKELY(end_seg_len >= UNIV_PAGE_SIZE << 1)) {
821 if (end_seg_len & 0x1UL) {
824 if (end_ptr < ptr + 1) {
839 ut_a(origin_offset < UNIV_PAGE_SIZE);
848 ut_a(mismatch_index < UNIV_PAGE_SIZE);
851 if (UNIV_UNLIKELY(end_ptr < ptr + (end_seg_len >> 1))) {
858 return(ptr + (end_seg_len >> 1));
867 offsets = rec_get_offsets(cursor_rec, index, offsets,
868 ULINT_UNDEFINED, &heap);
870 if (!(end_seg_len & 0x1UL)) {
874 mismatch_index =
rec_offs_size(offsets) - (end_seg_len >> 1);
879 if (mismatch_index + end_seg_len <
sizeof buf1) {
882 buf =
static_cast<byte *
>(mem_alloc(mismatch_index + end_seg_len));
887 if (UNIV_UNLIKELY(mismatch_index >= UNIV_PAGE_SIZE)) {
889 "Is short %lu, info_and_status_bits %lu, offset %lu, "
891 "mismatch index %lu, end_seg_len %lu\n"
893 (ulong) is_short, (ulong) info_and_status_bits,
895 (ulong) origin_offset,
896 (ulong) mismatch_index, (ulong) end_seg_len,
897 (ulong) (ptr - ptr2));
899 fputs(
"Dump of 300 bytes of log:\n", stderr);
903 buf_page_print(page, 0);
908 ut_memcpy(buf, rec_get_start(cursor_rec, offsets), mismatch_index);
909 ut_memcpy(buf + mismatch_index, ptr, end_seg_len);
913 info_and_status_bits);
916 info_and_status_bits);
921 offsets = rec_get_offsets(buf + origin_offset, index, offsets,
922 ULINT_UNDEFINED, &heap);
925 index, offsets, mtr))) {
936 if (UNIV_LIKELY_NULL(heap)) {
940 return(ptr + end_seg_len);
981 #ifdef UNIV_DEBUG_VALGRIND
983 const void* rec_start
988 ? REC_N_NEW_EXTRA_BYTES
989 : REC_N_OLD_EXTRA_BYTES);
994 UNIV_MEM_ASSERT_RW(rec_start, extra_size);
1001 if (UNIV_LIKELY_NULL(free_rec)) {
1003 ulint foffsets_[REC_OFFS_NORMAL_SIZE];
1004 ulint* foffsets = foffsets_;
1007 rec_offs_init(foffsets_);
1009 foffsets = rec_get_offsets(free_rec, index, foffsets,
1010 ULINT_UNDEFINED, &heap);
1012 if (UNIV_LIKELY_NULL(heap)) {
1033 if (UNIV_LIKELY_NULL(heap)) {
1040 rec_size, &heap_no);
1042 if (UNIV_UNLIKELY(insert_buf == NULL)) {
1048 insert_rec =
rec_copy(insert_buf, rec, offsets);
1049 rec_offs_make_valid(insert_rec, index, offsets);
1052 ut_ad(current_rec != insert_rec);
1060 <= REC_STATUS_INFIMUM);
1082 UNIV_MEM_ASSERT_RW(rec_get_start(insert_rec, offsets),
1091 if (UNIV_UNLIKELY(last_insert == NULL)) {
1096 }
else if ((last_insert == current_rec)
1104 page, PAGE_N_DIRECTION) + 1);
1114 page, PAGE_N_DIRECTION) + 1);
1139 if (UNIV_UNLIKELY(n_owned == PAGE_DIR_SLOT_MAX_N_OWNED)) {
1147 if (UNIV_LIKELY(mtr != NULL)) {
1148 page_cur_insert_rec_write_log(insert_rec, rec_size,
1149 current_rec, index, mtr);
1152 btr_blob_dbg_add_rec(insert_rec, index, offsets,
"insert");
1162 page_cur_insert_rec_zip_reorg(
1164 rec_t** current_rec,
1187 rec = page + PAGE_NEW_INFIMUM;
1200 btr_blob_dbg_remove(page, index,
"insert_zip_fail");
1205 btr_blob_dbg_add(page, index,
"insert_zip_fail");
1219 rec_t** current_rec,
1249 #ifdef UNIV_ZIP_DEBUG
1250 ut_a(page_zip_validate(page_zip, page));
1256 #ifdef UNIV_DEBUG_VALGRIND
1258 const void* rec_start
1263 ? REC_N_NEW_EXTRA_BYTES
1264 : REC_N_OLD_EXTRA_BYTES);
1269 UNIV_MEM_ASSERT_RW(rec_start, extra_size);
1279 index, rec, offsets,
1282 if (UNIV_LIKELY(insert_rec != NULL)) {
1283 insert_rec = page_cur_insert_rec_zip_reorg(
1284 current_rec, block, index, insert_rec,
1285 page, page_zip, mtr);
1292 if (UNIV_LIKELY_NULL(free_rec)) {
1294 lint extra_size_diff;
1295 ulint foffsets_[REC_OFFS_NORMAL_SIZE];
1296 ulint* foffsets = foffsets_;
1299 rec_offs_init(foffsets_);
1301 foffsets = rec_get_offsets(free_rec, index, foffsets,
1302 ULINT_UNDEFINED, &heap);
1305 if (UNIV_LIKELY_NULL(heap)) {
1320 if (UNIV_UNLIKELY(extra_size_diff < 0)) {
1323 < rec_size - extra_size_diff) {
1328 insert_buf -= extra_size_diff;
1329 }
else if (UNIV_UNLIKELY(extra_size_diff)) {
1345 ut_ad(rec_size > REC_NODE_PTR_SIZE);
1350 memset(rec_get_end(free_rec, foffsets)
1351 - REC_NODE_PTR_SIZE, 0,
1365 ut_ad(trx_id_col > 0);
1366 ut_ad(trx_id_col != ULINT_UNDEFINED);
1370 ut_ad(len == DATA_TRX_ID_LEN);
1372 if (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN + trx_id_offs
1379 memset(free_rec + trx_id_offs, 0,
1380 DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
1383 ut_ad(free_rec + trx_id_offs + DATA_TRX_ID_LEN
1384 == rec_get_nth_field(free_rec, foffsets,
1385 trx_id_col + 1, &len));
1386 ut_ad(len == DATA_ROLL_PTR_LEN);
1389 if (UNIV_LIKELY_NULL(heap)) {
1396 rec_size, &heap_no);
1398 if (UNIV_UNLIKELY(insert_buf == NULL)) {
1406 insert_rec =
rec_copy(insert_buf, rec, offsets);
1407 rec_offs_make_valid(insert_rec, index, offsets);
1410 ut_ad(*current_rec != insert_rec);
1416 <= REC_STATUS_INFIMUM);
1432 UNIV_MEM_ASSERT_RW(rec_get_start(insert_rec, offsets),
1444 if (UNIV_UNLIKELY(last_insert == NULL)) {
1449 }
else if ((last_insert == *current_rec)
1457 page, PAGE_N_DIRECTION) + 1);
1467 page, PAGE_N_DIRECTION) + 1);
1488 if (UNIV_UNLIKELY(n_owned == PAGE_DIR_SLOT_MAX_N_OWNED)) {
1497 btr_blob_dbg_add_rec(insert_rec, index, offsets,
"insert_zip_ok");
1500 if (UNIV_LIKELY(mtr != NULL)) {
1501 page_cur_insert_rec_write_log(insert_rec, rec_size,
1502 *current_rec, index, mtr);
1508 #ifndef UNIV_HOTBACKUP
1515 page_copy_rec_list_to_created_page_write_log(
1529 if (UNIV_LIKELY(log_ptr != NULL)) {
1555 if (ptr + 4 > end_ptr) {
1563 rec_end = ptr + log_data_len;
1565 if (rec_end > end_ptr) {
1575 while (ptr < rec_end) {
1580 ut_a(ptr == rec_end);
1582 page = buf_block_get_frame(block);
1593 #ifndef UNIV_HOTBACKUP
1606 page_dir_slot_t* slot = 0;
1608 rec_t* insert_rec = 0;
1618 ulint offsets_[REC_OFFS_NORMAL_SIZE];
1619 ulint* offsets = offsets_;
1620 rec_offs_init(offsets_);
1641 new_page + UNIV_PAGE_SIZE - 1);
1644 log_ptr = page_copy_rec_list_to_created_page_write_log(new_page,
1653 prev_rec = page_get_infimum_rec(new_page);
1655 heap_top = new_page + PAGE_NEW_SUPREMUM_END;
1657 heap_top = new_page + PAGE_OLD_SUPREMUM_END;
1664 offsets = rec_get_offsets(rec, index, offsets,
1665 ULINT_UNDEFINED, &heap);
1666 insert_rec =
rec_copy(heap_top, rec, offsets);
1674 PAGE_HEAP_NO_USER_LOW + n_recs);
1681 PAGE_HEAP_NO_USER_LOW + n_recs);
1688 (count == (PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2)) {
1692 slot = page_dir_get_nth_slot(new_page, slot_index);
1702 ut_ad(heap_top < new_page + UNIV_PAGE_SIZE);
1704 heap_top += rec_size;
1706 rec_offs_make_valid(insert_rec, index, offsets);
1707 btr_blob_dbg_add_rec(insert_rec, index, offsets,
"copy_end");
1709 page_cur_insert_rec_write_log(insert_rec, rec_size, prev_rec,
1711 prev_rec = insert_rec;
1715 if ((slot_index > 0) && (count + 1
1716 + (PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2
1717 <= PAGE_DIR_SLOT_MAX_N_OWNED)) {
1725 count += (PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2;
1732 if (UNIV_LIKELY_NULL(heap)) {
1738 ut_a(log_data_len < 100 * UNIV_PAGE_SIZE);
1740 if (UNIV_LIKELY(log_ptr != NULL)) {
1750 slot = page_dir_get_nth_slot(new_page, 1 + slot_index);
1774 page_cur_delete_rec_write_log(
1801 # define page_cur_delete_rec_write_log(rec,index,mtr) ((void) 0)
1820 if (end_ptr < ptr + 2) {
1829 ut_a(offset <= UNIV_PAGE_SIZE);
1832 page_t* page = buf_block_get_frame(block);
1834 ulint offsets_[REC_OFFS_NORMAL_SIZE];
1835 rec_t* rec = page + offset;
1836 rec_offs_init(offsets_);
1842 rec_get_offsets(rec, index, offsets_,
1843 ULINT_UNDEFINED, &heap),
1845 if (UNIV_LIKELY_NULL(heap)) {
1862 const ulint* offsets,
1865 page_dir_slot_t* cur_dir_slot;
1866 page_dir_slot_t* prev_slot;
1870 rec_t* prev_rec = NULL;
1876 ut_ad(cursor && mtr);
1878 page = page_cur_get_page(cursor);
1879 page_zip = page_cur_get_page_zip(cursor);
1889 current_rec = cursor->
rec;
1898 cur_dir_slot = page_dir_get_nth_slot(page, cur_slot_no);
1902 page_cur_delete_rec_write_log(current_rec, index, mtr);
1917 ut_ad(cur_slot_no > 0);
1918 prev_slot = page_dir_get_nth_slot(page, cur_slot_no - 1);
1925 while(current_rec != rec) {
1931 next_rec = cursor->
rec;
1942 #if PAGE_DIR_SLOT_MIN_N_OWNED < 2
1943 # error "PAGE_DIR_SLOT_MIN_N_OWNED < 2"
1945 ut_ad(cur_n_owned > 1);
1956 btr_blob_dbg_remove_rec(current_rec, index, offsets,
"delete");
1963 if (UNIV_UNLIKELY(cur_n_owned <= PAGE_DIR_SLOT_MIN_N_OWNED)) {
1967 #ifdef UNIV_ZIP_DEBUG
1968 ut_a(!page_zip || page_zip_validate(page_zip, page));
1972 #ifdef UNIV_COMPILE_TEST_FUNCS
1978 test_page_cur_lcg_prng(
1983 unsigned long long rnd;
1985 for (i = 0; i < n; i++) {
1986 rnd = page_cur_lcg_prng();
1987 printf(
"%llu\t%%2=%llu %%3=%llu %%5=%llu %%7=%llu %%11=%llu\n",