~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2009-03-17 04:26:36 UTC
  • mfrom: (933.1.4 innodb-plugin-merge)
  • Revision ID: brian@tangent.org-20090317042636-oyd238h2u2bqhfy1
Merging new Innodb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 
 
3
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
 
4
Copyright (c) 2008, Google Inc.
 
5
 
 
6
Portions of this file contain modifications contributed and copyrighted by
 
7
Google, Inc. Those modifications are gratefully acknowledged and are described
 
8
briefly in the InnoDB documentation. The contributions by Google are
 
9
incorporated with their permission, and subject to the conditions contained in
 
10
the file COPYING.Google.
 
11
 
 
12
This program is free software; you can redistribute it and/or modify it under
 
13
the terms of the GNU General Public License as published by the Free Software
 
14
Foundation; version 2 of the License.
 
15
 
 
16
This program is distributed in the hope that it will be useful, but WITHOUT
 
17
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
18
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 
19
 
 
20
You should have received a copy of the GNU General Public License along with
 
21
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
22
Place, Suite 330, Boston, MA 02111-1307 USA
 
23
 
 
24
*****************************************************************************/
 
25
 
1
26
/******************************************************
2
27
The index tree cursor
3
28
 
12
37
if leaf splitting has been started, it is difficult to undo, except
13
38
by crashing the database and doing a roll-forward.
14
39
 
15
 
(c) 1994-2001 Innobase Oy
16
 
 
17
40
Created 10/16/1994 Heikki Tuuri
18
41
*******************************************************/
19
42
 
319
342
        ulint           low_bytes;
320
343
        ulint           height;
321
344
        ulint           savepoint;
322
 
        ulint           rw_latch;
323
345
        ulint           page_mode;
324
346
        ulint           insert_planned;
325
 
        ulint           buf_mode;
326
347
        ulint           estimate;
327
348
        ulint           ignore_sec_unique;
328
349
        ulint           root_height = 0; /* remove warning */
368
389
#ifdef UNIV_SEARCH_PERF_STAT
369
390
        info->n_searches++;
370
391
#endif
371
 
        if (btr_search_latch.writer == RW_LOCK_NOT_LOCKED
 
392
        if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_NOT_LOCKED
372
393
            && latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ
373
394
            && !estimate
374
395
#ifdef PAGE_CUR_LE_OR_EXTENDS
375
396
            && mode != PAGE_CUR_LE_OR_EXTENDS
376
397
#endif /* PAGE_CUR_LE_OR_EXTENDS */
377
 
            && !UNIV_UNLIKELY(btr_search_disabled)
 
398
            /* If !has_search_latch, we do a dirty read of
 
399
            btr_search_enabled below, and btr_search_guess_on_hash()
 
400
            will have to check it again. */
 
401
            && UNIV_LIKELY(btr_search_enabled)
378
402
            && btr_search_guess_on_hash(index, info, tuple, mode,
379
403
                                        latch_mode, cursor,
380
404
                                        has_search_latch, mtr)) {
430
454
        low_bytes = 0;
431
455
 
432
456
        height = ULINT_UNDEFINED;
433
 
        rw_latch = RW_NO_LATCH;
434
 
        buf_mode = BUF_GET;
435
457
 
436
458
        /* We use these modified search modes on non-leaf levels of the
437
459
        B-tree. These let us end up in the right B-tree leaf. In that leaf
460
482
        for (;;) {
461
483
                ulint           zip_size;
462
484
                buf_block_t*    block;
 
485
                ulint           rw_latch;
 
486
                ulint           buf_mode;
 
487
 
 
488
                zip_size = dict_table_zip_size(index->table);
 
489
                rw_latch = RW_NO_LATCH;
 
490
                buf_mode = BUF_GET;
 
491
 
 
492
                if (height == 0 && latch_mode <= BTR_MODIFY_LEAF) {
 
493
 
 
494
                        rw_latch = latch_mode;
 
495
 
 
496
                        if (insert_planned
 
497
                            && ibuf_should_try(index, ignore_sec_unique)) {
 
498
 
 
499
                                /* Try insert to the insert buffer if the
 
500
                                page is not in the buffer pool */
 
501
 
 
502
                                buf_mode = BUF_GET_IF_IN_POOL;
 
503
                        }
 
504
                }
 
505
 
463
506
retry_page_get:
464
 
                zip_size = dict_table_zip_size(index->table);
465
 
 
466
507
                block = buf_page_get_gen(space, zip_size, page_no,
467
508
                                         rw_latch, guess, buf_mode,
468
509
                                         __FILE__, __LINE__, mtr);
474
515
                        ut_ad(insert_planned);
475
516
                        ut_ad(cursor->thr);
476
517
 
