~drizzle-trunk/drizzle/development

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
/*****************************************************************************

Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA

*****************************************************************************/

/******************************************************
Compressed page interface

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"
#include "buf0types.h"
#include "dict0types.h"
#include "mem0mem.h"

/**************************************************************************
Determine the size of a compressed page in bytes. */
UNIV_INLINE
ulint
page_zip_get_size(
/*==============*/
						/* out: size in bytes */
	const page_zip_des_t*	page_zip)	/* in: compressed page */
	__attribute__((nonnull, pure));
/**************************************************************************
Set the size of a compressed page in bytes. */
UNIV_INLINE
void
page_zip_set_size(
/*==============*/
	page_zip_des_t*	page_zip,	/* in/out: compressed page */
	ulint		size);		/* in: size in bytes */

/**************************************************************************
Determine if a record is so big that it needs to be stored externally. */
UNIV_INLINE
ibool
page_zip_rec_needs_ext(
/*===================*/
				/* out: FALSE if the entire record
				can be stored locally on the page */
	ulint	rec_size,	/* in: length of the record in bytes */
	ulint	comp,		/* in: nonzero=compact format */
	ulint	n_fields,	/* in: number of fields in the record;
				ignored if zip_size == 0 */
	ulint	zip_size)	/* in: compressed page size in bytes, or 0 */
	__attribute__((__const__));

/**************************************************************************
Determine the guaranteed free space on an empty page. */
UNIV_INTERN
ulint
page_zip_empty_size(
/*================*/
				/* out: minimum payload size on the page */
	ulint	n_fields,	/* in: number of columns in the index */
	ulint	zip_size)	/* in: compressed page size in bytes */
	__attribute__((const));

/**************************************************************************
Initialize a compressed page descriptor. */
UNIV_INLINE
void
page_zip_des_init(
/*==============*/
	page_zip_des_t*	page_zip);	/* in/out: compressed page
					descriptor */

/**************************************************************************
Configure the zlib allocator to use the given memory heap. */
UNIV_INTERN
void
page_zip_set_alloc(
/*===============*/
	void*		stream,		/* in/out: zlib stream */
	mem_heap_t*	heap);		/* in: memory heap to use */

/**************************************************************************
Compress a page. */
UNIV_INTERN
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,/* in: size; out: data, n_blobs,
				m_start, m_end, m_nonempty */
	const page_t*	page,	/* in: uncompressed page */
	dict_index_t*	index,	/* in: index of the B-tree node */
	mtr_t*		mtr)	/* in: mini-transaction, or NULL */
	__attribute__((nonnull(1,2,3)));

/**************************************************************************
Decompress a page.  This function should tolerate errors on the compressed
page.  Instead of letting assertions fail, it will return FALSE if an
inconsistency is detected. */
UNIV_INTERN
ibool
page_zip_decompress(
/*================*/
				/* out: TRUE on success, FALSE on failure */
	page_zip_des_t*	page_zip,/* in: data, ssize;
				out: m_start, m_end, m_nonempty, n_blobs */
	page_t*		page)	/* out: uncompressed page, may be trashed */
	__attribute__((nonnull));

#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 */
#endif /* UNIV_DEBUG */

#ifdef UNIV_ZIP_DEBUG
/**************************************************************************
Check that the compressed and decompressed pages match. */
UNIV_INTERN
ibool
page_zip_validate_low(
/*==================*/
					/* out: TRUE if valid, FALSE if not */
	const page_zip_des_t*	page_zip,/* in: compressed page */
	const page_t*		page,	/* in: uncompressed page */
	ibool			sloppy)	/* in: FALSE=strict,
					TRUE=ignore the MIN_REC_FLAG */
	__attribute__((nonnull));
/**************************************************************************
Check that the compressed and decompressed pages match. */
UNIV_INTERN
ibool
page_zip_validate(
/*==============*/
	const page_zip_des_t*	page_zip,/* in: compressed page */
	const page_t*		page)	/* in: uncompressed page */
	__attribute__((nonnull));
