1/***************************************************************************** 2 3Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. 4 5This program is free software; you can redistribute it and/or modify 6it under the terms of the GNU General Public License, version 2.0, 7as published by the Free Software Foundation. 8 9This program is also distributed with certain software (including 10but not limited to OpenSSL) that is licensed under separate terms, 11as designated in a particular file or component or in included license 12documentation. The authors of MySQL hereby grant you an additional 13permission to link the program and your derivative works with the 14separately licensed software that they have included with MySQL. 15 16This program is distributed in the hope that it will be useful, 17but WITHOUT ANY WARRANTY; without even the implied warranty of 18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19GNU General Public License, version 2.0, for more details. 20 21You should have received a copy of the GNU General Public License along with 22this program; if not, write to the Free Software Foundation, Inc., 2351 Franklin Street, Suite 500, Boston, MA 02110-1335 USA 24 25*****************************************************************************/ 26 27/**************************************************//** 28@file include/fsp0fsp.ic 29File space management 30 31Created 12/18/1995 Heikki Tuuri 32*******************************************************/ 33 34#ifndef UNIV_INNOCHECKSUM 35 36/***********************************************************************//** 37Checks if a page address is an extent descriptor page address. 38@return TRUE if a descriptor page */ 39UNIV_INLINE 40ibool 41fsp_descr_page( 42/*===========*/ 43 ulint zip_size,/*!< in: compressed page size in bytes; 44 0 for uncompressed pages */ 45 ulint page_no)/*!< in: page number */ 46{ 47 ut_ad(ut_is_2pow(zip_size)); 48 49 if (!zip_size) { 50 return((page_no & (UNIV_PAGE_SIZE - 1)) == FSP_XDES_OFFSET); 51 } 52 53 return((page_no & (zip_size - 1)) == FSP_XDES_OFFSET); 54} 55 56/********************************************************************//** 57Validate and return the tablespace flags, which are stored in the 58tablespace header at offset FSP_SPACE_FLAGS. They should be 0 for 59ROW_FORMAT=COMPACT and ROW_FORMAT=REDUNDANT. The newer row formats, 60COMPRESSED and DYNAMIC, use a file format > Antelope so they should 61have a file format number plus the DICT_TF_COMPACT bit set. 62@return true if check ok */ 63UNIV_INLINE 64bool 65fsp_flags_is_valid( 66/*===============*/ 67 ulint flags) /*!< in: tablespace flags */ 68{ 69 ulint post_antelope = FSP_FLAGS_GET_POST_ANTELOPE(flags); 70 ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(flags); 71 ulint atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(flags); 72 ulint page_ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags); 73 ulint unused = FSP_FLAGS_GET_UNUSED(flags); 74 75 DBUG_EXECUTE_IF("fsp_flags_is_valid_failure", return(false);); 76 77 /* fsp_flags is zero unless atomic_blobs is set. */ 78 /* Make sure there are no bits that we do not know about. */ 79 if (unused != 0 || flags == 1) { 80 return(false); 81 } else if (post_antelope) { 82 /* The Antelope row formats REDUNDANT and COMPACT did 83 not use tablespace flags, so this flag and the entire 84 4-byte field is zero for Antelope row formats. */ 85 86 if (!atomic_blobs) { 87 return(false); 88 } 89 } 90 91 if (!atomic_blobs) { 92 /* Barracuda row formats COMPRESSED and DYNAMIC build on 93 the page structure introduced for the COMPACT row format 94 by allowing long fields to be broken into prefix and 95 externally stored parts. */ 96 97 if (post_antelope || zip_ssize != 0) { 98 return(false); 99 } 100 101 } else if (!post_antelope || zip_ssize > PAGE_ZIP_SSIZE_MAX) { 102 return(false); 103 } else if (page_ssize > UNIV_PAGE_SSIZE_MAX) { 104 105 /* The page size field can be used for any row type, or it may 106 be zero for an original 16k page size. 107 Validate the page shift size is within allowed range. */ 108 109 return(false); 110 111 } else if (UNIV_PAGE_SIZE != UNIV_PAGE_SIZE_ORIG && !page_ssize) { 112 return(false); 113 } 114 115#if UNIV_FORMAT_MAX != UNIV_FORMAT_B 116# error "UNIV_FORMAT_MAX != UNIV_FORMAT_B, Add more validations." 117#endif 118 119 /* The DATA_DIR field can be used for any row type so there is 120 nothing here to validate. */ 121 122 return(true); 123} 124 125/********************************************************************//** 126Determine if the tablespace is compressed from dict_table_t::flags. 127@return TRUE if compressed, FALSE if not compressed */ 128UNIV_INLINE 129ibool 130fsp_flags_is_compressed( 131/*====================*/ 132 ulint flags) /*!< in: tablespace flags */ 133{ 134 return(FSP_FLAGS_GET_ZIP_SSIZE(flags) != 0); 135} 136 137#endif /* !UNIV_INNOCHECKSUM */ 138 139/********************************************************************//** 140Extract the zip size from tablespace flags. 141@return compressed page size of the file-per-table tablespace in bytes, 142or zero if the table is not compressed. */ 143UNIV_INLINE 144ulint 145fsp_flags_get_zip_size( 146/*===================*/ 147 ulint flags) /*!< in: tablespace flags */ 148{ 149 ulint zip_size = 0; 150 ulint ssize = FSP_FLAGS_GET_ZIP_SSIZE(flags); 151 152 /* Convert from a 'log2 minus 9' to a page size in bytes. */ 153 if (ssize) { 154 zip_size = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize); 155 156 ut_ad(zip_size <= UNIV_ZIP_SIZE_MAX); 157 } 158 159 return(zip_size); 160} 161 162/********************************************************************//** 163Extract the page size from tablespace flags. 164@return page size of the tablespace in bytes */ 165UNIV_INLINE 166ulint 167fsp_flags_get_page_size( 168/*====================*/ 169 ulint flags) /*!< in: tablespace flags */ 170{ 171 ulint page_size = 0; 172 ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags); 173 174 /* Convert from a 'log2 minus 9' to a page size in bytes. */ 175 if (UNIV_UNLIKELY(ssize)) { 176 page_size = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize); 177 178 ut_ad(page_size <= UNIV_PAGE_SIZE_MAX); 179 } else { 180 /* If the page size was not stored, then it is the 181 original 16k. */ 182 page_size = UNIV_PAGE_SIZE_ORIG; 183 } 184 185 return(page_size); 186} 187 188#ifndef UNIV_INNOCHECKSUM 189 190/********************************************************************//** 191Add the page size to the tablespace flags. 192@return tablespace flags after page size is added */ 193UNIV_INLINE 194ulint 195fsp_flags_set_page_size( 196/*====================*/ 197 ulint flags, /*!< in: tablespace flags */ 198 ulint page_size) /*!< in: page size in bytes */ 199{ 200 ulint ssize = 0; 201 ulint shift; 202 203 /* Page size should be > UNIV_PAGE_SIZE_MIN */ 204 ut_ad(page_size >= UNIV_PAGE_SIZE_MIN); 205 ut_ad(page_size <= UNIV_PAGE_SIZE_MAX); 206 207 if (page_size == UNIV_PAGE_SIZE_ORIG) { 208 ut_ad(0 == FSP_FLAGS_GET_PAGE_SSIZE(flags)); 209 return(flags); 210 } 211 212 for (shift = UNIV_PAGE_SIZE_SHIFT_MAX; 213 shift >= UNIV_PAGE_SIZE_SHIFT_MIN; 214 shift--) { 215 ulint mask = (1 << shift); 216 if (page_size & mask) { 217 ut_ad(!(page_size & ~mask)); 218 ssize = shift - UNIV_ZIP_SIZE_SHIFT_MIN + 1; 219 break; 220 } 221 } 222 223 ut_ad(ssize); 224 ut_ad(ssize <= UNIV_PAGE_SSIZE_MAX); 225 226 flags = FSP_FLAGS_SET_PAGE_SSIZE(flags, ssize); 227 228 ut_ad(fsp_flags_is_valid(flags)); 229 230 return(flags); 231} 232 233/********************************************************************//** 234Calculates the descriptor index within a descriptor page. 235@return descriptor index */ 236UNIV_INLINE 237ulint 238xdes_calc_descriptor_index( 239/*=======================*/ 240 ulint zip_size, /*!< in: compressed page size in bytes; 241 0 for uncompressed pages */ 242 ulint offset) /*!< in: page offset */ 243{ 244 ut_ad(ut_is_2pow(zip_size)); 245 246 if (zip_size == 0) { 247 return(ut_2pow_remainder(offset, UNIV_PAGE_SIZE) 248 / FSP_EXTENT_SIZE); 249 } else { 250 return(ut_2pow_remainder(offset, zip_size) / FSP_EXTENT_SIZE); 251 } 252} 253 254/**********************************************************************//** 255Gets a descriptor bit of a page. 256@return TRUE if free */ 257UNIV_INLINE 258ibool 259xdes_get_bit( 260/*=========*/ 261 const xdes_t* descr, /*!< in: descriptor */ 262 ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */ 263 ulint offset) /*!< in: page offset within extent: 264 0 ... FSP_EXTENT_SIZE - 1 */ 265{ 266 ut_ad(offset < FSP_EXTENT_SIZE); 267 ut_ad(bit == XDES_FREE_BIT || bit == XDES_CLEAN_BIT); 268 269 ulint index = bit + XDES_BITS_PER_PAGE * offset; 270 271 ulint bit_index = index % 8; 272 ulint byte_index = index / 8; 273 274 return(ut_bit_get_nth( 275 mach_read_ulint(descr + XDES_BITMAP + byte_index, 276 MLOG_1BYTE), 277 bit_index)); 278} 279 280/********************************************************************//** 281Calculates the page where the descriptor of a page resides. 282@return descriptor page offset */ 283UNIV_INLINE 284ulint 285xdes_calc_descriptor_page( 286/*======================*/ 287 ulint zip_size, /*!< in: compressed page size in bytes; 288 0 for uncompressed pages */ 289 ulint offset) /*!< in: page offset */ 290{ 291#ifndef DOXYGEN /* Doxygen gets confused by these */ 292# if UNIV_PAGE_SIZE_MAX <= XDES_ARR_OFFSET \ 293 + (UNIV_PAGE_SIZE_MAX / FSP_EXTENT_SIZE_MAX) \ 294 * XDES_SIZE_MAX 295# error 296# endif 297# if UNIV_ZIP_SIZE_MIN <= XDES_ARR_OFFSET \ 298 + (UNIV_ZIP_SIZE_MIN / FSP_EXTENT_SIZE_MIN) \ 299 * XDES_SIZE_MIN 300# error 301# endif 302#endif /* !DOXYGEN */ 303 304 ut_ad(UNIV_PAGE_SIZE > XDES_ARR_OFFSET 305 + (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE) 306 * XDES_SIZE); 307 ut_ad(UNIV_ZIP_SIZE_MIN > XDES_ARR_OFFSET 308 + (UNIV_ZIP_SIZE_MIN / FSP_EXTENT_SIZE) 309 * XDES_SIZE); 310 311 ut_ad(ut_is_2pow(zip_size)); 312 313 if (zip_size == 0) { 314 return(ut_2pow_round(offset, UNIV_PAGE_SIZE)); 315 } else { 316 ut_ad(zip_size > XDES_ARR_OFFSET 317 + (zip_size / FSP_EXTENT_SIZE) * XDES_SIZE); 318 return(ut_2pow_round(offset, zip_size)); 319 } 320} 321 322#endif /* !UNIV_INNOCHECKSUM */ 323