1 | /***************************************************************************** |
2 | |
3 | Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. |
4 | Copyright (c) 2017, MariaDB Corporation. |
5 | |
6 | This program is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free Software |
8 | Foundation; version 2 of the License. |
9 | |
10 | This program is distributed in the hope that it will be useful, but WITHOUT |
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
12 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License along with |
15 | this program; if not, write to the Free Software Foundation, Inc., |
16 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
17 | |
18 | *****************************************************************************/ |
19 | |
20 | /**************************************************//** |
21 | @file include/mtr0log.ic |
22 | Mini-transaction logging routines |
23 | |
24 | Created 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 | /********************************************************//** |
33 | Opens 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 */ |
35 | UNIV_INLINE |
36 | byte* |
37 | mlog_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 | /********************************************************//** |
55 | Closes a buffer opened to mlog. */ |
56 | UNIV_INLINE |
57 | void |
58 | mlog_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 | /********************************************************//** |
70 | Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */ |
71 | UNIV_INLINE |
72 | void |
73 | mlog_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 | /********************************************************//** |
102 | Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */ |
103 | UNIV_INLINE |
104 | void |
105 | mlog_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 | /********************************************************//** |
121 | Catenates a compressed ulint to mlog. */ |
122 | UNIV_INLINE |
123 | void |
124 | mlog_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 | /********************************************************//** |
145 | Catenates a compressed 64-bit integer to mlog. */ |
146 | UNIV_INLINE |
147 | void |
148 | mlog_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 */ |
175 | UNIV_INLINE |
176 | byte* |
177 | mlog_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 | /********************************************************//** |
205 | Writes the initial part of a log record (3..11 bytes). |
206 | If the implementation of this function is changed, all |
207 | size parameters to mlog_open() should be adjusted accordingly! |
208 | @return new value of log_ptr */ |
209 | UNIV_INLINE |
210 | byte* |
211 | mlog_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 | |