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