~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2008-10-27 23:19:48 UTC
  • mto: (520.4.12 merge-innodb-plugin)
  • mto: This revision was merged to the branch mainline in revision 563.
  • Revision ID: monty@inaugust.com-20081027231948-3kl6ss04plbakqcr
Split some more things out of common_includes.h.

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,
91
 
                                   trx_is_recv(node->trx)
92
 
                                   ? RB_RECOVERY
93
 
                                   : RB_NORMAL, &mtr);
94
 
 
95
 
        /* The delete operation may fail if we have little
96
 
        file space left: TODO: easiest to crash the database
97
 
        and restart with more file space */
98
 
 
99
 
        if (err == DB_OUT_OF_FILE_SPACE
100
 
            && n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
101
 
 
102
 
                btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
103
 
 
104
 
                n_tries++;
105
 
 
106
 
                os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
107
 
 
108
 
                goto retry;
109
 
        }
110
 
 
111
 
        btr_pcur_commit_specify_mtr(&(node->pcur), &mtr);
112
 
 
113
 
        trx_undo_rec_release(node->trx, node->undo_no);
114
 
 
115
 
        return(err);
116
 
}
117
 
 
118
 
/*******************************************************************
119
 
Removes a secondary index entry if found. */
120
 
static
121
 
ulint
122
 
row_undo_ins_remove_sec_low(
123
 
/*========================*/
124
 
                                /* out: DB_SUCCESS, DB_FAIL, or
125
 
                                DB_OUT_OF_FILE_SPACE */
126
 
        ulint           mode,   /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
127
 
                                depending on whether we wish optimistic or
128
 
                                pessimistic descent down the index tree */
129
 
        dict_index_t*   index,  /* in: index */
130
 
        dtuple_t*       entry)  /* in: index entry to remove */
131
 
{
132
 
        btr_pcur_t      pcur;
133
 
        btr_cur_t*      btr_cur;
134
 
        ibool           found;
135
 
        ibool           success;
136
 
        ulint           err;
137
 
        mtr_t           mtr;
138
 
 
139
 
        log_free_check();
140
 
        mtr_start(&mtr);
141
 
 
142
 
        found = row_search_index_entry(index, entry, mode, &pcur, &mtr);
143
 
 
144
 
        btr_cur = btr_pcur_get_btr_cur(&pcur);
145
 
 
146
 
        if (!found) {
147
 
                /* Not found */
148
 
 
149
 
                btr_pcur_close(&pcur);
150
 
                mtr_commit(&mtr);
151
 
 
152
 
                return(DB_SUCCESS);
153
 
        }
154
 
 
155
 
        if (mode == BTR_MODIFY_LEAF) {
156
 
                success = btr_cur_optimistic_delete(btr_cur, &mtr);
157
 
 
158
 
                if (success) {
159
 
                        err = DB_SUCCESS;
160
 
                } else {
161
 
                        err = DB_FAIL;
162
 
                }
163
 
        } else {
164
 
                ut_ad(mode == BTR_MODIFY_TREE);
165
 
 
166
 
                /* No need to distinguish RB_RECOVERY here, because we
167
 
                are deleting a secondary index record: the distinction
168
 
                between RB_NORMAL and RB_RECOVERY only matters when
169
 
                deleting a record that contains externally stored
170
 
                columns. */
171
 
                ut_ad(!dict_index_is_clust(index));
172
 
                btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
173
 
                                           RB_NORMAL, &mtr);
174
 
        }
175
 
 
176
 
        btr_pcur_close(&pcur);
177
 
        mtr_commit(&mtr);
178
 
 
179
 
        return(err);
180
 
}
181
 
 
182
 
/*******************************************************************
183
 
Removes a secondary index entry from the index if found. Tries first
184
 
optimistic, then pessimistic descent down the tree. */
185
 
static
186
 
ulint
187
 
row_undo_ins_remove_sec(
188
 
/*====================*/
189
 
                                /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
190
 
        dict_index_t*   index,  /* in: index */
191
 
        dtuple_t*       entry)  /* in: index entry to insert */
192
 
{
193
 
        ulint   err;
194
 
        ulint   n_tries = 0;
195
 
 
196
 
        /* Try first optimistic descent to the B-tree */
197
 
 
198
 
        err = row_undo_ins_remove_sec_low(BTR_MODIFY_LEAF, index, entry);
199
 
 
200
 
        if (err == DB_SUCCESS) {
201
 
 
202
 
                return(err);
203
 
        }
204
 
 
205
 
        /* Try then pessimistic descent to the B-tree */
206
 
retry:
207
 
        err = row_undo_ins_remove_sec_low(BTR_MODIFY_TREE, index, entry);
208
 
 
209
 
        /* The delete operation may fail if we have little
210
 
        file space left: TODO: easiest to crash the database
211
 
        and restart with more file space */
212
 
 
213
 
        if (err != DB_SUCCESS && n_tries < BTR_CUR_RETRY_DELETE_N_TIMES) {
214
 
 
215
 
                n_tries++;
216
 
 
217
 
                os_thread_sleep(BTR_CUR_RETRY_SLEEP_TIME);
218
 
 
219
 
                goto retry;
220
 
        }
221
 
 
222
 
        return(err);
223
 
}
224
 
 
225
 
