324
323
dropped! So, there seems to be no problem. */
326
325
/******************************************************************//**
327
Sets the flag in the current OS thread local storage denoting that it is
326
Sets the flag in the current mini-transaction record indicating we're
328
327
inside an insert buffer routine. */
332
mtr_t* mtr) /*!< in/out: mini-transaction */
336
ptr = thr_local_get_in_ibuf_field();
338
ut_ad(*ptr == FALSE);
334
ut_ad(!mtr->inside_ibuf);
335
mtr->inside_ibuf = TRUE;
343
338
/******************************************************************//**
344
Sets the flag in the current OS thread local storage denoting that it is
339
Sets the flag in the current mini-transaction record indicating we're
345
340
exiting an insert buffer routine. */
345
mtr_t* mtr) /*!< in/out: mini-transaction */
353
ptr = thr_local_get_in_ibuf_field();
347
ut_ad(mtr->inside_ibuf);
348
mtr->inside_ibuf = FALSE;
360
/******************************************************************//**
361
Returns TRUE if the current OS thread is performing an insert buffer
364
For instance, a read-ahead of non-ibuf pages is forbidden by threads
365
that are executing an insert buffer routine.
366
@return TRUE if inside an insert buffer routine */
351
/**************************************************************//**
352
Commits an insert buffer mini-transaction and sets the persistent
353
cursor latch mode to BTR_NO_LATCHES, that is, detaches the cursor. */
356
ibuf_btr_pcur_commit_specify_mtr(
357
/*=============================*/
358
btr_pcur_t* pcur, /*!< in/out: persistent cursor */
359
mtr_t* mtr) /*!< in/out: mini-transaction */
372
return(*thr_local_get_in_ibuf_field());
361
ut_d(ibuf_exit(mtr));
362
btr_pcur_commit_specify_mtr(pcur, mtr);
375
365
/******************************************************************//**
660
648
#ifndef UNIV_HOTBACKUP
650
/** Gets the desired bits for a given page from a bitmap page.
651
@param page in: bitmap page
652
@param offset in: page whose bits to get
653
@param zs in: compressed page size in bytes; 0 for uncompressed pages
654
@param bit in: IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
655
@param mtr in: mini-transaction holding an x-latch on the bitmap page
656
@return value of bits */
657
# define ibuf_bitmap_page_get_bits(page, offset, zs, bit, mtr) \
658
ibuf_bitmap_page_get_bits_low(page, offset, zs, \
659
MTR_MEMO_PAGE_X_FIX, mtr, bit)
660
# else /* UNIV_DEBUG */
661
/** Gets the desired bits for a given page from a bitmap page.
662
@param page in: bitmap page
663
@param offset in: page whose bits to get
664
@param zs in: compressed page size in bytes; 0 for uncompressed pages
665
@param bit in: IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
666
@param mtr in: mini-transaction holding an x-latch on the bitmap page
667
@return value of bits */
668
# define ibuf_bitmap_page_get_bits(page, offset, zs, bit, mtr) \
669
ibuf_bitmap_page_get_bits_low(page, offset, zs, bit)
670
# endif /* UNIV_DEBUG */
661
672
/********************************************************************//**
662
673
Gets the desired bits for a given page from a bitmap page.
663
674
@return value of bits */
666
ibuf_bitmap_page_get_bits(
667
/*======================*/
677
ibuf_bitmap_page_get_bits_low(
678
/*==========================*/
668
679
const page_t* page, /*!< in: bitmap page */
669
680
ulint page_no,/*!< in: page whose bits to get */
670
681
ulint zip_size,/*!< in: compressed page size in bytes;
671
682
0 for uncompressed pages */
672
ulint bit, /*!< in: IBUF_BITMAP_FREE,
685
/*!< in: MTR_MEMO_PAGE_X_FIX,
686
MTR_MEMO_BUF_FIX, ... */
687
mtr_t* mtr, /*!< in: mini-transaction holding latch_type
688
on the bitmap page */
689
#endif /* UNIV_DEBUG */
690
ulint bit) /*!< in: IBUF_BITMAP_FREE,
673
692
IBUF_BITMAP_BUFFERED, ... */
674
mtr_t* /*mtr __attribute__((unused))*/)
675
/*!< in: mtr containing an
676
x-latch to the bitmap page */
678
694
ulint byte_offset;
679
695
ulint bit_offset;
685
701
# error "IBUF_BITS_PER_PAGE % 2 != 0"
687
703
ut_ad(ut_is_2pow(zip_size));
688
ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
704
ut_ad(mtr_memo_contains_page(mtr, page, latch_type));
691
707
bit_offset = (page_no % UNIV_PAGE_SIZE) * IBUF_BITS_PER_PAGE
1111
1127
@return TRUE if level 2 or level 3 page */
1116
ulint space, /*!< in: space id */
1117
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
1118
ulint page_no,/*!< in: page number */
1119
mtr_t* mtr) /*!< in: mtr which will contain an x-latch to the
1120
bitmap page if the page is not one of the fixed
1121
address ibuf pages, or NULL, in which case a new
1122
transaction is created. */
1132
ulint space, /*!< in: space id */
1133
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
1134
ulint page_no,/*!< in: page number */
1136
ibool x_latch,/*!< in: FALSE if relaxed check
1137
(avoid latching the bitmap page) */
1138
#endif /* UNIV_DEBUG */
1139
const char* file, /*!< in: file name */
1140
ulint line, /*!< in: line where called */
1141
mtr_t* mtr) /*!< in: mtr which will contain an
1142
x-latch to the bitmap page if the page
1143
is not one of the fixed address ibuf
1144
pages, or NULL, in which case a new
1145
transaction is created. */
1125
1148
mtr_t local_mtr;
1126
1149
page_t* bitmap_page;
1128
1151
ut_ad(!recv_no_ibuf_operations);
1152
ut_ad(x_latch || mtr == NULL);
1130
1154
if (srv_fake_write)
1141
1165
ut_ad(fil_space_get_type(IBUF_SPACE_ID) == FIL_TABLESPACE);
1169
mtr_start(&local_mtr);
1171
/* Get the bitmap page without a page latch, so that
1172
we will not be violating the latching order when
1173
another bitmap page has already been latched by this
1174
thread. The page will be buffer-fixed, and thus it
1175
cannot be removed or relocated while we are looking at
1176
it. The contents of the page could change, but the
1177
IBUF_BITMAP_IBUF bit that we are interested in should
1178
not be modified by any other thread. Nobody should be
1179
calling ibuf_add_free_page() or ibuf_remove_free_page()
1180
while the page is linked to the insert buffer b-tree. */
1182
bitmap_page = buf_block_get_frame(
1185
ibuf_bitmap_page_no_calc(zip_size, page_no),
1186
RW_NO_LATCH, NULL, BUF_GET_NO_LATCH,
1187
file, line, &local_mtr));
1188
# ifdef UNIV_SYNC_DEBUG
1189
/* This is for tracking Bug #58212. This check and message can
1190
be removed once it has been established that our assumptions
1191
about this condition are correct. The bug was only a one-time
1192
occurrence, unable to repeat since then. */
1193
void* latch = sync_thread_levels_contains(SYNC_IBUF_BITMAP);
1195
fprintf(stderr, "Bug#58212 UNIV_SYNC_DEBUG"
1196
" levels %p (%u,%u)\n",
1197
latch, (unsigned) space, (unsigned) page_no);
1199
# endif /* UNIV_SYNC_DEBUG */
1200
ret = ibuf_bitmap_page_get_bits_low(
1201
bitmap_page, page_no, zip_size,
1202
MTR_MEMO_BUF_FIX, &local_mtr, IBUF_BITMAP_IBUF);
1204
mtr_commit(&local_mtr);
1207
#endif /* UNIV_DEBUG */
1143
1209
if (mtr == NULL) {
1144
1210
mtr = &local_mtr;
1145
1211
mtr_start(mtr);
1148
bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr);
1214
bitmap_page = ibuf_bitmap_get_map_page_func(space, page_no, zip_size,
1150
1217
ret = ibuf_bitmap_page_get_bits(bitmap_page, page_no, zip_size,
1151
1218
IBUF_BITMAP_IBUF, mtr);
1228
# define ibuf_rec_get_page_no(mtr,rec) ibuf_rec_get_page_no_func(mtr,rec)
1229
#else /* UNIV_DEBUG */
1230
# define ibuf_rec_get_page_no(mtr,rec) ibuf_rec_get_page_no_func(rec)
1231
#endif /* UNIV_DEBUG */
1160
1233
/********************************************************************//**
1161
1234
Returns the page number field of an ibuf record.
1162
1235
@return page number */
1165
ibuf_rec_get_page_no(
1166
/*=================*/
1238
ibuf_rec_get_page_no_func(
1239
/*======================*/
1241
mtr_t* mtr, /*!< in: mini-transaction owning rec */
1242
#endif /* UNIV_DEBUG */
1167
1243
const rec_t* rec) /*!< in: ibuf record */
1169
1245
const byte* field;
1172
ut_ad(ibuf_inside());
1248
ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
1249
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
1250
ut_ad(ibuf_inside(mtr));
1173
1251
ut_ad(rec_get_n_fields_old(rec) > 2);
1175
1253
field = rec_get_nth_field_old(rec, 1, &len);
1191
1269
return(mach_read_from_4(field));
1273
# define ibuf_rec_get_space(mtr,rec) ibuf_rec_get_space_func(mtr,rec)
1274
#else /* UNIV_DEBUG */
1275
# define ibuf_rec_get_space(mtr,rec) ibuf_rec_get_space_func(rec)
1276
#endif /* UNIV_DEBUG */
1194
1278
/********************************************************************//**
1195
1279
Returns the space id field of an ibuf record. For < 4.1.x format records
1197
1281
@return space id */
1284
ibuf_rec_get_space_func(
1285
/*====================*/
1287
mtr_t* mtr, /*!< in: mini-transaction owning rec */
1288
#endif /* UNIV_DEBUG */
1202
1289
const rec_t* rec) /*!< in: ibuf record */
1204
1291
const byte* field;
1207
ut_ad(ibuf_inside());
1294
ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
1295
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
1296
ut_ad(ibuf_inside(mtr));
1208
1297
ut_ad(rec_get_n_fields_old(rec) > 2);
1210
1299
field = rec_get_nth_field_old(rec, 1, &len);
1318
# define ibuf_rec_get_info(mtr,rec,op,comp,info_len,counter) \
1319
ibuf_rec_get_info_func(mtr,rec,op,comp,info_len,counter)
1320
#else /* UNIV_DEBUG */
1321
# define ibuf_rec_get_info(mtr,rec,op,comp,info_len,counter) \
1322
ibuf_rec_get_info_func(rec,op,comp,info_len,counter)
1228
1324
/****************************************************************//**
1229
1325
Get various information about an ibuf record in >= 4.1.x format. */
1328
ibuf_rec_get_info_func(
1329
/*===================*/
1331
mtr_t* mtr, /*!< in: mini-transaction owning rec */
1332
#endif /* UNIV_DEBUG */
1234
1333
const rec_t* rec, /*!< in: ibuf record */
1235
1334
ibuf_op_t* op, /*!< out: operation type, or NULL */
1236
1335
ibool* comp, /*!< out: compact flag, or NULL */
1403
# define ibuf_rec_get_op_type(mtr,rec) ibuf_rec_get_op_type_func(mtr,rec)
1404
#else /* UNIV_DEBUG */
1405
# define ibuf_rec_get_op_type(mtr,rec) ibuf_rec_get_op_type_func(rec)
1301
1408
/****************************************************************//**
1302
1409
Returns the operation type field of an ibuf record.
1303
1410
@return operation type */
1306
ibuf_rec_get_op_type(
1307
/*=================*/
1413
ibuf_rec_get_op_type_func(
1414
/*======================*/
1416
mtr_t* mtr, /*!< in: mini-transaction owning rec */
1417
#endif /* UNIV_DEBUG */
1308
1418
const rec_t* rec) /*!< in: ibuf record */
1312
ut_ad(ibuf_inside());
1422
ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
1423
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
1424
ut_ad(ibuf_inside(mtr));
1313
1425
ut_ad(rec_get_n_fields_old(rec) > 2);
1315
1427
(void) rec_get_nth_field_old(rec, 1, &len);
1636
# define ibuf_build_entry_from_ibuf_rec(mtr,ibuf_rec,heap,pindex) \
1637
ibuf_build_entry_from_ibuf_rec_func(mtr,ibuf_rec,heap,pindex)
1638
#else /* UNIV_DEBUG */
1639
# define ibuf_build_entry_from_ibuf_rec(mtr,ibuf_rec,heap,pindex) \
1640
ibuf_build_entry_from_ibuf_rec_func(ibuf_rec,heap,pindex)
1523
1643
/*********************************************************************//**
1524
1644
Builds the entry used to
1538
1658
@return own: entry to insert to a non-clustered index */
1541
ibuf_build_entry_from_ibuf_rec(
1542
/*===========================*/
1661
ibuf_build_entry_from_ibuf_rec_func(
1662
/*================================*/
1664
mtr_t* mtr, /*!< in: mini-transaction owning rec */
1665
#endif /* UNIV_DEBUG */
1543
1666
const rec_t* ibuf_rec, /*!< in: record in an insert buffer */
1544
1667
mem_heap_t* heap, /*!< in: heap where built */
1545
1668
dict_index_t** pindex) /*!< out, own: dummy index that
1577
1704
types = rec_get_nth_field_old(ibuf_rec, 3, &len);
1579
ibuf_rec_get_info(ibuf_rec, NULL, &comp, &info_len, NULL);
1706
ibuf_rec_get_info(mtr, ibuf_rec, NULL, &comp, &info_len, NULL);
1581
1708
index = ibuf_dummy_index_create(n_fields, comp);
1685
ut_ad(ibuf_inside());
1821
ut_ad(mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_X_FIX)
1822
|| mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_S_FIX));
1823
ut_ad(ibuf_inside(mtr));
1686
1824
ut_ad(rec_get_n_fields_old(ibuf_rec) > 2);
1688
1826
data = rec_get_nth_field_old(ibuf_rec, 1, &len);
1711
1849
types = rec_get_nth_field_old(ibuf_rec, 3, &len);
1713
ibuf_rec_get_info(ibuf_rec, &op, &comp, &info_len, NULL);
1851
ibuf_rec_get_info(mtr, ibuf_rec, &op, &comp, &info_len, NULL);
1715
1853
if (op == IBUF_OP_DELETE_MARK || op == IBUF_OP_DELETE) {
1716
1854
/* Delete-marking a record doesn't take any
1727
1865
mem_heap_t* heap = mem_heap_create(500);
1729
1867
entry = ibuf_build_entry_from_ibuf_rec(
1730
ibuf_rec, heap, &dummy_index);
1868
mtr, ibuf_rec, heap, &dummy_index);
1732
1870
volume = rec_get_converted_size(dummy_index, entry, 0);
2085
2223
mtr_commit(&mtr);
2093
block = buf_page_get(
2227
buf_block_t* block = buf_page_get(
2094
2228
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
2096
2229
buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
2099
2231
page = buf_block_get_frame(block);
2104
2236
mutex_enter(&ibuf_mutex);
2203
2330
fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
2204
2331
IBUF_SPACE_ID, page_no, &mtr);
2206
#ifdef UNIV_DEBUG_FILE_ACCESSES
2333
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
2207
2334
buf_page_reset_file_page_was_freed(IBUF_SPACE_ID, page_no);
2335
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
2212
2339
mutex_enter(&ibuf_mutex);
2249
2376
ibuf_bitmap_page_set_bits(
2250
2377
bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, FALSE, &mtr);
2252
#ifdef UNIV_DEBUG_FILE_ACCESSES
2379
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
2253
2380
buf_page_set_file_page_was_freed(IBUF_SPACE_ID, page_no);
2381
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
2382
ibuf_mtr_commit(&mtr);
2260
2385
/***********************************************************************//**
2435
# define ibuf_get_merge_page_nos(contract,rec,mtr,ids,vers,pages,n_stored) \
2436
ibuf_get_merge_page_nos_func(contract,rec,mtr,ids,vers,pages,n_stored)
2437
#else /* UNIV_DEBUG */
2438
# define ibuf_get_merge_page_nos(contract,rec,mtr,ids,vers,pages,n_stored) \
2439
ibuf_get_merge_page_nos_func(contract,rec,ids,vers,pages,n_stored)
2440
#endif /* UNIV_DEBUG */
2311
2442
/*********************************************************************//**
2312
2443
Reads page numbers from a leaf in an ibuf tree.
2313
2444
@return a lower limit for the combined volume of records which will be
2317
ibuf_get_merge_page_nos(
2318
/*====================*/
2448
ibuf_get_merge_page_nos_func(
2449
/*=========================*/
2319
2450
ibool contract,/*!< in: TRUE if this function is called to
2320
2451
contract the tree, FALSE if this is called
2321
2452
when a single page becomes full and we look
2322
2453
if it pays to read also nearby pages */
2323
rec_t* rec, /*!< in: record from which we read up and down
2324
in the chain of records */
2454
const rec_t* rec, /*!< in: insert buffer record */
2456
mtr_t* mtr, /*!< in: mini-transaction holding rec */
2457
#endif /* UNIV_DEBUG */
2325
2458
ulint* space_ids,/*!< in/out: space id's of the pages */
2326
2459
ib_int64_t* space_versions,/*!< in/out: tablespace version
2327
2460
timestamps; used to prevent reading in old
2480
ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
2481
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
2482
ut_ad(ibuf_inside(mtr));
2349
2486
limit = ut_min(IBUF_MAX_N_PAGES_MERGED, buf_pool_get_curr_size() / 4);
2351
2488
if (page_rec_is_supremum(rec)) {
2353
rec = page_rec_get_prev(rec);
2490
rec = page_rec_get_prev_const(rec);
2356
2493
if (page_rec_is_infimum(rec)) {
2358
rec = page_rec_get_next(rec);
2495
rec = page_rec_get_next_const(rec);
2361
2498
if (page_rec_is_supremum(rec)) {
2376
2513
while (!page_rec_is_infimum(rec) && UNIV_LIKELY(n_pages < limit)) {
2378
rec_page_no = ibuf_rec_get_page_no(rec);
2379
rec_space_id = ibuf_rec_get_space(rec);
2515
rec_page_no = ibuf_rec_get_page_no(mtr, rec);
2516
rec_space_id = ibuf_rec_get_space(mtr, rec);
2381
2518
if (rec_space_id != first_space_id
2382
2519
|| (rec_page_no / IBUF_MERGE_AREA)
2393
2530
prev_page_no = rec_page_no;
2394
2531
prev_space_id = rec_space_id;
2396
rec = page_rec_get_prev(rec);
2533
rec = page_rec_get_prev_const(rec);
2399
rec = page_rec_get_next(rec);
2536
rec = page_rec_get_next_const(rec);
2401
2538
/* At the loop start there is no prev page; we mark this with a pair
2402
2539
of space id, page no (0, 0) for which there can never be entries in
2426
2563
|| rec_page_no != prev_page_no)
2427
2564
&& (prev_space_id != 0 || prev_page_no != 0)) {
2429
if ((prev_page_no == first_page_no
2430
&& prev_space_id == first_space_id)
2567
|| (prev_page_no == first_page_no
2568
&& prev_space_id == first_space_id)
2432
2569
|| (volume_for_page
2433
2570
> ((IBUF_MERGE_THRESHOLD - 1)
2434
2571
* 4 * UNIV_PAGE_SIZE
2464
rec_volume = ibuf_rec_get_volume(rec);
2601
rec_volume = ibuf_rec_get_volume(mtr, rec);
2466
2603
volume_for_page += rec_volume;
2468
2605
prev_page_no = rec_page_no;
2469
2606
prev_space_id = rec_space_id;
2471
rec = page_rec_get_next(rec);
2608
rec = page_rec_get_next_const(rec);
2474
2611
#ifdef UNIV_IBUF_DEBUG
2513
2649
if (UNIV_UNLIKELY(ibuf->empty)
2514
2650
&& UNIV_LIKELY(!srv_shutdown_state)) {
2518
if (srv_shutdown_state) {
2519
/* If the insert buffer becomes empty during
2520
shutdown, note it in the system tablespace. */
2522
trx_sys_set_ibuf_format(TRX_SYS_IBUF_EMPTY);
2525
/* TO DO: call trx_sys_set_ibuf_format() at startup
2526
and whenever ibuf_use is changed to allow buffered
2527
delete-marking or deleting. Never downgrade the
2528
stamped format except when the insert buffer becomes
2654
ibuf_mtr_start(&mtr);
2539
2656
/* Open a cursor to a randomly chosen leaf of the tree, at a random
2540
2657
position within the leaf */
2553
2670
ut_ad(page_get_page_no(btr_pcur_get_page(&pcur))
2554
2671
== FSP_IBUF_TREE_ROOT_PAGE_NO);
2673
ibuf_mtr_commit(&mtr);
2559
2674
btr_pcur_close(&pcur);
2564
sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur),
2679
sum_sizes = ibuf_get_merge_page_nos(TRUE,
2680
btr_pcur_get_rec(&pcur), &mtr,
2565
2681
space_ids, space_versions,
2566
2682
page_nos, n_pages);
2567
2683
#if 0 /* defined UNIV_IBUF_DEBUG */
2568
2684
fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n",
2569
2685
sync, *n_pages, sum_sizes);
2687
ibuf_mtr_commit(&mtr);
2574
2688
btr_pcur_close(&pcur);
2576
2690
buf_read_ibuf_merge_pages(sync, space_ids, space_versions, page_nos,
2832
# define ibuf_get_volume_buffered_count(mtr,rec,hash,size,n_recs) \
2833
ibuf_get_volume_buffered_count_func(mtr,rec,hash,size,n_recs)
2834
#else /* UNIV_DEBUG */
2835
# define ibuf_get_volume_buffered_count(mtr,rec,hash,size,n_recs) \
2836
ibuf_get_volume_buffered_count_func(rec,hash,size,n_recs)
2717
2838
/*********************************************************************//**
2718
2839
Update the estimate of the number of records on a page, and
2719
2840
get the space taken by merging the buffered record to the index page.
2721
2842
taken in the page directory */
2724
ibuf_get_volume_buffered_count(
2725
/*===========================*/
2845
ibuf_get_volume_buffered_count_func(
2846
/*================================*/
2848
mtr_t* mtr, /*!< in: mini-transaction owning rec */
2849
#endif /* UNIV_DEBUG */
2726
2850
const rec_t* rec, /*!< in: insert buffer record */
2727
2851
ulint* hash, /*!< in/out: hash array */
2728
2852
ulint size, /*!< in: number of elements in hash array */
2819
2947
mem_heap_t* heap = mem_heap_create(500);
2821
2949
entry = ibuf_build_entry_from_ibuf_rec(
2822
rec, heap, &dummy_index);
2950
mtr, rec, heap, &dummy_index);
2824
2952
volume = rec_get_converted_size(dummy_index, entry, 0);
2841
2969
ibuf_get_volume_buffered(
2842
2970
/*=====================*/
2843
btr_pcur_t* pcur, /*!< in: pcur positioned at a place in an
2971
const btr_pcur_t*pcur, /*!< in: pcur positioned at a place in an
2844
2972
insert buffer tree where we would insert an
2845
2973
entry for the index page whose number is
2846
2974
page_no, latch mode has to be BTR_MODIFY_PREV
2850
2978
lint* n_recs, /*!< in/out: minimum number of records on the
2851
2979
page after the buffered changes have been
2852
2980
applied, or NULL to disable the counting */
2853
mtr_t* mtr) /*!< in: mtr */
2981
mtr_t* mtr) /*!< in: mini-transaction of pcur */
2862
ulint hash_bitmap[128 / sizeof(ulint)]; /* bitmap of buffered recs */
2987
const page_t* prev_page;
2989
const page_t* next_page;
2990
/* bitmap of buffered recs */
2991
ulint hash_bitmap[128 / sizeof(ulint)];
2864
2993
ut_a(trx_sys_multiple_tablespace_format);
2880
3009
ut_ad(page_validate(page, ibuf->index));
2882
3011
if (page_rec_is_supremum(rec)) {
2883
rec = page_rec_get_prev(rec);
3012
rec = page_rec_get_prev_const(rec);
2887
if (page_rec_is_infimum(rec)) {
2892
if (page_no != ibuf_rec_get_page_no(rec)
2893
|| space != ibuf_rec_get_space(rec)) {
2898
volume += ibuf_get_volume_buffered_count(
2899
rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
2901
rec = page_rec_get_prev(rec);
3015
for (; !page_rec_is_infimum(rec);
3016
rec = page_rec_get_prev_const(rec)) {
2902
3017
ut_ad(page_align(rec) == page);
3019
if (page_no != ibuf_rec_get_page_no(mtr, rec)
3020
|| space != ibuf_rec_get_space(mtr, rec)) {
3025
volume += ibuf_get_volume_buffered_count(
3027
hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
2905
3030
/* Look at the previous page */
2915
3040
buf_block_t* block;
2917
3042
block = buf_page_get(
2918
IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH, mtr);
3043
IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH,
2920
3046
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
2927
3053
#ifdef UNIV_BTR_DEBUG
2928
ut_a(btr_page_get_next(prev_page, mtr)
2929
== page_get_page_no(page));
3054
ut_a(btr_page_get_next(prev_page, mtr) == page_get_page_no(page));
2930
3055
#endif /* UNIV_BTR_DEBUG */
2932
3057
rec = page_get_supremum_rec(prev_page);
2933
rec = page_rec_get_prev(rec);
3058
rec = page_rec_get_prev_const(rec);
3060
for (;; rec = page_rec_get_prev_const(rec)) {
3061
ut_ad(page_align(rec) == prev_page);
2936
3063
if (page_rec_is_infimum(rec)) {
2938
3065
/* We cannot go to yet a previous page, because we
2942
3069
return(UNIV_PAGE_SIZE);
2945
if (page_no != ibuf_rec_get_page_no(rec)
2946
|| space != ibuf_rec_get_space(rec)) {
3072
if (page_no != ibuf_rec_get_page_no(mtr, rec)
3073
|| space != ibuf_rec_get_space(mtr, rec)) {
2948
3075
goto count_later;
2951
3078
volume += ibuf_get_volume_buffered_count(
2952
rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
2954
rec = page_rec_get_prev(rec);
2955
ut_ad(page_align(rec) == prev_page);
3080
hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
2959
3084
rec = btr_pcur_get_rec(pcur);
2961
3086
if (!page_rec_is_supremum(rec)) {
2962
rec = page_rec_get_next(rec);
3087
rec = page_rec_get_next_const(rec);
2966
if (page_rec_is_supremum(rec)) {
2971
if (page_no != ibuf_rec_get_page_no(rec)
2972
|| space != ibuf_rec_get_space(rec)) {
3090
for (; !page_rec_is_supremum(rec);
3091
rec = page_rec_get_next_const(rec)) {
3092
if (page_no != ibuf_rec_get_page_no(mtr, rec)
3093
|| space != ibuf_rec_get_space(mtr, rec)) {
2974
3095
return(volume);
2977
3098
volume += ibuf_get_volume_buffered_count(
2978
rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
2980
rec = page_rec_get_next(rec);
3100
hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
2983
3103
/* Look at the next page */
2993
3113
buf_block_t* block;
2995
3115
block = buf_page_get(
2996
IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH, mtr);
3116
IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH,
2998
3119
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
3007
3128
#endif /* UNIV_BTR_DEBUG */
3009
3130
rec = page_get_infimum_rec(next_page);
3010
rec = page_rec_get_next(rec);
3131
rec = page_rec_get_next_const(rec);
3133
for (;; rec = page_rec_get_next_const(rec)) {
3134
ut_ad(page_align(rec) == next_page);
3013
3136
if (page_rec_is_supremum(rec)) {
3015
3138
/* We give up */
3017
3140
return(UNIV_PAGE_SIZE);
3020
if (page_no != ibuf_rec_get_page_no(rec)
3021
|| space != ibuf_rec_get_space(rec)) {
3143
if (page_no != ibuf_rec_get_page_no(mtr, rec)
3144
|| space != ibuf_rec_get_space(mtr, rec)) {
3023
3146
return(volume);
3026
3149
volume += ibuf_get_volume_buffered_count(
3027
rec, hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
3029
rec = page_rec_get_next(rec);
3030
ut_ad(page_align(rec) == next_page);
3151
hash_bitmap, UT_ARR_SIZE(hash_bitmap), n_recs);
3073
3192
max_space_id = mach_read_from_4(field);
3195
ibuf_mtr_commit(&mtr);
3079
3197
/* printf("Maximum space id in insert buffer %lu\n", max_space_id); */
3081
3199
fil_set_max_space_id_if_bigger(max_space_id);
3203
# define ibuf_get_entry_counter_low(mtr,rec,space,page_no) \
3204
ibuf_get_entry_counter_low_func(mtr,rec,space,page_no)
3205
#else /* UNIV_DEBUG */
3206
# define ibuf_get_entry_counter_low(mtr,rec,space,page_no) \
3207
ibuf_get_entry_counter_low_func(rec,space,page_no)
3084
3209
/****************************************************************//**
3085
3210
Helper function for ibuf_set_entry_counter. Checks if rec is for (space,
3086
3211
page_no), and if so, reads counter value from it and returns that + 1.
3088
3213
@return new counter value, or 0 */
3091
ibuf_get_entry_counter_low(
3092
/*=======================*/
3216
ibuf_get_entry_counter_low_func(
3217
/*============================*/
3219
mtr_t* mtr, /*!< in: mini-transaction of rec */
3220
#endif /* UNIV_DEBUG */
3093
3221
const rec_t* rec, /*!< in: insert buffer record */
3094
3222
ulint space, /*!< in: space id */
3095
3223
ulint page_no) /*!< in: page number */
3098
3226
const byte* field;
3101
ut_ad(ibuf_inside());
3229
ut_ad(ibuf_inside(mtr));
3230
ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)
3231
|| mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX));
3102
3232
ut_ad(rec_get_n_fields_old(rec) > 2);
3104
3234
field = rec_get_nth_field_old(rec, 1, &len);
3170
3300
ulint counter = 0;
3172
3302
/* pcur points to either a user rec or to a page's infimum record. */
3303
ut_ad(ibuf_inside(mtr));
3304
ut_ad(mtr_memo_contains(mtr, btr_pcur_get_block(pcur),
3305
MTR_MEMO_PAGE_X_FIX));
3173
3306
ut_ad(page_validate(btr_pcur_get_page(pcur), ibuf->index));
3175
3308
if (btr_pcur_is_on_user_rec(pcur)) {
3177
3310
counter = ibuf_get_entry_counter_low(
3178
btr_pcur_get_rec(pcur), space, page_no);
3311
mtr, btr_pcur_get_rec(pcur), space, page_no);
3180
3313
if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) {
3181
3314
/* The record lacks a counter field.
3482
3611
if (buffered + entry_size + page_dir_calc_reserved_space(1)
3483
3612
> ibuf_index_page_calc_free_from_bits(zip_size, bits)) {
3484
3613
/* Release the bitmap page latch early. */
3485
mtr_commit(&bitmap_mtr);
3614
ibuf_mtr_commit(&bitmap_mtr);
3487
3616
/* It may not fit */
3488
3617
do_merge = TRUE;
3490
ibuf_get_merge_page_nos(
3491
FALSE, btr_pcur_get_rec(&pcur),
3492
space_ids, space_versions,
3493
page_nos, &n_stored);
3619
ibuf_get_merge_page_nos(FALSE,
3620
btr_pcur_get_rec(&pcur), &mtr,
3621
space_ids, space_versions,
3622
page_nos, &n_stored);
3495
3624
goto fail_exit;
4138
4266
/* The tablespace has been dropped. It is possible
4139
4267
that another thread has deleted the insert buffer
4140
4268
entry. Do not complain. */
4141
btr_pcur_commit_specify_mtr(pcur, mtr);
4269
ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
4143
4271
fprintf(stderr,
4144
4272
"InnoDB: ERROR: Submit the output to"
4156
4284
page_rec_get_next(btr_pcur_get_rec(pcur)));
4157
4285
fflush(stderr);
4159
btr_pcur_commit_specify_mtr(pcur, mtr);
4287
ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
4161
4289
fputs("InnoDB: Validating insert buffer tree:\n", stderr);
4162
4290
if (!btr_validate_index(ibuf->index, NULL)) {
4180
4308
ibuf_delete_rec(
4181
4309
/*============*/
4182
4310
ulint space, /*!< in: space id */
4183
ulint page_no,/*!< in: index page number where the record
4311
ulint page_no,/*!< in: index page number that the record
4185
4313
btr_pcur_t* pcur, /*!< in: pcur positioned on the record to
4186
4314
delete, having latch mode BTR_MODIFY_LEAF */
4187
4315
const dtuple_t* search_tuple,
4195
ut_ad(ibuf_inside());
4323
ut_ad(ibuf_inside(mtr));
4196
4324
ut_ad(page_rec_is_user_rec(btr_pcur_get_rec(pcur)));
4197
ut_ad(ibuf_rec_get_page_no(btr_pcur_get_rec(pcur)) == page_no);
4198
ut_ad(ibuf_rec_get_space(btr_pcur_get_rec(pcur)) == space);
4325
ut_ad(ibuf_rec_get_page_no(mtr, btr_pcur_get_rec(pcur)) == page_no);
4326
ut_ad(ibuf_rec_get_space(mtr, btr_pcur_get_rec(pcur)) == space);
4200
4328
success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr);
4230
4358
ut_ad(page_rec_is_user_rec(btr_pcur_get_rec(pcur)));
4231
ut_ad(ibuf_rec_get_page_no(btr_pcur_get_rec(pcur)) == page_no);
4232
ut_ad(ibuf_rec_get_space(btr_pcur_get_rec(pcur)) == space);
4359
ut_ad(ibuf_rec_get_page_no(mtr, btr_pcur_get_rec(pcur)) == page_no);
4360
ut_ad(ibuf_rec_get_space(mtr, btr_pcur_get_rec(pcur)) == space);
4234
4362
/* We have to resort to a pessimistic delete from ibuf */
4235
4363
btr_pcur_store_position(pcur, mtr);
4237
btr_pcur_commit_specify_mtr(pcur, mtr);
4364
ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
4366
ibuf_mtr_start(mtr);
4239
4367
mutex_enter(&ibuf_mutex);
4243
4369
if (!ibuf_restore_pos(space, page_no, search_tuple,
4244
4370
BTR_MODIFY_TREE, pcur, mtr)) {
4246
4372
mutex_exit(&ibuf_mutex);
4373
ut_ad(!ibuf_inside(mtr));
4374
ut_ad(mtr->state == MTR_COMMITTED);
4247
4375
goto func_exit;
4354
4484
update_ibuf_bitmap = FALSE;
4356
4486
page_t* bitmap_page;
4489
ibuf_mtr_start(&mtr);
4360
4491
bitmap_page = ibuf_bitmap_get_map_page(
4361
4492
space, page_no, zip_size, &mtr);
4363
if (!ibuf_bitmap_page_get_bits(bitmap_page, page_no,
4365
IBUF_BITMAP_BUFFERED,
4493
bitmap_bits = ibuf_bitmap_page_get_bits(
4494
bitmap_page, page_no, zip_size,
4495
IBUF_BITMAP_BUFFERED, &mtr);
4497
ibuf_mtr_commit(&mtr);
4367
4500
/* No inserts buffered for this page */
4370
4502
if (!tablespace_being_deleted) {
4371
4503
fil_decr_pending_ibuf_merges(space);
4487
4615
rec = btr_pcur_get_rec(&pcur);
4489
4617
/* Check if the entry is for this index page */
4490
if (ibuf_rec_get_page_no(rec) != page_no
4491
|| ibuf_rec_get_space(rec) != space) {
4618
if (ibuf_rec_get_page_no(&mtr, rec) != page_no
4619
|| ibuf_rec_get_space(&mtr, rec) != space) {
4494
4622
page_header_reset_last_insert(
4511
4639
dtuple_t* entry;
4512
4640
trx_id_t max_trx_id;
4513
4641
dict_index_t* dummy_index;
4514
ibuf_op_t op = ibuf_rec_get_op_type(rec);
4642
ibuf_op_t op = ibuf_rec_get_op_type(&mtr, rec);
4516
4644
max_trx_id = page_get_max_trx_id(page_align(rec));
4517
4645
page_update_max_trx_id(block, page_zip, max_trx_id,
4520
4648
ut_ad(page_validate(page_align(rec), ibuf->index));
4522
4650
entry = ibuf_build_entry_from_ibuf_rec(
4523
rec, heap, &dummy_index);
4651
&mtr, rec, heap, &dummy_index);
4525
4653
ut_ad(page_validate(block->frame, dummy_index));
4553
4681
Store and restore the cursor position. */
4554
4682
ut_ad(rec == btr_pcur_get_rec(&pcur));
4555
4683
ut_ad(page_rec_is_user_rec(rec));
4556
ut_ad(ibuf_rec_get_page_no(rec) == page_no);
4557
ut_ad(ibuf_rec_get_space(rec) == space);
4684
ut_ad(ibuf_rec_get_page_no(&mtr, rec)
4686
ut_ad(ibuf_rec_get_space(&mtr, rec) == space);
4559
4688
btr_pcur_store_position(&pcur, &mtr);
4560
btr_pcur_commit_specify_mtr(&pcur, &mtr);
4689
ibuf_btr_pcur_commit_specify_mtr(&pcur, &mtr);
4691
ibuf_mtr_start(&mtr);
4564
4693
success = buf_page_get_known_nowait(
4565
4694
RW_X_LATCH, block,
4718
4843
ibuf_rec = btr_pcur_get_rec(&pcur);
4720
4845
/* Check if the entry is for this space */
4721
if (ibuf_rec_get_space(ibuf_rec) != space) {
4846
if (ibuf_rec_get_space(&mtr, ibuf_rec) != space) {
4723
4848
goto leave_loop;
4726
page_no = ibuf_rec_get_page_no(ibuf_rec);
4851
page_no = ibuf_rec_get_page_no(&mtr, ibuf_rec);
4728
dops[ibuf_rec_get_op_type(ibuf_rec)]++;
4853
dops[ibuf_rec_get_op_type(&mtr, ibuf_rec)]++;
4730
4855
/* Delete the record from ibuf */
4731
closed = ibuf_delete_rec(space, page_no, &pcur, search_tuple,
4856
if (ibuf_delete_rec(space, page_no, &pcur, search_tuple,
4734
4858
/* Deletion was pessimistic and mtr was committed:
4735
4859
we start from the beginning again */
4742
4864
if (btr_pcur_is_after_last_on_page(&pcur)) {
4865
ibuf_mtr_commit(&mtr);
4744
4866
btr_pcur_close(&pcur);
4873
ibuf_mtr_commit(&mtr);
4754
4874
btr_pcur_close(&pcur);
4756
4876
#ifdef HAVE_ATOMIC_BUILTINS