Commit b34b37b5 authored by marko's avatar marko

branches/zip:

Initial import of the zip-like compression of B-tree pages.
parent 4979fcae
This diff is collapsed.
This diff is collapsed.
......@@ -37,6 +37,7 @@ Created 11/5/1995 Heikki Tuuri
#include "log0log.h"
#include "trx0undo.h"
#include "srv0srv.h"
#include "page0zip.h"
/*
IMPLEMENTATION OF THE BUFFER POOL
......@@ -482,6 +483,8 @@ buf_block_init(
block->n_pointers = 0;
page_zip_des_init(&block->page_zip);
rw_lock_create(&(block->lock));
ut_ad(rw_lock_validate(&(block->lock)));
......
......@@ -264,9 +264,11 @@ buf_flush_buffered_writes(void)
"InnoDB: before posting to the doublewrite buffer.\n");
}
if (block->check_index_page_at_flush
&& !page_simple_validate(block->frame)) {
if (!block->check_index_page_at_flush) {
} else if (page_is_comp(block->frame)
&& UNIV_UNLIKELY(!page_simple_validate_new(
block->frame))) {
corrupted_page:
buf_page_print(block->frame);
ut_print_timestamp(stderr);
......@@ -278,6 +280,10 @@ buf_flush_buffered_writes(void)
(ulong) block->offset, (ulong) block->space);
ut_error;
} else if (UNIV_UNLIKELY(!page_simple_validate_old(
block->frame))) {
goto corrupted_page;
}
}
......
......@@ -2761,6 +2761,7 @@ ibuf_insert(
ut_ad(dtuple_check_typed(entry));
ut_a(!(index->type & DICT_CLUSTERED));
ut_a(!index->table->zip);
if (rec_get_converted_size(index, entry)
>= page_get_free_space_of_empty(index->table->comp) / 2) {
......@@ -2846,9 +2847,10 @@ ibuf_insert_to_index_page(
btr_cur_del_unmark_for_ibuf(rec, mtr);
} else {
rec = page_cur_tuple_insert(&page_cur, entry, index, mtr);
rec = page_cur_tuple_insert(&page_cur, NULL,
entry, index, mtr);
if (rec == NULL) {
if (UNIV_UNLIKELY(rec == NULL)) {
/* If the record did not fit, reorganize */
btr_page_reorganize(page, index, mtr);
......@@ -2858,7 +2860,8 @@ ibuf_insert_to_index_page(
/* This time the record must fit */
if (UNIV_UNLIKELY(!page_cur_tuple_insert(
&page_cur, entry, index, mtr))) {
&page_cur, NULL,
entry, index, mtr))) {
ut_print_timestamp(stderr);
......
......@@ -265,8 +265,9 @@ Sets a record as the predefined minimum record. */
void
btr_set_min_rec_mark(
/*=================*/
rec_t* rec, /* in: record */
ulint comp, /* in: nonzero=compact page format */
rec_t* rec, /* in/out: record */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 5 bytes available, or NULL */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Deletes on the upper level the node pointer to a page. */
......@@ -295,11 +296,12 @@ conditions, looks at the right brother. If the page is the only one on that
level lifts the records of the page to the father page, thus reducing the
tree height. It is assumed that mtr holds an x-latch on the tree and on the
page. If cursor is on the leaf level, mtr must also hold x-latches to
the brothers, if they exist. NOTE: it is assumed that the caller has reserved
enough free extents so that the compression will always succeed if done! */
void
the brothers, if they exist. */
ibool
btr_compress(
/*=========*/
/* out: TRUE on success */
btr_cur_t* cursor, /* in: cursor on the page to merge or lift;
the page must not be empty: in record delete
use btr_discard_page if the page would become
......
......@@ -286,19 +286,6 @@ btr_cur_del_unmark_for_ibuf(
rec_t* rec, /* in: record to delete unmark */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Tries to compress a page of the tree on the leaf level. It is assumed
that mtr holds an x-latch on the tree and on the cursor page. To avoid
deadlocks, mtr must also own x-latches to brothers of page, if those
brothers exist. NOTE: it is assumed that the caller has reserved enough
free extents so that the compression will always succeed if done! */
void
btr_cur_compress(
/*=============*/
btr_cur_t* cursor, /* in: cursor on the page to compress;
cursor does not stay valid */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Tries to compress a page of the tree if it seems useful. It is assumed
that mtr holds an x-latch on the tree and on the cursor page. To avoid
deadlocks, mtr must also own x-latches to brothers of page, if those
......@@ -364,7 +351,8 @@ btr_cur_parse_update_in_place(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
page_t* page, /* in: page or NULL */
page_t* page, /* in/out: page or NULL */
page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
dict_index_t* index); /* in: index corresponding to page */
/********************************************************************
Parses the redo log record for delete marking or unmarking of a clustered
......@@ -376,8 +364,9 @@ btr_cur_parse_del_mark_set_clust_rec(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
dict_index_t* index, /* in: index corresponding to page */
page_t* page); /* in: page or NULL */
page_t* page, /* in/out: page or NULL */
page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
dict_index_t* index); /* in: index corresponding to page */
/********************************************************************
Parses the redo log record for delete marking or unmarking of a secondary
index record. */
......@@ -388,7 +377,8 @@ btr_cur_parse_del_mark_set_sec_rec(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
page_t* page); /* in: page or NULL */
page_t* page, /* in/out: page or NULL */
page_zip_des_t* page_zip);/* in/out: compressed page, or NULL */
/***********************************************************************
Estimates the number of rows in a given index range. */
......
......@@ -31,6 +31,7 @@ Created 11/5/1995 Heikki Tuuri
#include "hash0hash.h"
#include "ut0byte.h"
#include "os0proc.h"
#include "page0types.h"
/* Flags for flush types */
#define BUF_FLUSH_LRU 1
......@@ -612,6 +613,14 @@ buf_block_get_page_no(
/*==================*/
/* out: page number */
buf_block_t* block); /* in: pointer to the control block */
/*************************************************************************
Gets the compressed page descriptor of a block if applicable. */
UNIV_INLINE
page_zip_des_t*
buf_block_get_page_zip(
/*===================*/
/* out: compressed page descriptor, or NULL */
buf_block_t* block); /* in: pointer to the control block */
/***********************************************************************
Gets the block to whose frame the pointer is pointing to. */
UNIV_INLINE
......@@ -850,6 +859,7 @@ struct buf_block_struct{
ulint curr_side; /* BTR_SEARCH_LEFT_SIDE or
BTR_SEARCH_RIGHT_SIDE in hash
indexing */
page_zip_des_t page_zip; /* compressed page info */
/* 6. Debug fields */
#ifdef UNIV_SYNC_DEBUG
rw_lock_t debug_latch; /* in the debug version, each thread
......
......@@ -191,6 +191,24 @@ buf_block_get_page_no(
return(block->offset);
}
/*************************************************************************
Gets the compressed page descriptor of a block if applicable. */
UNIV_INLINE
page_zip_des_t*
buf_block_get_page_zip(
/*===================*/
/* out: compressed page descriptor, or NULL */
buf_block_t* block) /* in: pointer to the control block */
{
ut_ad(block);
if (UNIV_LIKELY_NULL(block->page_zip.data)) {
return(&block->page_zip);
}
return(NULL);
}
/***********************************************************************
Gets the block to whose frame the pointer is pointing to. */
UNIV_INLINE
......@@ -614,8 +632,6 @@ buf_page_release(
RW_NO_LATCH */
mtr_t* mtr) /* in: mtr */
{
ulint buf_fix_count;
ut_ad(block);
mutex_enter_fast(&(buf_pool->mutex));
......@@ -631,8 +647,7 @@ buf_page_release(
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
#endif
buf_fix_count = block->buf_fix_count;
block->buf_fix_count = buf_fix_count - 1;
block->buf_fix_count--;
mutex_exit(&(buf_pool->mutex));
......
......@@ -329,6 +329,7 @@ struct dict_table_struct{
user calls DISCARD TABLESPACE on this table,
and reset to FALSE in IMPORT TABLESPACE */
ibool comp; /* flag: TRUE=compact page format */
ibool zip; /* flag: TRUE=compressed page format */
hash_node_t name_hash; /* hash chain node */
hash_node_t id_hash; /* hash chain node */
ulint n_def; /* number of columns defined so far */
......
......@@ -88,6 +88,7 @@ ibuf_should_try(
decide */
{
if (!(index->type & DICT_CLUSTERED)
&& !index->table->zip
&& (ignore_sec_unique || !(index->type & DICT_UNIQUE))
&& ibuf->meter > IBUF_THRESHOLD) {
......
......@@ -129,8 +129,11 @@ flag value must give the length also! */
/* copy compact record list end
to a new created index page */
#define MLOG_COMP_PAGE_REORGANIZE ((byte)46) /* reorganize an index page */
#define MLOG_COMP_DECOMPRESS ((byte)47) /* decompress a page
to undo a compressed page
overflow */
#define MLOG_BIGGEST_TYPE ((byte)46) /* biggest value (used in
#define MLOG_BIGGEST_TYPE ((byte)47) /* biggest value (used in
asserts) */
/*******************************************************************
......
......@@ -130,6 +130,8 @@ page_cur_tuple_insert(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
page_zip_des_t* page_zip,/* in/out: compressed page with at least
25 + rec_size bytes available, or NULL */
dtuple_t* tuple, /* in: pointer to a data tuple */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mini-transaction handle */
......@@ -144,6 +146,8 @@ page_cur_rec_insert(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
page_zip_des_t* page_zip,/* in/out: compressed page with at least
25 + rec_size bytes available, or NULL */
rec_t* rec, /* in: record to insert */
dict_index_t* index, /* in: record descriptor */
ulint* offsets,/* in: rec_get_offsets(rec, index) */
......@@ -160,6 +164,8 @@ page_cur_insert_rec_low(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
page_zip_des_t* page_zip,/* in/out: compressed page with at least
25 + rec_size bytes available, or NULL */
dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
dict_index_t* index, /* in: record descriptor */
rec_t* rec, /* in: pointer to a physical record or NULL */
......@@ -173,7 +179,6 @@ void
page_copy_rec_list_end_to_created_page(
/*===================================*/
page_t* new_page, /* in: index page to copy to */
page_t* page, /* in: index page */
rec_t* rec, /* in: first record to copy */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mtr */
......@@ -184,9 +189,11 @@ next record after the deleted one. */
void
page_cur_delete_rec(
/*================*/
page_cur_t* cursor, /* in: a page cursor */
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) */
page_zip_des_t* page_zip,/* in/out: compressed page with at least
32 bytes available, or NULL */
mtr_t* mtr); /* in: mini-transaction handle */
/********************************************************************
Searches the right position for a page cursor. */
......@@ -245,7 +252,9 @@ page_cur_parse_insert_rec(
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
dict_index_t* index, /* in: record descriptor */
page_t* page, /* in: page or NULL */
page_t* page, /* in/out: page or NULL */
page_zip_des_t* page_zip,/* in/out: compressed page with at least
25 + rec_size bytes available, or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/**************************************************************
Parses a log record of copying a record list end to a new created page. */
......@@ -257,7 +266,8 @@ page_parse_copy_rec_list_to_created_page(
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
dict_index_t* index, /* in: record descriptor */
page_t* page, /* in: page or NULL */
page_t* page, /* in/out: page or NULL */
page_zip_des_t* page_zip,/* in/out: compressed page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/***************************************************************
Parses log record of a record delete on a page. */
......@@ -269,7 +279,9 @@ page_cur_parse_delete_rec(
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
dict_index_t* index, /* in: record descriptor */
page_t* page, /* in: page or NULL */
page_t* page, /* in/out: page or NULL */
page_zip_des_t* page_zip,/* in/out: compressed page with at least
32 bytes available, or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/* Index page cursor */
......
......@@ -181,11 +181,14 @@ page_cur_tuple_insert(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
page_zip_des_t* page_zip,/* in/out: compressed page with at least
25 + rec_size bytes available, or NULL */
dtuple_t* tuple, /* in: pointer to a data tuple */
dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mini-transaction handle */
{
return(page_cur_insert_rec_low(cursor, tuple, index, NULL, NULL, mtr));
return(page_cur_insert_rec_low(cursor, page_zip, tuple,
index, NULL, NULL, mtr));
}
/***************************************************************
......@@ -199,12 +202,14 @@ page_cur_rec_insert(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
page_zip_des_t* page_zip,/* in/out: compressed page with at least
25 + rec_size bytes available, or NULL */
rec_t* rec, /* in: record to insert */
dict_index_t* index, /* in: record descriptor */
ulint* offsets,/* in: rec_get_offsets(rec, index) */
mtr_t* mtr) /* in: mini-transaction handle */
{
return(page_cur_insert_rec_low(cursor, NULL, index, rec,
offsets, mtr));
return(page_cur_insert_rec_low(cursor, page_zip, NULL,
index, rec, offsets, mtr));
}
This diff is collapsed.
......@@ -35,7 +35,7 @@ UNIV_INLINE
void
page_update_max_trx_id(
/*===================*/
page_t* page, /* in: page */
page_t* page, /* in/out: page */
dulint trx_id) /* in: transaction id */
{
ut_ad(page);
......@@ -67,8 +67,9 @@ UNIV_INLINE
void
page_header_set_field(
/*==================*/
page_t* page, /* in: page */
ulint field, /* in: PAGE_LEVEL, ... */
page_t* page, /* in/out: page */
page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
ulint field, /* in: PAGE_N_DIR_SLOTS, ... */
ulint val) /* in: value */
{
ut_ad(page);
......@@ -77,6 +78,9 @@ page_header_set_field(
ut_ad(field != PAGE_N_HEAP || (val & 0x7fff) < UNIV_PAGE_SIZE);
mach_write_to_2(page + PAGE_HEADER + field, val);
if (UNIV_LIKELY_NULL(page_zip)) {
page_zip_write_header(page_zip, page + PAGE_HEADER + field, 2);
}
}
/*****************************************************************
......@@ -115,8 +119,9 @@ void
page_header_set_ptr(
/*================*/
page_t* page, /* in: page */
page_zip_des_t* page_zip,/* in: compressed page, or NULL */
ulint field, /* in: PAGE_FREE, ... */
byte* ptr) /* in: pointer or NULL*/
const byte* ptr) /* in: pointer or NULL*/
{
ulint offs;
......@@ -133,7 +138,7 @@ page_header_set_ptr(
ut_ad((field != PAGE_HEAP_TOP) || offs);
page_header_set_field(page, field, offs);
page_header_set_field(page, page_zip, field, offs);
}
/*****************************************************************
......@@ -413,11 +418,11 @@ UNIV_INLINE
void
page_dir_set_n_slots(
/*=================*/
/* out: number of slots */
page_t* page, /* in: index page */
page_t* page, /* in/out: page */
page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
ulint n_slots)/* in: number of slots */
{
page_header_set_field(page, PAGE_N_DIR_SLOTS, n_slots);
page_header_set_field(page, page_zip, PAGE_N_DIR_SLOTS, n_slots);
}
/*****************************************************************
......@@ -438,12 +443,13 @@ UNIV_INLINE
void
page_dir_set_n_heap(
/*================*/
page_t* page, /* in: index page */
page_t* page, /* in/out: index page */
page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
ulint n_heap) /* in: number of records */
{
ut_ad(n_heap < 0x8000);
page_header_set_field(page, PAGE_N_HEAP, n_heap | (0x8000 &
page_header_set_field(page, page_zip, PAGE_N_HEAP, n_heap | (0x8000 &
page_header_get_field(page, PAGE_N_HEAP)));
}
......@@ -520,7 +526,11 @@ page_dir_slot_get_n_owned(
page_dir_slot_t* slot) /* in: page directory slot */
{
rec_t* rec = page_dir_slot_get_rec(slot);
return(rec_get_n_owned(rec, page_rec_is_comp(rec)));
if (page_rec_is_comp(slot)) {
return(rec_get_n_owned_new(rec));
} else {
return(rec_get_n_owned_old(rec));
}
}
/*******************************************************************
......@@ -529,12 +539,18 @@ UNIV_INLINE
void
page_dir_slot_set_n_owned(
/*======================*/
page_dir_slot_t* slot, /* in: directory slot */
ulint n) /* in: number of records owned
by the slot */
page_dir_slot_t*slot, /* in/out: directory slot */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 5 bytes available, or NULL */
ulint n) /* in: number of records owned by the slot */
{
rec_t* rec = page_dir_slot_get_rec(slot);
rec_set_n_owned(rec, page_rec_is_comp(rec), n);
if (page_rec_is_comp(slot)) {
rec_set_n_owned_new(rec, page_zip, n);
} else {
ut_ad(!page_zip);
rec_set_n_owned_old(rec, n);
}
}
/****************************************************************
......@@ -597,26 +613,29 @@ UNIV_INLINE
void
page_rec_set_next(
/*==============*/
rec_t* rec, /* in: pointer to record, must not be page supremum */
rec_t* next) /* in: pointer to next record, must not be page
infimum */
rec_t* rec, /* in: pointer to record,
must not be page supremum */
rec_t* next, /* in: pointer to next record,
must not be page infimum */
page_zip_des_t* page_zip) /* in/out: compressed page with
at least 6 bytes available, or NULL */
{
page_t* page;
ulint offs;
ut_ad(page_rec_check(rec));
ut_ad(!page_rec_is_supremum(rec));
page = ut_align_down(rec, UNIV_PAGE_SIZE);
if (next) {
ut_ad(!page_rec_is_infimum(next));
ut_ad(page == ut_align_down(next, UNIV_PAGE_SIZE));
offs = (ulint) (next - page);
ut_ad(!next || !page_rec_is_infimum(next));
ut_ad(!next || ut_align_down(rec, UNIV_PAGE_SIZE)
== ut_align_down(next, UNIV_PAGE_SIZE));
offs = ut_align_offset(next, UNIV_PAGE_SIZE);
if (page_rec_is_comp(rec)) {
rec_set_next_offs_new(rec, page_zip, offs);
} else {
offs = 0;
rec_set_next_offs_old(rec, offs);
ut_ad(!page_zip);
}
rec_set_next_offs(rec, page_is_comp(page), offs);
}
/****************************************************************
......@@ -671,11 +690,11 @@ page_rec_find_owner_rec(
ut_ad(page_rec_check(rec));
if (page_rec_is_comp(rec)) {
while (rec_get_n_owned(rec, TRUE) == 0) {
while (rec_get_n_owned_new(rec) == 0) {
rec = page_rec_get_next(rec);
}
} else {
while (rec_get_n_owned(rec, FALSE) == 0) {
while (rec_get_n_owned_old(rec) == 0) {
rec = page_rec_get_next(rec);
}
}
......@@ -683,6 +702,23 @@ page_rec_find_owner_rec(
return(rec);
}
/**************************************************************
Returns the base extra size of a physical record. This is the
size of the fixed header, independent of the record size. */
UNIV_INLINE
ulint
page_rec_get_base_extra_size(
/*=========================*/
/* out: REC_N_NEW_EXTRA_BYTES
or REC_N_OLD_EXTRA_BYTES */
const rec_t* rec) /* in: physical record */
{
#if REC_N_NEW_EXTRA_BYTES + 1 != REC_N_OLD_EXTRA_BYTES
# error "REC_N_NEW_EXTRA_BYTES + 1 != REC_N_OLD_EXTRA_BYTES"
#endif
return(REC_N_NEW_EXTRA_BYTES + (ulint) !page_rec_is_comp(rec));
}
/****************************************************************
Returns the sum of the sizes of the records in the record list, excluding
the infimum and supremum records. */
......@@ -805,7 +841,9 @@ UNIV_INLINE
void
page_mem_free(
/*==========*/
page_t* page, /* in: index page */
page_t* page, /* in/out: index page */
page_zip_des_t* page_zip,/* in/out: compressed page with at least
6 bytes available, or NULL */
rec_t* rec, /* in: pointer to the (origin of) record */
const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
......@@ -816,8 +854,8 @@ page_mem_free(
ut_ad(!rec_offs_comp(offsets) == !page_rec_is_comp(rec));
free = page_header_get_ptr(page, PAGE_FREE);
page_rec_set_next(rec, free);
page_header_set_ptr(page, PAGE_FREE, rec);
page_rec_set_next(rec, free, page_zip);
page_header_set_ptr(page, page_zip, PAGE_FREE, rec);
#if 0 /* It's better not to destroy the user's data. */
......@@ -827,11 +865,18 @@ page_mem_free(
cannot be cleared, because page_mem_alloc() needs them in order
to determine the size of the deleted record. */
memset(rec, 0, rec_offs_data_size(offsets));
/* If you enable this code, make sure that the callers of
page_mem_free() account for the increased usage of space. */
if (UNIV_LIKELY_NULL(page_zip)) {
page_zip_write(page_zip, page, rec, rec - page,
rec_offs_data_size(offsets));
}
#endif
garbage = page_header_get_field(page, PAGE_GARBAGE);
page_header_set_field(page, PAGE_GARBAGE,
page_header_set_field(page, page_zip, PAGE_GARBAGE,
garbage + rec_offs_size(offsets));
}
......
......@@ -18,5 +18,71 @@ typedef byte page_t;
typedef struct page_search_struct page_search_t;
typedef struct page_cur_struct page_cur_t;
typedef byte page_zip_t;
typedef struct page_zip_des_struct page_zip_des_t;
/* The following definitions would better belong to page0zip.h,
but we cannot include page0zip.h from rem0rec.ic, because
page0*.h includes rem0rec.h and may include rem0rec.ic. */
/* Compressed page descriptor */
struct page_zip_des_struct
{
page_zip_t* data; /* compressed page data */
ulint size; /* total size of compressed page */
ulint m_start; /* start offset of modification log */
ulint m_end; /* end offset of modification log */
};
/**************************************************************************
Write data to the compressed page. The data must already be written to
the uncompressed page. */
void
page_zip_write(
/*===========*/
page_zip_des_t* page_zip,/* out: compressed page */
const byte* str, /* in: address on the uncompressed page */
ulint length) /* in: length of the data */
__attribute__((nonnull));
/**************************************************************************
Write data to the uncompressed header portion of a page. The data must
already have been written to the uncompressed page. */
UNIV_INLINE
void
page_zip_write_header(
/*==================*/
page_zip_des_t* page_zip,/* in/out: compressed page */
const byte* str, /* in: address on the uncompressed page */
ulint length) /* in: length of the data */
__attribute__((nonnull));
/**************************************************************************
Write data to the uncompressed trailer portion of a page. The data must
already have been written to the uncompressed page. */
UNIV_INLINE
void
page_zip_write_trailer(
/*===================*/
page_zip_des_t* page_zip,/* in/out: compressed page */
const byte* str, /* in: address on the uncompressed page */
ulint length) /* in: length of the data */
__attribute__((nonnull));
#ifdef UNIV_DEBUG
/**************************************************************************
Determine if enough space is available in the modification log. */
ibool
page_zip_available_noninline(
/*=========================*/
/* out: TRUE if enough space
is available */
const page_zip_des_t* page_zip,/* in: compressed page */
ulint size)
__attribute__((warn_unused_result, nonnull, pure));
#endif /* UNIV_DEBUG */
#endif
/******************************************************
Compressed page interface
(c) 2005 Innobase Oy
Created June 2005 by Marko Makela
*******************************************************/
#ifndef page0zip_h
#define page0zip_h
#ifdef UNIV_MATERIALIZE
# undef UNIV_INLINE
# define UNIV_INLINE
#endif
#include "mtr0types.h"
#include "page0types.h"
/**************************************************************************
Initialize a compressed page descriptor. */
UNIV_INLINE
void
page_zip_des_init(
/*==============*/
page_zip_des_t* page_zip); /* in/out: compressed page
descriptor */
/**************************************************************************
Compress a page. */
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,/* out: compressed page */
const page_t* page); /* in: uncompressed page */
/**************************************************************************
Decompress a page. */
ibool
page_zip_decompress(
/*================*/
/* out: TRUE on success, FALSE on failure */
page_zip_des_t* page_zip,/* in: data, size; out: m_start, m_end */
page_t* page, /* out: uncompressed page, may be trashed */
mtr_t* mtr) /* in: mini-transaction handle,
or NULL if no logging is needed */
__attribute__((warn_unused_result, nonnull(1, 2)));
#ifdef UNIV_DEBUG
/**************************************************************************
Validate a compressed page descriptor. */
UNIV_INLINE
ibool
page_zip_simple_validate(
/*=====================*/
/* out: TRUE if ok */
const page_zip_des_t* page_zip); /* in: compressed page
descriptor */
/**************************************************************************
Check that the compressed and decompressed pages match. */
ibool
page_zip_validate(
/*==============*/
const page_zip_des_t* page_zip,/* in: compressed page */
const page_t* page); /* in: uncompressed page */
#endif /* UNIV_DEBUG */
/**************************************************************************
Determine the encoded length of an integer in the modification log. */
UNIV_INLINE
ulint
page_zip_ulint_size(
/*================*/
/* out: length of the integer, in bytes */
ulint num) /* in: the integer */
__attribute__((const));
/**************************************************************************
Determine the size of a modification log entry. */
UNIV_INLINE
ulint
page_zip_entry_size(
/*================*/
/* out: length of the log entry, in bytes */
ulint pos, /* in: offset of the uncompressed page */
ulint length) /* in: length of the data */
__attribute__((const));
/**************************************************************************
Ensure that enough space is available in the modification log.
If not, try to compress the page. */
UNIV_INLINE
ibool
page_zip_alloc(
/*===========*/
/* out: TRUE if enough space is available */
page_zip_des_t* page_zip,/* in/out: compressed page;
will only be modified if compression is needed
and successful */
const page_t* page, /* in: uncompressed page */
ulint size) /* in: size of modification log entries */
__attribute__((nonnull));
/**************************************************************************
Determine if enough space is available in the modification log. */
UNIV_INLINE
ibool
page_zip_available(
/*===============*/
/* out: TRUE if enough space
is available */
const page_zip_des_t* page_zip,/* in: compressed page */
ulint size) /* in: requested size of
modification log entries */
__attribute__((warn_unused_result, nonnull, pure));
#ifdef UNIV_DEBUG
/**************************************************************************
Determine if enough space is available in the modification log. */
ibool
page_zip_available_noninline(
/*=========================*/
/* out: TRUE if enough space
is available */
const page_zip_des_t* page_zip,/* in: compressed page */
ulint size)
__attribute__((warn_unused_result, nonnull, pure));
#endif /* UNIV_DEBUG */
/**************************************************************************
Write data to the compressed portion of a page. The data must already
have been written to the uncompressed page. */
void
page_zip_write(
/*===========*/
page_zip_des_t* page_zip,/* in/out: compressed page */
const byte* str, /* in: address on the uncompressed page */
ulint length) /* in: length of the data */
__attribute__((nonnull));
/**************************************************************************
Write data to the uncompressed header portion of a page. The data must
already have been written to the uncompressed page. */
UNIV_INLINE
void
page_zip_write_header(
/*==================*/
page_zip_des_t* page_zip,/* in/out: compressed page */
const byte* str, /* in: address on the uncompressed page */
ulint length) /* in: length of the data */
__attribute__((nonnull));
/**************************************************************************
Write data to the uncompressed trailer portion of a page. The data must
already have been written to the uncompressed page. */
UNIV_INLINE
void
page_zip_write_trailer(
/*===================*/
page_zip_des_t* page_zip,/* in/out: compressed page */
const byte* str, /* in: address on the uncompressed page */
ulint length) /* in: length of the data */
__attribute__((nonnull));
#ifdef UNIV_MATERIALIZE
# undef UNIV_INLINE
# define UNIV_INLINE UNIV_INLINE_ORIGINAL
#endif
#ifndef UNIV_NONINL
# include "page0zip.ic"
#endif
#endif /* page0zip_h */
/******************************************************
Compressed page interface
(c) 2005 Innobase Oy
Created June 2005 by Marko Makela
*******************************************************/
#ifdef UNIV_MATERIALIZE
# undef UNIV_INLINE
# define UNIV_INLINE
#endif
#include "page0zip.h"
#include "page0page.h"
/* The format of compressed pages is as follows.
The header and trailer of the uncompressed pages, including the page
directory in the trailer, are copied as is to the header and trailer
of the compressed page. Immediately preceding the page trailer,
we store a 32-bit checksum of the compressed data.
The data between PAGE_DATA and the last page directory entry
will be written in compressed format, starting at offset PAGE_DATA.
The compressed data stream may be followed by a modification log
covering the compressed portion of the page, as follows.
MODIFICATION LOG ENTRY FORMAT
- length (1..2 bytes), not zero
- offset - PAGE_DATA (1..2 bytes)
- data bytes
The length and the offset are stored in a variable-length format:
- 0xxxxxxxx : 0..127
- 10xxxxxxx xxxxxxxx: 0..16383
- 11xxxxxxx xxxxxxxx: reserved
The end of the modification log is marked by length=0. */
/**************************************************************************
Initialize a compressed page descriptor. */
UNIV_INLINE
void
page_zip_des_init(
/*==============*/
page_zip_des_t* page_zip) /* in/out: compressed page
descriptor */
{
memset(page_zip, 0, sizeof *page_zip);
}
/**************************************************************************
Determine the encoded length of an integer in the modification log. */
UNIV_INLINE
ulint
page_zip_ulint_size(
/*================*/
/* out: length of the integer, in bytes */
ulint num) /* in: the integer */
{
if (num < 128) { /* 0xxxxxxx: 0..127 */
return(1);
}
if (num < 16384) { /* 10xxxxxx xxxxxxxx: 0..16383 */
return(2);
}
ut_error;
return(0);
}
/**************************************************************************
Determine the size of a modification log entry. */
UNIV_INLINE
ulint
page_zip_entry_size(
/*================*/
/* out: length of the log entry, in bytes */
ulint pos, /* in: offset of the uncompressed page */
ulint length) /* in: length of the data */
{
ut_ad(pos >= PAGE_DATA);
ut_ad(pos + length <= UNIV_PAGE_SIZE - PAGE_DATA /* - trailer_len */);
return(page_zip_ulint_size(pos - PAGE_DATA)
+ page_zip_ulint_size(length)
+ length);
}
#ifdef UNIV_DEBUG
/**************************************************************************
Validate a compressed page descriptor. */
UNIV_INLINE
ibool
page_zip_simple_validate(
/*=====================*/
/* out: TRUE if ok */
const page_zip_des_t* page_zip)/* in: compressed page descriptor */
{
ut_ad(page_zip);
ut_ad(page_zip->data);
ut_ad(!(page_zip->size & (page_zip->size - 1)));
ut_ad(page_zip->size < UNIV_PAGE_SIZE);
ut_ad(page_zip->size > PAGE_DATA + PAGE_EMPTY_DIR_START);
ut_ad(page_zip->m_start <= page_zip->m_end);
ut_ad(page_zip->m_end < page_zip->size);
return(TRUE);
}
#endif /* UNIV_DEBUG */
/**************************************************************************
Ensure that enough space is available in the modification log.
If not, try to compress the page. */
UNIV_INLINE
ibool
page_zip_alloc(
/*===========*/
/* out: TRUE if enough space is available */
page_zip_des_t* page_zip,/* in/out: compressed page;
will only be modified if compression is needed
and successful */
const page_t* page, /* in: uncompressed page */
ulint size) /* in: size of modification log entries */
{
ulint trailer_len = PAGE_DIR + PAGE_DIR_SLOT_SIZE
* page_dir_get_n_slots((page_t*) page_zip->data);
ut_ad(page_zip_simple_validate(page_zip));
ut_ad(page_zip->m_end + trailer_len < page_zip->size);
ut_ad(size >= 3); /* modification log entries are >= 1+1+1 bytes */
ut_ad(size < page_zip->size);
if (size < page_zip->size - page_zip->m_end - trailer_len) {
return(TRUE);
}
if (page_zip->m_start == page_zip->m_end) {
/* The page has been freshly compressed, so
recompressing it will not help. */
return(FALSE);
}
return(page_zip_compress(page_zip, page));
}
/**************************************************************************
Determine if enough space is available in the modification log. */
UNIV_INLINE
ibool
page_zip_available(
/*===============*/
/* out: TRUE if enough space
is available */
const page_zip_des_t* page_zip,/* in: compressed page */
ulint size) /* in: requested size of
modification log entries */
{
ulint trailer_len = PAGE_DIR + PAGE_DIR_SLOT_SIZE
* page_dir_get_n_slots((page_t*) page_zip->data);
ut_ad(page_zip_simple_validate(page_zip));
ut_ad(page_zip->m_end + trailer_len < page_zip->size);
ut_ad(size >= 3); /* modification log entries are >= 1+1+1 bytes */
ut_ad(size < page_zip->size);
return(UNIV_LIKELY(
size < page_zip->size - page_zip->m_end - trailer_len));
}
/**************************************************************************
Write data to the uncompressed header portion of a page. The data must
already have been written to the uncompressed page. */
UNIV_INLINE
void
page_zip_write_header(
/*==================*/
page_zip_des_t* page_zip,/* in/out: compressed page */
const byte* str, /* in: address on the uncompressed page */
ulint length) /* in: length of the data */
{
ulint pos;
ut_ad(buf_block_get_page_zip(buf_block_align((byte*)str)) == page_zip);
ut_ad(page_zip_simple_validate(page_zip));
pos = ut_align_offset(str, UNIV_PAGE_SIZE);
ut_ad(pos < PAGE_DATA);
memcpy(page_zip + pos, str, length);
ut_ad(page_zip_validate(page_zip, str - pos));
}
/**************************************************************************
Write data to the uncompressed trailer portion of a page. The data must
already have been written to the uncompressed page. */
UNIV_INLINE
void
page_zip_write_trailer(
/*===================*/
page_zip_des_t* page_zip,/* in/out: compressed page */
const byte* str, /* in: address on the uncompressed page */
ulint length) /* in: length of the data */
{
ulint pos;
ut_ad(buf_block_get_page_zip(buf_block_align((byte*)str)) == page_zip);
ut_ad(page_zip_simple_validate(page_zip));
pos = ut_align_offset(str, UNIV_PAGE_SIZE);
ut_ad(pos < PAGE_DATA);/* TODO */
memcpy(page_zip + pos/* TODO */, str, length);
ut_ad(page_zip_validate(page_zip, str - pos));
}
#ifdef UNIV_MATERIALIZE
# undef UNIV_INLINE
# define UNIV_INLINE UNIV_INLINE_ORIGINAL
#endif
......@@ -13,11 +13,10 @@ Created 5/30/1994 Heikki Tuuri
#include "data0data.h"
#include "rem0types.h"
#include "mtr0types.h"
#include "page0types.h"
/* Maximum values for various fields (for non-blob tuples) */
#define REC_MAX_N_FIELDS (1024 - 1)
#define REC_MAX_HEAP_NO (2 * 8192 - 1)
#define REC_MAX_N_OWNED (16 - 1)
/* Flag denoting the predefined minimum record: this bit is ORed in the 4
info bits of a record */
......@@ -41,6 +40,17 @@ offsets[] array, first passed to rec_get_offsets() */
#define REC_OFFS_NORMAL_SIZE 100
#define REC_OFFS_SMALL_SIZE 10
/**********************************************************
The following function is used to get the pointer of the next chained record
on the same page. */
UNIV_INLINE
rec_t*
rec_get_next_ptr(
/*=============*/
/* out: pointer to the next chained record, or
NULL if none */
rec_t* rec, /* in: physical record */
ulint comp); /* in: nonzero=compact page format */
/**********************************************************
The following function is used to get the offset of the
next chained record on the same page. */
......@@ -54,13 +64,23 @@ rec_get_next_offs(
ulint comp); /* in: nonzero=compact page format */
/**********************************************************
The following function is used to set the next record offset field
of the record. */
of an old-style record. */
UNIV_INLINE
void
rec_set_next_offs(
/*==============*/
rec_t* rec, /* in: physical record */
ulint comp, /* in: nonzero=compact page format */
rec_set_next_offs_old(
/*==================*/
rec_t* rec, /* in: old-style physical record */
ulint next); /* in: offset of the next record */
/**********************************************************
The following function is used to set the next record offset field
of a new-style record. */
UNIV_INLINE
void
rec_set_next_offs_new(
/*==================*/
rec_t* rec, /* in/out: new-style physical record */
page_zip_des_t* page_zip,/* in/out: compressed page with at least
6 bytes available, or NULL */
ulint next); /* in: offset of the next record */
/**********************************************************
The following function is used to get the number of fields
......@@ -82,26 +102,44 @@ rec_get_n_fields(
rec_t* rec, /* in: physical record */
dict_index_t* index); /* in: record descriptor */
/**********************************************************
The following function is used to get the number of records
owned by the previous directory record. */
The following function is used to get the number of records owned by the
previous directory record. */
UNIV_INLINE
ulint
rec_get_n_owned(
/*============*/
rec_get_n_owned_old(
/*================*/
/* out: number of owned records */
rec_t* rec, /* in: physical record */
ulint comp); /* in: nonzero=compact page format */
rec_t* rec); /* in: old-style physical record */
/**********************************************************
The following function is used to set the number of owned
records. */
The following function is used to set the number of owned records. */
UNIV_INLINE
void
rec_set_n_owned(
/*============*/
rec_t* rec, /* in: physical record */
ulint comp, /* in: nonzero=compact page format */
rec_set_n_owned_old(
/*================*/
/* out: TRUE on success */
rec_t* rec, /* in: old-style physical record */
ulint n_owned); /* in: the number of owned */
/**********************************************************
The following function is used to get the number of records owned by the
previous directory record. */
UNIV_INLINE
ulint
rec_get_n_owned_new(
/*================*/
/* out: number of owned records */
rec_t* rec); /* in: new-style physical record */
/**********************************************************
The following function is used to set the number of owned records. */
UNIV_INLINE
void
rec_set_n_owned_new(
/*================*/
/* out: TRUE on success */
rec_t* rec, /* in/out: new-style physical record */
page_zip_des_t* page_zip,/* in/out: compressed page with at least
5 bytes available, or NULL */
ulint n_owned);/* in: the number of owned */
/**********************************************************
The following function is used to retrieve the info bits of
a record. */
UNIV_INLINE
......@@ -115,10 +153,19 @@ rec_get_info_bits(
The following function is used to set the info bits of a record. */
UNIV_INLINE
void
rec_set_info_bits(
/*==============*/
rec_t* rec, /* in: physical record */
ulint comp, /* in: nonzero=compact page format */
rec_set_info_bits_old(
/*==================*/
rec_t* rec, /* in: old-style physical record */
ulint bits); /* in: info bits */
/**********************************************************
The following function is used to set the info bits of a record. */
UNIV_INLINE
void
rec_set_info_bits_new(
/*==================*/
rec_t* rec, /* in/out: new-style physical record */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 5 bytes available, or NULL */
ulint bits); /* in: info bits */
/**********************************************************
The following function retrieves the status bits of a new-style record. */
......@@ -135,7 +182,9 @@ UNIV_INLINE
void
rec_set_status(
/*===========*/
rec_t* rec, /* in: physical record */
rec_t* rec, /* in/out: physical record */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 5 bytes available, or NULL */
ulint bits); /* in: info bits */
/**********************************************************
......@@ -155,8 +204,9 @@ UNIV_INLINE
void
rec_set_info_and_status_bits(
/*=========================*/
rec_t* rec, /* in: physical record */
ulint comp, /* in: nonzero=compact page format */
rec_t* rec, /* in/out: compact physical record */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 5 bytes available, or NULL */
ulint bits); /* in: info bits */
/**********************************************************
......@@ -172,38 +222,65 @@ rec_get_deleted_flag(
The following function is used to set the deleted bit. */
UNIV_INLINE
void
rec_set_deleted_flag(
/*=================*/
rec_t* rec, /* in: physical record */
ulint comp, /* in: nonzero=compact page format */
rec_set_deleted_flag_old(
/*=====================*/
rec_t* rec, /* in: old-style physical record */
ulint flag); /* in: nonzero if delete marked */
/**********************************************************
The following function is used to set the deleted bit. */
UNIV_INLINE
void
rec_set_deleted_flag_new(
/*=====================*/
rec_t* rec, /* in/out: new-style physical record */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 5 bytes available, or NULL */
ulint flag); /* in: nonzero if delete marked */
/**********************************************************
The following function tells if a new-style record is a node pointer. */
UNIV_INLINE
ibool
rec_get_node_ptr_flag(
/*=================*/
/*==================*/
/* out: TRUE if node pointer */
rec_t* rec); /* in: physical record */
/**********************************************************
The following function is used to get the order number
of the record in the heap of the index page. */
of an old-style record in the heap of the index page. */
UNIV_INLINE
ulint
rec_get_heap_no(
/*=============*/
rec_get_heap_no_old(
/*================*/
/* out: heap order number */
rec_t* rec, /* in: physical record */
ulint comp); /* in: nonzero=compact page format */
rec_t* rec); /* in: physical record */
/**********************************************************
The following function is used to set the heap number
field in the record. */
field in an old-style record. */
UNIV_INLINE
void
rec_set_heap_no(
/*=============*/
rec_set_heap_no_old(
/*================*/
rec_t* rec, /* in: physical record */
ulint comp, /* in: nonzero=compact page format */
ulint heap_no);/* in: the heap number */
/**********************************************************
The following function is used to get the order number
of a new-style record in the heap of the index page. */
UNIV_INLINE
ulint
rec_get_heap_no_new(
/*================*/
/* out: heap order number */
rec_t* rec); /* in: physical record */
/**********************************************************
The following function is used to set the heap number
field in a new-style record. */
UNIV_INLINE
void
rec_set_heap_no_new(
/*================*/
rec_t* rec, /* in/out: physical record */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 6 bytes available, or NULL */
ulint heap_no);/* in: the heap number */
/**********************************************************
The following function is used to test whether the data offsets
......@@ -340,7 +417,7 @@ rec_offs_any_extern(
/* out: TRUE if a field is stored externally */
const ulint* offsets);/* in: array returned by rec_get_offsets() */
/***************************************************************
Sets the value of the ith field extern storage bit. */
Sets the ith field extern storage bit. */
UNIV_INLINE
void
rec_set_nth_field_extern_bit(
......@@ -348,7 +425,6 @@ rec_set_nth_field_extern_bit(
rec_t* rec, /* in: record */
dict_index_t* index, /* in: record descriptor */
ulint i, /* in: ith field */
ibool val, /* in: value to set */
mtr_t* mtr); /* in: mtr holding an X-latch to the page
where rec is, or NULL; in the NULL case
we do not write to log about the change */
......@@ -489,8 +565,8 @@ rec_fold(
in an incomplete last field */
dulint tree_id); /* in: index tree id */
/*************************************************************
Builds a physical record out of a data tuple and stores it beginning from
address destination. */
Builds a physical record out of a data tuple and
stores it into the given buffer. */
rec_t*
rec_convert_dtuple_to_rec(
......
This diff is collapsed.
......@@ -45,7 +45,9 @@ UNIV_INLINE
void
row_set_rec_trx_id(
/*===============*/
rec_t* rec, /* in: record */
rec_t* rec, /* in/out: record */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 10 bytes available,, or NULL */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint trx_id);/* in: value of the field */
......@@ -55,7 +57,9 @@ UNIV_INLINE
void
row_set_rec_roll_ptr(
/*=================*/
rec_t* rec, /* in: record */
rec_t* rec, /* in/out: record */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 11 bytes available, or NULL */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint roll_ptr);/* in: value of the field */
......
......@@ -29,9 +29,10 @@ is slower than the specialized inline functions. */
void
row_set_rec_sys_field(
/*==================*/
/* out: value of the field */
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
rec_t* rec, /* in/out: record */
page_zip_des_t* page_zip,/* in/out: compressed page with at least
10 or 11 bytes available, or NULL */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint val); /* in: value to set */
......@@ -94,7 +95,9 @@ UNIV_INLINE
void
row_set_rec_trx_id(
/*===============*/
rec_t* rec, /* in: record */
rec_t* rec, /* in/out: record */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 10 bytes available, or NULL */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint trx_id) /* in: value of the field */
......@@ -107,10 +110,10 @@ row_set_rec_trx_id(
offset = index->trx_id_offset;
if (offset) {
trx_write_trx_id(rec + offset, trx_id);
trx_write_trx_id(rec + offset, page_zip, trx_id);
} else {
row_set_rec_sys_field(DATA_TRX_ID,
rec, index, offsets, trx_id);
rec, page_zip, index, offsets, trx_id);
}
}
......@@ -120,7 +123,9 @@ UNIV_INLINE
void
row_set_rec_roll_ptr(
/*=================*/
rec_t* rec, /* in: record */
rec_t* rec, /* in/out: record */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 11 bytes available, or NULL */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint roll_ptr)/* in: value of the field */
......@@ -133,10 +138,11 @@ row_set_rec_roll_ptr(
offset = index->trx_id_offset;
if (offset) {
trx_write_roll_ptr(rec + offset + DATA_TRX_ID_LEN, roll_ptr);
trx_write_roll_ptr(rec + offset + DATA_TRX_ID_LEN,
page_zip, roll_ptr);
} else {
row_set_rec_sys_field(DATA_ROLL_PTR,
rec, index, offsets, roll_ptr);
rec, page_zip, index, offsets, roll_ptr);
}
}
......
......@@ -78,7 +78,9 @@ UNIV_INLINE
void
row_upd_rec_sys_fields(
/*===================*/
rec_t* rec, /* in: record */
rec_t* rec, /* in/out: record */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 21 bytes available, or NULL */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
trx_t* trx, /* in: transaction */
......@@ -276,7 +278,8 @@ recovery. */
void
row_upd_rec_sys_fields_in_recovery(
/*===============================*/
rec_t* rec, /* in: record */
rec_t* rec, /* in/out: record */
page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint pos, /* in: TRX_ID position in rec */
dulint trx_id, /* in: transaction id */
......
......@@ -11,6 +11,7 @@ Created 12/27/1996 Heikki Tuuri
#include "trx0undo.h"
#include "row0row.h"
#include "btr0sea.h"
#include "page0zip.h"
/*************************************************************************
Creates an update vector object. */
......@@ -104,7 +105,9 @@ UNIV_INLINE
void
row_upd_rec_sys_fields(
/*===================*/
rec_t* rec, /* in: record */
rec_t* rec, /* in/out: record */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 21 bytes available, or NULL */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
trx_t* trx, /* in: transaction */
......@@ -116,7 +119,8 @@ row_upd_rec_sys_fields(
ut_ad(!buf_block_align(rec)->is_hashed
|| rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(!page_zip || page_zip_available(page_zip, 21));
row_set_rec_trx_id(rec, index, offsets, trx->id);
row_set_rec_roll_ptr(rec, index, offsets, roll_ptr);
row_set_rec_trx_id(rec, page_zip, index, offsets, trx->id);
row_set_rec_roll_ptr(rec, page_zip, index, offsets, roll_ptr);
}
......@@ -23,6 +23,7 @@ Created 3/26/1996 Heikki Tuuri
#include "fut0lst.h"
#include "fsp0fsp.h"
#include "read0types.h"
#include "page0types.h"
/* In a MySQL replication slave, in crash recovery we store the master log
file name and position here. We have successfully got the updates to InnoDB
......@@ -211,6 +212,8 @@ void
trx_write_trx_id(
/*=============*/
byte* ptr, /* in: pointer to memory where written */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 10 bytes available, or NULL */
dulint id); /* in: id */
/*********************************************************************
Reads a trx id from an index page. In case that the id size changes in
......
......@@ -9,6 +9,7 @@ Created 3/26/1996 Heikki Tuuri
#include "srv0srv.h"
#include "trx0trx.h"
#include "data0type.h"
#include "page0zip.h"
/* The typedef for rseg slot in the file copy */
typedef byte trx_sysf_rseg_t;
......@@ -214,11 +215,17 @@ void
trx_write_trx_id(
/*=============*/
byte* ptr, /* in: pointer to memory where written */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 10 bytes available, or NULL */
dulint id) /* in: id */
{
ut_ad(DATA_TRX_ID_LEN == 6);
mach_write_to_6(ptr, id);
if (UNIV_LIKELY_NULL(page_zip)) {
ut_ad(page_zip_available(page_zip, 4 + DATA_TRX_ID_LEN));
page_zip_write(page_zip, ptr, DATA_TRX_ID_LEN);
}
}
/*********************************************************************
......
......@@ -55,6 +55,8 @@ void
trx_write_roll_ptr(
/*===============*/
byte* ptr, /* in: pointer to memory where written */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 11 bytes available, or NULL */
dulint roll_ptr); /* in: roll ptr */
/*********************************************************************
Reads a roll ptr from an index page. In case that the roll ptr size
......
......@@ -7,6 +7,7 @@ Created 3/26/1996 Heikki Tuuri
*******************************************************/
#include "data0type.h"
#include "page0zip.h"
/***************************************************************************
Builds a roll pointer dulint. */
......@@ -88,11 +89,17 @@ void
trx_write_roll_ptr(
/*===============*/
byte* ptr, /* in: pointer to memory where written */
dulint roll_ptr) /* in: roll ptr */
page_zip_des_t* page_zip,/* in/out: compressed page with
at least 11 bytes available, or NULL */
dulint roll_ptr)/* in: roll ptr */
{
ut_ad(DATA_ROLL_PTR_LEN == 7);
mach_write_to_7(ptr, roll_ptr);
if (UNIV_LIKELY_NULL(page_zip)) {
ut_ad(page_zip_available(page_zip, 4 + DATA_ROLL_PTR_LEN));
page_zip_write(page_zip, ptr, DATA_ROLL_PTR_LEN);
}
}
/*********************************************************************
......
This diff is collapsed.
......@@ -22,6 +22,7 @@ Created 9/20/1997 Heikki Tuuri
#include "mtr0log.h"
#include "page0page.h"
#include "page0cur.h"
#include "page0zip.h"
#include "btr0btr.h"
#include "btr0cur.h"
#include "ibuf0ibuf.h"
......@@ -753,9 +754,10 @@ recv_parse_or_apply_log_rec_body(
byte type, /* in: type */
byte* ptr, /* in: pointer to a buffer */
byte* end_ptr,/* in: pointer to the buffer end */
page_t* page, /* in: buffer page or NULL; if not NULL, then the log
record is applied to the page, and the log record
page_t* page, /* in/out: buffer page or NULL; if not NULL, then the
log record is applied to the page, and the log record
should be complete then */
page_zip_des_t* page_zip,/* in/out: compressed page or NULL */
mtr_t* mtr) /* in: mtr or NULL; should be non-NULL if and only if
page is non-NULL */
{
......@@ -771,7 +773,7 @@ recv_parse_or_apply_log_rec_body(
ut_a(!page
|| (ibool)!!page_is_comp(page)==index->table->comp);
ptr = page_cur_parse_insert_rec(FALSE, ptr, end_ptr,
index, page, mtr);
index, page, page_zip, mtr);
}
break;
case MLOG_REC_CLUST_DELETE_MARK: case MLOG_COMP_REC_CLUST_DELETE_MARK:
......@@ -780,7 +782,7 @@ recv_parse_or_apply_log_rec_body(
ut_a(!page
|| (ibool)!!page_is_comp(page)==index->table->comp);
ptr = btr_cur_parse_del_mark_set_clust_rec(ptr,
end_ptr, index, page);
end_ptr, page, page_zip, index);
}
break;
case MLOG_COMP_REC_SEC_DELETE_MARK:
......@@ -793,7 +795,8 @@ recv_parse_or_apply_log_rec_body(
}
/* Fall through */
case MLOG_REC_SEC_DELETE_MARK:
ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr, page);
ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr,
page, page_zip);
break;
case MLOG_REC_UPDATE_IN_PLACE: case MLOG_COMP_REC_UPDATE_IN_PLACE:
if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
......@@ -801,7 +804,7 @@ recv_parse_or_apply_log_rec_body(
ut_a(!page
|| (ibool)!!page_is_comp(page)==index->table->comp);
ptr = btr_cur_parse_update_in_place(ptr, end_ptr,
page, index);
page, page_zip, index);
}
break;
case MLOG_LIST_END_DELETE: case MLOG_COMP_LIST_END_DELETE:
......@@ -821,7 +824,7 @@ recv_parse_or_apply_log_rec_body(
ut_a(!page
|| (ibool)!!page_is_comp(page)==index->table->comp);
ptr = page_parse_copy_rec_list_to_created_page(ptr,
end_ptr, index, page, mtr);
end_ptr, index, page, page_zip, mtr);
}
break;
case MLOG_PAGE_REORGANIZE: case MLOG_COMP_PAGE_REORGANIZE:
......@@ -864,7 +867,7 @@ recv_parse_or_apply_log_rec_body(
ut_a(!page
|| (ibool)!!page_is_comp(page)==index->table->comp);
ptr = page_cur_parse_delete_rec(ptr, end_ptr,
index, page, mtr);
index, page, page_zip, mtr);
}
break;
case MLOG_IBUF_BITMAP_INIT:
......@@ -882,6 +885,16 @@ recv_parse_or_apply_log_rec_body(
ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, FALSE,
ULINT_UNDEFINED);
break;
case MLOG_COMP_DECOMPRESS:
if (page) {
ut_a(page_is_comp(page));
ut_a(page_zip);
if (UNIV_UNLIKELY(!page_zip_decompress(
page_zip, page, NULL))) {
ut_error;
}
}
break;
default:
ptr = NULL;
recv_sys->found_corrupt_log = TRUE;
......@@ -1089,6 +1102,7 @@ recv_recover_page(
ulint page_no) /* in: page number */
{
buf_block_t* block = NULL;
page_zip_des_t* page_zip = NULL;
recv_addr_t* recv_addr;
recv_t* recv;
byte* buf;
......@@ -1133,6 +1147,7 @@ recv_recover_page(
if (!recover_backup) {
block = buf_block_align(page);
page_zip = buf_block_get_page_zip(block);
if (just_read_in) {
/* Move the ownership of the x-latch on the page to this OS
......@@ -1220,7 +1235,8 @@ recv_recover_page(
#endif /* UNIV_DEBUG */
recv_parse_or_apply_log_rec_body(recv->type, buf,
buf + recv->len, page, &mtr);
buf + recv->len,
page, page_zip, &mtr);
mach_write_to_8(page + UNIV_PAGE_SIZE
- FIL_PAGE_END_LSN_OLD_CHKSUM,
ut_dulint_add(recv->start_lsn,
......@@ -1613,8 +1629,8 @@ recv_update_replicate(
buf_page_dbg_add_level(replica, SYNC_NO_ORDER_CHECK);
#endif /* UNIV_SYNC_DEBUG */
ptr = recv_parse_or_apply_log_rec_body(type, body, end_ptr, replica,
&mtr);
ptr = recv_parse_or_apply_log_rec_body(type, body, end_ptr,
replica, NULL, &mtr);
ut_a(ptr == end_ptr);
/* Notify the buffer manager that the page has been updated */
......@@ -1845,7 +1861,7 @@ recv_parse_log_rec(
}
new_ptr = recv_parse_or_apply_log_rec_body(*type, new_ptr, end_ptr,
NULL, NULL);
NULL, NULL, NULL);
if (UNIV_UNLIKELY(new_ptr == NULL)) {
return(0);
......
......@@ -19,6 +19,6 @@ include ../include/Makefile.i
noinst_LIBRARIES = libpage.a
libpage_a_SOURCES = page0page.c page0cur.c
libpage_a_SOURCES = page0page.c page0cur.c page0zip.c
EXTRA_PROGRAMS =
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -537,14 +537,13 @@ rec_set_nth_field_null_bit(
}
/***************************************************************
Sets the value of the ith field extern storage bit of an old-style record. */
Sets the ith field extern storage bit of an old-style record. */
void
rec_set_nth_field_extern_bit_old(
/*=============================*/
rec_t* rec, /* in: old-style record */
ulint i, /* in: ith field */
ibool val, /* in: value to set */
mtr_t* mtr) /* in: mtr holding an X-latch to the page where
rec is, or NULL; in the NULL case we do not
write to log about the change */
......@@ -556,11 +555,7 @@ rec_set_nth_field_extern_bit_old(
info = rec_2_get_field_end_info(rec, i);
if (val) {
info = info | REC_2BYTE_EXTERN_MASK;
} else {
info = info & ~REC_2BYTE_EXTERN_MASK;
}
info |= REC_2BYTE_EXTERN_MASK;
if (mtr) {
mlog_write_ulint(rec - REC_N_OLD_EXTRA_BYTES - 2 * (i + 1),
......@@ -571,7 +566,7 @@ rec_set_nth_field_extern_bit_old(
}
/***************************************************************
Sets the value of the ith field extern storage bit of a new-style record. */
Sets the ith field extern storage bit of a new-style record. */
void
rec_set_nth_field_extern_bit_new(
......@@ -579,7 +574,6 @@ rec_set_nth_field_extern_bit_new(
rec_t* rec, /* in: record */
dict_index_t* index, /* in: record descriptor */
ulint ith, /* in: ith field */
ibool val, /* in: value to set */
mtr_t* mtr) /* in: mtr holding an X-latch to the page
where rec is, or NULL; in the NULL case
we do not write to log about the change */
......@@ -632,11 +626,11 @@ rec_set_nth_field_extern_bit_new(
ulint len = lens[1];
if (len & 0x80) { /* 1exxxxxx: 2-byte length */
if (i == ith) {
if (!val == !(len & 0x40)) {
if (len & 0x40) {
return; /* no change */
}
/* toggle the extern bit */
len ^= 0x40;
len |= 0x40;
if (mtr) {
mlog_write_ulint(lens + 1, len,
MLOG_1BYTE, mtr);
......@@ -677,12 +671,11 @@ rec_set_field_extern_bits(
if (UNIV_LIKELY(index->table->comp)) {
for (i = 0; i < n_fields; i++) {
rec_set_nth_field_extern_bit_new(rec, index, vec[i],
TRUE, mtr);
mtr);
}
} else {
for (i = 0; i < n_fields; i++) {
rec_set_nth_field_extern_bit_old(rec, vec[i],
TRUE, mtr);
rec_set_nth_field_extern_bit_old(rec, vec[i], mtr);
}
}
}
......@@ -745,7 +738,7 @@ rec_convert_dtuple_to_rec_old(
rec_set_n_fields_old(rec, n_fields);
/* Set the info bits of the record */
rec_set_info_bits(rec, FALSE,
rec_set_info_bits_old(rec,
dtuple_get_info_bits(dtuple) & REC_INFO_BITS_MASK);
/* Store the data and the offsets */
......@@ -835,8 +828,6 @@ rec_convert_dtuple_to_rec_new(
ulint fixed_len;
ulint null_mask = 1;
const ulint n_fields = dtuple_get_n_fields(dtuple);
const ulint status = dtuple_get_info_bits(dtuple)
& REC_NEW_STATUS_MASK;
ut_ad(index->table->comp);
ut_ad(n_fields > 0);
......@@ -847,7 +838,8 @@ rec_convert_dtuple_to_rec_new(
UNIV_PREFETCH_RW(rec - REC_N_NEW_EXTRA_BYTES - n_fields);
UNIV_PREFETCH_RW(rec);
switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
switch (UNIV_EXPECT(dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK,
REC_STATUS_ORDINARY)) {
case REC_STATUS_ORDINARY:
ut_ad(n_fields <= dict_index_get_n_fields(index));
n_node_ptr_field = ULINT_UNDEFINED;
......@@ -862,7 +854,7 @@ rec_convert_dtuple_to_rec_new(
n_node_ptr_field = ULINT_UNDEFINED;
goto init;
default:
ut_a(0);
ut_error;
return(0);
}
......@@ -912,10 +904,8 @@ init:
memset (lens + 1, 0, nulls - lens);
/* Set the info bits of the record */
rec_set_status(rec, status);
rec_set_info_bits(rec, TRUE,
dtuple_get_info_bits(dtuple) & REC_INFO_BITS_MASK);
rec_set_info_and_status_bits(rec, NULL,
dtuple_get_info_bits(dtuple));
/* Store the data and the offsets */
......@@ -928,6 +918,7 @@ init:
ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
ut_ad(len == 4);
memcpy(end, dfield_get_data(field), len);
end += 4;
break;
}
fixed_len = dict_index_get_nth_field(index, i)->fixed_len;
......
......@@ -2409,7 +2409,7 @@ row_ins_step(
goto same_trx;
}
trx_write_trx_id(node->trx_id_buf, trx->id);
trx_write_trx_id(node->trx_id_buf, NULL, trx->id);
err = lock_table(0, node->table, LOCK_IX, thr);
......
......@@ -67,9 +67,10 @@ is slower than the specialized inline functions. */
void
row_set_rec_sys_field(
/*==================*/
/* out: value of the field */
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
rec_t* rec, /* in/out: record */
page_zip_des_t* page_zip,/* in/out: compressed page with at least
10 or 11 bytes available, or NULL */
dict_index_t* index, /* in: clustered index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint val) /* in: value to set */
......@@ -87,11 +88,11 @@ row_set_rec_sys_field(
if (type == DATA_TRX_ID) {
trx_write_trx_id(field, val);
trx_write_trx_id(field, page_zip/* 10 bytes */, val);
} else {
ut_ad(type == DATA_ROLL_PTR);
trx_write_roll_ptr(field, val);
trx_write_roll_ptr(field, page_zip/* 11 bytes */, val);
}
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -807,7 +807,7 @@ trx_undo_update_rec_get_update(
upd_field = upd_get_nth_field(update, n_fields);
buf = mem_heap_alloc(heap, DATA_TRX_ID_LEN);
trx_write_trx_id(buf, trx_id);
trx_write_trx_id(buf, NULL, trx_id);
upd_field_set_field_no(upd_field,
dict_index_get_sys_col_pos(index, DATA_TRX_ID),
......@@ -816,7 +816,7 @@ trx_undo_update_rec_get_update(
upd_field = upd_get_nth_field(update, n_fields + 1);
buf = mem_heap_alloc(heap, DATA_ROLL_PTR_LEN);
trx_write_roll_ptr(buf, roll_ptr);
trx_write_roll_ptr(buf, NULL, roll_ptr);
upd_field_set_field_no(upd_field,
dict_index_get_sys_col_pos(index, DATA_ROLL_PTR),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment