~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/ibuf/ibuf0ibuf.c

  • Committer: Brian Aker
  • Date: 2010-12-08 18:53:46 UTC
  • mto: This revision was merged to the branch mainline in revision 1983.
  • Revision ID: brian@tangent.org-20101208185346-89uak2ofyivk1yss
Update schema, make sure that it always ruturns a valid string (it just
makes the entire interface simpler to use).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 1997, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
49
49
#include "btr0cur.h"
50
50
#include "btr0pcur.h"
51
51
#include "btr0btr.h"
52
 
#include "row0upd.h"
53
52
#include "sync0sync.h"
54
53
#include "dict0boot.h"
55
54
#include "fut0lst.h"
193
192
/** Operations that can currently be buffered. */
194
193
UNIV_INTERN ibuf_use_t  ibuf_use                = IBUF_USE_ALL;
195
194
 
196
 
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
197
 
/** Flag to control insert buffer debugging. */
198
 
UNIV_INTERN uint        ibuf_debug;
199
 
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
200
 
 
201
195
/** The insert buffer control structure */
202
196
UNIV_INTERN ibuf_t*     ibuf                    = NULL;
203
197
 
516
510
        page_t*         header_page;
517
511
        ulint           error;
518
512
 
519
 
        ibuf = static_cast<ibuf_t *>(mem_alloc(sizeof(ibuf_t)));
 
513
        ibuf = mem_alloc(sizeof(ibuf_t));
520
514
 
521
515
        memset(ibuf, 0, sizeof(*ibuf));
522
516
 
643
637
ibuf_parse_bitmap_init(
644
638
/*===================*/
645
639
        byte*           ptr,    /*!< in: buffer */
646
 
        byte*           /*end_ptr __attribute__((unused))*/, /*!< in: buffer end */
 
640
        byte*           end_ptr __attribute__((unused)), /*!< in: buffer end */
647
641
        buf_block_t*    block,  /*!< in: block or NULL */
648
642
        mtr_t*          mtr)    /*!< in: mtr or NULL */
649
643
{
669
663
                                0 for uncompressed pages */
670
664
        ulint           bit,    /*!< in: IBUF_BITMAP_FREE,
671
665
                                IBUF_BITMAP_BUFFERED, ... */
672
 
        mtr_t*          /*mtr __attribute__((unused))*/)
 
666
        mtr_t*          mtr __attribute__((unused)))
673
667
                                /*!< in: mtr containing an
674
668
                                x-latch to the bitmap page */
675
669
{
1303
1297
        const rec_t*    rec)    /*!< in: ibuf record */
1304
1298
{
1305
1299
        ulint           len;
 
1300
        const byte*     field;
1306
1301
 
1307
1302
        ut_ad(ibuf_inside());
1308
1303
        ut_ad(rec_get_n_fields_old(rec) > 2);
1309
1304
 
1310
 
        (void) rec_get_nth_field_old(rec, 1, &len);
 
1305
        field = rec_get_nth_field_old(rec, 1, &len);
1311
1306
 
1312
1307
        if (len > 1) {
1313
1308
                /* This is a < 4.1.x format record */
1363
1358
        const ulint*    ops)    /*!< in: operation counts */
1364
1359
 
1365
1360
{
1366
 
        ulint   i;
1367
 
 
1368
1361
#ifndef HAVE_ATOMIC_BUILTINS
1369
1362
        ut_ad(mutex_own(&ibuf_mutex));
1370
1363
#endif /* !HAVE_ATOMIC_BUILTINS */
1371
1364
 
 
1365
        ulint   i;
 
1366
 
1372
1367
        for (i = 0; i < IBUF_OP_COUNT; i++) {
1373
1368
#ifdef HAVE_ATOMIC_BUILTINS
1374
1369
                os_atomic_increment_ulint(&arr[i], ops[i]);
1794
1789
 
1795
1790
        field = dtuple_get_nth_field(tuple, 0);
1796
1791
 
1797
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
 
1792
        buf = mem_heap_alloc(heap, 4);
1798
1793
 
1799
1794
        mach_write_to_4(buf, space);
1800
1795
 
1804
1799
 
1805
1800
        field = dtuple_get_nth_field(tuple, 1);
1806
1801
 
1807
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 1));
 
1802
        buf = mem_heap_alloc(heap, 1);
1808
1803
 
1809
1804
        /* We set the marker byte zero */
1810
1805
 
1816
1811
 
1817
1812
        field = dtuple_get_nth_field(tuple, 2);
1818
1813
 
1819
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
 
1814
        buf = mem_heap_alloc(heap, 4);
1820
1815
 
1821
1816
        mach_write_to_4(buf, page_no);
1822
1817
 
1831
1826
                i = IBUF_REC_INFO_SIZE;
1832
1827
        }
