1
/*****************************************************************************
3
Copyright (c) 1994, 2011, Oracle and/or its affiliates. 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/btr0btr.ic
23
Created 6/2/1994 Heikki Tuuri
24
*******************************************************/
26
#include "mach0data.h"
27
#ifndef UNIV_HOTBACKUP
32
#define BTR_MAX_NODE_LEVEL 50 /*!< Maximum B-tree page level
33
(not really a hard limit).
34
Used in debug assertions
35
in btr_page_set_level and
36
btr_page_get_level_low */
38
/**************************************************************//**
39
Gets a buffer page and declares its latching order level. */
44
ulint space, /*!< in: space id */
45
ulint zip_size, /*!< in: compressed page size in bytes
46
or 0 for uncompressed pages */
47
ulint page_no, /*!< in: page number */
48
ulint mode, /*!< in: latch mode */
49
const char* file, /*!< in: file name */
50
ulint line, /*!< in: line where called */
51
#ifdef UNIV_SYNC_DEBUG
52
const dict_index_t* index, /*!< in: index tree, may be NULL
53
if it is not an insert buffer tree */
54
#endif /* UNIV_SYNC_DEBUG */
55
mtr_t* mtr) /*!< in/out: mtr */
59
block = buf_page_get_gen(space, zip_size, page_no, mode,
60
NULL, BUF_GET, file, line, mtr);
62
if (mode != RW_NO_LATCH) {
64
buf_block_dbg_add_level(
65
block, index != NULL && dict_index_is_ibuf(index)
66
? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
72
/**************************************************************//**
73
Sets the index id field of a page. */
76
btr_page_set_index_id(
77
/*==================*/
78
page_t* page, /*!< in: page to be created */
79
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
80
part will be updated, or NULL */
81
index_id_t id, /*!< in: index id */
82
mtr_t* mtr) /*!< in: mtr */
84
if (UNIV_LIKELY_NULL(page_zip)) {
85
mach_write_to_8(page + (PAGE_HEADER + PAGE_INDEX_ID), id);
86
page_zip_write_header(page_zip,
87
page + (PAGE_HEADER + PAGE_INDEX_ID),
90
mlog_write_ull(page + (PAGE_HEADER + PAGE_INDEX_ID), id, mtr);
93
#endif /* !UNIV_HOTBACKUP */
95
/**************************************************************//**
96
Gets the index id field of a page.
100
btr_page_get_index_id(
101
/*==================*/
102
const page_t* page) /*!< in: index page */
104
return(mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID));
107
#ifndef UNIV_HOTBACKUP
108
/********************************************************//**
109
Gets the node level field in an index page.
110
@return level, leaf level == 0 */
113
btr_page_get_level_low(
114
/*===================*/
115
const page_t* page) /*!< in: index page */
121
level = mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL);
123
ut_ad(level <= BTR_MAX_NODE_LEVEL);
128
/********************************************************//**
129
Gets the node level field in an index page.
130
@return level, leaf level == 0 */
135
const page_t* page, /*!< in: index page */
136
mtr_t* mtr __attribute__((unused)))
137
/*!< in: mini-transaction handle */
141
return(btr_page_get_level_low(page));
144
/********************************************************//**
145
Sets the node level field in an index page. */
150
page_t* page, /*!< in: index page */
151
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
152
part will be updated, or NULL */
153
ulint level, /*!< in: level, leaf level == 0 */
154
mtr_t* mtr) /*!< in: mini-transaction handle */
157
ut_ad(level <= BTR_MAX_NODE_LEVEL);
159
if (UNIV_LIKELY_NULL(page_zip)) {
160
mach_write_to_2(page + (PAGE_HEADER + PAGE_LEVEL), level);
161
page_zip_write_header(page_zip,
162
page + (PAGE_HEADER + PAGE_LEVEL),
165
mlog_write_ulint(page + (PAGE_HEADER + PAGE_LEVEL), level,
170
/********************************************************//**
171
Gets the next index page number.
172
@return next page number */
177
const page_t* page, /*!< in: index page */
178
mtr_t* mtr __attribute__((unused)))
179
/*!< in: mini-transaction handle */
182
ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX)
183
|| mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_S_FIX));
185
return(mach_read_from_4(page + FIL_PAGE_NEXT));
188
/********************************************************//**
189
Sets the next index page field. */
194
page_t* page, /*!< in: index page */
195
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
196
part will be updated, or NULL */
197
ulint next, /*!< in: next page number */
198
mtr_t* mtr) /*!< in: mini-transaction handle */
202
if (UNIV_LIKELY_NULL(page_zip)) {
203
mach_write_to_4(page + FIL_PAGE_NEXT, next);
204
page_zip_write_header(page_zip, page + FIL_PAGE_NEXT, 4, mtr);
206
mlog_write_ulint(page + FIL_PAGE_NEXT, next, MLOG_4BYTES, mtr);
210
/********************************************************//**
211
Gets the previous index page number.
212
@return prev page number */
217
const page_t* page, /*!< in: index page */
218
mtr_t* mtr __attribute__((unused))) /*!< in: mini-transaction handle */
222
return(mach_read_from_4(page + FIL_PAGE_PREV));
225
/********************************************************//**
226
Sets the previous index page field. */
231
page_t* page, /*!< in: index page */
232
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
233
part will be updated, or NULL */
234
ulint prev, /*!< in: previous page number */
235
mtr_t* mtr) /*!< in: mini-transaction handle */
239
if (UNIV_LIKELY_NULL(page_zip)) {
240
mach_write_to_4(page + FIL_PAGE_PREV, prev);
241
page_zip_write_header(page_zip, page + FIL_PAGE_PREV, 4, mtr);
243
mlog_write_ulint(page + FIL_PAGE_PREV, prev, MLOG_4BYTES, mtr);
247
/**************************************************************//**
248
Gets the child node file address in a node pointer.
249
NOTE: the offsets array must contain all offsets for the record since
250
we read the last field according to offsets and assume that it contains
251
the child page number. In other words offsets must have been retrieved
252
with rec_get_offsets(n_fields=ULINT_UNDEFINED).
253
@return child node address */
256
btr_node_ptr_get_child_page_no(
257
/*===========================*/
258
const rec_t* rec, /*!< in: node pointer record */
259
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
265
ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec));
267
/* The child address is in the last field */
268
field = rec_get_nth_field(rec, offsets,
269
rec_offs_n_fields(offsets) - 1, &len);
273
page_no = mach_read_from_4(field);
275
if (UNIV_UNLIKELY(page_no == 0)) {
277
"InnoDB: a nonsensical page number 0"
278
" in a node ptr record at offset %lu\n",
279
(ulong) page_offset(rec));
280
buf_page_print(page_align(rec), 0);
286
/**************************************************************//**
287
Releases the latches on a leaf page and bufferunfixes it. */
290
btr_leaf_page_release(
291
/*==================*/
292
buf_block_t* block, /*!< in: buffer block */
293
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
295
mtr_t* mtr) /*!< in: mtr */
297
ut_ad(latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF);
298
ut_ad(!mtr_memo_contains(mtr, block, MTR_MEMO_MODIFY));
300
mtr_memo_release(mtr, block,
301
latch_mode == BTR_SEARCH_LEAF
302
? MTR_MEMO_PAGE_S_FIX
303
: MTR_MEMO_PAGE_X_FIX);
305
#endif /* !UNIV_HOTBACKUP */