#endif /* UNIV_ZIP_DEBUG */

/**************************************************************************
Determine how big record can be inserted without recompressing the page. */
UNIV_INLINE
lint
page_zip_max_ins_size(
/*==================*/
					/* out: a positive number
					indicating the maximum size of
					a record whose insertion is
					guaranteed to succeed, or
					zero or negative */
	const page_zip_des_t*	page_zip,/* in: compressed page */
	ibool			is_clust)/* in: TRUE if clustered index */
	__attribute__((nonnull, pure));

/**************************************************************************
Determine if enough space is available in the modification log. */
UNIV_INLINE
ibool
page_zip_available(
/*===============*/
					/* out: TRUE if page_zip_write_rec()
					will succeed */
	const page_zip_des_t*	page_zip,/* in: compressed page */
	ibool			is_clust,/* in: TRUE if clustered index */
	ulint			length,	/* in: combined size of the record */
	ulint			create)	/* in: nonzero=add the record to
					the heap */
	__attribute__((nonnull, pure));

/**************************************************************************
Write an entire record on the compressed page.  The data must already
have been written to the uncompressed page. */
UNIV_INTERN
void
page_zip_write_rec(
/*===============*/
	page_zip_des_t*	page_zip,/* in/out: compressed page */
	const byte*	rec,	/* in: record being written */
	dict_index_t*	index,	/* in: the index the record belongs to */
	const ulint*	offsets,/* in: rec_get_offsets(rec, index) */
	ulint		create)	/* in: nonzero=insert, zero=update */
	__attribute__((nonnull));

/***************************************************************
Parses a log record of writing a BLOB pointer of a record. */
UNIV_INTERN
byte*
page_zip_parse_write_blob_ptr(
/*==========================*/
				/* out: end of log record or NULL */
	byte*		ptr,	/* in: redo log buffer */
	byte*		end_ptr,/* in: redo log buffer end */
	page_t*		page,	/* in/out: uncompressed page */
	page_zip_des_t*	page_zip);/* in/out: compressed page */

/**************************************************************************
Write a BLOB pointer of a record on the leaf page of a clustered index.
The information must already have been updated on the uncompressed page. */
UNIV_INTERN
void
page_zip_write_blob_ptr(
/*====================*/
	page_zip_des_t*	page_zip,/* in/out: compressed page */
	const byte*	rec,	/* in/out: record whose data is being
				written */
	dict_index_t*	index,	/* in: index of the page */
	const ulint*	offsets,/* in: rec_get_offsets(rec, index) */
	ulint		n,	/* in: column index */
	mtr_t*		mtr)	/* in: mini-transaction handle,
				or NULL if no logging is needed */
	__attribute__((nonnull(1,2,3,4)));

/***************************************************************
Parses a log record of writing the node pointer of a record. */
UNIV_INTERN
byte*
page_zip_parse_write_node_ptr(
/*==========================*/
				/* out: end of log record or NULL */
	byte*		ptr,	/* in: redo log buffer */
	byte*		end_ptr,/* in: redo log buffer end */
	page_t*		page,	/* in/out: uncompressed page */
	page_zip_des_t*	page_zip);/* in/out: compressed page */

/**************************************************************************
Write the node pointer of a record on a non-leaf compressed page. */
UNIV_INTERN
void
page_zip_write_node_ptr(
/*====================*/
	page_zip_des_t*	page_zip,/* in/out: compressed page */
	byte*		rec,	/* in/out: record */
	ulint		size,	/* in: data size of rec */
	ulint		ptr,	/* in: node pointer */
	mtr_t*		mtr)	/* in: mini-transaction, or NULL */
	__attribute__((nonnull(1,2)));

/**************************************************************************
Write the trx_id and roll_ptr of a record on a B-tree leaf node page. */
UNIV_INTERN
void
page_zip_write_trx_id_and_roll_ptr(
/*===============================*/
	page_zip_des_t*	page_zip,/* in/out: compressed page */
	byte*		rec,	/* in/out: record */
	const ulint*	offsets,/* in: rec_get_offsets(rec, index) */
	ulint		trx_id_col,/* in: column number of TRX_ID in rec */
	dulint		trx_id,	/* in: transaction identifier */
	dulint		roll_ptr)/* in: roll_ptr */
	__attribute__((nonnull));

