/***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ /**************************************************//** @file include/mtr0log.ic Mini-transaction logging routines Created 12/7/1995 Heikki Tuuri *******************************************************/ #include "buf0dblwr.h" #include "fsp0types.h" #include "mach0data.h" #include "trx0types.h" /********************************************************//** Opens a buffer to mlog. It must be closed with mlog_close. @return buffer, NULL if log mode MTR_LOG_NONE or MTR_LOG_NO_REDO */ UNIV_INLINE byte* mlog_open( /*======*/ mtr_t* mtr, /*!< in: mtr */ ulint size) /*!< in: buffer size in bytes; MUST be smaller than mtr_t::buf_t::MAX_DATA_SIZE! */ { mtr->set_modified(); if (mtr_get_log_mode(mtr) == MTR_LOG_NONE || mtr_get_log_mode(mtr) == MTR_LOG_NO_REDO) { return(NULL); } return(mtr->get_log()->open(size)); } /********************************************************//** Closes a buffer opened to mlog. */ UNIV_INLINE void mlog_close( /*=======*/ mtr_t* mtr, /*!< in: mtr */ byte* ptr) /*!< in: buffer space from ptr up was not used */ { ut_ad(mtr_get_log_mode(mtr) != MTR_LOG_NONE); ut_ad(mtr_get_log_mode(mtr) != MTR_LOG_NO_REDO); mtr->get_log()->close(ptr); } /********************************************************//** Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */ UNIV_INLINE void mlog_catenate_ulint( /*================*/ mtr_buf_t* mtr_buf, /*!< in/out: buffer to write */ ulint val, /*!< in: value to write */ mlog_id_t type) /*!< in: type of value to write */ { compile_time_assert(MLOG_1BYTE == 1); compile_time_assert(MLOG_2BYTES == 2); compile_time_assert(MLOG_4BYTES == 4); compile_time_assert(MLOG_8BYTES == 8); byte* ptr = mtr_buf->push(type); switch (type) { case MLOG_4BYTES: mach_write_to_4(ptr, val); break; case MLOG_2BYTES: mach_write_to_2(ptr, val); break; case MLOG_1BYTE: mach_write_to_1(ptr, val); break; default: ut_error; } } /********************************************************//** Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */ UNIV_INLINE void mlog_catenate_ulint( /*================*/ mtr_t* mtr, /*!< in/out: mtr */ ulint val, /*!< in: value to write */ mlog_id_t type) /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */ { if (mtr_get_log_mode(mtr) == MTR_LOG_NONE || mtr_get_log_mode(mtr) == MTR_LOG_NO_REDO) { return; } mlog_catenate_ulint(mtr->get_log(), val, type); } /********************************************************//** Catenates a compressed ulint to mlog. */ UNIV_INLINE void mlog_catenate_ulint_compressed( /*===========================*/ mtr_t* mtr, /*!< in: mtr */ ulint val) /*!< in: value to write */ { byte* log_ptr; log_ptr = mlog_open(mtr, 10); /* If no logging is requested, we may return now */ if (log_ptr == NULL) { return; } log_ptr += mach_write_compressed(log_ptr, val); mlog_close(mtr, log_ptr); } /********************************************************//** Catenates a compressed 64-bit integer to mlog. */ UNIV_INLINE void mlog_catenate_ull_compressed( /*=========================*/ mtr_t* mtr, /*!< in: mtr */ ib_uint64_t val) /*!< in: value to write */ { byte* log_ptr; log_ptr = mlog_open(mtr, 15); /* If no logging is requested, we may return now */ if (log_ptr == NULL) { return; } log_ptr += mach_u64_write_compressed(log_ptr, val); mlog_close(mtr, log_ptr); } /** Writes a log record about an operation. @param[in] type redo log record type @param[in] space_id tablespace identifier @param[in] page_no page number @param[in,out] log_ptr current end of mini-transaction log @param[in,out] mtr mini-transaction @return end of mini-transaction log */ UNIV_INLINE byte* mlog_write_initial_log_record_low( mlog_id_t type, ulint space_id, ulint page_no, byte* log_ptr, mtr_t* mtr) { ut_ad(type <= MLOG_BIGGEST_TYPE || EXTRA_CHECK_MLOG_NUMBER(type)); ut_ad(type == MLOG_FILE_NAME || type == MLOG_FILE_DELETE || type == MLOG_FILE_CREATE2 || type == MLOG_FILE_RENAME2 || type == MLOG_INDEX_LOAD || type == MLOG_TRUNCATE || type == MLOG_FILE_WRITE_CRYPT_DATA || mtr->is_named_space(space_id)); mach_write_to_1(log_ptr, type); log_ptr++; log_ptr += mach_write_compressed(log_ptr, space_id); log_ptr += mach_write_compressed(log_ptr, page_no); mtr->added_rec(); return(log_ptr); } /********************************************************//** Writes the initial part of a log record (3..11 bytes). If the implementation of this function is changed, all size parameters to mlog_open() should be adjusted accordingly! @return new value of log_ptr */ UNIV_INLINE byte* mlog_write_initial_log_record_fast( /*===============================*/ const byte* ptr, /*!< in: pointer to (inside) a buffer frame holding the file page where modification is made */ mlog_id_t type, /*!< in: log item type: MLOG_1BYTE, ... */ byte* log_ptr,/*!< in: pointer to mtr log which has been opened */ mtr_t* mtr) /*!< in/out: mtr */ { const byte* page; ulint space; ulint offset; ut_ad(log_ptr); ut_d(mtr->memo_modify_page(ptr)); page = (const byte*) ut_align_down(ptr, UNIV_PAGE_SIZE); space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); offset = mach_read_from_4(page + FIL_PAGE_OFFSET); /* check whether the page is in the doublewrite buffer; the doublewrite buffer is located in pages FSP_EXTENT_SIZE, ..., 3 * FSP_EXTENT_SIZE - 1 in the system tablespace */ if (space == TRX_SYS_SPACE && offset >= FSP_EXTENT_SIZE && offset < 3 * FSP_EXTENT_SIZE) { ut_ad(buf_dblwr_being_created); /* Do nothing: we only come to this branch in an InnoDB database creation. We do not redo log anything for the doublewrite buffer pages. */ return(log_ptr); } return(mlog_write_initial_log_record_low(type, space, offset, log_ptr, mtr)); }