1 /***************************************************************************** 2 3 Copyright (c) 2017, 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/clone0desc.h 28 Innodb clone descriptors 29 30 *******************************************************/ 31 32 #ifndef CLONE_DESC_INCLUDE 33 #define CLONE_DESC_INCLUDE 34 35 #include "mem0mem.h" 36 #include "os0file.h" 37 #include "univ.i" 38 39 /** Invalid locator ID. */ 40 const ib_uint64_t CLONE_LOC_INVALID_ID = 0; 41 42 /** Maximum base length for any serialized descriptor. This is only used for 43 optimal allocation and has no impact on version compatibility. */ 44 const uint32_t CLONE_DESC_MAX_BASE_LEN = 64; 45 46 /** Align by 4K for O_DIRECT */ 47 const uint32_t CLONE_ALIGN_DIRECT_IO = 4 * 1024; 48 49 /** Maximum number of concurrent tasks for each clone */ 50 const int CLONE_MAX_TASKS = 128; 51 52 /** Snapshot state transfer during clone. 53 54 Clone Type: HA_CLONE_BLOCKING 55 @startuml 56 state CLONE_SNAPSHOT_INIT 57 state CLONE_SNAPSHOT_FILE_COPY 58 state CLONE_SNAPSHOT_DONE 59 60 [*] -down-> CLONE_SNAPSHOT_INIT : Build snapshot 61 CLONE_SNAPSHOT_INIT -right-> CLONE_SNAPSHOT_FILE_COPY 62 CLONE_SNAPSHOT_FILE_COPY -right-> CLONE_SNAPSHOT_DONE 63 CLONE_SNAPSHOT_DONE -down-> [*] : Destroy snapshot 64 @enduml 65 66 Clone Type: HA_CLONE_REDO 67 @startuml 68 state CLONE_SNAPSHOT_REDO_COPY 69 70 [*] -down-> CLONE_SNAPSHOT_INIT : Build snapshot 71 CLONE_SNAPSHOT_INIT -right-> CLONE_SNAPSHOT_FILE_COPY : Start redo archiving 72 CLONE_SNAPSHOT_FILE_COPY -right-> CLONE_SNAPSHOT_REDO_COPY 73 CLONE_SNAPSHOT_REDO_COPY -right-> CLONE_SNAPSHOT_DONE 74 CLONE_SNAPSHOT_DONE -down-> [*] : Destroy snapshot 75 @enduml 76 77 Clone Type: HA_CLONE_HYBRID 78 @startuml 79 state CLONE_SNAPSHOT_PAGE_COPY 80 81 [*] -down-> CLONE_SNAPSHOT_INIT : Build snapshot 82 CLONE_SNAPSHOT_INIT -right-> CLONE_SNAPSHOT_FILE_COPY : Start page tracking 83 CLONE_SNAPSHOT_FILE_COPY -right-> CLONE_SNAPSHOT_PAGE_COPY : Start redo \ 84 archiving 85 CLONE_SNAPSHOT_PAGE_COPY -right-> CLONE_SNAPSHOT_REDO_COPY 86 CLONE_SNAPSHOT_REDO_COPY -right> CLONE_SNAPSHOT_DONE 87 CLONE_SNAPSHOT_DONE -down-> [*] : Destroy snapshot 88 @enduml 89 90 Clone Type: HA_CLONE_PAGE: Not implemented 91 */ 92 enum Snapshot_State { 93 /** Invalid state */ 94 CLONE_SNAPSHOT_NONE = 0, 95 96 /** Initialize state when snapshot object is created */ 97 CLONE_SNAPSHOT_INIT, 98 99 /** Snapshot state while transferring files. */ 100 CLONE_SNAPSHOT_FILE_COPY, 101 102 /** Snapshot state while transferring pages. */ 103 CLONE_SNAPSHOT_PAGE_COPY, 104 105 /** Snapshot state while transferring redo. */ 106 CLONE_SNAPSHOT_REDO_COPY, 107 108 /** Snapshot state at end after finishing transfer. */ 109 CLONE_SNAPSHOT_DONE 110 }; 111 112 /** Choose lowest descriptor version between reference locator 113 and currently supported version. 114 @param[in] ref_loc reference locator 115 @return chosen version */ 116 uint choose_desc_version(const byte *ref_loc); 117 118 /** Check if clone locator is valid 119 @param[in] desc_loc serialized descriptor 120 @param[in] desc_len descriptor length 121 @return true, if valid locator */ 122 bool clone_validate_locator(const byte *desc_loc, uint desc_len); 123 124 /** Clone descriptors contain meta information needed for applying cloned data. 125 These are PODs with interface to serialize and deserialize them. */ 126 enum Clone_Desc_Type { 127 /** Logical pointer to identify a clone operation */ 128 CLONE_DESC_LOCATOR = 1, 129 130 /** Metadata for a Task/Thread for clone operation */ 131 CLONE_DESC_TASK_METADATA, 132 133 /** Information for snapshot state */ 134 CLONE_DESC_STATE, 135 136 /** Metadata for a database file */ 137 CLONE_DESC_FILE_METADATA, 138 139 /** Information for a data block */ 140 CLONE_DESC_DATA, 141 142 /** Must be the last member */ 143 CLONE_DESC_MAX 144 }; 145 146 /** Header common to all descriptors. */ 147 struct Clone_Desc_Header { 148 /** Descriptor version */ 149 uint m_version; 150 151 /** Serialized length of descriptor in bytes */ 152 uint m_length; 153 154 /** Descriptor type */ 155 Clone_Desc_Type m_type; 156 157 /** Serialize the descriptor header: Caller must allocate 158 the serialized buffer. 159 @param[out] desc_hdr serialized header */ 160 void serialize(byte *desc_hdr); 161 162 /** Deserialize the descriptor header. 163 @param[in] desc_hdr serialized header 164 @param[in] desc_len descriptor length 165 @return true, if successful. */ 166 bool deserialize(const byte *desc_hdr, uint desc_len); 167 }; 168 169 /** Task information in clone operation. */ 170 struct Clone_Task_Meta { 171 /** Index in task array. */ 172 uint m_task_index; 173 174 /** Current chunk number reserved by the task. */ 175 uint m_chunk_num; 176 177 /** Current block number that is already transferred. */ 178 uint m_block_num; 179 }; 180 181 /** Map for current block number for unfinished chunks. Used during 182 restart from incomplete clone operation. */ 183 using Chunk_Map = std::map<uint32_t, uint32_t>; 184 185 /** Bitmap for completed chunks in current state */ 186 class Chnunk_Bitmap { 187 public: 188 /** Construct bitmap */ Chnunk_Bitmap()189 Chnunk_Bitmap() : m_bitmap(), m_size(), m_bits() {} 190 191 /** Bitmap array index operator implementation */ 192 class Bitmap_Operator_Impl { 193 public: 194 /** Construct bitmap operator 195 @param[in] bitmap reference to bitmap buffer 196 @param[in] index array operation index */ Bitmap_Operator_Impl(uint32_t * & bitmap,uint32_t index)197 Bitmap_Operator_Impl(uint32_t *&bitmap, uint32_t index) 198 199 : m_bitmap_ref(bitmap) { 200 /* BYTE position */ 201 auto byte_index = index >> 3; 202 ut_ad(byte_index == index / 8); 203 204 /* MAP array position */ 205 m_map_index = byte_index >> 2; 206 ut_ad(m_map_index == byte_index / 4); 207 208 /* BIT position */ 209 auto bit_pos = index & 31; 210 ut_ad(bit_pos == index % 32); 211 212 m_bit_mask = 1 << bit_pos; 213 } 214 215 /** Check value at specified index in BITMAP 216 @return true if the BIT is set */ 217 operator bool() const { 218 auto &val = m_bitmap_ref[m_map_index]; 219 220 if ((val & m_bit_mask) == 0) { 221 return (false); 222 } 223 224 return (true); 225 } 226 227 /** Set BIT at specific index 228 @param[in] bit bit value to set */ 229 void operator=(bool bit) { 230 auto &val = m_bitmap_ref[m_map_index]; 231 232 if (bit) { 233 val |= m_bit_mask; 234 } else { 235 val &= ~m_bit_mask; 236 } 237 } 238 239 private: 240 /** Refernce to BITMAP array */ 241 uint32_t *&m_bitmap_ref; 242 243 /** Current array position */ 244 uint32_t m_map_index; 245 246 /** Mask with current BIT set */ 247 uint32_t m_bit_mask; 248 }; 249 250 /** Array index operator 251 @param[in] index bitmap array index 252 @return operator implementation object */ 253 Bitmap_Operator_Impl operator[](uint32_t index) { 254 /* Convert to zero based index */ 255 --index; 256 257 ut_a(index < m_bits); 258 return (Bitmap_Operator_Impl(m_bitmap, index)); 259 } 260 261 /** Reset bitmap with new size 262 @param[in] max_bits number of BITs to hold 263 @param[in] heap heap for allocating memory 264 @return old buffer pointer */ 265 uint32_t *reset(uint32_t max_bits, mem_heap_t *heap); 266 267 /** Get minimum BIT position that is not set 268 @return BIT position */ 269 uint32_t get_min_unset_bit(); 270 271 /** Get maximum BIT position that is not set 272 @return BIT position */ 273 uint32_t get_max_set_bit(); 274 275 /** Serialize the descriptor. Caller should pass 276 the length if allocated. 277 @param[out] desc_chunk serialized chunk info 278 @param[in,out] len length of serialized descriptor */ 279 void serialize(byte *&desc_chunk, uint &len); 280 281 /** Deserialize the descriptor. 282 @param[in] desc_chunk serialized chunk info 283 @param[in,out] len_left length left in bytes */ 284 void deserialize(const byte *desc_chunk, uint &len_left); 285 286 /** Get the length of serialized data 287 @return length serialized chunk info */ 288 size_t get_serialized_length(); 289 290 /** Maximum bit capacity 291 @return maximum number of BITs it can hold */ capacity()292 size_t capacity() const { return (8 * size()); } 293 294 /** Size of bitmap in bytes 295 @return BITMAP buffer size */ size()296 size_t size() const { return (m_size * 4); } 297 298 /** Size of bitmap in bits 299 @return number of BITs stored */ size_bits()300 uint32_t size_bits() const { return (m_bits); } 301 302 private: 303 /** BITMAP buffer */ 304 uint32_t *m_bitmap; 305 306 /** BITMAP buffer size: Number of 4 byte blocks */ 307 size_t m_size; 308 309 /** Total number of BITs in the MAP */ 310 uint32_t m_bits; 311 }; 312 313 /** Incomplete Chunk information */ 314 struct Chunk_Info { 315 /** Information about chunks completed */ 316 Chnunk_Bitmap m_reserved_chunks; 317 318 /** Information about unfinished chunks */ 319 Chunk_Map m_incomplete_chunks; 320 321 /** Chunks for current state */ 322 uint32_t m_total_chunks; 323 324 /** Minimum chunk number that is not reserved yet */ 325 uint32_t m_min_unres_chunk; 326 327 /** Maximum chunk number that is already reserved */ 328 uint32_t m_max_res_chunk; 329 330 /** Initialize Chunk number ranges */ init_chunk_numsChunk_Info331 void init_chunk_nums() { 332 m_min_unres_chunk = m_reserved_chunks.get_min_unset_bit(); 333 ut_ad(m_min_unres_chunk <= m_total_chunks + 1); 334 335 m_max_res_chunk = m_reserved_chunks.get_max_set_bit(); 336 ut_ad(m_max_res_chunk <= m_total_chunks); 337 } 338 339 /** Serialize the descriptor. Caller should pass 340 the length if allocated. 341 @param[out] desc_chunk serialized chunk info 342 @param[in,out] len length of serialized descriptor */ 343 void serialize(byte *desc_chunk, uint &len); 344 345 /** Deserialize the descriptor. 346 @param[in] desc_chunk serialized chunk info 347 @param[in,out] len_left length left in bytes */ 348 void deserialize(const byte *desc_chunk, uint &len_left); 349 350 /** Get the length of serialized data 351 @param[in] num_tasks number of tasks to include 352 @return length serialized chunk info */ 353 size_t get_serialized_length(uint32_t num_tasks); 354 }; 355 356 /** CLONE_DESC_LOCATOR: Descriptor for a task for clone operation. 357 A task is used by exactly one thread */ 358 struct Clone_Desc_Locator { 359 /** Descriptor header */ 360 Clone_Desc_Header m_header; 361 362 /** Unique identifier for a clone operation. */ 363 uint64_t m_clone_id; 364 365 /** Unique identifier for a clone snapshot. */ 366 uint64_t m_snapshot_id; 367 368 /** Index in clone array for fast reference. */ 369 uint32_t m_clone_index; 370 371 /** Current snapshot State */ 372 Snapshot_State m_state; 373 374 /** Sub-state information: metadata transferred */ 375 bool m_metadata_transferred; 376 377 /** Initialize clone locator. 378 @param[in] id Clone identifier 379 @param[in] snap_id Snapshot identifier 380 @param[in] state snapshot state 381 @param[in] version Descriptor version 382 @param[in] index clone index */ 383 void init(ib_uint64_t id, ib_uint64_t snap_id, Snapshot_State state, 384 uint version, uint index); 385 386 /** Check if the passed locator matches the current one. 387 @param[in] other_desc input locator descriptor 388 @return true if matches */ 389 bool match(Clone_Desc_Locator *other_desc); 390 391 /** Serialize the descriptor. Caller should pass 392 the length if allocated. 393 @param[out] desc_loc serialized descriptor 394 @param[in,out] len length of serialized descriptor 395 @param[in] chunk_info chunk information to serialize 396 @param[in] heap heap for allocating memory */ 397 void serialize(byte *&desc_loc, uint &len, Chunk_Info *chunk_info, 398 mem_heap_t *heap); 399 400 /** Deserialize the descriptor. 401 @param[in] desc_loc serialized locator 402 @param[in] desc_len locator length 403 @param[in,out] chunk_info chunk information */ 404 void deserialize(const byte *desc_loc, uint desc_len, Chunk_Info *chunk_info); 405 }; 406 407 /** CLONE_DESC_TASK_METADATA: Descriptor for a task for clone operation. 408 A task is used by exactly one thread */ 409 struct Clone_Desc_Task_Meta { 410 /** Descriptor header */ 411 Clone_Desc_Header m_header; 412 413 /** Task information */ 414 Clone_Task_Meta m_task_meta; 415 416 /** Initialize header 417 @param[in] version descriptor version */ 418 void init_header(uint version); 419 420 /** Serialize the descriptor. Caller should pass 421 the length if allocated. 422 @param[out] desc_task serialized descriptor 423 @param[in,out] len length of serialized descriptor 424 @param[in] heap heap for allocating memory */ 425 void serialize(byte *&desc_task, uint &len, mem_heap_t *heap); 426 427 /** Deserialize the descriptor. 428 @param[in] desc_task serialized descriptor 429 @param[in] desc_len descriptor length 430 @return true, if successful. */ 431 bool deserialize(const byte *desc_task, uint desc_len); 432 }; 433 434 /** CLONE_DESC_STATE: Descriptor for current snapshot state */ 435 struct Clone_Desc_State { 436 /** Descriptor header */ 437 Clone_Desc_Header m_header; 438 439 /** Current snapshot State */ 440 Snapshot_State m_state; 441 442 /** Task identifier */ 443 uint m_task_index; 444 445 /** Number of chunks in current state */ 446 uint m_num_chunks; 447 448 /** Number of files in current state */ 449 uint m_num_files; 450 451 /** Number of estimated bytes to transfer */ 452 uint64_t m_estimate; 453 454 /** Number of estimated bytes on disk */ 455 uint64_t m_estimate_disk; 456 457 /** If start processing state */ 458 bool m_is_start; 459 460 /** State transfer Acknowledgement */ 461 bool m_is_ack; 462 463 /** Initialize header 464 @param[in] version descriptor version */ 465 void init_header(uint version); 466 467 /** Serialize the descriptor. Caller should pass 468 the length if allocated. 469 @param[out] desc_state serialized descriptor 470 @param[in,out] len length of serialized descriptor 471 @param[in] heap heap for allocating memory */ 472 void serialize(byte *&desc_state, uint &len, mem_heap_t *heap); 473 474 /** Deserialize the descriptor. 475 @param[in] desc_state serialized descriptor 476 @param[in] desc_len descriptor length 477 @return true, if successful. */ 478 bool deserialize(const byte *desc_state, uint desc_len); 479 }; 480 481 /** Clone file information */ 482 struct Clone_File_Meta { 483 /** File size in bytes */ 484 uint64_t m_file_size; 485 486 /** File allocation size on disk for sparse files. */ 487 uint64_t m_alloc_size; 488 489 /** Tablespace FSP flags */ 490 uint32_t m_fsp_flags; 491 492 /** File compression type */ 493 Compression::Type m_compress_type; 494 495 /* File encryption type */ 496 Encryption::Type m_encrypt_type; 497 498 /** If transparent compression is needed. It is derived information 499 and is not transferred. */ 500 bool m_punch_hole; 501 502 /** File system block size. */ 503 size_t m_fsblk_size; 504 505 /** Tablespace ID for the file */ 506 space_id_t m_space_id; 507 508 /** File index in clone data file vector */ 509 uint m_file_index; 510 511 /** Chunk number for the first chunk in file */ 512 uint m_begin_chunk; 513 514 /** Chunk number for the last chunk in file */ 515 uint m_end_chunk; 516 517 /** File name length in bytes */ 518 size_t m_file_name_len; 519 520 /** File name */ 521 const char *m_file_name; 522 }; 523 524 /** CLONE_DESC_FILE_METADATA: Descriptor for file metadata */ 525 struct Clone_Desc_File_MetaData { 526 /** Descriptor header */ 527 Clone_Desc_Header m_header; 528 529 /** Current snapshot State */ 530 Snapshot_State m_state; 531 532 /** File metadata */ 533 Clone_File_Meta m_file_meta; 534 535 /** Initialize header 536 @param[in] version descriptor version */ 537 void init_header(uint version); 538 539 /** Serialize the descriptor. Caller should pass 540 the length if allocated. 541 @param[out] desc_file serialized descriptor 542 @param[in,out] len length of serialized descriptor 543 @param[in] heap heap for allocating memory */ 544 void serialize(byte *&desc_file, uint &len, mem_heap_t *heap); 545 546 /** Deserialize the descriptor. 547 @param[in] desc_file serialized descriptor 548 @param[in] desc_len descriptor length 549 @return true, if successful. */ 550 bool deserialize(const byte *desc_file, uint desc_len); 551 }; 552 553 /** CLONE_DESC_DATA: Descriptor for data */ 554 struct Clone_Desc_Data { 555 /** Descriptor header */ 556 Clone_Desc_Header m_header; 557 558 /** Current snapshot State */ 559 Snapshot_State m_state; 560 561 /** Task information */ 562 Clone_Task_Meta m_task_meta; 563 564 /** File identifier */ 565 uint32_t m_file_index; 566 567 /** Data Length */ 568 uint32_t m_data_len; 569 570 /** File offset for the data */ 571 uint64_t m_file_offset; 572 573 /** Updated file size */ 574 uint64_t m_file_size; 575 576 /** Initialize header 577 @param[in] version descriptor version */ 578 void init_header(uint version); 579 580 /** Serialize the descriptor. Caller should pass 581 the length if allocated. 582 @param[out] desc_data serialized descriptor 583 @param[in,out] len length of serialized descriptor 584 @param[in] heap heap for allocating memory */ 585 void serialize(byte *&desc_data, uint &len, mem_heap_t *heap); 586 587 /** Deserialize the descriptor. 588 @param[in] desc_data serialized descriptor 589 @param[in] desc_len descriptor length 590 @return true, if successful. */ 591 bool deserialize(const byte *desc_data, uint desc_len); 592 }; 593 594 #endif /* CLONE_DESC_INCLUDE */ 595