1 : /* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
2 :
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.
6 :
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.
11 :
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 */
15 :
16 : /*
17 : Rename a table
18 : */
19 :
20 : #include "ma_fulltext.h"
21 : #include "trnman_public.h"
22 :
23 : /**
24 : @brief renames a table
25 :
26 : @param old_name current name of table
27 : @param new_name table should be renamed to this name
28 :
29 : @return Operation status
30 : @retval 0 OK
31 : @retval !=0 Error
32 : */
33 :
34 : int maria_rename(const char *old_name, const char *new_name)
35 0 : {
36 : char from[FN_REFLEN],to[FN_REFLEN];
37 : int data_file_rename_error;
38 : #ifdef USE_RAID
39 : uint raid_type=0,raid_chunks=0;
40 : #endif
41 : MARIA_HA *info;
42 : MARIA_SHARE *share;
43 : myf sync_dir;
44 0 : DBUG_ENTER("maria_rename");
45 :
46 : #ifdef EXTRA_DEBUG
47 0 : _ma_check_table_is_closed(old_name,"rename old_table");
48 0 : _ma_check_table_is_closed(new_name,"rename new table2");
49 : #endif
50 : /** @todo LOCK take X-lock on table */
51 0 : if (!(info= maria_open(old_name, O_RDWR, HA_OPEN_FOR_REPAIR)))
52 0 : DBUG_RETURN(my_errno);
53 0 : share= info->s;
54 : #ifdef USE_RAID
55 : raid_type = share->base.raid_type;
56 : raid_chunks = share->base.raid_chunks;
57 : #endif
58 :
59 : /*
60 : the renaming of an internal table to the final table (like in ALTER TABLE)
61 : is the moment when this table receives its correct create_rename_lsn and
62 : this is important; make sure transactionality has been re-enabled.
63 : */
64 0 : DBUG_ASSERT(share->now_transactional == share->base.born_transactional);
65 0 : sync_dir= (share->now_transactional && !share->temporary &&
66 : !maria_in_recovery) ? MY_SYNC_DIR : 0;
67 0 : if (sync_dir)
68 : {
69 : LSN lsn;
70 : LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 2];
71 0 : uint old_name_len= strlen(old_name)+1, new_name_len= strlen(new_name)+1;
72 0 : log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (uchar*)old_name;
73 0 : log_array[TRANSLOG_INTERNAL_PARTS + 0].length= old_name_len;
74 0 : log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (uchar*)new_name;
75 0 : log_array[TRANSLOG_INTERNAL_PARTS + 1].length= new_name_len;
76 : /*
77 : For this record to be of any use for Recovery, we need the upper
78 : MySQL layer to be crash-safe, which it is not now (that would require
79 : work using the ddl_log of sql/sql_table.cc); when it is, we should
80 : reconsider the moment of writing this log record (before or after op,
81 : under THR_LOCK_maria or not...), how to use it in Recovery.
82 : For now it can serve to apply logs to a backup so we sync it.
83 : */
84 0 : if (unlikely(translog_write_record(&lsn, LOGREC_REDO_RENAME_TABLE,
85 : &dummy_transaction_object, NULL,
86 : old_name_len + new_name_len,
87 : sizeof(log_array)/sizeof(log_array[0]),
88 : log_array, NULL, NULL) ||
89 : translog_flush(lsn)))
90 : {
91 0 : maria_close(info);
92 0 : DBUG_RETURN(1);
93 : }
94 : /*
95 : store LSN into file, needed for Recovery to not be confused if a
96 : RENAME happened (applying REDOs to the wrong table).
97 : */
98 0 : if (_ma_update_state_lsns(share, lsn, share->state.create_trid, TRUE,
99 : TRUE))
100 : {
101 0 : maria_close(info);
102 0 : DBUG_RETURN(1);
103 : }
104 : }
105 :
106 0 : maria_close(info);
107 :
108 0 : fn_format(from,old_name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
109 0 : fn_format(to,new_name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
110 0 : if (my_rename_with_symlink(from, to, MYF(MY_WME | sync_dir)))
111 0 : DBUG_RETURN(my_errno);
112 0 : fn_format(from,old_name,"",MARIA_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
113 0 : fn_format(to,new_name,"",MARIA_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
114 : #ifdef USE_RAID
115 : if (raid_type)
116 : data_file_rename_error= my_raid_rename(from, to, raid_chunks,
117 : MYF(MY_WME | sync_dir));
118 : else
119 : #endif
120 0 : data_file_rename_error=
121 : my_rename_with_symlink(from, to, MYF(MY_WME | sync_dir));
122 0 : if (data_file_rename_error)
123 : {
124 : /*
125 : now we have a renamed index file and a non-renamed data file, try to
126 : undo the rename of the index file.
127 : */
128 0 : data_file_rename_error= my_errno;
129 0 : fn_format(from, old_name, "", MARIA_NAME_IEXT, MYF(MY_UNPACK_FILENAME|MY_APPEND_EXT));
130 0 : fn_format(to, new_name, "", MARIA_NAME_IEXT, MYF(MY_UNPACK_FILENAME|MY_APPEND_EXT));
131 0 : my_rename_with_symlink(to, from, MYF(MY_WME | sync_dir));
132 : }
133 0 : DBUG_RETURN(data_file_rename_error);
134 :
135 : }
|