btr0btr.h 19.1 KB
Newer Older
1 2
/*****************************************************************************

3
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

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

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

19 20
/**************************************************//**
@file include/btr0btr.h
osku's avatar
osku committed
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
The B-tree

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

#ifndef btr0btr_h
#define btr0btr_h

#include "univ.i"

#include "dict0dict.h"
#include "data0data.h"
#include "page0cur.h"
#include "mtr0mtr.h"
#include "btr0types.h"

37
#ifndef UNIV_HOTBACKUP
38
/** Maximum record size which can be stored on a page, without using the
osku's avatar
osku committed
39 40 41
special big record storage structure */
#define	BTR_PAGE_MAX_REC_SIZE	(UNIV_PAGE_SIZE / 2 - 200)

42 43 44 45 46 47 48 49 50
/** @brief Maximum depth of a B-tree in InnoDB.

Note that this isn't a maximum as such; none of the tree operations
avoid producing trees bigger than this. It is instead a "max depth
that other code must work with", useful for e.g.  fixed-size arrays
that must store some information about each level in a tree. In other
words: if a B-tree with bigger depth than this is encountered, it is
not acceptable for it to lead to mysterious memory corruption, but it
is acceptable for the program to die with a clear assert failure. */
51 52
#define BTR_MAX_LEVELS		100

53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
/** Latching modes for btr_cur_search_to_nth_level(). */
enum btr_latch_mode {
	/** Search a record on a leaf page and S-latch it. */
	BTR_SEARCH_LEAF = RW_S_LATCH,
	/** (Prepare to) modify a record on a leaf page and X-latch it. */
	BTR_MODIFY_LEAF	= RW_X_LATCH,
	/** Obtain no latches. */
	BTR_NO_LATCHES = RW_NO_LATCH,
	/** Start modifying the entire B-tree. */
	BTR_MODIFY_TREE = 33,
	/** Continue modifying the entire B-tree. */
	BTR_CONT_MODIFY_TREE = 34,
	/** Search the previous record. */
	BTR_SEARCH_PREV = 35,
	/** Modify the previous record. */
	BTR_MODIFY_PREV = 36
};
osku's avatar
osku committed
70

71 72
/* BTR_INSERT, BTR_DELETE and BTR_DELETE_MARK are mutually exclusive. */

73
/** If this is ORed to btr_latch_mode, it means that the search tuple
74 75
will be inserted to the index, at the searched position.
When the record is not in the buffer pool, try to use the insert buffer. */
osku's avatar
osku committed
76 77
#define BTR_INSERT		512

78
/** This flag ORed to btr_latch_mode says that we do the search in query
osku's avatar
osku committed
79 80 81
optimization */
#define BTR_ESTIMATE		1024

82
/** This flag ORed to BTR_INSERT says that we can ignore possible
83 84
UNIQUE definition on secondary indexes when we decide if we can use
the insert buffer to speed up inserts */
85
#define BTR_IGNORE_SEC_UNIQUE	2048
osku's avatar
osku committed
86

87
/** Try to delete mark the record at the searched position using the
88
insert/delete buffer when the record is not in the buffer pool. */
89 90
#define BTR_DELETE_MARK		4096

91 92
/** Try to purge the record at the searched position using the insert/delete
buffer when the record is not in the buffer pool. */
93 94
#define BTR_DELETE		8192

95
/**************************************************************//**
96 97
Gets the root node of a tree and x-latches it.
@return	root page, x-latched */
98
UNIV_INTERN
osku's avatar
osku committed
99 100 101
page_t*
btr_root_get(
/*=========*/
102 103
	dict_index_t*	index,	/*!< in: index tree */
	mtr_t*		mtr);	/*!< in: mtr */
