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