Merge lp:~stewart/drizzle/7.1-innodb-1.1.5 into lp:drizzle/7.1

Proposed by Stewart Smith
Status: Merged
Merged at revision: 2550
Proposed branch: lp:~stewart/drizzle/7.1-innodb-1.1.5
Merge into: lp:drizzle/7.1
Diff against target: 3520 lines (+1778/-498)
46 files modified
plugin/innobase/btr/btr0btr.cc (+1/-1)
plugin/innobase/btr/btr0cur.cc (+28/-132)
plugin/innobase/buf/buf0buf.cc (+272/-83)
plugin/innobase/buf/buf0flu.cc (+30/-2)
plugin/innobase/buf/buf0lru.cc (+12/-4)
plugin/innobase/dict/dict0dict.cc (+45/-30)
plugin/innobase/dict/dict0load.cc (+17/-3)
plugin/innobase/dict/dict0mem.cc (+56/-0)
plugin/innobase/fil/fil0fil.cc (+32/-4)
plugin/innobase/fsp/fsp0fsp.cc (+1/-1)
plugin/innobase/handler/ha_innodb.cc (+1/-1)
plugin/innobase/ibuf/ibuf0ibuf.cc (+96/-17)
plugin/innobase/include/btr0cur.h (+14/-28)
plugin/innobase/include/buf0buf.h (+70/-0)
plugin/innobase/include/data0data.h (+8/-3)
plugin/innobase/include/data0data.ic (+18/-8)
plugin/innobase/include/dict0mem.h (+24/-0)
plugin/innobase/include/ibuf0ibuf.h (+38/-9)
plugin/innobase/include/mem0mem.ic (+6/-6)
plugin/innobase/include/mtr0mtr.ic (+1/-1)
plugin/innobase/include/os0file.h (+2/-0)
plugin/innobase/include/row0upd.h (+11/-3)
plugin/innobase/include/srv0srv.h (+10/-2)
plugin/innobase/include/sync0rw.h (+1/-0)
plugin/innobase/include/univ.i (+25/-10)
plugin/innobase/include/ut0bh.h (+152/-0)
plugin/innobase/include/ut0bh.ic (+125/-0)
plugin/innobase/include/ut0ut.h (+13/-13)
plugin/innobase/include/ut0vec.h (+19/-0)
plugin/innobase/include/ut0vec.ic (+29/-0)
plugin/innobase/lock/lock0lock.cc (+75/-4)
plugin/innobase/log/log0recv.cc (+1/-1)
plugin/innobase/os/os0file.cc (+34/-9)
plugin/innobase/plugin.am (+3/-0)
plugin/innobase/row/row0ins.cc (+1/-1)
plugin/innobase/row/row0merge.cc (+2/-2)
plugin/innobase/row/row0mysql.cc (+2/-2)
plugin/innobase/row/row0purge.cc (+1/-1)
plugin/innobase/row/row0umod.cc (+6/-7)
plugin/innobase/row/row0upd.cc (+254/-91)
plugin/innobase/srv/srv0srv.cc (+39/-5)
plugin/innobase/srv/srv0start.cc (+19/-1)
plugin/innobase/sync/sync0arr.cc (+18/-10)
plugin/innobase/trx/trx0i_s.cc (+1/-2)
plugin/innobase/ut/ut0bh.cc (+164/-0)
plugin/innobase/ut/ut0dbg.cc (+1/-1)
To merge this branch: bzr merge lp:~stewart/drizzle/7.1-innodb-1.1.5
Reviewer Review Type Date Requested Status
Drizzle Trunk Pending
Review via email: mp+106800@code.launchpad.net

Description of the change

Update InnoDB to 1.1.5 from MySQL 5.5.9

No Jenkins run as it's giving me 404 instead of, well, Jenkins.

To post a comment you must log in.
Revision history for this message
Stewart Smith (stewart) wrote :
Revision history for this message
Vijay Samuel (vjsamuel) wrote :

We should probably add those files to POTFILES.in

Cheers,
 -Vijay

On Tue, May 22, 2012 at 7:04 PM, Stewart Smith <email address hidden>wrote:

> https://jenkins.drizzle.org/view/All/job/drizzle-param/923/
> --
> https://code.launchpad.net/~stewart/drizzle/7.1-innodb-1.1.5/+merge/106800<https://code.launchpad.net/%7Estewart/drizzle/7.1-innodb-1.1.5/+merge/106800>
> Your team Drizzle Trunk is requested to review the proposed merge of
> lp:~stewart/drizzle/7.1-innodb-1.1.5 into lp:drizzle/7.1.
>

Revision history for this message
Brian Aker (brianaker) wrote :
Revision history for this message
Stewart Smith (stewart) wrote :

On Tue, 22 May 2012 22:10:42 -0000, Brian Aker <email address hidden> wrote:
> https://jenkins.drizzle.org/view/Build/job/drizzle-build-matrix/label=ubuntu-10.04-i686/107/console
>
> Build failures.

Should be fixed now. Funny that it didn't show up on param build.

Do we have the blinken lights disabled for our jenkins now? Personally I
find them kind of useful to check status....

