page0page.h 35.9 KB
Newer Older
vasil's avatar
vasil committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*****************************************************************************

Copyright (c) 1994, 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

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

osku's avatar
osku committed
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
/******************************************************
Index page routines

Created 2/2/1994 Heikki Tuuri
*******************************************************/

#ifndef page0page_h
#define page0page_h

#include "univ.i"

#include "page0types.h"
#include "fil0fil.h"
#include "buf0buf.h"
#include "data0data.h"
#include "dict0dict.h"
#include "rem0rec.h"
#include "fsp0fsp.h"
#include "mtr0mtr.h"

#ifdef UNIV_MATERIALIZE
#undef UNIV_INLINE
#define UNIV_INLINE
#endif

/*			PAGE HEADER
			===========

Index page header starts at the first offset left free by the FIL-module */

typedef	byte		page_header_t;

#define	PAGE_HEADER	FSEG_PAGE_DATA	/* index page header starts at this
				offset */
/*-----------------------------*/
#define PAGE_N_DIR_SLOTS 0	/* number of slots in page directory */
#define	PAGE_HEAP_TOP	 2	/* pointer to record heap top */
#define	PAGE_N_HEAP	 4	/* number of records in the heap,
				bit 15=flag: new-style compact page format */
#define	PAGE_FREE	 6	/* pointer to start of page free record list */
#define	PAGE_GARBAGE	 8	/* number of bytes in deleted records */
#define	PAGE_LAST_INSERT 10	/* pointer to the last inserted record, or
				NULL if this info has been reset by a delete,
				for example */
#define	PAGE_DIRECTION	 12	/* last insert direction: PAGE_LEFT, ... */
#define	PAGE_N_DIRECTION 14	/* number of consecutive inserts to the same
				direction */
#define	PAGE_N_RECS	 16	/* number of user records on the page */
#define PAGE_MAX_TRX_ID	 18	/* highest id of a trx which may have modified
				a record on the page; a dulint; defined only
				in secondary indexes; specifically, not in an
				ibuf tree; NOTE: this may be modified only
				when the thread has an x-latch to the page,
				and ALSO an x-latch to btr_search_latch
				if there is a hash index to the page! */
#define PAGE_HEADER_PRIV_END 26	/* end of private data structure of the page
				header which are set in a page create */
/*----*/
#define	PAGE_LEVEL	 26	/* level of the node in an index tree; the
				leaf level is the level 0 */
#define	PAGE_INDEX_ID	 28	/* index id where the page belongs */
#define PAGE_BTR_SEG_LEAF 36	/* file segment header for the leaf pages in
				a B-tree: defined only on the root page of a
				B-tree, but not in the root of an ibuf tree */
#define PAGE_BTR_IBUF_FREE_LIST	PAGE_BTR_SEG_LEAF
#define PAGE_BTR_IBUF_FREE_LIST_NODE PAGE_BTR_SEG_LEAF
				/* in the place of PAGE_BTR_SEG_LEAF and _TOP
				there is a free list base node if the page is
				the root page of an ibuf tree, and at the same
				place is the free list node if the page is in
				a free list */
#define PAGE_BTR_SEG_TOP (36 + FSEG_HEADER_SIZE)
				/* file segment header for the non-leaf pages
				in a B-tree: defined only on the root page of
				a B-tree, but not in the root of an ibuf
				tree */
/*----*/
#define PAGE_DATA	(PAGE_HEADER + 36 + 2 * FSEG_HEADER_SIZE)
				/* start of data on the page */

#define PAGE_OLD_INFIMUM	(PAGE_DATA + 1 + REC_N_OLD_EXTRA_BYTES)
				/* offset of the page infimum record on an
				old-style page */
#define PAGE_OLD_SUPREMUM	(PAGE_DATA + 2 + 2 * REC_N_OLD_EXTRA_BYTES + 8)
				/* offset of the page supremum record on an
				old-style page */
#define PAGE_OLD_SUPREMUM_END (PAGE_OLD_SUPREMUM + 9)
				/* offset of the page supremum record end on
				an old-style page */
#define PAGE_NEW_INFIMUM	(PAGE_DATA + REC_N_NEW_EXTRA_BYTES)
				/* offset of the page infimum record on a
				new-style compact page */
#define PAGE_NEW_SUPREMUM	(PAGE_DATA + 2 * REC_N_NEW_EXTRA_BYTES + 8)
				/* offset of the page supremum record on a
				new-style compact page */
#define PAGE_NEW_SUPREMUM_END (PAGE_NEW_SUPREMUM + 8)
				/* offset of the page supremum record end on
				a new-style compact page */
/*-----------------------------*/

119 120 121 122 123 124 125 126
/* Heap numbers */
#define PAGE_HEAP_NO_INFIMUM	0	/* page infimum */
#define PAGE_HEAP_NO_SUPREMUM	1	/* page supremum */
#define PAGE_HEAP_NO_USER_LOW	2	/* first user record in
					creation (insertion) order,
					not necessarily collation order;
					this record may have been deleted */

osku's avatar
osku committed
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
/* Directions of cursor movement */
#define	PAGE_LEFT		1
#define	PAGE_RIGHT		2
#define	PAGE_SAME_REC		3
#define	PAGE_SAME_PAGE		4
#define	PAGE_NO_DIRECTION	5

/*			PAGE DIRECTORY
			==============
*/

typedef	byte			page_dir_slot_t;
typedef page_dir_slot_t		page_dir_t;

