1/***************************************************************************** 2 3Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. 4Copyright (c) 2017, 2018, MariaDB Corporation. 5 6This program is free software; you can redistribute it and/or modify it under 7the terms of the GNU General Public License as published by the Free Software 8Foundation; version 2 of the License. 9 10This program is distributed in the hope that it will be useful, but WITHOUT 11ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 14You should have received a copy of the GNU General Public License along with 15this program; if not, write to the Free Software Foundation, Inc., 1651 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA 17 18*****************************************************************************/ 19 20/**************************************************//** 21@file include/trx0undo.ic 22Transaction undo log 23 24Created 3/26/1996 Heikki Tuuri 25*******************************************************/ 26 27#include "data0type.h" 28#include "page0page.h" 29 30/***********************************************************************//** 31Builds a roll pointer. 32@return roll pointer */ 33UNIV_INLINE 34roll_ptr_t 35trx_undo_build_roll_ptr( 36/*====================*/ 37 ibool is_insert, /*!< in: TRUE if insert undo log */ 38 ulint rseg_id, /*!< in: rollback segment id */ 39 ulint page_no, /*!< in: page number */ 40 ulint offset) /*!< in: offset of the undo entry within page */ 41{ 42 roll_ptr_t roll_ptr; 43 compile_time_assert(DATA_ROLL_PTR_LEN == 7); 44 ut_ad(is_insert == 0 || is_insert == 1); 45 ut_ad(rseg_id < TRX_SYS_N_RSEGS); 46 ut_ad(offset < 65536); 47 48 roll_ptr = (roll_ptr_t) is_insert << ROLL_PTR_INSERT_FLAG_POS 49 | (roll_ptr_t) rseg_id << ROLL_PTR_RSEG_ID_POS 50 | (roll_ptr_t) page_no << ROLL_PTR_PAGE_POS 51 | offset; 52 return(roll_ptr); 53} 54 55/***********************************************************************//** 56Decodes a roll pointer. */ 57UNIV_INLINE 58void 59trx_undo_decode_roll_ptr( 60/*=====================*/ 61 roll_ptr_t roll_ptr, /*!< in: roll pointer */ 62 ibool* is_insert, /*!< out: TRUE if insert undo log */ 63 ulint* rseg_id, /*!< out: rollback segment id */ 64 ulint* page_no, /*!< out: page number */ 65 ulint* offset) /*!< out: offset of the undo 66 entry within page */ 67{ 68 compile_time_assert(DATA_ROLL_PTR_LEN == 7); 69 ut_ad(roll_ptr < (1ULL << 56)); 70 *offset = (ulint) roll_ptr & 0xFFFF; 71 roll_ptr >>= 16; 72 *page_no = (ulint) roll_ptr & 0xFFFFFFFF; 73 roll_ptr >>= 32; 74 *rseg_id = (ulint) roll_ptr & 0x7F; 75 roll_ptr >>= 7; 76 *is_insert = (ibool) roll_ptr; /* TRUE==1 */ 77} 78 79/***********************************************************************//** 80Returns TRUE if the roll pointer is of the insert type. 81@return TRUE if insert undo log */ 82UNIV_INLINE 83ibool 84trx_undo_roll_ptr_is_insert( 85/*========================*/ 86 roll_ptr_t roll_ptr) /*!< in: roll pointer */ 87{ 88 compile_time_assert(DATA_ROLL_PTR_LEN == 7); 89 ut_ad(roll_ptr < (1ULL << (ROLL_PTR_INSERT_FLAG_POS + 1))); 90 return((ibool) (roll_ptr >> ROLL_PTR_INSERT_FLAG_POS)); 91} 92 93/***********************************************************************//** 94Returns true if the record is of the insert type. 95@return true if the record was freshly inserted (not updated). */ 96UNIV_INLINE 97bool 98trx_undo_trx_id_is_insert( 99/*======================*/ 100 const byte* trx_id) /*!< in: DB_TRX_ID, followed by DB_ROLL_PTR */ 101{ 102 compile_time_assert(DATA_TRX_ID + 1 == DATA_ROLL_PTR); 103 return bool(trx_id[DATA_TRX_ID_LEN] >> 7); 104} 105 106/*****************************************************************//** 107Writes a roll ptr to an index page. In case that the size changes in 108some future version, this function should be used instead of 109mach_write_... */ 110UNIV_INLINE 111void 112trx_write_roll_ptr( 113/*===============*/ 114 byte* ptr, /*!< in: pointer to memory where 115 written */ 116 roll_ptr_t roll_ptr) /*!< in: roll ptr */ 117{ 118 compile_time_assert(DATA_ROLL_PTR_LEN == 7); 119 mach_write_to_7(ptr, roll_ptr); 120} 121 122/*****************************************************************//** 123Reads a roll ptr from an index page. In case that the roll ptr size 124changes in some future version, this function should be used instead of 125mach_read_... 126@return roll ptr */ 127UNIV_INLINE 128roll_ptr_t 129trx_read_roll_ptr( 130/*==============*/ 131 const byte* ptr) /*!< in: pointer to memory from where to read */ 132{ 133 compile_time_assert(DATA_ROLL_PTR_LEN == 7); 134 return(mach_read_from_7(ptr)); 135} 136 137/** Gets an undo log page and x-latches it. 138@param[in] page_id page id 139@param[in,out] mtr mini-transaction 140@return pointer to page x-latched */ 141UNIV_INLINE 142page_t* 143trx_undo_page_get(const page_id_t page_id, mtr_t* mtr) 144{ 145 buf_block_t* block = buf_page_get(page_id, univ_page_size, 146 RW_X_LATCH, mtr); 147 148 buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); 149 150 return(buf_block_get_frame(block)); 151} 152 153/** Gets an undo log page and s-latches it. 154@param[in] page_id page id 155@param[in,out] mtr mini-transaction 156@return pointer to page s-latched */ 157UNIV_INLINE 158page_t* 159trx_undo_page_get_s_latched(const page_id_t page_id, mtr_t* mtr) 160{ 161 buf_block_t* block = buf_page_get(page_id, univ_page_size, 162 RW_S_LATCH, mtr); 163 164 buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); 165 166 return(buf_block_get_frame(block)); 167} 168 169/** Determine the end offset of undo log records of an undo log page. 170@param[in] undo_page undo log page 171@param[in] page_no undo log header page number 172@param[in] offset undo log header offset 173@return end offset */ 174inline 175uint16_t 176trx_undo_page_get_end(const page_t* undo_page, ulint page_no, ulint offset) 177{ 178 if (page_no == page_get_page_no(undo_page)) { 179 if (uint16_t end = mach_read_from_2(TRX_UNDO_NEXT_LOG 180 + offset + undo_page)) { 181 return end; 182 } 183 } 184 185 return mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE 186 + undo_page); 187} 188 189/******************************************************************//** 190Returns the next undo log record on the page in the specified log, or 191NULL if none exists. 192@return pointer to record, NULL if none */ 193UNIV_INLINE 194trx_undo_rec_t* 195trx_undo_page_get_next_rec( 196/*=======================*/ 197 trx_undo_rec_t* rec, /*!< in: undo log record */ 198 ulint page_no,/*!< in: undo log header page number */ 199 ulint offset) /*!< in: undo log header offset on page */ 200{ 201 page_t* undo_page; 202 ulint end; 203 ulint next; 204 205 undo_page = (page_t*) ut_align_down(rec, srv_page_size); 206 207 end = trx_undo_page_get_end(undo_page, page_no, offset); 208 209 next = mach_read_from_2(rec); 210 211 if (next == end) { 212 213 return(NULL); 214 } 215 216 return(undo_page + next); 217} 218