/**************************************************************************
Insert a record to the dense page directory. */
UNIV_INTERN
void
page_zip_dir_insert(
/*================*/
	page_zip_des_t*	page_zip,/* in/out: compressed page */
	const byte*	prev_rec,/* in: record after which to insert */
	const byte*	free_rec,/* in: record from which rec was
				allocated, or NULL */
	byte*		rec);	/* in: record to insert */

/***************************************************************
Parses a log record of writing to the header of a page. */
UNIV_INTERN
byte*
page_zip_parse_write_header(
/*========================*/
				/* out: end of log record or NULL */
	byte*		ptr,	/* in: redo log buffer */
	byte*		end_ptr,/* in: redo log buffer end */
	page_t*		page,	/* in/out: uncompressed page */
	page_zip_des_t*	page_zip);/* in/out: compressed page */

/**************************************************************************
Write data to the uncompressed header portion of a page.  The data must
already have been written to the uncompressed page.
However, the data portion of the uncompressed page may differ from
the compressed page when a record is being inserted in
page_cur_insert_rec_low(). */
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 */
	mtr_t*		mtr)	/* in: mini-transaction, or NULL */
	__attribute__((nonnull(1,2)));

/**************************************************************************
Reorganize and compress a page.  This is a low-level operation for
compressed pages, to be used when page_zip_compress() fails.
On success, a redo log entry MLOG_ZIP_PAGE_COMPRESS will be written.
The function btr_page_reorganize() should be preferred whenever possible.
IMPORTANT: if page_zip_reorganize() is invoked on a leaf page of a
non-clustered index, the caller must update the insert buffer free
bits in the same mini-transaction in such a way that the modification
will be redo-logged. */
UNIV_INTERN
ibool
page_zip_reorganize(
/*================*/
				/* out: TRUE on success, FALSE on failure;
				page and page_zip will be left intact
				on failure. */
	buf_block_t*	block,	/* in/out: page with compressed page;
				on the compressed page, in: size;
				out: data, n_blobs,
				m_start, m_end, m_nonempty */
	dict_index_t*	index,	/* in: index of the B-tree node */
	mtr_t*		mtr)	/* in: mini-transaction */
	__attribute__((nonnull));
/**************************************************************************
Copy the records of a page byte for byte.  Do not copy the page header
or trailer, except those B-tree header fields that are directly
related to the storage of records.  Also copy PAGE_MAX_TRX_ID.
NOTE: The caller must update the lock table and the adaptive hash index. */
UNIV_INTERN
void
page_zip_copy_recs(
/*===============*/
	page_zip_des_t*		page_zip,	/* out: copy of src_zip
						(n_blobs, m_start, m_end,
						m_nonempty, data[0..size-1]) */
	page_t*			page,		/* out: copy of src */
	const page_zip_des_t*	src_zip,	/* in: compressed page */
	const page_t*		src,		/* in: page */
	dict_index_t*		index,		/* in: index of the B-tree */
	mtr_t*			mtr)		/* in: mini-transaction */
	__attribute__((nonnull(1,2,3,4)));

/**************************************************************************
Parses a log record of compressing an index page. */
UNIV_INTERN
byte*
page_zip_parse_compress(
/*====================*/
				/* out: end of log record or NULL */
	byte*		ptr,	/* in: buffer */
	byte*		end_ptr,/* in: buffer end */
	page_t*		page,	/* out: uncompressed page */
	page_zip_des_t*	page_zip)/* out: compressed page */
	__attribute__((nonnull(1,2)));

/**************************************************************************
Calculate the compressed page checksum. */
UNIV_INTERN
ulint
page_zip_calc_checksum(
/*===================*/
                                /* out: page checksum */
        const void*     data,   /* in: compressed page */
        ulint           size)   /* in: size of compressed page */
	__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 */