/* Offset of the directory start down from the page end. We call the
142
slot with the highest file address directory start, as it points to
osku's avatar
osku committed
143 144 145 146 147 148 149 150 151 152 153
the first record in the list of records. */
#define	PAGE_DIR		FIL_PAGE_DATA_END

/* We define a slot in the page directory as two bytes */
#define	PAGE_DIR_SLOT_SIZE	2

/* The offset of the physically lower end of the directory, counted from
page end, when the page is empty */
#define PAGE_EMPTY_DIR_START	(PAGE_DIR + 2 * PAGE_DIR_SLOT_SIZE)

/* The maximum and minimum number of records owned by a directory slot. The
154
number may drop below the minimum in the first and the last slot in the
osku's avatar
osku committed
155 156 157 158
directory. */
#define PAGE_DIR_SLOT_MAX_N_OWNED	8
#define	PAGE_DIR_SLOT_MIN_N_OWNED	4

159 160 161 162 163 164
/****************************************************************
Gets the start of a page. */
UNIV_INLINE
page_t*
page_align(
/*=======*/
165 166
				/* out: start of the page */
	const void*	ptr)	/* in: pointer to page frame */
167 168 169 170 171 172 173 174 175 176
		__attribute__((const));
/****************************************************************
Gets the offset within a page. */
UNIV_INLINE
ulint
page_offset(
/*========*/
				/* out: offset from the start of the page */
	const void*	ptr)	/* in: pointer to page frame */
		__attribute__((const));
osku's avatar
osku committed
177 178 179
/*****************************************************************
Returns the max trx id field value. */
UNIV_INLINE
180
trx_id_t
osku's avatar
osku committed
181 182
page_get_max_trx_id(
/*================*/
183
	const page_t*	page);	/* in: page */
osku's avatar
osku committed
184 185
/*****************************************************************
Sets the max trx id field value. */
186
UNIV_INTERN
osku's avatar
osku committed
187 188 189
void
page_set_max_trx_id(
/*================*/
marko's avatar
marko committed
190 191
	buf_block_t*	block,	/* in/out: page */
	page_zip_des_t*	page_zip,/* in/out: compressed page, or NULL */
192
	trx_id_t	trx_id);/* in: transaction id */
osku's avatar
osku committed
193 194 195 196 197 198 199
/*****************************************************************
Sets the max trx id field value if trx_id is bigger than the previous
value. */
UNIV_INLINE
void
page_update_max_trx_id(
/*===================*/
marko's avatar
marko committed
200
	buf_block_t*	block,	/* in/out: page */
marko's avatar
marko committed
201 202
	page_zip_des_t*	page_zip,/* in/out: compressed page whose
				uncompressed part will be updated, or NULL */
203
	trx_id_t	trx_id);/* in: transaction id */
osku's avatar
osku committed
204 205 206 207 208 209
/*****************************************************************
Reads the given header field. */
UNIV_INLINE
ulint
page_header_get_field(
/*==================*/
210 211
	const page_t*	page,	/* in: page */
	ulint		field);	/* in: PAGE_N_DIR_SLOTS, ... */
osku's avatar
osku committed
212 213 214 215 216 217
/*****************************************************************
Sets the given header field. */
UNIV_INLINE
void
page_header_set_field(
/*==================*/
marko's avatar
marko committed
218
	page_t*		page,	/* in/out: page */
marko's avatar
marko committed
219 220
	page_zip_des_t*	page_zip,/* in/out: compressed page whose
				uncompressed part will be updated, or NULL */
marko's avatar
marko committed
221 222
	ulint		field,	/* in: PAGE_N_DIR_SLOTS, ... */
	ulint		val);	/* in: value */
osku's avatar
osku committed
223
/*****************************************************************
224
Returns the offset stored in the given header field. */
osku's avatar
osku committed
225
UNIV_INLINE
226 227 228 229 230 231 232 233 234 235 236 237 238 239
ulint
page_header_get_offs(
/*=================*/
				/* out: offset from the start of the page,
				or 0 */
	const page_t*	page,	/* in: page */
	ulint		field)	/* in: PAGE_FREE, ... */
	__attribute__((nonnull, pure));

/*****************************************************************
Returns the pointer stored in the given header field, or NULL. */
#define page_header_get_ptr(page, field)			\
	(page_header_get_offs(page, field)			\
	 ? page + page_header_get_offs(page, field) : NULL)
osku's avatar
osku committed
240 241 242 243 244 245
/*****************************************************************
Sets the pointer stored in the given header field. */
UNIV_INLINE
void
page_header_set_ptr(
/*================*/
marko's avatar
marko committed
246
	page_t*		page,	/* in/out: page */
247
	page_zip_des_t*	page_zip,/* in/out: compressed page whose
marko's avatar
marko committed
248
				uncompressed part will be updated, or NULL */
marko's avatar
marko committed
249 250
	ulint		field,	/* in/out: PAGE_FREE, ... */
	const byte*	ptr);	/* in: pointer or NULL*/
251
#ifndef UNIV_HOTBACKUP
osku's avatar
osku committed
252 253 254 255 256 257 258
/*****************************************************************
Resets the last insert info field in the page header. Writes to mlog
about this operation. */
UNIV_INLINE
void
page_header_reset_last_insert(
/*==========================*/
259 260 261 262
	page_t*		page,	/* in: page */
	page_zip_des_t*	page_zip,/* in/out: compressed page whose
				uncompressed part will be updated, or NULL */
	mtr_t*		mtr);	/* in: mtr */
