Merge lp:~stewart/drizzle/7.1-innodb-from-mysql-5.5.10 into lp:drizzle/7.1
- 7.1-innodb-from-mysql-5.5.10
- Merge into 7.1
Status: | Merged |
---|---|
Merged at revision: | 2550 |
Proposed branch: | lp:~stewart/drizzle/7.1-innodb-from-mysql-5.5.10 |
Merge into: | lp:drizzle/7.1 |
Prerequisite: | lp:~stewart/drizzle/7.1-innodb-1.1.5 |
Diff against target: |
2942 lines (+915/-561) 40 files modified
plugin/innobase/btr/btr0btr.cc (+1/-1) plugin/innobase/btr/btr0cur.cc (+239/-84) plugin/innobase/btr/btr0sea.cc (+1/-1) plugin/innobase/buf/buf0buddy.cc (+1/-1) plugin/innobase/buf/buf0buf.cc (+26/-26) plugin/innobase/buf/buf0lru.cc (+7/-39) plugin/innobase/dict/dict0dict.cc (+10/-0) plugin/innobase/dict/dict0load.cc (+1/-1) plugin/innobase/fsp/fsp0fsp.cc (+4/-4) plugin/innobase/handler/ha_innodb.cc (+110/-7) plugin/innobase/ibuf/ibuf0ibuf.cc (+5/-22) plugin/innobase/include/btr0cur.h (+41/-6) plugin/innobase/include/buf0buf.h (+7/-7) plugin/innobase/include/buf0lru.h (+4/-8) plugin/innobase/include/dict0mem.h (+6/-0) plugin/innobase/include/dict0types.h (+0/-5) plugin/innobase/include/rem0cmp.h (+4/-0) plugin/innobase/include/rem0cmp.ic (+1/-1) plugin/innobase/include/row0upd.h (+18/-8) plugin/innobase/include/srv0srv.h (+18/-0) plugin/innobase/include/sync0rw.h (+2/-1) plugin/innobase/include/trx0rseg.h (+1/-3) plugin/innobase/include/trx0trx.h (+2/-2) plugin/innobase/include/univ.i (+4/-3) plugin/innobase/mem/mem0mem.cc (+1/-1) plugin/innobase/page/page0zip.cc (+1/-1) plugin/innobase/rem/rem0cmp.cc (+11/-3) plugin/innobase/row/row0ins.cc (+1/-1) plugin/innobase/row/row0merge.cc (+47/-23) plugin/innobase/row/row0purge.cc (+31/-47) plugin/innobase/row/row0umod.cc (+17/-30) plugin/innobase/row/row0upd.cc (+31/-16) plugin/innobase/row/row0vers.cc (+7/-3) plugin/innobase/srv/srv0srv.cc (+6/-1) plugin/innobase/srv/srv0start.cc (+8/-5) plugin/innobase/sync/sync0arr.cc (+2/-2) plugin/innobase/sync/sync0rw.cc (+10/-9) plugin/innobase/sync/sync0sync.cc (+216/-173) plugin/innobase/trx/trx0roll.cc (+2/-2) plugin/innobase/trx/trx0trx.cc (+11/-14) |
To merge this branch: | bzr merge lp:~stewart/drizzle/7.1-innodb-from-mysql-5.5.10 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Drizzle Trunk | Pending | ||
Review via email: mp+106811@code.launchpad.net |
Commit message
Description of the change
Merge InnoDB from MySQL 5.5.10.
Henrik Ingo (hingo) wrote : | # |
- 2552. By Stewart Smith
-
fix compiler warning on some compilers:
plugin/innobase/ srv/srv0srv. cc: In function 'ulint srv_thread_ has_reserved_ slot(srv_ thread_ type)':
plugin/innobase/ srv/srv0srv. cc:1075: error: comparison between signed and unsigned integer expressions [-Wsign-compare]
Stewart Smith (stewart) wrote : | # |
On Tue, 22 May 2012 19:56:26 -0000, Henrik Ingo <email address hidden> wrote:
> Why 5.5.10? It's like a year old. Why not latest and greatest? 5.5.24?
It's coming in stages. There's a suitably large jump where it's better
to do incremental improvements rather than jump all the way in one go.
--
Stewart Smith
Brian Aker (brianaker) wrote : | # |
https:/
Failure is happening when running with the server compiled as debug.
From master.err:
CURRENT_TEST: query_log.
Can't open shared library '/home/
Couldn't load plugin library named 'query_log'.
Aborting:"Failed to initialize plugins". Abort was called from drizzled/
Note: Forcing kill of process 16390
Stewart Smith (stewart) wrote : | # |
On Thu, 24 May 2012 22:58:18 -0000, Brian Aker <email address hidden> wrote:
> Failure is happening when running with the server compiled as debug.
>
> >From master.err:
>
>
> CURRENT_TEST: query_log.
> Can't open shared library '/home/
> Couldn't load plugin library named 'query_log'.
>
> Aborting:"Failed to initialize plugins". Abort was called from drizzled/
> Note: Forcing kill of process 16390
huh... I have nothing to do with boost in my patch.... perhaps this is
with linking of the query_log plugin itself? My guess is that there's a
library missing.
--
Stewart Smith
Preview Diff
1 | === modified file 'plugin/innobase/btr/btr0btr.cc' |
2 | --- plugin/innobase/btr/btr0btr.cc 2012-05-23 00:15:24 +0000 |
3 | +++ plugin/innobase/btr/btr0btr.cc 2012-05-23 00:15:24 +0000 |
4 | @@ -980,7 +980,7 @@ |
5 | log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); |
6 | |
7 | #ifndef UNIV_HOTBACKUP |
8 | - temp_block = buf_block_alloc(buf_pool, 0); |
9 | + temp_block = buf_block_alloc(buf_pool); |
10 | #else /* !UNIV_HOTBACKUP */ |
11 | ut_ad(block == back_block1); |
12 | temp_block = back_block2; |
13 | |
14 | === modified file 'plugin/innobase/btr/btr0cur.cc' |
15 | --- plugin/innobase/btr/btr0cur.cc 2012-05-23 00:15:24 +0000 |
16 | +++ plugin/innobase/btr/btr0cur.cc 2012-05-23 00:15:24 +0000 |
17 | @@ -111,6 +111,18 @@ |
18 | /*--------------------------------------*/ |
19 | #define BTR_BLOB_HDR_SIZE 8 /*!< Size of a BLOB |
20 | part header, in bytes */ |
21 | + |
22 | +/** Estimated table level stats from sampled value. |
23 | +@param value sampled stats |
24 | +@param index index being sampled |
25 | +@param sample number of sampled rows |
26 | +@param ext_size external stored data size |
27 | +@param not_empty table not empty |
28 | +@return estimated table wide stats from sampled value */ |
29 | +#define BTR_TABLE_STATS_FROM_SAMPLE(value, index, sample, ext_size, not_empty)\ |
30 | + (((value) * (ib_int64_t) index->stat_n_leaf_pages \ |
31 | + + (sample) - 1 + (ext_size) + (not_empty)) / ((sample) + (ext_size))) |
32 | + |
33 | /* @} */ |
34 | #endif /* !UNIV_HOTBACKUP */ |
35 | |
36 | @@ -185,7 +197,7 @@ |
37 | ulint |
38 | btr_rec_get_externally_stored_len( |
39 | /*==============================*/ |
40 | - rec_t* rec, /*!< in: record */ |
41 | + const rec_t* rec, /*!< in: record */ |
42 | const ulint* offsets);/*!< in: array returned by rec_get_offsets() */ |
43 | #endif /* !UNIV_HOTBACKUP */ |
44 | |
45 | @@ -1874,8 +1886,8 @@ |
46 | NOT call it if index is secondary */ |
47 | |
48 | if (!dict_index_is_clust(index) |
49 | - || row_upd_changes_ord_field_binary(NULL, NULL, |
50 | - index, update)) { |
51 | + || row_upd_changes_ord_field_binary(index, update, thr, |
52 | + NULL, NULL)) { |
53 | |
54 | /* Remove possible hash index pointer to this record */ |
55 | btr_search_update_hash_on_delete(cursor); |
56 | @@ -3479,9 +3491,53 @@ |
57 | } |
58 | |
59 | /*******************************************************************//** |
60 | +Record the number of non_null key values in a given index for |
61 | +each n-column prefix of the index where n < dict_index_get_n_unique(index). |
62 | +The estimates are eventually stored in the array: |
63 | +index->stat_n_non_null_key_vals. */ |
64 | +static |
65 | +void |
66 | +btr_record_not_null_field_in_rec( |
67 | +/*=============================*/ |
68 | + rec_t* rec, /*!< in: physical record */ |
69 | + ulint n_unique, /*!< in: dict_index_get_n_unique(index), |
70 | + number of columns uniquely determine |
71 | + an index entry */ |
72 | + const ulint* offsets, /*!< in: rec_get_offsets(rec, index), |
73 | + its size could be for all fields or |
74 | + that of "n_unique" */ |
75 | + ib_int64_t* n_not_null) /*!< in/out: array to record number of |
76 | + not null rows for n-column prefix */ |
77 | +{ |
78 | + ulint i; |
79 | + |
80 | + ut_ad(rec_offs_n_fields(offsets) >= n_unique); |
81 | + |
82 | + if (n_not_null == NULL) { |
83 | + return; |
84 | + } |
85 | + |
86 | + for (i = 0; i < n_unique; i++) { |
87 | + ulint rec_len; |
88 | + |
89 | + rec_get_nth_field(rec, offsets, i, &rec_len); |
90 | + |
91 | + if (rec_len != UNIV_SQL_NULL) { |
92 | + n_not_null[i]++; |
93 | + } else { |
94 | + /* Break if we hit the first NULL value */ |
95 | + break; |
96 | + } |
97 | + } |
98 | +} |
99 | + |
100 | +/*******************************************************************//** |
101 | Estimates the number of different key values in a given index, for |
102 | each n-column prefix of the index where n <= dict_index_get_n_unique(index). |
103 | -The estimates are stored in the array index->stat_n_diff_key_vals. */ |
104 | +The estimates are stored in the array index->stat_n_diff_key_vals. |
105 | +If innodb_stats_method is "nulls_ignored", we also record the number of |
106 | +non-null values for each prefix and store the estimates in |
107 | +array index->stat_n_non_null_key_vals. */ |
108 | UNIV_INTERN |
109 | void |
110 | btr_estimate_number_of_different_key_vals( |
111 | @@ -3495,6 +3551,8 @@ |
112 | ulint matched_fields; |
113 | ulint matched_bytes; |
114 | ib_int64_t* n_diff; |
115 | + ib_int64_t* n_not_null; |
116 | + ibool stats_null_not_equal; |
117 | ullint n_sample_pages; /* number of pages to sample */ |
118 | ulint not_empty_flag = 0; |
119 | ulint total_external_size = 0; |
120 | @@ -3503,16 +3561,43 @@ |
121 | ullint add_on; |
122 | mtr_t mtr; |
123 | mem_heap_t* heap = NULL; |
124 | - ulint offsets_rec_[REC_OFFS_NORMAL_SIZE]; |
125 | - ulint offsets_next_rec_[REC_OFFS_NORMAL_SIZE]; |
126 | - ulint* offsets_rec = offsets_rec_; |
127 | - ulint* offsets_next_rec= offsets_next_rec_; |
128 | - rec_offs_init(offsets_rec_); |
129 | - rec_offs_init(offsets_next_rec_); |
130 | + ulint* offsets_rec = NULL; |
131 | + ulint* offsets_next_rec = NULL; |
132 | |
133 | n_cols = dict_index_get_n_unique(index); |
134 | |
135 | - n_diff = (ib_int64_t *)mem_zalloc((n_cols + 1) * sizeof(ib_int64_t)); |
136 | + heap = mem_heap_create((sizeof *n_diff + sizeof *n_not_null) |
137 | + * (n_cols + 1) |
138 | + + dict_index_get_n_fields(index) |
139 | + * (sizeof *offsets_rec |
140 | + + sizeof *offsets_next_rec)); |
141 | + |
142 | + n_diff = static_cast<ib_int64_t *>(mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t))); |
143 | + |
144 | + n_not_null = NULL; |
145 | + |
146 | + /* Check srv_innodb_stats_method setting, and decide whether we |
147 | + need to record non-null value and also decide if NULL is |
148 | + considered equal (by setting stats_null_not_equal value) */ |
149 | + switch (srv_innodb_stats_method) { |
150 | + case SRV_STATS_NULLS_IGNORED: |
151 | + n_not_null = static_cast<ib_int64_t *>(mem_heap_zalloc(heap, (n_cols + 1) |
152 | + * sizeof *n_not_null)); |
153 | + /* fall through */ |
154 | + |
155 | + case SRV_STATS_NULLS_UNEQUAL: |
156 | + /* for both SRV_STATS_NULLS_IGNORED and SRV_STATS_NULLS_UNEQUAL |
157 | + case, we will treat NULLs as unequal value */ |
158 | + stats_null_not_equal = TRUE; |
159 | + break; |
160 | + |
161 | + case SRV_STATS_NULLS_EQUAL: |
162 | + stats_null_not_equal = FALSE; |
163 | + break; |
164 | + |
165 | + default: |
166 | + ut_error; |
167 | + } |
168 | |
169 | /* It makes no sense to test more pages than are contained |
170 | in the index, thus we lower the number if it is too high */ |
171 | @@ -3529,7 +3614,6 @@ |
172 | /* We sample some pages in the index to get an estimate */ |
173 | |
174 | for (i = 0; i < n_sample_pages; i++) { |
175 | - rec_t* supremum; |
176 | mtr_start(&mtr); |
177 | |
178 | btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr); |
179 | @@ -3542,18 +3626,25 @@ |
180 | |
181 | page = btr_cur_get_page(&cursor); |
182 | |
183 | - supremum = page_get_supremum_rec(page); |
184 | rec = page_rec_get_next(page_get_infimum_rec(page)); |
185 | |
186 | - if (rec != supremum) { |
187 | + if (!page_rec_is_supremum(rec)) { |
188 | not_empty_flag = 1; |
189 | offsets_rec = rec_get_offsets(rec, index, offsets_rec, |
190 | ULINT_UNDEFINED, &heap); |
191 | + |
192 | + if (n_not_null) { |
193 | + btr_record_not_null_field_in_rec( |
194 | + rec, n_cols, offsets_rec, n_not_null); |
195 | + } |
196 | } |
197 | |
198 | - while (rec != supremum) { |
199 | + while (!page_rec_is_supremum(rec)) { |
200 | rec_t* next_rec = page_rec_get_next(rec); |
201 | - if (next_rec == supremum) { |
202 | + if (page_rec_is_supremum(next_rec)) { |
203 | + total_external_size += |
204 | + btr_rec_get_externally_stored_len( |
205 | + rec, offsets_rec); |
206 | break; |
207 | } |
208 | |
209 | @@ -3561,11 +3652,13 @@ |
210 | matched_bytes = 0; |
211 | offsets_next_rec = rec_get_offsets(next_rec, index, |
212 | offsets_next_rec, |
213 | - n_cols, &heap); |
214 | + ULINT_UNDEFINED, |
215 | + &heap); |
216 | |
217 | cmp_rec_rec_with_match(rec, next_rec, |
218 | offsets_rec, offsets_next_rec, |
219 | - index, &matched_fields, |
220 | + index, stats_null_not_equal, |
221 | + &matched_fields, |
222 | &matched_bytes); |
223 | |
224 | for (j = matched_fields + 1; j <= n_cols; j++) { |
225 | @@ -3575,6 +3668,12 @@ |
226 | n_diff[j]++; |
227 | } |
228 | |
229 | + if (n_not_null) { |
230 | + btr_record_not_null_field_in_rec( |
231 | + next_rec, n_cols, offsets_next_rec, |
232 | + n_not_null); |
233 | + } |
234 | + |
235 | total_external_size |
236 | += btr_rec_get_externally_stored_len( |
237 | rec, offsets_rec); |
238 | @@ -3609,10 +3708,6 @@ |
239 | } |
240 | } |
241 | |
242 | - offsets_rec = rec_get_offsets(rec, index, offsets_rec, |
243 | - ULINT_UNDEFINED, &heap); |
244 | - total_external_size += btr_rec_get_externally_stored_len( |
245 | - rec, offsets_rec); |
246 | mtr_commit(&mtr); |
247 | } |
248 | |
249 | @@ -3626,13 +3721,9 @@ |
250 | |
251 | for (j = 0; j <= n_cols; j++) { |
252 | index->stat_n_diff_key_vals[j] |
253 | - = ((n_diff[j] |
254 | - * (ib_int64_t)index->stat_n_leaf_pages |
255 | - + n_sample_pages - 1 |
256 | - + total_external_size |
257 | - + not_empty_flag) |
258 | - / (n_sample_pages |
259 | - + total_external_size)); |
260 | + = BTR_TABLE_STATS_FROM_SAMPLE( |
261 | + n_diff[j], index, n_sample_pages, |
262 | + total_external_size, not_empty_flag); |
263 | |
264 | /* If the tree is small, smaller than |
265 | 10 * n_sample_pages + total_external_size, then |
266 | @@ -3651,45 +3742,81 @@ |
267 | } |
268 | |
269 | index->stat_n_diff_key_vals[j] += add_on; |
270 | - } |
271 | - |
272 | - mem_free(n_diff); |
273 | - if (UNIV_LIKELY_NULL(heap)) { |
274 | - mem_heap_free(heap); |
275 | - } |
276 | + |
277 | + /* Update the stat_n_non_null_key_vals[] with our |
278 | + sampled result. stat_n_non_null_key_vals[] is created |
279 | + and initialized to zero in dict_index_add_to_cache(), |
280 | + along with stat_n_diff_key_vals[] array */ |
281 | + if (n_not_null != NULL && (j < n_cols)) { |
282 | + index->stat_n_non_null_key_vals[j] = |
283 | + BTR_TABLE_STATS_FROM_SAMPLE( |
284 | + n_not_null[j], index, n_sample_pages, |
285 | + total_external_size, not_empty_flag); |
286 | + } |
287 | + } |
288 | + |
289 | + mem_heap_free(heap); |
290 | } |
291 | |
292 | /*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/ |
293 | |
294 | /***********************************************************//** |
295 | +Gets the offset of the pointer to the externally stored part of a field. |
296 | +@return offset of the pointer to the externally stored part */ |
297 | +static |
298 | +ulint |
299 | +btr_rec_get_field_ref_offs( |
300 | +/*=======================*/ |
301 | + const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ |
302 | + ulint n) /*!< in: index of the external field */ |
303 | +{ |
304 | + ulint field_ref_offs; |
305 | + ulint local_len; |
306 | + |
307 | + ut_a(rec_offs_nth_extern(offsets, n)); |
308 | + field_ref_offs = rec_get_nth_field_offs(offsets, n, &local_len); |
309 | + ut_a(local_len != UNIV_SQL_NULL); |
310 | + ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE); |
311 | + |
312 | + return(field_ref_offs + local_len - BTR_EXTERN_FIELD_REF_SIZE); |
313 | +} |
314 | + |
315 | +/** Gets a pointer to the externally stored part of a field. |
316 | +@param rec record |
317 | +@param offsets rec_get_offsets(rec) |
318 | +@param n index of the externally stored field |
319 | +@return pointer to the externally stored part */ |
320 | +#define btr_rec_get_field_ref(rec, offsets, n) \ |
321 | + ((rec) + btr_rec_get_field_ref_offs(offsets, n)) |
322 | + |
323 | +/***********************************************************//** |
324 | Gets the externally stored size of a record, in units of a database page. |
325 | @return externally stored part, in units of a database page */ |
326 | static |
327 | ulint |
328 | btr_rec_get_externally_stored_len( |
329 | /*==============================*/ |
330 | - rec_t* rec, /*!< in: record */ |
331 | + const rec_t* rec, /*!< in: record */ |
332 | const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ |
333 | { |
334 | ulint n_fields; |
335 | - byte* data; |
336 | - ulint local_len; |
337 | - ulint extern_len; |
338 | ulint total_extern_len = 0; |
339 | ulint i; |
340 | |
341 | ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec)); |
342 | + |
343 | + if (!rec_offs_any_extern(offsets)) { |
344 | + return(0); |
345 | + } |
346 | + |
347 | n_fields = rec_offs_n_fields(offsets); |
348 | |
349 | for (i = 0; i < n_fields; i++) { |
350 | if (rec_offs_nth_extern(offsets, i)) { |
351 | |
352 | - data = rec_get_nth_field(rec, offsets, i, &local_len); |
353 | - |
354 | - local_len -= BTR_EXTERN_FIELD_REF_SIZE; |
355 | - |
356 | - extern_len = mach_read_from_4(data + local_len |
357 | - + BTR_EXTERN_LEN + 4); |
358 | + ulint extern_len = mach_read_from_4( |
359 | + btr_rec_get_field_ref(rec, offsets, i) |
360 | + + BTR_EXTERN_LEN + 4); |
361 | |
362 | total_extern_len += ut_calc_align(extern_len, |
363 | UNIV_PAGE_SIZE); |
364 | @@ -3719,7 +3846,7 @@ |
365 | ulint byte_val; |
366 | |
367 | data = rec_get_nth_field(rec, offsets, i, &local_len); |
368 | - |
369 | + ut_ad(rec_offs_nth_extern(offsets, i)); |
370 | ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE); |
371 | |
372 | local_len -= BTR_EXTERN_FIELD_REF_SIZE; |
373 | @@ -3729,6 +3856,9 @@ |
374 | if (val) { |
375 | byte_val = byte_val & (~BTR_EXTERN_OWNER_FLAG); |
376 | } else { |
377 | +#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG |
378 | + ut_a(!(byte_val & BTR_EXTERN_OWNER_FLAG)); |
379 | +#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ |
380 | byte_val = byte_val | BTR_EXTERN_OWNER_FLAG; |
381 | } |
382 | |
383 | @@ -3946,13 +4076,12 @@ |
384 | && buf_block_get_space(block) == space |
385 | && buf_block_get_page_no(block) == page_no) { |
386 | |
387 | - if (buf_LRU_free_block(&block->page, all, NULL) |
388 | - != BUF_LRU_FREED |
389 | + if (buf_LRU_free_block(&block->page, all) != BUF_LRU_FREED |
390 | && all && block->page.zip.data) { |
391 | /* Attempt to deallocate the uncompressed page |
392 | if the whole block cannot be deallocted. */ |
393 | |
394 | - buf_LRU_free_block(&block->page, FALSE, NULL); |
395 | + buf_LRU_free_block(&block->page, FALSE); |
396 | } |
397 | } |
398 | |
399 | @@ -3968,8 +4097,8 @@ |
400 | @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ |
401 | UNIV_INTERN |
402 | ulint |
403 | -btr_store_big_rec_extern_fields( |
404 | -/*============================*/ |
405 | +btr_store_big_rec_extern_fields_func( |
406 | +/*=================================*/ |
407 | dict_index_t* index, /*!< in: index of rec; the index tree |
408 | MUST be X-latched */ |
409 | buf_block_t* rec_block, /*!< in/out: block containing rec */ |
410 | @@ -3978,11 +4107,16 @@ |
411 | the "external storage" flags in offsets |
412 | will not correspond to rec when |
413 | this function returns */ |
414 | - big_rec_t* big_rec_vec, /*!< in: vector containing fields |
415 | +#ifdef UNIV_DEBUG |
416 | + mtr_t* local_mtr, /*!< in: mtr containing the |
417 | + latch to rec and to the tree */ |
418 | +#endif /* UNIV_DEBUG */ |
419 | +#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG |
420 | + ibool update_in_place,/*! in: TRUE if the record is updated |
421 | + in place (not delete+insert) */ |
422 | +#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ |
423 | + const big_rec_t*big_rec_vec) /*!< in: vector containing fields |
424 | to be stored externally */ |
425 | - mtr_t* /*local_mtr __attribute__((unused))*/) /*!< in: mtr |
426 | - containing the latch to rec and to the |
427 | - tree */ |
428 | { |
429 | ulint rec_page_no; |
430 | byte* field_ref; |
431 | @@ -4000,6 +4134,7 @@ |
432 | z_stream c_stream; |
433 | |
434 | ut_ad(rec_offs_validate(rec, index, offsets)); |
435 | + ut_ad(rec_offs_any_extern(offsets)); |
436 | ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index), |
437 | MTR_MEMO_X_LOCK)); |
438 | ut_ad(mtr_memo_contains(local_mtr, rec_block, MTR_MEMO_PAGE_X_FIX)); |
439 | @@ -4031,21 +4166,37 @@ |
440 | ut_a(err == Z_OK); |
441 | } |
442 | |
443 | +#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG |
444 | + /* All pointers to externally stored columns in the record |
445 | + must either be zero or they must be pointers to inherited |
446 | + columns, owned by this record or an earlier record version. */ |
447 | + for (i = 0; i < rec_offs_n_fields(offsets); i++) { |
448 | + if (!rec_offs_nth_extern(offsets, i)) { |
449 | + continue; |
450 | + } |
451 | + field_ref = btr_rec_get_field_ref(rec, offsets, i); |
452 | + |
453 | + ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG)); |
454 | + /* Either this must be an update in place, |
455 | + or the BLOB must be inherited, or the BLOB pointer |
456 | + must be zero (will be written in this function). */ |
457 | + ut_a(update_in_place |
458 | + || (field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_INHERITED_FLAG) |
459 | + || !memcmp(field_ref, field_ref_zero, |
460 | + BTR_EXTERN_FIELD_REF_SIZE)); |
461 | + } |
462 | +#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ |
463 | /* We have to create a file segment to the tablespace |
464 | for each field and put the pointer to the field in rec */ |
465 | |
466 | for (i = 0; i < big_rec_vec->n_fields; i++) { |
467 | - ut_ad(rec_offs_nth_extern(offsets, |
468 | - big_rec_vec->fields[i].field_no)); |
469 | - { |
470 | - ulint local_len; |
471 | - field_ref = rec_get_nth_field( |
472 | - rec, offsets, big_rec_vec->fields[i].field_no, |
473 | - &local_len); |
474 | - ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE); |
475 | - local_len -= BTR_EXTERN_FIELD_REF_SIZE; |
476 | - field_ref += local_len; |
477 | - } |
478 | + field_ref = btr_rec_get_field_ref( |
479 | + rec, offsets, big_rec_vec->fields[i].field_no); |
480 | +#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG |
481 | + /* A zero BLOB pointer should have been initially inserted. */ |
482 | + ut_a(!memcmp(field_ref, field_ref_zero, |
483 | + BTR_EXTERN_FIELD_REF_SIZE)); |
484 | +#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ |
485 | extern_len = big_rec_vec->fields[i].len; |
486 | UNIV_MEM_ASSERT_RW(big_rec_vec->fields[i].data, |
487 | extern_len); |
488 | @@ -4327,6 +4478,23 @@ |
489 | mem_heap_free(heap); |
490 | } |
491 | |
492 | +#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG |
493 | + /* All pointers to externally stored columns in the record |
494 | + must be valid. */ |
495 | + for (i = 0; i < rec_offs_n_fields(offsets); i++) { |
496 | + if (!rec_offs_nth_extern(offsets, i)) { |
497 | + continue; |
498 | + } |
499 | + |
500 | + field_ref = btr_rec_get_field_ref(rec, offsets, i); |
501 | + |
502 | + /* The pointer must not be zero. */ |
503 | + ut_a(0 != memcmp(field_ref, field_ref_zero, |
504 | + BTR_EXTERN_FIELD_REF_SIZE)); |
505 | + /* The column must not be disowned by this record. */ |
506 | + ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG)); |
507 | + } |
508 | +#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ |
509 | return(DB_SUCCESS); |
510 | } |
511 | |
512 | @@ -4349,6 +4517,7 @@ |
513 | if (UNIV_UNLIKELY(type != FIL_PAGE_TYPE_BLOB)) { |
514 | ulint flags = fil_space_get_flags(space_id); |
515 | |
516 | +#ifndef UNIV_DEBUG /* Improve debug test coverage */ |
517 | if (UNIV_LIKELY |
518 | ((flags & DICT_TF_FORMAT_MASK) == DICT_TF_FORMAT_51)) { |
519 | /* Old versions of InnoDB did not initialize |
520 | @@ -4357,6 +4526,7 @@ |
521 | a BLOB page that is in Antelope format.*/ |
522 | return; |
523 | } |
524 | +#endif /* !UNIV_DEBUG */ |
525 | |
526 | ut_print_timestamp(stderr); |
527 | fprintf(stderr, |
528 | @@ -4406,23 +4576,13 @@ |
529 | ulint page_no; |
530 | ulint next_page_no; |
531 | mtr_t mtr; |
532 | -#ifdef UNIV_DEBUG |
533 | + |
534 | ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index), |
535 | MTR_MEMO_X_LOCK)); |
536 | ut_ad(mtr_memo_contains_page(local_mtr, field_ref, |
537 | MTR_MEMO_PAGE_X_FIX)); |
538 | ut_ad(!rec || rec_offs_validate(rec, index, offsets)); |
539 | - |
540 | - if (rec) { |
541 | - ulint local_len; |
542 | - const byte* f = rec_get_nth_field(rec, offsets, |
543 | - i, &local_len); |
544 | - ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE); |
545 | - local_len -= BTR_EXTERN_FIELD_REF_SIZE; |
546 | - f += local_len; |
547 | - ut_ad(f == field_ref); |
548 | - } |
549 | -#endif /* UNIV_DEBUG */ |
550 | + ut_ad(!rec || field_ref == btr_rec_get_field_ref(rec, offsets, i)); |
551 | |
552 | if (UNIV_UNLIKELY(!memcmp(field_ref, field_ref_zero, |
553 | BTR_EXTERN_FIELD_REF_SIZE))) { |
554 | @@ -4587,13 +4747,8 @@ |
555 | |
556 | for (i = 0; i < n_fields; i++) { |
557 | if (rec_offs_nth_extern(offsets, i)) { |
558 | - ulint len; |
559 | - byte* data |
560 | - = rec_get_nth_field(rec, offsets, i, &len); |
561 | - ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE); |
562 | - |
563 | btr_free_externally_stored_field( |
564 | - index, data + len - BTR_EXTERN_FIELD_REF_SIZE, |
565 | + index, btr_rec_get_field_ref(rec, offsets, i), |
566 | rec, offsets, page_zip, i, rb_ctx, mtr); |
567 | } |
568 | } |
569 | |
570 | === modified file 'plugin/innobase/btr/btr0sea.cc' |
571 | --- plugin/innobase/btr/btr0sea.cc 2010-12-27 18:39:11 +0000 |
572 | +++ plugin/innobase/btr/btr0sea.cc 2012-05-23 00:15:24 +0000 |
573 | @@ -146,7 +146,7 @@ |
574 | be enough free space in the hash table. */ |
575 | |
576 | if (heap->free_block == NULL) { |
577 | - buf_block_t* block = buf_block_alloc(NULL, 0); |
578 | + buf_block_t* block = buf_block_alloc(NULL); |
579 | |
580 | rw_lock_x_lock(&btr_search_latch); |
581 | |
582 | |
583 | === modified file 'plugin/innobase/buf/buf0buddy.cc' |
584 | --- plugin/innobase/buf/buf0buddy.cc 2010-12-24 00:04:05 +0000 |
585 | +++ plugin/innobase/buf/buf0buddy.cc 2012-05-23 00:15:24 +0000 |
586 | @@ -327,7 +327,7 @@ |
587 | |
588 | /* Try replacing an uncompressed page in the buffer pool. */ |
589 | buf_pool_mutex_exit(buf_pool); |
590 | - block = buf_LRU_get_free_block(buf_pool, 0); |
591 | + block = buf_LRU_get_free_block(buf_pool); |
592 | *lru = TRUE; |
593 | buf_pool_mutex_enter(buf_pool); |
594 | |
595 | |
596 | === modified file 'plugin/innobase/buf/buf0buf.cc' |
597 | --- plugin/innobase/buf/buf0buf.cc 2012-05-23 00:15:24 +0000 |
598 | +++ plugin/innobase/buf/buf0buf.cc 2012-05-23 00:15:24 +0000 |
599 | @@ -419,9 +419,9 @@ |
600 | buf_block_t* |
601 | buf_block_alloc( |
602 | /*============*/ |
603 | - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ |
604 | - ulint zip_size) /*!< in: compressed page size in bytes, |
605 | - or 0 if uncompressed tablespace */ |
606 | + buf_pool_t* buf_pool) /*!< in/out: buffer pool instance, |
607 | + or NULL for round-robin selection |
608 | + of the buffer pool */ |
609 | { |
610 | buf_block_t* block; |
611 | ulint index; |
612 | @@ -434,7 +434,7 @@ |
613 | buf_pool = buf_pool_from_array(index); |
614 | } |
615 | |
616 | - block = buf_LRU_get_free_block(buf_pool, zip_size); |
617 | + block = buf_LRU_get_free_block(buf_pool); |
618 | |
619 | buf_block_set_state(block, BUF_BLOCK_MEMORY); |
620 | |
621 | @@ -862,9 +862,9 @@ |
622 | |
623 | block->modify_clock = 0; |
624 | |
625 | -#ifdef UNIV_DEBUG_FILE_ACCESSES |
626 | +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
627 | block->page.file_page_was_freed = FALSE; |
628 | -#endif /* UNIV_DEBUG_FILE_ACCESSES */ |
629 | +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
630 | |
631 | block->check_index_page_at_flush = FALSE; |
632 | block->index = NULL; |
633 | @@ -1622,7 +1622,7 @@ |
634 | |
635 | buf_LRU_make_block_old(&block->page); |
636 | dirty++; |
637 | - } else if (buf_LRU_free_block(&block->page, TRUE, NULL) |
638 | + } else if (buf_LRU_free_block(&block->page, TRUE) |
639 | != BUF_LRU_FREED) { |
640 | nonfree++; |
641 | } |
642 | @@ -2228,7 +2228,7 @@ |
643 | return(is_hashed); |
644 | } |
645 | |
646 | -#ifdef UNIV_DEBUG_FILE_ACCESSES |
647 | +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
648 | /********************************************************************//** |
649 | Sets file_page_was_freed TRUE if the page is found in the buffer pool. |
650 | This function should be called when we free a file page and want the |
651 | @@ -2251,6 +2251,8 @@ |
652 | |
653 | if (bpage) { |
654 | ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage)); |
655 | + /* bpage->file_page_was_freed can already hold |
656 | + when this code is invoked from dict_drop_index_tree() */ |
657 | bpage->file_page_was_freed = TRUE; |
658 | } |
659 | |
660 | @@ -2288,7 +2290,7 @@ |
661 | |
662 | return(bpage); |
663 | } |
664 | -#endif /* UNIV_DEBUG_FILE_ACCESSES */ |
665 | +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
666 | |
667 | /********************************************************************//** |
668 | Get read access to a compressed page (usually of type |
669 | @@ -2365,8 +2367,7 @@ |
670 | mutex_enter(block_mutex); |
671 | |
672 | /* Discard the uncompressed page frame if possible. */ |
673 | - if (buf_LRU_free_block(bpage, FALSE, NULL) |
674 | - == BUF_LRU_FREED) { |
675 | + if (buf_LRU_free_block(bpage, FALSE) == BUF_LRU_FREED) { |
676 | |
677 | mutex_exit(block_mutex); |
678 | goto lookup; |
679 | @@ -2390,7 +2391,7 @@ |
680 | |
681 | buf_page_set_accessed_make_young(bpage, access_time); |
682 | |
683 | -#ifdef UNIV_DEBUG_FILE_ACCESSES |
684 | +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
685 | ut_a(!bpage->file_page_was_freed); |
686 | #endif |
687 | |
688 | @@ -2882,7 +2883,7 @@ |
689 | buf_pool_mutex_exit(buf_pool); |
690 | mutex_exit(&buf_pool->zip_mutex); |
691 | |
692 | - block = buf_LRU_get_free_block(buf_pool, 0); |
693 | + block = buf_LRU_get_free_block(buf_pool); |
694 | ut_a(block); |
695 | |
696 | buf_pool_mutex_enter(buf_pool); |
697 | @@ -3012,8 +3013,7 @@ |
698 | /* Try to evict the block from the buffer pool, to use the |
699 | insert buffer (change buffer) as much as possible. */ |
700 | |
701 | - if (buf_LRU_free_block(&block->page, TRUE, NULL) |
702 | - == BUF_LRU_FREED) { |
703 | + if (buf_LRU_free_block(&block->page, TRUE) == BUF_LRU_FREED) { |
704 | mutex_exit(&block->mutex); |
705 | if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) { |
706 | /* Set the watch, as it would have |
707 | @@ -3059,7 +3059,7 @@ |
708 | |
709 | buf_page_set_accessed_make_young(&block->page, access_time); |
710 | |
711 | -#ifdef UNIV_DEBUG_FILE_ACCESSES |
712 | +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
713 | ut_a(!block->page.file_page_was_freed); |
714 | #endif |
715 | |
716 | @@ -3218,7 +3218,7 @@ |
717 | ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); |
718 | #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ |
719 | |
720 | -#ifdef UNIV_DEBUG_FILE_ACCESSES |
721 | +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
722 | ut_a(block->page.file_page_was_freed == FALSE); |
723 | #endif |
724 | if (UNIV_UNLIKELY(!access_time)) { |
725 | @@ -3330,7 +3330,7 @@ |
726 | ut_a(block->page.buf_fix_count > 0); |
727 | ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); |
728 | #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ |
729 | -#ifdef UNIV_DEBUG_FILE_ACCESSES |
730 | +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
731 | ut_a(block->page.file_page_was_freed == FALSE); |
732 | #endif |
733 | |
734 | @@ -3416,9 +3416,9 @@ |
735 | ut_a(block->page.buf_fix_count > 0); |
736 | ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); |
737 | #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ |
738 | -#ifdef UNIV_DEBUG_FILE_ACCESSES |
739 | +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
740 | ut_a(block->page.file_page_was_freed == FALSE); |
741 | -#endif /* UNIV_DEBUG_FILE_ACCESSES */ |
742 | +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
743 | buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); |
744 | |
745 | buf_pool->stat.n_page_gets++; |
746 | @@ -3447,9 +3447,9 @@ |
747 | bpage->newest_modification = 0; |
748 | bpage->oldest_modification = 0; |
749 | HASH_INVALIDATE(bpage, hash); |
750 | -#ifdef UNIV_DEBUG_FILE_ACCESSES |
751 | +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
752 | bpage->file_page_was_freed = FALSE; |
753 | -#endif /* UNIV_DEBUG_FILE_ACCESSES */ |
754 | +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
755 | } |
756 | |
757 | /********************************************************************//** |
758 | @@ -3587,7 +3587,7 @@ |
759 | && UNIV_LIKELY(!recv_recovery_is_on())) { |
760 | block = NULL; |
761 | } else { |
762 | - block = buf_LRU_get_free_block(buf_pool, 0); |
763 | + block = buf_LRU_get_free_block(buf_pool); |
764 | ut_ad(block); |
765 | ut_ad(buf_pool_from_block(block) == buf_pool); |
766 | } |
767 | @@ -3793,7 +3793,7 @@ |
768 | ut_ad(mtr->state == MTR_ACTIVE); |
769 | ut_ad(space || !zip_size); |
770 | |
771 | - free_block = buf_LRU_get_free_block(buf_pool, 0); |
772 | + free_block = buf_LRU_get_free_block(buf_pool); |
773 | |
774 | fold = buf_page_address_fold(space, offset); |
775 | |
776 | @@ -3808,9 +3808,9 @@ |
777 | #ifdef UNIV_IBUF_COUNT_DEBUG |
778 | ut_a(ibuf_count_get(space, offset) == 0); |
779 | #endif |
780 | -#ifdef UNIV_DEBUG_FILE_ACCESSES |
781 | +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
782 | block->page.file_page_was_freed = FALSE; |
783 | -#endif /* UNIV_DEBUG_FILE_ACCESSES */ |
784 | +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
785 | |
786 | /* Page can be found in buf_pool */ |
787 | buf_pool_mutex_exit(buf_pool); |
788 | |
789 | === modified file 'plugin/innobase/buf/buf0lru.cc' |
790 | --- plugin/innobase/buf/buf0lru.cc 2012-05-23 00:15:24 +0000 |
791 | +++ plugin/innobase/buf/buf0lru.cc 2012-05-23 00:15:24 +0000 |
792 | @@ -604,7 +604,7 @@ |
793 | ut_ad(block->page.in_LRU_list); |
794 | |
795 | mutex_enter(&block->mutex); |
796 | - freed = buf_LRU_free_block(&block->page, FALSE, NULL); |
797 | + freed = buf_LRU_free_block(&block->page, FALSE); |
798 | mutex_exit(&block->mutex); |
799 | |
800 | switch (freed) { |
801 | @@ -667,7 +667,7 @@ |
802 | |
803 | mutex_enter(block_mutex); |
804 | accessed = buf_page_is_accessed(bpage); |
805 | - freed = buf_LRU_free_block(bpage, TRUE, NULL); |
806 | + freed = buf_LRU_free_block(bpage, TRUE); |
807 | mutex_exit(block_mutex); |
808 | |
809 | switch (freed) { |
810 | @@ -859,9 +859,7 @@ |
811 | buf_block_t* |
812 | buf_LRU_get_free_block( |
813 | /*===================*/ |
814 | - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ |
815 | - ulint zip_size) /*!< in: compressed page size in bytes, |
816 | - or 0 if uncompressed tablespace */ |
817 | + buf_pool_t* buf_pool) /*!< in/out: buffer pool instance */ |
818 | { |
819 | buf_block_t* block = NULL; |
820 | ibool freed; |
821 | @@ -937,31 +935,11 @@ |
822 | |
823 | /* If there is a block in the free list, take it */ |
824 | block = buf_LRU_get_free_only(buf_pool); |
825 | + buf_pool_mutex_exit(buf_pool); |
826 | + |
827 | if (block) { |
828 | - |
829 | ut_ad(buf_pool_from_block(block) == buf_pool); |
830 | - |
831 | -#ifdef UNIV_DEBUG |
832 | - block->page.zip.m_start = |
833 | -#endif /* UNIV_DEBUG */ |
834 | - block->page.zip.m_end = |
835 | - block->page.zip.m_nonempty = |
836 | - block->page.zip.n_blobs = 0; |
837 | - |
838 | - if (UNIV_UNLIKELY(zip_size)) { |
839 | - ibool lru; |
840 | - page_zip_set_size(&block->page.zip, zip_size); |
841 | - |
842 | - block->page.zip.data = static_cast<unsigned char *>(buf_buddy_alloc( |
843 | - buf_pool, zip_size, &lru)); |
844 | - |
845 | - UNIV_MEM_DESC(block->page.zip.data, zip_size, block); |
846 | - } else { |
847 | - page_zip_set_size(&block->page.zip, 0); |
848 | - block->page.zip.data = NULL; |
849 | - } |
850 | - |
851 | - buf_pool_mutex_exit(buf_pool); |
852 | + memset(&block->page.zip, 0, sizeof block->page.zip); |
853 | |
854 | if (started_monitor) { |
855 | srv_print_innodb_monitor = mon_value_was; |
856 | @@ -973,8 +951,6 @@ |
857 | /* If no block was in the free list, search from the end of the LRU |
858 | list and try to free a block there */ |
859 | |
860 | - buf_pool_mutex_exit(buf_pool); |
861 | - |
862 | freed = buf_LRU_search_and_free_block(buf_pool, n_iterations); |
863 | |
864 | if (freed > 0) { |
865 | @@ -1457,12 +1433,8 @@ |
866 | buf_LRU_free_block( |
867 | /*===============*/ |
868 | buf_page_t* bpage, /*!< in: block to be freed */ |
869 | - ibool zip, /*!< in: TRUE if should remove also the |
870 | + ibool zip) /*!< in: TRUE if should remove also the |
871 | compressed page of an uncompressed page */ |
872 | - ibool* buf_pool_mutex_released) |
873 | - /*!< in: pointer to a variable that will |
874 | - be assigned TRUE if buf_pool_mutex |
875 | - was temporarily released, or NULL */ |
876 | { |
877 | buf_page_t* b = NULL; |
878 | buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); |
879 | @@ -1639,10 +1611,6 @@ |
880 | b->io_fix = BUF_IO_READ; |
881 | } |
882 | |
883 | - if (buf_pool_mutex_released) { |
884 | - *buf_pool_mutex_released = TRUE; |
885 | - } |
886 | - |
887 | buf_pool_mutex_exit(buf_pool); |
888 | mutex_exit(block_mutex); |
889 | |
890 | |
891 | === modified file 'plugin/innobase/dict/dict0dict.cc' |
892 | --- plugin/innobase/dict/dict0dict.cc 2012-05-23 00:15:24 +0000 |
893 | +++ plugin/innobase/dict/dict0dict.cc 2012-05-23 00:15:24 +0000 |
894 | @@ -1691,6 +1691,12 @@ |
895 | new_index->heap, |
896 | (1 + dict_index_get_n_unique(new_index)) |
897 | * sizeof(ib_int64_t))); |
898 | + |
899 | + new_index->stat_n_non_null_key_vals = static_cast<ib_int64_t *>(mem_heap_zalloc( |
900 | + new_index->heap, |
901 | + (1 + dict_index_get_n_unique(new_index)) |
902 | + * sizeof(*new_index->stat_n_non_null_key_vals))); |
903 | + |
904 | /* Give some sensible values to stat_n_... in case we do |
905 | not calculate statistics quickly enough */ |
906 | |
907 | @@ -4323,6 +4329,10 @@ |
908 | for (i = dict_index_get_n_unique(index); i; ) { |
909 | index->stat_n_diff_key_vals[i--] = 1; |
910 | } |
911 | + |
912 | + memset(index->stat_n_non_null_key_vals, 0, |
913 | + (1 + dict_index_get_n_unique(index)) |
914 | + * sizeof(*index->stat_n_non_null_key_vals)); |
915 | } |
916 | |
917 | index = dict_table_get_next_index(index); |
918 | |
919 | === modified file 'plugin/innobase/dict/dict0load.cc' |
920 | --- plugin/innobase/dict/dict0load.cc 2012-05-23 00:15:24 +0000 |
921 | +++ plugin/innobase/dict/dict0load.cc 2012-05-23 00:15:24 +0000 |
922 | @@ -1630,7 +1630,7 @@ |
923 | "InnoDB: in InnoDB data dictionary" |
924 | " has unknown type %lx.\n", |
925 | (ulong) flags); |
926 | - return(NULL); |
927 | + return("incorrect flags in SYS_TABLES"); |
928 | } |
929 | } else { |
930 | flags = 0; |
931 | |
932 | === modified file 'plugin/innobase/fsp/fsp0fsp.cc' |
933 | --- plugin/innobase/fsp/fsp0fsp.cc 2012-05-23 00:15:24 +0000 |
934 | +++ plugin/innobase/fsp/fsp0fsp.cc 2012-05-23 00:15:24 +0000 |
935 | @@ -3424,9 +3424,9 @@ |
936 | |
937 | fseg_free_page_low(seg_inode, space, zip_size, page, mtr); |
938 | |
939 | -#ifdef UNIV_DEBUG_FILE_ACCESSES |
940 | +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
941 | buf_page_set_file_page_was_freed(space, page); |
942 | -#endif |
943 | +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
944 | } |
945 | |
946 | /**********************************************************************//** |
947 | @@ -3492,13 +3492,13 @@ |
948 | |
949 | fsp_free_extent(space, zip_size, page, mtr); |
950 | |
951 | -#ifdef UNIV_DEBUG_FILE_ACCESSES |
952 | +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
953 | for (i = 0; i < FSP_EXTENT_SIZE; i++) { |
954 | |
955 | buf_page_set_file_page_was_freed(space, |
956 | first_page_in_extent + i); |
957 | } |
958 | -#endif |
959 | +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
960 | } |
961 | |
962 | /**********************************************************************//** |
963 | |
964 | === modified file 'plugin/innobase/handler/ha_innodb.cc' |
965 | --- plugin/innobase/handler/ha_innodb.cc 2012-05-23 00:15:24 +0000 |
966 | +++ plugin/innobase/handler/ha_innodb.cc 2012-05-23 00:15:24 +0000 |
967 | @@ -292,6 +292,18 @@ |
968 | |
969 | static char* internal_innobase_data_file_path = NULL; |
970 | |
971 | +/** Possible values for system variable "innodb_stats_method". The values |
972 | +are defined the same as its corresponding MyISAM system variable |
973 | +"myisam_stats_method"(see "myisam_stats_method_names"), for better usability */ |
974 | +static const char* innodb_stats_method_names[] = { |
975 | + "nulls_equal", |
976 | + "nulls_unequal", |
977 | + "nulls_ignored", |
978 | + NULL |
979 | +}; |
980 | + |
981 | +static string innodb_stats_method; |
982 | + |
983 | /* The following counter is used to convey information to InnoDB |
984 | about server activity: in selects it is not sensible to call |
985 | srv_active_wake_master_thread after each fetch or search, we only do |
986 | @@ -2014,6 +2026,36 @@ |
987 | return(1); |
988 | } |
989 | |
990 | +static |
991 | +int |
992 | +innodb_stats_method_validate( |
993 | +/*=============================*/ |
994 | + Session* , /*!< in: thread handle */ |
995 | + set_var *var) |
996 | +{ |
997 | + const char *stats_method_input = var->value->str_value.ptr(); |
998 | + |
999 | + if (stats_method_input == NULL) |
1000 | + return 1; |
1001 | + |
1002 | + ulint use; |
1003 | + |
1004 | + for (use = 0; |
1005 | + use < UT_ARR_SIZE(innodb_stats_method_names); |
1006 | + ++use) { |
1007 | + if (!innobase_strcasecmp(stats_method_input, |
1008 | + innodb_stats_method_names[use])) |
1009 | + { |
1010 | + srv_innodb_stats_method= use; |
1011 | + innodb_stats_method= innodb_stats_method_names[use]; |
1012 | + return 0; |
1013 | + } |
1014 | + } |
1015 | + |
1016 | + return 1; |
1017 | +} |
1018 | + |
1019 | + |
1020 | /*************************************************************//** |
1021 | Check if it is a valid value of innodb_change_buffering. This function is |
1022 | registered as a callback with MySQL. |
1023 | @@ -2577,6 +2619,9 @@ |
1024 | context.registerVariable(new sys_var_constrained_value_readonly<uint64_t>("max_purge_lag", innodb_max_purge_lag)); |
1025 | context.registerVariable(new sys_var_constrained_value_readonly<uint64_t>("stats_sample_pages", innodb_stats_sample_pages)); |
1026 | context.registerVariable(new sys_var_bool_ptr("adaptive_hash_index", &btr_search_enabled, innodb_adaptive_hash_index_update)); |
1027 | + context.registerVariable(new sys_var_std_string("stats_method", |
1028 | + innodb_stats_method, |
1029 | + innodb_stats_method_validate)); |
1030 | |
1031 | context.registerVariable(new sys_var_constrained_value<uint32_t>("commit_concurrency", |
1032 | innobase_commit_concurrency, |
1033 | @@ -7247,6 +7292,65 @@ |
1034 | |
1035 | return(0); |
1036 | } |
1037 | + |
1038 | +/*********************************************************************//** |
1039 | +Calculate Record Per Key value. Need to exclude the NULL value if |
1040 | +innodb_stats_method is set to "nulls_ignored" |
1041 | +@return estimated record per key value */ |
1042 | +static |
1043 | +ha_rows |
1044 | +innodb_rec_per_key( |
1045 | +/*===============*/ |
1046 | + dict_index_t* index, /*!< in: dict_index_t structure */ |
1047 | + ulint i, /*!< in: the column we are |
1048 | + calculating rec per key */ |
1049 | + ha_rows records) /*!< in: estimated total records */ |
1050 | +{ |
1051 | + ha_rows rec_per_key; |
1052 | + |
1053 | + ut_ad(i < dict_index_get_n_unique(index)); |
1054 | + |
1055 | + /* Note the stat_n_diff_key_vals[] stores the diff value with |
1056 | + n-prefix indexing, so it is always stat_n_diff_key_vals[i + 1] */ |
1057 | + if (index->stat_n_diff_key_vals[i + 1] == 0) { |
1058 | + |
1059 | + rec_per_key = records; |
1060 | + } else if (srv_innodb_stats_method == SRV_STATS_NULLS_IGNORED) { |
1061 | + ib_int64_t num_null; |
1062 | + |
1063 | + /* Number of rows with NULL value in this |
1064 | + field */ |
1065 | + num_null = records - index->stat_n_non_null_key_vals[i]; |
1066 | + |
1067 | + /* In theory, index->stat_n_non_null_key_vals[i] |
1068 | + should always be less than the number of records. |
1069 | + Since this is statistics value, the value could |
1070 | + have slight discrepancy. But we will make sure |
1071 | + the number of null values is not a negative number. */ |
1072 | + num_null = (num_null < 0) ? 0 : num_null; |
1073 | + |
1074 | + /* If the number of NULL values is the same as or |
1075 | + large than that of the distinct values, we could |
1076 | + consider that the table consists mostly of NULL value. |
1077 | + Set rec_per_key to 1. */ |
1078 | + if (index->stat_n_diff_key_vals[i + 1] <= num_null) { |
1079 | + rec_per_key = 1; |
1080 | + } else { |
1081 | + /* Need to exclude rows with NULL values from |
1082 | + rec_per_key calculation */ |
1083 | + rec_per_key = (ha_rows)( |
1084 | + (records - num_null) |
1085 | + / (index->stat_n_diff_key_vals[i + 1] |
1086 | + - num_null)); |
1087 | + } |
1088 | + } else { |
1089 | + rec_per_key = (ha_rows) |
1090 | + (records / index->stat_n_diff_key_vals[i + 1]); |
1091 | + } |
1092 | + |
1093 | + return(rec_per_key); |
1094 | +} |
1095 | + |
1096 | /*********************************************************************//** |
1097 | Returns statistics information of the table to the MySQL interpreter, |
1098 | in various fields of the handle object. */ |
1099 | @@ -7468,13 +7572,7 @@ |
1100 | break; |
1101 | } |
1102 | |
1103 | - if (index->stat_n_diff_key_vals[j + 1] == 0) { |
1104 | - |
1105 | - rec_per_key = stats.records; |
1106 | - } else { |
1107 | - rec_per_key = (ha_rows)(stats.records / |
1108 | - index->stat_n_diff_key_vals[j + 1]); |
1109 | - } |
1110 | + rec_per_key = innodb_rec_per_key(index, j, stats.records); |
1111 | |
1112 | /* Since MySQL seems to favor table scans |
1113 | too much over index searches, we pretend |
1114 | @@ -9467,6 +9565,11 @@ |
1115 | _("ove blocks to the 'new' end of the buffer pool if the first access" |
1116 | " was at least this many milliseconds ago." |
1117 | " The timeout is disabled if 0 (the default).")); |
1118 | + context("stats-method", |
1119 | + po::value<string>(&innodb_stats_method), |
1120 | + "Specifies how InnoDB index statistics collection code should " |
1121 | + "treat NULLs. Possible values are NULLS_EQUAL (default), " |
1122 | + "NULLS_UNEQUAL and NULLS_IGNORED"); |
1123 | } |
1124 | |
1125 | |
1126 | |
1127 | === modified file 'plugin/innobase/ibuf/ibuf0ibuf.cc' |
1128 | --- plugin/innobase/ibuf/ibuf0ibuf.cc 2012-05-23 00:15:24 +0000 |
1129 | +++ plugin/innobase/ibuf/ibuf0ibuf.cc 2012-05-23 00:15:24 +0000 |
1130 | @@ -2282,9 +2282,9 @@ |
1131 | fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, |
1132 | IBUF_SPACE_ID, page_no, &mtr); |
1133 | |
1134 | -#ifdef UNIV_DEBUG_FILE_ACCESSES |
1135 | +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
1136 | buf_page_reset_file_page_was_freed(IBUF_SPACE_ID, page_no); |
1137 | -#endif |
1138 | +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
1139 | |
1140 | ibuf_enter(); |
1141 | |
1142 | @@ -2328,9 +2328,9 @@ |
1143 | ibuf_bitmap_page_set_bits( |
1144 | bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, FALSE, &mtr); |
1145 | |
1146 | -#ifdef UNIV_DEBUG_FILE_ACCESSES |
1147 | +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
1148 | buf_page_set_file_page_was_freed(IBUF_SPACE_ID, page_no); |
1149 | -#endif |
1150 | +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
1151 | mtr_commit(&mtr); |
1152 | |
1153 | ibuf_exit(); |
1154 | @@ -2591,23 +2591,6 @@ |
1155 | |
1156 | if (UNIV_UNLIKELY(ibuf->empty) |
1157 | && UNIV_LIKELY(!srv_shutdown_state)) { |
1158 | -ibuf_is_empty: |
1159 | - |
1160 | -#if 0 /* TODO */ |
1161 | - if (srv_shutdown_state) { |
1162 | - /* If the insert buffer becomes empty during |
1163 | - shutdown, note it in the system tablespace. */ |
1164 | - |
1165 | - trx_sys_set_ibuf_format(TRX_SYS_IBUF_EMPTY); |
1166 | - } |
1167 | - |
1168 | - /* TO DO: call trx_sys_set_ibuf_format() at startup |
1169 | - and whenever ibuf_use is changed to allow buffered |
1170 | - delete-marking or deleting. Never downgrade the |
1171 | - stamped format except when the insert buffer becomes |
1172 | - empty. */ |
1173 | -#endif |
1174 | - |
1175 | return(0); |
1176 | } |
1177 | |
1178 | @@ -2637,7 +2620,7 @@ |
1179 | mtr_commit(&mtr); |
1180 | btr_pcur_close(&pcur); |
1181 | |
1182 | - goto ibuf_is_empty; |
1183 | + return(0); |
1184 | } |
1185 | |
1186 | sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur), |
1187 | |
1188 | === modified file 'plugin/innobase/include/btr0cur.h' |
1189 | --- plugin/innobase/include/btr0cur.h 2012-05-23 00:15:24 +0000 |
1190 | +++ plugin/innobase/include/btr0cur.h 2012-05-23 00:15:24 +0000 |
1191 | @@ -467,7 +467,10 @@ |
1192 | /*******************************************************************//** |
1193 | Estimates the number of different key values in a given index, for |
1194 | each n-column prefix of the index where n <= dict_index_get_n_unique(index). |
1195 | -The estimates are stored in the array index->stat_n_diff_key_vals. */ |
1196 | +The estimates are stored in the array index->stat_n_diff_key_vals. |
1197 | +If innodb_stats_method is nulls_ignored, we also record the number of |
1198 | +non-null values for each prefix and stored the estimates in |
1199 | +array index->stat_n_non_null_key_vals. */ |
1200 | UNIV_INTERN |
1201 | void |
1202 | btr_estimate_number_of_different_key_vals( |
1203 | @@ -498,8 +501,8 @@ |
1204 | @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ |
1205 | UNIV_INTERN |
1206 | ulint |
1207 | -btr_store_big_rec_extern_fields( |
1208 | -/*============================*/ |
1209 | +btr_store_big_rec_extern_fields_func( |
1210 | +/*=================================*/ |
1211 | dict_index_t* index, /*!< in: index of rec; the index tree |
1212 | MUST be X-latched */ |
1213 | buf_block_t* rec_block, /*!< in/out: block containing rec */ |
1214 | @@ -508,10 +511,42 @@ |
1215 | the "external storage" flags in offsets |
1216 | will not correspond to rec when |
1217 | this function returns */ |
1218 | - big_rec_t* big_rec_vec, /*!< in: vector containing fields |
1219 | +#ifdef UNIV_DEBUG |
1220 | + mtr_t* local_mtr, /*!< in: mtr containing the |
1221 | + latch to rec and to the tree */ |
1222 | +#endif /* UNIV_DEBUG */ |
1223 | +#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG |
1224 | + ibool update_in_place,/*! in: TRUE if the record is updated |
1225 | + in place (not delete+insert) */ |
1226 | +#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ |
1227 | + const big_rec_t*big_rec_vec) /*!< in: vector containing fields |
1228 | to be stored externally */ |
1229 | - mtr_t* local_mtr); /*!< in: mtr containing the latch to |
1230 | - rec and to the tree */ |
1231 | + __attribute__((nonnull)); |
1232 | + |
1233 | +/** Stores the fields in big_rec_vec to the tablespace and puts pointers to |
1234 | +them in rec. The extern flags in rec will have to be set beforehand. |
1235 | +The fields are stored on pages allocated from leaf node |
1236 | +file segment of the index tree. |
1237 | +@param index in: clustered index; MUST be X-latched by mtr |
1238 | +@param b in/out: block containing rec; MUST be X-latched by mtr |
1239 | +@param rec in/out: clustered index record |
1240 | +@param offsets in: rec_get_offsets(rec, index); |
1241 | + the "external storage" flags in offsets will not be adjusted |
1242 | +@param mtr in: mini-transaction that holds x-latch on index and b |
1243 | +@param upd in: TRUE if the record is updated in place (not delete+insert) |
1244 | +@param big in: vector containing fields to be stored externally |
1245 | +@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ |
1246 | +#ifdef UNIV_DEBUG |
1247 | +# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \ |
1248 | + btr_store_big_rec_extern_fields_func(index,b,rec,offsets,mtr,upd,big) |
1249 | +#elif defined UNIV_BLOB_LIGHT_DEBUG |
1250 | +# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \ |
1251 | + btr_store_big_rec_extern_fields_func(index,b,rec,offsets,upd,big) |
1252 | +#else |
1253 | +# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \ |
1254 | + btr_store_big_rec_extern_fields_func(index,b,rec,offsets,big) |
1255 | +#endif |
1256 | + |
1257 | /*******************************************************************//** |
1258 | Frees the space in an externally stored field to the file space |
1259 | management if the field in data is owned the externally stored field, |
1260 | |
1261 | === modified file 'plugin/innobase/include/buf0buf.h' |
1262 | --- plugin/innobase/include/buf0buf.h 2012-05-23 00:15:24 +0000 |
1263 | +++ plugin/innobase/include/buf0buf.h 2012-05-23 00:15:24 +0000 |
1264 | @@ -273,9 +273,9 @@ |
1265 | buf_block_t* |
1266 | buf_block_alloc( |
1267 | /*============*/ |
1268 | - buf_pool_t* buf_pool, /*!< buffer pool instance */ |
1269 | - ulint zip_size); /*!< in: compressed page size in bytes, |
1270 | - or 0 if uncompressed tablespace */ |
1271 | + buf_pool_t* buf_pool); /*!< in: buffer pool instance, |
1272 | + or NULL for round-robin selection |
1273 | + of the buffer pool */ |
1274 | /********************************************************************//** |
1275 | Frees a buffer block which does not contain a file page. */ |
1276 | UNIV_INLINE |
1277 | @@ -477,7 +477,7 @@ |
1278 | /*================================*/ |
1279 | ulint space, /*!< in: space id */ |
1280 | ulint offset);/*!< in: page number */ |
1281 | -#ifdef UNIV_DEBUG_FILE_ACCESSES |
1282 | +#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
1283 | /********************************************************************//** |
1284 | Sets file_page_was_freed TRUE if the page is found in the buffer pool. |
1285 | This function should be called when we free a file page and want the |
1286 | @@ -502,7 +502,7 @@ |
1287 | /*===============================*/ |
1288 | ulint space, /*!< in: space id */ |
1289 | ulint offset); /*!< in: page number */ |
1290 | -#endif /* UNIV_DEBUG_FILE_ACCESSES */ |
1291 | +#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
1292 | /********************************************************************//** |
1293 | Reads the freed_page_clock of a buffer block. |
1294 | @return freed_page_clock */ |
1295 | @@ -1400,11 +1400,11 @@ |
1296 | 0 if the block was never accessed |
1297 | in the buffer pool */ |
1298 | /* @} */ |
1299 | -# ifdef UNIV_DEBUG_FILE_ACCESSES |
1300 | +# if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
1301 | ibool file_page_was_freed; |
1302 | /*!< this is set to TRUE when fsp |
1303 | frees a page in buffer pool */ |
1304 | -# endif /* UNIV_DEBUG_FILE_ACCESSES */ |
1305 | +# endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
1306 | #endif /* !UNIV_HOTBACKUP */ |
1307 | }; |
1308 | |
1309 | |
1310 | === modified file 'plugin/innobase/include/buf0lru.h' |
1311 | --- plugin/innobase/include/buf0lru.h 2011-04-07 12:10:16 +0000 |
1312 | +++ plugin/innobase/include/buf0lru.h 2012-05-23 00:15:24 +0000 |
1313 | @@ -113,12 +113,9 @@ |
1314 | buf_LRU_free_block( |
1315 | /*===============*/ |
1316 | buf_page_t* bpage, /*!< in: block to be freed */ |
1317 | - ibool zip, /*!< in: TRUE if should remove also the |
1318 | + ibool zip) /*!< in: TRUE if should remove also the |
1319 | compressed page of an uncompressed page */ |
1320 | - ibool* buf_pool_mutex_released); |
1321 | - /*!< in: pointer to a variable that will |
1322 | - be assigned TRUE if buf_pool->mutex |
1323 | - was temporarily released, or NULL */ |
1324 | + __attribute__((nonnull)); |
1325 | /******************************************************************//** |
1326 | Try to free a replaceable block. |
1327 | @return TRUE if found and freed */ |
1328 | @@ -155,9 +152,8 @@ |
1329 | buf_block_t* |
1330 | buf_LRU_get_free_block( |
1331 | /*===================*/ |
1332 | - buf_pool_t* buf_pool, /*!< in: preferred buffer pool */ |
1333 | - ulint zip_size); /*!< in: compressed page size in bytes, |
1334 | - or 0 if uncompressed tablespace */ |
1335 | + buf_pool_t* buf_pool) /*!< in/out: buffer pool instance */ |
1336 | + __attribute__((nonnull,warn_unused_result)); |
1337 | |
1338 | /******************************************************************//** |
1339 | Puts a block back to the free list. */ |
1340 | |
1341 | === modified file 'plugin/innobase/include/dict0mem.h' |
1342 | --- plugin/innobase/include/dict0mem.h 2012-05-23 00:15:24 +0000 |
1343 | +++ plugin/innobase/include/dict0mem.h 2012-05-23 00:15:24 +0000 |
1344 | @@ -377,6 +377,12 @@ |
1345 | dict_get_n_unique(index); we |
1346 | periodically calculate new |
1347 | estimates */ |
1348 | + ib_int64_t* stat_n_non_null_key_vals; |
1349 | + /* approximate number of non-null key values |
1350 | + for this index, for each column where |
1351 | + n < dict_get_n_unique(index); This |
1352 | + is used when innodb_stats_method is |
1353 | + "nulls_ignored". */ |
1354 | ulint stat_index_size; |
1355 | /*!< approximate index size in |
1356 | database pages */ |
1357 | |
1358 | === modified file 'plugin/innobase/include/dict0types.h' |
1359 | --- plugin/innobase/include/dict0types.h 2011-03-14 05:40:28 +0000 |
1360 | +++ plugin/innobase/include/dict0types.h 2012-05-23 00:15:24 +0000 |
1361 | @@ -34,11 +34,6 @@ |
1362 | typedef struct dict_table_struct dict_table_t; |
1363 | typedef struct dict_foreign_struct dict_foreign_t; |
1364 | |
1365 | -/* A cluster object is a table object with the type field set to |
1366 | -DICT_CLUSTERED */ |
1367 | - |
1368 | -typedef dict_table_t dict_cluster_t; |
1369 | - |
1370 | typedef struct ind_node_struct ind_node_t; |
1371 | typedef struct tab_node_struct tab_node_t; |
1372 | |
1373 | |
1374 | === modified file 'plugin/innobase/include/rem0cmp.h' |
1375 | --- plugin/innobase/include/rem0cmp.h 2011-03-14 05:40:28 +0000 |
1376 | +++ plugin/innobase/include/rem0cmp.h 2012-05-23 00:15:24 +0000 |
1377 | @@ -166,6 +166,10 @@ |
1378 | const ulint* offsets1,/*!< in: rec_get_offsets(rec1, index) */ |
1379 | const ulint* offsets2,/*!< in: rec_get_offsets(rec2, index) */ |
1380 | dict_index_t* index, /*!< in: data dictionary index */ |
1381 | + ibool nulls_unequal, |
1382 | + /* in: TRUE if this is for index statistics |
1383 | + cardinality estimation, and innodb_stats_method |
1384 | + is "nulls_unequal" or "nulls_ignored" */ |
1385 | ulint* matched_fields, /*!< in/out: number of already completely |
1386 | matched fields; when the function returns, |
1387 | contains the value the for current |
1388 | |
1389 | === modified file 'plugin/innobase/include/rem0cmp.ic' |
1390 | --- plugin/innobase/include/rem0cmp.ic 2010-12-18 04:43:40 +0000 |
1391 | +++ plugin/innobase/include/rem0cmp.ic 2012-05-23 00:15:24 +0000 |
1392 | @@ -87,5 +87,5 @@ |
1393 | ulint match_b = 0; |
1394 | |
1395 | return(cmp_rec_rec_with_match(rec1, rec2, offsets1, offsets2, index, |
1396 | - &match_f, &match_b)); |
1397 | + FALSE, &match_f, &match_b)); |
1398 | } |
1399 | |
1400 | === modified file 'plugin/innobase/include/row0upd.h' |
1401 | --- plugin/innobase/include/row0upd.h 2012-05-23 00:15:24 +0000 |
1402 | +++ plugin/innobase/include/row0upd.h 2012-05-23 00:15:24 +0000 |
1403 | @@ -281,19 +281,29 @@ |
1404 | @return TRUE if update vector changes an ordering field in the index record */ |
1405 | UNIV_INTERN |
1406 | ibool |
1407 | -row_upd_changes_ord_field_binary( |
1408 | -/*=============================*/ |
1409 | +row_upd_changes_ord_field_binary_func( |
1410 | +/*==================================*/ |
1411 | + dict_index_t* index, /*!< in: index of the record */ |
1412 | + const upd_t* update, /*!< in: update vector for the row; NOTE: the |
1413 | + field numbers in this MUST be clustered index |
1414 | + positions! */ |
1415 | +#ifdef UNIV_DEBUG |
1416 | + const que_thr_t*thr, /*!< in: query thread */ |
1417 | +#endif /* UNIV_DEBUG */ |
1418 | const dtuple_t* row, /*!< in: old value of row, or NULL if the |
1419 | row and the data values in update are not |
1420 | known when this function is called, e.g., at |
1421 | compile time */ |
1422 | - const row_ext_t*ext, /*!< NULL, or prefixes of the externally |
1423 | + const row_ext_t*ext) /*!< NULL, or prefixes of the externally |
1424 | stored columns in the old row */ |
1425 | - dict_index_t* index, /*!< in: index of the record */ |
1426 | - const upd_t* update) /*!< in: update vector for the row; NOTE: the |
1427 | - field numbers in this MUST be clustered index |
1428 | - positions! */ |
1429 | - __attribute__((nonnull(3,4), warn_unused_result)); |
1430 | + __attribute__((nonnull(1,2), warn_unused_result)); |
1431 | +#ifdef UNIV_DEBUG |
1432 | +# define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \ |
1433 | + row_upd_changes_ord_field_binary_func(index,update,thr,row,ext) |
1434 | +#else /* UNIV_DEBUG */ |
1435 | +# define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \ |
1436 | + row_upd_changes_ord_field_binary_func(index,update,row,ext) |
1437 | +#endif /* UNIV_DEBUG */ |
1438 | /***********************************************************//** |
1439 | Checks if an update vector changes an ordering field of an index record. |
1440 | This function is fast if the update vector is short or the number of ordering |
1441 | |
1442 | === modified file 'plugin/innobase/include/srv0srv.h' |
1443 | --- plugin/innobase/include/srv0srv.h 2012-05-23 00:15:24 +0000 |
1444 | +++ plugin/innobase/include/srv0srv.h 2012-05-23 00:15:24 +0000 |
1445 | @@ -183,6 +183,11 @@ |
1446 | is 5% of the max where max is srv_io_capacity. */ |
1447 | #define PCT_IO(p) ((ulong) (srv_io_capacity * ((double) p / 100.0))) |
1448 | |
1449 | +/* The "innodb_stats_method" setting, decides how InnoDB is going |
1450 | +to treat NULL value when collecting statistics. It is not defined |
1451 | +as enum type because the configure option takes unsigned integer type. */ |
1452 | +extern ulong srv_innodb_stats_method; |
1453 | + |
1454 | #ifdef UNIV_LOG_ARCHIVE |
1455 | extern ibool srv_log_archive_on; |
1456 | extern ibool srv_archive_recovery; |
1457 | @@ -445,6 +450,19 @@ |
1458 | in connection with recovery */ |
1459 | }; |
1460 | |
1461 | +/* Alternatives for srv_innodb_stats_method, which could be changed by |
1462 | +setting innodb_stats_method */ |
1463 | +enum srv_stats_method_name_enum { |
1464 | + SRV_STATS_NULLS_EQUAL, /* All NULL values are treated as |
1465 | + equal. This is the default setting |
1466 | + for innodb_stats_method */ |
1467 | + SRV_STATS_NULLS_UNEQUAL, /* All NULL values are treated as |
1468 | + NOT equal. */ |
1469 | + SRV_STATS_NULLS_IGNORED /* NULL values are ignored */ |
1470 | +}; |
1471 | + |
1472 | +typedef enum srv_stats_method_name_enum srv_stats_method_name_t; |
1473 | + |
1474 | #ifndef UNIV_HOTBACKUP |
1475 | /** Types of threads existing in the system. */ |
1476 | enum srv_thread_type { |
1477 | |
1478 | === modified file 'plugin/innobase/include/sync0rw.h' |
1479 | --- plugin/innobase/include/sync0rw.h 2012-05-23 00:15:24 +0000 |
1480 | +++ plugin/innobase/include/sync0rw.h 2012-05-23 00:15:24 +0000 |
1481 | @@ -1,6 +1,6 @@ |
1482 | /***************************************************************************** |
1483 | |
1484 | -Copyright (C) 1995, 2010, Innobase Oy. All Rights Reserved. |
1485 | +Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. |
1486 | Copyright (C) 2008, Google Inc. |
1487 | |
1488 | Portions of this file contain modifications contributed and copyrighted by |
1489 | @@ -556,6 +556,7 @@ |
1490 | void |
1491 | rw_lock_debug_print( |
1492 | /*================*/ |
1493 | + FILE* f, /*!< in: output stream */ |
1494 | rw_lock_debug_t* info); /*!< in: debug struct */ |
1495 | #endif /* UNIV_SYNC_DEBUG */ |
1496 | |
1497 | |
1498 | === modified file 'plugin/innobase/include/trx0rseg.h' |
1499 | --- plugin/innobase/include/trx0rseg.h 2011-03-14 05:40:28 +0000 |
1500 | +++ plugin/innobase/include/trx0rseg.h 2012-05-23 00:15:24 +0000 |
1501 | @@ -142,9 +142,7 @@ |
1502 | ulint id; /*!< rollback segment id == the index of |
1503 | its slot in the trx system file copy */ |
1504 | mutex_t mutex; /*!< mutex protecting the fields in this |
1505 | - struct except id; NOTE that the latching |
1506 | - order must always be kernel mutex -> |
1507 | - rseg mutex */ |
1508 | + struct except id, which is constant */ |
1509 | ulint space; /*!< space where the rollback segment is |
1510 | header is placed */ |
1511 | ulint zip_size;/* compressed page size of space |
1512 | |
1513 | === modified file 'plugin/innobase/include/trx0trx.h' |
1514 | --- plugin/innobase/include/trx0trx.h 2011-03-14 05:40:28 +0000 |
1515 | +++ plugin/innobase/include/trx0trx.h 2012-05-23 00:15:24 +0000 |
1516 | @@ -225,12 +225,12 @@ |
1517 | /*******************************************************************//** |
1518 | This function is used to find one X/Open XA distributed transaction |
1519 | which is in the prepared state |
1520 | -@return trx or NULL */ |
1521 | +@return trx or NULL; on match, the trx->xid will be invalidated */ |
1522 | UNIV_INTERN |
1523 | trx_t * |
1524 | trx_get_trx_by_xid( |
1525 | /*===============*/ |
1526 | - XID* xid); /*!< in: X/Open XA transaction identification */ |
1527 | + const XID* xid); /*!< in: X/Open XA transaction identifier */ |
1528 | /**********************************************************************//** |
1529 | If required, flushes the log to disk if we called trx_commit_for_mysql() |
1530 | with trx->flush_log_later == TRUE. |
1531 | |
1532 | === modified file 'plugin/innobase/include/univ.i' |
1533 | --- plugin/innobase/include/univ.i 2012-05-23 00:15:24 +0000 |
1534 | +++ plugin/innobase/include/univ.i 2012-05-23 00:15:24 +0000 |
1535 | @@ -204,14 +204,15 @@ |
1536 | debugging without UNIV_DEBUG */ |
1537 | #define UNIV_BUF_DEBUG /* Enable buffer pool |
1538 | debugging without UNIV_DEBUG */ |
1539 | +#define UNIV_BLOB_LIGHT_DEBUG /* Enable off-page column |
1540 | + debugging without UNIV_DEBUG */ |
1541 | #define UNIV_DEBUG /* Enable ut_ad() assertions |
1542 | and disable UNIV_INLINE */ |
1543 | #define UNIV_DEBUG_LOCK_VALIDATE /* Enable |
1544 | ut_ad(lock_rec_validate_page()) |
1545 | assertions. */ |
1546 | -#define UNIV_DEBUG_FILE_ACCESSES /* Debug .ibd file access |
1547 | - (field file_page_was_freed |
1548 | - in buf_page_t) */ |
1549 | +#define UNIV_DEBUG_FILE_ACCESSES /* Enable freed block access |
1550 | + debugging without UNIV_DEBUG */ |
1551 | #define UNIV_LRU_DEBUG /* debug the buffer pool LRU */ |
1552 | #define UNIV_HASH_DEBUG /* debug HASH_ macros */ |
1553 | #define UNIV_LIST_DEBUG /* debug UT_LIST_ macros */ |
1554 | |
1555 | === modified file 'plugin/innobase/mem/mem0mem.cc' |
1556 | --- plugin/innobase/mem/mem0mem.cc 2010-12-26 00:22:34 +0000 |
1557 | +++ plugin/innobase/mem/mem0mem.cc 2012-05-23 00:15:24 +0000 |
1558 | @@ -348,7 +348,7 @@ |
1559 | return(NULL); |
1560 | } |
1561 | } else { |
1562 | - buf_block = buf_block_alloc(NULL, 0); |
1563 | + buf_block = buf_block_alloc(NULL); |
1564 | } |
1565 | |
1566 | block = (mem_block_t*) buf_block->frame; |
1567 | |
1568 | === modified file 'plugin/innobase/page/page0zip.cc' |
1569 | --- plugin/innobase/page/page0zip.cc 2011-04-05 10:32:12 +0000 |
1570 | +++ plugin/innobase/page/page0zip.cc 2012-05-23 00:15:24 +0000 |
1571 | @@ -4434,7 +4434,7 @@ |
1572 | log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); |
1573 | |
1574 | #ifndef UNIV_HOTBACKUP |
1575 | - temp_block = buf_block_alloc(buf_pool, 0); |
1576 | + temp_block = buf_block_alloc(buf_pool); |
1577 | btr_search_drop_page_hash_index(block); |
1578 | block->check_index_page_at_flush = TRUE; |
1579 | #else /* !UNIV_HOTBACKUP */ |
1580 | |
1581 | === modified file 'plugin/innobase/rem/rem0cmp.cc' |
1582 | --- plugin/innobase/rem/rem0cmp.cc 2010-12-27 05:56:47 +0000 |
1583 | +++ plugin/innobase/rem/rem0cmp.cc 2012-05-23 00:15:24 +0000 |
1584 | @@ -861,6 +861,10 @@ |
1585 | const ulint* offsets1,/*!< in: rec_get_offsets(rec1, index) */ |
1586 | const ulint* offsets2,/*!< in: rec_get_offsets(rec2, index) */ |
1587 | dict_index_t* index, /*!< in: data dictionary index */ |
1588 | + ibool nulls_unequal, |
1589 | + /* in: TRUE if this is for index statistics |
1590 | + cardinality estimation, and innodb_stats_method |
1591 | + is "nulls_unequal" or "nulls_ignored" */ |
1592 | ulint* matched_fields, /*!< in/out: number of already completely |
1593 | matched fields; when the function returns, |
1594 | contains the value the for current |
1595 | @@ -960,9 +964,13 @@ |
1596 | || rec2_f_len == UNIV_SQL_NULL) { |
1597 | |
1598 | if (rec1_f_len == rec2_f_len) { |
1599 | - |
1600 | - goto next_field; |
1601 | - |
1602 | + /* This is limited to stats collection, |
1603 | + cannot use it for regular search */ |
1604 | + if (nulls_unequal) { |
1605 | + ret = -1; |
1606 | + } else { |
1607 | + goto next_field; |
1608 | + } |
1609 | } else if (rec2_f_len == UNIV_SQL_NULL) { |
1610 | |
1611 | /* We define the SQL null to be the |
1612 | |
1613 | === modified file 'plugin/innobase/row/row0ins.cc' |
1614 | --- plugin/innobase/row/row0ins.cc 2012-05-23 00:15:24 +0000 |
1615 | +++ plugin/innobase/row/row0ins.cc 2012-05-23 00:15:24 +0000 |
1616 | @@ -2123,7 +2123,7 @@ |
1617 | |
1618 | err = btr_store_big_rec_extern_fields( |
1619 | index, btr_cur_get_block(&cursor), |
1620 | - exit_rec, offsets, big_rec, &mtr); |
1621 | + exit_rec, offsets, &mtr, FALSE, big_rec); |
1622 | |
1623 | if (modify) { |
1624 | dtuple_big_rec_free(big_rec); |
1625 | |
1626 | === modified file 'plugin/innobase/row/row0merge.cc' |
1627 | --- plugin/innobase/row/row0merge.cc 2012-05-23 00:15:24 +0000 |
1628 | +++ plugin/innobase/row/row0merge.cc 2012-05-23 00:15:24 +0000 |
1629 | @@ -2193,13 +2193,15 @@ |
1630 | } |
1631 | |
1632 | /*********************************************************************//** |
1633 | -Create a merge file. */ |
1634 | -static |
1635 | -void |
1636 | -row_merge_file_create( |
1637 | -/*==================*/ |
1638 | - merge_file_t* merge_file) /*!< out: merge file structure */ |
1639 | +Creates temperary merge files, and if UNIV_PFS_IO defined, register |
1640 | +the file descriptor with Performance Schema. |
1641 | +@return File descriptor */ |
1642 | +UNIV_INLINE |
1643 | +int |
1644 | +row_merge_file_create_low(void) |
1645 | +/*===========================*/ |
1646 | { |
1647 | + int fd; |
1648 | #ifdef UNIV_PFS_IO |
1649 | /* This temp file open does not go through normal |
1650 | file APIs, add instrumentation to register with |
1651 | @@ -2211,15 +2213,47 @@ |
1652 | "Innodb Merge Temp File", |
1653 | __FILE__, __LINE__); |
1654 | #endif |
1655 | - merge_file->fd = innobase_mysql_tmpfile(); |
1656 | + fd = innobase_mysql_tmpfile(); |
1657 | +#ifdef UNIV_PFS_IO |
1658 | + register_pfs_file_open_end(locker, fd); |
1659 | +#endif |
1660 | + return(fd); |
1661 | +} |
1662 | +/*********************************************************************//** |
1663 | +Create a merge file. */ |
1664 | +static |
1665 | +void |
1666 | +row_merge_file_create( |
1667 | +/*==================*/ |
1668 | + merge_file_t* merge_file) /*!< out: merge file structure */ |
1669 | +{ |
1670 | + merge_file->fd = row_merge_file_create_low(); |
1671 | merge_file->offset = 0; |
1672 | merge_file->n_rec = 0; |
1673 | -#ifdef UNIV_PFS_IO |
1674 | - register_pfs_file_open_end(locker, merge_file->fd); |
1675 | -#endif |
1676 | } |
1677 | |
1678 | /*********************************************************************//** |
1679 | +Destroy a merge file. And de-register the file from Performance Schema |
1680 | +if UNIV_PFS_IO is defined. */ |
1681 | +UNIV_INLINE |
1682 | +void |
1683 | +row_merge_file_destroy_low( |
1684 | +/*=======================*/ |
1685 | + int fd) /*!< in: merge file descriptor */ |
1686 | +{ |
1687 | +#ifdef UNIV_PFS_IO |
1688 | + struct PSI_file_locker* locker = NULL; |
1689 | + PSI_file_locker_state state; |
1690 | + register_pfs_file_io_begin(&state, locker, |
1691 | + fd, 0, PSI_FILE_CLOSE, |
1692 | + __FILE__, __LINE__); |
1693 | +#endif |
1694 | + close(fd); |
1695 | +#ifdef UNIV_PFS_IO |
1696 | + register_pfs_file_io_end(locker, 0); |
1697 | +#endif |
1698 | +} |
1699 | +/*********************************************************************//** |
1700 | Destroy a merge file. */ |
1701 | static |
1702 | void |
1703 | @@ -2227,20 +2261,10 @@ |
1704 | /*===================*/ |
1705 | merge_file_t* merge_file) /*!< out: merge file structure */ |
1706 | { |
1707 | -#ifdef UNIV_PFS_IO |
1708 | - struct PSI_file_locker* locker = NULL; |
1709 | - PSI_file_locker_state state; |
1710 | - register_pfs_file_io_begin(&state, locker, merge_file->fd, 0, PSI_FILE_CLOSE, |
1711 | - __FILE__, __LINE__); |
1712 | -#endif |
1713 | if (merge_file->fd != -1) { |
1714 | - close(merge_file->fd); |
1715 | + row_merge_file_destroy_low(merge_file->fd); |
1716 | merge_file->fd = -1; |
1717 | } |
1718 | - |
1719 | -#ifdef UNIV_PFS_IO |
1720 | - register_pfs_file_io_end(locker, 0); |
1721 | -#endif |
1722 | } |
1723 | |
1724 | /*********************************************************************//** |
1725 | @@ -2646,7 +2670,7 @@ |
1726 | row_merge_file_create(&merge_files[i]); |
1727 | } |
1728 | |
1729 | - tmpfd = innobase_mysql_tmpfile(); |
1730 | + tmpfd = row_merge_file_create_low(); |
1731 | |
1732 | /* Reset the MySQL row buffer that is used when reporting |
1733 | duplicate keys. */ |
1734 | @@ -2688,7 +2712,7 @@ |
1735 | } |
1736 | |
1737 | func_exit: |
1738 | - close(tmpfd); |
1739 | + row_merge_file_destroy_low(tmpfd); |
1740 | |
1741 | for (i = 0; i < n_indexes; i++) { |
1742 | row_merge_file_destroy(&merge_files[i]); |
1743 | |
1744 | === modified file 'plugin/innobase/row/row0purge.cc' |
1745 | --- plugin/innobase/row/row0purge.cc 2012-05-23 00:15:24 +0000 |
1746 | +++ plugin/innobase/row/row0purge.cc 2012-05-23 00:15:24 +0000 |
1747 | @@ -499,8 +499,11 @@ |
1748 | marked record if that record contained an externally stored field. */ |
1749 | static |
1750 | void |
1751 | -row_purge_upd_exist_or_extern( |
1752 | -/*==========================*/ |
1753 | +row_purge_upd_exist_or_extern_func( |
1754 | +/*===============================*/ |
1755 | +#ifdef UNIV_DEBUG |
1756 | + const que_thr_t*thr, /*!< in: query thread */ |
1757 | +#endif /* UNIV_DEBUG */ |
1758 | purge_node_t* node) /*!< in: row purge node */ |
1759 | { |
1760 | mem_heap_t* heap; |
1761 | @@ -525,8 +528,8 @@ |
1762 | while (node->index != NULL) { |
1763 | index = node->index; |
1764 | |
1765 | - if (row_upd_changes_ord_field_binary(NULL, NULL, node->index, |
1766 | - node->update)) { |
1767 | + if (row_upd_changes_ord_field_binary(node->index, node->update, |
1768 | + thr, NULL, NULL)) { |
1769 | /* Build the older version of the index entry */ |
1770 | entry = row_build_index_entry(node->row, NULL, |
1771 | index, heap); |
1772 | @@ -608,6 +611,14 @@ |
1773 | } |
1774 | } |
1775 | |
1776 | +#ifdef UNIV_DEBUG |
1777 | +# define row_purge_upd_exist_or_extern(thr,node) \ |
1778 | + row_purge_upd_exist_or_extern_func(thr,node) |
1779 | +#else /* UNIV_DEBUG */ |
1780 | +# define row_purge_upd_exist_or_extern(thr,node) \ |
1781 | + row_purge_upd_exist_or_extern_func(node) |
1782 | +#endif /* UNIV_DEBUG */ |
1783 | + |
1784 | /***********************************************************//** |
1785 | Parses the row reference and other info in a modify undo log record. |
1786 | @return TRUE if purge operation required: NOTE that then the CALLER |
1787 | @@ -714,47 +725,32 @@ |
1788 | /***********************************************************//** |
1789 | Fetches an undo log record and does the purge for the recorded operation. |
1790 | If none left, or the current purge completed, returns the control to the |
1791 | -parent node, which is always a query thread node. |
1792 | -@return DB_SUCCESS if operation successfully completed, else error code */ |
1793 | -static |
1794 | -ulint |
1795 | +parent node, which is always a query thread node. */ |
1796 | +static __attribute__((nonnull)) |
1797 | +void |
1798 | row_purge( |
1799 | /*======*/ |
1800 | purge_node_t* node, /*!< in: row purge node */ |
1801 | que_thr_t* thr) /*!< in: query thread */ |
1802 | { |
1803 | - roll_ptr_t roll_ptr; |
1804 | - ibool purge_needed; |
1805 | ibool updated_extern; |
1806 | - trx_t* trx; |
1807 | - |
1808 | - ut_ad(node && thr); |
1809 | - |
1810 | - trx = thr_get_trx(thr); |
1811 | - |
1812 | - node->undo_rec = trx_purge_fetch_next_rec(&roll_ptr, |
1813 | - &(node->reservation), |
1814 | + |
1815 | + ut_ad(node); |
1816 | + ut_ad(thr); |
1817 | + |
1818 | + node->undo_rec = trx_purge_fetch_next_rec(&node->roll_ptr, |
1819 | + &node->reservation, |
1820 | node->heap); |
1821 | if (!node->undo_rec) { |
1822 | /* Purge completed for this query thread */ |
1823 | |
1824 | thr->run_node = que_node_get_parent(node); |
1825 | |
1826 | - return(DB_SUCCESS); |
1827 | - } |
1828 | - |
1829 | - node->roll_ptr = roll_ptr; |
1830 | - |
1831 | - if (node->undo_rec == &trx_purge_dummy_rec) { |
1832 | - purge_needed = FALSE; |
1833 | - } else { |
1834 | - purge_needed = row_purge_parse_undo_rec(node, &updated_extern, |
1835 | - thr); |
1836 | - /* If purge_needed == TRUE, we must also remember to unfreeze |
1837 | - data dictionary! */ |
1838 | - } |
1839 | - |
1840 | - if (purge_needed) { |
1841 | + return; |
1842 | + } |
1843 | + |
1844 | + if (node->undo_rec != &trx_purge_dummy_rec |
1845 | + && row_purge_parse_undo_rec(node, &updated_extern, thr)) { |
1846 | node->found_clust = FALSE; |
1847 | |
1848 | node->index = dict_table_get_next_index( |
1849 | @@ -766,14 +762,14 @@ |
1850 | } else if (updated_extern |
1851 | || node->rec_type == TRX_UNDO_UPD_EXIST_REC) { |
1852 | |
1853 | - row_purge_upd_exist_or_extern(node); |
1854 | + row_purge_upd_exist_or_extern(thr, node); |
1855 | } |
1856 | |
1857 | if (node->found_clust) { |
1858 | btr_pcur_close(&(node->pcur)); |
1859 | } |
1860 | |
1861 | - row_mysql_unfreeze_data_dictionary(trx); |
1862 | + row_mysql_unfreeze_data_dictionary(thr_get_trx(thr)); |
1863 | } |
1864 | |
1865 | /* Do some cleanup */ |
1866 | @@ -781,8 +777,6 @@ |
1867 | mem_heap_empty(node->heap); |
1868 | |
1869 | thr->run_node = node; |
1870 | - |
1871 | - return(DB_SUCCESS); |
1872 | } |
1873 | |
1874 | /***********************************************************//** |
1875 | @@ -796,9 +790,6 @@ |
1876 | que_thr_t* thr) /*!< in: query thread */ |
1877 | { |
1878 | purge_node_t* node; |
1879 | -#ifdef UNIV_DEBUG |
1880 | - ulint err; |
1881 | -#endif /* UNIV_DEBUG */ |
1882 | |
1883 | ut_ad(thr); |
1884 | |
1885 | @@ -806,14 +797,7 @@ |
1886 | |
1887 | ut_ad(que_node_get_type(node) == QUE_NODE_PURGE); |
1888 | |
1889 | -#ifdef UNIV_DEBUG |
1890 | - err = |
1891 | -#endif /* UNIV_DEBUG */ |
1892 | row_purge(node, thr); |
1893 | |
1894 | -#ifdef UNIV_DEBUG |
1895 | - ut_a(err == DB_SUCCESS); |
1896 | -#endif /* UNIV_DEBUG */ |
1897 | - |
1898 | return(thr); |
1899 | } |
1900 | |
1901 | === modified file 'plugin/innobase/row/row0umod.cc' |
1902 | --- plugin/innobase/row/row0umod.cc 2012-05-23 00:15:24 +0000 |
1903 | +++ plugin/innobase/row/row0umod.cc 2012-05-23 00:15:24 +0000 |
1904 | @@ -173,40 +173,26 @@ |
1905 | mtr_t* mtr, /*!< in: mtr */ |
1906 | ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ |
1907 | { |
1908 | - btr_pcur_t* pcur; |
1909 | btr_cur_t* btr_cur; |
1910 | ulint err; |
1911 | - ibool success; |
1912 | |
1913 | ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC); |
1914 | - pcur = &(node->pcur); |
1915 | - btr_cur = btr_pcur_get_btr_cur(pcur); |
1916 | - |
1917 | - success = btr_pcur_restore_position(mode, pcur, mtr); |
1918 | - |
1919 | - if (!success) { |
1920 | - |
1921 | - return(DB_SUCCESS); |
1922 | - } |
1923 | - |
1924 | - /* Find out if we can remove the whole clustered index record */ |
1925 | - |
1926 | - if (node->rec_type == TRX_UNDO_UPD_DEL_REC |
1927 | - && !row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) { |
1928 | - |
1929 | - /* Ok, we can remove */ |
1930 | - } else { |
1931 | - return(DB_SUCCESS); |
1932 | - } |
1933 | + |
1934 | + /* Find out if the record has been purged already |
1935 | + or if we can remove it. */ |
1936 | + |
1937 | + if (!btr_pcur_restore_position(mode, &node->pcur, mtr) |
1938 | + || row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) { |
1939 | + |
1940 | + return(DB_SUCCESS); |
1941 | + } |
1942 | + |
1943 | + btr_cur = btr_pcur_get_btr_cur(&node->pcur); |
1944 | |
1945 | if (mode == BTR_MODIFY_LEAF) { |
1946 | - success = btr_cur_optimistic_delete(btr_cur, mtr); |
1947 | - |
1948 | - if (success) { |
1949 | - err = DB_SUCCESS; |
1950 | - } else { |
1951 | - err = DB_FAIL; |
1952 | - } |
1953 | + err = btr_cur_optimistic_delete(btr_cur, mtr) |
1954 | + ? DB_SUCCESS |
1955 | + : DB_FAIL; |
1956 | } else { |
1957 | ut_ad(mode == BTR_MODIFY_TREE); |
1958 | |
1959 | @@ -693,8 +679,9 @@ |
1960 | while (node->index != NULL) { |
1961 | index = node->index; |
1962 | |
1963 | - if (row_upd_changes_ord_field_binary( |
1964 | - node->row, node->ext, node->index, node->update)) { |
1965 | + if (row_upd_changes_ord_field_binary(node->index, node->update, |
1966 | + thr, |
1967 | + node->row, node->ext)) { |
1968 | |
1969 | /* Build the newest version of the index entry */ |
1970 | entry = row_build_index_entry(node->row, node->ext, |
1971 | |
1972 | === modified file 'plugin/innobase/row/row0upd.cc' |
1973 | --- plugin/innobase/row/row0upd.cc 2012-05-23 00:15:24 +0000 |
1974 | +++ plugin/innobase/row/row0upd.cc 2012-05-23 00:15:24 +0000 |
1975 | @@ -1202,25 +1202,31 @@ |
1976 | @return TRUE if update vector changes an ordering field in the index record */ |
1977 | UNIV_INTERN |
1978 | ibool |
1979 | -row_upd_changes_ord_field_binary( |
1980 | -/*=============================*/ |
1981 | +row_upd_changes_ord_field_binary_func( |
1982 | +/*==================================*/ |
1983 | + dict_index_t* index, /*!< in: index of the record */ |
1984 | + const upd_t* update, /*!< in: update vector for the row; NOTE: the |
1985 | + field numbers in this MUST be clustered index |
1986 | + positions! */ |
1987 | +#ifdef UNIV_DEBUG |
1988 | + const que_thr_t*thr, /*!< in: query thread */ |
1989 | +#endif /* UNIV_DEBUG */ |
1990 | const dtuple_t* row, /*!< in: old value of row, or NULL if the |
1991 | row and the data values in update are not |
1992 | known when this function is called, e.g., at |
1993 | compile time */ |
1994 | - const row_ext_t*ext, /*!< NULL, or prefixes of the externally |
1995 | + const row_ext_t*ext) /*!< NULL, or prefixes of the externally |
1996 | stored columns in the old row */ |
1997 | - dict_index_t* index, /*!< in: index of the record */ |
1998 | - const upd_t* update) /*!< in: update vector for the row; NOTE: the |
1999 | - field numbers in this MUST be clustered index |
2000 | - positions! */ |
2001 | { |
2002 | ulint n_unique; |
2003 | ulint i; |
2004 | const dict_index_t* clust_index; |
2005 | |
2006 | + ut_ad(index); |
2007 | ut_ad(update); |
2008 | - ut_ad(index); |
2009 | + ut_ad(thr); |
2010 | + ut_ad(thr->graph); |
2011 | + ut_ad(thr->graph->trx); |
2012 | |
2013 | n_unique = dict_index_get_n_unique(index); |
2014 | |
2015 | @@ -1262,6 +1268,10 @@ |
2016 | || dfield_is_null(dfield)) { |
2017 | /* do nothing special */ |
2018 | } else if (UNIV_LIKELY_NULL(ext)) { |
2019 | + /* Silence a compiler warning without |
2020 | + silencing a Valgrind error. */ |
2021 | + dfield_len = 0; |
2022 | + UNIV_MEM_INVALID(&dfield_len, sizeof dfield_len); |
2023 | /* See if the column is stored externally. */ |
2024 | buf = row_ext_lookup(ext, col_no, &dfield_len); |
2025 | |
2026 | @@ -1269,9 +1279,14 @@ |
2027 | |
2028 | if (UNIV_LIKELY_NULL(buf)) { |
2029 | if (UNIV_UNLIKELY(buf == field_ref_zero)) { |
2030 | - /* This should never happen, but |
2031 | - we try to fail safe here. */ |
2032 | - ut_ad(0); |
2033 | + /* The externally stored field |
2034 | + was not written yet. This |
2035 | + record should only be seen by |
2036 | + recv_recovery_rollback_active(), |
2037 | + when the server had crashed before |
2038 | + storing the field. */ |
2039 | + ut_ad(thr->graph->trx->is_recovered); |
2040 | + ut_ad(trx_is_recv(thr->graph->trx)); |
2041 | return(TRUE); |
2042 | } |
2043 | |
2044 | @@ -1646,8 +1661,8 @@ |
2045 | ut_ad(!dict_index_is_clust(node->index)); |
2046 | |
2047 | if (node->state == UPD_NODE_UPDATE_ALL_SEC |
2048 | - || row_upd_changes_ord_field_binary(node->row, node->ext, |
2049 | - node->index, node->update)) { |
2050 | + || row_upd_changes_ord_field_binary(node->index, node->update, |
2051 | + thr, node->row, node->ext)) { |
2052 | return(row_upd_sec_index_entry(node, thr)); |
2053 | } |
2054 | |
2055 | @@ -1978,7 +1993,7 @@ |
2056 | index, btr_cur_get_block(btr_cur), rec, |
2057 | rec_get_offsets(rec, index, offsets_, |
2058 | ULINT_UNDEFINED, &heap), |
2059 | - big_rec, mtr); |
2060 | + mtr, TRUE, big_rec); |
2061 | mtr_commit(mtr); |
2062 | } |
2063 | |
2064 | @@ -2176,8 +2191,8 @@ |
2065 | |
2066 | row_upd_store_row(node); |
2067 | |
2068 | - if (row_upd_changes_ord_field_binary(node->row, node->ext, index, |
2069 | - node->update)) { |
2070 | + if (row_upd_changes_ord_field_binary(index, node->update, thr, |
2071 | + node->row, node->ext)) { |
2072 | |
2073 | /* Update causes an ordering field (ordering fields within |
2074 | the B-tree) of the clustered index record to change: perform |
2075 | |
2076 | === modified file 'plugin/innobase/row/row0vers.cc' |
2077 | --- plugin/innobase/row/row0vers.cc 2010-12-26 15:48:26 +0000 |
2078 | +++ plugin/innobase/row/row0vers.cc 2012-05-23 00:15:24 +0000 |
2079 | @@ -669,11 +669,15 @@ |
2080 | |
2081 | mutex_enter(&kernel_mutex); |
2082 | version_trx = trx_get_on_id(version_trx_id); |
2083 | + if (version_trx |
2084 | + && (version_trx->conc_state == TRX_COMMITTED_IN_MEMORY |
2085 | + || version_trx->conc_state == TRX_NOT_STARTED)) { |
2086 | + |
2087 | + version_trx = NULL; |
2088 | + } |
2089 | mutex_exit(&kernel_mutex); |
2090 | |
2091 | - if (!version_trx |
2092 | - || version_trx->conc_state == TRX_NOT_STARTED |
2093 | - || version_trx->conc_state == TRX_COMMITTED_IN_MEMORY) { |
2094 | + if (!version_trx) { |
2095 | |
2096 | /* We found a version that belongs to a |
2097 | committed transaction: return it. */ |
2098 | |
2099 | === modified file 'plugin/innobase/srv/srv0srv.cc' |
2100 | --- plugin/innobase/srv/srv0srv.cc 2012-05-23 00:15:24 +0000 |
2101 | +++ plugin/innobase/srv/srv0srv.cc 2012-05-23 00:15:24 +0000 |
2102 | @@ -321,6 +321,11 @@ |
2103 | /* variable counts amount of data read in total (in bytes) */ |
2104 | UNIV_INTERN ulint srv_data_read = 0; |
2105 | |
2106 | +/* Internal setting for "innodb_stats_method". Decides how InnoDB treats |
2107 | +NULL value when collecting statistics. By default, it is set to |
2108 | +SRV_STATS_NULLS_EQUAL(0), ie. all NULL value are treated equal */ |
2109 | +ulong srv_innodb_stats_method = SRV_STATS_NULLS_EQUAL; |
2110 | + |
2111 | /* here we count the amount of data written in total (in bytes) */ |
2112 | UNIV_INTERN ulint srv_data_written = 0; |
2113 | |
2114 | @@ -1067,7 +1072,7 @@ |
2115 | |
2116 | slot = srv_table_get_nth_slot(i); |
2117 | |
2118 | - if (slot->in_use && slot->type == type) { |
2119 | + if (slot->in_use && slot->type == (unsigned int)type) { |
2120 | slot_no = i; |
2121 | break; |
2122 | } |
2123 | |
2124 | === modified file 'plugin/innobase/srv/srv0start.cc' |
2125 | --- plugin/innobase/srv/srv0start.cc 2012-05-23 00:15:24 +0000 |
2126 | +++ plugin/innobase/srv/srv0start.cc 2012-05-23 00:15:24 +0000 |
2127 | @@ -1261,13 +1261,16 @@ |
2128 | |
2129 | ut_a(srv_n_file_io_threads <= SRV_MAX_N_IO_THREADS); |
2130 | |
2131 | - /* TODO: Investigate if SRV_N_PENDING_IOS_PER_THREAD (32) limit |
2132 | - still applies to windows. */ |
2133 | - if (!srv_use_native_aio) { |
2134 | - io_limit = 8 * SRV_N_PENDING_IOS_PER_THREAD; |
2135 | - } else { |
2136 | + io_limit = 8 * SRV_N_PENDING_IOS_PER_THREAD; |
2137 | + |
2138 | + /* On Windows when using native aio the number of aio requests |
2139 | + that a thread can handle at a given time is limited to 32 |
2140 | + i.e.: SRV_N_PENDING_IOS_PER_THREAD */ |
2141 | +# ifdef __WIN__ |
2142 | + if (srv_use_native_aio) { |
2143 | io_limit = SRV_N_PENDING_IOS_PER_THREAD; |
2144 | } |
2145 | +# endif /* __WIN__ */ |
2146 | |
2147 | os_aio_init(io_limit, |
2148 | srv_n_read_io_threads, |
2149 | |
2150 | === modified file 'plugin/innobase/sync/sync0arr.cc' |
2151 | --- plugin/innobase/sync/sync0arr.cc 2012-05-23 00:15:24 +0000 |
2152 | +++ plugin/innobase/sync/sync0arr.cc 2012-05-23 00:15:24 +0000 |
2153 | @@ -1,6 +1,6 @@ |
2154 | /***************************************************************************** |
2155 | |
2156 | -Copyright (C) 1995, 2009, Innobase Oy. All Rights Reserved. |
2157 | +Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. |
2158 | Copyright (C) 2008, Google Inc. |
2159 | |
2160 | Portions of this file contain modifications contributed and copyrighted by |
2161 | @@ -714,7 +714,7 @@ |
2162 | fprintf(stderr, "rw-lock %p ", |
2163 | (void*) lock); |
2164 | sync_array_cell_print(stderr, cell); |
2165 | - rw_lock_debug_print(debug); |
2166 | + rw_lock_debug_print(stderr, debug); |
2167 | return(TRUE); |
2168 | } |
2169 | } |
2170 | |
2171 | === modified file 'plugin/innobase/sync/sync0rw.cc' |
2172 | --- plugin/innobase/sync/sync0rw.cc 2010-12-24 00:04:05 +0000 |
2173 | +++ plugin/innobase/sync/sync0rw.cc 2012-05-23 00:15:24 +0000 |
2174 | @@ -1,6 +1,6 @@ |
2175 | /***************************************************************************** |
2176 | |
2177 | -Copyright (C) 1995, 2009, Innobase Oy. All Rights Reserved. |
2178 | +Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. |
2179 | Copyright (C) 2008, Google Inc. |
2180 | |
2181 | Portions of this file contain modifications contributed and copyrighted by |
2182 | @@ -936,7 +936,7 @@ |
2183 | |
2184 | info = UT_LIST_GET_FIRST(lock->debug_list); |
2185 | while (info != NULL) { |
2186 | - rw_lock_debug_print(info); |
2187 | + rw_lock_debug_print(file, info); |
2188 | info = UT_LIST_GET_NEXT(list, info); |
2189 | } |
2190 | } |
2191 | @@ -984,7 +984,7 @@ |
2192 | |
2193 | info = UT_LIST_GET_FIRST(lock->debug_list); |
2194 | while (info != NULL) { |
2195 | - rw_lock_debug_print(info); |
2196 | + rw_lock_debug_print(stderr, info); |
2197 | info = UT_LIST_GET_NEXT(list, info); |
2198 | } |
2199 | } |
2200 | @@ -996,28 +996,29 @@ |
2201 | void |
2202 | rw_lock_debug_print( |
2203 | /*================*/ |
2204 | + FILE* f, /*!< in: output stream */ |
2205 | rw_lock_debug_t* info) /*!< in: debug struct */ |
2206 | { |
2207 | ulint rwt; |
2208 | |
2209 | rwt = info->lock_type; |
2210 | |
2211 | - fprintf(stderr, "Locked: thread %lu file %s line %lu ", |
2212 | + fprintf(f, "Locked: thread %lu file %s line %lu ", |
2213 | (ulong) os_thread_pf(info->thread_id), info->file_name, |
2214 | (ulong) info->line); |
2215 | if (rwt == RW_LOCK_SHARED) { |
2216 | - fputs("S-LOCK", stderr); |
2217 | + fputs("S-LOCK", f); |
2218 | } else if (rwt == RW_LOCK_EX) { |
2219 | - fputs("X-LOCK", stderr); |
2220 | + fputs("X-LOCK", f); |
2221 | } else if (rwt == RW_LOCK_WAIT_EX) { |
2222 | - fputs("WAIT X-LOCK", stderr); |
2223 | + fputs("WAIT X-LOCK", f); |
2224 | } else { |
2225 | ut_error; |
2226 | } |
2227 | if (info->pass != 0) { |
2228 | - fprintf(stderr, " pass value %lu", (ulong) info->pass); |
2229 | + fprintf(f, " pass value %lu", (ulong) info->pass); |
2230 | } |
2231 | - putc('\n', stderr); |
2232 | + putc('\n', f); |
2233 | } |
2234 | |
2235 | /***************************************************************//** |
2236 | |
2237 | === modified file 'plugin/innobase/sync/sync0sync.cc' |
2238 | --- plugin/innobase/sync/sync0sync.cc 2011-10-20 02:45:57 +0000 |
2239 | +++ plugin/innobase/sync/sync0sync.cc 2012-05-23 00:15:24 +0000 |
2240 | @@ -189,11 +189,12 @@ |
2241 | UNIV_INTERN ibool sync_initialized = FALSE; |
2242 | |
2243 | /** An acquired mutex or rw-lock and its level in the latching order */ |
2244 | -typedef struct sync_level_struct sync_priority_t; |
2245 | +typedef struct sync_level_struct sync_level_t; |
2246 | /** Mutexes or rw-locks held by a thread */ |
2247 | typedef struct sync_thread_struct sync_thread_t; |
2248 | |
2249 | #ifdef UNIV_SYNC_DEBUG |
2250 | + |
2251 | /** The latch levels currently owned by threads are stored in this data |
2252 | structure; the size of this array is OS_THREAD_MAX_N */ |
2253 | |
2254 | @@ -222,21 +223,40 @@ |
2255 | UNIV_INTERN ibool sync_order_checks_on = FALSE; |
2256 | #endif /* UNIV_SYNC_DEBUG */ |
2257 | |
2258 | +/** Number of slots reserved for each OS thread in the sync level array */ |
2259 | +static const ulint SYNC_THREAD_N_LEVELS = 10000; |
2260 | + |
2261 | +typedef struct sync_arr_struct sync_arr_t; |
2262 | + |
2263 | +/** Array for tracking sync levels per thread. */ |
2264 | +struct sync_arr_struct { |
2265 | + ulint in_use; /*!< Number of active cells */ |
2266 | + ulint n_elems; /*!< Number of elements in the array */ |
2267 | + ulint max_elems; /*!< Maximum elements */ |
2268 | + ulint next_free; /*!< ULINT_UNDEFINED or index of next |
2269 | + free slot */ |
2270 | + sync_level_t* elems; /*!< Array elements */ |
2271 | +}; |
2272 | + |
2273 | /** Mutexes or rw-locks held by a thread */ |
2274 | struct sync_thread_struct{ |
2275 | - os_thread_id_t id; /*!< OS thread id */ |
2276 | - sync_priority_t* levels; /*!< level array for this thread; if |
2277 | - this is NULL this slot is unused */ |
2278 | + os_thread_id_t id; /*!< OS thread id */ |
2279 | + sync_arr_t* levels; /*!< level array for this thread; if |
2280 | + this is NULL this slot is unused */ |
2281 | }; |
2282 | |
2283 | -/** Number of slots reserved for each OS thread in the sync level array */ |
2284 | -#define SYNC_THREAD_N_LEVELS 10000 |
2285 | - |
2286 | /** An acquired mutex or rw-lock and its level in the latching order */ |
2287 | struct sync_level_struct{ |
2288 | - void* latch; /*!< pointer to a mutex or an rw-lock; NULL means that |
2289 | - the slot is empty */ |
2290 | - ulint level; /*!< level of the latch in the latching order */ |
2291 | + void* latch; /*!< pointer to a mutex or an |
2292 | + rw-lock; NULL means that |
2293 | + the slot is empty */ |
2294 | + ulint level; /*!< level of the latch in the |
2295 | + latching order. This field is |
2296 | + overloaded to serve as a node in a |
2297 | + linked list of free nodes too. When |
2298 | + latch == NULL then this will contain |
2299 | + the ordinal value of the next free |
2300 | + element */ |
2301 | }; |
2302 | |
2303 | /******************************************************************//** |
2304 | @@ -745,27 +765,28 @@ |
2305 | /*==================*/ |
2306 | { |
2307 | mutex_t* mutex; |
2308 | - ulint count = 0; |
2309 | + ulint count = 0; |
2310 | |
2311 | mutex_enter(&mutex_list_mutex); |
2312 | |
2313 | - mutex = UT_LIST_GET_FIRST(mutex_list); |
2314 | + for (mutex = UT_LIST_GET_FIRST(mutex_list); |
2315 | + mutex != NULL; |
2316 | + mutex = UT_LIST_GET_NEXT(list, mutex)) { |
2317 | |
2318 | - while (mutex != NULL) { |
2319 | if (mutex_get_lock_word(mutex) != 0) { |
2320 | |
2321 | count++; |
2322 | } |
2323 | - |
2324 | - mutex = UT_LIST_GET_NEXT(list, mutex); |
2325 | } |
2326 | |
2327 | mutex_exit(&mutex_list_mutex); |
2328 | |
2329 | ut_a(count >= 1); |
2330 | |
2331 | - return(count - 1); /* Subtract one, because this function itself |
2332 | - was holding one mutex (mutex_list_mutex) */ |
2333 | + /* Subtract one, because this function itself was holding |
2334 | + one mutex (mutex_list_mutex) */ |
2335 | + |
2336 | + return(count - 1); |
2337 | } |
2338 | |
2339 | /******************************************************************//** |
2340 | @@ -781,20 +802,6 @@ |
2341 | } |
2342 | |
2343 | /******************************************************************//** |
2344 | -Gets the value in the nth slot in the thread level arrays. |
2345 | -@return pointer to thread slot */ |
2346 | -static |
2347 | -sync_thread_t* |
2348 | -sync_thread_level_arrays_get_nth( |
2349 | -/*=============================*/ |
2350 | - ulint n) /*!< in: slot number */ |
2351 | -{ |
2352 | - ut_ad(n < OS_THREAD_MAX_N); |
2353 | - |
2354 | - return(sync_thread_level_arrays + n); |
2355 | -} |
2356 | - |
2357 | -/******************************************************************//** |
2358 | Looks for the thread slot for the calling thread. |
2359 | @return pointer to thread slot, NULL if not found */ |
2360 | static |
2361 | @@ -803,15 +810,15 @@ |
2362 | /*====================================*/ |
2363 | |
2364 | { |
2365 | - sync_thread_t* slot; |
2366 | + ulint i; |
2367 | os_thread_id_t id; |
2368 | - ulint i; |
2369 | |
2370 | id = os_thread_get_curr_id(); |
2371 | |
2372 | for (i = 0; i < OS_THREAD_MAX_N; i++) { |
2373 | + sync_thread_t* slot; |
2374 | |
2375 | - slot = sync_thread_level_arrays_get_nth(i); |
2376 | + slot = &sync_thread_level_arrays[i]; |
2377 | |
2378 | if (slot->levels && os_thread_eq(slot->id, id)) { |
2379 | |
2380 | @@ -831,12 +838,12 @@ |
2381 | /*====================================*/ |
2382 | |
2383 | { |
2384 | - sync_thread_t* slot; |
2385 | ulint i; |
2386 | |
2387 | for (i = 0; i < OS_THREAD_MAX_N; i++) { |
2388 | + sync_thread_t* slot; |
2389 | |
2390 | - slot = sync_thread_level_arrays_get_nth(i); |
2391 | + slot = &sync_thread_level_arrays[i]; |
2392 | |
2393 | if (slot->levels == NULL) { |
2394 | |
2395 | @@ -849,18 +856,44 @@ |
2396 | |
2397 | /******************************************************************//** |
2398 | Gets the value in the nth slot in the thread level array. |
2399 | -@return pointer to level slot */ |
2400 | +Print warning. */ |
2401 | static |
2402 | -sync_priority_t* |
2403 | -sync_thread_levels_get_nth( |
2404 | -/*=======================*/ |
2405 | - sync_priority_t* arr, /*!< in: pointer to level array for an OS |
2406 | - thread */ |
2407 | - ulint n) /*!< in: slot number */ |
2408 | +void |
2409 | +sync_print_warning( |
2410 | +/*===============*/ |
2411 | + const sync_level_t* slot) /*!< in: slot for which to |
2412 | + print warning */ |
2413 | { |
2414 | - ut_ad(n < SYNC_THREAD_N_LEVELS); |
2415 | - |
2416 | - return(arr + n); |
2417 | + mutex_t* mutex; |
2418 | + |
2419 | + mutex = slot->latch; |
2420 | + |
2421 | + if (mutex->magic_n == MUTEX_MAGIC_N) { |
2422 | + fprintf(stderr, |
2423 | + "Mutex created at %s %lu\n", |
2424 | + mutex->cfile_name, (ulong) mutex->cline); |
2425 | + |
2426 | + if (mutex_get_lock_word(mutex) != 0) { |
2427 | + ulint line; |
2428 | + const char* file_name; |
2429 | + os_thread_id_t thread_id; |
2430 | + |
2431 | + mutex_get_debug_info( |
2432 | + mutex, &file_name, &line, &thread_id); |
2433 | + |
2434 | + fprintf(stderr, |
2435 | + "InnoDB: Locked mutex:" |
2436 | + " addr %p thread %ld file %s line %ld\n", |
2437 | + (void*) mutex, os_thread_pf(thread_id), |
2438 | + file_name, (ulong) line); |
2439 | + } else { |
2440 | + fputs("Not locked\n", stderr); |
2441 | + } |
2442 | + } else { |
2443 | + rw_lock_t* lock = slot->latch; |
2444 | + |
2445 | + rw_lock_print(lock); |
2446 | + } |
2447 | } |
2448 | |
2449 | /******************************************************************//** |
2450 | @@ -871,69 +904,29 @@ |
2451 | ibool |
2452 | sync_thread_levels_g( |
2453 | /*=================*/ |
2454 | - sync_priority_t* arr, /*!< in: pointer to level array for an OS |
2455 | + sync_arr_t* arr, /*!< in: pointer to level array for an OS |
2456 | thread */ |
2457 | ulint limit, /*!< in: level limit */ |
2458 | ulint warn) /*!< in: TRUE=display a diagnostic message */ |
2459 | { |
2460 | - sync_priority_t* slot; |
2461 | - rw_lock_t* lock; |
2462 | - mutex_t* mutex; |
2463 | ulint i; |
2464 | |
2465 | - for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { |
2466 | - |
2467 | - slot = sync_thread_levels_get_nth(arr, i); |
2468 | - |
2469 | - if (slot->latch != NULL) { |
2470 | - if (slot->level <= limit) { |
2471 | - |
2472 | - if (!warn) { |
2473 | - |
2474 | - return(FALSE); |
2475 | - } |
2476 | - |
2477 | - lock = slot->latch; |
2478 | - mutex = slot->latch; |
2479 | - |
2480 | + for (i = 0; i < arr->n_elems; i++) { |
2481 | + const sync_level_t* slot; |
2482 | + |
2483 | + slot = &arr->elems[i]; |
2484 | + |
2485 | + if (slot->latch != NULL && slot->level <= limit) { |
2486 | + if (warn) { |
2487 | fprintf(stderr, |
2488 | "InnoDB: sync levels should be" |
2489 | " > %lu but a level is %lu\n", |
2490 | (ulong) limit, (ulong) slot->level); |
2491 | - |
2492 | - if (mutex->magic_n == MUTEX_MAGIC_N) { |
2493 | - fprintf(stderr, |
2494 | - "Mutex created at %s %lu\n", |
2495 | - mutex->cfile_name, |
2496 | - (ulong) mutex->cline); |
2497 | - |
2498 | - if (mutex_get_lock_word(mutex) != 0) { |
2499 | - const char* file_name; |
2500 | - ulint line; |
2501 | - os_thread_id_t thread_id; |
2502 | - |
2503 | - mutex_get_debug_info( |
2504 | - mutex, &file_name, |
2505 | - &line, &thread_id); |
2506 | - |
2507 | - fprintf(stderr, |
2508 | - "InnoDB: Locked mutex:" |
2509 | - " addr %p thread %ld" |
2510 | - " file %s line %ld\n", |
2511 | - (void*) mutex, |
2512 | - os_thread_pf( |
2513 | - thread_id), |
2514 | - file_name, |
2515 | - (ulong) line); |
2516 | - } else { |
2517 | - fputs("Not locked\n", stderr); |
2518 | - } |
2519 | - } else { |
2520 | - rw_lock_print(lock); |
2521 | - } |
2522 | - |
2523 | - return(FALSE); |
2524 | + sync_print_warning(slot); |
2525 | } |
2526 | + |
2527 | + return(FALSE); |
2528 | + |
2529 | } |
2530 | } |
2531 | |
2532 | @@ -942,31 +935,28 @@ |
2533 | |
2534 | /******************************************************************//** |
2535 | Checks if the level value is stored in the level array. |
2536 | -@return TRUE if stored */ |
2537 | +@return slot if found or NULL */ |
2538 | static |
2539 | -ibool |
2540 | +const sync_level_t* |
2541 | sync_thread_levels_contain( |
2542 | /*=======================*/ |
2543 | - sync_priority_t* arr, /*!< in: pointer to level array for an OS |
2544 | + sync_arr_t* arr, /*!< in: pointer to level array for an OS |
2545 | thread */ |
2546 | ulint level) /*!< in: level */ |
2547 | { |
2548 | - sync_priority_t* slot; |
2549 | ulint i; |
2550 | |
2551 | - for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { |
2552 | - |
2553 | - slot = sync_thread_levels_get_nth(arr, i); |
2554 | - |
2555 | - if (slot->latch != NULL) { |
2556 | - if (slot->level == level) { |
2557 | - |
2558 | - return(TRUE); |
2559 | - } |
2560 | + for (i = 0; i < arr->n_elems; i++) { |
2561 | + const sync_level_t* slot; |
2562 | + |
2563 | + slot = &arr->elems[i]; |
2564 | + |
2565 | + if (slot->latch != NULL && slot->level == level) { |
2566 | + return(slot); |
2567 | } |
2568 | } |
2569 | |
2570 | - return(FALSE); |
2571 | + return(NULL); |
2572 | } |
2573 | |
2574 | /******************************************************************//** |
2575 | @@ -980,10 +970,9 @@ |
2576 | ulint level) /*!< in: latching order level |
2577 | (SYNC_DICT, ...)*/ |
2578 | { |
2579 | - sync_priority_t* arr; |
2580 | + ulint i; |
2581 | + sync_arr_t* arr; |
2582 | sync_thread_t* thread_slot; |
2583 | - sync_priority_t* slot; |
2584 | - ulint i; |
2585 | |
2586 | if (!sync_order_checks_on) { |
2587 | |
2588 | @@ -1003,9 +992,10 @@ |
2589 | |
2590 | arr = thread_slot->levels; |
2591 | |
2592 | - for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { |
2593 | + for (i = 0; i < arr->n_elems; i++) { |
2594 | + sync_level_t* slot; |
2595 | |
2596 | - slot = sync_thread_levels_get_nth(arr, i); |
2597 | + slot = &arr->elems[i]; |
2598 | |
2599 | if (slot->latch != NULL && slot->level == level) { |
2600 | |
2601 | @@ -1031,10 +1021,9 @@ |
2602 | also purge_is_running mutex is |
2603 | allowed */ |
2604 | { |
2605 | - sync_priority_t* arr; |
2606 | + ulint i; |
2607 | + sync_arr_t* arr; |
2608 | sync_thread_t* thread_slot; |
2609 | - sync_priority_t* slot; |
2610 | - ulint i; |
2611 | |
2612 | if (!sync_order_checks_on) { |
2613 | |
2614 | @@ -1054,9 +1043,10 @@ |
2615 | |
2616 | arr = thread_slot->levels; |
2617 | |
2618 | - for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { |
2619 | + for (i = 0; i < arr->n_elems; ++i) { |
2620 | + const sync_level_t* slot; |
2621 | |
2622 | - slot = sync_thread_levels_get_nth(arr, i); |
2623 | + slot = &arr->elems[i]; |
2624 | |
2625 | if (slot->latch != NULL |
2626 | && (!dict_mutex_allowed |
2627 | @@ -1098,10 +1088,10 @@ |
2628 | ulint level) /*!< in: level in the latching order; if |
2629 | SYNC_LEVEL_VARYING, nothing is done */ |
2630 | { |
2631 | - sync_priority_t* array; |
2632 | - sync_priority_t* slot; |
2633 | + ulint i; |
2634 | + sync_level_t* slot; |
2635 | + sync_arr_t* array; |
2636 | sync_thread_t* thread_slot; |
2637 | - ulint i; |
2638 | |
2639 | if (!sync_order_checks_on) { |
2640 | |
2641 | @@ -1126,20 +1116,22 @@ |
2642 | thread_slot = sync_thread_level_arrays_find_slot(); |
2643 | |
2644 | if (thread_slot == NULL) { |
2645 | + ulint sz; |
2646 | + |
2647 | + sz = sizeof(*array) |
2648 | + + (sizeof(*array->elems) * SYNC_THREAD_N_LEVELS); |
2649 | + |
2650 | /* We have to allocate the level array for a new thread */ |
2651 | - array = ut_malloc(sizeof(sync_priority_t) * SYNC_THREAD_N_LEVELS); |
2652 | + array = calloc(sz, sizeof(char)); |
2653 | + ut_a(array != NULL); |
2654 | + |
2655 | + array->next_free = ULINT_UNDEFINED; |
2656 | + array->max_elems = SYNC_THREAD_N_LEVELS; |
2657 | + array->elems = (sync_level_t*) &array[1]; |
2658 | |
2659 | thread_slot = sync_thread_level_arrays_find_free(); |
2660 | - |
2661 | + thread_slot->levels = array; |
2662 | thread_slot->id = os_thread_get_curr_id(); |
2663 | - thread_slot->levels = array; |
2664 | - |
2665 | - for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { |
2666 | - |
2667 | - slot = sync_thread_levels_get_nth(array, i); |
2668 | - |
2669 | - slot->latch = NULL; |
2670 | - } |
2671 | } |
2672 | |
2673 | array = thread_slot->levels; |
2674 | @@ -1303,19 +1295,26 @@ |
2675 | ut_error; |
2676 | } |
2677 | |
2678 | - for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { |
2679 | - |
2680 | - slot = sync_thread_levels_get_nth(array, i); |
2681 | - |
2682 | - if (slot->latch == NULL) { |
2683 | - slot->latch = latch; |
2684 | - slot->level = level; |
2685 | - |
2686 | - break; |
2687 | - } |
2688 | + if (array->next_free == ULINT_UNDEFINED) { |
2689 | + ut_a(array->n_elems < array->max_elems); |
2690 | + |
2691 | + i = array->n_elems++; |
2692 | + } else { |
2693 | + i = array->next_free; |
2694 | + array->next_free = array->elems[i].level; |
2695 | } |
2696 | |
2697 | - ut_a(i < SYNC_THREAD_N_LEVELS); |
2698 | + ut_a(i < array->n_elems); |
2699 | + ut_a(i != ULINT_UNDEFINED); |
2700 | + |
2701 | + ++array->in_use; |
2702 | + |
2703 | + slot = &array->elems[i]; |
2704 | + |
2705 | + ut_a(slot->latch == NULL); |
2706 | + |
2707 | + slot->latch = latch; |
2708 | + slot->level = level; |
2709 | |
2710 | mutex_exit(&sync_thread_mutex); |
2711 | } |
2712 | @@ -1331,8 +1330,7 @@ |
2713 | /*====================*/ |
2714 | void* latch) /*!< in: pointer to a mutex or an rw-lock */ |
2715 | { |
2716 | - sync_priority_t* array; |
2717 | - sync_priority_t* slot; |
2718 | + sync_arr_t* array; |
2719 | sync_thread_t* thread_slot; |
2720 | ulint i; |
2721 | |
2722 | @@ -1363,17 +1361,37 @@ |
2723 | |
2724 | array = thread_slot->levels; |
2725 | |
2726 | - for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) { |
2727 | - |
2728 | - slot = sync_thread_levels_get_nth(array, i); |
2729 | - |
2730 | - if (slot->latch == latch) { |
2731 | - slot->latch = NULL; |
2732 | - |
2733 | - mutex_exit(&sync_thread_mutex); |
2734 | - |
2735 | - return(TRUE); |
2736 | - } |
2737 | + for (i = 0; i < array->n_elems; i++) { |
2738 | + sync_level_t* slot; |
2739 | + |
2740 | + slot = &array->elems[i]; |
2741 | + |
2742 | + if (slot->latch != latch) { |
2743 | + continue; |
2744 | + } |
2745 | + |
2746 | + slot->latch = NULL; |
2747 | + |
2748 | + /* Update the free slot list. See comment in sync_level_t |
2749 | + for the level field. */ |
2750 | + slot->level = array->next_free; |
2751 | + array->next_free = i; |
2752 | + |
2753 | + ut_a(array->in_use >= 1); |
2754 | + --array->in_use; |
2755 | + |
2756 | + /* If all cells are idle then reset the free |
2757 | + list. The assumption is that this will save |
2758 | + time when we need to scan up to n_elems. */ |
2759 | + |
2760 | + if (array->in_use == 0) { |
2761 | + array->n_elems = 0; |
2762 | + array->next_free = ULINT_UNDEFINED; |
2763 | + } |
2764 | + |
2765 | + mutex_exit(&sync_thread_mutex); |
2766 | + |
2767 | + return(TRUE); |
2768 | } |
2769 | |
2770 | if (((mutex_t*) latch)->magic_n != MUTEX_MAGIC_N) { |
2771 | @@ -1403,11 +1421,6 @@ |
2772 | sync_init(void) |
2773 | /*===========*/ |
2774 | { |
2775 | -#ifdef UNIV_SYNC_DEBUG |
2776 | - sync_thread_t* thread_slot; |
2777 | - ulint i; |
2778 | -#endif /* UNIV_SYNC_DEBUG */ |
2779 | - |
2780 | ut_a(sync_initialized == FALSE); |
2781 | |
2782 | sync_initialized = TRUE; |
2783 | @@ -1421,13 +1434,10 @@ |
2784 | /* Create the thread latch level array where the latch levels |
2785 | are stored for each OS thread */ |
2786 | |
2787 | - sync_thread_level_arrays = ut_malloc(OS_THREAD_MAX_N |
2788 | - * sizeof(sync_thread_t)); |
2789 | - for (i = 0; i < OS_THREAD_MAX_N; i++) { |
2790 | + sync_thread_level_arrays = calloc( |
2791 | + sizeof(sync_thread_t), OS_THREAD_MAX_N); |
2792 | + ut_a(sync_thread_level_arrays != NULL); |
2793 | |
2794 | - thread_slot = sync_thread_level_arrays_get_nth(i); |
2795 | - thread_slot->levels = NULL; |
2796 | - } |
2797 | #endif /* UNIV_SYNC_DEBUG */ |
2798 | /* Init the mutex list and create the mutex to protect it. */ |
2799 | |
2800 | @@ -1454,6 +1464,34 @@ |
2801 | #endif /* UNIV_SYNC_DEBUG */ |
2802 | } |
2803 | |
2804 | +#ifdef UNIV_SYNC_DEBUG |
2805 | +/******************************************************************//** |
2806 | +Frees all debug memory. */ |
2807 | +static |
2808 | +void |
2809 | +sync_thread_level_arrays_free(void) |
2810 | +/*===============================*/ |
2811 | + |
2812 | +{ |
2813 | + ulint i; |
2814 | + |
2815 | + for (i = 0; i < OS_THREAD_MAX_N; i++) { |
2816 | + sync_thread_t* slot; |
2817 | + |
2818 | + slot = &sync_thread_level_arrays[i]; |
2819 | + |
2820 | + /* If this slot was allocated then free the slot memory too. */ |
2821 | + if (slot->levels != NULL) { |
2822 | + free(slot->levels); |
2823 | + slot->levels = NULL; |
2824 | + } |
2825 | + } |
2826 | + |
2827 | + free(sync_thread_level_arrays); |
2828 | + sync_thread_level_arrays = NULL; |
2829 | +} |
2830 | +#endif /* UNIV_SYNC_DEBUG */ |
2831 | + |
2832 | /******************************************************************//** |
2833 | Frees the resources in InnoDB's own synchronization data structures. Use |
2834 | os_sync_free() after calling this. */ |
2835 | @@ -1466,17 +1504,20 @@ |
2836 | |
2837 | sync_array_free(sync_primary_wait_array); |
2838 | |
2839 | - mutex = UT_LIST_GET_FIRST(mutex_list); |
2840 | + for (mutex = UT_LIST_GET_FIRST(mutex_list); |
2841 | + mutex != NULL; |
2842 | + /* No op */) { |
2843 | |
2844 | - while (mutex) { |
2845 | #ifdef UNIV_MEM_DEBUG |
2846 | if (mutex == &mem_hash_mutex) { |
2847 | mutex = UT_LIST_GET_NEXT(list, mutex); |
2848 | continue; |
2849 | } |
2850 | #endif /* UNIV_MEM_DEBUG */ |
2851 | + |
2852 | mutex_free(mutex); |
2853 | - mutex = UT_LIST_GET_FIRST(mutex_list); |
2854 | + |
2855 | + mutex = UT_LIST_GET_FIRST(mutex_list); |
2856 | } |
2857 | |
2858 | mutex_free(&mutex_list_mutex); |
2859 | @@ -1485,6 +1526,8 @@ |
2860 | |
2861 | /* Switch latching order checks on in sync0sync.c */ |
2862 | sync_order_checks_on = FALSE; |
2863 | + |
2864 | + sync_thread_level_arrays_free(); |
2865 | #endif /* UNIV_SYNC_DEBUG */ |
2866 | |
2867 | sync_initialized = FALSE; |
2868 | |
2869 | === modified file 'plugin/innobase/trx/trx0roll.cc' |
2870 | --- plugin/innobase/trx/trx0roll.cc 2010-12-27 18:39:11 +0000 |
2871 | +++ plugin/innobase/trx/trx0roll.cc 2012-05-23 00:15:24 +0000 |
2872 | @@ -47,8 +47,8 @@ |
2873 | rollback */ |
2874 | #define TRX_ROLL_TRUNC_THRESHOLD 1 |
2875 | |
2876 | -/** In crash recovery, the current trx to be rolled back */ |
2877 | -static trx_t* trx_roll_crash_recv_trx = NULL; |
2878 | +/** In crash recovery, the current trx to be rolled back; NULL otherwise */ |
2879 | +static const trx_t* trx_roll_crash_recv_trx = NULL; |
2880 | |
2881 | /** In crash recovery we set this to the undo n:o of the current trx to be |
2882 | rolled back. Then we can print how many % the rollback has progressed. */ |
2883 | |
2884 | === modified file 'plugin/innobase/trx/trx0trx.cc' |
2885 | --- plugin/innobase/trx/trx0trx.cc 2011-02-07 03:54:06 +0000 |
2886 | +++ plugin/innobase/trx/trx0trx.cc 2012-05-23 00:15:24 +0000 |
2887 | @@ -1994,18 +1994,18 @@ |
2888 | /*******************************************************************//** |
2889 | This function is used to find one X/Open XA distributed transaction |
2890 | which is in the prepared state |
2891 | -@return trx or NULL */ |
2892 | +@return trx or NULL; on match, the trx->xid will be invalidated */ |
2893 | UNIV_INTERN |
2894 | trx_t* |
2895 | trx_get_trx_by_xid( |
2896 | /*===============*/ |
2897 | - XID* xid) /*!< in: X/Open XA transaction identification */ |
2898 | + const XID* xid) /*!< in: X/Open XA transaction identifier */ |
2899 | { |
2900 | trx_t* trx; |
2901 | |
2902 | if (xid == NULL) { |
2903 | |
2904 | - return (NULL); |
2905 | + return(NULL); |
2906 | } |
2907 | |
2908 | mutex_enter(&kernel_mutex); |
2909 | @@ -2018,10 +2018,16 @@ |
2910 | of gtrid_length+bqual_length bytes should be |
2911 | the same */ |
2912 | |
2913 | - if (xid->gtrid_length == trx->xid.gtrid_length |
2914 | + if (trx->conc_state == TRX_PREPARED |
2915 | + && xid->gtrid_length == trx->xid.gtrid_length |
2916 | && xid->bqual_length == trx->xid.bqual_length |
2917 | && memcmp(xid->data, trx->xid.data, |
2918 | xid->gtrid_length + xid->bqual_length) == 0) { |
2919 | + |
2920 | + /* Invalidate the XID, so that subsequent calls |
2921 | + will not find it. */ |
2922 | + memset(&trx->xid, 0, sizeof(trx->xid)); |
2923 | + trx->xid.formatID = -1; |
2924 | break; |
2925 | } |
2926 | |
2927 | @@ -2030,14 +2036,5 @@ |
2928 | |
2929 | mutex_exit(&kernel_mutex); |
2930 | |
2931 | - if (trx) { |
2932 | - if (trx->conc_state != TRX_PREPARED) { |
2933 | - |
2934 | - return(NULL); |
2935 | - } |
2936 | - |
2937 | - return(trx); |
2938 | - } else { |
2939 | - return(NULL); |
2940 | - } |
2941 | + return(trx); |
2942 | } |
Why 5.5.10? It's like a year old. Why not latest and greatest? 5.5.24?