1 | /***************************************************************************** |
2 | |
3 | Copyright (c) 1995, 2014, 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/mtr0mtr.ic |
22 | Mini-transaction buffer |
23 | |
24 | Created 11/26/1995 Heikki Tuuri |
25 | *******************************************************/ |
26 | |
27 | #include "buf0buf.h" |
28 | |
29 | /** |
30 | Pushes an object to an mtr memo stack. */ |
31 | void |
32 | mtr_t::memo_push(void* object, mtr_memo_type_t type) |
33 | { |
34 | ut_ad(is_active()); |
35 | ut_ad(object != NULL); |
36 | ut_ad(type >= MTR_MEMO_PAGE_S_FIX); |
37 | ut_ad(type <= MTR_MEMO_SX_LOCK); |
38 | ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); |
39 | ut_ad(ut_is_2pow(type)); |
40 | |
41 | /* If this mtr has x-fixed a clean page then we set |
42 | the made_dirty flag. This tells us if we need to |
43 | grab log_flush_order_mutex at mtr_commit so that we |
44 | can insert the dirtied page to the flush list. */ |
45 | |
46 | if ((type == MTR_MEMO_PAGE_X_FIX || type == MTR_MEMO_PAGE_SX_FIX) |
47 | && !m_impl.m_made_dirty) { |
48 | |
49 | m_impl.m_made_dirty = is_block_dirtied( |
50 | reinterpret_cast<const buf_block_t*>(object)); |
51 | } |
52 | |
53 | mtr_memo_slot_t* slot; |
54 | |
55 | slot = m_impl.m_memo.push<mtr_memo_slot_t*>(sizeof(*slot)); |
56 | |
57 | slot->type = type; |
58 | slot->object = object; |
59 | } |
60 | |
61 | /** |
62 | Releases the (index tree) s-latch stored in an mtr memo after a |
63 | savepoint. */ |
64 | void |
65 | mtr_t::release_s_latch_at_savepoint( |
66 | ulint savepoint, |
67 | rw_lock_t* lock) |
68 | { |
69 | ut_ad(is_active()); |
70 | ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); |
71 | |
72 | ut_ad(m_impl.m_memo.size() > savepoint); |
73 | |
74 | mtr_memo_slot_t* slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint); |
75 | |
76 | ut_ad(slot->object == lock); |
77 | ut_ad(slot->type == MTR_MEMO_S_LOCK); |
78 | |
79 | rw_lock_s_unlock(lock); |
80 | |
81 | slot->object = NULL; |
82 | } |
83 | |
84 | /** |
85 | SX-latches the not yet latched block after a savepoint. */ |
86 | |
87 | void |
88 | mtr_t::sx_latch_at_savepoint( |
89 | ulint savepoint, |
90 | buf_block_t* block) |
91 | { |
92 | ut_ad(is_active()); |
93 | ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); |
94 | ut_ad(m_impl.m_memo.size() > savepoint); |
95 | |
96 | ut_ad(!memo_contains_flagged( |
97 | block, |
98 | MTR_MEMO_PAGE_S_FIX |
99 | | MTR_MEMO_PAGE_X_FIX |
100 | | MTR_MEMO_PAGE_SX_FIX)); |
101 | |
102 | mtr_memo_slot_t* slot; |
103 | |
104 | slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint); |
105 | |
106 | ut_ad(slot->object == block); |
107 | |
108 | /* == RW_NO_LATCH */ |
109 | ut_a(slot->type == MTR_MEMO_BUF_FIX); |
110 | |
111 | rw_lock_sx_lock(&block->lock); |
112 | |
113 | if (!m_impl.m_made_dirty) { |
114 | m_impl.m_made_dirty = is_block_dirtied(block); |
115 | } |
116 | |
117 | slot->type = MTR_MEMO_PAGE_SX_FIX; |
118 | } |
119 | |
120 | /** |
121 | X-latches the not yet latched block after a savepoint. */ |
122 | |
123 | void |
124 | mtr_t::x_latch_at_savepoint( |
125 | ulint savepoint, |
126 | buf_block_t* block) |
127 | { |
128 | ut_ad(is_active()); |
129 | ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); |
130 | ut_ad(m_impl.m_memo.size() > savepoint); |
131 | |
132 | ut_ad(!memo_contains_flagged( |
133 | block, |
134 | MTR_MEMO_PAGE_S_FIX |
135 | | MTR_MEMO_PAGE_X_FIX |
136 | | MTR_MEMO_PAGE_SX_FIX)); |
137 | |
138 | mtr_memo_slot_t* slot; |
139 | |
140 | slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint); |
141 | |
142 | ut_ad(slot->object == block); |
143 | |
144 | /* == RW_NO_LATCH */ |
145 | ut_a(slot->type == MTR_MEMO_BUF_FIX); |
146 | |
147 | rw_lock_x_lock(&block->lock); |
148 | |
149 | if (!m_impl.m_made_dirty) { |
150 | m_impl.m_made_dirty = is_block_dirtied(block); |
151 | } |
152 | |
153 | slot->type = MTR_MEMO_PAGE_X_FIX; |
154 | } |
155 | |
156 | /** |
157 | Releases the block in an mtr memo after a savepoint. */ |
158 | |
159 | void |
160 | mtr_t::release_block_at_savepoint( |
161 | ulint savepoint, |
162 | buf_block_t* block) |
163 | { |
164 | ut_ad(is_active()); |
165 | ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); |
166 | |
167 | mtr_memo_slot_t* slot; |
168 | |
169 | slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint); |
170 | |
171 | ut_a(slot->object == block); |
172 | |
173 | buf_block_unfix(reinterpret_cast<buf_block_t*>(block)); |
174 | |
175 | buf_page_release_latch(block, slot->type); |
176 | |
177 | slot->object = NULL; |
178 | } |
179 | |
180 | /** |
181 | Gets the logging mode of a mini-transaction. |
182 | @return logging mode: MTR_LOG_NONE, ... */ |
183 | |
184 | mtr_log_t |
185 | mtr_t::get_log_mode() const |
186 | { |
187 | ut_ad(m_impl.m_log_mode >= MTR_LOG_ALL); |
188 | ut_ad(m_impl.m_log_mode <= MTR_LOG_SHORT_INSERTS); |
189 | |
190 | return(m_impl.m_log_mode); |
191 | } |
192 | |
193 | /** |
194 | Changes the logging mode of a mini-transaction. |
195 | @return old mode */ |
196 | |
197 | mtr_log_t |
198 | mtr_t::set_log_mode(mtr_log_t mode) |
199 | { |
200 | ut_ad(mode >= MTR_LOG_ALL); |
201 | ut_ad(mode <= MTR_LOG_SHORT_INSERTS); |
202 | |
203 | const mtr_log_t old_mode = m_impl.m_log_mode; |
204 | |
205 | switch (old_mode) { |
206 | case MTR_LOG_NO_REDO: |
207 | /* Once this mode is set, it must not be changed. */ |
208 | ut_ad(mode == MTR_LOG_NO_REDO || mode == MTR_LOG_NONE); |
209 | return(old_mode); |
210 | case MTR_LOG_NONE: |
211 | if (mode == old_mode || mode == MTR_LOG_SHORT_INSERTS) { |
212 | /* Keep MTR_LOG_NONE. */ |
213 | return(old_mode); |
214 | } |
215 | /* fall through */ |
216 | case MTR_LOG_SHORT_INSERTS: |
217 | ut_ad(mode == MTR_LOG_ALL); |
218 | /* fall through */ |
219 | case MTR_LOG_ALL: |
220 | /* MTR_LOG_NO_REDO can only be set before generating |
221 | any redo log records. */ |
222 | ut_ad(mode != MTR_LOG_NO_REDO |
223 | || m_impl.m_n_log_recs == 0); |
224 | m_impl.m_log_mode = mode; |
225 | return(old_mode); |
226 | } |
227 | |
228 | ut_ad(0); |
229 | return(old_mode); |
230 | } |
231 | |
232 | /** |
233 | Locks a lock in s-mode. */ |
234 | |
235 | void |
236 | mtr_t::s_lock(rw_lock_t* lock, const char* file, unsigned line) |
237 | { |
238 | rw_lock_s_lock_inline(lock, 0, file, line); |
239 | |
240 | memo_push(lock, MTR_MEMO_S_LOCK); |
241 | } |
242 | |
243 | /** |
244 | Locks a lock in x-mode. */ |
245 | |
246 | void |
247 | mtr_t::x_lock(rw_lock_t* lock, const char* file, unsigned line) |
248 | { |
249 | rw_lock_x_lock_inline(lock, 0, file, line); |
250 | |
251 | memo_push(lock, MTR_MEMO_X_LOCK); |
252 | } |
253 | |
254 | /** |
255 | Locks a lock in sx-mode. */ |
256 | |
257 | void |
258 | mtr_t::sx_lock(rw_lock_t* lock, const char* file, unsigned line) |
259 | { |
260 | rw_lock_sx_lock_inline(lock, 0, file, line); |
261 | |
262 | memo_push(lock, MTR_MEMO_SX_LOCK); |
263 | } |
264 | |
265 | /** |
266 | Reads 1 - 4 bytes from a file page buffered in the buffer pool. |
267 | @return value read */ |
268 | |
269 | ulint |
270 | mtr_t::read_ulint(const byte* ptr, mlog_id_t type) const |
271 | { |
272 | ut_ad(is_active()); |
273 | |
274 | ut_ad(memo_contains_page_flagged( |
275 | ptr, |
276 | MTR_MEMO_PAGE_S_FIX |
277 | | MTR_MEMO_PAGE_X_FIX |
278 | | MTR_MEMO_PAGE_SX_FIX)); |
279 | |
280 | return(mach_read_ulint(ptr, type)); |
281 | } |
282 | |