summaryrefslogtreecommitdiff
path: root/storage/innobase/page/page0cur.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/page/page0cur.c')
-rw-r--r--storage/innobase/page/page0cur.c1510
1 files changed, 0 insertions, 1510 deletions
diff --git a/storage/innobase/page/page0cur.c b/storage/innobase/page/page0cur.c
deleted file mode 100644
index 70b7de194fd..00000000000
--- a/storage/innobase/page/page0cur.c
+++ /dev/null
@@ -1,1510 +0,0 @@
-/************************************************************************
-The page cursor
-
-(c) 1994-1996 Innobase Oy
-
-Created 10/4/1994 Heikki Tuuri
-*************************************************************************/
-
-#include "page0cur.h"
-#ifdef UNIV_NONINL
-#include "page0cur.ic"
-#endif
-
-#include "rem0cmp.h"
-#include "mtr0log.h"
-#include "log0recv.h"
-#include "rem0cmp.h"
-#include "srv0srv.h"
-#include "ut0ut.h"
-
-static ulint page_rnd = 976722341;
-
-#ifdef PAGE_CUR_ADAPT
-# ifdef UNIV_SEARCH_PERF_STAT
-ulint page_cur_short_succ = 0;
-# endif /* UNIV_SEARCH_PERF_STAT */
-
-/***********************************************************************
-This is a linear congruential generator PRNG. Returns a pseudo random
-number between 0 and 2^64-1 inclusive. The formula and the constants
-being used are:
-X[n+1] = (a * X[n] + c) mod m
-where:
-X[0] = ut_usectime()
-a = 1103515245 (3^5 * 5 * 7 * 129749)
-c = 12345 (3 * 5 * 823)
-m = 18446744073709551616 (2^64)
-*/
-#define LCG_a 1103515245
-#define LCG_c 12345
-static
-unsigned long long
-page_cur_lcg_prng()
-/*===============*/
- /* out: number between 0 and 2^64-1 */
-{
- static unsigned long long lcg_current = 0;
- static ibool initialized = FALSE;
- ulint time_sec;
- ulint time_ms;
-
- if (!initialized) {
- ut_usectime(&time_sec, &time_ms);
- lcg_current = (unsigned long long) (time_sec * 1000000
- + time_ms);
- initialized = TRUE;
- }
-
- /* no need to "% 2^64" explicitly because lcg_current is
- 64 bit and this will be done anyway */
- lcg_current = LCG_a * lcg_current + LCG_c;
-
- return(lcg_current);
-}
-
-/********************************************************************
-Tries a search shortcut based on the last insert. */
-UNIV_INLINE
-ibool
-page_cur_try_search_shortcut(
-/*=========================*/
- /* out: TRUE on success */
- page_t* page, /* in: index page */
- dict_index_t* index, /* in: record descriptor */
- dtuple_t* tuple, /* in: data tuple */
- ulint* iup_matched_fields,
- /* in/out: already matched fields in upper
- limit record */
- ulint* iup_matched_bytes,
- /* in/out: already matched bytes in a field
- not yet completely matched */
- ulint* ilow_matched_fields,
- /* in/out: already matched fields in lower
- limit record */
- ulint* ilow_matched_bytes,
- /* in/out: already matched bytes in a field
- not yet completely matched */
- page_cur_t* cursor) /* out: page cursor */
-{
- rec_t* rec;
- rec_t* next_rec;
- ulint low_match;
- ulint low_bytes;
- ulint up_match;
- ulint up_bytes;
-#ifdef UNIV_SEARCH_DEBUG
- page_cur_t cursor2;
-#endif
- ibool success = FALSE;
- mem_heap_t* heap = NULL;
- ulint offsets_[REC_OFFS_NORMAL_SIZE];
- ulint* offsets = offsets_;
- *offsets_ = (sizeof offsets_) / sizeof *offsets_;
-
- ut_ad(dtuple_check_typed(tuple));
-
- rec = page_header_get_ptr(page, PAGE_LAST_INSERT);
- offsets = rec_get_offsets(rec, index, offsets,
- dtuple_get_n_fields(tuple), &heap);
-
- ut_ad(rec);
- ut_ad(page_rec_is_user_rec(rec));
-
- ut_pair_min(&low_match, &low_bytes,
- *ilow_matched_fields, *ilow_matched_bytes,
- *iup_matched_fields, *iup_matched_bytes);
-
- up_match = low_match;
- up_bytes = low_bytes;
-
- if (page_cmp_dtuple_rec_with_match(tuple, rec, offsets,
- &low_match, &low_bytes) < 0) {
- goto exit_func;
- }
-
- next_rec = page_rec_get_next(rec);
- offsets = rec_get_offsets(next_rec, index, offsets,
- dtuple_get_n_fields(tuple), &heap);
-
- if (page_cmp_dtuple_rec_with_match(tuple, next_rec, offsets,
- &up_match, &up_bytes) >= 0) {
- goto exit_func;
- }
-
- cursor->rec = rec;
-
-#ifdef UNIV_SEARCH_DEBUG
- page_cur_search_with_match(page, index, tuple, PAGE_CUR_DBG,
- iup_matched_fields,
- iup_matched_bytes,
- ilow_matched_fields,
- ilow_matched_bytes,
- &cursor2);
- ut_a(cursor2.rec == cursor->rec);
-
- if (next_rec != page_get_supremum_rec(page)) {
-
- ut_a(*iup_matched_fields == up_match);
- ut_a(*iup_matched_bytes == up_bytes);
- }
-
- ut_a(*ilow_matched_fields == low_match);
- ut_a(*ilow_matched_bytes == low_bytes);
-#endif
- if (!page_rec_is_supremum(next_rec)) {
-
- *iup_matched_fields = up_match;
- *iup_matched_bytes = up_bytes;
- }
-
- *ilow_matched_fields = low_match;
- *ilow_matched_bytes = low_bytes;
-
-#ifdef UNIV_SEARCH_PERF_STAT
- page_cur_short_succ++;
-#endif
- success = TRUE;
-exit_func:
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- return(success);
-}
-
-#endif
-
-#ifdef PAGE_CUR_LE_OR_EXTENDS
-/********************************************************************
-Checks if the nth field in a record is a character type field which extends
-the nth field in tuple, i.e., the field is longer or equal in length and has
-common first characters. */
-static
-ibool
-page_cur_rec_field_extends(
-/*=======================*/
- /* out: TRUE if rec field
- extends tuple field */
- dtuple_t* tuple, /* in: data tuple */
- rec_t* rec, /* in: record */
- const ulint* offsets,/* in: array returned by rec_get_offsets() */
- ulint n) /* in: compare nth field */
-{
- dtype_t* type;
- dfield_t* dfield;
- byte* rec_f;
- ulint rec_f_len;
-
- ut_ad(rec_offs_validate(rec, NULL, offsets));
- dfield = dtuple_get_nth_field(tuple, n);
-
- type = dfield_get_type(dfield);
-
- rec_f = rec_get_nth_field(rec, offsets, n, &rec_f_len);
-
- if (type->mtype == DATA_VARCHAR
- || type->mtype == DATA_CHAR
- || type->mtype == DATA_FIXBINARY
- || type->mtype == DATA_BINARY
- || type->mtype == DATA_BLOB
- || type->mtype == DATA_VARMYSQL
- || type->mtype == DATA_MYSQL) {
-
- if (dfield_get_len(dfield) != UNIV_SQL_NULL
- && rec_f_len != UNIV_SQL_NULL
- && rec_f_len >= dfield_get_len(dfield)
- && !cmp_data_data_slow(type,
- dfield_get_data(dfield),
- dfield_get_len(dfield),
- rec_f, dfield_get_len(dfield))) {
-
- return(TRUE);
- }
- }
-
- return(FALSE);
-}
-#endif /* PAGE_CUR_LE_OR_EXTENDS */
-
-/********************************************************************
-Searches the right position for a page cursor. */
-
-void
-page_cur_search_with_match(
-/*=======================*/
- page_t* page, /* in: index page */
- dict_index_t* index, /* in: record descriptor */
- dtuple_t* tuple, /* in: data tuple */
- ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
- or PAGE_CUR_GE */
- ulint* iup_matched_fields,
- /* in/out: already matched fields in upper
- limit record */
- ulint* iup_matched_bytes,
- /* in/out: already matched bytes in a field
- not yet completely matched */
- ulint* ilow_matched_fields,
- /* in/out: already matched fields in lower
- limit record */
- ulint* ilow_matched_bytes,
- /* in/out: already matched bytes in a field
- not yet completely matched */
- page_cur_t* cursor) /* out: page cursor */
-{
- ulint up;
- ulint low;
- ulint mid;
- page_dir_slot_t* slot;
- rec_t* up_rec;
- rec_t* low_rec;
- rec_t* mid_rec;
- ulint up_matched_fields;
- ulint up_matched_bytes;
- ulint low_matched_fields;
- ulint low_matched_bytes;
- ulint cur_matched_fields;
- ulint cur_matched_bytes;
- int cmp;
-#ifdef UNIV_SEARCH_DEBUG
- int dbg_cmp;
- ulint dbg_matched_fields;
- ulint dbg_matched_bytes;
-#endif
- mem_heap_t* heap = NULL;
- ulint offsets_[REC_OFFS_NORMAL_SIZE];
- ulint* offsets = offsets_;
- *offsets_ = (sizeof offsets_) / sizeof *offsets_;
-
- ut_ad(page && tuple && iup_matched_fields && iup_matched_bytes
- && ilow_matched_fields && ilow_matched_bytes && cursor);
- ut_ad(dtuple_validate(tuple));
- ut_ad(dtuple_check_typed(tuple));
-#ifdef UNIV_DEBUG
-# ifdef PAGE_CUR_DBG
- if (mode != PAGE_CUR_DBG)
-# endif /* PAGE_CUR_DBG */
-# ifdef PAGE_CUR_LE_OR_EXTENDS
- if (mode != PAGE_CUR_LE_OR_EXTENDS)
-# endif /* PAGE_CUR_LE_OR_EXTENDS */
- ut_ad(mode == PAGE_CUR_L || mode == PAGE_CUR_LE
- || mode == PAGE_CUR_G || mode == PAGE_CUR_GE);
-#endif /* UNIV_DEBUG */
-
- page_check_dir(page);
-
-#ifdef PAGE_CUR_ADAPT
- if ((page_header_get_field(page, PAGE_LEVEL) == 0)
- && (mode == PAGE_CUR_LE)
- && (page_header_get_field(page, PAGE_N_DIRECTION) > 3)
- && (page_header_get_ptr(page, PAGE_LAST_INSERT))
- && (page_header_get_field(page, PAGE_DIRECTION) == PAGE_RIGHT)) {
-
- if (page_cur_try_search_shortcut(
- page, index, tuple,
- iup_matched_fields, iup_matched_bytes,
- ilow_matched_fields, ilow_matched_bytes,
- cursor)) {
- return;
- }
- }
-# ifdef PAGE_CUR_DBG
- if (mode == PAGE_CUR_DBG) {
- mode = PAGE_CUR_LE;
- }
-# endif
-#endif
-
- /* The following flag does not work for non-latin1 char sets because
- cmp_full_field does not tell how many bytes matched */
-#ifdef PAGE_CUR_LE_OR_EXTENDS
- ut_a(mode != PAGE_CUR_LE_OR_EXTENDS);
-#endif /* PAGE_CUR_LE_OR_EXTENDS */
-
- /* If mode PAGE_CUR_G is specified, we are trying to position the
- cursor to answer a query of the form "tuple < X", where tuple is
- the input parameter, and X denotes an arbitrary physical record on
- the page. We want to position the cursor on the first X which
- satisfies the condition. */
-
- up_matched_fields = *iup_matched_fields;
- up_matched_bytes = *iup_matched_bytes;
- low_matched_fields = *ilow_matched_fields;
- low_matched_bytes = *ilow_matched_bytes;
-
- /* Perform binary search. First the search is done through the page
- directory, after that as a linear search in the list of records
- owned by the upper limit directory slot. */
-
- low = 0;
- up = page_dir_get_n_slots(page) - 1;
-
- /* Perform binary search until the lower and upper limit directory
- slots come to the distance 1 of each other */
-
- while (up - low > 1) {
- mid = (low + up) / 2;
- slot = page_dir_get_nth_slot(page, mid);
- mid_rec = page_dir_slot_get_rec(slot);
-
- ut_pair_min(&cur_matched_fields, &cur_matched_bytes,
- low_matched_fields, low_matched_bytes,
- up_matched_fields, up_matched_bytes);
-
- offsets = rec_get_offsets(mid_rec, index, offsets,
- dtuple_get_n_fields_cmp(tuple),
- &heap);
-
- cmp = cmp_dtuple_rec_with_match(tuple, mid_rec, offsets,
- &cur_matched_fields,
- &cur_matched_bytes);
- if (UNIV_LIKELY(cmp > 0)) {
-low_slot_match:
- low = mid;
- low_matched_fields = cur_matched_fields;
- low_matched_bytes = cur_matched_bytes;
-
- } else if (UNIV_EXPECT(cmp, -1)) {
-#ifdef PAGE_CUR_LE_OR_EXTENDS
- if (mode == PAGE_CUR_LE_OR_EXTENDS
- && page_cur_rec_field_extends(
- tuple, mid_rec, offsets,
- cur_matched_fields)) {
-
- goto low_slot_match;
- }
-#endif /* PAGE_CUR_LE_OR_EXTENDS */
-up_slot_match:
- up = mid;
- up_matched_fields = cur_matched_fields;
- up_matched_bytes = cur_matched_bytes;
-
- } else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE
-#ifdef PAGE_CUR_LE_OR_EXTENDS
- || mode == PAGE_CUR_LE_OR_EXTENDS
-#endif /* PAGE_CUR_LE_OR_EXTENDS */
- ) {
-
- goto low_slot_match;
- } else {
-
- goto up_slot_match;
- }
- }
-
- slot = page_dir_get_nth_slot(page, low);
- low_rec = page_dir_slot_get_rec(slot);
- slot = page_dir_get_nth_slot(page, up);
- up_rec = page_dir_slot_get_rec(slot);
-
- /* Perform linear search until the upper and lower records come to
- distance 1 of each other. */
-
- while (page_rec_get_next(low_rec) != up_rec) {
-
- mid_rec = page_rec_get_next(low_rec);
-
- ut_pair_min(&cur_matched_fields, &cur_matched_bytes,
- low_matched_fields, low_matched_bytes,
- up_matched_fields, up_matched_bytes);
-
- offsets = rec_get_offsets(mid_rec, index, offsets,
- dtuple_get_n_fields_cmp(tuple),
- &heap);
-
- cmp = cmp_dtuple_rec_with_match(tuple, mid_rec, offsets,
- &cur_matched_fields,
- &cur_matched_bytes);
- if (UNIV_LIKELY(cmp > 0)) {
-low_rec_match:
- low_rec = mid_rec;
- low_matched_fields = cur_matched_fields;
- low_matched_bytes = cur_matched_bytes;
-
- } else if (UNIV_EXPECT(cmp, -1)) {
-#ifdef PAGE_CUR_LE_OR_EXTENDS
- if (mode == PAGE_CUR_LE_OR_EXTENDS
- && page_cur_rec_field_extends(
- tuple, mid_rec, offsets,
- cur_matched_fields)) {
-
- goto low_rec_match;
- }
-#endif /* PAGE_CUR_LE_OR_EXTENDS */
-up_rec_match:
- up_rec = mid_rec;
- up_matched_fields = cur_matched_fields;
- up_matched_bytes = cur_matched_bytes;
- } else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE
-#ifdef PAGE_CUR_LE_OR_EXTENDS
- || mode == PAGE_CUR_LE_OR_EXTENDS
-#endif /* PAGE_CUR_LE_OR_EXTENDS */
- ) {
-
- goto low_rec_match;
- } else {
-
- goto up_rec_match;
- }
- }
-
-#ifdef UNIV_SEARCH_DEBUG
-
- /* Check that the lower and upper limit records have the
- right alphabetical order compared to tuple. */
- dbg_matched_fields = 0;
- dbg_matched_bytes = 0;
-
- offsets = rec_get_offsets(low_rec, index, offsets,
- ULINT_UNDEFINED, &heap);
- dbg_cmp = page_cmp_dtuple_rec_with_match(tuple, low_rec, offsets,
- &dbg_matched_fields,
- &dbg_matched_bytes);
- if (mode == PAGE_CUR_G) {
- ut_a(dbg_cmp >= 0);
- } else if (mode == PAGE_CUR_GE) {
- ut_a(dbg_cmp == 1);
- } else if (mode == PAGE_CUR_L) {
- ut_a(dbg_cmp == 1);
- } else if (mode == PAGE_CUR_LE) {
- ut_a(dbg_cmp >= 0);
- }
-
- if (low_rec != page_get_infimum_rec(page)) {
-
- ut_a(low_matched_fields == dbg_matched_fields);
- ut_a(low_matched_bytes == dbg_matched_bytes);
- }
-
- dbg_matched_fields = 0;
- dbg_matched_bytes = 0;
-
- offsets = rec_get_offsets(up_rec, index, offsets,
- ULINT_UNDEFINED, &heap);
- dbg_cmp = page_cmp_dtuple_rec_with_match(tuple, up_rec, offsets,
- &dbg_matched_fields,
- &dbg_matched_bytes);
- if (mode == PAGE_CUR_G) {
- ut_a(dbg_cmp == -1);
- } else if (mode == PAGE_CUR_GE) {
- ut_a(dbg_cmp <= 0);
- } else if (mode == PAGE_CUR_L) {
- ut_a(dbg_cmp <= 0);
- } else if (mode == PAGE_CUR_LE) {
- ut_a(dbg_cmp == -1);
- }
-
- if (up_rec != page_get_supremum_rec(page)) {
-
- ut_a(up_matched_fields == dbg_matched_fields);
- ut_a(up_matched_bytes == dbg_matched_bytes);
- }
-#endif
- if (mode <= PAGE_CUR_GE) {
- cursor->rec = up_rec;
- } else {
- cursor->rec = low_rec;
- }
-
- *iup_matched_fields = up_matched_fields;
- *iup_matched_bytes = up_matched_bytes;
- *ilow_matched_fields = low_matched_fields;
- *ilow_matched_bytes = low_matched_bytes;
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
-}
-
-/***************************************************************
-Positions a page cursor on a randomly chosen user record on a page. If there
-are no user records, sets the cursor on the infimum record. */
-
-void
-page_cur_open_on_rnd_user_rec(
-/*==========================*/
- page_t* page, /* in: page */
- page_cur_t* cursor) /* in/out: page cursor */
-{
- ulint rnd;
- rec_t* rec;
-
- if (page_get_n_recs(page) == 0) {
- page_cur_position(page_get_infimum_rec(page), cursor);
-
- return;
- }
-
- if (srv_use_legacy_cardinality_algorithm) {
- page_rnd += 87584577;
-
- rnd = page_rnd % page_get_n_recs(page);
- } else {
- rnd = (ulint) page_cur_lcg_prng() % page_get_n_recs(page);
- }
-
- rec = page_get_infimum_rec(page);
-
- rec = page_rec_get_next(rec);
-
- while (rnd > 0) {
- rec = page_rec_get_next(rec);
-
- rnd--;
- }
-
- page_cur_position(rec, cursor);
-}
-
-/***************************************************************
-Writes the log record of a record insert on a page. */
-static
-void
-page_cur_insert_rec_write_log(
-/*==========================*/
- rec_t* insert_rec, /* in: inserted physical record */
- ulint rec_size, /* in: insert_rec size */
- rec_t* cursor_rec, /* in: record the
- cursor is pointing to */
- dict_index_t* index, /* in: record descriptor */
- mtr_t* mtr) /* in: mini-transaction handle */
-{
- ulint cur_rec_size;
- ulint extra_size;
- ulint cur_extra_size;
- ulint min_rec_size;
- byte* ins_ptr;
- byte* cur_ptr;
- ulint extra_info_yes;
- 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)
- == !dict_table_is_comp(index->table));
- comp = page_rec_is_comp(insert_rec);
-
- {
- mem_heap_t* heap = NULL;
- ulint cur_offs_[REC_OFFS_NORMAL_SIZE];
- ulint ins_offs_[REC_OFFS_NORMAL_SIZE];
-
- ulint* cur_offs;
- ulint* ins_offs;
-
- *cur_offs_ = (sizeof cur_offs_) / sizeof *cur_offs_;
- *ins_offs_ = (sizeof ins_offs_) / sizeof *ins_offs_;
-
- cur_offs = rec_get_offsets(cursor_rec, index, cur_offs_,
- ULINT_UNDEFINED, &heap);
- ins_offs = rec_get_offsets(insert_rec, index, ins_offs_,
- ULINT_UNDEFINED, &heap);
-
- extra_size = rec_offs_extra_size(ins_offs);
- cur_extra_size = rec_offs_extra_size(cur_offs);
- ut_ad(rec_size == rec_offs_size(ins_offs));
- cur_rec_size = rec_offs_size(cur_offs);
-
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- }
-
- ins_ptr = insert_rec - extra_size;
-
- i = 0;
-
- if (cur_extra_size == extra_size) {
- min_rec_size = ut_min(cur_rec_size, rec_size);
-
- cur_ptr = cursor_rec - cur_extra_size;
-
- /* Find out the first byte in insert_rec which differs from
- cursor_rec; skip the bytes in the record info */
-
- for (;;) {
- if (i >= min_rec_size) {
-
- break;
- } else if (*ins_ptr == *cur_ptr) {
- i++;
- ins_ptr++;
- cur_ptr++;
- } else if ((i < extra_size)
- && (i >= extra_size
- - (comp
- ? REC_N_NEW_EXTRA_BYTES
- : REC_N_OLD_EXTRA_BYTES))) {
- i = extra_size;
- ins_ptr = insert_rec;
- cur_ptr = cursor_rec;
- } else {
- break;
- }
- }
- }
-
- if (mtr_get_log_mode(mtr) != MTR_LOG_SHORT_INSERTS) {
-
- log_ptr = mlog_open_and_write_index(mtr, insert_rec, index,
- comp
- ? MLOG_COMP_REC_INSERT
- : MLOG_REC_INSERT,
- 2 + 5 + 1 + 5 + 5
- + MLOG_BUF_MARGIN);
-
- if (!log_ptr) {
- /* Logging in mtr is switched off during crash
- recovery: in that case mlog_open returns NULL */
- return;
- }
-
- log_end = &log_ptr[2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN];
- /* Write the cursor rec offset as a 2-byte ulint */
- mach_write_to_2(log_ptr, cursor_rec
- - buf_frame_align(cursor_rec));
- log_ptr += 2;
- } else {
- log_ptr = mlog_open(mtr, 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN);
- if (!log_ptr) {
- /* Logging in mtr is switched off during crash
- recovery: in that case mlog_open returns NULL */
- return;
- }
- log_end = &log_ptr[5 + 1 + 5 + 5 + MLOG_BUF_MARGIN];
- }
-
- 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)) {
-
- extra_info_yes = 1;
- } else {
- extra_info_yes = 0;
- }
-
- /* Write the record end segment length and the extra info storage
- flag */
- log_ptr += mach_write_compressed(log_ptr, 2 * (rec_size - i)
- + extra_info_yes);
- if (extra_info_yes) {
- /* Write the info bits */
- mach_write_to_1(log_ptr,
- rec_get_info_and_status_bits(insert_rec,
- comp));
- log_ptr++;
-
- /* Write the record origin offset */
- log_ptr += mach_write_compressed(log_ptr, extra_size);
-
- /* Write the mismatch index */
- log_ptr += mach_write_compressed(log_ptr, i);
-
- ut_a(i < UNIV_PAGE_SIZE);
- ut_a(extra_size < UNIV_PAGE_SIZE);
- }
-
- /* Write to the log the inserted index record end segment which
- differs from the cursor record */
-
- rec_size -= i;
-
- if (log_ptr + rec_size <= log_end) {
- memcpy(log_ptr, ins_ptr, rec_size);
- mlog_close(mtr, log_ptr + rec_size);
- } else {
- mlog_close(mtr, log_ptr);
- ut_a(rec_size < UNIV_PAGE_SIZE);
- mlog_catenate_string(mtr, ins_ptr, rec_size);
- }
-}
-
-/***************************************************************
-Parses a log record of a record insert on a page. */
-
-byte*
-page_cur_parse_insert_rec(
-/*======================*/
- /* out: end of log record or NULL */
- ibool is_short,/* in: TRUE if short inserts */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- dict_index_t* index, /* in: record descriptor */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr) /* in: mtr or NULL */
-{
- ulint extra_info_yes;
- ulint offset = 0; /* remove warning */
- ulint origin_offset;
- ulint end_seg_len;
- ulint mismatch_index;
- rec_t* cursor_rec;
- byte buf1[1024];
- byte* buf;
- byte* ptr2 = ptr;
- ulint info_and_status_bits = 0; /* remove warning */
- page_cur_t cursor;
- mem_heap_t* heap = NULL;
- ulint offsets_[REC_OFFS_NORMAL_SIZE];
- ulint* offsets = offsets_;
- *offsets_ = (sizeof offsets_) / sizeof *offsets_;
-
- if (!is_short) {
- /* Read the cursor rec offset as a 2-byte ulint */
-
- if (end_ptr < ptr + 2) {
-
- return(NULL);
- }
-
- offset = mach_read_from_2(ptr);
-
- if (offset >= UNIV_PAGE_SIZE) {
-
- recv_sys->found_corrupt_log = TRUE;
-
- return(NULL);
- }
-
- ptr += 2;
- }
-
- ptr = mach_parse_compressed(ptr, end_ptr, &end_seg_len);
-
- if (ptr == NULL) {
-
- return(NULL);
- }
-
- extra_info_yes = end_seg_len & 0x1UL;
- end_seg_len >>= 1;
-
- if (end_seg_len >= UNIV_PAGE_SIZE) {
- recv_sys->found_corrupt_log = TRUE;
-
- return(NULL);
- }
-
- if (extra_info_yes) {
- /* Read the info bits */
-
- if (end_ptr < ptr + 1) {
-
- return(NULL);
- }
-
- info_and_status_bits = mach_read_from_1(ptr);
- ptr++;
-
- ptr = mach_parse_compressed(ptr, end_ptr, &origin_offset);
-
- if (ptr == NULL) {
-
- return(NULL);
- }
-
- ut_a(origin_offset < UNIV_PAGE_SIZE);
-
- ptr = mach_parse_compressed(ptr, end_ptr, &mismatch_index);
-
- if (ptr == NULL) {
-
- return(NULL);
- }
-
- ut_a(mismatch_index < UNIV_PAGE_SIZE);
- }
-
- if (end_ptr < ptr + end_seg_len) {
-
- return(NULL);
- }
-
- if (page == NULL) {
-
- return(ptr + end_seg_len);
- }
-
- ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table));
-
- /* Read from the log the inserted index record end segment which
- differs from the cursor record */
-
- if (is_short) {
- cursor_rec = page_rec_get_prev(page_get_supremum_rec(page));
- } else {
- cursor_rec = page + offset;
- }
-
- offsets = rec_get_offsets(cursor_rec, index, offsets,
- ULINT_UNDEFINED, &heap);
-
- if (extra_info_yes == 0) {
- info_and_status_bits = rec_get_info_and_status_bits(
- cursor_rec, page_is_comp(page));
- origin_offset = rec_offs_extra_size(offsets);
- mismatch_index = rec_offs_size(offsets) - end_seg_len;
- }
-
- if (mismatch_index + end_seg_len < sizeof buf1) {
- buf = buf1;
- } else {
- buf = mem_alloc(mismatch_index + end_seg_len);
- }
-
- /* Build the inserted record to buf */
-
- if (mismatch_index >= UNIV_PAGE_SIZE) {
- fprintf(stderr,
- "Is short %lu, info_and_status_bits %lu, offset %lu, "
- "o_offset %lu\n"
- "mismatch index %lu, end_seg_len %lu\n"
- "parsed len %lu\n",
- (ulong) is_short, (ulong) info_and_status_bits,
- (ulong) offset,
- (ulong) origin_offset,
- (ulong) mismatch_index, (ulong) end_seg_len,
- (ulong) (ptr - ptr2));
-
- fputs("Dump of 300 bytes of log:\n", stderr);
- ut_print_buf(stderr, ptr2, 300);
-
- buf_page_print(page);
-
- ut_error;
- }
-
- 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, page_is_comp(page),
- info_and_status_bits);
-
- page_cur_position(cursor_rec, &cursor);
-
- offsets = rec_get_offsets(buf + origin_offset, index, offsets,
- ULINT_UNDEFINED, &heap);
- page_cur_rec_insert(&cursor, buf + origin_offset, index, offsets, mtr);
-
- if (buf != buf1) {
-
- mem_free(buf);
- }
-
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
-
- return(ptr + end_seg_len);
-}
-
-/***************************************************************
-Inserts a record next to page cursor. Returns pointer to inserted record if
-succeed, i.e., enough space available, NULL otherwise. The record to be
-inserted can be in a data tuple or as a physical record. The other parameter
-must then be NULL. The cursor stays at the same position. */
-
-rec_t*
-page_cur_insert_rec_low(
-/*====================*/
- /* out: pointer to record if succeed, NULL
- otherwise */
- page_cur_t* cursor, /* in: a page cursor */
- dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
- dict_index_t* index, /* in: record descriptor */
- rec_t* rec, /* in: pointer to a physical record or NULL */
- ulint* offsets,/* in: rec_get_offsets(rec, index) or NULL */
- mtr_t* mtr) /* in: mini-transaction handle */
-{
- byte* insert_buf = NULL;
- ulint rec_size;
- byte* page; /* the relevant page */
- rec_t* last_insert; /* cursor position at previous
- insert */
- rec_t* insert_rec; /* inserted record */
- ulint heap_no; /* heap number of the inserted
- record */
- rec_t* current_rec; /* current record after which the
- new record is inserted */
- rec_t* next_rec; /* next record after current before
- the insertion */
- ulint owner_slot; /* the slot which owns the
- inserted record */
- rec_t* owner_rec;
- ulint n_owned;
- mem_heap_t* heap = NULL;
- ulint comp;
-
- ut_ad(cursor && mtr);
- ut_ad(tuple || rec);
- ut_ad(!(tuple && rec));
- ut_ad(rec || dtuple_check_typed(tuple));
-
- page = page_cur_get_page(cursor);
- comp = page_is_comp(page);
- ut_ad(dict_table_is_comp(index->table) == !!comp);
-
- ut_ad(cursor->rec != page_get_supremum_rec(page));
-
- /* 1. Get the size of the physical record in the page */
- if (tuple != NULL) {
- rec_size = rec_get_converted_size(index, tuple);
- } else {
- if (!offsets) {
- offsets = rec_get_offsets(rec, index, offsets,
- ULINT_UNDEFINED, &heap);
- }
- ut_ad(rec_offs_validate(rec, index, offsets));
- rec_size = rec_offs_size(offsets);
- }
-
- /* 2. Try to find suitable space from page memory management */
- insert_buf = page_mem_alloc(page, rec_size, index, &heap_no);
-
- if (insert_buf == NULL) {
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- return(NULL);
- }
-
- /* 3. Create the record */
- if (tuple != NULL) {
- insert_rec = rec_convert_dtuple_to_rec(insert_buf,
- index, tuple);
- offsets = rec_get_offsets(insert_rec, index, offsets,
- ULINT_UNDEFINED, &heap);
- } else {
- insert_rec = rec_copy(insert_buf, rec, offsets);
- ut_ad(rec_offs_validate(rec, index, offsets));
- rec_offs_make_valid(insert_rec, index, offsets);
- }
-
- ut_ad(insert_rec);
- ut_ad(rec_size == rec_offs_size(offsets));
-
- /* 4. Insert the record in the linked list of records */
- current_rec = cursor->rec;
-
- ut_ad(!comp || rec_get_status(current_rec) <= REC_STATUS_INFIMUM);
- ut_ad(!comp || rec_get_status(insert_rec) < REC_STATUS_INFIMUM);
-
- next_rec = page_rec_get_next(current_rec);
- ut_ad(!comp || rec_get_status(next_rec) != REC_STATUS_INFIMUM);
- page_rec_set_next(insert_rec, next_rec);
- page_rec_set_next(current_rec, insert_rec);
-
- page_header_set_field(page, PAGE_N_RECS, 1 + page_get_n_recs(page));
-
- /* 5. Set the n_owned field in the inserted record to zero,
- and set the heap_no field */
-
- rec_set_n_owned(insert_rec, comp, 0);
- rec_set_heap_no(insert_rec, comp, heap_no);
-
- /* 6. Update the last insertion info in page header */
-
- last_insert = page_header_get_ptr(page, PAGE_LAST_INSERT);
- ut_ad(!last_insert || !comp
- || rec_get_node_ptr_flag(last_insert)
- == rec_get_node_ptr_flag(insert_rec));
-
- if (last_insert == NULL) {
- page_header_set_field(page, PAGE_DIRECTION, PAGE_NO_DIRECTION);
- page_header_set_field(page, PAGE_N_DIRECTION, 0);
-
- } else if ((last_insert == current_rec)
- && (page_header_get_field(page, PAGE_DIRECTION)
- != PAGE_LEFT)) {
-
- page_header_set_field(page, PAGE_DIRECTION, PAGE_RIGHT);
- page_header_set_field(page, PAGE_N_DIRECTION,
- page_header_get_field(
- page, PAGE_N_DIRECTION) + 1);
-
- } else if ((page_rec_get_next(insert_rec) == last_insert)
- && (page_header_get_field(page, PAGE_DIRECTION)
- != PAGE_RIGHT)) {
-
- page_header_set_field(page, PAGE_DIRECTION, PAGE_LEFT);
- page_header_set_field(page, PAGE_N_DIRECTION,
- page_header_get_field(
- page, PAGE_N_DIRECTION) + 1);
- } else {
- page_header_set_field(page, PAGE_DIRECTION, PAGE_NO_DIRECTION);
- page_header_set_field(page, PAGE_N_DIRECTION, 0);
- }
-
- page_header_set_ptr(page, PAGE_LAST_INSERT, insert_rec);
-
- /* 7. It remains to update the owner record. */
-
- owner_rec = page_rec_find_owner_rec(insert_rec);
- n_owned = rec_get_n_owned(owner_rec, comp);
- rec_set_n_owned(owner_rec, comp, n_owned + 1);
-
- /* 8. Now we have incremented the n_owned field of the owner
- record. If the number exceeds PAGE_DIR_SLOT_MAX_N_OWNED,
- we have to split the corresponding directory slot in two. */
-
- if (n_owned == PAGE_DIR_SLOT_MAX_N_OWNED) {
- owner_slot = page_dir_find_owner_slot(owner_rec);
- page_dir_split_slot(page, owner_slot);
- }
-
- /* 9. Write log record of the insert */
- page_cur_insert_rec_write_log(insert_rec, rec_size, current_rec,
- index, mtr);
-
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- return(insert_rec);
-}
-
-/**************************************************************
-Writes a log record of copying a record list end to a new created page. */
-UNIV_INLINE
-byte*
-page_copy_rec_list_to_created_page_write_log(
-/*=========================================*/
- /* out: 4-byte field where to
- write the log data length */
- page_t* page, /* in: index page */
- dict_index_t* index, /* in: record descriptor */
- mtr_t* mtr) /* in: mtr */
-{
- byte* log_ptr;
-
- ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table));
-
- log_ptr = mlog_open_and_write_index(mtr, page, index,
- page_is_comp(page)
- ? MLOG_COMP_LIST_END_COPY_CREATED
- : MLOG_LIST_END_COPY_CREATED, 4);
- ut_a(log_ptr);
- mlog_close(mtr, log_ptr + 4);
-
- return(log_ptr);
-}
-
-/**************************************************************
-Parses a log record of copying a record list end to a new created page. */
-
-byte*
-page_parse_copy_rec_list_to_created_page(
-/*=====================================*/
- /* 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 */
- mtr_t* mtr) /* in: mtr or NULL */
-{
- byte* rec_end;
- ulint log_data_len;
-
- if (ptr + 4 > end_ptr) {
-
- return(NULL);
- }
-
- log_data_len = mach_read_from_4(ptr);
- ptr += 4;
-
- rec_end = ptr + log_data_len;
-
- if (rec_end > end_ptr) {
-
- return(NULL);
- }
-
- if (!page) {
-
- return(rec_end);
- }
-
- while (ptr < rec_end) {
- ptr = page_cur_parse_insert_rec(TRUE, ptr, end_ptr,
- index, page, mtr);
- }
-
- ut_a(ptr == rec_end);
-
- page_header_set_ptr(page, PAGE_LAST_INSERT, NULL);
- page_header_set_field(page, PAGE_DIRECTION, PAGE_NO_DIRECTION);
- page_header_set_field(page, PAGE_N_DIRECTION, 0);
-
- return(rec_end);
-}
-
-/*****************************************************************
-Copies records from page to a newly created page, from a given record onward,
-including that record. Infimum and supremum records are not copied. */
-
-void
-page_copy_rec_list_end_to_created_page(
-/*===================================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: first record to copy */
- dict_index_t* index, /* in: record descriptor */
- mtr_t* mtr) /* in: mtr */
-{
- page_dir_slot_t* slot = 0; /* remove warning */
- byte* heap_top;
- rec_t* insert_rec = 0; /* remove warning */
- rec_t* prev_rec;
- ulint count;
- ulint n_recs;
- ulint slot_index;
- ulint rec_size;
- ulint log_mode;
- byte* log_ptr;
- ulint log_data_len;
- ulint comp = page_is_comp(page);
- mem_heap_t* heap = NULL;
- ulint offsets_[REC_OFFS_NORMAL_SIZE];
- ulint* offsets = offsets_;
- *offsets_ = (sizeof offsets_) / sizeof *offsets_;
-
- ut_ad(page_dir_get_n_heap(new_page) == 2);
- ut_ad(page != new_page);
- ut_ad(comp == page_is_comp(new_page));
-
- if (rec == page_get_infimum_rec(page)) {
-
- rec = page_rec_get_next(rec);
- }
-
- if (rec == page_get_supremum_rec(page)) {
-
- return;
- }
-
-#ifdef UNIV_DEBUG
- /* To pass the debug tests we have to set these dummy values
- in the debug version */
- page_dir_set_n_slots(new_page, UNIV_PAGE_SIZE / 2);
- page_header_set_ptr(new_page, PAGE_HEAP_TOP,
- new_page + UNIV_PAGE_SIZE - 1);
-#endif
-
- log_ptr = page_copy_rec_list_to_created_page_write_log(new_page,
- index, mtr);
-
- log_data_len = dyn_array_get_data_size(&(mtr->log));
-
- /* Individual inserts are logged in a shorter form */
-
- log_mode = mtr_set_log_mode(mtr, MTR_LOG_SHORT_INSERTS);
-
- prev_rec = page_get_infimum_rec(new_page);
- if (comp) {
- heap_top = new_page + PAGE_NEW_SUPREMUM_END;
- } else {
- heap_top = new_page + PAGE_OLD_SUPREMUM_END;
- }
- count = 0;
- slot_index = 0;
- n_recs = 0;
-
- /* should be do ... until, comment by Jani */
- while (rec != page_get_supremum_rec(page)) {
- offsets = rec_get_offsets(rec, index, offsets,
- ULINT_UNDEFINED, &heap);
- insert_rec = rec_copy(heap_top, rec, offsets);
-
- rec_set_next_offs(prev_rec, comp, insert_rec - new_page);
-
- rec_set_n_owned(insert_rec, comp, 0);
- rec_set_heap_no(insert_rec, comp, 2 + n_recs);
-
- rec_size = rec_offs_size(offsets);
-
- heap_top = heap_top + rec_size;
-
- ut_ad(heap_top < new_page + UNIV_PAGE_SIZE);
-
- count++;
- n_recs++;
-
- if (count == (PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2) {
-
- slot_index++;
-
- slot = page_dir_get_nth_slot(new_page, slot_index);
-
- page_dir_slot_set_rec(slot, insert_rec);
- page_dir_slot_set_n_owned(slot, count);
-
- count = 0;
- }
-
- page_cur_insert_rec_write_log(insert_rec, rec_size, prev_rec,
- index, mtr);
- prev_rec = insert_rec;
- rec = page_rec_get_next(rec);
- }
-
- if ((slot_index > 0) && (count + 1
- + (PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2
- <= PAGE_DIR_SLOT_MAX_N_OWNED)) {
- /* We can merge the two last dir slots. This operation is
- here to make this function imitate exactly the equivalent
- task made using page_cur_insert_rec, which we use in database
- recovery to reproduce the task performed by this function.
- To be able to check the correctness of recovery, it is good
- that it imitates exactly. */
-
- count += (PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2;
-
- page_dir_slot_set_n_owned(slot, 0);
-
- slot_index--;
- }
-
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
-
- log_data_len = dyn_array_get_data_size(&(mtr->log)) - log_data_len;
-
- ut_a(log_data_len < 100 * UNIV_PAGE_SIZE);
-
- mach_write_to_4(log_ptr, log_data_len);
-
- rec_set_next_offs(insert_rec, comp,
- comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM);
-
- slot = page_dir_get_nth_slot(new_page, 1 + slot_index);
-
- page_dir_slot_set_rec(slot, page_get_supremum_rec(new_page));
- page_dir_slot_set_n_owned(slot, count + 1);
-
- page_dir_set_n_slots(new_page, 2 + slot_index);
- page_header_set_ptr(new_page, PAGE_HEAP_TOP, heap_top);
- page_dir_set_n_heap(new_page, 2 + n_recs);
- page_header_set_field(new_page, PAGE_N_RECS, n_recs);
-
- page_header_set_ptr(new_page, PAGE_LAST_INSERT, NULL);
- page_header_set_field(new_page, PAGE_DIRECTION, PAGE_NO_DIRECTION);
- page_header_set_field(new_page, PAGE_N_DIRECTION, 0);
-
- /* Restore the log mode */
-
- mtr_set_log_mode(mtr, log_mode);
-}
-
-/***************************************************************
-Writes log record of a record delete on a page. */
-UNIV_INLINE
-void
-page_cur_delete_rec_write_log(
-/*==========================*/
- rec_t* rec, /* in: record to be deleted */
- dict_index_t* index, /* in: record descriptor */
- mtr_t* mtr) /* in: mini-transaction handle */
-{
- byte* log_ptr;
-
- ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
-
- log_ptr = mlog_open_and_write_index(mtr, rec, index,
- page_rec_is_comp(rec)
- ? MLOG_COMP_REC_DELETE
- : MLOG_REC_DELETE, 2);
-
- if (!log_ptr) {
- /* Logging in mtr is switched off during crash recovery:
- in that case mlog_open returns NULL */
- return;
- }
-
- /* Write the cursor rec offset as a 2-byte ulint */
- mach_write_to_2(log_ptr, page_offset(rec));
-
- mlog_close(mtr, log_ptr + 2);
-}
-
-/***************************************************************
-Parses log record of a record delete on a page. */
-
-byte*
-page_cur_parse_delete_rec(
-/*======================*/
- /* out: pointer to record end 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 */
- mtr_t* mtr) /* in: mtr or NULL */
-{
- ulint offset;
- page_cur_t cursor;
-
- if (end_ptr < ptr + 2) {
-
- return(NULL);
- }
-
- /* Read the cursor rec offset as a 2-byte ulint */
- offset = mach_read_from_2(ptr);
- ptr += 2;
-
- ut_a(offset <= UNIV_PAGE_SIZE);
-
- if (page) {
- mem_heap_t* heap = NULL;
- ulint offsets_[REC_OFFS_NORMAL_SIZE];
- rec_t* rec = page + offset;
- *offsets_ = (sizeof offsets_) / sizeof *offsets_;
-
- page_cur_position(rec, &cursor);
-
- page_cur_delete_rec(&cursor, index,
- rec_get_offsets(rec, index, offsets_,
- ULINT_UNDEFINED, &heap),
- mtr);
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- }
-
- return(ptr);
-}
-
-/***************************************************************
-Deletes a record at the page cursor. The cursor is moved to the next
-record after the deleted one. */
-
-void
-page_cur_delete_rec(
-/*================*/
- page_cur_t* cursor, /* in: a page cursor */
- dict_index_t* index, /* in: record descriptor */
- const ulint* offsets,/* in: rec_get_offsets(cursor->rec, index) */
- mtr_t* mtr) /* in: mini-transaction handle */
-{
- page_dir_slot_t* cur_dir_slot;
- page_dir_slot_t* prev_slot;
- page_t* page;
- rec_t* current_rec;
- rec_t* prev_rec = NULL;
- rec_t* next_rec;
- ulint cur_slot_no;
- ulint cur_n_owned;
- rec_t* rec;
-
- ut_ad(cursor && mtr);
-
- 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) == dict_table_is_comp(index->table));
-
- /* The record must not be the supremum or infimum record. */
- ut_ad(current_rec != page_get_supremum_rec(page));
- ut_ad(current_rec != page_get_infimum_rec(page));
-
- /* Save to local variables some data associated with current_rec */
- cur_slot_no = page_dir_find_owner_slot(current_rec);
- cur_dir_slot = page_dir_get_nth_slot(page, cur_slot_no);
- cur_n_owned = page_dir_slot_get_n_owned(cur_dir_slot);
-
- /* 0. Write the log record */
- page_cur_delete_rec_write_log(current_rec, index, mtr);
-
- /* 1. Reset the last insert info in the page header and increment
- the modify clock for the frame */
-
- page_header_set_ptr(page, PAGE_LAST_INSERT, NULL);
-
- /* The page gets invalid for optimistic searches: increment the
- frame modify clock */
-
- buf_frame_modify_clock_inc(page);
-
- /* 2. Find the next and the previous record. Note that the cursor is
- left at the next record. */
-
- ut_ad(cur_slot_no > 0);
- prev_slot = page_dir_get_nth_slot(page, cur_slot_no - 1);
-
- rec = page_dir_slot_get_rec(prev_slot);
-
- /* rec now points to the record of the previous directory slot. Look
- for the immediate predecessor of current_rec in a loop. */
-
- while(current_rec != rec) {
- prev_rec = rec;
- rec = page_rec_get_next(rec);
- }
-
- page_cur_move_to_next(cursor);
- next_rec = cursor->rec;
-
- /* 3. Remove the record from the linked list of records */
-
- page_rec_set_next(prev_rec, next_rec);
- page_header_set_field(page, PAGE_N_RECS,
- (ulint)(page_get_n_recs(page) - 1));
-
- /* 4. If the deleted record is pointed to by a dir slot, update the
- record pointer in slot. In the following if-clause we assume that
- prev_rec is owned by the same slot, i.e., PAGE_DIR_SLOT_MIN_N_OWNED
- >= 2. */
-
-#if PAGE_DIR_SLOT_MIN_N_OWNED < 2
-# error "PAGE_DIR_SLOT_MIN_N_OWNED < 2"
-#endif
- ut_ad(cur_n_owned > 1);
-
- if (current_rec == page_dir_slot_get_rec(cur_dir_slot)) {
- page_dir_slot_set_rec(cur_dir_slot, prev_rec);
- }
-
- /* 5. Update the number of owned records of the slot */
-
- page_dir_slot_set_n_owned(cur_dir_slot, cur_n_owned - 1);
-
- /* 6. Free the memory occupied by the record */
- page_mem_free(page, current_rec, offsets);
-
- /* 7. Now we have decremented the number of owned records of the slot.
- If the number drops below PAGE_DIR_SLOT_MIN_N_OWNED, we balance the
- slots. */
-
- if (cur_n_owned <= PAGE_DIR_SLOT_MIN_N_OWNED) {
- page_dir_balance_slot(page, cur_slot_no);
- }
-}
-
-#ifdef UNIV_COMPILE_TEST_FUNCS
-
-/***********************************************************************
-Print the first n numbers, generated by page_cur_lcg_prng() to make sure
-(visually) that it works properly. */
-void
-test_page_cur_lcg_prng(
-/*===================*/
- int n) /* in: print first n numbers */
-{
- int i;
- unsigned long long rnd;
-
- for (i = 0; i < n; i++) {
- rnd = page_cur_lcg_prng();
- printf("%llu\t%%2=%llu %%3=%llu %%5=%llu %%7=%llu %%11=%llu\n",
- rnd,
- rnd % 2,
- rnd % 3,
- rnd % 5,
- rnd % 7,
- rnd % 11);
- }
-}
-
-#endif /* UNIV_COMPILE_TEST_FUNCS */