104
/**************************************************************//**
osku's avatar
osku committed
105 106
Gets a buffer page and declares its latching order level. */
UNIV_INLINE
107 108 109
buf_block_t*
btr_block_get(
/*==========*/
110 111
	ulint	space,		/*!< in: space id */
	ulint	zip_size,	/*!< in: compressed page size in bytes
112
				or 0 for uncompressed pages */
113 114 115
	ulint	page_no,	/*!< in: page number */
	ulint	mode,		/*!< in: latch mode */
	mtr_t*	mtr);		/*!< in: mtr */
116
/**************************************************************//**
117 118
Gets a buffer page and declares its latching order level. */
UNIV_INLINE
osku's avatar
osku committed
119 120 121
page_t*
btr_page_get(
/*=========*/
122 123
	ulint	space,		/*!< in: space id */
	ulint	zip_size,	/*!< in: compressed page size in bytes
124
				or 0 for uncompressed pages */
125 126 127
	ulint	page_no,	/*!< in: page number */
	ulint	mode,		/*!< in: latch mode */
	mtr_t*	mtr);		/*!< in: mtr */
128
#endif /* !UNIV_HOTBACKUP */
129
/**************************************************************//**
130 131
Gets the index id field of a page.
@return	index id */
osku's avatar
osku committed
132 133 134 135
UNIV_INLINE
dulint
btr_page_get_index_id(
/*==================*/
136
	const page_t*	page);	/*!< in: index page */
137
#ifndef UNIV_HOTBACKUP
138
/********************************************************//**
139 140
Gets the node level field in an index page.
@return	level, leaf level == 0 */
osku's avatar
osku committed
141 142 143 144
UNIV_INLINE
ulint
btr_page_get_level_low(
/*===================*/
145
	const page_t*	page);	/*!< in: index page */
146
/********************************************************//**
147 148
Gets the node level field in an index page.
@return	level, leaf level == 0 */
osku's avatar
osku committed
149 150 151 152
UNIV_INLINE
ulint
btr_page_get_level(
/*===============*/
153 154
	const page_t*	page,	/*!< in: index page */
	mtr_t*		mtr);	/*!< in: mini-transaction handle */
155
/********************************************************//**
156 157
Gets the next index page number.
@return	next page number */
osku's avatar
osku committed
158 159 160 161
UNIV_INLINE
ulint
btr_page_get_next(
/*==============*/
162 163
	const page_t*	page,	/*!< in: index page */
	mtr_t*		mtr);	/*!< in: mini-transaction handle */
164
/********************************************************//**
165 166
Gets the previous index page number.
@return	prev page number */
osku's avatar
osku committed
167 168 169 170
UNIV_INLINE
ulint
btr_page_get_prev(
/*==============*/
171 172
	const page_t*	page,	/*!< in: index page */
	mtr_t*		mtr);	/*!< in: mini-transaction handle */
173
/*************************************************************//**
osku's avatar
osku committed
174
Gets pointer to the previous user record in the tree. It is assumed
175 176
that the caller has appropriate latches on the page and its neighbor.
@return	previous user record, NULL if there is none */
177
UNIV_INTERN
osku's avatar
osku committed
178 179 180
rec_t*
btr_get_prev_user_rec(
/*==================*/
181 182
	rec_t*	rec,	/*!< in: record on leaf level */
	mtr_t*	mtr);	/*!< in: mtr holding a latch on the page, and if
osku's avatar
osku committed
183
			needed, also to the previous page */
184
/*************************************************************//**
osku's avatar
osku committed
185
Gets pointer to the next user record in the tree. It is assumed
186 187
that the caller has appropriate latches on the page and its neighbor.
@return	next user record, NULL if there is none */
188
UNIV_INTERN
osku's avatar
osku committed
189 190 191
rec_t*
btr_get_next_user_rec(
/*==================*/
192 193
	rec_t*	rec,	/*!< in: record on leaf level */
	mtr_t*	mtr);	/*!< in: mtr holding a latch on the page, and if
osku's avatar
osku committed
194
			needed, also to the next page */
