Merge lp:~laurynas-biveinis/percona-xtrabackup/bug1028949-2.0 into lp:percona-xtrabackup/2.0

Proposed by Laurynas Biveinis
Status: Merged
Approved by: Stewart Smith
Approved revision: no longer in the source branch.
Merged at revision: 454
Proposed branch: lp:~laurynas-biveinis/percona-xtrabackup/bug1028949-2.0
Merge into: lp:percona-xtrabackup/2.0
Prerequisite: lp:~laurynas-biveinis/percona-xtrabackup/bug1022562-2.0
Diff against target: 1160 lines (+818/-115)
5 files modified
patches/innodb51_builtin.patch (+67/-4)
src/xtrabackup.c (+463/-111)
test/t/bug1022562.sh (+93/-0)
test/t/bug1028949.sh (+110/-0)
test/t/bug932623.sh (+85/-0)
To merge this branch: bzr merge lp:~laurynas-biveinis/percona-xtrabackup/bug1028949-2.0
Reviewer Review Type Date Requested Status
Percona core Pending
Review via email: mp+117381@code.launchpad.net

Description of the change

Fix bug 1028949 (Assertion error in creating a compressed tablespace
at delta apply time).

The issue was incorrect tablespace flags parameter for the
fil_space_create() call: it passed the compressed page size itself,
which would only happen to work with uncompressed tablespaces.

Fixed by calculating and passing the flags for a given compressed page
size.

Added a testcase.

Jenkins the best managed I to get (includes follow-up changes too): http://jenkins.percona.com/job/percona-xtrabackup-2.0-param/236/

Issue #16274.