1833
1828
 
1834
 
        ti = type_info = static_cast<byte *>(mem_heap_alloc(heap, i + n_fields
1835
 
                                        * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE));
 
1829
        ti = type_info = mem_heap_alloc(heap, i + n_fields
 
1830
                                        * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
1836
1831
 
1837
1832
        switch (i) {
1838
1833
        default:
1935
1930
 
1936
1931
        field = dtuple_get_nth_field(tuple, 0);
1937
1932
 
1938
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
 
1933
        buf = mem_heap_alloc(heap, 4);
1939
1934
 
1940
1935
        mach_write_to_4(buf, page_no);
1941
1936
 
1970
1965
 
1971
1966
        field = dtuple_get_nth_field(tuple, 0);
1972
1967
 
1973
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
 
1968
        buf = mem_heap_alloc(heap, 4);
1974
1969
 
1975
1970
        mach_write_to_4(buf, space);
1976
1971
 
1980
1975
 
1981
1976
        field = dtuple_get_nth_field(tuple, 1);
1982
1977
 
1983
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 1));
 
1978
        buf = mem_heap_alloc(heap, 1);
1984
1979
 
1985
1980
        mach_write_to_1(buf, 0);
1986
1981
 
1990
1985
 
1991
1986
        field = dtuple_get_nth_field(tuple, 2);
1992
1987
 
1993
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
 
1988
        buf = mem_heap_alloc(heap, 4);
1994
1989
 
1995
1990
        mach_write_to_4(buf, page_no);
1996
1991
 
2767
2762
 
