1
/*****************************************************************************
3
Copyright (C) 2005, 2009, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/**************************************************//**
20
@file include/page0zip.h
21
Compressed page interface
23
Created June 2005 by Marko Makela
24
*******************************************************/
30
#ifdef UNIV_MATERIALIZE
35
#include "mtr0types.h"
36
#include "page0types.h"
37
#include "buf0types.h"
38
#include "dict0types.h"
39
#include "trx0types.h"
42
/**********************************************************************//**
43
Determine the size of a compressed page in bytes.
44
@return size in bytes */
49
const page_zip_des_t* page_zip) /*!< in: compressed page */
50
__attribute__((nonnull, pure));
51
/**********************************************************************//**
52
Set the size of a compressed page in bytes. */
57
page_zip_des_t* page_zip, /*!< in/out: compressed page */
58
ulint size); /*!< in: size in bytes */
60
#ifndef UNIV_HOTBACKUP
61
/**********************************************************************//**
62
Determine if a record is so big that it needs to be stored externally.
63
@return FALSE if the entire record can be stored locally on the page */
66
page_zip_rec_needs_ext(
67
/*===================*/
68
ulint rec_size, /*!< in: length of the record in bytes */
69
ulint comp, /*!< in: nonzero=compact format */
70
ulint n_fields, /*!< in: number of fields in the record;
71
ignored if zip_size == 0 */
72
ulint zip_size) /*!< in: compressed page size in bytes, or 0 */
73
__attribute__((const));
75
/**********************************************************************//**
76
Determine the guaranteed free space on an empty page.
77
@return minimum payload size on the page */
82
ulint n_fields, /*!< in: number of columns in the index */
83
ulint zip_size) /*!< in: compressed page size in bytes */
84
__attribute__((const));
85
#endif /* !UNIV_HOTBACKUP */
87
/**********************************************************************//**
88
Initialize a compressed page descriptor. */
93
page_zip_des_t* page_zip); /*!< in/out: compressed page
96
/**********************************************************************//**
97
Configure the zlib allocator to use the given memory heap. */
102
void* stream, /*!< in/out: zlib stream */
103
mem_heap_t* heap); /*!< in: memory heap to use */
105
/**********************************************************************//**
107
@return TRUE on success, FALSE on failure; page_zip will be left
108
intact on failure. */
113
page_zip_des_t* page_zip,/*!< in: size; out: data, n_blobs,
114
m_start, m_end, m_nonempty */
115
const page_t* page, /*!< in: uncompressed page */
116
dict_index_t* index, /*!< in: index of the B-tree node */
117
mtr_t* mtr) /*!< in: mini-transaction, or NULL */
118
__attribute__((nonnull(1,2,3)));
120
/**********************************************************************//**
121
Decompress a page. This function should tolerate errors on the compressed
122
page. Instead of letting assertions fail, it will return FALSE if an
123
inconsistency is detected.
124
@return TRUE on success, FALSE on failure */
129
page_zip_des_t* page_zip,/*!< in: data, ssize;
130
out: m_start, m_end, m_nonempty, n_blobs */
131
page_t* page, /*!< out: uncompressed page, may be trashed */
132
ibool all) /*!< in: TRUE=decompress the whole page;
133
FALSE=verify but do not copy some
134
page header fields that should not change
135
after page creation */
136
__attribute__((nonnull(1,2)));
139
/**********************************************************************//**
140
Validate a compressed page descriptor.
141
@return TRUE if ok */
144
page_zip_simple_validate(
145
/*=====================*/
146
const page_zip_des_t* page_zip); /*!< in: compressed page
148
#endif /* UNIV_DEBUG */
150
#ifdef UNIV_ZIP_DEBUG
151
/**********************************************************************//**
152
Check that the compressed and decompressed pages match.
153
@return TRUE if valid, FALSE if not */
156
page_zip_validate_low(
157
/*==================*/
158
const page_zip_des_t* page_zip,/*!< in: compressed page */
159
const page_t* page, /*!< in: uncompressed page */
160
ibool sloppy) /*!< in: FALSE=strict,
161
TRUE=ignore the MIN_REC_FLAG */
162
__attribute__((nonnull));
163
/**********************************************************************//**
164
Check that the compressed and decompressed pages match. */
169
const page_zip_des_t* page_zip,/*!< in: compressed page */
170
const page_t* page) /*!< in: uncompressed page */
171
__attribute__((nonnull));
172
#endif /* UNIV_ZIP_DEBUG */
174
/**********************************************************************//**
175
Determine how big record can be inserted without recompressing the page.
176
@return a positive number indicating the maximum size of a record
177
whose insertion is guaranteed to succeed, or zero or negative */
180
page_zip_max_ins_size(
181
/*==================*/
182
const page_zip_des_t* page_zip,/*!< in: compressed page */
183
ibool is_clust)/*!< in: TRUE if clustered index */
184
__attribute__((nonnull, pure));
186
/**********************************************************************//**
187
Determine if enough space is available in the modification log.
188
@return TRUE if page_zip_write_rec() will succeed */
193
const page_zip_des_t* page_zip,/*!< in: compressed page */
194
ibool is_clust,/*!< in: TRUE if clustered index */
195
ulint length, /*!< in: combined size of the record */
196
ulint create) /*!< in: nonzero=add the record to
198
__attribute__((nonnull, pure));
200
/**********************************************************************//**
201
Write data to the uncompressed header portion of a page. The data must
202
already have been written to the uncompressed page. */
205
page_zip_write_header(
206
/*==================*/
207
page_zip_des_t* page_zip,/*!< in/out: compressed page */
208
const byte* str, /*!< in: address on the uncompressed page */
209
ulint length, /*!< in: length of the data */
210
mtr_t* mtr) /*!< in: mini-transaction, or NULL */
211
__attribute__((nonnull(1,2)));
213
/**********************************************************************//**
214
Write an entire record on the compressed page. The data must already
215
have been written to the uncompressed page. */
220
page_zip_des_t* page_zip,/*!< in/out: compressed page */
221
const byte* rec, /*!< in: record being written */
222
dict_index_t* index, /*!< in: the index the record belongs to */
223
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
224
ulint create) /*!< in: nonzero=insert, zero=update */
225
__attribute__((nonnull));
227
/***********************************************************//**
228
Parses a log record of writing a BLOB pointer of a record.
229
@return end of log record or NULL */
232
page_zip_parse_write_blob_ptr(
233
/*==========================*/
234
byte* ptr, /*!< in: redo log buffer */
235
byte* end_ptr,/*!< in: redo log buffer end */
236
page_t* page, /*!< in/out: uncompressed page */
237
page_zip_des_t* page_zip);/*!< in/out: compressed page */
239
/**********************************************************************//**
240
Write a BLOB pointer of a record on the leaf page of a clustered index.
241
The information must already have been updated on the uncompressed page. */
244
page_zip_write_blob_ptr(
245
/*====================*/
246
page_zip_des_t* page_zip,/*!< in/out: compressed page */
247
const byte* rec, /*!< in/out: record whose data is being
249
dict_index_t* index, /*!< in: index of the page */
250
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
251
ulint n, /*!< in: column index */
252
mtr_t* mtr) /*!< in: mini-transaction handle,
253
or NULL if no logging is needed */
254
__attribute__((nonnull(1,2,3,4)));
256
/***********************************************************//**
257
Parses a log record of writing the node pointer of a record.
258
@return end of log record or NULL */
261
page_zip_parse_write_node_ptr(
262
/*==========================*/
263
byte* ptr, /*!< in: redo log buffer */
264
byte* end_ptr,/*!< in: redo log buffer end */
265
page_t* page, /*!< in/out: uncompressed page */
266
page_zip_des_t* page_zip);/*!< in/out: compressed page */
268
/**********************************************************************//**
269
Write the node pointer of a record on a non-leaf compressed page. */
272
page_zip_write_node_ptr(
273
/*====================*/
274
page_zip_des_t* page_zip,/*!< in/out: compressed page */
275
byte* rec, /*!< in/out: record */
276
ulint size, /*!< in: data size of rec */
277
ulint ptr, /*!< in: node pointer */
278
mtr_t* mtr) /*!< in: mini-transaction, or NULL */
279
__attribute__((nonnull(1,2)));
281
/**********************************************************************//**
282
Write the trx_id and roll_ptr of a record on a B-tree leaf node page. */
285
page_zip_write_trx_id_and_roll_ptr(
286
/*===============================*/
287
page_zip_des_t* page_zip,/*!< in/out: compressed page */
288
byte* rec, /*!< in/out: record */
289
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
290
ulint trx_id_col,/*!< in: column number of TRX_ID in rec */
291
trx_id_t trx_id, /*!< in: transaction identifier */
292
roll_ptr_t roll_ptr)/*!< in: roll_ptr */
293
__attribute__((nonnull));
296
/**********************************************************************//**
297
Insert a record to the dense page directory. */
302
page_zip_des_t* page_zip,/*!< in/out: compressed page */
303
const byte* prev_rec,/*!< in: record after which to insert */
304
const byte* free_rec,/*!< in: record from which rec was
305
allocated, or NULL */
306
byte* rec); /*!< in: record to insert */
310
page_zip_parse_write_header(
311
/*========================*/
312
byte* ptr, /*!< in: redo log buffer */
313
byte* end_ptr,/*!< in: redo log buffer end */
314
page_t* page, /*!< in/out: uncompressed page */
315
page_zip_des_t* page_zip);/*!< in/out: compressed page */
318
/**********************************************************************//**
319
Reorganize and compress a page. This is a low-level operation for
320
compressed pages, to be used when page_zip_compress() fails.
321
On success, a redo log entry MLOG_ZIP_PAGE_COMPRESS will be written.
322
The function btr_page_reorganize() should be preferred whenever possible.
323
IMPORTANT: if page_zip_reorganize() is invoked on a leaf page of a
324
non-clustered index, the caller must update the insert buffer free
325
bits in the same mini-transaction in such a way that the modification
327
@return TRUE on success, FALSE on failure; page_zip will be left
328
intact on failure, but page will be overwritten. */
333
buf_block_t* block, /*!< in/out: page with compressed page;
334
on the compressed page, in: size;
336
m_start, m_end, m_nonempty */
337
dict_index_t* index, /*!< in: index of the B-tree node */
338
mtr_t* mtr) /*!< in: mini-transaction */
339
__attribute__((nonnull));
340
#ifndef UNIV_HOTBACKUP
341
/**********************************************************************//**
342
Copy the records of a page byte for byte. Do not copy the page header
343
or trailer, except those B-tree header fields that are directly
344
related to the storage of records. Also copy PAGE_MAX_TRX_ID.
345
NOTE: The caller must update the lock table and the adaptive hash index. */
350
page_zip_des_t* page_zip, /*!< out: copy of src_zip
351
(n_blobs, m_start, m_end,
352
m_nonempty, data[0..size-1]) */
353
page_t* page, /*!< out: copy of src */
354
const page_zip_des_t* src_zip, /*!< in: compressed page */
355
const page_t* src, /*!< in: page */
356
dict_index_t* index, /*!< in: index of the B-tree */
357
mtr_t* mtr) /*!< in: mini-transaction */
358
__attribute__((nonnull(1,2,3,4)));
359
#endif /* !UNIV_HOTBACKUP */
361
/**********************************************************************//**
362
Parses a log record of compressing an index page.
363
@return end of log record or NULL */
366
page_zip_parse_compress(
367
/*====================*/
368
byte* ptr, /*!< in: buffer */
369
byte* end_ptr,/*!< in: buffer end */
370
page_t* page, /*!< out: uncompressed page */
371
page_zip_des_t* page_zip)/*!< out: compressed page */
372
__attribute__((nonnull(1,2)));
374
/**********************************************************************//**
375
Calculate the compressed page checksum.
376
@return page checksum */
379
page_zip_calc_checksum(
380
/*===================*/
381
const void* data, /*!< in: compressed page */
382
ulint size) /*!< in: size of compressed page */
383
__attribute__((nonnull));
385
#ifndef UNIV_HOTBACKUP
386
/** Check if a pointer to an uncompressed page matches a compressed page.
387
@param ptr pointer to an uncompressed page frame
388
@param page_zip compressed page descriptor
389
@return TRUE if ptr and page_zip refer to the same block */
390
# define PAGE_ZIP_MATCH(ptr, page_zip) \
391
(buf_frame_get_page_zip(ptr) == (page_zip))
392
#else /* !UNIV_HOTBACKUP */
393
/** Check if a pointer to an uncompressed page matches a compressed page.
394
@param ptr pointer to an uncompressed page frame
395
@param page_zip compressed page descriptor
396
@return TRUE if ptr and page_zip refer to the same block */
397
# define PAGE_ZIP_MATCH(ptr, page_zip) \
398
(page_align(ptr) + UNIV_PAGE_SIZE == (page_zip)->data)
399
#endif /* !UNIV_HOTBACKUP */
401
#ifdef UNIV_MATERIALIZE
403
# define UNIV_INLINE UNIV_INLINE_ORIGINAL
407
# include "page0zip.ic"
410
#endif /* page0zip_h */