--
Stewart Smith

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugin/innobase/btr/btr0btr.cc'
2--- plugin/innobase/btr/btr0btr.cc 2011-03-20 06:58:32 +0000
3+++ plugin/innobase/btr/btr0btr.cc 2012-05-22 12:41:18 +0000
4@@ -663,7 +663,7 @@
5 " to fix the\n"
6 "InnoDB: corruption. If the crash happens at "
7 "the database startup, see\n"
8- "InnoDB: " REFMAN "forcing-recovery.html about\n"
9+ "InnoDB: " REFMAN "forcing-innodb-recovery.html about\n"
10 "InnoDB: forcing recovery. "
11 "Then dump + drop + reimport.\n", stderr);
12
13
14=== modified file 'plugin/innobase/btr/btr0cur.cc'
15--- plugin/innobase/btr/btr0cur.cc 2010-12-27 18:39:11 +0000
16+++ plugin/innobase/btr/btr0cur.cc 2012-05-22 12:41:18 +0000
17@@ -1874,7 +1874,8 @@
18 NOT call it if index is secondary */
19
20 if (!dict_index_is_clust(index)
21- || row_upd_changes_ord_field_binary(NULL, index, update)) {
22+ || row_upd_changes_ord_field_binary(NULL, NULL,
23+ index, update)) {
24
25 /* Remove possible hash index pointer to this record */
26 btr_search_update_hash_on_delete(cursor);
27@@ -2626,27 +2627,24 @@
28 btr_cur_del_mark_set_clust_rec(
29 /*===========================*/
30 ulint flags, /*!< in: undo logging and locking flags */
31- btr_cur_t* cursor, /*!< in: cursor */
32+ buf_block_t* block, /*!< in/out: buffer block of the record */
33+ rec_t* rec, /*!< in/out: record */
34+ dict_index_t* index, /*!< in: clustered index of the record */
35+ const ulint* offsets,/*!< in: rec_get_offsets(rec) */
36 ibool val, /*!< in: value to set */
37 que_thr_t* thr, /*!< in: query thread */
38 mtr_t* mtr) /*!< in: mtr */
39 {
40- dict_index_t* index;
41- buf_block_t* block;
42 roll_ptr_t roll_ptr;
43 ulint err;
44- rec_t* rec;
45 page_zip_des_t* page_zip;
46 trx_t* trx;
47- mem_heap_t* heap = NULL;
48- ulint offsets_[REC_OFFS_NORMAL_SIZE];
49- ulint* offsets = offsets_;
50- rec_offs_init(offsets_);
51
52- rec = btr_cur_get_rec(cursor);
53- index = cursor->index;
54+ ut_ad(dict_index_is_clust(index));
55+ ut_ad(rec_offs_validate(rec, index, offsets));
56 ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
57- offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
58+ ut_ad(buf_block_get_frame(block) == page_align(rec));
59+ ut_ad(page_is_leaf(page_align(rec)));
60
61 #ifdef UNIV_DEBUG
62 if (btr_cur_print_record_ops && thr) {
63@@ -2658,13 +2656,12 @@
64 ut_ad(dict_index_is_clust(index));
65 ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
66
67- err = lock_clust_rec_modify_check_and_lock(flags,
68- btr_cur_get_block(cursor),
69+ err = lock_clust_rec_modify_check_and_lock(flags, block,
70 rec, index, offsets, thr);
71
72 if (err != DB_SUCCESS) {
73
74- goto func_exit;
75+ return(err);
76 }
77
78 err = trx_undo_report_row_operation(flags, TRX_UNDO_MODIFY_OP, thr,
79@@ -2672,11 +2669,9 @@
80 &roll_ptr);
81 if (err != DB_SUCCESS) {
82
83- goto func_exit;
84+ return(err);
85 }
86
87- block = btr_cur_get_block(cursor);
88-
89 if (block->is_hashed) {
90 rw_lock_x_lock(&btr_search_latch);
91 }
92@@ -2699,10 +2694,6 @@
93 btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx,
94 roll_ptr, mtr);
95
96-func_exit:
97- if (UNIV_LIKELY_NULL(heap)) {
98- mem_heap_free(heap);
99- }
100 return(err);
101 }
102
103@@ -3754,107 +3745,35 @@
104 }
105
106 /*******************************************************************//**
107-Marks not updated extern fields as not-owned by this record. The ownership
108-is transferred to the updated record which is inserted elsewhere in the
109+Marks non-updated off-page fields as disowned by this record. The ownership
110+must be transferred to the updated record which is inserted elsewhere in the
111 index tree. In purge only the owner of externally stored field is allowed
112-to free the field.
113-@return TRUE if BLOB ownership was transferred */
114+to free the field. */
115 UNIV_INTERN
116-ibool
117-btr_cur_mark_extern_inherited_fields(
118-/*=================================*/
119+void
120+btr_cur_disown_inherited_fields(
121+/*============================*/
122 page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
123 part will be updated, or NULL */
124 rec_t* rec, /*!< in/out: record in a clustered index */
125 dict_index_t* index, /*!< in: index of the page */
126 const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
127 const upd_t* update, /*!< in: update vector */
128- mtr_t* mtr) /*!< in: mtr, or NULL if not logged */
129+ mtr_t* mtr) /*!< in/out: mini-transaction */
130 {
131- ulint n;
132- ulint j;
133 ulint i;
134- ibool change_ownership = FALSE;
135
136- ut_ad(rec_offs_validate(rec, NULL, offsets));
137+ ut_ad(rec_offs_validate(rec, index, offsets));
138 ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
139-
140- if (!rec_offs_any_extern(offsets)) {
141-
142- return(FALSE);
143- }
144-
145- n = rec_offs_n_fields(offsets);
146-
147- for (i = 0; i < n; i++) {
148- if (rec_offs_nth_extern(offsets, i)) {
149-
150- /* Check it is not in updated fields */
151-
152- if (update) {
153- for (j = 0; j < upd_get_n_fields(update);
154- j++) {
155- if (upd_get_nth_field(update, j)
156- ->field_no == i) {
157-
158- goto updated;
159- }
160- }
161- }
162-
163+ ut_ad(rec_offs_any_extern(offsets));
164+ ut_ad(mtr);
165+
166+ for (i = 0; i < rec_offs_n_fields(offsets); i++) {
167+ if (rec_offs_nth_extern(offsets, i)
168+ && !upd_get_field_by_field_no(update, i)) {
169 btr_cur_set_ownership_of_extern_field(
170 page_zip, rec, index, offsets, i, FALSE, mtr);
171-
172- change_ownership = TRUE;
173-updated:
174- ;
175- }
176- }
177-
178- return(change_ownership);
179-}
180-
181-/*******************************************************************//**
182-The complement of the previous function: in an update entry may inherit
183-some externally stored fields from a record. We must mark them as inherited
184-in entry, so that they are not freed in a rollback. */
185-UNIV_INTERN
186-void
187-btr_cur_mark_dtuple_inherited_extern(
188-/*=================================*/
189- dtuple_t* entry, /*!< in/out: updated entry to be
190- inserted to clustered index */
191- const upd_t* update) /*!< in: update vector */
192-{
193- ulint i;
194-
195- for (i = 0; i < dtuple_get_n_fields(entry); i++) {
196-
197- dfield_t* dfield = dtuple_get_nth_field(entry, i);
198- byte* data;
199- ulint len;
200- ulint j;
201-
202- if (!dfield_is_ext(dfield)) {
203- continue;
204- }
205-
206- /* Check if it is in updated fields */
207-
208- for (j = 0; j < upd_get_n_fields(update); j++) {
209- if (upd_get_nth_field(update, j)->field_no == i) {
210-
211- goto is_updated;
212- }
213- }
214-
215- data = (unsigned char *)dfield_get_data(dfield);
216- len = dfield_get_len(dfield);
217- data[len - BTR_EXTERN_FIELD_REF_SIZE + BTR_EXTERN_LEN]
218- |= BTR_EXTERN_INHERITED_FLAG;
219-
220-is_updated:
221- ;
222+ }
223 }
224 }
225
226@@ -3894,29 +3813,6 @@
227 }
228
229 /*******************************************************************//**
230-Marks all extern fields in a dtuple as owned by the record. */
231-UNIV_INTERN
232-void
233-btr_cur_unmark_dtuple_extern_fields(
234-/*================================*/
235- dtuple_t* entry) /*!< in/out: clustered index entry */
236-{
237- ulint i;
238-
239- for (i = 0; i < dtuple_get_n_fields(entry); i++) {
240- dfield_t* dfield = dtuple_get_nth_field(entry, i);
241-
242- if (dfield_is_ext(dfield)) {
243- byte* data = (unsigned char *)dfield_get_data(dfield);
244- ulint len = dfield_get_len(dfield);
245-
246- data[len - BTR_EXTERN_FIELD_REF_SIZE + BTR_EXTERN_LEN]
247- &= ~BTR_EXTERN_OWNER_FLAG;
248- }
249- }
250-}
251-
252-/*******************************************************************//**
253 Flags the data tuple fields that are marked as extern storage in the
254 update vector. We use this function to remember which fields we must
255 mark as extern storage in a record inserted for an update.
256
257=== modified file 'plugin/innobase/buf/buf0buf.cc'
258--- plugin/innobase/buf/buf0buf.cc 2011-04-07 05:47:57 +0000
259+++ plugin/innobase/buf/buf0buf.cc 2012-05-22 12:41:18 +0000
260@@ -534,7 +534,7 @@
261 "InnoDB: Error: page %lu log sequence number %"PRIu64". "
262 "InnoDB: is in the future! Current system log sequence number %"PRIu64". "
263 "Your database may be corrupt or you may have copied the InnoDB tablespace but not the InnoDB log files. See "
264- " " REFMAN "forcing-recovery.html for more information. ",
265+ " " REFMAN "forcing-innodb-recovery.html for more information. ",
266 (ulong) mach_read_from_4(read_buf
267 + FIL_PAGE_OFFSET),
268 mach_read_from_8(read_buf + FIL_PAGE_LSN),
269@@ -2744,7 +2744,8 @@
270 ut_ad(zip_size == fil_space_get_zip_size(space));
271 ut_ad(ut_is_2pow(zip_size));
272 #ifndef UNIV_LOG_DEBUG
273- ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL));
274+ ut_ad(!ibuf_inside() || ibuf_page_low(space, zip_size, offset,
275+ FALSE, file, line, NULL));
276 #endif
277 buf_pool->stat.n_page_gets++;
278 fold = buf_page_address_fold(space, offset);
279@@ -4037,7 +4038,7 @@
280 "InnoDB: TABLE to scan your"
281 " table for corruption.\n"
282 "InnoDB: See also "
283- REFMAN "forcing-recovery.html\n"
284+ REFMAN "forcing-innodb-recovery.html\n"
285 "InnoDB: about forcing recovery.\n", stderr);
286
287 if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
288@@ -4792,23 +4793,203 @@
289 return(ratio);
290 }
291
292+/*******************************************************************//**
293+Aggregates a pool stats information with the total buffer pool stats */
294+static
295+void
296+buf_stats_aggregate_pool_info(
297+/*==========================*/
298+ buf_pool_info_t* total_info, /*!< in/out: the buffer pool
299+ info to store aggregated
300+ result */
301+ const buf_pool_info_t* pool_info) /*!< in: individual buffer pool
302+ stats info */
303+{
304+ ut_a(total_info && pool_info);
305+
306+ /* Nothing to copy if total_info is the same as pool_info */
307+ if (total_info == pool_info) {
308+ return;
309+ }
310+
311+ total_info->pool_size += pool_info->pool_size;
312+ total_info->lru_len += pool_info->lru_len;
313+ total_info->old_lru_len += pool_info->old_lru_len;
314+ total_info->free_list_len += pool_info->free_list_len;
315+ total_info->flush_list_len += pool_info->flush_list_len;
316+ total_info->n_pend_unzip += pool_info->n_pend_unzip;
317+ total_info->n_pend_reads += pool_info->n_pend_reads;
318+ total_info->n_pending_flush_lru += pool_info->n_pending_flush_lru;
319+ total_info->n_pending_flush_list += pool_info->n_pending_flush_list;
320+ total_info->n_pending_flush_single_page +=
321+ pool_info->n_pending_flush_single_page;
322+ total_info->n_pages_made_young += pool_info->n_pages_made_young;
323+ total_info->n_pages_not_made_young += pool_info->n_pages_not_made_young;
324+ total_info->n_pages_read += pool_info->n_pages_read;
325+ total_info->n_pages_created += pool_info->n_pages_created;
326+ total_info->n_pages_written += pool_info->n_pages_written;
327+ total_info->n_page_gets += pool_info->n_page_gets;
328+ total_info->n_ra_pages_read += pool_info->n_ra_pages_read;
329+ total_info->n_ra_pages_evicted += pool_info->n_ra_pages_evicted;
330+ total_info->page_made_young_rate += pool_info->page_made_young_rate;
331+ total_info->page_not_made_young_rate +=
332+ pool_info->page_not_made_young_rate;
333+ total_info->pages_read_rate += pool_info->pages_read_rate;
334+ total_info->pages_created_rate += pool_info->pages_created_rate;
335+ total_info->pages_written_rate += pool_info->pages_written_rate;
336+ total_info->n_page_get_delta += pool_info->n_page_get_delta;
337+ total_info->page_read_delta += pool_info->page_read_delta;
338+ total_info->young_making_delta += pool_info->young_making_delta;
339+ total_info->not_young_making_delta += pool_info->not_young_making_delta;
340+ total_info->pages_readahead_rate += pool_info->pages_readahead_rate;
341+ total_info->pages_evicted_rate += pool_info->pages_evicted_rate;
342+ total_info->unzip_lru_len += pool_info->unzip_lru_len;
343+ total_info->io_sum += pool_info->io_sum;
344+ total_info->io_cur += pool_info->io_cur;
345+ total_info->unzip_sum += pool_info->unzip_sum;
346+ total_info->unzip_cur += pool_info->unzip_cur;
347+}
348+/*******************************************************************//**
349+Collect buffer pool stats information for a buffer pool. Also
350+record aggregated stats if there are more than one buffer pool
351+in the server */
352+static
353+void
354+buf_stats_get_pool_info(
355+/*====================*/
356+ buf_pool_t* buf_pool, /*!< in: buffer pool */
357+ ulint pool_id, /*!< in: buffer pool ID */
358+ buf_pool_info_t* all_pool_info) /*!< in/out: buffer pool info
359+ to fill */
360+{
361+ buf_pool_info_t* pool_info;
362+ time_t current_time;
363+ double time_elapsed;
364+
365+ /* Find appropriate pool_info to store stats for this buffer pool */
366+ pool_info = &all_pool_info[pool_id];
367+
368+ buf_pool_mutex_enter(buf_pool);
369+ buf_flush_list_mutex_enter(buf_pool);
370+
371+ pool_info->pool_unique_id = pool_id;
372+
373+ pool_info->pool_size = buf_pool->curr_size;
374+
375+ pool_info->lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
376+
377+ pool_info->old_lru_len = buf_pool->LRU_old_len;
378+
379+ pool_info->free_list_len = UT_LIST_GET_LEN(buf_pool->free);
380+
381+ pool_info->flush_list_len = UT_LIST_GET_LEN(buf_pool->flush_list);
382+
383+ pool_info->n_pend_unzip = UT_LIST_GET_LEN(buf_pool->unzip_LRU);
384+
385+ pool_info->n_pend_reads = buf_pool->n_pend_reads;
386+
387+ pool_info->n_pending_flush_lru =
388+ (buf_pool->n_flush[BUF_FLUSH_LRU]
389+ + buf_pool->init_flush[BUF_FLUSH_LRU]);
390+
391+ pool_info->n_pending_flush_list =
392+ (buf_pool->n_flush[BUF_FLUSH_LIST]
393+ + buf_pool->init_flush[BUF_FLUSH_LIST]);
394+
395+ pool_info->n_pending_flush_single_page =
396+ buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE];
397+
398+ buf_flush_list_mutex_exit(buf_pool);
399+
400+ current_time = time(NULL);
401+ time_elapsed = 0.001 + difftime(current_time,
402+ buf_pool->last_printout_time);
403+
404+ pool_info->n_pages_made_young = buf_pool->stat.n_pages_made_young;
405+
406+ pool_info->n_pages_not_made_young =
407+ buf_pool->stat.n_pages_not_made_young;
408+
409+ pool_info->n_pages_read = buf_pool->stat.n_pages_read;
410+
411+ pool_info->n_pages_created = buf_pool->stat.n_pages_created;
412+
413+ pool_info->n_pages_written = buf_pool->stat.n_pages_written;
414+
415+ pool_info->n_page_gets = buf_pool->stat.n_page_gets;
416+
417+ pool_info->n_ra_pages_read = buf_pool->stat.n_ra_pages_read;
418+
419+ pool_info->n_ra_pages_evicted = buf_pool->stat.n_ra_pages_evicted;
420+
421+ pool_info->page_made_young_rate =
422+ (buf_pool->stat.n_pages_made_young
423+ - buf_pool->old_stat.n_pages_made_young) / time_elapsed;
424+
425+ pool_info->page_not_made_young_rate =
426+ (buf_pool->stat.n_pages_not_made_young
427+ - buf_pool->old_stat.n_pages_not_made_young) / time_elapsed;
428+
429+ pool_info->pages_read_rate =
430+ (buf_pool->stat.n_pages_read
431+ - buf_pool->old_stat.n_pages_read) / time_elapsed;
432+
433+ pool_info->pages_created_rate =
434+ (buf_pool->stat.n_pages_created
435+ - buf_pool->old_stat.n_pages_created) / time_elapsed;
436+
437+ pool_info->pages_written_rate =
438+ (buf_pool->stat.n_pages_written
439+ - buf_pool->old_stat.n_pages_written) / time_elapsed;
440+
441+ pool_info->n_page_get_delta = buf_pool->stat.n_page_gets
442+ - buf_pool->old_stat.n_page_gets;
443+
444+ if (pool_info->n_page_get_delta) {
445+ pool_info->page_read_delta = buf_pool->stat.n_pages_read
446+ - buf_pool->old_stat.n_pages_read;
447+
448+ pool_info->young_making_delta =
449+ buf_pool->stat.n_pages_made_young
450+ - buf_pool->old_stat.n_pages_made_young;
451+
452+ pool_info->not_young_making_delta =
453+ buf_pool->stat.n_pages_not_made_young
454+ - buf_pool->old_stat.n_pages_not_made_young;
455+ }
456+
457+ pool_info->pages_readahead_rate =
458+ (buf_pool->stat.n_ra_pages_read
459+ - buf_pool->old_stat.n_ra_pages_read) / time_elapsed;
460+
461+ pool_info->pages_evicted_rate =
462+ (buf_pool->stat.n_ra_pages_evicted
463+ - buf_pool->old_stat.n_ra_pages_evicted) / time_elapsed;
464+
465+ pool_info->unzip_lru_len = UT_LIST_GET_LEN(buf_pool->unzip_LRU);
466+
467+ pool_info->io_sum = buf_LRU_stat_sum.io;
468+
469+ pool_info->io_cur = buf_LRU_stat_cur.io;
470+
471+ pool_info->unzip_sum = buf_LRU_stat_sum.unzip;
472+
473+ pool_info->unzip_cur = buf_LRU_stat_cur.unzip;
474+
475+ buf_refresh_io_stats(buf_pool);
476+ buf_pool_mutex_exit(buf_pool);
477+}
478+
479 /*********************************************************************//**
480 Prints info of the buffer i/o. */
481 static
482 void
483 buf_print_io_instance(
484 /*==================*/
485- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
486+ buf_pool_info_t*pool_info, /*!< in: buffer pool info */
487 FILE* file) /*!< in/out: buffer where to print */
488 {
489- time_t current_time;
490- double time_elapsed;
491- ulint n_gets_diff;
492-
493- ut_ad(buf_pool);
494-
495- buf_pool_mutex_enter(buf_pool);
496- buf_flush_list_mutex_enter(buf_pool);
497+ ut_ad(pool_info);
498
499 fprintf(file,
500 "Buffer pool size %lu\n"
501@@ -4818,70 +4999,42 @@
502 "Modified db pages %lu\n"
503 "Pending reads %lu\n"
504 "Pending writes: LRU %lu, flush list %lu, single page %lu\n",
505- (ulong) buf_pool->curr_size,
506- (ulong) UT_LIST_GET_LEN(buf_pool->free),
507- (ulong) UT_LIST_GET_LEN(buf_pool->LRU),
508- (ulong) buf_pool->LRU_old_len,
509- (ulong) UT_LIST_GET_LEN(buf_pool->flush_list),
510- (ulong) buf_pool->n_pend_reads,
511- (ulong) buf_pool->n_flush[BUF_FLUSH_LRU]
512- + buf_pool->init_flush[BUF_FLUSH_LRU],
513- (ulong) buf_pool->n_flush[BUF_FLUSH_LIST]
514- + buf_pool->init_flush[BUF_FLUSH_LIST],
515- (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
516-
517- buf_flush_list_mutex_exit(buf_pool);
518-
519- current_time = time(NULL);
520- time_elapsed = 0.001 + difftime(current_time,
521- buf_pool->last_printout_time);
522+ pool_info->pool_size,
523+ pool_info->free_list_len,
524+ pool_info->lru_len,
525+ pool_info->old_lru_len,
526+ pool_info->flush_list_len,
527+ pool_info->n_pend_reads,
528+ pool_info->n_pending_flush_lru,
529+ pool_info->n_pending_flush_list,
530+ pool_info->n_pending_flush_single_page);
531
532 fprintf(file,
533 "Pages made young %lu, not young %lu\n"
534 "%.2f youngs/s, %.2f non-youngs/s\n"
535 "Pages read %lu, created %lu, written %lu\n"
536 "%.2f reads/s, %.2f creates/s, %.2f writes/s\n",
537- (ulong) buf_pool->stat.n_pages_made_young,
538- (ulong) buf_pool->stat.n_pages_not_made_young,
539- (buf_pool->stat.n_pages_made_young
540- - buf_pool->old_stat.n_pages_made_young)
541- / time_elapsed,
542- (buf_pool->stat.n_pages_not_made_young
543- - buf_pool->old_stat.n_pages_not_made_young)
544- / time_elapsed,
545- (ulong) buf_pool->stat.n_pages_read,
546- (ulong) buf_pool->stat.n_pages_created,
547- (ulong) buf_pool->stat.n_pages_written,
548- (buf_pool->stat.n_pages_read
549- - buf_pool->old_stat.n_pages_read)
550- / time_elapsed,
551- (buf_pool->stat.n_pages_created
552- - buf_pool->old_stat.n_pages_created)
553- / time_elapsed,
554- (buf_pool->stat.n_pages_written
555- - buf_pool->old_stat.n_pages_written)
556- / time_elapsed);
557-
558- n_gets_diff = buf_pool->stat.n_page_gets
559- - buf_pool->old_stat.n_page_gets;
560-
561- if (n_gets_diff) {
562+ pool_info->n_pages_made_young,
563+ pool_info->n_pages_not_made_young,
564+ pool_info->page_made_young_rate,
565+ pool_info->page_not_made_young_rate,
566+ pool_info->n_pages_read,
567+ pool_info->n_pages_created,
568+ pool_info->n_pages_written,
569+ pool_info->pages_read_rate,
570+ pool_info->pages_created_rate,
571+ pool_info->pages_written_rate);
572+
573+ if (pool_info->n_page_get_delta) {
574 fprintf(file,
575 "Buffer pool hit rate %lu / 1000,"
576 " young-making rate %lu / 1000 not %lu / 1000\n",
577- (ulong)
578- (1000 - ((1000 * (buf_pool->stat.n_pages_read
579- - buf_pool->old_stat.n_pages_read))
580- / (buf_pool->stat.n_page_gets
581- - buf_pool->old_stat.n_page_gets))),
582- (ulong)
583- (1000 * (buf_pool->stat.n_pages_made_young
584- - buf_pool->old_stat.n_pages_made_young)
585- / n_gets_diff),
586- (ulong)
587- (1000 * (buf_pool->stat.n_pages_not_made_young
588- - buf_pool->old_stat.n_pages_not_made_young)
589- / n_gets_diff));
590+ (ulong) (1000 - (1000 * pool_info->page_read_delta
591+ / pool_info->n_page_get_delta)),
592+ (ulong) (1000 * pool_info->young_making_delta
593+ / pool_info->n_page_get_delta),
594+ (ulong) (1000 * pool_info->not_young_making_delta
595+ / pool_info->n_page_get_delta));
596 } else {
597 fputs("No buffer pool page gets since the last printout\n",
598 file);
599@@ -4890,25 +5043,17 @@
600 /* Statistics about read ahead algorithm */
601 fprintf(file, "Pages read ahead %.2f/s,"
602 " evicted without access %.2f/s\n",
603- (buf_pool->stat.n_ra_pages_read
604- - buf_pool->old_stat.n_ra_pages_read)
605- / time_elapsed,
606- (buf_pool->stat.n_ra_pages_evicted
607- - buf_pool->old_stat.n_ra_pages_evicted)
608- / time_elapsed);
609+ pool_info->pages_readahead_rate,
610+ pool_info->pages_evicted_rate);
611
612 /* Print some values to help us with visualizing what is
613 happening with LRU eviction. */
614 fprintf(file,
615 "LRU len: %lu, unzip_LRU len: %lu\n"
616 "I/O sum[%lu]:cur[%lu], unzip sum[%lu]:cur[%lu]\n",
617- static_cast<ulint>(UT_LIST_GET_LEN(buf_pool->LRU)),
618- static_cast<ulint>(UT_LIST_GET_LEN(buf_pool->unzip_LRU)),
619- buf_LRU_stat_sum.io, buf_LRU_stat_cur.io,
620- buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip);
621-
622- buf_refresh_io_stats(buf_pool);
623- buf_pool_mutex_exit(buf_pool);
624+ pool_info->lru_len, pool_info->unzip_lru_len,
625+ pool_info->io_sum, pool_info->io_cur,
626+ pool_info->unzip_sum, pool_info->unzip_cur);
627 }
628
629 /*********************************************************************//**
630@@ -4919,14 +5064,58 @@
631 /*=========*/
632 FILE* file) /*!< in/out: buffer where to print */
633 {
634- ulint i;
635+ ulint i;
636+ buf_pool_info_t* pool_info;
637+ buf_pool_info_t* pool_info_total;
638+
639+ /* If srv_buf_pool_instances is greater than 1, allocate
640+ one extra buf_pool_info_t, the last one stores
641+ aggregated/total values from all pools */
642+ if (srv_buf_pool_instances > 1) {
643+ pool_info = (buf_pool_info_t*) mem_zalloc((
644+ srv_buf_pool_instances + 1) * sizeof *pool_info);
645+
646+ pool_info_total = &pool_info[srv_buf_pool_instances];
647+ } else {
648+ ut_a(srv_buf_pool_instances == 1);
649+ pool_info_total = pool_info = (buf_pool_info_t*) mem_zalloc(
650+ sizeof *pool_info)
651+ }
652
653 for (i = 0; i < srv_buf_pool_instances; i++) {
654 buf_pool_t* buf_pool;
655
656 buf_pool = buf_pool_from_array(i);
657- buf_print_io_instance(buf_pool, file);
658- }
659+
660+ /* Fetch individual buffer pool info and calculate
661+ aggregated stats along the way */
662+ buf_stats_get_pool_info(buf_pool, i, pool_info);
663+
664+ /* If we have more than one buffer pool, store
665+ the aggregated stats */
666+ if (srv_buf_pool_instances > 1) {
667+ buf_stats_aggregate_pool_info(pool_info_total,
668+ &pool_info[i]);
669+ }
670+ }
671+
672+ /* Print the aggreate buffer pool info */
673+ buf_print_io_instance(pool_info_total, file);
674+
675+ /* If there are more than one buffer pool, print each individual pool
676+ info */
677+ if (srv_buf_pool_instances > 1) {
678+ fputs("----------------------\n"
679+ "INDIVIDUAL BUFFER POOL INFO\n"
680+ "----------------------\n", file);
681+
682+ for (i = 0; i < srv_buf_pool_instances; i++) {
683+ fprintf(file, "---BUFFER POOL %lu\n", i);
684+ buf_print_io_instance(&pool_info[i], file);
685+ }
686+ }
687+
688+ mem_free(pool_info);
689 }
690
691 /**********************************************************************//**
692
693=== modified file 'plugin/innobase/buf/buf0flu.cc'
694--- plugin/innobase/buf/buf0flu.cc 2011-04-07 05:47:57 +0000
695+++ plugin/innobase/buf/buf0flu.cc 2012-05-22 12:41:18 +0000
696@@ -86,6 +86,34 @@
697 buf_flush_validate_low(
698 /*===================*/
699 buf_pool_t* buf_pool); /*!< in: Buffer pool instance */
700+
701+/******************************************************************//**
702+Validates the flush list some of the time.
703+@return TRUE if ok or the check was skipped */
704+static
705+ibool
706+buf_flush_validate_skip(
707+/*====================*/
708+ buf_pool_t* buf_pool) /*!< in: Buffer pool instance */
709+{
710+/** Try buf_flush_validate_low() every this many times */
711+# define BUF_FLUSH_VALIDATE_SKIP 23
712+
713+ /** The buf_flush_validate_low() call skip counter.
714+ Use a signed type because of the race condition below. */
715+ static int buf_flush_validate_count = BUF_FLUSH_VALIDATE_SKIP;
716+
717+ /* There is a race condition below, but it does not matter,
718+ because this call is only for heuristic purposes. We want to
719+ reduce the call frequency of the costly buf_flush_validate_low()
720+ check in debug builds. */
721+ if (--buf_flush_validate_count > 0) {
722+ return(TRUE);
723+ }
724+
725+ buf_flush_validate_count = BUF_FLUSH_VALIDATE_SKIP;
726+ return(buf_flush_validate_low(buf_pool));
727+}
728 #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
729
730 /******************************************************************//**
731@@ -301,7 +329,7 @@
732 }
733 #endif /* UNIV_DEBUG_VALGRIND */
734 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
735- ut_a(buf_flush_validate_low(buf_pool));
736+ ut_a(buf_flush_validate_skip(buf_pool));
737 #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
738
739 buf_flush_list_mutex_exit(buf_pool);
740@@ -535,7 +563,7 @@
741 bpage->oldest_modification = 0;
742
743 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
744- ut_a(buf_flush_validate_low(buf_pool));
745+ ut_a(buf_flush_validate_skip(buf_pool));
746 #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
747
748 buf_flush_list_mutex_exit(buf_pool);
749
750=== modified file 'plugin/innobase/buf/buf0lru.cc'
751--- plugin/innobase/buf/buf0lru.cc 2011-04-07 12:10:16 +0000
752+++ plugin/innobase/buf/buf0lru.cc 2012-05-22 12:41:18 +0000
753@@ -2077,6 +2077,7 @@
754 buf_LRU_stat_t* item;
755 buf_pool_t* buf_pool;
756 ibool evict_started = FALSE;
757+ buf_LRU_stat_t cur_stat;
758
759 /* If we haven't started eviction yet then don't update stats. */
760 for (i = 0; i < srv_buf_pool_instances; i++) {
761@@ -2098,12 +2099,19 @@
762 buf_LRU_stat_arr_ind++;
763 buf_LRU_stat_arr_ind %= BUF_LRU_STAT_N_INTERVAL;
764
765- /* Add the current value and subtract the obsolete entry. */
766- buf_LRU_stat_sum.io += buf_LRU_stat_cur.io - item->io;
767- buf_LRU_stat_sum.unzip += buf_LRU_stat_cur.unzip - item->unzip;
768+ /* Add the current value and subtract the obsolete entry.
769+ Since buf_LRU_stat_cur is not protected by any mutex,
770+ it can be changing between adding to buf_LRU_stat_sum
771+ and copying to item. Assign it to local variables to make
772+ sure the same value assign to the buf_LRU_stat_sum
773+ and item */
774+ cur_stat = buf_LRU_stat_cur;
775+
776+ buf_LRU_stat_sum.io += cur_stat.io - item->io;
777+ buf_LRU_stat_sum.unzip += cur_stat.unzip - item->unzip;
778
779 /* Put current entry in the array. */
780- memcpy(item, &buf_LRU_stat_cur, sizeof *item);
781+ memcpy(item, &cur_stat, sizeof *item);
782
783 func_exit:
784 /* Clear the current entry. */
785
786=== modified file 'plugin/innobase/dict/dict0dict.cc'
787--- plugin/innobase/dict/dict0dict.cc 2011-02-04 22:30:00 +0000
788+++ plugin/innobase/dict/dict0dict.cc 2012-05-22 12:41:18 +0000
789@@ -52,7 +52,8 @@
790 #include "que0que.h"
791 #include "rem0cmp.h"
792 #include "row0merge.h"
793-#include "ha_prototypes.h" /* innobase_strcasecmp() */
794+#include "srv0srv.h" /* srv_lower_case_table_names */
795+#include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str()*/
796
797 #include <ctype.h>
798
799@@ -75,6 +76,7 @@
800 #ifdef UNIV_PFS_RWLOCK
801 UNIV_INTERN mysql_pfs_key_t dict_operation_lock_key;
802 UNIV_INTERN mysql_pfs_key_t index_tree_rw_lock_key;
803+UNIV_INTERN mysql_pfs_key_t dict_table_stats_latch_key;
804 #endif /* UNIV_PFS_RWLOCK */
805
806 #ifdef UNIV_PFS_MUTEX
807@@ -714,7 +716,7 @@
808 &dict_foreign_err_mutex, SYNC_ANY_LATCH);
809
810 for (i = 0; i < DICT_TABLE_STATS_LATCHES_SIZE; i++) {
811- rw_lock_create(PFS_NOT_INSTRUMENTED,
812+ rw_lock_create(dict_table_stats_latch_key,
813 &dict_table_stats_latches[i], SYNC_INDEX_TREE);
814 }
815 }
816@@ -947,7 +949,7 @@
817 dict_foreign_t* foreign;
818 dict_index_t* index;
819 ulint fold;
820- char old_name[MAX_TABLE_NAME_LEN + 1];
821+ char old_name[MAX_FULL_NAME_LEN + 1];
822
823 ut_ad(table);
824 ut_ad(mutex_own(&(dict_sys->mutex)));
825@@ -959,7 +961,7 @@
826 ut_print_timestamp(stderr);
827 fprintf(stderr, "InnoDB: too long table name: '%s', "
828 "max length is %d\n", table->name,
829- MAX_TABLE_NAME_LEN);
830+ MAX_FULL_NAME_LEN);
831 ut_error;
832 }
833
834@@ -1080,13 +1082,14 @@
835 /* Allocate a longer name buffer;
836 TODO: store buf len to save memory */
837
838- foreign->foreign_table_name
839- = static_cast<char *>(mem_heap_alloc(foreign->heap,
840- ut_strlen(table->name) + 1));
841+ foreign->foreign_table_name = mem_heap_strdup(
842+ foreign->heap, table->name);
843+ dict_mem_foreign_table_name_lookup_set(foreign, TRUE);
844+ } else {
845+ strcpy(foreign->foreign_table_name, table->name);
846+ dict_mem_foreign_table_name_lookup_set(foreign, FALSE);
847 }
848
849- strcpy(foreign->foreign_table_name, table->name);
850-
851 if (strchr(foreign->id, '/')) {
852 ulint db_len;
853 char* old_id;
854@@ -1152,12 +1155,15 @@
855 /* Allocate a longer name buffer;
856 TODO: store buf len to save memory */
857
858- foreign->referenced_table_name = static_cast<char *>(mem_heap_alloc(
859- foreign->heap, strlen(table->name) + 1));
860+ foreign->referenced_table_name = mem_heap_strdup(
861+ foreign->heap, table->name);
862+ dict_mem_referenced_table_name_lookup_set(foreign, TRUE);
863+ } else {
864+ /* Use the same buffer */
865+ strcpy(foreign->referenced_table_name, table->name);
866+ dict_mem_referenced_table_name_lookup_set(foreign, FALSE);
867 }
868
869- strcpy(foreign->referenced_table_name, table->name);
870-
871 foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
872 }
873
874@@ -2585,10 +2591,10 @@
875 ut_ad(mutex_own(&(dict_sys->mutex)));
876
877 for_table = dict_table_check_if_in_cache_low(
878- foreign->foreign_table_name);
879+ foreign->foreign_table_name_lookup);
880
881 ref_table = dict_table_check_if_in_cache_low(
882- foreign->referenced_table_name);
883+ foreign->referenced_table_name_lookup);
884 ut_a(for_table || ref_table);
885
886 if (for_table) {
887@@ -2705,7 +2711,7 @@
888 quote = '\0';
889 } else if (quote) {
890 /* Within quotes: do nothing. */
891- } else if (*ptr == '`' || *ptr == '"') {
892+ } else if (*ptr == '`' || *ptr == '"' || *ptr == '\'') {
893 /* Starting quote: remember the quote character. */
894 quote = *ptr;
895 } else {
896@@ -3017,19 +3023,25 @@
897 memcpy(ref, database_name, database_name_len);
898 ref[database_name_len] = '/';
899 memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
900-#ifndef __WIN__
901- if (srv_lower_case_table_names) {
902-#endif /* !__WIN__ */
903- /* The table name is always put to lower case on Windows. */
904+
905+ /* Values; 0 = Store and compare as given; case sensitive
906+ 1 = Store and compare in lower; case insensitive
907+ 2 = Store as given, compare in lower; case semi-sensitive */
908+ if (srv_lower_case_table_names == 2) {
909 innobase_casedn_str(ref);
910-#ifndef __WIN__
911+ *table = dict_table_get_low(ref);
912+ memcpy(ref, database_name, database_name_len);
913+ ref[database_name_len] = '/';
914+ memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
915+ } else {
916+ if (srv_lower_case_table_names == 1) {
917+ innobase_casedn_str(ref);
918+ }
919+ *table = dict_table_get_low(ref);
920 }
921-#endif /* !__WIN__ */
922
923 *success = TRUE;
924 *ref_name = ref;
925- *table = dict_table_get_low(ref);
926-
927 return(ptr);
928 }
929
930@@ -3518,8 +3530,10 @@
931 }
932
933 foreign->foreign_table = table;
934- foreign->foreign_table_name = mem_heap_strdup(foreign->heap,
935- table->name);
936+ foreign->foreign_table_name = mem_heap_strdup(
937+ foreign->heap, table->name);
938+ dict_mem_foreign_table_name_lookup_set(foreign, TRUE);
939+
940 foreign->foreign_index = index;
941 foreign->n_fields = (unsigned int) i;
942 foreign->foreign_col_names = static_cast<const char **>(mem_heap_alloc(foreign->heap,
943@@ -3776,8 +3790,9 @@
944 foreign->referenced_index = index;
945 foreign->referenced_table = referenced_table;
946
947- foreign->referenced_table_name
948- = mem_heap_strdup(foreign->heap, referenced_table_name);
949+ foreign->referenced_table_name = mem_heap_strdup(
950+ foreign->heap, referenced_table_name);
951+ dict_mem_referenced_table_name_lookup_set(foreign, TRUE);
952
953 foreign->referenced_col_names = static_cast<const char **>(mem_heap_alloc(foreign->heap,
954 i * sizeof(void*)));
955@@ -4588,8 +4603,8 @@
956
957 fputs(") REFERENCES ", file);
958
959- if (dict_tables_have_same_db(foreign->foreign_table_name,
960- foreign->referenced_table_name)) {
961+ if (dict_tables_have_same_db(foreign->foreign_table_name_lookup,
962+ foreign->referenced_table_name_lookup)) {
963 /* Do not print the database name of the referenced table */
964 ut_print_name(file, trx, TRUE,
965 dict_remove_db_name(
966
967=== modified file 'plugin/innobase/dict/dict0load.cc'
968--- plugin/innobase/dict/dict0load.cc 2010-12-28 03:48:30 +0000
969+++ plugin/innobase/dict/dict0load.cc 2012-05-22 12:41:18 +0000
970@@ -44,6 +44,7 @@
971 #include "rem0cmp.h"
972 #include "srv0start.h"
973 #include "srv0srv.h"
974+#include "ha_prototypes.h" /* innobase_casedn_str() */
975
976
977 /** Following are six InnoDB system tables */
978@@ -442,10 +443,11 @@
979 return(err_msg);
980
981 }
982+
983 /********************************************************************//**
984 This function parses a SYS_FOREIGN record and populate a dict_foreign_t
985 structure with the information from the record. For detail information
986-about SYS_FOREIGN fields, please refer to dict_load_foreign() function
987+about SYS_FOREIGN fields, please refer to dict_load_foreign() function.
988 @return error message, or NULL on success */
989 UNIV_INTERN
990 const char*
991@@ -473,6 +475,11 @@
992 err_len:
993 return("incorrect column length in SYS_FOREIGN");
994 }
995+
996+ /* This recieves a dict_foreign_t* that points to a stack variable.
997+ So mem_heap_free(foreign->heap) is not used as elsewhere.
998+ Since the heap used here is freed elsewhere, foreign->heap
999+ is not assigned. */
1000 foreign->id = mem_heap_strdupl(heap, (const char*) field, len);
1001
1002 rec_get_nth_field_offs_old(rec, 1/*DB_TRX_ID*/, &len);
1003@@ -484,6 +491,9 @@
1004 goto err_len;
1005 }
1006
1007+ /* The _lookup versions of the referenced and foreign table names
1008+ are not assigned since they are not used in this dict_foreign_t */
1009+
1010 field = rec_get_nth_field_old(rec, 3/*FOR_NAME*/, &len);
1011 if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
1012 goto err_len;
1013@@ -509,6 +519,7 @@
1014
1015 return(NULL);
1016 }
1017+
1018 /********************************************************************//**
1019 This function parses a SYS_FOREIGN_COLS record and extract necessary
1020 information from the record and return to caller.
1021@@ -2139,12 +2150,15 @@
1022 foreign->id = mem_heap_strdup(foreign->heap, id);
1023
1024 field = rec_get_nth_field_old(rec, 3, &len);
1025+
1026 foreign->foreign_table_name = mem_heap_strdupl(
1027 foreign->heap, (char*) field, len);
1028+ dict_mem_foreign_table_name_lookup_set(foreign, TRUE);
1029
1030 field = rec_get_nth_field_old(rec, 4, &len);
1031 foreign->referenced_table_name = mem_heap_strdupl(
1032 foreign->heap, (char*) field, len);
1033+ dict_mem_referenced_table_name_lookup_set(foreign, TRUE);
1034
1035 btr_pcur_close(&pcur);
1036 mtr_commit(&mtr);
1037@@ -2152,7 +2166,7 @@
1038 dict_load_foreign_cols(id, foreign);
1039
1040 ref_table = dict_table_check_if_in_cache_low(
1041- foreign->referenced_table_name);
1042+ foreign->referenced_table_name_lookup);
1043
1044 /* We could possibly wind up in a deep recursive calls if
1045 we call dict_table_get_low() again here if there
1046@@ -2185,7 +2199,7 @@
1047 have to load it so that we are able to make type comparisons
1048 in the next function call. */
1049
1050- for_table = dict_table_get_low(foreign->foreign_table_name);
1051+ for_table = dict_table_get_low(foreign->foreign_table_name_lookup);
1052
1053 if (for_table && ref_table && check_recursive) {
1054 /* This is to record the longest chain of ancesters
1055
1056=== modified file 'plugin/innobase/dict/dict0mem.cc'
1057--- plugin/innobase/dict/dict0mem.cc 2010-12-28 03:48:30 +0000
1058+++ plugin/innobase/dict/dict0mem.cc 2012-05-22 12:41:18 +0000
1059@@ -33,6 +33,8 @@
1060 #include "data0type.h"
1061 #include "mach0data.h"
1062 #include "dict0dict.h"
1063+#include "srv0srv.h" /* srv_lower_case_table_names */
1064+#include "ha_prototypes.h" /* innobase_casedn_str()*/
1065 #ifndef UNIV_HOTBACKUP
1066 # include "lock0lock.h"
1067 #endif /* !UNIV_HOTBACKUP */
1068@@ -288,6 +290,60 @@
1069 }
1070
1071 /**********************************************************************//**
1072+Sets the foreign_table_name_lookup pointer based on the value of
1073+srv_lower_case_table_names. If that is 0 or 1, foreign_table_name_lookup
1074+will point to foreign_table_name. If 2, then another string is allocated
1075+of the heap and set to lower case. */
1076+UNIV_INTERN
1077+void
1078+dict_mem_foreign_table_name_lookup_set(
1079+/*===================================*/
1080+ dict_foreign_t* foreign, /*!< in/out: foreign struct */
1081+ ibool do_alloc) /*!< in: is an alloc needed */
1082+{
1083+ if (srv_lower_case_table_names == 2) {
1084+ if (do_alloc) {
1085+ foreign->foreign_table_name_lookup = static_cast<char *>(mem_heap_alloc(
1086+ foreign->heap,
1087+ strlen(foreign->foreign_table_name) + 1));
1088+ }
1089+ strcpy(foreign->foreign_table_name_lookup,
1090+ foreign->foreign_table_name);
1091+ innobase_casedn_str(foreign->foreign_table_name_lookup);
1092+ } else {
1093+ foreign->foreign_table_name_lookup
1094+ = foreign->foreign_table_name;
1095+ }
1096+}
1097+
1098+/**********************************************************************//**
1099+Sets the referenced_table_name_lookup pointer based on the value of
1100+srv_lower_case_table_names. If that is 0 or 1,
1101+referenced_table_name_lookup will point to referenced_table_name. If 2,
1102+then another string is allocated of the heap and set to lower case. */
1103+UNIV_INTERN
1104+void
1105+dict_mem_referenced_table_name_lookup_set(
1106+/*======================================*/
1107+ dict_foreign_t* foreign, /*!< in/out: foreign struct */
1108+ ibool do_alloc) /*!< in: is an alloc needed */
1109+{
1110+ if (srv_lower_case_table_names == 2) {
1111+ if (do_alloc) {
1112+ foreign->referenced_table_name_lookup = static_cast<char *>(mem_heap_alloc(
1113+ foreign->heap,
1114+ strlen(foreign->referenced_table_name) + 1));
1115+ }
1116+ strcpy(foreign->referenced_table_name_lookup,
1117+ foreign->referenced_table_name);
1118+ innobase_casedn_str(foreign->referenced_table_name_lookup);
1119+ } else {
1120+ foreign->referenced_table_name_lookup
1121+ = foreign->referenced_table_name;
1122+ }
1123+}
1124+
1125+/**********************************************************************//**
1126 Adds a field definition to an index. NOTE: does not take a copy
1127 of the column name if the field is a column. The memory occupied
1128 by the column name may be released only after publishing the index. */
1129
1130=== modified file 'plugin/innobase/fil/fil0fil.cc'
1131--- plugin/innobase/fil/fil0fil.cc 2011-07-30 09:20:56 +0000
1132+++ plugin/innobase/fil/fil0fil.cc 2012-05-22 12:41:18 +0000
1133@@ -300,6 +300,34 @@
1134 initialized. */
1135 fil_system_t* fil_system = NULL;
1136
1137+#ifdef UNIV_DEBUG
1138+/** Try fil_validate() every this many times */
1139+# define FIL_VALIDATE_SKIP 17
1140+
1141+/******************************************************************//**
1142+Checks the consistency of the tablespace cache some of the time.
1143+@return TRUE if ok or the check was skipped */
1144+static
1145+ibool
1146+fil_validate_skip(void)
1147+/*===================*/
1148+{
1149+ /** The fil_validate() call skip counter. Use a signed type
1150+ because of the race condition below. */
1151+ static int fil_validate_count = FIL_VALIDATE_SKIP;
1152+
1153+ /* There is a race condition below, but it does not matter,
1154+ because this call is only for heuristic purposes. We want to
1155+ reduce the call frequency of the costly fil_validate() check
1156+ in debug builds. */
1157+ if (--fil_validate_count > 0) {
1158+ return(TRUE);
1159+ }
1160+
1161+ fil_validate_count = FIL_VALIDATE_SKIP;
1162+ return(fil_validate());
1163+}
1164+#endif /* UNIV_DEBUG */
1165
1166 /********************************************************************//**
1167 NOTE: you must call fil_mutex_enter_and_prepare_for_io() first!
1168@@ -4304,7 +4332,7 @@
1169 ut_ad(ut_is_2pow(zip_size));
1170 ut_ad(buf);
1171 ut_ad(len > 0);
1172- ut_ad(fil_validate());
1173+ ut_ad(fil_validate_skip());
1174 #ifndef UNIV_HOTBACKUP
1175 # ifndef UNIV_LOG_DEBUG
1176 /* ibuf bitmap pages must be read in the sync aio mode: */
1177@@ -4463,7 +4491,7 @@
1178
1179 mutex_exit(&fil_system->mutex);
1180
1181- ut_ad(fil_validate());
1182+ ut_ad(fil_validate_skip());
1183 }
1184
1185 return(DB_SUCCESS);
1186@@ -4551,7 +4579,7 @@
1187 void* message;
1188 ulint type;
1189
1190- ut_ad(fil_validate());
1191+ ut_ad(fil_validate_skip());
1192
1193 if (srv_use_native_aio) {
1194 srv_set_io_thread_op_info(segment, "native aio handle");
1195@@ -4582,7 +4610,7 @@
1196
1197 mutex_exit(&fil_system->mutex);
1198
1199- ut_ad(fil_validate());
1200+ ut_ad(fil_validate_skip());
1201
1202 /* Do the i/o handling */
1203 /* IMPORTANT: since i/o handling for reads will read also the insert
1204
1205=== modified file 'plugin/innobase/fsp/fsp0fsp.cc'
1206--- plugin/innobase/fsp/fsp0fsp.cc 2011-04-05 10:32:12 +0000
1207+++ plugin/innobase/fsp/fsp0fsp.cc 2012-05-22 12:41:18 +0000
1208@@ -3310,7 +3310,7 @@
1209 "InnoDB: database!\n", (ulong) page);
1210 crash:
1211 fputs("InnoDB: Please refer to\n"
1212- "InnoDB: " REFMAN "forcing-recovery.html\n"
1213+ "InnoDB: " REFMAN "forcing-innodb-recovery.html\n"
1214 "InnoDB: about forcing recovery.\n", stderr);
1215 ut_error;
1216 }
1217
1218=== modified file 'plugin/innobase/handler/ha_innodb.cc'
1219--- plugin/innobase/handler/ha_innodb.cc 2012-03-03 20:57:17 +0000
1220+++ plugin/innobase/handler/ha_innodb.cc 2012-05-22 12:41:18 +0000
1221@@ -7370,7 +7370,7 @@
1222 /* We do not update delete_length if no
1223 locking is requested so the "old" value can
1224 remain. delete_length is initialized to 0 in
1225- the ha_statistics' constructor. */
1226+ the ha_statistics' constructor.*/
1227 } else if (UNIV_UNLIKELY
1228 (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE)) {
1229 /* Avoid accessing the tablespace if
1230
1231=== modified file 'plugin/innobase/ibuf/ibuf0ibuf.cc'
1232--- plugin/innobase/ibuf/ibuf0ibuf.cc 2011-04-07 05:47:57 +0000
1233+++ plugin/innobase/ibuf/ibuf0ibuf.cc 2012-05-22 12:41:18 +0000
1234@@ -658,22 +658,50 @@
1235 return(ptr);
1236 }
1237 #ifndef UNIV_HOTBACKUP
1238+# ifdef UNIV_DEBUG
1239+/** Gets the desired bits for a given page from a bitmap page.
1240+@param page in: bitmap page
1241+@param offset in: page whose bits to get
1242+@param zs in: compressed page size in bytes; 0 for uncompressed pages
1243+@param bit in: IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
1244+@param mtr in: mini-transaction holding an x-latch on the bitmap page
1245+@return value of bits */
1246+# define ibuf_bitmap_page_get_bits(page, offset, zs, bit, mtr) \
1247+ ibuf_bitmap_page_get_bits_low(page, offset, zs, \
1248+ MTR_MEMO_PAGE_X_FIX, mtr, bit)
1249+# else /* UNIV_DEBUG */
1250+/** Gets the desired bits for a given page from a bitmap page.
1251+@param page in: bitmap page
1252+@param offset in: page whose bits to get
1253+@param zs in: compressed page size in bytes; 0 for uncompressed pages
1254+@param bit in: IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
1255+@param mtr in: mini-transaction holding an x-latch on the bitmap page
1256+@return value of bits */
1257+# define ibuf_bitmap_page_get_bits(page, offset, zs, bit, mtr) \
1258+ ibuf_bitmap_page_get_bits_low(page, offset, zs, bit)
1259+# endif /* UNIV_DEBUG */
1260+
1261 /********************************************************************//**
1262 Gets the desired bits for a given page from a bitmap page.
1263 @return value of bits */
1264 UNIV_INLINE
1265 ulint
1266-ibuf_bitmap_page_get_bits(
1267-/*======================*/
1268+ibuf_bitmap_page_get_bits_low(
1269+/*==========================*/
1270 const page_t* page, /*!< in: bitmap page */
1271 ulint page_no,/*!< in: page whose bits to get */
1272 ulint zip_size,/*!< in: compressed page size in bytes;
1273 0 for uncompressed pages */
1274- ulint bit, /*!< in: IBUF_BITMAP_FREE,
1275+#ifdef UNIV_DEBUG
1276+ ulint latch_type,
1277+ /*!< in: MTR_MEMO_PAGE_X_FIX,
1278+ MTR_MEMO_BUF_FIX, ... */
1279+ mtr_t* mtr, /*!< in: mini-transaction holding latch_type
1280+ on the bitmap page */
1281+#endif /* UNIV_DEBUG */
1282+ ulint bit) /*!< in: IBUF_BITMAP_FREE,
1283+
1284 IBUF_BITMAP_BUFFERED, ... */
1285- mtr_t* /*mtr __attribute__((unused))*/)
1286- /*!< in: mtr containing an
1287- x-latch to the bitmap page */
1288 {
1289 ulint byte_offset;
1290 ulint bit_offset;
1291@@ -685,7 +713,7 @@
1292 # error "IBUF_BITS_PER_PAGE % 2 != 0"
1293 #endif
1294 ut_ad(ut_is_2pow(zip_size));
1295- ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
1296+ ut_ad(mtr_memo_contains_page(mtr, page, latch_type));
1297
1298 if (!zip_size) {
1299 bit_offset = (page_no % UNIV_PAGE_SIZE) * IBUF_BITS_PER_PAGE
1300@@ -1111,21 +1139,29 @@
1301 @return TRUE if level 2 or level 3 page */
1302 UNIV_INTERN
1303 ibool
1304-ibuf_page(
1305-/*======*/
1306- ulint space, /*!< in: space id */
1307- ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
1308- ulint page_no,/*!< in: page number */
1309- mtr_t* mtr) /*!< in: mtr which will contain an x-latch to the
1310- bitmap page if the page is not one of the fixed
1311- address ibuf pages, or NULL, in which case a new
1312- transaction is created. */
1313+ibuf_page_low(
1314+/*==========*/
1315+ ulint space, /*!< in: space id */
1316+ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
1317+ ulint page_no,/*!< in: page number */
1318+#ifdef UNIV_DEBUG
1319+ ibool x_latch,/*!< in: FALSE if relaxed check
1320+ (avoid latching the bitmap page) */
1321+#endif /* UNIV_DEBUG */
1322+ const char* file, /*!< in: file name */
1323+ ulint line, /*!< in: line where called */
1324+ mtr_t* mtr) /*!< in: mtr which will contain an
1325+ x-latch to the bitmap page if the page
1326+ is not one of the fixed address ibuf
1327+ pages, or NULL, in which case a new
1328+ transaction is created. */
1329 {
1330 ibool ret;
1331 mtr_t local_mtr;
1332 page_t* bitmap_page;
1333
1334 ut_ad(!recv_no_ibuf_operations);
1335+ ut_ad(x_latch || mtr == NULL);
1336
1337 if (srv_fake_write)
1338 return(FALSE);
1339@@ -1140,12 +1176,55 @@
1340
1341 ut_ad(fil_space_get_type(IBUF_SPACE_ID) == FIL_TABLESPACE);
1342
1343+#ifdef UNIV_DEBUG
1344+ if (!x_latch) {
1345+ mtr_start(&local_mtr);
1346+
1347+ /* Get the bitmap page without a page latch, so that
1348+ we will not be violating the latching order when
1349+ another bitmap page has already been latched by this
1350+ thread. The page will be buffer-fixed, and thus it
1351+ cannot be removed or relocated while we are looking at
1352+ it. The contents of the page could change, but the
1353+ IBUF_BITMAP_IBUF bit that we are interested in should
1354+ not be modified by any other thread. Nobody should be
1355+ calling ibuf_add_free_page() or ibuf_remove_free_page()
1356+ while the page is linked to the insert buffer b-tree. */
1357+
1358+ bitmap_page = buf_block_get_frame(
1359+ buf_page_get_gen(
1360+ space, zip_size,
1361+ ibuf_bitmap_page_no_calc(zip_size, page_no),
1362+ RW_NO_LATCH, NULL, BUF_GET_NO_LATCH,
1363+ file, line, &local_mtr));
1364+# ifdef UNIV_SYNC_DEBUG
1365+ /* This is for tracking Bug #58212. This check and message can
1366+ be removed once it has been established that our assumptions
1367+ about this condition are correct. The bug was only a one-time
1368+ occurrence, unable to repeat since then. */
1369+ void* latch = sync_thread_levels_contains(SYNC_IBUF_BITMAP);
1370+ if (latch) {
1371+ fprintf(stderr, "Bug#58212 UNIV_SYNC_DEBUG"
1372+ " levels %p (%u,%u)\n",
1373+ latch, (unsigned) space, (unsigned) page_no);
1374+ }
1375+# endif /* UNIV_SYNC_DEBUG */
1376+ ret = ibuf_bitmap_page_get_bits_low(
1377+ bitmap_page, page_no, zip_size,
1378+ MTR_MEMO_BUF_FIX, &local_mtr, IBUF_BITMAP_IBUF);
1379+
1380+ mtr_commit(&local_mtr);
1381+ return(ret);
1382+ }
1383+#endif /* UNIV_DEBUG */
1384+
1385 if (mtr == NULL) {
1386 mtr = &local_mtr;
1387 mtr_start(mtr);
1388 }
1389
1390- bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr);
1391+ bitmap_page = ibuf_bitmap_get_map_page_func(space, page_no, zip_size,
1392+ file, line, mtr);
1393
1394 ret = ibuf_bitmap_page_get_bits(bitmap_page, page_no, zip_size,
1395 IBUF_BITMAP_IBUF, mtr);
1396
1397=== modified file 'plugin/innobase/include/btr0cur.h'
1398--- plugin/innobase/include/btr0cur.h 2011-03-14 05:40:28 +0000
1399+++ plugin/innobase/include/btr0cur.h 2012-05-22 12:41:18 +0000
1400@@ -334,10 +334,14 @@
1401 btr_cur_del_mark_set_clust_rec(
1402 /*===========================*/
1403 ulint flags, /*!< in: undo logging and locking flags */
1404- btr_cur_t* cursor, /*!< in: cursor */
1405+ buf_block_t* block, /*!< in/out: buffer block of the record */
1406+ rec_t* rec, /*!< in/out: record */
1407+ dict_index_t* index, /*!< in: clustered index of the record */
1408+ const ulint* offsets,/*!< in: rec_get_offsets(rec) */
1409 ibool val, /*!< in: value to set */
1410 que_thr_t* thr, /*!< in: query thread */
1411- mtr_t* mtr); /*!< in: mtr */
1412+ mtr_t* mtr) /*!< in: mtr */
1413+ __attribute__((nonnull));
1414 /***********************************************************//**
1415 Sets a secondary index record delete mark to TRUE or FALSE.
1416 @return DB_SUCCESS, DB_LOCK_WAIT, or error number */
1417@@ -470,40 +474,22 @@
1418 /*======================================*/
1419 dict_index_t* index); /*!< in: index */
1420 /*******************************************************************//**
1421-Marks not updated extern fields as not-owned by this record. The ownership
1422-is transferred to the updated record which is inserted elsewhere in the
1423+Marks non-updated off-page fields as disowned by this record. The ownership
1424+must be transferred to the updated record which is inserted elsewhere in the
1425 index tree. In purge only the owner of externally stored field is allowed
1426-to free the field.
1427-@return TRUE if BLOB ownership was transferred */
1428+to free the field. */
1429 UNIV_INTERN
1430-ibool
1431-btr_cur_mark_extern_inherited_fields(
1432-/*=================================*/
1433+void
1434+btr_cur_disown_inherited_fields(
1435+/*============================*/
1436 page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
1437 part will be updated, or NULL */
1438 rec_t* rec, /*!< in/out: record in a clustered index */
1439 dict_index_t* index, /*!< in: index of the page */
1440 const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
1441 const upd_t* update, /*!< in: update vector */
1442- mtr_t* mtr); /*!< in: mtr, or NULL if not logged */
1443-/*******************************************************************//**
1444-The complement of the previous function: in an update entry may inherit
1445-some externally stored fields from a record. We must mark them as inherited
1446-in entry, so that they are not freed in a rollback. */
1447-UNIV_INTERN
1448-void
1449-btr_cur_mark_dtuple_inherited_extern(
1450-/*=================================*/
1451- dtuple_t* entry, /*!< in/out: updated entry to be
1452- inserted to clustered index */
1453- const upd_t* update); /*!< in: update vector */
1454-/*******************************************************************//**
1455-Marks all extern fields in a dtuple as owned by the record. */
1456-UNIV_INTERN
1457-void
1458-btr_cur_unmark_dtuple_extern_fields(
1459-/*================================*/
1460- dtuple_t* entry); /*!< in/out: clustered index entry */
1461+ mtr_t* mtr) /*!< in/out: mini-transaction */
1462+ __attribute__((nonnull(2,3,4,5,6)));
1463 /*******************************************************************//**
1464 Stores the fields in big_rec_vec to the tablespace and puts pointers to
1465 them in rec. The extern flags in rec will have to be set beforehand.
1466
1467=== modified file 'plugin/innobase/include/buf0buf.h'
1468--- plugin/innobase/include/buf0buf.h 2011-04-05 10:32:12 +0000
1469+++ plugin/innobase/include/buf0buf.h 2012-05-22 12:41:18 +0000
1470@@ -113,6 +113,76 @@
1471 before putting to the free list */
1472 };
1473
1474+
1475+/** This structure defines information we will fetch from each buffer pool. It
1476+will be used to print table IO stats */
1477+struct buf_pool_info_struct{
1478+ /* General buffer pool info */
1479+ ulint pool_unique_id; /*!< Buffer Pool ID */
1480+ ulint pool_size; /*!< Buffer Pool size in pages */
1481+ ulint lru_len; /*!< Length of buf_pool->LRU */
1482+ ulint old_lru_len; /*!< buf_pool->LRU_old_len */
1483+ ulint free_list_len; /*!< Length of buf_pool->free list */
1484+ ulint flush_list_len; /*!< Length of buf_pool->flush_list */
1485+ ulint n_pend_unzip; /*!< buf_pool->n_pend_unzip, pages
1486+ pending decompress */
1487+ ulint n_pend_reads; /*!< buf_pool->n_pend_reads, pages
1488+ pending read */
1489+ ulint n_pending_flush_lru; /*!< Pages pending flush in LRU */
1490+ ulint n_pending_flush_list; /*!< Pages pending flush in FLUSH
1491+ LIST */
1492+ ulint n_pending_flush_single_page;/*!< Pages pending flush in
1493+ BUF_FLUSH_SINGLE_PAGE list */
1494+ ulint n_pages_made_young; /*!< number of pages made young */
1495+ ulint n_pages_not_made_young; /*!< number of pages not made young */
1496+ ulint n_pages_read; /*!< buf_pool->n_pages_read */
1497+ ulint n_pages_created; /*!< buf_pool->n_pages_created */
1498+ ulint n_pages_written; /*!< buf_pool->n_pages_written */
1499+ ulint n_page_gets; /*!< buf_pool->n_page_gets */
1500+ ulint n_ra_pages_read; /*!< buf_pool->n_ra_pages_read, number
1501+ of pages readahead */
1502+ ulint n_ra_pages_evicted; /*!< buf_pool->n_ra_pages_evicted,
1503+ number of readahead pages evicted
1504+ without access */
1505+ ulint n_page_get_delta; /*!< num of buffer pool page gets since
1506+ last printout */
1507+
1508+ /* Buffer pool access stats */
1509+ double page_made_young_rate; /*!< page made young rate in pages
1510+ per second */
1511+ double page_not_made_young_rate;/*!< page not made young rate
1512+ in pages per second */
1513+ double pages_read_rate; /*!< num of pages read per second */
1514+ double pages_created_rate; /*!< num of pages create per second */
1515+ double pages_written_rate; /*!< num of pages written per second */
1516+ ulint page_read_delta; /*!< num of pages read since last
1517+ printout */
1518+ ulint young_making_delta; /*!< num of pages made young since
1519+ last printout */
1520+ ulint not_young_making_delta; /*!< num of pages not make young since
1521+ last printout */
1522+
1523+ /* Statistics about read ahead algorithm. */
1524+ double pages_readahead_rate; /*!< readahead rate in pages per
1525+ second */
1526+ double pages_evicted_rate; /*!< rate of readahead page evicted
1527+ without access, in pages per second */
1528+
1529+ /* Stats about LRU eviction */
1530+ ulint unzip_lru_len; /*!< length of buf_pool->unzip_LRU
1531+ list */
1532+ /* Counters for LRU policy */
1533+ ulint io_sum; /*!< buf_LRU_stat_sum.io */
1534+ ulint io_cur; /*!< buf_LRU_stat_cur.io, num of IO
1535+ for current interval */
1536+ ulint unzip_sum; /*!< buf_LRU_stat_sum.unzip */
1537+ ulint unzip_cur; /*!< buf_LRU_stat_cur.unzip, num
1538+ pages decompressed in current
1539+ interval */
1540+};
1541+
1542+typedef struct buf_pool_info_struct buf_pool_info_t;
1543+
1544 #ifndef UNIV_HOTBACKUP
1545 /********************************************************************//**
1546 Acquire mutex on all buffer pool instances */
1547
1548=== modified file 'plugin/innobase/include/data0data.h'
1549--- plugin/innobase/include/data0data.h 2011-03-14 05:40:28 +0000
1550+++ plugin/innobase/include/data0data.h 2012-05-22 12:41:18 +0000
1551@@ -155,14 +155,19 @@
1552 dfield_t* field, /*!< in/out: data field */
1553 mem_heap_t* heap); /*!< in: memory heap where allocated */
1554 /*********************************************************************//**
1555-Tests if data length and content is equal for two dfields.
1556-@return TRUE if equal */
1557+Tests if two data fields are equal.
1558+If len==0, tests the data length and content for equality.
1559+If len>0, tests the first len bytes of the content for equality.
1560+@return TRUE if both fields are NULL or if they are equal */
1561 UNIV_INLINE
1562 ibool
1563 dfield_datas_are_binary_equal(
1564 /*==========================*/
1565 const dfield_t* field1, /*!< in: field */
1566- const dfield_t* field2);/*!< in: field */
1567+ const dfield_t* field2, /*!< in: field */
1568+ ulint len) /*!< in: maximum prefix to compare,
1569+ or 0 to compare the whole field length */
1570+ __attribute__((nonnull, warn_unused_result));
1571 /*********************************************************************//**
1572 Tests if dfield data length and content is equal to the given.
1573 @return TRUE if equal */
1574
1575=== modified file 'plugin/innobase/include/data0data.ic'
1576--- plugin/innobase/include/data0data.ic 2010-12-18 04:43:40 +0000
1577+++ plugin/innobase/include/data0data.ic 2012-05-22 12:41:18 +0000
1578@@ -229,20 +229,30 @@
1579 }
1580
1581 /*********************************************************************//**
1582-Tests if data length and content is equal for two dfields.
1583-@return TRUE if equal */
1584+Tests if two data fields are equal.
1585+If len==0, tests the data length and content for equality.
1586+If len>0, tests the first len bytes of the content for equality.
1587+@return TRUE if both fields are NULL or if they are equal */
1588 UNIV_INLINE
1589 ibool
1590 dfield_datas_are_binary_equal(
1591 /*==========================*/
1592 const dfield_t* field1, /*!< in: field */
1593- const dfield_t* field2) /*!< in: field */
1594+ const dfield_t* field2, /*!< in: field */
1595+ ulint len) /*!< in: maximum prefix to compare,
1596+ or 0 to compare the whole field length */
1597 {
1598- ulint len;
1599-
1600- len = field1->len;
1601-
1602- return(len == field2->len
1603+ ulint len2 = len;
1604+
1605+ if (field1->len == UNIV_SQL_NULL || len == 0 || field1->len < len) {
1606+ len = field1->len;
1607+ }
1608+
1609+ if (field2->len == UNIV_SQL_NULL || len2 == 0 || field2->len < len2) {
1610+ len2 = field2->len;
1611+ }
1612+
1613+ return(len == len2
1614 && (len == UNIV_SQL_NULL
1615 || !memcmp(field1->data, field2->data, len)));
1616 }
1617
1618=== modified file 'plugin/innobase/include/dict0mem.h'
1619--- plugin/innobase/include/dict0mem.h 2011-03-14 05:40:28 +0000
1620+++ plugin/innobase/include/dict0mem.h 2012-05-22 12:41:18 +0000
1621@@ -239,6 +239,26 @@
1622 dict_mem_foreign_create(void);
1623 /*=========================*/
1624
1625+/**********************************************************************//**
1626+Sets the foreign_table_name_lookup pointer based on the value of
1627+srv_lower_case_table_names. */
1628+UNIV_INTERN
1629+void
1630+dict_mem_foreign_table_name_lookup_set(
1631+/*===================================*/
1632+ dict_foreign_t* foreign, /*!< in/out: foreign struct */
1633+ ibool do_alloc); /*!< in: is an alloc needed */
1634+
1635+/**********************************************************************//**
1636+Sets the reference_table_name_lookup pointer based on the value of
1637+srv_lower_case_table_names. */
1638+UNIV_INTERN
1639+void
1640+dict_mem_referenced_table_name_lookup_set(
1641+/*======================================*/
1642+ dict_foreign_t* foreign, /*!< in/out: foreign struct */
1643+ ibool do_alloc); /*!< in: is an alloc needed */
1644+
1645 /** Data structure for a column in a table */
1646 struct dict_col_struct{
1647 /*----------------------*/
1648@@ -394,10 +414,14 @@
1649 unsigned type:6; /*!< 0 or DICT_FOREIGN_ON_DELETE_CASCADE
1650 or DICT_FOREIGN_ON_DELETE_SET_NULL */
1651 char* foreign_table_name;/*!< foreign table name */
1652+ char* foreign_table_name_lookup;
1653+ /*!< foreign table name used for dict lookup */
1654 dict_table_t* foreign_table; /*!< table where the foreign key is */
1655 const char** foreign_col_names;/*!< names of the columns in the
1656 foreign key */
1657 char* referenced_table_name;/*!< referenced table name */
1658+ char* referenced_table_name_lookup;
1659+ /*!< referenced table name for dict lookup*/
1660 dict_table_t* referenced_table;/*!< table where the referenced key
1661 is */
1662 const char** referenced_col_names;/*!< names of the referenced
1663
1664=== modified file 'plugin/innobase/include/ibuf0ibuf.h'
1665--- plugin/innobase/include/ibuf0ibuf.h 2011-03-14 05:40:28 +0000
1666+++ plugin/innobase/include/ibuf0ibuf.h 2012-05-22 12:41:18 +0000
1667@@ -245,15 +245,44 @@
1668 @return TRUE if level 2 or level 3 page */
1669 UNIV_INTERN
1670 ibool
1671-ibuf_page(
1672-/*======*/
1673- ulint space, /*!< in: space id */
1674- ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
1675- ulint page_no,/*!< in: page number */
1676- mtr_t* mtr); /*!< in: mtr which will contain an x-latch to the
1677- bitmap page if the page is not one of the fixed
1678- address ibuf pages, or NULL, in which case a new
1679- transaction is created. */
1680+ibuf_page_low(
1681+/*==========*/
1682+ ulint space, /*!< in: space id */
1683+ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
1684+ ulint page_no,/*!< in: page number */
1685+#ifdef UNIV_DEBUG
1686+ ibool x_latch,/*!< in: FALSE if relaxed check
1687+ (avoid latching the bitmap page) */
1688+#endif /* UNIV_DEBUG */
1689+ const char* file, /*!< in: file name */
1690+ ulint line, /*!< in: line where called */
1691+ mtr_t* mtr) /*!< in: mtr which will contain an
1692+ x-latch to the bitmap page if the page
1693+ is not one of the fixed address ibuf
1694+ pages, or NULL, in which case a new
1695+ transaction is created. */
1696+ __attribute__((warn_unused_result));
1697+#ifdef UNIV_DEBUG
1698+/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of
1699+pages. Must not be called when recv_no_ibuf_operations==TRUE.
1700+@param space tablespace identifier
1701+@param zip_size compressed page size in bytes, or 0
1702+@param page_no page number
1703+@param mtr mini-transaction or NULL
1704+@return TRUE if level 2 or level 3 page */
1705+# define ibuf_page(space, zip_size, page_no, mtr) \
1706+ ibuf_page_low(space, zip_size, page_no, TRUE, __FILE__, __LINE__, mtr)
1707+#else /* UVIV_DEBUG */
1708+/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of
1709+pages. Must not be called when recv_no_ibuf_operations==TRUE.
1710+@param space tablespace identifier
1711+@param zip_size compressed page size in bytes, or 0
1712+@param page_no page number
1713+@param mtr mini-transaction or NULL
1714+@return TRUE if level 2 or level 3 page */
1715+# define ibuf_page(space, zip_size, page_no, mtr) \
1716+ ibuf_page_low(space, zip_size, page_no, __FILE__, __LINE__, mtr)
1717+#endif /* UVIV_DEBUG */
1718 /***********************************************************************//**
1719 Frees excess pages from the ibuf free list. This function is called when an OS
1720 thread calls fsp services to allocate a new file segment, or a new page to a
1721
1722=== modified file 'plugin/innobase/include/mem0mem.ic'
1723--- plugin/innobase/include/mem0mem.ic 2010-12-18 04:43:40 +0000
1724+++ plugin/innobase/include/mem0mem.ic 2012-05-22 12:41:18 +0000
1725@@ -350,27 +350,27 @@
1726 ulint n) /*!< in: size of the topmost element */
1727 {
1728 mem_block_t* block;
1729- void* buf;
1730+ byte* buf;
1731
1732 ut_ad(mem_heap_check(heap));
1733
1734 block = UT_LIST_GET_LAST(heap->base);
1735
1736- buf = (byte*)block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n);
1737+ buf = (byte*) block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n);
1738
1739 #ifdef UNIV_MEM_DEBUG
1740- ut_ad(mem_block_get_start(block) <=(ulint)((byte*)buf - (byte*)block));
1741+ ut_ad(mem_block_get_start(block) <= (ulint) (buf - (byte*) block));
1742
1743 /* In the debug version, advance buf to point at the storage which
1744 was given to the caller in the allocation*/
1745
1746- buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
1747+ buf += MEM_FIELD_HEADER_SIZE;
1748
1749 /* Check that the field lengths agree */
1750- ut_ad(n == (ulint)mem_field_header_get_len(buf));
1751+ ut_ad(n == mem_field_header_get_len(buf));
1752 #endif
1753
1754- return(buf);
1755+ return((void*) buf);
1756 }
1757
1758 /*****************************************************************//**
1759
1760=== modified file 'plugin/innobase/include/mtr0mtr.ic'
1761--- plugin/innobase/include/mtr0mtr.ic 2010-12-18 04:43:40 +0000
1762+++ plugin/innobase/include/mtr0mtr.ic 2012-05-22 12:41:18 +0000
1763@@ -160,7 +160,7 @@
1764 while (offset > 0) {
1765 offset -= sizeof(mtr_memo_slot_t);
1766
1767- slot = dyn_array_get_element(memo, offset);
1768+ slot = (mtr_memo_slot_t*) dyn_array_get_element(memo, offset);
1769
1770 if ((object == slot->object) && (type == slot->type)) {
1771
1772
1773=== modified file 'plugin/innobase/include/os0file.h'
1774--- plugin/innobase/include/os0file.h 2011-04-05 10:32:12 +0000
1775+++ plugin/innobase/include/os0file.h 2012-05-22 12:41:18 +0000
1776@@ -376,6 +376,7 @@
1777 typedef DIR* os_file_dir_t; /*!< directory stream */
1778 #endif
1779
1780+#ifdef __WIN__
1781 /***********************************************************************//**
1782 Gets the operating system version. Currently works only on Windows.
1783 @return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000, OS_WINXP, OS_WINVISTA,
1784@@ -384,6 +385,7 @@
1785 ulint
1786 os_get_os_version(void);
1787 /*===================*/
1788+#endif /* __WIN__ */
1789 #ifndef UNIV_HOTBACKUP
1790 /****************************************************************//**
1791 Creates the seek mutexes used in positioned reads and writes. */
1792
1793=== modified file 'plugin/innobase/include/row0upd.h'
1794--- plugin/innobase/include/row0upd.h 2011-03-14 05:40:28 +0000
1795+++ plugin/innobase/include/row0upd.h 2012-05-22 12:41:18 +0000
1796@@ -287,10 +287,13 @@
1797 row and the data values in update are not
1798 known when this function is called, e.g., at
1799 compile time */
1800+ const row_ext_t*ext, /*!< NULL, or prefixes of the externally
1801+ stored columns in the old row */
1802 dict_index_t* index, /*!< in: index of the record */
1803- const upd_t* update);/*!< in: update vector for the row; NOTE: the
1804+ const upd_t* update) /*!< in: update vector for the row; NOTE: the
1805 field numbers in this MUST be clustered index
1806 positions! */
1807+ __attribute__((nonnull(3,4), warn_unused_result));
1808 /***********************************************************//**
1809 Checks if an update vector changes an ordering field of an index record.
1810 This function is fast if the update vector is short or the number of ordering
1811@@ -463,11 +466,16 @@
1812 #define UPD_NODE_INSERT_CLUSTERED 3 /* clustered index record should be
1813 inserted, old record is already delete
1814 marked */
1815-#define UPD_NODE_UPDATE_ALL_SEC 4 /* an ordering field of the clustered
1816+#define UPD_NODE_INSERT_BLOB 4 /* clustered index record should be
1817+ inserted, old record is already
1818+ delete-marked; non-updated BLOBs
1819+ should be inherited by the new record
1820+ and disowned by the old record */
1821+#define UPD_NODE_UPDATE_ALL_SEC 5 /* an ordering field of the clustered
1822 index record was changed, or this is
1823 a delete operation: should update
1824 all the secondary index records */
1825-#define UPD_NODE_UPDATE_SOME_SEC 5 /* secondary index entries should be
1826+#define UPD_NODE_UPDATE_SOME_SEC 6 /* secondary index entries should be
1827 looked at and updated if an ordering
1828 field changed */
1829
1830
1831=== modified file 'plugin/innobase/include/srv0srv.h'
1832--- plugin/innobase/include/srv0srv.h 2011-04-11 21:43:24 +0000
1833+++ plugin/innobase/include/srv0srv.h 2012-05-22 12:41:18 +0000
1834@@ -77,8 +77,8 @@
1835 #define SRV_AUTO_EXTEND_INCREMENT \
1836 (srv_auto_extend_increment * ((1024 * 1024) / UNIV_PAGE_SIZE))
1837
1838-/* This is set to TRUE if the MySQL user has set it in MySQL */
1839-extern ibool srv_lower_case_table_names;
1840+/* This is set to the MySQL server value for this variable. */
1841+extern uint srv_lower_case_table_names;
1842
1843 /* Mutex for locking srv_monitor_file */
1844 extern mutex_t srv_monitor_file_mutex;
1845@@ -503,6 +503,14 @@
1846 srv_get_thread_type(void);
1847 /*=====================*/
1848 /*********************************************************************//**
1849+Check whether thread type has reserved a slot.
1850+@return slot number or UNDEFINED if not found*/
1851+UNIV_INTERN
1852+ulint
1853+srv_thread_has_reserved_slot(
1854+/*=========================*/
1855+ enum srv_thread_type type); /*!< in: thread type to check */
1856+/*********************************************************************//**
1857 Sets the info describing an i/o thread current state. */
1858 UNIV_INTERN
1859 void
1860
1861=== modified file 'plugin/innobase/include/sync0rw.h'
1862--- plugin/innobase/include/sync0rw.h 2011-03-14 05:40:28 +0000
1863+++ plugin/innobase/include/sync0rw.h 2012-05-22 12:41:18 +0000
1864@@ -123,6 +123,7 @@
1865 extern mysql_pfs_key_t trx_i_s_cache_lock_key;
1866 extern mysql_pfs_key_t trx_purge_latch_key;
1867 extern mysql_pfs_key_t index_tree_rw_lock_key;
1868+extern mysql_pfs_key_t dict_table_stats_latch_key;
1869 #endif /* UNIV_PFS_RWLOCK */
1870
1871
1872
1873=== modified file 'plugin/innobase/include/univ.i'
1874--- plugin/innobase/include/univ.i 2011-04-05 10:32:12 +0000
1875+++ plugin/innobase/include/univ.i 2012-05-22 12:41:18 +0000
1876@@ -50,9 +50,14 @@
1877 #include "hb_univ.i"
1878 #endif /* UNIV_HOTBACKUP */
1879
1880+/* aux macros to convert M into "123" (string) if M is defined like
1881+#define M 123 */
1882+#define _IB_TO_STR(s) #s
1883+#define IB_TO_STR(s) _IB_TO_STR(s)
1884+
1885 #define INNODB_VERSION_MAJOR 1
1886 #define INNODB_VERSION_MINOR 1
1887-#define INNODB_VERSION_BUGFIX 4
1888+#define INNODB_VERSION_BUGFIX 5
1889
1890 /* The following is the InnoDB version as shown in
1891 SELECT plugin_version FROM information_schema.plugins;
1892@@ -63,16 +68,14 @@
1893 #define INNODB_VERSION_SHORT \
1894 (INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR)
1895
1896-/* auxiliary macros to help creating the version as string */
1897-#define __INNODB_VERSION(a, b, c) (#a "." #b "." #c)
1898-#define _INNODB_VERSION(a, b, c) __INNODB_VERSION(a, b, c)
1899-
1900 #define INNODB_VERSION_STR \
1901- _INNODB_VERSION(INNODB_VERSION_MAJOR, \
1902- INNODB_VERSION_MINOR, \
1903- INNODB_VERSION_BUGFIX)
1904+ IB_TO_STR(INNODB_VERSION_MAJOR) "." \
1905+ IB_TO_STR(INNODB_VERSION_MINOR) "." \
1906+ IB_TO_STR(INNODB_VERSION_BUGFIX)
1907
1908-#define REFMAN "http://dev.mysql.com/doc/refman/5.1/en/"
1909+#define REFMAN "http://dev.mysql.com/doc/refman/" \
1910+ IB_TO_STR(MYSQL_MAJOR_VERSION) "." \
1911+ IB_TO_STR(MYSQL_MINOR_VERSION) "/en/"
1912
1913 #ifdef MYSQL_DYNAMIC_PLUGIN
1914 /* In the dynamic plugin, redefine some externally visible symbols
1915@@ -268,7 +271,7 @@
1916 # define UNIV_INTERN
1917 #endif
1918
1919-#if (!defined(UNIV_DEBUG) && !defined(UNIV_MUST_NOT_INLINE))
1920+#ifndef UNIV_MUST_NOT_INLINE
1921 /* Definition for inline version */
1922
1923 #ifdef __WIN__
1924@@ -331,6 +334,18 @@
1925 longer names internally */
1926 #define MAX_TABLE_NAME_LEN 192
1927
1928+/* The maximum length of a database name. Like MAX_TABLE_NAME_LEN this is
1929+the MySQL's NAME_LEN, see check_and_convert_db_name(). */
1930+#define MAX_DATABASE_NAME_LEN MAX_TABLE_NAME_LEN
1931+
1932+/* MAX_FULL_NAME_LEN defines the full name path including the
1933+database name and table name. In addition, 14 bytes is added for:
1934+ 2 for surrounding quotes around table name
1935+ 1 for the separating dot (.)
1936+ 9 for the #mysql50# prefix */
1937+#define MAX_FULL_NAME_LEN \
1938+ (MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN + 14)
1939+
1940 /*
1941 UNIVERSAL TYPE DEFINITIONS
1942 ==========================
1943
1944=== added file 'plugin/innobase/include/ut0bh.h'
1945--- plugin/innobase/include/ut0bh.h 1970-01-01 00:00:00 +0000
1946+++ plugin/innobase/include/ut0bh.h 2012-05-22 12:41:18 +0000
1947@@ -0,0 +1,152 @@
1948+/***************************************************************************//**
1949+
1950+Copyright (c) 2011, Oracle Corpn. All Rights Reserved.
1951+
1952+This program is free software; you can redistribute it and/or modify it under
1953+the terms of the GNU General Public License as published by the Free Software
1954+Foundation; version 2 of the License.
1955+
1956+This program is distributed in the hope that it will be useful, but WITHOUT
1957+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1958+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1959+
1960+You should have received a copy of the GNU General Public License along with
1961+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
1962+Place, Suite 330, Boston, MA 02111-1307 USA
1963+
1964+*****************************************************************************/
1965+
1966+/******************************************************************//**
1967+@file include/ut0bh.h
1968+Binary min-heap interface.
1969+
1970+Created 2010-05-28 by Sunny Bains
1971+*******************************************************/
1972+
1973+#ifndef INNOBASE_UT0BH_H
1974+#define INNOBASE_UT0BH_H
1975+
1976+#include "univ.i"
1977+
1978+/** Comparison function for objects in the binary heap. */
1979+typedef int (*ib_bh_cmp_t)(const void* p1, const void* p2);
1980+
1981+typedef struct ib_bh_struct ib_bh_t;
1982+
1983+/**********************************************************************//**
1984+Get the number of elements in the binary heap.
1985+@return number of elements */
1986+UNIV_INLINE
1987+ulint
1988+ib_bh_size(
1989+/*=======*/
1990+ const ib_bh_t* ib_bh); /*!< in: instance */
1991+
1992+/**********************************************************************//**
1993+Test if binary heap is empty.
1994+@return TRUE if empty. */
1995+UNIV_INLINE
1996+ibool
1997+ib_bh_is_empty(
1998+/*===========*/
1999+ const ib_bh_t* ib_bh); /*!< in: instance */
2000+
2001+/**********************************************************************//**
2002+Test if binary heap is full.
2003+@return TRUE if full. */
2004+UNIV_INLINE
2005+ibool
2006+ib_bh_is_full(
2007+/*===========*/
2008+ const ib_bh_t* ib_bh); /*!< in: instance */
2009+
2010+/**********************************************************************//**
2011+Get a pointer to the element.
2012+@return pointer to element */
2013+UNIV_INLINE
2014+void*
2015+ib_bh_get(
2016+/*=======*/
2017+ ib_bh_t* ib_bh, /*!< in: instance */
2018+ ulint i); /*!< in: index */
2019+
2020+/**********************************************************************//**
2021+Copy an element to the binary heap.
2022+@return pointer to copied element */
2023+UNIV_INLINE
2024+void*
2025+ib_bh_set(
2026+/*======*/
2027+ ib_bh_t* ib_bh, /*!< in/out: instance */
2028+ ulint i, /*!< in: index */
2029+ const void* elem); /*!< in: element to add */
2030+
2031+/**********************************************************************//**
2032+Return the first element from the binary heap.
2033+@return pointer to first element or NULL if empty. */
2034+UNIV_INLINE
2035+void*
2036+ib_bh_first(
2037+/*========*/
2038+ ib_bh_t* ib_bh); /*!< in: instance */
2039+
2040+/**********************************************************************//**
2041+Return the last element from the binary heap.
2042+@return pointer to last element or NULL if empty. */
2043+UNIV_INLINE
2044+void*
2045+ib_bh_last(
2046+/*========*/
2047+ ib_bh_t* ib_bh); /*!< in/out: instance */
2048+
2049+/**********************************************************************//**
2050+Create a binary heap.
2051+@return a new binary heap */
2052+UNIV_INTERN
2053+ib_bh_t*
2054+ib_bh_create(
2055+/*=========*/
2056+ ib_bh_cmp_t compare, /*!< in: comparator */
2057+ ulint sizeof_elem, /*!< in: size of one element */
2058+ ulint max_elems); /*!< in: max elements allowed */
2059+
2060+/**********************************************************************//**
2061+Free a binary heap.
2062+@return a new binary heap */
2063+UNIV_INTERN
2064+void
2065+ib_bh_free(
2066+/*=======*/
2067+ ib_bh_t* ib_bh); /*!< in,own: instance */
2068+
2069+/**********************************************************************//**
2070+Add an element to the binary heap. Note: The element is copied.
2071+@return pointer to added element or NULL if full. */
2072+UNIV_INTERN
2073+void*
2074+ib_bh_push(
2075+/*=======*/
2076+ ib_bh_t* ib_bh, /*!< in/out: instance */
2077+ const void* elem); /*!< in: element to add */
2078+
2079+/**********************************************************************//**
2080+Remove the first element from the binary heap. */
2081+UNIV_INTERN
2082+void
2083+ib_bh_pop(
2084+/*======*/
2085+ ib_bh_t* ib_bh); /*!< in/out: instance */
2086+
2087+/** Binary heap data structure */
2088+struct ib_bh_struct {
2089+ ulint max_elems; /*!< max elements allowed */
2090+ ulint n_elems; /*!< current size */
2091+ ulint sizeof_elem; /*!< sizeof element */
2092+ ib_bh_cmp_t compare; /*!< comparator */
2093+};
2094+
2095+#ifndef UNIV_NONINL
2096+#include "ut0bh.ic"
2097+#endif
2098+
2099+#endif /* INNOBASE_UT0BH_H */
2100
2101=== added file 'plugin/innobase/include/ut0bh.ic'
2102--- plugin/innobase/include/ut0bh.ic 1970-01-01 00:00:00 +0000
2103+++ plugin/innobase/include/ut0bh.ic 2012-05-22 12:41:18 +0000
2104@@ -0,0 +1,125 @@
2105+/***************************************************************************//**
2106+Copyright (c) 2011, Oracle Corpn. All Rights Reserved.
2107+
2108+This program is free software; you can redistribute it and/or modify it under
2109+the terms of the GNU General Public License as published by the Free Software
2110+Foundation; version 2 of the License.
2111+
2112+This program is distributed in the hope that it will be useful, but WITHOUT
2113+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2114+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
2115+
2116+You should have received a copy of the GNU General Public License along with
2117+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
2118+Place, Suite 330, Boston, MA 02111-1307 USA
2119+
2120+*****************************************************************************/
2121+
2122+/******************************************************************//**
2123+@file include/ut0bh.ic
2124+Binary min-heap implementation.
2125+
2126+Created 2011-01-15 by Sunny Bains
2127+*******************************************************/
2128+
2129+#include "ut0bh.h"
2130+#include "ut0mem.h" /* For ut_memcpy() */
2131+
2132+/**********************************************************************//**
2133+Get the number of elements in the binary heap.
2134+@return number of elements */
2135+UNIV_INLINE
2136+ulint
2137+ib_bh_size(
2138+/*=======*/
2139+ const ib_bh_t* ib_bh) /*!< in: instance */
2140+{
2141+ return(ib_bh->n_elems);
2142+}
2143+
2144+/**********************************************************************//**
2145+Test if binary heap is empty.
2146+@return TRUE if empty. */
2147+UNIV_INLINE
2148+ibool
2149+ib_bh_is_empty(
2150+/*===========*/
2151+ const ib_bh_t* ib_bh) /*!< in: instance */
2152+{
2153+ return(ib_bh_size(ib_bh) == 0);
2154+}
2155+
2156+/**********************************************************************//**
2157+Test if binary heap is full.
2158+@return TRUE if full. */
2159+UNIV_INLINE
2160+ibool
2161+ib_bh_is_full(
2162+/*===========*/
2163+ const ib_bh_t* ib_bh) /*!< in: instance */
2164+{
2165+ return(ib_bh_size(ib_bh) >= ib_bh->max_elems);
2166+}
2167+
2168+/**********************************************************************//**
2169+Get a pointer to the element.
2170+@return pointer to element */
2171+UNIV_INLINE
2172+void*
2173+ib_bh_get(
2174+/*=======*/
2175+ ib_bh_t* ib_bh, /*!< in: instance */
2176+ ulint i) /*!< in: index */
2177+{
2178+ byte* ptr = (byte*) (ib_bh + 1);
2179+
2180+ ut_a(i < ib_bh_size(ib_bh));
2181+
2182+ return(ptr + (ib_bh->sizeof_elem * i));
2183+}
2184+
2185+/**********************************************************************//**
2186+Copy an element to the binary heap.
2187+@return pointer to copied element */
2188+UNIV_INLINE
2189+void*
2190+ib_bh_set(
2191+/*======*/
2192+ ib_bh_t* ib_bh, /*!< in/out: instance */
2193+ ulint i, /*!< in: index */
2194+ const void* elem) /*!< in: element to add */
2195+{
2196+ void* ptr = ib_bh_get(ib_bh, i);
2197+
2198+ ut_memcpy(ptr, elem, ib_bh->sizeof_elem);
2199+
2200+ return(ptr);
2201+}
2202+
2203+/**********************************************************************//**
2204+Return the first element from the binary heap.
2205+@return pointer to first element or NULL if empty. */
2206+UNIV_INLINE
2207+void*
2208+ib_bh_first(
2209+/*========*/
2210+ ib_bh_t* ib_bh) /*!< in: instance */
2211+{
2212+ return(ib_bh_is_empty(ib_bh) ? NULL : ib_bh_get(ib_bh, 0));
2213+}
2214+
2215+/**********************************************************************//**
2216+Return the last element from the binary heap.
2217+@return pointer to last element or NULL if empty. */
2218+UNIV_INLINE
2219+void*
2220+ib_bh_last(
2221+/*========*/
2222+ ib_bh_t* ib_bh) /*!< in/out: instance */
2223+{
2224+ return(ib_bh_is_empty(ib_bh)
2225+ ? NULL
2226+ : ib_bh_get(ib_bh, ib_bh_size(ib_bh) - 1));
2227+}
2228+
2229+
2230
2231=== modified file 'plugin/innobase/include/ut0ut.h'
2232--- plugin/innobase/include/ut0ut.h 2011-07-30 12:19:38 +0000
2233+++ plugin/innobase/include/ut0ut.h 2012-05-22 12:41:18 +0000
2234@@ -56,24 +56,24 @@
2235 typedef time_t ib_time_t;
2236
2237 #ifndef UNIV_HOTBACKUP
2238-#if defined(HAVE_IB_PAUSE_INSTRUCTION)
2239-# ifdef WIN32
2240- /* In the Win32 API, the x86 PAUSE instruction is executed by calling
2241- the YieldProcessor macro defined in WinNT.h. It is a CPU architecture-
2242- independent way by using YieldProcessor.*/
2243-# define UT_RELAX_CPU() YieldProcessor()
2244-# else
2245- /* According to the gcc info page, asm volatile means that the
2246- instruction has important side-effects and must not be removed.
2247- Also asm volatile may trigger a memory barrier (spilling all registers
2248- to memory). */
2249-# define UT_RELAX_CPU() __asm__ __volatile__ ("pause")
2250-# endif
2251+#if defined(HAVE_PAUSE_INSTRUCTION)
2252+ /* According to the gcc info page, asm volatile means that the
2253+ instruction has important side-effects and must not be removed.
2254+ Also asm volatile may trigger a memory barrier (spilling all registers
2255+ to memory). */
2256+# define UT_RELAX_CPU() __asm__ __volatile__ ("pause")
2257+#elif defined(HAVE_FAKE_PAUSE_INSTRUCTION)
2258+# define UT_RELAX_CPU() __asm__ __volatile__ ("rep; nop")
2259 #elif defined(HAVE_ATOMIC_BUILTINS)
2260 # define UT_RELAX_CPU() do { \
2261 volatile lint volatile_var; \
2262 if (os_compare_and_swap_lint(&volatile_var, 0, 1)) ((void)0); \
2263 } while (0)
2264+#elif defined(HAVE_WINDOWS_ATOMICS)
2265+ /* In the Win32 API, the x86 PAUSE instruction is executed by calling
2266+ the YieldProcessor macro defined in WinNT.h. It is a CPU architecture-
2267+ independent way by using YieldProcessor. */
2268+# define UT_RELAX_CPU() YieldProcessor()
2269 #else
2270 # define UT_RELAX_CPU() ((void)0) /* avoid warning for an empty statement */
2271 #endif
2272
2273=== modified file 'plugin/innobase/include/ut0vec.h'
2274--- plugin/innobase/include/ut0vec.h 2011-03-14 05:40:28 +0000
2275+++ plugin/innobase/include/ut0vec.h 2012-05-22 12:41:18 +0000
2276@@ -95,6 +95,25 @@
2277 ulint n); /*!< in: element index to get */
2278
2279 /****************************************************************//**
2280+Get last element. The vector must not be empty.
2281+@return last element */
2282+UNIV_INLINE
2283+void*
2284+ib_vector_get_last(
2285+/*===============*/
2286+ ib_vector_t* vec); /*!< in: vector */
2287+
2288+/****************************************************************//**
2289+Set the n'th element. */
2290+UNIV_INLINE
2291+void
2292+ib_vector_set(
2293+/*==========*/
2294+ ib_vector_t* vec, /*!< in/out: vector */
2295+ ulint n, /*!< in: element index to set */
2296+ void* elem); /*!< in: data element */
2297+
2298+/****************************************************************//**
2299 Remove the last element from the vector. */
2300 UNIV_INLINE
2301 void*
2302
2303=== modified file 'plugin/innobase/include/ut0vec.ic'
2304--- plugin/innobase/include/ut0vec.ic 2010-12-18 04:43:40 +0000
2305+++ plugin/innobase/include/ut0vec.ic 2012-05-22 12:41:18 +0000
2306@@ -51,6 +51,35 @@
2307 }
2308
2309 /****************************************************************//**
2310+Get last element. The vector must not be empty.
2311+@return last element */
2312+UNIV_INLINE
2313+void*
2314+ib_vector_get_last(
2315+/*===============*/
2316+ ib_vector_t* vec) /*!< in: vector */
2317+{
2318+ ut_a(vec->used > 0);
2319+
2320+ return(vec->data[vec->used - 1]);
2321+}
2322+
2323+/****************************************************************//**
2324+Set the n'th element. */
2325+UNIV_INLINE
2326+void
2327+ib_vector_set(
2328+/*==========*/
2329+ ib_vector_t* vec, /*!< in/out: vector */
2330+ ulint n, /*!< in: element index to set */
2331+ void* elem) /*!< in: data element */
2332+{
2333+ ut_a(n < vec->used);
2334+
2335+ vec->data[n] = elem;
2336+}
2337+
2338+/****************************************************************//**
2339 Remove the last element from the vector.
2340 @return last vector element */
2341 UNIV_INLINE
2342
2343=== modified file 'plugin/innobase/lock/lock0lock.cc'
2344--- plugin/innobase/lock/lock0lock.cc 2010-12-26 03:44:24 +0000
2345+++ plugin/innobase/lock/lock0lock.cc 2012-05-22 12:41:18 +0000
2346@@ -3616,6 +3616,80 @@
2347 }
2348
2349 /*************************************************************//**
2350+Pops autoinc lock requests from the transaction's autoinc_locks. We
2351+handle the case where there are gaps in the array and they need to
2352+be popped off the stack. */
2353+UNIV_INLINE
2354+void
2355+lock_table_pop_autoinc_locks(
2356+/*=========================*/
2357+ trx_t* trx) /*!< in/out: transaction that owns the AUTOINC locks */
2358+{
2359+ ut_ad(mutex_own(&kernel_mutex));
2360+ ut_ad(!ib_vector_is_empty(trx->autoinc_locks));
2361+
2362+ /* Skip any gaps, gaps are NULL lock entries in the
2363+ trx->autoinc_locks vector. */
2364+
2365+ do {
2366+ ib_vector_pop(trx->autoinc_locks);
2367+
2368+ if (ib_vector_is_empty(trx->autoinc_locks)) {
2369+ return;
2370+ }
2371+
2372+ } while (ib_vector_get_last(trx->autoinc_locks) == NULL);
2373+}
2374+
2375+/*************************************************************//**
2376+Removes an autoinc lock request from the transaction's autoinc_locks. */
2377+UNIV_INLINE
2378+void
2379+lock_table_remove_autoinc_lock(
2380+/*===========================*/
2381+ lock_t* lock, /*!< in: table lock */
2382+ trx_t* trx) /*!< in/out: transaction that owns the lock */
2383+{
2384+ lock_t* autoinc_lock;
2385+ lint i = ib_vector_size(trx->autoinc_locks) - 1;
2386+
2387+ ut_ad(mutex_own(&kernel_mutex));
2388+ ut_ad(lock_get_mode(lock) == LOCK_AUTO_INC);
2389+ ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
2390+ ut_ad(!ib_vector_is_empty(trx->autoinc_locks));
2391+
2392+ /* With stored functions and procedures the user may drop
2393+ a table within the same "statement". This special case has
2394+ to be handled by deleting only those AUTOINC locks that were
2395+ held by the table being dropped. */
2396+
2397+ autoinc_lock = static_cast<ib_lock_t *>(ib_vector_get(trx->autoinc_locks, i));
2398+
2399+ /* This is the default fast case. */
2400+
2401+ if (autoinc_lock == lock) {
2402+ lock_table_pop_autoinc_locks(trx);
2403+ } else {
2404+ /* The last element should never be NULL */
2405+ ut_a(autoinc_lock != NULL);
2406+
2407+ /* Handle freeing the locks from within the stack. */
2408+
2409+ while (--i >= 0) {
2410+ autoinc_lock = static_cast<ib_lock_t *>(ib_vector_get(trx->autoinc_locks, i));
2411+
2412+ if (UNIV_LIKELY(autoinc_lock == lock)) {
2413+ ib_vector_set(trx->autoinc_locks, i, NULL);
2414+ return;
2415+ }
2416+ }
2417+
2418+ /* Must find the autoinc lock. */
2419+ ut_error;
2420+ }
2421+}
2422+
2423+/*************************************************************//**
2424 Removes a table lock request from the queue and the trx list of locks;
2425 this is a low-level function which does NOT check if waiting requests
2426 can now be granted. */
2427@@ -3654,10 +3728,7 @@
2428
2429 if (!lock_get_wait(lock)
2430 && !ib_vector_is_empty(trx->autoinc_locks)) {
2431- lock_t* autoinc_lock;
2432-
2433- autoinc_lock = static_cast<lock_t *>(ib_vector_pop(trx->autoinc_locks));
2434- ut_a(autoinc_lock == lock);
2435+ lock_table_remove_autoinc_lock(lock, trx);
2436 }
2437
2438 ut_a(table->n_waiting_or_granted_auto_inc_locks > 0);
2439
2440=== modified file 'plugin/innobase/log/log0recv.cc'
2441--- plugin/innobase/log/log0recv.cc 2011-04-07 02:36:30 +0000
2442+++ plugin/innobase/log/log0recv.cc 2012-05-22 12:41:18 +0000
2443@@ -2207,7 +2207,7 @@
2444 "InnoDB: far enough in recovery! Please run CHECK TABLE\n"
2445 "InnoDB: on your InnoDB tables to check that they are ok!\n"
2446 "InnoDB: If mysqld crashes after this recovery, look at\n"
2447- "InnoDB: " REFMAN "forcing-recovery.html\n"
2448+ "InnoDB: " REFMAN "forcing-innodb-recovery.html\n"
2449 "InnoDB: about forcing recovery.\n", stderr);
2450
2451 fflush(stderr);
2452
2453=== modified file 'plugin/innobase/os/os0file.cc'
2454--- plugin/innobase/os/os0file.cc 2011-04-07 05:47:57 +0000
2455+++ plugin/innobase/os/os0file.cc 2012-05-22 12:41:18 +0000
2456@@ -304,6 +304,36 @@
2457 /** Number of pending read operations */
2458 UNIV_INTERN ulint os_n_pending_reads = 0;
2459
2460+#ifdef UNIV_DEBUG
2461+/**********************************************************************//**
2462+Validates the consistency the aio system some of the time.
2463+@return TRUE if ok or the check was skipped */
2464+UNIV_INTERN
2465+ibool
2466+os_aio_validate_skip(void)
2467+/*======================*/
2468+{
2469+/** Try os_aio_validate() every this many times */
2470+# define OS_AIO_VALIDATE_SKIP 13
2471+
2472+ /** The os_aio_validate() call skip counter.
2473+ Use a signed type because of the race condition below. */
2474+ static int os_aio_validate_count = OS_AIO_VALIDATE_SKIP;
2475+
2476+ /* There is a race condition below, but it does not matter,
2477+ because this call is only for heuristic purposes. We want to
2478+ reduce the call frequency of the costly os_aio_validate()
2479+ check in debug builds. */
2480+ if (--os_aio_validate_count > 0) {
2481+ return(TRUE);
2482+ }
2483+
2484+ os_aio_validate_count = OS_AIO_VALIDATE_SKIP;
2485+ return(os_aio_validate());
2486+}
2487+#endif /* UNIV_DEBUG */
2488+
2489+#ifdef __WIN__
2490 /***********************************************************************//**
2491 Gets the operating system version. Currently works only on Windows.
2492 @return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000, OS_WINXP, OS_WINVISTA,
2493@@ -313,7 +343,6 @@
2494 os_get_os_version(void)
2495 /*===================*/
2496 {
2497-#ifdef __WIN__
2498 OSVERSIONINFO os_info;
2499
2500 os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
2501@@ -342,12 +371,8 @@
2502 ut_error;
2503 return(0);
2504 }
2505-#else
2506- ut_error;
2507-
2508- return(0);
2509-#endif
2510 }
2511+#endif /* __WIN__ */
2512
2513 /***********************************************************************//**
2514 Retrieves the last error number if an error occurs in a file io function.
2515@@ -4032,7 +4057,7 @@
2516 ut_ad(n > 0);
2517 ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
2518 ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
2519- ut_ad(os_aio_validate());
2520+ ut_ad(os_aio_validate_skip());
2521 #ifdef WIN_ASYNC_IO
2522 ut_ad((n & 0xFFFFFFFFUL) == n);
2523 #endif
2524@@ -4236,7 +4261,7 @@
2525 /* NOTE! We only access constant fields in os_aio_array. Therefore
2526 we do not have to acquire the protecting mutex yet */
2527
2528- ut_ad(os_aio_validate());
2529+ ut_ad(os_aio_validate_skip());
2530 ut_ad(segment < array->n_segments);
2531
2532 n = array->n_slots / array->n_segments;
2533@@ -4657,7 +4682,7 @@
2534
2535 srv_set_io_thread_op_info(global_segment,
2536 "looking for i/o requests (a)");
2537- ut_ad(os_aio_validate());
2538+ ut_ad(os_aio_validate_skip());
2539 ut_ad(segment < array->n_segments);
2540
2541 n = array->n_slots / array->n_segments;
2542
2543=== modified file 'plugin/innobase/plugin.am'
2544--- plugin/innobase/plugin.am 2011-04-06 16:21:39 +0000
2545+++ plugin/innobase/plugin.am 2012-05-22 12:41:18 +0000
2546@@ -193,6 +193,8 @@
2547 plugin/innobase/include/ut0byte.h \
2548 plugin/innobase/include/ut0byte.ic \
2549 plugin/innobase/include/ut0dbg.h \
2550+ plugin/innobase/include/ut0bh.h \
2551+ plugin/innobase/include/ut0bh.ic \
2552 plugin/innobase/include/ut0lst.h \
2553 plugin/innobase/include/ut0mem.h \
2554 plugin/innobase/include/ut0mem.ic \
2555@@ -319,6 +321,7 @@
2556 plugin/innobase/trx/trx0undo.cc \
2557 plugin/innobase/usr/usr0sess.cc \
2558 plugin/innobase/ut/ut0byte.cc \
2559+ plugin/innobase/ut/ut0bh.cc \
2560 plugin/innobase/ut/ut0dbg.cc \
2561 plugin/innobase/ut/ut0list.cc \
2562 plugin/innobase/ut/ut0mem.cc \
2563
2564=== modified file 'plugin/innobase/row/row0ins.cc'
2565--- plugin/innobase/row/row0ins.cc 2010-12-26 23:42:28 +0000
2566+++ plugin/innobase/row/row0ins.cc 2012-05-22 12:41:18 +0000
2567@@ -1526,7 +1526,7 @@
2568 if (foreign->foreign_index == index) {
2569
2570 if (foreign->referenced_table == NULL) {
2571- dict_table_get(foreign->referenced_table_name,
2572+ dict_table_get(foreign->referenced_table_name_lookup,
2573 FALSE);
2574 }
2575
2576
2577=== modified file 'plugin/innobase/row/row0merge.cc'
2578--- plugin/innobase/row/row0merge.cc 2011-04-05 10:32:12 +0000
2579+++ plugin/innobase/row/row0merge.cc 2012-05-22 12:41:18 +0000
2580@@ -2399,7 +2399,7 @@
2581 {
2582 ulint err = DB_ERROR;
2583 pars_info_t* info;
2584- char old_name[MAX_TABLE_NAME_LEN + 1];
2585+ char old_name[MAX_FULL_NAME_LEN + 1];
2586
2587 ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
2588 ut_ad(old_table != new_table);
2589@@ -2414,7 +2414,7 @@
2590 ut_print_timestamp(stderr);
2591 fprintf(stderr, "InnoDB: too long table name: '%s', "
2592 "max length is %d\n", old_table->name,
2593- MAX_TABLE_NAME_LEN);
2594+ MAX_FULL_NAME_LEN);
2595 ut_error;
2596 }
2597
2598
2599=== modified file 'plugin/innobase/row/row0mysql.cc'
2600--- plugin/innobase/row/row0mysql.cc 2010-12-26 23:42:28 +0000
2601+++ plugin/innobase/row/row0mysql.cc 2012-05-22 12:41:18 +0000
2602@@ -615,7 +615,7 @@
2603 "InnoDB: If the mysqld server crashes"
2604 " after the startup or when\n"
2605 "InnoDB: you dump the tables, look at\n"
2606- "InnoDB: " REFMAN "forcing-recovery.html"
2607+ "InnoDB: " REFMAN "forcing-innodb-recovery.html"
2608 " for help.\n", stderr);
2609 break;
2610 case DB_FOREIGN_EXCEED_MAX_CASCADE:
2611@@ -3150,7 +3150,7 @@
2612
2613 if (foreign && trx->check_foreigns
2614 && !(drop_db && dict_tables_have_same_db(
2615- name, foreign->foreign_table_name))) {
2616+ name, foreign->foreign_table_name_lookup))) {
2617 FILE* ef = dict_foreign_err_file;
2618
2619 /* We only allow dropping a referenced table if
2620
2621=== modified file 'plugin/innobase/row/row0purge.cc'
2622--- plugin/innobase/row/row0purge.cc 2010-12-26 15:48:26 +0000
2623+++ plugin/innobase/row/row0purge.cc 2012-05-22 12:41:18 +0000
2624@@ -525,7 +525,7 @@
2625 while (node->index != NULL) {
2626 index = node->index;
2627
2628- if (row_upd_changes_ord_field_binary(NULL, node->index,
2629+ if (row_upd_changes_ord_field_binary(NULL, NULL, node->index,
2630 node->update)) {
2631 /* Build the older version of the index entry */
2632 entry = row_build_index_entry(node->row, NULL,
2633
2634=== modified file 'plugin/innobase/row/row0umod.cc'
2635--- plugin/innobase/row/row0umod.cc 2010-12-24 00:04:05 +0000
2636+++ plugin/innobase/row/row0umod.cc 2012-05-22 12:41:18 +0000
2637@@ -693,19 +693,18 @@
2638 while (node->index != NULL) {
2639 index = node->index;
2640
2641- if (row_upd_changes_ord_field_binary(node->row, node->index,
2642- node->update)) {
2643+ if (row_upd_changes_ord_field_binary(
2644+ node->row, node->ext, node->index, node->update)) {
2645
2646 /* Build the newest version of the index entry */
2647 entry = row_build_index_entry(node->row, node->ext,
2648 index, heap);
2649 if (UNIV_UNLIKELY(!entry)) {
2650 /* The server must have crashed in
2651- row_upd_clust_rec_by_insert(), in
2652- row_ins_index_entry_low() before
2653- btr_store_big_rec_extern_fields()
2654- has written the externally stored columns
2655- (BLOBs) of the new clustered index entry. */
2656+ row_upd_clust_rec_by_insert() before
2657+ the updated externally stored columns (BLOBs)
2658+ of the new clustered index entry were
2659+ written. */
2660
2661 /* The table must be in DYNAMIC or COMPRESSED
2662 format. REDUNDANT and COMPACT formats
2663
2664=== modified file 'plugin/innobase/row/row0upd.cc'
2665--- plugin/innobase/row/row0upd.cc 2010-12-27 18:39:11 +0000
2666+++ plugin/innobase/row/row0upd.cc 2012-05-22 12:41:18 +0000
2667@@ -248,7 +248,7 @@
2668 foreign->n_fields))) {
2669
2670 if (foreign->foreign_table == NULL) {
2671- dict_table_get(foreign->foreign_table_name,
2672+ dict_table_get(foreign->foreign_table_name_lookup,
2673 FALSE);
2674 }
2675
2676@@ -1208,20 +1208,21 @@
2677 row and the data values in update are not
2678 known when this function is called, e.g., at
2679 compile time */
2680+ const row_ext_t*ext, /*!< NULL, or prefixes of the externally
2681+ stored columns in the old row */
2682 dict_index_t* index, /*!< in: index of the record */
2683 const upd_t* update) /*!< in: update vector for the row; NOTE: the
2684 field numbers in this MUST be clustered index
2685 positions! */
2686 {
2687- ulint n_unique;
2688- ulint n_upd_fields;
2689- ulint i, j;
2690- dict_index_t* clust_index;
2691+ ulint n_unique;
2692+ ulint i;
2693+ const dict_index_t* clust_index;
2694
2695- ut_ad(update && index);
2696+ ut_ad(update);
2697+ ut_ad(index);
2698
2699 n_unique = dict_index_get_n_unique(index);
2700- n_upd_fields = upd_get_n_fields(update);
2701
2702 clust_index = dict_table_get_first_index(index->table);
2703
2704@@ -1229,33 +1230,72 @@
2705
2706 const dict_field_t* ind_field;
2707 const dict_col_t* col;
2708- ulint col_pos;
2709 ulint col_no;
2710+ const upd_field_t* upd_field;
2711+ const dfield_t* dfield;
2712+ dfield_t dfield_ext;
2713+ ulint dfield_len;
2714+ const byte* buf;
2715
2716 ind_field = dict_index_get_nth_field(index, i);
2717 col = dict_field_get_col(ind_field);
2718- col_pos = dict_col_get_clust_pos(col, clust_index);
2719 col_no = dict_col_get_no(col);
2720
2721- for (j = 0; j < n_upd_fields; j++) {
2722-
2723- const upd_field_t* upd_field
2724- = upd_get_nth_field(update, j);
2725-
2726- /* Note that if the index field is a column prefix
2727- then it may be that row does not contain an externally
2728- stored part of the column value, and we cannot compare
2729- the datas */
2730-
2731- if (col_pos == upd_field->field_no
2732- && (row == NULL
2733- || ind_field->prefix_len > 0
2734- || !dfield_datas_are_binary_equal(
2735- dtuple_get_nth_field(row, col_no),
2736- &(upd_field->new_val)))) {
2737-
2738- return(TRUE);
2739+ upd_field = upd_get_field_by_field_no(
2740+ update, dict_col_get_clust_pos(col, clust_index));
2741+
2742+ if (upd_field == NULL) {
2743+ continue;
2744+ }
2745+
2746+ if (row == NULL) {
2747+ ut_ad(ext == NULL);
2748+ return(TRUE);
2749+ }
2750+
2751+ dfield = dtuple_get_nth_field(row, col_no);
2752+
2753+ /* This treatment of column prefix indexes is loosely
2754+ based on row_build_index_entry(). */
2755+
2756+ if (UNIV_LIKELY(ind_field->prefix_len == 0)
2757+ || dfield_is_null(dfield)) {
2758+ /* do nothing special */
2759+ } else if (UNIV_LIKELY_NULL(ext)) {
2760+ /* See if the column is stored externally. */
2761+ buf = row_ext_lookup(ext, col_no, &dfield_len);
2762+
2763+ ut_ad(col->ord_part);
2764+
2765+ if (UNIV_LIKELY_NULL(buf)) {
2766+ if (UNIV_UNLIKELY(buf == field_ref_zero)) {
2767+ /* This should never happen, but
2768+ we try to fail safe here. */
2769+ ut_ad(0);
2770+ return(TRUE);
2771+ }
2772+
2773+ goto copy_dfield;
2774 }
2775+ } else if (dfield_is_ext(dfield)) {
2776+ dfield_len = dfield_get_len(dfield);
2777+ ut_a(dfield_len > BTR_EXTERN_FIELD_REF_SIZE);
2778+ dfield_len -= BTR_EXTERN_FIELD_REF_SIZE;
2779+ ut_a(dict_index_is_clust(index)
2780+ || ind_field->prefix_len <= dfield_len);
2781+ buf = static_cast<const unsigned char*>(dfield_get_data(dfield));
2782+copy_dfield:
2783+ ut_a(dfield_len > 0);
2784+ dfield_copy(&dfield_ext, dfield);
2785+ dfield_set_data(&dfield_ext, buf, dfield_len);
2786+ dfield = &dfield_ext;
2787+ }
2788+
2789+ if (!dfield_datas_are_binary_equal(
2790+ dfield, &upd_field->new_val,
2791+ ind_field->prefix_len)) {
2792+
2793+ return(TRUE);
2794 }
2795 }
2796
2797@@ -1339,7 +1379,7 @@
2798 if (col_pos == upd_field->field_no
2799 && !dfield_datas_are_binary_equal(
2800 dtuple_get_nth_field(entry, i),
2801- &(upd_field->new_val))) {
2802+ &upd_field->new_val, 0)) {
2803
2804 return(TRUE);
2805 }
2806@@ -1606,14 +1646,99 @@
2807 ut_ad(!dict_index_is_clust(node->index));
2808
2809 if (node->state == UPD_NODE_UPDATE_ALL_SEC
2810- || row_upd_changes_ord_field_binary(node->row, node->index,
2811- node->update)) {
2812+ || row_upd_changes_ord_field_binary(node->row, node->ext,
2813+ node->index, node->update)) {
2814 return(row_upd_sec_index_entry(node, thr));
2815 }
2816
2817 return(DB_SUCCESS);
2818 }
2819
2820+#ifdef UNIV_DEBUG
2821+# define row_upd_clust_rec_by_insert_inherit(rec,offsets,entry,update) \
2822+ row_upd_clust_rec_by_insert_inherit_func(rec,offsets,entry,update)
2823+#else /* UNIV_DEBUG */
2824+# define row_upd_clust_rec_by_insert_inherit(rec,offsets,entry,update) \
2825+ row_upd_clust_rec_by_insert_inherit_func(entry,update)
2826+#endif /* UNIV_DEBUG */
2827+/*******************************************************************//**
2828+Mark non-updated off-page columns inherited when the primary key is
2829+updated. We must mark them as inherited in entry, so that they are not
2830+freed in a rollback. A limited version of this function used to be
2831+called btr_cur_mark_dtuple_inherited_extern().
2832+@return TRUE if any columns were inherited */
2833+static __attribute__((warn_unused_result))
2834+ibool
2835+row_upd_clust_rec_by_insert_inherit_func(
2836+/*=====================================*/
2837+#ifdef UNIV_DEBUG
2838+ const rec_t* rec, /*!< in: old record, or NULL */
2839+ const ulint* offsets,/*!< in: rec_get_offsets(rec), or NULL */
2840+#endif /* UNIV_DEBUG */
2841+ dtuple_t* entry, /*!< in/out: updated entry to be
2842+ inserted into the clustered index */
2843+ const upd_t* update) /*!< in: update vector */
2844+{
2845+ ibool inherit = FALSE;
2846+ ulint i;
2847+
2848+ ut_ad(!rec == !offsets);
2849+ ut_ad(!rec || rec_offs_any_extern(offsets));
2850+
2851+ for (i = 0; i < dtuple_get_n_fields(entry); i++) {
2852+ dfield_t* dfield = dtuple_get_nth_field(entry, i);
2853+ byte* data;
2854+ ulint len;
2855+
2856+ ut_ad(!offsets
2857+ || !rec_offs_nth_extern(offsets, i)
2858+ == !dfield_is_ext(dfield)
2859+ || upd_get_field_by_field_no(update, i));
2860+ if (!dfield_is_ext(dfield)
2861+ || upd_get_field_by_field_no(update, i)) {
2862+ continue;
2863+ }
2864+
2865+#ifdef UNIV_DEBUG
2866+ if (UNIV_LIKELY(rec != NULL)) {
2867+ const byte* rec_data
2868+ = rec_get_nth_field(rec, offsets, i, &len);
2869+ ut_ad(len == dfield_get_len(dfield));
2870+ ut_ad(len != UNIV_SQL_NULL);
2871+ ut_ad(len >= BTR_EXTERN_FIELD_REF_SIZE);
2872+
2873+ rec_data += len - BTR_EXTERN_FIELD_REF_SIZE;
2874+
2875+ /* The pointer must not be zero. */
2876+ ut_ad(memcmp(rec_data, field_ref_zero,
2877+ BTR_EXTERN_FIELD_REF_SIZE));
2878+ /* The BLOB must be owned. */
2879+ ut_ad(!(rec_data[BTR_EXTERN_LEN]
2880+ & BTR_EXTERN_OWNER_FLAG));
2881+ }
2882+#endif /* UNIV_DEBUG */
2883+
2884+ len = dfield_get_len(dfield);
2885+ ut_a(len != UNIV_SQL_NULL);
2886+ ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
2887+ data = static_cast<unsigned char*>(dfield_get_data(dfield));
2888+ data += len - BTR_EXTERN_FIELD_REF_SIZE;
2889+ /* The pointer must not be zero. */
2890+ ut_a(memcmp(data, field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE));
2891+ /* The BLOB must be owned. */
2892+ ut_a(!(data[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
2893+
2894+ data[BTR_EXTERN_LEN] |= BTR_EXTERN_INHERITED_FLAG;
2895+ /* The BTR_EXTERN_INHERITED_FLAG only matters in
2896+ rollback. Purge will always free the extern fields of
2897+ a delete-marked row. */
2898+
2899+ inherit = TRUE;
2900+ }
2901+
2902+ return(inherit);
2903+}
2904+
2905 /***********************************************************//**
2906 Marks the clustered index record deleted and inserts the updated version
2907 of the record to the index. This function should be used when the ordering
2908@@ -1632,14 +1757,16 @@
2909 a foreign key constraint */
2910 mtr_t* mtr) /*!< in/out: mtr; gets committed here */
2911 {
2912- mem_heap_t* heap = NULL;
2913+ mem_heap_t* heap;
2914 btr_pcur_t* pcur;
2915 btr_cur_t* btr_cur;
2916 trx_t* trx;
2917 dict_table_t* table;
2918 dtuple_t* entry;
2919 ulint err;
2920- ibool change_ownership = FALSE;
2921+ ibool change_ownership = FALSE;
2922+ rec_t* rec;
2923+ ulint* offsets = NULL;
2924
2925 ut_ad(node);
2926 ut_ad(dict_index_is_clust(index));
2927@@ -1649,82 +1776,115 @@
2928 pcur = node->pcur;
2929 btr_cur = btr_pcur_get_btr_cur(pcur);
2930
2931- if (node->state != UPD_NODE_INSERT_CLUSTERED) {
2932- rec_t* rec;
2933- dict_index_t* node_index;
2934- ulint offsets_[REC_OFFS_NORMAL_SIZE];
2935- ulint* offsets;
2936- rec_offs_init(offsets_);
2937-
2938- err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
2939- btr_cur, TRUE, thr, mtr);
2940+ heap = mem_heap_create(1000);
2941+
2942+
2943+ entry = row_build_index_entry(node->upd_row, node->upd_ext,
2944+ index, heap);
2945+ ut_a(entry);
2946+
2947+ row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
2948+
2949+ switch (node->state) {
2950+ default:
2951+ ut_error;
2952+ case UPD_NODE_INSERT_BLOB:
2953+ /* A lock wait occurred in row_ins_index_entry() in
2954+ the previous invocation of this function. Mark the
2955+ off-page columns in the entry inherited. */
2956+
2957+ change_ownership = row_upd_clust_rec_by_insert_inherit(
2958+ NULL, NULL, entry, node->update);
2959+ ut_a(change_ownership);
2960+ /* fall through */
2961+ case UPD_NODE_INSERT_CLUSTERED:
2962+ /* A lock wait occurred in row_ins_index_entry() in
2963+ the previous invocation of this function. */
2964+ break;
2965+ case UPD_NODE_UPDATE_CLUSTERED:
2966+ /* This is the first invocation of the function where
2967+ we update the primary key. Delete-mark the old record
2968+ in the clustered index and prepare to insert a new entry. */
2969+ rec = btr_cur_get_rec(btr_cur);
2970+ offsets = rec_get_offsets(rec, index, NULL,
2971+ ULINT_UNDEFINED, &heap);
2972+ ut_ad(page_rec_is_user_rec(rec));
2973+
2974+ err = btr_cur_del_mark_set_clust_rec(
2975+ BTR_NO_LOCKING_FLAG, btr_cur_get_block(btr_cur),
2976+ rec, index, offsets, TRUE, thr, mtr);
2977 if (err != DB_SUCCESS) {
2978+ err_exit:
2979 mtr_commit(mtr);
2980+ mem_heap_free(heap);
2981 return(err);
2982 }
2983
2984- /* Mark as not-owned the externally stored fields which the new
2985- row inherits from the delete marked record: purge should not
2986- free those externally stored fields even if the delete marked
2987- record is removed from the index tree, or updated. */
2988-
2989- rec = btr_cur_get_rec(btr_cur);
2990- node_index = dict_table_get_first_index(table);
2991- offsets = rec_get_offsets(rec, node_index, offsets_,
2992- ULINT_UNDEFINED, &heap);
2993- change_ownership = btr_cur_mark_extern_inherited_fields(
2994- btr_cur_get_page_zip(btr_cur), rec, node_index, offsets,
2995- node->update, mtr);
2996+ /* If the the new row inherits externally stored
2997+ fields (off-page columns a.k.a. BLOBs) from the
2998+ delete-marked old record, mark them disowned by the
2999+ old record and owned by the new entry. */
3000+
3001+ if (rec_offs_any_extern(offsets)) {
3002+ change_ownership = row_upd_clust_rec_by_insert_inherit(
3003+ rec, offsets, entry, node->update);
3004+
3005+ if (change_ownership) {
3006+ btr_pcur_store_position(pcur, mtr);
3007+ }
3008+ }
3009+
3010 if (referenced) {
3011 /* NOTE that the following call loses
3012 the position of pcur ! */
3013
3014 err = row_upd_check_references_constraints(
3015- node, pcur, table, node_index, offsets, thr, mtr);
3016+ node, pcur, table, index, offsets, thr, mtr);
3017
3018 if (err != DB_SUCCESS) {
3019-
3020- mtr_commit(mtr);
3021-
3022- if (UNIV_LIKELY_NULL(heap)) {
3023- mem_heap_free(heap);
3024- }
3025-
3026- return(err);
3027+ goto err_exit;
3028 }
3029 }
3030 }
3031
3032 mtr_commit(mtr);
3033
3034- if (!heap) {
3035- heap = mem_heap_create(500);
3036- }
3037- node->state = UPD_NODE_INSERT_CLUSTERED;
3038-
3039- entry = row_build_index_entry(node->upd_row, node->upd_ext,
3040- index, heap);
3041- ut_a(entry);
3042-
3043- row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
3044-
3045- if (change_ownership) {
3046- /* If we return from a lock wait, for example, we may have
3047- extern fields marked as not-owned in entry (marked in the
3048- if-branch above). We must unmark them, take the ownership
3049- back. */
3050-
3051- btr_cur_unmark_dtuple_extern_fields(entry);
3052-
3053- /* We must mark non-updated extern fields in entry as
3054- inherited, so that a possible rollback will not free them. */
3055-
3056- btr_cur_mark_dtuple_inherited_extern(entry, node->update);
3057- }
3058-
3059 err = row_ins_index_entry(index, entry,
3060 node->upd_ext ? node->upd_ext->n_ext : 0,
3061 TRUE, thr);
3062+ node->state = change_ownership
3063+ ? UPD_NODE_INSERT_BLOB
3064+ : UPD_NODE_INSERT_CLUSTERED;
3065+
3066+ if (err == DB_SUCCESS && change_ownership) {
3067+ /* Mark the non-updated fields disowned by the old record. */
3068+
3069+ /* NOTE: this transaction has an x-lock on the record
3070+ and therefore other transactions cannot modify the
3071+ record when we have no latch on the page. In addition,
3072+ we assume that other query threads of the same
3073+ transaction do not modify the record in the meantime.
3074+ Therefore we can assert that the restoration of the
3075+ cursor succeeds. */
3076+
3077+ mtr_start(mtr);
3078+
3079+ if (!btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr)) {
3080+ ut_error;
3081+ }
3082+
3083+ rec = btr_cur_get_rec(btr_cur);
3084+ offsets = rec_get_offsets(rec, index, offsets,
3085+ ULINT_UNDEFINED, &heap);
3086+ ut_ad(page_rec_is_user_rec(rec));
3087+
3088+ btr_cur_disown_inherited_fields(
3089+ btr_cur_get_page_zip(btr_cur),
3090+ rec, index, offsets, node->update, mtr);
3091+
3092+ mtr_commit(mtr);
3093+ }
3094+
3095 mem_heap_free(heap);
3096
3097 return(err);
3098@@ -1869,8 +2029,9 @@
3099 /* Mark the clustered index record deleted; we do not have to check
3100 locks, because we assume that we have an x-lock on the record */
3101
3102- err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
3103- btr_cur, TRUE, thr, mtr);
3104+ err = btr_cur_del_mark_set_clust_rec(
3105+ BTR_NO_LOCKING_FLAG, btr_cur_get_block(btr_cur),
3106+ btr_cur_get_rec(btr_cur), index, offsets, TRUE, thr, mtr);
3107 if (err == DB_SUCCESS && referenced) {
3108 /* NOTE that the following call loses the position of pcur ! */
3109
3110@@ -2015,7 +2176,8 @@
3111
3112 row_upd_store_row(node);
3113
3114- if (row_upd_changes_ord_field_binary(node->row, index, node->update)) {
3115+ if (row_upd_changes_ord_field_binary(node->row, node->ext, index,
3116+ node->update)) {
3117
3118 /* Update causes an ordering field (ordering fields within
3119 the B-tree) of the clustered index record to change: perform
3120@@ -2085,7 +2247,8 @@
3121 }
3122
3123 if (node->state == UPD_NODE_UPDATE_CLUSTERED
3124- || node->state == UPD_NODE_INSERT_CLUSTERED) {
3125+ || node->state == UPD_NODE_INSERT_CLUSTERED
3126+ || node->state == UPD_NODE_INSERT_BLOB) {
3127
3128 log_free_check();
3129 err = row_upd_clust_step(node, thr);
3130
3131=== modified file 'plugin/innobase/srv/srv0srv.cc'
3132--- plugin/innobase/srv/srv0srv.cc 2011-07-30 09:20:56 +0000
3133+++ plugin/innobase/srv/srv0srv.cc 2012-05-22 12:41:18 +0000
3134@@ -88,9 +88,11 @@
3135 #include "trx0i_s.h"
3136 #include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */
3137
3138-/* This is set to TRUE if the MySQL user has set it in MySQL; currently
3139-affects only FOREIGN KEY definition parsing */
3140-UNIV_INTERN ibool srv_lower_case_table_names = FALSE;
3141+/* This is set to the MySQL server value for this variable. It is only
3142+needed for FOREIGN KEY definition parsing since FOREIGN KEY names are not
3143+stored in the server metadata. The server stores and enforces it for
3144+regular database and table names.*/
3145+UNIV_INTERN uint srv_lower_case_table_names = 0;
3146
3147 /* The following counter is incremented whenever there is some user activity
3148 in the server */
3149@@ -894,6 +896,7 @@
3150
3151 ut_a(type > 0);
3152 ut_a(type <= SRV_MASTER);
3153+ ut_ad(mutex_own(&kernel_mutex));
3154
3155 i = 0;
3156 slot = srv_table_get_nth_slot(i);
3157@@ -1045,6 +1048,37 @@
3158 }
3159
3160 /*********************************************************************//**
3161+Check whether thread type has reserved a slot. Return the first slot that
3162+is found. This works because we currently have only 1 thread of each type.
3163+@return slot number or ULINT_UNDEFINED if not found*/
3164+UNIV_INTERN
3165+ulint
3166+srv_thread_has_reserved_slot(
3167+/*=========================*/
3168+ enum srv_thread_type type) /*!< in: thread type to check */
3169+{
3170+ ulint i;
3171+ ulint slot_no = ULINT_UNDEFINED;
3172+
3173+ mutex_enter(&kernel_mutex);
3174+
3175+ for (i = 0; i < OS_THREAD_MAX_N; i++) {
3176+ srv_slot_t* slot;
3177+
3178+ slot = srv_table_get_nth_slot(i);
3179+
3180+ if (slot->in_use && slot->type == type) {
3181+ slot_no = i;
3182+ break;
3183+ }
3184+ }
3185+
3186+ mutex_exit(&kernel_mutex);
3187+
3188+ return(slot_no);
3189+}
3190+
3191+/*********************************************************************//**
3192 Initializes the server. */
3193 UNIV_INTERN
3194 void
3195@@ -2753,10 +2787,10 @@
3196 srv_main_thread_process_no = os_proc_get_number();
3197 srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
3198
3199+ mutex_enter(&kernel_mutex);
3200+
3201 srv_table_reserve_slot(SRV_MASTER);
3202
3203- mutex_enter(&kernel_mutex);
3204-
3205 srv_n_threads_active[SRV_MASTER]++;
3206
3207 mutex_exit(&kernel_mutex);
3208
3209=== modified file 'plugin/innobase/srv/srv0start.cc'
3210--- plugin/innobase/srv/srv0start.cc 2011-07-30 09:20:56 +0000
3211+++ plugin/innobase/srv/srv0start.cc 2012-05-22 12:41:18 +0000
3212@@ -1292,7 +1292,7 @@
3213 drizzled::errmsg_printf(drizzled::error::INFO, "InnoDB: Completed initialization of buffer pool");
3214
3215 if (err != DB_SUCCESS) {
3216- drizzled::errmsg_printf(drizzled::error::ERROR, "InnoDB: Fatal error: cannot allocate the memory for the buffer pool");
3217+ drizzled::errmsg_printf(drizzled::error::ERROR, "InnoDB: Fatal error: cannot allocate memory for the buffer pool");
3218
3219 return(DB_ERROR);
3220 }
3221@@ -1697,6 +1697,24 @@
3222 os_thread_create(&srv_purge_thread, NULL, NULL);
3223 }
3224
3225+ /* Wait for the purge and master thread to startup. */
3226+
3227+ while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
3228+ if (srv_thread_has_reserved_slot(SRV_MASTER) == ULINT_UNDEFINED
3229+ || (srv_n_purge_threads == 1
3230+ && srv_thread_has_reserved_slot(SRV_WORKER)
3231+ == ULINT_UNDEFINED)) {
3232+
3233+ ut_print_timestamp(stderr);
3234+ fprintf(stderr, " InnoDB: "
3235+ "Waiting for the background threads to "
3236+ "start\n");
3237+ os_thread_sleep(1000000);
3238+ } else {
3239+ break;
3240+ }
3241+ }
3242+
3243 #ifdef UNIV_DEBUG
3244 /* buf_debug_prints = TRUE; */
3245 #endif /* UNIV_DEBUG */
3246
3247=== modified file 'plugin/innobase/sync/sync0arr.cc'
3248--- plugin/innobase/sync/sync0arr.cc 2010-12-26 00:22:34 +0000
3249+++ plugin/innobase/sync/sync0arr.cc 2012-05-22 12:41:18 +0000
3250@@ -590,9 +590,6 @@
3251 ulint depth) /*!< in: recursion depth */
3252 {
3253 sync_cell_t* new;
3254- ibool ret;
3255-
3256- depth++;
3257
3258 if (pass != 0) {
3259 /* If pass != 0, then we do not know which threads are
3260@@ -604,7 +601,7 @@
3261
3262 new = sync_array_find_thread(arr, thread);
3263
3264- if (new == start) {
3265+ if (UNIV_UNLIKELY(new == start)) {
3266 /* Stop running of other threads */
3267
3268 ut_dbg_stop_threads = TRUE;
3269@@ -616,11 +613,7 @@
3270 return(TRUE);
3271
3272 } else if (new) {
3273- ret = sync_array_detect_deadlock(arr, start, new, depth);
3274-
3275- if (ret) {
3276- return(TRUE);
3277- }
3278+ return(sync_array_detect_deadlock(arr, start, new, depth + 1));
3279 }
3280 return(FALSE);
3281 }
3282@@ -930,12 +923,25 @@
3283 ulint fatal_timeout = srv_fatal_semaphore_wait_threshold;
3284 ibool fatal = FALSE;
3285
3286+#ifdef UNIV_DEBUG_VALGRIND
3287+ /* Increase the timeouts if running under valgrind because it executes
3288+ extremely slowly. UNIV_DEBUG_VALGRIND does not necessary mean that
3289+ we are running under valgrind but we have no better way to tell.
3290+ See Bug#58432 innodb.innodb_bug56143 fails under valgrind
3291+ for an example */
3292+# define SYNC_ARRAY_TIMEOUT 2400
3293+ fatal_timeout *= 10;
3294+#else
3295+# define SYNC_ARRAY_TIMEOUT 240
3296+#endif
3297+
3298 for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
3299
3300 cell = sync_array_get_nth_cell(sync_primary_wait_array, i);
3301
3302 if (cell->wait_object != NULL && cell->waiting
3303- && difftime(time(NULL), cell->reservation_time) > 240) {
3304+ && difftime(time(NULL), cell->reservation_time)
3305+ > SYNC_ARRAY_TIMEOUT) {
3306 fputs("InnoDB: Warning: a long semaphore wait:\n",
3307 stderr);
3308 sync_array_cell_print(stderr, cell);
3309@@ -977,6 +983,8 @@
3310 " to the standard error stream\n");
3311 }
3312
3313+#undef SYNC_ARRAY_TIMEOUT
3314+
3315 return(fatal);
3316 }
3317
3318
3319=== modified file 'plugin/innobase/trx/trx0i_s.cc'
3320--- plugin/innobase/trx/trx0i_s.cc 2011-02-17 00:14:13 +0000
3321+++ plugin/innobase/trx/trx0i_s.cc 2012-05-22 12:41:18 +0000
3322@@ -447,7 +447,7 @@
3323 /* record lock */
3324 ut_ad(!strcmp("RECORD", row->lock_type));
3325 ut_ad(row->lock_index != NULL);
3326- ut_ad(row->lock_data != NULL);
3327+ /* row->lock_data == NULL if buf_page_try_get() == NULL */
3328 ut_ad(row->lock_page != ULINT_UNDEFINED);
3329 ut_ad(row->lock_rec != ULINT_UNDEFINED);
3330 }
3331@@ -513,7 +513,6 @@
3332 stmt= trx->mysql_thd->getQueryStringCopy(stmt_len);
3333
3334 if (stmt != NULL) {
3335-
3336 char query[TRX_I_S_TRX_QUERY_MAX_LEN + 1];
3337
3338 if (stmt_len > TRX_I_S_TRX_QUERY_MAX_LEN) {
3339
3340=== added file 'plugin/innobase/ut/ut0bh.cc'
3341--- plugin/innobase/ut/ut0bh.cc 1970-01-01 00:00:00 +0000
3342+++ plugin/innobase/ut/ut0bh.cc 2012-05-22 12:41:18 +0000
3343@@ -0,0 +1,164 @@
3344+/***************************************************************************//**
3345+Copyright (c) 2010, 2011, Oracle Corpn. All Rights Reserved.
3346+
3347+Portions of this file contain modifications contributed and copyrighted by
3348+Sun Microsystems, Inc. Those modifications are gratefully acknowledged and
3349+are described briefly in the InnoDB documentation. The contributions by
3350+Sun Microsystems are incorporated with their permission, and subject to the
3351+conditions contained in the file COPYING.Sun_Microsystems.
3352+
3353+This program is free software; you can redistribute it and/or modify it under
3354+the terms of the GNU General Public License as published by the Free Software
3355+Foundation; version 2 of the License.
3356+
3357+This program is distributed in the hope that it will be useful, but WITHOUT
3358+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
3359+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
3360+
3361+You should have received a copy of the GNU General Public License along with
3362+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
3363+Place, Suite 330, Boston, MA 02111-1307 USA
3364+
3365+*****************************************************************************/
3366+
3367+/******************************************************************//**
3368+@file ut/ut0bh.c
3369+Binary min-heap implementation.
3370+
3371+Created 2010-05-28 by Sunny Bains
3372+*******************************************************/
3373+
3374+#include "ut0bh.h"
3375+#include "ut0mem.h"
3376+
3377+#ifdef UNIV_NONINL
3378+#include "ut0bh.ic"
3379+#endif
3380+
3381+#include <string.h>
3382+
3383+/**********************************************************************//**
3384+Create a binary heap.
3385+@return a new binary heap */
3386+UNIV_INTERN
3387+ib_bh_t*
3388+ib_bh_create(
3389+/*=========*/
3390+ ib_bh_cmp_t compare, /*!< in: comparator */
3391+ ulint sizeof_elem, /*!< in: size of one element */
3392+ ulint max_elems) /*!< in: max elements allowed */
3393+{
3394+ ulint sz;
3395+ ib_bh_t* ib_bh;
3396+
3397+ sz = sizeof(*ib_bh) + (sizeof_elem * max_elems);
3398+
3399+ ib_bh = (ib_bh_t*) ut_malloc(sz);
3400+ memset(ib_bh, 0x0, sz);
3401+
3402+ ib_bh->compare = compare;
3403+ ib_bh->max_elems = max_elems;
3404+ ib_bh->sizeof_elem = sizeof_elem;
3405+
3406+ return(ib_bh);
3407+}
3408+
3409+/**********************************************************************//**
3410+Free a binary heap.
3411+@return a new binary heap */
3412+UNIV_INTERN
3413+void
3414+ib_bh_free(
3415+/*=======*/
3416+ ib_bh_t* ib_bh) /*!< in/own: instance */
3417+{
3418+ ut_free(ib_bh);
3419+}
3420+
3421+/**********************************************************************//**
3422+Add an element to the binary heap. Note: The element is copied.
3423+@return pointer to added element or NULL if full. */
3424+UNIV_INTERN
3425+void*
3426+ib_bh_push(
3427+/*=======*/
3428+ ib_bh_t* ib_bh, /*!< in/out: instance */
3429+ const void* elem) /*!< in: element to add */
3430+{
3431+ void* ptr;
3432+
3433+ if (ib_bh_is_full(ib_bh)) {
3434+ return(NULL);
3435+ } else if (ib_bh_is_empty(ib_bh)) {
3436+ ++ib_bh->n_elems;
3437+ return(ib_bh_set(ib_bh, 0, elem));
3438+ } else {
3439+ ulint i;
3440+
3441+ i = ib_bh->n_elems;
3442+
3443+ ++ib_bh->n_elems;
3444+
3445+ for (ptr = ib_bh_get(ib_bh, i >> 1);
3446+ i > 0 && ib_bh->compare(ptr, elem) > 0;
3447+ i >>= 1, ptr = ib_bh_get(ib_bh, i >> 1)) {
3448+
3449+ ib_bh_set(ib_bh, i, ptr);
3450+ }
3451+
3452+ ptr = ib_bh_set(ib_bh, i, elem);
3453+ }
3454+
3455+ return(ptr);
3456+}
3457+
3458+/**********************************************************************//**
3459+Remove the first element from the binary heap. */
3460+UNIV_INTERN
3461+void
3462+ib_bh_pop(
3463+/*======*/
3464+ ib_bh_t* ib_bh) /*!< in/out: instance */
3465+{
3466+ byte* ptr;
3467+ byte* last;
3468+ ulint parent = 0;
3469+
3470+ if (ib_bh_is_empty(ib_bh)) {
3471+ return;
3472+ } else if (ib_bh_size(ib_bh) == 1) {
3473+ --ib_bh->n_elems;
3474+ return;
3475+ }
3476+
3477+ last = (byte*) ib_bh_last(ib_bh);
3478+
3479+ /* Start from the child node */
3480+ ptr = (byte*) ib_bh_get(ib_bh, 1);
3481+
3482+ while (ptr < last) {
3483+ /* If the "right" child node is < "left" child node */
3484+ if (ib_bh->compare(ptr + ib_bh->sizeof_elem, ptr) < 0) {
3485+ ptr += ib_bh->sizeof_elem;
3486+ }
3487+
3488+ if (ib_bh->compare(last, ptr) <= 0) {
3489+ break;
3490+ }
3491+
3492+ ib_bh_set(ib_bh, parent, ptr);
3493+
3494+ parent = (ptr - (byte*) ib_bh_first(ib_bh))
3495+ / ib_bh->sizeof_elem;
3496+
3497+ if ((parent << 1) >= ib_bh_size(ib_bh)) {
3498+ break;
3499+ }
3500+
3501+ ptr = (byte*) ib_bh_get(ib_bh, parent << 1);
3502+ }
3503+
3504+ --ib_bh->n_elems;
3505+
3506+ ib_bh_set(ib_bh, parent, last);
3507+}
3508
3509=== modified file 'plugin/innobase/ut/ut0dbg.cc'
3510--- plugin/innobase/ut/ut0dbg.cc 2010-12-24 02:12:29 +0000
3511+++ plugin/innobase/ut/ut0dbg.cc 2012-05-22 12:41:18 +0000
3512@@ -77,7 +77,7 @@
3513 " or crashes, even\n"
3514 "InnoDB: immediately after the mysqld startup, there may be\n"
3515 "InnoDB: corruption in the InnoDB tablespace. Please refer to\n"
3516- "InnoDB: " REFMAN "forcing-recovery.html\n"
3517+ "InnoDB: " REFMAN "forcing-innodb-recovery.html\n"
3518 "InnoDB: about forcing recovery.\n", stderr);
3519 #if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT)
3520 ut_dbg_stop_threads = TRUE;

Subscribers

People subscribed via source and target branches

to all changes: