1
1
/*****************************************************************************
3
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
3
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
4
4
Copyright (c) 2008, Google Inc.
6
6
Portions of this file contain modifications contributed and copyrighted by
46
46
/** Flag: has the search system been enabled?
47
Protected by btr_search_latch and btr_search_enabled_mutex. */
47
Protected by btr_search_latch. */
48
48
UNIV_INTERN char btr_search_enabled = TRUE;
50
/** Mutex protecting btr_search_enabled */
51
static mutex_t btr_search_enabled_mutex;
53
50
/** A dummy variable to fool the compiler */
54
51
UNIV_INTERN ulint btr_search_this_is_zero = 0;
140
137
be enough free space in the hash table. */
142
139
if (heap->free_block == NULL) {
143
buf_block_t* block = buf_block_alloc(0);
140
buf_block_t* block = buf_block_alloc();
145
142
rw_lock_x_lock(&btr_search_latch);
168
165
btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
170
167
rw_lock_create(&btr_search_latch, SYNC_SEARCH_SYS);
171
mutex_create(&btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF);
173
169
btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
198
194
btr_search_disable(void)
199
195
/*====================*/
201
mutex_enter(&btr_search_enabled_mutex);
199
mutex_enter(&dict_sys->mutex);
202
200
rw_lock_x_lock(&btr_search_latch);
204
202
btr_search_enabled = FALSE;
206
/* Clear all block->is_hashed flags and remove all entries
207
from btr_search_sys->hash_index. */
208
buf_pool_drop_hash_index();
210
/* btr_search_enabled_mutex should guarantee this. */
211
ut_ad(!btr_search_enabled);
204
/* Clear the index->search_info->ref_count of every index in
205
the data dictionary cache. */
206
for (table = UT_LIST_GET_FIRST(dict_sys->table_LRU); table;
207
table = UT_LIST_GET_NEXT(table_LRU, table)) {
211
for (index = dict_table_get_first_index(table); index;
212
index = dict_table_get_next_index(index)) {
214
index->search_info->ref_count = 0;
218
mutex_exit(&dict_sys->mutex);
220
/* Set all block->index = NULL. */
221
buf_pool_clear_hash_index();
223
/* Clear the adaptive hash index. */
224
hash_table_clear(btr_search_sys->hash_index);
225
mem_heap_empty(btr_search_sys->hash_index->heap);
213
227
rw_lock_x_unlock(&btr_search_latch);
214
mutex_exit(&btr_search_enabled_mutex);
217
230
/********************************************************************//**
221
234
btr_search_enable(void)
222
235
/*====================*/
224
mutex_enter(&btr_search_enabled_mutex);
225
237
rw_lock_x_lock(&btr_search_latch);
227
239
btr_search_enabled = TRUE;
229
241
rw_lock_x_unlock(&btr_search_latch);
230
mutex_exit(&btr_search_enabled_mutex);
233
244
/*****************************************************************//**
450
461
&& (block->n_bytes == info->n_bytes)
451
462
&& (block->left_side == info->left_side)) {
453
if ((block->is_hashed)
454
465
&& (block->curr_n_fields == info->n_fields)
455
466
&& (block->curr_n_bytes == info->n_bytes)
456
467
&& (block->curr_left_side == info->left_side)) {
524
535
ut_ad(page_align(btr_cur_get_rec(cursor))
525
536
== buf_block_get_frame(block));
527
if (!block->is_hashed) {
538
index = block->index;
532
ut_a(block->index == cursor->index);
533
ut_a(!dict_index_is_ibuf(cursor->index));
545
ut_a(index == cursor->index);
546
ut_a(!dict_index_is_ibuf(index));
535
548
if ((info->n_hash_potential > 0)
536
549
&& (block->curr_n_fields == info->n_fields)
550
index_id = cursor->index->id;
551
563
fold = rec_fold(rec,
552
rec_get_offsets(rec, cursor->index, offsets_,
564
rec_get_offsets(rec, index, offsets_,
553
565
ULINT_UNDEFINED, &heap),
554
566
block->curr_n_fields,
555
block->curr_n_bytes, index_id);
567
block->curr_n_bytes, index->id);
556
568
if (UNIV_LIKELY_NULL(heap)) {
557
569
mem_heap_free(heap);
901
914
ut_ad(page_rec_is_user_rec(rec));
903
btr_cur_position(index, rec, block, cursor);
916
btr_cur_position(index, (rec_t*) rec, block, cursor);
905
918
/* Check the validity of the guess within the page */
1033
1046
rw_lock_s_lock(&btr_search_latch);
1034
page = block->frame;
1047
index = block->index;
1036
if (UNIV_LIKELY(!block->is_hashed)) {
1049
if (UNIV_LIKELY(!index)) {
1038
1051
rw_lock_s_unlock(&btr_search_latch);
1056
ut_a(!dict_index_is_ibuf(index));
1043
1057
table = btr_search_sys->hash_index;
1045
1059
#ifdef UNIV_SYNC_DEBUG
1051
1065
n_fields = block->curr_n_fields;
1052
1066
n_bytes = block->curr_n_bytes;
1053
index = block->index;
1054
ut_a(!dict_index_is_ibuf(index));
1056
1068
/* NOTE: The fields of block must not be accessed after
1057
1069
releasing btr_search_latch, as the index page might only
1137
1150
ut_a(index->search_info->ref_count > 0);
1138
1151
index->search_info->ref_count--;
1140
block->is_hashed = FALSE;
1141
1153
block->index = NULL;
1144
1156
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
1145
1157
if (UNIV_UNLIKELY(block->n_pointers)) {
1167
1179
/********************************************************************//**
1168
Drops a page hash index when a page is freed from a fseg to the file system.
1169
Drops possible hash index if the page happens to be in the buffer pool. */
1180
Drops a possible page hash index when a page is evicted from the buffer pool
1181
or freed in a file segment. */
1172
1184
btr_search_drop_page_hash_when_freed(
1179
1191
buf_block_t* block;
1182
if (!buf_page_peek_if_search_hashed(space, page_no)) {
1187
1194
mtr_start(&mtr);
1189
/* We assume that if the caller has a latch on the page, then the
1190
caller has already dropped the hash index for the page, and we never
1191
get here. Therefore we can acquire the s-latch to the page without
1192
having to fear a deadlock. */
1194
block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH, NULL,
1195
BUF_GET_IF_IN_POOL, __FILE__, __LINE__,
1197
/* Because the buffer pool mutex was released by
1198
buf_page_peek_if_search_hashed(), it is possible that the
1199
block was removed from the buffer pool by another thread
1200
before buf_page_get_gen() got a chance to acquire the buffer
1201
pool mutex again. Thus, we must check for a NULL return. */
1203
if (UNIV_LIKELY(block != NULL)) {
1196
/* If the caller has a latch on the page, then the caller must
1197
have a x-latch on the page and it must have already dropped
1198
the hash index for the page. Because of the x-latch that we
1199
are possibly holding, we cannot s-latch the page, but must
1200
(recursively) x-latch it, even though we are only reading. */
1202
block = buf_page_get_gen(space, zip_size, page_no, RW_X_LATCH, NULL,
1203
BUF_PEEK_IF_IN_POOL, __FILE__, __LINE__,
1206
if (block && block->index) {
1205
1208
buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
1247
1249
ut_a(!dict_index_is_ibuf(index));
1251
#ifdef UNIV_SYNC_DEBUG
1252
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1253
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
1254
|| rw_lock_own(&(block->lock), RW_LOCK_EX));
1255
#endif /* UNIV_SYNC_DEBUG */
1257
rw_lock_s_lock(&btr_search_latch);
1259
if (!btr_search_enabled) {
1260
rw_lock_s_unlock(&btr_search_latch);
1249
1264
table = btr_search_sys->hash_index;
1250
1265
page = buf_block_get_frame(block);
1252
#ifdef UNIV_SYNC_DEBUG
1253
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1254
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
1255
|| rw_lock_own(&(block->lock), RW_LOCK_EX));
1256
#endif /* UNIV_SYNC_DEBUG */
1258
rw_lock_s_lock(&btr_search_latch);
1260
if (block->is_hashed && ((block->curr_n_fields != n_fields)
1261
|| (block->curr_n_bytes != n_bytes)
1262
|| (block->curr_left_side != left_side))) {
1267
if (block->index && ((block->curr_n_fields != n_fields)
1268
|| (block->curr_n_bytes != n_bytes)
1269
|| (block->curr_left_side != left_side))) {
1264
1271
rw_lock_s_unlock(&btr_search_latch);
1314
fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
1321
fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id);
1316
1323
if (left_side) {
1338
1345
offsets = rec_get_offsets(next_rec, index, offsets,
1339
1346
n_fields + (n_bytes > 0), &heap);
1340
1347
next_fold = rec_fold(next_rec, offsets, n_fields,
1348
n_bytes, index->id);
1343
1350
if (fold != next_fold) {
1344
1351
/* Insert an entry into the hash index */
1367
1374
goto exit_func;
1370
if (block->is_hashed && ((block->curr_n_fields != n_fields)
1371
|| (block->curr_n_bytes != n_bytes)
1372
|| (block->curr_left_side != left_side))) {
1377
if (block->index && ((block->curr_n_fields != n_fields)
1378
|| (block->curr_n_bytes != n_bytes)
1379
|| (block->curr_left_side != left_side))) {
1373
1380
goto exit_func;
1378
1385
rebuild hash index for a page that is already hashed, we
1379
1386
have to take care not to increment the counter in that
1381
if (!block->is_hashed) {
1388
if (!block->index) {
1382
1389
index->search_info->ref_count++;
1385
block->is_hashed = TRUE;
1386
1392
block->n_hash_helps = 0;
1388
1394
block->curr_n_fields = n_fields;
1430
1436
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
1431
1437
ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));
1432
1438
#endif /* UNIV_SYNC_DEBUG */
1433
ut_a(!new_block->is_hashed || new_block->index == index);
1434
ut_a(!block->is_hashed || block->index == index);
1435
ut_a(!(new_block->is_hashed || block->is_hashed)
1440
rw_lock_s_lock(&btr_search_latch);
1442
ut_a(!new_block->index || new_block->index == index);
1443
ut_a(!block->index || block->index == index);
1444
ut_a(!(new_block->index || block->index)
1436
1445
|| !dict_index_is_ibuf(index));
1438
rw_lock_s_lock(&btr_search_latch);
1440
if (new_block->is_hashed) {
1447
if (new_block->index) {
1442
1449
rw_lock_s_unlock(&btr_search_latch);
1484
1491
hash_table_t* table;
1485
1492
buf_block_t* block;
1495
dict_index_t* index;
1490
1496
ulint offsets_[REC_OFFS_NORMAL_SIZE];
1491
1497
mem_heap_t* heap = NULL;
1492
1498
rec_offs_init(offsets_);
1494
rec = btr_cur_get_rec(cursor);
1496
1500
block = btr_cur_get_block(cursor);
1498
1502
#ifdef UNIV_SYNC_DEBUG
1499
1503
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
1500
1504
#endif /* UNIV_SYNC_DEBUG */
1502
if (!block->is_hashed) {
1506
index = block->index;
1507
ut_a(block->index == cursor->index);
1513
ut_a(index == cursor->index);
1508
1514
ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
1509
ut_a(!dict_index_is_ibuf(cursor->index));
1515
ut_a(!dict_index_is_ibuf(index));
1511
1517
table = btr_search_sys->hash_index;
1513
index_id = cursor->index->id;
1514
fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_,
1519
rec = btr_cur_get_rec(cursor);
1521
fold = rec_fold(rec, rec_get_offsets(rec, index, offsets_,
1515
1522
ULINT_UNDEFINED, &heap),
1516
block->curr_n_fields, block->curr_n_bytes, index_id);
1523
block->curr_n_fields, block->curr_n_bytes, index->id);
1517
1524
if (UNIV_LIKELY_NULL(heap)) {
1518
1525
mem_heap_free(heap);
1520
1528
rw_lock_x_lock(&btr_search_latch);
1522
found = ha_search_and_delete_if_found(table, fold, rec);
1531
ut_a(block->index == index);
1533
ha_search_and_delete_if_found(table, fold, rec);
1524
1536
rw_lock_x_unlock(&btr_search_latch);
1547
1560
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
1548
1561
#endif /* UNIV_SYNC_DEBUG */
1550
if (!block->is_hashed) {
1563
index = block->index;
1555
ut_a(block->index == cursor->index);
1556
ut_a(!dict_index_is_ibuf(cursor->index));
1570
ut_a(cursor->index == index);
1571
ut_a(!dict_index_is_ibuf(index));
1558
1573
rw_lock_x_lock(&btr_search_latch);
1575
if (!block->index) {
1580
ut_a(block->index == index);
1560
1582
if ((cursor->flag == BTR_CUR_HASH)
1561
1583
&& (cursor->n_fields == block->curr_n_fields)
1562
1584
&& (cursor->n_bytes == block->curr_n_bytes)
1567
1589
ha_search_and_update_if_found(table, cursor->fold, rec,
1568
1590
block, page_rec_get_next(rec));
1570
1593
rw_lock_x_unlock(&btr_search_latch);
1572
1595
rw_lock_x_unlock(&btr_search_latch);
1616
1639
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
1617
1640
#endif /* UNIV_SYNC_DEBUG */
1619
if (!block->is_hashed) {
1642
index = block->index;
1624
ut_a(block->index == cursor->index);
1625
ut_a(!dict_index_is_ibuf(cursor->index));
1627
index_id = cursor->index->id;
1649
ut_a(index == cursor->index);
1650
ut_a(!dict_index_is_ibuf(index));
1629
1652
n_fields = block->curr_n_fields;
1630
1653
n_bytes = block->curr_n_bytes;
1633
1656
ins_rec = page_rec_get_next(rec);
1634
1657
next_rec = page_rec_get_next(ins_rec);
1636
offsets = rec_get_offsets(ins_rec, cursor->index, offsets,
1659
offsets = rec_get_offsets(ins_rec, index, offsets,
1637
1660
ULINT_UNDEFINED, &heap);
1638
ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index_id);
1661
ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index->id);
1640
1663
if (!page_rec_is_supremum(next_rec)) {
1641
offsets = rec_get_offsets(next_rec, cursor->index, offsets,
1664
offsets = rec_get_offsets(next_rec, index, offsets,
1642
1665
n_fields + (n_bytes > 0), &heap);
1643
1666
next_fold = rec_fold(next_rec, offsets, n_fields,
1667
n_bytes, index->id);
1647
1670
if (!page_rec_is_infimum(rec)) {
1648
offsets = rec_get_offsets(rec, cursor->index, offsets,
1671
offsets = rec_get_offsets(rec, index, offsets,
1649
1672
n_fields + (n_bytes > 0), &heap);
1650
fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
1673
fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id);
1652
1675
if (left_side) {
1686
1717
rw_lock_x_lock(&btr_search_latch);
1721
if (!btr_search_enabled) {
1691
1726
ha_insert_for_fold(table, ins_fold, block, ins_rec);
1708
1747
ha_insert_for_fold(table, ins_fold, block, ins_rec);
1710
1749
fputs("Hash insert for ", stderr);
1711
dict_index_name_print(stderr, cursor->index);
1750
dict_index_name_print(stderr, index);
1712
1751
fprintf(stderr, " fold %lu\n", ins_fold);
1811
1851
+ (block->curr_n_bytes > 0),
1814
if (!block->is_hashed || node->fold
1854
if (!block->index || node->fold
1815
1855
!= rec_fold((rec_t*)(node->data),
1817
1857
block->curr_n_fields,
1846
1886
rec_print_new(stderr, (rec_t*)node->data,
1848
1888
fprintf(stderr, "\nInnoDB: on that page."
1849
" Page mem address %p, is hashed %lu,"
1889
" Page mem address %p, is hashed %p,"
1850
1890
" n fields %lu, n bytes %lu\n"
1851
1891
"InnoDB: side %lu\n",
1852
(void*) page, (ulong) block->is_hashed,
1892
(void*) page, (void*) block->index,
1853
1893
(ulong) block->curr_n_fields,
1854
1894
(ulong) block->curr_n_bytes,
1855
1895
(ulong) block->curr_left_side);