~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2010-12-02 22:51:54 UTC
  • mto: (1975.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 1976.
  • Revision ID: mordred@inaugust.com-20101202225154-h54ifmga9x6cckgs
Refactored syslog module and changed it to use sys_var directly.

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"
56
55
#include "lock0lock.h"
57
56
#include "log0recv.h"
58
57
#include "que0que.h"
59
 
#include "srv0start.h" /* srv_shutdown_state */
60
58
 
61
59
/*      STRUCTURE OF AN INSERT BUFFER RECORD
62
60
 
193
191
/** Operations that can currently be buffered. */
194
192
UNIV_INTERN ibuf_use_t  ibuf_use                = IBUF_USE_ALL;
195
193
 
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
194
/** The insert buffer control structure */
202
195
UNIV_INTERN ibuf_t*     ibuf                    = NULL;
203
196
 
402
395
        mtr_t*          mtr)    /*!< in: mtr */
403
396
{
404
397
        buf_block_t*    block;
405
 
        page_t*         root;
406
398
 
407
399
        ut_ad(ibuf_inside());
408
 
        ut_ad(mutex_own(&ibuf_mutex));
409
400
 
410
401
        mtr_x_lock(dict_index_get_lock(ibuf->index), mtr);
411
402
 
414
405
 
415
406
        buf_block_dbg_add_level(block, SYNC_TREE_NODE);
416
407
 
417
 
        root = buf_block_get_frame(block);
418
 
 
419
 
        ut_ad(page_get_space_id(root) == IBUF_SPACE_ID);
420
 
        ut_ad(page_get_page_no(root) == FSP_IBUF_TREE_ROOT_PAGE_NO);
421
 
        ut_ad(ibuf->empty == (page_get_n_recs(root) == 0));
422
 
 
423
 
        return(root);
 
408
        return(buf_block_get_frame(block));
424
409
}
425
410
 
426
411
#ifdef UNIV_IBUF_COUNT_DEBUG
497
482
 
498
483
        /* the '1 +' is the ibuf header page */
499
484
        ibuf->size = ibuf->seg_size - (1 + ibuf->free_list_len);
 
485
 
 
486
        ibuf->empty = page_get_n_recs(root) == 0;
500
487
}
501
488
 
502
489
/******************************************************************//**
516
503
        page_t*         header_page;
517
504
        ulint           error;
518
505
 
519
 
        ibuf = static_cast<ibuf_t *>(mem_alloc(sizeof(ibuf_t)));
 
506
        ibuf = mem_alloc(sizeof(ibuf_t));
520
507
 
521
508
        memset(ibuf, 0, sizeof(*ibuf));
522
509
 
567
554
        ibuf_size_update(root, &mtr);
568
555
        mutex_exit(&ibuf_mutex);
569
556
 
570
 
        ibuf->empty = (page_get_n_recs(root) == 0);
571
557
        mtr_commit(&mtr);
572
558
 
573
559
        ibuf_exit();
579
565
 
580
566
        dict_mem_table_add_col(table, heap, "DUMMY_COLUMN", DATA_BINARY, 0, 0);
581
567
 
582
 
        table->id = DICT_IBUF_ID_MIN + IBUF_SPACE_ID;
 
568
        table->id = ut_dulint_add(DICT_IBUF_ID_MIN, IBUF_SPACE_ID);
583
569
 
584
570
        dict_table_add_to_cache(table, heap);
585
571
        mem_heap_free(heap);
590
576
 
591
577
        dict_mem_index_add_field(index, "DUMMY_COLUMN", 0);
592
578
 
593
 
        index->id = DICT_IBUF_ID_MIN + IBUF_SPACE_ID;
 
579
        index->id = ut_dulint_add(DICT_IBUF_ID_MIN, IBUF_SPACE_ID);
594
580
 
595
581
        error = dict_index_add_to_cache(table, index,
596
582
                                        FSP_IBUF_TREE_ROOT_PAGE_NO, FALSE);
643
629
ibuf_parse_bitmap_init(
644
630
/*===================*/
645
631
        byte*           ptr,    /*!< in: buffer */
646
 
        byte*           /*end_ptr __attribute__((unused))*/, /*!< in: buffer end */
 
632
        byte*           end_ptr __attribute__((unused)), /*!< in: buffer end */
647
633
        buf_block_t*    block,  /*!< in: block or NULL */
648
634
        mtr_t*          mtr)    /*!< in: mtr or NULL */
649
635
{
669
655
                                0 for uncompressed pages */
670
656
        ulint           bit,    /*!< in: IBUF_BITMAP_FREE,
671
657
                                IBUF_BITMAP_BUFFERED, ... */
672
 
        mtr_t*          /*mtr __attribute__((unused))*/)
 
658
        mtr_t*          mtr __attribute__((unused)))
673
659
                                /*!< in: mtr containing an
674
660
                                x-latch to the bitmap page */
675
661
{
1303
1289
        const rec_t*    rec)    /*!< in: ibuf record */