263
#endif /* !UNIV_HOTBACKUP */
osku's avatar
osku committed
264
/****************************************************************
marko's avatar
marko committed
265
Gets the offset of the first record on the page. */
osku's avatar
osku committed
266
UNIV_INLINE
marko's avatar
marko committed
267 268 269 270 271 272
ulint
page_get_infimum_offset(
/*====================*/
				/* out: offset of the first record
				in record list, relative from page */
	const page_t*	page);	/* in: page which must have record(s) */
osku's avatar
osku committed
273
/****************************************************************
marko's avatar
marko committed
274
Gets the offset of the last record on the page. */
osku's avatar
osku committed
275
UNIV_INLINE
marko's avatar
marko committed
276 277 278 279 280 281 282 283
ulint
page_get_supremum_offset(
/*=====================*/
				/* out: offset of the last record in
				record list, relative from page */
	const page_t*	page);	/* in: page which must have record(s) */
#define page_get_infimum_rec(page) ((page) + page_get_infimum_offset(page))
#define page_get_supremum_rec(page) ((page) + page_get_supremum_offset(page))
osku's avatar
osku committed
284 285 286
/****************************************************************
Returns the middle record of record list. If there are an even number
of records in the list, returns the first record of upper half-list. */
287
UNIV_INTERN
osku's avatar
osku committed
288 289 290 291 292
rec_t*
page_get_middle_rec(
/*================*/
			/* out: middle record */
	page_t*	page);	/* in: page */
293
#ifndef UNIV_HOTBACKUP
osku's avatar
osku committed
294 295 296 297 298 299 300 301 302
/*****************************************************************
Compares a data tuple to a physical record. Differs from the function
cmp_dtuple_rec_with_match in the way that the record must reside on an
index page, and also page infimum and supremum records can be given in
the parameter rec. These are considered as the negative infinity and
the positive infinity in the alphabetical order. */
UNIV_INLINE
int
page_cmp_dtuple_rec_with_match(
303 304 305
/*===========================*/
				/* out: 1, 0, -1, if dtuple is greater, equal,
				less than rec, respectively, when only the
osku's avatar
osku committed
306
				common first fields are compared */
307 308
	const dtuple_t*	dtuple,	/* in: data tuple */
	const rec_t*	rec,	/* in: physical record on a page; may also
309 310
				be page infimum or supremum, in which case
				matched-parameter values below are not
osku's avatar
osku committed
311 312
				affected */
	const ulint*	offsets,/* in: array returned by rec_get_offsets() */
313
	ulint*		matched_fields, /* in/out: number of already completely
osku's avatar
osku committed
314 315
				matched fields; when function returns
				contains the value for current comparison */
316
	ulint*		matched_bytes); /* in/out: number of already matched
osku's avatar
osku committed
317 318 319
				bytes within the first field not completely
				matched; when function returns contains the
				value for current comparison */
320
#endif /* !UNIV_HOTBACKUP */
osku's avatar
osku committed
321
/*****************************************************************
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
Gets the page number. */
UNIV_INLINE
ulint
page_get_page_no(
/*=============*/
				/* out: page number */
	const page_t*	page);	/* in: page */
/*****************************************************************
Gets the tablespace identifier. */
UNIV_INLINE
ulint
page_get_space_id(
/*==============*/
				/* out: space id */
	const page_t*	page);	/* in: page */
/*****************************************************************
osku's avatar
osku committed
338 339 340 341 342 343
Gets the number of user records on page (the infimum and supremum records
are not user records). */
UNIV_INLINE
ulint
page_get_n_recs(
/*============*/
344 345
				/* out: number of user records */
	const page_t*	page);	/* in: index page */
osku's avatar
osku committed
346 347 348
/*******************************************************************
Returns the number of records before the given record in chain.
The number includes infimum and supremum records. */
349
UNIV_INTERN
osku's avatar
osku committed
350 351 352
ulint
page_rec_get_n_recs_before(
/*=======================*/
353 354
				/* out: number of records */
	const rec_t*	rec);	/* in: the physical record */
osku's avatar
osku committed
355 356 357 358 359 360
/*****************************************************************
Gets the number of records in the heap. */
UNIV_INLINE
ulint
page_dir_get_n_heap(
/*================*/
361 362
				/* out: number of user records */
	const page_t*	page);	/* in: index page */
osku's avatar
osku committed
363 364 365 366 367 368
/*****************************************************************
Sets the number of records in the heap. */
UNIV_INLINE
void
page_dir_set_n_heap(
/*================*/
marko's avatar
marko committed
369
	page_t*		page,	/* in/out: index page */
marko's avatar
marko committed
370
	page_zip_des_t*	page_zip,/* in/out: compressed page whose
371 372 373 374
				uncompressed part will be updated, or NULL.
				Note that the size of the dense page directory
				in the compressed page trailer is
				n_heap * PAGE_ZIP_DIR_SLOT_SIZE. */
marko's avatar
marko committed
375
	ulint		n_heap);/* in: number of records */
osku's avatar
osku committed
376 377 378 379 380 381
/*****************************************************************
Gets the number of dir slots in directory. */
UNIV_INLINE
ulint
page_dir_get_n_slots(
/*=================*/
382 383
				/* out: number of slots */
	const page_t*	page);	/* in: index page */
