~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/btr/btr0sea.c

  • Committer: Monty Taylor
  • Date: 2008-09-15 17:24:04 UTC
  • Revision ID: monty@inaugust.com-20080915172404-ygh6hiyu0q7qpa9x
Removed strndup calls.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
#include "btr0btr.h"
20
20
#include "ha0ha.h"
21
21
 
22
 
/* Flag: has the search system been disabled? */
23
 
UNIV_INTERN ibool               btr_search_disabled     = FALSE;
24
 
 
25
 
/* A dummy variable to fool the compiler */
26
 
UNIV_INTERN ulint               btr_search_this_is_zero = 0;
 
22
ulint   btr_search_this_is_zero = 0;    /* A dummy variable to fool the
 
23
                                        compiler */
27
24
 
28
25
#ifdef UNIV_SEARCH_PERF_STAT
29
 
UNIV_INTERN ulint               btr_search_n_succ       = 0;
30
 
UNIV_INTERN ulint               btr_search_n_hash_fail  = 0;
 
26
ulint   btr_search_n_succ       = 0;
 
27
ulint   btr_search_n_hash_fail  = 0;
31
28
#endif /* UNIV_SEARCH_PERF_STAT */
32
29
 
33
 
/* padding to prevent other memory update
34
 
hotspots from residing on the same memory
35
 
cache line as btr_search_latch */
36
 
UNIV_INTERN byte                btr_sea_pad1[64];
 
30
byte    btr_sea_pad1[64];       /* padding to prevent other memory update
 
31
                                hotspots from residing on the same memory
 
32
                                cache line as btr_search_latch */
37
33
 
38
34
/* The latch protecting the adaptive search system: this latch protects the
39
35
(1) positions of records on those pages where a hash index has been built.
41
37
being updated in-place! We can use fact (1) to perform unique searches to
42
38
indexes. */
43
39
 
44
 
/* We will allocate the latch from dynamic memory to get it to the
45
 
same DRAM page as other hotspot semaphores */
46
 
UNIV_INTERN rw_lock_t*          btr_search_latch_temp;
47
 
 
48
 
/* padding to prevent other memory update hotspots from residing on
49
 
the same memory cache line */
50
 
UNIV_INTERN byte                btr_sea_pad2[64];
51
 
 
52
 
UNIV_INTERN btr_search_sys_t*   btr_search_sys;
 
40
rw_lock_t*      btr_search_latch_temp; /* We will allocate the latch from
 
41
                                        dynamic memory to get it to the
 
42
                                        same DRAM page as other hotspot
 
43
                                        semaphores */
 
44
 
 
45
byte    btr_sea_pad2[64];       /* padding to prevent other memory update
 
46
                                hotspots from residing on the same memory
 
47
                                cache line */
 
48
 
 
49
btr_search_sys_t*       btr_search_sys;
53
50
 
54
51
/* If the number of records on the page divided by this parameter
55
52
would have been successfully accessed using a hash index, the index
73
70
/*=============================*/
74
71
        dict_index_t*   index,  /* in: index for which to build, or NULL if
75
72
                                not known */
76
 
        buf_block_t*    block,  /* in: index page, s- or x-latched */
 
73
        page_t*         page,   /* in: index page, s- or x-latched */
77
74
        ulint           n_fields,/* in: hash this many full fields */
78
75
        ulint           n_bytes,/* in: hash this many bytes from the next
79
76
                                field */
