~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/btr/btr0pcur.c

  • Committer: Brian Aker
  • Date: 2008-10-28 08:36:02 UTC
  • mfrom: (520.4.13 merge-innodb-plugin)
  • Revision ID: brian@tangent.org-20081028083602-0p3zzlhlxr5q2sqo
Merging Monty's work

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
/******************************************************************
20
20
Allocates memory for a persistent cursor object and initializes the cursor. */
21
 
 
 
21
UNIV_INTERN
22
22
btr_pcur_t*
23
23
btr_pcur_create_for_mysql(void)
24
24
/*============================*/
36
36
 
37
37
/******************************************************************
38
38
Frees the memory for a persistent cursor object. */
39
 
 
 
39
UNIV_INTERN
40
40
void
41
41
btr_pcur_free_for_mysql(
42
42
/*====================*/
67
67
first in an EMPTY tree, or after the last in an EMPTY tree. NOTE that the
68
68
page where the cursor is positioned must not be empty if the index tree is
69
69
not totally empty! */
70
 
 
 
70
UNIV_INTERN
71
71
void
72
72
btr_pcur_store_position(
73
73
/*====================*/
75
75
        mtr_t*          mtr)    /* in: mtr */
76
76
{
77
77
        page_cur_t*     page_cursor;
 
78
        buf_block_t*    block;
78
79
        rec_t*          rec;
79
80
        dict_index_t*   index;
80
81
        page_t*         page;
83
84
        ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
84
85
        ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
85
86
 
 
87
        block = btr_pcur_get_block(cursor);
86
88
        index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor));
87
89
 
88
90
        page_cursor = btr_pcur_get_page_cur(cursor);
91
93
        page = page_align(rec);
92
94
        offs = page_offset(rec);
93
95
 
94
 
        ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
95
 
                                MTR_MEMO_PAGE_S_FIX)
96
 
              || mtr_memo_contains(mtr, buf_block_align(page),
97
 
                                   MTR_MEMO_PAGE_X_FIX));
 
96
        ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_S_FIX)
 
97
              || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
98
98
        ut_a(cursor->latch_mode != BTR_NO_LATCHES);
99
99
 
100
100
        if (UNIV_UNLIKELY(page_get_n_recs(page) == 0)) {
137
137
                index, rec, &cursor->old_n_fields,
138
138
                &cursor->old_rec_buf, &cursor->buf_size);
139
139
 
140
 
        cursor->block_when_stored = buf_block_align(page);
141
 
        cursor->modify_clock = buf_block_get_modify_clock(
142
 
                cursor->block_when_stored);
 
140
        cursor->block_when_stored = block;
 
141
        cursor->modify_clock = buf_block_get_modify_clock(block);
143
142
}
144
143
 
145
144
/******************************************************************
146
145
Copies the stored position of a pcur to another pcur. */
147
 
 
 
146
UNIV_INTERN
148
147
void
149
148
btr_pcur_copy_stored_position(
150
149
/*==========================*/
184
183
GREATER than the user record which was the predecessor of the supremum.
185
184
(4) cursor was positioned before the first or after the last in an empty tree:
186
185
restores to before first or after the last in the tree. */
187
 
 
 
186
UNIV_INTERN
188
187
ibool
189
188
btr_pcur_restore_position(
190
189
/*======================*/
198
197
        mtr_t*          mtr)            /* in: mtr */
199
198
{
200
199
        dict_index_t*   index;
201
 
        page_t*         page;
202
200
        dtuple_t*       tuple;
203
201
        ulint           mode;
204
202
        ulint           old_mode;
217
215
                ut_error;
218
216
        }
219
217
 
220
 
        if (UNIV_UNLIKELY(
221
 
                    cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
222
 
                    || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE)) {
 
218
        if (UNIV_UNLIKELY
 
219
            (cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
 
220
             || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE)) {
223
221
 
224
222
                /* In these cases we do not try an optimistic restoration,
225
223
                but always do a search */
228
226
                        cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
229
227
                        index, latch_mode, btr_pcur_get_btr_cur(cursor), mtr);
230
228
 
231
 
                cursor->block_when_stored
232
 
                        = buf_block_align(btr_pcur_get_page(cursor));
 
229
                cursor->block_when_stored = btr_pcur_get_block(cursor);
233
230
 
234
231
                return(FALSE);
235
232
        }
237
234
        ut_a(cursor->old_rec);
238
235
        ut_a(cursor->old_n_fields);
239
236
 
240
 
        page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor));
