00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "ibuf0ibuf.h"
00027
00029 #define IBUF_BITS_PER_PAGE 4
00030 #if IBUF_BITS_PER_PAGE % 2
00031 # error "IBUF_BITS_PER_PAGE must be an even number!"
00032 #endif
00033
00034 #define IBUF_BITMAP PAGE_DATA
00035
00036 #ifdef UNIV_NONINL
00037 #include "ibuf0ibuf.ic"
00038 #endif
00039
00040 #ifndef UNIV_HOTBACKUP
00041
00042 #include "buf0buf.h"
00043 #include "buf0rea.h"
00044 #include "fsp0fsp.h"
00045 #include "trx0sys.h"
00046 #include "fil0fil.h"
00047 #include "thr0loc.h"
00048 #include "rem0rec.h"
00049 #include "btr0cur.h"
00050 #include "btr0pcur.h"
00051 #include "btr0btr.h"
00052 #include "row0upd.h"
00053 #include "sync0sync.h"
00054 #include "dict0boot.h"
00055 #include "fut0lst.h"
00056 #include "lock0lock.h"
00057 #include "log0recv.h"
00058 #include "que0que.h"
00059 #include "srv0start.h"
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00188 #define IBUF_POOL_SIZE_PER_MAX_SIZE 2
00189
00191 #define IBUF_TABLE_NAME "SYS_IBUF_TABLE"
00192
00194 UNIV_INTERN ibuf_use_t ibuf_use = IBUF_USE_ALL;
00195
00196 #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
00197
00198 UNIV_INTERN uint ibuf_debug;
00199 #endif
00200
00202 UNIV_INTERN ibuf_t* ibuf = NULL;
00203
00205 UNIV_INTERN ulint ibuf_flush_count = 0;
00206
00207 #ifdef UNIV_PFS_MUTEX
00208 UNIV_INTERN mysql_pfs_key_t ibuf_pessimistic_insert_mutex_key;
00209 UNIV_INTERN mysql_pfs_key_t ibuf_mutex_key;
00210 UNIV_INTERN mysql_pfs_key_t ibuf_bitmap_mutex_key;
00211 #endif
00212
00213 #ifdef UNIV_IBUF_COUNT_DEBUG
00214
00215 #define IBUF_COUNT_N_SPACES 4
00216
00217 #define IBUF_COUNT_N_PAGES 130000
00218
00220 static ulint ibuf_counts[IBUF_COUNT_N_SPACES][IBUF_COUNT_N_PAGES];
00221
00222
00224 UNIV_INLINE
00225 void
00226 ibuf_count_check(
00227
00228 ulint space_id,
00229 ulint page_no)
00230 {
00231 if (space_id < IBUF_COUNT_N_SPACES && page_no < IBUF_COUNT_N_PAGES) {
00232 return;
00233 }
00234
00235 fprintf(stderr,
00236 "InnoDB: UNIV_IBUF_COUNT_DEBUG limits space_id and page_no\n"
00237 "InnoDB: and breaks crash recovery.\n"
00238 "InnoDB: space_id=%lu, should be 0<=space_id<%lu\n"
00239 "InnoDB: page_no=%lu, should be 0<=page_no<%lu\n",
00240 (ulint) space_id, (ulint) IBUF_COUNT_N_SPACES,
00241 (ulint) page_no, (ulint) IBUF_COUNT_N_PAGES);
00242 ut_error;
00243 }
00244 #endif
00245
00247
00248 #define IBUF_BITMAP_FREE 0
00250 #define IBUF_BITMAP_BUFFERED 2
00252 #define IBUF_BITMAP_IBUF 3
00256
00257
00258
00259
00260
00261
00265
00266 #define IBUF_REC_INFO_SIZE 4
00268 #if IBUF_REC_INFO_SIZE >= DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
00269 # error "IBUF_REC_INFO_SIZE >= DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE"
00270 #endif
00271
00272
00273 #define IBUF_REC_OFFSET_COUNTER 0
00274 #define IBUF_REC_OFFSET_TYPE 2
00275 #define IBUF_REC_OFFSET_FLAGS 3
00277
00278 #define IBUF_REC_COMPACT 0x1
00285 static mutex_t ibuf_pessimistic_insert_mutex;
00286
00288 static mutex_t ibuf_mutex;
00289
00291 static mutex_t ibuf_bitmap_mutex;
00292
00294 #define IBUF_MERGE_AREA 8
00295
00299 #define IBUF_MERGE_THRESHOLD 4
00300
00303 #define IBUF_MAX_N_PAGES_MERGED IBUF_MERGE_AREA
00304
00308 #define IBUF_CONTRACT_ON_INSERT_NON_SYNC 0
00309
00313 #define IBUF_CONTRACT_ON_INSERT_SYNC 5
00314
00318 #define IBUF_CONTRACT_DO_NOT_INSERT 10
00319
00320
00321
00322
00323
00324
00325
00326
00329 UNIV_INLINE
00330 void
00331 ibuf_enter(void)
00332
00333 {
00334 ibool* ptr;
00335
00336 ptr = thr_local_get_in_ibuf_field();
00337
00338 ut_ad(*ptr == FALSE);
00339
00340 *ptr = TRUE;
00341 }
00342
00343
00346 UNIV_INLINE
00347 void
00348 ibuf_exit(void)
00349
00350 {
00351 ibool* ptr;
00352
00353 ptr = thr_local_get_in_ibuf_field();
00354
00355 ut_ad(*ptr == TRUE);
00356
00357 *ptr = FALSE;
00358 }
00359
00360
00367 UNIV_INTERN
00368 ibool
00369 ibuf_inside(void)
00370
00371 {
00372 return(*thr_local_get_in_ibuf_field());
00373 }
00374
00375
00378 static
00379 page_t*
00380 ibuf_header_page_get(
00381
00382 mtr_t* mtr)
00383 {
00384 buf_block_t* block;
00385
00386 ut_ad(!ibuf_inside());
00387
00388 block = buf_page_get(
00389 IBUF_SPACE_ID, 0, FSP_IBUF_HEADER_PAGE_NO, RW_X_LATCH, mtr);
00390 buf_block_dbg_add_level(block, SYNC_IBUF_HEADER);
00391
00392 return(buf_block_get_frame(block));
00393 }
00394
00395
00398 static
00399 page_t*
00400 ibuf_tree_root_get(
00401
00402 mtr_t* mtr)
00403 {
00404 buf_block_t* block;
00405 page_t* root;
00406
00407 ut_ad(ibuf_inside());
00408 ut_ad(mutex_own(&ibuf_mutex));
00409
00410 mtr_x_lock(dict_index_get_lock(ibuf->index), mtr);
00411
00412 block = buf_page_get(
00413 IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH, mtr);
00414
00415 buf_block_dbg_add_level(block, SYNC_TREE_NODE);
00416
00417 root = buf_block_get_frame(block);
00418
00419 ut_ad(page_get_space_id(root) == IBUF_SPACE_ID);
00420 ut_ad(page_get_page_no(root) == FSP_IBUF_TREE_ROOT_PAGE_NO);
00421 ut_ad(ibuf->empty == (page_get_n_recs(root) == 0));
00422
00423 return(root);
00424 }
00425
00426 #ifdef UNIV_IBUF_COUNT_DEBUG
00427
00431 UNIV_INTERN
00432 ulint
00433 ibuf_count_get(
00434
00435 ulint space,
00436 ulint page_no)
00437 {
00438 ibuf_count_check(space, page_no);
00439
00440 return(ibuf_counts[space][page_no]);
00441 }
00442
00443
00445 static
00446 void
00447 ibuf_count_set(
00448
00449 ulint space,
00450 ulint page_no,
00451 ulint val)
00452 {
00453 ibuf_count_check(space, page_no);
00454 ut_a(val < UNIV_PAGE_SIZE);
00455
00456 ibuf_counts[space][page_no] = val;
00457 }
00458 #endif
00459
00460
00462 UNIV_INTERN
00463 void
00464 ibuf_close(void)
00465
00466 {
00467 mutex_free(&ibuf_pessimistic_insert_mutex);
00468 memset(&ibuf_pessimistic_insert_mutex,
00469 0x0, sizeof(ibuf_pessimistic_insert_mutex));
00470
00471 mutex_free(&ibuf_mutex);
00472 memset(&ibuf_mutex, 0x0, sizeof(ibuf_mutex));
00473
00474 mutex_free(&ibuf_bitmap_mutex);
00475 memset(&ibuf_bitmap_mutex, 0x0, sizeof(ibuf_mutex));
00476
00477 mem_free(ibuf);
00478 ibuf = NULL;
00479 }
00480
00481
00484 static
00485 void
00486 ibuf_size_update(
00487
00488 const page_t* root,
00489 mtr_t* mtr)
00490 {
00491 ut_ad(mutex_own(&ibuf_mutex));
00492
00493 ibuf->free_list_len = flst_get_len(root + PAGE_HEADER
00494 + PAGE_BTR_IBUF_FREE_LIST, mtr);
00495
00496 ibuf->height = 1 + btr_page_get_level(root, mtr);
00497
00498
00499 ibuf->size = ibuf->seg_size - (1 + ibuf->free_list_len);
00500 }
00501
00502
00505 UNIV_INTERN
00506 void
00507 ibuf_init_at_db_start(void)
00508
00509 {
00510 page_t* root;
00511 mtr_t mtr;
00512 dict_table_t* table;
00513 mem_heap_t* heap;
00514 dict_index_t* index;
00515 ulint n_used;
00516 page_t* header_page;
00517 ulint error;
00518
00519 ibuf = static_cast<ibuf_t *>(mem_alloc(sizeof(ibuf_t)));
00520
00521 memset(ibuf, 0, sizeof(*ibuf));
00522
00523
00524
00525
00526
00527 ibuf->max_size = ut_min(buf_pool_get_curr_size() / UNIV_PAGE_SIZE
00528 / IBUF_POOL_SIZE_PER_MAX_SIZE,
00529 srv_ibuf_max_size / UNIV_PAGE_SIZE);
00530 srv_ibuf_max_size = ibuf->max_size * UNIV_PAGE_SIZE;
00531
00532 mutex_create(ibuf_pessimistic_insert_mutex_key,
00533 &ibuf_pessimistic_insert_mutex,
00534 SYNC_IBUF_PESS_INSERT_MUTEX);
00535
00536 mutex_create(ibuf_mutex_key,
00537 &ibuf_mutex, SYNC_IBUF_MUTEX);
00538
00539 mutex_create(ibuf_bitmap_mutex_key,
00540 &ibuf_bitmap_mutex, SYNC_IBUF_BITMAP_MUTEX);
00541
00542 mtr_start(&mtr);
00543
00544 mutex_enter(&ibuf_mutex);
00545
00546 mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, NULL), &mtr);
00547
00548 header_page = ibuf_header_page_get(&mtr);
00549
00550 fseg_n_reserved_pages(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
00551 &n_used, &mtr);
00552 ibuf_enter();
00553
00554 ut_ad(n_used >= 2);
00555
00556 ibuf->seg_size = n_used;
00557
00558 {
00559 buf_block_t* block;
00560
00561 block = buf_page_get(
00562 IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO,
00563 RW_X_LATCH, &mtr);
00564 buf_block_dbg_add_level(block, SYNC_TREE_NODE);
00565
00566 root = buf_block_get_frame(block);
00567 }
00568
00569 ibuf_size_update(root, &mtr);
00570 mutex_exit(&ibuf_mutex);
00571
00572 ibuf->empty = (page_get_n_recs(root) == 0);
00573 mtr_commit(&mtr);
00574
00575 ibuf_exit();
00576
00577 heap = mem_heap_create(450);
00578
00579
00580 table = dict_mem_table_create(IBUF_TABLE_NAME, IBUF_SPACE_ID, 1, 0);
00581
00582 dict_mem_table_add_col(table, heap, "DUMMY_COLUMN", DATA_BINARY, 0, 0);
00583
00584 table->id = DICT_IBUF_ID_MIN + IBUF_SPACE_ID;
00585
00586 dict_table_add_to_cache(table, heap);
00587 mem_heap_free(heap);
00588
00589 index = dict_mem_index_create(
00590 IBUF_TABLE_NAME, "CLUST_IND",
00591 IBUF_SPACE_ID, DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF, 1);
00592
00593 dict_mem_index_add_field(index, "DUMMY_COLUMN", 0);
00594
00595 index->id = DICT_IBUF_ID_MIN + IBUF_SPACE_ID;
00596
00597 error = dict_index_add_to_cache(table, index,
00598 FSP_IBUF_TREE_ROOT_PAGE_NO, FALSE);
00599 ut_a(error == DB_SUCCESS);
00600
00601 ibuf->index = dict_table_get_first_index(table);
00602 }
00603 #endif
00604
00606 UNIV_INTERN
00607 void
00608 ibuf_bitmap_page_init(
00609
00610 buf_block_t* block,
00611 mtr_t* mtr)
00612 {
00613 page_t* page;
00614 ulint byte_offset;
00615 ulint zip_size = buf_block_get_zip_size(block);
00616
00617 ut_a(ut_is_2pow(zip_size));
00618
00619 page = buf_block_get_frame(block);
00620 fil_page_set_type(page, FIL_PAGE_IBUF_BITMAP);
00621
00622
00623
00624 if (!zip_size) {
00625 byte_offset = UT_BITS_IN_BYTES(UNIV_PAGE_SIZE
00626 * IBUF_BITS_PER_PAGE);
00627 } else {
00628 byte_offset = UT_BITS_IN_BYTES(zip_size * IBUF_BITS_PER_PAGE);
00629 }
00630
00631 memset(page + IBUF_BITMAP, 0, byte_offset);
00632
00633
00634
00635 #ifndef UNIV_HOTBACKUP
00636 mlog_write_initial_log_record(page, MLOG_IBUF_BITMAP_INIT, mtr);
00637 #endif
00638 }
00639
00640
00643 UNIV_INTERN
00644 byte*
00645 ibuf_parse_bitmap_init(
00646
00647 byte* ptr,
00648 byte* ,
00649 buf_block_t* block,
00650 mtr_t* mtr)
00651 {
00652 ut_ad(ptr && end_ptr);
00653
00654 if (block) {
00655 ibuf_bitmap_page_init(block, mtr);
00656 }
00657
00658 return(ptr);
00659 }
00660 #ifndef UNIV_HOTBACKUP
00661
00664 UNIV_INLINE
00665 ulint
00666 ibuf_bitmap_page_get_bits(
00667
00668 const page_t* page,
00669 ulint page_no,
00670 ulint zip_size,
00672 ulint bit,
00674 mtr_t* )
00677 {
00678 ulint byte_offset;
00679 ulint bit_offset;
00680 ulint map_byte;
00681 ulint value;
00682
00683 ut_ad(bit < IBUF_BITS_PER_PAGE);
00684 #if IBUF_BITS_PER_PAGE % 2
00685 # error "IBUF_BITS_PER_PAGE % 2 != 0"
00686 #endif
00687 ut_ad(ut_is_2pow(zip_size));
00688 ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
00689
00690 if (!zip_size) {
00691 bit_offset = (page_no % UNIV_PAGE_SIZE) * IBUF_BITS_PER_PAGE
00692 + bit;
00693 } else {
00694 bit_offset = (page_no & (zip_size - 1)) * IBUF_BITS_PER_PAGE
00695 + bit;
00696 }
00697
00698 byte_offset = bit_offset / 8;
00699 bit_offset = bit_offset % 8;
00700
00701 ut_ad(byte_offset + IBUF_BITMAP < UNIV_PAGE_SIZE);
00702
00703 map_byte = mach_read_from_1(page + IBUF_BITMAP + byte_offset);
00704
00705 value = ut_bit_get_nth(map_byte, bit_offset);
00706
00707 if (bit == IBUF_BITMAP_FREE) {
00708 ut_ad(bit_offset + 1 < 8);
00709
00710 value = value * 2 + ut_bit_get_nth(map_byte, bit_offset + 1);
00711 }
00712
00713 return(value);
00714 }
00715
00716
00718 static
00719 void
00720 ibuf_bitmap_page_set_bits(
00721
00722 page_t* page,
00723 ulint page_no,
00724 ulint zip_size,
00726 ulint bit,
00727 ulint val,
00728 mtr_t* mtr)
00729 {
00730 ulint byte_offset;
00731 ulint bit_offset;
00732 ulint map_byte;
00733
00734 ut_ad(bit < IBUF_BITS_PER_PAGE);
00735 #if IBUF_BITS_PER_PAGE % 2
00736 # error "IBUF_BITS_PER_PAGE % 2 != 0"
00737 #endif
00738 ut_ad(ut_is_2pow(zip_size));
00739 ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
00740 #ifdef UNIV_IBUF_COUNT_DEBUG
00741 ut_a((bit != IBUF_BITMAP_BUFFERED) || (val != FALSE)
00742 || (0 == ibuf_count_get(page_get_space_id(page),
00743 page_no)));
00744 #endif
00745 if (!zip_size) {
00746 bit_offset = (page_no % UNIV_PAGE_SIZE) * IBUF_BITS_PER_PAGE
00747 + bit;
00748 } else {
00749 bit_offset = (page_no & (zip_size - 1)) * IBUF_BITS_PER_PAGE
00750 + bit;
00751 }
00752
00753 byte_offset = bit_offset / 8;
00754 bit_offset = bit_offset % 8;
00755
00756 ut_ad(byte_offset + IBUF_BITMAP < UNIV_PAGE_SIZE);
00757
00758 map_byte = mach_read_from_1(page + IBUF_BITMAP + byte_offset);
00759
00760 if (bit == IBUF_BITMAP_FREE) {
00761 ut_ad(bit_offset + 1 < 8);
00762 ut_ad(val <= 3);
00763
00764 map_byte = ut_bit_set_nth(map_byte, bit_offset, val / 2);
00765 map_byte = ut_bit_set_nth(map_byte, bit_offset + 1, val % 2);
00766 } else {
00767 ut_ad(val <= 1);
00768 map_byte = ut_bit_set_nth(map_byte, bit_offset, val);
00769 }
00770
00771 mlog_write_ulint(page + IBUF_BITMAP + byte_offset, map_byte,
00772 MLOG_1BYTE, mtr);
00773 }
00774
00775
00778 UNIV_INLINE
00779 ulint
00780 ibuf_bitmap_page_no_calc(
00781
00782 ulint zip_size,
00784 ulint page_no)
00785 {
00786 ut_ad(ut_is_2pow(zip_size));
00787
00788 if (!zip_size) {
00789 return(FSP_IBUF_BITMAP_OFFSET
00790 + (page_no & ~(UNIV_PAGE_SIZE - 1)));
00791 } else {
00792 return(FSP_IBUF_BITMAP_OFFSET
00793 + (page_no & ~(zip_size - 1)));
00794 }
00795 }
00796
00797
00803 static
00804 page_t*
00805 ibuf_bitmap_get_map_page_func(
00806
00807 ulint space,
00808 ulint page_no,
00809 ulint zip_size,
00811 const char* file,
00812 ulint line,
00813 mtr_t* mtr)
00814 {
00815 buf_block_t* block;
00816
00817 block = buf_page_get_gen(space, zip_size,
00818 ibuf_bitmap_page_no_calc(zip_size, page_no),
00819 RW_X_LATCH, NULL, BUF_GET,
00820 file, line, mtr);
00821 buf_block_dbg_add_level(block, SYNC_IBUF_BITMAP);
00822
00823 return(buf_block_get_frame(block));
00824 }
00825
00826
00836 #define ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr) \
00837 ibuf_bitmap_get_map_page_func(space, page_no, zip_size, \
00838 __FILE__, __LINE__, mtr)
00839
00840
00845 UNIV_INLINE
00846 void
00847 ibuf_set_free_bits_low(
00848
00849 ulint zip_size,
00851 const buf_block_t* block,
00854 ulint val,
00855 mtr_t* mtr)
00856 {
00857 page_t* bitmap_page;
00858 ulint space;
00859 ulint page_no;
00860
00861 if (!page_is_leaf(buf_block_get_frame(block))) {
00862
00863 return;
00864 }
00865
00866 space = buf_block_get_space(block);
00867 page_no = buf_block_get_page_no(block);
00868 bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr);
00869 #ifdef UNIV_IBUF_DEBUG
00870 # if 0
00871 fprintf(stderr,
00872 "Setting space %lu page %lu free bits to %lu should be %lu\n",
00873 space, page_no, val,
00874 ibuf_index_page_calc_free(zip_size, block));
00875 # endif
00876
00877 ut_a(val <= ibuf_index_page_calc_free(zip_size, block));
00878 #endif
00879 ibuf_bitmap_page_set_bits(bitmap_page, page_no, zip_size,
00880 IBUF_BITMAP_FREE, val, mtr);
00881 }
00882
00883
00888 UNIV_INTERN
00889 void
00890 ibuf_set_free_bits_func(
00891
00892 buf_block_t* block,
00894 #ifdef UNIV_IBUF_DEBUG
00895 ulint max_val,
00898 #endif
00899 ulint val)
00900 {
00901 mtr_t mtr;
00902 page_t* page;
00903 page_t* bitmap_page;
00904 ulint space;
00905 ulint page_no;
00906 ulint zip_size;
00907
00908 page = buf_block_get_frame(block);
00909
00910 if (!page_is_leaf(page)) {
00911
00912 return;
00913 }
00914
00915 mtr_start(&mtr);
00916
00917 space = buf_block_get_space(block);
00918 page_no = buf_block_get_page_no(block);
00919 zip_size = buf_block_get_zip_size(block);
00920 bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, &mtr);
00921
00922 #ifdef UNIV_IBUF_DEBUG
00923 if (max_val != ULINT_UNDEFINED) {
00924 ulint old_val;
00925
00926 old_val = ibuf_bitmap_page_get_bits(
00927 bitmap_page, page_no, zip_size,
00928 IBUF_BITMAP_FREE, &mtr);
00929 # if 0
00930 if (old_val != max_val) {
00931 fprintf(stderr,
00932 "Ibuf: page %lu old val %lu max val %lu\n",
00933 page_get_page_no(page),
00934 old_val, max_val);
00935 }
00936 # endif
00937
00938 ut_a(old_val <= max_val);
00939 }
00940 # if 0
00941 fprintf(stderr, "Setting page no %lu free bits to %lu should be %lu\n",
00942 page_get_page_no(page), val,
00943 ibuf_index_page_calc_free(zip_size, block));
00944 # endif
00945
00946 ut_a(val <= ibuf_index_page_calc_free(zip_size, block));
00947 #endif
00948 ibuf_bitmap_page_set_bits(bitmap_page, page_no, zip_size,
00949 IBUF_BITMAP_FREE, val, &mtr);
00950 mtr_commit(&mtr);
00951 }
00952
00953
00962 UNIV_INTERN
00963 void
00964 ibuf_reset_free_bits(
00965
00966 buf_block_t* block)
00969 {
00970 ibuf_set_free_bits(block, 0, ULINT_UNDEFINED);
00971 }
00972
00973
00981 UNIV_INTERN
00982 void
00983 ibuf_update_free_bits_low(
00984
00985 const buf_block_t* block,
00986 ulint max_ins_size,
00991 mtr_t* mtr)
00992 {
00993 ulint before;
00994 ulint after;
00995
00996 ut_a(!buf_block_get_page_zip(block));
00997
00998 before = ibuf_index_page_calc_free_bits(0, max_ins_size);
00999
01000 after = ibuf_index_page_calc_free(0, block);
01001
01002
01003
01004
01005
01006 if (before != after) {
01007 ibuf_set_free_bits_low(0, block, after, mtr);
01008 }
01009 }
01010
01011
01019 UNIV_INTERN
01020 void
01021 ibuf_update_free_bits_zip(
01022
01023 buf_block_t* block,
01024 mtr_t* mtr)
01025 {
01026 page_t* bitmap_page;
01027 ulint space;
01028 ulint page_no;
01029 ulint zip_size;
01030 ulint after;
01031
01032 space = buf_block_get_space(block);
01033 page_no = buf_block_get_page_no(block);
01034 zip_size = buf_block_get_zip_size(block);
01035
01036 ut_a(page_is_leaf(buf_block_get_frame(block)));
01037 ut_a(zip_size);
01038
01039 bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr);
01040
01041 after = ibuf_index_page_calc_free_zip(zip_size, block);
01042
01043 if (after == 0) {
01044
01045
01046
01047
01048
01049 buf_page_make_young(&block->page);
01050 }
01051
01052 ibuf_bitmap_page_set_bits(bitmap_page, page_no, zip_size,
01053 IBUF_BITMAP_FREE, after, mtr);
01054 }
01055
01056
01063 UNIV_INTERN
01064 void
01065 ibuf_update_free_bits_for_two_pages_low(
01066
01067 ulint zip_size,
01069 buf_block_t* block1,
01070 buf_block_t* block2,
01071 mtr_t* mtr)
01072 {
01073 ulint state;
01074
01075
01076
01077
01078
01079 mutex_enter(&ibuf_bitmap_mutex);
01080
01081 state = ibuf_index_page_calc_free(zip_size, block1);
01082
01083 ibuf_set_free_bits_low(zip_size, block1, state, mtr);
01084
01085 state = ibuf_index_page_calc_free(zip_size, block2);
01086
01087 ibuf_set_free_bits_low(zip_size, block2, state, mtr);
01088
01089 mutex_exit(&ibuf_bitmap_mutex);
01090 }
01091
01092
01095 UNIV_INLINE
01096 ibool
01097 ibuf_fixed_addr_page(
01098
01099 ulint space,
01100 ulint zip_size,
01102 ulint page_no)
01103 {
01104 return((space == IBUF_SPACE_ID && page_no == IBUF_TREE_ROOT_PAGE_NO)
01105 || ibuf_bitmap_page(zip_size, page_no));
01106 }
01107
01108
01112 UNIV_INTERN
01113 ibool
01114 ibuf_page(
01115
01116 ulint space,
01117 ulint zip_size,
01118 ulint page_no,
01119 mtr_t* mtr)
01123 {
01124 ibool ret;
01125 mtr_t local_mtr;
01126 page_t* bitmap_page;
01127
01128 ut_ad(!recv_no_ibuf_operations);
01129
01130 if (srv_fake_write)
01131 return(FALSE);
01132
01133 if (ibuf_fixed_addr_page(space, zip_size, page_no)) {
01134
01135 return(TRUE);
01136 } else if (space != IBUF_SPACE_ID) {
01137
01138 return(FALSE);
01139 }
01140
01141 ut_ad(fil_space_get_type(IBUF_SPACE_ID) == FIL_TABLESPACE);
01142
01143 if (mtr == NULL) {
01144 mtr = &local_mtr;
01145 mtr_start(mtr);
01146 }
01147
01148 bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr);
01149
01150 ret = ibuf_bitmap_page_get_bits(bitmap_page, page_no, zip_size,
01151 IBUF_BITMAP_IBUF, mtr);
01152
01153 if (mtr == &local_mtr) {
01154 mtr_commit(mtr);
01155 }
01156
01157 return(ret);
01158 }
01159
01160
01163 static
01164 ulint
01165 ibuf_rec_get_page_no(
01166
01167 const rec_t* rec)
01168 {
01169 const byte* field;
01170 ulint len;
01171
01172 ut_ad(ibuf_inside());
01173 ut_ad(rec_get_n_fields_old(rec) > 2);
01174
01175 field = rec_get_nth_field_old(rec, 1, &len);
01176
01177 if (len == 1) {
01178
01179 ut_a(trx_sys_multiple_tablespace_format);
01180
01181 field = rec_get_nth_field_old(rec, 2, &len);
01182 } else {
01183 ut_a(trx_doublewrite_must_reset_space_ids);
01184 ut_a(!trx_sys_multiple_tablespace_format);
01185
01186 field = rec_get_nth_field_old(rec, 0, &len);
01187 }
01188
01189 ut_a(len == 4);
01190
01191 return(mach_read_from_4(field));
01192 }
01193
01194
01198 static
01199 ulint
01200 ibuf_rec_get_space(
01201
01202 const rec_t* rec)
01203 {
01204 const byte* field;
01205 ulint len;
01206
01207 ut_ad(ibuf_inside());
01208 ut_ad(rec_get_n_fields_old(rec) > 2);
01209
01210 field = rec_get_nth_field_old(rec, 1, &len);
01211
01212 if (len == 1) {
01213
01214
01215 ut_a(trx_sys_multiple_tablespace_format);
01216 field = rec_get_nth_field_old(rec, 0, &len);
01217 ut_a(len == 4);
01218
01219 return(mach_read_from_4(field));
01220 }
01221
01222 ut_a(trx_doublewrite_must_reset_space_ids);
01223 ut_a(!trx_sys_multiple_tablespace_format);
01224
01225 return(0);
01226 }
01227
01228
01230 static
01231 void
01232 ibuf_rec_get_info(
01233
01234 const rec_t* rec,
01235 ibuf_op_t* op,
01236 ibool* comp,
01237 ulint* info_len,
01240 ulint* counter)
01241 {
01242 const byte* types;
01243 ulint fields;
01244 ulint len;
01245
01246
01247 ibuf_op_t op_local;
01248 ibool comp_local;
01249 ulint info_len_local;
01250 ulint counter_local;
01251
01252 ut_ad(ibuf_inside());
01253 fields = rec_get_n_fields_old(rec);
01254 ut_a(fields > 4);
01255
01256 types = rec_get_nth_field_old(rec, 3, &len);
01257
01258 info_len_local = len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE;
01259
01260 switch (info_len_local) {
01261 case 0:
01262 case 1:
01263 op_local = IBUF_OP_INSERT;
01264 comp_local = info_len_local;
01265 ut_ad(!counter);
01266 counter_local = ULINT_UNDEFINED;
01267 break;
01268
01269 case IBUF_REC_INFO_SIZE:
01270 op_local = (ibuf_op_t)types[IBUF_REC_OFFSET_TYPE];
01271 comp_local = types[IBUF_REC_OFFSET_FLAGS] & IBUF_REC_COMPACT;
01272 counter_local = mach_read_from_2(
01273 types + IBUF_REC_OFFSET_COUNTER);
01274 break;
01275
01276 default:
01277 ut_error;
01278 }
01279
01280 ut_a(op_local < IBUF_OP_COUNT);
01281 ut_a((len - info_len_local) ==
01282 (fields - 4) * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
01283
01284 if (op) {
01285 *op = op_local;
01286 }
01287
01288 if (comp) {
01289 *comp = comp_local;
01290 }
01291
01292 if (info_len) {
01293 *info_len = info_len_local;
01294 }
01295
01296 if (counter) {
01297 *counter = counter_local;
01298 }
01299 }
01300
01301
01304 static
01305 ibuf_op_t
01306 ibuf_rec_get_op_type(
01307
01308 const rec_t* rec)
01309 {
01310 ulint len;
01311
01312 ut_ad(ibuf_inside());
01313 ut_ad(rec_get_n_fields_old(rec) > 2);
01314
01315 (void) rec_get_nth_field_old(rec, 1, &len);
01316
01317 if (len > 1) {
01318
01319
01320 return(IBUF_OP_INSERT);
01321 } else {
01322 ibuf_op_t op;
01323
01324 ibuf_rec_get_info(rec, &op, NULL, NULL, NULL);
01325
01326 return(op);
01327 }
01328 }
01329
01330
01335 UNIV_INTERN
01336 ulint
01337 ibuf_rec_get_counter(
01338
01339 const rec_t* rec)
01340 {
01341 const byte* ptr;
01342 ulint len;
01343
01344 if (rec_get_n_fields_old(rec) < 4) {
01345
01346 return(ULINT_UNDEFINED);
01347 }
01348
01349 ptr = rec_get_nth_field_old(rec, 3, &len);
01350
01351 if (len >= 2) {
01352
01353 return(mach_read_from_2(ptr));
01354 } else {
01355
01356 return(ULINT_UNDEFINED);
01357 }
01358 }
01359
01360
01363 static
01364 void
01365 ibuf_add_ops(
01366
01367 ulint* arr,
01368 const ulint* ops)
01370 {
01371 ulint i;
01372
01373 #ifndef HAVE_ATOMIC_BUILTINS
01374 ut_ad(mutex_own(&ibuf_mutex));
01375 #endif
01376
01377 for (i = 0; i < IBUF_OP_COUNT; i++) {
01378 #ifdef HAVE_ATOMIC_BUILTINS
01379 os_atomic_increment_ulint(&arr[i], ops[i]);
01380 #else
01381 arr[i] += ops[i];
01382 #endif
01383 }
01384 }
01385
01386
01388 static
01389 void
01390 ibuf_print_ops(
01391
01392 const ulint* ops,
01393 FILE* file)
01394 {
01395 static const char* op_names[] = {
01396 "insert",
01397 "delete mark",
01398 "delete"
01399 };
01400 ulint i;
01401
01402 ut_a(UT_ARR_SIZE(op_names) == IBUF_OP_COUNT);
01403
01404 for (i = 0; i < IBUF_OP_COUNT; i++) {
01405 fprintf(file, "%s %lu%s", op_names[i],
01406 (ulong) ops[i], (i < (IBUF_OP_COUNT - 1)) ? ", " : "");
01407 }
01408
01409 putc('\n', file);
01410 }
01411
01412
01415 static
01416 dict_index_t*
01417 ibuf_dummy_index_create(
01418
01419 ulint n,
01420 ibool comp)
01421 {
01422 dict_table_t* table;
01423 dict_index_t* index;
01424
01425 table = dict_mem_table_create("IBUF_DUMMY",
01426 DICT_HDR_SPACE, n,
01427 comp ? DICT_TF_COMPACT : 0);
01428
01429 index = dict_mem_index_create("IBUF_DUMMY", "IBUF_DUMMY",
01430 DICT_HDR_SPACE, 0, n);
01431
01432 index->table = table;
01433
01434
01435 index->cached = TRUE;
01436
01437 return(index);
01438 }
01439
01441 static
01442 void
01443 ibuf_dummy_index_add_col(
01444
01445 dict_index_t* index,
01446 const dtype_t* type,
01447 ulint len)
01448 {
01449 ulint i = index->table->n_def;
01450 dict_mem_table_add_col(index->table, NULL, NULL,
01451 dtype_get_mtype(type),
01452 dtype_get_prtype(type),
01453 dtype_get_len(type));
01454 dict_index_add_col(index, index->table,
01455 dict_table_get_nth_col(index->table, i), len);
01456 }
01457
01459 static
01460 void
01461 ibuf_dummy_index_free(
01462
01463 dict_index_t* index)
01464 {
01465 dict_table_t* table = index->table;
01466
01467 dict_mem_index_free(index);
01468 dict_mem_table_free(table);
01469 }
01470
01471
01479 UNIV_INLINE
01480 dtuple_t*
01481 ibuf_build_entry_pre_4_1_x(
01482
01483 const rec_t* ibuf_rec,
01484 mem_heap_t* heap,
01485 dict_index_t** pindex)
01487 {
01488 ulint i;
01489 ulint len;
01490 const byte* types;
01491 dtuple_t* tuple;
01492 ulint n_fields;
01493
01494 ut_a(trx_doublewrite_must_reset_space_ids);
01495 ut_a(!trx_sys_multiple_tablespace_format);
01496
01497 n_fields = rec_get_n_fields_old(ibuf_rec) - 2;
01498 tuple = dtuple_create(heap, n_fields);
01499 types = rec_get_nth_field_old(ibuf_rec, 1, &len);
01500
01501 ut_a(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
01502
01503 for (i = 0; i < n_fields; i++) {
01504 const byte* data;
01505 dfield_t* field;
01506
01507 field = dtuple_get_nth_field(tuple, i);
01508
01509 data = rec_get_nth_field_old(ibuf_rec, i + 2, &len);
01510
01511 dfield_set_data(field, data, len);
01512
01513 dtype_read_for_order_and_null_size(
01514 dfield_get_type(field),
01515 types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
01516 }
01517
01518 *pindex = ibuf_dummy_index_create(n_fields, FALSE);
01519
01520 return(tuple);
01521 }
01522
01523
01539 static
01540 dtuple_t*
01541 ibuf_build_entry_from_ibuf_rec(
01542
01543 const rec_t* ibuf_rec,
01544 mem_heap_t* heap,
01545 dict_index_t** pindex)
01547 {
01548 dtuple_t* tuple;
01549 dfield_t* field;
01550 ulint n_fields;
01551 const byte* types;
01552 const byte* data;
01553 ulint len;
01554 ulint info_len;
01555 ulint i;
01556 ulint comp;
01557 dict_index_t* index;
01558
01559 data = rec_get_nth_field_old(ibuf_rec, 1, &len);
01560
01561 if (len > 1) {
01562
01563
01564 return(ibuf_build_entry_pre_4_1_x(ibuf_rec, heap, pindex));
01565 }
01566
01567
01568
01569 ut_a(trx_sys_multiple_tablespace_format);
01570 ut_a(*data == 0);
01571 ut_a(rec_get_n_fields_old(ibuf_rec) > 4);
01572
01573 n_fields = rec_get_n_fields_old(ibuf_rec) - 4;
01574
01575 tuple = dtuple_create(heap, n_fields);
01576
01577 types = rec_get_nth_field_old(ibuf_rec, 3, &len);
01578
01579 ibuf_rec_get_info(ibuf_rec, NULL, &comp, &info_len, NULL);
01580
01581 index = ibuf_dummy_index_create(n_fields, comp);
01582
01583 len -= info_len;
01584 types += info_len;
01585
01586 ut_a(len == n_fields * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
01587
01588 for (i = 0; i < n_fields; i++) {
01589 field = dtuple_get_nth_field(tuple, i);
01590
01591 data = rec_get_nth_field_old(ibuf_rec, i + 4, &len);
01592
01593 dfield_set_data(field, data, len);
01594
01595 dtype_new_read_for_order_and_null_size(
01596 dfield_get_type(field),
01597 types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
01598
01599 ibuf_dummy_index_add_col(index, dfield_get_type(field), len);
01600 }
01601
01602
01603
01604
01605
01606
01607 ut_d(dict_table_add_system_columns(index->table, index->table->heap));
01608
01609 *pindex = index;
01610
01611 return(tuple);
01612 }
01613
01614
01617 UNIV_INLINE
01618 ulint
01619 ibuf_rec_get_size(
01620
01621 const rec_t* rec,
01622 const byte* types,
01623 ulint n_fields,
01624 ibool pre_4_1,
01626 ulint comp)
01628 {
01629 ulint i;
01630 ulint field_offset;
01631 ulint types_offset;
01632 ulint size = 0;
01633
01634 if (pre_4_1) {
01635 field_offset = 2;
01636 types_offset = DATA_ORDER_NULL_TYPE_BUF_SIZE;
01637 } else {
01638 field_offset = 4;
01639 types_offset = DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE;
01640 }
01641
01642 for (i = 0; i < n_fields; i++) {
01643 ulint len;
01644 dtype_t dtype;
01645
01646 rec_get_nth_field_offs_old(rec, i + field_offset, &len);
01647
01648 if (len != UNIV_SQL_NULL) {
01649 size += len;
01650 } else if (pre_4_1) {
01651 dtype_read_for_order_and_null_size(&dtype, types);
01652
01653 size += dtype_get_sql_null_size(&dtype, comp);
01654 } else {
01655 dtype_new_read_for_order_and_null_size(&dtype, types);
01656
01657 size += dtype_get_sql_null_size(&dtype, comp);
01658 }
01659
01660 types += types_offset;
01661 }
01662
01663 return(size);
01664 }
01665
01666
01671 static
01672 ulint
01673 ibuf_rec_get_volume(
01674
01675 const rec_t* ibuf_rec)
01676 {
01677 ulint len;
01678 const byte* data;
01679 const byte* types;
01680 ulint n_fields;
01681 ulint data_size;
01682 ibool pre_4_1;
01683 ulint comp;
01684
01685 ut_ad(ibuf_inside());
01686 ut_ad(rec_get_n_fields_old(ibuf_rec) > 2);
01687
01688 data = rec_get_nth_field_old(ibuf_rec, 1, &len);
01689 pre_4_1 = (len > 1);
01690
01691 if (pre_4_1) {
01692
01693
01694 ut_a(trx_doublewrite_must_reset_space_ids);
01695 ut_a(!trx_sys_multiple_tablespace_format);
01696
01697 n_fields = rec_get_n_fields_old(ibuf_rec) - 2;
01698
01699 types = rec_get_nth_field_old(ibuf_rec, 1, &len);
01700
01701 ut_ad(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
01702 comp = 0;
01703 } else {
01704
01705 ibuf_op_t op;
01706 ulint info_len;
01707
01708 ut_a(trx_sys_multiple_tablespace_format);
01709 ut_a(*data == 0);
01710
01711 types = rec_get_nth_field_old(ibuf_rec, 3, &len);
01712
01713 ibuf_rec_get_info(ibuf_rec, &op, &comp, &info_len, NULL);
01714
01715 if (op == IBUF_OP_DELETE_MARK || op == IBUF_OP_DELETE) {
01716
01717
01718
01719
01720
01721
01722 return(0);
01723 } else if (comp) {
01724 dtuple_t* entry;
01725 ulint volume;
01726 dict_index_t* dummy_index;
01727 mem_heap_t* heap = mem_heap_create(500);
01728
01729 entry = ibuf_build_entry_from_ibuf_rec(
01730 ibuf_rec, heap, &dummy_index);
01731
01732 volume = rec_get_converted_size(dummy_index, entry, 0);
01733
01734 ibuf_dummy_index_free(dummy_index);
01735 mem_heap_free(heap);
01736
01737 return(volume + page_dir_calc_reserved_space(1));
01738 }
01739
01740 types += info_len;
01741 n_fields = rec_get_n_fields_old(ibuf_rec) - 4;
01742 }
01743
01744 data_size = ibuf_rec_get_size(ibuf_rec, types, n_fields, pre_4_1, comp);
01745
01746 return(data_size + rec_get_converted_extra_size(data_size, n_fields, 0)
01747 + page_dir_calc_reserved_space(1));
01748 }
01749
01750
01758 static
01759 dtuple_t*
01760 ibuf_entry_build(
01761
01762 ibuf_op_t op,
01763 dict_index_t* index,
01764 const dtuple_t* entry,
01765 ulint space,
01766 ulint page_no,
01768 ulint counter,
01770 mem_heap_t* heap)
01771 {
01772 dtuple_t* tuple;
01773 dfield_t* field;
01774 const dfield_t* entry_field;
01775 ulint n_fields;
01776 byte* buf;
01777 byte* ti;
01778 byte* type_info;
01779 ulint i;
01780
01781 ut_ad(counter != ULINT_UNDEFINED || op == IBUF_OP_INSERT);
01782 ut_ad(counter == ULINT_UNDEFINED || counter <= 0xFFFF);
01783 ut_ad(op < IBUF_OP_COUNT);
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794 n_fields = dtuple_get_n_fields(entry);
01795
01796 tuple = dtuple_create(heap, n_fields + 4);
01797
01798
01799
01800 field = dtuple_get_nth_field(tuple, 0);
01801
01802 buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
01803
01804 mach_write_to_4(buf, space);
01805
01806 dfield_set_data(field, buf, 4);
01807
01808
01809
01810 field = dtuple_get_nth_field(tuple, 1);
01811
01812 buf = static_cast<byte *>(mem_heap_alloc(heap, 1));
01813
01814
01815
01816 mach_write_to_1(buf, 0);
01817
01818 dfield_set_data(field, buf, 1);
01819
01820
01821
01822 field = dtuple_get_nth_field(tuple, 2);
01823
01824 buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
01825
01826 mach_write_to_4(buf, page_no);
01827
01828 dfield_set_data(field, buf, 4);
01829
01830
01831
01832 if (counter == ULINT_UNDEFINED) {
01833 i = dict_table_is_comp(index->table) ? 1 : 0;
01834 } else {
01835 ut_ad(counter <= 0xFFFF);
01836 i = IBUF_REC_INFO_SIZE;
01837 }
01838
01839 ti = type_info = static_cast<byte *>(mem_heap_alloc(heap, i + n_fields
01840 * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE));
01841
01842 switch (i) {
01843 default:
01844 ut_error;
01845 break;
01846 case 1:
01847
01848 *ti++ = 0;
01849
01850 case 0:
01851
01852 ut_ad(op == IBUF_OP_INSERT);
01853 break;
01854 case IBUF_REC_INFO_SIZE:
01855 mach_write_to_2(ti + IBUF_REC_OFFSET_COUNTER, counter);
01856
01857 ti[IBUF_REC_OFFSET_TYPE] = (byte) op;
01858 ti[IBUF_REC_OFFSET_FLAGS] = dict_table_is_comp(index->table)
01859 ? IBUF_REC_COMPACT : 0;
01860 ti += IBUF_REC_INFO_SIZE;
01861 break;
01862 }
01863
01864
01865
01866 for (i = 0; i < n_fields; i++) {
01867 ulint fixed_len;
01868 const dict_field_t* ifield;
01869
01870
01871
01872
01873 field = dtuple_get_nth_field(tuple, i + 4);
01874 entry_field = dtuple_get_nth_field(entry, i);
01875 dfield_copy(field, entry_field);
01876
01877 ifield = dict_index_get_nth_field(index, i);
01878
01879
01880
01881
01882
01883 fixed_len = ifield->fixed_len;
01884
01885 #ifdef UNIV_DEBUG
01886 if (fixed_len) {
01887
01888 ut_ad(fixed_len <= (ulint)
01889 dfield_get_type(entry_field)->len);
01890 if (ifield->prefix_len) {
01891 ut_ad(ifield->prefix_len == fixed_len);
01892 } else {
01893 ut_ad(fixed_len == (ulint)
01894 dfield_get_type(entry_field)->len);
01895 }
01896 }
01897 #endif
01898
01899 dtype_new_store_for_order_and_null_size(
01900 ti, dfield_get_type(entry_field), fixed_len);
01901 ti += DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE;
01902 }
01903
01904
01905
01906 field = dtuple_get_nth_field(tuple, 3);
01907
01908 dfield_set_data(field, type_info, ti - type_info);
01909
01910
01911
01912 dtuple_set_types_binary(tuple, n_fields + 4);
01913
01914 return(tuple);
01915 }
01916
01917
01921 static
01922 dtuple_t*
01923 ibuf_search_tuple_build(
01924
01925 ulint space,
01926 ulint page_no,
01927 mem_heap_t* heap)
01928 {
01929 dtuple_t* tuple;
01930 dfield_t* field;
01931 byte* buf;
01932
01933 ut_a(space == 0);
01934 ut_a(trx_doublewrite_must_reset_space_ids);
01935 ut_a(!trx_sys_multiple_tablespace_format);
01936
01937 tuple = dtuple_create(heap, 1);
01938
01939
01940
01941 field = dtuple_get_nth_field(tuple, 0);
01942
01943 buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
01944
01945 mach_write_to_4(buf, page_no);
01946
01947 dfield_set_data(field, buf, 4);
01948
01949 dtuple_set_types_binary(tuple, 1);
01950
01951 return(tuple);
01952 }
01953
01954
01958 static
01959 dtuple_t*
01960 ibuf_new_search_tuple_build(
01961
01962 ulint space,
01963 ulint page_no,
01964 mem_heap_t* heap)
01965 {
01966 dtuple_t* tuple;
01967 dfield_t* field;
01968 byte* buf;
01969
01970 ut_a(trx_sys_multiple_tablespace_format);
01971
01972 tuple = dtuple_create(heap, 3);
01973
01974
01975
01976 field = dtuple_get_nth_field(tuple, 0);
01977
01978 buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
01979
01980 mach_write_to_4(buf, space);
01981
01982 dfield_set_data(field, buf, 4);
01983
01984
01985
01986 field = dtuple_get_nth_field(tuple, 1);
01987
01988 buf = static_cast<byte *>(mem_heap_alloc(heap, 1));
01989
01990 mach_write_to_1(buf, 0);
01991
01992 dfield_set_data(field, buf, 1);
01993
01994
01995
01996 field = dtuple_get_nth_field(tuple, 2);
01997
01998 buf = static_cast<byte *>(mem_heap_alloc(heap, 4));
01999
02000 mach_write_to_4(buf, page_no);
02001
02002 dfield_set_data(field, buf, 4);
02003
02004 dtuple_set_types_binary(tuple, 3);
02005
02006 return(tuple);
02007 }
02008
02009
02013 UNIV_INLINE
02014 ibool
02015 ibuf_data_enough_free_for_insert(void)
02016
02017 {
02018 ut_ad(mutex_own(&ibuf_mutex));
02019
02020
02021
02022
02023
02024
02025
02026 return(ibuf->free_list_len >= (ibuf->size / 2) + 3 * ibuf->height);
02027 }
02028
02029
02033 UNIV_INLINE
02034 ibool
02035 ibuf_data_too_much_free(void)
02036
02037 {
02038 ut_ad(mutex_own(&ibuf_mutex));
02039
02040 return(ibuf->free_list_len >= 3 + (ibuf->size / 2) + 3 * ibuf->height);
02041 }
02042
02043
02047 static
02048 ibool
02049 ibuf_add_free_page(void)
02050
02051 {
02052 mtr_t mtr;
02053 page_t* header_page;
02054 ulint flags;
02055 ulint zip_size;
02056 ulint page_no;
02057 page_t* page;
02058 page_t* root;
02059 page_t* bitmap_page;
02060
02061 mtr_start(&mtr);
02062
02063
02064
02065 mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr);
02066 zip_size = dict_table_flags_to_zip_size(flags);
02067
02068 header_page = ibuf_header_page_get(&mtr);
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080 page_no = fseg_alloc_free_page(
02081 header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 0, FSP_UP,
02082 &mtr);
02083
02084 if (UNIV_UNLIKELY(page_no == FIL_NULL)) {
02085 mtr_commit(&mtr);
02086
02087 return(FALSE);
02088 }
02089
02090 {
02091 buf_block_t* block;
02092
02093 block = buf_page_get(
02094 IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
02095
02096 buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
02097
02098
02099 page = buf_block_get_frame(block);
02100 }
02101
02102 ibuf_enter();
02103
02104 mutex_enter(&ibuf_mutex);
02105
02106 root = ibuf_tree_root_get(&mtr);
02107
02108
02109
02110 flst_add_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
02111 page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
02112
02113 mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_IBUF_FREE_LIST,
02114 MLOG_2BYTES, &mtr);
02115
02116 ibuf->seg_size++;
02117 ibuf->free_list_len++;
02118
02119
02120
02121
02122 bitmap_page = ibuf_bitmap_get_map_page(
02123 IBUF_SPACE_ID, page_no, zip_size, &mtr);
02124
02125 mutex_exit(&ibuf_mutex);
02126
02127 ibuf_bitmap_page_set_bits(
02128 bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, TRUE, &mtr);
02129
02130 mtr_commit(&mtr);
02131
02132 ibuf_exit();
02133
02134 return(TRUE);
02135 }
02136
02137
02139 static
02140 void
02141 ibuf_remove_free_page(void)
02142
02143 {
02144 mtr_t mtr;
02145 mtr_t mtr2;
02146 page_t* header_page;
02147 ulint flags;
02148 ulint zip_size;
02149 ulint page_no;
02150 page_t* page;
02151 page_t* root;
02152 page_t* bitmap_page;
02153
02154 mtr_start(&mtr);
02155
02156
02157
02158 mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr);
02159 zip_size = dict_table_flags_to_zip_size(flags);
02160
02161 header_page = ibuf_header_page_get(&mtr);
02162
02163
02164 ibuf_enter();
02165 mutex_enter(&ibuf_pessimistic_insert_mutex);
02166 mutex_enter(&ibuf_mutex);
02167
02168 if (!ibuf_data_too_much_free()) {
02169
02170 mutex_exit(&ibuf_mutex);
02171 mutex_exit(&ibuf_pessimistic_insert_mutex);
02172
02173 ibuf_exit();
02174
02175 mtr_commit(&mtr);
02176
02177 return;
02178 }
02179
02180 mtr_start(&mtr2);
02181
02182 root = ibuf_tree_root_get(&mtr2);
02183
02184 mutex_exit(&ibuf_mutex);
02185
02186 page_no = flst_get_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
02187 &mtr2).page;
02188
02189
02190
02191
02192
02193 mtr_commit(&mtr2);
02194
02195 ibuf_exit();
02196
02197
02198
02199
02200
02201
02202
02203 fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
02204 IBUF_SPACE_ID, page_no, &mtr);
02205
02206 #ifdef UNIV_DEBUG_FILE_ACCESSES
02207 buf_page_reset_file_page_was_freed(IBUF_SPACE_ID, page_no);
02208 #endif
02209
02210 ibuf_enter();
02211
02212 mutex_enter(&ibuf_mutex);
02213
02214 root = ibuf_tree_root_get(&mtr);
02215
02216 ut_ad(page_no == flst_get_last(root + PAGE_HEADER
02217 + PAGE_BTR_IBUF_FREE_LIST, &mtr).page);
02218
02219 {
02220 buf_block_t* block;
02221
02222 block = buf_page_get(
02223 IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
02224
02225 buf_block_dbg_add_level(block, SYNC_TREE_NODE);
02226
02227
02228 page = buf_block_get_frame(block);
02229 }
02230
02231
02232
02233 flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
02234 page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
02235
02236 mutex_exit(&ibuf_pessimistic_insert_mutex);
02237
02238 ibuf->seg_size--;
02239 ibuf->free_list_len--;
02240
02241
02242
02243
02244 bitmap_page = ibuf_bitmap_get_map_page(
02245 IBUF_SPACE_ID, page_no, zip_size, &mtr);
02246
02247 mutex_exit(&ibuf_mutex);
02248
02249 ibuf_bitmap_page_set_bits(
02250 bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, FALSE, &mtr);
02251
02252 #ifdef UNIV_DEBUG_FILE_ACCESSES
02253 buf_page_set_file_page_was_freed(IBUF_SPACE_ID, page_no);
02254 #endif
02255 mtr_commit(&mtr);
02256
02257 ibuf_exit();
02258 }
02259
02260
02264 UNIV_INTERN
02265 void
02266 ibuf_free_excess_pages(void)
02267
02268 {
02269 ulint i;
02270
02271 #ifdef UNIV_SYNC_DEBUG
02272 ut_ad(rw_lock_own(fil_space_get_latch(IBUF_SPACE_ID, NULL),
02273 RW_LOCK_EX));
02274 #endif
02275
02276 ut_ad(rw_lock_get_x_lock_count(
02277 fil_space_get_latch(IBUF_SPACE_ID, NULL)) == 1);
02278
02279 ut_ad(!ibuf_inside());
02280
02281
02282
02283
02284
02285 if (!ibuf) {
02286
02287
02288
02289 return;
02290 }
02291
02292
02293
02294
02295 for (i = 0; i < 4; i++) {
02296
02297 ibool too_much_free;
02298
02299 mutex_enter(&ibuf_mutex);
02300 too_much_free = ibuf_data_too_much_free();
02301 mutex_exit(&ibuf_mutex);
02302
02303 if (!too_much_free) {
02304 return;
02305 }
02306
02307 ibuf_remove_free_page();
02308 }
02309 }
02310
02311
02315 static
02316 ulint
02317 ibuf_get_merge_page_nos(
02318
02319 ibool contract,
02323 rec_t* rec,
02325 ulint* space_ids,
02326 ib_int64_t* space_versions,
02329 ulint* page_nos,
02332 ulint* n_stored)
02334 {
02335 ulint prev_page_no;
02336 ulint prev_space_id;
02337 ulint first_page_no;
02338 ulint first_space_id;
02339 ulint rec_page_no;
02340 ulint rec_space_id;
02341 ulint sum_volumes;
02342 ulint volume_for_page;
02343 ulint rec_volume;
02344 ulint limit;
02345 ulint n_pages;
02346
02347 *n_stored = 0;
02348
02349 limit = ut_min(IBUF_MAX_N_PAGES_MERGED, buf_pool_get_curr_size() / 4);
02350
02351 if (page_rec_is_supremum(rec)) {
02352
02353 rec = page_rec_get_prev(rec);
02354 }
02355
02356 if (page_rec_is_infimum(rec)) {
02357
02358 rec = page_rec_get_next(rec);
02359 }
02360
02361 if (page_rec_is_supremum(rec)) {
02362
02363 return(0);
02364 }
02365
02366 first_page_no = ibuf_rec_get_page_no(rec);
02367 first_space_id = ibuf_rec_get_space(rec);
02368 n_pages = 0;
02369 prev_page_no = 0;
02370 prev_space_id = 0;
02371
02372
02373
02374
02375
02376 while (!page_rec_is_infimum(rec) && UNIV_LIKELY(n_pages < limit)) {
02377
02378 rec_page_no = ibuf_rec_get_page_no(rec);
02379 rec_space_id = ibuf_rec_get_space(rec);
02380
02381 if (rec_space_id != first_space_id
02382 || (rec_page_no / IBUF_MERGE_AREA)
02383 != (first_page_no / IBUF_MERGE_AREA)) {
02384
02385 break;
02386 }
02387
02388 if (rec_page_no != prev_page_no
02389 || rec_space_id != prev_space_id) {
02390 n_pages++;
02391 }
02392
02393 prev_page_no = rec_page_no;
02394 prev_space_id = rec_space_id;
02395
02396 rec = page_rec_get_prev(rec);
02397 }
02398
02399 rec = page_rec_get_next(rec);
02400
02401
02402
02403
02404
02405 prev_page_no = 0;
02406 prev_space_id = 0;
02407 sum_volumes = 0;
02408 volume_for_page = 0;
02409
02410 while (*n_stored < limit) {
02411 if (page_rec_is_supremum(rec)) {
02412
02413
02414 rec_page_no = 1;
02415 rec_space_id = 0;
02416 } else {
02417 rec_page_no = ibuf_rec_get_page_no(rec);
02418 rec_space_id = ibuf_rec_get_space(rec);
02419 ut_ad(rec_page_no > IBUF_TREE_ROOT_PAGE_NO);
02420 }
02421
02422 #ifdef UNIV_IBUF_DEBUG
02423 ut_a(*n_stored < IBUF_MAX_N_PAGES_MERGED);
02424 #endif
02425 if ((rec_space_id != prev_space_id
02426 || rec_page_no != prev_page_no)
02427 && (prev_space_id != 0 || prev_page_no != 0)) {
02428
02429 if ((prev_page_no == first_page_no
02430 && prev_space_id == first_space_id)
02431 || contract
02432 || (volume_for_page
02433 > ((IBUF_MERGE_THRESHOLD - 1)
02434 * 4 * UNIV_PAGE_SIZE
02435 / IBUF_PAGE_SIZE_PER_FREE_SPACE)
02436 / IBUF_MERGE_THRESHOLD)) {
02437
02438 space_ids[*n_stored] = prev_space_id;
02439 space_versions[*n_stored]
02440 = fil_space_get_version(prev_space_id);
02441 page_nos[*n_stored] = prev_page_no;
02442
02443 (*n_stored)++;
02444
02445 sum_volumes += volume_for_page;
02446 }
02447
02448 if (rec_space_id != first_space_id
02449 || rec_page_no / IBUF_MERGE_AREA
02450 != first_page_no / IBUF_MERGE_AREA) {
02451
02452 break;
02453 }
02454
02455 volume_for_page = 0;
02456 }
02457
02458 if (rec_page_no == 1 && rec_space_id == 0) {
02459
02460
02461 break;
02462 }
02463
02464 rec_volume = ibuf_rec_get_volume(rec);
02465
02466 volume_for_page += rec_volume;
02467
02468 prev_page_no = rec_page_no;
02469 prev_space_id = rec_space_id;
02470
02471 rec = page_rec_get_next(rec);
02472 }
02473
02474 #ifdef UNIV_IBUF_DEBUG
02475 ut_a(*n_stored <= IBUF_MAX_N_PAGES_MERGED);
02476 #endif
02477 #if 0
02478 fprintf(stderr, "Ibuf merge batch %lu pages %lu volume\n",
02479 *n_stored, sum_volumes);
02480 #endif
02481 return(sum_volumes);
02482 }
02483
02484
02489 static
02490 ulint
02491 ibuf_contract_ext(
02492
02493 ulint* n_pages,
02494 ibool sync)
02497 {
02498 btr_pcur_t pcur;
02499 ulint page_nos[IBUF_MAX_N_PAGES_MERGED];
02500 ulint space_ids[IBUF_MAX_N_PAGES_MERGED];
02501 ib_int64_t space_versions[IBUF_MAX_N_PAGES_MERGED];
02502 ulint sum_sizes;
02503 mtr_t mtr;
02504
02505 *n_pages = 0;
02506 ut_ad(!ibuf_inside());
02507
02508
02509
02510
02511
02512
02513 if (UNIV_UNLIKELY(ibuf->empty)
02514 && UNIV_LIKELY(!srv_shutdown_state)) {
02515 ibuf_is_empty:
02516
02517 #if 0
02518 if (srv_shutdown_state) {
02519
02520
02521
02522 trx_sys_set_ibuf_format(TRX_SYS_IBUF_EMPTY);
02523 }
02524
02525
02526
02527
02528
02529
02530 #endif
02531
02532 return(0);
02533 }
02534
02535 mtr_start(&mtr);
02536
02537 ibuf_enter();
02538
02539
02540
02541
02542 btr_pcur_open_at_rnd_pos(ibuf->index, BTR_SEARCH_LEAF, &pcur, &mtr);
02543
02544 ut_ad(page_validate(btr_pcur_get_page(&pcur), ibuf->index));
02545
02546 if (page_get_n_recs(btr_pcur_get_page(&pcur)) == 0) {
02547
02548
02549
02550 ut_ad(ibuf->empty);
02551 ut_ad(page_get_space_id(btr_pcur_get_page(&pcur))
02552 == IBUF_SPACE_ID);
02553 ut_ad(page_get_page_no(btr_pcur_get_page(&pcur))
02554 == FSP_IBUF_TREE_ROOT_PAGE_NO);
02555
02556 ibuf_exit();
02557
02558 mtr_commit(&mtr);
02559 btr_pcur_close(&pcur);
02560
02561 goto ibuf_is_empty;
02562 }
02563
02564 sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur),
02565 space_ids, space_versions,
02566 page_nos, n_pages);
02567 #if 0
02568 fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n",
02569 sync, *n_pages, sum_sizes);
02570 #endif
02571 ibuf_exit();
02572
02573 mtr_commit(&mtr);
02574 btr_pcur_close(&pcur);
02575
02576 buf_read_ibuf_merge_pages(sync, space_ids, space_versions, page_nos,
02577 *n_pages);
02578
02579 return(sum_sizes + 1);
02580 }
02581
02582
02587 UNIV_INTERN
02588 ulint
02589 ibuf_contract(
02590
02591 ibool sync)
02594 {
02595 ulint n_pages;
02596
02597 return(ibuf_contract_ext(&n_pages, sync));
02598 }
02599
02600
02605 UNIV_INTERN
02606 ulint
02607 ibuf_contract_for_n_pages(
02608
02609 ibool sync,
02612 ulint n_pages)
02615 {
02616 ulint sum_bytes = 0;
02617 ulint sum_pages = 0;
02618 ulint n_bytes;
02619 ulint n_pag2;
02620
02621 if (srv_fake_write)
02622 return(0);
02623
02624 while (sum_pages < n_pages) {
02625 n_bytes = ibuf_contract_ext(&n_pag2, sync);
02626
02627 if (n_bytes == 0) {
02628 return(sum_bytes);
02629 }
02630
02631 sum_bytes += n_bytes;
02632 sum_pages += n_pag2;
02633 }
02634
02635 return(sum_bytes);
02636 }
02637
02638
02640 UNIV_INLINE
02641 void
02642 ibuf_contract_after_insert(
02643
02644 ulint entry_size)
02646 {
02647 ibool sync;
02648 ulint sum_sizes;
02649 ulint size;
02650 ulint max_size;
02651
02652
02653
02654
02655
02656
02657
02658
02659 size = ibuf->size;
02660 max_size = ibuf->max_size;
02661
02662 if (srv_ibuf_active_contract == false
02663 && size < max_size + IBUF_CONTRACT_ON_INSERT_NON_SYNC) {
02664 return;
02665 }
02666
02667 sync = (size >= max_size + IBUF_CONTRACT_ON_INSERT_SYNC);
02668
02669
02670 sum_sizes = 0;
02671 size = 1;
02672
02673 do {
02674
02675 size = ibuf_contract(sync);
02676 sum_sizes += size;
02677 } while (size > 0 && sum_sizes < entry_size);
02678 }
02679
02680
02683 static
02684 ibool
02685 ibuf_get_volume_buffered_hash(
02686
02687 const rec_t* rec,
02688 const byte* types,
02689 const byte* data,
02690 ulint comp,
02692 ulint* hash,
02693 ulint size)
02694 {
02695 ulint len;
02696 ulint fold;
02697 ulint bitmask;
02698
02699 len = ibuf_rec_get_size(rec, types, rec_get_n_fields_old(rec) - 4,
02700 FALSE, comp);
02701 fold = ut_fold_binary(data, len);
02702
02703 hash += (fold / (8 * sizeof *hash)) % size;
02704 bitmask = 1 << (fold % (8 * sizeof *hash));
02705
02706 if (*hash & bitmask) {
02707
02708 return(FALSE);
02709 }
02710
02711
02712 *hash |= bitmask;
02713
02714 return(TRUE);
02715 }
02716
02717
02722 static
02723 ulint
02724 ibuf_get_volume_buffered_count(
02725
02726 const rec_t* rec,
02727 ulint* hash,
02728 ulint size,
02729 lint* n_recs)
02731 {
02732 ulint len;
02733 ibuf_op_t ibuf_op;
02734 const byte* types;
02735 ulint n_fields = rec_get_n_fields_old(rec);
02736
02737 ut_ad(ibuf_inside());
02738 ut_ad(n_fields > 4);
02739 n_fields -= 4;
02740
02741 rec_get_nth_field_offs_old(rec, 1, &len);
02742
02743
02744
02745 ut_a(len == 1);
02746 ut_ad(trx_sys_multiple_tablespace_format);
02747
02748 types = rec_get_nth_field_old(rec, 3, &len);
02749
02750 switch (UNIV_EXPECT(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE,
02751 IBUF_REC_INFO_SIZE)) {
02752 default:
02753 ut_error;
02754 case 0:
02755
02756
02757
02758
02759
02760 len = ibuf_rec_get_size(rec, types, n_fields, FALSE, 0);
02761
02762 return(len
02763 + rec_get_converted_extra_size(len, n_fields, 0)
02764 + page_dir_calc_reserved_space(1));
02765 case 1:
02766
02767
02768
02769
02770 goto get_volume_comp;
02771
02772 case IBUF_REC_INFO_SIZE:
02773 ibuf_op = (ibuf_op_t) types[IBUF_REC_OFFSET_TYPE];
02774 break;
02775 }
02776
02777 switch (ibuf_op) {
02778 case IBUF_OP_INSERT:
02779
02780
02781
02782 case IBUF_OP_DELETE_MARK:
02783
02784
02785 if (n_recs && ibuf_get_volume_buffered_hash(
02786 rec, types + IBUF_REC_INFO_SIZE,
02787 types + len,
02788 types[IBUF_REC_OFFSET_FLAGS] & IBUF_REC_COMPACT,
02789 hash, size)) {
02790 (*n_recs)++;
02791 }
02792
02793 if (ibuf_op == IBUF_OP_DELETE_MARK) {
02794
02795
02796 return(0);
02797 }
02798 break;
02799 case IBUF_OP_DELETE:
02800
02801 if (n_recs) {
02802 (*n_recs)--;
02803 }
02804
02805
02806
02807 return(0);
02808 default:
02809 ut_error;
02810 }
02811
02812 ut_ad(ibuf_op == IBUF_OP_INSERT);
02813
02814 get_volume_comp:
02815 {
02816 dtuple_t* entry;
02817 ulint volume;
02818 dict_index_t* dummy_index;
02819 mem_heap_t* heap = mem_heap_create(500);
02820
02821 entry = ibuf_build_entry_from_ibuf_rec(
02822 rec, heap, &dummy_index);
02823
02824 volume = rec_get_converted_size(dummy_index, entry, 0);
02825
02826 ibuf_dummy_index_free(dummy_index);
02827 mem_heap_free(heap);
02828
02829 return(volume + page_dir_calc_reserved_space(1));
02830 }
02831 }
02832
02833
02839 static
02840 ulint
02841 ibuf_get_volume_buffered(
02842
02843 btr_pcur_t* pcur,
02848 ulint space,
02849 ulint page_no,
02850 lint* n_recs,
02853 mtr_t* mtr)
02854 {
02855 ulint volume;
02856 rec_t* rec;
02857 page_t* page;
02858 ulint prev_page_no;
02859 page_t* prev_page;
02860 ulint next_page_no;
02861 page_t* next_page;
02862 ulint hash_bitmap[128 / sizeof(ulint)];
02863
02864 ut_a(trx_sys_multiple_tablespace_format);
02865
02866 ut_ad((pcur->latch_mode == BTR_MODIFY_PREV)
02867 || (pcur->latch_mode == BTR_MODIFY_TREE));
02868
02869
02870
02871
02872 volume = 0;
02873
02874 if (n_recs) {
02875 memset(hash_bitmap, 0, sizeof hash_bitmap);
02876 }
02877
02878 rec = btr_pcur_get_rec(pcur);
02879 page = page_align(rec);
02880 ut_ad(page_validate(page, ibuf->index));
02881
02882 if (page_rec_is_supremum(rec)) {
02883 rec = page_rec_get_prev(rec);
02884 }
02885
02886 for (;;) {
02887 if (page_rec_is_infimum(rec)) {
02888
02889 break;
02890 }
02891
02892 if (page_no != ibuf_rec_get_page_no(rec)
02893 || space != ibuf_rec_get_space(rec)) {
02894
02895 goto count_later;
02896 }
02897
02898 volume += ibuf_get_volume_buffered_count(
02899 rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
02900
02901 rec = page_rec_get_prev(rec);
02902 ut_ad(page_align(rec) == page);
02903 }
02904
02905
02906
02907 prev_page_no = btr_page_get_prev(page, mtr);
02908
02909 if (prev_page_no == FIL_NULL) {
02910
02911 goto count_later;
02912 }
02913
02914 {
02915 buf_block_t* block;
02916
02917 block = buf_page_get(
02918 IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH, mtr);
02919
02920 buf_block_dbg_add_level(block, SYNC_TREE_NODE);
02921
02922
02923 prev_page = buf_block_get_frame(block);
02924 ut_ad(page_validate(prev_page, ibuf->index));
02925 }
02926
02927 #ifdef UNIV_BTR_DEBUG
02928 ut_a(btr_page_get_next(prev_page, mtr)
02929 == page_get_page_no(page));
02930 #endif
02931
02932 rec = page_get_supremum_rec(prev_page);
02933 rec = page_rec_get_prev(rec);
02934
02935 for (;;) {
02936 if (page_rec_is_infimum(rec)) {
02937
02938
02939
02940
02941
02942 return(UNIV_PAGE_SIZE);
02943 }
02944
02945 if (page_no != ibuf_rec_get_page_no(rec)
02946 || space != ibuf_rec_get_space(rec)) {
02947
02948 goto count_later;
02949 }
02950
02951 volume += ibuf_get_volume_buffered_count(
02952 rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
02953
02954 rec = page_rec_get_prev(rec);
02955 ut_ad(page_align(rec) == prev_page);
02956 }
02957
02958 count_later:
02959 rec = btr_pcur_get_rec(pcur);
02960
02961 if (!page_rec_is_supremum(rec)) {
02962 rec = page_rec_get_next(rec);
02963 }
02964
02965 for (;;) {
02966 if (page_rec_is_supremum(rec)) {
02967
02968 break;
02969 }
02970
02971 if (page_no != ibuf_rec_get_page_no(rec)
02972 || space != ibuf_rec_get_space(rec)) {
02973
02974 return(volume);
02975 }
02976
02977 volume += ibuf_get_volume_buffered_count(
02978 rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
02979
02980 rec = page_rec_get_next(rec);
02981 }
02982
02983
02984
02985 next_page_no = btr_page_get_next(page, mtr);
02986
02987 if (next_page_no == FIL_NULL) {
02988
02989 return(volume);
02990 }
02991
02992 {
02993 buf_block_t* block;
02994
02995 block = buf_page_get(
02996 IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH, mtr);
02997
02998 buf_block_dbg_add_level(block, SYNC_TREE_NODE);
02999
03000
03001 next_page = buf_block_get_frame(block);
03002 ut_ad(page_validate(next_page, ibuf->index));
03003 }
03004
03005 #ifdef UNIV_BTR_DEBUG
03006 ut_a(btr_page_get_prev(next_page, mtr) == page_get_page_no(page));
03007 #endif
03008
03009 rec = page_get_infimum_rec(next_page);
03010 rec = page_rec_get_next(rec);
03011
03012 for (;;) {
03013 if (page_rec_is_supremum(rec)) {
03014
03015
03016
03017 return(UNIV_PAGE_SIZE);
03018 }
03019
03020 if (page_no != ibuf_rec_get_page_no(rec)
03021 || space != ibuf_rec_get_space(rec)) {
03022
03023 return(volume);
03024 }
03025
03026 volume += ibuf_get_volume_buffered_count(
03027 rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
03028
03029 rec = page_rec_get_next(rec);
03030 ut_ad(page_align(rec) == next_page);
03031 }
03032 }
03033
03034
03037 UNIV_INTERN
03038 void
03039 ibuf_update_max_tablespace_id(void)
03040
03041 {
03042 ulint max_space_id;
03043 const rec_t* rec;
03044 const byte* field;
03045 ulint len;
03046 btr_pcur_t pcur;
03047 mtr_t mtr;
03048
03049 ut_a(!dict_table_is_comp(ibuf->index->table));
03050
03051 ibuf_enter();
03052
03053 mtr_start(&mtr);
03054
03055 btr_pcur_open_at_index_side(
03056 FALSE, ibuf->index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
03057
03058 ut_ad(page_validate(btr_pcur_get_page(&pcur), ibuf->index));
03059
03060 btr_pcur_move_to_prev(&pcur, &mtr);
03061
03062 if (btr_pcur_is_before_first_on_page(&pcur)) {
03063
03064
03065 max_space_id = 0;
03066 } else {
03067 rec = btr_pcur_get_rec(&pcur);
03068
03069 field = rec_get_nth_field_old(rec, 0, &len);
03070
03071 ut_a(len == 4);
03072
03073 max_space_id = mach_read_from_4(field);
03074 }
03075
03076 mtr_commit(&mtr);
03077 ibuf_exit();
03078
03079
03080
03081 fil_set_max_space_id_if_bigger(max_space_id);
03082 }
03083
03084
03089 static
03090 ulint
03091 ibuf_get_entry_counter_low(
03092
03093 const rec_t* rec,
03094 ulint space,
03095 ulint page_no)
03096 {
03097 ulint counter;
03098 const byte* field;
03099 ulint len;
03100
03101 ut_ad(ibuf_inside());
03102 ut_ad(rec_get_n_fields_old(rec) > 2);
03103
03104 field = rec_get_nth_field_old(rec, 1, &len);
03105
03106 if (UNIV_UNLIKELY(len != 1)) {
03107
03108 ut_a(trx_doublewrite_must_reset_space_ids);
03109 ut_a(!trx_sys_multiple_tablespace_format);
03110
03111 return(ULINT_UNDEFINED);
03112 }
03113
03114 ut_a(trx_sys_multiple_tablespace_format);
03115
03116
03117 field = rec_get_nth_field_old(rec, 0, &len);
03118 ut_a(len == 4);
03119
03120 if (mach_read_from_4(field) != space) {
03121
03122 return(0);
03123 }
03124
03125
03126 field = rec_get_nth_field_old(rec, 2, &len);
03127 ut_a(len == 4);
03128
03129 if (mach_read_from_4(field) != page_no) {
03130
03131 return(0);
03132 }
03133
03134
03135 field = rec_get_nth_field_old(rec, 3, &len);
03136
03137 switch (len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE) {
03138 default:
03139 ut_error;
03140 case 0:
03141 case 1:
03142 return(ULINT_UNDEFINED);
03143
03144 case IBUF_REC_INFO_SIZE:
03145 counter = mach_read_from_2(field + IBUF_REC_OFFSET_COUNTER);
03146 ut_a(counter < 0xFFFF);
03147 return(counter + 1);
03148 }
03149 }
03150
03151
03155 static
03156 ibool
03157 ibuf_set_entry_counter(
03158
03159 dtuple_t* entry,
03160 ulint space,
03161 ulint page_no,
03162 btr_pcur_t* pcur,
03165 ibool is_optimistic,
03166 mtr_t* mtr)
03167 {
03168 dfield_t* field;
03169 byte* data;
03170 ulint counter = 0;
03171
03172
03173 ut_ad(page_validate(btr_pcur_get_page(pcur), ibuf->index));
03174
03175 if (btr_pcur_is_on_user_rec(pcur)) {
03176
03177 counter = ibuf_get_entry_counter_low(
03178 btr_pcur_get_rec(pcur), space, page_no);
03179
03180 if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) {
03181
03182
03183
03184
03185 return(FALSE);
03186 }
03187 } else if (btr_pcur_is_before_first_in_tree(pcur, mtr)) {
03188
03189
03190
03191
03192
03193 counter = 0;
03194 } else if (btr_pcur_is_before_first_on_page(pcur)) {
03195 btr_cur_t* cursor = btr_pcur_get_btr_cur(pcur);
03196
03197 if (cursor->low_match < 3) {
03198
03199
03200
03201
03202
03203
03204
03205 counter = 0;
03206 } else {
03207 rec_t* rec;
03208 const page_t* page;
03209 buf_block_t* block;
03210 page_t* prev_page;
03211 ulint prev_page_no;
03212
03213 ut_a(cursor->ibuf_cnt != ULINT_UNDEFINED);
03214
03215 page = btr_pcur_get_page(pcur);
03216 prev_page_no = btr_page_get_prev(page, mtr);
03217
03218 ut_a(prev_page_no != FIL_NULL);
03219
03220 block = buf_page_get(
03221 IBUF_SPACE_ID, 0, prev_page_no,
03222 RW_X_LATCH, mtr);
03223
03224 buf_block_dbg_add_level(block, SYNC_TREE_NODE);
03225
03226 prev_page = buf_block_get_frame(block);
03227
03228 rec = page_rec_get_prev(
03229 page_get_supremum_rec(prev_page));
03230
03231 ut_ad(page_rec_is_user_rec(rec));
03232
03233 counter = ibuf_get_entry_counter_low(
03234 rec, space, page_no);
03235
03236 if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) {
03237
03238
03239
03240
03241 return(FALSE);
03242 }
03243
03244 if (counter < cursor->ibuf_cnt) {
03245
03246
03247 if (is_optimistic) {
03248
03249
03250
03251
03252
03253
03254 btr_cur_position(
03255 ibuf->index, rec, block,
03256 btr_pcur_get_btr_cur(pcur));
03257 } else {
03258
03259
03260
03261
03262
03263
03264
03265 return(FALSE);
03266 }
03267 } else {
03268
03269
03270
03271
03272
03273
03274 return(FALSE);
03275 }
03276 }
03277 } else {
03278
03279 return(FALSE);
03280 }
03281
03282
03283 field = dtuple_get_nth_field(entry, 3);
03284 data = static_cast<byte *>(dfield_get_data(field));
03285
03286 mach_write_to_2(data + IBUF_REC_OFFSET_COUNTER, counter);
03287
03288 return(TRUE);
03289 }
03290
03291
03295 static
03296 ulint
03297 ibuf_insert_low(
03298
03299 ulint mode,
03300 ibuf_op_t op,
03301 ibool no_counter,
03304 const dtuple_t* entry,
03305 ulint entry_size,
03307 dict_index_t* index,
03309 ulint space,
03310 ulint zip_size,
03311 ulint page_no,
03312 que_thr_t* thr)
03313 {
03314 big_rec_t* dummy_big_rec;
03315 btr_pcur_t pcur;
03316 btr_cur_t* cursor;
03317 dtuple_t* ibuf_entry;
03318 mem_heap_t* heap;
03319 ulint buffered;
03320 lint min_n_recs;
03321 rec_t* ins_rec;
03322 ibool old_bit_value;
03323 page_t* bitmap_page;
03324 buf_block_t* block;
03325 page_t* root;
03326 ulint err;
03327 ibool do_merge;
03328 ulint space_ids[IBUF_MAX_N_PAGES_MERGED];
03329 ib_int64_t space_versions[IBUF_MAX_N_PAGES_MERGED];
03330 ulint page_nos[IBUF_MAX_N_PAGES_MERGED];
03331 ulint n_stored;
03332 mtr_t mtr;
03333 mtr_t bitmap_mtr;
03334
03335 ut_a(!dict_index_is_clust(index));
03336 ut_ad(dtuple_check_typed(entry));
03337 ut_ad(ut_is_2pow(zip_size));
03338 ut_ad(!no_counter || op == IBUF_OP_INSERT);
03339 ut_a(op < IBUF_OP_COUNT);
03340
03341 ut_a(trx_sys_multiple_tablespace_format);
03342
03343 do_merge = FALSE;
03344
03345
03346
03347
03348
03349
03350
03351
03352 if (ibuf->size >= ibuf->max_size + IBUF_CONTRACT_DO_NOT_INSERT) {
03353
03354
03355
03356
03357 #ifdef UNIV_IBUF_DEBUG
03358 fputs("Ibuf too big\n", stderr);
03359 #endif
03360
03361 ibuf_contract(TRUE);
03362
03363 return(DB_STRONG_FAIL);
03364 }
03365
03366 heap = mem_heap_create(512);
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376 ibuf_entry = ibuf_entry_build(
03377 op, index, entry, space, page_no,
03378 no_counter ? ULINT_UNDEFINED : 0xFFFF, heap);
03379
03380
03381
03382
03383
03384 if (mode == BTR_MODIFY_TREE) {
03385 for (;;) {
03386 ibuf_enter();
03387 mutex_enter(&ibuf_pessimistic_insert_mutex);
03388 mutex_enter(&ibuf_mutex);
03389
03390 if (UNIV_LIKELY(ibuf_data_enough_free_for_insert())) {
03391
03392 break;
03393 }
03394
03395 mutex_exit(&ibuf_mutex);
03396 mutex_exit(&ibuf_pessimistic_insert_mutex);
03397 ibuf_exit();
03398
03399 if (UNIV_UNLIKELY(!ibuf_add_free_page())) {
03400
03401 mem_heap_free(heap);
03402 return(DB_STRONG_FAIL);
03403 }
03404 }
03405 } else {
03406 ibuf_enter();
03407 }
03408
03409 mtr_start(&mtr);
03410
03411 btr_pcur_open(ibuf->index, ibuf_entry, PAGE_CUR_LE, mode, &pcur, &mtr);
03412 ut_ad(page_validate(btr_pcur_get_page(&pcur), ibuf->index));
03413
03414
03415
03416 min_n_recs = 0;
03417 buffered = ibuf_get_volume_buffered(&pcur, space, page_no,
03418 op == IBUF_OP_DELETE
03419 ? &min_n_recs
03420 : NULL, &mtr);
03421
03422 if (op == IBUF_OP_DELETE
03423 && (min_n_recs < 2
03424 || buf_pool_watch_occurred(space, page_no))) {
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442 fail_exit:
03443 if (mode == BTR_MODIFY_TREE) {
03444 mutex_exit(&ibuf_mutex);
03445 mutex_exit(&ibuf_pessimistic_insert_mutex);
03446 }
03447
03448 err = DB_STRONG_FAIL;
03449 goto func_exit;
03450 }
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461 #ifdef UNIV_IBUF_COUNT_DEBUG
03462 ut_a((buffered == 0) || ibuf_count_get(space, page_no));
03463 #endif
03464 mtr_start(&bitmap_mtr);
03465
03466 bitmap_page = ibuf_bitmap_get_map_page(space, page_no,
03467 zip_size, &bitmap_mtr);
03468
03469
03470
03471 if (buf_page_peek(space, page_no)
03472 || lock_rec_expl_exist_on_page(space, page_no)) {
03473
03474 goto bitmap_fail;
03475 }
03476
03477 if (op == IBUF_OP_INSERT) {
03478 ulint bits = ibuf_bitmap_page_get_bits(
03479 bitmap_page, page_no, zip_size, IBUF_BITMAP_FREE,
03480 &bitmap_mtr);
03481
03482 if (buffered + entry_size + page_dir_calc_reserved_space(1)
03483 > ibuf_index_page_calc_free_from_bits(zip_size, bits)) {
03484
03485 mtr_commit(&bitmap_mtr);
03486
03487
03488 do_merge = TRUE;
03489
03490 ibuf_get_merge_page_nos(
03491 FALSE, btr_pcur_get_rec(&pcur),
03492 space_ids, space_versions,
03493 page_nos, &n_stored);
03494
03495 goto fail_exit;
03496 }
03497 }
03498
03499
03500
03501
03502 if (!no_counter
03503 && !ibuf_set_entry_counter(ibuf_entry, space, page_no, &pcur,
03504 mode == BTR_MODIFY_PREV, &mtr)) {
03505 bitmap_fail:
03506 mtr_commit(&bitmap_mtr);
03507
03508 goto fail_exit;
03509 }
03510
03511
03512
03513
03514 old_bit_value = ibuf_bitmap_page_get_bits(
03515 bitmap_page, page_no, zip_size,
03516 IBUF_BITMAP_BUFFERED, &bitmap_mtr);
03517
03518 if (!old_bit_value) {
03519 ibuf_bitmap_page_set_bits(bitmap_page, page_no, zip_size,
03520 IBUF_BITMAP_BUFFERED, TRUE,
03521 &bitmap_mtr);
03522 }
03523
03524 mtr_commit(&bitmap_mtr);
03525
03526 cursor = btr_pcur_get_btr_cur(&pcur);
03527
03528 if (mode == BTR_MODIFY_PREV) {
03529 err = btr_cur_optimistic_insert(BTR_NO_LOCKING_FLAG, cursor,
03530 ibuf_entry, &ins_rec,
03531 &dummy_big_rec, 0, thr, &mtr);
03532 block = btr_cur_get_block(cursor);
03533 ut_ad(buf_block_get_space(block) == IBUF_SPACE_ID);
03534
03535
03536 if (UNIV_UNLIKELY(buf_block_get_page_no(block)
03537 == FSP_IBUF_TREE_ROOT_PAGE_NO)) {
03538 const page_t* page_root = buf_block_get_frame(block);
03539
03540 ut_ad(page_get_space_id(page_root) == IBUF_SPACE_ID);
03541 ut_ad(page_get_page_no(page_root)
03542 == FSP_IBUF_TREE_ROOT_PAGE_NO);
03543
03544 ibuf->empty = (page_get_n_recs(page_root) == 0);
03545 }
03546 } else {
03547 ut_ad(mode == BTR_MODIFY_TREE);
03548
03549
03550
03551
03552
03553
03554 root = ibuf_tree_root_get(&mtr);
03555
03556 err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG
03557 | BTR_NO_UNDO_LOG_FLAG,
03558 cursor,
03559 ibuf_entry, &ins_rec,
03560 &dummy_big_rec, 0, thr, &mtr);
03561 mutex_exit(&ibuf_pessimistic_insert_mutex);
03562 ibuf_size_update(root, &mtr);
03563 mutex_exit(&ibuf_mutex);
03564 ibuf->empty = (page_get_n_recs(root) == 0);
03565
03566 block = btr_cur_get_block(cursor);
03567 ut_ad(buf_block_get_space(block) == IBUF_SPACE_ID);
03568 }
03569
03570 if (err == DB_SUCCESS && op != IBUF_OP_DELETE) {
03571
03572 page_update_max_trx_id(block, NULL,
03573 thr_get_trx(thr)->id, &mtr);
03574 }
03575
03576 func_exit:
03577 #ifdef UNIV_IBUF_COUNT_DEBUG
03578 if (err == DB_SUCCESS) {
03579 fprintf(stderr,
03580 "Incrementing ibuf count of space %lu page %lu\n"
03581 "from %lu by 1\n", space, page_no,
03582 ibuf_count_get(space, page_no));
03583
03584 ibuf_count_set(space, page_no,
03585 ibuf_count_get(space, page_no) + 1);
03586 }
03587 #endif
03588
03589 mtr_commit(&mtr);
03590 btr_pcur_close(&pcur);
03591 ibuf_exit();
03592
03593 mem_heap_free(heap);
03594
03595 if (err == DB_SUCCESS && mode == BTR_MODIFY_TREE) {
03596 ibuf_contract_after_insert(entry_size);
03597 }
03598
03599 if (do_merge) {
03600 #ifdef UNIV_IBUF_DEBUG
03601 ut_a(n_stored <= IBUF_MAX_N_PAGES_MERGED);
03602 #endif
03603 buf_read_ibuf_merge_pages(FALSE, space_ids, space_versions,
03604 page_nos, n_stored);
03605 }
03606
03607 return(err);
03608 }
03609
03610
03615 UNIV_INTERN
03616 ibool
03617 ibuf_insert(
03618
03619 ibuf_op_t op,
03620 const dtuple_t* entry,
03621 dict_index_t* index,
03622 ulint space,
03623 ulint zip_size,
03624 ulint page_no,
03625 que_thr_t* thr)
03626 {
03627 ulint err;
03628 ulint entry_size;
03629 ibool no_counter;
03630
03631
03632 ibuf_use_t use = ibuf_use;
03633
03634 ut_a(trx_sys_multiple_tablespace_format);
03635 ut_ad(dtuple_check_typed(entry));
03636 ut_ad(ut_is_2pow(zip_size));
03637
03638 ut_a(!dict_index_is_clust(index));
03639
03640 no_counter = use <= IBUF_USE_INSERT;
03641
03642 switch (op) {
03643 case IBUF_OP_INSERT:
03644 switch (use) {
03645 case IBUF_USE_NONE:
03646 case IBUF_USE_DELETE:
03647 case IBUF_USE_DELETE_MARK:
03648 return(FALSE);
03649 case IBUF_USE_INSERT:
03650 case IBUF_USE_INSERT_DELETE_MARK:
03651 case IBUF_USE_ALL:
03652 goto check_watch;
03653 case IBUF_USE_COUNT:
03654 break;
03655 }
03656 break;
03657 case IBUF_OP_DELETE_MARK:
03658 switch (use) {
03659 case IBUF_USE_NONE:
03660 case IBUF_USE_INSERT:
03661 return(FALSE);
03662 case IBUF_USE_DELETE_MARK:
03663 case IBUF_USE_DELETE:
03664 case IBUF_USE_INSERT_DELETE_MARK:
03665 case IBUF_USE_ALL:
03666 ut_ad(!no_counter);
03667 goto check_watch;
03668 case IBUF_USE_COUNT:
03669 break;
03670 }
03671 break;
03672 case IBUF_OP_DELETE:
03673 switch (use) {
03674 case IBUF_USE_NONE:
03675 case IBUF_USE_INSERT:
03676 case IBUF_USE_INSERT_DELETE_MARK:
03677 return(FALSE);
03678 case IBUF_USE_DELETE_MARK:
03679 case IBUF_USE_DELETE:
03680 case IBUF_USE_ALL:
03681 ut_ad(!no_counter);
03682 goto skip_watch;
03683 case IBUF_USE_COUNT:
03684 break;
03685 }
03686 break;
03687 case IBUF_OP_COUNT:
03688 break;
03689 }
03690
03691
03692 ut_error;
03693
03694 check_watch:
03695
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707 {
03708 buf_page_t* bpage;
03709 ulint fold = buf_page_address_fold(space, page_no);
03710 buf_pool_t* buf_pool = buf_pool_get(space, page_no);
03711
03712 buf_pool_mutex_enter(buf_pool);
03713 bpage = buf_page_hash_get_low(buf_pool, space, page_no, fold);
03714 buf_pool_mutex_exit(buf_pool);
03715
03716 if (UNIV_LIKELY_NULL(bpage)) {
03717
03718
03719
03720
03721
03722
03723 return(FALSE);
03724 }
03725 }
03726
03727 skip_watch:
03728 entry_size = rec_get_converted_size(index, entry, 0);
03729
03730 if (entry_size
03731 >= page_get_free_space_of_empty(dict_table_is_comp(index->table))
03732 / 2) {
03733
03734 return(FALSE);
03735 }
03736
03737 err = ibuf_insert_low(BTR_MODIFY_PREV, op, no_counter,
03738 entry, entry_size,
03739 index, space, zip_size, page_no, thr);
03740 if (err == DB_FAIL) {
03741 err = ibuf_insert_low(BTR_MODIFY_TREE, op, no_counter,
03742 entry, entry_size,
03743 index, space, zip_size, page_no, thr);
03744 }
03745
03746 if (err == DB_SUCCESS) {
03747 #ifdef UNIV_IBUF_DEBUG
03748
03749
03750 #endif
03751 return(TRUE);
03752
03753 } else {
03754 ut_a(err == DB_STRONG_FAIL);
03755
03756 return(FALSE);
03757 }
03758 }
03759
03760
03763 static
03764 void
03765 ibuf_insert_to_index_page_low(
03766
03767 const dtuple_t* entry,
03768 buf_block_t* block,
03770 dict_index_t* index,
03771 mtr_t* mtr,
03772 page_cur_t* page_cur)
03774 {
03775 const page_t* page;
03776 ulint space;
03777 ulint page_no;
03778 ulint zip_size;
03779 const page_t* bitmap_page;
03780 ulint old_bits;
03781
03782 if (UNIV_LIKELY
03783 (page_cur_tuple_insert(page_cur, entry, index, 0, mtr) != NULL)) {
03784 return;
03785 }
03786
03787
03788
03789 btr_page_reorganize(block, index, mtr);
03790 page_cur_search(block, index, entry, PAGE_CUR_LE, page_cur);
03791
03792
03793
03794 if (UNIV_LIKELY
03795 (page_cur_tuple_insert(page_cur, entry, index, 0, mtr) != NULL)) {
03796 return;
03797 }
03798
03799 page = buf_block_get_frame(block);
03800
03801 ut_print_timestamp(stderr);
03802
03803 fprintf(stderr,
03804 " InnoDB: Error: Insert buffer insert fails;"
03805 " page free %lu, dtuple size %lu\n",
03806 (ulong) page_get_max_insert_size(page, 1),
03807 (ulong) rec_get_converted_size(index, entry, 0));
03808 fputs("InnoDB: Cannot insert index record ", stderr);
03809 dtuple_print(stderr, entry);
03810 fputs("\nInnoDB: The table where this index record belongs\n"
03811 "InnoDB: is now probably corrupt. Please run CHECK TABLE on\n"
03812 "InnoDB: that table.\n", stderr);
03813
03814 space = page_get_space_id(page);
03815 zip_size = buf_block_get_zip_size(block);
03816 page_no = page_get_page_no(page);
03817
03818 bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr);
03819 old_bits = ibuf_bitmap_page_get_bits(bitmap_page, page_no, zip_size,
03820 IBUF_BITMAP_FREE, mtr);
03821
03822 fprintf(stderr,
03823 "InnoDB: space %lu, page %lu, zip_size %lu, bitmap bits %lu\n",
03824 (ulong) space, (ulong) page_no,
03825 (ulong) zip_size, (ulong) old_bits);
03826
03827 fputs("InnoDB: Submit a detailed bug report"
03828 " to http://bugs.mysql.com\n", stderr);
03829 }
03830
03831
03832
03833
03834 static
03835 void
03836 ibuf_insert_to_index_page(
03837
03838 const dtuple_t* entry,
03839 buf_block_t* block,
03841 dict_index_t* index,
03842 mtr_t* mtr)
03843 {
03844 page_cur_t page_cur;
03845 ulint low_match;
03846 page_t* page = buf_block_get_frame(block);
03847 rec_t* rec;
03848
03849 ut_ad(ibuf_inside());
03850 ut_ad(dtuple_check_typed(entry));
03851 ut_ad(!buf_block_align(page)->is_hashed);
03852
03853 if (UNIV_UNLIKELY(dict_table_is_comp(index->table)
03854 != (ibool)!!page_is_comp(page))) {
03855 fputs("InnoDB: Trying to insert a record from"
03856 " the insert buffer to an index page\n"
03857 "InnoDB: but the 'compact' flag does not match!\n",
03858 stderr);
03859 goto dump;
03860 }
03861
03862 rec = page_rec_get_next(page_get_infimum_rec(page));
03863
03864 if (page_rec_is_supremum(rec)) {
03865 fputs("InnoDB: Trying to insert a record from"
03866 " the insert buffer to an index page\n"
03867 "InnoDB: but the index page is empty!\n",
03868 stderr);
03869 goto dump;
03870 }
03871
03872 if (UNIV_UNLIKELY(rec_get_n_fields(rec, index)
03873 != dtuple_get_n_fields(entry))) {
03874 fputs("InnoDB: Trying to insert a record from"
03875 " the insert buffer to an index page\n"
03876 "InnoDB: but the number of fields does not match!\n",
03877 stderr);
03878 dump:
03879 buf_page_print(page, 0);
03880
03881 dtuple_print(stderr, entry);
03882
03883 fputs("InnoDB: The table where where"
03884 " this index record belongs\n"
03885 "InnoDB: is now probably corrupt."
03886 " Please run CHECK TABLE on\n"
03887 "InnoDB: your tables.\n"
03888 "InnoDB: Submit a detailed bug report to"
03889 " http://bugs.mysql.com!\n", stderr);
03890
03891 return;
03892 }
03893
03894 low_match = page_cur_search(block, index, entry,
03895 PAGE_CUR_LE, &page_cur);
03896
03897 if (UNIV_UNLIKELY(low_match == dtuple_get_n_fields(entry))) {
03898 mem_heap_t* heap;
03899 upd_t* update;
03900 ulint* offsets;
03901 page_zip_des_t* page_zip;
03902
03903 rec = page_cur_get_rec(&page_cur);
03904
03905
03906
03907 ut_ad(rec_get_deleted_flag(rec, page_is_comp(page)));
03908
03909 heap = mem_heap_create(1024);
03910
03911 offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED,
03912 &heap);
03913 update = row_upd_build_sec_rec_difference_binary(
03914 index, entry, rec, NULL, heap);
03915
03916 page_zip = buf_block_get_page_zip(block);
03917
03918 if (update->n_fields == 0) {
03919
03920
03921
03922 btr_cur_set_deleted_flag_for_ibuf(
03923 rec, page_zip, FALSE, mtr);
03924 updated_in_place:
03925 mem_heap_free(heap);
03926 return;
03927 }
03928
03929
03930 update->info_bits = rec_get_info_bits(rec, page_is_comp(page));
03931 update->info_bits &= ~REC_INFO_DELETED_FLAG;
03932
03933
03934
03935
03936 if (!row_upd_changes_field_size_or_external(index, offsets,
03937 update)
03938 && (!page_zip || btr_cur_update_alloc_zip(
03939 page_zip, block, index,
03940 rec_offs_size(offsets), FALSE, mtr))) {
03941
03942
03943 row_upd_rec_in_place(rec, index, offsets,
03944 update, page_zip);
03945 goto updated_in_place;
03946 }
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959
03960
03961
03962
03963
03964
03965
03966
03967 lock_rec_store_on_page_infimum(block, rec);
03968 page_cur_delete_rec(&page_cur, index, offsets, mtr);
03969 page_cur_move_to_prev(&page_cur);
03970 mem_heap_free(heap);
03971
03972 ibuf_insert_to_index_page_low(entry, block, index, mtr,
03973 &page_cur);
03974 lock_rec_restore_from_page_infimum(block, rec, block);
03975 } else {
03976 ibuf_insert_to_index_page_low(entry, block, index, mtr,
03977 &page_cur);
03978 }
03979 }
03980
03981
03984 static
03985 void
03986 ibuf_set_del_mark(
03987
03988 const dtuple_t* entry,
03989 buf_block_t* block,
03990 const dict_index_t* index,
03991 mtr_t* mtr)
03992 {
03993 page_cur_t page_cur;
03994 ulint low_match;
03995
03996 ut_ad(ibuf_inside());
03997 ut_ad(dtuple_check_typed(entry));
03998
03999 low_match = page_cur_search(
04000 block, index, entry, PAGE_CUR_LE, &page_cur);
04001
04002 if (low_match == dtuple_get_n_fields(entry)) {
04003 rec_t* rec;
04004 page_zip_des_t* page_zip;
04005
04006 rec = page_cur_get_rec(&page_cur);
04007 page_zip = page_cur_get_page_zip(&page_cur);
04008
04009
04010
04011
04012
04013
04014
04015 if (UNIV_LIKELY
04016 (!rec_get_deleted_flag(
04017 rec, dict_table_is_comp(index->table)))) {
04018 btr_cur_set_deleted_flag_for_ibuf(rec, page_zip,
04019 TRUE, mtr);
04020 }
04021 } else {
04022 ut_print_timestamp(stderr);
04023 fputs(" InnoDB: unable to find a record to delete-mark\n",
04024 stderr);
04025 fputs("InnoDB: tuple ", stderr);
04026 dtuple_print(stderr, entry);
04027 fputs("\n"
04028 "InnoDB: record ", stderr);
04029 rec_print(stderr, page_cur_get_rec(&page_cur), index);
04030 putc('\n', stderr);
04031 fputs("\n"
04032 "InnoDB: Submit a detailed bug report"
04033 " to http://bugs.mysql.com\n", stderr);
04034 ut_ad(0);
04035 }
04036 }
04037
04038
04040 static
04041 void
04042 ibuf_delete(
04043
04044 const dtuple_t* entry,
04045 buf_block_t* block,
04046 dict_index_t* index,
04047 mtr_t* mtr)
04049 {
04050 page_cur_t page_cur;
04051 ulint low_match;
04052
04053 ut_ad(ibuf_inside());
04054 ut_ad(dtuple_check_typed(entry));
04055
04056 low_match = page_cur_search(
04057 block, index, entry, PAGE_CUR_LE, &page_cur);
04058
04059 if (low_match == dtuple_get_n_fields(entry)) {
04060 page_zip_des_t* page_zip= buf_block_get_page_zip(block);
04061 page_t* page = buf_block_get_frame(block);
04062 rec_t* rec = page_cur_get_rec(&page_cur);
04063
04064
04065
04066
04067 ulint offsets_[REC_OFFS_NORMAL_SIZE];
04068 ulint* offsets = offsets_;
04069 mem_heap_t* heap = NULL;
04070 ulint max_ins_size;
04071
04072 rec_offs_init(offsets_);
04073
04074 offsets = rec_get_offsets(
04075 rec, index, offsets, ULINT_UNDEFINED, &heap);
04076
04077
04078 ut_a(page_get_n_recs(page) > 1);
04079
04080
04081 ut_ad(REC_INFO_DELETED_FLAG
04082 & rec_get_info_bits(rec, page_is_comp(page)));
04083
04084 lock_update_delete(block, rec);
04085
04086 if (!page_zip) {
04087 max_ins_size
04088 = page_get_max_insert_size_after_reorganize(
04089 page, 1);
04090 }
04091 #ifdef UNIV_ZIP_DEBUG
04092 ut_a(!page_zip || page_zip_validate(page_zip, page));
04093 #endif
04094 page_cur_delete_rec(&page_cur, index, offsets, mtr);
04095 #ifdef UNIV_ZIP_DEBUG
04096 ut_a(!page_zip || page_zip_validate(page_zip, page));
04097 #endif
04098
04099 if (page_zip) {
04100 ibuf_update_free_bits_zip(block, mtr);
04101 } else {
04102 ibuf_update_free_bits_low(block, max_ins_size, mtr);
04103 }
04104
04105 if (UNIV_LIKELY_NULL(heap)) {
04106 mem_heap_free(heap);
04107 }
04108 } else {
04109
04110 }
04111 }
04112
04113
04116 static __attribute__((nonnull))
04117 ibool
04118 ibuf_restore_pos(
04119
04120 ulint space,
04121 ulint page_no,
04123 const dtuple_t* search_tuple,
04125 ulint mode,
04126 btr_pcur_t* pcur,
04128 mtr_t* mtr)
04129 {
04130 ut_ad(mode == BTR_MODIFY_LEAF || mode == BTR_MODIFY_TREE);
04131
04132 if (btr_pcur_restore_position(mode, pcur, mtr)) {
04133
04134 return(TRUE);
04135 }
04136
04137 if (fil_space_get_flags(space) == ULINT_UNDEFINED) {
04138
04139
04140
04141 btr_pcur_commit_specify_mtr(pcur, mtr);
04142 } else {
04143 fprintf(stderr,
04144 "InnoDB: ERROR: Submit the output to"
04145 " http://bugs.mysql.com\n"
04146 "InnoDB: ibuf cursor restoration fails!\n"
04147 "InnoDB: ibuf record inserted to page %lu:%lu\n",
04148 (ulong) space, (ulong) page_no);
04149 fflush(stderr);
04150
04151 rec_print_old(stderr, btr_pcur_get_rec(pcur));
04152 rec_print_old(stderr, pcur->old_rec);
04153 dtuple_print(stderr, search_tuple);
04154
04155 rec_print_old(stderr,
04156 page_rec_get_next(btr_pcur_get_rec(pcur)));
04157 fflush(stderr);
04158
04159 btr_pcur_commit_specify_mtr(pcur, mtr);
04160
04161 fputs("InnoDB: Validating insert buffer tree:\n", stderr);
04162 if (!btr_validate_index(ibuf->index, NULL)) {
04163 ut_error;
04164 }
04165
04166 fprintf(stderr, "InnoDB: ibuf tree ok\n");
04167 fflush(stderr);
04168 }
04169
04170 return(FALSE);
04171 }
04172
04173
04178 static
04179 ibool
04180 ibuf_delete_rec(
04181
04182 ulint space,
04183 ulint page_no,
04185 btr_pcur_t* pcur,
04187 const dtuple_t* search_tuple,
04189 mtr_t* mtr)
04190 {
04191 ibool success;
04192 page_t* root;
04193 ulint err;
04194
04195 ut_ad(ibuf_inside());
04196 ut_ad(page_rec_is_user_rec(btr_pcur_get_rec(pcur)));
04197 ut_ad(ibuf_rec_get_page_no(btr_pcur_get_rec(pcur)) == page_no);
04198 ut_ad(ibuf_rec_get_space(btr_pcur_get_rec(pcur)) == space);
04199
04200 success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr);
04201
04202 if (success) {
04203 if (UNIV_UNLIKELY(!page_get_n_recs(btr_pcur_get_page(pcur)))) {
04204
04205
04206
04207 root = btr_pcur_get_page(pcur);
04208
04209 ut_ad(page_get_space_id(root) == IBUF_SPACE_ID);
04210 ut_ad(page_get_page_no(root)
04211 == FSP_IBUF_TREE_ROOT_PAGE_NO);
04212
04213
04214
04215 ut_ad(!ibuf->empty);
04216 ibuf->empty = TRUE;
04217 }
04218
04219 #ifdef UNIV_IBUF_COUNT_DEBUG
04220 fprintf(stderr,
04221 "Decrementing ibuf count of space %lu page %lu\n"
04222 "from %lu by 1\n", space, page_no,
04223 ibuf_count_get(space, page_no));
04224 ibuf_count_set(space, page_no,
04225 ibuf_count_get(space, page_no) - 1);
04226 #endif
04227 return(FALSE);
04228 }
04229
04230 ut_ad(page_rec_is_user_rec(btr_pcur_get_rec(pcur)));
04231 ut_ad(ibuf_rec_get_page_no(btr_pcur_get_rec(pcur)) == page_no);
04232 ut_ad(ibuf_rec_get_space(btr_pcur_get_rec(pcur)) == space);
04233
04234
04235 btr_pcur_store_position(pcur, mtr);
04236
04237 btr_pcur_commit_specify_mtr(pcur, mtr);
04238
04239 mutex_enter(&ibuf_mutex);
04240
04241 mtr_start(mtr);
04242
04243 if (!ibuf_restore_pos(space, page_no, search_tuple,
04244 BTR_MODIFY_TREE, pcur, mtr)) {
04245
04246 mutex_exit(&ibuf_mutex);
04247 goto func_exit;
04248 }
04249
04250 root = ibuf_tree_root_get(mtr);
04251
04252 btr_cur_pessimistic_delete(&err, TRUE, btr_pcur_get_btr_cur(pcur),
04253 RB_NONE, mtr);
04254 ut_a(err == DB_SUCCESS);
04255
04256 #ifdef UNIV_IBUF_COUNT_DEBUG
04257 ibuf_count_set(space, page_no, ibuf_count_get(space, page_no) - 1);
04258 #endif
04259 ibuf_size_update(root, mtr);
04260 mutex_exit(&ibuf_mutex);
04261
04262 ibuf->empty = (page_get_n_recs(root) == 0);
04263 btr_pcur_commit_specify_mtr(pcur, mtr);
04264
04265 func_exit:
04266 btr_pcur_close(pcur);
04267
04268 return(TRUE);
04269 }
04270
04271
04278 UNIV_INTERN
04279 void
04280 ibuf_merge_or_delete_for_page(
04281
04282 buf_block_t* block,
04285 ulint space,
04286 ulint page_no,
04287 ulint zip_size,
04289 ibool update_ibuf_bitmap)
04294 {
04295 mem_heap_t* heap;
04296 btr_pcur_t pcur;
04297 dtuple_t* search_tuple;
04298 #ifdef UNIV_IBUF_DEBUG
04299 ulint volume = 0;
04300 #endif
04301 page_zip_des_t* page_zip = NULL;
04302 ibool tablespace_being_deleted = FALSE;
04303 ibool corruption_noticed = FALSE;
04304 mtr_t mtr;
04305
04306
04307 ulint mops[IBUF_OP_COUNT];
04308 ulint dops[IBUF_OP_COUNT];
04309
04310 ut_ad(!block || buf_block_get_space(block) == space);
04311 ut_ad(!block || buf_block_get_page_no(block) == page_no);
04312 ut_ad(!block || buf_block_get_zip_size(block) == zip_size);
04313
04314 if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE
04315 || trx_sys_hdr_page(space, page_no)) {
04316 return;
04317 }
04318
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328
04329 if (ibuf_fixed_addr_page(space, 0, page_no)
04330 || fsp_descr_page(0, page_no)) {
04331 return;
04332 }
04333
04334 if (UNIV_LIKELY(update_ibuf_bitmap)) {
04335 ut_a(ut_is_2pow(zip_size));
04336
04337 if (ibuf_fixed_addr_page(space, zip_size, page_no)
04338 || fsp_descr_page(zip_size, page_no)) {
04339 return;
04340 }
04341
04342
04343
04344
04345
04346
04347 tablespace_being_deleted = fil_inc_pending_ibuf_merges(space);
04348
04349 if (UNIV_UNLIKELY(tablespace_being_deleted)) {
04350
04351
04352
04353 block = NULL;
04354 update_ibuf_bitmap = FALSE;
04355 } else {
04356 page_t* bitmap_page;
04357
04358 mtr_start(&mtr);
04359
04360 bitmap_page = ibuf_bitmap_get_map_page(
04361 space, page_no, zip_size, &mtr);
04362
04363 if (!ibuf_bitmap_page_get_bits(bitmap_page, page_no,
04364 zip_size,
04365 IBUF_BITMAP_BUFFERED,
04366 &mtr)) {
04367
04368 mtr_commit(&mtr);
04369
04370 if (!tablespace_being_deleted) {
04371 fil_decr_pending_ibuf_merges(space);
04372 }
04373
04374 return;
04375 }
04376 mtr_commit(&mtr);
04377 }
04378 } else if (block
04379 && (ibuf_fixed_addr_page(space, zip_size, page_no)
04380 || fsp_descr_page(zip_size, page_no))) {
04381
04382 return;
04383 }
04384
04385 ibuf_enter();
04386
04387 heap = mem_heap_create(512);
04388
04389 if (!trx_sys_multiple_tablespace_format) {
04390 ut_a(trx_doublewrite_must_reset_space_ids);
04391 search_tuple = ibuf_search_tuple_build(space, page_no, heap);
04392 } else {
04393 search_tuple = ibuf_new_search_tuple_build(space, page_no,
04394 heap);
04395 }
04396
04397 if (block) {
04398
04399
04400
04401
04402
04403 rw_lock_x_lock_move_ownership(&(block->lock));
04404 page_zip = buf_block_get_page_zip(block);
04405
04406 if (UNIV_UNLIKELY(fil_page_get_type(block->frame)
04407 != FIL_PAGE_INDEX)
04408 || UNIV_UNLIKELY(!page_is_leaf(block->frame))) {
04409
04410 page_t* bitmap_page;
04411
04412 corruption_noticed = TRUE;
04413
04414 ut_print_timestamp(stderr);
04415
04416 mtr_start(&mtr);
04417
04418 fputs(" InnoDB: Dump of the ibuf bitmap page:\n",
04419 stderr);
04420
04421 bitmap_page = ibuf_bitmap_get_map_page(space, page_no,
04422 zip_size, &mtr);
04423 buf_page_print(bitmap_page, 0);
04424
04425 mtr_commit(&mtr);
04426
04427 fputs("\nInnoDB: Dump of the page:\n", stderr);
04428
04429 buf_page_print(block->frame, 0);
04430
04431 fprintf(stderr,
04432 "InnoDB: Error: corruption in the tablespace."
04433 " Bitmap shows insert\n"
04434 "InnoDB: buffer records to page n:o %lu"
04435 " though the page\n"
04436 "InnoDB: type is %lu, which is"
04437 " not an index leaf page!\n"
04438 "InnoDB: We try to resolve the problem"
04439 " by skipping the insert buffer\n"
04440 "InnoDB: merge for this page."
04441 " Please run CHECK TABLE on your tables\n"
04442 "InnoDB: to determine if they are corrupt"
04443 " after this.\n\n"
04444 "InnoDB: Please submit a detailed bug report"
04445 " to http://bugs.mysql.com\n\n",
04446 (ulong) page_no,
04447 (ulong)
04448 fil_page_get_type(block->frame));
04449 }
04450 }
04451
04452 memset(mops, 0, sizeof(mops));
04453 memset(dops, 0, sizeof(dops));
04454
04455 loop:
04456 mtr_start(&mtr);
04457
04458 if (block) {
04459 ibool success;
04460
04461 success = buf_page_get_known_nowait(
04462 RW_X_LATCH, block,
04463 BUF_KEEP_OLD, __FILE__, __LINE__, &mtr);
04464
04465 ut_a(success);
04466
04467 buf_block_dbg_add_level(block, SYNC_TREE_NODE);
04468 }
04469
04470
04471
04472 btr_pcur_open_on_user_rec(
04473 ibuf->index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF,
04474 &pcur, &mtr);
04475
04476 if (!btr_pcur_is_on_user_rec(&pcur)) {
04477 ut_ad(btr_pcur_is_after_last_in_tree(&pcur, &mtr));
04478
04479 goto reset_bit;
04480 }
04481
04482 for (;;) {
04483 rec_t* rec;
04484
04485 ut_ad(btr_pcur_is_on_user_rec(&pcur));
04486
04487 rec = btr_pcur_get_rec(&pcur);
04488
04489
04490 if (ibuf_rec_get_page_no(rec) != page_no
04491 || ibuf_rec_get_space(rec) != space) {
04492
04493 if (block) {
04494 page_header_reset_last_insert(
04495 block->frame, page_zip, &mtr);
04496 }
04497
04498 goto reset_bit;
04499 }
04500
04501 if (UNIV_UNLIKELY(corruption_noticed)) {
04502 fputs("InnoDB: Discarding record\n ", stderr);
04503 rec_print_old(stderr, rec);
04504 fputs("\nInnoDB: from the insert buffer!\n\n", stderr);
04505 } else if (block) {
04506
04507
04508
04509
04510
04511 dtuple_t* entry;
04512 trx_id_t max_trx_id;
04513 dict_index_t* dummy_index;
04514 ibuf_op_t op = ibuf_rec_get_op_type(rec);
04515
04516 max_trx_id = page_get_max_trx_id(page_align(rec));
04517 page_update_max_trx_id(block, page_zip, max_trx_id,
04518 &mtr);
04519
04520 ut_ad(page_validate(page_align(rec), ibuf->index));
04521
04522 entry = ibuf_build_entry_from_ibuf_rec(
04523 rec, heap, &dummy_index);
04524
04525 ut_ad(page_validate(block->frame, dummy_index));
04526
04527 switch (op) {
04528 ibool success;
04529 case IBUF_OP_INSERT:
04530 #ifdef UNIV_IBUF_DEBUG
04531 volume += rec_get_converted_size(
04532 dummy_index, entry, 0);
04533
04534 volume += page_dir_calc_reserved_space(1);
04535
04536 ut_a(volume <= 4 * UNIV_PAGE_SIZE
04537 / IBUF_PAGE_SIZE_PER_FREE_SPACE);
04538 #endif
04539 ibuf_insert_to_index_page(
04540 entry, block, dummy_index, &mtr);
04541 break;
04542
04543 case IBUF_OP_DELETE_MARK:
04544 ibuf_set_del_mark(
04545 entry, block, dummy_index, &mtr);
04546 break;
04547
04548 case IBUF_OP_DELETE:
04549 ibuf_delete(entry, block, dummy_index, &mtr);
04550
04551
04552
04553
04554 ut_ad(rec == btr_pcur_get_rec(&pcur));
04555 ut_ad(page_rec_is_user_rec(rec));
04556 ut_ad(ibuf_rec_get_page_no(rec) == page_no);
04557 ut_ad(ibuf_rec_get_space(rec) == space);
04558
04559 btr_pcur_store_position(&pcur, &mtr);
04560 btr_pcur_commit_specify_mtr(&pcur, &mtr);
04561
04562 mtr_start(&mtr);
04563
04564 success = buf_page_get_known_nowait(
04565 RW_X_LATCH, block,
04566 BUF_KEEP_OLD,
04567 __FILE__, __LINE__, &mtr);
04568 ut_a(success);
04569
04570 buf_block_dbg_add_level(block, SYNC_TREE_NODE);
04571
04572 if (!ibuf_restore_pos(space, page_no,
04573 search_tuple,
04574 BTR_MODIFY_LEAF,
04575 &pcur, &mtr)) {
04576
04577 mtr_commit(&mtr);
04578 mops[op]++;
04579 ibuf_dummy_index_free(dummy_index);
04580 goto loop;
04581 }
04582
04583 break;
04584 default:
04585 ut_error;
04586 }
04587
04588 mops[op]++;
04589
04590 ibuf_dummy_index_free(dummy_index);
04591 } else {
04592 dops[ibuf_rec_get_op_type(rec)]++;
04593 }
04594
04595
04596 if (ibuf_delete_rec(space, page_no, &pcur, search_tuple,
04597 &mtr)) {
04598
04599
04600
04601 goto loop;
04602 } else if (btr_pcur_is_after_last_on_page(&pcur)) {
04603 mtr_commit(&mtr);
04604 btr_pcur_close(&pcur);
04605
04606 goto loop;
04607 }
04608 }
04609
04610 reset_bit:
04611 if (UNIV_LIKELY(update_ibuf_bitmap)) {
04612 page_t* bitmap_page;
04613
04614 bitmap_page = ibuf_bitmap_get_map_page(
04615 space, page_no, zip_size, &mtr);
04616
04617 ibuf_bitmap_page_set_bits(
04618 bitmap_page, page_no, zip_size,
04619 IBUF_BITMAP_BUFFERED, FALSE, &mtr);
04620
04621 if (block) {
04622 ulint old_bits = ibuf_bitmap_page_get_bits(
04623 bitmap_page, page_no, zip_size,
04624 IBUF_BITMAP_FREE, &mtr);
04625
04626 ulint new_bits = ibuf_index_page_calc_free(
04627 zip_size, block);
04628
04629 if (old_bits != new_bits) {
04630 ibuf_bitmap_page_set_bits(
04631 bitmap_page, page_no, zip_size,
04632 IBUF_BITMAP_FREE, new_bits, &mtr);
04633 }
04634 }
04635 }
04636
04637 mtr_commit(&mtr);
04638 btr_pcur_close(&pcur);
04639 mem_heap_free(heap);
04640
04641 #ifdef HAVE_ATOMIC_BUILTINS
04642 os_atomic_increment_ulint(&ibuf->n_merges, 1);
04643 ibuf_add_ops(ibuf->n_merged_ops, mops);
04644 ibuf_add_ops(ibuf->n_discarded_ops, dops);
04645 #else
04646
04647 mutex_enter(&ibuf_mutex);
04648
04649 ibuf->n_merges++;
04650 ibuf_add_ops(ibuf->n_merged_ops, mops);
04651 ibuf_add_ops(ibuf->n_discarded_ops, dops);
04652
04653 mutex_exit(&ibuf_mutex);
04654 #endif
04655
04656 if (update_ibuf_bitmap && !tablespace_being_deleted) {
04657
04658 fil_decr_pending_ibuf_merges(space);
04659 }
04660
04661 ibuf_exit();
04662
04663 #ifdef UNIV_IBUF_COUNT_DEBUG
04664 ut_a(ibuf_count_get(space, page_no) == 0);
04665 #endif
04666 }
04667
04668
04673 UNIV_INTERN
04674 void
04675 ibuf_delete_for_discarded_space(
04676
04677 ulint space)
04678 {
04679 mem_heap_t* heap;
04680 btr_pcur_t pcur;
04681 dtuple_t* search_tuple;
04682 rec_t* ibuf_rec;
04683 ulint page_no;
04684 ibool closed;
04685 mtr_t mtr;
04686
04687
04688 ulint dops[IBUF_OP_COUNT];
04689
04690 heap = mem_heap_create(512);
04691
04692
04693
04694
04695 search_tuple = ibuf_new_search_tuple_build(space, 0, heap);
04696
04697 memset(dops, 0, sizeof(dops));
04698 loop:
04699 ibuf_enter();
04700
04701 mtr_start(&mtr);
04702
04703
04704
04705 btr_pcur_open_on_user_rec(
04706 ibuf->index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF,
04707 &pcur, &mtr);
04708
04709 if (!btr_pcur_is_on_user_rec(&pcur)) {
04710 ut_ad(btr_pcur_is_after_last_in_tree(&pcur, &mtr));
04711
04712 goto leave_loop;
04713 }
04714
04715 for (;;) {
04716 ut_ad(btr_pcur_is_on_user_rec(&pcur));
04717
04718 ibuf_rec = btr_pcur_get_rec(&pcur);
04719
04720
04721 if (ibuf_rec_get_space(ibuf_rec) != space) {
04722
04723 goto leave_loop;
04724 }
04725
04726 page_no = ibuf_rec_get_page_no(ibuf_rec);
04727
04728 dops[ibuf_rec_get_op_type(ibuf_rec)]++;
04729
04730
04731 closed = ibuf_delete_rec(space, page_no, &pcur, search_tuple,
04732 &mtr);
04733 if (closed) {
04734
04735
04736
04737 ibuf_exit();
04738
04739 goto loop;
04740 }
04741
04742 if (btr_pcur_is_after_last_on_page(&pcur)) {
04743 mtr_commit(&mtr);
04744 btr_pcur_close(&pcur);
04745
04746 ibuf_exit();
04747
04748 goto loop;
04749 }
04750 }
04751
04752 leave_loop:
04753 mtr_commit(&mtr);
04754 btr_pcur_close(&pcur);
04755
04756 #ifdef HAVE_ATOMIC_BUILTINS
04757 ibuf_add_ops(ibuf->n_discarded_ops, dops);
04758 #else
04759
04760 mutex_enter(&ibuf_mutex);
04761 ibuf_add_ops(ibuf->n_discarded_ops, dops);
04762 mutex_exit(&ibuf_mutex);
04763 #endif
04764
04765 ibuf_exit();
04766
04767 mem_heap_free(heap);
04768 }
04769
04770
04773 UNIV_INTERN
04774 ibool
04775 ibuf_is_empty(void)
04776
04777 {
04778 ibool is_empty;
04779 const page_t* root;
04780 mtr_t mtr;
04781
04782 ibuf_enter();
04783 mtr_start(&mtr);
04784
04785 mutex_enter(&ibuf_mutex);
04786 root = ibuf_tree_root_get(&mtr);
04787 mutex_exit(&ibuf_mutex);
04788
04789 is_empty = (page_get_n_recs(root) == 0);
04790 mtr_commit(&mtr);
04791 ibuf_exit();
04792
04793 ut_a(is_empty == ibuf->empty);
04794
04795 return(is_empty);
04796 }
04797
04798
04800 UNIV_INTERN
04801 void
04802 ibuf_print(
04803
04804 FILE* file)
04805 {
04806 #ifdef UNIV_IBUF_COUNT_DEBUG
04807 ulint i;
04808 ulint j;
04809 #endif
04810
04811 mutex_enter(&ibuf_mutex);
04812
04813 fprintf(file,
04814 "Ibuf: size %lu, free list len %lu,"
04815 " seg size %lu, %lu merges\n",
04816 (ulong) ibuf->size,
04817 (ulong) ibuf->free_list_len,
04818 (ulong) ibuf->seg_size,
04819 (ulong) ibuf->n_merges);
04820
04821 fputs("merged operations:\n ", file);
04822 ibuf_print_ops(ibuf->n_merged_ops, file);
04823
04824 fputs("discarded operations:\n ", file);
04825 ibuf_print_ops(ibuf->n_discarded_ops, file);
04826
04827 #ifdef UNIV_IBUF_COUNT_DEBUG
04828 for (i = 0; i < IBUF_COUNT_N_SPACES; i++) {
04829 for (j = 0; j < IBUF_COUNT_N_PAGES; j++) {
04830 ulint count = ibuf_count_get(i, j);
04831
04832 if (count > 0) {
04833 fprintf(stderr,
04834 "Ibuf count for space/page %lu/%lu"
04835 " is %lu\n",
04836 (ulong) i, (ulong) j, (ulong) count);
04837 }
04838 }
04839 }
04840 #endif
04841
04842 mutex_exit(&ibuf_mutex);
04843 }
04844 #endif