195
/**************************************************************//**
osku's avatar
osku committed
196 197 198 199 200
Releases the latch on a leaf page and bufferunfixes it. */
UNIV_INLINE
void
btr_leaf_page_release(
/*==================*/
201 202
	buf_block_t*	block,		/*!< in: buffer block */
	ulint		latch_mode,	/*!< in: BTR_SEARCH_LEAF or
203
					BTR_MODIFY_LEAF */
204
	mtr_t*		mtr);		/*!< in: mtr */
205
/**************************************************************//**
206
Gets the child node file address in a node pointer.
207 208 209 210
NOTE: the offsets array must contain all offsets for the record since
we read the last field according to offsets and assume that it contains
the child page number. In other words offsets must have been retrieved
with rec_get_offsets(n_fields=ULINT_UNDEFINED).
211
@return	child node address */
osku's avatar
osku committed
212 213 214 215
UNIV_INLINE
ulint
btr_node_ptr_get_child_page_no(
/*===========================*/
216 217
	const rec_t*	rec,	/*!< in: node pointer record */
	const ulint*	offsets);/*!< in: array returned by rec_get_offsets() */
218
/************************************************************//**
219 220
Creates the root node for a new index tree.
@return	page number of the created root, FIL_NULL if did not succeed */
221
UNIV_INTERN
osku's avatar
osku committed
222 223 224
ulint
btr_create(
/*=======*/
225 226 227
	ulint		type,	/*!< in: type of the index */
	ulint		space,	/*!< in: space where created */
	ulint		zip_size,/*!< in: compressed page size in bytes
228
				or 0 for uncompressed pages */
229 230 231
	dulint		index_id,/*!< in: index id */
	dict_index_t*	index,	/*!< in: index */
	mtr_t*		mtr);	/*!< in: mini-transaction handle */
232
/************************************************************//**
osku's avatar
osku committed
233 234
Frees a B-tree except the root page, which MUST be freed after this
by calling btr_free_root. */
235
UNIV_INTERN
osku's avatar
osku committed
236 237 238
void
btr_free_but_not_root(
/*==================*/
239 240
	ulint	space,		/*!< in: space where created */
	ulint	zip_size,	/*!< in: compressed page size in bytes
241
				or 0 for uncompressed pages */
242
	ulint	root_page_no);	/*!< in: root page number */
243
/************************************************************//**
osku's avatar
osku committed
244
Frees the B-tree root page. Other tree MUST already have been freed. */
245
UNIV_INTERN
osku's avatar
osku committed
246 247 248
void
btr_free_root(
/*==========*/
249 250
	ulint	space,		/*!< in: space where created */
	ulint	zip_size,	/*!< in: compressed page size in bytes
251
				or 0 for uncompressed pages */
252 253
	ulint	root_page_no,	/*!< in: root page number */
	mtr_t*	mtr);		/*!< in: a mini-transaction which has already
osku's avatar
osku committed
254
				been started */
255
/*************************************************************//**
osku's avatar
osku committed
256 257 258 259
Makes tree one level higher by splitting the root, and inserts
the tuple. It is assumed that mtr contains an x-latch on the tree.
NOTE that the operation of this function must always succeed,
we cannot reverse it: therefore enough free disk space must be
260 261
guaranteed to be available before this function is called.
@return	inserted record */
262
UNIV_INTERN
osku's avatar
osku committed
263 264 265
rec_t*
btr_root_raise_and_insert(
/*======================*/
266
	btr_cur_t*	cursor,	/*!< in: cursor at which to insert: must be
osku's avatar
osku committed
267 268 269
				on the root page; when the function returns,
				the cursor is positioned on the predecessor
				of the inserted record */
270 271 272
	const dtuple_t*	tuple,	/*!< in: tuple to insert */
	ulint		n_ext,	/*!< in: number of externally stored columns */
	mtr_t*		mtr);	/*!< in: mtr */