/***************************************************************
226
 
Parses the row reference and other info in a fresh insert undo record. */
227
 
static
228
 
void
229
 
row_undo_ins_parse_undo_rec(
230
 
/*========================*/
231
 
        undo_node_t*    node)   /* in/out: row undo node */
232
 
{
233
 
        dict_index_t*   clust_index;
234
 
        byte*           ptr;
235
 
        dulint          undo_no;
236
 
        dulint          table_id;
237
 
        ulint           type;
238
 
        ulint           dummy;
239
 
        ibool           dummy_extern;
240
 
 
241
 
        ut_ad(node);
242
 
 
243
 
        ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &dummy,
244
 
                                    &dummy_extern, &undo_no, &table_id);
245
 
        ut_ad(type == TRX_UNDO_INSERT_REC);
246
 
        node->rec_type = type;
247
 
 
248
 
        node->update = NULL;
249
 
        node->table = dict_table_get_on_id(table_id, node->trx);
250
 
 
251
 
        /* Skip the UNDO if we can't find the table or the .ibd file. */
252
 
        if (UNIV_UNLIKELY(node->table == NULL)) {
253
 
        } else if (UNIV_UNLIKELY(node->table->ibd_file_missing)) {
254
 
                node->table = NULL;
255
 
        } else {
256
 
                clust_index = dict_table_get_first_index(node->table);
257
 
 
258
 
                if (clust_index != NULL) {
259
 
                        ptr = trx_undo_rec_get_row_ref(
260
 
                                ptr, clust_index, &node->ref, node->heap);
261
 
                } else {
262
 
                        ut_print_timestamp(stderr);
263
 
                        fprintf(stderr, "  InnoDB: table ");
264
 
                        ut_print_name(stderr, node->trx, TRUE,
265
 
                                      node->table->name);
266
 
                        fprintf(stderr, " has no indexes, "
267
 
                                "ignoring the table\n");
268
 
 
269
 
                        node->table = NULL;
270
 
                }
271
 
        }
272
 
}
273
 
 
274
 
/***************************************************************
275
 
Undoes a fresh insert of a row to a table. A fresh insert means that
276
 
the same clustered index unique key did not have any record, even delete
277
 
marked, at the time of the insert. */
278
 
UNIV_INTERN
279
 
ulint
280
 
row_undo_ins(
281
 
/*=========*/
282
 
                                /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
283
 
        undo_node_t*    node)   /* in: row undo node */
284
 
{
285
 
        ut_ad(node);
286
 
        ut_ad(node->state == UNDO_NODE_INSERT);
287
 
 
288
 
        row_undo_ins_parse_undo_rec(node);
289
 
 
290
 
        if (!node->table || !row_undo_search_clust_to_pcur(node)) {
291
 
                trx_undo_rec_release(node->trx, node->undo_no);
292
 
 
293
 
                return(DB_SUCCESS);
294
 
        }
295
 
 
296
 
        /* Iterate over all the indexes and undo the insert.*/
297
 
 
298
 
        /* Skip the clustered index (the first index) */
299
 
        node->index = dict_table_get_next_index(
300
 
                dict_table_get_first_index(node->table));
301
 
 
302
 
        while (node->index != NULL) {
303
 
                dtuple_t*       entry;
304
 
                ulint           err;
305
 
 
306
 
                entry = row_build_index_entry(node->row, node->ext,
307
 
                                              node->index, node->heap);
308
 
                if (UNIV_UNLIKELY(!entry)) {
309
 
                        /* The database must have crashed after
310
 
                        inserting a clustered index record but before
311
 
                        writing all the externally stored columns of
312
 
                        that record.  Because secondary index entries
313
 
                        are inserted after the clustered index record,
314
 
                        we may assume that the secondary index record
315
 
                        does not exist.  However, this situation may
316
 
                        only occur during the rollback of incomplete
317
 
                        transactions. */
318
 
                        ut_a(trx_is_recv(node->trx));
319
 
                } else {
320
 
                        err = row_undo_ins_remove_sec(node->index, entry);
321
 
 
322
 
                        if (err != DB_SUCCESS) {
323
 
 
324
 
                                return(err);
325
 
                        }
326
 
                }
327
 
 
328
 
                node->index = dict_table_get_next_index(node->index);
329
 
        }
330
 
 
331
 
        return(row_undo_ins_remove_clust_rec(node));
332
 
}