1/***************************************************************************** 2 3Copyright (c) 1996, 2009, Oracle and/or its affiliates. All Rights Reserved. 4 5This program is free software; you can redistribute it and/or modify 6it under the terms of the GNU General Public License, version 2.0, 7as published by the Free Software Foundation. 8 9This program is also distributed with certain software (including 10but not limited to OpenSSL) that is licensed under separate terms, 11as designated in a particular file or component or in included license 12documentation. The authors of MySQL hereby grant you an additional 13permission to link the program and your derivative works with the 14separately licensed software that they have included with MySQL. 15 16This program is distributed in the hope that it will be useful, 17but WITHOUT ANY WARRANTY; without even the implied warranty of 18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19GNU General Public License, version 2.0, for more details. 20 21You should have received a copy of the GNU General Public License along with 22this program; if not, write to the Free Software Foundation, Inc., 2351 Franklin Street, Suite 500, Boston, MA 02110-1335 USA 24 25*****************************************************************************/ 26 27/**************************************************//** 28@file include/trx0undo.ic 29Transaction undo log 30 31Created 3/26/1996 Heikki Tuuri 32*******************************************************/ 33 34#include "data0type.h" 35#include "page0page.h" 36 37#ifndef UNIV_HOTBACKUP 38/***********************************************************************//** 39Builds a roll pointer. 40@return roll pointer */ 41UNIV_INLINE 42roll_ptr_t 43trx_undo_build_roll_ptr( 44/*====================*/ 45 ibool is_insert, /*!< in: TRUE if insert undo log */ 46 ulint rseg_id, /*!< in: rollback segment id */ 47 ulint page_no, /*!< in: page number */ 48 ulint offset) /*!< in: offset of the undo entry within page */ 49{ 50 roll_ptr_t roll_ptr; 51#if DATA_ROLL_PTR_LEN != 7 52# error "DATA_ROLL_PTR_LEN != 7" 53#endif 54 ut_ad(is_insert == 0 || is_insert == 1); 55 ut_ad(rseg_id < TRX_SYS_N_RSEGS); 56 ut_ad(offset < 65536); 57 58 roll_ptr = (roll_ptr_t) is_insert << 55 59 | (roll_ptr_t) rseg_id << 48 60 | (roll_ptr_t) page_no << 16 61 | offset; 62 return(roll_ptr); 63} 64 65/***********************************************************************//** 66Decodes a roll pointer. */ 67UNIV_INLINE 68void 69trx_undo_decode_roll_ptr( 70/*=====================*/ 71 roll_ptr_t roll_ptr, /*!< in: roll pointer */ 72 ibool* is_insert, /*!< out: TRUE if insert undo log */ 73 ulint* rseg_id, /*!< out: rollback segment id */ 74 ulint* page_no, /*!< out: page number */ 75 ulint* offset) /*!< out: offset of the undo 76 entry within page */ 77{ 78#if DATA_ROLL_PTR_LEN != 7 79# error "DATA_ROLL_PTR_LEN != 7" 80#endif 81#if TRUE != 1 82# error "TRUE != 1" 83#endif 84 ut_ad(roll_ptr < (1ULL << 56)); 85 *offset = (ulint) roll_ptr & 0xFFFF; 86 roll_ptr >>= 16; 87 *page_no = (ulint) roll_ptr & 0xFFFFFFFF; 88 roll_ptr >>= 32; 89 *rseg_id = (ulint) roll_ptr & 0x7F; 90 roll_ptr >>= 7; 91 *is_insert = (ibool) roll_ptr; /* TRUE==1 */ 92} 93 94/***********************************************************************//** 95Returns TRUE if the roll pointer is of the insert type. 96@return TRUE if insert undo log */ 97UNIV_INLINE 98ibool 99trx_undo_roll_ptr_is_insert( 100/*========================*/ 101 roll_ptr_t roll_ptr) /*!< in: roll pointer */ 102{ 103#if DATA_ROLL_PTR_LEN != 7 104# error "DATA_ROLL_PTR_LEN != 7" 105#endif 106#if TRUE != 1 107# error "TRUE != 1" 108#endif 109 ut_ad(roll_ptr < (1ULL << 56)); 110 return((ibool) (roll_ptr >> 55)); 111} 112 113/***********************************************************************//** 114Returns true if the record is of the insert type. 115@return true if the record was freshly inserted (not updated). */ 116UNIV_INLINE 117bool 118trx_undo_trx_id_is_insert( 119/*======================*/ 120 const byte* trx_id) /*!< in: DB_TRX_ID, followed by DB_ROLL_PTR */ 121{ 122#if DATA_TRX_ID + 1 != DATA_ROLL_PTR 123# error 124#endif 125 return(static_cast<bool>(trx_id[DATA_TRX_ID_LEN] >> 7)); 126} 127#endif /* !UNIV_HOTBACKUP */ 128 129/*****************************************************************//** 130Writes a roll ptr to an index page. In case that the size changes in 131some future version, this function should be used instead of 132mach_write_... */ 133UNIV_INLINE 134void 135trx_write_roll_ptr( 136/*===============*/ 137 byte* ptr, /*!< in: pointer to memory where 138 written */ 139 roll_ptr_t roll_ptr) /*!< in: roll ptr */ 140{ 141#if DATA_ROLL_PTR_LEN != 7 142# error "DATA_ROLL_PTR_LEN != 7" 143#endif 144 mach_write_to_7(ptr, roll_ptr); 145} 146 147/*****************************************************************//** 148Reads a roll ptr from an index page. In case that the roll ptr size 149changes in some future version, this function should be used instead of 150mach_read_... 151@return roll ptr */ 152UNIV_INLINE 153roll_ptr_t 154trx_read_roll_ptr( 155/*==============*/ 156 const byte* ptr) /*!< in: pointer to memory from where to read */ 157{ 158#if DATA_ROLL_PTR_LEN != 7 159# error "DATA_ROLL_PTR_LEN != 7" 160#endif 161 return(mach_read_from_7(ptr)); 162} 163 164#ifndef UNIV_HOTBACKUP 165/******************************************************************//** 166Gets an undo log page and x-latches it. 167@return pointer to page x-latched */ 168UNIV_INLINE 169page_t* 170trx_undo_page_get( 171/*==============*/ 172 ulint space, /*!< in: space where placed */ 173 ulint zip_size, /*!< in: compressed page size in bytes 174 or 0 for uncompressed pages */ 175 ulint page_no, /*!< in: page number */ 176 mtr_t* mtr) /*!< in: mtr */ 177{ 178 buf_block_t* block = buf_page_get(space, zip_size, page_no, 179 RW_X_LATCH, mtr); 180 buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); 181 182 return(buf_block_get_frame(block)); 183} 184 185/******************************************************************//** 186Gets an undo log page and s-latches it. 187@return pointer to page s-latched */ 188UNIV_INLINE 189page_t* 190trx_undo_page_get_s_latched( 191/*========================*/ 192 ulint space, /*!< in: space where placed */ 193 ulint zip_size, /*!< in: compressed page size in bytes 194 or 0 for uncompressed pages */ 195 ulint page_no, /*!< in: page number */ 196 mtr_t* mtr) /*!< in: mtr */ 197{ 198 buf_block_t* block = buf_page_get(space, zip_size, page_no, 199 RW_S_LATCH, mtr); 200 buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); 201 202 return(buf_block_get_frame(block)); 203} 204 205/******************************************************************//** 206Returns the start offset of the undo log records of the specified undo 207log on the page. 208@return start offset */ 209UNIV_INLINE 210ulint 211trx_undo_page_get_start( 212/*====================*/ 213 page_t* undo_page,/*!< in: undo log page */ 214 ulint page_no,/*!< in: undo log header page number */ 215 ulint offset) /*!< in: undo log header offset on page */ 216{ 217 ulint start; 218 219 if (page_no == page_get_page_no(undo_page)) { 220 221 start = mach_read_from_2(offset + undo_page 222 + TRX_UNDO_LOG_START); 223 } else { 224 start = TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE; 225 } 226 227 return(start); 228} 229 230/******************************************************************//** 231Returns the end offset of the undo log records of the specified undo 232log on the page. 233@return end offset */ 234UNIV_INLINE 235ulint 236trx_undo_page_get_end( 237/*==================*/ 238 page_t* undo_page,/*!< in: undo log page */ 239 ulint page_no,/*!< in: undo log header page number */ 240 ulint offset) /*!< in: undo log header offset on page */ 241{ 242 trx_ulogf_t* log_hdr; 243 ulint end; 244 245 if (page_no == page_get_page_no(undo_page)) { 246 247 log_hdr = undo_page + offset; 248 249 end = mach_read_from_2(log_hdr + TRX_UNDO_NEXT_LOG); 250 251 if (end == 0) { 252 end = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR 253 + TRX_UNDO_PAGE_FREE); 254 } 255 } else { 256 end = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR 257 + TRX_UNDO_PAGE_FREE); 258 } 259 260 return(end); 261} 262 263/******************************************************************//** 264Returns the previous undo record on the page in the specified log, or 265NULL if none exists. 266@return pointer to record, NULL if none */ 267UNIV_INLINE 268trx_undo_rec_t* 269trx_undo_page_get_prev_rec( 270/*=======================*/ 271 trx_undo_rec_t* rec, /*!< in: undo log record */ 272 ulint page_no,/*!< in: undo log header page number */ 273 ulint offset) /*!< in: undo log header offset on page */ 274{ 275 page_t* undo_page; 276 ulint start; 277 278 undo_page = (page_t*) ut_align_down(rec, UNIV_PAGE_SIZE); 279 280 start = trx_undo_page_get_start(undo_page, page_no, offset); 281 282 if (start + undo_page == rec) { 283 284 return(NULL); 285 } 286 287 return(undo_page + mach_read_from_2(rec - 2)); 288} 289 290/******************************************************************//** 291Returns the next undo log record on the page in the specified log, or 292NULL if none exists. 293@return pointer to record, NULL if none */ 294UNIV_INLINE 295trx_undo_rec_t* 296trx_undo_page_get_next_rec( 297/*=======================*/ 298 trx_undo_rec_t* rec, /*!< in: undo log record */ 299 ulint page_no,/*!< in: undo log header page number */ 300 ulint offset) /*!< in: undo log header offset on page */ 301{ 302 page_t* undo_page; 303 ulint end; 304 ulint next; 305 306 undo_page = (page_t*) ut_align_down(rec, UNIV_PAGE_SIZE); 307 308 end = trx_undo_page_get_end(undo_page, page_no, offset); 309 310 next = mach_read_from_2(rec); 311 312 if (next == end) { 313 314 return(NULL); 315 } 316 317 return(undo_page + next); 318} 319 320/******************************************************************//** 321Returns the last undo record on the page in the specified undo log, or 322NULL if none exists. 323@return pointer to record, NULL if none */ 324UNIV_INLINE 325trx_undo_rec_t* 326trx_undo_page_get_last_rec( 327/*=======================*/ 328 page_t* undo_page,/*!< in: undo log page */ 329 ulint page_no,/*!< in: undo log header page number */ 330 ulint offset) /*!< in: undo log header offset on page */ 331{ 332 ulint start; 333 ulint end; 334 335 start = trx_undo_page_get_start(undo_page, page_no, offset); 336 end = trx_undo_page_get_end(undo_page, page_no, offset); 337 338 if (start == end) { 339 340 return(NULL); 341 } 342 343 return(undo_page + mach_read_from_2(undo_page + end - 2)); 344} 345 346/******************************************************************//** 347Returns the first undo record on the page in the specified undo log, or 348NULL if none exists. 349@return pointer to record, NULL if none */ 350UNIV_INLINE 351trx_undo_rec_t* 352trx_undo_page_get_first_rec( 353/*========================*/ 354 page_t* undo_page,/*!< in: undo log page */ 355 ulint page_no,/*!< in: undo log header page number */ 356 ulint offset) /*!< in: undo log header offset on page */ 357{ 358 ulint start; 359 ulint end; 360 361 start = trx_undo_page_get_start(undo_page, page_no, offset); 362 end = trx_undo_page_get_end(undo_page, page_no, offset); 363 364 if (start == end) { 365 366 return(NULL); 367 } 368 369 return(undo_page + start); 370} 371#endif /* !UNIV_HOTBACKUP */ 372