273
/*************************************************************//**
274 275 276 277
Reorganizes an index page.
IMPORTANT: if btr_page_reorganize() is invoked on a compressed 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
278 279
modification will be redo-logged.
@return	TRUE on success, FALSE on failure */
280
UNIV_INTERN
281
ibool
osku's avatar
osku committed
282 283
btr_page_reorganize(
/*================*/
284 285 286
	buf_block_t*	block,	/*!< in: page to be reorganized */
	dict_index_t*	index,	/*!< in: record descriptor */
	mtr_t*		mtr);	/*!< in: mtr */
287
/*************************************************************//**
osku's avatar
osku committed
288
Decides if the page should be split at the convergence point of
289 290
inserts converging to left.
@return	TRUE if split recommended */
291
UNIV_INTERN
osku's avatar
osku committed
292 293 294
ibool
btr_page_get_split_rec_to_left(
/*===========================*/
295 296
	btr_cur_t*	cursor,	/*!< in: cursor at which to insert */
	rec_t**		split_rec);/*!< out: if split recommended,
osku's avatar
osku committed
297 298
				the first record on upper half page,
				or NULL if tuple should be first */
299
/*************************************************************//**
osku's avatar
osku committed
300
Decides if the page should be split at the convergence point of
301 302
inserts converging to right.
@return	TRUE if split recommended */
303
UNIV_INTERN
osku's avatar
osku committed
304 305 306
ibool
btr_page_get_split_rec_to_right(
/*============================*/
307 308
	btr_cur_t*	cursor,	/*!< in: cursor at which to insert */
	rec_t**		split_rec);/*!< out: if split recommended,
osku's avatar
osku committed
309 310
				the first record on upper half page,
				or NULL if tuple should be first */
311
/*************************************************************//**
osku's avatar
osku committed
312
Splits an index page to halves and inserts the tuple. It is assumed
313 314 315 316
that mtr holds an x-latch to the index tree. NOTE: the tree x-latch is
released within this function! NOTE that the operation of this
function must always succeed, we cannot reverse it: therefore enough
free disk space (2 pages) must be guaranteed to be available before
317
this function is called.
318 319

@return inserted record */
320
UNIV_INTERN
osku's avatar
osku committed
321 322 323
rec_t*
btr_page_split_and_insert(
/*======================*/
324
	btr_cur_t*	cursor,	/*!< in: cursor at which to insert; when the
osku's avatar
osku committed
325 326
				function returns, the cursor is positioned
				on the predecessor of the inserted record */
327 328 329
	const dtuple_t*	tuple,	/*!< in: tuple to insert */
	ulint		n_ext,	/*!< in: number of externally stored columns */
	mtr_t*		mtr);	/*!< in: mtr */
330
/*******************************************************//**
osku's avatar
osku committed
331 332
Inserts a data tuple to a tree on a non-leaf level. It is assumed
that mtr holds an x-latch on the tree. */
333
UNIV_INTERN
osku's avatar
osku committed
334
void
335 336
btr_insert_on_non_leaf_level_func(
/*==============================*/
337 338 339
	dict_index_t*	index,	/*!< in: index */
	ulint		level,	/*!< in: level, must be > 0 */
	dtuple_t*	tuple,	/*!< in: the record to be inserted */
340 341
	const char*	file,	/*!< in: file name */
	ulint		line,	/*!< in: line where called */
342
	mtr_t*		mtr);	/*!< in: mtr */
343 344
# define btr_insert_on_non_leaf_level(i,l,t,m)				\
	btr_insert_on_non_leaf_level_func(i,l,t,__FILE__,__LINE__,m)
345
#endif /* !UNIV_HOTBACKUP */
346
/****************************************************************//**
osku's avatar
osku committed
347
Sets a record as the predefined minimum record. */
348
UNIV_INTERN
osku's avatar
osku committed
349 350 351
void
btr_set_min_rec_mark(
/*=================*/
352 353
	rec_t*	rec,	/*!< in/out: record */
	mtr_t*	mtr);	/*!< in: mtr */
