~drizzle-trunk/drizzle/development

641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1
/*****************************************************************************
2
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
3
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
4
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
8
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13
You should have received a copy of the GNU General Public License along with
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
16
17
*****************************************************************************/
18
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
19
/**************************************************//**
20
@file trx/trx0sys.c
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
21
Transaction system
22
23
Created 3/26/1996 Heikki Tuuri
24
*******************************************************/
25
26
#include "trx0sys.h"
27
28
#ifdef UNIV_NONINL
29
#include "trx0sys.ic"
30
#endif
31
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
32
#ifndef UNIV_HOTBACKUP
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
33
#include "fsp0fsp.h"
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
34
#include "mtr0log.h"
35
#include "mtr0log.h"
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
36
#include "trx0trx.h"
37
#include "trx0rseg.h"
38
#include "trx0undo.h"
39
#include "srv0srv.h"
40
#include "trx0purge.h"
41
#include "log0log.h"
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
42
#include "log0recv.h"
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
43
#include "os0file.h"
1819.5.106 by stewart at flamingspork
[patch 106/129] Merge patch for revision 1915 from InnoDB SVN:
44
#include "read0read.h"
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
45
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
46
/** The file format tag structure with id and name. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
47
struct file_format_struct {
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
48
	ulint		id;		/*!< id of the file format */
49
	const char*	name;		/*!< text representation of the
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
50
					file format */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
51
	mutex_t		mutex;		/*!< covers changes to the above
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
52
					fields */
53
};
54
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
55
/** The file format tag */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
56
typedef struct file_format_struct	file_format_t;
57
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
58
/** The transaction system */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
59
UNIV_INTERN trx_sys_t*		trx_sys		= NULL;
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
60
/** The doublewrite buffer */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
61
UNIV_INTERN trx_doublewrite_t*	trx_doublewrite = NULL;
62
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
63
/** The following is set to TRUE when we are upgrading from pre-4.1
64
format data files to the multiple tablespaces format data files */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
65
UNIV_INTERN ibool	trx_doublewrite_must_reset_space_ids	= FALSE;
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
66
/** Set to TRUE when the doublewrite buffer is being created */
67
UNIV_INTERN ibool	trx_doublewrite_buf_is_being_created = FALSE;
68
69
/** The following is TRUE when we are using the database in the
70
post-4.1 format, i.e., we have successfully upgraded, or have created
71
a new database installation */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
72
UNIV_INTERN ibool	trx_sys_multiple_tablespace_format	= FALSE;
73
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
74
/** In a MySQL replication slave, in crash recovery we store the master log
75
file name and position here. */
76
/* @{ */
77
/** Master binlog file name */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
78
UNIV_INTERN char	trx_sys_mysql_master_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN];
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
79
/** Master binlog file position.  We have successfully got the updates
80
up to this position.  -1 means that no crash recovery was needed, or
81
there was no master log position info inside InnoDB.*/
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
82
UNIV_INTERN ib_int64_t	trx_sys_mysql_master_log_pos	= -1;
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
83
/* @} */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
84
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
85
/** If this MySQL server uses binary logging, after InnoDB has been inited
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
86
and if it has done a crash recovery, we store the binlog file name and position
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
87
here. */
88
/* @{ */
89
/** Binlog file name */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
90
UNIV_INTERN char	trx_sys_mysql_bin_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN];
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
91
/** Binlog file position, or -1 if unknown */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
92
UNIV_INTERN ib_int64_t	trx_sys_mysql_bin_log_pos	= -1;
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
93
/* @} */
94
#endif /* !UNIV_HOTBACKUP */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
95
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
96
/** List of animal names representing file format. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
97
static const char*	file_format_name_map[] = {
98
	"Antelope",
99
	"Barracuda",
100
	"Cheetah",
101
	"Dragon",
102
	"Elk",
103
	"Fox",
104
	"Gazelle",
105
	"Hornet",
106
	"Impala",
107
	"Jaguar",
108
	"Kangaroo",
109
	"Leopard",
110
	"Moose",
111
	"Nautilus",
112
	"Ocelot",
113
	"Porpoise",
114
	"Quail",
115
	"Rabbit",
116
	"Shark",
117
	"Tiger",
118
	"Urchin",
119
	"Viper",
120
	"Whale",
121
	"Xenops",
122
	"Yak",
123
	"Zebra"
124
};
125
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
126
/** The number of elements in the file format name array. */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
127
static const ulint	FILE_FORMAT_NAME_N
128
	= sizeof(file_format_name_map) / sizeof(file_format_name_map[0]);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