2768
2763
        switch (ibuf_op) {
2769
2764
        case IBUF_OP_INSERT:
2770
 
                /* Inserts can be done by updating a delete-marked record.
2771
 
                Because delete-mark and insert operations can be pointing to
 
2765
                /* Inserts can be done by
 
2766
                btr_cur_set_deleted_flag_for_ibuf().  Because
 
2767
                delete-mark and insert operations can be pointing to
2772
2768
                the same records, we must not count duplicates. */
2773
2769
        case IBUF_OP_DELETE_MARK:
2774
2770
                /* There must be a record to delete-mark.
3272
3268
 
3273
3269
        /* Patch counter value in already built entry. */
3274
3270
        field = dtuple_get_nth_field(entry, 3);
3275
 
        data = static_cast<byte *>(dfield_get_data(field));
 
3271
        data = dfield_get_data(field);
3276
3272
 
3277
3273
        mach_write_to_2(data + IBUF_REC_OFFSET_COUNTER, counter);
3278
3274
 
3526
3522
                /* If this is the root page, update ibuf->empty. */
3527
3523
                if (UNIV_UNLIKELY(buf_block_get_page_no(block)
3528
3524
                                  == FSP_IBUF_TREE_ROOT_PAGE_NO)) {
3529
 
                        const page_t*   page_root = buf_block_get_frame(block);
 
3525
                        const page_t*   root = buf_block_get_frame(block);
3530
3526
 
3531
 
                        ut_ad(page_get_space_id(page_root) == IBUF_SPACE_ID);
3532
 
                        ut_ad(page_get_page_no(page_root)
 
3527
                        ut_ad(page_get_space_id(root) == IBUF_SPACE_ID);
 
3528
                        ut_ad(page_get_page_no(root)
3533
3529
                              == FSP_IBUF_TREE_ROOT_PAGE_NO);
3534
3530
 
3535
 
                        ibuf->empty = (page_get_n_recs(page_root) == 0);
 
3531
                        ibuf->empty = (page_get_n_recs(root) == 0);
3536
3532
                }
3537
3533
        } else {
3538
3534
                ut_ad(mode == BTR_MODIFY_TREE);
3753
3749
from the insert buffer. */
3754
3750
static
3755
3751
void
3756
 
ibuf_insert_to_index_page_low(
3757
 
/*==========================*/
3758
 
        const dtuple_t* entry,  /*!< in: buffered entry to insert */
3759
 
        buf_block_t*    block,  /*!< in/out: index page where the buffered
3760
 
                                entry should be placed */
3761
 
        dict_index_t*   index,  /*!< in: record descriptor */
3762
 
        mtr_t*          mtr,    /*!< in/out: mtr */
3763
 
        page_cur_t*     page_cur)/*!< in/out: cursor positioned on the record
3764
 
                                after which to insert the buffered entry */
3765
 
{
3766
 
        const page_t*   page;
3767
 
        ulint           space;
3768
 
        ulint           page_no;
3769
 
        ulint           zip_size;
3770
 
        const page_t*   bitmap_page;
3771
 
        ulint           old_bits;
3772
 
 
3773
 
        if (UNIV_LIKELY
3774
 
            (page_cur_tuple_insert(page_cur, entry, index, 0, mtr) != NULL)) {
3775
 
                return;
3776
 
        }
3777
 
 
3778
 
        /* If the record did not fit, reorganize */
3779
 
 
3780
 
        btr_page_reorganize(block, index, mtr);
3781
 
        page_cur_search(block, index, entry, PAGE_CUR_LE, page_cur);
3782
 
 
3783
 
        /* This time the record must fit */
3784
 
 
3785
 
        if (UNIV_LIKELY
3786
 
            (page_cur_tuple_insert(page_cur, entry, index, 0, mtr) != NULL)) {
3787
 
                return;
3788
 
        }
3789
 
 
3790
 
        page = buf_block_get_frame(block);
3791
 
 
3792
 
        ut_print_timestamp(stderr);
3793
 
 
3794
 
        fprintf(stderr,
3795
 
                "  InnoDB: Error: Insert buffer insert fails;"
3796
 
                " page free %lu, dtuple size %lu\n",
3797
 
                (ulong) page_get_max_insert_size(page, 1),
3798
 
                (ulong) rec_get_converted_size(index, entry, 0));
3799
 
        fputs("InnoDB: Cannot insert index record ", stderr);
3800
 
        dtuple_print(stderr, entry);
3801
 
        fputs("\nInnoDB: The table where this index record belongs\n"
3802
 
              "InnoDB: is now probably corrupt. Please run CHECK TABLE on\n"
3803
 
              "InnoDB: that table.\n", stderr);
3804
 
 
3805
 
        space = page_get_space_id(page);
3806
 
        zip_size = buf_block_get_zip_size(block);
3807
 
        page_no = page_get_page_no(page);
3808
 
 
3809
 
        bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr);
3810
 
        old_bits = ibuf_bitmap_page_get_bits(bitmap_page, page_no, zip_size,
3811
 
                                             IBUF_BITMAP_FREE, mtr);
3812
 
 
3813
 
        fprintf(stderr,
3814
 
                "InnoDB: space %lu, page %lu, zip_size %lu, bitmap bits %lu\n",
3815
 
                (ulong) space, (ulong) page_no,
3816
 
                (ulong) zip_size, (ulong) old_bits);
3817
 
 
3818
 
        fputs("InnoDB: Submit a detailed bug report"
3819
 
              " to http://bugs.mysql.com\n", stderr);
3820
 
}
3821
 
 
3822
 
/************************************************************************
3823
 
During merge, inserts to an index page a secondary index entry extracted
3824
 
from the insert buffer. */
3825
 
static
3826
 
void
3827
3752
ibuf_insert_to_index_page(
3828
3753
/*======================*/
3829
 
        const dtuple_t* entry,  /*!< in: buffered entry to insert */
 
3754
        dtuple_t*       entry,  /*!< in: buffered entry to insert */
3830
3755
        buf_block_t*    block,  /*!< in/out: index page where the buffered entry
3831
3756
                                should be placed */
3832
3757
        dict_index_t*   index,  /*!< in: record descriptor */
3836
3761
        ulint           low_match;
3837
3762
        page_t*         page            = buf_block_get_frame(block);
3838
3763
        rec_t*          rec;
 
3764
        page_t*         bitmap_page;
 
3765
        ulint           old_bits;
3839
3766
 
3840
3767
        ut_ad(ibuf_inside());
3841
3768
        ut_ad(dtuple_check_typed(entry));
3842
 
        ut_ad(!buf_block_align(page)->is_hashed);
3843
3769
 
3844
3770
        if (UNIV_UNLIKELY(dict_table_is_comp(index->table)
3845
3771
                          != (ibool)!!page_is_comp(page))) {
3853
3779
        rec = page_rec_get_next(page_get_infimum_rec(page));
3854
3780
 
3855
3781
        if (page_rec_is_supremum(rec)) {
3856
 
                fputs("InnoDB: Trying to insert a record from"
3857
 
                      " the insert buffer to an index page\n"
3858
 
                      "InnoDB: but the index page is empty!\n",
3859
 
                      stderr);
3860
 
                goto dump;
 
3782
                /* Empty pages can result from buffered delete operations.
 
3783
                The first record from the free list can be used to find the
 
3784
                father node. */
 
3785
                rec = page_header_get_ptr(page, PAGE_FREE);
 
3786
                if (UNIV_UNLIKELY(rec == NULL)) {
 
3787
                        fputs("InnoDB: Trying to insert a record from"
 
3788
                              " the insert buffer to an index page\n"
 
3789
                              "InnoDB: but the index page is empty!\n",
 
3790
                              stderr);
 
3791
                        goto dump;
 
3792
                }
3861
3793
        }
3862
3794
 
3863
3795
        if (UNIV_UNLIKELY(rec_get_n_fields(rec, index)
3885
3817
        low_match = page_cur_search(block, index, entry,
3886
3818
                                    PAGE_CUR_LE, &page_cur);
3887
3819
 
3888
 
        if (UNIV_UNLIKELY(low_match == dtuple_get_n_fields(entry))) {
3889
 
                mem_heap_t*     heap;
3890
 
                upd_t*          update;
3891
 
                ulint*          offsets;
 
3820
        if (low_match == dtuple_get_n_fields(entry)) {
3892
3821
                page_zip_des_t* page_zip;
3893
3822
 
3894
3823
                rec = page_cur_get_rec(&page_cur);
3895
 
 
3896
 
                /* This is based on
3897
 
                row_ins_sec_index_entry_by_modify(BTR_MODIFY_LEAF). */
3898
 
                ut_ad(rec_get_deleted_flag(rec, page_is_comp(page)));
3899
 
 
3900
 
                heap = mem_heap_create(1024);
3901
 
 
3902
 
                offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED,
3903
 
                                          &heap);
3904
 
                update = row_upd_build_sec_rec_difference_binary(
3905
 
                        index, entry, rec, NULL, heap);
3906
 
 
3907
3824
                page_zip = buf_block_get_page_zip(block);
3908
3825
 
3909
 
                if (update->n_fields == 0) {
3910
 
                        /* The records only differ in the delete-mark.
3911
 
                        Clear the delete-mark, like we did before
3912
 
                        Bug #56680 was fixed. */
3913
 
                        btr_cur_set_deleted_flag_for_ibuf(
3914
 
                                rec, page_zip, FALSE, mtr);
3915
 
updated_in_place:
3916
 
                        mem_heap_free(heap);
 
3826
                btr_cur_set_deleted_flag_for_ibuf(rec, page_zip, FALSE, mtr);
 
3827
        } else {
 
3828
                rec = page_cur_tuple_insert(&page_cur, entry, index, 0, mtr);
 
3829
 
 
3830
                if (UNIV_LIKELY(rec != NULL)) {
3917
3831
                        return;
3918
3832
                }
3919
3833
 
3920
 
                /* Copy the info bits. Clear the delete-mark. */
3921
 
                update->info_bits = rec_get_info_bits(rec, page_is_comp(page));
3922
 
                update->info_bits &= ~REC_INFO_DELETED_FLAG;
3923
 
 
3924
 
                /* We cannot invoke btr_cur_optimistic_update() here,
3925
 
                because we do not have a btr_cur_t or que_thr_t,
3926
 
                as the insert buffer merge occurs at a very low level. */
3927
 
                if (!row_upd_changes_field_size_or_external(index, offsets,
3928
 
                                                            update)
3929
 
                    && (!page_zip || btr_cur_update_alloc_zip(
3930
 
                                page_zip, block, index,
3931
 
                                rec_offs_size(offsets), FALSE, mtr))) {
3932
 
                        /* This is the easy case. Do something similar
3933
 
                        to btr_cur_update_in_place(). */
3934
 
                        row_upd_rec_in_place(rec, index, offsets,
3935
 
                                             update, page_zip);
3936
 
                        goto updated_in_place;
 
3834
                /* If the record did not fit, reorganize */
 
3835
 
 
3836
                btr_page_reorganize(block, index, mtr);
 
3837
                page_cur_search(block, index, entry, PAGE_CUR_LE, &page_cur);
 
3838
 
 
3839
                /* This time the record must fit */
 
3840
                if (UNIV_UNLIKELY
 
3841
                    (!page_cur_tuple_insert(&page_cur, entry, index,
 
3842
                                            0, mtr))) {
 
3843
                        ulint   space;
 
3844
                        ulint   page_no;
 
3845
                        ulint   zip_size;
 
3846
 
 
3847
                        ut_print_timestamp(stderr);
 
3848
 
 
3849
                        fprintf(stderr,
 
3850
                                "  InnoDB: Error: Insert buffer insert"
 
3851
                                " fails; page free %lu,"
 
3852
                                " dtuple size %lu\n",
 
3853
                                (ulong) page_get_max_insert_size(
 
3854
                                        page, 1),
 
3855
                                (ulong) rec_get_converted_size(
 
3856
                                        index, entry, 0));
 
3857
                        fputs("InnoDB: Cannot insert index record ",
 
3858
                              stderr);
 
3859
                        dtuple_print(stderr, entry);
 
3860
                        fputs("\nInnoDB: The table where"
 
3861
                              " this index record belongs\n"
 
3862
                              "InnoDB: is now probably corrupt."
 
3863
                              " Please run CHECK TABLE on\n"
 
3864
                              "InnoDB: that table.\n", stderr);
 
3865
 
 
3866
                        space = page_get_space_id(page);
 
3867
                        zip_size = buf_block_get_zip_size(block);
 
3868
                        page_no = page_get_page_no(page);
 
3869
 
 
3870
                        bitmap_page = ibuf_bitmap_get_map_page(
 
3871
                                space, page_no, zip_size, mtr);
 
3872
                        old_bits = ibuf_bitmap_page_get_bits(
 
3873
                                bitmap_page, page_no, zip_size,
 
3874
                                IBUF_BITMAP_FREE, mtr);
 
3875
 
 
3876
                        fprintf(stderr,
 
3877
                                "InnoDB: space %lu, page %lu,"
 
3878
                                " zip_size %lu, bitmap bits %lu\n",
 
3879
                                (ulong) space, (ulong) page_no,
 
3880
                                (ulong) zip_size, (ulong) old_bits);
 
3881
 
 
3882
                        fputs("InnoDB: Submit a detailed bug report"
 
3883
                              " to http://bugs.mysql.com\n", stderr);
3937
3884
                }
3938
 
 
3939
 
                /* A collation may identify values that differ in
3940
 
                storage length.
3941
 
                Some examples (1 or 2 bytes):
3942
 
                utf8_turkish_ci: I = U+0131 LATIN SMALL LETTER DOTLESS I
3943
 
                utf8_general_ci: S = U+00DF LATIN SMALL LETTER SHARP S
3944
 
                utf8_general_ci: A = U+00E4 LATIN SMALL LETTER A WITH DIAERESIS
3945
 
 
3946
 
                latin1_german2_ci: SS = U+00DF LATIN SMALL LETTER SHARP S
3947
 
 
3948
 
                Examples of a character (3-byte UTF-8 sequence)
3949
 
                identified with 2 or 4 characters (1-byte UTF-8 sequences):
3950
 
 
3951
 
                utf8_unicode_ci: 'II' = U+2171 SMALL ROMAN NUMERAL TWO
3952
 
                utf8_unicode_ci: '(10)' = U+247D PARENTHESIZED NUMBER TEN
3953
 
                */
3954
 
 
3955
 
                /* Delete the different-length record, and insert the
3956
 
                buffered one. */
3957
 
 
3958
 
                lock_rec_store_on_page_infimum(block, rec);
3959
 
                page_cur_delete_rec(&page_cur, index, offsets, mtr);
3960
 
                page_cur_move_to_prev(&page_cur);
3961
 
                mem_heap_free(heap);
3962
 
 
3963
 
                ibuf_insert_to_index_page_low(entry, block, index, mtr,
3964
 
                                              &page_cur);
3965
 
                lock_rec_restore_from_page_infimum(block, rec, block);
3966
 
        } else {
3967
 
                ibuf_insert_to_index_page_low(entry, block, index, mtr,
3968
 
                                              &page_cur);
3969
3885
        }
3970
3886
}
3971
3887
 
3997
3913
                rec = page_cur_get_rec(&page_cur);
3998
3914
                page_zip = page_cur_get_page_zip(&page_cur);
3999
3915
 
4000
 
                /* Delete mark the old index record. According to a
4001
 
                comment in row_upd_sec_index_entry(), it can already
4002
 
                have been delete marked if a lock wait occurred in
4003
 
                row_ins_index_entry() in a previous invocation of
4004
 
                row_upd_sec_index_entry(). */
4005
 
 
4006
 
                if (UNIV_LIKELY
4007
 
                    (!rec_get_deleted_flag(
4008
 
                            rec, dict_table_is_comp(index->table)))) {
4009
 
                        btr_cur_set_deleted_flag_for_ibuf(rec, page_zip,
4010
 
                                                          TRUE, mtr);
4011
 
                }
 
3916
                btr_cur_set_deleted_flag_for_ibuf(rec, page_zip, TRUE, mtr);
4012
3917
        } else {
4013
 
                ut_print_timestamp(stderr);
4014
 
                fputs("  InnoDB: unable to find a record to delete-mark\n",
4015
 
                      stderr);
4016
 
                fputs("InnoDB: tuple ", stderr);
4017
 
                dtuple_print(stderr, entry);
4018
 
                fputs("\n"
4019
 
                      "InnoDB: record ", stderr);
4020
 
                rec_print(stderr, page_cur_get_rec(&page_cur), index);
4021
 
                putc('\n', stderr);
4022
 
                fputs("\n"
4023
 
                      "InnoDB: Submit a detailed bug report"
4024
 
                      " to http://bugs.mysql.com\n", stderr);
4025
 
                ut_ad(0);
 
3918
                /* This can happen benignly in some situations. */
4026
3919
        }
4027
3920
}
4028
3921
 
4097
3990
                        mem_heap_free(heap);
4098
3991
                }
4099
3992
        } else {
4100
 
                /* The record must have been purged already. */
 
3993
                /* This can happen benignly in some situations: either when
 
3994
                we crashed at just the right time, or on database startup
 
3995
                when we redo some old log entries (due to worse stored
 
3996
                position granularity on disk than in memory). */
4101
3997
        }
4102
3998
}
4103
3999