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