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., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
17
*****************************************************************************/
19
/**************************************************//**
20
@file include/page0zip.h
21
Compressed page interface
23
Created June 2005 by Marko Makela
24
*******************************************************/
29
#ifdef UNIV_MATERIALIZE
34
#include "mtr0types.h"
35
#include "page0types.h"
36
#include "buf0types.h"
37
#include "dict0types.h"
38
#include "trx0types.h"
41
/**********************************************************************//**
42
Determine the size of a compressed page in bytes.
43
@return size in bytes */
48
const page_zip_des_t* page_zip) /*!< in: compressed page */
49
__attribute__((nonnull, pure));
50
/**********************************************************************//**
51
Set the size of a compressed page in bytes. */
56
page_zip_des_t* page_zip, /*!< in/out: compressed page */
57
ulint size); /*!< in: size in bytes */
59
#ifndef UNIV_HOTBACKUP
60
/**********************************************************************//**
61
Determine if a record is so big that it needs to be stored externally.
62
@return FALSE if the entire record can be stored locally on the page */
65
page_zip_rec_needs_ext(
66
/*===================*/
67
ulint rec_size, /*!< in: length of the record in bytes */
68
ulint comp, /*!< in: nonzero=compact format */
69
ulint n_fields, /*!< in: number of fields in the record;
70
ignored if zip_size == 0 */
71
ulint zip_size) /*!< in: compressed page size in bytes, or 0 */
72
__attribute__((const));
74
/**********************************************************************//**
75
Determine the guaranteed free space on an empty page.
76
@return minimum payload size on the page */
81
ulint n_fields, /*!< in: number of columns in the index */
82
ulint zip_size) /*!< in: compressed page size in bytes */
83
__attribute__((const));
84
#endif /* !UNIV_HOTBACKUP */
86
/**********************************************************************//**
87
Initialize a compressed page descriptor. */
92
page_zip_des_t* page_zip); /*!< in/out: compressed page
95
/**********************************************************************//**
96
Configure the zlib allocator to use the given memory heap. */
101
void* stream, /*!< in/out: zlib stream */
102
mem_heap_t* heap); /*!< in: memory heap to use */
104
/**********************************************************************//**
106
@return TRUE on success, FALSE on failure; page_zip will be left
107
intact on failure. */
112
page_zip_des_t* page_zip,/*!< in: size; out: data, n_blobs,
113
m_start, m_end, m_nonempty */
114
const page_t* page, /*!< in: uncompressed page */
115
dict_index_t* index, /*!< in: index of the B-tree node */
116
mtr_t* mtr) /*!< in: mini-transaction, or NULL */
117
__attribute__((nonnull(1,2,3)));
119
/**********************************************************************//**
120
Decompress a page. This function should tolerate errors on the compressed
121
page. Instead of letting assertions fail, it will return FALSE if an
122
inconsistency is detected.
123
@return TRUE on success, FALSE on failure */
128
page_zip_des_t* page_zip,/*!< in: data, ssize;
129
out: m_start, m_end, m_nonempty, n_blobs */
130
page_t* page, /*!< out: uncompressed page, may be trashed */
131
ibool all) /*!< in: TRUE=decompress the whole page;
132
FALSE=verify but do not copy some
133
page header fields that should not change
134
after page creation */
135
__attribute__((nonnull(1,2)));
138
/**********************************************************************//**
139
Validate a compressed page descriptor.
140
@return TRUE if ok */
143
page_zip_simple_validate(
144
/*=====================*/
145
const page_zip_des_t* page_zip); /*!< in: compressed page
147
#endif /* UNIV_DEBUG */
149
#ifdef UNIV_ZIP_DEBUG
150
/**********************************************************************//**
151
Check that the compressed and decompressed pages match.
152
@return TRUE if valid, FALSE if not */
155
page_zip_validate_low(
156
/*==================*/
157
const page_zip_des_t* page_zip,/*!< in: compressed page */
158
const page_t* page, /*!< in: uncompressed page */
159
ibool sloppy) /*!< in: FALSE=strict,
160
TRUE=ignore the MIN_REC_FLAG */
161
__attribute__((nonnull));
162
/**********************************************************************//**
163
Check that the compressed and decompressed pages match. */
168
const page_zip_des_t* page_zip,/*!< in: compressed page */
169
const page_t* page) /*!< in: uncompressed page */
170
__attribute__((nonnull));
171
#endif /* UNIV_ZIP_DEBUG */
173
/**********************************************************************//**
174
Determine how big record can be inserted without recompressing the page.
175
@return a positive number indicating the maximum size of a record
176
whose insertion is guaranteed to succeed, or zero or negative */
179
page_zip_max_ins_size(
180
/*==================*/
181
const page_zip_des_t* page_zip,/*!< in: compressed page */
182
ibool is_clust)/*!< in: TRUE if clustered index */
183
__attribute__((nonnull, pure));
185
/**********************************************************************//**
186
Determine if enough space is available in the modification log.
187
@return TRUE if page_zip_write_rec() will succeed */
192
const page_zip_des_t* page_zip,/*!< in: compressed page */
193
ibool is_clust,/*!< in: TRUE if clustered index */
194
ulint length, /*!< in: combined size of the record */
195
ulint create) /*!< in: nonzero=add the record to
197
__attribute__((nonnull, pure));
199
/**********************************************************************//**
200
Write data to the uncompressed header portion of a page. The data must
201
already have been written to the uncompressed page. */
204
page_zip_write_header(
205
/*==================*/
206
page_zip_des_t* page_zip,/*!< in/out: compressed page */
207
const byte* str, /*!< in: address on the uncompressed page */
208
ulint length, /*!< in: length of the data */
209
mtr_t* mtr) /*!< in: mini-transaction, or NULL */
210
__attribute__((nonnull(1,2)));
212
/**********************************************************************//**
213
Write an entire record on the compressed page. The data must already
214
have been written to the uncompressed page. */
219
page_zip_des_t* page_zip,/*!< in/out: compressed page */
220
const byte* rec, /*!< in: record being written */
221
dict_index_t* index, /*!< in: the index the record belongs to */
222
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
223
ulint create) /*!< in: nonzero=insert, zero=update */
224
__attribute__((nonnull));
226
/***********************************************************//**
227
Parses a log record of writing a BLOB pointer of a record.
228
@return end of log record or NULL */
231
page_zip_parse_write_blob_ptr(
232
/*==========================*/
233
byte* ptr, /*!< in: redo log buffer */
234
byte* end_ptr,/*!< in: redo log buffer end */
235
page_t* page, /*!< in/out: uncompressed page */
236
page_zip_des_t* page_zip);/*!< in/out: compressed page */
238
/**********************************************************************//**
239
Write a BLOB pointer of a record on the leaf page of a clustered index.
240
The information must already have been updated on the uncompressed page. */
243
page_zip_write_blob_ptr(
244
/*====================*/
245
page_zip_des_t* page_zip,/*!< in/out: compressed page */
246
const byte* rec, /*!< in/out: record whose data is being
248
dict_index_t* index, /*!< in: index of the page */
249
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
250
ulint n, /*!< in: column index */
251
mtr_t* mtr) /*!< in: mini-transaction handle,
252
or NULL if no logging is needed */
253
__attribute__((nonnull(1,2,3,4)));
255
/***********************************************************//**
256
Parses a log record of writing the node pointer of a record.
257
@return end of log record or NULL */
260
page_zip_parse_write_node_ptr(
261
/*==========================*/
262
byte* ptr, /*!< in: redo log buffer */
263
byte* end_ptr,/*!< in: redo log buffer end */
264
page_t* page, /*!< in/out: uncompressed page */
265
page_zip_des_t* page_zip);/*!< in/out: compressed page */
267
/**********************************************************************//**
268
Write the node pointer of a record on a non-leaf compressed page. */
271
page_zip_write_node_ptr(
272
/*====================*/
273
page_zip_des_t* page_zip,/*!< in/out: compressed page */
274
byte* rec, /*!< in/out: record */
275
ulint size, /*!< in: data size of rec */
276
ulint ptr, /*!< in: node pointer */
277
mtr_t* mtr) /*!< in: mini-transaction, or NULL */
278
__attribute__((nonnull(1,2)));
280
/**********************************************************************//**
281
Write the trx_id and roll_ptr of a record on a B-tree leaf node page. */
284
page_zip_write_trx_id_and_roll_ptr(
285
/*===============================*/
286
page_zip_des_t* page_zip,/*!< in/out: compressed page */
287
byte* rec, /*!< in/out: record */
288
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
289
ulint trx_id_col,/*!< in: column number of TRX_ID in rec */
290
trx_id_t trx_id, /*!< in: transaction identifier */
291
roll_ptr_t roll_ptr)/*!< in: roll_ptr */
292
__attribute__((nonnull));
294
/**********************************************************************//**
295
Write the "deleted" flag of a record on a compressed page. The flag must
296
already have been written on the uncompressed page. */
299
page_zip_rec_set_deleted(
300
/*=====================*/
301
page_zip_des_t* page_zip,/*!< in/out: compressed page */
302
const byte* rec, /*!< in: record on the uncompressed page */
303
ulint flag) /*!< in: the deleted flag (nonzero=TRUE) */
304
__attribute__((nonnull));
306
/**********************************************************************//**
307
Write the "owned" flag of a record on a compressed page. The n_owned field
308
must already have been written on the uncompressed page. */
311
page_zip_rec_set_owned(
312
/*===================*/
313
page_zip_des_t* page_zip,/*!< in/out: compressed page */
314
const byte* rec, /*!< in: record on the uncompressed page */
315
ulint flag) /*!< in: the owned flag (nonzero=TRUE) */
316
__attribute__((nonnull));
318
/**********************************************************************//**
319
Insert a record to the dense page directory. */
324
page_zip_des_t* page_zip,/*!< in/out: compressed page */
325
const byte* prev_rec,/*!< in: record after which to insert */
326
const byte* free_rec,/*!< in: record from which rec was
327
allocated, or NULL */
328
byte* rec); /*!< in: record to insert */
330
/**********************************************************************//**
331
Shift the dense page directory and the array of BLOB pointers
332
when a record is deleted. */
337
page_zip_des_t* page_zip,/*!< in/out: compressed page */
338
byte* rec, /*!< in: deleted record */
339
dict_index_t* index, /*!< in: index of rec */
340
const ulint* offsets,/*!< in: rec_get_offsets(rec) */
341
const byte* free) /*!< in: previous start of the free list */
342
__attribute__((nonnull(1,2,3,4)));
344
/**********************************************************************//**
345
Add a slot to the dense page directory. */
348
page_zip_dir_add_slot(
349
/*==================*/
350
page_zip_des_t* page_zip, /*!< in/out: compressed page */
351
ulint is_clustered) /*!< in: nonzero for clustered index,
353
__attribute__((nonnull));
355
/***********************************************************//**
356
Parses a log record of writing to the header of a page.
357
@return end of log record or NULL */
360
page_zip_parse_write_header(
361
/*========================*/
362
byte* ptr, /*!< in: redo log buffer */
363
byte* end_ptr,/*!< in: redo log buffer end */
364
page_t* page, /*!< in/out: uncompressed page */
365
page_zip_des_t* page_zip);/*!< in/out: compressed page */
367
/**********************************************************************//**
368
Write data to the uncompressed header portion of a page. The data must
369
already have been written to the uncompressed page.
370
However, the data portion of the uncompressed page may differ from
371
the compressed page when a record is being inserted in
372
page_cur_insert_rec_low(). */
375
page_zip_write_header(
376
/*==================*/
377
page_zip_des_t* page_zip,/*!< in/out: compressed page */
378
const byte* str, /*!< in: address on the uncompressed page */
379
ulint length, /*!< in: length of the data */
380
mtr_t* mtr) /*!< in: mini-transaction, or NULL */
381
__attribute__((nonnull(1,2)));
383
/**********************************************************************//**
384
Reorganize and compress a page. This is a low-level operation for
385
compressed pages, to be used when page_zip_compress() fails.
386
On success, a redo log entry MLOG_ZIP_PAGE_COMPRESS will be written.
387
The function btr_page_reorganize() should be preferred whenever possible.
388
IMPORTANT: if page_zip_reorganize() is invoked on a leaf page of a
389
non-clustered index, the caller must update the insert buffer free
390
bits in the same mini-transaction in such a way that the modification
392
@return TRUE on success, FALSE on failure; page_zip will be left
393
intact on failure, but page will be overwritten. */
398
buf_block_t* block, /*!< in/out: page with compressed page;
399
on the compressed page, in: size;
401
m_start, m_end, m_nonempty */
402
dict_index_t* index, /*!< in: index of the B-tree node */
403
mtr_t* mtr) /*!< in: mini-transaction */
404
__attribute__((nonnull));
405
#ifndef UNIV_HOTBACKUP
406
/**********************************************************************//**
407
Copy the records of a page byte for byte. Do not copy the page header
408
or trailer, except those B-tree header fields that are directly
409
related to the storage of records. Also copy PAGE_MAX_TRX_ID.
410
NOTE: The caller must update the lock table and the adaptive hash index. */
415
page_zip_des_t* page_zip, /*!< out: copy of src_zip
416
(n_blobs, m_start, m_end,
417
m_nonempty, data[0..size-1]) */
418
page_t* page, /*!< out: copy of src */
419
const page_zip_des_t* src_zip, /*!< in: compressed page */
420
const page_t* src, /*!< in: page */
421
dict_index_t* index, /*!< in: index of the B-tree */
422
mtr_t* mtr) /*!< in: mini-transaction */
423
__attribute__((nonnull(1,2,3,4)));
424
#endif /* !UNIV_HOTBACKUP */
426
/**********************************************************************//**
427
Parses a log record of compressing an index page.
428
@return end of log record or NULL */
431
page_zip_parse_compress(
432
/*====================*/
433
byte* ptr, /*!< in: buffer */
434
byte* end_ptr,/*!< in: buffer end */
435
page_t* page, /*!< out: uncompressed page */
436
page_zip_des_t* page_zip)/*!< out: compressed page */
437
__attribute__((nonnull(1,2)));
439
/**********************************************************************//**
440
Calculate the compressed page checksum.
441
@return page checksum */
444
page_zip_calc_checksum(
445
/*===================*/
446
const void* data, /*!< in: compressed page */
447
ulint size) /*!< in: size of compressed page */
448
__attribute__((nonnull));
450
#ifndef UNIV_HOTBACKUP
451
/** Check if a pointer to an uncompressed page matches a compressed page.
452
@param ptr pointer to an uncompressed page frame
453
@param page_zip compressed page descriptor
454
@return TRUE if ptr and page_zip refer to the same block */
455
# define PAGE_ZIP_MATCH(ptr, page_zip) \
456
(buf_frame_get_page_zip(ptr) == (page_zip))
457
#else /* !UNIV_HOTBACKUP */
458
/** Check if a pointer to an uncompressed page matches a compressed page.
459
@param ptr pointer to an uncompressed page frame
460
@param page_zip compressed page descriptor
461
@return TRUE if ptr and page_zip refer to the same block */
462
# define PAGE_ZIP_MATCH(ptr, page_zip) \
463
(page_align(ptr) + UNIV_PAGE_SIZE == (page_zip)->data)
464
#endif /* !UNIV_HOTBACKUP */
466
#ifdef UNIV_MATERIALIZE
468
# define UNIV_INLINE UNIV_INLINE_ORIGINAL
472
# include "page0zip.ic"
475
#endif /* page0zip_h */