~akopytov/percona-xtrabackup/bug1210266-2.1

392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
1
/******************************************************
2
XtraBackup: hot backup tool for InnoDB
472 by Alexey Kopytov
s/Percona Inc/Percona Ireland Ltd/g
3
(c) 2009-2012 Percona Ireland Ltd.
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
4
Originally Created 3/3/2009 Yasufumi Kinoshita
5
Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
6
Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
7
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; version 2 of the License.
11
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
GNU General Public License for more details.
16
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21
*******************************************************/
22
23
/* Source file cursor implementation */
24
25
#include <my_base.h>
26
#include "innodb_int.h"
27
#include "fil_cur.h"
28
#include "common.h"
534.7.1 by Laurynas Biveinis
Implement bitmap-based incremental backups.
29
#include "read_filt.h"
398.1.1 by Laurynas Biveinis
Non-functional refactoring:
30
#include "xtrabackup.h"
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
31
32
/* Size of read buffer in pages */
33
#define XB_FIL_CUR_PAGES 64
34
546.1.3 by Alexey Kopytov
Manual merge from 2.0.
35
/***********************************************************************
36
Extracts the relative path ("database/table.ibd") of a tablespace from a
37
specified possibly absolute path.
38
39
For user tablespaces both "./database/table.ibd" and
40
"/remote/dir/database/table.ibd" result in "database/table.ibd".
41
42
For system tablepsaces (i.e. When is_system is TRUE) both "/remote/dir/ibdata1"
43
and "./ibdata1" yield "ibdata1" in the output. */
44
static
45
const char *
46
xb_get_relative_path(
47
/*=================*/
48
	const char*	path,		/*!< in: tablespace path (either
49
			  		relative or absolute) */
50
	ibool		is_system)	/*!< in: TRUE for system tablespaces,
51
					i.e. when only the filename must be
52
					returned. */
53
{
54
	const char *next;
55
	const char *cur;
56
	const char *prev;
57
58
	prev = NULL;
59
	cur = path;
60
61
	while ((next = strchr(cur, SRV_PATH_SEPARATOR)) != NULL) {
62
63
		prev = cur;
64
		cur = next + 1;
65
	}
66
67
	if (is_system) {
68
69
		return(cur);
70
	} else {
71
72
		return((prev == NULL) ? cur : prev);
73
	}
74
75
}
76
595.1.1 by Alexey Kopytov
Very manual merge from 2.0.
77
/**********************************************************************//**
78
Closes a file. */
79
static
80
void
81
xb_fil_node_close_file(
82
/*===================*/
83
	fil_node_t*	node)	/*!< in: file node */
84
{
85
	ibool	ret;
86
87
	mutex_enter(&fil_system->mutex);
88
89
	ut_ad(node);
90
	ut_a(node->n_pending == 0);
91
	ut_a(node->n_pending_flushes == 0);
92
#if MYSQL_VERSION_ID >= 50600
93
	ut_a(!node->being_extended);
94
#endif
95
96
	if (!node->open) {
97
98
		mutex_exit(&fil_system->mutex);
99
100
		return;
101
	}
102
103
	ret = os_file_close(node->handle);
104
	ut_a(ret);
105
106
	node->open = FALSE;
107
108
	ut_a(fil_system->n_open > 0);
109
	fil_system->n_open--;
110
#if MYSQL_VERSION_ID >= 50600
111
	fil_n_file_opened--;
112
#endif
113
114
	if (node->space->purpose == FIL_TABLESPACE &&
115
	    !trx_sys_sys_space(node->space->id)) {
116
117
		ut_a(UT_LIST_GET_LEN(fil_system->LRU) > 0);
118
119
		/* The node is in the LRU list, remove it */
120
		UT_LIST_REMOVE(LRU, fil_system->LRU, node);
121
	}
122
123
	mutex_exit(&fil_system->mutex);
124
}
125
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
126
/************************************************************************
534.7.1 by Laurynas Biveinis
Implement bitmap-based incremental backups.
127
Open a source file cursor and initialize the associated read filter.
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
128
129
@return XB_FIL_CUR_SUCCESS on success, XB_FIL_CUR_SKIP if the source file must
130
be skipped and XB_FIL_CUR_ERROR on error. */
131
xb_fil_cur_result_t
132
xb_fil_cur_open(
133
/*============*/
134
	xb_fil_cur_t*	cursor,		/*!< out: source file cursor */
534.7.1 by Laurynas Biveinis
Implement bitmap-based incremental backups.
135
	xb_read_filt_t*	read_filter,	/*!< in/out: the read filter */
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
136
	fil_node_t*	node,		/*!< in: source tablespace node */
137
	uint		thread_n)	/*!< thread number for diagnostics */
