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