mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
branches/zip: Do not write to PAGE_INDEX_ID after page creation,
not even when restoring an uncompressed page after a compression failure. btr_page_reorganize_low(): On compression failure, do not restore those page header fields that should not be affected by the reorganization. Instead, compare the fields. page_zip_decompress(): Add the parameter ibool all, for copying all page header fields. Pass the parameter all=TRUE on block read completion, redo log application, and page_zip_validate(); pass all=FALSE in all other cases. page_zip_reorganize(): Do not restore the uncompressed page on failure. It will be restored (to pre-modification state) by the caller anyway. rb://167, Issue #346
This commit is contained in:
parent
43833984dd
commit
97fdf6c598
8 changed files with 85 additions and 24 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2009-09-28 The InnoDB Team
|
||||
|
||||
* btr/btr0btr.c, buf/buf0buf.c,
|
||||
include/page0page.h, include/page0zip.h,
|
||||
page/page0cur.c, page/page0page.c, page/page0zip.c:
|
||||
Do not write to PAGE_INDEX_ID when restoring an uncompressed page
|
||||
after a compression failure. The field should only be written
|
||||
when creating a B-tree page. This fix addresses a race condition
|
||||
in a debug assertion.
|
||||
|
||||
2009-09-28 The InnoDB Team
|
||||
|
||||
* fil/fil0fil.c:
|
||||
|
|
|
@ -1011,7 +1011,26 @@ btr_page_reorganize_low(
|
|||
(!page_zip_compress(page_zip, page, index, NULL))) {
|
||||
|
||||
/* Restore the old page and exit. */
|
||||
buf_frame_copy(page, temp_page);
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
|
||||
/* Check that the bytes that we skip are identical. */
|
||||
ut_a(!memcmp(page, temp_page, PAGE_HEADER));
|
||||
ut_a(!memcmp(PAGE_HEADER + PAGE_N_RECS + page,
|
||||
PAGE_HEADER + PAGE_N_RECS + temp_page,
|
||||
PAGE_DATA - (PAGE_HEADER + PAGE_N_RECS)));
|
||||
ut_a(!memcmp(UNIV_PAGE_SIZE - FIL_PAGE_DATA_END + page,
|
||||
UNIV_PAGE_SIZE - FIL_PAGE_DATA_END + temp_page,
|
||||
FIL_PAGE_DATA_END));
|
||||
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
|
||||
|
||||
memcpy(PAGE_HEADER + page, PAGE_HEADER + temp_page,
|
||||
PAGE_N_RECS - PAGE_N_DIR_SLOTS);
|
||||
memcpy(PAGE_DATA + page, PAGE_DATA + temp_page,
|
||||
UNIV_PAGE_SIZE - PAGE_DATA - FIL_PAGE_DATA_END);
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
|
||||
ut_a(!memcmp(page, temp_page, UNIV_PAGE_SIZE));
|
||||
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
|
|
@ -1834,7 +1834,7 @@ buf_zip_decompress(
|
|||
switch (fil_page_get_type(frame)) {
|
||||
case FIL_PAGE_INDEX:
|
||||
if (page_zip_decompress(&block->page.zip,
|
||||
block->frame)) {
|
||||
block->frame, TRUE)) {
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
|
|
@ -76,8 +76,11 @@ typedef byte page_header_t;
|
|||
header which are set in a page create */
|
||||
/*----*/
|
||||
#define PAGE_LEVEL 26 /* level of the node in an index tree; the
|
||||
leaf level is the level 0 */
|
||||
#define PAGE_INDEX_ID 28 /* index id where the page belongs */
|
||||
leaf level is the level 0. This field should
|
||||
not be written to after page creation. */
|
||||
#define PAGE_INDEX_ID 28 /* index id where the page belongs.
|
||||
This field should not be written to after
|
||||
page creation. */
|
||||
#define PAGE_BTR_SEG_LEAF 36 /* file segment header for the leaf pages in
|
||||
a B-tree: defined only on the root page of a
|
||||
B-tree, but not in the root of an ibuf tree */
|
||||
|
|
|
@ -127,8 +127,12 @@ page_zip_decompress(
|
|||
/*================*/
|
||||
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 */
|
||||
__attribute__((nonnull));
|
||||
page_t* page, /*!< out: uncompressed page, may be trashed */
|
||||
ibool all) /*!< in: TRUE=decompress the whole page;
|
||||
FALSE=verify but do not copy some
|
||||
page header fields that should not change
|
||||
after page creation */
|
||||
__attribute__((nonnull(1,2)));
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/**********************************************************************//**
|
||||
|
@ -385,8 +389,8 @@ 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.
|
||||
@return TRUE on success, FALSE on failure; page and page_zip will be
|
||||
left intact on failure. */
|
||||
@return TRUE on success, FALSE on failure; page_zip will be left
|
||||
intact on failure, but page will be overwritten. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
page_zip_reorganize(
|
||||
|
|
|
@ -1195,7 +1195,7 @@ page_cur_insert_rec_zip_reorg(
|
|||
}
|
||||
|
||||
/* Out of space: restore the page */
|
||||
if (!page_zip_decompress(page_zip, page)) {
|
||||
if (!page_zip_decompress(page_zip, page, FALSE)) {
|
||||
ut_error; /* Memory corrupted? */
|
||||
}
|
||||
ut_ad(page_validate(page, index));
|
||||
|
|
|
@ -679,7 +679,7 @@ page_copy_rec_list_end(
|
|||
|
||||
if (UNIV_UNLIKELY
|
||||
(!page_zip_decompress(new_page_zip,
|
||||
new_page))) {
|
||||
new_page, FALSE))) {
|
||||
ut_error;
|
||||
}
|
||||
ut_ad(page_validate(new_page, index));
|
||||
|
@ -792,7 +792,7 @@ page_copy_rec_list_start(
|
|||
|
||||
if (UNIV_UNLIKELY
|
||||
(!page_zip_decompress(new_page_zip,
|
||||
new_page))) {
|
||||
new_page, FALSE))) {
|
||||
ut_error;
|
||||
}
|
||||
ut_ad(page_validate(new_page, index));
|
||||
|
|
|
@ -2821,7 +2821,11 @@ page_zip_decompress(
|
|||
/*================*/
|
||||
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 */
|
||||
ibool all) /*!< in: TRUE=decompress the whole page;
|
||||
FALSE=verify but do not copy some
|
||||
page header fields that should not change
|
||||
after page creation */
|
||||
{
|
||||
z_stream d_stream;
|
||||
dict_index_t* index = NULL;
|
||||
|
@ -2851,13 +2855,36 @@ page_zip_decompress(
|
|||
heap = mem_heap_create(n_dense * (3 * sizeof *recs) + UNIV_PAGE_SIZE);
|
||||
recs = mem_heap_alloc(heap, n_dense * (2 * sizeof *recs));
|
||||
|
||||
if (all) {
|
||||
/* Copy the page header. */
|
||||
memcpy(page, page_zip->data, PAGE_DATA);
|
||||
} else {
|
||||
/* Check that the bytes that we skip are identical. */
|
||||
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
|
||||
ut_a(!memcmp(FIL_PAGE_TYPE + page,
|
||||
FIL_PAGE_TYPE + page_zip->data,
|
||||
PAGE_HEADER - FIL_PAGE_TYPE));
|
||||
ut_a(!memcmp(PAGE_HEADER + PAGE_LEVEL + page,
|
||||
PAGE_HEADER + PAGE_LEVEL + page_zip->data,
|
||||
PAGE_DATA - (PAGE_HEADER + PAGE_LEVEL)));
|
||||
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
|
||||
|
||||
/* Copy the mutable parts of the page header. */
|
||||
memcpy(page, page_zip->data, FIL_PAGE_TYPE);
|
||||
memcpy(PAGE_HEADER + page, PAGE_HEADER + page_zip->data,
|
||||
PAGE_LEVEL - PAGE_N_DIR_SLOTS);
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
|
||||
/* Check that the page headers match after copying. */
|
||||
ut_a(!memcmp(page, page_zip->data, PAGE_DATA));
|
||||
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
|
||||
}
|
||||
|
||||
#ifdef UNIV_ZIP_DEBUG
|
||||
/* Clear the page. */
|
||||
memset(page, 0x55, UNIV_PAGE_SIZE);
|
||||
/* Clear the uncompressed page, except the header. */
|
||||
memset(PAGE_DATA + page, 0x55, UNIV_PAGE_SIZE - PAGE_DATA);
|
||||
#endif /* UNIV_ZIP_DEBUG */
|
||||
UNIV_MEM_INVALID(page, UNIV_PAGE_SIZE);
|
||||
/* Copy the page header. */
|
||||
memcpy(page, page_zip->data, PAGE_DATA);
|
||||
UNIV_MEM_INVALID(PAGE_DATA + page, UNIV_PAGE_SIZE - PAGE_DATA);
|
||||
|
||||
/* Copy the page directory. */
|
||||
if (UNIV_UNLIKELY(!page_zip_dir_decode(page_zip, page, recs,
|
||||
|
@ -3098,7 +3125,7 @@ page_zip_validate_low(
|
|||
#endif /* UNIV_DEBUG_VALGRIND */
|
||||
|
||||
temp_page_zip = *page_zip;
|
||||
valid = page_zip_decompress(&temp_page_zip, temp_page);
|
||||
valid = page_zip_decompress(&temp_page_zip, temp_page, TRUE);
|
||||
if (!valid) {
|
||||
fputs("page_zip_validate(): failed to decompress\n", stderr);
|
||||
goto func_exit;
|
||||
|
@ -4376,8 +4403,8 @@ 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.
|
||||
@return TRUE on success, FALSE on failure; page and page_zip will be
|
||||
left intact on failure. */
|
||||
@return TRUE on success, FALSE on failure; page_zip will be left
|
||||
intact on failure, but page will be overwritten. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
page_zip_reorganize(
|
||||
|
@ -4442,9 +4469,6 @@ page_zip_reorganize(
|
|||
|
||||
if (UNIV_UNLIKELY(!page_zip_compress(page_zip, page, index, mtr))) {
|
||||
|
||||
/* Restore the old page and exit. */
|
||||
buf_frame_copy(page, temp_page);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
buf_block_free(temp_block);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
@ -4605,7 +4629,8 @@ corrupt:
|
|||
memcpy(page_zip->data + page_zip_get_size(page_zip)
|
||||
- trailer_size, ptr + 8 + size, trailer_size);
|
||||
|
||||
if (UNIV_UNLIKELY(!page_zip_decompress(page_zip, page))) {
|
||||
if (UNIV_UNLIKELY(!page_zip_decompress(page_zip, page,
|
||||
TRUE))) {
|
||||
|
||||
goto corrupt;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue