~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-18 10:14:05 UTC
  • mfrom: (2008.1.3 clean)
  • Revision ID: brian@tangent.org-20101218101405-qjbse29shi9coklg
Merge of user identifier work

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
{
1363
1357
        const ulint*    ops)    /*!< in: operation counts */
1364
1358
 
1365
1359
{
1366
 
        ulint   i;
1367
 
 
1368
1360
#ifndef HAVE_ATOMIC_BUILTINS
1369
1361
        ut_ad(mutex_own(&ibuf_mutex));
1370
1362
#endif /* !HAVE_ATOMIC_BUILTINS */
1371
1363
 
 
1364
        ulint   i;
 
1365
 
1372
1366
        for (i = 0; i < IBUF_OP_COUNT; i++) {
1373
1367
#ifdef HAVE_ATOMIC_BUILTINS
1374
1368
                os_atomic_increment_ulint(&arr[i], ops[i]);
1794
1788
 
1795
1789
        field = dtuple_get_nth_field(tuple, 0);
1796
1790
 
1797
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
 
1791
        buf = mem_heap_alloc(heap, 4);
1798
1792
 
1799
1793
        mach_write_to_4(buf, space);
1800
1794
 
1804
1798
 
1805
1799
        field = dtuple_get_nth_field(tuple, 1);
1806
1800
 
1807
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 1));
 
1801
        buf = mem_heap_alloc(heap, 1);
1808
1802
 
1809
1803
        /* We set the marker byte zero */
1810
1804
 
1816
1810
 
1817
1811
        field = dtuple_get_nth_field(tuple, 2);
1818
1812
 
1819
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
 
1813
        buf = mem_heap_alloc(heap, 4);
1820
1814
 
1821
1815
        mach_write_to_4(buf, page_no);
1822
1816
 
1831
1825
                i = IBUF_REC_INFO_SIZE;
1832
1826
        }
1833
1827
 
1834
 
        ti = type_info = static_cast<byte *>(mem_heap_alloc(heap, i + n_fields
1835
 
                                        * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE));
 
1828
        ti = type_info = mem_heap_alloc(heap, i + n_fields
 
1829
                                        * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
1836
1830
 
1837
1831
        switch (i) {
1838
1832
        default:
1935
1929
 
1936
1930
        field = dtuple_get_nth_field(tuple, 0);
1937
1931
 
1938
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
 
1932
        buf = mem_heap_alloc(heap, 4);
1939
1933
 
1940
1934
        mach_write_to_4(buf, page_no);
1941
1935
 
1970
1964
 
1971
1965
        field = dtuple_get_nth_field(tuple, 0);
1972
1966
 
1973
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
 
1967
        buf = mem_heap_alloc(heap, 4);
1974
1968
 
1975
1969
        mach_write_to_4(buf, space);
1976
1970
 
1980
1974
 
1981
1975
        field = dtuple_get_nth_field(tuple, 1);
1982
1976
 
1983
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 1));
 
1977
        buf = mem_heap_alloc(heap, 1);
1984
1978
 
1985
1979
        mach_write_to_1(buf, 0);
1986
1980
 
1990
1984
 
1991
1985
        field = dtuple_get_nth_field(tuple, 2);
1992
1986
 
1993
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
 
1987
        buf = mem_heap_alloc(heap, 4);
1994
1988
 
1995
1989
        mach_write_to_4(buf, page_no);
1996
1990
 
2767
2761
 
2768
2762
        switch (ibuf_op) {
2769
2763
        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
 
2764
                /* Inserts can be done by
 
2765
                btr_cur_set_deleted_flag_for_ibuf().  Because
 
2766
                delete-mark and insert operations can be pointing to
2772
2767
                the same records, we must not count duplicates. */
2773
2768
        case IBUF_OP_DELETE_MARK:
2774
2769
                /* There must be a record to delete-mark.
3272
3267
 
3273
3268
        /* Patch counter value in already built entry. */
3274
3269
        field = dtuple_get_nth_field(entry, 3);
3275
 
        data = static_cast<byte *>(dfield_get_data(field));
 
3270
        data = dfield_get_data(field);
3276
3271
 
3277
3272
        mach_write_to_2(data + IBUF_REC_OFFSET_COUNTER, counter);
3278
3273
 
3526
3521
                /* If this is the root page, update ibuf->empty. */
3527
3522
                if (UNIV_UNLIKELY(buf_block_get_page_no(block)
3528
3523
                                  == FSP_IBUF_TREE_ROOT_PAGE_NO)) {
3529
 
                        const page_t*   page_root = buf_block_get_frame(block);
 
3524
                        const page_t*   root = buf_block_get_frame(block);
3530
3525
 
3531
 
                        ut_ad(page_get_space_id(page_root) == IBUF_SPACE_ID);
3532
 
                        ut_ad(page_get_page_no(page_root)
 
3526
                        ut_ad(page_get_space_id(root) == IBUF_SPACE_ID);
 
3527
                        ut_ad(page_get_page_no(root)
3533
3528
                              == FSP_IBUF_TREE_ROOT_PAGE_NO);
3534
3529
 
3535
 
                        ibuf->empty = (page_get_n_recs(page_root) == 0);
 
3530
                        ibuf->empty = (page_get_n_recs(root) == 0);
3536
3531
                }
3537
3532
        } else {
3538
3533
                ut_ad(mode == BTR_MODIFY_TREE);
3753
3748
from the insert buffer. */
3754
3749
static
3755
3750
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
3751
ibuf_insert_to_index_page(
3828
3752
/*======================*/
3829
 
        const dtuple_t* entry,  /*!< in: buffered entry to insert */
 
3753
        dtuple_t*       entry,  /*!< in: buffered entry to insert */
3830
3754
        buf_block_t*    block,  /*!< in/out: index page where the buffered entry
3831
3755
                                should be placed */
3832
3756
        dict_index_t*   index,  /*!< in: record descriptor */
3836
3760
        ulint           low_match;
3837
3761
        page_t*         page            = buf_block_get_frame(block);
3838
3762
        rec_t*          rec;
 
3763
        page_t*         bitmap_page;
 
3764
        ulint           old_bits;
3839
3765
 
3840
3766
        ut_ad(ibuf_inside());
3841
3767
        ut_ad(dtuple_check_typed(entry));
3842
 
        ut_ad(!buf_block_align(page)->is_hashed);
3843
3768
 
3844
3769
        if (UNIV_UNLIKELY(dict_table_is_comp(index->table)
3845
3770
                          != (ibool)!!page_is_comp(page))) {
3885
3810
        low_match = page_cur_search(block, index, entry,
3886
3811
                                    PAGE_CUR_LE, &page_cur);
3887
3812
 
3888
 
        if (UNIV_UNLIKELY(low_match == dtuple_get_n_fields(entry))) {
3889
 
                mem_heap_t*     heap;
3890
 
                upd_t*          update;
3891
 
                ulint*          offsets;
 
3813
        if (low_match == dtuple_get_n_fields(entry)) {
3892
3814
                page_zip_des_t* page_zip;
3893
3815
 
3894
3816
                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
3817
                page_zip = buf_block_get_page_zip(block);
3908
3818
 
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);
 
3819
                btr_cur_set_deleted_flag_for_ibuf(rec, page_zip, FALSE, mtr);
 
3820
        } else {
 
3821
                rec = page_cur_tuple_insert(&page_cur, entry, index, 0, mtr);
 
3822
 
 
3823
                if (UNIV_LIKELY(rec != NULL)) {
3917
3824
                        return;
3918
3825
                }
3919
3826
 
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;
 
3827
                /* If the record did not fit, reorganize */
 
3828
 
 
3829
                btr_page_reorganize(block, index, mtr);
 
3830
                page_cur_search(block, index, entry, PAGE_CUR_LE, &page_cur);
 
3831
 
 
3832
                /* This time the record must fit */
 
3833
                if (UNIV_UNLIKELY
 
3834
                    (!page_cur_tuple_insert(&page_cur, entry, index,
 
3835
                                            0, mtr))) {
 
3836
                        ulint   space;
 
3837
                        ulint   page_no;
 
3838
                        ulint   zip_size;
 
3839
 
 
3840
                        ut_print_timestamp(stderr);
 
3841
 
 
3842
                        fprintf(stderr,
 
3843
                                "  InnoDB: Error: Insert buffer insert"
 
3844
                                " fails; page free %lu,"
 
3845
                                " dtuple size %lu\n",
 
3846
                                (ulong) page_get_max_insert_size(
 
3847
                                        page, 1),
 
3848
                                (ulong) rec_get_converted_size(
 
3849
                                        index, entry, 0));
 
3850
                        fputs("InnoDB: Cannot insert index record ",
 
3851
                              stderr);
 
3852
                        dtuple_print(stderr, entry);
 
3853
                        fputs("\nInnoDB: The table where"
 
3854
                              " this index record belongs\n"
 
3855
                              "InnoDB: is now probably corrupt."
 
3856
                              " Please run CHECK TABLE on\n"
 
3857
                              "InnoDB: that table.\n", stderr);
 
3858
 
 
3859
                        space = page_get_space_id(page);
 
3860
                        zip_size = buf_block_get_zip_size(block);
 
3861
                        page_no = page_get_page_no(page);
 
3862
 
 
3863
                        bitmap_page = ibuf_bitmap_get_map_page(
 
3864
                                space, page_no, zip_size, mtr);
 
3865
                        old_bits = ibuf_bitmap_page_get_bits(
 
3866
                                bitmap_page, page_no, zip_size,
 
3867
                                IBUF_BITMAP_FREE, mtr);
 
3868
 
 
3869
                        fprintf(stderr,
 
3870
                                "InnoDB: space %lu, page %lu,"
 
3871
                                " zip_size %lu, bitmap bits %lu\n",
 
3872
                                (ulong) space, (ulong) page_no,
 
3873
                                (ulong) zip_size, (ulong) old_bits);
 
3874
 
 
3875
                        fputs("InnoDB: Submit a detailed bug report"
 
3876
                              " to http://bugs.mysql.com\n", stderr);
3937
3877
                }
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
3878
        }
3970
3879
}
3971
3880
 
3997
3906
                rec = page_cur_get_rec(&page_cur);
3998
3907
                page_zip = page_cur_get_page_zip(&page_cur);
3999
3908
 
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
 
                }
 
3909
                btr_cur_set_deleted_flag_for_ibuf(rec, page_zip, TRUE, mtr);
4012
3910
        } 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);
 
3911
                /* This can happen benignly in some situations. */
4026
3912
        }
4027
3913
}
4028
3914
 
4097
3983
                        mem_heap_free(heap);
4098
3984
                }
4099
3985
        } else {
4100
 
                /* The record must have been purged already. */
 
3986
                /* This can happen benignly in some situations: either when
 
3987
                we crashed at just the right time, or on database startup
 
3988
                when we redo some old log entries (due to worse stored
 
3989
                position granularity on disk than in memory). */
4101
3990
        }
4102
3991
}
4103
3992