diff options
author | unknown <knielsen@knielsen-hq.org> | 2009-11-13 22:26:08 +0100 |
---|---|---|
committer | unknown <knielsen@knielsen-hq.org> | 2009-11-13 22:26:08 +0100 |
commit | 898f6f48b79d1f2c334fb559225b2b0fade5ea93 (patch) | |
tree | 84df8eecd942b650f172cbd67050ee8984c0d52b /storage/xtradb/page | |
parent | 275c0a7f96502b33f763fb9388dcc1c289e4792b (diff) | |
parent | 2bde0c5e6d31583e5197e3b513f572a693161f62 (diff) | |
download | mariadb-git-898f6f48b79d1f2c334fb559225b2b0fade5ea93.tar.gz |
Merge XtraDB 8 into MariaDB.
Diffstat (limited to 'storage/xtradb/page')
-rw-r--r-- | storage/xtradb/page/page0cur.c | 325 | ||||
-rw-r--r-- | storage/xtradb/page/page0page.c | 480 | ||||
-rw-r--r-- | storage/xtradb/page/page0zip.c | 847 |
3 files changed, 905 insertions, 747 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 */ diff --git a/storage/xtradb/page/page0page.c b/storage/xtradb/page/page0page.c index 0ce532068ce..f056ef77bdc 100644 --- a/storage/xtradb/page/page0page.c +++ b/storage/xtradb/page/page0page.c @@ -16,7 +16,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA *****************************************************************************/ -/****************************************************** +/**************************************************//** +@file page/page0page.c Index page routines Created 2/2/1994 Heikki Tuuri @@ -31,12 +32,14 @@ Created 2/2/1994 Heikki Tuuri #include "page0cur.h" #include "page0zip.h" -#include "lock0lock.h" -#include "fut0lst.h" -#include "btr0sea.h" #include "buf0buf.h" -#include "srv0srv.h" #include "btr0btr.h" +#ifndef UNIV_HOTBACKUP +# include "srv0srv.h" +# include "lock0lock.h" +# include "fut0lst.h" +# include "btr0sea.h" +#endif /* !UNIV_HOTBACKUP */ /* THE INDEX PAGE ============== @@ -80,14 +83,14 @@ Assuming a page size of 8 kB, a typical index page of a secondary index contains 300 index entries, and the size of the page directory is 50 x 4 bytes = 200 bytes. */ -/******************************************************************* -Looks for the directory slot which owns the given record. */ +/***************************************************************//** +Looks for the directory slot which owns the given record. +@return the directory slot number */ UNIV_INTERN ulint page_dir_find_owner_slot( /*=====================*/ - /* out: the directory slot number */ - const rec_t* rec) /* in: the physical record */ + const rec_t* rec) /*!< in: the physical record */ { const page_t* page; register uint16 rec_offs_bytes; @@ -156,14 +159,14 @@ page_dir_find_owner_slot( return(((ulint) (first_slot - slot)) / PAGE_DIR_SLOT_SIZE); } -/****************************************************************** -Used to check the consistency of a directory slot. */ +/**************************************************************//** +Used to check the consistency of a directory slot. +@return TRUE if succeed */ static ibool page_dir_slot_check( /*================*/ - /* out: TRUE if succeed */ - page_dir_slot_t* slot) /* in: slot */ + page_dir_slot_t* slot) /*!< in: slot */ { page_t* page; ulint n_slots; @@ -199,53 +202,66 @@ page_dir_slot_check( return(TRUE); } -/***************************************************************** +/*************************************************************//** Sets the max trx id field value. */ UNIV_INTERN void page_set_max_trx_id( /*================*/ - buf_block_t* block, /* in/out: page */ - page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */ - dulint trx_id) /* in: transaction id */ + buf_block_t* block, /*!< in/out: page */ + page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ + trx_id_t trx_id, /*!< in: transaction id */ + mtr_t* mtr) /*!< in/out: mini-transaction, or NULL */ { - const ibool is_hashed = block->is_hashed; page_t* page = buf_block_get_frame(block); +#ifndef UNIV_HOTBACKUP + const ibool is_hashed = block->is_hashed; if (is_hashed) { rw_lock_x_lock(&btr_search_latch); } + ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); +#endif /* !UNIV_HOTBACKUP */ + /* It is not necessary to write this change to the redo log, as during a database recovery we assume that the max trx id of every page is the maximum trx id assigned before the crash. */ - mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id); if (UNIV_LIKELY_NULL(page_zip)) { + mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id); page_zip_write_header(page_zip, page + (PAGE_HEADER + PAGE_MAX_TRX_ID), - 8, NULL); + 8, mtr); +#ifndef UNIV_HOTBACKUP + } else if (mtr) { + mlog_write_dulint(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), + trx_id, mtr); +#endif /* !UNIV_HOTBACKUP */ + } else { + mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id); } +#ifndef UNIV_HOTBACKUP if (is_hashed) { rw_lock_x_unlock(&btr_search_latch); } +#endif /* !UNIV_HOTBACKUP */ } -/**************************************************************** -Allocates a block of memory from the heap of an index page. */ +/************************************************************//** +Allocates a block of memory from the heap of an index page. +@return pointer to start of allocated buffer, or NULL if allocation fails */ UNIV_INTERN byte* page_mem_alloc_heap( /*================*/ - /* out: pointer to start of allocated - buffer, or NULL if allocation fails */ - page_t* page, /* in/out: index page */ - page_zip_des_t* page_zip,/* in/out: compressed page with enough + page_t* page, /*!< in/out: index page */ + page_zip_des_t* page_zip,/*!< in/out: compressed page with enough space available for inserting the record, or NULL */ - ulint need, /* in: total number of bytes needed */ - ulint* heap_no)/* out: this contains the heap number + ulint need, /*!< in: total number of bytes needed */ + ulint* heap_no)/*!< out: this contains the heap number of the allocated record if allocation succeeds */ { @@ -271,34 +287,38 @@ page_mem_alloc_heap( return(NULL); } -/************************************************************** +#ifndef UNIV_HOTBACKUP +/**********************************************************//** Writes a log record of page creation. */ UNIV_INLINE void page_create_write_log( /*==================*/ - buf_frame_t* frame, /* in: a buffer frame where the page is + buf_frame_t* frame, /*!< in: a buffer frame where the page is created */ - mtr_t* mtr, /* in: mini-transaction handle */ - ibool comp) /* in: TRUE=compact page format */ + mtr_t* mtr, /*!< in: mini-transaction handle */ + ibool comp) /*!< in: TRUE=compact page format */ { mlog_write_initial_log_record(frame, comp ? MLOG_COMP_PAGE_CREATE : MLOG_PAGE_CREATE, mtr); } +#else /* !UNIV_HOTBACKUP */ +# define page_create_write_log(frame,mtr,comp) ((void) 0) +#endif /* !UNIV_HOTBACKUP */ -/*************************************************************** -Parses a redo log record of creating a page. */ +/***********************************************************//** +Parses a redo log record of creating a page. +@return end of log record or NULL */ UNIV_INTERN byte* page_parse_create( /*==============*/ - /* out: end of log record or NULL */ - byte* ptr, /* in: buffer */ - byte* end_ptr __attribute__((unused)), /* in: buffer end */ - ulint comp, /* in: nonzero=compact page format */ - buf_block_t* block, /* in: block or NULL */ - mtr_t* mtr) /* in: mtr or NULL */ + byte* ptr, /*!< in: buffer */ + byte* end_ptr __attribute__((unused)), /*!< in: buffer end */ + ulint comp, /*!< in: nonzero=compact page format */ + buf_block_t* block, /*!< in: block or NULL */ + mtr_t* mtr) /*!< in: mtr or NULL */ { ut_ad(ptr && end_ptr); @@ -311,16 +331,16 @@ page_parse_create( return(ptr); } -/************************************************************** -The index page creation function. */ +/**********************************************************//** +The index page creation function. +@return pointer to the page */ static page_t* page_create_low( /*============*/ - /* out: pointer to the page */ - buf_block_t* block, /* in: a buffer block where the + buf_block_t* block, /*!< in: a buffer block where the page is created */ - ulint comp) /* in: nonzero=compact page format */ + ulint comp) /*!< in: nonzero=compact page format */ { page_dir_slot_t* slot; mem_heap_t* heap; @@ -343,9 +363,9 @@ page_create_low( /* The infimum and supremum records use a dummy index. */ if (UNIV_LIKELY(comp)) { - index = srv_sys->dummy_ind2; + index = dict_ind_compact; } else { - index = srv_sys->dummy_ind1; + index = dict_ind_redundant; } /* 1. INCREMENT MODIFY CLOCK */ @@ -437,7 +457,7 @@ page_create_low( page_header_set_field(page, NULL, PAGE_DIRECTION, PAGE_NO_DIRECTION); page_header_set_field(page, NULL, PAGE_N_DIRECTION, 0); page_header_set_field(page, NULL, PAGE_N_RECS, 0); - page_set_max_trx_id(block, NULL, ut_dulint_zero); + page_set_max_trx_id(block, NULL, ut_dulint_zero, NULL); memset(heap_top, 0, UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START - page_offset(heap_top)); @@ -464,34 +484,34 @@ page_create_low( return(page); } -/************************************************************** -Create an uncompressed B-tree index page. */ +/**********************************************************//** +Create an uncompressed B-tree index page. +@return pointer to the page */ UNIV_INTERN page_t* page_create( /*========*/ - /* out: pointer to the page */ - buf_block_t* block, /* in: a buffer block where the + buf_block_t* block, /*!< in: a buffer block where the page is created */ - mtr_t* mtr, /* in: mini-transaction handle */ - ulint comp) /* in: nonzero=compact page format */ + mtr_t* mtr, /*!< in: mini-transaction handle */ + ulint comp) /*!< in: nonzero=compact page format */ { page_create_write_log(buf_block_get_frame(block), mtr, comp); return(page_create_low(block, comp)); } -/************************************************************** -Create a compressed B-tree index page. */ +/**********************************************************//** +Create a compressed B-tree index page. +@return pointer to the page */ UNIV_INTERN page_t* page_create_zip( /*============*/ - /* out: pointer to the page */ - buf_block_t* block, /* in/out: a buffer frame where the + buf_block_t* block, /*!< in/out: a buffer frame where the page is created */ - dict_index_t* index, /* in: the index of the page */ - ulint level, /* in: the B-tree level of the page */ - mtr_t* mtr) /* in: mini-transaction handle */ + dict_index_t* index, /*!< in: the index of the page */ + ulint level, /*!< in: the B-tree level of the page */ + mtr_t* mtr) /*!< in: mini-transaction handle */ { page_t* page; page_zip_des_t* page_zip = buf_block_get_page_zip(block); @@ -513,18 +533,18 @@ page_create_zip( return(page); } -/***************************************************************** +/*************************************************************//** Differs from page_copy_rec_list_end, because this function does not touch the lock table and max trx id on page or compress the page. */ UNIV_INTERN void page_copy_rec_list_end_no_locks( /*============================*/ - buf_block_t* new_block, /* in: index page to copy to */ - buf_block_t* block, /* in: index page of rec */ - rec_t* rec, /* in: record on page */ - dict_index_t* index, /* in: record descriptor */ - mtr_t* mtr) /* in: mtr */ + buf_block_t* new_block, /*!< in: index page to copy to */ + buf_block_t* block, /*!< in: index page of rec */ + rec_t* rec, /*!< in: record on page */ + dict_index_t* index, /*!< in: record descriptor */ + mtr_t* mtr) /*!< in: mtr */ { page_t* new_page = buf_block_get_frame(new_block); page_cur_t cur1; @@ -584,23 +604,22 @@ page_copy_rec_list_end_no_locks( } } -/***************************************************************** +#ifndef UNIV_HOTBACKUP +/*************************************************************//** Copies records from page to new_page, from a given record onward, including that record. Infimum and supremum records are not copied. -The records are copied to the start of the record list on new_page. */ +The records are copied to the start of the record list on new_page. +@return pointer to the original successor of the infimum record on +new_page, or NULL on zip overflow (new_block will be decompressed) */ UNIV_INTERN rec_t* page_copy_rec_list_end( /*===================*/ - /* out: pointer to the original - successor of the infimum record - on new_page, or NULL on zip overflow - (new_block will be decompressed) */ - buf_block_t* new_block, /* in/out: index page to copy to */ - buf_block_t* block, /* in: index page containing rec */ - rec_t* rec, /* in: record on page */ - dict_index_t* index, /* in: record descriptor */ - mtr_t* mtr) /* in: mtr */ + buf_block_t* new_block, /*!< in/out: index page to copy to */ + buf_block_t* block, /*!< in: index page containing rec */ + rec_t* rec, /*!< in: record on page */ + dict_index_t* index, /*!< in: record descriptor */ + mtr_t* mtr) /*!< in: mtr */ { page_t* new_page = buf_block_get_frame(new_block); page_zip_des_t* new_page_zip = buf_block_get_page_zip(new_block); @@ -681,31 +700,31 @@ page_copy_rec_list_end( lock_move_rec_list_end(new_block, block, rec); - page_update_max_trx_id(new_block, new_page_zip, - page_get_max_trx_id(page)); + if (dict_index_is_sec_or_ibuf(index) && page_is_leaf(page)) { + page_update_max_trx_id(new_block, new_page_zip, + page_get_max_trx_id(page), mtr); + } btr_search_move_or_delete_hash_entries(new_block, block, index); return(ret); } -/***************************************************************** +/*************************************************************//** Copies records from page to new_page, up to the given record, NOT including that record. Infimum and supremum records are not copied. -The records are copied to the end of the record list on new_page. */ +The records are copied to the end of the record list on new_page. +@return pointer to the original predecessor of the supremum record on +new_page, or NULL on zip overflow (new_block will be decompressed) */ UNIV_INTERN rec_t* page_copy_rec_list_start( /*=====================*/ - /* out: pointer to the original - predecessor of the supremum record - on new_page, or NULL on zip overflow - (new_block will be decompressed) */ - buf_block_t* new_block, /* in/out: index page to copy to */ - buf_block_t* block, /* in: index page containing rec */ - rec_t* rec, /* in: record on page */ - dict_index_t* index, /* in: record descriptor */ - mtr_t* mtr) /* in: mtr */ + buf_block_t* new_block, /*!< in/out: index page to copy to */ + buf_block_t* block, /*!< in: index page containing rec */ + rec_t* rec, /*!< in: record on page */ + dict_index_t* index, /*!< in: record descriptor */ + mtr_t* mtr) /*!< in: mtr */ { page_t* new_page = buf_block_get_frame(new_block); page_zip_des_t* new_page_zip = buf_block_get_page_zip(new_block); @@ -792,8 +811,12 @@ page_copy_rec_list_start( /* Update MAX_TRX_ID, the lock table, and possible hash index */ - page_update_max_trx_id(new_block, new_page_zip, - page_get_max_trx_id(page_align(rec))); + if (dict_index_is_sec_or_ibuf(index) + && page_is_leaf(page_align(rec))) { + page_update_max_trx_id(new_block, new_page_zip, + page_get_max_trx_id(page_align(rec)), + mtr); + } lock_move_rec_list_start(new_block, block, rec, ret); @@ -802,17 +825,17 @@ page_copy_rec_list_start( return(ret); } -/************************************************************** +/**********************************************************//** Writes a log record of a record list end or start deletion. */ UNIV_INLINE void page_delete_rec_list_write_log( /*===========================*/ - rec_t* rec, /* in: record on page */ - dict_index_t* index, /* in: record descriptor */ - byte type, /* in: operation type: + rec_t* rec, /*!< in: record on page */ + dict_index_t* index, /*!< in: record descriptor */ + byte type, /*!< in: operation type: MLOG_LIST_END_DELETE, ... */ - mtr_t* mtr) /* in: mtr */ + mtr_t* mtr) /*!< in: mtr */ { byte* log_ptr; ut_ad(type == MLOG_LIST_END_DELETE @@ -827,23 +850,26 @@ page_delete_rec_list_write_log( mlog_close(mtr, log_ptr + 2); } } +#else /* !UNIV_HOTBACKUP */ +# define page_delete_rec_list_write_log(rec,index,type,mtr) ((void) 0) +#endif /* !UNIV_HOTBACKUP */ -/************************************************************** -Parses a log record of a record list end or start deletion. */ +/**********************************************************//** +Parses a log record of a record list end or start deletion. +@return end of log record or NULL */ UNIV_INTERN byte* page_parse_delete_rec_list( /*=======================*/ - /* out: end of log record or NULL */ - byte type, /* in: MLOG_LIST_END_DELETE, + byte type, /*!< in: MLOG_LIST_END_DELETE, MLOG_LIST_START_DELETE, MLOG_COMP_LIST_END_DELETE or MLOG_COMP_LIST_START_DELETE */ - byte* ptr, /* in: buffer */ - byte* end_ptr,/* in: buffer end */ - buf_block_t* block, /* in/out: buffer block 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/out: buffer block or NULL */ + dict_index_t* index, /*!< in: record descriptor */ + mtr_t* mtr) /*!< in: mtr or NULL */ { page_t* page; ulint offset; @@ -884,22 +910,22 @@ page_parse_delete_rec_list( return(ptr); } -/***************************************************************** +/*************************************************************//** Deletes records from a page from a given record onward, including that record. The infimum and supremum records are not deleted. */ UNIV_INTERN void page_delete_rec_list_end( /*=====================*/ - rec_t* rec, /* in: pointer to record on page */ - buf_block_t* block, /* in: buffer block of the page */ - dict_index_t* index, /* in: record descriptor */ - ulint n_recs, /* in: number of records to delete, + rec_t* rec, /*!< in: pointer to record on page */ + buf_block_t* block, /*!< in: buffer block of the page */ + dict_index_t* index, /*!< in: record descriptor */ + ulint n_recs, /*!< in: number of records to delete, or ULINT_UNDEFINED if not known */ - ulint size, /* in: the sum of the sizes of the + ulint size, /*!< in: the sum of the sizes of the records in the end of the chain to delete, or ULINT_UNDEFINED if not known */ - mtr_t* mtr) /* in: mtr */ + mtr_t* mtr) /*!< in: mtr */ { page_dir_slot_t*slot; ulint slot_index; @@ -1060,17 +1086,17 @@ page_delete_rec_list_end( (ulint)(page_get_n_recs(page) - n_recs)); } -/***************************************************************** +/*************************************************************//** Deletes records from page, up to the given record, NOT including that record. Infimum and supremum records are not deleted. */ UNIV_INTERN void page_delete_rec_list_start( /*=======================*/ - rec_t* rec, /* in: record on page */ - buf_block_t* block, /* in: buffer block of the page */ - dict_index_t* index, /* in: record descriptor */ - mtr_t* mtr) /* in: mtr */ + rec_t* rec, /*!< in: record on page */ + buf_block_t* block, /*!< in: buffer block of the page */ + dict_index_t* index, /*!< in: record descriptor */ + mtr_t* mtr) /*!< in: mtr */ { page_cur_t cur1; ulint log_mode; @@ -1132,21 +1158,21 @@ page_delete_rec_list_start( mtr_set_log_mode(mtr, log_mode); } -/***************************************************************** +#ifndef UNIV_HOTBACKUP +/*************************************************************//** Moves record list end to another page. Moved records include -split_rec. */ +split_rec. +@return TRUE on success; FALSE on compression failure (new_block will +be decompressed) */ UNIV_INTERN ibool page_move_rec_list_end( /*===================*/ - /* out: TRUE on success; FALSE on - compression failure - (new_block will be decompressed) */ - buf_block_t* new_block, /* in/out: index page where to move */ - buf_block_t* block, /* in: index page from where to move */ - rec_t* split_rec, /* in: first record to move */ - dict_index_t* index, /* in: record descriptor */ - mtr_t* mtr) /* in: mtr */ + buf_block_t* new_block, /*!< in/out: index page where to move */ + buf_block_t* block, /*!< in: index page from where to move */ + rec_t* split_rec, /*!< in: first record to move */ + dict_index_t* index, /*!< in: record descriptor */ + mtr_t* mtr) /*!< in: mtr */ { page_t* new_page = buf_block_get_frame(new_block); ulint old_data_size; @@ -1187,20 +1213,19 @@ page_move_rec_list_end( return(TRUE); } -/***************************************************************** +/*************************************************************//** Moves record list start to another page. Moved records do not include -split_rec. */ +split_rec. +@return TRUE on success; FALSE on compression failure */ UNIV_INTERN ibool page_move_rec_list_start( /*=====================*/ - /* out: TRUE on success; FALSE on - compression failure */ - buf_block_t* new_block, /* in/out: index page where to move */ - buf_block_t* block, /* in/out: page containing split_rec */ - rec_t* split_rec, /* in: first record not to move */ - dict_index_t* index, /* in: record descriptor */ - mtr_t* mtr) /* in: mtr */ + buf_block_t* new_block, /*!< in/out: index page where to move */ + buf_block_t* block, /*!< in/out: page containing split_rec */ + rec_t* split_rec, /*!< in: first record not to move */ + dict_index_t* index, /*!< in: record descriptor */ + mtr_t* mtr) /*!< in: mtr */ { if (UNIV_UNLIKELY(!page_copy_rec_list_start(new_block, block, split_rec, index, mtr))) { @@ -1212,17 +1237,17 @@ page_move_rec_list_start( return(TRUE); } -/*************************************************************************** +/***********************************************************************//** This is a low-level operation which is used in a database index creation to update the page number of a created B-tree to a data dictionary record. */ UNIV_INTERN void page_rec_write_index_page_no( /*=========================*/ - rec_t* rec, /* in: record to update */ - ulint i, /* in: index of the field to update */ - ulint page_no,/* in: value to write */ - mtr_t* mtr) /* in: mtr */ + rec_t* rec, /*!< in: record to update */ + ulint i, /*!< in: index of the field to update */ + ulint page_no,/*!< in: value to write */ + mtr_t* mtr) /*!< in: mtr */ { byte* data; ulint len; @@ -1233,8 +1258,9 @@ page_rec_write_index_page_no( mlog_write_ulint(data, page_no, MLOG_4BYTES, mtr); } +#endif /* !UNIV_HOTBACKUP */ -/****************************************************************** +/**************************************************************//** Used to delete n slots from the directory. This function updates also n_owned fields in the records, so that the first slot after the deleted ones inherits the records of the deleted slots. */ @@ -1242,9 +1268,9 @@ UNIV_INLINE void page_dir_delete_slot( /*=================*/ - page_t* page, /* in/out: the index page */ - page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */ - ulint slot_no)/* in: slot to be deleted */ + page_t* page, /*!< in/out: the index page */ + page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ + ulint slot_no)/*!< in: slot to be deleted */ { page_dir_slot_t* slot; ulint n_owned; @@ -1283,7 +1309,7 @@ page_dir_delete_slot( page_header_set_field(page, page_zip, PAGE_N_DIR_SLOTS, n_slots - 1); } -/****************************************************************** +/**************************************************************//** Used to add n slots to the directory. Does not set the record pointers in the added slots or update n_owned values: this is the responsibility of the caller. */ @@ -1291,9 +1317,9 @@ UNIV_INLINE void page_dir_add_slot( /*==============*/ - page_t* page, /* in/out: the index page */ - page_zip_des_t* page_zip,/* in/out: comprssed page, or NULL */ - ulint start) /* in: the slot above which the new slots + page_t* page, /*!< in/out: the index page */ + page_zip_des_t* page_zip,/*!< in/out: comprssed page, or NULL */ + ulint start) /*!< in: the slot above which the new slots are added */ { page_dir_slot_t* slot; @@ -1312,16 +1338,16 @@ page_dir_add_slot( (n_slots - 1 - start) * PAGE_DIR_SLOT_SIZE); } -/******************************************************************** +/****************************************************************//** Splits a directory slot which owns too many records. */ UNIV_INTERN void page_dir_split_slot( /*================*/ - page_t* page, /* in/out: index page */ - page_zip_des_t* page_zip,/* in/out: compressed page whose + page_t* page, /*!< in/out: index page */ + page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed part will be written, or NULL */ - ulint slot_no)/* in: the directory slot */ + ulint slot_no)/*!< in: the directory slot */ { rec_t* rec; page_dir_slot_t* new_slot; @@ -1373,7 +1399,7 @@ page_dir_split_slot( page_dir_slot_set_n_owned(slot, page_zip, n_owned - (n_owned / 2)); } -/***************************************************************** +/*************************************************************//** Tries to balance the given directory slot with too few records with the upper neighbor, so that there are at least the minimum number of records owned by the slot; this may result in the merging of two slots. */ @@ -1381,9 +1407,9 @@ UNIV_INTERN void page_dir_balance_slot( /*==================*/ - page_t* page, /* in/out: index page */ - page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */ - ulint slot_no)/* in: the directory slot */ + page_t* page, /*!< in/out: index page */ + page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ + ulint slot_no)/*!< in: the directory slot */ { page_dir_slot_t* slot; page_dir_slot_t* up_slot; @@ -1444,15 +1470,16 @@ page_dir_balance_slot( } } -/**************************************************************** +#ifndef UNIV_HOTBACKUP +/************************************************************//** Returns the middle record of the record list. If there are an even number -of records in the list, returns the first record of the upper half-list. */ +of records in the list, returns the first record of the upper half-list. +@return middle record */ UNIV_INTERN rec_t* page_get_middle_rec( /*================*/ - /* out: middle record */ - page_t* page) /* in: page */ + page_t* page) /*!< in: page */ { page_dir_slot_t* slot; ulint middle; @@ -1491,16 +1518,17 @@ page_get_middle_rec( return(rec); } +#endif /* !UNIV_HOTBACKUP */ -/******************************************************************* +/***************************************************************//** Returns the number of records before the given record in chain. -The number includes infimum and supremum records. */ +The number includes infimum and supremum records. +@return number of records */ UNIV_INTERN ulint page_rec_get_n_recs_before( /*=======================*/ - /* out: number of records */ - const rec_t* rec) /* in: the physical record */ + const rec_t* rec) /*!< in: the physical record */ { const page_dir_slot_t* slot; const rec_t* slot_rec; @@ -1556,15 +1584,16 @@ page_rec_get_n_recs_before( return((ulint) n); } -/**************************************************************** +#ifndef UNIV_HOTBACKUP +/************************************************************//** Prints record contents including the data relevant only in the index page context. */ UNIV_INTERN void page_rec_print( /*===========*/ - const rec_t* rec, /* in: physical record */ - const ulint* offsets)/* in: record descriptor */ + const rec_t* rec, /*!< in: physical record */ + const ulint* offsets)/*!< in: record descriptor */ { ut_a(!page_rec_is_comp(rec) == !rec_offs_comp(offsets)); rec_print_new(stderr, rec, offsets); @@ -1586,15 +1615,15 @@ page_rec_print( rec_validate(rec, offsets); } -/******************************************************************* +/***************************************************************//** This is used to print the contents of the directory for debugging purposes. */ UNIV_INTERN void page_dir_print( /*===========*/ - page_t* page, /* in: index page */ - ulint pr_n) /* in: print n first and n last entries */ + page_t* page, /*!< in: index page */ + ulint pr_n) /*!< in: print n first and n last entries */ { ulint n; ulint i; @@ -1628,16 +1657,16 @@ page_dir_print( (ulong) (PAGE_HEAP_NO_USER_LOW + page_get_n_recs(page))); } -/******************************************************************* +/***************************************************************//** This is used to print the contents of the page record list for debugging purposes. */ UNIV_INTERN void page_print_list( /*============*/ - buf_block_t* block, /* in: index page */ - dict_index_t* index, /* in: dictionary index of the page */ - ulint pr_n) /* in: print n first and n last entries */ + buf_block_t* block, /*!< in: index page */ + dict_index_t* index, /*!< in: dictionary index of the page */ + ulint pr_n) /*!< in: print n first and n last entries */ { page_t* page = block->frame; page_cur_t cur; @@ -1699,7 +1728,7 @@ page_print_list( } } -/******************************************************************* +/***************************************************************//** Prints the info in a page header. */ UNIV_INTERN void @@ -1726,18 +1755,18 @@ page_header_print( (ulong) page_header_get_field(page, PAGE_N_DIRECTION)); } -/******************************************************************* +/***************************************************************//** This is used to print the contents of the page for debugging purposes. */ UNIV_INTERN void page_print( /*=======*/ - buf_block_t* block, /* in: index page */ - dict_index_t* index, /* in: dictionary index of the page */ - ulint dn, /* in: print dn first and last entries + buf_block_t* block, /*!< in: index page */ + dict_index_t* index, /*!< in: dictionary index of the page */ + ulint dn, /*!< in: print dn first and last entries in directory */ - ulint rn) /* in: print rn first and last records + ulint rn) /*!< in: print rn first and last records in directory */ { page_t* page = block->frame; @@ -1746,18 +1775,19 @@ page_print( page_dir_print(page, dn); page_print_list(block, index, rn); } +#endif /* !UNIV_HOTBACKUP */ -/******************************************************************* +/***************************************************************//** The following is used to validate a record on a page. This function differs from rec_validate as it can also check the n_owned field and -the heap_no field. */ +the heap_no field. +@return TRUE if ok */ UNIV_INTERN ibool page_rec_validate( /*==============*/ - /* out: TRUE if ok */ - rec_t* rec, /* in: physical record */ - const ulint* offsets)/* in: array returned by rec_get_offsets() */ + rec_t* rec, /*!< in: physical record */ + const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ { ulint n_owned; ulint heap_no; @@ -1795,7 +1825,8 @@ page_rec_validate( return(TRUE); } -/******************************************************************* +#ifndef UNIV_HOTBACKUP +/***************************************************************//** Checks that the first directory slot points to the infimum record and the last to the supremum. This function is intended to track if the bug fixed in 4.0.14 has caused corruption to users' databases. */ @@ -1803,7 +1834,7 @@ UNIV_INTERN void page_check_dir( /*===========*/ - const page_t* page) /* in: index page */ + const page_t* page) /*!< in: index page */ { ulint n_slots; ulint infimum_offs; @@ -1830,17 +1861,18 @@ page_check_dir( buf_page_print(page, 0); } } +#endif /* !UNIV_HOTBACKUP */ -/******************************************************************* +/***************************************************************//** This function checks the consistency of an index page when we do not know the index. This is also resilient so that this should never crash -even if the page is total garbage. */ +even if the page is total garbage. +@return TRUE if ok */ UNIV_INTERN ibool page_simple_validate_old( /*=====================*/ - /* out: TRUE if ok */ - page_t* page) /* in: old-style index page */ + page_t* page) /*!< in: old-style index page */ { page_dir_slot_t* slot; ulint slot_no; @@ -2041,16 +2073,16 @@ func_exit: return(ret); } -/******************************************************************* +/***************************************************************//** This function checks the consistency of an index page when we do not know the index. This is also resilient so that this should never crash -even if the page is total garbage. */ +even if the page is total garbage. +@return TRUE if ok */ UNIV_INTERN ibool page_simple_validate_new( /*=====================*/ - /* out: TRUE if ok */ - page_t* page) /* in: new-style index page */ + page_t* page) /*!< in: new-style index page */ { page_dir_slot_t* slot; ulint slot_no; @@ -2252,15 +2284,15 @@ func_exit: return(ret); } -/******************************************************************* -This function checks the consistency of an index page. */ +/***************************************************************//** +This function checks the consistency of an index page. +@return TRUE if ok */ UNIV_INTERN ibool page_validate( /*==========*/ - /* out: TRUE if ok */ - page_t* page, /* in: index page */ - dict_index_t* index) /* in: data dictionary index containing + page_t* page, /*!< in: index page */ + dict_index_t* index) /*!< in: data dictionary index containing the page record type definition */ { page_dir_slot_t*slot; @@ -2310,10 +2342,11 @@ page_validate( if (UNIV_UNLIKELY(!(page_header_get_ptr(page, PAGE_HEAP_TOP) <= page_dir_get_nth_slot(page, n_slots - 1)))) { - fputs("InnoDB: Record heap and dir overlap on a page ", - stderr); - dict_index_name_print(stderr, NULL, index); - fprintf(stderr, ", %p, %p\n", + fprintf(stderr, + "InnoDB: Record heap and dir overlap" + " on space %lu page %lu index %s, %p, %p\n", + (ulong) page_get_space_id(page), + (ulong) page_get_page_no(page), index->name, page_header_get_ptr(page, PAGE_HEAP_TOP), page_dir_get_nth_slot(page, n_slots - 1)); @@ -2345,17 +2378,19 @@ page_validate( goto func_exit; } +#ifndef UNIV_HOTBACKUP /* Check that the records are in the ascending order */ if (UNIV_LIKELY(count >= PAGE_HEAP_NO_USER_LOW) && !page_rec_is_supremum(rec)) { if (UNIV_UNLIKELY (1 != cmp_rec_rec(rec, old_rec, offsets, old_offsets, index))) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Records in wrong order" - " on page %lu ", - (ulong) page_get_page_no(page)); - dict_index_name_print(stderr, NULL, index); + " on space %lu page %lu index %s\n", + (ulong) page_get_space_id(page), + (ulong) page_get_page_no(page), + index->name); fputs("\nInnoDB: previous record ", stderr); rec_print_new(stderr, old_rec, old_offsets); fputs("\nInnoDB: record ", stderr); @@ -2365,6 +2400,7 @@ page_validate( goto func_exit; } } +#endif /* !UNIV_HOTBACKUP */ if (page_rec_is_user_rec(rec)) { @@ -2510,25 +2546,28 @@ func_exit: if (UNIV_UNLIKELY(ret == FALSE)) { func_exit2: - fprintf(stderr, "InnoDB: Apparent corruption in page %lu in ", - (ulong) page_get_page_no(page)); - dict_index_name_print(stderr, NULL, index); - putc('\n', stderr); + fprintf(stderr, + "InnoDB: Apparent corruption" + " in space %lu page %lu index %s\n", + (ulong) page_get_space_id(page), + (ulong) page_get_page_no(page), + index->name); buf_page_print(page, 0); } return(ret); } -/******************************************************************* -Looks in the page record list for a record with the given heap number. */ +#ifndef UNIV_HOTBACKUP +/***************************************************************//** +Looks in the page record list for a record with the given heap number. +@return record, NULL if not found */ UNIV_INTERN const rec_t* page_find_rec_with_heap_no( /*=======================*/ - /* out: record, NULL if not found */ - const page_t* page, /* in: index page */ - ulint heap_no)/* in: heap number */ + const page_t* page, /*!< in: index page */ + ulint heap_no)/*!< in: heap number */ { const rec_t* rec; @@ -2566,3 +2605,4 @@ page_find_rec_with_heap_no( } } } +#endif /* !UNIV_HOTBACKUP */ diff --git a/storage/xtradb/page/page0zip.c b/storage/xtradb/page/page0zip.c index 56189ce3bad..92ba0ec768a 100644 --- a/storage/xtradb/page/page0zip.c +++ b/storage/xtradb/page/page0zip.c @@ -16,7 +16,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA *****************************************************************************/ -/****************************************************** +/**************************************************//** +@file page/page0zip.c Compressed page interface Created June 2005 by Marko Makela @@ -31,15 +32,20 @@ Created June 2005 by Marko Makela #include "page0page.h" #include "mtr0log.h" #include "ut0sort.h" -#include "dict0boot.h" #include "dict0dict.h" -#include "btr0sea.h" #include "btr0cur.h" #include "page0types.h" -#include "lock0lock.h" #include "log0recv.h" #include "zlib.h" -#include "buf0lru.h" +#ifndef UNIV_HOTBACKUP +# include "buf0lru.h" +# include "btr0sea.h" +# include "dict0boot.h" +# include "lock0lock.h" +#else /* !UNIV_HOTBACKUP */ +# define lock_move_reorganize_page(block, temp_block) ((void) 0) +# define buf_LRU_stat_inc_unzip() ((void) 0) +#endif /* !UNIV_HOTBACKUP */ /** Statistics on compression, indexed by page_zip_des_t::ssize - 1 */ UNIV_INTERN page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE - 1]; @@ -50,15 +56,18 @@ compressed page format. */ /* The infimum and supremum records are omitted from the compressed page. On compress, we compare that the records are there, and on uncompress we restore the records. */ +/** Extra bytes of an infimum record */ static const byte infimum_extra[] = { 0x01, /* info_bits=0, n_owned=1 */ 0x00, 0x02 /* heap_no=0, status=2 */ /* ?, ? */ /* next=(first user rec, or supremum) */ }; +/** Data bytes of an infimum record */ static const byte infimum_data[] = { 0x69, 0x6e, 0x66, 0x69, 0x6d, 0x75, 0x6d, 0x00 /* "infimum\0" */ }; +/** Extra bytes and data bytes of a supremum record */ static const byte supremum_extra_data[] = { /* 0x0?, */ /* info_bits=0, n_owned=1..8 */ 0x00, 0x0b, /* heap_no=1, status=3 */ @@ -68,10 +77,13 @@ static const byte supremum_extra_data[] = { }; /** Assert that a block of memory is filled with zero bytes. -Compare at most sizeof(field_ref_zero) bytes. */ +Compare at most sizeof(field_ref_zero) bytes. +@param b in: memory block +@param s in: size of the memory block, in bytes */ #define ASSERT_ZERO(b, s) \ ut_ad(!memcmp(b, field_ref_zero, ut_min(s, sizeof field_ref_zero))) -/** Assert that a BLOB pointer is filled with zero bytes. */ +/** Assert that a BLOB pointer is filled with zero bytes. +@param b in: BLOB pointer */ #define ASSERT_ZERO_BLOB(b) \ ut_ad(!memcmp(b, field_ref_zero, sizeof field_ref_zero)) @@ -80,15 +92,15 @@ independently of any UNIV_ debugging conditions. */ #if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG # include <stdarg.h> __attribute__((format (printf, 1, 2))) -/************************************************************************** -Report a failure to decompress or compress. */ +/**********************************************************************//** +Report a failure to decompress or compress. +@return number of characters printed */ static int page_zip_fail_func( /*===============*/ - /* out: number of characters printed */ - const char* fmt, /* in: printf(3) format string */ - ...) /* in: arguments corresponding to fmt */ + const char* fmt, /*!< in: printf(3) format string */ + ...) /*!< in: arguments corresponding to fmt */ { int res; va_list ap; @@ -101,20 +113,25 @@ page_zip_fail_func( return(res); } +/** Wrapper for page_zip_fail_func() +@param fmt_args in: printf(3) format string and arguments */ # define page_zip_fail(fmt_args) page_zip_fail_func fmt_args #else /* UNIV_DEBUG || UNIV_ZIP_DEBUG */ +/** Dummy wrapper for page_zip_fail_func() +@param fmt_args ignored: printf(3) format string and arguments */ # define page_zip_fail(fmt_args) /* empty */ #endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */ -/************************************************************************** -Determine the guaranteed free space on an empty page. */ +#ifndef UNIV_HOTBACKUP +/**********************************************************************//** +Determine the guaranteed free space on an empty page. +@return minimum payload size on the page */ UNIV_INTERN ulint page_zip_empty_size( /*================*/ - /* out: minimum payload size on the page */ - ulint n_fields, /* in: number of columns in the index */ - ulint zip_size) /* in: compressed page size in bytes */ + ulint n_fields, /*!< in: number of columns in the index */ + ulint zip_size) /*!< in: compressed page size in bytes */ { lint size = zip_size /* subtract the page header and the longest @@ -129,17 +146,17 @@ page_zip_empty_size( - compressBound(2 * (n_fields + 1)); return(size > 0 ? (ulint) size : 0); } +#endif /* !UNIV_HOTBACKUP */ -/***************************************************************** +/*************************************************************//** Gets the size of the compressed page trailer (the dense page directory), -including deleted records (the free list). */ +including deleted records (the free list). +@return length of dense page directory, in bytes */ UNIV_INLINE ulint page_zip_dir_size( /*==============*/ - /* out: length of dense page - directory, in bytes */ - const page_zip_des_t* page_zip) /* in: compressed page */ + const page_zip_des_t* page_zip) /*!< in: compressed page */ { /* Exclude the page infimum and supremum from the record count. */ ulint size = PAGE_ZIP_DIR_SLOT_SIZE @@ -148,17 +165,15 @@ page_zip_dir_size( return(size); } -/***************************************************************** +/*************************************************************//** Gets the size of the compressed page trailer (the dense page directory), -only including user records (excluding the free list). */ +only including user records (excluding the free list). +@return length of dense page directory comprising existing records, in bytes */ UNIV_INLINE ulint page_zip_dir_user_size( /*===================*/ - /* out: length of dense page - directory comprising existing - records, in bytes */ - const page_zip_des_t* page_zip) /* in: compressed page */ + const page_zip_des_t* page_zip) /*!< in: compressed page */ { ulint size = PAGE_ZIP_DIR_SLOT_SIZE * page_get_n_recs(page_zip->data); @@ -166,17 +181,16 @@ page_zip_dir_user_size( return(size); } -/***************************************************************** -Find the slot of the given record in the dense page directory. */ +/*************************************************************//** +Find the slot of the given record in the dense page directory. +@return dense directory slot, or NULL if record not found */ UNIV_INLINE byte* page_zip_dir_find_low( /*==================*/ - /* out: dense directory slot, - or NULL if record not found */ - byte* slot, /* in: start of records */ - byte* end, /* in: end of records */ - ulint offset) /* in: offset of user record */ + byte* slot, /*!< in: start of records */ + byte* end, /*!< in: end of records */ + ulint offset) /*!< in: offset of user record */ { ut_ad(slot <= end); @@ -190,16 +204,15 @@ page_zip_dir_find_low( return(NULL); } -/***************************************************************** -Find the slot of the given non-free record in the dense page directory. */ +/*************************************************************//** +Find the slot of the given non-free record in the dense page directory. +@return dense directory slot, or NULL if record not found */ UNIV_INLINE byte* page_zip_dir_find( /*==============*/ - /* out: dense directory slot, - or NULL if record not found */ - page_zip_des_t* page_zip, /* in: compressed page */ - ulint offset) /* in: offset of user record */ + page_zip_des_t* page_zip, /*!< in: compressed page */ + ulint offset) /*!< in: offset of user record */ { byte* end = page_zip->data + page_zip_get_size(page_zip); @@ -210,16 +223,15 @@ page_zip_dir_find( offset)); } -/***************************************************************** -Find the slot of the given free record in the dense page directory. */ +/*************************************************************//** +Find the slot of the given free record in the dense page directory. +@return dense directory slot, or NULL if record not found */ UNIV_INLINE byte* page_zip_dir_find_free( /*===================*/ - /* out: dense directory slot, - or NULL if record not found */ - page_zip_des_t* page_zip, /* in: compressed page */ - ulint offset) /* in: offset of user record */ + page_zip_des_t* page_zip, /*!< in: compressed page */ + ulint offset) /*!< in: offset of user record */ { byte* end = page_zip->data + page_zip_get_size(page_zip); @@ -230,19 +242,16 @@ page_zip_dir_find_free( offset)); } -/***************************************************************** -Read a given slot in the dense page directory. */ +/*************************************************************//** +Read a given slot in the dense page directory. +@return record offset on the uncompressed page, possibly ORed with +PAGE_ZIP_DIR_SLOT_DEL or PAGE_ZIP_DIR_SLOT_OWNED */ UNIV_INLINE ulint page_zip_dir_get( /*=============*/ - /* out: record offset - on the uncompressed page, - possibly ORed with - PAGE_ZIP_DIR_SLOT_DEL or - PAGE_ZIP_DIR_SLOT_OWNED */ - const page_zip_des_t* page_zip, /* in: compressed page */ - ulint slot) /* in: slot + const page_zip_des_t* page_zip, /*!< in: compressed page */ + ulint slot) /*!< in: slot (0=first user record) */ { ut_ad(page_zip_simple_validate(page_zip)); @@ -251,20 +260,23 @@ page_zip_dir_get( - PAGE_ZIP_DIR_SLOT_SIZE * (slot + 1))); } -/************************************************************************** +#ifndef UNIV_HOTBACKUP +/**********************************************************************//** Write a log record of compressing an index page. */ static void page_zip_compress_write_log( /*========================*/ - const page_zip_des_t* page_zip,/* in: compressed page */ - const page_t* page, /* in: uncompressed page */ - dict_index_t* index, /* in: index of the B-tree node */ - mtr_t* mtr) /* in: mini-transaction */ + const page_zip_des_t* page_zip,/*!< in: compressed page */ + const page_t* page, /*!< in: uncompressed page */ + dict_index_t* index, /*!< in: index of the B-tree node */ + mtr_t* mtr) /*!< in: mini-transaction */ { byte* log_ptr; ulint trailer_size; + ut_ad(!dict_index_is_ibuf(index)); + log_ptr = mlog_open(mtr, 11 + 2 + 2); if (!log_ptr) { @@ -312,19 +324,20 @@ page_zip_compress_write_log( mlog_catenate_string(mtr, page_zip->data + page_zip_get_size(page_zip) - trailer_size, trailer_size); } +#endif /* !UNIV_HOTBACKUP */ -/********************************************************** +/******************************************************//** Determine how many externally stored columns are contained in existing records with smaller heap_no than rec. */ static ulint page_zip_get_n_prev_extern( /*=======================*/ - const page_zip_des_t* page_zip,/* in: dense page directory on + const page_zip_des_t* page_zip,/*!< in: dense page directory on compressed page */ - const rec_t* rec, /* in: compact physical record + const rec_t* rec, /*!< in: compact physical record on a B-tree leaf page */ - dict_index_t* index) /* in: record descriptor */ + dict_index_t* index) /*!< in: record descriptor */ { const page_t* page = page_align(rec); ulint n_ext = 0; @@ -337,6 +350,7 @@ page_zip_get_n_prev_extern( ut_ad(page_is_comp(page)); ut_ad(dict_table_is_comp(index->table)); ut_ad(dict_index_is_clust(index)); + ut_ad(!dict_index_is_ibuf(index)); heap_no = rec_get_heap_no_new(rec); ut_ad(heap_no >= PAGE_HEAP_NO_USER_LOW); @@ -361,15 +375,15 @@ page_zip_get_n_prev_extern( return(n_ext); } -/************************************************************************** -Encode the length of a fixed-length column. */ +/**********************************************************************//** +Encode the length of a fixed-length column. +@return buf + length of encoded val */ static byte* page_zip_fixed_field_encode( /*========================*/ - /* out: buf + length of encoded val */ - byte* buf, /* in: pointer to buffer where to write */ - ulint val) /* in: value to write */ + byte* buf, /*!< in: pointer to buffer where to write */ + ulint val) /*!< in: value to write */ { ut_ad(val >= 2); @@ -389,19 +403,19 @@ page_zip_fixed_field_encode( return(buf); } -/************************************************************************** -Write the index information for the compressed page. */ +/**********************************************************************//** +Write the index information for the compressed page. +@return used size of buf */ static ulint page_zip_fields_encode( /*===================*/ - /* out: used size of buf */ - ulint n, /* in: number of fields to compress */ - dict_index_t* index, /* in: index comprising at least n fields */ - ulint trx_id_pos,/* in: position of the trx_id column + ulint n, /*!< in: number of fields to compress */ + dict_index_t* index, /*!< in: index comprising at least n fields */ + ulint trx_id_pos,/*!< in: position of the trx_id column in the index, or ULINT_UNDEFINED if this is a non-leaf page */ - byte* buf) /* out: buffer of (n + 1) * 2 bytes */ + byte* buf) /*!< out: buffer of (n + 1) * 2 bytes */ { const byte* buf_start = buf; ulint i; @@ -517,16 +531,16 @@ page_zip_fields_encode( return((ulint) (buf - buf_start)); } -/************************************************************************** +/**********************************************************************//** Populate the dense page directory from the sparse directory. */ static void page_zip_dir_encode( /*================*/ - const page_t* page, /* in: compact page */ - byte* buf, /* in: pointer to dense page directory[-1]; + const page_t* page, /*!< in: compact page */ + byte* buf, /*!< in: pointer to dense page directory[-1]; out: dense directory on compressed page */ - const rec_t** recs) /* in: pointer to an array of 0, or NULL; + const rec_t** recs) /*!< in: pointer to an array of 0, or NULL; out: dense page directory sorted by ascending address (and heap_no) */ { @@ -633,38 +647,38 @@ page_zip_dir_encode( ut_a(i + PAGE_HEAP_NO_USER_LOW == n_heap); } -/************************************************************************** +/**********************************************************************//** Allocate memory for zlib. */ static void* page_zip_malloc( /*============*/ - void* opaque, - uInt items, - uInt size) + void* opaque, /*!< in/out: memory heap */ + uInt items, /*!< in: number of items to allocate */ + uInt size) /*!< in: size of an item in bytes */ { return(mem_heap_alloc(opaque, items * size)); } -/************************************************************************** +/**********************************************************************//** Deallocate memory for zlib. */ static void page_zip_free( /*==========*/ - void* opaque __attribute__((unused)), - void* address __attribute__((unused))) + void* opaque __attribute__((unused)), /*!< in: memory heap */ + void* address __attribute__((unused)))/*!< in: object to free */ { } -/************************************************************************** +/**********************************************************************//** Configure the zlib allocator to use the given memory heap. */ UNIV_INTERN void page_zip_set_alloc( /*===============*/ - void* stream, /* in/out: zlib stream */ - mem_heap_t* heap) /* in: memory heap to use */ + void* stream, /*!< in/out: zlib stream */ + mem_heap_t* heap) /*!< in: memory heap to use */ { z_stream* strm = stream; @@ -674,28 +688,30 @@ page_zip_set_alloc( } #if 0 || defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG +/** Symbol for enabling compression and decompression diagnostics */ # define PAGE_ZIP_COMPRESS_DBG #endif #ifdef PAGE_ZIP_COMPRESS_DBG -/* Set this variable in a debugger to enable +/** Set this variable in a debugger to enable excessive logging in page_zip_compress(). */ UNIV_INTERN ibool page_zip_compress_dbg; -/* Set this variable in a debugger to enable +/** Set this variable in a debugger to enable binary logging of the data passed to deflate(). When this variable is nonzero, it will act as a log file name generator. */ UNIV_INTERN unsigned page_zip_compress_log; -/************************************************************************** -Wrapper for deflate(). Log the operation if page_zip_compress_dbg is set. */ +/**********************************************************************//** +Wrapper for deflate(). Log the operation if page_zip_compress_dbg is set. +@return deflate() status: Z_OK, Z_BUF_ERROR, ... */ static -ibool +int page_zip_compress_deflate( /*======================*/ - FILE* logfile,/* in: log file, or NULL */ - z_streamp strm, /* in/out: compressed stream for deflate() */ - int flush) /* in: deflate() flushing method */ + FILE* logfile,/*!< in: log file, or NULL */ + z_streamp strm, /*!< in/out: compressed stream for deflate() */ + int flush) /*!< in: deflate() flushing method */ { int status; if (UNIV_UNLIKELY(page_zip_compress_dbg)) { @@ -713,29 +729,38 @@ page_zip_compress_deflate( /* Redefine deflate(). */ # undef deflate +/** Debug wrapper for the zlib compression routine deflate(). +Log the operation if page_zip_compress_dbg is set. +@param strm in/out: compressed stream +@param flush in: flushing method +@return deflate() status: Z_OK, Z_BUF_ERROR, ... */ # define deflate(strm, flush) page_zip_compress_deflate(logfile, strm, flush) +/** Declaration of the logfile parameter */ # define FILE_LOGFILE FILE* logfile, +/** The logfile parameter */ # define LOGFILE logfile, #else /* PAGE_ZIP_COMPRESS_DBG */ +/** Empty declaration of the logfile parameter */ # define FILE_LOGFILE +/** Missing logfile parameter */ # define LOGFILE #endif /* PAGE_ZIP_COMPRESS_DBG */ -/************************************************************************** -Compress the records of a node pointer page. */ +/**********************************************************************//** +Compress the records of a node pointer page. +@return Z_OK, or a zlib error code */ static int page_zip_compress_node_ptrs( /*========================*/ - /* out: Z_OK, or a zlib error code */ FILE_LOGFILE - z_stream* c_stream, /* in/out: compressed page stream */ - const rec_t** recs, /* in: dense page directory + z_stream* c_stream, /*!< in/out: compressed page stream */ + const rec_t** recs, /*!< in: dense page directory sorted by address */ - ulint n_dense, /* in: size of recs[] */ - dict_index_t* index, /* in: the index of the page */ - byte* storage, /* in: end of dense page directory */ - mem_heap_t* heap) /* in: temporary memory heap */ + ulint n_dense, /*!< in: size of recs[] */ + dict_index_t* index, /*!< in: the index of the page */ + byte* storage, /*!< in: end of dense page directory */ + mem_heap_t* heap) /*!< in: temporary memory heap */ { int err = Z_OK; ulint* offsets = NULL; @@ -786,18 +811,18 @@ page_zip_compress_node_ptrs( return(err); } -/************************************************************************** -Compress the records of a leaf node of a secondary index. */ +/**********************************************************************//** +Compress the records of a leaf node of a secondary index. +@return Z_OK, or a zlib error code */ static int page_zip_compress_sec( /*==================*/ - /* out: Z_OK, or a zlib error code */ FILE_LOGFILE - z_stream* c_stream, /* in/out: compressed page stream */ - const rec_t** recs, /* in: dense page directory + z_stream* c_stream, /*!< in/out: compressed page stream */ + const rec_t** recs, /*!< in: dense page directory sorted by address */ - ulint n_dense) /* in: size of recs[] */ + ulint n_dense) /*!< in: size of recs[] */ { int err = Z_OK; @@ -830,25 +855,25 @@ page_zip_compress_sec( return(err); } -/************************************************************************** +/**********************************************************************//** Compress a record of a leaf node of a clustered index that contains -externally stored columns. */ +externally stored columns. +@return Z_OK, or a zlib error code */ static int page_zip_compress_clust_ext( /*========================*/ - /* out: Z_OK, or a zlib error code */ FILE_LOGFILE - z_stream* c_stream, /* in/out: compressed page stream */ - const rec_t* rec, /* in: record */ - const ulint* offsets, /* in: rec_get_offsets(rec) */ - ulint trx_id_col, /* in: position of of DB_TRX_ID */ - byte* deleted, /* in: dense directory entry pointing + z_stream* c_stream, /*!< in/out: compressed page stream */ + const rec_t* rec, /*!< in: record */ + const ulint* offsets, /*!< in: rec_get_offsets(rec) */ + ulint trx_id_col, /*!< in: position of of DB_TRX_ID */ + byte* deleted, /*!< in: dense directory entry pointing to the head of the free list */ - byte* storage, /* in: end of dense page directory */ - byte** externs, /* in/out: pointer to the next + byte* storage, /*!< in: end of dense page directory */ + byte** externs, /*!< in/out: pointer to the next available BLOB pointer */ - ulint* n_blobs) /* in/out: number of + ulint* n_blobs) /*!< in/out: number of externally stored columns */ { int err; @@ -958,26 +983,26 @@ page_zip_compress_clust_ext( return(Z_OK); } -/************************************************************************** -Compress the records of a leaf node of a clustered index. */ +/**********************************************************************//** +Compress the records of a leaf node of a clustered index. +@return Z_OK, or a zlib error code */ static int page_zip_compress_clust( /*====================*/ - /* out: Z_OK, or a zlib error code */ FILE_LOGFILE - z_stream* c_stream, /* in/out: compressed page stream */ - const rec_t** recs, /* in: dense page directory + z_stream* c_stream, /*!< in/out: compressed page stream */ + const rec_t** recs, /*!< in: dense page directory sorted by address */ - ulint n_dense, /* in: size of recs[] */ - dict_index_t* index, /* in: the index of the page */ - ulint* n_blobs, /* in: 0; out: number of + ulint n_dense, /*!< in: size of recs[] */ + dict_index_t* index, /*!< in: the index of the page */ + ulint* n_blobs, /*!< in: 0; out: number of externally stored columns */ - ulint trx_id_col, /* index of the trx_id column */ - byte* deleted, /* in: dense directory entry pointing + ulint trx_id_col, /*!< index of the trx_id column */ + byte* deleted, /*!< in: dense directory entry pointing to the head of the free list */ - byte* storage, /* in: end of dense page directory */ - mem_heap_t* heap) /* in: temporary memory heap */ + byte* storage, /*!< in: end of dense page directory */ + mem_heap_t* heap) /*!< in: temporary memory heap */ { int err = Z_OK; ulint* offsets = NULL; @@ -1091,29 +1116,29 @@ func_exit: return(err); } -/************************************************************************** -Compress a page. */ +/**********************************************************************//** +Compress a page. +@return TRUE on success, FALSE on failure; page_zip will be left +intact on failure. */ UNIV_INTERN ibool page_zip_compress( /*==============*/ - /* out: TRUE on success, FALSE on failure; - page_zip will be left intact on failure. */ - page_zip_des_t* page_zip,/* in: size; out: data, n_blobs, + page_zip_des_t* page_zip,/*!< in: size; out: data, n_blobs, m_start, m_end, m_nonempty */ - const page_t* page, /* in: uncompressed page */ - dict_index_t* index, /* in: index of the B-tree node */ - mtr_t* mtr) /* in: mini-transaction, or NULL */ + const page_t* page, /*!< in: uncompressed page */ + dict_index_t* index, /*!< in: index of the B-tree node */ + mtr_t* mtr) /*!< in: mini-transaction, or NULL */ { z_stream c_stream; int err; ulint n_fields;/* number of index fields needed */ - byte* fields; /* index field information */ - byte* buf; /* compressed payload of the page */ + byte* fields; /*!< index field information */ + byte* buf; /*!< compressed payload of the page */ byte* buf_end;/* end of buf */ ulint n_dense; ulint slot_size;/* amount of uncompressed bytes per record */ - const rec_t** recs; /* dense page directory, sorted by address */ + const rec_t** recs; /*!< dense page directory, sorted by address */ mem_heap_t* heap; ulint trx_id_col; ulint* offsets = NULL; @@ -1128,6 +1153,8 @@ page_zip_compress( ut_a(fil_page_get_type(page) == FIL_PAGE_INDEX); ut_ad(page_simple_validate_new((page_t*) page)); ut_ad(page_zip_simple_validate(page_zip)); + ut_ad(dict_table_is_comp(index->table)); + ut_ad(!dict_index_is_ibuf(index)); UNIV_MEM_ASSERT_RW(page, UNIV_PAGE_SIZE); @@ -1360,7 +1387,9 @@ err_exit: #endif /* UNIV_ZIP_DEBUG */ if (mtr) { +#ifndef UNIV_HOTBACKUP page_zip_compress_write_log(page_zip, page, index, mtr); +#endif /* !UNIV_HOTBACKUP */ } UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); @@ -1385,41 +1414,41 @@ err_exit: return(TRUE); } -/************************************************************************** -Compare two page directory entries. */ +/**********************************************************************//** +Compare two page directory entries. +@return positive if rec1 > rec2 */ UNIV_INLINE ibool page_zip_dir_cmp( /*=============*/ - /* out: positive if rec1 > rec2 */ - const rec_t* rec1, /* in: rec1 */ - const rec_t* rec2) /* in: rec2 */ + const rec_t* rec1, /*!< in: rec1 */ + const rec_t* rec2) /*!< in: rec2 */ { return(rec1 > rec2); } -/************************************************************************** +/**********************************************************************//** Sort the dense page directory by address (heap_no). */ static void page_zip_dir_sort( /*==============*/ - rec_t** arr, /* in/out: dense page directory */ - rec_t** aux_arr,/* in/out: work area */ - ulint low, /* in: lower bound of the sorting area, inclusive */ - ulint high) /* in: upper bound of the sorting area, exclusive */ + rec_t** arr, /*!< in/out: dense page directory */ + rec_t** aux_arr,/*!< in/out: work area */ + ulint low, /*!< in: lower bound of the sorting area, inclusive */ + ulint high) /*!< in: upper bound of the sorting area, exclusive */ { UT_SORT_FUNCTION_BODY(page_zip_dir_sort, arr, aux_arr, low, high, page_zip_dir_cmp); } -/************************************************************************** +/**********************************************************************//** Deallocate the index information initialized by page_zip_fields_decode(). */ static void page_zip_fields_free( /*=================*/ - dict_index_t* index) /* in: dummy index to be freed */ + dict_index_t* index) /*!< in: dummy index to be freed */ { if (index) { dict_table_t* table = index->table; @@ -1429,17 +1458,16 @@ page_zip_fields_free( } } -/************************************************************************** -Read the index information for the compressed page. */ +/**********************************************************************//** +Read the index information for the compressed page. +@return own: dummy index describing the page, or NULL on error */ static dict_index_t* page_zip_fields_decode( /*===================*/ - /* out,own: dummy index describing the page, - or NULL on error */ - const byte* buf, /* in: index information */ - const byte* end, /* in: end of buf */ - ulint* trx_id_col)/* in: NULL for non-leaf pages; + const byte* buf, /*!< in: index information */ + const byte* end, /*!< in: end of buf */ + ulint* trx_id_col)/*!< in: NULL for non-leaf pages; for leaf pages, pointer to where to store the position of the trx_id column */ { @@ -1546,23 +1574,22 @@ page_zip_fields_decode( return(index); } -/************************************************************************** -Populate the sparse page directory from the dense directory. */ +/**********************************************************************//** +Populate the sparse page directory from the dense directory. +@return TRUE on success, FALSE on failure */ static ibool page_zip_dir_decode( /*================*/ - /* out: TRUE on success, - FALSE on failure */ - const page_zip_des_t* page_zip,/* in: dense page directory on + const page_zip_des_t* page_zip,/*!< in: dense page directory on compressed page */ - page_t* page, /* in: compact page with valid header; + page_t* page, /*!< in: compact page with valid header; out: trailer and sparse page directory filled in */ - rec_t** recs, /* out: dense page directory sorted by + rec_t** recs, /*!< out: dense page directory sorted by ascending address (and heap_no) */ - rec_t** recs_aux,/* in/out: scratch area */ - ulint n_dense)/* in: number of user records, and + rec_t** recs_aux,/*!< in/out: scratch area */ + ulint n_dense)/*!< in: number of user records, and size of recs[] and recs_aux[] */ { ulint i; @@ -1644,17 +1671,16 @@ page_zip_dir_decode( return(TRUE); } -/************************************************************************** -Initialize the REC_N_NEW_EXTRA_BYTES of each record. */ +/**********************************************************************//** +Initialize the REC_N_NEW_EXTRA_BYTES of each record. +@return TRUE on success, FALSE on failure */ static ibool page_zip_set_extra_bytes( /*=====================*/ - /* out: TRUE on success, - FALSE on failure */ - const page_zip_des_t* page_zip,/* in: compressed page */ - page_t* page, /* in/out: uncompressed page */ - ulint info_bits)/* in: REC_INFO_MIN_REC_FLAG or 0 */ + const page_zip_des_t* page_zip,/*!< in: compressed page */ + page_t* page, /*!< in/out: uncompressed page */ + ulint info_bits)/*!< in: REC_INFO_MIN_REC_FLAG or 0 */ { ulint n; ulint i; @@ -1742,20 +1768,19 @@ page_zip_set_extra_bytes( return(TRUE); } -/************************************************************************** +/**********************************************************************//** Apply the modification log to a record containing externally stored -columns. Do not copy the fields that are stored separately. */ +columns. Do not copy the fields that are stored separately. +@return pointer to modification log, or NULL on failure */ static const byte* page_zip_apply_log_ext( /*===================*/ - /* out: pointer to modification log, - or NULL on failure */ - rec_t* rec, /* in/out: record */ - const ulint* offsets, /* in: rec_get_offsets(rec) */ - ulint trx_id_col, /* in: position of of DB_TRX_ID */ - const byte* data, /* in: modification log */ - const byte* end) /* in: end of modification log */ + rec_t* rec, /*!< in/out: record */ + const ulint* offsets, /*!< in: rec_get_offsets(rec) */ + ulint trx_id_col, /*!< in: position of of DB_TRX_ID */ + const byte* data, /*!< in: modification log */ + const byte* end) /*!< in: end of modification log */ { ulint i; ulint len; @@ -1832,28 +1857,27 @@ page_zip_apply_log_ext( return(data); } -/************************************************************************** +/**********************************************************************//** Apply the modification log to an uncompressed page. -Do not copy the fields that are stored separately. */ +Do not copy the fields that are stored separately. +@return pointer to end of modification log, or NULL on failure */ static const byte* page_zip_apply_log( /*===============*/ - /* out: pointer to end of modification log, - or NULL on failure */ - const byte* data, /* in: modification log */ - ulint size, /* in: maximum length of the log, in bytes */ - rec_t** recs, /* in: dense page directory, + const byte* data, /*!< in: modification log */ + ulint size, /*!< in: maximum length of the log, in bytes */ + rec_t** recs, /*!< in: dense page directory, sorted by address (indexed by heap_no - PAGE_HEAP_NO_USER_LOW) */ - ulint n_dense,/* in: size of recs[] */ - ulint trx_id_col,/* in: column number of trx_id in the index, + ulint n_dense,/*!< in: size of recs[] */ + ulint trx_id_col,/*!< in: column number of trx_id in the index, or ULINT_UNDEFINED if none */ ulint heap_status, - /* in: heap_no and status bits for + /*!< in: heap_no and status bits for the next record to uncompress */ - dict_index_t* index, /* in: index of the page */ - ulint* offsets)/* in/out: work area for + dict_index_t* index, /*!< in: index of the page */ + ulint* offsets)/*!< in/out: work area for rec_get_offsets_reverse() */ { const byte* const end = data + size; @@ -2034,22 +2058,21 @@ page_zip_apply_log( } } -/************************************************************************** -Decompress the records of a node pointer page. */ +/**********************************************************************//** +Decompress the records of a node pointer page. +@return TRUE on success, FALSE on failure */ static ibool page_zip_decompress_node_ptrs( /*==========================*/ - /* out: TRUE on success, - FALSE on failure */ - page_zip_des_t* page_zip, /* in/out: compressed page */ - z_stream* d_stream, /* in/out: compressed page stream */ - rec_t** recs, /* in: dense page directory + page_zip_des_t* page_zip, /*!< in/out: compressed page */ + z_stream* d_stream, /*!< in/out: compressed page stream */ + rec_t** recs, /*!< in: dense page directory sorted by address */ - ulint n_dense, /* in: size of recs[] */ - dict_index_t* index, /* in: the index of the page */ - ulint* offsets, /* in/out: temporary offsets */ - mem_heap_t* heap) /* in: temporary memory heap */ + ulint n_dense, /*!< in: size of recs[] */ + dict_index_t* index, /*!< in: the index of the page */ + ulint* offsets, /*!< in/out: temporary offsets */ + mem_heap_t* heap) /*!< in: temporary memory heap */ { ulint heap_status = REC_STATUS_NODE_PTR | PAGE_HEAP_NO_USER_LOW << REC_HEAP_NO_SHIFT; @@ -2228,21 +2251,20 @@ zlib_done: return(TRUE); } -/************************************************************************** -Decompress the records of a leaf node of a secondary index. */ +/**********************************************************************//** +Decompress the records of a leaf node of a secondary index. +@return TRUE on success, FALSE on failure */ static ibool page_zip_decompress_sec( /*====================*/ - /* out: TRUE on success, - FALSE on failure */ - page_zip_des_t* page_zip, /* in/out: compressed page */ - z_stream* d_stream, /* in/out: compressed page stream */ - rec_t** recs, /* in: dense page directory + page_zip_des_t* page_zip, /*!< in/out: compressed page */ + z_stream* d_stream, /*!< in/out: compressed page stream */ + rec_t** recs, /*!< in: dense page directory sorted by address */ - ulint n_dense, /* in: size of recs[] */ - dict_index_t* index, /* in: the index of the page */ - ulint* offsets) /* in/out: temporary offsets */ + ulint n_dense, /*!< in: size of recs[] */ + dict_index_t* index, /*!< in: the index of the page */ + ulint* offsets) /*!< in/out: temporary offsets */ { ulint heap_status = REC_STATUS_ORDINARY | PAGE_HEAP_NO_USER_LOW << REC_HEAP_NO_SHIFT; @@ -2370,18 +2392,18 @@ zlib_done: return(TRUE); } -/************************************************************************** +/**********************************************************************//** Decompress a record of a leaf node of a clustered index that contains -externally stored columns. */ +externally stored columns. +@return TRUE on success */ static ibool page_zip_decompress_clust_ext( /*==========================*/ - /* out: TRUE on success */ - z_stream* d_stream, /* in/out: compressed page stream */ - rec_t* rec, /* in/out: record */ - const ulint* offsets, /* in: rec_get_offsets(rec) */ - ulint trx_id_col) /* in: position of of DB_TRX_ID */ + z_stream* d_stream, /*!< in/out: compressed page stream */ + rec_t* rec, /*!< in/out: record */ + const ulint* offsets, /*!< in: rec_get_offsets(rec) */ + ulint trx_id_col) /*!< in: position of of DB_TRX_ID */ { ulint i; @@ -2479,23 +2501,22 @@ page_zip_decompress_clust_ext( return(TRUE); } -/************************************************************************** -Compress the records of a leaf node of a clustered index. */ +/**********************************************************************//** +Compress the records of a leaf node of a clustered index. +@return TRUE on success, FALSE on failure */ static ibool page_zip_decompress_clust( /*======================*/ - /* out: TRUE on success, - FALSE on failure */ - page_zip_des_t* page_zip, /* in/out: compressed page */ - z_stream* d_stream, /* in/out: compressed page stream */ - rec_t** recs, /* in: dense page directory + page_zip_des_t* page_zip, /*!< in/out: compressed page */ + z_stream* d_stream, /*!< in/out: compressed page stream */ + rec_t** recs, /*!< in: dense page directory sorted by address */ - ulint n_dense, /* in: size of recs[] */ - dict_index_t* index, /* in: the index of the page */ - ulint trx_id_col, /* index of the trx_id column */ - ulint* offsets, /* in/out: temporary offsets */ - mem_heap_t* heap) /* in: temporary memory heap */ + ulint n_dense, /*!< in: size of recs[] */ + dict_index_t* index, /*!< in: the index of the page */ + ulint trx_id_col, /*!< index of the trx_id column */ + ulint* offsets, /*!< in/out: temporary offsets */ + mem_heap_t* heap) /*!< in: temporary memory heap */ { int err; ulint slot; @@ -2779,22 +2800,22 @@ zlib_done: return(TRUE); } -/************************************************************************** +/**********************************************************************//** Decompress a page. This function should tolerate errors on the compressed page. Instead of letting assertions fail, it will return FALSE if an -inconsistency is detected. */ +inconsistency is detected. +@return TRUE on success, FALSE on failure */ UNIV_INTERN ibool page_zip_decompress( /*================*/ - /* out: TRUE on success, FALSE on failure */ - page_zip_des_t* page_zip,/* in: data, ssize; + page_zip_des_t* page_zip,/*!< in: data, ssize; out: m_start, m_end, m_nonempty, n_blobs */ - page_t* page) /* out: uncompressed page, may be trashed */ + page_t* page) /*!< out: uncompressed page, may be trashed */ { z_stream d_stream; dict_index_t* index = NULL; - rec_t** recs; /* dense page directory, sorted by address */ + rec_t** recs; /*!< dense page directory, sorted by address */ ulint n_dense;/* number of user records on the page */ ulint trx_id_col = ULINT_UNDEFINED; mem_heap_t* heap; @@ -2969,15 +2990,15 @@ err_exit: } #ifdef UNIV_ZIP_DEBUG -/************************************************************************** +/**********************************************************************//** Dump a block of memory on the standard error stream. */ static void page_zip_hexdump_func( /*==================*/ - const char* name, /* in: name of the data structure */ - const void* buf, /* in: data */ - ulint size) /* in: length of the data, in bytes */ + const char* name, /*!< in: name of the data structure */ + const void* buf, /*!< in: data */ + ulint size) /*!< in: length of the data, in bytes */ { const byte* s = buf; ulint addr; @@ -3000,21 +3021,24 @@ page_zip_hexdump_func( } } +/** Dump a block of memory on the standard error stream. +@param buf in: data +@param size in: length of the data, in bytes */ #define page_zip_hexdump(buf, size) page_zip_hexdump_func(#buf, buf, size) -/* Flag: make page_zip_validate() compare page headers only */ +/** Flag: make page_zip_validate() compare page headers only */ UNIV_INTERN ibool page_zip_validate_header_only = FALSE; -/************************************************************************** -Check that the compressed and decompressed pages match. */ +/**********************************************************************//** +Check that the compressed and decompressed pages match. +@return TRUE if valid, FALSE if not */ UNIV_INTERN ibool page_zip_validate_low( /*==================*/ - /* out: TRUE if valid, FALSE if not */ - const page_zip_des_t* page_zip,/* in: compressed page */ - const page_t* page, /* in: uncompressed page */ - ibool sloppy) /* in: FALSE=strict, + const page_zip_des_t* page_zip,/*!< in: compressed page */ + const page_t* page, /*!< in: uncompressed page */ + ibool sloppy) /*!< in: FALSE=strict, TRUE=ignore the MIN_REC_FLAG */ { page_zip_des_t temp_page_zip; @@ -3142,15 +3166,15 @@ func_exit: return(valid); } -/************************************************************************** -Check that the compressed and decompressed pages match. */ +/**********************************************************************//** +Check that the compressed and decompressed pages match. +@return TRUE if valid, FALSE if not */ UNIV_INTERN ibool page_zip_validate( /*==============*/ - /* out: TRUE if valid, FALSE if not */ - const page_zip_des_t* page_zip,/* in: compressed page */ - const page_t* page) /* in: uncompressed page */ + const page_zip_des_t* page_zip,/*!< in: compressed page */ + const page_t* page) /*!< in: uncompressed page */ { return(page_zip_validate_low(page_zip, page, recv_recovery_is_on())); @@ -3158,13 +3182,15 @@ page_zip_validate( #endif /* UNIV_ZIP_DEBUG */ #ifdef UNIV_DEBUG +/**********************************************************************//** +Assert that the compressed and decompressed page headers match. +@return TRUE */ static ibool page_zip_header_cmp( /*================*/ - /* out: TRUE */ - const page_zip_des_t* page_zip,/* in: compressed page */ - const byte* page) /* in: uncompressed page */ + const page_zip_des_t* page_zip,/*!< in: compressed page */ + const byte* page) /*!< in: uncompressed page */ { ut_ad(!memcmp(page_zip->data + FIL_PAGE_PREV, page + FIL_PAGE_PREV, FIL_PAGE_LSN - FIL_PAGE_PREV)); @@ -3177,24 +3203,24 @@ page_zip_header_cmp( } #endif /* UNIV_DEBUG */ -/************************************************************************** +/**********************************************************************//** Write a record on the compressed page that contains externally stored -columns. The data must already have been written to the uncompressed page. */ +columns. The data must already have been written to the uncompressed page. +@return end of modification log */ static byte* page_zip_write_rec_ext( /*===================*/ - /* out: end of modification log */ - page_zip_des_t* page_zip, /* in/out: compressed page */ - const page_t* page, /* in: page containing rec */ - const byte* rec, /* in: record being written */ - dict_index_t* index, /* in: record descriptor */ - const ulint* offsets, /* in: rec_get_offsets(rec, index) */ - ulint create, /* in: nonzero=insert, zero=update */ - ulint trx_id_col, /* in: position of DB_TRX_ID */ - ulint heap_no, /* in: heap number of rec */ - byte* storage, /* in: end of dense page directory */ - byte* data) /* in: end of modification log */ + page_zip_des_t* page_zip, /*!< in/out: compressed page */ + const page_t* page, /*!< in: page containing rec */ + const byte* rec, /*!< in: record being written */ + dict_index_t* index, /*!< in: record descriptor */ + const ulint* offsets, /*!< in: rec_get_offsets(rec, index) */ + ulint create, /*!< in: nonzero=insert, zero=update */ + ulint trx_id_col, /*!< in: position of DB_TRX_ID */ + ulint heap_no, /*!< in: heap number of rec */ + byte* storage, /*!< in: end of dense page directory */ + byte* data) /*!< in: end of modification log */ { const byte* start = rec; ulint i; @@ -3299,18 +3325,18 @@ page_zip_write_rec_ext( return(data); } -/************************************************************************** +/**********************************************************************//** Write an entire record on the compressed page. The data must already have been written to the uncompressed page. */ UNIV_INTERN void page_zip_write_rec( /*===============*/ - page_zip_des_t* page_zip,/* in/out: compressed page */ - const byte* rec, /* in: record being written */ - dict_index_t* index, /* in: the index the record belongs to */ - const ulint* offsets,/* in: rec_get_offsets(rec, index) */ - ulint create) /* in: nonzero=insert, zero=update */ + page_zip_des_t* page_zip,/*!< in/out: compressed page */ + const byte* rec, /*!< in: record being written */ + dict_index_t* index, /*!< in: the index the record belongs to */ + const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ + ulint create) /*!< in: nonzero=insert, zero=update */ { const page_t* page; byte* data; @@ -3318,7 +3344,7 @@ page_zip_write_rec( ulint heap_no; byte* slot; - ut_ad(buf_frame_get_page_zip(rec) == page_zip); + ut_ad(PAGE_ZIP_MATCH(rec, page_zip)); ut_ad(page_zip_simple_validate(page_zip)); ut_ad(page_zip_get_size(page_zip) > PAGE_DATA + page_zip_dir_size(page_zip)); @@ -3487,17 +3513,17 @@ page_zip_write_rec( #endif /* UNIV_ZIP_DEBUG */ } -/*************************************************************** -Parses a log record of writing a BLOB pointer of a record. */ +/***********************************************************//** +Parses a log record of writing a BLOB pointer of a record. +@return end of log record or NULL */ UNIV_INTERN byte* page_zip_parse_write_blob_ptr( /*==========================*/ - /* out: end of log record or NULL */ - byte* ptr, /* in: redo log buffer */ - byte* end_ptr,/* in: redo log buffer end */ - page_t* page, /* in/out: uncompressed page */ - page_zip_des_t* page_zip)/* in/out: compressed page */ + byte* ptr, /*!< in: redo log buffer */ + byte* end_ptr,/*!< in: redo log buffer end */ + page_t* page, /*!< in/out: uncompressed page */ + page_zip_des_t* page_zip)/*!< in/out: compressed page */ { ulint offset; ulint z_offset; @@ -3546,20 +3572,20 @@ corrupt: return(ptr + (2 + 2 + BTR_EXTERN_FIELD_REF_SIZE)); } -/************************************************************************** +/**********************************************************************//** Write a BLOB pointer of a record on the leaf page of a clustered index. The information must already have been updated on the uncompressed page. */ UNIV_INTERN void page_zip_write_blob_ptr( /*====================*/ - page_zip_des_t* page_zip,/* in/out: compressed page */ - const byte* rec, /* in/out: record whose data is being + page_zip_des_t* page_zip,/*!< in/out: compressed page */ + const byte* rec, /*!< in/out: record whose data is being written */ - dict_index_t* index, /* in: index of the page */ - const ulint* offsets,/* in: rec_get_offsets(rec, index) */ - ulint n, /* in: column index */ - mtr_t* mtr) /* in: mini-transaction handle, + dict_index_t* index, /*!< in: index of the page */ + const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ + ulint n, /*!< in: column index */ + mtr_t* mtr) /*!< in: mini-transaction handle, or NULL if no logging is needed */ { const byte* field; @@ -3568,7 +3594,7 @@ page_zip_write_blob_ptr( ulint blob_no; ulint len; - ut_ad(buf_frame_get_page_zip(rec) == page_zip); + ut_ad(PAGE_ZIP_MATCH(rec, page_zip)); ut_ad(page_simple_validate_new((page_t*) page)); ut_ad(page_zip_simple_validate(page_zip)); ut_ad(page_zip_get_size(page_zip) @@ -3610,6 +3636,7 @@ page_zip_write_blob_ptr( #endif /* UNIV_ZIP_DEBUG */ if (mtr) { +#ifndef UNIV_HOTBACKUP byte* log_ptr = mlog_open( mtr, 11 + 2 + 2 + BTR_EXTERN_FIELD_REF_SIZE); if (UNIV_UNLIKELY(!log_ptr)) { @@ -3625,20 +3652,21 @@ page_zip_write_blob_ptr( memcpy(log_ptr, externs, BTR_EXTERN_FIELD_REF_SIZE); log_ptr += BTR_EXTERN_FIELD_REF_SIZE; mlog_close(mtr, log_ptr); +#endif /* !UNIV_HOTBACKUP */ } } -/*************************************************************** -Parses a log record of writing the node pointer of a record. */ +/***********************************************************//** +Parses a log record of writing the node pointer of a record. +@return end of log record or NULL */ UNIV_INTERN byte* page_zip_parse_write_node_ptr( /*==========================*/ - /* out: end of log record or NULL */ - byte* ptr, /* in: redo log buffer */ - byte* end_ptr,/* in: redo log buffer end */ - page_t* page, /* in/out: uncompressed page */ - page_zip_des_t* page_zip)/* in/out: compressed page */ + byte* ptr, /*!< in: redo log buffer */ + byte* end_ptr,/*!< in: redo log buffer end */ + page_t* page, /*!< in/out: uncompressed page */ + page_zip_des_t* page_zip)/*!< in/out: compressed page */ { ulint offset; ulint z_offset; @@ -3705,23 +3733,23 @@ corrupt: return(ptr + (2 + 2 + REC_NODE_PTR_SIZE)); } -/************************************************************************** +/**********************************************************************//** Write the node pointer of a record on a non-leaf compressed page. */ UNIV_INTERN void page_zip_write_node_ptr( /*====================*/ - page_zip_des_t* page_zip,/* in/out: compressed page */ - byte* rec, /* in/out: record */ - ulint size, /* in: data size of rec */ - ulint ptr, /* in: node pointer */ - mtr_t* mtr) /* in: mini-transaction, or NULL */ + page_zip_des_t* page_zip,/*!< in/out: compressed page */ + byte* rec, /*!< in/out: record */ + ulint size, /*!< in: data size of rec */ + ulint ptr, /*!< in: node pointer */ + mtr_t* mtr) /*!< in: mini-transaction, or NULL */ { byte* field; byte* storage; page_t* page = page_align(rec); - ut_ad(buf_frame_get_page_zip(rec) == page_zip); + ut_ad(PAGE_ZIP_MATCH(rec, page_zip)); ut_ad(page_simple_validate_new(page)); ut_ad(page_zip_simple_validate(page_zip)); ut_ad(page_zip_get_size(page_zip) @@ -3752,6 +3780,7 @@ page_zip_write_node_ptr( memcpy(storage, field, REC_NODE_PTR_SIZE); if (mtr) { +#ifndef UNIV_HOTBACKUP byte* log_ptr = mlog_open(mtr, 11 + 2 + 2 + REC_NODE_PTR_SIZE); if (UNIV_UNLIKELY(!log_ptr)) { @@ -3767,28 +3796,29 @@ page_zip_write_node_ptr( memcpy(log_ptr, field, REC_NODE_PTR_SIZE); log_ptr += REC_NODE_PTR_SIZE; mlog_close(mtr, log_ptr); +#endif /* !UNIV_HOTBACKUP */ } } -/************************************************************************** +/**********************************************************************//** Write the trx_id and roll_ptr of a record on a B-tree leaf node page. */ UNIV_INTERN void page_zip_write_trx_id_and_roll_ptr( /*===============================*/ - page_zip_des_t* page_zip,/* in/out: compressed page */ - byte* rec, /* in/out: record */ - const ulint* offsets,/* in: rec_get_offsets(rec, index) */ - ulint trx_id_col,/* in: column number of TRX_ID in rec */ - dulint trx_id, /* in: transaction identifier */ - dulint roll_ptr)/* in: roll_ptr */ + page_zip_des_t* page_zip,/*!< in/out: compressed page */ + byte* rec, /*!< in/out: record */ + const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ + ulint trx_id_col,/*!< in: column number of TRX_ID in rec */ + trx_id_t trx_id, /*!< in: transaction identifier */ + roll_ptr_t roll_ptr)/*!< in: roll_ptr */ { byte* field; byte* storage; page_t* page = page_align(rec); ulint len; - ut_ad(buf_frame_get_page_zip(rec) == page_zip); + ut_ad(PAGE_ZIP_MATCH(rec, page_zip)); ut_ad(page_simple_validate_new(page)); ut_ad(page_zip_simple_validate(page_zip)); ut_ad(page_zip_get_size(page_zip) @@ -3837,7 +3867,7 @@ page_zip_write_trx_id_and_roll_ptr( } #ifdef UNIV_ZIP_DEBUG -/* Set this variable in a debugger to disable page_zip_clear_rec(). +/** Set this variable in a debugger to disable page_zip_clear_rec(). The only observable effect should be the compression ratio due to deleted records not being zeroed out. In rare cases, there can be page_zip_validate() failures on the node_ptr, trx_id and roll_ptr @@ -3845,16 +3875,16 @@ columns if the space is reallocated for a smaller record. */ UNIV_INTERN ibool page_zip_clear_rec_disable; #endif /* UNIV_ZIP_DEBUG */ -/************************************************************************** +/**********************************************************************//** Clear an area on the uncompressed and compressed page, if possible. */ static void page_zip_clear_rec( /*===============*/ - page_zip_des_t* page_zip,/* in/out: compressed page */ - byte* rec, /* in: record to clear */ - dict_index_t* index, /* in: index of rec */ - const ulint* offsets)/* in: rec_get_offsets(rec, index) */ + page_zip_des_t* page_zip,/*!< in/out: compressed page */ + byte* rec, /*!< in: record to clear */ + dict_index_t* index, /*!< in: index of rec */ + const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */ { ulint heap_no; page_t* page = page_align(rec); @@ -3951,16 +3981,16 @@ page_zip_clear_rec( #endif /* UNIV_ZIP_DEBUG */ } -/************************************************************************** +/**********************************************************************//** Write the "deleted" flag of a record on a compressed page. The flag must already have been written on the uncompressed page. */ UNIV_INTERN void page_zip_rec_set_deleted( /*=====================*/ - page_zip_des_t* page_zip,/* in/out: compressed page */ - const byte* rec, /* in: record on the uncompressed page */ - ulint flag) /* in: the deleted flag (nonzero=TRUE) */ + page_zip_des_t* page_zip,/*!< in/out: compressed page */ + const byte* rec, /*!< in: record on the uncompressed page */ + ulint flag) /*!< in: the deleted flag (nonzero=TRUE) */ { byte* slot = page_zip_dir_find(page_zip, page_offset(rec)); ut_a(slot); @@ -3975,16 +4005,16 @@ page_zip_rec_set_deleted( #endif /* UNIV_ZIP_DEBUG */ } -/************************************************************************** +/**********************************************************************//** Write the "owned" flag of a record on a compressed page. The n_owned field must already have been written on the uncompressed page. */ UNIV_INTERN void page_zip_rec_set_owned( /*===================*/ - page_zip_des_t* page_zip,/* in/out: compressed page */ - const byte* rec, /* in: record on the uncompressed page */ - ulint flag) /* in: the owned flag (nonzero=TRUE) */ + page_zip_des_t* page_zip,/*!< in/out: compressed page */ + const byte* rec, /*!< in: record on the uncompressed page */ + ulint flag) /*!< in: the owned flag (nonzero=TRUE) */ { byte* slot = page_zip_dir_find(page_zip, page_offset(rec)); ut_a(slot); @@ -3996,17 +4026,17 @@ page_zip_rec_set_owned( } } -/************************************************************************** +/**********************************************************************//** Insert a record to the dense page directory. */ UNIV_INTERN void page_zip_dir_insert( /*================*/ - page_zip_des_t* page_zip,/* in/out: compressed page */ - const byte* prev_rec,/* in: record after which to insert */ - const byte* free_rec,/* in: record from which rec was + page_zip_des_t* page_zip,/*!< in/out: compressed page */ + const byte* prev_rec,/*!< in: record after which to insert */ + const byte* free_rec,/*!< in: record from which rec was allocated, or NULL */ - byte* rec) /* in: record to insert */ + byte* rec) /*!< in: record to insert */ { ulint n_dense; byte* slot_rec; @@ -4074,18 +4104,18 @@ page_zip_dir_insert( mach_write_to_2(slot_rec - PAGE_ZIP_DIR_SLOT_SIZE, page_offset(rec)); } -/************************************************************************** +/**********************************************************************//** Shift the dense page directory and the array of BLOB pointers when a record is deleted. */ UNIV_INTERN void page_zip_dir_delete( /*================*/ - page_zip_des_t* page_zip,/* in/out: compressed page */ - byte* rec, /* in: record to delete */ - dict_index_t* index, /* in: index of rec */ - const ulint* offsets,/* in: rec_get_offsets(rec) */ - const byte* free) /* in: previous start of the free list */ + page_zip_des_t* page_zip,/*!< in/out: compressed page */ + byte* rec, /*!< in: record to delete */ + dict_index_t* index, /*!< in: index of rec */ + const ulint* offsets,/*!< in: rec_get_offsets(rec) */ + const byte* free) /*!< in: previous start of the free list */ { byte* slot_rec; byte* slot_free; @@ -4172,14 +4202,14 @@ skip_blobs: page_zip_clear_rec(page_zip, rec, index, offsets); } -/************************************************************************** +/**********************************************************************//** Add a slot to the dense page directory. */ UNIV_INTERN void page_zip_dir_add_slot( /*==================*/ - page_zip_des_t* page_zip, /* in/out: compressed page */ - ulint is_clustered) /* in: nonzero for clustered index, + page_zip_des_t* page_zip, /*!< in/out: compressed page */ + ulint is_clustered) /*!< in: nonzero for clustered index, zero for others */ { ulint n_dense; @@ -4228,17 +4258,17 @@ page_zip_dir_add_slot( memmove(stored - PAGE_ZIP_DIR_SLOT_SIZE, stored, dir - stored); } -/*************************************************************** -Parses a log record of writing to the header of a page. */ +/***********************************************************//** +Parses a log record of writing to the header of a page. +@return end of log record or NULL */ UNIV_INTERN byte* page_zip_parse_write_header( /*========================*/ - /* out: end of log record or NULL */ - byte* ptr, /* in: redo log buffer */ - byte* end_ptr,/* in: redo log buffer end */ - page_t* page, /* in/out: uncompressed page */ - page_zip_des_t* page_zip)/* in/out: compressed page */ + byte* ptr, /*!< in: redo log buffer */ + byte* end_ptr,/*!< in: redo log buffer end */ + page_t* page, /*!< in/out: uncompressed page */ + page_zip_des_t* page_zip)/*!< in/out: compressed page */ { ulint offset; ulint len; @@ -4286,15 +4316,16 @@ corrupt: return(ptr + len); } -/************************************************************************** +#ifndef UNIV_HOTBACKUP +/**********************************************************************//** Write a log record of writing to the uncompressed header portion of a page. */ UNIV_INTERN void page_zip_write_header_log( /*======================*/ - const byte* data, /* in: data on the uncompressed page */ - ulint length, /* in: length of the data */ - mtr_t* mtr) /* in: mini-transaction */ + const byte* data, /*!< in: data on the uncompressed page */ + ulint length, /*!< in: length of the data */ + mtr_t* mtr) /*!< in: mini-transaction */ { byte* log_ptr = mlog_open(mtr, 11 + 1 + 1); ulint offset = page_offset(data); @@ -4320,8 +4351,9 @@ page_zip_write_header_log( mlog_catenate_string(mtr, data, length); } +#endif /* !UNIV_HOTBACKUP */ -/************************************************************************** +/**********************************************************************//** Reorganize and compress a page. This is a low-level operation for compressed pages, to be used when page_zip_compress() fails. On success, a redo log entry MLOG_ZIP_PAGE_COMPRESS will be written. @@ -4329,20 +4361,19 @@ The function btr_page_reorganize() should be preferred whenever possible. IMPORTANT: if page_zip_reorganize() is invoked on a leaf page of a non-clustered index, the caller must update the insert buffer free bits in the same mini-transaction in such a way that the modification -will be redo-logged. */ +will be redo-logged. +@return TRUE on success, FALSE on failure; page and page_zip will be +left intact on failure. */ UNIV_INTERN ibool page_zip_reorganize( /*================*/ - /* out: TRUE on success, FALSE on failure; - page and page_zip will be left intact - on failure. */ - buf_block_t* block, /* in/out: page with compressed page; + buf_block_t* block, /*!< in/out: page with compressed page; on the compressed page, in: size; out: data, n_blobs, m_start, m_end, m_nonempty */ - dict_index_t* index, /* in: index of the B-tree node */ - mtr_t* mtr) /* in: mini-transaction */ + dict_index_t* index, /*!< in: index of the B-tree node */ + mtr_t* mtr) /*!< in: mini-transaction */ { page_zip_des_t* page_zip = buf_block_get_page_zip(block); page_t* page = buf_block_get_frame(block); @@ -4352,6 +4383,7 @@ page_zip_reorganize( ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); ut_ad(page_is_comp(page)); + ut_ad(!dict_index_is_ibuf(index)); /* Note that page_zip_validate(page_zip, page) may fail here. */ UNIV_MEM_ASSERT_RW(page, UNIV_PAGE_SIZE); UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); @@ -4359,10 +4391,15 @@ page_zip_reorganize( /* Disable logging */ log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); +#ifndef UNIV_HOTBACKUP temp_block = buf_block_alloc(0); - temp_page = temp_block->frame; - btr_search_drop_page_hash_index(block); + block->check_index_page_at_flush = TRUE; +#else /* !UNIV_HOTBACKUP */ + ut_ad(block == back_block1); + temp_block = back_block2; +#endif /* !UNIV_HOTBACKUP */ + temp_page = temp_block->frame; /* Copy the old page to temporary space */ buf_frame_copy(temp_page, page); @@ -4371,7 +4408,6 @@ page_zip_reorganize( segment headers, next page-field, etc.) is preserved intact */ page_create(block, mtr, TRUE); - block->check_index_page_at_flush = TRUE; /* Copy the records from the temporary space to the recreated page; do not copy the lock bits yet */ @@ -4379,8 +4415,13 @@ page_zip_reorganize( page_copy_rec_list_end_no_locks(block, temp_block, page_get_infimum_rec(temp_page), index, mtr); - /* Copy max trx id to recreated page */ - page_set_max_trx_id(block, NULL, page_get_max_trx_id(temp_page)); + + if (!dict_index_is_clust(index) && page_is_leaf(temp_page)) { + /* Copy max trx id to recreated page */ + trx_id_t max_trx_id = page_get_max_trx_id(temp_page); + page_set_max_trx_id(block, NULL, max_trx_id, NULL); + ut_ad(!ut_dulint_is_zero(max_trx_id)); + } /* Restore logging. */ mtr_set_log_mode(mtr, log_mode); @@ -4390,17 +4431,22 @@ page_zip_reorganize( /* Restore the old page and exit. */ buf_frame_copy(page, temp_page); +#ifndef UNIV_HOTBACKUP buf_block_free(temp_block); +#endif /* !UNIV_HOTBACKUP */ return(FALSE); } lock_move_reorganize_page(block, temp_block); +#ifndef UNIV_HOTBACKUP buf_block_free(temp_block); +#endif /* !UNIV_HOTBACKUP */ return(TRUE); } -/************************************************************************** +#ifndef UNIV_HOTBACKUP +/**********************************************************************//** Copy the records of a page byte for byte. Do not copy the page header or trailer, except those B-tree header fields that are directly related to the storage of records. Also copy PAGE_MAX_TRX_ID. @@ -4409,17 +4455,18 @@ UNIV_INTERN void page_zip_copy_recs( /*===============*/ - page_zip_des_t* page_zip, /* out: copy of src_zip + page_zip_des_t* page_zip, /*!< out: copy of src_zip (n_blobs, m_start, m_end, m_nonempty, data[0..size-1]) */ - page_t* page, /* out: copy of src */ - const page_zip_des_t* src_zip, /* in: compressed page */ - const page_t* src, /* in: page */ - dict_index_t* index, /* in: index of the B-tree */ - mtr_t* mtr) /* in: mini-transaction */ + page_t* page, /*!< out: copy of src */ + const page_zip_des_t* src_zip, /*!< in: compressed page */ + const page_t* src, /*!< in: page */ + dict_index_t* index, /*!< in: index of the B-tree */ + mtr_t* mtr) /*!< in: mini-transaction */ { ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr_memo_contains_page(mtr, (page_t*) src, MTR_MEMO_PAGE_X_FIX)); + ut_ad(!dict_index_is_ibuf(index)); #ifdef UNIV_ZIP_DEBUG /* The B-tree operations that call this function may set FIL_PAGE_PREV or PAGE_LEVEL, causing a temporary min_rec_flag @@ -4433,6 +4480,11 @@ page_zip_copy_recs( ut_a(dict_index_is_clust(index)); } + /* The PAGE_MAX_TRX_ID must be set on leaf pages of secondary + indexes. It does not matter on other pages. */ + ut_a(dict_index_is_clust(index) || !page_is_leaf(src) + || !ut_dulint_is_zero(page_get_max_trx_id(src))); + UNIV_MEM_ASSERT_W(page, UNIV_PAGE_SIZE); UNIV_MEM_ASSERT_W(page_zip->data, page_zip_get_size(page_zip)); UNIV_MEM_ASSERT_RW(src, UNIV_PAGE_SIZE); @@ -4486,18 +4538,19 @@ page_zip_copy_recs( page_zip_compress_write_log(page_zip, page, index, mtr); } +#endif /* !UNIV_HOTBACKUP */ -/************************************************************************** -Parses a log record of compressing an index page. */ +/**********************************************************************//** +Parses a log record of compressing an index page. +@return end of log record or NULL */ UNIV_INTERN byte* page_zip_parse_compress( /*====================*/ - /* out: end of log record or NULL */ - byte* ptr, /* in: buffer */ - byte* end_ptr,/* in: buffer end */ - page_t* page, /* out: uncompressed page */ - page_zip_des_t* page_zip)/* out: compressed page */ + byte* ptr, /*!< in: buffer */ + byte* end_ptr,/*!< in: buffer end */ + page_t* page, /*!< out: uncompressed page */ + page_zip_des_t* page_zip)/*!< out: compressed page */ { ulint size; ulint trailer_size; @@ -4547,15 +4600,15 @@ corrupt: return(ptr + 8 + size + trailer_size); } -/************************************************************************** -Calculate the compressed page checksum. */ +/**********************************************************************//** +Calculate the compressed page checksum. +@return page checksum */ UNIV_INTERN ulint page_zip_calc_checksum( /*===================*/ - /* out: page checksum */ - const void* data, /* in: compressed page */ - ulint size) /* in: size of compressed page */ + const void* data, /*!< in: compressed page */ + ulint size) /*!< in: size of compressed page */ { /* Exclude FIL_PAGE_SPACE_OR_CHKSUM, FIL_PAGE_LSN, and FIL_PAGE_FILE_FLUSH_LSN from the checksum. */ |