1 /*****************************************************************************
2 
3 Copyright (c) 2017, 2018, 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/arch0page.h
28  Innodb interface for modified page archive
29 
30  *******************************************************/
31 
32 #ifndef ARCH_PAGE_INCLUDE
33 #define ARCH_PAGE_INCLUDE
34 
35 #include "arch0arch.h"
36 #include "buf0buf.h"
37 
38 /** Archived page header file size (RESET Page) in number of blocks. */
39 constexpr uint ARCH_PAGE_FILE_NUM_RESET_PAGE = 1;
40 
41 /** Archived file header size. No file header for this version. */
42 constexpr uint ARCH_PAGE_FILE_HDR_SIZE =
43     ARCH_PAGE_FILE_NUM_RESET_PAGE * ARCH_PAGE_BLK_SIZE;
44 
45 /** @name Page Archive doublewrite buffer file name prefix and constant length
46 parameters. //@{ */
47 
48 /** Archive doublewrite buffer directory prefix */
49 constexpr char ARCH_DBLWR_DIR[] = "ib_dblwr";
50 
51 /** Archive doublewrite buffer file prefix */
52 constexpr char ARCH_DBLWR_FILE[] = "dblwr_";
53 
54 /** File name for the active file which indicates whether a group is active or
55 not. */
56 constexpr char ARCH_PAGE_GROUP_ACTIVE_FILE_NAME[] = "active";
57 
58 /** Archive doublewrite buffer number of files */
59 constexpr uint ARCH_DBLWR_NUM_FILES = 1;
60 
61 /** Archive doublewrite buffer file capacity in no. of blocks */
62 constexpr uint ARCH_DBLWR_FILE_CAPACITY = 3;
63 
64 /** //@} */
65 
66 /** @name Archive block header elements //@{ */
67 
68 /** Block Header: Version is in first 1 byte. */
69 constexpr uint ARCH_PAGE_BLK_HEADER_VERSION_OFFSET = 0;
70 
71 /** Block Header: Block Type is in next 1 byte. */
72 constexpr uint ARCH_PAGE_BLK_HEADER_TYPE_OFFSET = 1;
73 
74 /** Block Header: Checksum is in next 4 bytes. */
75 constexpr uint ARCH_PAGE_BLK_HEADER_CHECKSUM_OFFSET = 2;
76 
77 /** Block Header: Data length is in next 2 bytes. */
78 constexpr uint ARCH_PAGE_BLK_HEADER_DATA_LEN_OFFSET = 6;
79 
80 /** Block Header: Stop LSN is in next 8 bytes */
81 constexpr uint ARCH_PAGE_BLK_HEADER_STOP_LSN_OFFSET = 8;
82 
83 /** Block Header: Reset LSN is in next 8 bytes */
84 constexpr uint ARCH_PAGE_BLK_HEADER_RESET_LSN_OFFSET = 16;
85 
86 /** Block Header: Block number is in next 8 bytes */
87 constexpr uint ARCH_PAGE_BLK_HEADER_NUMBER_OFFSET = 24;
88 
89 /** Block Header: Total length.
90 Keep header length in multiple of #ARCH_BLK_PAGE_ID_SIZE */
91 constexpr uint ARCH_PAGE_BLK_HEADER_LENGTH = 32;
92 
93 /** //@} */
94 
95 /** @name Page Archive reset block elements size. //@{ */
96 
97 /** Serialized Reset ID: Reset LSN total size */
98 constexpr uint ARCH_PAGE_FILE_HEADER_RESET_LSN_SIZE = 8;
99 
100 /** Serialized Reset ID: Reset block number size */
101 constexpr uint ARCH_PAGE_FILE_HEADER_RESET_BLOCK_NUM_SIZE = 2;
102 
103 /** Serialized Reset ID: Reset block offset size */
104 constexpr uint ARCH_PAGE_FILE_HEADER_RESET_BLOCK_OFFSET_SIZE = 2;
105 
106 /** Serialized Reset ID: Reset position total size */
107 constexpr uint ARCH_PAGE_FILE_HEADER_RESET_POS_SIZE =
108     ARCH_PAGE_FILE_HEADER_RESET_BLOCK_NUM_SIZE +
109     ARCH_PAGE_FILE_HEADER_RESET_BLOCK_OFFSET_SIZE;
110 
111 /** //@} */
112 
113 /** @name Page Archive data block elements //@{ */
114 
115 /** Serialized page ID: tablespace ID in First 4 bytes */
116 constexpr uint ARCH_BLK_SPCE_ID_OFFSET = 0;
117 
118 /** Serialized page ID: Page number in next 4 bytes */
119 constexpr uint ARCH_BLK_PAGE_NO_OFFSET = 4;
120 
121 /** Serialized page ID: Total length */
122 constexpr uint ARCH_BLK_PAGE_ID_SIZE = 8;
123 
124 /** //@} */
125 
126 /** Number of memory blocks */
127 constexpr uint ARCH_PAGE_NUM_BLKS = 32;
128 
129 /** Archived file format version */
130 constexpr uint ARCH_PAGE_FILE_VERSION = 1;
131 
132 #ifdef UNIV_DEBUG
133 /** Archived page file default size in number of blocks. */
134 extern uint ARCH_PAGE_FILE_CAPACITY;
135 
136 /** Archived page data file size (without header) in number of blocks. */
137 extern uint ARCH_PAGE_FILE_DATA_CAPACITY;
138 #else
139 /** Archived page file default size in number of blocks. */
140 constexpr uint ARCH_PAGE_FILE_CAPACITY =
141     (ARCH_PAGE_BLK_SIZE - ARCH_PAGE_BLK_HEADER_LENGTH) / ARCH_BLK_PAGE_ID_SIZE;
142 
143 /** Archived page data file size (without header) in number of blocks. */
144 constexpr uint ARCH_PAGE_FILE_DATA_CAPACITY =
145     ARCH_PAGE_FILE_CAPACITY - ARCH_PAGE_FILE_NUM_RESET_PAGE;
146 #endif
147 
148 /** Threshold for page archive reset. Attach to current reset if the number of
149 tracked pages between the reset request and the current reset is less than this
150 threshold as we allow only one reset per data block. */
151 constexpr uint ARCH_PAGE_RESET_THRESHOLD =
152     (ARCH_PAGE_BLK_SIZE - ARCH_PAGE_BLK_HEADER_LENGTH) / ARCH_BLK_PAGE_ID_SIZE;
153 
154 /** Callback for retrieving archived page IDs
155 @param[in]	ctx		context passed by caller
156 @param[in]	buff		buffer with page IDs
157 @param[in]	num_pages	number of page IDs in buffer
158 @return error code */
159 using Page_Arch_Cbk = int(void *ctx, byte *buff, uint num_pages);
160 
161 /** Callback function to check if we need to wait for flush archiver to flush
162 more blocks */
163 using Page_Wait_Flush_Archiver_Cbk = std::function<bool(void)>;
164 
165 /** Dirty page archiver client context */
166 class Page_Arch_Client_Ctx {
167  public:
168   /** Constructor: Initialize elements
169   @param[in]	is_durable	true if the client requires durability, else
170   false */
Page_Arch_Client_Ctx(bool is_durable)171   Page_Arch_Client_Ctx(bool is_durable) : m_is_durable(is_durable) {
172     m_start_pos.init();
173     m_stop_pos.init();
174     mutex_create(LATCH_ID_PAGE_ARCH_CLIENT, &m_mutex);
175   }
176 
177   /** Destructor. */
~Page_Arch_Client_Ctx()178   ~Page_Arch_Client_Ctx() { mutex_free(&m_mutex); }
179 
180   /** Start dirty page tracking and archiving
181   @param[in]	recovery	true if the tracking is being started as part of
182   recovery process
183   @param[out]   start_id    fill the start lsn
184   @return error code. */
185   int start(bool recovery, uint64_t *start_id);
186 
187   /** Stop dirty page tracking and archiving
188   @param[out]	stop_id	fill the stop lsn
189   @return error code. */
190   int stop(uint64_t *stop_id);
191 
192   /** Release archived data so that system can purge it */
193   void release();
194 
195   /** Initialize context during recovery.
196   @param[in]	group		Group which needs to be attached to the client
197   @param[in]	last_lsn	last reset lsn
198   @return error code. */
199   int init_during_recovery(Arch_Group *group, lsn_t last_lsn);
200 
201   /** Check if this client context is active.
202   @return true if active, else false */
is_active()203   bool is_active() const { return (m_state == ARCH_CLIENT_STATE_STARTED); }
204 
205   /** Get archived page Ids.
206   Attempt to read blocks directly from in memory buffer. If overwritten,
207   copy from archived files.
208   @param[in]	cbk_func	called repeatedly with page ID buffer
209   @param[in]	cbk_ctx		callback function context
210   @param[in,out]	buff		buffer to fill page IDs
211   @param[in]	buf_len		buffer length in bytes
212   @return error code */
213   int get_pages(Page_Arch_Cbk *cbk_func, void *cbk_ctx, byte *buff,
214                 uint buf_len);
215 
216 #ifdef UNIV_DEBUG
217   /** Print information related to the archiver client for debugging purposes.
218    */
219   void print();
220 #endif
221 
222   /** Disable copy construction */
223   Page_Arch_Client_Ctx(Page_Arch_Client_Ctx const &) = delete;
224 
225   /** Disable assignment */
226   Page_Arch_Client_Ctx &operator=(Page_Arch_Client_Ctx const &) = delete;
227 
228  private:
229   /** Acquire client archiver mutex.
230   It synchronizes members on concurrent start and stop operations. */
arch_client_mutex_enter()231   void arch_client_mutex_enter() { mutex_enter(&m_mutex); }
232 
233   /** Release client archiver mutex */
arch_client_mutex_exit()234   void arch_client_mutex_exit() { mutex_exit(&m_mutex); }
235 
236  private:
237   /** Page archiver client state */
238   Arch_Client_State m_state{ARCH_CLIENT_STATE_INIT};
239 
240   /** Archive group the client is attached to */
241   Arch_Group *m_group{nullptr};
242 
243   /** True if the client requires durablity */
244   bool m_is_durable;
245 
246   /** Start LSN for archived data */
247   lsn_t m_start_lsn{LSN_MAX};
248 
249   /** Stop LSN for archived data */
250   lsn_t m_stop_lsn{LSN_MAX};
251 
252   /** Reset LSN at the time of last reset. */
253   lsn_t m_last_reset_lsn{LSN_MAX};
254 
255   /** Start position for client in archived file group */
256   Arch_Page_Pos m_start_pos;
257 
258   /** Stop position for client in archived file group */
259   Arch_Page_Pos m_stop_pos;
260 
261   /** Mutex protecting concurrent operation on data */
262   ib_mutex_t m_mutex;
263 };
264 
265 #endif /* ARCH_PAGE_INCLUDE */
266