241
 
 
242
237
        if (UNIV_LIKELY(latch_mode == BTR_SEARCH_LEAF)
243
238
            || UNIV_LIKELY(latch_mode == BTR_MODIFY_LEAF)) {
244
239
                /* Try optimistic restoration */
245
240
 
246
241
                if (UNIV_LIKELY(buf_page_optimistic_get(
247
242
                                        latch_mode,
248
 
                                        cursor->block_when_stored, page,
 
243
                                        cursor->block_when_stored,
249
244
                                        cursor->modify_clock, mtr))) {
250
245
                        cursor->pos_state = BTR_PCUR_IS_POSITIONED;
251
246
#ifdef UNIV_SYNC_DEBUG
252
 
                        buf_page_dbg_add_level(page, SYNC_TREE_NODE);
 
247
                        buf_block_dbg_add_level(btr_pcur_get_block(cursor),
 
248
                                                SYNC_TREE_NODE);
253
249
#endif /* UNIV_SYNC_DEBUG */
254
250
                        if (cursor->rel_pos == BTR_PCUR_ON) {
255
251
#ifdef UNIV_DEBUG
256
 
                                rec_t*          rec;
257
 
                                ulint*          offsets1;
258
 
                                ulint*          offsets2;
 
252
                                const rec_t*    rec;
 
253
                                const ulint*    offsets1;
 
254
                                const ulint*    offsets2;
259
255
#endif /* UNIV_DEBUG */
260
256
                                cursor->latch_mode = latch_mode;
261
257
#ifdef UNIV_DEBUG
307
303
        cursor->search_mode = old_mode;
308
304
 
309
305
        if (cursor->rel_pos == BTR_PCUR_ON
310
 
            && btr_pcur_is_on_user_rec(cursor, mtr)
 
306
            && btr_pcur_is_on_user_rec(cursor)
311
307
            && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor),
312
308
                                   rec_get_offsets(
313
309
                                           btr_pcur_get_rec(cursor), index,
317
313
                the cursor can now be on a different page! But we can retain
318
314
                the value of old_rec */
319
315
 
320
 
                cursor->block_when_stored = buf_block_align(
321
 
                        btr_pcur_get_page(cursor));
 
316
                cursor->block_when_stored = btr_pcur_get_block(cursor);
322
317
                cursor->modify_clock = buf_block_get_modify_clock(
323
318
                        cursor->block_when_stored);
324
319
                cursor->old_stored = BTR_PCUR_OLD_STORED;
345
340
NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
346
341
made by the current mini-transaction to the data protected by the
347
342
cursor latch, as then the latch must not be released until mtr_commit. */
348
 
 
 
343
UNIV_INTERN
349
344
void
350
345
btr_pcur_release_leaf(
351
346
/*==================*/
352
347
        btr_pcur_t*     cursor, /* in: persistent cursor */
353
348
        mtr_t*          mtr)    /* in: mtr */
354
349
{
355
 
        page_t* page;
 
350
        buf_block_t*    block;
356
351
 
357
352
        ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
358
353
        ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
359
354
 
360
 
        page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor));
 
355
        block = btr_pcur_get_block(cursor);
361
356
 
362
 
        btr_leaf_page_release(page, cursor->latch_mode, mtr);
 
357
        btr_leaf_page_release(block, cursor->latch_mode, mtr);
363
358
 
364
359
        cursor->latch_mode = BTR_NO_LATCHES;
365
360
 
371
366
latch on the current page, and bufferunfixes it. Note that there must not be
372
367
modifications on the current page, as then the x-latch can be released only in
373
368
mtr_commit. */
374
 
 
 
369
UNIV_INTERN
375
370
void
376
371
btr_pcur_move_to_next_page(
377
372
/*=======================*/
379
374
                                last record of the current page */
380
375
        mtr_t*          mtr)    /* in: mtr */
381
376
{
382
 
        ulint   next_page_no;
383
 
        ulint   space;
384
 
        page_t* page;
385
 
        page_t* next_page;
 
377
        ulint           next_page_no;
 
378
        ulint           space;
 
379
        ulint           zip_size;
 
380
        page_t*         page;
 
381
        buf_block_t*    next_block;
 
382
        page_t*         next_page;
386
383
 
387
384
        ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
388
385
        ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
389
 
        ut_ad(btr_pcur_is_after_last_on_page(cursor, mtr));
 
386
        ut_ad(btr_pcur_is_after_last_on_page(cursor));
390
387
 
391
388
        cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
392
389
 
393
390
        page = btr_pcur_get_page(cursor);
394
 
 
395
391
        next_page_no = btr_page_get_next(page, mtr);
396
 
        space = buf_frame_get_space_id(page);
 
392
        space = buf_block_get_space(btr_pcur_get_block(cursor));
 
393
        zip_size = buf_block_get_zip_size(btr_pcur_get_block(cursor));
397
394
 
398
395
        ut_ad(next_page_no != FIL_NULL);
399
396
 
400
 
        next_page = btr_page_get(space, next_page_no, cursor->latch_mode, mtr);
 
397
        next_block = btr_block_get(space, zip_size, next_page_no,
 
398
                                   cursor->latch_mode, mtr);
 
399
        next_page = buf_block_get_frame(next_block);
401
400
#ifdef UNIV_BTR_DEBUG
402
 
        ut_a(btr_page_get_prev(next_page, mtr) == buf_frame_get_page_no(page));
 
401
        ut_a(page_is_comp(next_page) == page_is_comp(page));
 
402
        ut_a(btr_page_get_prev(next_page, mtr)
 
403
             == buf_block_get_page_no(btr_pcur_get_block(cursor)));
403
404
#endif /* UNIV_BTR_DEBUG */
404
 
        ut_a(page_is_comp(next_page) == page_is_comp(page));
405
 
        buf_block_align(next_page)->check_index_page_at_flush = TRUE;
406
 
 
407
 
        btr_leaf_page_release(page, cursor->latch_mode, mtr);
408
 
 
409
 
        page_cur_set_before_first(next_page, btr_pcur_get_page_cur(cursor));
 
405
        next_block->check_index_page_at_flush = TRUE;
 
406
 
 
407
        btr_leaf_page_release(btr_pcur_get_block(cursor),
 
408
                              cursor->latch_mode, mtr);
 
409
 
 
410
        page_cur_set_before_first(next_block, btr_pcur_get_page_cur(cursor));
410
411
 
411
412
        page_check_dir(next_page);
412
413
}
420
421
return, but it may happen that the cursor is not positioned on the last
421
422
record of any page, because the structure of the tree may have changed
422
423
during the time when the cursor had no latches. */
423
 
 
 
424
UNIV_INTERN
424
425
void
425
426
btr_pcur_move_backward_from_page(
426
427
/*=============================*/
428
429
                                record of the current page */
429
430
        mtr_t*          mtr)    /* in: mtr */
430
431
{
431
 
        ulint   prev_page_no;
432
 
        ulint   space;
433
 
        page_t* page;
434
 
        page_t* prev_page;
435
 
        ulint   latch_mode;
436
 
        ulint   latch_mode2;
 
432
        ulint           prev_page_no;
 
433
        ulint           space;
 
434
        page_t*         page;
 
435
        buf_block_t*    prev_block;
 
436
        ulint           latch_mode;
 
437
        ulint           latch_mode2;
437
438
 
438
439
        ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
439
440
        ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
440
 
        ut_ad(btr_pcur_is_before_first_on_page(cursor, mtr));
 
441
        ut_ad(btr_pcur_is_before_first_on_page(cursor));
441
442
        ut_ad(!btr_pcur_is_before_first_in_tree(cursor, mtr));
442
443
 
443
444
        latch_mode = cursor->latch_mode;
465
466
        page = btr_pcur_get_page(cursor);
466
467
 
467
468
        prev_page_no = btr_page_get_prev(page, mtr);
468
 
        space = buf_frame_get_space_id(page);
469
 
 
470
 
        if (btr_pcur_is_before_first_on_page(cursor, mtr)
471
 
            && (prev_page_no != FIL_NULL)) {
472
 
 
473
 
                prev_page = btr_pcur_get_btr_cur(cursor)->left_page;
474
 
 
475
 
                btr_leaf_page_release(page, latch_mode, mtr);
476
 
 
477
 
                page_cur_set_after_last(prev_page,
 
469
        space = buf_block_get_space(btr_pcur_get_block(cursor));
 
470
 
 
471
        if (prev_page_no == FIL_NULL) {
 
472
        } else if (btr_pcur_is_before_first_on_page(cursor)) {
 
473
 
 
474
                prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
 
475
 
 
476
                btr_leaf_page_release(btr_pcur_get_block(cursor),
 
477
                                      latch_mode, mtr);
 
478
 
 
479
                page_cur_set_after_last(prev_block,
478
480
                                        btr_pcur_get_page_cur(cursor));
479
 
        } else if (prev_page_no != FIL_NULL) {
 
481
        } else {
480
482
 
481
483
                /* The repositioned cursor did not end on an infimum record on
482
484
                a page. Cursor repositioning acquired a latch also on the
483
485
                previous page, but we do not need the latch: release it. */
484
486
 
485
 
                prev_page = btr_pcur_get_btr_cur(cursor)->left_page;
 
487
                prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
486
488
 
487
 
                btr_leaf_page_release(prev_page, latch_mode, mtr);
 
489
                btr_leaf_page_release(prev_block, latch_mode, mtr);
488
490
        }
489
491
 
490
492
        cursor->latch_mode = latch_mode;
495
497
/*************************************************************
496
498
Moves the persistent cursor to the previous record in the tree. If no records
497
499
are left, the cursor stays 'before first in tree'. */
498
 
 
 
500
UNIV_INTERN
499
501
ibool
500
502
btr_pcur_move_to_prev(
501
503
/*==================*/
510
512
 
511
513
        cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
512
514
 
513
 
        if (btr_pcur_is_before_first_on_page(cursor, mtr)) {
 
515
        if (btr_pcur_is_before_first_on_page(cursor)) {
514
516
 
515
517
                if (btr_pcur_is_before_first_in_tree(cursor, mtr)) {
516
518
 
522
524
                return(TRUE);
523
525
        }
524
526
 
525
 
        btr_pcur_move_to_prev_on_page(cursor, mtr);
 
527
        btr_pcur_move_to_prev_on_page(cursor);
526
528
 
527
529
        return(TRUE);
528
530
}
534
536
in the first case sets the cursor after last in tree, and in the latter case
535
537
before first in tree. The latching mode must be BTR_SEARCH_LEAF or
536
538
BTR_MODIFY_LEAF. */
537
 
 
 
539
UNIV_INTERN
538
540
void
539
541
btr_pcur_open_on_user_rec(
540
542
/*======================*/
541
543
        dict_index_t*   index,          /* in: index */
542
 
        dtuple_t*       tuple,          /* in: tuple on which search done */
 
544
        const dtuple_t* tuple,          /* in: tuple on which search done */
543
545
        ulint           mode,           /* in: PAGE_CUR_L, ... */
544
546
        ulint           latch_mode,     /* in: BTR_SEARCH_LEAF or
545
547
                                        BTR_MODIFY_LEAF */
551
553
 
552
554
        if ((mode == PAGE_CUR_GE) || (mode == PAGE_CUR_G)) {
553
555
 
554
 
                if (btr_pcur_is_after_last_on_page(cursor, mtr)) {
 
556
                if (btr_pcur_is_after_last_on_page(cursor)) {
555
557
 
556
558
                        btr_pcur_move_to_next_user_rec(cursor, mtr);
557
559
                }