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 |
}
|