1304
1290
{
1305
1291
        ulint           len;
 
1292
        const byte*     field;
1306
1293
 
1307
1294
        ut_ad(ibuf_inside());
1308
1295
        ut_ad(rec_get_n_fields_old(rec) > 2);
1309
1296
 
1310
 
        (void) rec_get_nth_field_old(rec, 1, &len);
 
1297
        field = rec_get_nth_field_old(rec, 1, &len);
1311
1298
 
1312
1299
        if (len > 1) {
1313
1300
                /* This is a < 4.1.x format record */
1365
1352
{
1366
1353
        ulint   i;
1367
1354
 
1368
 
#ifndef HAVE_ATOMIC_BUILTINS
1369
 
        ut_ad(mutex_own(&ibuf_mutex));
1370
 
#endif /* !HAVE_ATOMIC_BUILTINS */
1371
 
 
1372
1355
        for (i = 0; i < IBUF_OP_COUNT; i++) {
1373
 
#ifdef HAVE_ATOMIC_BUILTINS
1374
 
                os_atomic_increment_ulint(&arr[i], ops[i]);
1375
 
#else /* HAVE_ATOMIC_BUILTINS */
1376
1356
                arr[i] += ops[i];
1377
 
#endif /* HAVE_ATOMIC_BUILTINS */
1378
1357
        }
1379
1358
}
1380
1359
 
1794
1773
 
1795
1774
        field = dtuple_get_nth_field(tuple, 0);
1796
1775
 
1797
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
 
1776
        buf = mem_heap_alloc(heap, 4);
1798
1777
 
1799
1778
        mach_write_to_4(buf, space);
1800
1779
 
1804
1783
 
1805
1784
        field = dtuple_get_nth_field(tuple, 1);
1806
1785
 
1807
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 1));
 
1786
        buf = mem_heap_alloc(heap, 1);
1808
1787
 
1809
1788
        /* We set the marker byte zero */
1810
1789
 
1816
1795
 
1817
1796
        field = dtuple_get_nth_field(tuple, 2);
1818
1797
 
1819
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
 
1798
        buf = mem_heap_alloc(heap, 4);
1820
1799
 
1821
1800
        mach_write_to_4(buf, page_no);
1822
1801
 
1831
1810
                i = IBUF_REC_INFO_SIZE;
1832
1811
        }
1833
1812
 
1834
 
        ti = type_info = static_cast<byte *>(mem_heap_alloc(heap, i + n_fields
1835
 
                                        * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE));
 
1813
        ti = type_info = mem_heap_alloc(heap, i + n_fields
 
1814
                                        * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
1836
1815
 
1837
1816
        switch (i) {
1838
1817
        default:
1935
1914
 
1936
1915
        field = dtuple_get_nth_field(tuple, 0);
1937
1916
 
1938
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
 
1917
        buf = mem_heap_alloc(heap, 4);
1939
1918
 
1940
1919
        mach_write_to_4(buf, page_no);
1941
1920
 
1970
1949
 
1971
1950
        field = dtuple_get_nth_field(tuple, 0);
1972
1951
 
1973
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
 
1952
        buf = mem_heap_alloc(heap, 4);
1974
1953
 
1975
1954
        mach_write_to_4(buf, space);
1976
1955
 
1980
1959
 
1981
1960
        field = dtuple_get_nth_field(tuple, 1);
1982
1961
 
1983
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 1));
 
1962
        buf = mem_heap_alloc(heap, 1);
1984
1963
 
1985
1964
        mach_write_to_1(buf, 0);
1986
1965
 
1990
1969
 
1991
1970
        field = dtuple_get_nth_field(tuple, 2);
1992
1971
 
1993
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
 
1972
        buf = mem_heap_alloc(heap, 4);
1994
1973
 
1995
1974
        mach_write_to_4(buf, page_no);
1996
1975
 
2038
2017
/*********************************************************************//**
2039
2018
Allocates a new page from the ibuf file segment and adds it to the free
2040
2019
list.
2041
 
@return TRUE on success, FALSE if no space left */
 
2020
@return DB_SUCCESS, or DB_STRONG_FAIL if no space left */
2042
2021
static
2043
 
ibool
 
2022
ulint
2044
2023
ibuf_add_free_page(void)
2045
2024
/*====================*/
2046
2025
{
2076
2055
                header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 0, FSP_UP,
2077
2056
                &mtr);
2078
2057
 
2079
 
        if (UNIV_UNLIKELY(page_no == FIL_NULL)) {
 
2058
        if (page_no == FIL_NULL) {
2080
2059
                mtr_commit(&mtr);
2081
2060
 
2082
 
                return(FALSE);
 
2061
                return(DB_STRONG_FAIL);
2083
2062
        }
2084
2063
 
2085
2064
        {
2117
2096
        bitmap_page = ibuf_bitmap_get_map_page(
2118
2097
                IBUF_SPACE_ID, page_no, zip_size, &mtr);
2119
2098
 
2120
 
        mutex_exit(&ibuf_mutex);
2121
 
 
2122
2099
        ibuf_bitmap_page_set_bits(
2123
2100
                bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, TRUE, &mtr);
2124
2101
 
2125
2102
        mtr_commit(&mtr);
2126
2103
 
 
2104
        mutex_exit(&ibuf_mutex);
 
2105
 
2127
2106
        ibuf_exit();
2128
2107
 
2129
 
        return(TRUE);
 
2108
        return(DB_SUCCESS);
2130
2109
}
2131
2110
 
2132
2111
/*********************************************************************//**
2156
2135
        header_page = ibuf_header_page_get(&mtr);
2157
2136
 
2158
2137
        /* Prevent pessimistic inserts to insert buffer trees for a while */
2159
 
        ibuf_enter();
2160
2138
        mutex_enter(&ibuf_pessimistic_insert_mutex);
 
2139
 
 
2140
        ibuf_enter();
 
2141
 
2161
2142
        mutex_enter(&ibuf_mutex);
2162
2143
 
2163
2144
        if (!ibuf_data_too_much_free()) {
2164
2145
 
2165
2146
                mutex_exit(&ibuf_mutex);
 
2147
 
 
2148
                ibuf_exit();
 
2149
 
2166
2150
                mutex_exit(&ibuf_pessimistic_insert_mutex);
2167
2151
 
2168
 
                ibuf_exit();
2169
 
 
2170
2152
                mtr_commit(&mtr);
2171
2153
 
2172
2154
                return;
2176
2158
 
2177
2159
        root = ibuf_tree_root_get(&mtr2);
2178
2160
 
2179
 
        mutex_exit(&ibuf_mutex);
2180
 
 
2181
2161
        page_no = flst_get_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
2182
2162
                                &mtr2).page;
2183
2163
 
2186
2166
        is a level 2 page. */
2187
2167
 
2188
2168
        mtr_commit(&mtr2);
 
2169
        mutex_exit(&ibuf_mutex);
2189
2170
 
2190
2171
        ibuf_exit();
2191
2172
 
2228
2209
        flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
2229
2210
                    page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
2230
2211
 
2231
 
        mutex_exit(&ibuf_pessimistic_insert_mutex);
2232
 
 
2233
2212
        ibuf->seg_size--;
2234
2213
        ibuf->free_list_len--;
2235
2214
 
 
2215
        mutex_exit(&ibuf_pessimistic_insert_mutex);
 
2216
 
2236
2217
        /* Set the bit indicating that this page is no more an ibuf tree page
2237
2218
        (level 2 page) */
2238
2219
 
2239
2220
        bitmap_page = ibuf_bitmap_get_map_page(
2240
2221
                IBUF_SPACE_ID, page_no, zip_size, &mtr);
2241
2222
 
2242
 
        mutex_exit(&ibuf_mutex);
2243
 
 
2244
2223
        ibuf_bitmap_page_set_bits(
2245
2224
                bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, FALSE, &mtr);
2246
2225
 
2249
2228
#endif
2250
2229
        mtr_commit(&mtr);
2251
2230
 
 
2231
        mutex_exit(&ibuf_mutex);
 
2232
 
2252
2233
        ibuf_exit();
2253
2234
}
2254
2235
 
2289
2270
 
2290
2271
        for (i = 0; i < 4; i++) {
2291
2272
 
2292
 
                ibool   too_much_free;
2293
 
 
2294
2273
                mutex_enter(&ibuf_mutex);
2295
 
                too_much_free = ibuf_data_too_much_free();
2296
 
                mutex_exit(&ibuf_mutex);
2297
 
 
2298
 
                if (!too_much_free) {
 
2274
 
 
2275
                if (!ibuf_data_too_much_free()) {
 
2276
 
 
2277
                        mutex_exit(&ibuf_mutex);
 
2278
 
2299
2279
                        return;
2300
2280
                }
2301
2281
 
 
2282
                mutex_exit(&ibuf_mutex);
 
2283
 
2302
2284
                ibuf_remove_free_page();
2303
2285
        }
2304
2286
}
2494
2476
        ulint           page_nos[IBUF_MAX_N_PAGES_MERGED];
2495
2477
        ulint           space_ids[IBUF_MAX_N_PAGES_MERGED];
2496
2478
        ib_int64_t      space_versions[IBUF_MAX_N_PAGES_MERGED];
 
2479
        ulint           n_stored;
2497
2480
        ulint           sum_sizes;
2498
2481
        mtr_t           mtr;
2499
2482
 
2500
2483
        *n_pages = 0;
2501
2484
        ut_ad(!ibuf_inside());
2502
2485
 
2503
 
        /* We perform a dirty read of ibuf->empty, without latching
2504
 
        the insert buffer root page. We trust this dirty read except
2505
 
        when a slow shutdown is being executed. During a slow
2506
 
        shutdown, the insert buffer merge must be completed. */
 
2486
        mutex_enter(&ibuf_mutex);
2507
2487
 
2508
 
        if (UNIV_UNLIKELY(ibuf->empty)
2509
 
            && UNIV_LIKELY(!srv_shutdown_state)) {
 
2488
        if (ibuf->empty) {
2510
2489
ibuf_is_empty:
 
2490
                mutex_exit(&ibuf_mutex);
2511
2491
 
2512
2492
#if 0 /* TODO */
2513
2493
                if (srv_shutdown_state) {
2539
2519
        ut_ad(page_validate(btr_pcur_get_page(&pcur), ibuf->index));
2540
2520
 
2541
2521
        if (page_get_n_recs(btr_pcur_get_page(&pcur)) == 0) {
2542
 
                /* If a B-tree page is empty, it must be the root page
2543
 
                and the whole B-tree must be empty. InnoDB does not
2544
 
                allow empty B-tree pages other than the root. */
2545
 
                ut_ad(ibuf->empty);
2546
 
                ut_ad(page_get_space_id(btr_pcur_get_page(&pcur))
2547
 
                      == IBUF_SPACE_ID);
2548
 
                ut_ad(page_get_page_no(btr_pcur_get_page(&pcur))
2549
 
                      == FSP_IBUF_TREE_ROOT_PAGE_NO);
 
2522
                /* When the ibuf tree is emptied completely, the last record
 
2523
                is removed using an optimistic delete and ibuf_size_update
 
2524
                is not called, causing ibuf->empty to remain FALSE. If we do
 
2525
                not reset it to TRUE here then database shutdown will hang
 
2526
                in the loop in ibuf_contract_for_n_pages. */
 
2527
 
 
2528
                ibuf->empty = TRUE;
2550
2529
 
2551
2530
                ibuf_exit();
2552
2531
 
2556
2535
                goto ibuf_is_empty;
2557
2536
        }
2558
2537
 
 
2538
        mutex_exit(&ibuf_mutex);
 
2539
 
2559
2540
        sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur),
2560
2541
                                            space_ids, space_versions,
2561
 
                                            page_nos, n_pages);
 
2542
                                            page_nos, &n_stored);
2562
2543
#if 0 /* defined UNIV_IBUF_DEBUG */
2563
2544
        fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n",
2564
 
                sync, *n_pages, sum_sizes);
 
2545
                sync, n_stored, sum_sizes);
2565
2546
#endif
2566
2547
        ibuf_exit();
2567
2548
 
2569
2550
        btr_pcur_close(&pcur);
2570
2551
 
2571
2552
        buf_read_ibuf_merge_pages(sync, space_ids, space_versions, page_nos,
2572
 
                                  *n_pages);
 
2553
                                  n_stored);
 
2554
        *n_pages = n_stored;
2573
2555
 
2574
2556
        return(sum_sizes + 1);
2575
2557
}
2639
2621
        ibool   sync;
2640
2622
        ulint   sum_sizes;
2641
2623
        ulint   size;
2642
 
        ulint   max_size;
2643
 
 
2644
 
        /* Perform dirty reads of ibuf->size and ibuf->max_size, to
2645
 
        reduce ibuf_mutex contention. ibuf->max_size remains constant
2646
 
        after ibuf_init_at_db_start(), but ibuf->size should be
2647
 
        protected by ibuf_mutex. Given that ibuf->size fits in a
2648
 
        machine word, this should be OK; at worst we are doing some
2649
 
        excessive ibuf_contract() or occasionally skipping a
2650
 
        ibuf_contract(). */
2651
 
        size = ibuf->size;
2652
 
        max_size = ibuf->max_size;
2653
 
 
2654
 
        if (size < max_size + IBUF_CONTRACT_ON_INSERT_NON_SYNC) {
 
2624
 
 
2625
        mutex_enter(&ibuf_mutex);
 
2626
 
 
2627
        if (ibuf->size < ibuf->max_size + IBUF_CONTRACT_ON_INSERT_NON_SYNC) {
 
2628
                mutex_exit(&ibuf_mutex);
 
2629
 
2655
2630
                return;
2656
2631
        }
2657
2632
 
2658
 
        sync = (size >= max_size + IBUF_CONTRACT_ON_INSERT_SYNC);
 
2633
        sync = FALSE;
 
2634
 
 
2635
        if (ibuf->size >= ibuf->max_size + IBUF_CONTRACT_ON_INSERT_SYNC) {
 
2636
 
 
2637
                sync = TRUE;
 
2638
        }
 
2639
 
 
2640
        mutex_exit(&ibuf_mutex);
2659
2641
 
2660
2642
        /* Contract at least entry_size many bytes */
2661
2643
        sum_sizes = 0;
2662
2644
        size = 1;
2663
2645
 
2664
 
        do {
 
2646
        while ((size > 0) && (sum_sizes < entry_size)) {
2665
2647
 
2666
2648
                size = ibuf_contract(sync);
2667
2649
                sum_sizes += size;
2668
 
        } while (size > 0 && sum_sizes < entry_size);
 
2650
        }
2669
2651
}
2670
2652
 
2671
2653
/*********************************************************************//**
2767
2749
 
2768
2750
        switch (ibuf_op) {
2769
2751
        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
 
2752
                /* Inserts can be done by
 
2753
                btr_cur_set_deleted_flag_for_ibuf().  Because
 
2754
                delete-mark and insert operations can be pointing to
2772
2755
                the same records, we must not count duplicates. */
2773
2756
        case IBUF_OP_DELETE_MARK:
2774
2757
                /* There must be a record to delete-mark.
3272
3255
 
3273
3256
        /* Patch counter value in already built entry. */
3274
3257
        field = dtuple_get_nth_field(entry, 3);
3275
 
        data = static_cast<byte *>(dfield_get_data(field));
 
3258
        data = dfield_get_data(field);
3276
3259
 
3277
3260
        mach_write_to_2(data + IBUF_REC_OFFSET_COUNTER, counter);
3278
3261
 
3282
3265
/*********************************************************************//**
3283
3266
Buffer an operation in the insert/delete buffer, instead of doing it
3284
3267
directly to the disk page, if this is possible.
3285
 
@return DB_SUCCESS, DB_STRONG_FAIL or other error */
 
3268
@return DB_SUCCESS, DB_FAIL, DB_STRONG_FAIL */
3286
3269
static
3287
3270
ulint
3288
3271
ibuf_insert_low(
3312
3295
        rec_t*          ins_rec;
3313
3296
        ibool           old_bit_value;
3314
3297
        page_t*         bitmap_page;
3315
 
        buf_block_t*    block;
3316
3298
        page_t*         root;
3317
3299
        ulint           err;
3318
3300
        ibool           do_merge;
3333
3315
 
3334
3316
        do_merge = FALSE;
3335
3317
 
3336
 
        /* Perform dirty reads of ibuf->size and ibuf->max_size, to
3337
 
        reduce ibuf_mutex contention. ibuf->max_size remains constant
3338
 
        after ibuf_init_at_db_start(), but ibuf->size should be
3339
 
        protected by ibuf_mutex. Given that ibuf->size fits in a
3340
 
        machine word, this should be OK; at worst we are doing some
3341
 
        excessive ibuf_contract() or occasionally skipping a
3342
 
        ibuf_contract(). */
 
3318
        mutex_enter(&ibuf_mutex);
 
3319
 
3343
3320
        if (ibuf->size >= ibuf->max_size + IBUF_CONTRACT_DO_NOT_INSERT) {
3344
3321
                /* Insert buffer is now too big, contract it but do not try
3345
3322
                to insert */
3346
3323
 
 
3324
                mutex_exit(&ibuf_mutex);
3347
3325
 
3348
3326
#ifdef UNIV_IBUF_DEBUG
3349
3327
                fputs("Ibuf too big\n", stderr);
3354
3332
                return(DB_STRONG_FAIL);
3355
3333
        }
3356
3334
 
 
3335
        mutex_exit(&ibuf_mutex);
 
3336
 
 
3337
        if (mode == BTR_MODIFY_TREE) {
 
3338
                mutex_enter(&ibuf_pessimistic_insert_mutex);
 
3339
 
 
3340
                ibuf_enter();
 
3341
 
 
3342
                mutex_enter(&ibuf_mutex);
 
3343
 
 
3344
                while (!ibuf_data_enough_free_for_insert()) {
 
3345
 
 
3346
                        mutex_exit(&ibuf_mutex);
 
3347
 
 
3348
                        ibuf_exit();
 
3349
 
 
3350
                        mutex_exit(&ibuf_pessimistic_insert_mutex);
 
3351
 
 
3352
                        err = ibuf_add_free_page();
 
3353
 
 
3354
                        if (err == DB_STRONG_FAIL) {
 
3355
 
 
3356
                                return(err);
 
3357
                        }
 
3358
 
 
3359
                        mutex_enter(&ibuf_pessimistic_insert_mutex);
 
3360
 
 
3361
                        ibuf_enter();
 
3362
 
 
3363
                        mutex_enter(&ibuf_mutex);
 
3364
                }
 
3365
        } else {
 
3366
                ibuf_enter();
 
3367
        }
 
3368
 
3357
3369
        heap = mem_heap_create(512);
3358
3370
 
3359
3371
        /* Build the entry which contains the space id and the page number
3372
3384
        the new entry to it without exceeding the free space limit for the
3373
3385
        page. */
3374
3386
 
3375
 
        if (mode == BTR_MODIFY_TREE) {
3376
 
                for (;;) {
3377
 
                        ibuf_enter();
3378
 
                        mutex_enter(&ibuf_pessimistic_insert_mutex);
3379
 
                        mutex_enter(&ibuf_mutex);
3380
 
 
3381
 
                        if (UNIV_LIKELY(ibuf_data_enough_free_for_insert())) {
3382
 
 
3383
 
                                break;
3384
 
                        }
3385
 
 
3386
 
                        mutex_exit(&ibuf_mutex);
3387
 
                        mutex_exit(&ibuf_pessimistic_insert_mutex);
3388
 
                        ibuf_exit();
3389
 
 
3390
 
                        if (UNIV_UNLIKELY(!ibuf_add_free_page())) {
3391
 
 
3392
 
                                mem_heap_free(heap);
3393
 
                                return(DB_STRONG_FAIL);
3394
 
                        }
3395
 
                }
3396
 
        } else {
3397
 
                ibuf_enter();
3398
 
        }
3399
 
 
3400
3387
        mtr_start(&mtr);
3401
3388
 
3402
3389
        btr_pcur_open(ibuf->index, ibuf_entry, PAGE_CUR_LE, mode, &pcur, &mtr);
3430
3417
                before mtr_commit(&mtr).  We must not mtr_commit(&mtr)
3431
3418
                until after the IBUF_OP_DELETE has been buffered. */
3432
3419
 
3433
 
fail_exit:
3434
 
                if (mode == BTR_MODIFY_TREE) {
3435
 
                        mutex_exit(&ibuf_mutex);
3436
 
                        mutex_exit(&ibuf_pessimistic_insert_mutex);
3437
 
                }
3438
 
 
3439
3420
                err = DB_STRONG_FAIL;
3440
 
                goto func_exit;
 
3421
 
 
3422
                goto function_exit;
3441
3423
        }
3442
3424
 
3443
3425
        /* After this point, the page could still be loaded to the
3483
3465
                                space_ids, space_versions,
3484
3466
                                page_nos, &n_stored);
3485
3467
 
3486
 
                        goto fail_exit;
 
3468
                        err = DB_STRONG_FAIL;
 
3469
 
 
3470
                        goto function_exit;
3487
3471
                }
3488
3472
        }
3489
3473
 
3494
3478
            && !ibuf_set_entry_counter(ibuf_entry, space, page_no, &pcur,
3495
3479
                                       mode == BTR_MODIFY_PREV, &mtr)) {
3496
3480
bitmap_fail:
 
3481
                err = DB_STRONG_FAIL;
 
3482
 
3497
3483
                mtr_commit(&bitmap_mtr);
3498
3484
 
3499
 
                goto fail_exit;
 
3485
                goto function_exit;
3500
3486
        }
3501
3487
 
3502
3488
        /* Set the bitmap bit denoting that the insert buffer contains
3520
3506
                err = btr_cur_optimistic_insert(BTR_NO_LOCKING_FLAG, cursor,
3521
3507
                                                ibuf_entry, &ins_rec,
3522
3508
                                                &dummy_big_rec, 0, thr, &mtr);
3523
 
                block = btr_cur_get_block(cursor);
3524
 
                ut_ad(buf_block_get_space(block) == IBUF_SPACE_ID);
3525
 
 
3526
 
                /* If this is the root page, update ibuf->empty. */
3527
 
                if (UNIV_UNLIKELY(buf_block_get_page_no(block)
3528
 
                                  == FSP_IBUF_TREE_ROOT_PAGE_NO)) {
3529
 
                        const page_t*   page_root = buf_block_get_frame(block);
3530
 
 
3531
 
                        ut_ad(page_get_space_id(page_root) == IBUF_SPACE_ID);
3532
 
                        ut_ad(page_get_page_no(page_root)
3533
 
                              == FSP_IBUF_TREE_ROOT_PAGE_NO);
3534
 
 
3535
 
                        ibuf->empty = (page_get_n_recs(page_root) == 0);
 
3509
                if (err == DB_SUCCESS && op != IBUF_OP_DELETE) {
 
3510
                        /* Update the page max trx id field */
 
3511
                        page_update_max_trx_id(btr_cur_get_block(cursor), NULL,
 
3512
                                               thr_get_trx(thr)->id, &mtr);
3536
3513
                }
3537
3514
        } else {
3538
3515
                ut_ad(mode == BTR_MODIFY_TREE);
3549
3526
                                                 cursor,
3550
3527
                                                 ibuf_entry, &ins_rec,
3551
3528
                                                 &dummy_big_rec, 0, thr, &mtr);
3552
 
                mutex_exit(&ibuf_pessimistic_insert_mutex);
 
3529
                if (err == DB_SUCCESS && op != IBUF_OP_DELETE) {
 
3530
                        /* Update the page max trx id field */
 
3531
                        page_update_max_trx_id(btr_cur_get_block(cursor), NULL,
 
3532
                                               thr_get_trx(thr)->id, &mtr);
 
3533
                }
 
3534
 
3553
3535
                ibuf_size_update(root, &mtr);
3554
 
                mutex_exit(&ibuf_mutex);
3555
 
                ibuf->empty = (page_get_n_recs(root) == 0);
3556
 
 
3557
 
                block = btr_cur_get_block(cursor);
3558
 
                ut_ad(buf_block_get_space(block) == IBUF_SPACE_ID);
3559
 
        }
3560
 
 
3561
 
        if (err == DB_SUCCESS && op != IBUF_OP_DELETE) {
3562
 
                /* Update the page max trx id field */
3563
 
                page_update_max_trx_id(block, NULL,
3564
 
                                       thr_get_trx(thr)->id, &mtr);
3565
 
        }
3566
 
 
3567
 
func_exit:
 
3536
        }
 
3537
 
 
3538
function_exit:
3568
3539
#ifdef UNIV_IBUF_COUNT_DEBUG
3569
3540
        if (err == DB_SUCCESS) {
3570
3541
                fprintf(stderr,
3576
3547
                               ibuf_count_get(space, page_no) + 1);
3577
3548
        }
3578
3549
#endif
 
3550
        if (mode == BTR_MODIFY_TREE) {
 
3551
 
 
3552
                mutex_exit(&ibuf_mutex);
 
3553
                mutex_exit(&ibuf_pessimistic_insert_mutex);
 
3554
        }
3579
3555
 
3580
3556
        mtr_commit(&mtr);
3581
3557
        btr_pcur_close(&pcur);
3583
3559
 
3584
3560
        mem_heap_free(heap);
3585
3561
 
3586
 
        if (err == DB_SUCCESS && mode == BTR_MODIFY_TREE) {
3587
 
                ibuf_contract_after_insert(entry_size);
 
3562
        if (err == DB_SUCCESS) {
 
3563
                mutex_enter(&ibuf_mutex);
 
3564
 
 
3565
                ibuf->empty = FALSE;
 
3566
 
 
3567
                mutex_exit(&ibuf_mutex);
 
3568
 
 
3569
                if (mode == BTR_MODIFY_TREE) {
 
3570
                        ibuf_contract_after_insert(entry_size);
 
3571
                }
3588
3572
        }
3589
3573
 
3590
3574
        if (do_merge) {
3753
3737
from the insert buffer. */
3754
3738
static
3755
3739
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
3740
ibuf_insert_to_index_page(
3828
3741
/*======================*/
3829
 
        const dtuple_t* entry,  /*!< in: buffered entry to insert */
 
3742
        dtuple_t*       entry,  /*!< in: buffered entry to insert */
3830
3743
        buf_block_t*    block,  /*!< in/out: index page where the buffered entry
3831
3744
                                should be placed */
3832
3745
        dict_index_t*   index,  /*!< in: record descriptor */
3836
3749
        ulint           low_match;
3837
3750
        page_t*         page            = buf_block_get_frame(block);
3838
3751
        rec_t*          rec;
 
3752
        page_t*         bitmap_page;
 
3753
        ulint           old_bits;
3839
3754
 
3840
3755
        ut_ad(ibuf_inside());
3841
3756
        ut_ad(dtuple_check_typed(entry));
3842
 
        ut_ad(!buf_block_align(page)->is_hashed);
3843
3757
 
3844
3758
        if (UNIV_UNLIKELY(dict_table_is_comp(index->table)
3845
3759
                          != (ibool)!!page_is_comp(page))) {
3853
3767
        rec = page_rec_get_next(page_get_infimum_rec(page));
3854
3768
 
3855
3769
        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;
 
3770
                /* Empty pages can result from buffered delete operations.
 
3771
                The first record from the free list can be used to find the
 
3772
                father node. */
 
3773
                rec = page_header_get_ptr(page, PAGE_FREE);
 
3774
                if (UNIV_UNLIKELY(rec == NULL)) {
 
3775
                        fputs("InnoDB: Trying to insert a record from"
 
3776
                              " the insert buffer to an index page\n"
 
3777
                              "InnoDB: but the index page is empty!\n",
 
3778
                              stderr);
 
3779
                        goto dump;
 
3780
                }
3861
3781
        }
3862
3782
 
3863
3783
        if (UNIV_UNLIKELY(rec_get_n_fields(rec, index)
3885
3805
        low_match = page_cur_search(block, index, entry,
3886
3806
                                    PAGE_CUR_LE, &page_cur);
3887
3807
 
3888
 
        if (UNIV_UNLIKELY(low_match == dtuple_get_n_fields(entry))) {
3889
 
                mem_heap_t*     heap;
3890
 
                upd_t*          update;
3891
 
                ulint*          offsets;
 
3808
        if (low_match == dtuple_get_n_fields(entry)) {
3892
3809
                page_zip_des_t* page_zip;
3893
3810
 
3894
3811
                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
3812
                page_zip = buf_block_get_page_zip(block);
3908
3813
 
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);
 
3814
                btr_cur_set_deleted_flag_for_ibuf(rec, page_zip, FALSE, mtr);
 
3815
        } else {
 
3816
                rec = page_cur_tuple_insert(&page_cur, entry, index, 0, mtr);
 
3817
 
 
3818
                if (UNIV_LIKELY(rec != NULL)) {
3917
3819
                        return;
3918
3820
                }
3919
3821
 
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;
 
3822
                /* If the record did not fit, reorganize */
 
3823
 
 
3824
                btr_page_reorganize(block, index, mtr);
 
3825
                page_cur_search(block, index, entry, PAGE_CUR_LE, &page_cur);
 
3826
 
 
3827
                /* This time the record must fit */
 
3828
                if (UNIV_UNLIKELY
 
3829
                    (!page_cur_tuple_insert(&page_cur, entry, index,
 
3830
                                            0, mtr))) {
 
3831
                        ulint   space;
 
3832
                        ulint   page_no;
 
3833
                        ulint   zip_size;
 
3834
 
 
3835
                        ut_print_timestamp(stderr);
 
3836
 
 
3837
                        fprintf(stderr,
 
3838
                                "  InnoDB: Error: Insert buffer insert"
 
3839
                                " fails; page free %lu,"
 
3840
                                " dtuple size %lu\n",
 
3841
                                (ulong) page_get_max_insert_size(
 
3842
                                        page, 1),
 
3843
                                (ulong) rec_get_converted_size(
 
3844
                                        index, entry, 0));
 
3845
                        fputs("InnoDB: Cannot insert index record ",
 
3846
                              stderr);
 
3847
                        dtuple_print(stderr, entry);
 
3848
                        fputs("\nInnoDB: The table where"
 
3849
                              " this index record belongs\n"
 
3850
                              "InnoDB: is now probably corrupt."
 
3851
                              " Please run CHECK TABLE on\n"
 
3852
                              "InnoDB: that table.\n", stderr);
 
3853
 
 
3854
                        space = page_get_space_id(page);
 
3855
                        zip_size = buf_block_get_zip_size(block);
 
3856
                        page_no = page_get_page_no(page);
 
3857
 
 
3858
                        bitmap_page = ibuf_bitmap_get_map_page(
 
3859
                                space, page_no, zip_size, mtr);
 
3860
                        old_bits = ibuf_bitmap_page_get_bits(
 
3861
                                bitmap_page, page_no, zip_size,
 
3862
                                IBUF_BITMAP_FREE, mtr);
 
3863
 
 
3864
                        fprintf(stderr,
 
3865
                                "InnoDB: space %lu, page %lu,"
 
3866
                                " zip_size %lu, bitmap bits %lu\n",
 
3867
                                (ulong) space, (ulong) page_no,
 
3868
                                (ulong) zip_size, (ulong) old_bits);
 
3869
 
 
3870
                        fputs("InnoDB: Submit a detailed bug report"
 
3871
                              " to http://bugs.mysql.com\n", stderr);
3937
3872
                }
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
3873
        }
3970
3874
}
3971
3875
 
3997
3901
                rec = page_cur_get_rec(&page_cur);
3998
3902
                page_zip = page_cur_get_page_zip(&page_cur);
3999
3903
 
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
 
                }
 
3904
                btr_cur_set_deleted_flag_for_ibuf(rec, page_zip, TRUE, mtr);
4012
3905
        } 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);
 
3906
                /* This can happen benignly in some situations. */
4026
3907
        }
4027
3908
}
4028
3909
 
4097
3978
                        mem_heap_free(heap);
4098
3979
                }
4099
3980
        } else {
4100
 
                /* The record must have been purged already. */
 
3981
                /* This can happen benignly in some situations: either when
 
3982
                we crashed at just the right time, or on database startup
 
3983
                when we redo some old log entries (due to worse stored
 
3984
                position granularity on disk than in memory). */
4101
3985
        }
4102
3986
}
4103
3987
 
4191
4075
        success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr);
4192
4076
 
