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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 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 | { |
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 | DBUG_ENTER("maria_rename" ); |
45 | |
46 | #ifdef EXTRA_DEBUG |
47 | _ma_check_table_is_closed(old_name,"rename old_table" ); |
48 | _ma_check_table_is_closed(new_name,"rename new table2" ); |
49 | #endif |
50 | /** @todo LOCK take X-lock on table */ |
51 | if (!(info= maria_open(old_name, O_RDWR, HA_OPEN_FOR_REPAIR))) |
52 | DBUG_RETURN(my_errno); |
53 | 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 | DBUG_ASSERT(share->now_transactional == share->base.born_transactional); |
65 | sync_dir= (share->now_transactional && !share->temporary && |
66 | !maria_in_recovery) ? MY_SYNC_DIR : 0; |
67 | if (sync_dir) |
68 | { |
69 | LSN lsn; |
70 | LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; |
71 | size_t old_name_len= strlen(old_name)+1, new_name_len= strlen(new_name)+1; |
72 | log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (uchar*)old_name; |
73 | log_array[TRANSLOG_INTERNAL_PARTS + 0].length= old_name_len; |
74 | log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (uchar*)new_name; |
75 | 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 | if (unlikely(translog_write_record(&lsn, LOGREC_REDO_RENAME_TABLE, |
85 | &dummy_transaction_object, NULL, |
86 | (translog_size_t)(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 | maria_close(info); |
92 | 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 | if (_ma_update_state_lsns(share, lsn, share->state.create_trid, TRUE, |
99 | TRUE)) |
100 | { |
101 | maria_close(info); |
102 | DBUG_RETURN(1); |
103 | } |
104 | } |
105 | |
106 | _ma_reset_state(info); |
107 | maria_close(info); |
108 | |
109 | fn_format(from,old_name,"" ,MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT); |
110 | fn_format(to,new_name,"" ,MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT); |
111 | if (mysql_file_rename_with_symlink(key_file_kfile, from, to, |
112 | MYF(MY_WME | sync_dir))) |
113 | DBUG_RETURN(my_errno); |
114 | fn_format(from,old_name,"" ,MARIA_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT); |
115 | fn_format(to,new_name,"" ,MARIA_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT); |
116 | data_file_rename_error= |
117 | mysql_file_rename_with_symlink(key_file_dfile, from, to, |
118 | MYF(MY_WME | sync_dir)); |
119 | if (data_file_rename_error) |
120 | { |
121 | /* |
122 | now we have a renamed index file and a non-renamed data file, try to |
123 | undo the rename of the index file. |
124 | */ |
125 | data_file_rename_error= my_errno; |
126 | fn_format(from, old_name, "" , MARIA_NAME_IEXT, MYF(MY_UNPACK_FILENAME|MY_APPEND_EXT)); |
127 | fn_format(to, new_name, "" , MARIA_NAME_IEXT, MYF(MY_UNPACK_FILENAME|MY_APPEND_EXT)); |
128 | mysql_file_rename_with_symlink(key_file_kfile, to, from, |
129 | MYF(MY_WME | sync_dir)); |
130 | } |
131 | DBUG_RETURN(data_file_rename_error); |
132 | |
133 | } |
134 | |