69
69
cache line as btr_search_latch */
70
70
UNIV_INTERN byte btr_sea_pad1[64];
72
/** The latch protecting the adaptive search system: this latch protects the
73
(1) positions of records on those pages where a hash index has been built.
74
NOTE: It does not protect values of non-ordering fields within a record from
72
/** Array of latches protecting individual AHI partitions. The latches
73
protect: (1) positions of records on those pages where a hash index from the
74
corresponding AHI partition has been built.
75
NOTE: They do not protect values of non-ordering fields within a record from
75
76
being updated in-place! We can use fact (1) to perform unique searches to
78
/* We will allocate the latch from dynamic memory to get it to the
79
same DRAM page as other hotspot semaphores */
80
//UNIV_INTERN rw_lock_t* btr_search_latch_temp;
82
UNIV_INTERN rw_lock_t** btr_search_latch_part;
79
UNIV_INTERN rw_lock_t* btr_search_latch_arr;
84
81
/** padding to prevent other memory update hotspots from residing on
85
82
the same memory cache line */
134
131
btr_search_check_free_space_in_heap(
135
132
/*=====================================*/
138
135
hash_table_t* table;
139
136
mem_heap_t* heap;
141
138
#ifdef UNIV_SYNC_DEBUG
142
ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
143
ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
139
ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_SHARED));
140
ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_EX));
144
141
#endif /* UNIV_SYNC_DEBUG */
146
table = btr_search_get_hash_index(key);
143
table = btr_search_get_hash_table(index);
148
145
heap = table->heap;
154
151
if (heap->free_block == NULL) {
155
152
buf_block_t* block = buf_block_alloc(NULL);
157
rw_lock_x_lock(btr_search_get_latch(key));
154
rw_lock_x_lock(btr_search_get_latch(index));
159
156
if (heap->free_block == NULL) {
160
157
heap->free_block = block;
195
192
btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
197
/* btr_search_index_num should be <= 32. (bits of trx->has_search_latch) */
198
btr_search_latch_part = mem_alloc(sizeof(rw_lock_t*) * btr_search_index_num);
199
btr_search_sys->hash_index = mem_alloc(sizeof(hash_table_t*) * btr_search_index_num);
194
/* btr_search_index_num is constrained to machine word size for
195
historical reasons. This limitation can be easily removed later. */
197
btr_search_latch_arr = mem_alloc(sizeof(rw_lock_t) *
198
btr_search_index_num);
199
btr_search_sys->hash_tables = mem_alloc(sizeof(hash_table_t *) *
200
btr_search_index_num);
200
201
for (i = 0; i < btr_search_index_num; i++) {
201
btr_search_latch_part[i] = mem_alloc(sizeof(rw_lock_t));
203
203
rw_lock_create(btr_search_latch_key,
204
btr_search_latch_part[i], SYNC_SEARCH_SYS);
204
&btr_search_latch_arr[i], SYNC_SEARCH_SYS);
206
btr_search_sys->hash_index[i] = ha_create(hash_size, 0, 0);
206
btr_search_sys->hash_tables[i] = ha_create(hash_size, 0, 0);
219
219
for (i = 0; i < btr_search_index_num; i++) {
220
mem_heap_free(btr_search_sys->hash_index[i]->heap);
221
hash_table_free(btr_search_sys->hash_index[i]);
223
rw_lock_free(btr_search_latch_part[i]);
225
mem_free(btr_search_latch_part[i]);
220
mem_heap_free(btr_search_sys->hash_tables[i]->heap);
221
hash_table_free(btr_search_sys->hash_tables[i]);
223
rw_lock_free(&btr_search_latch_arr[i]);
227
mem_free(btr_search_sys->hash_index);
228
mem_free(btr_search_latch_part);
225
mem_free(btr_search_sys->hash_tables);
226
mem_free(btr_search_latch_arr);
230
228
//rw_lock_free(&btr_search_latch);
231
229
//mem_free(btr_search_latch_temp);
271
269
/* Clear the adaptive hash index. */
272
270
for (i = 0; i < btr_search_index_num; i++) {
273
hash_table_clear(btr_search_sys->hash_index[i]);
274
mem_heap_empty(btr_search_sys->hash_index[i]->heap);
271
hash_table_clear(btr_search_sys->hash_tables[i]);
272
mem_heap_empty(btr_search_sys->hash_tables[i]->heap);
277
275
btr_search_x_unlock_all();
335
333
/*****************************************************************//**
336
334
Returns the value of ref_count. The value is protected by
335
the latch of the AHI partition corresponding to this index.
338
336
@return ref_count value. */
341
339
btr_search_info_get_ref_count(
342
340
/*==========================*/
343
341
btr_search_t* info, /*!< in: search info. */
342
dict_index_t* index) /*!< in: index */
350
348
#ifdef UNIV_SYNC_DEBUG
351
ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
352
ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
349
ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_SHARED));
350
ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_EX));
353
351
#endif /* UNIV_SYNC_DEBUG */
355
rw_lock_s_lock(btr_search_get_latch(key));
353
rw_lock_s_lock(btr_search_get_latch(index));
356
354
ret = info->ref_count;
357
rw_lock_s_unlock(btr_search_get_latch(key));
355
rw_lock_s_unlock(btr_search_get_latch(index));
377
375
#ifdef UNIV_SYNC_DEBUG
378
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
379
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
376
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_SHARED));
377
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_EX));
380
378
#endif /* UNIV_SYNC_DEBUG */
382
380
index = cursor->index;
494
492
/*!< in: cursor */
496
494
#ifdef UNIV_SYNC_DEBUG
497
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
498
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
495
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_SHARED));
496
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_EX));
499
497
ut_ad(rw_lock_own(&block->lock, RW_LOCK_SHARED)
500
498
|| rw_lock_own(&block->lock, RW_LOCK_EX));
501
499
#endif /* UNIV_SYNC_DEBUG */
580
578
ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
581
579
#ifdef UNIV_SYNC_DEBUG
582
ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
580
ut_ad(rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_EX));
583
581
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
584
582
|| rw_lock_own(&(block->lock), RW_LOCK_EX));
585
583
#endif /* UNIV_SYNC_DEBUG */
620
618
mem_heap_free(heap);
622
620
#ifdef UNIV_SYNC_DEBUG
623
ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
621
ut_ad(rw_lock_own(btr_search_get_latch(cursor->index),
624
623
#endif /* UNIV_SYNC_DEBUG */
626
ha_insert_for_fold(btr_search_get_hash_index(cursor->index->id), fold,
625
ha_insert_for_fold(btr_search_get_hash_table(cursor->index),
645
644
#ifdef UNIV_SYNC_DEBUG
646
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
647
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
645
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_SHARED));
646
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_EX));
648
647
#endif /* UNIV_SYNC_DEBUG */
650
649
block = btr_cur_get_block(cursor);
663
662
if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
665
btr_search_check_free_space_in_heap(cursor->index->id);
664
btr_search_check_free_space_in_heap(cursor->index);
668
667
if (cursor->flag == BTR_CUR_HASH_FAIL) {
672
671
btr_search_n_hash_fail++;
673
672
#endif /* UNIV_SEARCH_PERF_STAT */
675
rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
674
rw_lock_x_lock(btr_search_get_latch(cursor->index));
677
676
btr_search_update_hash_ref(info, block, cursor);
679
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
678
rw_lock_x_unlock(btr_search_get_latch(cursor->index));
682
681
if (build_index) {
921
920
cursor->flag = BTR_CUR_HASH;
923
922
if (UNIV_LIKELY(!has_search_latch)) {
924
rw_lock_s_lock(btr_search_get_latch(index_id));
923
rw_lock_s_lock(btr_search_get_latch(index));
926
925
if (UNIV_UNLIKELY(!btr_search_enabled)) {
927
926
goto failure_unlock;
931
ut_ad(rw_lock_get_writer(btr_search_get_latch(index_id)) != RW_LOCK_EX);
932
ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index_id)) > 0);
930
ut_ad(rw_lock_get_writer(btr_search_get_latch(index)) != RW_LOCK_EX);
931
ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index)) > 0);
934
rec = ha_search_and_get_data(btr_search_get_hash_index(index_id), fold);
933
rec = ha_search_and_get_data(btr_search_get_hash_table(index), fold);
936
935
if (UNIV_UNLIKELY(!rec)) {
937
936
goto failure_unlock;
1046
1045
/*-------------------------------------------*/
1047
1046
failure_unlock:
1048
1047
if (UNIV_LIKELY(!has_search_latch)) {
1049
rw_lock_s_unlock(btr_search_get_latch(index_id));
1048
rw_lock_s_unlock(btr_search_get_latch(index));
1052
1051
cursor->flag = BTR_CUR_HASH_FAIL;
1091
1090
ulint* offsets;
1094
if (btr_search_index_num > 1) {
1095
rw_lock_t* btr_search_latch;
1097
/* FIXME: This may be optimistic implementation still. */
1098
btr_search_latch = (rw_lock_t*)(block->btr_search_latch);
1099
if (UNIV_LIKELY(!btr_search_latch)) {
1105
rw_lock_s_lock(btr_search_latch);
1106
if (UNIV_LIKELY(btr_search_latch != block->btr_search_latch)) {
1107
rw_lock_s_unlock(btr_search_latch);
1110
if (UNIV_LIKELY(!block->index)) {
1111
rw_lock_s_unlock(btr_search_latch);
1114
index = block->index;
1115
ut_a(btr_search_latch == btr_search_get_latch(index->id));
1117
/* btr_search_index_num == 1 */
1118
/* btr_search_latch is only one and able to obtain
1119
before evaluating block->index. */
1120
rw_lock_s_lock(btr_search_latch_part[0]);
1121
if (UNIV_LIKELY(!block->index)) {
1122
rw_lock_s_unlock(btr_search_latch_part[0]);
1125
index = block->index;
1128
if (UNIV_LIKELY(!index)) {
1130
rw_lock_s_unlock(btr_search_get_latch(index->id));
1093
/* Do a dirty check on block->index, return if the block is not in the
1094
adaptive hash index. This is to avoid acquiring an AHI latch for
1095
performance considerations. */
1097
index = block->index;
1135
table = btr_search_get_hash_index(index->id);
1103
rw_lock_s_lock(btr_search_get_latch(index));
1105
if (UNIV_UNLIKELY(index != block->index)) {
1107
rw_lock_s_unlock(btr_search_get_latch(index));
1112
table = btr_search_get_hash_table(index);
1137
1114
#ifdef UNIV_SYNC_DEBUG
1138
1115
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
1149
1126
releasing btr_search_latch, as the index page might only
1150
1127
be s-latched! */
1152
rw_lock_s_unlock(btr_search_get_latch(index->id));
1129
rw_lock_s_unlock(btr_search_get_latch(index));
1154
1131
ut_a(n_fields + n_bytes > 0);
1216
1193
/* Someone else has meanwhile built a new hash index on the
1217
1194
page, with different parameters */
1219
rw_lock_x_unlock(btr_search_get_latch(index->id));
1196
rw_lock_x_unlock(btr_search_get_latch(index));
1221
1198
mem_free(folds);
1244
1220
"InnoDB: the hash index to a page of %s,"
1245
1221
" still %lu hash nodes remain.\n",
1246
1222
index->name, (ulong) block->n_pointers);
1247
rw_lock_x_unlock(btr_search_get_latch(index->id));
1223
rw_lock_x_unlock(btr_search_get_latch(index));
1249
1225
ut_ad(btr_search_validate());
1251
rw_lock_x_unlock(btr_search_get_latch(index->id));
1227
rw_lock_x_unlock(btr_search_get_latch(index));
1253
1229
#else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
1254
rw_lock_x_unlock(btr_search_get_latch(index->id));
1230
rw_lock_x_unlock(btr_search_get_latch(index));
1255
1231
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
1257
1233
mem_free(folds);
1283
1259
ulint* offsets;
1284
1260
ibool released_search_latch;
1286
rw_lock_s_lock(btr_search_get_latch(index->id));
1262
rw_lock_s_lock(btr_search_get_latch(index));
1288
table = btr_search_get_hash_index(index->id);
1264
table = btr_search_get_hash_table(index);
1290
1266
for (j = 0; j < srv_buf_pool_instances; j++) {
1291
1267
buf_pool_t* buf_pool;
1321
1297
/* keeping latch order */
1322
rw_lock_s_unlock(btr_search_get_latch(index->id));
1299
btr_search_get_latch(index));
1323
1300
released_search_latch = TRUE;
1324
1301
rw_lock_x_lock(&block->lock);
1382
1360
if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
1383
1361
|| UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
1384
rw_lock_x_unlock(btr_search_get_latch(index->id));
1363
btr_search_get_latch(index));
1385
1364
rw_lock_x_unlock(&block->lock);
1387
1366
mem_free(folds);
1389
rw_lock_s_lock(btr_search_get_latch(index->id));
1369
btr_search_get_latch(index));
1412
1391
index->name, (ulong) block->n_pointers);
1414
1393
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
1415
rw_lock_x_unlock(btr_search_get_latch(index->id));
1395
btr_search_get_latch(index));
1416
1396
rw_lock_x_unlock(&block->lock);
1418
1398
mem_free(folds);
1420
rw_lock_s_lock(btr_search_get_latch(index->id));
1401
btr_search_get_latch(index));
1423
1404
} while (released_search_latch);
1426
rw_lock_s_unlock(btr_search_get_latch(index->id));
1407
rw_lock_s_unlock(btr_search_get_latch(index));
1428
1409
if (UNIV_LIKELY_NULL(heap)) {
1429
1410
mem_heap_free(heap);
1511
1492
|| rw_lock_own(&(block->lock), RW_LOCK_EX));
1512
1493
#endif /* UNIV_SYNC_DEBUG */
1514
rw_lock_s_lock(btr_search_get_latch(index->id));
1495
rw_lock_s_lock(btr_search_get_latch(index));
1516
1497
if (block->index && ((block->curr_n_fields != n_fields)
1517
1498
|| (block->curr_n_bytes != n_bytes)
1518
1499
|| (block->curr_left_side != left_side))) {
1520
rw_lock_s_unlock(btr_search_get_latch(index->id));
1501
rw_lock_s_unlock(btr_search_get_latch(index));
1522
1503
btr_search_drop_page_hash_index(block);
1524
rw_lock_s_unlock(btr_search_get_latch(index->id));
1505
rw_lock_s_unlock(btr_search_get_latch(index));
1527
1508
n_recs = page_get_n_recs(page);
1615
1596
fold = next_fold;
1618
btr_search_check_free_space_in_heap(index->id);
1599
btr_search_check_free_space_in_heap(index);
1620
rw_lock_x_lock(btr_search_get_latch(index->id));
1601
rw_lock_x_lock(btr_search_get_latch(index));
1622
1603
if (UNIV_UNLIKELY(!btr_search_enabled)) {
1623
1604
goto exit_func;
1687
1667
ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));
1688
1668
#endif /* UNIV_SYNC_DEBUG */
1690
rw_lock_s_lock(btr_search_get_latch(index->id));
1670
rw_lock_s_lock(btr_search_get_latch(index));
1692
1672
ut_a(!new_block->index || new_block->index == index);
1693
1673
ut_a(!block->index || block->index == index);
1713
1693
new_block->n_bytes = block->curr_n_bytes;
1714
1694
new_block->left_side = left_side;
1716
rw_lock_s_unlock(btr_search_get_latch(index->id));
1696
rw_lock_s_unlock(btr_search_get_latch(index));
1718
1698
ut_a(n_fields + n_bytes > 0);
1764
1744
ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
1765
1745
ut_a(!dict_index_is_ibuf(index));
1767
table = btr_search_get_hash_index(cursor->index->id);
1747
table = btr_search_get_hash_table(cursor->index);
1769
1749
rec = btr_cur_get_rec(cursor);
1783
1763
ha_search_and_delete_if_found(table, fold, rec);
1786
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
1766
rw_lock_x_unlock(btr_search_get_latch(cursor->index));
1789
1769
/********************************************************************//**
1834
1814
&& (cursor->n_bytes == block->curr_n_bytes)
1835
1815
&& !block->curr_left_side) {
1837
table = btr_search_get_hash_index(cursor->index->id);
1817
table = btr_search_get_hash_table(cursor->index);
1839
1819
ha_search_and_update_if_found(table, cursor->fold, rec,
1840
1820
block, page_rec_get_next(rec));
1843
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
1823
rw_lock_x_unlock(btr_search_get_latch(cursor->index));
1845
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
1825
rw_lock_x_unlock(btr_search_get_latch(cursor->index));
1847
1827
btr_search_update_hash_on_insert(cursor);
1877
1857
ulint* offsets = offsets_;
1878
1858
rec_offs_init(offsets_);
1880
table = btr_search_get_hash_index(cursor->index->id);
1860
table = btr_search_get_hash_table(cursor->index);
1882
btr_search_check_free_space_in_heap(cursor->index->id);
1862
btr_search_check_free_space_in_heap(cursor->index);
1884
1864
rec = btr_cur_get_rec(cursor);
2044
2024
for (j = 0; j < btr_search_index_num; j++) {
2046
cell_count = hash_get_n_cells(btr_search_sys->hash_index[j]);
2026
cell_count = hash_get_n_cells(btr_search_sys->hash_tables[j]);
2048
2028
for (i = 0; i < cell_count; i++) {
2049
2029
/* We release btr_search_latch every once in a while to
2056
2036
buf_pool_page_hash_x_lock_all();
2059
node = hash_get_nth_cell(btr_search_sys->hash_index[j], i)->node;
2039
node = hash_get_nth_cell(btr_search_sys->hash_tables[j], i)->node;
2061
2041
for (; node != NULL; node = node->next) {
2062
2042
const buf_block_t* block
2171
2151
buf_pool_page_hash_x_lock_all();
2174
if (!ha_validate(btr_search_sys->hash_index[j], i, end_index)) {
2154
if (!ha_validate(btr_search_sys->hash_tables[j], i, end_index)) {