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, Suite 500, 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