138
{
139
	ulint	page_size;
140
	ulint	page_size_shift;
141
	ulint	zip_size;
595.1.1 by Alexey Kopytov
Very manual merge from 2.0.
142
	ibool	success;
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
143
144
	/* Initialize these first so xb_fil_cur_close() handles them correctly
145
	in case of error */
146
	cursor->orig_buf = NULL;
595.1.1 by Alexey Kopytov
Very manual merge from 2.0.
147
	cursor->node = NULL;
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
148
413.1.1 by Sergei Glushchenko
merge fix for bug #932623 from 2.0
149
	cursor->space_id = node->space->id;
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
150
	cursor->is_system = trx_sys_sys_space(node->space->id);
151
577 by Alexey Kopytov
Fixed an incorrect merge resulting in bug766033.sh failures on *56 builds.
152
	strncpy(cursor->abs_path, node->name, sizeof(cursor->abs_path));
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
153
546.1.3 by Alexey Kopytov
Manual merge from 2.0.
154
	/* Get the relative path for the destination tablespace name, i.e. the
155
	one that can be appended to the backup root directory. Non-system
156
	tablespaces may have absolute paths for remote tablespaces in MySQL
157
	5.6+. We want to make "local" copies for the backup. */
158
	strncpy(cursor->rel_path,
577 by Alexey Kopytov
Fixed an incorrect merge resulting in bug766033.sh failures on *56 builds.
159
		xb_get_relative_path(cursor->abs_path, cursor->is_system),
546.1.3 by Alexey Kopytov
Manual merge from 2.0.
160
		sizeof(cursor->rel_path));
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
161
595.1.1 by Alexey Kopytov
Very manual merge from 2.0.
162
	/* In the backup mode we should already have a tablespace handle created
163
	by fil_load_single_table_tablespace() unless it is a system
164
	tablespace. Otherwise we open the file here. */
165
	if (cursor->is_system || !srv_backup_mode) {
166
		node->handle =
167
			xb_file_create_no_error_handling(node->name,
493.1.1 by Alexey Kopytov
Manual merge from 2.0.
168
						 OS_FILE_OPEN,
169
						 OS_FILE_READ_ONLY,
170
						 &success);
595.1.1 by Alexey Kopytov
Very manual merge from 2.0.
171
		if (!success) {
172
			/* The following call prints an error message */
173
			os_file_get_last_error(TRUE);
174
175
			msg("[%02u] xtrabackup: error: cannot open "
176
			    "tablespace %s\n",
177
			    thread_n, cursor->abs_path);
178
179
			return(XB_FIL_CUR_ERROR);
180
		}
181
		mutex_enter(&fil_system->mutex);
182
183
		node->open = TRUE;
184
185
		fil_system->n_open++;
186
#if MYSQL_VERSION_ID >= 50600
187
		fil_n_file_opened++;
188
#endif
189
190
		if (node->space->purpose == FIL_TABLESPACE &&
191
		    !trx_sys_sys_space(node->space->id)) {
192
193
			/* Put the node to the LRU list */
194
			UT_LIST_ADD_FIRST(LRU, fil_system->LRU, node);
195
		}
196
197
		mutex_exit(&fil_system->mutex);
198
	}
199
200
	ut_ad(node->open);
201
202
	cursor->node = node;
203
	cursor->file = node->handle;
204
205
	if (my_fstat(cursor->file, &cursor->statinfo, MYF(MY_WME))) {
206
		msg("[%02u] xtrabackup: error: cannot stat %s\n",
207
		    thread_n, cursor->abs_path);
208
209
		xb_fil_cur_close(cursor);
210
211
		return(XB_FIL_CUR_ERROR);
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
212
	}
493.1.1 by Alexey Kopytov
Manual merge from 2.0.
213
214
	xb_file_set_nocache(cursor->file, node->name, "OPEN");
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
215
	posix_fadvise(cursor->file, 0, 0, POSIX_FADV_SEQUENTIAL);
401 by Alexey Kopytov
Manual merge of the fix for bug #713267 from 2.0.
216
217
	/* Determine the page size */
218
	zip_size = xb_get_zip_size(cursor->file);
219
	if (zip_size == ULINT_UNDEFINED) {
595.1.1 by Alexey Kopytov
Very manual merge from 2.0.
220
		xb_fil_cur_close(cursor);
401 by Alexey Kopytov
Manual merge of the fix for bug #713267 from 2.0.
221
		return(XB_FIL_CUR_SKIP);
222
	} else if (zip_size) {
223
		page_size = zip_size;
224
		page_size_shift = get_bit_shift(page_size);
225
		msg("[%02u] %s is compressed with page size = "
226
		    "%lu bytes\n", thread_n, node->name, page_size);
227
		if (page_size_shift < 10 || page_size_shift > 14) {
228
			msg("[%02u] xtrabackup: Error: Invalid "
229
			    "page size: %lu.\n", thread_n, page_size);
230
			ut_error;
231
		}
232
	} else {
233
		page_size = UNIV_PAGE_SIZE;
234
		page_size_shift = UNIV_PAGE_SIZE_SHIFT;
235
	}
236
	cursor->page_size = page_size;
237
	cursor->page_size_shift = page_size_shift;
238
	cursor->zip_size = zip_size;
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
239
240
	/* Allocate read buffer */
241
	cursor->buf_size = XB_FIL_CUR_PAGES * page_size;
488 by Laurynas Biveinis
Merge C++ build support from 2.0
242
	cursor->orig_buf = static_cast<byte *>
243
		(ut_malloc(cursor->buf_size + UNIV_PAGE_SIZE));
244
	cursor->buf = static_cast<byte *>
245
		(ut_align(cursor->orig_buf, UNIV_PAGE_SIZE));
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
246
247
	cursor->buf_read = 0;
248
	cursor->buf_npages = 0;
249
	cursor->buf_offset = 0;
250
	cursor->buf_page_no = 0;
251
	cursor->thread_n = thread_n;
252
477.1.1 by Alexey Kopytov
Compact backups implementation:
253
	cursor->space_size = cursor->statinfo.st_size / page_size;
254
534.7.1 by Laurynas Biveinis
Implement bitmap-based incremental backups.
255
	cursor->read_filter = read_filter;
256
	cursor->read_filter->init(&cursor->read_filter_ctxt, cursor,
257
				  node->space->id);
258
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
259
	return(XB_FIL_CUR_SUCCESS);
260
}
261
262
/************************************************************************
263
Reads and verifies the next block of pages from the source
264
file. Positions the cursor after the last read non-corrupted page.
265
266
@return XB_FIL_CUR_SUCCESS if some have been read successfully, XB_FIL_CUR_EOF
267
if there are no more pages to read and XB_FIL_CUR_ERROR on error. */
268
xb_fil_cur_result_t
269
xb_fil_cur_read(
270
/*============*/
271
	xb_fil_cur_t*	cursor)	/*!< in/out: source file cursor */
