~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2009-09-30 07:01:32 UTC
  • mto: This revision was merged to the branch mainline in revision 1184.
  • Revision ID: mordred@inaugust.com-20090930070132-b1ol1xu1rpajdddy
Small namespace cleanup.

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
 
}