Merge lp:~sergei.glushchenko/percona-xtrabackup/xb21-bug932623 into lp:percona-xtrabackup/2.1

Proposed by Sergei Glushchenko on 2012-07-11
Status: Merged
Approved by: Alexey Kopytov on 2012-07-11
Approved revision: 414
Merged at revision: 416
Proposed branch: lp:~sergei.glushchenko/percona-xtrabackup/xb21-bug932623
Merge into: lp:percona-xtrabackup/2.1
Diff against target: 955 lines (+594/-111)
9 files modified
patches/innodb51_builtin.patch (+67/-4)
src/fil_cur.c (+1/-0)
src/fil_cur.h (+1/-0)
src/innodb_int.c (+76/-0)
src/innodb_int.h (+29/-0)
src/write_filt.c (+1/-0)
src/xtrabackup.c (+333/-107)
src/xtrabackup.h (+1/-0)
test/t/bug932623.sh (+85/-0)
To merge this branch: bzr merge lp:~sergei.glushchenko/percona-xtrabackup/xb21-bug932623
Reviewer Review Type Date Requested Status
Alexey Kopytov (community) 2012-07-11 Approve on 2012-07-11
Review via email: mp+114363@code.launchpad.net

Description of the change

To post a comment you must log in.
Alexey Kopytov (akopytov) :
review: Approve

This branch introduces many messages like this one:

2012-07-31 13:58:32: xb_incremental.sh: ===> /home/laurynas/percona/src/xb21-bug932623/test/../src/xtrabackup --no-defaults --datadir=/home/laurynas/percona/src/xb21-bug932623/test/var1/data --backup --target-dir=/home/laurynas/percona/src/xb21-bug932623/test/var1/data/full
/home/laurynas/percona/src/xb21-bug932623/test/../src/xtrabackup version 2.0.0 for Percona Server 5.1.59 unknown-linux-gnu (x86_64) (revision id: undefined)
xtrabackup: uses posix_fadvise().
xtrabackup: cd to /home/laurynas/percona/src/xb21-bug932623/test/var1/data
xtrabackup: Target instance is assumed as followings.
xtrabackup: innodb_data_home_dir = ./
xtrabackup: innodb_data_file_path = ibdata1:10M:autoextend
xtrabackup: innodb_log_group_home_dir = ./
xtrabackup: innodb_log_files_in_group = 2
xtrabackup: innodb_log_file_size = 5242880
120731 13:58:32 InnoDB: Warning: allocated tablespace 10, old maximum was 9
120731 13:58:32 InnoDB: Warning: trying to init to the tablespace memory cache
InnoDB: a tablespace 10 of name './incremental_sample/test.ibd',
InnoDB: but a tablespace 10 of the same name
InnoDB: already exists in the tablespace memory cache!
InnoDB: We assume that InnoDB did a crash recovery, and you had
InnoDB: an .ibd file for which the table did not exist in the
InnoDB: InnoDB internal data dictionary in the ibdata files.
InnoDB: We assume that you later removed the .ibd and .frm files,
InnoDB: and are now trying to recreate the table. We now remove the
InnoDB: conflicting tablespace object from the memory cache and try
InnoDB: the init again.

Since Sergei is on vacation and I depend on this code, let's keep this "Approved" and merge and I will fix as a follow-up.