272
{
273
	ibool			success;
274
	byte*			page;
275
	ulint			i;
276
	ulint			npages;
277
	ulint			retry_count;
278
	xb_fil_cur_result_t	ret;
534.7.1 by Laurynas Biveinis
Implement bitmap-based incremental backups.
279
	ib_int64_t		offset;
522.6.1 by Laurynas Biveinis
Merge build against MySQL 5.6 support from 2.0.
280
	ib_int64_t		to_read;
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
281
534.7.1 by Laurynas Biveinis
Implement bitmap-based incremental backups.
282
	cursor->read_filter->get_next_batch(&cursor->read_filter_ctxt,
283
					    &offset, &to_read);
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
284
285
	if (to_read == 0LL) {
286
		return(XB_FIL_CUR_EOF);
287
	}
288
522.6.1 by Laurynas Biveinis
Merge build against MySQL 5.6 support from 2.0.
289
	if (to_read > (ib_int64_t) cursor->buf_size) {
290
		to_read = (ib_int64_t) cursor->buf_size;
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
291
	}
534.7.1 by Laurynas Biveinis
Implement bitmap-based incremental backups.
292
	xb_a(to_read > 0 && to_read <= 0xFFFFFFFFLL);
293
	xb_a(to_read % cursor->page_size == 0);
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
294
295
	npages = (ulint) (to_read >> cursor->page_size_shift);
296
297
	retry_count = 10;
298
	ret = XB_FIL_CUR_SUCCESS;
299
300
read_retry:
301
	xtrabackup_io_throttling();
302
303
	cursor->buf_read = 0;
304
	cursor->buf_npages = 0;
534.7.1 by Laurynas Biveinis
Implement bitmap-based incremental backups.
305
	cursor->buf_offset = offset;
306
	cursor->buf_page_no = (ulint) (offset >> cursor->page_size_shift);
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
307
595.1.1 by Alexey Kopytov
Very manual merge from 2.0.
308
	success = xb_os_file_read(cursor->file, cursor->buf, offset,
309
				  to_read);
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
310
	if (!success) {
311
		return(XB_FIL_CUR_ERROR);
312
	}
313
314
	/* check pages for corruption and re-read if necessary. i.e. in case of
315
	partially written pages */
534.7.1 by Laurynas Biveinis
Implement bitmap-based incremental backups.
316
	for (page = cursor->buf, i = 0; i < npages;
317
	     page += cursor->page_size, i++) {
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
318
		if (xb_buf_page_is_corrupted(page, cursor->zip_size))
319
		{
320
			ulint page_no = cursor->buf_page_no + i;
321
322
			if (cursor->is_system &&
323
			    page_no >= FSP_EXTENT_SIZE &&
324
			    page_no < FSP_EXTENT_SIZE * 3) {
325
				/* skip doublewrite buffer pages */
534.7.1 by Laurynas Biveinis
Implement bitmap-based incremental backups.
326
				xb_a(cursor->page_size == UNIV_PAGE_SIZE);
477.1.1 by Alexey Kopytov
Compact backups implementation:
327
				msg("[%02u] xtrabackup: "
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
328
				    "Page %lu is a doublewrite buffer page, "
329
				    "skipping.\n", cursor->thread_n, page_no);
330
			} else {
331
				retry_count--;
332
				if (retry_count == 0) {
477.1.1 by Alexey Kopytov
Compact backups implementation:
333
					msg("[%02u] xtrabackup: "
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
334
					    "Error: failed to read page after "
393 by Alexey Kopytov
Manual merge from trunk.
335
					    "10 retries. File %s seems to be "
336
					    "corrupted.\n", cursor->thread_n,
546.1.3 by Alexey Kopytov
Manual merge from 2.0.
337
					    cursor->abs_path);
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
338
					ret = XB_FIL_CUR_ERROR;
339
					break;
340
				}
477.1.1 by Alexey Kopytov
Compact backups implementation:
341
				msg("[%02u] xtrabackup: "
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
342
				    "Database page corruption detected at page "
343
				    "%lu, retrying...\n", cursor->thread_n,
344
				    page_no);
466.3.2 by Alexey Kopytov
Manual merge of the fix for bug #1081882 to 2.1.
345
346
				os_thread_sleep(100000);
347
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
348
				goto read_retry;
349
			}
350
		}
534.7.1 by Laurynas Biveinis
Implement bitmap-based incremental backups.
351
		cursor->buf_read += cursor->page_size;
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
352
		cursor->buf_npages++;
353
	}
354
401 by Alexey Kopytov
Manual merge of the fix for bug #713267 from 2.0.
355
	posix_fadvise(cursor->file, 0, 0, POSIX_FADV_DONTNEED);
356
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
357
	return(ret);
358
}
359
360
/************************************************************************
534.7.1 by Laurynas Biveinis
Implement bitmap-based incremental backups.
361
Close the source file cursor opened with xb_fil_cur_open() and its
362
associated read filter. */
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
363
void
364
xb_fil_cur_close(
365
/*=============*/
366
	xb_fil_cur_t *cursor)	/*!< in/out: source file cursor */
367
{
534.7.1 by Laurynas Biveinis
Implement bitmap-based incremental backups.
368
	cursor->read_filter->deinit(&cursor->read_filter_ctxt);
369
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
370
	if (cursor->orig_buf != NULL) {
371
		ut_free(cursor->orig_buf);
372
	}
595.1.1 by Alexey Kopytov
Very manual merge from 2.0.
373
	if (cursor->node != NULL) {
374
		xb_fil_node_close_file(cursor->node);
375
		cursor->file = XB_FILE_UNDEFINED;
392 by Alexey Kopytov
Refactoring required to do page filtering in xtrabackup.
376
	}
377
}