osku's avatar
osku committed
384 385 386 387 388 389
/*****************************************************************
Sets the number of dir slots in directory. */
UNIV_INLINE
void
page_dir_set_n_slots(
/*=================*/
marko's avatar
marko committed
390
	page_t*		page,	/* in/out: page */
marko's avatar
marko committed
391 392
	page_zip_des_t*	page_zip,/* in/out: compressed page whose
				uncompressed part will be updated, or NULL */
marko's avatar
marko committed
393
	ulint		n_slots);/* in: number of slots */
394
#ifdef UNIV_DEBUG
osku's avatar
osku committed
395 396 397 398 399 400
/*****************************************************************
Gets pointer to nth directory slot. */
UNIV_INLINE
page_dir_slot_t*
page_dir_get_nth_slot(
/*==================*/
401 402 403 404 405 406 407 408
				/* out: pointer to dir slot */
	const page_t*	page,	/* in: index page */
	ulint		n);	/* in: position */
#else /* UNIV_DEBUG */
# define page_dir_get_nth_slot(page, n)		\
	((page) + UNIV_PAGE_SIZE - PAGE_DIR	\
	 - (n + 1) * PAGE_DIR_SLOT_SIZE)
#endif /* UNIV_DEBUG */
osku's avatar
osku committed
409 410 411 412 413 414
/******************************************************************
Used to check the consistency of a record on a page. */
UNIV_INLINE
ibool
page_rec_check(
/*===========*/
marko's avatar
marko committed
415 416
				/* out: TRUE if succeed */
	const rec_t*	rec);	/* in: record */
osku's avatar
osku committed
417 418 419
/*******************************************************************
Gets the record pointed to by a directory slot. */
UNIV_INLINE
420
const rec_t*
osku's avatar
osku committed
421 422 423
page_dir_slot_get_rec(
/*==================*/
					/* out: pointer to record */
424
	const page_dir_slot_t*	slot);	/* in: directory slot */
osku's avatar
osku committed
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
/*******************************************************************
This is used to set the record offset in a directory slot. */
UNIV_INLINE
void
page_dir_slot_set_rec(
/*==================*/
	page_dir_slot_t* slot,	/* in: directory slot */
	rec_t*		 rec);	/* in: record on the page */
/*******************************************************************
Gets the number of records owned by a directory slot. */
UNIV_INLINE
ulint
page_dir_slot_get_n_owned(
/*======================*/
					/* out: number of records */
440
	const page_dir_slot_t*	slot);	/* in: page directory slot */
osku's avatar
osku committed
441 442 443 444 445 446
/*******************************************************************
This is used to set the owned records field of a directory slot. */
UNIV_INLINE
void
page_dir_slot_set_n_owned(
/*======================*/
marko's avatar
marko committed
447
	page_dir_slot_t*slot,	/* in/out: directory slot */
448
	page_zip_des_t*	page_zip,/* in/out: compressed page, or NULL */
marko's avatar
marko committed
449
	ulint		n);	/* in: number of records owned by the slot */
osku's avatar
osku committed
450 451 452 453 454 455 456 457 458 459 460 461
/****************************************************************
Calculates the space reserved for directory slots of a given
number of records. The exact value is a fraction number
n * PAGE_DIR_SLOT_SIZE / PAGE_DIR_SLOT_MIN_N_OWNED, and it is
rounded upwards to an integer. */
UNIV_INLINE
ulint
page_dir_calc_reserved_space(
/*=========================*/
	ulint	n_recs);	/* in: number of records */
/*******************************************************************
Looks for the directory slot which owns the given record. */
462
UNIV_INTERN
osku's avatar
osku committed
463 464 465 466
ulint
page_dir_find_owner_slot(
/*=====================*/
				/* out: the directory slot number */
467
	const rec_t*	rec);	/* in: the physical record */
osku's avatar
osku committed
468 469 470 471 472 473
/****************************************************************
Determine whether the page is in new-style compact format. */
UNIV_INLINE
ulint
page_is_comp(
/*=========*/
474 475 476
				/* out: nonzero if the page is in compact
				format, zero if it is in old-style format */
	const page_t*	page);	/* in: index page */
osku's avatar
osku committed
477 478 479 480 481 482 483 484
/****************************************************************
TRUE if the record is on a page in compact format. */
UNIV_INLINE
ulint
page_rec_is_comp(
/*=============*/
				/* out: nonzero if in compact format */
	const rec_t*	rec);	/* in: record */
485 486 487 488 489 490 491 492
/*******************************************************************
Returns the heap number of a record. */
UNIV_INLINE
ulint
page_rec_get_heap_no(
/*=================*/
				/* out: heap number */
	const rec_t*	rec);	/* in: the physical record */
osku's avatar
osku committed
493
/****************************************************************
494 495 496 497 498 499 500 501 502
Determine whether the page is a B-tree leaf. */
UNIV_INLINE
ibool
page_is_leaf(
/*=========*/
				/* out: TRUE if the page is a B-tree leaf */
	const page_t*	page)	/* in: page */
	__attribute__((nonnull, pure));
/****************************************************************
osku's avatar
osku committed
503 504
Gets the pointer to the next record on the page. */
UNIV_INLINE
505
const rec_t*
marko's avatar
marko committed
506 507
page_rec_get_next_low(
/*==================*/
508 509 510
				/* out: pointer to next record */
	const rec_t*	rec,	/* in: pointer to record */
	ulint		comp);	/* in: nonzero=compact page layout */
