summaryrefslogtreecommitdiff
path: root/storage/xtradb/page/page0cur.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/xtradb/page/page0cur.c')
-rw-r--r--storage/xtradb/page/page0cur.c327
1 files changed, 196 insertions, 131 deletions
diff --git a/storage/xtradb/page/page0cur.c b/storage/xtradb/page/page0cur.c
index e810756c1e4..f10f16a7dd9 100644
--- a/storage/xtradb/page/page0cur.c
+++ b/storage/xtradb/page/page0cur.c
@@ -16,7 +16,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
-/************************************************************************
+/********************************************************************//**
+@file page/page0cur.c
The page cursor
Created 10/4/1994 Heikki Tuuri
@@ -30,40 +31,74 @@ Created 10/4/1994 Heikki Tuuri
#include "page0zip.h"
#include "mtr0log.h"
#include "log0recv.h"
+#include "ut0ut.h"
+#ifndef UNIV_HOTBACKUP
#include "rem0cmp.h"
-static ulint page_rnd = 976722341;
-
#ifdef PAGE_CUR_ADAPT
# ifdef UNIV_SEARCH_PERF_STAT
static ulint page_cur_short_succ = 0;
# endif /* UNIV_SEARCH_PERF_STAT */
-/********************************************************************
-Tries a search shortcut based on the last insert. */
+/*******************************************************************//**
+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_time_us(NULL)
+a = 1103515245 (3^5 * 5 * 7 * 129749)
+c = 12345 (3 * 5 * 823)
+m = 18446744073709551616 (2^64)
+
+@return number between 0 and 2^64-1 */
+static
+ib_uint64_t
+page_cur_lcg_prng(void)
+/*===================*/
+{
+#define LCG_a 1103515245
+#define LCG_c 12345
+ static ib_uint64_t lcg_current = 0;
+ static ibool initialized = FALSE;
+
+ if (!initialized) {
+ lcg_current = (ib_uint64_t) ut_time_us(NULL);
+ 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.
+@return TRUE on success */
UNIV_INLINE
ibool
page_cur_try_search_shortcut(
/*=========================*/
- /* out: TRUE on success */
- const buf_block_t* block, /* in: index page */
- const dict_index_t* index, /* in: record descriptor */
- const dtuple_t* tuple, /* in: data tuple */
+ const buf_block_t* block, /*!< in: index page */
+ const dict_index_t* index, /*!< in: record descriptor */
+ const dtuple_t* tuple, /*!< in: data tuple */
ulint* iup_matched_fields,
- /* in/out: already matched
+ /*!< in/out: already matched
fields in upper limit record */
ulint* iup_matched_bytes,
- /* in/out: already matched
+ /*!< in/out: already matched
bytes in a field not yet
completely matched */
ulint* ilow_matched_fields,
- /* in/out: already matched
+ /*!< in/out: already matched
fields in lower limit record */
ulint* ilow_matched_bytes,
- /* in/out: already matched
+ /*!< in/out: already matched
bytes in a field not yet
completely matched */
- page_cur_t* cursor) /* out: page cursor */
+ page_cur_t* cursor) /*!< out: page cursor */
{
const rec_t* rec;
const rec_t* next_rec;
@@ -154,20 +189,19 @@ exit_func:
#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. */
+common first characters.
+@return TRUE if rec field extends tuple field */
static
ibool
page_cur_rec_field_extends(
/*=======================*/
- /* out: TRUE if rec field
- extends tuple field */
- const dtuple_t* tuple, /* in: data tuple */
- const rec_t* rec, /* in: record */
- const ulint* offsets,/* in: array returned by rec_get_offsets() */
- ulint n) /* in: compare nth field */
+ const dtuple_t* tuple, /*!< in: data tuple */
+ const rec_t* rec, /*!< in: record */
+ const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
+ ulint n) /*!< in: compare nth field */
{
const dtype_t* type;
const dfield_t* dfield;
@@ -205,33 +239,33 @@ page_cur_rec_field_extends(
}
#endif /* PAGE_CUR_LE_OR_EXTENDS */
-/********************************************************************
+/****************************************************************//**
Searches the right position for a page cursor. */
UNIV_INTERN
void
page_cur_search_with_match(
/*=======================*/
- const buf_block_t* block, /* in: buffer block */
- const dict_index_t* index, /* in: record descriptor */
- const dtuple_t* tuple, /* in: data tuple */
- ulint mode, /* in: PAGE_CUR_L,
+ const buf_block_t* block, /*!< in: buffer block */
+ const dict_index_t* index, /*!< in: record descriptor */
+ const 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
+ /*!< in/out: already matched
fields in upper limit record */
ulint* iup_matched_bytes,
- /* in/out: already matched
+ /*!< in/out: already matched
bytes in a field not yet
completely matched */
ulint* ilow_matched_fields,
- /* in/out: already matched
+ /*!< in/out: already matched
fields in lower limit record */
ulint* ilow_matched_bytes,
- /* in/out: already matched
+ /*!< in/out: already matched
bytes in a field not yet
completely matched */
- page_cur_t* cursor) /* out: page cursor */
+ page_cur_t* cursor) /*!< out: page cursor */
{
ulint up;
ulint low;
@@ -503,15 +537,15 @@ up_rec_match:
}
}
-/***************************************************************
+/***********************************************************//**
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. */
UNIV_INTERN
void
page_cur_open_on_rnd_user_rec(
/*==========================*/
- buf_block_t* block, /* in: page */
- page_cur_t* cursor) /* out: page cursor */
+ buf_block_t* block, /*!< in: page */
+ page_cur_t* cursor) /*!< out: page cursor */
{
ulint rnd;
ulint n_recs = page_get_n_recs(buf_block_get_frame(block));
@@ -523,27 +557,25 @@ page_cur_open_on_rnd_user_rec(
return;
}
- page_rnd += 87584577;
-
- rnd = page_rnd % n_recs;
+ rnd = (ulint) (page_cur_lcg_prng() % n_recs);
do {
page_cur_move_to_next(cursor);
} while (rnd--);
}
-/***************************************************************
+/***********************************************************//**
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
+ 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 */
+ dict_index_t* index, /*!< in: record descriptor */
+ mtr_t* mtr) /*!< in: mini-transaction handle */
{
ulint cur_rec_size;
ulint extra_size;
@@ -713,20 +745,23 @@ need_extra_info:
mlog_catenate_string(mtr, ins_ptr, rec_size);
}
}
+#else /* !UNIV_HOTBACKUP */
+# define page_cur_insert_rec_write_log(ins_rec,size,cur,index,mtr) ((void) 0)
+#endif /* !UNIV_HOTBACKUP */
-/***************************************************************
-Parses a log record of a record insert on a page. */
+/***********************************************************//**
+Parses a log record of a record insert on a page.
+@return end of log record or NULL */
UNIV_INTERN
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 */
- buf_block_t* block, /* in: page or NULL */
- dict_index_t* index, /* in: record descriptor */
- mtr_t* mtr) /* in: mtr or NULL */
+ ibool is_short,/*!< in: TRUE if short inserts */
+ byte* ptr, /*!< in: buffer */
+ byte* end_ptr,/*!< in: buffer end */
+ buf_block_t* block, /*!< in: page or NULL */
+ dict_index_t* index, /*!< in: record descriptor */
+ mtr_t* mtr) /*!< in: mtr or NULL */
{
ulint origin_offset;
ulint end_seg_len;
@@ -905,32 +940,31 @@ page_cur_parse_insert_rec(
return(ptr + end_seg_len);
}
-/***************************************************************
+/***********************************************************//**
Inserts a record next to page cursor on an uncompressed page.
Returns pointer to inserted record if succeed, i.e., enough
-space available, NULL otherwise. The cursor stays at the same position. */
+space available, NULL otherwise. The cursor stays at the same position.
+@return pointer to record if succeed, NULL otherwise */
UNIV_INTERN
rec_t*
page_cur_insert_rec_low(
/*====================*/
- /* out: pointer to record if succeed, NULL
- otherwise */
- rec_t* current_rec,/* in: pointer to current record after
+ rec_t* current_rec,/*!< in: pointer to current record after
which the new record is inserted */
- dict_index_t* index, /* in: record descriptor */
- const rec_t* rec, /* in: pointer to a physical record */
- ulint* offsets,/* in/out: rec_get_offsets(rec, index) */
- mtr_t* mtr) /* in: mini-transaction handle, or NULL */
+ dict_index_t* index, /*!< in: record descriptor */
+ const rec_t* rec, /*!< in: pointer to a physical record */
+ ulint* offsets,/*!< in/out: rec_get_offsets(rec, index) */
+ mtr_t* mtr) /*!< in: mini-transaction handle, or NULL */
{
byte* insert_buf;
ulint rec_size;
- page_t* page; /* the relevant page */
- rec_t* last_insert; /* cursor position at previous
+ page_t* page; /*!< the relevant page */
+ rec_t* last_insert; /*!< cursor position at previous
insert */
- rec_t* free_rec; /* a free record that was reused,
+ rec_t* free_rec; /*!< a free record that was reused,
or NULL */
- rec_t* insert_rec; /* inserted record */
- ulint heap_no; /* heap number of the inserted
+ rec_t* insert_rec; /*!< inserted record */
+ ulint heap_no; /*!< heap number of the inserted
record */
ut_ad(rec_offs_validate(rec, index, offsets));
@@ -1118,21 +1152,21 @@ use_heap:
return(insert_rec);
}
-/***************************************************************
-Compresses or reorganizes a page after an optimistic insert. */
+/***********************************************************//**
+Compresses or reorganizes a page after an optimistic insert.
+@return rec if succeed, NULL otherwise */
static
rec_t*
page_cur_insert_rec_zip_reorg(
/*==========================*/
- /* out: rec if succeed, NULL otherwise */
- rec_t** current_rec,/* in/out: pointer to current record after
+ rec_t** current_rec,/*!< in/out: pointer to current record after
which the new record is inserted */
- buf_block_t* block, /* in: buffer block */
- dict_index_t* index, /* in: record descriptor */
- rec_t* rec, /* in: inserted record */
- page_t* page, /* in: uncompressed page */
- page_zip_des_t* page_zip,/* in: compressed page */
- mtr_t* mtr) /* in: mini-transaction, or NULL */
+ buf_block_t* block, /*!< in: buffer block */
+ dict_index_t* index, /*!< in: record descriptor */
+ rec_t* rec, /*!< in: inserted record */
+ page_t* page, /*!< in: uncompressed page */
+ page_zip_des_t* page_zip,/*!< in: compressed page */
+ mtr_t* mtr) /*!< in: mini-transaction, or NULL */
{
ulint pos;
@@ -1161,41 +1195,40 @@ page_cur_insert_rec_zip_reorg(
}
/* Out of space: restore the page */
- if (!page_zip_decompress(page_zip, page)) {
+ if (!page_zip_decompress(page_zip, page, FALSE)) {
ut_error; /* Memory corrupted? */
}
ut_ad(page_validate(page, index));
return(NULL);
}
-/***************************************************************
+/***********************************************************//**
Inserts a record next to page cursor on a compressed and uncompressed
page. Returns pointer to inserted record if succeed, i.e.,
enough space available, NULL otherwise.
-The cursor stays at the same position. */
+The cursor stays at the same position.
+@return pointer to record if succeed, NULL otherwise */
UNIV_INTERN
rec_t*
page_cur_insert_rec_zip(
/*====================*/
- /* out: pointer to record if succeed, NULL
- otherwise */
- rec_t** current_rec,/* in/out: pointer to current record after
+ rec_t** current_rec,/*!< in/out: pointer to current record after
which the new record is inserted */
- buf_block_t* block, /* in: buffer block of *current_rec */
- dict_index_t* index, /* in: record descriptor */
- const rec_t* rec, /* in: pointer to a physical record */
- ulint* offsets,/* in/out: rec_get_offsets(rec, index) */
- mtr_t* mtr) /* in: mini-transaction handle, or NULL */
+ buf_block_t* block, /*!< in: buffer block of *current_rec */
+ dict_index_t* index, /*!< in: record descriptor */
+ const rec_t* rec, /*!< in: pointer to a physical record */
+ ulint* offsets,/*!< in/out: rec_get_offsets(rec, index) */
+ mtr_t* mtr) /*!< in: mini-transaction handle, or NULL */
{
byte* insert_buf;
ulint rec_size;
- page_t* page; /* the relevant page */
- rec_t* last_insert; /* cursor position at previous
+ page_t* page; /*!< the relevant page */
+ rec_t* last_insert; /*!< cursor position at previous
insert */
- rec_t* free_rec; /* a free record that was reused,
+ rec_t* free_rec; /*!< a free record that was reused,
or NULL */
- rec_t* insert_rec; /* inserted record */
- ulint heap_no; /* heap number of the inserted
+ rec_t* insert_rec; /*!< inserted record */
+ ulint heap_no; /*!< heap number of the inserted
record */
page_zip_des_t* page_zip;
@@ -1466,18 +1499,18 @@ use_heap:
return(insert_rec);
}
-/**************************************************************
-Writes a log record of copying a record list end to a new created page. */
+#ifndef UNIV_HOTBACKUP
+/**********************************************************//**
+Writes a log record of copying a record list end to a new created page.
+@return 4-byte field where to write the log data length, or NULL if
+logging is disabled */
UNIV_INLINE
byte*
page_copy_rec_list_to_created_page_write_log(
/*=========================================*/
- /* out: 4-byte field where to
- write the log data length,
- or NULL if logging is disabled */
- page_t* page, /* in: index page */
- dict_index_t* index, /* in: record descriptor */
- mtr_t* mtr) /* in: mtr */
+ page_t* page, /*!< in: index page */
+ dict_index_t* index, /*!< in: record descriptor */
+ mtr_t* mtr) /*!< in: mtr */
{
byte* log_ptr;
@@ -1493,19 +1526,20 @@ page_copy_rec_list_to_created_page_write_log(
return(log_ptr);
}
+#endif /* !UNIV_HOTBACKUP */
-/**************************************************************
-Parses a log record of copying a record list end to a new created page. */
+/**********************************************************//**
+Parses a log record of copying a record list end to a new created page.
+@return end of log record or NULL */
UNIV_INTERN
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 */
- buf_block_t* block, /* in: page or NULL */
- dict_index_t* index, /* in: record descriptor */
- mtr_t* mtr) /* in: mtr or NULL */
+ byte* ptr, /*!< in: buffer */
+ byte* end_ptr,/*!< in: buffer end */
+ buf_block_t* block, /*!< in: page or NULL */
+ dict_index_t* index, /*!< in: record descriptor */
+ mtr_t* mtr) /*!< in: mtr or NULL */
{
byte* rec_end;
ulint log_data_len;
@@ -1550,17 +1584,18 @@ page_parse_copy_rec_list_to_created_page(
return(rec_end);
}
-/*****************************************************************
+#ifndef UNIV_HOTBACKUP
+/*************************************************************//**
Copies records from page to a newly created page, from a given record onward,
including that record. Infimum and supremum records are not copied. */
UNIV_INTERN
void
page_copy_rec_list_end_to_created_page(
/*===================================*/
- page_t* new_page, /* in/out: index page to copy to */
- rec_t* rec, /* in: first record to copy */
- dict_index_t* index, /* in: record descriptor */
- mtr_t* mtr) /* in: mtr */
+ page_t* new_page, /*!< in/out: index page to copy to */
+ 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;
@@ -1723,15 +1758,15 @@ page_copy_rec_list_end_to_created_page(
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 */
+ 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;
@@ -1753,19 +1788,22 @@ page_cur_delete_rec_write_log(
mlog_close(mtr, log_ptr + 2);
}
+#else /* !UNIV_HOTBACKUP */
+# define page_cur_delete_rec_write_log(rec,index,mtr) ((void) 0)
+#endif /* !UNIV_HOTBACKUP */
-/***************************************************************
-Parses log record of a record delete on a page. */
+/***********************************************************//**
+Parses log record of a record delete on a page.
+@return pointer to record end or NULL */
UNIV_INTERN
byte*
page_cur_parse_delete_rec(
/*======================*/
- /* out: pointer to record end or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- buf_block_t* block, /* in: page or NULL */
- dict_index_t* index, /* in: record descriptor */
- mtr_t* mtr) /* in: mtr or NULL */
+ byte* ptr, /*!< in: buffer */
+ byte* end_ptr,/*!< in: buffer end */
+ buf_block_t* block, /*!< in: page or NULL */
+ dict_index_t* index, /*!< in: record descriptor */
+ mtr_t* mtr) /*!< in: mtr or NULL */
{
ulint offset;
page_cur_t cursor;
@@ -1803,17 +1841,17 @@ page_cur_parse_delete_rec(
return(ptr);
}
-/***************************************************************
+/***********************************************************//**
Deletes a record at the page cursor. The cursor is moved to the next
record after the deleted one. */
UNIV_INTERN
void
page_cur_delete_rec(
/*================*/
- page_cur_t* cursor, /* in/out: 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_cur_t* cursor, /*!< in/out: 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;
@@ -1920,3 +1958,30 @@ page_cur_delete_rec(
ut_a(!page_zip || page_zip_validate(page_zip, page));
#endif /* UNIV_ZIP_DEBUG */
}
+
+#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 */