| 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 | |