summaryrefslogtreecommitdiff
path: root/storage/innobase/page/page0page.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/page/page0page.cc')
-rw-r--r--storage/innobase/page/page0page.cc996
1 files changed, 482 insertions, 514 deletions
diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc
index a09f270a54f..89669d09e89 100644
--- a/storage/innobase/page/page0page.cc
+++ b/storage/innobase/page/page0page.cc
@@ -24,17 +24,16 @@ Index page routines
Created 2/2/1994 Heikki Tuuri
*******************************************************/
-#define THIS_MODULE
#include "page0page.h"
#ifdef UNIV_NONINL
#include "page0page.ic"
#endif
-#undef THIS_MODULE
#include "page0cur.h"
#include "page0zip.h"
#include "buf0buf.h"
#include "btr0btr.h"
+#include "row0trunc.h"
#ifndef UNIV_HOTBACKUP
# include "srv0srv.h"
# include "lock0lock.h"
@@ -86,8 +85,7 @@ is 50 x 4 bytes = 200 bytes. */
/***************************************************************//**
Looks for the directory slot which owns the given record.
-@return the directory slot number */
-UNIV_INTERN
+@return the directory slot number */
ulint
page_dir_find_owner_slot(
/*=====================*/
@@ -124,11 +122,9 @@ page_dir_find_owner_slot(
while (UNIV_LIKELY(*(uint16*) slot != rec_offs_bytes)) {
if (UNIV_UNLIKELY(slot == first_slot)) {
- fprintf(stderr,
- "InnoDB: Probable data corruption on"
- " page %lu\n"
- "InnoDB: Original record ",
- (ulong) page_get_page_no(page));
+ ib::error() << "Probable data corruption on page "
+ << page_get_page_no(page)
+ << ". Original record on that page;";
if (page_is_comp(page)) {
fputs("(compact record)", stderr);
@@ -136,20 +132,15 @@ page_dir_find_owner_slot(
rec_print_old(stderr, rec);
}
- fputs("\n"
- "InnoDB: on that page.\n"
- "InnoDB: Cannot find the dir slot for record ",
- stderr);
+ ib::error() << "Cannot find the dir slot for this"
+ " record on that page;";
+
if (page_is_comp(page)) {
fputs("(compact record)", stderr);
} else {
rec_print_old(stderr, page
+ mach_decode_2(rec_offs_bytes));
}
- fputs("\n"
- "InnoDB: on that page!\n", stderr);
-
- buf_page_print(page, 0, 0);
ut_error;
}
@@ -162,7 +153,7 @@ page_dir_find_owner_slot(
/**************************************************************//**
Used to check the consistency of a directory slot.
-@return TRUE if succeed */
+@return TRUE if succeed */
static
ibool
page_dir_slot_check(
@@ -205,7 +196,6 @@ page_dir_slot_check(
/*************************************************************//**
Sets the max trx id field value. */
-UNIV_INTERN
void
page_set_max_trx_id(
/*================*/
@@ -240,8 +230,7 @@ page_set_max_trx_id(
/************************************************************//**
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
+@return pointer to start of allocated buffer, or NULL if allocation fails */
byte*
page_mem_alloc_heap(
/*================*/
@@ -286,63 +275,70 @@ page_create_write_log(
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 */
-{
- 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.
-@return end of log record or NULL */
-UNIV_INTERN
-byte*
-page_parse_create(
-/*==============*/
- byte* ptr, /*!< in: buffer */
- byte* end_ptr MY_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 */
+ ibool comp, /*!< in: TRUE=compact page format */
+ bool is_rtree) /*!< in: whether it is R-tree */
{
- ut_ad(ptr && end_ptr);
-
- /* The record is empty, except for the record initial part */
+ mlog_id_t type;
- if (block) {
- page_create(block, mtr, comp);
+ if (is_rtree) {
+ type = comp ? MLOG_COMP_PAGE_CREATE_RTREE
+ : MLOG_PAGE_CREATE_RTREE;
+ } else {
+ type = comp ? MLOG_COMP_PAGE_CREATE : MLOG_PAGE_CREATE;
}
- return(ptr);
+ mlog_write_initial_log_record(frame, type, mtr);
}
+#else /* !UNIV_HOTBACKUP */
+# define page_create_write_log(frame,mtr,comp,is_rtree) ((void) 0)
+#endif /* !UNIV_HOTBACKUP */
+
+/** The page infimum and supremum of an empty page in ROW_FORMAT=REDUNDANT */
+static const byte infimum_supremum_redundant[] = {
+ /* the infimum record */
+ 0x08/*end offset*/,
+ 0x01/*n_owned*/,
+ 0x00, 0x00/*heap_no=0*/,
+ 0x03/*n_fields=1, 1-byte offsets*/,
+ 0x00, 0x74/* pointer to supremum */,
+ 'i', 'n', 'f', 'i', 'm', 'u', 'm', 0,
+ /* the supremum record */
+ 0x09/*end offset*/,
+ 0x01/*n_owned*/,
+ 0x00, 0x08/*heap_no=1*/,
+ 0x03/*n_fields=1, 1-byte offsets*/,
+ 0x00, 0x00/* end of record list */,
+ 's', 'u', 'p', 'r', 'e', 'm', 'u', 'm', 0
+};
+
+/** The page infimum and supremum of an empty page in ROW_FORMAT=COMPACT */
+static const byte infimum_supremum_compact[] = {
+ /* the infimum record */
+ 0x01/*n_owned=1*/,
+ 0x00, 0x02/* heap_no=0, REC_STATUS_INFIMUM */,
+ 0x00, 0x0d/* pointer to supremum */,
+ 'i', 'n', 'f', 'i', 'm', 'u', 'm', 0,
+ /* the supremum record */
+ 0x01/*n_owned=1*/,
+ 0x00, 0x0b/* heap_no=1, REC_STATUS_SUPREMUM */,
+ 0x00, 0x00/* end of record list */,
+ 's', 'u', 'p', 'r', 'e', 'm', 'u', 'm'
+};
/**********************************************************//**
The index page creation function.
-@return pointer to the page */
+@return pointer to the page */
static
page_t*
page_create_low(
/*============*/
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 */
+ bool is_rtree) /*!< in: if it is an R-Tree page */
{
- page_dir_slot_t* slot;
- mem_heap_t* heap;
- dtuple_t* tuple;
- dfield_t* field;
- byte* heap_top;
- rec_t* infimum_rec;
- rec_t* supremum_rec;
page_t* page;
- dict_index_t* index;
- ulint* offsets;
- ut_ad(block);
#if PAGE_BTR_IBUF_FREE_LIST + FLST_BASE_NODE_SIZE > PAGE_DATA
# error "PAGE_BTR_IBUF_FREE_LIST + FLST_BASE_NODE_SIZE > PAGE_DATA"
#endif
@@ -350,175 +346,132 @@ page_create_low(
# error "PAGE_BTR_IBUF_FREE_LIST_NODE + FLST_NODE_SIZE > PAGE_DATA"
#endif
- /* The infimum and supremum records use a dummy index. */
- if (UNIV_LIKELY(comp)) {
- index = dict_ind_compact;
- } else {
- index = dict_ind_redundant;
- }
-
- /* 1. INCREMENT MODIFY CLOCK */
buf_block_modify_clock_inc(block);
page = buf_block_get_frame(block);
- fil_page_set_type(page, FIL_PAGE_INDEX);
-
- heap = mem_heap_create(200);
-
- /* 3. CREATE THE INFIMUM AND SUPREMUM RECORDS */
-
- /* Create first a data tuple for infimum record */
- tuple = dtuple_create(heap, 1);
- dtuple_set_info_bits(tuple, REC_STATUS_INFIMUM);
- field = dtuple_get_nth_field(tuple, 0);
-
- dfield_set_data(field, "infimum", 8);
- dtype_set(dfield_get_type(field),
- DATA_VARCHAR, DATA_ENGLISH | DATA_NOT_NULL, 8);
- /* Set the corresponding physical record to its place in the page
- record heap */
-
- heap_top = page + PAGE_DATA;
-
- infimum_rec = rec_convert_dtuple_to_rec(heap_top, index, tuple, 0);
-
- if (UNIV_LIKELY(comp)) {
- ut_a(infimum_rec == page + PAGE_NEW_INFIMUM);
-
- rec_set_n_owned_new(infimum_rec, NULL, 1);
- rec_set_heap_no_new(infimum_rec, 0);
+ if (is_rtree) {
+ fil_page_set_type(page, FIL_PAGE_RTREE);
} else {
- ut_a(infimum_rec == page + PAGE_OLD_INFIMUM);
-
- rec_set_n_owned_old(infimum_rec, 1);
- rec_set_heap_no_old(infimum_rec, 0);
- }
-
- offsets = rec_get_offsets(infimum_rec, index, NULL,
- ULINT_UNDEFINED, &heap);
-
- heap_top = rec_get_end(infimum_rec, offsets);
-
- /* Create then a tuple for supremum */
-
- tuple = dtuple_create(heap, 1);
- dtuple_set_info_bits(tuple, REC_STATUS_SUPREMUM);
- field = dtuple_get_nth_field(tuple, 0);
-
- dfield_set_data(field, "supremum", comp ? 8 : 9);
- dtype_set(dfield_get_type(field),
- DATA_VARCHAR, DATA_ENGLISH | DATA_NOT_NULL, comp ? 8 : 9);
-
- supremum_rec = rec_convert_dtuple_to_rec(heap_top, index, tuple, 0);
-
- if (UNIV_LIKELY(comp)) {
- ut_a(supremum_rec == page + PAGE_NEW_SUPREMUM);
-
- rec_set_n_owned_new(supremum_rec, NULL, 1);
- rec_set_heap_no_new(supremum_rec, 1);
+ fil_page_set_type(page, FIL_PAGE_INDEX);
+ }
+
+ memset(page + PAGE_HEADER, 0, PAGE_HEADER_PRIV_END);
+ page[PAGE_HEADER + PAGE_N_DIR_SLOTS + 1] = 2;
+ page[PAGE_HEADER + PAGE_DIRECTION + 1] = PAGE_NO_DIRECTION;
+
+ if (comp) {
+ page[PAGE_HEADER + PAGE_N_HEAP] = 0x80;/*page_is_comp()*/
+ page[PAGE_HEADER + PAGE_N_HEAP + 1] = PAGE_HEAP_NO_USER_LOW;
+ page[PAGE_HEADER + PAGE_HEAP_TOP + 1] = PAGE_NEW_SUPREMUM_END;
+ memcpy(page + PAGE_DATA, infimum_supremum_compact,
+ sizeof infimum_supremum_compact);
+ memset(page
+ + PAGE_NEW_SUPREMUM_END, 0,
+ UNIV_PAGE_SIZE - PAGE_DIR - PAGE_NEW_SUPREMUM_END);
+ page[UNIV_PAGE_SIZE - PAGE_DIR - PAGE_DIR_SLOT_SIZE * 2 + 1]
+ = PAGE_NEW_SUPREMUM;
+ page[UNIV_PAGE_SIZE - PAGE_DIR - PAGE_DIR_SLOT_SIZE + 1]
+ = PAGE_NEW_INFIMUM;
} else {
- ut_a(supremum_rec == page + PAGE_OLD_SUPREMUM);
-
- rec_set_n_owned_old(supremum_rec, 1);
- rec_set_heap_no_old(supremum_rec, 1);
+ page[PAGE_HEADER + PAGE_N_HEAP + 1] = PAGE_HEAP_NO_USER_LOW;
+ page[PAGE_HEADER + PAGE_HEAP_TOP + 1] = PAGE_OLD_SUPREMUM_END;
+ memcpy(page + PAGE_DATA, infimum_supremum_redundant,
+ sizeof infimum_supremum_redundant);
+ memset(page
+ + PAGE_OLD_SUPREMUM_END, 0,
+ UNIV_PAGE_SIZE - PAGE_DIR - PAGE_OLD_SUPREMUM_END);
+ page[UNIV_PAGE_SIZE - PAGE_DIR - PAGE_DIR_SLOT_SIZE * 2 + 1]
+ = PAGE_OLD_SUPREMUM;
+ page[UNIV_PAGE_SIZE - PAGE_DIR - PAGE_DIR_SLOT_SIZE + 1]
+ = PAGE_OLD_INFIMUM;
}
- offsets = rec_get_offsets(supremum_rec, index, offsets,
- ULINT_UNDEFINED, &heap);
- heap_top = rec_get_end(supremum_rec, offsets);
-
- ut_ad(heap_top == page
- + (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END));
-
- mem_heap_free(heap);
-
- /* 4. INITIALIZE THE PAGE */
-
- page_header_set_field(page, NULL, PAGE_N_DIR_SLOTS, 2);
- page_header_set_ptr(page, NULL, PAGE_HEAP_TOP, heap_top);
- page_header_set_field(page, NULL, PAGE_N_HEAP, comp
- ? 0x8000 | PAGE_HEAP_NO_USER_LOW
- : PAGE_HEAP_NO_USER_LOW);
- page_header_set_ptr(page, NULL, PAGE_FREE, NULL);
- page_header_set_field(page, NULL, PAGE_GARBAGE, 0);
- page_header_set_ptr(page, NULL, PAGE_LAST_INSERT, NULL);
- 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, 0, NULL);
- memset(heap_top, 0, UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START
- - page_offset(heap_top));
-
- /* 5. SET POINTERS IN RECORDS AND DIR SLOTS */
-
- /* Set the slots to point to infimum and supremum. */
-
- slot = page_dir_get_nth_slot(page, 0);
- page_dir_slot_set_rec(slot, infimum_rec);
-
- slot = page_dir_get_nth_slot(page, 1);
- page_dir_slot_set_rec(slot, supremum_rec);
-
- /* Set the next pointers in infimum and supremum */
+ return(page);
+}
- if (UNIV_LIKELY(comp)) {
- rec_set_next_offs_new(infimum_rec, PAGE_NEW_SUPREMUM);
- rec_set_next_offs_new(supremum_rec, 0);
- } else {
- rec_set_next_offs_old(infimum_rec, PAGE_OLD_SUPREMUM);
- rec_set_next_offs_old(supremum_rec, 0);
+/** Parses a redo log record of creating a page.
+@param[in,out] block buffer block, or NULL
+@param[in] comp nonzero=compact page format
+@param[in] is_rtree whether it is rtree page */
+void
+page_parse_create(
+ buf_block_t* block,
+ ulint comp,
+ bool is_rtree)
+{
+ if (block != NULL) {
+ page_create_low(block, comp, is_rtree);
}
-
- return(page);
}
/**********************************************************//**
-Create an uncompressed B-tree index page.
-@return pointer to the page */
-UNIV_INTERN
+Create an uncompressed B-tree or R-tree index page.
+@return pointer to the page */
page_t*
page_create(
/*========*/
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 */
+ ulint comp, /*!< in: nonzero=compact page format */
+ bool is_rtree) /*!< in: whether it is a R-Tree page */
{
- page_create_write_log(buf_block_get_frame(block), mtr, comp);
- return(page_create_low(block, comp));
+ ut_ad(mtr->is_named_space(block->page.id.space()));
+ page_create_write_log(buf_block_get_frame(block), mtr, comp, is_rtree);
+ return(page_create_low(block, comp, is_rtree));
}
/**********************************************************//**
Create a compressed B-tree index page.
-@return pointer to the page */
-UNIV_INTERN
+@return pointer to the page */
page_t*
page_create_zip(
/*============*/
- 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 */
- trx_id_t max_trx_id, /*!< in: PAGE_MAX_TRX_ID */
- mtr_t* mtr) /*!< in/out: mini-transaction */
+ buf_block_t* block, /*!< in/out: a buffer frame
+ where the page is created */
+ dict_index_t* index, /*!< in: the index of the
+ page, or NULL when applying
+ TRUNCATE log
+ record during recovery */
+ ulint level, /*!< in: the B-tree level
+ of the page */
+ trx_id_t max_trx_id, /*!< in: PAGE_MAX_TRX_ID */
+ const redo_page_compress_t* page_comp_info,
+ /*!< in: used for applying
+ TRUNCATE log
+ record during recovery */
+ mtr_t* mtr) /*!< in/out: mini-transaction
+ handle */
{
- page_t* page;
- page_zip_des_t* page_zip = buf_block_get_page_zip(block);
+ page_t* page;
+ page_zip_des_t* page_zip = buf_block_get_page_zip(block);
+ bool is_spatial;
ut_ad(block);
ut_ad(page_zip);
- ut_ad(index);
- ut_ad(dict_table_is_comp(index->table));
+ ut_ad(index == NULL || dict_table_is_comp(index->table));
+ is_spatial = index ? dict_index_is_spatial(index)
+ : page_comp_info->type & DICT_SPATIAL;
- page = page_create_low(block, TRUE);
+ page = page_create_low(block, TRUE, is_spatial);
mach_write_to_2(PAGE_HEADER + PAGE_LEVEL + page, level);
mach_write_to_8(PAGE_HEADER + PAGE_MAX_TRX_ID + page, max_trx_id);
- if (!page_zip_compress(page_zip, page, index,
- page_zip_level, mtr)) {
- /* The compression of a newly created page
- should always succeed. */
+ if (truncate_t::s_fix_up_active) {
+ /* Compress the index page created when applying
+ TRUNCATE log during recovery */
+ if (!page_zip_compress(page_zip, page, index, page_zip_level,
+ page_comp_info, NULL)) {
+ /* The compression of a newly created
+ page should always succeed. */
+ ut_error;
+ }
+
+ } else if (!page_zip_compress(page_zip, page, index,
+ page_zip_level, NULL, mtr)) {
+ /* The compression of a newly created
+ page should always succeed. */
ut_error;
}
@@ -527,7 +480,6 @@ page_create_zip(
/**********************************************************//**
Empty a previously created B-tree index page. */
-UNIV_INTERN
void
page_create_empty(
/*==============*/
@@ -539,9 +491,15 @@ page_create_empty(
const page_t* page = buf_block_get_frame(block);
page_zip_des_t* page_zip= buf_block_get_page_zip(block);
- ut_ad(fil_page_get_type(page) == FIL_PAGE_INDEX);
+ ut_ad(fil_page_index_page_check(page));
- if (dict_index_is_sec_or_ibuf(index) && page_is_leaf(page)) {
+ /* Multiple transactions cannot simultaneously operate on the
+ same temp-table in parallel.
+ max_trx_id is ignored for temp tables because it not required
+ for MVCC. */
+ if (dict_index_is_sec_or_ibuf(index)
+ && !dict_table_is_temporary(index->table)
+ && page_is_leaf(page)) {
max_trx_id = page_get_max_trx_id(page);
ut_ad(max_trx_id);
}
@@ -549,9 +507,10 @@ page_create_empty(
if (page_zip) {
page_create_zip(block, index,
page_header_get_field(page, PAGE_LEVEL),
- max_trx_id, mtr);
+ max_trx_id, NULL, mtr);
} else {
- page_create(block, mtr, page_is_comp(page));
+ page_create(block, mtr, page_is_comp(page),
+ dict_index_is_spatial(index));
if (max_trx_id) {
page_update_max_trx_id(
@@ -568,7 +527,6 @@ IMPORTANT: The caller will have to update IBUF_BITMAP_FREE
if new_block is a compressed leaf page in a secondary index.
This has to be done either within the same mini-transaction,
or by invoking ibuf_reset_free_bits() before mtr_commit(). */
-UNIV_INTERN
void
page_copy_rec_list_end_no_locks(
/*============================*/
@@ -610,22 +568,10 @@ page_copy_rec_list_end_no_locks(
ins_rec = page_cur_insert_rec_low(cur2, index,
cur1_rec, offsets, mtr);
if (UNIV_UNLIKELY(!ins_rec)) {
- /* Track an assertion failure reported on the mailing
- list on June 18th, 2003 */
-
- buf_page_print(new_page, 0,
- BUF_PAGE_PRINT_NO_CRASH);
- buf_page_print(page_align(rec), 0,
- BUF_PAGE_PRINT_NO_CRASH);
- ut_print_timestamp(stderr);
-
- fprintf(stderr,
- "InnoDB: rec offset %lu, cur1 offset %lu,"
- " cur2 offset %lu\n",
- (ulong) page_offset(rec),
- (ulong) page_offset(page_cur_get_rec(&cur1)),
- (ulong) page_offset(cur2));
- ut_error;
+ ib::fatal() << "Rec offset " << page_offset(rec)
+ << ", cur1 offset "
+ << page_offset(page_cur_get_rec(&cur1))
+ << ", cur2 offset " << page_offset(cur2);
}
page_cur_move_to_next(&cur1);
@@ -650,7 +596,6 @@ or by invoking ibuf_reset_free_bits() before mtr_commit().
@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(
/*===================*/
@@ -665,7 +610,9 @@ page_copy_rec_list_end(
page_t* page = page_align(rec);
rec_t* ret = page_rec_get_next(
page_get_infimum_rec(new_page));
- ulint log_mode = 0; /* remove warning */
+ ulint num_moved = 0;
+ rtr_rec_move_t* rec_move = NULL;
+ mem_heap_t* heap = NULL;
#ifdef UNIV_ZIP_DEBUG
if (new_page_zip) {
@@ -685,6 +632,8 @@ page_copy_rec_list_end(
/* Here, "ret" may be pointing to a user record or the
predefined supremum record. */
+ mtr_log_t log_mode = MTR_LOG_NONE;
+
if (new_page_zip) {
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
}
@@ -693,14 +642,39 @@ page_copy_rec_list_end(
page_copy_rec_list_end_to_created_page(new_page, rec,
index, mtr);
} else {
- page_copy_rec_list_end_no_locks(new_block, block, rec,
- index, mtr);
+ if (dict_index_is_spatial(index)) {
+ ulint max_to_move = page_get_n_recs(
+ buf_block_get_frame(block));
+ heap = mem_heap_create(256);
+
+ rec_move = static_cast<rtr_rec_move_t*>(mem_heap_alloc(
+ heap,
+ sizeof (*rec_move) * max_to_move));
+
+ /* For spatial index, we need to insert recs one by one
+ to keep recs ordered. */
+ rtr_page_copy_rec_list_end_no_locks(new_block,
+ block, rec, index,
+ heap, rec_move,
+ max_to_move,
+ &num_moved,
+ mtr);
+ } else {
+ page_copy_rec_list_end_no_locks(new_block, block, rec,
+ index, mtr);
+ }
}
/* Update PAGE_MAX_TRX_ID on the uncompressed page.
Modifications will be redo logged and copied to the compressed
- page in page_zip_compress() or page_zip_reorganize() below. */
- if (dict_index_is_sec_or_ibuf(index) && page_is_leaf(page)) {
+ page in page_zip_compress() or page_zip_reorganize() below.
+ Multiple transactions cannot simultaneously operate on the
+ same temp-table in parallel.
+ max_trx_id is ignored for temp tables because it not required
+ for MVCC. */
+ if (dict_index_is_sec_or_ibuf(index)
+ && page_is_leaf(page)
+ && !dict_table_is_temporary(index->table)) {
page_update_max_trx_id(new_block, NULL,
page_get_max_trx_id(page), mtr);
}
@@ -708,8 +682,11 @@ page_copy_rec_list_end(
if (new_page_zip) {
mtr_set_log_mode(mtr, log_mode);
- if (!page_zip_compress(new_page_zip, new_page,
- index, page_zip_level, mtr)) {
+ if (!page_zip_compress(new_page_zip,
+ new_page,
+ index,
+ page_zip_level,
+ NULL, mtr)) {
/* Before trying to reorganize the page,
store the number of preceding records on the page. */
ulint ret_pos
@@ -723,15 +700,16 @@ page_copy_rec_list_end(
if (!page_zip_reorganize(new_block, index, mtr)) {
- btr_blob_dbg_remove(new_page, index,
- "copy_end_reorg_fail");
if (!page_zip_decompress(new_page_zip,
new_page, FALSE)) {
ut_error;
}
ut_ad(page_validate(new_page, index));
- btr_blob_dbg_add(new_page, index,
- "copy_end_reorg_fail");
+
+ if (heap) {
+ mem_heap_free(heap);
+ }
+
return(NULL);
} else {
/* The page was reorganized:
@@ -747,7 +725,15 @@ page_copy_rec_list_end(
/* Update the lock table and possible hash index */
- lock_move_rec_list_end(new_block, block, rec);
+ if (dict_index_is_spatial(index) && rec_move) {
+ lock_rtr_move_rec_list(new_block, block, rec_move, num_moved);
+ } else if (!dict_table_is_locking_disabled(index->table)) {
+ lock_move_rec_list_end(new_block, block, rec);
+ }
+
+ if (heap) {
+ mem_heap_free(heap);
+ }
btr_search_move_or_delete_hash_entries(new_block, block, index);
@@ -766,7 +752,6 @@ or by invoking ibuf_reset_free_bits() before mtr_commit().
@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(
/*=====================*/
@@ -780,8 +765,9 @@ page_copy_rec_list_start(
page_zip_des_t* new_page_zip = buf_block_get_page_zip(new_block);
page_cur_t cur1;
rec_t* cur2;
- ulint log_mode = 0 /* remove warning */;
mem_heap_t* heap = NULL;
+ ulint num_moved = 0;
+ rtr_rec_move_t* rec_move = NULL;
rec_t* ret
= page_rec_get_prev(page_get_supremum_rec(new_page));
ulint offsets_[REC_OFFS_NORMAL_SIZE];
@@ -796,6 +782,8 @@ page_copy_rec_list_start(
return(ret);
}
+ mtr_log_t log_mode = MTR_LOG_NONE;
+
if (new_page_zip) {
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
}
@@ -806,27 +794,45 @@ page_copy_rec_list_start(
cur2 = ret;
/* Copy records from the original page to the new page */
+ if (dict_index_is_spatial(index)) {
+ ulint max_to_move = page_get_n_recs(
+ buf_block_get_frame(block));
+ heap = mem_heap_create(256);
+
+ rec_move = static_cast<rtr_rec_move_t*>(mem_heap_alloc(
+ heap,
+ sizeof (*rec_move) * max_to_move));
+
+ /* For spatial index, we need to insert recs one by one
+ to keep recs ordered. */
+ rtr_page_copy_rec_list_start_no_locks(new_block,
+ block, rec, index, heap,
+ rec_move, max_to_move,
+ &num_moved, mtr);
+ } else {
- while (page_cur_get_rec(&cur1) != rec) {
- rec_t* cur1_rec = page_cur_get_rec(&cur1);
- offsets = rec_get_offsets(cur1_rec, index, offsets,
- ULINT_UNDEFINED, &heap);
- cur2 = page_cur_insert_rec_low(cur2, index,
- cur1_rec, offsets, mtr);
- ut_a(cur2);
-
- page_cur_move_to_next(&cur1);
- }
+ while (page_cur_get_rec(&cur1) != rec) {
+ rec_t* cur1_rec = page_cur_get_rec(&cur1);
+ offsets = rec_get_offsets(cur1_rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ cur2 = page_cur_insert_rec_low(cur2, index,
+ cur1_rec, offsets, mtr);
+ ut_a(cur2);
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
+ page_cur_move_to_next(&cur1);
+ }
}
/* Update PAGE_MAX_TRX_ID on the uncompressed page.
Modifications will be redo logged and copied to the compressed
- page in page_zip_compress() or page_zip_reorganize() below. */
+ page in page_zip_compress() or page_zip_reorganize() below.
+ Multiple transactions cannot simultaneously operate on the
+ same temp-table in parallel.
+ max_trx_id is ignored for temp tables because it not required
+ for MVCC. */
if (dict_index_is_sec_or_ibuf(index)
- && page_is_leaf(page_align(rec))) {
+ && page_is_leaf(page_align(rec))
+ && !dict_table_is_temporary(index->table)) {
page_update_max_trx_id(new_block, NULL,
page_get_max_trx_id(page_align(rec)),
mtr);
@@ -839,8 +845,7 @@ page_copy_rec_list_start(
goto zip_reorganize;);
if (!page_zip_compress(new_page_zip, new_page, index,
- page_zip_level, mtr)) {
-
+ page_zip_level, NULL, mtr)) {
ulint ret_pos;
#ifndef DBUG_OFF
zip_reorganize:
@@ -857,16 +862,17 @@ zip_reorganize:
if (UNIV_UNLIKELY
(!page_zip_reorganize(new_block, index, mtr))) {
- btr_blob_dbg_remove(new_page, index,
- "copy_start_reorg_fail");
if (UNIV_UNLIKELY
(!page_zip_decompress(new_page_zip,
new_page, FALSE))) {
ut_error;
}
ut_ad(page_validate(new_page, index));
- btr_blob_dbg_add(new_page, index,
- "copy_start_reorg_fail");
+
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
+ }
+
return(NULL);
}
@@ -877,7 +883,15 @@ zip_reorganize:
/* Update the lock table and possible hash index */
- lock_move_rec_list_start(new_block, block, rec, ret);
+ if (dict_index_is_spatial(index)) {
+ lock_rtr_move_rec_list(new_block, block, rec_move, num_moved);
+ } else if (!dict_table_is_locking_disabled(index->table)) {
+ lock_move_rec_list_start(new_block, block, rec, ret);
+ }
+
+ if (heap) {
+ mem_heap_free(heap);
+ }
btr_search_move_or_delete_hash_entries(new_block, block, index);
@@ -892,7 +906,7 @@ 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:
+ mlog_id_t type, /*!< in: operation type:
MLOG_LIST_END_DELETE, ... */
mtr_t* mtr) /*!< in: mtr */
{
@@ -915,12 +929,11 @@ page_delete_rec_list_write_log(
/**********************************************************//**
Parses a log record of a record list end or start deletion.
-@return end of log record or NULL */
-UNIV_INTERN
+@return end of log record or NULL */
byte*
page_parse_delete_rec_list(
/*=======================*/
- byte type, /*!< in: MLOG_LIST_END_DELETE,
+ mlog_id_t type, /*!< in: MLOG_LIST_END_DELETE,
MLOG_LIST_START_DELETE,
MLOG_COMP_LIST_END_DELETE or
MLOG_COMP_LIST_START_DELETE */
@@ -972,7 +985,6 @@ page_parse_delete_rec_list(
/*************************************************************//**
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(
/*=====================*/
@@ -1053,7 +1065,7 @@ delete_all:
: MLOG_LIST_END_DELETE, mtr);
if (page_zip) {
- ulint log_mode;
+ mtr_log_t log_mode;
ut_a(page_is_comp(page));
/* Individual deletes are not logged */
@@ -1168,9 +1180,6 @@ delete_all:
/* Remove the record chain segment from the record chain */
page_rec_set_next(prev_rec, page_get_supremum_rec(page));
- btr_blob_dbg_op(page, rec, index, "delete_end",
- btr_blob_dbg_remove_rec);
-
/* Catenate the deleted chain segment to the page free list */
page_rec_set_next(last_rec, page_header_get_ptr(page, PAGE_FREE));
@@ -1186,7 +1195,6 @@ delete_all:
/*************************************************************//**
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(
/*=======================*/
@@ -1196,11 +1204,9 @@ page_delete_rec_list_start(
mtr_t* mtr) /*!< in: mtr */
{
page_cur_t cur1;
- ulint log_mode;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
mem_heap_t* heap = NULL;
- byte type;
rec_offs_init(offsets_);
@@ -1231,6 +1237,8 @@ page_delete_rec_list_start(
return;
}
+ mlog_id_t type;
+
if (page_rec_is_comp(rec)) {
type = MLOG_COMP_LIST_START_DELETE;
} else {
@@ -1244,7 +1252,7 @@ page_delete_rec_list_start(
/* Individual deletes are not logged */
- log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
+ mtr_log_t log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
while (page_cur_get_rec(&cur1) != rec) {
offsets = rec_get_offsets(page_cur_get_rec(&cur1), index,
@@ -1273,7 +1281,6 @@ or by invoking ibuf_reset_free_bits() before mtr_commit().
@return TRUE on success; FALSE on compression failure (new_block will
be decompressed) */
-UNIV_INTERN
ibool
page_move_rec_list_end(
/*===================*/
@@ -1289,6 +1296,8 @@ page_move_rec_list_end(
ulint old_n_recs;
ulint new_n_recs;
+ ut_ad(!dict_index_is_spatial(index));
+
old_data_size = page_get_data_size(new_page);
old_n_recs = page_get_n_recs(new_page);
#ifdef UNIV_ZIP_DEBUG
@@ -1332,8 +1341,7 @@ if new_block is a compressed leaf page in a secondary index.
This has to be done either within the same mini-transaction,
or by invoking ibuf_reset_free_bits() before mtr_commit().
-@return TRUE on success; FALSE on compression failure */
-UNIV_INTERN
+@return TRUE on success; FALSE on compression failure */
ibool
page_move_rec_list_start(
/*=====================*/
@@ -1434,7 +1442,6 @@ page_dir_add_slot(
/****************************************************************//**
Splits a directory slot which owns too many records. */
-UNIV_INTERN
void
page_dir_split_slot(
/*================*/
@@ -1497,7 +1504,6 @@ page_dir_split_slot(
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. */
-UNIV_INTERN
void
page_dir_balance_slot(
/*==================*/
@@ -1567,8 +1573,7 @@ page_dir_balance_slot(
/************************************************************//**
Returns the nth record of the record list.
This is the inverse function of page_rec_get_n_recs_before().
-@return nth record */
-UNIV_INTERN
+@return nth record */
const rec_t*
page_rec_get_nth_const(
/*===================*/
@@ -1620,8 +1625,7 @@ page_rec_get_nth_const(
/***************************************************************//**
Returns the number of records before the given record in chain.
The number includes infimum and supremum records.
-@return number of records */
-UNIV_INTERN
+@return number of records */
ulint
page_rec_get_n_recs_before(
/*=======================*/
@@ -1686,7 +1690,6 @@ page_rec_get_n_recs_before(
/************************************************************//**
Prints record contents including the data relevant only in
the index page context. */
-UNIV_INTERN
void
page_rec_print(
/*===========*/
@@ -1696,17 +1699,13 @@ page_rec_print(
ut_a(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
rec_print_new(stderr, rec, offsets);
if (page_rec_is_comp(rec)) {
- fprintf(stderr,
- " n_owned: %lu; heap_no: %lu; next rec: %lu\n",
- (ulong) rec_get_n_owned_new(rec),
- (ulong) rec_get_heap_no_new(rec),
- (ulong) rec_get_next_offs(rec, TRUE));
+ ib::info() << "n_owned: " << rec_get_n_owned_new(rec)
+ << "; heap_no: " << rec_get_heap_no_new(rec)
+ << "; next rec: " << rec_get_next_offs(rec, TRUE);
} else {
- fprintf(stderr,
- " n_owned: %lu; heap_no: %lu; next rec: %lu\n",
- (ulong) rec_get_n_owned_old(rec),
- (ulong) rec_get_heap_no_old(rec),
- (ulong) rec_get_next_offs(rec, FALSE));
+ ib::info() << "n_owned: " << rec_get_n_owned_old(rec)
+ << "; heap_no: " << rec_get_heap_no_old(rec)
+ << "; next rec: " << rec_get_next_offs(rec, FALSE);
}
page_rec_check(rec);
@@ -1717,7 +1716,6 @@ page_rec_print(
/***************************************************************//**
This is used to print the contents of the directory for
debugging purposes. */
-UNIV_INTERN
void
page_dir_print(
/*===========*/
@@ -1759,7 +1757,6 @@ page_dir_print(
/***************************************************************//**
This is used to print the contents of the page record list for
debugging purposes. */
-UNIV_INTERN
void
page_print_list(
/*============*/
@@ -1778,7 +1775,7 @@ page_print_list(
ut_a((ibool)!!page_is_comp(page) == dict_table_is_comp(index->table));
- fprintf(stderr,
+ fprint(stderr,
"--------------------------------\n"
"PAGE RECORD LIST\n"
"Page address %p\n", page);
@@ -1829,7 +1826,6 @@ page_print_list(
/***************************************************************//**
Prints the info in a page header. */
-UNIV_INTERN
void
page_header_print(
/*==============*/
@@ -1857,7 +1853,6 @@ page_header_print(
/***************************************************************//**
This is used to print the contents of the page for
debugging purposes. */
-UNIV_INTERN
void
page_print(
/*=======*/
@@ -1881,8 +1876,7 @@ page_print(
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.
-@return TRUE if ok */
-UNIV_INTERN
+@return TRUE if ok */
ibool
page_rec_validate(
/*==============*/
@@ -1908,17 +1902,15 @@ page_rec_validate(
}
if (UNIV_UNLIKELY(!(n_owned <= PAGE_DIR_SLOT_MAX_N_OWNED))) {
- fprintf(stderr,
- "InnoDB: Dir slot of rec %lu, n owned too big %lu\n",
- (ulong) page_offset(rec), (ulong) n_owned);
+ ib::warn() << "Dir slot of rec " << page_offset(rec)
+ << ", n owned too big " << n_owned;
return(FALSE);
}
if (UNIV_UNLIKELY(!(heap_no < page_dir_get_n_heap(page)))) {
- fprintf(stderr,
- "InnoDB: Heap no of rec %lu too big %lu %lu\n",
- (ulong) page_offset(rec), (ulong) heap_no,
- (ulong) page_dir_get_n_heap(page));
+ ib::warn() << "Heap no of rec " << page_offset(rec)
+ << " too big " << heap_no << " "
+ << page_dir_get_n_heap(page);
return(FALSE);
}
@@ -1926,11 +1918,11 @@ page_rec_validate(
}
#ifndef UNIV_HOTBACKUP
+#ifdef UNIV_DEBUG
/***************************************************************//**
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. */
-UNIV_INTERN
void
page_check_dir(
/*===========*/
@@ -1947,28 +1939,24 @@ page_check_dir(
if (UNIV_UNLIKELY(!page_rec_is_infimum_low(infimum_offs))) {
- fprintf(stderr,
- "InnoDB: Page directory corruption:"
- " infimum not pointed to\n");
- buf_page_print(page, 0, 0);
+ ib::fatal() << "Page directory corruption: infimum not"
+ " pointed to";
}
if (UNIV_UNLIKELY(!page_rec_is_supremum_low(supremum_offs))) {
- fprintf(stderr,
- "InnoDB: Page directory corruption:"
- " supremum not pointed to\n");
- buf_page_print(page, 0, 0);
+ ib::fatal() << "Page directory corruption: supremum not"
+ " pointed to";
}
}
+#endif /* UNIV_DEBUG */
#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.
-@return TRUE if ok */
-UNIV_INTERN
+@return TRUE if ok */
ibool
page_simple_validate_old(
/*=====================*/
@@ -1991,9 +1979,8 @@ page_simple_validate_old(
n_slots = page_dir_get_n_slots(page);
if (UNIV_UNLIKELY(n_slots > UNIV_PAGE_SIZE / 4)) {
- fprintf(stderr,
- "InnoDB: Nonsensical number %lu of page dir slots\n",
- (ulong) n_slots);
+ ib::error() << "Nonsensical number " << n_slots
+ << " of page dir slots";
goto func_exit;
}
@@ -2002,13 +1989,12 @@ page_simple_validate_old(
if (UNIV_UNLIKELY(rec_heap_top
> page_dir_get_nth_slot(page, n_slots - 1))) {
-
- fprintf(stderr,
- "InnoDB: Record heap and dir overlap on a page,"
- " heap top %lu, dir %lu\n",
- (ulong) page_header_get_field(page, PAGE_HEAP_TOP),
- (ulong)
- page_offset(page_dir_get_nth_slot(page, n_slots - 1)));
+ ib::error()
+ << "Record heap and dir overlap on a page, heap top "
+ << page_header_get_field(page, PAGE_HEAP_TOP)
+ << ", dir "
+ << page_offset(page_dir_get_nth_slot(page,
+ n_slots - 1));
goto func_exit;
}
@@ -2025,11 +2011,9 @@ page_simple_validate_old(
for (;;) {
if (UNIV_UNLIKELY(rec > rec_heap_top)) {
- fprintf(stderr,
- "InnoDB: Record %lu is above"
- " rec heap top %lu\n",
- (ulong)(rec - page),
- (ulong)(rec_heap_top - page));
+ ib::error() << "Record " << (rec - page)
+ << " is above rec heap top "
+ << (rec_heap_top - page);
goto func_exit;
}
@@ -2039,22 +2023,18 @@ page_simple_validate_old(
if (UNIV_UNLIKELY(rec_get_n_owned_old(rec)
!= own_count)) {
- fprintf(stderr,
- "InnoDB: Wrong owned count %lu, %lu,"
- " rec %lu\n",
- (ulong) rec_get_n_owned_old(rec),
- (ulong) own_count,
- (ulong)(rec - page));
+ ib::error() << "Wrong owned count "
+ << rec_get_n_owned_old(rec)
+ << ", " << own_count << ", rec "
+ << (rec - page);
goto func_exit;
}
if (UNIV_UNLIKELY
(page_dir_slot_get_rec(slot) != rec)) {
- fprintf(stderr,
- "InnoDB: Dir slot does not point"
- " to right rec %lu\n",
- (ulong)(rec - page));
+ ib::error() << "Dir slot does not point"
+ " to right rec " << (rec - page);
goto func_exit;
}
@@ -2075,11 +2055,10 @@ page_simple_validate_old(
if (UNIV_UNLIKELY
(rec_get_next_offs(rec, FALSE) < FIL_PAGE_DATA
|| rec_get_next_offs(rec, FALSE) >= UNIV_PAGE_SIZE)) {
- fprintf(stderr,
- "InnoDB: Next record offset"
- " nonsensical %lu for rec %lu\n",
- (ulong) rec_get_next_offs(rec, FALSE),
- (ulong) (rec - page));
+
+ ib::error() << "Next record offset nonsensical "
+ << rec_get_next_offs(rec, FALSE) << " for rec "
+ << (rec - page);
goto func_exit;
}
@@ -2087,10 +2066,8 @@ page_simple_validate_old(
count++;
if (UNIV_UNLIKELY(count > UNIV_PAGE_SIZE)) {
- fprintf(stderr,
- "InnoDB: Page record list appears"
- " to be circular %lu\n",
- (ulong) count);
+ ib::error() << "Page record list appears"
+ " to be circular " << count;
goto func_exit;
}
@@ -2099,24 +2076,23 @@ page_simple_validate_old(
}
if (UNIV_UNLIKELY(rec_get_n_owned_old(rec) == 0)) {
- fprintf(stderr, "InnoDB: n owned is zero in a supremum rec\n");
+ ib::error() << "n owned is zero in a supremum rec";
goto func_exit;
}
if (UNIV_UNLIKELY(slot_no != n_slots - 1)) {
- fprintf(stderr, "InnoDB: n slots wrong %lu, %lu\n",
- (ulong) slot_no, (ulong) (n_slots - 1));
+ ib::error() << "n slots wrong "
+ << slot_no << ", " << (n_slots - 1);
goto func_exit;
}
if (UNIV_UNLIKELY(page_header_get_field(page, PAGE_N_RECS)
+ PAGE_HEAP_NO_USER_LOW
!= count + 1)) {
- fprintf(stderr, "InnoDB: n recs wrong %lu %lu\n",
- (ulong) page_header_get_field(page, PAGE_N_RECS)
- + PAGE_HEAP_NO_USER_LOW,
- (ulong) (count + 1));
+ ib::error() << "n recs wrong "
+ << page_header_get_field(page, PAGE_N_RECS)
+ + PAGE_HEAP_NO_USER_LOW << " " << (count + 1);
goto func_exit;
}
@@ -2127,20 +2103,16 @@ page_simple_validate_old(
while (rec != NULL) {
if (UNIV_UNLIKELY(rec < page + FIL_PAGE_DATA
|| rec >= page + UNIV_PAGE_SIZE)) {
- fprintf(stderr,
- "InnoDB: Free list record has"
- " a nonsensical offset %lu\n",
- (ulong) (rec - page));
+ ib::error() << "Free list record has"
+ " a nonsensical offset " << (rec - page);
goto func_exit;
}
if (UNIV_UNLIKELY(rec > rec_heap_top)) {
- fprintf(stderr,
- "InnoDB: Free list record %lu"
- " is above rec heap top %lu\n",
- (ulong) (rec - page),
- (ulong) (rec_heap_top - page));
+ ib::error() << "Free list record " << (rec - page)
+ << " is above rec heap top "
+ << (rec_heap_top - page);
goto func_exit;
}
@@ -2148,10 +2120,8 @@ page_simple_validate_old(
count++;
if (UNIV_UNLIKELY(count > UNIV_PAGE_SIZE)) {
- fprintf(stderr,
- "InnoDB: Page free list appears"
- " to be circular %lu\n",
- (ulong) count);
+ ib::error() << "Page free list appears"
+ " to be circular " << count;
goto func_exit;
}
@@ -2160,9 +2130,8 @@ page_simple_validate_old(
if (UNIV_UNLIKELY(page_dir_get_n_heap(page) != count + 1)) {
- fprintf(stderr, "InnoDB: N heap is wrong %lu, %lu\n",
- (ulong) page_dir_get_n_heap(page),
- (ulong) (count + 1));
+ ib::error() << "N heap is wrong "
+ << page_dir_get_n_heap(page) << ", " << (count + 1);
goto func_exit;
}
@@ -2177,8 +2146,7 @@ func_exit:
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.
-@return TRUE if ok */
-UNIV_INTERN
+@return TRUE if ok */
ibool
page_simple_validate_new(
/*=====================*/
@@ -2201,9 +2169,8 @@ page_simple_validate_new(
n_slots = page_dir_get_n_slots(page);
if (UNIV_UNLIKELY(n_slots > UNIV_PAGE_SIZE / 4)) {
- fprintf(stderr,
- "InnoDB: Nonsensical number %lu"
- " of page dir slots\n", (ulong) n_slots);
+ ib::error() << "Nonsensical number " << n_slots
+ << " of page dir slots";
goto func_exit;
}
@@ -2213,12 +2180,11 @@ page_simple_validate_new(
if (UNIV_UNLIKELY(rec_heap_top
> page_dir_get_nth_slot(page, n_slots - 1))) {
- fprintf(stderr,
- "InnoDB: Record heap and dir overlap on a page,"
- " heap top %lu, dir %lu\n",
- (ulong) page_header_get_field(page, PAGE_HEAP_TOP),
- (ulong)
- page_offset(page_dir_get_nth_slot(page, n_slots - 1)));
+ ib::error() << "Record heap and dir overlap on a page,"
+ " heap top "
+ << page_header_get_field(page, PAGE_HEAP_TOP)
+ << ", dir " << page_offset(
+ page_dir_get_nth_slot(page, n_slots - 1));
goto func_exit;
}
@@ -2235,11 +2201,10 @@ page_simple_validate_new(
for (;;) {
if (UNIV_UNLIKELY(rec > rec_heap_top)) {
- fprintf(stderr,
- "InnoDB: Record %lu is above rec"
- " heap top %lu\n",
- (ulong) page_offset(rec),
- (ulong) page_offset(rec_heap_top));
+
+ ib::error() << "Record " << page_offset(rec)
+ << " is above rec heap top "
+ << page_offset(rec_heap_top);
goto func_exit;
}
@@ -2249,22 +2214,18 @@ page_simple_validate_new(
if (UNIV_UNLIKELY(rec_get_n_owned_new(rec)
!= own_count)) {
- fprintf(stderr,
- "InnoDB: Wrong owned count %lu, %lu,"
- " rec %lu\n",
- (ulong) rec_get_n_owned_new(rec),
- (ulong) own_count,
- (ulong) page_offset(rec));
+ ib::error() << "Wrong owned count "
+ << rec_get_n_owned_new(rec) << ", "
+ << own_count << ", rec "
+ << page_offset(rec);
goto func_exit;
}
if (UNIV_UNLIKELY
(page_dir_slot_get_rec(slot) != rec)) {
- fprintf(stderr,
- "InnoDB: Dir slot does not point"
- " to right rec %lu\n",
- (ulong) page_offset(rec));
+ ib::error() << "Dir slot does not point"
+ " to right rec " << page_offset(rec);
goto func_exit;
}
@@ -2285,11 +2246,10 @@ page_simple_validate_new(
if (UNIV_UNLIKELY
(rec_get_next_offs(rec, TRUE) < FIL_PAGE_DATA
|| rec_get_next_offs(rec, TRUE) >= UNIV_PAGE_SIZE)) {
- fprintf(stderr,
- "InnoDB: Next record offset nonsensical %lu"
- " for rec %lu\n",
- (ulong) rec_get_next_offs(rec, TRUE),
- (ulong) page_offset(rec));
+
+ ib::error() << "Next record offset nonsensical "
+ << rec_get_next_offs(rec, TRUE)
+ << " for rec " << page_offset(rec);
goto func_exit;
}
@@ -2297,10 +2257,8 @@ page_simple_validate_new(
count++;
if (UNIV_UNLIKELY(count > UNIV_PAGE_SIZE)) {
- fprintf(stderr,
- "InnoDB: Page record list appears"
- " to be circular %lu\n",
- (ulong) count);
+ ib::error() << "Page record list appears to be"
+ " circular " << count;
goto func_exit;
}
@@ -2309,25 +2267,23 @@ page_simple_validate_new(
}
if (UNIV_UNLIKELY(rec_get_n_owned_new(rec) == 0)) {
- fprintf(stderr, "InnoDB: n owned is zero"
- " in a supremum rec\n");
+ ib::error() << "n owned is zero in a supremum rec";
goto func_exit;
}
if (UNIV_UNLIKELY(slot_no != n_slots - 1)) {
- fprintf(stderr, "InnoDB: n slots wrong %lu, %lu\n",
- (ulong) slot_no, (ulong) (n_slots - 1));
+ ib::error() << "n slots wrong " << slot_no << ", "
+ << (n_slots - 1);
goto func_exit;
}
if (UNIV_UNLIKELY(page_header_get_field(page, PAGE_N_RECS)
+ PAGE_HEAP_NO_USER_LOW
!= count + 1)) {
- fprintf(stderr, "InnoDB: n recs wrong %lu %lu\n",
- (ulong) page_header_get_field(page, PAGE_N_RECS)
- + PAGE_HEAP_NO_USER_LOW,
- (ulong) (count + 1));
+ ib::error() << "n recs wrong "
+ << page_header_get_field(page, PAGE_N_RECS)
+ + PAGE_HEAP_NO_USER_LOW << " " << (count + 1);
goto func_exit;
}
@@ -2338,20 +2294,17 @@ page_simple_validate_new(
while (rec != NULL) {
if (UNIV_UNLIKELY(rec < page + FIL_PAGE_DATA
|| rec >= page + UNIV_PAGE_SIZE)) {
- fprintf(stderr,
- "InnoDB: Free list record has"
- " a nonsensical offset %lu\n",
- (ulong) page_offset(rec));
+
+ ib::error() << "Free list record has"
+ " a nonsensical offset " << page_offset(rec);
goto func_exit;
}
if (UNIV_UNLIKELY(rec > rec_heap_top)) {
- fprintf(stderr,
- "InnoDB: Free list record %lu"
- " is above rec heap top %lu\n",
- (ulong) page_offset(rec),
- (ulong) page_offset(rec_heap_top));
+ ib::error() << "Free list record " << page_offset(rec)
+ << " is above rec heap top "
+ << page_offset(rec_heap_top);
goto func_exit;
}
@@ -2359,10 +2312,8 @@ page_simple_validate_new(
count++;
if (UNIV_UNLIKELY(count > UNIV_PAGE_SIZE)) {
- fprintf(stderr,
- "InnoDB: Page free list appears"
- " to be circular %lu\n",
- (ulong) count);
+ ib::error() << "Page free list appears to be"
+ " circular " << count;
goto func_exit;
}
@@ -2371,9 +2322,8 @@ page_simple_validate_new(
if (UNIV_UNLIKELY(page_dir_get_n_heap(page) != count + 1)) {
- fprintf(stderr, "InnoDB: N heap is wrong %lu, %lu\n",
- (ulong) page_dir_get_n_heap(page),
- (ulong) (count + 1));
+ ib::error() << "N heap is wrong "
+ << page_dir_get_n_heap(page) << ", " << (count + 1);
goto func_exit;
}
@@ -2386,8 +2336,7 @@ func_exit:
/***************************************************************//**
This function checks the consistency of an index page.
-@return TRUE if ok */
-UNIV_INTERN
+@return TRUE if ok */
ibool
page_validate(
/*==========*/
@@ -2412,9 +2361,15 @@ page_validate(
ulint* offsets = NULL;
ulint* old_offsets = NULL;
+#ifdef UNIV_GIS_DEBUG
+ if (dict_index_is_spatial(index)) {
+ fprintf(stderr, "Page no: %lu\n", page_get_page_no(page));
+ }
+#endif /* UNIV_DEBUG */
+
if (UNIV_UNLIKELY((ibool) !!page_is_comp(page)
!= dict_table_is_comp(index->table))) {
- fputs("InnoDB: 'compact format' flag mismatch\n", stderr);
+ ib::error() << "'compact format' flag mismatch";
goto func_exit2;
}
if (page_is_comp(page)) {
@@ -2427,16 +2382,20 @@ page_validate(
}
}
- if (dict_index_is_sec_or_ibuf(index) && page_is_leaf(page)
+ /* Multiple transactions cannot simultaneously operate on the
+ same temp-table in parallel.
+ max_trx_id is ignored for temp tables because it not required
+ for MVCC. */
+ if (dict_index_is_sec_or_ibuf(index)
+ && !dict_table_is_temporary(index->table)
+ && page_is_leaf(page)
&& !page_is_empty(page)) {
trx_id_t max_trx_id = page_get_max_trx_id(page);
trx_id_t sys_max_trx_id = trx_sys_get_max_trx_id();
if (max_trx_id == 0 || max_trx_id > sys_max_trx_id) {
- ib_logf(IB_LOG_LEVEL_ERROR,
- "PAGE_MAX_TRX_ID out of bounds: "
- TRX_ID_FMT ", " TRX_ID_FMT,
- max_trx_id, sys_max_trx_id);
+ ib::error() << "PAGE_MAX_TRX_ID out of bounds: "
+ << max_trx_id << ", " << sys_max_trx_id;
goto func_exit2;
}
}
@@ -2456,13 +2415,11 @@ page_validate(
if (UNIV_UNLIKELY(!(page_header_get_ptr(page, PAGE_HEAP_TOP)
<= page_dir_get_nth_slot(page, n_slots - 1)))) {
- 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));
+ ib::warn() << "Record heap and dir overlap on space "
+ << page_get_space_id(page) << " page "
+ << page_get_page_no(page) << " index " << index->name
+ << ", " << page_header_get_ptr(page, PAGE_HEAP_TOP)
+ << ", " << page_dir_get_nth_slot(page, n_slots - 1);
goto func_exit;
}
@@ -2484,7 +2441,7 @@ page_validate(
if (page_is_comp(page) && page_rec_is_user_rec(rec)
&& UNIV_UNLIKELY(rec_get_node_ptr_flag(rec)
== page_is_leaf(page))) {
- fputs("InnoDB: node_ptr flag mismatch\n", stderr);
+ ib::error() << "'node_ptr' flag mismatch";
goto func_exit;
}
@@ -2494,22 +2451,43 @@ page_validate(
#ifndef UNIV_HOTBACKUP
/* Check that the records are in the ascending order */
- if (UNIV_LIKELY(count >= PAGE_HEAP_NO_USER_LOW)
+ if (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,
- "InnoDB: Records in wrong order"
- " on space %lu page %lu index %s\n",
- (ulong) page_get_space_id(page),
- (ulong) page_get_page_no(page),
- index->name);
+
+ int ret = cmp_rec_rec(
+ rec, old_rec, offsets, old_offsets, index);
+
+ /* For spatial index, on nonleaf leavel, we
+ allow recs to be equal. */
+ bool rtr_equal_nodeptrs =
+ (ret == 0 && dict_index_is_spatial(index)
+ && !page_is_leaf(page));
+
+ if (ret <= 0 && !rtr_equal_nodeptrs) {
+
+ ib::error() << "Records in wrong order on"
+ " space " << page_get_space_id(page)
+ << " page " << page_get_page_no(page)
+ << " index " << index->name;
+
fputs("\nInnoDB: previous record ", stderr);
- rec_print_new(stderr, old_rec, old_offsets);
- fputs("\nInnoDB: record ", stderr);
- rec_print_new(stderr, rec, offsets);
- putc('\n', stderr);
+ /* For spatial index, print the mbr info.*/
+ if (index->type & DICT_SPATIAL) {
+ putc('\n', stderr);
+ rec_print_mbr_rec(stderr,
+ old_rec, old_offsets);
+ fputs("\nInnoDB: record ", stderr);
+ putc('\n', stderr);
+ rec_print_mbr_rec(stderr, rec, offsets);
+ putc('\n', stderr);
+ putc('\n', stderr);
+
+ } else {
+ rec_print_new(stderr, old_rec, old_offsets);
+ fputs("\nInnoDB: record ", stderr);
+ rec_print_new(stderr, rec, offsets);
+ putc('\n', stderr);
+ }
goto func_exit;
}
@@ -2519,21 +2497,27 @@ page_validate(
if (page_rec_is_user_rec(rec)) {
data_size += rec_offs_size(offsets);
+
+#if UNIV_GIS_DEBUG
+ /* For spatial index, print the mbr info.*/
+ if (index->type & DICT_SPATIAL) {
+ rec_print_mbr_rec(stderr, rec, offsets);
+ putc('\n', stderr);
+ }
+#endif /* UNIV_GIS_DEBUG */
}
offs = page_offset(rec_get_start(rec, offsets));
i = rec_offs_size(offsets);
if (UNIV_UNLIKELY(offs + i >= UNIV_PAGE_SIZE)) {
- fputs("InnoDB: record offset out of bounds\n", stderr);
+ ib::error() << "Record offset out of bounds";
goto func_exit;
}
while (i--) {
if (UNIV_UNLIKELY(buf[offs + i])) {
/* No other record may overlap this */
-
- fputs("InnoDB: Record overlaps another\n",
- stderr);
+ ib::error() << "Record overlaps another";
goto func_exit;
}
@@ -2549,17 +2533,14 @@ page_validate(
if (UNIV_UNLIKELY(rec_own_count)) {
/* This is a record pointed to by a dir slot */
if (UNIV_UNLIKELY(rec_own_count != own_count)) {
- fprintf(stderr,
- "InnoDB: Wrong owned count %lu, %lu\n",
- (ulong) rec_own_count,
- (ulong) own_count);
+ ib::error() << "Wrong owned count "
+ << rec_own_count << ", " << own_count;
goto func_exit;
}
if (page_dir_slot_get_rec(slot) != rec) {
- fputs("InnoDB: Dir slot does not"
- " point to right rec\n",
- stderr);
+ ib::error() << "Dir slot does not"
+ " point to right rec";
goto func_exit;
}
@@ -2596,30 +2577,28 @@ page_validate(
}
} else if (UNIV_UNLIKELY(rec_get_n_owned_old(rec) == 0)) {
n_owned_zero:
- fputs("InnoDB: n owned is zero\n", stderr);
+ ib::error() << "n owned is zero";
goto func_exit;
}
if (UNIV_UNLIKELY(slot_no != n_slots - 1)) {
- fprintf(stderr, "InnoDB: n slots wrong %lu %lu\n",
- (ulong) slot_no, (ulong) (n_slots - 1));
+ ib::error() << "n slots wrong " << slot_no << " "
+ << (n_slots - 1);
goto func_exit;
}
if (UNIV_UNLIKELY(page_header_get_field(page, PAGE_N_RECS)
+ PAGE_HEAP_NO_USER_LOW
!= count + 1)) {
- fprintf(stderr, "InnoDB: n recs wrong %lu %lu\n",
- (ulong) page_header_get_field(page, PAGE_N_RECS)
- + PAGE_HEAP_NO_USER_LOW,
- (ulong) (count + 1));
+ ib::error() << "n recs wrong "
+ << page_header_get_field(page, PAGE_N_RECS)
+ + PAGE_HEAP_NO_USER_LOW << " " << (count + 1);
goto func_exit;
}
if (UNIV_UNLIKELY(data_size != page_get_data_size(page))) {
- fprintf(stderr,
- "InnoDB: Summed data size %lu, returned by func %lu\n",
- (ulong) data_size, (ulong) page_get_data_size(page));
+ ib::error() << "Summed data size " << data_size
+ << ", returned by func " << page_get_data_size(page);
goto func_exit;
}
@@ -2638,15 +2617,15 @@ n_owned_zero:
offs = page_offset(rec_get_start(rec, offsets));
i = rec_offs_size(offsets);
if (UNIV_UNLIKELY(offs + i >= UNIV_PAGE_SIZE)) {
- fputs("InnoDB: record offset out of bounds\n", stderr);
+ ib::error() << "Record offset out of bounds";
goto func_exit;
}
while (i--) {
if (UNIV_UNLIKELY(buf[offs + i])) {
- fputs("InnoDB: Record overlaps another"
- " in free list\n", stderr);
+ ib::error() << "Record overlaps another"
+ " in free list";
goto func_exit;
}
@@ -2657,9 +2636,8 @@ n_owned_zero:
}
if (UNIV_UNLIKELY(page_dir_get_n_heap(page) != count + 1)) {
- fprintf(stderr, "InnoDB: N heap is wrong %lu %lu\n",
- (ulong) page_dir_get_n_heap(page),
- (ulong) count + 1);
+ ib::error() << "N heap is wrong "
+ << page_dir_get_n_heap(page) << " " << count + 1;
goto func_exit;
}
@@ -2670,13 +2648,9 @@ func_exit:
if (UNIV_UNLIKELY(ret == FALSE)) {
func_exit2:
- 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, 0);
+ ib::error() << "Apparent corruption in space "
+ << page_get_space_id(page) << " page "
+ << page_get_page_no(page) << " index " << index->name;
}
return(ret);
@@ -2685,8 +2659,7 @@ func_exit2:
#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
+@return record, NULL if not found */
const rec_t*
page_find_rec_with_heap_no(
/*=======================*/
@@ -2698,7 +2671,7 @@ page_find_rec_with_heap_no(
if (page_is_comp(page)) {
rec = page + PAGE_NEW_INFIMUM;
- for(;;) {
+ for (;;) {
ulint rec_heap_no = rec_get_heap_no_new(rec);
if (rec_heap_no == heap_no) {
@@ -2735,8 +2708,7 @@ page_find_rec_with_heap_no(
Removes the record from a leaf page. This function does not log
any changes. It is used by the IMPORT tablespace functions.
The cursor is moved to the next record after the deleted one.
-@return true if success, i.e., the page did not become too empty */
-UNIV_INTERN
+@return true if success, i.e., the page did not become too empty */
bool
page_delete_rec(
/*============*/
@@ -2755,7 +2727,7 @@ page_delete_rec(
if (!rec_offs_any_extern(offsets)
&& ((page_get_data_size(page) - rec_offs_size(offsets)
- < BTR_CUR_PAGE_COMPRESS_LIMIT)
+ < BTR_CUR_PAGE_COMPRESS_LIMIT(index))
|| (mach_read_from_4(page + FIL_PAGE_NEXT) == FIL_NULL
&& mach_read_from_4(page + FIL_PAGE_PREV) == FIL_NULL)
|| (page_get_n_recs(page) < 2))) {
@@ -2791,7 +2763,6 @@ page_delete_rec(
@param[in] page index tree leaf page
@return the last record, not delete-marked
@retval infimum record if all records are delete-marked */
-
const rec_t*
page_find_rec_max_not_deleted(
const page_t* page)
@@ -2824,14 +2795,12 @@ page_find_rec_max_not_deleted(
but different than the global setting innodb_checksum_algorithm.
@param[in] current_algo current checksum algorithm
@param[in] page_checksum page valid checksum
-@param[in] space_id tablespace id
-@param[in] page_no page number */
+@param[in] page_id page identifier */
void
page_warn_strict_checksum(
srv_checksum_algorithm_t curr_algo,
srv_checksum_algorithm_t page_checksum,
- ulint space_id,
- ulint page_no)
+ const page_id_t& page_id)
{
srv_checksum_algorithm_t curr_algo_nonstrict;
switch (curr_algo) {
@@ -2848,16 +2817,15 @@ page_warn_strict_checksum(
ut_error;
}
- ib_logf(IB_LOG_LEVEL_WARN,
- "innodb_checksum_algorithm is set to \"%s\""
- " but the page [page id: space=" ULINTPF ","
- " page number=" ULINTPF "] contains a valid checksum \"%s\"."
- " Accepting the page as valid. Change innodb_checksum_algorithm"
- " to \"%s\" to silently accept such pages or rewrite all pages"
- " so that they contain \"%s\" checksum.",
- buf_checksum_algorithm_name(curr_algo),
- space_id, page_no,
- buf_checksum_algorithm_name(page_checksum),
- buf_checksum_algorithm_name(curr_algo_nonstrict),
- buf_checksum_algorithm_name(curr_algo_nonstrict));
+ ib::warn() << "innodb_checksum_algorithm is set to \""
+ << buf_checksum_algorithm_name(curr_algo) << "\""
+ << " but the page " << page_id << " contains a valid checksum \""
+ << buf_checksum_algorithm_name(page_checksum) << "\". "
+ << " Accepting the page as valid. Change"
+ << " innodb_checksum_algorithm to \""
+ << buf_checksum_algorithm_name(curr_algo_nonstrict)
+ << "\" to silently accept such pages or rewrite all pages"
+ << " so that they contain \""
+ << buf_checksum_algorithm_name(curr_algo_nonstrict)
+ << "\" checksum.";
}