129
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
130
#ifdef UNIV_PFS_MUTEX
131
/* Key to register the mutex with performance schema */
132
UNIV_INTERN mysql_pfs_key_t	trx_doublewrite_mutex_key;
133
UNIV_INTERN mysql_pfs_key_t	file_format_max_mutex_key;
134
#endif /* UNIV_PFS_MUTEX */
135
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
136
#ifndef UNIV_HOTBACKUP
137
/** This is used to track the maximum file format id known to InnoDB. It's
1819.7.175 by Jimmy Yang, Stewart Smith
Merge Revision revid:jimmy.yang@oracle.com-20100617091353-5zga8o5hxpi0l15q from MySQL InnoDB
138
updated via SET GLOBAL innodb_file_format_max = 'x' or when we open
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
139
or create a table. */
140
static	file_format_t	file_format_max;
141
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
142
/****************************************************************//**
143
Determines if a page number is located inside the doublewrite buffer.
144
@return TRUE if the location is inside the two blocks of the
145
doublewrite buffer */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
146
UNIV_INTERN
147
ibool
148
trx_doublewrite_page_inside(
149
/*========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
150
	ulint	page_no)	/*!< in: page number */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
151
{
152
	if (trx_doublewrite == NULL) {
153
154
		return(FALSE);
155
	}
156
157
	if (page_no >= trx_doublewrite->block1
158
	    && page_no < trx_doublewrite->block1
159
	    + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
160
		return(TRUE);
161
	}
162
163
	if (page_no >= trx_doublewrite->block2
164
	    && page_no < trx_doublewrite->block2
165
	    + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
166
		return(TRUE);
167
	}
168
169
	return(FALSE);
170
}
171
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
172
/****************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
173
Creates or initialializes the doublewrite buffer at a database start. */
174
static
175
void
176
trx_doublewrite_init(
177
/*=================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
178
	byte*	doublewrite)	/*!< in: pointer to the doublewrite buf
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
179
				header on trx sys page */
180
{
2023.3.17 by Monty Taylor
More casting. Getting old.
181
  trx_doublewrite = static_cast<trx_doublewrite_t *>(mem_alloc(sizeof(trx_doublewrite_t)));
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
182
183
	/* Since we now start to use the doublewrite buffer, no need to call
184
	fsync() after every write to a data file */
185
#ifdef UNIV_DO_FLUSH
186
	os_do_not_call_flush_at_each_write = TRUE;
187
#endif /* UNIV_DO_FLUSH */
188
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
189
	mutex_create(trx_doublewrite_mutex_key,
190
		     &trx_doublewrite->mutex, SYNC_DOUBLEWRITE);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
191
192
	trx_doublewrite->first_free = 0;
193
194
	trx_doublewrite->block1 = mach_read_from_4(
195
		doublewrite + TRX_SYS_DOUBLEWRITE_BLOCK1);
196
	trx_doublewrite->block2 = mach_read_from_4(
197
		doublewrite + TRX_SYS_DOUBLEWRITE_BLOCK2);
2023.3.17 by Monty Taylor
More casting. Getting old.
198
        trx_doublewrite->write_buf_unaligned = static_cast<byte *>(ut_malloc(
199
                                                                             (1 + 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) * UNIV_PAGE_SIZE));
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
200
2023.3.17 by Monty Taylor
More casting. Getting old.
201
        trx_doublewrite->write_buf = static_cast<byte *>(ut_align(
202
                                                                  trx_doublewrite->write_buf_unaligned, UNIV_PAGE_SIZE));
203
        trx_doublewrite->buf_block_arr = static_cast<buf_page_t **>(mem_alloc(
204
                                                                             2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * sizeof(void*)));
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
205
}
206
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
207
/****************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
208
Marks the trx sys header when we have successfully upgraded to the >= 4.1.x
209
multiple tablespace format. */
210
UNIV_INTERN
211
void
212
trx_sys_mark_upgraded_to_multiple_tablespaces(void)
213
/*===============================================*/
214
{
215
	buf_block_t*	block;
216
	byte*		doublewrite;
217
	mtr_t		mtr;
218
219
	/* We upgraded to 4.1.x and reset the space id fields in the
220
	doublewrite buffer. Let us mark to the trx_sys header that the upgrade
221
	has been done. */
222
223
	mtr_start(&mtr);
224
225
	block = buf_page_get(TRX_SYS_SPACE, 0, TRX_SYS_PAGE_NO,
226
			     RW_X_LATCH, &mtr);
227
	buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
228
229
	doublewrite = buf_block_get_frame(block) + TRX_SYS_DOUBLEWRITE;
230
231
	mlog_write_ulint(doublewrite + TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED,
232
			 TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N,
233
			 MLOG_4BYTES, &mtr);
234
	mtr_commit(&mtr);
235
236
	/* Flush the modified pages to disk and make a checkpoint */
237
	log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE);
238
239
	trx_sys_multiple_tablespace_format = TRUE;
240
}
241
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
242
/****************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
243
Creates the doublewrite buffer to a new InnoDB installation. The header of the
244
doublewrite buffer is placed on the trx system header page. */
245
UNIV_INTERN
246
void
247
trx_sys_create_doublewrite_buf(void)
248
/*================================*/
249
{
250
	buf_block_t*	block;
251
	buf_block_t*	block2;
1819.9.126 by Vasil Dimov
Merge Revision revid:vasil.dimov@oracle.com-20100915165836-zydiy6urspd3xsva from MySQL InnoDB
252
#ifdef UNIV_SYNC_DEBUG
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
253
	buf_block_t*	new_block;
1819.9.126 by Vasil Dimov
Merge Revision revid:vasil.dimov@oracle.com-20100915165836-zydiy6urspd3xsva from MySQL InnoDB
254
#endif /* UNIV_SYNC_DEBUG */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
255
	byte*	doublewrite;
256
	byte*	fseg_header;
257
	ulint	page_no;
258
	ulint	prev_page_no;
259
	ulint	i;
260
	mtr_t	mtr;
261
262
	if (trx_doublewrite) {
263
		/* Already inited */
264
265
		return;
266
	}
267
268
start_again:
269
	mtr_start(&mtr);
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
270
	trx_doublewrite_buf_is_being_created = TRUE;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
271
272
	block = buf_page_get(TRX_SYS_SPACE, 0, TRX_SYS_PAGE_NO,
273
			     RW_X_LATCH, &mtr);
274
	buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
275
276
	doublewrite = buf_block_get_frame(block) + TRX_SYS_DOUBLEWRITE;
277
278
	if (mach_read_from_4(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC)
279
	    == TRX_SYS_DOUBLEWRITE_MAGIC_N) {
280
		/* The doublewrite buffer has already been created:
281
		just read in some numbers */
282
283
		trx_doublewrite_init(doublewrite);
284
285
		mtr_commit(&mtr);
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
286
		trx_doublewrite_buf_is_being_created = FALSE;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
287
	} else {
288
		fprintf(stderr,
289
			"InnoDB: Doublewrite buffer not found:"
290
			" creating new\n");
291
292
		if (buf_pool_get_curr_size()
293
		    < ((2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
294
			+ FSP_EXTENT_SIZE / 2 + 100)
295
		       * UNIV_PAGE_SIZE)) {
296
			fprintf(stderr,
297
				"InnoDB: Cannot create doublewrite buffer:"
298
				" you must\n"
299
				"InnoDB: increase your buffer pool size.\n"
300
				"InnoDB: Cannot continue operation.\n");
301
302
			exit(1);
303
		}
304
305
		block2 = fseg_create(TRX_SYS_SPACE, TRX_SYS_PAGE_NO,
306
				     TRX_SYS_DOUBLEWRITE
307
				     + TRX_SYS_DOUBLEWRITE_FSEG, &mtr);
308
309
		/* fseg_create acquires a second latch on the page,
310
		therefore we must declare it: */
311
312
		buf_block_dbg_add_level(block2, SYNC_NO_ORDER_CHECK);
313
314
		if (block2 == NULL) {
315
			fprintf(stderr,
316
				"InnoDB: Cannot create doublewrite buffer:"
317
				" you must\n"
318
				"InnoDB: increase your tablespace size.\n"
319
				"InnoDB: Cannot continue operation.\n");
320
321
			/* We exit without committing the mtr to prevent
322
			its modifications to the database getting to disk */
323
324
			exit(1);
325
		}
326
327
		fseg_header = buf_block_get_frame(block)
328
			+ TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_FSEG;
329
		prev_page_no = 0;
330
331
		for (i = 0; i < 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
332
			     + FSP_EXTENT_SIZE / 2; i++) {
333
			page_no = fseg_alloc_free_page(fseg_header,
334
						       prev_page_no + 1,
335
						       FSP_UP, &mtr);
336
			if (page_no == FIL_NULL) {
337
				fprintf(stderr,
338
					"InnoDB: Cannot create doublewrite"
339
					" buffer: you must\n"
340
					"InnoDB: increase your"
341
					" tablespace size.\n"
342
					"InnoDB: Cannot continue operation.\n"
343
					);
344
345
				exit(1);
346
			}
347
348
			/* We read the allocated pages to the buffer pool;
349
			when they are written to disk in a flush, the space
350
			id and page number fields are also written to the
351
			pages. When we at database startup read pages
352
			from the doublewrite buffer, we know that if the
353
			space id and page number in them are the same as
354
			the page position in the tablespace, then the page
355
			has not been written to in doublewrite. */
356
1819.9.126 by Vasil Dimov
Merge Revision revid:vasil.dimov@oracle.com-20100915165836-zydiy6urspd3xsva from MySQL InnoDB
357
#ifdef UNIV_SYNC_DEBUG
1819.9.125 by Vasil Dimov
Merge Revision revid:vasil.dimov@oracle.com-20100915164735-jh9wtp8pgss2fuft from MySQL InnoDB
358
			new_block =
1819.9.126 by Vasil Dimov
Merge Revision revid:vasil.dimov@oracle.com-20100915165836-zydiy6urspd3xsva from MySQL InnoDB
359
#endif /* UNIV_SYNC_DEBUG */
1819.9.125 by Vasil Dimov
Merge Revision revid:vasil.dimov@oracle.com-20100915164735-jh9wtp8pgss2fuft from MySQL InnoDB
360
			buf_page_get(TRX_SYS_SPACE, 0, page_no,
361
				     RW_X_LATCH, &mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
362
			buf_block_dbg_add_level(new_block,
363
						SYNC_NO_ORDER_CHECK);
364
365
			if (i == FSP_EXTENT_SIZE / 2) {
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
366
				ut_a(page_no == FSP_EXTENT_SIZE);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
367
				mlog_write_ulint(doublewrite
368
						 + TRX_SYS_DOUBLEWRITE_BLOCK1,
369
						 page_no, MLOG_4BYTES, &mtr);
370
				mlog_write_ulint(doublewrite
371
						 + TRX_SYS_DOUBLEWRITE_REPEAT
372
						 + TRX_SYS_DOUBLEWRITE_BLOCK1,
373
						 page_no, MLOG_4BYTES, &mtr);
374
			} else if (i == FSP_EXTENT_SIZE / 2
375
				   + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
376
				ut_a(page_no == 2 * FSP_EXTENT_SIZE);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
377
				mlog_write_ulint(doublewrite
378
						 + TRX_SYS_DOUBLEWRITE_BLOCK2,
379
						 page_no, MLOG_4BYTES, &mtr);
380
				mlog_write_ulint(doublewrite
381
						 + TRX_SYS_DOUBLEWRITE_REPEAT
382
						 + TRX_SYS_DOUBLEWRITE_BLOCK2,
383
						 page_no, MLOG_4BYTES, &mtr);
384
			} else if (i > FSP_EXTENT_SIZE / 2) {
385
				ut_a(page_no == prev_page_no + 1);
386
			}
387
388
			prev_page_no = page_no;
389
		}
390
391
		mlog_write_ulint(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC,
392
				 TRX_SYS_DOUBLEWRITE_MAGIC_N,
393
				 MLOG_4BYTES, &mtr);
394
		mlog_write_ulint(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC
395
				 + TRX_SYS_DOUBLEWRITE_REPEAT,
396
				 TRX_SYS_DOUBLEWRITE_MAGIC_N,
397
				 MLOG_4BYTES, &mtr);
398
399
		mlog_write_ulint(doublewrite
400
				 + TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED,
401
				 TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N,
402
				 MLOG_4BYTES, &mtr);
403
		mtr_commit(&mtr);
404
405
		/* Flush the modified pages to disk and make a checkpoint */
406
		log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE);
407
408
		fprintf(stderr, "InnoDB: Doublewrite buffer created\n");
409
410
		trx_sys_multiple_tablespace_format = TRUE;
411
412
		goto start_again;
413
	}
414
}
415
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
416
/****************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
417
At a database startup initializes the doublewrite buffer memory structure if
418
we already have a doublewrite buffer created in the data files. If we are
419
upgrading to an InnoDB version which supports multiple tablespaces, then this
420
function performs the necessary update operations. If we are in a crash
421
recovery, this function uses a possible doublewrite buffer to restore
422
half-written pages in the data files. */
423
UNIV_INTERN
424
void
425
trx_sys_doublewrite_init_or_restore_pages(
426
/*======================================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
427
	ibool	restore_corrupt_pages)	/*!< in: TRUE=restore pages */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
428
{
429
	byte*	buf;
430
	byte*	read_buf;
431
	byte*	unaligned_read_buf;
432
	ulint	block1;
433
	ulint	block2;
434
	ulint	source_page_no;
435
	byte*	page;
436
	byte*	doublewrite;
437
	ulint	space_id;
438
	ulint	page_no;
439
	ulint	i;
440
441
	/* We do the file i/o past the buffer pool */
442
2023.3.17 by Monty Taylor
More casting. Getting old.
443
        unaligned_read_buf = static_cast<byte *>(ut_malloc(2 * UNIV_PAGE_SIZE));
444
        read_buf = static_cast<byte *>(ut_align(unaligned_read_buf, UNIV_PAGE_SIZE));
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
445
446
	/* Read the trx sys header to check if we are using the doublewrite
447
	buffer */
448
449
	fil_io(OS_FILE_READ, TRUE, TRX_SYS_SPACE, 0, TRX_SYS_PAGE_NO, 0,
450
	       UNIV_PAGE_SIZE, read_buf, NULL);
451
	doublewrite = read_buf + TRX_SYS_DOUBLEWRITE;
452
453
	if (mach_read_from_4(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC)
454
	    == TRX_SYS_DOUBLEWRITE_MAGIC_N) {
455
		/* The doublewrite buffer has been created */
456
457
		trx_doublewrite_init(doublewrite);
458
459
		block1 = trx_doublewrite->block1;
460
		block2 = trx_doublewrite->block2;
461
462
		buf = trx_doublewrite->write_buf;
463
	} else {
464
		goto leave_func;
465
	}
466
467
	if (mach_read_from_4(doublewrite + TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED)
468
	    != TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N) {
469
470
		/* We are upgrading from a version < 4.1.x to a version where
471
		multiple tablespaces are supported. We must reset the space id
472
		field in the pages in the doublewrite buffer because starting
473
		from this version the space id is stored to
474
		FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID. */
475
476
		trx_doublewrite_must_reset_space_ids = TRUE;
477
478
		fprintf(stderr,
479
			"InnoDB: Resetting space id's in the"
480
			" doublewrite buffer\n");
481
	} else {
482
		trx_sys_multiple_tablespace_format = TRUE;
483
	}
484
485
	/* Read the pages from the doublewrite buffer to memory */
486
487
	fil_io(OS_FILE_READ, TRUE, TRX_SYS_SPACE, 0, block1, 0,
488
	       TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE,
489
	       buf, NULL);
490
	fil_io(OS_FILE_READ, TRUE, TRX_SYS_SPACE, 0, block2, 0,
491
	       TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE,
492
	       buf + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE,
493
	       NULL);
494
	/* Check if any of these pages is half-written in data files, in the
495
	intended position */
496
497
	page = buf;
498
499
	for (i = 0; i < TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 2; i++) {
500
501
		page_no = mach_read_from_4(page + FIL_PAGE_OFFSET);
502
503
		if (trx_doublewrite_must_reset_space_ids) {
504
505
			space_id = 0;
506
			mach_write_to_4(page
507
					+ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0);
508
			/* We do not need to calculate new checksums for the
509
			pages because the field .._SPACE_ID does not affect
510
			them. Write the page back to where we read it from. */
511
512
			if (i < TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
513
				source_page_no = block1 + i;
514
			} else {
515
				source_page_no = block2
516
					+ i - TRX_SYS_DOUBLEWRITE_BLOCK_SIZE;
517
			}
518
519
			fil_io(OS_FILE_WRITE, TRUE, 0, 0, source_page_no, 0,
520
			       UNIV_PAGE_SIZE, page, NULL);
521
			/* printf("Resetting space id in page %lu\n",
522
			source_page_no); */
523
		} else {
524
			space_id = mach_read_from_4(
525
				page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
526
		}
527
528
		if (!restore_corrupt_pages) {
529
			/* The database was shut down gracefully: no need to
530
			restore pages */
531
532
		} else if (!fil_tablespace_exists_in_mem(space_id)) {
533
			/* Maybe we have dropped the single-table tablespace
534
			and this page once belonged to it: do nothing */
535
536
		} else if (!fil_check_adress_in_tablespace(space_id,
537
							   page_no)) {
538
			fprintf(stderr,
539
				"InnoDB: Warning: a page in the"
540
				" doublewrite buffer is not within space\n"
541
				"InnoDB: bounds; space id %lu"
542
				" page number %lu, page %lu in"
543
				" doublewrite buf.\n",
544
				(ulong) space_id, (ulong) page_no, (ulong) i);
545
546
		} else if (space_id == TRX_SYS_SPACE
547
			   && ((page_no >= block1
548
				&& page_no
549
				< block1 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE)
550
			       || (page_no >= block2
551
				   && page_no
552
				   < (block2
553
				      + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE)))) {
554
555
			/* It is an unwritten doublewrite buffer page:
556
			do nothing */
557
		} else {
558
			ulint	zip_size = fil_space_get_zip_size(space_id);
559
560
			/* Read in the actual page from the file */
561
			fil_io(OS_FILE_READ, TRUE, space_id, zip_size,
562
			       page_no, 0,
563
			       zip_size ? zip_size : UNIV_PAGE_SIZE,
564
			       read_buf, NULL);
565
566
			/* Check if the page is corrupt */
567
568
			if (UNIV_UNLIKELY
569
			    (buf_page_is_corrupted(read_buf, zip_size))) {
570
571
				fprintf(stderr,
572
					"InnoDB: Warning: database page"
573
					" corruption or a failed\n"
574
					"InnoDB: file read of"
575
					" space %lu page %lu.\n"
576
					"InnoDB: Trying to recover it from"
577
					" the doublewrite buffer.\n",
578
					(ulong) space_id, (ulong) page_no);
579
580
				if (buf_page_is_corrupted(page, zip_size)) {
581
					fprintf(stderr,
582
						"InnoDB: Dump of the page:\n");
583
					buf_page_print(read_buf, zip_size);
584
					fprintf(stderr,
585
						"InnoDB: Dump of"
586
						" corresponding page"
587
						" in doublewrite buffer:\n");
588
					buf_page_print(page, zip_size);
589
590
					fprintf(stderr,
591
						"InnoDB: Also the page in the"
592
						" doublewrite buffer"
593
						" is corrupt.\n"
594
						"InnoDB: Cannot continue"
595
						" operation.\n"
596
						"InnoDB: You can try to"
597
						" recover the database"
598
						" with the my.cnf\n"
599
						"InnoDB: option:\n"
1819.5.239 by marko
Merge Revision revid:svn-v4:16c675df-0fcb-4bc9-8058-dcc011a37293:branches/zip:6793 from MySQL InnoDB
600
						"InnoDB:"
601
						" innodb_force_recovery=6\n");
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
602
					exit(1);
603
				}
604
605
				/* Write the good page from the
606
				doublewrite buffer to the intended
607
				position */
608
609
				fil_io(OS_FILE_WRITE, TRUE, space_id,
610
				       zip_size, page_no, 0,
611
				       zip_size ? zip_size : UNIV_PAGE_SIZE,
612
				       page, NULL);
613
				fprintf(stderr,
614
					"InnoDB: Recovered the page from"
615
					" the doublewrite buffer.\n");
616
			}
617
		}
618
619
		page += UNIV_PAGE_SIZE;
620
	}
621
622
	fil_flush_file_spaces(FIL_TABLESPACE);
623
624
leave_func:
625
	ut_free(unaligned_read_buf);
626
}
627
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
628
/****************************************************************//**
629
Checks that trx is in the trx list.
630
@return	TRUE if is in */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
631
UNIV_INTERN
632
ibool
633
trx_in_trx_list(
634
/*============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
635
	trx_t*	in_trx)	/*!< in: trx */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
636
{
637
	trx_t*	trx;
638
639
	ut_ad(mutex_own(&(kernel_mutex)));
640
641
	trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
642
643
	while (trx != NULL) {
644
645
		if (trx == in_trx) {
646
647
			return(TRUE);
648
		}
649
650
		trx = UT_LIST_GET_NEXT(trx_list, trx);
651
	}
652
653
	return(FALSE);
654
}
655
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
656
/*****************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
657
Writes the value of max_trx_id to the file based trx system header. */
658
UNIV_INTERN
659
void
660
trx_sys_flush_max_trx_id(void)
661
/*==========================*/
662
{
663
	trx_sysf_t*	sys_header;
664
	mtr_t		mtr;
665
666
	ut_ad(mutex_own(&kernel_mutex));
667
668
	mtr_start(&mtr);
669
670
	sys_header = trx_sysf_get(&mtr);
671
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
672
	mlog_write_ull(sys_header + TRX_SYS_TRX_ID_STORE,
673
		       trx_sys->max_trx_id, &mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
674
	mtr_commit(&mtr);
675
}
676
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
677
/*****************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
678
Updates the offset information about the end of the MySQL binlog entry
679
which corresponds to the transaction just being committed. In a MySQL
680
replication slave updates the latest master binlog position up to which
681
replication has proceeded. */
682
UNIV_INTERN
683
void
684
trx_sys_update_mysql_binlog_offset(
685
/*===============================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
686
	const char*	file_name,/*!< in: MySQL log file name */
687
	ib_int64_t	offset,	/*!< in: position in that log file */
688
	ulint		field,	/*!< in: offset of the MySQL log info field in
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
689
				the trx sys header */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
690
	mtr_t*		mtr)	/*!< in: mtr */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
691
{
692
	trx_sysf_t*	sys_header;
693
694
	if (ut_strlen(file_name) >= TRX_SYS_MYSQL_LOG_NAME_LEN) {
695
696
		/* We cannot fit the name to the 512 bytes we have reserved */
697
698
		return;
699
	}
700
701
	sys_header = trx_sysf_get(mtr);
702
703
	if (mach_read_from_4(sys_header + field
704
			     + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
705
	    != TRX_SYS_MYSQL_LOG_MAGIC_N) {
706
707
		mlog_write_ulint(sys_header + field
708
				 + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD,
709
				 TRX_SYS_MYSQL_LOG_MAGIC_N,
710
				 MLOG_4BYTES, mtr);
711
	}
712
713
	if (0 != strcmp((char*) (sys_header + field + TRX_SYS_MYSQL_LOG_NAME),
714
			file_name)) {
715
716
		mlog_write_string(sys_header + field
717
				  + TRX_SYS_MYSQL_LOG_NAME,
718
				  (byte*) file_name, 1 + ut_strlen(file_name),
719
				  mtr);
720
	}
721
722
	if (mach_read_from_4(sys_header + field
723
			     + TRX_SYS_MYSQL_LOG_OFFSET_HIGH) > 0
724
	    || (offset >> 32) > 0) {
725
726
		mlog_write_ulint(sys_header + field
727
				 + TRX_SYS_MYSQL_LOG_OFFSET_HIGH,
728
				 (ulint)(offset >> 32),
729
				 MLOG_4BYTES, mtr);
730
	}
731
732
	mlog_write_ulint(sys_header + field
733
			 + TRX_SYS_MYSQL_LOG_OFFSET_LOW,
734
			 (ulint)(offset & 0xFFFFFFFFUL),
735
			 MLOG_4BYTES, mtr);
736
}
737
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
738
/*****************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
739
Stores the MySQL binlog offset info in the trx system header if
740
the magic number shows it valid, and print the info to stderr */
741
UNIV_INTERN
742
void
743
trx_sys_print_mysql_binlog_offset(void)
744
/*===================================*/
745
{
746
	trx_sysf_t*	sys_header;
747
	mtr_t		mtr;
748
	ulint		trx_sys_mysql_bin_log_pos_high;
749
	ulint		trx_sys_mysql_bin_log_pos_low;
750
751
	mtr_start(&mtr);
752
753
	sys_header = trx_sysf_get(&mtr);
754
755
	if (mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
756
			     + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
757
	    != TRX_SYS_MYSQL_LOG_MAGIC_N) {
758
759
		mtr_commit(&mtr);
760
761
		return;
762
	}
763
764
	trx_sys_mysql_bin_log_pos_high = mach_read_from_4(
765
		sys_header + TRX_SYS_MYSQL_LOG_INFO
766
		+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH);
767
	trx_sys_mysql_bin_log_pos_low = mach_read_from_4(
768
		sys_header + TRX_SYS_MYSQL_LOG_INFO
769
		+ TRX_SYS_MYSQL_LOG_OFFSET_LOW);
770
771
	trx_sys_mysql_bin_log_pos
772
		= (((ib_int64_t)trx_sys_mysql_bin_log_pos_high) << 32)
773
		+ (ib_int64_t)trx_sys_mysql_bin_log_pos_low;
774
775
	ut_memcpy(trx_sys_mysql_bin_log_name,
776
		  sys_header + TRX_SYS_MYSQL_LOG_INFO
777
		  + TRX_SYS_MYSQL_LOG_NAME, TRX_SYS_MYSQL_LOG_NAME_LEN);
778
779
	fprintf(stderr,
780
		"InnoDB: Last MySQL binlog file position %lu %lu,"
781
		" file name %s\n",
782
		trx_sys_mysql_bin_log_pos_high, trx_sys_mysql_bin_log_pos_low,
783
		trx_sys_mysql_bin_log_name);
784
785
	mtr_commit(&mtr);
786
}
787
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
788
/*****************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
789
Prints to stderr the MySQL master log offset info in the trx system header if
790
the magic number shows it valid. */
791
UNIV_INTERN
792
void
793
trx_sys_print_mysql_master_log_pos(void)
794
/*====================================*/
795
{
796
	trx_sysf_t*	sys_header;
797
	mtr_t		mtr;
798
799
	mtr_start(&mtr);
800
801
	sys_header = trx_sysf_get(&mtr);
802
803
	if (mach_read_from_4(sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
804
			     + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
805
	    != TRX_SYS_MYSQL_LOG_MAGIC_N) {
806
807
		mtr_commit(&mtr);
808
809
		return;
810
	}
811
812
	fprintf(stderr,
813
		"InnoDB: In a MySQL replication slave the last"
814
		" master binlog file\n"
815
		"InnoDB: position %lu %lu, file name %s\n",
816
		(ulong) mach_read_from_4(sys_header
817
					 + TRX_SYS_MYSQL_MASTER_LOG_INFO
818
					 + TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
819
		(ulong) mach_read_from_4(sys_header
820
					 + TRX_SYS_MYSQL_MASTER_LOG_INFO
821
					 + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
822
		sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
823
		+ TRX_SYS_MYSQL_LOG_NAME);
824
	/* Copy the master log position info to global variables we can
825
	use in ha_innobase.cc to initialize glob_mi to right values */
826
827
	ut_memcpy(trx_sys_mysql_master_log_name,
828
		  sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
829
		  + TRX_SYS_MYSQL_LOG_NAME,
830
		  TRX_SYS_MYSQL_LOG_NAME_LEN);
831
832
	trx_sys_mysql_master_log_pos
833
		= (((ib_int64_t) mach_read_from_4(
834
			    sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
835
			    + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
836
		+ ((ib_int64_t) mach_read_from_4(
837
			   sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
838
			   + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
839
	mtr_commit(&mtr);
840
}
841
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
842
/****************************************************************//**
843
Looks for a free slot for a rollback segment in the trx system file copy.
844
@return	slot index or ULINT_UNDEFINED if not found */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
845
UNIV_INTERN
846
ulint
847
trx_sysf_rseg_find_free(
848
/*====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
849
	mtr_t*	mtr)	/*!< in: mtr */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
850
{
851
	trx_sysf_t*	sys_header;
852
	ulint		page_no;
853
	ulint		i;
854
855
	ut_ad(mutex_own(&(kernel_mutex)));
856
857
	sys_header = trx_sysf_get(mtr);
858
859
	for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
860
861
		page_no = trx_sysf_rseg_get_page_no(sys_header, i, mtr);
862
863
		if (page_no == FIL_NULL) {
864
865
			return(i);
866
		}
867
	}
868
869
	return(ULINT_UNDEFINED);
870
}
871
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
872
/*****************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
873
Creates the file page for the transaction system. This function is called only
874
at the database creation, before trx_sys_init. */
875
static
876
void
877
trx_sysf_create(
878
/*============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
879
	mtr_t*	mtr)	/*!< in: mtr */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
880
{
881
	trx_sysf_t*	sys_header;
882
	ulint		slot_no;
883
	buf_block_t*	block;
884
	page_t*		page;
885
	ulint		page_no;
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
886
	byte*		ptr;
887
	ulint		len;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
888
889
	ut_ad(mtr);
890
891
	/* Note that below we first reserve the file space x-latch, and
892
	then enter the kernel: we must do it in this order to conform
893
	to the latching order rules. */
894
895
	mtr_x_lock(fil_space_get_latch(TRX_SYS_SPACE, NULL), mtr);
896
	mutex_enter(&kernel_mutex);
897
898
	/* Create the trx sys file block in a new allocated file segment */
899
	block = fseg_create(TRX_SYS_SPACE, 0, TRX_SYS + TRX_SYS_FSEG_HEADER,
900
			    mtr);
901
	buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER);
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
902
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
903
	ut_a(buf_block_get_page_no(block) == TRX_SYS_PAGE_NO);
904
905
	page = buf_block_get_frame(block);
906
907
	mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_TYPE_TRX_SYS,
908
			 MLOG_2BYTES, mtr);
909
910
	/* Reset the doublewrite buffer magic number to zero so that we
911
	know that the doublewrite buffer has not yet been created (this
912
	suppresses a Valgrind warning) */
913
914
	mlog_write_ulint(page + TRX_SYS_DOUBLEWRITE
915
			 + TRX_SYS_DOUBLEWRITE_MAGIC, 0, MLOG_4BYTES, mtr);
916
917
	sys_header = trx_sysf_get(mtr);
918
919
	/* Start counting transaction ids from number 1 up */
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
920
	mach_write_to_8(sys_header + TRX_SYS_TRX_ID_STORE, 1);
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
921
922
	/* Reset the rollback segment slots.  Old versions of InnoDB
923
	define TRX_SYS_N_RSEGS as 256 (TRX_SYS_OLD_N_RSEGS) and expect
924
	that the whole array is initialized. */
925
	ptr = TRX_SYS_RSEGS + sys_header;
926
	len = ut_max(TRX_SYS_OLD_N_RSEGS, TRX_SYS_N_RSEGS)
927
		* TRX_SYS_RSEG_SLOT_SIZE;
928
	memset(ptr, 0xff, len);
929
	ptr += len;
930
	ut_a(ptr <= page + (UNIV_PAGE_SIZE - FIL_PAGE_DATA_END));
931
932
	/* Initialize all of the page.  This part used to be uninitialized. */
933
	memset(ptr, 0, UNIV_PAGE_SIZE - FIL_PAGE_DATA_END + page - ptr);
934
935
	mlog_log_string(sys_header, UNIV_PAGE_SIZE - FIL_PAGE_DATA_END
936
			+ page - sys_header, mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
937
938
	/* Create the first rollback segment in the SYSTEM tablespace */
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
939
	slot_no = trx_sysf_rseg_find_free(mtr);
940
	page_no = trx_rseg_header_create(TRX_SYS_SPACE, 0, ULINT_MAX, slot_no,
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
941
					 mtr);
942
	ut_a(slot_no == TRX_SYS_SYSTEM_RSEG_ID);
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
943
	ut_a(page_no == FSP_FIRST_RSEG_PAGE_NO);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
944
945
	mutex_exit(&kernel_mutex);
946
}
947
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
948
/*****************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
949
Creates and initializes the central memory structures for the transaction
950
system. This is called when the database is started. */
951
UNIV_INTERN
952
void
953
trx_sys_init_at_db_start(void)
954
/*==========================*/
955
{
956
	trx_sysf_t*	sys_header;
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
957
	ib_uint64_t	rows_to_undo	= 0;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
958
	const char*	unit		= "";
959
	trx_t*		trx;
960
	mtr_t		mtr;
961
962
	mtr_start(&mtr);
963
964
	ut_ad(trx_sys == NULL);
965
966
	mutex_enter(&kernel_mutex);
967
2023.3.17 by Monty Taylor
More casting. Getting old.
968
        trx_sys = static_cast<trx_sys_t *>(mem_alloc(sizeof(trx_sys_t)));
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
969
970
	sys_header = trx_sysf_get(&mtr);
971
972
	trx_rseg_list_and_array_init(sys_header, &mtr);
973
974
	trx_sys->latest_rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
975
976
	/* VERY important: after the database is started, max_trx_id value is
977
	divisible by TRX_SYS_TRX_ID_WRITE_MARGIN, and the 'if' in
978
	trx_sys_get_new_trx_id will evaluate to TRUE when the function
979
	is first time called, and the value for trx id will be written
980
	to the disk-based header! Thus trx id values will not overlap when
981
	the database is repeatedly started! */
982
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
983
	trx_sys->max_trx_id = 2 * TRX_SYS_TRX_ID_WRITE_MARGIN
984
		+ ut_uint64_align_up(mach_read_from_8(sys_header
985
						   + TRX_SYS_TRX_ID_STORE),
986
				     TRX_SYS_TRX_ID_WRITE_MARGIN);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
987
988
	UT_LIST_INIT(trx_sys->mysql_trx_list);
989
	trx_dummy_sess = sess_open();
990
	trx_lists_init_at_db_start();
991
992
	if (UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
993
		trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
994
995
		for (;;) {
996
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
997
			if (trx->conc_state != TRX_PREPARED) {
998
				rows_to_undo += trx->undo_no;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
999
			}
1000
1001
			trx = UT_LIST_GET_NEXT(trx_list, trx);
1002
1003
			if (!trx) {
1004
				break;
1005
			}
1006
		}
1007
1008
		if (rows_to_undo > 1000000000) {
1009
			unit = "M";
1010
			rows_to_undo = rows_to_undo / 1000000;
1011
		}
1012
1013
		fprintf(stderr,
1014
			"InnoDB: %lu transaction(s) which must be"
1015
			" rolled back or cleaned up\n"
1016
			"InnoDB: in total %lu%s row operations to undo\n",
1017
			(ulong) UT_LIST_GET_LEN(trx_sys->trx_list),
1018
			(ulong) rows_to_undo, unit);
1019
1020
		fprintf(stderr, "InnoDB: Trx id counter is " TRX_ID_FMT "\n",
1819.9.78 by Stewart Smith
fix TRX_ID_FMT and associated printf()
1021
			trx_sys->max_trx_id);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1022
	}
1023
1024
	UT_LIST_INIT(trx_sys->view_list);
1025
1026
	trx_purge_sys_create();
1027
1028
	mutex_exit(&kernel_mutex);
1029
1030
	mtr_commit(&mtr);
1031
}
1032
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1033
/*****************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1034
Creates and initializes the transaction system at the database creation. */
1035
UNIV_INTERN
1036
void
1037
trx_sys_create(void)
1038
/*================*/
1039
{
1040
	mtr_t	mtr;
1041
1042
	mtr_start(&mtr);
1043
1044
	trx_sysf_create(&mtr);
1045
1046
	mtr_commit(&mtr);
1047
1048
	trx_sys_init_at_db_start();
1049
}
1050
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1051
/*****************************************************************//**
1052
Update the file format tag.
1053
@return	always TRUE */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1054
static
1055
ibool
1056
trx_sys_file_format_max_write(
1057
/*==========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1058
	ulint		format_id,	/*!< in: file format id */
1059
	const char**	name)		/*!< out: max file format name, can
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1060
					be NULL */
1061
{
1062
	mtr_t		mtr;
1063
	byte*		ptr;
1064
	buf_block_t*	block;
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
1065
	ib_uint64_t	tag_value;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1066
1067
	mtr_start(&mtr);
1068
1069
	block = buf_page_get(
1070
		TRX_SYS_SPACE, 0, TRX_SYS_PAGE_NO, RW_X_LATCH, &mtr);
1071
1072
	file_format_max.id = format_id;
1073
	file_format_max.name = trx_sys_file_format_id_to_name(format_id);
1074
1075
	ptr = buf_block_get_frame(block) + TRX_SYS_FILE_FORMAT_TAG;
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
1076
	tag_value = format_id + TRX_SYS_FILE_FORMAT_TAG_MAGIC_N;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1077
1078
	if (name) {
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1079
		*name = file_format_max.name;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1080
	}
1081
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
1082
	mlog_write_ull(ptr, tag_value, &mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1083
1084
	mtr_commit(&mtr);
1085
1086
	return(TRUE);
1087
}
1088
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1089
/*****************************************************************//**
1090
Read the file format tag.
1091
@return	the file format or ULINT_UNDEFINED if not set. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1092
static
1093
ulint
1094
trx_sys_file_format_max_read(void)
1095
/*==============================*/
1096
{
1097
	mtr_t			mtr;
1098
	const byte*		ptr;
1099
	const buf_block_t*	block;
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
1100
	ib_id_t			file_format_id;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1101
1102
	/* Since this is called during the startup phase it's safe to
1103
	read the value without a covering mutex. */
1104
	mtr_start(&mtr);
1105
1106
	block = buf_page_get(
1107
		TRX_SYS_SPACE, 0, TRX_SYS_PAGE_NO, RW_X_LATCH, &mtr);
1108
1109
	ptr = buf_block_get_frame(block) + TRX_SYS_FILE_FORMAT_TAG;
1110
	file_format_id = mach_read_from_8(ptr);
1111
1112
	mtr_commit(&mtr);
1113
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
1114
	file_format_id -= TRX_SYS_FILE_FORMAT_TAG_MAGIC_N;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1115
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
1116
	if (file_format_id >= FILE_FORMAT_NAME_N) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1117
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1118
		/* Either it has never been tagged, or garbage in it. */
1119
		return(ULINT_UNDEFINED);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1120
	}
1121
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
1122
	return((ulint) file_format_id);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1123
}
1124
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1125
/*****************************************************************//**
1126
Get the name representation of the file format from its id.
1127
@return	pointer to the name */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1128
UNIV_INTERN
1129
const char*
1130
trx_sys_file_format_id_to_name(
1131
/*===========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1132
	const ulint	id)	/*!< in: id of the file format */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1133
{
1134
	ut_a(id < FILE_FORMAT_NAME_N);
1135
1136
	return(file_format_name_map[id]);
1137
}
1138
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1139
/*****************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1140
Check for the max file format tag stored on disk. Note: If max_format_id
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1141
is == DICT_TF_FORMAT_MAX + 1 then we only print a warning.
1142
@return	DB_SUCCESS or error code */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1143
UNIV_INTERN
1144
ulint
1145
trx_sys_file_format_max_check(
1146
/*==========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1147
	ulint	max_format_id)	/*!< in: max format id to check */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1148
{
1149
	ulint	format_id;
1150
1151
	/* Check the file format in the tablespace. Do not try to
1152
	recover if the file format is not supported by the engine
1153
	unless forced by the user. */
1154
	format_id = trx_sys_file_format_max_read();
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1155
	if (format_id == ULINT_UNDEFINED) {
1156
		/* Format ID was not set. Set it to minimum possible
1157
		value. */
1819.7.175 by Jimmy Yang, Stewart Smith
Merge Revision revid:jimmy.yang@oracle.com-20100617091353-5zga8o5hxpi0l15q from MySQL InnoDB
1158
		format_id = DICT_TF_FORMAT_MIN;
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1159
	}
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1160
1161
	ut_print_timestamp(stderr);
1162
	fprintf(stderr,
1163
		"  InnoDB: highest supported file format is %s.\n",
1164
		trx_sys_file_format_id_to_name(DICT_TF_FORMAT_MAX));
1165
1166
	if (format_id > DICT_TF_FORMAT_MAX) {
1167
1168
		ut_a(format_id < FILE_FORMAT_NAME_N);
1169
1170
		ut_print_timestamp(stderr);
1171
		fprintf(stderr,
1172
			"  InnoDB: %s: the system tablespace is in a file "
1173
			"format that this version doesn't support - %s\n",
1174
			((max_format_id <= DICT_TF_FORMAT_MAX)
1175
				? "Error" : "Warning"),
1176
			trx_sys_file_format_id_to_name(format_id));
1177
1178
		if (max_format_id <= DICT_TF_FORMAT_MAX) {
1179
			return(DB_ERROR);
1180
		}
1181
	}
1182
1183
	format_id = (format_id > max_format_id) ? format_id : max_format_id;
1184
1185
	/* We don't need a mutex here, as this function should only
1186
	be called once at start up. */
1187
	file_format_max.id = format_id;
1188
	file_format_max.name = trx_sys_file_format_id_to_name(format_id);
1189
1190
	return(DB_SUCCESS);
1191
}
1192
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1193
/*****************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1194
Set the file format id unconditionally except if it's already the
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1195
same value.
1196
@return	TRUE if value updated */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1197
UNIV_INTERN
1198
ibool
1199
trx_sys_file_format_max_set(
1200
/*========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1201
	ulint		format_id,	/*!< in: file format id */
1202
	const char**	name)		/*!< out: max file format name or
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1203
					NULL if not needed. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1204
{
1205
	ibool		ret = FALSE;
1206
1207
	ut_a(format_id <= DICT_TF_FORMAT_MAX);
1208
1209
	mutex_enter(&file_format_max.mutex);
1210
1211
	/* Only update if not already same value. */
1212
	if (format_id != file_format_max.id) {
1213
1214
		ret = trx_sys_file_format_max_write(format_id, name);
1215
	}
1216
1217
	mutex_exit(&file_format_max.mutex);
1218
1219
	return(ret);
1220
}
1221
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1222
/********************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1223
Tags the system table space with minimum format id if it has not been
1224
tagged yet.
1225
WARNING: This function is only called during the startup and AFTER the
1226
redo log application during recovery has finished. */
1227
UNIV_INTERN
1228
void
1229
trx_sys_file_format_tag_init(void)
1230
/*==============================*/
1231
{
1232
	ulint	format_id;
1233
1234
	format_id = trx_sys_file_format_max_read();
1235
1236
	/* If format_id is not set then set it to the minimum. */
1237
	if (format_id == ULINT_UNDEFINED) {
1819.7.175 by Jimmy Yang, Stewart Smith
Merge Revision revid:jimmy.yang@oracle.com-20100617091353-5zga8o5hxpi0l15q from MySQL InnoDB
1238
		trx_sys_file_format_max_set(DICT_TF_FORMAT_MIN, NULL);
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1239
	}
1240
}
1241
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1242
/********************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1243
Update the file format tag in the system tablespace only if the given
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1244
format id is greater than the known max id.
1245
@return	TRUE if format_id was bigger than the known max id */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1246
UNIV_INTERN
1247
ibool
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1248
trx_sys_file_format_max_upgrade(
1249
/*============================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1250
	const char**	name,		/*!< out: max file format name */
1251
	ulint		format_id)	/*!< in: file format identifier */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1252
{
1253
	ibool		ret = FALSE;
1254
1255
	ut_a(name);
1256
	ut_a(file_format_max.name != NULL);
1257
	ut_a(format_id <= DICT_TF_FORMAT_MAX);
1258
1259
	mutex_enter(&file_format_max.mutex);
1260
1261
	if (format_id > file_format_max.id) {
1262
1263
		ret = trx_sys_file_format_max_write(format_id, name);
1264
	}
1265
1266
	mutex_exit(&file_format_max.mutex);
1267
1268
	return(ret);
1269
}
1270
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1271
/*****************************************************************//**
1272
Get the name representation of the file format from its id.
1273
@return	pointer to the max format name */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1274
UNIV_INTERN
1275
const char*
1276
trx_sys_file_format_max_get(void)
1277
/*=============================*/
1278
{
1279
	return(file_format_max.name);
1280
}
1281
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1282
/*****************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1283
Initializes the tablespace tag system. */
1284
UNIV_INTERN
1285
void
1286
trx_sys_file_format_init(void)
1287
/*==========================*/
1288
{
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
1289
	mutex_create(file_format_max_mutex_key,
1290
		     &file_format_max.mutex, SYNC_FILE_FORMAT_TAG);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1291
1292
	/* We don't need a mutex here, as this function should only
1293
	be called once at start up. */
1819.7.175 by Jimmy Yang, Stewart Smith
Merge Revision revid:jimmy.yang@oracle.com-20100617091353-5zga8o5hxpi0l15q from MySQL InnoDB
1294
	file_format_max.id = DICT_TF_FORMAT_MIN;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1295
1296
	file_format_max.name = trx_sys_file_format_id_to_name(
1297
		file_format_max.id);
1298
}
1299
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1300
/*****************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1301
Closes the tablespace tag system. */
1302
UNIV_INTERN
1303
void
1304
trx_sys_file_format_close(void)
1305
/*===========================*/
1306
{
1307
	/* Does nothing at the moment */
1308
}
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
1309
1310
/*********************************************************************
1311
Creates the rollback segments */
1312
UNIV_INTERN
1313
void
1314
trx_sys_create_rsegs(
1315
/*=================*/
1316
	ulint	n_rsegs)	/*!< number of rollback segments to create */
1317
{
1318
	ulint	new_rsegs = 0;
1319
1320
	/* Do not create additional rollback segments if
1321
	innodb_force_recovery has been set and the database
1322
	was not shutdown cleanly. */
1323
	if (!srv_force_recovery && !recv_needed_recovery) {
1324
		ulint	i;
1325
1326
		for (i = 0;  i < n_rsegs; ++i) {
1327
1328
			if (trx_rseg_create() != NULL) {
1329
				++new_rsegs;
1330
			} else {
1331
				break;
1332
			}
1333
		}
1334
	}
1335
1336
	if (new_rsegs > 0) {
1337
		fprintf(stderr,
1338
			"InnoDB: %lu rollback segment(s) active.\n",
1339
		       	new_rsegs);
1340
	}
1341
}
1342
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1343
#else /* !UNIV_HOTBACKUP */
1344
/*****************************************************************//**
1345
Prints to stderr the MySQL binlog info in the system header if the
1346
magic number shows it valid. */
1347
UNIV_INTERN
1348
void
1349
trx_sys_print_mysql_binlog_offset_from_page(
1350
/*========================================*/
1351
	const byte*	page)	/*!< in: buffer containing the trx
1352
				system header page, i.e., page number
1353
				TRX_SYS_PAGE_NO in the tablespace */
1354
{
1355
	const trx_sysf_t*	sys_header;
1356
1357
	sys_header = page + TRX_SYS;
1358
1359
	if (mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
1360
			     + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
1361
	    == TRX_SYS_MYSQL_LOG_MAGIC_N) {
1362
1363
		fprintf(stderr,
1364
			"ibbackup: Last MySQL binlog file position %lu %lu,"
1365
			" file name %s\n",
1366
			(ulong) mach_read_from_4(
1367
				sys_header + TRX_SYS_MYSQL_LOG_INFO
1368
				+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
1369
			(ulong) mach_read_from_4(
1370
				sys_header + TRX_SYS_MYSQL_LOG_INFO
1371
				+ TRX_SYS_MYSQL_LOG_OFFSET_LOW),
1372
			sys_header + TRX_SYS_MYSQL_LOG_INFO
1373
			+ TRX_SYS_MYSQL_LOG_NAME);
1374
	}
1375
}
1376
1377
1378
/* THESE ARE COPIED FROM NON-HOTBACKUP PART OF THE INNODB SOURCE TREE
1379
   (This code duplicaton should be fixed at some point!)
1380
*/
1381
1382
#define	TRX_SYS_SPACE	0	/* the SYSTEM tablespace */
1383
/* The offset of the file format tag on the trx system header page */
1384
#define TRX_SYS_FILE_FORMAT_TAG		(UNIV_PAGE_SIZE - 16)
1385
/* We use these random constants to reduce the probability of reading
1386
garbage (from previous versions) that maps to an actual format id. We
1387
use these as bit masks at the time of  reading and writing from/to disk. */
1388
#define TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_LOW	3645922177UL
1389
#define TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_HIGH	2745987765UL
1390
1391
/* END OF COPIED DEFINITIONS */
1392
1393
1394
/*****************************************************************//**
1395
Reads the file format id from the first system table space file.
1396
Even if the call succeeds and returns TRUE, the returned format id
1397
may be ULINT_UNDEFINED signalling that the format id was not present
1398
in the data file.
1399
@return TRUE if call succeeds */
1400
UNIV_INTERN
1401
ibool
1402
trx_sys_read_file_format_id(
1403
/*========================*/
1404
	const char *pathname,  /*!< in: pathname of the first system
1405
				        table space file */
1406
	ulint *format_id)      /*!< out: file format of the system table
1407
				         space */
1408
{
1409
	os_file_t	file;
1410
	ibool		success;
1411
	byte		buf[UNIV_PAGE_SIZE * 2];
1412
	page_t*		page = ut_align(buf, UNIV_PAGE_SIZE);
1413
	const byte*	ptr;
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
1414
	ib_id_t		file_format_id;
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1415
1416
	*format_id = ULINT_UNDEFINED;
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
1417
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1418
	file = os_file_create_simple_no_error_handling(
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
1419
		innodb_file_data_key,
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1420
		pathname,
1421
		OS_FILE_OPEN,
1422
		OS_FILE_READ_ONLY,
1423
		&success
1424
	);
1425
	if (!success) {
1426
		/* The following call prints an error message */
1427
		os_file_get_last_error(TRUE);
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
1428
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1429
		ut_print_timestamp(stderr);
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
1430
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1431
		fprintf(stderr,
1432
"  ibbackup: Error: trying to read system tablespace file format,\n"
1433
"  ibbackup: but could not open the tablespace file %s!\n",
1434
			pathname
1435
		);
1436
		return(FALSE);
1437
	}
1438
1439
	/* Read the page on which file format is stored */
1440
1441
	success = os_file_read_no_error_handling(
1442
		file, page, TRX_SYS_PAGE_NO * UNIV_PAGE_SIZE, 0, UNIV_PAGE_SIZE
1443
	);
1444
	if (!success) {
1445
		/* The following call prints an error message */
1446
		os_file_get_last_error(TRUE);
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
1447
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1448
		ut_print_timestamp(stderr);
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
1449
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1450
		fprintf(stderr,
1451
"  ibbackup: Error: trying to read system table space file format,\n"
1452
"  ibbackup: but failed to read the tablespace file %s!\n",
1453
			pathname
1454
		);
1455
		os_file_close(file);
1456
		return(FALSE);
1457
	}
1458
	os_file_close(file);
1459
1460
	/* get the file format from the page */
1461
	ptr = page + TRX_SYS_FILE_FORMAT_TAG;
1462
	file_format_id = mach_read_from_8(ptr);
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
1463
	file_format_id -= TRX_SYS_FILE_FORMAT_TAG_MAGIC_N;
1464
1465
	if (file_format_id >= FILE_FORMAT_NAME_N) {
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1466
1467
		/* Either it has never been tagged, or garbage in it. */
1468
		return(TRUE);
1469
	}
1819.9.31 by Marko Mäkelä, Stewart Smith
Merge Revision revid:marko.makela@oracle.com-20100623110659-pk5bqnmo0j7hj6md from MySQL InnoDB
1470
1471
	*format_id = (ulint) file_format_id;
1472
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1473
	return(TRUE);
1474
}
1475
1476
1477
/*****************************************************************//**
1478
Reads the file format id from the given per-table data file.
1479
@return TRUE if call succeeds */
1480
UNIV_INTERN
1481
ibool
1482
trx_sys_read_pertable_file_format_id(
1483
/*=================================*/
1484
	const char *pathname,  /*!< in: pathname of a per-table
1485
				        datafile */
1486
	ulint *format_id)      /*!< out: file format of the per-table
1487
				         data file */
1488
{
1489
	os_file_t	file;
1490
	ibool		success;
1491
	byte		buf[UNIV_PAGE_SIZE * 2];
1492
	page_t*		page = ut_align(buf, UNIV_PAGE_SIZE);
1493
	const byte*	ptr;
1494
	ib_uint32_t	flags;
1495
1496
	*format_id = ULINT_UNDEFINED;
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
1497
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1498
	file = os_file_create_simple_no_error_handling(
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
1499
		innodb_file_data_key,
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1500
		pathname,
1501
		OS_FILE_OPEN,
1502
		OS_FILE_READ_ONLY,
1503
		&success
1504
	);
1505
	if (!success) {
1506
		/* The following call prints an error message */
1507
		os_file_get_last_error(TRUE);
1508
        
1509
		ut_print_timestamp(stderr);
1510
        
1511
		fprintf(stderr,
1512
"  ibbackup: Error: trying to read per-table tablespace format,\n"
1513
"  ibbackup: but could not open the tablespace file %s!\n",
1514
			pathname
1515
		);
1516
		return(FALSE);
1517
	}
1518
1519
	/* Read the first page of the per-table datafile */
1520
1521
	success = os_file_read_no_error_handling(
1522
		file, page, 0, 0, UNIV_PAGE_SIZE
1523
	);
1524
	if (!success) {
1525
		/* The following call prints an error message */
1526
		os_file_get_last_error(TRUE);
1527
        
1528
		ut_print_timestamp(stderr);
1529
        
1530
		fprintf(stderr,
1531
"  ibbackup: Error: trying to per-table data file format,\n"
1532
"  ibbackup: but failed to read the tablespace file %s!\n",
1533
			pathname
1534
		);
1535
		os_file_close(file);
1536
		return(FALSE);
1537
	}
1538
	os_file_close(file);
1539
1540
	/* get the file format from the page */
1541
	ptr = page + 54;
1542
	flags = mach_read_from_4(ptr);
1543
	if (flags == 0) {
1544
		/* file format is Antelope */
1545
		*format_id = 0;
1546
		return (TRUE);
1547
	} else if (flags & 1) {
1548
		/* tablespace flags are ok */
1549
		*format_id = (flags / 32) % 128;
1550
		return (TRUE);
1551
	} else {
1552
		/* bad tablespace flags */
1553
		return(FALSE);
1554
	}
1555
}
1556
1557
1558
/*****************************************************************//**
1559
Get the name representation of the file format from its id.
1560
@return	pointer to the name */
1561
UNIV_INTERN
1562
const char*
1563
trx_sys_file_format_id_to_name(
1564
/*===========================*/
1565
	const ulint	id)	/*!< in: id of the file format */
1566
{
1567
	if (!(id < FILE_FORMAT_NAME_N)) {
1568
		/* unknown id */
1569
		return ("Unknown");
1570
	}
1571
1572
	return(file_format_name_map[id]);
1573
}
1574
1575
#endif /* !UNIV_HOTBACKUP */
1819.5.106 by stewart at flamingspork
[patch 106/129] Merge patch for revision 1915 from InnoDB SVN:
1576
1819.5.149 by pekka
Merge Revision revid:svn-v4:16c675df-0fcb-4bc9-8058-dcc011a37293:branches/zip:6275 from MySQL InnoDB
1577
#ifndef UNIV_HOTBACKUP
1819.5.106 by stewart at flamingspork
[patch 106/129] Merge patch for revision 1915 from InnoDB SVN:
1578
/*********************************************************************
1579
Shutdown/Close the transaction system. */
1580
UNIV_INTERN
1581
void
1582
trx_sys_close(void)
1583
/*===============*/
1584
{
1585
	trx_rseg_t*	rseg;
1586
	read_view_t*	view;
1587
1588
	ut_ad(trx_sys != NULL);
1589
1590
	/* Check that all read views are closed except read view owned
1591
	by a purge. */
1592
1593
	if (UT_LIST_GET_LEN(trx_sys->view_list) > 1) {
1594
		fprintf(stderr,
1595
			"InnoDB: Error: all read views were not closed"
1596
			" before shutdown:\n"
1597
			"InnoDB: %lu read views open \n",
2023.3.26 by mordred
A few 32-bit fixes.
1598
			static_cast<ulint>(UT_LIST_GET_LEN(trx_sys->view_list)) - 1);
1819.5.106 by stewart at flamingspork
[patch 106/129] Merge patch for revision 1915 from InnoDB SVN:
1599
	}
1600
1601
	sess_close(trx_dummy_sess);
1602
	trx_dummy_sess = NULL;
1603
1604
	trx_purge_sys_close();
1605
1606
	mutex_enter(&kernel_mutex);
1607
1608
	/* Free the double write data structures. */
1609
	ut_a(trx_doublewrite != NULL);
1610
	ut_free(trx_doublewrite->write_buf_unaligned);
1611
	trx_doublewrite->write_buf_unaligned = NULL;
1612
1613
	mem_free(trx_doublewrite->buf_block_arr);
1614
	trx_doublewrite->buf_block_arr = NULL;
1615
1616
	mutex_free(&trx_doublewrite->mutex);
1617
	mem_free(trx_doublewrite);
1618
	trx_doublewrite = NULL;
1619
1620
	/* There can't be any active transactions. */
1621
	rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
1622
1623
	while (rseg != NULL) {
1624
		trx_rseg_t*	prev_rseg = rseg;
1625
1626
		rseg = UT_LIST_GET_NEXT(rseg_list, prev_rseg);
1627
		UT_LIST_REMOVE(rseg_list, trx_sys->rseg_list, prev_rseg);
1628
1629
		trx_rseg_mem_free(prev_rseg);
1630
	}
1631
1632
	view = UT_LIST_GET_FIRST(trx_sys->view_list);
1633
1634
	while (view != NULL) {
1635
		read_view_t*	prev_view = view;
1636
1637
		view = UT_LIST_GET_NEXT(view_list, prev_view);
1638
1639
		/* Views are allocated from the trx_sys->global_read_view_heap.
1640
		So, we simply remove the element here. */
1641
		UT_LIST_REMOVE(view_list, trx_sys->view_list, prev_view);
1642
	}
1643
1644
	ut_a(UT_LIST_GET_LEN(trx_sys->trx_list) == 0);
1645
	ut_a(UT_LIST_GET_LEN(trx_sys->rseg_list) == 0);
1646
	ut_a(UT_LIST_GET_LEN(trx_sys->view_list) == 0);
1647
	ut_a(UT_LIST_GET_LEN(trx_sys->mysql_trx_list) == 0);
1648
1649
	mem_free(trx_sys);
1650
1651
	trx_sys = NULL;
1652
	mutex_exit(&kernel_mutex);
1653
}
1819.5.149 by pekka
Merge Revision revid:svn-v4:16c675df-0fcb-4bc9-8058-dcc011a37293:branches/zip:6275 from MySQL InnoDB
1654
#endif /* !UNIV_HOTBACKUP */