1/***************************************************************************** 2 3Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. 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 "mach0data.h" 35#include "ut0lst.h" 36#include "buf0buf.h" 37#include "buf0dblwr.h" 38#include "fsp0types.h" 39#include "trx0sys.h" 40 41/********************************************************//** 42Opens a buffer to mlog. It must be closed with mlog_close. 43@return buffer, NULL if log mode MTR_LOG_NONE */ 44UNIV_INLINE 45byte* 46mlog_open( 47/*======*/ 48 mtr_t* mtr, /*!< in: mtr */ 49 ulint size) /*!< in: buffer size in bytes; MUST be 50 smaller than DYN_ARRAY_DATA_SIZE! */ 51{ 52 dyn_array_t* mlog; 53 54 mtr->modifications = TRUE; 55 56 if (mtr_get_log_mode(mtr) == MTR_LOG_NONE) { 57 58 return(NULL); 59 } 60 61 mlog = &(mtr->log); 62 63 return(dyn_array_open(mlog, size)); 64} 65 66/********************************************************//** 67Closes a buffer opened to mlog. */ 68UNIV_INLINE 69void 70mlog_close( 71/*=======*/ 72 mtr_t* mtr, /*!< in: mtr */ 73 byte* ptr) /*!< in: buffer space from ptr up was not used */ 74{ 75 dyn_array_t* mlog; 76 77 ut_ad(mtr_get_log_mode(mtr) != MTR_LOG_NONE); 78 79 mlog = &(mtr->log); 80 81 dyn_array_close(mlog, ptr); 82} 83 84#ifndef UNIV_HOTBACKUP 85/********************************************************//** 86Catenates 1 - 4 bytes to the mtr log. The value is not compressed. */ 87UNIV_INLINE 88void 89mlog_catenate_ulint( 90/*================*/ 91 mtr_t* mtr, /*!< in: mtr */ 92 ulint val, /*!< in: value to write */ 93 ulint type) /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */ 94{ 95 dyn_array_t* mlog; 96 byte* ptr; 97 98 if (mtr_get_log_mode(mtr) == MTR_LOG_NONE) { 99 100 return; 101 } 102 103 mlog = &(mtr->log); 104 105#if MLOG_1BYTE != 1 106# error "MLOG_1BYTE != 1" 107#endif 108#if MLOG_2BYTES != 2 109# error "MLOG_2BYTES != 2" 110#endif 111#if MLOG_4BYTES != 4 112# error "MLOG_4BYTES != 4" 113#endif 114#if MLOG_8BYTES != 8 115# error "MLOG_8BYTES != 8" 116#endif 117 ptr = (byte*) dyn_array_push(mlog, type); 118 119 if (type == MLOG_4BYTES) { 120 mach_write_to_4(ptr, val); 121 } else if (type == MLOG_2BYTES) { 122 mach_write_to_2(ptr, val); 123 } else { 124 ut_ad(type == MLOG_1BYTE); 125 mach_write_to_1(ptr, val); 126 } 127} 128 129/********************************************************//** 130Catenates a compressed ulint to mlog. */ 131UNIV_INLINE 132void 133mlog_catenate_ulint_compressed( 134/*===========================*/ 135 mtr_t* mtr, /*!< in: mtr */ 136 ulint val) /*!< in: value to write */ 137{ 138 byte* log_ptr; 139 140 log_ptr = mlog_open(mtr, 10); 141 142 /* If no logging is requested, we may return now */ 143 if (log_ptr == NULL) { 144 145 return; 146 } 147 148 log_ptr += mach_write_compressed(log_ptr, val); 149 150 mlog_close(mtr, log_ptr); 151} 152 153/********************************************************//** 154Catenates a compressed 64-bit integer to mlog. */ 155UNIV_INLINE 156void 157mlog_catenate_ull_compressed( 158/*=========================*/ 159 mtr_t* mtr, /*!< in: mtr */ 160 ib_uint64_t val) /*!< in: value to write */ 161{ 162 byte* log_ptr; 163 164 log_ptr = mlog_open(mtr, 15); 165 166 /* If no logging is requested, we may return now */ 167 if (log_ptr == NULL) { 168 169 return; 170 } 171 172 log_ptr += mach_ull_write_compressed(log_ptr, val); 173 174 mlog_close(mtr, log_ptr); 175} 176 177/********************************************************//** 178Writes the initial part of a log record (3..11 bytes). 179If the implementation of this function is changed, all 180size parameters to mlog_open() should be adjusted accordingly! 181@return new value of log_ptr */ 182UNIV_INLINE 183byte* 184mlog_write_initial_log_record_fast( 185/*===============================*/ 186 const byte* ptr, /*!< in: pointer to (inside) a buffer 187 frame holding the file page where 188 modification is made */ 189 byte type, /*!< in: log item type: MLOG_1BYTE, ... */ 190 byte* log_ptr,/*!< in: pointer to mtr log which has 191 been opened */ 192 mtr_t* mtr) /*!< in: mtr */ 193{ 194#ifdef UNIV_DEBUG 195 buf_block_t* block; 196#endif 197 const byte* page; 198 ulint space; 199 ulint offset; 200 201 ut_ad(mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_X_FIX)); 202 ut_ad(type <= MLOG_BIGGEST_TYPE); 203 ut_ad(ptr && log_ptr); 204 205 page = (const byte*) ut_align_down(ptr, UNIV_PAGE_SIZE); 206 space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); 207 offset = mach_read_from_4(page + FIL_PAGE_OFFSET); 208 209 /* check whether the page is in the doublewrite buffer; 210 the doublewrite buffer is located in pages 211 FSP_EXTENT_SIZE, ..., 3 * FSP_EXTENT_SIZE - 1 in the 212 system tablespace */ 213 if (space == TRX_SYS_SPACE 214 && offset >= FSP_EXTENT_SIZE && offset < 3 * FSP_EXTENT_SIZE) { 215 if (buf_dblwr_being_created) { 216 /* Do nothing: we only come to this branch in an 217 InnoDB database creation. We do not redo log 218 anything for the doublewrite buffer pages. */ 219 return(log_ptr); 220 } else { 221 fprintf(stderr, 222 "Error: trying to redo log a record of type " 223 "%d on page %lu of space %lu in the " 224 "doublewrite buffer, continuing anyway.\n" 225 "Please post a bug report to " 226 "bugs.mysql.com.\n", 227 type, offset, space); 228 ut_ad(0); 229 } 230 } 231 232 mach_write_to_1(log_ptr, type); 233 log_ptr++; 234 log_ptr += mach_write_compressed(log_ptr, space); 235 log_ptr += mach_write_compressed(log_ptr, offset); 236 237 mtr->n_log_recs++; 238 239#ifdef UNIV_LOG_DEBUG 240 fprintf(stderr, 241 "Adding to mtr log record type %lu space %lu page no %lu\n", 242 (ulong) type, space, offset); 243#endif 244 245#ifdef UNIV_DEBUG 246 /* We now assume that all x-latched pages have been modified! */ 247 block = (buf_block_t*) buf_block_align(ptr); 248 249 if (!mtr_memo_contains(mtr, block, MTR_MEMO_MODIFY)) { 250 251 mtr_memo_push(mtr, block, MTR_MEMO_MODIFY); 252 } 253#endif 254 return(log_ptr); 255} 256 257/********************************************************//** 258Writes a log record about an .ibd file create/delete/rename. 259@return new value of log_ptr */ 260UNIV_INLINE 261byte* 262mlog_write_initial_log_record_for_file_op( 263/*======================================*/ 264 ulint type, /*!< in: MLOG_FILE_CREATE, MLOG_FILE_DELETE, or 265 MLOG_FILE_RENAME */ 266 ulint space_id,/*!< in: space id, if applicable */ 267 ulint page_no,/*!< in: page number (not relevant currently) */ 268 byte* log_ptr,/*!< in: pointer to mtr log which has been opened */ 269 mtr_t* mtr) /*!< in: mtr */ 270{ 271 ut_ad(log_ptr); 272 273 mach_write_to_1(log_ptr, type); 274 log_ptr++; 275 276 /* We write dummy space id and page number */ 277 log_ptr += mach_write_compressed(log_ptr, space_id); 278 log_ptr += mach_write_compressed(log_ptr, page_no); 279 280 mtr->n_log_recs++; 281 282 return(log_ptr); 283} 284#endif /* !UNIV_HOTBACKUP */ 285