1 | /***************************************************************************** |
2 | |
3 | Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. |
4 | Copyright (c) 2014, 2018, 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/fsp0types.h |
22 | File space management types |
23 | |
24 | Created May 26, 2009 Vasil Dimov |
25 | *******************************************************/ |
26 | |
27 | #ifndef fsp0types_h |
28 | #define fsp0types_h |
29 | |
30 | #ifndef UNIV_INNOCHECKSUM |
31 | |
32 | /** The fil_space_t::id of the redo log. All persistent tablespaces |
33 | have a smaller fil_space_t::id. */ |
34 | #define SRV_LOG_SPACE_FIRST_ID 0xFFFFFFF0U |
35 | /** The fil_space_t::id of the innodb_temporary tablespace. */ |
36 | #define SRV_TMP_SPACE_ID 0xFFFFFFFEU |
37 | |
38 | #include "univ.i" |
39 | #include "ut0byte.h" |
40 | |
41 | /** @name Flags for inserting records in order |
42 | If records are inserted in order, there are the following |
43 | flags to tell this (their type is made byte for the compiler |
44 | to warn if direction and hint parameters are switched in |
45 | fseg_alloc_free_page) */ |
46 | /* @{ */ |
47 | #define FSP_UP ((byte)111) /*!< alphabetically upwards */ |
48 | #define FSP_DOWN ((byte)112) /*!< alphabetically downwards */ |
49 | #define FSP_NO_DIR ((byte)113) /*!< no order */ |
50 | /* @} */ |
51 | |
52 | #endif /* !UNIV_INNOCHECKSUM */ |
53 | /** File space extent size in pages |
54 | page size | file space extent size |
55 | ----------+----------------------- |
56 | 4 KiB | 256 pages = 1 MiB |
57 | 8 KiB | 128 pages = 1 MiB |
58 | 16 KiB | 64 pages = 1 MiB |
59 | 32 KiB | 64 pages = 2 MiB |
60 | 64 KiB | 64 pages = 4 MiB |
61 | */ |
62 | #define FSP_EXTENT_SIZE (srv_page_size_shift < 14 ? \ |
63 | (1048576U >> srv_page_size_shift) : 64U) |
64 | |
65 | /** File space extent size (four megabyte) in pages for MAX page size */ |
66 | #define FSP_EXTENT_SIZE_MAX (4194304 / UNIV_PAGE_SIZE_MAX) |
67 | |
68 | /** File space extent size (one megabyte) in pages for MIN page size */ |
69 | #define FSP_EXTENT_SIZE_MIN (1048576 / UNIV_PAGE_SIZE_MIN) |
70 | |
71 | /** On a page of any file segment, data may be put starting from this |
72 | offset */ |
73 | #define FSEG_PAGE_DATA FIL_PAGE_DATA |
74 | |
75 | #ifndef UNIV_INNOCHECKSUM |
76 | /** @name File segment header |
77 | The file segment header points to the inode describing the file segment. */ |
78 | /* @{ */ |
79 | /** Data type for file segment header */ |
80 | typedef byte fseg_header_t; |
81 | |
82 | #define FSEG_HDR_SPACE 0 /*!< space id of the inode */ |
83 | #define FSEG_HDR_PAGE_NO 4 /*!< page number of the inode */ |
84 | #define FSEG_HDR_OFFSET 8 /*!< byte offset of the inode */ |
85 | |
86 | #define FSEG_HEADER_SIZE 10 /*!< Length of the file system |
87 | header, in bytes */ |
88 | /* @} */ |
89 | |
90 | #ifdef UNIV_DEBUG |
91 | |
92 | struct mtr_t; |
93 | |
94 | /** A wrapper class to print the file segment header information. */ |
95 | class fseg_header |
96 | { |
97 | public: |
98 | /** Constructor of fseg_header. |
99 | @param[in] header the underlying file segment header object |
100 | @param[in] mtr the mini-transaction. No redo logs are |
101 | generated, only latches are checked within |
102 | mini-transaction */ |
103 | fseg_header( |
104 | const fseg_header_t* header, |
105 | mtr_t* mtr) |
106 | : |
107 | m_header(header), |
108 | m_mtr(mtr) |
109 | {} |
110 | |
111 | /** Print the file segment header to the given output stream. |
112 | @param[in,out] out the output stream into which the object |
113 | is printed. |
114 | @retval the output stream into which the object was printed. */ |
115 | std::ostream& |
116 | to_stream(std::ostream& out) const; |
117 | private: |
118 | /** The underlying file segment header */ |
119 | const fseg_header_t* m_header; |
120 | |
121 | /** The mini transaction, which is used mainly to check whether |
122 | appropriate latches have been taken by the calling thread. */ |
123 | mtr_t* m_mtr; |
124 | }; |
125 | |
126 | /* Overloading the global output operator to print a file segment header |
127 | @param[in,out] out the output stream into which object will be printed |
128 | @param[in] header the file segment header to be printed |
129 | @retval the output stream */ |
130 | inline |
131 | std::ostream& |
132 | operator<<( |
133 | std::ostream& out, |
134 | const fseg_header& header) |
135 | { |
136 | return(header.to_stream(out)); |
137 | } |
138 | #endif /* UNIV_DEBUG */ |
139 | |
140 | /** Flags for fsp_reserve_free_extents */ |
141 | enum fsp_reserve_t { |
142 | FSP_NORMAL, /* reservation during normal B-tree operations */ |
143 | FSP_UNDO, /* reservation done for undo logging */ |
144 | FSP_CLEANING, /* reservation done during purge operations */ |
145 | FSP_BLOB /* reservation being done for BLOB insertion */ |
146 | }; |
147 | |
148 | /* Number of pages described in a single descriptor page: currently each page |
149 | description takes less than 1 byte; a descriptor page is repeated every |
150 | this many file pages */ |
151 | /* #define XDES_DESCRIBED_PER_PAGE srv_page_size */ |
152 | /* This has been replaced with either srv_page_size or page_zip->size. */ |
153 | |
154 | /** @name The space low address page map |
155 | The pages at FSP_XDES_OFFSET and FSP_IBUF_BITMAP_OFFSET are repeated |
156 | every XDES_DESCRIBED_PER_PAGE pages in every tablespace. */ |
157 | /* @{ */ |
158 | /*--------------------------------------*/ |
159 | #define FSP_XDES_OFFSET 0U /* !< extent descriptor */ |
160 | #define FSP_IBUF_BITMAP_OFFSET 1U /* !< insert buffer bitmap */ |
161 | /* The ibuf bitmap pages are the ones whose |
162 | page number is the number above plus a |
163 | multiple of XDES_DESCRIBED_PER_PAGE */ |
164 | |
165 | #define FSP_FIRST_INODE_PAGE_NO 2U /*!< in every tablespace */ |
166 | /* The following pages exist |
167 | in the system tablespace (space 0). */ |
168 | #define FSP_IBUF_HEADER_PAGE_NO 3U /*!< insert buffer |
169 | header page, in |
170 | tablespace 0 */ |
171 | #define FSP_IBUF_TREE_ROOT_PAGE_NO 4U /*!< insert buffer |
172 | B-tree root page in |
173 | tablespace 0 */ |
174 | /* The ibuf tree root page number in |
175 | tablespace 0; its fseg inode is on the page |
176 | number FSP_FIRST_INODE_PAGE_NO */ |
177 | #define FSP_TRX_SYS_PAGE_NO 5U /*!< transaction |
178 | system header, in |
179 | tablespace 0 */ |
180 | #define FSP_FIRST_RSEG_PAGE_NO 6U /*!< first rollback segment |
181 | page, in tablespace 0 */ |
182 | #define FSP_DICT_HDR_PAGE_NO 7U /*!< data dictionary header |
183 | page, in tablespace 0 */ |
184 | /*--------------------------------------*/ |
185 | /* @} */ |
186 | |
187 | /** Check if tablespace is system temporary. |
188 | @param[in] space_id verify is checksum is enabled for given space. |
189 | @return true if tablespace is system temporary. */ |
190 | inline |
191 | bool |
192 | fsp_is_system_temporary(ulint space_id) |
193 | { |
194 | return(space_id == SRV_TMP_SPACE_ID); |
195 | } |
196 | #endif /* !UNIV_INNOCHECKSUM */ |
197 | |
198 | /* @defgroup fsp_flags InnoDB Tablespace Flag Constants @{ */ |
199 | |
200 | /** Width of the POST_ANTELOPE flag */ |
201 | #define FSP_FLAGS_WIDTH_POST_ANTELOPE 1 |
202 | /** Number of flag bits used to indicate the tablespace zip page size */ |
203 | #define FSP_FLAGS_WIDTH_ZIP_SSIZE 4 |
204 | /** Width of the ATOMIC_BLOBS flag. The ability to break up a long |
205 | column into an in-record prefix and an externally stored part is available |
206 | to ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT. */ |
207 | #define FSP_FLAGS_WIDTH_ATOMIC_BLOBS 1 |
208 | /** Number of flag bits used to indicate the tablespace page size */ |
209 | #define FSP_FLAGS_WIDTH_PAGE_SSIZE 4 |
210 | /** Number of reserved bits */ |
211 | #define FSP_FLAGS_WIDTH_RESERVED 6 |
212 | /** Number of flag bits used to indicate the page compression */ |
213 | #define FSP_FLAGS_WIDTH_PAGE_COMPRESSION 1 |
214 | |
215 | /** Width of all the currently known persistent tablespace flags */ |
216 | #define FSP_FLAGS_WIDTH (FSP_FLAGS_WIDTH_POST_ANTELOPE \ |
217 | + FSP_FLAGS_WIDTH_ZIP_SSIZE \ |
218 | + FSP_FLAGS_WIDTH_ATOMIC_BLOBS \ |
219 | + FSP_FLAGS_WIDTH_PAGE_SSIZE \ |
220 | + FSP_FLAGS_WIDTH_RESERVED \ |
221 | + FSP_FLAGS_WIDTH_PAGE_COMPRESSION) |
222 | |
223 | /** A mask of all the known/used bits in FSP_SPACE_FLAGS */ |
224 | #define FSP_FLAGS_MASK (~(~0U << FSP_FLAGS_WIDTH)) |
225 | |
226 | /* FSP_SPACE_FLAGS position and name in MySQL 5.6/MariaDB 10.0 or older |
227 | and MariaDB 10.1.20 or older MariaDB 10.1 and in MariaDB 10.1.21 |
228 | or newer. |
229 | MySQL 5.6 MariaDB 10.1.x MariaDB 10.1.21 |
230 | ==================================================================== |
231 | Below flags in same offset |
232 | ==================================================================== |
233 | 0: POST_ANTELOPE 0:POST_ANTELOPE 0: POST_ANTELOPE |
234 | 1..4: ZIP_SSIZE(0..5) 1..4:ZIP_SSIZE(0..5) 1..4: ZIP_SSIZE(0..5) |
235 | (NOTE: bit 4 is always 0) |
236 | 5: ATOMIC_BLOBS 5:ATOMIC_BLOBS 5: ATOMIC_BLOBS |
237 | ===================================================================== |
238 | Below note the order difference: |
239 | ===================================================================== |
240 | 6..9: PAGE_SSIZE(3..7) 6: COMPRESSION 6..9: PAGE_SSIZE(3..7) |
241 | 10: DATA_DIR 7..10: COMP_LEVEL(0..9) 10: RESERVED (5.6 DATA_DIR) |
242 | ===================================================================== |
243 | The flags below were in incorrect position in MariaDB 10.1, |
244 | or have been introduced in MySQL 5.7 or 8.0: |
245 | ===================================================================== |
246 | 11: UNUSED 11..12:ATOMIC_WRITES 11: RESERVED (5.7 SHARED) |
247 | 12: RESERVED (5.7 TEMPORARY) |
248 | 13..15:PAGE_SSIZE(3..7) 13: RESERVED (5.7 ENCRYPTION) |
249 | 14: RESERVED (8.0 SDI) |
250 | 15: RESERVED |
251 | 16: PAGE_SSIZE_msb(0) 16: COMPRESSION |
252 | 17: DATA_DIR 17: UNUSED |
253 | 18: UNUSED |
254 | ===================================================================== |
255 | The flags below only exist in fil_space_t::flags, not in FSP_SPACE_FLAGS: |
256 | ===================================================================== |
257 | 25: DATA_DIR |
258 | 26..27: ATOMIC_WRITES |
259 | 28..31: COMPRESSION_LEVEL |
260 | */ |
261 | |
262 | /** A mask of the memory-only flags in fil_space_t::flags */ |
263 | #define FSP_FLAGS_MEM_MASK (~0U << FSP_FLAGS_MEM_DATA_DIR) |
264 | |
265 | /** Zero relative shift position of the DATA_DIR flag */ |
266 | #define FSP_FLAGS_MEM_DATA_DIR 25 |
267 | /** Zero relative shift position of the COMPRESSION_LEVEL field */ |
268 | #define FSP_FLAGS_MEM_COMPRESSION_LEVEL 26 |
269 | |
270 | /** Zero relative shift position of the POST_ANTELOPE field */ |
271 | #define FSP_FLAGS_POS_POST_ANTELOPE 0 |
272 | /** Zero relative shift position of the ZIP_SSIZE field */ |
273 | #define FSP_FLAGS_POS_ZIP_SSIZE (FSP_FLAGS_POS_POST_ANTELOPE \ |
274 | + FSP_FLAGS_WIDTH_POST_ANTELOPE) |
275 | /** Zero relative shift position of the ATOMIC_BLOBS field */ |
276 | #define FSP_FLAGS_POS_ATOMIC_BLOBS (FSP_FLAGS_POS_ZIP_SSIZE \ |
277 | + FSP_FLAGS_WIDTH_ZIP_SSIZE) |
278 | /** Zero relative shift position of the start of the PAGE_SSIZE bits */ |
279 | #define FSP_FLAGS_POS_PAGE_SSIZE (FSP_FLAGS_POS_ATOMIC_BLOBS \ |
280 | + FSP_FLAGS_WIDTH_ATOMIC_BLOBS) |
281 | /** Zero relative shift position of the start of the RESERVED bits |
282 | these are only used in MySQL 5.7 and used for compatibility. */ |
283 | #define FSP_FLAGS_POS_RESERVED (FSP_FLAGS_POS_PAGE_SSIZE \ |
284 | + FSP_FLAGS_WIDTH_PAGE_SSIZE) |
285 | /** Zero relative shift position of the PAGE_COMPRESSION field */ |
286 | #define FSP_FLAGS_POS_PAGE_COMPRESSION (FSP_FLAGS_POS_RESERVED \ |
287 | + FSP_FLAGS_WIDTH_RESERVED) |
288 | |
289 | /** Bit mask of the POST_ANTELOPE field */ |
290 | #define FSP_FLAGS_MASK_POST_ANTELOPE \ |
291 | ((~(~0U << FSP_FLAGS_WIDTH_POST_ANTELOPE)) \ |
292 | << FSP_FLAGS_POS_POST_ANTELOPE) |
293 | /** Bit mask of the ZIP_SSIZE field */ |
294 | #define FSP_FLAGS_MASK_ZIP_SSIZE \ |
295 | ((~(~0U << FSP_FLAGS_WIDTH_ZIP_SSIZE)) \ |
296 | << FSP_FLAGS_POS_ZIP_SSIZE) |
297 | /** Bit mask of the ATOMIC_BLOBS field */ |
298 | #define FSP_FLAGS_MASK_ATOMIC_BLOBS \ |
299 | ((~(~0U << FSP_FLAGS_WIDTH_ATOMIC_BLOBS)) \ |
300 | << FSP_FLAGS_POS_ATOMIC_BLOBS) |
301 | /** Bit mask of the PAGE_SSIZE field */ |
302 | #define FSP_FLAGS_MASK_PAGE_SSIZE \ |
303 | ((~(~0U << FSP_FLAGS_WIDTH_PAGE_SSIZE)) \ |
304 | << FSP_FLAGS_POS_PAGE_SSIZE) |
305 | /** Bit mask of the RESERVED1 field */ |
306 | #define FSP_FLAGS_MASK_RESERVED \ |
307 | ((~(~0U << FSP_FLAGS_WIDTH_RESERVED)) \ |
308 | << FSP_FLAGS_POS_RESERVED) |
309 | /** Bit mask of the PAGE_COMPRESSION field */ |
310 | #define FSP_FLAGS_MASK_PAGE_COMPRESSION \ |
311 | ((~(~0U << FSP_FLAGS_WIDTH_PAGE_COMPRESSION)) \ |
312 | << FSP_FLAGS_POS_PAGE_COMPRESSION) |
313 | |
314 | /** Bit mask of the in-memory COMPRESSION_LEVEL field */ |
315 | #define FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL \ |
316 | (15U << FSP_FLAGS_MEM_COMPRESSION_LEVEL) |
317 | |
318 | /** Return the value of the POST_ANTELOPE field */ |
319 | #define FSP_FLAGS_GET_POST_ANTELOPE(flags) \ |
320 | ((flags & FSP_FLAGS_MASK_POST_ANTELOPE) \ |
321 | >> FSP_FLAGS_POS_POST_ANTELOPE) |
322 | /** Return the value of the ZIP_SSIZE field */ |
323 | #define FSP_FLAGS_GET_ZIP_SSIZE(flags) \ |
324 | ((flags & FSP_FLAGS_MASK_ZIP_SSIZE) \ |
325 | >> FSP_FLAGS_POS_ZIP_SSIZE) |
326 | /** Return the value of the ATOMIC_BLOBS field */ |
327 | #define FSP_FLAGS_HAS_ATOMIC_BLOBS(flags) \ |
328 | ((flags & FSP_FLAGS_MASK_ATOMIC_BLOBS) \ |
329 | >> FSP_FLAGS_POS_ATOMIC_BLOBS) |
330 | /** Return the value of the PAGE_SSIZE field */ |
331 | #define FSP_FLAGS_GET_PAGE_SSIZE(flags) \ |
332 | ((flags & FSP_FLAGS_MASK_PAGE_SSIZE) \ |
333 | >> FSP_FLAGS_POS_PAGE_SSIZE) |
334 | /** @return the RESERVED flags */ |
335 | #define FSP_FLAGS_GET_RESERVED(flags) \ |
336 | ((flags & FSP_FLAGS_MASK_RESERVED) \ |
337 | >> FSP_FLAGS_POS_RESERVED) |
338 | /** @return the PAGE_COMPRESSION flag */ |
339 | #define FSP_FLAGS_HAS_PAGE_COMPRESSION(flags) \ |
340 | ((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION) \ |
341 | >> FSP_FLAGS_POS_PAGE_COMPRESSION) |
342 | |
343 | /** Return the contents of the UNUSED bits */ |
344 | #define FSP_FLAGS_GET_UNUSED(flags) \ |
345 | (flags >> FSP_FLAGS_POS_UNUSED) |
346 | |
347 | /** @return the value of the DATA_DIR field */ |
348 | #define FSP_FLAGS_HAS_DATA_DIR(flags) \ |
349 | (flags & 1U << FSP_FLAGS_MEM_DATA_DIR) |
350 | /** @return the COMPRESSION_LEVEL field */ |
351 | #define FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags) \ |
352 | ((flags & FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL) \ |
353 | >> FSP_FLAGS_MEM_COMPRESSION_LEVEL) |
354 | |
355 | /* @} */ |
356 | |
357 | /** Validate the tablespace flags, which are stored in the |
358 | tablespace header at offset FSP_SPACE_FLAGS. |
359 | @param[in] flags the contents of FSP_SPACE_FLAGS |
360 | @param[in] is_ibd whether this is an .ibd file (not system tablespace) |
361 | @return whether the flags are correct (not in the buggy 10.1) format */ |
362 | MY_ATTRIBUTE((warn_unused_result, const)) |
363 | UNIV_INLINE |
364 | bool |
365 | fsp_flags_is_valid(ulint flags, bool is_ibd) |
366 | { |
367 | DBUG_EXECUTE_IF("fsp_flags_is_valid_failure" , |
368 | return(false);); |
369 | if (flags == 0) { |
370 | return(true); |
371 | } |
372 | if (flags & ~FSP_FLAGS_MASK) { |
373 | return(false); |
374 | } |
375 | if ((flags & (FSP_FLAGS_MASK_POST_ANTELOPE | FSP_FLAGS_MASK_ATOMIC_BLOBS)) |
376 | == FSP_FLAGS_MASK_ATOMIC_BLOBS) { |
377 | /* If the "atomic blobs" flag (indicating |
378 | ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED) flag |
379 | is set, then the "post Antelope" (ROW_FORMAT!=REDUNDANT) flag |
380 | must also be set. */ |
381 | return(false); |
382 | } |
383 | /* Bits 10..14 should be 0b0000d where d is the DATA_DIR flag |
384 | of MySQL 5.6 and MariaDB 10.0, which we ignore. |
385 | In the buggy FSP_SPACE_FLAGS written by MariaDB 10.1.0 to 10.1.20, |
386 | bits 10..14 would be nonzero 0bsssaa where sss is |
387 | nonzero PAGE_SSIZE (3, 4, 6, or 7) |
388 | and aa is ATOMIC_WRITES (not 0b11). */ |
389 | if (FSP_FLAGS_GET_RESERVED(flags) & ~1U) { |
390 | return(false); |
391 | } |
392 | |
393 | const ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags); |
394 | if (ssize == 1 || ssize == 2 || ssize == 5 || ssize & 8) { |
395 | /* the page_size is not between 4k and 64k; |
396 | 16k should be encoded as 0, not 5 */ |
397 | return(false); |
398 | } |
399 | const ulint zssize = FSP_FLAGS_GET_ZIP_SSIZE(flags); |
400 | if (zssize == 0) { |
401 | /* not ROW_FORMAT=COMPRESSED */ |
402 | } else if (zssize > (ssize ? ssize : 5)) { |
403 | /* invalid KEY_BLOCK_SIZE */ |
404 | return(false); |
405 | } else if (~flags & (FSP_FLAGS_MASK_POST_ANTELOPE |
406 | | FSP_FLAGS_MASK_ATOMIC_BLOBS)) { |
407 | /* both these flags should be set for |
408 | ROW_FORMAT=COMPRESSED */ |
409 | return(false); |
410 | } |
411 | |
412 | /* The flags do look valid. But, avoid misinterpreting |
413 | buggy MariaDB 10.1 format flags for |
414 | PAGE_COMPRESSED=1 PAGE_COMPRESSION_LEVEL={0,2,3} |
415 | as valid-looking PAGE_SSIZE if this is known to be |
416 | an .ibd file and we are using the default innodb_page_size=16k. */ |
417 | return(ssize == 0 || !is_ibd || srv_page_size != UNIV_PAGE_SIZE_ORIG); |
418 | } |
419 | |
420 | #endif /* fsp0types_h */ |
421 | |