mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / innobase / row / row0uins.c
blobce9ab792204ae7449b435c973a9f24c61ef47032
1 /******************************************************
2 Fresh insert undo
4 (c) 1996 Innobase Oy
6 Created 2/25/1997 Heikki Tuuri
7 *******************************************************/
9 #include "row0uins.h"
11 #ifdef UNIV_NONINL
12 #include "row0uins.ic"
13 #endif
15 #include "dict0dict.h"
16 #include "dict0boot.h"
17 #include "dict0crea.h"
18 #include "trx0undo.h"
19 #include "trx0roll.h"
20 #include "btr0btr.h"
21 #include "mach0data.h"
22 #include "row0undo.h"
23 #include "row0vers.h"
24 #include "trx0trx.h"
25 #include "trx0rec.h"
26 #include "row0row.h"
27 #include "row0upd.h"
28 #include "que0que.h"
29 #include "ibuf0ibuf.h"
30 #include "log0log.h"
32 /*******************************************************************
33 Removes a clustered index record. The pcur in node was positioned on the
34 record, now it is detached. */
35 static
36 ulint
37 row_undo_ins_remove_clust_rec(
38 /*==========================*/
39 /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
40 undo_node_t* node) /* in: undo node */
42 btr_cur_t* btr_cur;
43 ibool success;
44 ulint err;
45 ulint n_tries = 0;
46 mtr_t mtr;
48 mtr_start(&mtr);
50 success = btr_pcur_restore_position(BTR_MODIFY_LEAF, &(node->pcur),
51 &mtr);
52 ut_a(success);
54 if (ut_dulint_cmp(node->table->id, DICT_INDEXES_ID) == 0) {
56 /* Drop the index tree associated with the row in
57 SYS_INDEXES table: */
59 dict_drop_index_tree(btr_pcur_get_rec(&(node->pcur)), &mtr);
61 mtr_commit(&mtr);
63 mtr_start(&mtr);
65 success = btr_pcur_restore_position(BTR_MODIFY_LEAF,
66 &(node->pcur), &mtr);
67 ut_a(success);
70 btr_cur = btr_pcur_get_btr_cur(&(node->pcur));
72 success = btr_cur_optimistic_delete(btr_cur, &mtr);
74 btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
76 if (success) {
77 trx_undo_rec_release(node->trx, node->undo_no);
79 return(DB_SUCCESS);
81 retry:
82 /* If did not succeed, try pessimistic descent to tree */
83 mtr_start(&mtr);
85 success = btr_pcur_restore_position(BTR_MODIFY_TREE,
86 &(node->pcur), &mtr);
87 ut_a(success);
89 btr_cur_pessimistic_delete(&err, FALSE, btr_cur, TRUE, &mtr);
91 /* The delete operation may fail if we have little
92 file space left: TODO: easiest to crash the database
93 and restart with more file space */
95 if (err == DB_OUT_OF_FILE_SPACE
96 && n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
98 btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
100 n_tries++;
102 os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
104 goto retry;
107 btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
109 trx_undo_rec_release(node->trx, node->undo_no);
111 return(err);
114 /*******************************************************************
115 Removes a secondary index entry if found. */
116 static
117 ulint
118 row_undo_ins_remove_sec_low(
119 /*========================*/
120 /* out: DB_SUCCESS, DB_FAIL, or
121 DB_OUT_OF_FILE_SPACE */
122 ulint mode, /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
123 depending on whether we wish optimistic or
124 pessimistic descent down the index tree */
125 dict_index_t* index, /* in: index */
126 dtuple_t* entry) /* in: index entry to remove */
128 btr_pcur_t pcur;
129 btr_cur_t* btr_cur;
130 ibool found;
131 ibool success;
132 ulint err;
133 mtr_t mtr;
135 log_free_check();
136 mtr_start(&mtr);
138 found = row_search_index_entry(index, entry, mode, &pcur, &mtr);
140 btr_cur = btr_pcur_get_btr_cur(&pcur);
142 if (!found) {
143 /* Not found */
145 btr_pcur_close(&pcur);
146 mtr_commit(&mtr);
148 return(DB_SUCCESS);
151 if (mode == BTR_MODIFY_LEAF) {
152 success = btr_cur_optimistic_delete(btr_cur, &mtr);
154 if (success) {
155 err = DB_SUCCESS;
156 } else {
157 err = DB_FAIL;
159 } else {
160 ut_ad(mode == BTR_MODIFY_TREE);
162 btr_cur_pessimistic_delete(&err, FALSE, btr_cur, TRUE, &mtr);
165 btr_pcur_close(&pcur);
166 mtr_commit(&mtr);
168 return(err);
171 /*******************************************************************
172 Removes a secondary index entry from the index if found. Tries first
173 optimistic, then pessimistic descent down the tree. */
174 static
175 ulint
176 row_undo_ins_remove_sec(
177 /*====================*/
178 /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
179 dict_index_t* index, /* in: index */
180 dtuple_t* entry) /* in: index entry to insert */
182 ulint err;
183 ulint n_tries = 0;
185 /* Try first optimistic descent to the B-tree */
187 err = row_undo_ins_remove_sec_low(BTR_MODIFY_LEAF, index, entry);
189 if (err == DB_SUCCESS) {
191 return(err);
194 /* Try then pessimistic descent to the B-tree */
195 retry:
196 err = row_undo_ins_remove_sec_low(BTR_MODIFY_TREE, index, entry);
198 /* The delete operation may fail if we have little
199 file space left: TODO: easiest to crash the database
200 and restart with more file space */
202 if (err != DB_SUCCESS && n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
204 n_tries++;
206 os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
208 goto retry;
211 return(err);
214 /***************************************************************
215 Parses the row reference and other info in a fresh insert undo record. */
216 static
217 void
218 row_undo_ins_parse_undo_rec(
219 /*========================*/
220 undo_node_t* node) /* in: row undo node */
222 dict_index_t* clust_index;
223 byte* ptr;
224 dulint undo_no;
225 dulint table_id;
226 ulint type;
227 ulint dummy;
228 ibool dummy_extern;
230 ut_ad(node);
232 ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &dummy,
233 &dummy_extern, &undo_no, &table_id);
234 ut_ad(type == TRX_UNDO_INSERT_REC);
235 node->rec_type = type;
237 node->table = dict_table_get_on_id(table_id, node->trx);
239 if (node->table == NULL) {
241 return;
244 if (node->table->ibd_file_missing) {
245 /* We skip undo operations to missing .ibd files */
246 node->table = NULL;
248 return;
251 clust_index = dict_table_get_first_index(node->table);
253 ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref),
254 node->heap);
257 /***************************************************************
258 Undoes a fresh insert of a row to a table. A fresh insert means that
259 the same clustered index unique key did not have any record, even delete
260 marked, at the time of the insert. */
262 ulint
263 row_undo_ins(
264 /*=========*/
265 /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
266 undo_node_t* node) /* in: row undo node */
268 dtuple_t* entry;
269 ibool found;
270 ulint err;
272 ut_ad(node);
273 ut_ad(node->state == UNDO_NODE_INSERT);
275 row_undo_ins_parse_undo_rec(node);
277 if (node->table == NULL) {
278 found = FALSE;
279 } else {
280 found = row_undo_search_clust_to_pcur(node);
283 if (!found) {
284 trx_undo_rec_release(node->trx, node->undo_no);
286 return(DB_SUCCESS);
289 node->index = dict_table_get_next_index(
290 dict_table_get_first_index(node->table));
292 while (node->index != NULL) {
293 entry = row_build_index_entry(node->row, node->index,
294 node->heap);
295 err = row_undo_ins_remove_sec(node->index, entry);
297 if (err != DB_SUCCESS) {
299 return(err);
302 node->index = dict_table_get_next_index(node->index);
305 err = row_undo_ins_remove_clust_rec(node);
307 return(err);