diff options
Diffstat (limited to 'storage/xtradb/page/page0cur.c')
-rw-r--r-- | storage/xtradb/page/page0cur.c | 325 |
1 files changed, 195 insertions, 130 deletions
diff --git a/storage/xtradb/page/page0cur.c b/storage/xtradb/page/page0cur.c index e810756c1e4..65f3ba67439 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; @@ -1168,34 +1202,33 @@ page_cur_insert_rec_zip_reorg( 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 */ |