1
/* Copyright (C) 2000-2005 MySQL AB & Innobase Oy
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
InnoDB tablespace, table, and index id renamer.
19
Written by Andrew Gaul <andrew@gaul.org>.
21
Published with permission.
25
/* TODO: requires innodb_file_per_table; confused tablespace and table id */
30
#include "page0page.h"
31
#include "innochecksum.h"
33
static void usage(const char *progname)
35
printf("InnoDB tablespace, table, and index id renamer.\n"
36
"usage: %s [OPTIONS]... FILENAME\n"
37
"\t-t ID\tset new tablespace id\n"
38
"\t-I ID\tmap from this index id\n"
39
"\t-i ID\tmap to this index id\n"
40
"\t-v\tverbose output\n",
44
static uint64_t dulint_to_uint64_t(dulint x)
46
return (((uint64_t) x.high) << 32) | x.low;
49
static void write_page(FILE *file, fpos_t pos, const uchar *page)
51
if (0 != fsetpos(file, &pos)) {
52
perror("couldn't set a position to the start of the page");
55
if (1 != fwrite(page, UNIV_PAGE_SIZE, 1, file)) {
56
perror("couldn't update the page");
61
int main(int argc, char **argv)
63
FILE *file = NULL; /* input file */
64
uchar *page = (uchar *)malloc(UNIV_PAGE_SIZE); /* storage for pages read */
65
int bytes; /* bytes read count */
66
ulint page_no = 0; /* current page number (0-based) */
67
int32_t tablespace_id_to = -1;
68
int64_t *index_id_from = malloc(0);
69
size_t index_id_from_size = 0;
70
int64_t *index_id_to = malloc(0);
71
size_t index_id_to_size = 0;
78
int retval = EXIT_FAILURE;
81
while ((c = getopt(argc, argv, "hvt:I:i:")) != -1) {
87
tablespace_id_to = strtol(optarg, &endptr, 10);
88
if (*endptr != '\0') {
89
fprintf(stderr, "invalid value %s\n", optarg);
94
index_id = strtoll(optarg, &endptr, 10);
95
if (*endptr != '\0') {
96
fprintf(stderr, "invalid value %s\n", optarg);
99
index_id_from = realloc(index_id_from,
100
sizeof(*index_id_from) * (index_id_from_size + 1));
101
index_id_from[index_id_from_size++] = index_id;
104
index_id = strtoll(optarg, &endptr, 10);
105
if (*endptr != '\0') {
106
fprintf(stderr, "invalid value %s\n", optarg);
109
index_id_to = realloc(index_id_to,
110
sizeof(*index_id_to) * (index_id_to_size + 1));
111
index_id_to[index_id_to_size++] = index_id;
114
fprintf(stderr, "option -%c requires an argument\n", optopt);
117
fprintf(stderr, "unrecognized option: -%c\n", optopt);
126
/* make sure we have the right arguments */
127
if (optind >= argc) {
132
if (index_id_from_size != index_id_to_size) {
133
fprintf(stderr, "Mismatched -T and -t parameters.\n");
137
file = fopen(argv[optind], "r+");
139
perror("error opening file");
143
while (!feof(file)) {
145
bytes = fread(page, 1, UNIV_PAGE_SIZE, file);
146
if (!bytes && feof(file)) break;
147
if (bytes != UNIV_PAGE_SIZE) {
149
"bytes read (%d) does not match universal page size (%d)\n",
150
bytes, UNIV_PAGE_SIZE);
154
uint16_t type = mach_read_from_2(page + FIL_PAGE_TYPE);
155
uint32_t id = mach_read_from_4((uchar*)&tablespace_id_to);
156
int modified = FALSE;
157
if (type != FIL_PAGE_TYPE_ALLOCATED) {
158
if (tablespace_id_to != -1) {
160
printf("changing tablespace id from %lu to %u at page %lu\n",
161
mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID),
162
tablespace_id_to, page_no);
164
memcpy(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, &id, sizeof(id));
168
if (type == FIL_PAGE_TYPE_FSP_HDR) {
169
if (tablespace_id_to != -1) {
170
memcpy(page + FIL_PAGE_DATA + FSEG_HDR_SPACE, &id, sizeof(id));
173
} else if (type == FIL_PAGE_INDEX) {
174
uint64_t on_disk_index_id = dulint_to_uint64_t(mach_read_from_8(
175
page + FIL_PAGE_DATA + PAGE_INDEX_ID));
176
for (i = 0; i < index_id_from_size; ++i) {
177
if (on_disk_index_id == index_id_from[i]) {
179
printf("changing index id from %" PRIu64 " to %" PRIi64
180
" at page %lu\n", index_id_from[i], index_id_to[i], page_no);
182
uint64_t index_id_to_swapped = dulint_to_uint64_t(mach_read_from_8(
183
(uchar*)&index_id_to[i]));
184
memcpy(page + FIL_PAGE_DATA + PAGE_INDEX_ID, &index_id_to_swapped,
185
sizeof(index_id_to_swapped));
191
if (tablespace_id_to != -1) {
192
memcpy(page + FIL_PAGE_DATA + FSEG_HDR_SPACE + PAGE_BTR_SEG_LEAF, &id,
194
memcpy(page + FIL_PAGE_DATA + FSEG_HDR_SPACE + PAGE_BTR_SEG_TOP, &id,
201
/* recalculate new-style checksum */
202
uint32_t new_checksum = buf_calc_page_new_checksum(page);
203
new_checksum = mach_read_from_4((uchar *)&new_checksum);
204
memcpy(page + FIL_PAGE_SPACE_OR_CHKSUM, &new_checksum,
205
sizeof(new_checksum));
207
/* recalculate old-style checksum */
208
uint32_t old_checksum = buf_calc_page_old_checksum(page);
209
old_checksum = mach_read_from_4((uchar *)&old_checksum);
210
memcpy(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, &old_checksum,
211
sizeof(old_checksum));
213
write_page(file, pos, page);
219
retval = EXIT_SUCCESS;