1/***************************************************************************** 2 3Copyright (c) 1995, 2020, Oracle and/or its affiliates. All Rights Reserved. 4 5This program is free software; you can redistribute it and/or modify it under 6the terms of the GNU General Public License, version 2.0, as published by the 7Free Software Foundation. 8 9This program is also distributed with certain software (including but not 10limited to OpenSSL) that is licensed under separate terms, as designated in a 11particular file or component or in included license documentation. The authors 12of MySQL hereby grant you an additional permission to link the program and 13your derivative works with the separately licensed software that they have 14included with MySQL. 15 16This program is distributed in the hope that it will be useful, but WITHOUT 17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 18FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, 19for 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 St, Fifth Floor, Boston, MA 02110-1301 USA 24 25*****************************************************************************/ 26 27/** @file include/mtr0log.ic 28 Mini-transaction logging routines 29 30 Created 12/7/1995 Heikki Tuuri 31 *******************************************************/ 32 33#include "buf0dblwr.h" 34#include "fsp0types.h" 35#include "mach0data.h" 36#include "trx0types.h" 37 38#include "mysqld_error.h" 39 40UNIV_INLINE 41bool mlog_open(mtr_t *mtr, ulint size, byte *&buffer) { 42 mtr->set_modified(); 43 return (mlog_open_metadata(mtr, size, buffer)); 44} 45 46UNIV_INLINE 47bool mlog_open_metadata(mtr_t *mtr, ulint size, byte *&buffer) { 48 if (mtr_get_log_mode(mtr) == MTR_LOG_NONE || 49 mtr_get_log_mode(mtr) == MTR_LOG_NO_REDO) { 50 buffer = nullptr; 51 return (false); 52 } 53 54 buffer = mtr->get_log()->open(size); 55 return (buffer != nullptr); 56} 57 58/** Closes a buffer opened to mlog. */ 59UNIV_INLINE 60void mlog_close(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/** Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */ 70UNIV_INLINE 71void mlog_catenate_ulint(mtr_buf_t *mtr_buf, /*!< in/out: buffer to write */ 72 ulint val, /*!< in: value to write */ 73 mlog_id_t type) /*!< in: type of value to write */ 74{ 75 ut_ad(MLOG_1BYTE == 1); 76 ut_ad(MLOG_2BYTES == 2); 77 ut_ad(MLOG_4BYTES == 4); 78 ut_ad(MLOG_8BYTES == 8); 79 80 byte *ptr = mtr_buf->push<byte *>(type); 81 82 switch (type) { 83 case MLOG_4BYTES: 84 mach_write_to_4(ptr, val); 85 break; 86 case MLOG_2BYTES: 87 mach_write_to_2(ptr, val); 88 break; 89 case MLOG_1BYTE: 90 mach_write_to_1(ptr, val); 91 break; 92 default: 93 ut_error; 94 } 95} 96 97/** Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */ 98UNIV_INLINE 99void mlog_catenate_ulint( 100 mtr_t *mtr, /*!< in/out: mtr */ 101 ulint val, /*!< in: value to write */ 102 mlog_id_t type) /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */ 103{ 104 if (mtr_get_log_mode(mtr) == MTR_LOG_NONE || 105 mtr_get_log_mode(mtr) == MTR_LOG_NO_REDO) { 106 return; 107 } 108 109 mlog_catenate_ulint(mtr->get_log(), val, type); 110} 111 112/** Catenates a compressed ulint to mlog. */ 113UNIV_INLINE 114void mlog_catenate_ulint_compressed(mtr_t *mtr, /*!< in: mtr */ 115 ulint val) /*!< in: value to write */ 116{ 117 byte *log_ptr = nullptr; 118 119 /* If no logging is requested, we may return now */ 120 if (!mlog_open(mtr, 10, log_ptr)) { 121 return; 122 } 123 124 log_ptr += mach_write_compressed(log_ptr, val); 125 126 mlog_close(mtr, log_ptr); 127} 128 129/** Catenates a compressed 64-bit integer to mlog. */ 130UNIV_INLINE 131void mlog_catenate_ull_compressed(mtr_t *mtr, /*!< in: mtr */ 132 ib_uint64_t val) /*!< in: value to write */ 133{ 134 byte *log_ptr = nullptr; 135 136 /* If no logging is requested, we may return now */ 137 if (!mlog_open(mtr, 15, log_ptr)) { 138 return; 139 } 140 141 log_ptr += mach_u64_write_compressed(log_ptr, val); 142 143 mlog_close(mtr, log_ptr); 144} 145 146UNIV_INLINE 147byte *mlog_write_initial_dict_log_record(mlog_id_t type, table_id_t id, 148 uint64_t version, byte *log_ptr, 149 mtr_t *mtr) { 150 ut_ad(type <= MLOG_BIGGEST_TYPE); 151 ut_ad(type == MLOG_TABLE_DYNAMIC_META); 152 153 mach_write_to_1(log_ptr, type); 154 log_ptr++; 155 156 log_ptr += mach_u64_write_much_compressed(log_ptr, id); 157 log_ptr += mach_u64_write_much_compressed(log_ptr, version); 158 159 mtr->added_rec(); 160 return (log_ptr); 161} 162 163/** Writes a log record about an operation. 164@param[in] type redo log record type 165@param[in] space_id tablespace identifier 166@param[in] page_no page number 167@param[in,out] log_ptr current end of mini-transaction log 168@param[in,out] mtr mini-transaction 169@return end of mini-transaction log */ 170UNIV_INLINE 171byte *mlog_write_initial_log_record_low(mlog_id_t type, space_id_t space_id, 172 page_no_t page_no, byte *log_ptr, 173 mtr_t *mtr) { 174 ut_ad(type <= MLOG_BIGGEST_TYPE); 175 176 mach_write_to_1(log_ptr, type); 177 log_ptr++; 178 179 log_ptr += mach_write_compressed(log_ptr, space_id); 180 log_ptr += mach_write_compressed(log_ptr, page_no); 181 182 mtr->added_rec(); 183 return (log_ptr); 184} 185 186#ifndef UNIV_HOTBACKUP 187/** Writes the initial part of a log record (3..11 bytes). 188 If the implementation of this function is changed, all 189 size parameters to mlog_open() should be adjusted accordingly! 190 @return new value of log_ptr */ 191UNIV_INLINE 192byte *mlog_write_initial_log_record_fast( 193 const byte *ptr, /*!< in: pointer to (inside) a buffer 194 frame holding the file page where 195 modification is made */ 196 mlog_id_t type, /*!< in: log item type: MLOG_1BYTE, ... */ 197 byte *log_ptr, /*!< in: pointer to mtr log which has 198 been opened */ 199 mtr_t *mtr) /*!< in/out: mtr */ 200{ 201 const byte *page; 202 space_id_t space; 203 page_no_t offset; 204 205 ut_ad(log_ptr); 206 ut_d(mtr->memo_modify_page(ptr)); 207 208 page = (const byte *)ut_align_down(ptr, UNIV_PAGE_SIZE); 209 space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); 210 offset = mach_read_from_4(page + FIL_PAGE_OFFSET); 211 212 /* check whether the page is in the doublewrite buffer; 213 the doublewrite buffer is located in pages 214 FSP_EXTENT_SIZE, ..., 3 * FSP_EXTENT_SIZE - 1 in the 215 system tablespace */ 216 217 /* We don't redo log the double write buffer */ 218 if (space == TRX_SYS_SPACE && offset >= FSP_EXTENT_SIZE && 219 offset < 3 * FSP_EXTENT_SIZE) { 220 return (log_ptr); 221 } 222 223 return (mlog_write_initial_log_record_low(type, space, offset, log_ptr, mtr)); 224} 225#endif /* !UNIV_HOTBACKUP */ 226