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 : /* Remove all rows from a MARIA table */
17 : /* This clears the status information and truncates files */
18 :
19 : #include "maria_def.h"
20 : #include "trnman.h"
21 :
22 : /**
23 : @brief deletes all rows from a table
24 :
25 : @param info Maria handler
26 :
27 : @note It is important that this function does not rely on the state
28 : information, as it may be called by ma_apply_undo_bulk_insert() on an
29 : inconsistent table left by a crash.
30 :
31 : @return Operation status
32 : @retval 0 ok
33 : @retval 1 error
34 : */
35 :
36 : int maria_delete_all_rows(MARIA_HA *info)
37 0 : {
38 0 : MARIA_SHARE *share= info->s;
39 : my_bool log_record;
40 : LSN lsn;
41 0 : DBUG_ENTER("maria_delete_all_rows");
42 :
43 0 : if (share->options & HA_OPTION_READ_ONLY_DATA)
44 : {
45 0 : DBUG_RETURN(my_errno=EACCES);
46 : }
47 : /**
48 : @todo LOCK take X-lock on table here.
49 : When we have versioning, if some other thread is looking at this table,
50 : we cannot shrink the file like this.
51 : */
52 0 : if (_ma_readinfo(info,F_WRLCK,1))
53 0 : DBUG_RETURN(my_errno);
54 0 : log_record= share->now_transactional && !share->temporary;
55 0 : if (_ma_mark_file_changed(info))
56 0 : goto err;
57 :
58 0 : if (log_record)
59 : {
60 : /*
61 : This record will be used by Recovery to finish the deletion if it
62 : crashed. We force it to have a complete history in the log.
63 : */
64 : LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 1];
65 : uchar log_data[FILEID_STORE_SIZE];
66 0 : log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data;
67 0 : log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data);
68 0 : if (unlikely(translog_write_record(&lsn, LOGREC_REDO_DELETE_ALL,
69 : info->trn, info, 0,
70 : sizeof(log_array)/sizeof(log_array[0]),
71 : log_array, log_data, NULL) ||
72 : translog_flush(lsn)))
73 : goto err;
74 : /*
75 : If we fail in this function after this point, log and table will be
76 : inconsistent.
77 : */
78 : }
79 : else
80 : {
81 : /* Other branch called function below when writing log record, in hook */
82 0 : _ma_reset_status(info);
83 : }
84 : /* Remove old history as the table is now empty for everyone */
85 0 : _ma_reset_state(info);
86 :
87 : /*
88 : If we are using delayed keys or if the user has done changes to the tables
89 : since it was locked then there may be key blocks in the page cache. Or
90 : there may be data blocks there. We need to throw them away or they may
91 : re-enter the emptied table or another table later.
92 : */
93 :
94 : #ifdef HAVE_MMAP
95 0 : if (share->file_map)
96 0 : _ma_unmap_file(info);
97 : #endif
98 :
99 0 : if (_ma_flush_table_files(info, MARIA_FLUSH_DATA|MARIA_FLUSH_INDEX,
100 : FLUSH_IGNORE_CHANGED, FLUSH_IGNORE_CHANGED) ||
101 : my_chsize(info->dfile.file, 0, 0, MYF(MY_WME)) ||
102 : my_chsize(share->kfile.file, share->base.keystart, 0, MYF(MY_WME)))
103 : goto err;
104 :
105 0 : if (_ma_initialize_data_file(share, info->dfile.file))
106 0 : goto err;
107 :
108 0 : if (log_record)
109 : {
110 : /*
111 : Because LOGREC_REDO_DELETE_ALL does not operate on pages, it has the
112 : following problem:
113 : delete_all; inserts (redo_insert); all pages get flushed; checkpoint:
114 : the dirty pages list will be empty. In recovery, delete_all is executed,
115 : but redo_insert are skipped (dirty pages list is empty).
116 : To avoid this, we need to set skip_redo_lsn now, and thus need to sync
117 : files.
118 : Also fixes the problem of:
119 : bulk insert; insert; delete_all; crash:
120 : "bulk insert" is skipped (no REDOs), so if "insert" would not be skipped
121 : (if we didn't update skip_redo_lsn below) then "insert" would be tried
122 : and fail, saying that it sees that the first page has to be created
123 : though the inserted row has rownr>0.
124 : */
125 : my_bool error= _ma_state_info_write(share,
126 : MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET |
127 : MA_STATE_INFO_WRITE_LOCK) ||
128 : _ma_update_state_lsns(share, lsn, trnman_get_min_trid(), FALSE, FALSE) ||
129 0 : _ma_sync_table_files(info);
130 0 : info->trn->rec_lsn= LSN_IMPOSSIBLE;
131 0 : if (error)
132 0 : goto err;
133 : }
134 :
135 0 : VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
136 : #ifdef HAVE_MMAP
137 : /* Map again */
138 0 : if (share->file_map)
139 0 : _ma_dynmap_file(info, (my_off_t) 0);
140 : #endif
141 : allow_break(); /* Allow SIGHUP & SIGINT */
142 0 : DBUG_RETURN(0);
143 :
144 0 : err:
145 : {
146 0 : int save_errno=my_errno;
147 0 : VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
148 0 : info->update|=HA_STATE_WRITTEN; /* Buffer changed */
149 : allow_break(); /* Allow SIGHUP & SIGINT */
150 0 : DBUG_RETURN(my_errno=save_errno);
151 : }
152 : } /* maria_delete_all_rows */
153 :
154 :
155 : /*
156 : Reset status information
157 :
158 : SYNOPSIS
159 : _ma_reset_status()
160 : maria Maria handler
161 :
162 : DESCRIPTION
163 : Resets data and index file information as if the file would be empty
164 : Files are not touched.
165 : */
166 :
167 : void _ma_reset_status(MARIA_HA *info)
168 45 : {
169 45 : MARIA_SHARE *share= info->s;
170 45 : MARIA_STATE_INFO *state= &share->state;
171 : uint i;
172 45 : DBUG_ENTER("_ma_reset_status");
173 :
174 45 : state->split= 0;
175 45 : state->state.records= state->state.del= 0;
176 45 : state->changed= 0; /* File is optimized */
177 45 : state->dellink= HA_OFFSET_ERROR;
178 45 : state->sortkey= (ushort) ~0;
179 45 : state->state.key_file_length= share->base.keystart;
180 45 : state->state.data_file_length= 0;
181 45 : state->state.empty= state->state.key_empty= 0;
182 45 : state->state.checksum= 0;
183 :
184 45 : *info->state= state->state;
185 :
186 : /* Drop the delete key chain. */
187 45 : state->key_del= HA_OFFSET_ERROR;
188 : /* Clear all keys */
189 165 : for (i=0 ; i < share->base.keys ; i++)
190 120 : state->key_root[i]= HA_OFFSET_ERROR;
191 45 : DBUG_VOID_RETURN;
192 : }
|