94
91
btr_search_check_free_space_in_heap(void)
95
92
/*=====================================*/
96
93
{
 
94
        buf_frame_t*    frame;
97
95
        hash_table_t*   table;
98
96
        mem_heap_t*     heap;
99
97
 
111
109
        be enough free space in the hash table. */
112
110
 
113
111
        if (heap->free_block == NULL) {
114
 
                buf_block_t*    block = buf_block_alloc(0);
 
112
                frame = buf_frame_alloc();
115
113
 
116
114
                rw_lock_x_lock(&btr_search_latch);
117
115
 
118
116
                if (heap->free_block == NULL) {
119
 
                        heap->free_block = block;
 
117
                        heap->free_block = frame;
120
118
                } else {
121
 
                        buf_block_free(block);
 
119
                        buf_frame_free(frame);
122
120
                }
123
121
 
124
122
                rw_lock_x_unlock(&btr_search_latch);
127
125
 
128
126
/*********************************************************************
129
127
Creates and initializes the adaptive search system at a database start. */
130
 
UNIV_INTERN
 
128
 
131
129
void
132
130
btr_search_sys_create(
133
131
/*==================*/
142
140
 
143
141
        btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
144
142
 
145
 
        btr_search_sys->hash_index = ha_create(hash_size, 0, 0);
146
 
 
147
 
}
148
 
 
149
 
/************************************************************************
150
 
Disable the adaptive hash search system and empty the index. */
151
 
UNIV_INTERN
152
 
void
153
 
btr_search_disable(void)
154
 
/*====================*/
155
 
{
156
 
        btr_search_disabled = TRUE;
157
 
        rw_lock_x_lock(&btr_search_latch);
158
 
 
159
 
        ha_clear(btr_search_sys->hash_index);
160
 
 
161
 
        rw_lock_x_unlock(&btr_search_latch);
162
 
}
163
 
 
164
 
/************************************************************************
165
 
Enable the adaptive hash search system. */
166
 
UNIV_INTERN
167
 
void
168
 
btr_search_enable(void)
169
 
/*====================*/
170
 
{
171
 
        btr_search_disabled = FALSE;
 
143
        btr_search_sys->hash_index = ha_create(TRUE, hash_size, 0, 0);
 
144
 
172
145
}
173
146
 
174
147
/*********************************************************************
175
148
Creates and initializes a search info struct. */
176
 
UNIV_INTERN
 
149
 
177
150
btr_search_t*
178
151
btr_search_info_create(
179
152
/*===================*/
233
206
 
234
207
        index = cursor->index;
235
208
 
236
 
        if (dict_index_is_ibuf(index)) {
 
209
        if (index->type & DICT_IBUF) {
237
210
                /* So many deletes are performed on an insert buffer tree
238
211
                that we do not consider a hash index useful on it: */
239
212
 
349
322
#ifdef UNIV_SYNC_DEBUG
350
323
        ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
351
324
        ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
352
 
        ut_ad(rw_lock_own(&block->lock, RW_LOCK_SHARED)
353
 
              || rw_lock_own(&block->lock, RW_LOCK_EX));
 
325
        ut_ad(rw_lock_own(&((buf_block_t*) block)->lock, RW_LOCK_SHARED)
 
326
              || rw_lock_own(&((buf_block_t*) block)->lock, RW_LOCK_EX));
354
327
#endif /* UNIV_SYNC_DEBUG */
355
328
        ut_ad(cursor);
356
329
 
357
330
        info->last_hash_succ = FALSE;
358
331
 
359
 
        ut_a(buf_block_state_valid(block));
 
332
        ut_a(block->magic_n == BUF_BLOCK_MAGIC_N);
360
333
        ut_ad(info->magic_n == BTR_SEARCH_MAGIC_N);
361
334
 
362
335
        if ((block->n_hash_helps > 0)
436
409
        ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
437
410
              || rw_lock_own(&(block->lock), RW_LOCK_EX));
438
411
#endif /* UNIV_SYNC_DEBUG */
439
 
        ut_ad(page_align(btr_cur_get_rec(cursor))
440
 
              == buf_block_get_frame(block));
441
 
 
442
 
        if (!block->is_hashed) {
443
 
 
444
 
                return;
445
 
        }
446
 
 
447
 
        ut_a(block->index == cursor->index);
448
 
        ut_a(!dict_index_is_ibuf(cursor->index));
449
 
 
450
 
        if ((info->n_hash_potential > 0)
 
412
        ut_ad(buf_block_align(btr_cur_get_rec(cursor)) == block);
 
413
        ut_a(!block->is_hashed || block->index == cursor->index);
 
414
 
 
415
        if (block->is_hashed
 
416
            && (info->n_hash_potential > 0)
451
417
            && (block->curr_n_fields == info->n_fields)
452
418
            && (block->curr_n_bytes == info->n_bytes)
453
419
            && (block->curr_left_side == info->left_side)) {
454
420
                mem_heap_t*     heap            = NULL;
455
421
                ulint           offsets_[REC_OFFS_NORMAL_SIZE];
456
 
                rec_offs_init(offsets_);
 
422
                *offsets_ = (sizeof offsets_) / sizeof *offsets_;
457
423
 
458
424
                rec = btr_cur_get_rec(cursor);
459
425
 
475
441
                ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
476
442
#endif /* UNIV_SYNC_DEBUG */
477
443
 
478
 
                ha_insert_for_fold(btr_search_sys->hash_index, fold,
479
 
                                   block, rec);
 
444
                ha_insert_for_fold(btr_search_sys->hash_index, fold, rec);
480
445
        }
481
446
}
482
447
 
483
448
/*************************************************************************
484
449
Updates the search info. */
485
 
UNIV_INTERN
 
450
 
486
451
void
487
452
btr_search_info_update_slow(
488
453
/*========================*/
499
464
        ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
500
465
#endif /* UNIV_SYNC_DEBUG */
501
466
 
502
 
        block = btr_cur_get_block(cursor);
 
467
        block = buf_block_align(btr_cur_get_rec(cursor));
503
468
 
504
469
        /* NOTE that the following two function calls do NOT protect
505
470
        info or block->n_fields etc. with any semaphore, to save CPU time!
549
514
                params2 = params + btr_search_this_is_zero;
550
515
 
551
516
                btr_search_build_page_hash_index(cursor->index,
552
 
                                                 block,
 
517
                                                 block->frame,
553
518
                                                 params2[0],
554
519
                                                 params2[1],
555
520
                                                 params2[2]);
575
540
                                protected, not the next or previous record
576
541
                                in the chain: we cannot look at the next or
577
542
                                previous record to check our guess! */
578
 
        const dtuple_t* tuple,  /* in: data tuple */
 
543
        dtuple_t*       tuple,  /* in: data tuple */
579
544
        ulint           mode,   /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
580
545
                                or PAGE_CUR_GE */
581
546
        mtr_t*          mtr)    /* in: mtr */
589
554
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
590
555
        ulint*          offsets         = offsets_;
591
556
        ibool           success         = FALSE;
592
 
        rec_offs_init(offsets_);
 
557
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
593
558
 
594
559
        n_unique = dict_index_get_n_unique_in_tree(cursor->index);
595
560
 
650
615
                prev_rec = page_rec_get_prev(rec);
651
616
 
652
617
                if (page_rec_is_infimum(prev_rec)) {
653
 
                        success = btr_page_get_prev(page_align(prev_rec), mtr)
654
 
                                == FIL_NULL;
 
618
                        success = btr_page_get_prev(
 
619
                                buf_frame_align(prev_rec), mtr) == FIL_NULL;
655
620
 
656
621
                        goto exit_func;
657
622
                }
675
640
                next_rec = page_rec_get_next(rec);
676
641
 
677
642
                if (page_rec_is_supremum(next_rec)) {
678
 
                        if (btr_page_get_next(page_align(next_rec), mtr)
 
643
                        if (btr_page_get_next(
 
644
                                    buf_frame_align(next_rec), mtr)
679
645
                            == FIL_NULL) {
680
646
 
681
647
                                cursor->up_match = 0;
708
674
of the index. Note that if mode is PAGE_CUR_LE, which is used in inserts,
709
675
and the function returns TRUE, then cursor->up_match and cursor->low_match
710
676
both have sensible values. */
711
 
UNIV_INTERN
 
677
 
712
678
ibool
713
679
btr_search_guess_on_hash(
714
680
/*=====================*/
715
681
                                        /* out: TRUE if succeeded */
716
682
        dict_index_t*   index,          /* in: index */
717
683
        btr_search_t*   info,           /* in: index search info */
718
 
        const dtuple_t* tuple,          /* in: logical record */
 
684
        dtuple_t*       tuple,          /* in: logical record */
719
685
        ulint           mode,           /* in: PAGE_CUR_L, ... */
720
686
        ulint           latch_mode,     /* in: BTR_SEARCH_LEAF, ...;
721
687
                                        NOTE that only if has_search_latch
731
697
{
732
698
        buf_block_t*    block;
733
699
        rec_t*          rec;
734
 
        const page_t*   page;
 
700
        page_t*         page;
735
701
        ulint           fold;
 
702
        ulint           tuple_n_fields;
736
703
        dulint          index_id;
 
704
        ibool           can_only_compare_to_cursor_rec = TRUE;
737
705
#ifdef notdefined
738
706
        btr_cur_t       cursor2;
739
707
        btr_pcur_t      pcur;
753
721
        cursor->n_fields = info->n_fields;
754
722
        cursor->n_bytes = info->n_bytes;
755
723
 
756
 
        if (UNIV_UNLIKELY(dtuple_get_n_fields(tuple)
757
 
                          < cursor->n_fields + (cursor->n_bytes > 0))) {
 
724
        tuple_n_fields = dtuple_get_n_fields(tuple);
 
725
 
 
726
        if (UNIV_UNLIKELY(tuple_n_fields < cursor->n_fields)) {
 
727
 
 
728
                return(FALSE);
 
729
        }
 
730
 
 
731
        if (UNIV_UNLIKELY(tuple_n_fields == cursor->n_fields)
 
732
            && (cursor->n_bytes > 0)) {
758
733
 
759
734
                return(FALSE);
760
735
        }
782
757
                goto failure_unlock;
783
758
        }
784
759
 
785
 
        page = page_align(rec);
786
 
        {
787
 
                ulint   page_no         = page_get_page_no(page);
788
 
                ulint   space_id        = page_get_space_id(page);
789
 
 
790
 
                buf_pool_mutex_enter();
791
 
                block = (buf_block_t*) buf_page_hash_get(space_id, page_no);
792
 
                buf_pool_mutex_exit();
793
 
        }
794
 
 
795
 
        if (UNIV_UNLIKELY(!block)
796
 
            || UNIV_UNLIKELY(buf_block_get_state(block)
797
 
                             != BUF_BLOCK_FILE_PAGE)) {
798
 
 
799
 
                /* The block is most probably being freed.
800
 
                The function buf_LRU_search_and_free_block()
801
 
                first removes the block from buf_pool->page_hash
802
 
                by calling buf_LRU_block_remove_hashed_page().
803
 
                After that, it invokes btr_search_drop_page_hash_index().
804
 
                Let us pretend that the block was also removed from
805
 
                the adaptive hash index. */
806
 
                goto failure_unlock;
807
 
        }
 
760
        page = buf_frame_align(rec);
808
761
 
809
762
        if (UNIV_LIKELY(!has_search_latch)) {
810
763
 
811
764
                if (UNIV_UNLIKELY(
812
 
                            !buf_page_get_known_nowait(latch_mode, block,
 
765
                            !buf_page_get_known_nowait(latch_mode, page,
813
766
                                                       BUF_MAKE_YOUNG,
814
767
                                                       __FILE__, __LINE__,
815
768
                                                       mtr))) {
817
770
                }
818
771
 
819
772
                rw_lock_s_unlock(&btr_search_latch);
 
773
                can_only_compare_to_cursor_rec = FALSE;
820
774
 
821
775
#ifdef UNIV_SYNC_DEBUG
822
 
                buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
 
776
                buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH);
823
777
#endif /* UNIV_SYNC_DEBUG */
824
778
        }
825
779
 
826
 
        if (UNIV_UNLIKELY(buf_block_get_state(block)
827
 
                          == BUF_BLOCK_REMOVE_HASH)) {
 
780
        block = buf_block_align(page);
 
781
 
 
782
        if (UNIV_UNLIKELY(block->state == BUF_BLOCK_REMOVE_HASH)) {
828
783
                if (UNIV_LIKELY(!has_search_latch)) {
829
784
 
830
 
                        btr_leaf_page_release(block, latch_mode, mtr);
 
785
                        btr_leaf_page_release(page, latch_mode, mtr);
831
786
                }
832
787
 
833
788
                goto failure;
834
789
        }
835
790
 
836
 
        ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
 
791
        ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
837
792
        ut_ad(page_rec_is_user_rec(rec));
838
793
 
839
 
        btr_cur_position(index, rec, block, cursor);
 
794
        btr_cur_position(index, rec, cursor);
840
795
 
841
796
        /* Check the validity of the guess within the page */
842
797
 
848
803
        if (UNIV_EXPECT(
849
804
                    ut_dulint_cmp(index_id, btr_page_get_index_id(page)), 0)
850
805
            || !btr_search_check_guess(cursor,
851
 
                                       has_search_latch,
 
806
                                       can_only_compare_to_cursor_rec,
852
807
                                       tuple, mode, mtr)) {
853
808
                if (UNIV_LIKELY(!has_search_latch)) {
854
 
                        btr_leaf_page_release(block, latch_mode, mtr);
 
809
                        btr_leaf_page_release(page, latch_mode, mtr);
855
810
                }
856
811
 
857
812
                goto failure;
871
826
        /* Currently, does not work if the following fails: */
872
827
        ut_ad(!has_search_latch);
873
828
 
874
 
        btr_leaf_page_release(block, latch_mode, mtr);
 
829
        btr_leaf_page_release(page, latch_mode, mtr);
875
830
 
876
831
        btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
877
832
                                    &cursor2, 0, mtr);
901
856
        btr_search_n_succ++;
902
857
#endif
903
858
        if (UNIV_LIKELY(!has_search_latch)
904
 
            && buf_page_peek_if_too_old(&block->page)) {
 
859
            && buf_block_peek_if_too_old(block)) {
905
860
 
906
 
                buf_page_make_young(&block->page);
 
861
                buf_page_make_young(page);
907
862
        }
908
863
 
909
864
        /* Increment the page get statistics though we did not really
935
890
 
936
891
/************************************************************************
937
892
Drops a page hash index. */
938
 
UNIV_INTERN
 
893
 
939
894
void
940
895
btr_search_drop_page_hash_index(
941
896
/*============================*/
942
 
        buf_block_t*    block)  /* in: block containing index page,
943
 
                                s- or x-latched, or an index page
944
 
                                for which we know that
945
 
                                block->buf_fix_count == 0 */
 
897
        page_t* page)   /* in: index page, s- or x-latched, or an index page
 
898
                        for which we know that block->buf_fix_count == 0 */
946
899
{
947
900
        hash_table_t*   table;
 
901
        buf_block_t*    block;
948
902
        ulint           n_fields;
949
903
        ulint           n_bytes;
950
 
        page_t*         page;
951
904
        rec_t*          rec;
952
905
        ulint           fold;
953
906
        ulint           prev_fold;
964
917
        ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
965
918
        ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
966
919
#endif /* UNIV_SYNC_DEBUG */
967
 
 
968
920
retry:
969
921
        rw_lock_s_lock(&btr_search_latch);
970
 
        page = block->frame;
 
922
 
 
923
        block = buf_block_align(page);
971
924
 
972
925
        if (UNIV_LIKELY(!block->is_hashed)) {
973
926
 
981
934
#ifdef UNIV_SYNC_DEBUG
982
935
        ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
983
936
              || rw_lock_own(&(block->lock), RW_LOCK_EX)
984
 
              || (block->page.buf_fix_count == 0));
 
937
              || (block->buf_fix_count == 0));
985
938
#endif /* UNIV_SYNC_DEBUG */
986
939
 
987
940
        n_fields = block->curr_n_fields;
988
941
        n_bytes = block->curr_n_bytes;
989
942
        index = block->index;
990
 
        ut_a(!dict_index_is_ibuf(index));
991
943
 
992
944
        /* NOTE: The fields of block must not be accessed after
993
945
        releasing btr_search_latch, as the index page might only
1073
1025
        block->is_hashed = FALSE;
1074
1026
        block->index = NULL;
1075
1027
cleanup:
1076
 
#ifdef UNIV_DEBUG
1077
1028
        if (UNIV_UNLIKELY(block->n_pointers)) {
1078
1029
                /* Corruption */
1079
1030
                ut_print_timestamp(stderr);
1089
1040
        } else {
1090
1041
                rw_lock_x_unlock(&btr_search_latch);
1091
1042
        }
1092
 
#else /* UNIV_DEBUG */
1093
 
        rw_lock_x_unlock(&btr_search_latch);
1094
 
#endif /* UNIV_DEBUG */
1095
1043
 
1096
1044
        mem_free(folds);
1097
1045
}
1099
1047
/************************************************************************
1100
1048
Drops a page hash index when a page is freed from a fseg to the file system.
1101
1049
Drops possible hash index if the page happens to be in the buffer pool. */
1102
 
UNIV_INTERN
 
1050
 
1103
1051
void
1104
1052
btr_search_drop_page_hash_when_freed(
1105
1053
/*=================================*/
1106
1054
        ulint   space,          /* in: space id */
1107
 
        ulint   zip_size,       /* in: compressed page size in bytes
1108
 
                                or 0 for uncompressed pages */
1109
1055
        ulint   page_no)        /* in: page number */
1110
1056
{
1111
 
        buf_block_t*    block;
1112
 
        mtr_t           mtr;
1113
 
 
1114
 
        if (!buf_page_peek_if_search_hashed(space, page_no)) {
 
1057
        ibool   is_hashed;
 
1058
        page_t* page;
 
1059
        mtr_t   mtr;
 
1060
 
 
1061
        is_hashed = buf_page_peek_if_search_hashed(space, page_no);
 
1062
 
 
1063
        if (!is_hashed) {
1115
1064
 
1116
1065
                return;
1117
1066
        }
1123
1072
        get here. Therefore we can acquire the s-latch to the page without
1124
1073
        having to fear a deadlock. */
1125
1074
 
1126
 
        block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH, NULL,
 
1075
        page = buf_page_get_gen(space, page_no, RW_S_LATCH, NULL,
1127
1076
                                BUF_GET_IF_IN_POOL, __FILE__, __LINE__,
1128
1077
                                &mtr);
1129
1078
 
1130
1079
#ifdef UNIV_SYNC_DEBUG
1131
 
        buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
 
1080
        buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH);
1132
1081
#endif /* UNIV_SYNC_DEBUG */
1133
1082
 
1134
 
        btr_search_drop_page_hash_index(block);
 
1083
        btr_search_drop_page_hash_index(page);
1135
1084
 
1136
1085
        mtr_commit(&mtr);
1137
1086
}
1146
1095
btr_search_build_page_hash_index(
1147
1096
/*=============================*/
1148
1097
        dict_index_t*   index,  /* in: index for which to build */
1149
 
        buf_block_t*    block,  /* in: index page, s- or x-latched */
 
1098
        page_t*         page,   /* in: index page, s- or x-latched */
1150
1099
        ulint           n_fields,/* in: hash this many full fields */
1151
1100
        ulint           n_bytes,/* in: hash this many bytes from the next
1152
1101
                                field */
1153
1102
        ibool           left_side)/* in: hash for searches from left side? */
1154
1103
{
1155
1104
        hash_table_t*   table;
1156
 
        page_t*         page;
 
1105
        buf_block_t*    block;
1157
1106
        rec_t*          rec;
1158
1107
        rec_t*          next_rec;
1159
1108
        ulint           fold;
1167
1116
        mem_heap_t*     heap            = NULL;
1168
1117
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1169
1118
        ulint*          offsets         = offsets_;
1170
 
        rec_offs_init(offsets_);
 
1119
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
1171
1120
 
1172
1121
        ut_ad(index);
1173
 
        ut_a(!dict_index_is_ibuf(index));
1174
1122
 
 
1123
        block = buf_block_align(page);
1175
1124
        table = btr_search_sys->hash_index;
1176
 
        page = buf_block_get_frame(block);
1177
1125
 
1178
1126
#ifdef UNIV_SYNC_DEBUG
1179
1127
        ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1189
1137
 
1190
1138
                rw_lock_s_unlock(&btr_search_latch);
1191
1139
 
1192
 
                btr_search_drop_page_hash_index(block);
 
1140
                btr_search_drop_page_hash_index(page);
1193
1141
        } else {
1194
1142
                rw_lock_s_unlock(&btr_search_latch);
1195
1143
        }
1224
1172
 
1225
1173
        index_id = btr_page_get_index_id(page);
1226
1174
 
1227
 
        rec = page_rec_get_next(page_get_infimum_rec(page));
 
1175
        rec = page_get_infimum_rec(page);
 
1176
        rec = page_rec_get_next(rec);
1228
1177
 
1229
1178
        offsets = rec_get_offsets(rec, index, offsets,
1230
1179
                                  n_fields + (n_bytes > 0), &heap);
1305
1254
 
1306
1255
        for (i = 0; i < n_cached; i++) {
1307
1256
 
1308
 
                ha_insert_for_fold(table, folds[i], block, recs[i]);
 
1257
                ha_insert_for_fold(table, folds[i], recs[i]);
1309
1258
        }
1310
1259
 
1311
1260
exit_func:
1323
1272
then the hash index for page, if any, is dropped. If new_page is not hashed,
1324
1273
and page is hashed, then a new hash index is built to new_page with the same
1325
1274
parameters as page (this often happens when a page is split). */
1326
 
UNIV_INTERN
 
1275
 
1327
1276
void
1328
1277
btr_search_move_or_delete_hash_entries(
1329
1278
/*===================================*/
1330
 
        buf_block_t*    new_block,      /* in: records are copied
 
1279
        page_t*         new_page,       /* in: records are copied
1331
1280
                                        to this page */
1332
 
        buf_block_t*    block,          /* in: index page from which
 
1281
        page_t*         page,           /* in: index page from which
1333
1282
                                        records were copied, and the
1334
1283
                                        copied records will be deleted
1335
1284
                                        from this page */
1336
1285
        dict_index_t*   index)          /* in: record descriptor */
1337
1286
{
1338
 
        ulint   n_fields;
1339
 
        ulint   n_bytes;
1340
 
        ibool   left_side;
 
1287
        buf_block_t*    block;
 
1288
        buf_block_t*    new_block;
 
1289
        ulint           n_fields;
 
1290
        ulint           n_bytes;
 
1291
        ibool           left_side;
 
1292
 
 
1293
        block = buf_block_align(page);
 
1294
        new_block = buf_block_align(new_page);
 
1295
        ut_a(page_is_comp(page) == page_is_comp(new_page));
1341
1296
 
1342
1297
#ifdef UNIV_SYNC_DEBUG
1343
1298
        ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
1345
1300
#endif /* UNIV_SYNC_DEBUG */
1346
1301
        ut_a(!new_block->is_hashed || new_block->index == index);
1347
1302
        ut_a(!block->is_hashed || block->index == index);
1348
 
        ut_a(!(new_block->is_hashed || block->is_hashed)
1349
 
             || !dict_index_is_ibuf(index));
1350
1303
 
1351
1304
        rw_lock_s_lock(&btr_search_latch);
1352
1305
 
1354
1307
 
1355
1308
                rw_lock_s_unlock(&btr_search_latch);
1356
1309
 
1357
 
                btr_search_drop_page_hash_index(block);
 
1310
                btr_search_drop_page_hash_index(page);
1358
1311
 
1359
1312
                return;
1360
1313
        }
1373
1326
 
1374
1327
                ut_a(n_fields + n_bytes > 0);
1375
1328
 
1376
 
                btr_search_build_page_hash_index(index, new_block, n_fields,
 
1329
                btr_search_build_page_hash_index(index, new_page, n_fields,
1377
1330
                                                 n_bytes, left_side);
1378
 
                ut_ad(n_fields == block->curr_n_fields);
1379
 
                ut_ad(n_bytes == block->curr_n_bytes);
1380
 
                ut_ad(left_side == block->curr_left_side);
 
1331
#if 1 /* TODO: safe to remove? */
 
1332
                ut_a(n_fields == block->curr_n_fields);
 
1333
                ut_a(n_bytes == block->curr_n_bytes);
 
1334
                ut_a(left_side == block->curr_left_side);
 
1335
#endif
1381
1336
                return;
1382
1337
        }
1383
1338
 
1386
1341
 
1387
1342
/************************************************************************
1388
1343
Updates the page hash index when a single record is deleted from a page. */
1389
 
UNIV_INTERN
 
1344
 
1390
1345
void
1391
1346
btr_search_update_hash_on_delete(
1392
1347
/*=============================*/
1402
1357
        ibool           found;
1403
1358
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1404
1359
        mem_heap_t*     heap            = NULL;
1405
 
        rec_offs_init(offsets_);
 
1360
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
1406
1361
 
1407
1362
        rec = btr_cur_get_rec(cursor);
1408
1363
 
1409
 
        block = btr_cur_get_block(cursor);
 
1364
        block = buf_block_align(rec);
1410
1365
 
1411
1366
#ifdef UNIV_SYNC_DEBUG
1412
1367
        ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
1419
1374
 
1420
1375
        ut_a(block->index == cursor->index);
1421
1376
        ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
1422
 
        ut_a(!dict_index_is_ibuf(cursor->index));
1423
1377
 
1424
1378
        table = btr_search_sys->hash_index;
1425
1379
 
1439
1393
 
1440
1394
/************************************************************************
1441
1395
Updates the page hash index when a single record is inserted on a page. */
1442
 
UNIV_INTERN
 
1396
 
1443
1397
void
1444
1398
btr_search_update_hash_node_on_insert(
1445
1399
/*==================================*/
1454
1408
 
1455
1409
        rec = btr_cur_get_rec(cursor);
1456
1410
 
1457
 
        block = btr_cur_get_block(cursor);
 
1411
        block = buf_block_align(rec);
1458
1412
 
1459
1413
#ifdef UNIV_SYNC_DEBUG
1460
1414
        ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
1466
1420
        }
1467
1421
 
1468
1422
        ut_a(block->index == cursor->index);
1469
 
        ut_a(!dict_index_is_ibuf(cursor->index));
1470
1423
 
1471
1424
        rw_lock_x_lock(&btr_search_latch);
1472
1425
 
1478
1431
                table = btr_search_sys->hash_index;
1479
1432
 
1480
1433
                ha_search_and_update_if_found(table, cursor->fold, rec,
1481
 
                                              block, page_rec_get_next(rec));
 
1434
                                              page_rec_get_next(rec));
1482
1435
 
1483
1436
                rw_lock_x_unlock(&btr_search_latch);
1484
1437
        } else {
1490
1443
 
1491
1444
/************************************************************************
1492
1445
Updates the page hash index when a single record is inserted on a page. */
1493
 
UNIV_INTERN
 
1446
 
1494
1447
void
1495
1448
btr_search_update_hash_on_insert(
1496
1449
/*=============================*/
1515
1468
        mem_heap_t*     heap            = NULL;
1516
1469
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
1517
1470
        ulint*          offsets         = offsets_;
1518
 
        rec_offs_init(offsets_);
 
1471
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
1519
1472
 
1520
1473
        table = btr_search_sys->hash_index;
1521
1474
 
1523
1476
 
1524
1477
        rec = btr_cur_get_rec(cursor);
1525
1478
 
1526
 
        block = btr_cur_get_block(cursor);
 
1479
        block = buf_block_align(rec);
1527
1480
 
1528
1481
#ifdef UNIV_SYNC_DEBUG
1529
1482
        ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
1535
1488
        }
1536
1489
 
1537
1490
        ut_a(block->index == cursor->index);
1538
 
        ut_a(!dict_index_is_ibuf(cursor->index));
1539
1491
 
1540
1492
        index_id = cursor->index->id;
1541
1493
 
1568
1520
 
1569
1521
                        locked = TRUE;
1570
1522
 
1571
 
                        ha_insert_for_fold(table, ins_fold, block, ins_rec);
 
1523
                        ha_insert_for_fold(table, ins_fold, ins_rec);
1572
1524
                }
1573
1525
 
1574
1526
                goto check_next_rec;
1584
1536
                }
1585
1537
 
1586
1538
                if (!left_side) {
1587
 
                        ha_insert_for_fold(table, fold, block, rec);
 
1539
                        ha_insert_for_fold(table, fold, rec);
1588
1540
                } else {
1589
 
                        ha_insert_for_fold(table, ins_fold, block, ins_rec);
 
1541
                        ha_insert_for_fold(table, ins_fold, ins_rec);
1590
1542
                }
1591
1543
        }
1592
1544
 
1601
1553
                                locked = TRUE;
1602
1554
                        }
1603
1555
 
1604
 
                        ha_insert_for_fold(table, ins_fold, block, ins_rec);
 
1556
                        ha_insert_for_fold(table, ins_fold, ins_rec);
1605
1557
                }
1606
1558
 
1607
1559
                goto function_exit;
1618
1570
 
1619
1571
                if (!left_side) {
1620
1572
 
1621
 
                        ha_insert_for_fold(table, ins_fold, block, ins_rec);
 
1573
                        ha_insert_for_fold(table, ins_fold, ins_rec);
1622
1574
                        /*
1623
1575
                        fputs("Hash insert for ", stderr);
1624
1576
                        dict_index_name_print(stderr, cursor->index);
1625
1577
                        fprintf(stderr, " fold %lu\n", ins_fold);
1626
1578
                        */
1627
1579
                } else {
1628
 
                        ha_insert_for_fold(table, next_fold, block, next_rec);
 
1580
                        ha_insert_for_fold(table, next_fold, next_rec);
1629
1581
                }
1630
1582
        }