477
 
                        if (ibuf_should_try(index, ignore_sec_unique)
478
 
                            && ibuf_insert(tuple, index, space, zip_size,
479
 
                                           page_no, cursor->thr)) {
 
518
                        if (ibuf_insert(tuple, index, space, zip_size,
 
519
                                        page_no, cursor->thr)) {
480
520
                                /* Insertion to the insert buffer succeeded */
481
521
                                cursor->flag = BTR_CUR_INSERT_TO_IBUF;
482
522
                                if (UNIV_LIKELY_NULL(heap)) {
494
534
                }
495
535
 
496
536
                page = buf_block_get_frame(block);
 
537
 
 
538
                block->check_index_page_at_flush = TRUE;
 
539
 
 
540
                if (rw_latch != RW_NO_LATCH) {
497
541
#ifdef UNIV_ZIP_DEBUG
498
 
                if (rw_latch != RW_NO_LATCH) {
499
542
                        const page_zip_des_t*   page_zip
500
543
                                = buf_block_get_page_zip(block);
501
544
                        ut_a(!page_zip || page_zip_validate(page_zip, page));
502
 
                }
503
545
#endif /* UNIV_ZIP_DEBUG */
504
546
 
505
 
                block->check_index_page_at_flush = TRUE;
506
 
 
507
 
                if (rw_latch != RW_NO_LATCH) {
508
547
                        buf_block_dbg_add_level(block, SYNC_TREE_NODE);
509
548
                }
510
549
 
576
615
 
577
616
                height--;
578
617
 
579
 
                if ((height == 0) && (latch_mode <= BTR_MODIFY_LEAF)) {
580
 
 
581
 
                        rw_latch = latch_mode;
582
 
 
583
 
                        if (insert_planned
584
 
                            && ibuf_should_try(index, ignore_sec_unique)) {
585
 
 
586
 
                                /* Try insert to the insert buffer if the
587
 
                                page is not in the buffer pool */
588
 
 
589
 
                                buf_mode = BUF_GET_IF_IN_POOL;
590
 
                        }
591
 
                }
592
 
 
593
618
                guess = NULL;
594
619
 
595
620
                node_ptr = page_cur_get_rec(page_cursor);
610
635
                cursor->up_bytes = up_bytes;
611
636
 
612
637
#ifdef BTR_CUR_ADAPT
613
 
                if (!UNIV_UNLIKELY(btr_search_disabled)) {
 
638
                /* We do a dirty read of btr_search_enabled here.  We
 
639
                will properly check btr_search_enabled again in
 
640
                btr_search_build_page_hash_index() before building a
 
641
                page hash index, while holding btr_search_latch. */
 
642
                if (UNIV_LIKELY(btr_search_enabled)) {
614
643
 
615
644
                        btr_search_info_update(index, cursor);
616
645
                }
1219
1248
                buf_block_get_page_no(block), max_size,
1220
1249
                rec_size + PAGE_DIR_SLOT_SIZE, index->type);
1221
1250
#endif
1222
 
        if (!dict_index_is_clust(index) && leaf) {
 
1251
        if (leaf
 
1252
            && !dict_index_is_clust(index)
 
1253
            && !dict_index_is_ibuf(index)) {
1223
1254
                /* Update the free bits of the B-tree page in the
1224
1255
                insert buffer bitmap. */
1225
1256
 
1600
1631
{
1601
1632
        ut_a(page_zip == buf_block_get_page_zip(block));
1602
1633
        ut_ad(page_zip);
 
1634
        ut_ad(!dict_index_is_ibuf(index));
1603
1635
 
1604
1636
        if (page_zip_available(page_zip, dict_index_is_clust(index),
1605
1637
                               length, 0)) {
1676
1708
        rec = btr_cur_get_rec(cursor);
1677
1709
        index = cursor->index;
1678
1710
        ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
 
1711
        /* The insert buffer tree should never be updated in place. */
 
1712
        ut_ad(!dict_index_is_ibuf(index));
 
1713
 
1679
1714
        trx = thr_get_trx(thr);
1680
1715
        offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
1681
1716
#ifdef UNIV_DEBUG
1812
1847
        index = cursor->index;
1813
1848
        ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
1814
1849
        ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
 
1850
        /* The insert buffer tree should never be updated in place. */
 
1851
        ut_ad(!dict_index_is_ibuf(index));
1815
1852
 
1816
1853
        heap = mem_heap_create(1024);
1817
1854
        offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
2075
2112
#ifdef UNIV_ZIP_DEBUG
2076
2113
        ut_a(!page_zip || page_zip_validate(page_zip, page));
2077
2114
#endif /* UNIV_ZIP_DEBUG */
 
2115
        /* The insert buffer tree should never be updated in place. */
 
2116
        ut_ad(!dict_index_is_ibuf(index));
2078
2117
 
2079
2118
        optim_err = btr_cur_optimistic_update(flags, cursor, update,
2080
2119
                                              cmpl_info, thr, mtr);
2724
2763
                                delete; cursor stays valid: if deletion
2725
2764
                                succeeds, on function exit it points to the
2726
2765
                                successor of the deleted record */
2727
 
        mtr_t*          mtr)    /* in: mtr */
 
2766
        mtr_t*          mtr)    /* in: mtr; if this function returns
 
2767
                                TRUE on a leaf page of a secondary
 
2768
                                index, the mtr must be committed
 
2769
                                before latching any further pages */
2728
2770
{
2729
2771
        buf_block_t*    block;
2730
2772
        rec_t*          rec;
2774
2816
#endif /* UNIV_ZIP_DEBUG */
2775
2817
 
2776
2818
                if (dict_index_is_clust(cursor->index)
 
2819
                    || dict_index_is_ibuf(cursor->index)
2777
2820
                    || !page_is_leaf(page)) {
2778
2821
                        /* The insert buffer does not handle
2779
 
                        inserts to clustered indexes or to non-leaf
2780
 
                        pages of secondary index B-trees. */
 
2822
                        inserts to clustered indexes, to
 
2823
                        non-leaf pages of secondary index B-trees,
 
2824
                        or to the insert buffer. */
2781
2825
                } else if (page_zip) {
2782
2826
                        ibuf_update_free_bits_zip(block, mtr);
2783
2827
                } else {
4073
4117
}
4074
4118
 
4075
4119
/***********************************************************************
 
4120
Check the FIL_PAGE_TYPE on an uncompressed BLOB page. */
 
4121
static
 
4122
void
 
4123
btr_check_blob_fil_page_type(
 
4124
/*=========================*/
 
4125
        ulint           space_id,       /* in: space id */
 
4126
        ulint           page_no,        /* in: page number */
 
4127
        const page_t*   page,           /* in: page */
 
4128
        ibool           read)           /* in: TRUE=read, FALSE=purge */
 
4129
{
 
4130
        ulint   type = fil_page_get_type(page);
 
4131
 
 
4132
        ut_a(space_id == page_get_space_id(page));
 
4133
        ut_a(page_no == page_get_page_no(page));
 
4134
 
 
4135
        if (UNIV_UNLIKELY(type != FIL_PAGE_TYPE_BLOB)) {
 
4136
                ulint   flags = fil_space_get_flags(space_id);
 
4137
 
 
4138
                if (UNIV_LIKELY
 
4139
                    ((flags & DICT_TF_FORMAT_MASK) == DICT_TF_FORMAT_51)) {
 
4140
                        /* Old versions of InnoDB did not initialize
 
4141
                        FIL_PAGE_TYPE on BLOB pages.  Do not print
 
4142
                        anything about the type mismatch when reading
 
4143
                        a BLOB page that is in Antelope format.*/
 
4144
                        return;
 
4145
                }
 
4146
 
 
4147
                ut_print_timestamp(stderr);
 
4148
                fprintf(stderr,
 
4149
                        "  InnoDB: FIL_PAGE_TYPE=%lu"
 
4150
                        " on BLOB %s space %lu page %lu flags %lx\n",
 
4151
                        (ulong) type, read ? "read" : "purge",
 
4152
                        (ulong) space_id, (ulong) page_no, (ulong) flags);
 
4153
                ut_error;
 
4154
        }
 
4155
}
 
4156
 
 
4157
/***********************************************************************
4076
4158
Frees the space in an externally stored field to the file space
4077
4159
management if the field in data is owned by the externally stored field,
4078
4160
in a rollback we may have the additional condition that the field must
4225
4307
                                                 MLOG_4BYTES, &mtr);
4226
4308
                        }
4227
4309
                } else {
4228
 
                        ut_a(fil_page_get_type(page) == FIL_PAGE_TYPE_BLOB);
4229
4310
                        ut_a(!page_zip);
 
4311
                        btr_check_blob_fil_page_type(space_id, page_no, page,
 
4312
                                                     FALSE);
4230
4313
 
4231
4314
                        next_page_no = mach_read_from_4(
4232
4315
                                page + FIL_PAGE_DATA
4236
4319
                        because we did not store it on the page (we save the
4237
4320
                        space overhead from an index page header. */
4238
4321
 
4239
 
                        ut_a(space_id == page_get_space_id(page));
4240
 
                        ut_a(page_no == page_get_page_no(page));
4241
 
 
4242
4322
                        btr_page_free_low(index, ext_block, 0, &mtr);
4243
4323
 
4244
4324
                        mlog_write_ulint(field_ref + BTR_EXTERN_PAGE_NO,
4376
4456
                buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE);
4377
4457
                page = buf_block_get_frame(block);
4378
4458
 
4379
 
                /* Unfortunately, FIL_PAGE_TYPE was uninitialized for
4380
 
                many pages until MySQL/InnoDB 5.1.7. */
4381
 
                /* ut_ad(fil_page_get_type(page) == FIL_PAGE_TYPE_BLOB); */
 
4459
                btr_check_blob_fil_page_type(space_id, page_no, page, TRUE);
 
4460
 
4382
4461
                blob_header = page + offset;
4383
4462
                part_len = btr_blob_get_part_len(blob_header);
4384
4463
                copy_len = ut_min(part_len, len - copied_len);