1 | /***************************************************************************** |
2 | |
3 | Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. |
4 | Copyright (c) 2015, 2017, MariaDB Corporation. |
5 | |
6 | This program is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free Software |
8 | Foundation; version 2 of the License. |
9 | |
10 | This program is distributed in the hope that it will be useful, but WITHOUT |
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
12 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License along with |
15 | this program; if not, write to the Free Software Foundation, Inc., |
16 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
17 | |
18 | *****************************************************************************/ |
19 | |
20 | /**************************************************//** |
21 | @file include/btr0btr.ic |
22 | The B-tree |
23 | |
24 | Created 6/2/1994 Heikki Tuuri |
25 | *******************************************************/ |
26 | |
27 | #include "mach0data.h" |
28 | #include "mtr0mtr.h" |
29 | #include "mtr0log.h" |
30 | #include "page0zip.h" |
31 | |
32 | /** Gets a buffer page and declares its latching order level. |
33 | @param[in] page_id page id |
34 | @param[in] mode latch mode |
35 | @param[in] file file name |
36 | @param[in] line line where called |
37 | @param[in] index index tree, may be NULL if it is not an insert buffer |
38 | tree |
39 | @param[in,out] mtr mini-transaction |
40 | @return block */ |
41 | UNIV_INLINE |
42 | buf_block_t* |
43 | btr_block_get_func( |
44 | const page_id_t& page_id, |
45 | const page_size_t& page_size, |
46 | ulint mode, |
47 | const char* file, |
48 | unsigned line, |
49 | dict_index_t* index, |
50 | mtr_t* mtr) |
51 | { |
52 | buf_block_t* block; |
53 | dberr_t err=DB_SUCCESS; |
54 | |
55 | block = buf_page_get_gen( |
56 | page_id, page_size, mode, NULL, BUF_GET, file, line, mtr, &err); |
57 | |
58 | if (err == DB_DECRYPTION_FAILED) { |
59 | if (index && index->table) { |
60 | index->table->file_unreadable = true; |
61 | } |
62 | } |
63 | |
64 | if (block) { |
65 | if (mode != RW_NO_LATCH) { |
66 | |
67 | buf_block_dbg_add_level( |
68 | block, index != NULL && dict_index_is_ibuf(index) |
69 | ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE); |
70 | } |
71 | } |
72 | |
73 | return(block); |
74 | } |
75 | |
76 | /**************************************************************//** |
77 | Sets the index id field of a page. */ |
78 | UNIV_INLINE |
79 | void |
80 | btr_page_set_index_id( |
81 | /*==================*/ |
82 | page_t* page, /*!< in: page to be created */ |
83 | page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed |
84 | part will be updated, or NULL */ |
85 | index_id_t id, /*!< in: index id */ |
86 | mtr_t* mtr) /*!< in: mtr */ |
87 | { |
88 | if (page_zip) { |
89 | mach_write_to_8(page + (PAGE_HEADER + PAGE_INDEX_ID), id); |
90 | page_zip_write_header(page_zip, |
91 | page + (PAGE_HEADER + PAGE_INDEX_ID), |
92 | 8, mtr); |
93 | } else { |
94 | mlog_write_ull(page + (PAGE_HEADER + PAGE_INDEX_ID), id, mtr); |
95 | } |
96 | } |
97 | |
98 | /** Gets a buffer page and declares its latching order level. |
99 | @param space tablespace identifier |
100 | @param zip_size compressed page size in bytes or 0 for uncompressed pages |
101 | @param page_no page number |
102 | @param mode latch mode |
103 | @param idx index tree, may be NULL if not the insert buffer tree |
104 | @param mtr mini-transaction handle |
105 | @return the uncompressed page frame */ |
106 | UNIV_INLINE |
107 | page_t* |
108 | btr_page_get( |
109 | /*=========*/ |
110 | const page_id_t& page_id, |
111 | const page_size_t& page_size, |
112 | ulint mode, |
113 | dict_index_t* index, |
114 | mtr_t* mtr) |
115 | { |
116 | buf_block_t* block=NULL; |
117 | buf_frame_t* frame=NULL; |
118 | |
119 | block = btr_block_get(page_id, page_size, mode, index, mtr); |
120 | |
121 | if (block) { |
122 | frame = buf_block_get_frame(block); |
123 | } |
124 | |
125 | return ((page_t*)frame); |
126 | } |
127 | |
128 | /**************************************************************//** |
129 | Gets the index id field of a page. |
130 | @return index id */ |
131 | UNIV_INLINE |
132 | index_id_t |
133 | btr_page_get_index_id( |
134 | /*==================*/ |
135 | const page_t* page) /*!< in: index page */ |
136 | { |
137 | return(mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID)); |
138 | } |
139 | |
140 | /********************************************************//** |
141 | Sets the node level field in an index page. */ |
142 | UNIV_INLINE |
143 | void |
144 | btr_page_set_level( |
145 | /*===============*/ |
146 | page_t* page, /*!< in: index page */ |
147 | page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed |
148 | part will be updated, or NULL */ |
149 | ulint level, /*!< in: level, leaf level == 0 */ |
150 | mtr_t* mtr) /*!< in: mini-transaction handle */ |
151 | { |
152 | ut_ad(page != NULL); |
153 | ut_ad(mtr != NULL); |
154 | ut_ad(level <= BTR_MAX_NODE_LEVEL); |
155 | |
156 | if (page_zip) { |
157 | mach_write_to_2(page + (PAGE_HEADER + PAGE_LEVEL), level); |
158 | page_zip_write_header(page_zip, |
159 | page + (PAGE_HEADER + PAGE_LEVEL), |
160 | 2, mtr); |
161 | } else { |
162 | mlog_write_ulint(page + (PAGE_HEADER + PAGE_LEVEL), level, |
163 | MLOG_2BYTES, mtr); |
164 | } |
165 | } |
166 | |
167 | /********************************************************//** |
168 | Gets the next index page number. |
169 | @return next page number */ |
170 | UNIV_INLINE |
171 | ulint |
172 | btr_page_get_next( |
173 | /*==============*/ |
174 | const page_t* page, /*!< in: index page */ |
175 | mtr_t* mtr MY_ATTRIBUTE((unused))) |
176 | /*!< in: mini-transaction handle */ |
177 | { |
178 | ut_ad(page != NULL); |
179 | ut_ad(mtr != NULL); |
180 | |
181 | return(mach_read_from_4(page + FIL_PAGE_NEXT)); |
182 | } |
183 | |
184 | /********************************************************//** |
185 | Sets the next index page field. */ |
186 | UNIV_INLINE |
187 | void |
188 | btr_page_set_next( |
189 | /*==============*/ |
190 | page_t* page, /*!< in: index page */ |
191 | page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed |
192 | part will be updated, or NULL */ |
193 | ulint next, /*!< in: next page number */ |
194 | mtr_t* mtr) /*!< in: mini-transaction handle */ |
195 | { |
196 | ut_ad(page != NULL); |
197 | ut_ad(mtr != NULL); |
198 | |
199 | if (page_zip) { |
200 | mach_write_to_4(page + FIL_PAGE_NEXT, next); |
201 | page_zip_write_header(page_zip, page + FIL_PAGE_NEXT, 4, mtr); |
202 | } else { |
203 | mlog_write_ulint(page + FIL_PAGE_NEXT, next, MLOG_4BYTES, mtr); |
204 | } |
205 | } |
206 | |
207 | /********************************************************//** |
208 | Gets the previous index page number. |
209 | @return prev page number */ |
210 | UNIV_INLINE |
211 | ulint |
212 | btr_page_get_prev( |
213 | /*==============*/ |
214 | const page_t* page, /*!< in: index page */ |
215 | mtr_t* mtr MY_ATTRIBUTE((unused))) /*!< in: mini-transaction handle */ |
216 | { |
217 | ut_ad(page != NULL); |
218 | ut_ad(mtr != NULL); |
219 | |
220 | return(mach_read_from_4(page + FIL_PAGE_PREV)); |
221 | } |
222 | |
223 | /********************************************************//** |
224 | Sets the previous index page field. */ |
225 | UNIV_INLINE |
226 | void |
227 | btr_page_set_prev( |
228 | /*==============*/ |
229 | page_t* page, /*!< in: index page */ |
230 | page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed |
231 | part will be updated, or NULL */ |
232 | ulint prev, /*!< in: previous page number */ |
233 | mtr_t* mtr) /*!< in: mini-transaction handle */ |
234 | { |
235 | ut_ad(page != NULL); |
236 | ut_ad(mtr != NULL); |
237 | |
238 | if (page_zip) { |
239 | mach_write_to_4(page + FIL_PAGE_PREV, prev); |
240 | page_zip_write_header(page_zip, page + FIL_PAGE_PREV, 4, mtr); |
241 | } else { |
242 | mlog_write_ulint(page + FIL_PAGE_PREV, prev, MLOG_4BYTES, mtr); |
243 | } |
244 | } |
245 | |
246 | /**************************************************************//** |
247 | Gets the child node file address in a node pointer. |
248 | NOTE: the offsets array must contain all offsets for the record since |
249 | we read the last field according to offsets and assume that it contains |
250 | the child page number. In other words offsets must have been retrieved |
251 | with rec_get_offsets(n_fields=ULINT_UNDEFINED). |
252 | @return child node address */ |
253 | UNIV_INLINE |
254 | ulint |
255 | btr_node_ptr_get_child_page_no( |
256 | /*===========================*/ |
257 | const rec_t* rec, /*!< in: node pointer record */ |
258 | const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ |
259 | { |
260 | const byte* field; |
261 | ulint len; |
262 | ulint page_no; |
263 | |
264 | ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec)); |
265 | |
266 | /* The child address is in the last field */ |
267 | field = rec_get_nth_field(rec, offsets, |
268 | rec_offs_n_fields(offsets) - 1, &len); |
269 | |
270 | ut_ad(len == 4); |
271 | |
272 | page_no = mach_read_from_4(field); |
273 | ut_ad(page_no > 1); |
274 | |
275 | return(page_no); |
276 | } |
277 | |
278 | /**************************************************************//** |
279 | Releases the latches on a leaf page and bufferunfixes it. */ |
280 | UNIV_INLINE |
281 | void |
282 | btr_leaf_page_release( |
283 | /*==================*/ |
284 | buf_block_t* block, /*!< in: buffer block */ |
285 | ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or |
286 | BTR_MODIFY_LEAF */ |
287 | mtr_t* mtr) /*!< in: mtr */ |
288 | { |
289 | ut_ad(latch_mode == BTR_SEARCH_LEAF |
290 | || latch_mode == BTR_MODIFY_LEAF |
291 | || latch_mode == BTR_NO_LATCHES); |
292 | |
293 | ut_ad(!mtr_memo_contains(mtr, block, MTR_MEMO_MODIFY)); |
294 | |
295 | ulint mode; |
296 | switch (latch_mode) { |
297 | case BTR_SEARCH_LEAF: |
298 | mode = MTR_MEMO_PAGE_S_FIX; |
299 | break; |
300 | case BTR_MODIFY_LEAF: |
301 | mode = MTR_MEMO_PAGE_X_FIX; |
302 | break; |
303 | case BTR_NO_LATCHES: |
304 | mode = MTR_MEMO_BUF_FIX; |
305 | break; |
306 | default: |
307 | ut_a(0); |
308 | } |
309 | |
310 | mtr->memo_release(block, mode); |
311 | } |
312 | |