To post a comment you must log in.

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-08-01 10:28: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/xtrabackup.c'
119--- src/xtrabackup.c 2012-06-20 07:36:26 +0000
120+++ src/xtrabackup.c 2012-08-01 10:28:21 +0000
121@@ -655,10 +655,107 @@
122
123 typedef struct {
124 ulint page_size;
125+ ulint space_id;
126 } xb_delta_info_t;
127
128 extern fil_system_t* fil_system;
129
130+/** Value of fil_space_struct::magic_n */
131+#define FIL_SPACE_MAGIC_N 89472
132+
133+/*******************************************************************//**
134+Returns the table space by a given id, NULL if not found. */
135+fil_space_t*
136+xb_space_get_by_id(
137+/*================*/
138+ ulint id); /*!< in: space id */
139+
140+/*******************************************************************//**
141+Returns the table space by a given name, NULL if not found. */
142+fil_space_t*
143+xb_space_get_by_name(
144+/*==================*/
145+ const char* name); /*!< in: space name */
146+
147+/*******************************************************************//**
148+Returns the table space by a given id, NULL if not found. */
149+fil_space_t*
150+xb_space_get_by_id(
151+/*================*/
152+ ulint id) /*!< in: space id */
153+{
154+ fil_space_t* space;
155+
156+ ut_ad(mutex_own(&fil_system->mutex));
157+
158+#ifdef INNODB_VERSION_SHORT
159+ HASH_SEARCH(hash, fil_system->spaces, id,
160+ fil_space_t*, space,
161+ ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
162+ space->id == id);
163+#else
164+ HASH_SEARCH(hash, fil_system->spaces, id, space, space->id == id);
165+#endif
166+
167+ return(space);
168+}
169+
170+/*******************************************************************//**
171+Returns the table space by a given name, NULL if not found. */
172+fil_space_t*
173+xb_space_get_by_name(
174+/*==================*/
175+ const char* name) /*!< in: space name */
176+{
177+ fil_space_t* space;
178+ ulint fold;
179+
180+ ut_ad(mutex_own(&fil_system->mutex));
181+
182+#ifdef INNODB_VERSION_SHORT
183+ fold = ut_fold_string(name);
184+ HASH_SEARCH(name_hash, fil_system->name_hash, fold,
185+ fil_space_t*, space,
186+ ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
187+ !strcmp(name, space->name));
188+#else
189+ HASH_SEARCH(name_hash, fil_system->name_hash, ut_fold_string(name),
190+ space, 0 == strcmp(name, space->name));
191+#endif
192+
193+ return(space);
194+}
195+
196+#ifndef INNODB_VERSION_SHORT
197+
198+/*******************************************************************//**
199+Free all spaces in space_list. */
200+void
201+fil_free_all_spaces(void)
202+/*=====================*/
203+{
204+ fil_space_t* space;
205+
206+ mutex_enter(&fil_system->mutex);
207+
208+ space = UT_LIST_GET_FIRST(fil_system->space_list);
209+
210+ while (space != NULL) {
211+ fil_node_t* node;
212+ fil_space_t* prev_space = space;
213+
214+ space = UT_LIST_GET_NEXT(space_list, space);
215+
216+ fil_space_free(prev_space->id, FALSE);
217+ }
218+
219+ mutex_exit(&fil_system->mutex);
220+}
221+
222+#define SRV_SHUTDOWN_NONE 0
223+
224+#endif
225+
226 /* ==end=== definition at fil0fil.c === */
227
228
229@@ -2752,7 +2849,8 @@
230 return(TRUE);
231 }
232
233- if (fscanf(fp, "page_size = %lu\n", &info->page_size) != 1)
234+ if (fscanf(fp, "page_size = %lu\nspace_id = %lu\n",
235+ &info->page_size, &info->space_id) != 2)
236 r= FALSE;
237
238 fclose(fp);
239@@ -2770,14 +2868,16 @@
240 {
241 datasink_t *ds = ds_ctxt->datasink;
242 ds_file_t *f;
243- char buf[32];
244+ char buf[64];
245 my_bool ret;
246 size_t len;
247 MY_STAT mystat;
248
249- snprintf(buf, sizeof(buf), "page_size = %lu\n", info->page_size);
250-
251+ snprintf(buf, sizeof(buf),
252+ "page_size = %lu\nspace_id = %lu\n",
253+ info->page_size, info->space_id);
254 len = strlen(buf);
255+
256 mystat.st_size = len;
257 mystat.st_mtime = my_time(0);
258
259@@ -2981,6 +3081,7 @@
260 ds_file_t *dstfile = NULL;
261
262 info.page_size = 0;
263+ info.space_id = 0;
264
265 #ifdef XTRADB_BASED
266 if (xtrabackup_tables && (!trx_sys_sys_space(node->space->id)))
267@@ -3163,6 +3264,7 @@
268 page_in_buffer++;
269
270 info.page_size = page_size;
271+ info.space_id = node->space->id;
272 } else
273 info.page_size = 0;
274
275@@ -3286,9 +3388,18 @@
276 if (xtrabackup_incremental) {
277 for (chunk_offset = 0; chunk_offset < chunk; chunk_offset += page_size) {
278 /* newer page */
279- /* This condition may be OK for header, ibuf and fsp */
280+ /* This condition may be OK for header, ibuf and fsp
281+ We always copy the 1st
282+ FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE
283+ bytes of any tablespace, regardless of the LSNs
284+ of the pages there. These pages are guaranteed
285+ to be flushed upon tablespace create and they
286+ are required for InnoDB to recognize the
287+ tablespace. */
288 if (ut_dulint_cmp(incremental_lsn,
289- MACH_READ_64(page + chunk_offset + FIL_PAGE_LSN)) < 0) {
290+ MACH_READ_64(page + chunk_offset + FIL_PAGE_LSN)) < 0
291+ || (offset + chunk_offset
292+ < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE)) {
293 /* ========================================= */
294 IB_INT64 offset_on_page;
295
296@@ -3722,11 +3833,10 @@
297 void* arg)
298 {
299 ulint segment;
300- ulint i;
301
302 segment = *((ulint*)arg);
303
304- for (i = 0;; i++) {
305+ while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) {
306 fil_aio_wait(segment);
307 }
308
309@@ -3744,6 +3854,141 @@
310 #endif
311 }
312
313+#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD
314+#define SRV_MAX_N_PENDING_SYNC_IOS 100
315+
316+/************************************************************************
317+Initialize the tablespace memory cache and populate it by scanning for and
318+opening data files.
319+@returns DB_SUCCESS or error code.*/
320+ulint
321+xb_data_files_init(void)
322+/*====================*/
323+{
324+ ulint i;
325+ ibool create_new_db;
326+#ifdef XTRADB_BASED
327+ ibool create_new_doublewrite_file;
328+#endif
329+ ulint err;
330+ LSN64 min_flushed_lsn;
331+ LSN64 max_flushed_lsn;
332+ ulint sum_of_new_sizes;
333+
334+#ifndef INNODB_VERSION_SHORT
335+ os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD
336+ * srv_n_file_io_threads,
337+ srv_n_file_io_threads,
338+ SRV_MAX_N_PENDING_SYNC_IOS);
339+
340+ fil_init(srv_max_n_open_files);
341+#else
342+ srv_n_file_io_threads = 2 + srv_n_read_io_threads +
343+ srv_n_write_io_threads;
344+
345+ os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD,
346+ srv_n_read_io_threads,
347+ srv_n_write_io_threads,
348+ SRV_MAX_N_PENDING_SYNC_IOS);
349+
350+ fil_init(srv_file_per_table ? 50000 : 5000,
351+ srv_max_n_open_files);
352+#endif
353+
354+ fsp_init();
355+
356+ for (i = 0; i < srv_n_file_io_threads; i++) {
357+ thread_nr[i] = i;
358+
359+ os_thread_create(io_handler_thread, thread_nr + i,
360+ thread_ids + i);
361+ }
362+
363+ os_thread_sleep(200000); /*0.2 sec*/
364+
365+ err = open_or_create_data_files(&create_new_db,
366+#ifdef XTRADB_BASED
367+ &create_new_doublewrite_file,
368+#endif
369+ &min_flushed_lsn, &max_flushed_lsn,
370+ &sum_of_new_sizes);
371+ if (err != DB_SUCCESS) {
372+ msg("xtrabackup: Could not open or create data files.\n"
373+ "xtrabackup: If you tried to add new data files, and it "
374+ "failed here,\n"
375+ "xtrabackup: you should now edit innodb_data_file_path in "
376+ "my.cnf back\n"
377+ "xtrabackup: to what it was, and remove the new ibdata "
378+ "files InnoDB created\n"
379+ "xtrabackup: in this failed attempt. InnoDB only wrote "
380+ "those files full of\n"
381+ "xtrabackup: zeros, but did not yet use them in any way. "
382+ "But be careful: do not\n"
383+ "xtrabackup: remove old data files which contain your "
384+ "precious data!\n");
385+ return(err);
386+ }
387+
388+ /* create_new_db must not be TRUE.. */
389+ if (create_new_db) {
390+ msg("xtrabackup: could not find data files at the "
391+ "specified datadir\n");
392+ return(DB_ERROR);
393+ }
394+
395+ return(fil_load_single_table_tablespaces());
396+}
397+
398+/************************************************************************
399+Destroy the tablespace memory cache. */
400+void
401+xb_data_files_close(void)
402+/*====================*/
403+{
404+ ulint i;
405+
406+ /* Shutdown the aio threads. This has been copied from
407+ innobase_shutdown_for_mysql(). */
408+
409+ srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
410+
411+ for (i = 0; i < 1000; i++) {
412+ os_aio_wake_all_threads_at_shutdown();
413+
414+ os_mutex_enter(os_sync_mutex);
415+
416+ if (os_thread_count == 0) {
417+
418+ os_mutex_exit(os_sync_mutex);
419+
420+ os_thread_sleep(10000);
421+
422+ break;
423+ }
424+
425+ os_mutex_exit(os_sync_mutex);
426+
427+ os_thread_sleep(10000);
428+ }
429+
430+ if (i == 1000) {
431+ msg("xtrabackup: Warning: %lu threads created by InnoDB"
432+ " had not exited at shutdown!\n",
433+ (ulong) os_thread_count);
434+ }
435+
436+#ifdef INNODB_VERSION_SHORT
437+ os_aio_free();
438+#endif
439+ fil_close_all_files();
440+#ifndef INNODB_VERSION_SHORT
441+ fil_free_all_spaces();
442+#endif
443+ fil_system = NULL;
444+
445+ srv_shutdown_state = SRV_SHUTDOWN_NONE;
446+}
447+
448 /***************************************************************************
449 Creates an output directory for a given tablespace, if it does not exist */
450 static
451@@ -4050,85 +4295,25 @@
452 srv_general_init();
453
454 {
455- ibool create_new_db;
456-#ifdef XTRADB_BASED
457- ibool create_new_doublewrite_file;
458-#endif
459 ibool log_file_created;
460 ibool log_created = FALSE;
461 ibool log_opened = FALSE;
462- LSN64 min_flushed_lsn;
463- LSN64 max_flushed_lsn;
464- ulint sum_of_new_sizes;
465 ulint err;
466 ulint i;
467
468-
469-
470-
471-#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD
472-#define SRV_MAX_N_PENDING_SYNC_IOS 100
473-
474-#ifndef INNODB_VERSION_SHORT
475- os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD
476- * srv_n_file_io_threads,
477- srv_n_file_io_threads,
478- SRV_MAX_N_PENDING_SYNC_IOS);
479-
480- fil_init(srv_max_n_open_files);
481-#else
482- srv_n_file_io_threads = 2 + srv_n_read_io_threads + srv_n_write_io_threads;
483-
484- os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD,
485- srv_n_read_io_threads,
486- srv_n_write_io_threads,
487- SRV_MAX_N_PENDING_SYNC_IOS);
488-
489- fil_init(srv_file_per_table ? 50000 : 5000,
490- srv_max_n_open_files);
491-#endif
492-
493- fsp_init();
494+ err = xb_data_files_init();
495+ if (err != DB_SUCCESS) {
496+ msg("xtrabackup: error: xb_data_files_init() failed with"
497+ "error code %lu\n", err);
498+ exit(EXIT_FAILURE);
499+ }
500+
501 log_init();
502
503 lock_sys_create(srv_lock_table_size);
504
505- for (i = 0; i < srv_n_file_io_threads; i++) {
506- thread_nr[i] = i;
507-
508- os_thread_create(io_handler_thread, thread_nr + i, thread_ids + i);
509- }
510-
511- os_thread_sleep(200000); /*0.2 sec*/
512-
513- err = open_or_create_data_files(&create_new_db,
514-#ifdef XTRADB_BASED
515- &create_new_doublewrite_file,
516-#endif
517- &min_flushed_lsn, &max_flushed_lsn,
518- &sum_of_new_sizes);
519- if (err != DB_SUCCESS) {
520- msg(
521-"xtrabackup: Could not open or create data files.\n"
522-"xtrabackup: If you tried to add new data files, and it failed here,\n"
523-"xtrabackup: you should now edit innodb_data_file_path in my.cnf back\n"
524-"xtrabackup: to what it was, and remove the new ibdata files InnoDB created\n"
525-"xtrabackup: in this failed attempt. InnoDB only wrote those files full of\n"
526-"xtrabackup: zeros, but did not yet use them in any way. But be careful: do not\n"
527-"xtrabackup: remove old data files which contain your precious data!\n");
528-
529- //return((int) err);
530- exit(EXIT_FAILURE);
531- }
532-
533- /* create_new_db must not be TRUE.. */
534- if (create_new_db) {
535- msg("xtrabackup: Something wrong with source files...\n");
536- exit(EXIT_FAILURE);
537- }
538-
539 for (i = 0; i < srv_n_log_files; i++) {
540- err = open_or_create_log_file(create_new_db, &log_file_created,
541+ err = open_or_create_log_file(FALSE, &log_file_created,
542 log_opened, 0, i);
543 if (err != DB_SUCCESS) {
544
545@@ -4141,8 +4326,7 @@
546 } else {
547 log_opened = TRUE;
548 }
549- if ((log_opened && create_new_db)
550- || (log_opened && log_created)) {
551+ if ((log_opened && log_created)) {
552 msg(
553 "xtrabackup: Error: all log files must be created at the same time.\n"
554 "xtrabackup: All log files must be created also in database creation.\n"
555@@ -4162,8 +4346,6 @@
556 exit(EXIT_FAILURE);
557 }
558
559- fil_load_single_table_tablespaces();
560-
561 }
562
563 /* create extra LSN dir if it does not exist. */
564@@ -4545,6 +4727,8 @@
565 msg("xtrabackup: Transaction log of lsn (%llu) to (%llu) was copied.\n",
566 checkpoint_lsn_start, log_copy_scanned_lsn);
567 #endif
568+
569+ xb_data_files_close();
570 }
571
572 /* ================= stats ================= */
573@@ -5434,6 +5618,176 @@
574 return TRUE;
575 }
576
577+/***********************************************************************
578+Searches for matching tablespace file for given .delta file and space_id
579+in given directory. When matching tablespace found, renames it to match the
580+name of .delta file. If there was a tablespace with matching name and
581+mismatching ID, renames it to xtrabackup_tmp_#ID.ibd. If there was no
582+matching file, creates a placeholder for the new tablespace.
583+@return file handle of matched or created file */
584+static
585+os_file_t
586+xb_delta_open_matching_space(
587+ const char* dbname, /* in: path to destination database dir */
588+ const char* name, /* in: name of delta file (without .delta) */
589+ ulint space_id, /* in: space id of delta file */
590+ ulint zip_size, /* in: zip_size of tablespace */
591+ char* real_name, /* out: full path of destination file */
592+ size_t real_name_len, /* out: buffer size for real_name */
593+ ibool* success) /* out: indicates error. TRUE = success */
594+{
595+ char dest_dir[FN_REFLEN];
596+ char dest_space_name[FN_REFLEN];
597+ ibool ok;
598+ fil_space_t* fil_space;
599+ os_file_t file = 0;
600+ ulint tablespace_flags;
601+
602+ ut_a(dbname || space_id == 0);
603+
604+ *success = FALSE;
605+
606+ if (dbname) {
607+ snprintf(dest_dir, FN_REFLEN, "%s/%s",
608+ xtrabackup_target_dir, dbname);
609+ srv_normalize_path_for_win(dest_dir);
610+
611+ snprintf(dest_space_name, FN_REFLEN, "./%s/%s",
612+ dbname, name);
613+ } else {
614+ snprintf(dest_dir, FN_REFLEN, "%s", xtrabackup_target_dir);
615+ srv_normalize_path_for_win(dest_dir);
616+
617+ snprintf(dest_space_name, FN_REFLEN, "./%s", name);
618+ }
619+
620+ snprintf(real_name, real_name_len,
621+ "%s/%s",
622+ xtrabackup_target_dir, dest_space_name);
623+ srv_normalize_path_for_win(real_name);
624+
625+ /* Create the database directory if it doesn't exist yet */
626+ if (!os_file_create_directory(dest_dir, FALSE)) {
627+ msg("xtrabackup: error: cannot create dir %s\n", dest_dir);
628+ return file;
629+ }
630+
631+ mutex_enter(&fil_system->mutex);
632+ fil_space = xb_space_get_by_name(dest_space_name);
633+ mutex_exit(&fil_system->mutex);
634+
635+ if (fil_space != NULL) {
636+ if (fil_space->id == space_id) {
637+ /* we found matching space */
638+ goto found;
639+ } else {
640+
641+ char tmpname[FN_REFLEN];
642+
643+ snprintf(tmpname, FN_REFLEN, "./%s/xtrabackup_tmp_#%lu",
644+ dbname, fil_space->id);
645+
646+ msg("xtrabackup: Renaming %s to %s.ibd\n",
647+ fil_space->name, tmpname);
648+
649+ if (!fil_rename_tablespace(NULL,
650+ fil_space->id, tmpname))
651+ {
652+ msg("xtrabackup: Cannot rename %s to %s\n",
653+ fil_space->name, tmpname);
654+ goto exit;
655+ }
656+ }
657+ }
658+
659+ mutex_enter(&fil_system->mutex);
660+ fil_space = xb_space_get_by_id(space_id);
661+ mutex_exit(&fil_system->mutex);
662+ if (fil_space != NULL) {
663+ char tmpname[FN_REFLEN];
664+
665+ strncpy(tmpname, dest_space_name, FN_REFLEN);
666+ tmpname[strlen(tmpname) - 4] = 0;
667+
668+ msg("xtrabackup: Renaming %s to %s\n",
669+ fil_space->name, dest_space_name);
670+
671+ if (!fil_rename_tablespace(NULL,
672+ fil_space->id, tmpname))
673+ {
674+ msg("xtrabackup: Cannot rename %s to %s\n",
675+ fil_space->name, dest_space_name);
676+ goto exit;
677+ }
678+
679+ goto found;
680+ }
681+
682+ /* No matching space found. create the new one. Note that this is not
683+ a full-fledged tablespace create, as done by
684+ fil_create_new_single_table_tablespace(): the minumum tablespace size
685+ is not ensured and the 1st page fields are not set. We rely on backup
686+ delta to contain the 1st FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE
687+ to ensure the correct tablespace image. */
688+
689+#ifdef INNODB_VERSION_SHORT
690+ /* Calculate correct tablespace flags for compressed tablespaces. Do
691+ not bother to set all flags correctly, just enough for
692+ fil_space_create() to work. The full flags will be restored from the
693+ delta later. */
694+ if (!zip_size) {
695+ tablespace_flags = 0;
696+ }
697+ else {
698+ tablespace_flags
699+ = (get_bit_shift(zip_size >> PAGE_ZIP_MIN_SIZE_SHIFT
700+ << 1)
701+ << DICT_TF_ZSSIZE_SHIFT)
702+ | DICT_TF_COMPACT
703+ | (DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT);
704+ }
705+ ut_a(dict_table_flags_to_zip_size(tablespace_flags) == zip_size);
706+ if (!fil_space_create(dest_space_name, space_id, tablespace_flags,
707+ FIL_TABLESPACE)) {
708+#else
709+ if (!fil_space_create(dest_space_name, space_id,
710+ FIL_TABLESPACE)) {
711+#endif
712+ msg("xtrabackup: Cannot create tablespace %s\n",
713+ dest_space_name);
714+ goto exit;
715+ }
716+
717+ file = xb_file_create_no_error_handling(real_name, OS_FILE_CREATE,
718+ OS_FILE_READ_WRITE,
719+ &ok);
720+
721+ if (ok) {
722+ *success = TRUE;
723+ } else {
724+ msg("xtrabackup: Cannot open file %s\n", real_name);
725+ }
726+
727+ goto exit;
728+
729+found:
730+ /* open the file and return it's handle */
731+
732+ file = xb_file_create_no_error_handling(real_name, OS_FILE_OPEN,
733+ OS_FILE_READ_WRITE,
734+ &ok);
735+
736+ if (ok) {
737+ *success = TRUE;
738+ } else {
739+ msg("xtrabackup: Cannot open file %s\n", real_name);
740+ }
741+
742+exit:
743+
744+ return file;
745+}
746+
747 /************************************************************************
748 Applies a given .delta file to the corresponding data file.
749 @return TRUE on success */
750@@ -5451,6 +5805,7 @@
751 char src_path[FN_REFLEN];
752 char dst_path[FN_REFLEN];
753 char meta_path[FN_REFLEN];
754+ char space_name[FN_REFLEN];
755 ibool success;
756
757 ibool last_buffer = FALSE;
758@@ -5478,6 +5833,9 @@
759 }
760 dst_path[strlen(dst_path) - 6] = '\0';
761
762+ strncpy(space_name, filename, FN_REFLEN);
763+ space_name[strlen(space_name) - 6] = 0;
764+
765 if (!get_meta_path(src_path, meta_path)) {
766 goto error;
767 }
768@@ -5517,36 +5875,11 @@
769
770 xb_file_set_nocache(src_file, src_path, "OPEN");
771
772- dst_file = xb_file_create_no_error_handling(dst_path, OS_FILE_OPEN,
773- OS_FILE_READ_WRITE,
774- &success);
775-again:
776+ dst_file = xb_delta_open_matching_space(
777+ dbname, space_name, info.space_id,
778+ info.page_size == UNIV_PAGE_SIZE ? 0 : info.page_size,
779+ dst_path, sizeof(dst_path), &success);
780 if (!success) {
781- ulint errcode = os_file_get_last_error(TRUE);
782-
783- if (errcode == OS_FILE_NOT_FOUND) {
784- msg("xtrabackup: target data file %s "
785- "is not found, creating a new one\n", dst_path);
786- /* Create the database directory if it doesn't exist yet
787- */
788- if (dbname) {
789- char dst_dir[FN_REFLEN];
790-
791- snprintf(dst_dir, sizeof(dst_dir), "%s/%s",
792- xtrabackup_real_target_dir, dbname);
793- srv_normalize_path_for_win(dst_dir);
794-
795- if (!os_file_create_directory(dst_dir, FALSE))
796- goto error;
797- }
798- dst_file =
799- xb_file_create_no_error_handling(dst_path,
800- OS_FILE_CREATE,
801- OS_FILE_READ_WRITE,
802- &success);
803- goto again;
804- }
805-
806 msg("xtrabackup: error: cannot open %s\n", dst_path);
807 goto error;
808 }
809@@ -5563,7 +5896,7 @@
810 incremental_buffer = ut_align(incremental_buffer_base,
811 UNIV_PAGE_SIZE_MAX);
812
813- msg("Applying %s ...\n", src_path);
814+ msg("Applying %s to %s...\n", src_path, dst_path);
815
816 while (!last_buffer) {
817 ulint cluster_header;
818@@ -5873,6 +6206,8 @@
819 static void
820 xtrabackup_prepare_func(void)
821 {
822+ ulint err;
823+
824 /* cd to target-dir */
825
826 if (my_setwd(xtrabackup_real_target_dir,MYF(MY_WME)))
827@@ -5943,12 +6278,29 @@
828 if(xtrabackup_init_temp_log())
829 goto error;
830
831- if(xtrabackup_incremental && !xtrabackup_apply_deltas(TRUE))
832+ if(innodb_init_param())
833 goto error;
834
835+ mem_init(srv_mem_pool_size);
836+ if (xtrabackup_incremental) {
837+ err = xb_data_files_init();
838+ if (err != DB_SUCCESS) {
839+ msg("xtrabackup: error: xb_data_files_init() failed with"
840+ "error code %lu\n", err);
841+ goto error;
842+ }
843+
844+ if(!xtrabackup_apply_deltas(TRUE)) {
845+ xb_data_files_close();
846+ goto error;
847+ }
848+
849+ xb_data_files_close();
850+ }
851 sync_close();
852 sync_initialized = FALSE;
853 os_sync_free();
854+ mem_close();
855 os_sync_mutex = NULL;
856 ut_free_all_mem();
857
858
859=== added file 'test/t/bug1022562.sh'
860--- test/t/bug1022562.sh 1970-01-01 00:00:00 +0000
861+++ test/t/bug1022562.sh 2012-08-01 10:28:21 +0000
862@@ -0,0 +1,93 @@
863+. inc/common.sh
864+
865+mysqld_additional_args="--innodb_file_per_table"
866+
867+start_server ${mysqld_additional_args}
868+
869+load_dbase_schema incremental_sample
870+
871+# Full backup
872+
873+# Full backup folder
874+rm -rf $topdir/data/full
875+mkdir -p $topdir/data/full
876+# Incremental data
877+rm -rf $topdir/data/delta
878+mkdir -p $topdir/data/delta
879+
880+vlog "Starting backup"
881+
882+xtrabackup --datadir=$mysql_datadir --backup --target-dir=$topdir/data/full \
883+ $mysqld_additional_args
884+
885+vlog "Full backup done"
886+
887+# Changing data in sakila
888+
889+vlog "Making changes to database"
890+
891+${MYSQL} ${MYSQL_ARGS} -e "CREATE TABLE t2 (a INT(11) DEFAULT NULL, \
892+ number INT(11) DEFAULT NULL) ENGINE=INNODB" incremental_sample
893+${MYSQL} ${MYSQL_ARGS} -e "INSERT INTO t2 VALUES (1, 1)" incremental_sample
894+
895+vlog "Changes done"
896+
897+# Saving the checksum of original table
898+checksum_t2_a=`checksum_table incremental_sample t2`
899+
900+vlog "Table 't2' checksum is $checksum_t2_a"
901+
902+vlog "Making incremental backup"
903+
904+# Incremental backup
905+xtrabackup --datadir=$mysql_datadir --backup \
906+ --target-dir=$topdir/data/delta --incremental-basedir=$topdir/data/full \
907+ $mysqld_additional_args
908+
909+vlog "Incremental backup done"
910+vlog "Preparing backup"
911+
912+# Prepare backup
913+xtrabackup --datadir=$mysql_datadir --prepare --apply-log-only \
914+ --target-dir=$topdir/data/full $mysqld_additional_args
915+vlog "Log applied to backup"
916+
917+xtrabackup --datadir=$mysql_datadir --prepare --apply-log-only \
918+ --target-dir=$topdir/data/full --incremental-dir=$topdir/data/delta \
919+ $mysqld_additional_args
920+vlog "Delta applied to backup"
921+
922+xtrabackup --datadir=$mysql_datadir --prepare --target-dir=$topdir/data/full \
923+ $mysqld_additional_args
924+vlog "Data prepared for restore"
925+
926+# removing rows
927+${MYSQL} ${MYSQL_ARGS} -e "delete from t2;" incremental_sample
928+vlog "Table cleared"
929+
930+# Restore backup
931+
932+stop_server
933+
934+vlog "Copying files"
935+
936+cd $topdir/data/full/
937+cp -r * $mysql_datadir
938+cd -
939+
940+vlog "Data restored"
941+
942+start_server ${mysqld_additional_args}
943+
944+vlog "Checking checksums"
945+checksum_t2_b=`checksum_table incremental_sample t2`
946+
947+if [ "$checksum_t2_a" != "$checksum_t2_b" ]
948+then
949+ vlog "Checksums of table 't2' are not equal"
950+ exit -1
951+fi
952+
953+vlog "Checksums are OK"
954+
955+stop_server
956
957=== added file 'test/t/bug1028949.sh'
958--- test/t/bug1028949.sh 1970-01-01 00:00:00 +0000
959+++ test/t/bug1028949.sh 2012-08-01 10:28:21 +0000
960@@ -0,0 +1,110 @@
961+. inc/common.sh
962+
963+if [ -z "$INNODB_VERSION" ]; then
964+ echo "Requires InnoDB plugin or XtraDB" >$SKIPPED_REASON
965+ exit $SKIPPED_EXIT_CODE
966+fi
967+
968+function test_bug_1028949()
969+{
970+ page_size=$1
971+
972+ mysqld_additional_args="--innodb_file_per_table --innodb_strict_mode \
973+--innodb_file_format=Barracuda"
974+
975+ start_server ${mysqld_additional_args}
976+
977+ load_dbase_schema incremental_sample
978+
979+ # Full backup
980+
981+ # Full backup folder
982+ rm -rf $topdir/data/full
983+ mkdir -p $topdir/data/full
984+ # Incremental data
985+ rm -rf $topdir/data/delta
986+ mkdir -p $topdir/data/delta
987+
988+ vlog "Starting backup"
989+
990+ xtrabackup --datadir=$mysql_datadir --backup --target-dir=$topdir/data/full \
991+ $mysqld_additional_args
992+
993+ vlog "Full backup done"
994+
995+ # Changing data in sakila
996+
997+ vlog "Making changes to database"
998+
999+ ${MYSQL} ${MYSQL_ARGS} -e "CREATE TABLE t2 (a INT(11) DEFAULT NULL, \
1000+ number INT(11) DEFAULT NULL) ENGINE=INNODB\
1001+ ROW_FORMAT=compressed KEY_BLOCK_SIZE=$page_size" incremental_sample
1002+ ${MYSQL} ${MYSQL_ARGS} -e "INSERT INTO t2 VALUES (1, 1)" incremental_sample
1003+
1004+ vlog "Changes done"
1005+
1006+ # Saving the checksum of original table
1007+ checksum_t2_a=`checksum_table incremental_sample t2`
1008+
1009+ vlog "Table 't2' checksum is $checksum_t2_a"
1010+
1011+ vlog "Making incremental backup"
1012+
1013+ # Incremental backup
1014+ xtrabackup --datadir=$mysql_datadir --backup \
1015+ --target-dir=$topdir/data/delta --incremental-basedir=$topdir/data/full \
1016+ $mysqld_additional_args
1017+
1018+ vlog "Incremental backup done"
1019+ vlog "Preparing backup"
1020+
1021+ # Prepare backup
1022+ xtrabackup --datadir=$mysql_datadir --prepare --apply-log-only \
1023+ --target-dir=$topdir/data/full $mysqld_additional_args
1024+ vlog "Log applied to backup"
1025+
1026+ xtrabackup --datadir=$mysql_datadir --prepare --apply-log-only \
1027+ --target-dir=$topdir/data/full --incremental-dir=$topdir/data/delta \
1028+ $mysqld_additional_args
1029+ vlog "Delta applied to backup"
1030+
1031+ xtrabackup --datadir=$mysql_datadir --prepare --target-dir=$topdir/data/full \
1032+ $mysqld_additional_args
1033+ vlog "Data prepared for restore"
1034+
1035+ # removing rows
1036+ ${MYSQL} ${MYSQL_ARGS} -e "delete from t2;" incremental_sample
1037+ vlog "Table cleared"
1038+
1039+ # Restore backup
1040+
1041+ stop_server
1042+
1043+ vlog "Copying files"
1044+
1045+ cd $topdir/data/full/
1046+ cp -r * $mysql_datadir
1047+ cd -
1048+
1049+ vlog "Data restored"
1050+
1051+ start_server ${mysqld_additional_args}
1052+
1053+ vlog "Checking checksums"
1054+ checksum_t2_b=`checksum_table incremental_sample t2`
1055+
1056+ if [ "$checksum_t2_a" != "$checksum_t2_b" ]
1057+ then
1058+ vlog "Checksums of table 't2' are not equal"
1059+ exit -1
1060+ fi
1061+
1062+ vlog "Checksums are OK"
1063+
1064+ stop_server
1065+}
1066+
1067+for page_size in 1 2 4 8 16; do
1068+ test_bug_1028949 ${page_size}
1069+ clean
1070+done
1071
1072=== added file 'test/t/bug932623.sh'
1073--- test/t/bug932623.sh 1970-01-01 00:00:00 +0000
1074+++ test/t/bug932623.sh 2012-08-01 10:28:21 +0000
1075@@ -0,0 +1,85 @@
1076+########################################################################
1077+# Bug #932623: RENAME TABLE causes incremental prepare to fail
1078+########################################################################
1079+
1080+. inc/common.sh
1081+
1082+start_server --innodb_file_per_table
1083+
1084+run_cmd $MYSQL $MYSQL_ARGS test <<EOF
1085+CREATE TABLE t1_old(a INT) ENGINE=InnoDB;
1086+INSERT INTO t1_old VALUES (1), (2), (3);
1087+
1088+CREATE TABLE t1(a INT) ENGINE=InnoDB;
1089+INSERT INTO t1 VALUES (4), (5), (6);
1090+EOF
1091+
1092+# Full backup
1093+# backup root directory
1094+vlog "Starting backup"
1095+innobackupex --no-timestamp $topdir/full
1096+
1097+vlog "Rotating the table"
1098+
1099+run_cmd $MYSQL $MYSQL_ARGS test <<EOF
1100+CREATE TABLE t1_new(a int) ENGINE=InnoDB;
1101+INSERT INTO t1_new VALUES (7), (8), (9);
1102+
1103+CREATE DATABASE db2;
1104+RENAME TABLE t1_old TO db2.t1;
1105+
1106+RENAME TABLE t1 TO t1_old;
1107+RENAME TABLE t1_new TO t1;
1108+
1109+INSERT INTO t1_old VALUES (10), (11), (12);
1110+INSERT INTO t1 VALUES (13), (14), (15);
1111+
1112+EOF
1113+
1114+vlog "Creating incremental backup"
1115+
1116+innobackupex --incremental --no-timestamp \
1117+ --incremental-basedir=$topdir/full $topdir/inc
1118+
1119+vlog "Preparing backup"
1120+
1121+innobackupex --apply-log --redo-only $topdir/full
1122+vlog "Log applied to full backup"
1123+
1124+innobackupex --apply-log --redo-only --incremental-dir=$topdir/inc \
1125+ $topdir/full
1126+vlog "Delta applied to full backup"
1127+
1128+innobackupex --apply-log $topdir/full
1129+vlog "Data prepared for restore"
1130+
1131+checksum_t1_a=`checksum_table test t1`
1132+checksum_t1_old_a=`checksum_table test t1_old`
1133+checksum_t1_db2_a=`checksum_table db2 t1`
1134+
1135+# Destroying mysql data
1136+stop_server
1137+rm -rf $mysql_datadir/*
1138+vlog "Data destroyed"
1139+
1140+# Restore backup
1141+vlog "Copying files"
1142+
1143+innobackupex --copy-back $topdir/full
1144+vlog "Data restored"
1145+
1146+start_server --innodb_file_per_table
1147+
1148+vlog "Checking checksums"
1149+checksum_t1_b=`checksum_table test t1`
1150+checksum_t1_old_b=`checksum_table test t1_old`
1151+checksum_t1_db2_b=`checksum_table db2 t1`
1152+
1153+if [ "$checksum_t1_a" != "$checksum_t1_b" -o "$checksum_t1_old_a" != "$checksum_t1_old_b" \
1154+ -o "$checksum_t1_db2_a" != "$checksum_t1_db2_b" ]
1155+then
1156+ vlog "Checksums do not match"
1157+ exit -1
1158+fi
1159+
1160+vlog "Checksums are OK"

Subscribers

People subscribed via source and target branches