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