1/***************************************************************************** 2 3Copyright (c) 1995, 2021, Oracle and/or its affiliates. 4 5This program is free software; you can redistribute it and/or modify 6it under the terms of the GNU General Public License, version 2.0, 7as published by the Free Software Foundation. 8 9This program is also distributed with certain software (including 10but not limited to OpenSSL) that is licensed under separate terms, 11as designated in a particular file or component or in included license 12documentation. The authors of MySQL hereby grant you an additional 13permission to link the program and your derivative works with the 14separately licensed software that they have included with MySQL. 15 16This program is distributed in the hope that it will be useful, 17but WITHOUT ANY WARRANTY; without even the implied warranty of 18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19GNU General Public License, version 2.0, for more details. 20 21You should have received a copy of the GNU General Public License along with 22this program; if not, write to the Free Software Foundation, Inc., 2351 Franklin Street, Suite 500, Boston, MA 02110-1335 USA 24 25*****************************************************************************/ 26 27/**************************************************//** 28@file include/mtr0mtr.ic 29Mini-transaction buffer 30 31Created 11/26/1995 Heikki Tuuri 32*******************************************************/ 33 34#include "buf0buf.h" 35 36/** 37Pushes an object to an mtr memo stack. */ 38void 39mtr_t::memo_push(void* object, mtr_memo_type_t type) 40{ 41 ut_ad(is_active()); 42 ut_ad(object != NULL); 43 ut_ad(type >= MTR_MEMO_PAGE_S_FIX); 44 ut_ad(type <= MTR_MEMO_SX_LOCK); 45 ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); 46 ut_ad(ut_is_2pow(type)); 47 48 /* If this mtr has x-fixed a clean page then we set 49 the made_dirty flag. This tells us if we need to 50 grab log_flush_order_mutex at mtr_commit so that we 51 can insert the dirtied page to the flush list. */ 52 53 if ((type == MTR_MEMO_PAGE_X_FIX || type == MTR_MEMO_PAGE_SX_FIX) 54 && !m_impl.m_made_dirty) { 55 56 m_impl.m_made_dirty = is_block_dirtied( 57 reinterpret_cast<const buf_block_t*>(object)); 58 } else if (type == MTR_MEMO_BUF_FIX && !m_impl.m_made_dirty) { 59 60 if (reinterpret_cast<const buf_block_t*>( 61 object)->made_dirty_with_no_latch) { 62 63 m_impl.m_made_dirty = true; 64 } 65 } 66 67 mtr_memo_slot_t* slot; 68 69 slot = m_impl.m_memo.push<mtr_memo_slot_t*>(sizeof(*slot)); 70 71 slot->type = type; 72 slot->object = object; 73} 74 75/** 76Releases the (index tree) s-latch stored in an mtr memo after a 77savepoint. */ 78void 79mtr_t::release_s_latch_at_savepoint( 80 ulint savepoint, 81 rw_lock_t* lock) 82{ 83 ut_ad(is_active()); 84 ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); 85 86 ut_ad(m_impl.m_memo.size() > savepoint); 87 88 mtr_memo_slot_t* slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint); 89 90 ut_ad(slot->object == lock); 91 ut_ad(slot->type == MTR_MEMO_S_LOCK); 92 93 rw_lock_s_unlock(lock); 94 95 slot->object = NULL; 96} 97 98/** 99SX-latches the not yet latched block after a savepoint. */ 100 101void 102mtr_t::sx_latch_at_savepoint( 103 ulint savepoint, 104 buf_block_t* block) 105{ 106 ut_ad(is_active()); 107 ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); 108 ut_ad(m_impl.m_memo.size() > savepoint); 109 110 ut_ad(!memo_contains_flagged( 111 block, 112 MTR_MEMO_PAGE_S_FIX 113 | MTR_MEMO_PAGE_X_FIX 114 | MTR_MEMO_PAGE_SX_FIX)); 115 116 mtr_memo_slot_t* slot; 117 118 slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint); 119 120 ut_ad(slot->object == block); 121 122 /* == RW_NO_LATCH */ 123 ut_a(slot->type == MTR_MEMO_BUF_FIX); 124 125 rw_lock_sx_lock(&block->lock); 126 127 if (!m_impl.m_made_dirty) { 128 m_impl.m_made_dirty = is_block_dirtied(block); 129 } 130 131 slot->type = MTR_MEMO_PAGE_SX_FIX; 132} 133 134/** 135X-latches the not yet latched block after a savepoint. */ 136 137void 138mtr_t::x_latch_at_savepoint( 139 ulint savepoint, 140 buf_block_t* block) 141{ 142 ut_ad(is_active()); 143 ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); 144 ut_ad(m_impl.m_memo.size() > savepoint); 145 146 ut_ad(!memo_contains_flagged( 147 block, 148 MTR_MEMO_PAGE_S_FIX 149 | MTR_MEMO_PAGE_X_FIX 150 | MTR_MEMO_PAGE_SX_FIX)); 151 152 mtr_memo_slot_t* slot; 153 154 slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint); 155 156 ut_ad(slot->object == block); 157 158 /* == RW_NO_LATCH */ 159 ut_a(slot->type == MTR_MEMO_BUF_FIX); 160 161 rw_lock_x_lock(&block->lock); 162 163 if (!m_impl.m_made_dirty) { 164 m_impl.m_made_dirty = is_block_dirtied(block); 165 } 166 167 slot->type = MTR_MEMO_PAGE_X_FIX; 168} 169 170/** 171Releases the block in an mtr memo after a savepoint. */ 172 173void 174mtr_t::release_block_at_savepoint( 175 ulint savepoint, 176 buf_block_t* block) 177{ 178 ut_ad(is_active()); 179 ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); 180 181 mtr_memo_slot_t* slot; 182 183 slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint); 184 185 ut_a(slot->object == block); 186 187 buf_page_release_latch(block, slot->type); 188 buf_block_unfix(block); 189 190 slot->object = NULL; 191} 192 193/** 194Gets the logging mode of a mini-transaction. 195@return logging mode: MTR_LOG_NONE, ... */ 196 197mtr_log_t 198mtr_t::get_log_mode() const 199{ 200 ut_ad(m_impl.m_log_mode >= MTR_LOG_ALL); 201 ut_ad(m_impl.m_log_mode <= MTR_LOG_SHORT_INSERTS); 202 203 return(m_impl.m_log_mode); 204} 205 206/** 207Changes the logging mode of a mini-transaction. 208@return old mode */ 209 210mtr_log_t 211mtr_t::set_log_mode(mtr_log_t mode) 212{ 213 ut_ad(mode >= MTR_LOG_ALL); 214 ut_ad(mode <= MTR_LOG_SHORT_INSERTS); 215 216 const mtr_log_t old_mode = m_impl.m_log_mode; 217 218 switch (old_mode) { 219 case MTR_LOG_NO_REDO: 220 /* Once this mode is set, it must not be changed. */ 221 ut_ad(mode == MTR_LOG_NO_REDO || mode == MTR_LOG_NONE); 222 return(old_mode); 223 case MTR_LOG_NONE: 224 if (mode == old_mode || mode == MTR_LOG_SHORT_INSERTS) { 225 /* Keep MTR_LOG_NONE. */ 226 return(old_mode); 227 } 228 /* fall through */ 229 case MTR_LOG_SHORT_INSERTS: 230 ut_ad(mode == MTR_LOG_ALL); 231 /* fall through */ 232 case MTR_LOG_ALL: 233 /* MTR_LOG_NO_REDO can only be set before generating 234 any redo log records. */ 235 ut_ad(mode != MTR_LOG_NO_REDO 236 || m_impl.m_n_log_recs == 0); 237 m_impl.m_log_mode = mode; 238 return(old_mode); 239 } 240 241 ut_ad(0); 242 return(old_mode); 243} 244 245/** 246Locks a lock in s-mode. */ 247 248void 249mtr_t::s_lock(rw_lock_t* lock, const char* file, ulint line) 250{ 251 rw_lock_s_lock_inline(lock, 0, file, line); 252 253 memo_push(lock, MTR_MEMO_S_LOCK); 254} 255 256/** 257Locks a lock in x-mode. */ 258 259void 260mtr_t::x_lock(rw_lock_t* lock, const char* file, ulint line) 261{ 262 rw_lock_x_lock_inline(lock, 0, file, line); 263 264 memo_push(lock, MTR_MEMO_X_LOCK); 265} 266 267/** 268Locks a lock in sx-mode. */ 269 270void 271mtr_t::sx_lock(rw_lock_t* lock, const char* file, ulint line) 272{ 273 rw_lock_sx_lock_inline(lock, 0, file, line); 274 275 memo_push(lock, MTR_MEMO_SX_LOCK); 276} 277 278/** 279Reads 1 - 4 bytes from a file page buffered in the buffer pool. 280@return value read */ 281 282ulint 283mtr_t::read_ulint(const byte* ptr, mlog_id_t type) const 284{ 285 ut_ad(is_active()); 286 287 ut_ad(memo_contains_page_flagged( 288 ptr, 289 MTR_MEMO_PAGE_S_FIX 290 | MTR_MEMO_PAGE_X_FIX 291 | MTR_MEMO_PAGE_SX_FIX)); 292 293 return(mach_read_ulint(ptr, type)); 294} 295