1
by brian
clean slate |
1 |
/******************************************************
|
2 |
The B-tree
|
|
3 |
||
4 |
(c) 1994-1996 Innobase Oy
|
|
5 |
||
6 |
Created 6/2/1994 Heikki Tuuri
|
|
7 |
*******************************************************/
|
|
8 |
||
9 |
#include "mach0data.h" |
|
10 |
#include "mtr0mtr.h" |
|
11 |
#include "mtr0log.h" |
|
12 |
||
13 |
#define BTR_MAX_NODE_LEVEL 50 /* used in debug checking */ |
|
14 |
||
15 |
/******************************************************************
|
|
16 |
Gets a buffer page and declares its latching order level. */
|
|
17 |
UNIV_INLINE
|
|
18 |
page_t* |
|
19 |
btr_page_get( |
|
20 |
/*=========*/
|
|
21 |
ulint space, /* in: space id */ |
|
22 |
ulint page_no, /* in: page number */ |
|
23 |
ulint mode, /* in: latch mode */ |
|
24 |
mtr_t* mtr) /* in: mtr */ |
|
25 |
{
|
|
26 |
page_t* page; |
|
27 |
||
28 |
page = buf_page_get(space, page_no, mode, mtr); |
|
29 |
#ifdef UNIV_SYNC_DEBUG
|
|
30 |
if (mode != RW_NO_LATCH) { |
|
31 |
||
32 |
buf_page_dbg_add_level(page, SYNC_TREE_NODE); |
|
33 |
}
|
|
34 |
#endif
|
|
35 |
return(page); |
|
36 |
}
|
|
37 |
||
38 |
/******************************************************************
|
|
39 |
Sets the index id field of a page. */
|
|
40 |
UNIV_INLINE
|
|
41 |
void
|
|
42 |
btr_page_set_index_id( |
|
43 |
/*==================*/
|
|
44 |
page_t* page, /* in: page to be created */ |
|
45 |
dulint id, /* in: index id */ |
|
46 |
mtr_t* mtr) /* in: mtr */ |
|
47 |
{
|
|
48 |
mlog_write_dulint(page + PAGE_HEADER + PAGE_INDEX_ID, id, mtr); |
|
49 |
}
|
|
50 |
||
51 |
/******************************************************************
|
|
52 |
Gets the index id field of a page. */
|
|
53 |
UNIV_INLINE
|
|
54 |
dulint
|
|
55 |
btr_page_get_index_id( |
|
56 |
/*==================*/
|
|
57 |
/* out: index id */
|
|
58 |
page_t* page) /* in: index page */ |
|
59 |
{
|
|
60 |
return(mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID)); |
|
61 |
}
|
|
62 |
||
63 |
/************************************************************
|
|
64 |
Gets the node level field in an index page. */
|
|
65 |
UNIV_INLINE
|
|
66 |
ulint
|
|
67 |
btr_page_get_level_low( |
|
68 |
/*===================*/
|
|
69 |
/* out: level, leaf level == 0 */
|
|
70 |
page_t* page) /* in: index page */ |
|
71 |
{
|
|
72 |
ulint level; |
|
73 |
||
74 |
ut_ad(page); |
|
75 |
||
76 |
level = mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL); |
|
77 |
||
78 |
ut_ad(level <= BTR_MAX_NODE_LEVEL); |
|
79 |
||
80 |
return(level); |
|
81 |
}
|
|
82 |
||
83 |
/************************************************************
|
|
84 |
Gets the node level field in an index page. */
|
|
85 |
UNIV_INLINE
|
|
86 |
ulint
|
|
87 |
btr_page_get_level( |
|
88 |
/*===============*/
|
|
89 |
/* out: level, leaf level == 0 */
|
|
90 |
page_t* page, /* in: index page */ |
|
91 |
mtr_t* mtr __attribute__((unused))) /* in: mini-transaction handle */ |
|
92 |
{
|
|
93 |
ut_ad(page && mtr); |
|
94 |
||
95 |
return(btr_page_get_level_low(page)); |
|
96 |
}
|
|
97 |
||
98 |
/************************************************************
|
|
99 |
Sets the node level field in an index page. */
|
|
100 |
UNIV_INLINE
|
|
101 |
void
|
|
102 |
btr_page_set_level( |
|
103 |
/*===============*/
|
|
104 |
page_t* page, /* in: index page */ |
|
105 |
ulint level, /* in: level, leaf level == 0 */ |
|
106 |
mtr_t* mtr) /* in: mini-transaction handle */ |
|
107 |
{
|
|
108 |
ut_ad(page && mtr); |
|
109 |
ut_ad(level <= BTR_MAX_NODE_LEVEL); |
|
110 |
||
111 |
mlog_write_ulint(page + PAGE_HEADER + PAGE_LEVEL, level, |
|
112 |
MLOG_2BYTES, mtr); |
|
113 |
}
|
|
114 |
||
115 |
/************************************************************
|
|
116 |
Gets the next index page number. */
|
|
117 |
UNIV_INLINE
|
|
118 |
ulint
|
|
119 |
btr_page_get_next( |
|
120 |
/*==============*/
|
|
121 |
/* out: next page number */
|
|
122 |
page_t* page, /* in: index page */ |
|
123 |
mtr_t* mtr __attribute__((unused))) /* in: mini-transaction handle */ |
|
124 |
{
|
|
125 |
ut_ad(page && mtr); |
|
126 |
ut_ad(mtr_memo_contains(mtr, buf_block_align(page), |
|
127 |
MTR_MEMO_PAGE_X_FIX) |
|
128 |
|| mtr_memo_contains(mtr, buf_block_align(page), |
|
129 |
MTR_MEMO_PAGE_S_FIX)); |
|
130 |
||
131 |
return(mach_read_from_4(page + FIL_PAGE_NEXT)); |
|
132 |
}
|
|
133 |
||
134 |
/************************************************************
|
|
135 |
Sets the next index page field. */
|
|
136 |
UNIV_INLINE
|
|
137 |
void
|
|
138 |
btr_page_set_next( |
|
139 |
/*==============*/
|
|
140 |
page_t* page, /* in: index page */ |
|
141 |
ulint next, /* in: next page number */ |
|
142 |
mtr_t* mtr) /* in: mini-transaction handle */ |
|
143 |
{
|
|
144 |
ut_ad(page && mtr); |
|
145 |
||
146 |
mlog_write_ulint(page + FIL_PAGE_NEXT, next, MLOG_4BYTES, mtr); |
|
147 |
}
|
|
148 |
||
149 |
/************************************************************
|
|
150 |
Gets the previous index page number. */
|
|
151 |
UNIV_INLINE
|
|
152 |
ulint
|
|
153 |
btr_page_get_prev( |
|
154 |
/*==============*/
|
|
155 |
/* out: prev page number */
|
|
156 |
page_t* page, /* in: index page */ |
|
157 |
mtr_t* mtr __attribute__((unused))) /* in: mini-transaction handle */ |
|
158 |
{
|
|
159 |
ut_ad(page && mtr); |
|
160 |
||
161 |
return(mach_read_from_4(page + FIL_PAGE_PREV)); |
|
162 |
}
|
|
163 |
||
164 |
/************************************************************
|
|
165 |
Sets the previous index page field. */
|
|
166 |
UNIV_INLINE
|
|
167 |
void
|
|
168 |
btr_page_set_prev( |
|
169 |
/*==============*/
|
|
170 |
page_t* page, /* in: index page */ |
|
171 |
ulint prev, /* in: previous page number */ |
|
172 |
mtr_t* mtr) /* in: mini-transaction handle */ |
|
173 |
{
|
|
174 |
ut_ad(page && mtr); |
|
175 |
||
176 |
mlog_write_ulint(page + FIL_PAGE_PREV, prev, MLOG_4BYTES, mtr); |
|
177 |
}
|
|
178 |
||
179 |
/******************************************************************
|
|
180 |
Gets the child node file address in a node pointer. */
|
|
181 |
UNIV_INLINE
|
|
182 |
ulint
|
|
183 |
btr_node_ptr_get_child_page_no( |
|
184 |
/*===========================*/
|
|
185 |
/* out: child node address */
|
|
186 |
rec_t* rec, /* in: node pointer record */ |
|
187 |
const ulint* offsets)/* in: array returned by rec_get_offsets() */ |
|
188 |
{
|
|
189 |
byte* field; |
|
190 |
ulint len; |
|
191 |
ulint page_no; |
|
192 |
||
193 |
ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec)); |
|
194 |
||
195 |
/* The child address is in the last field */
|
|
196 |
field = rec_get_nth_field(rec, offsets, |
|
197 |
rec_offs_n_fields(offsets) - 1, &len); |
|
198 |
||
199 |
ut_ad(len == 4); |
|
200 |
||
201 |
page_no = mach_read_from_4(field); |
|
202 |
||
203 |
if (UNIV_UNLIKELY(page_no == 0)) { |
|
204 |
fprintf(stderr, |
|
205 |
"InnoDB: a nonsensical page number 0"
|
|
206 |
" in a node ptr record at offset %lu\n", |
|
207 |
(ulong) page_offset(rec)); |
|
208 |
buf_page_print(buf_frame_align(rec)); |
|
209 |
}
|
|
210 |
||
211 |
return(page_no); |
|
212 |
}
|
|
213 |
||
214 |
/******************************************************************
|
|
215 |
Releases the latches on a leaf page and bufferunfixes it. */
|
|
216 |
UNIV_INLINE
|
|
217 |
void
|
|
218 |
btr_leaf_page_release( |
|
219 |
/*==================*/
|
|
220 |
page_t* page, /* in: page */ |
|
221 |
ulint latch_mode, /* in: BTR_SEARCH_LEAF or BTR_MODIFY_LEAF */ |
|
222 |
mtr_t* mtr) /* in: mtr */ |
|
223 |
{
|
|
224 |
ut_ad(!mtr_memo_contains(mtr, buf_block_align(page), |
|
225 |
MTR_MEMO_MODIFY)); |
|
226 |
if (latch_mode == BTR_SEARCH_LEAF) { |
|
227 |
mtr_memo_release(mtr, buf_block_align(page), |
|
228 |
MTR_MEMO_PAGE_S_FIX); |
|
229 |
} else { |
|
230 |
ut_ad(latch_mode == BTR_MODIFY_LEAF); |
|
231 |
mtr_memo_release(mtr, buf_block_align(page), |
|
232 |
MTR_MEMO_PAGE_X_FIX); |
|
233 |
}
|
|
234 |
}
|