4193
4077
        if (success) {
4194
 
                if (UNIV_UNLIKELY(!page_get_n_recs(btr_pcur_get_page(pcur)))) {
4195
 
                        /* If a B-tree page is empty, it must be the root page
4196
 
                        and the whole B-tree must be empty. InnoDB does not
4197
 
                        allow empty B-tree pages other than the root. */
4198
 
                        root = btr_pcur_get_page(pcur);
4199
 
 
4200
 
                        ut_ad(page_get_space_id(root) == IBUF_SPACE_ID);
4201
 
                        ut_ad(page_get_page_no(root)
4202
 
                              == FSP_IBUF_TREE_ROOT_PAGE_NO);
4203
 
 
4204
 
                        /* ibuf->empty is protected by the root page latch.
4205
 
                        Before the deletion, it had to be FALSE. */
4206
 
                        ut_ad(!ibuf->empty);
4207
 
                        ibuf->empty = TRUE;
4208
 
                }
4209
 
 
4210
4078
#ifdef UNIV_IBUF_COUNT_DEBUG
4211
4079
                fprintf(stderr,
4212
4080
                        "Decrementing ibuf count of space %lu page %lu\n"
4234
4102
        if (!ibuf_restore_pos(space, page_no, search_tuple,
4235
4103
                              BTR_MODIFY_TREE, pcur, mtr)) {
4236
4104
 
4237
 
                mutex_exit(&ibuf_mutex);
4238
4105
                goto func_exit;
4239
4106
        }
4240
4107
 
4248
4115
        ibuf_count_set(space, page_no, ibuf_count_get(space, page_no) - 1);
4249
4116
#endif
4250
4117
        ibuf_size_update(root, mtr);
4251
 
        mutex_exit(&ibuf_mutex);
4252
 
 
4253
 
        ibuf->empty = (page_get_n_recs(root) == 0);
4254
4118
        btr_pcur_commit_specify_mtr(pcur, mtr);
4255
4119
 
4256
4120
func_exit:
4257
4121
        btr_pcur_close(pcur);
4258
4122
 
 
4123
        mutex_exit(&ibuf_mutex);
 
4124
 
4259
4125
        return(TRUE);
4260
4126
}
4261
4127
 
4629
4495
        btr_pcur_close(&pcur);
4630
4496
        mem_heap_free(heap);
4631
4497
 
4632
 
#ifdef HAVE_ATOMIC_BUILTINS
4633
 
        os_atomic_increment_ulint(&ibuf->n_merges, 1);
4634
 
        ibuf_add_ops(ibuf->n_merged_ops, mops);
4635
 
        ibuf_add_ops(ibuf->n_discarded_ops, dops);
4636
 
#else /* HAVE_ATOMIC_BUILTINS */
4637
4498
        /* Protect our statistics keeping from race conditions */
4638
4499
        mutex_enter(&ibuf_mutex);
4639
4500
 
4642
4503
        ibuf_add_ops(ibuf->n_discarded_ops, dops);
4643
4504
 
4644
4505
        mutex_exit(&ibuf_mutex);
4645
 
#endif /* HAVE_ATOMIC_BUILTINS */
4646
4506
 
4647
4507
        if (update_ibuf_bitmap && !tablespace_being_deleted) {
4648
4508
 
4744
4604
        mtr_commit(&mtr);
4745
4605
        btr_pcur_close(&pcur);
4746
4606
 
4747
 
#ifdef HAVE_ATOMIC_BUILTINS
4748
 
        ibuf_add_ops(ibuf->n_discarded_ops, dops);
4749
 
#else /* HAVE_ATOMIC_BUILTINS */
4750
4607
        /* Protect our statistics keeping from race conditions */
4751
4608
        mutex_enter(&ibuf_mutex);
4752
4609
        ibuf_add_ops(ibuf->n_discarded_ops, dops);
4753
4610
        mutex_exit(&ibuf_mutex);
4754
 
#endif /* HAVE_ATOMIC_BUILTINS */
4755
4611
 
4756
4612
        ibuf_exit();
4757
4613
 
4771
4627
        mtr_t           mtr;
4772
4628
 
4773
4629
        ibuf_enter();
 
4630
 
 
4631
        mutex_enter(&ibuf_mutex);
 
4632
 
4774
4633
        mtr_start(&mtr);
4775
4634
 
4776
 
        mutex_enter(&ibuf_mutex);
4777
4635
        root = ibuf_tree_root_get(&mtr);
 
4636
 
 
4637
        if (page_get_n_recs(root) == 0) {
 
4638
 
 
4639
                is_empty = TRUE;
 
4640
 
 
4641
                if (ibuf->empty == FALSE) {
 
4642
                        fprintf(stderr,
 
4643
                                "InnoDB: Warning: insert buffer tree is empty"
 
4644
                                " but the data struct does not\n"
 
4645
                                "InnoDB: know it. This condition is legal"
 
4646
                                " if the master thread has not yet\n"
 
4647
                                "InnoDB: run to completion.\n");
 
4648
                }
 
4649
        } else {
 
4650
                ut_a(ibuf->empty == FALSE);
 
4651
 
 
4652
                is_empty = FALSE;
 
4653
        }
 
4654
 
 
4655
        mtr_commit(&mtr);
 
4656
 
4778
4657
        mutex_exit(&ibuf_mutex);
4779
4658
 
4780
 
        is_empty = (page_get_n_recs(root) == 0);
4781
 
        mtr_commit(&mtr);
4782
4659
        ibuf_exit();
4783
4660
 
4784
 
        ut_a(is_empty == ibuf->empty);
4785
 
 
4786
4661
        return(is_empty);
4787
4662
}
4788
4663