marko's avatar
marko committed
511 512 513 514
/****************************************************************
Gets the pointer to the next record on the page. */
UNIV_INLINE
rec_t*
osku's avatar
osku committed
515 516 517
page_rec_get_next(
/*==============*/
			/* out: pointer to next record */
marko's avatar
marko committed
518
	rec_t*	rec);	/* in: pointer to record */
osku's avatar
osku committed
519
/****************************************************************
520 521 522 523 524 525 526 527
Gets the pointer to the next record on the page. */
UNIV_INLINE
const rec_t*
page_rec_get_next_const(
/*====================*/
				/* out: pointer to next record */
	const rec_t*	rec);	/* in: pointer to record */
/****************************************************************
528
Sets the pointer to the next record on the page. */
osku's avatar
osku committed
529 530 531 532
UNIV_INLINE
void
page_rec_set_next(
/*==============*/
533 534 535 536
	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 */
osku's avatar
osku committed
537 538 539
/****************************************************************
Gets the pointer to the previous record. */
UNIV_INLINE
540 541 542 543 544 545 546 547 548
const rec_t*
page_rec_get_prev_const(
/*====================*/
				/* out: pointer to previous record */
	const rec_t*	rec);	/* in: pointer to record, must not be page
				infimum */
/****************************************************************
Gets the pointer to the previous record. */
UNIV_INLINE
osku's avatar
osku committed
549 550 551 552 553 554 555 556 557 558 559 560 561
rec_t*
page_rec_get_prev(
/*==============*/
				/* out: pointer to previous record */
	rec_t*		rec);	/* in: pointer to record,
				must not be page infimum */
/****************************************************************
TRUE if the record is a user record on the page. */
UNIV_INLINE
ibool
page_rec_is_user_rec_low(
/*=====================*/
			/* out: TRUE if a user record */
marko's avatar
marko committed
562 563
	ulint	offset)	/* in: record offset on page */
	__attribute__((const));
osku's avatar
osku committed
564 565 566 567 568 569 570
/****************************************************************
TRUE if the record is the supremum record on a page. */
UNIV_INLINE
ibool
page_rec_is_supremum_low(
/*=====================*/
			/* out: TRUE if the supremum record */
marko's avatar
marko committed
571 572
	ulint	offset)	/* in: record offset on page */
	__attribute__((const));
osku's avatar
osku committed
573 574 575 576 577
/****************************************************************
TRUE if the record is the infimum record on a page. */
UNIV_INLINE
ibool
page_rec_is_infimum_low(
578
/*====================*/
osku's avatar
osku committed
579
			/* out: TRUE if the infimum record */
marko's avatar
marko committed
580 581
	ulint	offset)	/* in: record offset on page */
	__attribute__((const));
osku's avatar
osku committed
582 583 584 585 586 587 588 589

/****************************************************************
TRUE if the record is a user record on the page. */
UNIV_INLINE
ibool
page_rec_is_user_rec(
/*=================*/
				/* out: TRUE if a user record */
marko's avatar
marko committed
590 591
	const rec_t*	rec)	/* in: record */
	__attribute__((const));
osku's avatar
osku committed
592 593 594 595 596 597 598
/****************************************************************
TRUE if the record is the supremum record on a page. */
UNIV_INLINE
ibool
page_rec_is_supremum(
/*=================*/
				/* out: TRUE if the supremum record */
marko's avatar
marko committed
599 600 601
	const rec_t*	rec)	/* in: record */
	__attribute__((const));

osku's avatar
osku committed
602 603 604 605 606 607 608
/****************************************************************
TRUE if the record is the infimum record on a page. */
UNIV_INLINE
ibool
page_rec_is_infimum(
/*================*/
				/* out: TRUE if the infimum record */
marko's avatar
marko committed
609 610
	const rec_t*	rec)	/* in: record */
	__attribute__((const));
osku's avatar
osku committed
611 612 613 614 615 616 617 618 619 620 621 622
/*******************************************************************
Looks for the record which owns the given record. */
UNIV_INLINE
rec_t*
page_rec_find_owner_rec(
/*====================*/
			/* out: the owner record */
	rec_t*	rec);	/* in: the physical record */
/***************************************************************************
This is a low-level operation which is used in a database index creation
to update the page number of a created B-tree to a data dictionary
record. */
623
UNIV_INTERN
osku's avatar
osku committed
624 625 626 627 628 629 630 631 632 633 634 635 636 637
void
page_rec_write_index_page_no(
/*=========================*/
	rec_t*	rec,	/* in: record to update */
	ulint	i,	/* in: index of the field to update */
	ulint	page_no,/* in: value to write */
	mtr_t*	mtr);	/* in: mtr */
/****************************************************************
Returns the maximum combined size of records which can be inserted on top
of record heap. */
UNIV_INLINE
ulint
page_get_max_insert_size(
/*=====================*/
638 639 640 641
				/* out: maximum combined size for
				inserted records */
	const page_t*	page,	/* in: index page */
	ulint		n_recs);/* in: number of records */
osku's avatar
osku committed
642 643 644 645 646 647 648
/****************************************************************
Returns the maximum combined size of records which can be inserted on top
of record heap if page is first reorganized. */
UNIV_INLINE
ulint
page_get_max_insert_size_after_reorganize(
/*======================================*/
649 650 651 652
				/* out: maximum combined size for
				inserted records */
	const page_t*	page,	/* in: index page */
	ulint		n_recs);/* in: number of records */
osku's avatar
osku committed
653 654 655 656 657 658 659 660 661
/*****************************************************************
Calculates free space if a page is emptied. */
UNIV_INLINE
ulint
page_get_free_space_of_empty(
/*=========================*/
			/* out: free space */
	ulint	comp)	/* in: nonzero=compact page format */
		__attribute__((const));
marko's avatar
marko committed
662 663 664 665 666 667 668 669 670 671
/**************************************************************
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 */
osku's avatar
osku committed
672 673 674 675 676 677 678
/****************************************************************
Returns the sum of the sizes of the records in the record list
excluding the infimum and supremum records. */
UNIV_INLINE
ulint
page_get_data_size(
/*===============*/
679 680
				/* out: data in bytes */
	const page_t*	page);	/* in: index page */
osku's avatar
osku committed
681
/****************************************************************
682 683 684 685 686 687 688 689 690 691 692 693 694 695 696
Allocates a block of memory from the head of the free list
of an index page. */
UNIV_INLINE
void
page_mem_alloc_free(
/*================*/
	page_t*		page,	/* in/out: index page */
	page_zip_des_t*	page_zip,/* in/out: compressed page with enough
				space available for inserting the record,
				or NULL */
	rec_t*		next_rec,/* in: pointer to the new head of the
				free record list */
	ulint		need);	/* in: number of bytes allocated */
/****************************************************************
Allocates a block of memory from the heap of an index page. */
697
UNIV_INTERN
osku's avatar
osku committed
698
byte*
699 700
page_mem_alloc_heap(
/*================*/
osku's avatar
osku committed
701 702
				/* out: pointer to start of allocated
				buffer, or NULL if allocation fails */
marko's avatar
marko committed
703
	page_t*		page,	/* in/out: index page */
704 705 706 707 708
	page_zip_des_t*	page_zip,/* in/out: compressed page with enough
				space available for inserting the record,
				or NULL */
	ulint		need,	/* in: total number of bytes needed */
	ulint*		heap_no);/* out: this contains the heap number
osku's avatar
osku committed
709 710 711 712 713 714 715 716
				of the allocated record
				if allocation succeeds */
/****************************************************************
Puts a record to free list. */
UNIV_INLINE
void
page_mem_free(
/*==========*/
marko's avatar
marko committed
717
	page_t*		page,	/* in/out: index page */
718
	page_zip_des_t*	page_zip,/* in/out: compressed page, or NULL */
osku's avatar
osku committed
719
	rec_t*		rec,	/* in: pointer to the (origin of) record */
720
	dict_index_t*	index,	/* in: index of rec */
721
	const ulint*	offsets);/* in: array returned by rec_get_offsets() */
osku's avatar
osku committed
722
/**************************************************************
723
Create an uncompressed B-tree index page. */
724
UNIV_INTERN
725
page_t*
osku's avatar
osku committed
726 727 728
page_create(
/*========*/
					/* out: pointer to the page */
729
	buf_block_t*	block,		/* in: a buffer block where the
730
					page is created */
osku's avatar
osku committed
731
	mtr_t*		mtr,		/* in: mini-transaction handle */
732 733 734
	ulint		comp);		/* in: nonzero=compact page format */
/**************************************************************
Create a compressed B-tree index page. */
735
UNIV_INTERN
736 737 738 739
page_t*
page_create_zip(
/*============*/
					/* out: pointer to the page */
740
	buf_block_t*	block,		/* in/out: a buffer frame where the
741 742 743 744 745
					page is created */
	dict_index_t*	index,		/* in: the index of the page */
	ulint		level,		/* in: the B-tree level of the page */
	mtr_t*		mtr);		/* in: mini-transaction handle */

osku's avatar
osku committed
746 747
/*****************************************************************
Differs from page_copy_rec_list_end, because this function does not
marko's avatar
marko committed
748
touch the lock table and max trx id on page or compress the page. */
749
UNIV_INTERN
osku's avatar
osku committed
750 751 752
void
page_copy_rec_list_end_no_locks(
/*============================*/
753 754
	buf_block_t*	new_block,	/* in: index page to copy to */
	buf_block_t*	block,		/* in: index page of rec */
osku's avatar
osku committed
755 756 757 758 759 760 761
	rec_t*		rec,		/* in: record on page */
	dict_index_t*	index,		/* in: record descriptor */
	mtr_t*		mtr);		/* in: mtr */
/*****************************************************************
Copies records from page to new_page, from the given record onward,
including that record. Infimum and supremum records are not copied.
The records are copied to the start of the record list on new_page. */
762
UNIV_INTERN
763
rec_t*
osku's avatar
osku committed
764 765
page_copy_rec_list_end(
/*===================*/
766 767 768
					/* out: pointer to the original
					successor of the infimum record
					on new_page, or NULL on zip overflow
769
					(new_block will be decompressed) */
770
	buf_block_t*	new_block,	/* in/out: index page to copy to */
771
	buf_block_t*	block,		/* in: index page containing rec */
osku's avatar
osku committed
772 773
	rec_t*		rec,		/* in: record on page */
	dict_index_t*	index,		/* in: record descriptor */
marko's avatar
marko committed
774
	mtr_t*		mtr)		/* in: mtr */
775
	__attribute__((nonnull));
osku's avatar
osku committed
776 777 778 779
/*****************************************************************
Copies records from page to new_page, up to the given record, NOT
including that record. Infimum and supremum records are not copied.
The records are copied to the end of the record list on new_page. */
780
UNIV_INTERN
781
rec_t*
osku's avatar
osku committed
782 783
page_copy_rec_list_start(
/*=====================*/
784 785 786
					/* out: pointer to the original
					predecessor of the supremum record
					on new_page, or NULL on zip overflow
787
					(new_block will be decompressed) */
788
	buf_block_t*	new_block,	/* in/out: index page to copy to */
789
	buf_block_t*	block,		/* in: index page containing rec */
osku's avatar
osku committed
790 791
	rec_t*		rec,		/* in: record on page */
	dict_index_t*	index,		/* in: record descriptor */
marko's avatar
marko committed
792
	mtr_t*		mtr)		/* in: mtr */
793
	__attribute__((nonnull));
osku's avatar
osku committed
794 795 796
/*****************************************************************
Deletes records from a page from a given record onward, including that record.
The infimum and supremum records are not deleted. */
797
UNIV_INTERN
osku's avatar
osku committed
798 799 800
void
page_delete_rec_list_end(
/*=====================*/
marko's avatar
marko committed
801
	rec_t*		rec,	/* in: pointer to record on page */
802
	buf_block_t*	block,	/* in: buffer block of the page */
osku's avatar
osku committed
803 804 805 806 807 808
	dict_index_t*	index,	/* in: record descriptor */
	ulint		n_recs,	/* in: number of records to delete,
				or ULINT_UNDEFINED if not known */
	ulint		size,	/* in: the sum of the sizes of the
				records in the end of the chain to
				delete, or ULINT_UNDEFINED if not known */
marko's avatar
marko committed
809
	mtr_t*		mtr)	/* in: mtr */
810
	__attribute__((nonnull));
osku's avatar
osku committed
811
/*****************************************************************
812 813
Deletes records from page, up to the given record, NOT including
that record. Infimum and supremum records are not deleted. */
814
UNIV_INTERN
815 816 817 818
void
page_delete_rec_list_start(
/*=======================*/
	rec_t*		rec,	/* in: record on page */
819
	buf_block_t*	block,	/* in: buffer block of the page */
820 821
	dict_index_t*	index,	/* in: record descriptor */
	mtr_t*		mtr)	/* in: mtr */
822
	__attribute__((nonnull));
823
/*****************************************************************
osku's avatar
osku committed
824 825
Moves record list end to another page. Moved records include
split_rec. */
826
UNIV_INTERN
827
ibool
osku's avatar
osku committed
828 829
page_move_rec_list_end(
/*===================*/
830
					/* out: TRUE on success; FALSE on
831 832
					compression failure
					(new_block will be decompressed) */
833
	buf_block_t*	new_block,	/* in/out: index page where to move */
834
	buf_block_t*	block,		/* in: index page from where to move */
osku's avatar
osku committed
835 836
	rec_t*		split_rec,	/* in: first record to move */
	dict_index_t*	index,		/* in: record descriptor */
marko's avatar
marko committed
837
	mtr_t*		mtr)		/* in: mtr */
838
	__attribute__((nonnull(1, 2, 4, 5)));
839 840 841
/*****************************************************************
Moves record list start to another page. Moved records do not include
split_rec. */
842
UNIV_INTERN
843
ibool
844 845
page_move_rec_list_start(
/*=====================*/
846 847
					/* out: TRUE on success; FALSE on
					compression failure */
848
	buf_block_t*	new_block,	/* in/out: index page where to move */
849
	buf_block_t*	block,		/* in/out: page containing split_rec */
850 851 852
	rec_t*		split_rec,	/* in: first record not to move */
	dict_index_t*	index,		/* in: record descriptor */
	mtr_t*		mtr)		/* in: mtr */
853
	__attribute__((nonnull(1, 2, 4, 5)));
osku's avatar
osku committed
854 855
/********************************************************************
Splits a directory slot which owns too many records. */
856
UNIV_INTERN
osku's avatar
osku committed
857 858 859
void
page_dir_split_slot(
/*================*/
marko's avatar
marko committed
860
	page_t*		page,	/* in: index page */
861 862
	page_zip_des_t*	page_zip,/* in/out: compressed page whose
				uncompressed part will be written, or NULL */
marko's avatar
marko committed
863 864
	ulint		slot_no)/* in: the directory slot */
	__attribute__((nonnull(1)));
osku's avatar
osku committed
865 866
/*****************************************************************
Tries to balance the given directory slot with too few records
867 868
with the upper neighbor, so that there are at least the minimum number
of records owned by the slot; this may result in the merging of
osku's avatar
osku committed
869
two slots. */
870
UNIV_INTERN
osku's avatar
osku committed
871 872 873
void
page_dir_balance_slot(
/*==================*/
marko's avatar
marko committed
874
	page_t*		page,	/* in/out: index page */
875
	page_zip_des_t*	page_zip,/* in/out: compressed page, or NULL */
marko's avatar
marko committed
876 877
	ulint		slot_no)/* in: the directory slot */
	__attribute__((nonnull(1)));
osku's avatar
osku committed
878 879
/**************************************************************
Parses a log record of a record list end or start deletion. */
880
UNIV_INTERN
osku's avatar
osku committed
881 882 883 884 885 886 887 888 889 890
byte*
page_parse_delete_rec_list(
/*=======================*/
				/* out: end of log record or NULL */
	byte		type,	/* in: MLOG_LIST_END_DELETE,
				MLOG_LIST_START_DELETE,
				MLOG_COMP_LIST_END_DELETE or
				MLOG_COMP_LIST_START_DELETE */
	byte*		ptr,	/* in: buffer */
	byte*		end_ptr,/* in: buffer end */
891
	buf_block_t*	block,	/* in/out: buffer block or NULL */
osku's avatar
osku committed
892 893 894 895
	dict_index_t*	index,	/* in: record descriptor */
	mtr_t*		mtr);	/* in: mtr or NULL */
/***************************************************************
Parses a redo log record of creating a page. */
896
UNIV_INTERN
osku's avatar
osku committed
897 898 899
byte*
page_parse_create(
/*==============*/
900 901 902 903
				/* out: end of log record or NULL */
	byte*		ptr,	/* in: buffer */
	byte*		end_ptr,/* in: buffer end */
	ulint		comp,	/* in: nonzero=compact page format */
904
	buf_block_t*	block,	/* in: block or NULL */
905
	mtr_t*		mtr);	/* in: mtr or NULL */
osku's avatar
osku committed
906 907 908
/****************************************************************
Prints record contents including the data relevant only in
the index page context. */
909
UNIV_INTERN
osku's avatar
osku committed
910 911 912
void
page_rec_print(
/*===========*/
marko's avatar
marko committed
913
	const rec_t*	rec,	/* in: physical record */
osku's avatar
osku committed
914 915 916 917
	const ulint*	offsets);/* in: record descriptor */
/*******************************************************************
This is used to print the contents of the directory for
debugging purposes. */
918
UNIV_INTERN
osku's avatar
osku committed
919 920 921 922 923 924 925 926
void
page_dir_print(
/*===========*/
	page_t*	page,	/* in: index page */
	ulint	pr_n);	/* in: print n first and n last entries */
/*******************************************************************
This is used to print the contents of the page record list for
debugging purposes. */
927
UNIV_INTERN
osku's avatar
osku committed
928 929 930
void
page_print_list(
/*============*/
931
	buf_block_t*	block,	/* in: index page */
osku's avatar
osku committed
932 933 934 935
	dict_index_t*	index,	/* in: dictionary index of the page */
	ulint		pr_n);	/* in: print n first and n last entries */
/*******************************************************************
Prints the info in a page header. */
936
UNIV_INTERN
osku's avatar
osku committed
937 938 939
void
page_header_print(
/*==============*/
940
	const page_t*	page);
osku's avatar
osku committed
941 942 943
/*******************************************************************
This is used to print the contents of the page for
debugging purposes. */
944
UNIV_INTERN
osku's avatar
osku committed
945 946
void
page_print(
947
/*=======*/
948
	buf_block_t*	block,	/* in: index page */
osku's avatar
osku committed
949 950 951 952 953 954 955 956 957
	dict_index_t*	index,	/* in: dictionary index of the page */
	ulint		dn,	/* in: print dn first and last entries
				in directory */
	ulint		rn);	/* in: print rn first and last records
				in directory */
/*******************************************************************
The following is used to validate a record on a page. This function
differs from rec_validate as it can also check the n_owned field and
the heap_no field. */
958
UNIV_INTERN
osku's avatar
osku committed
959 960 961 962 963 964 965 966 967 968
ibool
page_rec_validate(
/*==============*/
				/* out: TRUE if ok */
	rec_t*		rec,	/* in: physical record */
	const ulint*	offsets);/* in: array returned by rec_get_offsets() */
/*******************************************************************
Checks that the first directory slot points to the infimum record and
the last to the supremum. This function is intended to track if the
bug fixed in 4.0.14 has caused corruption to users' databases. */
969
UNIV_INTERN
osku's avatar
osku committed
970 971 972
void
page_check_dir(
/*===========*/
973
	const page_t*	page);	/* in: index page */
osku's avatar
osku committed
974 975 976 977
/*******************************************************************
This function checks the consistency of an index page when we do not
know the index. This is also resilient so that this should never crash
even if the page is total garbage. */
978
UNIV_INTERN
osku's avatar
osku committed
979
ibool
marko's avatar
marko committed
980 981
page_simple_validate_old(
/*=====================*/
osku's avatar
osku committed
982
			/* out: TRUE if ok */
marko's avatar
marko committed
983 984 985 986 987
	page_t*	page);	/* in: old-style index page */
/*******************************************************************
This function checks the consistency of an index page when we do not
know the index. This is also resilient so that this should never crash
even if the page is total garbage. */
988
UNIV_INTERN
marko's avatar
marko committed
989 990 991 992
ibool
page_simple_validate_new(
/*=====================*/
			/* out: TRUE if ok */
993
	page_t*	block);	/* in: new-style index page */
osku's avatar
osku committed
994 995
/*******************************************************************
This function checks the consistency of an index page. */
996
UNIV_INTERN
osku's avatar
osku committed
997 998 999 1000 1001 1002 1003 1004 1005 1006
ibool
page_validate(
/*==========*/
				/* out: TRUE if ok */
	page_t*		page,	/* in: index page */
	dict_index_t*	index);	/* in: data dictionary index containing
				the page record type definition */
/*******************************************************************
Looks in the page record list for a record with the given heap number. */

1007
const rec_t*
osku's avatar
osku committed
1008 1009
page_find_rec_with_heap_no(
/*=======================*/
1010 1011 1012
				/* out: record, NULL if not found */
	const page_t*	page,	/* in: index page */
	ulint		heap_no);/* in: heap number */
osku's avatar
osku committed
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022

#ifdef UNIV_MATERIALIZE
#undef UNIV_INLINE
#define UNIV_INLINE  UNIV_INLINE_ORIGINAL
#endif

#ifndef UNIV_NONINL
#include "page0page.ic"
#endif

1023
#endif