]> git.pld-linux.org Git - packages/mysql.git/blame - mysql-innodb_expand_import.patch
remove id expansion
[packages/mysql.git] / mysql-innodb_expand_import.patch
CommitLineData
8c0fcd57
ER
1# name : innodb_expand_import.patch
2# introduced : 11 or before
3# maintainer : Yasufumi
4#
5#!!! notice !!!
6# Any small change to this file in the main branch
7# should be done or reviewed by the maintainer!
4eec3829
AM
8--- a/storage/innodb_plugin/btr/btr0btr.c
9+++ b/storage/innodb_plugin/btr/btr0btr.c
10@@ -837,7 +837,7 @@
11 /**************************************************************//**
12 Creates a new index page (not the root, and also not
13 used in page reorganization). @see btr_page_empty(). */
14-static
15+UNIV_INTERN
16 void
17 btr_page_create(
18 /*============*/
19@@ -1704,7 +1704,7 @@
20 #ifndef UNIV_HOTBACKUP
21 /*************************************************************//**
22 Empties an index page. @see btr_page_create(). */
23-static
24+UNIV_INTERN
25 void
26 btr_page_empty(
27 /*===========*/
28@@ -2266,7 +2266,7 @@
29 /**************************************************************//**
30 Attaches the halves of an index page on the appropriate level in an
31 index tree. */
32-static
33+UNIV_INTERN
34 void
35 btr_attach_half_pages(
36 /*==================*/
37--- a/storage/innodb_plugin/fil/fil0fil.c
38+++ b/storage/innodb_plugin/fil/fil0fil.c
39@@ -40,6 +40,14 @@
8c0fcd57
ER
40 #include "dict0dict.h"
41 #include "page0page.h"
42 #include "page0zip.h"
43+#include "trx0trx.h"
44+#include "trx0sys.h"
45+#include "pars0pars.h"
46+#include "row0mysql.h"
47+#include "row0row.h"
48+#include "que0que.h"
4eec3829
AM
49+#include "btr0btr.h"
50+#include "btr0sea.h"
8c0fcd57
ER
51 #ifndef UNIV_HOTBACKUP
52 # include "buf0lru.h"
53 # include "ibuf0ibuf.h"
4eec3829
AM
54@@ -2984,6 +2992,84 @@
55 }
56
57 /********************************************************************//**
58+Checks if a page is corrupt. (for offline page)
59+*/
60+static
61+ibool
62+fil_page_buf_page_is_corrupted_offline(
63+/*===================================*/
64+ const byte* page, /*!< in: a database page */
65+ ulint zip_size) /*!< in: size of compressed page;
66+ 0 for uncompressed pages */
67+{
68+ ulint checksum_field;
69+ ulint old_checksum_field;
70+
71+ if (!zip_size
72+ && memcmp(page + FIL_PAGE_LSN + 4,
73+ page + UNIV_PAGE_SIZE
74+ - FIL_PAGE_END_LSN_OLD_CHKSUM + 4, 4)) {
75+ return(TRUE);
76+ }
77+
78+ checksum_field = mach_read_from_4(page
79+ + FIL_PAGE_SPACE_OR_CHKSUM);
80+
81+ if (zip_size) {
82+ return(checksum_field != BUF_NO_CHECKSUM_MAGIC
83+ && checksum_field
84+ != page_zip_calc_checksum(page, zip_size));
85+ }
86+
87+ old_checksum_field = mach_read_from_4(
88+ page + UNIV_PAGE_SIZE
89+ - FIL_PAGE_END_LSN_OLD_CHKSUM);
90+
91+ if (old_checksum_field != mach_read_from_4(page
92+ + FIL_PAGE_LSN)
93+ && old_checksum_field != BUF_NO_CHECKSUM_MAGIC
94+ && old_checksum_field
95+ != buf_calc_page_old_checksum(page)) {
96+ return(TRUE);
97+ }
98+
99+ if (checksum_field != 0
100+ && checksum_field != BUF_NO_CHECKSUM_MAGIC
101+ && checksum_field
102+ != buf_calc_page_new_checksum(page)) {
103+ return(TRUE);
104+ }
105+
106+ return(FALSE);
107+}
108+
109+/********************************************************************//**
110+*/
111+static
112+void
113+fil_page_buf_page_store_checksum(
114+/*=============================*/
115+ byte* page,
116+ ulint zip_size)
117+{
118+ if (!zip_size) {
119+ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
120+ srv_use_checksums
121+ ? buf_calc_page_new_checksum(page)
122+ : BUF_NO_CHECKSUM_MAGIC);
123+ mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
124+ srv_use_checksums
125+ ? buf_calc_page_old_checksum(page)
126+ : BUF_NO_CHECKSUM_MAGIC);
127+ } else {
128+ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
129+ srv_use_checksums
130+ ? page_zip_calc_checksum(page, zip_size)
131+ : BUF_NO_CHECKSUM_MAGIC);
132+ }
133+}
134+
135+/********************************************************************//**
136 Tries to open a single-table tablespace and optionally checks the space id is
137 right in it. If does not succeed, prints an error message to the .err log. This
138 function is used to open a tablespace when we start up mysqld, and also in
139@@ -3029,7 +3115,7 @@
8c0fcd57
ER
140 ut_a(!(flags & (~0UL << DICT_TF_BITS)));
141
142 file = os_file_create_simple_no_error_handling(
143- filepath, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
144+ filepath, OS_FILE_OPEN, OS_FILE_READ_WRITE, &success);
145 if (!success) {
146 /* The following call prints an error message */
147 os_file_get_last_error(TRUE);
4eec3829 148@@ -3076,6 +3162,445 @@
8c0fcd57
ER
149 space_id = fsp_header_get_space_id(page);
150 space_flags = fsp_header_get_flags(page);
151
74952c29
AM
152+ if (srv_expand_import) {
153+
8c0fcd57
ER
154+ ibool file_is_corrupt = FALSE;
155+ byte* buf3;
156+ byte* descr_page;
157+ ibool descr_is_corrupt = FALSE;
158+ dulint old_id[31];
159+ dulint new_id[31];
160+ ulint root_page[31];
161+ ulint n_index;
162+ os_file_t info_file = -1;
163+ char* info_file_path;
164+ ulint i;
165+ int len;
166+ ib_uint64_t current_lsn;
167+ ulint size_low, size_high, size, free_limit;
168+ ib_int64_t size_bytes, free_limit_bytes;
169+ dict_table_t* table;
170+ dict_index_t* index;
171+ fil_system_t* system;
172+ fil_node_t* node = NULL;
173+ fil_space_t* space;
4eec3829 174+ ulint zip_size;
8c0fcd57
ER
175+
176+ buf3 = ut_malloc(2 * UNIV_PAGE_SIZE);
177+ descr_page = ut_align(buf3, UNIV_PAGE_SIZE);
178+
179+ current_lsn = log_get_lsn();
180+
181+ /* check the header page's consistency */
182+ if (buf_page_is_corrupted(page,
183+ dict_table_flags_to_zip_size(space_flags))) {
184+ fprintf(stderr, "InnoDB: page 0 of %s seems corrupt.\n", filepath);
185+ file_is_corrupt = TRUE;
186+ descr_is_corrupt = TRUE;
187+ }
188+
189+ /* store as first descr page */
190+ memcpy(descr_page, page, UNIV_PAGE_SIZE);
191+
4eec3829
AM
192+ zip_size = dict_table_flags_to_zip_size(flags);
193+ ut_a(zip_size == dict_table_flags_to_zip_size(space_flags));
194+
8c0fcd57
ER
195+ /* get free limit (page number) of the table space */
196+/* these should be same to the definition in fsp0fsp.c */
197+#define FSP_HEADER_OFFSET FIL_PAGE_DATA
198+#define FSP_FREE_LIMIT 12
199+ free_limit = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT + page);
4eec3829 200+ free_limit_bytes = (ib_int64_t)free_limit * (ib_int64_t)(zip_size ? zip_size : UNIV_PAGE_SIZE);
8c0fcd57
ER
201+
202+ /* overwrite fsp header */
203+ fsp_header_init_fields(page, id, flags);
204+ mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, id);
205+ space_id = id;
206+ space_flags = flags;
207+ if (mach_read_ull(page + FIL_PAGE_FILE_FLUSH_LSN) > current_lsn)
208+ mach_write_ull(page + FIL_PAGE_FILE_FLUSH_LSN, current_lsn);
4eec3829
AM
209+
210+ fil_page_buf_page_store_checksum(page, zip_size);
211+
8c0fcd57
ER
212+ success = os_file_write(filepath, file, page, 0, 0, UNIV_PAGE_SIZE);
213+
214+ /* get file size */
215+ os_file_get_size(file, &size_low, &size_high);
216+ size_bytes = (((ib_int64_t)size_high) << 32)
217+ + (ib_int64_t)size_low;
218+
219+ if (size_bytes < free_limit_bytes) {
220+ free_limit_bytes = size_bytes;
4eec3829 221+ if (size_bytes >= (ib_int64_t) (FSP_EXTENT_SIZE * (zip_size ? zip_size : UNIV_PAGE_SIZE))) {
967eb3b7
ER
222+ fprintf(stderr, "InnoDB: free limit of %s is larger than its real size.\n", filepath);
223+ file_is_corrupt = TRUE;
224+ }
8c0fcd57
ER
225+ }
226+
227+ /* get cruster index information */
228+ table = dict_table_get_low(name);
229+ index = dict_table_get_first_index(table);
230+ ut_a(index->page==3);
231+
232+ /* read metadata from .exp file */
233+ n_index = 0;
234+ memset(old_id, 0, sizeof(old_id));
235+ memset(new_id, 0, sizeof(new_id));
236+ memset(root_page, 0, sizeof(root_page));
237+
238+ info_file_path = fil_make_ibd_name(name, FALSE);
239+ len = strlen(info_file_path);
240+ info_file_path[len - 3] = 'e';
241+ info_file_path[len - 2] = 'x';
242+ info_file_path[len - 1] = 'p';
243+
244+ info_file = os_file_create_simple_no_error_handling(
245+ info_file_path, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
246+ if (!success) {
247+ fprintf(stderr, "InnoDB: cannot open %s\n", info_file_path);
248+ file_is_corrupt = TRUE;
249+ goto skip_info;
250+ }
251+ success = os_file_read(info_file, page, 0, 0, UNIV_PAGE_SIZE);
252+ if (!success) {
253+ fprintf(stderr, "InnoDB: cannot read %s\n", info_file_path);
254+ file_is_corrupt = TRUE;
255+ goto skip_info;
256+ }
257+ if (mach_read_from_4(page) != 0x78706f72UL
258+ || mach_read_from_4(page + 4) != 0x74696e66UL) {
259+ fprintf(stderr, "InnoDB: %s seems not to be a correct .exp file\n", info_file_path);
260+ file_is_corrupt = TRUE;
261+ goto skip_info;
262+ }
263+
264+ fprintf(stderr, "InnoDB: import: extended import of %s is started.\n", name);
265+
266+ n_index = mach_read_from_4(page + 8);
267+ fprintf(stderr, "InnoDB: import: %lu indexes are detected.\n", (ulong)n_index);
268+ for (i = 0; i < n_index; i++) {
269+ new_id[i] =
270+ dict_table_get_index_on_name(table,
271+ (char*)(page + (i + 1) * 512 + 12))->id;
272+ old_id[i] = mach_read_from_8(page + (i + 1) * 512);
273+ root_page[i] = mach_read_from_4(page + (i + 1) * 512 + 8);
274+ }
275+
276+skip_info:
277+ if (info_file != -1)
278+ os_file_close(info_file);
279+
280+ /*
281+ if (size_bytes >= 1024 * 1024) {
282+ size_bytes = ut_2pow_round(size_bytes, 1024 * 1024);
283+ }
284+ */
4eec3829
AM
285+
286+ if (zip_size) {
287+ fprintf(stderr, "InnoDB: Warning: importing compressed table is still EXPERIMENTAL, currently.\n");
288+ }
289+
290+ {
8c0fcd57
ER
291+ mem_heap_t* heap = NULL;
292+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
293+ ulint* offsets = offsets_;
294+ ib_int64_t offset;
295+
4eec3829 296+ size = (ulint) (size_bytes / (zip_size ? zip_size : UNIV_PAGE_SIZE));
8c0fcd57
ER
297+ /* over write space id of all pages */
298+ rec_offs_init(offsets_);
299+
300+ fprintf(stderr, "InnoDB: Progress in %%:");
301+
4eec3829
AM
302+ for (offset = 0; offset < free_limit_bytes;
303+ offset += zip_size ? zip_size : UNIV_PAGE_SIZE) {
8c0fcd57
ER
304+ ibool page_is_corrupt;
305+
306+ success = os_file_read(file, page,
307+ (ulint)(offset & 0xFFFFFFFFUL),
4eec3829
AM
308+ (ulint)(offset >> 32),
309+ zip_size ? zip_size : UNIV_PAGE_SIZE);
8c0fcd57
ER
310+
311+ page_is_corrupt = FALSE;
312+
313+ /* check consistency */
4eec3829 314+ if (fil_page_buf_page_is_corrupted_offline(page, zip_size)) {
8c0fcd57
ER
315+ page_is_corrupt = TRUE;
316+ }
317+
318+ if (mach_read_from_4(page + FIL_PAGE_OFFSET)
4eec3829 319+ != offset / (zip_size ? zip_size : UNIV_PAGE_SIZE)) {
8c0fcd57
ER
320+
321+ page_is_corrupt = TRUE;
322+ }
323+
324+ /* if it is free page, inconsistency is acceptable */
325+ if (!offset) {
326+ /* header page*/
327+ /* it should be overwritten already */
328+ ut_a(!page_is_corrupt);
329+
4eec3829
AM
330+ } else if (!((offset / (zip_size ? zip_size : UNIV_PAGE_SIZE))
331+ % (zip_size ? zip_size : UNIV_PAGE_SIZE))) {
8c0fcd57
ER
332+ /* descr page (not header) */
333+ if (page_is_corrupt) {
334+ file_is_corrupt = TRUE;
335+ descr_is_corrupt = TRUE;
336+ } else {
967eb3b7 337+
8c0fcd57
ER
338+ descr_is_corrupt = FALSE;
339+ }
340+
341+ /* store as descr page */
4eec3829 342+ memcpy(descr_page, page, (zip_size ? zip_size : UNIV_PAGE_SIZE));
8c0fcd57
ER
343+
344+ } else if (descr_is_corrupt) {
345+ /* unknown state of the page */
346+ if (page_is_corrupt) {
347+ file_is_corrupt = TRUE;
348+ }
349+
350+ } else {
351+ /* check free page or not */
352+ /* These definitions should be same to fsp0fsp.c */
353+#define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE)
354+
355+#define XDES_BITMAP (FLST_NODE_SIZE + 12)
356+#define XDES_BITS_PER_PAGE 2
357+#define XDES_FREE_BIT 0
358+#define XDES_SIZE \
359+ (XDES_BITMAP + UT_BITS_IN_BYTES(FSP_EXTENT_SIZE * XDES_BITS_PER_PAGE))
360+#define XDES_ARR_OFFSET (FSP_HEADER_OFFSET + FSP_HEADER_SIZE)
361+
362+ /*descr = descr_page + XDES_ARR_OFFSET + XDES_SIZE * xdes_calc_descriptor_index(zip_size, offset)*/
363+ /*xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)*/
364+ byte* descr;
365+ ulint index;
366+ ulint byte_index;
367+ ulint bit_index;
368+
369+ descr = descr_page + XDES_ARR_OFFSET
4eec3829
AM
370+ + XDES_SIZE * (ut_2pow_remainder(
371+ (offset / (zip_size ? zip_size : UNIV_PAGE_SIZE)),
372+ (zip_size ? zip_size : UNIV_PAGE_SIZE)) / FSP_EXTENT_SIZE);
8c0fcd57 373+
4eec3829
AM
374+ index = XDES_FREE_BIT
375+ + XDES_BITS_PER_PAGE * ((offset / (zip_size ? zip_size : UNIV_PAGE_SIZE)) % FSP_EXTENT_SIZE);
8c0fcd57
ER
376+ byte_index = index / 8;
377+ bit_index = index % 8;
378+
379+ if (ut_bit_get_nth(mach_read_from_1(descr + XDES_BITMAP + byte_index), bit_index)) {
380+ /* free page */
381+ if (page_is_corrupt) {
382+ goto skip_write;
383+ }
384+ } else {
385+ /* not free */
386+ if (page_is_corrupt) {
387+ file_is_corrupt = TRUE;
388+ }
389+ }
390+ }
391+
392+ if (page_is_corrupt) {
4eec3829 393+ fprintf(stderr, " [errp:%lld]", offset / (zip_size ? zip_size : UNIV_PAGE_SIZE));
8c0fcd57
ER
394+
395+ /* cannot treat corrupt page */
396+ goto skip_write;
397+ }
398+
399+ if (mach_read_from_4(page + FIL_PAGE_OFFSET) || !offset) {
400+ mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, id);
401+
402+ for (i = 0; i < n_index; i++) {
4eec3829
AM
403+ if (offset / (zip_size ? zip_size : UNIV_PAGE_SIZE) == root_page[i]) {
404+ if (fil_page_get_type(page) != FIL_PAGE_INDEX) {
405+ file_is_corrupt = TRUE;
406+ fprintf(stderr, " [etyp:%lld]",
407+ offset / (zip_size ? zip_size : UNIV_PAGE_SIZE));
408+ goto skip_write;
409+ }
8c0fcd57
ER
410+ /* this is index root page */
411+ mach_write_to_4(page + FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
412+ + FSEG_HDR_SPACE, id);
413+ mach_write_to_4(page + FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
414+ + FSEG_HDR_SPACE, id);
415+ break;
416+ }
417+ }
418+
419+ if (fil_page_get_type(page) == FIL_PAGE_INDEX) {
420+ dulint tmp = mach_read_from_8(page + (PAGE_HEADER + PAGE_INDEX_ID));
421+
4eec3829
AM
422+ for (i = 0; i < n_index; i++) {
423+ if (ut_dulint_cmp(old_id[i], tmp) == 0) {
424+ mach_write_to_8(page + (PAGE_HEADER + PAGE_INDEX_ID), new_id[i]);
425+ break;
426+ }
427+ }
428+
429+ if (!zip_size && mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL) == 0
8c0fcd57
ER
430+ && ut_dulint_cmp(old_id[0], tmp) == 0) {
431+ /* leaf page of cluster index, reset trx_id of records */
432+ rec_t* rec;
433+ rec_t* supremum;
434+ ulint n_recs;
435+
436+ supremum = page_get_supremum_rec(page);
437+ rec = page_rec_get_next(page_get_infimum_rec(page));
438+ n_recs = page_get_n_recs(page);
439+
440+ while (rec && rec != supremum && n_recs > 0) {
441+ ulint n_fields;
442+ ulint i;
443+ ulint offset = index->trx_id_offset;
444+ offsets = rec_get_offsets(rec, index, offsets,
445+ ULINT_UNDEFINED, &heap);
446+ n_fields = rec_offs_n_fields(offsets);
447+ if (!offset) {
3700c2a6 448+ offset = row_get_trx_id_offset(index, offsets);
8c0fcd57
ER
449+ }
450+ trx_write_trx_id(rec + offset, ut_dulint_create(0, 1));
451+
452+ for (i = 0; i < n_fields; i++) {
453+ if (rec_offs_nth_extern(offsets, i)) {
454+ ulint local_len;
455+ byte* data;
456+
457+ data = rec_get_nth_field(rec, offsets, i, &local_len);
458+
459+ local_len -= BTR_EXTERN_FIELD_REF_SIZE;
460+
461+ mach_write_to_4(data + local_len + BTR_EXTERN_SPACE_ID, id);
462+ }
463+ }
464+
465+ rec = page_rec_get_next(rec);
466+ n_recs--;
467+ }
4eec3829
AM
468+ } else if (mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL) == 0
469+ && ut_dulint_cmp(old_id[0], tmp) != 0) {
470+ mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), ut_dulint_create(0, 1));
8c0fcd57
ER
471+ }
472+ }
473+
474+ if (mach_read_ull(page + FIL_PAGE_LSN) > current_lsn) {
475+ mach_write_ull(page + FIL_PAGE_LSN, current_lsn);
4eec3829
AM
476+ if (!zip_size) {
477+ mach_write_ull(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
478+ current_lsn);
479+ }
8c0fcd57
ER
480+ }
481+
4eec3829 482+ fil_page_buf_page_store_checksum(page, zip_size);
8c0fcd57
ER
483+
484+ success = os_file_write(filepath, file, page,
485+ (ulint)(offset & 0xFFFFFFFFUL),
4eec3829
AM
486+ (ulint)(offset >> 32),
487+ zip_size ? zip_size : UNIV_PAGE_SIZE);
8c0fcd57
ER
488+ }
489+
490+skip_write:
491+ if (free_limit_bytes
4eec3829 492+ && ((ib_int64_t)((offset + (zip_size ? zip_size : UNIV_PAGE_SIZE)) * 100) / free_limit_bytes)
8c0fcd57
ER
493+ != ((offset * 100) / free_limit_bytes)) {
494+ fprintf(stderr, " %lu",
4eec3829 495+ (ulong)((ib_int64_t)((offset + (zip_size ? zip_size : UNIV_PAGE_SIZE)) * 100) / free_limit_bytes));
8c0fcd57
ER
496+ }
497+ }
498+
499+ fprintf(stderr, " done.\n");
500+
501+ /* update SYS_INDEXES set root page */
502+ index = dict_table_get_first_index(table);
503+ while (index) {
504+ for (i = 0; i < n_index; i++) {
505+ if (ut_dulint_cmp(new_id[i], index->id) == 0) {
506+ break;
507+ }
508+ }
509+
510+ if (i != n_index
511+ && root_page[i] != index->page) {
512+ /* must update */
513+ ulint error;
514+ trx_t* trx;
515+ pars_info_t* info = NULL;
516+
517+ trx = trx_allocate_for_mysql();
518+ trx->op_info = "extended import";
519+
520+ info = pars_info_create();
521+
522+ pars_info_add_dulint_literal(info, "indexid", new_id[i]);
523+ pars_info_add_int4_literal(info, "new_page", (lint) root_page[i]);
524+
525+ error = que_eval_sql(info,
526+ "PROCEDURE UPDATE_INDEX_PAGE () IS\n"
527+ "BEGIN\n"
528+ "UPDATE SYS_INDEXES"
529+ " SET PAGE_NO = :new_page"
530+ " WHERE ID = :indexid;\n"
531+ "COMMIT WORK;\n"
532+ "END;\n",
533+ FALSE, trx);
534+
535+ if (error != DB_SUCCESS) {
536+ fprintf(stderr, "InnoDB: failed to update SYS_INDEXES\n");
537+ }
538+
539+ trx_commit_for_mysql(trx);
540+
541+ trx_free_for_mysql(trx);
542+
543+ index->page = root_page[i];
544+ }
545+
546+ index = dict_table_get_next_index(index);
547+ }
548+ if (UNIV_LIKELY_NULL(heap)) {
549+ mem_heap_free(heap);
550+ }
8c0fcd57
ER
551+ }
552+ /* .exp file should be removed */
553+ success = os_file_delete(info_file_path);
554+ if (!success) {
555+ success = os_file_delete_if_exists(info_file_path);
556+ }
557+ mem_free(info_file_path);
558+
559+ system = fil_system;
560+ mutex_enter(&(system->mutex));
561+ space = fil_space_get_by_id(id);
562+ if (space)
563+ node = UT_LIST_GET_FIRST(space->chain);
564+ if (node && node->size < size) {
565+ space->size += (size - node->size);
566+ node->size = size;
567+ }
568+ mutex_exit(&(system->mutex));
569+
570+ ut_free(buf3);
571+
572+ if (file_is_corrupt) {
573+ ut_print_timestamp(stderr);
574+ fputs(" InnoDB: Error: file ",
575+ stderr);
576+ ut_print_filename(stderr, filepath);
577+ fprintf(stderr, " seems to be corrupt.\n"
578+ "InnoDB: anyway, all not corrupt pages were tried to be converted to salvage.\n"
579+ "InnoDB: ##### CAUTION #####\n"
580+ "InnoDB: ## The .ibd must cause to crash InnoDB, though re-import would seem to be succeeded.\n"
581+ "InnoDB: ## If you don't have knowledge about salvaging data from .ibd, you should not use the file.\n"
582+ "InnoDB: ###################\n");
583+ success = FALSE;
584+
585+ ut_free(buf2);
586+
587+ goto func_exit;
588+ }
589+ }
590+
591 ut_free(buf2);
592
593 if (UNIV_UNLIKELY(space_id != id
3700c2a6 594@@ -3117,6 +3642,269 @@
4eec3829
AM
595 os_file_close(file);
596 mem_free(filepath);
597
598+ if (srv_expand_import && dict_table_flags_to_zip_size(flags)) {
599+ ulint page_no;
600+ ulint zip_size;
601+ ulint height;
4eec3829
AM
602+ rec_t* node_ptr;
603+ dict_table_t* table;
604+ dict_index_t* index;
605+ buf_block_t* block;
606+ page_t* page;
607+ page_zip_des_t* page_zip;
608+ mtr_t mtr;
609+
610+ mem_heap_t* heap = NULL;
611+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
612+ ulint* offsets = offsets_;
613+
614+ rec_offs_init(offsets_);
615+
616+ zip_size = dict_table_flags_to_zip_size(flags);
617+
618+ table = dict_table_get_low(name);
619+ index = dict_table_get_first_index(table);
620+ page_no = dict_index_get_page(index);
621+ ut_a(page_no == 3);
622+
623+ fprintf(stderr, "InnoDB: It is compressed .ibd file. need to convert additionaly on buffer pool.\n");
624+
625+ /* down to leaf */
626+ mtr_start(&mtr);
627+ mtr_set_log_mode(&mtr, MTR_LOG_NONE);
628+
629+ height = ULINT_UNDEFINED;
630+
631+ for (;;) {
632+ block = buf_page_get(space_id, zip_size, page_no,
633+ RW_NO_LATCH, &mtr);
634+ page = buf_block_get_frame(block);
635+
636+ block->check_index_page_at_flush = TRUE;
637+
638+ if (height == ULINT_UNDEFINED) {
639+ height = btr_page_get_level(page, &mtr);
4eec3829
AM
640+ }
641+
642+ if (height == 0) {
643+ break;
644+ }
645+
646+ node_ptr = page_rec_get_next(page_get_infimum_rec(page));
647+
648+ height--;
649+
650+ offsets = rec_get_offsets(node_ptr, index, offsets, ULINT_UNDEFINED, &heap);
651+ page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
652+ }
653+
654+ mtr_commit(&mtr);
655+
656+ fprintf(stderr, "InnoDB: pages needs split are ...");
657+
658+ /* scan reaf pages */
659+ while (page_no != FIL_NULL) {
660+ rec_t* rec;
661+ rec_t* supremum;
662+ ulint n_recs;
663+
664+ mtr_start(&mtr);
665+
666+ block = buf_page_get(space_id, zip_size, page_no,
667+ RW_X_LATCH, &mtr);
668+ page = buf_block_get_frame(block);
669+ page_zip = buf_block_get_page_zip(block);
670+
671+ if (!page_zip) {
672+ /*something wrong*/
673+ fprintf(stderr, "InnoDB: Something wrong with reading page %lu.\n", page_no);
674+convert_err_exit:
675+ mtr_commit(&mtr);
676+ mutex_enter(&fil_system->mutex);
677+ fil_space_free(space_id, FALSE);
678+ mutex_exit(&fil_system->mutex);
679+ success = FALSE;
680+ goto convert_exit;
681+ }
682+
683+ supremum = page_get_supremum_rec(page);
684+ rec = page_rec_get_next(page_get_infimum_rec(page));
685+ n_recs = page_get_n_recs(page);
686+
687+ /* illegal operation as InnoDB online system. so not logged */
688+ while (rec && rec != supremum && n_recs > 0) {
689+ ulint n_fields;
690+ ulint i;
691+ ulint offset = index->trx_id_offset;
692+
693+ offsets = rec_get_offsets(rec, index, offsets,
694+ ULINT_UNDEFINED, &heap);
695+ n_fields = rec_offs_n_fields(offsets);
696+ if (!offset) {
3700c2a6 697+ offset = row_get_trx_id_offset(index, offsets);
4eec3829
AM
698+ }
699+ trx_write_trx_id(rec + offset, ut_dulint_create(0, 1));
700+
701+ for (i = 0; i < n_fields; i++) {
702+ if (rec_offs_nth_extern(offsets, i)) {
703+ ulint local_len;
704+ byte* data;
705+
706+ data = rec_get_nth_field(rec, offsets, i, &local_len);
707+
708+ local_len -= BTR_EXTERN_FIELD_REF_SIZE;
709+
710+ mach_write_to_4(data + local_len + BTR_EXTERN_SPACE_ID, id);
711+ }
712+ }
713+
714+ rec = page_rec_get_next(rec);
715+ n_recs--;
716+ }
717+
718+ /* dummy logged update for along with modified page path */
719+ if (ut_dulint_cmp(index->id, btr_page_get_index_id(page)) != 0) {
720+ /* this should be adjusted already */
721+ fprintf(stderr, "InnoDB: The page %lu seems to be converted wrong.\n", page_no);
722+ goto convert_err_exit;
723+ }
724+ btr_page_set_index_id(page, page_zip, index->id, &mtr);
725+
726+ /* confirm whether fits to the page size or not */
727+ if (!page_zip_compress(page_zip, page, index, &mtr)
728+ && !btr_page_reorganize(block, index, &mtr)) {
729+ buf_block_t* new_block;
730+ page_t* new_page;
731+ page_zip_des_t* new_page_zip;
732+ rec_t* split_rec;
733+ ulint n_uniq;
734+
735+ /* split page is needed */
736+ fprintf(stderr, " %lu", page_no);
737+
738+ mtr_x_lock(dict_index_get_lock(index), &mtr);
739+
740+ n_uniq = dict_index_get_n_unique_in_tree(index);
741+
742+ if(page_get_n_recs(page) < 2) {
743+ /* no way to make smaller */
744+ fprintf(stderr, "InnoDB: The page %lu cannot be store to the page size.\n", page_no);
745+ goto convert_err_exit;
746+ }
747+
748+ if (UNIV_UNLIKELY(page_no == dict_index_get_page(index))) {
749+ ulint new_page_no;
750+ dtuple_t* node_ptr;
751+ ulint level;
752+ rec_t* node_ptr_rec;
753+ page_cur_t page_cursor;
754+
755+ /* it is root page, need to raise before split */
756+
757+ level = btr_page_get_level(page, &mtr);
758+
759+ new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, &mtr);
760+ new_page = buf_block_get_frame(new_block);
761+ new_page_zip = buf_block_get_page_zip(new_block);
762+ btr_page_create(new_block, new_page_zip, index, level, &mtr);
763+
764+ btr_page_set_next(new_page, new_page_zip, FIL_NULL, &mtr);
765+ btr_page_set_prev(new_page, new_page_zip, FIL_NULL, &mtr);
766+
767+ page_zip_copy_recs(new_page_zip, new_page,
768+ page_zip, page, index, &mtr);
769+ btr_search_move_or_delete_hash_entries(new_block, block, index);
770+
771+ rec = page_rec_get_next(page_get_infimum_rec(new_page));
772+ new_page_no = buf_block_get_page_no(new_block);
773+
774+ node_ptr = dict_index_build_node_ptr(index, rec, new_page_no, heap,
775+ level);
776+ dtuple_set_info_bits(node_ptr,
777+ dtuple_get_info_bits(node_ptr)
778+ | REC_INFO_MIN_REC_FLAG);
779+ btr_page_empty(block, page_zip, index, level + 1, &mtr);
780+
781+ btr_page_set_next(page, page_zip, FIL_NULL, &mtr);
782+ btr_page_set_prev(page, page_zip, FIL_NULL, &mtr);
783+
784+ page_cur_set_before_first(block, &page_cursor);
785+
786+ node_ptr_rec = page_cur_tuple_insert(&page_cursor, node_ptr,
787+ index, 0, &mtr);
788+ ut_a(node_ptr_rec);
789+
790+ if (!btr_page_reorganize(block, index, &mtr)) {
791+ fprintf(stderr, "InnoDB: failed to store the page %lu.\n", page_no);
792+ goto convert_err_exit;
793+ }
794+
795+ /* move to the raised page */
796+ page_no = new_page_no;
797+ block = new_block;
798+ page = new_page;
799+ page_zip = new_page_zip;
800+
801+ fprintf(stderr, "(raise_to:%lu)", page_no);
802+ }
803+
804+ split_rec = page_get_middle_rec(page);
805+
806+ new_block = btr_page_alloc(index, page_no + 1, FSP_UP,
807+ btr_page_get_level(page, &mtr), &mtr);
808+ new_page = buf_block_get_frame(new_block);
809+ new_page_zip = buf_block_get_page_zip(new_block);
810+ btr_page_create(new_block, new_page_zip, index,
811+ btr_page_get_level(page, &mtr), &mtr);
812+
813+ offsets = rec_get_offsets(split_rec, index, offsets, n_uniq, &heap);
814+
815+ btr_attach_half_pages(index, block,
816+ split_rec, new_block, FSP_UP, &mtr);
817+
818+ page_zip_copy_recs(new_page_zip, new_page,
819+ page_zip, page, index, &mtr);
820+ page_delete_rec_list_start(split_rec - page + new_page,
821+ new_block, index, &mtr);
822+ btr_search_move_or_delete_hash_entries(new_block, block, index);
823+ page_delete_rec_list_end(split_rec, block, index,
824+ ULINT_UNDEFINED, ULINT_UNDEFINED, &mtr);
825+
826+ fprintf(stderr, "(new:%lu)", buf_block_get_page_no(new_block));
827+
828+ /* Are they needed? */
829+ if (!btr_page_reorganize(block, index, &mtr)) {
830+ fprintf(stderr, "InnoDB: failed to store the page %lu.\n", page_no);
831+ goto convert_err_exit;
832+ }
833+ if (!btr_page_reorganize(new_block, index, &mtr)) {
834+ fprintf(stderr, "InnoDB: failed to store the page %lu.\n", buf_block_get_page_no(new_block));
835+ goto convert_err_exit;
836+ }
837+ }
838+
839+ page_no = btr_page_get_next(page, &mtr);
840+
841+ mtr_commit(&mtr);
842+
843+ if (heap) {
844+ mem_heap_empty(heap);
845+ }
846+ }
847+
848+ fprintf(stderr, "...done.\nInnoDB: waiting the flush batch of the additional conversion.\n");
849+
850+ /* should wait for the not-logged changes are all flushed */
851+ buf_flush_batch(BUF_FLUSH_LIST, ULINT_MAX, mtr.end_lsn + 1);
852+ buf_flush_wait_batch_end(BUF_FLUSH_LIST);
853+
854+ fprintf(stderr, "InnoDB: done.\n");
855+convert_exit:
856+ if (UNIV_LIKELY_NULL(heap)) {
857+ mem_heap_free(heap);
858+ }
859+ }
860+
861 return(success);
862 }
863 #endif /* !UNIV_HOTBACKUP */
864--- a/storage/innodb_plugin/handler/ha_innodb.cc
865+++ b/storage/innodb_plugin/handler/ha_innodb.cc
3700c2a6 866@@ -7102,6 +7102,14 @@
74952c29
AM
867 err = row_discard_tablespace_for_mysql(dict_table->name, trx);
868 } else {
869 err = row_import_tablespace_for_mysql(dict_table->name, trx);
870+
871+ /* in expanded import mode re-initialize auto_increment again */
872+ if ((err == DB_SUCCESS) && srv_expand_import &&
873+ (table->found_next_number_field != NULL)) {
874+ dict_table_autoinc_lock(dict_table);
875+ innobase_initialize_autoinc();
876+ dict_table_autoinc_unlock(dict_table);
877+ }
878 }
879
880 err = convert_error_code_to_mysql(err, dict_table->flags, NULL);
3700c2a6 881@@ -11378,6 +11386,11 @@
8c0fcd57
ER
882 "Enable/Disable unsafe group commit when support_xa=OFF and use with binlog or other XA storage engine.",
883 NULL, NULL, 0, 0, 1, 0);
884
885+static MYSQL_SYSVAR_ULONG(expand_import, srv_expand_import,
886+ PLUGIN_VAR_RQCMDARG,
887+ "Enable/Disable converting automatically *.ibd files when import tablespace.",
888+ NULL, NULL, 0, 0, 1, 0);
889+
890 static MYSQL_SYSVAR_ULONG(extra_rsegments, srv_extra_rsegments,
891 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
892 "Number of extra user rollback segments when create new database.",
3700c2a6 893@@ -11455,6 +11468,7 @@
8c0fcd57
ER
894 MYSQL_SYSVAR(adaptive_checkpoint),
895 MYSQL_SYSVAR(flush_log_at_trx_commit_session),
896 MYSQL_SYSVAR(enable_unsafe_group_commit),
897+ MYSQL_SYSVAR(expand_import),
898 MYSQL_SYSVAR(extra_rsegments),
899 MYSQL_SYSVAR(dict_size_limit),
900 MYSQL_SYSVAR(use_sys_malloc),
4eec3829
AM
901--- a/storage/innodb_plugin/handler/innodb_patch_info.h
902+++ b/storage/innodb_plugin/handler/innodb_patch_info.h
8c0fcd57
ER
903@@ -32,6 +32,7 @@
904 {"innodb_extra_rseg","allow to create extra rollback segments","When create new db, the new parameter allows to create more rollback segments","http://www.percona.com/docs/wiki/percona-xtradb"},
905 {"innodb_overwrite_relay_log_info","overwrite relay-log.info when slave recovery","Building as plugin, it is not used.","http://www.percona.com/docs/wiki/percona-xtradb:innodb_overwrite_relay_log_info"},
906 {"innodb_thread_concurrency_timer_based","use InnoDB timer based concurrency throttling (backport from MySQL 5.4.0)","",""},
907+{"innodb_expand_import","convert .ibd file automatically when import tablespace","the files are generated by xtrabackup export mode.","http://www.percona.com/docs/wiki/percona-xtradb"},
908 {"innodb_dict_size_limit","Limit dictionary cache size","Variable innodb_dict_size_limit in bytes","http://www.percona.com/docs/wiki/percona-xtradb"},
909 {"innodb_split_buf_pool_mutex","More fix of buffer_pool mutex","Spliting buf_pool_mutex and optimizing based on innodb_opt_lru_count","http://www.percona.com/docs/wiki/percona-xtradb"},
910 {NULL, NULL, NULL, NULL}
4eec3829
AM
911--- a/storage/innodb_plugin/include/btr0btr.h
912+++ b/storage/innodb_plugin/include/btr0btr.h
913@@ -208,6 +208,17 @@
914 @return the uncompressed page frame */
915 # define btr_page_get(space,zip_size,page_no,mode,mtr) \
916 buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,mtr))
917+/**************************************************************//**
918+Sets the index id field of a page. */
919+UNIV_INLINE
920+void
921+btr_page_set_index_id(
922+/*==================*/
923+ page_t* page, /*!< in: page to be created */
924+ page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
925+ part will be updated, or NULL */
926+ dulint id, /*!< in: index id */
927+ mtr_t* mtr); /*!< in: mtr */
928 #endif /* !UNIV_HOTBACKUP */
929 /**************************************************************//**
930 Gets the index id field of a page.
931@@ -245,6 +256,17 @@
932 const page_t* page, /*!< in: index page */
933 mtr_t* mtr); /*!< in: mini-transaction handle */
934 /********************************************************//**
935+Sets the next index page field. */
936+UNIV_INLINE
937+void
938+btr_page_set_next(
939+/*==============*/
940+ page_t* page, /*!< in: index page */
941+ page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
942+ part will be updated, or NULL */
943+ ulint next, /*!< in: next page number */
944+ mtr_t* mtr); /*!< in: mini-transaction handle */
945+/********************************************************//**
946 Gets the previous index page number.
947 @return prev page number */
948 UNIV_INLINE
949@@ -253,6 +275,17 @@
950 /*==============*/
951 const page_t* page, /*!< in: index page */
952 mtr_t* mtr); /*!< in: mini-transaction handle */
953+/********************************************************//**
954+Sets the previous index page field. */
955+UNIV_INLINE
956+void
957+btr_page_set_prev(
958+/*==============*/
959+ page_t* page, /*!< in: index page */
960+ page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
961+ part will be updated, or NULL */
962+ ulint prev, /*!< in: previous page number */
963+ mtr_t* mtr); /*!< in: mini-transaction handle */
964 /*************************************************************//**
965 Gets pointer to the previous user record in the tree. It is assumed
966 that the caller has appropriate latches on the page and its neighbor.
967@@ -298,6 +331,18 @@
968 /*===========================*/
969 const rec_t* rec, /*!< in: node pointer record */
970 const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
971+/**************************************************************//**
972+Creates a new index page (not the root, and also not
973+used in page reorganization). @see btr_page_empty(). */
974+UNIV_INTERN
975+void
976+btr_page_create(
977+/*============*/
978+ buf_block_t* block, /*!< in/out: page to be created */
979+ page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
980+ dict_index_t* index, /*!< in: index */
981+ ulint level, /*!< in: the B-tree level of the page */
982+ mtr_t* mtr); /*!< in: mtr */
983 /************************************************************//**
984 Creates the root node for a new index tree.
985 @return page number of the created root, FIL_NULL if did not succeed */
986@@ -368,6 +413,17 @@
987 dict_index_t* index, /*!< in: record descriptor */
988 mtr_t* mtr); /*!< in: mtr */
989 /*************************************************************//**
990+Empties an index page. @see btr_page_create(). */
991+UNIV_INTERN
992+void
993+btr_page_empty(
994+/*===========*/
995+ buf_block_t* block, /*!< in: page to be emptied */
996+ page_zip_des_t* page_zip,/*!< out: compressed page, or NULL */
997+ dict_index_t* index, /*!< in: index of the page */
998+ ulint level, /*!< in: the B-tree level of the page */
999+ mtr_t* mtr); /*!< in: mtr */
1000+/*************************************************************//**
1001 Decides if the page should be split at the convergence point of
1002 inserts converging to left.
1003 @return TRUE if split recommended */
1004@@ -426,6 +482,20 @@
1005 # define btr_insert_on_non_leaf_level(i,l,t,m) \
1006 btr_insert_on_non_leaf_level_func(i,l,t,__FILE__,__LINE__,m)
1007 #endif /* !UNIV_HOTBACKUP */
1008+/**************************************************************//**
1009+Attaches the halves of an index page on the appropriate level in an
1010+index tree. */
1011+UNIV_INTERN
1012+void
1013+btr_attach_half_pages(
1014+/*==================*/
1015+ dict_index_t* index, /*!< in: the index tree */
1016+ buf_block_t* block, /*!< in/out: page to be split */
3700c2a6 1017+ const rec_t* split_rec, /*!< in: first record on upper
4eec3829
AM
1018+ half page */
1019+ buf_block_t* new_block, /*!< in/out: the new half page */
1020+ ulint direction, /*!< in: FSP_UP or FSP_DOWN */
1021+ mtr_t* mtr); /*!< in: mtr */
1022 /****************************************************************//**
1023 Sets a record as the predefined minimum record. */
1024 UNIV_INTERN
1025--- a/storage/innodb_plugin/include/srv0srv.h
1026+++ b/storage/innodb_plugin/include/srv0srv.h
3700c2a6 1027@@ -219,6 +219,8 @@
8c0fcd57
ER
1028 extern ulint srv_read_ahead;
1029 extern ulint srv_adaptive_checkpoint;
1030
1031+extern ulint srv_expand_import;
1032+
1033 extern ulint srv_extra_rsegments;
1034 extern ulint srv_dict_size_limit;
1035 /*-------------------------------------------*/
4eec3829
AM
1036--- a/storage/innodb_plugin/row/row0mysql.c
1037+++ b/storage/innodb_plugin/row/row0mysql.c
1038@@ -2520,6 +2520,11 @@
1039
1040 current_lsn = log_get_lsn();
1041
1042+ /* Enlarge the fatal lock wait timeout during import. */
1043+ mutex_enter(&kernel_mutex);
1044+ srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
1045+ mutex_exit(&kernel_mutex);
1046+
1047 /* It is possible, though very improbable, that the lsn's in the
1048 tablespace to be imported have risen above the current system lsn, if
1049 a lengthy purge, ibuf merge, or rollback was performed on a backup
1050@@ -2631,6 +2636,11 @@
1051
1052 trx->op_info = "";
1053
1054+ /* Restore the fatal semaphore wait timeout */
1055+ mutex_enter(&kernel_mutex);
1056+ srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
1057+ mutex_exit(&kernel_mutex);
1058+
1059 return((int) err);
1060 }
1061
1062--- a/storage/innodb_plugin/srv/srv0srv.c
1063+++ b/storage/innodb_plugin/srv/srv0srv.c
3700c2a6 1064@@ -392,6 +392,8 @@
8c0fcd57
ER
1065 UNIV_INTERN ulint srv_read_ahead = 3; /* 1: random 2: linear 3: Both */
1066 UNIV_INTERN ulint srv_adaptive_checkpoint = 0; /* 0: none 1: reflex 2: estimate */
1067
1068+UNIV_INTERN ulint srv_expand_import = 0; /* 0:disable 1:enable */
1069+
1070 UNIV_INTERN ulint srv_extra_rsegments = 0; /* extra rseg for users */
1071 UNIV_INTERN ulint srv_dict_size_limit = 0;
1072 /*-------------------------------------------*/
This page took 0.279232 seconds and 4 git commands to generate.