Bug 1031324, one-liner fix MP'ed.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'patches/innodb51_builtin.patch'
2--- patches/innodb51_builtin.patch 2012-02-10 05:04:04 +0000
3+++ patches/innodb51_builtin.patch 2012-07-11 09:06:21 +0000
4@@ -613,7 +613,21 @@
5
6 --- a/storage/innobase/include/mem0mem.h
7 +++ b/storage/innobase/include/mem0mem.h
8-@@ -401,6 +401,7 @@
9+@@ -63,6 +63,13 @@
10+ mem_init(
11+ /*=====*/
12+ ulint size); /* in: common pool size in bytes */
13++
14++/******************************************************************//**
15++Closes the memory system. */
16++void
17++mem_close(void);
18++/*===========*/
19++
20+ /******************************************************************
21+ Use this macro instead of the corresponding function! Macro for memory
22+ heap creation. */
23+@@ -401,6 +409,7 @@
24 allocated buffer frame, which can be appended as a
25 free block to the heap, if we need more space;
26 otherwise, this is NULL */
27@@ -654,6 +668,21 @@
28
29 if (heap->free_block) {
30 size += UNIV_PAGE_SIZE;
31+--- a/storage/innobase/include/mem0pool.h
32++++ b/storage/innobase/include/mem0pool.h
33+@@ -42,6 +42,12 @@
34+ /*============*/
35+ /* out: memory pool */
36+ ulint size); /* in: pool size in bytes */
37++/********************************************************************//**
38++Frees a memory pool. */
39++void
40++mem_pool_free(
41++/*==========*/
42++ mem_pool_t* pool); /*!< in, own: memory pool */
43+ /************************************************************************
44+ Allocates memory from a pool. NOTE: This low-level function should only be
45+ used in mem0mem.*! */
46 --- a/storage/innobase/include/srv0srv.h
47 +++ b/storage/innobase/include/srv0srv.h
48 @@ -60,6 +60,8 @@
49@@ -958,7 +987,7 @@
50 /**********************************************************
51 --- a/storage/innobase/mem/mem0dbg.c
52 +++ b/storage/innobase/mem/mem0dbg.c
53-@@ -133,6 +133,14 @@
54+@@ -133,9 +133,30 @@
55 mem_hash_initialized = TRUE;
56 #endif
57
58@@ -973,6 +1002,22 @@
59 mem_comm_pool = mem_pool_create(size);
60 }
61
62++/******************************************************************//**
63++Closes the memory system. */
64++void
65++mem_close(void)
66++/*===========*/
67++{
68++ mem_pool_free(mem_comm_pool);
69++ mem_comm_pool = NULL;
70++#ifdef UNIV_MEM_DEBUG
71++ mem_hash_initialized = FALSE;
72++#endif /* UNIV_MEM_DEBUG */
73++}
74++
75+ #ifdef UNIV_MEM_DEBUG
76+ /**********************************************************************
77+ Initializes an allocated memory field in the debug version. */
78 --- a/storage/innobase/mem/mem0mem.c
79 +++ b/storage/innobase/mem/mem0mem.c
80 @@ -472,6 +472,7 @@
81@@ -1026,7 +1071,25 @@
82 pool = ut_malloc(sizeof(mem_pool_t));
83
84 /* We do not set the memory to zero (FALSE) in the pool,
85-@@ -333,6 +332,10 @@
86+@@ -244,6 +243,17 @@
87+ return(pool);
88+ }
89+
90++/********************************************************************//**
91++Frees a memory pool. */
92++void
93++mem_pool_free(
94++/*==========*/
95++ mem_pool_t* pool) /*!< in, own: memory pool */
96++{
97++ ut_free(pool->buf);
98++ ut_free(pool);
99++}
100++
101+ /************************************************************************
102+ Fills the specified free list. */
103+ static
104+@@ -333,6 +344,10 @@
105 ulint n;
106 ibool ret;
107
108@@ -1037,7 +1100,7 @@
109 n = ut_2_log(ut_max(size + MEM_AREA_EXTRA_SIZE, MEM_AREA_MIN_SIZE));
110
111 mutex_enter(&(pool->mutex));
112-@@ -465,6 +468,11 @@
113+@@ -465,6 +480,11 @@
114 ulint size;
115 ulint n;
116
117
118=== modified file 'src/fil_cur.c'
119--- src/fil_cur.c 2012-05-28 16:49:14 +0000
120+++ src/fil_cur.c 2012-07-11 09:06:21 +0000
121@@ -54,6 +54,7 @@
122 cursor->orig_buf = NULL;
123 cursor->file = XB_FILE_UNDEFINED;
124
125+ cursor->space_id = node->space->id;
126 cursor->is_system = trx_sys_sys_space(node->space->id);
127
128 /* Make the file path relative to the backup root,
129
130=== modified file 'src/fil_cur.h'
131--- src/fil_cur.h 2012-05-25 11:38:15 +0000
132+++ src/fil_cur.h 2012-07-11 09:06:21 +0000
133@@ -53,6 +53,7 @@
134 ulint buf_page_no; /*!< number of the first page in
135 buffer */
136 ulint thread_n; /*!< thread number for diagnostics */
137+ ulint space_id; /*!< ID of tablespace */
138 } xb_fil_cur_t;
139
140 typedef enum {
141
142=== modified file 'src/innodb_int.c'
143--- src/innodb_int.c 2012-02-16 18:02:07 +0000
144+++ src/innodb_int.c 2012-07-11 09:06:21 +0000
145@@ -151,6 +151,82 @@
146 return os_file_flush(file);
147 #endif
148 }
149+/*******************************************************************//**
150+Returns the table space by a given id, NULL if not found. */
151+fil_space_t*
152+xb_space_get_by_id(
153+/*================*/
154+ ulint id) /*!< in: space id */
155+{
156+ fil_space_t* space;
157+
158+ ut_ad(mutex_own(&fil_system->mutex));
159+
160+#ifdef INNODB_VERSION_SHORT
161+ HASH_SEARCH(hash, fil_system->spaces, id,
162+ fil_space_t*, space,
163+ ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
164+ space->id == id);
165+#else
166+ HASH_SEARCH(hash, fil_system->spaces, id, space, space->id == id);
167+#endif
168+
169+ return(space);
170+}
171+
172+/*******************************************************************//**
173+Returns the table space by a given name, NULL if not found. */
174+fil_space_t*
175+xb_space_get_by_name(
176+/*==================*/
177+ const char* name) /*!< in: space name */
178+{
179+ fil_space_t* space;
180+ ulint fold;
181+
182+ ut_ad(mutex_own(&fil_system->mutex));
183+
184+#ifdef INNODB_VERSION_SHORT
185+ fold = ut_fold_string(name);
186+ HASH_SEARCH(name_hash, fil_system->name_hash, fold,
187+ fil_space_t*, space,
188+ ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
189+ !strcmp(name, space->name));
190+#else
191+ HASH_SEARCH(name_hash, fil_system->name_hash, ut_fold_string(name),
192+ space, 0 == strcmp(name, space->name));
193+#endif
194+
195+ return(space);
196+}
197+
198+#ifndef INNODB_VERSION_SHORT
199+
200+/*******************************************************************//**
201+Free all spaces in space_list. */
202+void
203+fil_free_all_spaces(void)
204+/*=====================*/
205+{
206+ fil_space_t* space;
207+
208+ mutex_enter(&fil_system->mutex);
209+
210+ space = UT_LIST_GET_FIRST(fil_system->space_list);
211+
212+ while (space != NULL) {
213+ fil_node_t* node;
214+ fil_space_t* prev_space = space;
215+
216+ space = UT_LIST_GET_NEXT(space_list, space);
217+
218+ fil_space_free(prev_space->id, FALSE);
219+ }
220+
221+ mutex_exit(&fil_system->mutex);
222+}
223+
224+#endif
225
226 void
227 innobase_invalidate_query_cache(
228
229=== modified file 'src/innodb_int.h'
230--- src/innodb_int.h 2012-05-25 11:38:15 +0000
231+++ src/innodb_int.h 2012-07-11 09:06:21 +0000
232@@ -410,6 +410,9 @@
233 extern char *opt_mysql_tmpdir;
234 extern MY_TMPDIR mysql_tmpdir_list;
235
236+/** Value of fil_space_struct::magic_n */
237+#define FIL_SPACE_MAGIC_N 89472
238+
239 /* ==end=== definition at fil0fil.c === */
240
241 /* prototypes for static functions in original */
242@@ -581,6 +584,32 @@
243 /*==========*/
244 os_file_t file); /*!< in, own: handle to a file */
245
246+/*******************************************************************//**
247+Returns the table space by a given id, NULL if not found. */
248+fil_space_t*
249+xb_space_get_by_id(
250+/*================*/
251+ ulint id); /*!< in: space id */
252+
253+/*******************************************************************//**
254+Returns the table space by a given name, NULL if not found. */
255+fil_space_t*
256+xb_space_get_by_name(
257+/*==================*/
258+ const char* name); /*!< in: space name */
259+
260+#ifndef INNODB_VERSION_SHORT
261+
262+#define SRV_SHUTDOWN_NONE 0
263+
264+/*******************************************************************//**
265+Free all spaces in space_list. */
266+void
267+fil_free_all_spaces(void);
268+/*=====================*/
269+
270+#endif
271+
272 void
273 innobase_mysql_prepare_print_arbitrary_thd(void);
274
275
276=== modified file 'src/write_filt.c'
277--- src/write_filt.c 2012-05-25 11:38:15 +0000
278+++ src/write_filt.c 2012-07-11 09:06:21 +0000
279@@ -102,6 +102,7 @@
280 snprintf(meta_name, sizeof(meta_name), "%s%s", dst_name,
281 XB_DELTA_INFO_SUFFIX);
282 info.page_size = cursor->page_size;
283+ info.space_id = cursor->space_id;
284 if (!xb_write_delta_metadata(meta_name, &info)) {
285 msg("[%02lu] xtrabackup: Error: "
286 "failed to write meta info for %s\n",
287
288=== modified file 'src/xtrabackup.c'
289--- src/xtrabackup.c 2012-06-20 16:23:58 +0000
290+++ src/xtrabackup.c 2012-07-11 09:06:21 +0000
291@@ -1500,7 +1500,8 @@
292 return(TRUE);
293 }
294
295- if (fscanf(fp, "page_size = %lu\n", &info->page_size) != 1)
296+ if (fscanf(fp, "page_size = %lu\nspace_id = %lu\n",
297+ &info->page_size, &info->space_id) != 2)
298 r= FALSE;
299
300 fclose(fp);
301@@ -1515,14 +1516,16 @@
302 xb_write_delta_metadata(const char *filename, const xb_delta_info_t *info)
303 {
304 ds_file_t *f;
305- char buf[32];
306+ char buf[64];
307 my_bool ret;
308 size_t len;
309 MY_STAT mystat;
310
311- snprintf(buf, sizeof(buf), "page_size = %lu\n", info->page_size);
312-
313+ snprintf(buf, sizeof(buf),
314+ "page_size = %lu\nspace_id = %lu\n",
315+ info->page_size, info->space_id);
316 len = strlen(buf);
317+
318 mystat.st_size = len;
319 mystat.st_mtime = my_time(0);
320
321@@ -2108,11 +2111,11 @@
322 void* arg)
323 {
324 ulint segment;
325- ulint i;
326+
327
328 segment = *((ulint*)arg);
329
330- for (i = 0;; i++) {
331+ while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) {
332 fil_aio_wait(segment);
333 }
334
335@@ -2265,6 +2268,141 @@
336 ds_meta = NULL;
337 }
338
339+#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD
340+#define SRV_MAX_N_PENDING_SYNC_IOS 100
341+
342+/************************************************************************
343+Initialize the tablespace memory cache and populate it by scanning for and
344+opening data files.
345+@returns DB_SUCCESS or error code.*/
346+ulint
347+xb_data_files_init(void)
348+/*====================*/
349+{
350+ ulint i;
351+ ibool create_new_db;
352+#ifdef XTRADB_BASED
353+ ibool create_new_doublewrite_file;
354+#endif
355+ ulint err;
356+ LSN64 min_flushed_lsn;
357+ LSN64 max_flushed_lsn;
358+ ulint sum_of_new_sizes;
359+
360+#ifndef INNODB_VERSION_SHORT
361+ os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD
362+ * srv_n_file_io_threads,
363+ srv_n_file_io_threads,
364+ SRV_MAX_N_PENDING_SYNC_IOS);
365+
366+ fil_init(srv_max_n_open_files);
367+#else
368+ srv_n_file_io_threads = 2 + srv_n_read_io_threads +
369+ srv_n_write_io_threads;
370+
371+ os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD,
372+ srv_n_read_io_threads,
373+ srv_n_write_io_threads,
374+ SRV_MAX_N_PENDING_SYNC_IOS);
375+
376+ fil_init(srv_file_per_table ? 50000 : 5000,
377+ srv_max_n_open_files);
378+#endif
379+
380+ fsp_init();
381+
382+ for (i = 0; i < srv_n_file_io_threads; i++) {
383+ thread_nr[i] = i;
384+
385+ os_thread_create(io_handler_thread, thread_nr + i,
386+ thread_ids + i);
387+ }
388+
389+ os_thread_sleep(200000); /*0.2 sec*/
390+
391+ err = open_or_create_data_files(&create_new_db,
392+#ifdef XTRADB_BASED
393+ &create_new_doublewrite_file,
394+#endif
395+ &min_flushed_lsn, &max_flushed_lsn,
396+ &sum_of_new_sizes);
397+ if (err != DB_SUCCESS) {
398+ msg("xtrabackup: Could not open or create data files.\n"
399+ "xtrabackup: If you tried to add new data files, and it "
400+ "failed here,\n"
401+ "xtrabackup: you should now edit innodb_data_file_path in "
402+ "my.cnf back\n"
403+ "xtrabackup: to what it was, and remove the new ibdata "
404+ "files InnoDB created\n"
405+ "xtrabackup: in this failed attempt. InnoDB only wrote "
406+ "those files full of\n"
407+ "xtrabackup: zeros, but did not yet use them in any way. "
408+ "But be careful: do not\n"
409+ "xtrabackup: remove old data files which contain your "
410+ "precious data!\n");
411+ return(err);
412+ }
413+
414+ /* create_new_db must not be TRUE.. */
415+ if (create_new_db) {
416+ msg("xtrabackup: could not find data files at the "
417+ "specified datadir\n");
418+ return(DB_ERROR);
419+ }
420+
421+ return(fil_load_single_table_tablespaces());
422+}
423+
424+/************************************************************************
425+Destroy the tablespace memory cache. */
426+void
427+xb_data_files_close(void)
428+/*====================*/
429+{
430+ ulint i;
431+
432+ /* Shutdown the aio threads. This has been copied from
433+ innobase_shutdown_for_mysql(). */
434+
435+ srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
436+
437+ for (i = 0; i < 1000; i++) {
438+ os_aio_wake_all_threads_at_shutdown();
439+
440+ os_mutex_enter(os_sync_mutex);
441+
442+ if (os_thread_count == 0) {
443+
444+ os_mutex_exit(os_sync_mutex);
445+
446+ os_thread_sleep(10000);
447+
448+ break;
449+ }
450+
451+ os_mutex_exit(os_sync_mutex);
452+
453+ os_thread_sleep(10000);
454+ }
455+
456+ if (i == 1000) {
457+ msg("xtrabackup: Warning: %lu threads created by InnoDB"
458+ " had not exited at shutdown!\n",
459+ (ulong) os_thread_count);
460+ }
461+
462+#ifdef INNODB_VERSION_SHORT
463+ os_aio_free();
464+#endif
465+ fil_close_all_files();
466+#ifndef INNODB_VERSION_SHORT
467+ fil_free_all_spaces();
468+#endif
469+ fil_system = NULL;
470+
471+ srv_shutdown_state = SRV_SHUTDOWN_NONE;
472+}
473+
474 static void
475 xtrabackup_backup_func(void)
476 {
477@@ -2418,85 +2556,25 @@
478 srv_general_init();
479
480 {
481- ibool create_new_db;
482-#ifdef XTRADB_BASED
483- ibool create_new_doublewrite_file;
484-#endif
485 ibool log_file_created;
486 ibool log_created = FALSE;
487 ibool log_opened = FALSE;
488- LSN64 min_flushed_lsn;
489- LSN64 max_flushed_lsn;
490- ulint sum_of_new_sizes;
491 ulint err;
492 ulint i;
493
494-
495-
496-
497-#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD
498-#define SRV_MAX_N_PENDING_SYNC_IOS 100
499-
500-#ifndef INNODB_VERSION_SHORT
501- os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD
502- * srv_n_file_io_threads,
503- srv_n_file_io_threads,
504- SRV_MAX_N_PENDING_SYNC_IOS);
505-
506- fil_init(srv_max_n_open_files);
507-#else
508- srv_n_file_io_threads = 2 + srv_n_read_io_threads + srv_n_write_io_threads;
509-
510- os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD,
511- srv_n_read_io_threads,
512- srv_n_write_io_threads,
513- SRV_MAX_N_PENDING_SYNC_IOS);
514-
515- fil_init(srv_file_per_table ? 50000 : 5000,
516- srv_max_n_open_files);
517-#endif
518-
519- fsp_init();
520+ err = xb_data_files_init();
521+ if (err != DB_SUCCESS) {
522+ msg("xtrabackup: error: xb_data_files_init() failed with"
523+ "error code %lu\n", err);
524+ exit(EXIT_FAILURE);
525+ }
526+
527 log_init();
528
529 lock_sys_create(srv_lock_table_size);
530
531- for (i = 0; i < srv_n_file_io_threads; i++) {
532- thread_nr[i] = i;
533-
534- os_thread_create(io_handler_thread, thread_nr + i, thread_ids + i);
535- }
536-
537- os_thread_sleep(200000); /*0.2 sec*/
538-
539- err = open_or_create_data_files(&create_new_db,
540-#ifdef XTRADB_BASED
541- &create_new_doublewrite_file,
542-#endif
543- &min_flushed_lsn, &max_flushed_lsn,
544- &sum_of_new_sizes);
545- if (err != DB_SUCCESS) {
546- msg(
547-"xtrabackup: Could not open or create data files.\n"
548-"xtrabackup: If you tried to add new data files, and it failed here,\n"
549-"xtrabackup: you should now edit innodb_data_file_path in my.cnf back\n"
550-"xtrabackup: to what it was, and remove the new ibdata files InnoDB created\n"
551-"xtrabackup: in this failed attempt. InnoDB only wrote those files full of\n"
552-"xtrabackup: zeros, but did not yet use them in any way. But be careful: do not\n"
553-"xtrabackup: remove old data files which contain your precious data!\n");
554-
555- //return((int) err);
556- exit(EXIT_FAILURE);
557- }
558-
559- /* create_new_db must not be TRUE.. */
560- if (create_new_db) {
561- msg("xtrabackup: Something wrong with source files...\n");
562- exit(EXIT_FAILURE);
563- }
564-
565 for (i = 0; i < srv_n_log_files; i++) {
566- err = open_or_create_log_file(create_new_db, &log_file_created,
567+ err = open_or_create_log_file(FALSE, &log_file_created,
568 log_opened, 0, i);
569 if (err != DB_SUCCESS) {
570
571@@ -2509,8 +2587,7 @@
572 } else {
573 log_opened = TRUE;
574 }
575- if ((log_opened && create_new_db)
576- || (log_opened && log_created)) {
577+ if ((log_opened && log_created)) {
578 msg(
579 "xtrabackup: Error: all log files must be created at the same time.\n"
580 "xtrabackup: All log files must be created also in database creation.\n"
581@@ -2830,6 +2907,8 @@
582 msg("xtrabackup: Transaction log of lsn (%llu) to (%llu) was copied.\n",
583 checkpoint_lsn_start, log_copy_scanned_lsn);
584 #endif
585+
586+ xb_data_files_close();
587 }
588
589 /* ================= stats ================= */
590@@ -3717,6 +3796,155 @@
591 return TRUE;
592 }
593
594+
595+/***********************************************************************
596+Searches for matching tablespace file for given .delta file and space_id
597+in given directory. When matching tablespace found, renames it to match the
598+name of .delta file. If there was a tablespace with matching name and
599+mismatching ID, renames it to xtrabackup_tmp_#ID.ibd. If there was no
600+matching file, creates the new one.
601+@return file handle of matched or created file */
602+static
603+os_file_t
604+xb_delta_open_matching_space(
605+ const char* dbname, /* in: path to destination database dir */
606+ const char* name, /* in: name of delta file (without .delta) */
607+ ulint space_id, /* in: space id of delta file */
608+ ulint zip_size, /* in: zip_size of tablespace */
609+ char* real_name, /* out: full path of destination file */
610+ size_t real_name_len, /* out: buffer size for real_name */
611+ ibool* success) /* out: indicates error. TRUE = success */
612+{
613+ char dest_dir[FN_REFLEN];
614+ char dest_space_name[FN_REFLEN];
615+ ibool ok;
616+ fil_space_t* fil_space;
617+ os_file_t file = 0;
618+
619+ ut_a(dbname || space_id == 0);
620+
621+ *success = FALSE;
622+
623+ if (dbname) {
624+ snprintf(dest_dir, FN_REFLEN, "%s/%s",
625+ xtrabackup_target_dir, dbname);
626+ srv_normalize_path_for_win(dest_dir);
627+
628+ snprintf(dest_space_name, FN_REFLEN, "./%s/%s",
629+ dbname, name);
630+ } else {
631+ snprintf(dest_dir, FN_REFLEN, "%s", xtrabackup_target_dir);
632+ srv_normalize_path_for_win(dest_dir);
633+
634+ snprintf(dest_space_name, FN_REFLEN, "./%s", name);
635+ }
636+
637+ snprintf(real_name, real_name_len,
638+ "%s/%s",
639+ xtrabackup_target_dir, dest_space_name);
640+ srv_normalize_path_for_win(real_name);
641+
642+ /* Create the database directory if it doesn't exist yet */
643+ if (!os_file_create_directory(dest_dir, FALSE)) {
644+ msg("xtrabackup: error: cannot create dir %s\n", dest_dir);
645+ return file;
646+ }
647+
648+ mutex_enter(&fil_system->mutex);
649+ fil_space = xb_space_get_by_name(dest_space_name);
650+ mutex_exit(&fil_system->mutex);
651+
652+ if (fil_space != NULL) {
653+ if (fil_space->id == space_id) {
654+ /* we found matching space */
655+ goto found;
656+ } else {
657+
658+ char tmpname[FN_REFLEN];
659+
660+ snprintf(tmpname, FN_REFLEN, "./%s/xtrabackup_tmp_#%lu",
661+ dbname, fil_space->id);
662+
663+ msg("xtrabackup: Renaming %s to %s.ibd\n",
664+ fil_space->name, tmpname);
665+
666+ if (!fil_rename_tablespace(NULL,
667+ fil_space->id, tmpname))
668+ {
669+ msg("xtrabackup: Cannot rename %s to %s\n",
670+ fil_space->name, tmpname);
671+ goto exit;
672+ }
673+ }
674+ }
675+
676+ mutex_enter(&fil_system->mutex);
677+ fil_space = xb_space_get_by_id(space_id);
678+ mutex_exit(&fil_system->mutex);
679+ if (fil_space != NULL) {
680+ char tmpname[FN_REFLEN];
681+
682+ strncpy(tmpname, dest_space_name, FN_REFLEN);
683+ tmpname[strlen(tmpname) - 4] = 0;
684+
685+ msg("xtrabackup: Renaming %s to %s\n",
686+ fil_space->name, dest_space_name);
687+
688+ if (!fil_rename_tablespace(NULL,
689+ fil_space->id, tmpname))
690+ {
691+ msg("xtrabackup: Cannot rename %s to %s\n",
692+ fil_space->name, dest_space_name);
693+ goto exit;
694+ }
695+
696+ goto found;
697+ }
698+
699+ /* no matching space found. create the new one */
700+
701+#ifdef INNODB_VERSION_SHORT
702+ if (!fil_space_create(dest_space_name, space_id,
703+ zip_size, FIL_TABLESPACE)) {
704+#else
705+ if (!fil_space_create(dest_space_name, space_id,
706+ FIL_TABLESPACE)) {
707+#endif
708+ msg("xtrabackup: Cannot create tablespace %s\n",
709+ dest_space_name);
710+ goto exit;
711+ }
712+
713+ file = xb_file_create_no_error_handling(real_name, OS_FILE_CREATE,
714+ OS_FILE_READ_WRITE,
715+ &ok);
716+
717+ if (ok) {
718+ *success = TRUE;
719+ } else {
720+ msg("xtrabackup: Cannot open file %s\n", real_name);
721+ }
722+
723+ goto exit;
724+
725+found:
726+ /* open the file and return it's handle */
727+
728+ file = xb_file_create_no_error_handling(real_name, OS_FILE_OPEN,
729+ OS_FILE_READ_WRITE,
730+ &ok);
731+
732+ if (ok) {
733+ *success = TRUE;
734+ } else {
735+ msg("xtrabackup: Cannot open file %s\n", real_name);
736+ }
737+
738+exit:
739+
740+ return file;
741+}
742+
743 /************************************************************************
744 Applies a given .delta file to the corresponding data file.
745 @return TRUE on success */
746@@ -3734,6 +3962,7 @@
747 char src_path[FN_REFLEN];
748 char dst_path[FN_REFLEN];
749 char meta_path[FN_REFLEN];
750+ char space_name[FN_REFLEN];
751 ibool success;
752
753 ibool last_buffer = FALSE;
754@@ -3761,6 +3990,9 @@
755 }
756 dst_path[strlen(dst_path) - 6] = '\0';
757
758+ strncpy(space_name, filename, FN_REFLEN);
759+ space_name[strlen(space_name) - 6] = 0;
760+
761 if (!get_meta_path(src_path, meta_path)) {
762 goto error;
763 }
764@@ -3798,36 +4030,11 @@
765
766 xb_file_set_nocache(src_file, src_path, "OPEN");
767
768- dst_file = xb_file_create_no_error_handling(dst_path, OS_FILE_OPEN,
769- OS_FILE_READ_WRITE,
770- &success);
771-again:
772+ dst_file = xb_delta_open_matching_space(
773+ dbname, space_name, info.space_id,
774+ info.page_size == UNIV_PAGE_SIZE ? 0 : info.page_size,
775+ dst_path, sizeof(dst_path), &success);
776 if (!success) {
777- ulint errcode = os_file_get_last_error(TRUE);
778-
779- if (errcode == OS_FILE_NOT_FOUND) {
780- msg("xtrabackup: target data file %s "
781- "is not found, creating a new one\n", dst_path);
782- /* Create the database directory if it doesn't exist yet
783- */
784- if (dbname) {
785- char dst_dir[FN_REFLEN];
786-
787- snprintf(dst_dir, sizeof(dst_dir), "%s/%s",
788- xtrabackup_real_target_dir, dbname);
789- srv_normalize_path_for_win(dst_dir);
790-
791- if (!os_file_create_directory(dst_dir, FALSE))
792- goto error;
793- }
794- dst_file =
795- xb_file_create_no_error_handling(dst_path,
796- OS_FILE_CREATE,
797- OS_FILE_READ_WRITE,
798- &success);
799- goto again;
800- }
801-
802 msg("xtrabackup: error: cannot open %s\n", dst_path);
803 goto error;
804 }
805@@ -3842,7 +4049,7 @@
806 incremental_buffer = ut_align(incremental_buffer_base,
807 UNIV_PAGE_SIZE_MAX);
808
809- msg("Applying %s ...\n", src_path);
810+ msg("Applying %s to %s...\n", src_path, dst_path);
811
812 while (!last_buffer) {
813 ulint cluster_header;
814@@ -4150,6 +4357,8 @@
815 static void
816 xtrabackup_prepare_func(void)
817 {
818+ ulint err;
819+
820 /* cd to target-dir */
821
822 if (my_setwd(xtrabackup_real_target_dir,MYF(MY_WME)))
823@@ -4220,12 +4429,29 @@
824 if(xtrabackup_init_temp_log())
825 goto error;
826
827- if(xtrabackup_incremental && !xtrabackup_apply_deltas(TRUE))
828+ if(innodb_init_param())
829 goto error;
830
831+ mem_init(srv_mem_pool_size);
832+ if (xtrabackup_incremental) {
833+ err = xb_data_files_init();
834+ if (err != DB_SUCCESS) {
835+ msg("xtrabackup: error: xb_data_files_init() failed with"
836+ "error code %lu\n", err);
837+ goto error;
838+ }
839+
840+ if(!xtrabackup_apply_deltas(TRUE)) {
841+ xb_data_files_close();
842+ goto error;
843+ }
844+
845+ xb_data_files_close();
846+ }
847 sync_close();
848 sync_initialized = FALSE;
849 os_sync_free();
850+ mem_close();
851 os_sync_mutex = NULL;
852 ut_free_all_mem();
853
854
855=== modified file 'src/xtrabackup.h'
856--- src/xtrabackup.h 2012-05-28 16:49:14 +0000
857+++ src/xtrabackup.h 2012-07-11 09:06:21 +0000
858@@ -23,6 +23,7 @@
859
860 typedef struct {
861 ulint page_size;
862+ ulint space_id;
863 } xb_delta_info_t;
864
865 typedef enum {
866
867=== added file 'test/t/bug932623.sh'
868--- test/t/bug932623.sh 1970-01-01 00:00:00 +0000
869+++ test/t/bug932623.sh 2012-07-11 09:06:21 +0000
870@@ -0,0 +1,85 @@
871+########################################################################
872+# Bug #932623: RENAME TABLE causes incremental prepare to fail
873+########################################################################
874+
875+. inc/common.sh
876+
877+start_server --innodb_file_per_table
878+
879+run_cmd $MYSQL $MYSQL_ARGS test <<EOF
880+CREATE TABLE t1_old(a INT) ENGINE=InnoDB;
881+INSERT INTO t1_old VALUES (1), (2), (3);
882+
883+CREATE TABLE t1(a INT) ENGINE=InnoDB;
884+INSERT INTO t1 VALUES (4), (5), (6);
885+EOF
886+
887+# Full backup
888+# backup root directory
889+vlog "Starting backup"
890+innobackupex --no-timestamp $topdir/full
891+
892+vlog "Rotating the table"
893+
894+run_cmd $MYSQL $MYSQL_ARGS test <<EOF
895+CREATE TABLE t1_new(a int) ENGINE=InnoDB;
896+INSERT INTO t1_new VALUES (7), (8), (9);
897+
898+CREATE DATABASE db2;
899+RENAME TABLE t1_old TO db2.t1;
900+
901+RENAME TABLE t1 TO t1_old;
902+RENAME TABLE t1_new TO t1;
903+
904+INSERT INTO t1_old VALUES (10), (11), (12);
905+INSERT INTO t1 VALUES (13), (14), (15);
906+
907+EOF
908+
909+vlog "Creating incremental backup"
910+
911+innobackupex --incremental --no-timestamp \
912+ --incremental-basedir=$topdir/full $topdir/inc
913+
914+vlog "Preparing backup"
915+
916+innobackupex --apply-log --redo-only $topdir/full
917+vlog "Log applied to full backup"
918+
919+innobackupex --apply-log --redo-only --incremental-dir=$topdir/inc \
920+ $topdir/full
921+vlog "Delta applied to full backup"
922+
923+innobackupex --apply-log $topdir/full
924+vlog "Data prepared for restore"
925+
926+checksum_t1_a=`checksum_table test t1`
927+checksum_t1_old_a=`checksum_table test t1_old`
928+checksum_t1_db2_a=`checksum_table db2 t1`
929+
930+# Destroying mysql data
931+stop_server
932+rm -rf $mysql_datadir/*
933+vlog "Data destroyed"
934+
935+# Restore backup
936+vlog "Copying files"
937+
938+innobackupex --copy-back $topdir/full
939+vlog "Data restored"
940+
941+start_server --innodb_file_per_table
942+
943+vlog "Checking checksums"
944+checksum_t1_b=`checksum_table test t1`
945+checksum_t1_old_b=`checksum_table test t1_old`
946+checksum_t1_db2_b=`checksum_table db2 t1`
947+
948+if [ "$checksum_t1_a" != "$checksum_t1_b" -o "$checksum_t1_old_a" != "$checksum_t1_old_b" \
949+ -o "$checksum_t1_db2_a" != "$checksum_t1_db2_b" ]
950+then
951+ vlog "Checksums do not match"
952+ exit -1
953+fi
954+
955+vlog "Checksums are OK"

Subscribers

People subscribed via source and target branches