Merge lp:~gaul/percona-data-recovery-tool-for-innodb/ibd_rename_ids into lp:percona-data-recovery-tool-for-innodb

Proposed by Andrew Gaul
Status: Approved
Approved by: Aleksandr Kuzminsky
Approved revision: 69
Proposed branch: lp:~gaul/percona-data-recovery-tool-for-innodb/ibd_rename_ids
Merge into: lp:percona-data-recovery-tool-for-innodb
Diff against target: 265 lines (+234/-2)
2 files modified
Makefile (+5/-2)
ibd_rename_ids.c (+229/-0)
To merge this branch: bzr merge lp:~gaul/percona-data-recovery-tool-for-innodb/ibd_rename_ids
Reviewer Review Type Date Requested Status
Percona developers Pending
Review via email: mp+119652@code.launchpad.net
To post a comment you must log in.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2012-08-10 01:04:21 +0000
3+++ Makefile 2012-08-15 01:14:19 +0000
4@@ -4,7 +4,7 @@
5
6 INCLUDES=-I include -I mysql-source/include -I mysql-source/innobase/include
7
8-all: prerequisites constraints_parser page_parser page_printer innochecksum ibdconnect
9+all: prerequisites constraints_parser page_parser page_printer innochecksum ibdconnect ibd_rename_ids
10
11 prerequisites:
12 @echo "Make sure you have installed following packages:"
13@@ -51,6 +51,9 @@
14 ibdconnect: ibdconnect.c include/ibdconnect.h include/sys_defs.h
15 gcc $(CFLAGS) $(INCLUDES) -o $@ $<
16
17+ibd_rename_ids: ibd_rename_ids.c include/innochecksum.h
18+ gcc $(CFLAGS) $(INCLUDES) -o $@ $<
19+
20 dict_parsers: all
21 @mkdir -p bin
22 @ln -fs table_defs.h.SYS_TABLES include/table_defs.h
23@@ -93,7 +96,7 @@
24 rm -rf innodb_recovery
25
26 clean:
27- rm -f page_parser page_printer constraints_parser innochecksum ibdconnect prerequisites
28+ rm -f page_parser page_printer constraints_parser innochecksum ibdconnect prerequisites ibd_rename_ids
29 rm -rf lib constraints_parser.dSYM page_parser.dSYM
30
31 distclean: clean
32
33=== added file 'ibd_rename_ids.c'
34--- ibd_rename_ids.c 1970-01-01 00:00:00 +0000
35+++ ibd_rename_ids.c 2012-08-15 01:14:19 +0000
36@@ -0,0 +1,229 @@
37+/* Copyright (C) 2000-2005 MySQL AB & Innobase Oy
38+
39+ This program is free software; you can redistribute it and/or modify
40+ it under the terms of the GNU General Public License as published by
41+ the Free Software Foundation; version 2 of the License.
42+
43+ This program is distributed in the hope that it will be useful,
44+ but WITHOUT ANY WARRANTY; without even the implied warranty of
45+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46+ GNU General Public License for more details.
47+
48+ You should have received a copy of the GNU General Public License
49+ along with this program; if not, write to the Free Software
50+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
51+
52+/*
53+ InnoDB tablespace, table, and index id renamer.
54+
55+ Written by Andrew Gaul <andrew@gaul.org>.
56+
57+ Published with permission.
58+*/
59+
60+/* TODO: batch IO */
61+/* TODO: requires innodb_file_per_table; confused tablespace and table id */
62+
63+#include <inttypes.h>
64+#include <stdint.h>
65+#include <unistd.h>
66+#include "page0page.h"
67+#include "innochecksum.h"
68+
69+static void usage(const char *progname)
70+{
71+ printf("InnoDB tablespace, table, and index id renamer.\n"
72+ "usage: %s [OPTIONS]... FILENAME\n"
73+ "\t-t ID\tset new tablespace id\n"
74+ "\t-I ID\tmap from this index id\n"
75+ "\t-i ID\tmap to this index id\n"
76+ "\t-v\tverbose output\n",
77+ progname);
78+}
79+
80+static uint64_t dulint_to_uint64_t(dulint x)
81+{
82+ return (((uint64_t) x.high) << 32) | x.low;
83+}
84+
85+static void write_page(FILE *file, fpos_t pos, const uchar *page)
86+{
87+ if (0 != fsetpos(file, &pos)) {
88+ perror("couldn't set a position to the start of the page");
89+ exit(1);
90+ }
91+ if (1 != fwrite(page, UNIV_PAGE_SIZE, 1, file)) {
92+ perror("couldn't update the page");
93+ exit(1);
94+ }
95+}
96+
97+int main(int argc, char **argv)
98+{
99+ FILE *file = NULL; /* input file */
100+ uchar *page = (uchar *)malloc(UNIV_PAGE_SIZE); /* storage for pages read */
101+ int bytes; /* bytes read count */
102+ ulint page_no = 0; /* current page number (0-based) */
103+ int32_t tablespace_id_to = -1;
104+ int64_t *index_id_from = malloc(0);
105+ size_t index_id_from_size = 0;
106+ int64_t *index_id_to = malloc(0);
107+ size_t index_id_to_size = 0;
108+ int64_t index_id;
109+ size_t i;
110+ int verbose = 0;
111+ int c;
112+ char *endptr;
113+ fpos_t pos;
114+ int retval = EXIT_FAILURE;
115+
116+ /* parse arguments */
117+ while ((c = getopt(argc, argv, "hvt:I:i:")) != -1) {
118+ switch (c) {
119+ case 'v':
120+ verbose = 1;
121+ break;
122+ case 't':
123+ tablespace_id_to = strtol(optarg, &endptr, 10);
124+ if (*endptr != '\0') {
125+ fprintf(stderr, "invalid value %s\n", optarg);
126+ goto out;
127+ }
128+ break;
129+ case 'I':
130+ index_id = strtoll(optarg, &endptr, 10);
131+ if (*endptr != '\0') {
132+ fprintf(stderr, "invalid value %s\n", optarg);
133+ goto out;
134+ }
135+ index_id_from = realloc(index_id_from,
136+ sizeof(*index_id_from) * (index_id_from_size + 1));
137+ index_id_from[index_id_from_size++] = index_id;
138+ break;
139+ case 'i':
140+ index_id = strtoll(optarg, &endptr, 10);
141+ if (*endptr != '\0') {
142+ fprintf(stderr, "invalid value %s\n", optarg);
143+ goto out;
144+ }
145+ index_id_to = realloc(index_id_to,
146+ sizeof(*index_id_to) * (index_id_to_size + 1));
147+ index_id_to[index_id_to_size++] = index_id;
148+ break;
149+ case ':':
150+ fprintf(stderr, "option -%c requires an argument\n", optopt);
151+ goto out;
152+ case '?':
153+ fprintf(stderr, "unrecognized option: -%c\n", optopt);
154+ goto out;
155+ case 'h':
156+ default:
157+ usage(argv[0]);
158+ goto out;
159+ }
160+ }
161+
162+ /* make sure we have the right arguments */
163+ if (optind >= argc) {
164+ usage(argv[0]);
165+ goto out;
166+ }
167+
168+ if (index_id_from_size != index_id_to_size) {
169+ fprintf(stderr, "Mismatched -T and -t parameters.\n");
170+ goto out;
171+ }
172+
173+ file = fopen(argv[optind], "r+");
174+ if (!file) {
175+ perror("error opening file");
176+ goto out;
177+ }
178+
179+ while (!feof(file)) {
180+ fgetpos(file, &pos);
181+ bytes = fread(page, 1, UNIV_PAGE_SIZE, file);
182+ if (!bytes && feof(file)) break;
183+ if (bytes != UNIV_PAGE_SIZE) {
184+ fprintf(stderr,
185+ "bytes read (%d) does not match universal page size (%d)\n",
186+ bytes, UNIV_PAGE_SIZE);
187+ goto out;
188+ }
189+
190+ uint16_t type = mach_read_from_2(page + FIL_PAGE_TYPE);
191+ uint32_t id = mach_read_from_4((uchar*)&tablespace_id_to);
192+ int modified = FALSE;
193+ if (type != FIL_PAGE_TYPE_ALLOCATED) {
194+ if (tablespace_id_to != -1) {
195+ if (verbose) {
196+ printf("changing tablespace id from %lu to %u at page %lu\n",
197+ mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID),
198+ tablespace_id_to, page_no);
199+ }
200+ memcpy(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, &id, sizeof(id));
201+ modified = TRUE;
202+ }
203+ }
204+ if (type == FIL_PAGE_TYPE_FSP_HDR) {
205+ if (tablespace_id_to != -1) {
206+ memcpy(page + FIL_PAGE_DATA + FSEG_HDR_SPACE, &id, sizeof(id));
207+ modified = TRUE;
208+ }
209+ } else if (type == FIL_PAGE_INDEX) {
210+ uint64_t on_disk_index_id = dulint_to_uint64_t(mach_read_from_8(
211+ page + FIL_PAGE_DATA + PAGE_INDEX_ID));
212+ for (i = 0; i < index_id_from_size; ++i) {
213+ if (on_disk_index_id == index_id_from[i]) {
214+ if (verbose) {
215+ printf("changing index id from %" PRIu64 " to %" PRIi64
216+ " at page %lu\n", index_id_from[i], index_id_to[i], page_no);
217+ }
218+ uint64_t index_id_to_swapped = dulint_to_uint64_t(mach_read_from_8(
219+ (uchar*)&index_id_to[i]));
220+ memcpy(page + FIL_PAGE_DATA + PAGE_INDEX_ID, &index_id_to_swapped,
221+ sizeof(index_id_to_swapped));
222+ modified = TRUE;
223+ break;
224+ }
225+ }
226+
227+ if (tablespace_id_to != -1) {
228+ memcpy(page + FIL_PAGE_DATA + FSEG_HDR_SPACE + PAGE_BTR_SEG_LEAF, &id,
229+ sizeof(id));
230+ memcpy(page + FIL_PAGE_DATA + FSEG_HDR_SPACE + PAGE_BTR_SEG_TOP, &id,
231+ sizeof(id));
232+ modified = TRUE;
233+ }
234+ }
235+
236+ if (modified) {
237+ /* recalculate new-style checksum */
238+ uint32_t new_checksum = buf_calc_page_new_checksum(page);
239+ new_checksum = mach_read_from_4((uchar *)&new_checksum);
240+ memcpy(page + FIL_PAGE_SPACE_OR_CHKSUM, &new_checksum,
241+ sizeof(new_checksum));
242+
243+ /* recalculate old-style checksum */
244+ uint32_t old_checksum = buf_calc_page_old_checksum(page);
245+ old_checksum = mach_read_from_4((uchar *)&old_checksum);
246+ memcpy(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, &old_checksum,
247+ sizeof(old_checksum));
248+
249+ write_page(file, pos, page);
250+ }
251+
252+ ++page_no;
253+ }
254+
255+ retval = EXIT_SUCCESS;
256+
257+out:
258+ free(index_id_from);
259+ free(index_id_to);
260+ free(page);
261+ if (file != NULL) {
262+ fclose(file);
263+ }
264+ return retval;
265+}

Subscribers

People subscribed via source and target branches