354
#ifndef UNIV_HOTBACKUP
355
/*************************************************************//**
osku's avatar
osku committed
356
Deletes on the upper level the node pointer to a page. */
357
UNIV_INTERN
osku's avatar
osku committed
358 359 360
void
btr_node_ptr_delete(
/*================*/
361 362 363
	dict_index_t*	index,	/*!< in: index tree */
	buf_block_t*	block,	/*!< in: page whose node pointer is deleted */
	mtr_t*		mtr);	/*!< in: mtr */
364
#ifdef UNIV_DEBUG
365
/************************************************************//**
366 367
Checks that the node pointer to a page is appropriate.
@return	TRUE */
368
UNIV_INTERN
osku's avatar
osku committed
369 370 371
ibool
btr_check_node_ptr(
/*===============*/
372 373 374
	dict_index_t*	index,	/*!< in: index tree */
	buf_block_t*	block,	/*!< in: index page */
	mtr_t*		mtr);	/*!< in: mtr */
375
#endif /* UNIV_DEBUG */
376
/*************************************************************//**
osku's avatar
osku committed
377 378 379 380 381 382 383
Tries to merge the page first to the left immediate brother if such a
brother exists, and the node pointers to the current page and to the
brother reside on the same page. If the left brother does not satisfy these
conditions, looks at the right brother. If the page is the only one on that
level lifts the records of the page to the father page, thus reducing the
tree height. It is assumed that mtr holds an x-latch on the tree and on the
page. If cursor is on the leaf level, mtr must also hold x-latches to
384 385
the brothers, if they exist.
@return	TRUE on success */
386
UNIV_INTERN
marko's avatar
marko committed
387
ibool
osku's avatar
osku committed
388 389
btr_compress(
/*=========*/
390
	btr_cur_t*	cursor,	/*!< in: cursor on the page to merge or lift;
osku's avatar
osku committed
391 392 393
				the page must not be empty: in record delete
				use btr_discard_page if the page would become
				empty */
394
	mtr_t*		mtr);	/*!< in: mtr */
395
/*************************************************************//**
osku's avatar
osku committed
396 397 398
Discards a page from a B-tree. This is used to remove the last record from
a B-tree page: the whole page must be removed at the same time. This cannot
be used for the root page, which is allowed to be empty. */
399
UNIV_INTERN
osku's avatar
osku committed
400 401 402
void
btr_discard_page(
/*=============*/
403
	btr_cur_t*	cursor,	/*!< in: cursor on the page to discard: not on
osku's avatar
osku committed
404
				the root page */
405
	mtr_t*		mtr);	/*!< in: mtr */
406
#endif /* !UNIV_HOTBACKUP */
407
/****************************************************************//**
osku's avatar
osku committed
408
Parses the redo log record for setting an index record as the predefined
409 410
minimum record.
@return	end of log record or NULL */
411
UNIV_INTERN
osku's avatar
osku committed
412 413 414
byte*
btr_parse_set_min_rec_mark(
/*=======================*/
415 416 417 418 419
	byte*	ptr,	/*!< in: buffer */
	byte*	end_ptr,/*!< in: buffer end */
	ulint	comp,	/*!< in: nonzero=compact page format */
	page_t*	page,	/*!< in: page or NULL */
	mtr_t*	mtr);	/*!< in: mtr or NULL */
420
/***********************************************************//**
421 422
Parses a redo log record of reorganizing a page.
@return	end of log record or NULL */
423
UNIV_INTERN
osku's avatar
osku committed
424 425 426
byte*
btr_parse_page_reorganize(
/*======================*/
427 428 429 430 431
	byte*		ptr,	/*!< in: buffer */
	byte*		end_ptr,/*!< in: buffer end */
	dict_index_t*	index,	/*!< in: record descriptor */
	buf_block_t*	block,	/*!< in: page to be reorganized, or NULL */
	mtr_t*		mtr);	/*!< in: mtr or NULL */
