1/*****************************************************************************
2
3Copyright (c) 1996, 2019, Oracle and/or its affiliates. All Rights Reserved.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is also distributed with certain software (including but not
10limited to OpenSSL) that is licensed under separate terms, as designated in a
11particular file or component or in included license documentation. The authors
12of MySQL hereby grant you an additional permission to link the program and
13your derivative works with the separately licensed software that they have
14included with MySQL.
15
16This program is distributed in the hope that it will be useful, but WITHOUT
17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
19for more details.
20
21You should have received a copy of the GNU General Public License along with
22this program; if not, write to the Free Software Foundation, Inc.,
2351 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24
25*****************************************************************************/
26
27/** @file include/btr0sea.ic
28 The index tree adaptive search
29
30 Created 2/17/1996 Heikki Tuuri
31 *************************************************************************/
32
33#include "btr0cur.h"
34#include "buf0buf.h"
35#include "dict0mem.h"
36
37/** Updates the search info. */
38void btr_search_info_update_slow(
39    btr_search_t *info, /*!< in/out: search info */
40    btr_cur_t *cursor); /*!< in: cursor which was just positioned */
41
42/** Returns search info for an index.
43 @return search info; search mutex reserved */
44UNIV_INLINE
45const btr_search_t *btr_search_get_info(
46    const dict_index_t *index) /*!< in: index */
47{
48  return (index->search_info);
49}
50
51/** Returns search info for an index.
52 @return search info; search mutex reserved */
53UNIV_INLINE
54btr_search_t *btr_search_get_info(dict_index_t *index) /*!< in: index */
55{
56  return (index->search_info);
57}
58
59/** Updates the search info. */
60UNIV_INLINE
61void btr_search_info_update(
62    dict_index_t *index, /*!< in: index of the cursor */
63    btr_cur_t *cursor)   /*!< in: cursor which was just positioned */
64{
65  ut_ad(!rw_lock_own(btr_get_search_latch(index), RW_LOCK_S));
66  ut_ad(!rw_lock_own(btr_get_search_latch(index), RW_LOCK_X));
67
68  if (dict_index_is_spatial(index) || !btr_search_enabled) {
69    return;
70  }
71
72  btr_search_t *info;
73  info = btr_search_get_info(index);
74
75  info->hash_analysis++;
76
77  if (info->hash_analysis < BTR_SEARCH_HASH_ANALYSIS) {
78    /* Do nothing */
79
80    return;
81  }
82
83  ut_ad(cursor->flag != BTR_CUR_HASH);
84
85  btr_search_info_update_slow(info, cursor);
86}
87
88/** X-Lock the search latch (corresponding to given index)
89@param[in]	index	index handler */
90UNIV_INLINE
91void btr_search_x_lock(const dict_index_t *index) {
92  rw_lock_x_lock(btr_get_search_latch(index));
93}
94
95/** X-Unlock the search latch (corresponding to given index)
96@param[in]	index	index handler */
97UNIV_INLINE
98void btr_search_x_unlock(const dict_index_t *index) {
99  rw_lock_x_unlock(btr_get_search_latch(index));
100}
101
102/** Lock all search latches in exclusive mode. */
103UNIV_INLINE
104void btr_search_x_lock_all() {
105  for (ulint i = 0; i < btr_ahi_parts; ++i) {
106    rw_lock_x_lock(btr_search_latches[i]);
107  }
108}
109
110/** Unlock all search latches from exclusive mode. */
111UNIV_INLINE
112void btr_search_x_unlock_all() {
113  for (ulint i = 0; i < btr_ahi_parts; ++i) {
114    rw_lock_x_unlock(btr_search_latches[i]);
115  }
116}
117
118/** S-Lock the search latch (corresponding to given index)
119@param[in]	index	index handler */
120UNIV_INLINE
121void btr_search_s_lock(const dict_index_t *index) {
122  rw_lock_s_lock(btr_get_search_latch(index));
123}
124
125/** S-Unlock the search latch (corresponding to given index)
126@param[in]	index	index handler */
127UNIV_INLINE
128void btr_search_s_unlock(const dict_index_t *index) {
129  rw_lock_s_unlock(btr_get_search_latch(index));
130}
131
132/** Lock all search latches in shared mode. */
133UNIV_INLINE
134void btr_search_s_lock_all() {
135  for (ulint i = 0; i < btr_ahi_parts; ++i) {
136    rw_lock_s_lock(btr_search_latches[i]);
137  }
138}
139
140/** Unlock all search latches from shared mode. */
141UNIV_INLINE
142void btr_search_s_unlock_all() {
143  for (ulint i = 0; i < btr_ahi_parts; ++i) {
144    rw_lock_s_unlock(btr_search_latches[i]);
145  }
146}
147
148#ifdef UNIV_DEBUG
149/** Check if thread owns all the search latches.
150@param[in]	mode	lock mode check
151@retval true if owns all of them
152@retval false if does not own some of them */
153UNIV_INLINE
154bool btr_search_own_all(ulint mode) {
155  for (ulint i = 0; i < btr_ahi_parts; ++i) {
156    if (!rw_lock_own(btr_search_latches[i], mode)) {
157      return (false);
158    }
159  }
160  return (true);
161}
162
163/** Check if thread owns any of the search latches.
164@param[in]	mode	lock mode check
165@retval true if owns any of them
166@retval false if owns no search latch */
167UNIV_INLINE
168bool btr_search_own_any(ulint mode) {
169  for (ulint i = 0; i < btr_ahi_parts; ++i) {
170    if (rw_lock_own(btr_search_latches[i], mode)) {
171      return (true);
172    }
173  }
174  return (false);
175}
176#endif /* UNIV_DEBUG */
177
178/** Get the adaptive hash search index latch for a b-tree.
179@param[in]	index	b-tree index
180@return latch */
181UNIV_INLINE
182rw_lock_t *btr_get_search_latch(const dict_index_t *index) {
183  ut_ad(index != nullptr);
184
185  ulint ifold = ut_fold_ulint_pair(static_cast<ulint>(index->id),
186                                   static_cast<ulint>(index->space));
187
188  return (btr_search_latches[ifold % btr_ahi_parts]);
189}
190
191/** Get the hash-table based on index attributes.
192A table is selected from an array of tables using pair of index-id, space-id.
193@param[in]	index	index handler
194@return hash table */
195UNIV_INLINE
196hash_table_t *btr_get_search_table(const dict_index_t *index) {
197  ut_ad(index != nullptr);
198
199  ulint ifold = ut_fold_ulint_pair(static_cast<ulint>(index->id),
200                                   static_cast<ulint>(index->space));
201
202  return (btr_search_sys->hash_tables[ifold % btr_ahi_parts]);
203}
204