1631
1583
 
1640
1592
 
1641
1593
/************************************************************************
1642
1594
Validates the search system. */
1643
 
UNIV_INTERN
 
1595
 
1644
1596
ibool
1645
1597
btr_search_validate(void)
1646
1598
/*=====================*/
1647
1599
                                /* out: TRUE if ok */
1648
1600
{
 
1601
        buf_block_t*    block;
1649
1602
        page_t*         page;
1650
1603
        ha_node_t*      node;
1651
1604
        ulint           n_page_dumps    = 0;
1660
1613
        btr_search_latch. */
1661
1614
        ulint           chunk_size = 10000;
1662
1615
 
1663
 
        rec_offs_init(offsets_);
 
1616
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
1664
1617
 
1665
1618
        rw_lock_x_lock(&btr_search_latch);
1666
 
        buf_pool_mutex_enter();
1667
1619
 
1668
1620
        cell_count = hash_get_n_cells(btr_search_sys->hash_index);
1669
1621
 
1671
1623
                /* We release btr_search_latch every once in a while to
1672
1624
                give other queries a chance to run. */
1673
1625
                if ((i != 0) && ((i % chunk_size) == 0)) {
1674
 
                        buf_pool_mutex_exit();
1675
1626
                        rw_lock_x_unlock(&btr_search_latch);
1676
1627
                        os_thread_yield();
1677
1628
                        rw_lock_x_lock(&btr_search_latch);
1678
 
                        buf_pool_mutex_enter();
1679
1629
                }
1680
1630
 
1681
1631
                node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
1682
1632
 
1683
 
                for (; node != NULL; node = node->next) {
1684
 
                        const buf_block_t*      block;
1685
 
 
1686
 
                        page = page_align(node->data);
1687
 
                        {
1688
 
                                ulint   page_no = page_get_page_no(page);
1689
 
                                ulint   space_id= page_get_space_id(page);
1690
 
 
1691
 
                                block = buf_block_hash_get(space_id, page_no);
1692
 
                        }
1693
 
 
1694
 
                        if (UNIV_UNLIKELY(!block)) {
1695
 
 
1696
 
                                /* The block is most probably being freed.
1697
 
                                The function buf_LRU_search_and_free_block()
1698
 
                                first removes the block from
1699
 
                                buf_pool->page_hash by calling
1700
 
                                buf_LRU_block_remove_hashed_page().
1701
 
                                After that, it invokes
1702
 
                                btr_search_drop_page_hash_index().
1703
 
                                Let us pretend that the block was also removed
1704
 
                                from the adaptive hash index. */
1705
 
                                continue;
1706
 
                        }
1707
 
 
1708
 
                        ut_a(!dict_index_is_ibuf(block->index));
1709
 
 
1710
 
                        offsets = rec_get_offsets((const rec_t*) node->data,
 
1633
                while (node != NULL) {
 
1634
                        block = buf_block_align(node->data);
 
1635
                        page = buf_frame_align(node->data);
 
1636
                        offsets = rec_get_offsets((rec_t*) node->data,
1711
1637
                                                  block->index, offsets,
1712
1638
                                                  block->curr_n_fields
1713
1639
                                                  + (block->curr_n_bytes > 0),
1728
1654
                                        "InnoDB: ptr mem address %p"
1729
1655
                                        " index id %lu %lu,"
1730
1656
                                        " node fold %lu, rec fold %lu\n",
1731
 
                                        (ulong) page_get_page_no(page),
 
1657
                                        (ulong) buf_frame_get_page_no(page),
1732
1658
                                        node->data,
1733
1659
                                        (ulong) ut_dulint_get_high(
1734
1660
                                                btr_page_get_index_id(page)),
1755
1681
                                        (ulong) block->curr_left_side);
1756
1682
 
1757
1683
                                if (n_page_dumps < 20) {
1758
 
                                        buf_page_print(page, 0);
 
1684
                                        buf_page_print(page);
1759
1685
                                        n_page_dumps++;
1760
1686
                                }
1761
1687
                        }
 
1688
 
 
1689
                        node = node->next;
1762
1690
                }
1763
1691
        }
1764
1692
 
1768
1696
                /* We release btr_search_latch every once in a while to
1769
1697
                give other queries a chance to run. */
1770
1698
                if (i != 0) {
1771
 
                        buf_pool_mutex_exit();
1772
1699
                        rw_lock_x_unlock(&btr_search_latch);
1773
1700
                        os_thread_yield();
1774
1701
                        rw_lock_x_lock(&btr_search_latch);
1775
 
                        buf_pool_mutex_enter();
1776
1702
                }
1777
1703
 
1778
1704
                if (!ha_validate(btr_search_sys->hash_index, i, end_index)) {
1780
1706
                }
1781
1707
        }
1782
1708
 
1783
 
        buf_pool_mutex_exit();
1784
1709
        rw_lock_x_unlock(&btr_search_latch);
1785
1710
        if (UNIV_LIKELY_NULL(heap)) {
1786
1711
                mem_heap_free(heap);