Merge lp:~akopytov/percona-server/ahi-fixes-5.5 into lp:percona-server/5.5

Proposed by Alexey Kopytov
Status: Merged
Approved by: Laurynas Biveinis
Approved revision: 561
Merged at revision: 569
Proposed branch: lp:~akopytov/percona-server/ahi-fixes-5.5
Merge into: lp:percona-server/5.5
Diff against target: 1935 lines (+448/-373) (has conflicts)
22 files modified
Percona-Server/mysql-test/r/percona_bug1218330.result (+8/-0)
Percona-Server/mysql-test/t/percona_bug1218330-master.opt (+1/-0)
Percona-Server/mysql-test/t/percona_bug1218330.test (+42/-0)
Percona-Server/storage/innobase/btr/btr0cur.c (+6/-5)
Percona-Server/storage/innobase/btr/btr0sea.c (+119/-139)
Percona-Server/storage/innobase/buf/buf0buf.c (+1/-3)
Percona-Server/storage/innobase/dict/dict0boot.c (+8/-0)
Percona-Server/storage/innobase/dict/dict0dict.c (+3/-1)
Percona-Server/storage/innobase/dict/dict0load.c (+2/-0)
Percona-Server/storage/innobase/handler/ha_innodb.cc (+11/-6)
Percona-Server/storage/innobase/ibuf/ibuf0ibuf.c (+2/-0)
Percona-Server/storage/innobase/include/btr0sea.h (+36/-15)
Percona-Server/storage/innobase/include/btr0sea.ic (+67/-35)
Percona-Server/storage/innobase/include/btr0types.h (+6/-7)
Percona-Server/storage/innobase/include/buf0buf.h (+0/-1)
Percona-Server/storage/innobase/include/dict0mem.h (+4/-0)
Percona-Server/storage/innobase/include/trx0trx.h (+7/-5)
Percona-Server/storage/innobase/include/trx0trx.ic (+13/-0)
Percona-Server/storage/innobase/row/row0mysql.c (+6/-2)
Percona-Server/storage/innobase/row/row0sel.c (+36/-97)
Percona-Server/storage/innobase/srv/srv0srv.c (+64/-36)
Percona-Server/storage/innobase/trx/trx0trx.c (+6/-21)
Text conflict in Percona-Server/storage/innobase/handler/ha_innodb.cc
To merge this branch: bzr merge lp:~akopytov/percona-server/ahi-fixes-5.5
Reviewer Review Type Date Requested Status
Laurynas Biveinis (community) Approve
Review via email: mp+183471@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

    - In percona_bug1218330.test, consider replacing MTR variables
      with SQL variables. Then the need to hide the exact values by
      disable_query_log is removed from the adaptive_hash_mem_2 point
      onwards, resulting in an easier-to-understand test result file.
    - btr_search_info_get_ref_count header comment in btr0sea.c has
      "the ." Also, this header comment should be synced with
      btr0sea.h after editing.
    - It seems that now every index structure in memory create must
      be accompanied by a btr_search_index_init() call. This is OK,
      but I'm wondering if there is any way to merge-proof this
      further. For example, poison index->search_latch and
      search_table pointers in dict_mem_fill_index_struct() if
      UNIV_DEBUG?
    - The ha_innodb.cc conflict needs either you fixing it, if
      possible on GCA, otherwise me fixing it on merge. Note that
      the snippet which was supposed to go to
      innodb_release_stat_resources() went to
      innodb_srv_conc_force_exit_innodb() instead.
    - Why do innobase_release_stat_resources(),
      innobase_commit_ordered(), and innobase_commit() appear to have
      new calls to trx_search_latch_release_if_reserved() added
      anyway, if they are? Or is it a bzr mismerge and only comments
      next to the calls have been added?
    - Diff line 1273: "These latches"
    - It appears that sync_thread_levels_nonempty_trx() is dead code
      now, and all its calls may be replaced by
      sync_thread_levels_nonempty_gen(FALSE).
    - trx->search_latch_timeout now becomes a never-changing constant
      BTR_SEA_TIMEOUT. It can be removed and
      I_S.INNODB_TRX.TRX_ADAPTIVE_HASH_TIMEOUT field can return
      BTR_SEA_TIMEOUT directly, always.
    - Not fully sure but it appears that there are some
      locking/unlocking assymetries wrt UNIV_SEARCH_DEBUG, preceding
      this MP. Not if actionable, probably no need to waste time on
      this. One suspicious example is the target code of
      release_search_latch goto label.

review: Needs Fixing
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

I forgot that I can just look at the ha_innodb.cc diff on your branch directly. It answered both the ha_innodb.cc-related questions I had, no need to address it in any way, I'll be able to merge GCA to trunk correctly there.

Revision history for this message
Alexey Kopytov (akopytov) wrote :
Download full text (4.6 KiB)

Hi Laurynas,

On Wed, 04 Sep 2013 14:50:31 -0000, Laurynas Biveinis wrote:
> Review: Needs Fixing
>
> - In percona_bug1218330.test, consider replacing MTR variables
> with SQL variables. Then the need to hide the exact values by
> disable_query_log is removed from the adaptive_hash_mem_2 point
> onwards, resulting in an easier-to-understand test result file.
> - btr_search_info_get_ref_count header comment in btr0sea.c has
> "the ." Also, this header comment should be synced with
> btr0sea.h after editing.

I considered SQL variables when implementing the test, but preferred MTR
variables, because the .test file is easier to read this way. And the
.result file is for MTR to read.

> - It seems that now every index structure in memory create must
> be accompanied by a btr_search_index_init() call. This is OK,
> but I'm wondering if there is any way to merge-proof this
> further. For example, poison index->search_latch and
> search_table pointers in dict_mem_fill_index_struct() if
> UNIV_DEBUG?

Yes, btr_search_index_init() must be called. The main reason is that
dict_mem_index_create() does not set the index id, it is supposed to be
assigned by the caller and btr_search_index_init() needs an ID.

Now the callers of dict_mem_index_create() do assign an ID in most, but
not all cases. For instance, when a "dummy" index is created, it doesn't
get an ID.

One way to fix that would be to modify dict_mem_index_create() to accept
an ID argument, and make dummy index pass some bogus value (0) as an ID.
But that's almost as fragile as the current approach. Consider a
potential index copy routine that copies an existing index (i.e.
bypassing dict_mem_index_create()) and assigning an ID separately.

I don't see any value in poisoning index->search_latch, as index
structure is created with mem_heap_zalloc(), so if an uninitialized
value is used, we'll know.

> - The ha_innodb.cc conflict needs either you fixing it, if
> possible on GCA, otherwise me fixing it on merge. Note that
> the snippet which was supposed to go to
> innodb_release_stat_resources() went to
> innodb_srv_conc_force_exit_innodb() instead.

Yes, saw the conflict. The reason is that 5.5 GCA tree is behind the
refactoring which made it into the 5.6 tree.

Basically, do what 5.6 code does when merging. It's rather trivial to
resolve.

> - Why do innobase_release_stat_resources(),
> innobase_commit_ordered(), and innobase_commit() appear to have
> new calls to trx_search_latch_release_if_reserved() added
> anyway, if they are? Or is it a bzr mismerge and only comments
> next to the calls have been added?

It's just that the GCA branch has those calls, but they were removed
later. Null-merge those conflicts.

> - Diff line 1273: "These latches"

Oh noes :) But since that is just a "typo in a comment" kind of issue,
and the recommit/merge procedure is quite complicated in this specific
case, I'd keep it as is.

> - It appears that sync_thread_levels_nonempty_trx() is dead code
> now, and all its calls may be...

Read more...

Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

Alexey -

> > - btr_search_info_get_ref_count header comment in btr0sea.c has
> > "the ." Also, this header comment should be synced with
> > btr0sea.h after editing.

You haven't acknowledged this "oh noes :)" comment. I think I can just fix those typos on trunk merge if a repush is not needed otherwise.

> > - It seems that now every index structure in memory create must
> > be accompanied by a btr_search_index_init() call. This is OK,
> > but I'm wondering if there is any way to merge-proof this
> > further. For example, poison index->search_latch and
> > search_table pointers in dict_mem_fill_index_struct() if
> > UNIV_DEBUG?
...
> I don't see any value in poisoning index->search_latch, as index
> structure is created with mem_heap_zalloc(), so if an uninitialized
> value is used, we'll know.

I guess then index->search_table poisoning is not that needed neither. Thus no need to do anything about poisoning.

> > - It appears that sync_thread_levels_nonempty_trx() is dead code
> > now, and all its calls may be replaced by
> > sync_thread_levels_nonempty_gen(FALSE).
>
> It's not "dead code", it's more a debug validation check that we _think_
> is now unnecessary because on the current code paths we believe
> trx->has_search_latch is always FALSE. We may be wrong. Or code paths
> may change in the future. The more debug checks, the better.

I don't think I fully agree: sync_thread_levels_nonempty_gen(FALSE) is a stricter condition than sync_thread_levels_nonempty_trx(). Thus if we replaced all the calls of the latter with the former, we wouldn't lose any debug checks. The problem of course if we are wrong as you say and may have to add the checks back.

review: Approve
Revision history for this message
Alexey Kopytov (akopytov) wrote :

Hi Laurynas,

On Fri, 06 Sep 2013 12:46:10 -0000, Laurynas Biveinis wrote:
> Review: Approve
>
> Alexey -
>
>>> - btr_search_info_get_ref_count header comment in btr0sea.c has
>>> "the ." Also, this header comment should be synced with
>>> btr0sea.h after editing.
>
> You haven't acknowledged this "oh noes :)" comment. I think I can just fix those typos on trunk merge if a repush is not needed otherwise.
>