432
#ifndef UNIV_HOTBACKUP
433
/**************************************************************//**
434 435
Gets the number of pages in a B-tree.
@return	number of pages */
436
UNIV_INTERN
osku's avatar
osku committed
437 438 439
ulint
btr_get_size(
/*=========*/
440 441
	dict_index_t*	index,	/*!< in: index */
	ulint		flag);	/*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
442
/**************************************************************//**
osku's avatar
osku committed
443
Allocates a new file page to be used in an index tree. NOTE: we assume
444 445
that the caller has made the reservation for free extents!
@return	new allocated block, x-latched; NULL if out of space */
446
UNIV_INTERN
447
buf_block_t*
osku's avatar
osku committed
448 449
btr_page_alloc(
/*===========*/
450 451 452
	dict_index_t*	index,		/*!< in: index tree */
	ulint		hint_page_no,	/*!< in: hint of a good page */
	byte		file_direction,	/*!< in: direction where a possible
osku's avatar
osku committed
453
					page split is made */
454
	ulint		level,		/*!< in: level where the page is placed
osku's avatar
osku committed
455
					in the tree */
456
	mtr_t*		mtr);		/*!< in: mtr */
457
/**************************************************************//**
osku's avatar
osku committed
458 459
Frees a file page used in an index tree. NOTE: cannot free field external
storage pages because the page must contain info on its level. */
460
UNIV_INTERN
osku's avatar
osku committed
461 462 463
void
btr_page_free(
/*==========*/
464 465 466
	dict_index_t*	index,	/*!< in: index tree */
	buf_block_t*	block,	/*!< in: block to be freed, x-latched */
	mtr_t*		mtr);	/*!< in: mtr */
467
/**************************************************************//**
osku's avatar
osku committed
468 469 470
Frees a file page used in an index tree. Can be used also to BLOB
external storage pages, because the page level 0 can be given as an
argument. */
471
UNIV_INTERN
osku's avatar
osku committed
472 473 474
void
btr_page_free_low(
/*==============*/
475 476 477 478
	dict_index_t*	index,	/*!< in: index tree */
	buf_block_t*	block,	/*!< in: block to be freed, x-latched */
	ulint		level,	/*!< in: page level */
	mtr_t*		mtr);	/*!< in: mtr */
osku's avatar
osku committed
479
#ifdef UNIV_BTR_PRINT
480
/*************************************************************//**
osku's avatar
osku committed
481
Prints size info of a B-tree. */
482
UNIV_INTERN
osku's avatar
osku committed
483 484 485
void
btr_print_size(
/*===========*/
486
	dict_index_t*	index);	/*!< in: index tree */
487
/**************************************************************//**
488
Prints directories and other info of all nodes in the index. */
489
UNIV_INTERN
osku's avatar
osku committed
490
void
491 492
btr_print_index(
/*============*/
493 494
	dict_index_t*	index,	/*!< in: index */
	ulint		width);	/*!< in: print this many entries from start
osku's avatar
osku committed
495 496
				and end */
#endif /* UNIV_BTR_PRINT */
497
/************************************************************//**
osku's avatar
osku committed
498
Checks the size and number of fields in a record based on the definition of
499 500
the index.
@return	TRUE if ok */
501
UNIV_INTERN
osku's avatar
osku committed
502 503
ibool
btr_index_rec_validate(
504
/*===================*/
505 506 507
	const rec_t*		rec,		/*!< in: index record */
	const dict_index_t*	index,		/*!< in: index */
	ibool			dump_on_error);	/*!< in: TRUE if the function
508 509
						should print hex dump of record
						and page on error */
510
/**************************************************************//**
511 512
Checks the consistency of an index tree.
@return	TRUE if ok */
513
UNIV_INTERN
osku's avatar
osku committed
514
ibool
515 516
btr_validate_index(
/*===============*/
517 518
	dict_index_t*	index,	/*!< in: index */
	trx_t*		trx);	/*!< in: transaction or NULL */
osku's avatar
osku committed
519

520
#define BTR_N_LEAF_PAGES	1
osku's avatar
osku committed
521
#define BTR_TOTAL_SIZE		2
522
#endif /* !UNIV_HOTBACKUP */
osku's avatar
osku committed
523 524 525 526 527

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

528
#endif