1/*****************************************************************************
2
3Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
4Copyright (c) 2017, 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/mtr0log.ic
22Mini-transaction logging routines
23
24Created 12/7/1995 Heikki Tuuri
25*******************************************************/
26
27#include "buf0dblwr.h"
28#include "fsp0types.h"
29#include "mach0data.h"
30#include "trx0types.h"
31
32/********************************************************//**
33Opens a buffer to mlog. It must be closed with mlog_close.
34@return buffer, NULL if log mode MTR_LOG_NONE or MTR_LOG_NO_REDO */
35UNIV_INLINE
36byte*
37mlog_open(
38/*======*/
39 mtr_t* mtr, /*!< in: mtr */
40 ulint size) /*!< in: buffer size in bytes; MUST be
41 smaller than mtr_t::buf_t::MAX_DATA_SIZE! */
42{
43 mtr->set_modified();
44
45 if (mtr_get_log_mode(mtr) == MTR_LOG_NONE
46 || mtr_get_log_mode(mtr) == MTR_LOG_NO_REDO) {
47
48 return(NULL);
49 }
50
51 return(mtr->get_log()->open(size));
52}
53
54/********************************************************//**
55Closes a buffer opened to mlog. */
56UNIV_INLINE
57void
58mlog_close(
59/*=======*/
60 mtr_t* mtr, /*!< in: mtr */
61 byte* ptr) /*!< in: buffer space from ptr up was not used */
62{
63 ut_ad(mtr_get_log_mode(mtr) != MTR_LOG_NONE);
64 ut_ad(mtr_get_log_mode(mtr) != MTR_LOG_NO_REDO);
65
66 mtr->get_log()->close(ptr);
67}
68
69/********************************************************//**
70Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */
71UNIV_INLINE
72void
73mlog_catenate_ulint(
74/*================*/
75 mtr_buf_t* mtr_buf, /*!< in/out: buffer to write */
76 ulint val, /*!< in: value to write */
77 mlog_id_t type) /*!< in: type of value to write */
78{
79 compile_time_assert(MLOG_1BYTE == 1);
80 compile_time_assert(MLOG_2BYTES == 2);
81 compile_time_assert(MLOG_4BYTES == 4);
82 compile_time_assert(MLOG_8BYTES == 8);
83
84 byte* ptr = mtr_buf->push<byte*>(type);
85
86 switch (type) {
87 case MLOG_4BYTES:
88 mach_write_to_4(ptr, val);
89 break;
90 case MLOG_2BYTES:
91 mach_write_to_2(ptr, val);
92 break;
93 case MLOG_1BYTE:
94 mach_write_to_1(ptr, val);
95 break;
96 default:
97 ut_error;
98 }
99}
100
101/********************************************************//**
102Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */
103UNIV_INLINE
104void
105mlog_catenate_ulint(
106/*================*/
107 mtr_t* mtr, /*!< in/out: mtr */
108 ulint val, /*!< in: value to write */
109 mlog_id_t type) /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
110{
111 if (mtr_get_log_mode(mtr) == MTR_LOG_NONE
112 || mtr_get_log_mode(mtr) == MTR_LOG_NO_REDO) {
113
114 return;
115 }
116
117 mlog_catenate_ulint(mtr->get_log(), val, type);
118}
119
120/********************************************************//**
121Catenates a compressed ulint to mlog. */
122UNIV_INLINE
123void
124mlog_catenate_ulint_compressed(
125/*===========================*/
126 mtr_t* mtr, /*!< in: mtr */
127 ulint val) /*!< in: value to write */
128{
129 byte* log_ptr;
130
131 log_ptr = mlog_open(mtr, 10);
132
133 /* If no logging is requested, we may return now */
134 if (log_ptr == NULL) {
135
136 return;
137 }
138
139 log_ptr += mach_write_compressed(log_ptr, val);
140
141 mlog_close(mtr, log_ptr);
142}
143
144/********************************************************//**
145Catenates a compressed 64-bit integer to mlog. */
146UNIV_INLINE
147void
148mlog_catenate_ull_compressed(
149/*=========================*/
150 mtr_t* mtr, /*!< in: mtr */
151 ib_uint64_t val) /*!< in: value to write */
152{
153 byte* log_ptr;
154
155 log_ptr = mlog_open(mtr, 15);
156
157 /* If no logging is requested, we may return now */
158 if (log_ptr == NULL) {
159
160 return;
161 }
162
163 log_ptr += mach_u64_write_compressed(log_ptr, val);
164
165 mlog_close(mtr, log_ptr);
166}
167
168/** Writes a log record about an operation.
169@param[in] type redo log record type
170@param[in] space_id tablespace identifier
171@param[in] page_no page number
172@param[in,out] log_ptr current end of mini-transaction log
173@param[in,out] mtr mini-transaction
174@return end of mini-transaction log */
175UNIV_INLINE
176byte*
177mlog_write_initial_log_record_low(
178 mlog_id_t type,
179 ulint space_id,
180 ulint page_no,
181 byte* log_ptr,
182 mtr_t* mtr)
183{
184 ut_ad(type <= MLOG_BIGGEST_TYPE || EXTRA_CHECK_MLOG_NUMBER(type));
185 ut_ad(type == MLOG_FILE_NAME
186 || type == MLOG_FILE_DELETE
187 || type == MLOG_FILE_CREATE2
188 || type == MLOG_FILE_RENAME2
189 || type == MLOG_INDEX_LOAD
190 || type == MLOG_TRUNCATE
191 || type == MLOG_FILE_WRITE_CRYPT_DATA
192 || mtr->is_named_space(space_id));
193
194 mach_write_to_1(log_ptr, type);
195 log_ptr++;
196
197 log_ptr += mach_write_compressed(log_ptr, space_id);
198 log_ptr += mach_write_compressed(log_ptr, page_no);
199
200 mtr->added_rec();
201 return(log_ptr);
202}
203
204/********************************************************//**
205Writes the initial part of a log record (3..11 bytes).
206If the implementation of this function is changed, all
207size parameters to mlog_open() should be adjusted accordingly!
208@return new value of log_ptr */
209UNIV_INLINE
210byte*
211mlog_write_initial_log_record_fast(
212/*===============================*/
213 const byte* ptr, /*!< in: pointer to (inside) a buffer
214 frame holding the file page where
215 modification is made */
216 mlog_id_t type, /*!< in: log item type: MLOG_1BYTE, ... */
217 byte* log_ptr,/*!< in: pointer to mtr log which has
218 been opened */
219 mtr_t* mtr) /*!< in/out: mtr */
220{
221 const byte* page;
222 ulint space;
223 ulint offset;
224
225 ut_ad(log_ptr);
226 ut_d(mtr->memo_modify_page(ptr));
227
228 page = (const byte*) ut_align_down(ptr, srv_page_size);
229 space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
230 offset = mach_read_from_4(page + FIL_PAGE_OFFSET);
231
232 /* check whether the page is in the doublewrite buffer;
233 the doublewrite buffer is located in pages
234 FSP_EXTENT_SIZE, ..., 3 * FSP_EXTENT_SIZE - 1 in the
235 system tablespace */
236
237 if (space == TRX_SYS_SPACE
238 && offset >= FSP_EXTENT_SIZE && offset < 3 * FSP_EXTENT_SIZE) {
239 ut_ad(buf_dblwr_being_created);
240 /* Do nothing: we only come to this branch in an
241 InnoDB database creation. We do not redo log
242 anything for the doublewrite buffer pages. */
243 return(log_ptr);
244 }
245
246 return(mlog_write_initial_log_record_low(type, space, offset,
247 log_ptr, mtr));
248}
249