Yes, missed that one. I originally intended to fix all comments to
reflect AHI partitioning, as that introduced unnecessary maintenance
burden. But then I changed my mind and forgot to fully rollback some of
the changes.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'Percona-Server/mysql-test/r/percona_bug1218330.result'
2--- Percona-Server/mysql-test/r/percona_bug1218330.result 1970-01-01 00:00:00 +0000
3+++ Percona-Server/mysql-test/r/percona_bug1218330.result 2013-09-02 14:07:43 +0000
4@@ -0,0 +1,8 @@
5+CREATE TABLE t1 (
6+a INT PRIMARY KEY, b INT,
7+c CHAR(200),
8+UNIQUE INDEX b(b)) ENGINE=InnoDB;
9+INSERT INTO t1 VALUES (1, 1, REPEAT("a", 200));
10+should_be_1
11+1
12+DROP TABLE t1;
13
14=== added file 'Percona-Server/mysql-test/t/percona_bug1218330-master.opt'
15--- Percona-Server/mysql-test/t/percona_bug1218330-master.opt 1970-01-01 00:00:00 +0000
16+++ Percona-Server/mysql-test/t/percona_bug1218330-master.opt 2013-09-02 14:07:43 +0000
17@@ -0,0 +1,1 @@
18+--innodb-adaptive-hash-index-partitions=32
19
20=== added file 'Percona-Server/mysql-test/t/percona_bug1218330.test'
21--- Percona-Server/mysql-test/t/percona_bug1218330.test 1970-01-01 00:00:00 +0000
22+++ Percona-Server/mysql-test/t/percona_bug1218330.test 2013-09-02 14:07:43 +0000
23@@ -0,0 +1,42 @@
24+############################################################################
25+# Bug #1218330: Adaptive hash index memory is incorrectly calculated in SHOW
26+# ENGINE INNODB STATUS and I_S
27+############################################################################
28+
29+--source include/have_innodb.inc
30+
31+let $adaptive_hash_mem_1=`SELECT VARIABLE_VALUE FROM
32+ INFORMATION_SCHEMA.GLOBAL_STATUS WHERE
33+ VARIABLE_NAME='Innodb_mem_adaptive_hash'`;
34+
35+CREATE TABLE t1 (
36+ a INT PRIMARY KEY, b INT,
37+ c CHAR(200),
38+ UNIQUE INDEX b(b)) ENGINE=InnoDB;
39+
40+INSERT INTO t1 VALUES (1, 1, REPEAT("a", 200));
41+
42+--disable_query_log
43+
44+--let $i=200
45+--disable_result_log
46+while ($i)
47+{
48+ SELECT a FROM t1 WHERE a=1;
49+ SELECT b FROM t1 WHERE b=1;
50+ --dec $i
51+}
52+--enable_result_log
53+
54+let $adaptive_hash_mem_2=`SELECT VARIABLE_VALUE FROM
55+ INFORMATION_SCHEMA.GLOBAL_STATUS WHERE
56+ VARIABLE_NAME='Innodb_mem_adaptive_hash'`;
57+
58+# The original implementation would should identical values in
59+# adaptive_hash_mem_1 and adaptive_hash_mem_2
60+
61+--eval SELECT $adaptive_hash_mem_1 != $adaptive_hash_mem_2 as should_be_1
62+
63+--enable_query_log
64+
65+DROP TABLE t1;
66
67=== modified file 'Percona-Server/storage/innobase/btr/btr0cur.c'
68--- Percona-Server/storage/innobase/btr/btr0cur.c 2013-06-27 15:35:20 +0000
69+++ Percona-Server/storage/innobase/btr/btr0cur.c 2013-09-02 14:07:43 +0000
70@@ -520,7 +520,8 @@
71 #ifdef UNIV_SEARCH_PERF_STAT
72 info->n_searches++;
73 #endif
74- if (rw_lock_get_writer(btr_search_get_latch(cursor->index->id)) == RW_LOCK_NOT_LOCKED
75+ if (rw_lock_get_writer(btr_search_get_latch(cursor->index)) ==
76+ RW_LOCK_NOT_LOCKED
77 && latch_mode <= BTR_MODIFY_LEAF
78 && info->last_hash_succ
79 && !estimate
80@@ -556,7 +557,7 @@
81
82 if (has_search_latch) {
83 /* Release possible search latch to obey latching order */
84- rw_lock_s_unlock(btr_search_get_latch(cursor->index->id));
85+ rw_lock_s_unlock(btr_search_get_latch(cursor->index));
86 }
87
88 /* Store the position of the tree latch we push to mtr so that we
89@@ -871,7 +872,7 @@
90
91 if (has_search_latch) {
92
93- rw_lock_s_lock(btr_search_get_latch(cursor->index->id));
94+ rw_lock_s_lock(btr_search_get_latch(cursor->index));
95 }
96 }
97
98@@ -2056,13 +2057,13 @@
99 btr_search_update_hash_on_delete(cursor);
100 }
101
102- rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
103+ rw_lock_x_lock(btr_search_get_latch(cursor->index));
104 }
105
106 row_upd_rec_in_place(rec, index, offsets, update, page_zip);
107
108 if (is_hashed) {
109- rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
110+ rw_lock_x_unlock(btr_search_get_latch(cursor->index));
111 }
112
113 if (page_zip && !dict_index_is_clust(index)
114
115=== modified file 'Percona-Server/storage/innobase/btr/btr0sea.c'
116--- Percona-Server/storage/innobase/btr/btr0sea.c 2013-08-14 03:52:04 +0000
117+++ Percona-Server/storage/innobase/btr/btr0sea.c 2013-09-02 14:07:43 +0000
118@@ -69,17 +69,14 @@
119 cache line as btr_search_latch */
120 UNIV_INTERN byte btr_sea_pad1[64];
121
122-/** The latch protecting the adaptive search system: this latch protects the
123-(1) positions of records on those pages where a hash index has been built.
124-NOTE: It does not protect values of non-ordering fields within a record from
125+/** Array of latches protecting individual AHI partitions. The latches
126+protect: (1) positions of records on those pages where a hash index from the
127+corresponding AHI partition has been built.
128+NOTE: They do not protect values of non-ordering fields within a record from
129 being updated in-place! We can use fact (1) to perform unique searches to
130 indexes. */
131
132-/* We will allocate the latch from dynamic memory to get it to the
133-same DRAM page as other hotspot semaphores */
134-//UNIV_INTERN rw_lock_t* btr_search_latch_temp;
135-
136-UNIV_INTERN rw_lock_t** btr_search_latch_part;
137+UNIV_INTERN rw_lock_t* btr_search_latch_arr;
138
139 /** padding to prevent other memory update hotspots from residing on
140 the same memory cache line */
141@@ -133,17 +130,17 @@
142 void
143 btr_search_check_free_space_in_heap(
144 /*=====================================*/
145- index_id_t key)
146+ dict_index_t* index)
147 {
148 hash_table_t* table;
149 mem_heap_t* heap;
150
151 #ifdef UNIV_SYNC_DEBUG
152- ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
153- ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
154+ ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_SHARED));
155+ ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_EX));
156 #endif /* UNIV_SYNC_DEBUG */
157
158- table = btr_search_get_hash_index(key);
159+ table = btr_search_get_hash_table(index);
160
161 heap = table->heap;
162
163@@ -154,7 +151,7 @@
164 if (heap->free_block == NULL) {
165 buf_block_t* block = buf_block_alloc(NULL);
166
167- rw_lock_x_lock(btr_search_get_latch(key));
168+ rw_lock_x_lock(btr_search_get_latch(index));
169
170 if (heap->free_block == NULL) {
171 heap->free_block = block;
172@@ -162,7 +159,7 @@
173 buf_block_free(block);
174 }
175
176- rw_lock_x_unlock(btr_search_get_latch(key));
177+ rw_lock_x_unlock(btr_search_get_latch(index));
178 }
179 }
180
181@@ -194,16 +191,19 @@
182
183 btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
184
185- /* btr_search_index_num should be <= 32. (bits of trx->has_search_latch) */
186- btr_search_latch_part = mem_alloc(sizeof(rw_lock_t*) * btr_search_index_num);
187- btr_search_sys->hash_index = mem_alloc(sizeof(hash_table_t*) * btr_search_index_num);
188+ /* btr_search_index_num is constrained to machine word size for
189+ historical reasons. This limitation can be easily removed later. */
190+
191+ btr_search_latch_arr = mem_alloc(sizeof(rw_lock_t) *
192+ btr_search_index_num);
193+ btr_search_sys->hash_tables = mem_alloc(sizeof(hash_table_t *) *
194+ btr_search_index_num);
195 for (i = 0; i < btr_search_index_num; i++) {
196- btr_search_latch_part[i] = mem_alloc(sizeof(rw_lock_t));
197
198 rw_lock_create(btr_search_latch_key,
199- btr_search_latch_part[i], SYNC_SEARCH_SYS);
200+ &btr_search_latch_arr[i], SYNC_SEARCH_SYS);
201
202- btr_search_sys->hash_index[i] = ha_create(hash_size, 0, 0);
203+ btr_search_sys->hash_tables[i] = ha_create(hash_size, 0, 0);
204 }
205 }
206
207@@ -217,15 +217,13 @@
208 ulint i;
209
210 for (i = 0; i < btr_search_index_num; i++) {
211- mem_heap_free(btr_search_sys->hash_index[i]->heap);
212- hash_table_free(btr_search_sys->hash_index[i]);
213-
214- rw_lock_free(btr_search_latch_part[i]);
215-
216- mem_free(btr_search_latch_part[i]);
217+ mem_heap_free(btr_search_sys->hash_tables[i]->heap);
218+ hash_table_free(btr_search_sys->hash_tables[i]);
219+
220+ rw_lock_free(&btr_search_latch_arr[i]);
221 }
222- mem_free(btr_search_sys->hash_index);
223- mem_free(btr_search_latch_part);
224+ mem_free(btr_search_sys->hash_tables);
225+ mem_free(btr_search_latch_arr);
226
227 //rw_lock_free(&btr_search_latch);
228 //mem_free(btr_search_latch_temp);
229@@ -270,8 +268,8 @@
230
231 /* Clear the adaptive hash index. */
232 for (i = 0; i < btr_search_index_num; i++) {
233- hash_table_clear(btr_search_sys->hash_index[i]);
234- mem_heap_empty(btr_search_sys->hash_index[i]->heap);
235+ hash_table_clear(btr_search_sys->hash_tables[i]);
236+ mem_heap_empty(btr_search_sys->hash_tables[i]->heap);
237 }
238
239 btr_search_x_unlock_all();
240@@ -334,27 +332,27 @@
241
242 /*****************************************************************//**
243 Returns the value of ref_count. The value is protected by
244-btr_search_latch.
245+the .
246 @return ref_count value. */
247 UNIV_INTERN
248 ulint
249 btr_search_info_get_ref_count(
250 /*==========================*/
251 btr_search_t* info, /*!< in: search info. */
252- index_id_t key)
253+ dict_index_t* index) /*!< in: index */
254 {
255 ulint ret;
256
257 ut_ad(info);
258
259 #ifdef UNIV_SYNC_DEBUG
260- ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
261- ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
262+ ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_SHARED));
263+ ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_EX));
264 #endif /* UNIV_SYNC_DEBUG */
265
266- rw_lock_s_lock(btr_search_get_latch(key));
267+ rw_lock_s_lock(btr_search_get_latch(index));
268 ret = info->ref_count;
269- rw_lock_s_unlock(btr_search_get_latch(key));
270+ rw_lock_s_unlock(btr_search_get_latch(index));
271
272 return(ret);
273 }
274@@ -375,8 +373,8 @@
275 int cmp;
276
277 #ifdef UNIV_SYNC_DEBUG
278- ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
279- ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
280+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_SHARED));
281+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_EX));
282 #endif /* UNIV_SYNC_DEBUG */
283
284 index = cursor->index;
285@@ -494,8 +492,8 @@
286 /*!< in: cursor */
287 {
288 #ifdef UNIV_SYNC_DEBUG
289- ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
290- ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
291+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_SHARED));
292+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_EX));
293 ut_ad(rw_lock_own(&block->lock, RW_LOCK_SHARED)
294 || rw_lock_own(&block->lock, RW_LOCK_EX));
295 #endif /* UNIV_SYNC_DEBUG */
296@@ -579,7 +577,7 @@
297
298 ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
299 #ifdef UNIV_SYNC_DEBUG
300- ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
301+ ut_ad(rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_EX));
302 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
303 || rw_lock_own(&(block->lock), RW_LOCK_EX));
304 #endif /* UNIV_SYNC_DEBUG */
305@@ -620,11 +618,12 @@
306 mem_heap_free(heap);
307 }
308 #ifdef UNIV_SYNC_DEBUG
309- ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
310+ ut_ad(rw_lock_own(btr_search_get_latch(cursor->index),
311+ RW_LOCK_EX));
312 #endif /* UNIV_SYNC_DEBUG */
313
314- ha_insert_for_fold(btr_search_get_hash_index(cursor->index->id), fold,
315- block, rec);
316+ ha_insert_for_fold(btr_search_get_hash_table(cursor->index),
317+ fold, block, rec);
318 }
319 }
320
321@@ -643,8 +642,8 @@
322 ulint* params2;
323
324 #ifdef UNIV_SYNC_DEBUG
325- ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
326- ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
327+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_SHARED));
328+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_EX));
329 #endif /* UNIV_SYNC_DEBUG */
330
331 block = btr_cur_get_block(cursor);
332@@ -662,7 +661,7 @@
333
334 if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
335
336- btr_search_check_free_space_in_heap(cursor->index->id);
337+ btr_search_check_free_space_in_heap(cursor->index);
338 }
339
340 if (cursor->flag == BTR_CUR_HASH_FAIL) {
341@@ -672,11 +671,11 @@
342 btr_search_n_hash_fail++;
343 #endif /* UNIV_SEARCH_PERF_STAT */
344
345- rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
346+ rw_lock_x_lock(btr_search_get_latch(cursor->index));
347
348 btr_search_update_hash_ref(info, block, cursor);
349
350- rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
351+ rw_lock_x_unlock(btr_search_get_latch(cursor->index));
352 }
353
354 if (build_index) {
355@@ -921,17 +920,17 @@
356 cursor->flag = BTR_CUR_HASH;
357
358 if (UNIV_LIKELY(!has_search_latch)) {
359- rw_lock_s_lock(btr_search_get_latch(index_id));
360+ rw_lock_s_lock(btr_search_get_latch(index));
361
362 if (UNIV_UNLIKELY(!btr_search_enabled)) {
363 goto failure_unlock;
364 }
365 }
366
367- ut_ad(rw_lock_get_writer(btr_search_get_latch(index_id)) != RW_LOCK_EX);
368- ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index_id)) > 0);
369+ ut_ad(rw_lock_get_writer(btr_search_get_latch(index)) != RW_LOCK_EX);
370+ ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index)) > 0);
371
372- rec = ha_search_and_get_data(btr_search_get_hash_index(index_id), fold);
373+ rec = ha_search_and_get_data(btr_search_get_hash_table(index), fold);
374
375 if (UNIV_UNLIKELY(!rec)) {
376 goto failure_unlock;
377@@ -949,7 +948,7 @@
378 goto failure_unlock;
379 }
380
381- rw_lock_s_unlock(btr_search_get_latch(index_id));
382+ rw_lock_s_unlock(btr_search_get_latch(index));
383
384 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
385 }
386@@ -1046,7 +1045,7 @@
387 /*-------------------------------------------*/
388 failure_unlock:
389 if (UNIV_LIKELY(!has_search_latch)) {
390- rw_lock_s_unlock(btr_search_get_latch(index_id));
391+ rw_lock_s_unlock(btr_search_get_latch(index));
392 }
393 failure:
394 cursor->flag = BTR_CUR_HASH_FAIL;
395@@ -1091,48 +1090,26 @@
396 ulint* offsets;
397
398 retry:
399- if (btr_search_index_num > 1) {
400- rw_lock_t* btr_search_latch;
401-
402- /* FIXME: This may be optimistic implementation still. */
403- btr_search_latch = (rw_lock_t*)(block->btr_search_latch);
404- if (UNIV_LIKELY(!btr_search_latch)) {
405- if (block->index) {
406- goto retry;
407- }
408- return;
409- }
410- rw_lock_s_lock(btr_search_latch);
411- if (UNIV_LIKELY(btr_search_latch != block->btr_search_latch)) {
412- rw_lock_s_unlock(btr_search_latch);
413- goto retry;
414- }
415- if (UNIV_LIKELY(!block->index)) {
416- rw_lock_s_unlock(btr_search_latch);
417- goto retry;
418- }
419- index = block->index;
420- ut_a(btr_search_latch == btr_search_get_latch(index->id));
421- } else {
422- /* btr_search_index_num == 1 */
423- /* btr_search_latch is only one and able to obtain
424- before evaluating block->index. */
425- rw_lock_s_lock(btr_search_latch_part[0]);
426- if (UNIV_LIKELY(!block->index)) {
427- rw_lock_s_unlock(btr_search_latch_part[0]);
428- return;
429- }
430- index = block->index;
431- }
432-
433- if (UNIV_LIKELY(!index)) {
434-
435- rw_lock_s_unlock(btr_search_get_latch(index->id));
436+ /* Do a dirty check on block->index, return if the block is not in the
437+ adaptive hash index. This is to avoid acquiring an AHI latch for
438+ performance considerations. */
439+
440+ index = block->index;
441+ if (!index) {
442
443 return;
444 }
445
446- table = btr_search_get_hash_index(index->id);
447+ rw_lock_s_lock(btr_search_get_latch(index));
448+
449+ if (UNIV_UNLIKELY(index != block->index)) {
450+
451+ rw_lock_s_unlock(btr_search_get_latch(index));
452+
453+ goto retry;
454+ }
455+
456+ table = btr_search_get_hash_table(index);
457
458 #ifdef UNIV_SYNC_DEBUG
459 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
460@@ -1149,7 +1126,7 @@
461 releasing btr_search_latch, as the index page might only
462 be s-latched! */
463
464- rw_lock_s_unlock(btr_search_get_latch(index->id));
465+ rw_lock_s_unlock(btr_search_get_latch(index));
466
467 ut_a(n_fields + n_bytes > 0);
468
469@@ -1200,7 +1177,7 @@
470 mem_heap_free(heap);
471 }
472
473- rw_lock_x_lock(btr_search_get_latch(index->id));
474+ rw_lock_x_lock(btr_search_get_latch(index));
475
476 if (UNIV_UNLIKELY(!block->index)) {
477 /* Someone else has meanwhile dropped the hash index */
478@@ -1216,7 +1193,7 @@
479 /* Someone else has meanwhile built a new hash index on the
480 page, with different parameters */
481
482- rw_lock_x_unlock(btr_search_get_latch(index->id));
483+ rw_lock_x_unlock(btr_search_get_latch(index));
484
485 mem_free(folds);
486 goto retry;
487@@ -1231,7 +1208,6 @@
488 index->search_info->ref_count--;
489
490 block->index = NULL;
491- block->btr_search_latch = NULL;
492
493 cleanup:
494 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
495@@ -1244,14 +1220,14 @@
496 "InnoDB: the hash index to a page of %s,"
497 " still %lu hash nodes remain.\n",
498 index->name, (ulong) block->n_pointers);
499- rw_lock_x_unlock(btr_search_get_latch(index->id));
500+ rw_lock_x_unlock(btr_search_get_latch(index));
501
502 ut_ad(btr_search_validate());
503 } else {
504- rw_lock_x_unlock(btr_search_get_latch(index->id));
505+ rw_lock_x_unlock(btr_search_get_latch(index));
506 }
507 #else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
508- rw_lock_x_unlock(btr_search_get_latch(index->id));
509+ rw_lock_x_unlock(btr_search_get_latch(index));
510 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
511
512 mem_free(folds);
513@@ -1283,9 +1259,9 @@
514 ulint* offsets;
515 ibool released_search_latch;
516
517- rw_lock_s_lock(btr_search_get_latch(index->id));
518+ rw_lock_s_lock(btr_search_get_latch(index));
519
520- table = btr_search_get_hash_index(index->id);
521+ table = btr_search_get_hash_table(index);
522
523 for (j = 0; j < srv_buf_pool_instances; j++) {
524 buf_pool_t* buf_pool;
525@@ -1319,7 +1295,8 @@
526
527
528 /* keeping latch order */
529- rw_lock_s_unlock(btr_search_get_latch(index->id));
530+ rw_lock_s_unlock(
531+ btr_search_get_latch(index));
532 released_search_latch = TRUE;
533 rw_lock_x_lock(&block->lock);
534
535@@ -1371,7 +1348,8 @@
536 mem_heap_empty(heap);
537 }
538
539- rw_lock_x_lock(btr_search_get_latch(index->id));
540+ rw_lock_x_lock(
541+ btr_search_get_latch(index));
542
543 if (UNIV_UNLIKELY(!block->index)) {
544 goto cleanup;
545@@ -1381,12 +1359,14 @@
546
547 if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
548 || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
549- rw_lock_x_unlock(btr_search_get_latch(index->id));
550+ rw_lock_x_unlock(
551+ btr_search_get_latch(index));
552 rw_lock_x_unlock(&block->lock);
553
554 mem_free(folds);
555
556- rw_lock_s_lock(btr_search_get_latch(index->id));
557+ rw_lock_s_lock(
558+ btr_search_get_latch(index));
559 goto retry;
560 }
561
562@@ -1399,7 +1379,6 @@
563 index->search_info->ref_count--;
564
565 block->index = NULL;
566- block->btr_search_latch = NULL;
567
568 cleanup:
569 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
570@@ -1412,18 +1391,20 @@
571 index->name, (ulong) block->n_pointers);
572 }
573 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
574- rw_lock_x_unlock(btr_search_get_latch(index->id));
575+ rw_lock_x_unlock(
576+ btr_search_get_latch(index));
577 rw_lock_x_unlock(&block->lock);
578
579 mem_free(folds);
580
581- rw_lock_s_lock(btr_search_get_latch(index->id));
582+ rw_lock_s_lock(
583+ btr_search_get_latch(index));
584 }
585 }
586 } while (released_search_latch);
587 }
588
589- rw_lock_s_unlock(btr_search_get_latch(index->id));
590+ rw_lock_s_unlock(btr_search_get_latch(index));
591
592 if (UNIV_LIKELY_NULL(heap)) {
593 mem_heap_free(heap);
594@@ -1502,7 +1483,7 @@
595 ut_ad(index);
596 ut_a(!dict_index_is_ibuf(index));
597
598- table = btr_search_get_hash_index(index->id);
599+ table = btr_search_get_hash_table(index);
600 page = buf_block_get_frame(block);
601
602 #ifdef UNIV_SYNC_DEBUG
603@@ -1511,17 +1492,17 @@
604 || rw_lock_own(&(block->lock), RW_LOCK_EX));
605 #endif /* UNIV_SYNC_DEBUG */
606
607- rw_lock_s_lock(btr_search_get_latch(index->id));
608+ rw_lock_s_lock(btr_search_get_latch(index));
609
610 if (block->index && ((block->curr_n_fields != n_fields)
611 || (block->curr_n_bytes != n_bytes)
612 || (block->curr_left_side != left_side))) {
613
614- rw_lock_s_unlock(btr_search_get_latch(index->id));
615+ rw_lock_s_unlock(btr_search_get_latch(index));
616
617 btr_search_drop_page_hash_index(block);
618 } else {
619- rw_lock_s_unlock(btr_search_get_latch(index->id));
620+ rw_lock_s_unlock(btr_search_get_latch(index));
621 }
622
623 n_recs = page_get_n_recs(page);
624@@ -1615,9 +1596,9 @@
625 fold = next_fold;
626 }
627
628- btr_search_check_free_space_in_heap(index->id);
629+ btr_search_check_free_space_in_heap(index);
630
631- rw_lock_x_lock(btr_search_get_latch(index->id));
632+ rw_lock_x_lock(btr_search_get_latch(index));
633
634 if (UNIV_UNLIKELY(!btr_search_enabled)) {
635 goto exit_func;
636@@ -1644,7 +1625,6 @@
637 block->curr_n_bytes = n_bytes;
638 block->curr_left_side = left_side;
639 block->index = index;
640- block->btr_search_latch = btr_search_get_latch(index->id);
641
642 for (i = 0; i < n_cached; i++) {
643
644@@ -1652,7 +1632,7 @@
645 }
646
647 exit_func:
648- rw_lock_x_unlock(btr_search_get_latch(index->id));
649+ rw_lock_x_unlock(btr_search_get_latch(index));
650
651 mem_free(folds);
652 mem_free(recs);
653@@ -1687,7 +1667,7 @@
654 ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));
655 #endif /* UNIV_SYNC_DEBUG */
656
657- rw_lock_s_lock(btr_search_get_latch(index->id));
658+ rw_lock_s_lock(btr_search_get_latch(index));
659
660 ut_a(!new_block->index || new_block->index == index);
661 ut_a(!block->index || block->index == index);
662@@ -1696,7 +1676,7 @@
663
664 if (new_block->index) {
665
666- rw_lock_s_unlock(btr_search_get_latch(index->id));
667+ rw_lock_s_unlock(btr_search_get_latch(index));
668
669 btr_search_drop_page_hash_index(block);
670
671@@ -1713,7 +1693,7 @@
672 new_block->n_bytes = block->curr_n_bytes;
673 new_block->left_side = left_side;
674
675- rw_lock_s_unlock(btr_search_get_latch(index->id));
676+ rw_lock_s_unlock(btr_search_get_latch(index));
677
678 ut_a(n_fields + n_bytes > 0);
679
680@@ -1725,7 +1705,7 @@
681 return;
682 }
683
684- rw_lock_s_unlock(btr_search_get_latch(index->id));
685+ rw_lock_s_unlock(btr_search_get_latch(index));
686 }
687
688 /********************************************************************//**
689@@ -1764,7 +1744,7 @@
690 ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
691 ut_a(!dict_index_is_ibuf(index));
692
693- table = btr_search_get_hash_index(cursor->index->id);
694+ table = btr_search_get_hash_table(cursor->index);
695
696 rec = btr_cur_get_rec(cursor);
697
698@@ -1775,7 +1755,7 @@
699 mem_heap_free(heap);
700 }
701
702- rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
703+ rw_lock_x_lock(btr_search_get_latch(cursor->index));
704
705 if (block->index) {
706 ut_a(block->index == index);
707@@ -1783,7 +1763,7 @@
708 ha_search_and_delete_if_found(table, fold, rec);
709 }
710
711- rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
712+ rw_lock_x_unlock(btr_search_get_latch(cursor->index));
713 }
714
715 /********************************************************************//**
716@@ -1820,7 +1800,7 @@
717 ut_a(cursor->index == index);
718 ut_a(!dict_index_is_ibuf(index));
719
720- rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
721+ rw_lock_x_lock(btr_search_get_latch(cursor->index));
722
723 if (!block->index) {
724
725@@ -1834,15 +1814,15 @@
726 && (cursor->n_bytes == block->curr_n_bytes)
727 && !block->curr_left_side) {
728
729- table = btr_search_get_hash_index(cursor->index->id);
730+ table = btr_search_get_hash_table(cursor->index);
731
732 ha_search_and_update_if_found(table, cursor->fold, rec,
733 block, page_rec_get_next(rec));
734
735 func_exit:
736- rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
737+ rw_lock_x_unlock(btr_search_get_latch(cursor->index));
738 } else {
739- rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
740+ rw_lock_x_unlock(btr_search_get_latch(cursor->index));
741
742 btr_search_update_hash_on_insert(cursor);
743 }
744@@ -1877,9 +1857,9 @@
745 ulint* offsets = offsets_;
746 rec_offs_init(offsets_);
747
748- table = btr_search_get_hash_index(cursor->index->id);
749+ table = btr_search_get_hash_table(cursor->index);
750
751- btr_search_check_free_space_in_heap(cursor->index->id);
752+ btr_search_check_free_space_in_heap(cursor->index);
753
754 rec = btr_cur_get_rec(cursor);
755
756@@ -1924,7 +1904,7 @@
757 } else {
758 if (left_side) {
759
760- rw_lock_x_lock(btr_search_get_latch(index->id));
761+ rw_lock_x_lock(btr_search_get_latch(index));
762
763 locked = TRUE;
764
765@@ -1942,7 +1922,7 @@
766
767 if (!locked) {
768
769- rw_lock_x_lock(btr_search_get_latch(index->id));
770+ rw_lock_x_lock(btr_search_get_latch(index));
771
772 locked = TRUE;
773
774@@ -1964,7 +1944,7 @@
775 if (!left_side) {
776
777 if (!locked) {
778- rw_lock_x_lock(btr_search_get_latch(index->id));
779+ rw_lock_x_lock(btr_search_get_latch(index));
780
781 locked = TRUE;
782
783@@ -1983,7 +1963,7 @@
784
785 if (!locked) {
786
787- rw_lock_x_lock(btr_search_get_latch(index->id));
788+ rw_lock_x_lock(btr_search_get_latch(index));
789
790 locked = TRUE;
791
792@@ -2010,7 +1990,7 @@
793 mem_heap_free(heap);
794 }
795 if (locked) {
796- rw_lock_x_unlock(btr_search_get_latch(index->id));
797+ rw_lock_x_unlock(btr_search_get_latch(index));
798 }
799 }
800
801@@ -2043,7 +2023,7 @@
802
803 for (j = 0; j < btr_search_index_num; j++) {
804
805- cell_count = hash_get_n_cells(btr_search_sys->hash_index[j]);
806+ cell_count = hash_get_n_cells(btr_search_sys->hash_tables[j]);
807
808 for (i = 0; i < cell_count; i++) {
809 /* We release btr_search_latch every once in a while to
810@@ -2056,7 +2036,7 @@
811 buf_pool_page_hash_x_lock_all();
812 }
813
814- node = hash_get_nth_cell(btr_search_sys->hash_index[j], i)->node;
815+ node = hash_get_nth_cell(btr_search_sys->hash_tables[j], i)->node;
816
817 for (; node != NULL; node = node->next) {
818 const buf_block_t* block
819@@ -2171,7 +2151,7 @@
820 buf_pool_page_hash_x_lock_all();
821 }
822
823- if (!ha_validate(btr_search_sys->hash_index[j], i, end_index)) {
824+ if (!ha_validate(btr_search_sys->hash_tables[j], i, end_index)) {
825 ok = FALSE;
826 }
827 }
828
829=== modified file 'Percona-Server/storage/innobase/buf/buf0buf.c'
830--- Percona-Server/storage/innobase/buf/buf0buf.c 2013-08-16 13:17:34 +0000
831+++ Percona-Server/storage/innobase/buf/buf0buf.c 2013-09-02 14:07:43 +0000
832@@ -989,7 +989,6 @@
833
834 block->check_index_page_at_flush = FALSE;
835 block->index = NULL;
836- block->btr_search_latch = NULL;
837
838 #ifdef UNIV_DEBUG
839 block->page.in_page_hash = FALSE;
840@@ -1468,7 +1467,7 @@
841 ulint j;
842
843 for (j = 0; j < btr_search_index_num; j++) {
844- ut_ad(rw_lock_own(btr_search_latch_part[j], RW_LOCK_EX));
845+ ut_ad(rw_lock_own(&btr_search_latch_arr[j], RW_LOCK_EX));
846 }
847 #endif /* UNIV_SYNC_DEBUG */
848 ut_ad(!btr_search_enabled);
849@@ -2147,7 +2146,6 @@
850 {
851 block->check_index_page_at_flush = FALSE;
852 block->index = NULL;
853- block->btr_search_latch = NULL;
854
855 block->n_hash_helps = 0;
856 block->n_fields = 1;
857
858=== modified file 'Percona-Server/storage/innobase/dict/dict0boot.c'
859--- Percona-Server/storage/innobase/dict/dict0boot.c 2013-08-14 03:52:04 +0000
860+++ Percona-Server/storage/innobase/dict/dict0boot.c 2013-09-02 14:07:43 +0000
861@@ -31,6 +31,7 @@
862
863 #include "dict0crea.h"
864 #include "btr0btr.h"
865+#include "btr0sea.h"
866 #include "dict0load.h"
867 #include "dict0load.h"
868 #include "trx0trx.h"
869@@ -346,6 +347,7 @@
870 dict_mem_index_add_field(index, "KEY_COLS", 0);
871
872 index->id = DICT_STATS_ID;
873+ btr_search_index_init(index);
874
875 root_page_id = mtr_read_ulint(dict_hdr + DICT_HDR_STATS, MLOG_4BYTES,
876 mtr);
877@@ -481,6 +483,7 @@
878 dict_mem_index_add_field(index, "NAME", 0);
879
880 index->id = DICT_TABLES_ID;
881+ btr_search_index_init(index);
882
883 error = dict_index_add_to_cache(table, index,
884 mtr_read_ulint(dict_hdr
885@@ -495,6 +498,8 @@
886 dict_mem_index_add_field(index, "ID", 0);
887
888 index->id = DICT_TABLE_IDS_ID;
889+ btr_search_index_init(index);
890+
891 error = dict_index_add_to_cache(table, index,
892 mtr_read_ulint(dict_hdr
893 + DICT_HDR_TABLE_IDS,
894@@ -528,6 +533,7 @@
895 dict_mem_index_add_field(index, "POS", 0);
896
897 index->id = DICT_COLUMNS_ID;
898+ btr_search_index_init(index);
899 error = dict_index_add_to_cache(table, index,
900 mtr_read_ulint(dict_hdr
901 + DICT_HDR_COLUMNS,
902@@ -574,6 +580,7 @@
903 dict_mem_index_add_field(index, "ID", 0);
904
905 index->id = DICT_INDEXES_ID;
906+ btr_search_index_init(index);
907 error = dict_index_add_to_cache(table, index,
908 mtr_read_ulint(dict_hdr
909 + DICT_HDR_INDEXES,
910@@ -602,6 +609,7 @@
911 dict_mem_index_add_field(index, "POS", 0);
912
913 index->id = DICT_FIELDS_ID;
914+ btr_search_index_init(index);
915 error = dict_index_add_to_cache(table, index,
916 mtr_read_ulint(dict_hdr
917 + DICT_HDR_FIELDS,
918
919=== modified file 'Percona-Server/storage/innobase/dict/dict0dict.c'
920--- Percona-Server/storage/innobase/dict/dict0dict.c 2013-08-14 03:52:04 +0000
921+++ Percona-Server/storage/innobase/dict/dict0dict.c 2013-09-02 14:07:43 +0000
922@@ -1972,7 +1972,7 @@
923 zero. */
924
925 for (;;) {
926- ulint ref_count = btr_search_info_get_ref_count(info, index->id);
927+ ulint ref_count = btr_search_info_get_ref_count(info, index);
928 if (ref_count == 0) {
929 break;
930 }
931@@ -2224,6 +2224,7 @@
932 new_index->n_user_defined_cols = index->n_fields;
933
934 new_index->id = index->id;
935+ btr_search_index_init(new_index);
936
937 /* Copy the fields of index */
938 dict_index_copy(new_index, index, table, 0, index->n_fields);
939@@ -2394,6 +2395,7 @@
940 new_index->n_user_defined_cols = index->n_fields;
941
942 new_index->id = index->id;
943+ btr_search_index_init(new_index);
944
945 /* Copy fields from index to new_index */
946 dict_index_copy(new_index, index, table, 0, index->n_fields);
947
948=== modified file 'Percona-Server/storage/innobase/dict/dict0load.c'
949--- Percona-Server/storage/innobase/dict/dict0load.c 2013-08-14 03:52:04 +0000
950+++ Percona-Server/storage/innobase/dict/dict0load.c 2013-09-02 14:07:43 +0000
951@@ -33,6 +33,7 @@
952
953 #include "btr0pcur.h"
954 #include "btr0btr.h"
955+#include "btr0sea.h"
956 #include "page0page.h"
957 #include "mach0data.h"
958 #include "dict0dict.h"
959@@ -1432,6 +1433,7 @@
960
961 (*index)->id = id;
962 (*index)->page = mach_read_from_4(field);
963+ btr_search_index_init(*index);
964 ut_ad((*index)->page);
965
966 return(NULL);
967
968=== modified file 'Percona-Server/storage/innobase/handler/ha_innodb.cc'
969--- Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-08-23 07:35:34 +0000
970+++ Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-09-02 14:07:43 +0000
971@@ -963,9 +963,14 @@
972 /*==============================*/
973 trx_t* trx) /*!< in: transaction handle */
974 {
975+<<<<<<< TREE
976 #ifdef UNIV_SYNC_DEBUG
977 ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
978 #endif /* UNIV_SYNC_DEBUG */
979+=======
980+ /* No-op in XtraDB */
981+ trx_search_latch_release_if_reserved(trx);
982+>>>>>>> MERGE-SOURCE
983
984 if (trx->declared_to_be_inside_innodb) {
985
986@@ -3564,9 +3569,8 @@
987 /* Since we will reserve the kernel mutex, we have to release
988 the search system latch first to obey the latching order. */
989
990- if (trx->has_search_latch) {
991- trx_search_latch_release_if_reserved(trx);
992- }
993+ /* No-op in XtraDB */
994+ trx_search_latch_release_if_reserved(trx);
995
996 if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
997 /* We cannot throw error here; instead we will catch this error
998@@ -3612,9 +3616,8 @@
999 /* Since we will reserve the kernel mutex, we have to release
1000 the search system latch first to obey the latching order. */
1001
1002- if (trx->has_search_latch) {
1003- trx_search_latch_release_if_reserved(trx);
1004- }
1005+ /* No-op in XtraDB */
1006+ trx_search_latch_release_if_reserved(trx);
1007
1008 if (trx->fake_changes && (all || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
1009 innobase_rollback(hton, thd, all); /* rollback implicitly */
1010@@ -12820,6 +12823,8 @@
1011 "Disable with --skip-innodb-adaptive-hash-index.",
1012 NULL, innodb_adaptive_hash_index_update, TRUE);
1013
1014+/* btr_search_index_num is constrained to machine word size for historical
1015+reasons. This limitation can be easily removed later. */
1016 static MYSQL_SYSVAR_ULONG(adaptive_hash_index_partitions, btr_search_index_num,
1017 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
1018 "Number of InnoDB adaptive hash index partitions (default 1: disable partitioning)",
1019
1020=== modified file 'Percona-Server/storage/innobase/ibuf/ibuf0ibuf.c'
1021--- Percona-Server/storage/innobase/ibuf/ibuf0ibuf.c 2013-08-14 03:52:04 +0000
1022+++ Percona-Server/storage/innobase/ibuf/ibuf0ibuf.c 2013-09-02 14:07:43 +0000
1023@@ -48,6 +48,7 @@
1024 #include "btr0cur.h"
1025 #include "btr0pcur.h"
1026 #include "btr0btr.h"
1027+#include "btr0sea.h"
1028 #include "row0upd.h"
1029 #include "sync0sync.h"
1030 #include "dict0boot.h"
1031@@ -631,6 +632,7 @@
1032 dict_mem_index_add_field(index, "DUMMY_COLUMN", 0);
1033
1034 index->id = DICT_IBUF_ID_MIN + IBUF_SPACE_ID;
1035+ btr_search_index_init(index);
1036
1037 error = dict_index_add_to_cache(table, index,
1038 FSP_IBUF_TREE_ROOT_PAGE_NO, FALSE);
1039
1040=== modified file 'Percona-Server/storage/innobase/include/btr0sea.h'
1041--- Percona-Server/storage/innobase/include/btr0sea.h 2013-08-14 03:52:04 +0000
1042+++ Percona-Server/storage/innobase/include/btr0sea.h 2013-09-02 14:07:43 +0000
1043@@ -86,7 +86,7 @@
1044 btr_search_info_get_ref_count(
1045 /*==========================*/
1046 btr_search_t* info, /*!< in: search info. */
1047- index_id_t key);
1048+ dict_index_t* index); /*!< in: index */
1049 /*********************************************************************//**
1050 Updates the search info. */
1051 UNIV_INLINE
1052@@ -204,15 +204,35 @@
1053 New functions to control split btr_search_index */
1054 UNIV_INLINE
1055 hash_table_t*
1056-btr_search_get_hash_index(
1057+btr_search_get_hash_table(
1058 /*======================*/
1059- index_id_t key);
1060+ const dict_index_t* index) /*!< in: index */
1061+ __attribute__((nonnull,pure,warn_unused_result));
1062
1063 UNIV_INLINE
1064 rw_lock_t*
1065 btr_search_get_latch(
1066 /*=================*/
1067- index_id_t key);
1068+ const dict_index_t* index) /*!< in: index */
1069+ __attribute__((nonnull,pure,warn_unused_result));
1070+
1071+/*********************************************************************//**
1072+Returns the AHI partition number corresponding to a give index ID. */
1073+UNIV_INLINE
1074+ulint
1075+btr_search_get_key(
1076+/*===============*/
1077+ index_id_t index_id) /*!< in: index ID */
1078+ __attribute__((pure,warn_unused_result));
1079+
1080+/*********************************************************************//**
1081+Initializes AHI-related fields in a newly created index. */
1082+UNIV_INLINE
1083+void
1084+btr_search_index_init(
1085+/*===============*/
1086+ dict_index_t* index) /*!< in: index */
1087+ __attribute__((nonnull));
1088
1089 UNIV_INLINE
1090 void
1091@@ -224,15 +244,16 @@
1092 btr_search_x_unlock_all(void);
1093 /*==========================*/
1094
1095-UNIV_INLINE
1096-void
1097-btr_search_s_lock_all(void);
1098-/*========================*/
1099-
1100-UNIV_INLINE
1101-void
1102-btr_search_s_unlock_all(void);
1103-/*==========================*/
1104+#ifdef UNIV_SYNC_DEBUG
1105+/********************************************************************//**
1106+Checks if the thread owns any adaptive hash latches in either S or X mode.
1107+@return TRUE if the thread owns at least one latch in any mode. */
1108+UNIV_INLINE
1109+ibool
1110+btr_search_own_any(void)
1111+/*=====================*/
1112+ __attribute__((warn_unused_result));
1113+#endif
1114
1115 /** The search info struct in an index */
1116 struct btr_search_struct{
1117@@ -294,8 +315,8 @@
1118
1119 /** The hash index system */
1120 struct btr_search_sys_struct{
1121- hash_table_t** hash_index; /*!< the adaptive hash index,
1122- mapping dtuple_fold values
1123+ hash_table_t** hash_tables; /*!< the array of adaptive hash index,
1124+ tables mapping dtuple_fold values
1125 to rec_t pointers on index pages */
1126 };
1127
1128
1129=== modified file 'Percona-Server/storage/innobase/include/btr0sea.ic'
1130--- Percona-Server/storage/innobase/include/btr0sea.ic 2013-08-02 09:40:55 +0000
1131+++ Percona-Server/storage/innobase/include/btr0sea.ic 2013-09-02 14:07:43 +0000
1132@@ -87,20 +87,55 @@
1133 New functions to control split btr_search_index */
1134 UNIV_INLINE
1135 hash_table_t*
1136-btr_search_get_hash_index(
1137+btr_search_get_hash_table(
1138 /*======================*/
1139- index_id_t key)
1140+ const dict_index_t* index) /*!< in: index */
1141 {
1142- return(btr_search_sys->hash_index[key % btr_search_index_num]);
1143+ ut_ad(index);
1144+ ut_ad(index->search_table);
1145+
1146+ return(index->search_table);
1147 }
1148
1149 UNIV_INLINE
1150 rw_lock_t*
1151 btr_search_get_latch(
1152 /*=================*/
1153- index_id_t key)
1154-{
1155- return(btr_search_latch_part[key % btr_search_index_num]);
1156+ const dict_index_t* index) /*!< in: index */
1157+{
1158+ ut_ad(index);
1159+ ut_ad(index->search_latch >= btr_search_latch_arr &&
1160+ index->search_latch < btr_search_latch_arr +
1161+ btr_search_index_num);
1162+
1163+ return(index->search_latch);
1164+}
1165+
1166+/*********************************************************************//**
1167+Returns the AHI partition number corresponding to a give index ID. */
1168+UNIV_INLINE
1169+ulint
1170+btr_search_get_key(
1171+/*===============*/
1172+ index_id_t index_id) /*!< in: index ID */
1173+{
1174+ return(index_id % btr_search_index_num);
1175+}
1176+
1177+/*********************************************************************//**
1178+Initializes AHI-related fields in a newly created index. */
1179+UNIV_INLINE
1180+void
1181+btr_search_index_init(
1182+/*===============*/
1183+ dict_index_t* index) /*!< in: index */
1184+{
1185+ ut_ad(index);
1186+
1187+ index->search_latch =
1188+ &btr_search_latch_arr[btr_search_get_key(index->id)];
1189+ index->search_table =
1190+ btr_search_sys->hash_tables[btr_search_get_key(index->id)];
1191 }
1192
1193 UNIV_INLINE
1194@@ -111,7 +146,7 @@
1195 ulint i;
1196
1197 for (i = 0; i < btr_search_index_num; i++) {
1198- rw_lock_x_lock(btr_search_latch_part[i]);
1199+ rw_lock_x_lock(&btr_search_latch_arr[i]);
1200 }
1201 }
1202
1203@@ -123,31 +158,28 @@
1204 ulint i;
1205
1206 for (i = 0; i < btr_search_index_num; i++) {
1207- rw_lock_x_unlock(btr_search_latch_part[i]);
1208- }
1209-}
1210-
1211-UNIV_INLINE
1212-void
1213-btr_search_s_lock_all(void)
1214-/*=======================*/
1215-{
1216- ulint i;
1217-
1218- for (i = 0; i < btr_search_index_num; i++) {
1219- rw_lock_s_lock(btr_search_latch_part[i]);
1220- }
1221-}
1222-
1223-UNIV_INLINE
1224-void
1225-btr_search_s_unlock_all(void)
1226-/*=========================*/
1227-{
1228- ulint i;
1229-
1230- for (i = 0; i < btr_search_index_num; i++) {
1231- rw_lock_s_unlock(btr_search_latch_part[i]);
1232- }
1233-}
1234-
1235+ rw_lock_x_unlock(&btr_search_latch_arr[i]);
1236+ }
1237+}
1238+
1239+#ifdef UNIV_SYNC_DEBUG
1240+/********************************************************************//**
1241+Checks if the thread owns any adaptive hash latches in either S or X mode.
1242+@return TRUE if the thread owns at least one latch in any mode. */
1243+UNIV_INLINE
1244+ibool
1245+btr_search_own_any(void)
1246+/*====================*/
1247+{
1248+ ulint i;
1249+
1250+ for (i = 0; i < btr_search_index_num; i++) {
1251+ if (rw_lock_own(&btr_search_latch_arr[i], RW_LOCK_SHARED) ||
1252+ rw_lock_own(&btr_search_latch_arr[i], RW_LOCK_EX)) {
1253+ return(TRUE);
1254+ }
1255+ }
1256+
1257+ return(FALSE);
1258+}
1259+#endif
1260
1261=== modified file 'Percona-Server/storage/innobase/include/btr0types.h'
1262--- Percona-Server/storage/innobase/include/btr0types.h 2013-08-02 09:40:55 +0000
1263+++ Percona-Server/storage/innobase/include/btr0types.h 2013-09-02 14:07:43 +0000
1264@@ -41,22 +41,21 @@
1265
1266 #ifndef UNIV_HOTBACKUP
1267
1268-/** @brief The latch protecting the adaptive search system
1269+/** @brief The array of latches protecting the adaptive search partitions
1270
1271-This latch protects the
1272-(1) hash index;
1273+These latch protect the
1274+(1) hash index from the corresponding AHI partition;
1275 (2) columns of a record to which we have a pointer in the hash index;
1276
1277-but does NOT protect:
1278+but do NOT protect:
1279
1280 (3) next record offset field in a record;
1281 (4) next or previous records on the same page.
1282
1283-Bear in mind (3) and (4) when using the hash index.
1284+Bear in mind (3) and (4) when using the hash indexes.
1285 */
1286-//extern rw_lock_t* btr_search_latch_temp;
1287
1288-extern rw_lock_t** btr_search_latch_part;
1289+extern rw_lock_t* btr_search_latch_arr;
1290
1291 #endif /* UNIV_HOTBACKUP */
1292
1293
1294=== modified file 'Percona-Server/storage/innobase/include/buf0buf.h'
1295--- Percona-Server/storage/innobase/include/buf0buf.h 2013-08-16 08:58:49 +0000
1296+++ Percona-Server/storage/innobase/include/buf0buf.h 2013-09-02 14:07:43 +0000
1297@@ -1714,7 +1714,6 @@
1298 complete, though: there may
1299 have been hash collisions,
1300 record deletions, etc. */
1301- volatile rw_lock_t* btr_search_latch;
1302 /* @} */
1303 # ifdef UNIV_SYNC_DEBUG
1304 /** @name Debug fields */
1305
1306=== modified file 'Percona-Server/storage/innobase/include/dict0mem.h'
1307--- Percona-Server/storage/innobase/include/dict0mem.h 2013-06-27 15:35:20 +0000
1308+++ Percona-Server/storage/innobase/include/dict0mem.h 2013-09-02 14:07:43 +0000
1309@@ -365,6 +365,10 @@
1310 initialized to 0, NULL or FALSE in dict_mem_index_create(). */
1311 struct dict_index_struct{
1312 index_id_t id; /*!< id of the index */
1313+ rw_lock_t* search_latch; /*!< latch protecting the AHI partition
1314+ corresponding to this index */
1315+ hash_table_t* search_table; /*!< hash table protected by
1316+ search_latch */
1317 mem_heap_t* heap; /*!< memory heap */
1318 const char* name; /*!< index name */
1319 const char* table_name;/*!< table name */
1320
1321=== modified file 'Percona-Server/storage/innobase/include/trx0trx.h'
1322--- Percona-Server/storage/innobase/include/trx0trx.h 2013-08-14 03:52:04 +0000
1323+++ Percona-Server/storage/innobase/include/trx0trx.h 2013-09-02 14:07:43 +0000
1324@@ -49,12 +49,14 @@
1325 extern ulint trx_n_prepared;
1326
1327 /********************************************************************//**
1328-Releases the search latch if trx has reserved it. */
1329-UNIV_INTERN
1330+In XtraDB it is impossible for a transaction to own a search latch outside of
1331+InnoDB code, so there is nothing to release on demand. We keep this function to
1332+simplify maintenance.*/
1333+UNIV_INLINE
1334 void
1335 trx_search_latch_release_if_reserved(
1336 /*=================================*/
1337- trx_t* trx); /*!< in: transaction */
1338+ trx_t* trx __attribute__((unused))); /*!< in: transaction */
1339 /******************************************************************//**
1340 Set detailed error message for the transaction. */
1341 UNIV_INTERN
1342@@ -555,8 +557,8 @@
1343 in that case we must flush the log
1344 in trx_commit_complete_for_mysql() */
1345 ulint duplicates; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */
1346- ulint has_search_latch;
1347- /* TRUE if this trx has latched the
1348+ ibool has_search_latch;
1349+ /* TRUE if this trx has latched any
1350 search system latch in S-mode */
1351 ulint deadlock_mark; /*!< a mark field used in deadlock
1352 checking algorithm. */
1353
1354=== modified file 'Percona-Server/storage/innobase/include/trx0trx.ic'
1355--- Percona-Server/storage/innobase/include/trx0trx.ic 2013-08-02 09:40:55 +0000
1356+++ Percona-Server/storage/innobase/include/trx0trx.ic 2013-09-02 14:07:43 +0000
1357@@ -23,6 +23,19 @@
1358 Created 3/26/1996 Heikki Tuuri
1359 *******************************************************/
1360
1361+/********************************************************************//**
1362+In XtraDB it is impossible for a transaction to own a search latch outside of
1363+InnoDB code, so there is nothing to release on demand. We keep this function to
1364+simplify maintenance.*/
1365+UNIV_INLINE
1366+void
1367+trx_search_latch_release_if_reserved(
1368+/*=================================*/
1369+ trx_t* trx __attribute__((unused))) /*!< in: transaction */
1370+{
1371+ ut_ad(!trx->has_search_latch);
1372+}
1373+
1374 /*************************************************************//**
1375 Starts the transaction if it is not yet started. */
1376 UNIV_INLINE
1377
1378=== modified file 'Percona-Server/storage/innobase/row/row0mysql.c'
1379--- Percona-Server/storage/innobase/row/row0mysql.c 2013-08-14 03:52:04 +0000
1380+++ Percona-Server/storage/innobase/row/row0mysql.c 2013-09-02 14:07:43 +0000
1381@@ -2664,7 +2664,9 @@
1382 /* check adaptive hash entries */
1383 index = dict_table_get_first_index(table);
1384 while (index) {
1385- ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
1386+ ulint ref_count =
1387+ btr_search_info_get_ref_count(
1388+ index->search_info, index);
1389 if (ref_count) {
1390 fprintf(stderr, "InnoDB: Warning:"
1391 " hash index ref_count (%lu) is not zero"
1392@@ -3025,7 +3027,9 @@
1393 table->space = space;
1394 index = dict_table_get_first_index(table);
1395 do {
1396- ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
1397+ ulint ref_count =
1398+ btr_search_info_get_ref_count(
1399+ index->search_info, index);
1400 /* check adaptive hash entries */
1401 if (ref_count) {
1402 fprintf(stderr, "InnoDB: Warning:"
1403
1404=== modified file 'Percona-Server/storage/innobase/row/row0sel.c'
1405--- Percona-Server/storage/innobase/row/row0sel.c 2013-08-14 03:52:04 +0000
1406+++ Percona-Server/storage/innobase/row/row0sel.c 2013-09-02 14:07:43 +0000
1407@@ -1224,7 +1224,7 @@
1408 ut_ad(plan->unique_search);
1409 ut_ad(!plan->must_get_clust);
1410 #ifdef UNIV_SYNC_DEBUG
1411- ut_ad(rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
1412+ ut_ad(rw_lock_own(btr_search_get_latch(index), RW_LOCK_SHARED));
1413 #endif /* UNIV_SYNC_DEBUG */
1414
1415 row_sel_open_pcur(plan, TRUE, mtr);
1416@@ -1395,10 +1395,11 @@
1417 && !plan->must_get_clust
1418 && !plan->table->big_rows) {
1419 if (!search_latch_locked) {
1420- rw_lock_s_lock(btr_search_get_latch(index->id));
1421+ rw_lock_s_lock(btr_search_get_latch(index));
1422
1423 search_latch_locked = TRUE;
1424- } else if (rw_lock_get_writer(btr_search_get_latch(index->id)) == RW_LOCK_WAIT_EX) {
1425+ } else if (rw_lock_get_writer(btr_search_get_latch(index))
1426+ == RW_LOCK_WAIT_EX) {
1427
1428 /* There is an x-latch request waiting: release the
1429 s-latch for a moment; as an s-latch here is often
1430@@ -1407,8 +1408,8 @@
1431 from acquiring an s-latch for a long time, lowering
1432 performance significantly in multiprocessors. */
1433
1434- rw_lock_s_unlock(btr_search_get_latch(index->id));
1435- rw_lock_s_lock(btr_search_get_latch(index->id));
1436+ rw_lock_s_unlock(btr_search_get_latch(index));
1437+ rw_lock_s_lock(btr_search_get_latch(index));
1438 }
1439
1440 found_flag = row_sel_try_search_shortcut(node, plan, &mtr);
1441@@ -1431,7 +1432,7 @@
1442 }
1443
1444 if (search_latch_locked) {
1445- rw_lock_s_unlock(btr_search_get_latch(index->id));
1446+ rw_lock_s_unlock(btr_search_get_latch(index));
1447
1448 search_latch_locked = FALSE;
1449 }
1450@@ -2007,7 +2008,7 @@
1451
1452 func_exit:
1453 if (search_latch_locked) {
1454- rw_lock_s_unlock(btr_search_get_latch(index->id));
1455+ rw_lock_s_unlock(btr_search_get_latch(index));
1456 }
1457 if (UNIV_LIKELY_NULL(heap)) {
1458 mem_heap_free(heap);
1459@@ -2744,6 +2745,9 @@
1460 heap */
1461
1462 ut_a(!prebuilt->trx->has_search_latch);
1463+#ifdef UNIV_SYNC_DEBUG
1464+ ut_ad(!btr_search_own_any());
1465+#endif
1466
1467 if (UNIV_UNLIKELY(templ->type == DATA_BLOB)) {
1468 if (prebuilt->blob_heap == NULL) {
1469@@ -3320,6 +3324,8 @@
1470 ut_ad(!prebuilt->templ_contains_blob);
1471
1472 #ifndef UNIV_SEARCH_DEBUG
1473+ ut_ad(trx->has_search_latch);
1474+
1475 btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
1476 BTR_SEARCH_LEAF, pcur,
1477 RW_S_LATCH,
1478@@ -3420,8 +3426,6 @@
1479 /* if the returned record was locked and we did a semi-consistent
1480 read (fetch the newest committed version), then this is set to
1481 TRUE */
1482- ulint i;
1483- ulint should_release;
1484 #ifdef UNIV_SEARCH_DEBUG
1485 ulint cnt = 0;
1486 #endif /* UNIV_SEARCH_DEBUG */
1487@@ -3438,6 +3442,12 @@
1488
1489 ut_ad(index && pcur && search_tuple);
1490
1491+ ut_ad(!trx->has_search_latch);
1492+#ifdef UNIV_SYNC_DEBUG
1493+ ut_ad(!btr_search_own_any());
1494+ ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
1495+#endif /* UNIV_SYNC_DEBUG */
1496+
1497 if (UNIV_UNLIKELY(prebuilt->table->ibd_file_missing)) {
1498 ut_print_timestamp(stderr);
1499 fprintf(stderr, " InnoDB: Error:\n"
1500@@ -3453,24 +3463,15 @@
1501 "InnoDB: how you can resolve the problem.\n",
1502 prebuilt->table->name);
1503
1504-#ifdef UNIV_SYNC_DEBUG
1505- ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
1506-#endif /* UNIV_SYNC_DEBUG */
1507 return(DB_ERROR);
1508 }
1509
1510 if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
1511
1512-#ifdef UNIV_SYNC_DEBUG
1513- ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
1514-#endif /* UNIV_SYNC_DEBUG */
1515 return(DB_MISSING_HISTORY);
1516 }
1517
1518 if (dict_index_is_corrupted(index)) {
1519-#ifdef UNIV_SYNC_DEBUG
1520- ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
1521-#endif /* UNIV_SYNC_DEBUG */
1522 return(DB_CORRUPTION);
1523 }
1524
1525@@ -3515,38 +3516,6 @@
1526 fprintf(stderr, "N tables locked %lu\n",
1527 (ulong) trx->mysql_n_tables_locked);
1528 #endif
1529- /*-------------------------------------------------------------*/
1530- /* PHASE 0: Release a possible s-latch we are holding on the
1531- adaptive hash index latch if there is someone waiting behind */
1532-
1533- should_release = 0;
1534- for (i = 0; i < btr_search_index_num; i++) {
1535- /* we should check all latches (fix Bug#791030) */
1536- if (UNIV_UNLIKELY(rw_lock_get_writer(btr_search_latch_part[i])
1537- != RW_LOCK_NOT_LOCKED)) {
1538- should_release |= ((ulint)1 << i);
1539- }
1540- }
1541-
1542- if (UNIV_UNLIKELY(should_release)) {
1543-
1544- /* There is an x-latch request on the adaptive hash index:
1545- release the s-latch to reduce starvation and wait for
1546- BTR_SEA_TIMEOUT rounds before trying to keep it again over
1547- calls from MySQL */
1548-
1549- for (i = 0; i < btr_search_index_num; i++) {
1550- /* we should release all s-latches (fix Bug#791030) */
1551- if (trx->has_search_latch & ((ulint)1 << i)) {
1552- rw_lock_s_unlock(btr_search_latch_part[i]);
1553- trx->has_search_latch &= (~((ulint)1 << i));
1554- }
1555- }
1556-
1557- if (!trx->has_search_latch) {
1558- trx->search_latch_timeout = BTR_SEA_TIMEOUT;
1559- }
1560- }
1561
1562 /* Reset the new record lock info if srv_locks_unsafe_for_binlog
1563 is set or session is using a READ COMMITED isolation level. Then
1564@@ -3696,29 +3665,9 @@
1565 hash index semaphore! */
1566
1567 #ifndef UNIV_SEARCH_DEBUG
1568- if (!(trx->has_search_latch
1569- & ((ulint)1 << (index->id % btr_search_index_num)))) {
1570- if (trx->has_search_latch
1571- < ((ulint)1 << (index->id % btr_search_index_num))) {
1572- rw_lock_s_lock(btr_search_get_latch(index->id));
1573- trx->has_search_latch |=
1574- ((ulint)1 << (index->id % btr_search_index_num));
1575- } else {
1576- /* should re-lock to obay latch-order */
1577- for (i = 0; i < btr_search_index_num; i++) {
1578- if (trx->has_search_latch & ((ulint)1 << i)) {
1579- rw_lock_s_unlock(btr_search_latch_part[i]);
1580- }
1581- }
1582- trx->has_search_latch |=
1583- ((ulint)1 << (index->id % btr_search_index_num));
1584- for (i = 0; i < btr_search_index_num; i++) {
1585- if (trx->has_search_latch & ((ulint)1 << i)) {
1586- rw_lock_s_lock(btr_search_latch_part[i]);
1587- }
1588- }
1589- }
1590- }
1591+ ut_ad(!trx->has_search_latch);
1592+ rw_lock_s_lock(btr_search_get_latch(index));
1593+ trx->has_search_latch = TRUE;
1594 #endif
1595 switch (row_sel_try_search_shortcut_for_mysql(
1596 &rec, prebuilt, &offsets, &heap,
1597@@ -3763,7 +3712,7 @@
1598 srv_n_rows_read++;
1599
1600 err = DB_SUCCESS;
1601- goto release_search_latch_if_needed;
1602+ goto release_search_latch;
1603
1604 case SEL_EXHAUSTED:
1605 mtr_commit(&mtr);
1606@@ -3772,19 +3721,10 @@
1607 fputs(" record not found 2\n", stderr); */
1608
1609 err = DB_RECORD_NOT_FOUND;
1610-release_search_latch_if_needed:
1611- if (trx->search_latch_timeout > 0
1612- && trx->has_search_latch) {
1613-
1614- trx->search_latch_timeout--;
1615-
1616- for (i = 0; i < btr_search_index_num; i++) {
1617- if (trx->has_search_latch & ((ulint)1 << i)) {
1618- rw_lock_s_unlock(btr_search_latch_part[i]);
1619- }
1620- }
1621- trx->has_search_latch = FALSE;
1622- }
1623+release_search_latch:
1624+ rw_lock_s_unlock(
1625+ btr_search_get_latch(index));
1626+ trx->has_search_latch = FALSE;
1627
1628 /* NOTE that we do NOT store the cursor
1629 position */
1630@@ -3799,22 +3739,19 @@
1631
1632 mtr_commit(&mtr);
1633 mtr_start(&mtr);
1634+
1635+ rw_lock_s_unlock(btr_search_get_latch(index));
1636+ trx->has_search_latch = FALSE;
1637 }
1638 }
1639
1640 /*-------------------------------------------------------------*/
1641 /* PHASE 3: Open or restore index cursor position */
1642
1643- if (trx->has_search_latch) {
1644-
1645- for (i = 0; i < btr_search_index_num; i++) {
1646- if (trx->has_search_latch & ((ulint)1 << i)) {
1647- rw_lock_s_unlock(btr_search_latch_part[i]);
1648- }
1649- }
1650- trx->has_search_latch = FALSE;
1651- }
1652-
1653+ ut_ad(!trx->has_search_latch);
1654+#ifdef UNIV_SYNC_DEBUG
1655+ ut_ad(!btr_search_own_any());
1656+#endif
1657 ut_ad(prebuilt->sql_stat_start || trx->state == TRX_ACTIVE);
1658 ut_ad(trx->state == TRX_NOT_STARTED
1659 || trx->state == TRX_ACTIVE);
1660@@ -4851,7 +4788,9 @@
1661 }
1662 }
1663
1664+ ut_ad(!trx->has_search_latch);
1665 #ifdef UNIV_SYNC_DEBUG
1666+ ut_ad(!btr_search_own_any());
1667 ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
1668 #endif /* UNIV_SYNC_DEBUG */
1669 return(err);
1670
1671=== modified file 'Percona-Server/storage/innobase/srv/srv0srv.c'
1672--- Percona-Server/storage/innobase/srv/srv0srv.c 2013-08-14 03:52:04 +0000
1673+++ Percona-Server/storage/innobase/srv/srv0srv.c 2013-09-02 14:07:43 +0000
1674@@ -1275,8 +1275,10 @@
1675 os_thread_yield();
1676 goto retry;
1677 }
1678- if (trx->has_search_latch
1679- || NULL != UT_LIST_GET_FIRST(trx->trx_locks)) {
1680+
1681+ ut_ad(!trx->has_search_latch);
1682+
1683+ if (NULL != UT_LIST_GET_FIRST(trx->trx_locks)) {
1684
1685 conc_n_threads = os_atomic_increment_lint(&srv_conc_n_threads, 1);
1686 enter_innodb_with_tickets(trx);
1687@@ -1319,7 +1321,9 @@
1688 ulint sec;
1689 ulint ms;
1690
1691+ ut_ad(!trx->has_search_latch);
1692 #ifdef UNIV_SYNC_DEBUG
1693+ ut_ad(!btr_search_own_any());
1694 ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
1695 #endif /* UNIV_SYNC_DEBUG */
1696
1697@@ -1379,7 +1383,9 @@
1698 /* If the transaction is not holding resources, let it sleep
1699 for SRV_THREAD_SLEEP_DELAY microseconds, and try again then */
1700
1701- if (!has_slept && !trx->has_search_latch
1702+ ut_ad(!trx->has_search_latch);
1703+
1704+ if (!has_slept
1705 && NULL == UT_LIST_GET_FIRST(trx->trx_locks)) {
1706
1707 has_slept = TRUE; /* We let it sleep only once to avoid
1708@@ -1434,10 +1440,8 @@
1709 return;
1710 }
1711
1712- /* Release possible search system latch this thread has */
1713- if (trx->has_search_latch) {
1714- trx_search_latch_release_if_reserved(trx);
1715- }
1716+ /* No-op for XtraDB. */
1717+ trx_search_latch_release_if_reserved(trx);
1718
1719 /* Add to the queue */
1720 slot->reserved = TRUE;
1721@@ -1456,6 +1460,7 @@
1722
1723 ut_ad(!trx->has_search_latch);
1724 #ifdef UNIV_SYNC_DEBUG
1725+ ut_ad(!btr_search_own_any());
1726 ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
1727 #endif /* UNIV_SYNC_DEBUG */
1728
1729@@ -1507,7 +1512,9 @@
1730 trx_t* trx) /*!< in: transaction object associated with the
1731 thread */
1732 {
1733+ ut_ad(!trx->has_search_latch);
1734 #ifdef UNIV_SYNC_DEBUG
1735+ ut_ad(!btr_search_own_any());
1736 ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
1737 #endif /* UNIV_SYNC_DEBUG */
1738
1739@@ -1598,7 +1605,9 @@
1740 os_event_set(slot->event);
1741 }
1742
1743+ ut_ad(!trx->has_search_latch);
1744 #ifdef UNIV_SYNC_DEBUG
1745+ ut_ad(!btr_search_own_any());
1746 ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
1747 #endif /* UNIV_SYNC_DEBUG */
1748 }
1749@@ -1612,7 +1621,9 @@
1750 trx_t* trx) /*!< in: transaction object associated with the
1751 thread */
1752 {
1753+ ut_ad(!trx->has_search_latch);
1754 #ifdef UNIV_SYNC_DEBUG
1755+ ut_ad(!btr_search_own_any());
1756 ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
1757 #endif /* UNIV_SYNC_DEBUG */
1758
1759@@ -1885,7 +1896,9 @@
1760 os_event_wait(event);
1761 thd_wait_end(trx->mysql_thd);
1762
1763+ ut_ad(!trx->has_search_latch);
1764 #ifdef UNIV_SYNC_DEBUG
1765+ ut_ad(!btr_search_own_any());
1766 ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
1767 #endif /* UNIV_SYNC_DEBUG */
1768
1769@@ -2047,7 +2060,8 @@
1770 ulint n_reserved;
1771 ibool ret;
1772
1773- ulint btr_search_sys_subtotal;
1774+ ulong btr_search_sys_constant;
1775+ ulong btr_search_sys_variable;
1776 ulint lock_sys_subtotal;
1777 ulint recv_sys_subtotal;
1778
1779@@ -2113,7 +2127,7 @@
1780 ibuf_print(file);
1781
1782 for (i = 0; i < btr_search_index_num; i++) {
1783- ha_print_info(file, btr_search_get_hash_index((index_id_t)i));
1784+ ha_print_info(file, btr_search_sys->hash_tables[i]);
1785 }
1786
1787 fprintf(file,
1788@@ -2141,16 +2155,28 @@
1789 fprintf(file,
1790 "Total memory allocated by read views " ULINTPF "\n",
1791 srv_read_views_memory);
1792- /* Calcurate reserved memories */
1793- if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
1794- btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index[0]->heap);
1795- } else {
1796- btr_search_sys_subtotal = 0;
1797- for (i=0; i < btr_search_sys->hash_index[0]->n_mutexes; i++) {
1798- btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index[0]->heaps[i]);
1799- }
1800+
1801+ /* Calculate AHI constant and variable memory allocations */
1802+
1803+ btr_search_sys_constant = 0;
1804+ btr_search_sys_variable = 0;
1805+
1806+ ut_ad(btr_search_sys->hash_tables);
1807+
1808+ for (i = 0; i < btr_search_index_num; i++) {
1809+ hash_table_t* ht = btr_search_sys->hash_tables[i];
1810+
1811+ ut_ad(ht);
1812+ ut_ad(ht->heap);
1813+
1814+ /* Multiple mutexes/heaps are currently never used for adaptive
1815+ hash index tables. */
1816+ ut_ad(!ht->n_mutexes);
1817+ ut_ad(!ht->heaps);
1818+
1819+ btr_search_sys_variable += mem_heap_get_size(ht->heap);
1820+ btr_search_sys_constant += ht->n_cells * sizeof(hash_cell_t);
1821 }
1822- btr_search_sys_subtotal *= btr_search_index_num;
1823
1824 lock_sys_subtotal = 0;
1825 if (trx_sys) {
1826@@ -2175,12 +2201,9 @@
1827 " Lock system %lu \t(%lu + %lu)\n"
1828 " Recovery system %lu \t(%lu + %lu)\n",
1829
1830- (ulong) (btr_search_sys
1831- ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0)
1832- + btr_search_sys_subtotal,
1833- (ulong) (btr_search_sys
1834- ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0),
1835- (ulong) btr_search_sys_subtotal,
1836+ btr_search_sys_constant + btr_search_sys_variable,
1837+ btr_search_sys_constant,
1838+ btr_search_sys_variable,
1839
1840 (ulong) (buf_pool_from_array(0)->page_hash->n_cells * sizeof(hash_cell_t)),
1841
1842@@ -2342,17 +2365,22 @@
1843 buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len);
1844 buf_get_total_list_size_in_bytes(&buf_pools_list_size);
1845
1846- if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
1847- mem_adaptive_hash = mem_heap_get_size(btr_search_sys->hash_index[0]->heap);
1848- } else {
1849- mem_adaptive_hash = 0;
1850- for (i=0; i < btr_search_sys->hash_index[0]->n_mutexes; i++) {
1851- mem_adaptive_hash += mem_heap_get_size(btr_search_sys->hash_index[0]->heaps[i]);
1852- }
1853- }
1854- mem_adaptive_hash *= btr_search_index_num;
1855- if (btr_search_sys) {
1856- mem_adaptive_hash += (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t));
1857+ mem_adaptive_hash = 0;
1858+
1859+ ut_ad(btr_search_sys->hash_tables);
1860+
1861+ for (i = 0; i < btr_search_index_num; i++) {
1862+ hash_table_t* ht = btr_search_sys->hash_tables[i];
1863+
1864+ ut_ad(ht);
1865+ ut_ad(ht->heap);
1866+ /* Multiple mutexes/heaps are currently never used for adaptive
1867+ hash index tables. */
1868+ ut_ad(!ht->n_mutexes);
1869+ ut_ad(!ht->heaps);
1870+
1871+ mem_adaptive_hash += mem_heap_get_size(ht->heap);
1872+ mem_adaptive_hash += ht->n_cells * sizeof(hash_cell_t);
1873 }
1874
1875 mem_dictionary = (dict_sys ? ((dict_sys->table_hash->n_cells
1876@@ -2365,7 +2393,7 @@
1877 export_vars.innodb_adaptive_hash_cells = 0;
1878 export_vars.innodb_adaptive_hash_heap_buffers = 0;
1879 for (i = 0; i < btr_search_index_num; i++) {
1880- hash_table_t* table = btr_search_get_hash_index((index_id_t)i);
1881+ hash_table_t* table = btr_search_sys->hash_tables[i];
1882
1883 export_vars.innodb_adaptive_hash_cells
1884 += hash_get_n_cells(table);
1885
1886=== modified file 'Percona-Server/storage/innobase/trx/trx0trx.c'
1887--- Percona-Server/storage/innobase/trx/trx0trx.c 2013-08-14 03:52:04 +0000
1888+++ Percona-Server/storage/innobase/trx/trx0trx.c 2013-09-02 14:07:43 +0000
1889@@ -386,27 +386,6 @@
1890 }
1891
1892 /********************************************************************//**
1893-Releases the search latch if trx has reserved it. */
1894-UNIV_INTERN
1895-void
1896-trx_search_latch_release_if_reserved(
1897-/*=================================*/
1898- trx_t* trx) /*!< in: transaction */
1899-{
1900- ulint i;
1901-
1902- if (trx->has_search_latch) {
1903- for (i = 0; i < btr_search_index_num; i++) {
1904- if (trx->has_search_latch & ((ulint)1 << i)) {
1905- rw_lock_s_unlock(btr_search_latch_part[i]);
1906- }
1907- }
1908-
1909- trx->has_search_latch = FALSE;
1910- }
1911-}
1912-
1913-/********************************************************************//**
1914 Frees a transaction object. */
1915 UNIV_INTERN
1916 void
1917@@ -468,6 +447,9 @@
1918 ut_a(UT_LIST_GET_LEN(trx->wait_thrs) == 0);
1919
1920 ut_a(!trx->has_search_latch);
1921+#ifdef UNIV_SYNC_DEBUG
1922+ ut_ad(!btr_search_own_any());
1923+#endif
1924
1925 ut_a(trx->dict_operation_lock_mode == 0);
1926
1927@@ -527,6 +509,9 @@
1928 ut_a(UT_LIST_GET_LEN(trx->wait_thrs) == 0);
1929
1930 ut_a(!trx->has_search_latch);
1931+#ifdef UNIV_SYNC_DEBUG
1932+ ut_ad(!btr_search_own_any());
1933+#endif
1934
1935 ut_a(trx->dict_operation_lock_mode == 0);
1936

Subscribers

People subscribed via source and target branches