~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2008-10-29 13:46:43 UTC
  • Revision ID: brian@tangent.org-20081029134643-z6jcwjvyruhk2vlu
Updates for ignore file.

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
                ut_ad(node->trx->dict_operation_lock_mode == RW_X_LATCH);
 
56
 
 
57
                /* Drop the index tree associated with the row in
 
58
                SYS_INDEXES table: */
 
59
 
 
60
                dict_drop_index_tree(btr_pcur_get_rec(&(node->pcur)), &mtr);
 
61
 
 
62
                mtr_commit(&mtr);
 
63
 
 
64
                mtr_start(&mtr);
 
65
 
 
66
                success = btr_pcur_restore_position(BTR_MODIFY_LEAF,
 
67
                                                    &(node->pcur), &mtr);
 
68
                ut_a(success);
 
69
        }
 
70
 
 
71
        btr_cur = btr_pcur_get_btr_cur(&(node->pcur));
 
72
 
 
73
        success = btr_cur_optimistic_delete(btr_cur, &mtr);
 
74
 
 
75
        btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
 
76
 
 
77
        if (success) {
 
78
                trx_undo_rec_release(node->trx, node->undo_no);
 
79
 
 
80
                return(DB_SUCCESS);
 
81
        }
 
82
retry:
 
83
        /* If did not succeed, try pessimistic descent to tree */
 
84
        mtr_start(&mtr);
 
85
 
 
86
        success = btr_pcur_restore_position(BTR_MODIFY_TREE,
 
87
                                            &(node->pcur), &mtr);
 
88
        ut_a(success);
 
89
 
 
90
        btr_cur_pessimistic_delete(&err, FALSE, btr_cur, TRUE, &mtr);
 
91
 
 
92
        /* The delete operation may fail if we have little
 
93
        file space left: TODO: easiest to crash the database
 
94
        and restart with more file space */
 
95
 
 
96
        if (err == DB_OUT_OF_FILE_SPACE
 
97
            && n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
 
98
 
 
99
                btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
 
100
 
 
101
                n_tries++;
 
102
 
 
103
                os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
 
104
 
 
105
                goto retry;
 
106
        }
 
107
 
 
108
        btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
 
109
 
 
110
        trx_undo_rec_release(node->trx, node->undo_no);
 
111
 
 
112
        return(err);
 
113
}
 
114
 
 
115
/*******************************************************************
 
116
Removes a secondary index entry if found. */
 
117
static
 
118
ulint
 
119
row_undo_ins_remove_sec_low(
 
120
/*========================*/
 
121
                                /* out: DB_SUCCESS, DB_FAIL, or
 
122
                                DB_OUT_OF_FILE_SPACE */
 
123
        ulint           mode,   /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
 
124
                                depending on whether we wish optimistic or
 
125
                                pessimistic descent down the index tree */
 
126
        dict_index_t*   index,  /* in: index */
 
127
        dtuple_t*       entry)  /* in: index entry to remove */
 
128
{
 
129
        btr_pcur_t      pcur;
 
130
        btr_cur_t*      btr_cur;
 
131
        ibool           found;
 
132
        ibool           success;
 
133
        ulint           err;
 
134
        mtr_t           mtr;
 
135
 
 
136
        log_free_check();
 
137
        mtr_start(&mtr);
 
138
 
 
139
        found = row_search_index_entry(index, entry, mode, &pcur, &mtr);
 
140
 
 
141
        btr_cur = btr_pcur_get_btr_cur(&pcur);
 
142
 
 
143
        if (!found) {
 
144
                /* Not found */
 
145
 
 
146
                btr_pcur_close(&pcur);
 
147
                mtr_commit(&mtr);
 
148
 
 
149
                return(DB_SUCCESS);
 
150
        }
 
151
 
 
152
        if (mode == BTR_MODIFY_LEAF) {
 
153
                success = btr_cur_optimistic_delete(btr_cur, &mtr);
 
154
 
 
155
                if (success) {
 
156
                        err = DB_SUCCESS;
 
157
                } else {
 
158
                        err = DB_FAIL;
 
159
                }
 
160
        } else {
 
161
                ut_ad(mode == BTR_MODIFY_TREE);
 
162
 
 
163
                btr_cur_pessimistic_delete(&err, FALSE, btr_cur, TRUE, &mtr);
 
164
        }
 
165
 
 
166
        btr_pcur_close(&pcur);
 
167
        mtr_commit(&mtr);
 
168
 
 
169
        return(err);
 
170
}
 
171
 
 
172
/*******************************************************************
 
173
Removes a secondary index entry from the index if found. Tries first
 
174
optimistic, then pessimistic descent down the tree. */
 
