1 /***************************************************************************** 2 3 Copyright (c) 2013, 2020, Oracle and/or its affiliates. All Rights Reserved. 4 5 This program is free software; you can redistribute it and/or modify it under 6 the terms of the GNU General Public License, version 2.0, as published by the 7 Free Software Foundation. 8 9 This program is also distributed with certain software (including but not 10 limited to OpenSSL) that is licensed under separate terms, as designated in a 11 particular file or component or in included license documentation. The authors 12 of MySQL hereby grant you an additional permission to link the program and 13 your derivative works with the separately licensed software that they have 14 included with MySQL. 15 16 This program is distributed in the hope that it will be useful, but WITHOUT 17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 18 FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, 19 for more details. 20 21 You should have received a copy of the GNU General Public License along with 22 this program; if not, write to the Free Software Foundation, Inc., 23 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 25 *****************************************************************************/ 26 27 /** @file include/fsp0file.h 28 Tablespace data file implementation. 29 30 Created 2013-7-26 by Kevin Lewis 31 *******************************************************/ 32 33 #ifndef fsp0file_h 34 #define fsp0file_h 35 36 #include <vector> 37 #include "fil0fil.h" /* SPACE_UNKNOWN */ 38 #include "ha_prototypes.h" 39 #include "log0log.h" 40 #include "mem0mem.h" 41 #include "os0file.h" 42 43 #ifdef UNIV_HOTBACKUP 44 #include "fil0fil.h" 45 #include "fsp0types.h" 46 47 /** MEB routine to get the master key. MEB will extract 48 the key from the keyring encrypted file stored in backup. 49 @param[in] key_id the id of the master key 50 @param[in] key_type master key type 51 @param[out] key the master key being returned 52 @param[out] key_length the length of the returned key 53 @retval 0 if the key is being returned, 1 otherwise. */ 54 extern int meb_key_fetch(const char *key_id, char **key_type, 55 const char *user_id, void **key, size_t *key_length); 56 #endif /* UNIV_HOTBACKUP */ 57 58 /** Types of raw partitions in innodb_data_file_path */ 59 enum device_t { 60 61 /** Not a raw partition */ 62 SRV_NOT_RAW = 0, 63 64 /** A 'newraw' partition, only to be initialized */ 65 SRV_NEW_RAW, 66 67 /** An initialized raw partition */ 68 SRV_OLD_RAW 69 }; 70 71 /** Data file control information. */ 72 class Datafile { 73 friend class Tablespace; 74 friend class SysTablespace; 75 76 public: Datafile()77 Datafile() 78 : m_name(), 79 m_filename(), 80 m_open_flags(OS_FILE_OPEN), 81 m_size(), 82 m_order(), 83 m_type(SRV_NOT_RAW), 84 m_space_id(SPACE_UNKNOWN), 85 m_flags(), 86 m_exists(), 87 m_is_valid(), 88 m_first_page_buf(), 89 m_first_page(), 90 m_atomic_write(), 91 m_filepath(), 92 m_last_os_error(), 93 m_file_info(), 94 m_encryption_key(), 95 m_encryption_iv(), 96 m_encryption_op_in_progress(NONE) { 97 m_handle.m_file = OS_FILE_CLOSED; 98 } 99 Datafile(const char * name,uint32_t flags,page_no_t size,ulint order)100 Datafile(const char *name, uint32_t flags, page_no_t size, ulint order) 101 : m_name(mem_strdup(name)), 102 m_filename(), 103 m_open_flags(OS_FILE_OPEN), 104 m_size(size), 105 m_order(order), 106 m_type(SRV_NOT_RAW), 107 m_space_id(SPACE_UNKNOWN), 108 m_flags(flags), 109 m_exists(), 110 m_is_valid(), 111 m_first_page_buf(), 112 m_first_page(), 113 m_atomic_write(), 114 m_filepath(), 115 m_last_os_error(), 116 m_file_info(), 117 m_encryption_key(), 118 m_encryption_iv(), 119 m_encryption_op_in_progress(NONE) { 120 ut_ad(m_name != nullptr); 121 m_handle.m_file = OS_FILE_CLOSED; 122 /* No op */ 123 } 124 Datafile(const Datafile & file)125 Datafile(const Datafile &file) 126 : m_handle(file.m_handle), 127 m_open_flags(file.m_open_flags), 128 m_size(file.m_size), 129 m_order(file.m_order), 130 m_type(file.m_type), 131 m_space_id(file.m_space_id), 132 m_flags(file.m_flags), 133 m_exists(file.m_exists), 134 m_is_valid(file.m_is_valid), 135 m_first_page_buf(), 136 m_first_page(), 137 m_atomic_write(file.m_atomic_write), 138 m_last_os_error(), 139 m_file_info(), 140 m_encryption_key(), 141 m_encryption_iv(), 142 m_encryption_op_in_progress(NONE) { 143 m_name = mem_strdup(file.m_name); 144 ut_ad(m_name != nullptr); 145 146 if (file.m_filepath != nullptr) { 147 m_filepath = mem_strdup(file.m_filepath); 148 ut_a(m_filepath != nullptr); 149 set_filename(); 150 } else { 151 m_filepath = nullptr; 152 m_filename = nullptr; 153 } 154 } 155 ~Datafile()156 ~Datafile() { shutdown(); } 157 158 Datafile &operator=(const Datafile &file) { 159 ut_a(this != &file); 160 161 ut_ad(m_name == nullptr); 162 m_name = mem_strdup(file.m_name); 163 ut_a(m_name != nullptr); 164 165 m_size = file.m_size; 166 m_order = file.m_order; 167 m_type = file.m_type; 168 169 ut_a(m_handle.m_file == OS_FILE_CLOSED); 170 m_handle = file.m_handle; 171 172 m_exists = file.m_exists; 173 m_is_valid = file.m_is_valid; 174 m_open_flags = file.m_open_flags; 175 m_space_id = file.m_space_id; 176 m_flags = file.m_flags; 177 m_last_os_error = 0; 178 179 if (m_filepath != nullptr) { 180 ut_free(m_filepath); 181 m_filepath = nullptr; 182 m_filename = nullptr; 183 } 184 185 if (file.m_filepath != nullptr) { 186 m_filepath = mem_strdup(file.m_filepath); 187 ut_a(m_filepath != nullptr); 188 set_filename(); 189 } 190 191 /* Do not make a copy of the first page, 192 it should be reread if needed */ 193 m_first_page_buf = nullptr; 194 m_first_page = nullptr; 195 m_encryption_key = nullptr; 196 m_encryption_iv = nullptr; 197 m_encryption_op_in_progress = NONE; 198 199 m_atomic_write = file.m_atomic_write; 200 201 return (*this); 202 } 203 204 /** Initialize the name and flags of this datafile. 205 @param[in] name tablespace name, will be copied 206 @param[in] flags tablespace flags */ 207 void init(const char *name, uint32_t flags); 208 209 /** Release the resources. */ 210 void shutdown(); 211 212 /** Open a data file in read-only mode to check if it exists 213 so that it can be validated. 214 @param[in] strict whether to issue error messages 215 @return DB_SUCCESS or error code */ 216 dberr_t open_read_only(bool strict) MY_ATTRIBUTE((warn_unused_result)); 217 218 /** Open a data file in read-write mode during start-up so that 219 doublewrite pages can be restored and then it can be validated. 220 @param[in] read_only_mode if true, then readonly mode checks 221 are enforced. 222 @return DB_SUCCESS or error code */ 223 dberr_t open_read_write(bool read_only_mode) 224 MY_ATTRIBUTE((warn_unused_result)); 225 226 /** Initialize OS specific file info. */ 227 void init_file_info(); 228 229 /** Close a data file. 230 @return DB_SUCCESS or error code */ 231 dberr_t close(); 232 233 /** Make a full filepath from a directory path and a filename. 234 Prepend the dirpath to filename using the extension given. 235 If dirpath is nullptr, prepend the default datadir to filepath. 236 Store the result in m_filepath. 237 @param[in] dirpath directory path 238 @param[in] filename filename or filepath 239 @param[in] ext filename extension */ 240 void make_filepath(const char *dirpath, const char *filename, 241 ib_file_suffix ext); 242 243 /** Set the filepath by duplicating the filepath sent in */ 244 void set_filepath(const char *filepath); 245 246 /** Allocate and set the datafile or tablespace name in m_name. 247 If a name is provided, use it; else if the datafile is file-per-table, 248 extract a file-per-table tablespace name from m_filepath; else it is a 249 general tablespace, so just call it that for now. The value of m_name 250 will be freed in the destructor. 251 @param[in] name Tablespace Name if known, nullptr if not */ 252 void set_name(const char *name); 253 254 /** Validates the datafile and checks that it conforms with 255 the expected space ID and flags. The file should exist and be 256 successfully opened in order for this function to validate it. 257 @param[in] space_id The expected tablespace ID. 258 @param[in] flags The expected tablespace flags. 259 @param[in] for_import is it for importing 260 @retval DB_SUCCESS if tablespace is valid, DB_ERROR if not. 261 m_is_valid is also set true on success, else false. */ 262 dberr_t validate_to_dd(space_id_t space_id, uint32_t flags, bool for_import) 263 MY_ATTRIBUTE((warn_unused_result)); 264 265 /** Validates this datafile for the purpose of recovery. 266 The file should exist and be successfully opened. We initially 267 open it in read-only mode because we just want to read the SpaceID. 268 However, if the first page is corrupt and needs to be restored 269 from the doublewrite buffer, we will reopen it in write mode and 270 ry to restore that page. 271 @param[in] space_id Expected space ID 272 @retval DB_SUCCESS on success 273 m_is_valid is also set true on success, else false. */ 274 dberr_t validate_for_recovery(space_id_t space_id) 275 MY_ATTRIBUTE((warn_unused_result)); 276 277 /** Checks the consistency of the first page of a datafile when the 278 tablespace is opened. This occurs before the fil_space_t is created 279 so the Space ID found here must not already be open. 280 m_is_valid is set true on success, else false. 281 @param[in] space_id Expected space ID 282 @param[out] flush_lsn contents of FIL_PAGE_FILE_FLUSH_LSN 283 @param[in] for_import if it is for importing 284 (only valid for the first file of the system tablespace) 285 @retval DB_WRONG_FILE_NAME tablespace in file header doesn't match 286 expected value 287 @retval DB_SUCCESS on if the datafile is valid 288 @retval DB_CORRUPTION if the datafile is not readable 289 @retval DB_INVALID_ENCRYPTION_META if the encrypption meta data 290 is not readable 291 @retval DB_TABLESPACE_EXISTS if there is a duplicate space_id */ 292 dberr_t validate_first_page(space_id_t space_id, lsn_t *flush_lsn, 293 bool for_import) 294 MY_ATTRIBUTE((warn_unused_result)); 295 296 /** Get Datafile::m_name. 297 @return m_name */ name()298 const char *name() const { return (m_name); } 299 300 /** Get Datafile::m_filepath. 301 @return m_filepath */ filepath()302 const char *filepath() const { return (m_filepath); } 303 304 /** Get Datafile::m_handle. 305 @return m_handle */ handle()306 pfs_os_file_t handle() const { return (m_handle); } 307 308 /** Get Datafile::m_order. 309 @return m_order */ order()310 ulint order() const { return (m_order); } 311 312 /** Get Datafile::m_server_version. 313 @return m_server_version */ server_version()314 ulint server_version() const { return (m_server_version); } 315 316 /** Get Datafile::m_space_version. 317 @return m_space_version */ space_version()318 ulint space_version() const { return (m_space_version); } 319 320 /** Get Datafile::m_space_id. 321 @return m_space_id */ space_id()322 space_id_t space_id() const { return (m_space_id); } 323 324 /** Get Datafile::m_flags. 325 @return m_flags */ flags()326 uint32_t flags() const { return (m_flags); } 327 328 /** 329 @return true if m_handle is open, false if not */ is_open()330 bool is_open() const { return (m_handle.m_file != OS_FILE_CLOSED); } 331 332 /** Get Datafile::m_is_valid. 333 @return m_is_valid */ is_valid()334 bool is_valid() const { return (m_is_valid); } 335 336 /** Get the last OS error reported 337 @return m_last_os_error */ last_os_error()338 ulint last_os_error() const { return (m_last_os_error); } 339 340 /** Test if the filepath provided looks the same as this filepath 341 by string comparison. If they are two different paths to the same 342 file, same_as() will be used to show that after the files are opened. 343 @param[in] other filepath to compare with 344 @retval true if it is the same filename by char comparison 345 @retval false if it looks different */ 346 bool same_filepath_as(const char *other) const; 347 348 /** Test if another opened datafile is the same file as this object. 349 @param[in] other Datafile to compare with 350 @return true if it is the same file, else false */ 351 bool same_as(const Datafile &other) const; 352 353 /** Determine the space id of the given file descriptor by reading 354 a few pages from the beginning of the .ibd file. 355 @return DB_SUCCESS if space id was successfully identified, 356 else DB_ERROR. */ 357 dberr_t find_space_id(); 358 359 /** @return file size in number of pages */ size()360 page_no_t size() const { return (m_size); } 361 362 #if defined(UNIV_HOTBACKUP) || defined(XTRABACKUP) 363 /** Set the tablespace ID. 364 @param[in] space_id Tablespace ID to set */ set_space_id(space_id_t space_id)365 void set_space_id(space_id_t space_id) { 366 ut_ad(space_id <= 0xFFFFFFFFU); 367 m_space_id = space_id; 368 } 369 370 /** Set th tablespace flags 371 @param[in] flags Tablespace flags */ set_flags(uint32_t flags)372 void set_flags(uint32_t flags) { m_flags = flags; } 373 #endif /* UNIV_HOTBACKUP || XTRABACKUP*/ 374 375 private: 376 /** Free the filepath buffer. */ 377 void free_filepath(); 378 379 /** Set the filename pointer to the start of the file name 380 in the filepath. */ set_filename()381 void set_filename() { 382 if (m_filepath == nullptr) { 383 return; 384 } 385 386 char *last_slash = strrchr(m_filepath, OS_PATH_SEPARATOR); 387 388 m_filename = last_slash ? last_slash + 1 : m_filepath; 389 } 390 391 /** Create/open a data file. 392 @param[in] read_only_mode if true, then readonly mode checks 393 are enforced. 394 @return DB_SUCCESS or error code */ 395 dberr_t open_or_create(bool read_only_mode) 396 MY_ATTRIBUTE((warn_unused_result)); 397 398 /** Reads a few significant fields from the first page of the 399 datafile, which must already be open. 400 @param[in] read_only_mode if true, then readonly mode checks 401 are enforced. 402 @return DB_SUCCESS or DB_IO_ERROR if page cannot be read */ 403 dberr_t read_first_page(bool read_only_mode) 404 MY_ATTRIBUTE((warn_unused_result)); 405 406 /** Free the first page from memory when it is no longer needed. */ 407 void free_first_page(); 408 409 /** Set the Datafile::m_open_flags. 410 @param open_flags The Open flags to set. */ set_open_flags(os_file_create_t open_flags)411 void set_open_flags(os_file_create_t open_flags) { 412 m_open_flags = open_flags; 413 } 414 415 /** Finds a given page of the given space id from the double write 416 buffer and copies it to the corresponding .ibd file. 417 @param[in] restore_page_no Page number to restore 418 @return DB_SUCCESS if page was restored, else DB_ERROR */ 419 dberr_t restore_from_doublewrite(page_no_t restore_page_no); 420 421 private: 422 /** Datafile name at the tablespace location. 423 This is either the basename of the file if an absolute path 424 was entered, or it is the relative path to the datadir or 425 Tablespace::m_path. */ 426 char *m_name; 427 428 /** Points into m_filepath to the file name with extension */ 429 char *m_filename; 430 431 /** Open file handle */ 432 pfs_os_file_t m_handle; 433 434 /** Flags to use for opening the data file */ 435 os_file_create_t m_open_flags; 436 437 /** size in pages */ 438 page_no_t m_size; 439 440 /** ordinal position of this datafile in the tablespace */ 441 ulint m_order; 442 443 /** The type of the data file */ 444 device_t m_type; 445 446 /** Tablespace ID. Contained in the datafile header. 447 If this is a system tablespace, FSP_SPACE_ID is only valid 448 in the first datafile. */ 449 space_id_t m_space_id; 450 451 /** Server version */ 452 uint32 m_server_version; 453 454 /** Space version */ 455 uint32 m_space_version; 456 457 /** Tablespace flags. Contained in the datafile header. 458 If this is a system tablespace, FSP_SPACE_FLAGS are only valid 459 in the first datafile. */ 460 uint32_t m_flags; 461 462 /** true if file already existed on startup */ 463 bool m_exists; 464 465 /* true if the tablespace is valid */ 466 bool m_is_valid; 467 468 /** Buffer to hold first page */ 469 byte *m_first_page_buf; 470 471 /** Pointer to the first page held in the buffer above */ 472 byte *m_first_page; 473 474 /** true if atomic writes enabled for this file */ 475 bool m_atomic_write; 476 477 protected: 478 /** Physical file path with base name and extension */ 479 char *m_filepath; 480 481 /** Last OS error received so it can be reported if needed. */ 482 ulint m_last_os_error; 483 484 public: 485 /** Use the following to determine the uniqueness of this datafile. */ 486 #ifdef _WIN32 487 using WIN32_FILE_INFO = BY_HANDLE_FILE_INFORMATION; 488 489 /** Use fields dwVolumeSerialNumber, nFileIndexLow, nFileIndexHigh. */ 490 WIN32_FILE_INFO m_file_info; 491 #else 492 /** Use field st_ino. */ 493 struct stat m_file_info; 494 #endif /* WIN32 */ 495 496 /** Encryption key read from first page */ 497 byte *m_encryption_key; 498 499 /** Encryption iv read from first page */ 500 byte *m_encryption_iv; 501 502 /** Encryption operation in progress */ 503 encryption_op_type m_encryption_op_in_progress; 504 }; 505 #endif /* fsp0file_h */ 506