~stewart/drizzle/embedded-innodb-create-select-transaction-arrgh

« back to all changes in this revision

Viewing changes to storage/innobase/row/row0uins.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
Fresh insert undo
 
3
 
 
4
(c) 1996 Innobase Oy
 
5
 
 
6
Created 2/25/1997 Heikki Tuuri
 
7
*******************************************************/
 
8
 
 
9
#include "row0uins.h"
 
10
 
 
11
#ifdef UNIV_NONINL
 
12
#include "row0uins.ic"
 
13
#endif
 
14
 
 
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"
 
31
 
 
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 */
 
41
{
 
42
        btr_cur_t*      btr_cur;
 
43
        ibool           success;
 
44
        ulint           err;
 
45
        ulint           n_tries         = 0;
 
46
        mtr_t           mtr;
 
47
 
 
48
        mtr_start(&mtr);
 
49
 
 
50
        success = btr_pcur_restore_position(BTR_MODIFY_LEAF, &(node->pcur),
 
51
                                            &mtr);
 
52
        ut_a(success);
 
53
 
 
54
        if (ut_dulint_cmp(node->table->id, DICT_INDEXES_ID) == 0) {
 
55
 
 
56
                /* Drop the index tree associated with the row in
 
57
                SYS_INDEXES table: */
 
58
 
 
59
                dict_drop_index_tree(btr_pcur_get_rec(&(node->pcur)), &mtr);
 
60
 
 
61
                mtr_commit(&mtr);
 
62
 
 
63
                mtr_start(&mtr);
 
64
 
 
65
                success = btr_pcur_restore_position(BTR_MODIFY_LEAF,
 
66
                                                    &(node->pcur), &mtr);
 
67
                ut_a(success);
 
68
        }
 
69
 
 
70
        btr_cur = btr_pcur_get_btr_cur(&(node->pcur));
 
71
 
 
72
        success = btr_cur_optimistic_delete(btr_cur, &mtr);
 
73
 
 
74
        btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
 
75
 
 
76
        if (success) {
 
77
                trx_undo_rec_release(node->trx, node->undo_no);
 
78
 
 
79
                return(DB_SUCCESS);
 
80
        }
 
81
retry:
 
82
        /* If did not succeed, try pessimistic descent to tree */
 
83
        mtr_start(&mtr);
 
84
 
 
85
        success = btr_pcur_restore_position(BTR_MODIFY_TREE,
 
86
                                            &(node->pcur), &mtr);
 
87
        ut_a(success);
 
88
 
 
89
        btr_cur_pessimistic_delete(&err, FALSE, btr_cur, TRUE, &mtr);
 
90
 
 
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 */
 
94
 
 
95
        if (err == DB_OUT_OF_FILE_SPACE
 
96
            && n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
 
97
 
 
98
                btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
 
99
 
 
100
                n_tries++;
 
101
 
 
102
                os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
 
103
 
 
104
                goto retry;
 
105
        }
 
106
 
 
107
        btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
 
108
 
 
109
        trx_undo_rec_release(node->trx, node->undo_no);
 
110
 
 
111
        return(err);
 
112
}
 
113
 
 
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 */
 
127
{
 
128
        btr_pcur_t      pcur;
 
129
        btr_cur_t*      btr_cur;
 
130
        ibool           found;
 
131
        ibool           success;
 
132
        ulint           err;
 
133
        mtr_t           mtr;
 
134
 
 
135
        log_free_check();
 
136
        mtr_start(&mtr);
 
137
 
 
138
        found = row_search_index_entry(index, entry, mode, &pcur, &mtr);
 
139
 
 
140
        btr_cur = btr_pcur_get_btr_cur(&pcur);
 
141
 
 
142
        if (!found) {
 
143
                /* Not found */
 
144
 
 
145
                btr_pcur_close(&pcur);
 
146
                mtr_commit(&mtr);
 
147
 
 
148
                return(DB_SUCCESS);
 
149
        }
 
150
 
 
151
        if (mode == BTR_MODIFY_LEAF) {
 
152
                success = btr_cur_optimistic_delete(btr_cur, &mtr);
 
153
 
 
154
                if (success) {
 
155
                        err = DB_SUCCESS;
 
156
                } else {
 
157
                        err = DB_FAIL;
 
158
                }
 
159
        } else {
 
160
                ut_ad(mode == BTR_MODIFY_TREE);
 
161
 
 
162
                btr_cur_pessimistic_delete(&err, FALSE, btr_cur, TRUE, &mtr);
 
163
        }
 
164
 
 
165
        btr_pcur_close(&pcur);
 
166
        mtr_commit(&mtr);
 
167
 
 
168
        return(err);
 
169
}
 
170
 
 
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 */
 
181
{
 
182
        ulint   err;
 
183
        ulint   n_tries = 0;
 
184
 
 
185
        /* Try first optimistic descent to the B-tree */
 
186
 
 
187
        err = row_undo_ins_remove_sec_low(BTR_MODIFY_LEAF, index, entry);
 
188
 
 
189
        if (err == DB_SUCCESS) {
 
190
 
 
191
                return(err);
 
192
        }
 
193
 
 
194
        /* Try then pessimistic descent to the B-tree */
 
195
retry:
 
196
        err = row_undo_ins_remove_sec_low(BTR_MODIFY_TREE, index, entry);
 
197
 
 
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 */
 
201
 
 
202
        if (err != DB_SUCCESS && n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
 
203
 
 
204
                n_tries++;
 
205
 
 
206
                os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
 
207
 
 
208
                goto retry;
 
209
        }
 
210
 
 
211
        return(err);
 
212
}
 
213
 
 
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 */
 
221
{
 
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;
 
229
 
 
230
        ut_ad(node);
 
231
 
 
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;
 
236
 
 
237
        node->table = dict_table_get_on_id(table_id, node->trx);
 
238
 
 
239
        if (node->table == NULL) {
 
240
 
 
241
                return;
 
242
        }
 
243
 
 
244
        if (node->table->ibd_file_missing) {
 
245
                /* We skip undo operations to missing .ibd files */
 
246
                node->table = NULL;
 
247
 
 
248
                return;
 
249
        }
 
250
 
 
251
        clust_index = dict_table_get_first_index(node->table);
 
252
 
 
253
        ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref),
 
254
                                       node->heap);
 
255
}
 
256
 
 
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. */
 
261
 
 
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 */
 
267
{
 
268
        dtuple_t*       entry;
 
269
        ibool           found;
 
270
        ulint           err;
 
271
 
 
272
        ut_ad(node);
 
273
        ut_ad(node->state == UNDO_NODE_INSERT);
 
274
 
 
275
        row_undo_ins_parse_undo_rec(node);
 
276
 
 
277
        if (node->table == NULL) {
 
278
                found = FALSE;
 
279
        } else {
 
280
                found = row_undo_search_clust_to_pcur(node);
 
281
        }
 
282
 
 
283
        if (!found) {
 
284
                trx_undo_rec_release(node->trx, node->undo_no);
 
285
 
 
286
                return(DB_SUCCESS);
 
287
        }
 
288
 
 
289
        node->index = dict_table_get_next_index(
 
290
                dict_table_get_first_index(node->table));
 
291
 
 
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);
 
296
 
 
297
                if (err != DB_SUCCESS) {
 
298
 
 
299
                        return(err);
 
300
                }
 
301
 
 
302
                node->index = dict_table_get_next_index(node->index);
 
303
        }
 
304
 
 
305
        err = row_undo_ins_remove_clust_rec(node);
 
306
 
 
307
        return(err);
 
308
}