175
static
 
176
ulint
 
177
row_undo_ins_remove_sec(
 
178
/*====================*/
 
179
                                /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
 
180
        dict_index_t*   index,  /* in: index */
 
181
        dtuple_t*       entry)  /* in: index entry to insert */
 
182
{
 
183
        ulint   err;
 
184
        ulint   n_tries = 0;
 
185
 
 
186
        /* Try first optimistic descent to the B-tree */
 
187
 
 
188
        err = row_undo_ins_remove_sec_low(BTR_MODIFY_LEAF, index, entry);
 
189
 
 
190
        if (err == DB_SUCCESS) {
 
191
 
 
192
                return(err);
 
193
        }
 
194
 
 
195
        /* Try then pessimistic descent to the B-tree */
 
196
retry:
 
197
        err = row_undo_ins_remove_sec_low(BTR_MODIFY_TREE, index, entry);
 
198
 
 
199
        /* The delete operation may fail if we have little
 
200
        file space left: TODO: easiest to crash the database
 
201
        and restart with more file space */
 
202
 
 
203
        if (err != DB_SUCCESS && n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
 
204
 
 
205
                n_tries++;
 
206
 
 
207
                os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
 
208
 
 
209
                goto retry;
 
210
        }
 
211
 
 
212
        return(err);
 
213
}
 
214
 
 
215
/***************************************************************
 
216
Parses the row reference and other info in a fresh insert undo record. */
 
217
static
 
218
void
 
219
row_undo_ins_parse_undo_rec(
 
220
/*========================*/
 
221
        undo_node_t*    node)   /* in: row undo node */
 
222
{
 
223
        dict_index_t*   clust_index;
 
224
        byte*           ptr;
 
225
        dulint          undo_no;
 
226
        dulint          table_id;
 
227
        ulint           type;
 
228
        ulint           dummy;
 
229
        ibool           dummy_extern;
 
230
 
 
231
        ut_ad(node);
 
232
 
 
233
        ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &dummy,
 
234
                                    &dummy_extern, &undo_no, &table_id);
 
235
        ut_ad(type == TRX_UNDO_INSERT_REC);
 
236
        node->rec_type = type;
 
237
 
 
238
        node->update = NULL;
 
239
        node->table = dict_table_get_on_id(table_id, node->trx);
 
240
 
 
241
        /* Skip the UNDO if we can't find the table or the .ibd file. */
 
242
        if (UNIV_UNLIKELY(node->table == NULL)) {
 
243
        } else if (UNIV_UNLIKELY(node->table->ibd_file_missing)) {
 
244
                node->table = NULL;
 
245
        } else {
 
246
                clust_index = dict_table_get_first_index(node->table);
 
247
 
 
248
                ptr = trx_undo_rec_get_row_ref(
 
249
                        ptr, clust_index, &node->ref, node->heap);
 
250
        }
 
251
}
 
252
 
 
253
/***************************************************************
 
254
Undoes a fresh insert of a row to a table. A fresh insert means that
 
255
the same clustered index unique key did not have any record, even delete
 
256
marked, at the time of the insert. */
 
257
UNIV_INTERN
 
258
ulint
 
259
row_undo_ins(
 
260
/*=========*/
 
261
                                /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
 
262
        undo_node_t*    node)   /* in: row undo node */
 
263
{
 
264
        ut_ad(node);
 
265
        ut_ad(node->state == UNDO_NODE_INSERT);
 
266
 
 
267
        row_undo_ins_parse_undo_rec(node);
 
268
 
 
269
        if (!node->table || !row_undo_search_clust_to_pcur(node)) {
 
270
                trx_undo_rec_release(node->trx, node->undo_no);
 
271
 
 
272
                return(DB_SUCCESS);
 
273
        }
 
274
 
 
275
        /* Iterate over all the indexes and undo the insert.*/
 
276
 
 
277
        /* Skip the clustered index (the first index) */
 
278
        node->index = dict_table_get_next_index(
 
279
                dict_table_get_first_index(node->table));
 
280
 
 
281
        while (node->index != NULL) {
 
282
                dtuple_t*       entry;
 
283
                ulint           err;
 
284
 
 
285
                entry = row_build_index_entry(node->row, node->ext,
 
286
                                              node->index, node->heap);
 
287
                ut_a(entry);
 
288
                err = row_undo_ins_remove_sec(node->index, entry);
 
289
 
 
290
                if (err != DB_SUCCESS) {
 
291
 
 
292
                        return(err);
 
293
                }
 
294
 
 
295
                node->index = dict_table_get_next_index(node->index);
 
296
        }
 
297
 
 
298
        return(row_undo_ins_remove_clust_rec(node));
 
299
}