+++ /dev/null
---- a/include/my_sys.h
-+++ b/include/my_sys.h
-@@ -320,8 +320,8 @@
- typedef struct st_dynamic_array
- {
- uchar *buffer;
-- uint elements,max_element;
-- uint alloc_increment;
-+ ulong elements, max_element;
-+ ulong alloc_increment;
- uint size_of_element;
- } DYNAMIC_ARRAY;
-
-@@ -758,21 +758,21 @@
- #define my_init_dynamic_array2(A,B,C,D,E) init_dynamic_array2(A,B,C,D,E)
- #define my_init_dynamic_array2_ci(A,B,C,D,E) init_dynamic_array2(A,B,C,D,E)
- extern my_bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint element_size,
-- void *init_buffer, uint init_alloc,
-- uint alloc_increment);
-+ void *init_buffer, ulong init_alloc,
-+ ulong alloc_increment);
- /* init_dynamic_array() function is deprecated */
- extern my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size,
-- uint init_alloc, uint alloc_increment);
-+ ulong init_alloc, ulong alloc_increment);
- extern my_bool insert_dynamic(DYNAMIC_ARRAY *array,uchar * element);
- extern uchar *alloc_dynamic(DYNAMIC_ARRAY *array);
- extern uchar *pop_dynamic(DYNAMIC_ARRAY*);
--extern my_bool set_dynamic(DYNAMIC_ARRAY *array,uchar * element,uint array_index);
--extern my_bool allocate_dynamic(DYNAMIC_ARRAY *array, uint max_elements);
--extern void get_dynamic(DYNAMIC_ARRAY *array,uchar * element,uint array_index);
-+extern my_bool set_dynamic(DYNAMIC_ARRAY *array, uchar * element, ulong array_index);
-+extern my_bool allocate_dynamic(DYNAMIC_ARRAY *array, ulong max_elements);
-+extern void get_dynamic(DYNAMIC_ARRAY *array, uchar * element, ulong array_index);
- extern void delete_dynamic(DYNAMIC_ARRAY *array);
--extern void delete_dynamic_element(DYNAMIC_ARRAY *array, uint array_index);
-+extern void delete_dynamic_element(DYNAMIC_ARRAY *array, ulong array_index);
- extern void freeze_size(DYNAMIC_ARRAY *array);
--extern int get_index_dynamic(DYNAMIC_ARRAY *array, uchar * element);
-+extern long get_index_dynamic(DYNAMIC_ARRAY *array, uchar * element);
- #define dynamic_array_ptr(array,array_index) ((array)->buffer+(array_index)*(array)->size_of_element)
- #define dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index))
- #define push_dynamic(A,B) insert_dynamic((A),(B))
---- a/mysys/array.c
-+++ b/mysys/array.c
-@@ -41,8 +41,8 @@
- */
-
- my_bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint element_size,
-- void *init_buffer, uint init_alloc,
-- uint alloc_increment)
-+ void *init_buffer, ulong init_alloc,
-+ ulong alloc_increment)
- {
- DBUG_ENTER("init_dynamic_array");
- if (!alloc_increment)
-@@ -73,7 +73,7 @@
- }
-
- my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size,
-- uint init_alloc, uint alloc_increment)
-+ ulong init_alloc, ulong alloc_increment)
- {
- /* placeholder to preserve ABI */
- return my_init_dynamic_array_ci(array, element_size, init_alloc,
-@@ -196,7 +196,7 @@
- FALSE Ok
- */
-
--my_bool set_dynamic(DYNAMIC_ARRAY *array, uchar* element, uint idx)
-+my_bool set_dynamic(DYNAMIC_ARRAY *array, uchar* element, ulong idx)
- {
- if (idx >= array->elements)
- {
-@@ -228,11 +228,11 @@
- TRUE Allocation of new memory failed
- */
-
--my_bool allocate_dynamic(DYNAMIC_ARRAY *array, uint max_elements)
-+my_bool allocate_dynamic(DYNAMIC_ARRAY *array, ulong max_elements)
- {
- if (max_elements >= array->max_element)
- {
-- uint size;
-+ ulong size;
- uchar *new_ptr;
- size= (max_elements + array->alloc_increment)/array->alloc_increment;
- size*= array->alloc_increment;
-@@ -273,11 +273,11 @@
- idx Index of element wanted.
- */
-
--void get_dynamic(DYNAMIC_ARRAY *array, uchar* element, uint idx)
-+void get_dynamic(DYNAMIC_ARRAY *array, uchar* element, ulong idx)
- {
- if (idx >= array->elements)
- {
-- DBUG_PRINT("warning",("To big array idx: %d, array size is %d",
-+ DBUG_PRINT("warning",("To big array idx: %lu, array size is %lu",
- idx,array->elements));
- bzero(element,array->size_of_element);
- return;
-@@ -320,7 +320,7 @@
- idx Index of element to be deleted
- */
-
--void delete_dynamic_element(DYNAMIC_ARRAY *array, uint idx)
-+void delete_dynamic_element(DYNAMIC_ARRAY *array, ulong idx)
- {
- char *ptr= (char*) array->buffer+array->size_of_element*idx;
- array->elements--;
-@@ -340,7 +340,7 @@
-
- void freeze_size(DYNAMIC_ARRAY *array)
- {
-- uint elements=max(array->elements,1);
-+ ulong elements= max(array->elements, 1);
-
- /*
- Do nothing if we are using a static buffer
-@@ -368,7 +368,7 @@
-
- */
-
--int get_index_dynamic(DYNAMIC_ARRAY *array, uchar* element)
-+long get_index_dynamic(DYNAMIC_ARRAY *array, uchar* element)
- {
- size_t ret;
- if (array->buffer > element)
---- a/storage/myisam/mi_check.c
-+++ b/storage/myisam/mi_check.c
-@@ -2429,7 +2429,7 @@
-
- if (_create_index_by_sort(&sort_param,
- (my_bool) (!(param->testflag & T_VERBOSE)),
-- (uint) param->sort_buffer_length))
-+ param->sort_buffer_length))
- {
- param->retry_repair=1;
- goto err;
---- a/storage/myisam/sort.c
-+++ b/storage/myisam/sort.c
-@@ -45,42 +45,42 @@
-
- /* Functions defined in this file */
-
--static ha_rows find_all_keys(MI_SORT_PARAM *info,uint keys,
-+static ha_rows find_all_keys(MI_SORT_PARAM *info, ulong keys,
- uchar **sort_keys,
-- DYNAMIC_ARRAY *buffpek,int *maxbuffer,
-+ DYNAMIC_ARRAY *buffpek, long *maxbuffer,
- IO_CACHE *tempfile,
- IO_CACHE *tempfile_for_exceptions);
- static int write_keys(MI_SORT_PARAM *info,uchar **sort_keys,
-- uint count, BUFFPEK *buffpek,IO_CACHE *tempfile);
-+ ulong count, BUFFPEK *buffpek,IO_CACHE *tempfile);
- static int write_key(MI_SORT_PARAM *info, uchar *key,
- IO_CACHE *tempfile);
- static int write_index(MI_SORT_PARAM *info,uchar * *sort_keys,
-- uint count);
--static int merge_many_buff(MI_SORT_PARAM *info,uint keys,
-+ ulong count);
-+static int merge_many_buff(MI_SORT_PARAM *info, ulong keys,
- uchar * *sort_keys,
-- BUFFPEK *buffpek,int *maxbuffer,
-+ BUFFPEK *buffpek, long *maxbuffer,
- IO_CACHE *t_file);
--static uint read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek,
-+static ulong read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek,
- uint sort_length);
--static int merge_buffers(MI_SORT_PARAM *info,uint keys,
-+static int merge_buffers(MI_SORT_PARAM *info, ulong keys,
- IO_CACHE *from_file, IO_CACHE *to_file,
- uchar * *sort_keys, BUFFPEK *lastbuff,
- BUFFPEK *Fb, BUFFPEK *Tb);
--static int merge_index(MI_SORT_PARAM *,uint,uchar **,BUFFPEK *, int,
-+static int merge_index(MI_SORT_PARAM *, ulong, uchar **, BUFFPEK *, long,
- IO_CACHE *);
- static int flush_ft_buf(MI_SORT_PARAM *info);
-
- static int write_keys_varlen(MI_SORT_PARAM *info,uchar **sort_keys,
-- uint count, BUFFPEK *buffpek,
-+ ulong count, BUFFPEK *buffpek,
- IO_CACHE *tempfile);
--static uint read_to_buffer_varlen(IO_CACHE *fromfile,BUFFPEK *buffpek,
-- uint sort_length);
-+static ulong read_to_buffer_varlen(IO_CACHE *fromfile,BUFFPEK *buffpek,
-+ uint sort_length);
- static int write_merge_key(MI_SORT_PARAM *info, IO_CACHE *to_file,
-- uchar *key, uint sort_length, uint count);
-+ uchar *key, uint sort_length, ulong count);
- static int write_merge_key_varlen(MI_SORT_PARAM *info,
- IO_CACHE *to_file,
- uchar* key, uint sort_length,
-- uint count);
-+ ulong count);
- static inline int
- my_var_write(MI_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs);
-
-@@ -101,8 +101,9 @@
- int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
- ulong sortbuff_size)
- {
-- int error,maxbuffer,skr;
-- uint memavl,old_memavl,keys,sort_length;
-+ int error;
-+ long maxbuffer, skr;
-+ ulong memavl, old_memavl, keys, sort_length;
- DYNAMIC_ARRAY buffpek;
- ha_rows records;
- uchar **sort_keys;
-@@ -136,25 +137,25 @@
-
- while (memavl >= MIN_SORT_BUFFER)
- {
-- if ((records < UINT_MAX32) &&
-+ if ((records < ULONG_MAX) &&
- ((my_off_t) (records + 1) *
- (sort_length + sizeof(char*)) <= (my_off_t) memavl))
-- keys= (uint)records+1;
-+ keys= (ulong) records + 1;
- else
- do
- {
- skr=maxbuffer;
-- if (memavl < sizeof(BUFFPEK)*(uint) maxbuffer ||
-- (keys=(memavl-sizeof(BUFFPEK)*(uint) maxbuffer)/
-+ if (memavl < sizeof(BUFFPEK) * (ulong) maxbuffer ||
-+ (keys = (memavl - sizeof(BUFFPEK) * (ulong) maxbuffer) /
- (sort_length+sizeof(char*))) <= 1 ||
-- keys < (uint) maxbuffer)
-+ keys < (ulong) maxbuffer)
- {
- mi_check_print_error(info->sort_info->param,
- "myisam_sort_buffer_size is too small");
- goto err;
- }
- }
-- while ((maxbuffer= (int) (records/(keys-1)+1)) != skr);
-+ while ((maxbuffer= (long) (records / (keys - 1) + 1)) != skr);
-
- if ((sort_keys=(uchar **)my_malloc(keys*(sort_length+sizeof(char*))+
- HA_FT_MAXBYTELEN, MYF(0))))
-@@ -180,7 +181,7 @@
- (*info->lock_in_memory)(info->sort_info->param);/* Everything is allocated */
-
- if (!no_messages)
-- printf(" - Searching for keys, allocating buffer for %d keys\n",keys);
-+ printf(" - Searching for keys, allocating buffer for %lu keys\n", keys);
-
- if ((records=find_all_keys(info,keys,sort_keys,&buffpek,&maxbuffer,
- &tempfile,&tempfile_for_exceptions))
-@@ -190,7 +191,7 @@
- {
- if (!no_messages)
- printf(" - Dumping %lu keys\n", (ulong) records);
-- if (write_index(info,sort_keys, (uint) records))
-+ if (write_index(info,sort_keys, (ulong) records))
- goto err; /* purecov: inspected */
- }
- else
-@@ -253,13 +254,13 @@
-
- /* Search after all keys and place them in a temp. file */
-
--static ha_rows find_all_keys(MI_SORT_PARAM *info, uint keys,
-+static ha_rows find_all_keys(MI_SORT_PARAM *info, ulong keys,
- uchar **sort_keys, DYNAMIC_ARRAY *buffpek,
-- int *maxbuffer, IO_CACHE *tempfile,
-+ long *maxbuffer, IO_CACHE *tempfile,
- IO_CACHE *tempfile_for_exceptions)
- {
- int error;
-- uint idx;
-+ ulong idx;
- DBUG_ENTER("find_all_keys");
-
- idx=error=0;
-@@ -308,8 +309,8 @@
- {
- MI_SORT_PARAM *sort_param= (MI_SORT_PARAM*) arg;
- int error;
-- uint memavl,old_memavl,keys,sort_length;
-- uint idx, maxbuffer;
-+ ulong memavl,old_memavl,keys,sort_length;
-+ ulong idx, maxbuffer;
- uchar **sort_keys=0;
-
- LINT_INIT(keys);
-@@ -345,7 +346,7 @@
- sort_keys= (uchar **) NULL;
-
- memavl= max(sort_param->sortbuff_size, MIN_SORT_BUFFER);
-- idx= (uint)sort_param->sort_info->max_records;
-+ idx= (ulong) sort_param->sort_info->max_records;
- sort_length= sort_param->key_length;
- maxbuffer= 1;
-
-@@ -356,21 +357,21 @@
- keys= idx+1;
- else
- {
-- uint skr;
-+ ulong skr;
- do
- {
- skr= maxbuffer;
- if (memavl < sizeof(BUFFPEK)*maxbuffer ||
- (keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/
- (sort_length+sizeof(char*))) <= 1 ||
-- keys < (uint) maxbuffer)
-+ keys < maxbuffer)
- {
- mi_check_print_error(sort_param->sort_info->param,
- "myisam_sort_buffer_size is too small");
- goto err;
- }
- }
-- while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr);
-+ while ((maxbuffer= (idx/(keys-1)+1)) != skr);
- }
- if ((sort_keys= (uchar**)
- my_malloc(keys*(sort_length+sizeof(char*))+
-@@ -399,7 +400,7 @@
- }
-
- if (sort_param->sort_info->param->testflag & T_VERBOSE)
-- printf("Key %d - Allocating buffer for %d keys\n",
-+ printf("Key %d - Allocating buffer for %lu keys\n",
- sort_param->key + 1, keys);
- sort_param->sort_keys= sort_keys;
-
-@@ -553,7 +554,7 @@
- }
- if (sinfo->buffpek.elements)
- {
-- uint maxbuffer=sinfo->buffpek.elements-1;
-+ ulong maxbuffer=sinfo->buffpek.elements-1;
- if (!mergebuf)
- {
- length=param->sort_buffer_length;
-@@ -576,7 +577,7 @@
- printf("Key %d - Merging %u keys\n",sinfo->key+1, sinfo->keys);
- if (merge_many_buff(sinfo, keys, (uchar **)mergebuf,
- dynamic_element(&sinfo->buffpek, 0, BUFFPEK *),
-- (int*) &maxbuffer, &sinfo->tempfile))
-+ (long *) &maxbuffer, &sinfo->tempfile))
- {
- got_error=1;
- continue;
-@@ -640,7 +641,7 @@
- /* Write all keys in memory to file for later merge */
-
- static int write_keys(MI_SORT_PARAM *info, register uchar **sort_keys,
-- uint count, BUFFPEK *buffpek, IO_CACHE *tempfile)
-+ ulong count, BUFFPEK *buffpek, IO_CACHE *tempfile)
- {
- uchar **end;
- uint sort_length=info->key_length;
-@@ -682,7 +683,7 @@
-
- static int write_keys_varlen(MI_SORT_PARAM *info,
- register uchar **sort_keys,
-- uint count, BUFFPEK *buffpek,
-+ ulong count, BUFFPEK *buffpek,
- IO_CACHE *tempfile)
- {
- uchar **end;
-@@ -727,7 +728,7 @@
- /* Write index */
-
- static int write_index(MI_SORT_PARAM *info, register uchar **sort_keys,
-- register uint count)
-+ register ulong count)
- {
- DBUG_ENTER("write_index");
-
-@@ -744,11 +745,11 @@
-
- /* Merge buffers to make < MERGEBUFF2 buffers */
-
--static int merge_many_buff(MI_SORT_PARAM *info, uint keys,
-+static int merge_many_buff(MI_SORT_PARAM *info, ulong keys,
- uchar **sort_keys, BUFFPEK *buffpek,
-- int *maxbuffer, IO_CACHE *t_file)
-+ long *maxbuffer, IO_CACHE *t_file)
- {
-- register int i;
-+ register long i;
- IO_CACHE t_file2, *from_file, *to_file, *temp;
- BUFFPEK *lastbuff;
- DBUG_ENTER("merge_many_buff");
-@@ -778,7 +779,7 @@
- if (flush_io_cache(to_file))
- break; /* purecov: inspected */
- temp=from_file; from_file=to_file; to_file=temp;
-- *maxbuffer= (int) (lastbuff-buffpek)-1;
-+ *maxbuffer= (long) (lastbuff-buffpek)-1;
- }
- cleanup:
- close_cached_file(to_file); /* This holds old result */
-@@ -807,18 +808,18 @@
- -1 Error
- */
-
--static uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
-- uint sort_length)
-+static ulong read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
-+ uint sort_length)
- {
-- register uint count;
-- uint length;
-+ register ulong count;
-+ ulong length;
-
-- if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
-+ if ((count=(ulong) min((ha_rows) buffpek->max_keys,buffpek->count)))
- {
- if (mysql_file_pread(fromfile->file, (uchar*) buffpek->base,
- (length= sort_length*count),
- buffpek->file_pos, MYF_RW))
-- return((uint) -1); /* purecov: inspected */
-+ return((ulong) -1); /* purecov: inspected */
- buffpek->key=buffpek->base;
- buffpek->file_pos+= length; /* New filepos */
- buffpek->count-= count;
-@@ -827,15 +828,15 @@
- return (count*sort_length);
- } /* read_to_buffer */
-
--static uint read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek,
-+static ulong read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek,
- uint sort_length)
- {
-- register uint count;
-+ register ulong count;
- uint16 length_of_key = 0;
-- uint idx;
-+ ulong idx;
- uchar *buffp;
-
-- if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
-+ if ((count=(ulong) min((ha_rows) buffpek->max_keys,buffpek->count)))
- {
- buffp = buffpek->base;
-
-@@ -843,11 +844,11 @@
- {
- if (mysql_file_pread(fromfile->file, (uchar*)&length_of_key,
- sizeof(length_of_key), buffpek->file_pos, MYF_RW))
-- return((uint) -1);
-+ return((ulong) -1);
- buffpek->file_pos+=sizeof(length_of_key);
- if (mysql_file_pread(fromfile->file, (uchar*) buffp,
- length_of_key, buffpek->file_pos, MYF_RW))
-- return((uint) -1);
-+ return((ulong) -1);
- buffpek->file_pos+=length_of_key;
- buffp = buffp + sort_length;
- }
-@@ -861,9 +862,9 @@
-
- static int write_merge_key_varlen(MI_SORT_PARAM *info,
- IO_CACHE *to_file, uchar* key,
-- uint sort_length, uint count)
-+ uint sort_length, ulong count)
- {
-- uint idx;
-+ ulong idx;
- uchar *bufs = key;
-
- for (idx=1;idx<=count;idx++)
-@@ -879,7 +880,7 @@
-
- static int write_merge_key(MI_SORT_PARAM *info __attribute__((unused)),
- IO_CACHE *to_file, uchar *key,
-- uint sort_length, uint count)
-+ uint sort_length, ulong count)
- {
- return my_b_write(to_file, key, (size_t) sort_length*count);
- }
-@@ -890,12 +891,13 @@
- */
-
- static int
--merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
-+merge_buffers(MI_SORT_PARAM *info, ulong keys, IO_CACHE *from_file,
- IO_CACHE *to_file, uchar **sort_keys, BUFFPEK *lastbuff,
- BUFFPEK *Fb, BUFFPEK *Tb)
- {
-- int error;
-- uint sort_length,maxcount;
-+ ulong error;
-+ uint sort_length;
-+ ulong maxcount;
- ha_rows count;
- my_off_t UNINIT_VAR(to_start_filepos);
- uchar *strpos;
-@@ -905,7 +907,7 @@
- DBUG_ENTER("merge_buffers");
-
- count=error=0;
-- maxcount=keys/((uint) (Tb-Fb) +1);
-+ maxcount= keys / ((ulong) (Tb-Fb) + 1);
- DBUG_ASSERT(maxcount > 0);
- LINT_INIT(to_start_filepos);
- if (to_file)
-@@ -913,7 +915,7 @@
- strpos=(uchar*) sort_keys;
- sort_length=info->key_length;
-
-- if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
-+ if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
- (int (*)(void*, uchar *,uchar*)) info->key_cmp,
- (void*) info))
- DBUG_RETURN(1); /* purecov: inspected */
-@@ -923,9 +925,8 @@
- count+= buffpek->count;
- buffpek->base= strpos;
- buffpek->max_keys=maxcount;
-- strpos+= (uint) (error=(int) info->read_to_buffer(from_file,buffpek,
-- sort_length));
-- if (error == -1)
-+ strpos+= (error= info->read_to_buffer(from_file,buffpek, sort_length));
-+ if (error == (ulong) -1)
- goto err; /* purecov: inspected */
- queue_insert(&queue,(uchar*) buffpek);
- }
-@@ -957,10 +958,10 @@
- buffpek->key+=sort_length;
- if (! --buffpek->mem_count)
- {
-- if (!(error=(int) info->read_to_buffer(from_file,buffpek,sort_length)))
-+ if (!(error= info->read_to_buffer(from_file,buffpek,sort_length)))
- {
- uchar *base=buffpek->base;
-- uint max_keys=buffpek->max_keys;
-+ ulong max_keys=buffpek->max_keys;
-
- (void) queue_remove(&queue,0);
-
-@@ -985,7 +986,7 @@
- break; /* One buffer have been removed */
- }
- }
-- else if (error == -1)
-+ else if (error == (ulong) -1)
- goto err; /* purecov: inspected */
- queue_replaced(&queue); /* Top element has been replaced */
- }
-@@ -1018,23 +1019,23 @@
- }
- }
- }
-- while ((error=(int) info->read_to_buffer(from_file,buffpek,sort_length)) != -1 &&
-- error != 0);
-+ while ((error= info->read_to_buffer(from_file,buffpek,sort_length))
-+ != (ulong) -1 && error != 0);
-
- lastbuff->count=count;
- if (to_file)
- lastbuff->file_pos=to_start_filepos;
- err:
- delete_queue(&queue);
-- DBUG_RETURN(error);
-+ DBUG_RETURN(error != 0);
- } /* merge_buffers */
-
-
- /* Do a merge to output-file (save only positions) */
-
- static int
--merge_index(MI_SORT_PARAM *info, uint keys, uchar **sort_keys,
-- BUFFPEK *buffpek, int maxbuffer, IO_CACHE *tempfile)
-+merge_index(MI_SORT_PARAM *info, ulong keys, uchar **sort_keys,
-+ BUFFPEK *buffpek, long maxbuffer, IO_CACHE *tempfile)
- {
- DBUG_ENTER("merge_index");
- if (merge_buffers(info,keys,tempfile,(IO_CACHE*) 0,sort_keys,buffpek,buffpek,
---- /dev/null
-+++ b/mysql-test/r/percona_bug45702.result
-@@ -0,0 +1,21 @@
-+CREATE TABLE t1 (a BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY) ENGINE=MyISAM;
-+INSERT INTO t1 VALUES (), (), (), (), (), (), (), ();
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+SET @old_myisam_sort_buffer_size = @@myisam_sort_buffer_size;
-+SET @@myisam_sort_buffer_size = 4 * 1024 * 1024 * 1024;
-+REPAIR TABLE t1;
-+Table Op Msg_type Msg_text
-+test.t1 repair status OK
-+- recovering (with sort) MyISAM-table 'MYSQLD_DATADIR/test/t1'
-+Data records: 4096
-+- Fixing index 1
-+SET @@myisam_sort_buffer_size = @old_myisam_sort_buffer_size;
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/t/percona_bug45702.test
-@@ -0,0 +1,34 @@
-+###############################################################################
-+# Bug #45702: Impossible to specify myisam_sort_buffer > 4GB on 64 bit machines
-+###############################################################################
-+
-+--source include/have_64bit.inc
-+
-+# Check that having data larger than MIN_SORT_BUFFER bytes can be handled by
-+# _create_index_by_sort() with myisam_sort_buffer_size = 4 GB without errors.
-+# The full test with large data volumes can not be a part of the test suite.
-+
-+CREATE TABLE t1 (a BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY) ENGINE=MyISAM;
-+INSERT INTO t1 VALUES (), (), (), (), (), (), (), ();
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+INSERT INTO t1 SELECT NULL FROM t1;
-+
-+SET @old_myisam_sort_buffer_size = @@myisam_sort_buffer_size;
-+SET @@myisam_sort_buffer_size = 4 * 1024 * 1024 * 1024;
-+
-+REPAIR TABLE t1;
-+
-+--let $MYSQLD_DATADIR= `select @@datadir`
-+--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
-+--exec $MYISAMCHK -r --sort_buffer_size=4G $MYSQLD_DATADIR/test/t1
-+
-+SET @@myisam_sort_buffer_size = @old_myisam_sort_buffer_size;
-+
-+DROP TABLE t1;
---- a/sql/opt_range.cc
-+++ b/sql/opt_range.cc
-@@ -11728,7 +11728,7 @@
- }
- if (min_max_ranges.elements > 0)
- {
-- fprintf(DBUG_FILE, "%*susing %d quick_ranges for MIN/MAX:\n",
-+ fprintf(DBUG_FILE, "%*susing %lu quick_ranges for MIN/MAX:\n",
- indent, "", min_max_ranges.elements);
- }
- }
---- a/mysys/my_pread.c
-+++ b/mysys/my_pread.c
-@@ -49,6 +49,7 @@
- myf MyFlags)
- {
- size_t readbytes;
-+ size_t total_readbytes= 0;
- int error= 0;
- #if !defined (HAVE_PREAD) && !defined (_WIN32)
- int save_errno;
-@@ -76,8 +77,30 @@
- #endif
- error= (readbytes != Count);
- #endif
-+ if (readbytes > 0)
-+ total_readbytes+= readbytes;
-+
- if(error)
- {
-+ if (readbytes > 0 && readbytes < Count && errno == 0)
-+ {
-+ /*
-+ pread() may return less bytes than requested even if enough bytes are
-+ available according to the Linux man page.
-+ This makes determining the end-of-file condition a bit harder.
-+ We just do another pread() call to see if more bytes can be read,
-+ since all my_pread() users expect it to always return all available
-+ bytes. For end-of-file 0 bytes is returned. This can never be the case
-+ for a partial read, since according to the man page, -1 is returned
-+ with errno set to EINTR if no data has been read.
-+ */
-+ Buffer+= readbytes;
-+ offset+= readbytes;
-+ Count-= readbytes;
-+
-+ continue;
-+ }
-+
- my_errno= errno ? errno : -1;
- if (errno == 0 || (readbytes != (size_t) -1 &&
- (MyFlags & (MY_NABP | MY_FNABP))))
-@@ -107,7 +130,7 @@
- }
- if (MyFlags & (MY_NABP | MY_FNABP))
- DBUG_RETURN(0); /* Read went ok; Return 0 */
-- DBUG_RETURN(readbytes); /* purecov: inspected */
-+ DBUG_RETURN(total_readbytes); /* purecov: inspected */
- }
- } /* my_pread */
-
---- a/storage/myisam/myisamdef.h
-+++ b/storage/myisam/myisamdef.h
-@@ -340,10 +340,10 @@
- int (*key_write)(struct st_mi_sort_param *, const void *);
- void (*lock_in_memory)(MI_CHECK *);
- int (*write_keys)(struct st_mi_sort_param *, register uchar **,
-- uint , struct st_buffpek *, IO_CACHE *);
-- uint (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint);
-+ ulong , struct st_buffpek *, IO_CACHE *);
-+ ulong (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint);
- int (*write_key)(struct st_mi_sort_param *, IO_CACHE *,uchar *,
-- uint, uint);
-+ uint, ulong);
- } MI_SORT_PARAM;
-
- /* Some defines used by isam-funktions */
---- a/sql/rpl_mi.cc
-+++ b/sql/rpl_mi.cc
-@@ -491,7 +491,7 @@
- (1 + mi->ignore_server_ids.elements), MYF(MY_WME));
- if (!ignore_server_ids_buf)
- DBUG_RETURN(1);
-- ulong cur_len= sprintf(ignore_server_ids_buf, "%u",
-+ ulong cur_len= sprintf(ignore_server_ids_buf, "%lu",
- mi->ignore_server_ids.elements);
- for (ulong i= 0; i < mi->ignore_server_ids.elements; i++)
- {
+++ /dev/null
---- a/storage/innobase/row/row0merge.c
-+++ b/storage/innobase/row/row0merge.c
-@@ -1607,22 +1607,28 @@
- const dict_index_t* index, /*!< in: index being created */
- merge_file_t* file, /*!< in/out: file containing
- index entries */
-- ulint* half, /*!< in/out: half the file */
- row_merge_block_t* block, /*!< in/out: 3 buffers */
- int* tmpfd, /*!< in/out: temporary file handle */
-- struct TABLE* table) /*!< in/out: MySQL table, for
-+ struct TABLE* table, /*!< in/out: MySQL table, for
- reporting erroneous key value
- if applicable */
-+ ulint* num_run,/*!< in/out: Number of runs remain
-+ to be merged */
-+ ulint* run_offset) /*!< in/out: Array contains the
-+ first offset number for each merge
-+ run */
- {
- ulint foffs0; /*!< first input offset */
- ulint foffs1; /*!< second input offset */
- ulint error; /*!< error code */
- merge_file_t of; /*!< output file */
-- const ulint ihalf = *half;
-+ const ulint ihalf = run_offset[*num_run / 2];
- /*!< half the input file */
-- ulint ohalf; /*!< half the output file */
-+ ulint n_run = 0;
-+ /*!< num of runs generated from this merge */
-
- UNIV_MEM_ASSERT_W(block[0], 3 * sizeof block[0]);
-+
- ut_ad(ihalf < file->offset);
-
- of.fd = *tmpfd;
-@@ -1638,17 +1644,20 @@
- #endif /* POSIX_FADV_SEQUENTIAL */
-
- /* Merge blocks to the output file. */
-- ohalf = 0;
- foffs0 = 0;
- foffs1 = ihalf;
-
-+ UNIV_MEM_INVALID(run_offset, *num_run * sizeof *run_offset);
-+
- for (; foffs0 < ihalf && foffs1 < file->offset; foffs0++, foffs1++) {
-- ulint ahalf; /*!< arithmetic half the input file */
-
- if (UNIV_UNLIKELY(trx_is_interrupted(trx))) {
- return(DB_INTERRUPTED);
- }
-
-+ /* Remember the offset number for this run */
-+ run_offset[n_run++] = of.offset;
-+
- error = row_merge_blocks(index, file, block,
- &foffs0, &foffs1, &of, table);
-
-@@ -1656,21 +1665,6 @@
- return(error);
- }
-
-- /* Record the offset of the output file when
-- approximately half the output has been generated. In
-- this way, the next invocation of row_merge() will
-- spend most of the time in this loop. The initial
-- estimate is ohalf==0. */
-- ahalf = file->offset / 2;
-- ut_ad(ohalf <= of.offset);
--
-- /* Improve the estimate until reaching half the input
-- file size, or we can not get any closer to it. All
-- comparands should be non-negative when !(ohalf < ahalf)
-- because ohalf <= of.offset. */
-- if (ohalf < ahalf || of.offset - ahalf < ohalf - ahalf) {
-- ohalf = of.offset;
-- }
- }
-
- /* Copy the last blocks, if there are any. */
-@@ -1680,6 +1674,9 @@
- return(DB_INTERRUPTED);
- }
-
-+ /* Remember the offset number for this run */
-+ run_offset[n_run++] = of.offset;
-+
- if (!row_merge_blocks_copy(index, file, block, &foffs0, &of)) {
- return(DB_CORRUPTION);
- }
-@@ -1692,6 +1689,9 @@
- return(DB_INTERRUPTED);
- }
-
-+ /* Remember the offset number for this run */
-+ run_offset[n_run++] = of.offset;
-+
- if (!row_merge_blocks_copy(index, file, block, &foffs1, &of)) {
- return(DB_CORRUPTION);
- }
-@@ -1703,10 +1703,23 @@
- return(DB_CORRUPTION);
- }
-
-+ ut_ad(n_run <= *num_run);
-+
-+ *num_run = n_run;
-+
-+ /* Each run can contain one or more offsets. As merge goes on,
-+ the number of runs (to merge) will reduce until we have one
-+ single run. So the number of runs will always be smaller than
-+ the number of offsets in file */
-+ ut_ad((*num_run) <= file->offset);
-+
-+ /* The number of offsets in output file is always equal or
-+ smaller than input file */
-+ ut_ad(of.offset <= file->offset);
-+
- /* Swap file descriptors for the next pass. */
- *tmpfd = file->fd;
- *file = of;
-- *half = ohalf;
-
- UNIV_MEM_INVALID(block[0], 3 * sizeof block[0]);
-
-@@ -1731,27 +1744,44 @@
- if applicable */
- {
- ulint half = file->offset / 2;
-+ ulint num_runs;
-+ ulint* run_offset;
-+ ulint error = DB_SUCCESS;
-+
-+ /* Record the number of merge runs we need to perform */
-+ num_runs = file->offset;
-+
-+ /* If num_runs are less than 1, nothing to merge */
-+ if (num_runs <= 1) {
-+ return(error);
-+ }
-+
-+ /* "run_offset" records each run's first offset number */
-+ run_offset = (ulint*) mem_alloc(file->offset * sizeof(ulint));
-+
-+ /* This tells row_merge() where to start for the first round
-+ of merge. */
-+ run_offset[half] = half;
-
- /* The file should always contain at least one byte (the end
- of file marker). Thus, it must be at least one block. */
- ut_ad(file->offset > 0);
-
-+ /* Merge the runs until we have one big run */
- do {
-- ulint error;
-+ error = row_merge(trx, index, file, block, tmpfd,
-+ table, &num_runs, run_offset);
-
-- error = row_merge(trx, index, file, &half,
-- block, tmpfd, table);
-+ UNIV_MEM_ASSERT_RW(run_offset, num_runs * sizeof *run_offset);
-
- if (error != DB_SUCCESS) {
-- return(error);
-+ break;
- }
-+ } while (num_runs > 1);
-
-- /* half > 0 should hold except when the file consists
-- of one block. No need to merge further then. */
-- ut_ad(half > 0 || file->offset == 1);
-- } while (half < file->offset && half > 0);
-+ mem_free(run_offset);
-
-- return(DB_SUCCESS);
-+ return(error);
- }
-
- /*************************************************************//**
---- /dev/null
-+++ b/mysql-test/suite/innodb/r/bug54330.result
-@@ -0,0 +1,13 @@
-+DROP TABLE IF EXISTS t1;
-+CREATE TABLE t1 (
-+id BIGINT(20) AUTO_INCREMENT PRIMARY KEY,
-+bar BIGINT(20)
-+) ENGINE=InnoDB;
-+SELECT COUNT(*) FROM t1;
-+COUNT(*)
-+517672
-+ALTER TABLE t1 ADD INDEX baz (bar);
-+SELECT COUNT(*) FROM t1 FORCE INDEX (baz);
-+COUNT(*)
-+517672
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/suite/innodb/t/bug54330.test
-@@ -0,0 +1,38 @@
-+# Testcase for MySQL bug #54330 - broken fast index creation
-+
-+--disable_warnings
-+DROP TABLE IF EXISTS t1;
-+--enable_warnings
-+
-+CREATE TABLE t1 (
-+ id BIGINT(20) AUTO_INCREMENT PRIMARY KEY,
-+ bar BIGINT(20)
-+) ENGINE=InnoDB;
-+
-+--disable_query_log
-+SET @old_autocommit=@@AUTOCOMMIT;
-+SET AUTOCOMMIT=0;
-+let $1= 515641;
-+while ($1)
-+{
-+ eval INSERT INTO t1 (bar) VALUES (NULL);
-+ dec $1;
-+}
-+let $1= 2031;
-+while ($1)
-+{
-+ eval INSERT INTO t1 (bar) VALUES ($1);
-+ dec $1;
-+}
-+COMMIT;
-+SET AUTOCOMMIT=@old_autocommit;
-+--enable_query_log
-+
-+SELECT COUNT(*) FROM t1;
-+
-+ALTER TABLE t1 ADD INDEX baz (bar);
-+
-+# With the bug present this will differ from the SELECT above!
-+SELECT COUNT(*) FROM t1 FORCE INDEX (baz);
-+
-+DROP TABLE t1;
+++ /dev/null
-# name : bug580324.patch
-# introduced : 11 or before
-# maintainer : Oleg
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/sql/sql_base.cc
-+++ b/sql/sql_base.cc
-@@ -314,8 +314,12 @@
- const TABLE_LIST *table_list,
- bool tmp_table)
- {
-- uint key_length= (uint) (strmov(strmov(key, table_list->db)+1,
-- table_list->table_name)-key)+1;
-+ char *db_end= strnmov(key, table_list->db, MAX_DBKEY_LENGTH - 2);
-+ *db_end++= '\0';
-+ char *table_end= strnmov(db_end, table_list->table_name,
-+ key + MAX_DBKEY_LENGTH - 1 - db_end);
-+ *table_end++= '\0';
-+ uint key_length= (uint) (table_end-key);
- if (tmp_table)
- {
- int4store(key + key_length, thd->server_id);
---- a/sql/sql_parse.cc
-+++ b/sql/sql_parse.cc
-@@ -1116,11 +1116,18 @@
- break;
- #else
- {
-- char *fields, *packet_end= packet + packet_length, *arg_end;
-+ char *fields;
-+ char *packet_end= packet + packet_length;
-+ char *wildcard;
- /* Locked closure of all tables */
- TABLE_LIST table_list;
-+ char table_name_buff[NAME_LEN+1];
- LEX_STRING table_name;
-+ uint dummy_errors;
- LEX_STRING db;
-+
-+ table_name.str= table_name_buff;
-+ table_name.length= 0;
- /*
- SHOW statements should not add the used tables to the list of tables
- used in a transaction.
-@@ -1133,24 +1140,23 @@
- /*
- We have name + wildcard in packet, separated by endzero
- */
-- arg_end= strend(packet);
-- uint arg_length= arg_end - packet;
--
-- /* Check given table name length. */
-- if (arg_length >= packet_length || arg_length > NAME_LEN)
-+ wildcard= strend(packet);
-+ table_name.length= wildcard - packet;
-+ wildcard++;
-+ uint query_length= (uint) (packet_end - wildcard); // Don't count end \0
-+ if (table_name.length > NAME_LEN || query_length > NAME_LEN)
- {
- my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
- break;
- }
-- thd->convert_string(&table_name, system_charset_info,
-- packet, arg_length, thd->charset());
-- if (check_table_name(table_name.str, table_name.length, FALSE))
-- {
-- /* this is OK due to convert_string() null-terminating the string */
-- my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name.str);
-+ table_name.length= copy_and_convert(table_name.str,
-+ sizeof(table_name_buff)-1,
-+ system_charset_info,
-+ packet, table_name.length,
-+ thd->charset(), &dummy_errors);
-+ table_name.str[table_name.length]= '\0';
-+ if (!(fields= (char *) thd->memdup(wildcard, query_length + 1)))
- break;
-- }
-- packet= arg_end + 1;
- mysql_reset_thd_for_next_command(thd);
- lex_start(thd);
- /* Must be before we init the table list. */
-@@ -1175,9 +1181,6 @@
- table_list.schema_table= schema_table;
- }
-
-- uint query_length= (uint) (packet_end - packet); // Don't count end \0
-- if (!(fields= (char *) thd->memdup(packet, query_length + 1)))
-- break;
- thd->set_query(fields, query_length);
- general_log_print(thd, command, "%s %s", table_list.table_name, fields);
-
---- a/strings/ctype-utf8.c
-+++ b/strings/ctype-utf8.c
-@@ -4212,6 +4212,10 @@
- {
- int code;
- char hex[]= "0123456789abcdef";
-+
-+ if (s >= e)
-+ return MY_CS_TOOSMALL;
-+
- if (wc < 128 && filename_safe_char[wc])
- {
- *s= (uchar) wc;
+++ /dev/null
-# name : bug813587.patch
-# maintainer : Alexey
-#
-# Fix for LP bug #813587 / MySQL bug #51196 / MySQL bug #61790
-#
-# Clear MySQL connection errors in ha_federated::close(), since they
-# can affect queries on other tables due to table cache eviction.
-#
---- a/storage/federated/ha_federated.cc
-+++ b/storage/federated/ha_federated.cc
-@@ -1675,6 +1675,8 @@
-
- int ha_federated::close(void)
- {
-+ THD *thd= current_thd;
-+
- DBUG_ENTER("ha_federated::close");
-
- free_result();
-@@ -1685,6 +1687,10 @@
- mysql_close(mysql);
- mysql= NULL;
-
-+ /* Clear possible errors from mysql_close(), see LP bug #813587. */
-+ if (thd)
-+ thd->clear_error();
-+
- DBUG_RETURN(free_share(share));
- }
-
+++ /dev/null
-# name : bug860910.patch
-# maintainer : Alexey
-#
-# Fixes LP bug #860910 / MySQL bug #62557
-#
---- /dev/null
-+++ b/mysql-test/suite/rpl/r/percona_bug860910.result
-@@ -0,0 +1,17 @@
-+*** Set up master (server_1) <-> master (server_2) replication ***
-+include/rpl_init.inc [topology=1->2->1]
-+
-+SELECT @@global.log_slave_updates;
-+@@global.log_slave_updates
-+1
-+SELECT @@global.log_slave_updates;
-+@@global.log_slave_updates
-+1
-+CREATE TABLE t1(a INT);
-+SET @var:=0;
-+INSERT INTO t1 VALUES (@var);
-+INSERT INTO t1 VALUES (1);
-+DROP TABLE t1;
-+include/rpl_sync.inc
-+include/check_slave_param.inc [Exec_Master_Log_Pos]
-+include/rpl_end.inc
---- /dev/null
-+++ b/mysql-test/suite/rpl/t/percona_bug860910.cnf
-@@ -0,0 +1,8 @@
-+!include ../my.cnf
-+
-+[mysqld.1]
-+log-slave-updates
-+
-+[mysqld.2]
-+log-slave-updates
-+
---- /dev/null
-+++ b/mysql-test/suite/rpl/t/percona_bug860910.test
-@@ -0,0 +1,38 @@
-+########################################################################
-+# Bug #860910: SHOW SLAVE STATUS gives wrong output with master-master
-+# and using SET uservars
-+########################################################################
-+
-+--echo *** Set up master (server_1) <-> master (server_2) replication ***
-+--let $rpl_topology= 1->2->1
-+--source include/rpl_init.inc
-+--echo
-+
-+--connection server_1
-+SELECT @@global.log_slave_updates;
-+
-+--connection server_2
-+SELECT @@global.log_slave_updates;
-+
-+--connection server_1
-+CREATE TABLE t1(a INT);
-+SET @var:=0;
-+INSERT INTO t1 VALUES (@var);
-+INSERT INTO t1 VALUES (1);
-+
-+DROP TABLE t1;
-+
-+# The following would hang with the bug not fixed due to incorrect
-+# Exec_Master_Log_Pos
-+--source include/rpl_sync.inc
-+
-+--connection server_2
-+--let $master_log_pos= query_get_value(SHOW MASTER STATUS, Position, 1)
-+
-+--connection server_1
-+--let $slave_param= Exec_Master_Log_Pos
-+--let $slave_param_value= $master_log_pos
-+--source include/check_slave_param.inc
-+
-+# Cleanup
-+--source include/rpl_end.inc
---- a/sql/log.cc
-+++ b/sql/log.cc
-@@ -5112,6 +5112,12 @@
- user_var_event->type,
- user_var_event->charset_number,
- flags);
-+ /*
-+ These User_var_log_events must be logged with event_info's
-+ server_id, rather than the current one.
-+ */
-+ e.server_id= event_info->server_id;
-+
- if (e.write(file))
- goto err;
- if (file == &log_file)
+++ /dev/null
---- /dev/null
-+++ b/mysql-test/r/percona_innodb_version.result
-@@ -0,0 +1,3 @@
-+SELECT @@innodb_version;
-+@@innodb_version
-+1.1.x-x.x
---- /dev/null
-+++ b/mysql-test/t/percona_innodb_version.test
-@@ -0,0 +1,8 @@
-+--source include/have_innodb.inc
-+
-+########################################################################
-+# Bug #917246: Unintentional change of innodb_version format in 5.1.60
-+########################################################################
-+
-+--replace_regex /1\.1\.[0-9]+-[0-9]+\.[0-9]+/1.1.x-x.x/
-+SELECT @@innodb_version;
+++ /dev/null
---- /dev/null
-+++ b/mysql-test/r/percona_bug933969.result
-@@ -0,0 +1,16 @@
-+RESET MASTER;
-+DROP TABLE IF EXISTS t1;
-+CREATE TABLE t1 (word VARCHAR(20));
-+INSERT INTO t1 VALUES ("hamite");
-+INSERT INTO t1 VALUES ("hoho");
-+INSERT INTO t1 VALUES ("znamenito");
-+INSERT INTO t1 VALUES ("mrachny");
-+INSERT INTO t1 VALUES ("mrak");
-+INSERT INTO t1 VALUES ("zhut");
-+INSERT INTO t1 VALUES ("parnisha");
-+INSERT INTO t1 VALUES ("krrasota!");
-+INSERT INTO t1 VALUES ("podumayesh");
-+INSERT INTO t1 VALUES ("ogo!");
-+FLUSH LOGS;
-+DROP TABLE t1;
-+RESET MASTER;
---- /dev/null
-+++ b/mysql-test/t/percona_bug933969.test
-@@ -0,0 +1,42 @@
-+###################### percona_bug933969.test ########################
-+# Bug #933969: mysqlbinlog doesn't accept stdin #
-+# #
-+# The goal of this testcase is to test that mysqlbinlog handle #
-+# stdin correctly when stdin is pipe. #
-+# i.e. "cat log | mysqlbinlog -" don't cause mysqlbinlog failure #
-+######################################################################
-+-- source include/have_log_bin.inc
-+-- source include/not_windows.inc
-+-- source include/not_embedded.inc
-+
-+# deletes all the binary logs
-+RESET MASTER;
-+
-+--disable_warnings
-+DROP TABLE IF EXISTS t1;
-+--enable_warnings
-+
-+# produce some statements for binlog
-+
-+CREATE TABLE t1 (word VARCHAR(20));
-+
-+INSERT INTO t1 VALUES ("hamite");
-+INSERT INTO t1 VALUES ("hoho");
-+INSERT INTO t1 VALUES ("znamenito");
-+INSERT INTO t1 VALUES ("mrachny");
-+INSERT INTO t1 VALUES ("mrak");
-+INSERT INTO t1 VALUES ("zhut");
-+INSERT INTO t1 VALUES ("parnisha");
-+INSERT INTO t1 VALUES ("krrasota!");
-+INSERT INTO t1 VALUES ("podumayesh");
-+INSERT INTO t1 VALUES ("ogo!");
-+
-+FLUSH LOGS;
-+
-+# run mysqlbinlog and make sure it ends normally
-+
-+let $MYSQLD_DATADIR= `SELECT @@datadir`;
-+--system cat $MYSQLD_DATADIR/master-bin.000001 | $MYSQL_BINLOG - >/dev/null
-+
-+DROP TABLE t1;
-+RESET MASTER;
---- a/client/mysqlbinlog.cc
-+++ b/client/mysqlbinlog.cc
-@@ -1760,7 +1760,7 @@
- }
-
- pos= my_b_tell(file);
-- my_b_seek(file, (my_off_t)0);
-+ DBUG_ASSERT(pos == 0);
- if (my_b_read(file, header, sizeof(header)))
- {
- error("Failed reading header; probably an empty file.");
-@@ -1920,7 +1920,7 @@
- /* read from normal file */
- if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0)
- return ERROR_STOP;
-- if (init_io_cache(file, fd, 0, READ_CACHE, start_position_mot, 0,
-+ if (init_io_cache(file, fd, 0, READ_CACHE, (my_off_t) 0, 0,
- MYF(MY_WME | MY_NABP)))
- {
- my_close(fd, MYF(MY_WME));
-@@ -1928,6 +1928,7 @@
- }
- if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
- goto end;
-+ my_b_seek(file, start_position_mot);
- }
- else
- {
+++ /dev/null
-Bug#966844 "page size 1024 but the only supported page size in this release is=16384" error on upgrade to 5.5.2[01]
-
-Patch is from http://bugs.mysql.com/bug.php?id=64160
-http://bugs.mysql.com/file.php?id=18031&text=1
-By Kevin Lewis
-
-Adapted to Percona Server by Stewart Smith
-
---- a/storage/innobase/srv/srv0start.c
-+++ b/storage/innobase/srv/srv0start.c
-@@ -925,8 +925,9 @@
- #endif /* UNIV_LOG_ARCHIVE */
- min_flushed_lsn, max_flushed_lsn);
-
-- if (UNIV_PAGE_SIZE
-- != fsp_flags_get_page_size(flags)) {
-+ if (!one_opened
-+ && UNIV_PAGE_SIZE
-+ != fsp_flags_get_page_size(flags)) {
-
- ut_print_timestamp(stderr);
- fprintf(stderr,
+++ /dev/null
-# name : control_online_alter_index.patch
-# introduced : 12
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/sql/handler.h
-+++ b/sql/handler.h
-@@ -206,6 +206,8 @@
- #define HA_INPLACE_DROP_UNIQUE_INDEX_NO_WRITE (1L << 9)
- #define HA_INPLACE_ADD_PK_INDEX_NO_WRITE (1L << 10)
- #define HA_INPLACE_DROP_PK_INDEX_NO_WRITE (1L << 11)
-+
-+#define HA_INPLACE_ALTER_INDEX_MASK ((1L << 12) - 1)
- /*
- HA_PARTITION_FUNCTION_SUPPORTED indicates that the function is
- supported at all.
---- a/sql/sql_class.h
-+++ b/sql/sql_class.h
-@@ -479,6 +479,8 @@
- my_bool engine_condition_pushdown;
- my_bool keep_files_on_create;
-
-+ my_bool online_alter_index;
-+
- my_bool old_alter_table;
- my_bool old_passwords;
- my_bool big_tables;
---- a/sql/sql_partition.cc
-+++ b/sql/sql_partition.cc
-@@ -4637,7 +4637,12 @@
- alter_info->num_parts= curr_part_no - new_part_no;
- }
- }
-- if (!(flags= new_table->file->alter_table_flags(alter_info->flags)))
-+ flags= new_table->file->alter_table_flags(alter_info->flags);
-+ if (!thd->variables.online_alter_index)
-+ {
-+ flags&= ~((uint)HA_INPLACE_ALTER_INDEX_MASK);
-+ }
-+ if (!flags)
- {
- my_error(ER_PARTITION_FUNCTION_FAILURE, MYF(0));
- goto err;
---- a/sql/sql_table.cc
-+++ b/sql/sql_table.cc
-@@ -6146,6 +6146,10 @@
- uint *idx_end_p;
-
- alter_flags= table->file->alter_table_flags(alter_info->flags);
-+ if (!thd->variables.online_alter_index)
-+ {
-+ alter_flags&= ~((ulong)HA_INPLACE_ALTER_INDEX_MASK);
-+ }
- DBUG_PRINT("info", ("alter_flags: %lu", alter_flags));
- /* Check dropped indexes. */
- for (idx_p= index_drop_buffer, idx_end_p= idx_p + index_drop_count;
---- a/sql/sys_vars.cc
-+++ b/sql/sys_vars.cc
-@@ -2265,6 +2265,13 @@
- GLOBAL_VAR(opt_optimizer_fix),
- NO_CMD_LINE, DEFAULT(TRUE));
-
-+static Sys_var_mybool Sys_fast_index_creation(
-+ "fast_index_creation",
-+ "If disabled, suppresses online operations for indexes of ALTER TABLE "
-+ "(e.g. fast index creation of InnoDB Plugin) for the session.",
-+ SESSION_VAR(online_alter_index), NO_CMD_LINE,
-+ DEFAULT(TRUE));
-+
- /** propagates changes to the relevant flag of @@optimizer_switch */
- static bool fix_engine_condition_pushdown(sys_var *self, THD *thd,
- enum_var_type type)
+++ /dev/null
-# name : error_pad.patch
-# introduced : 12
-# maintainer : Oleg
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/extra/comp_err.c
-+++ b/extra/comp_err.c
-@@ -32,11 +32,12 @@
- #include <assert.h>
- #include <my_dir.h>
-
--#define MAX_ROWS 1000
-+#define MAX_ROWS 5000
- #define HEADER_LENGTH 32 /* Length of header in errmsg.sys */
- #define DEFAULT_CHARSET_DIR "../sql/share/charsets"
- #define ER_PREFIX "ER_"
- #define WARN_PREFIX "WARN_"
-+#define PADD_PREFIX "PADD_"
- static char *OUTFILE= (char*) "errmsg.sys";
- static char *HEADERFILE= (char*) "mysqld_error.h";
- static char *NAMEFILE= (char*) "mysqld_ername.h";
-@@ -91,6 +92,7 @@
- const char *sql_code1; /* sql state */
- const char *sql_code2; /* ODBC state */
- struct errors *next_error; /* Pointer to next error */
-+ my_bool is_padding; /* If true - padd this er_name while er_code != d_code*/
- DYNAMIC_ARRAY msg; /* All language texts for this error */
- };
-
-@@ -129,6 +131,7 @@
-
-
- static struct languages *parse_charset_string(char *str);
-+static struct errors *parse_padd_string(char *ptr, int er_count);
- static struct errors *parse_error_string(char *ptr, int er_count);
- static struct message *parse_message_string(struct message *new_message,
- char *str);
-@@ -253,6 +256,11 @@
-
- for (tmp_error= error_head; tmp_error; tmp_error= tmp_error->next_error)
- {
-+ if (tmp_error->is_padding)
-+ {
-+ er_last= tmp_error->d_code;
-+ continue;
-+ }
- /*
- generating mysqld_error.h
- fprintf() will automatically add \r on windows
-@@ -345,12 +353,29 @@
- "language\n", tmp_error->er_name, tmp_lang->lang_short_name);
- goto err;
- }
-- if (copy_rows(to, tmp->text, row_nr, start_pos))
-+ if (tmp_error->is_padding)
- {
-- fprintf(stderr, "Failed to copy rows to %s\n", outfile);
-- goto err;
-+ uint padd_to= tmp_error->d_code;
-+ char* padd_message= tmp->text;
-+ while ((row_nr+er_offset) < padd_to)
-+ {
-+ if (copy_rows(to, padd_message,row_nr,start_pos))
-+ {
-+ fprintf(stderr, "Failed to copy rows to %s\n", outfile);
-+ goto err;
-+ }
-+ row_nr++;
-+ }
-+ }
-+ else
-+ {
-+ if (copy_rows(to, tmp->text, row_nr, start_pos))
-+ {
-+ fprintf(stderr, "Failed to copy rows to %s\n", outfile);
-+ goto err;
-+ }
-+ row_nr++;
- }
-- row_nr++;
- }
-
- /* continue with header of the errmsg.sys file */
-@@ -501,14 +526,26 @@
- DBUG_RETURN(0);
- continue;
- }
-- if (is_prefix(str, ER_PREFIX) || is_prefix(str, WARN_PREFIX))
-+ if (is_prefix(str, ER_PREFIX) || is_prefix(str, WARN_PREFIX) || is_prefix(str, PADD_PREFIX))
- {
-- if (!(current_error= parse_error_string(str, rcount)))
-+ if (is_prefix(str, PADD_PREFIX))
- {
-- fprintf(stderr, "Failed to parse the error name string\n");
-- DBUG_RETURN(0);
-+ if (!(current_error= parse_padd_string(str, rcount)))
-+ {
-+ fprintf(stderr, "Failed to parse the error pad string\n");
-+ DBUG_RETURN(0);
-+ }
-+ rcount= current_error->d_code - er_offset; /* Count number of unique errors */
-+ }
-+ else
-+ {
-+ if (!(current_error= parse_error_string(str, rcount)))
-+ {
-+ fprintf(stderr, "Failed to parse the error name string\n");
-+ DBUG_RETURN(0);
-+ }
-+ rcount++; /* Count number of unique errors */
- }
-- rcount++; /* Count number of unique errors */
-
- /* add error to the list */
- *tail_error= current_error;
-@@ -849,78 +886,122 @@
- DBUG_RETURN(new_message);
- }
-
-+static struct errors* create_new_error(my_bool is_padding, char *er_name, int d_code, const char *sql_code1, const char *sql_code2)
-+{
-+ struct errors *new_error;
-+ DBUG_ENTER("create_new_error");
-+ /* create a new element */
-+ new_error= (struct errors *) my_malloc(sizeof(*new_error), MYF(MY_WME));
-+ if (my_init_dynamic_array(&new_error->msg, sizeof(struct message), 0, 0))
-+ DBUG_RETURN(0); /* OOM: Fatal error */
-+ new_error->is_padding= is_padding;
-+ DBUG_PRINT("info", ("is_padding: %s", (is_padding ? "true" : "false")));
-+ new_error->er_name= er_name;
-+ DBUG_PRINT("info", ("er_name: %s", er_name));
-+ new_error->d_code= d_code;
-+ DBUG_PRINT("info", ("d_code: %d", d_code));
-+ new_error->sql_code1= sql_code1;
-+ DBUG_PRINT("info", ("sql_code1: %s", sql_code1));
-+ new_error->sql_code2= sql_code2;
-+ DBUG_PRINT("info", ("sql_code2: %s", sql_code2));
-+ DBUG_RETURN(new_error);
-+}
-
- /*
-- Parsing the string with error name and codes; returns the pointer to
-+ Parsing the string with padd syntax (name + error to pad); returns the pointer to
- the errors struct
- */
-
--static struct errors *parse_error_string(char *str, int er_count)
-+static struct errors *parse_padd_string(char* str, int er_count)
- {
-- struct errors *new_error;
-+ char *er_name;
-+ uint d_code;
-+ char *start;
- DBUG_ENTER("parse_error_string");
- DBUG_PRINT("enter", ("str: %s", str));
-
-- /* create a new element */
-- new_error= (struct errors *) my_malloc(sizeof(*new_error), MYF(MY_WME));
-+ start= str;
-+ str= skip_delimiters(str);
-
-- if (my_init_dynamic_array(&new_error->msg, sizeof(struct message), 0, 0))
-+ /* getting the error name */
-+
-+ if (!(er_name= get_word(&str)))
- DBUG_RETURN(0); /* OOM: Fatal error */
-
-- /* getting the error name */
- str= skip_delimiters(str);
-
-- if (!(new_error->er_name= get_word(&str)))
-+ if (!(d_code= parse_error_offset(start)))
-+ {
-+ fprintf(stderr, "Failed to parse the error pad string '%s' '%s' (d_code doesn't parse)!\n",er_name,str);
-+ DBUG_RETURN(0);
-+ }
-+ if (d_code < (uint)(er_offset + er_count))
-+ {
-+ fprintf(stderr, "Error to padding less current error number!\n");
-+ DBUG_RETURN(0);
-+ }
-+ DBUG_RETURN(create_new_error(TRUE,er_name,d_code,empty_string,empty_string));
-+}
-+
-+/*
-+ Parsing the string with error name and codes; returns the pointer to
-+ the errors struct
-+*/
-+
-+static struct errors *parse_error_string(char *str, int er_count)
-+{
-+ char *er_name;
-+ int d_code;
-+ const char *sql_code1= empty_string;
-+ const char *sql_code2= empty_string;
-+ DBUG_ENTER("parse_error_string");
-+ DBUG_PRINT("enter", ("str: %s", str));
-+
-+ str= skip_delimiters(str);
-+
-+ /* getting the error name */
-+
-+ if (!(er_name= get_word(&str)))
- DBUG_RETURN(0); /* OOM: Fatal error */
-- DBUG_PRINT("info", ("er_name: %s", new_error->er_name));
-
- str= skip_delimiters(str);
-
- /* getting the code1 */
--
-- new_error->d_code= er_offset + er_count;
-- DBUG_PRINT("info", ("d_code: %d", new_error->d_code));
-+ d_code= er_offset + er_count;
-
- str= skip_delimiters(str);
-
- /* if we reached EOL => no more codes, but this can happen */
- if (!*str)
- {
-- new_error->sql_code1= empty_string;
-- new_error->sql_code2= empty_string;
- DBUG_PRINT("info", ("str: %s", str));
-- DBUG_RETURN(new_error);
-+ goto complete_create;
- }
--
- /* getting the sql_code 1 */
--
-- if (!(new_error->sql_code1= get_word(&str)))
-+ if (!(sql_code1= get_word(&str)))
- DBUG_RETURN(0); /* OOM: Fatal error */
-- DBUG_PRINT("info", ("sql_code1: %s", new_error->sql_code1));
-
- str= skip_delimiters(str);
-
- /* if we reached EOL => no more codes, but this can happen */
- if (!*str)
- {
-- new_error->sql_code2= empty_string;
- DBUG_PRINT("info", ("str: %s", str));
-- DBUG_RETURN(new_error);
-+ goto complete_create;
- }
--
- /* getting the sql_code 2 */
-- if (!(new_error->sql_code2= get_word(&str)))
-+ if (!(sql_code2= get_word(&str)))
- DBUG_RETURN(0); /* OOM: Fatal error */
-- DBUG_PRINT("info", ("sql_code2: %s", new_error->sql_code2));
-
- str= skip_delimiters(str);
-+
- if (*str)
- {
- fprintf(stderr, "The error line did not end with sql/odbc code!");
- DBUG_RETURN(0);
- }
--
-- DBUG_RETURN(new_error);
-+complete_create:
-+ DBUG_RETURN(create_new_error(FALSE,er_name,d_code,sql_code1,sql_code2));
- }
-
-
+++ /dev/null
---- a/mysql-test/t/file_contents.test
-+++ b/mysql-test/t/file_contents.test
-@@ -20,7 +20,7 @@
- $dir_docs = glob "$dir_docs/packages/MySQL-server*";
- } else {
- # RedHat: version number in directory name
-- $dir_docs = glob "$dir_docs/MySQL-server*";
-+ $dir_docs = glob "$dir_docs/Percona-Server-server*";
- }
- } elsif ($dir_bin =~ m|/usr$|) {
- # RPM build during development
-@@ -28,9 +28,12 @@
- if(-d "$dir_docs/packages") {
- # SuSE: "packages/" in the documentation path
- $dir_docs = glob "$dir_docs/packages/MySQL-server*";
-+ } elsif (glob "$dir_docs/percona-server-server*") {
-+ # Debian
-+ $dir_docs = glob "$dir_docs/percona-server-server*";
- } else {
- # RedHat: version number in directory name
-- $dir_docs = glob "$dir_docs/MySQL-server*";
-+ $dir_docs = glob "$dir_docs/Percona-Server-server*";
- }
- } else {
- # tar.gz package, Windows, or developer work (in BZR)
+++ /dev/null
---- a/include/my_sys.h
-+++ b/include/my_sys.h
-@@ -524,6 +524,8 @@
-
- #define my_b_tell(info) ((info)->pos_in_file + \
- (size_t) (*(info)->current_pos - (info)->request_pos))
-+#define my_b_write_tell(info) ((info)->pos_in_file + \
-+ ((info)->write_pos - (info)->write_buffer))
-
- #define my_b_get_buffer_start(info) (info)->request_pos
- #define my_b_get_bytes_in_buffer(info) (char*) (info)->read_end - \
---- a/include/mysql/plugin.h
-+++ b/include/mysql/plugin.h
-@@ -559,6 +559,8 @@
-
- #define EXTENDED_FOR_USERSTAT
-
-+#define EXTENDED_FOR_COMMIT_ORDERED
-+
- /**
- Create a temporary file.
-
---- a/sql/handler.cc
-+++ b/sql/handler.cc
-@@ -90,6 +90,8 @@
- static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
- uint known_extensions_id= 0;
-
-+static int commit_one_phase_low(THD *thd, bool all, THD_TRANS *trans,
-+ bool is_real_trans);
-
-
- static plugin_ref ha_default_plugin(THD *thd)
-@@ -1119,7 +1121,8 @@
- */
- bool is_real_trans= all || thd->transaction.all.ha_list == 0;
- Ha_trx_info *ha_info= trans->ha_list;
-- my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
-+ bool need_commit_ordered;
-+ my_xid xid;
- DBUG_ENTER("ha_commit_trans");
-
- /*
-@@ -1152,13 +1155,20 @@
- DBUG_RETURN(2);
- }
-
-- if (ha_info)
-+ if (!ha_info)
-+ {
-+ /* Free resources and perform other cleanup even for 'empty' transactions. */
-+ if (is_real_trans)
-+ thd->transaction.cleanup();
-+ DBUG_RETURN(0);
-+ }
-+ else
- {
- uint rw_ha_count;
- bool rw_trans;
- MDL_request mdl_request;
-
-- DBUG_EXECUTE_IF("crash_commit_before", DBUG_SUICIDE(););
-+ DBUG_EXECUTE_IF("crash_commit_before", abort(););
-
- /* Close all cursors that can not survive COMMIT */
- if (is_real_trans) /* not a statement commit */
-@@ -1197,57 +1207,80 @@
- !thd->slave_thread)
- {
- my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
-- ha_rollback_trans(thd, all);
-- error= 1;
-- goto end;
-+ goto err;
- }
-
-- if (!trans->no_2pc && (rw_ha_count > 1))
-+ if (trans->no_2pc || (rw_ha_count <= 1))
- {
-- for (; ha_info && !error; ha_info= ha_info->next())
-+ error= ha_commit_one_phase(thd, all);
-+ DBUG_EXECUTE_IF("crash_commit_after", DBUG_ABORT(););
-+ goto end;
-+ }
-+
-+ need_commit_ordered= FALSE;
-+ xid= thd->transaction.xid_state.xid.get_my_xid();
-+
-+ for (Ha_trx_info *hi= ha_info; hi; hi= hi->next())
- {
- int err;
-- handlerton *ht= ha_info->ht();
-+ handlerton *ht= hi->ht();
- /*
- Do not call two-phase commit if this particular
- transaction is read-only. This allows for simpler
- implementation in engines that are always read-only.
- */
-- if (! ha_info->is_trx_read_write())
-+ if (! hi->is_trx_read_write())
- continue;
- /*
- Sic: we know that prepare() is not NULL since otherwise
- trans->no_2pc would have been set.
- */
-- if ((err= ht->prepare(ht, thd, all)))
-- {
-- my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
-- error= 1;
-- }
-+ err= ht->prepare(ht, thd, all);
- status_var_increment(thd->status_var.ha_prepare_count);
-+ if (err)
-+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
-+
-+ if (err)
-+ goto err;
-+
-+ need_commit_ordered|= (ht->commit_ordered != NULL);
- }
-- DBUG_EXECUTE_IF("crash_commit_after_prepare", DBUG_SUICIDE(););
-- if (error || (is_real_trans && xid &&
-- (error= !(cookie= tc_log->log_xid(thd, xid)))))
-+ DBUG_EXECUTE_IF("crash_commit_after_prepare", DBUG_ABORT(););
-+
-+ if (!is_real_trans)
- {
-- ha_rollback_trans(thd, all);
-- error= 1;
-+ error= commit_one_phase_low(thd, all, trans, is_real_trans);
-+ DBUG_EXECUTE_IF("crash_commit_after", DBUG_ABORT(););
- goto end;
- }
-- DBUG_EXECUTE_IF("crash_commit_after_log", DBUG_SUICIDE(););
-- }
-- error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
-- DBUG_EXECUTE_IF("crash_commit_before_unlog", DBUG_SUICIDE(););
-- if (cookie)
-+
-+ cookie= tc_log->log_and_order(thd, xid, all, need_commit_ordered);
-+ if (!cookie)
-+ goto err;
-+
-+ DBUG_EXECUTE_IF("crash_commit_after_log", DBUG_ABORT(););
-+
-+ error= commit_one_phase_low(thd, all, trans, is_real_trans) ? 2 : 0;
-+ DBUG_EXECUTE_IF("crash_commit_after", DBUG_ABORT(););
-+ if (is_real_trans) /* userstat.patch */
-+ thd->diff_commit_trans++; /* userstat.patch */
-+ RUN_HOOK(transaction, after_commit, (thd, FALSE));
-+
-+ DBUG_EXECUTE_IF("crash_commit_before_unlog", DBUG_ABORT(););
- if(tc_log->unlog(cookie, xid))
- {
- error= 2;
- goto end;
- }
-- DBUG_EXECUTE_IF("crash_commit_after", DBUG_SUICIDE(););
-- if (is_real_trans)
-- thd->diff_commit_trans++;
-- RUN_HOOK(transaction, after_commit, (thd, FALSE));
-+
-+ DBUG_EXECUTE_IF("crash_commit_after", DBUG_ABORT(););
-+ goto end;
-+
-+ /* Come here if error and we need to rollback. */
-+err:
-+ error= 1; /* Transaction was rolled back */
-+ ha_rollback_trans(thd, all);
-+
- end:
- if (rw_trans && mdl_request.ticket)
- {
-@@ -1260,9 +1293,6 @@
- thd->mdl_context.release_lock(mdl_request.ticket);
- }
- }
-- /* Free resources and perform other cleanup even for 'empty' transactions. */
-- else if (is_real_trans)
-- thd->transaction.cleanup();
- DBUG_RETURN(error);
- }
-
-@@ -1279,7 +1309,6 @@
-
- int ha_commit_one_phase(THD *thd, bool all)
- {
-- int error=0;
- THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
- /*
- "real" is a nick name for a transaction for which a commit will
-@@ -1295,8 +1324,16 @@
- transaction.all.ha_list, see why in trans_register_ha()).
- */
- bool is_real_trans=all || thd->transaction.all.ha_list == 0;
-- Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
- DBUG_ENTER("ha_commit_one_phase");
-+ DBUG_RETURN(commit_one_phase_low(thd, all, trans, is_real_trans));
-+}
-+
-+static int
-+commit_one_phase_low(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans)
-+{
-+ int error= 0;
-+ Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
-+ DBUG_ENTER("commit_one_phase_low");
-
- if (ha_info)
- {
-@@ -1894,7 +1931,16 @@
- {
- bool warn= true;
-
-+ /*
-+ Holding the LOCK_commit_ordered mutex ensures that we get the same
-+ snapshot for all engines (including the binary log). This allows us
-+ among other things to do backups with
-+ START TRANSACTION WITH CONSISTENT SNAPSHOT and
-+ have a consistent binlog position.
-+ */
-+ mysql_mutex_lock(&LOCK_commit_ordered);
- plugin_foreach(thd, snapshot_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &warn);
-+ mysql_mutex_unlock(&LOCK_commit_ordered);
-
- /*
- Same idea as when one wants to CREATE TABLE in one engine which does not
---- a/sql/handler.h
-+++ b/sql/handler.h
-@@ -756,6 +756,53 @@
- and 'real commit' mean the same event.
- */
- int (*commit)(handlerton *hton, THD *thd, bool all);
-+ /*
-+ The commit_ordered() method is called prior to the commit() method, after
-+ the transaction manager has decided to commit (not rollback) the
-+ transaction. Unlike commit(), commit_ordered() is called only when the
-+ full transaction is committed, not for each commit of statement
-+ transaction in a multi-statement transaction.
-+
-+ Not that like prepare(), commit_ordered() is only called when 2-phase
-+ commit takes place. Ie. when no binary log and only a single engine
-+ participates in a transaction, one commit() is called, no
-+ commit_ordered(). So engines must be prepared for this.
-+
-+ The calls to commit_ordered() in multiple parallel transactions is
-+ guaranteed to happen in the same order in every participating
-+ handler. This can be used to ensure the same commit order among multiple
-+ handlers (eg. in table handler and binlog). So if transaction T1 calls
-+ into commit_ordered() of handler A before T2, then T1 will also call
-+ commit_ordered() of handler B before T2.
-+
-+ Engines that implement this method should during this call make the
-+ transaction visible to other transactions, thereby making the order of
-+ transaction commits be defined by the order of commit_ordered() calls.
-+
-+ The intention is that commit_ordered() should do the minimal amount of
-+ work that needs to happen in consistent commit order among handlers. To
-+ preserve ordering, calls need to be serialised on a global mutex, so
-+ doing any time-consuming or blocking operations in commit_ordered() will
-+ limit scalability.
-+
-+ Handlers can rely on commit_ordered() calls to be serialised (no two
-+ calls can run in parallel, so no extra locking on the handler part is
-+ required to ensure this).
-+
-+ Note that commit_ordered() can be called from a different thread than the
-+ one handling the transaction! So it can not do anything that depends on
-+ thread local storage, in particular it can not call my_error() and
-+ friends (instead it can store the error code and delay the call of
-+ my_error() to the commit() method).
-+
-+ Similarly, since commit_ordered() returns void, any return error code
-+ must be saved and returned from the commit() method instead.
-+
-+ The commit_ordered method is optional, and can be left unset if not
-+ needed in a particular handler (then there will be no ordering guarantees
-+ wrt. other engines and binary log).
-+ */
-+ void (*commit_ordered)(handlerton *hton, THD *thd, bool all);
- int (*rollback)(handlerton *hton, THD *thd, bool all);
- int (*prepare)(handlerton *hton, THD *thd, bool all);
- int (*recover)(handlerton *hton, XID *xid_list, uint len);
---- a/sql/log.cc
-+++ b/sql/log.cc
-@@ -71,6 +71,25 @@
- static int binlog_rollback(handlerton *hton, THD *thd, bool all);
- static int binlog_prepare(handlerton *hton, THD *thd, bool all);
-
-+static LEX_STRING const write_error_msg=
-+ { C_STRING_WITH_LEN("error writing to the binary log") };
-+
-+static my_bool mutexes_inited;
-+mysql_mutex_t LOCK_group_commit_queue;
-+mysql_mutex_t LOCK_commit_ordered;
-+
-+static ulonglong binlog_status_var_num_commits;
-+static ulonglong binlog_status_var_num_group_commits;
-+
-+static SHOW_VAR binlog_status_vars_detail[]=
-+{
-+ {"commits",
-+ (char *)&binlog_status_var_num_commits, SHOW_LONGLONG},
-+ {"group_commits",
-+ (char *)&binlog_status_var_num_group_commits, SHOW_LONGLONG},
-+ {NullS, NullS, SHOW_LONG}
-+};
-+
- /**
- purge logs, master and slave sides both, related error code
- convertor.
-@@ -167,41 +186,6 @@
- }
-
- /*
-- Helper class to hold a mutex for the duration of the
-- block.
--
-- Eliminates the need for explicit unlocking of mutexes on, e.g.,
-- error returns. On passing a null pointer, the sentry will not do
-- anything.
-- */
--class Mutex_sentry
--{
--public:
-- Mutex_sentry(mysql_mutex_t *mutex)
-- : m_mutex(mutex)
-- {
-- if (m_mutex)
-- mysql_mutex_lock(mutex);
-- }
--
-- ~Mutex_sentry()
-- {
-- if (m_mutex)
-- mysql_mutex_unlock(m_mutex);
--#ifndef DBUG_OFF
-- m_mutex= 0;
--#endif
-- }
--
--private:
-- mysql_mutex_t *m_mutex;
--
-- // It's not allowed to copy this object in any way
-- Mutex_sentry(Mutex_sentry const&);
-- void operator=(Mutex_sentry const&);
--};
--
--/*
- Helper classes to store non-transactional and transactional data
- before copying it to the binary log.
- */
-@@ -211,7 +195,8 @@
- binlog_cache_data(): m_pending(0), before_stmt_pos(MY_OFF_T_UNDEF),
- incident(FALSE), changes_to_non_trans_temp_table_flag(FALSE),
- saved_max_binlog_cache_size(0), ptr_binlog_cache_use(0),
-- ptr_binlog_cache_disk_use(0)
-+ ptr_binlog_cache_disk_use(0), commit_bin_log_file_pos(0),
-+ using_xa(FALSE), xa_xid(0)
- { }
-
- ~binlog_cache_data()
-@@ -270,6 +255,8 @@
- variable after truncating the cache.
- */
- cache_log.disk_writes= 0;
-+ using_xa= FALSE;
-+ commit_bin_log_file_pos= 0;
- DBUG_ASSERT(empty());
- }
-
-@@ -411,6 +398,20 @@
-
- binlog_cache_data& operator=(const binlog_cache_data& info);
- binlog_cache_data(const binlog_cache_data& info);
-+
-+public:
-+ /*
-+ Binlog position after current commit, available to storage engines during
-+ commit_ordered() and commit().
-+ */
-+ ulonglong commit_bin_log_file_pos;
-+
-+ /*
-+ Flag set true if this transaction is committed with log_xid() as part of
-+ XA, false if not.
-+ */
-+ bool using_xa;
-+ my_xid xa_xid;
- };
-
- class binlog_cache_mngr {
-@@ -1624,7 +1625,7 @@
- */
- static inline int
- binlog_flush_cache(THD *thd, binlog_cache_data* cache_data, Log_event *end_evt,
-- bool is_transactional)
-+ bool is_transactional, bool all)
- {
- DBUG_ENTER("binlog_flush_cache");
- int error= 0;
-@@ -1643,8 +1644,8 @@
- were, we would have to ensure that we're not ending a statement
- inside a stored function.
- */
-- error= mysql_bin_log.write(thd, &cache_data->cache_log, end_evt,
-- cache_data->has_incident());
-+ error= mysql_bin_log.write_transaction_to_binlog(thd, cache_data,
-+ end_evt, all);
- }
- cache_data->reset();
-
-@@ -1663,12 +1664,12 @@
- */
- static inline int
- binlog_commit_flush_stmt_cache(THD *thd,
-- binlog_cache_mngr *cache_mngr)
-+ binlog_cache_mngr *cache_mngr, bool all)
- {
- Query_log_event end_evt(thd, STRING_WITH_LEN("COMMIT"),
- FALSE, FALSE, TRUE, 0);
- return (binlog_flush_cache(thd, &cache_mngr->stmt_cache, &end_evt,
-- FALSE));
-+ FALSE, all));
- }
-
- /**
-@@ -1681,12 +1682,12 @@
- nonzero if an error pops up when flushing the cache.
- */
- static inline int
--binlog_commit_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr)
-+binlog_commit_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr, bool all)
- {
- Query_log_event end_evt(thd, STRING_WITH_LEN("COMMIT"),
- TRUE, FALSE, TRUE, 0);
- return (binlog_flush_cache(thd, &cache_mngr->trx_cache, &end_evt,
-- TRUE));
-+ TRUE, all));
- }
-
- /**
-@@ -1699,12 +1700,12 @@
- nonzero if an error pops up when flushing the cache.
- */
- static inline int
--binlog_rollback_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr)
-+binlog_rollback_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr, bool all)
- {
- Query_log_event end_evt(thd, STRING_WITH_LEN("ROLLBACK"),
- TRUE, FALSE, TRUE, 0);
- return (binlog_flush_cache(thd, &cache_mngr->trx_cache, &end_evt,
-- TRUE));
-+ TRUE, all));
- }
-
- /**
-@@ -1719,11 +1720,11 @@
- */
- static inline int
- binlog_commit_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr,
-- my_xid xid)
-+ my_xid xid, bool all)
- {
- Xid_log_event end_evt(thd, xid);
- return (binlog_flush_cache(thd, &cache_mngr->trx_cache, &end_evt,
-- TRUE));
-+ TRUE, all));
- }
-
- /**
-@@ -1785,7 +1786,7 @@
- do nothing.
- just pretend we can do 2pc, so that MySQL won't
- switch to 1pc.
-- real work will be done in MYSQL_BIN_LOG::log_xid()
-+ real work will be done in MYSQL_BIN_LOG::log_and_order()
- */
- return 0;
- }
-@@ -1818,7 +1819,7 @@
-
- if (!cache_mngr->stmt_cache.empty())
- {
-- error= binlog_commit_flush_stmt_cache(thd, cache_mngr);
-+ error= binlog_commit_flush_stmt_cache(thd, cache_mngr, all);
- }
-
- if (cache_mngr->trx_cache.empty())
-@@ -1837,7 +1838,7 @@
- Otherwise, we accumulate the changes.
- */
- if (!error && ending_trans(thd, all))
-- error= binlog_commit_flush_trx_cache(thd, cache_mngr);
-+ error= binlog_commit_flush_trx_cache(thd, cache_mngr, all);
-
- /*
- This is part of the stmt rollback.
-@@ -1881,7 +1882,7 @@
- }
- else if (!cache_mngr->stmt_cache.empty())
- {
-- error= binlog_commit_flush_stmt_cache(thd, cache_mngr);
-+ error= binlog_commit_flush_stmt_cache(thd, cache_mngr, all);
- }
-
- if (cache_mngr->trx_cache.empty())
-@@ -1929,7 +1930,7 @@
- (trans_has_updated_non_trans_table(thd) &&
- ending_single_stmt_trans(thd,all) &&
- thd->variables.binlog_format == BINLOG_FORMAT_MIXED)))
-- error= binlog_rollback_flush_trx_cache(thd, cache_mngr);
-+ error= binlog_rollback_flush_trx_cache(thd, cache_mngr, all);
- /*
- Truncate the cache if:
- . aborting a single or multi-statement transaction or;
-@@ -2904,6 +2905,7 @@
- MYSQL_BIN_LOG::MYSQL_BIN_LOG(uint *sync_period)
- :bytes_written(0), prepared_xids(0), file_id(1), open_count(1),
- need_start_event(TRUE),
-+ group_commit_queue(0), num_commits(0), num_group_commits(0),
- sync_period_ptr(sync_period),
- is_relay_log(0), signal_cnt(0),
- description_event_for_exec(0), description_event_for_queue(0)
-@@ -5361,19 +5363,15 @@
- SYNOPSIS
- write_cache()
- cache Cache to write to the binary log
-- lock_log True if the LOCK_log mutex should be aquired, false otherwise
-- sync_log True if the log should be flushed and synced
-
- DESCRIPTION
- Write the contents of the cache to the binary log. The cache will
- be reset as a READ_CACHE to be able to read the contents from it.
- */
-
--int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache,
-- bool lock_log, bool sync_log)
-+int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache)
- {
-- Mutex_sentry sentry(lock_log ? &LOCK_log : NULL);
--
-+ mysql_mutex_assert_owner(&LOCK_log);
- if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
- return ER_ERROR_ON_WRITE;
- uint length= my_b_bytes_in_cache(cache), group, carry, hdr_offs;
-@@ -5484,6 +5482,8 @@
- }
-
- /* Write data to the binary log file */
-+ DBUG_EXECUTE_IF("fail_binlog_write_1",
-+ errno= 28; return ER_ERROR_ON_WRITE;);
- if (my_b_write(&log_file, cache->read_pos, length))
- return ER_ERROR_ON_WRITE;
- thd->binlog_bytes_written+= length;
-@@ -5492,9 +5492,6 @@
-
- DBUG_ASSERT(carry == 0);
-
-- if (sync_log)
-- return flush_and_sync(0);
--
- return 0; // All OK
- }
-
-@@ -5535,8 +5532,6 @@
- if (!is_open())
- DBUG_RETURN(error);
-
-- LEX_STRING const write_error_msg=
-- { C_STRING_WITH_LEN("error writing to the binary log") };
- Incident incident= INCIDENT_LOST_EVENTS;
- Incident_log_event ev(thd, incident, write_error_msg);
- if (lock)
-@@ -5585,112 +5580,332 @@
- 'cache' needs to be reinitialized after this functions returns.
- */
-
--bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event,
-- bool incident)
-+bool
-+MYSQL_BIN_LOG::write_transaction_to_binlog(THD *thd, binlog_cache_data *cache_data,
-+ Log_event *end_ev, bool all)
-+{
-+ group_commit_entry entry;
-+ bool ret;
-+ DBUG_ENTER("MYSQL_BIN_LOG::write_transaction_to_binlog");
-+
-+ entry.thd= thd;
-+ entry.cache_data= cache_data;
-+ entry.error= 0;
-+ entry.all= all;
-+
-+ /*
-+ Log "BEGIN" at the beginning of every transaction. Here, a transaction is
-+ either a BEGIN..COMMIT block or a single statement in autocommit mode.
-+
-+ Create the necessary events here, where we have the correct THD (and
-+ thread context).
-+
-+ Due to group commit the actual writing to binlog may happen in a different
-+ thread.
-+ */
-+ Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE, TRUE, 0);
-+ entry.begin_event= &qinfo;
-+ entry.end_event= end_ev;
-+ if (cache_data->has_incident())
-+ {
-+ Incident_log_event inc_ev(thd, INCIDENT_LOST_EVENTS, write_error_msg);
-+ entry.incident_event= &inc_ev;
-+ ret = write_transaction_to_binlog_events(&entry);
-+ }
-+ else
-+ {
-+ entry.incident_event= NULL;
-+ ret = write_transaction_to_binlog_events(&entry);
-+ }
-+ if (!ret) /* userstat.patch */
-+ thd->binlog_bytes_written += qinfo.data_written; /* userstat.patch */
-+ DBUG_RETURN(ret);
-+}
-+
-+bool
-+MYSQL_BIN_LOG::write_transaction_to_binlog_events(group_commit_entry *entry)
- {
-- DBUG_ENTER("MYSQL_BIN_LOG::write(THD *, IO_CACHE *, Log_event *)");
-+ /*
-+ To facilitate group commit for the binlog, we first queue up ourselves in
-+ the group commit queue. Then the first thread to enter the queue waits for
-+ the LOCK_log mutex, and commits for everyone in the queue once it gets the
-+ lock. Any other threads in the queue just wait for the first one to finish
-+ the commit and wake them up.
-+ */
-+ entry->thd->clear_wakeup_ready();
-+ mysql_mutex_lock(&LOCK_group_commit_queue);
-+ group_commit_entry *orig_queue= group_commit_queue;
-+ entry->next= orig_queue;
-+ group_commit_queue= entry;
-+ DEBUG_SYNC(entry->thd, "commit_group_commit_queue");
-+ mysql_mutex_unlock(&LOCK_group_commit_queue);
-+
-+ /*
-+ The first in the queue handle group commit for all; the others just wait
-+ to be signalled when group commit is done.
-+ */
-+ if (orig_queue != NULL)
-+ entry->thd->wait_for_wakeup_ready();
-+ else
-+ trx_group_commit_leader(entry);
-+
-+ if (likely(!entry->error))
-+ return 0;
-+
-+ switch (entry->error)
-+ {
-+ case ER_ERROR_ON_WRITE:
-+ my_error(ER_ERROR_ON_WRITE, MYF(ME_NOREFRESH), name, entry->commit_errno);
-+ break;
-+ case ER_ERROR_ON_READ:
-+ my_error(ER_ERROR_ON_READ, MYF(ME_NOREFRESH),
-+ entry->cache_data->cache_log.file_name, entry->commit_errno);
-+ break;
-+ default:
-+ /*
-+ There are not (and should not be) any errors thrown not covered above.
-+ But just in case one is added later without updating the above switch
-+ statement, include a catch-all.
-+ */
-+ my_printf_error(entry->error,
-+ "Error writing transaction to binary log: %d",
-+ MYF(ME_NOREFRESH), entry->error);
-+ }
-
-+ /*
-+ Since we return error, this transaction XID will not be committed, so
-+ we need to mark it as not needed for recovery (unlog() is not called
-+ for a transaction if log_xid() fails).
-+ */
-+ if (entry->cache_data->using_xa && entry->cache_data->xa_xid)
-+ mark_xid_done();
-+
-+ return 1;
-+}
-+
-+/*
-+ Do binlog group commit as the lead thread.
-+
-+ This must be called when this thread/transaction is queued at the start of
-+ the group_commit_queue. It will wait to obtain the LOCK_log mutex, then group
-+ commit all the transactions in the queue (more may have entered while waiting
-+ for LOCK_log). After commit is done, all other threads in the queue will be
-+ signalled.
-+
-+ */
-+void
-+MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader)
-+{
-+ DBUG_ENTER("MYSQL_BIN_LOG::trx_group_commit_leader");
-+ uint xid_count= 0;
-+ uint write_count= 0;
-+ bool check_purge= false;
-+ group_commit_entry *current= 0;
- DBUG_ASSERT(is_open());
- if (likely(is_open())) // Should always be true
- {
-- bool check_purge;
--
-+ /*
-+ Lock the LOCK_log(), and once we get it, collect any additional writes
-+ that queued up while we were waiting.
-+ */
- mysql_mutex_lock(&LOCK_log);
-+
-+ DEBUG_SYNC(leader->thd, "commit_after_get_LOCK_log");
-+ mysql_mutex_lock(&LOCK_group_commit_queue);
-+ current= group_commit_queue;
-+ group_commit_queue= NULL;
-+ mysql_mutex_unlock(&LOCK_group_commit_queue);
-+
-+ /* As the queue is in reverse order of entering, reverse it. */
-+ group_commit_entry *queue= NULL;
-+ while (current)
-+ {
-+ group_commit_entry *next= current->next;
-+ current->next= queue;
-+ queue= current;
-+ current= next;
-+ }
-+ DBUG_ASSERT(leader == queue /* the leader should be first in queue */);
- /*
-- We only bother to write to the binary log if there is anything
-- to write.
-- */
-- if (my_b_tell(cache) > 0)
-+ Now we have in queue the list of transactions to be committed in order.
-+
-+ Commit every transaction in the queue.
-+
-+ Note that we are doing this in a different thread than the one running
-+ the transaction! So we are limited in the operations we can do. In
-+ particular, we cannot call my_error() on behalf of a transaction, as
-+ that obtains the THD from thread local storage. Instead, we must set
-+ current->error and let the thread do the error reporting itself once
-+ we wake it up.
-+ */
-+ for (current= queue; current != NULL; current= current->next)
- {
-+ binlog_cache_data *cache_data= current->cache_data;
-+ IO_CACHE *cache= &cache_data->cache_log;
-+
- /*
-- Log "BEGIN" at the beginning of every transaction. Here, a
-- transaction is either a BEGIN..COMMIT block or a single
-- statement in autocommit mode.
-+ We only bother to write to the binary log if there is anything
-+ to write.
- */
-- Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE, TRUE, 0);
-- if (qinfo.write(&log_file))
-- goto err;
-- thd->binlog_bytes_written+= qinfo.data_written;
-- DBUG_EXECUTE_IF("crash_before_writing_xid",
-- {
-- if ((write_error= write_cache(thd, cache, false, true)))
-- DBUG_PRINT("info", ("error writing binlog cache: %d",
-- write_error));
-- DBUG_PRINT("info", ("crashing before writing xid"));
-- DBUG_SUICIDE();
-- });
--
-- if ((write_error= write_cache(thd, cache, false, false)))
-- goto err;
--
-- if (commit_event && commit_event->write(&log_file))
-- goto err;
-- if (commit_event)
-- thd->binlog_bytes_written+= commit_event->data_written;
-+ if (my_b_tell(cache) > 0)
-+ {
-+ if ((current->error= write_transaction(current)))
-+ current->commit_errno= errno;
-+ write_count++;
-+ }
-
-- if (incident && write_incident(thd, FALSE))
-- goto err;
-+ cache_data->commit_bin_log_file_pos= my_b_write_tell(&log_file);
-+ if (cache_data->using_xa && cache_data->xa_xid)
-+ xid_count++;
-+ }
-
-+ if (write_count > 0)
-+ {
- bool synced= 0;
- if (flush_and_sync(&synced))
-- goto err;
-- DBUG_EXECUTE_IF("half_binlogged_transaction", DBUG_SUICIDE(););
-- if (cache->error) // Error on read
- {
-- sql_print_error(ER(ER_ERROR_ON_READ), cache->file_name, errno);
-- write_error=1; // Don't give more errors
-- goto err;
-+ for (current= queue; current != NULL; current= current->next)
-+ {
-+ if (!current->error)
-+ {
-+ current->error= ER_ERROR_ON_WRITE;
-+ current->commit_errno= errno;
-+ }
-+ }
-+ }
-+ else
-+ {
-+ signal_update();
- }
-
- if (RUN_HOOK(binlog_storage, after_flush,
-- (thd, log_file_name, log_file.pos_in_file, synced)))
-+ (leader->thd, log_file_name, log_file.pos_in_file, synced)))
- {
- sql_print_error("Failed to run 'after_flush' hooks");
-- write_error=1;
-- goto err;
-+ for (current= queue; current != NULL; current= current->next)
-+ {
-+ if (!current->error)
-+ {
-+ current->error= ER_ERROR_ON_WRITE;
-+ current->commit_errno= errno;
-+ }
-+ }
- }
-
-- signal_update();
- }
-
- /*
-- if commit_event is Xid_log_event, increase the number of
-- prepared_xids (it's decreasd in ::unlog()). Binlog cannot be rotated
-+ if any commit_events are Xid_log_event, increase the number of
-+ prepared_xids (it's decreased in ::unlog()). Binlog cannot be rotated
- if there're prepared xids in it - see the comment in new_file() for
- an explanation.
-- If the commit_event is not Xid_log_event (then it's a Query_log_event)
-- rotate binlog, if necessary.
-+ If no Xid_log_events (then it's all Query_log_event) rotate binlog,
-+ if necessary.
- */
-- if (commit_event && commit_event->get_type_code() == XID_EVENT)
-+ if (xid_count > 0)
- {
-- mysql_mutex_lock(&LOCK_prep_xids);
-- prepared_xids++;
-- mysql_mutex_unlock(&LOCK_prep_xids);
-- mysql_mutex_unlock(&LOCK_log);
-+ mark_xids_active(xid_count);
- }
- else
- {
- if (rotate(false, &check_purge))
-- goto err;
-- mysql_mutex_unlock(&LOCK_log);
-- if (check_purge)
-- purge();
-+ {
-+ for (current= queue; current != NULL; current= current->next)
-+ {
-+ if (!current->error)
-+ {
-+ current->error= ER_ERROR_ON_WRITE;
-+ current->commit_errno= errno;
-+ }
-+ }
-+ }
- }
-- }
-
-- DBUG_RETURN(0);
-+ DEBUG_SYNC(leader->thd, "commit_before_get_LOCK_commit_ordered");
-+ mysql_mutex_lock(&LOCK_commit_ordered);
-+ /*
-+ We cannot unlock LOCK_log until we have locked LOCK_commit_ordered;
-+ otherwise scheduling could allow the next group commit to run ahead of us,
-+ messing up the order of commit_ordered() calls. But as soon as
-+ LOCK_commit_ordered is obtained, we can let the next group commit start.
-+ */
-
--err:
-- if (!write_error)
-- {
-- write_error= 1;
-- sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
-+ mysql_mutex_unlock(&LOCK_log);
-+
-+ if (xid_count > 0 && check_purge)
-+ {
-+ purge();
-+ }
-+
-+ DEBUG_SYNC(leader->thd, "commit_after_release_LOCK_log");
-+ ++num_group_commits;
-+
-+ /*
-+ Wakeup each participant waiting for our group commit, first calling the
-+ commit_ordered() methods for any transactions doing 2-phase commit.
-+ */
-+ current= queue;
-+ while (current != NULL)
-+ {
-+ group_commit_entry *next;
-+
-+ DEBUG_SYNC(leader->thd, "commit_loop_entry_commit_ordered");
-+ ++num_commits;
-+ if (current->cache_data->using_xa && !current->error)
-+ run_commit_ordered(current->thd, current->all);
-+
-+ /*
-+ Careful not to access current->next after waking up the other thread! As
-+ it may change immediately after wakeup.
-+ */
-+ next= current->next;
-+ if (current != leader) // Don't wake up ourself
-+ current->thd->signal_wakeup_ready();
-+ current= next;
-+ }
-+ DEBUG_SYNC(leader->thd, "commit_after_group_run_commit_ordered");
-+ mysql_mutex_unlock(&LOCK_commit_ordered);
- }
-- mysql_mutex_unlock(&LOCK_log);
-- DBUG_RETURN(1);
-+
-+ DBUG_VOID_RETURN;
- }
-
-
-+int
-+MYSQL_BIN_LOG::write_transaction(group_commit_entry *entry)
-+{
-+ binlog_cache_data *cache_data= entry->cache_data;
-+ IO_CACHE *cache= &cache_data->cache_log;
-+
-+ if (entry->begin_event->write(&log_file))
-+ return ER_ERROR_ON_WRITE;
-+
-+ DBUG_EXECUTE_IF("crash_before_writing_xid",
-+ {
-+ if ((write_cache(entry->thd, cache)))
-+ DBUG_PRINT("info", ("error writing binlog cache"));
-+ else
-+ flush_and_sync(0);
-+
-+ DBUG_PRINT("info", ("crashing before writing xid"));
-+ abort();
-+ });
-+
-+ if (write_cache(entry->thd, cache))
-+ return ER_ERROR_ON_WRITE;
-+
-+ if (entry->end_event->write(&log_file))
-+ return ER_ERROR_ON_WRITE;
-+
-+ if (entry->incident_event && entry->incident_event->write(&log_file))
-+ return ER_ERROR_ON_WRITE;
-+
-+ if (cache->error) // Error on read
-+ return ER_ERROR_ON_READ;
-+
-+ return 0;
-+}
-+
- /**
- Wait until we get a signal that the relay log has been updated.
-
-@@ -6095,6 +6310,68 @@
- }
-
-
-+void
-+TC_init()
-+{
-+ mysql_mutex_init(key_LOCK_group_commit_queue, &LOCK_group_commit_queue, MY_MUTEX_INIT_SLOW);
-+ mysql_mutex_init(key_LOCK_commit_ordered, &LOCK_commit_ordered, MY_MUTEX_INIT_SLOW);
-+ mutexes_inited= TRUE;
-+}
-+
-+
-+void
-+TC_destroy()
-+{
-+ if (mutexes_inited)
-+ {
-+ mysql_mutex_destroy(&LOCK_group_commit_queue);
-+ mysql_mutex_destroy(&LOCK_commit_ordered);
-+ mutexes_inited= FALSE;
-+ }
-+}
-+
-+
-+void
-+TC_LOG::run_commit_ordered(THD *thd, bool all)
-+{
-+ Ha_trx_info *ha_info=
-+ all ? thd->transaction.all.ha_list : thd->transaction.stmt.ha_list;
-+
-+ mysql_mutex_assert_owner(&LOCK_commit_ordered);
-+ for (; ha_info; ha_info= ha_info->next())
-+ {
-+ handlerton *ht= ha_info->ht();
-+ if (!ht->commit_ordered)
-+ continue;
-+ ht->commit_ordered(ht, thd, all);
-+ DEBUG_SYNC(thd, "commit_after_run_commit_ordered");
-+ }
-+}
-+
-+int TC_LOG_MMAP::log_and_order(THD *thd, my_xid xid, bool all,
-+ bool need_commit_ordered)
-+{
-+ int cookie;
-+
-+ cookie= 0;
-+ if (xid)
-+ cookie= log_one_transaction(xid);
-+
-+ if (need_commit_ordered)
-+ {
-+ /* Only run commit_ordered() if log_xid was successful. */
-+ if (cookie)
-+ {
-+ mysql_mutex_lock(&LOCK_commit_ordered);
-+ run_commit_ordered(thd, all);
-+ mysql_mutex_unlock(&LOCK_commit_ordered);
-+ }
-+ }
-+
-+ return cookie;
-+}
-+
-+
- /********* transaction coordinator log for 2pc - mmap() based solution *******/
-
- /*
-@@ -6231,6 +6508,7 @@
- mysql_mutex_init(key_LOCK_pool, &LOCK_pool, MY_MUTEX_INIT_FAST);
- mysql_cond_init(key_COND_active, &COND_active, 0);
- mysql_cond_init(key_COND_pool, &COND_pool, 0);
-+ mysql_cond_init(key_COND_queue_busy, &COND_queue_busy, 0);
-
- inited=6;
-
-@@ -6238,6 +6516,8 @@
- active=pages;
- pool=pages+1;
- pool_last=pages+npages-1;
-+ commit_ordered_queue= NULL;
-+ commit_ordered_queue_busy= false;
-
- return 0;
-
-@@ -6343,7 +6623,7 @@
- to the position in memory where xid was logged to.
- */
-
--int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid)
-+int TC_LOG_MMAP::log_one_transaction(my_xid xid)
- {
- int err;
- PAGE *p;
-@@ -6482,7 +6762,9 @@
- mysql_mutex_destroy(&LOCK_sync);
- mysql_mutex_destroy(&LOCK_active);
- mysql_mutex_destroy(&LOCK_pool);
-+ mysql_cond_destroy(&COND_active);
- mysql_cond_destroy(&COND_pool);
-+ mysql_cond_destroy(&COND_queue_busy);
- case 5:
- data[0]='A'; // garble the first (signature) byte, in case mysql_file_delete fails
- case 4:
-@@ -6692,42 +6974,87 @@
- mysql_cond_destroy(&COND_prep_xids);
- }
-
--/**
-- @todo
-- group commit
-+/*
-+ Do a binlog log_xid() for a group of transactions, linked through
-+ thd->next_commit_ordered.
-
- @retval
- 0 error
- @retval
- 1 success
- */
--int TC_LOG_BINLOG::log_xid(THD *thd, my_xid xid)
-+int TC_LOG_BINLOG::log_and_order(THD *thd, my_xid xid, bool all,
-+ bool need_commit_ordered __attribute__((unused)))
- {
-- DBUG_ENTER("TC_LOG_BINLOG::log");
-+ DBUG_ENTER("TC_LOG_BINLOG::log_and_order");
- binlog_cache_mngr *cache_mngr=
- (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
-+
-+ cache_mngr->trx_cache.using_xa= TRUE;
-+ cache_mngr->trx_cache.xa_xid= xid;
- /*
- We always commit the entire transaction when writing an XID. Also
- note that the return value is inverted.
- */
-- DBUG_RETURN(!binlog_commit_flush_stmt_cache(thd, cache_mngr) &&
-- !binlog_commit_flush_trx_cache(thd, cache_mngr, xid));
-+ DBUG_RETURN(!binlog_commit_flush_stmt_cache(thd, cache_mngr, all) &&
-+ !binlog_commit_flush_trx_cache(thd, cache_mngr, xid, all));
- }
-
--int TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
-+/*
-+ After an XID is logged, we need to hold on to the current binlog file until
-+ it is fully committed in the storage engine. The reason is that crash
-+ recovery only looks at the latest binlog, so we must make sure there are no
-+ outstanding prepared (but not committed) transactions before rotating the
-+ binlog.
-+
-+ To handle this, we keep a count of outstanding XIDs. This function is used
-+ to increase this count when committing one or more transactions to the
-+ binary log.
-+*/
-+void
-+TC_LOG_BINLOG::mark_xids_active(uint xid_count)
- {
-- DBUG_ENTER("TC_LOG_BINLOG::unlog");
-+ DBUG_ENTER("TC_LOG_BINLOG::mark_xids_active");
-+ DBUG_PRINT("info", ("xid_count=%u", xid_count));
-+ mysql_mutex_lock(&LOCK_prep_xids);
-+ prepared_xids+= xid_count;
-+ mysql_mutex_unlock(&LOCK_prep_xids);
-+ DBUG_VOID_RETURN;
-+}
-+
-+/*
-+ Once an XID is committed, it is safe to rotate the binary log, as it can no
-+ longer be needed during crash recovery.
-+
-+ This function is called to mark an XID this way. It needs to decrease the
-+ count of pending XIDs, and signal the log rotator thread when it reaches zero.
-+*/
-+void
-+TC_LOG_BINLOG::mark_xid_done()
-+{
-+ my_bool send_signal;
-+
-+ DBUG_ENTER("TC_LOG_BINLOG::mark_xid_done");
- mysql_mutex_lock(&LOCK_prep_xids);
- // prepared_xids can be 0 if the transaction had ignorable errors.
- DBUG_ASSERT(prepared_xids >= 0);
- if (prepared_xids > 0)
- prepared_xids--;
-- if (prepared_xids == 0) {
-+ send_signal= (prepared_xids == 0);
-+ mysql_mutex_unlock(&LOCK_prep_xids);
-+ if (send_signal) {
- DBUG_PRINT("info", ("prepared_xids=%lu", prepared_xids));
- mysql_cond_signal(&COND_prep_xids);
- }
-- mysql_mutex_unlock(&LOCK_prep_xids);
-- DBUG_RETURN(rotate_and_purge(0)); // as ::write() did not rotate
-+ DBUG_VOID_RETURN;
-+}
-+
-+int TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
-+{
-+ DBUG_ENTER("TC_LOG_BINLOG::unlog");
-+ if (xid)
-+ mark_xid_done();
-+ DBUG_RETURN(rotate_and_purge(0));
- }
-
- int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle)
-@@ -6796,9 +7123,67 @@
- {
- return (ulonglong) mysql_bin_log.get_log_file()->pos_in_file;
- }
-+/*
-+ Get the current position of the MySQL binlog for transaction currently being
-+ committed.
-+
-+ This is valid to call from within storage engine commit_ordered() and
-+ commit() methods only.
-+
-+ Since it stores the position inside THD, it is safe to call without any
-+ locking.
-+
-+ Note that currently the binlog file name is not stored inside THD, but this
-+ is still safe as it can only change when the log is rotated, and we never
-+ rotate the binlog while commits are pending inside storage engines.
-+*/
-+extern "C"
-+void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file)
-+{
-+ binlog_cache_mngr *cache_mngr;
-+ if (binlog_hton->state == SHOW_OPTION_YES
-+ && (cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton)))
-+ {
-+ *out_pos= cache_mngr->trx_cache.commit_bin_log_file_pos;
-+ *out_file= mysql_bin_log.get_log_fname();
-+ }
-+ else
-+ {
-+ *out_pos= 0ULL;
-+ *out_file= NULL;
-+ }
-+}
- #endif /* INNODB_COMPATIBILITY_HOOKS */
-
-
-+static int show_binlog_vars(THD *thd, SHOW_VAR *var, char *buff)
-+{
-+ mysql_bin_log.set_status_variables();
-+ var->type= SHOW_ARRAY;
-+ var->value= (char *)&binlog_status_vars_detail;
-+ return 0;
-+}
-+
-+static SHOW_VAR binlog_status_vars_top[]= {
-+ {"binlog", (char *) &show_binlog_vars, SHOW_FUNC},
-+ {NullS, NullS, SHOW_LONG}
-+};
-+
-+/*
-+ Copy out current values of status variables, for SHOW STATUS or
-+ information_schema.global_status.
-+
-+ This is called only under LOCK_status, so we can fill in a static array.
-+*/
-+void
-+TC_LOG_BINLOG::set_status_variables()
-+{
-+ mysql_mutex_lock(&LOCK_commit_ordered);
-+ binlog_status_var_num_commits= this->num_commits;
-+ binlog_status_var_num_group_commits= this->num_group_commits;
-+ mysql_mutex_unlock(&LOCK_commit_ordered);
-+}
-+
- struct st_mysql_storage_engine binlog_storage_engine=
- { MYSQL_HANDLERTON_INTERFACE_VERSION };
-
-@@ -6813,7 +7198,7 @@
- binlog_init, /* Plugin Init */
- NULL, /* Plugin Deinit */
- 0x0100 /* 1.0 */,
-- NULL, /* status variables */
-+ binlog_status_vars_top, /* status variables */
- NULL, /* system variables */
- NULL, /* config options */
- 0, /* flags */
---- a/sql/log.h
-+++ b/sql/log.h
-@@ -44,17 +44,42 @@
-
- virtual int open(const char *opt_name)=0;
- virtual void close()=0;
-- virtual int log_xid(THD *thd, my_xid xid)=0;
-+ virtual int log_and_order(THD *thd, my_xid xid, bool all,
-+ bool need_commit_ordered)=0;
- virtual int unlog(ulong cookie, my_xid xid)=0;
-+
-+ protected:
-+ void run_commit_ordered(THD *thd, bool all);
- };
-
-+/*
-+ Locks used to ensure serialised execution of
-+ TC_LOG::run_commit_ordered(), or any other code that calls handler
-+ commit_ordered() methods.
-+*/
-+extern mysql_mutex_t LOCK_group_commit_queue;
-+extern mysql_mutex_t LOCK_commit_ordered;
-+
-+extern void TC_init();
-+extern void TC_destroy();
-+
- class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging
- {
- public:
- TC_LOG_DUMMY() {}
- int open(const char *opt_name) { return 0; }
- void close() { }
-- int log_xid(THD *thd, my_xid xid) { return 1; }
-+ /*
-+ TC_LOG_DUMMY is only used when there are <= 1 XA-capable engines, and we
-+ only use internal XA during commit when >= 2 XA-capable engines
-+ participate.
-+ */
-+ int log_and_order(THD *thd, my_xid xid, bool all,
-+ bool need_commit_ordered)
-+ {
-+ DBUG_ASSERT(0 /* Internal error - TC_LOG_DUMMY::log_and_order() called */);
-+ return 1;
-+ }
- int unlog(ulong cookie, my_xid xid) { return 0; }
- };
-
-@@ -80,6 +105,13 @@
- mysql_cond_t cond; // to wait for a sync
- } PAGE;
-
-+ /* List of THDs for which to invoke commit_ordered(), in order. */
-+ struct commit_entry
-+ {
-+ struct commit_entry *next;
-+ THD *thd;
-+ };
-+
- char logname[FN_REFLEN];
- File fd;
- my_off_t file_length;
-@@ -94,16 +126,38 @@
- */
- mysql_mutex_t LOCK_active, LOCK_pool, LOCK_sync;
- mysql_cond_t COND_pool, COND_active;
-+ /*
-+ Queue of threads that need to call commit_ordered().
-+ Access to this queue must be protected by LOCK_group_commit_queue
-+ */
-+ commit_entry *commit_ordered_queue;
-+ /*
-+ This flag and condition is used to reserve the queue while threads in it
-+ each run the commit_ordered() methods one after the other. Only once the
-+ last commit_ordered() in the queue is done can we start on a new queue
-+ run.
-+
-+ Since we start this process in the first thread in the queue and finish in
-+ the last (and possibly different) thread, we need a condition variable for
-+ this (we cannot unlock a mutex in a different thread than the one who
-+ locked it).
-+
-+ The condition is used together with the LOCK_group_commit_queue mutex.
-+ */
-+ my_bool commit_ordered_queue_busy;
-+ mysql_cond_t COND_queue_busy;
-
- public:
- TC_LOG_MMAP(): inited(0) {}
- int open(const char *opt_name);
- void close();
-- int log_xid(THD *thd, my_xid xid);
-+ int log_and_order(THD *thd, my_xid xid, bool all,
-+ bool need_commit_ordered);
- int unlog(ulong cookie, my_xid xid);
- int recover();
-
- private:
-+ int log_one_transaction(my_xid xid);
- void get_active_from_pool();
- int sync();
- int overflow();
-@@ -271,9 +325,31 @@
- time_t last_time;
- };
-
-+class binlog_cache_data;
- class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
- {
- private:
-+ struct group_commit_entry
-+ {
-+ struct group_commit_entry *next;
-+ THD *thd;
-+ binlog_cache_data *cache_data;
-+ /*
-+ Extra events (BEGIN, COMMIT/ROLLBACK/XID, and possibly INCIDENT) to be
-+ written during group commit. The incident_event is only valid if
-+ trx_data->has_incident() is true.
-+ */
-+ Log_event *begin_event;
-+ Log_event *end_event;
-+ Log_event *incident_event;
-+ /* Set during group commit to record any per-thread error. */
-+ int error;
-+ int commit_errno;
-+ /* This is the `all' parameter for ha_commit_ordered(). */
-+ bool all;
-+ /* True if we come in through XA log_and_order(), false otherwise. */
-+ };
-+
- #ifdef HAVE_PSI_INTERFACE
- /** The instrumentation key to use for @ LOCK_index. */
- PSI_mutex_key m_key_LOCK_index;
-@@ -325,6 +401,12 @@
- In 5.0 it's 0 for relay logs too!
- */
- bool no_auto_events;
-+ /* Queue of transactions queued up to participate in group commit. */
-+ group_commit_entry *group_commit_queue;
-+ /* Total number of committed transactions. */
-+ ulonglong num_commits;
-+ /* Number of group commits done. */
-+ ulonglong num_group_commits;
-
- /* pointer to the sync period variable, for binlog this will be
- sync_binlog_period, for relay log this will be
-@@ -346,6 +428,11 @@
- */
- int new_file_without_locking();
- int new_file_impl(bool need_lock);
-+ int write_transaction(group_commit_entry *entry);
-+ bool write_transaction_to_binlog_events(group_commit_entry *entry);
-+ void trx_group_commit_leader(group_commit_entry *leader);
-+ void mark_xid_done();
-+ void mark_xids_active(uint xid_count);
-
- public:
- MYSQL_LOG::generate_name;
-@@ -387,7 +474,8 @@
-
- int open(const char *opt_name);
- void close();
-- int log_xid(THD *thd, my_xid xid);
-+ int log_and_order(THD *thd, my_xid xid, bool all,
-+ bool need_commit_ordered);
- int unlog(ulong cookie, my_xid xid);
- int recover(IO_CACHE *log, Format_description_log_event *fdle);
- #if !defined(MYSQL_CLIENT)
-@@ -434,11 +522,11 @@
- int new_file();
-
- bool write(Log_event* event_info); // binary log write
-- bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident);
-+ bool write_transaction_to_binlog(THD *thd, binlog_cache_data *cache_data,
-+ Log_event *end_ev, bool all);
- bool write_incident(THD *thd, bool lock);
-
-- int write_cache(THD *thd, IO_CACHE *cache,
-- bool lock_log, bool flush_and_sync);
-+ int write_cache(THD *thd, IO_CACHE *cache);
- void set_write_error(THD *thd, bool is_transactional);
- bool check_write_error(THD *thd);
-
-@@ -509,6 +597,7 @@
- inline void unlock_index() { mysql_mutex_unlock(&LOCK_index);}
- inline IO_CACHE *get_index_file() { return &index_file;}
- inline uint32 get_open_count() { return open_count; }
-+ void set_status_variables();
- };
-
- class Log_event_handler
---- a/sql/mysqld.cc
-+++ b/sql/mysqld.cc
-@@ -1495,6 +1495,7 @@
- ha_end();
- if (tc_log)
- tc_log->close();
-+ TC_destroy();
- delegates_destroy();
- xid_cache_free();
- table_def_free();
-@@ -3911,6 +3912,8 @@
- query_response_time_init();
- #endif // HAVE_RESPONSE_TIME_DISTRIBUTION
- /* We have to initialize the storage engines before CSV logging */
-+ TC_init();
-+
- init_global_table_stats();
- init_global_index_stats();
-
-@@ -7872,6 +7875,7 @@
- key_LOCK_error_messages, key_LOG_INFO_lock, key_LOCK_thread_count,
- key_PARTITION_LOCK_auto_inc;
- PSI_mutex_key key_RELAYLOG_LOCK_index;
-+PSI_mutex_key key_LOCK_wakeup_ready, key_LOCK_group_commit_queue, key_LOCK_commit_ordered;
-
- static PSI_mutex_info all_server_mutexes[]=
- {
-@@ -7892,6 +7896,7 @@
- { &key_delayed_insert_mutex, "Delayed_insert::mutex", 0},
- { &key_hash_filo_lock, "hash_filo::lock", 0},
- { &key_LOCK_active_mi, "LOCK_active_mi", PSI_FLAG_GLOBAL},
-+ { &key_LOCK_commit_ordered, "LOCK_commit_ordered", PSI_FLAG_GLOBAL},
- { &key_LOCK_connection_count, "LOCK_connection_count", PSI_FLAG_GLOBAL},
- { &key_LOCK_crypt, "LOCK_crypt", PSI_FLAG_GLOBAL},
- { &key_LOCK_delayed_create, "LOCK_delayed_create", PSI_FLAG_GLOBAL},
-@@ -7907,6 +7912,7 @@
- "LOCK_global_index_stats", PSI_FLAG_GLOBAL},
- { &key_LOCK_gdl, "LOCK_gdl", PSI_FLAG_GLOBAL},
- { &key_LOCK_global_system_variables, "LOCK_global_system_variables", PSI_FLAG_GLOBAL},
-+ { &key_LOCK_group_commit_queue, "LOCK_group_commit_queue", PSI_FLAG_GLOBAL},
- { &key_LOCK_manager, "LOCK_manager", PSI_FLAG_GLOBAL},
- { &key_LOCK_prepared_stmt_count, "LOCK_prepared_stmt_count", PSI_FLAG_GLOBAL},
- { &key_LOCK_rpl_status, "LOCK_rpl_status", PSI_FLAG_GLOBAL},
-@@ -7918,6 +7924,7 @@
- { &key_LOCK_temporary_tables, "THD::LOCK_temporary_tables", 0},
- { &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_GLOBAL},
- { &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_GLOBAL},
-+ { &key_LOCK_wakeup_ready, "THD::LOCK_wakeup_ready", 0},
- { &key_LOG_LOCK_log, "LOG::LOCK_log", 0},
- { &key_master_info_data_lock, "Master_info::data_lock", 0},
- { &key_master_info_run_lock, "Master_info::run_lock", 0},
-@@ -7965,6 +7972,7 @@
- key_TABLE_SHARE_cond, key_user_level_lock_cond,
- key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache;
- PSI_cond_key key_RELAYLOG_update_cond;
-+PSI_cond_key key_COND_wakeup_ready, key_COND_queue_busy;
-
- static PSI_cond_info all_server_conds[]=
- {
-@@ -7981,8 +7989,10 @@
- { &key_RELAYLOG_update_cond, "MYSQL_RELAY_LOG::update_cond", 0},
- { &key_COND_cache_status_changed, "Query_cache::COND_cache_status_changed", 0},
- { &key_COND_manager, "COND_manager", PSI_FLAG_GLOBAL},
-+ { &key_COND_queue_busy, "COND_queue_busy", PSI_FLAG_GLOBAL},
- { &key_COND_rpl_status, "COND_rpl_status", PSI_FLAG_GLOBAL},
- { &key_COND_server_started, "COND_server_started", PSI_FLAG_GLOBAL},
-+ { &key_COND_wakeup_ready, "THD::COND_wakeup_ready", 0},
- { &key_delayed_insert_cond, "Delayed_insert::cond", 0},
- { &key_delayed_insert_cond_client, "Delayed_insert::cond_client", 0},
- { &key_item_func_sleep_cond, "Item_func_sleep::cond", 0},
---- a/sql/mysqld.h
-+++ b/sql/mysqld.h
-@@ -274,6 +274,7 @@
- key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
- key_LOCK_error_messages, key_LOCK_thread_count, key_PARTITION_LOCK_auto_inc;
- extern PSI_mutex_key key_RELAYLOG_LOCK_index;
-+extern PSI_mutex_key key_LOCK_wakeup_ready, key_LOCK_group_commit_queue, key_LOCK_commit_ordered;
-
- extern PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
- key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave,
-@@ -294,6 +295,7 @@
- key_TABLE_SHARE_cond, key_user_level_lock_cond,
- key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache;
- extern PSI_cond_key key_RELAYLOG_update_cond;
-+extern PSI_cond_key key_COND_wakeup_ready, key_COND_queue_busy;
-
- extern PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert,
- key_thread_handle_manager, key_thread_kill_server, key_thread_main,
---- a/sql/sql_class.cc
-+++ b/sql/sql_class.cc
-@@ -1005,6 +1005,8 @@
- mysql_mutex_init(key_LOCK_thd_data, &LOCK_thd_data, MY_MUTEX_INIT_FAST);
- mysql_mutex_init(key_LOCK_temporary_tables, &LOCK_temporary_tables,
- MY_MUTEX_INIT_FAST);
-+ mysql_mutex_init(key_LOCK_wakeup_ready, &LOCK_wakeup_ready, MY_MUTEX_INIT_FAST);
-+ mysql_cond_init(key_COND_wakeup_ready, &COND_wakeup_ready, NULL);
-
- /* Variables with default values */
- proc_info="login";
-@@ -1609,6 +1611,8 @@
- my_free(db);
- db= NULL;
- free_root(&transaction.mem_root,MYF(0));
-+ mysql_cond_destroy(&COND_wakeup_ready);
-+ mysql_mutex_destroy(&LOCK_wakeup_ready);
- mysql_mutex_destroy(&LOCK_thd_data);
- mysql_mutex_destroy(&LOCK_temporary_tables);
- #ifndef DBUG_OFF
-@@ -5297,6 +5301,24 @@
- DBUG_RETURN(0);
- }
-
-+void
-+THD::wait_for_wakeup_ready()
-+{
-+ mysql_mutex_lock(&LOCK_wakeup_ready);
-+ while (!wakeup_ready)
-+ mysql_cond_wait(&COND_wakeup_ready, &LOCK_wakeup_ready);
-+ mysql_mutex_unlock(&LOCK_wakeup_ready);
-+}
-+
-+void
-+THD::signal_wakeup_ready()
-+{
-+ mysql_mutex_lock(&LOCK_wakeup_ready);
-+ wakeup_ready= true;
-+ mysql_mutex_unlock(&LOCK_wakeup_ready);
-+ mysql_cond_signal(&COND_wakeup_ready);
-+}
-+
- bool Discrete_intervals_list::append(ulonglong start, ulonglong val,
- ulonglong incr)
- {
---- a/sql/sql_class.h
-+++ b/sql/sql_class.h
-@@ -3078,6 +3078,14 @@
- LEX_STRING get_invoker_user() { return invoker_user; }
- LEX_STRING get_invoker_host() { return invoker_host; }
- bool has_invoker() { return invoker_user.length > 0; }
-+ void clear_wakeup_ready() { wakeup_ready= false; }
-+ /*
-+ Sleep waiting for others to wake us up with signal_wakeup_ready().
-+ Must call clear_wakeup_ready() before waiting.
-+ */
-+ void wait_for_wakeup_ready();
-+ /* Wake this thread up from wait_for_wakeup_ready(). */
-+ void signal_wakeup_ready();
- private:
-
- /** The current internal error handler for this thread, or NULL. */
-@@ -3120,6 +3128,16 @@
- */
- LEX_STRING invoker_user;
- LEX_STRING invoker_host;
-+ /*
-+ Flag, mutex and condition for a thread to wait for a signal from another
-+ thread.
-+
-+ Currently used to wait for group commit to complete, can also be used for
-+ other purposes.
-+ */
-+ bool wakeup_ready;
-+ mysql_mutex_t LOCK_wakeup_ready;
-+ mysql_cond_t COND_wakeup_ready;
- };
-
- /* Returns string as 'IP' for the client-side of the connection represented by
---- a/sql/sql_parse.cc
-+++ b/sql/sql_parse.cc
-@@ -889,6 +889,10 @@
- DBUG_ENTER("dispatch_command");
- DBUG_PRINT("info",("packet: '%*.s'; command: %d", packet_length, packet, command));
-
-+ DBUG_EXECUTE_IF("crash_dispatch_command_before",
-+ { DBUG_PRINT("crash_dispatch_command_before", ("now"));
-+ DBUG_ABORT(); });
-+
- #if defined(ENABLED_PROFILING)
- thd->profiling.start_new_query();
- #endif
---- a/mysql-test/suite/perfschema/r/dml_setup_instruments.result
-+++ b/mysql-test/suite/perfschema/r/dml_setup_instruments.result
-@@ -11,9 +11,9 @@
- wait/synch/mutex/sql/HA_DATA_PARTITION::LOCK_auto_inc YES YES
- wait/synch/mutex/sql/LOCK_active_mi YES YES
- wait/synch/mutex/sql/LOCK_audit_mask YES YES
-+wait/synch/mutex/sql/LOCK_commit_ordered YES YES
- wait/synch/mutex/sql/LOCK_connection_count YES YES
- wait/synch/mutex/sql/LOCK_crypt YES YES
--wait/synch/mutex/sql/LOCK_delayed_create YES YES
- select * from performance_schema.setup_instruments
- where name like 'Wait/Synch/Rwlock/sql/%'
- and name not in ('wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock')
-@@ -38,6 +38,7 @@
- NAME ENABLED TIMED
- wait/synch/cond/sql/COND_flush_thread_cache YES YES
- wait/synch/cond/sql/COND_manager YES YES
-+wait/synch/cond/sql/COND_queue_busy YES YES
- wait/synch/cond/sql/COND_queue_state YES YES
- wait/synch/cond/sql/COND_rpl_status YES YES
- wait/synch/cond/sql/COND_server_started YES YES
-@@ -45,7 +46,6 @@
- wait/synch/cond/sql/COND_thread_count YES YES
- wait/synch/cond/sql/Delayed_insert::cond YES YES
- wait/synch/cond/sql/Delayed_insert::cond_client YES YES
--wait/synch/cond/sql/Event_scheduler::COND_state YES YES
- select * from performance_schema.setup_instruments
- where name='Wait';
- select * from performance_schema.setup_instruments
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -375,6 +375,9 @@
- static INNOBASE_SHARE *get_share(const char *table_name);
- static void free_share(INNOBASE_SHARE *share);
- static int innobase_close_connection(handlerton *hton, THD* thd);
-+#ifdef EXTENDED_FOR_COMMIT_ORDERED
-+static void innobase_commit_ordered(handlerton *hton, THD* thd, bool all);
-+#endif
- static int innobase_commit(handlerton *hton, THD* thd, bool all);
- static int innobase_rollback(handlerton *hton, THD* thd, bool all);
- static int innobase_rollback_to_savepoint(handlerton *hton, THD* thd,
-@@ -1699,7 +1702,10 @@
- trx_t* trx) /*!< in/out: InnoDB transaction handle */
- {
- DBUG_ENTER("innobase_trx_init");
-+#ifndef EXTENDED_FOR_COMMIT_ORDERED
-+ /* used by innobase_commit_ordered */
- DBUG_ASSERT(EQ_CURRENT_THD(thd));
-+#endif
- DBUG_ASSERT(thd == trx->mysql_thd);
-
- trx->check_foreigns = !thd_test_options(
-@@ -1760,7 +1766,10 @@
- {
- trx_t*& trx = thd_to_trx(thd);
-
-+#ifndef EXTENDED_FOR_COMMIT_ORDERED
-+ /* used by innobase_commit_ordered */
- ut_ad(EQ_CURRENT_THD(thd));
-+#endif
-
- if (trx == NULL) {
- trx = innobase_trx_allocate(thd);
-@@ -1846,6 +1855,7 @@
- {
- trx->is_registered = 0;
- trx->owns_prepare_mutex = 0;
-+ trx->called_commit_ordered = 0;
- }
-
- /*********************************************************************//**
-@@ -1861,6 +1871,29 @@
- }
-
- /*********************************************************************//**
-+*/
-+static inline
-+void
-+trx_called_commit_ordered_set(
-+/*==========================*/
-+ trx_t* trx)
-+{
-+ ut_a(trx_is_registered_for_2pc(trx));
-+ trx->called_commit_ordered = 1;
-+}
-+
-+/*********************************************************************//**
-+*/
-+static inline
-+bool
-+trx_called_commit_ordered(
-+/*======================*/
-+ const trx_t* trx)
-+{
-+ return(trx->called_commit_ordered == 1);
-+}
-+
-+/*********************************************************************//**
- Check if transaction is started.
- @reutrn true if transaction is in state started */
- static
-@@ -2435,6 +2468,9 @@
- innobase_hton->savepoint_set=innobase_savepoint;
- innobase_hton->savepoint_rollback=innobase_rollback_to_savepoint;
- innobase_hton->savepoint_release=innobase_release_savepoint;
-+#ifdef EXTENDED_FOR_COMMIT_ORDERED
-+ innobase_hton->commit_ordered=innobase_commit_ordered;
-+#endif
- innobase_hton->commit=innobase_commit;
- innobase_hton->rollback=innobase_rollback;
- innobase_hton->prepare=innobase_xa_prepare;
-@@ -3187,6 +3223,126 @@
- DBUG_RETURN(0);
- }
-
-+#ifdef EXTENDED_FOR_COMMIT_ORDERED
-+/* MEMO:
-+ InnoDB is coded with intention that always trx is accessed by the owner thd.
-+ (not protected by any mutex/lock)
-+ So, the caller of innobase_commit_ordered() should be conscious of
-+ cache coherency between multi CPU about the trx, if called from another thd.
-+
-+ MariaDB's first implementation about it seems the cherency is protected by
-+ the pthread_mutex LOCK_wakeup_ready. So, no problem for now.
-+
-+ But we should be aware the importance of the coherency.
-+ */
-+/*****************************************************************//**
-+low function function innobase_commit_ordered().*/
-+static
-+void
-+innobase_commit_ordered_low(
-+/*========================*/
-+ trx_t* trx, /*!< in: Innodb transaction */
-+ THD* thd) /*!< in: MySQL thread handle */
-+{
-+ ulonglong tmp_pos;
-+ DBUG_ENTER("innobase_commit_ordered");
-+
-+ /* This part was from innobase_commit() */
-+
-+ /* We need current binlog position for ibbackup to work.
-+ Note, the position is current because commit_ordered is guaranteed
-+ to be called in same sequenece as writing to binlog. */
-+retry:
-+ if (innobase_commit_concurrency > 0) {
-+ mysql_mutex_lock(&commit_cond_m);
-+ commit_threads++;
-+
-+ if (commit_threads > innobase_commit_concurrency) {
-+ commit_threads--;
-+ mysql_cond_wait(&commit_cond,
-+ &commit_cond_m);
-+ mysql_mutex_unlock(&commit_cond_m);
-+ goto retry;
-+ }
-+ else {
-+ mysql_mutex_unlock(&commit_cond_m);
-+ }
-+ }
-+
-+ mysql_bin_log_commit_pos(thd, &tmp_pos, &(trx->mysql_log_file_name));
-+ trx->mysql_log_offset = (ib_int64_t) tmp_pos;
-+
-+ /* Don't do write + flush right now. For group commit
-+ to work we want to do the flush in the innobase_commit()
-+ method, which runs without holding any locks. */
-+ trx->flush_log_later = TRUE;
-+ innobase_commit_low(trx);
-+ trx->flush_log_later = FALSE;
-+
-+ if (innobase_commit_concurrency > 0) {
-+ mysql_mutex_lock(&commit_cond_m);
-+ commit_threads--;
-+ mysql_cond_signal(&commit_cond);
-+ mysql_mutex_unlock(&commit_cond_m);
-+ }
-+
-+ DBUG_VOID_RETURN;
-+}
-+
-+/*****************************************************************//**
-+Perform the first, fast part of InnoDB commit.
-+
-+Doing it in this call ensures that we get the same commit order here
-+as in binlog and any other participating transactional storage engines.
-+
-+Note that we want to do as little as really needed here, as we run
-+under a global mutex. The expensive fsync() is done later, in
-+innobase_commit(), without a lock so group commit can take place.
-+
-+Note also that this method can be called from a different thread than
-+the one handling the rest of the transaction. */
-+static
-+void
-+innobase_commit_ordered(
-+/*====================*/
-+ handlerton *hton, /*!< in: Innodb handlerton */
-+ THD* thd, /*!< in: MySQL thread handle of the user for whom
-+ the transaction should be committed */
-+ bool all) /*!< in: TRUE - commit transaction
-+ FALSE - the current SQL statement ended */
-+{
-+ trx_t* trx;
-+ DBUG_ENTER("innobase_commit_ordered");
-+ DBUG_ASSERT(hton == innodb_hton_ptr);
-+
-+ trx = check_trx_exists(thd);
-+
-+ /* Since we will reserve the kernel mutex, we have to release
-+ the search system latch first to obey the latching order. */
-+
-+ if (trx->has_search_latch) {
-+ trx_search_latch_release_if_reserved(trx);
-+ }
-+
-+ if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
-+ /* We cannot throw error here; instead we will catch this error
-+ again in innobase_commit() and report it from there. */
-+ DBUG_VOID_RETURN;
-+ }
-+
-+ /* commit_ordered is only called when committing the whole transaction
-+ (or an SQL statement when autocommit is on). */
-+ DBUG_ASSERT(all ||
-+ (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)));
-+
-+ innobase_commit_ordered_low(trx, thd);
-+
-+ trx_called_commit_ordered_set(trx);
-+
-+ DBUG_VOID_RETURN;
-+}
-+#endif /* EXTENDED_FOR_COMMIT_ORDERED */
-+
- /*****************************************************************//**
- Commits a transaction in an InnoDB database or marks an SQL statement
- ended.
-@@ -3238,6 +3394,16 @@
- /* We were instructed to commit the whole transaction, or
- this is an SQL statement end and autocommit is on */
-
-+#ifdef EXTENDED_FOR_COMMIT_ORDERED
-+ ut_ad(!trx_has_prepare_commit_mutex(trx));
-+
-+ /* Run the fast part of commit if we did not already. */
-+ if (!trx_called_commit_ordered(trx)) {
-+ innobase_commit_ordered_low(trx, thd);
-+ }
-+#else
-+ ut_ad(!trx_called_commit_ordered(trx));
-+
- /* We need current binlog position for ibbackup to work.
- Note, the position is current because of
- prepare_commit_mutex */
-@@ -3292,6 +3458,7 @@
-
- mysql_mutex_unlock(&prepare_commit_mutex);
- }
-+#endif /* EXTENDED_FOR_COMMIT_ORDERED */
-
- trx_deregister_from_2pc(trx);
-
-@@ -10981,6 +11148,7 @@
-
- srv_active_wake_master_thread();
-
-+#ifndef EXTENDED_FOR_COMMIT_ORDERED
- if (thd_sql_command(thd) != SQLCOM_XA_PREPARE
- && (all
- || !thd_test_options(
-@@ -11007,6 +11175,7 @@
- mysql_mutex_lock(&prepare_commit_mutex);
- trx_owns_prepare_commit_mutex_set(trx);
- }
-+#endif /* ifndef EXTENDED_FOR_COMMIT_ORDERED */
-
- return(error);
- }
---- a/storage/innobase/handler/ha_innodb.h
-+++ b/storage/innobase/handler/ha_innodb.h
-@@ -240,6 +240,12 @@
- struct charset_info_st *thd_charset(MYSQL_THD thd);
- LEX_STRING *thd_query_string(MYSQL_THD thd);
-
-+#ifdef EXTENDED_FOR_COMMIT_ORDERED
-+/** Get the file name and position of the MySQL binlog corresponding to the
-+ * current commit.
-+ */
-+void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file);
-+#else
- /** Get the file name of the MySQL binlog.
- * @return the name of the binlog file
- */
-@@ -249,6 +255,7 @@
- * @return byte offset from the beginning of the binlog
- */
- ulonglong mysql_bin_log_file_pos(void);
-+#endif
-
- /**
- Check if a user thread is a replication slave thread
---- a/storage/innobase/include/trx0trx.h
-+++ b/storage/innobase/include/trx0trx.h
-@@ -494,6 +494,7 @@
- this is set to 1 then registered should
- also be set to 1. This is used in the
- XA code */
-+ unsigned called_commit_ordered:1;/* 1 if innobase_commit_ordered has run. */
- /*------------------------------*/
- ulint isolation_level;/* TRX_ISO_REPEATABLE_READ, ... */
- ulint check_foreigns; /* normally TRUE, but if the user
---- a/storage/innobase/trx/trx0trx.c
-+++ b/storage/innobase/trx/trx0trx.c
-@@ -111,6 +111,7 @@
-
- trx->is_registered = 0;
- trx->owns_prepare_mutex = 0;
-+ trx->called_commit_ordered = 0;
-
- trx->start_time = ut_time();
-
---- /dev/null
-+++ b/mysql-test/r/group_commit.result
-@@ -0,0 +1,63 @@
-+CREATE TABLE t1 (a VARCHAR(10) PRIMARY KEY) ENGINE=innodb;
-+SELECT variable_value INTO @commits FROM information_schema.global_status
-+WHERE variable_name = 'binlog_commits';
-+SELECT variable_value INTO @group_commits FROM information_schema.global_status
-+WHERE variable_name = 'binlog_group_commits';
-+SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL group1_running WAIT_FOR group2_queued";
-+INSERT INTO t1 VALUES ("con1");
-+set DEBUG_SYNC= "now WAIT_FOR group1_running";
-+SET DEBUG_SYNC= "commit_group_commit_queue SIGNAL group2_con2";
-+SET DEBUG_SYNC= "commit_after_release_LOCK_log WAIT_FOR group3_committed";
-+SET DEBUG_SYNC= "commit_after_group_run_commit_ordered SIGNAL group2_visible WAIT_FOR group2_checked";
-+INSERT INTO t1 VALUES ("con2");
-+SET DEBUG_SYNC= "now WAIT_FOR group2_con2";
-+SET DEBUG_SYNC= "commit_group_commit_queue SIGNAL group2_con3";
-+INSERT INTO t1 VALUES ("con3");
-+SET DEBUG_SYNC= "now WAIT_FOR group2_con3";
-+SET DEBUG_SYNC= "commit_group_commit_queue SIGNAL group2_con4";
-+INSERT INTO t1 VALUES ("con4");
-+SET DEBUG_SYNC= "now WAIT_FOR group2_con4";
-+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
-+SELECT * FROM t1 ORDER BY a;
-+a
-+SET DEBUG_SYNC= "now SIGNAL group2_queued";
-+SELECT * FROM t1 ORDER BY a;
-+a
-+con1
-+SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL group3_con5";
-+SET DEBUG_SYNC= "commit_after_get_LOCK_log SIGNAL con5_leader WAIT_FOR con6_queued";
-+INSERT INTO t1 VALUES ("con5");
-+SET DEBUG_SYNC= "now WAIT_FOR con5_leader";
-+SET DEBUG_SYNC= "commit_group_commit_queue SIGNAL con6_queued";
-+INSERT INTO t1 VALUES ("con6");
-+SET DEBUG_SYNC= "now WAIT_FOR group3_con5";
-+SELECT * FROM t1 ORDER BY a;
-+a
-+con1
-+SET DEBUG_SYNC= "now SIGNAL group3_committed";
-+SET DEBUG_SYNC= "now WAIT_FOR group2_visible";
-+SELECT * FROM t1 ORDER BY a;
-+a
-+con1
-+con2
-+con3
-+con4
-+SET DEBUG_SYNC= "now SIGNAL group2_checked";
-+SELECT * FROM t1 ORDER BY a;
-+a
-+con1
-+con2
-+con3
-+con4
-+con5
-+con6
-+SELECT variable_value - @commits FROM information_schema.global_status
-+WHERE variable_name = 'binlog_commits';
-+variable_value - @commits
-+6
-+SELECT variable_value - @group_commits FROM information_schema.global_status
-+WHERE variable_name = 'binlog_group_commits';
-+variable_value - @group_commits
-+3
-+SET DEBUG_SYNC= 'RESET';
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/r/group_commit_binlog_pos.result
-@@ -0,0 +1,35 @@
-+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb;
-+INSERT INTO t1 VALUES (0);
-+SET DEBUG_SYNC= "commit_after_get_LOCK_log SIGNAL con1_waiting WAIT_FOR con3_queued";
-+SET DEBUG_SYNC= "commit_loop_entry_commit_ordered SIGNAL con1_loop WAIT_FOR con1_loop_cont EXECUTE 3";
-+INSERT INTO t1 VALUES (1);
-+SET DEBUG_SYNC= "now WAIT_FOR con1_waiting";
-+SET DEBUG_SYNC= "commit_group_commit_queue SIGNAL con2_queued";
-+INSERT INTO t1 VALUES (2);
-+SET DEBUG_SYNC= "now WAIT_FOR con2_queued";
-+SET DEBUG_SYNC= "commit_group_commit_queue SIGNAL con3_queued";
-+INSERT INTO t1 VALUES (3);
-+SET DEBUG_SYNC= "now WAIT_FOR con1_loop";
-+SET DEBUG_SYNC= "now SIGNAL con1_loop_cont";
-+SET DEBUG_SYNC= "now WAIT_FOR con1_loop";
-+SET DEBUG_SYNC= "now SIGNAL con1_loop_cont";
-+SET DEBUG_SYNC= "now WAIT_FOR con1_loop";
-+SELECT * FROM t1 ORDER BY a;
-+a
-+0
-+1
-+2
-+SET SESSION debug="+d,crash_dispatch_command_before";
-+SELECT 1;
-+Got one of the listed errors
-+Got one of the listed errors
-+Got one of the listed errors
-+SELECT * FROM t1 ORDER BY a;
-+a
-+0
-+1
-+2
-+3
-+InnoDB: Last MySQL binlog file position 0 768, file name ./master-bin.000001
-+SET DEBUG_SYNC= 'RESET';
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/r/group_commit_crash.result
-@@ -0,0 +1,120 @@
-+CREATE TABLE t1(a CHAR(255),
-+b CHAR(255),
-+c CHAR(255),
-+d CHAR(255),
-+id INT AUTO_INCREMENT,
-+PRIMARY KEY(id)) ENGINE=InnoDB;
-+create table t2 like t1;
-+create procedure setcrash(IN i INT)
-+begin
-+CASE i
-+WHEN 1 THEN SET SESSION debug="d,crash_commit_after_prepare";
-+WHEN 2 THEN SET SESSION debug="d,crash_commit_after_log";
-+WHEN 3 THEN SET SESSION debug="d,crash_commit_before_unlog";
-+WHEN 4 THEN SET SESSION debug="d,crash_commit_after";
-+WHEN 5 THEN SET SESSION debug="d,crash_commit_before";
-+ELSE BEGIN END;
-+END CASE;
-+end //
-+FLUSH TABLES;
-+INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd');
-+INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd');
-+INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd');
-+INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd');
-+INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd');
-+INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd');
-+INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd');
-+INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd');
-+INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd');
-+INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd');
-+RESET MASTER;
-+START TRANSACTION;
-+insert into t1 select * from t2;
-+call setcrash(5);
-+COMMIT;
-+Got one of the listed errors
-+SELECT * FROM t1 ORDER BY id;
-+a b c d id
-+SHOW BINLOG EVENTS LIMIT 2,1;
-+Log_name Pos Event_type Server_id End_log_pos Info
-+delete from t1;
-+RESET MASTER;
-+START TRANSACTION;
-+insert into t1 select * from t2;
-+call setcrash(4);
-+COMMIT;
-+Got one of the listed errors
-+SELECT * FROM t1 ORDER BY id;
-+a b c d id
-+a b c d 1
-+a b c d 2
-+a b c d 3
-+a b c d 4
-+a b c d 5
-+a b c d 6
-+a b c d 7
-+a b c d 8
-+a b c d 9
-+a b c d 10
-+SHOW BINLOG EVENTS LIMIT 2,1;
-+Log_name Pos Event_type Server_id End_log_pos Info
-+master-bin.000001 175 Query 1 269 use `test`; insert into t1 select * from t2
-+delete from t1;
-+RESET MASTER;
-+START TRANSACTION;
-+insert into t1 select * from t2;
-+call setcrash(3);
-+COMMIT;
-+Got one of the listed errors
-+SELECT * FROM t1 ORDER BY id;
-+a b c d id
-+a b c d 1
-+a b c d 2
-+a b c d 3
-+a b c d 4
-+a b c d 5
-+a b c d 6
-+a b c d 7
-+a b c d 8
-+a b c d 9
-+a b c d 10
-+SHOW BINLOG EVENTS LIMIT 2,1;
-+Log_name Pos Event_type Server_id End_log_pos Info
-+master-bin.000001 175 Query 1 269 use `test`; insert into t1 select * from t2
-+delete from t1;
-+RESET MASTER;
-+START TRANSACTION;
-+insert into t1 select * from t2;
-+call setcrash(2);
-+COMMIT;
-+Got one of the listed errors
-+SELECT * FROM t1 ORDER BY id;
-+a b c d id
-+a b c d 1
-+a b c d 2
-+a b c d 3
-+a b c d 4
-+a b c d 5
-+a b c d 6
-+a b c d 7
-+a b c d 8
-+a b c d 9
-+a b c d 10
-+SHOW BINLOG EVENTS LIMIT 2,1;
-+Log_name Pos Event_type Server_id End_log_pos Info
-+master-bin.000001 175 Query 1 269 use `test`; insert into t1 select * from t2
-+delete from t1;
-+RESET MASTER;
-+START TRANSACTION;
-+insert into t1 select * from t2;
-+call setcrash(1);
-+COMMIT;
-+Got one of the listed errors
-+SELECT * FROM t1 ORDER BY id;
-+a b c d id
-+SHOW BINLOG EVENTS LIMIT 2,1;
-+Log_name Pos Event_type Server_id End_log_pos Info
-+delete from t1;
-+DROP TABLE t1;
-+DROP TABLE t2;
-+DROP PROCEDURE setcrash;
---- /dev/null
-+++ b/mysql-test/r/xa_binlog.result
-@@ -0,0 +1,32 @@
-+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
-+SET binlog_format= mixed;
-+RESET MASTER;
-+XA START 'xatest';
-+INSERT INTO t1 VALUES (1);
-+XA END 'xatest';
-+XA PREPARE 'xatest';
-+XA COMMIT 'xatest';
-+XA START 'xatest';
-+INSERT INTO t1 VALUES (2);
-+XA END 'xatest';
-+XA COMMIT 'xatest' ONE PHASE;
-+BEGIN;
-+INSERT INTO t1 VALUES (3);
-+COMMIT;
-+SELECT * FROM t1 ORDER BY a;
-+a
-+1
-+2
-+3
-+SHOW BINLOG EVENTS LIMIT 1,9;
-+Log_name Pos Event_type Server_id End_log_pos Info
-+master-bin.000001 # Query 1 # BEGIN
-+master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 VALUES (1)
-+master-bin.000001 # Query 1 # COMMIT
-+master-bin.000001 # Query 1 # BEGIN
-+master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 VALUES (2)
-+master-bin.000001 # Xid 1 # COMMIT /* xid=XX */
-+master-bin.000001 # Query 1 # BEGIN
-+master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 VALUES (3)
-+master-bin.000001 # Xid 1 # COMMIT /* xid=XX */
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/suite/binlog/r/binlog_ioerr.result
-@@ -0,0 +1,28 @@
-+CALL mtr.add_suppression("Error writing file 'master-bin'");
-+RESET MASTER;
-+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb;
-+INSERT INTO t1 VALUES(0);
-+SET SESSION debug='+d,fail_binlog_write_1';
-+INSERT INTO t1 VALUES(1);
-+ERROR HY000: Error writing file 'master-bin' (errno: 28)
-+INSERT INTO t1 VALUES(2);
-+ERROR HY000: Error writing file 'master-bin' (errno: 28)
-+SET SESSION debug='';
-+INSERT INTO t1 VALUES(3);
-+SELECT * FROM t1;
-+a
-+0
-+3
-+SHOW BINLOG EVENTS;
-+Log_name Pos Event_type Server_id End_log_pos Info
-+BINLOG POS Format_desc 1 ENDPOS Server ver: #, Binlog ver: #
-+BINLOG POS Query 1 ENDPOS use `test`; CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb
-+BINLOG POS Query 1 ENDPOS BEGIN
-+BINLOG POS Query 1 ENDPOS use `test`; INSERT INTO t1 VALUES(0)
-+BINLOG POS Xid 1 ENDPOS COMMIT /* XID */
-+BINLOG POS Query 1 ENDPOS BEGIN
-+BINLOG POS Query 1 ENDPOS BEGIN
-+BINLOG POS Query 1 ENDPOS BEGIN
-+BINLOG POS Query 1 ENDPOS use `test`; INSERT INTO t1 VALUES(3)
-+BINLOG POS Xid 1 ENDPOS COMMIT /* XID */
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/suite/binlog/t/binlog_ioerr.test
-@@ -0,0 +1,30 @@
-+source include/have_debug.inc;
-+source include/have_innodb.inc;
-+source include/have_log_bin.inc;
-+source include/have_binlog_format_mixed_or_statement.inc;
-+
-+CALL mtr.add_suppression("Error writing file 'master-bin'");
-+
-+RESET MASTER;
-+
-+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb;
-+INSERT INTO t1 VALUES(0);
-+SET SESSION debug='+d,fail_binlog_write_1';
-+--error ER_ERROR_ON_WRITE
-+INSERT INTO t1 VALUES(1);
-+--error ER_ERROR_ON_WRITE
-+INSERT INTO t1 VALUES(2);
-+SET SESSION debug='';
-+INSERT INTO t1 VALUES(3);
-+SELECT * FROM t1;
-+
-+# Actually the output from this currently shows a bug.
-+# The injected IO error leaves partially written transactions in the binlog in
-+# the form of stray "BEGIN" events.
-+# These should disappear from the output if binlog error handling is improved
-+# (see MySQL Bug#37148 and WL#1790).
-+--replace_regex /\/\* xid=.* \*\//\/* XID *\// /Server ver: .*, Binlog ver: .*/Server ver: #, Binlog ver: #/ /table_id: [0-9]+/table_id: #/
-+--replace_column 1 BINLOG 2 POS 5 ENDPOS
-+SHOW BINLOG EVENTS;
-+
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/t/group_commit.test
-@@ -0,0 +1,115 @@
-+--source include/have_debug_sync.inc
-+--source include/have_innodb.inc
-+--source include/have_log_bin.inc
-+
-+# Test some group commit code paths by using debug_sync to do controlled
-+# commits of 6 transactions: first 1 alone, then 3 as a group, then 2 as a
-+# group.
-+#
-+# Group 3 is allowed to race as far as possible ahead before group 2 finishes
-+# to check some edge case for concurrency control.
-+
-+CREATE TABLE t1 (a VARCHAR(10) PRIMARY KEY) ENGINE=innodb;
-+
-+SELECT variable_value INTO @commits FROM information_schema.global_status
-+ WHERE variable_name = 'binlog_commits';
-+SELECT variable_value INTO @group_commits FROM information_schema.global_status
-+ WHERE variable_name = 'binlog_group_commits';
-+
-+connect(con1,localhost,root,,);
-+connect(con2,localhost,root,,);
-+connect(con3,localhost,root,,);
-+connect(con4,localhost,root,,);
-+connect(con5,localhost,root,,);
-+connect(con6,localhost,root,,);
-+
-+# Start group1 (with one thread) doing commit, waiting for
-+# group2 to queue up before finishing.
-+
-+connection con1;
-+SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL group1_running WAIT_FOR group2_queued";
-+send INSERT INTO t1 VALUES ("con1");
-+
-+# Make group2 (with three threads) queue up.
-+# Make sure con2 is the group commit leader for group2.
-+# Make group2 wait with running commit_ordered() until group3 has committed.
-+
-+connection con2;
-+set DEBUG_SYNC= "now WAIT_FOR group1_running";
-+SET DEBUG_SYNC= "commit_group_commit_queue SIGNAL group2_con2";
-+SET DEBUG_SYNC= "commit_after_release_LOCK_log WAIT_FOR group3_committed";
-+SET DEBUG_SYNC= "commit_after_group_run_commit_ordered SIGNAL group2_visible WAIT_FOR group2_checked";
-+send INSERT INTO t1 VALUES ("con2");
-+connection con3;
-+SET DEBUG_SYNC= "now WAIT_FOR group2_con2";
-+SET DEBUG_SYNC= "commit_group_commit_queue SIGNAL group2_con3";
-+send INSERT INTO t1 VALUES ("con3");
-+connection con4;
-+SET DEBUG_SYNC= "now WAIT_FOR group2_con3";
-+SET DEBUG_SYNC= "commit_group_commit_queue SIGNAL group2_con4";
-+send INSERT INTO t1 VALUES ("con4");
-+
-+# When group2 is queued, let group1 continue and queue group3.
-+
-+connection default;
-+SET DEBUG_SYNC= "now WAIT_FOR group2_con4";
-+
-+# At this point, trasaction 1 is still not visible as commit_ordered() has not
-+# been called yet.
-+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
-+SELECT * FROM t1 ORDER BY a;
-+
-+SET DEBUG_SYNC= "now SIGNAL group2_queued";
-+connection con1;
-+reap;
-+
-+# Now transaction 1 is visible.
-+connection default;
-+SELECT * FROM t1 ORDER BY a;
-+
-+connection con5;
-+SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL group3_con5";
-+SET DEBUG_SYNC= "commit_after_get_LOCK_log SIGNAL con5_leader WAIT_FOR con6_queued";
-+send INSERT INTO t1 VALUES ("con5");
-+
-+connection con6;
-+SET DEBUG_SYNC= "now WAIT_FOR con5_leader";
-+SET DEBUG_SYNC= "commit_group_commit_queue SIGNAL con6_queued";
-+send INSERT INTO t1 VALUES ("con6");
-+
-+connection default;
-+SET DEBUG_SYNC= "now WAIT_FOR group3_con5";
-+# Still only transaction 1 visible, as group2 have not yet run commit_ordered().
-+SELECT * FROM t1 ORDER BY a;
-+SET DEBUG_SYNC= "now SIGNAL group3_committed";
-+SET DEBUG_SYNC= "now WAIT_FOR group2_visible";
-+# Now transactions 1-4 visible.
-+SELECT * FROM t1 ORDER BY a;
-+SET DEBUG_SYNC= "now SIGNAL group2_checked";
-+
-+connection con2;
-+reap;
-+
-+connection con3;
-+reap;
-+
-+connection con4;
-+reap;
-+
-+connection con5;
-+reap;
-+
-+connection con6;
-+reap;
-+
-+connection default;
-+# Check all transactions finally visible.
-+SELECT * FROM t1 ORDER BY a;
-+
-+SELECT variable_value - @commits FROM information_schema.global_status
-+ WHERE variable_name = 'binlog_commits';
-+SELECT variable_value - @group_commits FROM information_schema.global_status
-+ WHERE variable_name = 'binlog_group_commits';
-+
-+SET DEBUG_SYNC= 'RESET';
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/t/group_commit_binlog_pos-master.opt
-@@ -0,0 +1 @@
-+--skip-stack-trace --skip-core-file
---- /dev/null
-+++ b/mysql-test/t/group_commit_binlog_pos.test
-@@ -0,0 +1,89 @@
-+--source include/have_debug_sync.inc
-+--source include/have_innodb.inc
-+--source include/have_log_bin.inc
-+--source include/have_binlog_format_mixed_or_statement.inc
-+
-+# Need DBUG to crash the server intentionally
-+--source include/have_debug.inc
-+# Don't test this under valgrind, memory leaks will occur as we crash
-+--source include/not_valgrind.inc
-+
-+# The test case currently uses grep and tail, which may be unavailable on
-+# some windows systems. But see MWL#191 for how to remove the need for grep.
-+--source include/not_windows.inc
-+
-+# XtraDB stores the binlog position corresponding to the last commit, and
-+# prints it during crash recovery.
-+# Test that we get the correct position when we group commit several
-+# transactions together.
-+
-+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb;
-+INSERT INTO t1 VALUES (0);
-+
-+connect(con1,localhost,root,,);
-+connect(con2,localhost,root,,);
-+connect(con3,localhost,root,,);
-+
-+# Queue up three commits for group commit.
-+
-+connection con1;
-+SET DEBUG_SYNC= "commit_after_get_LOCK_log SIGNAL con1_waiting WAIT_FOR con3_queued";
-+SET DEBUG_SYNC= "commit_loop_entry_commit_ordered SIGNAL con1_loop WAIT_FOR con1_loop_cont EXECUTE 3";
-+send INSERT INTO t1 VALUES (1);
-+
-+connection con2;
-+SET DEBUG_SYNC= "now WAIT_FOR con1_waiting";
-+SET DEBUG_SYNC= "commit_group_commit_queue SIGNAL con2_queued";
-+send INSERT INTO t1 VALUES (2);
-+
-+connection con3;
-+SET DEBUG_SYNC= "now WAIT_FOR con2_queued";
-+SET DEBUG_SYNC= "commit_group_commit_queue SIGNAL con3_queued";
-+send INSERT INTO t1 VALUES (3);
-+
-+connection default;
-+SET DEBUG_SYNC= "now WAIT_FOR con1_loop";
-+# At this point, no transactions are committed.
-+SET DEBUG_SYNC= "now SIGNAL con1_loop_cont";
-+SET DEBUG_SYNC= "now WAIT_FOR con1_loop";
-+# At this point, 1 transaction is committed.
-+SET DEBUG_SYNC= "now SIGNAL con1_loop_cont";
-+SET DEBUG_SYNC= "now WAIT_FOR con1_loop";
-+
-+# At this point, 2 transactions are committed.
-+SELECT * FROM t1 ORDER BY a;
-+
-+connection con2;
-+reap;
-+
-+# Now crash the server with 1+2 in-memory committed, 3 only prepared.
-+connection default;
-+system echo wait-group_commit_binlog_pos.test >> $MYSQLTEST_VARDIR/tmp/mysqld.1.expect;
-+SET SESSION debug="+d,crash_dispatch_command_before";
-+--error 2006,2013
-+SELECT 1;
-+
-+connection con1;
-+--error 2006,2013
-+reap;
-+connection con3;
-+--error 2006,2013
-+reap;
-+
-+system echo restart-group_commit_binlog_pos.test >> $MYSQLTEST_VARDIR/tmp/mysqld.1.expect;
-+
-+connection default;
-+--enable_reconnect
-+--source include/wait_until_connected_again.inc
-+
-+# Crash recovery should recover all three transactions.
-+SELECT * FROM t1 ORDER BY a;
-+
-+# Check that the binlog position reported by InnoDB is the correct one
-+# for the end of the second transaction (as can be checked with
-+# mysqlbinlog).
-+let $MYSQLD_DATADIR= `SELECT @@datadir`;
-+--exec grep 'InnoDB: Last MySQL binlog file position' $MYSQLD_DATADIR/../../log/mysqld.1.err | tail -1
-+
-+SET DEBUG_SYNC= 'RESET';
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/t/group_commit_crash-master.opt
-@@ -0,0 +1 @@
-+--skip-stack-trace --skip-core-file
---- /dev/null
-+++ b/mysql-test/t/group_commit_crash.test
-@@ -0,0 +1,80 @@
-+# Testing group commit by crashing a few times.
-+# Test adapted from the Facebook patch: lp:mysqlatfacebook
-+--source include/not_embedded.inc
-+# Don't test this under valgrind, memory leaks will occur
-+--source include/not_valgrind.inc
-+
-+# Binary must be compiled with debug for crash to occur
-+--source include/have_debug.inc
-+--source include/have_innodb.inc
-+--source include/have_log_bin.inc
-+
-+let $innodb_file_format_max_orig=`select @@innodb_file_format_max`;
-+CREATE TABLE t1(a CHAR(255),
-+ b CHAR(255),
-+ c CHAR(255),
-+ d CHAR(255),
-+ id INT AUTO_INCREMENT,
-+ PRIMARY KEY(id)) ENGINE=InnoDB;
-+create table t2 like t1;
-+delimiter //;
-+create procedure setcrash(IN i INT)
-+begin
-+ CASE i
-+ WHEN 1 THEN SET SESSION debug="d,crash_commit_after_prepare";
-+ WHEN 2 THEN SET SESSION debug="d,crash_commit_after_log";
-+ WHEN 3 THEN SET SESSION debug="d,crash_commit_before_unlog";
-+ WHEN 4 THEN SET SESSION debug="d,crash_commit_after";
-+ WHEN 5 THEN SET SESSION debug="d,crash_commit_before";
-+ ELSE BEGIN END;
-+ END CASE;
-+end //
-+delimiter ;//
-+# Avoid getting a crashed mysql.proc table.
-+FLUSH TABLES;
-+
-+let $numtests = 5;
-+
-+let $numinserts = 10;
-+while ($numinserts)
-+{
-+ dec $numinserts;
-+ INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd');
-+}
-+
-+--enable_reconnect
-+
-+while ($numtests)
-+{
-+ RESET MASTER;
-+
-+ START TRANSACTION;
-+ insert into t1 select * from t2;
-+ # Write file to make mysql-test-run.pl expect crash
-+ --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
-+
-+ eval call setcrash($numtests);
-+
-+ # Run the crashing query
-+ --error 2006,2013
-+ COMMIT;
-+
-+ # Poll the server waiting for it to be back online again.
-+ --source include/wait_until_connected_again.inc
-+
-+ # table and binlog should be in sync.
-+ SELECT * FROM t1 ORDER BY id;
-+ SHOW BINLOG EVENTS LIMIT 2,1;
-+
-+ delete from t1;
-+
-+ dec $numtests;
-+}
-+
-+# final cleanup
-+DROP TABLE t1;
-+DROP TABLE t2;
-+DROP PROCEDURE setcrash;
-+--disable_query_log
-+eval SET GLOBAL innodb_file_format_max=$innodb_file_format_max_orig;
-+--enable_query_log
---- /dev/null
-+++ b/mysql-test/t/xa_binlog.test
-@@ -0,0 +1,32 @@
-+--source include/have_innodb.inc
-+--source include/have_log_bin.inc
-+
-+CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
-+
-+# Fix binlog format (otherwise SHOW BINLOG EVENTS will fluctuate).
-+SET binlog_format= mixed;
-+
-+RESET MASTER;
-+
-+XA START 'xatest';
-+INSERT INTO t1 VALUES (1);
-+XA END 'xatest';
-+XA PREPARE 'xatest';
-+XA COMMIT 'xatest';
-+
-+XA START 'xatest';
-+INSERT INTO t1 VALUES (2);
-+XA END 'xatest';
-+XA COMMIT 'xatest' ONE PHASE;
-+
-+BEGIN;
-+INSERT INTO t1 VALUES (3);
-+COMMIT;
-+
-+SELECT * FROM t1 ORDER BY a;
-+
-+--replace_column 2 # 5 #
-+--replace_regex /xid=[0-9]+/xid=XX/
-+SHOW BINLOG EVENTS LIMIT 1,9;
-+
-+DROP TABLE t1;
+++ /dev/null
-# name : innodb_adaptive_hash_index_num.patch
-# introduced : XtraDB on 5.5 (-13?)
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/btr/btr0cur.c
-+++ b/storage/innobase/btr/btr0cur.c
-@@ -500,7 +500,7 @@
- #ifdef UNIV_SEARCH_PERF_STAT
- info->n_searches++;
- #endif
-- if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_NOT_LOCKED
-+ if (rw_lock_get_writer(btr_search_get_latch(cursor->index->id)) == RW_LOCK_NOT_LOCKED
- && latch_mode <= BTR_MODIFY_LEAF
- && info->last_hash_succ
- && !estimate
-@@ -536,7 +536,7 @@
-
- if (has_search_latch) {
- /* Release possible search latch to obey latching order */
-- rw_lock_s_unlock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(cursor->index->id));
- }
-
- /* Store the position of the tree latch we push to mtr so that we
-@@ -847,7 +847,7 @@
-
- if (has_search_latch) {
-
-- rw_lock_s_lock(&btr_search_latch);
-+ rw_lock_s_lock(btr_search_get_latch(cursor->index->id));
- }
- }
-
-@@ -1977,13 +1977,13 @@
- btr_search_update_hash_on_delete(cursor);
- }
-
-- rw_lock_x_lock(&btr_search_latch);
-+ rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
- }
-
- row_upd_rec_in_place(rec, index, offsets, update, page_zip);
-
- if (is_hashed) {
-- rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
- }
-
- if (page_zip && !dict_index_is_clust(index)
---- a/storage/innobase/btr/btr0sea.c
-+++ b/storage/innobase/btr/btr0sea.c
-@@ -47,6 +47,8 @@
- Protected by btr_search_latch. */
- UNIV_INTERN char btr_search_enabled = TRUE;
-
-+UNIV_INTERN ulint btr_search_index_num = 1;
-+
- #ifdef UNIV_PFS_MUTEX
- /* Key to register btr_search_enabled_mutex with performance schema */
- UNIV_INTERN mysql_pfs_key_t btr_search_enabled_mutex_key;
-@@ -75,7 +77,9 @@
-
- /* We will allocate the latch from dynamic memory to get it to the
- same DRAM page as other hotspot semaphores */
--UNIV_INTERN rw_lock_t* btr_search_latch_temp;
-+//UNIV_INTERN rw_lock_t* btr_search_latch_temp;
-+
-+UNIV_INTERN rw_lock_t** btr_search_latch_part;
-
- /** padding to prevent other memory update hotspots from residing on
- the same memory cache line */
-@@ -127,18 +131,19 @@
- will not guarantee success. */
- static
- void
--btr_search_check_free_space_in_heap(void)
-+btr_search_check_free_space_in_heap(
- /*=====================================*/
-+ index_id_t key)
- {
- hash_table_t* table;
- mem_heap_t* heap;
-
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
-- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-+ ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
-+ ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
- #endif /* UNIV_SYNC_DEBUG */
-
-- table = btr_search_sys->hash_index;
-+ table = btr_search_get_hash_index(key);
-
- heap = table->heap;
-
-@@ -149,7 +154,7 @@
- if (heap->free_block == NULL) {
- buf_block_t* block = buf_block_alloc(NULL);
-
-- rw_lock_x_lock(&btr_search_latch);
-+ rw_lock_x_lock(btr_search_get_latch(key));
-
- if (heap->free_block == NULL) {
- heap->free_block = block;
-@@ -157,7 +162,7 @@
- buf_block_free(block);
- }
-
-- rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(btr_search_get_latch(key));
- }
- }
-
-@@ -169,17 +174,28 @@
- /*==================*/
- ulint hash_size) /*!< in: hash index hash table size */
- {
-+ ulint i;
- /* We allocate the search latch from dynamic memory:
- see above at the global variable definition */
-
-- btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
-+ //btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
-
-- rw_lock_create(btr_search_latch_key, &btr_search_latch,
-- SYNC_SEARCH_SYS);
-+ //rw_lock_create(btr_search_latch_key, &btr_search_latch,
-+ // SYNC_SEARCH_SYS);
-
- btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
-
-- btr_search_sys->hash_index = ha_create(hash_size, 0, 0);
-+ /* btr_search_index_num should be <= 32. (bits of trx->has_search_latch) */
-+ btr_search_latch_part = mem_alloc(sizeof(rw_lock_t*) * btr_search_index_num);
-+ btr_search_sys->hash_index = mem_alloc(sizeof(hash_table_t*) * btr_search_index_num);
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ btr_search_latch_part[i] = mem_alloc(sizeof(rw_lock_t));
-+
-+ rw_lock_create(btr_search_latch_key,
-+ btr_search_latch_part[i], SYNC_SEARCH_SYS);
-+
-+ btr_search_sys->hash_index[i] = ha_create(hash_size, 0, 0);
-+ }
- }
-
- /*****************************************************************//**
-@@ -189,11 +205,22 @@
- btr_search_sys_free(void)
- /*=====================*/
- {
-- rw_lock_free(&btr_search_latch);
-- mem_free(btr_search_latch_temp);
-- btr_search_latch_temp = NULL;
-- mem_heap_free(btr_search_sys->hash_index->heap);
-- hash_table_free(btr_search_sys->hash_index);
-+ ulint i;
-+
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ mem_heap_free(btr_search_sys->hash_index[i]->heap);
-+ hash_table_free(btr_search_sys->hash_index[i]);
-+
-+ rw_lock_free(btr_search_latch_part[i]);
-+
-+ mem_free(btr_search_latch_part[i]);
-+ }
-+ mem_free(btr_search_sys->hash_index);
-+ mem_free(btr_search_latch_part);
-+
-+ //rw_lock_free(&btr_search_latch);
-+ //mem_free(btr_search_latch_temp);
-+ //btr_search_latch_temp = NULL;
- mem_free(btr_search_sys);
- btr_search_sys = NULL;
- }
-@@ -206,9 +233,10 @@
- /*====================*/
- {
- dict_table_t* table;
-+ ulint i;
-
- mutex_enter(&dict_sys->mutex);
-- rw_lock_x_lock(&btr_search_latch);
-+ btr_search_x_lock_all();
-
- btr_search_enabled = FALSE;
-
-@@ -232,10 +260,12 @@
- buf_pool_clear_hash_index();
-
- /* Clear the adaptive hash index. */
-- hash_table_clear(btr_search_sys->hash_index);
-- mem_heap_empty(btr_search_sys->hash_index->heap);
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ hash_table_clear(btr_search_sys->hash_index[i]);
-+ mem_heap_empty(btr_search_sys->hash_index[i]->heap);
-+ }
-
-- rw_lock_x_unlock(&btr_search_latch);
-+ btr_search_x_unlock_all();
- }
-
- /********************************************************************//**
-@@ -245,11 +275,11 @@
- btr_search_enable(void)
- /*====================*/
- {
-- rw_lock_x_lock(&btr_search_latch);
-+ btr_search_x_lock_all();
-
- btr_search_enabled = TRUE;
-
-- rw_lock_x_unlock(&btr_search_latch);
-+ btr_search_x_unlock_all();
- }
-
- /*****************************************************************//**
-@@ -301,20 +331,21 @@
- ulint
- btr_search_info_get_ref_count(
- /*==========================*/
-- btr_search_t* info) /*!< in: search info. */
-+ btr_search_t* info, /*!< in: search info. */
-+ index_id_t key)
- {
- ulint ret;
-
- ut_ad(info);
-
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
-- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-+ ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
-+ ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
- #endif /* UNIV_SYNC_DEBUG */
-
-- rw_lock_s_lock(&btr_search_latch);
-+ rw_lock_s_lock(btr_search_get_latch(key));
- ret = info->ref_count;
-- rw_lock_s_unlock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(key));
-
- return(ret);
- }
-@@ -335,8 +366,8 @@
- int cmp;
-
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
-- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
-+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
- #endif /* UNIV_SYNC_DEBUG */
-
- index = cursor->index;
-@@ -454,8 +485,8 @@
- /*!< in: cursor */
- {
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
-- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
-+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
- ut_ad(rw_lock_own(&block->lock, RW_LOCK_SHARED)
- || rw_lock_own(&block->lock, RW_LOCK_EX));
- #endif /* UNIV_SYNC_DEBUG */
-@@ -539,7 +570,7 @@
-
- ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-+ ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
- ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
- || rw_lock_own(&(block->lock), RW_LOCK_EX));
- #endif /* UNIV_SYNC_DEBUG */
-@@ -580,10 +611,10 @@
- mem_heap_free(heap);
- }
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-+ ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
- #endif /* UNIV_SYNC_DEBUG */
-
-- ha_insert_for_fold(btr_search_sys->hash_index, fold,
-+ ha_insert_for_fold(btr_search_get_hash_index(cursor->index->id), fold,
- block, rec);
- }
- }
-@@ -603,8 +634,8 @@
- ulint* params2;
-
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
-- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
-+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
- #endif /* UNIV_SYNC_DEBUG */
-
- block = btr_cur_get_block(cursor);
-@@ -625,7 +656,7 @@
-
- if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
-
-- btr_search_check_free_space_in_heap();
-+ btr_search_check_free_space_in_heap(cursor->index->id);
- }
-
- if (cursor->flag == BTR_CUR_HASH_FAIL) {
-@@ -635,11 +666,11 @@
- btr_search_n_hash_fail++;
- #endif /* UNIV_SEARCH_PERF_STAT */
-
-- rw_lock_x_lock(&btr_search_latch);
-+ rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
-
- btr_search_update_hash_ref(info, block, cursor);
-
-- rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
- }
-
- if (build_index) {
-@@ -884,17 +915,17 @@
- cursor->flag = BTR_CUR_HASH;
-
- if (UNIV_LIKELY(!has_search_latch)) {
-- rw_lock_s_lock(&btr_search_latch);
-+ rw_lock_s_lock(btr_search_get_latch(index_id));
-
- if (UNIV_UNLIKELY(!btr_search_enabled)) {
- goto failure_unlock;
- }
- }
-
-- ut_ad(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_EX);
-- ut_ad(rw_lock_get_reader_count(&btr_search_latch) > 0);
-+ ut_ad(rw_lock_get_writer(btr_search_get_latch(index_id)) != RW_LOCK_EX);
-+ ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index_id)) > 0);
-
-- rec = ha_search_and_get_data(btr_search_sys->hash_index, fold);
-+ rec = ha_search_and_get_data(btr_search_get_hash_index(index_id), fold);
-
- if (UNIV_UNLIKELY(!rec)) {
- goto failure_unlock;
-@@ -912,7 +943,7 @@
- goto failure_unlock;
- }
-
-- rw_lock_s_unlock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(index_id));
-
- buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
- }
-@@ -1009,7 +1040,7 @@
- /*-------------------------------------------*/
- failure_unlock:
- if (UNIV_LIKELY(!has_search_latch)) {
-- rw_lock_s_unlock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(index_id));
- }
- failure:
- cursor->flag = BTR_CUR_HASH_FAIL;
-@@ -1053,24 +1084,49 @@
- const dict_index_t* index;
- ulint* offsets;
-
--#ifdef UNIV_SYNC_DEBUG
-- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
-- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
--#endif /* UNIV_SYNC_DEBUG */
--
- retry:
-- rw_lock_s_lock(&btr_search_latch);
-- index = block->index;
-+ if (btr_search_index_num > 1) {
-+ rw_lock_t* btr_search_latch;
-+
-+ /* FIXME: This may be optimistic implementation still. */
-+ btr_search_latch = (rw_lock_t*)(block->btr_search_latch);
-+ if (UNIV_LIKELY(!btr_search_latch)) {
-+ if (block->index) {
-+ goto retry;
-+ }
-+ return;
-+ }
-+ rw_lock_s_lock(btr_search_latch);
-+ if (UNIV_LIKELY(btr_search_latch != block->btr_search_latch)) {
-+ rw_lock_s_unlock(btr_search_latch);
-+ goto retry;
-+ }
-+ if (UNIV_LIKELY(!block->index)) {
-+ rw_lock_s_unlock(btr_search_latch);
-+ goto retry;
-+ }
-+ index = block->index;
-+ ut_a(btr_search_latch == btr_search_get_latch(index->id));
-+ } else {
-+ /* btr_search_index_num == 1 */
-+ /* btr_search_latch is only one and able to obtain
-+ before evaluating block->index. */
-+ rw_lock_s_lock(btr_search_latch_part[0]);
-+ if (UNIV_LIKELY(!block->index)) {
-+ rw_lock_s_unlock(btr_search_latch_part[0]);
-+ return;
-+ }
-+ index = block->index;
-+ }
-
- if (UNIV_LIKELY(!index)) {
-
-- rw_lock_s_unlock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(index->id));
-
- return;
- }
-
-- ut_a(!dict_index_is_ibuf(index));
-- table = btr_search_sys->hash_index;
-+ table = btr_search_get_hash_index(index->id);
-
- #ifdef UNIV_SYNC_DEBUG
- ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
-@@ -1080,12 +1136,14 @@
-
- n_fields = block->curr_n_fields;
- n_bytes = block->curr_n_bytes;
-+ ut_a(index == block->index);
-+ ut_a(!dict_index_is_ibuf(index));
-
- /* NOTE: The fields of block must not be accessed after
- releasing btr_search_latch, as the index page might only
- be s-latched! */
-
-- rw_lock_s_unlock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(index->id));
-
- ut_a(n_fields + n_bytes > 0);
-
-@@ -1136,7 +1194,7 @@
- mem_heap_free(heap);
- }
-
-- rw_lock_x_lock(&btr_search_latch);
-+ rw_lock_x_lock(btr_search_get_latch(index->id));
-
- if (UNIV_UNLIKELY(!block->index)) {
- /* Someone else has meanwhile dropped the hash index */
-@@ -1152,7 +1210,7 @@
- /* Someone else has meanwhile built a new hash index on the
- page, with different parameters */
-
-- rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(btr_search_get_latch(index->id));
-
- mem_free(folds);
- goto retry;
-@@ -1167,6 +1225,7 @@
- index->search_info->ref_count--;
-
- block->index = NULL;
-+ block->btr_search_latch = NULL;
-
- cleanup:
- #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
-@@ -1179,14 +1238,14 @@
- "InnoDB: the hash index to a page of %s,"
- " still %lu hash nodes remain.\n",
- index->name, (ulong) block->n_pointers);
-- rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(btr_search_get_latch(index->id));
-
- btr_search_validate();
- } else {
-- rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(btr_search_get_latch(index->id));
- }
- #else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
-- rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(btr_search_get_latch(index->id));
- #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
-
- mem_free(folds);
-@@ -1218,9 +1277,9 @@
- ulint* offsets;
- ibool released_search_latch;
-
-- rw_lock_s_lock(&btr_search_latch);
-+ rw_lock_s_lock(btr_search_get_latch(index->id));
-
-- table = btr_search_sys->hash_index;
-+ table = btr_search_get_hash_index(index->id);
-
- for (j = 0; j < srv_buf_pool_instances; j++) {
- buf_pool_t* buf_pool;
-@@ -1254,7 +1313,7 @@
-
-
- /* keeping latch order */
-- rw_lock_s_unlock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(index->id));
- released_search_latch = TRUE;
- rw_lock_x_lock(&block->lock);
-
-@@ -1306,7 +1365,7 @@
- mem_heap_empty(heap);
- }
-
-- rw_lock_x_lock(&btr_search_latch);
-+ rw_lock_x_lock(btr_search_get_latch(index->id));
-
- if (UNIV_UNLIKELY(!block->index)) {
- goto cleanup;
-@@ -1316,12 +1375,12 @@
-
- if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
- || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
-- rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(btr_search_get_latch(index->id));
- rw_lock_x_unlock(&block->lock);
-
- mem_free(folds);
-
-- rw_lock_s_lock(&btr_search_latch);
-+ rw_lock_s_lock(btr_search_get_latch(index->id));
- goto retry;
- }
-
-@@ -1334,6 +1393,7 @@
- index->search_info->ref_count--;
-
- block->index = NULL;
-+ block->btr_search_latch = NULL;
-
- cleanup:
- #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
-@@ -1346,18 +1406,18 @@
- index->name, (ulong) block->n_pointers);
- }
- #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
-- rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(btr_search_get_latch(index->id));
- rw_lock_x_unlock(&block->lock);
-
- mem_free(folds);
-
-- rw_lock_s_lock(&btr_search_latch);
-+ rw_lock_s_lock(btr_search_get_latch(index->id));
- }
- }
- } while (released_search_latch);
- }
-
-- rw_lock_s_unlock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(index->id));
-
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
-@@ -1436,31 +1496,26 @@
- ut_ad(index);
- ut_a(!dict_index_is_ibuf(index));
-
-+ table = btr_search_get_hash_index(index->id);
-+ page = buf_block_get_frame(block);
-+
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-+ ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
- ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
- || rw_lock_own(&(block->lock), RW_LOCK_EX));
- #endif /* UNIV_SYNC_DEBUG */
-
-- rw_lock_s_lock(&btr_search_latch);
--
-- if (!btr_search_enabled) {
-- rw_lock_s_unlock(&btr_search_latch);
-- return;
-- }
--
-- table = btr_search_sys->hash_index;
-- page = buf_block_get_frame(block);
-+ rw_lock_s_lock(btr_search_get_latch(index->id));
-
- if (block->index && ((block->curr_n_fields != n_fields)
-- || (block->curr_n_bytes != n_bytes)
-- || (block->curr_left_side != left_side))) {
-+ || (block->curr_n_bytes != n_bytes)
-+ || (block->curr_left_side != left_side))) {
-
-- rw_lock_s_unlock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(index->id));
-
- btr_search_drop_page_hash_index(block);
- } else {
-- rw_lock_s_unlock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(index->id));
- }
-
- n_recs = page_get_n_recs(page);
-@@ -1554,9 +1609,9 @@
- fold = next_fold;
- }
-
-- btr_search_check_free_space_in_heap();
-+ btr_search_check_free_space_in_heap(index->id);
-
-- rw_lock_x_lock(&btr_search_latch);
-+ rw_lock_x_lock(btr_search_get_latch(index->id));
-
- if (UNIV_UNLIKELY(!btr_search_enabled)) {
- goto exit_func;
-@@ -1583,6 +1638,7 @@
- block->curr_n_bytes = n_bytes;
- block->curr_left_side = left_side;
- block->index = index;
-+ block->btr_search_latch = btr_search_get_latch(index->id);
-
- for (i = 0; i < n_cached; i++) {
-
-@@ -1590,7 +1646,7 @@
- }
-
- exit_func:
-- rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(btr_search_get_latch(index->id));
-
- mem_free(folds);
- mem_free(recs);
-@@ -1625,7 +1681,7 @@
- ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));
- #endif /* UNIV_SYNC_DEBUG */
-
-- rw_lock_s_lock(&btr_search_latch);
-+ rw_lock_s_lock(btr_search_get_latch(index->id));
-
- ut_a(!new_block->index || new_block->index == index);
- ut_a(!block->index || block->index == index);
-@@ -1634,7 +1690,7 @@
-
- if (new_block->index) {
-
-- rw_lock_s_unlock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(index->id));
-
- btr_search_drop_page_hash_index(block);
-
-@@ -1651,7 +1707,7 @@
- new_block->n_bytes = block->curr_n_bytes;
- new_block->left_side = left_side;
-
-- rw_lock_s_unlock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(index->id));
-
- ut_a(n_fields + n_bytes > 0);
-
-@@ -1663,7 +1719,7 @@
- return;
- }
-
-- rw_lock_s_unlock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(index->id));
- }
-
- /********************************************************************//**
-@@ -1702,7 +1758,7 @@
- ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
- ut_a(!dict_index_is_ibuf(index));
-
-- table = btr_search_sys->hash_index;
-+ table = btr_search_get_hash_index(cursor->index->id);
-
- rec = btr_cur_get_rec(cursor);
-
-@@ -1713,7 +1769,7 @@
- mem_heap_free(heap);
- }
-
-- rw_lock_x_lock(&btr_search_latch);
-+ rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
-
- if (block->index) {
- ut_a(block->index == index);
-@@ -1721,7 +1777,7 @@
- ha_search_and_delete_if_found(table, fold, rec);
- }
-
-- rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
- }
-
- /********************************************************************//**
-@@ -1758,7 +1814,7 @@
- ut_a(cursor->index == index);
- ut_a(!dict_index_is_ibuf(index));
-
-- rw_lock_x_lock(&btr_search_latch);
-+ rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
-
- if (!block->index) {
-
-@@ -1772,15 +1828,15 @@
- && (cursor->n_bytes == block->curr_n_bytes)
- && !block->curr_left_side) {
-
-- table = btr_search_sys->hash_index;
-+ table = btr_search_get_hash_index(cursor->index->id);
-
- ha_search_and_update_if_found(table, cursor->fold, rec,
- block, page_rec_get_next(rec));
-
- func_exit:
-- rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
- } else {
-- rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
-
- btr_search_update_hash_on_insert(cursor);
- }
-@@ -1815,9 +1871,9 @@
- ulint* offsets = offsets_;
- rec_offs_init(offsets_);
-
-- table = btr_search_sys->hash_index;
-+ table = btr_search_get_hash_index(cursor->index->id);
-
-- btr_search_check_free_space_in_heap();
-+ btr_search_check_free_space_in_heap(cursor->index->id);
-
- rec = btr_cur_get_rec(cursor);
-
-@@ -1862,7 +1918,7 @@
- } else {
- if (left_side) {
-
-- rw_lock_x_lock(&btr_search_latch);
-+ rw_lock_x_lock(btr_search_get_latch(index->id));
-
- locked = TRUE;
-
-@@ -1880,7 +1936,7 @@
-
- if (!locked) {
-
-- rw_lock_x_lock(&btr_search_latch);
-+ rw_lock_x_lock(btr_search_get_latch(index->id));
-
- locked = TRUE;
-
-@@ -1902,7 +1958,7 @@
- if (!left_side) {
-
- if (!locked) {
-- rw_lock_x_lock(&btr_search_latch);
-+ rw_lock_x_lock(btr_search_get_latch(index->id));
-
- locked = TRUE;
-
-@@ -1921,7 +1977,7 @@
-
- if (!locked) {
-
-- rw_lock_x_lock(&btr_search_latch);
-+ rw_lock_x_lock(btr_search_get_latch(index->id));
-
- locked = TRUE;
-
-@@ -1948,7 +2004,7 @@
- mem_heap_free(heap);
- }
- if (locked) {
-- rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(btr_search_get_latch(index->id));
- }
- }
-
-@@ -1964,7 +2020,7 @@
- ha_node_t* node;
- ulint n_page_dumps = 0;
- ibool ok = TRUE;
-- ulint i;
-+ ulint i,j;
- ulint cell_count;
- mem_heap_t* heap = NULL;
- ulint offsets_[REC_OFFS_NORMAL_SIZE];
-@@ -1976,23 +2032,25 @@
-
- rec_offs_init(offsets_);
-
-- rw_lock_x_lock(&btr_search_latch);
-+ btr_search_x_lock_all();
- buf_pool_page_hash_x_lock_all();
-
-- cell_count = hash_get_n_cells(btr_search_sys->hash_index);
-+ for (j = 0; j < btr_search_index_num; j++) {
-+
-+ cell_count = hash_get_n_cells(btr_search_sys->hash_index[j]);
-
- for (i = 0; i < cell_count; i++) {
- /* We release btr_search_latch every once in a while to
- give other queries a chance to run. */
- if ((i != 0) && ((i % chunk_size) == 0)) {
- buf_pool_page_hash_x_unlock_all();
-- rw_lock_x_unlock(&btr_search_latch);
-+ btr_search_x_unlock_all();
- os_thread_yield();
-- rw_lock_x_lock(&btr_search_latch);
-+ btr_search_x_lock_all();
- buf_pool_page_hash_x_lock_all();
- }
-
-- node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
-+ node = hash_get_nth_cell(btr_search_sys->hash_index[j], i)->node;
-
- for (; node != NULL; node = node->next) {
- const buf_block_t* block
-@@ -2099,19 +2157,21 @@
- give other queries a chance to run. */
- if (i != 0) {
- buf_pool_page_hash_x_unlock_all();
-- rw_lock_x_unlock(&btr_search_latch);
-+ btr_search_x_unlock_all();
- os_thread_yield();
-- rw_lock_x_lock(&btr_search_latch);
-+ btr_search_x_lock_all();
- buf_pool_page_hash_x_lock_all();
- }
-
-- if (!ha_validate(btr_search_sys->hash_index, i, end_index)) {
-+ if (!ha_validate(btr_search_sys->hash_index[j], i, end_index)) {
- ok = FALSE;
- }
- }
-
-+ } /*for (j = 0; j < btr_search_index_num; j++)*/
-+
- buf_pool_page_hash_x_unlock_all();
-- rw_lock_x_unlock(&btr_search_latch);
-+ btr_search_x_unlock_all();
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
---- a/storage/innobase/buf/buf0buf.c
-+++ b/storage/innobase/buf/buf0buf.c
-@@ -960,6 +960,7 @@
-
- block->check_index_page_at_flush = FALSE;
- block->index = NULL;
-+ block->btr_search_latch = NULL;
-
- #ifdef UNIV_DEBUG
- block->page.in_page_hash = FALSE;
-@@ -1429,7 +1430,11 @@
- ulint p;
-
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-+ ulint j;
-+
-+ for (j = 0; j < btr_search_index_num; j++) {
-+ ut_ad(rw_lock_own(btr_search_latch_part[j], RW_LOCK_EX));
-+ }
- #endif /* UNIV_SYNC_DEBUG */
- ut_ad(!btr_search_enabled);
-
-@@ -2144,6 +2149,7 @@
- {
- block->check_index_page_at_flush = FALSE;
- block->index = NULL;
-+ block->btr_search_latch = NULL;
-
- block->n_hash_helps = 0;
- block->n_fields = 1;
---- a/storage/innobase/buf/buf0lru.c
-+++ b/storage/innobase/buf/buf0lru.c
-@@ -576,7 +576,7 @@
-
- mutex_exit(&buf_pool->LRU_list_mutex);
-
-- rw_lock_s_lock(&btr_search_latch);
-+ btr_search_s_lock_all();
- chunk = buf_pool->chunks;
- for (j = buf_pool->n_chunks; j--; chunk++) {
- buf_block_t* block = chunk->blocks;
-@@ -588,16 +588,16 @@
- continue;
- }
-
-- rw_lock_s_unlock(&btr_search_latch);
-+ btr_search_s_unlock_all();
-
- rw_lock_x_lock(&block->lock);
- btr_search_drop_page_hash_index(block);
- rw_lock_x_unlock(&block->lock);
-
-- rw_lock_s_lock(&btr_search_latch);
-+ btr_search_s_lock_all();
- }
- }
-- rw_lock_s_unlock(&btr_search_latch);
-+ btr_search_s_unlock_all();
- }
- }
-
---- a/storage/innobase/dict/dict0dict.c
-+++ b/storage/innobase/dict/dict0dict.c
-@@ -1851,7 +1851,7 @@
- zero. */
-
- for (;;) {
-- ulint ref_count = btr_search_info_get_ref_count(info);
-+ ulint ref_count = btr_search_info_get_ref_count(info, index->id);
- if (ref_count == 0) {
- break;
- }
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -11832,6 +11832,11 @@
- "Disable with --skip-innodb-adaptive-hash-index.",
- NULL, innodb_adaptive_hash_index_update, TRUE);
-
-+static MYSQL_SYSVAR_ULONG(adaptive_hash_index_partitions, btr_search_index_num,
-+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
-+ "Number of InnoDB adaptive hash index partitions (default 1: disable partitioning)",
-+ NULL, NULL, 1, 1, sizeof(ulint) * 8, 0);
-+
- static MYSQL_SYSVAR_ULONG(replication_delay, srv_replication_delay,
- PLUGIN_VAR_RQCMDARG,
- "Replication thread delay (ms) on the slave server if "
-@@ -12252,6 +12257,7 @@
- MYSQL_SYSVAR(use_sys_stats_table),
- MYSQL_SYSVAR(stats_sample_pages),
- MYSQL_SYSVAR(adaptive_hash_index),
-+ MYSQL_SYSVAR(adaptive_hash_index_partitions),
- MYSQL_SYSVAR(stats_method),
- MYSQL_SYSVAR(replication_delay),
- MYSQL_SYSVAR(status_file),
---- a/storage/innobase/include/btr0sea.h
-+++ b/storage/innobase/include/btr0sea.h
-@@ -85,7 +85,8 @@
- ulint
- btr_search_info_get_ref_count(
- /*==========================*/
-- btr_search_t* info); /*!< in: search info. */
-+ btr_search_t* info, /*!< in: search info. */
-+ index_id_t key);
- /*********************************************************************//**
- Updates the search info. */
- UNIV_INLINE
-@@ -199,6 +200,40 @@
- # define btr_search_validate() TRUE
- #endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
-
-+/********************************************************************//**
-+New functions to control split btr_search_index */
-+UNIV_INLINE
-+hash_table_t*
-+btr_search_get_hash_index(
-+/*======================*/
-+ index_id_t key);
-+
-+UNIV_INLINE
-+rw_lock_t*
-+btr_search_get_latch(
-+/*=================*/
-+ index_id_t key);
-+
-+UNIV_INLINE
-+void
-+btr_search_x_lock_all(void);
-+/*========================*/
-+
-+UNIV_INLINE
-+void
-+btr_search_x_unlock_all(void);
-+/*==========================*/
-+
-+UNIV_INLINE
-+void
-+btr_search_s_lock_all(void);
-+/*========================*/
-+
-+UNIV_INLINE
-+void
-+btr_search_s_unlock_all(void);
-+/*==========================*/
-+
- /** The search info struct in an index */
- struct btr_search_struct{
- ulint ref_count; /*!< Number of blocks in this index tree
-@@ -259,7 +294,7 @@
-
- /** The hash index system */
- struct btr_search_sys_struct{
-- hash_table_t* hash_index; /*!< the adaptive hash index,
-+ hash_table_t** hash_index; /*!< the adaptive hash index,
- mapping dtuple_fold values
- to rec_t pointers on index pages */
- };
---- a/storage/innobase/include/btr0sea.ic
-+++ b/storage/innobase/include/btr0sea.ic
-@@ -62,8 +62,8 @@
- btr_search_t* info;
-
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
-- ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-+ ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
-+ ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
- #endif /* UNIV_SYNC_DEBUG */
-
- info = btr_search_get_info(index);
-@@ -82,3 +82,72 @@
-
- btr_search_info_update_slow(info, cursor);
- }
-+
-+/*********************************************************************//**
-+New functions to control split btr_search_index */
-+UNIV_INLINE
-+hash_table_t*
-+btr_search_get_hash_index(
-+/*======================*/
-+ index_id_t key)
-+{
-+ return(btr_search_sys->hash_index[key % btr_search_index_num]);
-+}
-+
-+UNIV_INLINE
-+rw_lock_t*
-+btr_search_get_latch(
-+/*=================*/
-+ index_id_t key)
-+{
-+ return(btr_search_latch_part[key % btr_search_index_num]);
-+}
-+
-+UNIV_INLINE
-+void
-+btr_search_x_lock_all(void)
-+/*=======================*/
-+{
-+ ulint i;
-+
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ rw_lock_x_lock(btr_search_latch_part[i]);
-+ }
-+}
-+
-+UNIV_INLINE
-+void
-+btr_search_x_unlock_all(void)
-+/*==========================*/
-+{
-+ ulint i;
-+
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ rw_lock_x_unlock(btr_search_latch_part[i]);
-+ }
-+}
-+
-+UNIV_INLINE
-+void
-+btr_search_s_lock_all(void)
-+/*=======================*/
-+{
-+ ulint i;
-+
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ rw_lock_s_lock(btr_search_latch_part[i]);
-+ }
-+}
-+
-+UNIV_INLINE
-+void
-+btr_search_s_unlock_all(void)
-+/*=========================*/
-+{
-+ ulint i;
-+
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ rw_lock_s_unlock(btr_search_latch_part[i]);
-+ }
-+}
-+
---- a/storage/innobase/row/row0mysql.c
-+++ b/storage/innobase/row/row0mysql.c
-@@ -2594,7 +2594,7 @@
- /* check adaptive hash entries */
- index = dict_table_get_first_index(table);
- while (index) {
-- ulint ref_count = btr_search_info_get_ref_count(index->search_info);
-+ ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
- if (ref_count) {
- fprintf(stderr, "InnoDB: Warning:"
- " hash index ref_count (%lu) is not zero"
-@@ -2955,7 +2955,7 @@
- table->space = space;
- index = dict_table_get_first_index(table);
- do {
-- ulint ref_count = btr_search_info_get_ref_count(index->search_info);
-+ ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
- /* check adaptive hash entries */
- if (ref_count) {
- fprintf(stderr, "InnoDB: Warning:"
---- a/storage/innobase/row/row0sel.c
-+++ b/storage/innobase/row/row0sel.c
-@@ -1222,7 +1222,7 @@
- ut_ad(plan->unique_search);
- ut_ad(!plan->must_get_clust);
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
-+ ut_ad(rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
- #endif /* UNIV_SYNC_DEBUG */
-
- row_sel_open_pcur(plan, TRUE, mtr);
-@@ -1393,10 +1393,10 @@
- && !plan->must_get_clust
- && !plan->table->big_rows) {
- if (!search_latch_locked) {
-- rw_lock_s_lock(&btr_search_latch);
-+ rw_lock_s_lock(btr_search_get_latch(index->id));
-
- search_latch_locked = TRUE;
-- } else if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_WAIT_EX) {
-+ } else if (rw_lock_get_writer(btr_search_get_latch(index->id)) == RW_LOCK_WAIT_EX) {
-
- /* There is an x-latch request waiting: release the
- s-latch for a moment; as an s-latch here is often
-@@ -1405,8 +1405,8 @@
- from acquiring an s-latch for a long time, lowering
- performance significantly in multiprocessors. */
-
-- rw_lock_s_unlock(&btr_search_latch);
-- rw_lock_s_lock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(index->id));
-+ rw_lock_s_lock(btr_search_get_latch(index->id));
- }
-
- found_flag = row_sel_try_search_shortcut(node, plan, &mtr);
-@@ -1429,7 +1429,7 @@
- }
-
- if (search_latch_locked) {
-- rw_lock_s_unlock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(index->id));
-
- search_latch_locked = FALSE;
- }
-@@ -2005,7 +2005,7 @@
-
- func_exit:
- if (search_latch_locked) {
-- rw_lock_s_unlock(&btr_search_latch);
-+ rw_lock_s_unlock(btr_search_get_latch(index->id));
- }
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
-@@ -3408,6 +3408,8 @@
- /* if the returned record was locked and we did a semi-consistent
- read (fetch the newest committed version), then this is set to
- TRUE */
-+ ulint i;
-+ ulint should_release;
- #ifdef UNIV_SEARCH_DEBUG
- ulint cnt = 0;
- #endif /* UNIV_SEARCH_DEBUG */
-@@ -3505,18 +3507,33 @@
- /* PHASE 0: Release a possible s-latch we are holding on the
- adaptive hash index latch if there is someone waiting behind */
-
-- if (UNIV_UNLIKELY(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_NOT_LOCKED)
-- && trx->has_search_latch) {
-+ should_release = 0;
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ /* we should check all latches (fix Bug#791030) */
-+ if (rw_lock_get_writer(btr_search_latch_part[i])
-+ != RW_LOCK_NOT_LOCKED) {
-+ should_release |= ((ulint)1 << i);
-+ }
-+ }
-+
-+ if (should_release) {
-
- /* There is an x-latch request on the adaptive hash index:
- release the s-latch to reduce starvation and wait for
- BTR_SEA_TIMEOUT rounds before trying to keep it again over
- calls from MySQL */
-
-- rw_lock_s_unlock(&btr_search_latch);
-- trx->has_search_latch = FALSE;
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ /* we should release all s-latches (fix Bug#791030) */
-+ if (trx->has_search_latch & ((ulint)1 << i)) {
-+ rw_lock_s_unlock(btr_search_latch_part[i]);
-+ trx->has_search_latch &= (~((ulint)1 << i));
-+ }
-+ }
-
-+ if (!trx->has_search_latch) {
- trx->search_latch_timeout = BTR_SEA_TIMEOUT;
-+ }
- }
-
- /* Reset the new record lock info if srv_locks_unsafe_for_binlog
-@@ -3667,9 +3684,28 @@
- hash index semaphore! */
-
- #ifndef UNIV_SEARCH_DEBUG
-- if (!trx->has_search_latch) {
-- rw_lock_s_lock(&btr_search_latch);
-- trx->has_search_latch = TRUE;
-+ if (!(trx->has_search_latch
-+ & ((ulint)1 << (index->id % btr_search_index_num)))) {
-+ if (trx->has_search_latch
-+ < ((ulint)1 << (index->id % btr_search_index_num))) {
-+ rw_lock_s_lock(btr_search_get_latch(index->id));
-+ trx->has_search_latch |=
-+ ((ulint)1 << (index->id % btr_search_index_num));
-+ } else {
-+ /* should re-lock to obay latch-order */
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ if (trx->has_search_latch & ((ulint)1 << i)) {
-+ rw_lock_s_unlock(btr_search_latch_part[i]);
-+ }
-+ }
-+ trx->has_search_latch |=
-+ ((ulint)1 << (index->id % btr_search_index_num));
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ if (trx->has_search_latch & ((ulint)1 << i)) {
-+ rw_lock_s_lock(btr_search_latch_part[i]);
-+ }
-+ }
-+ }
- }
- #endif
- switch (row_sel_try_search_shortcut_for_mysql(
-@@ -3730,7 +3766,11 @@
-
- trx->search_latch_timeout--;
-
-- rw_lock_s_unlock(&btr_search_latch);
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ if (trx->has_search_latch & ((ulint)1 << i)) {
-+ rw_lock_s_unlock(btr_search_latch_part[i]);
-+ }
-+ }
- trx->has_search_latch = FALSE;
- }
-
-@@ -3754,7 +3794,12 @@
- /* PHASE 3: Open or restore index cursor position */
-
- if (trx->has_search_latch) {
-- rw_lock_s_unlock(&btr_search_latch);
-+
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ if (trx->has_search_latch & ((ulint)1 << i)) {
-+ rw_lock_s_unlock(btr_search_latch_part[i]);
-+ }
-+ }
- trx->has_search_latch = FALSE;
- }
-
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -2054,7 +2054,9 @@
- "-------------------------------------\n", file);
- ibuf_print(file);
-
-- ha_print_info(file, btr_search_sys->hash_index);
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ ha_print_info(file, btr_search_get_hash_index((index_id_t)i));
-+ }
-
- fprintf(file,
- "%.2f hash searches/s, %.2f non-hash searches/s\n",
-@@ -2079,14 +2081,15 @@
- ut_total_allocated_memory,
- mem_pool_get_reserved(mem_comm_pool));
- /* Calcurate reserved memories */
-- if (btr_search_sys && btr_search_sys->hash_index->heap) {
-- btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index->heap);
-+ if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
-+ btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index[0]->heap);
- } else {
- btr_search_sys_subtotal = 0;
-- for (i=0; i < btr_search_sys->hash_index->n_mutexes; i++) {
-- btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index->heaps[i]);
-+ for (i=0; i < btr_search_sys->hash_index[0]->n_mutexes; i++) {
-+ btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index[0]->heaps[i]);
- }
- }
-+ btr_search_sys_subtotal *= btr_search_index_num;
-
- lock_sys_subtotal = 0;
- if (trx_sys) {
-@@ -2112,10 +2115,10 @@
- " Recovery system %lu \t(%lu + %lu)\n",
-
- (ulong) (btr_search_sys
-- ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0)
-+ ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0)
- + btr_search_sys_subtotal,
- (ulong) (btr_search_sys
-- ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0),
-+ ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0),
- (ulong) btr_search_sys_subtotal,
-
- (ulong) (buf_pool_from_array(0)->page_hash->n_cells * sizeof(hash_cell_t)),
---- a/storage/innobase/trx/trx0trx.c
-+++ b/storage/innobase/trx/trx0trx.c
-@@ -265,8 +265,14 @@
- /*=================================*/
- trx_t* trx) /*!< in: transaction */
- {
-+ ulint i;
-+
- if (trx->has_search_latch) {
-- rw_lock_s_unlock(&btr_search_latch);
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ if (trx->has_search_latch & ((ulint)1 << i)) {
-+ rw_lock_s_unlock(btr_search_latch_part[i]);
-+ }
-+ }
-
- trx->has_search_latch = FALSE;
- }
---- a/storage/innobase/include/btr0types.h
-+++ b/storage/innobase/include/btr0types.h
-@@ -52,15 +52,19 @@
-
- Bear in mind (3) and (4) when using the hash index.
- */
--extern rw_lock_t* btr_search_latch_temp;
-+//extern rw_lock_t* btr_search_latch_temp;
-+
-+extern rw_lock_t** btr_search_latch_part;
-
- /** The latch protecting the adaptive search system */
--#define btr_search_latch (*btr_search_latch_temp)
-+//#define btr_search_latch (*btr_search_latch_temp)
-
- /** Flag: has the search system been enabled?
- Protected by btr_search_latch. */
- extern char btr_search_enabled;
-
-+extern ulint btr_search_index_num;
-+
- #ifdef UNIV_BLOB_DEBUG
- # include "buf0types.h"
- /** An index->blobs entry for keeping track of off-page column references */
---- a/storage/innobase/ha/ha0ha.c
-+++ b/storage/innobase/ha/ha0ha.c
-@@ -120,7 +120,7 @@
- ut_a(block->frame == page_align(data));
- #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-+ ut_ad(rw_lock_own(block->btr_search_latch, RW_LOCK_EX));
- #endif /* UNIV_SYNC_DEBUG */
- ASSERT_HASH_MUTEX_OWN(table, fold);
- ut_ad(btr_search_enabled);
-@@ -213,7 +213,7 @@
- ut_ad(table);
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-+ // ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
- #endif /* UNIV_SYNC_DEBUG */
- ut_ad(btr_search_enabled);
- #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
-@@ -253,7 +253,7 @@
- ut_a(new_block->frame == page_align(new_data));
- #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-+ // ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
- #endif /* UNIV_SYNC_DEBUG */
-
- if (!btr_search_enabled) {
-@@ -296,7 +296,7 @@
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
- ASSERT_HASH_MUTEX_OWN(table, fold);
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-+ // ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
- #endif /* UNIV_SYNC_DEBUG */
- ut_ad(btr_search_enabled);
-
---- a/storage/innobase/include/ha0ha.ic
-+++ b/storage/innobase/include/ha0ha.ic
-@@ -121,7 +121,7 @@
-
- ASSERT_HASH_MUTEX_OWN(table, fold);
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
-+// ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
- #endif /* UNIV_SYNC_DEBUG */
- ut_ad(btr_search_enabled);
-
-@@ -186,7 +186,7 @@
-
- ASSERT_HASH_MUTEX_OWN(table, fold);
- #ifdef UNIV_SYNC_DEBUG
-- ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
-+// ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
- #endif /* UNIV_SYNC_DEBUG */
- ut_ad(btr_search_enabled);
-
---- a/storage/innobase/include/buf0buf.h
-+++ b/storage/innobase/include/buf0buf.h
-@@ -1600,6 +1600,7 @@
- complete, though: there may
- have been hash collisions,
- record deletions, etc. */
-+ volatile rw_lock_t* btr_search_latch;
- /* @} */
- # ifdef UNIV_SYNC_DEBUG
- /** @name Debug fields */
---- a/storage/innobase/sync/sync0sync.c
-+++ b/storage/innobase/sync/sync0sync.c
-@@ -1222,7 +1222,6 @@
- case SYNC_OUTER_ANY_LATCH:
- case SYNC_FILE_FORMAT_TAG:
- case SYNC_DOUBLEWRITE:
-- case SYNC_SEARCH_SYS:
- case SYNC_TRX_LOCK_HEAP:
- case SYNC_KERNEL:
- case SYNC_IBUF_BITMAP_MUTEX:
-@@ -1243,6 +1242,7 @@
- ut_error;
- }
- break;
-+ case SYNC_SEARCH_SYS:
- case SYNC_BUF_LRU_LIST:
- case SYNC_BUF_FLUSH_LIST:
- case SYNC_BUF_PAGE_HASH:
+++ /dev/null
-# name : innodb_admin_command_base.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -12041,7 +12041,8 @@
- i_s_innodb_sys_foreign_cols,
- i_s_innodb_sys_stats,
- i_s_innodb_table_stats,
--i_s_innodb_index_stats
-+i_s_innodb_index_stats,
-+i_s_innodb_admin_command
- mysql_declare_plugin_end;
-
- /** @brief Initialize the default value of innodb_commit_concurrency.
---- a/storage/innobase/handler/i_s.cc
-+++ b/storage/innobase/handler/i_s.cc
-@@ -4243,3 +4243,140 @@
- STRUCT_FLD(__reserved1, NULL),
- STRUCT_FLD(flags, 0UL)
- };
-+
-+/***********************************************************************
-+*/
-+static ST_FIELD_INFO i_s_innodb_admin_command_info[] =
-+{
-+ {STRUCT_FLD(field_name, "result_message"),
-+ STRUCT_FLD(field_length, 1024),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ END_OF_ST_FIELD_INFO
-+};
-+
-+#ifndef INNODB_COMPATIBILITY_HOOKS
-+#error InnoDB needs MySQL to be built with #define INNODB_COMPATIBILITY_HOOKS
-+#endif
-+
-+extern "C" {
-+char **thd_query(MYSQL_THD thd);
-+}
-+
-+static
-+int
-+i_s_innodb_admin_command_fill(
-+/*==========================*/
-+ THD* thd,
-+ TABLE_LIST* tables,
-+ COND* cond)
-+{
-+ TABLE* i_s_table = (TABLE *) tables->table;
-+ char** query_str;
-+ char* ptr;
-+ char quote = '\0';
-+ const char* command_head = "XTRA_";
-+
-+ DBUG_ENTER("i_s_innodb_admin_command_fill");
-+
-+ /* deny access to non-superusers */
-+ if (check_global_access(thd, PROCESS_ACL)) {
-+ DBUG_RETURN(0);
-+ }
-+
-+ if(thd_sql_command(thd) != SQLCOM_SELECT) {
-+ field_store_string(i_s_table->field[0],
-+ "SELECT command is only accepted.");
-+ goto end_func;
-+ }
-+
-+ query_str = thd_query(thd);
-+ ptr = *query_str;
-+
-+ for (; *ptr; ptr++) {
-+ if (*ptr == quote) {
-+ quote = '\0';
-+ } else if (quote) {
-+ } else if (*ptr == '`' || *ptr == '"') {
-+ quote = *ptr;
-+ } else {
-+ long i;
-+ for (i = 0; command_head[i]; i++) {
-+ if (toupper((int)(unsigned char)(ptr[i]))
-+ != toupper((int)(unsigned char)
-+ (command_head[i]))) {
-+ goto nomatch;
-+ }
-+ }
-+ break;
-+nomatch:
-+ ;
-+ }
-+ }
-+
-+ if (!*ptr) {
-+ field_store_string(i_s_table->field[0],
-+ "No XTRA_* command in the SQL statement."
-+ " Please add /*!XTRA_xxxx*/ to the SQL.");
-+ goto end_func;
-+ }
-+
-+ if (!strncasecmp("XTRA_HELLO", ptr, 10)) {
-+ /* This is example command XTRA_HELLO */
-+
-+ ut_print_timestamp(stderr);
-+ fprintf(stderr, " InnoDB: administration command test for XtraDB"
-+ " 'XTRA_HELLO' was detected.\n");
-+
-+ field_store_string(i_s_table->field[0],
-+ "Hello!");
-+ goto end_func;
-+ }
-+
-+ field_store_string(i_s_table->field[0],
-+ "Undefined XTRA_* command.");
-+ goto end_func;
-+
-+end_func:
-+ if (schema_table_store_record(thd, i_s_table)) {
-+ DBUG_RETURN(1);
-+ } else {
-+ DBUG_RETURN(0);
-+ }
-+}
-+
-+static
-+int
-+i_s_innodb_admin_command_init(
-+/*==========================*/
-+ void* p)
-+{
-+ DBUG_ENTER("i_s_innodb_admin_command_init");
-+ ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
-+
-+ schema->fields_info = i_s_innodb_admin_command_info;
-+ schema->fill_table = i_s_innodb_admin_command_fill;
-+
-+ DBUG_RETURN(0);
-+}
-+
-+UNIV_INTERN struct st_mysql_plugin i_s_innodb_admin_command =
-+{
-+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-+ STRUCT_FLD(info, &i_s_info),
-+ STRUCT_FLD(name, "XTRADB_ADMIN_COMMAND"),
-+ STRUCT_FLD(author, "Percona"),
-+ STRUCT_FLD(descr, "XtraDB specific command acceptor"),
-+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-+ STRUCT_FLD(init, i_s_innodb_admin_command_init),
-+ STRUCT_FLD(deinit, i_s_common_deinit),
-+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
-+ STRUCT_FLD(status_vars, NULL),
-+ STRUCT_FLD(system_vars, NULL),
-+ STRUCT_FLD(__reserved1, NULL),
-+ STRUCT_FLD(flags, 0UL)
-+};
---- a/storage/innobase/handler/i_s.h
-+++ b/storage/innobase/handler/i_s.h
-@@ -46,5 +46,6 @@
- extern struct st_mysql_plugin i_s_innodb_sys_stats;
- extern struct st_mysql_plugin i_s_innodb_table_stats;
- extern struct st_mysql_plugin i_s_innodb_index_stats;
-+extern struct st_mysql_plugin i_s_innodb_admin_command;
-
- #endif /* i_s_h */
---- /dev/null
-+++ b/mysql-test/r/percona_xtradb_admin_command.result
-@@ -0,0 +1,6 @@
-+select * from information_schema.XTRADB_ADMIN_COMMAND;
-+result_message
-+No XTRA_* command in the SQL statement. Please add /*!XTRA_xxxx*/ to the SQL.
-+select * from information_schema.XTRADB_ADMIN_COMMAND /*!XTRA_HELLO*/;
-+result_message
-+Hello!
---- /dev/null
-+++ b/mysql-test/t/percona_xtradb_admin_command.test
-@@ -0,0 +1,3 @@
-+--source include/have_innodb.inc
-+select * from information_schema.XTRADB_ADMIN_COMMAND;
-+select * from information_schema.XTRADB_ADMIN_COMMAND /*!XTRA_HELLO*/;
---- a/mysql-test/r/mysqld--help-notwin.result
-+++ b/mysql-test/r/mysqld--help-notwin.result
-@@ -733,6 +733,10 @@
- -V, --version Output version information and exit.
- --wait-timeout=# The number of seconds the server waits for activity on a
- connection before closing it
-+ --xtradb-admin-command[=name]
-+ Enable or disable XTRADB_ADMIN_COMMAND plugin. Possible
-+ values are ON, OFF, FORCE (don't start if the plugin
-+ fails to load).
-
- Variables (--variable-name=value)
- abort-slave-event-count 0
-@@ -958,6 +962,7 @@
- updatable-views-with-limit YES
- verbose TRUE
- wait-timeout 28800
-+xtradb-admin-command ON
-
- To see what values a running MySQL server is using, type
- 'mysqladmin variables' instead of 'mysqld --verbose --help'.
+++ /dev/null
-# name : innodb_buffer_pool_pages_i_s.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/buf/buf0buf.c
-+++ b/storage/innobase/buf/buf0buf.c
-@@ -4163,6 +4163,36 @@
- mutex_exit(block_mutex);
- }
-
-+/********************************************************************//**
-+*/
-+UNIV_INTERN
-+buf_block_t*
-+buf_page_from_array(
-+/*================*/
-+ buf_pool_t* buf_pool,
-+ ulint n_block)
-+{
-+ ulint n_chunks, offset;
-+ buf_chunk_t* chunk;
-+
-+ ut_a(n_block < buf_pool->curr_size);
-+
-+ chunk = buf_pool->chunks;
-+ offset = n_block;
-+
-+ for (n_chunks = buf_pool->n_chunks; n_chunks--; chunk++) {
-+ if (offset < chunk->size) {
-+ return(&chunk->blocks[offset]);
-+ }
-+
-+ offset -= chunk->size;
-+ }
-+
-+ ut_error;
-+
-+ return(NULL);
-+}
-+
- /*********************************************************************//**
- Asserts that all file pages in the buffer are in a replaceable state.
- @return TRUE */
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -12338,6 +12338,9 @@
- i_s_innodb_sys_stats,
- i_s_innodb_table_stats,
- i_s_innodb_index_stats,
-+i_s_innodb_buffer_pool_pages,
-+i_s_innodb_buffer_pool_pages_index,
-+i_s_innodb_buffer_pool_pages_blob,
- i_s_innodb_admin_command
- mysql_declare_plugin_end;
-
---- a/storage/innobase/handler/i_s.cc
-+++ b/storage/innobase/handler/i_s.cc
-@@ -51,6 +51,7 @@
- #include "trx0sys.h" /* for trx_sys */
- #include "dict0dict.h" /* for dict_sys */
- #include "buf0lru.h" /* for XTRA_LRU_[DUMP/RESTORE] */
-+#include "btr0btr.h" /* for btr_page_get_index_id */
- }
-
- #define OK(expr) \
-@@ -4411,3 +4412,713 @@
- STRUCT_FLD(__reserved1, NULL),
- STRUCT_FLD(flags, 0UL)
- };
-+
-+/***********************************************************************
-+*/
-+static ST_FIELD_INFO i_s_innodb_buffer_pool_pages_fields_info[] =
-+{
-+ {STRUCT_FLD(field_name, "page_type"),
-+ STRUCT_FLD(field_length, 64),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "space_id"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "page_no"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "lru_position"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "fix_count"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "flush_type"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ END_OF_ST_FIELD_INFO
-+};
-+
-+static ST_FIELD_INFO i_s_innodb_buffer_pool_pages_index_fields_info[] =
-+{
-+ {STRUCT_FLD(field_name, "index_id"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "space_id"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "page_no"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "n_recs"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "data_size"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "hashed"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "access_time"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "modified"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "dirty"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "old"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "lru_position"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "fix_count"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "flush_type"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ END_OF_ST_FIELD_INFO
-+};
-+
-+static ST_FIELD_INFO i_s_innodb_buffer_pool_pages_blob_fields_info[] =
-+{
-+ {STRUCT_FLD(field_name, "space_id"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "page_no"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "compressed"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "part_len"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "next_page_no"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "lru_position"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "fix_count"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "flush_type"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ END_OF_ST_FIELD_INFO
-+};
-+
-+/***********************************************************************
-+Fill the dynamic table information_schema.innodb_buffer_pool_pages. */
-+static
-+int
-+i_s_innodb_buffer_pool_pages_fill(
-+/*================*/
-+ /* out: 0 on success, 1 on failure */
-+ THD* thd, /* in: thread */
-+ TABLE_LIST* tables, /* in/out: tables to fill */
-+ COND* cond) /* in: condition (ignored) */
-+{
-+ TABLE* table = (TABLE *) tables->table;
-+ int status = 0;
-+ ulint i;
-+
-+ DBUG_ENTER("i_s_innodb_buffer_pool_pages_fill");
-+
-+ /* deny access to non-superusers */
-+ if (check_global_access(thd, PROCESS_ACL)) {
-+
-+ DBUG_RETURN(0);
-+ }
-+
-+ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
-+
-+ for (i = 0; i < srv_buf_pool_instances; i++) {
-+ ulint n_block;
-+ buf_pool_t* buf_pool;
-+
-+ buf_pool = buf_pool_from_array(i);
-+
-+ buf_pool_mutex_enter(buf_pool);
-+
-+ for (n_block = 0; n_block < buf_pool->curr_size; n_block++) {
-+ buf_block_t* block = buf_page_from_array(buf_pool, n_block);
-+ const buf_frame_t* frame = block->frame;
-+
-+ char page_type[64];
-+
-+ switch(fil_page_get_type(frame))
-+ {
-+ case FIL_PAGE_INDEX:
-+ strcpy(page_type, "index");
-+ break;
-+ case FIL_PAGE_UNDO_LOG:
-+ strcpy(page_type, "undo_log");
-+ break;
-+ case FIL_PAGE_INODE:
-+ strcpy(page_type, "inode");
-+ break;
-+ case FIL_PAGE_IBUF_FREE_LIST:
-+ strcpy(page_type, "ibuf_free_list");
-+ break;
-+ case FIL_PAGE_TYPE_ALLOCATED:
-+ strcpy(page_type, "allocated");
-+ break;
-+ case FIL_PAGE_IBUF_BITMAP:
-+ strcpy(page_type, "bitmap");
-+ break;
-+ case FIL_PAGE_TYPE_SYS:
-+ strcpy(page_type, "sys");
-+ break;
-+ case FIL_PAGE_TYPE_TRX_SYS:
-+ strcpy(page_type, "trx_sys");
-+ break;
-+ case FIL_PAGE_TYPE_FSP_HDR:
-+ strcpy(page_type, "fsp_hdr");
-+ break;
-+ case FIL_PAGE_TYPE_XDES:
-+ strcpy(page_type, "xdes");
-+ break;
-+ case FIL_PAGE_TYPE_BLOB:
-+ strcpy(page_type, "blob");
-+ break;
-+ case FIL_PAGE_TYPE_ZBLOB:
-+ strcpy(page_type, "zblob");
-+ break;
-+ case FIL_PAGE_TYPE_ZBLOB2:
-+ strcpy(page_type, "zblob2");
-+ break;
-+ default:
-+ sprintf(page_type, "unknown (type=%li)", fil_page_get_type(frame));
-+ }
-+
-+ field_store_string(table->field[0], page_type);
-+ table->field[1]->store(block->page.space);
-+ table->field[2]->store(block->page.offset);
-+ table->field[3]->store(0);
-+ table->field[4]->store(block->page.buf_fix_count);
-+ table->field[5]->store(block->page.flush_type);
-+
-+ if (schema_table_store_record(thd, table)) {
-+ status = 1;
-+ break;
-+ }
-+
-+ }
-+
-+ buf_pool_mutex_exit(buf_pool);
-+ }
-+
-+ DBUG_RETURN(status);
-+}
-+
-+/***********************************************************************
-+Fill the dynamic table information_schema.innodb_buffer_pool_pages_index. */
-+static
-+int
-+i_s_innodb_buffer_pool_pages_index_fill(
-+/*================*/
-+ /* out: 0 on success, 1 on failure */
-+ THD* thd, /* in: thread */
-+ TABLE_LIST* tables, /* in/out: tables to fill */
-+ COND* cond) /* in: condition (ignored) */
-+{
-+ TABLE* table = (TABLE *) tables->table;
-+ int status = 0;
-+ ulint i;
-+ index_id_t index_id;
-+
-+ DBUG_ENTER("i_s_innodb_buffer_pool_pages_index_fill");
-+
-+ /* deny access to non-superusers */
-+ if (check_global_access(thd, PROCESS_ACL)) {
-+
-+ DBUG_RETURN(0);
-+ }
-+
-+ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
-+
-+ for (i = 0; i < srv_buf_pool_instances; i++) {
-+ ulint n_block;
-+ buf_pool_t* buf_pool;
-+
-+ buf_pool = buf_pool_from_array(i);
-+
-+ buf_pool_mutex_enter(buf_pool);
-+
-+ for (n_block = 0; n_block < buf_pool->curr_size; n_block++) {
-+ buf_block_t* block = buf_page_from_array(buf_pool, n_block);
-+ const buf_frame_t* frame = block->frame;
-+
-+ if (fil_page_get_type(frame) == FIL_PAGE_INDEX) {
-+ index_id = btr_page_get_index_id(frame);
-+ table->field[0]->store(index_id);
-+ table->field[1]->store(block->page.space);
-+ table->field[2]->store(block->page.offset);
-+ table->field[3]->store(page_get_n_recs(frame));
-+ table->field[4]->store(page_get_data_size(frame));
-+ table->field[5]->store(block->index != NULL);
-+ table->field[6]->store(block->page.access_time);
-+ table->field[7]->store(block->page.newest_modification != 0);
-+ table->field[8]->store(block->page.oldest_modification != 0);
-+ table->field[9]->store(block->page.old);
-+ table->field[10]->store(0);
-+ table->field[11]->store(block->page.buf_fix_count);
-+ table->field[12]->store(block->page.flush_type);
-+
-+ if (schema_table_store_record(thd, table)) {
-+ status = 1;
-+ break;
-+ }
-+ }
-+ }
-+
-+ buf_pool_mutex_exit(buf_pool);
-+ }
-+
-+ DBUG_RETURN(status);
-+}
-+
-+/***********************************************************************
-+Fill the dynamic table information_schema.innodb_buffer_pool_pages_index. */
-+static
-+int
-+i_s_innodb_buffer_pool_pages_blob_fill(
-+/*================*/
-+ /* out: 0 on success, 1 on failure */
-+ THD* thd, /* in: thread */
-+ TABLE_LIST* tables, /* in/out: tables to fill */
-+ COND* cond) /* in: condition (ignored) */
-+{
-+ TABLE* table = (TABLE *) tables->table;
-+ int status = 0;
-+ ulint i;
-+
-+ ulint part_len;
-+ ulint next_page_no;
-+
-+ DBUG_ENTER("i_s_innodb_buffer_pool_pages_blob_fill");
-+
-+ /* deny access to non-superusers */
-+ if (check_global_access(thd, PROCESS_ACL)) {
-+
-+ DBUG_RETURN(0);
-+ }
-+
-+ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
-+
-+ for (i = 0; i < srv_buf_pool_instances; i++) {
-+ ulint n_block;
-+ buf_pool_t* buf_pool;
-+
-+ buf_pool = buf_pool_from_array(i);
-+
-+ buf_pool_mutex_enter(buf_pool);
-+
-+ for (n_block = 0; n_block < buf_pool->curr_size; n_block++) {
-+ buf_block_t* block = buf_page_from_array(buf_pool, n_block);
-+ page_zip_des_t* block_page_zip = buf_block_get_page_zip(block);
-+ const buf_frame_t* frame = block->frame;
-+
-+ if (fil_page_get_type(frame) == FIL_PAGE_TYPE_BLOB) {
-+
-+ if (UNIV_LIKELY_NULL(block_page_zip)) {
-+ part_len = 0; /* hmm, can't figure it out */
-+
-+ next_page_no = mach_read_from_4(
-+ buf_block_get_frame(block)
-+ + FIL_PAGE_NEXT);
-+ } else {
-+ part_len = mach_read_from_4(
-+ buf_block_get_frame(block)
-+ + FIL_PAGE_DATA
-+ + 0 /*BTR_BLOB_HDR_PART_LEN*/);
-+
-+ next_page_no = mach_read_from_4(
-+ buf_block_get_frame(block)
-+ + FIL_PAGE_DATA
-+ + 4 /*BTR_BLOB_HDR_NEXT_PAGE_NO*/);
-+ }
-+
-+ table->field[0]->store(block->page.space);
-+ table->field[1]->store(block->page.offset);
-+ table->field[2]->store(block_page_zip != NULL);
-+ table->field[3]->store(part_len);
-+
-+ if(next_page_no == FIL_NULL)
-+ {
-+ table->field[4]->store(0);
-+ } else {
-+ table->field[4]->store(block->page.offset);
-+ }
-+
-+ table->field[5]->store(0);
-+ table->field[6]->store(block->page.buf_fix_count);
-+ table->field[7]->store(block->page.flush_type);
-+
-+ if (schema_table_store_record(thd, table)) {
-+ status = 1;
-+ break;
-+ }
-+
-+ }
-+ }
-+
-+ buf_pool_mutex_exit(buf_pool);
-+ }
-+
-+ DBUG_RETURN(status);
-+}
-+
-+/***********************************************************************
-+Bind the dynamic table information_schema.innodb_buffer_pool_pages. */
-+static
-+int
-+i_s_innodb_buffer_pool_pages_init(
-+/*=========*/
-+ /* out: 0 on success */
-+ void* p) /* in/out: table schema object */
-+{
-+ DBUG_ENTER("i_s_innodb_buffer_pool_pages_init");
-+ ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
-+
-+ schema->fields_info = i_s_innodb_buffer_pool_pages_fields_info;
-+ schema->fill_table = i_s_innodb_buffer_pool_pages_fill;
-+
-+ DBUG_RETURN(0);
-+}
-+
-+/***********************************************************************
-+Bind the dynamic table information_schema.innodb_buffer_pool_pages. */
-+static
-+int
-+i_s_innodb_buffer_pool_pages_index_init(
-+/*=========*/
-+ /* out: 0 on success */
-+ void* p) /* in/out: table schema object */
-+{
-+ DBUG_ENTER("i_s_innodb_buffer_pool_pages_index_init");
-+ ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
-+
-+ schema->fields_info = i_s_innodb_buffer_pool_pages_index_fields_info;
-+ schema->fill_table = i_s_innodb_buffer_pool_pages_index_fill;
-+
-+ DBUG_RETURN(0);
-+}
-+
-+/***********************************************************************
-+Bind the dynamic table information_schema.innodb_buffer_pool_pages. */
-+static
-+int
-+i_s_innodb_buffer_pool_pages_blob_init(
-+/*=========*/
-+ /* out: 0 on success */
-+ void* p) /* in/out: table schema object */
-+{
-+ DBUG_ENTER("i_s_innodb_buffer_pool_pages_blob_init");
-+ ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
-+
-+ schema->fields_info = i_s_innodb_buffer_pool_pages_blob_fields_info;
-+ schema->fill_table = i_s_innodb_buffer_pool_pages_blob_fill;
-+
-+ DBUG_RETURN(0);
-+}
-+
-+
-+UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages =
-+{
-+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
-+ /* int */
-+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-+
-+ /* pointer to type-specific plugin descriptor */
-+ /* void* */
-+ STRUCT_FLD(info, &i_s_info),
-+
-+ /* plugin name */
-+ /* const char* */
-+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES"),
-+
-+ /* plugin author (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(author, "Percona"),
-+
-+ /* general descriptive text (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(descr, "InnoDB buffer pool pages"),
-+
-+ /* the plugin license (PLUGIN_LICENSE_XXX) */
-+ /* int */
-+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-+
-+ /* the function to invoke when plugin is loaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_init),
-+
-+ /* the function to invoke when plugin is unloaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(deinit, i_s_common_deinit),
-+
-+ /* plugin version (for SHOW PLUGINS) */
-+ /* unsigned int */
-+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
-+
-+ /* struct st_mysql_show_var* */
-+ STRUCT_FLD(status_vars, NULL),
-+
-+ /* struct st_mysql_sys_var** */
-+ STRUCT_FLD(system_vars, NULL),
-+
-+ /* reserved for dependency checking */
-+ /* void* */
-+ STRUCT_FLD(__reserved1, NULL),
-+
-+ /* flags for plugin */
-+ /* unsigned long */
-+ STRUCT_FLD(flags, 0UL)
-+};
-+
-+UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_index =
-+{
-+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
-+ /* int */
-+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-+
-+ /* pointer to type-specific plugin descriptor */
-+ /* void* */
-+ STRUCT_FLD(info, &i_s_info),
-+
-+ /* plugin name */
-+ /* const char* */
-+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES_INDEX"),
-+
-+ /* plugin author (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(author, "Percona"),
-+
-+ /* general descriptive text (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(descr, "InnoDB buffer pool index pages"),
-+
-+ /* the plugin license (PLUGIN_LICENSE_XXX) */
-+ /* int */
-+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-+
-+ /* the function to invoke when plugin is loaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_index_init),
-+
-+ /* the function to invoke when plugin is unloaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(deinit, i_s_common_deinit),
-+
-+ /* plugin version (for SHOW PLUGINS) */
-+ /* unsigned int */
-+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
-+
-+ /* struct st_mysql_show_var* */
-+ STRUCT_FLD(status_vars, NULL),
-+
-+ /* struct st_mysql_sys_var** */
-+ STRUCT_FLD(system_vars, NULL),
-+
-+ /* reserved for dependency checking */
-+ /* void* */
-+ STRUCT_FLD(__reserved1, NULL),
-+
-+ /* flags for plugin */
-+ /* unsigned long */
-+ STRUCT_FLD(flags, 0UL)
-+};
-+
-+UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_blob =
-+{
-+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
-+ /* int */
-+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-+
-+ /* pointer to type-specific plugin descriptor */
-+ /* void* */
-+ STRUCT_FLD(info, &i_s_info),
-+
-+ /* plugin name */
-+ /* const char* */
-+ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES_BLOB"),
-+
-+ /* plugin author (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(author, "Percona"),
-+
-+ /* general descriptive text (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(descr, "InnoDB buffer pool blob pages"),
-+
-+ /* the plugin license (PLUGIN_LICENSE_XXX) */
-+ /* int */
-+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-+
-+ /* the function to invoke when plugin is loaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_blob_init),
-+
-+ /* the function to invoke when plugin is unloaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(deinit, i_s_common_deinit),
-+
-+ /* plugin version (for SHOW PLUGINS) */
-+ /* unsigned int */
-+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
-+
-+ /* struct st_mysql_show_var* */
-+ STRUCT_FLD(status_vars, NULL),
-+
-+ /* struct st_mysql_sys_var** */
-+ STRUCT_FLD(system_vars, NULL),
-+
-+ /* reserved for dependency checking */
-+ /* void* */
-+ STRUCT_FLD(__reserved1, NULL),
-+
-+ /* flags for plugin */
-+ /* unsigned long */
-+ STRUCT_FLD(flags, 0UL)
-+};
-+
---- a/storage/innobase/handler/i_s.h
-+++ b/storage/innobase/handler/i_s.h
-@@ -47,5 +47,8 @@
- extern struct st_mysql_plugin i_s_innodb_table_stats;
- extern struct st_mysql_plugin i_s_innodb_index_stats;
- extern struct st_mysql_plugin i_s_innodb_admin_command;
-+extern struct st_mysql_plugin i_s_innodb_buffer_pool_pages;
-+extern struct st_mysql_plugin i_s_innodb_buffer_pool_pages_index;
-+extern struct st_mysql_plugin i_s_innodb_buffer_pool_pages_blob;
-
- #endif /* i_s_h */
---- a/storage/innobase/include/buf0buf.h
-+++ b/storage/innobase/include/buf0buf.h
-@@ -1181,6 +1181,14 @@
- /*===========*/
- const buf_pool_t* buf_pool) /*!< in: buffer pool */
- __attribute__((nonnull, const));
-+/********************************************************************//**
-+*/
-+UNIV_INTERN
-+buf_block_t*
-+buf_page_from_array(
-+/*================*/
-+ buf_pool_t* buf_pool,
-+ ulint n_block);
- /******************************************************************//**
- Returns the buffer pool instance given a page instance
- @return buf_pool */
+++ /dev/null
-# name : innodb_buffer_pool_shm.patch
-# introduced : 12
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/buf/buf0buf.c
-+++ b/storage/innobase/buf/buf0buf.c
-@@ -1022,10 +1022,12 @@
- buf_block_t* block;
- byte* frame;
- ulint i;
-+ ulint size_target;
-
- /* Round down to a multiple of page size,
- although it already should be. */
- mem_size = ut_2pow_round(mem_size, UNIV_PAGE_SIZE);
-+ size_target = (mem_size / UNIV_PAGE_SIZE) - 1;
- /* Reserve space for the block descriptors. */
- mem_size += ut_2pow_round((mem_size / UNIV_PAGE_SIZE) * (sizeof *block)
- + (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
-@@ -1063,6 +1065,10 @@
- chunk->size = size;
- }
-
-+ if (chunk->size > size_target) {
-+ chunk->size = size_target;
-+ }
-+
- /* Init block structs and assign frames for them. Then we
- assign the frames to the first blocks (we already mapped the
- memory above). */
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -195,6 +195,8 @@
- static my_bool innobase_stats_on_metadata = TRUE;
- static my_bool innobase_large_prefix = FALSE;
- static my_bool innobase_use_sys_stats_table = FALSE;
-+static my_bool innobase_buffer_pool_shm_checksum = TRUE;
-+static uint innobase_buffer_pool_shm_key = 0;
-
-
- static char* internal_innobase_data_file_path = NULL;
-@@ -2706,6 +2708,12 @@
- srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
- srv_buf_pool_instances = (ulint) innobase_buffer_pool_instances;
-
-+ if (innobase_buffer_pool_shm_key) {
-+ fprintf(stderr,
-+ "InnoDB: Warning: innodb_buffer_pool_shm_key is deprecated function.\n"
-+ "InnoDB: innodb_buffer_pool_shm_key was ignored.\n");
-+ }
-+
- srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
-
- srv_n_file_io_threads = (ulint) innobase_file_io_threads;
-@@ -11863,6 +11871,16 @@
- "Number of buffer pool instances, set to higher value on high-end machines to increase scalability",
- NULL, NULL, 1L, 1L, MAX_BUFFER_POOLS, 1L);
-
-+static MYSQL_SYSVAR_UINT(buffer_pool_shm_key, innobase_buffer_pool_shm_key,
-+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
-+ "[Deprecated option] no effect",
-+ NULL, NULL, 0, 0, INT_MAX32, 0);
-+
-+static MYSQL_SYSVAR_BOOL(buffer_pool_shm_checksum, innobase_buffer_pool_shm_checksum,
-+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
-+ "[Deprecated option] no effect",
-+ NULL, NULL, TRUE);
-+
- static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
- PLUGIN_VAR_RQCMDARG,
- "Helps in performance tuning in heavily concurrent environments.",
-@@ -12209,6 +12227,8 @@
- MYSQL_SYSVAR(autoextend_increment),
- MYSQL_SYSVAR(buffer_pool_size),
- MYSQL_SYSVAR(buffer_pool_instances),
-+ MYSQL_SYSVAR(buffer_pool_shm_key),
-+ MYSQL_SYSVAR(buffer_pool_shm_checksum),
- MYSQL_SYSVAR(checksums),
- MYSQL_SYSVAR(fast_checksum),
- MYSQL_SYSVAR(commit_concurrency),
---- /dev/null
-+++ b/mysql-test/r/percona_innodb_buffer_pool_shm.result
-@@ -0,0 +1,4 @@
-+show variables like 'innodb_buffer_pool_shm%';
-+Variable_name Value
-+innodb_buffer_pool_shm_checksum ON
-+innodb_buffer_pool_shm_key 123456
---- /dev/null
-+++ b/mysql-test/t/percona_innodb_buffer_pool_shm-master.opt
-@@ -0,0 +1 @@
-+--innodb_buffer_pool_shm_key=123456
---- /dev/null
-+++ b/mysql-test/t/percona_innodb_buffer_pool_shm.test
-@@ -0,0 +1,2 @@
-+--source include/have_innodb.inc
-+show variables like 'innodb_buffer_pool_shm%';
+++ /dev/null
-# name : innodb_bug60788.patch
-# maintainer : Alexey
-#
-# Fix for MySQL bug #60788: InnoDB crashes with an assertion failure when
-# receiving a signal on pwrite()
-#
-# Changes InnoDB IO code so that fsync(), pread() and pwrite() are restarted
-# when interrupted by a signal.
-#
---- a/storage/innobase/os/os0file.c
-+++ b/storage/innobase/os/os0file.c
-@@ -2093,6 +2093,9 @@
- failures++;
-
- retry = TRUE;
-+ } else if (ret == -1 && errno == EINTR) {
-+ /* Handle signal interruptions correctly */
-+ retry = TRUE;
- } else {
-
- retry = FALSE;
-@@ -2223,6 +2226,7 @@
- off_t offs;
- #if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
- ssize_t n_bytes;
-+ ssize_t n_read;
- #endif /* HAVE_PREAD && !HAVE_BROKEN_PREAD */
- ulint sec;
- ulint ms;
-@@ -2263,7 +2267,18 @@
- os_n_pending_reads++;
- os_mutex_exit(os_file_count_mutex);
-
-- n_bytes = pread(file, buf, (ssize_t)n, offs);
-+ /* Handle signal interruptions correctly */
-+ for (n_bytes = 0; n_bytes < (ssize_t) n; ) {
-+ n_read = pread(file, buf, (ssize_t)n, offs);
-+ if (n_read > 0) {
-+ n_bytes += n_read;
-+ offs += n_read;
-+ } else if (n_read == -1 && errno == EINTR) {
-+ continue;
-+ } else {
-+ break;
-+ }
-+ }
-
- os_mutex_enter(os_file_count_mutex);
- os_file_n_pending_preads--;
-@@ -2282,6 +2297,7 @@
- {
- off_t ret_offset;
- ssize_t ret;
-+ ssize_t n_read;
- #ifndef UNIV_HOTBACKUP
- ulint i;
- #endif /* !UNIV_HOTBACKUP */
-@@ -2302,7 +2318,17 @@
- if (ret_offset < 0) {
- ret = -1;
- } else {
-- ret = read(file, buf, (ssize_t)n);
-+ /* Handle signal interruptions correctly */
-+ for (ret = 0; ret < (ssize_t) n; ) {
-+ n_read = read(file, buf, (ssize_t)n);
-+ if (n_read > 0) {
-+ ret += n_read;
-+ } else if (n_read == -1 && errno == EINTR) {
-+ continue;
-+ } else {
-+ break;
-+ }
-+ }
- }
-
- #ifndef UNIV_HOTBACKUP
-@@ -2341,6 +2367,7 @@
- offset */
- {
- ssize_t ret;
-+ ssize_t n_written;
- off_t offs;
-
- ut_a((offset & 0xFFFFFFFFUL) == offset);
-@@ -2368,7 +2395,18 @@
- os_n_pending_writes++;
- os_mutex_exit(os_file_count_mutex);
-
-- ret = pwrite(file, buf, (ssize_t)n, offs);
-+ /* Handle signal interruptions correctly */
-+ for (ret = 0; ret < (ssize_t) n; ) {
-+ n_written = pwrite(file, buf, (ssize_t)n, offs);
-+ if (n_written > 0) {
-+ ret += n_written;
-+ offs += n_written;
-+ } else if (n_written == -1 && errno == EINTR) {
-+ continue;
-+ } else {
-+ break;
-+ }
-+ }
-
- os_mutex_enter(os_file_count_mutex);
- os_file_n_pending_pwrites--;
-@@ -2415,7 +2453,17 @@
- goto func_exit;
- }
-
-- ret = write(file, buf, (ssize_t)n);
-+ /* Handle signal interruptions correctly */
-+ for (ret = 0; ret < (ssize_t) n; ) {
-+ n_written = write(file, buf, (ssize_t)n);
-+ if (n_written > 0) {
-+ ret += n_written;
-+ } else if (n_written == -1 && errno == EINTR) {
-+ continue;
-+ } else {
-+ break;
-+ }
-+ }
-
- # ifdef UNIV_DO_FLUSH
- if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC
+++ /dev/null
-# name : innodb_deadlock_count.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -691,6 +691,8 @@
- (char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG},
- {"dblwr_writes",
- (char*) &export_vars.innodb_dblwr_writes, SHOW_LONG},
-+ {"deadlocks",
-+ (char*) &export_vars.innodb_deadlocks, SHOW_LONG},
- {"dict_tables",
- (char*) &export_vars.innodb_dict_tables, SHOW_LONG},
- {"have_atomic_builtins",
---- a/storage/innobase/include/lock0lock.h
-+++ b/storage/innobase/include/lock0lock.h
-@@ -43,6 +43,7 @@
- #endif /* UNIV_DEBUG */
- /* Buffer for storing information about the most recent deadlock error */
- extern FILE* lock_latest_err_file;
-+extern ulint srv_n_lock_deadlock_count;
-
- /*********************************************************************//**
- Gets the size of a lock struct.
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -770,6 +770,7 @@
- ulint innodb_buffer_pool_read_ahead_evicted;/*!< srv_read_ahead evicted*/
- ulint innodb_dblwr_pages_written; /*!< srv_dblwr_pages_written */
- ulint innodb_dblwr_writes; /*!< srv_dblwr_writes */
-+ ulint innodb_deadlocks;
- ibool innodb_have_atomic_builtins; /*!< HAVE_ATOMIC_BUILTINS */
- ulint innodb_log_waits; /*!< srv_log_waits */
- ulint innodb_log_write_requests; /*!< srv_log_write_requests */
---- a/storage/innobase/lock/lock0lock.c
-+++ b/storage/innobase/lock/lock0lock.c
-@@ -3330,6 +3330,7 @@
- break;
-
- case LOCK_VICTIM_IS_START:
-+ srv_n_lock_deadlock_count++;
- fputs("*** WE ROLL BACK TRANSACTION (2)\n",
- lock_latest_err_file);
- break;
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -477,6 +477,7 @@
- static ulint srv_n_rows_deleted_old = 0;
- static ulint srv_n_rows_read_old = 0;
-
-+UNIV_INTERN ulint srv_n_lock_deadlock_count = 0;
- UNIV_INTERN ulint srv_n_lock_wait_count = 0;
- UNIV_INTERN ulint srv_n_lock_wait_current_count = 0;
- UNIV_INTERN ib_int64_t srv_n_lock_wait_time = 0;
-@@ -2293,6 +2294,7 @@
- export_vars.innodb_buffer_pool_pages_data = LRU_len;
- export_vars.innodb_buffer_pool_pages_dirty = flush_list_len;
- export_vars.innodb_buffer_pool_pages_free = free_len;
-+ export_vars.innodb_deadlocks = srv_n_lock_deadlock_count;
- #ifdef UNIV_DEBUG
- export_vars.innodb_buffer_pool_pages_latched
- = buf_get_latched_pages_number();
---- /dev/null
-+++ b/mysql-test/r/percona_innodb_deadlock_count.result
-@@ -0,0 +1,28 @@
-+# Establish connection con1 (user=root)
-+# Establish connection con2 (user=root)
-+# Establish connection con3 (user=root)
-+# Drop test table
-+drop table if exists t;
-+# Create test table
-+create table t(a INT PRIMARY KEY, b INT) engine=InnoDB;
-+# Insert two rows to test table
-+insert into t values(2,1);
-+insert into t values(1,2);
-+# Switch to connection con1
-+BEGIN;
-+SELECT b FROM t WHERE a=1 FOR UPDATE;
-+# Switch to connection con2
-+BEGIN;
-+SELECT b FROM t WHERE a=2 FOR UPDATE;
-+# Switch to connection con1
-+SELECT b FROM t WHERE a=2 FOR UPDATE;
-+# Switch to connection con2
-+SELECT b FROM t WHERE a=1 FOR UPDATE;
-+# Switch to connection con1
-+ROLLBACK;
-+# Switch to connection con2
-+ROLLBACK;
-+# Switch to connection con3
-+Deadlocks: 1
-+# Drop test table
-+drop table t;
---- /dev/null
-+++ b/mysql-test/t/percona_innodb_deadlock_count.test
-@@ -0,0 +1,61 @@
-+--source include/have_innodb.inc
-+--echo # Establish connection con1 (user=root)
-+connect (con1,localhost,root,,);
-+--echo # Establish connection con2 (user=root)
-+connect (con2,localhost,root,,);
-+--echo # Establish connection con3 (user=root)
-+connect (con3,localhost,root,,);
-+--echo # Drop test table
-+--disable_warnings
-+drop table if exists t;
-+--enable_warnings
-+
-+--echo # Create test table
-+create table t(a INT PRIMARY KEY, b INT) engine=InnoDB;
-+--echo # Insert two rows to test table
-+insert into t values(2,1);
-+insert into t values(1,2);
-+
-+#--echo # Save current deadlock count
-+let $current = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Innodb_deadlocks'`;
-+
-+--disable_result_log
-+
-+--echo # Switch to connection con1
-+connection con1;
-+BEGIN; SELECT b FROM t WHERE a=1 FOR UPDATE;
-+
-+--echo # Switch to connection con2
-+connection con2;
-+BEGIN; SELECT b FROM t WHERE a=2 FOR UPDATE;
-+
-+--echo # Switch to connection con1
-+connection con1;
-+SEND SELECT b FROM t WHERE a=2 FOR UPDATE;
-+
-+--echo # Switch to connection con2
-+connection con2;
-+SEND SELECT b FROM t WHERE a=1 FOR UPDATE;
-+
-+--echo # Switch to connection con1
-+connection con1;
-+--error 0, ER_LOCK_DEADLOCK
-+reap;
-+ROLLBACK;
-+
-+--echo # Switch to connection con2
-+connection con2;
-+--error 0, ER_LOCK_DEADLOCK
-+reap;
-+ROLLBACK;
-+
-+--echo # Switch to connection con3
-+connection con3;
-+let $result = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Innodb_deadlocks'`;
-+
-+--enable_result_log
-+
-+let $diff = `SELECT $result - $current`;
-+echo Deadlocks: $diff;
-+--echo # Drop test table
-+drop table t;
+++ /dev/null
-# name : innodb_dict_size_limit.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/btr/btr0sea.c
-+++ b/storage/innobase/btr/btr0sea.c
-@@ -1187,6 +1187,178 @@
- mem_free(folds);
- }
-
-+/************************************************************************
-+Drops a page hash index based on index */
-+UNIV_INTERN
-+void
-+btr_search_drop_page_hash_index_on_index(
-+/*=====================================*/
-+ dict_index_t* index) /* in: record descriptor */
-+{
-+
-+ hash_table_t* table;
-+ buf_block_t* block;
-+ ulint n_fields;
-+ ulint n_bytes;
-+ const page_t* page;
-+ const rec_t* rec;
-+ ulint fold;
-+ ulint prev_fold;
-+ index_id_t index_id;
-+ ulint n_cached;
-+ ulint n_recs;
-+ ulint* folds;
-+ ulint i, j;
-+ mem_heap_t* heap = NULL;
-+ ulint* offsets;
-+ ibool released_search_latch;
-+
-+ rw_lock_s_lock(&btr_search_latch);
-+
-+ table = btr_search_sys->hash_index;
-+
-+ for (j = 0; j < srv_buf_pool_instances; j++) {
-+ buf_pool_t* buf_pool;
-+
-+ buf_pool = buf_pool_from_array(j);
-+
-+ do {
-+ buf_chunk_t* chunks = buf_pool->chunks;
-+ buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
-+
-+ released_search_latch = FALSE;
-+
-+ while (--chunk >= chunks) {
-+ block = chunk->blocks;
-+ i = chunk->size;
-+
-+retry:
-+ for (; i--; block++) {
-+ if (buf_block_get_state(block)
-+ != BUF_BLOCK_FILE_PAGE
-+ || block->index != index
-+ || !block->index) {
-+ continue;
-+ }
-+
-+ page = block->frame;
-+
-+ /* from btr_search_drop_page_hash_index() */
-+ n_fields = block->curr_n_fields;
-+ n_bytes = block->curr_n_bytes;
-+
-+
-+ /* keeping latch order */
-+ rw_lock_s_unlock(&btr_search_latch);
-+ released_search_latch = TRUE;
-+ rw_lock_x_lock(&block->lock);
-+
-+
-+ ut_a(n_fields + n_bytes > 0);
-+
-+ n_recs = page_get_n_recs(page);
-+
-+ /* Calculate and cache fold values into an array for fast deletion
-+ from the hash index */
-+
-+ folds = mem_alloc(n_recs * sizeof(ulint));
-+
-+ n_cached = 0;
-+
-+ rec = page_get_infimum_rec(page);
-+ rec = page_rec_get_next_low(rec, page_is_comp(page));
-+
-+ index_id = btr_page_get_index_id(page);
-+
-+ ut_a(index_id == index->id);
-+
-+ prev_fold = 0;
-+
-+ offsets = NULL;
-+
-+ while (!page_rec_is_supremum(rec)) {
-+ offsets = rec_get_offsets(rec, index, offsets,
-+ n_fields + (n_bytes > 0), &heap);
-+ ut_a(rec_offs_n_fields(offsets) == n_fields + (n_bytes > 0));
-+ fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
-+
-+ if (fold == prev_fold && prev_fold != 0) {
-+
-+ goto next_rec;
-+ }
-+
-+ /* Remove all hash nodes pointing to this page from the
-+ hash chain */
-+
-+ folds[n_cached] = fold;
-+ n_cached++;
-+next_rec:
-+ rec = page_rec_get_next_low(rec, page_rec_is_comp(rec));
-+ prev_fold = fold;
-+ }
-+
-+ if (UNIV_LIKELY_NULL(heap)) {
-+ mem_heap_empty(heap);
-+ }
-+
-+ rw_lock_x_lock(&btr_search_latch);
-+
-+ if (UNIV_UNLIKELY(!block->index)) {
-+ goto cleanup;
-+ }
-+
-+ ut_a(block->index == index);
-+
-+ if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
-+ || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
-+ rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(&block->lock);
-+
-+ mem_free(folds);
-+
-+ rw_lock_s_lock(&btr_search_latch);
-+ goto retry;
-+ }
-+
-+ for (i = 0; i < n_cached; i++) {
-+
-+ ha_remove_all_nodes_to_page(table, folds[i], page);
-+ }
-+
-+ ut_a(index->search_info->ref_count > 0);
-+ index->search_info->ref_count--;
-+
-+ block->index = NULL;
-+
-+cleanup:
-+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
-+ if (UNIV_UNLIKELY(block->n_pointers)) {
-+ /* Corruption */
-+ ut_print_timestamp(stderr);
-+ fprintf(stderr,
-+"InnoDB: The adaptive hash index is corrupted. After dropping\n"
-+"InnoDB: the hash index to a page of %s, %lu hash nodes still remain.\n",
-+ index->name, (ulong) block->n_pointers);
-+ }
-+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
-+ rw_lock_x_unlock(&btr_search_latch);
-+ rw_lock_x_unlock(&block->lock);
-+
-+ mem_free(folds);
-+
-+ rw_lock_s_lock(&btr_search_latch);
-+ }
-+ }
-+ } while (released_search_latch);
-+ }
-+
-+ rw_lock_s_unlock(&btr_search_latch);
-+
-+ if (UNIV_LIKELY_NULL(heap)) {
-+ mem_heap_free(heap);
-+ }
-+}
-+
- /********************************************************************//**
- Drops a possible page hash index when a page is evicted from the buffer pool
- or freed in a file segment. */
---- a/storage/innobase/buf/buf0buf.c
-+++ b/storage/innobase/buf/buf0buf.c
-@@ -294,14 +294,14 @@
- # endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
- #endif /* UNIV_PFS_MUTEX || UNIV_PFS_RWLOCK */
-
--/** A chunk of buffers. The buffer pool is allocated in chunks. */
--struct buf_chunk_struct{
-- ulint mem_size; /*!< allocated size of the chunk */
-- ulint size; /*!< size of frames[] and blocks[] */
-- void* mem; /*!< pointer to the memory area which
-- was allocated for the frames */
-- buf_block_t* blocks; /*!< array of buffer control blocks */
--};
-+/** A chunk of buffers. The buffer pool is allocated in chunks. (moved to buf0buf.h)*/
-+//struct buf_chunk_struct{
-+// ulint mem_size; /*!< allocated size of the chunk */
-+// ulint size; /*!< size of frames[] and blocks[] */
-+// void* mem; /*!< pointer to the memory area which
-+// was allocated for the frames */
-+// buf_block_t* blocks; /*!< array of buffer control blocks */
-+//};
- #endif /* !UNIV_HOTBACKUP */
-
- /********************************************************************//**
---- a/storage/innobase/dict/dict0boot.c
-+++ b/storage/innobase/dict/dict0boot.c
-@@ -284,6 +284,7 @@
- system tables */
- /*-------------------------*/
- table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, 0);
-+ table->n_mysql_handles_opened = 1; /* for pin */
-
- dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
- dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0);
-@@ -336,6 +337,7 @@
-
- /*-------------------------*/
- table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, 0);
-+ table->n_mysql_handles_opened = 1; /* for pin */
-
- dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
- dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
-@@ -368,6 +370,7 @@
-
- /*-------------------------*/
- table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, 0);
-+ table->n_mysql_handles_opened = 1; /* for pin */
-
- dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
- dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0);
-@@ -413,6 +416,7 @@
-
- /*-------------------------*/
- table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, 0);
-+ table->n_mysql_handles_opened = 1; /* for pin */
-
- dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
- dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
---- a/storage/innobase/dict/dict0crea.c
-+++ b/storage/innobase/dict/dict0crea.c
-@@ -1209,6 +1209,9 @@
- /* Foreign constraint system tables have already been
- created, and they are ok */
-
-+ table1->n_mysql_handles_opened = 1; /* for pin */
-+ table2->n_mysql_handles_opened = 1; /* for pin */
-+
- mutex_exit(&(dict_sys->mutex));
-
- return(DB_SUCCESS);
-@@ -1290,6 +1293,11 @@
-
- trx_commit_for_mysql(trx);
-
-+ table1 = dict_table_get_low("SYS_FOREIGN");
-+ table2 = dict_table_get_low("SYS_FOREIGN_COLS");
-+ table1->n_mysql_handles_opened = 1; /* for pin */
-+ table2->n_mysql_handles_opened = 1; /* for pin */
-+
- row_mysql_unlock_data_dictionary(trx);
-
- trx_free_for_mysql(trx);
---- a/storage/innobase/dict/dict0dict.c
-+++ b/storage/innobase/dict/dict0dict.c
-@@ -626,6 +626,8 @@
-
- table = dict_table_get_on_id_low(table_id);
-
-+ dict_table_LRU_trim(table);
-+
- mutex_exit(&(dict_sys->mutex));
-
- return(table);
-@@ -744,6 +746,8 @@
- table->n_mysql_handles_opened++;
- }
-
-+ dict_table_LRU_trim(table);
-+
- mutex_exit(&(dict_sys->mutex));
-
- if (table != NULL) {
-@@ -1264,6 +1268,64 @@
- dict_mem_table_free(table);
- }
-
-+/**************************************************************************
-+Frees tables from the end of table_LRU if the dictionary cache occupies
-+too much space. */
-+UNIV_INTERN
-+void
-+dict_table_LRU_trim(
-+/*================*/
-+ dict_table_t* self)
-+{
-+ dict_table_t* table;
-+ dict_table_t* prev_table;
-+ dict_foreign_t* foreign;
-+ ulint n_removed;
-+ ulint n_have_parent;
-+ ulint cached_foreign_tables;
-+
-+#ifdef UNIV_SYNC_DEBUG
-+ ut_ad(mutex_own(&(dict_sys->mutex)));
-+#endif /* UNIV_SYNC_DEBUG */
-+
-+retry:
-+ n_removed = n_have_parent = 0;
-+ table = UT_LIST_GET_LAST(dict_sys->table_LRU);
-+
-+ while ( srv_dict_size_limit && table
-+ && ((dict_sys->table_hash->n_cells
-+ + dict_sys->table_id_hash->n_cells) * sizeof(hash_cell_t)
-+ + dict_sys->size) > srv_dict_size_limit ) {
-+ prev_table = UT_LIST_GET_PREV(table_LRU, table);
-+
-+ if (table == self || table->n_mysql_handles_opened)
-+ goto next_loop;
-+
-+ cached_foreign_tables = 0;
-+ foreign = UT_LIST_GET_FIRST(table->foreign_list);
-+ while (foreign != NULL) {
-+ if (foreign->referenced_table)
-+ cached_foreign_tables++;
-+ foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
-+ }
-+
-+ if (cached_foreign_tables == 0) {
-+ dict_table_remove_from_cache(table);
-+ n_removed++;
-+ } else {
-+ n_have_parent++;
-+ }
-+next_loop:
-+ table = prev_table;
-+ }
-+
-+ if ( srv_dict_size_limit && n_have_parent && n_removed
-+ && ((dict_sys->table_hash->n_cells
-+ + dict_sys->table_id_hash->n_cells) * sizeof(hash_cell_t)
-+ + dict_sys->size) > srv_dict_size_limit )
-+ goto retry;
-+}
-+
- /****************************************************************//**
- If the given column name is reserved for InnoDB system columns, return
- TRUE.
-@@ -1768,6 +1830,11 @@
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
- ut_ad(mutex_own(&(dict_sys->mutex)));
-
-+ /* remove all entry of the index from adaptive hash index,
-+ because removing from adaptive hash index needs dict_index */
-+ if (btr_search_enabled && srv_dict_size_limit)
-+ btr_search_drop_page_hash_index_on_index(index);
-+
- /* We always create search info whether or not adaptive
- hash index is enabled or not. */
- info = index->search_info;
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -677,6 +677,8 @@
- (char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG},
- {"dblwr_writes",
- (char*) &export_vars.innodb_dblwr_writes, SHOW_LONG},
-+ {"dict_tables",
-+ (char*) &export_vars.innodb_dict_tables, SHOW_LONG},
- {"have_atomic_builtins",
- (char*) &export_vars.innodb_have_atomic_builtins, SHOW_BOOL},
- {"log_waits",
-@@ -11813,6 +11815,11 @@
- NULL, NULL, 0, 0, 1, 0);
- #endif
-
-+static MYSQL_SYSVAR_ULONG(dict_size_limit, srv_dict_size_limit,
-+ PLUGIN_VAR_RQCMDARG,
-+ "Limit the allocated memory for dictionary cache. (0: unlimited)",
-+ NULL, NULL, 0, 0, LONG_MAX, 0);
-+
- static struct st_mysql_sys_var* innobase_system_variables[]= {
- MYSQL_SYSVAR(additional_mem_pool_size),
- MYSQL_SYSVAR(autoextend_increment),
-@@ -11882,6 +11889,7 @@
- MYSQL_SYSVAR(flush_neighbor_pages),
- MYSQL_SYSVAR(read_ahead),
- MYSQL_SYSVAR(adaptive_flushing_method),
-+ MYSQL_SYSVAR(dict_size_limit),
- MYSQL_SYSVAR(use_sys_malloc),
- MYSQL_SYSVAR(use_native_aio),
- MYSQL_SYSVAR(change_buffering),
---- a/storage/innobase/ibuf/ibuf0ibuf.c
-+++ b/storage/innobase/ibuf/ibuf0ibuf.c
-@@ -575,6 +575,7 @@
-
- /* Use old-style record format for the insert buffer. */
- table = dict_mem_table_create(IBUF_TABLE_NAME, IBUF_SPACE_ID, 1, 0);
-+ table->n_mysql_handles_opened = 1; /* for pin */
-
- dict_mem_table_add_col(table, heap, "DUMMY_COLUMN", DATA_BINARY, 0, 0);
-
---- a/storage/innobase/include/btr0sea.h
-+++ b/storage/innobase/include/btr0sea.h
-@@ -140,6 +140,13 @@
- s- or x-latched, or an index page
- for which we know that
- block->buf_fix_count == 0 */
-+/************************************************************************
-+Drops a page hash index based on index */
-+UNIV_INTERN
-+void
-+btr_search_drop_page_hash_index_on_index(
-+/*=====================================*/
-+ dict_index_t* index); /* in: record descriptor */
- /********************************************************************//**
- Drops a possible page hash index when a page is evicted from the buffer pool
- or freed in a file segment. */
---- a/storage/innobase/include/buf0buf.h
-+++ b/storage/innobase/include/buf0buf.h
-@@ -1595,6 +1595,15 @@
- #define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b))
- /* @} */
-
-+/** A chunk of buffers. The buffer pool is allocated in chunks. */
-+struct buf_chunk_struct{
-+ ulint mem_size; /*!< allocated size of the chunk */
-+ ulint size; /*!< size of frames[] and blocks[] */
-+ void* mem; /*!< pointer to the memory area which
-+ was allocated for the frames */
-+ buf_block_t* blocks; /*!< array of buffer control blocks */
-+};
-+
- /** @brief The buffer pool statistics structure. */
- struct buf_pool_stat_struct{
- ulint n_page_gets; /*!< number of page gets performed;
---- a/storage/innobase/include/dict0dict.h
-+++ b/storage/innobase/include/dict0dict.h
-@@ -1200,6 +1200,12 @@
- /*====================================*/
- dict_table_t* table, /*!< in: table */
- const char* name); /*!< in: name of the index to find */
-+
-+UNIV_INTERN
-+void
-+dict_table_LRU_trim(
-+/*================*/
-+ dict_table_t* self);
- /* Buffers for storing detailed information about the latest foreign key
- and unique key errors */
- extern FILE* dict_foreign_err_file;
---- a/storage/innobase/include/dict0dict.ic
-+++ b/storage/innobase/include/dict0dict.ic
-@@ -825,6 +825,13 @@
- HASH_SEARCH(name_hash, dict_sys->table_hash, table_fold,
- dict_table_t*, table, ut_ad(table->cached),
- !strcmp(table->name, table_name));
-+
-+ /* make young in table_LRU */
-+ if (table) {
-+ UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
-+ UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
-+ }
-+
- return(table);
- }
-
-@@ -918,6 +925,12 @@
- table = dict_load_table_on_id(table_id);
- }
-
-+ /* make young in table_LRU */
-+ if (table) {
-+ UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
-+ UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
-+ }
-+
- ut_ad(!table || table->cached);
-
- /* TODO: should get the type information from MySQL */
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -234,6 +234,7 @@
- extern ulint srv_read_ahead;
- extern ulint srv_adaptive_flushing_method;
-
-+extern ulint srv_dict_size_limit;
- /*-------------------------------------------*/
-
- extern ulint srv_n_rows_inserted;
-@@ -717,6 +718,7 @@
- ulint innodb_data_writes; /*!< I/O write requests */
- ulint innodb_data_written; /*!< Data bytes written */
- ulint innodb_data_reads; /*!< I/O read requests */
-+ ulint innodb_dict_tables;
- ulint innodb_buffer_pool_pages_total; /*!< Buffer pool size */
- ulint innodb_buffer_pool_pages_data; /*!< Data pages */
- ulint innodb_buffer_pool_pages_dirty; /*!< Dirty data pages */
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -417,6 +417,8 @@
- UNIV_INTERN ulint srv_enable_unsafe_group_commit = 0; /* 0:disable 1:enable */
- UNIV_INTERN ulint srv_read_ahead = 3; /* 1: random 2: linear 3: Both */
- UNIV_INTERN ulint srv_adaptive_flushing_method = 0; /* 0: native 1: estimate 2: keep_average */
-+
-+UNIV_INTERN ulint srv_dict_size_limit = 0;
- /*-------------------------------------------*/
- UNIV_INTERN ulong srv_n_spin_wait_rounds = 30;
- UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500;
-@@ -2225,6 +2227,7 @@
- export_vars.innodb_data_reads = os_n_file_reads;
- export_vars.innodb_data_writes = os_n_file_writes;
- export_vars.innodb_data_written = srv_data_written;
-+ export_vars.innodb_dict_tables= (dict_sys ? UT_LIST_GET_LEN(dict_sys->table_LRU) : 0);
- export_vars.innodb_buffer_pool_read_requests = stat.n_page_gets;
- export_vars.innodb_buffer_pool_write_requests
- = srv_buf_pool_write_requests;
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/r/innodb_dict_size_limit_basic.result
-@@ -0,0 +1,3 @@
-+SELECT @@global.innodb_dict_size_limit;
-+@@global.innodb_dict_size_limit
-+0
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/t/innodb_dict_size_limit_basic.test
-@@ -0,0 +1 @@
-+SELECT @@global.innodb_dict_size_limit;
+++ /dev/null
-# name : innodb_expand_fast_index_creation.patch
-# maintainer : Alexey
-#
-# Expands the applicability of InnoDB fast index creation to mysqldump,
-# ALTER TABLE and OPTIMIZE TABLE.
-#
-#
---- a/client/client_priv.h
-+++ b/client/client_priv.h
-@@ -92,6 +92,7 @@
- OPT_NO_REMOVE_EOL_CARRET,
- OPT_DEFAULT_AUTH,
- OPT_DEFAULT_PLUGIN,
-+ OPT_INNODB_OPTIMIZE_KEYS,
- OPT_MAX_CLIENT_OPTION
- };
-
---- a/client/mysqldump.c
-+++ b/client/mysqldump.c
-@@ -47,6 +47,7 @@
- #include <m_ctype.h>
- #include <hash.h>
- #include <stdarg.h>
-+#include <my_list.h>
-
- #include "client_priv.h"
- #include "mysql.h"
-@@ -145,6 +146,8 @@
-
- static my_bool server_supports_sql_no_fcache= FALSE;
-
-+static my_bool opt_innodb_optimize_keys= FALSE;
-+
- /*
- Dynamic_string wrapper functions. In this file use these
- wrappers, they will terminate the process if there is
-@@ -190,6 +193,8 @@
-
- HASH ignore_table;
-
-+LIST *skipped_keys_list;
-+
- static struct my_option my_long_options[] =
- {
- {"all-databases", 'A',
-@@ -353,6 +358,11 @@
- "in dump produced with --dump-slave.", &opt_include_master_host_port,
- &opt_include_master_host_port, 0, GET_BOOL, NO_ARG,
- 0, 0, 0, 0, 0, 0},
-+ {"innodb-optimize-keys", OPT_INNODB_OPTIMIZE_KEYS,
-+ "Use InnoDB fast index creation by creating secondary indexes after "
-+ "dumping the data.",
-+ &opt_innodb_optimize_keys, &opt_innodb_optimize_keys, 0, GET_BOOL, NO_ARG,
-+ 0, 0, 0, 0, 0, 0},
- {"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
- &opt_ignore, &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
- 0, 0},
-@@ -2240,6 +2250,189 @@
- }
-
- /*
-+ Parse the specified key definition string and check if the key indexes
-+ any of the columns from ignored_columns.
-+*/
-+static my_bool contains_ignored_column(HASH *ignored_columns, char *keydef)
-+{
-+ char *leftp, *rightp;
-+
-+ if ((leftp = strchr(keydef, '(')) &&
-+ (rightp = strchr(leftp, ')')) &&
-+ rightp > leftp + 3 && /* (`...`) */
-+ leftp[1] == '`' &&
-+ rightp[-1] == '`' &&
-+ my_hash_search(ignored_columns, (uchar *) leftp + 2, rightp - leftp - 3))
-+ return TRUE;
-+
-+ return FALSE;
-+}
-+
-+
-+/*
-+ Remove secondary/foreign key definitions from a given SHOW CREATE TABLE string
-+ and store them into a temporary list to be used later.
-+
-+ SYNOPSIS
-+ skip_secondary_keys()
-+ create_str SHOW CREATE TABLE output
-+ has_pk TRUE, if the table has PRIMARY KEY
-+ (or UNIQUE key on non-nullable columns)
-+
-+
-+ DESCRIPTION
-+
-+ Stores all lines starting with "KEY" or "UNIQUE KEY"
-+ into skipped_keys_list and removes them from the input string.
-+ Ignoring FOREIGN KEYS constraints when creating the table is ok, because
-+ mysqldump sets foreign_key_checks to 0 anyway.
-+*/
-+
-+static void skip_secondary_keys(char *create_str, my_bool has_pk)
-+{
-+ char *ptr, *strend;
-+ char *last_comma = NULL;
-+ HASH ignored_columns;
-+ my_bool pk_processed= FALSE;
-+
-+ if (my_hash_init(&ignored_columns, charset_info, 16, 0, 0,
-+ (my_hash_get_key) get_table_key, my_free, 0))
-+ exit(EX_EOM);
-+
-+ strend= create_str + strlen(create_str);
-+
-+ ptr= create_str;
-+ while (*ptr)
-+ {
-+ char *tmp, *orig_ptr, c;
-+ my_bool is_unique= FALSE;
-+
-+ orig_ptr= ptr;
-+ /* Skip leading whitespace */
-+ while (*ptr && my_isspace(charset_info, *ptr))
-+ ptr++;
-+
-+ /* Read the next line */
-+ for (tmp= ptr; *tmp != '\n' && *tmp != '\0'; tmp++);
-+
-+ c= *tmp;
-+ *tmp= '\0'; /* so strstr() only processes the current line */
-+
-+ /* Is it a secondary index definition? */
-+ if (c == '\n' &&
-+ (((is_unique= !strncmp(ptr, "UNIQUE KEY ", sizeof("UNIQUE KEY ")-1)) &&
-+ (pk_processed || !has_pk)) ||
-+ !strncmp(ptr, "KEY ", sizeof("KEY ") - 1)) &&
-+ !contains_ignored_column(&ignored_columns, ptr))
-+ {
-+ char *data, *end= tmp - 1;
-+
-+ /* Remove the trailing comma */
-+ if (*end == ',')
-+ end--;
-+ data= my_strndup(ptr, end - ptr + 1, MYF(MY_FAE));
-+ skipped_keys_list= list_cons(data, skipped_keys_list);
-+
-+ memmove(orig_ptr, tmp + 1, strend - tmp);
-+ ptr= orig_ptr;
-+ strend-= tmp + 1 - ptr;
-+
-+ /* Remove the comma on the previos line */
-+ if (last_comma != NULL)
-+ {
-+ *last_comma= ' ';
-+ }
-+ }
-+ else
-+ {
-+ char *end;
-+
-+ if (last_comma != NULL && *ptr != ')')
-+ {
-+ /*
-+ It's not the last line of CREATE TABLE, so we have skipped a key
-+ definition. We have to restore the last removed comma.
-+ */
-+ *last_comma= ',';
-+ }
-+
-+ if ((has_pk && is_unique && !pk_processed) ||
-+ !strncmp(ptr, "PRIMARY KEY ", sizeof("PRIMARY KEY ") - 1))
-+ pk_processed= TRUE;
-+
-+ if (strstr(ptr, "AUTO_INCREMENT") && *ptr == '`')
-+ {
-+ /*
-+ If a secondary key is defined on this column later,
-+ it cannot be skipped, as CREATE TABLE would fail on import.
-+ */
-+ for (end= ptr + 1; *end != '`' && *end != '\0'; end++);
-+ if (*end == '`' && end > ptr + 1 &&
-+ my_hash_insert(&ignored_columns,
-+ (uchar *) my_strndup(ptr + 1,
-+ end - ptr - 1, MYF(0))))
-+ {
-+ exit(EX_EOM);
-+ }
-+ }
-+
-+ *tmp= c;
-+
-+ if (tmp[-1] == ',')
-+ last_comma= tmp - 1;
-+ ptr= (*tmp == '\0') ? tmp : tmp + 1;
-+ }
-+ }
-+
-+ my_hash_free(&ignored_columns);
-+}
-+
-+/*
-+ Check if the table has a primary key defined either explicitly or
-+ implicitly (i.e. a unique key on non-nullable columns).
-+
-+ SYNOPSIS
-+ my_bool has_primary_key(const char *table_name)
-+
-+ table_name quoted table name
-+
-+ RETURNS TRUE if the table has a primary key
-+
-+ DESCRIPTION
-+*/
-+
-+static my_bool has_primary_key(const char *table_name)
-+{
-+ MYSQL_RES *res= NULL;
-+ MYSQL_ROW row;
-+ char query_buff[QUERY_LENGTH];
-+ my_bool has_pk= TRUE;
-+
-+ my_snprintf(query_buff, sizeof(query_buff),
-+ "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE "
-+ "TABLE_SCHEMA=DATABASE() AND TABLE_NAME='%s' AND "
-+ "COLUMN_KEY='PRI'", table_name);
-+ if (mysql_query(mysql, query_buff) || !(res= mysql_store_result(mysql)) ||
-+ !(row= mysql_fetch_row(res)))
-+ {
-+ fprintf(stderr, "Warning: Couldn't determine if table %s has a "
-+ "primary key (%s). "
-+ "--innodb-optimize-keys may work inefficiently.\n",
-+ table_name, mysql_error(mysql));
-+ goto cleanup;
-+ }
-+
-+ has_pk= atoi(row[0]) > 0;
-+
-+cleanup:
-+ if (res)
-+ mysql_free_result(res);
-+
-+ return has_pk;
-+}
-+
-+
-+/*
- get_table_structure -- retrievs database structure, prints out corresponding
- CREATE statement and fills out insert_pat if the table is the type we will
- be dumping.
-@@ -2276,6 +2469,7 @@
- int len;
- MYSQL_RES *result;
- MYSQL_ROW row;
-+ my_bool has_pk= FALSE;
- DBUG_ENTER("get_table_structure");
- DBUG_PRINT("enter", ("db: %s table: %s", db, table));
-
-@@ -2317,6 +2511,9 @@
- result_table= quote_name(table, table_buff, 1);
- opt_quoted_table= quote_name(table, table_buff2, 0);
-
-+ if (opt_innodb_optimize_keys && !strcmp(table_type, "InnoDB"))
-+ has_pk= has_primary_key(table);
-+
- if (opt_order_by_primary)
- order_by= primary_key_fields(result_table);
-
-@@ -2480,6 +2677,9 @@
-
- row= mysql_fetch_row(result);
-
-+ if (opt_innodb_optimize_keys && !strcmp(table_type, "InnoDB"))
-+ skip_secondary_keys(row[1], has_pk);
-+
- fprintf(sql_file, (opt_compatible_mode & 3) ? "%s;\n" :
- "/*!40101 SET @saved_cs_client = @@character_set_client */;\n"
- "/*!40101 SET character_set_client = utf8 */;\n"
-@@ -3574,6 +3774,27 @@
- goto err;
- }
-
-+ /* Perform delayed secondary index creation for --innodb-optimize-keys */
-+ if (skipped_keys_list)
-+ {
-+ uint keys;
-+ skipped_keys_list= list_reverse(skipped_keys_list);
-+ fprintf(md_result_file, "ALTER TABLE %s ", opt_quoted_table);
-+ for (keys= list_length(skipped_keys_list); keys > 0; keys--)
-+ {
-+ LIST *node= skipped_keys_list;
-+ char *def= node->data;
-+
-+ fprintf(md_result_file, "ADD %s%s", def, (keys > 1) ? ", " : ";\n");
-+
-+ skipped_keys_list= list_delete(skipped_keys_list, node);
-+ my_free(def);
-+ my_free(node);
-+ }
-+
-+ DBUG_ASSERT(skipped_keys_list == NULL);
-+ }
-+
- /* Moved enable keys to before unlock per bug 15977 */
- if (opt_disable_keys)
- {
---- /dev/null
-+++ b/mysql-test/r/percona_mysqldump_innodb_optimize_keys.result
-@@ -0,0 +1,367 @@
-+#
-+# Test the --innodb-optimize-keys option.
-+#
-+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, KEY(b)) ENGINE=MyISAM;
-+######################################
-+
-+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
-+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
-+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
-+/*!40101 SET NAMES utf8 */;
-+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
-+/*!40103 SET TIME_ZONE='+00:00' */;
-+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
-+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-+DROP TABLE IF EXISTS `t1`;
-+/*!40101 SET @saved_cs_client = @@character_set_client */;
-+/*!40101 SET character_set_client = utf8 */;
-+CREATE TABLE `t1` (
-+ `a` int(11) NOT NULL,
-+ `b` int(11) DEFAULT NULL,
-+ PRIMARY KEY (`a`),
-+ KEY `b` (`b`)
-+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
-+/*!40101 SET character_set_client = @saved_cs_client */;
-+
-+LOCK TABLES `t1` WRITE;
-+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
-+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
-+UNLOCK TABLES;
-+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
-+
-+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
-+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
-+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
-+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
-+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
-+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
-+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-+
-+######################################
-+DROP TABLE t1;
-+CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
-+INSERT INTO t2 VALUES (0), (1), (2);
-+CREATE TABLE t1 (
-+id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-+a INT, b VARCHAR(255), c DECIMAL(10,3),
-+KEY (b),
-+UNIQUE KEY uniq(c,a),
-+FOREIGN KEY (a) REFERENCES t2(a) ON DELETE CASCADE
-+) ENGINE=InnoDB;
-+INSERT INTO t1(a,b,c) VALUES (0, "0", 0.0), (1, "1", 1.1), (2, "2", 2.2);
-+######################################
-+
-+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
-+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
-+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
-+/*!40101 SET NAMES utf8 */;
-+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
-+/*!40103 SET TIME_ZONE='+00:00' */;
-+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
-+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-+DROP TABLE IF EXISTS `t1`;
-+/*!40101 SET @saved_cs_client = @@character_set_client */;
-+/*!40101 SET character_set_client = utf8 */;
-+CREATE TABLE `t1` (
-+ `id` int(11) NOT NULL AUTO_INCREMENT,
-+ `a` int(11) DEFAULT NULL,
-+ `b` varchar(255) DEFAULT NULL,
-+ `c` decimal(10,3) DEFAULT NULL,
-+ PRIMARY KEY (`id`),
-+ CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t2` (`a`) ON DELETE CASCADE
-+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
-+/*!40101 SET character_set_client = @saved_cs_client */;
-+
-+LOCK TABLES `t1` WRITE;
-+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
-+INSERT INTO `t1` VALUES (1,0,'0',0.000),(2,1,'1',1.100),(3,2,'2',2.200);
-+ALTER TABLE `t1` ADD UNIQUE KEY `uniq` (`c`,`a`), ADD KEY `b` (`b`), ADD KEY `a` (`a`);
-+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
-+UNLOCK TABLES;
-+DROP TABLE IF EXISTS `t2`;
-+/*!40101 SET @saved_cs_client = @@character_set_client */;
-+/*!40101 SET character_set_client = utf8 */;
-+CREATE TABLE `t2` (
-+ `a` int(11) NOT NULL,
-+ PRIMARY KEY (`a`)
-+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-+/*!40101 SET character_set_client = @saved_cs_client */;
-+
-+LOCK TABLES `t2` WRITE;
-+/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
-+INSERT INTO `t2` VALUES (0),(1),(2);
-+/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
-+UNLOCK TABLES;
-+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
-+
-+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
-+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
-+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
-+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
-+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
-+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
-+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-+
-+######################################
-+DROP TABLE t1, t2;
-+CREATE TABLE t1 (
-+id INT NOT NULL AUTO_INCREMENT,
-+KEY (id)
-+) ENGINE=InnoDB;
-+CREATE TABLE t2 (
-+id INT NOT NULL AUTO_INCREMENT,
-+UNIQUE KEY (id)
-+) ENGINE=InnoDB;
-+INSERT INTO t1 VALUES (), (), ();
-+INSERT INTO t2 VALUES (), (), ();
-+######################################
-+
-+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
-+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
-+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
-+/*!40101 SET NAMES utf8 */;
-+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
-+/*!40103 SET TIME_ZONE='+00:00' */;
-+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
-+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-+DROP TABLE IF EXISTS `t1`;
-+/*!40101 SET @saved_cs_client = @@character_set_client */;
-+/*!40101 SET character_set_client = utf8 */;
-+CREATE TABLE `t1` (
-+ `id` int(11) NOT NULL AUTO_INCREMENT,
-+ KEY `id` (`id`)
-+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
-+/*!40101 SET character_set_client = @saved_cs_client */;
-+
-+LOCK TABLES `t1` WRITE;
-+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
-+INSERT INTO `t1` VALUES (1),(2),(3);
-+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
-+UNLOCK TABLES;
-+DROP TABLE IF EXISTS `t2`;
-+/*!40101 SET @saved_cs_client = @@character_set_client */;
-+/*!40101 SET character_set_client = utf8 */;
-+CREATE TABLE `t2` (
-+ `id` int(11) NOT NULL AUTO_INCREMENT,
-+ UNIQUE KEY `id` (`id`)
-+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
-+/*!40101 SET character_set_client = @saved_cs_client */;
-+
-+LOCK TABLES `t2` WRITE;
-+/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
-+INSERT INTO `t2` VALUES (1),(2),(3);
-+/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
-+UNLOCK TABLES;
-+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
-+
-+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
-+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
-+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
-+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
-+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
-+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
-+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-+
-+######################################
-+DROP TABLE t1, t2;
-+CREATE TABLE t1 (
-+a INT NOT NULL,
-+UNIQUE KEY (a)) ENGINE=InnoDB;
-+CREATE TABLE t2 (
-+a INT NOT NULL,
-+b INT NOT NULL,
-+UNIQUE KEY (a,b)) ENGINE=InnoDB;
-+CREATE TABLE t3 (
-+a INT,
-+b INT,
-+UNIQUE KEY (a,b)) ENGINE=InnoDB;
-+CREATE TABLE t4 (
-+a INT NOT NULL,
-+b INT NOT NULL,
-+PRIMARY KEY (a,b),
-+UNIQUE KEY(b)) ENGINE=InnoDB;
-+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
-+TABLE_SCHEMA=DATABASE() AND
-+TABLE_NAME='t1' AND
-+COLUMN_KEY='PRI';
-+COUNT(*)
-+1
-+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
-+TABLE_SCHEMA=DATABASE() AND
-+TABLE_NAME='t2' AND
-+COLUMN_KEY='PRI';
-+COUNT(*)
-+2
-+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
-+TABLE_SCHEMA=DATABASE() AND
-+TABLE_NAME='t3' AND
-+COLUMN_KEY='PRI';
-+COUNT(*)
-+0
-+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
-+TABLE_SCHEMA=DATABASE() AND
-+TABLE_NAME='t4' AND
-+COLUMN_KEY='PRI';
-+COUNT(*)
-+2
-+INSERT INTO t1 VALUES (1), (2), (3);
-+INSERT INTO t2 VALUES (1,1), (2,2), (3,3);
-+INSERT INTO t3 SELECT * FROM t2;
-+INSERT INTO t4 SELECT * FROM t2;
-+######################################
-+
-+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
-+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
-+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
-+/*!40101 SET NAMES utf8 */;
-+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
-+/*!40103 SET TIME_ZONE='+00:00' */;
-+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
-+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-+DROP TABLE IF EXISTS `t1`;
-+/*!40101 SET @saved_cs_client = @@character_set_client */;
-+/*!40101 SET character_set_client = utf8 */;
-+CREATE TABLE `t1` (
-+ `a` int(11) NOT NULL,
-+ UNIQUE KEY `a` (`a`)
-+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-+/*!40101 SET character_set_client = @saved_cs_client */;
-+
-+LOCK TABLES `t1` WRITE;
-+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
-+INSERT INTO `t1` VALUES (1),(2),(3);
-+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
-+UNLOCK TABLES;
-+DROP TABLE IF EXISTS `t2`;
-+/*!40101 SET @saved_cs_client = @@character_set_client */;
-+/*!40101 SET character_set_client = utf8 */;
-+CREATE TABLE `t2` (
-+ `a` int(11) NOT NULL,
-+ `b` int(11) NOT NULL,
-+ UNIQUE KEY `a` (`a`,`b`)
-+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-+/*!40101 SET character_set_client = @saved_cs_client */;
-+
-+LOCK TABLES `t2` WRITE;
-+/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
-+INSERT INTO `t2` VALUES (1,1),(2,2),(3,3);
-+/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
-+UNLOCK TABLES;
-+DROP TABLE IF EXISTS `t3`;
-+/*!40101 SET @saved_cs_client = @@character_set_client */;
-+/*!40101 SET character_set_client = utf8 */;
-+CREATE TABLE `t3` (
-+ `a` int(11) DEFAULT NULL,
-+ `b` int(11) DEFAULT NULL
-+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-+/*!40101 SET character_set_client = @saved_cs_client */;
-+
-+LOCK TABLES `t3` WRITE;
-+/*!40000 ALTER TABLE `t3` DISABLE KEYS */;
-+INSERT INTO `t3` VALUES (1,1),(2,2),(3,3);
-+ALTER TABLE `t3` ADD UNIQUE KEY `a` (`a`,`b`);
-+/*!40000 ALTER TABLE `t3` ENABLE KEYS */;
-+UNLOCK TABLES;
-+DROP TABLE IF EXISTS `t4`;
-+/*!40101 SET @saved_cs_client = @@character_set_client */;
-+/*!40101 SET character_set_client = utf8 */;
-+CREATE TABLE `t4` (
-+ `a` int(11) NOT NULL,
-+ `b` int(11) NOT NULL,
-+ PRIMARY KEY (`a`,`b`)
-+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-+/*!40101 SET character_set_client = @saved_cs_client */;
-+
-+LOCK TABLES `t4` WRITE;
-+/*!40000 ALTER TABLE `t4` DISABLE KEYS */;
-+INSERT INTO `t4` VALUES (1,1),(2,2),(3,3);
-+ALTER TABLE `t4` ADD UNIQUE KEY `b` (`b`);
-+/*!40000 ALTER TABLE `t4` ENABLE KEYS */;
-+UNLOCK TABLES;
-+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
-+
-+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
-+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
-+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
-+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
-+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
-+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
-+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-+
-+######################################
-+DROP TABLE t1, t2, t3, t4;
-+CREATE TABLE t1 (
-+id INT NOT NULL PRIMARY KEY
-+) ENGINE=InnoDB;
-+CREATE TABLE t2 (
-+id INT NOT NULL AUTO_INCREMENT,
-+a INT NOT NULL,
-+PRIMARY KEY (id),
-+KEY (a),
-+FOREIGN KEY (a) REFERENCES t2 (id)
-+) ENGINE=InnoDB;
-+INSERT INTO t1 VALUES (1), (2), (3);
-+INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3);
-+######################################
-+
-+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
-+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
-+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
-+/*!40101 SET NAMES utf8 */;
-+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
-+/*!40103 SET TIME_ZONE='+00:00' */;
-+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
-+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-+DROP TABLE IF EXISTS `t1`;
-+/*!40101 SET @saved_cs_client = @@character_set_client */;
-+/*!40101 SET character_set_client = utf8 */;
-+CREATE TABLE `t1` (
-+ `id` int(11) NOT NULL,
-+ PRIMARY KEY (`id`)
-+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-+/*!40101 SET character_set_client = @saved_cs_client */;
-+
-+LOCK TABLES `t1` WRITE;
-+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
-+INSERT INTO `t1` VALUES (1),(2),(3);
-+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
-+UNLOCK TABLES;
-+DROP TABLE IF EXISTS `t2`;
-+/*!40101 SET @saved_cs_client = @@character_set_client */;
-+/*!40101 SET character_set_client = utf8 */;
-+CREATE TABLE `t2` (
-+ `id` int(11) NOT NULL AUTO_INCREMENT,
-+ `a` int(11) NOT NULL,
-+ PRIMARY KEY (`id`),
-+ CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t2` (`id`)
-+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
-+/*!40101 SET character_set_client = @saved_cs_client */;
-+
-+LOCK TABLES `t2` WRITE;
-+/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
-+INSERT INTO `t2` VALUES (1,1),(2,2),(3,3);
-+ALTER TABLE `t2` ADD KEY `a` (`a`);
-+/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
-+UNLOCK TABLES;
-+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
-+
-+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
-+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
-+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
-+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
-+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
-+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
-+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-+
-+######################################
-+DROP TABLE t1, t2;
---- /dev/null
-+++ b/mysql-test/t/percona_mysqldump_innodb_optimize_keys.test
-@@ -0,0 +1,188 @@
-+# Embedded server doesn't support external clients
-+--source include/not_embedded.inc
-+
-+# Fast index creation is only available in InnoDB plugin
-+--source include/have_innodb.inc
-+
-+# Save the initial number of concurrent sessions
-+--source include/count_sessions.inc
-+
-+--echo #
-+--echo # Test the --innodb-optimize-keys option.
-+--echo #
-+
-+--let $file=$MYSQLTEST_VARDIR/tmp/t1.sql
-+
-+# First test that the option has no effect on non-InnoDB tables
-+
-+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, KEY(b)) ENGINE=MyISAM;
-+
-+--exec $MYSQL_DUMP --skip-comments --innodb-optimize-keys test t1 >$file
-+
-+--echo ######################################
-+--cat_file $file
-+--echo ######################################
-+
-+--remove_file $file
-+
-+DROP TABLE t1;
-+
-+
-+# Check that for InnoDB tables secondary keys are created after the data is
-+# dumped but foreign ones are left in CREATE TABLE
-+
-+CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
-+INSERT INTO t2 VALUES (0), (1), (2);
-+
-+CREATE TABLE t1 (
-+ id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-+ a INT, b VARCHAR(255), c DECIMAL(10,3),
-+ KEY (b),
-+ UNIQUE KEY uniq(c,a),
-+ FOREIGN KEY (a) REFERENCES t2(a) ON DELETE CASCADE
-+) ENGINE=InnoDB;
-+
-+INSERT INTO t1(a,b,c) VALUES (0, "0", 0.0), (1, "1", 1.1), (2, "2", 2.2);
-+
-+--exec $MYSQL_DUMP --skip-comments --innodb-optimize-keys test t1 t2 >$file
-+
-+--echo ######################################
-+--cat_file $file
-+--echo ######################################
-+
-+# Check that the resulting dump can be imported back
-+
-+--exec $MYSQL test < $file
-+
-+--remove_file $file
-+
-+DROP TABLE t1, t2;
-+
-+########################################################################
-+# Bug #812179: AUTO_INCREMENT columns must be skipped by the
-+# --innodb-optimize-keys optimization in mysqldump
-+########################################################################
-+
-+CREATE TABLE t1 (
-+ id INT NOT NULL AUTO_INCREMENT,
-+ KEY (id)
-+) ENGINE=InnoDB;
-+
-+CREATE TABLE t2 (
-+ id INT NOT NULL AUTO_INCREMENT,
-+ UNIQUE KEY (id)
-+) ENGINE=InnoDB;
-+
-+INSERT INTO t1 VALUES (), (), ();
-+INSERT INTO t2 VALUES (), (), ();
-+
-+--exec $MYSQL_DUMP --skip-comments --innodb-optimize-keys test t1 t2 >$file
-+
-+--echo ######################################
-+--cat_file $file
-+--echo ######################################
-+
-+# Check that the resulting dump can be imported back
-+
-+--exec $MYSQL test < $file
-+
-+--remove_file $file
-+
-+DROP TABLE t1, t2;
-+
-+########################################################################
-+# Bug #851674: --innodb-optimize-keys does not work correctly with table
-+# without PRIMARY KEY
-+########################################################################
-+
-+CREATE TABLE t1 (
-+ a INT NOT NULL,
-+ UNIQUE KEY (a)) ENGINE=InnoDB;
-+
-+CREATE TABLE t2 (
-+ a INT NOT NULL,
-+ b INT NOT NULL,
-+ UNIQUE KEY (a,b)) ENGINE=InnoDB;
-+
-+CREATE TABLE t3 (
-+ a INT,
-+ b INT,
-+ UNIQUE KEY (a,b)) ENGINE=InnoDB;
-+
-+CREATE TABLE t4 (
-+ a INT NOT NULL,
-+ b INT NOT NULL,
-+ PRIMARY KEY (a,b),
-+ UNIQUE KEY(b)) ENGINE=InnoDB;
-+
-+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
-+ TABLE_SCHEMA=DATABASE() AND
-+ TABLE_NAME='t1' AND
-+ COLUMN_KEY='PRI';
-+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
-+ TABLE_SCHEMA=DATABASE() AND
-+ TABLE_NAME='t2' AND
-+ COLUMN_KEY='PRI';
-+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
-+ TABLE_SCHEMA=DATABASE() AND
-+ TABLE_NAME='t3' AND
-+ COLUMN_KEY='PRI';
-+SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
-+ TABLE_SCHEMA=DATABASE() AND
-+ TABLE_NAME='t4' AND
-+ COLUMN_KEY='PRI';
-+
-+INSERT INTO t1 VALUES (1), (2), (3);
-+INSERT INTO t2 VALUES (1,1), (2,2), (3,3);
-+INSERT INTO t3 SELECT * FROM t2;
-+INSERT INTO t4 SELECT * FROM t2;
-+
-+--exec $MYSQL_DUMP --skip-comments --innodb-optimize-keys test t1 t2 t3 t4 >$file
-+
-+--echo ######################################
-+--cat_file $file
-+--echo ######################################
-+
-+# Check that the resulting dump can be imported back
-+
-+--exec $MYSQL test < $file
-+
-+--remove_file $file
-+
-+DROP TABLE t1, t2, t3, t4;
-+
-+########################################################################
-+# Bug #859078: --innodb-optimize-keys should ignore foreign keys
-+########################################################################
-+
-+CREATE TABLE t1 (
-+ id INT NOT NULL PRIMARY KEY
-+) ENGINE=InnoDB;
-+
-+CREATE TABLE t2 (
-+ id INT NOT NULL AUTO_INCREMENT,
-+ a INT NOT NULL,
-+ PRIMARY KEY (id),
-+ KEY (a),
-+ FOREIGN KEY (a) REFERENCES t2 (id)
-+) ENGINE=InnoDB;
-+
-+INSERT INTO t1 VALUES (1), (2), (3);
-+INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3);
-+
-+--exec $MYSQL_DUMP --skip-comments --innodb-optimize-keys test t1 t2 >$file
-+
-+--echo ######################################
-+--cat_file $file
-+--echo ######################################
-+
-+# Check that the resulting dump can be imported back
-+
-+--exec $MYSQL test < $file
-+
-+--remove_file $file
-+
-+DROP TABLE t1, t2;
-+
-+# Wait till we reached the initial number of concurrent sessions
-+--source include/wait_until_count_sessions.inc
---- a/sql/sql_lex.cc
-+++ b/sql/sql_lex.cc
-@@ -1638,6 +1638,9 @@
- alter_list(rhs.alter_list, mem_root),
- key_list(rhs.key_list, mem_root),
- create_list(rhs.create_list, mem_root),
-+ delayed_key_list(rhs.delayed_key_list, mem_root),
-+ delayed_key_info(rhs.delayed_key_info),
-+ delayed_key_count(rhs.delayed_key_count),
- flags(rhs.flags),
- keys_onoff(rhs.keys_onoff),
- tablespace_op(rhs.tablespace_op),
-@@ -1660,6 +1663,7 @@
- list_copy_and_replace_each_value(alter_list, mem_root);
- list_copy_and_replace_each_value(key_list, mem_root);
- list_copy_and_replace_each_value(create_list, mem_root);
-+ list_copy_and_replace_each_value(delayed_key_list, mem_root);
- /* partition_names are not deeply copied currently */
- }
-
---- a/sql/sql_lex.h
-+++ b/sql/sql_lex.h
-@@ -1014,6 +1014,9 @@
- List<Alter_column> alter_list;
- List<Key> key_list;
- List<Create_field> create_list;
-+ List<Key> delayed_key_list;
-+ KEY *delayed_key_info;
-+ uint delayed_key_count;
- uint flags;
- enum enum_enable_or_disable keys_onoff;
- enum tablespace_op_type tablespace_op;
-@@ -1025,6 +1028,8 @@
-
-
- Alter_info() :
-+ delayed_key_info(NULL),
-+ delayed_key_count(0),
- flags(0),
- keys_onoff(LEAVE_AS_IS),
- tablespace_op(NO_TABLESPACE_OP),
-@@ -1040,6 +1045,9 @@
- alter_list.empty();
- key_list.empty();
- create_list.empty();
-+ delayed_key_list.empty();
-+ delayed_key_info= NULL;
-+ delayed_key_count= 0;
- flags= 0;
- keys_onoff= LEAVE_AS_IS;
- tablespace_op= NO_TABLESPACE_OP;
---- a/sql/sql_table.cc
-+++ b/sql/sql_table.cc
-@@ -3220,6 +3220,14 @@
- if (!*key_info_buffer || ! key_part_info)
- DBUG_RETURN(TRUE); // Out of memory
-
-+ List_iterator<Key> delayed_key_iterator(alter_info->delayed_key_list);
-+ alter_info->delayed_key_count= 0;
-+ if (alter_info->delayed_key_list.elements > 0)
-+ {
-+ alter_info->delayed_key_info= (KEY *) sql_calloc(sizeof(KEY) *
-+ (*key_count));
-+ }
-+
- key_iterator.rewind();
- key_number=0;
- for (; (key=key_iterator++) ; key_number++)
-@@ -3638,6 +3646,22 @@
- key_info->comment.str= key->key_create_info.comment.str;
- }
-
-+ if (alter_info->delayed_key_list.elements > 0)
-+ {
-+ Key *delayed_key;
-+
-+ delayed_key_iterator.rewind();
-+ while ((delayed_key= delayed_key_iterator++))
-+ {
-+ if (delayed_key == key)
-+ {
-+ alter_info->delayed_key_info[alter_info->delayed_key_count++]=
-+ *key_info;
-+ break;
-+ }
-+ }
-+ }
-+
- key_info++;
- }
- if (!unique_key && !primary_key &&
-@@ -5261,6 +5285,10 @@
- List<Create_field> new_create_list;
- /* New key definitions are added here */
- List<Key> new_key_list;
-+ /* List with secondary keys which should be created after copying the data */
-+ List<Key> delayed_key_list;
-+ /* Foreign key list returned by handler::get_foreign_key_list() */
-+ List<FOREIGN_KEY_INFO> f_key_list;
- List_iterator<Alter_drop> drop_it(alter_info->drop_list);
- List_iterator<Create_field> def_it(alter_info->create_list);
- List_iterator<Alter_column> alter_it(alter_info->alter_list);
-@@ -5273,6 +5301,7 @@
- uint used_fields= create_info->used_fields;
- KEY *key_info=table->key_info;
- bool rc= TRUE;
-+ bool skip_secondary;
-
- DBUG_ENTER("mysql_prepare_alter_table");
-
-@@ -5462,7 +5491,26 @@
- /*
- Collect all keys which isn't in drop list. Add only those
- for which some fields exists.
-- */
-+
-+ We also store secondary keys in delayed_key_list to make use of
-+ the InnoDB fast index creation. The following conditions must be
-+ met:
-+
-+ - fast_index_creation is enabled for the current session
-+ - expand_fast_index_creation is enabled for the current session;
-+ - we are going to create an InnoDB table (this is checked later when the
-+ target engine is known);
-+ - the key most be a non-UNIQUE one;
-+ - there are no foreign keys. This can be optimized later to exclude only
-+ those keys which are a part of foreign key constraints. Currently we
-+ simply disable this optimization for all keys if there are any foreign
-+ key constraints in the table.
-+ */
-+
-+ skip_secondary= thd->variables.online_alter_index &&
-+ thd->variables.expand_fast_index_creation &&
-+ !table->file->get_foreign_key_list(thd, &f_key_list) &&
-+ f_key_list.elements == 0;
-
- for (uint i=0 ; i < table->s->keys ; i++,key_info++)
- {
-@@ -5579,6 +5627,8 @@
- test(key_info->flags & HA_GENERATED_KEY),
- key_parts);
- new_key_list.push_back(key);
-+ if (skip_secondary && key_type == Key::MULTIPLE)
-+ delayed_key_list.push_back(key);
- }
- }
- {
-@@ -5586,7 +5636,21 @@
- while ((key=key_it++)) // Add new keys
- {
- if (key->type != Key::FOREIGN_KEY)
-+ {
- new_key_list.push_back(key);
-+ if (skip_secondary && key->type == Key::MULTIPLE)
-+ delayed_key_list.push_back(key);
-+ }
-+ else if (skip_secondary)
-+ {
-+ /*
-+ We are adding a foreign key so disable the secondary keys
-+ optimization.
-+ */
-+ skip_secondary= FALSE;
-+ delayed_key_list.empty();
-+ }
-+
- if (key->name.str &&
- !my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
- {
-@@ -5635,12 +5699,104 @@
- rc= FALSE;
- alter_info->create_list.swap(new_create_list);
- alter_info->key_list.swap(new_key_list);
-+ alter_info->delayed_key_list.swap(delayed_key_list);
- err:
- DBUG_RETURN(rc);
- }
-
-
- /*
-+ Temporarily remove secondary keys previously stored in
-+ alter_info->delayed_key_info.
-+*/
-+static int
-+remove_secondary_keys(THD *thd, TABLE *table, Alter_info *alter_info)
-+{
-+ uint *key_numbers;
-+ uint key_counter= 0;
-+ uint i;
-+ int error;
-+ DBUG_ENTER("remove_secondary_keys");
-+ DBUG_ASSERT(alter_info->delayed_key_count > 0);
-+
-+ key_numbers= (uint *) thd->alloc(sizeof(uint) *
-+ alter_info->delayed_key_count);
-+ for (i= 0; i < alter_info->delayed_key_count; i++)
-+ {
-+ KEY *key= alter_info->delayed_key_info + i;
-+ uint j;
-+
-+ for (j= 0; j < table->s->keys; j++)
-+ {
-+ if (!strcmp(table->key_info[j].name, key->name))
-+ {
-+ key_numbers[key_counter++]= j;
-+ break;
-+ }
-+ }
-+ }
-+
-+ DBUG_ASSERT(key_counter == alter_info->delayed_key_count);
-+
-+ if ((error= table->file->prepare_drop_index(table, key_numbers,
-+ key_counter)) ||
-+ (error= table->file->final_drop_index(table)))
-+ {
-+ table->file->print_error(error, MYF(0));
-+ }
-+
-+ DBUG_RETURN(error);
-+}
-+
-+/*
-+ Restore secondary keys previously removed in remove_secondary_keys.
-+*/
-+
-+static int
-+restore_secondary_keys(THD *thd, TABLE *table, Alter_info *alter_info)
-+{
-+ uint i;
-+ int error;
-+ DBUG_ENTER("restore_secondary_keys");
-+ DBUG_ASSERT(alter_info->delayed_key_count > 0);
-+
-+ thd_proc_info(thd, "restoring secondary keys");
-+
-+ /* Fix the key parts */
-+ for (i= 0; i < alter_info->delayed_key_count; i++)
-+ {
-+ KEY *key = alter_info->delayed_key_info + i;
-+ KEY_PART_INFO *key_part;
-+ KEY_PART_INFO *part_end;
-+
-+ part_end= key->key_part + key->key_parts;
-+ for (key_part= key->key_part; key_part < part_end; key_part++)
-+ key_part->field= table->field[key_part->fieldnr];
-+ }
-+ handler_add_index *add;
-+ if ((error= table->file->add_index(table, alter_info->delayed_key_info,
-+ alter_info->delayed_key_count, &add)))
-+ {
-+ /*
-+ Exchange the key_info for the error message. If we exchange
-+ key number by key name in the message later, we need correct info.
-+ */
-+ KEY *save_key_info= table->key_info;
-+ table->key_info= alter_info->delayed_key_info;
-+ table->file->print_error(error, MYF(0));
-+ table->key_info= save_key_info;
-+
-+ DBUG_RETURN(error);
-+ }
-+ if ((error= table->file->final_add_index(add, true)))
-+ {
-+ table->file->print_error(error, MYF(0));
-+ }
-+
-+ DBUG_RETURN(error);
-+}
-+
-+/*
- Alter table
-
- SYNOPSIS
-@@ -6434,19 +6590,38 @@
- */
- if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
- {
-+ /*
-+ Check if we can temporarily remove secondary indexes from the table
-+ before copying the data and recreate them later to utilize InnoDB fast
-+ index creation.
-+ TODO: is there a better way to check for InnoDB?
-+ */
-+ bool optimize_keys= (alter_info->delayed_key_count > 0) &&
-+ !my_strcasecmp(system_charset_info,
-+ new_table->file->table_type(), "InnoDB");
- /* We don't want update TIMESTAMP fields during ALTER TABLE. */
- new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
- new_table->next_number_field=new_table->found_next_number_field;
-+
- thd_proc_info(thd, "copy to tmp table");
- DBUG_EXECUTE_IF("abort_copy_table", {
- my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
- goto err_new_table_cleanup;
- });
-+
-+ if (optimize_keys)
-+ {
-+ /* ignore the error */
-+ error= remove_secondary_keys(thd, new_table, alter_info);
-+ }
-+
- error= copy_data_between_tables(table, new_table,
- alter_info->create_list, ignore,
- order_num, order, &copied, &deleted,
- alter_info->keys_onoff,
- alter_info->error_if_not_empty);
-+ if (!error && optimize_keys)
-+ error= restore_secondary_keys(thd, new_table, alter_info);
- }
- else
- {
---- /dev/null
-+++ b/mysql-test/r/percona_innodb_expand_fast_index_creation.result
-@@ -0,0 +1,64 @@
-+CREATE TABLE t1(
-+id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-+a CHAR(1) NOT NULL,
-+b CHAR(36) NOT NULL) ENGINE=InnoDB;
-+INSERT INTO t1(a,b) VALUES ('a','b');
-+INSERT INTO t1(a,b) SELECT a,b FROM t1;
-+INSERT INTO t1(a,b) SELECT a,b FROM t1;
-+INSERT INTO t1(a,b) SELECT a,b FROM t1;
-+INSERT INTO t1(a,b) SELECT a,b FROM t1;
-+ALTER TABLE t1 ADD KEY (a);
-+affected rows: 0
-+info: Records: 0 Duplicates: 0 Warnings: 0
-+EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b;
-+id 1
-+select_type SIMPLE
-+table t1
-+type ALL
-+possible_keys a
-+key NULL
-+key_len NULL
-+ref NULL
-+rows 16
-+Extra
-+id 1
-+select_type SIMPLE
-+table t2
-+type ref
-+possible_keys a
-+key a
-+key_len 1
-+ref test.t1.a
-+rows 1
-+Extra Using where
-+ALTER TABLE t1 DROP KEY a;
-+SET expand_fast_index_creation = 1;
-+SELECT @@expand_fast_index_creation;
-+@@expand_fast_index_creation
-+1
-+ALTER TABLE t1 ADD KEY (a);
-+affected rows: 0
-+info: Records: 0 Duplicates: 0 Warnings: 0
-+EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b;
-+id 1
-+select_type SIMPLE
-+table t1
-+type ALL
-+possible_keys a
-+key NULL
-+key_len NULL
-+ref NULL
-+rows 16
-+Extra
-+id 1
-+select_type SIMPLE
-+table t2
-+type ALL
-+possible_keys a
-+key NULL
-+key_len NULL
-+ref NULL
-+rows 16
-+Extra Using where; Using join buffer
-+SET expand_fast_index_creation = 0;
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/t/percona_innodb_expand_fast_index_creation.test
-@@ -0,0 +1,45 @@
-+--source include/have_innodb.inc
-+
-+########################################################################
-+# Bug #857590: Fast index creation does not update index statistics
-+########################################################################
-+
-+CREATE TABLE t1(
-+ id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-+ a CHAR(1) NOT NULL,
-+ b CHAR(36) NOT NULL) ENGINE=InnoDB;
-+
-+INSERT INTO t1(a,b) VALUES ('a','b');
-+INSERT INTO t1(a,b) SELECT a,b FROM t1;
-+INSERT INTO t1(a,b) SELECT a,b FROM t1;
-+INSERT INTO t1(a,b) SELECT a,b FROM t1;
-+INSERT INTO t1(a,b) SELECT a,b FROM t1;
-+
-+# Check that fast index creation is used
-+--enable_info
-+ALTER TABLE t1 ADD KEY (a);
-+--disable_info
-+
-+# The default (wrong) plan due to bogus statistics
-+--vertical_results
-+EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b;
-+--horizontal_results
-+
-+ALTER TABLE t1 DROP KEY a;
-+
-+SET expand_fast_index_creation = 1;
-+SELECT @@expand_fast_index_creation;
-+
-+# Check that stats are updated with the option enabled
-+
-+--enable_info
-+ALTER TABLE t1 ADD KEY (a);
-+--disable_info
-+
-+--vertical_results
-+EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b;
-+--horizontal_results
-+
-+SET expand_fast_index_creation = 0;
-+
-+DROP TABLE t1;
---- a/storage/innobase/row/row0merge.c
-+++ b/storage/innobase/row/row0merge.c
-@@ -56,6 +56,7 @@
- #include "log0log.h"
- #include "ut0sort.h"
- #include "handler0alter.h"
-+#include "ha_prototypes.h"
-
- /* Ignore posix_fadvise() on those platforms where it does not exist */
- #if defined __WIN__
-@@ -2673,6 +2674,9 @@
- }
- }
-
-+ if (trx->mysql_thd && thd_expand_fast_index_creation(trx->mysql_thd))
-+ dict_update_statistics(new_table, FALSE, TRUE);
-+
- func_exit:
- row_merge_file_destroy_low(tmpfd);
-
---- a/sql/sql_class.h
-+++ b/sql/sql_class.h
-@@ -551,6 +551,7 @@
-
- double long_query_time_double;
-
-+ my_bool expand_fast_index_creation;
- } SV;
-
-
---- a/sql/sys_vars.cc
-+++ b/sql/sys_vars.cc
-@@ -783,6 +783,14 @@
- ON_CHECK(event_scheduler_check), ON_UPDATE(event_scheduler_update));
- #endif
-
-+static Sys_var_mybool Sys_expand_fast_index_creation(
-+ "expand_fast_index_creation",
-+ "Enable/disable improvements to the InnoDB fast index creation "
-+ "functionality. Has no effect when fast index creation is disabled with "
-+ "the fast-index-creation option",
-+ SESSION_VAR(expand_fast_index_creation), CMD_LINE(OPT_ARG),
-+ DEFAULT(FALSE));
-+
- static Sys_var_ulong Sys_expire_logs_days(
- "expire_logs_days",
- "If non-zero, binary logs will be purged after expire_logs_days "
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -999,6 +999,19 @@
- return(THDVAR((THD*) thd, flush_log_at_trx_commit));
- }
-
-+/******************************************************************//**
-+Returns true if expand_fast_index_creation is enabled for the current
-+session.
-+@return the value of the server's expand_fast_index_creation variable */
-+extern "C" UNIV_INTERN
-+ibool
-+thd_expand_fast_index_creation(
-+/*================================*/
-+ void* thd)
-+{
-+ return((ibool) (((THD*) thd)->variables.expand_fast_index_creation));
-+}
-+
- /********************************************************************//**
- Obtain the InnoDB transaction of a MySQL thread.
- @return reference to transaction pointer */
---- a/storage/innobase/include/ha_prototypes.h
-+++ b/storage/innobase/include/ha_prototypes.h
-@@ -303,4 +303,15 @@
- innobase_get_lower_case_table_names(void);
- /*=====================================*/
-
-+/******************************************************************//**
-+Returns true if innodb_expand_fast_index_creation is enabled for the current
-+session.
-+@return the value of the server's innodb_expand_fast_index_creation variable */
-+
-+ibool
-+thd_expand_fast_index_creation(
-+/*==================*/
-+ void* thd); /*!< in: thread handle (THD*) */
-+
-+
- #endif
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/r/expand_fast_index_creation_basic.result
-@@ -0,0 +1,6 @@
-+SELECT @@global.expand_fast_index_creation;
-+@@global.expand_fast_index_creation
-+0
-+SELECT @@local.expand_fast_index_creation;
-+@@local.expand_fast_index_creation
-+0
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/t/expand_fast_index_creation_basic.test
-@@ -0,0 +1,2 @@
-+SELECT @@global.expand_fast_index_creation;
-+SELECT @@local.expand_fast_index_creation;
---- a/mysql-test/r/mysqld--help-notwin.result
-+++ b/mysql-test/r/mysqld--help-notwin.result
-@@ -140,6 +140,10 @@
- and DISABLED (keep the event scheduler completely
- deactivated, it cannot be activated run-time)
- -T, --exit-info[=#] Used for debugging. Use at your own risk.
-+ --expand-fast-index-creation
-+ Enable/disable improvements to the InnoDB fast index
-+ creation functionality. Has no effect when fast index
-+ creation is disabled with the fast-index-creation option
- --expire-logs-days=#
- If non-zero, binary logs will be purged after
- expire_logs_days days; possible purges happen at startup
-@@ -823,6 +827,7 @@
- div-precision-increment 4
- engine-condition-pushdown TRUE
- event-scheduler OFF
-+expand-fast-index-creation FALSE
- expire-logs-days 0
- external-locking FALSE
- flush FALSE
---- a/mysql-test/r/mysqld--help-win.result
-+++ b/mysql-test/r/mysqld--help-win.result
-@@ -140,6 +140,10 @@
- and DISABLED (keep the event scheduler completely
- deactivated, it cannot be activated run-time)
- -T, --exit-info[=#] Used for debugging. Use at your own risk.
-+ --expand-fast-index-creation
-+ Enable/disable improvements to InnoDB fast index creation
-+ functionality. Has no effect when fast index creation is
-+ disabled with the fast-index-creation option
- --expire-logs-days=#
- If non-zero, binary logs will be purged after
- expire_logs_days days; possible purges happen at startup
-@@ -781,6 +785,7 @@
- div-precision-increment 4
- engine-condition-pushdown TRUE
- event-scheduler OFF
-+expand-fast-index-creation FALSE
- expire-logs-days 0
- external-locking FALSE
- flush FALSE
+++ /dev/null
-# name : innodb_expand_import.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/btr/btr0btr.c
-+++ b/storage/innobase/btr/btr0btr.c
-@@ -838,7 +838,7 @@
- /**************************************************************//**
- Creates a new index page (not the root, and also not
- used in page reorganization). @see btr_page_empty(). */
--static
-+UNIV_INTERN
- void
- btr_page_create(
- /*============*/
-@@ -1712,7 +1712,7 @@
- #ifndef UNIV_HOTBACKUP
- /*************************************************************//**
- Empties an index page. @see btr_page_create(). */
--static
-+UNIV_INTERN
- void
- btr_page_empty(
- /*===========*/
-@@ -2274,7 +2274,7 @@
- /**************************************************************//**
- Attaches the halves of an index page on the appropriate level in an
- index tree. */
--static
-+UNIV_INTERN
- void
- btr_attach_half_pages(
- /*==================*/
---- a/storage/innobase/fil/fil0fil.c
-+++ b/storage/innobase/fil/fil0fil.c
-@@ -40,6 +40,14 @@
- #include "dict0dict.h"
- #include "page0page.h"
- #include "page0zip.h"
-+#include "trx0trx.h"
-+#include "trx0sys.h"
-+#include "pars0pars.h"
-+#include "row0mysql.h"
-+#include "row0row.h"
-+#include "que0que.h"
-+#include "btr0btr.h"
-+#include "btr0sea.h"
- #ifndef UNIV_HOTBACKUP
- # include "buf0lru.h"
- # include "ibuf0ibuf.h"
-@@ -3041,6 +3049,84 @@
- }
-
- /********************************************************************//**
-+Checks if a page is corrupt. (for offline page)
-+*/
-+static
-+ibool
-+fil_page_buf_page_is_corrupted_offline(
-+/*===================================*/
-+ const byte* page, /*!< in: a database page */
-+ ulint zip_size) /*!< in: size of compressed page;
-+ 0 for uncompressed pages */
-+{
-+ ulint checksum_field;
-+ ulint old_checksum_field;
-+
-+ if (!zip_size
-+ && memcmp(page + FIL_PAGE_LSN + 4,
-+ page + UNIV_PAGE_SIZE
-+ - FIL_PAGE_END_LSN_OLD_CHKSUM + 4, 4)) {
-+ return(TRUE);
-+ }
-+
-+ checksum_field = mach_read_from_4(page
-+ + FIL_PAGE_SPACE_OR_CHKSUM);
-+
-+ if (zip_size) {
-+ return(checksum_field != BUF_NO_CHECKSUM_MAGIC
-+ && checksum_field
-+ != page_zip_calc_checksum(page, zip_size));
-+ }
-+
-+ old_checksum_field = mach_read_from_4(
-+ page + UNIV_PAGE_SIZE
-+ - FIL_PAGE_END_LSN_OLD_CHKSUM);
-+
-+ if (old_checksum_field != mach_read_from_4(page
-+ + FIL_PAGE_LSN)
-+ && old_checksum_field != BUF_NO_CHECKSUM_MAGIC
-+ && old_checksum_field
-+ != buf_calc_page_old_checksum(page)) {
-+ return(TRUE);
-+ }
-+
-+ if (checksum_field != 0
-+ && checksum_field != BUF_NO_CHECKSUM_MAGIC
-+ && checksum_field
-+ != buf_calc_page_new_checksum(page)) {
-+ return(TRUE);
-+ }
-+
-+ return(FALSE);
-+}
-+
-+/********************************************************************//**
-+*/
-+static
-+void
-+fil_page_buf_page_store_checksum(
-+/*=============================*/
-+ byte* page,
-+ ulint zip_size)
-+{
-+ if (!zip_size) {
-+ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
-+ srv_use_checksums
-+ ? buf_calc_page_new_checksum(page)
-+ : BUF_NO_CHECKSUM_MAGIC);
-+ mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
-+ srv_use_checksums
-+ ? buf_calc_page_old_checksum(page)
-+ : BUF_NO_CHECKSUM_MAGIC);
-+ } else {
-+ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
-+ srv_use_checksums
-+ ? page_zip_calc_checksum(page, zip_size)
-+ : BUF_NO_CHECKSUM_MAGIC);
-+ }
-+}
-+
-+/********************************************************************//**
- Tries to open a single-table tablespace and optionally checks the space id is
- right in it. If does not succeed, prints an error message to the .err log. This
- function is used to open a tablespace when we start up mysqld, and also in
-@@ -3063,8 +3149,11 @@
- accessing the first page of the file */
- ulint id, /*!< in: space id */
- ulint flags, /*!< in: tablespace flags */
-- const char* name) /*!< in: table name in the
-+ const char* name, /*!< in: table name in the
- databasename/tablename format */
-+ trx_t* trx) /*!< in: transaction. This is only used
-+ for IMPORT TABLESPACE, must be NULL
-+ otherwise */
- {
- os_file_t file;
- char* filepath;
-@@ -3087,7 +3176,7 @@
-
- file = os_file_create_simple_no_error_handling(
- innodb_file_data_key, filepath, OS_FILE_OPEN,
-- OS_FILE_READ_ONLY, &success);
-+ OS_FILE_READ_WRITE, &success);
- if (!success) {
- /* The following call prints an error message */
- os_file_get_last_error(TRUE);
-@@ -3134,6 +3223,453 @@
- space_id = fsp_header_get_space_id(page);
- space_flags = fsp_header_get_flags(page);
-
-+ if (srv_expand_import) {
-+
-+ ibool file_is_corrupt = FALSE;
-+ byte* buf3;
-+ byte* descr_page;
-+ ibool descr_is_corrupt = FALSE;
-+ index_id_t old_id[31];
-+ index_id_t new_id[31];
-+ ulint root_page[31];
-+ ulint n_index;
-+ os_file_t info_file = -1;
-+ char* info_file_path;
-+ ulint i;
-+ int len;
-+ ib_uint64_t current_lsn;
-+ ulint size_low, size_high, size, free_limit;
-+ ib_int64_t size_bytes, free_limit_bytes;
-+ dict_table_t* table;
-+ dict_index_t* index;
-+ fil_system_t* system;
-+ fil_node_t* node = NULL;
-+ fil_space_t* space;
-+ ulint zip_size;
-+
-+ buf3 = ut_malloc(2 * UNIV_PAGE_SIZE);
-+ descr_page = ut_align(buf3, UNIV_PAGE_SIZE);
-+
-+ current_lsn = log_get_lsn();
-+
-+ /* check the header page's consistency */
-+ if (buf_page_is_corrupted(page,
-+ dict_table_flags_to_zip_size(space_flags))) {
-+ fprintf(stderr, "InnoDB: page 0 of %s seems corrupt.\n", filepath);
-+ file_is_corrupt = TRUE;
-+ descr_is_corrupt = TRUE;
-+ }
-+
-+ /* store as first descr page */
-+ memcpy(descr_page, page, UNIV_PAGE_SIZE);
-+
-+ zip_size = dict_table_flags_to_zip_size(flags);
-+ ut_a(zip_size == dict_table_flags_to_zip_size(space_flags));
-+
-+ /* get free limit (page number) of the table space */
-+/* these should be same to the definition in fsp0fsp.c */
-+#define FSP_HEADER_OFFSET FIL_PAGE_DATA
-+#define FSP_FREE_LIMIT 12
-+ free_limit = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT + page);
-+ free_limit_bytes = (ib_int64_t)free_limit * (ib_int64_t)(zip_size ? zip_size : UNIV_PAGE_SIZE);
-+
-+ /* overwrite fsp header */
-+ fsp_header_init_fields(page, id, flags);
-+ mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, id);
-+ space_id = id;
-+ space_flags = flags;
-+ if (mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN) > current_lsn)
-+ mach_write_to_8(page + FIL_PAGE_FILE_FLUSH_LSN, current_lsn);
-+
-+ fil_page_buf_page_store_checksum(page, zip_size);
-+
-+ success = os_file_write(filepath, file, page, 0, 0, UNIV_PAGE_SIZE);
-+
-+ /* get file size */
-+ os_file_get_size(file, &size_low, &size_high);
-+ size_bytes = (((ib_int64_t)size_high) << 32)
-+ + (ib_int64_t)size_low;
-+
-+ if (size_bytes < free_limit_bytes) {
-+ free_limit_bytes = size_bytes;
-+ if (size_bytes >= (lint)FSP_EXTENT_SIZE * (lint)(zip_size ? zip_size : UNIV_PAGE_SIZE)) {
-+ fprintf(stderr, "InnoDB: free limit of %s is larger than its real size.\n", filepath);
-+ file_is_corrupt = TRUE;
-+ }
-+ }
-+
-+ /* get cruster index information */
-+ table = dict_table_get_low(name);
-+ index = dict_table_get_first_index(table);
-+ ut_a(index->page==3);
-+
-+ /* read metadata from .exp file */
-+ n_index = 0;
-+ memset(old_id, 0, sizeof(old_id));
-+ memset(new_id, 0, sizeof(new_id));
-+ memset(root_page, 0, sizeof(root_page));
-+
-+ info_file_path = fil_make_ibd_name(name, FALSE);
-+ len = strlen(info_file_path);
-+ info_file_path[len - 3] = 'e';
-+ info_file_path[len - 2] = 'x';
-+ info_file_path[len - 1] = 'p';
-+
-+ info_file = os_file_create_simple_no_error_handling(innodb_file_data_key,
-+ info_file_path, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
-+ if (!success) {
-+ fprintf(stderr, "InnoDB: Cannot open the file: %s\n", info_file_path);
-+ file_is_corrupt = TRUE;
-+ goto skip_info;
-+ }
-+ success = os_file_read(info_file, page, 0, 0, UNIV_PAGE_SIZE);
-+ if (!success) {
-+ fprintf(stderr, "InnoDB: Cannot read the file: %s\n", info_file_path);
-+ file_is_corrupt = TRUE;
-+ goto skip_info;
-+ }
-+ if (mach_read_from_4(page) != 0x78706f72UL
-+ || mach_read_from_4(page + 4) != 0x74696e66UL) {
-+ fprintf(stderr, "InnoDB: %s seems to be an incorrect .exp file.\n", info_file_path);
-+ file_is_corrupt = TRUE;
-+ goto skip_info;
-+ }
-+
-+ fprintf(stderr, "InnoDB: Import: The extended import of %s is being started.\n", name);
-+
-+ n_index = mach_read_from_4(page + 8);
-+ fprintf(stderr, "InnoDB: Import: %lu indexes have been detected.\n", (ulong)n_index);
-+ for (i = 0; i < n_index; i++) {
-+ new_id[i] =
-+ dict_table_get_index_on_name(table,
-+ (char*)(page + (i + 1) * 512 + 12))->id;
-+ old_id[i] = mach_read_from_8(page + (i + 1) * 512);
-+ root_page[i] = mach_read_from_4(page + (i + 1) * 512 + 8);
-+ }
-+
-+skip_info:
-+ if (info_file != -1)
-+ os_file_close(info_file);
-+
-+ /*
-+ if (size_bytes >= 1024 * 1024) {
-+ size_bytes = ut_2pow_round(size_bytes, 1024 * 1024);
-+ }
-+ */
-+
-+ if (zip_size) {
-+ fprintf(stderr, "InnoDB: Warning: importing compressed table is still EXPERIMENTAL, currently.\n");
-+ }
-+
-+ {
-+ mem_heap_t* heap = NULL;
-+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
-+ ulint* offsets = offsets_;
-+ ib_int64_t offset;
-+
-+ size = (ulint) (size_bytes / (zip_size ? zip_size : UNIV_PAGE_SIZE));
-+ /* over write space id of all pages */
-+ rec_offs_init(offsets_);
-+
-+ /* Unlock the data dictionary to not block queries
-+ accessing other tables */
-+ ut_a(trx);
-+ row_mysql_unlock_data_dictionary(trx);
-+
-+ fprintf(stderr, "InnoDB: Progress in %%:");
-+
-+ for (offset = 0; offset < free_limit_bytes;
-+ offset += zip_size ? zip_size : UNIV_PAGE_SIZE) {
-+ ibool page_is_corrupt;
-+
-+ success = os_file_read(file, page,
-+ (ulint)(offset & 0xFFFFFFFFUL),
-+ (ulint)(offset >> 32),
-+ zip_size ? zip_size : UNIV_PAGE_SIZE);
-+
-+ page_is_corrupt = FALSE;
-+
-+ /* check consistency */
-+ if (fil_page_buf_page_is_corrupted_offline(page, zip_size)) {
-+ page_is_corrupt = TRUE;
-+ }
-+
-+ if (mach_read_from_4(page + FIL_PAGE_OFFSET)
-+ != offset / (zip_size ? zip_size : UNIV_PAGE_SIZE)) {
-+
-+ page_is_corrupt = TRUE;
-+ }
-+
-+ /* if it is free page, inconsistency is acceptable */
-+ if (!offset) {
-+ /* header page*/
-+ /* it should be overwritten already */
-+ ut_a(!page_is_corrupt);
-+
-+ } else if (!((offset / (zip_size ? zip_size : UNIV_PAGE_SIZE))
-+ % (zip_size ? zip_size : UNIV_PAGE_SIZE))) {
-+ /* descr page (not header) */
-+ if (page_is_corrupt) {
-+ file_is_corrupt = TRUE;
-+ descr_is_corrupt = TRUE;
-+ } else {
-+ ut_ad(fil_page_get_type(page) == FIL_PAGE_TYPE_XDES);
-+ descr_is_corrupt = FALSE;
-+ }
-+
-+ /* store as descr page */
-+ memcpy(descr_page, page, (zip_size ? zip_size : UNIV_PAGE_SIZE));
-+
-+ } else if (descr_is_corrupt) {
-+ /* unknown state of the page */
-+ if (page_is_corrupt) {
-+ file_is_corrupt = TRUE;
-+ }
-+
-+ } else {
-+ /* check free page or not */
-+ /* These definitions should be same to fsp0fsp.c */
-+#define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE)
-+
-+#define XDES_BITMAP (FLST_NODE_SIZE + 12)
-+#define XDES_BITS_PER_PAGE 2
-+#define XDES_FREE_BIT 0
-+#define XDES_SIZE \
-+ (XDES_BITMAP + UT_BITS_IN_BYTES(FSP_EXTENT_SIZE * XDES_BITS_PER_PAGE))
-+#define XDES_ARR_OFFSET (FSP_HEADER_OFFSET + FSP_HEADER_SIZE)
-+
-+ /*descr = descr_page + XDES_ARR_OFFSET + XDES_SIZE * xdes_calc_descriptor_index(zip_size, offset)*/
-+ /*xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)*/
-+ byte* descr;
-+ ulint index;
-+ ulint byte_index;
-+ ulint bit_index;
-+
-+ descr = descr_page + XDES_ARR_OFFSET
-+ + XDES_SIZE * (ut_2pow_remainder(
-+ (offset / (zip_size ? zip_size : UNIV_PAGE_SIZE)),
-+ (zip_size ? zip_size : UNIV_PAGE_SIZE)) / FSP_EXTENT_SIZE);
-+
-+ index = XDES_FREE_BIT
-+ + XDES_BITS_PER_PAGE * ((offset / (zip_size ? zip_size : UNIV_PAGE_SIZE)) % FSP_EXTENT_SIZE);
-+ byte_index = index / 8;
-+ bit_index = index % 8;
-+
-+ if (ut_bit_get_nth(mach_read_from_1(descr + XDES_BITMAP + byte_index), bit_index)) {
-+ /* free page */
-+ if (page_is_corrupt) {
-+ goto skip_write;
-+ }
-+ } else {
-+ /* not free */
-+ if (page_is_corrupt) {
-+ file_is_corrupt = TRUE;
-+ }
-+ }
-+ }
-+
-+ if (page_is_corrupt) {
-+ fprintf(stderr, " [errp:%lld]", offset / (zip_size ? zip_size : UNIV_PAGE_SIZE));
-+
-+ /* cannot treat corrupt page */
-+ goto skip_write;
-+ }
-+
-+ if (mach_read_from_4(page + FIL_PAGE_OFFSET) || !offset) {
-+ mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, id);
-+
-+ for (i = 0; i < n_index; i++) {
-+ if (offset / (zip_size ? zip_size : UNIV_PAGE_SIZE) == root_page[i]) {
-+ if (fil_page_get_type(page) != FIL_PAGE_INDEX) {
-+ file_is_corrupt = TRUE;
-+ fprintf(stderr, " [etyp:%lld]",
-+ offset / (zip_size ? zip_size : UNIV_PAGE_SIZE));
-+ goto skip_write;
-+ }
-+ /* this is index root page */
-+ mach_write_to_4(page + FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
-+ + FSEG_HDR_SPACE, id);
-+ mach_write_to_4(page + FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
-+ + FSEG_HDR_SPACE, id);
-+ break;
-+ }
-+ }
-+
-+ if (fil_page_get_type(page) == FIL_PAGE_INDEX) {
-+ index_id_t tmp = mach_read_from_8(page + (PAGE_HEADER + PAGE_INDEX_ID));
-+
-+ for (i = 0; i < n_index; i++) {
-+ if (old_id[i] == tmp) {
-+ mach_write_to_8(page + (PAGE_HEADER + PAGE_INDEX_ID), new_id[i]);
-+ break;
-+ }
-+ }
-+
-+ if (!zip_size && mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL) == 0
-+ && old_id[0] == tmp) {
-+ /* leaf page of cluster index, reset trx_id of records */
-+ rec_t* rec;
-+ rec_t* supremum;
-+ ulint n_recs;
-+
-+ supremum = page_get_supremum_rec(page);
-+ rec = page_rec_get_next(page_get_infimum_rec(page));
-+ n_recs = page_get_n_recs(page);
-+
-+ while (rec && rec != supremum && n_recs > 0) {
-+ ulint n_fields;
-+ ulint i;
-+ ulint offset = index->trx_id_offset;
-+ offsets = rec_get_offsets(rec, index, offsets,
-+ ULINT_UNDEFINED, &heap);
-+ n_fields = rec_offs_n_fields(offsets);
-+ if (!offset) {
-+ offset = row_get_trx_id_offset(index, offsets);
-+ }
-+ trx_write_trx_id(rec + offset, 1);
-+
-+ for (i = 0; i < n_fields; i++) {
-+ if (rec_offs_nth_extern(offsets, i)) {
-+ ulint local_len;
-+ byte* data;
-+
-+ data = rec_get_nth_field(rec, offsets, i, &local_len);
-+
-+ local_len -= BTR_EXTERN_FIELD_REF_SIZE;
-+
-+ mach_write_to_4(data + local_len + BTR_EXTERN_SPACE_ID, id);
-+ }
-+ }
-+
-+ rec = page_rec_get_next(rec);
-+ n_recs--;
-+ }
-+ } else if (mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL) == 0
-+ && old_id[0] != tmp) {
-+ mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), 1);
-+ }
-+ }
-+
-+ if (mach_read_from_8(page + FIL_PAGE_LSN) > current_lsn) {
-+ mach_write_to_8(page + FIL_PAGE_LSN, current_lsn);
-+ if (!zip_size) {
-+ mach_write_to_8(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
-+ current_lsn);
-+ }
-+ }
-+
-+ fil_page_buf_page_store_checksum(page, zip_size);
-+
-+ success = os_file_write(filepath, file, page,
-+ (ulint)(offset & 0xFFFFFFFFUL),
-+ (ulint)(offset >> 32),
-+ zip_size ? zip_size : UNIV_PAGE_SIZE);
-+ }
-+
-+skip_write:
-+ if (free_limit_bytes
-+ && ((ib_int64_t)((offset + (zip_size ? zip_size : UNIV_PAGE_SIZE)) * 100) / free_limit_bytes)
-+ != ((offset * 100) / free_limit_bytes)) {
-+ fprintf(stderr, " %lu",
-+ (ulong)((ib_int64_t)((offset + (zip_size ? zip_size : UNIV_PAGE_SIZE)) * 100) / free_limit_bytes));
-+ }
-+ }
-+
-+ fprintf(stderr, " done.\n");
-+
-+ /* Reacquire the data dictionary lock */
-+ row_mysql_lock_data_dictionary(trx);
-+
-+ /* update SYS_INDEXES set root page */
-+ index = dict_table_get_first_index(table);
-+ while (index) {
-+ for (i = 0; i < n_index; i++) {
-+ if (new_id[i] == index->id) {
-+ break;
-+ }
-+ }
-+
-+ if (i != n_index
-+ && root_page[i] != index->page) {
-+ /* must update */
-+ ulint error;
-+ trx_t* trx;
-+ pars_info_t* info = NULL;
-+
-+ trx = trx_allocate_for_mysql();
-+ trx->op_info = "extended import";
-+
-+ info = pars_info_create();
-+
-+ pars_info_add_ull_literal(info, "indexid", new_id[i]);
-+ pars_info_add_int4_literal(info, "new_page", (lint) root_page[i]);
-+
-+ error = que_eval_sql(info,
-+ "PROCEDURE UPDATE_INDEX_PAGE () IS\n"
-+ "BEGIN\n"
-+ "UPDATE SYS_INDEXES"
-+ " SET PAGE_NO = :new_page"
-+ " WHERE ID = :indexid;\n"
-+ "COMMIT WORK;\n"
-+ "END;\n",
-+ FALSE, trx);
-+
-+ if (error != DB_SUCCESS) {
-+ fprintf(stderr, "InnoDB: failed to update SYS_INDEXES\n");
-+ }
-+
-+ trx_commit_for_mysql(trx);
-+
-+ trx_free_for_mysql(trx);
-+
-+ index->page = root_page[i];
-+ }
-+
-+ index = dict_table_get_next_index(index);
-+ }
-+ if (UNIV_LIKELY_NULL(heap)) {
-+ mem_heap_free(heap);
-+ }
-+ }
-+ /* .exp file should be removed */
-+ success = os_file_delete(info_file_path);
-+ if (!success) {
-+ success = os_file_delete_if_exists(info_file_path);
-+ }
-+ mem_free(info_file_path);
-+
-+ system = fil_system;
-+ mutex_enter(&(system->mutex));
-+ space = fil_space_get_by_id(id);
-+ if (space)
-+ node = UT_LIST_GET_FIRST(space->chain);
-+ if (node && node->size < size) {
-+ space->size += (size - node->size);
-+ node->size = size;
-+ }
-+ mutex_exit(&(system->mutex));
-+
-+ ut_free(buf3);
-+
-+ if (file_is_corrupt) {
-+ ut_print_timestamp(stderr);
-+ fputs(" InnoDB: Error: file ",
-+ stderr);
-+ ut_print_filename(stderr, filepath);
-+ fprintf(stderr, " seems to be corrupt.\n"
-+ "InnoDB: An attempt to convert and salvage all corrupt pages was not made.\n"
-+ "InnoDB: ##### CAUTION #####\n"
-+ "InnoDB: ## The .ibd file may cause InnoDB to crash, even though its re-import seems to have succeeded.\n"
-+ "InnoDB: ## If you don't know how to salvage data from a .ibd, you should not use the file.\n"
-+ "InnoDB: ###################\n");
-+ success = FALSE;
-+
-+ ut_free(buf2);
-+
-+ goto func_exit;
-+ }
-+ }
-+
- ut_free(buf2);
-
- if (UNIV_UNLIKELY(space_id != id
-@@ -3175,6 +3711,269 @@
- os_file_close(file);
- mem_free(filepath);
-
-+ if (srv_expand_import && dict_table_flags_to_zip_size(flags)) {
-+ ulint page_no;
-+ ulint zip_size;
-+ ulint height;
-+ rec_t* node_ptr;
-+ dict_table_t* table;
-+ dict_index_t* index;
-+ buf_block_t* block;
-+ page_t* page;
-+ page_zip_des_t* page_zip;
-+ mtr_t mtr;
-+
-+ mem_heap_t* heap = NULL;
-+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
-+ ulint* offsets = offsets_;
-+
-+ rec_offs_init(offsets_);
-+
-+ zip_size = dict_table_flags_to_zip_size(flags);
-+
-+ table = dict_table_get_low(name);
-+ index = dict_table_get_first_index(table);
-+ page_no = dict_index_get_page(index);
-+ ut_a(page_no == 3);
-+
-+ fprintf(stderr, "InnoDB: It is compressed .ibd file. need to convert additionaly on buffer pool.\n");
-+
-+ /* down to leaf */
-+ mtr_start(&mtr);
-+ mtr_set_log_mode(&mtr, MTR_LOG_NONE);
-+
-+ height = ULINT_UNDEFINED;
-+
-+ for (;;) {
-+ block = buf_page_get(space_id, zip_size, page_no,
-+ RW_NO_LATCH, &mtr);
-+ page = buf_block_get_frame(block);
-+
-+ block->check_index_page_at_flush = TRUE;
-+
-+ if (height == ULINT_UNDEFINED) {
-+ height = btr_page_get_level(page, &mtr);
-+ }
-+
-+ if (height == 0) {
-+ break;
-+ }
-+
-+ node_ptr = page_rec_get_next(page_get_infimum_rec(page));
-+
-+ height--;
-+
-+ offsets = rec_get_offsets(node_ptr, index, offsets, ULINT_UNDEFINED, &heap);
-+ page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
-+ }
-+
-+ mtr_commit(&mtr);
-+
-+ fprintf(stderr, "InnoDB: pages needs split are ...");
-+
-+ /* scan reaf pages */
-+ while (page_no != FIL_NULL) {
-+ rec_t* rec;
-+ rec_t* supremum;
-+ ulint n_recs;
-+
-+ mtr_start(&mtr);
-+
-+ block = buf_page_get(space_id, zip_size, page_no,
-+ RW_X_LATCH, &mtr);
-+ page = buf_block_get_frame(block);
-+ page_zip = buf_block_get_page_zip(block);
-+
-+ if (!page_zip) {
-+ /*something wrong*/
-+ fprintf(stderr, "InnoDB: Something wrong with reading page %lu.\n", page_no);
-+convert_err_exit:
-+ mtr_commit(&mtr);
-+ mutex_enter(&fil_system->mutex);
-+ fil_space_free(space_id, FALSE);
-+ mutex_exit(&fil_system->mutex);
-+ success = FALSE;
-+ goto convert_exit;
-+ }
-+
-+ supremum = page_get_supremum_rec(page);
-+ rec = page_rec_get_next(page_get_infimum_rec(page));
-+ n_recs = page_get_n_recs(page);
-+
-+ /* illegal operation as InnoDB online system. so not logged */
-+ while (rec && rec != supremum && n_recs > 0) {
-+ ulint n_fields;
-+ ulint i;
-+ ulint offset = index->trx_id_offset;
-+
-+ offsets = rec_get_offsets(rec, index, offsets,
-+ ULINT_UNDEFINED, &heap);
-+ n_fields = rec_offs_n_fields(offsets);
-+ if (!offset) {
-+ offset = row_get_trx_id_offset(index, offsets);
-+ }
-+ trx_write_trx_id(rec + offset, 1);
-+
-+ for (i = 0; i < n_fields; i++) {
-+ if (rec_offs_nth_extern(offsets, i)) {
-+ ulint local_len;
-+ byte* data;
-+
-+ data = rec_get_nth_field(rec, offsets, i, &local_len);
-+
-+ local_len -= BTR_EXTERN_FIELD_REF_SIZE;
-+
-+ mach_write_to_4(data + local_len + BTR_EXTERN_SPACE_ID, id);
-+ }
-+ }
-+
-+ rec = page_rec_get_next(rec);
-+ n_recs--;
-+ }
-+
-+ /* dummy logged update for along with modified page path */
-+ if (index->id != btr_page_get_index_id(page)) {
-+ /* this should be adjusted already */
-+ fprintf(stderr, "InnoDB: The page %lu seems to be converted wrong.\n", page_no);
-+ goto convert_err_exit;
-+ }
-+ btr_page_set_index_id(page, page_zip, index->id, &mtr);
-+
-+ /* confirm whether fits to the page size or not */
-+ if (!page_zip_compress(page_zip, page, index, &mtr)
-+ && !btr_page_reorganize(block, index, &mtr)) {
-+ buf_block_t* new_block;
-+ page_t* new_page;
-+ page_zip_des_t* new_page_zip;
-+ rec_t* split_rec;
-+ ulint n_uniq;
-+
-+ /* split page is needed */
-+ fprintf(stderr, " %lu", page_no);
-+
-+ mtr_x_lock(dict_index_get_lock(index), &mtr);
-+
-+ n_uniq = dict_index_get_n_unique_in_tree(index);
-+
-+ if(page_get_n_recs(page) < 2) {
-+ /* no way to make smaller */
-+ fprintf(stderr, "InnoDB: The page %lu cannot be store to the page size.\n", page_no);
-+ goto convert_err_exit;
-+ }
-+
-+ if (UNIV_UNLIKELY(page_no == dict_index_get_page(index))) {
-+ ulint new_page_no;
-+ dtuple_t* node_ptr;
-+ ulint level;
-+ rec_t* node_ptr_rec;
-+ page_cur_t page_cursor;
-+
-+ /* it is root page, need to raise before split */
-+
-+ level = btr_page_get_level(page, &mtr);
-+
-+ new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, &mtr);
-+ new_page = buf_block_get_frame(new_block);
-+ new_page_zip = buf_block_get_page_zip(new_block);
-+ btr_page_create(new_block, new_page_zip, index, level, &mtr);
-+
-+ btr_page_set_next(new_page, new_page_zip, FIL_NULL, &mtr);
-+ btr_page_set_prev(new_page, new_page_zip, FIL_NULL, &mtr);
-+
-+ page_zip_copy_recs(new_page_zip, new_page,
-+ page_zip, page, index, &mtr);
-+ btr_search_move_or_delete_hash_entries(new_block, block, index);
-+
-+ rec = page_rec_get_next(page_get_infimum_rec(new_page));
-+ new_page_no = buf_block_get_page_no(new_block);
-+
-+ node_ptr = dict_index_build_node_ptr(index, rec, new_page_no, heap,
-+ level);
-+ dtuple_set_info_bits(node_ptr,
-+ dtuple_get_info_bits(node_ptr)
-+ | REC_INFO_MIN_REC_FLAG);
-+ btr_page_empty(block, page_zip, index, level + 1, &mtr);
-+
-+ btr_page_set_next(page, page_zip, FIL_NULL, &mtr);
-+ btr_page_set_prev(page, page_zip, FIL_NULL, &mtr);
-+
-+ page_cur_set_before_first(block, &page_cursor);
-+
-+ node_ptr_rec = page_cur_tuple_insert(&page_cursor, node_ptr,
-+ index, 0, &mtr);
-+ ut_a(node_ptr_rec);
-+
-+ if (!btr_page_reorganize(block, index, &mtr)) {
-+ fprintf(stderr, "InnoDB: failed to store the page %lu.\n", page_no);
-+ goto convert_err_exit;
-+ }
-+
-+ /* move to the raised page */
-+ page_no = new_page_no;
-+ block = new_block;
-+ page = new_page;
-+ page_zip = new_page_zip;
-+
-+ fprintf(stderr, "(raise_to:%lu)", page_no);
-+ }
-+
-+ split_rec = page_get_middle_rec(page);
-+
-+ new_block = btr_page_alloc(index, page_no + 1, FSP_UP,
-+ btr_page_get_level(page, &mtr), &mtr);
-+ new_page = buf_block_get_frame(new_block);
-+ new_page_zip = buf_block_get_page_zip(new_block);
-+ btr_page_create(new_block, new_page_zip, index,
-+ btr_page_get_level(page, &mtr), &mtr);
-+
-+ offsets = rec_get_offsets(split_rec, index, offsets, n_uniq, &heap);
-+
-+ btr_attach_half_pages(index, block,
-+ split_rec, new_block, FSP_UP, &mtr);
-+
-+ page_zip_copy_recs(new_page_zip, new_page,
-+ page_zip, page, index, &mtr);
-+ page_delete_rec_list_start(split_rec - page + new_page,
-+ new_block, index, &mtr);
-+ btr_search_move_or_delete_hash_entries(new_block, block, index);
-+ page_delete_rec_list_end(split_rec, block, index,
-+ ULINT_UNDEFINED, ULINT_UNDEFINED, &mtr);
-+
-+ fprintf(stderr, "(new:%lu)", buf_block_get_page_no(new_block));
-+
-+ /* Are they needed? */
-+ if (!btr_page_reorganize(block, index, &mtr)) {
-+ fprintf(stderr, "InnoDB: failed to store the page %lu.\n", page_no);
-+ goto convert_err_exit;
-+ }
-+ if (!btr_page_reorganize(new_block, index, &mtr)) {
-+ fprintf(stderr, "InnoDB: failed to store the page %lu.\n", buf_block_get_page_no(new_block));
-+ goto convert_err_exit;
-+ }
-+ }
-+
-+ page_no = btr_page_get_next(page, &mtr);
-+
-+ mtr_commit(&mtr);
-+
-+ if (heap) {
-+ mem_heap_empty(heap);
-+ }
-+ }
-+
-+ fprintf(stderr, "...done.\nInnoDB: waiting the flush batch of the additional conversion.\n");
-+
-+ /* should wait for the not-logged changes are all flushed */
-+ buf_flush_list(ULINT_MAX, mtr.end_lsn + 1);
-+ buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
-+
-+ fprintf(stderr, "InnoDB: done.\n");
-+convert_exit:
-+ if (UNIV_LIKELY_NULL(heap)) {
-+ mem_heap_free(heap);
-+ }
-+ }
-+
- return(success);
- }
- #endif /* !UNIV_HOTBACKUP */
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -7421,6 +7421,14 @@
- err = row_discard_tablespace_for_mysql(dict_table->name, trx);
- } else {
- err = row_import_tablespace_for_mysql(dict_table->name, trx);
-+
-+ /* in expanded import mode re-initialize auto_increment again */
-+ if ((err == DB_SUCCESS) && srv_expand_import &&
-+ (table->found_next_number_field != NULL)) {
-+ dict_table_autoinc_lock(dict_table);
-+ innobase_initialize_autoinc();
-+ dict_table_autoinc_unlock(dict_table);
-+ }
- }
-
- err = convert_error_code_to_mysql(err, dict_table->flags, NULL);
-@@ -11820,6 +11828,11 @@
- NULL, NULL, 0, 0, 1, 0);
- #endif
-
-+static MYSQL_SYSVAR_ULONG(import_table_from_xtrabackup, srv_expand_import,
-+ PLUGIN_VAR_RQCMDARG,
-+ "Enable/Disable converting automatically *.ibd files when import tablespace.",
-+ NULL, NULL, 0, 0, 1, 0);
-+
- static MYSQL_SYSVAR_ULONG(dict_size_limit, srv_dict_size_limit,
- PLUGIN_VAR_RQCMDARG,
- "Limit the allocated memory for dictionary cache. (0: unlimited)",
-@@ -11894,6 +11907,7 @@
- MYSQL_SYSVAR(flush_neighbor_pages),
- MYSQL_SYSVAR(read_ahead),
- MYSQL_SYSVAR(adaptive_flushing_method),
-+ MYSQL_SYSVAR(import_table_from_xtrabackup),
- MYSQL_SYSVAR(dict_size_limit),
- MYSQL_SYSVAR(use_sys_malloc),
- MYSQL_SYSVAR(use_native_aio),
---- a/storage/innobase/include/btr0btr.h
-+++ b/storage/innobase/include/btr0btr.h
-@@ -238,6 +238,17 @@
- @return the uncompressed page frame */
- # define btr_page_get(space,zip_size,page_no,mode,idx,mtr) \
- buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,idx,mtr))
-+/**************************************************************//**
-+Sets the index id field of a page. */
-+UNIV_INLINE
-+void
-+btr_page_set_index_id(
-+/*==================*/
-+ page_t* page, /*!< in: page to be created */
-+ page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
-+ part will be updated, or NULL */
-+ index_id_t id, /*!< in: index id */
-+ mtr_t* mtr); /*!< in: mtr */
- #endif /* !UNIV_HOTBACKUP */
- /**************************************************************//**
- Gets the index id field of a page.
-@@ -275,6 +286,17 @@
- const page_t* page, /*!< in: index page */
- mtr_t* mtr); /*!< in: mini-transaction handle */
- /********************************************************//**
-+Sets the next index page field. */
-+UNIV_INLINE
-+void
-+btr_page_set_next(
-+/*==============*/
-+ page_t* page, /*!< in: index page */
-+ page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
-+ part will be updated, or NULL */
-+ ulint next, /*!< in: next page number */
-+ mtr_t* mtr); /*!< in: mini-transaction handle */
-+/********************************************************//**
- Gets the previous index page number.
- @return prev page number */
- UNIV_INLINE
-@@ -283,6 +305,17 @@
- /*==============*/
- const page_t* page, /*!< in: index page */
- mtr_t* mtr); /*!< in: mini-transaction handle */
-+/********************************************************//**
-+Sets the previous index page field. */
-+UNIV_INLINE
-+void
-+btr_page_set_prev(
-+/*==============*/
-+ page_t* page, /*!< in: index page */
-+ page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
-+ part will be updated, or NULL */
-+ ulint prev, /*!< in: previous page number */
-+ mtr_t* mtr); /*!< in: mini-transaction handle */
- /*************************************************************//**
- Gets pointer to the previous user record in the tree. It is assumed
- that the caller has appropriate latches on the page and its neighbor.
-@@ -328,6 +361,18 @@
- /*===========================*/
- const rec_t* rec, /*!< in: node pointer record */
- const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
-+/**************************************************************//**
-+Creates a new index page (not the root, and also not
-+used in page reorganization). @see btr_page_empty(). */
-+UNIV_INTERN
-+void
-+btr_page_create(
-+/*============*/
-+ buf_block_t* block, /*!< in/out: page to be created */
-+ page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
-+ dict_index_t* index, /*!< in: index */
-+ ulint level, /*!< in: the B-tree level of the page */
-+ mtr_t* mtr); /*!< in: mtr */
- /************************************************************//**
- Creates the root node for a new index tree.
- @return page number of the created root, FIL_NULL if did not succeed */
-@@ -397,6 +442,17 @@
- dict_index_t* index, /*!< in: record descriptor */
- mtr_t* mtr); /*!< in: mtr */
- /*************************************************************//**
-+Empties an index page. @see btr_page_create(). */
-+UNIV_INTERN
-+void
-+btr_page_empty(
-+/*===========*/
-+ buf_block_t* block, /*!< in: page to be emptied */
-+ page_zip_des_t* page_zip,/*!< out: compressed page, or NULL */
-+ dict_index_t* index, /*!< in: index of the page */
-+ ulint level, /*!< in: the B-tree level of the page */
-+ mtr_t* mtr); /*!< in: mtr */
-+/*************************************************************//**
- Decides if the page should be split at the convergence point of
- inserts converging to left.
- @return TRUE if split recommended */
-@@ -455,6 +511,20 @@
- # define btr_insert_on_non_leaf_level(i,l,t,m) \
- btr_insert_on_non_leaf_level_func(i,l,t,__FILE__,__LINE__,m)
- #endif /* !UNIV_HOTBACKUP */
-+/**************************************************************//**
-+Attaches the halves of an index page on the appropriate level in an
-+index tree. */
-+UNIV_INTERN
-+void
-+btr_attach_half_pages(
-+/*==================*/
-+ dict_index_t* index, /*!< in: the index tree */
-+ buf_block_t* block, /*!< in/out: page to be split */
-+ rec_t* split_rec, /*!< in: first record on upper
-+ half page */
-+ buf_block_t* new_block, /*!< in/out: the new half page */
-+ ulint direction, /*!< in: FSP_UP or FSP_DOWN */
-+ mtr_t* mtr); /*!< in: mtr */
- /****************************************************************//**
- Sets a record as the predefined minimum record. */
- UNIV_INTERN
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -234,6 +234,8 @@
- extern ulint srv_read_ahead;
- extern ulint srv_adaptive_flushing_method;
-
-+extern ulint srv_expand_import;
-+
- extern ulint srv_dict_size_limit;
- /*-------------------------------------------*/
-
---- a/storage/innobase/row/row0mysql.c
-+++ b/storage/innobase/row/row0mysql.c
-@@ -2547,6 +2547,11 @@
-
- current_lsn = log_get_lsn();
-
-+ /* Enlarge the fatal lock wait timeout during import. */
-+ mutex_enter(&kernel_mutex);
-+ srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
-+ mutex_exit(&kernel_mutex);
-+
- /* It is possible, though very improbable, that the lsn's in the
- tablespace to be imported have risen above the current system lsn, if
- a lengthy purge, ibuf merge, or rollback was performed on a backup
-@@ -2632,7 +2637,7 @@
- success = fil_open_single_table_tablespace(
- TRUE, table->space,
- table->flags == DICT_TF_COMPACT ? 0 : table->flags,
-- table->name);
-+ table->name, trx);
- if (success) {
- table->ibd_file_missing = FALSE;
- table->tablespace_discarded = FALSE;
-@@ -2658,6 +2663,11 @@
-
- trx->op_info = "";
-
-+ /* Restore the fatal semaphore wait timeout */
-+ mutex_enter(&kernel_mutex);
-+ srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
-+ mutex_exit(&kernel_mutex);
-+
- return((int) err);
- }
-
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -418,6 +418,8 @@
- UNIV_INTERN ulint srv_read_ahead = 3; /* 1: random 2: linear 3: Both */
- UNIV_INTERN ulint srv_adaptive_flushing_method = 0; /* 0: native 1: estimate 2: keep_average */
-
-+UNIV_INTERN ulint srv_expand_import = 0; /* 0:disable 1:enable */
-+
- UNIV_INTERN ulint srv_dict_size_limit = 0;
- /*-------------------------------------------*/
- UNIV_INTERN ulong srv_n_spin_wait_rounds = 30;
---- a/storage/innobase/dict/dict0load.c
-+++ b/storage/innobase/dict/dict0load.c
-@@ -778,7 +778,7 @@
- object and check that the .ibd file exists. */
-
- fil_open_single_table_tablespace(FALSE, space_id,
-- flags, name);
-+ flags, name, NULL);
- }
-
- mem_free(name);
-@@ -1833,7 +1833,7 @@
- if (!fil_open_single_table_tablespace(
- TRUE, table->space,
- table->flags == DICT_TF_COMPACT ? 0 :
-- table->flags & ~(~0 << DICT_TF_BITS), name)) {
-+ table->flags & ~(~0 << DICT_TF_BITS), name, NULL)) {
- /* We failed to find a sensible
- tablespace file */
-
---- a/storage/innobase/include/fil0fil.h
-+++ b/storage/innobase/include/fil0fil.h
-@@ -34,6 +34,7 @@
- #include "sync0rw.h"
- #include "ibuf0types.h"
- #endif /* !UNIV_HOTBACKUP */
-+#include "trx0types.h"
-
- /** When mysqld is run, the default directory "." is the mysqld datadir,
- but in the MySQL Embedded Server Library and ibbackup it is not the default
-@@ -478,8 +479,11 @@
- accessing the first page of the file */
- ulint id, /*!< in: space id */
- ulint flags, /*!< in: tablespace flags */
-- const char* name); /*!< in: table name in the
-+ const char* name, /*!< in: table name in the
- databasename/tablename format */
-+ trx_t* trx); /*!< in: transaction. This is only used
-+ for IMPORT TABLESPACE, must be NULL
-+ otherwise */
- /********************************************************************//**
- It is possible, though very improbable, that the lsn's in the tablespace to be
- imported have risen above the current system lsn, if a lengthy purge, ibuf
+++ /dev/null
-# name : innodb_extend_slow.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/buf/buf0buf.c
-+++ b/storage/innobase/buf/buf0buf.c
-@@ -51,6 +51,40 @@
- #include "dict0dict.h"
- #include "log0recv.h"
- #include "page0zip.h"
-+#include "trx0trx.h"
-+
-+/* prototypes for new functions added to ha_innodb.cc */
-+trx_t* innobase_get_trx();
-+
-+inline void _increment_page_get_statistics(buf_block_t* block, trx_t* trx)
-+{
-+ ulint block_hash;
-+ ulint block_hash_byte;
-+ byte block_hash_offset;
-+
-+ ut_ad(block);
-+
-+ if (!innobase_get_slow_log() || !trx || !trx->take_stats)
-+ return;
-+
-+ if (!trx->distinct_page_access_hash) {
-+ trx->distinct_page_access_hash = mem_alloc(DPAH_SIZE);
-+ memset(trx->distinct_page_access_hash, 0, DPAH_SIZE);
-+ }
-+
-+ block_hash = ut_hash_ulint((block->page.space << 20) + block->page.space +
-+ block->page.offset, DPAH_SIZE << 3);
-+ block_hash_byte = block_hash >> 3;
-+ block_hash_offset = (byte) block_hash & 0x07;
-+ if (block_hash_byte >= DPAH_SIZE)
-+ fprintf(stderr, "!!! block_hash_byte = %lu block_hash_offset = %d !!!\n", block_hash_byte, block_hash_offset);
-+ if (block_hash_offset > 7)
-+ fprintf(stderr, "!!! block_hash_byte = %lu block_hash_offset = %d !!!\n", block_hash_byte, block_hash_offset);
-+ if ((trx->distinct_page_access_hash[block_hash_byte] & ((byte) 0x01 << block_hash_offset)) == 0)
-+ trx->distinct_page_access++;
-+ trx->distinct_page_access_hash[block_hash_byte] |= (byte) 0x01 << block_hash_offset;
-+ return;
-+}
-
- /*
- IMPLEMENTATION OF THE BUFFER POOL
-@@ -1871,8 +1905,16 @@
- mutex_t* block_mutex;
- ibool must_read;
- unsigned access_time;
-+ trx_t* trx = NULL;
-+ ulint sec;
-+ ulint ms;
-+ ib_uint64_t start_time;
-+ ib_uint64_t finish_time;
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
-
-+ if (innobase_get_slow_log()) {
-+ trx = innobase_get_trx();
-+ }
- buf_pool->stat.n_page_gets++;
-
- for (;;) {
-@@ -1890,7 +1932,7 @@
- //buf_pool_mutex_exit(buf_pool);
- rw_lock_s_unlock(&buf_pool->page_hash_latch);
-
-- buf_read_page(space, zip_size, offset);
-+ buf_read_page(space, zip_size, offset, trx);
-
- #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
- ut_a(++buf_dbg_counter % 37 || buf_validate());
-@@ -1986,6 +2028,13 @@
- /* Let us wait until the read operation
- completes */
-
-+ if (innobase_get_slow_log() && trx && trx->take_stats)
-+ {
-+ ut_usectime(&sec, &ms);
-+ start_time = (ib_uint64_t)sec * 1000000 + ms;
-+ } else {
-+ start_time = 0;
-+ }
- for (;;) {
- enum buf_io_fix io_fix;
-
-@@ -2000,6 +2049,12 @@
- break;
- }
- }
-+ if (innobase_get_slow_log() && trx && trx->take_stats && start_time)
-+ {
-+ ut_usectime(&sec, &ms);
-+ finish_time = (ib_uint64_t)sec * 1000000 + ms;
-+ trx->io_reads_wait_timer += (ulint)(finish_time - start_time);
-+ }
- }
-
- #ifdef UNIV_IBUF_COUNT_DEBUG
-@@ -2314,6 +2369,11 @@
- ibool must_read;
- ulint retries = 0;
- mutex_t* block_mutex = NULL;
-+ trx_t* trx = NULL;
-+ ulint sec;
-+ ulint ms;
-+ ib_uint64_t start_time;
-+ ib_uint64_t finish_time;
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
-
- ut_ad(mtr);
-@@ -2343,6 +2403,9 @@
- || ibuf_page_low(space, zip_size, offset,
- FALSE, file, line, NULL));
- #endif
-+ if (innobase_get_slow_log()) {
-+ trx = innobase_get_trx();
-+ }
- buf_pool->stat.n_page_gets++;
- fold = buf_page_address_fold(space, offset);
- loop:
-@@ -2413,9 +2476,9 @@
- return(NULL);
- }
-
-- if (buf_read_page(space, zip_size, offset)) {
-+ if (buf_read_page(space, zip_size, offset, trx)) {
- buf_read_ahead_random(space, zip_size, offset,
-- ibuf_inside(mtr));
-+ ibuf_inside(mtr), trx);
-
- retries = 0;
- } else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
-@@ -2725,6 +2788,13 @@
- /* Let us wait until the read operation
- completes */
-
-+ if (innobase_get_slow_log() && trx && trx->take_stats)
-+ {
-+ ut_usectime(&sec, &ms);
-+ start_time = (ib_uint64_t)sec * 1000000 + ms;
-+ } else {
-+ start_time = 0;
-+ }
- for (;;) {
- enum buf_io_fix io_fix;
-
-@@ -2739,6 +2809,12 @@
- break;
- }
- }
-+ if (innobase_get_slow_log() && trx && trx->take_stats && start_time)
-+ {
-+ ut_usectime(&sec, &ms);
-+ finish_time = (ib_uint64_t)sec * 1000000 + ms;
-+ trx->io_reads_wait_timer += (ulint)(finish_time - start_time);
-+ }
- }
-
- fix_type = MTR_MEMO_BUF_FIX;
-@@ -2765,13 +2841,17 @@
- read-ahead */
-
- buf_read_ahead_linear(space, zip_size, offset,
-- ibuf_inside(mtr));
-+ ibuf_inside(mtr), trx);
- }
-
- #ifdef UNIV_IBUF_COUNT_DEBUG
- ut_a(ibuf_count_get(buf_block_get_space(block),
- buf_block_get_page_no(block)) == 0);
- #endif
-+ if (innobase_get_slow_log()) {
-+ _increment_page_get_statistics(block, trx);
-+ }
-+
- return(block);
- }
-
-@@ -2795,6 +2875,7 @@
- unsigned access_time;
- ibool success;
- ulint fix_type;
-+ trx_t* trx = NULL;
-
- ut_ad(block);
- ut_ad(mtr);
-@@ -2872,6 +2953,10 @@
- #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
- ut_a(block->page.file_page_was_freed == FALSE);
- #endif
-+ if (innobase_get_slow_log()) {
-+ trx = innobase_get_trx();
-+ }
-+
- if (UNIV_UNLIKELY(!access_time)) {
- /* In the case of a first access, try to apply linear
- read-ahead */
-@@ -2879,7 +2964,7 @@
- buf_read_ahead_linear(buf_block_get_space(block),
- buf_block_get_zip_size(block),
- buf_block_get_page_no(block),
-- ibuf_inside(mtr));
-+ ibuf_inside(mtr), trx);
- }
-
- #ifdef UNIV_IBUF_COUNT_DEBUG
-@@ -2889,6 +2974,9 @@
- buf_pool = buf_pool_from_block(block);
- buf_pool->stat.n_page_gets++;
-
-+ if (innobase_get_slow_log()) {
-+ _increment_page_get_statistics(block, trx);
-+ }
- return(TRUE);
- }
-
-@@ -2911,6 +2999,7 @@
- buf_pool_t* buf_pool;
- ibool success;
- ulint fix_type;
-+ trx_t* trx = NULL;
-
- ut_ad(mtr);
- ut_ad(mtr->state == MTR_ACTIVE);
-@@ -2997,6 +3086,11 @@
- #endif
- buf_pool->stat.n_page_gets++;
-
-+ if (innobase_get_slow_log()) {
-+ trx = innobase_get_trx();
-+ _increment_page_get_statistics(block, trx);
-+ }
-+
- return(TRUE);
- }
-
---- a/storage/innobase/buf/buf0rea.c
-+++ b/storage/innobase/buf/buf0rea.c
-@@ -79,7 +79,8 @@
- treat the tablespace as dropped; this is a timestamp we
- use to stop dangling page reads from a tablespace
- which we have DISCARDed + IMPORTed back */
-- ulint offset) /*!< in: page number */
-+ ulint offset, /*!< in: page number */
-+ trx_t* trx)
- {
- buf_page_t* bpage;
- ulint wake_later;
-@@ -181,15 +182,15 @@
-
- thd_wait_begin(NULL, THD_WAIT_DISKIO);
- if (zip_size) {
-- *err = fil_io(OS_FILE_READ | wake_later,
-+ *err = _fil_io(OS_FILE_READ | wake_later,
- sync, space, zip_size, offset, 0, zip_size,
-- bpage->zip.data, bpage);
-+ bpage->zip.data, bpage, trx);
- } else {
- ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
-
-- *err = fil_io(OS_FILE_READ | wake_later,
-+ *err = _fil_io(OS_FILE_READ | wake_later,
- sync, space, 0, offset, 0, UNIV_PAGE_SIZE,
-- ((buf_block_t*) bpage)->frame, bpage);
-+ ((buf_block_t*) bpage)->frame, bpage, trx);
- }
- thd_wait_end(NULL);
- ut_a(*err == DB_SUCCESS);
-@@ -226,8 +227,9 @@
- or 0 */
- ulint offset, /*!< in: page number of a page which
- the current thread wants to access */
-- ibool inside_ibuf) /*!< in: TRUE if we are inside ibuf
-+ ibool inside_ibuf, /*!< in: TRUE if we are inside ibuf
- routine */
-+ trx_t* trx)
- {
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
- ib_int64_t tablespace_version;
-@@ -330,7 +332,7 @@
- &err, FALSE,
- ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
- space, zip_size, FALSE,
-- tablespace_version, i);
-+ tablespace_version, i, trx);
- if (err == DB_TABLESPACE_DELETED) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
-@@ -380,7 +382,8 @@
- /*==========*/
- ulint space, /*!< in: space id */
- ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
-- ulint offset) /*!< in: page number */
-+ ulint offset, /*!< in: page number */
-+ trx_t* trx)
- {
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
- ib_int64_t tablespace_version;
-@@ -394,7 +397,7 @@
-
- count = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
- zip_size, FALSE,
-- tablespace_version, offset);
-+ tablespace_version, offset, trx);
- srv_buf_pool_reads += count;
- if (err == DB_TABLESPACE_DELETED) {
- ut_print_timestamp(stderr);
-@@ -446,7 +449,8 @@
- ulint space, /*!< in: space id */
- ulint zip_size, /*!< in: compressed page size in bytes, or 0 */
- ulint offset, /*!< in: page number; see NOTE 3 above */
-- ibool inside_ibuf) /*!< in: TRUE if we are inside ibuf routine */
-+ ibool inside_ibuf, /*!< in: TRUE if we are inside ibuf routine */
-+ trx_t* trx)
- {
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
- ib_int64_t tablespace_version;
-@@ -665,7 +669,7 @@
- count += buf_read_page_low(
- &err, FALSE,
- ibuf_mode,
-- space, zip_size, FALSE, tablespace_version, i);
-+ space, zip_size, FALSE, tablespace_version, i, trx);
- if (err == DB_TABLESPACE_DELETED) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
-@@ -758,7 +762,7 @@
- buf_read_page_low(&err, sync && (i + 1 == n_stored),
- BUF_READ_ANY_PAGE, space_ids[i],
- zip_size, TRUE, space_versions[i],
-- page_nos[i]);
-+ page_nos[i], NULL);
-
- if (UNIV_UNLIKELY(err == DB_TABLESPACE_DELETED)) {
- tablespace_deleted:
-@@ -900,12 +904,12 @@
- if ((i + 1 == n_stored) && sync) {
- buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
- zip_size, TRUE, tablespace_version,
-- page_nos[i]);
-+ page_nos[i], NULL);
- } else {
- buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE
- | OS_AIO_SIMULATED_WAKE_LATER,
- space, zip_size, TRUE,
-- tablespace_version, page_nos[i]);
-+ tablespace_version, page_nos[i], NULL);
- }
- }
-
---- a/storage/innobase/fil/fil0fil.c
-+++ b/storage/innobase/fil/fil0fil.c
-@@ -4765,7 +4765,7 @@
- node->name, node->handle, buf,
- offset_low, offset_high,
- page_size * n_pages,
-- NULL, NULL);
-+ NULL, NULL, NULL);
- #endif
- if (success) {
- node->size += n_pages;
-@@ -5092,7 +5092,7 @@
- i/o on a tablespace which does not exist */
- UNIV_INTERN
- ulint
--fil_io(
-+_fil_io(
- /*===*/
- ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE,
- ORed to OS_FILE_LOG, if a log i/o
-@@ -5117,8 +5117,9 @@
- void* buf, /*!< in/out: buffer where to store read data
- or from where to write; in aio this must be
- appropriately aligned */
-- void* message) /*!< in: message for aio handler if non-sync
-+ void* message, /*!< in: message for aio handler if non-sync
- aio used, else ignored */
-+ trx_t* trx)
- {
- ulint mode;
- fil_space_t* space;
-@@ -5286,7 +5287,7 @@
- #else
- /* Queue the aio request */
- ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
-- offset_low, offset_high, len, node, message);
-+ offset_low, offset_high, len, node, message, trx);
- #endif
- ut_a(ret);
-
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -1584,6 +1584,16 @@
- trx->check_unique_secondary = !thd_test_options(
- thd, OPTION_RELAXED_UNIQUE_CHECKS);
-
-+#ifdef EXTENDED_SLOWLOG
-+ if (thd_log_slow_verbosity(thd) & SLOG_V_INNODB) {
-+ trx->take_stats = TRUE;
-+ } else {
-+ trx->take_stats = FALSE;
-+ }
-+#else
-+ trx->take_stats = FALSE;
-+#endif
-+
- DBUG_VOID_RETURN;
- }
-
-@@ -1638,6 +1648,32 @@
- return(trx);
- }
-
-+/*************************************************************************
-+Gets current trx. */
-+extern "C"
-+trx_t*
-+innobase_get_trx()
-+{
-+ THD *thd=current_thd;
-+ if (likely(thd != 0)) {
-+ trx_t*& trx = thd_to_trx(thd);
-+ return(trx);
-+ } else {
-+ return(NULL);
-+ }
-+}
-+
-+extern "C"
-+ibool
-+innobase_get_slow_log()
-+{
-+#ifdef EXTENDED_SLOWLOG
-+ return((ibool) thd_opt_slow_log());
-+#else
-+ return(FALSE);
-+#endif
-+}
-+
- /*********************************************************************//**
- Note that a transaction has been registered with MySQL.
- @return true if transaction is registered with MySQL 2PC coordinator */
-@@ -9417,6 +9453,25 @@
- statement has ended */
-
- if (trx->n_mysql_tables_in_use == 0) {
-+#ifdef EXTENDED_SLOWLOG
-+ increment_thd_innodb_stats(thd,
-+ (unsigned long long) trx->id,
-+ trx->io_reads,
-+ trx->io_read,
-+ trx->io_reads_wait_timer,
-+ trx->lock_que_wait_timer,
-+ trx->innodb_que_wait_timer,
-+ trx->distinct_page_access);
-+
-+ trx->io_reads = 0;
-+ trx->io_read = 0;
-+ trx->io_reads_wait_timer = 0;
-+ trx->lock_que_wait_timer = 0;
-+ trx->innodb_que_wait_timer = 0;
-+ trx->distinct_page_access = 0;
-+ if (trx->distinct_page_access_hash)
-+ memset(trx->distinct_page_access_hash, 0, DPAH_SIZE);
-+#endif
-
- trx->mysql_n_tables_locked = 0;
- prebuilt->used_in_HANDLER = FALSE;
---- a/storage/innobase/include/buf0rea.h
-+++ b/storage/innobase/include/buf0rea.h
-@@ -27,6 +27,7 @@
- #define buf0rea_h
-
- #include "univ.i"
-+#include "trx0types.h"
- #include "buf0types.h"
-
- /********************************************************************//**
-@@ -41,7 +42,8 @@
- /*==========*/
- ulint space, /*!< in: space id */
- ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
-- ulint offset);/*!< in: page number */
-+ ulint offset, /*!< in: page number */
-+ trx_t* trx);
- /********************************************************************//**
- Applies a random read-ahead in buf_pool if there are at least a threshold
- value of accessed pages from the random read-ahead area. Does not read any
-@@ -65,8 +67,9 @@
- or 0 */
- ulint offset, /*!< in: page number of a page which
- the current thread wants to access */
-- ibool inside_ibuf); /*!< in: TRUE if we are inside ibuf
-+ ibool inside_ibuf, /*!< in: TRUE if we are inside ibuf
- routine */
-+ trx_t* trx);
- /********************************************************************//**
- Applies linear read-ahead if in the buf_pool the page is a border page of
- a linear read-ahead area and all the pages in the area have been accessed.
-@@ -98,7 +101,8 @@
- ulint space, /*!< in: space id */
- ulint zip_size, /*!< in: compressed page size in bytes, or 0 */
- ulint offset, /*!< in: page number; see NOTE 3 above */
-- ibool inside_ibuf); /*!< in: TRUE if we are inside ibuf routine */
-+ ibool inside_ibuf, /*!< in: TRUE if we are inside ibuf routine */
-+ trx_t* trx);
- /********************************************************************//**
- Issues read requests for pages which the ibuf module wants to read in, in
- order to contract the insert buffer tree. Technically, this function is like
---- a/storage/innobase/include/fil0fil.h
-+++ b/storage/innobase/include/fil0fil.h
-@@ -620,9 +620,12 @@
- Reads or writes data. This operation is asynchronous (aio).
- @return DB_SUCCESS, or DB_TABLESPACE_DELETED if we are trying to do
- i/o on a tablespace which does not exist */
-+#define fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message) \
-+ _fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message, NULL)
-+
- UNIV_INTERN
- ulint
--fil_io(
-+_fil_io(
- /*===*/
- ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE,
- ORed to OS_FILE_LOG, if a log i/o
-@@ -647,8 +650,9 @@
- void* buf, /*!< in/out: buffer where to store read data
- or from where to write; in aio this must be
- appropriately aligned */
-- void* message); /*!< in: message for aio handler if non-sync
-+ void* message, /*!< in: message for aio handler if non-sync
- aio used, else ignored */
-+ trx_t* trx);
- /**********************************************************************//**
- Waits for an aio operation to complete. This function is used to write the
- handler for completed requests. The aio array of pending requests is divided
---- a/storage/innobase/include/os0file.h
-+++ b/storage/innobase/include/os0file.h
-@@ -36,6 +36,7 @@
- #define os0file_h
-
- #include "univ.i"
-+#include "trx0types.h"
-
- #ifndef __WIN__
- #include <dirent.h>
-@@ -277,13 +278,17 @@
- pfs_os_file_close_func(file, __FILE__, __LINE__)
-
- # define os_aio(type, mode, name, file, buf, offset, offset_high, \
-- n, message1, message2) \
-+ n, message1, message2, trx) \
- pfs_os_aio_func(type, mode, name, file, buf, offset, \
-- offset_high, n, message1, message2, \
-+ offset_high, n, message1, message2, trx, \
- __FILE__, __LINE__)
-
- # define os_file_read(file, buf, offset, offset_high, n) \
-- pfs_os_file_read_func(file, buf, offset, offset_high, n, \
-+ pfs_os_file_read_func(file, buf, offset, offset_high, n, NULL, \
-+ __FILE__, __LINE__)
-+
-+# define os_file_read_trx(file, buf, offset, offset_high, n, trx) \
-+ pfs_os_file_read_func(file, buf, offset, offset_high, n, trx, \
- __FILE__, __LINE__)
-
- # define os_file_read_no_error_handling(file, buf, offset, \
-@@ -319,12 +324,15 @@
- # define os_file_close(file) os_file_close_func(file)
-
- # define os_aio(type, mode, name, file, buf, offset, offset_high, \
-- n, message1, message2) \
-+ n, message1, message2, trx) \
- os_aio_func(type, mode, name, file, buf, offset, offset_high, n,\
-- message1, message2)
-+ message1, message2, trx)
-
- # define os_file_read(file, buf, offset, offset_high, n) \
-- os_file_read_func(file, buf, offset, offset_high, n)
-+ os_file_read_func(file, buf, offset, offset_high, n, NULL)
-+
-+# define os_file_read_trx(file, buf, offset, offset_high, n, trx) \
-+ os_file_read_func(file, buf, offset, offset_high, n, trx)
-
- # define os_file_read_no_error_handling(file, buf, offset, \
- offset_high, n) \
-@@ -692,6 +700,7 @@
- ulint offset_high,/*!< in: most significant 32 bits of
- offset */
- ulint n, /*!< in: number of bytes to read */
-+ trx_t* trx,
- const char* src_file,/*!< in: file name where func invoked */
- ulint src_line);/*!< in: line where the func invoked */
-
-@@ -746,6 +755,7 @@
- (can be used to identify a completed
- aio operation); ignored if mode is
- OS_AIO_SYNC */
-+ trx_t* trx,
- const char* src_file,/*!< in: file name where func invoked */
- ulint src_line);/*!< in: line where the func invoked */
- /*******************************************************************//**
-@@ -889,7 +899,8 @@
- offset where to read */
- ulint offset_high,/*!< in: most significant 32 bits of
- offset */
-- ulint n); /*!< in: number of bytes to read */
-+ ulint n, /*!< in: number of bytes to read */
-+ trx_t* trx);
- /*******************************************************************//**
- Rewind file to its start, read at most size - 1 bytes from it to str, and
- NUL-terminate str. All errors are silently ignored. This function is
-@@ -1048,10 +1059,11 @@
- (can be used to identify a completed
- aio operation); ignored if mode is
- OS_AIO_SYNC */
-- void* message2);/*!< in: message for the aio handler
-+ void* message2,/*!< in: message for the aio handler
- (can be used to identify a completed
- aio operation); ignored if mode is
- OS_AIO_SYNC */
-+ trx_t* trx);
- /************************************************************************//**
- Wakes up all async i/o threads so that they know to exit themselves in
- shutdown. */
---- a/storage/innobase/include/os0file.ic
-+++ b/storage/innobase/include/os0file.ic
-@@ -229,6 +229,7 @@
- (can be used to identify a completed
- aio operation); ignored if mode is
- OS_AIO_SYNC */
-+ trx_t* trx,
- const char* src_file,/*!< in: file name where func invoked */
- ulint src_line)/*!< in: line where the func invoked */
- {
-@@ -244,7 +245,7 @@
- src_file, src_line);
-
- result = os_aio_func(type, mode, name, file, buf, offset, offset_high,
-- n, message1, message2);
-+ n, message1, message2, trx);
-
- register_pfs_file_io_end(locker, n);
-
-@@ -268,6 +269,7 @@
- ulint offset_high,/*!< in: most significant 32 bits of
- offset */
- ulint n, /*!< in: number of bytes to read */
-+ trx_t* trx,
- const char* src_file,/*!< in: file name where func invoked */
- ulint src_line)/*!< in: line where the func invoked */
- {
-@@ -278,7 +280,7 @@
- register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_READ,
- src_file, src_line);
-
-- result = os_file_read_func(file, buf, offset, offset_high, n);
-+ result = os_file_read_func(file, buf, offset, offset_high, n, trx);
-
- register_pfs_file_io_end(locker, n);
-
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -71,6 +71,9 @@
- #define SRV_AUTO_EXTEND_INCREMENT \
- (srv_auto_extend_increment * ((1024 * 1024) / UNIV_PAGE_SIZE))
-
-+/* prototypes for new functions added to ha_innodb.cc */
-+ibool innobase_get_slow_log();
-+
- /* Mutex for locking srv_monitor_file */
- extern mutex_t srv_monitor_file_mutex;
- /* Temporary file for innodb monitor output */
---- a/storage/innobase/include/trx0trx.h
-+++ b/storage/innobase/include/trx0trx.h
-@@ -743,6 +743,17 @@
- /*------------------------------*/
- char detailed_error[256]; /*!< detailed error message for last
- error, or empty. */
-+ /*------------------------------*/
-+ ulint io_reads;
-+ ib_uint64_t io_read;
-+ ulint io_reads_wait_timer;
-+ ib_uint64_t lock_que_wait_ustarted;
-+ ulint lock_que_wait_timer;
-+ ulint innodb_que_wait_timer;
-+ ulint distinct_page_access;
-+#define DPAH_SIZE 8192
-+ byte* distinct_page_access_hash;
-+ ibool take_stats;
- };
-
- #define TRX_MAX_N_THREADS 32 /* maximum number of
---- a/storage/innobase/lock/lock0lock.c
-+++ b/storage/innobase/lock/lock0lock.c
-@@ -1765,6 +1765,8 @@
- {
- lock_t* lock;
- trx_t* trx;
-+ ulint sec;
-+ ulint ms;
-
- ut_ad(mutex_own(&kernel_mutex));
-
-@@ -1823,6 +1825,10 @@
- trx->que_state = TRX_QUE_LOCK_WAIT;
- trx->was_chosen_as_deadlock_victim = FALSE;
- trx->wait_started = time(NULL);
-+ if (innobase_get_slow_log() && trx->take_stats) {
-+ ut_usectime(&sec, &ms);
-+ trx->lock_que_wait_ustarted = (ib_uint64_t)sec * 1000000 + ms;
-+ }
-
- ut_a(que_thr_stop(thr));
-
-@@ -3766,6 +3772,8 @@
- {
- lock_t* lock;
- trx_t* trx;
-+ ulint sec;
-+ ulint ms;
-
- ut_ad(mutex_own(&kernel_mutex));
-
-@@ -3821,6 +3829,10 @@
- return(DB_SUCCESS);
- }
-
-+ if (innobase_get_slow_log() && trx->take_stats) {
-+ ut_usectime(&sec, &ms);
-+ trx->lock_que_wait_ustarted = (ib_uint64_t)sec * 1000000 + ms;
-+ }
- trx->que_state = TRX_QUE_LOCK_WAIT;
- trx->was_chosen_as_deadlock_victim = FALSE;
- trx->wait_started = time(NULL);
---- a/storage/innobase/os/os0file.c
-+++ b/storage/innobase/os/os0file.c
-@@ -43,6 +43,8 @@
- #include "srv0start.h"
- #include "fil0fil.h"
- #include "buf0buf.h"
-+#include "trx0sys.h"
-+#include "trx0trx.h"
- #include "log0recv.h"
- #ifndef UNIV_HOTBACKUP
- # include "os0sync.h"
-@@ -2213,13 +2215,18 @@
- ulint n, /*!< in: number of bytes to read */
- ulint offset, /*!< in: least significant 32 bits of file
- offset from where to read */
-- ulint offset_high) /*!< in: most significant 32 bits of
-+ ulint offset_high, /*!< in: most significant 32 bits of
- offset */
-+ trx_t* trx)
- {
- off_t offs;
- #if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
- ssize_t n_bytes;
- #endif /* HAVE_PREAD && !HAVE_BROKEN_PREAD */
-+ ulint sec;
-+ ulint ms;
-+ ib_uint64_t start_time;
-+ ib_uint64_t finish_time;
-
- ut_a((offset & 0xFFFFFFFFUL) == offset);
-
-@@ -2240,6 +2247,15 @@
-
- os_n_file_reads++;
-
-+ if (innobase_get_slow_log() && trx && trx->take_stats)
-+ {
-+ trx->io_reads++;
-+ trx->io_read += n;
-+ ut_usectime(&sec, &ms);
-+ start_time = (ib_uint64_t)sec * 1000000 + ms;
-+ } else {
-+ start_time = 0;
-+ }
- #if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
- os_mutex_enter(os_file_count_mutex);
- os_file_n_pending_preads++;
-@@ -2253,6 +2269,13 @@
- os_n_pending_reads--;
- os_mutex_exit(os_file_count_mutex);
-
-+ if (innobase_get_slow_log() && trx && trx->take_stats && start_time)
-+ {
-+ ut_usectime(&sec, &ms);
-+ finish_time = (ib_uint64_t)sec * 1000000 + ms;
-+ trx->io_reads_wait_timer += (ulint)(finish_time - start_time);
-+ }
-+
- return(n_bytes);
- #else
- {
-@@ -2289,6 +2312,13 @@
- os_n_pending_reads--;
- os_mutex_exit(os_file_count_mutex);
-
-+ if (innobase_get_slow_log() && trx && trx->take_stats && start_time)
-+ {
-+ ut_usectime(&sec, &ms);
-+ finish_time = (ib_uint64_t)sec * 1000000 + ms;
-+ trx->io_reads_wait_timer += (ulint)(finish_time - start_time);
-+ }
-+
- return(ret);
- }
- #endif
-@@ -2429,7 +2459,8 @@
- offset where to read */
- ulint offset_high, /*!< in: most significant 32 bits of
- offset */
-- ulint n) /*!< in: number of bytes to read */
-+ ulint n, /*!< in: number of bytes to read */
-+ trx_t* trx)
- {
- #ifdef __WIN__
- BOOL ret;
-@@ -2504,7 +2535,7 @@
- os_bytes_read_since_printout += n;
-
- try_again:
-- ret = os_file_pread(file, buf, n, offset, offset_high);
-+ ret = os_file_pread(file, buf, n, offset, offset_high, trx);
-
- if ((ulint)ret == n) {
-
-@@ -2633,7 +2664,7 @@
- os_bytes_read_since_printout += n;
-
- try_again:
-- ret = os_file_pread(file, buf, n, offset, offset_high);
-+ ret = os_file_pread(file, buf, n, offset, offset_high, NULL);
-
- if ((ulint)ret == n) {
-
-@@ -4027,10 +4058,11 @@
- (can be used to identify a completed
- aio operation); ignored if mode is
- OS_AIO_SYNC */
-- void* message2)/*!< in: message for the aio handler
-+ void* message2,/*!< in: message for the aio handler
- (can be used to identify a completed
- aio operation); ignored if mode is
- OS_AIO_SYNC */
-+ trx_t* trx)
- {
- os_aio_array_t* array;
- os_aio_slot_t* slot;
-@@ -4078,7 +4110,7 @@
-
- if (type == OS_FILE_READ) {
- return(os_file_read_func(file, buf, offset,
-- offset_high, n));
-+ offset_high, n, trx));
- }
-
- ut_a(type == OS_FILE_WRITE);
-@@ -4119,6 +4151,11 @@
- array = NULL; /* Eliminate compiler warning */
- }
-
-+ if (trx && type == OS_FILE_READ)
-+ {
-+ trx->io_reads++;
-+ trx->io_read += n;
-+ }
- slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
- name, buf, offset, offset_high, n);
- if (type == OS_FILE_READ) {
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -87,6 +87,9 @@
- #include "mysql/plugin.h"
- #include "mysql/service_thd_wait.h"
-
-+/* prototypes for new functions added to ha_innodb.cc */
-+ibool innobase_get_slow_log();
-+
- /* The following counter is incremented whenever there is some user activity
- in the server */
- UNIV_INTERN ulint srv_activity_count = 0;
-@@ -1237,6 +1240,10 @@
- ibool has_slept = FALSE;
- srv_conc_slot_t* slot = NULL;
- ulint i;
-+ ib_uint64_t start_time = 0L;
-+ ib_uint64_t finish_time = 0L;
-+ ulint sec;
-+ ulint ms;
-
- #ifdef UNIV_SYNC_DEBUG
- ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
-@@ -1317,6 +1324,7 @@
- switches. */
- if (SRV_THREAD_SLEEP_DELAY > 0) {
- os_thread_sleep(SRV_THREAD_SLEEP_DELAY);
-+ trx->innodb_que_wait_timer += SRV_THREAD_SLEEP_DELAY;
- }
-
- trx->op_info = "";
-@@ -1376,6 +1384,14 @@
- #ifdef UNIV_SYNC_DEBUG
- ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
- #endif /* UNIV_SYNC_DEBUG */
-+
-+ if (innobase_get_slow_log() && trx->take_stats) {
-+ ut_usectime(&sec, &ms);
-+ start_time = (ib_uint64_t)sec * 1000000 + ms;
-+ } else {
-+ start_time = 0;
-+ }
-+
- trx->op_info = "waiting in InnoDB queue";
-
- thd_wait_begin(trx->mysql_thd, THD_WAIT_USER_LOCK);
-@@ -1384,6 +1400,12 @@
-
- trx->op_info = "";
-
-+ if (innobase_get_slow_log() && trx->take_stats && start_time) {
-+ ut_usectime(&sec, &ms);
-+ finish_time = (ib_uint64_t)sec * 1000000 + ms;
-+ trx->innodb_que_wait_timer += (ulint)(finish_time - start_time);
-+ }
-+
- os_fast_mutex_lock(&srv_conc_mutex);
-
- srv_conc_n_waiting_threads--;
---- a/storage/innobase/trx/trx0trx.c
-+++ b/storage/innobase/trx/trx0trx.c
-@@ -188,6 +188,15 @@
- trx->global_read_view = NULL;
- trx->read_view = NULL;
-
-+ trx->io_reads = 0;
-+ trx->io_read = 0;
-+ trx->io_reads_wait_timer = 0;
-+ trx->lock_que_wait_timer = 0;
-+ trx->innodb_que_wait_timer = 0;
-+ trx->distinct_page_access = 0;
-+ trx->distinct_page_access_hash = NULL;
-+ trx->take_stats = FALSE;
-+
- /* Set X/Open XA transaction identification to NULL */
- memset(&trx->xid, 0, sizeof(trx->xid));
- trx->xid.formatID = -1;
-@@ -221,6 +230,11 @@
-
- mutex_exit(&kernel_mutex);
-
-+ if (innobase_get_slow_log() && trx->take_stats) {
-+ trx->distinct_page_access_hash = mem_alloc(DPAH_SIZE);
-+ memset(trx->distinct_page_access_hash, 0, DPAH_SIZE);
-+ }
-+
- return(trx);
- }
-
-@@ -406,6 +420,12 @@
- /*===============*/
- trx_t* trx) /*!< in, own: trx object */
- {
-+ if (trx->distinct_page_access_hash)
-+ {
-+ mem_free(trx->distinct_page_access_hash);
-+ trx->distinct_page_access_hash= NULL;
-+ }
-+
- mutex_enter(&kernel_mutex);
-
- UT_LIST_REMOVE(mysql_trx_list, trx_sys->mysql_trx_list, trx);
-@@ -427,6 +447,12 @@
- /*====================*/
- trx_t* trx) /*!< in, own: trx object */
- {
-+ if (trx->distinct_page_access_hash)
-+ {
-+ mem_free(trx->distinct_page_access_hash);
-+ trx->distinct_page_access_hash= NULL;
-+ }
-+
- mutex_enter(&kernel_mutex);
-
- trx_free(trx);
-@@ -1212,6 +1238,9 @@
- trx_t* trx) /*!< in: transaction */
- {
- que_thr_t* thr;
-+ ulint sec;
-+ ulint ms;
-+ ib_uint64_t now;
-
- ut_ad(mutex_own(&kernel_mutex));
- ut_ad(trx->que_state == TRX_QUE_LOCK_WAIT);
-@@ -1226,6 +1255,11 @@
- thr = UT_LIST_GET_FIRST(trx->wait_thrs);
- }
-
-+ if (innobase_get_slow_log() && trx->take_stats) {
-+ ut_usectime(&sec, &ms);
-+ now = (ib_uint64_t)sec * 1000000 + ms;
-+ trx->lock_que_wait_timer += (ulint)(now - trx->lock_que_wait_ustarted);
-+ }
- trx->que_state = TRX_QUE_RUNNING;
- }
-
-@@ -1239,6 +1273,9 @@
- trx_t* trx) /*!< in: transaction in the TRX_QUE_LOCK_WAIT state */
- {
- que_thr_t* thr;
-+ ulint sec;
-+ ulint ms;
-+ ib_uint64_t now;
-
- ut_ad(mutex_own(&kernel_mutex));
- ut_ad(trx->que_state == TRX_QUE_LOCK_WAIT);
-@@ -1253,6 +1290,11 @@
- thr = UT_LIST_GET_FIRST(trx->wait_thrs);
- }
-
-+ if (innobase_get_slow_log() && trx->take_stats) {
-+ ut_usectime(&sec, &ms);
-+ now = (ib_uint64_t)sec * 1000000 + ms;
-+ trx->lock_que_wait_timer += (ulint)(now - trx->lock_que_wait_ustarted);
-+ }
- trx->que_state = TRX_QUE_RUNNING;
- }
-
+++ /dev/null
-# name : innodb_extra_rseg.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -11706,6 +11706,7 @@
- NULL, /* reserved */
- 0, /* flags */
- },
-+i_s_innodb_rseg,
- i_s_innodb_trx,
- i_s_innodb_locks,
- i_s_innodb_lock_waits,
---- a/storage/innobase/handler/i_s.cc
-+++ b/storage/innobase/handler/i_s.cc
-@@ -45,6 +45,8 @@
- #include "srv0start.h" /* for srv_was_started */
- #include "trx0i_s.h"
- #include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
-+#include "trx0rseg.h" /* for trx_rseg_struct */
-+#include "trx0sys.h" /* for trx_sys */
- }
-
- #define OK(expr) \
-@@ -1807,3 +1809,170 @@
-
- DBUG_RETURN(0);
- }
-+
-+/***********************************************************************
-+*/
-+static ST_FIELD_INFO i_s_innodb_rseg_fields_info[] =
-+{
-+ {STRUCT_FLD(field_name, "rseg_id"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "space_id"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "zip_size"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "page_no"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "max_size"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "curr_size"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ END_OF_ST_FIELD_INFO
-+};
-+
-+static
-+int
-+i_s_innodb_rseg_fill(
-+/*=================*/
-+ THD* thd, /* in: thread */
-+ TABLE_LIST* tables, /* in/out: tables to fill */
-+ COND* cond) /* in: condition (ignored) */
-+{
-+ TABLE* table = (TABLE *) tables->table;
-+ int status = 0;
-+ trx_rseg_t* rseg;
-+
-+ DBUG_ENTER("i_s_innodb_rseg_fill");
-+
-+ /* deny access to non-superusers */
-+ if (check_global_access(thd, PROCESS_ACL)) {
-+
-+ DBUG_RETURN(0);
-+ }
-+
-+ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
-+
-+ rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
-+
-+ while (rseg) {
-+ table->field[0]->store(rseg->id);
-+ table->field[1]->store(rseg->space);
-+ table->field[2]->store(rseg->zip_size);
-+ table->field[3]->store(rseg->page_no);
-+ table->field[4]->store(rseg->max_size);
-+ table->field[5]->store(rseg->curr_size);
-+
-+ if (schema_table_store_record(thd, table)) {
-+ status = 1;
-+ break;
-+ }
-+
-+ rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
-+ }
-+
-+ DBUG_RETURN(status);
-+}
-+
-+static
-+int
-+i_s_innodb_rseg_init(
-+/*=================*/
-+ /* out: 0 on success */
-+ void* p) /* in/out: table schema object */
-+{
-+ DBUG_ENTER("i_s_innodb_rseg_init");
-+ ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
-+
-+ schema->fields_info = i_s_innodb_rseg_fields_info;
-+ schema->fill_table = i_s_innodb_rseg_fill;
-+
-+ DBUG_RETURN(0);
-+}
-+
-+UNIV_INTERN struct st_mysql_plugin i_s_innodb_rseg =
-+{
-+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
-+ /* int */
-+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-+
-+ /* pointer to type-specific plugin descriptor */
-+ /* void* */
-+ STRUCT_FLD(info, &i_s_info),
-+
-+ /* plugin name */
-+ /* const char* */
-+ STRUCT_FLD(name, "INNODB_RSEG"),
-+
-+ /* plugin author (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(author, "Percona"),
-+
-+ /* general descriptive text (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(descr, "InnoDB rollback segment information"),
-+
-+ /* the plugin license (PLUGIN_LICENSE_XXX) */
-+ /* int */
-+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-+
-+ /* the function to invoke when plugin is loaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(init, i_s_innodb_rseg_init),
-+
-+ /* the function to invoke when plugin is unloaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(deinit, i_s_common_deinit),
-+
-+ /* plugin version (for SHOW PLUGINS) */
-+ /* unsigned int */
-+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
-+
-+ /* struct st_mysql_show_var* */
-+ STRUCT_FLD(status_vars, NULL),
-+
-+ /* struct st_mysql_sys_var** */
-+ STRUCT_FLD(system_vars, NULL),
-+
-+ /* reserved for dependency checking */
-+ /* void* */
-+ STRUCT_FLD(__reserved1, NULL),
-+
-+ /* Plugin flags */
-+ /* unsigned long */
-+ STRUCT_FLD(flags, 0UL),
-+};
---- a/storage/innobase/handler/i_s.h
-+++ b/storage/innobase/handler/i_s.h
-@@ -35,5 +35,6 @@
- extern struct st_mysql_plugin i_s_innodb_cmp_reset;
- extern struct st_mysql_plugin i_s_innodb_cmpmem;
- extern struct st_mysql_plugin i_s_innodb_cmpmem_reset;
-+extern struct st_mysql_plugin i_s_innodb_rseg;
-
- #endif /* i_s_h */
+++ /dev/null
-# name : innodb_fake_changes.patch
-# introduced : 5.5.15
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/btr/btr0cur.c
-+++ b/storage/innobase/btr/btr0cur.c
-@@ -1158,6 +1158,11 @@
- rec_t* rec;
- roll_ptr_t roll_ptr;
-
-+ if (thr && thr_get_trx(thr)->fake_changes) {
-+ /* skip LOCK, UNDO */
-+ return(DB_SUCCESS);
-+ }
-+
- /* Check if we have to wait for a lock: enqueue an explicit lock
- request if yes */
-
-@@ -1289,7 +1294,7 @@
- }
- #endif /* UNIV_DEBUG */
-
-- ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
-+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
- max_size = page_get_max_insert_size_after_reorganize(page, 1);
- leaf = page_is_leaf(page);
-
-@@ -1384,6 +1389,12 @@
- goto fail_err;
- }
-
-+ if (thr && thr_get_trx(thr)->fake_changes) {
-+ /* skip CHANGE, LOG */
-+ *big_rec = big_rec_vec;
-+ return(err); /* == DB_SUCCESS */
-+ }
-+
- page_cursor = btr_cur_get_page_cur(cursor);
-
- /* Now, try the insert */
-@@ -1526,10 +1537,10 @@
-
- *big_rec = NULL;
-
-- ut_ad(mtr_memo_contains(mtr,
-+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr,
- dict_index_get_lock(btr_cur_get_index(cursor)),
- MTR_MEMO_X_LOCK));
-- ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
-+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, btr_cur_get_block(cursor),
- MTR_MEMO_PAGE_X_FIX));
-
- /* Try first an optimistic insert; reset the cursor flag: we do not
-@@ -1595,6 +1606,16 @@
- }
- }
-
-+ if (thr && thr_get_trx(thr)->fake_changes) {
-+ /* skip CHANGE, LOG */
-+ if (n_extents > 0) {
-+ fil_space_release_free_extents(index->space,
-+ n_reserved);
-+ }
-+ *big_rec = big_rec_vec;
-+ return(DB_SUCCESS);
-+ }
-+
- if (dict_index_get_page(index)
- == buf_block_get_page_no(btr_cur_get_block(cursor))) {
-
-@@ -1651,6 +1672,11 @@
-
- ut_ad(cursor && update && thr && roll_ptr);
-
-+ if (thr && thr_get_trx(thr)->fake_changes) {
-+ /* skip LOCK, UNDO */
-+ return(DB_SUCCESS);
-+ }
-+
- rec = btr_cur_get_rec(cursor);
- index = cursor->index;
-
-@@ -1950,6 +1976,14 @@
- return(err);
- }
-
-+ if (trx->fake_changes) {
-+ /* skip CHANGE, LOG */
-+ if (UNIV_LIKELY_NULL(heap)) {
-+ mem_heap_free(heap);
-+ }
-+ return(err); /* == DB_SUCCESS */
-+ }
-+
- if (!(flags & BTR_KEEP_SYS_FLAG)) {
- row_upd_rec_sys_fields(rec, NULL,
- index, offsets, trx, roll_ptr);
-@@ -2059,7 +2093,7 @@
- rec = btr_cur_get_rec(cursor);
- index = cursor->index;
- ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
-- ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
-+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
- /* The insert buffer tree should never be updated in place. */
- ut_ad(!dict_index_is_ibuf(index));
-
-@@ -2172,6 +2206,11 @@
- goto err_exit;
- }
-
-+ if (thr && thr_get_trx(thr)->fake_changes) {
-+ /* skip CHANGE, LOG */
-+ goto err_exit; /* == DB_SUCCESS */
-+ }
-+
- /* Ok, we may do the replacement. Store on the page infimum the
- explicit locks on rec, before deleting rec (see the comment in
- btr_cur_pessimistic_update). */
-@@ -2322,9 +2361,9 @@
- rec = btr_cur_get_rec(cursor);
- index = cursor->index;
-
-- ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
-+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, dict_index_get_lock(index),
- MTR_MEMO_X_LOCK));
-- ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
-+ ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
- #ifdef UNIV_ZIP_DEBUG
- ut_a(!page_zip || page_zip_validate(page_zip, page));
- #endif /* UNIV_ZIP_DEBUG */
-@@ -2412,6 +2451,9 @@
-
- ut_ad(big_rec_vec == NULL);
-
-+ /* fake_changes should not cause undo. so never reaches here */
-+ ut_ad(!(trx->fake_changes));
-+
- btr_rec_free_updated_extern_fields(
- index, rec, page_zip, offsets, update,
- trx_is_recv(trx) ? RB_RECOVERY : RB_NORMAL, mtr);
-@@ -2446,6 +2488,12 @@
- }
- }
-
-+ if (trx->fake_changes) {
-+ /* skip CHANGE, LOG */
-+ err = DB_SUCCESS;
-+ goto return_after_reservations;
-+ }
-+
- /* Store state of explicit locks on rec on the page infimum record,
- before deleting rec. The page infimum acts as a dummy carrier of the
- locks, taking care also of lock releases, before we can move the locks
-@@ -2748,6 +2796,11 @@
- ut_ad(dict_index_is_clust(index));
- ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
-
-+ if (thr && thr_get_trx(thr)->fake_changes) {
-+ /* skip LOCK, UNDO, CHANGE, LOG */
-+ return(DB_SUCCESS);
-+ }
-+
- err = lock_clust_rec_modify_check_and_lock(flags, block,
- rec, index, offsets, thr);
-
-@@ -2882,6 +2935,11 @@
- rec_t* rec;
- ulint err;
-
-+ if (thr && thr_get_trx(thr)->fake_changes) {
-+ /* skip LOCK, CHANGE, LOG */
-+ return(DB_SUCCESS);
-+ }
-+
- block = btr_cur_get_block(cursor);
- rec = btr_cur_get_rec(cursor);
-
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -488,6 +488,12 @@
- " or 2 (write at commit, flush once per second).",
- NULL, NULL, 1, 0, 2, 0);
-
-+static MYSQL_THDVAR_BOOL(fake_changes, PLUGIN_VAR_OPCMDARG,
-+ "In the transaction after enabled, UPDATE, INSERT and DELETE only move the cursor to the records "
-+ "and do nothing other operations (no changes, no ibuf, no undo, no transaction log) in the transaction. "
-+ "This is to cause replication prefetch IO. ATTENTION: the transaction started after enabled is affected.",
-+ NULL, NULL, FALSE);
-+
-
- static handler *innobase_create_handler(handlerton *hton,
- TABLE_SHARE *table,
-@@ -1689,6 +1695,8 @@
- trx->check_unique_secondary = !thd_test_options(
- thd, OPTION_RELAXED_UNIQUE_CHECKS);
-
-+ trx->fake_changes = THDVAR(thd, fake_changes);
-+
- #ifdef EXTENDED_SLOWLOG
- if (thd_log_slow_verbosity(thd) & SLOG_V_INNODB) {
- trx->take_stats = TRUE;
-@@ -3195,6 +3203,11 @@
- trx_search_latch_release_if_reserved(trx);
- }
-
-+ if (trx->fake_changes && (all || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
-+ innobase_rollback(hton, thd, all); /* rollback implicitly */
-+ thd->stmt_da->reset_diagnostics_area(); /* because debug assertion code complains, if something left */
-+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-+ }
- /* Transaction is deregistered only in a commit or a rollback. If
- it is deregistered we know there cannot be resources to be freed
- and we could return immediately. For the time being, we play safe
-@@ -7543,6 +7556,12 @@
-
- trx = innobase_trx_allocate(thd);
-
-+ if (trx->fake_changes) {
-+ innobase_commit_low(trx);
-+ trx_free_for_mysql(trx);
-+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-+ }
-+
- /* Latch the InnoDB data dictionary exclusively so that no deadlocks
- or lock waits can happen in it during a table create operation.
- Drop table etc. do this latching in row0mysql.c. */
-@@ -7763,6 +7782,10 @@
- DBUG_RETURN(HA_ERR_CRASHED);
- }
-
-+ if (prebuilt->trx->fake_changes) {
-+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-+ }
-+
- /* Truncate the table in InnoDB */
-
- error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
-@@ -7819,6 +7842,12 @@
-
- trx = innobase_trx_allocate(thd);
-
-+ if (trx->fake_changes) {
-+ innobase_commit_low(trx);
-+ trx_free_for_mysql(trx);
-+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-+ }
-+
- name_len = strlen(name);
-
- ut_a(name_len < 1000);
-@@ -7905,6 +7934,12 @@
- trx->mysql_thd = NULL;
- #else
- trx = innobase_trx_allocate(thd);
-+ if (trx->fake_changes) {
-+ my_free(namebuf);
-+ innobase_commit_low(trx);
-+ trx_free_for_mysql(trx);
-+ return; /* ignore */
-+ }
- #endif
- row_drop_database_for_mysql(namebuf, trx);
- my_free(namebuf);
-@@ -8010,6 +8045,11 @@
- trx_search_latch_release_if_reserved(parent_trx);
-
- trx = innobase_trx_allocate(thd);
-+ if (trx->fake_changes) {
-+ innobase_commit_low(trx);
-+ trx_free_for_mysql(trx);
-+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-+ }
-
- error = innobase_rename_table(trx, from, to, TRUE);
-
-@@ -10880,6 +10920,10 @@
- return(0);
- }
-
-+ if (trx->fake_changes) {
-+ return(0);
-+ }
-+
- thd_get_xid(thd, (MYSQL_XID*) &trx->xid);
-
- /* Release a possible FIFO ticket and search latch. Since we will
-@@ -12480,6 +12524,7 @@
- #endif
- MYSQL_SYSVAR(corrupt_table_action),
- MYSQL_SYSVAR(lazy_drop_table),
-+ MYSQL_SYSVAR(fake_changes),
- NULL
- };
-
---- a/storage/innobase/handler/handler0alter.cc
-+++ b/storage/innobase/handler/handler0alter.cc
-@@ -695,6 +695,10 @@
- possible adaptive hash latch to avoid deadlocks of threads. */
- trx_search_latch_release_if_reserved(prebuilt->trx);
-
-+ if (prebuilt->trx->fake_changes) {
-+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-+ }
-+
- /* Check if the index name is reserved. */
- if (innobase_index_name_is_reserved(user_thd, key_info, num_of_keys)) {
- DBUG_RETURN(-1);
-@@ -732,6 +736,13 @@
- /* Create a background transaction for the operations on
- the data dictionary tables. */
- trx = innobase_trx_allocate(user_thd);
-+ if (trx->fake_changes) {
-+ mem_heap_free(heap);
-+ trx_general_rollback_for_mysql(trx, NULL);
-+ trx_free_for_mysql(trx);
-+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-+ }
-+
- trx_start_if_not_started(trx);
-
- /* Create table containing all indexes to be built in this
-@@ -1092,6 +1103,10 @@
- trx_search_latch_release_if_reserved(prebuilt->trx);
- trx = prebuilt->trx;
-
-+ if (trx->fake_changes) {
-+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-+ }
-+
- /* Test and mark all the indexes to be dropped */
-
- row_mysql_lock_data_dictionary(trx);
-@@ -1296,6 +1311,12 @@
- /* Create a background transaction for the operations on
- the data dictionary tables. */
- trx = innobase_trx_allocate(user_thd);
-+ if (trx->fake_changes) {
-+ trx_general_rollback_for_mysql(trx, NULL);
-+ trx_free_for_mysql(trx);
-+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-+ }
-+
- trx_start_if_not_started(trx);
-
- /* Flag this transaction as a dictionary operation, so that
---- a/storage/innobase/ibuf/ibuf0ibuf.c
-+++ b/storage/innobase/ibuf/ibuf0ibuf.c
-@@ -3424,6 +3424,8 @@
-
- ut_a(trx_sys_multiple_tablespace_format);
-
-+ ut_ad(!(thr_get_trx(thr)->fake_changes));
-+
- do_merge = FALSE;
-
- /* Perform dirty reads of ibuf->size and ibuf->max_size, to
---- a/storage/innobase/include/trx0trx.h
-+++ b/storage/innobase/include/trx0trx.h
-@@ -512,6 +512,7 @@
- FALSE, one can save CPU time and about
- 150 bytes in the undo log size as then
- we skip XA steps */
-+ ulint fake_changes;
- ulint flush_log_later;/* In 2PC, we hold the
- prepare_commit mutex across
- both phases. In that case, we
---- a/storage/innobase/lock/lock0lock.c
-+++ b/storage/innobase/lock/lock0lock.c
-@@ -3912,6 +3912,10 @@
-
- trx = thr_get_trx(thr);
-
-+ if (trx->fake_changes && mode == LOCK_IX) {
-+ mode = LOCK_IS;
-+ }
-+
- lock_mutex_enter_kernel();
-
- /* Look for stronger locks the same trx already has on the table */
-@@ -5114,6 +5118,11 @@
- }
-
- trx = thr_get_trx(thr);
-+
-+ if (trx->fake_changes) {
-+ return(DB_SUCCESS);
-+ }
-+
- next_rec = page_rec_get_next_const(rec);
- next_rec_heap_no = page_rec_get_heap_no(next_rec);
-
-@@ -5282,6 +5291,10 @@
- return(DB_SUCCESS);
- }
-
-+ if (thr && thr_get_trx(thr)->fake_changes) {
-+ return(DB_SUCCESS);
-+ }
-+
- heap_no = rec_offs_comp(offsets)
- ? rec_get_heap_no_new(rec)
- : rec_get_heap_no_old(rec);
-@@ -5340,6 +5353,10 @@
- return(DB_SUCCESS);
- }
-
-+ if (thr && thr_get_trx(thr)->fake_changes) {
-+ return(DB_SUCCESS);
-+ }
-+
- heap_no = page_rec_get_heap_no(rec);
-
- /* Another transaction cannot have an implicit lock on the record,
-@@ -5427,6 +5444,10 @@
- return(DB_SUCCESS);
- }
-
-+ if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) {
-+ mode = LOCK_S;
-+ }
-+
- heap_no = page_rec_get_heap_no(rec);
-
- lock_mutex_enter_kernel();
-@@ -5503,6 +5524,10 @@
- return(DB_SUCCESS);
- }
-
-+ if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) {
-+ mode = LOCK_S;
-+ }
-+
- heap_no = page_rec_get_heap_no(rec);
-
- lock_mutex_enter_kernel();
---- a/storage/innobase/que/que0que.c
-+++ b/storage/innobase/que/que0que.c
-@@ -1417,6 +1417,12 @@
-
- ut_a(trx->error_state == DB_SUCCESS);
-
-+ if (trx->fake_changes) {
-+ /* fake_changes should not access to system tables */
-+ fprintf(stderr, "InnoDB: ERROR: innodb_fake_changes tried to access to system tables.\n");
-+ return(DB_ERROR);
-+ }
-+
- if (reserve_dict_mutex) {
- mutex_enter(&dict_sys->mutex);
- }
---- a/storage/innobase/row/row0ins.c
-+++ b/storage/innobase/row/row0ins.c
-@@ -1505,6 +1505,11 @@
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
-+
-+ if (trx->fake_changes) {
-+ err = DB_SUCCESS;
-+ }
-+
- return(err);
- }
-
-@@ -2010,7 +2015,7 @@
- }
-
- btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
-- search_mode,
-+ thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : search_mode,
- &cursor, 0, __FILE__, __LINE__, &mtr);
-
- if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
-@@ -2070,7 +2075,7 @@
-
- btr_cur_search_to_nth_level(index, 0, entry,
- PAGE_CUR_LE,
-- mode | BTR_INSERT,
-+ thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : (mode | BTR_INSERT),
- &cursor, 0,
- __FILE__, __LINE__, &mtr);
- }
-@@ -2124,6 +2129,22 @@
- if (UNIV_LIKELY_NULL(big_rec)) {
- rec_t* rec;
- ulint* offsets;
-+
-+ if (thr_get_trx(thr)->fake_changes) {
-+ /* skip store extern */
-+ if (modify) {
-+ dtuple_big_rec_free(big_rec);
-+ } else {
-+ dtuple_convert_back_big_rec(index, entry, big_rec);
-+ }
-+
-+ if (UNIV_LIKELY_NULL(heap)) {
-+ mem_heap_free(heap);
-+ }
-+
-+ return(err);
-+ }
-+
- mtr_start(&mtr);
-
- btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
---- a/storage/innobase/row/row0mysql.c
-+++ b/storage/innobase/row/row0mysql.c
-@@ -1246,6 +1246,7 @@
- prebuilt->table->stat_n_rows--;
- }
-
-+ if (!(trx->fake_changes))
- row_update_statistics_if_needed(prebuilt->table);
- trx->op_info = "";
-
-@@ -1505,6 +1506,7 @@
- that changes indexed columns, UPDATEs that change only non-indexed
- columns would not affect statistics. */
- if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
-+ if (!(trx->fake_changes))
- row_update_statistics_if_needed(prebuilt->table);
- }
-
-@@ -1722,6 +1724,7 @@
- srv_n_rows_updated++;
- }
-
-+ if (!(trx->fake_changes))
- row_update_statistics_if_needed(table);
-
- return(err);
---- a/storage/innobase/row/row0upd.c
-+++ b/storage/innobase/row/row0upd.c
-@@ -1603,7 +1603,8 @@
- mode |= BTR_DELETE_MARK;
- }
-
-- search_result = row_search_index_entry(index, entry, mode,
-+ search_result = row_search_index_entry(index, entry,
-+ trx->fake_changes ? BTR_SEARCH_LEAF : mode,
- &pcur, &mtr);
-
- btr_cur = btr_pcur_get_btr_cur(&pcur);
-@@ -1850,9 +1851,11 @@
- the previous invocation of this function. Mark the
- off-page columns in the entry inherited. */
-
-+ if (!(trx->fake_changes)) {
- change_ownership = row_upd_clust_rec_by_insert_inherit(
- NULL, NULL, entry, node->update);
- ut_a(change_ownership);
-+ }
- /* fall through */
- case UPD_NODE_INSERT_CLUSTERED:
- /* A lock wait occurred in row_ins_index_entry() in
-@@ -1882,7 +1885,7 @@
- delete-marked old record, mark them disowned by the
- old record and owned by the new entry. */
-
-- if (rec_offs_any_extern(offsets)) {
-+ if (rec_offs_any_extern(offsets) && !(trx->fake_changes)) {
- change_ownership = row_upd_clust_rec_by_insert_inherit(
- rec, offsets, entry, node->update);
-
-@@ -2012,7 +2015,8 @@
- the same transaction do not modify the record in the meantime.
- Therefore we can assert that the restoration of the cursor succeeds. */
-
-- ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
-+ ut_a(btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_TREE,
-+ pcur, mtr));
-
- ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
- dict_table_is_comp(index->table)));
-@@ -2022,7 +2026,8 @@
- node->cmpl_info, thr, mtr);
- mtr_commit(mtr);
-
-- if (err == DB_SUCCESS && big_rec) {
-+ /* skip store extern for fake_changes */
-+ if (err == DB_SUCCESS && big_rec && !(thr_get_trx(thr)->fake_changes)) {
- ulint offsets_[REC_OFFS_NORMAL_SIZE];
- rec_t* rec;
- rec_offs_init(offsets_);
-@@ -2146,7 +2151,8 @@
-
- ut_a(pcur->rel_pos == BTR_PCUR_ON);
-
-- success = btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
-+ success = btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_LEAF,
-+ pcur, mtr);
-
- if (!success) {
- err = DB_RECORD_NOT_FOUND;
---- a/storage/innobase/trx/trx0trx.c
-+++ b/storage/innobase/trx/trx0trx.c
-@@ -121,6 +121,8 @@
-
- trx->support_xa = TRUE;
-
-+ trx->fake_changes = FALSE;
-+
- trx->check_foreigns = TRUE;
- trx->check_unique_secondary = TRUE;
-
---- /dev/null
-+++ b/mysql-test/r/percona_innodb_fake_changes.result
-@@ -0,0 +1,55 @@
-+DROP TABLE IF EXISTS t1;
-+# Checking variables
-+SHOW VARIABLES LIKE 'innodb_fake_changes';
-+Variable_name Value
-+innodb_fake_changes OFF
-+SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
-+VARIABLE_VALUE
-+OFF
-+SET innodb_fake_changes=1;
-+SHOW VARIABLES LIKE 'innodb_fake_changes';
-+Variable_name Value
-+innodb_fake_changes ON
-+SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
-+VARIABLE_VALUE
-+ON
-+SET innodb_fake_changes=default;
-+SHOW VARIABLES LIKE 'innodb_fake_changes';
-+Variable_name Value
-+innodb_fake_changes OFF
-+SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
-+VARIABLE_VALUE
-+OFF
-+# Explicit COMMIT should fail when innodb_fake_changes is enabled
-+# DML should be fine
-+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
-+INSERT INTO t1 VALUES (1);
-+SET autocommit=0;
-+SET innodb_fake_changes=1;
-+BEGIN;
-+INSERT INTO t1 VALUES (2);
-+UPDATE t1 SET a=0;
-+DELETE FROM t1 LIMIT 1;
-+SELECT * FROM t1;
-+a
-+1
-+COMMIT;
-+ERROR HY000: Got error 131 during COMMIT
-+SET innodb_fake_changes=default;
-+DROP TABLE t1;
-+# DDL must result in error
-+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
-+SET autocommit=0;
-+SET innodb_fake_changes=1;
-+BEGIN;
-+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
-+ERROR HY000: Can't create table 'test.t2' (errno: 131)
-+DROP TABLE t1;
-+ERROR 42S02: Unknown table 't1'
-+TRUNCATE TABLE t1;
-+ERROR HY000: Got error 131 during COMMIT
-+ALTER TABLE t1 ENGINE=MyISAM;
-+ERROR HY000: Got error 131 during COMMIT
-+ROLLBACK;
-+SET innodb_fake_changes=default;
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/r/percona_innodb_fake_changes_locks.result
-@@ -0,0 +1,19 @@
-+DROP TABLE IF EXISTS t1;
-+# Verifying that X_LOCK not acquired
-+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
-+INSERT INTO t1 VALUES (1);
-+SET autocommit=0;
-+SET innodb_fake_changes=1;
-+BEGIN;
-+SELECT * FROM t1 FOR UPDATE;
-+a
-+1
-+SET innodb_lock_wait_timeout=3;
-+UPDATE t1 SET a=2;
-+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
-+SELECT * FROM t1 LOCK IN SHARE MODE;
-+a
-+1
-+ROLLBACK;
-+SET innodb_fake_changes=default;
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/t/percona_innodb_fake_changes.test
-@@ -0,0 +1,49 @@
-+--source include/have_innodb.inc
-+
-+--disable_warnings
-+DROP TABLE IF EXISTS t1;
-+--enable_warnings
-+
-+
-+--echo # Checking variables
-+SHOW VARIABLES LIKE 'innodb_fake_changes';
-+SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
-+SET innodb_fake_changes=1;
-+SHOW VARIABLES LIKE 'innodb_fake_changes';
-+SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
-+SET innodb_fake_changes=default;
-+SHOW VARIABLES LIKE 'innodb_fake_changes';
-+SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
-+
-+--echo # Explicit COMMIT should fail when innodb_fake_changes is enabled
-+--echo # DML should be fine
-+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
-+INSERT INTO t1 VALUES (1);
-+SET autocommit=0;
-+SET innodb_fake_changes=1;
-+BEGIN;
-+INSERT INTO t1 VALUES (2);
-+UPDATE t1 SET a=0;
-+DELETE FROM t1 LIMIT 1;
-+SELECT * FROM t1;
-+--error 1180
-+COMMIT;
-+SET innodb_fake_changes=default;
-+DROP TABLE t1;
-+
-+--echo # DDL must result in error
-+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
-+SET autocommit=0;
-+SET innodb_fake_changes=1;
-+BEGIN;
-+--error 1005
-+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
-+--error 1051
-+DROP TABLE t1;
-+--error 1180
-+TRUNCATE TABLE t1;
-+--error 1180
-+ALTER TABLE t1 ENGINE=MyISAM;
-+ROLLBACK;
-+SET innodb_fake_changes=default;
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/t/percona_innodb_fake_changes_locks.test
-@@ -0,0 +1,24 @@
-+--source include/have_innodb.inc
-+
-+--disable_warnings
-+DROP TABLE IF EXISTS t1;
-+--enable_warnings
-+
-+--echo # Verifying that X_LOCK not acquired
-+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
-+INSERT INTO t1 VALUES (1);
-+--connect (conn1,localhost,root,,)
-+--connection conn1
-+SET autocommit=0;
-+SET innodb_fake_changes=1;
-+BEGIN;
-+SELECT * FROM t1 FOR UPDATE;
-+--connection default
-+SET innodb_lock_wait_timeout=3;
-+--error 1205
-+UPDATE t1 SET a=2;
-+SELECT * FROM t1 LOCK IN SHARE MODE;
-+--connection conn1
-+ROLLBACK;
-+SET innodb_fake_changes=default;
-+DROP TABLE t1;
+++ /dev/null
-# name : innodb_fast_checksum.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/buf/buf0buf.c
-+++ b/storage/innobase/buf/buf0buf.c
-@@ -512,6 +512,27 @@
- return(checksum);
- }
-
-+UNIV_INTERN
-+ulint
-+buf_calc_page_new_checksum_32(
-+/*==========================*/
-+ const byte* page) /*!< in: buffer page */
-+{
-+ ulint checksum;
-+
-+ checksum = ut_fold_binary(page + FIL_PAGE_OFFSET,
-+ FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
-+ + ut_fold_binary(page + FIL_PAGE_DATA,
-+ FIL_PAGE_DATA_ALIGN_32 - FIL_PAGE_DATA)
-+ + ut_fold_binary_32(page + FIL_PAGE_DATA_ALIGN_32,
-+ UNIV_PAGE_SIZE - FIL_PAGE_DATA_ALIGN_32
-+ - FIL_PAGE_END_LSN_OLD_CHKSUM);
-+
-+ checksum = checksum & 0xFFFFFFFFUL;
-+
-+ return(checksum);
-+}
-+
- /********************************************************************//**
- In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only
- looked at the first few bytes of the page. This calculates that old
-@@ -628,9 +649,21 @@
- /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
- (always equal to 0), to FIL_PAGE_SPACE_OR_CHKSUM */
-
-- if (checksum_field != 0
-+ if (!srv_fast_checksum
-+ && checksum_field != 0
-+ && checksum_field != BUF_NO_CHECKSUM_MAGIC
-+ && checksum_field
-+ != buf_calc_page_new_checksum(read_buf)) {
-+
-+ return(TRUE);
-+ }
-+
-+ if (srv_fast_checksum
-+ && checksum_field != 0
- && checksum_field != BUF_NO_CHECKSUM_MAGIC
- && checksum_field
-+ != buf_calc_page_new_checksum_32(read_buf)
-+ && checksum_field
- != buf_calc_page_new_checksum(read_buf)) {
-
- return(TRUE);
-@@ -654,6 +687,7 @@
- dict_index_t* index;
- #endif /* !UNIV_HOTBACKUP */
- ulint checksum;
-+ ulint checksum_32;
- ulint old_checksum;
- ulint size = zip_size;
-
-@@ -740,12 +774,14 @@
-
- checksum = srv_use_checksums
- ? buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
-+ checksum_32 = srv_use_checksums
-+ ? buf_calc_page_new_checksum_32(read_buf) : BUF_NO_CHECKSUM_MAGIC;
- old_checksum = srv_use_checksums
- ? buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
-
- ut_print_timestamp(stderr);
- fprintf(stderr,
-- " InnoDB: Page checksum %lu, prior-to-4.0.14-form"
-+ " InnoDB: Page checksum %lu (32bit_calc: %lu), prior-to-4.0.14-form"
- " checksum %lu\n"
- "InnoDB: stored checksum %lu, prior-to-4.0.14-form"
- " stored checksum %lu\n"
-@@ -754,7 +790,7 @@
- "InnoDB: Page number (if stored to page already) %lu,\n"
- "InnoDB: space id (if created with >= MySQL-4.1.1"
- " and stored already) %lu\n",
-- (ulong) checksum, (ulong) old_checksum,
-+ (ulong) checksum, (ulong) checksum_32, (ulong) old_checksum,
- (ulong) mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM),
- (ulong) mach_read_from_4(read_buf + UNIV_PAGE_SIZE
- - FIL_PAGE_END_LSN_OLD_CHKSUM),
---- a/storage/innobase/buf/buf0flu.c
-+++ b/storage/innobase/buf/buf0flu.c
-@@ -1057,7 +1057,9 @@
-
- mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
- srv_use_checksums
-- ? buf_calc_page_new_checksum(page)
-+ ? (!srv_fast_checksum
-+ ? buf_calc_page_new_checksum(page)
-+ : buf_calc_page_new_checksum_32(page))
- : BUF_NO_CHECKSUM_MAGIC);
-
- /* We overwrite the first 4 bytes of the end lsn field to store
---- a/storage/innobase/fil/fil0fil.c
-+++ b/storage/innobase/fil/fil0fil.c
-@@ -3103,13 +3103,24 @@
- return(TRUE);
- }
-
-- if (checksum_field != 0
-+ if (!srv_fast_checksum
-+ && checksum_field != 0
- && checksum_field != BUF_NO_CHECKSUM_MAGIC
- && checksum_field
- != buf_calc_page_new_checksum(page)) {
- return(TRUE);
- }
-
-+ if (srv_fast_checksum
-+ && checksum_field != 0
-+ && checksum_field != BUF_NO_CHECKSUM_MAGIC
-+ && checksum_field
-+ != buf_calc_page_new_checksum_32(page)
-+ && checksum_field
-+ != buf_calc_page_new_checksum(page)) {
-+ return(TRUE);
-+ }
-+
- return(FALSE);
- }
-
-@@ -3125,7 +3136,9 @@
- if (!zip_size) {
- mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
- srv_use_checksums
-- ? buf_calc_page_new_checksum(page)
-+ ? (!srv_fast_checksum
-+ ? buf_calc_page_new_checksum(page)
-+ : buf_calc_page_new_checksum_32(page))
- : BUF_NO_CHECKSUM_MAGIC);
- mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
- srv_use_checksums
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -183,6 +183,7 @@
- #endif /* UNIV_LOG_ARCHIVE */
- static my_bool innobase_use_doublewrite = TRUE;
- static my_bool innobase_use_checksums = TRUE;
-+static my_bool innobase_fast_checksum = FALSE;
- static my_bool innobase_recovery_stats = TRUE;
- static my_bool innobase_locks_unsafe_for_binlog = FALSE;
- static my_bool innobase_overwrite_relay_log_info = FALSE;
-@@ -2656,6 +2657,7 @@
-
- srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
- srv_use_checksums = (ibool) innobase_use_checksums;
-+ srv_fast_checksum = (ibool) innobase_fast_checksum;
-
- srv_blocking_lru_restore = (ibool) innobase_blocking_lru_restore;
-
-@@ -11541,6 +11543,15 @@
- "Disable with --skip-innodb-checksums.",
- NULL, NULL, TRUE);
-
-+static MYSQL_SYSVAR_BOOL(fast_checksum, innobase_fast_checksum,
-+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
-+ "Change the algorithm of checksum for the whole of datapage to 4-bytes word based. "
-+ "The original checksum is checked after the new one. It may be slow for reading page"
-+ " which has orginal checksum. Overwrite the page or recreate the InnoDB database, "
-+ "if you want the entire benefit for performance at once. "
-+ "#### Attention: The checksum is not compatible for normal or disabled version! ####",
-+ NULL, NULL, FALSE);
-+
- static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
- PLUGIN_VAR_READONLY,
- "The common part for InnoDB table spaces.",
-@@ -12112,6 +12123,7 @@
- MYSQL_SYSVAR(buffer_pool_size),
- MYSQL_SYSVAR(buffer_pool_instances),
- MYSQL_SYSVAR(checksums),
-+ MYSQL_SYSVAR(fast_checksum),
- MYSQL_SYSVAR(commit_concurrency),
- MYSQL_SYSVAR(concurrency_tickets),
- MYSQL_SYSVAR(data_file_path),
---- a/storage/innobase/include/buf0buf.h
-+++ b/storage/innobase/include/buf0buf.h
-@@ -621,6 +621,11 @@
- buf_calc_page_new_checksum(
- /*=======================*/
- const byte* page); /*!< in: buffer page */
-+UNIV_INTERN
-+ulint
-+buf_calc_page_new_checksum_32(
-+/*==========================*/
-+ const byte* page); /*!< in: buffer page */
- /********************************************************************//**
- In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only
- looked at the first few bytes of the page. This calculates that old
---- a/storage/innobase/include/fil0fil.h
-+++ b/storage/innobase/include/fil0fil.h
-@@ -119,6 +119,7 @@
- #define FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID 34 /*!< starting from 4.1.x this
- contains the space id of the page */
- #define FIL_PAGE_DATA 38 /*!< start of the data on the page */
-+#define FIL_PAGE_DATA_ALIGN_32 40
- /* @} */
- /** File page trailer @{ */
- #define FIL_PAGE_END_LSN_OLD_CHKSUM 8 /*!< the low 4 bytes of this are used
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -229,6 +229,7 @@
-
- extern ibool srv_use_doublewrite_buf;
- extern ibool srv_use_checksums;
-+extern ibool srv_fast_checksum;
-
- extern ulong srv_max_buf_pool_modified_pct;
- extern ulong srv_max_purge_lag;
---- a/storage/innobase/include/ut0rnd.h
-+++ b/storage/innobase/include/ut0rnd.h
-@@ -124,6 +124,13 @@
- const byte* str, /*!< in: string of bytes */
- ulint len) /*!< in: length */
- __attribute__((pure));
-+UNIV_INLINE
-+ulint
-+ut_fold_binary_32(
-+/*==============*/
-+ const byte* str, /*!< in: string of bytes */
-+ ulint len) /*!< in: length */
-+ __attribute__((pure));
- /***********************************************************//**
- Looks for a prime number slightly greater than the given argument.
- The prime is chosen so that it is not near any power of 2.
---- a/storage/innobase/include/ut0rnd.ic
-+++ b/storage/innobase/include/ut0rnd.ic
-@@ -226,3 +226,28 @@
-
- return(fold);
- }
-+
-+UNIV_INLINE
-+ulint
-+ut_fold_binary_32(
-+/*==============*/
-+ const byte* str, /*!< in: string of bytes */
-+ ulint len) /*!< in: length */
-+{
-+ const ib_uint32_t* str_end = (const ib_uint32_t*) (str + len);
-+ const ib_uint32_t* str_32 = (const ib_uint32_t*) str;
-+ ulint fold = 0;
-+
-+ ut_ad(str);
-+ /* This function is only for word-aligned data */
-+ ut_ad(len % 4 == 0);
-+ ut_ad((ulint)str % 4 == 0);
-+
-+ while (str_32 < str_end) {
-+ fold = ut_fold_ulint_pair(fold, (ulint)(*str_32));
-+
-+ str_32++;
-+ }
-+
-+ return(fold);
-+}
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -419,6 +419,7 @@
-
- UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE;
- UNIV_INTERN ibool srv_use_checksums = TRUE;
-+UNIV_INTERN ibool srv_fast_checksum = FALSE;
-
- UNIV_INTERN ulong srv_replication_delay = 0;
-
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/r/innodb_fast_checksum_basic.result
-@@ -0,0 +1,3 @@
-+SELECT @@global.innodb_fast_checksum;
-+@@global.innodb_fast_checksum
-+0
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/t/innodb_fast_checksum_basic.test
-@@ -0,0 +1 @@
-+SELECT @@global.innodb_fast_checksum;
+++ /dev/null
-# name : innodb_files_extend.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/fil/fil0fil.c
-+++ b/storage/innobase/fil/fil0fil.c
-@@ -731,7 +731,7 @@
- ut_a(space->purpose != FIL_LOG);
- ut_a(!trx_sys_sys_space(space->id));
-
-- if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
-+ if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) {
- fprintf(stderr,
- "InnoDB: Error: the size of single-table"
- " tablespace file %s\n"
-@@ -4169,7 +4169,7 @@
-
- size = (((ib_int64_t)size_high) << 32) + (ib_int64_t)size_low;
- #ifndef UNIV_HOTBACKUP
-- if (size < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
-+ if (size < FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) {
- fprintf(stderr,
- "InnoDB: Error: the size of single-table tablespace"
- " file %s\n"
-@@ -4189,7 +4189,7 @@
- /* Align the memory for file i/o if we might have O_DIRECT set */
- page = ut_align(buf2, UNIV_PAGE_SIZE);
-
-- if (size >= FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
-+ if (size >= FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) {
- success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE);
-
- /* We have to read the tablespace id from the file */
-@@ -5167,9 +5167,9 @@
- ut_ad(ut_is_2pow(zip_size));
- ut_ad(buf);
- ut_ad(len > 0);
--#if (1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE
--# error "(1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE"
--#endif
-+//#if (1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE
-+//# error "(1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE"
-+//#endif
- ut_ad(fil_validate_skip());
- #ifndef UNIV_HOTBACKUP
- # ifndef UNIV_LOG_DEBUG
---- a/storage/innobase/fsp/fsp0fsp.c
-+++ b/storage/innobase/fsp/fsp0fsp.c
-@@ -595,16 +595,18 @@
- 0 for uncompressed pages */
- ulint offset) /*!< in: page offset */
- {
--#ifndef DOXYGEN /* Doxygen gets confused of these */
--# if UNIV_PAGE_SIZE <= XDES_ARR_OFFSET \
-- + (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE
--# error
--# endif
--# if PAGE_ZIP_MIN_SIZE <= XDES_ARR_OFFSET \
-- + (PAGE_ZIP_MIN_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE
--# error
--# endif
--#endif /* !DOXYGEN */
-+//#ifndef DOXYGEN /* Doxygen gets confused of these */
-+//# if UNIV_PAGE_SIZE <= XDES_ARR_OFFSET
-+// + (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE
-+//# error
-+//# endif
-+//# if PAGE_ZIP_MIN_SIZE <= XDES_ARR_OFFSET
-+// + (PAGE_ZIP_MIN_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE
-+//# error
-+//# endif
-+//#endif /* !DOXYGEN */
-+ ut_a(UNIV_PAGE_SIZE > XDES_ARR_OFFSET + (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE);
-+ ut_a(PAGE_ZIP_MIN_SIZE > XDES_ARR_OFFSET + (PAGE_ZIP_MIN_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE);
- ut_ad(ut_is_2pow(zip_size));
-
- if (!zip_size) {
-@@ -1403,12 +1405,12 @@
- mtr);
- xdes_init(descr, mtr);
-
--#if UNIV_PAGE_SIZE % FSP_EXTENT_SIZE
--# error "UNIV_PAGE_SIZE % FSP_EXTENT_SIZE != 0"
--#endif
--#if PAGE_ZIP_MIN_SIZE % FSP_EXTENT_SIZE
--# error "PAGE_ZIP_MIN_SIZE % FSP_EXTENT_SIZE != 0"
--#endif
-+//#if UNIV_PAGE_SIZE % FSP_EXTENT_SIZE
-+//# error "UNIV_PAGE_SIZE % FSP_EXTENT_SIZE != 0"
-+//#endif
-+//#if PAGE_ZIP_MIN_SIZE % FSP_EXTENT_SIZE
-+//# error "PAGE_ZIP_MIN_SIZE % FSP_EXTENT_SIZE != 0"
-+//#endif
-
- if (UNIV_UNLIKELY(init_xdes)) {
-
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -148,6 +148,9 @@
- static ulong innobase_write_io_threads;
- static long innobase_buffer_pool_instances = 1;
-
-+static ulong innobase_page_size;
-+static ulong innobase_log_block_size;
-+
- static my_bool innobase_thread_concurrency_timer_based;
- static long long innobase_buffer_pool_size, innobase_log_file_size;
-
-@@ -2352,6 +2355,65 @@
- }
- #endif /* DBUG_OFF */
-
-+ srv_page_size = 0;
-+ srv_page_size_shift = 0;
-+
-+ if (innobase_page_size != (1 << 14)) {
-+ uint n_shift;
-+
-+ fprintf(stderr,
-+ "InnoDB: Warning: innodb_page_size has been changed from default value 16384. (###EXPERIMENTAL### operation)\n");
-+ for (n_shift = 12; n_shift <= UNIV_PAGE_SIZE_SHIFT_MAX; n_shift++) {
-+ if (innobase_page_size == ((ulong)1 << n_shift)) {
-+ srv_page_size_shift = n_shift;
-+ srv_page_size = (1 << srv_page_size_shift);
-+ fprintf(stderr,
-+ "InnoDB: The universal page size of the database is set to %lu.\n",
-+ srv_page_size);
-+ break;
-+ }
-+ }
-+ } else {
-+ srv_page_size_shift = 14;
-+ srv_page_size = (1 << srv_page_size_shift);
-+ }
-+
-+ if (!srv_page_size_shift) {
-+ fprintf(stderr,
-+ "InnoDB: Error: %lu is not a valid value for innodb_page_size.\n"
-+ "InnoDB: Error: Valid values are 4096, 8192, and 16384 (default=16384).\n",
-+ innobase_page_size);
-+ goto error;
-+ }
-+
-+ srv_log_block_size = 0;
-+ if (innobase_log_block_size != (1 << 9)) { /*!=512*/
-+ uint n_shift;
-+
-+ fprintf(stderr,
-+ "InnoDB: Warning: innodb_log_block_size has been changed from default value 512. (###EXPERIMENTAL### operation)\n");
-+ for (n_shift = 9; n_shift <= UNIV_PAGE_SIZE_SHIFT_MAX; n_shift++) {
-+ if (innobase_log_block_size == ((ulong)1 << n_shift)) {
-+ srv_log_block_size = (1 << n_shift);
-+ fprintf(stderr,
-+ "InnoDB: The log block size is set to %lu.\n",
-+ srv_log_block_size);
-+ break;
-+ }
-+ }
-+ } else {
-+ srv_log_block_size = 512;
-+ }
-+
-+ if (!srv_log_block_size) {
-+ fprintf(stderr,
-+ "InnoDB: Error: %lu is not a valid value for innodb_log_block_size.\n"
-+ "InnoDB: Error: A valid value for innodb_log_block_size is\n"
-+ "InnoDB: Error: a power of 2 from 512 to 16384.\n",
-+ innobase_log_block_size);
-+ goto error;
-+ }
-+
- #ifndef MYSQL_SERVER
- innodb_overwrite_relay_log_info = FALSE;
- #endif
-@@ -7289,9 +7351,9 @@
- | DICT_TF_COMPACT
- | DICT_TF_FORMAT_ZIP
- << DICT_TF_FORMAT_SHIFT;
--#if DICT_TF_ZSSIZE_MAX < 1
--# error "DICT_TF_ZSSIZE_MAX < 1"
--#endif
-+//#if DICT_TF_ZSSIZE_MAX < 1
-+//# error "DICT_TF_ZSSIZE_MAX < 1"
-+//#endif
- }
- }
-
-@@ -11552,6 +11614,16 @@
- "#### Attention: The checksum is not compatible for normal or disabled version! ####",
- NULL, NULL, FALSE);
-
-+static MYSQL_SYSVAR_ULONG(page_size, innobase_page_size,
-+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
-+ "###EXPERIMENTAL###: The universal page size of the database. Changing for created database is not supported. Use on your own risk!",
-+ NULL, NULL, (1 << 14), (1 << 12), (1 << UNIV_PAGE_SIZE_SHIFT_MAX), 0);
-+
-+static MYSQL_SYSVAR_ULONG(log_block_size, innobase_log_block_size,
-+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
-+ "###EXPERIMENTAL###: The log block size of the transaction log file. Changing for created log file is not supported. Use on your own risk!",
-+ NULL, NULL, (1 << 9)/*512*/, (1 << 9)/*512*/, (1 << UNIV_PAGE_SIZE_SHIFT_MAX), 0);
-+
- static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
- PLUGIN_VAR_READONLY,
- "The common part for InnoDB table spaces.",
-@@ -12118,6 +12190,8 @@
- NULL, NULL, 0, &corrupt_table_action_typelib);
-
- static struct st_mysql_sys_var* innobase_system_variables[]= {
-+ MYSQL_SYSVAR(page_size),
-+ MYSQL_SYSVAR(log_block_size),
- MYSQL_SYSVAR(additional_mem_pool_size),
- MYSQL_SYSVAR(autoextend_increment),
- MYSQL_SYSVAR(buffer_pool_size),
---- a/storage/innobase/include/buf0buf.h
-+++ b/storage/innobase/include/buf0buf.h
-@@ -1725,7 +1725,7 @@
- time_t last_printout_time;
- /*!< when buf_print_io was last time
- called */
-- buf_buddy_stat_t buddy_stat[BUF_BUDDY_SIZES + 1];
-+ buf_buddy_stat_t buddy_stat[BUF_BUDDY_SIZES_MAX + 1];
- /*!< Statistics of buddy system,
- indexed by block size */
- buf_pool_stat_t stat; /*!< current statistics */
-@@ -1823,7 +1823,7 @@
- UT_LIST_BASE_NODE_T(buf_page_t) zip_clean;
- /*!< unmodified compressed pages */
- #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
-- UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES];
-+ UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES_MAX];
- /*!< buddy free lists */
-
- buf_page_t watch[BUF_POOL_WATCH_SIZE];
-@@ -1831,9 +1831,9 @@
- pool watches. Protected by
- buf_pool->mutex. */
-
--#if BUF_BUDDY_HIGH != UNIV_PAGE_SIZE
--# error "BUF_BUDDY_HIGH != UNIV_PAGE_SIZE"
--#endif
-+//#if BUF_BUDDY_HIGH != UNIV_PAGE_SIZE
-+//# error "BUF_BUDDY_HIGH != UNIV_PAGE_SIZE"
-+//#endif
- #if BUF_BUDDY_LOW > PAGE_ZIP_MIN_SIZE
- # error "BUF_BUDDY_LOW > PAGE_ZIP_MIN_SIZE"
- #endif
---- a/storage/innobase/include/buf0types.h
-+++ b/storage/innobase/include/buf0types.h
-@@ -70,12 +70,13 @@
- #define BUF_BUDDY_LOW (1 << BUF_BUDDY_LOW_SHIFT)
-
- #define BUF_BUDDY_SIZES (UNIV_PAGE_SIZE_SHIFT - BUF_BUDDY_LOW_SHIFT)
-+#define BUF_BUDDY_SIZES_MAX (UNIV_PAGE_SIZE_SHIFT_MAX - BUF_BUDDY_LOW_SHIFT)
- /*!< number of buddy sizes */
-
- /** twice the maximum block size of the buddy system;
- the underlying memory is aligned by this amount:
- this must be equal to UNIV_PAGE_SIZE */
--#define BUF_BUDDY_HIGH (BUF_BUDDY_LOW << BUF_BUDDY_SIZES)
-+#define BUF_BUDDY_HIGH ((ulint)BUF_BUDDY_LOW << BUF_BUDDY_SIZES)
- /* @} */
-
- #endif
---- a/storage/innobase/include/fsp0types.h
-+++ b/storage/innobase/include/fsp0types.h
-@@ -42,7 +42,7 @@
- /* @} */
-
- /** File space extent size (one megabyte) in pages */
--#define FSP_EXTENT_SIZE (1 << (20 - UNIV_PAGE_SIZE_SHIFT))
-+#define FSP_EXTENT_SIZE ((ulint)1 << (20 - UNIV_PAGE_SIZE_SHIFT))
-
- /** On a page of any file segment, data may be put starting from this
- offset */
---- a/storage/innobase/include/log0log.h
-+++ b/storage/innobase/include/log0log.h
-@@ -672,6 +672,9 @@
- when mysqld is first time started
- on the restored database, it can
- print helpful info for the user */
-+#define LOG_FILE_OS_FILE_LOG_BLOCK_SIZE 64
-+ /* extend to record log_block_size
-+ of XtraDB. 0 means default 512 */
- #define LOG_FILE_ARCH_COMPLETED OS_FILE_LOG_BLOCK_SIZE
- /* this 4-byte field is TRUE when
- the writing of an archived log file
---- a/storage/innobase/include/mtr0log.ic
-+++ b/storage/innobase/include/mtr0log.ic
-@@ -203,7 +203,7 @@
- system tablespace */
- if ((space == TRX_SYS_SPACE
- || (srv_doublewrite_file && space == TRX_DOUBLEWRITE_SPACE))
-- && offset >= FSP_EXTENT_SIZE && offset < 3 * FSP_EXTENT_SIZE) {
-+ && offset >= (ulint)FSP_EXTENT_SIZE && offset < 3 * (ulint)FSP_EXTENT_SIZE) {
- if (trx_doublewrite_buf_is_being_created) {
- /* Do nothing: we only come to this branch in an
- InnoDB database creation. We do not redo log
---- a/storage/innobase/include/os0file.h
-+++ b/storage/innobase/include/os0file.h
-@@ -101,7 +101,7 @@
- if this fails for a log block, then it is equivalent to a media failure in the
- log. */
-
--#define OS_FILE_LOG_BLOCK_SIZE 512
-+#define OS_FILE_LOG_BLOCK_SIZE srv_log_block_size
-
- /** Options for file_create @{ */
- #define OS_FILE_OPEN 51
-@@ -190,6 +190,8 @@
- extern ulint os_n_file_writes;
- extern ulint os_n_fsyncs;
-
-+extern ulint srv_log_block_size;
-+
- #ifdef UNIV_PFS_IO
- /* Keys to register InnoDB I/O with performance schema */
- extern mysql_pfs_key_t innodb_file_data_key;
---- a/storage/innobase/include/page0types.h
-+++ b/storage/innobase/include/page0types.h
-@@ -56,8 +56,9 @@
-
- /** Number of supported compressed page sizes */
- #define PAGE_ZIP_NUM_SSIZE (UNIV_PAGE_SIZE_SHIFT - PAGE_ZIP_MIN_SIZE_SHIFT + 2)
--#if PAGE_ZIP_NUM_SSIZE > (1 << PAGE_ZIP_SSIZE_BITS)
--# error "PAGE_ZIP_NUM_SSIZE > (1 << PAGE_ZIP_SSIZE_BITS)"
-+#define PAGE_ZIP_NUM_SSIZE_MAX (UNIV_PAGE_SIZE_SHIFT_MAX - PAGE_ZIP_MIN_SIZE_SHIFT + 2)
-+#if PAGE_ZIP_NUM_SSIZE_MAX > (1 << PAGE_ZIP_SSIZE_BITS)
-+# error "PAGE_ZIP_NUM_SSIZE_MAX > (1 << PAGE_ZIP_SSIZE_BITS)"
- #endif
-
- /** Compressed page descriptor */
-@@ -98,7 +99,7 @@
- typedef struct page_zip_stat_struct page_zip_stat_t;
-
- /** Statistics on compression, indexed by page_zip_des_struct::ssize - 1 */
--extern page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE - 1];
-+extern page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE_MAX - 1];
-
- /**********************************************************************//**
- Write the "deleted" flag of a record on a compressed page. The flag must
---- a/storage/innobase/include/trx0sys.h
-+++ b/storage/innobase/include/trx0sys.h
-@@ -526,9 +526,9 @@
- /** Contents of TRX_SYS_MYSQL_LOG_MAGIC_N_FLD */
- #define TRX_SYS_MYSQL_LOG_MAGIC_N 873422344
-
--#if UNIV_PAGE_SIZE < 4096
--# error "UNIV_PAGE_SIZE < 4096"
--#endif
-+//#if UNIV_PAGE_SIZE < 4096
-+//# error "UNIV_PAGE_SIZE < 4096"
-+//#endif
- /** The offset of the MySQL replication info in the trx system header;
- this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
- #define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
---- a/storage/innobase/include/univ.i
-+++ b/storage/innobase/include/univ.i
-@@ -313,9 +313,13 @@
- */
-
- /* The 2-logarithm of UNIV_PAGE_SIZE: */
--#define UNIV_PAGE_SIZE_SHIFT 14
-+/* #define UNIV_PAGE_SIZE_SHIFT 14 */
-+#define UNIV_PAGE_SIZE_SHIFT_MAX 14
-+#define UNIV_PAGE_SIZE_SHIFT srv_page_size_shift
- /* The universal page size of the database */
--#define UNIV_PAGE_SIZE (1 << UNIV_PAGE_SIZE_SHIFT)
-+/* #define UNIV_PAGE_SIZE (1 << UNIV_PAGE_SIZE_SHIFT) */
-+#define UNIV_PAGE_SIZE srv_page_size
-+#define UNIV_PAGE_SIZE_MAX (1 << UNIV_PAGE_SIZE_SHIFT_MAX)
-
- /* Maximum number of parallel threads in a parallelized operation */
- #define UNIV_MAX_PARALLELISM 32
-@@ -434,7 +438,7 @@
- stored part of the field in the tablespace. The length field then
- contains the sum of the following flag and the locally stored len. */
-
--#define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE)
-+#define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE_MAX)
-
- /* Some macros to improve branch prediction and reduce cache misses */
- #if defined(__GNUC__) && (__GNUC__ > 2) && ! defined(__INTEL_COMPILER)
-@@ -537,4 +541,6 @@
- UNIV_MEM_ALLOC(addr, size); \
- } while (0)
-
-+extern ulint srv_page_size_shift;
-+extern ulint srv_page_size;
- #endif
---- a/storage/innobase/log/log0log.c
-+++ b/storage/innobase/log/log0log.c
-@@ -604,7 +604,9 @@
-
- offset = (gr_lsn_size_offset + difference) % group_size;
-
-+ if (sizeof(ulint) == 4) {
- ut_a(offset < (((ib_int64_t) 1) << 32)); /* offset must be < 4 GB */
-+ }
-
- /* fprintf(stderr,
- "Offset is %lu gr_lsn_offset is %lu difference is %lu\n",
-@@ -1201,6 +1203,9 @@
- /* Wipe over possible label of ibbackup --restore */
- memcpy(buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, " ", 4);
-
-+ mach_write_to_4(buf + LOG_FILE_OS_FILE_LOG_BLOCK_SIZE,
-+ srv_log_block_size);
-+
- dest_offset = nth_file * group->file_size;
-
- #ifdef UNIV_DEBUG
-@@ -1797,9 +1802,7 @@
- ulint i;
-
- ut_ad(mutex_own(&(log_sys->mutex)));
--#if LOG_CHECKPOINT_SIZE > OS_FILE_LOG_BLOCK_SIZE
--# error "LOG_CHECKPOINT_SIZE > OS_FILE_LOG_BLOCK_SIZE"
--#endif
-+ ut_a(LOG_CHECKPOINT_SIZE <= OS_FILE_LOG_BLOCK_SIZE);
-
- buf = group->checkpoint_buf;
-
-@@ -1813,6 +1816,7 @@
- mach_write_to_4(buf + LOG_CHECKPOINT_LOG_BUF_SIZE, log_sys->buf_size);
-
- #ifdef UNIV_LOG_ARCHIVE
-+#error "UNIV_LOG_ARCHIVE could not be enabled"
- if (log_sys->archiving_state == LOG_ARCH_OFF) {
- archived_lsn = IB_ULONGLONG_MAX;
- } else {
-@@ -1826,7 +1830,9 @@
-
- mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, archived_lsn);
- #else /* UNIV_LOG_ARCHIVE */
-- mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, IB_ULONGLONG_MAX);
-+ mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN,
-+ (ib_uint64_t)log_group_calc_lsn_offset(
-+ log_sys->next_checkpoint_lsn, group));
- #endif /* UNIV_LOG_ARCHIVE */
-
- for (i = 0; i < LOG_MAX_N_GROUPS; i++) {
---- a/storage/innobase/log/log0recv.c
-+++ b/storage/innobase/log/log0recv.c
-@@ -712,8 +712,22 @@
-
- group->lsn = mach_read_from_8(
- buf + LOG_CHECKPOINT_LSN);
-+
-+#ifdef UNIV_LOG_ARCHIVE
-+#error "UNIV_LOG_ARCHIVE could not be enabled"
-+#endif
-+ {
-+ ib_uint64_t tmp_lsn_offset = mach_read_from_8(
-+ buf + LOG_CHECKPOINT_ARCHIVED_LSN);
-+ if (sizeof(ulint) != 4
-+ && tmp_lsn_offset != IB_ULONGLONG_MAX) {
-+ group->lsn_offset = (ulint) tmp_lsn_offset;
-+ } else {
- group->lsn_offset = mach_read_from_4(
- buf + LOG_CHECKPOINT_OFFSET);
-+ }
-+ }
-+
- checkpoint_no = mach_read_from_8(
- buf + LOG_CHECKPOINT_NO);
-
-@@ -2955,6 +2969,7 @@
- log_group_t* max_cp_group;
- log_group_t* up_to_date_group;
- ulint max_cp_field;
-+ ulint log_hdr_log_block_size;
- ib_uint64_t checkpoint_lsn;
- ib_uint64_t checkpoint_no;
- ib_uint64_t old_scanned_lsn;
-@@ -3056,6 +3071,21 @@
- log_hdr_buf, max_cp_group);
- }
-
-+ log_hdr_log_block_size
-+ = mach_read_from_4(log_hdr_buf + LOG_FILE_OS_FILE_LOG_BLOCK_SIZE);
-+ if (log_hdr_log_block_size == 0) {
-+ /* 0 means default value */
-+ log_hdr_log_block_size = 512;
-+ }
-+ if (log_hdr_log_block_size != srv_log_block_size) {
-+ fprintf(stderr,
-+ "InnoDB: Error: The block size of ib_logfile (%lu) "
-+ "is not equal to innodb_log_block_size.\n"
-+ "InnoDB: Error: Suggestion - Recreate log files.\n",
-+ log_hdr_log_block_size);
-+ return(DB_ERROR);
-+ }
-+
- #ifdef UNIV_LOG_ARCHIVE
- group = UT_LIST_GET_FIRST(log_sys->log_groups);
-
---- a/storage/innobase/page/page0zip.c
-+++ b/storage/innobase/page/page0zip.c
-@@ -49,7 +49,7 @@
-
- #ifndef UNIV_HOTBACKUP
- /** Statistics on compression, indexed by page_zip_des_t::ssize - 1 */
--UNIV_INTERN page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE - 1];
-+UNIV_INTERN page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE_MAX - 1];
- #endif /* !UNIV_HOTBACKUP */
-
- /* Please refer to ../include/page0zip.ic for a description of the
---- a/storage/innobase/row/row0merge.c
-+++ b/storage/innobase/row/row0merge.c
-@@ -97,7 +97,7 @@
- row_merge_block_t. Thus, it must be able to hold one merge record,
- whose maximum size is the same as the minimum size of
- row_merge_block_t. */
--typedef byte mrec_buf_t[UNIV_PAGE_SIZE];
-+typedef byte mrec_buf_t[UNIV_PAGE_SIZE_MAX];
-
- /** @brief Merge record in row_merge_block_t.
-
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -236,6 +236,14 @@
-
- /* Switch to enable random read ahead. */
- UNIV_INTERN my_bool srv_random_read_ahead = FALSE;
-+
-+/* The universal page size of the database */
-+UNIV_INTERN ulint srv_page_size_shift = 0;
-+UNIV_INTERN ulint srv_page_size = 0;
-+
-+/* The log block size */
-+UNIV_INTERN ulint srv_log_block_size = 0;
-+
- /* User settable value of the number of pages that must be present
- in the buffer cache and accessed sequentially for InnoDB to trigger a
- readahead request. */
---- a/storage/innobase/srv/srv0start.c
-+++ b/storage/innobase/srv/srv0start.c
-@@ -1582,11 +1582,13 @@
- }
- #endif /* UNIV_LOG_ARCHIVE */
-
-- if (srv_n_log_files * srv_log_file_size >= 262144) {
-+ if (sizeof(ulint) == 4
-+ && srv_n_log_files * srv_log_file_size
-+ >= ((ulint)1 << (32 - UNIV_PAGE_SIZE_SHIFT))) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: combined size of log files"
-- " must be < 4 GB\n");
-+ " must be < 4 GB on 32-bit systems\n");
-
- return(DB_ERROR);
- }
-@@ -1595,7 +1597,7 @@
-
- for (i = 0; i < srv_n_data_files; i++) {
- #ifndef __WIN__
-- if (sizeof(off_t) < 5 && srv_data_file_sizes[i] >= 262144) {
-+ if (sizeof(off_t) < 5 && srv_data_file_sizes[i] >= ((ulint)1 << (32 - UNIV_PAGE_SIZE_SHIFT))) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: file size must be < 4 GB"
+++ /dev/null
-# name : innodb_fix_misc.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-# Bug fix for
-# http://bugs.mysql.com/56433 (always: because good for all users, and safe)
-# and http://bugs.mysql.com/51325 (optional: innodb_lazy_drop_table)
-# were added. They may be removed in the future when will be fixed officially.
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/buf/buf0buf.c
-+++ b/storage/innobase/buf/buf0buf.c
-@@ -1981,6 +1981,27 @@
- #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
- }
-
-+ if (UNIV_UNLIKELY(bpage->space_was_being_deleted)) {
-+ /* This page is obsoleted, should discard and retry */
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
-+
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ block_mutex = buf_page_get_mutex_enter(bpage);
-+
-+ if (UNIV_UNLIKELY(!block_mutex)) {
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ goto lookup;
-+ }
-+
-+ buf_LRU_free_block(bpage, TRUE, TRUE);
-+
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ mutex_exit(block_mutex);
-+ block_mutex = NULL;
-+
-+ goto lookup;
-+ }
-+
- if (UNIV_UNLIKELY(!bpage->zip.data)) {
- /* There is no compressed page. */
- err_exit:
-@@ -2489,6 +2510,27 @@
- block = (buf_block_t*) buf_page_hash_get_low(
- buf_pool, space, offset, fold);
- if (block) {
-+ if (UNIV_UNLIKELY(block->page.space_was_being_deleted)) {
-+ /* This page is obsoleted, should discard and retry */
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
-+
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
-+
-+ if (UNIV_UNLIKELY(!block_mutex)) {
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ goto loop;
-+ }
-+
-+ buf_LRU_free_block((buf_page_t*)block, TRUE, TRUE);
-+
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ mutex_exit(block_mutex);
-+ block_mutex = NULL;
-+
-+ goto loop;
-+ }
-+
- block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
- ut_a(block_mutex);
- }
-@@ -3411,11 +3453,28 @@
-
- fold = buf_page_address_fold(space, offset);
-
-+retry:
- //buf_pool_mutex_enter(buf_pool);
- mutex_enter(&buf_pool->LRU_list_mutex);
- rw_lock_x_lock(&buf_pool->page_hash_latch);
-
- watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
-+
-+ if (UNIV_UNLIKELY(watch_page && watch_page->space_was_being_deleted)) {
-+ mutex_t* block_mutex = buf_page_get_mutex_enter(watch_page);
-+
-+ /* This page is obsoleted, should discard and retry */
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ ut_a(block_mutex);
-+
-+ buf_LRU_free_block(watch_page, TRUE, TRUE);
-+
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ mutex_exit(block_mutex);
-+
-+ goto retry;
-+ }
-+
- if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) {
- /* The page is already in the buffer pool. */
- watch_page = NULL;
-@@ -3546,6 +3605,7 @@
- bpage->state = BUF_BLOCK_ZIP_PAGE;
- bpage->space = space;
- bpage->offset = offset;
-+ bpage->space_was_being_deleted = FALSE;
-
- #ifdef UNIV_DEBUG
- bpage->in_page_hash = FALSE;
-@@ -3630,6 +3690,7 @@
-
- fold = buf_page_address_fold(space, offset);
-
-+retry:
- //buf_pool_mutex_enter(buf_pool);
- mutex_enter(&buf_pool->LRU_list_mutex);
- rw_lock_x_lock(&buf_pool->page_hash_latch);
-@@ -3637,6 +3698,21 @@
- block = (buf_block_t*) buf_page_hash_get_low(
- buf_pool, space, offset, fold);
-
-+ if (UNIV_UNLIKELY(block && block->page.space_was_being_deleted)) {
-+ mutex_t* block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
-+
-+ /* This page is obsoleted, should discard and retry */
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ ut_a(block_mutex);
-+
-+ buf_LRU_free_block((buf_page_t*)block, TRUE, TRUE);
-+
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ mutex_exit(block_mutex);
-+
-+ goto retry;
-+ }
-+
- if (block
- && buf_page_in_file(&block->page)
- && !buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
-@@ -3990,8 +4066,11 @@
- }
-
- if (io_type == BUF_IO_WRITE
-- && (buf_page_get_state(bpage) == BUF_BLOCK_ZIP_DIRTY
-- || buf_page_get_flush_type(bpage) == BUF_FLUSH_LRU)) {
-+ && (
-+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
-+ buf_page_get_state(bpage) == BUF_BLOCK_ZIP_DIRTY ||
-+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
-+ buf_page_get_flush_type(bpage) == BUF_FLUSH_LRU)) {
- /* to keep consistency at buf_LRU_insert_zip_clean() */
- have_LRU_mutex = TRUE; /* optimistic */
- }
---- a/storage/innobase/buf/buf0flu.c
-+++ b/storage/innobase/buf/buf0flu.c
-@@ -439,7 +439,7 @@
-
- if (UNIV_LIKELY(bpage->in_LRU_list && buf_page_in_file(bpage))) {
-
-- return(bpage->oldest_modification == 0
-+ return((bpage->oldest_modification == 0 || bpage->space_was_being_deleted)
- && buf_page_get_io_fix(bpage) == BUF_IO_NONE
- && bpage->buf_fix_count == 0);
- }
-@@ -481,6 +481,13 @@
- && buf_page_get_io_fix(bpage) == BUF_IO_NONE) {
- ut_ad(bpage->in_flush_list);
-
-+ if (bpage->space_was_being_deleted) {
-+ /* should be removed from flush_list here */
-+ /* because buf_flush_try_neighbors() cannot flush without fil_space_get_size(space) */
-+ buf_flush_remove(bpage);
-+ return(FALSE);
-+ }
-+
- if (flush_type != BUF_FLUSH_LRU) {
-
- return(TRUE);
---- a/storage/innobase/buf/buf0lru.c
-+++ b/storage/innobase/buf/buf0lru.c
-@@ -545,6 +545,62 @@
- }
- }
-
-+/******************************************************************//**
-+*/
-+UNIV_INTERN
-+void
-+buf_LRU_mark_space_was_deleted(
-+/*===========================*/
-+ ulint id) /*!< in: space id */
-+{
-+ ulint i;
-+
-+ for (i = 0; i < srv_buf_pool_instances; i++) {
-+ buf_pool_t* buf_pool;
-+ buf_page_t* bpage;
-+ buf_chunk_t* chunk;
-+ ulint j, k;
-+
-+ buf_pool = buf_pool_from_array(i);
-+
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+
-+ bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
-+
-+ while (bpage != NULL) {
-+ if (buf_page_get_space(bpage) == id) {
-+ bpage->space_was_being_deleted = TRUE;
-+ }
-+ bpage = UT_LIST_GET_NEXT(LRU, bpage);
-+ }
-+
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+
-+ rw_lock_s_lock(&btr_search_latch);
-+ chunk = buf_pool->chunks;
-+ for (j = buf_pool->n_chunks; j--; chunk++) {
-+ buf_block_t* block = chunk->blocks;
-+ for (k = chunk->size; k--; block++) {
-+ if (buf_block_get_state(block)
-+ != BUF_BLOCK_FILE_PAGE
-+ || !block->index
-+ || buf_page_get_space(&block->page) != id) {
-+ continue;
-+ }
-+
-+ rw_lock_s_unlock(&btr_search_latch);
-+
-+ rw_lock_x_lock(&block->lock);
-+ btr_search_drop_page_hash_index(block);
-+ rw_lock_x_unlock(&block->lock);
-+
-+ rw_lock_s_lock(&btr_search_latch);
-+ }
-+ }
-+ rw_lock_s_unlock(&btr_search_latch);
-+ }
-+}
-+
- #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
- /********************************************************************//**
- Insert a compressed block into buf_pool->zip_clean in the LRU order. */
-@@ -1499,6 +1555,10 @@
- return(FALSE);
- }
-
-+ if (bpage->space_was_being_deleted && bpage->oldest_modification != 0) {
-+ buf_flush_remove(bpage);
-+ }
-+
- #ifdef UNIV_IBUF_COUNT_DEBUG
- ut_a(ibuf_count_get(bpage->space, bpage->offset) == 0);
- #endif /* UNIV_IBUF_COUNT_DEBUG */
---- a/storage/innobase/fil/fil0fil.c
-+++ b/storage/innobase/fil/fil0fil.c
-@@ -254,6 +254,7 @@
- struct fil_system_struct {
- #ifndef UNIV_HOTBACKUP
- mutex_t mutex; /*!< The mutex protecting the cache */
-+ mutex_t file_extend_mutex;
- #endif /* !UNIV_HOTBACKUP */
- hash_table_t* spaces; /*!< The hash table of spaces in the
- system; they are hashed on the space
-@@ -863,7 +864,7 @@
- ut_ad(node && system);
- ut_ad(mutex_own(&(system->mutex)));
- ut_a(node->open);
-- ut_a(node->n_pending == 0);
-+ ut_a(node->n_pending == 0 || node->space->is_being_deleted);
- ut_a(node->n_pending_flushes == 0);
- ut_a(node->modification_counter == node->flush_counter
- || srv_fast_shutdown == 2);
-@@ -877,7 +878,7 @@
- ut_a(system->n_open > 0);
- system->n_open--;
-
-- if (node->space->purpose == FIL_TABLESPACE && !trx_sys_sys_space(node->space->id)) {
-+ if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE && !trx_sys_sys_space(node->space->id)) {
- ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
-
- /* The node is in the LRU list, remove it */
-@@ -1076,7 +1077,7 @@
- ut_ad(node && system && space);
- ut_ad(mutex_own(&(system->mutex)));
- ut_a(node->magic_n == FIL_NODE_MAGIC_N);
-- ut_a(node->n_pending == 0);
-+ ut_a(node->n_pending == 0 || space->is_being_deleted);
-
- if (node->open) {
- /* We fool the assertion in fil_node_close_file() to think
-@@ -1598,6 +1599,8 @@
-
- mutex_create(fil_system_mutex_key,
- &fil_system->mutex, SYNC_ANY_LATCH);
-+ mutex_create(fil_system_mutex_key,
-+ &fil_system->file_extend_mutex, SYNC_OUTER_ANY_LATCH);
-
- fil_system->spaces = hash_create(hash_size);
- fil_system->name_hash = hash_create(hash_size);
-@@ -2352,7 +2355,11 @@
- completely and permanently. The flag is_being_deleted also prevents
- fil_flush() from being applied to this tablespace. */
-
-+ if (srv_lazy_drop_table) {
-+ buf_LRU_mark_space_was_deleted(id);
-+ } else {
- buf_LRU_invalidate_tablespace(id);
-+ }
- #endif
- /* printf("Deleting tablespace %s id %lu\n", space->name, id); */
-
-@@ -4739,6 +4746,10 @@
- ulint page_size;
- ibool success = TRUE;
-
-+ /* file_extend_mutex is for http://bugs.mysql.com/56433 */
-+ /* to protect from the other fil_extend_space_to_desired_size() */
-+ /* during temprary releasing &fil_system->mutex */
-+ mutex_enter(&fil_system->file_extend_mutex);
- fil_mutex_enter_and_prepare_for_io(space_id);
-
- space = fil_space_get_by_id(space_id);
-@@ -4750,6 +4761,7 @@
- *actual_size = space->size;
-
- mutex_exit(&fil_system->mutex);
-+ mutex_exit(&fil_system->file_extend_mutex);
-
- return(TRUE);
- }
-@@ -4782,6 +4794,8 @@
- offset_low = ((start_page_no - file_start_page_no)
- % (4096 * ((1024 * 1024) / page_size)))
- * page_size;
-+
-+ mutex_exit(&fil_system->mutex);
- #ifdef UNIV_HOTBACKUP
- success = os_file_write(node->name, node->handle, buf,
- offset_low, offset_high,
-@@ -4791,8 +4805,10 @@
- node->name, node->handle, buf,
- offset_low, offset_high,
- page_size * n_pages,
-- NULL, NULL, NULL);
-+ NULL, NULL, space_id, NULL);
- #endif
-+ mutex_enter(&fil_system->mutex);
-+
- if (success) {
- node->size += n_pages;
- space->size += n_pages;
-@@ -4838,6 +4854,7 @@
- printf("Extended %s to %lu, actual size %lu pages\n", space->name,
- size_after_extend, *actual_size); */
- mutex_exit(&fil_system->mutex);
-+ mutex_exit(&fil_system->file_extend_mutex);
-
- fil_flush(space_id, TRUE);
-
-@@ -5200,6 +5217,22 @@
- srv_data_written+= len;
- }
-
-+ /* if the table space was already deleted, space might not exist already. */
-+ if (message
-+ && space_id < SRV_LOG_SPACE_FIRST_ID
-+ && ((buf_page_t*)message)->space_was_being_deleted) {
-+
-+ if (mode == OS_AIO_NORMAL) {
-+ buf_page_io_complete(message);
-+ return(DB_SUCCESS); /*fake*/
-+ }
-+ if (type == OS_FILE_READ) {
-+ return(DB_TABLESPACE_DELETED);
-+ } else {
-+ return(DB_SUCCESS); /*fake*/
-+ }
-+ }
-+
- /* Reserve the fil_system mutex and make sure that we can open at
- least one file while holding it, if the file is not already open */
-
-@@ -5341,10 +5374,24 @@
- #else
- /* Queue the aio request */
- ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
-- offset_low, offset_high, len, node, message, trx);
-+ offset_low, offset_high, len, node, message, space_id, trx);
- #endif
- } /**/
-
-+ /* if the table space was already deleted, space might not exist already. */
-+ if (message
-+ && space_id < SRV_LOG_SPACE_FIRST_ID
-+ && ((buf_page_t*)message)->space_was_being_deleted) {
-+
-+ if (mode == OS_AIO_SYNC) {
-+ if (type == OS_FILE_READ) {
-+ return(DB_TABLESPACE_DELETED);
-+ } else {
-+ return(DB_SUCCESS); /*fake*/
-+ }
-+ }
-+ }
-+
- ut_a(ret);
-
- if (mode == OS_AIO_SYNC) {
-@@ -5444,6 +5491,7 @@
- fil_node_t* fil_node;
- void* message;
- ulint type;
-+ ulint space_id = 0;
-
- ut_ad(fil_validate_skip());
-
-@@ -5451,10 +5499,10 @@
- srv_set_io_thread_op_info(segment, "native aio handle");
- #ifdef WIN_ASYNC_IO
- ret = os_aio_windows_handle(segment, 0, &fil_node,
-- &message, &type);
-+ &message, &type, &space_id);
- #elif defined(LINUX_NATIVE_AIO)
- ret = os_aio_linux_handle(segment, &fil_node,
-- &message, &type);
-+ &message, &type, &space_id);
- #else
- ut_error;
- ret = 0; /* Eliminate compiler warning */
-@@ -5463,7 +5511,22 @@
- srv_set_io_thread_op_info(segment, "simulated aio handle");
-
- ret = os_aio_simulated_handle(segment, &fil_node,
-- &message, &type);
-+ &message, &type, &space_id);
-+ }
-+
-+ /* if the table space was already deleted, fil_node might not exist already. */
-+ if (message
-+ && space_id < SRV_LOG_SPACE_FIRST_ID
-+ && ((buf_page_t*)message)->space_was_being_deleted) {
-+
-+ /* intended not to be uncompress read page */
-+ ut_a(buf_page_get_io_fix(message) == BUF_IO_WRITE
-+ || !buf_page_get_zip_size(message)
-+ || buf_page_get_state(message) != BUF_BLOCK_FILE_PAGE);
-+
-+ srv_set_io_thread_op_info(segment, "complete io for buf page");
-+ buf_page_io_complete(message);
-+ return;
- }
-
- ut_a(ret);
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -12189,6 +12189,12 @@
- "except for the deletion.",
- NULL, NULL, 0, &corrupt_table_action_typelib);
-
-+static MYSQL_SYSVAR_ULONG(lazy_drop_table, srv_lazy_drop_table,
-+ PLUGIN_VAR_RQCMDARG,
-+ "At deleting tablespace, only miminum needed processes at the time are done. "
-+ "e.g. for http://bugs.mysql.com/51325",
-+ NULL, NULL, 0, 0, 1, 0);
-+
- static struct st_mysql_sys_var* innobase_system_variables[]= {
- MYSQL_SYSVAR(page_size),
- MYSQL_SYSVAR(log_block_size),
-@@ -12286,6 +12292,7 @@
- MYSQL_SYSVAR(flush_checkpoint_debug),
- #endif
- MYSQL_SYSVAR(corrupt_table_action),
-+ MYSQL_SYSVAR(lazy_drop_table),
- NULL
- };
-
-@@ -12295,7 +12302,7 @@
- &innobase_storage_engine,
- innobase_hton_name,
- plugin_author,
-- "Supports transactions, row-level locking, and foreign keys",
-+ "Percona-XtraDB, Supports transactions, row-level locking, and foreign keys",
- PLUGIN_LICENSE_GPL,
- innobase_init, /* Plugin Init */
- NULL, /* Plugin Deinit */
---- a/storage/innobase/include/buf0buf.h
-+++ b/storage/innobase/include/buf0buf.h
-@@ -1475,6 +1475,7 @@
- 0 if the block was never accessed
- in the buffer pool */
- /* @} */
-+ ibool space_was_being_deleted;
- ibool is_corrupt;
- # if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
- ibool file_page_was_freed;
---- a/storage/innobase/include/buf0buf.ic
-+++ b/storage/innobase/include/buf0buf.ic
-@@ -426,6 +426,7 @@
- buf_block_set_state(block, BUF_BLOCK_FILE_PAGE);
- block->page.space = space;
- block->page.offset = page_no;
-+ block->page.space_was_being_deleted = FALSE;
- }
-
- /*********************************************************************//**
---- a/storage/innobase/include/buf0lru.h
-+++ b/storage/innobase/include/buf0lru.h
-@@ -73,6 +73,14 @@
- buf_LRU_invalidate_tablespace(
- /*==========================*/
- ulint id); /*!< in: space id */
-+
-+/******************************************************************//**
-+*/
-+UNIV_INTERN
-+void
-+buf_LRU_mark_space_was_deleted(
-+/*===========================*/
-+ ulint id); /*!< in: space id */
- #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
- /********************************************************************//**
- Insert a compressed block into buf_pool->zip_clean in the LRU order. */
---- a/storage/innobase/include/os0file.h
-+++ b/storage/innobase/include/os0file.h
-@@ -280,9 +280,9 @@
- pfs_os_file_close_func(file, __FILE__, __LINE__)
-
- # define os_aio(type, mode, name, file, buf, offset, offset_high, \
-- n, message1, message2, trx) \
-+ n, message1, message2, space_id, trx) \
- pfs_os_aio_func(type, mode, name, file, buf, offset, \
-- offset_high, n, message1, message2, trx, \
-+ offset_high, n, message1, message2, space_id, trx,\
- __FILE__, __LINE__)
-
- # define os_file_read(file, buf, offset, offset_high, n) \
-@@ -326,9 +326,9 @@
- # define os_file_close(file) os_file_close_func(file)
-
- # define os_aio(type, mode, name, file, buf, offset, offset_high, \
-- n, message1, message2, trx) \
-+ n, message1, message2, space_id, trx) \
- os_aio_func(type, mode, name, file, buf, offset, offset_high, n,\
-- message1, message2, trx)
-+ message1, message2, space_id, trx)
-
- # define os_file_read(file, buf, offset, offset_high, n) \
- os_file_read_func(file, buf, offset, offset_high, n, NULL)
-@@ -757,6 +757,7 @@
- (can be used to identify a completed
- aio operation); ignored if mode is
- OS_AIO_SYNC */
-+ ulint space_id,
- trx_t* trx,
- const char* src_file,/*!< in: file name where func invoked */
- ulint src_line);/*!< in: line where the func invoked */
-@@ -1065,6 +1066,7 @@
- (can be used to identify a completed
- aio operation); ignored if mode is
- OS_AIO_SYNC */
-+ ulint space_id,
- trx_t* trx);
- /************************************************************************//**
- Wakes up all async i/o threads so that they know to exit themselves in
-@@ -1125,7 +1127,8 @@
- parameters are valid and can be used to
- restart the operation, for example */
- void** message2,
-- ulint* type); /*!< out: OS_FILE_WRITE or ..._READ */
-+ ulint* type, /*!< out: OS_FILE_WRITE or ..._READ */
-+ ulint* space_id);
- #endif
-
- /**********************************************************************//**
-@@ -1147,7 +1150,8 @@
- parameters are valid and can be used to
- restart the operation, for example */
- void** message2,
-- ulint* type); /*!< out: OS_FILE_WRITE or ..._READ */
-+ ulint* type, /*!< out: OS_FILE_WRITE or ..._READ */
-+ ulint* space_id);
- /**********************************************************************//**
- Validates the consistency of the aio system.
- @return TRUE if ok */
-@@ -1226,7 +1230,8 @@
- aio operation failed, these output
- parameters are valid and can be used to
- restart the operation. */
-- ulint* type); /*!< out: OS_FILE_WRITE or ..._READ */
-+ ulint* type, /*!< out: OS_FILE_WRITE or ..._READ */
-+ ulint* space_id);
- #endif /* LINUX_NATIVE_AIO */
-
- #ifndef UNIV_NONINL
---- a/storage/innobase/include/os0file.ic
-+++ b/storage/innobase/include/os0file.ic
-@@ -229,6 +229,7 @@
- (can be used to identify a completed
- aio operation); ignored if mode is
- OS_AIO_SYNC */
-+ ulint space_id,
- trx_t* trx,
- const char* src_file,/*!< in: file name where func invoked */
- ulint src_line)/*!< in: line where the func invoked */
-@@ -245,7 +246,7 @@
- src_file, src_line);
-
- result = os_aio_func(type, mode, name, file, buf, offset, offset_high,
-- n, message1, message2, trx);
-+ n, message1, message2, space_id, trx);
-
- register_pfs_file_io_end(locker, n);
-
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -249,6 +249,8 @@
- extern ulint srv_pass_corrupt_table;
-
- extern ulint srv_dict_size_limit;
-+
-+extern ulint srv_lazy_drop_table;
- /*-------------------------------------------*/
-
- extern ulint srv_n_rows_inserted;
---- a/storage/innobase/include/sync0sync.h
-+++ b/storage/innobase/include/sync0sync.h
-@@ -689,6 +689,7 @@
- #define SYNC_BUF_POOL 150 /* Buffer pool mutex */
- #define SYNC_BUF_FLUSH_LIST 145 /* Buffer flush list mutex */
- #define SYNC_DOUBLEWRITE 140
-+#define SYNC_OUTER_ANY_LATCH 136
- #define SYNC_ANY_LATCH 135
- #define SYNC_MEM_HASH 131
- #define SYNC_MEM_POOL 130
---- a/storage/innobase/include/univ.i
-+++ b/storage/innobase/include/univ.i
-@@ -53,6 +53,11 @@
- #define INNODB_VERSION_MINOR 1
- #define INNODB_VERSION_BUGFIX 8
-
-+#ifndef PERCONA_INNODB_VERSION
-+#define PERCONA_INNODB_VERSION 20.1
-+#endif
-+
-+
- /* The following is the InnoDB version as shown in
- SELECT plugin_version FROM information_schema.plugins;
- calculated in make_version_string() in sql/sql_show.cc like this:
-@@ -65,7 +70,8 @@
- #define INNODB_VERSION_STR \
- IB_TO_STR(INNODB_VERSION_MAJOR) "." \
- IB_TO_STR(INNODB_VERSION_MINOR) "." \
-- IB_TO_STR(INNODB_VERSION_BUGFIX)
-+ IB_TO_STR(INNODB_VERSION_BUGFIX) "-" \
-+ IB_TO_STR(PERCONA_INNODB_VERSION)
-
- #define REFMAN "http://dev.mysql.com/doc/refman/" \
- IB_TO_STR(MYSQL_MAJOR_VERSION) "." \
---- a/storage/innobase/os/os0file.c
-+++ b/storage/innobase/os/os0file.c
-@@ -180,6 +180,7 @@
- made and only the slot message
- needs to be passed to the caller
- of os_aio_simulated_handle */
-+ ulint space_id;
- fil_node_t* message1; /*!< message which is given by the */
- void* message2; /*!< the requester of an aio operation
- and which can be used to identify
-@@ -3686,7 +3687,8 @@
- offset */
- ulint offset_high, /*!< in: most significant 32 bits of
- offset */
-- ulint len) /*!< in: length of the block to read or write */
-+ ulint len, /*!< in: length of the block to read or write */
-+ ulint space_id)
- {
- os_aio_slot_t* slot = NULL;
- #ifdef WIN_ASYNC_IO
-@@ -3775,6 +3777,7 @@
- slot->offset = offset;
- slot->offset_high = offset_high;
- slot->io_already_done = FALSE;
-+ slot->space_id = space_id;
-
- #ifdef WIN_ASYNC_IO
- control = &(slot->control);
-@@ -4062,6 +4065,7 @@
- (can be used to identify a completed
- aio operation); ignored if mode is
- OS_AIO_SYNC */
-+ ulint space_id,
- trx_t* trx)
- {
- os_aio_array_t* array;
-@@ -4157,7 +4161,7 @@
- trx->io_read += n;
- }
- slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
-- name, buf, offset, offset_high, n);
-+ name, buf, offset, offset_high, n, space_id);
- if (type == OS_FILE_READ) {
- if (srv_use_native_aio) {
- os_n_file_reads++;
-@@ -4276,7 +4280,8 @@
- parameters are valid and can be used to
- restart the operation, for example */
- void** message2,
-- ulint* type) /*!< out: OS_FILE_WRITE or ..._READ */
-+ ulint* type, /*!< out: OS_FILE_WRITE or ..._READ */
-+ ulint* space_id)
- {
- ulint orig_seg = segment;
- os_aio_array_t* array;
-@@ -4355,6 +4360,7 @@
- *message2 = slot->message2;
-
- *type = slot->type;
-+ *space_id = slot->space_id;
-
- if (ret && len == slot->len) {
- ret_val = TRUE;
-@@ -4583,7 +4589,8 @@
- aio operation failed, these output
- parameters are valid and can be used to
- restart the operation. */
-- ulint* type) /*!< out: OS_FILE_WRITE or ..._READ */
-+ ulint* type, /*!< out: OS_FILE_WRITE or ..._READ */
-+ ulint* space_id)
- {
- ulint segment;
- os_aio_array_t* array;
-@@ -4656,6 +4663,7 @@
- *message2 = slot->message2;
-
- *type = slot->type;
-+ *space_id = slot->space_id;
-
- if ((slot->ret == 0) && (slot->n_bytes == (long)slot->len)) {
- ret = TRUE;
-@@ -4709,7 +4717,8 @@
- parameters are valid and can be used to
- restart the operation, for example */
- void** message2,
-- ulint* type) /*!< out: OS_FILE_WRITE or ..._READ */
-+ ulint* type, /*!< out: OS_FILE_WRITE or ..._READ */
-+ ulint* space_id)
- {
- os_aio_array_t* array;
- ulint segment;
-@@ -5005,6 +5014,7 @@
- *message2 = slot->message2;
-
- *type = slot->type;
-+ *space_id = slot->space_id;
-
- os_mutex_exit(array->mutex);
-
---- a/storage/innobase/row/row0mysql.c
-+++ b/storage/innobase/row/row0mysql.c
-@@ -51,6 +51,7 @@
- #include "btr0sea.h"
- #include "fil0fil.h"
- #include "ibuf0ibuf.h"
-+#include "ha_prototypes.h"
-
- /** Provide optional 4.x backwards compatibility for 5.0 and above */
- UNIV_INTERN ibool row_rollback_on_timeout = FALSE;
-@@ -1192,6 +1193,13 @@
-
- thr = que_fork_get_first_thr(prebuilt->ins_graph);
-
-+ if (!prebuilt->mysql_has_locked && !(prebuilt->table->flags & (DICT_TF2_TEMPORARY << DICT_TF2_SHIFT))) {
-+ fprintf(stderr, "InnoDB: Error: row_insert_for_mysql is called without ha_innobase::external_lock()\n");
-+ if (trx->mysql_thd != NULL) {
-+ innobase_mysql_print_thd(stderr, trx->mysql_thd, 600);
-+ }
-+ }
-+
- if (prebuilt->sql_stat_start) {
- node->state = INS_NODE_SET_IX_LOCK;
- prebuilt->sql_stat_start = FALSE;
-@@ -2576,10 +2584,29 @@
-
- err = DB_ERROR;
- } else {
-+ dict_index_t* index;
-+
- /* Set the flag which tells that now it is legal to
- IMPORT a tablespace for this table */
- table->tablespace_discarded = TRUE;
- table->ibd_file_missing = TRUE;
-+
-+ /* check adaptive hash entries */
-+ index = dict_table_get_first_index(table);
-+ while (index) {
-+ ulint ref_count = btr_search_info_get_ref_count(index->search_info);
-+ if (ref_count) {
-+ fprintf(stderr, "InnoDB: Warning:"
-+ " hash index ref_count (%lu) is not zero"
-+ " after fil_discard_tablespace().\n"
-+ "index: \"%s\""
-+ " table: \"%s\"\n",
-+ ref_count,
-+ index->name,
-+ table->name);
-+ }
-+ index = dict_table_get_next_index(index);
-+ }
- }
- }
-
-@@ -2928,6 +2955,19 @@
- table->space = space;
- index = dict_table_get_first_index(table);
- do {
-+ ulint ref_count = btr_search_info_get_ref_count(index->search_info);
-+ /* check adaptive hash entries */
-+ if (ref_count) {
-+ fprintf(stderr, "InnoDB: Warning:"
-+ " hash index ref_count (%lu) is not zero"
-+ " after fil_discard_tablespace().\n"
-+ "index: \"%s\""
-+ " table: \"%s\"\n",
-+ ref_count,
-+ index->name,
-+ table->name);
-+ }
-+
- index->space = space;
- index = dict_table_get_next_index(index);
- } while (index);
---- a/storage/innobase/row/row0sel.c
-+++ b/storage/innobase/row/row0sel.c
-@@ -3418,6 +3418,7 @@
- ulint offsets_[REC_OFFS_NORMAL_SIZE];
- ulint* offsets = offsets_;
- ibool table_lock_waited = FALSE;
-+ ibool problematic_use = FALSE;
-
- rec_offs_init(offsets_);
-
-@@ -3796,6 +3797,17 @@
-
- /* Do some start-of-statement preparations */
-
-+ if (!prebuilt->mysql_has_locked) {
-+ if (!(prebuilt->table->flags & (DICT_TF2_TEMPORARY << DICT_TF2_SHIFT))) {
-+ fprintf(stderr, "InnoDB: Error: row_search_for_mysql() is called without ha_innobase::external_lock()\n");
-+ if (trx->mysql_thd != NULL) {
-+ innobase_mysql_print_thd(stderr, trx->mysql_thd, 600);
-+ }
-+ }
-+ problematic_use = TRUE;
-+ }
-+retry_check:
-+
- if (!prebuilt->sql_stat_start) {
- /* No need to set an intention lock or assign a read view */
-
-@@ -3806,6 +3818,18 @@
- " perform a consistent read\n"
- "InnoDB: but the read view is not assigned!\n",
- stderr);
-+ if (problematic_use) {
-+ fprintf(stderr, "InnoDB: It may be caused by calling "
-+ "without ha_innobase::external_lock()\n"
-+ "InnoDB: For the first-aid, avoiding the crash. "
-+ "But it should be fixed ASAP.\n");
-+ if (prebuilt->table->flags & (DICT_TF2_TEMPORARY << DICT_TF2_SHIFT)
-+ && trx->mysql_thd != NULL) {
-+ innobase_mysql_print_thd(stderr, trx->mysql_thd, 600);
-+ }
-+ prebuilt->sql_stat_start = TRUE;
-+ goto retry_check;
-+ }
- trx_print(stderr, trx, 600);
- fputc('\n', stderr);
- ut_error;
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -447,6 +447,8 @@
- UNIV_INTERN ulint srv_pass_corrupt_table = 0; /* 0:disable 1:enable */
-
- UNIV_INTERN ulint srv_dict_size_limit = 0;
-+
-+UNIV_INTERN ulint srv_lazy_drop_table = 0;
- /*-------------------------------------------*/
- UNIV_INTERN ulong srv_n_spin_wait_rounds = 30;
- UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500;
---- a/storage/innobase/srv/srv0start.c
-+++ b/storage/innobase/srv/srv0start.c
-@@ -2187,7 +2187,7 @@
- if (srv_print_verbose_log) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
-- " InnoDB: %s started; "
-+ " Percona XtraDB (http://www.percona.com) %s started; "
- "log sequence number %llu\n",
- INNODB_VERSION_STR, srv_start_lsn);
- }
---- a/storage/innobase/sync/sync0sync.c
-+++ b/storage/innobase/sync/sync0sync.c
-@@ -1219,6 +1219,7 @@
- case SYNC_LOG:
- case SYNC_LOG_FLUSH_ORDER:
- case SYNC_ANY_LATCH:
-+ case SYNC_OUTER_ANY_LATCH:
- case SYNC_FILE_FORMAT_TAG:
- case SYNC_DOUBLEWRITE:
- case SYNC_SEARCH_SYS:
---- a/storage/innobase/trx/trx0purge.c
-+++ b/storage/innobase/trx/trx0purge.c
-@@ -1149,8 +1149,7 @@
- /* If we cannot advance the 'purge view' because of an old
- 'consistent read view', then the DML statements cannot be delayed.
- Also, srv_max_purge_lag <= 0 means 'infinity'. */
-- if (srv_max_purge_lag > 0
-- && !UT_LIST_GET_LAST(trx_sys->view_list)) {
-+ if (srv_max_purge_lag > 0) {
- float ratio = (float) trx_sys->rseg_history_len
- / srv_max_purge_lag;
- if (ratio > ULINT_MAX / 10000) {
+++ /dev/null
-# name : innodb_io_patches.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/buf/buf0buf.c
-+++ b/storage/innobase/buf/buf0buf.c
-@@ -320,6 +320,7 @@
-
- /* When we traverse all the flush lists we don't want another
- thread to add a dirty page to any flush list. */
-+ if (srv_buf_pool_instances > 1)
- log_flush_order_mutex_enter();
-
- for (i = 0; i < srv_buf_pool_instances; i++) {
-@@ -343,6 +344,7 @@
- }
- }
-
-+ if (srv_buf_pool_instances > 1)
- log_flush_order_mutex_exit();
-
- /* The returned answer may be out of date: the flush_list can
---- a/storage/innobase/buf/buf0flu.c
-+++ b/storage/innobase/buf/buf0flu.c
-@@ -857,7 +857,7 @@
- flush:
- /* Now flush the doublewrite buffer data to disk */
-
-- fil_flush(TRX_SYS_SPACE);
-+ fil_flush(TRX_SYS_SPACE, FALSE);
-
- /* We know that the writes have been flushed to disk now
- and in recovery we will find them in the doublewrite buffer
-@@ -1375,10 +1375,11 @@
- ulint high;
- ulint count = 0;
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
-+ ibool is_forward_scan;
-
- ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST);
-
-- if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN) {
-+ if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN || !srv_flush_neighbor_pages) {
- /* If there is little space, it is better not to flush
- any block except from the end of the LRU list */
-
-@@ -1405,7 +1406,32 @@
- high = fil_space_get_size(space);
- }
-
-- for (i = low; i < high; i++) {
-+ if (srv_flush_neighbor_pages == 2) {
-+
-+ /* In the case of contiguous flush where the requested page
-+ does not fall at the start of flush area, first scan backward
-+ from the page and later forward from it. */
-+ is_forward_scan = (offset == low);
-+ }
-+ else {
-+ is_forward_scan = TRUE;
-+ }
-+
-+scan:
-+ if (srv_flush_neighbor_pages == 2) {
-+ if (is_forward_scan) {
-+ i = offset;
-+ }
-+ else {
-+ i = offset - 1;
-+ }
-+ }
-+ else {
-+ i = low;
-+ }
-+
-+ for (; is_forward_scan ? (i < high) : (i >= low);
-+ is_forward_scan ? i++ : i--) {
-
- buf_page_t* bpage;
-
-@@ -1434,6 +1460,12 @@
- if (!bpage) {
-
- buf_pool_mutex_exit(buf_pool);
-+ if (srv_flush_neighbor_pages == 2) {
-+
-+ /* This is contiguous neighbor page flush and
-+ the pages here are not contiguous. */
-+ break;
-+ }
- continue;
- }
-
-@@ -1470,6 +1502,22 @@
- }
- }
- buf_pool_mutex_exit(buf_pool);
-+
-+ if (srv_flush_neighbor_pages == 2) {
-+
-+ /* We are trying to do the contiguous neighbor page
-+ flush, but the last page we checked was unflushable,
-+ making a "hole" in the flush, so stop this attempt. */
-+ break;
-+ }
-+ }
-+
-+ if (!is_forward_scan) {
-+
-+ /* Backward scan done, now do the forward scan */
-+ ut_a (srv_flush_neighbor_pages == 2);
-+ is_forward_scan = TRUE;
-+ goto scan;
- }
-
- return(count);
---- a/storage/innobase/buf/buf0rea.c
-+++ b/storage/innobase/buf/buf0rea.c
-@@ -427,6 +427,10 @@
- = BUF_READ_AHEAD_AREA(buf_pool);
- ulint threshold;
-
-+ if (!(srv_read_ahead & 2)) {
-+ return(0);
-+ }
-+
- if (UNIV_UNLIKELY(srv_startup_is_before_trx_rollback_phase)) {
- /* No read-ahead to avoid thread deadlocks */
- return(0);
---- a/storage/innobase/fil/fil0fil.c
-+++ b/storage/innobase/fil/fil0fil.c
-@@ -2609,7 +2609,7 @@
-
- os_thread_sleep(20000);
-
-- fil_flush(id);
-+ fil_flush(id, TRUE);
-
- goto retry;
-
-@@ -2823,7 +2823,7 @@
- goto error_exit;
- }
-
-- ret = os_file_flush(file);
-+ ret = os_file_flush(file, TRUE);
-
- if (!ret) {
- fputs("InnoDB: Error: file flush of tablespace ", stderr);
-@@ -3009,7 +3009,7 @@
- }
- }
-
-- success = os_file_flush(file);
-+ success = os_file_flush(file, TRUE);
- if (!success) {
-
- goto func_exit;
-@@ -3031,7 +3031,7 @@
-
- goto func_exit;
- }
-- success = os_file_flush(file);
-+ success = os_file_flush(file, TRUE);
- func_exit:
- os_file_close(file);
- ut_free(buf2);
-@@ -4014,7 +4014,7 @@
- size_after_extend, *actual_size); */
- mutex_exit(&fil_system->mutex);
-
-- fil_flush(space_id);
-+ fil_flush(space_id, TRUE);
-
- return(success);
- }
-@@ -4585,8 +4585,9 @@
- void
- fil_flush(
- /*======*/
-- ulint space_id) /*!< in: file space id (this can be a group of
-+ ulint space_id, /*!< in: file space id (this can be a group of
- log files or a tablespace of the database) */
-+ ibool metadata)
- {
- fil_space_t* space;
- fil_node_t* node;
-@@ -4657,7 +4658,7 @@
- /* fprintf(stderr, "Flushing to file %s\n",
- node->name); */
-
-- os_file_flush(file);
-+ os_file_flush(file, metadata);
-
- mutex_enter(&fil_system->mutex);
-
-@@ -4740,7 +4741,7 @@
- a non-existing space id. */
- for (i = 0; i < n_space_ids; i++) {
-
-- fil_flush(space_ids[i]);
-+ fil_flush(space_ids[i], TRUE);
- }
-
- mem_free(space_ids);
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -445,6 +445,12 @@
- "Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout.",
- NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
-
-+static MYSQL_THDVAR_ULONG(flush_log_at_trx_commit, PLUGIN_VAR_OPCMDARG,
-+ "Set to 0 (write and flush once per second),"
-+ " 1 (write and flush at each commit)"
-+ " or 2 (write at commit, flush once per second).",
-+ NULL, NULL, 1, 0, 2, 0);
-+
-
- static handler *innobase_create_handler(handlerton *hton,
- TABLE_SHARE *table,
-@@ -841,6 +847,17 @@
- }
- }
-
-+/******************************************************************//**
-+*/
-+extern "C" UNIV_INTERN
-+ulong
-+thd_flush_log_at_trx_commit(
-+/*================================*/
-+ void* thd)
-+{
-+ return(THDVAR((THD*) thd, flush_log_at_trx_commit));
-+}
-+
- /********************************************************************//**
- Obtain the InnoDB transaction of a MySQL thread.
- @return reference to transaction pointer */
-@@ -2471,6 +2488,9 @@
- srv_n_read_io_threads = (ulint) innobase_read_io_threads;
- srv_n_write_io_threads = (ulint) innobase_write_io_threads;
-
-+ srv_read_ahead &= 3;
-+ srv_adaptive_flushing_method %= 3;
-+
- srv_force_recovery = (ulint) innobase_force_recovery;
-
- srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
-@@ -11141,7 +11161,7 @@
- PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
- "Purge threads can be either 0 or 1.",
- NULL, NULL,
-- 0, /* Default setting */
-+ 1, /* Default setting */
- 0, /* Minimum value */
- 1, 0); /* Maximum value */
-
-@@ -11183,12 +11203,18 @@
- innodb_file_format_max_validate,
- innodb_file_format_max_update, "Antelope");
-
--static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
-- PLUGIN_VAR_OPCMDARG,
-- "Set to 0 (write and flush once per second),"
-- " 1 (write and flush at each commit)"
-- " or 2 (write at commit, flush once per second).",
-- NULL, NULL, 1, 0, 2, 0);
-+/* Changed to the THDVAR */
-+//static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
-+// PLUGIN_VAR_OPCMDARG,
-+// "Set to 0 (write and flush once per second),"
-+// " 1 (write and flush at each commit)"
-+// " or 2 (write at commit, flush once per second).",
-+// NULL, NULL, 1, 0, 2, 0);
-+
-+static MYSQL_SYSVAR_BOOL(use_global_flush_log_at_trx_commit, srv_use_global_flush_log_at_trx_commit,
-+ PLUGIN_VAR_NOCMDARG,
-+ "Use global innodb_flush_log_at_trx_commit value. (default: ON).",
-+ NULL, NULL, TRUE);
-
- static MYSQL_SYSVAR_STR(flush_method, innobase_file_flush_method,
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
-@@ -11293,7 +11319,7 @@
- static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
- "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
-- NULL, NULL, 128*1024*1024L, 5*1024*1024L, LONGLONG_MAX, 1024*1024L);
-+ NULL, NULL, 128*1024*1024L, 32*1024*1024L, LONGLONG_MAX, 1024*1024L);
-
- static MYSQL_SYSVAR_LONG(buffer_pool_instances, innobase_buffer_pool_instances,
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
-@@ -11442,6 +11468,127 @@
- "trigger a readahead.",
- NULL, NULL, 56, 0, 64, 0);
-
-+static MYSQL_SYSVAR_LONGLONG(ibuf_max_size, srv_ibuf_max_size,
-+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
-+ "The maximum size of the insert buffer. (in bytes)",
-+ NULL, NULL, LONGLONG_MAX, 0, LONGLONG_MAX, 0);
-+
-+static MYSQL_SYSVAR_ULONG(ibuf_active_contract, srv_ibuf_active_contract,
-+ PLUGIN_VAR_RQCMDARG,
-+ "Enable/Disable active_contract of insert buffer. 0:disable 1:enable",
-+ NULL, NULL, 1, 0, 1, 0);
-+
-+static MYSQL_SYSVAR_ULONG(ibuf_accel_rate, srv_ibuf_accel_rate,
-+ PLUGIN_VAR_RQCMDARG,
-+ "Tunes amount of insert buffer processing of background, in addition to innodb_io_capacity. (in percentage)",
-+ NULL, NULL, 100, 100, 999999999, 0);
-+
-+static MYSQL_SYSVAR_ULONG(checkpoint_age_target, srv_checkpoint_age_target,
-+ PLUGIN_VAR_RQCMDARG,
-+ "Control soft limit of checkpoint age. (0 : not control)",
-+ NULL, NULL, 0, 0, ~0UL, 0);
-+
-+static
-+void
-+innodb_flush_neighbor_pages_update(
-+ THD* thd,
-+ struct st_mysql_sys_var* var,
-+ void* var_ptr,
-+ const void* save)
-+{
-+ *(long *)var_ptr = (*(long *)save) % 3;
-+}
-+
-+const char *flush_neighbor_pages_names[]=
-+{
-+ "none", /* 0 */
-+ "area",
-+ "cont", /* 2 */
-+ /* For compatibility with the older patch */
-+ "0", /* "none" + 3 */
-+ "1", /* "area" + 3 */
-+ "2", /* "cont" + 3 */
-+ NullS
-+};
-+
-+TYPELIB flush_neighbor_pages_typelib=
-+{
-+ array_elements(flush_neighbor_pages_names) - 1,
-+ "flush_neighbor_pages_typelib",
-+ flush_neighbor_pages_names,
-+ NULL
-+};
-+
-+static MYSQL_SYSVAR_ENUM(flush_neighbor_pages, srv_flush_neighbor_pages,
-+ PLUGIN_VAR_RQCMDARG, "Neighbor page flushing behaviour: none: do not flush, "
-+ "[area]: flush selected pages one-by-one, "
-+ "cont: flush a contiguous block of pages", NULL,
-+ innodb_flush_neighbor_pages_update, 1, &flush_neighbor_pages_typelib);
-+
-+static
-+void
-+innodb_read_ahead_update(
-+ THD* thd,
-+ struct st_mysql_sys_var* var,
-+ void* var_ptr,
-+ const void* save)
-+{
-+ *(long *)var_ptr= (*(long *)save) & 3;
-+}
-+const char *read_ahead_names[]=
-+{
-+ "none", /* 0 */
-+ "random",
-+ "linear",
-+ "both", /* 3 */
-+ /* For compatibility of the older patch */
-+ "0", /* 4 ("none" + 4) */
-+ "1",
-+ "2",
-+ "3", /* 7 ("both" + 4) */
-+ NullS
-+};
-+TYPELIB read_ahead_typelib=
-+{
-+ array_elements(read_ahead_names) - 1, "read_ahead_typelib",
-+ read_ahead_names, NULL
-+};
-+static MYSQL_SYSVAR_ENUM(read_ahead, srv_read_ahead,
-+ PLUGIN_VAR_RQCMDARG,
-+ "Control read ahead activity (none, random, [linear], both). [from 1.0.5: random read ahead is ignored]",
-+ NULL, innodb_read_ahead_update, 2, &read_ahead_typelib);
-+
-+static
-+void
-+innodb_adaptive_flushing_method_update(
-+ THD* thd,
-+ struct st_mysql_sys_var* var,
-+ void* var_ptr,
-+ const void* save)
-+{
-+ *(long *)var_ptr= (*(long *)save) % 4;
-+}
-+const char *adaptive_flushing_method_names[]=
-+{
-+ "native", /* 0 */
-+ "estimate", /* 1 */
-+ "keep_average", /* 2 */
-+ /* For compatibility of the older patch */
-+ "0", /* 3 ("none" + 3) */
-+ "1", /* 4 ("estimate" + 3) */
-+ "2", /* 5 ("keep_average" + 3) */
-+ NullS
-+};
-+TYPELIB adaptive_flushing_method_typelib=
-+{
-+ array_elements(adaptive_flushing_method_names) - 1, "adaptive_flushing_method_typelib",
-+ adaptive_flushing_method_names, NULL
-+};
-+static MYSQL_SYSVAR_ENUM(adaptive_flushing_method, srv_adaptive_flushing_method,
-+ PLUGIN_VAR_RQCMDARG,
-+ "Choose method of innodb_adaptive_flushing. (native, [estimate], keep_average)",
-+ NULL, innodb_adaptive_flushing_method_update, 1, &adaptive_flushing_method_typelib);
-+
- static struct st_mysql_sys_var* innobase_system_variables[]= {
- MYSQL_SYSVAR(additional_mem_pool_size),
- MYSQL_SYSVAR(autoextend_increment),
-@@ -11462,6 +11609,7 @@
- MYSQL_SYSVAR(file_format_check),
- MYSQL_SYSVAR(file_format_max),
- MYSQL_SYSVAR(flush_log_at_trx_commit),
-+ MYSQL_SYSVAR(use_global_flush_log_at_trx_commit),
- MYSQL_SYSVAR(flush_method),
- MYSQL_SYSVAR(force_recovery),
- MYSQL_SYSVAR(large_prefix),
-@@ -11501,6 +11649,13 @@
- MYSQL_SYSVAR(show_verbose_locks),
- MYSQL_SYSVAR(show_locks_held),
- MYSQL_SYSVAR(version),
-+ MYSQL_SYSVAR(ibuf_max_size),
-+ MYSQL_SYSVAR(ibuf_active_contract),
-+ MYSQL_SYSVAR(ibuf_accel_rate),
-+ MYSQL_SYSVAR(checkpoint_age_target),
-+ MYSQL_SYSVAR(flush_neighbor_pages),
-+ MYSQL_SYSVAR(read_ahead),
-+ MYSQL_SYSVAR(adaptive_flushing_method),
- MYSQL_SYSVAR(use_sys_malloc),
- MYSQL_SYSVAR(use_native_aio),
- MYSQL_SYSVAR(change_buffering),
---- a/storage/innobase/ibuf/ibuf0ibuf.c
-+++ b/storage/innobase/ibuf/ibuf0ibuf.c
-@@ -523,8 +523,10 @@
- grow in size, as the references on the upper levels of the tree can
- change */
-
-- ibuf->max_size = buf_pool_get_curr_size() / UNIV_PAGE_SIZE
-- / IBUF_POOL_SIZE_PER_MAX_SIZE;
-+ ibuf->max_size = ut_min( buf_pool_get_curr_size() / UNIV_PAGE_SIZE
-+ / IBUF_POOL_SIZE_PER_MAX_SIZE, (ulint) srv_ibuf_max_size / UNIV_PAGE_SIZE);
-+
-+ srv_ibuf_max_size = (long long) ibuf->max_size * UNIV_PAGE_SIZE;
-
- mutex_create(ibuf_pessimistic_insert_mutex_key,
- &ibuf_pessimistic_insert_mutex,
-@@ -2763,9 +2765,11 @@
- size = ibuf->size;
- max_size = ibuf->max_size;
-
-+ if (!srv_ibuf_active_contract) {
- if (size < max_size + IBUF_CONTRACT_ON_INSERT_NON_SYNC) {
- return;
- }
-+ }
-
- sync = (size >= max_size + IBUF_CONTRACT_ON_INSERT_SYNC);
-
---- a/storage/innobase/include/buf0rea.h
-+++ b/storage/innobase/include/buf0rea.h
-@@ -149,8 +149,7 @@
-
- /** The size in pages of the area which the read-ahead algorithms read if
- invoked */
--#define BUF_READ_AHEAD_AREA(b) \
-- ut_min(64, ut_2_power_up((b)->curr_size / 32))
-+#define BUF_READ_AHEAD_AREA(b) 64
-
- /** @name Modes used in read-ahead @{ */
- /** read only pages belonging to the insert buffer tree */
---- a/storage/innobase/include/fil0fil.h
-+++ b/storage/innobase/include/fil0fil.h
-@@ -663,8 +663,9 @@
- void
- fil_flush(
- /*======*/
-- ulint space_id); /*!< in: file space id (this can be a group of
-+ ulint space_id, /*!< in: file space id (this can be a group of
- log files or a tablespace of the database) */
-+ ibool metadata);
- /**********************************************************************//**
- Flushes to disk writes in file spaces of the given type possibly cached by
- the OS. */
---- a/storage/innobase/include/ha_prototypes.h
-+++ b/storage/innobase/include/ha_prototypes.h
-@@ -284,6 +284,13 @@
- /*===================*/
- void* thd, /*!< in: thread handle (THD*) */
- ulint value); /*!< in: time waited for the lock */
-+/******************************************************************//**
-+*/
-+
-+ulong
-+thd_flush_log_at_trx_commit(
-+/*================================*/
-+ void* thd);
-
- /**********************************************************************//**
- Get the current setting of the lower_case_table_names global parameter from
---- a/storage/innobase/include/os0file.h
-+++ b/storage/innobase/include/os0file.h
-@@ -296,8 +296,8 @@
- pfs_os_file_write_func(name, file, buf, offset, offset_high, \
- n, __FILE__, __LINE__)
-
--# define os_file_flush(file) \
-- pfs_os_file_flush_func(file, __FILE__, __LINE__)
-+# define os_file_flush(file, metadata) \
-+ pfs_os_file_flush_func(file, metadata, __FILE__, __LINE__)
-
- # define os_file_rename(key, oldpath, newpath) \
- pfs_os_file_rename_func(key, oldpath, newpath, __FILE__, __LINE__)
-@@ -333,7 +333,7 @@
- # define os_file_write(name, file, buf, offset, offset_high, n) \
- os_file_write_func(name, file, buf, offset, offset_high, n)
-
--# define os_file_flush(file) os_file_flush_func(file)
-+# define os_file_flush(file, metadata) os_file_flush_func(file, metadata)
-
- # define os_file_rename(key, oldpath, newpath) \
- os_file_rename_func(oldpath, newpath)
-@@ -781,6 +781,7 @@
- pfs_os_file_flush_func(
- /*===================*/
- os_file_t file, /*!< in, own: handle to a file */
-+ ibool metadata,
- const char* src_file,/*!< in: file name where func invoked */
- ulint src_line);/*!< in: line where the func invoked */
-
-@@ -860,7 +861,8 @@
- ibool
- os_file_flush_func(
- /*===============*/
-- os_file_t file); /*!< in, own: handle to a file */
-+ os_file_t file, /*!< in, own: handle to a file */
-+ ibool metadata);
- /***********************************************************************//**
- Retrieves the last error number if an error occurs in a file io function.
- The number should be retrieved before any other OS calls (because they may
---- a/storage/innobase/include/os0file.ic
-+++ b/storage/innobase/include/os0file.ic
-@@ -369,6 +369,7 @@
- pfs_os_file_flush_func(
- /*===================*/
- os_file_t file, /*!< in, own: handle to a file */
-+ ibool metadata,
- const char* src_file,/*!< in: file name where func invoked */
- ulint src_line)/*!< in: line where the func invoked */
- {
-@@ -378,7 +379,7 @@
-
- register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_SYNC,
- src_file, src_line);
-- result = os_file_flush_func(file);
-+ result = os_file_flush_func(file, metadata);
-
- register_pfs_file_io_end(locker, 0);
-
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -138,7 +138,8 @@
- extern ulint srv_n_log_files;
- extern ulint srv_log_file_size;
- extern ulint srv_log_buffer_size;
--extern ulong srv_flush_log_at_trx_commit;
-+//extern ulong srv_flush_log_at_trx_commit;
-+extern char srv_use_global_flush_log_at_trx_commit;
- extern char srv_adaptive_flushing;
-
- /* If this flag is TRUE, then we will load the indexes' (and tables') metadata
-@@ -221,6 +222,16 @@
- extern ulong srv_max_purge_lag;
-
- extern ulong srv_replication_delay;
-+
-+extern long long srv_ibuf_max_size;
-+extern ulint srv_ibuf_active_contract;
-+extern ulint srv_ibuf_accel_rate;
-+extern ulint srv_checkpoint_age_target;
-+extern ulint srv_flush_neighbor_pages;
-+extern ulint srv_enable_unsafe_group_commit;
-+extern ulint srv_read_ahead;
-+extern ulint srv_adaptive_flushing_method;
-+
- /*-------------------------------------------*/
-
- extern ulint srv_n_rows_inserted;
-@@ -399,8 +410,9 @@
- when writing data files, but do flush
- after writing to log files */
- SRV_UNIX_NOSYNC, /*!< do not flush after writing */
-- SRV_UNIX_O_DIRECT /*!< invoke os_file_set_nocache() on
-+ SRV_UNIX_O_DIRECT, /*!< invoke os_file_set_nocache() on
- data files */
-+ SRV_UNIX_ALL_O_DIRECT /* new method for examination: logfile also open O_DIRECT */
- };
-
- /** Alternatives for file i/o in Windows */
---- a/storage/innobase/log/log0log.c
-+++ b/storage/innobase/log/log0log.c
-@@ -48,6 +48,7 @@
- #include "srv0start.h"
- #include "trx0sys.h"
- #include "trx0trx.h"
-+#include "ha_prototypes.h"
-
- /*
- General philosophy of InnoDB redo-logs:
-@@ -359,6 +360,33 @@
- }
-
- /************************************************************//**
-+*/
-+UNIV_INLINE
-+ulint
-+log_max_modified_age_async()
-+{
-+ if (srv_checkpoint_age_target) {
-+ return(ut_min(log_sys->max_modified_age_async,
-+ srv_checkpoint_age_target
-+ - srv_checkpoint_age_target / 8));
-+ } else {
-+ return(log_sys->max_modified_age_async);
-+ }
-+}
-+
-+UNIV_INLINE
-+ulint
-+log_max_checkpoint_age_async()
-+{
-+ if (srv_checkpoint_age_target) {
-+ return(ut_min(log_sys->max_checkpoint_age_async,
-+ srv_checkpoint_age_target));
-+ } else {
-+ return(log_sys->max_checkpoint_age_async);
-+ }
-+}
-+
-+/************************************************************//**
- Closes the log.
- @return lsn */
- UNIV_INTERN
-@@ -427,7 +455,7 @@
- }
- }
-
-- if (checkpoint_age <= log->max_modified_age_async) {
-+ if (checkpoint_age <= log_max_modified_age_async()) {
-
- goto function_exit;
- }
-@@ -435,8 +463,8 @@
- oldest_lsn = buf_pool_get_oldest_modification();
-
- if (!oldest_lsn
-- || lsn - oldest_lsn > log->max_modified_age_async
-- || checkpoint_age > log->max_checkpoint_age_async) {
-+ || lsn - oldest_lsn > log_max_modified_age_async()
-+ || checkpoint_age > log_max_checkpoint_age_async()) {
-
- log->check_flush_or_checkpoint = TRUE;
- }
-@@ -1100,9 +1128,10 @@
- group = (log_group_t*)((ulint)group - 1);
-
- if (srv_unix_file_flush_method != SRV_UNIX_O_DSYNC
-+ && srv_unix_file_flush_method != SRV_UNIX_ALL_O_DIRECT
- && srv_unix_file_flush_method != SRV_UNIX_NOSYNC) {
-
-- fil_flush(group->space_id);
-+ fil_flush(group->space_id, FALSE);
- }
-
- #ifdef UNIV_DEBUG
-@@ -1121,10 +1150,11 @@
- logs and cannot end up here! */
-
- if (srv_unix_file_flush_method != SRV_UNIX_O_DSYNC
-+ && srv_unix_file_flush_method != SRV_UNIX_ALL_O_DIRECT
- && srv_unix_file_flush_method != SRV_UNIX_NOSYNC
-- && srv_flush_log_at_trx_commit != 2) {
-+ && thd_flush_log_at_trx_commit(NULL) != 2) {
-
-- fil_flush(group->space_id);
-+ fil_flush(group->space_id, FALSE);
- }
-
- mutex_enter(&(log_sys->mutex));
-@@ -1501,7 +1531,8 @@
-
- mutex_exit(&(log_sys->mutex));
-
-- if (srv_unix_file_flush_method == SRV_UNIX_O_DSYNC) {
-+ if (srv_unix_file_flush_method == SRV_UNIX_O_DSYNC
-+ || srv_unix_file_flush_method == SRV_UNIX_ALL_O_DIRECT) {
- /* O_DSYNC means the OS did not buffer the log file at all:
- so we have also flushed to disk what we have written */
-
-@@ -1511,7 +1542,7 @@
-
- group = UT_LIST_GET_FIRST(log_sys->log_groups);
-
-- fil_flush(group->space_id);
-+ fil_flush(group->space_id, FALSE);
- log_sys->flushed_to_disk_lsn = log_sys->write_lsn;
- }
-
-@@ -2120,10 +2151,10 @@
-
- sync = TRUE;
- advance = 2 * (age - log->max_modified_age_sync);
-- } else if (age > log->max_modified_age_async) {
-+ } else if (age > log_max_modified_age_async()) {
-
- /* A flush is not urgent: we do an asynchronous preflush */
-- advance = age - log->max_modified_age_async;
-+ advance = age - log_max_modified_age_async();
- } else {
- advance = 0;
- }
-@@ -2137,7 +2168,7 @@
-
- do_checkpoint = TRUE;
-
-- } else if (checkpoint_age > log->max_checkpoint_age_async) {
-+ } else if (checkpoint_age > log_max_checkpoint_age_async()) {
- /* A checkpoint is not urgent: do it asynchronously */
-
- do_checkpoint = TRUE;
-@@ -2607,7 +2638,7 @@
-
- mutex_exit(&(log_sys->mutex));
-
-- fil_flush(group->archive_space_id);
-+ fil_flush(group->archive_space_id, TRUE);
-
- mutex_enter(&(log_sys->mutex));
-
-@@ -3349,6 +3380,17 @@
- log_sys->flushed_to_disk_lsn,
- log_sys->last_checkpoint_lsn);
-
-+ fprintf(file,
-+ "Max checkpoint age %lu\n"
-+ "Checkpoint age target %lu\n"
-+ "Modified age %lu\n"
-+ "Checkpoint age %lu\n",
-+ (ulong) log_sys->max_checkpoint_age,
-+ (ulong) log_max_checkpoint_age_async(),
-+ (ulong) (log_sys->lsn -
-+ log_buf_pool_get_oldest_modification()),
-+ (ulong) (log_sys->lsn - log_sys->last_checkpoint_lsn));
-+
- current_time = time(NULL);
-
- time_elapsed = 0.001 + difftime(current_time,
---- a/storage/innobase/log/log0recv.c
-+++ b/storage/innobase/log/log0recv.c
-@@ -2906,9 +2906,12 @@
- ib_uint64_t archived_lsn;
- #endif /* UNIV_LOG_ARCHIVE */
- byte* buf;
-- byte log_hdr_buf[LOG_FILE_HDR_SIZE];
-+ byte* log_hdr_buf;
-+ byte log_hdr_buf_base[LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE];
- ulint err;
-
-+ log_hdr_buf = ut_align(log_hdr_buf_base, OS_FILE_LOG_BLOCK_SIZE);
-+
- #ifdef UNIV_LOG_ARCHIVE
- ut_ad(type != LOG_CHECKPOINT || limit_lsn == IB_ULONGLONG_MAX);
- /** TRUE when recovering from a checkpoint */
-@@ -3468,7 +3471,7 @@
- exit(1);
- }
-
-- os_file_flush(log_file);
-+ os_file_flush(log_file, TRUE);
- os_file_close(log_file);
- }
-
-@@ -3492,7 +3495,7 @@
-
- os_file_write(name, log_file, buf, 0, 0,
- LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE);
-- os_file_flush(log_file);
-+ os_file_flush(log_file, TRUE);
- os_file_close(log_file);
-
- ut_free(buf);
---- a/storage/innobase/os/os0file.c
-+++ b/storage/innobase/os/os0file.c
-@@ -1424,7 +1424,7 @@
- #endif
- #ifdef UNIV_NON_BUFFERED_IO
- # ifndef UNIV_HOTBACKUP
-- if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
-+ if (type == OS_LOG_FILE && thd_flush_log_at_trx_commit(NULL) == 2) {
- /* Do not use unbuffered i/o to log files because
- value 2 denotes that we do not flush the log at every
- commit, but only once per second */
-@@ -1440,7 +1440,7 @@
- attributes = 0;
- #ifdef UNIV_NON_BUFFERED_IO
- # ifndef UNIV_HOTBACKUP
-- if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
-+ if (type == OS_LOG_FILE && thd_flush_log_at_trx_commit(NULL) == 2) {
- /* Do not use unbuffered i/o to log files because
- value 2 denotes that we do not flush the log at every
- commit, but only once per second */
-@@ -1585,6 +1585,11 @@
- os_file_set_nocache(file, name, mode_str);
- }
-
-+ /* ALL_O_DIRECT: O_DIRECT also for transaction log file */
-+ if (srv_unix_file_flush_method == SRV_UNIX_ALL_O_DIRECT) {
-+ os_file_set_nocache(file, name, mode_str);
-+ }
-+
- #ifdef USE_FILE_LOCK
- if (create_mode != OS_FILE_OPEN_RAW && os_file_lock(file, name)) {
-
-@@ -2008,7 +2013,7 @@
-
- ut_free(buf2);
-
-- ret = os_file_flush(file);
-+ ret = os_file_flush(file, TRUE);
-
- if (ret) {
- return(TRUE);
-@@ -2046,7 +2051,8 @@
- int
- os_file_fsync(
- /*==========*/
-- os_file_t file) /*!< in: handle to a file */
-+ os_file_t file, /*!< in: handle to a file */
-+ ibool metadata)
- {
- int ret;
- int failures;
-@@ -2055,7 +2061,16 @@
- failures = 0;
-
- do {
-+#if defined(HAVE_FDATASYNC) && HAVE_DECL_FDATASYNC
-+ if (metadata) {
-+ ret = fsync(file);
-+ } else {
-+ ret = fdatasync(file);
-+ }
-+#else
-+ (void) metadata;
- ret = fsync(file);
-+#endif
-
- os_n_fsyncs++;
-
-@@ -2092,7 +2107,8 @@
- ibool
- os_file_flush_func(
- /*===============*/
-- os_file_t file) /*!< in, own: handle to a file */
-+ os_file_t file, /*!< in, own: handle to a file */
-+ ibool metadata)
- {
- #ifdef __WIN__
- BOOL ret;
-@@ -2142,18 +2158,18 @@
- /* If we are not on an operating system that supports this,
- then fall back to a plain fsync. */
-
-- ret = os_file_fsync(file);
-+ ret = os_file_fsync(file, metadata);
- } else {
- ret = fcntl(file, F_FULLFSYNC, NULL);
-
- if (ret) {
- /* If we are not on a file system that supports this,
- then fall back to a plain fsync. */
-- ret = os_file_fsync(file);
-+ ret = os_file_fsync(file, metadata);
- }
- }
- #else
-- ret = os_file_fsync(file);
-+ ret = os_file_fsync(file, metadata);
- #endif
-
- if (ret == 0) {
-@@ -2336,7 +2352,7 @@
- the OS crashes, a database page is only partially
- physically written to disk. */
-
-- ut_a(TRUE == os_file_flush(file));
-+ ut_a(TRUE == os_file_flush(file, TRUE));
- }
- # endif /* UNIV_DO_FLUSH */
-
-@@ -2378,7 +2394,7 @@
- the OS crashes, a database page is only partially
- physically written to disk. */
-
-- ut_a(TRUE == os_file_flush(file));
-+ ut_a(TRUE == os_file_flush(file, TRUE));
- }
- # endif /* UNIV_DO_FLUSH */
-
-@@ -2750,7 +2766,7 @@
-
- # ifdef UNIV_DO_FLUSH
- if (!os_do_not_call_flush_at_each_write) {
-- ut_a(TRUE == os_file_flush(file));
-+ ut_a(TRUE == os_file_flush(file, TRUE));
- }
- # endif /* UNIV_DO_FLUSH */
-
-@@ -4296,7 +4312,7 @@
- #ifdef UNIV_DO_FLUSH
- if (slot->type == OS_FILE_WRITE
- && !os_do_not_call_flush_at_each_write) {
-- if (!os_file_flush(slot->file)) {
-+ if (!os_file_flush(slot->file, TRUE)) {
- ut_error;
- }
- }
-@@ -4597,7 +4613,7 @@
- #ifdef UNIV_DO_FLUSH
- if (slot->type == OS_FILE_WRITE
- && !os_do_not_call_flush_at_each_write)
-- && !os_file_flush(slot->file) {
-+ && !os_file_flush(slot->file, TRUE) {
- ut_error;
- }
- #endif /* UNIV_DO_FLUSH */
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -183,7 +183,8 @@
- UNIV_INTERN ulint srv_log_file_size = ULINT_MAX;
- /* size in database pages */
- UNIV_INTERN ulint srv_log_buffer_size = ULINT_MAX;
--UNIV_INTERN ulong srv_flush_log_at_trx_commit = 1;
-+//UNIV_INTERN ulong srv_flush_log_at_trx_commit = 1;
-+UNIV_INTERN char srv_use_global_flush_log_at_trx_commit = TRUE;
-
- /* Try to flush dirty pages so as to avoid IO bursts at
- the checkpoints. */
-@@ -404,6 +405,17 @@
-
- UNIV_INTERN ulong srv_replication_delay = 0;
-
-+UNIV_INTERN long long srv_ibuf_max_size = 0;
-+UNIV_INTERN ulint srv_ibuf_active_contract = 0; /* 0:disable 1:enable */
-+UNIV_INTERN ulint srv_ibuf_accel_rate = 100;
-+#define PCT_IBUF_IO(pct) ((ulint) (srv_io_capacity * srv_ibuf_accel_rate * ((double) pct / 10000.0)))
-+
-+UNIV_INTERN ulint srv_checkpoint_age_target = 0;
-+UNIV_INTERN ulint srv_flush_neighbor_pages = 1; /* 0:disable 1:area 2:contiguous */
-+
-+UNIV_INTERN ulint srv_enable_unsafe_group_commit = 0; /* 0:disable 1:enable */
-+UNIV_INTERN ulint srv_read_ahead = 3; /* 1: random 2: linear 3: Both */
-+UNIV_INTERN ulint srv_adaptive_flushing_method = 0; /* 0: native 1: estimate 2: keep_average */
- /*-------------------------------------------*/
- UNIV_INTERN ulong srv_n_spin_wait_rounds = 30;
- UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500;
-@@ -2713,7 +2725,7 @@
-
- ut_ad(!mutex_own(&kernel_mutex));
-
-- ut_a(srv_n_purge_threads == 0);
-+ ut_a(srv_n_purge_threads == 0 || (srv_shutdown_state > 0 && srv_n_threads_active[SRV_WORKER] == 0));
-
- do {
- /* Check for shutdown and change in purge config. */
-@@ -2746,6 +2758,7 @@
- ulint n_pages_purged = 0;
- ulint n_bytes_merged;
- ulint n_pages_flushed;
-+ ulint n_pages_flushed_prev = 0;
- ulint n_bytes_archived;
- ulint n_tables_to_drop;
- ulint n_ios;
-@@ -2753,7 +2766,20 @@
- ulint n_ios_very_old;
- ulint n_pend_ios;
- ulint next_itr_time;
-+ ulint prev_adaptive_flushing_method = ULINT_UNDEFINED;
-+ ulint inner_loop = 0;
-+ ibool skip_sleep = FALSE;
- ulint i;
-+ struct t_prev_flush_info_struct {
-+ ulint count;
-+ unsigned space:32;
-+ unsigned offset:32;
-+ ib_uint64_t oldest_modification;
-+ } prev_flush_info[MAX_BUFFER_POOLS];
-+
-+ ib_uint64_t lsn_old;
-+
-+ ib_uint64_t oldest_lsn;
-
- #ifdef UNIV_DEBUG_THREAD_CREATION
- fprintf(stderr, "Master thread starts, id %lu\n",
-@@ -2775,6 +2801,9 @@
-
- mutex_exit(&kernel_mutex);
-
-+ mutex_enter(&(log_sys->mutex));
-+ lsn_old = log_sys->lsn;
-+ mutex_exit(&(log_sys->mutex));
- loop:
- /*****************************************************************/
- /* ---- When there is database activity by users, we cycle in this
-@@ -2805,9 +2834,13 @@
- /* Sleep for 1 second on entrying the for loop below the first time. */
- next_itr_time = ut_time_ms() + 1000;
-
-+ skip_sleep = FALSE;
-+
- for (i = 0; i < 10; i++) {
- ulint cur_time = ut_time_ms();
-
-+ n_pages_flushed = 0; /* initialize */
-+
- /* ALTER TABLE in MySQL requires on Unix that the table handler
- can drop tables lazily after there no longer are SELECT
- queries to them. */
-@@ -2831,6 +2864,7 @@
- srv_main_thread_op_info = "sleeping";
- srv_main_1_second_loops++;
-
-+ if (!skip_sleep) {
- if (next_itr_time > cur_time
- && srv_shutdown_state == SRV_SHUTDOWN_NONE) {
-
-@@ -2841,10 +2875,26 @@
- (next_itr_time - cur_time)
- * 1000));
- srv_main_sleeps++;
-+
-+ /*
-+ mutex_enter(&(log_sys->mutex));
-+ oldest_lsn = buf_pool_get_oldest_modification();
-+ ib_uint64_t lsn = log_sys->lsn;
-+ mutex_exit(&(log_sys->mutex));
-+
-+ if(oldest_lsn)
-+ fprintf(stderr,
-+ "InnoDB flush: age pct: %lu, lsn progress: %lu\n",
-+ (lsn - oldest_lsn) * 100 / log_sys->max_checkpoint_age,
-+ lsn - lsn_old);
-+ */
- }
-
- /* Each iteration should happen at 1 second interval. */
- next_itr_time = ut_time_ms() + 1000;
-+ } /* if (!skip_sleep) */
-+
-+ skip_sleep = FALSE;
-
- /* Flush logs if needed */
- srv_sync_log_buffer_in_background();
-@@ -2864,7 +2914,7 @@
- if (n_pend_ios < SRV_PEND_IO_THRESHOLD
- && (n_ios - n_ios_old < SRV_RECENT_IO_ACTIVITY)) {
- srv_main_thread_op_info = "doing insert buffer merge";
-- ibuf_contract_for_n_pages(FALSE, PCT_IO(5));
-+ ibuf_contract_for_n_pages(FALSE, PCT_IBUF_IO(5));
-
- /* Flush logs if needed */
- srv_sync_log_buffer_in_background();
-@@ -2881,7 +2931,11 @@
- n_pages_flushed = buf_flush_list(
- PCT_IO(100), IB_ULONGLONG_MAX);
-
-- } else if (srv_adaptive_flushing) {
-+ mutex_enter(&(log_sys->mutex));
-+ lsn_old = log_sys->lsn;
-+ mutex_exit(&(log_sys->mutex));
-+ prev_adaptive_flushing_method = ULINT_UNDEFINED;
-+ } else if (srv_adaptive_flushing && srv_adaptive_flushing_method == 0) {
-
- /* Try to keep the rate of flushing of dirty
- pages such that redo log generation does not
-@@ -2897,6 +2951,224 @@
- n_flush,
- IB_ULONGLONG_MAX);
- }
-+
-+ mutex_enter(&(log_sys->mutex));
-+ lsn_old = log_sys->lsn;
-+ mutex_exit(&(log_sys->mutex));
-+ prev_adaptive_flushing_method = ULINT_UNDEFINED;
-+ } else if (srv_adaptive_flushing && srv_adaptive_flushing_method == 1) {
-+
-+ /* Try to keep modified age not to exceed
-+ max_checkpoint_age * 7/8 line */
-+
-+ mutex_enter(&(log_sys->mutex));
-+
-+ oldest_lsn = buf_pool_get_oldest_modification();
-+ if (oldest_lsn == 0) {
-+ lsn_old = log_sys->lsn;
-+ mutex_exit(&(log_sys->mutex));
-+
-+ } else {
-+ if ((log_sys->lsn - oldest_lsn)
-+ > (log_sys->max_checkpoint_age) - ((log_sys->max_checkpoint_age) / 8)) {
-+ /* LOG_POOL_PREFLUSH_RATIO_ASYNC is exceeded. */
-+ /* We should not flush from here. */
-+ lsn_old = log_sys->lsn;
-+ mutex_exit(&(log_sys->mutex));
-+ } else if ((log_sys->lsn - oldest_lsn)
-+ > (log_sys->max_checkpoint_age)/4 ) {
-+
-+ /* defence line (max_checkpoint_age * 1/2) */
-+ ib_uint64_t lsn = log_sys->lsn;
-+
-+ ib_uint64_t level, bpl;
-+ buf_page_t* bpage;
-+ ulint j;
-+
-+ mutex_exit(&(log_sys->mutex));
-+
-+ bpl = 0;
-+
-+ for (j = 0; j < srv_buf_pool_instances; j++) {
-+ buf_pool_t* buf_pool;
-+ ulint n_blocks;
-+
-+ buf_pool = buf_pool_from_array(j);
-+
-+ /* The scanning flush_list is optimistic here */
-+
-+ level = 0;
-+ n_blocks = 0;
-+ bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
-+
-+ while (bpage != NULL) {
-+ ib_uint64_t oldest_modification = bpage->oldest_modification;
-+ if (oldest_modification != 0) {
-+ level += log_sys->max_checkpoint_age
-+ - (lsn - oldest_modification);
-+ }
-+ bpage = UT_LIST_GET_NEXT(list, bpage);
-+ n_blocks++;
-+ }
-+
-+ if (level) {
-+ bpl += ((ib_uint64_t) n_blocks * n_blocks
-+ * (lsn - lsn_old)) / level;
-+ }
-+
-+ }
-+
-+ if (!srv_use_doublewrite_buf) {
-+ /* flush is faster than when doublewrite */
-+ bpl = (bpl * 7) / 8;
-+ }
-+
-+ if (bpl) {
-+retry_flush_batch:
-+ n_pages_flushed = buf_flush_list(bpl,
-+ oldest_lsn + (lsn - lsn_old));
-+ if (n_pages_flushed == ULINT_UNDEFINED) {
-+ os_thread_sleep(5000);
-+ goto retry_flush_batch;
-+ }
-+ }
-+
-+ lsn_old = lsn;
-+ /*
-+ fprintf(stderr,
-+ "InnoDB flush: age pct: %lu, lsn progress: %lu, blocks to flush:%llu\n",
-+ (lsn - oldest_lsn) * 100 / log_sys->max_checkpoint_age,
-+ lsn - lsn_old, bpl);
-+ */
-+ } else {
-+ lsn_old = log_sys->lsn;
-+ mutex_exit(&(log_sys->mutex));
-+ }
-+ }
-+ prev_adaptive_flushing_method = 1;
-+ } else if (srv_adaptive_flushing && srv_adaptive_flushing_method == 2) {
-+ buf_pool_t* buf_pool;
-+ buf_page_t* bpage;
-+ ib_uint64_t lsn;
-+ ulint j;
-+
-+ mutex_enter(&(log_sys->mutex));
-+ oldest_lsn = buf_pool_get_oldest_modification();
-+ lsn = log_sys->lsn;
-+ mutex_exit(&(log_sys->mutex));
-+
-+ /* upper loop/sec. (x10) */
-+ next_itr_time -= 900; /* 1000 - 900 == 100 */
-+ inner_loop++;
-+ if (inner_loop < 10) {
-+ i--;
-+ } else {
-+ inner_loop = 0;
-+ }
-+
-+ if (prev_adaptive_flushing_method == 2) {
-+ lint n_flush;
-+ lint blocks_sum;
-+ ulint new_blocks_sum, flushed_blocks_sum;
-+
-+ blocks_sum = new_blocks_sum = flushed_blocks_sum = 0;
-+
-+ /* prev_flush_info[j] should be the previous loop's */
-+ for (j = 0; j < srv_buf_pool_instances; j++) {
-+ lint blocks_num, new_blocks_num, flushed_blocks_num;
-+ ibool found;
-+
-+ buf_pool = buf_pool_from_array(j);
-+
-+ blocks_num = UT_LIST_GET_LEN(buf_pool->flush_list);
-+ bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
-+ new_blocks_num = 0;
-+
-+ found = FALSE;
-+ while (bpage != NULL) {
-+ if (prev_flush_info[j].space == bpage->space
-+ && prev_flush_info[j].offset == bpage->offset
-+ && prev_flush_info[j].oldest_modification
-+ == bpage->oldest_modification) {
-+ found = TRUE;
-+ break;
-+ }
-+ bpage = UT_LIST_GET_NEXT(list, bpage);
-+ new_blocks_num++;
-+ }
-+ if (!found) {
-+ new_blocks_num = blocks_num;
-+ }
-+
-+ flushed_blocks_num = new_blocks_num + prev_flush_info[j].count
-+ - blocks_num;
-+ if (flushed_blocks_num < 0) {
-+ flushed_blocks_num = 0;
-+ }
-+
-+ bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
-+
-+ prev_flush_info[j].count = UT_LIST_GET_LEN(buf_pool->flush_list);
-+ if (bpage) {
-+ prev_flush_info[j].space = bpage->space;
-+ prev_flush_info[j].offset = bpage->offset;
-+ prev_flush_info[j].oldest_modification = bpage->oldest_modification;
-+ } else {
-+ prev_flush_info[j].space = 0;
-+ prev_flush_info[j].offset = 0;
-+ prev_flush_info[j].oldest_modification = 0;
-+ }
-+
-+ new_blocks_sum += new_blocks_num;
-+ flushed_blocks_sum += flushed_blocks_num;
-+ blocks_sum += blocks_num;
-+ }
-+
-+ n_flush = blocks_sum * (lsn - lsn_old) / log_sys->max_modified_age_async;
-+ if (flushed_blocks_sum > n_pages_flushed_prev) {
-+ n_flush -= (flushed_blocks_sum - n_pages_flushed_prev);
-+ }
-+
-+ if (n_flush > 0) {
-+ n_flush++;
-+ n_pages_flushed = buf_flush_list(n_flush, oldest_lsn + (lsn - lsn_old));
-+ } else {
-+ n_pages_flushed = 0;
-+ }
-+ } else {
-+ /* store previous first pages of the flush_list */
-+ for (j = 0; j < srv_buf_pool_instances; j++) {
-+ buf_pool = buf_pool_from_array(j);
-+
-+ bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
-+
-+ prev_flush_info[j].count = UT_LIST_GET_LEN(buf_pool->flush_list);
-+ if (bpage) {
-+ prev_flush_info[j].space = bpage->space;
-+ prev_flush_info[j].offset = bpage->offset;
-+ prev_flush_info[j].oldest_modification = bpage->oldest_modification;
-+ } else {
-+ prev_flush_info[j].space = 0;
-+ prev_flush_info[j].offset = 0;
-+ prev_flush_info[j].oldest_modification = 0;
-+ }
-+ }
-+ n_pages_flushed = 0;
-+ }
-+
-+ lsn_old = lsn;
-+ prev_adaptive_flushing_method = 2;
-+ } else {
-+ mutex_enter(&(log_sys->mutex));
-+ lsn_old = log_sys->lsn;
-+ mutex_exit(&(log_sys->mutex));
-+ prev_adaptive_flushing_method = ULINT_UNDEFINED;
-+ }
-+
-+ if (n_pages_flushed == ULINT_UNDEFINED) {
-+ n_pages_flushed_prev = 0;
-+ } else {
-+ n_pages_flushed_prev = n_pages_flushed;
- }
-
- if (srv_activity_count == old_activity_count) {
-@@ -2945,12 +3217,12 @@
- even if the server were active */
-
- srv_main_thread_op_info = "doing insert buffer merge";
-- ibuf_contract_for_n_pages(FALSE, PCT_IO(5));
-+ ibuf_contract_for_n_pages(FALSE, PCT_IBUF_IO(5));
-
- /* Flush logs if needed */
- srv_sync_log_buffer_in_background();
-
-- if (srv_n_purge_threads == 0) {
-+ if (srv_n_purge_threads == 0 || (srv_shutdown_state > 0 && srv_n_threads_active[SRV_WORKER] == 0)) {
- srv_main_thread_op_info = "master purging";
-
- srv_master_do_purge();
-@@ -3028,7 +3300,7 @@
- }
- }
-
-- if (srv_n_purge_threads == 0) {
-+ if (srv_n_purge_threads == 0 || (srv_shutdown_state > 0 && srv_n_threads_active[SRV_WORKER] == 0)) {
- srv_main_thread_op_info = "master purging";
-
- srv_master_do_purge();
-@@ -3053,7 +3325,7 @@
- buf_flush_list below. Otherwise, the system favors
- clean pages over cleanup throughput. */
- n_bytes_merged = ibuf_contract_for_n_pages(FALSE,
-- PCT_IO(100));
-+ PCT_IBUF_IO(100));
- }
-
- srv_main_thread_op_info = "reserving kernel mutex";
-@@ -3193,6 +3465,7 @@
- srv_slot_t* slot;
- ulint retries = 0;
- ulint n_total_purged = ULINT_UNDEFINED;
-+ ulint next_itr_time;
-
- ut_a(srv_n_purge_threads == 1);
-
-@@ -3213,9 +3486,12 @@
-
- mutex_exit(&kernel_mutex);
-
-+ next_itr_time = ut_time_ms();
-+
- while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) {
-
- ulint n_pages_purged = 0;
-+ ulint cur_time;
-
- /* If there are very few records to purge or the last
- purge didn't purge any records then wait for activity.
-@@ -3262,6 +3538,16 @@
- } while (n_pages_purged > 0 && !srv_fast_shutdown);
-
- srv_sync_log_buffer_in_background();
-+
-+ cur_time = ut_time_ms();
-+ if (next_itr_time > cur_time) {
-+ os_thread_sleep(ut_min(1000000,
-+ (next_itr_time - cur_time)
-+ * 1000));
-+ next_itr_time = ut_time_ms() + 1000;
-+ } else {
-+ next_itr_time = cur_time + 1000;
-+ }
- }
-
- mutex_enter(&kernel_mutex);
---- a/storage/innobase/srv/srv0start.c
-+++ b/storage/innobase/srv/srv0start.c
-@@ -1237,6 +1237,9 @@
- } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DIRECT")) {
- srv_unix_file_flush_method = SRV_UNIX_O_DIRECT;
-
-+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "ALL_O_DIRECT")) {
-+ srv_unix_file_flush_method = SRV_UNIX_ALL_O_DIRECT;
-+
- } else if (0 == ut_strcmp(srv_file_flush_method_str, "littlesync")) {
- srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
-
---- a/storage/innobase/trx/trx0purge.c
-+++ b/storage/innobase/trx/trx0purge.c
-@@ -392,10 +392,10 @@
- trx_sys->rseg_history_len++;
- mutex_exit(&kernel_mutex);
-
-- if (!(trx_sys->rseg_history_len % srv_purge_batch_size)) {
-+// if (!(trx_sys->rseg_history_len % srv_purge_batch_size)) { /*should wake up always*/
- /* Inform the purge thread that there is work to do. */
- srv_wake_purge_thread_if_not_active();
-- }
-+// }
- }
-
- /**********************************************************************//**
---- a/storage/innobase/trx/trx0trx.c
-+++ b/storage/innobase/trx/trx0trx.c
-@@ -984,6 +984,7 @@
- trx->read_view = NULL;
-
- if (lsn) {
-+ ulint flush_log_at_trx_commit;
-
- mutex_exit(&kernel_mutex);
-
-@@ -992,6 +993,12 @@
- trx_undo_insert_cleanup(trx);
- }
-
-+ if (srv_use_global_flush_log_at_trx_commit) {
-+ flush_log_at_trx_commit = thd_flush_log_at_trx_commit(NULL);
-+ } else {
-+ flush_log_at_trx_commit = thd_flush_log_at_trx_commit(trx->mysql_thd);
-+ }
-+
- /* NOTE that we could possibly make a group commit more
- efficient here: call os_thread_yield here to allow also other
- trxs to come to commit! */
-@@ -1023,9 +1030,9 @@
- if (trx->flush_log_later) {
- /* Do nothing yet */
- trx->must_flush_log_later = TRUE;
-- } else if (srv_flush_log_at_trx_commit == 0) {
-+ } else if (flush_log_at_trx_commit == 0) {
- /* Do nothing */
-- } else if (srv_flush_log_at_trx_commit == 1) {
-+ } else if (flush_log_at_trx_commit == 1) {
- if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) {
- /* Write the log but do not flush it to disk */
-
-@@ -1037,7 +1044,7 @@
-
- log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE);
- }
-- } else if (srv_flush_log_at_trx_commit == 2) {
-+ } else if (flush_log_at_trx_commit == 2) {
-
- /* Write the log but do not flush it to disk */
-
-@@ -1701,16 +1708,23 @@
- trx_t* trx) /*!< in: trx handle */
- {
- ib_uint64_t lsn = trx->commit_lsn;
-+ ulint flush_log_at_trx_commit;
-
- ut_a(trx);
-
- trx->op_info = "flushing log";
-
-+ if (srv_use_global_flush_log_at_trx_commit) {
-+ flush_log_at_trx_commit = thd_flush_log_at_trx_commit(NULL);
-+ } else {
-+ flush_log_at_trx_commit = thd_flush_log_at_trx_commit(trx->mysql_thd);
-+ }
-+
- if (!trx->must_flush_log_later) {
- /* Do nothing */
-- } else if (srv_flush_log_at_trx_commit == 0) {
-+ } else if (flush_log_at_trx_commit == 0) {
- /* Do nothing */
-- } else if (srv_flush_log_at_trx_commit == 1) {
-+ } else if (flush_log_at_trx_commit == 1) {
- if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) {
- /* Write the log but do not flush it to disk */
-
-@@ -1721,7 +1735,7 @@
-
- log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE);
- }
-- } else if (srv_flush_log_at_trx_commit == 2) {
-+ } else if (flush_log_at_trx_commit == 2) {
-
- /* Write the log but do not flush it to disk */
-
-@@ -1969,6 +1983,8 @@
- /*--------------------------------------*/
-
- if (lsn) {
-+ ulint flush_log_at_trx_commit;
-+
- /* Depending on the my.cnf options, we may now write the log
- buffer to the log files, making the prepared state of the
- transaction durable if the OS does not crash. We may also
-@@ -1988,9 +2004,15 @@
-
- mutex_exit(&kernel_mutex);
-
-- if (srv_flush_log_at_trx_commit == 0) {
-+ if (srv_use_global_flush_log_at_trx_commit) {
-+ flush_log_at_trx_commit = thd_flush_log_at_trx_commit(NULL);
-+ } else {
-+ flush_log_at_trx_commit = thd_flush_log_at_trx_commit(trx->mysql_thd);
-+ }
-+
-+ if (flush_log_at_trx_commit == 0) {
- /* Do nothing */
-- } else if (srv_flush_log_at_trx_commit == 1) {
-+ } else if (flush_log_at_trx_commit == 1) {
- if (srv_unix_file_flush_method == SRV_UNIX_NOSYNC) {
- /* Write the log but do not flush it to disk */
-
-@@ -2002,7 +2024,7 @@
-
- log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE);
- }
-- } else if (srv_flush_log_at_trx_commit == 2) {
-+ } else if (flush_log_at_trx_commit == 2) {
-
- /* Write the log but do not flush it to disk */
-
---- a/mysql-test/include/default_mysqld.cnf
-+++ b/mysql-test/include/default_mysqld.cnf
-@@ -29,7 +29,7 @@
- max_heap_table_size= 1M
-
- loose-innodb_data_file_path= ibdata1:10M:autoextend
--loose-innodb_buffer_pool_size= 8M
-+loose-innodb_buffer_pool_size= 32M
- loose-innodb_write_io_threads= 2
- loose-innodb_read_io_threads= 2
- loose-innodb_log_buffer_size= 1M
---- a/mysql-test/suite/innodb/r/innodb.result
-+++ b/mysql-test/suite/innodb/r/innodb.result
-@@ -1678,7 +1678,7 @@
- drop table t1;
- SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_buffer_pool_pages_total';
- variable_value
--511
-+2047
- SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_page_size';
- variable_value
- 16384
---- /dev/null
-+++ b/mysql-test/suite/innodb/r/percona_flush_contiguous_neighbors.result
-@@ -0,0 +1,21 @@
-+DROP TABLE IF EXISTS t1;
-+CREATE TABLE t1 (id INT AUTO_INCREMENT, foo CHAR(255), PRIMARY KEY (id)) ENGINE=InnoDB;
-+INSERT INTO t1(foo) VALUES ('a'), ('b');
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/suite/innodb/t/percona_flush_contiguous_neighbors-master.opt
-@@ -0,0 +1 @@
-+--innodb_flush_neighbor_pages=cont
---- /dev/null
-+++ b/mysql-test/suite/innodb/t/percona_flush_contiguous_neighbors.test
-@@ -0,0 +1,36 @@
-+# Test for innodb_flush_neighbor_pages=contiguous.
-+# The test is very crude: we simply overflow the buffer pool with such a number of
-+# new/modified pages that some flushing is bound to happen.
-+
-+--source include/have_innodb.inc
-+
-+--disable_warnings
-+DROP TABLE IF EXISTS t1;
-+--enable_warnings
-+
-+CREATE TABLE t1 (id INT AUTO_INCREMENT, foo CHAR(255), PRIMARY KEY (id)) ENGINE=InnoDB;
-+
-+INSERT INTO t1(foo) VALUES ('a'), ('b');
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+
-+# TODO: cannot record a stable value here. A check of > 0 should be enough,
-+# but the variable is not accessible through INFORMATION_SCHEMA currently.
-+# SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_flushed';
-+
-+DROP TABLE t1;
---- a/mysql-test/suite/innodb/t/innodb_cmp_drop_table-master.opt
-+++ b/mysql-test/suite/innodb/t/innodb_cmp_drop_table-master.opt
-@@ -1 +1 @@
----innodb-buffer-pool-size=8M
-+--innodb-buffer-pool-size=32M
---- a/mysql-test/suite/innodb/t/innodb_cmp_drop_table.test
-+++ b/mysql-test/suite/innodb/t/innodb_cmp_drop_table.test
-@@ -36,13 +36,14 @@
-
- -- disable_query_log
-
---- let $i = 400
-+-- let $i = 4000
-+begin;
- while ($i)
- {
- insert into t2 values(repeat('abcdefghijklmnopqrstuvwxyz',1000));
- dec $i;
- }
--
-+commit;
- -- enable_query_log
-
- # now there should be no 8K pages in the buffer pool
+++ /dev/null
-# name : innodb_kill_idle_transaction.patch
-# introduced : 5.5.15
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/include/mysql/plugin.h
-+++ b/include/mysql/plugin.h
-@@ -634,6 +634,12 @@
- */
- void thd_set_ha_data(MYSQL_THD thd, const struct handlerton *hton,
- const void *ha_data);
-+
-+int thd_command(const MYSQL_THD thd);
-+long long thd_start_time(const MYSQL_THD thd);
-+void thd_kill(unsigned long id);
-+#define EXTENDED_FOR_KILLIDLE
-+
- #ifdef __cplusplus
- }
- #endif
---- a/include/mysql/plugin_audit.h.pp
-+++ b/include/mysql/plugin_audit.h.pp
-@@ -196,6 +196,9 @@
- void *thd_get_ha_data(const void* thd, const struct handlerton *hton);
- void thd_set_ha_data(void* thd, const struct handlerton *hton,
- const void *ha_data);
-+int thd_command(const void* thd);
-+long long thd_start_time(const void* thd);
-+void thd_kill(unsigned long id);
- struct mysql_event_general
- {
- unsigned int event_subclass;
---- a/include/mysql/plugin_auth.h.pp
-+++ b/include/mysql/plugin_auth.h.pp
-@@ -196,6 +196,9 @@
- void *thd_get_ha_data(const void* thd, const struct handlerton *hton);
- void thd_set_ha_data(void* thd, const struct handlerton *hton,
- const void *ha_data);
-+int thd_command(const void* thd);
-+long long thd_start_time(const void* thd);
-+void thd_kill(unsigned long id);
- #include <mysql/plugin_auth_common.h>
- typedef struct st_plugin_vio_info
- {
---- a/include/mysql/plugin_ftparser.h.pp
-+++ b/include/mysql/plugin_ftparser.h.pp
-@@ -149,6 +149,9 @@
- void *thd_get_ha_data(const void* thd, const struct handlerton *hton);
- void thd_set_ha_data(void* thd, const struct handlerton *hton,
- const void *ha_data);
-+int thd_command(const void* thd);
-+long long thd_start_time(const void* thd);
-+void thd_kill(unsigned long id);
- enum enum_ftparser_mode
- {
- MYSQL_FTPARSER_SIMPLE_MODE= 0,
---- a/sql/sql_class.cc
-+++ b/sql/sql_class.cc
-@@ -713,6 +713,42 @@
- return buffer;
- }
-
-+/* extend for kill session of idle transaction from engine */
-+extern "C"
-+int thd_command(const THD* thd)
-+{
-+ return (int) thd->command;
-+}
-+
-+extern "C"
-+long long thd_start_time(const THD* thd)
-+{
-+ return (long long) thd->start_time;
-+}
-+
-+extern "C"
-+void thd_kill(ulong id)
-+{
-+ THD *tmp;
-+ mysql_mutex_lock(&LOCK_thread_count);
-+ I_List_iterator<THD> it(threads);
-+ while ((tmp=it++))
-+ {
-+ if (tmp->command == COM_DAEMON)
-+ continue;
-+ if (tmp->thread_id == id)
-+ {
-+ mysql_mutex_lock(&tmp->LOCK_thd_data);
-+ break;
-+ }
-+ }
-+ mysql_mutex_unlock(&LOCK_thread_count);
-+ if (tmp)
-+ {
-+ tmp->awake(THD::KILL_CONNECTION);
-+ mysql_mutex_unlock(&tmp->LOCK_thd_data);
-+ }
-+}
-
- /**
- Implementation of Drop_table_error_handler::handle_condition().
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -2860,6 +2860,10 @@
-
- innobase_commit_concurrency_init_default();
-
-+#ifndef EXTENDED_FOR_KILLIDLE
-+ srv_kill_idle_transaction = 0;
-+#endif
-+
- #ifdef HAVE_PSI_INTERFACE
- /* Register keys with MySQL performance schema */
- if (PSI_server) {
-@@ -11694,6 +11698,57 @@
- return(false);
- }
-
-+/***********************************************************************
-+functions for kill session of idle transaction */
-+extern "C"
-+ibool
-+innobase_thd_is_idle(
-+/*=================*/
-+ const void* thd) /*!< in: thread handle (THD*) */
-+{
-+#ifdef EXTENDED_FOR_KILLIDLE
-+ return(thd_command((const THD*) thd) == COM_SLEEP);
-+#else
-+ return(FALSE);
-+#endif
-+}
-+
-+extern "C"
-+ib_int64_t
-+innobase_thd_get_start_time(
-+/*========================*/
-+ const void* thd) /*!< in: thread handle (THD*) */
-+{
-+#ifdef EXTENDED_FOR_KILLIDLE
-+ return((ib_int64_t)thd_start_time((const THD*) thd));
-+#else
-+ return(0); /*dummy value*/
-+#endif
-+}
-+
-+extern "C"
-+void
-+innobase_thd_kill(
-+/*==============*/
-+ ulong thd_id)
-+{
-+#ifdef EXTENDED_FOR_KILLIDLE
-+ thd_kill(thd_id);
-+#else
-+ return;
-+#endif
-+}
-+
-+extern "C"
-+ulong
-+innobase_thd_get_thread_id(
-+/*=======================*/
-+ const void* thd)
-+{
-+ return(thd_get_thread_id((const THD*) thd));
-+}
-+
-+
- static SHOW_VAR innodb_status_variables_export[]= {
- {"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
- {NullS, NullS, SHOW_LONG}
-@@ -11985,6 +12040,15 @@
- "Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
- NULL, NULL, 500L, 1L, ~0L, 0);
-
-+static MYSQL_SYSVAR_LONG(kill_idle_transaction, srv_kill_idle_transaction,
-+ PLUGIN_VAR_RQCMDARG,
-+#ifdef EXTENDED_FOR_KILLIDLE
-+ "If non-zero value, the idle session with transaction which is idle over the value in seconds is killed by InnoDB.",
-+#else
-+ "No effect for this build.",
-+#endif
-+ NULL, NULL, 0, 0, LONG_MAX, 0);
-+
- static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR,
- "Number of file I/O threads in InnoDB.",
-@@ -12327,6 +12391,7 @@
- MYSQL_SYSVAR(fast_checksum),
- MYSQL_SYSVAR(commit_concurrency),
- MYSQL_SYSVAR(concurrency_tickets),
-+ MYSQL_SYSVAR(kill_idle_transaction),
- MYSQL_SYSVAR(data_file_path),
- MYSQL_SYSVAR(doublewrite_file),
- MYSQL_SYSVAR(data_home_dir),
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -299,6 +299,7 @@
- extern ulint srv_activity_count;
- extern ulint srv_fatal_semaphore_wait_threshold;
- extern ulint srv_dml_needed_delay;
-+extern lint srv_kill_idle_transaction;
-
- extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
- query threads, and lock table: we allocate
---- a/storage/innobase/include/trx0trx.h
-+++ b/storage/innobase/include/trx0trx.h
-@@ -594,6 +594,8 @@
- replication has processed */
- const char* mysql_relay_log_file_name;
- ib_int64_t mysql_relay_log_pos;
-+ time_t idle_start;
-+ ib_int64_t last_stmt_start;
- /*------------------------------*/
- ulint n_mysql_tables_in_use; /* number of Innobase tables
- used in the processing of the current
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -87,6 +87,12 @@
- #include "mysql/plugin.h"
- #include "mysql/service_thd_wait.h"
-
-+/* prototypes of new functions added to ha_innodb.cc for kill_idle_transaction */
-+ibool innobase_thd_is_idle(const void* thd);
-+ib_int64_t innobase_thd_get_start_time(const void* thd);
-+void innobase_thd_kill(ulong thd_id);
-+ulong innobase_thd_get_thread_id(const void* thd);
-+
- /* prototypes for new functions added to ha_innodb.cc */
- ibool innobase_get_slow_log();
-
-@@ -97,6 +103,9 @@
- /* The following is the maximum allowed duration of a lock wait. */
- UNIV_INTERN ulint srv_fatal_semaphore_wait_threshold = 600;
-
-+/**/
-+UNIV_INTERN lint srv_kill_idle_transaction = 0;
-+
- /* How much data manipulation language (DML) statements need to be delayed,
- in microseconds, in order to reduce the lagging of the purge thread. */
- UNIV_INTERN ulint srv_dml_needed_delay = 0;
-@@ -2837,6 +2846,36 @@
- old_sema = sema;
- }
-
-+ if (srv_kill_idle_transaction && trx_sys) {
-+ trx_t* trx;
-+ time_t now;
-+rescan_idle:
-+ now = time(NULL);
-+ mutex_enter(&kernel_mutex);
-+ trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
-+ while (trx) {
-+ if (trx->conc_state == TRX_ACTIVE
-+ && trx->mysql_thd
-+ && innobase_thd_is_idle(trx->mysql_thd)) {
-+ ib_int64_t start_time = innobase_thd_get_start_time(trx->mysql_thd);
-+ ulong thd_id = innobase_thd_get_thread_id(trx->mysql_thd);
-+
-+ if (trx->last_stmt_start != start_time) {
-+ trx->idle_start = now;
-+ trx->last_stmt_start = start_time;
-+ } else if (difftime(now, trx->idle_start)
-+ > srv_kill_idle_transaction) {
-+ /* kill the session */
-+ mutex_exit(&kernel_mutex);
-+ innobase_thd_kill(thd_id);
-+ goto rescan_idle;
-+ }
-+ }
-+ trx = UT_LIST_GET_NEXT(mysql_trx_list, trx);
-+ }
-+ mutex_exit(&kernel_mutex);
-+ }
-+
- /* Flush stderr so that a database user gets the output
- to possible MySQL error file */
-
---- a/storage/innobase/trx/trx0trx.c
-+++ b/storage/innobase/trx/trx0trx.c
-@@ -143,6 +143,9 @@
- trx->mysql_relay_log_file_name = "";
- trx->mysql_relay_log_pos = 0;
-
-+ trx->idle_start = 0;
-+ trx->last_stmt_start = 0;
-+
- mutex_create(trx_undo_mutex_key, &trx->undo_mutex, SYNC_TRX_UNDO);
-
- trx->rseg = NULL;
---- /dev/null
-+++ b/mysql-test/r/percona_innodb_kill_idle_trx.result
-@@ -0,0 +1,41 @@
-+DROP TABLE IF EXISTS t1;
-+SET autocommit=0;
-+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
-+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
-+Variable_name Value
-+innodb_kill_idle_transaction 0
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
-+VARIABLE_NAME VARIABLE_VALUE
-+INNODB_KILL_IDLE_TRANSACTION 0
-+SET GLOBAL innodb_kill_idle_transaction=1;
-+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
-+Variable_name Value
-+innodb_kill_idle_transaction 1
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
-+VARIABLE_NAME VARIABLE_VALUE
-+INNODB_KILL_IDLE_TRANSACTION 1
-+BEGIN;
-+INSERT INTO t1 VALUES (1),(2),(3);
-+COMMIT;
-+SELECT * FROM t1;
-+a
-+1
-+2
-+3
-+BEGIN;
-+INSERT INTO t1 VALUES (4),(5),(6);
-+SELECT * FROM t1;
-+ERROR HY000: MySQL server has gone away
-+SELECT * FROM t1;
-+a
-+1
-+2
-+3
-+DROP TABLE t1;
-+SET GLOBAL innodb_kill_idle_transaction=0;
-+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
-+Variable_name Value
-+innodb_kill_idle_transaction 0
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
-+VARIABLE_NAME VARIABLE_VALUE
-+INNODB_KILL_IDLE_TRANSACTION 0
---- /dev/null
-+++ b/mysql-test/r/percona_innodb_kill_idle_trx_locks.result
-@@ -0,0 +1,45 @@
-+DROP TABLE IF EXISTS t1;
-+SET autocommit=0;
-+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
-+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
-+Variable_name Value
-+innodb_kill_idle_transaction 0
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
-+VARIABLE_NAME VARIABLE_VALUE
-+INNODB_KILL_IDLE_TRANSACTION 0
-+SET GLOBAL innodb_kill_idle_transaction=5;
-+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
-+Variable_name Value
-+innodb_kill_idle_transaction 5
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
-+VARIABLE_NAME VARIABLE_VALUE
-+INNODB_KILL_IDLE_TRANSACTION 5
-+BEGIN;
-+INSERT INTO t1 VALUES (1),(2),(3);
-+COMMIT;
-+SELECT * FROM t1;
-+a
-+1
-+2
-+3
-+### Locking rows. Lock should be released when idle trx is killed.
-+BEGIN;
-+SELECT * FROM t1 FOR UPDATE;
-+a
-+1
-+2
-+3
-+UPDATE t1 set a=4;
-+SELECT * FROM t1;
-+a
-+4
-+4
-+4
-+DROP TABLE t1;
-+SET GLOBAL innodb_kill_idle_transaction=0;
-+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
-+Variable_name Value
-+innodb_kill_idle_transaction 0
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
-+VARIABLE_NAME VARIABLE_VALUE
-+INNODB_KILL_IDLE_TRANSACTION 0
---- /dev/null
-+++ b/mysql-test/t/percona_innodb_kill_idle_trx.test
-@@ -0,0 +1,28 @@
-+--source include/have_innodb.inc
-+--disable_warnings
-+DROP TABLE IF EXISTS t1;
-+--enable_warnings
-+
-+SET autocommit=0;
-+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
-+
-+--source include/percona_innodb_kill_idle_trx_show.inc
-+SET GLOBAL innodb_kill_idle_transaction=1;
-+--source include/percona_innodb_kill_idle_trx_show.inc
-+
-+BEGIN;
-+INSERT INTO t1 VALUES (1),(2),(3);
-+COMMIT;
-+SELECT * FROM t1;
-+
-+BEGIN;
-+INSERT INTO t1 VALUES (4),(5),(6);
-+sleep 3;
-+
-+--enable_reconnect
-+--error 2006 --error CR_SERVER_GONE_ERROR
-+SELECT * FROM t1;
-+SELECT * FROM t1;
-+DROP TABLE t1;
-+SET GLOBAL innodb_kill_idle_transaction=0;
-+--source include/percona_innodb_kill_idle_trx_show.inc
---- /dev/null
-+++ b/mysql-test/t/percona_innodb_kill_idle_trx_locks.test
-@@ -0,0 +1,31 @@
-+--source include/have_innodb.inc
-+--disable_warnings
-+DROP TABLE IF EXISTS t1;
-+--enable_warnings
-+
-+SET autocommit=0;
-+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
-+
-+--source include/percona_innodb_kill_idle_trx_show.inc
-+SET GLOBAL innodb_kill_idle_transaction=5;
-+--source include/percona_innodb_kill_idle_trx_show.inc
-+
-+connect (conn1,localhost,root,,);
-+connection conn1;
-+
-+BEGIN;
-+INSERT INTO t1 VALUES (1),(2),(3);
-+COMMIT;
-+SELECT * FROM t1;
-+
-+--echo ### Locking rows. Lock should be released when idle trx is killed.
-+BEGIN;
-+SELECT * FROM t1 FOR UPDATE;
-+
-+connection default;
-+UPDATE t1 set a=4;
-+
-+SELECT * FROM t1;
-+DROP TABLE t1;
-+SET GLOBAL innodb_kill_idle_transaction=0;
-+--source include/percona_innodb_kill_idle_trx_show.inc
---- /dev/null
-+++ b/mysql-test/include/percona_innodb_kill_idle_trx_show.inc
-@@ -0,0 +1,2 @@
-+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
+++ /dev/null
-# name : innodb_lru_dump_restore.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/buf/buf0lru.c
-+++ b/storage/innobase/buf/buf0lru.c
-@@ -2197,6 +2197,289 @@
- memset(&buf_LRU_stat_cur, 0, sizeof buf_LRU_stat_cur);
- }
-
-+/********************************************************************//**
-+Dump the LRU page list to the specific file. */
-+#define LRU_DUMP_FILE "ib_lru_dump"
-+
-+UNIV_INTERN
-+ibool
-+buf_LRU_file_dump(void)
-+/*===================*/
-+{
-+ os_file_t dump_file = -1;
-+ ibool success;
-+ byte* buffer_base = NULL;
-+ byte* buffer = NULL;
-+ buf_page_t* bpage;
-+ ulint buffers;
-+ ulint offset;
-+ ibool ret = FALSE;
-+ ulint i;
-+
-+ for (i = 0; i < srv_n_data_files; i++) {
-+ if (strstr(srv_data_file_names[i], LRU_DUMP_FILE) != NULL) {
-+ fprintf(stderr,
-+ " InnoDB: The name '%s' seems to be used for"
-+ " innodb_data_file_path. For safety, dumping of the LRU list"
-+ " is not being done.\n", LRU_DUMP_FILE);
-+ goto end;
-+ }
-+ }
-+
-+ buffer_base = ut_malloc(2 * UNIV_PAGE_SIZE);
-+ buffer = ut_align(buffer_base, UNIV_PAGE_SIZE);
-+ if (!buffer) {
-+ fprintf(stderr,
-+ " InnoDB: cannot allocate buffer.\n");
-+ goto end;
-+ }
-+
-+ dump_file = os_file_create(innodb_file_temp_key, LRU_DUMP_FILE, OS_FILE_OVERWRITE,
-+ OS_FILE_NORMAL, OS_DATA_FILE, &success);
-+ if (!success) {
-+ os_file_get_last_error(TRUE);
-+ fprintf(stderr,
-+ " InnoDB: cannot open %s\n", LRU_DUMP_FILE);
-+ goto end;
-+ }
-+
-+ buffers = offset = 0;
-+
-+ for (i = 0; i < srv_buf_pool_instances; i++) {
-+ buf_pool_t* buf_pool;
-+
-+ buf_pool = buf_pool_from_array(i);
-+
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ bpage = UT_LIST_GET_LAST(buf_pool->LRU);
-+
-+ while (bpage != NULL) {
-+ if (offset == 0) {
-+ memset(buffer, 0, UNIV_PAGE_SIZE);
-+ }
-+
-+ mach_write_to_4(buffer + offset * 4, bpage->space);
-+ offset++;
-+ mach_write_to_4(buffer + offset * 4, bpage->offset);
-+ offset++;
-+
-+ if (offset == UNIV_PAGE_SIZE/4) {
-+ success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
-+ (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
-+ (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
-+ UNIV_PAGE_SIZE);
-+ if (!success) {
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ fprintf(stderr,
-+ " InnoDB: cannot write page %lu of %s\n",
-+ buffers, LRU_DUMP_FILE);
-+ goto end;
-+ }
-+ buffers++;
-+ offset = 0;
-+ }
-+
-+ bpage = UT_LIST_GET_PREV(LRU, bpage);
-+ }
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ }
-+
-+ if (offset == 0) {
-+ memset(buffer, 0, UNIV_PAGE_SIZE);
-+ }
-+
-+ mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
-+ offset++;
-+ mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
-+ offset++;
-+
-+ success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
-+ (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
-+ (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
-+ UNIV_PAGE_SIZE);
-+ if (!success) {
-+ goto end;
-+ }
-+
-+ ret = TRUE;
-+end:
-+ if (dump_file != -1)
-+ os_file_close(dump_file);
-+ if (buffer_base)
-+ ut_free(buffer_base);
-+
-+ return(ret);
-+}
-+
-+typedef struct {
-+ ib_uint32_t space_id;
-+ ib_uint32_t page_no;
-+} dump_record_t;
-+
-+static int dump_record_cmp(const void *a, const void *b)
-+{
-+ const dump_record_t *rec1 = (dump_record_t *) a;
-+ const dump_record_t *rec2 = (dump_record_t *) b;
-+
-+ if (rec1->space_id < rec2->space_id)
-+ return -1;
-+ if (rec1->space_id > rec2->space_id)
-+ return 1;
-+ if (rec1->page_no < rec2->page_no)
-+ return -1;
-+ return rec1->page_no > rec2->page_no;
-+}
-+
-+/********************************************************************//**
-+Read the pages based on the specific file.*/
-+UNIV_INTERN
-+ibool
-+buf_LRU_file_restore(void)
-+/*======================*/
-+{
-+ os_file_t dump_file = -1;
-+ ibool success;
-+ byte* buffer_base = NULL;
-+ byte* buffer = NULL;
-+ ulint buffers;
-+ ulint offset;
-+ ulint reads = 0;
-+ ulint req = 0;
-+ ibool terminated = FALSE;
-+ ibool ret = FALSE;
-+ dump_record_t* records = NULL;
-+ ulint size;
-+ ulint size_high;
-+ ulint length;
-+
-+ dump_file = os_file_create_simple_no_error_handling(innodb_file_temp_key,
-+ LRU_DUMP_FILE, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
-+ if (!success || !os_file_get_size(dump_file, &size, &size_high)) {
-+ os_file_get_last_error(TRUE);
-+ fprintf(stderr,
-+ " InnoDB: cannot open %s\n", LRU_DUMP_FILE);
-+ goto end;
-+ }
-+
-+ ut_print_timestamp(stderr);
-+ fprintf(stderr, " InnoDB: Restoring buffer pool pages from %s\n",
-+ LRU_DUMP_FILE);
-+
-+ if (size == 0 || size_high > 0 || size % 8) {
-+ fprintf(stderr, " InnoDB: broken LRU dump file\n");
-+ goto end;
-+ }
-+ buffer_base = ut_malloc(2 * UNIV_PAGE_SIZE);
-+ buffer = ut_align(buffer_base, UNIV_PAGE_SIZE);
-+ records = ut_malloc(size);
-+ if (!buffer || !records) {
-+ fprintf(stderr,
-+ " InnoDB: cannot allocate buffer.\n");
-+ goto end;
-+ }
-+
-+ buffers = 0;
-+ length = 0;
-+ while (!terminated) {
-+ success = os_file_read(dump_file, buffer,
-+ (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
-+ (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
-+ UNIV_PAGE_SIZE);
-+ if (!success) {
-+ fprintf(stderr,
-+ " InnoDB: either could not read page %lu of %s,"
-+ " or terminated unexpectedly.\n",
-+ buffers, LRU_DUMP_FILE);
-+ goto end;
-+ }
-+
-+ for (offset = 0; offset < UNIV_PAGE_SIZE/4; offset += 2) {
-+ ulint space_id;
-+ ulint page_no;
-+
-+ space_id = mach_read_from_4(buffer + offset * 4);
-+ page_no = mach_read_from_4(buffer + (offset + 1) * 4);
-+ if (space_id == 0xFFFFFFFFUL
-+ || page_no == 0xFFFFFFFFUL) {
-+ terminated = TRUE;
-+ break;
-+ }
-+
-+ records[length].space_id = space_id;
-+ records[length].page_no = page_no;
-+ length++;
-+ if (length * 8 >= size) {
-+ fprintf(stderr,
-+ " InnoDB: could not find the "
-+ "end-of-file marker after reading "
-+ "the expected %lu bytes from the "
-+ "LRU dump file.\n"
-+ " InnoDB: this could be caused by a "
-+ "broken or incomplete file.\n"
-+ " InnoDB: trying to process what has "
-+ "been read so far.\n",
-+ size);
-+ terminated= TRUE;
-+ break;
-+ }
-+ }
-+ buffers++;
-+ }
-+
-+ qsort(records, length, sizeof(dump_record_t), dump_record_cmp);
-+
-+ for (offset = 0; offset < length; offset++) {
-+ ulint space_id;
-+ ulint page_no;
-+ ulint zip_size;
-+ ulint err;
-+ ib_int64_t tablespace_version;
-+
-+ space_id = records[offset].space_id;
-+ page_no = records[offset].page_no;
-+
-+ if (offset % 16 == 15) {
-+ os_aio_simulated_wake_handler_threads();
-+ buf_flush_free_margins(FALSE);
-+ }
-+
-+ zip_size = fil_space_get_zip_size(space_id);
-+ if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
-+ continue;
-+ }
-+
-+ if (fil_is_exist(space_id, page_no)) {
-+
-+ tablespace_version = fil_space_get_version(space_id);
-+
-+ req++;
-+ reads += buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE
-+ | OS_AIO_SIMULATED_WAKE_LATER,
-+ space_id, zip_size, TRUE,
-+ tablespace_version, page_no, NULL);
-+ buf_LRU_stat_inc_io();
-+ }
-+ }
-+
-+ os_aio_simulated_wake_handler_threads();
-+ buf_flush_free_margins(FALSE);
-+
-+ ut_print_timestamp(stderr);
-+ fprintf(stderr,
-+ " InnoDB: Completed reading buffer pool pages"
-+ " (requested: %lu, read: %lu)\n", req, reads);
-+ ret = TRUE;
-+end:
-+ if (dump_file != -1)
-+ os_file_close(dump_file);
-+ if (buffer_base)
-+ ut_free(buffer_base);
-+ if (records)
-+ ut_free(records);
-+
-+ return(ret);
-+}
-+
- #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
- /**********************************************************************//**
- Validates the LRU list for one buffer pool instance. */
---- a/storage/innobase/buf/buf0rea.c
-+++ b/storage/innobase/buf/buf0rea.c
-@@ -60,7 +60,7 @@
- which case it is never read into the pool, or if the tablespace does
- not exist or is being dropped
- @return 1 if read request is issued. 0 if it is not */
--static
-+UNIV_INTERN
- ulint
- buf_read_page_low(
- /*==============*/
---- a/storage/innobase/fil/fil0fil.c
-+++ b/storage/innobase/fil/fil0fil.c
-@@ -5307,6 +5307,70 @@
- return(DB_SUCCESS);
- }
-
-+/********************************************************************//**
-+Confirm whether the parameters are valid or not */
-+UNIV_INTERN
-+ibool
-+fil_is_exist(
-+/*==============*/
-+ ulint space_id, /*!< in: space id */
-+ ulint block_offset) /*!< in: offset in number of blocks */
-+{
-+ fil_space_t* space;
-+ fil_node_t* node;
-+
-+ /* Reserve the fil_system mutex and make sure that we can open at
-+ least one file while holding it, if the file is not already open */
-+
-+ fil_mutex_enter_and_prepare_for_io(space_id);
-+
-+ space = fil_space_get_by_id(space_id);
-+
-+ if (!space) {
-+ mutex_exit(&fil_system->mutex);
-+ return(FALSE);
-+ }
-+
-+ node = UT_LIST_GET_FIRST(space->chain);
-+
-+ for (;;) {
-+ if (UNIV_UNLIKELY(node == NULL)) {
-+ mutex_exit(&fil_system->mutex);
-+ return(FALSE);
-+ }
-+
-+ if (space->id != 0 && node->size == 0) {
-+ /* We do not know the size of a single-table tablespace
-+ before we open the file */
-+
-+ break;
-+ }
-+
-+ if (node->size > block_offset) {
-+ /* Found! */
-+ break;
-+ } else {
-+ block_offset -= node->size;
-+ node = UT_LIST_GET_NEXT(chain, node);
-+ }
-+ }
-+
-+ /* Open file if closed */
-+ fil_node_prepare_for_io(node, fil_system, space);
-+ fil_node_complete_io(node, fil_system, OS_FILE_READ);
-+
-+ /* Check that at least the start offset is within the bounds of a
-+ single-table tablespace */
-+ if (UNIV_UNLIKELY(node->size <= block_offset)
-+ && space->id != 0 && space->purpose == FIL_TABLESPACE) {
-+ mutex_exit(&fil_system->mutex);
-+ return(FALSE);
-+ }
-+
-+ mutex_exit(&fil_system->mutex);
-+ return(TRUE);
-+}
-+
- #ifndef UNIV_HOTBACKUP
- /**********************************************************************//**
- Waits for an aio operation to complete. This function is used to write the
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -196,6 +196,8 @@
-
- static char* innodb_version_str = (char*) INNODB_VERSION_STR;
-
-+static my_bool innobase_blocking_lru_restore = FALSE;
-+
- /** Possible values for system variable "innodb_stats_method". The values
- are defined the same as its corresponding MyISAM system variable
- "myisam_stats_method"(see "myisam_stats_method_names"), for better usability */
-@@ -2652,6 +2654,8 @@
- srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
- srv_use_checksums = (ibool) innobase_use_checksums;
-
-+ srv_blocking_lru_restore = (ibool) innobase_blocking_lru_restore;
-+
- #ifdef HAVE_LARGE_PAGES
- if ((os_use_large_pages = (ibool) my_use_large_pages))
- os_large_page_size = (ulint) opt_large_page_size;
-@@ -11964,6 +11968,19 @@
- "Limit the allocated memory for dictionary cache. (0: unlimited)",
- NULL, NULL, 0, 0, LONG_MAX, 0);
-
-+static MYSQL_SYSVAR_UINT(buffer_pool_restore_at_startup, srv_auto_lru_dump,
-+ PLUGIN_VAR_RQCMDARG,
-+ "Time in seconds between automatic buffer pool dumps. "
-+ "0 (the default) disables automatic dumps.",
-+ NULL, NULL, 0, 0, UINT_MAX32, 0);
-+
-+static MYSQL_SYSVAR_BOOL(blocking_buffer_pool_restore,
-+ innobase_blocking_lru_restore,
-+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
-+ "Block XtraDB startup process until buffer pool is full restored from a "
-+ "dump file (if present). Disabled by default.",
-+ NULL, NULL, FALSE);
-+
- static struct st_mysql_sys_var* innobase_system_variables[]= {
- MYSQL_SYSVAR(additional_mem_pool_size),
- MYSQL_SYSVAR(autoextend_increment),
-@@ -12048,6 +12065,8 @@
- MYSQL_SYSVAR(random_read_ahead),
- MYSQL_SYSVAR(read_ahead_threshold),
- MYSQL_SYSVAR(io_capacity),
-+ MYSQL_SYSVAR(buffer_pool_restore_at_startup),
-+ MYSQL_SYSVAR(blocking_buffer_pool_restore),
- MYSQL_SYSVAR(purge_threads),
- MYSQL_SYSVAR(purge_batch_size),
- MYSQL_SYSVAR(rollback_segments),
---- a/storage/innobase/handler/i_s.cc
-+++ b/storage/innobase/handler/i_s.cc
-@@ -50,6 +50,7 @@
- #include "trx0rseg.h" /* for trx_rseg_struct */
- #include "trx0sys.h" /* for trx_sys */
- #include "dict0dict.h" /* for dict_sys */
-+#include "buf0lru.h" /* for XTRA_LRU_[DUMP/RESTORE] */
- }
-
- #define OK(expr) \
-@@ -4336,6 +4337,36 @@
- "Hello!");
- goto end_func;
- }
-+ else if (!strncasecmp("XTRA_LRU_DUMP", ptr, 13)) {
-+ ut_print_timestamp(stderr);
-+ fprintf(stderr, " InnoDB: Administrative command 'XTRA_LRU_DUMP'"
-+ " was detected.\n");
-+
-+ if (buf_LRU_file_dump()) {
-+ field_store_string(i_s_table->field[0],
-+ "XTRA_LRU_DUMP was succeeded.");
-+ } else {
-+ field_store_string(i_s_table->field[0],
-+ "XTRA_LRU_DUMP was failed.");
-+ }
-+
-+ goto end_func;
-+ }
-+ else if (!strncasecmp("XTRA_LRU_RESTORE", ptr, 16)) {
-+ ut_print_timestamp(stderr);
-+ fprintf(stderr, " InnoDB: Administrative command 'XTRA_LRU_RESTORE'"
-+ " was detected.\n");
-+
-+ if (buf_LRU_file_restore()) {
-+ field_store_string(i_s_table->field[0],
-+ "XTRA_LRU_RESTORE was succeeded.");
-+ } else {
-+ field_store_string(i_s_table->field[0],
-+ "XTRA_LRU_RESTORE was failed.");
-+ }
-+
-+ goto end_func;
-+ }
-
- field_store_string(i_s_table->field[0],
- "Undefined XTRA_* command.");
---- a/storage/innobase/include/buf0lru.h
-+++ b/storage/innobase/include/buf0lru.h
-@@ -204,6 +204,18 @@
- void
- buf_LRU_stat_update(void);
- /*=====================*/
-+/********************************************************************//**
-+Dump the LRU page list to the specific file. */
-+UNIV_INTERN
-+ibool
-+buf_LRU_file_dump(void);
-+/*===================*/
-+/********************************************************************//**
-+Read the pages based on the specific file.*/
-+UNIV_INTERN
-+ibool
-+buf_LRU_file_restore(void);
-+/*======================*/
-
- /******************************************************************//**
- Remove one page from LRU list and put it to free list */
---- a/storage/innobase/include/buf0rea.h
-+++ b/storage/innobase/include/buf0rea.h
-@@ -31,6 +31,37 @@
- #include "buf0types.h"
-
- /********************************************************************//**
-+Low-level function which reads a page asynchronously from a file to the
-+buffer buf_pool if it is not already there, in which case does nothing.
-+Sets the io_fix flag and sets an exclusive lock on the buffer frame. The
-+flag is cleared and the x-lock released by an i/o-handler thread.
-+@return 1 if a read request was queued, 0 if the page already resided
-+in buf_pool, or if the page is in the doublewrite buffer blocks in
-+which case it is never read into the pool, or if the tablespace does
-+not exist or is being dropped
-+@return 1 if read request is issued. 0 if it is not */
-+UNIV_INTERN
-+ulint
-+buf_read_page_low(
-+/*==============*/
-+ ulint* err, /*!< out: DB_SUCCESS or DB_TABLESPACE_DELETED if we are
-+ trying to read from a non-existent tablespace, or a
-+ tablespace which is just now being dropped */
-+ ibool sync, /*!< in: TRUE if synchronous aio is desired */
-+ ulint mode, /*!< in: BUF_READ_IBUF_PAGES_ONLY, ...,
-+ ORed to OS_AIO_SIMULATED_WAKE_LATER (see below
-+ at read-ahead functions) */
-+ ulint space, /*!< in: space id */
-+ ulint zip_size,/*!< in: compressed page size, or 0 */
-+ ibool unzip, /*!< in: TRUE=request uncompressed page */
-+ ib_int64_t tablespace_version, /*!< in: if the space memory object has
-+ this timestamp different from what we are giving here,
-+ treat the tablespace as dropped; this is a timestamp we
-+ use to stop dangling page reads from a tablespace
-+ which we have DISCARDed + IMPORTed back */
-+ ulint offset, /*!< in: page number */
-+ trx_t* trx);
-+/********************************************************************//**
- High-level function which reads a page asynchronously from a file to the
- buffer buf_pool if it is not already there. Sets the io_fix flag and sets
- an exclusive lock on the buffer frame. The flag is cleared and the x-lock
---- a/storage/innobase/include/fil0fil.h
-+++ b/storage/innobase/include/fil0fil.h
-@@ -653,6 +653,14 @@
- void* message, /*!< in: message for aio handler if non-sync
- aio used, else ignored */
- trx_t* trx);
-+/********************************************************************//**
-+Confirm whether the parameters are valid or not */
-+UNIV_INTERN
-+ibool
-+fil_is_exist(
-+/*==============*/
-+ ulint space_id, /*!< in: space id */
-+ ulint block_offset); /*!< in: offset in number of blocks */
- /**********************************************************************//**
- Waits for an aio operation to complete. This function is used to write the
- handler for completed requests. The aio array of pending requests is divided
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -364,6 +364,12 @@
- reading of a disk page */
- extern ulint srv_buf_pool_reads;
-
-+/** Time in seconds between automatic buffer pool dumps */
-+extern uint srv_auto_lru_dump;
-+
-+/** Whether startup should be blocked until buffer pool is fully restored */
-+extern ibool srv_blocking_lru_restore;
-+
- /** Status variables to be passed to MySQL */
- typedef struct export_var_struct export_struc;
-
-@@ -669,6 +675,16 @@
- /*=====================*/
- void* arg); /*!< in: a dummy parameter required by
- os_thread_create */
-+/*********************************************************************//**
-+A thread which restores the buffer pool from a dump file on startup and does
-+periodic buffer pool dumps.
-+@return a dummy parameter */
-+UNIV_INTERN
-+os_thread_ret_t
-+srv_LRU_dump_restore_thread(
-+/*====================*/
-+ void* arg); /*!< in: a dummy parameter required by
-+ os_thread_create */
- /******************************************************************//**
- Outputs to a file the output of the InnoDB Monitor.
- @return FALSE if not all information printed
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -332,6 +332,12 @@
- reading of a disk page */
- UNIV_INTERN ulint srv_buf_pool_reads = 0;
-
-+/** Time in seconds between automatic buffer pool dumps */
-+UNIV_INTERN uint srv_auto_lru_dump = 0;
-+
-+/** Whether startup should be blocked until buffer pool is fully restored */
-+UNIV_INTERN ibool srv_blocking_lru_restore;
-+
- /* structure to pass status variables to MySQL */
- UNIV_INTERN export_struc export_vars;
-
-@@ -2708,6 +2714,58 @@
- /* We count the number of threads in os_thread_exit(). A created
- thread should always use that to exit and not use return() to exit. */
-
-+ os_thread_exit(NULL);
-+
-+ OS_THREAD_DUMMY_RETURN;
-+}
-+
-+/*********************************************************************//**
-+A thread which restores the buffer pool from a dump file on startup and does
-+periodic buffer pool dumps.
-+@return a dummy parameter */
-+UNIV_INTERN
-+os_thread_ret_t
-+srv_LRU_dump_restore_thread(
-+/*====================*/
-+ void* arg __attribute__((unused)))
-+ /*!< in: a dummy parameter required by
-+ os_thread_create */
-+{
-+ uint auto_lru_dump;
-+ time_t last_dump_time;
-+ time_t time_elapsed;
-+
-+#ifdef UNIV_DEBUG_THREAD_CREATION
-+ fprintf(stderr, "The LRU dump/restore thread has started, id %lu\n",
-+ os_thread_pf(os_thread_get_curr_id()));
-+#endif
-+
-+ /* If srv_blocking_lru_restore is TRUE, restore will be done
-+ synchronously on startup. */
-+ if (srv_auto_lru_dump && !srv_blocking_lru_restore)
-+ buf_LRU_file_restore();
-+
-+ last_dump_time = time(NULL);
-+
-+loop:
-+ os_thread_sleep(5000000);
-+
-+ if (srv_shutdown_state >= SRV_SHUTDOWN_CLEANUP) {
-+ goto exit_func;
-+ }
-+
-+ time_elapsed = time(NULL) - last_dump_time;
-+ auto_lru_dump = srv_auto_lru_dump;
-+ if (auto_lru_dump > 0 && (time_t) auto_lru_dump < time_elapsed) {
-+ last_dump_time = time(NULL);
-+ buf_LRU_file_dump();
-+ }
-+
-+ goto loop;
-+exit_func:
-+ /* We count the number of threads in os_thread_exit(). A created
-+ thread should always use that to exit and not use return() to exit. */
-+
- os_thread_exit(NULL);
-
- OS_THREAD_DUMMY_RETURN;
---- a/storage/innobase/srv/srv0start.c
-+++ b/storage/innobase/srv/srv0start.c
-@@ -87,6 +87,7 @@
- # include "btr0pcur.h"
- # include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
- # include "zlib.h" /* for ZLIB_VERSION */
-+# include "buf0lru.h" /* for buf_LRU_file_restore() */
-
- /** Log sequence number immediately after startup */
- UNIV_INTERN ib_uint64_t srv_start_lsn;
-@@ -120,9 +121,9 @@
- static os_file_t files[1000];
-
- /** io_handler_thread parameters for thread identification */
--static ulint n[SRV_MAX_N_IO_THREADS + 6];
-+static ulint n[SRV_MAX_N_IO_THREADS + 7];
- /** io_handler_thread identifiers */
--static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6];
-+static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 7];
-
- /** We use this mutex to test the return value of pthread_mutex_trylock
- on successful locking. HP-UX does NOT return 0, though Linux et al do. */
-@@ -1841,6 +1842,15 @@
- os_thread_create(&srv_monitor_thread, NULL,
- thread_ids + 4 + SRV_MAX_N_IO_THREADS);
-
-+ /* Create the thread which automaticaly dumps/restore buffer pool */
-+ os_thread_create(&srv_LRU_dump_restore_thread, NULL,
-+ thread_ids + 5 + SRV_MAX_N_IO_THREADS);
-+
-+ /* If srv_blocking_lru_restore is TRUE, load buffer pool contents
-+ synchronously */
-+ if (srv_auto_lru_dump && srv_blocking_lru_restore)
-+ buf_LRU_file_restore();
-+
- srv_is_being_started = FALSE;
-
- err = dict_create_or_check_foreign_constraint_tables();
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/r/innodb_blocking_buffer_pool_restore_basic.result
-@@ -0,0 +1,3 @@
-+SELECT @@global.innodb_blocking_buffer_pool_restore;
-+@@global.innodb_blocking_buffer_pool_restore
-+0
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/t/innodb_blocking_buffer_pool_restore_basic.test
-@@ -0,0 +1 @@
-+SELECT @@global.innodb_blocking_buffer_pool_restore;
+++ /dev/null
-# name : innodb_opt_lru_count.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/buf/buf0buddy.c
-+++ b/storage/innobase/buf/buf0buddy.c
-@@ -123,7 +123,7 @@
-
- ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i));
-
-- bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
-+ bpage = UT_LIST_GET_LAST(buf_pool->zip_free[i]);
-
- if (bpage) {
- ut_a(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
---- a/storage/innobase/buf/buf0buf.c
-+++ b/storage/innobase/buf/buf0buf.c
-@@ -890,9 +890,9 @@
- block->page.in_zip_hash = FALSE;
- block->page.in_flush_list = FALSE;
- block->page.in_free_list = FALSE;
-- block->page.in_LRU_list = FALSE;
- block->in_unzip_LRU_list = FALSE;
- #endif /* UNIV_DEBUG */
-+ block->page.in_LRU_list = FALSE;
- #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- block->n_pointers = 0;
- #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
-@@ -1403,7 +1403,7 @@
-
- memcpy(dpage, bpage, sizeof *dpage);
-
-- ut_d(bpage->in_LRU_list = FALSE);
-+ bpage->in_LRU_list = FALSE;
- ut_d(bpage->in_page_hash = FALSE);
-
- /* relocate buf_pool->LRU */
-@@ -3225,8 +3225,8 @@
- bpage->in_zip_hash = FALSE;
- bpage->in_flush_list = FALSE;
- bpage->in_free_list = FALSE;
-- bpage->in_LRU_list = FALSE;
- #endif /* UNIV_DEBUG */
-+ bpage->in_LRU_list = FALSE;
-
- ut_d(bpage->in_page_hash = TRUE);
-
-@@ -3391,7 +3391,7 @@
- ibuf_merge_or_delete_for_page(NULL, space, offset, zip_size, TRUE);
-
- /* Flush pages from the end of the LRU list if necessary */
-- buf_flush_free_margin(buf_pool);
-+ buf_flush_free_margin(buf_pool, FALSE);
-
- frame = block->frame;
-
---- a/storage/innobase/buf/buf0flu.c
-+++ b/storage/innobase/buf/buf0flu.c
-@@ -431,19 +431,21 @@
- buf_page_in_file(bpage) and in the LRU list */
- {
- #ifdef UNIV_DEBUG
-- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- #endif
-- ut_ad(mutex_own(buf_page_get_mutex(bpage)));
-- ut_ad(bpage->in_LRU_list);
-+ //ut_ad(mutex_own(buf_page_get_mutex(bpage)));
-+ //ut_ad(bpage->in_LRU_list);
-
-- if (UNIV_LIKELY(buf_page_in_file(bpage))) {
-+ if (UNIV_LIKELY(bpage->in_LRU_list && buf_page_in_file(bpage))) {
-
- return(bpage->oldest_modification == 0
- && buf_page_get_io_fix(bpage) == BUF_IO_NONE
- && bpage->buf_fix_count == 0);
- }
-
-+ /* permited not to own LRU_mutex.. */
-+/*
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: buffer block state %lu"
-@@ -451,6 +453,7 @@
- (ulong) buf_page_get_state(bpage));
- ut_print_buf(stderr, bpage, sizeof(buf_page_t));
- putc('\n', stderr);
-+*/
-
- return(FALSE);
- }
-@@ -2049,8 +2052,14 @@
- buf_page_t* bpage;
- ulint n_replaceable;
- ulint distance = 0;
-+ ibool have_LRU_mutex = FALSE;
-
-- buf_pool_mutex_enter(buf_pool);
-+ if(UT_LIST_GET_LEN(buf_pool->unzip_LRU))
-+ have_LRU_mutex = TRUE;
-+retry:
-+ //buf_pool_mutex_enter(buf_pool);
-+ if (have_LRU_mutex)
-+ buf_pool_mutex_enter(buf_pool);
-
- n_replaceable = UT_LIST_GET_LEN(buf_pool->free);
-
-@@ -2061,7 +2070,13 @@
- + BUF_FLUSH_EXTRA_MARGIN(buf_pool))
- && (distance < BUF_LRU_FREE_SEARCH_LEN(buf_pool))) {
-
-- mutex_t* block_mutex = buf_page_get_mutex(bpage);
-+ mutex_t* block_mutex;
-+ if (!bpage->in_LRU_list) {
-+ /* reatart. but it is very optimistic */
-+ bpage = UT_LIST_GET_LAST(buf_pool->LRU);
-+ continue;
-+ }
-+ block_mutex = buf_page_get_mutex(bpage);
-
- mutex_enter(block_mutex);
-
-@@ -2076,11 +2091,18 @@
- bpage = UT_LIST_GET_PREV(LRU, bpage);
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ if (have_LRU_mutex)
-+ buf_pool_mutex_exit(buf_pool);
-
- if (n_replaceable >= BUF_FLUSH_FREE_BLOCK_MARGIN(buf_pool)) {
-
- return(0);
-+ } else if (!have_LRU_mutex) {
-+ /* confirm it again with LRU_mutex for exactness */
-+ have_LRU_mutex = TRUE;
-+ distance = 0;
-+ goto retry;
- }
-
- return(BUF_FLUSH_FREE_BLOCK_MARGIN(buf_pool)
-@@ -2098,7 +2120,8 @@
- void
- buf_flush_free_margin(
- /*==================*/
-- buf_pool_t* buf_pool) /*!< in: Buffer pool instance */
-+ buf_pool_t* buf_pool, /*!< in: Buffer pool instance */
-+ ibool wait)
- {
- ulint n_to_flush;
-
-@@ -2109,7 +2132,7 @@
-
- n_flushed = buf_flush_LRU(buf_pool, n_to_flush);
-
-- if (n_flushed == ULINT_UNDEFINED) {
-+ if (wait && n_flushed == ULINT_UNDEFINED) {
- /* There was an LRU type flush batch already running;
- let us wait for it to end */
-
-@@ -2122,8 +2145,9 @@
- Flushes pages from the end of all the LRU lists. */
- UNIV_INTERN
- void
--buf_flush_free_margins(void)
-+buf_flush_free_margins(
- /*========================*/
-+ ibool wait)
- {
- ulint i;
-
-@@ -2132,7 +2156,7 @@
-
- buf_pool = buf_pool_from_array(i);
-
-- buf_flush_free_margin(buf_pool);
-+ buf_flush_free_margin(buf_pool, wait);
- }
- }
-
---- a/storage/innobase/buf/buf0lru.c
-+++ b/storage/innobase/buf/buf0lru.c
-@@ -934,7 +934,7 @@
-
- /* No free block was found: try to flush the LRU list */
-
-- buf_flush_free_margin(buf_pool);
-+ buf_flush_free_margin(buf_pool, TRUE);
- ++srv_buf_pool_wait_free;
-
- os_aio_simulated_wake_handler_threads();
-@@ -1131,7 +1131,7 @@
-
- /* Remove the block from the LRU list */
- UT_LIST_REMOVE(LRU, buf_pool->LRU, bpage);
-- ut_d(bpage->in_LRU_list = FALSE);
-+ bpage->in_LRU_list = FALSE;
-
- buf_unzip_LRU_remove_block_if_needed(bpage);
-
-@@ -1210,7 +1210,7 @@
-
- ut_ad(!bpage->in_LRU_list);
- UT_LIST_ADD_LAST(LRU, buf_pool->LRU, bpage);
-- ut_d(bpage->in_LRU_list = TRUE);
-+ bpage->in_LRU_list = TRUE;
-
- if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) {
-
-@@ -1280,7 +1280,7 @@
- buf_pool->LRU_old_len++;
- }
-
-- ut_d(bpage->in_LRU_list = TRUE);
-+ bpage->in_LRU_list = TRUE;
-
- if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) {
-
-@@ -1524,7 +1524,7 @@
- buf_page_set_old(b, buf_page_is_old(b));
- #endif /* UNIV_LRU_DEBUG */
- } else {
-- ut_d(b->in_LRU_list = FALSE);
-+ b->in_LRU_list = FALSE;
- buf_LRU_add_block_low(b, buf_page_is_old(b));
- }
-
---- a/storage/innobase/buf/buf0rea.c
-+++ b/storage/innobase/buf/buf0rea.c
-@@ -367,7 +367,7 @@
- }
-
- /* Flush pages from the end of the LRU list if necessary */
-- buf_flush_free_margin(buf_pool);
-+ buf_flush_free_margin(buf_pool, TRUE);
-
- /* Increment number of I/O operations used for LRU policy. */
- buf_LRU_stat_inc_io();
-@@ -641,7 +641,7 @@
- os_aio_simulated_wake_handler_threads();
-
- /* Flush pages from the end of the LRU list if necessary */
-- buf_flush_free_margin(buf_pool);
-+ buf_flush_free_margin(buf_pool, TRUE);
-
- #ifdef UNIV_DEBUG
- if (buf_debug_prints && (count > 0)) {
-@@ -729,7 +729,7 @@
- os_aio_simulated_wake_handler_threads();
-
- /* Flush pages from the end of all the LRU lists if necessary */
-- buf_flush_free_margins();
-+ buf_flush_free_margins(FALSE);
-
- #ifdef UNIV_DEBUG
- if (buf_debug_prints) {
-@@ -823,7 +823,7 @@
- os_aio_simulated_wake_handler_threads();
-
- /* Flush pages from the end of all the LRU lists if necessary */
-- buf_flush_free_margins();
-+ buf_flush_free_margins(FALSE);
-
- #ifdef UNIV_DEBUG
- if (buf_debug_prints) {
---- a/storage/innobase/include/buf0buf.h
-+++ b/storage/innobase/include/buf0buf.h
-@@ -1424,11 +1424,11 @@
-
- UT_LIST_NODE_T(buf_page_t) LRU;
- /*!< node of the LRU list */
--#ifdef UNIV_DEBUG
-+//#ifdef UNIV_DEBUG
- ibool in_LRU_list; /*!< TRUE if the page is in
- the LRU list; used in
- debugging */
--#endif /* UNIV_DEBUG */
-+//#endif /* UNIV_DEBUG */
- unsigned old:1; /*!< TRUE if the block is in the old
- blocks in buf_pool->LRU_old */
- unsigned freed_page_clock:31;/*!< the value of
---- a/storage/innobase/include/buf0flu.h
-+++ b/storage/innobase/include/buf0flu.h
-@@ -65,13 +65,15 @@
- void
- buf_flush_free_margin(
- /*==================*/
-- buf_pool_t* buf_pool);
-+ buf_pool_t* buf_pool,
-+ ibool wait);
- /*********************************************************************//**
- Flushes pages from the end of all the LRU lists. */
- UNIV_INTERN
- void
--buf_flush_free_margins(void);
-+buf_flush_free_margins(
- /*=========================*/
-+ ibool wait);
- #endif /* !UNIV_HOTBACKUP */
- /********************************************************************//**
- Initializes a page for writing to the tablespace. */
+++ /dev/null
-# name : innodb_overwrite_relay_log_info.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -42,6 +42,8 @@
- #pragma implementation // gcc: Class implementation
- #endif
-
-+#define MYSQL_SERVER
-+
- #include <sql_table.h> // explain_filename, nz2, EXPLAIN_PARTITIONS_AS_COMMENT,
- // EXPLAIN_FILENAME_MAX_EXTRA_LENGTH
-
-@@ -53,6 +55,15 @@
- #include <mysql/psi/psi.h>
- #include <my_sys.h>
-
-+#ifdef MYSQL_SERVER
-+#include <rpl_mi.h>
-+#include <slave.h>
-+// Defined in slave.cc
-+int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
-+int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
-+ const char *default_val);
-+#endif /* MYSQL_SERVER */
-+
- /** @file ha_innodb.cc */
-
- /* Include necessary InnoDB headers */
-@@ -91,6 +102,14 @@
- #include "ha_innodb.h"
- #include "i_s.h"
-
-+#ifdef MYSQL_SERVER
-+// Defined in trx0sys.c
-+extern char trx_sys_mysql_master_log_name[];
-+extern ib_int64_t trx_sys_mysql_master_log_pos;
-+extern char trx_sys_mysql_relay_log_name[];
-+extern ib_int64_t trx_sys_mysql_relay_log_pos;
-+#endif /* MYSQL_SERVER */
-+
- # ifndef MYSQL_PLUGIN_IMPORT
- # define MYSQL_PLUGIN_IMPORT /* nothing */
- # endif /* MYSQL_PLUGIN_IMPORT */
-@@ -163,6 +182,7 @@
- static my_bool innobase_use_doublewrite = TRUE;
- static my_bool innobase_use_checksums = TRUE;
- static my_bool innobase_locks_unsafe_for_binlog = FALSE;
-+static my_bool innobase_overwrite_relay_log_info = FALSE;
- static my_bool innobase_rollback_on_timeout = FALSE;
- static my_bool innobase_create_status_file = FALSE;
- static my_bool innobase_stats_on_metadata = TRUE;
-@@ -2282,6 +2302,89 @@
- }
- #endif /* DBUG_OFF */
-
-+#ifndef MYSQL_SERVER
-+ innodb_overwrite_relay_log_info = FALSE;
-+#endif
-+
-+#ifdef HAVE_REPLICATION
-+#ifdef MYSQL_SERVER
-+ /* read master log position from relay-log.info if exists */
-+ char fname[FN_REFLEN+128];
-+ int pos;
-+ int info_fd;
-+ IO_CACHE info_file;
-+
-+ fname[0] = '\0';
-+
-+ if(innobase_overwrite_relay_log_info) {
-+
-+ fprintf(stderr,
-+ "InnoDB: Warning: innodb_overwrite_relay_log_info is enabled."
-+ " Updates by other storage engines may not be synchronized.\n");
-+
-+ bzero((char*) &info_file, sizeof(info_file));
-+ fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
-+
-+ int error=0;
-+
-+ if (!access(fname,F_OK)) {
-+ /* exist */
-+ if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
-+ error=1;
-+ } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
-+ READ_CACHE, 0L, 0, MYF(MY_WME))) {
-+ error=1;
-+ }
-+
-+ if (error) {
-+relay_info_error:
-+ if (info_fd >= 0)
-+ my_close(info_fd, MYF(0));
-+ fname[0] = '\0';
-+ goto skip_relay;
-+ }
-+ } else {
-+ fname[0] = '\0';
-+ goto skip_relay;
-+ }
-+
-+ if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") || /* dummy (it is relay-log) */
-+ init_intvar_from_file(&pos, &info_file, BIN_LOG_HEADER_SIZE)) {
-+ end_io_cache(&info_file);
-+ error=1;
-+ goto relay_info_error;
-+ }
-+
-+ fprintf(stderr,
-+ "InnoDB: relay-log.info is detected.\n"
-+ "InnoDB: relay log: position %u, file name %s\n",
-+ pos, fname);
-+
-+ strncpy(trx_sys_mysql_relay_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
-+ trx_sys_mysql_relay_log_pos = (ib_int64_t) pos;
-+
-+ if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") ||
-+ init_intvar_from_file(&pos, &info_file, 0)) {
-+ end_io_cache(&info_file);
-+ error=1;
-+ goto relay_info_error;
-+ }
-+
-+ fprintf(stderr,
-+ "InnoDB: master log: position %u, file name %s\n",
-+ pos, fname);
-+
-+ strncpy(trx_sys_mysql_master_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
-+ trx_sys_mysql_master_log_pos = (ib_int64_t) pos;
-+
-+ end_io_cache(&info_file);
-+ if (info_fd >= 0)
-+ my_close(info_fd, MYF(0));
-+ }
-+skip_relay:
-+#endif /* MYSQL_SERVER */
-+#endif /* HAVE_REPLICATION */
-+
- /* Check that values don't overflow on 32-bit systems. */
- if (sizeof(ulint) == 4) {
- if (innobase_buffer_pool_size > UINT_MAX32) {
-@@ -2580,6 +2683,76 @@
- goto mem_free_and_error;
- }
-
-+#ifdef HAVE_REPLICATION
-+#ifdef MYSQL_SERVER
-+ if(innobase_overwrite_relay_log_info) {
-+ /* If InnoDB progressed from relay-log.info, overwrite it */
-+ if (fname[0] == '\0') {
-+ fprintf(stderr,
-+ "InnoDB: Something is wrong with the file relay-info.log. InnoDB will not overwrite it.\n");
-+ } else if (0 != strcmp(fname, trx_sys_mysql_master_log_name)
-+ || pos != trx_sys_mysql_master_log_pos) {
-+ /* Overwrite relay-log.info */
-+ bzero((char*) &info_file, sizeof(info_file));
-+ fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
-+
-+ int error = 0;
-+
-+ if (!access(fname,F_OK)) {
-+ /* exist */
-+ if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
-+ error = 1;
-+ } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
-+ WRITE_CACHE, 0L, 0, MYF(MY_WME))) {
-+ error = 1;
-+ }
-+
-+ if (error) {
-+ if (info_fd >= 0)
-+ my_close(info_fd, MYF(0));
-+ goto skip_overwrite;
-+ }
-+ } else {
-+ error = 1;
-+ goto skip_overwrite;
-+ }
-+
-+ char buff[FN_REFLEN*2+22*2+4], *pos;
-+
-+ my_b_seek(&info_file, 0L);
-+ pos=strmov(buff, trx_sys_mysql_relay_log_name);
-+ *pos++='\n';
-+ pos=longlong2str(trx_sys_mysql_relay_log_pos, pos, 10);
-+ *pos++='\n';
-+ pos=strmov(pos, trx_sys_mysql_master_log_name);
-+ *pos++='\n';
-+ pos=longlong2str(trx_sys_mysql_master_log_pos, pos, 10);
-+ *pos='\n';
-+
-+ if (my_b_write(&info_file, (uchar*) buff, (size_t) (pos-buff)+1))
-+ error = 1;
-+ if (flush_io_cache(&info_file))
-+ error = 1;
-+
-+ end_io_cache(&info_file);
-+ if (info_fd >= 0)
-+ my_close(info_fd, MYF(0));
-+skip_overwrite:
-+ if (error) {
-+ fprintf(stderr,
-+ "InnoDB: ERROR: An error occurred while overwriting relay-log.info.\n");
-+ } else {
-+ fprintf(stderr,
-+ "InnoDB: The file relay-log.info was successfully overwritten.\n");
-+ }
-+ } else {
-+ fprintf(stderr,
-+ "InnoDB: InnoDB and relay-log.info are synchronized. InnoDB will not overwrite it.\n");
-+ }
-+ }
-+#endif /* MYSQL_SERVER */
-+#endif /* HAVE_REPLICATION */
-+
- innobase_old_blocks_pct = buf_LRU_old_ratio_update(
- innobase_old_blocks_pct, TRUE);
-
-@@ -2693,6 +2866,25 @@
- trx_t* trx) /*!< in: transaction handle */
- {
- if (trx_is_started(trx)) {
-+#ifdef HAVE_REPLICATION
-+#ifdef MYSQL_SERVER
-+ THD *thd=current_thd;
-+
-+ if (thd && thd->slave_thread) {
-+ /* Update the replication position info inside InnoDB */
-+ trx->mysql_master_log_file_name
-+ = active_mi->rli.group_master_log_name;
-+ trx->mysql_master_log_pos
-+ = ((ib_int64_t)active_mi->rli.group_master_log_pos +
-+ ((ib_int64_t)active_mi->rli.future_event_relay_log_pos -
-+ (ib_int64_t)active_mi->rli.group_relay_log_pos));
-+ trx->mysql_relay_log_file_name
-+ = active_mi->rli.group_relay_log_name;
-+ trx->mysql_relay_log_pos
-+ = (ib_int64_t)active_mi->rli.future_event_relay_log_pos;
-+ }
-+#endif /* MYSQL_SERVER */
-+#endif /* HAVE_REPLICATION */
-
- trx_commit_for_mysql(trx);
- }
-@@ -11130,6 +11322,12 @@
- "The common part for InnoDB table spaces.",
- NULL, NULL, NULL);
-
-+static MYSQL_SYSVAR_BOOL(recovery_update_relay_log, innobase_overwrite_relay_log_info,
-+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
-+ "During InnoDB crash recovery on slave overwrite relay-log.info "
-+ "to align master log file position if information in InnoDB and relay-log.info is different.",
-+ NULL, NULL, FALSE);
-+
- static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
- PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
- "Enable InnoDB doublewrite buffer (enabled by default). "
-@@ -11647,6 +11845,7 @@
- MYSQL_SYSVAR(old_blocks_pct),
- MYSQL_SYSVAR(old_blocks_time),
- MYSQL_SYSVAR(open_files),
-+ MYSQL_SYSVAR(recovery_update_relay_log),
- MYSQL_SYSVAR(rollback_on_timeout),
- MYSQL_SYSVAR(stats_on_metadata),
- MYSQL_SYSVAR(stats_sample_pages),
---- a/storage/innobase/include/trx0sys.h
-+++ b/storage/innobase/include/trx0sys.h
-@@ -53,6 +53,9 @@
- extern ib_int64_t trx_sys_mysql_master_log_pos;
- /* @} */
-
-+extern char trx_sys_mysql_relay_log_name[];
-+extern ib_int64_t trx_sys_mysql_relay_log_pos;
-+
- /** If this MySQL server uses binary logging, after InnoDB has been inited
- and if it has done a crash recovery, we store the binlog file name and position
- here. */
-@@ -298,7 +301,8 @@
- void
- trx_sys_update_mysql_binlog_offset(
- /*===============================*/
-- const char* file_name,/*!< in: MySQL log file name */
-+ trx_sysf_t* sys_header,
-+ const char* file_name_in,/*!< in: MySQL log file name */
- ib_int64_t offset, /*!< in: position in that log file */
- ulint field, /*!< in: offset of the MySQL log info field in
- the trx sys header */
-@@ -493,6 +497,7 @@
- @see trx_sys_mysql_master_log_name
- @see trx_sys_mysql_bin_log_name */
- #define TRX_SYS_MYSQL_LOG_NAME_LEN 512
-+#define TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN 480 /* (500 - 12) is dead line. */
- /** Contents of TRX_SYS_MYSQL_LOG_MAGIC_N_FLD */
- #define TRX_SYS_MYSQL_LOG_MAGIC_N 873422344
-
-@@ -502,6 +507,7 @@
- /** The offset of the MySQL replication info in the trx system header;
- this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
- #define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
-+#define TRX_SYS_MYSQL_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 1500)
-
- /** The offset of the MySQL binlog offset info in the trx system header */
- #define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 1000)
---- a/storage/innobase/include/trx0trx.h
-+++ b/storage/innobase/include/trx0trx.h
-@@ -580,6 +580,20 @@
- ib_int64_t mysql_log_offset;/* if MySQL binlog is used, this field
- contains the end offset of the binlog
- entry */
-+ const char* mysql_master_log_file_name;
-+ /* if the database server is a MySQL
-+ replication slave, we have here the
-+ master binlog name up to which
-+ replication has processed; otherwise
-+ this is a pointer to a null
-+ character */
-+ ib_int64_t mysql_master_log_pos;
-+ /* if the database server is a MySQL
-+ replication slave, this is the
-+ position in the log file up to which
-+ replication has processed */
-+ const char* mysql_relay_log_file_name;
-+ ib_int64_t mysql_relay_log_pos;
- /*------------------------------*/
- ulint n_mysql_tables_in_use; /* number of Innobase tables
- used in the processing of the current
---- a/storage/innobase/trx/trx0sys.c
-+++ b/storage/innobase/trx/trx0sys.c
-@@ -76,13 +76,16 @@
- file name and position here. */
- /* @{ */
- /** Master binlog file name */
--UNIV_INTERN char trx_sys_mysql_master_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN];
-+UNIV_INTERN char trx_sys_mysql_master_log_name[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN];
- /** Master binlog file position. We have successfully got the updates
- up to this position. -1 means that no crash recovery was needed, or
- there was no master log position info inside InnoDB.*/
- UNIV_INTERN ib_int64_t trx_sys_mysql_master_log_pos = -1;
- /* @} */
-
-+UNIV_INTERN char trx_sys_mysql_relay_log_name[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN];
-+UNIV_INTERN ib_int64_t trx_sys_mysql_relay_log_pos = -1;
-+
- /** If this MySQL server uses binary logging, after InnoDB has been inited
- and if it has done a crash recovery, we store the binlog file name and position
- here. */
-@@ -684,23 +687,25 @@
- void
- trx_sys_update_mysql_binlog_offset(
- /*===============================*/
-- const char* file_name,/*!< in: MySQL log file name */
-+ trx_sysf_t* sys_header,
-+ const char* file_name_in,/*!< in: MySQL log file name */
- ib_int64_t offset, /*!< in: position in that log file */
- ulint field, /*!< in: offset of the MySQL log info field in
- the trx sys header */
- mtr_t* mtr) /*!< in: mtr */
- {
-- trx_sysf_t* sys_header;
-+ const char* file_name;
-
-- if (ut_strlen(file_name) >= TRX_SYS_MYSQL_LOG_NAME_LEN) {
-+ if (ut_strlen(file_name_in) >= TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN) {
-
- /* We cannot fit the name to the 512 bytes we have reserved */
-+ /* -> To store relay log file information, file_name must fit to the 480 bytes */
-
-- return;
-+ file_name = "";
-+ } else {
-+ file_name = file_name_in;
- }
-
-- sys_header = trx_sysf_get(mtr);
--
- if (mach_read_from_4(sys_header + field
- + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
- != TRX_SYS_MYSQL_LOG_MAGIC_N) {
-@@ -822,13 +827,26 @@
- + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_NAME);
-+
-+ fprintf(stderr,
-+ "InnoDB: and relay log file\n"
-+ "InnoDB: position %lu %lu, file name %s\n",
-+ (ulong) mach_read_from_4(sys_header
-+ + TRX_SYS_MYSQL_RELAY_LOG_INFO
-+ + TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
-+ (ulong) mach_read_from_4(sys_header
-+ + TRX_SYS_MYSQL_RELAY_LOG_INFO
-+ + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
-+ sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
-+ + TRX_SYS_MYSQL_LOG_NAME);
-+
- /* Copy the master log position info to global variables we can
- use in ha_innobase.cc to initialize glob_mi to right values */
-
- ut_memcpy(trx_sys_mysql_master_log_name,
- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_NAME,
-- TRX_SYS_MYSQL_LOG_NAME_LEN);
-+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
-
- trx_sys_mysql_master_log_pos
- = (((ib_int64_t) mach_read_from_4(
-@@ -837,6 +855,19 @@
- + ((ib_int64_t) mach_read_from_4(
- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
-+
-+ ut_memcpy(trx_sys_mysql_relay_log_name,
-+ sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
-+ + TRX_SYS_MYSQL_LOG_NAME,
-+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
-+
-+ trx_sys_mysql_relay_log_pos
-+ = (((ib_int64_t) mach_read_from_4(
-+ sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
-+ + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
-+ + ((ib_int64_t) mach_read_from_4(
-+ sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
-+ + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
- mtr_commit(&mtr);
- }
-
---- a/storage/innobase/trx/trx0trx.c
-+++ b/storage/innobase/trx/trx0trx.c
-@@ -138,6 +138,10 @@
-
- trx->mysql_log_file_name = NULL;
- trx->mysql_log_offset = 0;
-+ trx->mysql_master_log_file_name = "";
-+ trx->mysql_master_log_pos = 0;
-+ trx->mysql_relay_log_file_name = "";
-+ trx->mysql_relay_log_pos = 0;
-
- mutex_create(trx_undo_mutex_key, &trx->undo_mutex, SYNC_TRX_UNDO);
-
-@@ -820,6 +824,7 @@
- {
- mtr_t mtr;
- trx_rseg_t* rseg;
-+ trx_sysf_t* sys_header = NULL;
-
- ut_ad(!mutex_own(&kernel_mutex));
-
-@@ -873,8 +878,12 @@
-
- if (trx->mysql_log_file_name
- && trx->mysql_log_file_name[0] != '\0') {
-+ if (!sys_header) {
-+ sys_header = trx_sysf_get(&mtr);
-+ }
-
- trx_sys_update_mysql_binlog_offset(
-+ sys_header,
- trx->mysql_log_file_name,
- trx->mysql_log_offset,
- TRX_SYS_MYSQL_LOG_INFO, &mtr);
-@@ -882,6 +891,27 @@
- trx->mysql_log_file_name = NULL;
- }
-
-+ if (trx->mysql_master_log_file_name[0] != '\0') {
-+ /* This database server is a MySQL replication slave */
-+ if (!sys_header) {
-+ sys_header = trx_sysf_get(&mtr);
-+ }
-+
-+ trx_sys_update_mysql_binlog_offset(
-+ sys_header,
-+ trx->mysql_relay_log_file_name,
-+ trx->mysql_relay_log_pos,
-+ TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
-+
-+ trx_sys_update_mysql_binlog_offset(
-+ sys_header,
-+ trx->mysql_master_log_file_name,
-+ trx->mysql_master_log_pos,
-+ TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
-+
-+ trx->mysql_master_log_file_name = "";
-+ }
-+
- /* The following call commits the mini-transaction, making the
- whole transaction committed in the file-based world, at this
- log sequence number. The transaction becomes 'durable' when
+++ /dev/null
-# name : innodb_pass_corrupt_table.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/btr/btr0btr.c
-+++ b/storage/innobase/btr/btr0btr.c
-@@ -713,6 +713,12 @@
-
- block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
- index, mtr);
-+
-+ if (srv_pass_corrupt_table && !block) {
-+ return(0);
-+ }
-+ ut_a(block);
-+
- btr_assert_not_corrupted(block, index);
- #ifdef UNIV_BTR_DEBUG
- if (!dict_index_is_ibuf(index)) {
-@@ -998,6 +1004,12 @@
-
- root = btr_root_get(index, &mtr);
-
-+ if (srv_pass_corrupt_table && !root) {
-+ mtr_commit(&mtr);
-+ return(0);
-+ }
-+ ut_a(root);
-+
- if (flag == BTR_N_LEAF_PAGES) {
- seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
-
-@@ -1457,6 +1469,13 @@
-
- root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
- NULL, &mtr);
-+
-+ if (srv_pass_corrupt_table && !root) {
-+ mtr_commit(&mtr);
-+ return;
-+ }
-+ ut_a(root);
-+
- #ifdef UNIV_BTR_DEBUG
- ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
- + root, space));
-@@ -1480,6 +1499,12 @@
-
- root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
- NULL, &mtr);
-+
-+ if (srv_pass_corrupt_table && !root) {
-+ mtr_commit(&mtr);
-+ return;
-+ }
-+ ut_a(root);
- #ifdef UNIV_BTR_DEBUG
- ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
- + root, space));
-@@ -1513,6 +1538,11 @@
- block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
- NULL, mtr);
-
-+ if (srv_pass_corrupt_table && !block) {
-+ return;
-+ }
-+ ut_a(block);
-+
- btr_search_drop_page_hash_index(block);
-
- header = buf_block_get_frame(block) + PAGE_HEADER + PAGE_BTR_SEG_TOP;
---- a/storage/innobase/btr/btr0cur.c
-+++ b/storage/innobase/btr/btr0cur.c
-@@ -251,6 +251,11 @@
- mode = latch_mode == BTR_SEARCH_LEAF ? RW_S_LATCH : RW_X_LATCH;
- get_block = btr_block_get(
- space, zip_size, page_no, mode, cursor->index, mtr);
-+
-+ if (srv_pass_corrupt_table && !get_block) {
-+ return;
-+ }
-+ ut_a(get_block);
- #ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
- #endif /* UNIV_BTR_DEBUG */
-@@ -264,6 +269,11 @@
- get_block = btr_block_get(
- space, zip_size, left_page_no,
- RW_X_LATCH, cursor->index, mtr);
-+
-+ if (srv_pass_corrupt_table && !get_block) {
-+ return;
-+ }
-+ ut_a(get_block);
- #ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->frame)
- == page_is_comp(page));
-@@ -276,6 +286,11 @@
- get_block = btr_block_get(
- space, zip_size, page_no,
- RW_X_LATCH, cursor->index, mtr);
-+
-+ if (srv_pass_corrupt_table && !get_block) {
-+ return;
-+ }
-+ ut_a(get_block);
- #ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
- #endif /* UNIV_BTR_DEBUG */
-@@ -287,6 +302,11 @@
- get_block = btr_block_get(
- space, zip_size, right_page_no,
- RW_X_LATCH, cursor->index, mtr);
-+
-+ if (srv_pass_corrupt_table && !get_block) {
-+ return;
-+ }
-+ ut_a(get_block);
- #ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->frame)
- == page_is_comp(page));
-@@ -309,6 +329,11 @@
- space, zip_size,
- left_page_no, mode, cursor->index, mtr);
- cursor->left_block = get_block;
-+
-+ if (srv_pass_corrupt_table && !get_block) {
-+ return;
-+ }
-+ ut_a(get_block);
- #ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->frame)
- == page_is_comp(page));
-@@ -320,6 +345,11 @@
-
- get_block = btr_block_get(
- space, zip_size, page_no, mode, cursor->index, mtr);
-+
-+ if (srv_pass_corrupt_table && !get_block) {
-+ return;
-+ }
-+ ut_a(get_block);
- #ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
- #endif /* UNIV_BTR_DEBUG */
-@@ -595,6 +625,19 @@
- file, line, mtr);
-
- if (block == NULL) {
-+ if (srv_pass_corrupt_table
-+ && buf_mode != BUF_GET_IF_IN_POOL
-+ && buf_mode != BUF_GET_IF_IN_POOL_OR_WATCH) {
-+ page_cursor->block = 0;
-+ page_cursor->rec = 0;
-+ if (estimate) {
-+ cursor->path_arr->nth_rec = ULINT_UNDEFINED;
-+ }
-+ goto func_exit;
-+ }
-+ ut_a(buf_mode == BUF_GET_IF_IN_POOL
-+ || buf_mode == BUF_GET_IF_IN_POOL_OR_WATCH);
-+
- /* This must be a search to perform an insert/delete
- mark/ delete; try using the insert/delete buffer */
-
-@@ -669,6 +712,16 @@
- block->check_index_page_at_flush = TRUE;
- page = buf_block_get_frame(block);
-
-+ if (srv_pass_corrupt_table && !page) {
-+ page_cursor->block = 0;
-+ page_cursor->rec = 0;
-+ if (estimate) {
-+ cursor->path_arr->nth_rec = ULINT_UNDEFINED;
-+ }
-+ goto func_exit;
-+ }
-+ ut_a(page);
-+
- if (rw_latch != RW_NO_LATCH) {
- #ifdef UNIV_ZIP_DEBUG
- const page_zip_des_t* page_zip
-@@ -862,6 +915,17 @@
- RW_NO_LATCH, NULL, BUF_GET,
- file, line, mtr);
- page = buf_block_get_frame(block);
-+
-+ if (srv_pass_corrupt_table && !page) {
-+ page_cursor->block = 0;
-+ page_cursor->rec = 0;
-+ if (estimate) {
-+ cursor->path_arr->nth_rec = ULINT_UNDEFINED;
-+ }
-+ break;
-+ }
-+ ut_a(page);
-+
- ut_ad(index->id == btr_page_get_index_id(page));
-
- block->check_index_page_at_flush = TRUE;
-@@ -982,6 +1046,14 @@
- RW_NO_LATCH, NULL, BUF_GET,
- file, line, mtr);
- page = buf_block_get_frame(block);
-+
-+ if (srv_pass_corrupt_table && !page) {
-+ page_cursor->block = 0;
-+ page_cursor->rec = 0;
-+ break;
-+ }
-+ ut_a(page);
-+
- ut_ad(index->id == btr_page_get_index_id(page));
-
- if (height == ULINT_UNDEFINED) {
-@@ -1195,6 +1267,12 @@
- *big_rec = NULL;
-
- block = btr_cur_get_block(cursor);
-+
-+ if (srv_pass_corrupt_table && !block) {
-+ return(DB_CORRUPTION);
-+ }
-+ ut_a(block);
-+
- page = buf_block_get_frame(block);
- index = cursor->index;
- zip_size = buf_block_get_zip_size(block);
-@@ -2927,6 +3005,11 @@
-
- block = btr_cur_get_block(cursor);
-
-+ if (srv_pass_corrupt_table && !block) {
-+ return(DB_CORRUPTION);
-+ }
-+ ut_a(block);
-+
- ut_ad(page_is_leaf(buf_block_get_frame(block)));
-
- rec = btr_cur_get_rec(cursor);
-@@ -3635,6 +3718,11 @@
-
- page = btr_cur_get_page(&cursor);
-
-+ if (srv_pass_corrupt_table && !page) {
-+ break;
-+ }
-+ ut_a(page);
-+
- rec = page_rec_get_next(page_get_infimum_rec(page));
-
- if (!page_rec_is_supremum(rec)) {
---- a/storage/innobase/btr/btr0pcur.c
-+++ b/storage/innobase/btr/btr0pcur.c
-@@ -32,7 +32,7 @@
- #include "ut0byte.h"
- #include "rem0cmp.h"
- #include "trx0trx.h"
--
-+#include "srv0srv.h"
- /**************************************************************//**
- Allocates memory for a persistent cursor object and initializes the cursor.
- @return own: persistent cursor */
-@@ -114,6 +114,12 @@
- ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
-
- block = btr_pcur_get_block(cursor);
-+
-+ if (srv_pass_corrupt_table && !block) {
-+ return;
-+ }
-+ ut_a(block);
-+
- index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor));
-
- page_cursor = btr_pcur_get_page_cur(cursor);
-@@ -409,6 +415,15 @@
- cursor->latch_mode,
- btr_pcur_get_btr_cur(cursor)->index, mtr);
- next_page = buf_block_get_frame(next_block);
-+
-+ if (srv_pass_corrupt_table && !next_page) {
-+ btr_leaf_page_release(btr_pcur_get_block(cursor),
-+ cursor->latch_mode, mtr);
-+ btr_pcur_get_page_cur(cursor)->block = 0;
-+ btr_pcur_get_page_cur(cursor)->rec = 0;
-+ return;
-+ }
-+ ut_a(next_page);
- #ifdef UNIV_BTR_DEBUG
- ut_a(page_is_comp(next_page) == page_is_comp(page));
- ut_a(btr_page_get_prev(next_page, mtr)
---- a/storage/innobase/btr/btr0sea.c
-+++ b/storage/innobase/btr/btr0sea.c
-@@ -42,7 +42,7 @@
- #include "btr0pcur.h"
- #include "btr0btr.h"
- #include "ha0ha.h"
--
-+#include "srv0srv.h"
- /** Flag: has the search system been enabled?
- Protected by btr_search_latch. */
- UNIV_INTERN char btr_search_enabled = TRUE;
-@@ -609,6 +609,11 @@
-
- block = btr_cur_get_block(cursor);
-
-+ if (srv_pass_corrupt_table && !block) {
-+ return;
-+ }
-+ ut_a(block);
-+
- /* NOTE that the following two function calls do NOT protect
- info or block->n_fields etc. with any semaphore, to save CPU time!
- We cannot assume the fields are consistent when we return from
---- a/storage/innobase/buf/buf0buf.c
-+++ b/storage/innobase/buf/buf0buf.c
-@@ -52,6 +52,7 @@
- #include "log0recv.h"
- #include "page0zip.h"
- #include "trx0trx.h"
-+#include "srv0start.h"
-
- /* prototypes for new functions added to ha_innodb.cc */
- trx_t* innobase_get_trx();
-@@ -1150,6 +1151,11 @@
- ready = buf_flush_ready_for_replace(&block->page);
- mutex_exit(&block->mutex);
-
-+ if (block->page.is_corrupt) {
-+ /* corrupt page may remain, it can be skipped */
-+ break;
-+ }
-+
- if (!ready) {
-
- return(block);
-@@ -1946,6 +1952,13 @@
- return(NULL);
- }
-
-+ if (srv_pass_corrupt_table <= 1) {
-+ if (bpage->is_corrupt) {
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
-+ return(NULL);
-+ }
-+ }
-+
- block_mutex = buf_page_get_mutex_enter(bpage);
-
- rw_lock_s_unlock(&buf_pool->page_hash_latch);
-@@ -2525,6 +2538,13 @@
- return(NULL);
- }
-
-+ if (srv_pass_corrupt_table <= 1) {
-+ if (block->page.is_corrupt) {
-+ mutex_exit(block_mutex);
-+ return(NULL);
-+ }
-+ }
-+
- switch (buf_block_get_state(block)) {
- buf_page_t* bpage;
- ibool success;
-@@ -3199,6 +3219,7 @@
- bpage->newest_modification = 0;
- bpage->oldest_modification = 0;
- HASH_INVALIDATE(bpage, hash);
-+ bpage->is_corrupt = FALSE;
- #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
- bpage->file_page_was_freed = FALSE;
- #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
-@@ -3837,6 +3858,7 @@
- (ulong) bpage->offset);
- }
-
-+ if (!srv_pass_corrupt_table || !bpage->is_corrupt) {
- /* From version 3.23.38 up we store the page checksum
- to the 4 first bytes of the page end lsn field */
-
-@@ -3878,6 +3900,23 @@
- REFMAN "forcing-innodb-recovery.html\n"
- "InnoDB: about forcing recovery.\n", stderr);
-
-+ if (srv_pass_corrupt_table && !trx_sys_sys_space(bpage->space)
-+ && bpage->space < SRV_LOG_SPACE_FIRST_ID) {
-+ trx_t* trx;
-+
-+ fprintf(stderr,
-+ "InnoDB: space %u will be treated as corrupt.\n",
-+ bpage->space);
-+ fil_space_set_corrupt(bpage->space);
-+
-+ trx = innobase_get_trx();
-+ if (trx && trx->dict_operation_lock_mode == RW_X_LATCH) {
-+ dict_table_set_corrupt_by_space(bpage->space, FALSE);
-+ } else {
-+ dict_table_set_corrupt_by_space(bpage->space, TRUE);
-+ }
-+ bpage->is_corrupt = TRUE;
-+ } else
- if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
- /* If page space id is larger than TRX_SYS_SPACE
- (0), we will attempt to mark the corresponding
-@@ -3894,6 +3933,7 @@
- }
- }
- }
-+ } /**/
-
- if (recv_recovery_is_on()) {
- /* Pages must be uncompressed for crash recovery. */
-@@ -3903,8 +3943,11 @@
-
- if (uncompressed && !recv_no_ibuf_operations) {
- ibuf_merge_or_delete_for_page(
-+ /* Delete possible entries, if bpage is_corrupt */
-+ (srv_pass_corrupt_table && bpage->is_corrupt) ? NULL :
- (buf_block_t*) bpage, bpage->space,
- bpage->offset, buf_page_get_zip_size(bpage),
-+ (srv_pass_corrupt_table && bpage->is_corrupt) ? FALSE :
- TRUE);
- }
- }
---- a/storage/innobase/buf/buf0rea.c
-+++ b/storage/innobase/buf/buf0rea.c
-@@ -195,7 +195,14 @@
- ((buf_block_t*) bpage)->frame, bpage, trx);
- }
- thd_wait_end(NULL);
-+
-+ if (srv_pass_corrupt_table) {
-+ if (*err != DB_SUCCESS) {
-+ bpage->is_corrupt = TRUE;
-+ }
-+ } else {
- ut_a(*err == DB_SUCCESS);
-+ }
-
- if (sync) {
- /* The i/o is already completed when we arrive from
---- a/storage/innobase/dict/dict0dict.c
-+++ b/storage/innobase/dict/dict0dict.c
-@@ -55,6 +55,7 @@
- #include "m_ctype.h" /* my_isspace() */
- #include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str()*/
- #include "row0upd.h"
-+#include "srv0start.h" /* SRV_LOG_SPACE_FIRST_ID */
-
- #include <ctype.h>
-
-@@ -750,7 +751,7 @@
-
- mutex_exit(&(dict_sys->mutex));
-
-- if (table != NULL) {
-+ if (table != NULL && !table->is_corrupt) {
- /* If table->ibd_file_missing == TRUE, this will
- print an error message and return without doing
- anything. */
-@@ -1298,7 +1299,7 @@
- + dict_sys->size) > srv_dict_size_limit ) {
- prev_table = UT_LIST_GET_PREV(table_LRU, table);
-
-- if (table == self || table->n_mysql_handles_opened)
-+ if (table == self || table->n_mysql_handles_opened || table->is_corrupt)
- goto next_loop;
-
- cached_foreign_tables = 0;
-@@ -4377,6 +4378,12 @@
- heap = mem_heap_create(1000);
-
- while (index) {
-+ if (table->is_corrupt) {
-+ ut_a(srv_pass_corrupt_table);
-+ mem_heap_free(heap);
-+ return(FALSE);
-+ }
-+
- size = btr_get_size(index, BTR_TOTAL_SIZE);
-
- index->stat_index_size = size;
-@@ -4524,6 +4531,12 @@
- heap = mem_heap_create(1000);
-
- while (index) {
-+ if (table->is_corrupt) {
-+ ut_a(srv_pass_corrupt_table);
-+ mem_heap_free(heap);
-+ return;
-+ }
-+
- /*===========================================*/
- {
- dict_table_t* sys_stats;
-@@ -4716,6 +4729,13 @@
- || (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
- && dict_index_is_clust(index)))) {
- ulint size;
-+
-+ if (table->is_corrupt) {
-+ ut_a(srv_pass_corrupt_table);
-+ dict_table_stats_unlock(table, RW_X_LATCH);
-+ return;
-+ }
-+
- size = btr_get_size(index, BTR_TOTAL_SIZE);
-
- index->stat_index_size = size;
-@@ -5695,4 +5715,42 @@
-
- index->type |= DICT_CORRUPT;
- }
-+
-+/*************************************************************************
-+set is_corrupt flag by space_id*/
-+
-+void
-+dict_table_set_corrupt_by_space(
-+/*============================*/
-+ ulint space_id,
-+ ibool need_mutex)
-+{
-+ dict_table_t* table;
-+ ibool found = FALSE;
-+
-+ ut_a(!trx_sys_sys_space(space_id) && space_id < SRV_LOG_SPACE_FIRST_ID);
-+
-+ if (need_mutex)
-+ mutex_enter(&(dict_sys->mutex));
-+
-+ table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
-+
-+ while (table) {
-+ if (table->space == space_id) {
-+ table->is_corrupt = TRUE;
-+ found = TRUE;
-+ }
-+
-+ table = UT_LIST_GET_NEXT(table_LRU, table);
-+ }
-+
-+ if (need_mutex)
-+ mutex_exit(&(dict_sys->mutex));
-+
-+ if (!found) {
-+ fprintf(stderr, "InnoDB: space to be marked as "
-+ "crashed was not found for id %lu.\n",
-+ (ulong) space_id);
-+ }
-+}
- #endif /* !UNIV_HOTBACKUP */
---- a/storage/innobase/dict/dict0mem.c
-+++ b/storage/innobase/dict/dict0mem.c
-@@ -96,6 +96,8 @@
- /* The number of transactions that are either waiting on the
- AUTOINC lock or have been granted the lock. */
- table->n_waiting_or_granted_auto_inc_locks = 0;
-+
-+ table->is_corrupt = FALSE;
- #endif /* !UNIV_HOTBACKUP */
-
- ut_d(table->magic_n = DICT_TABLE_MAGIC_N);
---- a/storage/innobase/fil/fil0fil.c
-+++ b/storage/innobase/fil/fil0fil.c
-@@ -235,6 +235,7 @@
- file we have written to */
- ibool is_in_unflushed_spaces; /*!< TRUE if this space is
- currently in unflushed_spaces */
-+ ibool is_corrupt;
- UT_LIST_NODE_T(fil_space_t) space_list;
- /*!< list of all spaces */
- ulint magic_n;/*!< FIL_SPACE_MAGIC_N */
-@@ -1294,6 +1295,8 @@
- ut_fold_string(name), space);
- space->is_in_unflushed_spaces = FALSE;
-
-+ space->is_corrupt = FALSE;
-+
- UT_LIST_ADD_LAST(space_list, fil_system->space_list, space);
-
- mutex_exit(&fil_system->mutex);
-@@ -5285,6 +5288,34 @@
- ut_a(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
- ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0);
-
-+ if (srv_pass_corrupt_table == 1 && space->is_corrupt) {
-+ /* should ignore i/o for the crashed space */
-+ mutex_enter(&fil_system->mutex);
-+ fil_node_complete_io(node, fil_system, type);
-+ mutex_exit(&fil_system->mutex);
-+ if (mode == OS_AIO_NORMAL) {
-+ ut_a(space->purpose == FIL_TABLESPACE);
-+ buf_page_io_complete(message);
-+ }
-+ if (type == OS_FILE_READ) {
-+ return(DB_TABLESPACE_DELETED);
-+ } else {
-+ return(DB_SUCCESS);
-+ }
-+ } else {
-+ if (srv_pass_corrupt_table > 1 && space->is_corrupt) {
-+ /* should ignore write i/o for the crashed space */
-+ if (type == OS_FILE_WRITE) {
-+ mutex_enter(&fil_system->mutex);
-+ fil_node_complete_io(node, fil_system, type);
-+ mutex_exit(&fil_system->mutex);
-+ if (mode == OS_AIO_NORMAL) {
-+ ut_a(space->purpose == FIL_TABLESPACE);
-+ buf_page_io_complete(message);
-+ }
-+ return(DB_SUCCESS);
-+ }
-+ }
- #ifdef UNIV_HOTBACKUP
- /* In ibbackup do normal i/o, not aio */
- if (type == OS_FILE_READ) {
-@@ -5299,6 +5330,8 @@
- ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
- offset_low, offset_high, len, node, message, trx);
- #endif
-+ } /**/
-+
- ut_a(ret);
-
- if (mode == OS_AIO_SYNC) {
-@@ -5799,3 +5832,46 @@
- return 0;
- }
- }
-+
-+/*************************************************************************
-+functions to access is_corrupt flag of fil_space_t*/
-+
-+ibool
-+fil_space_is_corrupt(
-+/*=================*/
-+ ulint space_id)
-+{
-+ fil_space_t* space;
-+ ibool ret = FALSE;
-+
-+ mutex_enter(&fil_system->mutex);
-+
-+ space = fil_space_get_by_id(space_id);
-+
-+ if (space && space->is_corrupt) {
-+ ret = TRUE;
-+ }
-+
-+ mutex_exit(&fil_system->mutex);
-+
-+ return(ret);
-+}
-+
-+void
-+fil_space_set_corrupt(
-+/*==================*/
-+ ulint space_id)
-+{
-+ fil_space_t* space;
-+
-+ mutex_enter(&fil_system->mutex);
-+
-+ space = fil_space_get_by_id(space_id);
-+
-+ if (space) {
-+ space->is_corrupt = TRUE;
-+ }
-+
-+ mutex_exit(&fil_system->mutex);
-+}
-+
---- a/storage/innobase/fsp/fsp0fsp.c
-+++ b/storage/innobase/fsp/fsp0fsp.c
-@@ -308,6 +308,12 @@
- ut_ad(id || !zip_size);
-
- block = buf_page_get(id, zip_size, 0, RW_X_LATCH, mtr);
-+
-+ if (srv_pass_corrupt_table && !block) {
-+ return(0);
-+ }
-+ ut_a(block);
-+
- header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
- buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
-
-@@ -726,6 +732,12 @@
- fsp_header_t* sp_header;
-
- block = buf_page_get(space, zip_size, 0, RW_X_LATCH, mtr);
-+
-+ if (srv_pass_corrupt_table && !block) {
-+ return(0);
-+ }
-+ ut_a(block);
-+
- buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
-
- sp_header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
-@@ -1805,6 +1817,11 @@
- {
- fseg_inode_t* inode;
-
-+ if (srv_pass_corrupt_table && !page) {
-+ return(ULINT_UNDEFINED);
-+ }
-+ ut_a(page);
-+
- for (; i < FSP_SEG_INODES_PER_PAGE(zip_size); i++) {
-
- inode = fsp_seg_inode_page_get_nth_inode(
-@@ -1918,6 +1935,11 @@
-
- page = buf_block_get_frame(block);
-
-+ if (srv_pass_corrupt_table && !page) {
-+ return(0);
-+ }
-+ ut_a(page);
-+
- n = fsp_seg_inode_page_find_free(page, 0, zip_size, mtr);
-
- ut_a(n != ULINT_UNDEFINED);
-@@ -2011,6 +2033,11 @@
-
- inode = fut_get_ptr(space, zip_size, inode_addr, RW_X_LATCH, mtr);
-
-+ if (srv_pass_corrupt_table && !inode) {
-+ return(0);
-+ }
-+ ut_a(inode);
-+
- if (UNIV_UNLIKELY(!mach_read_from_8(inode + FSEG_ID))) {
-
- inode = NULL;
-@@ -2037,7 +2064,7 @@
- {
- fseg_inode_t* inode
- = fseg_inode_try_get(header, space, zip_size, mtr);
-- ut_a(inode);
-+ ut_a(srv_pass_corrupt_table || inode);
- return(inode);
- }
-
-@@ -3243,6 +3270,11 @@
-
- descr = xdes_get_descriptor(space, zip_size, page, mtr);
-
-+ if (srv_pass_corrupt_table && !descr) {
-+ /* The page may be corrupt. pass it. */
-+ return;
-+ }
-+
- ut_a(descr);
- if (xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)) {
- fputs("InnoDB: Dump of the tablespace extent descriptor: ",
-@@ -3490,6 +3522,11 @@
-
- descr = xdes_get_descriptor(space, zip_size, header_page, mtr);
-
-+ if (srv_pass_corrupt_table && !descr) {
-+ /* The page may be corrupt. pass it. */
-+ return(TRUE);
-+ }
-+
- /* Check that the header resides on a page which has not been
- freed yet */
-
-@@ -3574,6 +3611,12 @@
-
- inode = fseg_inode_get(header, space, zip_size, mtr);
-
-+ if (srv_pass_corrupt_table && !inode) {
-+ /* ignore the corruption */
-+ return(TRUE);
-+ }
-+ ut_a(inode);
-+
- descr = fseg_get_first_extent(inode, space, zip_size, mtr);
-
- if (descr != NULL) {
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -4024,6 +4024,12 @@
- DBUG_RETURN(1);
- }
-
-+ if (srv_pass_corrupt_table <= 1 && share->ib_table && share->ib_table->is_corrupt) {
-+ free_share(share);
-+
-+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
-+ }
-+
- /* Will be allocated if it is needed in ::update_row() */
- upd_buf = NULL;
- upd_buf_size = 0;
-@@ -4043,6 +4049,17 @@
- /* Get pointer to a table object in InnoDB dictionary cache */
- ib_table = dict_table_get(norm_name, TRUE);
-
-+ if (srv_pass_corrupt_table <= 1 && ib_table && ib_table->is_corrupt) {
-+ free_share(share);
-+ my_free(upd_buf);
-+ upd_buf = NULL;
-+ upd_buf_size = 0;
-+
-+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
-+ }
-+
-+ share->ib_table = ib_table;
-+
- if (NULL == ib_table) {
- if (is_part && retries < 10) {
- /* MySQL partition engine hard codes the file name
-@@ -5263,6 +5280,10 @@
-
- ha_statistic_increment(&SSV::ha_write_count);
-
-+ if (share->ib_table->is_corrupt) {
-+ DBUG_RETURN(HA_ERR_CRASHED);
-+ }
-+
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
- table->timestamp_field->set_time();
-
-@@ -5479,6 +5500,10 @@
- func_exit:
- innobase_active_small();
-
-+ if (share->ib_table->is_corrupt) {
-+ DBUG_RETURN(HA_ERR_CRASHED);
-+ }
-+
- DBUG_RETURN(error_result);
- }
-
-@@ -5673,6 +5698,10 @@
-
- ha_statistic_increment(&SSV::ha_update_count);
-
-+ if (share->ib_table->is_corrupt) {
-+ DBUG_RETURN(HA_ERR_CRASHED);
-+ }
-+
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
- table->timestamp_field->set_time();
-
-@@ -5760,6 +5789,10 @@
-
- innobase_active_small();
-
-+ if (share->ib_table->is_corrupt) {
-+ DBUG_RETURN(HA_ERR_CRASHED);
-+ }
-+
- DBUG_RETURN(error);
- }
-
-@@ -5781,6 +5814,10 @@
-
- ha_statistic_increment(&SSV::ha_delete_count);
-
-+ if (share->ib_table->is_corrupt) {
-+ DBUG_RETURN(HA_ERR_CRASHED);
-+ }
-+
- if (!prebuilt->upd_node) {
- row_get_prebuilt_update_vector(prebuilt);
- }
-@@ -5807,6 +5844,10 @@
-
- innobase_active_small();
-
-+ if (share->ib_table->is_corrupt) {
-+ DBUG_RETURN(HA_ERR_CRASHED);
-+ }
-+
- DBUG_RETURN(error);
- }
-
-@@ -6046,6 +6087,10 @@
-
- ha_statistic_increment(&SSV::ha_read_key_count);
-
-+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
-+ DBUG_RETURN(HA_ERR_CRASHED);
-+ }
-+
- index = prebuilt->index;
-
- if (UNIV_UNLIKELY(index == NULL) || dict_index_is_corrupted(index)) {
-@@ -6113,6 +6158,10 @@
- ret = DB_UNSUPPORTED;
- }
-
-+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
-+ DBUG_RETURN(HA_ERR_CRASHED);
-+ }
-+
- switch (ret) {
- case DB_SUCCESS:
- error = 0;
-@@ -6227,6 +6276,10 @@
- {
- DBUG_ENTER("change_active_index");
-
-+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
-+ DBUG_RETURN(HA_ERR_CRASHED);
-+ }
-+
- ut_ad(user_thd == ha_thd());
- ut_a(prebuilt->trx == thd_to_trx(user_thd));
-
-@@ -6340,6 +6393,10 @@
-
- DBUG_ENTER("general_fetch");
-
-+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
-+ DBUG_RETURN(HA_ERR_CRASHED);
-+ }
-+
- ut_a(prebuilt->trx == thd_to_trx(user_thd));
-
- innodb_srv_conc_enter_innodb(prebuilt->trx);
-@@ -6349,6 +6406,10 @@
-
- innodb_srv_conc_exit_innodb(prebuilt->trx);
-
-+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
-+ DBUG_RETURN(HA_ERR_CRASHED);
-+ }
-+
- switch (ret) {
- case DB_SUCCESS:
- error = 0;
-@@ -7615,10 +7676,18 @@
-
- update_thd(ha_thd());
-
-+ if (share->ib_table->is_corrupt) {
-+ DBUG_RETURN(HA_ERR_CRASHED);
-+ }
-+
- /* Truncate the table in InnoDB */
-
- error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
-
-+ if (share->ib_table->is_corrupt) {
-+ DBUG_RETURN(HA_ERR_CRASHED);
-+ }
-+
- error = convert_error_code_to_mysql(error, prebuilt->table->flags,
- NULL);
-
-@@ -8124,6 +8193,16 @@
- return(ranges + (double) rows / (double) total_rows * time_for_scan);
- }
-
-+UNIV_INTERN
-+bool
-+ha_innobase::is_corrupt() const
-+{
-+ if (share->ib_table)
-+ return ((bool)share->ib_table->is_corrupt);
-+ else
-+ return (FALSE);
-+}
-+
- /*********************************************************************//**
- Calculates the key number used inside MySQL for an Innobase index. We will
- first check the "index translation table" for a match of the index to get
-@@ -8301,7 +8380,7 @@
- ib_table = prebuilt->table;
-
- if (flag & HA_STATUS_TIME) {
-- if (called_from_analyze || innobase_stats_on_metadata) {
-+ if ((called_from_analyze || innobase_stats_on_metadata) && !share->ib_table->is_corrupt) {
- /* In sql_show we call with this flag: update
- then statistics so that they are up-to-date */
-
-@@ -8601,10 +8680,18 @@
- THD* thd, /*!< in: connection thread handle */
- HA_CHECK_OPT* check_opt) /*!< in: currently ignored */
- {
-+ if (share->ib_table->is_corrupt) {
-+ return(HA_ADMIN_CORRUPT);
-+ }
-+
- /* Simply call ::info() with all the flags */
- info_low(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE,
- true /* called from analyze */);
-
-+ if (share->ib_table->is_corrupt) {
-+ return(HA_ADMIN_CORRUPT);
-+ }
-+
- return(0);
- }
-
-@@ -8840,6 +8927,10 @@
- my_error(ER_QUERY_INTERRUPTED, MYF(0));
- }
-
-+ if (share->ib_table->is_corrupt) {
-+ return(HA_ADMIN_CORRUPT);
-+ }
-+
- DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT);
- }
-
-@@ -9610,6 +9701,10 @@
-
- update_thd(thd);
-
-+ if (share->ib_table->is_corrupt) {
-+ DBUG_RETURN(HA_ERR_CRASHED);
-+ }
-+
- if (prebuilt->table->ibd_file_missing && !thd_tablespace_op(thd)) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
-@@ -12073,6 +12168,26 @@
- "dump file (if present). Disabled by default.",
- NULL, NULL, FALSE);
-
-+const char *corrupt_table_action_names[]=
-+{
-+ "assert", /* 0 */
-+ "warn", /* 1 */
-+ "salvage", /* 2 */
-+ NullS
-+};
-+TYPELIB corrupt_table_action_typelib=
-+{
-+ array_elements(corrupt_table_action_names) - 1, "corrupt_table_action_typelib",
-+ corrupt_table_action_names, NULL
-+};
-+static MYSQL_SYSVAR_ENUM(corrupt_table_action, srv_pass_corrupt_table,
-+ PLUGIN_VAR_RQCMDARG,
-+ "Warn corruptions of user tables as 'corrupt table' instead of not crashing itself, "
-+ "when used with file_per_table. "
-+ "All file io for the datafile after detected as corrupt are disabled, "
-+ "except for the deletion.",
-+ NULL, NULL, 0, &corrupt_table_action_typelib);
-+
- static struct st_mysql_sys_var* innobase_system_variables[]= {
- MYSQL_SYSVAR(additional_mem_pool_size),
- MYSQL_SYSVAR(autoextend_increment),
-@@ -12166,6 +12281,7 @@
- #ifdef UNIV_DEBUG
- MYSQL_SYSVAR(trx_rseg_n_slots_debug),
- #endif /* UNIV_DEBUG */
-+ MYSQL_SYSVAR(corrupt_table_action),
- NULL
- };
-
---- a/storage/innobase/handler/ha_innodb.h
-+++ b/storage/innobase/handler/ha_innodb.h
-@@ -52,6 +52,7 @@
- innodb_idx_translate_t idx_trans_tbl; /*!< index translation
- table between MySQL and
- Innodb */
-+ dict_table_t* ib_table;
- } INNOBASE_SHARE;
-
-
-@@ -136,6 +137,7 @@
- int close(void);
- double scan_time();
- double read_time(uint index, uint ranges, ha_rows rows);
-+ bool is_corrupt() const;
-
- int write_row(uchar * buf);
- int update_row(const uchar * old_data, uchar * new_data);
---- a/storage/innobase/include/btr0btr.ic
-+++ b/storage/innobase/include/btr0btr.ic
-@@ -28,7 +28,7 @@
- #include "mtr0mtr.h"
- #include "mtr0log.h"
- #include "page0zip.h"
--
-+#include "srv0srv.h"
- #define BTR_MAX_NODE_LEVEL 50 /*!< Maximum B-tree page level
- (not really a hard limit).
- Used in debug assertions
-@@ -59,7 +59,9 @@
- block = buf_page_get_gen(space, zip_size, page_no, mode,
- NULL, BUF_GET, file, line, mtr);
-
-- if (mode != RW_NO_LATCH) {
-+ ut_a(srv_pass_corrupt_table || block);
-+
-+ if (block && mode != RW_NO_LATCH) {
-
- buf_block_dbg_add_level(
- block, index != NULL && dict_index_is_ibuf(index)
---- a/storage/innobase/include/buf0buf.h
-+++ b/storage/innobase/include/buf0buf.h
-@@ -1023,7 +1023,7 @@
- const buf_block_t* block) /*!< in: pointer to the control block */
- __attribute__((pure));
- #else /* UNIV_DEBUG */
--# define buf_block_get_frame(block) (block)->frame
-+# define buf_block_get_frame(block) (block ? (block)->frame : 0)
- #endif /* UNIV_DEBUG */
- /*********************************************************************//**
- Gets the space id of a block.
-@@ -1470,6 +1470,7 @@
- 0 if the block was never accessed
- in the buffer pool */
- /* @} */
-+ ibool is_corrupt;
- # if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
- ibool file_page_was_freed;
- /*!< this is set to TRUE when fsp
---- a/storage/innobase/include/buf0buf.ic
-+++ b/storage/innobase/include/buf0buf.ic
-@@ -34,7 +34,7 @@
- #include "buf0flu.h"
- #include "buf0lru.h"
- #include "buf0rea.h"
--
-+#include "srv0srv.h"
- /*********************************************************************//**
- Gets the current size of buffer buf_pool in bytes.
- @return size in bytes */
-@@ -681,6 +681,12 @@
- /*================*/
- const buf_block_t* block) /*!< in: pointer to the control block */
- {
-+ ut_a(srv_pass_corrupt_table || block);
-+
-+ if (srv_pass_corrupt_table && !block) {
-+ return(0);
-+ }
-+
- ut_ad(block);
-
- switch (buf_block_get_state(block)) {
---- a/storage/innobase/include/dict0dict.h
-+++ b/storage/innobase/include/dict0dict.h
-@@ -1326,6 +1326,15 @@
- /*========================*/
- ulint space_id); /*!< in: space ID */
-
-+/*************************************************************************
-+set is_corrupt flag by space_id*/
-+
-+void
-+dict_table_set_corrupt_by_space(
-+/*============================*/
-+ ulint space_id,
-+ ibool need_mutex);
-+
- #ifndef UNIV_NONINL
- #include "dict0dict.ic"
- #endif
---- a/storage/innobase/include/dict0mem.h
-+++ b/storage/innobase/include/dict0mem.h
-@@ -670,6 +670,7 @@
- the AUTOINC lock on this table. */
- /* @} */
- /*----------------------*/
-+ ibool is_corrupt;
- #endif /* !UNIV_HOTBACKUP */
-
- #ifdef UNIV_DEBUG
---- a/storage/innobase/include/fil0fil.h
-+++ b/storage/innobase/include/fil0fil.h
-@@ -759,6 +759,19 @@
- fil_system_hash_nodes(void);
- /*========================*/
-
-+/*************************************************************************
-+functions to access is_corrupt flag of fil_space_t*/
-+
-+ibool
-+fil_space_is_corrupt(
-+/*=================*/
-+ ulint space_id);
-+
-+void
-+fil_space_set_corrupt(
-+/*==================*/
-+ ulint space_id);
-+
- typedef struct fil_space_struct fil_space_t;
-
- #endif
---- a/storage/innobase/include/fut0fut.ic
-+++ b/storage/innobase/include/fut0fut.ic
-@@ -23,6 +23,7 @@
- Created 12/13/1995 Heikki Tuuri
- ***********************************************************************/
-
-+#include "srv0srv.h"
- #include "sync0rw.h"
- #include "buf0buf.h"
-
-@@ -48,6 +49,12 @@
- ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
-
- block = buf_page_get(space, zip_size, addr.page, rw_latch, mtr);
-+
-+ if (srv_pass_corrupt_table && !block) {
-+ return(0);
-+ }
-+ ut_a(block);
-+
- ptr = buf_block_get_frame(block) + addr.boffset;
-
- buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
---- a/storage/innobase/include/page0page.h
-+++ b/storage/innobase/include/page0page.h
-@@ -497,7 +497,7 @@
- page_is_leaf(
- /*=========*/
- const page_t* page) /*!< in: page */
-- __attribute__((nonnull, pure));
-+ __attribute__((pure));
- /************************************************************//**
- Gets the pointer to the next record on the page.
- @return pointer to next record */
---- a/storage/innobase/include/page0page.ic
-+++ b/storage/innobase/include/page0page.ic
-@@ -274,6 +274,9 @@
- /*=========*/
- const page_t* page) /*!< in: page */
- {
-+ if (!page) {
-+ return(FALSE);
-+ }
- return(!*(const uint16*) (page + (PAGE_HEADER + PAGE_LEVEL)));
- }
-
---- a/storage/innobase/include/page0zip.h
-+++ b/storage/innobase/include/page0zip.h
-@@ -114,7 +114,7 @@
- const page_t* page, /*!< in: uncompressed page */
- dict_index_t* index, /*!< in: index of the B-tree node */
- mtr_t* mtr) /*!< in: mini-transaction, or NULL */
-- __attribute__((nonnull(1,2,3)));
-+ __attribute__((nonnull(1,3)));
-
- /**********************************************************************//**
- Decompress a page. This function should tolerate errors on the compressed
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -245,6 +245,7 @@
- extern ulint srv_adaptive_flushing_method;
-
- extern ulint srv_expand_import;
-+extern ulint srv_pass_corrupt_table;
-
- extern ulint srv_dict_size_limit;
- /*-------------------------------------------*/
---- a/storage/innobase/page/page0zip.c
-+++ b/storage/innobase/page/page0zip.c
-@@ -1195,6 +1195,10 @@
- FILE* logfile = NULL;
- #endif
-
-+ if (!page) {
-+ return(FALSE);
-+ }
-+
- ut_a(page_is_comp(page));
- ut_a(fil_page_get_type(page) == FIL_PAGE_INDEX);
- ut_ad(page_simple_validate_new((page_t*) page));
---- a/storage/innobase/row/row0ins.c
-+++ b/storage/innobase/row/row0ins.c
-@@ -1341,6 +1341,12 @@
- const rec_t* rec = btr_pcur_get_rec(&pcur);
- const buf_block_t* block = btr_pcur_get_block(&pcur);
-
-+ if (srv_pass_corrupt_table && !block) {
-+ err = DB_CORRUPTION;
-+ break;
-+ }
-+ ut_a(block);
-+
- if (page_rec_is_infimum(rec)) {
-
- continue;
---- a/storage/innobase/row/row0merge.c
-+++ b/storage/innobase/row/row0merge.c
-@@ -1245,6 +1245,13 @@
-
- if (UNIV_LIKELY(has_next)) {
- rec = btr_pcur_get_rec(&pcur);
-+
-+ if (srv_pass_corrupt_table && !rec) {
-+ err = DB_CORRUPTION;
-+ goto err_exit;
-+ }
-+ ut_a(rec);
-+
- offsets = rec_get_offsets(rec, clust_index, NULL,
- ULINT_UNDEFINED, &row_heap);
-
---- a/storage/innobase/row/row0sel.c
-+++ b/storage/innobase/row/row0sel.c
-@@ -3919,6 +3919,13 @@
- /* PHASE 4: Look for matching records in a loop */
-
- rec = btr_pcur_get_rec(pcur);
-+
-+ if (srv_pass_corrupt_table && !rec) {
-+ err = DB_CORRUPTION;
-+ goto lock_wait_or_error;
-+ }
-+ ut_a(rec);
-+
- ut_ad(!!page_rec_is_comp(rec) == comp);
- #ifdef UNIV_SEARCH_DEBUG
- /*
-@@ -3996,7 +4003,13 @@
- if (UNIV_UNLIKELY(next_offs >= UNIV_PAGE_SIZE - PAGE_DIR)) {
-
- wrong_offs:
-- if (srv_force_recovery == 0 || moves_up == FALSE) {
-+ if (srv_pass_corrupt_table && !trx_sys_sys_space(index->table->space)) {
-+ index->table->is_corrupt = TRUE;
-+ fil_space_set_corrupt(index->table->space);
-+ }
-+
-+ if ((srv_force_recovery == 0 || moves_up == FALSE)
-+ && srv_pass_corrupt_table <= 1) {
- ut_print_timestamp(stderr);
- buf_page_print(page_align(rec), 0);
- fprintf(stderr,
-@@ -4047,7 +4060,8 @@
-
- offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
-
-- if (UNIV_UNLIKELY(srv_force_recovery > 0)) {
-+ if (UNIV_UNLIKELY(srv_force_recovery > 0)
-+ || (srv_pass_corrupt_table == 2 && index->table->is_corrupt)) {
- if (!rec_validate(rec, offsets)
- || !btr_index_rec_validate(rec, index, FALSE)) {
- fprintf(stderr,
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -435,6 +435,7 @@
- UNIV_INTERN ulint srv_adaptive_flushing_method = 0; /* 0: native 1: estimate 2: keep_average */
-
- UNIV_INTERN ulint srv_expand_import = 0; /* 0:disable 1:enable */
-+UNIV_INTERN ulint srv_pass_corrupt_table = 0; /* 0:disable 1:enable */
-
- UNIV_INTERN ulint srv_dict_size_limit = 0;
- /*-------------------------------------------*/
---- a/storage/innobase/srv/srv0start.c
-+++ b/storage/innobase/srv/srv0start.c
-@@ -2175,6 +2175,13 @@
-
- os_fast_mutex_free(&srv_os_test_mutex);
-
-+ if (!srv_file_per_table_original_value
-+ && srv_pass_corrupt_table) {
-+ fprintf(stderr, "InnoDB: Warning:"
-+ " The option innodb_file_per_table is disabled,"
-+ " so using the option innodb_pass_corrupt_table doesn't make sense.\n");
-+ }
-+
- if (srv_print_verbose_log) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
+++ /dev/null
-# name : innodb_recovery_patches.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/buf/buf0rea.c
-+++ b/storage/innobase/buf/buf0rea.c
-@@ -124,6 +124,46 @@
- bpage = buf_page_init_for_read(err, mode, space, zip_size, unzip,
- tablespace_version, offset);
- if (bpage == NULL) {
-+ /* bugfix: http://bugs.mysql.com/bug.php?id=43948 */
-+ if (recv_recovery_is_on() && *err == DB_TABLESPACE_DELETED) {
-+ /* hashed log recs must be treated here */
-+ recv_addr_t* recv_addr;
-+
-+ mutex_enter(&(recv_sys->mutex));
-+
-+ if (recv_sys->apply_log_recs == FALSE) {
-+ mutex_exit(&(recv_sys->mutex));
-+ goto not_to_recover;
-+ }
-+
-+ /* recv_get_fil_addr_struct() */
-+ recv_addr = HASH_GET_FIRST(recv_sys->addr_hash,
-+ hash_calc_hash(ut_fold_ulint_pair(space, offset),
-+ recv_sys->addr_hash));
-+ while (recv_addr) {
-+ if ((recv_addr->space == space)
-+ && (recv_addr->page_no == offset)) {
-+ break;
-+ }
-+ recv_addr = HASH_GET_NEXT(addr_hash, recv_addr);
-+ }
-+
-+ if ((recv_addr == NULL)
-+ || (recv_addr->state == RECV_BEING_PROCESSED)
-+ || (recv_addr->state == RECV_PROCESSED)) {
-+ mutex_exit(&(recv_sys->mutex));
-+ goto not_to_recover;
-+ }
-+
-+ fprintf(stderr, " (cannot find space: %lu)", space);
-+ recv_addr->state = RECV_PROCESSED;
-+
-+ ut_a(recv_sys->n_addrs);
-+ recv_sys->n_addrs--;
-+
-+ mutex_exit(&(recv_sys->mutex));
-+ }
-+not_to_recover:
-
- return(0);
- }
-@@ -777,6 +817,50 @@
- /* It is a single table tablespace and the .ibd file is
- missing: do nothing */
-
-+ /* the log records should be treated here same reason
-+ for http://bugs.mysql.com/bug.php?id=43948 */
-+
-+ if (recv_recovery_is_on()) {
-+ recv_addr_t* recv_addr;
-+
-+ mutex_enter(&(recv_sys->mutex));
-+
-+ if (recv_sys->apply_log_recs == FALSE) {
-+ mutex_exit(&(recv_sys->mutex));
-+ goto not_to_recover;
-+ }
-+
-+ for (i = 0; i < n_stored; i++) {
-+ /* recv_get_fil_addr_struct() */
-+ recv_addr = HASH_GET_FIRST(recv_sys->addr_hash,
-+ hash_calc_hash(ut_fold_ulint_pair(space, page_nos[i]),
-+ recv_sys->addr_hash));
-+ while (recv_addr) {
-+ if ((recv_addr->space == space)
-+ && (recv_addr->page_no == page_nos[i])) {
-+ break;
-+ }
-+ recv_addr = HASH_GET_NEXT(addr_hash, recv_addr);
-+ }
-+
-+ if ((recv_addr == NULL)
-+ || (recv_addr->state == RECV_BEING_PROCESSED)
-+ || (recv_addr->state == RECV_PROCESSED)) {
-+ continue;
-+ }
-+
-+ recv_addr->state = RECV_PROCESSED;
-+
-+ ut_a(recv_sys->n_addrs);
-+ recv_sys->n_addrs--;
-+ }
-+
-+ mutex_exit(&(recv_sys->mutex));
-+
-+ fprintf(stderr, " (cannot find space: %lu)", space);
-+ }
-+not_to_recover:
-+
- return;
- }
-
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -182,6 +182,7 @@
- #endif /* UNIV_LOG_ARCHIVE */
- static my_bool innobase_use_doublewrite = TRUE;
- static my_bool innobase_use_checksums = TRUE;
-+static my_bool innobase_recovery_stats = TRUE;
- static my_bool innobase_locks_unsafe_for_binlog = FALSE;
- static my_bool innobase_overwrite_relay_log_info = FALSE;
- static my_bool innobase_rollback_on_timeout = FALSE;
-@@ -2610,6 +2611,8 @@
-
- srv_force_recovery = (ulint) innobase_force_recovery;
-
-+ srv_recovery_stats = (ibool) innobase_recovery_stats;
-+
- srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
- srv_use_checksums = (ibool) innobase_use_checksums;
-
-@@ -11390,6 +11393,11 @@
- "The common part for InnoDB table spaces.",
- NULL, NULL, NULL);
-
-+static MYSQL_SYSVAR_BOOL(recovery_stats, innobase_recovery_stats,
-+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
-+ "Output statistics of recovery process after it.",
-+ NULL, NULL, FALSE);
-+
- static MYSQL_SYSVAR_BOOL(recovery_update_relay_log, innobase_overwrite_relay_log_info,
- PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
- "During InnoDB crash recovery on slave overwrite relay-log.info "
-@@ -11918,6 +11926,7 @@
- MYSQL_SYSVAR(data_file_path),
- MYSQL_SYSVAR(data_home_dir),
- MYSQL_SYSVAR(doublewrite),
-+ MYSQL_SYSVAR(recovery_stats),
- MYSQL_SYSVAR(fast_shutdown),
- MYSQL_SYSVAR(file_io_threads),
- MYSQL_SYSVAR(read_io_threads),
---- a/storage/innobase/include/log0recv.h
-+++ b/storage/innobase/include/log0recv.h
-@@ -438,6 +438,39 @@
- hash_table_t* addr_hash;/*!< hash table of file addresses of pages */
- ulint n_addrs;/*!< number of not processed hashed file
- addresses in the hash table */
-+
-+/* If you modified the following defines at original file,
-+ You should also modify them. */
-+/* defined in os0file.c */
-+#define OS_AIO_MERGE_N_CONSECUTIVE 64
-+/* defined in log0recv.c */
-+#define RECV_READ_AHEAD_AREA 32
-+ time_t stats_recv_start_time;
-+ ulint stats_recv_turns;
-+
-+ ulint stats_read_requested_pages;
-+ ulint stats_read_in_area[RECV_READ_AHEAD_AREA];
-+
-+ ulint stats_read_io_pages;
-+ ulint stats_read_io_consecutive[OS_AIO_MERGE_N_CONSECUTIVE];
-+ ulint stats_write_io_pages;
-+ ulint stats_write_io_consecutive[OS_AIO_MERGE_N_CONSECUTIVE];
-+
-+ ulint stats_doublewrite_check_pages;
-+ ulint stats_doublewrite_overwrite_pages;
-+
-+ ulint stats_recover_pages_with_read;
-+ ulint stats_recover_pages_without_read;
-+
-+ ulint stats_log_recs;
-+ ulint stats_log_len_sum;
-+
-+ ulint stats_applied_log_recs;
-+ ulint stats_applied_log_len_sum;
-+ ulint stats_pages_already_new;
-+
-+ ib_uint64_t stats_oldest_modified_lsn;
-+ ib_uint64_t stats_newest_modified_lsn;
- };
-
- /** The recovery system */
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -126,6 +126,8 @@
- extern ulint* srv_data_file_sizes;
- extern ulint* srv_data_file_is_raw_partition;
-
-+extern ibool srv_recovery_stats;
-+
- extern ibool srv_auto_extend_last_data_file;
- extern ulint srv_last_file_size_max;
- extern char** srv_log_group_home_dirs;
---- a/storage/innobase/log/log0recv.c
-+++ b/storage/innobase/log/log0recv.c
-@@ -187,6 +187,9 @@
-
- recv_sys->heap = NULL;
- recv_sys->addr_hash = NULL;
-+
-+ recv_sys->stats_recv_start_time = time(NULL);
-+ recv_sys->stats_oldest_modified_lsn = IB_ULONGLONG_MAX;
- }
-
- /********************************************************//**
-@@ -327,6 +330,11 @@
- recv_n_pool_free_frames = 512;
- }
-
-+ if (buf_pool_get_curr_size() >= (32 * 1024 * 1024)) {
-+ /* Buffer pool of size greater than 32 MB. */
-+ recv_n_pool_free_frames = 1024;
-+ }
-+
- recv_sys->buf = ut_malloc(RECV_PARSING_BUF_SIZE);
- recv_sys->len = 0;
- recv_sys->recovered_offset = 0;
-@@ -1363,6 +1371,11 @@
-
- len = rec_end - body;
-
-+ if (srv_recovery_stats) {
-+ recv_sys->stats_log_recs++;
-+ recv_sys->stats_log_len_sum += len;
-+ }
-+
- recv = mem_heap_alloc(recv_sys->heap, sizeof(recv_t));
- recv->type = type;
- recv->len = rec_end - body;
-@@ -1474,6 +1487,7 @@
- ib_uint64_t start_lsn;
- ib_uint64_t end_lsn;
- ib_uint64_t page_lsn;
-+ ib_uint64_t page_lsn_orig;
- ib_uint64_t page_newest_lsn;
- ibool modification_to_page;
- #ifndef UNIV_HOTBACKUP
-@@ -1496,6 +1510,8 @@
- buf_block_get_page_no(block));
-
- if ((recv_addr == NULL)
-+ /* bugfix: http://bugs.mysql.com/bug.php?id=44140 */
-+ || (recv_addr->state == RECV_BEING_READ && !just_read_in)
- || (recv_addr->state == RECV_BEING_PROCESSED)
- || (recv_addr->state == RECV_PROCESSED)) {
-
-@@ -1511,6 +1527,14 @@
-
- recv_addr->state = RECV_BEING_PROCESSED;
-
-+ if (srv_recovery_stats) {
-+ if (just_read_in) {
-+ recv_sys->stats_recover_pages_with_read++;
-+ } else {
-+ recv_sys->stats_recover_pages_without_read++;
-+ }
-+ }
-+
- mutex_exit(&(recv_sys->mutex));
-
- mtr_start(&mtr);
-@@ -1540,6 +1564,7 @@
-
- /* Read the newest modification lsn from the page */
- page_lsn = mach_read_from_8(page + FIL_PAGE_LSN);
-+ page_lsn_orig = page_lsn;
-
- #ifndef UNIV_HOTBACKUP
- /* It may be that the page has been modified in the buffer
-@@ -1559,6 +1584,21 @@
- modification_to_page = FALSE;
- start_lsn = end_lsn = 0;
-
-+ if (srv_recovery_stats) {
-+ mutex_enter(&(recv_sys->mutex));
-+ if (page_lsn_orig && recv_sys->stats_oldest_modified_lsn > page_lsn_orig) {
-+ recv_sys->stats_oldest_modified_lsn = page_lsn_orig;
-+ }
-+ if (page_lsn_orig && recv_sys->stats_newest_modified_lsn < page_lsn_orig) {
-+ recv_sys->stats_newest_modified_lsn = page_lsn_orig;
-+ }
-+ if (UT_LIST_GET_LAST(recv_addr->rec_list)->start_lsn
-+ < page_lsn_orig) {
-+ recv_sys->stats_pages_already_new++;
-+ }
-+ mutex_exit(&(recv_sys->mutex));
-+ }
-+
- recv = UT_LIST_GET_FIRST(recv_addr->rec_list);
-
- while (recv) {
-@@ -1613,6 +1653,13 @@
- buf + recv->len,
- block, &mtr);
-
-+ if (srv_recovery_stats) {
-+ mutex_enter(&(recv_sys->mutex));
-+ recv_sys->stats_applied_log_recs++;
-+ recv_sys->stats_applied_log_len_sum += recv->len;
-+ mutex_exit(&(recv_sys->mutex));
-+ }
-+
- end_lsn = recv->start_lsn + recv->len;
- mach_write_to_8(FIL_PAGE_LSN + page, end_lsn);
- mach_write_to_8(UNIV_PAGE_SIZE
-@@ -1715,6 +1762,13 @@
- }
- }
-
-+ if (srv_recovery_stats && n) {
-+ mutex_enter(&(recv_sys->mutex));
-+ recv_sys->stats_read_requested_pages += n;
-+ recv_sys->stats_read_in_area[n - 1]++;
-+ mutex_exit(&(recv_sys->mutex));
-+ }
-+
- buf_read_recv_pages(FALSE, space, zip_size, page_nos, n);
- /*
- fprintf(stderr, "Recv pages at %lu n %lu\n", page_nos[0], n);
-@@ -1867,6 +1921,10 @@
-
- if (has_printed) {
- fprintf(stderr, "InnoDB: Apply batch completed\n");
-+
-+ if (srv_recovery_stats) {
-+ recv_sys->stats_recv_turns++;
-+ }
- }
-
- mutex_exit(&(recv_sys->mutex));
-@@ -3270,6 +3328,90 @@
- }
- #endif /* UNIV_DEBUG */
-
-+ if (recv_needed_recovery && srv_recovery_stats) {
-+ ulint flush_list_len = 0;
-+ ulint i;
-+
-+ fprintf(stderr,
-+ "InnoDB: Log records have been applied. The statistics that were gathered follow.\n");
-+
-+ fprintf(stderr,
-+ "============================================================\n"
-+ "-------------------\n"
-+ "RECOVERY STATISTICS\n"
-+ "-------------------\n");
-+ fprintf(stderr,
-+ "Recovery time: %g sec. (%lu turns)\n",
-+ difftime(time(NULL), recv_sys->stats_recv_start_time),
-+ recv_sys->stats_recv_turns);
-+
-+ for (i = 0; i < srv_buf_pool_instances; i++) {
-+ buf_pool_t* buf_pool;
-+
-+ buf_pool = buf_pool_from_array(i);
-+ flush_list_len += UT_LIST_GET_LEN(buf_pool->flush_list);
-+ }
-+ fprintf(stderr,
-+ "\n"
-+ "Data page IO statistics\n"
-+ " Requested pages: %lu\n"
-+ " Read pages: %lu\n"
-+ " Written pages: %lu\n"
-+ " (Dirty blocks): %lu\n",
-+ recv_sys->stats_read_requested_pages,
-+ recv_sys->stats_read_io_pages,
-+ recv_sys->stats_write_io_pages,
-+ flush_list_len);
-+
-+ fprintf(stderr,
-+ " Grouping IO [times]:\n"
-+ "\tnumber of pages,\n"
-+ "\t\tread request neighbors (in %d pages chunk),\n"
-+ "\t\t\tcombined read IO,\n"
-+ "\t\t\t\tcombined write IO\n",
-+ RECV_READ_AHEAD_AREA);
-+ for (i = 0; i < ut_max(RECV_READ_AHEAD_AREA,
-+ OS_AIO_MERGE_N_CONSECUTIVE); i++) {
-+ fprintf(stderr,
-+ "\t%3lu,\t%lu,\t%lu,\t%lu\n", i + 1,
-+ (i < RECV_READ_AHEAD_AREA) ?
-+ recv_sys->stats_read_in_area[i] : 0,
-+ (i < OS_AIO_MERGE_N_CONSECUTIVE) ?
-+ recv_sys->stats_read_io_consecutive[i] : 0,
-+ (i < OS_AIO_MERGE_N_CONSECUTIVE) ?
-+ recv_sys->stats_write_io_consecutive[i] : 0);
-+ }
-+
-+ fprintf(stderr,
-+ "\n"
-+ "Recovery process statistics\n"
-+ " Checked pages by doublewrite buffer: %lu\n"
-+ " Overwritten pages from doublewrite: %lu\n"
-+ " Recovered pages by io_thread: %lu\n"
-+ " Recovered pages by main thread: %lu\n"
-+ " Parsed log records to apply: %lu\n"
-+ " Sum of the length: %lu\n"
-+ " Applied log records: %lu\n"
-+ " Sum of the length: %lu\n"
-+ " Pages which are already new enough: %lu (It may not be accurate, if turns > 1)\n"
-+ " Oldest page's LSN: %llu\n"
-+ " Newest page's LSN: %llu\n",
-+ recv_sys->stats_doublewrite_check_pages,
-+ recv_sys->stats_doublewrite_overwrite_pages,
-+ recv_sys->stats_recover_pages_with_read,
-+ recv_sys->stats_recover_pages_without_read,
-+ recv_sys->stats_log_recs,
-+ recv_sys->stats_log_len_sum,
-+ recv_sys->stats_applied_log_recs,
-+ recv_sys->stats_applied_log_len_sum,
-+ recv_sys->stats_pages_already_new,
-+ recv_sys->stats_oldest_modified_lsn,
-+ recv_sys->stats_newest_modified_lsn);
-+
-+ fprintf(stderr,
-+ "============================================================\n");
-+ }
-+
- if (recv_needed_recovery) {
- trx_sys_print_mysql_master_log_pos();
- trx_sys_print_mysql_binlog_offset();
---- a/storage/innobase/os/os0file.c
-+++ b/storage/innobase/os/os0file.c
-@@ -43,6 +43,7 @@
- #include "srv0start.h"
- #include "fil0fil.h"
- #include "buf0buf.h"
-+#include "log0recv.h"
- #ifndef UNIV_HOTBACKUP
- # include "os0sync.h"
- # include "os0thread.h"
-@@ -4278,6 +4279,18 @@
- INFINITE);
- }
-
-+ if (srv_recovery_stats && recv_recovery_is_on() && n_consecutive) {
-+ mutex_enter(&(recv_sys->mutex));
-+ if (slot->type == OS_FILE_READ) {
-+ recv_sys->stats_read_io_pages += n_consecutive;
-+ recv_sys->stats_read_io_consecutive[n_consecutive - 1]++;
-+ } else if (slot->type == OS_FILE_WRITE) {
-+ recv_sys->stats_write_io_pages += n_consecutive;
-+ recv_sys->stats_write_io_consecutive[n_consecutive - 1]++;
-+ }
-+ mutex_exit(&(recv_sys->mutex));
-+ }
-+
- os_mutex_enter(array->mutex);
-
- if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -160,6 +160,8 @@
- /* size in database pages */
- UNIV_INTERN ulint* srv_data_file_sizes = NULL;
-
-+UNIV_INTERN ibool srv_recovery_stats = FALSE;
-+
- /* if TRUE, then we auto-extend the last data file */
- UNIV_INTERN ibool srv_auto_extend_last_data_file = FALSE;
- /* if != 0, this tells the max size auto-extending may increase the
---- a/storage/innobase/trx/trx0sys.c
-+++ b/storage/innobase/trx/trx0sys.c
-@@ -567,6 +567,12 @@
- zip_size ? zip_size : UNIV_PAGE_SIZE,
- read_buf, NULL);
-
-+ if (srv_recovery_stats && recv_recovery_is_on()) {
-+ mutex_enter(&(recv_sys->mutex));
-+ recv_sys->stats_doublewrite_check_pages++;
-+ mutex_exit(&(recv_sys->mutex));
-+ }
-+
- /* Check if the page is corrupt */
-
- if (UNIV_UNLIKELY
-@@ -614,6 +620,13 @@
- zip_size, page_no, 0,
- zip_size ? zip_size : UNIV_PAGE_SIZE,
- page, NULL);
-+
-+ if (srv_recovery_stats && recv_recovery_is_on()) {
-+ mutex_enter(&(recv_sys->mutex));
-+ recv_sys->stats_doublewrite_overwrite_pages++;
-+ mutex_exit(&(recv_sys->mutex));
-+ }
-+
- fprintf(stderr,
- "InnoDB: Recovered the page from"
- " the doublewrite buffer.\n");
+++ /dev/null
-# name : innodb_separate_doublewrite.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/buf/buf0buf.c
-+++ b/storage/innobase/buf/buf0buf.c
-@@ -3807,7 +3807,8 @@
- read_space_id = mach_read_from_4(
- frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
-
-- if (bpage->space == TRX_SYS_SPACE
-+ if ((bpage->space == TRX_SYS_SPACE
-+ || (srv_doublewrite_file && bpage->space == TRX_DOUBLEWRITE_SPACE))
- && trx_doublewrite_page_inside(bpage->offset)) {
-
- ut_print_timestamp(stderr);
---- a/storage/innobase/buf/buf0flu.c
-+++ b/storage/innobase/buf/buf0flu.c
-@@ -793,7 +793,8 @@
- write_buf = trx_doublewrite->write_buf;
- i = 0;
-
-- fil_io(OS_FILE_WRITE, TRUE, TRX_SYS_SPACE, 0,
-+ fil_io(OS_FILE_WRITE, TRUE,
-+ (srv_doublewrite_file ? TRX_DOUBLEWRITE_SPACE : TRX_SYS_SPACE), 0,
- trx_doublewrite->block1, 0, len,
- (void*) write_buf, NULL);
-
-@@ -830,7 +831,8 @@
- + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE;
- ut_ad(i == TRX_SYS_DOUBLEWRITE_BLOCK_SIZE);
-
-- fil_io(OS_FILE_WRITE, TRUE, TRX_SYS_SPACE, 0,
-+ fil_io(OS_FILE_WRITE, TRUE,
-+ (srv_doublewrite_file ? TRX_DOUBLEWRITE_SPACE : TRX_SYS_SPACE), 0,
- trx_doublewrite->block2, 0, len,
- (void*) write_buf, NULL);
-
-@@ -860,7 +862,7 @@
- flush:
- /* Now flush the doublewrite buffer data to disk */
-
-- fil_flush(TRX_SYS_SPACE, FALSE);
-+ fil_flush(srv_doublewrite_file ? TRX_DOUBLEWRITE_SPACE : TRX_SYS_SPACE, FALSE);
-
- /* We know that the writes have been flushed to disk now
- and in recovery we will find them in the doublewrite buffer
---- a/storage/innobase/buf/buf0rea.c
-+++ b/storage/innobase/buf/buf0rea.c
-@@ -90,7 +90,9 @@
- wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
- mode = mode & ~OS_AIO_SIMULATED_WAKE_LATER;
-
-- if (trx_doublewrite && space == TRX_SYS_SPACE
-+ if (trx_doublewrite
-+ && (space == TRX_SYS_SPACE
-+ || (srv_doublewrite_file && space == TRX_DOUBLEWRITE_SPACE))
- && ( (offset >= trx_doublewrite->block1
- && offset < trx_doublewrite->block1
- + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE)
---- a/storage/innobase/dict/dict0load.c
-+++ b/storage/innobase/dict/dict0load.c
-@@ -41,6 +41,7 @@
- #include "srv0start.h"
- #include "srv0srv.h"
- #include "ha_prototypes.h" /* innobase_casedn_str() */
-+#include "trx0sys.h"
-
-
- /** Following are six InnoDB system tables */
-@@ -816,7 +817,7 @@
-
- mtr_commit(&mtr);
-
-- if (space_id == 0) {
-+ if (trx_sys_sys_space(space_id)) {
- /* The system tablespace always exists. */
- } else if (in_crash_recovery) {
- /* Check that the tablespace (the .ibd file) really
-@@ -1727,7 +1728,7 @@
- space = mach_read_from_4(field);
-
- /* Check if the tablespace exists and has the right name */
-- if (space != 0) {
-+ if (!trx_sys_sys_space(space)) {
- flags = dict_sys_tables_get_flags(rec);
-
- if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
-@@ -1880,7 +1881,7 @@
- goto err_exit;
- }
-
-- if (table->space == 0) {
-+ if (trx_sys_sys_space(table->space)) {
- /* The system tablespace is always available. */
- } else if (!fil_space_for_table_exists_in_mem(
- table->space, name,
---- a/storage/innobase/fil/fil0fil.c
-+++ b/storage/innobase/fil/fil0fil.c
-@@ -657,7 +657,7 @@
-
- UT_LIST_ADD_LAST(chain, space->chain, node);
-
-- if (id < SRV_LOG_SPACE_FIRST_ID && fil_system->max_assigned_id < id) {
-+ if (id < SRV_EXTRA_SYS_SPACE_FIRST_ID && fil_system->max_assigned_id < id) {
-
- fil_system->max_assigned_id = id;
- }
-@@ -721,14 +721,14 @@
- size_bytes = (((ib_int64_t)size_high) << 32)
- + (ib_int64_t)size_low;
- #ifdef UNIV_HOTBACKUP
-- if (space->id == 0) {
-+ if (trx_sys_sys_space(space->id)) {
- node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
- os_file_close(node->handle);
- goto add_size;
- }
- #endif /* UNIV_HOTBACKUP */
- ut_a(space->purpose != FIL_LOG);
-- ut_a(space->id != 0);
-+ ut_a(!trx_sys_sys_space(space->id));
-
- if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
- fprintf(stderr,
-@@ -774,7 +774,7 @@
- }
-
- if (UNIV_UNLIKELY(space_id == ULINT_UNDEFINED
-- || space_id == 0)) {
-+ || trx_sys_sys_space(space_id))) {
- fprintf(stderr,
- "InnoDB: Error: tablespace id %lu"
- " in file %s is not sensible\n",
-@@ -842,7 +842,7 @@
-
- system->n_open++;
-
-- if (space->purpose == FIL_TABLESPACE && space->id != 0) {
-+ if (space->purpose == FIL_TABLESPACE && !trx_sys_sys_space(space->id)) {
- /* Put the node to the LRU list */
- UT_LIST_ADD_FIRST(LRU, system->LRU, node);
- }
-@@ -876,7 +876,7 @@
- ut_a(system->n_open > 0);
- system->n_open--;
-
-- if (node->space->purpose == FIL_TABLESPACE && node->space->id != 0) {
-+ if (node->space->purpose == FIL_TABLESPACE && !trx_sys_sys_space(node->space->id)) {
- ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
-
- /* The node is in the LRU list, remove it */
-@@ -962,7 +962,7 @@
- retry:
- mutex_enter(&fil_system->mutex);
-
-- if (space_id == 0 || space_id >= SRV_LOG_SPACE_FIRST_ID) {
-+ if (trx_sys_sys_space(space_id) || space_id >= SRV_LOG_SPACE_FIRST_ID) {
- /* We keep log files and system tablespace files always open;
- this is important in preventing deadlocks in this module, as
- a page read completion often performs another read from the
-@@ -1193,7 +1193,7 @@
- " tablespace memory cache!\n",
- (ulong) space->id);
-
-- if (id == 0 || purpose != FIL_TABLESPACE) {
-+ if (trx_sys_sys_space(id) || purpose != FIL_TABLESPACE) {
-
- mutex_exit(&fil_system->mutex);
-
-@@ -1255,6 +1255,7 @@
- space->mark = FALSE;
-
- if (UNIV_LIKELY(purpose == FIL_TABLESPACE && !recv_recovery_on)
-+ && UNIV_UNLIKELY(id < SRV_EXTRA_SYS_SPACE_FIRST_ID)
- && UNIV_UNLIKELY(id > fil_system->max_assigned_id)) {
- if (!fil_system->space_id_reuse_warned) {
- fil_system->space_id_reuse_warned = TRUE;
-@@ -1338,7 +1339,7 @@
- (ulong) SRV_LOG_SPACE_FIRST_ID);
- }
-
-- success = (id < SRV_LOG_SPACE_FIRST_ID);
-+ success = (id < SRV_EXTRA_SYS_SPACE_FIRST_ID);
-
- if (success) {
- *space_id = fil_system->max_assigned_id = id;
-@@ -1601,6 +1602,8 @@
- UT_LIST_INIT(fil_system->LRU);
-
- fil_system->max_n_open = max_n_open;
-+
-+ fil_system->max_assigned_id = TRX_SYS_SPACE_MAX;
- }
-
- /*******************************************************************//**
-@@ -1622,7 +1625,7 @@
- space = UT_LIST_GET_FIRST(fil_system->space_list);
-
- while (space != NULL) {
-- if (space->purpose != FIL_TABLESPACE || space->id == 0) {
-+ if (space->purpose != FIL_TABLESPACE || trx_sys_sys_space(space->id)) {
- node = UT_LIST_GET_FIRST(space->chain);
-
- while (node != NULL) {
-@@ -1712,6 +1715,10 @@
- ut_error;
- }
-
-+ if (max_id >= SRV_EXTRA_SYS_SPACE_FIRST_ID) {
-+ return;
-+ }
-+
- mutex_enter(&fil_system->mutex);
-
- if (fil_system->max_assigned_id < max_id) {
-@@ -1730,6 +1737,7 @@
- ulint
- fil_write_lsn_and_arch_no_to_file(
- /*==============================*/
-+ ulint space_id,
- ulint sum_of_sizes, /*!< in: combined size of previous files
- in space, in database pages */
- ib_uint64_t lsn, /*!< in: lsn to write */
-@@ -1739,14 +1747,16 @@
- byte* buf1;
- byte* buf;
-
-+ ut_a(trx_sys_sys_space(space_id));
-+
- buf1 = mem_alloc(2 * UNIV_PAGE_SIZE);
- buf = ut_align(buf1, UNIV_PAGE_SIZE);
-
-- fil_read(TRUE, 0, 0, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL);
-+ fil_read(TRUE, space_id, 0, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL);
-
- mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN, lsn);
-
-- fil_write(TRUE, 0, 0, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL);
-+ fil_write(TRUE, space_id, 0, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL);
-
- mem_free(buf1);
-
-@@ -1782,7 +1792,7 @@
- always open. */
-
- if (space->purpose == FIL_TABLESPACE
-- && space->id == 0) {
-+ && trx_sys_sys_space(space->id)) {
- sum_of_sizes = 0;
-
- node = UT_LIST_GET_FIRST(space->chain);
-@@ -1790,7 +1800,7 @@
- mutex_exit(&fil_system->mutex);
-
- err = fil_write_lsn_and_arch_no_to_file(
-- sum_of_sizes, lsn, arch_log_no);
-+ space->id, sum_of_sizes, lsn, arch_log_no);
- if (err != DB_SUCCESS) {
-
- return(err);
-@@ -4176,7 +4186,7 @@
- }
-
- #ifndef UNIV_HOTBACKUP
-- if (space_id == ULINT_UNDEFINED || space_id == 0) {
-+ if (space_id == ULINT_UNDEFINED || trx_sys_sys_space(space_id)) {
- fprintf(stderr,
- "InnoDB: Error: tablespace id %lu in file %s"
- " is not sensible\n",
-@@ -4185,7 +4195,7 @@
- goto func_exit;
- }
- #else
-- if (space_id == ULINT_UNDEFINED || space_id == 0) {
-+ if (space_id == ULINT_UNDEFINED || trx_sys_sys_space(space_id)) {
- char* new_path;
-
- fprintf(stderr,
-@@ -5006,7 +5016,7 @@
- }
-
- if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE
-- && space->id != 0) {
-+ && !trx_sys_sys_space(space->id)) {
- /* The node is in the LRU list, remove it */
-
- ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
-@@ -5052,7 +5062,7 @@
- }
-
- if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE
-- && node->space->id != 0) {
-+ && !trx_sys_sys_space(node->space->id)) {
- /* The node must be put back to the LRU list */
- UT_LIST_ADD_FIRST(LRU, system->LRU, node);
- }
-@@ -5663,7 +5673,7 @@
- ut_a(fil_node->n_pending == 0);
- ut_a(fil_node->open);
- ut_a(fil_node->space->purpose == FIL_TABLESPACE);
-- ut_a(fil_node->space->id != 0);
-+ ut_a(!trx_sys_sys_space(fil_node->space->id));
-
- fil_node = UT_LIST_GET_NEXT(LRU, fil_node);
- }
---- a/storage/innobase/fsp/fsp0fsp.c
-+++ b/storage/innobase/fsp/fsp0fsp.c
-@@ -48,7 +48,7 @@
- # include "log0log.h"
- #endif /* UNIV_HOTBACKUP */
- #include "dict0mem.h"
--
-+#include "trx0sys.h"
-
- /* FILE SEGMENT INODE
- ==================
-@@ -938,10 +938,10 @@
- flst_init(header + FSP_SEG_INODES_FREE, mtr);
-
- mlog_write_ull(header + FSP_SEG_ID, 1, mtr);
-- if (space == 0) {
-+ if (space == TRX_SYS_SPACE || space == TRX_DOUBLEWRITE_SPACE) {
- fsp_fill_free_list(FALSE, space, header, mtr);
- btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,
-- 0, 0, DICT_IBUF_ID_MIN + space,
-+ space, 0, DICT_IBUF_ID_MIN + space,
- dict_ind_redundant, mtr);
- } else {
- fsp_fill_free_list(TRUE, space, header, mtr);
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -163,6 +163,7 @@
- static char* innobase_log_group_home_dir = NULL;
- static char* innobase_file_format_name = NULL;
- static char* innobase_change_buffering = NULL;
-+static char* innobase_doublewrite_file = NULL;
-
- /* The highest file format being used in the database. The value can be
- set by user, however, it will be adjusted to the newer file format if
-@@ -2508,6 +2509,8 @@
- goto error;
- }
-
-+ srv_doublewrite_file = innobase_doublewrite_file;
-+
- srv_use_sys_stats_table = (ibool) innobase_use_sys_stats_table;
-
- /* -------------- Log files ---------------------------*/
-@@ -11771,6 +11774,11 @@
- "Path to individual files and their sizes.",
- NULL, NULL, NULL);
-
-+static MYSQL_SYSVAR_STR(doublewrite_file, innobase_doublewrite_file,
-+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
-+ "Path to special datafile for doublewrite buffer. (default is "": not used) ### ONLY FOR EXPERTS!!! ###",
-+ NULL, NULL, NULL);
-+
- static MYSQL_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
- "The AUTOINC lock modes supported by InnoDB: "
-@@ -11990,6 +11998,7 @@
- MYSQL_SYSVAR(commit_concurrency),
- MYSQL_SYSVAR(concurrency_tickets),
- MYSQL_SYSVAR(data_file_path),
-+ MYSQL_SYSVAR(doublewrite_file),
- MYSQL_SYSVAR(data_home_dir),
- MYSQL_SYSVAR(doublewrite),
- MYSQL_SYSVAR(recovery_stats),
---- a/storage/innobase/include/mtr0log.ic
-+++ b/storage/innobase/include/mtr0log.ic
-@@ -27,8 +27,8 @@
- #include "ut0lst.h"
- #include "buf0buf.h"
- #include "fsp0types.h"
-+#include "srv0srv.h"
- #include "trx0sys.h"
--
- /********************************************************//**
- Opens a buffer to mlog. It must be closed with mlog_close.
- @return buffer, NULL if log mode MTR_LOG_NONE */
-@@ -201,7 +201,8 @@
- the doublewrite buffer is located in pages
- FSP_EXTENT_SIZE, ..., 3 * FSP_EXTENT_SIZE - 1 in the
- system tablespace */
-- if (space == TRX_SYS_SPACE
-+ if ((space == TRX_SYS_SPACE
-+ || (srv_doublewrite_file && space == TRX_DOUBLEWRITE_SPACE))
- && offset >= FSP_EXTENT_SIZE && offset < 3 * FSP_EXTENT_SIZE) {
- if (trx_doublewrite_buf_is_being_created) {
- /* Do nothing: we only come to this branch in an
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -129,6 +129,8 @@
- extern ulint* srv_data_file_sizes;
- extern ulint* srv_data_file_is_raw_partition;
-
-+extern char* srv_doublewrite_file;
-+
- extern ibool srv_recovery_stats;
-
- extern ibool srv_auto_extend_last_data_file;
---- a/storage/innobase/include/srv0start.h
-+++ b/storage/innobase/include/srv0start.h
-@@ -127,4 +127,7 @@
- /** Log 'spaces' have id's >= this */
- #define SRV_LOG_SPACE_FIRST_ID 0xFFFFFFF0UL
-
-+/** reserved for extra system tables */
-+#define SRV_EXTRA_SYS_SPACE_FIRST_ID 0xFFFFFFE0UL
-+
- #endif
---- a/storage/innobase/include/trx0sys.h
-+++ b/storage/innobase/include/trx0sys.h
-@@ -125,6 +125,22 @@
- /*=============*/
- ulint space, /*!< in: space */
- ulint page_no);/*!< in: page number */
-+/***************************************************************//**
-+Checks if a space is the system tablespaces.
-+@return TRUE if system tablespace */
-+UNIV_INLINE
-+ibool
-+trx_sys_sys_space(
-+/*==============*/
-+ ulint space); /*!< in: space */
-+/***************************************************************//**
-+Checks if a space is the doublewrite tablespace.
-+@return TRUE if doublewrite tablespace */
-+UNIV_INLINE
-+ibool
-+trx_sys_doublewrite_space(
-+/*======================*/
-+ ulint space); /*!< in: space */
- /*****************************************************************//**
- Creates and initializes the central memory structures for the transaction
- system. This is called when the database is started. */
-@@ -138,6 +154,13 @@
- void
- trx_sys_create(void);
- /*================*/
-+/*****************************************************************//**
-+Creates and initializes the dummy transaction system page for tablespace. */
-+UNIV_INTERN
-+void
-+trx_sys_dummy_create(
-+/*=================*/
-+ ulint space);
- /****************************************************************//**
- Looks for a free slot for a rollback segment in the trx system file copy.
- @return slot index or ULINT_UNDEFINED if not found */
-@@ -453,6 +476,8 @@
-
- /* Space id and page no where the trx system file copy resides */
- #define TRX_SYS_SPACE 0 /* the SYSTEM tablespace */
-+#define TRX_DOUBLEWRITE_SPACE 0xFFFFFFE0UL /* the doublewrite buffer tablespace if used */
-+#define TRX_SYS_SPACE_MAX 9 /* reserved max space id for system tablespaces */
- #include "fsp0fsp.h"
- #define TRX_SYS_PAGE_NO FSP_TRX_SYS_PAGE_NO
-
---- a/storage/innobase/include/trx0sys.ic
-+++ b/storage/innobase/include/trx0sys.ic
-@@ -71,6 +71,40 @@
- }
-
- /***************************************************************//**
-+Checks if a space is the system tablespaces.
-+@return TRUE if system tablespace */
-+UNIV_INLINE
-+ibool
-+trx_sys_sys_space(
-+/*==============*/
-+ ulint space) /*!< in: space */
-+{
-+ if (srv_doublewrite_file) {
-+ /* several spaces are reserved */
-+ return((ibool)(space == TRX_SYS_SPACE || space == TRX_DOUBLEWRITE_SPACE));
-+ } else {
-+ return((ibool)(space == TRX_SYS_SPACE));
-+ }
-+}
-+
-+/***************************************************************//**
-+Checks if a space is the doublewrite tablespace.
-+@return TRUE if doublewrite tablespace */
-+UNIV_INLINE
-+ibool
-+trx_sys_doublewrite_space(
-+/*======================*/
-+ ulint space) /*!< in: space */
-+{
-+ if (srv_doublewrite_file) {
-+ /* doublewrite buffer is separated */
-+ return((ibool)(space == TRX_DOUBLEWRITE_SPACE));
-+ } else {
-+ return((ibool)(space == TRX_SYS_SPACE));
-+ }
-+}
-+
-+/***************************************************************//**
- Gets the pointer in the nth slot of the rseg array.
- @return pointer to rseg object, NULL if slot not in use */
- UNIV_INLINE
---- a/storage/innobase/row/row0mysql.c
-+++ b/storage/innobase/row/row0mysql.c
-@@ -3436,7 +3436,7 @@
- /* Do not drop possible .ibd tablespace if something went
- wrong: we do not want to delete valuable data of the user */
-
-- if (err == DB_SUCCESS && space_id > 0) {
-+ if (err == DB_SUCCESS && !trx_sys_sys_space(space_id)) {
- if (!fil_space_for_table_exists_in_mem(space_id,
- name_or_path,
- is_temp, FALSE,
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -163,6 +163,8 @@
- /* size in database pages */
- UNIV_INTERN ulint* srv_data_file_sizes = NULL;
-
-+UNIV_INTERN char* srv_doublewrite_file = NULL;
-+
- UNIV_INTERN ibool srv_recovery_stats = FALSE;
-
- /* if TRUE, then we auto-extend the last data file */
---- a/storage/innobase/srv/srv0start.c
-+++ b/storage/innobase/srv/srv0start.c
-@@ -715,6 +715,7 @@
- /*======================*/
- ibool* create_new_db, /*!< out: TRUE if new database should be
- created */
-+ ibool* create_new_doublewrite_file,
- #ifdef UNIV_LOG_ARCHIVE
- ulint* min_arch_log_no,/*!< out: min of archived log
- numbers in data files */
-@@ -748,6 +749,7 @@
- *sum_of_new_sizes = 0;
-
- *create_new_db = FALSE;
-+ *create_new_doublewrite_file = FALSE;
-
- srv_normalize_path_for_win(srv_data_home);
-
-@@ -1004,6 +1006,142 @@
- srv_data_file_is_raw_partition[i] != 0);
- }
-
-+ /* special file for doublewrite buffer */
-+ if (srv_doublewrite_file)
-+ {
-+ srv_normalize_path_for_win(srv_doublewrite_file);
-+
-+ fprintf(stderr,
-+ "InnoDB: Note: The innodb_doublewrite_file option has been specified.\n"
-+ "InnoDB: This option is for experts only. Don't use it unless you understand WELL what it is.\n"
-+ "InnoDB: ### Don't specify a file older than the last checkpoint. ###\n"
-+ "InnoDB: Otherwise, the older doublewrite buffer will break your data during recovery!\n");
-+
-+ strcpy(name, srv_doublewrite_file);
-+
-+ /* First we try to create the file: if it already
-+ exists, ret will get value FALSE */
-+
-+ files[i] = os_file_create(innodb_file_data_key, name, OS_FILE_CREATE,
-+ OS_FILE_NORMAL,
-+ OS_DATA_FILE, &ret);
-+
-+ if (ret == FALSE && os_file_get_last_error(FALSE)
-+ != OS_FILE_ALREADY_EXISTS
-+#ifdef UNIV_AIX
-+ /* AIX 5.1 after security patch ML7 may have
-+ errno set to 0 here, which causes our function
-+ to return 100; work around that AIX problem */
-+ && os_file_get_last_error(FALSE) != 100
-+#endif
-+ ) {
-+ fprintf(stderr,
-+ "InnoDB: Error in creating"
-+ " or opening %s\n",
-+ name);
-+
-+ return(DB_ERROR);
-+ }
-+
-+ if (ret == FALSE) {
-+ /* We open the data file */
-+
-+ files[i] = os_file_create(innodb_file_data_key,
-+ name, OS_FILE_OPEN, OS_FILE_NORMAL,
-+ OS_DATA_FILE, &ret);
-+
-+ if (!ret) {
-+ fprintf(stderr,
-+ "InnoDB: Error in opening %s\n", name);
-+ os_file_get_last_error(TRUE);
-+
-+ return(DB_ERROR);
-+ }
-+
-+ ret = os_file_get_size(files[i], &size, &size_high);
-+ ut_a(ret);
-+ /* Round size downward to megabytes */
-+
-+ rounded_size_pages
-+ = (size / (1024 * 1024) + 4096 * size_high)
-+ << (20 - UNIV_PAGE_SIZE_SHIFT);
-+
-+ if (rounded_size_pages != TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9) {
-+
-+ fprintf(stderr,
-+ "InnoDB: Warning: doublewrite buffer file %s"
-+ " is of a different size\n"
-+ "InnoDB: %lu pages"
-+ " (rounded down to MB)\n"
-+ "InnoDB: than intended size"
-+ " %lu pages...\n",
-+ name,
-+ (ulong) rounded_size_pages,
-+ (ulong) TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9);
-+ }
-+
-+ fil_read_first_page(
-+ files[i], one_opened, &flags,
-+#ifdef UNIV_LOG_ARCHIVE
-+ min_arch_log_no, max_arch_log_no,
-+#endif /* UNIV_LOG_ARCHIVE */
-+ min_flushed_lsn, max_flushed_lsn);
-+ one_opened = TRUE;
-+ } else {
-+ /* We created the data file and now write it full of
-+ zeros */
-+
-+ *create_new_doublewrite_file = TRUE;
-+
-+ ut_print_timestamp(stderr);
-+ fprintf(stderr,
-+ " InnoDB: Doublewrite buffer file %s did not"
-+ " exist. It will be be created.\n",
-+ name);
-+
-+ if (*create_new_db == FALSE) {
-+ fprintf(stderr,
-+ "InnoDB: Notice: Previous version's ibdata files may cause crash.\n"
-+ " If you use that, please use the ibdata files of this version.\n");
-+ }
-+
-+ ut_print_timestamp(stderr);
-+ fprintf(stderr,
-+ " InnoDB: Setting file %s size to %lu MB\n",
-+ name,
-+ (ulong) ((TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9)
-+ >> (20 - UNIV_PAGE_SIZE_SHIFT)));
-+
-+ fprintf(stderr,
-+ "InnoDB: Database physically writes the"
-+ " file full: wait...\n");
-+
-+ ret = os_file_set_size(
-+ name, files[i],
-+ srv_calc_low32(TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9),
-+ srv_calc_high32(TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9));
-+
-+ if (!ret) {
-+ fprintf(stderr,
-+ "InnoDB: Error in creating %s:"
-+ " probably out of disk space\n", name);
-+
-+ return(DB_ERROR);
-+ }
-+ }
-+
-+ ret = os_file_close(files[i]);
-+ ut_a(ret);
-+
-+ fil_space_create(name, TRX_DOUBLEWRITE_SPACE, 0, FIL_TABLESPACE);
-+
-+ ut_a(fil_validate());
-+
-+ fil_node_create(name, TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9, TRX_DOUBLEWRITE_SPACE, FALSE);
-+
-+ i++;
-+ }
-+
- return(DB_SUCCESS);
- }
-
-@@ -1017,6 +1155,7 @@
- /*====================================*/
- {
- ibool create_new_db;
-+ ibool create_new_doublewrite_file;
- ibool log_file_created;
- ibool log_created = FALSE;
- ibool log_opened = FALSE;
-@@ -1482,6 +1621,7 @@
- }
-
- err = open_or_create_data_files(&create_new_db,
-+ &create_new_doublewrite_file,
- #ifdef UNIV_LOG_ARCHIVE
- &min_arch_log_no, &max_arch_log_no,
- #endif /* UNIV_LOG_ARCHIVE */
-@@ -1649,6 +1789,14 @@
- after the double write buffer has been created. */
- trx_sys_create();
-
-+ if (create_new_doublewrite_file) {
-+ mtr_start(&mtr);
-+ fsp_header_init(TRX_DOUBLEWRITE_SPACE, TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9, &mtr);
-+ mtr_commit(&mtr);
-+
-+ trx_sys_dummy_create(TRX_DOUBLEWRITE_SPACE);
-+ }
-+
- dict_create();
-
- srv_startup_is_before_trx_rollback_phase = FALSE;
-@@ -1682,6 +1830,13 @@
- recv_recovery_from_archive_finish();
- #endif /* UNIV_LOG_ARCHIVE */
- } else {
-+ char* save_srv_doublewrite_file = NULL;
-+
-+ if (create_new_doublewrite_file) {
-+ /* doublewrite_file cannot be used for recovery yet. */
-+ save_srv_doublewrite_file = srv_doublewrite_file;
-+ srv_doublewrite_file = NULL;
-+ }
-
- /* Check if we support the max format that is stamped
- on the system tablespace.
-@@ -1768,6 +1923,17 @@
- we have finished the recovery process so that the
- image of TRX_SYS_PAGE_NO is not stale. */
- trx_sys_file_format_tag_init();
-+
-+ if (create_new_doublewrite_file) {
-+ /* restore the value */
-+ srv_doublewrite_file = save_srv_doublewrite_file;
-+
-+ mtr_start(&mtr);
-+ fsp_header_init(TRX_DOUBLEWRITE_SPACE, TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9, &mtr);
-+ mtr_commit(&mtr);
-+
-+ trx_sys_dummy_create(TRX_DOUBLEWRITE_SPACE);
-+ }
- }
-
- if (!create_new_db && sum_of_new_sizes > 0) {
---- a/storage/innobase/trx/trx0sys.c
-+++ b/storage/innobase/trx/trx0sys.c
-@@ -415,6 +415,152 @@
-
- goto start_again;
- }
-+
-+ if (srv_doublewrite_file) {
-+ /* the same doublewrite buffer to TRX_SYS_SPACE should exist.
-+ check and create if not exist.*/
-+
-+ mtr_start(&mtr);
-+ trx_doublewrite_buf_is_being_created = TRUE;
-+
-+ block = buf_page_get(TRX_DOUBLEWRITE_SPACE, 0, TRX_SYS_PAGE_NO,
-+ RW_X_LATCH, &mtr);
-+ buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
-+
-+ doublewrite = buf_block_get_frame(block) + TRX_SYS_DOUBLEWRITE;
-+
-+ if (mach_read_from_4(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC)
-+ == TRX_SYS_DOUBLEWRITE_MAGIC_N) {
-+ /* The doublewrite buffer has already been created:
-+ just read in some numbers */
-+
-+ mtr_commit(&mtr);
-+ } else {
-+ fprintf(stderr,
-+ "InnoDB: Doublewrite buffer not found in the doublewrite file:"
-+ " creating new doublewrite buffer.\n");
-+
-+ if (buf_pool_get_curr_size()
-+ < ((2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
-+ + FSP_EXTENT_SIZE / 2 + 100)
-+ * UNIV_PAGE_SIZE)) {
-+ fprintf(stderr,
-+ "InnoDB: Cannot create the doublewrite buffer:"
-+ " You must\n"
-+ "InnoDB: increase your buffer pool size.\n"
-+ "InnoDB: Cannot continue processing.\n");
-+
-+ exit(1);
-+ }
-+
-+ block2 = fseg_create(TRX_DOUBLEWRITE_SPACE, TRX_SYS_PAGE_NO,
-+ TRX_SYS_DOUBLEWRITE
-+ + TRX_SYS_DOUBLEWRITE_FSEG, &mtr);
-+
-+ /* fseg_create acquires a second latch on the page,
-+ therefore we must declare it: */
-+
-+ buf_block_dbg_add_level(block2, SYNC_NO_ORDER_CHECK);
-+
-+ if (block2 == NULL) {
-+ fprintf(stderr,
-+ "InnoDB: Cannot create the doublewrite buffer:"
-+ " You must\n"
-+ "InnoDB: increase your tablespace size.\n"
-+ "InnoDB: Cannot continue processing.\n");
-+
-+ /* We exit without committing the mtr to prevent
-+ its modifications to the database getting to disk */
-+
-+ exit(1);
-+ }
-+
-+ fseg_header = buf_block_get_frame(block)
-+ + TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_FSEG;
-+ prev_page_no = 0;
-+
-+ for (i = 0; i < 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
-+ + FSP_EXTENT_SIZE / 2; i++) {
-+ page_no = fseg_alloc_free_page(fseg_header,
-+ prev_page_no + 1,
-+ FSP_UP, &mtr);
-+ if (page_no == FIL_NULL) {
-+ fprintf(stderr,
-+ "InnoDB: Cannot create the doublewrite"
-+ " buffer: You must\n"
-+ "InnoDB: increase your"
-+ " tablespace size.\n"
-+ "InnoDB: Cannot continue operation.\n"
-+ );
-+
-+ exit(1);
-+ }
-+
-+ /* We read the allocated pages to the buffer pool;
-+ when they are written to disk in a flush, the space
-+ id and page number fields are also written to the
-+ pages. When we at database startup read pages
-+ from the doublewrite buffer, we know that if the
-+ space id and page number in them are the same as
-+ the page position in the tablespace, then the page
-+ has not been written to in doublewrite. */
-+
-+#ifdef UNIV_SYNC_DEBUG
-+ new_block =
-+#endif /* UNIV_SYNC_DEBUG */
-+ buf_page_get(TRX_DOUBLEWRITE_SPACE, 0, page_no,
-+ RW_X_LATCH, &mtr);
-+ buf_block_dbg_add_level(new_block,
-+ SYNC_NO_ORDER_CHECK);
-+
-+ if (i == FSP_EXTENT_SIZE / 2) {
-+ ut_a(page_no == FSP_EXTENT_SIZE);
-+ mlog_write_ulint(doublewrite
-+ + TRX_SYS_DOUBLEWRITE_BLOCK1,
-+ page_no, MLOG_4BYTES, &mtr);
-+ mlog_write_ulint(doublewrite
-+ + TRX_SYS_DOUBLEWRITE_REPEAT
-+ + TRX_SYS_DOUBLEWRITE_BLOCK1,
-+ page_no, MLOG_4BYTES, &mtr);
-+ } else if (i == FSP_EXTENT_SIZE / 2
-+ + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
-+ ut_a(page_no == 2 * FSP_EXTENT_SIZE);
-+ mlog_write_ulint(doublewrite
-+ + TRX_SYS_DOUBLEWRITE_BLOCK2,
-+ page_no, MLOG_4BYTES, &mtr);
-+ mlog_write_ulint(doublewrite
-+ + TRX_SYS_DOUBLEWRITE_REPEAT
-+ + TRX_SYS_DOUBLEWRITE_BLOCK2,
-+ page_no, MLOG_4BYTES, &mtr);
-+ } else if (i > FSP_EXTENT_SIZE / 2) {
-+ ut_a(page_no == prev_page_no + 1);
-+ }
-+
-+ prev_page_no = page_no;
-+ }
-+
-+ mlog_write_ulint(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC,
-+ TRX_SYS_DOUBLEWRITE_MAGIC_N,
-+ MLOG_4BYTES, &mtr);
-+ mlog_write_ulint(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC
-+ + TRX_SYS_DOUBLEWRITE_REPEAT,
-+ TRX_SYS_DOUBLEWRITE_MAGIC_N,
-+ MLOG_4BYTES, &mtr);
-+
-+ mlog_write_ulint(doublewrite
-+ + TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED,
-+ TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N,
-+ MLOG_4BYTES, &mtr);
-+ mtr_commit(&mtr);
-+
-+ /* Flush the modified pages to disk and make a checkpoint */
-+ log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE);
-+
-+ fprintf(stderr, "InnoDB: Doublewrite buffer created in the doublewrite file\n");
-+ trx_sys_multiple_tablespace_format = TRUE;
-+ }
-+ trx_doublewrite_buf_is_being_created = FALSE;
-+ }
- }
-
- /****************************************************************//**
-@@ -438,10 +584,19 @@
- ulint source_page_no;
- byte* page;
- byte* doublewrite;
-+ ulint doublewrite_space_id;
- ulint space_id;
- ulint page_no;
- ulint i;
-
-+ doublewrite_space_id = (srv_doublewrite_file ? TRX_DOUBLEWRITE_SPACE : TRX_SYS_SPACE);
-+
-+ if (srv_doublewrite_file) {
-+ fprintf(stderr,
-+ "InnoDB: doublewrite file '%s' is used.\n",
-+ srv_doublewrite_file);
-+ }
-+
- /* We do the file i/o past the buffer pool */
-
- unaligned_read_buf = ut_malloc(2 * UNIV_PAGE_SIZE);
-@@ -450,7 +605,7 @@
- /* Read the trx sys header to check if we are using the doublewrite
- buffer */
-
-- fil_io(OS_FILE_READ, TRUE, TRX_SYS_SPACE, 0, TRX_SYS_PAGE_NO, 0,
-+ fil_io(OS_FILE_READ, TRUE, doublewrite_space_id, 0, TRX_SYS_PAGE_NO, 0,
- UNIV_PAGE_SIZE, read_buf, NULL);
- doublewrite = read_buf + TRX_SYS_DOUBLEWRITE;
-
-@@ -488,10 +643,10 @@
-
- /* Read the pages from the doublewrite buffer to memory */
-
-- fil_io(OS_FILE_READ, TRUE, TRX_SYS_SPACE, 0, block1, 0,
-+ fil_io(OS_FILE_READ, TRUE, doublewrite_space_id, 0, block1, 0,
- TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE,
- buf, NULL);
-- fil_io(OS_FILE_READ, TRUE, TRX_SYS_SPACE, 0, block2, 0,
-+ fil_io(OS_FILE_READ, TRUE, doublewrite_space_id, 0, block2, 0,
- TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE,
- buf + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE,
- NULL);
-@@ -547,7 +702,8 @@
- " doublewrite buf.\n",
- (ulong) space_id, (ulong) page_no, (ulong) i);
-
-- } else if (space_id == TRX_SYS_SPACE
-+ } else if ((space_id == TRX_SYS_SPACE
-+ || (srv_doublewrite_file && space_id == TRX_DOUBLEWRITE_SPACE))
- && ((page_no >= block1
- && page_no
- < block1 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE)
-@@ -1016,6 +1172,83 @@
- }
-
- /*****************************************************************//**
-+Creates dummy of the file page for the transaction system. */
-+static
-+void
-+trx_sysf_dummy_create(
-+/*==================*/
-+ ulint space,
-+ mtr_t* mtr)
-+{
-+ buf_block_t* block;
-+ page_t* page;
-+
-+ ut_ad(mtr);
-+
-+ /* Note that below we first reserve the file space x-latch, and
-+ then enter the kernel: we must do it in this order to conform
-+ to the latching order rules. */
-+
-+ mtr_x_lock(fil_space_get_latch(space, NULL), mtr);
-+ mutex_enter(&kernel_mutex);
-+
-+ /* Create the trx sys file block in a new allocated file segment */
-+ block = fseg_create(space, 0, TRX_SYS + TRX_SYS_FSEG_HEADER,
-+ mtr);
-+ buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER);
-+
-+ fprintf(stderr, "%lu\n", buf_block_get_page_no(block));
-+ ut_a(buf_block_get_page_no(block) == TRX_SYS_PAGE_NO);
-+
-+ page = buf_block_get_frame(block);
-+
-+ mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_TYPE_TRX_SYS,
-+ MLOG_2BYTES, mtr);
-+
-+ /* Reset the doublewrite buffer magic number to zero so that we
-+ know that the doublewrite buffer has not yet been created (this
-+ suppresses a Valgrind warning) */
-+
-+ mlog_write_ulint(page + TRX_SYS_DOUBLEWRITE
-+ + TRX_SYS_DOUBLEWRITE_MAGIC, 0, MLOG_4BYTES, mtr);
-+
-+#ifdef UNDEFINED
-+ /* TODO: REMOVE IT: The bellow is not needed, I think */
-+ sys_header = trx_sysf_get(mtr);
-+
-+ /* Start counting transaction ids from number 1 up */
-+ mlog_write_dulint(sys_header + TRX_SYS_TRX_ID_STORE,
-+ ut_dulint_create(0, 1), mtr);
-+
-+ /* Reset the rollback segment slots */
-+ for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
-+
-+ trx_sysf_rseg_set_space(sys_header, i, ULINT_UNDEFINED, mtr);
-+ trx_sysf_rseg_set_page_no(sys_header, i, FIL_NULL, mtr);
-+ }
-+
-+ /* The remaining area (up to the page trailer) is uninitialized.
-+ Silence Valgrind warnings about it. */
-+ UNIV_MEM_VALID(sys_header + (TRX_SYS_RSEGS
-+ + TRX_SYS_N_RSEGS * TRX_SYS_RSEG_SLOT_SIZE
-+ + TRX_SYS_RSEG_SPACE),
-+ (UNIV_PAGE_SIZE - FIL_PAGE_DATA_END
-+ - (TRX_SYS_RSEGS
-+ + TRX_SYS_N_RSEGS * TRX_SYS_RSEG_SLOT_SIZE
-+ + TRX_SYS_RSEG_SPACE))
-+ + page - sys_header);
-+
-+ /* Create the first rollback segment in the SYSTEM tablespace */
-+ page_no = trx_rseg_header_create(space, 0, ULINT_MAX, &slot_no,
-+ mtr);
-+ ut_a(slot_no == TRX_SYS_SYSTEM_RSEG_ID);
-+ ut_a(page_no != FIL_NULL);
-+#endif
-+
-+ mutex_exit(&kernel_mutex);
-+}
-+
-+/*****************************************************************//**
- Creates and initializes the central memory structures for the transaction
- system. This is called when the database is started. */
- UNIV_INTERN
-@@ -1387,6 +1620,26 @@
- /* Does nothing at the moment */
- }
-
-+/*****************************************************************//**
-+Creates and initializes the dummy transaction system page for tablespace. */
-+UNIV_INTERN
-+void
-+trx_sys_dummy_create(
-+/*=================*/
-+ ulint space)
-+{
-+ mtr_t mtr;
-+
-+ /* This function is only for doublewrite file for now */
-+ ut_a(space == TRX_DOUBLEWRITE_SPACE);
-+
-+ mtr_start(&mtr);
-+
-+ trx_sysf_dummy_create(space, &mtr);
-+
-+ mtr_commit(&mtr);
-+}
-+
- /*********************************************************************
- Creates the rollback segments */
- UNIV_INTERN
---- /dev/null
-+++ b/mysql-test/r/percona_innodb_doublewrite_file.result
-@@ -0,0 +1,4 @@
-+show variables like 'innodb_doublewrite%';
-+Variable_name Value
-+innodb_doublewrite ON
-+innodb_doublewrite_file ib_doublewrite
---- /dev/null
-+++ b/mysql-test/t/percona_innodb_doublewrite_file-master.opt
-@@ -0,0 +1 @@
-+--innodb_doublewrite_file=ib_doublewrite
---- /dev/null
-+++ b/mysql-test/t/percona_innodb_doublewrite_file.test
-@@ -0,0 +1,2 @@
-+--source include/have_innodb.inc
-+show variables like 'innodb_doublewrite%';
+++ /dev/null
-# name : innodb_show_lock_name.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -9709,9 +9709,8 @@
- rw_lock_wait_time += mutex->lspent_time;
- }
- #else /* UNIV_DEBUG */
-- buf1len= (uint) my_snprintf(buf1, sizeof(buf1), "%s:%lu",
-- innobase_basename(mutex->cfile_name),
-- (ulong) mutex->cline);
-+ buf1len= (uint) my_snprintf(buf1, sizeof(buf1), "%s",
-+ mutex->cmutex_name);
- buf2len= (uint) my_snprintf(buf2, sizeof(buf2), "os_waits=%lu",
- (ulong) mutex->count_os_wait);
-
-@@ -9726,10 +9725,8 @@
-
- if (block_mutex) {
- buf1len = (uint) my_snprintf(buf1, sizeof buf1,
-- "combined %s:%lu",
-- innobase_basename(
-- block_mutex->cfile_name),
-- (ulong) block_mutex->cline);
-+ "combined %s",
-+ block_mutex->cmutex_name);
- buf2len = (uint) my_snprintf(buf2, sizeof buf2,
- "os_waits=%lu",
- (ulong) block_mutex_oswait_count);
-@@ -9758,9 +9755,8 @@
- continue;
- }
-
-- buf1len = my_snprintf(buf1, sizeof buf1, "%s:%lu",
-- innobase_basename(lock->cfile_name),
-- (ulong) lock->cline);
-+ buf1len = my_snprintf(buf1, sizeof buf1, "%s",
-+ lock->lock_name);
- buf2len = my_snprintf(buf2, sizeof buf2, "os_waits=%lu",
- (ulong) lock->count_os_wait);
-
-@@ -9774,10 +9770,8 @@
-
- if (block_lock) {
- buf1len = (uint) my_snprintf(buf1, sizeof buf1,
-- "combined %s:%lu",
-- innobase_basename(
-- block_lock->cfile_name),
-- (ulong) block_lock->cline);
-+ "combined %s",
-+ block_lock->lock_name);
- buf2len = (uint) my_snprintf(buf2, sizeof buf2,
- "os_waits=%lu",
- (ulong) block_lock_oswait_count);
---- a/storage/innobase/include/sync0rw.h
-+++ b/storage/innobase/include/sync0rw.h
-@@ -138,14 +138,14 @@
- # ifdef UNIV_DEBUG
- # ifdef UNIV_SYNC_DEBUG
- # define rw_lock_create(K, L, level) \
-- rw_lock_create_func((L), (level), #L, __FILE__, __LINE__)
-+ rw_lock_create_func((L), (level), __FILE__, __LINE__, #L)
- # else /* UNIV_SYNC_DEBUG */
- # define rw_lock_create(K, L, level) \
-- rw_lock_create_func((L), #L, __FILE__, __LINE__)
-+ rw_lock_create_func((L), __FILE__, __LINE__, #L)
- # endif/* UNIV_SYNC_DEBUG */
- # else /* UNIV_DEBUG */
- # define rw_lock_create(K, L, level) \
-- rw_lock_create_func((L), __FILE__, __LINE__)
-+ rw_lock_create_func((L), #L)
- # endif /* UNIV_DEBUG */
-
- /**************************************************************//**
-@@ -191,14 +191,14 @@
- # ifdef UNIV_DEBUG
- # ifdef UNIV_SYNC_DEBUG
- # define rw_lock_create(K, L, level) \
-- pfs_rw_lock_create_func((K), (L), (level), #L, __FILE__, __LINE__)
-+ pfs_rw_lock_create_func((K), (L), (level), __FILE__, __LINE__, #L)
- # else /* UNIV_SYNC_DEBUG */
- # define rw_lock_create(K, L, level) \
-- pfs_rw_lock_create_func((K), (L), #L, __FILE__, __LINE__)
-+ pfs_rw_lock_create_func((K), (L), __FILE__, __LINE__, #L)
- # endif/* UNIV_SYNC_DEBUG */
- # else /* UNIV_DEBUG */
- # define rw_lock_create(K, L, level) \
-- pfs_rw_lock_create_func((K), (L), __FILE__, __LINE__)
-+ pfs_rw_lock_create_func((K), (L), #L)
- # endif /* UNIV_DEBUG */
-
- /******************************************************************
-@@ -256,10 +256,10 @@
- # ifdef UNIV_SYNC_DEBUG
- ulint level, /*!< in: level */
- # endif /* UNIV_SYNC_DEBUG */
-- const char* cmutex_name, /*!< in: mutex name */
--#endif /* UNIV_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
-- ulint cline); /*!< in: file line where created */
-+ ulint cline, /*!< in: file line where created */
-+#endif /* UNIV_DEBUG */
-+ const char* cmutex_name); /*!< in: mutex name */
- /******************************************************************//**
- Calling this function is obligatory only if the memory buffer containing
- the rw-lock is freed. Removes an rw-lock object from the global list. The
-@@ -611,7 +611,8 @@
- struct PSI_rwlock *pfs_psi;/*!< The instrumentation hook */
- #endif
- ulint count_os_wait; /*!< Count of os_waits. May not be accurate */
-- const char* cfile_name;/*!< File name where lock created */
-+ //const char* cfile_name;/*!< File name where lock created */
-+ const char* lock_name;/*!< lock name */
- /* last s-lock file/line is not guaranteed to be correct */
- const char* last_s_file_name;/*!< File name where last s-locked */
- const char* last_x_file_name;/*!< File name where last x-locked */
-@@ -622,7 +623,7 @@
- are at the start of this struct, thus we can
- peek this field without causing much memory
- bus traffic */
-- unsigned cline:14; /*!< Line where created */
-+ //unsigned cline:14; /*!< Line where created */
- unsigned last_s_line:14; /*!< Line number where last time s-locked */
- unsigned last_x_line:14; /*!< Line number where last time x-locked */
- #ifdef UNIV_DEBUG
-@@ -693,10 +694,10 @@
- # ifdef UNIV_SYNC_DEBUG
- ulint level, /*!< in: level */
- # endif /* UNIV_SYNC_DEBUG */
-- const char* cmutex_name, /*!< in: mutex name */
--#endif /* UNIV_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
-- ulint cline); /*!< in: file line where created */
-+ ulint cline, /*!< in: file line where created */
-+#endif /* UNIV_DEBUG */
-+ const char* cmutex_name); /*!< in: mutex name */
-
- /******************************************************************//**
- Performance schema instrumented wrap function for rw_lock_x_lock_func()
---- a/storage/innobase/include/sync0rw.ic
-+++ b/storage/innobase/include/sync0rw.ic
-@@ -641,10 +641,10 @@
- # ifdef UNIV_SYNC_DEBUG
- ulint level, /*!< in: level */
- # endif /* UNIV_SYNC_DEBUG */
-- const char* cmutex_name, /*!< in: mutex name */
--# endif /* UNIV_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
-- ulint cline) /*!< in: file line where created */
-+ ulint cline, /*!< in: file line where created */
-+# endif /* UNIV_DEBUG */
-+ const char* cmutex_name) /*!< in: mutex name */
- {
- /* Initialize the rwlock for performance schema */
- lock->pfs_psi = (PSI_server && PFS_IS_INSTRUMENTED(key))
-@@ -657,10 +657,10 @@
- # ifdef UNIV_SYNC_DEBUG
- level,
- # endif /* UNIV_SYNC_DEBUG */
-- cmutex_name,
--# endif /* UNIV_DEBUG */
- cfile_name,
-- cline);
-+ cline,
-+# endif /* UNIV_DEBUG */
-+ cmutex_name);
- }
- /******************************************************************//**
- Performance schema instrumented wrap function for rw_lock_x_lock_func()
---- a/storage/innobase/include/sync0sync.h
-+++ b/storage/innobase/include/sync0sync.h
-@@ -158,14 +158,14 @@
- # ifdef UNIV_DEBUG
- # ifdef UNIV_SYNC_DEBUG
- # define mutex_create(K, M, level) \
-- pfs_mutex_create_func((K), (M), #M, (level), __FILE__, __LINE__)
-+ pfs_mutex_create_func((K), (M), (level), __FILE__, __LINE__, #M)
- # else
- # define mutex_create(K, M, level) \
-- pfs_mutex_create_func((K), (M), #M, __FILE__, __LINE__)
-+ pfs_mutex_create_func((K), (M), __FILE__, __LINE__, #M)
- # endif/* UNIV_SYNC_DEBUG */
- # else
- # define mutex_create(K, M, level) \
-- pfs_mutex_create_func((K), (M), __FILE__, __LINE__)
-+ pfs_mutex_create_func((K), (M), #M)
- # endif /* UNIV_DEBUG */
-
- # define mutex_enter(M) \
-@@ -185,14 +185,14 @@
- # ifdef UNIV_DEBUG
- # ifdef UNIV_SYNC_DEBUG
- # define mutex_create(K, M, level) \
-- mutex_create_func((M), #M, (level), __FILE__, __LINE__)
-+ mutex_create_func((M), (level), __FILE__, __LINE__, #M)
- # else /* UNIV_SYNC_DEBUG */
- # define mutex_create(K, M, level) \
-- mutex_create_func((M), #M, __FILE__, __LINE__)
-+ mutex_create_func((M), __FILE__, __LINE__, #M)
- # endif /* UNIV_SYNC_DEBUG */
- # else /* UNIV_DEBUG */
- # define mutex_create(K, M, level) \
-- mutex_create_func((M), __FILE__, __LINE__)
-+ mutex_create_func((M), #M)
- # endif /* UNIV_DEBUG */
-
- # define mutex_enter(M) mutex_enter_func((M), __FILE__, __LINE__)
-@@ -217,13 +217,13 @@
- /*==============*/
- mutex_t* mutex, /*!< in: pointer to memory */
- #ifdef UNIV_DEBUG
-- const char* cmutex_name, /*!< in: mutex name */
- # ifdef UNIV_SYNC_DEBUG
- ulint level, /*!< in: level */
- # endif /* UNIV_SYNC_DEBUG */
--#endif /* UNIV_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
-- ulint cline); /*!< in: file line where created */
-+ ulint cline, /*!< in: file line where created */
-+#endif /* UNIV_DEBUG */
-+ const char* cmutex_name); /*!< in: mutex name */
-
- /******************************************************************//**
- NOTE! Use the corresponding macro mutex_free(), not directly this function!
-@@ -291,13 +291,13 @@
- PSI_mutex_key key, /*!< in: Performance Schema key */
- mutex_t* mutex, /*!< in: pointer to memory */
- # ifdef UNIV_DEBUG
-- const char* cmutex_name, /*!< in: mutex name */
- # ifdef UNIV_SYNC_DEBUG
- ulint level, /*!< in: level */
- # endif /* UNIV_SYNC_DEBUG */
--# endif /* UNIV_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
-- ulint cline); /*!< in: file line where created */
-+ ulint cline, /*!< in: file line where created */
-+# endif /* UNIV_DEBUG */
-+ const char* cmutex_name);
- /******************************************************************//**
- NOTE! Please use the corresponding macro mutex_enter(), not directly
- this function!
-@@ -728,9 +728,9 @@
- ulint line; /*!< Line where the mutex was locked */
- ulint level; /*!< Level in the global latching order */
- #endif /* UNIV_SYNC_DEBUG */
-+#ifdef UNIV_DEBUG
- const char* cfile_name;/*!< File name where mutex created */
- ulint cline; /*!< Line where created */
--#ifdef UNIV_DEBUG
- os_thread_id_t thread_id; /*!< The thread id of the thread
- which locked the mutex. */
- ulint magic_n; /*!< MUTEX_MAGIC_N */
-@@ -745,9 +745,9 @@
- ulong count_os_yield; /*!< count of os_wait */
- ulonglong lspent_time; /*!< mutex os_wait timer msec */
- ulonglong lmax_spent_time;/*!< mutex os_wait timer msec */
-- const char* cmutex_name; /*!< mutex name */
- ulint mutex_type; /*!< 0=usual mutex, 1=rw_lock mutex */
- #endif /* UNIV_DEBUG */
-+ const char* cmutex_name; /*!< mutex name */
- #ifdef UNIV_PFS_MUTEX
- struct PSI_mutex* pfs_psi; /*!< The performance schema
- instrumentation hook */
---- a/storage/innobase/include/sync0sync.ic
-+++ b/storage/innobase/include/sync0sync.ic
-@@ -320,13 +320,13 @@
- mysql_pfs_key_t key, /*!< in: Performance Schema key */
- mutex_t* mutex, /*!< in: pointer to memory */
- # ifdef UNIV_DEBUG
-- const char* cmutex_name, /*!< in: mutex name */
- # ifdef UNIV_SYNC_DEBUG
- ulint level, /*!< in: level */
- # endif /* UNIV_SYNC_DEBUG */
--# endif /* UNIV_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
-- ulint cline) /*!< in: file line where created */
-+ ulint cline, /*!< in: file line where created */
-+# endif /* UNIV_DEBUG */
-+ const char* cmutex_name) /*!< in: mutex name */
- {
- mutex->pfs_psi = (PSI_server && PFS_IS_INSTRUMENTED(key))
- ? PSI_server->init_mutex(key, mutex)
-@@ -334,13 +334,13 @@
-
- mutex_create_func(mutex,
- # ifdef UNIV_DEBUG
-- cmutex_name,
- # ifdef UNIV_SYNC_DEBUG
- level,
- # endif /* UNIV_SYNC_DEBUG */
--# endif /* UNIV_DEBUG */
- cfile_name,
-- cline);
-+ cline,
-+# endif /* UNIV_DEBUG */
-+ cmutex_name);
- }
- /******************************************************************//**
- NOTE! Please use the corresponding macro mutex_free(), not directly
---- a/storage/innobase/sync/sync0arr.c
-+++ b/storage/innobase/sync/sync0arr.c
-@@ -489,13 +489,12 @@
- mutex = cell->old_wait_mutex;
-
- fprintf(file,
-- "Mutex at %p created file %s line %lu, lock var %lu\n"
-+ "Mutex at %p '%s', lock var %lu\n"
- #ifdef UNIV_SYNC_DEBUG
- "Last time reserved in file %s line %lu, "
- #endif /* UNIV_SYNC_DEBUG */
- "waiters flag %lu\n",
-- (void*) mutex, innobase_basename(mutex->cfile_name),
-- (ulong) mutex->cline,
-+ (void*) mutex, mutex->cmutex_name,
- (ulong) mutex->lock_word,
- #ifdef UNIV_SYNC_DEBUG
- mutex->file_name, (ulong) mutex->line,
-@@ -513,9 +512,8 @@
- rwlock = cell->old_wait_rw_lock;
-
- fprintf(file,
-- " RW-latch at %p created in file %s line %lu\n",
-- (void*) rwlock, innobase_basename(rwlock->cfile_name),
-- (ulong) rwlock->cline);
-+ " RW-latch at %p '%s'\n",
-+ (void*) rwlock, rwlock->lock_name);
- writer = rw_lock_get_writer(rwlock);
- if (writer != RW_LOCK_NOT_LOCKED) {
- fprintf(file,
---- a/storage/innobase/sync/sync0rw.c
-+++ b/storage/innobase/sync/sync0rw.c
-@@ -242,10 +242,10 @@
- # ifdef UNIV_SYNC_DEBUG
- ulint level, /*!< in: level */
- # endif /* UNIV_SYNC_DEBUG */
-- const char* cmutex_name, /*!< in: mutex name */
--#endif /* UNIV_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
-- ulint cline) /*!< in: file line where created */
-+ ulint cline, /*!< in: file line where created */
-+#endif /* UNIV_DEBUG */
-+ const char* cmutex_name) /*!< in: mutex name */
- {
- /* If this is the very first time a synchronization object is
- created, then the following call initializes the sync system. */
-@@ -254,14 +254,15 @@
- mutex_create(rw_lock_mutex_key, rw_lock_get_mutex(lock),
- SYNC_NO_ORDER_CHECK);
-
-- lock->mutex.cfile_name = cfile_name;
-- lock->mutex.cline = cline;
-+ ut_d(lock->mutex.cfile_name = cfile_name);
-+ ut_d(lock->mutex.cline = cline);
-
-- ut_d(lock->mutex.cmutex_name = cmutex_name);
-+ lock->mutex.cmutex_name = cmutex_name;
- ut_d(lock->mutex.mutex_type = 1);
- #else /* INNODB_RW_LOCKS_USE_ATOMICS */
- # ifdef UNIV_DEBUG
-- UT_NOT_USED(cmutex_name);
-+ UT_NOT_USED(cfile_name);
-+ UT_NOT_USED(cline);
- # endif
- #endif /* INNODB_RW_LOCKS_USE_ATOMICS */
-
-@@ -284,8 +285,7 @@
-
- ut_d(lock->magic_n = RW_LOCK_MAGIC_N);
-
-- lock->cfile_name = cfile_name;
-- lock->cline = (unsigned int) cline;
-+ lock->lock_name = cmutex_name;
-
- lock->count_os_wait = 0;
- lock->last_s_file_name = "not yet reserved";
-@@ -405,11 +405,10 @@
- if (srv_print_latch_waits) {
- fprintf(stderr,
- "Thread %lu spin wait rw-s-lock at %p"
-- " cfile %s cline %lu rnds %lu\n",
-+ " '%s' rnds %lu\n",
- (ulong) os_thread_pf(os_thread_get_curr_id()),
- (void*) lock,
-- innobase_basename(lock->cfile_name),
-- (ulong) lock->cline, (ulong) i);
-+ lock->lock_name, (ulong) i);
- }
-
- /* We try once again to obtain the lock */
-@@ -442,11 +441,9 @@
- if (srv_print_latch_waits) {
- fprintf(stderr,
- "Thread %lu OS wait rw-s-lock at %p"
-- " cfile %s cline %lu\n",
-+ " '%s'\n",
- os_thread_pf(os_thread_get_curr_id()),
-- (void*) lock,
-- innobase_basename(lock->cfile_name),
-- (ulong) lock->cline);
-+ (void*) lock, lock->lock_name);
- }
-
- /* these stats may not be accurate */
-@@ -668,10 +665,9 @@
- if (srv_print_latch_waits) {
- fprintf(stderr,
- "Thread %lu spin wait rw-x-lock at %p"
-- " cfile %s cline %lu rnds %lu\n",
-+ " '%s' rnds %lu\n",
- os_thread_pf(os_thread_get_curr_id()), (void*) lock,
-- innobase_basename(lock->cfile_name),
-- (ulong) lock->cline, (ulong) i);
-+ lock->lock_name, (ulong) i);
- }
-
- sync_array_reserve_cell(sync_primary_wait_array,
-@@ -692,10 +688,9 @@
- if (srv_print_latch_waits) {
- fprintf(stderr,
- "Thread %lu OS wait for rw-x-lock at %p"
-- " cfile %s cline %lu\n",
-+ " '%s'\n",
- os_thread_pf(os_thread_get_curr_id()), (void*) lock,
-- innobase_basename(lock->cfile_name),
-- (ulong) lock->cline);
-+ lock->lock_name);
- }
-
- /* these stats may not be accurate */
---- a/storage/innobase/sync/sync0sync.c
-+++ b/storage/innobase/sync/sync0sync.c
-@@ -270,13 +270,13 @@
- /*==============*/
- mutex_t* mutex, /*!< in: pointer to memory */
- #ifdef UNIV_DEBUG
-- const char* cmutex_name, /*!< in: mutex name */
- # ifdef UNIV_SYNC_DEBUG
- ulint level, /*!< in: level */
- # endif /* UNIV_SYNC_DEBUG */
--#endif /* UNIV_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
-- ulint cline) /*!< in: file line where created */
-+ ulint cline, /*!< in: file line where created */
-+#endif /* UNIV_DEBUG */
-+ const char* cmutex_name) /*!< in: mutex name */
- {
- #if defined(HAVE_ATOMIC_BUILTINS)
- mutex_reset_lock_word(mutex);
-@@ -294,11 +294,13 @@
- mutex->file_name = "not yet reserved";
- mutex->level = level;
- #endif /* UNIV_SYNC_DEBUG */
-+#ifdef UNIV_DEBUG
- mutex->cfile_name = cfile_name;
- mutex->cline = cline;
-+#endif /* UNIV_DEBUG */
- mutex->count_os_wait = 0;
--#ifdef UNIV_DEBUG
- mutex->cmutex_name= cmutex_name;
-+#ifdef UNIV_DEBUG
- mutex->count_using= 0;
- mutex->mutex_type= 0;
- mutex->lspent_time= 0;
-@@ -552,10 +554,9 @@
- #ifdef UNIV_SRV_PRINT_LATCH_WAITS
- fprintf(stderr,
- "Thread %lu spin wait mutex at %p"
-- " cfile %s cline %lu rnds %lu\n",
-+ " '%s' rnds %lu\n",
- (ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex,
-- innobase_basename(mutex->cfile_name),
-- (ulong) mutex->cline, (ulong) i);
-+ mutex->cmutex_name, (ulong) i);
- #endif
-
- mutex_spin_round_count += i;
-@@ -630,10 +631,9 @@
-
- #ifdef UNIV_SRV_PRINT_LATCH_WAITS
- fprintf(stderr,
-- "Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n",
-+ "Thread %lu OS wait mutex at %p '%s' rnds %lu\n",
- (ulong) os_thread_pf(os_thread_get_curr_id()), (void*) mutex,
-- innobase_basename(mutex->cfile_name),
-- (ulong) mutex->cline, (ulong) i);
-+ mutex->cmutex_name, (ulong) i);
- #endif
-
- mutex_os_wait_count++;
-@@ -881,9 +881,8 @@
-
- if (mutex->magic_n == MUTEX_MAGIC_N) {
- fprintf(stderr,
-- "Mutex created at %s %lu\n",
-- innobase_basename(mutex->cfile_name),
-- (ulong) mutex->cline);
-+ "Mutex '%s'\n",
-+ mutex->cmutex_name);
-
- if (mutex_get_lock_word(mutex) != 0) {
- ulint line;
+++ /dev/null
-# name : innodb_show_status.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/buf/buf0buf.c
-+++ b/storage/innobase/buf/buf0buf.c
-@@ -4372,6 +4372,7 @@
- }
-
- total_info->pool_size += pool_info->pool_size;
-+ total_info->pool_size_bytes += pool_info->pool_size_bytes;
- total_info->lru_len += pool_info->lru_len;
- total_info->old_lru_len += pool_info->old_lru_len;
- total_info->free_list_len += pool_info->free_list_len;
-@@ -4437,6 +4438,8 @@
-
- pool_info->pool_size = buf_pool->curr_size;
-
-+ pool_info->pool_size_bytes = buf_pool->curr_pool_size;
-+
- pool_info->lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
-
- pool_info->old_lru_len = buf_pool->LRU_old_len;
-@@ -4558,14 +4561,16 @@
- ut_ad(pool_info);
-
- fprintf(file,
-- "Buffer pool size %lu\n"
-- "Free buffers %lu\n"
-- "Database pages %lu\n"
-- "Old database pages %lu\n"
-- "Modified db pages %lu\n"
-+ "Buffer pool size %lu\n"
-+ "Buffer pool size, bytes %lu\n"
-+ "Free buffers %lu\n"
-+ "Database pages %lu\n"
-+ "Old database pages %lu\n"
-+ "Modified db pages %lu\n"
- "Pending reads %lu\n"
- "Pending writes: LRU %lu, flush list %lu, single page %lu\n",
- pool_info->pool_size,
-+ pool_info->pool_size_bytes,
- pool_info->free_list_len,
- pool_info->lru_len,
- pool_info->old_lru_len,
---- a/storage/innobase/buf/buf0flu.c
-+++ b/storage/innobase/buf/buf0flu.c
-@@ -75,7 +75,7 @@
- static buf_flush_stat_t buf_flush_stat_sum;
-
- /** Number of pages flushed through non flush_list flushes. */
--static ulint buf_lru_flush_page_count = 0;
-+// static ulint buf_lru_flush_page_count = 0;
-
- /* @} */
-
---- a/storage/innobase/fil/fil0fil.c
-+++ b/storage/innobase/fil/fil0fil.c
-@@ -4897,3 +4897,30 @@
-
- fil_system = NULL;
- }
-+
-+/*************************************************************************
-+Return local hash table informations. */
-+
-+ulint
-+fil_system_hash_cells(void)
-+/*=======================*/
-+{
-+ if (fil_system) {
-+ return (fil_system->spaces->n_cells
-+ + fil_system->name_hash->n_cells);
-+ } else {
-+ return 0;
-+ }
-+}
-+
-+ulint
-+fil_system_hash_nodes(void)
-+/*=======================*/
-+{
-+ if (fil_system) {
-+ return (UT_LIST_GET_LEN(fil_system->space_list)
-+ * (sizeof(fil_space_t) + MEM_BLOCK_HEADER_SIZE));
-+ } else {
-+ return 0;
-+ }
-+}
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -604,6 +604,8 @@
- (char*) &export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG},
- {"buffer_pool_pages_flushed",
- (char*) &export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG},
-+ {"buffer_pool_pages_LRU_flushed",
-+ (char*) &export_vars.innodb_buffer_pool_pages_LRU_flushed, SHOW_LONG},
- {"buffer_pool_pages_free",
- (char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG},
- #ifdef UNIV_DEBUG
-@@ -11207,6 +11209,16 @@
- "Force InnoDB to not use next-key locking, to use only row-level locking.",
- NULL, NULL, FALSE);
-
-+static MYSQL_SYSVAR_ULONG(show_verbose_locks, srv_show_verbose_locks,
-+ PLUGIN_VAR_OPCMDARG,
-+ "Whether to show records locked in SHOW INNODB STATUS.",
-+ NULL, NULL, 0, 0, 1, 0);
-+
-+static MYSQL_SYSVAR_ULONG(show_locks_held, srv_show_locks_held,
-+ PLUGIN_VAR_RQCMDARG,
-+ "Number of locks held to print for each InnoDB transaction in SHOW INNODB STATUS.",
-+ NULL, NULL, 10, 0, 1000, 0);
-+
- #ifdef UNIV_LOG_ARCHIVE
- static MYSQL_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
-@@ -11394,7 +11406,7 @@
-
- static MYSQL_SYSVAR_STR(version, innodb_version_str,
- PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
-- "InnoDB version", NULL, NULL, INNODB_VERSION_STR);
-+ "Percona-InnoDB-plugin version", NULL, NULL, INNODB_VERSION_STR);
-
- static MYSQL_SYSVAR_BOOL(use_sys_malloc, srv_use_sys_malloc,
- PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
-@@ -11494,6 +11506,8 @@
- MYSQL_SYSVAR(thread_concurrency),
- MYSQL_SYSVAR(thread_sleep_delay),
- MYSQL_SYSVAR(autoinc_lock_mode),
-+ MYSQL_SYSVAR(show_verbose_locks),
-+ MYSQL_SYSVAR(show_locks_held),
- MYSQL_SYSVAR(version),
- MYSQL_SYSVAR(use_sys_malloc),
- MYSQL_SYSVAR(use_native_aio),
---- a/storage/innobase/include/buf0buf.h
-+++ b/storage/innobase/include/buf0buf.h
-@@ -128,6 +128,7 @@
- /* General buffer pool info */
- ulint pool_unique_id; /*!< Buffer Pool ID */
- ulint pool_size; /*!< Buffer Pool size in pages */
-+ ulint pool_size_bytes;
- ulint lru_len; /*!< Length of buf_pool->LRU */
- ulint old_lru_len; /*!< buf_pool->LRU_old_len */
- ulint free_list_len; /*!< Length of buf_pool->free list */
---- a/storage/innobase/include/fil0fil.h
-+++ b/storage/innobase/include/fil0fil.h
-@@ -731,6 +731,17 @@
- /*============================*/
- ulint id); /*!< in: space id */
-
-+/*************************************************************************
-+Return local hash table informations. */
-+
-+ulint
-+fil_system_hash_cells(void);
-+/*========================*/
-+
-+ulint
-+fil_system_hash_nodes(void);
-+/*========================*/
-+
- typedef struct fil_space_struct fil_space_t;
-
- #endif
---- a/storage/innobase/include/read0read.h
-+++ b/storage/innobase/include/read0read.h
-@@ -88,6 +88,7 @@
- void
- read_view_print(
- /*============*/
-+ FILE* file,
- const read_view_t* view); /*!< in: read view */
- /*********************************************************************//**
- Create a consistent cursor view for mysql to be used in cursors. In this
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -146,6 +146,9 @@
- corrupted index and table */
- extern my_bool srv_load_corrupted;
-
-+extern ulint srv_show_locks_held;
-+extern ulint srv_show_verbose_locks;
-+
- /* The sort order table of the MySQL latin1_swedish_ci character set
- collation */
- extern const byte* srv_latin1_ordering;
-@@ -328,6 +331,8 @@
- buffer pool to disk */
- extern ulint srv_buf_pool_flushed;
-
-+extern ulint buf_lru_flush_page_count;
-+
- /** Number of buffer pool reads that led to the
- reading of a disk page */
- extern ulint srv_buf_pool_reads;
-@@ -707,6 +712,7 @@
- ulint innodb_buffer_pool_reads; /*!< srv_buf_pool_reads */
- ulint innodb_buffer_pool_wait_free; /*!< srv_buf_pool_wait_free */
- ulint innodb_buffer_pool_pages_flushed; /*!< srv_buf_pool_flushed */
-+ ulint innodb_buffer_pool_pages_LRU_flushed; /*!< buf_lru_flush_page_count */
- ulint innodb_buffer_pool_write_requests;/*!< srv_buf_pool_write_requests */
- ulint innodb_buffer_pool_read_ahead_rnd;/*!< srv_read_ahead_rnd */
- ulint innodb_buffer_pool_read_ahead; /*!< srv_read_ahead */
---- a/storage/innobase/lock/lock0lock.c
-+++ b/storage/innobase/lock/lock0lock.c
-@@ -4377,6 +4377,7 @@
-
- putc('\n', file);
-
-+ if ( srv_show_verbose_locks ) {
- block = buf_page_try_get(space, page_no, &mtr);
-
- for (i = 0; i < lock_rec_get_n_bits(lock); ++i) {
-@@ -4403,6 +4404,7 @@
-
- putc('\n', file);
- }
-+ }
-
- mtr_commit(&mtr);
- if (UNIV_LIKELY_NULL(heap)) {
-@@ -4586,7 +4588,7 @@
- }
- }
-
-- if (!srv_print_innodb_lock_monitor) {
-+ if (!srv_print_innodb_lock_monitor && !srv_show_locks_held) {
- nth_trx++;
- goto loop;
- }
-@@ -4658,8 +4660,8 @@
-
- nth_lock++;
-
-- if (nth_lock >= 10) {
-- fputs("10 LOCKS PRINTED FOR THIS TRX:"
-+ if (nth_lock >= srv_show_locks_held) {
-+ fputs("TOO MANY LOCKS PRINTED FOR THIS TRX:"
- " SUPPRESSING FURTHER PRINTS\n",
- file);
-
---- a/storage/innobase/read/read0read.c
-+++ b/storage/innobase/read/read0read.c
-@@ -357,34 +357,35 @@
- void
- read_view_print(
- /*============*/
-+ FILE* file,
- const read_view_t* view) /*!< in: read view */
- {
- ulint n_ids;
- ulint i;
-
- if (view->type == VIEW_HIGH_GRANULARITY) {
-- fprintf(stderr,
-+ fprintf(file,
- "High-granularity read view undo_n:o %llu\n",
- (ullint) view->undo_no);
- } else {
-- fprintf(stderr, "Normal read view\n");
-+ fprintf(file, "Normal read view\n");
- }
-
-- fprintf(stderr, "Read view low limit trx n:o " TRX_ID_FMT "\n",
-+ fprintf(file, "Read view low limit trx n:o " TRX_ID_FMT "\n",
- (ullint) view->low_limit_no);
-
-- fprintf(stderr, "Read view up limit trx id " TRX_ID_FMT "\n",
-+ fprintf(file, "Read view up limit trx id " TRX_ID_FMT "\n",
- (ullint) view->up_limit_id);
-
-- fprintf(stderr, "Read view low limit trx id " TRX_ID_FMT "\n",
-+ fprintf(file, "Read view low limit trx id " TRX_ID_FMT "\n",
- (ullint) view->low_limit_id);
-
-- fprintf(stderr, "Read view individually stored trx ids:\n");
-+ fprintf(file, "Read view individually stored trx ids:\n");
-
- n_ids = view->n_trx_ids;
-
- for (i = 0; i < n_ids; i++) {
-- fprintf(stderr, "Read view trx id " TRX_ID_FMT "\n",
-+ fprintf(file, "Read view trx id " TRX_ID_FMT "\n",
- (ullint) read_view_get_nth_trx_id(view, i));
- }
- }
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -83,6 +83,7 @@
- #include "ha_prototypes.h"
- #include "trx0i_s.h"
- #include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */
-+#include "read0read.h"
- #include "mysql/plugin.h"
- #include "mysql/service_thd_wait.h"
-
-@@ -188,6 +189,9 @@
- the checkpoints. */
- UNIV_INTERN char srv_adaptive_flushing = TRUE;
-
-+UNIV_INTERN ulint srv_show_locks_held = 10;
-+UNIV_INTERN ulint srv_show_verbose_locks = 0;
-+
- /** Maximum number of times allowed to conditionally acquire
- mutex before switching to blocking wait on the mutex */
- #define MAX_MUTEX_NOWAIT 20
-@@ -316,6 +320,7 @@
- /* variable to count the number of pages that were written from buffer
- pool to the disk */
- UNIV_INTERN ulint srv_buf_pool_flushed = 0;
-+UNIV_INTERN ulint buf_lru_flush_page_count = 0;
-
- /** Number of buffer pool reads that led to the
- reading of a disk page */
-@@ -1825,6 +1830,13 @@
- ulint n_reserved;
- ibool ret;
-
-+ ulint btr_search_sys_subtotal;
-+ ulint lock_sys_subtotal;
-+ ulint recv_sys_subtotal;
-+
-+ ulint i;
-+ trx_t* trx;
-+
- mutex_enter(&srv_innodb_monitor_mutex);
-
- current_time = time(NULL);
-@@ -1873,31 +1885,6 @@
-
- mutex_exit(&dict_foreign_err_mutex);
-
-- /* Only if lock_print_info_summary proceeds correctly,
-- before we call the lock_print_info_all_transactions
-- to print all the lock information. */
-- ret = lock_print_info_summary(file, nowait);
--
-- if (ret) {
-- if (trx_start) {
-- long t = ftell(file);
-- if (t < 0) {
-- *trx_start = ULINT_UNDEFINED;
-- } else {
-- *trx_start = (ulint) t;
-- }
-- }
-- lock_print_info_all_transactions(file);
-- if (trx_end) {
-- long t = ftell(file);
-- if (t < 0) {
-- *trx_end = ULINT_UNDEFINED;
-- } else {
-- *trx_end = (ulint) t;
-- }
-- }
-- }
--
- fputs("--------\n"
- "FILE I/O\n"
- "--------\n", file);
-@@ -1928,10 +1915,78 @@
- "BUFFER POOL AND MEMORY\n"
- "----------------------\n", file);
- fprintf(file,
-- "Total memory allocated " ULINTPF
-- "; in additional pool allocated " ULINTPF "\n",
-- ut_total_allocated_memory,
-- mem_pool_get_reserved(mem_comm_pool));
-+ "Total memory allocated " ULINTPF
-+ "; in additional pool allocated " ULINTPF "\n",
-+ ut_total_allocated_memory,
-+ mem_pool_get_reserved(mem_comm_pool));
-+ /* Calcurate reserved memories */
-+ if (btr_search_sys && btr_search_sys->hash_index->heap) {
-+ btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index->heap);
-+ } else {
-+ btr_search_sys_subtotal = 0;
-+ for (i=0; i < btr_search_sys->hash_index->n_mutexes; i++) {
-+ btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index->heaps[i]);
-+ }
-+ }
-+
-+ lock_sys_subtotal = 0;
-+ if (trx_sys) {
-+ mutex_enter(&kernel_mutex);
-+ trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
-+ while (trx) {
-+ lock_sys_subtotal += ((trx->lock_heap) ? mem_heap_get_size(trx->lock_heap) : 0);
-+ trx = UT_LIST_GET_NEXT(mysql_trx_list, trx);
-+ }
-+ mutex_exit(&kernel_mutex);
-+ }
-+
-+ recv_sys_subtotal = ((recv_sys && recv_sys->addr_hash)
-+ ? mem_heap_get_size(recv_sys->heap) : 0);
-+
-+ fprintf(file,
-+ "Internal hash tables (constant factor + variable factor)\n"
-+ " Adaptive hash index %lu \t(%lu + %lu)\n"
-+ " Page hash %lu (buffer pool 0 only)\n"
-+ " Dictionary cache %lu \t(%lu + %lu)\n"
-+ " File system %lu \t(%lu + %lu)\n"
-+ " Lock system %lu \t(%lu + %lu)\n"
-+ " Recovery system %lu \t(%lu + %lu)\n",
-+
-+ (ulong) (btr_search_sys
-+ ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0)
-+ + btr_search_sys_subtotal,
-+ (ulong) (btr_search_sys
-+ ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0),
-+ (ulong) btr_search_sys_subtotal,
-+
-+ (ulong) (buf_pool_from_array(0)->page_hash->n_cells * sizeof(hash_cell_t)),
-+
-+ (ulong) (dict_sys ? ((dict_sys->table_hash->n_cells
-+ + dict_sys->table_id_hash->n_cells
-+ ) * sizeof(hash_cell_t)
-+ + dict_sys->size) : 0),
-+ (ulong) (dict_sys ? ((dict_sys->table_hash->n_cells
-+ + dict_sys->table_id_hash->n_cells
-+ ) * sizeof(hash_cell_t)) : 0),
-+ (ulong) (dict_sys ? (dict_sys->size) : 0),
-+
-+ (ulong) (fil_system_hash_cells() * sizeof(hash_cell_t)
-+ + fil_system_hash_nodes()),
-+ (ulong) (fil_system_hash_cells() * sizeof(hash_cell_t)),
-+ (ulong) fil_system_hash_nodes(),
-+
-+ (ulong) ((lock_sys ? (lock_sys->rec_hash->n_cells * sizeof(hash_cell_t)) : 0)
-+ + lock_sys_subtotal),
-+ (ulong) (lock_sys ? (lock_sys->rec_hash->n_cells * sizeof(hash_cell_t)) : 0),
-+ (ulong) lock_sys_subtotal,
-+
-+ (ulong) (((recv_sys && recv_sys->addr_hash)
-+ ? (recv_sys->addr_hash->n_cells * sizeof(hash_cell_t)) : 0)
-+ + recv_sys_subtotal),
-+ (ulong) ((recv_sys && recv_sys->addr_hash)
-+ ? (recv_sys->addr_hash->n_cells * sizeof(hash_cell_t)) : 0),
-+ (ulong) recv_sys_subtotal);
-+
- fprintf(file, "Dictionary memory allocated " ULINTPF "\n",
- dict_sys->size);
-
-@@ -1947,6 +2002,16 @@
- fprintf(file, "%lu read views open inside InnoDB\n",
- UT_LIST_GET_LEN(trx_sys->view_list));
-
-+ if (UT_LIST_GET_LEN(trx_sys->view_list)) {
-+ read_view_t* view = UT_LIST_GET_LAST(trx_sys->view_list);
-+
-+ if (view) {
-+ fprintf(file, "---OLDEST VIEW---\n");
-+ read_view_print(file, view);
-+ fprintf(file, "-----------------\n");
-+ }
-+ }
-+
- n_reserved = fil_space_get_n_reserved_extents(0);
- if (n_reserved > 0) {
- fprintf(file,
-@@ -1990,6 +2055,31 @@
- srv_n_rows_deleted_old = srv_n_rows_deleted;
- srv_n_rows_read_old = srv_n_rows_read;
-
-+ /* Only if lock_print_info_summary proceeds correctly,
-+ before we call the lock_print_info_all_transactions
-+ to print all the lock information. */
-+ ret = lock_print_info_summary(file, nowait);
-+
-+ if (ret) {
-+ if (trx_start) {
-+ long t = ftell(file);
-+ if (t < 0) {
-+ *trx_start = ULINT_UNDEFINED;
-+ } else {
-+ *trx_start = (ulint) t;
-+ }
-+ }
-+ lock_print_info_all_transactions(file);
-+ if (trx_end) {
-+ long t = ftell(file);
-+ if (t < 0) {
-+ *trx_end = ULINT_UNDEFINED;
-+ } else {
-+ *trx_end = (ulint) t;
-+ }
-+ }
-+ }
-+
- fputs("----------------------------\n"
- "END OF INNODB MONITOR OUTPUT\n"
- "============================\n", file);
-@@ -2033,6 +2123,7 @@
- = srv_buf_pool_write_requests;
- export_vars.innodb_buffer_pool_wait_free = srv_buf_pool_wait_free;
- export_vars.innodb_buffer_pool_pages_flushed = srv_buf_pool_flushed;
-+ export_vars.innodb_buffer_pool_pages_LRU_flushed = buf_lru_flush_page_count;
- export_vars.innodb_buffer_pool_reads = srv_buf_pool_reads;
- export_vars.innodb_buffer_pool_read_ahead_rnd
- = stat.n_ra_pages_read_rnd;
---- a/storage/innobase/sync/sync0arr.c
-+++ b/storage/innobase/sync/sync0arr.c
-@@ -478,7 +478,7 @@
-
- fprintf(file,
- "--Thread %lu has waited at %s line %lu"
-- " for %.2f seconds the semaphore:\n",
-+ " for %#.5g seconds the semaphore:\n",
- (ulong) os_thread_pf(cell->thread),
- innobase_basename(cell->file), (ulong) cell->line,
- difftime(time(NULL), cell->reservation_time));
---- a/storage/innobase/trx/trx0purge.c
-+++ b/storage/innobase/trx/trx0purge.c
-@@ -1212,7 +1212,7 @@
- /*=====================*/
- {
- fprintf(stderr, "InnoDB: Purge system view:\n");
-- read_view_print(purge_sys->view);
-+ read_view_print(stderr, purge_sys->view);
-
- fprintf(stderr, "InnoDB: Purge trx n:o " TRX_ID_FMT
- ", undo n:o " TRX_ID_FMT "\n",
+++ /dev/null
-# name : innodb_show_status_extend.patch
-# introduced : XtraDB based 5.5.8
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -641,6 +641,16 @@
- trx_t* trx); /*!< in: transaction handle */
-
- static SHOW_VAR innodb_status_variables[]= {
-+ {"adaptive_hash_cells",
-+ (char*) &export_vars.innodb_adaptive_hash_cells, SHOW_LONG},
-+ {"adaptive_hash_heap_buffers",
-+ (char*) &export_vars.innodb_adaptive_hash_heap_buffers, SHOW_LONG},
-+ {"adaptive_hash_hash_searches",
-+ (char*) &export_vars.innodb_adaptive_hash_hash_searches, SHOW_LONG},
-+ {"adaptive_hash_non_hash_searches",
-+ (char*) &export_vars.innodb_adaptive_hash_non_hash_searches, SHOW_LONG},
-+ {"background_log_sync",
-+ (char*) &export_vars.innodb_background_log_sync, SHOW_LONG},
- {"buffer_pool_pages_data",
- (char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG},
- {"buffer_pool_pages_dirty",
-@@ -655,8 +665,14 @@
- {"buffer_pool_pages_latched",
- (char*) &export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG},
- #endif /* UNIV_DEBUG */
-+ {"buffer_pool_pages_made_not_young",
-+ (char*) &export_vars.innodb_buffer_pool_pages_made_not_young, SHOW_LONG},
-+ {"buffer_pool_pages_made_young",
-+ (char*) &export_vars.innodb_buffer_pool_pages_made_young, SHOW_LONG},
- {"buffer_pool_pages_misc",
- (char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG},
-+ {"buffer_pool_pages_old",
-+ (char*) &export_vars.innodb_buffer_pool_pages_old, SHOW_LONG},
- {"buffer_pool_pages_total",
- (char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG},
- {"buffer_pool_read_ahead_rnd",
-@@ -673,6 +689,12 @@
- (char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG},
- {"buffer_pool_write_requests",
- (char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG},
-+ {"checkpoint_age",
-+ (char*) &export_vars.innodb_checkpoint_age, SHOW_LONG},
-+ {"checkpoint_max_age",
-+ (char*) &export_vars.innodb_checkpoint_max_age, SHOW_LONG},
-+ {"checkpoint_target_age",
-+ (char*) &export_vars.innodb_checkpoint_target_age, SHOW_LONG},
- {"data_fsyncs",
- (char*) &export_vars.innodb_data_fsyncs, SHOW_LONG},
- {"data_pending_fsyncs",
-@@ -699,12 +721,66 @@
- (char*) &export_vars.innodb_dict_tables, SHOW_LONG},
- {"have_atomic_builtins",
- (char*) &export_vars.innodb_have_atomic_builtins, SHOW_BOOL},
-+ {"history_list_length",
-+ (char*) &export_vars.innodb_history_list_length, SHOW_LONG},
-+ {"ibuf_discarded_delete_marks",
-+ (char*) &export_vars.innodb_ibuf_discarded_delete_marks, SHOW_LONG},
-+ {"ibuf_discarded_deletes",
-+ (char*) &export_vars.innodb_ibuf_discarded_deletes, SHOW_LONG},
-+ {"ibuf_discarded_inserts",
-+ (char*) &export_vars.innodb_ibuf_discarded_inserts, SHOW_LONG},
-+ {"ibuf_free_list",
-+ (char*) &export_vars.innodb_ibuf_free_list, SHOW_LONG},
-+ {"ibuf_merged_delete_marks",
-+ (char*) &export_vars.innodb_ibuf_merged_delete_marks, SHOW_LONG},
-+ {"ibuf_merged_deletes",
-+ (char*) &export_vars.innodb_ibuf_merged_deletes, SHOW_LONG},
-+ {"ibuf_merged_inserts",
-+ (char*) &export_vars.innodb_ibuf_merged_inserts, SHOW_LONG},
-+ {"ibuf_merges",
-+ (char*) &export_vars.innodb_ibuf_merges, SHOW_LONG},
-+ {"ibuf_segment_size",
-+ (char*) &export_vars.innodb_ibuf_segment_size, SHOW_LONG},
-+ {"ibuf_size",
-+ (char*) &export_vars.innodb_ibuf_size, SHOW_LONG},
- {"log_waits",
- (char*) &export_vars.innodb_log_waits, SHOW_LONG},
- {"log_write_requests",
- (char*) &export_vars.innodb_log_write_requests, SHOW_LONG},
- {"log_writes",
- (char*) &export_vars.innodb_log_writes, SHOW_LONG},
-+ {"lsn_current",
-+ (char*) &export_vars.innodb_lsn_current, SHOW_LONGLONG},
-+ {"lsn_flushed",
-+ (char*) &export_vars.innodb_lsn_flushed, SHOW_LONGLONG},
-+ {"lsn_last_checkpoint",
-+ (char*) &export_vars.innodb_lsn_last_checkpoint, SHOW_LONGLONG},
-+ {"master_thread_1_second_loops",
-+ (char*) &export_vars.innodb_master_thread_1_second_loops, SHOW_LONG},
-+ {"master_thread_10_second_loops",
-+ (char*) &export_vars.innodb_master_thread_10_second_loops, SHOW_LONG},
-+ {"master_thread_background_loops",
-+ (char*) &export_vars.innodb_master_thread_background_loops, SHOW_LONG},
-+ {"master_thread_main_flush_loops",
-+ (char*) &export_vars.innodb_master_thread_main_flush_loops, SHOW_LONG},
-+ {"master_thread_sleeps",
-+ (char*) &export_vars.innodb_master_thread_sleeps, SHOW_LONG},
-+ {"max_trx_id",
-+ (char*) &export_vars.innodb_max_trx_id, SHOW_LONGLONG},
-+ {"mem_adaptive_hash",
-+ (char*) &export_vars.innodb_mem_adaptive_hash, SHOW_LONG},
-+ {"mem_dictionary",
-+ (char*) &export_vars.innodb_mem_dictionary, SHOW_LONG},
-+ {"mem_total",
-+ (char*) &export_vars.innodb_mem_total, SHOW_LONG},
-+ {"mutex_os_waits",
-+ (char*) &export_vars.innodb_mutex_os_waits, SHOW_LONGLONG},
-+ {"mutex_spin_rounds",
-+ (char*) &export_vars.innodb_mutex_spin_rounds, SHOW_LONGLONG},
-+ {"mutex_spin_waits",
-+ (char*) &export_vars.innodb_mutex_spin_waits, SHOW_LONGLONG},
-+ {"oldest_view_low_limit_trx_id",
-+ (char*) &export_vars.innodb_oldest_view_low_limit_trx_id, SHOW_LONGLONG},
- {"os_log_fsyncs",
- (char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG},
- {"os_log_pending_fsyncs",
-@@ -721,8 +797,14 @@
- (char*) &export_vars.innodb_pages_read, SHOW_LONG},
- {"pages_written",
- (char*) &export_vars.innodb_pages_written, SHOW_LONG},
-+ {"purge_trx_id",
-+ (char*) &export_vars.innodb_purge_trx_id, SHOW_LONGLONG},
-+ {"purge_undo_no",
-+ (char*) &export_vars.innodb_purge_undo_no, SHOW_LONGLONG},
- {"row_lock_current_waits",
- (char*) &export_vars.innodb_row_lock_current_waits, SHOW_LONG},
-+ {"current_row_locks",
-+ (char*) &export_vars.innodb_current_row_locks, SHOW_LONG},
- {"row_lock_time",
- (char*) &export_vars.innodb_row_lock_time, SHOW_LONGLONG},
- {"row_lock_time_avg",
-@@ -739,8 +821,20 @@
- (char*) &export_vars.innodb_rows_read, SHOW_LONG},
- {"rows_updated",
- (char*) &export_vars.innodb_rows_updated, SHOW_LONG},
-+ {"s_lock_os_waits",
-+ (char*) &export_vars.innodb_s_lock_os_waits, SHOW_LONGLONG},
-+ {"s_lock_spin_rounds",
-+ (char*) &export_vars.innodb_s_lock_spin_rounds, SHOW_LONGLONG},
-+ {"s_lock_spin_waits",
-+ (char*) &export_vars.innodb_s_lock_spin_waits, SHOW_LONGLONG},
- {"truncated_status_writes",
- (char*) &export_vars.innodb_truncated_status_writes, SHOW_LONG},
-+ {"x_lock_os_waits",
-+ (char*) &export_vars.innodb_x_lock_os_waits, SHOW_LONGLONG},
-+ {"x_lock_spin_rounds",
-+ (char*) &export_vars.innodb_x_lock_spin_rounds, SHOW_LONGLONG},
-+ {"x_lock_spin_waits",
-+ (char*) &export_vars.innodb_x_lock_spin_waits, SHOW_LONGLONG},
- {NullS, NullS, SHOW_LONG}
- };
-
---- a/storage/innobase/ibuf/ibuf0ibuf.c
-+++ b/storage/innobase/ibuf/ibuf0ibuf.c
-@@ -478,6 +478,45 @@
- }
-
- /******************************************************************//**
-+Function to pass ibuf status variables */
-+UNIV_INTERN
-+void
-+ibuf_export_ibuf_status(
-+/*====================*/
-+ ulint* size,
-+ ulint* free_list,
-+ ulint* segment_size,
-+ ulint* merges,
-+ ulint* merged_inserts,
-+ ulint* merged_delete_marks,
-+ ulint* merged_deletes,
-+ ulint* discarded_inserts,
-+ ulint* discarded_delete_marks,
-+ ulint* discarded_deletes)
-+{
-+ *size
-+ = ibuf->size;
-+ *free_list
-+ = ibuf->free_list_len;
-+ *segment_size
-+ = ibuf->seg_size;
-+ *merges
-+ = ibuf->n_merges;
-+ *merged_inserts
-+ = ibuf->n_merged_ops[IBUF_OP_INSERT];
-+ *merged_delete_marks
-+ = ibuf->n_merged_ops[IBUF_OP_DELETE_MARK];
-+ *merged_deletes
-+ = ibuf->n_merged_ops[IBUF_OP_DELETE];
-+ *discarded_inserts
-+ = ibuf->n_discarded_ops[IBUF_OP_INSERT];
-+ *discarded_delete_marks
-+ = ibuf->n_discarded_ops[IBUF_OP_DELETE_MARK];
-+ *discarded_deletes
-+ = ibuf->n_discarded_ops[IBUF_OP_DELETE];
-+}
-+
-+/******************************************************************//**
- Updates the size information of the ibuf, assuming the segment size has not
- changed. */
- static
---- a/storage/innobase/include/ibuf0ibuf.h
-+++ b/storage/innobase/include/ibuf0ibuf.h
-@@ -438,6 +438,22 @@
- void
- ibuf_close(void);
- /*============*/
-+/******************************************************************//**
-+Function to pass ibuf status variables */
-+UNIV_INTERN
-+void
-+ibuf_export_ibuf_status(
-+/*====================*/
-+ ulint* size,
-+ ulint* free_list,
-+ ulint* segment_size,
-+ ulint* merges,
-+ ulint* merged_inserts,
-+ ulint* merged_delete_marks,
-+ ulint* merged_deletes,
-+ ulint* discarded_inserts,
-+ ulint* discarded_delete_marks,
-+ ulint* discarded_deletes);
-
- #define IBUF_HEADER_PAGE_NO FSP_IBUF_HEADER_PAGE_NO
- #define IBUF_TREE_ROOT_PAGE_NO FSP_IBUF_TREE_ROOT_PAGE_NO
---- a/storage/innobase/include/lock0lock.h
-+++ b/storage/innobase/include/lock0lock.h
-@@ -817,6 +817,7 @@
- /** The lock system struct */
- struct lock_sys_struct{
- hash_table_t* rec_hash; /*!< hash table of the record locks */
-+ ulint rec_num;
- };
-
- /** The lock system */
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -742,6 +742,11 @@
-
- /** Status variables to be passed to MySQL */
- struct export_var_struct{
-+ ulint innodb_adaptive_hash_cells;
-+ ulint innodb_adaptive_hash_heap_buffers;
-+ ulint innodb_adaptive_hash_hash_searches;
-+ ulint innodb_adaptive_hash_non_hash_searches;
-+ ulint innodb_background_log_sync;
- ulint innodb_data_pending_reads; /*!< Pending reads */
- ulint innodb_data_pending_writes; /*!< Pending writes */
- ulint innodb_data_pending_fsyncs; /*!< Pending fsyncs */
-@@ -759,6 +764,9 @@
- #ifdef UNIV_DEBUG
- ulint innodb_buffer_pool_pages_latched; /*!< Latched pages */
- #endif /* UNIV_DEBUG */
-+ ulint innodb_buffer_pool_pages_made_not_young;
-+ ulint innodb_buffer_pool_pages_made_young;
-+ ulint innodb_buffer_pool_pages_old;
- ulint innodb_buffer_pool_read_requests; /*!< buf_pool->stat.n_page_gets */
- ulint innodb_buffer_pool_reads; /*!< srv_buf_pool_reads */
- ulint innodb_buffer_pool_wait_free; /*!< srv_buf_pool_wait_free */
-@@ -768,13 +776,43 @@
- ulint innodb_buffer_pool_read_ahead_rnd;/*!< srv_read_ahead_rnd */
- ulint innodb_buffer_pool_read_ahead; /*!< srv_read_ahead */
- ulint innodb_buffer_pool_read_ahead_evicted;/*!< srv_read_ahead evicted*/
-+ ulint innodb_checkpoint_age;
-+ ulint innodb_checkpoint_max_age;
-+ ulint innodb_checkpoint_target_age;
- ulint innodb_dblwr_pages_written; /*!< srv_dblwr_pages_written */
- ulint innodb_dblwr_writes; /*!< srv_dblwr_writes */
- ulint innodb_deadlocks;
- ibool innodb_have_atomic_builtins; /*!< HAVE_ATOMIC_BUILTINS */
-+ ulint innodb_history_list_length;
-+ ulint innodb_ibuf_size;
-+ ulint innodb_ibuf_free_list;
-+ ulint innodb_ibuf_segment_size;
-+ ulint innodb_ibuf_merges;
-+ ulint innodb_ibuf_merged_inserts;
-+ ulint innodb_ibuf_merged_delete_marks;
-+ ulint innodb_ibuf_merged_deletes;
-+ ulint innodb_ibuf_discarded_inserts;
-+ ulint innodb_ibuf_discarded_delete_marks;
-+ ulint innodb_ibuf_discarded_deletes;
- ulint innodb_log_waits; /*!< srv_log_waits */
- ulint innodb_log_write_requests; /*!< srv_log_write_requests */
- ulint innodb_log_writes; /*!< srv_log_writes */
-+ ib_int64_t innodb_lsn_current;
-+ ib_int64_t innodb_lsn_flushed;
-+ ib_int64_t innodb_lsn_last_checkpoint;
-+ ulint innodb_master_thread_1_second_loops;
-+ ulint innodb_master_thread_10_second_loops;
-+ ulint innodb_master_thread_background_loops;
-+ ulint innodb_master_thread_main_flush_loops;
-+ ulint innodb_master_thread_sleeps;
-+ ib_int64_t innodb_max_trx_id;
-+ ulint innodb_mem_adaptive_hash;
-+ ulint innodb_mem_dictionary;
-+ ulint innodb_mem_total;
-+ ib_int64_t innodb_mutex_os_waits;
-+ ib_int64_t innodb_mutex_spin_rounds;
-+ ib_int64_t innodb_mutex_spin_waits;
-+ ib_int64_t innodb_oldest_view_low_limit_trx_id;
- ulint innodb_os_log_written; /*!< srv_os_log_written */
- ulint innodb_os_log_fsyncs; /*!< fil_n_log_flushes */
- ulint innodb_os_log_pending_writes; /*!< srv_os_log_pending_writes */
-@@ -783,6 +821,8 @@
- ulint innodb_pages_created; /*!< buf_pool->stat.n_pages_created */
- ulint innodb_pages_read; /*!< buf_pool->stat.n_pages_read */
- ulint innodb_pages_written; /*!< buf_pool->stat.n_pages_written */
-+ ib_int64_t innodb_purge_trx_id;
-+ ib_int64_t innodb_purge_undo_no;
- ulint innodb_row_lock_waits; /*!< srv_n_lock_wait_count */
- ulint innodb_row_lock_current_waits; /*!< srv_n_lock_wait_current_count */
- ib_int64_t innodb_row_lock_time; /*!< srv_n_lock_wait_time
-@@ -792,11 +832,18 @@
- / srv_n_lock_wait_count */
- ulint innodb_row_lock_time_max; /*!< srv_n_lock_max_wait_time
- / 1000 */
-+ ulint innodb_current_row_locks;
- ulint innodb_rows_read; /*!< srv_n_rows_read */
- ulint innodb_rows_inserted; /*!< srv_n_rows_inserted */
- ulint innodb_rows_updated; /*!< srv_n_rows_updated */
- ulint innodb_rows_deleted; /*!< srv_n_rows_deleted */
- ulint innodb_truncated_status_writes; /*!< srv_truncated_status_writes */
-+ ib_int64_t innodb_s_lock_os_waits;
-+ ib_int64_t innodb_s_lock_spin_rounds;
-+ ib_int64_t innodb_s_lock_spin_waits;
-+ ib_int64_t innodb_x_lock_os_waits;
-+ ib_int64_t innodb_x_lock_spin_rounds;
-+ ib_int64_t innodb_x_lock_spin_waits;
- };
-
- /** Thread slot in the thread table */
---- a/storage/innobase/include/sync0sync.h
-+++ b/storage/innobase/include/sync0sync.h
-@@ -766,6 +766,10 @@
-
- #define SYNC_SPIN_ROUNDS srv_n_spin_wait_rounds
-
-+extern ib_int64_t mutex_spin_round_count;
-+extern ib_int64_t mutex_spin_wait_count;
-+extern ib_int64_t mutex_os_wait_count;
-+
- /** The number of mutex_exit calls. Intended for performance monitoring. */
- extern ib_int64_t mutex_exit_count;
-
---- a/storage/innobase/lock/lock0lock.c
-+++ b/storage/innobase/lock/lock0lock.c
-@@ -569,6 +569,7 @@
- lock_sys = mem_alloc(sizeof(lock_sys_t));
-
- lock_sys->rec_hash = hash_create(n_cells);
-+ lock_sys->rec_num = 0;
-
- /* hash_create_mutexes(lock_sys->rec_hash, 2, SYNC_REC_LOCK); */
-
-@@ -1729,6 +1730,7 @@
-
- HASH_INSERT(lock_t, hash, lock_sys->rec_hash,
- lock_rec_fold(space, page_no), lock);
-+ lock_sys->rec_num++;
- if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
-
- lock_set_lock_and_trx_wait(lock, trx);
-@@ -2275,6 +2277,7 @@
-
- HASH_DELETE(lock_t, hash, lock_sys->rec_hash,
- lock_rec_fold(space, page_no), in_lock);
-+ lock_sys->rec_num--;
-
- UT_LIST_REMOVE(trx_locks, trx->trx_locks, in_lock);
-
-@@ -2318,6 +2321,7 @@
-
- HASH_DELETE(lock_t, hash, lock_sys->rec_hash,
- lock_rec_fold(space, page_no), in_lock);
-+ lock_sys->rec_num--;
-
- UT_LIST_REMOVE(trx_locks, trx->trx_locks, in_lock);
- }
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -2262,12 +2262,49 @@
- ulint LRU_len;
- ulint free_len;
- ulint flush_list_len;
-+ ulint mem_adaptive_hash, mem_dictionary;
-+ read_view_t* oldest_view;
-+ ulint i;
-
- buf_get_total_stat(&stat);
- buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len);
-
-+ if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
-+ mem_adaptive_hash = mem_heap_get_size(btr_search_sys->hash_index[0]->heap);
-+ } else {
-+ mem_adaptive_hash = 0;
-+ for (i=0; i < btr_search_sys->hash_index[0]->n_mutexes; i++) {
-+ mem_adaptive_hash += mem_heap_get_size(btr_search_sys->hash_index[0]->heaps[i]);
-+ }
-+ }
-+ mem_adaptive_hash *= btr_search_index_num;
-+ if (btr_search_sys) {
-+ mem_adaptive_hash += (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t));
-+ }
-+
-+ mem_dictionary = (dict_sys ? ((dict_sys->table_hash->n_cells
-+ + dict_sys->table_id_hash->n_cells
-+ ) * sizeof(hash_cell_t)
-+ + dict_sys->size) : 0);
-+
- mutex_enter(&srv_innodb_monitor_mutex);
-
-+ export_vars.innodb_adaptive_hash_cells = 0;
-+ export_vars.innodb_adaptive_hash_heap_buffers = 0;
-+ for (i = 0; i < btr_search_index_num; i++) {
-+ hash_table_t* table = btr_search_get_hash_index((index_id_t)i);
-+
-+ export_vars.innodb_adaptive_hash_cells
-+ += hash_get_n_cells(table);
-+ export_vars.innodb_adaptive_hash_heap_buffers
-+ += (UT_LIST_GET_LEN(table->heap->base) - 1);
-+ }
-+ export_vars.innodb_adaptive_hash_hash_searches
-+ = btr_cur_n_sea;
-+ export_vars.innodb_adaptive_hash_non_hash_searches
-+ = btr_cur_n_non_sea;
-+ export_vars.innodb_background_log_sync
-+ = srv_log_writes_and_flush;
- export_vars.innodb_data_pending_reads
- = os_n_pending_reads;
- export_vars.innodb_data_pending_writes
-@@ -2306,6 +2343,92 @@
-
- export_vars.innodb_buffer_pool_pages_misc
- = buf_pool_get_n_pages() - LRU_len - free_len;
-+
-+ export_vars.innodb_buffer_pool_pages_made_young
-+ = stat.n_pages_made_young;
-+ export_vars.innodb_buffer_pool_pages_made_not_young
-+ = stat.n_pages_not_made_young;
-+ export_vars.innodb_buffer_pool_pages_old = 0;
-+ for (i = 0; i < srv_buf_pool_instances; i++) {
-+ buf_pool_t* buf_pool = buf_pool_from_array(i);
-+ export_vars.innodb_buffer_pool_pages_old
-+ += buf_pool->LRU_old_len;
-+ }
-+ export_vars.innodb_checkpoint_age
-+ = (log_sys->lsn - log_sys->last_checkpoint_lsn);
-+ export_vars.innodb_checkpoint_max_age
-+ = log_sys->max_checkpoint_age;
-+ export_vars.innodb_checkpoint_target_age
-+ = srv_checkpoint_age_target
-+ ? ut_min(log_sys->max_checkpoint_age_async, srv_checkpoint_age_target)
-+ : log_sys->max_checkpoint_age_async;
-+ export_vars.innodb_history_list_length
-+ = trx_sys->rseg_history_len;
-+ ibuf_export_ibuf_status(
-+ &export_vars.innodb_ibuf_size,
-+ &export_vars.innodb_ibuf_free_list,
-+ &export_vars.innodb_ibuf_segment_size,
-+ &export_vars.innodb_ibuf_merges,
-+ &export_vars.innodb_ibuf_merged_inserts,
-+ &export_vars.innodb_ibuf_merged_delete_marks,
-+ &export_vars.innodb_ibuf_merged_deletes,
-+ &export_vars.innodb_ibuf_discarded_inserts,
-+ &export_vars.innodb_ibuf_discarded_delete_marks,
-+ &export_vars.innodb_ibuf_discarded_deletes);
-+ export_vars.innodb_lsn_current
-+ = log_sys->lsn;
-+ export_vars.innodb_lsn_flushed
-+ = log_sys->flushed_to_disk_lsn;
-+ export_vars.innodb_lsn_last_checkpoint
-+ = log_sys->last_checkpoint_lsn;
-+ export_vars.innodb_master_thread_1_second_loops
-+ = srv_main_1_second_loops;
-+ export_vars.innodb_master_thread_10_second_loops
-+ = srv_main_10_second_loops;
-+ export_vars.innodb_master_thread_background_loops
-+ = srv_main_background_loops;
-+ export_vars.innodb_master_thread_main_flush_loops
-+ = srv_main_flush_loops;
-+ export_vars.innodb_master_thread_sleeps
-+ = srv_main_sleeps;
-+ export_vars.innodb_max_trx_id
-+ = trx_sys->max_trx_id;
-+ export_vars.innodb_mem_adaptive_hash
-+ = mem_adaptive_hash;
-+ export_vars.innodb_mem_dictionary
-+ = mem_dictionary;
-+ export_vars.innodb_mem_total
-+ = ut_total_allocated_memory;
-+ export_vars.innodb_mutex_os_waits
-+ = mutex_os_wait_count;
-+ export_vars.innodb_mutex_spin_rounds
-+ = mutex_spin_round_count;
-+ export_vars.innodb_mutex_spin_waits
-+ = mutex_spin_wait_count;
-+ export_vars.innodb_s_lock_os_waits
-+ = rw_s_os_wait_count;
-+ export_vars.innodb_s_lock_spin_rounds
-+ = rw_s_spin_round_count;
-+ export_vars.innodb_s_lock_spin_waits
-+ = rw_s_spin_wait_count;
-+ export_vars.innodb_x_lock_os_waits
-+ = rw_x_os_wait_count;
-+ export_vars.innodb_x_lock_spin_rounds
-+ = rw_x_spin_round_count;
-+ export_vars.innodb_x_lock_spin_waits
-+ = rw_x_spin_wait_count;
-+
-+ oldest_view = UT_LIST_GET_LAST(trx_sys->view_list);
-+ export_vars.innodb_oldest_view_low_limit_trx_id
-+ = oldest_view ? oldest_view->low_limit_id : 0;
-+
-+ export_vars.innodb_purge_trx_id
-+ = purge_sys->purge_trx_no;
-+ export_vars.innodb_purge_undo_no
-+ = purge_sys->purge_undo_no;
-+ export_vars.innodb_current_row_locks
-+ = lock_sys->rec_num;
-+
- #ifdef HAVE_ATOMIC_BUILTINS
- export_vars.innodb_have_atomic_builtins = 1;
- #else
---- a/storage/innobase/sync/sync0sync.c
-+++ b/storage/innobase/sync/sync0sync.c
-@@ -171,13 +171,13 @@
-
- /** The number of iterations in the mutex_spin_wait() spin loop.
- Intended for performance monitoring. */
--static ib_int64_t mutex_spin_round_count = 0;
-+UNIV_INTERN ib_int64_t mutex_spin_round_count = 0;
- /** The number of mutex_spin_wait() calls. Intended for
- performance monitoring. */
--static ib_int64_t mutex_spin_wait_count = 0;
-+UNIV_INTERN ib_int64_t mutex_spin_wait_count = 0;
- /** The number of OS waits in mutex_spin_wait(). Intended for
- performance monitoring. */
--static ib_int64_t mutex_os_wait_count = 0;
-+UNIV_INTERN ib_int64_t mutex_os_wait_count = 0;
- /** The number of mutex_exit() calls. Intended for performance
- monitoring. */
- UNIV_INTERN ib_int64_t mutex_exit_count = 0;
+++ /dev/null
-# name : innodb_show_sys_tables.patch
-# introduced : 13?
-# maintainer : Yasufumi
-# (It is revived from mysql-5.5.6-rc)
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/dict/dict0load.c
-+++ b/storage/innobase/dict/dict0load.c
-@@ -442,7 +442,7 @@
-
- }
-
--#ifdef FOREIGN_NOT_USED
-+//#ifdef FOREIGN_NOT_USED
- /********************************************************************//**
- This function parses a SYS_FOREIGN record and populate a dict_foreign_t
- structure with the information from the record. For detail information
-@@ -518,9 +518,9 @@
-
- return(NULL);
- }
--#endif /* FOREIGN_NOT_USED */
-+//#endif /* FOREIGN_NOT_USED */
-
--#ifdef FOREIGN_NOT_USED
-+//#ifdef FOREIGN_NOT_USED
- /********************************************************************//**
- This function parses a SYS_FOREIGN_COLS record and extract necessary
- information from the record and return to caller.
-@@ -584,7 +584,7 @@
-
- return(NULL);
- }
--#endif /* FOREIGN_NOT_USED */
-+//#endif /* FOREIGN_NOT_USED */
-
- /********************************************************************//**
- Determine the flags of a table described in SYS_TABLES.
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -11950,7 +11950,14 @@
- i_s_innodb_cmp,
- i_s_innodb_cmp_reset,
- i_s_innodb_cmpmem,
--i_s_innodb_cmpmem_reset
-+i_s_innodb_cmpmem_reset,
-+i_s_innodb_sys_tables,
-+i_s_innodb_sys_tablestats,
-+i_s_innodb_sys_indexes,
-+i_s_innodb_sys_columns,
-+i_s_innodb_sys_fields,
-+i_s_innodb_sys_foreign,
-+i_s_innodb_sys_foreign_cols
- mysql_declare_plugin_end;
-
- /** @brief Initialize the default value of innodb_commit_concurrency.
---- a/storage/innobase/handler/i_s.cc
-+++ b/storage/innobase/handler/i_s.cc
-@@ -36,9 +36,11 @@
- #include <mysql/innodb_priv.h>
-
- extern "C" {
-+#include "btr0pcur.h" /* for file sys_tables related info. */
- #include "btr0types.h"
- #include "buf0buddy.h" /* for i_s_cmpmem */
- #include "buf0buf.h" /* for buf_pool and PAGE_ZIP_MIN_SIZE */
-+#include "dict0load.h" /* for file sys_tables related info. */
- #include "dict0mem.h"
- #include "dict0types.h"
- #include "ha_prototypes.h" /* for innobase_convert_name() */
-@@ -1812,6 +1814,1703 @@
- DBUG_RETURN(0);
- }
-
-+/* Fields of the dynamic table INFORMATION_SCHEMA.SYS_TABLES */
-+static ST_FIELD_INFO innodb_sys_tables_fields_info[] =
-+{
-+#define SYS_TABLE_ID 0
-+ {STRUCT_FLD(field_name, "TABLE_ID"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_TABLE_SCHEMA 1
-+ {STRUCT_FLD(field_name, "SCHEMA"),
-+ STRUCT_FLD(field_length, NAME_LEN + 1),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_TABLE_NAME 2
-+ {STRUCT_FLD(field_name, "NAME"),
-+ STRUCT_FLD(field_length, NAME_LEN + 1),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_TABLE_FLAG 3
-+ {STRUCT_FLD(field_name, "FLAG"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_TABLE_NUM_COLUMN 4
-+ {STRUCT_FLD(field_name, "N_COLS"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_TABLE_SPACE 5
-+ {STRUCT_FLD(field_name, "SPACE"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ END_OF_ST_FIELD_INFO
-+};
-+
-+/**********************************************************************//**
-+Populate information_schema.innodb_sys_tables table with information
-+from SYS_TABLES.
-+@return 0 on success */
-+static
-+int
-+i_s_dict_fill_sys_tables(
-+/*=====================*/
-+ THD* thd, /*!< in: thread */
-+ dict_table_t* table, /*!< in: table */
-+ TABLE* table_to_fill) /*!< in/out: fill this table */
-+{
-+ Field** fields;
-+ char buf[NAME_LEN * 2 + 2];
-+ char* ptr;
-+
-+ DBUG_ENTER("i_s_dict_fill_sys_tables");
-+
-+ fields = table_to_fill->field;
-+
-+ OK(fields[SYS_TABLE_ID]->store(longlong(table->id), TRUE));
-+
-+ strncpy(buf, table->name, NAME_LEN * 2 + 2);
-+ ptr = strchr(buf, '/');
-+ if (ptr) {
-+ *ptr = '\0';
-+ ++ptr;
-+
-+ OK(field_store_string(fields[SYS_TABLE_SCHEMA], buf));
-+ OK(field_store_string(fields[SYS_TABLE_NAME], ptr));
-+ } else {
-+ fields[SYS_TABLE_SCHEMA]->set_null();
-+ OK(field_store_string(fields[SYS_TABLE_NAME], buf));
-+ }
-+
-+ OK(fields[SYS_TABLE_FLAG]->store(table->flags));
-+
-+ OK(fields[SYS_TABLE_NUM_COLUMN]->store(table->n_cols));
-+
-+ OK(fields[SYS_TABLE_SPACE]->store(table->space));
-+
-+ OK(schema_table_store_record(thd, table_to_fill));
-+
-+ DBUG_RETURN(0);
-+}
-+/*******************************************************************//**
-+Function to go through each record in SYS_TABLES table, and fill the
-+information_schema.innodb_sys_tables table with related table information
-+@return 0 on success */
-+static
-+int
-+i_s_sys_tables_fill_table(
-+/*======================*/
-+ THD* thd, /*!< in: thread */
-+ TABLE_LIST* tables, /*!< in/out: tables to fill */
-+ COND* cond) /*!< in: condition (not used) */
-+{
-+ btr_pcur_t pcur;
-+ const rec_t* rec;
-+ mem_heap_t* heap;
-+ mtr_t mtr;
-+
-+ DBUG_ENTER("i_s_sys_tables_fill_table");
-+
-+ /* deny access to non-superusers */
-+ if (check_global_access(thd, PROCESS_ACL)) {
-+
-+ DBUG_RETURN(0);
-+ }
-+
-+ heap = mem_heap_create(1000);
-+ mutex_enter(&(dict_sys->mutex));
-+ mtr_start(&mtr);
-+
-+ rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
-+
-+ while (rec) {
-+ const char* err_msg;
-+ dict_table_t* table_rec;
-+
-+ /* Create and populate a dict_table_t structure with
-+ information from SYS_TABLES row */
-+ err_msg = dict_process_sys_tables_rec(
-+ heap, rec, &table_rec, DICT_TABLE_LOAD_FROM_RECORD);
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+
-+ if (!err_msg) {
-+ i_s_dict_fill_sys_tables(thd, table_rec, tables->table);
-+ } else {
-+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-+ ER_CANT_FIND_SYSTEM_REC,
-+ err_msg);
-+ }
-+
-+ /* Since dict_process_sys_tables_rec() is called with
-+ DICT_TABLE_LOAD_FROM_RECORD, the table_rec is created in
-+ dict_process_sys_tables_rec(), we will need to free it */
-+ if (table_rec) {
-+ dict_mem_table_free(table_rec);
-+ }
-+
-+ mem_heap_empty(heap);
-+
-+ /* Get the next record */
-+ mutex_enter(&dict_sys->mutex);
-+ mtr_start(&mtr);
-+ rec = dict_getnext_system(&pcur, &mtr);
-+ }
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+ mem_heap_free(heap);
-+
-+ DBUG_RETURN(0);
-+}
-+
-+/*******************************************************************//**
-+Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_tables
-+@return 0 on success */
-+static
-+int
-+innodb_sys_tables_init(
-+/*===================*/
-+ void* p) /*!< in/out: table schema object */
-+{
-+ ST_SCHEMA_TABLE* schema;
-+
-+ DBUG_ENTER("innodb_sys_tables_init");
-+
-+ schema = (ST_SCHEMA_TABLE*) p;
-+
-+ schema->fields_info = innodb_sys_tables_fields_info;
-+ schema->fill_table = i_s_sys_tables_fill_table;
-+
-+ DBUG_RETURN(0);
-+}
-+
-+UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tables =
-+{
-+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
-+ /* int */
-+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-+
-+ /* pointer to type-specific plugin descriptor */
-+ /* void* */
-+ STRUCT_FLD(info, &i_s_info),
-+
-+ /* plugin name */
-+ /* const char* */
-+ STRUCT_FLD(name, "INNODB_SYS_TABLES"),
-+
-+ /* plugin author (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(author, "Percona"),
-+
-+ /* general descriptive text (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(descr, "InnoDB SYS_TABLES"),
-+
-+ /* the plugin license (PLUGIN_LICENSE_XXX) */
-+ /* int */
-+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-+
-+ /* the function to invoke when plugin is loaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(init, innodb_sys_tables_init),
-+
-+ /* the function to invoke when plugin is unloaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(deinit, i_s_common_deinit),
-+
-+ /* plugin version (for SHOW PLUGINS) */
-+ /* unsigned int */
-+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
-+
-+ /* struct st_mysql_show_var* */
-+ STRUCT_FLD(status_vars, NULL),
-+
-+ /* struct st_mysql_sys_var** */
-+ STRUCT_FLD(system_vars, NULL),
-+
-+ /* reserved for dependency checking */
-+ /* void* */
-+ STRUCT_FLD(__reserved1, NULL),
-+
-+ /* flags for plugin */
-+ /* unsigned long */
-+ STRUCT_FLD(flags, 0UL)
-+};
-+
-+/* Fields of the dynamic table INFORMATION_SCHEMA.SYS_TABLESTATS */
-+static ST_FIELD_INFO innodb_sys_tablestats_fields_info[] =
-+{
-+#define SYS_TABLESTATS_ID 0
-+ {STRUCT_FLD(field_name, "TABLE_ID"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_TABLESTATS_SCHEMA 1
-+ {STRUCT_FLD(field_name, "SCHEMA"),
-+ STRUCT_FLD(field_length, NAME_LEN + 1),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_TABLESTATS_NAME 2
-+ {STRUCT_FLD(field_name, "NAME"),
-+ STRUCT_FLD(field_length, NAME_LEN + 1),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_TABLESTATS_INIT 3
-+ {STRUCT_FLD(field_name, "STATS_INITIALIZED"),
-+ STRUCT_FLD(field_length, NAME_LEN + 1),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_TABLESTATS_NROW 4
-+ {STRUCT_FLD(field_name, "NUM_ROWS"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_TABLESTATS_CLUST_SIZE 5
-+ {STRUCT_FLD(field_name, "CLUST_INDEX_SIZE"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_TABLESTATS_INDEX_SIZE 6
-+ {STRUCT_FLD(field_name, "OTHER_INDEX_SIZE"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_TABLESTATS_MODIFIED 7
-+ {STRUCT_FLD(field_name, "MODIFIED_COUNTER"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_TABLESTATS_AUTONINC 8
-+ {STRUCT_FLD(field_name, "AUTOINC"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_TABLESTATS_MYSQL_OPEN_HANDLE 9
-+ {STRUCT_FLD(field_name, "MYSQL_HANDLES_OPENED"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ END_OF_ST_FIELD_INFO
-+};
-+
-+/**********************************************************************//**
-+Populate information_schema.innodb_sys_tablestats table with information
-+from SYS_TABLES.
-+@return 0 on success */
-+static
-+int
-+i_s_dict_fill_sys_tablestats(
-+/*=========================*/
-+ THD* thd, /*!< in: thread */
-+ dict_table_t* table, /*!< in: table */
-+ TABLE* table_to_fill) /*!< in/out: fill this table */
-+{
-+ Field** fields;
-+ char buf[NAME_LEN * 2 + 2];
-+ char* ptr;
-+
-+ DBUG_ENTER("i_s_dict_fill_sys_tablestats");
-+
-+ fields = table_to_fill->field;
-+
-+ OK(fields[SYS_TABLESTATS_ID]->store(longlong(table->id), TRUE));
-+
-+ strncpy(buf, table->name, NAME_LEN * 2 + 2);
-+ ptr = strchr(buf, '/');
-+ if (ptr) {
-+ *ptr = '\0';
-+ ++ptr;
-+
-+ OK(field_store_string(fields[SYS_TABLESTATS_SCHEMA], buf));
-+ OK(field_store_string(fields[SYS_TABLESTATS_NAME], ptr));
-+ } else {
-+ fields[SYS_TABLESTATS_SCHEMA]->set_null();
-+ OK(field_store_string(fields[SYS_TABLESTATS_NAME], buf));
-+ }
-+
-+ if (table->stat_initialized) {
-+ OK(field_store_string(fields[SYS_TABLESTATS_INIT],
-+ "Initialized"));
-+ } else {
-+ OK(field_store_string(fields[SYS_TABLESTATS_INIT],
-+ "Uninitialized"));
-+ }
-+
-+ OK(fields[SYS_TABLESTATS_NROW]->store(table->stat_n_rows, TRUE));
-+
-+ OK(fields[SYS_TABLESTATS_CLUST_SIZE]->store(
-+ table->stat_clustered_index_size));
-+
-+ OK(fields[SYS_TABLESTATS_INDEX_SIZE]->store(
-+ table->stat_sum_of_other_index_sizes));
-+
-+ OK(fields[SYS_TABLESTATS_MODIFIED]->store(
-+ table->stat_modified_counter));
-+
-+ OK(fields[SYS_TABLESTATS_AUTONINC]->store(table->autoinc, TRUE));
-+
-+ OK(fields[SYS_TABLESTATS_MYSQL_OPEN_HANDLE]->store(
-+ table->n_mysql_handles_opened));
-+
-+ OK(schema_table_store_record(thd, table_to_fill));
-+
-+ DBUG_RETURN(0);
-+}
-+/*******************************************************************//**
-+Function to go through each record in SYS_TABLES table, and fill the
-+information_schema.innodb_sys_tablestats table with table statistics
-+related information
-+@return 0 on success */
-+static
-+int
-+i_s_sys_tables_fill_table_stats(
-+/*============================*/
-+ THD* thd, /*!< in: thread */
-+ TABLE_LIST* tables, /*!< in/out: tables to fill */
-+ COND* cond) /*!< in: condition (not used) */
-+{
-+ btr_pcur_t pcur;
-+ const rec_t* rec;
-+ mem_heap_t* heap;
-+ mtr_t mtr;
-+
-+ DBUG_ENTER("i_s_sys_tables_fill_table_stats");
-+
-+ /* deny access to non-superusers */
-+ if (check_global_access(thd, PROCESS_ACL)) {
-+
-+ DBUG_RETURN(0);
-+ }
-+
-+ heap = mem_heap_create(1000);
-+ mutex_enter(&dict_sys->mutex);
-+ mtr_start(&mtr);
-+
-+ rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
-+
-+ while (rec) {
-+ const char* err_msg;
-+ dict_table_t* table_rec;
-+
-+ /* Fetch the dict_table_t structure corresponding to
-+ this SYS_TABLES record */
-+ err_msg = dict_process_sys_tables_rec(
-+ heap, rec, &table_rec, DICT_TABLE_LOAD_FROM_CACHE);
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+
-+ if (!err_msg) {
-+ i_s_dict_fill_sys_tablestats(thd, table_rec,
-+ tables->table);
-+ } else {
-+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-+ ER_CANT_FIND_SYSTEM_REC,
-+ err_msg);
-+ }
-+
-+ mem_heap_empty(heap);
-+
-+ /* Get the next record */
-+ mutex_enter(&dict_sys->mutex);
-+ mtr_start(&mtr);
-+ rec = dict_getnext_system(&pcur, &mtr);
-+ }
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+ mem_heap_free(heap);
-+
-+ DBUG_RETURN(0);
-+}
-+
-+/*******************************************************************//**
-+Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_tablestats
-+@return 0 on success */
-+static
-+int
-+innodb_sys_tablestats_init(
-+/*=======================*/
-+ void* p) /*!< in/out: table schema object */
-+{
-+ ST_SCHEMA_TABLE* schema;
-+
-+ DBUG_ENTER("innodb_sys_tablestats_init");
-+
-+ schema = (ST_SCHEMA_TABLE*) p;
-+
-+ schema->fields_info = innodb_sys_tablestats_fields_info;
-+ schema->fill_table = i_s_sys_tables_fill_table_stats;
-+
-+ DBUG_RETURN(0);
-+}
-+
-+UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tablestats =
-+{
-+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
-+ /* int */
-+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-+
-+ /* pointer to type-specific plugin descriptor */
-+ /* void* */
-+ STRUCT_FLD(info, &i_s_info),
-+
-+ /* plugin name */
-+ /* const char* */
-+ STRUCT_FLD(name, "INNODB_SYS_TABLESTATS"),
-+
-+ /* plugin author (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(author, "Percona"),
-+
-+ /* general descriptive text (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(descr, "InnoDB SYS_TABLESTATS"),
-+
-+ /* the plugin license (PLUGIN_LICENSE_XXX) */
-+ /* int */
-+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-+
-+ /* the function to invoke when plugin is loaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(init, innodb_sys_tablestats_init),
-+
-+ /* the function to invoke when plugin is unloaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(deinit, i_s_common_deinit),
-+
-+ /* plugin version (for SHOW PLUGINS) */
-+ /* unsigned int */
-+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
-+
-+ /* struct st_mysql_show_var* */
-+ STRUCT_FLD(status_vars, NULL),
-+
-+ /* struct st_mysql_sys_var** */
-+ STRUCT_FLD(system_vars, NULL),
-+
-+ /* reserved for dependency checking */
-+ /* void* */
-+ STRUCT_FLD(__reserved1, NULL),
-+
-+ /* flags for plugin */
-+ /* unsigned long */
-+ STRUCT_FLD(flags, 0UL)
-+};
-+
-+/* Fields of the dynamic table INFORMATION_SCHEMA.SYS_INDEXES */
-+static ST_FIELD_INFO innodb_sysindex_fields_info[] =
-+{
-+#define SYS_INDEX_ID 0
-+ {STRUCT_FLD(field_name, "INDEX_ID"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_INDEX_NAME 1
-+ {STRUCT_FLD(field_name, "NAME"),
-+ STRUCT_FLD(field_length, NAME_LEN + 1),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_INDEX_TABLE_ID 2
-+ {STRUCT_FLD(field_name, "TABLE_ID"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_INDEX_TYPE 3
-+ {STRUCT_FLD(field_name, "TYPE"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_INDEX_NUM_FIELDS 4
-+ {STRUCT_FLD(field_name, "N_FIELDS"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_INDEX_PAGE_NO 5
-+ {STRUCT_FLD(field_name, "PAGE_NO"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_INDEX_SPACE 6
-+ {STRUCT_FLD(field_name, "SPACE"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ END_OF_ST_FIELD_INFO
-+};
-+
-+/**********************************************************************//**
-+Function to populate the information_schema.innodb_sys_indexes table with
-+collected index information
-+@return 0 on success */
-+static
-+int
-+i_s_dict_fill_sys_indexes(
-+/*======================*/
-+ THD* thd, /*!< in: thread */
-+ table_id_t table_id, /*!< in: table id */
-+ dict_index_t* index, /*!< in: populated dict_index_t
-+ struct with index info */
-+ TABLE* table_to_fill) /*!< in/out: fill this table */
-+{
-+ Field** fields;
-+
-+ DBUG_ENTER("i_s_dict_fill_sys_indexes");
-+
-+ fields = table_to_fill->field;
-+
-+ OK(fields[SYS_INDEX_ID]->store(longlong(index->id), TRUE));
-+
-+ OK(field_store_string(fields[SYS_INDEX_NAME], index->name));
-+
-+ OK(fields[SYS_INDEX_TABLE_ID]->store(longlong(table_id), TRUE));
-+
-+ OK(fields[SYS_INDEX_TYPE]->store(index->type));
-+
-+ OK(fields[SYS_INDEX_NUM_FIELDS]->store(index->n_fields));
-+
-+ OK(fields[SYS_INDEX_PAGE_NO]->store(index->page));
-+
-+ OK(fields[SYS_INDEX_SPACE]->store(index->space));
-+
-+ OK(schema_table_store_record(thd, table_to_fill));
-+
-+ DBUG_RETURN(0);
-+}
-+/*******************************************************************//**
-+Function to go through each record in SYS_INDEXES table, and fill the
-+information_schema.innodb_sys_indexes table with related index information
-+@return 0 on success */
-+static
-+int
-+i_s_sys_indexes_fill_table(
-+/*=======================*/
-+ THD* thd, /*!< in: thread */
-+ TABLE_LIST* tables, /*!< in/out: tables to fill */
-+ COND* cond) /*!< in: condition (not used) */
-+{
-+ btr_pcur_t pcur;
-+ const rec_t* rec;
-+ mem_heap_t* heap;
-+ mtr_t mtr;
-+
-+ DBUG_ENTER("i_s_sys_indexes_fill_table");
-+
-+ /* deny access to non-superusers */
-+ if (check_global_access(thd, PROCESS_ACL)) {
-+
-+ DBUG_RETURN(0);
-+ }
-+
-+ heap = mem_heap_create(1000);
-+ mutex_enter(&dict_sys->mutex);
-+ mtr_start(&mtr);
-+
-+ /* Start scan the SYS_INDEXES table */
-+ rec = dict_startscan_system(&pcur, &mtr, SYS_INDEXES);
-+
-+ /* Process each record in the table */
-+ while (rec) {
-+ const char* err_msg;;
-+ table_id_t table_id;
-+ dict_index_t index_rec;
-+
-+ /* Populate a dict_index_t structure with information from
-+ a SYS_INDEXES row */
-+ err_msg = dict_process_sys_indexes_rec(heap, rec, &index_rec,
-+ &table_id);
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+
-+ if (!err_msg) {
-+ i_s_dict_fill_sys_indexes(thd, table_id, &index_rec,
-+ tables->table);
-+ } else {
-+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-+ ER_CANT_FIND_SYSTEM_REC,
-+ err_msg);
-+ }
-+
-+ mem_heap_empty(heap);
-+
-+ /* Get the next record */
-+ mutex_enter(&dict_sys->mutex);
-+ mtr_start(&mtr);
-+ rec = dict_getnext_system(&pcur, &mtr);
-+ }
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+ mem_heap_free(heap);
-+
-+ DBUG_RETURN(0);
-+}
-+/*******************************************************************//**
-+Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_indexes
-+@return 0 on success */
-+static
-+int
-+innodb_sys_indexes_init(
-+/*====================*/
-+ void* p) /*!< in/out: table schema object */
-+{
-+ ST_SCHEMA_TABLE* schema;
-+
-+ DBUG_ENTER("innodb_sys_index_init");
-+
-+ schema = (ST_SCHEMA_TABLE*) p;
-+
-+ schema->fields_info = innodb_sysindex_fields_info;
-+ schema->fill_table = i_s_sys_indexes_fill_table;
-+
-+ DBUG_RETURN(0);
-+}
-+
-+UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_indexes =
-+{
-+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
-+ /* int */
-+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-+
-+ /* pointer to type-specific plugin descriptor */
-+ /* void* */
-+ STRUCT_FLD(info, &i_s_info),
-+
-+ /* plugin name */
-+ /* const char* */
-+ STRUCT_FLD(name, "INNODB_SYS_INDEXES"),
-+
-+ /* plugin author (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(author, "Percona"),
-+
-+ /* general descriptive text (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(descr, "InnoDB SYS_INDEXES"),
-+
-+ /* the plugin license (PLUGIN_LICENSE_XXX) */
-+ /* int */
-+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-+
-+ /* the function to invoke when plugin is loaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(init, innodb_sys_indexes_init),
-+
-+ /* the function to invoke when plugin is unloaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(deinit, i_s_common_deinit),
-+
-+ /* plugin version (for SHOW PLUGINS) */
-+ /* unsigned int */
-+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
-+
-+ /* struct st_mysql_show_var* */
-+ STRUCT_FLD(status_vars, NULL),
-+
-+ /* struct st_mysql_sys_var** */
-+ STRUCT_FLD(system_vars, NULL),
-+
-+ /* reserved for dependency checking */
-+ /* void* */
-+ STRUCT_FLD(__reserved1, NULL),
-+
-+ /* flags for plugin */
-+ /* unsigned long */
-+ STRUCT_FLD(flags, 0UL)
-+};
-+
-+/* Fields of the dynamic table INFORMATION_SCHEMA.SYS_COLUMNS */
-+static ST_FIELD_INFO innodb_sys_columns_fields_info[] =
-+{
-+#define SYS_COLUMN_TABLE_ID 0
-+ {STRUCT_FLD(field_name, "TABLE_ID"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_COLUMN_NAME 1
-+ {STRUCT_FLD(field_name, "NAME"),
-+ STRUCT_FLD(field_length, NAME_LEN + 1),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_COLUMN_POSITION 2
-+ {STRUCT_FLD(field_name, "POS"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_COLUMN_MTYPE 3
-+ {STRUCT_FLD(field_name, "MTYPE"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_COLUMN__PRTYPE 4
-+ {STRUCT_FLD(field_name, "PRTYPE"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_COLUMN_COLUMN_LEN 5
-+ {STRUCT_FLD(field_name, "LEN"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ END_OF_ST_FIELD_INFO
-+};
-+
-+/**********************************************************************//**
-+Function to populate the information_schema.innodb_sys_columns with
-+related column information
-+@return 0 on success */
-+static
-+int
-+i_s_dict_fill_sys_columns(
-+/*======================*/
-+ THD* thd, /*!< in: thread */
-+ table_id_t table_id, /*!< in: table ID */
-+ const char* col_name, /*!< in: column name */
-+ dict_col_t* column, /*!< in: dict_col_t struct holding
-+ more column information */
-+ TABLE* table_to_fill) /*!< in/out: fill this table */
-+{
-+ Field** fields;
-+
-+ DBUG_ENTER("i_s_dict_fill_sys_columns");
-+
-+ fields = table_to_fill->field;
-+
-+ OK(fields[SYS_COLUMN_TABLE_ID]->store(longlong(table_id), TRUE));
-+
-+ OK(field_store_string(fields[SYS_COLUMN_NAME], col_name));
-+
-+ OK(fields[SYS_COLUMN_POSITION]->store(column->ind));
-+
-+ OK(fields[SYS_COLUMN_MTYPE]->store(column->mtype));
-+
-+ OK(fields[SYS_COLUMN__PRTYPE]->store(column->prtype));
-+
-+ OK(fields[SYS_COLUMN_COLUMN_LEN]->store(column->len));
-+
-+ OK(schema_table_store_record(thd, table_to_fill));
-+
-+ DBUG_RETURN(0);
-+}
-+/*******************************************************************//**
-+Function to fill information_schema.innodb_sys_columns with information
-+collected by scanning SYS_COLUMNS table.
-+@return 0 on success */
-+static
-+int
-+i_s_sys_columns_fill_table(
-+/*=======================*/
-+ THD* thd, /*!< in: thread */
-+ TABLE_LIST* tables, /*!< in/out: tables to fill */
-+ COND* cond) /*!< in: condition (not used) */
-+{
-+ btr_pcur_t pcur;
-+ const rec_t* rec;
-+ const char* col_name;
-+ mem_heap_t* heap;
-+ mtr_t mtr;
-+
-+ DBUG_ENTER("i_s_sys_columns_fill_table");
-+
-+ /* deny access to non-superusers */
-+ if (check_global_access(thd, PROCESS_ACL)) {
-+
-+ DBUG_RETURN(0);
-+ }
-+
-+ heap = mem_heap_create(1000);
-+ mutex_enter(&dict_sys->mutex);
-+ mtr_start(&mtr);
-+
-+ rec = dict_startscan_system(&pcur, &mtr, SYS_COLUMNS);
-+
-+ while (rec) {
-+ const char* err_msg;
-+ dict_col_t column_rec;
-+ table_id_t table_id;
-+
-+ /* populate a dict_col_t structure with information from
-+ a SYS_COLUMNS row */
-+ err_msg = dict_process_sys_columns_rec(heap, rec, &column_rec,
-+ &table_id, &col_name);
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+
-+ if (!err_msg) {
-+ i_s_dict_fill_sys_columns(thd, table_id, col_name,
-+ &column_rec,
-+ tables->table);
-+ } else {
-+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-+ ER_CANT_FIND_SYSTEM_REC,
-+ err_msg);
-+ }
-+
-+ mem_heap_empty(heap);
-+
-+ /* Get the next record */
-+ mutex_enter(&dict_sys->mutex);
-+ mtr_start(&mtr);
-+ rec = dict_getnext_system(&pcur, &mtr);
-+ }
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+ mem_heap_free(heap);
-+
-+ DBUG_RETURN(0);
-+}
-+/*******************************************************************//**
-+Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_columns
-+@return 0 on success */
-+static
-+int
-+innodb_sys_columns_init(
-+/*====================*/
-+ void* p) /*!< in/out: table schema object */
-+{
-+ ST_SCHEMA_TABLE* schema;
-+
-+ DBUG_ENTER("innodb_sys_columns_init");
-+
-+ schema = (ST_SCHEMA_TABLE*) p;
-+
-+ schema->fields_info = innodb_sys_columns_fields_info;
-+ schema->fill_table = i_s_sys_columns_fill_table;
-+
-+ DBUG_RETURN(0);
-+}
-+
-+UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_columns =
-+{
-+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
-+ /* int */
-+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-+
-+ /* pointer to type-specific plugin descriptor */
-+ /* void* */
-+ STRUCT_FLD(info, &i_s_info),
-+
-+ /* plugin name */
-+ /* const char* */
-+ STRUCT_FLD(name, "INNODB_SYS_COLUMNS"),
-+
-+ /* plugin author (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(author, "Percona"),
-+
-+ /* general descriptive text (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(descr, "InnoDB SYS_COLUMNS"),
-+
-+ /* the plugin license (PLUGIN_LICENSE_XXX) */
-+ /* int */
-+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-+
-+ /* the function to invoke when plugin is loaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(init, innodb_sys_columns_init),
-+
-+ /* the function to invoke when plugin is unloaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(deinit, i_s_common_deinit),
-+
-+ /* plugin version (for SHOW PLUGINS) */
-+ /* unsigned int */
-+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
-+
-+ /* struct st_mysql_show_var* */
-+ STRUCT_FLD(status_vars, NULL),
-+
-+ /* struct st_mysql_sys_var** */
-+ STRUCT_FLD(system_vars, NULL),
-+
-+ /* reserved for dependency checking */
-+ /* void* */
-+ STRUCT_FLD(__reserved1, NULL),
-+
-+ /* flags for plugin */
-+ /* unsigned long */
-+ STRUCT_FLD(flags, 0UL)
-+};
-+/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_sys_fields */
-+static ST_FIELD_INFO innodb_sys_fields_fields_info[] =
-+{
-+#define SYS_FIELD_INDEX_ID 0
-+ {STRUCT_FLD(field_name, "INDEX_ID"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_FIELD_NAME 1
-+ {STRUCT_FLD(field_name, "NAME"),
-+ STRUCT_FLD(field_length, NAME_LEN + 1),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_FIELD_POS 2
-+ {STRUCT_FLD(field_name, "POS"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ END_OF_ST_FIELD_INFO
-+};
-+
-+/**********************************************************************//**
-+Function to fill information_schema.innodb_sys_fields with information
-+collected by scanning SYS_FIELDS table.
-+@return 0 on success */
-+static
-+int
-+i_s_dict_fill_sys_fields(
-+/*=====================*/
-+ THD* thd, /*!< in: thread */
-+ index_id_t index_id, /*!< in: index id for the field */
-+ dict_field_t* field, /*!< in: table */
-+ ulint pos, /*!< in: Field position */
-+ TABLE* table_to_fill) /*!< in/out: fill this table */
-+{
-+ Field** fields;
-+
-+ DBUG_ENTER("i_s_dict_fill_sys_fields");
-+
-+ fields = table_to_fill->field;
-+
-+ OK(fields[SYS_FIELD_INDEX_ID]->store(longlong(index_id), TRUE));
-+
-+ OK(field_store_string(fields[SYS_FIELD_NAME], field->name));
-+
-+ OK(fields[SYS_FIELD_POS]->store(pos));
-+
-+ OK(schema_table_store_record(thd, table_to_fill));
-+
-+ DBUG_RETURN(0);
-+}
-+/*******************************************************************//**
-+Function to go through each record in SYS_FIELDS table, and fill the
-+information_schema.innodb_sys_fields table with related index field
-+information
-+@return 0 on success */
-+static
-+int
-+i_s_sys_fields_fill_table(
-+/*======================*/
-+ THD* thd, /*!< in: thread */
-+ TABLE_LIST* tables, /*!< in/out: tables to fill */
-+ COND* cond) /*!< in: condition (not used) */
-+{
-+ btr_pcur_t pcur;
-+ const rec_t* rec;
-+ mem_heap_t* heap;
-+ index_id_t last_id;
-+ mtr_t mtr;
-+
-+ DBUG_ENTER("i_s_sys_fields_fill_table");
-+
-+ /* deny access to non-superusers */
-+ if (check_global_access(thd, PROCESS_ACL)) {
-+
-+ DBUG_RETURN(0);
-+ }
-+
-+ heap = mem_heap_create(1000);
-+ mutex_enter(&dict_sys->mutex);
-+ mtr_start(&mtr);
-+
-+ /* will save last index id so that we know whether we move to
-+ the next index. This is used to calculate prefix length */
-+ last_id = 0;
-+
-+ rec = dict_startscan_system(&pcur, &mtr, SYS_FIELDS);
-+
-+ while (rec) {
-+ ulint pos;
-+ const char* err_msg;
-+ index_id_t index_id;
-+ dict_field_t field_rec;
-+
-+ /* Populate a dict_field_t structure with information from
-+ a SYS_FIELDS row */
-+ err_msg = dict_process_sys_fields_rec(heap, rec, &field_rec,
-+ &pos, &index_id, last_id);
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+
-+ if (!err_msg) {
-+ i_s_dict_fill_sys_fields(thd, index_id, &field_rec,
-+ pos, tables->table);
-+ last_id = index_id;
-+ } else {
-+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-+ ER_CANT_FIND_SYSTEM_REC,
-+ err_msg);
-+ }
-+
-+ mem_heap_empty(heap);
-+
-+ /* Get the next record */
-+ mutex_enter(&dict_sys->mutex);
-+ mtr_start(&mtr);
-+ rec = dict_getnext_system(&pcur, &mtr);
-+ }
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+ mem_heap_free(heap);
-+
-+ DBUG_RETURN(0);
-+}
-+/*******************************************************************//**
-+Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_fields
-+@return 0 on success */
-+static
-+int
-+innodb_sys_fields_init(
-+/*===================*/
-+ void* p) /*!< in/out: table schema object */
-+{
-+ ST_SCHEMA_TABLE* schema;
-+
-+ DBUG_ENTER("innodb_sys_field_init");
-+
-+ schema = (ST_SCHEMA_TABLE*) p;
-+
-+ schema->fields_info = innodb_sys_fields_fields_info;
-+ schema->fill_table = i_s_sys_fields_fill_table;
-+
-+ DBUG_RETURN(0);
-+}
-+
-+UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_fields =
-+{
-+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
-+ /* int */
-+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-+
-+ /* pointer to type-specific plugin descriptor */
-+ /* void* */
-+ STRUCT_FLD(info, &i_s_info),
-+
-+ /* plugin name */
-+ /* const char* */
-+ STRUCT_FLD(name, "INNODB_SYS_FIELDS"),
-+
-+ /* plugin author (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(author, "Percona"),
-+
-+ /* general descriptive text (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(descr, "InnoDB SYS_FIELDS"),
-+
-+ /* the plugin license (PLUGIN_LICENSE_XXX) */
-+ /* int */
-+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-+
-+ /* the function to invoke when plugin is loaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(init, innodb_sys_fields_init),
-+
-+ /* the function to invoke when plugin is unloaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(deinit, i_s_common_deinit),
-+
-+ /* plugin version (for SHOW PLUGINS) */
-+ /* unsigned int */
-+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
-+
-+ /* struct st_mysql_show_var* */
-+ STRUCT_FLD(status_vars, NULL),
-+
-+ /* struct st_mysql_sys_var** */
-+ STRUCT_FLD(system_vars, NULL),
-+
-+ /* reserved for dependency checking */
-+ /* void* */
-+ STRUCT_FLD(__reserved1, NULL),
-+
-+ /* flags for plugin */
-+ /* unsigned long */
-+ STRUCT_FLD(flags, 0UL)
-+};
-+
-+/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign */
-+static ST_FIELD_INFO innodb_sys_foreign_fields_info[] =
-+{
-+#define SYS_FOREIGN_ID 0
-+ {STRUCT_FLD(field_name, "ID"),
-+ STRUCT_FLD(field_length, NAME_LEN + 1),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_FOREIGN_FOR_NAME 1
-+ {STRUCT_FLD(field_name, "FOR_NAME"),
-+ STRUCT_FLD(field_length, NAME_LEN + 1),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_FOREIGN_REF_NAME 2
-+ {STRUCT_FLD(field_name, "REF_NAME"),
-+ STRUCT_FLD(field_length, NAME_LEN + 1),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_FOREIGN_NUM_COL 3
-+ {STRUCT_FLD(field_name, "N_COLS"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_FOREIGN_TYPE 4
-+ {STRUCT_FLD(field_name, "TYPE"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ END_OF_ST_FIELD_INFO
-+};
-+
-+/**********************************************************************//**
-+Function to fill information_schema.innodb_sys_foreign with information
-+collected by scanning SYS_FOREIGN table.
-+@return 0 on success */
-+static
-+int
-+i_s_dict_fill_sys_foreign(
-+/*======================*/
-+ THD* thd, /*!< in: thread */
-+ dict_foreign_t* foreign, /*!< in: table */
-+ TABLE* table_to_fill) /*!< in/out: fill this table */
-+{
-+ Field** fields;
-+
-+ DBUG_ENTER("i_s_dict_fill_sys_foreign");
-+
-+ fields = table_to_fill->field;
-+
-+ OK(field_store_string(fields[SYS_FOREIGN_ID], foreign->id));
-+
-+ OK(field_store_string(fields[SYS_FOREIGN_FOR_NAME],
-+ foreign->foreign_table_name));
-+
-+ OK(field_store_string(fields[SYS_FOREIGN_REF_NAME],
-+ foreign->referenced_table_name));
-+
-+ OK(fields[SYS_FOREIGN_NUM_COL]->store(foreign->n_fields));
-+
-+ OK(fields[SYS_FOREIGN_TYPE]->store(foreign->type));
-+
-+ OK(schema_table_store_record(thd, table_to_fill));
-+
-+ DBUG_RETURN(0);
-+}
-+/*******************************************************************//**
-+Function to populate INFORMATION_SCHEMA.innodb_sys_foreign table. Loop
-+through each record in SYS_FOREIGN, and extract the foreign key
-+information.
-+@return 0 on success */
-+static
-+int
-+i_s_sys_foreign_fill_table(
-+/*=======================*/
-+ THD* thd, /*!< in: thread */
-+ TABLE_LIST* tables, /*!< in/out: tables to fill */
-+ COND* cond) /*!< in: condition (not used) */
-+{
-+ btr_pcur_t pcur;
-+ const rec_t* rec;
-+ mem_heap_t* heap;
-+ mtr_t mtr;
-+
-+ DBUG_ENTER("i_s_sys_foreign_fill_table");
-+
-+ /* deny access to non-superusers */
-+ if (check_global_access(thd, PROCESS_ACL)) {
-+
-+ DBUG_RETURN(0);
-+ }
-+
-+ heap = mem_heap_create(1000);
-+ mutex_enter(&dict_sys->mutex);
-+ mtr_start(&mtr);
-+
-+ rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN);
-+
-+ while (rec) {
-+ const char* err_msg;
-+ dict_foreign_t foreign_rec;
-+
-+ /* Populate a dict_foreign_t structure with information from
-+ a SYS_FOREIGN row */
-+ err_msg = dict_process_sys_foreign_rec(heap, rec, &foreign_rec);
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+
-+ if (!err_msg) {
-+ i_s_dict_fill_sys_foreign(thd, &foreign_rec,
-+ tables->table);
-+ } else {
-+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-+ ER_CANT_FIND_SYSTEM_REC,
-+ err_msg);
-+ }
-+
-+ mem_heap_empty(heap);
-+
-+ /* Get the next record */
-+ mtr_start(&mtr);
-+ mutex_enter(&dict_sys->mutex);
-+ rec = dict_getnext_system(&pcur, &mtr);
-+ }
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+ mem_heap_free(heap);
-+
-+ DBUG_RETURN(0);
-+}
-+/*******************************************************************//**
-+Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign
-+@return 0 on success */
-+static
-+int
-+innodb_sys_foreign_init(
-+/*====================*/
-+ void* p) /*!< in/out: table schema object */
-+{
-+ ST_SCHEMA_TABLE* schema;
-+
-+ DBUG_ENTER("innodb_sys_foreign_init");
-+
-+ schema = (ST_SCHEMA_TABLE*) p;
-+
-+ schema->fields_info = innodb_sys_foreign_fields_info;
-+ schema->fill_table = i_s_sys_foreign_fill_table;
-+
-+ DBUG_RETURN(0);
-+}
-+
-+UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_foreign =
-+{
-+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
-+ /* int */
-+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-+
-+ /* pointer to type-specific plugin descriptor */
-+ /* void* */
-+ STRUCT_FLD(info, &i_s_info),
-+
-+ /* plugin name */
-+ /* const char* */
-+ STRUCT_FLD(name, "INNODB_SYS_FOREIGN"),
-+
-+ /* plugin author (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(author, "Percona"),
-+
-+ /* general descriptive text (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(descr, "InnoDB SYS_FOREIGN"),
-+
-+ /* the plugin license (PLUGIN_LICENSE_XXX) */
-+ /* int */
-+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-+
-+ /* the function to invoke when plugin is loaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(init, innodb_sys_foreign_init),
-+
-+ /* the function to invoke when plugin is unloaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(deinit, i_s_common_deinit),
-+
-+ /* plugin version (for SHOW PLUGINS) */
-+ /* unsigned int */
-+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
-+
-+ /* struct st_mysql_show_var* */
-+ STRUCT_FLD(status_vars, NULL),
-+
-+ /* struct st_mysql_sys_var** */
-+ STRUCT_FLD(system_vars, NULL),
-+
-+ /* reserved for dependency checking */
-+ /* void* */
-+ STRUCT_FLD(__reserved1, NULL),
-+
-+ /* flags for plugin */
-+ /* unsigned long */
-+ STRUCT_FLD(flags, 0UL)
-+};
-+/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign_cols */
-+static ST_FIELD_INFO innodb_sys_foreign_cols_fields_info[] =
-+{
-+#define SYS_FOREIGN_COL_ID 0
-+ {STRUCT_FLD(field_name, "ID"),
-+ STRUCT_FLD(field_length, NAME_LEN + 1),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_FOREIGN_COL_FOR_NAME 1
-+ {STRUCT_FLD(field_name, "FOR_COL_NAME"),
-+ STRUCT_FLD(field_length, NAME_LEN + 1),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_FOREIGN_COL_REF_NAME 2
-+ {STRUCT_FLD(field_name, "REF_COL_NAME"),
-+ STRUCT_FLD(field_length, NAME_LEN + 1),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_FOREIGN_COL_POS 3
-+ {STRUCT_FLD(field_name, "POS"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ END_OF_ST_FIELD_INFO
-+};
-+
-+/**********************************************************************//**
-+Function to fill information_schema.innodb_sys_foreign_cols with information
-+collected by scanning SYS_FOREIGN_COLS table.
-+@return 0 on success */
-+static
-+int
-+i_s_dict_fill_sys_foreign_cols(
-+/*==========================*/
-+ THD* thd, /*!< in: thread */
-+ const char* name, /*!< in: foreign key constraint name */
-+ const char* for_col_name, /*!< in: referencing column name*/
-+ const char* ref_col_name, /*!< in: referenced column
-+ name */
-+ ulint pos, /*!< in: column position */
-+ TABLE* table_to_fill) /*!< in/out: fill this table */
-+{
-+ Field** fields;
-+
-+ DBUG_ENTER("i_s_dict_fill_sys_foreign_cols");
-+
-+ fields = table_to_fill->field;
-+
-+ OK(field_store_string(fields[SYS_FOREIGN_COL_ID], name));
-+
-+ OK(field_store_string(fields[SYS_FOREIGN_COL_FOR_NAME], for_col_name));
-+
-+ OK(field_store_string(fields[SYS_FOREIGN_COL_REF_NAME], ref_col_name));
-+
-+ OK(fields[SYS_FOREIGN_COL_POS]->store(pos));
-+
-+ OK(schema_table_store_record(thd, table_to_fill));
-+
-+ DBUG_RETURN(0);
-+}
-+/*******************************************************************//**
-+Function to populate INFORMATION_SCHEMA.innodb_sys_foreign_cols table. Loop
-+through each record in SYS_FOREIGN_COLS, and extract the foreign key column
-+information and fill the INFORMATION_SCHEMA.innodb_sys_foreign_cols table.
-+@return 0 on success */
-+static
-+int
-+i_s_sys_foreign_cols_fill_table(
-+/*============================*/
-+ THD* thd, /*!< in: thread */
-+ TABLE_LIST* tables, /*!< in/out: tables to fill */
-+ COND* cond) /*!< in: condition (not used) */
-+{
-+ btr_pcur_t pcur;
-+ const rec_t* rec;
-+ mem_heap_t* heap;
-+ mtr_t mtr;
-+
-+ DBUG_ENTER("i_s_sys_foreign_cols_fill_table");
-+
-+ /* deny access to non-superusers */
-+ if (check_global_access(thd, PROCESS_ACL)) {
-+ DBUG_RETURN(0);
-+ }
-+
-+ heap = mem_heap_create(1000);
-+ mutex_enter(&dict_sys->mutex);
-+ mtr_start(&mtr);
-+
-+ rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN_COLS);
-+
-+ while (rec) {
-+ const char* err_msg;
-+ const char* name;
-+ const char* for_col_name;
-+ const char* ref_col_name;
-+ ulint pos;
-+
-+ /* Extract necessary information from a SYS_FOREIGN_COLS row */
-+ err_msg = dict_process_sys_foreign_col_rec(
-+ heap, rec, &name, &for_col_name, &ref_col_name, &pos);
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+
-+ if (!err_msg) {
-+ i_s_dict_fill_sys_foreign_cols(
-+ thd, name, for_col_name, ref_col_name, pos,
-+ tables->table);
-+ } else {
-+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-+ ER_CANT_FIND_SYSTEM_REC,
-+ err_msg);
-+ }
-+
-+ mem_heap_empty(heap);
-+
-+ /* Get the next record */
-+ mutex_enter(&dict_sys->mutex);
-+ mtr_start(&mtr);
-+ rec = dict_getnext_system(&pcur, &mtr);
-+ }
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+ mem_heap_free(heap);
-+
-+ DBUG_RETURN(0);
-+}
-+/*******************************************************************//**
-+Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign_cols
-+@return 0 on success */
-+static
-+int
-+innodb_sys_foreign_cols_init(
-+/*========================*/
-+ void* p) /*!< in/out: table schema object */
-+{
-+ ST_SCHEMA_TABLE* schema;
-+
-+ DBUG_ENTER("innodb_sys_foreign_cols_init");
-+
-+ schema = (ST_SCHEMA_TABLE*) p;
-+
-+ schema->fields_info = innodb_sys_foreign_cols_fields_info;
-+ schema->fill_table = i_s_sys_foreign_cols_fill_table;
-+
-+ DBUG_RETURN(0);
-+}
-+
-+UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_foreign_cols =
-+{
-+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
-+ /* int */
-+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-+
-+ /* pointer to type-specific plugin descriptor */
-+ /* void* */
-+ STRUCT_FLD(info, &i_s_info),
-+
-+ /* plugin name */
-+ /* const char* */
-+ STRUCT_FLD(name, "INNODB_SYS_FOREIGN_COLS"),
-+
-+ /* plugin author (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(author, "Percona"),
-+
-+ /* general descriptive text (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(descr, "InnoDB SYS_FOREIGN_COLS"),
-+
-+ /* the plugin license (PLUGIN_LICENSE_XXX) */
-+ /* int */
-+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-+
-+ /* the function to invoke when plugin is loaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(init, innodb_sys_foreign_cols_init),
-+
-+ /* the function to invoke when plugin is unloaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(deinit, i_s_common_deinit),
-+
-+ /* plugin version (for SHOW PLUGINS) */
-+ /* unsigned int */
-+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
-+
-+ /* struct st_mysql_show_var* */
-+ STRUCT_FLD(status_vars, NULL),
-+
-+ /* struct st_mysql_sys_var** */
-+ STRUCT_FLD(system_vars, NULL),
-+
-+ /* reserved for dependency checking */
-+ /* void* */
-+ STRUCT_FLD(__reserved1, NULL),
-+
-+ /* flags for plugin */
-+ /* unsigned long */
-+ STRUCT_FLD(flags, 0UL)
-+};
-+
- /***********************************************************************
- */
- static ST_FIELD_INFO i_s_innodb_rseg_fields_info[] =
---- a/storage/innobase/handler/i_s.h
-+++ b/storage/innobase/handler/i_s.h
-@@ -35,6 +35,13 @@
- extern struct st_mysql_plugin i_s_innodb_cmp_reset;
- extern struct st_mysql_plugin i_s_innodb_cmpmem;
- extern struct st_mysql_plugin i_s_innodb_cmpmem_reset;
-+extern struct st_mysql_plugin i_s_innodb_sys_tables;
-+extern struct st_mysql_plugin i_s_innodb_sys_tablestats;
-+extern struct st_mysql_plugin i_s_innodb_sys_indexes;
-+extern struct st_mysql_plugin i_s_innodb_sys_columns;
-+extern struct st_mysql_plugin i_s_innodb_sys_fields;
-+extern struct st_mysql_plugin i_s_innodb_sys_foreign;
-+extern struct st_mysql_plugin i_s_innodb_sys_foreign_cols;
- extern struct st_mysql_plugin i_s_innodb_rseg;
-
- #endif /* i_s_h */
+++ /dev/null
-# name : innodb_split_buf_pool_mutex.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/btr/btr0cur.c
-+++ b/storage/innobase/btr/btr0cur.c
-@@ -4070,7 +4070,8 @@
-
- mtr_commit(mtr);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
- mutex_enter(&block->mutex);
-
- /* Only free the block if it is still allocated to
-@@ -4081,16 +4082,21 @@
- && buf_block_get_space(block) == space
- && buf_block_get_page_no(block) == page_no) {
-
-- if (!buf_LRU_free_block(&block->page, all)
-- && all && block->page.zip.data) {
-+ if (!buf_LRU_free_block(&block->page, all, TRUE)
-+ && all && block->page.zip.data
-+ /* Now, buf_LRU_free_block() may release mutex temporarily */
-+ && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE
-+ && buf_block_get_space(block) == space
-+ && buf_block_get_page_no(block) == page_no) {
- /* Attempt to deallocate the uncompressed page
- if the whole block cannot be deallocted. */
-
-- buf_LRU_free_block(&block->page, FALSE);
-+ buf_LRU_free_block(&block->page, FALSE, TRUE);
- }
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- mutex_exit(&block->mutex);
- }
-
---- a/storage/innobase/btr/btr0sea.c
-+++ b/storage/innobase/btr/btr0sea.c
-@@ -1972,7 +1972,7 @@
- rec_offs_init(offsets_);
-
- rw_lock_x_lock(&btr_search_latch);
-- buf_pool_mutex_enter_all();
-+ buf_pool_page_hash_x_lock_all();
-
- cell_count = hash_get_n_cells(btr_search_sys->hash_index);
-
-@@ -1980,11 +1980,11 @@
- /* We release btr_search_latch every once in a while to
- give other queries a chance to run. */
- if ((i != 0) && ((i % chunk_size) == 0)) {
-- buf_pool_mutex_exit_all();
-+ buf_pool_page_hash_x_unlock_all();
- rw_lock_x_unlock(&btr_search_latch);
- os_thread_yield();
- rw_lock_x_lock(&btr_search_latch);
-- buf_pool_mutex_enter_all();
-+ buf_pool_page_hash_x_lock_all();
- }
-
- node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
-@@ -2093,11 +2093,11 @@
- /* We release btr_search_latch every once in a while to
- give other queries a chance to run. */
- if (i != 0) {
-- buf_pool_mutex_exit_all();
-+ buf_pool_page_hash_x_unlock_all();
- rw_lock_x_unlock(&btr_search_latch);
- os_thread_yield();
- rw_lock_x_lock(&btr_search_latch);
-- buf_pool_mutex_enter_all();
-+ buf_pool_page_hash_x_lock_all();
- }
-
- if (!ha_validate(btr_search_sys->hash_index, i, end_index)) {
-@@ -2105,7 +2105,7 @@
- }
- }
-
-- buf_pool_mutex_exit_all();
-+ buf_pool_page_hash_x_unlock_all();
- rw_lock_x_unlock(&btr_search_latch);
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
---- a/storage/innobase/buf/buf0buddy.c
-+++ b/storage/innobase/buf/buf0buddy.c
-@@ -58,7 +58,7 @@
-
- /** Validate a given zip_free list. */
- #define BUF_BUDDY_LIST_VALIDATE(b, i) \
-- UT_LIST_VALIDATE(list, buf_page_t, \
-+ UT_LIST_VALIDATE(zip_list, buf_page_t, \
- b->zip_free[i], \
- ut_ad(buf_page_get_state( \
- ut_list_node_313) \
-@@ -75,10 +75,11 @@
- ulint i) /*!< in: index of
- buf_pool->zip_free[] */
- {
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->zip_free_mutex));
- ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
- ut_ad(buf_pool->zip_free[i].start != bpage);
-- UT_LIST_ADD_FIRST(list, buf_pool->zip_free[i], bpage);
-+ UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_free[i], bpage);
- }
-
- /**********************************************************************//**
-@@ -93,16 +94,17 @@
- buf_pool->zip_free[] */
- {
- #ifdef UNIV_DEBUG
-- buf_page_t* prev = UT_LIST_GET_PREV(list, bpage);
-- buf_page_t* next = UT_LIST_GET_NEXT(list, bpage);
-+ buf_page_t* prev = UT_LIST_GET_PREV(zip_list, bpage);
-+ buf_page_t* next = UT_LIST_GET_NEXT(zip_list, bpage);
-
- ut_ad(!prev || buf_page_get_state(prev) == BUF_BLOCK_ZIP_FREE);
- ut_ad(!next || buf_page_get_state(next) == BUF_BLOCK_ZIP_FREE);
- #endif /* UNIV_DEBUG */
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->zip_free_mutex));
- ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
-- UT_LIST_REMOVE(list, buf_pool->zip_free[i], bpage);
-+ UT_LIST_REMOVE(zip_list, buf_pool->zip_free[i], bpage);
- }
-
- /**********************************************************************//**
-@@ -117,7 +119,8 @@
- {
- buf_page_t* bpage;
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->zip_free_mutex));
- ut_a(i < BUF_BUDDY_SIZES);
- ut_a(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
-
-@@ -159,16 +162,19 @@
- buf_buddy_block_free(
- /*=================*/
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
-- void* buf) /*!< in: buffer frame to deallocate */
-+ void* buf, /*!< in: buffer frame to deallocate */
-+ ibool have_page_hash_mutex)
- {
- const ulint fold = BUF_POOL_ZIP_FOLD_PTR(buf);
- buf_page_t* bpage;
- buf_block_t* block;
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- ut_ad(!mutex_own(&buf_pool->zip_mutex));
- ut_a(!ut_align_offset(buf, UNIV_PAGE_SIZE));
-
-+ mutex_enter(&buf_pool->zip_hash_mutex);
-+
- HASH_SEARCH(hash, buf_pool->zip_hash, fold, buf_page_t*, bpage,
- ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_MEMORY
- && bpage->in_zip_hash && !bpage->in_page_hash),
-@@ -180,12 +186,14 @@
- ut_d(bpage->in_zip_hash = FALSE);
- HASH_DELETE(buf_page_t, hash, buf_pool->zip_hash, fold, bpage);
-
-+ mutex_exit(&buf_pool->zip_hash_mutex);
-+
- ut_d(memset(buf, 0, UNIV_PAGE_SIZE));
- UNIV_MEM_INVALID(buf, UNIV_PAGE_SIZE);
-
- block = (buf_block_t*) bpage;
- mutex_enter(&block->mutex);
-- buf_LRU_block_free_non_file_page(block);
-+ buf_LRU_block_free_non_file_page(block, have_page_hash_mutex);
- mutex_exit(&block->mutex);
-
- ut_ad(buf_pool->buddy_n_frames > 0);
-@@ -202,7 +210,7 @@
- {
- buf_pool_t* buf_pool = buf_pool_from_block(block);
- const ulint fold = BUF_POOL_ZIP_FOLD(block);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- ut_ad(!mutex_own(&buf_pool->zip_mutex));
- ut_ad(buf_block_get_state(block) == BUF_BLOCK_READY_FOR_USE);
-
-@@ -214,7 +222,10 @@
- ut_ad(!block->page.in_page_hash);
- ut_ad(!block->page.in_zip_hash);
- ut_d(block->page.in_zip_hash = TRUE);
-+
-+ mutex_enter(&buf_pool->zip_hash_mutex);
- HASH_INSERT(buf_page_t, hash, buf_pool->zip_hash, fold, &block->page);
-+ mutex_exit(&buf_pool->zip_hash_mutex);
-
- ut_d(buf_pool->buddy_n_frames++);
- }
-@@ -268,26 +279,30 @@
- buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */
- ulint i, /*!< in: index of buf_pool->zip_free[],
- or BUF_BUDDY_SIZES */
-- ibool* lru) /*!< in: pointer to a variable that
-+ ibool* lru, /*!< in: pointer to a variable that
- will be assigned TRUE if storage was
- allocated from the LRU list and
- buf_pool->mutex was temporarily
- released */
-+ ibool have_page_hash_mutex)
- {
- buf_block_t* block;
-
- ut_ad(lru);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
- ut_ad(!mutex_own(&buf_pool->zip_mutex));
- ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
-
- if (i < BUF_BUDDY_SIZES) {
- /* Try to allocate from the buddy system. */
-+ mutex_enter(&buf_pool->zip_free_mutex);
- block = buf_buddy_alloc_zip(buf_pool, i);
-
- if (block) {
- goto func_exit;
- }
-+ mutex_exit(&buf_pool->zip_free_mutex);
- }
-
- /* Try allocating from the buf_pool->free list. */
-@@ -299,19 +314,30 @@
- }
-
- /* Try replacing an uncompressed page in the buffer pool. */
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ if (have_page_hash_mutex) {
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ }
- block = buf_LRU_get_free_block(buf_pool);
- *lru = TRUE;
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ if (have_page_hash_mutex) {
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
-+ }
-
- alloc_big:
- buf_buddy_block_register(block);
-
-+ mutex_enter(&buf_pool->zip_free_mutex);
- block = buf_buddy_alloc_from(
- buf_pool, block->frame, i, BUF_BUDDY_SIZES);
-
- func_exit:
- buf_pool->buddy_stat[i].used++;
-+ mutex_exit(&buf_pool->zip_free_mutex);
-+
- return(block);
- }
-
-@@ -325,8 +351,9 @@
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
- void* src, /*!< in: block to relocate */
- void* dst, /*!< in: free block to relocate to */
-- ulint i) /*!< in: index of
-+ ulint i, /*!< in: index of
- buf_pool->zip_free[] */
-+ ibool have_page_hash_mutex)
- {
- buf_page_t* bpage;
- const ulint size = BUF_BUDDY_LOW << i;
-@@ -334,13 +361,20 @@
- ulint space;
- ulint page_no;
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->zip_free_mutex));
- ut_ad(!mutex_own(&buf_pool->zip_mutex));
- ut_ad(!ut_align_offset(src, size));
- ut_ad(!ut_align_offset(dst, size));
- ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
- UNIV_MEM_ASSERT_W(dst, size);
-
-+ if (!have_page_hash_mutex) {
-+ mutex_exit(&buf_pool->zip_free_mutex);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
-+ }
-+
- /* We assume that all memory from buf_buddy_alloc()
- is used for compressed page frames. */
-
-@@ -374,6 +408,11 @@
- added to buf_pool->page_hash yet. Obviously,
- it cannot be relocated. */
-
-+ if (!have_page_hash_mutex) {
-+ mutex_enter(&buf_pool->zip_free_mutex);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ }
- return(FALSE);
- }
-
-@@ -383,18 +422,27 @@
- For the sake of simplicity, give up. */
- ut_ad(page_zip_get_size(&bpage->zip) < size);
-
-+ if (!have_page_hash_mutex) {
-+ mutex_enter(&buf_pool->zip_free_mutex);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ }
- return(FALSE);
- }
-
-+ /* To keep latch order */
-+ if (have_page_hash_mutex)
-+ mutex_exit(&buf_pool->zip_free_mutex);
-+
- /* The block must have been allocated, but it may
- contain uninitialized data. */
- UNIV_MEM_ASSERT_W(src, size);
-
-- mutex = buf_page_get_mutex(bpage);
-+ mutex = buf_page_get_mutex_enter(bpage);
-
-- mutex_enter(mutex);
-+ mutex_enter(&buf_pool->zip_free_mutex);
-
-- if (buf_page_can_relocate(bpage)) {
-+ if (mutex && buf_page_can_relocate(bpage)) {
- /* Relocate the compressed page. */
- ullint usec = ut_time_us(NULL);
- ut_a(bpage->zip.data == src);
-@@ -409,10 +457,22 @@
- buddy_stat->relocated_usec
- += ut_time_us(NULL) - usec;
- }
-+
-+ if (!have_page_hash_mutex) {
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ }
- return(TRUE);
- }
-
-- mutex_exit(mutex);
-+ if (!have_page_hash_mutex) {
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ }
-+
-+ if (mutex) {
-+ mutex_exit(mutex);
-+ }
- return(FALSE);
- }
-
-@@ -425,13 +485,15 @@
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
- void* buf, /*!< in: block to be freed, must not be
- pointed to by the buffer pool */
-- ulint i) /*!< in: index of buf_pool->zip_free[],
-+ ulint i, /*!< in: index of buf_pool->zip_free[],
- or BUF_BUDDY_SIZES */
-+ ibool have_page_hash_mutex)
- {
- buf_page_t* bpage;
- buf_page_t* buddy;
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->zip_free_mutex));
- ut_ad(!mutex_own(&buf_pool->zip_mutex));
- ut_ad(i <= BUF_BUDDY_SIZES);
- ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
-@@ -443,7 +505,9 @@
- ((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE;
-
- if (i == BUF_BUDDY_SIZES) {
-- buf_buddy_block_free(buf_pool, buf);
-+ mutex_exit(&buf_pool->zip_free_mutex);
-+ buf_buddy_block_free(buf_pool, buf, have_page_hash_mutex);
-+ mutex_enter(&buf_pool->zip_free_mutex);
- return;
- }
-
-@@ -491,7 +555,7 @@
-
- ut_a(bpage != buf);
- UNIV_MEM_ASSERT_W(bpage, BUF_BUDDY_LOW << i);
-- bpage = UT_LIST_GET_NEXT(list, bpage);
-+ bpage = UT_LIST_GET_NEXT(zip_list, bpage);
- }
-
- #ifndef UNIV_DEBUG_VALGRIND
-@@ -501,7 +565,7 @@
- ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i));
-
- /* The buddy is not free. Is there a free block of this size? */
-- bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
-+ bpage = UT_LIST_GET_LAST(buf_pool->zip_free[i]);
-
- if (bpage) {
-
-@@ -510,7 +574,7 @@
- buf_buddy_remove_from_free(buf_pool, bpage, i);
-
- /* Try to relocate the buddy of buf to the free block. */
-- if (buf_buddy_relocate(buf_pool, buddy, bpage, i)) {
-+ if (buf_buddy_relocate(buf_pool, buddy, bpage, i, have_page_hash_mutex)) {
-
- buddy->state = BUF_BLOCK_ZIP_FREE;
- goto buddy_is_free;
---- a/storage/innobase/buf/buf0buf.c
-+++ b/storage/innobase/buf/buf0buf.c
-@@ -263,6 +263,7 @@
- #ifdef UNIV_PFS_RWLOCK
- /* Keys to register buffer block related rwlocks and mutexes with
- performance schema */
-+UNIV_INTERN mysql_pfs_key_t buf_pool_page_hash_key;
- UNIV_INTERN mysql_pfs_key_t buf_block_lock_key;
- # ifdef UNIV_SYNC_DEBUG
- UNIV_INTERN mysql_pfs_key_t buf_block_debug_latch_key;
-@@ -273,6 +274,10 @@
- UNIV_INTERN mysql_pfs_key_t buffer_block_mutex_key;
- UNIV_INTERN mysql_pfs_key_t buf_pool_mutex_key;
- UNIV_INTERN mysql_pfs_key_t buf_pool_zip_mutex_key;
-+UNIV_INTERN mysql_pfs_key_t buf_pool_LRU_list_mutex_key;
-+UNIV_INTERN mysql_pfs_key_t buf_pool_free_list_mutex_key;
-+UNIV_INTERN mysql_pfs_key_t buf_pool_zip_free_mutex_key;
-+UNIV_INTERN mysql_pfs_key_t buf_pool_zip_hash_mutex_key;
- UNIV_INTERN mysql_pfs_key_t flush_list_mutex_key;
- #endif /* UNIV_PFS_MUTEX */
-
-@@ -890,9 +895,13 @@
- block->page.in_zip_hash = FALSE;
- block->page.in_flush_list = FALSE;
- block->page.in_free_list = FALSE;
-- block->in_unzip_LRU_list = FALSE;
- #endif /* UNIV_DEBUG */
-+ block->page.flush_list.prev = NULL;
-+ block->page.flush_list.next = NULL;
-+ block->page.zip_list.prev = NULL;
-+ block->page.zip_list.next = NULL;
- block->page.in_LRU_list = FALSE;
-+ block->in_unzip_LRU_list = FALSE;
- #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- block->n_pointers = 0;
- #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
-@@ -997,9 +1006,11 @@
- memset(block->frame, '\0', UNIV_PAGE_SIZE);
- #endif
- /* Add the block to the free list */
-- UT_LIST_ADD_LAST(list, buf_pool->free, (&block->page));
-+ mutex_enter(&buf_pool->free_list_mutex);
-+ UT_LIST_ADD_LAST(free, buf_pool->free, (&block->page));
-
- ut_d(block->page.in_free_list = TRUE);
-+ mutex_exit(&buf_pool->free_list_mutex);
- ut_ad(buf_pool_from_block(block) == buf_pool);
-
- block++;
-@@ -1054,7 +1065,8 @@
- buf_chunk_t* chunk = buf_pool->chunks;
-
- ut_ad(buf_pool);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->zip_free_mutex));
- for (n = buf_pool->n_chunks; n--; chunk++) {
-
- buf_block_t* block = buf_chunk_contains_zip(chunk, data);
-@@ -1160,9 +1172,21 @@
- ------------------------------- */
- mutex_create(buf_pool_mutex_key,
- &buf_pool->mutex, SYNC_BUF_POOL);
-+ mutex_create(buf_pool_LRU_list_mutex_key,
-+ &buf_pool->LRU_list_mutex, SYNC_BUF_LRU_LIST);
-+ rw_lock_create(buf_pool_page_hash_key,
-+ &buf_pool->page_hash_latch, SYNC_BUF_PAGE_HASH);
-+ mutex_create(buf_pool_free_list_mutex_key,
-+ &buf_pool->free_list_mutex, SYNC_BUF_FREE_LIST);
-+ mutex_create(buf_pool_zip_free_mutex_key,
-+ &buf_pool->zip_free_mutex, SYNC_BUF_ZIP_FREE);
-+ mutex_create(buf_pool_zip_hash_mutex_key,
-+ &buf_pool->zip_hash_mutex, SYNC_BUF_ZIP_HASH);
- mutex_create(buf_pool_zip_mutex_key,
- &buf_pool->zip_mutex, SYNC_BUF_BLOCK);
-
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
- buf_pool_mutex_enter(buf_pool);
-
- if (buf_pool_size > 0) {
-@@ -1175,6 +1199,8 @@
- mem_free(chunk);
- mem_free(buf_pool);
-
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
- buf_pool_mutex_exit(buf_pool);
-
- return(DB_ERROR);
-@@ -1205,6 +1231,8 @@
-
- /* All fields are initialized by mem_zalloc(). */
-
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
- buf_pool_mutex_exit(buf_pool);
-
- return(DB_SUCCESS);
-@@ -1376,7 +1404,11 @@
- ulint fold;
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
-+#ifdef UNIV_SYNC_DEBUG
-+ ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX));
-+#endif
- ut_ad(mutex_own(buf_page_get_mutex(bpage)));
- ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
- ut_a(bpage->buf_fix_count == 0);
-@@ -1487,21 +1519,32 @@
- buf_page_t* bpage;
- ulint i;
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
-+ mutex_t* block_mutex;
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
- bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
-
- if (UNIV_LIKELY_NULL(bpage)) {
-+
-+ block_mutex = buf_page_get_mutex_enter(bpage);
-+ ut_a(block_mutex);
-+
- if (!buf_pool_watch_is_sentinel(buf_pool, bpage)) {
- /* The page was loaded meanwhile. */
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
- return(bpage);
- }
- /* Add to an existing watch. */
- bpage->buf_fix_count++;
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ mutex_exit(block_mutex);
- return(NULL);
- }
-
-+ /* buf_pool->watch is protected by zip_mutex for now */
-+ mutex_enter(&buf_pool->zip_mutex);
- for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) {
- bpage = &buf_pool->watch[i];
-
-@@ -1525,10 +1568,12 @@
- bpage->space = space;
- bpage->offset = offset;
- bpage->buf_fix_count = 1;
--
-+ bpage->buf_pool_index = buf_pool_index(buf_pool);
- ut_d(bpage->in_page_hash = TRUE);
- HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
- fold, bpage);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ mutex_exit(&buf_pool->zip_mutex);
- return(NULL);
- case BUF_BLOCK_ZIP_PAGE:
- ut_ad(bpage->in_page_hash);
-@@ -1546,6 +1591,8 @@
- ut_error;
-
- /* Fix compiler warning */
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ mutex_exit(&buf_pool->zip_mutex);
- return(NULL);
- }
-
-@@ -1563,7 +1610,11 @@
- space, offset) */
- buf_page_t* watch) /*!< in/out: sentinel for watch */
- {
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+#ifdef UNIV_SYNC_DEBUG
-+ ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX));
-+#endif
-+ ut_ad(mutex_own(&buf_pool->zip_mutex)); /* for now */
-
- HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, watch);
- ut_d(watch->in_page_hash = FALSE);
-@@ -1585,28 +1636,31 @@
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
- ulint fold = buf_page_address_fold(space, offset);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
- bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
- /* The page must exist because buf_pool_watch_set()
- increments buf_fix_count. */
- ut_a(bpage);
-
- if (UNIV_UNLIKELY(!buf_pool_watch_is_sentinel(buf_pool, bpage))) {
-- mutex_t* mutex = buf_page_get_mutex(bpage);
-+ mutex_t* mutex = buf_page_get_mutex_enter(bpage);
-
-- mutex_enter(mutex);
- ut_a(bpage->buf_fix_count > 0);
- bpage->buf_fix_count--;
- mutex_exit(mutex);
- } else {
-+ mutex_enter(&buf_pool->zip_mutex);
- ut_a(bpage->buf_fix_count > 0);
-
- if (UNIV_LIKELY(!--bpage->buf_fix_count)) {
- buf_pool_watch_remove(buf_pool, fold, bpage);
- }
-+ mutex_exit(&buf_pool->zip_mutex);
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
- }
-
- /****************************************************************//**
-@@ -1626,14 +1680,16 @@
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
- ulint fold = buf_page_address_fold(space, offset);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ rw_lock_s_lock(&buf_pool->page_hash_latch);
-
- bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
- /* The page must exist because buf_pool_watch_set()
- increments buf_fix_count. */
- ut_a(bpage);
- ret = !buf_pool_watch_is_sentinel(buf_pool, bpage);
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
-
- return(ret);
- }
-@@ -1650,13 +1706,15 @@
- {
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-
- ut_a(buf_page_in_file(bpage));
-
- buf_LRU_make_block_young(bpage);
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- }
-
- /********************************************************************//**
-@@ -1680,14 +1738,20 @@
- ut_a(buf_page_in_file(bpage));
-
- if (buf_page_peek_if_too_old(bpage)) {
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
- buf_LRU_make_block_young(bpage);
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- } else if (!access_time) {
- ulint time_ms = ut_time_ms();
-- buf_pool_mutex_enter(buf_pool);
-+ mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
-+ //buf_pool_mutex_enter(buf_pool);
-+ if (block_mutex) {
- buf_page_set_accessed(bpage, time_ms);
-- buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(block_mutex);
-+ }
-+ //buf_pool_mutex_exit(buf_pool);
- }
- }
-
-@@ -1704,7 +1768,8 @@
- buf_block_t* block;
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ rw_lock_s_lock(&buf_pool->page_hash_latch);
-
- block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
-
-@@ -1713,7 +1778,8 @@
- block->check_index_page_at_flush = FALSE;
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
- }
-
- #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
-@@ -1733,7 +1799,8 @@
- buf_page_t* bpage;
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ rw_lock_s_lock(&buf_pool->page_hash_latch);
-
- bpage = buf_page_hash_get(buf_pool, space, offset);
-
-@@ -1744,7 +1811,8 @@
- bpage->file_page_was_freed = TRUE;
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
-
- return(bpage);
- }
-@@ -1765,7 +1833,8 @@
- buf_page_t* bpage;
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ rw_lock_s_lock(&buf_pool->page_hash_latch);
-
- bpage = buf_page_hash_get(buf_pool, space, offset);
-
-@@ -1774,7 +1843,8 @@
- bpage->file_page_was_freed = FALSE;
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
-
- return(bpage);
- }
-@@ -1806,8 +1876,9 @@
- buf_pool->stat.n_page_gets++;
-
- for (;;) {
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
- lookup:
-+ rw_lock_s_lock(&buf_pool->page_hash_latch);
- bpage = buf_page_hash_get(buf_pool, space, offset);
- if (bpage) {
- ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
-@@ -1816,7 +1887,8 @@
-
- /* Page not in buf_pool: needs to be read from file */
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
-
- buf_read_page(space, zip_size, offset);
-
-@@ -1828,10 +1900,15 @@
- if (UNIV_UNLIKELY(!bpage->zip.data)) {
- /* There is no compressed page. */
- err_exit:
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
- return(NULL);
- }
-
-+ block_mutex = buf_page_get_mutex_enter(bpage);
-+
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
-+
- ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
-
- switch (buf_page_get_state(bpage)) {
-@@ -1840,24 +1917,43 @@
- case BUF_BLOCK_MEMORY:
- case BUF_BLOCK_REMOVE_HASH:
- case BUF_BLOCK_ZIP_FREE:
-+ if (block_mutex)
-+ mutex_exit(block_mutex);
- break;
- case BUF_BLOCK_ZIP_PAGE:
- case BUF_BLOCK_ZIP_DIRTY:
-- block_mutex = &buf_pool->zip_mutex;
-- mutex_enter(block_mutex);
-+ ut_a(block_mutex == &buf_pool->zip_mutex);
- bpage->buf_fix_count++;
- goto got_block;
- case BUF_BLOCK_FILE_PAGE:
-- block_mutex = &((buf_block_t*) bpage)->mutex;
-+ ut_a(block_mutex == &((buf_block_t*) bpage)->mutex);
-+
-+ /* release mutex to obey to latch-order */
-+ mutex_exit(block_mutex);
-+
-+ /* get LRU_list_mutex for buf_LRU_free_block() */
-+ mutex_enter(&buf_pool->LRU_list_mutex);
- mutex_enter(block_mutex);
-
-- /* Discard the uncompressed page frame if possible. */
-- if (buf_LRU_free_block(bpage, FALSE)) {
-+ if (UNIV_UNLIKELY(bpage->space != space
-+ || bpage->offset != offset
-+ || !bpage->in_LRU_list
-+ || !bpage->zip.data)) {
-+ /* someone should interrupt, retry */
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ mutex_exit(block_mutex);
-+ goto lookup;
-+ }
-
-+ /* Discard the uncompressed page frame if possible. */
-+ if (buf_LRU_free_block(bpage, FALSE, TRUE)) {
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- mutex_exit(block_mutex);
- goto lookup;
- }
-
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+
- buf_block_buf_fix_inc((buf_block_t*) bpage,
- __FILE__, __LINE__);
- goto got_block;
-@@ -1870,7 +1966,7 @@
- must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ;
- access_time = buf_page_is_accessed(bpage);
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-
- mutex_exit(block_mutex);
-
-@@ -2181,7 +2277,7 @@
- const buf_block_t* block) /*!< in: pointer to block,
- not dereferenced */
- {
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-
- if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
- /* The pointer should be aligned. */
-@@ -2217,6 +2313,7 @@
- ulint fix_type;
- ibool must_read;
- ulint retries = 0;
-+ mutex_t* block_mutex = NULL;
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
-
- ut_ad(mtr);
-@@ -2250,18 +2347,24 @@
- fold = buf_page_address_fold(space, offset);
- loop:
- block = guess;
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-
- if (block) {
-+ block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
-+
- /* If the guess is a compressed page descriptor that
- has been allocated by buf_page_alloc_descriptor(),
- it may have been freed by buf_relocate(). */
-
-- if (!buf_block_is_uncompressed(buf_pool, block)
-+ if (!block_mutex) {
-+ block = guess = NULL;
-+ } else if (!buf_block_is_uncompressed(buf_pool, block)
- || offset != block->page.offset
- || space != block->page.space
- || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
-
-+ mutex_exit(block_mutex);
-+
- block = guess = NULL;
- } else {
- ut_ad(!block->page.in_zip_hash);
-@@ -2270,12 +2373,19 @@
- }
-
- if (block == NULL) {
-+ rw_lock_s_lock(&buf_pool->page_hash_latch);
- block = (buf_block_t*) buf_page_hash_get_low(
- buf_pool, space, offset, fold);
-+ if (block) {
-+ block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
-+ ut_a(block_mutex);
-+ }
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
- }
-
- loop2:
- if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
-+ mutex_exit(block_mutex);
- block = NULL;
- }
-
-@@ -2287,12 +2397,14 @@
- space, offset, fold);
-
- if (UNIV_LIKELY_NULL(block)) {
--
-+ block_mutex = buf_page_get_mutex((buf_page_t*)block);
-+ ut_a(block_mutex);
-+ ut_ad(mutex_own(block_mutex));
- goto got_block;
- }
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-
- if (mode == BUF_GET_IF_IN_POOL
- || mode == BUF_PEEK_IF_IN_POOL
-@@ -2345,7 +2457,8 @@
- /* The page is being read to buffer pool,
- but we cannot wait around for the read to
- complete. */
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(block_mutex);
-
- return(NULL);
- }
-@@ -2355,38 +2468,49 @@
- ibool success;
-
- case BUF_BLOCK_FILE_PAGE:
-+ if (block_mutex == &buf_pool->zip_mutex) {
-+ /* it is wrong mutex... */
-+ mutex_exit(block_mutex);
-+ goto loop;
-+ }
- break;
-
- case BUF_BLOCK_ZIP_PAGE:
- case BUF_BLOCK_ZIP_DIRTY:
-+ ut_ad(block_mutex == &buf_pool->zip_mutex);
- bpage = &block->page;
- /* Protect bpage->buf_fix_count. */
-- mutex_enter(&buf_pool->zip_mutex);
-+ //mutex_enter(&buf_pool->zip_mutex);
-
- if (bpage->buf_fix_count
- || buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
- /* This condition often occurs when the buffer
- is not buffer-fixed, but I/O-fixed by
- buf_page_init_for_read(). */
-- mutex_exit(&buf_pool->zip_mutex);
-+ //mutex_exit(&buf_pool->zip_mutex);
- wait_until_unfixed:
- /* The block is buffer-fixed or I/O-fixed.
- Try again later. */
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(block_mutex);
- os_thread_sleep(WAIT_FOR_READ);
-
- goto loop;
- }
-
- /* Allocate an uncompressed page. */
-- buf_pool_mutex_exit(buf_pool);
-- mutex_exit(&buf_pool->zip_mutex);
-+ //buf_pool_mutex_exit(buf_pool);
-+ //mutex_exit(&buf_pool->zip_mutex);
-+ mutex_exit(block_mutex);
-
- block = buf_LRU_get_free_block(buf_pool);
- ut_a(block);
-+ block_mutex = &block->mutex;
-
-- buf_pool_mutex_enter(buf_pool);
-- mutex_enter(&block->mutex);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
-+ mutex_enter(block_mutex);
-
- {
- buf_page_t* hash_bpage;
-@@ -2399,35 +2523,47 @@
- while buf_pool->mutex was released.
- Free the block that was allocated. */
-
-- buf_LRU_block_free_non_file_page(block);
-- mutex_exit(&block->mutex);
-+ buf_LRU_block_free_non_file_page(block, TRUE);
-+ mutex_exit(block_mutex);
-
- block = (buf_block_t*) hash_bpage;
-+ if (block) {
-+ block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
-+ ut_a(block_mutex);
-+ }
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- goto loop2;
- }
- }
-
-+ mutex_enter(&buf_pool->zip_mutex);
-+
- if (UNIV_UNLIKELY
- (bpage->buf_fix_count
- || buf_page_get_io_fix(bpage) != BUF_IO_NONE)) {
-
-+ mutex_exit(&buf_pool->zip_mutex);
- /* The block was buffer-fixed or I/O-fixed
- while buf_pool->mutex was not held by this thread.
- Free the block that was allocated and try again.
- This should be extremely unlikely. */
-
-- buf_LRU_block_free_non_file_page(block);
-- mutex_exit(&block->mutex);
-+ buf_LRU_block_free_non_file_page(block, TRUE);
-+ //mutex_exit(&block->mutex);
-
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- goto wait_until_unfixed;
- }
-
- /* Move the compressed page from bpage to block,
- and uncompress it. */
-
-- mutex_enter(&buf_pool->zip_mutex);
--
- buf_relocate(bpage, &block->page);
-+
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+
- buf_block_init_low(block);
- block->lock_hash_val = lock_rec_hash(space, offset);
-
-@@ -2437,7 +2573,7 @@
- if (buf_page_get_state(&block->page)
- == BUF_BLOCK_ZIP_PAGE) {
- #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
-- UT_LIST_REMOVE(list, buf_pool->zip_clean,
-+ UT_LIST_REMOVE(zip_list, buf_pool->zip_clean,
- &block->page);
- #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
- ut_ad(!block->page.in_flush_list);
-@@ -2455,18 +2591,23 @@
- /* Insert at the front of unzip_LRU list */
- buf_unzip_LRU_add_block(block, FALSE);
-
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+
- block->page.buf_fix_count = 1;
- buf_block_set_io_fix(block, BUF_IO_READ);
- rw_lock_x_lock_func(&block->lock, 0, file, line);
-
- UNIV_MEM_INVALID(bpage, sizeof *bpage);
-
-- mutex_exit(&block->mutex);
-+ mutex_exit(block_mutex);
- mutex_exit(&buf_pool->zip_mutex);
-- buf_pool->n_pend_unzip++;
-
-+ buf_pool_mutex_enter(buf_pool);
-+ buf_pool->n_pend_unzip++;
- buf_pool_mutex_exit(buf_pool);
-
-+ //buf_pool_mutex_exit(buf_pool);
-+
- buf_page_free_descriptor(bpage);
-
- /* Decompress the page and apply buffered operations
-@@ -2480,12 +2621,15 @@
- }
-
- /* Unfix and unlatch the block. */
-- buf_pool_mutex_enter(buf_pool);
-- mutex_enter(&block->mutex);
-+ //buf_pool_mutex_enter(buf_pool);
-+ block_mutex = &block->mutex;
-+ mutex_enter(block_mutex);
- block->page.buf_fix_count--;
- buf_block_set_io_fix(block, BUF_IO_NONE);
-- mutex_exit(&block->mutex);
-+
-+ buf_pool_mutex_enter(buf_pool);
- buf_pool->n_pend_unzip--;
-+ buf_pool_mutex_exit(buf_pool);
- rw_lock_x_unlock(&block->lock);
-
- break;
-@@ -2501,7 +2645,7 @@
-
- ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
-
-- mutex_enter(&block->mutex);
-+ //mutex_enter(&block->mutex);
- #if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no padding in buf_page_t. On
- other systems, Valgrind could complain about uninitialized pad
-@@ -2514,8 +2658,8 @@
- /* Try to evict the block from the buffer pool, to use the
- insert buffer (change buffer) as much as possible. */
-
-- if (buf_LRU_free_block(&block->page, TRUE)) {
-- mutex_exit(&block->mutex);
-+ if (buf_LRU_free_block(&block->page, TRUE, FALSE)) {
-+ mutex_exit(block_mutex);
- if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
- /* Set the watch, as it would have
- been set if the page were not in the
-@@ -2524,6 +2668,9 @@
- space, offset, fold);
-
- if (UNIV_LIKELY_NULL(block)) {
-+ block_mutex = buf_page_get_mutex((buf_page_t*)block);
-+ ut_a(block_mutex);
-+ ut_ad(mutex_own(block_mutex));
-
- /* The page entered the buffer
- pool for some reason. Try to
-@@ -2531,7 +2678,7 @@
- goto got_block;
- }
- }
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
- fprintf(stderr,
- "innodb_change_buffering_debug evict %u %u\n",
- (unsigned) space, (unsigned) offset);
-@@ -2553,13 +2700,14 @@
- ut_a(mode == BUF_GET_POSSIBLY_FREED
- || !block->page.file_page_was_freed);
- #endif
-- mutex_exit(&block->mutex);
-+ //mutex_exit(&block->mutex);
-
- /* Check if this is the first access to the page */
-
- access_time = buf_page_is_accessed(&block->page);
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(block_mutex);
-
- if (UNIV_LIKELY(mode != BUF_PEEK_IF_IN_POOL)) {
- buf_page_set_accessed_make_young(&block->page, access_time);
-@@ -2792,9 +2940,11 @@
- buf_pool = buf_pool_from_block(block);
-
- if (mode == BUF_MAKE_YOUNG && buf_page_peek_if_too_old(&block->page)) {
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
- buf_LRU_make_block_young(&block->page);
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- } else if (!buf_page_is_accessed(&block->page)) {
- /* Above, we do a dirty read on purpose, to avoid
- mutex contention. The field buf_page_t::access_time
-@@ -2802,9 +2952,11 @@
- field must be protected by mutex, however. */
- ulint time_ms = ut_time_ms();
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&block->mutex);
- buf_page_set_accessed(&block->page, time_ms);
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&block->mutex);
- }
-
- ut_ad(!ibuf_inside(mtr) || mode == BUF_KEEP_OLD);
-@@ -2871,18 +3023,21 @@
- ut_ad(mtr);
- ut_ad(mtr->state == MTR_ACTIVE);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ rw_lock_s_lock(&buf_pool->page_hash_latch);
- block = buf_block_hash_get(buf_pool, space_id, page_no);
-
- if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
- return(NULL);
- }
-
- ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
-
- mutex_enter(&block->mutex);
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
-
- #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
- ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
-@@ -2972,7 +3127,10 @@
- buf_page_t* hash_page;
-
- ut_ad(buf_pool == buf_pool_get(space, offset));
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+#ifdef UNIV_SYNC_DEBUG
-+ ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX));
-+#endif
- ut_ad(mutex_own(&(block->mutex)));
- ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
-
-@@ -3001,11 +3159,14 @@
- if (UNIV_LIKELY(!hash_page)) {
- } else if (buf_pool_watch_is_sentinel(buf_pool, hash_page)) {
- /* Preserve the reference count. */
-- ulint buf_fix_count = hash_page->buf_fix_count;
-+ ulint buf_fix_count;
-
-+ mutex_enter(&buf_pool->zip_mutex);
-+ buf_fix_count = hash_page->buf_fix_count;
- ut_a(buf_fix_count > 0);
- block->page.buf_fix_count += buf_fix_count;
- buf_pool_watch_remove(buf_pool, fold, hash_page);
-+ mutex_exit(&buf_pool->zip_mutex);
- } else {
- fprintf(stderr,
- "InnoDB: Error: page %lu %lu already found"
-@@ -3015,7 +3176,8 @@
- (const void*) hash_page, (const void*) block);
- #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
- mutex_exit(&block->mutex);
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
- buf_print();
- buf_LRU_print();
- buf_validate();
-@@ -3098,7 +3260,9 @@
-
- fold = buf_page_address_fold(space, offset);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
-
- watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
- if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) {
-@@ -3107,9 +3271,15 @@
- err_exit:
- if (block) {
- mutex_enter(&block->mutex);
-- buf_LRU_block_free_non_file_page(block);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ buf_LRU_block_free_non_file_page(block, FALSE);
- mutex_exit(&block->mutex);
- }
-+ else {
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ }
-
- bpage = NULL;
- goto func_exit;
-@@ -3132,6 +3302,8 @@
-
- buf_page_init(buf_pool, space, offset, fold, block);
-
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+
- /* The block must be put to the LRU list, to the old blocks */
- buf_LRU_add_block(bpage, TRUE/* to old blocks */);
-
-@@ -3159,7 +3331,7 @@
- been added to buf_pool->LRU and
- buf_pool->page_hash. */
- mutex_exit(&block->mutex);
-- data = buf_buddy_alloc(buf_pool, zip_size, &lru);
-+ data = buf_buddy_alloc(buf_pool, zip_size, &lru, FALSE);
- mutex_enter(&block->mutex);
- block->page.zip.data = data;
-
-@@ -3172,13 +3344,14 @@
- buf_unzip_LRU_add_block(block, TRUE);
- }
-
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- mutex_exit(&block->mutex);
- } else {
- /* The compressed page must be allocated before the
- control block (bpage), in order to avoid the
- invocation of buf_buddy_relocate_block() on
- uninitialized data. */
-- data = buf_buddy_alloc(buf_pool, zip_size, &lru);
-+ data = buf_buddy_alloc(buf_pool, zip_size, &lru, TRUE);
-
- /* If buf_buddy_alloc() allocated storage from the LRU list,
- it released and reacquired buf_pool->mutex. Thus, we must
-@@ -3194,7 +3367,10 @@
-
- /* The block was added by some other thread. */
- watch_page = NULL;
-- buf_buddy_free(buf_pool, data, zip_size);
-+ buf_buddy_free(buf_pool, data, zip_size, TRUE);
-+
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-
- bpage = NULL;
- goto func_exit;
-@@ -3242,20 +3418,26 @@
- HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold,
- bpage);
-
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+
- /* The block must be put to the LRU list, to the old blocks */
- buf_LRU_add_block(bpage, TRUE/* to old blocks */);
- #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
- buf_LRU_insert_zip_clean(bpage);
- #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
-
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+
- buf_page_set_io_fix(bpage, BUF_IO_READ);
-
- mutex_exit(&buf_pool->zip_mutex);
- }
-
-+ buf_pool_mutex_enter(buf_pool);
- buf_pool->n_pend_reads++;
--func_exit:
- buf_pool_mutex_exit(buf_pool);
-+func_exit:
-+ //buf_pool_mutex_exit(buf_pool);
-
- if (mode == BUF_READ_IBUF_PAGES_ONLY) {
-
-@@ -3297,7 +3479,9 @@
-
- fold = buf_page_address_fold(space, offset);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
-
- block = (buf_block_t*) buf_page_hash_get_low(
- buf_pool, space, offset, fold);
-@@ -3313,7 +3497,9 @@
- #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
-
- /* Page can be found in buf_pool */
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-
- buf_block_free(free_block);
-
-@@ -3335,6 +3521,7 @@
- mutex_enter(&block->mutex);
-
- buf_page_init(buf_pool, space, offset, fold, block);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-
- /* The block must be put to the LRU list */
- buf_LRU_add_block(&block->page, FALSE);
-@@ -3361,7 +3548,7 @@
- the reacquisition of buf_pool->mutex. We also must
- defer this operation until after the block descriptor
- has been added to buf_pool->LRU and buf_pool->page_hash. */
-- data = buf_buddy_alloc(buf_pool, zip_size, &lru);
-+ data = buf_buddy_alloc(buf_pool, zip_size, &lru, FALSE);
- mutex_enter(&block->mutex);
- block->page.zip.data = data;
-
-@@ -3379,7 +3566,8 @@
-
- buf_page_set_accessed(&block->page, time_ms);
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-
- mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
-
-@@ -3434,7 +3622,9 @@
- ibool ret = TRUE;
-
- /* First unfix and release lock on the bpage */
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
- mutex_enter(buf_page_get_mutex(bpage));
- ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ);
- ut_ad(bpage->buf_fix_count == 0);
-@@ -3455,11 +3645,15 @@
- ret = FALSE;
- }
-
-+ buf_pool_mutex_enter(buf_pool);
- ut_ad(buf_pool->n_pend_reads > 0);
- buf_pool->n_pend_reads--;
-+ buf_pool_mutex_exit(buf_pool);
-
- mutex_exit(buf_page_get_mutex(bpage));
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-
- return(ret);
- }
-@@ -3477,6 +3671,8 @@
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
- const ibool uncompressed = (buf_page_get_state(bpage)
- == BUF_BLOCK_FILE_PAGE);
-+ ibool have_LRU_mutex = FALSE;
-+ mutex_t* block_mutex;
-
- ut_a(buf_page_in_file(bpage));
-
-@@ -3619,8 +3815,26 @@
- }
- }
-
-+ if (io_type == BUF_IO_WRITE
-+ && (buf_page_get_state(bpage) == BUF_BLOCK_ZIP_DIRTY
-+ || buf_page_get_flush_type(bpage) == BUF_FLUSH_LRU)) {
-+ /* to keep consistency at buf_LRU_insert_zip_clean() */
-+ have_LRU_mutex = TRUE; /* optimistic */
-+ }
-+retry_mutex:
-+ if (have_LRU_mutex)
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ block_mutex = buf_page_get_mutex_enter(bpage);
-+ ut_a(block_mutex);
-+ if (io_type == BUF_IO_WRITE
-+ && (buf_page_get_state(bpage) == BUF_BLOCK_ZIP_DIRTY
-+ || buf_page_get_flush_type(bpage) == BUF_FLUSH_LRU)
-+ && !have_LRU_mutex) {
-+ mutex_exit(block_mutex);
-+ have_LRU_mutex = TRUE;
-+ goto retry_mutex;
-+ }
- buf_pool_mutex_enter(buf_pool);
-- mutex_enter(buf_page_get_mutex(bpage));
-
- #ifdef UNIV_IBUF_COUNT_DEBUG
- if (io_type == BUF_IO_WRITE || uncompressed) {
-@@ -3643,6 +3857,7 @@
- the x-latch to this OS thread: do not let this confuse you in
- debugging! */
-
-+ ut_a(!have_LRU_mutex);
- ut_ad(buf_pool->n_pend_reads > 0);
- buf_pool->n_pend_reads--;
- buf_pool->stat.n_pages_read++;
-@@ -3660,6 +3875,9 @@
-
- buf_flush_write_complete(bpage);
-
-+ if (have_LRU_mutex)
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+
- if (uncompressed) {
- rw_lock_s_unlock_gen(&((buf_block_t*) bpage)->lock,
- BUF_IO_WRITE);
-@@ -3682,8 +3900,8 @@
- }
- #endif /* UNIV_DEBUG */
-
-- mutex_exit(buf_page_get_mutex(bpage));
- buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(block_mutex);
- }
-
- /*********************************************************************//**
-@@ -3700,7 +3918,9 @@
-
- ut_ad(buf_pool);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
-
- chunk = buf_pool->chunks;
-
-@@ -3717,7 +3937,9 @@
- }
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-
- return(TRUE);
- }
-@@ -3765,7 +3987,8 @@
- freed = buf_LRU_search_and_free_block(buf_pool, 100);
- }
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-
- ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
- ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
-@@ -3778,7 +4001,8 @@
- memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat));
- buf_refresh_io_stats(buf_pool);
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- }
-
- /*********************************************************************//**
-@@ -3820,7 +4044,10 @@
-
- ut_ad(buf_pool);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
-+ /* for keep the new latch order, it cannot validate correctly... */
-
- chunk = buf_pool->chunks;
-
-@@ -3918,7 +4145,7 @@
- /* Check clean compressed-only blocks. */
-
- for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
-- b = UT_LIST_GET_NEXT(list, b)) {
-+ b = UT_LIST_GET_NEXT(zip_list, b)) {
- ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
- switch (buf_page_get_io_fix(b)) {
- case BUF_IO_NONE:
-@@ -3950,7 +4177,7 @@
-
- buf_flush_list_mutex_enter(buf_pool);
- for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
-- b = UT_LIST_GET_NEXT(list, b)) {
-+ b = UT_LIST_GET_NEXT(flush_list, b)) {
- ut_ad(b->in_flush_list);
- ut_a(b->oldest_modification);
- n_flush++;
-@@ -4010,6 +4237,8 @@
- }
-
- ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == n_lru);
-+ /* because of latching order with block->mutex, we cannot get needed mutexes before that */
-+/*
- if (UT_LIST_GET_LEN(buf_pool->free) != n_free) {
- fprintf(stderr, "Free list len %lu, free blocks %lu\n",
- (ulong) UT_LIST_GET_LEN(buf_pool->free),
-@@ -4020,8 +4249,11 @@
- ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
- ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
- ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
-+*/
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-
- ut_a(buf_LRU_validate());
- ut_a(buf_flush_validate(buf_pool));
-@@ -4077,7 +4309,9 @@
- index_ids = mem_alloc(size * sizeof *index_ids);
- counts = mem_alloc(sizeof(ulint) * size);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ mutex_enter(&buf_pool->free_list_mutex);
- buf_flush_list_mutex_enter(buf_pool);
-
- fprintf(stderr,
-@@ -4146,7 +4380,9 @@
- }
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ mutex_exit(&buf_pool->free_list_mutex);
-
- for (i = 0; i < n_found; i++) {
- index = dict_index_get_if_in_cache(index_ids[i]);
-@@ -4203,7 +4439,7 @@
- buf_chunk_t* chunk;
- ulint fixed_pages_number = 0;
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-
- chunk = buf_pool->chunks;
-
-@@ -4237,7 +4473,7 @@
- /* Traverse the lists of clean and dirty compressed-only blocks. */
-
- for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
-- b = UT_LIST_GET_NEXT(list, b)) {
-+ b = UT_LIST_GET_NEXT(zip_list, b)) {
- ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
- ut_a(buf_page_get_io_fix(b) != BUF_IO_WRITE);
-
-@@ -4249,7 +4485,7 @@
-
- buf_flush_list_mutex_enter(buf_pool);
- for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
-- b = UT_LIST_GET_NEXT(list, b)) {
-+ b = UT_LIST_GET_NEXT(flush_list, b)) {
- ut_ad(b->in_flush_list);
-
- switch (buf_page_get_state(b)) {
-@@ -4275,7 +4511,7 @@
-
- buf_flush_list_mutex_exit(buf_pool);
- mutex_exit(&buf_pool->zip_mutex);
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-
- return(fixed_pages_number);
- }
-@@ -4433,6 +4669,8 @@
- /* Find appropriate pool_info to store stats for this buffer pool */
- pool_info = &all_pool_info[pool_id];
-
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ mutex_enter(&buf_pool->free_list_mutex);
- buf_pool_mutex_enter(buf_pool);
- buf_flush_list_mutex_enter(buf_pool);
-
-@@ -4548,6 +4786,8 @@
- pool_info->unzip_cur = buf_LRU_stat_cur.unzip;
-
- buf_refresh_io_stats(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ mutex_exit(&buf_pool->free_list_mutex);
- buf_pool_mutex_exit(buf_pool);
- }
-
-@@ -4792,11 +5032,13 @@
- {
- ulint len;
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->free_list_mutex);
-
- len = UT_LIST_GET_LEN(buf_pool->free);
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->free_list_mutex);
-
- return(len);
- }
---- a/storage/innobase/buf/buf0flu.c
-+++ b/storage/innobase/buf/buf0flu.c
-@@ -307,7 +307,7 @@
-
- ut_d(block->page.in_flush_list = TRUE);
- block->page.oldest_modification = lsn;
-- UT_LIST_ADD_FIRST(list, buf_pool->flush_list, &block->page);
-+ UT_LIST_ADD_FIRST(flush_list, buf_pool->flush_list, &block->page);
-
- #ifdef UNIV_DEBUG_VALGRIND
- {
-@@ -401,14 +401,14 @@
- > block->page.oldest_modification) {
- ut_ad(b->in_flush_list);
- prev_b = b;
-- b = UT_LIST_GET_NEXT(list, b);
-+ b = UT_LIST_GET_NEXT(flush_list, b);
- }
- }
-
- if (prev_b == NULL) {
-- UT_LIST_ADD_FIRST(list, buf_pool->flush_list, &block->page);
-+ UT_LIST_ADD_FIRST(flush_list, buf_pool->flush_list, &block->page);
- } else {
-- UT_LIST_INSERT_AFTER(list, buf_pool->flush_list,
-+ UT_LIST_INSERT_AFTER(flush_list, buf_pool->flush_list,
- prev_b, &block->page);
- }
-
-@@ -434,7 +434,7 @@
- //buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
- //ut_ad(buf_pool_mutex_own(buf_pool));
- #endif
-- //ut_ad(mutex_own(buf_page_get_mutex(bpage)));
-+ ut_ad(mutex_own(buf_page_get_mutex(bpage)));
- //ut_ad(bpage->in_LRU_list);
-
- if (UNIV_LIKELY(bpage->in_LRU_list && buf_page_in_file(bpage))) {
-@@ -470,14 +470,14 @@
- enum buf_flush flush_type)/*!< in: BUF_FLUSH_LRU or BUF_FLUSH_LIST */
- {
- #ifdef UNIV_DEBUG
-- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- #endif
-- ut_a(buf_page_in_file(bpage));
-+ //ut_a(buf_page_in_file(bpage));
- ut_ad(mutex_own(buf_page_get_mutex(bpage)));
- ut_ad(flush_type == BUF_FLUSH_LRU || BUF_FLUSH_LIST);
-
-- if (bpage->oldest_modification != 0
-+ if (buf_page_in_file(bpage) && bpage->oldest_modification != 0
- && buf_page_get_io_fix(bpage) == BUF_IO_NONE) {
- ut_ad(bpage->in_flush_list);
-
-@@ -508,7 +508,7 @@
- {
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- ut_ad(mutex_own(buf_page_get_mutex(bpage)));
- ut_ad(bpage->in_flush_list);
-
-@@ -526,13 +526,13 @@
- return;
- case BUF_BLOCK_ZIP_DIRTY:
- buf_page_set_state(bpage, BUF_BLOCK_ZIP_PAGE);
-- UT_LIST_REMOVE(list, buf_pool->flush_list, bpage);
-+ UT_LIST_REMOVE(flush_list, buf_pool->flush_list, bpage);
- #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
- buf_LRU_insert_zip_clean(bpage);
- #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
- break;
- case BUF_BLOCK_FILE_PAGE:
-- UT_LIST_REMOVE(list, buf_pool->flush_list, bpage);
-+ UT_LIST_REMOVE(flush_list, buf_pool->flush_list, bpage);
- break;
- }
-
-@@ -576,7 +576,7 @@
- buf_page_t* prev_b = NULL;
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- /* Must reside in the same buffer pool. */
- ut_ad(buf_pool == buf_pool_from_bpage(dpage));
-
-@@ -605,18 +605,18 @@
- because we assert on in_flush_list in comparison function. */
- ut_d(bpage->in_flush_list = FALSE);
-
-- prev = UT_LIST_GET_PREV(list, bpage);
-- UT_LIST_REMOVE(list, buf_pool->flush_list, bpage);
-+ prev = UT_LIST_GET_PREV(flush_list, bpage);
-+ UT_LIST_REMOVE(flush_list, buf_pool->flush_list, bpage);
-
- if (prev) {
- ut_ad(prev->in_flush_list);
- UT_LIST_INSERT_AFTER(
-- list,
-+ flush_list,
- buf_pool->flush_list,
- prev, dpage);
- } else {
- UT_LIST_ADD_FIRST(
-- list,
-+ flush_list,
- buf_pool->flush_list,
- dpage);
- }
-@@ -1085,7 +1085,7 @@
-
- #ifdef UNIV_DEBUG
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-- ut_ad(!buf_pool_mutex_own(buf_pool));
-+ //ut_ad(!buf_pool_mutex_own(buf_pool));
- #endif
-
- #ifdef UNIV_LOG_DEBUG
-@@ -1099,7 +1099,8 @@
- io_fixed and oldest_modification != 0. Thus, it cannot be
- relocated in the buffer pool or removed from flush_list or
- LRU_list. */
-- ut_ad(!buf_pool_mutex_own(buf_pool));
-+ //ut_ad(!buf_pool_mutex_own(buf_pool));
-+ ut_ad(!mutex_own(&buf_pool->LRU_list_mutex));
- ut_ad(!buf_flush_list_mutex_own(buf_pool));
- ut_ad(!mutex_own(buf_page_get_mutex(bpage)));
- ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_WRITE);
-@@ -1179,7 +1180,7 @@
- buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */
- buf_block_t* block) /*!< in/out: buffer control block */
- {
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
- ut_ad(mutex_own(&block->mutex));
-
-@@ -1187,8 +1188,11 @@
- return(FALSE);
- }
-
-+ buf_pool_mutex_enter(buf_pool);
-+
- if (buf_pool->n_flush[BUF_FLUSH_LRU] > 0
- || buf_pool->init_flush[BUF_FLUSH_LRU]) {
-+ buf_pool_mutex_exit(buf_pool);
- /* There is already a flush batch of the same type running */
- return(FALSE);
- }
-@@ -1262,12 +1266,18 @@
- ibool is_uncompressed;
-
- ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+#ifdef UNIV_SYNC_DEBUG
-+ ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_SHARED));
-+#endif
- ut_ad(buf_page_in_file(bpage));
-
- block_mutex = buf_page_get_mutex(bpage);
- ut_ad(mutex_own(block_mutex));
-
-+ buf_pool_mutex_enter(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
-+
- ut_ad(buf_flush_ready_for_flush(bpage, flush_type));
-
- buf_page_set_io_fix(bpage, BUF_IO_WRITE);
-@@ -1455,14 +1465,16 @@
-
- buf_pool = buf_pool_get(space, i);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ rw_lock_s_lock(&buf_pool->page_hash_latch);
-
- /* We only want to flush pages from this buffer pool. */
- bpage = buf_page_hash_get(buf_pool, space, i);
-
- if (!bpage) {
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
- if (srv_flush_neighbor_pages == 2) {
-
- /* This is contiguous neighbor page flush and
-@@ -1480,11 +1492,9 @@
- if (flush_type != BUF_FLUSH_LRU
- || i == offset
- || buf_page_is_old(bpage)) {
-- mutex_t* block_mutex = buf_page_get_mutex(bpage);
-+ mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
-
-- mutex_enter(block_mutex);
--
-- if (buf_flush_ready_for_flush(bpage, flush_type)
-+ if (block_mutex && buf_flush_ready_for_flush(bpage, flush_type)
- && (i == offset || !bpage->buf_fix_count)) {
- /* We only try to flush those
- neighbors != offset where the buf fix
-@@ -1500,11 +1510,12 @@
- ut_ad(!buf_pool_mutex_own(buf_pool));
- count++;
- continue;
-- } else {
-+ } else if (block_mutex) {
- mutex_exit(block_mutex);
- }
- }
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
-
- if (srv_flush_neighbor_pages == 2) {
-
-@@ -1553,21 +1564,25 @@
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
- #endif /* UNIV_DEBUG */
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(flush_type != BUF_FLUSH_LRU
-+ || mutex_own(&buf_pool->LRU_list_mutex));
-
-- block_mutex = buf_page_get_mutex(bpage);
-- mutex_enter(block_mutex);
-+ block_mutex = buf_page_get_mutex_enter(bpage);
-
-- ut_a(buf_page_in_file(bpage));
-+ //ut_a(buf_page_in_file(bpage));
-
-- if (buf_flush_ready_for_flush(bpage, flush_type)) {
-+ if (block_mutex && buf_flush_ready_for_flush(bpage, flush_type)) {
- ulint space;
- ulint offset;
- buf_pool_t* buf_pool;
-
- buf_pool = buf_pool_from_bpage(bpage);
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ if (flush_type == BUF_FLUSH_LRU) {
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ }
-
- /* These fields are protected by both the
- buffer pool mutex and block mutex. */
-@@ -1583,13 +1598,18 @@
- *count,
- n_to_flush);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ if (flush_type == BUF_FLUSH_LRU) {
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ }
- flushed = TRUE;
-- } else {
-+ } else if (block_mutex) {
- mutex_exit(block_mutex);
- }
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(flush_type != BUF_FLUSH_LRU
-+ || mutex_own(&buf_pool->LRU_list_mutex));
-
- return(flushed);
- }
-@@ -1610,7 +1630,8 @@
- buf_page_t* bpage;
- ulint count = 0;
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
-
- do {
- /* Start from the end of the list looking for a
-@@ -1632,7 +1653,8 @@
- should be flushed, we factor in this value. */
- buf_lru_flush_page_count += count;
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
-
- return(count);
- }
-@@ -1660,9 +1682,10 @@
- {
- ulint len;
- buf_page_t* bpage;
-+ buf_page_t* prev_bpage = NULL;
- ulint count = 0;
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-
- /* If we have flushed enough, leave the loop */
- do {
-@@ -1681,6 +1704,7 @@
-
- if (bpage) {
- ut_a(bpage->oldest_modification > 0);
-+ prev_bpage = UT_LIST_GET_PREV(flush_list, bpage);
- }
-
- if (!bpage || bpage->oldest_modification >= lsn_limit) {
-@@ -1722,9 +1746,17 @@
- break;
- }
-
-- bpage = UT_LIST_GET_PREV(list, bpage);
-+ bpage = UT_LIST_GET_PREV(flush_list, bpage);
-
-- ut_ad(!bpage || bpage->in_flush_list);
-+ //ut_ad(!bpage || bpage->in_flush_list);
-+ if (bpage != prev_bpage) {
-+ /* the search might warp.. retrying */
-+ buf_flush_list_mutex_exit(buf_pool);
-+ break;
-+ }
-+ if (bpage) {
-+ prev_bpage = UT_LIST_GET_PREV(flush_list, bpage);
-+ }
-
- buf_flush_list_mutex_exit(buf_pool);
-
-@@ -1733,7 +1765,7 @@
-
- } while (count < min_n && bpage != NULL && len > 0);
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-
- return(count);
- }
-@@ -1772,13 +1804,15 @@
- || sync_thread_levels_empty_except_dict());
- #endif /* UNIV_SYNC_DEBUG */
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-
- /* Note: The buffer pool mutex is released and reacquired within
- the flush functions. */
- switch(flush_type) {
- case BUF_FLUSH_LRU:
-+ mutex_enter(&buf_pool->LRU_list_mutex);
- count = buf_flush_LRU_list_batch(buf_pool, min_n);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- break;
- case BUF_FLUSH_LIST:
- count = buf_flush_flush_list_batch(buf_pool, min_n, lsn_limit);
-@@ -1787,7 +1821,7 @@
- ut_error;
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-
- buf_flush_buffered_writes();
-
-@@ -2059,7 +2093,7 @@
- retry:
- //buf_pool_mutex_enter(buf_pool);
- if (have_LRU_mutex)
-- buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-
- n_replaceable = UT_LIST_GET_LEN(buf_pool->free);
-
-@@ -2076,15 +2110,15 @@
- bpage = UT_LIST_GET_LAST(buf_pool->LRU);
- continue;
- }
-- block_mutex = buf_page_get_mutex(bpage);
--
-- mutex_enter(block_mutex);
-+ block_mutex = buf_page_get_mutex_enter(bpage);
-
-- if (buf_flush_ready_for_replace(bpage)) {
-+ if (block_mutex && buf_flush_ready_for_replace(bpage)) {
- n_replaceable++;
- }
-
-- mutex_exit(block_mutex);
-+ if (block_mutex) {
-+ mutex_exit(block_mutex);
-+ }
-
- distance++;
-
-@@ -2093,7 +2127,7 @@
-
- //buf_pool_mutex_exit(buf_pool);
- if (have_LRU_mutex)
-- buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-
- if (n_replaceable >= BUF_FLUSH_FREE_BLOCK_MARGIN(buf_pool)) {
-
-@@ -2292,7 +2326,7 @@
-
- ut_ad(buf_flush_list_mutex_own(buf_pool));
-
-- UT_LIST_VALIDATE(list, buf_page_t, buf_pool->flush_list,
-+ UT_LIST_VALIDATE(flush_list, buf_page_t, buf_pool->flush_list,
- ut_ad(ut_list_node_313->in_flush_list));
-
- bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
-@@ -2332,7 +2366,7 @@
- rnode = rbt_next(buf_pool->flush_rbt, rnode);
- }
-
-- bpage = UT_LIST_GET_NEXT(list, bpage);
-+ bpage = UT_LIST_GET_NEXT(flush_list, bpage);
-
- ut_a(!bpage || om >= bpage->oldest_modification);
- }
---- a/storage/innobase/buf/buf0lru.c
-+++ b/storage/innobase/buf/buf0lru.c
-@@ -147,8 +147,9 @@
- void
- buf_LRU_block_free_hashed_page(
- /*===========================*/
-- buf_block_t* block); /*!< in: block, must contain a file page and
-+ buf_block_t* block, /*!< in: block, must contain a file page and
- be in a state where it can be freed */
-+ ibool have_page_hash_mutex);
-
- /******************************************************************//**
- Determines if the unzip_LRU list should be used for evicting a victim
-@@ -158,15 +159,20 @@
- ibool
- buf_LRU_evict_from_unzip_LRU(
- /*=========================*/
-- buf_pool_t* buf_pool)
-+ buf_pool_t* buf_pool,
-+ ibool have_LRU_mutex)
- {
- ulint io_avg;
- ulint unzip_avg;
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-
-+ if (!have_LRU_mutex)
-+ mutex_enter(&buf_pool->LRU_list_mutex);
- /* If the unzip_LRU list is empty, we can only use the LRU. */
- if (UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0) {
-+ if (!have_LRU_mutex)
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- return(FALSE);
- }
-
-@@ -175,14 +181,20 @@
- decompressed pages in the buffer pool. */
- if (UT_LIST_GET_LEN(buf_pool->unzip_LRU)
- <= UT_LIST_GET_LEN(buf_pool->LRU) / 10) {
-+ if (!have_LRU_mutex)
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- return(FALSE);
- }
-
- /* If eviction hasn't started yet, we assume by default
- that a workload is disk bound. */
- if (buf_pool->freed_page_clock == 0) {
-+ if (!have_LRU_mutex)
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- return(TRUE);
- }
-+ if (!have_LRU_mutex)
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-
- /* Calculate the average over past intervals, and add the values
- of the current interval. */
-@@ -250,18 +262,25 @@
- page_arr = ut_malloc(
- sizeof(ulint) * BUF_LRU_DROP_SEARCH_SIZE);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
- num_entries = 0;
-
- scan_again:
- bpage = UT_LIST_GET_LAST(buf_pool->LRU);
-
- while (bpage != NULL) {
-+ /* bpage->state,space,io_fix,buf_fix_count are protected by block_mutex at XtraDB */
-+ mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
- buf_page_t* prev_bpage;
- ibool is_fixed;
-
- prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
-
-+ if (UNIV_UNLIKELY(!block_mutex)) {
-+ goto next_page;
-+ }
-+
- ut_a(buf_page_in_file(bpage));
-
- if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE
-@@ -270,24 +289,30 @@
- /* Compressed pages are never hashed.
- Skip blocks of other tablespaces.
- Skip I/O-fixed blocks (to be dealt with later). */
-+ mutex_exit(block_mutex);
- next_page:
- bpage = prev_bpage;
- continue;
- }
-
-- mutex_enter(&((buf_block_t*) bpage)->mutex);
-+ //mutex_enter(&((buf_block_t*) bpage)->mutex);
- is_fixed = bpage->buf_fix_count > 0
- || !((buf_block_t*) bpage)->index;
-- mutex_exit(&((buf_block_t*) bpage)->mutex);
-+ //mutex_exit(&((buf_block_t*) bpage)->mutex);
-
- if (is_fixed) {
-+ mutex_exit(block_mutex);
- goto next_page;
- }
-
- /* Store the page number so that we can drop the hash
- index in a batch later. */
- page_arr[num_entries] = bpage->offset;
-+
-+ mutex_exit(block_mutex);
-+
- ut_a(num_entries < BUF_LRU_DROP_SEARCH_SIZE);
-+
- ++num_entries;
-
- if (num_entries < BUF_LRU_DROP_SEARCH_SIZE) {
-@@ -296,14 +321,16 @@
-
- /* Array full. We release the buf_pool->mutex to obey
- the latching order. */
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-
- buf_LRU_drop_page_hash_batch(
- id, zip_size, page_arr, num_entries);
-
- num_entries = 0;
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-
- /* Note that we released the buf_pool mutex above
- after reading the prev_bpage during processing of a
-@@ -321,13 +348,23 @@
- /* If, however, bpage has been removed from LRU list
- to the free list then we should restart the scan.
- bpage->state is protected by buf_pool mutex. */
-+
-+ /* obtain block_mutex again to avoid race condition of bpage->state */
-+ block_mutex = buf_page_get_mutex_enter(bpage);
-+ if (!block_mutex) {
-+ goto scan_again;
-+ }
-+
- if (bpage
- && buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
-+ mutex_exit(block_mutex);
- goto scan_again;
- }
-+ mutex_exit(block_mutex);
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-
- /* Drop any remaining batch of search hashed pages. */
- buf_LRU_drop_page_hash_batch(id, zip_size, page_arr, num_entries);
-@@ -351,7 +388,9 @@
- ulint i;
-
- scan_again:
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
- buf_flush_list_mutex_enter(buf_pool);
-
- all_freed = TRUE;
-@@ -364,7 +403,7 @@
-
- ut_a(buf_page_in_file(bpage));
-
-- prev_bpage = UT_LIST_GET_PREV(list, bpage);
-+ prev_bpage = UT_LIST_GET_PREV(flush_list, bpage);
-
- /* bpage->space and bpage->io_fix are protected by
- buf_pool->mutex and block_mutex. It is safe to check
-@@ -388,8 +427,14 @@
- will stay in the flush_list because buf_flush_remove()
- needs buf_pool->mutex as well. */
- buf_flush_list_mutex_exit(buf_pool);
-- block_mutex = buf_page_get_mutex(bpage);
-- mutex_enter(block_mutex);
-+ block_mutex = buf_page_get_mutex_enter(bpage);
-+
-+ if (!block_mutex) {
-+ /* It may be impossible case...
-+ Something wrong, so will be scan_again */
-+ all_freed = FALSE;
-+ goto next_page;
-+ }
-
- if (bpage->buf_fix_count > 0) {
- mutex_exit(block_mutex);
-@@ -440,9 +485,15 @@
- mutex_exit(block_mutex);
-
- /* Now it is safe to release the buf_pool->mutex. */
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+
- os_thread_yield();
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
-+
-
- mutex_enter(block_mutex);
- buf_page_unset_sticky(bpage);
-@@ -454,7 +505,9 @@
- i = 0;
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+// buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
- buf_flush_list_mutex_exit(buf_pool);
-
- ut_ad(buf_flush_validate(buf_pool));
-@@ -504,7 +557,9 @@
- buf_page_t* b;
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
-+ ut_ad(mutex_own(&buf_pool->zip_mutex));
- ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE);
-
- /* Find the first successor of bpage in the LRU list
-@@ -512,17 +567,17 @@
- b = bpage;
- do {
- b = UT_LIST_GET_NEXT(LRU, b);
-- } while (b && buf_page_get_state(b) != BUF_BLOCK_ZIP_PAGE);
-+ } while (b && (buf_page_get_state(b) != BUF_BLOCK_ZIP_PAGE || !b->in_LRU_list));
-
- /* Insert bpage before b, i.e., after the predecessor of b. */
- if (b) {
-- b = UT_LIST_GET_PREV(list, b);
-+ b = UT_LIST_GET_PREV(zip_list, b);
- }
-
- if (b) {
-- UT_LIST_INSERT_AFTER(list, buf_pool->zip_clean, b, bpage);
-+ UT_LIST_INSERT_AFTER(zip_list, buf_pool->zip_clean, b, bpage);
- } else {
-- UT_LIST_ADD_FIRST(list, buf_pool->zip_clean, bpage);
-+ UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_clean, bpage);
- }
- }
- #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
-@@ -536,18 +591,19 @@
- buf_LRU_free_from_unzip_LRU_list(
- /*=============================*/
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
-- ulint n_iterations) /*!< in: how many times this has
-+ ulint n_iterations, /*!< in: how many times this has
- been called repeatedly without
- result: a high value means that
- we should search farther; we will
- search n_iterations / 5 of the
- unzip_LRU list, or nothing if
- n_iterations >= 5 */
-+ ibool have_LRU_mutex)
- {
- buf_block_t* block;
- ulint distance;
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-
- /* Theoratically it should be much easier to find a victim
- from unzip_LRU as we can choose even a dirty block (as we'll
-@@ -557,7 +613,7 @@
- if we have done five iterations so far. */
-
- if (UNIV_UNLIKELY(n_iterations >= 5)
-- || !buf_LRU_evict_from_unzip_LRU(buf_pool)) {
-+ || !buf_LRU_evict_from_unzip_LRU(buf_pool, have_LRU_mutex)) {
-
- return(FALSE);
- }
-@@ -565,18 +621,25 @@
- distance = 100 + (n_iterations
- * UT_LIST_GET_LEN(buf_pool->unzip_LRU)) / 5;
-
-+restart:
- for (block = UT_LIST_GET_LAST(buf_pool->unzip_LRU);
- UNIV_LIKELY(block != NULL) && UNIV_LIKELY(distance > 0);
- block = UT_LIST_GET_PREV(unzip_LRU, block), distance--) {
-
- ibool freed;
-
-+ mutex_enter(&block->mutex);
-+ if (!block->in_unzip_LRU_list || !block->page.in_LRU_list
-+ || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
-+ mutex_exit(&block->mutex);
-+ goto restart;
-+ }
-+
- ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
- ut_ad(block->in_unzip_LRU_list);
- ut_ad(block->page.in_LRU_list);
-
-- mutex_enter(&block->mutex);
-- freed = buf_LRU_free_block(&block->page, FALSE);
-+ freed = buf_LRU_free_block(&block->page, FALSE, have_LRU_mutex);
- mutex_exit(&block->mutex);
-
- if (freed) {
-@@ -595,35 +658,46 @@
- buf_LRU_free_from_common_LRU_list(
- /*==============================*/
- buf_pool_t* buf_pool,
-- ulint n_iterations)
-+ ulint n_iterations,
- /*!< in: how many times this has been called
- repeatedly without result: a high value means
- that we should search farther; if
- n_iterations < 10, then we search
- n_iterations / 10 * buf_pool->curr_size
- pages from the end of the LRU list */
-+ ibool have_LRU_mutex)
- {
- buf_page_t* bpage;
- ulint distance;
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-
- distance = 100 + (n_iterations * buf_pool->curr_size) / 10;
-
-+restart:
- for (bpage = UT_LIST_GET_LAST(buf_pool->LRU);
- UNIV_LIKELY(bpage != NULL) && UNIV_LIKELY(distance > 0);
- bpage = UT_LIST_GET_PREV(LRU, bpage), distance--) {
-
- ibool freed;
- unsigned accessed;
-- mutex_t* block_mutex = buf_page_get_mutex(bpage);
-+ mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
-+
-+ if (!block_mutex) {
-+ goto restart;
-+ }
-+
-+ if (!bpage->in_LRU_list
-+ || !buf_page_in_file(bpage)) {
-+ mutex_exit(block_mutex);
-+ goto restart;
-+ }
-
- ut_ad(buf_page_in_file(bpage));
- ut_ad(bpage->in_LRU_list);
-
-- mutex_enter(block_mutex);
- accessed = buf_page_is_accessed(bpage);
-- freed = buf_LRU_free_block(bpage, TRUE);
-+ freed = buf_LRU_free_block(bpage, TRUE, have_LRU_mutex);
- mutex_exit(block_mutex);
-
- if (freed) {
-@@ -660,16 +734,23 @@
- n_iterations / 5 of the unzip_LRU list. */
- {
- ibool freed = FALSE;
-+ ibool have_LRU_mutex = FALSE;
-
-- buf_pool_mutex_enter(buf_pool);
-+ if (UT_LIST_GET_LEN(buf_pool->unzip_LRU))
-+ have_LRU_mutex = TRUE;
-+
-+ //buf_pool_mutex_enter(buf_pool);
-+ if (have_LRU_mutex)
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-
-- freed = buf_LRU_free_from_unzip_LRU_list(buf_pool, n_iterations);
-+ freed = buf_LRU_free_from_unzip_LRU_list(buf_pool, n_iterations, have_LRU_mutex);
-
- if (!freed) {
- freed = buf_LRU_free_from_common_LRU_list(
-- buf_pool, n_iterations);
-+ buf_pool, n_iterations, have_LRU_mutex);
- }
-
-+ buf_pool_mutex_enter(buf_pool);
- if (!freed) {
- buf_pool->LRU_flush_ended = 0;
- } else if (buf_pool->LRU_flush_ended > 0) {
-@@ -677,6 +758,8 @@
- }
-
- buf_pool_mutex_exit(buf_pool);
-+ if (have_LRU_mutex)
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-
- return(freed);
- }
-@@ -737,7 +820,9 @@
-
- buf_pool = buf_pool_from_array(i);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ mutex_enter(&buf_pool->free_list_mutex);
-
- if (!recv_recovery_on
- && UT_LIST_GET_LEN(buf_pool->free)
-@@ -747,7 +832,9 @@
- ret = TRUE;
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ mutex_exit(&buf_pool->free_list_mutex);
- }
-
- return(ret);
-@@ -765,9 +852,10 @@
- {
- buf_block_t* block;
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-
-- block = (buf_block_t*) UT_LIST_GET_FIRST(buf_pool->free);
-+ mutex_enter(&buf_pool->free_list_mutex);
-+ block = (buf_block_t*) UT_LIST_GET_LAST(buf_pool->free);
-
- if (block) {
-
-@@ -776,7 +864,9 @@
- ut_ad(!block->page.in_flush_list);
- ut_ad(!block->page.in_LRU_list);
- ut_a(!buf_page_in_file(&block->page));
-- UT_LIST_REMOVE(list, buf_pool->free, (&block->page));
-+ UT_LIST_REMOVE(free, buf_pool->free, (&block->page));
-+
-+ mutex_exit(&buf_pool->free_list_mutex);
-
- mutex_enter(&block->mutex);
-
-@@ -786,6 +876,8 @@
- ut_ad(buf_pool_from_block(block) == buf_pool);
-
- mutex_exit(&block->mutex);
-+ } else {
-+ mutex_exit(&buf_pool->free_list_mutex);
- }
-
- return(block);
-@@ -808,7 +900,7 @@
- ibool mon_value_was = FALSE;
- ibool started_monitor = FALSE;
- loop:
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-
- if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
- + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->curr_size / 20) {
-@@ -876,7 +968,7 @@
-
- /* If there is a block in the free list, take it */
- block = buf_LRU_get_free_only(buf_pool);
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-
- if (block) {
- ut_ad(buf_pool_from_block(block) == buf_pool);
-@@ -976,7 +1068,8 @@
- ulint new_len;
-
- ut_a(buf_pool->LRU_old);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
- ut_ad(buf_pool->LRU_old_ratio >= BUF_LRU_OLD_RATIO_MIN);
- ut_ad(buf_pool->LRU_old_ratio <= BUF_LRU_OLD_RATIO_MAX);
- #if BUF_LRU_OLD_RATIO_MIN * BUF_LRU_OLD_MIN_LEN <= BUF_LRU_OLD_RATIO_DIV * (BUF_LRU_OLD_TOLERANCE + 5)
-@@ -1042,7 +1135,8 @@
- {
- buf_page_t* bpage;
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
- ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN);
-
- /* We first initialize all blocks in the LRU list as old and then use
-@@ -1077,13 +1171,14 @@
- ut_ad(buf_pool);
- ut_ad(bpage);
- ut_ad(buf_page_in_file(bpage));
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
-
- if (buf_page_belongs_to_unzip_LRU(bpage)) {
- buf_block_t* block = (buf_block_t*) bpage;
-
- ut_ad(block->in_unzip_LRU_list);
-- ut_d(block->in_unzip_LRU_list = FALSE);
-+ block->in_unzip_LRU_list = FALSE;
-
- UT_LIST_REMOVE(unzip_LRU, buf_pool->unzip_LRU, block);
- }
-@@ -1101,7 +1196,8 @@
-
- ut_ad(buf_pool);
- ut_ad(bpage);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
-
- ut_a(buf_page_in_file(bpage));
-
-@@ -1178,12 +1274,13 @@
-
- ut_ad(buf_pool);
- ut_ad(block);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
-
- ut_a(buf_page_belongs_to_unzip_LRU(&block->page));
-
- ut_ad(!block->in_unzip_LRU_list);
-- ut_d(block->in_unzip_LRU_list = TRUE);
-+ block->in_unzip_LRU_list = TRUE;
-
- if (old) {
- UT_LIST_ADD_LAST(unzip_LRU, buf_pool->unzip_LRU, block);
-@@ -1204,7 +1301,8 @@
-
- ut_ad(buf_pool);
- ut_ad(bpage);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
-
- ut_a(buf_page_in_file(bpage));
-
-@@ -1255,7 +1353,8 @@
-
- ut_ad(buf_pool);
- ut_ad(bpage);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
-
- ut_a(buf_page_in_file(bpage));
- ut_ad(!bpage->in_LRU_list);
-@@ -1334,7 +1433,8 @@
- {
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
-
- if (bpage->old) {
- buf_pool->stat.n_pages_made_young++;
-@@ -1373,17 +1473,18 @@
- buf_LRU_free_block(
- /*===============*/
- buf_page_t* bpage, /*!< in: block to be freed */
-- ibool zip) /*!< in: TRUE if should remove also the
-+ ibool zip, /*!< in: TRUE if should remove also the
- compressed page of an uncompressed page */
-+ ibool have_LRU_mutex)
- {
- buf_page_t* b = NULL;
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
- mutex_t* block_mutex = buf_page_get_mutex(bpage);
-
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- ut_ad(mutex_own(block_mutex));
- ut_ad(buf_page_in_file(bpage));
-- ut_ad(bpage->in_LRU_list);
-+ //ut_ad(bpage->in_LRU_list);
- ut_ad(!bpage->in_flush_list == !bpage->oldest_modification);
- #if UNIV_WORD_SIZE == 4
- /* On 32-bit systems, there is no padding in buf_page_t. On
-@@ -1392,7 +1493,7 @@
- UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
- #endif
-
-- if (!buf_page_can_relocate(bpage)) {
-+ if (!bpage->in_LRU_list || !block_mutex || !buf_page_can_relocate(bpage)) {
-
- /* Do not free buffer-fixed or I/O-fixed blocks. */
- return(FALSE);
-@@ -1426,7 +1527,7 @@
- alloc:
- b = buf_page_alloc_descriptor();
- ut_a(b);
-- memcpy(b, bpage, sizeof *b);
-+ //memcpy(b, bpage, sizeof *b);
- }
-
- #ifdef UNIV_DEBUG
-@@ -1437,6 +1538,39 @@
- }
- #endif /* UNIV_DEBUG */
-
-+ /* not to break latch order, must re-enter block_mutex */
-+ mutex_exit(block_mutex);
-+
-+ if (!have_LRU_mutex)
-+ mutex_enter(&buf_pool->LRU_list_mutex); /* optimistic */
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
-+ mutex_enter(block_mutex);
-+
-+ /* recheck states of block */
-+ if (!bpage->in_LRU_list || block_mutex != buf_page_get_mutex(bpage)
-+ || !buf_page_can_relocate(bpage)) {
-+not_freed:
-+ if (b) {
-+ buf_buddy_free(buf_pool, b, sizeof *b, TRUE);
-+ }
-+ if (!have_LRU_mutex)
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ return(FALSE);
-+ } else if (zip || !bpage->zip.data) {
-+ if (bpage->oldest_modification)
-+ goto not_freed;
-+ } else if (bpage->oldest_modification) {
-+ if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
-+ ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_DIRTY);
-+ goto not_freed;
-+ }
-+ }
-+
-+ if (b) {
-+ memcpy(b, bpage, sizeof *b);
-+ }
-+
- if (buf_LRU_block_remove_hashed_page(bpage, zip)
- != BUF_BLOCK_ZIP_FREE) {
- ut_a(bpage->buf_fix_count == 0);
-@@ -1453,6 +1587,10 @@
-
- ut_a(!hash_b);
-
-+ while (prev_b && !prev_b->in_LRU_list) {
-+ prev_b = UT_LIST_GET_PREV(LRU, prev_b);
-+ }
-+
- b->state = b->oldest_modification
- ? BUF_BLOCK_ZIP_DIRTY
- : BUF_BLOCK_ZIP_PAGE;
-@@ -1528,6 +1666,7 @@
- buf_LRU_add_block_low(b, buf_page_is_old(b));
- }
-
-+ mutex_enter(&buf_pool->zip_mutex);
- if (b->state == BUF_BLOCK_ZIP_PAGE) {
- #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
- buf_LRU_insert_zip_clean(b);
-@@ -1543,12 +1682,13 @@
- /* Prevent buf_page_get_gen() from
- decompressing the block while we release
- buf_pool->mutex and block_mutex. */
-- mutex_enter(&buf_pool->zip_mutex);
- buf_page_set_sticky(b);
- mutex_exit(&buf_pool->zip_mutex);
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
- mutex_exit(block_mutex);
-
- /* Remove possible adaptive hash index on the page.
-@@ -1580,7 +1720,9 @@
- : BUF_NO_CHECKSUM_MAGIC);
- }
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ if (have_LRU_mutex)
-+ mutex_enter(&buf_pool->LRU_list_mutex);
- mutex_enter(block_mutex);
-
- if (b) {
-@@ -1589,13 +1731,17 @@
- mutex_exit(&buf_pool->zip_mutex);
- }
-
-- buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
-+ buf_LRU_block_free_hashed_page((buf_block_t*) bpage, FALSE);
- } else {
- /* The block_mutex should have been released by
- buf_LRU_block_remove_hashed_page() when it returns
- BUF_BLOCK_ZIP_FREE. */
- ut_ad(block_mutex == &buf_pool->zip_mutex);
- mutex_enter(block_mutex);
-+
-+ if (!have_LRU_mutex)
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
- }
-
- return(TRUE);
-@@ -1607,13 +1753,14 @@
- void
- buf_LRU_block_free_non_file_page(
- /*=============================*/
-- buf_block_t* block) /*!< in: block, must not contain a file page */
-+ buf_block_t* block, /*!< in: block, must not contain a file page */
-+ ibool have_page_hash_mutex)
- {
- void* data;
- buf_pool_t* buf_pool = buf_pool_from_block(block);
-
- ut_ad(block);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- ut_ad(mutex_own(&block->mutex));
-
- switch (buf_block_get_state(block)) {
-@@ -1647,18 +1794,21 @@
- if (data) {
- block->page.zip.data = NULL;
- mutex_exit(&block->mutex);
-- buf_pool_mutex_exit_forbid(buf_pool);
-+ //buf_pool_mutex_exit_forbid(buf_pool);
-
- buf_buddy_free(
-- buf_pool, data, page_zip_get_size(&block->page.zip));
-+ buf_pool, data, page_zip_get_size(&block->page.zip),
-+ have_page_hash_mutex);
-
-- buf_pool_mutex_exit_allow(buf_pool);
-+ //buf_pool_mutex_exit_allow(buf_pool);
- mutex_enter(&block->mutex);
- page_zip_set_size(&block->page.zip, 0);
- }
-
-- UT_LIST_ADD_FIRST(list, buf_pool->free, (&block->page));
-+ mutex_enter(&buf_pool->free_list_mutex);
-+ UT_LIST_ADD_FIRST(free, buf_pool->free, (&block->page));
- ut_d(block->page.in_free_list = TRUE);
-+ mutex_exit(&buf_pool->free_list_mutex);
-
- UNIV_MEM_ASSERT_AND_FREE(block->frame, UNIV_PAGE_SIZE);
- }
-@@ -1688,7 +1838,11 @@
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-
- ut_ad(bpage);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
-+#ifdef UNIV_SYNC_DEBUG
-+ ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX));
-+#endif
- ut_ad(mutex_own(buf_page_get_mutex(bpage)));
-
- ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
-@@ -1796,7 +1950,9 @@
-
- #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
- mutex_exit(buf_page_get_mutex(bpage));
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
- buf_print();
- buf_LRU_print();
- buf_validate();
-@@ -1818,17 +1974,17 @@
- ut_a(buf_page_get_zip_size(bpage));
-
- #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
-- UT_LIST_REMOVE(list, buf_pool->zip_clean, bpage);
-+ UT_LIST_REMOVE(zip_list, buf_pool->zip_clean, bpage);
- #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
-
- mutex_exit(&buf_pool->zip_mutex);
-- buf_pool_mutex_exit_forbid(buf_pool);
-+ //buf_pool_mutex_exit_forbid(buf_pool);
-
- buf_buddy_free(
- buf_pool, bpage->zip.data,
-- page_zip_get_size(&bpage->zip));
-+ page_zip_get_size(&bpage->zip), TRUE);
-
-- buf_pool_mutex_exit_allow(buf_pool);
-+ //buf_pool_mutex_exit_allow(buf_pool);
- buf_page_free_descriptor(bpage);
- return(BUF_BLOCK_ZIP_FREE);
-
-@@ -1850,13 +2006,13 @@
- ut_ad(!bpage->in_flush_list);
- ut_ad(!bpage->in_LRU_list);
- mutex_exit(&((buf_block_t*) bpage)->mutex);
-- buf_pool_mutex_exit_forbid(buf_pool);
-+ //buf_pool_mutex_exit_forbid(buf_pool);
-
- buf_buddy_free(
- buf_pool, data,
-- page_zip_get_size(&bpage->zip));
-+ page_zip_get_size(&bpage->zip), TRUE);
-
-- buf_pool_mutex_exit_allow(buf_pool);
-+ //buf_pool_mutex_exit_allow(buf_pool);
- mutex_enter(&((buf_block_t*) bpage)->mutex);
- page_zip_set_size(&bpage->zip, 0);
- }
-@@ -1882,18 +2038,19 @@
- void
- buf_LRU_block_free_hashed_page(
- /*===========================*/
-- buf_block_t* block) /*!< in: block, must contain a file page and
-+ buf_block_t* block, /*!< in: block, must contain a file page and
- be in a state where it can be freed */
-+ ibool have_page_hash_mutex)
- {
- #ifdef UNIV_DEBUG
-- buf_pool_t* buf_pool = buf_pool_from_block(block);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //buf_pool_t* buf_pool = buf_pool_from_block(block);
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- #endif
- ut_ad(mutex_own(&block->mutex));
-
- buf_block_set_state(block, BUF_BLOCK_MEMORY);
-
-- buf_LRU_block_free_non_file_page(block);
-+ buf_LRU_block_free_non_file_page(block, have_page_hash_mutex);
- }
-
- /******************************************************************//**
-@@ -1908,7 +2065,7 @@
- {
- if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
- != BUF_BLOCK_ZIP_FREE) {
-- buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
-+ buf_LRU_block_free_hashed_page((buf_block_t*) bpage, TRUE);
- }
- }
-
-@@ -1936,7 +2093,8 @@
- }
-
- if (adjust) {
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-
- if (ratio != buf_pool->LRU_old_ratio) {
- buf_pool->LRU_old_ratio = ratio;
-@@ -1948,7 +2106,8 @@
- }
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- } else {
- buf_pool->LRU_old_ratio = ratio;
- }
-@@ -2053,7 +2212,8 @@
- ulint new_len;
-
- ut_ad(buf_pool);
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-
- if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {
-
-@@ -2114,16 +2274,22 @@
-
- ut_a(buf_pool->LRU_old_len == old_len);
-
-- UT_LIST_VALIDATE(list, buf_page_t, buf_pool->free,
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ mutex_enter(&buf_pool->free_list_mutex);
-+
-+ UT_LIST_VALIDATE(free, buf_page_t, buf_pool->free,
- ut_ad(ut_list_node_313->in_free_list));
-
- for (bpage = UT_LIST_GET_FIRST(buf_pool->free);
- bpage != NULL;
-- bpage = UT_LIST_GET_NEXT(list, bpage)) {
-+ bpage = UT_LIST_GET_NEXT(free, bpage)) {
-
- ut_a(buf_page_get_state(bpage) == BUF_BLOCK_NOT_USED);
- }
-
-+ mutex_exit(&buf_pool->free_list_mutex);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+
- UT_LIST_VALIDATE(unzip_LRU, buf_block_t, buf_pool->unzip_LRU,
- ut_ad(ut_list_node_313->in_unzip_LRU_list
- && ut_list_node_313->page.in_LRU_list));
-@@ -2137,7 +2303,8 @@
- ut_a(buf_page_belongs_to_unzip_LRU(&block->page));
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- }
-
- /**********************************************************************//**
-@@ -2173,7 +2340,8 @@
- const buf_page_t* bpage;
-
- ut_ad(buf_pool);
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-
- bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
-
-@@ -2230,7 +2398,8 @@
- bpage = UT_LIST_GET_NEXT(LRU, bpage);
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->LRU_list_mutex);
- }
-
- /**********************************************************************//**
---- a/storage/innobase/buf/buf0rea.c
-+++ b/storage/innobase/buf/buf0rea.c
-@@ -478,6 +478,7 @@
-
- return(0);
- }
-+ buf_pool_mutex_exit(buf_pool);
-
- /* Check that almost all pages in the area have been accessed; if
- offset == low, the accesses must be in a descending order, otherwise,
-@@ -496,6 +497,7 @@
-
- fail_count = 0;
-
-+ rw_lock_s_lock(&buf_pool->page_hash_latch);
- for (i = low; i < high; i++) {
- bpage = buf_page_hash_get(buf_pool, space, i);
-
-@@ -523,7 +525,8 @@
-
- if (fail_count > threshold) {
- /* Too many failures: return */
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
- return(0);
- }
-
-@@ -538,7 +541,8 @@
- bpage = buf_page_hash_get(buf_pool, space, offset);
-
- if (bpage == NULL) {
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
-
- return(0);
- }
-@@ -564,7 +568,8 @@
- pred_offset = fil_page_get_prev(frame);
- succ_offset = fil_page_get_next(frame);
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
-
- if ((offset == low) && (succ_offset == offset + 1)) {
-
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -265,6 +265,10 @@
- # endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
- {&buf_pool_mutex_key, "buf_pool_mutex", 0},
- {&buf_pool_zip_mutex_key, "buf_pool_zip_mutex", 0},
-+ {&buf_pool_LRU_list_mutex_key, "buf_pool_LRU_list_mutex", 0},
-+ {&buf_pool_free_list_mutex_key, "buf_pool_free_list_mutex", 0},
-+ {&buf_pool_zip_free_mutex_key, "buf_pool_zip_free_mutex", 0},
-+ {&buf_pool_zip_hash_mutex_key, "buf_pool_zip_hash_mutex", 0},
- {&cache_last_read_mutex_key, "cache_last_read_mutex", 0},
- {&dict_foreign_err_mutex_key, "dict_foreign_err_mutex", 0},
- {&dict_sys_mutex_key, "dict_sys_mutex", 0},
-@@ -314,6 +318,7 @@
- {&archive_lock_key, "archive_lock", 0},
- # endif /* UNIV_LOG_ARCHIVE */
- {&btr_search_latch_key, "btr_search_latch", 0},
-+ {&buf_pool_page_hash_key, "buf_pool_page_hash_latch", 0},
- # ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK
- {&buf_block_lock_key, "buf_block_lock", 0},
- # endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
---- a/storage/innobase/handler/i_s.cc
-+++ b/storage/innobase/handler/i_s.cc
-@@ -1583,7 +1583,8 @@
-
- buf_pool = buf_pool_from_array(i);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ mutex_enter(&buf_pool->zip_free_mutex);
-
- for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) {
- buf_buddy_stat_t* buddy_stat;
-@@ -1613,7 +1614,8 @@
- }
- }
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ mutex_exit(&buf_pool->zip_free_mutex);
-
- if (status) {
- break;
---- a/storage/innobase/ibuf/ibuf0ibuf.c
-+++ b/storage/innobase/ibuf/ibuf0ibuf.c
-@@ -3760,9 +3760,11 @@
- ulint fold = buf_page_address_fold(space, page_no);
- buf_pool_t* buf_pool = buf_pool_get(space, page_no);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ rw_lock_s_lock(&buf_pool->page_hash_latch);
- bpage = buf_page_hash_get_low(buf_pool, space, page_no, fold);
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
-
- if (UNIV_LIKELY_NULL(bpage)) {
- /* A buffer pool watch has been set or the
---- a/storage/innobase/include/buf0buddy.h
-+++ b/storage/innobase/include/buf0buddy.h
-@@ -49,11 +49,12 @@
- ulint size, /*!< in: compressed page size
- (between PAGE_ZIP_MIN_SIZE and
- UNIV_PAGE_SIZE) */
-- ibool* lru) /*!< in: pointer to a variable
-+ ibool* lru, /*!< in: pointer to a variable
- that will be assigned TRUE if
- storage was allocated from the
- LRU list and buf_pool->mutex was
- temporarily released */
-+ ibool have_page_hash_mutex)
- __attribute__((malloc, nonnull));
-
- /**********************************************************************//**
-@@ -66,8 +67,9 @@
- the block resides */
- void* buf, /*!< in: block to be freed, must not
- be pointed to by the buffer pool */
-- ulint size) /*!< in: block size,
-+ ulint size, /*!< in: block size,
- up to UNIV_PAGE_SIZE */
-+ ibool have_page_hash_mutex)
- __attribute__((nonnull));
-
- #ifndef UNIV_NONINL
---- a/storage/innobase/include/buf0buddy.ic
-+++ b/storage/innobase/include/buf0buddy.ic
-@@ -45,11 +45,12 @@
- buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */
- ulint i, /*!< in: index of buf_pool->zip_free[],
- or BUF_BUDDY_SIZES */
-- ibool* lru) /*!< in: pointer to a variable that
-+ ibool* lru, /*!< in: pointer to a variable that
- will be assigned TRUE if storage was
- allocated from the LRU list and
- buf_pool->mutex was temporarily
- released */
-+ ibool have_page_hash_mutex)
- __attribute__((malloc, nonnull));
-
- /**********************************************************************//**
-@@ -61,8 +62,9 @@
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
- void* buf, /*!< in: block to be freed, must not be
- pointed to by the buffer pool */
-- ulint i) /*!< in: index of buf_pool->zip_free[],
-+ ulint i, /*!< in: index of buf_pool->zip_free[],
- or BUF_BUDDY_SIZES */
-+ ibool have_page_hash_mutex)
- __attribute__((nonnull));
-
- /**********************************************************************//**
-@@ -101,19 +103,20 @@
- ulint size, /*!< in: compressed page size
- (between PAGE_ZIP_MIN_SIZE and
- UNIV_PAGE_SIZE) */
-- ibool* lru) /*!< in: pointer to a variable
-+ ibool* lru, /*!< in: pointer to a variable
- that will be assigned TRUE if
- storage was allocated from the
- LRU list and buf_pool->mutex was
- temporarily released */
-+ ibool have_page_hash_mutex)
- {
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- ut_ad(ut_is_2pow(size));
- ut_ad(size >= PAGE_ZIP_MIN_SIZE);
- ut_ad(size <= UNIV_PAGE_SIZE);
-
- return((byte*) buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size),
-- lru));
-+ lru, have_page_hash_mutex));
- }
-
- /**********************************************************************//**
-@@ -126,15 +129,28 @@
- the block resides */
- void* buf, /*!< in: block to be freed, must not
- be pointed to by the buffer pool */
-- ulint size) /*!< in: block size,
-+ ulint size, /*!< in: block size,
- up to UNIV_PAGE_SIZE */
-+ ibool have_page_hash_mutex)
- {
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- ut_ad(ut_is_2pow(size));
- ut_ad(size >= PAGE_ZIP_MIN_SIZE);
- ut_ad(size <= UNIV_PAGE_SIZE);
-
-- buf_buddy_free_low(buf_pool, buf, buf_buddy_get_slot(size));
-+ if (!have_page_hash_mutex) {
-+ mutex_enter(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
-+ }
-+
-+ mutex_enter(&buf_pool->zip_free_mutex);
-+ buf_buddy_free_low(buf_pool, buf, buf_buddy_get_slot(size), TRUE);
-+ mutex_exit(&buf_pool->zip_free_mutex);
-+
-+ if (!have_page_hash_mutex) {
-+ mutex_exit(&buf_pool->LRU_list_mutex);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ }
- }
-
- #ifdef UNIV_MATERIALIZE
---- a/storage/innobase/include/buf0buf.h
-+++ b/storage/innobase/include/buf0buf.h
-@@ -212,6 +212,20 @@
- /*==========================*/
-
- /********************************************************************//**
-+*/
-+UNIV_INLINE
-+void
-+buf_pool_page_hash_x_lock_all(void);
-+/*================================*/
-+
-+/********************************************************************//**
-+*/
-+UNIV_INLINE
-+void
-+buf_pool_page_hash_x_unlock_all(void);
-+/*==================================*/
-+
-+/********************************************************************//**
- Creates the buffer pool.
- @return own: buf_pool object, NULL if not enough memory or error */
- UNIV_INTERN
-@@ -851,6 +865,15 @@
- const buf_page_t* bpage) /*!< in: pointer to control block */
- __attribute__((pure));
-
-+/*************************************************************************
-+Gets the mutex of a block and enter the mutex with consistency. */
-+UNIV_INLINE
-+mutex_t*
-+buf_page_get_mutex_enter(
-+/*=========================*/
-+ const buf_page_t* bpage) /*!< in: pointer to control block */
-+ __attribute__((pure));
-+
- /*********************************************************************//**
- Get the flush type of a page.
- @return flush type */
-@@ -1352,7 +1375,7 @@
- All these are protected by buf_pool->mutex. */
- /* @{ */
-
-- UT_LIST_NODE_T(buf_page_t) list;
-+ /* UT_LIST_NODE_T(buf_page_t) list; */
- /*!< based on state, this is a
- list node, protected either by
- buf_pool->mutex or by
-@@ -1380,6 +1403,10 @@
- BUF_BLOCK_REMOVE_HASH or
- BUF_BLOCK_READY_IN_USE. */
-
-+ /* resplit for optimistic use */
-+ UT_LIST_NODE_T(buf_page_t) free;
-+ UT_LIST_NODE_T(buf_page_t) flush_list;
-+ UT_LIST_NODE_T(buf_page_t) zip_list; /* zip_clean or zip_free[] */
- #ifdef UNIV_DEBUG
- ibool in_flush_list; /*!< TRUE if in buf_pool->flush_list;
- when buf_pool->flush_list_mutex is
-@@ -1472,11 +1499,11 @@
- a block is in the unzip_LRU list
- if page.state == BUF_BLOCK_FILE_PAGE
- and page.zip.data != NULL */
--#ifdef UNIV_DEBUG
-+//#ifdef UNIV_DEBUG
- ibool in_unzip_LRU_list;/*!< TRUE if the page is in the
- decompressed LRU list;
- used in debugging */
--#endif /* UNIV_DEBUG */
-+//#endif /* UNIV_DEBUG */
- mutex_t mutex; /*!< mutex protecting this block:
- state (also protected by the buffer
- pool mutex), io_fix, buf_fix_count,
-@@ -1656,6 +1683,11 @@
- pool instance, protects compressed
- only pages (of type buf_page_t, not
- buf_block_t */
-+ mutex_t LRU_list_mutex;
-+ rw_lock_t page_hash_latch;
-+ mutex_t free_list_mutex;
-+ mutex_t zip_free_mutex;
-+ mutex_t zip_hash_mutex;
- ulint instance_no; /*!< Array index of this buffer
- pool instance */
- ulint old_pool_size; /*!< Old pool size in bytes */
-@@ -1809,8 +1841,8 @@
- /** Test if a buffer pool mutex is owned. */
- #define buf_pool_mutex_own(b) mutex_own(&b->mutex)
- /** Acquire a buffer pool mutex. */
-+/* the buf_pool_mutex is changed the latch order */
- #define buf_pool_mutex_enter(b) do { \
-- ut_ad(!mutex_own(&b->zip_mutex)); \
- mutex_enter(&b->mutex); \
- } while (0)
-
---- a/storage/innobase/include/buf0buf.ic
-+++ b/storage/innobase/include/buf0buf.ic
-@@ -292,7 +292,7 @@
- case BUF_BLOCK_ZIP_FREE:
- /* This is a free page in buf_pool->zip_free[].
- Such pages should only be accessed by the buddy allocator. */
-- ut_error;
-+ /* ut_error; */ /* optimistic */
- break;
- case BUF_BLOCK_ZIP_PAGE:
- case BUF_BLOCK_ZIP_DIRTY:
-@@ -335,9 +335,16 @@
- {
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-
-+ if (/*equivalent to buf_pool_watch_is_sentinel(buf_pool, bpage)*/
-+ bpage >= &buf_pool->watch[0]
-+ && bpage < &buf_pool->watch[BUF_POOL_WATCH_SIZE]) {
-+ /* TODO: this code is the interim. should be confirmed later. */
-+ return(&buf_pool->zip_mutex);
-+ }
-+
- switch (buf_page_get_state(bpage)) {
- case BUF_BLOCK_ZIP_FREE:
-- ut_error;
-+ /* ut_error; */ /* optimistic */
- return(NULL);
- case BUF_BLOCK_ZIP_PAGE:
- case BUF_BLOCK_ZIP_DIRTY:
-@@ -347,6 +354,28 @@
- }
- }
-
-+/*************************************************************************
-+Gets the mutex of a block and enter the mutex with consistency. */
-+UNIV_INLINE
-+mutex_t*
-+buf_page_get_mutex_enter(
-+/*=========================*/
-+ const buf_page_t* bpage) /*!< in: pointer to control block */
-+{
-+ mutex_t* block_mutex;
-+
-+ while(1) {
-+ block_mutex = buf_page_get_mutex(bpage);
-+ if (!block_mutex)
-+ return block_mutex;
-+
-+ mutex_enter(block_mutex);
-+ if (block_mutex == buf_page_get_mutex(bpage))
-+ return block_mutex;
-+ mutex_exit(block_mutex);
-+ }
-+}
-+
- /*********************************************************************//**
- Get the flush type of a page.
- @return flush type */
-@@ -444,8 +473,8 @@
- enum buf_io_fix io_fix) /*!< in: io_fix state */
- {
- #ifdef UNIV_DEBUG
-- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- #endif
- ut_ad(mutex_own(buf_page_get_mutex(bpage)));
-
-@@ -482,7 +511,7 @@
- {
- #ifdef UNIV_DEBUG
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
- #endif
- ut_ad(mutex_own(buf_page_get_mutex(bpage)));
- ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
-@@ -500,7 +529,7 @@
- {
- #ifdef UNIV_DEBUG
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
- #endif
- ut_ad(mutex_own(buf_page_get_mutex(bpage)));
- ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_PIN);
-@@ -518,14 +547,14 @@
- const buf_page_t* bpage) /*!< control block being relocated */
- {
- #ifdef UNIV_DEBUG
-- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- #endif
- ut_ad(mutex_own(buf_page_get_mutex(bpage)));
- ut_ad(buf_page_in_file(bpage));
-- ut_ad(bpage->in_LRU_list);
-+ //ut_ad(bpage->in_LRU_list);
-
-- return(buf_page_get_io_fix(bpage) == BUF_IO_NONE
-+ return(bpage->in_LRU_list && bpage->io_fix == BUF_IO_NONE
- && bpage->buf_fix_count == 0);
- }
-
-@@ -539,8 +568,8 @@
- const buf_page_t* bpage) /*!< in: control block */
- {
- #ifdef UNIV_DEBUG
-- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- #endif
- ut_ad(buf_page_in_file(bpage));
-
-@@ -560,7 +589,8 @@
- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
- #endif /* UNIV_DEBUG */
- ut_a(buf_page_in_file(bpage));
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
- ut_ad(bpage->in_LRU_list);
-
- #ifdef UNIV_LRU_DEBUG
-@@ -607,9 +637,10 @@
- ulint time_ms) /*!< in: ut_time_ms() */
- {
- #ifdef UNIV_DEBUG
-- buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
- #endif
-+ ut_ad(mutex_own(buf_page_get_mutex(bpage)));
- ut_a(buf_page_in_file(bpage));
-
- if (!bpage->access_time) {
-@@ -852,19 +883,19 @@
- /*===========*/
- buf_block_t* block) /*!< in, own: block to be freed */
- {
-- buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*)block);
-+ //buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*)block);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-
- mutex_enter(&block->mutex);
-
- ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
-
-- buf_LRU_block_free_non_file_page(block);
-+ buf_LRU_block_free_non_file_page(block, FALSE);
-
- mutex_exit(&block->mutex);
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
- }
- #endif /* !UNIV_HOTBACKUP */
-
-@@ -912,17 +943,17 @@
- page frame */
- {
- ib_uint64_t lsn;
-- mutex_t* block_mutex = buf_page_get_mutex(bpage);
--
-- mutex_enter(block_mutex);
-+ mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
-
-- if (buf_page_in_file(bpage)) {
-+ if (block_mutex && buf_page_in_file(bpage)) {
- lsn = bpage->newest_modification;
- } else {
- lsn = 0;
- }
-
-- mutex_exit(block_mutex);
-+ if (block_mutex) {
-+ mutex_exit(block_mutex);
-+ }
-
- return(lsn);
- }
-@@ -940,7 +971,7 @@
- #ifdef UNIV_SYNC_DEBUG
- buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*)block);
-
-- ut_ad((buf_pool_mutex_own(buf_pool)
-+ ut_ad((mutex_own(&buf_pool->LRU_list_mutex)
- && (block->page.buf_fix_count == 0))
- || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
- #endif /* UNIV_SYNC_DEBUG */
-@@ -1070,7 +1101,11 @@
- buf_page_t* bpage;
-
- ut_ad(buf_pool);
-- ut_ad(buf_pool_mutex_own(buf_pool));
-+ //ut_ad(buf_pool_mutex_own(buf_pool));
-+#ifdef UNIV_SYNC_DEBUG
-+ ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX)
-+ || rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_SHARED));
-+#endif
- ut_ad(fold == buf_page_address_fold(space, offset));
-
- /* Look for the page in the hash table */
-@@ -1155,11 +1190,13 @@
- const buf_page_t* bpage;
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
-
-- buf_pool_mutex_enter(buf_pool);
-+ //buf_pool_mutex_enter(buf_pool);
-+ rw_lock_s_lock(&buf_pool->page_hash_latch);
-
- bpage = buf_page_hash_get(buf_pool, space, offset);
-
-- buf_pool_mutex_exit(buf_pool);
-+ //buf_pool_mutex_exit(buf_pool);
-+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
-
- return(bpage != NULL);
- }
-@@ -1287,4 +1324,38 @@
- buf_pool_mutex_exit(buf_pool);
- }
- }
-+
-+/********************************************************************//**
-+*/
-+UNIV_INLINE
-+void
-+buf_pool_page_hash_x_lock_all(void)
-+/*===============================*/
-+{
-+ ulint i;
-+
-+ for (i = 0; i < srv_buf_pool_instances; i++) {
-+ buf_pool_t* buf_pool;
-+
-+ buf_pool = buf_pool_from_array(i);
-+ rw_lock_x_lock(&buf_pool->page_hash_latch);
-+ }
-+}
-+
-+/********************************************************************//**
-+*/
-+UNIV_INLINE
-+void
-+buf_pool_page_hash_x_unlock_all(void)
-+/*=================================*/
-+{
-+ ulint i;
-+
-+ for (i = 0; i < srv_buf_pool_instances; i++) {
-+ buf_pool_t* buf_pool;
-+
-+ buf_pool = buf_pool_from_array(i);
-+ rw_lock_x_unlock(&buf_pool->page_hash_latch);
-+ }
-+}
- #endif /* !UNIV_HOTBACKUP */
---- a/storage/innobase/include/buf0lru.h
-+++ b/storage/innobase/include/buf0lru.h
-@@ -100,8 +100,9 @@
- buf_LRU_free_block(
- /*===============*/
- buf_page_t* bpage, /*!< in: block to be freed */
-- ibool zip) /*!< in: TRUE if should remove also the
-+ ibool zip, /*!< in: TRUE if should remove also the
- compressed page of an uncompressed page */
-+ ibool have_LRU_mutex)
- __attribute__((nonnull));
- /******************************************************************//**
- Try to free a replaceable block.
-@@ -148,7 +149,8 @@
- void
- buf_LRU_block_free_non_file_page(
- /*=============================*/
-- buf_block_t* block); /*!< in: block, must not contain a file page */
-+ buf_block_t* block, /*!< in: block, must not contain a file page */
-+ ibool have_page_hash_mutex);
- /******************************************************************//**
- Adds a block to the LRU list. */
- UNIV_INTERN
---- a/storage/innobase/include/sync0rw.h
-+++ b/storage/innobase/include/sync0rw.h
-@@ -112,6 +112,7 @@
- extern mysql_pfs_key_t archive_lock_key;
- # endif /* UNIV_LOG_ARCHIVE */
- extern mysql_pfs_key_t btr_search_latch_key;
-+extern mysql_pfs_key_t buf_pool_page_hash_key;
- extern mysql_pfs_key_t buf_block_lock_key;
- # ifdef UNIV_SYNC_DEBUG
- extern mysql_pfs_key_t buf_block_debug_latch_key;
---- a/storage/innobase/include/sync0sync.h
-+++ b/storage/innobase/include/sync0sync.h
-@@ -75,6 +75,10 @@
- extern mysql_pfs_key_t buffer_block_mutex_key;
- extern mysql_pfs_key_t buf_pool_mutex_key;
- extern mysql_pfs_key_t buf_pool_zip_mutex_key;
-+extern mysql_pfs_key_t buf_pool_LRU_list_mutex_key;
-+extern mysql_pfs_key_t buf_pool_free_list_mutex_key;
-+extern mysql_pfs_key_t buf_pool_zip_free_mutex_key;
-+extern mysql_pfs_key_t buf_pool_zip_hash_mutex_key;
- extern mysql_pfs_key_t cache_last_read_mutex_key;
- extern mysql_pfs_key_t dict_foreign_err_mutex_key;
- extern mysql_pfs_key_t dict_sys_mutex_key;
-@@ -667,7 +671,7 @@
- #define SYNC_TRX_SYS_HEADER 290
- #define SYNC_PURGE_QUEUE 200
- #define SYNC_LOG 170
--#define SYNC_LOG_FLUSH_ORDER 147
-+#define SYNC_LOG_FLUSH_ORDER 156
- #define SYNC_RECV 168
- #define SYNC_WORK_QUEUE 162
- #define SYNC_SEARCH_SYS 160 /* NOTE that if we have a memory
-@@ -676,8 +680,13 @@
- SYNC_SEARCH_SYS, as memory allocation
- can call routines there! Otherwise
- the level is SYNC_MEM_HASH. */
-+#define SYNC_BUF_LRU_LIST 158
-+#define SYNC_BUF_PAGE_HASH 157
-+#define SYNC_BUF_BLOCK 155 /* Block mutex */
-+#define SYNC_BUF_FREE_LIST 153
-+#define SYNC_BUF_ZIP_FREE 152
-+#define SYNC_BUF_ZIP_HASH 151
- #define SYNC_BUF_POOL 150 /* Buffer pool mutex */
--#define SYNC_BUF_BLOCK 146 /* Block mutex */
- #define SYNC_BUF_FLUSH_LIST 145 /* Buffer flush list mutex */
- #define SYNC_DOUBLEWRITE 140
- #define SYNC_ANY_LATCH 135
-@@ -708,7 +717,7 @@
- os_fast_mutex; /*!< We use this OS mutex in place of lock_word
- when atomic operations are not enabled */
- #endif
-- ulint waiters; /*!< This ulint is set to 1 if there are (or
-+ volatile ulint waiters; /*!< This ulint is set to 1 if there are (or
- may be) threads waiting in the global wait
- array for this mutex to be released.
- Otherwise, this is 0. */
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -3105,7 +3105,7 @@
- level += log_sys->max_checkpoint_age
- - (lsn - oldest_modification);
- }
-- bpage = UT_LIST_GET_NEXT(list, bpage);
-+ bpage = UT_LIST_GET_NEXT(flush_list, bpage);
- n_blocks++;
- }
-
-@@ -3191,7 +3191,7 @@
- found = TRUE;
- break;
- }
-- bpage = UT_LIST_GET_NEXT(list, bpage);
-+ bpage = UT_LIST_GET_NEXT(flush_list, bpage);
- new_blocks_num++;
- }
- if (!found) {
---- a/storage/innobase/sync/sync0sync.c
-+++ b/storage/innobase/sync/sync0sync.c
-@@ -285,7 +285,7 @@
- mutex->lock_word = 0;
- #endif
- mutex->event = os_event_create(NULL);
-- mutex_set_waiters(mutex, 0);
-+ mutex->waiters = 0;
- #ifdef UNIV_DEBUG
- mutex->magic_n = MUTEX_MAGIC_N;
- #endif /* UNIV_DEBUG */
-@@ -464,6 +464,15 @@
- mutex_t* mutex, /*!< in: mutex */
- ulint n) /*!< in: value to set */
- {
-+#ifdef INNODB_RW_LOCKS_USE_ATOMICS
-+ ut_ad(mutex);
-+
-+ if (n) {
-+ os_compare_and_swap_ulint(&mutex->waiters, 0, 1);
-+ } else {
-+ os_compare_and_swap_ulint(&mutex->waiters, 1, 0);
-+ }
-+#else
- volatile ulint* ptr; /* declared volatile to ensure that
- the value is stored to memory */
- ut_ad(mutex);
-@@ -472,6 +481,7 @@
-
- *ptr = n; /* Here we assume that the write of a single
- word in memory is atomic */
-+#endif
- }
-
- /******************************************************************//**
-@@ -1233,7 +1243,12 @@
- ut_error;
- }
- break;
-+ case SYNC_BUF_LRU_LIST:
- case SYNC_BUF_FLUSH_LIST:
-+ case SYNC_BUF_PAGE_HASH:
-+ case SYNC_BUF_FREE_LIST:
-+ case SYNC_BUF_ZIP_FREE:
-+ case SYNC_BUF_ZIP_HASH:
- case SYNC_BUF_POOL:
- /* We can have multiple mutexes of this type therefore we
- can only check whether the greater than condition holds. */
-@@ -1251,7 +1266,8 @@
- buffer block (block->mutex or buf_pool->zip_mutex). */
- if (!sync_thread_levels_g(array, level, FALSE)) {
- ut_a(sync_thread_levels_g(array, level - 1, TRUE));
-- ut_a(sync_thread_levels_contain(array, SYNC_BUF_POOL));
-+ /* the exact rule is not fixed yet, for now */
-+ //ut_a(sync_thread_levels_contain(array, SYNC_BUF_LRU_LIST));
- }
- break;
- case SYNC_REC_LOCK:
+++ /dev/null
-# name : innodb_stats.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/dict/dict0boot.c
-+++ b/storage/innobase/dict/dict0boot.c
-@@ -266,6 +266,29 @@
- /* Get the dictionary header */
- dict_hdr = dict_hdr_get(&mtr);
-
-+ if (mach_read_from_8(dict_hdr + DICT_HDR_XTRADB_MARK)
-+ != DICT_HDR_XTRADB_FLAG) {
-+ /* not extended yet by XtraDB, need to be extended */
-+ ulint root_page_no;
-+
-+ root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
-+ DICT_HDR_SPACE, 0, DICT_STATS_ID,
-+ dict_ind_redundant, &mtr);
-+ if (root_page_no == FIL_NULL) {
-+ fprintf(stderr, "InnoDB: Warning: failed to create SYS_STATS btr.\n");
-+ srv_use_sys_stats_table = FALSE;
-+ } else {
-+ mlog_write_ulint(dict_hdr + DICT_HDR_STATS, root_page_no,
-+ MLOG_4BYTES, &mtr);
-+ mlog_write_ull(dict_hdr + DICT_HDR_XTRADB_MARK,
-+ DICT_HDR_XTRADB_FLAG, &mtr);
-+ }
-+ mtr_commit(&mtr);
-+ /* restart mtr */
-+ mtr_start(&mtr);
-+ dict_hdr = dict_hdr_get(&mtr);
-+ }
-+
- /* Because we only write new row ids to disk-based data structure
- (dictionary header) when it is divisible by
- DICT_HDR_ROW_ID_WRITE_MARGIN, in recovery we will not recover
-@@ -425,7 +448,7 @@
- table->id = DICT_FIELDS_ID;
- dict_table_add_to_cache(table, heap);
- dict_sys->sys_fields = table;
-- mem_heap_free(heap);
-+ mem_heap_empty(heap);
-
- index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND",
- DICT_HDR_SPACE,
-@@ -442,6 +465,45 @@
- FALSE);
- ut_a(error == DB_SUCCESS);
-
-+ /*-------------------------*/
-+ table = dict_mem_table_create("SYS_STATS", DICT_HDR_SPACE, 4, 0);
-+ table->n_mysql_handles_opened = 1; /* for pin */
-+
-+ dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
-+ dict_mem_table_add_col(table, heap, "KEY_COLS", DATA_INT, 0, 4);
-+ dict_mem_table_add_col(table, heap, "DIFF_VALS", DATA_BINARY, 0, 0);
-+ dict_mem_table_add_col(table, heap, "NON_NULL_VALS", DATA_BINARY, 0, 0);
-+
-+ /* The '+ 2' below comes from the fields DB_TRX_ID, DB_ROLL_PTR */
-+#if DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2
-+#error "DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2"
-+#endif
-+#if DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2
-+#error "DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2"
-+#endif
-+
-+ table->id = DICT_STATS_ID;
-+ dict_table_add_to_cache(table, heap);
-+ dict_sys->sys_stats = table;
-+ mem_heap_empty(heap);
-+
-+ index = dict_mem_index_create("SYS_STATS", "CLUST_IND",
-+ DICT_HDR_SPACE,
-+ DICT_UNIQUE | DICT_CLUSTERED, 2);
-+
-+ dict_mem_index_add_field(index, "INDEX_ID", 0);
-+ dict_mem_index_add_field(index, "KEY_COLS", 0);
-+
-+ index->id = DICT_STATS_ID;
-+ error = dict_index_add_to_cache(table, index,
-+ mtr_read_ulint(dict_hdr
-+ + DICT_HDR_STATS,
-+ MLOG_4BYTES, &mtr),
-+ FALSE);
-+ ut_a(error == DB_SUCCESS);
-+
-+ mem_heap_free(heap);
-+
- mtr_commit(&mtr);
- /*-------------------------*/
-
-@@ -455,6 +517,7 @@
- dict_load_sys_table(dict_sys->sys_columns);
- dict_load_sys_table(dict_sys->sys_indexes);
- dict_load_sys_table(dict_sys->sys_fields);
-+ dict_load_sys_table(dict_sys->sys_stats);
-
- mutex_exit(&(dict_sys->mutex));
- }
---- a/storage/innobase/dict/dict0crea.c
-+++ b/storage/innobase/dict/dict0crea.c
-@@ -508,6 +508,56 @@
- }
-
- /*****************************************************************//**
-+Based on an index object, this function builds the entry to be inserted
-+in the SYS_STATS system table.
-+@return the tuple which should be inserted */
-+static
-+dtuple_t*
-+dict_create_sys_stats_tuple(
-+/*========================*/
-+ const dict_index_t* index,
-+ ulint i,
-+ mem_heap_t* heap)
-+{
-+ dict_table_t* sys_stats;
-+ dtuple_t* entry;
-+ dfield_t* dfield;
-+ byte* ptr;
-+
-+ ut_ad(index);
-+ ut_ad(heap);
-+
-+ sys_stats = dict_sys->sys_stats;
-+
-+ entry = dtuple_create(heap, 4 + DATA_N_SYS_COLS);
-+
-+ dict_table_copy_types(entry, sys_stats);
-+
-+ /* 0: INDEX_ID -----------------------*/
-+ dfield = dtuple_get_nth_field(entry, 0/*INDEX_ID*/);
-+ ptr = mem_heap_alloc(heap, 8);
-+ mach_write_to_8(ptr, index->id);
-+ dfield_set_data(dfield, ptr, 8);
-+ /* 1: KEY_COLS -----------------------*/
-+ dfield = dtuple_get_nth_field(entry, 1/*KEY_COLS*/);
-+ ptr = mem_heap_alloc(heap, 4);
-+ mach_write_to_4(ptr, i);
-+ dfield_set_data(dfield, ptr, 4);
-+ /* 4: DIFF_VALS ----------------------*/
-+ dfield = dtuple_get_nth_field(entry, 2/*DIFF_VALS*/);
-+ ptr = mem_heap_alloc(heap, 8);
-+ mach_write_to_8(ptr, 0); /* initial value is 0 */
-+ dfield_set_data(dfield, ptr, 8);
-+ /* 5: NON_NULL_VALS ------------------*/
-+ dfield = dtuple_get_nth_field(entry, 3/*NON_NULL_VALS*/);
-+ ptr = mem_heap_alloc(heap, 8);
-+ mach_write_to_8(ptr, 0); /* initial value is 0 */
-+ dfield_set_data(dfield, ptr, 8);
-+
-+ return(entry);
-+}
-+
-+/*****************************************************************//**
- Creates the tuple with which the index entry is searched for writing the index
- tree root page number, if such a tree is created.
- @return the tuple for search */
-@@ -617,6 +667,27 @@
- }
-
- /***************************************************************//**
-+Builds a row for storing stats to insert.
-+@return DB_SUCCESS */
-+static
-+ulint
-+dict_build_stats_def_step(
-+/*======================*/
-+ ind_node_t* node)
-+{
-+ dict_index_t* index;
-+ dtuple_t* row;
-+
-+ index = node->index;
-+
-+ row = dict_create_sys_stats_tuple(index, node->stats_no, node->heap);
-+
-+ ins_node_set_new_row(node->stats_def, row);
-+
-+ return(DB_SUCCESS);
-+}
-+
-+/***************************************************************//**
- Creates an index tree for the index if it is not a member of a cluster.
- @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
- static
-@@ -936,6 +1007,49 @@
- dict_sys->sys_fields, heap);
- node->field_def->common.parent = node;
-
-+ if (srv_use_sys_stats_table) {
-+ node->stats_def = ins_node_create(INS_DIRECT,
-+ dict_sys->sys_stats, heap);
-+ node->stats_def->common.parent = node;
-+ } else {
-+ node->stats_def = NULL;
-+ }
-+
-+ node->commit_node = commit_node_create(heap);
-+ node->commit_node->common.parent = node;
-+
-+ return(node);
-+}
-+
-+/*********************************************************************//**
-+*/
-+UNIV_INTERN
-+ind_node_t*
-+ind_insert_stats_graph_create(
-+/*==========================*/
-+ dict_index_t* index,
-+ mem_heap_t* heap)
-+{
-+ ind_node_t* node;
-+
-+ node = mem_heap_alloc(heap, sizeof(ind_node_t));
-+
-+ node->common.type = QUE_NODE_INSERT_STATS;
-+
-+ node->index = index;
-+
-+ node->state = INDEX_BUILD_STATS_COLS;
-+ node->page_no = FIL_NULL;
-+ node->heap = mem_heap_create(256);
-+
-+ node->ind_def = NULL;
-+ node->field_def = NULL;
-+
-+ node->stats_def = ins_node_create(INS_DIRECT,
-+ dict_sys->sys_stats, heap);
-+ node->stats_def->common.parent = node;
-+ node->stats_no = 0;
-+
- node->commit_node = commit_node_create(heap);
- node->commit_node->common.parent = node;
-
-@@ -1086,6 +1200,7 @@
-
- node->state = INDEX_BUILD_FIELD_DEF;
- node->field_no = 0;
-+ node->stats_no = 0;
-
- thr->run_node = node->ind_def;
-
-@@ -1131,7 +1246,31 @@
- goto function_exit;
- }
-
-- node->state = INDEX_CREATE_INDEX_TREE;
-+ if (srv_use_sys_stats_table
-+ && !((node->table->flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY)) {
-+ node->state = INDEX_BUILD_STATS_COLS;
-+ } else {
-+ node->state = INDEX_CREATE_INDEX_TREE;
-+ }
-+ }
-+ if (node->state == INDEX_BUILD_STATS_COLS) {
-+ if (node->stats_no <= dict_index_get_n_unique(node->index)) {
-+
-+ err = dict_build_stats_def_step(node);
-+
-+ if (err != DB_SUCCESS) {
-+
-+ goto function_exit;
-+ }
-+
-+ node->stats_no++;
-+
-+ thr->run_node = node->stats_def;
-+
-+ return(thr);
-+ } else {
-+ node->state = INDEX_CREATE_INDEX_TREE;
-+ }
- }
-
- if (node->state == INDEX_CREATE_INDEX_TREE) {
-@@ -1177,6 +1316,66 @@
- return(NULL);
- }
-
-+ thr->run_node = que_node_get_parent(node);
-+
-+ return(thr);
-+}
-+
-+/****************************************************************//**
-+*/
-+UNIV_INTERN
-+que_thr_t*
-+dict_insert_stats_step(
-+/*===================*/
-+ que_thr_t* thr) /*!< in: query thread */
-+{
-+ ind_node_t* node;
-+ ulint err = DB_ERROR;
-+ trx_t* trx;
-+
-+ ut_ad(thr);
-+
-+ trx = thr_get_trx(thr);
-+
-+ node = thr->run_node;
-+
-+ if (thr->prev_node == que_node_get_parent(node)) {
-+ node->state = INDEX_BUILD_STATS_COLS;
-+ }
-+
-+ if (node->state == INDEX_BUILD_STATS_COLS) {
-+ if (node->stats_no <= dict_index_get_n_unique(node->index)) {
-+
-+ err = dict_build_stats_def_step(node);
-+
-+ if (err != DB_SUCCESS) {
-+
-+ goto function_exit;
-+ }
-+
-+ node->stats_no++;
-+
-+ thr->run_node = node->stats_def;
-+
-+ return(thr);
-+ } else {
-+ node->state = INDEX_COMMIT_WORK;
-+ }
-+ }
-+
-+ if (node->state == INDEX_COMMIT_WORK) {
-+
-+ /* do not commit transaction here for now */
-+ }
-+
-+function_exit:
-+ trx->error_state = err;
-+
-+ if (err == DB_SUCCESS) {
-+ } else {
-+ return(NULL);
-+ }
-+
- thr->run_node = que_node_get_parent(node);
-
- return(thr);
---- a/storage/innobase/dict/dict0dict.c
-+++ b/storage/innobase/dict/dict0dict.c
-@@ -755,7 +755,7 @@
- print an error message and return without doing
- anything. */
- dict_update_statistics(table, TRUE /* only update stats
-- if they have not been initialized */);
-+ if they have not been initialized */, FALSE);
- }
-
- return(table);
-@@ -4354,6 +4354,295 @@
- }
-
- /*********************************************************************//**
-+functions to use SYS_STATS system table. */
-+static
-+ibool
-+dict_reload_statistics(
-+/*===================*/
-+ dict_table_t* table,
-+ ulint* sum_of_index_sizes)
-+{
-+ dict_index_t* index;
-+ ulint size;
-+ mem_heap_t* heap;
-+
-+ index = dict_table_get_first_index(table);
-+
-+ if (index == NULL) {
-+ /* Table definition is corrupt */
-+
-+ return(FALSE);
-+ }
-+
-+ heap = mem_heap_create(1000);
-+
-+ while (index) {
-+ size = btr_get_size(index, BTR_TOTAL_SIZE);
-+
-+ index->stat_index_size = size;
-+
-+ *sum_of_index_sizes += size;
-+
-+ size = btr_get_size(index, BTR_N_LEAF_PAGES);
-+
-+ if (size == 0) {
-+ /* The root node of the tree is a leaf */
-+ size = 1;
-+ }
-+
-+ index->stat_n_leaf_pages = size;
-+
-+/*===========================================*/
-+{
-+ dict_table_t* sys_stats;
-+ dict_index_t* sys_index;
-+ btr_pcur_t pcur;
-+ dtuple_t* tuple;
-+ dfield_t* dfield;
-+ ulint key_cols;
-+ ulint n_cols;
-+ const rec_t* rec;
-+ ulint n_fields;
-+ const byte* field;
-+ ulint len;
-+ ib_int64_t* stat_n_diff_key_vals_tmp;
-+ ib_int64_t* stat_n_non_null_key_vals_tmp;
-+ byte* buf;
-+ ulint i;
-+ mtr_t mtr;
-+
-+ n_cols = dict_index_get_n_unique(index);
-+ stat_n_diff_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
-+ stat_n_non_null_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
-+
-+ sys_stats = dict_sys->sys_stats;
-+ sys_index = UT_LIST_GET_FIRST(sys_stats->indexes);
-+ ut_a(!dict_table_is_comp(sys_stats));
-+
-+ tuple = dtuple_create(heap, 1);
-+ dfield = dtuple_get_nth_field(tuple, 0);
-+
-+ buf = mem_heap_alloc(heap, 8);
-+ mach_write_to_8(buf, index->id);
-+
-+ dfield_set_data(dfield, buf, 8);
-+ dict_index_copy_types(tuple, sys_index, 1);
-+
-+ mtr_start(&mtr);
-+
-+ btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
-+ BTR_SEARCH_LEAF, &pcur, &mtr);
-+ for (i = 0; i <= n_cols; i++) {
-+ rec = btr_pcur_get_rec(&pcur);
-+
-+ if (!btr_pcur_is_on_user_rec(&pcur)
-+ || mach_read_from_8(rec_get_nth_field_old(rec, 0, &len))
-+ != index->id) {
-+ /* not found: even 1 if not found should not be alowed */
-+ fprintf(stderr, "InnoDB: Warning: stats for %s/%s (%lu/%lu)"
-+ " not found in SYS_STATS\n",
-+ index->table_name, index->name, i, n_cols);
-+ btr_pcur_close(&pcur);
-+ mtr_commit(&mtr);
-+ mem_heap_free(heap);
-+ return(FALSE);
-+ }
-+
-+ if (rec_get_deleted_flag(rec, 0)) {
-+ /* don't count */
-+ i--;
-+ goto next_rec;
-+ }
-+
-+ n_fields = rec_get_n_fields_old(rec);
-+
-+ field = rec_get_nth_field_old(rec, 1, &len);
-+ ut_a(len == 4);
-+
-+ key_cols = mach_read_from_4(field);
-+
-+ ut_a(i == key_cols);
-+
-+ field = rec_get_nth_field_old(rec, DICT_SYS_STATS_DIFF_VALS_FIELD, &len);
-+ ut_a(len == 8);
-+
-+ stat_n_diff_key_vals_tmp[i] = mach_read_from_8(field);
-+
-+ if (n_fields > DICT_SYS_STATS_NON_NULL_VALS_FIELD) {
-+ field = rec_get_nth_field_old(rec, DICT_SYS_STATS_NON_NULL_VALS_FIELD, &len);
-+ ut_a(len == 8);
-+
-+ stat_n_non_null_key_vals_tmp[i] = mach_read_from_8(field);
-+ } else {
-+ /* not enough fields: should be older */
-+ fprintf(stderr, "InnoDB: Notice: stats for %s/%s (%lu/%lu)"
-+ " in SYS_STATS seems older format. "
-+ "Please execute ANALYZE TABLE for it.\n",
-+ index->table_name, index->name, i, n_cols);
-+
-+ stat_n_non_null_key_vals_tmp[i] = ((ib_int64_t)(-1));
-+ }
-+next_rec:
-+ btr_pcur_move_to_next_user_rec(&pcur, &mtr);
-+ }
-+
-+ btr_pcur_close(&pcur);
-+ mtr_commit(&mtr);
-+
-+ for (i = 0; i <= n_cols; i++) {
-+ index->stat_n_diff_key_vals[i] = stat_n_diff_key_vals_tmp[i];
-+ if (stat_n_non_null_key_vals_tmp[i] == ((ib_int64_t)(-1))) {
-+ /* approximate value */
-+ index->stat_n_non_null_key_vals[i] = stat_n_diff_key_vals_tmp[n_cols];
-+ } else {
-+ index->stat_n_non_null_key_vals[i] = stat_n_non_null_key_vals_tmp[i];
-+ }
-+ }
-+}
-+/*===========================================*/
-+
-+ index = dict_table_get_next_index(index);
-+ }
-+
-+ mem_heap_free(heap);
-+ return(TRUE);
-+}
-+
-+static
-+void
-+dict_store_statistics(
-+/*==================*/
-+ dict_table_t* table)
-+{
-+ dict_index_t* index;
-+ mem_heap_t* heap;
-+
-+ index = dict_table_get_first_index(table);
-+
-+ ut_a(index);
-+
-+ heap = mem_heap_create(1000);
-+
-+ while (index) {
-+/*===========================================*/
-+{
-+ dict_table_t* sys_stats;
-+ dict_index_t* sys_index;
-+ btr_pcur_t pcur;
-+ dtuple_t* tuple;
-+ dfield_t* dfield;
-+ ulint key_cols;
-+ ulint n_cols;
-+ ulint rests;
-+ const rec_t* rec;
-+ ulint n_fields;
-+ const byte* field;
-+ ulint len;
-+ ib_int64_t* stat_n_diff_key_vals_tmp;
-+ ib_int64_t* stat_n_non_null_key_vals_tmp;
-+ byte* buf;
-+ ulint i;
-+ mtr_t mtr;
-+
-+ n_cols = dict_index_get_n_unique(index);
-+ stat_n_diff_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
-+ stat_n_non_null_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
-+
-+ for (i = 0; i <= n_cols; i++) {
-+ stat_n_diff_key_vals_tmp[i] = index->stat_n_diff_key_vals[i];
-+ stat_n_non_null_key_vals_tmp[i] = index->stat_n_non_null_key_vals[i];
-+ }
-+
-+ sys_stats = dict_sys->sys_stats;
-+ sys_index = UT_LIST_GET_FIRST(sys_stats->indexes);
-+ ut_a(!dict_table_is_comp(sys_stats));
-+
-+ tuple = dtuple_create(heap, 1);
-+ dfield = dtuple_get_nth_field(tuple, 0);
-+
-+ buf = mem_heap_alloc(heap, 8);
-+ mach_write_to_8(buf, index->id);
-+
-+ dfield_set_data(dfield, buf, 8);
-+ dict_index_copy_types(tuple, sys_index, 1);
-+
-+ mtr_start(&mtr);
-+
-+ btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
-+ BTR_MODIFY_LEAF, &pcur, &mtr);
-+ rests = n_cols + 1;
-+ for (i = 0; i <= n_cols; i++) {
-+ rec = btr_pcur_get_rec(&pcur);
-+
-+ if (!btr_pcur_is_on_user_rec(&pcur)
-+ || mach_read_from_8(rec_get_nth_field_old(rec, 0, &len))
-+ != index->id) {
-+ /* not found */
-+
-+
-+ break;
-+ }
-+
-+ btr_pcur_store_position(&pcur, &mtr);
-+
-+ if (rec_get_deleted_flag(rec, 0)) {
-+ /* don't count */
-+ i--;
-+ goto next_rec;
-+ }
-+
-+ n_fields = rec_get_n_fields_old(rec);
-+
-+ if (n_fields <= DICT_SYS_STATS_NON_NULL_VALS_FIELD) {
-+ /* not update for the older smaller format */
-+ fprintf(stderr, "InnoDB: Notice: stats for %s/%s (%lu/%lu)"
-+ " in SYS_STATS seems older format. Please ANALYZE TABLE it.\n",
-+ index->table_name, index->name, i, n_cols);
-+ goto next_rec;
-+ }
-+
-+ field = rec_get_nth_field_old(rec, 1, &len);
-+ ut_a(len == 4);
-+
-+ key_cols = mach_read_from_4(field);
-+
-+ field = rec_get_nth_field_old(rec, DICT_SYS_STATS_DIFF_VALS_FIELD, &len);
-+ ut_a(len == 8);
-+
-+ mlog_write_ull((byte*)field, stat_n_diff_key_vals_tmp[key_cols], &mtr);
-+
-+ field = rec_get_nth_field_old(rec, DICT_SYS_STATS_NON_NULL_VALS_FIELD, &len);
-+ ut_a(len == 8);
-+
-+ mlog_write_ull((byte*)field, stat_n_non_null_key_vals_tmp[key_cols], &mtr);
-+
-+ rests--;
-+
-+next_rec:
-+ mtr_commit(&mtr);
-+ mtr_start(&mtr);
-+ btr_pcur_restore_position(BTR_MODIFY_LEAF, &pcur, &mtr);
-+
-+ btr_pcur_move_to_next_user_rec(&pcur, &mtr);
-+ }
-+ btr_pcur_close(&pcur);
-+ mtr_commit(&mtr);
-+
-+ if (rests) {
-+ fprintf(stderr, "InnoDB: Warning: failed to store %lu stats entries"
-+ " of %s/%s to SYS_STATS system table.\n",
-+ rests, index->table_name, index->name);
-+ }
-+}
-+/*===========================================*/
-+
-+ index = dict_table_get_next_index(index);
-+ }
-+
-+ mem_heap_free(heap);
-+}
-+
-+/*********************************************************************//**
- Calculates new estimates for table and index statistics. The statistics
- are used in query optimization. */
- UNIV_INTERN
-@@ -4361,10 +4650,11 @@
- dict_update_statistics(
- /*===================*/
- dict_table_t* table, /*!< in/out: table */
-- ibool only_calc_if_missing_stats)/*!< in: only
-+ ibool only_calc_if_missing_stats,/*!< in: only
- update/recalc the stats if they have
- not been initialized yet, otherwise
- do nothing */
-+ ibool sync) /*!< in: TRUE if must update SYS_STATS */
- {
- dict_index_t* index;
- ulint sum_of_index_sizes = 0;
-@@ -4381,6 +4671,27 @@
- return;
- }
-
-+ if (srv_use_sys_stats_table && !((table->flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY) && !sync) {
-+ dict_table_stats_lock(table, RW_X_LATCH);
-+
-+ /* reload statistics from SYS_STATS table */
-+ if (dict_reload_statistics(table, &sum_of_index_sizes)) {
-+ /* success */
-+#ifdef UNIV_DEBUG
-+ fprintf(stderr, "InnoDB: DEBUG: reload_statistics succeeded for %s.\n",
-+ table->name);
-+#endif
-+ goto end;
-+ }
-+
-+ dict_table_stats_unlock(table, RW_X_LATCH);
-+ }
-+#ifdef UNIV_DEBUG
-+ fprintf(stderr, "InnoDB: DEBUG: update_statistics for %s.\n",
-+ table->name);
-+#endif
-+ sum_of_index_sizes = 0;
-+
- /* Find out the sizes of the indexes and how many different values
- for the key they approximately have */
-
-@@ -4445,6 +4756,11 @@
- index = dict_table_get_next_index(index);
- } while (index);
-
-+ if (srv_use_sys_stats_table && !((table->flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY)) {
-+ /* store statistics to SYS_STATS table */
-+ dict_store_statistics(table);
-+ }
-+end:
- index = dict_table_get_first_index(table);
-
- table->stat_n_rows = index->stat_n_diff_key_vals[
-@@ -4462,6 +4778,78 @@
- dict_table_stats_unlock(table, RW_X_LATCH);
- }
-
-+/*********************************************************************//**
-+*/
-+UNIV_INTERN
-+ibool
-+dict_is_older_statistics(
-+/*=====================*/
-+ dict_index_t* index)
-+{
-+ mem_heap_t* heap;
-+ dict_table_t* sys_stats;
-+ dict_index_t* sys_index;
-+ btr_pcur_t pcur;
-+ dtuple_t* tuple;
-+ dfield_t* dfield;
-+ const rec_t* rec;
-+ ulint n_fields;
-+ ulint len;
-+ byte* buf;
-+ mtr_t mtr;
-+
-+ heap = mem_heap_create(100);
-+
-+ sys_stats = dict_sys->sys_stats;
-+ sys_index = UT_LIST_GET_FIRST(sys_stats->indexes);
-+ ut_a(!dict_table_is_comp(sys_stats));
-+
-+ tuple = dtuple_create(heap, 1);
-+ dfield = dtuple_get_nth_field(tuple, 0);
-+
-+ buf = mem_heap_alloc(heap, 8);
-+ mach_write_to_8(buf, index->id);
-+
-+ dfield_set_data(dfield, buf, 8);
-+ dict_index_copy_types(tuple, sys_index, 1);
-+
-+ mtr_start(&mtr);
-+
-+ btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
-+ BTR_SEARCH_LEAF, &pcur, &mtr);
-+
-+next_rec:
-+ rec = btr_pcur_get_rec(&pcur);
-+
-+ if (!btr_pcur_is_on_user_rec(&pcur)
-+ || mach_read_from_8(rec_get_nth_field_old(rec, 0, &len))
-+ != index->id) {
-+ /* not found */
-+ btr_pcur_close(&pcur);
-+ mtr_commit(&mtr);
-+ mem_heap_free(heap);
-+ /* no statistics == not older statistics */
-+ return(FALSE);
-+ }
-+
-+ if (rec_get_deleted_flag(rec, 0)) {
-+ btr_pcur_move_to_next_user_rec(&pcur, &mtr);
-+ goto next_rec;
-+ }
-+
-+ n_fields = rec_get_n_fields_old(rec);
-+
-+ btr_pcur_close(&pcur);
-+ mtr_commit(&mtr);
-+ mem_heap_free(heap);
-+
-+ if (n_fields > DICT_SYS_STATS_NON_NULL_VALS_FIELD) {
-+ return(FALSE);
-+ } else {
-+ return(TRUE);
-+ }
-+}
-+
- /**********************************************************************//**
- Prints info of a foreign key constraint. */
- static
-@@ -4539,7 +4927,8 @@
-
- ut_ad(mutex_own(&(dict_sys->mutex)));
-
-- dict_update_statistics(table, FALSE /* update even if initialized */);
-+ if (srv_stats_auto_update)
-+ dict_update_statistics(table, FALSE /* update even if initialized */, FALSE);
-
- dict_table_stats_lock(table, RW_S_LATCH);
-
---- a/storage/innobase/dict/dict0load.c
-+++ b/storage/innobase/dict/dict0load.c
-@@ -50,7 +50,8 @@
- "SYS_COLUMNS",
- "SYS_FIELDS",
- "SYS_FOREIGN",
-- "SYS_FOREIGN_COLS"
-+ "SYS_FOREIGN_COLS",
-+ "SYS_STATS"
- };
-
- /* If this flag is TRUE, then we will load the cluster index's (and tables')
-@@ -348,12 +349,13 @@
- }
-
- if ((status & DICT_TABLE_UPDATE_STATS)
-+ && srv_stats_auto_update
- && dict_table_get_first_index(*table)) {
-
- /* Update statistics if DICT_TABLE_UPDATE_STATS
- is set */
- dict_update_statistics(*table, FALSE /* update even if
-- initialized */);
-+ initialized */, FALSE);
- }
-
- return(NULL);
-@@ -587,6 +589,75 @@
- //#endif /* FOREIGN_NOT_USED */
-
- /********************************************************************//**
-+This function parses a SYS_STATS record and extract necessary
-+information from the record and return to caller.
-+@return error message, or NULL on success */
-+UNIV_INTERN
-+const char*
-+dict_process_sys_stats_rec(
-+/*=============================*/
-+ mem_heap_t* heap __attribute__((unused)), /*!< in/out: heap memory */
-+ const rec_t* rec, /*!< in: current SYS_STATS rec */
-+ index_id_t* index_id, /*!< out: INDEX_ID */
-+ ulint* key_cols, /*!< out: KEY_COLS */
-+ ib_uint64_t* diff_vals, /*!< out: DIFF_VALS */
-+ ib_uint64_t* non_null_vals) /*!< out: NON_NULL_VALS */
-+{
-+ ulint len;
-+ const byte* field;
-+ ulint n_fields;
-+
-+ if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
-+ return("delete-marked record in SYS_STATS");
-+ }
-+
-+ n_fields = rec_get_n_fields_old(rec);
-+
-+ if (UNIV_UNLIKELY(n_fields < 5)) {
-+ return("wrong number of columns in SYS_STATS record");
-+ }
-+
-+ field = rec_get_nth_field_old(rec, 0/*INDEX_ID*/, &len);
-+ if (UNIV_UNLIKELY(len != 8)) {
-+err_len:
-+ return("incorrect column length in SYS_STATS");
-+ }
-+ *index_id = mach_read_from_8(field);
-+
-+ field = rec_get_nth_field_old(rec, 1/*KEY_COLS*/, &len);
-+ if (UNIV_UNLIKELY(len != 4)) {
-+ goto err_len;
-+ }
-+ *key_cols = mach_read_from_4(field);
-+
-+ rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
-+ if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
-+ goto err_len;
-+ }
-+ rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
-+ if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
-+ goto err_len;
-+ }
-+
-+ field = rec_get_nth_field_old(rec, 4/*DIFF_VALS*/, &len);
-+ if (UNIV_UNLIKELY(len != 8)) {
-+ goto err_len;
-+ }
-+ *diff_vals = mach_read_from_8(field);
-+
-+ if (n_fields < 6) {
-+ *non_null_vals = ((ib_uint64_t)(-1));
-+ } else {
-+ field = rec_get_nth_field_old(rec, 5/*NON_NULL_VALS*/, &len);
-+ if (UNIV_UNLIKELY(len != 8)) {
-+ goto err_len;
-+ }
-+ *non_null_vals = mach_read_from_8(field);
-+ }
-+
-+ return(NULL);
-+}
-+/********************************************************************//**
- Determine the flags of a table described in SYS_TABLES.
- @return compressed page size in kilobytes; or 0 if the tablespace is
- uncompressed, ULINT_UNDEFINED on error */
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -188,6 +188,7 @@
- static my_bool innobase_create_status_file = FALSE;
- static my_bool innobase_stats_on_metadata = TRUE;
- static my_bool innobase_large_prefix = FALSE;
-+static my_bool innobase_use_sys_stats_table = FALSE;
-
-
- static char* internal_innobase_data_file_path = NULL;
-@@ -2468,6 +2469,8 @@
- goto error;
- }
-
-+ srv_use_sys_stats_table = (ibool) innobase_use_sys_stats_table;
-+
- /* -------------- Log files ---------------------------*/
-
- /* The default dir for log files is the datadir of MySQL */
-@@ -5256,6 +5259,10 @@
-
- error = row_insert_for_mysql((byte*) record, prebuilt);
-
-+#ifdef EXTENDED_FOR_USERSTAT
-+ if (error == DB_SUCCESS) rows_changed++;
-+#endif
-+
- /* Handle duplicate key errors */
- if (auto_inc_used) {
- ulint err;
-@@ -5591,6 +5598,10 @@
- }
- }
-
-+#ifdef EXTENDED_FOR_USERSTAT
-+ if (error == DB_SUCCESS) rows_changed++;
-+#endif
-+
- innodb_srv_conc_exit_innodb(trx);
-
- error = convert_error_code_to_mysql(error,
-@@ -5644,6 +5655,10 @@
-
- error = row_update_for_mysql((byte*) record, prebuilt);
-
-+#ifdef EXTENDED_FOR_USERSTAT
-+ if (error == DB_SUCCESS) rows_changed++;
-+#endif
-+
- innodb_srv_conc_exit_innodb(trx);
-
- error = convert_error_code_to_mysql(
-@@ -5965,6 +5980,11 @@
- case DB_SUCCESS:
- error = 0;
- table->status = 0;
-+#ifdef EXTENDED_FOR_USERSTAT
-+ rows_read++;
-+ if (active_index < MAX_KEY)
-+ index_rows_read[active_index]++;
-+#endif
- break;
- case DB_RECORD_NOT_FOUND:
- error = HA_ERR_KEY_NOT_FOUND;
-@@ -6196,6 +6216,11 @@
- case DB_SUCCESS:
- error = 0;
- table->status = 0;
-+#ifdef EXTENDED_FOR_USERSTAT
-+ rows_read++;
-+ if (active_index < MAX_KEY)
-+ index_rows_read[active_index]++;
-+#endif
- break;
- case DB_RECORD_NOT_FOUND:
- error = HA_ERR_END_OF_FILE;
-@@ -8149,11 +8174,35 @@
- /* In sql_show we call with this flag: update
- then statistics so that they are up-to-date */
-
-+ if (srv_use_sys_stats_table && !((ib_table->flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY)
-+ && called_from_analyze) {
-+ /* If the indexes on the table don't have enough rows in SYS_STATS system table, */
-+ /* they need to be created. */
-+ dict_index_t* index;
-+
-+ prebuilt->trx->op_info = "confirming rows of SYS_STATS to store statistics";
-+
-+ ut_a(prebuilt->trx->conc_state == TRX_NOT_STARTED);
-+
-+ for (index = dict_table_get_first_index(ib_table);
-+ index != NULL;
-+ index = dict_table_get_next_index(index)) {
-+ if (dict_is_older_statistics(index)) {
-+ row_delete_stats_for_mysql(index, prebuilt->trx);
-+ innobase_commit_low(prebuilt->trx);
-+ }
-+ row_insert_stats_for_mysql(index, prebuilt->trx);
-+ innobase_commit_low(prebuilt->trx);
-+ }
-+
-+ ut_a(prebuilt->trx->conc_state == TRX_NOT_STARTED);
-+ }
-+
- prebuilt->trx->op_info = "updating table statistics";
-
- dict_update_statistics(ib_table,
- FALSE /* update even if stats
-- are initialized */);
-+ are initialized */, called_from_analyze);
-
- prebuilt->trx->op_info = "returning various info to MySQL";
- }
-@@ -8238,7 +8287,7 @@
- are asked by MySQL to avoid locking. Another reason to
- avoid the call is that it uses quite a lot of CPU.
- See Bug#38185. */
-- if (flag & HA_STATUS_NO_LOCK
-+ if (flag & HA_STATUS_NO_LOCK || !srv_stats_update_need_lock
- || !(flag & HA_STATUS_VARIABLE_EXTRA)) {
- /* We do not update delete_length if no
- locking is requested so the "old" value can
-@@ -11511,6 +11560,26 @@
- "The number of index pages to sample when calculating statistics (default 8)",
- NULL, NULL, 8, 1, ~0ULL, 0);
-
-+static MYSQL_SYSVAR_ULONG(stats_auto_update, srv_stats_auto_update,
-+ PLUGIN_VAR_RQCMDARG,
-+ "Enable/Disable InnoDB's auto update statistics of indexes. "
-+ "(except for ANALYZE TABLE command) 0:disable 1:enable",
-+ NULL, NULL, 1, 0, 1, 0);
-+
-+static MYSQL_SYSVAR_ULONG(stats_update_need_lock, srv_stats_update_need_lock,
-+ PLUGIN_VAR_RQCMDARG,
-+ "Enable/Disable InnoDB's update statistics which needs to lock dictionary. "
-+ "e.g. Data_free.",
-+ NULL, NULL, 1, 0, 1, 0);
-+
-+static MYSQL_SYSVAR_BOOL(use_sys_stats_table, innobase_use_sys_stats_table,
-+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
-+ "Enable to use SYS_STATS system table to store statistics statically, "
-+ "And avoids to calculate statistics at every first open of the tables. "
-+ "This option may make the opportunities of update statistics less. "
-+ "So you should use ANALYZE TABLE command intentionally.",
-+ NULL, NULL, FALSE);
-+
- static MYSQL_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled,
- PLUGIN_VAR_OPCMDARG,
- "Enable InnoDB adaptive hash index (enabled by default). "
-@@ -11883,6 +11952,9 @@
- MYSQL_SYSVAR(recovery_update_relay_log),
- MYSQL_SYSVAR(rollback_on_timeout),
- MYSQL_SYSVAR(stats_on_metadata),
-+ MYSQL_SYSVAR(stats_auto_update),
-+ MYSQL_SYSVAR(stats_update_need_lock),
-+ MYSQL_SYSVAR(use_sys_stats_table),
- MYSQL_SYSVAR(stats_sample_pages),
- MYSQL_SYSVAR(adaptive_hash_index),
- MYSQL_SYSVAR(stats_method),
-@@ -11957,7 +12029,10 @@
- i_s_innodb_sys_columns,
- i_s_innodb_sys_fields,
- i_s_innodb_sys_foreign,
--i_s_innodb_sys_foreign_cols
-+i_s_innodb_sys_foreign_cols,
-+i_s_innodb_sys_stats,
-+i_s_innodb_table_stats,
-+i_s_innodb_index_stats
- mysql_declare_plugin_end;
-
- /** @brief Initialize the default value of innodb_commit_concurrency.
---- a/storage/innobase/handler/i_s.cc
-+++ b/storage/innobase/handler/i_s.cc
-@@ -49,6 +49,7 @@
- #include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
- #include "trx0rseg.h" /* for trx_rseg_struct */
- #include "trx0sys.h" /* for trx_sys */
-+#include "dict0dict.h" /* for dict_sys */
- }
-
- #define OK(expr) \
-@@ -3511,6 +3512,225 @@
- STRUCT_FLD(flags, 0UL)
- };
-
-+/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_sys_stats */
-+static ST_FIELD_INFO innodb_sys_stats_fields_info[] =
-+{
-+#define SYS_STATS_INDEX_ID 0
-+ {STRUCT_FLD(field_name, "INDEX_ID"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_STATS_KEY_COLS 1
-+ {STRUCT_FLD(field_name, "KEY_COLS"),
-+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_STATS_DIFF_VALS 2
-+ {STRUCT_FLD(field_name, "DIFF_VALS"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+#define SYS_STATS_NON_NULL_VALS 3
-+ {STRUCT_FLD(field_name, "NON_NULL_VALS"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ END_OF_ST_FIELD_INFO
-+};
-+/**********************************************************************//**
-+Function to fill information_schema.innodb_sys_stats
-+@return 0 on success */
-+static
-+int
-+i_s_dict_fill_sys_stats(
-+/*====================*/
-+ THD* thd, /*!< in: thread */
-+ index_id_t index_id, /*!< in: INDEX_ID */
-+ ulint key_cols, /*!< in: KEY_COLS */
-+ ib_uint64_t diff_vals, /*!< in: DIFF_VALS */
-+ ib_uint64_t non_null_vals, /*!< in: NON_NULL_VALS */
-+ TABLE* table_to_fill) /*!< in/out: fill this table */
-+{
-+ Field** fields;
-+
-+ DBUG_ENTER("i_s_dict_fill_sys_stats");
-+
-+ fields = table_to_fill->field;
-+
-+ OK(fields[SYS_STATS_INDEX_ID]->store(longlong(index_id), TRUE));
-+
-+ OK(fields[SYS_STATS_KEY_COLS]->store(key_cols));
-+
-+ OK(fields[SYS_STATS_DIFF_VALS]->store(longlong(diff_vals), TRUE));
-+
-+ if (non_null_vals == ((ib_uint64_t)(-1))) {
-+ fields[SYS_STATS_NON_NULL_VALS]->set_null();
-+ } else {
-+ OK(fields[SYS_STATS_NON_NULL_VALS]->store(longlong(non_null_vals), TRUE));
-+ fields[SYS_STATS_NON_NULL_VALS]->set_notnull();
-+ }
-+
-+ OK(schema_table_store_record(thd, table_to_fill));
-+
-+ DBUG_RETURN(0);
-+}
-+/*******************************************************************//**
-+Function to populate INFORMATION_SCHEMA.innodb_sys_stats table.
-+@return 0 on success */
-+static
-+int
-+i_s_sys_stats_fill_table(
-+/*=====================*/
-+ THD* thd, /*!< in: thread */
-+ TABLE_LIST* tables, /*!< in/out: tables to fill */
-+ COND* cond) /*!< in: condition (not used) */
-+{
-+ btr_pcur_t pcur;
-+ const rec_t* rec;
-+ mem_heap_t* heap;
-+ mtr_t mtr;
-+
-+ DBUG_ENTER("i_s_sys_stats_fill_table");
-+
-+ /* deny access to non-superusers */
-+ if (check_global_access(thd, PROCESS_ACL)) {
-+ DBUG_RETURN(0);
-+ }
-+
-+ heap = mem_heap_create(1000);
-+ mutex_enter(&dict_sys->mutex);
-+ mtr_start(&mtr);
-+
-+ rec = dict_startscan_system(&pcur, &mtr, SYS_STATS);
-+
-+ while (rec) {
-+ const char* err_msg;
-+ index_id_t index_id;
-+ ulint key_cols;
-+ ib_uint64_t diff_vals;
-+ ib_uint64_t non_null_vals;
-+
-+ /* Extract necessary information from a SYS_FOREIGN_COLS row */
-+ err_msg = dict_process_sys_stats_rec(
-+ heap, rec, &index_id, &key_cols, &diff_vals, &non_null_vals);
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+
-+ if (!err_msg) {
-+ i_s_dict_fill_sys_stats(
-+ thd, index_id, key_cols, diff_vals, non_null_vals,
-+ tables->table);
-+ } else {
-+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-+ ER_CANT_FIND_SYSTEM_REC,
-+ err_msg);
-+ }
-+
-+ mem_heap_empty(heap);
-+
-+ /* Get the next record */
-+ mutex_enter(&dict_sys->mutex);
-+ mtr_start(&mtr);
-+ rec = dict_getnext_system(&pcur, &mtr);
-+ }
-+
-+ mtr_commit(&mtr);
-+ mutex_exit(&dict_sys->mutex);
-+ mem_heap_free(heap);
-+
-+ DBUG_RETURN(0);
-+}
-+/*******************************************************************//**
-+Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_stats
-+@return 0 on success */
-+static
-+int
-+innodb_sys_stats_init(
-+/*========================*/
-+ void* p) /*!< in/out: table schema object */
-+{
-+ ST_SCHEMA_TABLE* schema;
-+
-+ DBUG_ENTER("innodb_sys_stats_init");
-+
-+ schema = (ST_SCHEMA_TABLE*) p;
-+
-+ schema->fields_info = innodb_sys_stats_fields_info;
-+ schema->fill_table = i_s_sys_stats_fill_table;
-+
-+ DBUG_RETURN(0);
-+}
-+
-+UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_stats =
-+{
-+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
-+ /* int */
-+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-+
-+ /* pointer to type-specific plugin descriptor */
-+ /* void* */
-+ STRUCT_FLD(info, &i_s_info),
-+
-+ /* plugin name */
-+ /* const char* */
-+ STRUCT_FLD(name, "INNODB_SYS_STATS"),
-+
-+ /* plugin author (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(author, "Percona"),
-+
-+ /* general descriptive text (for SHOW PLUGINS) */
-+ /* const char* */
-+ STRUCT_FLD(descr, "XtraDB SYS_STATS table"),
-+
-+ /* the plugin license (PLUGIN_LICENSE_XXX) */
-+ /* int */
-+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-+
-+ /* the function to invoke when plugin is loaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(init, innodb_sys_stats_init),
-+
-+ /* the function to invoke when plugin is unloaded */
-+ /* int (*)(void*); */
-+ STRUCT_FLD(deinit, i_s_common_deinit),
-+
-+ /* plugin version (for SHOW PLUGINS) */
-+ /* unsigned int */
-+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
-+
-+ /* struct st_mysql_show_var* */
-+ STRUCT_FLD(status_vars, NULL),
-+
-+ /* struct st_mysql_sys_var** */
-+ STRUCT_FLD(system_vars, NULL),
-+
-+ /* reserved for dependency checking */
-+ /* void* */
-+ STRUCT_FLD(__reserved1, NULL),
-+
-+ /* flags for plugin */
-+ /* unsigned long */
-+ STRUCT_FLD(flags, 0UL)
-+};
-+
- /***********************************************************************
- */
- static ST_FIELD_INFO i_s_innodb_rseg_fields_info[] =
-@@ -3677,3 +3897,349 @@
- /* unsigned long */
- STRUCT_FLD(flags, 0UL),
- };
-+
-+/***********************************************************************
-+*/
-+static ST_FIELD_INFO i_s_innodb_table_stats_info[] =
-+{
-+ {STRUCT_FLD(field_name, "table_schema"),
-+ STRUCT_FLD(field_length, NAME_LEN),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "table_name"),
-+ STRUCT_FLD(field_length, NAME_LEN),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "rows"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "clust_size"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "other_size"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "modified"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ END_OF_ST_FIELD_INFO
-+};
-+
-+static ST_FIELD_INFO i_s_innodb_index_stats_info[] =
-+{
-+ {STRUCT_FLD(field_name, "table_schema"),
-+ STRUCT_FLD(field_length, NAME_LEN),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "table_name"),
-+ STRUCT_FLD(field_length, NAME_LEN),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "index_name"),
-+ STRUCT_FLD(field_length, NAME_LEN),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "fields"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "rows_per_key"),
-+ STRUCT_FLD(field_length, 256),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, 0),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "index_total_pages"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ {STRUCT_FLD(field_name, "index_leaf_pages"),
-+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
-+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
-+ STRUCT_FLD(value, 0),
-+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
-+ STRUCT_FLD(old_name, ""),
-+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
-+
-+ END_OF_ST_FIELD_INFO
-+};
-+
-+static
-+int
-+i_s_innodb_table_stats_fill(
-+/*========================*/
-+ THD* thd,
-+ TABLE_LIST* tables,
-+ COND* cond)
-+{
-+ TABLE* i_s_table = (TABLE *) tables->table;
-+ int status = 0;
-+ dict_table_t* table;
-+
-+ DBUG_ENTER("i_s_innodb_table_stats_fill");
-+
-+ /* deny access to non-superusers */
-+ if (check_global_access(thd, PROCESS_ACL)) {
-+ DBUG_RETURN(0);
-+ }
-+
-+ mutex_enter(&(dict_sys->mutex));
-+
-+ table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
-+
-+ while (table) {
-+ char buf[NAME_LEN * 2 + 2];
-+ char* ptr;
-+
-+ if (table->stat_clustered_index_size == 0) {
-+ table = UT_LIST_GET_NEXT(table_LRU, table);
-+ continue;
-+ }
-+
-+ buf[NAME_LEN * 2 + 1] = 0;
-+ strncpy(buf, table->name, NAME_LEN * 2 + 1);
-+ ptr = strchr(buf, '/');
-+ if (ptr) {
-+ *ptr = '\0';
-+ ++ptr;
-+ } else {
-+ ptr = buf;
-+ }
-+
-+ field_store_string(i_s_table->field[0], buf);
-+ field_store_string(i_s_table->field[1], ptr);
-+ i_s_table->field[2]->store(table->stat_n_rows);
-+ i_s_table->field[3]->store(table->stat_clustered_index_size);
-+ i_s_table->field[4]->store(table->stat_sum_of_other_index_sizes);
-+ i_s_table->field[5]->store(table->stat_modified_counter);
-+
-+ if (schema_table_store_record(thd, i_s_table)) {
-+ status = 1;
-+ break;
-+ }
-+
-+ table = UT_LIST_GET_NEXT(table_LRU, table);
-+ }
-+
-+ mutex_exit(&(dict_sys->mutex));
-+
-+ DBUG_RETURN(status);
-+}
-+
-+static
-+int
-+i_s_innodb_index_stats_fill(
-+/*========================*/
-+ THD* thd,
-+ TABLE_LIST* tables,
-+ COND* cond)
-+{
-+ TABLE* i_s_table = (TABLE *) tables->table;
-+ int status = 0;
-+ dict_table_t* table;
-+ dict_index_t* index;
-+
-+ DBUG_ENTER("i_s_innodb_index_stats_fill");
-+
-+ /* deny access to non-superusers */
-+ if (check_global_access(thd, PROCESS_ACL)) {
-+ DBUG_RETURN(0);
-+ }
-+
-+ mutex_enter(&(dict_sys->mutex));
-+
-+ table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
-+
-+ while (table) {
-+ if (table->stat_clustered_index_size == 0) {
-+ table = UT_LIST_GET_NEXT(table_LRU, table);
-+ continue;
-+ }
-+
-+ ib_int64_t n_rows = table->stat_n_rows;
-+
-+ if (n_rows < 0) {
-+ n_rows = 0;
-+ }
-+
-+ index = dict_table_get_first_index(table);
-+
-+ while (index) {
-+ char buff[256+1];
-+ char row_per_keys[256+1];
-+ char buf[NAME_LEN * 2 + 2];
-+ char* ptr;
-+ ulint i;
-+
-+ buf[NAME_LEN * 2 + 1] = 0;
-+ strncpy(buf, table->name, NAME_LEN * 2 + 1);
-+ ptr = strchr(buf, '/');
-+ if (ptr) {
-+ *ptr = '\0';
-+ ++ptr;
-+ } else {
-+ ptr = buf;
-+ }
-+
-+ field_store_string(i_s_table->field[0], buf);
-+ field_store_string(i_s_table->field[1], ptr);
-+ field_store_string(i_s_table->field[2], index->name);
-+ i_s_table->field[3]->store(index->n_uniq);
-+
-+ row_per_keys[0] = '\0';
-+
-+ /* It is remained optimistic operation still for now */
-+ //dict_index_stat_mutex_enter(index);
-+ if (index->stat_n_diff_key_vals) {
-+ for (i = 1; i <= index->n_uniq; i++) {
-+ ib_int64_t rec_per_key;
-+ if (index->stat_n_diff_key_vals[i]) {
-+ rec_per_key = n_rows / index->stat_n_diff_key_vals[i];
-+ } else {
-+ rec_per_key = n_rows;
-+ }
-+ ut_snprintf(buff, 256, (i == index->n_uniq)?"%llu":"%llu, ",
-+ rec_per_key);
-+ strncat(row_per_keys, buff, 256 - strlen(row_per_keys));
-+ }
-+ }
-+ //dict_index_stat_mutex_exit(index);
-+
-+ field_store_string(i_s_table->field[4], row_per_keys);
-+
-+ i_s_table->field[5]->store(index->stat_index_size);
-+ i_s_table->field[6]->store(index->stat_n_leaf_pages);
-+
-+ if (schema_table_store_record(thd, i_s_table)) {
-+ status = 1;
-+ break;
-+ }
-+
-+ index = dict_table_get_next_index(index);
-+ }
-+
-+ if (status == 1) {
-+ break;
-+ }
-+
-+ table = UT_LIST_GET_NEXT(table_LRU, table);
-+ }
-+
-+ mutex_exit(&(dict_sys->mutex));
-+
-+ DBUG_RETURN(status);
-+}
-+
-+static
-+int
-+i_s_innodb_table_stats_init(
-+/*========================*/
-+ void* p)
-+{
-+ DBUG_ENTER("i_s_innodb_table_stats_init");
-+ ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
-+
-+ schema->fields_info = i_s_innodb_table_stats_info;
-+ schema->fill_table = i_s_innodb_table_stats_fill;
-+
-+ DBUG_RETURN(0);
-+}
-+
-+static
-+int
-+i_s_innodb_index_stats_init(
-+/*========================*/
-+ void* p)
-+{
-+ DBUG_ENTER("i_s_innodb_index_stats_init");
-+ ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
-+
-+ schema->fields_info = i_s_innodb_index_stats_info;
-+ schema->fill_table = i_s_innodb_index_stats_fill;
-+
-+ DBUG_RETURN(0);
-+}
-+
-+UNIV_INTERN struct st_mysql_plugin i_s_innodb_table_stats =
-+{
-+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-+ STRUCT_FLD(info, &i_s_info),
-+ STRUCT_FLD(name, "INNODB_TABLE_STATS"),
-+ STRUCT_FLD(author, "Percona"),
-+ STRUCT_FLD(descr, "InnoDB table statistics in memory"),
-+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-+ STRUCT_FLD(init, i_s_innodb_table_stats_init),
-+ STRUCT_FLD(deinit, i_s_common_deinit),
-+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
-+ STRUCT_FLD(status_vars, NULL),
-+ STRUCT_FLD(system_vars, NULL),
-+ STRUCT_FLD(__reserved1, NULL),
-+ STRUCT_FLD(flags, 0UL)
-+};
-+
-+UNIV_INTERN struct st_mysql_plugin i_s_innodb_index_stats =
-+{
-+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
-+ STRUCT_FLD(info, &i_s_info),
-+ STRUCT_FLD(name, "INNODB_INDEX_STATS"),
-+ STRUCT_FLD(author, "Percona"),
-+ STRUCT_FLD(descr, "InnoDB index statistics in memory"),
-+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
-+ STRUCT_FLD(init, i_s_innodb_index_stats_init),
-+ STRUCT_FLD(deinit, i_s_common_deinit),
-+ STRUCT_FLD(version, 0x0100 /* 1.0 */),
-+ STRUCT_FLD(status_vars, NULL),
-+ STRUCT_FLD(system_vars, NULL),
-+ STRUCT_FLD(__reserved1, NULL),
-+ STRUCT_FLD(flags, 0UL)
-+};
---- a/storage/innobase/handler/i_s.h
-+++ b/storage/innobase/handler/i_s.h
-@@ -43,5 +43,8 @@
- extern struct st_mysql_plugin i_s_innodb_sys_foreign;
- extern struct st_mysql_plugin i_s_innodb_sys_foreign_cols;
- extern struct st_mysql_plugin i_s_innodb_rseg;
-+extern struct st_mysql_plugin i_s_innodb_sys_stats;
-+extern struct st_mysql_plugin i_s_innodb_table_stats;
-+extern struct st_mysql_plugin i_s_innodb_index_stats;
-
- #endif /* i_s_h */
---- a/storage/innobase/include/dict0boot.h
-+++ b/storage/innobase/include/dict0boot.h
-@@ -104,6 +104,7 @@
- #define DICT_COLUMNS_ID 2
- #define DICT_INDEXES_ID 3
- #define DICT_FIELDS_ID 4
-+#define DICT_STATS_ID 6
- /* The following is a secondary index on SYS_TABLES */
- #define DICT_TABLE_IDS_ID 5
-
-@@ -131,10 +132,13 @@
- #define DICT_HDR_INDEXES 44 /* Root of the index index tree */
- #define DICT_HDR_FIELDS 48 /* Root of the index field
- index tree */
-+#define DICT_HDR_STATS 52 /* Root of the stats tree */
-
- #define DICT_HDR_FSEG_HEADER 56 /* Segment header for the tablespace
- segment into which the dictionary
- header is created */
-+
-+#define DICT_HDR_XTRADB_MARK 256 /* Flag to distinguish expansion of XtraDB */
- /*-------------------------------------------------------------*/
-
- /* The field numbers in the SYS_TABLES clustered index */
-@@ -146,11 +150,16 @@
- #define DICT_SYS_INDEXES_TYPE_FIELD 6
- #define DICT_SYS_INDEXES_NAME_FIELD 4
-
-+#define DICT_SYS_STATS_DIFF_VALS_FIELD 4
-+#define DICT_SYS_STATS_NON_NULL_VALS_FIELD 5
-+
- /* When a row id which is zero modulo this number (which must be a power of
- two) is assigned, the field DICT_HDR_ROW_ID on the dictionary header page is
- updated */
- #define DICT_HDR_ROW_ID_WRITE_MARGIN 256
-
-+#define DICT_HDR_XTRADB_FLAG 0x5854524144425F31ULL /* "XTRADB_1" */
-+
- #ifndef UNIV_NONINL
- #include "dict0boot.ic"
- #endif
---- a/storage/innobase/include/dict0crea.h
-+++ b/storage/innobase/include/dict0crea.h
-@@ -53,6 +53,14 @@
- dict_index_t* index, /*!< in: index to create, built as a memory data
- structure */
- mem_heap_t* heap); /*!< in: heap where created */
-+/*********************************************************************//**
-+*/
-+UNIV_INTERN
-+ind_node_t*
-+ind_insert_stats_graph_create(
-+/*==========================*/
-+ dict_index_t* index,
-+ mem_heap_t* heap);
- /***********************************************************//**
- Creates a table. This is a high-level function used in SQL execution graphs.
- @return query thread to run next or NULL */
-@@ -62,6 +70,13 @@
- /*===================*/
- que_thr_t* thr); /*!< in: query thread */
- /***********************************************************//**
-+*/
-+UNIV_INTERN
-+que_thr_t*
-+dict_insert_stats_step(
-+/*===================*/
-+ que_thr_t* thr);
-+/***********************************************************//**
- Creates an index. This is a high-level function used in SQL execution
- graphs.
- @return query thread to run next or NULL */
-@@ -170,6 +185,7 @@
- ins_node_t* field_def; /* child node which does the inserts of
- the field definitions; the row to be inserted
- is built by the parent node */
-+ ins_node_t* stats_def;
- commit_node_t* commit_node;
- /* child node which performs a commit after
- a successful index creation */
-@@ -180,6 +196,7 @@
- dict_table_t* table; /*!< table which owns the index */
- dtuple_t* ind_row;/* index definition row built */
- ulint field_no;/* next field definition to insert */
-+ ulint stats_no;
- mem_heap_t* heap; /*!< memory heap used as auxiliary storage */
- };
-
-@@ -189,6 +206,7 @@
- #define INDEX_CREATE_INDEX_TREE 3
- #define INDEX_COMMIT_WORK 4
- #define INDEX_ADD_TO_CACHE 5
-+#define INDEX_BUILD_STATS_COLS 6
-
- #ifndef UNIV_NONINL
- #include "dict0crea.ic"
---- a/storage/innobase/include/dict0dict.h
-+++ b/storage/innobase/include/dict0dict.h
-@@ -1126,10 +1126,18 @@
- dict_update_statistics(
- /*===================*/
- dict_table_t* table, /*!< in/out: table */
-- ibool only_calc_if_missing_stats);/*!< in: only
-+ ibool only_calc_if_missing_stats, /*!< in: only
- update/recalc the stats if they have
- not been initialized yet, otherwise
- do nothing */
-+ ibool sync);
-+/*********************************************************************//**
-+*/
-+UNIV_INTERN
-+ibool
-+dict_is_older_statistics(
-+/*=====================*/
-+ dict_index_t* index);
- /********************************************************************//**
- Reserves the dictionary system mutex for MySQL. */
- UNIV_INTERN
-@@ -1244,6 +1252,7 @@
- dict_table_t* sys_columns; /*!< SYS_COLUMNS table */
- dict_table_t* sys_indexes; /*!< SYS_INDEXES table */
- dict_table_t* sys_fields; /*!< SYS_FIELDS table */
-+ dict_table_t* sys_stats; /*!< SYS_STATS table */
- };
- #endif /* !UNIV_HOTBACKUP */
-
---- a/storage/innobase/include/dict0load.h
-+++ b/storage/innobase/include/dict0load.h
-@@ -41,6 +41,7 @@
- SYS_FIELDS,
- SYS_FOREIGN,
- SYS_FOREIGN_COLS,
-+ SYS_STATS,
-
- /* This must be last item. Defines the number of system tables. */
- SYS_NUM_SYSTEM_TABLES
-@@ -327,6 +328,20 @@
- const char** ref_col_name, /*!< out: referenced column name
- in referenced table */
- ulint* pos); /*!< out: column position */
-+/********************************************************************//**
-+This function parses a SYS_STATS record and extract necessary
-+information from the record and return to caller.
-+@return error message, or NULL on success */
-+UNIV_INTERN
-+const char*
-+dict_process_sys_stats_rec(
-+/*=============================*/
-+ mem_heap_t* heap, /*!< in/out: heap memory */
-+ const rec_t* rec, /*!< in: current SYS_STATS rec */
-+ index_id_t* index_id, /*!< out: INDEX_ID */
-+ ulint* key_cols, /*!< out: KEY_COLS */
-+ ib_uint64_t* diff_vals, /*!< out: DIFF_VALS */
-+ ib_uint64_t* non_null_vals); /*!< out: NON_NULL_VALS */
- #ifndef UNIV_NONINL
- #include "dict0load.ic"
- #endif
---- a/storage/innobase/include/que0que.h
-+++ b/storage/innobase/include/que0que.h
-@@ -492,6 +492,8 @@
- #define QUE_NODE_CALL 31
- #define QUE_NODE_EXIT 32
-
-+#define QUE_NODE_INSERT_STATS 34
-+
- /* Query thread states */
- #define QUE_THR_RUNNING 1
- #define QUE_THR_PROCEDURE_WAIT 2
---- a/storage/innobase/include/row0mysql.h
-+++ b/storage/innobase/include/row0mysql.h
-@@ -387,6 +387,22 @@
- then checked for not being too
- large. */
- /*********************************************************************//**
-+*/
-+UNIV_INTERN
-+int
-+row_insert_stats_for_mysql(
-+/*=======================*/
-+ dict_index_t* index,
-+ trx_t* trx);
-+/*********************************************************************//**
-+*/
-+UNIV_INTERN
-+int
-+row_delete_stats_for_mysql(
-+/*=======================*/
-+ dict_index_t* index,
-+ trx_t* trx);
-+/*********************************************************************//**
- Scans a table create SQL string and adds to the data dictionary
- the foreign key constraints declared in the string. This function
- should be called after the indexes for a table have been created.
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -216,6 +216,9 @@
- extern ibool srv_innodb_status;
-
- extern unsigned long long srv_stats_sample_pages;
-+extern ulint srv_stats_auto_update;
-+extern ulint srv_stats_update_need_lock;
-+extern ibool srv_use_sys_stats_table;
-
- extern ibool srv_use_doublewrite_buf;
- extern ibool srv_use_checksums;
---- a/storage/innobase/que/que0que.c
-+++ b/storage/innobase/que/que0que.c
-@@ -621,11 +621,21 @@
-
- que_graph_free_recursive(cre_ind->ind_def);
- que_graph_free_recursive(cre_ind->field_def);
-+ if (srv_use_sys_stats_table)
-+ que_graph_free_recursive(cre_ind->stats_def);
- que_graph_free_recursive(cre_ind->commit_node);
-
- mem_heap_free(cre_ind->heap);
-
- break;
-+ case QUE_NODE_INSERT_STATS:
-+ cre_ind = node;
-+
-+ que_graph_free_recursive(cre_ind->stats_def);
-+ que_graph_free_recursive(cre_ind->commit_node);
-+
-+ mem_heap_free(cre_ind->heap);
-+ break;
- case QUE_NODE_PROC:
- que_graph_free_stat_list(((proc_node_t*)node)->stat_list);
-
-@@ -1138,6 +1148,8 @@
- str = "CREATE TABLE";
- } else if (type == QUE_NODE_CREATE_INDEX) {
- str = "CREATE INDEX";
-+ } else if (type == QUE_NODE_INSERT_STATS) {
-+ str = "INSERT TO SYS_STATS";
- } else if (type == QUE_NODE_FOR) {
- str = "FOR LOOP";
- } else if (type == QUE_NODE_RETURN) {
-@@ -1255,6 +1267,8 @@
- thr = dict_create_table_step(thr);
- } else if (type == QUE_NODE_CREATE_INDEX) {
- thr = dict_create_index_step(thr);
-+ } else if (type == QUE_NODE_INSERT_STATS) {
-+ thr = dict_insert_stats_step(thr);
- } else if (type == QUE_NODE_ROW_PRINTF) {
- thr = row_printf_step(thr);
- } else {
---- a/storage/innobase/row/row0ins.c
-+++ b/storage/innobase/row/row0ins.c
-@@ -2018,6 +2018,8 @@
- }
-
- #ifdef UNIV_DEBUG
-+ if (!srv_use_sys_stats_table
-+ || index != UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes))
- {
- page_t* page = btr_cur_get_page(&cursor);
- rec_t* first_rec = page_rec_get_next(
---- a/storage/innobase/row/row0merge.c
-+++ b/storage/innobase/row/row0merge.c
-@@ -2019,6 +2019,8 @@
- "UPDATE SYS_INDEXES SET NAME=CONCAT('"
- TEMP_INDEX_PREFIX_STR "', NAME) WHERE ID = :indexid;\n"
- "COMMIT WORK;\n"
-+ /* Drop the statistics of the index. */
-+ "DELETE FROM SYS_STATS WHERE INDEX_ID = :indexid;\n"
- /* Drop the field definitions of the index. */
- "DELETE FROM SYS_FIELDS WHERE INDEX_ID = :indexid;\n"
- /* Drop the index definition and the B-tree. */
---- a/storage/innobase/row/row0mysql.c
-+++ b/storage/innobase/row/row0mysql.c
-@@ -922,6 +922,9 @@
-
- table->stat_modified_counter = counter + 1;
-
-+ if (!srv_stats_auto_update)
-+ return;
-+
- /* Calculate new statistics if 1 / 16 of table has been modified
- since the last time a statistics batch was run, or if
- stat_modified_counter > 2 000 000 000 (to avoid wrap-around).
-@@ -932,7 +935,7 @@
- || ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) {
-
- dict_update_statistics(table, FALSE /* update even if stats
-- are initialized */);
-+ are initialized */, TRUE);
- }
- }
-
-@@ -2077,6 +2080,71 @@
- }
-
- /*********************************************************************//**
-+*/
-+UNIV_INTERN
-+int
-+row_insert_stats_for_mysql(
-+/*=======================*/
-+ dict_index_t* index,
-+ trx_t* trx)
-+{
-+ ind_node_t* node;
-+ mem_heap_t* heap;
-+ que_thr_t* thr;
-+ ulint err;
-+
-+ //ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
-+
-+ trx->op_info = "try to insert rows to SYS_STATS";
-+
-+ trx_start_if_not_started(trx);
-+ trx->error_state = DB_SUCCESS;
-+
-+ heap = mem_heap_create(512);
-+
-+ node = ind_insert_stats_graph_create(index, heap);
-+
-+ thr = pars_complete_graph_for_exec(node, trx, heap);
-+
-+ ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
-+ que_run_threads(thr);
-+
-+ err = trx->error_state;
-+
-+ que_graph_free((que_t*) que_node_get_parent(thr));
-+
-+ trx->op_info = "";
-+
-+ return((int) err);
-+}
-+
-+/*********************************************************************//**
-+*/
-+UNIV_INTERN
-+int
-+row_delete_stats_for_mysql(
-+/*=============================*/
-+ dict_index_t* index,
-+ trx_t* trx)
-+{
-+ pars_info_t* info = pars_info_create();
-+
-+ trx->op_info = "delete rows from SYS_STATS";
-+
-+ trx_start_if_not_started(trx);
-+ trx->error_state = DB_SUCCESS;
-+
-+ pars_info_add_ull_literal(info, "indexid", index->id);
-+
-+ return((int) que_eval_sql(info,
-+ "PROCEDURE DELETE_STATISTICS_PROC () IS\n"
-+ "BEGIN\n"
-+ "DELETE FROM SYS_STATS WHERE INDEX_ID = :indexid;\n"
-+ "END;\n"
-+ , TRUE, trx));
-+}
-+
-+/*********************************************************************//**
- Scans a table create SQL string and adds to the data dictionary
- the foreign key constraints declared in the string. This function
- should be called after the indexes for a table have been created.
-@@ -3001,7 +3069,7 @@
- dict_table_autoinc_initialize(table, 1);
- dict_table_autoinc_unlock(table);
- dict_update_statistics(table, FALSE /* update even if stats are
-- initialized */);
-+ initialized */, TRUE);
-
- trx_commit_for_mysql(trx);
-
-@@ -3312,6 +3380,8 @@
- " IF (SQL % NOTFOUND) THEN\n"
- " found := 0;\n"
- " ELSE\n"
-+ " DELETE FROM SYS_STATS\n"
-+ " WHERE INDEX_ID = index_id;\n"
- " DELETE FROM SYS_FIELDS\n"
- " WHERE INDEX_ID = index_id;\n"
- " DELETE FROM SYS_INDEXES\n"
---- a/storage/innobase/row/row0row.c
-+++ b/storage/innobase/row/row0row.c
-@@ -364,6 +364,14 @@
-
- rec_len = rec_offs_n_fields(offsets);
-
-+ if (srv_use_sys_stats_table
-+ && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)) {
-+ if (rec_len < dict_index_get_n_fields(index)) {
-+ /* the new record should be extended */
-+ rec_len = dict_index_get_n_fields(index);
-+ }
-+ }
-+
- entry = dtuple_create(heap, rec_len);
-
- dtuple_set_n_fields_cmp(entry,
-@@ -375,6 +383,14 @@
- for (i = 0; i < rec_len; i++) {
-
- dfield = dtuple_get_nth_field(entry, i);
-+
-+ if (srv_use_sys_stats_table
-+ && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)
-+ && i >= rec_offs_n_fields(offsets)) {
-+ dfield_set_null(dfield);
-+ continue;
-+ }
-+
- field = rec_get_nth_field(rec, offsets, i, &len);
-
- dfield_set_data(dfield, field, len);
---- a/storage/innobase/row/row0upd.c
-+++ b/storage/innobase/row/row0upd.c
-@@ -439,6 +439,12 @@
- 0);
- }
-
-+ if (srv_use_sys_stats_table
-+ && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)
-+ && upd_field->field_no >= rec_offs_n_fields(offsets)) {
-+ return(TRUE);
-+ }
-+
- old_len = rec_offs_nth_size(offsets, upd_field->field_no);
-
- if (rec_offs_comp(offsets)
-@@ -879,6 +885,18 @@
-
- for (i = 0; i < dtuple_get_n_fields(entry); i++) {
-
-+ if (srv_use_sys_stats_table
-+ && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)
-+ && i >= rec_offs_n_fields(offsets)) {
-+ dfield = dtuple_get_nth_field(entry, i);
-+
-+ upd_field = upd_get_nth_field(update, n_diff);
-+ dfield_copy(&(upd_field->new_val), dfield);
-+ upd_field_set_field_no(upd_field, i, index, trx);
-+ n_diff++;
-+ goto skip_compare;
-+ }
-+
- data = rec_get_nth_field(rec, offsets, i, &len);
-
- dfield = dtuple_get_nth_field(entry, i);
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -400,6 +400,9 @@
- /* When estimating number of different key values in an index, sample
- this many index pages */
- UNIV_INTERN unsigned long long srv_stats_sample_pages = 8;
-+UNIV_INTERN ulint srv_stats_auto_update = 1;
-+UNIV_INTERN ulint srv_stats_update_need_lock = 1;
-+UNIV_INTERN ibool srv_use_sys_stats_table = FALSE;
-
- UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE;
- UNIV_INTERN ibool srv_use_checksums = TRUE;
---- a/storage/innobase/trx/trx0rec.c
-+++ b/storage/innobase/trx/trx0rec.c
-@@ -669,14 +669,27 @@
- /* Save to the undo log the old values of the columns to be updated. */
-
- if (update) {
-+ ulint extended = 0;
-+
- if (trx_undo_left(undo_page, ptr) < 5) {
-
- return(0);
- }
-
-- ptr += mach_write_compressed(ptr, upd_get_n_fields(update));
-+ if (srv_use_sys_stats_table
-+ && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)) {
-+ for (i = 0; i < upd_get_n_fields(update); i++) {
-+ ulint pos = upd_get_nth_field(update, i)->field_no;
-+
-+ if (pos >= rec_offs_n_fields(offsets)) {
-+ extended++;
-+ }
-+ }
-+ }
-+
-+ ptr += mach_write_compressed(ptr, upd_get_n_fields(update) - extended);
-
-- for (i = 0; i < upd_get_n_fields(update); i++) {
-+ for (i = 0; i < upd_get_n_fields(update) - extended; i++) {
-
- ulint pos = upd_get_nth_field(update, i)->field_no;
-
---- /dev/null
-+++ b/mysql-test/r/percona_innodb_use_sys_stats_table.result
-@@ -0,0 +1,3 @@
-+show variables like 'innodb_use_sys_stats%';
-+Variable_name Value
-+innodb_use_sys_stats_table ON
---- /dev/null
-+++ b/mysql-test/t/percona_innodb_use_sys_stats_table-master.opt
-@@ -0,0 +1 @@
-+--innodb_use_sys_stats_table
---- /dev/null
-+++ b/mysql-test/t/percona_innodb_use_sys_stats_table.test
-@@ -0,0 +1,2 @@
-+--source include/have_innodb.inc
-+show variables like 'innodb_use_sys_stats%';
+++ /dev/null
-# name : innodb_thread_concurrency_timer_based.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -148,6 +148,7 @@
- static ulong innobase_write_io_threads;
- static long innobase_buffer_pool_instances = 1;
-
-+static my_bool innobase_thread_concurrency_timer_based;
- static long long innobase_buffer_pool_size, innobase_log_file_size;
-
- /** Percentage of the buffer pool to reserve for 'old' blocks.
-@@ -2577,6 +2578,9 @@
- srv_n_log_files = (ulint) innobase_log_files_in_group;
- srv_log_file_size = (ulint) innobase_log_file_size;
-
-+ srv_thread_concurrency_timer_based =
-+ (ibool) innobase_thread_concurrency_timer_based;
-+
- #ifdef UNIV_LOG_ARCHIVE
- srv_log_archive_on = (ulint) innobase_log_archive;
- #endif /* UNIV_LOG_ARCHIVE */
-@@ -11601,6 +11605,12 @@
- "Maximum delay between polling for a spin lock (6 by default)",
- NULL, NULL, 6L, 0L, ~0L, 0);
-
-+static MYSQL_SYSVAR_BOOL(thread_concurrency_timer_based,
-+ innobase_thread_concurrency_timer_based,
-+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
-+ "Use InnoDB timer based concurrency throttling. ",
-+ NULL, NULL, FALSE);
-+
- static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
- PLUGIN_VAR_RQCMDARG,
- "Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.",
-@@ -11859,6 +11869,7 @@
- MYSQL_SYSVAR(spin_wait_delay),
- MYSQL_SYSVAR(table_locks),
- MYSQL_SYSVAR(thread_concurrency),
-+ MYSQL_SYSVAR(thread_concurrency_timer_based),
- MYSQL_SYSVAR(thread_sleep_delay),
- MYSQL_SYSVAR(autoinc_lock_mode),
- MYSQL_SYSVAR(show_verbose_locks),
---- a/storage/innobase/include/srv0srv.h
-+++ b/storage/innobase/include/srv0srv.h
-@@ -165,6 +165,8 @@
- extern ulint srv_mem_pool_size;
- extern ulint srv_lock_table_size;
-
-+extern ibool srv_thread_concurrency_timer_based;
-+
- extern ulint srv_n_file_io_threads;
- extern my_bool srv_random_read_ahead;
- extern ulong srv_read_ahead_threshold;
---- a/storage/innobase/srv/srv0srv.c
-+++ b/storage/innobase/srv/srv0srv.c
-@@ -349,6 +349,7 @@
- computer. Bigger computers need bigger values. Value 0 will disable the
- concurrency check. */
-
-+UNIV_INTERN ibool srv_thread_concurrency_timer_based = FALSE;
- UNIV_INTERN ulong srv_thread_concurrency = 0;
-
- /* this mutex protects srv_conc data structures */
-@@ -1148,6 +1149,75 @@
- /*********************************************************************//**
- Puts an OS thread to wait if there are too many concurrent threads
- (>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */
-+
-+#ifdef HAVE_ATOMIC_BUILTINS
-+static void
-+enter_innodb_with_tickets(trx_t* trx)
-+{
-+ trx->declared_to_be_inside_innodb = TRUE;
-+ trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER;
-+ return;
-+}
-+
-+static void
-+srv_conc_enter_innodb_timer_based(trx_t* trx)
-+{
-+ lint conc_n_threads;
-+ ibool has_yielded = FALSE;
-+ ulint has_slept = 0;
-+
-+ if (trx->declared_to_be_inside_innodb) {
-+ ut_print_timestamp(stderr);
-+ fputs(
-+" InnoDB: Error: trying to declare trx to enter InnoDB, but\n"
-+"InnoDB: it already is declared.\n", stderr);
-+ trx_print(stderr, trx, 0);
-+ putc('\n', stderr);
-+ }
-+retry:
-+ if (srv_conc_n_threads < (lint) srv_thread_concurrency) {
-+ conc_n_threads = os_atomic_increment_lint(&srv_conc_n_threads, 1);
-+ if (conc_n_threads <= (lint) srv_thread_concurrency) {
-+ enter_innodb_with_tickets(trx);
-+ return;
-+ }
-+ (void) os_atomic_increment_lint(&srv_conc_n_threads, -1);
-+ }
-+ if (!has_yielded)
-+ {
-+ has_yielded = TRUE;
-+ os_thread_yield();
-+ goto retry;
-+ }
-+ if (trx->has_search_latch
-+ || NULL != UT_LIST_GET_FIRST(trx->trx_locks)) {
-+
-+ conc_n_threads = os_atomic_increment_lint(&srv_conc_n_threads, 1);
-+ enter_innodb_with_tickets(trx);
-+ return;
-+ }
-+ if (has_slept < 2)
-+ {
-+ trx->op_info = "sleeping before entering InnoDB";
-+ os_thread_sleep(10000);
-+ trx->op_info = "";
-+ has_slept++;
-+ }
-+ conc_n_threads = os_atomic_increment_lint(&srv_conc_n_threads, 1);
-+ enter_innodb_with_tickets(trx);
-+ return;
-+}
-+
-+static void
-+srv_conc_exit_innodb_timer_based(trx_t* trx)
-+{
-+ (void) os_atomic_increment_lint(&srv_conc_n_threads, -1);
-+ trx->declared_to_be_inside_innodb = FALSE;
-+ trx->n_tickets_to_enter_innodb = 0;
-+ return;
-+}
-+#endif
-+
- UNIV_INTERN
- void
- srv_conc_enter_innodb(
-@@ -1182,6 +1252,13 @@
- return;
- }
-
-+#ifdef HAVE_ATOMIC_BUILTINS
-+ if (srv_thread_concurrency_timer_based) {
-+ srv_conc_enter_innodb_timer_based(trx);
-+ return;
-+ }
-+#endif
-+
- os_fast_mutex_lock(&srv_conc_mutex);
- retry:
- if (trx->declared_to_be_inside_innodb) {
-@@ -1335,6 +1412,14 @@
- }
-
- ut_ad(srv_conc_n_threads >= 0);
-+#ifdef HAVE_ATOMIC_BUILTINS
-+ if (srv_thread_concurrency_timer_based) {
-+ (void) os_atomic_increment_lint(&srv_conc_n_threads, 1);
-+ trx->declared_to_be_inside_innodb = TRUE;
-+ trx->n_tickets_to_enter_innodb = 1;
-+ return;
-+ }
-+#endif
-
- os_fast_mutex_lock(&srv_conc_mutex);
-
-@@ -1368,6 +1453,13 @@
- return;
- }
-
-+#ifdef HAVE_ATOMIC_BUILTINS
-+ if (srv_thread_concurrency_timer_based) {
-+ srv_conc_exit_innodb_timer_based(trx);
-+ return;
-+ }
-+#endif
-+
- os_fast_mutex_lock(&srv_conc_mutex);
-
- ut_ad(srv_conc_n_threads > 0);
+++ /dev/null
-# name : log_connection_error.patch
-# introduced : 12
-# maintainer : Oleg
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- /dev/null
-+++ b/patch_info/log_connection_error.patch
-@@ -0,0 +1,6 @@
-+File=log_connection_error.patch
-+Name=logging abandoned connections
-+Version=1.0
-+Author=Percona <info@percona.com>
-+License=GPL
-+Comment=
---- a/sql/mysqld.cc
-+++ b/sql/mysqld.cc
-@@ -4959,6 +4959,10 @@
-
- DBUG_PRINT("error",("Too many connections"));
- close_connection(thd, ER_CON_COUNT_ERROR);
-+ if (global_system_variables.log_warnings)
-+ {
-+ sql_print_warning("%s", ER_DEFAULT(ER_CON_COUNT_ERROR));
-+ }
- delete thd;
- DBUG_VOID_RETURN;
- }
-@@ -5342,6 +5346,10 @@
- if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) ||
- my_net_init(&thd->net, thd->net.vio))
- {
-+ if (global_system_variables.log_warnings)
-+ {
-+ sql_print_warning("%s", ER_DEFAULT(ER_OUT_OF_RESOURCES));
-+ }
- close_connection(thd, ER_OUT_OF_RESOURCES);
- delete thd;
- continue;
-@@ -5537,6 +5545,10 @@
- event_conn_closed)) ||
- my_net_init(&thd->net, thd->net.vio))
- {
-+ if (global_system_variables.log_warnings)
-+ {
-+ sql_print_warning("%s", ER_DEFAULT(ER_OUT_OF_RESOURCES));
-+ }
- close_connection(thd, ER_OUT_OF_RESOURCES);
- errmsg= 0;
- goto errorconn;
---- /dev/null
-+++ b/mysql-test/r/percona_log_connection_error.result
-@@ -0,0 +1,16 @@
-+SET @old_max_connections = @@max_connections;
-+SET @old_log_warnings = @@log_warnings;
-+SET GLOBAL max_connections=2;
-+SET GLOBAL LOG_WARNINGS = 0;
-+connect(localhost,root,,test,port,socket);
-+ERROR HY000: Too many connections
-+SET GLOBAL LOG_WARNINGS = 1;
-+connect(localhost,root,,test,port,socket);
-+ERROR HY000: Too many connections
-+SET GLOBAL LOG_WARNINGS = 0;
-+connect(localhost,root,,test,port,socket);
-+ERROR HY000: Too many connections
-+SET GLOBAL max_connections = @old_max_connections;
-+SET GLOBAL log_warnings = @old_log_warnings;
-+[log_grep.inc] file: percona.log_connection_error.err pattern: Too many connections
-+[log_grep.inc] lines: 1
---- /dev/null
-+++ b/mysql-test/t/percona_log_connection_error-master.opt
-@@ -0,0 +1 @@
-+--log-error
---- /dev/null
-+++ b/mysql-test/t/percona_log_connection_error.test
-@@ -0,0 +1,54 @@
-+--source include/not_embedded.inc
-+
-+connect (main,localhost,root,,);
-+connection main;
-+SET @old_max_connections = @@max_connections;
-+SET @old_log_warnings = @@log_warnings;
-+SET GLOBAL max_connections=2;
-+let $port=`SELECT Variable_value FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE Variable_name LIKE 'port'`;
-+let $socket=`SELECT Variable_value FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE Variable_name LIKE 'socket'`;
-+
-+SET GLOBAL LOG_WARNINGS = 0;
-+--connect (conn0,localhost,root,,)
-+connection conn0;
-+replace_result $port port $socket socket;
-+--error 1040
-+--connect(conn1,localhost,root,,)
-+disconnect conn0;
-+SLEEP 0.1; # tsarev: hack, but i don't know (and didn't find) how right
-+
-+connection main;
-+SET GLOBAL LOG_WARNINGS = 1;
-+--connect (conn1,localhost,root,,)
-+replace_result $port port $socket socket;
-+--error 1040
-+--connect (conn0,localhost,root,,)
-+disconnect conn1;
-+SLEEP 0.1; # tsarev: hack, but i don't know (and didn't find) how right
-+
-+connection main;
-+SET GLOBAL LOG_WARNINGS = 0;
-+--connect (conn0,localhost,root,,)
-+replace_result $port port $socket socket;
-+--error 1040
-+--connect(conn1,localhost,root,,)
-+disconnect conn0;
-+SLEEP 0.1; # tsarev: hack, but i don't know (and didn't find) how right
-+
-+connection main;
-+SET GLOBAL max_connections = @old_max_connections;
-+SET GLOBAL log_warnings = @old_log_warnings;
-+let $log_error_= `SELECT @@GLOBAL.log_error`;
-+if(!`select LENGTH('$log_error_')`)
-+{
-+ # MySQL Server on windows is started with --console and thus
-+ # does not know the location of its .err log, use default location
-+ let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err;
-+}
-+
-+--let log_error=$log_error_
-+--let log_file=percona.log_connection_error.err
-+--let log_file_full_path=$log_error
-+--let grep_pattern= Too many connections
-+--source include/log_grep.inc
-+
+++ /dev/null
-# name : log_warnings_suppress.patch
-# introduced : 11 or before
-# maintainer : Oleg
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- /dev/null
-+++ b/patch_info/log_warnings_suppress.patch
-@@ -0,0 +1,9 @@
-+File=log_warnings_suppress.patch
-+Name=Disable log warnings for enumerated warnings (old name:suppress_log_warning_1592.patch)
-+Version=1.0
-+Author=Percona <info@percona.com>
-+License=GPL
-+Comment=
-+Changelog
-+2011-01-05 rename patch suppress_log_warning_1592.patch to log_warnings_silence.patch. Also remove boolean system variable "suppress_log_warning_1592" and add set varbile "log_warnings_silence" (possible values: 1592)
-+2011-02-21 rename patch log_warning_silence.patch to log_warnings_suppress.patch. Also rename variable "log_warning_silence" to "log_warning_suppress".
---- a/sql/mysqld.cc
-+++ b/sql/mysqld.cc
-@@ -632,6 +632,8 @@
- SHOW_COMP_OPTION have_crypt, have_compress;
- SHOW_COMP_OPTION have_profiling;
-
-+ulonglong opt_log_warnings_suppress= 0;
-+
- /* Thread specific variables */
-
- pthread_key(MEM_ROOT**,THR_MALLOC);
---- a/sql/mysqld.h
-+++ b/sql/mysqld.h
-@@ -229,6 +229,8 @@
- extern TYPELIB thread_handling_typelib;
- extern my_decimal decimal_zero;
-
-+extern ulonglong opt_log_warnings_suppress;
-+
- /*
- THR_MALLOC is a key which will be used to set/get MEM_ROOT** for a thread,
- using my_pthread_setspecific_ptr()/my_thread_getspecific_ptr().
---- a/sql/sql_class.cc
-+++ b/sql/sql_class.cc
-@@ -5029,7 +5029,7 @@
- ER_BINLOG_UNSAFE_STATEMENT,
- ER(ER_BINLOG_UNSAFE_STATEMENT),
- ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));
-- if (global_system_variables.log_warnings)
-+ if (global_system_variables.log_warnings && ((opt_log_warnings_suppress & (ULL(1) << log_warnings_suppress_1592)) == 0))
- {
- char buf[MYSQL_ERRMSG_SIZE * 2];
- sprintf(buf, ER(ER_BINLOG_UNSAFE_STATEMENT),
---- a/sql/sql_class.h
-+++ b/sql/sql_class.h
-@@ -87,6 +87,7 @@
- SLOG_F_TMP_TABLE, SLOG_F_TMP_DISK, SLOG_F_FILESORT,
- SLOG_F_FILESORT_DISK
- };
-+enum enum_log_warnings_suppress { log_warnings_suppress_1592 };
- enum enum_slave_exec_mode { SLAVE_EXEC_MODE_STRICT,
- SLAVE_EXEC_MODE_IDEMPOTENT,
- SLAVE_EXEC_MODE_LAST_BIT};
---- a/sql/sys_vars.cc
-+++ b/sql/sys_vars.cc
-@@ -1572,6 +1572,15 @@
- READ_ONLY GLOBAL_VAR(mysqld_port), CMD_LINE(REQUIRED_ARG, 'P'),
- VALID_RANGE(0, UINT_MAX32), DEFAULT(0), BLOCK_SIZE(1));
-
-+const char *log_warnings_suppress_name[]= { "1592" };
-+static Sys_var_set Sys_log_warnings_suppress(
-+ "log_warnings_suppress",
-+ "disable logging of enumerated warnings: "
-+ "1592: unsafe statements for binary logging; "
-+ "possible values : [1592]",
-+ GLOBAL_VAR(opt_log_warnings_suppress), CMD_LINE(REQUIRED_ARG),
-+ log_warnings_suppress_name, DEFAULT(0));
-+
- static Sys_var_ulong Sys_preload_buff_size(
- "preload_buffer_size",
- "The size of the buffer that is allocated when preloading indexes",
---- /dev/null
-+++ b/mysql-test/r/percona_log_warnings_suppress.result
-@@ -0,0 +1,31 @@
-+SET @old_log_warnings = @@log_warnings;
-+SET @old_log_warnings_suppress = @@log_warnings_suppress;
-+DROP TABLE IF EXISTS t1;
-+CREATE TABLE t1 (a VARCHAR(36), b VARCHAR(20));
-+SET GLOBAL log_warnings_suppress='';
-+SET GLOBAL LOG_WARNINGS=0;
-+SHOW GLOBAL VARIABLES LIKE 'log_warnings_suppress';
-+Variable_name Value
-+log_warnings_suppress
-+INSERT INTO t1 VALUES(UUID(), 'suppress_1592');
-+Warnings:
-+Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave.
-+SET GLOBAL LOG_WARNINGS=1;
-+INSERT INTO t1 VALUES(UUID(), 'suppress_1592');
-+Warnings:
-+Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave.
-+SET GLOBAL log_warnings_suppress='1592';
-+SET GLOBAL LOG_WARNINGS=0;
-+INSERT INTO t1 VALUES(UUID(), 'suppress_1592');
-+Warnings:
-+Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave.
-+SET GLOBAL LOG_WARNINGS=1;
-+INSERT INTO t1 VALUES(UUID(), 'suppress_1592');
-+Warnings:
-+Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave.
-+DROP TABLE t1;
-+SET GLOBAL log_warnings = @old_log_warnings;
-+SET GLOBAL log_warnings_suppress = @old_log_warnings_suppress;
-+# Count the number of times the "Unsafe" message was printed
-+# to the error log.
-+Occurrences: 1
---- /dev/null
-+++ b/mysql-test/t/percona_log_warnings_suppress-master.opt
-@@ -0,0 +1 @@
-+--log-error
---- /dev/null
-+++ b/mysql-test/t/percona_log_warnings_suppress.test
-@@ -0,0 +1,47 @@
-+-- source include/have_log_bin.inc
-+-- source include/have_binlog_format_statement.inc
-+
-+SET @old_log_warnings = @@log_warnings;
-+SET @old_log_warnings_suppress = @@log_warnings_suppress;
-+
-+--disable_warnings
-+DROP TABLE IF EXISTS t1;
-+--enable_warnings
-+CREATE TABLE t1 (a VARCHAR(36), b VARCHAR(20));
-+SET GLOBAL log_warnings_suppress='';
-+SET GLOBAL LOG_WARNINGS=0;
-+SHOW GLOBAL VARIABLES LIKE 'log_warnings_suppress';
-+INSERT INTO t1 VALUES(UUID(), 'suppress_1592');
-+SET GLOBAL LOG_WARNINGS=1;
-+INSERT INTO t1 VALUES(UUID(), 'suppress_1592');
-+SET GLOBAL log_warnings_suppress='1592';
-+SET GLOBAL LOG_WARNINGS=0;
-+INSERT INTO t1 VALUES(UUID(), 'suppress_1592');
-+SET GLOBAL LOG_WARNINGS=1;
-+INSERT INTO t1 VALUES(UUID(), 'suppress_1592');
-+DROP TABLE t1;
-+
-+SET GLOBAL log_warnings = @old_log_warnings;
-+SET GLOBAL log_warnings_suppress = @old_log_warnings_suppress;
-+
-+let $log_error_= `SELECT @@GLOBAL.log_error`;
-+if(!`select LENGTH('$log_error_')`)
-+{
-+ # MySQL Server on windows is started with --console and thus
-+ # does not know the location of its .err log, use default location
-+ let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err;
-+}
-+# Assign env variable LOG_ERROR
-+let LOG_ERROR=$log_error_;
-+
-+--echo # Count the number of times the "Unsafe" message was printed
-+--echo # to the error log.
-+
-+perl;
-+ use strict;
-+ my $log_error= $ENV{'LOG_ERROR'} or die "LOG_ERROR not set";
-+ open(FILE, "$log_error") or die("Unable to open $log_error: $!\n");
-+ my $count = () = grep(/suppress_1592/g,<FILE>);
-+ print "Occurrences: $count\n";
-+ close(FILE);
-+EOF
---- a/mysql-test/r/mysqld--help-notwin.result
-+++ b/mysql-test/r/mysqld--help-notwin.result
-@@ -281,6 +281,9 @@
- --log-tc-size=# Size of transaction coordinator log.
- -W, --log-warnings[=#]
- Log some not critical warnings to the log file
-+ --log-warnings-suppress=name
-+ disable logging of enumerated warnings: 1592: unsafe
-+ statements for binary logging; possible values : [1592]
- --long-query-time=# Log all queries that have taken more than long_query_time
- seconds to execute to file. The argument will be treated
- as a decimal value with microsecond precision
-@@ -865,6 +868,7 @@
- log-tc tc.log
- log-tc-size 24576
- log-warnings 1
-+log-warnings-suppress
- long-query-time 10
- low-priority-updates FALSE
- lower-case-table-names 1
+++ /dev/null
---- a/include/heap.h
-+++ b/include/heap.h
-@@ -34,7 +34,17 @@
- #include "my_compare.h"
- #include "my_tree.h"
-
-- /* defines used by heap-funktions */
-+/* Define index limits to be identical to MyISAM ones for compatibility. */
-+
-+#if MAX_INDEXES > HA_MAX_POSSIBLE_KEY
-+#define HP_MAX_KEY HA_MAX_POSSIBLE_KEY /* Max allowed keys */
-+#else
-+#define HP_MAX_KEY MAX_INDEXES /* Max allowed keys */
-+#endif
-+
-+#define HP_MAX_KEY_LENGTH 1000 /* Max length in bytes */
-+
-+/* defines used by heap-funktions */
-
- #define HP_MAX_LEVELS 4 /* 128^5 records is enough */
- #define HP_PTRS_IN_NOD 128
-@@ -131,22 +141,58 @@
- uint (*get_key_length)(struct st_hp_keydef *keydef, const uchar *key);
- } HP_KEYDEF;
-
--typedef struct st_heap_share
-+typedef struct st_heap_columndef /* column information */
-+{
-+ int16 type; /* en_fieldtype */
-+ uint32 length; /* length of field */
-+ uint32 offset; /* Offset to position in row */
-+ uint8 null_bit; /* If column may be 0 */
-+ uint16 null_pos; /* position for null marker */
-+ uint8 length_bytes; /* length of the size, 1 o 2 bytes */
-+} HP_COLUMNDEF;
-+
-+typedef struct st_heap_dataspace /* control data for data space */
- {
- HP_BLOCK block;
-+ /* Total chunks ever allocated in this dataspace */
-+ uint chunk_count;
-+ uint del_chunk_count; /* Deleted chunks count */
-+ uchar *del_link; /* Link to last deleted chunk */
-+ uint chunk_length; /* Total length of one chunk */
-+ /* Length of payload that will be placed into one chunk */
-+ uint chunk_dataspace_length;
-+ /* Offset of the status flag relative to the chunk start */
-+ uint offset_status;
-+ /* Offset of the linking pointer relative to the chunk start */
-+ uint offset_link;
-+ /* Test whether records have variable size and so "next" pointer */
-+ uint is_variable_size;
-+ /* Total size allocated within this data space */
-+ ulonglong total_data_length;
-+} HP_DATASPACE;
-+
-+typedef struct st_heap_share
-+{
- HP_KEYDEF *keydef;
-+ HP_COLUMNDEF *column_defs;
-+ /* Describes "block", which contains actual records */
-+ HP_DATASPACE recordspace;
- ulong min_records,max_records; /* Params to open */
-- ulonglong data_length,index_length,max_table_size;
-+ ulonglong index_length, max_table_size;
- uint key_stat_version; /* version to indicate insert/delete */
-- uint records; /* records */
-- uint blength; /* records rounded up to 2^n */
-- uint deleted; /* Deleted records in database */
-- uint reclength; /* Length of one record */
-+ uint records; /* Actual record (row) count */
-+ uint blength; /* used_chunk_count rounded up to 2^n */
-+ /*
-+ Length of record's fixed part, which contains keys and always fits into the
-+ first chunk.
-+ */
-+ uint fixed_data_length;
-+ uint fixed_column_count; /* Number of columns stored in fixed_data_length */
- uint changed;
- uint keys,max_key_length;
-+ uint column_count;
- uint currently_disabled_keys; /* saved value from "keys" when disabled */
- uint open_count;
-- uchar *del_link; /* Link to next block with del. rec */
- char * name; /* Name of "memory-file" */
- time_t create_time;
- THR_LOCK lock;
-@@ -156,6 +202,7 @@
- uint auto_key;
- uint auto_key_type; /* real type of the auto key segment */
- ulonglong auto_increment;
-+ uint blobs; /* Number of blobs in table */
- } HP_SHARE;
-
- struct st_hp_hash_info;
-@@ -165,7 +212,7 @@
- HP_SHARE *s;
- uchar *current_ptr;
- struct st_hp_hash_info *current_hash_ptr;
-- ulong current_record,next_block;
-+ ulong current_record;
- int lastinx,errkey;
- int mode; /* Mode of file (READONLY..) */
- uint opt_flag,update;
-@@ -178,6 +225,9 @@
- my_bool implicit_emptied;
- THR_LOCK_DATA lock;
- LIST open_list;
-+ uchar *blob_buffer; /* Temporary buffer used to return BLOB values */
-+ uint blob_size; /* Current blob_buffer size */
-+ uint blob_offset; /* Current offset in blob_buffer */
- } HP_INFO;
-
-
-@@ -199,6 +249,14 @@
- open_count to 1. Is only looked at if not internal_table.
- */
- my_bool pin_share;
-+ uint columns;
-+ HP_COLUMNDEF *columndef;
-+ uint fixed_key_fieldnr;
-+ uint fixed_data_size;
-+ uint keys_memory_size;
-+ uint max_chunk_size;
-+ uint is_dynamic;
-+ uint blobs;
- } HP_CREATE_INFO;
-
- /* Prototypes for heap-functions */
-@@ -215,9 +273,8 @@
- extern int heap_scan(register HP_INFO *info, uchar *record);
- extern int heap_delete(HP_INFO *info,const uchar *buff);
- extern int heap_info(HP_INFO *info,HEAPINFO *x,int flag);
--extern int heap_create(const char *name,
-- HP_CREATE_INFO *create_info, HP_SHARE **share,
-- my_bool *created_new_share);
-+extern int heap_create(const char *name, HP_CREATE_INFO *create_info,
-+ HP_SHARE **res, my_bool *created_new_share);
- extern int heap_delete_table(const char *name);
- extern void heap_drop_table(HP_INFO *info);
- extern int heap_extra(HP_INFO *info,enum ha_extra_function function);
---- a/mysql-test/r/create.result
-+++ b/mysql-test/r/create.result
-@@ -33,10 +33,7 @@
- create table t1 (b char(0) not null, index(b));
- ERROR 42000: The used storage engine can't index column 'b'
- create table t1 (a int not null,b text) engine=heap;
--ERROR 42000: The used table type doesn't support BLOB/TEXT columns
- drop table if exists t1;
--Warnings:
--Note 1051 Unknown table 't1'
- create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) engine=heap;
- ERROR 42000: Incorrect table definition; there can be only one auto column and it must be defined as a key
- create table not_existing_database.test (a int);
---- a/mysql-test/r/ctype_utf8mb4_heap.result
-+++ b/mysql-test/r/ctype_utf8mb4_heap.result
-@@ -1124,6 +1124,8 @@
- a varchar(255) NOT NULL default '',
- KEY a (a)
- ) ENGINE=heap DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;
-+Warnings:
-+Warning 1071 Specified key was too long; max key length is 1000 bytes
- insert into t1 values (_utf8mb4 0xe880bd);
- insert into t1 values (_utf8mb4 0x5b);
- select hex(a) from t1;
-@@ -1162,6 +1164,8 @@
- Warnings:
- Note 1051 Unknown table 't1'
- CREATE TABLE t1(a VARCHAR(255), KEY(a)) ENGINE=heap DEFAULT CHARSET=utf8mb4;
-+Warnings:
-+Warning 1071 Specified key was too long; max key length is 1000 bytes
- INSERT INTO t1 VALUES('uuABCDEFGHIGKLMNOPRSTUVWXYZ̈bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb');
- INSERT INTO t1 VALUES('uu');
- check table t1;
---- a/mysql-test/t/create.test
-+++ b/mysql-test/t/create.test
-@@ -33,7 +33,7 @@
- drop table if exists t1,t2;
- --error 1167
- create table t1 (b char(0) not null, index(b));
----error 1163
-+# BLOB/TEXT fields are now supported by HEAP
- create table t1 (a int not null,b text) engine=heap;
- drop table if exists t1;
-
---- a/storage/heap/CMakeLists.txt
-+++ b/storage/heap/CMakeLists.txt
-@@ -20,6 +20,7 @@
- ha_heap.cc
- hp_delete.c hp_extra.c hp_hash.c hp_info.c hp_open.c hp_panic.c
- hp_rename.c hp_rfirst.c hp_rkey.c hp_rlast.c hp_rnext.c hp_rprev.c
-+ hp_dspace.c hp_record.c
- hp_rrnd.c hp_rsame.c hp_scan.c hp_static.c hp_update.c hp_write.c)
-
- MYSQL_ADD_PLUGIN(heap ${HEAP_SOURCES} STORAGE_ENGINE MANDATORY RECOMPILE_FOR_EMBEDDED)
---- a/storage/heap/_check.c
-+++ b/storage/heap/_check.c
-@@ -43,7 +43,7 @@
- {
- int error;
- uint key;
-- ulong records=0, deleted=0, pos, next_block;
-+ ulong records= 0, deleted= 0, chunk_count= 0, pos, next_block;
- HP_SHARE *share=info->s;
- HP_INFO save_info= *info; /* Needed because scan_init */
- DBUG_ENTER("heap_check_heap");
-@@ -64,31 +64,55 @@
- {
- if (pos < next_block)
- {
-- info->current_ptr+= share->block.recbuffer;
-+ info->current_ptr+= share->recordspace.block.recbuffer;
- }
- else
- {
-- next_block+= share->block.records_in_block;
-- if (next_block >= share->records+share->deleted)
-+ next_block+= share->recordspace.block.records_in_block;
-+ if (next_block >= share->recordspace.chunk_count)
- {
-- next_block= share->records+share->deleted;
-- if (pos >= next_block)
-- break; /* End of file */
-+ next_block= share->recordspace.chunk_count;
-+ if (pos >= next_block)
-+ break; /* End of file */
- }
- }
- hp_find_record(info,pos);
-
-- if (!info->current_ptr[share->reclength])
-+ switch (get_chunk_status(&share->recordspace, info->current_ptr)) {
-+ case CHUNK_STATUS_DELETED:
- deleted++;
-- else
-+ chunk_count++;
-+ break;
-+ case CHUNK_STATUS_ACTIVE:
- records++;
-+ chunk_count++;
-+ break;
-+ case CHUNK_STATUS_LINKED:
-+ chunk_count++;
-+ break;
-+ default:
-+ DBUG_PRINT("error",
-+ ("Unknown record status: Record: 0x%lx Status %lu",
-+ (long) info->current_ptr,
-+ (ulong) get_chunk_status(&share->recordspace,
-+ info->current_ptr)));
-+ error|= 1;
-+ break;
-+ }
- }
-
-- if (records != share->records || deleted != share->deleted)
-- {
-- DBUG_PRINT("error",("Found rows: %lu (%lu) deleted %lu (%lu)",
-- records, (ulong) share->records,
-- deleted, (ulong) share->deleted));
-+ /* TODO: verify linked chunks (no orphans, no cycles, no bad links) */
-+
-+ if (records != share->records ||
-+ chunk_count != share->recordspace.chunk_count ||
-+ deleted != share->recordspace.del_chunk_count)
-+ {
-+ DBUG_PRINT("error",
-+ ("Found rows: %lu (%lu) total chunks %lu (%lu) deleted chunks "
-+ "%lu (%lu)",
-+ records, (ulong) share->records,
-+ chunk_count, (ulong) share->recordspace.chunk_count,
-+ deleted, (ulong) share->recordspace.del_chunk_count));
- error= 1;
- }
- *info= save_info;
-@@ -177,7 +201,7 @@
- do
- {
- memcpy(&recpos, key + (*keydef->get_key_length)(keydef,key), sizeof(uchar*));
-- key_length= hp_rb_make_key(keydef, info->recbuf, recpos, 0);
-+ key_length= hp_rb_make_key(keydef, info->recbuf, recpos, 0, TRUE);
- if (ha_key_cmp(keydef->seg, (uchar*) info->recbuf, (uchar*) key,
- key_length, SEARCH_FIND | SEARCH_SAME, not_used))
- {
---- a/storage/heap/_rectest.c
-+++ b/storage/heap/_rectest.c
-@@ -22,7 +22,9 @@
- {
- DBUG_ENTER("hp_rectest");
-
-- if (memcmp(info->current_ptr,old,(size_t) info->s->reclength))
-+ if (hp_process_record_data_to_chunkset(info->s, old,
-+ info->current_ptr,
-+ 1))
- {
- DBUG_RETURN((my_errno=HA_ERR_RECORD_CHANGED)); /* Record have changed */
- }
---- a/storage/heap/ha_heap.cc
-+++ b/storage/heap/ha_heap.cc
-@@ -114,6 +114,7 @@
-
- rc= heap_create(name, &create_info, &internal_share, &created_new_share);
- my_free(create_info.keydef);
-+ my_free(create_info.columndef);
- if (rc)
- goto end;
-
-@@ -195,6 +196,12 @@
- {
- if (table->key_info[i].algorithm == HA_KEY_ALG_BTREE)
- btree_keys.set_bit(i);
-+ /*
-+ Reset per-key block size specification so they are not shown
-+ in SHOW CREATE TABLE.
-+ */
-+ table->key_info[i].block_size= 0;
-+ table->key_info[i].flags&= ~HA_USES_BLOCK_SIZE;
- }
- }
-
-@@ -429,6 +436,13 @@
- return 0;
- }
-
-+enum row_type ha_heap::get_row_type() const
-+{
-+ if (file->s->recordspace.is_variable_size)
-+ return ROW_TYPE_DYNAMIC;
-+
-+ return ROW_TYPE_FIXED;
-+}
-
- int ha_heap::extra(enum ha_extra_function operation)
- {
-@@ -646,23 +660,70 @@
- heap_prepare_hp_create_info(TABLE *table_arg, bool internal_table,
- HP_CREATE_INFO *hp_create_info)
- {
-- uint key, parts, mem_per_row= 0, keys= table_arg->s->keys;
-+ uint key, parts, mem_per_row_keys= 0, keys= table_arg->s->keys;
- uint auto_key= 0, auto_key_type= 0;
-- ha_rows max_rows;
-+ uint fixed_key_fieldnr = 0, fixed_data_size = 0, next_field_pos = 0;
-+ uint column_idx, column_count= table_arg->s->fields;
-+ HP_COLUMNDEF *columndef;
- HP_KEYDEF *keydef;
- HA_KEYSEG *seg;
- TABLE_SHARE *share= table_arg->s;
- bool found_real_auto_increment= 0;
-+ uint blobs= 0;
-
- bzero(hp_create_info, sizeof(*hp_create_info));
-
-+ if (!(columndef= (HP_COLUMNDEF*) my_malloc(column_count *
-+ sizeof(HP_COLUMNDEF),
-+ MYF(MY_WME))))
-+ return my_errno;
-+
-+ for (column_idx= 0; column_idx < column_count; column_idx++)
-+ {
-+ Field* field= *(table_arg->field + column_idx);
-+ HP_COLUMNDEF* column= columndef + column_idx;
-+ column->type= (uint16) field->type();
-+ column->length= field->pack_length();
-+ column->offset= field->offset(table_arg->record[0]);
-+
-+ if (field->null_bit)
-+ {
-+ column->null_bit= field->null_bit;
-+ column->null_pos= (uint) (field->null_ptr -
-+ (uchar*) table_arg->record[0]);
-+ }
-+ else
-+ {
-+ column->null_bit= 0;
-+ column->null_pos= 0;
-+ }
-+
-+ if (field->type() == MYSQL_TYPE_VARCHAR)
-+ {
-+ column->length_bytes= (uint8) (((Field_varstring *) field)->length_bytes);
-+ }
-+ else if (field->type() == MYSQL_TYPE_BLOB)
-+ {
-+ blobs++;
-+ column->length_bytes= (uint8)
-+ (((Field_blob *) field)->pack_length_no_ptr());
-+ }
-+ else
-+ {
-+ column->length_bytes= 0;
-+ }
-+ }
-+
- for (key= parts= 0; key < keys; key++)
- parts+= table_arg->key_info[key].key_parts;
-
- if (!(keydef= (HP_KEYDEF*) my_malloc(keys * sizeof(HP_KEYDEF) +
- parts * sizeof(HA_KEYSEG),
- MYF(MY_WME))))
-+ {
-+ my_free((uchar *) columndef);
- return my_errno;
-+ }
- seg= reinterpret_cast<HA_KEYSEG*>(keydef + keys);
- for (key= 0; key < keys; key++)
- {
-@@ -678,11 +739,11 @@
- case HA_KEY_ALG_UNDEF:
- case HA_KEY_ALG_HASH:
- keydef[key].algorithm= HA_KEY_ALG_HASH;
-- mem_per_row+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
-+ mem_per_row_keys+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
- break;
- case HA_KEY_ALG_BTREE:
- keydef[key].algorithm= HA_KEY_ALG_BTREE;
-- mem_per_row+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*);
-+ mem_per_row_keys+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*);
- break;
- default:
- DBUG_ASSERT(0); // cannot happen
-@@ -707,6 +768,16 @@
- seg->length= (uint) key_part->length;
- seg->flag= key_part->key_part_flag;
-
-+ next_field_pos= seg->start;
-+ if (field->type() == MYSQL_TYPE_VARCHAR)
-+ {
-+ Field *orig_field= *(table_arg->field + key_part->field->field_index);
-+ next_field_pos+= orig_field->pack_length();
-+ }
-+ else
-+ {
-+ next_field_pos+= seg->length;
-+ }
- if (field->flags & (ENUM_FLAG | SET_FLAG))
- seg->charset= &my_charset_bin;
- else
-@@ -732,9 +803,75 @@
- auto_key= key+ 1;
- auto_key_type= field->key_type();
- }
-+
-+ switch (seg->type) {
-+ case HA_KEYTYPE_SHORT_INT:
-+ case HA_KEYTYPE_LONG_INT:
-+ case HA_KEYTYPE_FLOAT:
-+ case HA_KEYTYPE_DOUBLE:
-+ case HA_KEYTYPE_USHORT_INT:
-+ case HA_KEYTYPE_ULONG_INT:
-+ case HA_KEYTYPE_LONGLONG:
-+ case HA_KEYTYPE_ULONGLONG:
-+ case HA_KEYTYPE_INT24:
-+ case HA_KEYTYPE_UINT24:
-+ case HA_KEYTYPE_INT8:
-+ seg->flag|= HA_SWAP_KEY;
-+ break;
-+ case HA_KEYTYPE_VARBINARY1:
-+ /* Case-insensitiveness is handled in coll->hash_sort */
-+ seg->type= HA_KEYTYPE_VARTEXT1;
-+ /* fall through */
-+ case HA_KEYTYPE_VARTEXT1:
-+ keydef[key].flag|= HA_VAR_LENGTH_KEY;
-+ /* Save number of bytes used to store length */
-+ if (seg->flag & HA_BLOB_PART)
-+ seg->bit_start= field->pack_length() - share->blob_ptr_size;
-+ else
-+ seg->bit_start= 1;
-+ break;
-+ case HA_KEYTYPE_VARBINARY2:
-+ /* Case-insensitiveness is handled in coll->hash_sort */
-+ /* fall_through */
-+ case HA_KEYTYPE_VARTEXT2:
-+ keydef[key].flag|= HA_VAR_LENGTH_KEY;
-+ /* Save number of bytes used to store length */
-+ if (seg->flag & HA_BLOB_PART)
-+ seg->bit_start= field->pack_length() - share->blob_ptr_size;
-+ else
-+ seg->bit_start= 2;
-+ /*
-+ Make future comparison simpler by only having to check for
-+ one type
-+ */
-+ seg->type= HA_KEYTYPE_VARTEXT1;
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ if (next_field_pos > fixed_data_size)
-+ {
-+ fixed_data_size= next_field_pos;
-+ }
-+
-+
-+ if (field->field_index >= fixed_key_fieldnr)
-+ {
-+ /*
-+ Do not use seg->fieldnr as it's not reliable in case of temp tables
-+ */
-+ fixed_key_fieldnr= field->field_index + 1;
-+ }
- }
- }
-- mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*));
-+
-+ if (fixed_data_size < share->null_bytes)
-+ {
-+ /* Make sure to include null fields regardless of the presense of keys */
-+ fixed_data_size = share->null_bytes;
-+ }
-+
- if (table_arg->found_next_number_field)
- {
- keydef[share->next_number_index].flag|= HA_AUTO_KEY;
-@@ -745,16 +882,19 @@
- hp_create_info->max_table_size=current_thd->variables.max_heap_table_size;
- hp_create_info->with_auto_increment= found_real_auto_increment;
- hp_create_info->internal_table= internal_table;
--
-- max_rows= (ha_rows) (hp_create_info->max_table_size / mem_per_row);
-- if (share->max_rows && share->max_rows < max_rows)
-- max_rows= share->max_rows;
--
-- hp_create_info->max_records= (ulong) max_rows;
-+ hp_create_info->max_chunk_size= share->key_block_size;
-+ hp_create_info->is_dynamic= (share->row_type == ROW_TYPE_DYNAMIC);
-+ hp_create_info->columns= column_count;
-+ hp_create_info->columndef= columndef;
-+ hp_create_info->fixed_key_fieldnr= fixed_key_fieldnr;
-+ hp_create_info->fixed_data_size= fixed_data_size;
-+ hp_create_info->max_records= (ulong) share->max_rows;
- hp_create_info->min_records= (ulong) share->min_rows;
- hp_create_info->keys= share->keys;
- hp_create_info->reclength= share->reclength;
-+ hp_create_info->keys_memory_size= mem_per_row_keys;
- hp_create_info->keydef= keydef;
-+ hp_create_info->blobs= blobs;
- return 0;
- }
-
-@@ -774,6 +914,7 @@
- create_info->auto_increment_value - 1 : 0);
- error= heap_create(name, &hp_create_info, &internal_share, &created);
- my_free(hp_create_info.keydef);
-+ my_free(hp_create_info.columndef);
- DBUG_ASSERT(file == 0);
- return (error);
- }
-@@ -784,6 +925,13 @@
- table->file->info(HA_STATUS_AUTO);
- if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
- create_info->auto_increment_value= stats.auto_increment_value;
-+ if (!(create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
-+ {
-+ if (file->s->recordspace.is_variable_size)
-+ create_info->key_block_size= file->s->recordspace.chunk_length;
-+ else
-+ create_info->key_block_size= 0;
-+ }
- }
-
- void ha_heap::get_auto_increment(ulonglong offset, ulonglong increment,
---- a/storage/heap/ha_heap.h
-+++ b/storage/heap/ha_heap.h
-@@ -47,12 +47,11 @@
- return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_BTREE) ?
- "BTREE" : "HASH");
- }
-- /* Rows also use a fixed-size format */
-- enum row_type get_row_type() const { return ROW_TYPE_FIXED; }
-+ enum row_type get_row_type() const;
- const char **bas_ext() const;
- ulonglong table_flags() const
- {
-- return (HA_FAST_KEY_READ | HA_NO_BLOBS | HA_NULL_IN_KEY |
-+ return (HA_FAST_KEY_READ | HA_NULL_IN_KEY |
- HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
- HA_REC_NOT_IN_SEQ | HA_CAN_INSERT_DELAYED | HA_NO_TRANSACTIONS |
- HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT);
-@@ -64,8 +63,9 @@
- HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR);
- }
- const key_map *keys_to_use_for_scanning() { return &btree_keys; }
-- uint max_supported_keys() const { return MAX_KEY; }
-- uint max_supported_key_part_length() const { return MAX_KEY_LENGTH; }
-+ uint max_supported_keys() const { return HP_MAX_KEY; }
-+ uint max_supported_key_length() const { return HP_MAX_KEY_LENGTH; }
-+ uint max_supported_key_part_length() const { return HP_MAX_KEY_LENGTH; }
- double scan_time()
- { return (double) (stats.records+stats.deleted) / 20.0+10; }
- double read_time(uint index, uint ranges, ha_rows rows)
---- a/storage/heap/heapdef.h
-+++ b/storage/heap/heapdef.h
-@@ -32,6 +32,13 @@
- #define HP_MIN_RECORDS_IN_BLOCK 16
- #define HP_MAX_RECORDS_IN_BLOCK 8192
-
-+/* this chunk has been deleted and can be reused */
-+#define CHUNK_STATUS_DELETED 0
-+/* this chunk represents the first part of a live record */
-+#define CHUNK_STATUS_ACTIVE 1
-+/* this chunk is a continuation from another chunk (part of chunkset) */
-+#define CHUNK_STATUS_LINKED 2
-+
- /* Some extern variables */
-
- extern LIST *heap_open_list,*heap_share_list;
-@@ -42,7 +49,14 @@
- #define hp_find_hash(A,B) ((HASH_INFO*) hp_find_block((A),(B)))
-
- /* Find pos for record and update it in info->current_ptr */
--#define hp_find_record(info,pos) (info)->current_ptr= hp_find_block(&(info)->s->block,pos)
-+#define hp_find_record(info,pos) \
-+ (info)->current_ptr= hp_find_block(&(info)->s->recordspace.block,pos)
-+
-+#define get_chunk_status(info,ptr) (ptr[(info)->offset_status])
-+
-+#define get_chunk_count(info,rec_length) \
-+ ((rec_length + (info)->chunk_dataspace_length - 1) / \
-+ (info)->chunk_dataspace_length)
-
- typedef struct st_hp_hash_info
- {
-@@ -90,7 +104,7 @@
- const uchar *key);
- extern void hp_make_key(HP_KEYDEF *keydef,uchar *key,const uchar *rec);
- extern uint hp_rb_make_key(HP_KEYDEF *keydef, uchar *key,
-- const uchar *rec, uchar *recpos);
-+ const uchar *rec, uchar *recpos, my_bool packed);
- extern uint hp_rb_key_length(HP_KEYDEF *keydef, const uchar *key);
- extern uint hp_rb_null_key_length(HP_KEYDEF *keydef, const uchar *key);
- extern uint hp_rb_var_key_length(HP_KEYDEF *keydef, const uchar *key);
-@@ -100,6 +114,23 @@
- extern void hp_clear_keys(HP_SHARE *info);
- extern uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
- key_part_map keypart_map);
-+extern uint hp_calc_blob_length(uint length, const uchar *pos);
-+
-+/* Chunkset management (alloc/free/encode/decode) functions */
-+extern uchar *hp_allocate_chunkset(HP_DATASPACE *info, uint chunk_count);
-+extern int hp_reallocate_chunkset(HP_DATASPACE *info, uint chunk_count,
-+ uchar *pos);
-+extern void hp_free_chunks(HP_DATASPACE *info, uchar *pos);
-+extern void hp_clear_dataspace(HP_DATASPACE *info);
-+
-+extern uint hp_get_encoded_data_length(HP_SHARE *info, const uchar *record,
-+ uint *chunk_count);
-+extern void hp_copy_record_data_to_chunkset(HP_SHARE *info, const uchar *record,
-+ uchar *pos);
-+extern int hp_extract_record(HP_INFO *info, uchar *record, const uchar *pos);
-+extern uint hp_process_record_data_to_chunkset(HP_SHARE *info,
-+ const uchar *record, uchar *pos,
-+ uint is_compare);
-
- extern mysql_mutex_t THR_LOCK_heap;
-
---- a/storage/heap/hp_clear.c
-+++ b/storage/heap/hp_clear.c
-@@ -31,16 +31,11 @@
- {
- DBUG_ENTER("hp_clear");
-
-- if (info->block.levels)
-- (void) hp_free_level(&info->block,info->block.levels,info->block.root,
-- (uchar*) 0);
-- info->block.levels=0;
-+ hp_clear_dataspace(&info->recordspace);
- hp_clear_keys(info);
-- info->records= info->deleted= 0;
-- info->data_length= 0;
-+ info->records= 0;
- info->blength=1;
- info->changed=0;
-- info->del_link=0;
- DBUG_VOID_RETURN;
- }
-
-@@ -158,7 +153,7 @@
- int error= 0;
- HP_SHARE *share= info->s;
-
-- if (share->data_length || share->index_length)
-+ if (share->recordspace.total_data_length || share->index_length)
- error= HA_ERR_CRASHED;
- else
- if (share->currently_disabled_keys)
---- a/storage/heap/hp_close.c
-+++ b/storage/heap/hp_close.c
-@@ -46,6 +46,10 @@
- heap_open_list=list_delete(heap_open_list,&info->open_list);
- if (!--info->s->open_count && info->s->delete_on_close)
- hp_free(info->s); /* Table was deleted */
-+ if (info->blob_buffer)
-+ {
-+ my_free(info->blob_buffer);
-+ }
- my_free(info);
- DBUG_RETURN(error);
- }
---- a/storage/heap/hp_create.c
-+++ b/storage/heap/hp_create.c
-@@ -14,11 +14,21 @@
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-
- #include "heapdef.h"
-+#include <mysql_com.h>
-+#include <mysqld_error.h>
-
- static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2);
--static void init_block(HP_BLOCK *block,uint reclength,ulong min_records,
-+static void init_block(HP_BLOCK *block,uint chunk_length, ulong min_records,
- ulong max_records);
-
-+#define FIXED_REC_OVERHEAD (sizeof(uchar))
-+#define VARIABLE_REC_OVERHEAD (sizeof(uchar **) + sizeof(uchar))
-+
-+/* Minimum size that a chunk can take, 12 bytes on 32bit, 24 bytes on 64bit */
-+#define VARIABLE_MIN_CHUNK_SIZE \
-+ ((sizeof(uchar **) + VARIABLE_REC_OVERHEAD + sizeof(uchar **) - 1) & \
-+ ~(sizeof(uchar **) - 1))
-+
- /* Create a heap table */
-
- int heap_create(const char *name, HP_CREATE_INFO *create_info,
-@@ -32,6 +42,7 @@
- uint keys= create_info->keys;
- ulong min_records= create_info->min_records;
- ulong max_records= create_info->max_records;
-+ ulong max_rows_for_stated_memory;
- DBUG_ENTER("heap_create");
-
- if (!create_info->internal_table)
-@@ -48,15 +59,147 @@
-
- if (!share)
- {
-+ uint chunk_dataspace_length, chunk_length, is_variable_size;
-+ uint fixed_data_length, fixed_column_count;
- HP_KEYDEF *keyinfo;
- DBUG_PRINT("info",("Initializing new table"));
--
-+
-+ if (create_info->max_chunk_size)
-+ {
-+ uint configured_chunk_size= create_info->max_chunk_size;
-+
-+ /* User requested variable-size records, let's see if they're possible */
-+
-+ if (configured_chunk_size < create_info->fixed_data_size)
-+ {
-+ /*
-+ The resulting chunk_size cannot be smaller than fixed data part
-+ at the start of the first chunk which allows faster copying
-+ with a single memcpy().
-+ */
-+ my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "key_block_size");
-+ goto err;
-+ }
-+
-+ if (reclength > configured_chunk_size + VARIABLE_REC_OVERHEAD ||
-+ create_info->blobs > 0)
-+ {
-+ /*
-+ Allow variable size only if we're saving some space, i.e.
-+ if a fixed-size record would take more space than variable-size
-+ one plus the variable-size overhead.
-+ There has to be at least one field after indexed fields.
-+ Note that NULL bits are already included in key_part_size.
-+ */
-+ is_variable_size= 1;
-+ chunk_dataspace_length= configured_chunk_size;
-+ }
-+ else
-+ {
-+ /* max_chunk_size is near the full reclength, let's use fixed size */
-+ is_variable_size= 0;
-+ chunk_dataspace_length= reclength;
-+ }
-+ }
-+ else if ((create_info->is_dynamic && reclength >
-+ 256 + VARIABLE_REC_OVERHEAD)
-+ || create_info->blobs > 0)
-+ {
-+ /*
-+ User asked for dynamic records - use 256 as the chunk size, if that
-+ will may save some memory. Otherwise revert to fixed size format.
-+ */
-+ if ((create_info->fixed_data_size + VARIABLE_REC_OVERHEAD) > 256)
-+ chunk_dataspace_length= create_info->fixed_data_size;
-+ else
-+ chunk_dataspace_length= 256 - VARIABLE_REC_OVERHEAD;
-+
-+ is_variable_size= 1;
-+ }
-+ else
-+ {
-+ /*
-+ If max_chunk_size is not specified, put the whole record in one chunk
-+ */
-+ is_variable_size= 0;
-+ chunk_dataspace_length= reclength;
-+ }
-+
-+ if (is_variable_size)
-+ {
-+ /* Check whether we have any variable size records past key data */
-+ uint has_variable_fields= 0;
-+
-+ fixed_data_length= create_info->fixed_data_size;
-+ fixed_column_count= create_info->fixed_key_fieldnr;
-+
-+ for (i= create_info->fixed_key_fieldnr; i < create_info->columns; i++)
-+ {
-+ HP_COLUMNDEF *column= create_info->columndef + i;
-+ if ((column->type == MYSQL_TYPE_VARCHAR &&
-+ (column->length - column->length_bytes) >= 32) ||
-+ column->type == MYSQL_TYPE_BLOB)
-+ {
-+ /*
-+ The field has to be either blob or >= 5.0.3 true VARCHAR
-+ and have substantial length.
-+ TODO: do we want to calculate minimum length?
-+ */
-+ has_variable_fields= 1;
-+ break;
-+ }
-+
-+ if (has_variable_fields)
-+ {
-+ break;
-+ }
-+
-+ if ((column->offset + column->length) <= chunk_dataspace_length)
-+ {
-+ /* Still no variable-size columns, add one fixed-length */
-+ fixed_column_count= i + 1;
-+ fixed_data_length= column->offset + column->length;
-+ }
-+ }
-+
-+ if (!has_variable_fields && create_info->blobs == 0)
-+ {
-+ /*
-+ There is no need to use variable-size records without variable-size
-+ columns.
-+ Reset sizes if it's not variable size anymore.
-+ */
-+ is_variable_size= 0;
-+ chunk_dataspace_length= reclength;
-+ fixed_data_length= reclength;
-+ fixed_column_count= create_info->columns;
-+ }
-+ }
-+ else
-+ {
-+ fixed_data_length= reclength;
-+ fixed_column_count= create_info->columns;
-+ }
-+
- /*
-- We have to store sometimes uchar* del_link in records,
-- so the record length should be at least sizeof(uchar*)
-+ We store uchar* del_link inside the data area of deleted records,
-+ so the data length should be at least sizeof(uchar*)
- */
-- set_if_bigger(reclength, sizeof (uchar*));
--
-+ set_if_bigger(chunk_dataspace_length, sizeof (uchar **));
-+
-+ if (is_variable_size)
-+ {
-+ chunk_length= chunk_dataspace_length + VARIABLE_REC_OVERHEAD;
-+ }
-+ else
-+ {
-+ chunk_length= chunk_dataspace_length + FIXED_REC_OVERHEAD;
-+ }
-+
-+ /* Align chunk length to the next pointer */
-+ chunk_length= (uint) (chunk_length + sizeof(uchar **) - 1) &
-+ ~(sizeof(uchar **) - 1);
-+
- for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
- {
- bzero((char*) &keyinfo->block,sizeof(keyinfo->block));
-@@ -73,42 +216,11 @@
- keyinfo->rb_tree.size_of_element++;
- }
- switch (keyinfo->seg[j].type) {
-- case HA_KEYTYPE_SHORT_INT:
-- case HA_KEYTYPE_LONG_INT:
-- case HA_KEYTYPE_FLOAT:
-- case HA_KEYTYPE_DOUBLE:
-- case HA_KEYTYPE_USHORT_INT:
-- case HA_KEYTYPE_ULONG_INT:
-- case HA_KEYTYPE_LONGLONG:
-- case HA_KEYTYPE_ULONGLONG:
-- case HA_KEYTYPE_INT24:
-- case HA_KEYTYPE_UINT24:
-- case HA_KEYTYPE_INT8:
-- keyinfo->seg[j].flag|= HA_SWAP_KEY;
-- break;
- case HA_KEYTYPE_VARBINARY1:
-- /* Case-insensitiveness is handled in coll->hash_sort */
-- keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1;
-- /* fall_through */
- case HA_KEYTYPE_VARTEXT1:
-- keyinfo->flag|= HA_VAR_LENGTH_KEY;
-- length+= 2;
-- /* Save number of bytes used to store length */
-- keyinfo->seg[j].bit_start= 1;
-- break;
- case HA_KEYTYPE_VARBINARY2:
-- /* Case-insensitiveness is handled in coll->hash_sort */
-- /* fall_through */
- case HA_KEYTYPE_VARTEXT2:
-- keyinfo->flag|= HA_VAR_LENGTH_KEY;
- length+= 2;
-- /* Save number of bytes used to store length */
-- keyinfo->seg[j].bit_start= 2;
-- /*
-- Make future comparison simpler by only having to check for
-- one type
-- */
-- keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1;
- break;
- default:
- break;
-@@ -133,13 +245,34 @@
- }
- if (!(share= (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
- keys*sizeof(HP_KEYDEF)+
-+ (create_info->columns *
-+ sizeof(HP_COLUMNDEF)) +
- key_segs*sizeof(HA_KEYSEG),
- MYF(MY_ZEROFILL))))
- goto err;
-- share->keydef= (HP_KEYDEF*) (share + 1);
-+
-+ /*
-+ Max_records is used for estimating block sizes and for enforcement.
-+ Calculate the very maximum number of rows (if everything was one chunk)
-+ and then take either that value or configured max_records (pick smallest
-+ one).
-+ */
-+ max_rows_for_stated_memory= (ha_rows) (create_info->max_table_size /
-+ (create_info->keys_memory_size +
-+ chunk_length));
-+ max_records = ((max_records && max_records < max_rows_for_stated_memory) ?
-+ max_records : max_rows_for_stated_memory);
-+
-+ share->column_defs= (HP_COLUMNDEF*) (share + 1);
-+ memcpy(share->column_defs, create_info->columndef,
-+ (size_t) (sizeof(create_info->columndef[0]) *
-+ create_info->columns));
-+
-+ share->keydef= (HP_KEYDEF*) (share->column_defs + create_info->columns);
- share->key_stat_version= 1;
- keyseg= (HA_KEYSEG*) (share->keydef + keys);
-- init_block(&share->block, reclength + 1, min_records, max_records);
-+ init_block(&share->recordspace.block, chunk_length, min_records,
-+ max_records);
- /* Fix keys */
- memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys));
- for (i= 0, keyinfo= share->keydef; i < keys; i++, keyinfo++)
-@@ -177,16 +310,36 @@
- share->min_records= min_records;
- share->max_records= max_records;
- share->max_table_size= create_info->max_table_size;
-- share->data_length= share->index_length= 0;
-- share->reclength= reclength;
-+ share->index_length= 0;
- share->blength= 1;
- share->keys= keys;
- share->max_key_length= max_length;
-+ share->column_count= create_info->columns;
- share->changed= 0;
- share->auto_key= create_info->auto_key;
- share->auto_key_type= create_info->auto_key_type;
- share->auto_increment= create_info->auto_increment;
- share->create_time= (long) time((time_t*) 0);
-+
-+ share->fixed_data_length= fixed_data_length;
-+ share->fixed_column_count= fixed_column_count;
-+ share->blobs= create_info->blobs;
-+
-+ share->recordspace.chunk_length= chunk_length;
-+ share->recordspace.chunk_dataspace_length= chunk_dataspace_length;
-+ share->recordspace.is_variable_size= is_variable_size;
-+ share->recordspace.total_data_length= 0;
-+
-+ if (is_variable_size) {
-+ share->recordspace.offset_link= chunk_dataspace_length;
-+ share->recordspace.offset_status= share->recordspace.offset_link +
-+ sizeof(uchar **);
-+ } else {
-+ /* Make it likely to fail if anyone uses this offset */
-+ share->recordspace.offset_link= 1 << 22;
-+ share->recordspace.offset_status= chunk_dataspace_length;
-+ }
-+
- /* Must be allocated separately for rename to work */
- if (!(share->name= my_strdup(name,MYF(0))))
- {
-@@ -228,7 +381,7 @@
- param->search_flag, not_used);
- }
-
--static void init_block(HP_BLOCK *block, uint reclength, ulong min_records,
-+static void init_block(HP_BLOCK *block, uint chunk_length, ulong min_records,
- ulong max_records)
- {
- uint i,recbuffer,records_in_block;
-@@ -236,7 +389,12 @@
- max_records= max(min_records,max_records);
- if (!max_records)
- max_records= 1000; /* As good as quess as anything */
-- recbuffer= (uint) (reclength + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1);
-+ /*
-+ We want to start each chunk at 8 bytes boundary, round recbuffer to the
-+ next 8.
-+ */
-+ recbuffer= (uint) (chunk_length + sizeof(uchar**) - 1) &
-+ ~(sizeof(uchar**) - 1);
- records_in_block= max_records / 10;
- if (records_in_block < 10 && max_records)
- records_in_block= 10;
---- a/storage/heap/hp_delete.c
-+++ b/storage/heap/hp_delete.c
-@@ -22,6 +22,7 @@
- uchar *pos;
- HP_SHARE *share=info->s;
- HP_KEYDEF *keydef, *end, *p_lastinx;
-+
- DBUG_ENTER("heap_delete");
- DBUG_PRINT("enter",("info: 0x%lx record: 0x%lx", (long) info, (long) record));
-
-@@ -43,10 +44,7 @@
- }
-
- info->update=HA_STATE_DELETED;
-- *((uchar**) pos)=share->del_link;
-- share->del_link=pos;
-- pos[share->reclength]=0; /* Record deleted */
-- share->deleted++;
-+ hp_free_chunks(&share->recordspace, pos);
- info->current_hash_ptr=0;
- #if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
- DBUG_EXECUTE("check_heap",heap_check_heap(info, 0););
-@@ -75,7 +73,8 @@
- info->last_pos= NULL; /* For heap_rnext/heap_rprev */
-
- custom_arg.keyseg= keyinfo->seg;
-- custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
-+ custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos,
-+ FALSE);
- custom_arg.search_flag= SEARCH_SAME;
- old_allocated= keyinfo->rb_tree.allocated;
- res= tree_delete(&keyinfo->rb_tree, info->recbuf, custom_arg.key_length,
-@@ -112,6 +111,7 @@
- blength=share->blength;
- if (share->records+1 == blength)
- blength+= blength;
-+
- lastpos=hp_find_hash(&keyinfo->block,share->records);
- last_ptr=0;
-
---- /dev/null
-+++ b/storage/heap/hp_dspace.c
-@@ -0,0 +1,440 @@
-+/* Copyright (C) 2000-2002 MySQL AB
-+ Copyright (C) 2008 eBay, Inc
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; version 2 of the License.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-+
-+/*
-+ Implements various base dataspace-related functions - allocate, free, clear
-+*/
-+
-+#include "heapdef.h"
-+
-+
-+/*
-+ MySQL Heap tables keep data in arrays of fixed-size chunks.
-+ These chunks are organized into two groups of HP_BLOCK structures:
-+ - group1 contains indexes, with one HP_BLOCK per key
-+ (part of HP_KEYDEF)
-+ - group2 contains record data, with single HP_BLOCK
-+ for all records, referenced by HP_SHARE.recordspace.block
-+
-+ While columns used in index are usually small, other columns
-+ in the table may need to accomodate larger data. Typically,
-+ larger data is placed into VARCHAR or BLOB columns. With actual
-+ sizes varying, Heap Engine has to support variable-sized records
-+ in memory. Heap Engine implements the concept of dataspace
-+ (HP_DATASPACE), which incorporates HP_BLOCK for the record data,
-+ and adds more information for managing variable-sized records.
-+
-+ Variable-size records are stored in multiple "chunks",
-+ which means that a single record of data (database "row") can
-+ consist of multiple chunks organized into one "set". HP_BLOCK
-+ contains chunks. In variable-size format, one record
-+ is represented as one or many chunks, depending on the actual
-+ data, while in fixed-size mode, one record is always represented
-+ as one chunk. The index structures would always point to the first
-+ chunk in the chunkset.
-+
-+ At the time of table creation, Heap Engine attempts to find out if
-+ variable-size records are desired. A user can request
-+ variable-size records by providing either row_type=dynamic or
-+ key_block_size=NNN table create option. Heap Engine will check
-+ whether key_block_size provides enough space in the first chunk
-+ to keep all null bits and columns that are used in indexes.
-+ If key_block_size is too small, table creation will be aborted
-+ with an error. Heap Engine will revert to fixed-size allocation
-+ mode if key_block_size provides no memory benefits (if the
-+ fixed-size record would always be shorter then the first chunk
-+ in the chunkset with the specified key_block_size).
-+
-+ In order to improve index search performance, Heap Engine needs
-+ to keep all null flags and all columns used as keys inside
-+ the first chunk of a chunkset. In particular, this means that
-+ all columns used as keys should be defined first in the table
-+ creation SQL. The length of data used by null bits and key columns
-+ is stored as fixed_data_length inside HP_SHARE. fixed_data_length
-+ will extend past last key column if more fixed-length fields can
-+ fit into the first chunk.
-+
-+ Variable-size records are necessary only in the presence of
-+ variable-size columns. Heap Engine will be looking for BLOB
-+ columns or VARCHAR columns, which declare length of 32 or more. If
-+ no such columns are found, table will be switched to fixed-size
-+ format. You should always try to put such columns at the end of
-+ the table definition.
-+
-+ Whenever data is being inserted or updated in the table
-+ Heap Engine will calculate how many chunks are necessary.
-+ For insert operations, Heap Engine allocates new chunkset in
-+ the recordspace. For update operations it will modify length of
-+ the existing chunkset, unlinking unnecessary chunks at the end,
-+ or allocating and adding more if larger length is necessary.
-+
-+ When writing data to chunks or copying data back to record,
-+ fixed-size columns are copied in their full format. VARCHARs and
-+ BLOBs are copied based on their actual length. Any NULL values
-+ after fixed_data_length are skipped.
-+
-+ The allocation and contents of the actual chunks varies between
-+ fixed and variable-size modes. Total chunk length is always
-+ aligned to the next sizeof(uchar*). Here is the format of
-+ fixed-size chunk:
-+ uchar[] - sizeof=chunk_dataspace_length, but at least
-+ sizeof(uchar*) bytes. Keeps actual data or pointer
-+ to the next deleted chunk.
-+ chunk_dataspace_length equals to full record length
-+ uchar - status field (1 means "in use", 0 means "deleted")
-+
-+ Variable-size chunk uses different format:
-+ uchar[] - sizeof=chunk_dataspace_length, but at least
-+ sizeof(uchar*) bytes. Keeps actual data or pointer
-+ to the next deleted chunk.
-+ chunk_dataspace_length is set according to table
-+ setup (key_block_size)
-+ uchar* - pointer to the next chunk in this chunkset,
-+ or NULL for the last chunk
-+ uchar - status field (1 means "first", 0 means "deleted",
-+ 2 means "linked")
-+
-+ When allocating a new chunkset of N chunks, Heap Engine will try
-+ to allocate chunks one-by-one, linking them as they become
-+ allocated. Allocation of a single chunk will attempt to reuse
-+ a deleted (freed) chunk. If no free chunks are available,
-+ it will attempt to allocate a new area inside HP_BLOCK.
-+ Freeing chunks will place them at the front of free list
-+ referenced by del_link in HP_DATASPACE. The newly freed chunk
-+ will contain reference to the previously freed chunk in its first
-+ sizeof(uchar*) of the payload space.
-+
-+ Here is open issues:
-+ - It is not very nice to require people to keep key columns
-+ at the beginning of the table creation SQL. There are three
-+ proposed resolutions:
-+ a. Leave it as is. It's a reasonable limitation
-+ b. Add new HA_KEEP_KEY_COLUMNS_TO_FRONT flag to handler.h and
-+ make table.cpp align columns when it creates the table
-+ c. Make HeapEngine reorder columns in the chunk data, so that
-+ key columns go first. Add parallel HA_KEYSEG structures
-+ to distinguish positions in record vs. positions in
-+ the first chunk. Copy all data field-by-field rather than
-+ using single memcpy unless DBA kept key columns to
-+ the beginning.
-+ - heap_check_heap needs verify linked chunks, looking for
-+ issues such as orphans, cycles, and bad links. However,
-+ Heap Engine today does not do similar things even for
-+ free list.
-+ - In a more sophisticated implementation, some space can
-+ be saved even with all fixed-size columns if many of them
-+ have NULL value, as long as these columns are not used
-+ in indexes
-+ - In variable-size format status should be moved to lower
-+ bits of the "next" pointer. Pointer is always aligned
-+ to sizeof(byte*), which is at least 4, leaving 2 lower
-+ bits free. This will save 8 bytes per chunk
-+ on 64-bit platform.
-+ - As we do not want to modify FRM format or to add new SQL
-+ keywords, KEY_BLOCK_SIZE option of "CREATE TABLE" is reused
-+ to specify block size for Heap Engine tables.
-+ - since all key columns must fit in the first chunk, having keys
-+ on BLOB columns is currently impossible. This limitation is
-+ relatively easiy to remove in future.
-+*/
-+
-+static uchar *hp_allocate_one_chunk(HP_DATASPACE *info);
-+
-+
-+/**
-+ Clear a dataspace
-+
-+ Frees memory and zeros-out any relevant counters in the dataspace
-+
-+ @param info the dataspace to clear
-+*/
-+
-+void hp_clear_dataspace(HP_DATASPACE *info)
-+{
-+ if (info->block.levels)
-+ {
-+ hp_free_level(&info->block,info->block.levels,info->block.root,
-+ (uchar *) 0);
-+ }
-+ info->block.levels= 0;
-+ info->del_chunk_count= info->chunk_count= 0;
-+ info->del_link= 0;
-+ info->total_data_length= 0;
-+}
-+
-+
-+/**
-+ Allocate or reallocate a chunkset in the dataspace
-+
-+ Attempts to allocate a new chunkset or change the size of an existing chunkset
-+
-+ @param info the hosting dataspace
-+ @param chunk_count the number of chunks that we expect as the result
-+ @param existing_set non-null value asks function to resize existing
-+ chunkset, return value would point to this set
-+
-+ @return Pointer to the first chunk in the new or updated chunkset, or NULL
-+ if unsuccessful
-+*/
-+
-+static uchar *hp_allocate_variable_chunkset(HP_DATASPACE *info,
-+ uint chunk_count,
-+ uchar *existing_set)
-+{
-+ int alloc_count= chunk_count, i;
-+ uchar *first_chunk= 0, *curr_chunk= 0, *prev_chunk= 0;
-+ uchar *last_existing_chunk= 0;
-+
-+ DBUG_ASSERT(alloc_count);
-+
-+ if (existing_set)
-+ {
-+ first_chunk= existing_set;
-+
-+ curr_chunk= existing_set;
-+ while (curr_chunk && alloc_count)
-+ {
-+ prev_chunk= curr_chunk;
-+ curr_chunk= *((uchar **) (curr_chunk + info->offset_link));
-+ alloc_count--;
-+ }
-+
-+ if (!alloc_count)
-+ {
-+ if (curr_chunk)
-+ {
-+ /*
-+ We came through all chunks and there is more left, let's truncate the
-+ list.
-+ */
-+ *((uchar **) (prev_chunk + info->offset_link))= NULL;
-+ hp_free_chunks(info, curr_chunk);
-+ }
-+
-+ return first_chunk;
-+ }
-+
-+ last_existing_chunk= prev_chunk;
-+ }
-+
-+ /*
-+ We can reach this point only if we're allocating new chunkset or more chunks
-+ in existing set.
-+ */
-+
-+ for (i= 0; i < alloc_count; i++)
-+ {
-+ curr_chunk= hp_allocate_one_chunk(info);
-+ if (!curr_chunk)
-+ {
-+ /* no space in the current block */
-+
-+ if (last_existing_chunk)
-+ {
-+ /* Truncate whatever was added at the end of the existing chunkset */
-+ prev_chunk= last_existing_chunk;
-+ curr_chunk= *((uchar **)(prev_chunk + info->offset_link));
-+ *((uchar **)(prev_chunk + info->offset_link))= NULL;
-+ hp_free_chunks(info, curr_chunk);
-+ }
-+ else if (first_chunk)
-+ {
-+ /* free any chunks previously allocated */
-+ hp_free_chunks(info, first_chunk);
-+ }
-+
-+ return NULL;
-+ }
-+
-+ /* mark as if this chunk is last in the chunkset */
-+ *((uchar **) (curr_chunk + info->offset_link))= 0;
-+
-+ if (prev_chunk)
-+ {
-+ /* tie them into a linked list */
-+ *((uchar **) (prev_chunk + info->offset_link))= curr_chunk;
-+ /* Record linked from active */
-+ curr_chunk[info->offset_status]= CHUNK_STATUS_LINKED;
-+ }
-+ else
-+ {
-+ /* Record active */
-+ curr_chunk[info->offset_status]= CHUNK_STATUS_ACTIVE;
-+ }
-+
-+ if (!first_chunk)
-+ {
-+ first_chunk= curr_chunk;
-+ }
-+
-+ prev_chunk= curr_chunk;
-+}
-+
-+ return first_chunk;
-+}
-+
-+
-+/**
-+ Allocate a new chunkset in the dataspace
-+
-+ Attempts to allocate a new chunkset
-+
-+ @param info the hosting dataspace
-+ @param chunk_count the number of chunks that we expect as the result
-+
-+ @return Pointer to the first chunk in the new or updated chunkset, or NULL if
-+ unsuccessful
-+*/
-+
-+uchar *hp_allocate_chunkset(HP_DATASPACE *info, uint chunk_count)
-+{
-+ uchar *result;
-+
-+ DBUG_ENTER("hp_allocate_chunks");
-+
-+ if (info->is_variable_size)
-+ {
-+ result = hp_allocate_variable_chunkset(info, chunk_count, NULL);
-+ }
-+ else
-+ {
-+ result= hp_allocate_one_chunk(info);
-+ if (result)
-+ {
-+ result[info->offset_status]= CHUNK_STATUS_ACTIVE;
-+ }
-+
-+ DBUG_RETURN(result);
-+ }
-+
-+ DBUG_RETURN(result);
-+}
-+
-+
-+/**
-+ Reallocate an existing chunkset in the dataspace
-+
-+ Attempts to change the size of an existing chunkset
-+
-+ @param info the hosting dataspace
-+ @param chunk_count the number of chunks that we expect as the result
-+ @param pos pointer to the existing chunkset
-+
-+ @return Error code or zero if successful
-+*/
-+
-+int hp_reallocate_chunkset(HP_DATASPACE *info, uint chunk_count, uchar *pos)
-+{
-+ DBUG_ENTER("hp_reallocate_chunks");
-+
-+ if (!info->is_variable_size)
-+ {
-+ /* Update should never change chunk_count in fixed-size mode */
-+ my_errno= HA_ERR_WRONG_COMMAND;
-+ return my_errno;
-+ }
-+
-+ /* Reallocate never moves the first chunk */
-+ if (!hp_allocate_variable_chunkset(info, chunk_count, pos))
-+ DBUG_RETURN(my_errno);
-+
-+ DBUG_RETURN(0);
-+}
-+
-+
-+/**
-+ Allocate a single chunk in the dataspace
-+
-+ Attempts to allocate a new chunk or reuse one from deleted list
-+
-+ @param info the hosting dataspace
-+
-+ @return Pointer to the chunk, or NULL if unsuccessful
-+*/
-+
-+static uchar *hp_allocate_one_chunk(HP_DATASPACE *info)
-+{
-+ uchar *curr_chunk;
-+ size_t length;
-+ ulong block_pos;
-+
-+ if (info->del_link)
-+ {
-+ curr_chunk= info->del_link;
-+ info->del_link= *((uchar **) curr_chunk);
-+ info->del_chunk_count--;
-+
-+ DBUG_PRINT("hp_allocate_one_chunk",
-+ ("Used old position: 0x%lx",(long) curr_chunk));
-+ return curr_chunk;
-+ }
-+
-+ block_pos= (info->chunk_count % info->block.records_in_block);
-+ if (!block_pos)
-+ {
-+ if (hp_get_new_block(&info->block, &length))
-+ {
-+ /* no space in the current block */
-+ return NULL;
-+ }
-+
-+ info->total_data_length+= length;
-+ }
-+
-+ info->chunk_count++;
-+ curr_chunk= ((uchar *) info->block.level_info[0].last_blocks +
-+ block_pos * info->block.recbuffer);
-+
-+ DBUG_PRINT("hp_allocate_one_chunk",
-+ ("Used new position: 0x%lx", (long) curr_chunk));
-+
-+ return curr_chunk;
-+}
-+
-+
-+/**
-+ Free a list of chunks
-+
-+ Reclaims all chunks linked by the pointer,
-+ which could be the whole chunkset or a part of an existing chunkset
-+
-+ @param info the hosting dataspace
-+ @param pos pointer to the head of the chunkset
-+*/
-+
-+void hp_free_chunks(HP_DATASPACE *info, uchar *pos)
-+{
-+ uchar *curr_chunk= pos;
-+
-+ while (curr_chunk)
-+ {
-+ info->del_chunk_count++;
-+ *((uchar **) curr_chunk)= info->del_link;
-+ info->del_link= curr_chunk;
-+
-+ curr_chunk[info->offset_status]= CHUNK_STATUS_DELETED;
-+
-+ DBUG_PRINT("hp_free_chunks",("Freed position: 0x%lx", (long) curr_chunk));
-+
-+ if (!info->is_variable_size)
-+ {
-+ break;
-+ }
-+
-+ /* Delete next chunk in this chunkset */
-+ curr_chunk= *((uchar **)(curr_chunk + info->offset_link));
-+ }
-+}
---- a/storage/heap/hp_extra.c
-+++ b/storage/heap/hp_extra.c
-@@ -56,7 +56,6 @@
- info->current_record= (ulong) ~0L;
- info->current_hash_ptr=0;
- info->update=0;
-- info->next_block=0;
- return 0;
- }
-
---- a/storage/heap/hp_hash.c
-+++ b/storage/heap/hp_hash.c
-@@ -336,16 +336,26 @@
- {
- CHARSET_INFO *cs= seg->charset;
- uint pack_length= seg->bit_start;
-- uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos));
-+ uint length= hp_calc_blob_length(pack_length, pos);
-+
-+ if (seg->flag & HA_BLOB_PART)
-+ {
-+ memcpy(&pos, pos + pack_length, sizeof(char *));
-+ }
-+ else
-+ {
-+ pos+= pack_length;
-+ }
-+
- if (cs->mbmaxlen > 1)
- {
- uint char_length;
-- char_length= my_charpos(cs, pos + pack_length,
-- pos + pack_length + length,
-+ char_length= my_charpos(cs, pos,
-+ pos + length,
- seg->length/cs->mbmaxlen);
- set_if_smaller(length, char_length);
- }
-- cs->coll->hash_sort(cs, pos+pack_length, length, &nr, &nr2);
-+ cs->coll->hash_sort(cs, pos, length, &nr, &nr2);
- }
- else
- {
-@@ -545,18 +555,18 @@
- uint char_length1, char_length2;
- uint pack_length= seg->bit_start;
- CHARSET_INFO *cs= seg->charset;
-- if (pack_length == 1)
-- {
-- char_length1= (uint) *(uchar*) pos1++;
-- char_length2= (uint) *(uchar*) pos2++;
-- }
-- else
-+
-+ char_length1= hp_calc_blob_length(pack_length, pos1);
-+ char_length2= hp_calc_blob_length(pack_length, pos2);
-+ pos1+= pack_length;
-+ pos2+= pack_length;
-+
-+ if (seg->flag & HA_BLOB_PART)
- {
-- char_length1= uint2korr(pos1);
-- char_length2= uint2korr(pos2);
-- pos1+= 2;
-- pos2+= 2;
-+ memcpy(&pos1, pos1, sizeof(char *));
-+ memcpy(&pos2, pos2, sizeof(char *));
- }
-+
- if (cs->mbmaxlen > 1)
- {
- uint safe_length1= char_length1;
-@@ -668,6 +678,34 @@
- }
-
-
-+/**
-+ Returns a BLOB length stored in the specified number of bytes at the
-+ specified location.
-+
-+ @param length the number of bytes used to store length
-+ @param pos pointer to length bytes
-+
-+ @return Length of BLOB data.
-+*/
-+
-+uint hp_calc_blob_length(uint bytes, const uchar *pos)
-+{
-+ switch (bytes) {
-+ case 1:
-+ return (uint) *pos;
-+ case 2:
-+ return uint2korr(pos);
-+ case 3:
-+ return uint3korr(pos);
-+ case 4:
-+ return uint4korr(pos);
-+ default:
-+ break;
-+ }
-+
-+ return 0; /* Impossible */
-+}
-+
- /* Copy a key from a record to a keybuffer */
-
- void hp_make_key(HP_KEYDEF *keydef, uchar *key, const uchar *rec)
-@@ -678,18 +716,37 @@
- {
- CHARSET_INFO *cs= seg->charset;
- uint char_length= seg->length;
-- uchar *pos= (uchar*) rec + seg->start;
-+ const uchar *pos= rec + seg->start;
- if (seg->null_bit)
- *key++= test(rec[seg->null_pos] & seg->null_bit);
-- if (cs->mbmaxlen > 1)
-+
-+ if (seg->flag & HA_BLOB_PART)
- {
-- char_length= my_charpos(cs, pos, pos + seg->length,
-- char_length / cs->mbmaxlen);
-- set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
-+ uint tmp_length= hp_calc_blob_length(seg->bit_start, pos);
-+ uint length= min(seg->length, tmp_length);
-+
-+ memcpy(&pos, rec + seg->bit_start, sizeof(char *));
-+ if (cs->mbmaxlen > 1)
-+ {
-+ char_length= my_charpos(cs, pos, pos + seg->length,
-+ char_length / cs->mbmaxlen);
-+ set_if_smaller(char_length, length); /* QQ: ok to remove? */
-+ }
-+ store_key_length_inc(key, char_length);
- }
-- if (seg->type == HA_KEYTYPE_VARTEXT1)
-- char_length+= seg->bit_start; /* Copy also length */
-- memcpy(key,rec+seg->start,(size_t) char_length);
-+ else
-+ {
-+ if (cs->mbmaxlen > 1)
-+ {
-+ char_length= my_charpos(cs, pos, pos + seg->length,
-+ char_length / cs->mbmaxlen);
-+ set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
-+ }
-+ if (seg->type == HA_KEYTYPE_VARTEXT1)
-+ char_length+= seg->bit_start; /* Copy also length */
-+ }
-+
-+ memcpy(key, pos, (size_t) char_length);
- key+= char_length;
- }
- }
-@@ -702,8 +759,8 @@
- } while(0)
-
-
--uint hp_rb_make_key(HP_KEYDEF *keydef, uchar *key,
-- const uchar *rec, uchar *recpos)
-+uint hp_rb_make_key(HP_KEYDEF *keydef, uchar *key,
-+ const uchar *rec, uchar *recpos, my_bool packed)
- {
- uchar *start_key= key;
- HA_KEYSEG *seg, *endseg;
-@@ -772,6 +829,29 @@
- key+= char_length;
- continue;
- }
-+ else if (seg->flag & HA_BLOB_PART)
-+ {
-+ uchar *pos= (uchar*) rec + seg->start;
-+ uint tmp_length= hp_calc_blob_length(seg->bit_start, pos);
-+ uint length= min(seg->length, tmp_length);
-+ CHARSET_INFO *cs= seg->charset;
-+ char_length= seg->length / cs->mbmaxlen;
-+
-+ /* check_one_rb_key() calls hp_rb_make_key() for already packed records */
-+ if (!packed)
-+ {
-+ memcpy(&pos, pos + seg->bit_start, sizeof(char *));
-+ }
-+ else
-+ {
-+ pos+= seg->bit_start;
-+ }
-+ FIX_LENGTH(cs, pos, length, char_length);
-+ store_key_length_inc(key, char_length);
-+ memcpy(key, pos, (size_t) char_length);
-+ key+= char_length;
-+ continue;
-+ }
-
- char_length= seg->length;
- if (seg->charset->mbmaxlen > 1)
---- a/storage/heap/hp_info.c
-+++ b/storage/heap/hp_info.c
-@@ -47,9 +47,22 @@
- {
- DBUG_ENTER("heap_info");
- x->records = info->s->records;
-- x->deleted = info->s->deleted;
-- x->reclength = info->s->reclength;
-- x->data_length = info->s->data_length;
-+ x->deleted = info->s->recordspace.del_chunk_count;
-+
-+ if (info->s->recordspace.is_variable_size)
-+ {
-+ if (info->s->records)
-+ x->reclength = (uint) (info->s->recordspace.total_data_length /
-+ (ulonglong) info->s->records);
-+ else
-+ x->reclength = info->s->recordspace.chunk_length;
-+ }
-+ else
-+ {
-+ x->reclength = info->s->recordspace.chunk_dataspace_length;
-+ }
-+
-+ x->data_length = info->s->recordspace.total_data_length;
- x->index_length = info->s->index_length;
- x->max_records = info->s->max_records;
- x->errkey = info->errkey;
---- a/storage/heap/hp_open.c
-+++ b/storage/heap/hp_open.c
-@@ -47,9 +47,9 @@
- #ifndef DBUG_OFF
- info->opt_flag= READ_CHECK_USED; /* Check when changing */
- #endif
-- DBUG_PRINT("exit",("heap: 0x%lx reclength: %d records_in_block: %d",
-- (long) info, share->reclength,
-- share->block.records_in_block));
-+ DBUG_PRINT("exit",("heap: 0x%lx chunk_length: %d records_in_block: %d",
-+ (long) info, share->recordspace.chunk_length,
-+ share->recordspace.block.records_in_block));
- DBUG_RETURN(info);
- }
-
---- /dev/null
-+++ b/storage/heap/hp_record.c
-@@ -0,0 +1,498 @@
-+/* Copyright (C) 2000-2002 MySQL AB
-+ Copyright (C) 2008 eBay, Inc
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; version 2 of the License.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-+
-+/*
-+ Implements various base record-related functions, such as encode and decode
-+ into chunks.
-+*/
-+
-+#include "heapdef.h"
-+#include <mysql_com.h>
-+
-+/**
-+ Calculate size of the record for the purpose of storing in chunks
-+
-+ Walk through the fields of the record and calculates the exact space
-+ needed in chunks as well the the total chunk count
-+
-+ @param info the hosting table
-+ @param record the record in standard unpacked format
-+ @param[out] chunk_count the number of chunks needed for this record
-+
-+ @return The size of the required storage in bytes
-+*/
-+
-+uint hp_get_encoded_data_length(HP_SHARE *info, const uchar *record,
-+ uint *chunk_count)
-+{
-+ uint i, dst_offset;
-+
-+ dst_offset= info->fixed_data_length;
-+
-+ if (!info->recordspace.is_variable_size)
-+ {
-+ /* Nothing more to copy */
-+ *chunk_count= 1;
-+ return dst_offset;
-+ }
-+
-+ for (i= info->fixed_column_count; i < info->column_count; i++)
-+ {
-+ uint src_offset, length;
-+
-+ HP_COLUMNDEF *column= info->column_defs + i;
-+
-+ if (column->null_bit)
-+ {
-+ if (record[column->null_pos] & column->null_bit)
-+ {
-+ /* Skip all NULL values */
-+ continue;
-+ }
-+ }
-+
-+ src_offset= column->offset;
-+ if (column->type == MYSQL_TYPE_VARCHAR)
-+ {
-+ uint pack_length;
-+
-+ /* >= 5.0.3 true VARCHAR */
-+
-+ pack_length= column->length_bytes;
-+ length= pack_length + (pack_length == 1 ?
-+ (uint) *(uchar *) (record + src_offset) :
-+ uint2korr(record + src_offset));
-+ }
-+ else if (column->type == MYSQL_TYPE_BLOB)
-+ {
-+ uint pack_length= column->length_bytes;
-+
-+ length= pack_length + hp_calc_blob_length(pack_length,
-+ record + src_offset);
-+ }
-+ else
-+ {
-+ length= column->length;
-+ }
-+
-+ dst_offset+= length;
-+ }
-+
-+ *chunk_count= get_chunk_count(&info->recordspace, dst_offset);
-+
-+ return dst_offset;
-+}
-+
-+
-+#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
-+static void dump_chunk(HP_SHARE *info, const uchar *curr_chunk)
-+{
-+ uint i;
-+ fprintf(stdout, "Chunk dump at 0x%lx: ", (long) curr_chunk);
-+ for (i= 0; i < info->recordspace.chunk_dataspace_length; i++)
-+ {
-+ uint b= *((uchar *)(curr_chunk + i));
-+ if (b < 0x10)
-+ {
-+ fprintf(stdout, "0");
-+ }
-+ fprintf(stdout, "%lx ", (long) b);
-+ }
-+ fprintf(stdout, ". Next = 0x%lx, Status = %d\n",
-+ (long) (*((uchar **) (curr_chunk + info->recordspace.offset_link))),
-+ (uint) (*((uchar *) (curr_chunk + info->recordspace.offset_status))));
-+}
-+#endif
-+
-+/**
-+ Stores data from packed field into the preallocated chunkset,
-+ or performs data comparison
-+
-+ @param info the hosting table
-+ @param data the field data in packed format
-+ @param length the field data length
-+ @param pos_ptr the target chunkset
-+ @param off_ptr the pointer to the offset within the current chunkset
-+ @param is_compare flag indicating whether we should compare data or store
-+ it
-+
-+ @return Status of comparison
-+ @retval non-zero if comparison found data differences
-+ @retval zero otherwise
-+*/
-+
-+static inline uint
-+hp_process_field_data_to_chunkset(HP_SHARE *info, const uchar *data,
-+ uint length, uchar **pos_ptr, uint *off_ptr,
-+ uint is_compare)
-+{
-+ uint to_copy;
-+ uchar *curr_chunk= *pos_ptr;
-+ uint dst_offset= *off_ptr;
-+ uint rc= 1;
-+
-+ while (length > 0)
-+ {
-+
-+ to_copy= info->recordspace.chunk_dataspace_length - dst_offset;
-+ if (to_copy == 0)
-+ {
-+ /* Jump to the next chunk */
-+#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
-+ dump_chunk(info, curr_chunk);
-+#endif
-+ curr_chunk= *((uchar **) (curr_chunk + info->recordspace.offset_link));
-+ dst_offset= 0;
-+ continue;
-+ }
-+
-+ to_copy= min(length, to_copy);
-+
-+ if (is_compare)
-+ {
-+ if (memcmp(curr_chunk + dst_offset, data, (size_t) to_copy))
-+ {
-+ goto end;
-+ }
-+ }
-+ else
-+ {
-+ memcpy(curr_chunk + dst_offset, data, (size_t) to_copy);
-+ }
-+
-+ data+= to_copy;
-+ dst_offset+= to_copy;
-+ length-= to_copy;
-+ }
-+
-+ rc= 0;
-+
-+end:
-+ *pos_ptr= curr_chunk;
-+ *off_ptr= dst_offset;
-+
-+ return rc;
-+}
-+
-+/**
-+ Encodes or compares record
-+
-+ Copies data from original unpacked record into the preallocated chunkset,
-+ or performs data comparison
-+
-+ @param info the hosting table
-+ @param record the record in standard unpacked format
-+ @param pos the target chunkset
-+ @param is_compare flag indicating whether we should compare data or store
-+ it
-+
-+ @return Status of comparison
-+ @retval non-zero if comparison fond data differences
-+ @retval zero otherwise
-+*/
-+
-+uint hp_process_record_data_to_chunkset(HP_SHARE *info, const uchar *record,
-+ uchar *pos, uint is_compare)
-+{
-+ uint i, dst_offset;
-+ uchar *curr_chunk= pos;
-+
-+ if (is_compare)
-+ {
-+ if (memcmp(curr_chunk, record, (size_t) info->fixed_data_length))
-+ {
-+ return 1;
-+ }
-+ }
-+ else
-+ {
-+ memcpy(curr_chunk, record, (size_t) info->fixed_data_length);
-+ }
-+
-+ if (!info->recordspace.is_variable_size)
-+ {
-+ /* Nothing more to copy */
-+ return 0;
-+ }
-+
-+ dst_offset= info->fixed_data_length;
-+
-+ for (i= info->fixed_column_count; i < info->column_count; i++)
-+ {
-+ uint length;
-+ const uchar *data;
-+
-+ HP_COLUMNDEF *column= info->column_defs + i;
-+
-+ if (column->null_bit)
-+ {
-+ if (record[column->null_pos] & column->null_bit)
-+ {
-+ /* Skip all NULL values */
-+ continue;
-+ }
-+ }
-+
-+ data= record + column->offset;
-+ if (column->type == MYSQL_TYPE_VARCHAR)
-+ {
-+ uint pack_length;
-+
-+ /* >= 5.0.3 true VARCHAR */
-+
-+ /* Make sure to copy length indicator and actuals string bytes */
-+ pack_length= column->length_bytes;
-+ length= pack_length + (pack_length == 1 ? (uint) *data : uint2korr(data));
-+ }
-+ else if (column->type == MYSQL_TYPE_BLOB)
-+ {
-+ uint pack_length;
-+
-+ pack_length= column->length_bytes;
-+ /* Just want to store the length, so not interested in the return code */
-+ (void) hp_process_field_data_to_chunkset(info, data, pack_length,
-+ &curr_chunk, &dst_offset, 0);
-+ length= hp_calc_blob_length(pack_length, data);
-+ memcpy(&data, data + pack_length, sizeof(char *));
-+ }
-+ else
-+ {
-+ length= column->length;
-+ }
-+
-+ if (hp_process_field_data_to_chunkset(info, data, length, &curr_chunk,
-+ &dst_offset, is_compare))
-+ {
-+ return 1;
-+ }
-+ }
-+
-+#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
-+ dump_chunk(info, curr_chunk);
-+#endif
-+
-+ return 0;
-+}
-+
-+
-+/**
-+ Stores record in the heap table chunks
-+
-+ Copies data from original unpacked record into the preallocated chunkset
-+
-+ @param info the hosting table
-+ @param record the record in standard unpacked format
-+ @param pos the target chunkset
-+*/
-+
-+void hp_copy_record_data_to_chunkset(HP_SHARE *info, const uchar *record,
-+ uchar *pos)
-+{
-+ DBUG_ENTER("hp_copy_record_data_to_chunks");
-+
-+ hp_process_record_data_to_chunkset(info, record, pos, 0);
-+
-+ DBUG_VOID_RETURN;
-+}
-+
-+
-+/*
-+ Macro to switch curr_chunk to the next chunk in the chunkset and reset
-+ src_offset.
-+*/
-+#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
-+#define SWITCH_TO_NEXT_CHUNK_FOR_READ(share, curr_chunk, src_offset) \
-+ { \
-+ curr_chunk= *((uchar**) (curr_chunk + share->recordspace.offset_link)); \
-+ src_offset= 0; \
-+ dump_chunk(share, curr_chunk); \
-+ }
-+#else
-+#define SWITCH_TO_NEXT_CHUNK_FOR_READ(share, curr_chunk, src_offset) \
-+ { \
-+ curr_chunk= *((uchar**) (curr_chunk + share->recordspace.offset_link)); \
-+ src_offset= 0; \
-+ }
-+#endif
-+
-+/**
-+ Copies record data from storage to unpacked record format
-+
-+ Copies data from chunkset into its original unpacked record
-+
-+ @param info the hosting table
-+ @param[out] record the target record in standard unpacked format
-+ @param pos the source chunkset
-+
-+ @return Status of conversion
-+ @retval 0 success
-+ @retval 1 out of memory
-+*/
-+
-+int hp_extract_record(HP_INFO *info, uchar *record, const uchar *pos)
-+{
-+ uint i, src_offset;
-+ const uchar *curr_chunk= pos;
-+ HP_SHARE *share= info->s;
-+ uint *rec_offsets= NULL;
-+ uint *buf_offsets= NULL;
-+ uint nblobs= 0;
-+ uint init_offset= share->blobs * sizeof(uint) * 2;
-+
-+ DBUG_ENTER("hp_extract_record");
-+
-+#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
-+ if (share->recordspace.is_variable_size)
-+ {
-+ dump_chunk(share, curr_chunk);
-+ }
-+#endif
-+
-+ memcpy(record, curr_chunk, (size_t) share->fixed_data_length);
-+
-+ if (!share->recordspace.is_variable_size)
-+ {
-+ /* Nothing more to copy */
-+ DBUG_RETURN(0);
-+ }
-+
-+ /* Reserve space for rec_offsets and buf_offsets.*/
-+ info->blob_offset= init_offset;
-+ src_offset= share->fixed_data_length;
-+
-+ for (i= share->fixed_column_count; i < share->column_count; i++)
-+ {
-+ uint length, is_null= 0;
-+ uchar *to;
-+
-+ HP_COLUMNDEF *column= share->column_defs + i;
-+
-+ if (column->null_bit)
-+ {
-+ if (record[column->null_pos] & column->null_bit)
-+ {
-+ is_null= 1;
-+ }
-+ }
-+
-+ if (is_null)
-+ {
-+ /* TODO: is memset really needed? */
-+ memset(record + column->offset, 0, column->length);
-+ continue;
-+ }
-+
-+ to= record + column->offset;
-+ if (column->type == MYSQL_TYPE_VARCHAR || column->type == MYSQL_TYPE_BLOB)
-+ {
-+ uint pack_length, i;
-+ uchar *tmp= to;
-+
-+ pack_length= column->length_bytes;
-+
-+ for (i= 0; i < pack_length; i++)
-+ {
-+ if (src_offset == share->recordspace.chunk_dataspace_length)
-+ {
-+ SWITCH_TO_NEXT_CHUNK_FOR_READ(share, curr_chunk, src_offset);
-+ }
-+ *to++= curr_chunk[src_offset++];
-+ }
-+ /*
-+ We copy byte-by-byte and then use hp_calc_blob_length to combine bytes
-+ in the right order.
-+ */
-+ length= hp_calc_blob_length(pack_length, tmp);
-+
-+ if (column->type == MYSQL_TYPE_BLOB && length == 0)
-+ {
-+ /*
-+ Store a zero pointer for zero-length BLOBs because the server
-+ relies on that (see Field_blob::val_*().
-+ */
-+ *(uchar **) to= 0;
-+ }
-+ else if (column->type == MYSQL_TYPE_BLOB && length > 0)
-+ {
-+ uint newsize= info->blob_offset + length;
-+
-+ DBUG_ASSERT(share->blobs > 0);
-+ /*
-+ Make sure we have enough space in blob_buffer and store the pointer
-+ to this blob in record.
-+ */
-+ if (info->blob_size < newsize)
-+ {
-+ uchar *ptr;
-+ ptr= my_realloc(info->blob_buffer, newsize, MYF(MY_ALLOW_ZERO_PTR));
-+ if (ptr == NULL)
-+ {
-+ DBUG_RETURN(1);
-+ }
-+
-+ if (info->blob_buffer == NULL)
-+ {
-+ memset(ptr, 0, init_offset);
-+ }
-+ info->blob_buffer= ptr;
-+ info->blob_size= newsize;
-+ }
-+
-+ rec_offsets= (uint *) info->blob_buffer;
-+ buf_offsets= rec_offsets + share->blobs;
-+
-+ rec_offsets[nblobs]= (uint) (to - record);
-+ buf_offsets[nblobs]= info->blob_offset;
-+ nblobs++;
-+
-+ /* Change 'to' so blob data is copied into blob_buffer */
-+ to= info->blob_buffer + info->blob_offset;
-+ info->blob_offset= newsize;
-+ }
-+ }
-+ else
-+ {
-+ length= column->length;
-+ }
-+
-+ while (length > 0)
-+ {
-+ uint to_copy;
-+
-+ to_copy= share->recordspace.chunk_dataspace_length - src_offset;
-+ if (to_copy == 0)
-+ {
-+ SWITCH_TO_NEXT_CHUNK_FOR_READ(share, curr_chunk, src_offset);
-+ to_copy= share->recordspace.chunk_dataspace_length;
-+ }
-+
-+ to_copy= min(length, to_copy);
-+
-+ memcpy(to, curr_chunk + src_offset, (size_t) to_copy);
-+ src_offset+= to_copy;
-+ to+= to_copy;
-+ length-= to_copy;
-+ }
-+ }
-+
-+ /* Store pointers to blob data in record */
-+ for (i= 0; i < nblobs; i++)
-+ {
-+ *(uchar **) (record + rec_offsets[i]) = info->blob_buffer + buf_offsets[i];
-+ }
-+
-+ DBUG_RETURN(0);
-+}
---- a/storage/heap/hp_rfirst.c
-+++ b/storage/heap/hp_rfirst.c
-@@ -34,7 +34,10 @@
- memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos),
- sizeof(uchar*));
- info->current_ptr = pos;
-- memcpy(record, pos, (size_t)share->reclength);
-+ if (hp_extract_record(info, record, pos))
-+ {
-+ DBUG_RETURN(my_errno);
-+ }
- /*
- If we're performing index_first on a table that was taken from
- table cache, info->lastkey_len is initialized to previous query.
---- a/storage/heap/hp_rkey.c
-+++ b/storage/heap/hp_rkey.c
-@@ -67,7 +67,10 @@
- if (!(keyinfo->flag & HA_NOSAME))
- memcpy(info->lastkey, key, (size_t) keyinfo->length);
- }
-- memcpy(record, pos, (size_t) share->reclength);
-+ if (hp_extract_record(info, record, pos))
-+ {
-+ DBUG_RETURN(my_errno);
-+ }
- info->update= HA_STATE_AKTIV;
- DBUG_RETURN(0);
- }
---- a/storage/heap/hp_rlast.c
-+++ b/storage/heap/hp_rlast.c
-@@ -35,7 +35,10 @@
- memcpy(&pos, pos + (*keyinfo->get_key_length)(keyinfo, pos),
- sizeof(uchar*));
- info->current_ptr = pos;
-- memcpy(record, pos, (size_t)share->reclength);
-+ if (hp_extract_record(info, record, pos))
-+ {
-+ DBUG_RETURN(my_errno);
-+ }
- info->update = HA_STATE_AKTIV;
- }
- else
---- a/storage/heap/hp_rnext.c
-+++ b/storage/heap/hp_rnext.c
-@@ -109,7 +109,10 @@
- my_errno=HA_ERR_END_OF_FILE;
- DBUG_RETURN(my_errno);
- }
-- memcpy(record,pos,(size_t) share->reclength);
-+ if (hp_extract_record(info, record, pos))
-+ {
-+ DBUG_RETURN(my_errno);
-+ }
- info->update=HA_STATE_AKTIV | HA_STATE_NEXT_FOUND;
- DBUG_RETURN(0);
- }
---- a/storage/heap/hp_rprev.c
-+++ b/storage/heap/hp_rprev.c
-@@ -77,7 +77,10 @@
- my_errno=HA_ERR_END_OF_FILE;
- DBUG_RETURN(my_errno);
- }
-- memcpy(record,pos,(size_t) share->reclength);
-+ if (hp_extract_record(info, record, pos))
-+ {
-+ DBUG_RETURN(my_errno);
-+ }
- info->update=HA_STATE_AKTIV | HA_STATE_PREV_FOUND;
- DBUG_RETURN(0);
- }
---- a/storage/heap/hp_rrnd.c
-+++ b/storage/heap/hp_rrnd.c
-@@ -36,13 +36,18 @@
- info->update= 0;
- DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE);
- }
-- if (!info->current_ptr[share->reclength])
-+ if (get_chunk_status(&share->recordspace, info->current_ptr) !=
-+ CHUNK_STATUS_ACTIVE)
- {
-+ /* treat deleted and linked chunks as deleted */
- info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND;
- DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED);
- }
- info->update=HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV;
-- memcpy(record,info->current_ptr,(size_t) share->reclength);
-+ if (hp_extract_record(info, record, info->current_ptr))
-+ {
-+ DBUG_RETURN(my_errno);
-+ }
- DBUG_PRINT("exit", ("found record at 0x%lx", (long) info->current_ptr));
- info->current_hash_ptr=0; /* Can't use rnext */
- DBUG_RETURN(0);
-@@ -70,17 +75,17 @@
- {
- pos= ++info->current_record;
- if (pos % share->block.records_in_block && /* Quick next record */
-- pos < share->records+share->deleted &&
-- (info->update & HA_STATE_PREV_FOUND))
-+ pos < share->used_chunk_count + share->deleted_chunk_count &&
-+ (info->update & HA_STATE_PREV_FOUND))
- {
-- info->current_ptr+=share->block.recbuffer;
-+ info->current_ptr+= share->block.recbufferlen;
- goto end;
- }
- }
- else
- info->current_record=pos;
-
-- if (pos >= share->records+share->deleted)
-+ if (pos >= share->used_chunk_count + share->deleted_chunk_count)
- {
- info->update= 0;
- DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE);
-@@ -90,13 +95,17 @@
- hp_find_record(info, pos);
-
- end:
-- if (!info->current_ptr[share->reclength])
-+ if (GET_CHUNK_STATUS(info, info->current_ptr) != CHUNK_STATUS_ACTIVE)
- {
-+ /* treat deleted and linked chunks as deleted */
- info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND;
- DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED);
- }
- info->update=HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV;
-- memcpy(record,info->current_ptr,(size_t) share->reclength);
-+ if (hp_extract_record(info, record, info->current_ptr))
-+ {
-+ DBUG_RETURN(my_errno);
-+ }
- DBUG_PRINT("exit",("found record at 0x%lx",info->current_ptr));
- info->current_hash_ptr=0; /* Can't use rnext */
- DBUG_RETURN(0);
---- a/storage/heap/hp_rsame.c
-+++ b/storage/heap/hp_rsame.c
-@@ -31,7 +31,8 @@
- DBUG_ENTER("heap_rsame");
-
- test_active(info);
-- if (info->current_ptr[share->reclength])
-+ if (get_chunk_status(&share->recordspace, info->current_ptr) ==
-+ CHUNK_STATUS_ACTIVE)
- {
- if (inx < -1 || inx >= (int) share->keys)
- {
-@@ -47,9 +48,15 @@
- DBUG_RETURN(my_errno);
- }
- }
-- memcpy(record,info->current_ptr,(size_t) share->reclength);
-+ if (hp_extract_record(info, record, info->current_ptr))
-+ {
-+ DBUG_RETURN(my_errno);
-+ }
- DBUG_RETURN(0);
- }
-+
-+ /* treat deleted and linked chunks as deleted */
-+
- info->update=0;
-
- DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED);
---- a/storage/heap/hp_scan.c
-+++ b/storage/heap/hp_scan.c
-@@ -30,7 +30,6 @@
- info->lastinx= -1;
- info->current_record= (ulong) ~0L; /* No current record */
- info->update=0;
-- info->next_block=0;
- DBUG_RETURN(0);
- }
-
-@@ -41,32 +40,26 @@
- DBUG_ENTER("heap_scan");
-
- pos= ++info->current_record;
-- if (pos < info->next_block)
-+ if (pos >= share->recordspace.chunk_count)
- {
-- info->current_ptr+=share->block.recbuffer;
-+ info->update= 0;
-+ DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE);
- }
-- else
-- {
-- info->next_block+=share->block.records_in_block;
-- if (info->next_block >= share->records+share->deleted)
-- {
-- info->next_block= share->records+share->deleted;
-- if (pos >= info->next_block)
-- {
-- info->update= 0;
-- DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE);
-- }
-- }
-- hp_find_record(info, pos);
-- }
-- if (!info->current_ptr[share->reclength])
-+
-+ hp_find_record(info, pos);
-+
-+ if (get_chunk_status(&share->recordspace, info->current_ptr) !=
-+ CHUNK_STATUS_ACTIVE)
- {
-- DBUG_PRINT("warning",("Found deleted record"));
-+ DBUG_PRINT("warning",("Found deleted record or secondary chunk"));
- info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND;
- DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED);
- }
- info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV;
-- memcpy(record,info->current_ptr,(size_t) share->reclength);
-+ if (hp_extract_record(info, record, info->current_ptr))
-+ {
-+ DBUG_RETURN(my_errno);
-+ }
- info->current_hash_ptr=0; /* Can't use read_next */
- DBUG_RETURN(0);
- } /* heap_scan */
---- a/storage/heap/hp_test1.c
-+++ b/storage/heap/hp_test1.c
-@@ -22,6 +22,7 @@
- #include <my_global.h>
- #include <my_sys.h>
- #include <m_string.h>
-+#include <mysql_com.h>
- #include "heap.h"
-
- static int get_options(int argc, char *argv[]);
-@@ -35,6 +36,7 @@
- uchar record[128],key[32];
- const char *filename;
- HP_KEYDEF keyinfo[10];
-+ HP_COLUMNDEF columndef[2];
- HA_KEYSEG keyseg[4];
- HP_CREATE_INFO hp_create_info;
- HP_SHARE *tmp_share;
-@@ -51,6 +53,10 @@
- hp_create_info.reclength= 30;
- hp_create_info.max_records= (ulong) flag*100000L;
- hp_create_info.min_records= 10UL;
-+ hp_create_info.columns= 2;
-+ hp_create_info.columndef= columndef;
-+ hp_create_info.fixed_key_fieldnr= 30;
-+ hp_create_info.fixed_data_size= sizeof(char*) * 2;
-
- keyinfo[0].keysegs=1;
- keyinfo[0].seg=keyseg;
-@@ -62,11 +68,20 @@
- keyinfo[0].seg[0].null_bit= 0;
- keyinfo[0].flag = HA_NOSAME;
-
-+ memset(columndef, 0, 2 * sizeof(HP_COLUMNDEF));
-+ columndef[0].type= MYSQL_TYPE_STRING;
-+ columndef[0].offset= 1;
-+ columndef[0].length= 6;
-+ columndef[1].type= MYSQL_TYPE_STRING;
-+ columndef[1].offset= 7;
-+ columndef[1].length= 23;
-+
- deleted=0;
- bzero((uchar*) flags,sizeof(flags));
-
- printf("- Creating heap-file\n");
-- if (heap_create(filename, &hp_create_info, &tmp_share, &unused) ||
-+ if (heap_create(filename, &hp_create_info,
-+ &tmp_share, &unused) ||
- !(file= heap_open(filename, 2)))
- goto err;
- printf("- Writing records:s\n");
---- a/storage/heap/hp_test2.c
-+++ b/storage/heap/hp_test2.c
-@@ -18,6 +18,7 @@
-
- #include "heapdef.h" /* Because of hp_find_block */
- #include <signal.h>
-+#include <mysql_com.h>
-
- #define MAX_RECORDS 100000
- #define MAX_KEYS 4
-@@ -53,6 +54,7 @@
- HP_SHARE *tmp_share;
- HP_KEYDEF keyinfo[MAX_KEYS];
- HA_KEYSEG keyseg[MAX_KEYS*5];
-+ HP_COLUMNDEF columndef[4];
- HEAP_PTR UNINIT_VAR(position);
- HP_CREATE_INFO hp_create_info;
- CHARSET_INFO *cs= &my_charset_latin1;
-@@ -65,12 +67,16 @@
- get_options(argc,argv);
-
- bzero(&hp_create_info, sizeof(hp_create_info));
-- hp_create_info.max_table_size= 1024L*1024L;
-+ hp_create_info.max_table_size= 1024L*1024L*1024L;
- hp_create_info.keys= keys;
- hp_create_info.keydef= keyinfo;
- hp_create_info.reclength= reclength;
- hp_create_info.max_records= (ulong) flag*100000L;
- hp_create_info.min_records= (ulong) recant/2;
-+ hp_create_info.columns= 4;
-+ hp_create_info.columndef= columndef;
-+ hp_create_info.fixed_key_fieldnr= 4;
-+ hp_create_info.fixed_data_size= 39;
-
- write_count=update=opt_delete=0;
- key_check=0;
-@@ -118,11 +124,28 @@
- keyinfo[3].seg[0].null_pos=38;
- keyinfo[3].seg[0].charset=cs;
-
-+ memset(columndef, 0, 4 * sizeof(HP_COLUMNDEF));
-+ columndef[0].type= MYSQL_TYPE_STRING;
-+ columndef[0].offset= 0;
-+ columndef[0].length= 6;
-+ columndef[1].type= MYSQL_TYPE_STRING;
-+ columndef[1].offset= 7;
-+ columndef[1].length= 6;
-+ columndef[2].type= MYSQL_TYPE_STRING;
-+ columndef[2].offset= 12;
-+ columndef[2].length= 8;
-+ columndef[3].type= MYSQL_TYPE_TINY;
-+ columndef[3].offset= 37;
-+ columndef[3].length= 1;
-+ columndef[3].null_bit= 1;
-+ columndef[3].null_pos= 38;
-+
- bzero((char*) key1,sizeof(key1));
- bzero((char*) key3,sizeof(key3));
-
- printf("- Creating heap-file\n");
-- if (heap_create(filename, &hp_create_info, &tmp_share, &unused) ||
-+ if (heap_create(filename, &hp_create_info,
-+ &tmp_share, &unused) ||
- !(file= heap_open(filename, 2)))
- goto err;
- signal(SIGINT,endprog);
---- a/storage/heap/hp_write.c
-+++ b/storage/heap/hp_write.c
-@@ -26,7 +26,6 @@
- #define HIGHFIND 4
- #define HIGHUSED 8
-
--static uchar *next_free_record_pos(HP_SHARE *info);
- static HASH_INFO *hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block,
- ulong records);
-
-@@ -35,6 +34,8 @@
- HP_KEYDEF *keydef, *end;
- uchar *pos;
- HP_SHARE *share=info->s;
-+ uint chunk_count;
-+
- DBUG_ENTER("heap_write");
- #ifndef DBUG_OFF
- if (info->mode & O_RDONLY)
-@@ -42,7 +43,18 @@
- DBUG_RETURN(my_errno=EACCES);
- }
- #endif
-- if (!(pos=next_free_record_pos(share)))
-+
-+ if ((share->records >= share->max_records && share->max_records) ||
-+ (share->recordspace.total_data_length + share->index_length >=
-+ share->max_table_size))
-+ {
-+ my_errno= HA_ERR_RECORD_FILE_FULL;
-+ DBUG_RETURN(my_errno);
-+ }
-+
-+ hp_get_encoded_data_length(share, record, &chunk_count);
-+
-+ if (!(pos= hp_allocate_chunkset(&share->recordspace, chunk_count)))
- DBUG_RETURN(my_errno);
- share->changed=1;
-
-@@ -53,8 +65,8 @@
- goto err;
- }
-
-- memcpy(pos,record,(size_t) share->reclength);
-- pos[share->reclength]=1; /* Mark record as not deleted */
-+ hp_copy_record_data_to_chunkset(share, record, pos);
-+
- if (++share->records == share->blength)
- share->blength+= share->blength;
- info->current_ptr=pos;
-@@ -88,10 +100,7 @@
- keydef--;
- }
-
-- share->deleted++;
-- *((uchar**) pos)=share->del_link;
-- share->del_link=pos;
-- pos[share->reclength]=0; /* Record deleted */
-+ hp_free_chunks(&share->recordspace, pos);
-
- DBUG_RETURN(my_errno);
- } /* heap_write */
-@@ -107,7 +116,8 @@
- uint old_allocated;
-
- custom_arg.keyseg= keyinfo->seg;
-- custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
-+ custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos,
-+ FALSE);
- if (keyinfo->flag & HA_NOSAME)
- {
- custom_arg.search_flag= SEARCH_FIND | SEARCH_UPDATE;
-@@ -129,42 +139,6 @@
- return 0;
- }
-
-- /* Find where to place new record */
--
--static uchar *next_free_record_pos(HP_SHARE *info)
--{
-- int block_pos;
-- uchar *pos;
-- size_t length;
-- DBUG_ENTER("next_free_record_pos");
--
-- if (info->del_link)
-- {
-- pos=info->del_link;
-- info->del_link= *((uchar**) pos);
-- info->deleted--;
-- DBUG_PRINT("exit",("Used old position: 0x%lx",(long) pos));
-- DBUG_RETURN(pos);
-- }
-- if (!(block_pos=(info->records % info->block.records_in_block)))
-- {
-- if ((info->records > info->max_records && info->max_records) ||
-- (info->data_length + info->index_length >= info->max_table_size))
-- {
-- my_errno=HA_ERR_RECORD_FILE_FULL;
-- DBUG_RETURN(NULL);
-- }
-- if (hp_get_new_block(&info->block,&length))
-- DBUG_RETURN(NULL);
-- info->data_length+=length;
-- }
-- DBUG_PRINT("exit",("Used new position: 0x%lx",
-- (long) ((uchar*) info->block.level_info[0].last_blocks+
-- block_pos * info->block.recbuffer)));
-- DBUG_RETURN((uchar*) info->block.level_info[0].last_blocks+
-- block_pos*info->block.recbuffer);
--}
--
-
- /*
- Write a hash-key to the hash-index
---- a/storage/heap/hp_update.c
-+++ b/storage/heap/hp_update.c
-@@ -17,43 +17,65 @@
-
- #include "heapdef.h"
-
--int heap_update(HP_INFO *info, const uchar *old, const uchar *heap_new)
-+int heap_update(HP_INFO *info, const uchar *old_record, const uchar *new_record)
- {
- HP_KEYDEF *keydef, *end, *p_lastinx;
- uchar *pos;
- my_bool auto_key_changed= 0;
- HP_SHARE *share= info->s;
-+ uint old_chunk_count, new_chunk_count;
-+
- DBUG_ENTER("heap_update");
-
- test_active(info);
- pos=info->current_ptr;
-
-- if (info->opt_flag & READ_CHECK_USED && hp_rectest(info,old))
-+ if (info->opt_flag & READ_CHECK_USED && hp_rectest(info, old_record))
- DBUG_RETURN(my_errno); /* Record changed */
-+
-+ hp_get_encoded_data_length(share, old_record, &old_chunk_count);
-+ hp_get_encoded_data_length(share, new_record, &new_chunk_count);
-+
-+ if (new_chunk_count > old_chunk_count)
-+ {
-+ /* extend the old chunkset size as necessary, but do not shrink yet */
-+ if (hp_reallocate_chunkset(&share->recordspace, new_chunk_count, pos))
-+ {
-+ DBUG_RETURN(my_errno); /* Out of memory or table space */
-+ }
-+ }
-+
- if (--(share->records) < share->blength >> 1) share->blength>>= 1;
- share->changed=1;
-
- p_lastinx= share->keydef + info->lastinx;
- for (keydef= share->keydef, end= keydef + share->keys; keydef < end; keydef++)
- {
-- if (hp_rec_key_cmp(keydef, old, heap_new, 0))
-+ if (hp_rec_key_cmp(keydef, old_record, new_record, 0))
- {
-- if ((*keydef->delete_key)(info, keydef, old, pos, keydef == p_lastinx) ||
-- (*keydef->write_key)(info, keydef, heap_new, pos))
-+ if ((*keydef->delete_key)(info, keydef, old_record, pos,
-+ keydef == p_lastinx) ||
-+ (*keydef->write_key)(info, keydef, new_record, pos))
- goto err;
- if (share->auto_key == (uint) (keydef - share->keydef + 1))
- auto_key_changed= 1;
- }
- }
-
-- memcpy(pos,heap_new,(size_t) share->reclength);
-+ hp_copy_record_data_to_chunkset(share, new_record, pos);
- if (++(share->records) == share->blength) share->blength+= share->blength;
-
-+ if (new_chunk_count < old_chunk_count)
-+ {
-+ /* Shrink the chunkset to its new size */
-+ hp_reallocate_chunkset(&share->recordspace, new_chunk_count, pos);
-+ }
-+
- #if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
- DBUG_EXECUTE("check_heap",heap_check_heap(info, 0););
- #endif
- if (auto_key_changed)
-- heap_update_auto_increment(info, heap_new);
-+ heap_update_auto_increment(info, new_record);
- DBUG_RETURN(0);
-
- err:
-@@ -63,7 +85,7 @@
- if (keydef->algorithm == HA_KEY_ALG_BTREE)
- {
- /* we don't need to delete non-inserted key from rb-tree */
-- if ((*keydef->write_key)(info, keydef, old, pos))
-+ if ((*keydef->write_key)(info, keydef, old_record, pos))
- {
- if (++(share->records) == share->blength)
- share->blength+= share->blength;
-@@ -73,10 +95,10 @@
- }
- while (keydef >= share->keydef)
- {
-- if (hp_rec_key_cmp(keydef, old, heap_new, 0))
-+ if (hp_rec_key_cmp(keydef, old_record, new_record, 0))
- {
-- if ((*keydef->delete_key)(info, keydef, heap_new, pos, 0) ||
-- (*keydef->write_key)(info, keydef, old, pos))
-+ if ((*keydef->delete_key)(info, keydef, new_record, pos, 0) ||
-+ (*keydef->write_key)(info, keydef, old_record, pos))
- break;
- }
- keydef--;
-@@ -84,5 +106,12 @@
- }
- if (++(share->records) == share->blength)
- share->blength+= share->blength;
-+
-+ if (new_chunk_count > old_chunk_count)
-+ {
-+ /* Shrink the chunkset to its original size */
-+ hp_reallocate_chunkset(&share->recordspace, old_chunk_count, pos);
-+ }
-+
- DBUG_RETURN(my_errno);
- } /* heap_update */
---- /dev/null
-+++ b/mysql-test/r/percona_heap_blob.result
-@@ -0,0 +1,956 @@
-+SET @old_default_storage_engine=@@default_storage_engine;
-+SET default_storage_engine=MEMORY;
-+drop table if exists t1,t2,t3,t4,t5,t6,t7;
-+CREATE TABLE t1 (a blob, b text, c blob(250), d text(70000), e text(70000000));
-+show columns from t1;
-+Field Type Null Key Default Extra
-+a blob YES NULL
-+b text YES NULL
-+c tinyblob YES NULL
-+d mediumtext YES NULL
-+e longtext YES NULL
-+CREATE TABLE t2 (a char(255), b varbinary(70000), c varchar(70000000));
-+Warnings:
-+Note 1246 Converting column 'b' from VARBINARY to BLOB
-+Note 1246 Converting column 'c' from VARCHAR to TEXT
-+CREATE TABLE t4 (c varchar(65530) character set utf8 not null);
-+Warnings:
-+Note 1246 Converting column 'c' from VARCHAR to TEXT
-+show columns from t2;
-+Field Type Null Key Default Extra
-+a char(255) YES NULL
-+b mediumblob YES NULL
-+c longtext YES NULL
-+create table t3 (a long, b long byte);
-+show create TABLE t3;
-+Table Create Table
-+t3 CREATE TABLE `t3` (
-+ `a` mediumtext,
-+ `b` mediumblob
-+) ENGINE=MEMORY DEFAULT CHARSET=latin1
-+show create TABLE t4;
-+Table Create Table
-+t4 CREATE TABLE `t4` (
-+ `c` mediumtext CHARACTER SET utf8 NOT NULL
-+) ENGINE=MEMORY DEFAULT CHARSET=latin1
-+drop table t1,t2,t3,t4;
-+CREATE TABLE t1 (a char(257) default "hello");
-+ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB or TEXT instead
-+CREATE TABLE t2 (a char(256));
-+ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB or TEXT instead
-+CREATE TABLE t1 (a varchar(70000) default "hello");
-+ERROR 42000: Column length too big for column 'a' (max = 65535); use BLOB or TEXT instead
-+CREATE TABLE t2 (a blob default "hello");
-+ERROR 42000: BLOB/TEXT column 'a' can't have a default value
-+drop table if exists t1,t2;
-+create table t1 (nr int(5) not null auto_increment,b blob,str char(10), primary key (nr));
-+insert into t1 values (null,"a","A");
-+insert into t1 values (null,"bbb","BBB");
-+insert into t1 values (null,"ccc","CCC");
-+select last_insert_id();
-+last_insert_id()
-+3
-+select * from t1,t1 as t2;
-+nr b str nr b str
-+1 a A 1 a A
-+2 bbb BBB 1 a A
-+3 ccc CCC 1 a A
-+1 a A 2 bbb BBB
-+2 bbb BBB 2 bbb BBB
-+3 ccc CCC 2 bbb BBB
-+1 a A 3 ccc CCC
-+2 bbb BBB 3 ccc CCC
-+3 ccc CCC 3 ccc CCC
-+drop table t1;
-+create table t1 (a text);
-+insert into t1 values ('where');
-+update t1 set a='Where';
-+select * from t1;
-+a
-+Where
-+drop table t1;
-+create table t1 (t text,c char(10),b blob, d varbinary(10)) collate latin1_general_cs;
-+insert into t1 values (NULL,NULL,NULL,NULL);
-+insert into t1 values ("","","","");
-+insert into t1 values ("hello","hello","hello","hello");
-+insert into t1 values ("HELLO","HELLO","HELLO","HELLO");
-+insert into t1 values ("HELLO MY","HELLO MY","HELLO MY","HELLO MY");
-+insert into t1 values ("a","a","a","a");
-+insert into t1 values (1,1,1,1);
-+insert into t1 values (NULL,NULL,NULL,NULL);
-+update t1 set c="",b=null where c="1";
-+lock tables t1 READ;
-+show full fields from t1;
-+Field Type Collation Null Key Default Extra Privileges Comment
-+t text latin1_general_cs YES NULL #
-+c char(10) latin1_general_cs YES NULL #
-+b blob NULL YES NULL #
-+d varbinary(10) NULL YES NULL #
-+lock tables t1 WRITE;
-+show full fields from t1;
-+Field Type Collation Null Key Default Extra Privileges Comment
-+t text latin1_general_cs YES NULL #
-+c char(10) latin1_general_cs YES NULL #
-+b blob NULL YES NULL #
-+d varbinary(10) NULL YES NULL #
-+unlock tables;
-+select t from t1 where t like "hello";
-+t
-+hello
-+select c from t1 where c like "hello";
-+c
-+hello
-+select b from t1 where b like "hello";
-+b
-+hello
-+select d from t1 where d like "hello";
-+d
-+hello
-+select c from t1 having c like "hello";
-+c
-+hello
-+select d from t1 having d like "hello";
-+d
-+hello
-+select t from t1 where t like "%HELLO%";
-+t
-+HELLO
-+HELLO MY
-+select c from t1 where c like "%HELLO%";
-+c
-+HELLO
-+HELLO MY
-+select b from t1 where b like "%HELLO%";
-+b
-+HELLO
-+HELLO MY
-+select d from t1 where d like "%HELLO%";
-+d
-+HELLO
-+HELLO MY
-+select c from t1 having c like "%HELLO%";
-+c
-+HELLO
-+HELLO MY
-+select d from t1 having d like "%HELLO%";
-+d
-+HELLO
-+HELLO MY
-+select d from t1 having d like "%HE%LLO%";
-+d
-+HELLO
-+HELLO MY
-+select t from t1 order by t;
-+t
-+NULL
-+NULL
-+
-+1
-+a
-+HELLO
-+HELLO MY
-+hello
-+select c from t1 order by c;
-+c
-+NULL
-+NULL
-+
-+
-+a
-+HELLO
-+HELLO MY
-+hello
-+select b from t1 order by b;
-+b
-+NULL
-+NULL
-+NULL
-+
-+HELLO
-+HELLO MY
-+a
-+hello
-+select d from t1 order by d;
-+d
-+NULL
-+NULL
-+
-+1
-+HELLO
-+HELLO MY
-+a
-+hello
-+select distinct t from t1;
-+t
-+NULL
-+
-+hello
-+HELLO
-+HELLO MY
-+a
-+1
-+select distinct b from t1;
-+b
-+NULL
-+
-+hello
-+HELLO
-+HELLO MY
-+a
-+select distinct t from t1 order by t;
-+t
-+NULL
-+
-+1
-+a
-+HELLO
-+HELLO MY
-+hello
-+select distinct b from t1 order by b;
-+b
-+NULL
-+
-+HELLO
-+HELLO MY
-+a
-+hello
-+select t from t1 group by t;
-+t
-+NULL
-+
-+1
-+a
-+HELLO
-+HELLO MY
-+hello
-+select b from t1 group by b;
-+b
-+NULL
-+
-+HELLO
-+HELLO MY
-+a
-+hello
-+set option sql_big_tables=1;
-+select distinct t from t1;
-+t
-+NULL
-+
-+hello
-+HELLO
-+HELLO MY
-+a
-+1
-+select distinct b from t1;
-+b
-+NULL
-+
-+hello
-+HELLO
-+HELLO MY
-+a
-+select distinct t from t1 order by t;
-+t
-+NULL
-+
-+1
-+a
-+HELLO
-+HELLO MY
-+hello
-+select distinct b from t1 order by b;
-+b
-+NULL
-+
-+HELLO
-+HELLO MY
-+a
-+hello
-+select distinct c from t1;
-+c
-+NULL
-+
-+hello
-+HELLO
-+HELLO MY
-+a
-+select distinct d from t1;
-+d
-+NULL
-+
-+hello
-+HELLO
-+HELLO MY
-+a
-+1
-+select distinct c from t1 order by c;
-+c
-+NULL
-+
-+a
-+HELLO
-+HELLO MY
-+hello
-+select distinct d from t1 order by d;
-+d
-+NULL
-+
-+1
-+HELLO
-+HELLO MY
-+a
-+hello
-+select c from t1 group by c;
-+c
-+NULL
-+
-+a
-+HELLO
-+HELLO MY
-+hello
-+select d from t1 group by d;
-+d
-+NULL
-+
-+1
-+HELLO
-+HELLO MY
-+a
-+hello
-+set option sql_big_tables=0;
-+select distinct * from t1;
-+t c b d
-+NULL NULL NULL NULL
-+
-+hello hello hello hello
-+HELLO HELLO HELLO HELLO
-+HELLO MY HELLO MY HELLO MY HELLO MY
-+a a a a
-+1 NULL 1
-+select t,count(*) from t1 group by t;
-+t count(*)
-+NULL 2
-+ 1
-+1 1
-+a 1
-+HELLO 1
-+HELLO MY 1
-+hello 1
-+select b,count(*) from t1 group by b;
-+b count(*)
-+NULL 3
-+ 1
-+HELLO 1
-+HELLO MY 1
-+a 1
-+hello 1
-+select c,count(*) from t1 group by c;
-+c count(*)
-+NULL 2
-+ 2
-+a 1
-+HELLO 1
-+HELLO MY 1
-+hello 1
-+select d,count(*) from t1 group by d;
-+d count(*)
-+NULL 2
-+ 1
-+1 1
-+HELLO 1
-+HELLO MY 1
-+a 1
-+hello 1
-+drop table t1;
-+CREATE TABLE t1 (
-+t1_id bigint(21) NOT NULL auto_increment,
-+_field_72 varchar(128) DEFAULT '' NOT NULL,
-+_field_95 varchar(32),
-+_field_115 tinyint(4) DEFAULT '0' NOT NULL,
-+_field_122 tinyint(4) DEFAULT '0' NOT NULL,
-+_field_126 tinyint(4),
-+_field_134 tinyint(4),
-+PRIMARY KEY (t1_id),
-+UNIQUE _field_72 (_field_72),
-+KEY _field_115 (_field_115),
-+KEY _field_122 (_field_122)
-+);
-+INSERT INTO t1 VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',0,1,NULL,NULL);
-+INSERT INTO t1 VALUES (2,'hroberts','7415275a8c95952901e42b13a6b78566',0,1,NULL,NULL);
-+INSERT INTO t1 VALUES (3,'guest','d41d8cd98f00b204e9800998ecf8427e',1,0,NULL,NULL);
-+CREATE TABLE t2 (
-+seq_0_id bigint(21) DEFAULT '0' NOT NULL,
-+seq_1_id bigint(21) DEFAULT '0' NOT NULL,
-+PRIMARY KEY (seq_0_id,seq_1_id)
-+);
-+INSERT INTO t2 VALUES (1,1);
-+INSERT INTO t2 VALUES (2,1);
-+INSERT INTO t2 VALUES (2,2);
-+CREATE TABLE t3 (
-+t3_id bigint(21) NOT NULL auto_increment,
-+_field_131 varchar(128),
-+_field_133 tinyint(4) DEFAULT '0' NOT NULL,
-+_field_135 datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
-+_field_137 tinyint(4),
-+_field_139 datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
-+_field_140 blob,
-+_field_142 tinyint(4) DEFAULT '0' NOT NULL,
-+_field_145 tinyint(4) DEFAULT '0' NOT NULL,
-+_field_148 tinyint(4) DEFAULT '0' NOT NULL,
-+PRIMARY KEY (t3_id),
-+KEY _field_133 (_field_133),
-+KEY _field_135 (_field_135),
-+KEY _field_139 (_field_139),
-+KEY _field_142 (_field_142),
-+KEY _field_145 (_field_145),
-+KEY _field_148 (_field_148)
-+);
-+INSERT INTO t3 VALUES (1,'test job 1',0,'0000-00-00 00:00:00',0,'1999-02-25 22:43:32','test\r\njob\r\n1',0,0,0);
-+INSERT INTO t3 VALUES (2,'test job 2',0,'0000-00-00 00:00:00',0,'1999-02-26 21:08:04','',0,0,0);
-+CREATE TABLE t4 (
-+seq_0_id bigint(21) DEFAULT '0' NOT NULL,
-+seq_1_id bigint(21) DEFAULT '0' NOT NULL,
-+PRIMARY KEY (seq_0_id,seq_1_id)
-+);
-+INSERT INTO t4 VALUES (1,1);
-+INSERT INTO t4 VALUES (2,1);
-+CREATE TABLE t5 (
-+t5_id bigint(21) NOT NULL auto_increment,
-+_field_149 tinyint(4),
-+_field_156 varchar(128) DEFAULT '' NOT NULL,
-+_field_157 varchar(128) DEFAULT '' NOT NULL,
-+_field_158 varchar(128) DEFAULT '' NOT NULL,
-+_field_159 varchar(128) DEFAULT '' NOT NULL,
-+_field_160 varchar(128) DEFAULT '' NOT NULL,
-+_field_161 varchar(128) DEFAULT '' NOT NULL,
-+PRIMARY KEY (t5_id),
-+KEY _field_156 (_field_156),
-+KEY _field_157 (_field_157),
-+KEY _field_158 (_field_158),
-+KEY _field_159 (_field_159),
-+KEY _field_160 (_field_160),
-+KEY _field_161 (_field_161)
-+);
-+INSERT INTO t5 VALUES (1,0,'tomato','','','','','');
-+INSERT INTO t5 VALUES (2,0,'cilantro','','','','','');
-+CREATE TABLE t6 (
-+seq_0_id bigint(21) DEFAULT '0' NOT NULL,
-+seq_1_id bigint(21) DEFAULT '0' NOT NULL,
-+PRIMARY KEY (seq_0_id,seq_1_id)
-+);
-+INSERT INTO t6 VALUES (1,1);
-+INSERT INTO t6 VALUES (1,2);
-+INSERT INTO t6 VALUES (2,2);
-+CREATE TABLE t7 (
-+t7_id bigint(21) NOT NULL auto_increment,
-+_field_143 tinyint(4),
-+_field_165 varchar(32),
-+_field_166 smallint(6) DEFAULT '0' NOT NULL,
-+PRIMARY KEY (t7_id),
-+KEY _field_166 (_field_166)
-+);
-+INSERT INTO t7 VALUES (1,0,'High',1);
-+INSERT INTO t7 VALUES (2,0,'Medium',2);
-+INSERT INTO t7 VALUES (3,0,'Low',3);
-+select replace(t3._field_140, "\r","^M"),t3_id,min(t3._field_131), min(t3._field_135), min(t3._field_139), min(t3._field_137), min(link_alias_142._field_165), min(link_alias_133._field_72), min(t3._field_145), min(link_alias_148._field_156), replace(min(t3._field_140), "\r","^M"),t3.t3_id from t3 left join t4 on t4.seq_0_id = t3.t3_id left join t7 link_alias_142 on t4.seq_1_id = link_alias_142.t7_id left join t6 on t6.seq_0_id = t3.t3_id left join t1 link_alias_133 on t6.seq_1_id = link_alias_133.t1_id left join t2 on t2.seq_0_id = t3.t3_id left join t5 link_alias_148 on t2.seq_1_id = link_alias_148.t5_id where t3.t3_id in (1) group by t3.t3_id order by link_alias_142._field_166, _field_139, link_alias_133._field_72, _field_135, link_alias_148._field_156;
-+replace(t3._field_140, "\r","^M") t3_id min(t3._field_131) min(t3._field_135) min(t3._field_139) min(t3._field_137) min(link_alias_142._field_165) min(link_alias_133._field_72) min(t3._field_145) min(link_alias_148._field_156) replace(min(t3._field_140), "\r","^M") t3_id
-+test^M
-+job^M
-+1 1 test job 1 0000-00-00 00:00:00 1999-02-25 22:43:32 0 High admin 0 tomato test^M
-+job^M
-+1 1
-+drop table t1,t2,t3,t4,t5,t6,t7;
-+create table t1 (a blob);
-+insert into t1 values ("empty"),("");
-+select a,reverse(a) from t1;
-+a reverse(a)
-+empty ytpme
-+
-+drop table t1;
-+create table t1 (id integer auto_increment unique,imagem LONGBLOB not null default '');
-+Warnings:
-+Warning 1101 BLOB/TEXT column 'imagem' can't have a default value
-+insert into t1 (id) values (1);
-+select
-+charset(load_file('../../std_data/words.dat')),
-+collation(load_file('../../std_data/words.dat')),
-+coercibility(load_file('../../std_data/words.dat'));
-+charset(load_file('../../std_data/words.dat')) collation(load_file('../../std_data/words.dat')) coercibility(load_file('../../std_data/words.dat'))
-+binary binary 4
-+explain extended select
-+charset(load_file('MYSQLTEST_VARDIR/std_data/words.dat')),
-+collation(load_file('MYSQLTEST_VARDIR/std_data/words.dat')),
-+coercibility(load_file('MYSQLTEST_VARDIR/std_data/words.dat'));
-+id select_type table type possible_keys key key_len ref rows filtered Extra
-+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
-+Warnings:
-+Note 1003 select charset(load_file('MYSQLTEST_VARDIR/std_data/words.dat')) AS `charset(load_file('MYSQLTEST_VARDIR/std_data/words.dat'))`,collation(load_file('MYSQLTEST_VARDIR/std_data/words.dat')) AS `collation(load_file('MYSQLTEST_VARDIR/std_data/words.dat'))`,coercibility(load_file('MYSQLTEST_VARDIR/std_data/words.dat')) AS `coercibility(load_file('MYSQLTEST_VARDIR/std_data/words.dat'))`
-+update t1 set imagem=load_file('MYSQLTEST_VARDIR/std_data/words.dat') where id=1;
-+select if(imagem is null, "ERROR", "OK"),length(imagem) from t1 where id = 1;
-+if(imagem is null, "ERROR", "OK") length(imagem)
-+OK 581
-+drop table t1;
-+create table t1 select load_file('MYSQLTEST_VARDIR/std_data/words.dat') l;
-+show full fields from t1;
-+Field Type Collation Null Key Default Extra Privileges Comment
-+l longblob NULL YES NULL #
-+drop table t1;
-+create table t1 (id integer primary key auto_increment, txt text not null);
-+insert into t1 (txt) values ('Chevy ');
-+select * from t1 where txt='Chevy';
-+id txt
-+1 Chevy
-+select * from t1 where txt='Chevy ';
-+id txt
-+1 Chevy
-+select * from t1 where txt='Chevy ' or txt='Chevy';
-+id txt
-+1 Chevy
-+select * from t1 where txt='Chevy' or txt='Chevy ';
-+id txt
-+1 Chevy
-+select * from t1 where id='1' or id='2';
-+id txt
-+1 Chevy
-+insert into t1 (txt) values('Ford');
-+select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford';
-+id txt
-+1 Chevy
-+2 Ford
-+select * from t1 where txt='Chevy' or txt='Chevy ';
-+id txt
-+1 Chevy
-+select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy';
-+id txt
-+1 Chevy
-+select * from t1 where txt in ('Chevy ','Chevy');
-+id txt
-+1 Chevy
-+select * from t1 where txt in ('Chevy');
-+id txt
-+1 Chevy
-+select * from t1 where txt between 'Chevy' and 'Chevy';
-+id txt
-+1 Chevy
-+select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy ';
-+id txt
-+1 Chevy
-+select * from t1 where txt between 'Chevy' and 'Chevy ';
-+id txt
-+1 Chevy
-+select * from t1 where txt < 'Chevy ';
-+id txt
-+select * from t1 where txt <= 'Chevy';
-+id txt
-+1 Chevy
-+select * from t1 where txt > 'Chevy';
-+id txt
-+2 Ford
-+select * from t1 where txt >= 'Chevy';
-+id txt
-+1 Chevy
-+2 Ford
-+drop table t1;
-+create table t1 (id integer primary key auto_increment, txt text);
-+insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
-+select * from t1 where txt='Chevy' or txt is NULL;
-+id txt
-+1 Chevy
-+2 Chevy
-+3 NULL
-+explain select * from t1 where txt='Chevy' or txt is NULL;
-+id select_type table type possible_keys key key_len ref rows Extra
-+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where
-+select * from t1 where txt='Chevy ';
-+id txt
-+1 Chevy
-+2 Chevy
-+select * from t1 where txt='Chevy ' or txt='Chevy';
-+id txt
-+1 Chevy
-+2 Chevy
-+select * from t1 where txt='Chevy' or txt='Chevy ';
-+id txt
-+1 Chevy
-+2 Chevy
-+select * from t1 where id='1' or id='2';
-+id txt
-+1 Chevy
-+2 Chevy
-+insert into t1 (txt) values('Ford');
-+select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford';
-+id txt
-+1 Chevy
-+2 Chevy
-+4 Ford
-+select * from t1 where txt='Chevy' or txt='Chevy ';
-+id txt
-+1 Chevy
-+2 Chevy
-+select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy';
-+id txt
-+1 Chevy
-+2 Chevy
-+select * from t1 where txt in ('Chevy ','Chevy');
-+id txt
-+1 Chevy
-+2 Chevy
-+select * from t1 where txt in ('Chevy');
-+id txt
-+1 Chevy
-+2 Chevy
-+select * from t1 where txt between 'Chevy' and 'Chevy';
-+id txt
-+1 Chevy
-+2 Chevy
-+select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy ';
-+id txt
-+1 Chevy
-+2 Chevy
-+select * from t1 where txt between 'Chevy' and 'Chevy ';
-+id txt
-+1 Chevy
-+2 Chevy
-+select * from t1 where txt < 'Chevy ';
-+id txt
-+select * from t1 where txt < 'Chevy ' or txt is NULL;
-+id txt
-+3 NULL
-+select * from t1 where txt <= 'Chevy';
-+id txt
-+1 Chevy
-+2 Chevy
-+select * from t1 where txt > 'Chevy';
-+id txt
-+4 Ford
-+select * from t1 where txt >= 'Chevy';
-+id txt
-+1 Chevy
-+2 Chevy
-+4 Ford
-+alter table t1 modify column txt blob;
-+explain select * from t1 where txt='Chevy' or txt is NULL;
-+id select_type table type possible_keys key key_len ref rows Extra
-+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where
-+select * from t1 where txt='Chevy' or txt is NULL;
-+id txt
-+1 Chevy
-+3 NULL
-+explain select * from t1 where txt='Chevy' or txt is NULL order by txt;
-+id select_type table type possible_keys key key_len ref rows Extra
-+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where; Using filesort
-+select * from t1 where txt='Chevy' or txt is NULL order by txt;
-+id txt
-+3 NULL
-+1 Chevy
-+drop table t1;
-+CREATE TABLE t1 ( i int(11) NOT NULL default '0', c text NOT NULL, d varchar(1) NOT NULL DEFAULT ' ', PRIMARY KEY (i));
-+INSERT t1 (i, c) VALUES (1,''),(2,''),(3,'asdfh'),(4,'');
-+select max(i) from t1 where c = '';
-+max(i)
-+4
-+drop table t1;
-+CREATE table t1 (a blob);
-+insert into t1 values ('b'),('a\0'),('a'),('a '),('aa'),(NULL);
-+select hex(a) from t1 order by a;
-+hex(a)
-+NULL
-+61
-+6100
-+6120
-+6161
-+62
-+select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0');
-+b
-+NULL
-+6100
-+610000
-+612000
-+616100
-+6200
-+alter table t1 modify a varbinary(5);
-+select hex(a) from t1 order by a;
-+hex(a)
-+NULL
-+61
-+6100
-+6120
-+6161
-+62
-+select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0');
-+b
-+NULL
-+6100
-+610000
-+612000
-+616100
-+6200
-+alter table t1 modify a char(5);
-+select hex(a) from t1 order by a;
-+hex(a)
-+NULL
-+6100
-+61
-+61
-+6161
-+62
-+select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0');
-+b
-+NULL
-+610000
-+6100
-+6100
-+616100
-+6200
-+alter table t1 modify a binary(5);
-+select hex(a) from t1 order by a;
-+hex(a)
-+NULL
-+6100000000
-+6100000000
-+6100000000
-+6161000000
-+6200000000
-+select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0');
-+b
-+NULL
-+610000000000
-+610000000000
-+610000000000
-+616100000000
-+620000000000
-+drop table t1;
-+create table t1 (a text default '');
-+Warnings:
-+Warning 1101 BLOB/TEXT column 'a' can't have a default value
-+show create table t1;
-+Table Create Table
-+t1 CREATE TABLE `t1` (
-+ `a` text
-+) ENGINE=MEMORY DEFAULT CHARSET=latin1
-+insert into t1 values (default);
-+select * from t1;
-+a
-+NULL
-+drop table t1;
-+set @@sql_mode='TRADITIONAL';
-+create table t1 (a text default '');
-+ERROR 42000: BLOB/TEXT column 'a' can't have a default value
-+set @@sql_mode='';
-+CREATE TABLE t (c TEXT CHARSET ASCII);
-+INSERT INTO t (c) VALUES (REPEAT('1',65537));
-+Warnings:
-+Warning 1265 Data truncated for column 'c' at row 1
-+INSERT INTO t (c) VALUES (REPEAT('2',65536));
-+Warnings:
-+Warning 1265 Data truncated for column 'c' at row 1
-+INSERT INTO t (c) VALUES (REPEAT('3',65535));
-+SELECT LENGTH(c), CHAR_LENGTH(c) FROM t;
-+LENGTH(c) CHAR_LENGTH(c)
-+65535 65535
-+65535 65535
-+65535 65535
-+DROP TABLE t;
-+drop table if exists b15776;
-+create table b15776 (data blob(2147483647));
-+drop table b15776;
-+create table b15776 (data blob(-1));
-+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1))' at line 1
-+create table b15776 (data blob(2147483648));
-+drop table b15776;
-+create table b15776 (data blob(4294967294));
-+drop table b15776;
-+create table b15776 (data blob(4294967295));
-+drop table b15776;
-+create table b15776 (data blob(4294967296));
-+ERROR 42000: Display width out of range for column 'data' (max = 4294967295)
-+CREATE TABLE b15776 (a blob(2147483647), b blob(2147483648), c blob(4294967295), a1 text(2147483647), b1 text(2147483648), c1 text(4294967295) );
-+show columns from b15776;
-+Field Type Null Key Default Extra
-+a longblob YES NULL
-+b longblob YES NULL
-+c longblob YES NULL
-+a1 longtext YES NULL
-+b1 longtext YES NULL
-+c1 longtext YES NULL
-+drop table b15776;
-+CREATE TABLE b15776 (a blob(4294967296));
-+ERROR 42000: Display width out of range for column 'a' (max = 4294967295)
-+CREATE TABLE b15776 (a text(4294967296));
-+ERROR 42000: Display width out of range for column 'a' (max = 4294967295)
-+CREATE TABLE b15776 (a blob(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+ERROR 42000: Display width out of range for column 'a' (max = 4294967295)
-+CREATE TABLE b15776 (a text(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+ERROR 42000: Display width out of range for column 'a' (max = 4294967295)
-+CREATE TABLE b15776 (a int(0));
-+INSERT INTO b15776 values (NULL), (1), (42), (654);
-+SELECT * from b15776 ORDER BY a;
-+a
-+NULL
-+1
-+42
-+654
-+DROP TABLE b15776;
-+CREATE TABLE b15776 (a int(-1));
-+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1))' at line 1
-+CREATE TABLE b15776 (a int(255));
-+DROP TABLE b15776;
-+CREATE TABLE b15776 (a int(256));
-+ERROR 42000: Display width out of range for column 'a' (max = 255)
-+CREATE TABLE b15776 (data blob(-1));
-+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1))' at line 1
-+CREATE TABLE b15776 (a char(2147483647));
-+ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB or TEXT instead
-+CREATE TABLE b15776 (a char(2147483648));
-+ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB or TEXT instead
-+CREATE TABLE b15776 (a char(4294967295));
-+ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB or TEXT instead
-+CREATE TABLE b15776 (a char(4294967296));
-+ERROR 42000: Display width out of range for column 'a' (max = 4294967295)
-+CREATE TABLE b15776 (a year(4294967295));
-+INSERT INTO b15776 VALUES (42);
-+SELECT * FROM b15776;
-+a
-+2042
-+DROP TABLE b15776;
-+CREATE TABLE b15776 (a year(4294967296));
-+ERROR 42000: Display width out of range for column 'a' (max = 4294967295)
-+CREATE TABLE b15776 (a year(0));
-+DROP TABLE b15776;
-+CREATE TABLE b15776 (a year(-2));
-+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-2))' at line 1
-+CREATE TABLE b15776 (a int(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+ERROR 42000: Display width out of range for column 'a' (max = 4294967295)
-+CREATE TABLE b15776 (a char(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+ERROR 42000: Display width out of range for column 'a' (max = 4294967295)
-+CREATE TABLE b15776 (a year(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+ERROR 42000: Display width out of range for column 'a' (max = 4294967295)
-+CREATE TABLE b15776 select cast(null as char(4294967295));
-+show columns from b15776;
-+Field Type Null Key Default Extra
-+cast(null as char(4294967295)) char(0) YES NULL
-+drop table b15776;
-+CREATE TABLE b15776 select cast(null as nchar(4294967295));
-+show columns from b15776;
-+Field Type Null Key Default Extra
-+cast(null as nchar(4294967295)) char(0) YES NULL
-+drop table b15776;
-+CREATE TABLE b15776 select cast(null as binary(4294967295));
-+show columns from b15776;
-+Field Type Null Key Default Extra
-+cast(null as binary(4294967295)) binary(0) YES NULL
-+drop table b15776;
-+explain select cast(1 as char(4294967295));
-+id select_type table type possible_keys key key_len ref rows Extra
-+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
-+explain select cast(1 as nchar(4294967295));
-+id select_type table type possible_keys key key_len ref rows Extra
-+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
-+explain select cast(1 as binary(4294967295));
-+id select_type table type possible_keys key key_len ref rows Extra
-+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
-+explain select cast(1 as char(4294967296));
-+ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295)
-+explain select cast(1 as nchar(4294967296));
-+ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295)
-+explain select cast(1 as binary(4294967296));
-+ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295)
-+explain select cast(1 as decimal(-1));
-+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1))' at line 1
-+explain select cast(1 as decimal(64, 30));
-+id select_type table type possible_keys key key_len ref rows Extra
-+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
-+explain select cast(1 as decimal(64, 999999999999999999999999999999));
-+Got one of the listed errors
-+explain select cast(1 as decimal(4294967296));
-+Got one of the listed errors
-+explain select cast(1 as decimal(999999999999999999999999999999999999));
-+Got one of the listed errors
-+explain select convert(1, char(4294967295));
-+id select_type table type possible_keys key key_len ref rows Extra
-+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
-+explain select convert(1, char(4294967296));
-+ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295)
-+explain select convert(1, char(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295)
-+explain select convert(1, nchar(4294967295));
-+id select_type table type possible_keys key key_len ref rows Extra
-+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
-+explain select convert(1, nchar(4294967296));
-+ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295)
-+explain select convert(1, nchar(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295)
-+explain select convert(1, binary(4294967295));
-+id select_type table type possible_keys key key_len ref rows Extra
-+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
-+explain select convert(1, binary(4294967296));
-+ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295)
-+explain select convert(1, binary(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+ERROR 42000: Display width out of range for column 'cast as char' (max = 4294967295)
-+End of 5.0 tests
-+CREATE TABLE t1(id INT NOT NULL);
-+CREATE TABLE t2(id INT NOT NULL, c TEXT NOT NULL);
-+INSERT INTO t1 VALUES (1);
-+INSERT INTO t2 VALUES (1, '');
-+UPDATE t2 SET c = REPEAT('1', 70000);
-+Warnings:
-+Warning 1265 Data truncated for column 'c' at row 1
-+SELECT LENGTH(c) FROM t2;
-+LENGTH(c)
-+65535
-+UPDATE t1 LEFT JOIN t2 USING(id) SET t2.c = REPEAT('1', 70000) WHERE t1.id = 1;
-+Warnings:
-+Warning 1265 Data truncated for column 'c' at row 1
-+SELECT LENGTH(c) FROM t2;
-+LENGTH(c)
-+65535
-+DROP TABLE t1, t2;
-+# Bug #52160: crash and inconsistent results when grouping
-+# by a function and column
-+CREATE FUNCTION f1() RETURNS TINYBLOB RETURN 1;
-+CREATE TABLE t1(a CHAR(1));
-+INSERT INTO t1 VALUES ('0'), ('0');
-+SELECT COUNT(*) FROM t1 GROUP BY f1(), a;
-+COUNT(*)
-+2
-+DROP FUNCTION f1;
-+DROP TABLE t1;
-+SET @old_max_heap_table_size = @@global.max_heap_table_size;
-+SET @old_max_allowed_packet = @@global.max_allowed_packet;
-+SET GLOBAL max_heap_table_size = 18 * 1024 * 1024;
-+SET GLOBAL max_allowed_packet = 24 * 1024 * 1024;
-+drop table if exists t1;
-+CREATE TABLE t1 (data LONGBLOB);
-+INSERT INTO t1 (data) VALUES (NULL);
-+UPDATE t1 set data=repeat('a',18*1024*1024);
-+select length(data) from t1;
-+length(data)
-+18874368
-+delete from t1 where left(data,1)='a';
-+truncate table t1;
-+INSERT INTO t1 (data) VALUES (repeat('a',1*1024*1024));
-+INSERT INTO t1 (data) VALUES (repeat('b',16*1024*1024-1024));
-+delete from t1 where left(data,1)='b';
-+UPDATE t1 set data=repeat('c',17*1024*1024);
-+delete from t1 where left(data,1)='c';
-+INSERT INTO t1 set data=repeat('a',18*1024*1024);
-+select length(data) from t1;
-+length(data)
-+18874368
-+alter table t1 modify data blob;
-+select length(data) from t1;
-+length(data)
-+0
-+drop table t1;
-+CREATE TABLE t1 (data BLOB);
-+INSERT INTO t1 (data) VALUES (NULL);
-+UPDATE t1 set data=repeat('a',18*1024*1024);
-+Warnings:
-+Warning 1265 Data truncated for column 'data' at row 1
-+select length(data) from t1;
-+length(data)
-+65535
-+drop table t1;
-+SET GLOBAL max_allowed_packet = @old_max_allowed_packet;
-+SET GLOBAL max_heap_table_size = @old_max_heap_table_size;
-+SET default_storage_engine=@old_default_storage_engine;
---- /dev/null
-+++ b/mysql-test/r/percona_heap_bug783366.result
-@@ -0,0 +1,14 @@
-+drop table if exists t1;
-+CREATE TABLE t1 (
-+f1 VARCHAR ( 128 ) ,
-+f2 VARCHAR ( 32 ),
-+PRIMARY KEY ( f2 ( 2 ) , f1 )
-+)
-+ENGINE=HEAP KEY_BLOCK_SIZE = 512;
-+INSERT IGNORE INTO t1 VALUES ( 'te' , 'm') , ( NULL , 'think' );
-+Warnings:
-+Warning 1048 Column 'f1' cannot be null
-+INSERT IGNORE INTO t1 VALUES ( 'te' , 'm') , ( NULL , 'think' );
-+Warnings:
-+Warning 1048 Column 'f1' cannot be null
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/r/percona_heap_bug783451.result
-@@ -0,0 +1,132 @@
-+DROP TABLE IF EXISTS local_1_1;
-+CREATE TABLE IF NOT EXISTS local_1_1 ( f1 VARCHAR ( 32 ) NOT NULL , f2 VARCHAR ( 128 ) NOT NULL DEFAULT 'cboepfaobilcchabvglgjdbynog' , f3 VARCHAR ( 32 ) NOT NULL , f4 VARBINARY ( 32 ) NOT NULL , f5 VARBINARY ( 1024 ) DEFAULT 'ycboepfao' , KEY ( f1 /* ( 2 ) */ , f2 /* ( 2 ) */ ) ) ENGINE=HEAP KEY_BLOCK_SIZE = 512;
-+INSERT IGNORE INTO local_1_1 VALUES ( REPEAT( 'ervydbimvmbqmsowdbsa' , 1 ) , 'v' , NULL , NULL , REPEAT( 'mervydbimvmbqms' , 5 ) ) , ( 'p' , 6 , 'n' , REPEAT( 'imervydbimvmbqmsowdbs' , 4 ) , 'do' ) , ( NULL , NULL , REPEAT( 'himervydbimvmbqmsowdbsaybudvwaamvhempuublmia' , 6 ) , REPEAT('X', POW(2, 20) * 2) , REPEAT('X', POW(2, 20) * 2) ) , ( REPEAT('X', POW(2, 20) * 2) , REPEAT( 'Y' , 763 ) , NULL , REPEAT('X', POW(2, 20) * 2) , NULL ) , ( REPEAT('X', POW(2, 20) * 2) , 'time' , 'how' , 2 , REPEAT( 'Y' , 107 ) ) , ( REPEAT( 'hyshimervydbimvmbqmsowdbsaybud' , 5 ) , 2 , 8 , NULL , REPEAT('X', POW(2, 20) * 2) ) , ( 'come' , NULL , 'i' , NULL , REPEAT('X', POW(2, 20) * 2) );
-+Warnings:
-+Warning 1048 Column 'f3' cannot be null
-+Warning 1048 Column 'f4' cannot be null
-+Warning 1265 Data truncated for column 'f4' at row 2
-+Warning 1048 Column 'f1' cannot be null
-+Warning 1048 Column 'f2' cannot be null
-+Warning 1265 Data truncated for column 'f3' at row 3
-+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
-+Warning 1048 Column 'f4' cannot be null
-+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
-+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
-+Warning 1048 Column 'f1' cannot be null
-+Warning 1265 Data truncated for column 'f2' at row 4
-+Warning 1048 Column 'f3' cannot be null
-+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
-+Warning 1048 Column 'f4' cannot be null
-+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
-+Warning 1048 Column 'f1' cannot be null
-+Warning 1265 Data truncated for column 'f1' at row 6
-+Warning 1048 Column 'f4' cannot be null
-+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
-+Warning 1048 Column 'f2' cannot be null
-+Warning 1048 Column 'f4' cannot be null
-+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
-+INSERT IGNORE INTO local_1_1 VALUES ( 'ok' , NULL , REPEAT( 'Y' , 651 ) , 2 , 5 ) , ( REPEAT( 'zylcdzkfrqpihyshimervydbimvmbqmsowdbsaybu' , 3 ) , REPEAT( 'Y' , 282 ) , REPEAT( 'X' , 0 ) , REPEAT( 'Y' , 369 ) , 'g' ) , ( 'think' , REPEAT('X', POW(2, 20) * 2), NULL , NULL , REPEAT('X', POW(2, 20) * 2) ) , ( REPEAT( 'Y' , 468 ) , REPEAT( 'dfvbrzylcd' , 6 ) , REPEAT( 'Y' , 264 ) , NULL , 'c' ) , ( NULL , NULL , REPEAT( 'srdfvbrzylcdzkfrqpihyshimervydbimvmbqms' , 0 ) , REPEAT( 'Y' , 244 ) , 7 ) , ( REPEAT( 'Y' , 0 ) , 'how' , 'going' , 'q' , NULL );
-+Warnings:
-+Warning 1048 Column 'f2' cannot be null
-+Warning 1265 Data truncated for column 'f3' at row 1
-+Warning 1265 Data truncated for column 'f1' at row 2
-+Warning 1265 Data truncated for column 'f2' at row 2
-+Warning 1265 Data truncated for column 'f4' at row 2
-+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
-+Warning 1048 Column 'f2' cannot be null
-+Warning 1048 Column 'f3' cannot be null
-+Warning 1048 Column 'f4' cannot be null
-+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
-+Warning 1265 Data truncated for column 'f1' at row 4
-+Warning 1265 Data truncated for column 'f3' at row 4
-+Warning 1048 Column 'f4' cannot be null
-+Warning 1048 Column 'f1' cannot be null
-+Warning 1048 Column 'f2' cannot be null
-+Warning 1265 Data truncated for column 'f4' at row 5
-+INSERT IGNORE INTO local_1_1 VALUES ( REPEAT('X', POW(2, 20) * 2) , NULL , NULL , NULL , REPEAT('X', POW(2, 20) * 2) ) , ( REPEAT('X', POW(2, 20) * 2) , NULL , REPEAT('X', POW(2, 20) * 2) , 'this' , 'e' ) , ( NULL , 'think' , NULL , 'were' , NULL ) , ( 9 , 'l' , 'c' , 3 , REPEAT( 'geysrdfvbrzylcdzkfrqpihyshimervydbi' , 5 ) ) , ( NULL , NULL , NULL , 'h' , 'w' );
-+Warnings:
-+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
-+Warning 1048 Column 'f1' cannot be null
-+Warning 1048 Column 'f2' cannot be null
-+Warning 1048 Column 'f3' cannot be null
-+Warning 1048 Column 'f4' cannot be null
-+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
-+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
-+Warning 1048 Column 'f1' cannot be null
-+Warning 1048 Column 'f2' cannot be null
-+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
-+Warning 1048 Column 'f3' cannot be null
-+Warning 1048 Column 'f1' cannot be null
-+Warning 1048 Column 'f3' cannot be null
-+Warning 1048 Column 'f1' cannot be null
-+Warning 1048 Column 'f2' cannot be null
-+Warning 1048 Column 'f3' cannot be null
-+INSERT IGNORE INTO local_1_1 SELECT * FROM local_1_1;
-+INSERT IGNORE INTO local_1_1 SELECT * FROM local_1_1;
-+UPDATE local_1_1 SET f5 = REPEAT ('X', 215566);
-+Warnings:
-+Warning 1265 Data truncated for column 'f5' at row 1
-+Warning 1265 Data truncated for column 'f5' at row 2
-+Warning 1265 Data truncated for column 'f5' at row 3
-+Warning 1265 Data truncated for column 'f5' at row 4
-+Warning 1265 Data truncated for column 'f5' at row 5
-+Warning 1265 Data truncated for column 'f5' at row 6
-+Warning 1265 Data truncated for column 'f5' at row 7
-+Warning 1265 Data truncated for column 'f5' at row 8
-+Warning 1265 Data truncated for column 'f5' at row 9
-+Warning 1265 Data truncated for column 'f5' at row 10
-+Warning 1265 Data truncated for column 'f5' at row 11
-+Warning 1265 Data truncated for column 'f5' at row 12
-+Warning 1265 Data truncated for column 'f5' at row 13
-+Warning 1265 Data truncated for column 'f5' at row 14
-+Warning 1265 Data truncated for column 'f5' at row 15
-+Warning 1265 Data truncated for column 'f5' at row 16
-+Warning 1265 Data truncated for column 'f5' at row 17
-+Warning 1265 Data truncated for column 'f5' at row 18
-+Warning 1265 Data truncated for column 'f5' at row 19
-+Warning 1265 Data truncated for column 'f5' at row 20
-+Warning 1265 Data truncated for column 'f5' at row 21
-+Warning 1265 Data truncated for column 'f5' at row 22
-+Warning 1265 Data truncated for column 'f5' at row 23
-+Warning 1265 Data truncated for column 'f5' at row 24
-+Warning 1265 Data truncated for column 'f5' at row 25
-+Warning 1265 Data truncated for column 'f5' at row 26
-+Warning 1265 Data truncated for column 'f5' at row 27
-+Warning 1265 Data truncated for column 'f5' at row 28
-+Warning 1265 Data truncated for column 'f5' at row 29
-+Warning 1265 Data truncated for column 'f5' at row 30
-+Warning 1265 Data truncated for column 'f5' at row 31
-+Warning 1265 Data truncated for column 'f5' at row 32
-+Warning 1265 Data truncated for column 'f5' at row 33
-+Warning 1265 Data truncated for column 'f5' at row 34
-+Warning 1265 Data truncated for column 'f5' at row 35
-+Warning 1265 Data truncated for column 'f5' at row 36
-+Warning 1265 Data truncated for column 'f5' at row 37
-+Warning 1265 Data truncated for column 'f5' at row 38
-+Warning 1265 Data truncated for column 'f5' at row 39
-+Warning 1265 Data truncated for column 'f5' at row 40
-+Warning 1265 Data truncated for column 'f5' at row 41
-+Warning 1265 Data truncated for column 'f5' at row 42
-+Warning 1265 Data truncated for column 'f5' at row 43
-+Warning 1265 Data truncated for column 'f5' at row 44
-+Warning 1265 Data truncated for column 'f5' at row 45
-+Warning 1265 Data truncated for column 'f5' at row 46
-+Warning 1265 Data truncated for column 'f5' at row 47
-+Warning 1265 Data truncated for column 'f5' at row 48
-+Warning 1265 Data truncated for column 'f5' at row 49
-+Warning 1265 Data truncated for column 'f5' at row 50
-+Warning 1265 Data truncated for column 'f5' at row 51
-+Warning 1265 Data truncated for column 'f5' at row 52
-+Warning 1265 Data truncated for column 'f5' at row 53
-+Warning 1265 Data truncated for column 'f5' at row 54
-+Warning 1265 Data truncated for column 'f5' at row 55
-+Warning 1265 Data truncated for column 'f5' at row 56
-+Warning 1265 Data truncated for column 'f5' at row 57
-+Warning 1265 Data truncated for column 'f5' at row 58
-+Warning 1265 Data truncated for column 'f5' at row 59
-+Warning 1265 Data truncated for column 'f5' at row 60
-+Warning 1265 Data truncated for column 'f5' at row 61
-+Warning 1265 Data truncated for column 'f5' at row 62
-+Warning 1265 Data truncated for column 'f5' at row 63
-+Warning 1265 Data truncated for column 'f5' at row 64
-+DROP TABLE local_1_1;
---- /dev/null
-+++ b/mysql-test/r/percona_heap_bug784464.result
-@@ -0,0 +1,58 @@
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32),
-+PRIMARY KEY (f1)) ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+t1 MEMORY 10 Fixed 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC
-+DROP TABLE t1;
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32),
-+PRIMARY KEY (f1)) KEY_BLOCK_SIZE=33 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+ERROR 42000: Incorrect usage/placement of 'key_block_size'
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32),
-+PRIMARY KEY (f1)) KEY_BLOCK_SIZE=34 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+t1 MEMORY 10 Dynamic 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=34
-+DROP TABLE t1;
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32),
-+PRIMARY KEY (f1)) KEY_BLOCK_SIZE=123 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+t1 MEMORY 10 Dynamic 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=123
-+DROP TABLE t1;
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32),
-+PRIMARY KEY (f1)) KEY_BLOCK_SIZE=1000 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+t1 MEMORY 10 Fixed 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=1000
-+DROP TABLE t1;
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96),
-+PRIMARY KEY (f1)) ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+t1 MEMORY 10 Fixed 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC
-+DROP TABLE t1;
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96),
-+PRIMARY KEY (f1)) KEY_BLOCK_SIZE=33 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+ERROR 42000: Incorrect usage/placement of 'key_block_size'
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96),
-+PRIMARY KEY (f1)) KEY_BLOCK_SIZE=34 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+t1 MEMORY 10 Dynamic 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=34
-+DROP TABLE t1;
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96),
-+PRIMARY KEY (f1)) KEY_BLOCK_SIZE=121 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+t1 MEMORY 10 Dynamic 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=121
-+DROP TABLE t1;
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96),
-+PRIMARY KEY (f1)) KEY_BLOCK_SIZE=1000 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+t1 MEMORY 10 Fixed 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=1000
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/r/percona_heap_bug784464_32bit.result
-@@ -0,0 +1,12 @@
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32),
-+PRIMARY KEY (f1)) KEY_BLOCK_SIZE=124 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+t1 MEMORY 10 Dynamic 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=124
-+DROP TABLE t1;
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96),
-+PRIMARY KEY (f1)) KEY_BLOCK_SIZE=122 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+t1 MEMORY 10 Dynamic 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=122
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/r/percona_heap_bug784464_64bit.result
-@@ -0,0 +1,12 @@
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32),
-+PRIMARY KEY (f1)) KEY_BLOCK_SIZE=124 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+t1 MEMORY 10 Fixed 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=124
-+DROP TABLE t1;
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96),
-+PRIMARY KEY (f1)) KEY_BLOCK_SIZE=122 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+t1 MEMORY 10 Fixed 0 X 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC KEY_BLOCK_SIZE=122
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/r/percona_heap_bug784468.result
-@@ -0,0 +1,15 @@
-+CREATE TABLE t1 ( f1 VARCHAR(30)) ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+t1 MEMORY 10 Fixed 0 32 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC
-+DROP TABLE t1;
-+CREATE TABLE t1 ( f1 VARCHAR(31)) ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+t1 MEMORY 10 Fixed 0 33 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC
-+DROP TABLE t1;
-+CREATE TABLE t1 ( f1 VARCHAR(32)) ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+SHOW TABLE STATUS LIKE 't1';
-+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-+t1 MEMORY 10 Fixed 0 34 0 X 0 0 NULL X X NULL latin1_swedish_ci NULL row_format=DYNAMIC
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/r/percona_heap_bug788544.result
-@@ -0,0 +1,9 @@
-+CREATE TABLE t1 (f2 VARCHAR (32), f4 LONGBLOB, f5 TEXT) ENGINE=HEAP;
-+INSERT INTO t1 VALUES ('a', NULL, NULL),
-+('b' , REPEAT('a' , 593338), REPEAT('a', 800));
-+UPDATE t1 SET f2 = 'c' WHERE f4 = 'd';
-+SELECT LENGTH(f2), LENGTH(f4), LENGTH(f5) FROM t1;
-+LENGTH(f2) LENGTH(f4) LENGTH(f5)
-+1 NULL NULL
-+1 593338 800
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/r/percona_heap_bug788576.result
-@@ -0,0 +1,19 @@
-+CREATE TABLE t1 (f1 VARCHAR (32), f2 VARCHAR (128), f3 VARBINARY (128),
-+f4 VARBINARY (512), f5 VARBINARY (1024),
-+KEY (f2(1))) ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+INSERT IGNORE INTO t1 VALUES (2, NULL, 6, REPEAT('glugcgqk', 5), 'look'),
-+(REPEAT( 'kglugcgqkin', 6), 'if', 'was', NULL, NULL),
-+(NULL, NULL, NULL, NULL, 7);
-+Warnings:
-+Warning 1265 Data truncated for column 'f1' at row 2
-+SELECT * FROM t1;
-+f1 f2 f3 f4 f5
-+2 NULL 6 glugcgqkglugcgqkglugcgqkglugcgqkglugcgqk look
-+kglugcgqkinkglugcgqkinkglugcgqki if was NULL NULL
-+NULL NULL NULL NULL 7
-+DELETE FROM t1 WHERE f5 <=> NULL;
-+SELECT * FROM t1;
-+f1 f2 f3 f4 f5
-+2 NULL 6 glugcgqkglugcgqkglugcgqkglugcgqkglugcgqk look
-+NULL NULL NULL NULL 7
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/r/percona_heap_bug788722.result
-@@ -0,0 +1,18 @@
-+CREATE TABLE IF NOT EXISTS local_1_1 (f1 VARCHAR (32) NOT NULL,
-+f2 VARCHAR (128) NOT NULL,
-+f3 BLOB NOT NULL,
-+f4 TEXT,
-+f5 BLOB (1024),
-+PRIMARY KEY (f1),
-+KEY (f1 , f2)
-+) ENGINE=HEAP ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE = 2048;
-+INSERT IGNORE INTO local_1_1 VALUES
-+(REPEAT('egqeqfxwaejpqixuvvtentruyqadxiybjdfqjspfbyjdjczrrwjnagkzsoagatqookhsgtrvvbxacppljfzaseidqggxvuirm' , 5), NULL, NULL, NULL, REPEAT('hegqeqfxwaejpqixuvvtentruyqadxiy', 1)),
-+('you', NULL, 0, REPEAT("X", 2048) , 0);
-+Warnings:
-+Warning 1265 Data truncated for column 'f1' at row 1
-+Warning 1048 Column 'f2' cannot be null
-+Warning 1048 Column 'f3' cannot be null
-+Warning 1048 Column 'f2' cannot be null
-+INSERT IGNORE INTO local_1_1 SELECT * FROM local_1_1;
-+DROP TABLE local_1_1;
---- /dev/null
-+++ b/mysql-test/r/percona_heap_bug789131.result
-@@ -0,0 +1,7 @@
-+CREATE TABLE t1 (f1 VARCHAR (128), f2 VARCHAR (128), f3 VARBINARY (512),
-+f4 TEXT (65525), f5 VARCHAR (128), KEY (f1(1))) ENGINE=HEAP;
-+INSERT IGNORE INTO t1 VALUES
-+( 'o' , "" , NULL , "" , 0 ) ,
-+(NULL, "" , "" , "" , 'f' ) ;
-+INSERT IGNORE INTO t1 SELECT * FROM t1;
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/r/percona_heap_var.result
-@@ -0,0 +1,194 @@
-+drop table if exists t1;
-+set @@session.max_heap_table_size=16*1024*1024;
-+create table t1 (a int not null, b varchar(400), c int, primary key (a), key (c)) engine=heap comment="testing heaps" key_block_size=128;
-+ERROR 42000: Incorrect usage/placement of 'key_block_size'
-+create table t1 (a int not null, b int, c varchar(400), primary key (a), key (b)) engine=heap comment="testing heaps" key_block_size=4;
-+ERROR 42000: Incorrect usage/placement of 'key_block_size'
-+create table t1 (a int not null, b int, c varchar(400), d varchar(400), primary key (a), key (b)) engine=heap comment="testing heaps" key_block_size=24;
-+show table status like "t1";
-+Name t1
-+Engine MEMORY
-+Version 10
-+Row_format Dynamic
-+Rows 0
-+Avg_row_length X
-+Data_length X
-+Max_data_length X
-+Index_length X
-+Data_free X
-+Auto_increment X
-+Create_time X
-+Update_time X
-+Check_time X
-+Collation latin1_swedish_ci
-+Checksum NULL
-+Create_options KEY_BLOCK_SIZE=24
-+Comment testing heaps
-+insert into t1 values (1,1,'012',NULL), (2,2,'0123456789',NULL), (3,3,'012345678901234567890123456789',NULL), (4,4,NULL,'0123456789012345678901234567890123456789012345678901234567890123456789');
-+select * from t1;
-+a b c d
-+1 1 012 NULL
-+2 2 0123456789 NULL
-+3 3 012345678901234567890123456789 NULL
-+4 4 NULL 0123456789012345678901234567890123456789012345678901234567890123456789
-+delete from t1 where a = 3;
-+select * from t1;
-+a b c d
-+1 1 012 NULL
-+2 2 0123456789 NULL
-+4 4 NULL 0123456789012345678901234567890123456789012345678901234567890123456789
-+insert into t1 values (5,5,NULL,'0123'), (6,6,NULL,'0123');
-+select * from t1;
-+a b c d
-+1 1 012 NULL
-+2 2 0123456789 NULL
-+6 6 NULL 0123
-+5 5 NULL 0123
-+4 4 NULL 0123456789012345678901234567890123456789012345678901234567890123456789
-+update t1 set c = '012345678901234567890123456789' where a = 2;
-+select * from t1;
-+a b c d
-+1 1 012 NULL
-+2 2 012345678901234567890123456789 NULL
-+6 6 NULL 0123
-+5 5 NULL 0123
-+4 4 NULL 0123456789012345678901234567890123456789012345678901234567890123456789
-+update t1 set c = '0123456789' where a = 2;
-+select * from t1;
-+a b c d
-+1 1 012 NULL
-+2 2 0123456789 NULL
-+6 6 NULL 0123
-+5 5 NULL 0123
-+4 4 NULL 0123456789012345678901234567890123456789012345678901234567890123456789
-+insert into t1 values (7,7,'0123',NULL), (8,8,'0123',NULL);
-+select * from t1;
-+a b c d
-+1 1 012 NULL
-+2 2 0123456789 NULL
-+6 6 NULL 0123
-+5 5 NULL 0123
-+4 4 NULL 0123456789012345678901234567890123456789012345678901234567890123456789
-+7 7 0123 NULL
-+8 8 0123 NULL
-+show table status like "t1";
-+Name t1
-+Engine MEMORY
-+Version 10
-+Row_format Dynamic
-+Rows 7
-+Avg_row_length X
-+Data_length X
-+Max_data_length X
-+Index_length X
-+Data_free X
-+Auto_increment X
-+Create_time X
-+Update_time X
-+Check_time X
-+Collation latin1_swedish_ci
-+Checksum NULL
-+Create_options KEY_BLOCK_SIZE=24
-+Comment testing heaps
-+alter table t1 key_block_size = 0;
-+show table status like "t1";
-+Name t1
-+Engine MEMORY
-+Version 10
-+Row_format Dynamic
-+Rows 7
-+Avg_row_length X
-+Data_length X
-+Max_data_length X
-+Index_length X
-+Data_free X
-+Auto_increment X
-+Create_time X
-+Update_time X
-+Check_time X
-+Collation latin1_swedish_ci
-+Checksum NULL
-+Create_options
-+Comment testing heaps
-+alter table t1 row_format = dynamic;
-+show table status like "t1";
-+Name t1
-+Engine MEMORY
-+Version 10
-+Row_format Dynamic
-+Rows 7
-+Avg_row_length X
-+Data_length X
-+Max_data_length X
-+Index_length X
-+Data_free X
-+Auto_increment X
-+Create_time X
-+Update_time X
-+Check_time X
-+Collation latin1_swedish_ci
-+Checksum NULL
-+Create_options row_format=DYNAMIC KEY_BLOCK_SIZE=X
-+Comment testing heaps
-+alter table t1 key_block_size = 128, max_rows = 10001;
-+show table status like "t1";
-+Name t1
-+Engine MEMORY
-+Version 10
-+Row_format Dynamic
-+Rows 7
-+Avg_row_length X
-+Data_length X
-+Max_data_length X
-+Index_length X
-+Data_free X
-+Auto_increment X
-+Create_time X
-+Update_time X
-+Check_time X
-+Collation latin1_swedish_ci
-+Checksum NULL
-+Create_options max_rows=10001 row_format=DYNAMIC KEY_BLOCK_SIZE=128
-+Comment testing heaps
-+select * from t1;
-+a b c d
-+1 1 012 NULL
-+2 2 0123456789 NULL
-+6 6 NULL 0123
-+5 5 NULL 0123
-+4 4 NULL 0123456789012345678901234567890123456789012345678901234567890123456789
-+7 7 0123 NULL
-+8 8 0123 NULL
-+delete from t1;
-+select * from t1;
-+a b c d
-+call mtr.add_suppression("The table 't1' is full");
-+select count(*) from t1;
-+count(*)
-+10001
-+insert into t1 values (100000,100000,NULL,'0123'), (100000,100000,NULL,'0123');
-+ERROR HY000: The table 't1' is full
-+show table status like "t1";
-+Name t1
-+Engine MEMORY
-+Version 10
-+Row_format Dynamic
-+Rows 10001
-+Avg_row_length X
-+Data_length X
-+Max_data_length X
-+Index_length X
-+Data_free X
-+Auto_increment X
-+Create_time X
-+Update_time X
-+Check_time X
-+Collation latin1_swedish_ci
-+Checksum NULL
-+Create_options max_rows=10001 row_format=DYNAMIC KEY_BLOCK_SIZE=128
-+Comment testing heaps
-+select count(*) from t1;
-+count(*)
-+10001
-+set @@session.max_heap_table_size=default;
-+drop table t1;
---- /dev/null
-+++ b/mysql-test/t/percona_heap_blob.test
-@@ -0,0 +1,642 @@
-+########################################################################
-+# Test blobs with the HEAP/MEMORY storage engine
-+########################################################################
-+
-+########################################################################
-+# Modified tests from type_blob.test
-+########################################################################
-+
-+SET @old_default_storage_engine=@@default_storage_engine;
-+SET default_storage_engine=MEMORY;
-+
-+#
-+# Basic cleanup
-+#
-+--disable_warnings
-+drop table if exists t1,t2,t3,t4,t5,t6,t7;
-+--enable_warnings
-+
-+
-+#
-+# Check syntax for creating BLOB/TEXT
-+#
-+
-+CREATE TABLE t1 (a blob, b text, c blob(250), d text(70000), e text(70000000));
-+show columns from t1;
-+# PS doesn't give errors on prepare yet
-+CREATE TABLE t2 (a char(255), b varbinary(70000), c varchar(70000000));
-+CREATE TABLE t4 (c varchar(65530) character set utf8 not null);
-+show columns from t2;
-+create table t3 (a long, b long byte);
-+show create TABLE t3;
-+show create TABLE t4;
-+drop table t1,t2,t3,t4;
-+
-+#
-+# Check errors with blob
-+#
-+
-+--error 1074
-+CREATE TABLE t1 (a char(257) default "hello");
-+--error 1074
-+CREATE TABLE t2 (a char(256));
-+--error 1074
-+CREATE TABLE t1 (a varchar(70000) default "hello");
-+--error 1101
-+CREATE TABLE t2 (a blob default "hello");
-+
-+# Safety to be able to continue with other tests if above fails
-+--disable_warnings
-+drop table if exists t1,t2;
-+--enable_warnings
-+
-+#
-+# test of full join with blob
-+#
-+
-+create table t1 (nr int(5) not null auto_increment,b blob,str char(10), primary key (nr));
-+insert into t1 values (null,"a","A");
-+insert into t1 values (null,"bbb","BBB");
-+insert into t1 values (null,"ccc","CCC");
-+select last_insert_id();
-+select * from t1,t1 as t2;
-+
-+drop table t1;
-+
-+#
-+# Test of changing TEXT column
-+#
-+
-+create table t1 (a text);
-+insert into t1 values ('where');
-+update t1 set a='Where';
-+select * from t1;
-+drop table t1;
-+
-+#
-+# test of blob, text, char and varbinary
-+#
-+create table t1 (t text,c char(10),b blob, d varbinary(10)) collate latin1_general_cs;
-+insert into t1 values (NULL,NULL,NULL,NULL);
-+insert into t1 values ("","","","");
-+insert into t1 values ("hello","hello","hello","hello");
-+insert into t1 values ("HELLO","HELLO","HELLO","HELLO");
-+insert into t1 values ("HELLO MY","HELLO MY","HELLO MY","HELLO MY");
-+insert into t1 values ("a","a","a","a");
-+insert into t1 values (1,1,1,1);
-+insert into t1 values (NULL,NULL,NULL,NULL);
-+update t1 set c="",b=null where c="1";
-+
-+lock tables t1 READ;
-+# We mask out the Privileges column because it differs for embedded server
-+--replace_column 8 #
-+show full fields from t1;
-+lock tables t1 WRITE;
-+--replace_column 8 #
-+show full fields from t1;
-+unlock tables;
-+
-+select t from t1 where t like "hello";
-+select c from t1 where c like "hello";
-+select b from t1 where b like "hello";
-+select d from t1 where d like "hello";
-+select c from t1 having c like "hello";
-+select d from t1 having d like "hello";
-+select t from t1 where t like "%HELLO%";
-+select c from t1 where c like "%HELLO%";
-+select b from t1 where b like "%HELLO%";
-+select d from t1 where d like "%HELLO%";
-+select c from t1 having c like "%HELLO%";
-+select d from t1 having d like "%HELLO%";
-+select d from t1 having d like "%HE%LLO%";
-+select t from t1 order by t;
-+select c from t1 order by c;
-+select b from t1 order by b;
-+select d from t1 order by d;
-+select distinct t from t1;
-+select distinct b from t1;
-+select distinct t from t1 order by t;
-+select distinct b from t1 order by b;
-+select t from t1 group by t;
-+select b from t1 group by b;
-+set option sql_big_tables=1;
-+select distinct t from t1;
-+select distinct b from t1;
-+select distinct t from t1 order by t;
-+select distinct b from t1 order by b;
-+select distinct c from t1;
-+select distinct d from t1;
-+select distinct c from t1 order by c;
-+select distinct d from t1 order by d;
-+select c from t1 group by c;
-+select d from t1 group by d;
-+set option sql_big_tables=0;
-+select distinct * from t1;
-+select t,count(*) from t1 group by t;
-+select b,count(*) from t1 group by b;
-+select c,count(*) from t1 group by c;
-+select d,count(*) from t1 group by d;
-+drop table t1;
-+
-+
-+#
-+# Test of join with blobs and min
-+#
-+
-+CREATE TABLE t1 (
-+ t1_id bigint(21) NOT NULL auto_increment,
-+ _field_72 varchar(128) DEFAULT '' NOT NULL,
-+ _field_95 varchar(32),
-+ _field_115 tinyint(4) DEFAULT '0' NOT NULL,
-+ _field_122 tinyint(4) DEFAULT '0' NOT NULL,
-+ _field_126 tinyint(4),
-+ _field_134 tinyint(4),
-+ PRIMARY KEY (t1_id),
-+ UNIQUE _field_72 (_field_72),
-+ KEY _field_115 (_field_115),
-+ KEY _field_122 (_field_122)
-+);
-+
-+
-+INSERT INTO t1 VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',0,1,NULL,NULL);
-+INSERT INTO t1 VALUES (2,'hroberts','7415275a8c95952901e42b13a6b78566',0,1,NULL,NULL);
-+INSERT INTO t1 VALUES (3,'guest','d41d8cd98f00b204e9800998ecf8427e',1,0,NULL,NULL);
-+
-+
-+CREATE TABLE t2 (
-+ seq_0_id bigint(21) DEFAULT '0' NOT NULL,
-+ seq_1_id bigint(21) DEFAULT '0' NOT NULL,
-+ PRIMARY KEY (seq_0_id,seq_1_id)
-+);
-+
-+
-+INSERT INTO t2 VALUES (1,1);
-+INSERT INTO t2 VALUES (2,1);
-+INSERT INTO t2 VALUES (2,2);
-+
-+CREATE TABLE t3 (
-+ t3_id bigint(21) NOT NULL auto_increment,
-+ _field_131 varchar(128),
-+ _field_133 tinyint(4) DEFAULT '0' NOT NULL,
-+ _field_135 datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
-+ _field_137 tinyint(4),
-+ _field_139 datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
-+ _field_140 blob,
-+ _field_142 tinyint(4) DEFAULT '0' NOT NULL,
-+ _field_145 tinyint(4) DEFAULT '0' NOT NULL,
-+ _field_148 tinyint(4) DEFAULT '0' NOT NULL,
-+ PRIMARY KEY (t3_id),
-+ KEY _field_133 (_field_133),
-+ KEY _field_135 (_field_135),
-+ KEY _field_139 (_field_139),
-+ KEY _field_142 (_field_142),
-+ KEY _field_145 (_field_145),
-+ KEY _field_148 (_field_148)
-+);
-+
-+
-+INSERT INTO t3 VALUES (1,'test job 1',0,'0000-00-00 00:00:00',0,'1999-02-25 22:43:32','test\r\njob\r\n1',0,0,0);
-+INSERT INTO t3 VALUES (2,'test job 2',0,'0000-00-00 00:00:00',0,'1999-02-26 21:08:04','',0,0,0);
-+
-+
-+CREATE TABLE t4 (
-+ seq_0_id bigint(21) DEFAULT '0' NOT NULL,
-+ seq_1_id bigint(21) DEFAULT '0' NOT NULL,
-+ PRIMARY KEY (seq_0_id,seq_1_id)
-+);
-+
-+
-+INSERT INTO t4 VALUES (1,1);
-+INSERT INTO t4 VALUES (2,1);
-+
-+CREATE TABLE t5 (
-+ t5_id bigint(21) NOT NULL auto_increment,
-+ _field_149 tinyint(4),
-+ _field_156 varchar(128) DEFAULT '' NOT NULL,
-+ _field_157 varchar(128) DEFAULT '' NOT NULL,
-+ _field_158 varchar(128) DEFAULT '' NOT NULL,
-+ _field_159 varchar(128) DEFAULT '' NOT NULL,
-+ _field_160 varchar(128) DEFAULT '' NOT NULL,
-+ _field_161 varchar(128) DEFAULT '' NOT NULL,
-+ PRIMARY KEY (t5_id),
-+ KEY _field_156 (_field_156),
-+ KEY _field_157 (_field_157),
-+ KEY _field_158 (_field_158),
-+ KEY _field_159 (_field_159),
-+ KEY _field_160 (_field_160),
-+ KEY _field_161 (_field_161)
-+);
-+
-+
-+INSERT INTO t5 VALUES (1,0,'tomato','','','','','');
-+INSERT INTO t5 VALUES (2,0,'cilantro','','','','','');
-+
-+CREATE TABLE t6 (
-+ seq_0_id bigint(21) DEFAULT '0' NOT NULL,
-+ seq_1_id bigint(21) DEFAULT '0' NOT NULL,
-+ PRIMARY KEY (seq_0_id,seq_1_id)
-+);
-+
-+INSERT INTO t6 VALUES (1,1);
-+INSERT INTO t6 VALUES (1,2);
-+INSERT INTO t6 VALUES (2,2);
-+
-+CREATE TABLE t7 (
-+ t7_id bigint(21) NOT NULL auto_increment,
-+ _field_143 tinyint(4),
-+ _field_165 varchar(32),
-+ _field_166 smallint(6) DEFAULT '0' NOT NULL,
-+ PRIMARY KEY (t7_id),
-+ KEY _field_166 (_field_166)
-+);
-+
-+
-+INSERT INTO t7 VALUES (1,0,'High',1);
-+INSERT INTO t7 VALUES (2,0,'Medium',2);
-+INSERT INTO t7 VALUES (3,0,'Low',3);
-+
-+select replace(t3._field_140, "\r","^M"),t3_id,min(t3._field_131), min(t3._field_135), min(t3._field_139), min(t3._field_137), min(link_alias_142._field_165), min(link_alias_133._field_72), min(t3._field_145), min(link_alias_148._field_156), replace(min(t3._field_140), "\r","^M"),t3.t3_id from t3 left join t4 on t4.seq_0_id = t3.t3_id left join t7 link_alias_142 on t4.seq_1_id = link_alias_142.t7_id left join t6 on t6.seq_0_id = t3.t3_id left join t1 link_alias_133 on t6.seq_1_id = link_alias_133.t1_id left join t2 on t2.seq_0_id = t3.t3_id left join t5 link_alias_148 on t2.seq_1_id = link_alias_148.t5_id where t3.t3_id in (1) group by t3.t3_id order by link_alias_142._field_166, _field_139, link_alias_133._field_72, _field_135, link_alias_148._field_156;
-+
-+drop table t1,t2,t3,t4,t5,t6,t7;
-+
-+#
-+# Test of reverse with empty blob
-+#
-+
-+create table t1 (a blob);
-+insert into t1 values ("empty"),("");
-+select a,reverse(a) from t1;
-+drop table t1;
-+
-+#
-+# Bug when blob is updated
-+#
-+
-+create table t1 (id integer auto_increment unique,imagem LONGBLOB not null default '');
-+insert into t1 (id) values (1);
-+# We have to clean up the path in the results for safe comparison
-+eval select
-+ charset(load_file('../../std_data/words.dat')),
-+ collation(load_file('../../std_data/words.dat')),
-+ coercibility(load_file('../../std_data/words.dat'));
-+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-+eval explain extended select
-+ charset(load_file('$MYSQLTEST_VARDIR/std_data/words.dat')),
-+ collation(load_file('$MYSQLTEST_VARDIR/std_data/words.dat')),
-+ coercibility(load_file('$MYSQLTEST_VARDIR/std_data/words.dat'));
-+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-+eval update t1 set imagem=load_file('$MYSQLTEST_VARDIR/std_data/words.dat') where id=1;
-+select if(imagem is null, "ERROR", "OK"),length(imagem) from t1 where id = 1;
-+drop table t1;
-+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-+eval create table t1 select load_file('$MYSQLTEST_VARDIR/std_data/words.dat') l;
-+# We mask out the Privileges column because it differs for embedded server
-+--replace_column 8 #
-+show full fields from t1;
-+drop table t1;
-+
-+#
-+# Test blob's with end space (Bug #1651)
-+# This is a bit changed since we now have true varchar
-+#
-+
-+create table t1 (id integer primary key auto_increment, txt text not null);
-+insert into t1 (txt) values ('Chevy ');
-+select * from t1 where txt='Chevy';
-+select * from t1 where txt='Chevy ';
-+select * from t1 where txt='Chevy ' or txt='Chevy';
-+select * from t1 where txt='Chevy' or txt='Chevy ';
-+select * from t1 where id='1' or id='2';
-+insert into t1 (txt) values('Ford');
-+select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford';
-+select * from t1 where txt='Chevy' or txt='Chevy ';
-+select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy';
-+select * from t1 where txt in ('Chevy ','Chevy');
-+select * from t1 where txt in ('Chevy');
-+select * from t1 where txt between 'Chevy' and 'Chevy';
-+select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy ';
-+select * from t1 where txt between 'Chevy' and 'Chevy ';
-+select * from t1 where txt < 'Chevy ';
-+select * from t1 where txt <= 'Chevy';
-+select * from t1 where txt > 'Chevy';
-+select * from t1 where txt >= 'Chevy';
-+drop table t1;
-+
-+create table t1 (id integer primary key auto_increment, txt text);
-+insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
-+select * from t1 where txt='Chevy' or txt is NULL;
-+explain select * from t1 where txt='Chevy' or txt is NULL;
-+select * from t1 where txt='Chevy ';
-+select * from t1 where txt='Chevy ' or txt='Chevy';
-+select * from t1 where txt='Chevy' or txt='Chevy ';
-+select * from t1 where id='1' or id='2';
-+insert into t1 (txt) values('Ford');
-+select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford';
-+select * from t1 where txt='Chevy' or txt='Chevy ';
-+select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy';
-+select * from t1 where txt in ('Chevy ','Chevy');
-+select * from t1 where txt in ('Chevy');
-+select * from t1 where txt between 'Chevy' and 'Chevy';
-+select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy ';
-+select * from t1 where txt between 'Chevy' and 'Chevy ';
-+select * from t1 where txt < 'Chevy ';
-+select * from t1 where txt < 'Chevy ' or txt is NULL;
-+select * from t1 where txt <= 'Chevy';
-+select * from t1 where txt > 'Chevy';
-+select * from t1 where txt >= 'Chevy';
-+alter table t1 modify column txt blob;
-+explain select * from t1 where txt='Chevy' or txt is NULL;
-+select * from t1 where txt='Chevy' or txt is NULL;
-+explain select * from t1 where txt='Chevy' or txt is NULL order by txt;
-+select * from t1 where txt='Chevy' or txt is NULL order by txt;
-+drop table t1;
-+
-+CREATE TABLE t1 ( i int(11) NOT NULL default '0', c text NOT NULL, d varchar(1) NOT NULL DEFAULT ' ', PRIMARY KEY (i));
-+INSERT t1 (i, c) VALUES (1,''),(2,''),(3,'asdfh'),(4,'');
-+select max(i) from t1 where c = '';
-+drop table t1;
-+
-+# End of 4.1 tests
-+
-+#
-+# Test that blob's and varbinary are sorted according to length
-+#
-+
-+CREATE table t1 (a blob);
-+insert into t1 values ('b'),('a\0'),('a'),('a '),('aa'),(NULL);
-+select hex(a) from t1 order by a;
-+select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0');
-+alter table t1 modify a varbinary(5);
-+select hex(a) from t1 order by a;
-+select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0');
-+alter table t1 modify a char(5);
-+select hex(a) from t1 order by a;
-+select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0');
-+alter table t1 modify a binary(5);
-+select hex(a) from t1 order by a;
-+select hex(concat(a,'\0')) as b from t1 order by concat(a,'\0');
-+drop table t1;
-+
-+#
-+# Bug #19489: Inconsistent support for DEFAULT in TEXT columns
-+#
-+create table t1 (a text default '');
-+show create table t1;
-+insert into t1 values (default);
-+select * from t1;
-+drop table t1;
-+set @@sql_mode='TRADITIONAL';
-+--error ER_BLOB_CANT_HAVE_DEFAULT
-+create table t1 (a text default '');
-+set @@sql_mode='';
-+
-+#
-+# Bug #32282: TEXT silently truncates when value is exactly 65536 bytes
-+#
-+
-+CREATE TABLE t (c TEXT CHARSET ASCII);
-+INSERT INTO t (c) VALUES (REPEAT('1',65537));
-+INSERT INTO t (c) VALUES (REPEAT('2',65536));
-+INSERT INTO t (c) VALUES (REPEAT('3',65535));
-+SELECT LENGTH(c), CHAR_LENGTH(c) FROM t;
-+DROP TABLE t;
-+# Bug#15776: 32-bit signed int used for length of blob
-+# """LONGBLOB: A BLOB column with a maximum length of 4,294,967,295 or 4GB."""
-+#
-+# Conditions should be in this order:
-+# A size is not in the allowed bounds.
-+# If the type is char-ish AND size is within the max blob size:
-+# raise ER_TOO_BIG_FIELDLENGTH (suggest using BLOB)
-+# If size is too small:
-+# raise ER_PARSE_ERROR
-+# raise ER_TOO_BIG_DISPLAYWIDTH
-+
-+# BLOB and TEXT types
-+--disable_warnings
-+drop table if exists b15776;
-+--enable_warnings
-+create table b15776 (data blob(2147483647));
-+drop table b15776;
-+--error ER_PARSE_ERROR
-+create table b15776 (data blob(-1));
-+create table b15776 (data blob(2147483648));
-+drop table b15776;
-+create table b15776 (data blob(4294967294));
-+drop table b15776;
-+create table b15776 (data blob(4294967295));
-+drop table b15776;
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+create table b15776 (data blob(4294967296));
-+
-+CREATE TABLE b15776 (a blob(2147483647), b blob(2147483648), c blob(4294967295), a1 text(2147483647), b1 text(2147483648), c1 text(4294967295) );
-+show columns from b15776;
-+drop table b15776;
-+
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+CREATE TABLE b15776 (a blob(4294967296));
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+CREATE TABLE b15776 (a text(4294967296));
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+CREATE TABLE b15776 (a blob(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+CREATE TABLE b15776 (a text(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+
-+# Int types
-+# "Another extension is supported by MySQL for optionally specifying the
-+# display width of integer data types in parentheses following the base keyword
-+# for the type (for example, INT(4)). This optional display width is used to
-+# display integer values having a width less than the width specified for the
-+# column by left-padding them with spaces." § Numeric Types
-+CREATE TABLE b15776 (a int(0)); # 0 is special case, means default size
-+INSERT INTO b15776 values (NULL), (1), (42), (654);
-+SELECT * from b15776 ORDER BY a;
-+DROP TABLE b15776;
-+--error ER_PARSE_ERROR
-+CREATE TABLE b15776 (a int(-1));
-+CREATE TABLE b15776 (a int(255));
-+DROP TABLE b15776;
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+CREATE TABLE b15776 (a int(256));
-+--error ER_PARSE_ERROR
-+CREATE TABLE b15776 (data blob(-1));
-+
-+# Char types
-+# Recommend BLOB
-+--error ER_TOO_BIG_FIELDLENGTH
-+CREATE TABLE b15776 (a char(2147483647));
-+--error ER_TOO_BIG_FIELDLENGTH
-+CREATE TABLE b15776 (a char(2147483648));
-+--error ER_TOO_BIG_FIELDLENGTH
-+CREATE TABLE b15776 (a char(4294967295));
-+# Even BLOB won't hold
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+CREATE TABLE b15776 (a char(4294967296));
-+
-+
-+# Other numeric-ish types
-+## For year, widths not "2" or "4" are silently rewritten to "4". But
-+## When we complain about it, we say that the max is 255. We may be
-+## talking about different things. It's confusing.
-+CREATE TABLE b15776 (a year(4294967295));
-+INSERT INTO b15776 VALUES (42);
-+SELECT * FROM b15776;
-+DROP TABLE b15776;
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+CREATE TABLE b15776 (a year(4294967296));
-+CREATE TABLE b15776 (a year(0)); # 0 is special case, means default size
-+DROP TABLE b15776;
-+--error ER_PARSE_ERROR
-+CREATE TABLE b15776 (a year(-2));
-+
-+
-+# We've already tested the case, but this should visually show that
-+# widths that are too large to be interpreted cause DISPLAYWIDTH errors.
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+CREATE TABLE b15776 (a int(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+CREATE TABLE b15776 (a char(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+CREATE TABLE b15776 (a year(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+
-+## Do not select, too much memory needed.
-+CREATE TABLE b15776 select cast(null as char(4294967295));
-+show columns from b15776;
-+drop table b15776;
-+CREATE TABLE b15776 select cast(null as nchar(4294967295));
-+show columns from b15776;
-+drop table b15776;
-+CREATE TABLE b15776 select cast(null as binary(4294967295));
-+show columns from b15776;
-+drop table b15776;
-+
-+explain select cast(1 as char(4294967295));
-+explain select cast(1 as nchar(4294967295));
-+explain select cast(1 as binary(4294967295));
-+
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+explain select cast(1 as char(4294967296));
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+explain select cast(1 as nchar(4294967296));
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+explain select cast(1 as binary(4294967296));
-+
-+--error ER_PARSE_ERROR
-+explain select cast(1 as decimal(-1));
-+explain select cast(1 as decimal(64, 30));
-+# It's not as important which errors are raised for these, since the
-+# limit is nowhere near 2**32. We may fix these eventually to take
-+# 4294967295 and still reject it because it's greater than 64 or 30,
-+# but that's not a high priority and the parser needn't worry about
-+# such a weird case.
-+--error ER_TOO_BIG_SCALE,ER_PARSE_ERROR
-+explain select cast(1 as decimal(64, 999999999999999999999999999999));
-+--error ER_TOO_BIG_PRECISION,ER_PARSE_ERROR
-+explain select cast(1 as decimal(4294967296));
-+--error ER_TOO_BIG_PRECISION,ER_PARSE_ERROR
-+explain select cast(1 as decimal(999999999999999999999999999999999999));
-+
-+explain select convert(1, char(4294967295));
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+explain select convert(1, char(4294967296));
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+explain select convert(1, char(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+explain select convert(1, nchar(4294967295));
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+explain select convert(1, nchar(4294967296));
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+explain select convert(1, nchar(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+explain select convert(1, binary(4294967295));
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+explain select convert(1, binary(4294967296));
-+--error ER_TOO_BIG_DISPLAYWIDTH
-+explain select convert(1, binary(999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999));
-+
-+--echo End of 5.0 tests
-+
-+#
-+# Bug #33969: Updating a text field via a left join
-+#
-+
-+CREATE TABLE t1(id INT NOT NULL);
-+CREATE TABLE t2(id INT NOT NULL, c TEXT NOT NULL);
-+
-+INSERT INTO t1 VALUES (1);
-+INSERT INTO t2 VALUES (1, '');
-+
-+UPDATE t2 SET c = REPEAT('1', 70000);
-+SELECT LENGTH(c) FROM t2;
-+
-+UPDATE t1 LEFT JOIN t2 USING(id) SET t2.c = REPEAT('1', 70000) WHERE t1.id = 1;
-+SELECT LENGTH(c) FROM t2;
-+
-+DROP TABLE t1, t2;
-+
-+--echo # Bug #52160: crash and inconsistent results when grouping
-+--echo # by a function and column
-+
-+CREATE FUNCTION f1() RETURNS TINYBLOB RETURN 1;
-+
-+CREATE TABLE t1(a CHAR(1));
-+INSERT INTO t1 VALUES ('0'), ('0');
-+
-+SELECT COUNT(*) FROM t1 GROUP BY f1(), a;
-+
-+DROP FUNCTION f1;
-+DROP TABLE t1;
-+
-+
-+
-+
-+
-+########################################################################
-+# Modified test from myisam-blob.test
-+########################################################################
-+
-+SET @old_max_heap_table_size = @@global.max_heap_table_size;
-+SET @old_max_allowed_packet = @@global.max_allowed_packet;
-+SET GLOBAL max_heap_table_size = 18 * 1024 * 1024;
-+SET GLOBAL max_allowed_packet = 24 * 1024 * 1024;
-+
-+connect(con1, localhost, root,,);
-+connection con1;
-+
-+--disable_warnings
-+drop table if exists t1;
-+--enable_warnings
-+
-+# Bug #2159 (Problem with update of blob to > 16M)
-+
-+CREATE TABLE t1 (data LONGBLOB);
-+INSERT INTO t1 (data) VALUES (NULL);
-+UPDATE t1 set data=repeat('a',18*1024*1024);
-+select length(data) from t1;
-+delete from t1 where left(data,1)='a';
-+truncate table t1;
-+INSERT INTO t1 (data) VALUES (repeat('a',1*1024*1024));
-+INSERT INTO t1 (data) VALUES (repeat('b',16*1024*1024-1024));
-+delete from t1 where left(data,1)='b';
-+
-+# now we have two blocks in the table, first is a 1M record and second is
-+# a 16M delete block.
-+
-+UPDATE t1 set data=repeat('c',17*1024*1024);
-+delete from t1 where left(data,1)='c';
-+
-+INSERT INTO t1 set data=repeat('a',18*1024*1024);
-+select length(data) from t1;
-+alter table t1 modify data blob;
-+select length(data) from t1;
-+drop table t1;
-+
-+CREATE TABLE t1 (data BLOB);
-+INSERT INTO t1 (data) VALUES (NULL);
-+UPDATE t1 set data=repeat('a',18*1024*1024);
-+select length(data) from t1;
-+drop table t1;
-+
-+disconnect con1;
-+connection default;
-+
-+SET GLOBAL max_allowed_packet = @old_max_allowed_packet;
-+SET GLOBAL max_heap_table_size = @old_max_heap_table_size;
-+SET default_storage_engine=@old_default_storage_engine;
---- /dev/null
-+++ b/mysql-test/t/percona_heap_bug783366.test
-@@ -0,0 +1,19 @@
-+#
-+# Test for bug lp:783366
-+#
-+
-+--disable_warnings
-+drop table if exists t1;
-+--enable_warnings
-+
-+CREATE TABLE t1 (
-+ f1 VARCHAR ( 128 ) ,
-+ f2 VARCHAR ( 32 ),
-+ PRIMARY KEY ( f2 ( 2 ) , f1 )
-+)
-+ENGINE=HEAP KEY_BLOCK_SIZE = 512;
-+INSERT IGNORE INTO t1 VALUES ( 'te' , 'm') , ( NULL , 'think' );
-+INSERT IGNORE INTO t1 VALUES ( 'te' , 'm') , ( NULL , 'think' );
-+
-+DROP TABLE t1;
-+
---- /dev/null
-+++ b/mysql-test/t/percona_heap_bug783451.test
-@@ -0,0 +1,16 @@
-+# Testcase for the bug https://bugs.launchpad.net/percona-projects-qa/+bug/783451
-+# With dynamic row format in HEAP and the UPDATE statement that significantly
-+# increases the data size, the table scan in-progress desyncs its table position state.
-+# Run with Valgrind if it does not crash for you.
-+--disable_warnings
-+DROP TABLE IF EXISTS local_1_1;
-+--enable_warnings
-+CREATE TABLE IF NOT EXISTS local_1_1 ( f1 VARCHAR ( 32 ) NOT NULL , f2 VARCHAR ( 128 ) NOT NULL DEFAULT 'cboepfaobilcchabvglgjdbynog' , f3 VARCHAR ( 32 ) NOT NULL , f4 VARBINARY ( 32 ) NOT NULL , f5 VARBINARY ( 1024 ) DEFAULT 'ycboepfao' , KEY ( f1 /* ( 2 ) */ , f2 /* ( 2 ) */ ) ) ENGINE=HEAP KEY_BLOCK_SIZE = 512;
-+INSERT IGNORE INTO local_1_1 VALUES ( REPEAT( 'ervydbimvmbqmsowdbsa' , 1 ) , 'v' , NULL , NULL , REPEAT( 'mervydbimvmbqms' , 5 ) ) , ( 'p' , 6 , 'n' , REPEAT( 'imervydbimvmbqmsowdbs' , 4 ) , 'do' ) , ( NULL , NULL , REPEAT( 'himervydbimvmbqmsowdbsaybudvwaamvhempuublmia' , 6 ) , REPEAT('X', POW(2, 20) * 2) , REPEAT('X', POW(2, 20) * 2) ) , ( REPEAT('X', POW(2, 20) * 2) , REPEAT( 'Y' , 763 ) , NULL , REPEAT('X', POW(2, 20) * 2) , NULL ) , ( REPEAT('X', POW(2, 20) * 2) , 'time' , 'how' , 2 , REPEAT( 'Y' , 107 ) ) , ( REPEAT( 'hyshimervydbimvmbqmsowdbsaybud' , 5 ) , 2 , 8 , NULL , REPEAT('X', POW(2, 20) * 2) ) , ( 'come' , NULL , 'i' , NULL , REPEAT('X', POW(2, 20) * 2) );
-+INSERT IGNORE INTO local_1_1 VALUES ( 'ok' , NULL , REPEAT( 'Y' , 651 ) , 2 , 5 ) , ( REPEAT( 'zylcdzkfrqpihyshimervydbimvmbqmsowdbsaybu' , 3 ) , REPEAT( 'Y' , 282 ) , REPEAT( 'X' , 0 ) , REPEAT( 'Y' , 369 ) , 'g' ) , ( 'think' , REPEAT('X', POW(2, 20) * 2), NULL , NULL , REPEAT('X', POW(2, 20) * 2) ) , ( REPEAT( 'Y' , 468 ) , REPEAT( 'dfvbrzylcd' , 6 ) , REPEAT( 'Y' , 264 ) , NULL , 'c' ) , ( NULL , NULL , REPEAT( 'srdfvbrzylcdzkfrqpihyshimervydbimvmbqms' , 0 ) , REPEAT( 'Y' , 244 ) , 7 ) , ( REPEAT( 'Y' , 0 ) , 'how' , 'going' , 'q' , NULL );
-+INSERT IGNORE INTO local_1_1 VALUES ( REPEAT('X', POW(2, 20) * 2) , NULL , NULL , NULL , REPEAT('X', POW(2, 20) * 2) ) , ( REPEAT('X', POW(2, 20) * 2) , NULL , REPEAT('X', POW(2, 20) * 2) , 'this' , 'e' ) , ( NULL , 'think' , NULL , 'were' , NULL ) , ( 9 , 'l' , 'c' , 3 , REPEAT( 'geysrdfvbrzylcdzkfrqpihyshimervydbi' , 5 ) ) , ( NULL , NULL , NULL , 'h' , 'w' );
-+--enable_warnings
-+INSERT IGNORE INTO local_1_1 SELECT * FROM local_1_1;
-+INSERT IGNORE INTO local_1_1 SELECT * FROM local_1_1;
-+UPDATE local_1_1 SET f5 = REPEAT ('X', 215566);
-+DROP TABLE local_1_1;
---- /dev/null
-+++ b/mysql-test/t/percona_heap_bug784464.test
-@@ -0,0 +1,66 @@
-+#
-+# Bug #784464: Silent conversion from Dynamic to Fixed row_format for certain
-+# values of key_block_size.
-+# Also see percona_heap_bug784464_32bit and percona_heap_bug784464_64bit tests.
-+#
-+
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32),
-+ PRIMARY KEY (f1)) ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 6 X 8 X 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+DROP TABLE t1;
-+
-+--error ER_CANT_USE_OPTION_HERE
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32),
-+ PRIMARY KEY (f1)) KEY_BLOCK_SIZE=33 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32),
-+ PRIMARY KEY (f1)) KEY_BLOCK_SIZE=34 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 6 X 8 X 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+DROP TABLE t1;
-+
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32),
-+ PRIMARY KEY (f1)) KEY_BLOCK_SIZE=123 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 6 X 8 X 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+DROP TABLE t1;
-+
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32),
-+ PRIMARY KEY (f1)) KEY_BLOCK_SIZE=1000 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 6 X 8 X 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+DROP TABLE t1;
-+
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96),
-+ PRIMARY KEY (f1)) ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 6 X 8 X 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+DROP TABLE t1;
-+
-+--error ER_CANT_USE_OPTION_HERE
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96),
-+ PRIMARY KEY (f1)) KEY_BLOCK_SIZE=33 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96),
-+ PRIMARY KEY (f1)) KEY_BLOCK_SIZE=34 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 6 X 8 X 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+DROP TABLE t1;
-+
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96),
-+ PRIMARY KEY (f1)) KEY_BLOCK_SIZE=121 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 6 X 8 X 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+DROP TABLE t1;
-+
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96),
-+ PRIMARY KEY (f1)) KEY_BLOCK_SIZE=1000 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 6 X 8 X 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+DROP TABLE t1;
-+
---- /dev/null
-+++ b/mysql-test/t/percona_heap_bug784464_32bit.test
-@@ -0,0 +1,15 @@
-+# 32-bit platform specific parts of tests for LP bug #784464
-+
-+--source include/have_32bit.inc
-+
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32),
-+ PRIMARY KEY (f1)) KEY_BLOCK_SIZE=124 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 6 X 8 X 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+DROP TABLE t1;
-+
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96),
-+ PRIMARY KEY (f1)) KEY_BLOCK_SIZE=122 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 6 X 8 X 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/t/percona_heap_bug784464_64bit.test
-@@ -0,0 +1,15 @@
-+# 64-bit platform specific parts of tests for LP bug #784464
-+
-+--source include/have_64bit.inc
-+
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(32), f3 VARCHAR(32), f4 VARCHAR(32),
-+ PRIMARY KEY (f1)) KEY_BLOCK_SIZE=124 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 6 X 8 X 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+DROP TABLE t1;
-+
-+CREATE TABLE t1 (f1 VARCHAR(32), f2 VARCHAR(96),
-+ PRIMARY KEY (f1)) KEY_BLOCK_SIZE=122 ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 6 X 8 X 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/t/percona_heap_bug784468.test
-@@ -0,0 +1,19 @@
-+#
-+# Bug #784468: Tables with VARCHAR(<31) are created as row_format = Fixed
-+#
-+
-+CREATE TABLE t1 ( f1 VARCHAR(30)) ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 8 X 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+DROP TABLE t1;
-+
-+CREATE TABLE t1 ( f1 VARCHAR(31)) ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 8 X 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+DROP TABLE t1;
-+
-+CREATE TABLE t1 ( f1 VARCHAR(32)) ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+--replace_column 8 X 12 X 13 X
-+SHOW TABLE STATUS LIKE 't1';
-+DROP TABLE t1;
-+
---- /dev/null
-+++ b/mysql-test/t/percona_heap_bug788544.test
-@@ -0,0 +1,15 @@
-+#
-+# Bug #788544: Valgrind warnings/crash in mysql-55-eb-blobs in
-+# hp_extract_record / hp_process_field_data_to_chunkset
-+#
-+
-+CREATE TABLE t1 (f2 VARCHAR (32), f4 LONGBLOB, f5 TEXT) ENGINE=HEAP;
-+
-+INSERT INTO t1 VALUES ('a', NULL, NULL),
-+ ('b' , REPEAT('a' , 593338), REPEAT('a', 800));
-+
-+UPDATE t1 SET f2 = 'c' WHERE f4 = 'd';
-+
-+SELECT LENGTH(f2), LENGTH(f4), LENGTH(f5) FROM t1;
-+
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/t/percona_heap_bug788576.test
-@@ -0,0 +1,19 @@
-+#
-+# Bug #788576: Second crash in hp_movelink with mysql-55-eb
-+#
-+
-+CREATE TABLE t1 (f1 VARCHAR (32), f2 VARCHAR (128), f3 VARBINARY (128),
-+ f4 VARBINARY (512), f5 VARBINARY (1024),
-+ KEY (f2(1))) ENGINE=HEAP ROW_FORMAT=DYNAMIC;
-+
-+INSERT IGNORE INTO t1 VALUES (2, NULL, 6, REPEAT('glugcgqk', 5), 'look'),
-+ (REPEAT( 'kglugcgqkin', 6), 'if', 'was', NULL, NULL),
-+ (NULL, NULL, NULL, NULL, 7);
-+
-+SELECT * FROM t1;
-+
-+DELETE FROM t1 WHERE f5 <=> NULL;
-+
-+SELECT * FROM t1;
-+
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/t/percona_heap_bug788722.test
-@@ -0,0 +1,20 @@
-+#
-+# Bug #788722: Second valgrind warning around hp_extract_record in mysql-55-eb-blobs
-+#
-+
-+CREATE TABLE IF NOT EXISTS local_1_1 (f1 VARCHAR (32) NOT NULL,
-+ f2 VARCHAR (128) NOT NULL,
-+ f3 BLOB NOT NULL,
-+ f4 TEXT,
-+ f5 BLOB (1024),
-+ PRIMARY KEY (f1),
-+ KEY (f1 , f2)
-+) ENGINE=HEAP ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE = 2048;
-+
-+INSERT IGNORE INTO local_1_1 VALUES
-+ (REPEAT('egqeqfxwaejpqixuvvtentruyqadxiybjdfqjspfbyjdjczrrwjnagkzsoagatqookhsgtrvvbxacppljfzaseidqggxvuirm' , 5), NULL, NULL, NULL, REPEAT('hegqeqfxwaejpqixuvvtentruyqadxiy', 1)),
-+ ('you', NULL, 0, REPEAT("X", 2048) , 0);
-+
-+INSERT IGNORE INTO local_1_1 SELECT * FROM local_1_1;
-+
-+DROP TABLE local_1_1;
---- /dev/null
-+++ b/mysql-test/t/percona_heap_bug789131.test
-@@ -0,0 +1,14 @@
-+#
-+# Bug #789131: Valgrind warning in MyISAM in mysql-55-eb-blobs
-+#
-+
-+CREATE TABLE t1 (f1 VARCHAR (128), f2 VARCHAR (128), f3 VARBINARY (512),
-+ f4 TEXT (65525), f5 VARCHAR (128), KEY (f1(1))) ENGINE=HEAP;
-+
-+INSERT IGNORE INTO t1 VALUES
-+ ( 'o' , "" , NULL , "" , 0 ) ,
-+ (NULL, "" , "" , "" , 'f' ) ;
-+
-+INSERT IGNORE INTO t1 SELECT * FROM t1;
-+
-+DROP TABLE t1;
-\ No newline at end of file
---- /dev/null
-+++ b/mysql-test/t/percona_heap_var.test
-@@ -0,0 +1,85 @@
-+#
-+# Test heap tables with variable-sized records.
-+#
-+
-+--disable_warnings
-+drop table if exists t1;
-+--enable_warnings
-+
-+set @@session.max_heap_table_size=16*1024*1024;
-+
-+--error 1234
-+create table t1 (a int not null, b varchar(400), c int, primary key (a), key (c)) engine=heap comment="testing heaps" key_block_size=128;
-+
-+--error 1234
-+create table t1 (a int not null, b int, c varchar(400), primary key (a), key (b)) engine=heap comment="testing heaps" key_block_size=4;
-+
-+create table t1 (a int not null, b int, c varchar(400), d varchar(400), primary key (a), key (b)) engine=heap comment="testing heaps" key_block_size=24;
-+
-+--replace_column 6 X 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X
-+--query_vertical show table status like "t1"
-+
-+insert into t1 values (1,1,'012',NULL), (2,2,'0123456789',NULL), (3,3,'012345678901234567890123456789',NULL), (4,4,NULL,'0123456789012345678901234567890123456789012345678901234567890123456789');
-+select * from t1;
-+
-+delete from t1 where a = 3;
-+select * from t1;
-+
-+insert into t1 values (5,5,NULL,'0123'), (6,6,NULL,'0123');
-+select * from t1;
-+
-+update t1 set c = '012345678901234567890123456789' where a = 2;
-+select * from t1;
-+
-+update t1 set c = '0123456789' where a = 2;
-+select * from t1;
-+
-+insert into t1 values (7,7,'0123',NULL), (8,8,'0123',NULL);
-+select * from t1;
-+
-+--replace_column 6 X 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X
-+--query_vertical show table status like "t1"
-+alter table t1 key_block_size = 0;
-+--replace_column 6 X 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X
-+--query_vertical show table status like "t1"
-+alter table t1 row_format = dynamic;
-+--replace_column 6 X 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X
-+--replace_regex /KEY_BLOCK_SIZE=[[:digit:]]+/KEY_BLOCK_SIZE=X/
-+--query_vertical show table status like "t1"
-+alter table t1 key_block_size = 128, max_rows = 10001;
-+--replace_column 6 X 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X
-+--query_vertical show table status like "t1"
-+
-+select * from t1;
-+
-+delete from t1;
-+select * from t1;
-+
-+let $1=10001;
-+
-+call mtr.add_suppression("The table 't1' is full");
-+
-+disable_query_log;
-+
-+while ($1)
-+{
-+
-+ eval insert into t1 values ($1,$1,$1,$1);
-+
-+ dec $1;
-+
-+}
-+enable_query_log;
-+
-+select count(*) from t1;
-+
-+--error 1114
-+insert into t1 values (100000,100000,NULL,'0123'), (100000,100000,NULL,'0123');
-+
-+--replace_column 6 X 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X
-+--query_vertical show table status like "t1"
-+select count(*) from t1;
-+
-+set @@session.max_heap_table_size=default;
-+
-+drop table t1;
+++ /dev/null
-# name : microsec_process.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- /dev/null
-+++ b/patch_info/microsec_process.info
-@@ -0,0 +1,8 @@
-+File=microsec_process.patch
-+Name=Adds INFOMATION_SCHEMA.PROCESSLIST with TIME_MS column
-+Version=1.0
-+Author=Percona <info@percona.com>
-+License=GPL
-+Comment=
-+2010-01
-+Ported to 5.1.42
---- a/sql/sql_show.cc
-+++ b/sql/sql_show.cc
-@@ -1890,7 +1890,8 @@
- TABLE *table= tables->table;
- CHARSET_INFO *cs= system_charset_info;
- char *user;
-- time_t now= my_time(0);
-+ time_t now;
-+ ulonglong now_utime= my_micro_time_and_time(&now);
- DBUG_ENTER("fill_process_list");
-
- user= thd->security_ctx->master_access & PROCESS_ACL ?
-@@ -1974,6 +1975,10 @@
- }
- mysql_mutex_unlock(&tmp->LOCK_thd_data);
-
-+ /* TIME_MS */
-+ table->field[8]->store(((tmp->start_utime ?
-+ now_utime - tmp->start_utime : 0)/ 1000));
-+
- if (schema_table_store_record(thd, table))
- {
- mysql_mutex_unlock(&LOCK_thread_count);
-@@ -7464,6 +7469,8 @@
- {"STATE", 64, MYSQL_TYPE_STRING, 0, 1, "State", SKIP_OPEN_TABLE},
- {"INFO", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info",
- SKIP_OPEN_TABLE},
-+ {"TIME_MS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG,
-+ 0, 0, "Time_ms", SKIP_OPEN_TABLE},
- {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
- };
-
+++ /dev/null
-# name : mysql-test.diff
-# introduced : ???
-# maintainer : ???
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
-diff -ruN a/mysql-test/include/default_mysqld.cnf b/mysql-test/include/default_mysqld.cnf
---- a/mysql-test/include/default_mysqld.cnf 2010-11-03 07:01:11.000000000 +0900
-+++ b/mysql-test/include/default_mysqld.cnf 2010-12-10 16:48:10.996387047 +0900
-@@ -29,7 +29,7 @@
- max_heap_table_size= 1M
-
- loose-innodb_data_file_path= ibdata1:10M:autoextend
--loose-innodb_buffer_pool_size= 8M
-+loose-innodb_buffer_pool_size= 32M
- loose-innodb_write_io_threads= 2
- loose-innodb_read_io_threads= 2
- loose-innodb_log_buffer_size= 1M
-diff -ruN a/mysql-test/r/connect.result b/mysql-test/r/connect.result
---- a/mysql-test/r/connect.result 2010-11-03 07:01:12.000000000 +0900
-+++ b/mysql-test/r/connect.result 2010-12-10 16:48:10.997386982 +0900
-@@ -1,3 +1,4 @@
-+set global log_warnings=0;
- drop table if exists t1,t2;
- show tables;
- Tables_in_mysql
-@@ -221,3 +222,4 @@
- # ------------------------------------------------------------------
- # -- End of 5.1 tests
- # ------------------------------------------------------------------
-+set global log_warnings=1;
-diff -ruN a/mysql-test/r/create.result b/mysql-test/r/create.result
---- a/mysql-test/r/create.result 2010-11-03 07:01:12.000000000 +0900
-+++ b/mysql-test/r/create.result 2010-12-10 16:48:11.001009442 +0900
-@@ -1741,7 +1741,8 @@
- `COMMAND` varchar(16) NOT NULL DEFAULT '',
- `TIME` int(7) NOT NULL DEFAULT '0',
- `STATE` varchar(64) DEFAULT NULL,
-- `INFO` longtext
-+ `INFO` longtext,
-+ `TIME_MS` bigint(21) NOT NULL DEFAULT '0'
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8
- drop table t1;
- create temporary table t1 like information_schema.processlist;
-@@ -1755,7 +1756,8 @@
- `COMMAND` varchar(16) NOT NULL DEFAULT '',
- `TIME` int(7) NOT NULL DEFAULT '0',
- `STATE` varchar(64) DEFAULT NULL,
-- `INFO` longtext
-+ `INFO` longtext,
-+ `TIME_MS` bigint(21) NOT NULL DEFAULT '0'
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8
- drop table t1;
- create table t1 like information_schema.character_sets;
-diff -ruN a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
---- a/mysql-test/r/information_schema.result 2010-12-03 20:58:24.000000000 +0300
-+++ b/mysql-test/r/information_schema.result 2011-01-10 23:02:09.000000000 +0300
-@@ -46,14 +46,17 @@
- select * from v1;
- c
- CHARACTER_SETS
-+CLIENT_STATISTICS
- COLLATIONS
- COLLATION_CHARACTER_SET_APPLICABILITY
- COLUMNS
- COLUMN_PRIVILEGES
-+INDEX_STATISTICS
- ENGINES
- EVENTS
- FILES
- GLOBAL_STATUS
-+GLOBAL_TEMPORARY_TABLES
- GLOBAL_VARIABLES
- KEY_COLUMN_USAGE
- PARAMETERS
-@@ -63,6 +66,7 @@
- PROFILING
- REFERENTIAL_CONSTRAINTS
- ROUTINES
-+QUERY_RESPONSE_TIME
- SCHEMATA
- SCHEMA_PRIVILEGES
- SESSION_STATUS
-@@ -72,9 +76,14 @@
- TABLESPACES
- TABLE_CONSTRAINTS
- TABLE_PRIVILEGES
-+TABLE_STATISTICS
-+TEMPORARY_TABLES
-+THREAD_STATISTICS
- TRIGGERS
- USER_PRIVILEGES
-+USER_STATISTICS
- VIEWS
-+XTRADB_ADMIN_COMMAND
- columns_priv
- db
- event
-@@ -112,6 +121,9 @@
- TABLESPACES TABLESPACES
- TABLE_CONSTRAINTS TABLE_CONSTRAINTS
- TABLE_PRIVILEGES TABLE_PRIVILEGES
-+TABLE_STATISTICS TABLE_STATISTICS
-+TEMPORARY_TABLES TEMPORARY_TABLES
-+THREAD_STATISTICS THREAD_STATISTICS
- TRIGGERS TRIGGERS
- tables_priv tables_priv
- time_zone time_zone
-@@ -132,6 +144,9 @@
- TABLESPACES TABLESPACES
- TABLE_CONSTRAINTS TABLE_CONSTRAINTS
- TABLE_PRIVILEGES TABLE_PRIVILEGES
-+TABLE_STATISTICS TABLE_STATISTICS
-+TEMPORARY_TABLES TEMPORARY_TABLES
-+THREAD_STATISTICS THREAD_STATISTICS
- TRIGGERS TRIGGERS
- tables_priv tables_priv
- time_zone time_zone
-@@ -152,6 +167,9 @@
- TABLESPACES TABLESPACES
- TABLE_CONSTRAINTS TABLE_CONSTRAINTS
- TABLE_PRIVILEGES TABLE_PRIVILEGES
-+TABLE_STATISTICS TABLE_STATISTICS
-+TEMPORARY_TABLES TEMPORARY_TABLES
-+THREAD_STATISTICS THREAD_STATISTICS
- TRIGGERS TRIGGERS
- tables_priv tables_priv
- time_zone time_zone
-@@ -634,13 +652,16 @@
- where table_schema='information_schema' limit 2;
- TABLE_NAME TABLE_TYPE ENGINE
- CHARACTER_SETS SYSTEM VIEW MEMORY
--COLLATIONS SYSTEM VIEW MEMORY
-+CLIENT_STATISTICS SYSTEM VIEW MEMORY
- show tables from information_schema like "T%";
- Tables_in_information_schema (T%)
- TABLES
- TABLESPACES
- TABLE_CONSTRAINTS
- TABLE_PRIVILEGES
-+TABLE_STATISTICS
-+TEMPORARY_TABLES
-+THREAD_STATISTICS
- TRIGGERS
- create database information_schema;
- ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
-@@ -651,6 +672,9 @@
- TABLESPACES SYSTEM VIEW
- TABLE_CONSTRAINTS SYSTEM VIEW
- TABLE_PRIVILEGES SYSTEM VIEW
-+TABLE_STATISTICS SYSTEM VIEW
-+TEMPORARY_TABLES SYSTEM VIEW
-+THREAD_STATISTICS SYSTEM VIEW
- TRIGGERS SYSTEM VIEW
- create table t1(a int);
- ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
-@@ -664,6 +688,9 @@
- TABLESPACES
- TABLE_CONSTRAINTS
- TABLE_PRIVILEGES
-+TABLE_STATISTICS
-+TEMPORARY_TABLES
-+THREAD_STATISTICS
- TRIGGERS
- select table_name from tables where table_name='user';
- table_name
-@@ -806,6 +833,8 @@
- FILES CREATE_TIME datetime
- FILES UPDATE_TIME datetime
- FILES CHECK_TIME datetime
-+GLOBAL_TEMPORARY_TABLES CREATE_TIME datetime
-+GLOBAL_TEMPORARY_TABLES UPDATE_TIME datetime
- PARTITIONS CREATE_TIME datetime
- PARTITIONS UPDATE_TIME datetime
- PARTITIONS CHECK_TIME datetime
-@@ -814,6 +843,8 @@
- TABLES CREATE_TIME datetime
- TABLES UPDATE_TIME datetime
- TABLES CHECK_TIME datetime
-+TEMPORARY_TABLES CREATE_TIME datetime
-+TEMPORARY_TABLES UPDATE_TIME datetime
- TRIGGERS CREATED datetime
- event execute_at datetime
- event last_executed datetime
-@@ -854,7 +885,9 @@
- TABLE_NAME COLUMN_NAME PRIVILEGES
- COLUMNS TABLE_NAME select
- COLUMN_PRIVILEGES TABLE_NAME select
-+INDEX_STATISTICS TABLE_NAME select
- FILES TABLE_NAME select
-+GLOBAL_TEMPORARY_TABLES TABLE_NAME select
- KEY_COLUMN_USAGE TABLE_NAME select
- PARTITIONS TABLE_NAME select
- REFERENTIAL_CONSTRAINTS TABLE_NAME select
-@@ -862,7 +895,11 @@
- TABLES TABLE_NAME select
- TABLE_CONSTRAINTS TABLE_NAME select
- TABLE_PRIVILEGES TABLE_NAME select
-+TABLE_STATISTICS TABLE_NAME select
-+TEMPORARY_TABLES TABLE_NAME select
- VIEWS TABLE_NAME select
-+INNODB_TABLE_STATS table_name select
-+INNODB_INDEX_STATS table_name select
- delete from mysql.user where user='mysqltest_4';
- delete from mysql.db where user='mysqltest_4';
- flush privileges;
-@@ -871,7 +908,7 @@
- AND table_name not like 'ndb%' AND table_name not like 'innodb_%'
- GROUP BY TABLE_SCHEMA;
- table_schema count(*)
--information_schema 30
-+information_schema 39
- mysql 23
- create table t1 (i int, j int);
- create trigger trg1 before insert on t1 for each row
-@@ -1245,12 +1282,12 @@
- DROP USER mysql_bug20230@localhost;
- SELECT MAX(table_name) FROM information_schema.tables WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test');
- MAX(table_name)
--VIEWS
-+XTRADB_ADMIN_COMMAND
- SELECT table_name from information_schema.tables
- WHERE table_name=(SELECT MAX(table_name)
- FROM information_schema.tables WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test'));
- table_name
--VIEWS
-+XTRADB_ADMIN_COMMAND
- DROP TABLE IF EXISTS bug23037;
- DROP FUNCTION IF EXISTS get_value;
- SELECT COLUMN_NAME, MD5(COLUMN_DEFAULT), LENGTH(COLUMN_DEFAULT) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='bug23037';
-@@ -1311,6 +1348,7 @@
- group by t.table_name order by num1, t.table_name;
- table_name group_concat(t.table_schema, '.', t.table_name) num1
- CHARACTER_SETS information_schema.CHARACTER_SETS 1
-+CLIENT_STATISTICS information_schema.CLIENT_STATISTICS 1
- COLLATIONS information_schema.COLLATIONS 1
- COLLATION_CHARACTER_SET_APPLICABILITY information_schema.COLLATION_CHARACTER_SET_APPLICABILITY 1
- COLUMNS information_schema.COLUMNS 1
-@@ -1319,13 +1357,16 @@
- EVENTS information_schema.EVENTS 1
- FILES information_schema.FILES 1
- GLOBAL_STATUS information_schema.GLOBAL_STATUS 1
-+GLOBAL_TEMPORARY_TABLES information_schema.GLOBAL_TEMPORARY_TABLES 1
- GLOBAL_VARIABLES information_schema.GLOBAL_VARIABLES 1
-+INDEX_STATISTICS information_schema.INDEX_STATISTICS 1
- KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
- PARAMETERS information_schema.PARAMETERS 1
- PARTITIONS information_schema.PARTITIONS 1
- PLUGINS information_schema.PLUGINS 1
- PROCESSLIST information_schema.PROCESSLIST 1
- PROFILING information_schema.PROFILING 1
-+QUERY_RESPONSE_TIME information_schema.QUERY_RESPONSE_TIME 1
- REFERENTIAL_CONSTRAINTS information_schema.REFERENTIAL_CONSTRAINTS 1
- ROUTINES information_schema.ROUTINES 1
- SCHEMATA information_schema.SCHEMATA 1
-@@ -1337,8 +1378,12 @@
- TABLESPACES information_schema.TABLESPACES 1
- TABLE_CONSTRAINTS information_schema.TABLE_CONSTRAINTS 1
- TABLE_PRIVILEGES information_schema.TABLE_PRIVILEGES 1
-+TABLE_STATISTICS information_schema.TABLE_STATISTICS 1
-+TEMPORARY_TABLES information_schema.TEMPORARY_TABLES 1
-+THREAD_STATISTICS information_schema.THREAD_STATISTICS 1
- TRIGGERS information_schema.TRIGGERS 1
- USER_PRIVILEGES information_schema.USER_PRIVILEGES 1
-+USER_STATISTICS information_schema.USER_STATISTICS 1
- VIEWS information_schema.VIEWS 1
- create table t1(f1 int);
- create view v1 as select f1+1 as a from t1;
-diff -ruN a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result
---- a/mysql-test/r/information_schema_db.result 2010-12-03 20:58:24.000000000 +0300
-+++ b/mysql-test/r/information_schema_db.result 2011-01-10 23:06:43.000000000 +0300
-@@ -6,14 +6,17 @@
- show tables where Tables_in_information_schema NOT LIKE 'Innodb%';
- Tables_in_information_schema
- CHARACTER_SETS
-+CLIENT_STATISTICS
- COLLATIONS
- COLLATION_CHARACTER_SET_APPLICABILITY
- COLUMNS
- COLUMN_PRIVILEGES
-+INDEX_STATISTICS
- ENGINES
- EVENTS
- FILES
- GLOBAL_STATUS
-+GLOBAL_TEMPORARY_TABLES
- GLOBAL_VARIABLES
- KEY_COLUMN_USAGE
- PARAMETERS
-@@ -23,6 +26,7 @@
- PROFILING
- REFERENTIAL_CONSTRAINTS
- ROUTINES
-+QUERY_RESPONSE_TIME
- SCHEMATA
- SCHEMA_PRIVILEGES
- SESSION_STATUS
-@@ -32,15 +36,23 @@
- TABLESPACES
- TABLE_CONSTRAINTS
- TABLE_PRIVILEGES
-+TABLE_STATISTICS
-+TEMPORARY_TABLES
-+THREAD_STATISTICS
- TRIGGERS
- USER_PRIVILEGES
-+USER_STATISTICS
- VIEWS
-+XTRADB_ADMIN_COMMAND
- show tables from INFORMATION_SCHEMA like 'T%';
- Tables_in_information_schema (T%)
- TABLES
- TABLESPACES
- TABLE_CONSTRAINTS
- TABLE_PRIVILEGES
-+TABLE_STATISTICS
-+TEMPORARY_TABLES
-+THREAD_STATISTICS
- TRIGGERS
- create database `inf%`;
- create database mbase;
-diff -ruN a/mysql-test/r/mysqld--help-notwin.result b/mysql-test/r/mysqld--help-notwin.result
---- a/mysql-test/r/mysqld--help-notwin.result 2011-01-20 00:37:09.000000000 +0200
-+++ b/mysql-test/r/mysqld--help-notwin.result 2011-02-18 13:14:44.701736864 +0200
-@@ -249,21 +249,43 @@
- --log-slow-admin-statements
- Log slow OPTIMIZE, ANALYZE, ALTER and other
- administrative statements to the slow log if it is open.
-+ --log-slow-filter=name
-+ Log only the queries that followed certain execution
-+ plan. Multiple flags allowed in a comma-separated string.
-+ [qc_miss, full_scan, full_join, tmp_table,
-+ tmp_table_on_disk, filesort, filesort_on_disk]
- --log-slow-queries[=name]
- Log slow queries to a table or log file. Defaults logging
- to table mysql.slow_log or hostname-slow.log if
- --log-output=file is used. Must be enabled to activate
- other slow log options. Deprecated option, use
- --slow-query-log/--slow-query-log-file instead.
-+ --log-slow-rate-limit=#
-+ Rate limit statement writes to slow log to only those
-+ from every (1/log_slow_rate_limit) session.
- --log-slow-slave-statements
-- Log slow statements executed by slave thread to the slow
-- log if it is open.
-+ Log queries replayed be the slave SQL thread
-+ --log-slow-sp-statements
-+ Log slow statements executed by stored procedure to the
-+ slow log if it is open.
-+ (Defaults to on; use --skip-log-slow-sp-statements to disable.)
-+ --log-slow-timestamp-every
-+ Timestamp is printed for all records of the slow log even
-+ if they are same time.
-+ --log-slow-verbosity=name
-+ Choose how verbose the messages to your slow log will be.
-+ Multiple flags allowed in a comma-separated string.
-+ [microtime, query_plan, innodb, profiling,
-+ profiling_use_getrusage]
- --log-tc=name Path to transaction coordinator log (used for
- transactions that affect more than one storage engine,
- when binary log is disabled).
- --log-tc-size=# Size of transaction coordinator log.
- -W, --log-warnings[=#]
- Log some not critical warnings to the log file
-+ --log-warnings-silence=name
-+ disable logging of enumerated warnings: 1592: unsafe
-+ statements for binary logging; possible values : [1592]
- --long-query-time=# Log all queries that have taken more than long_query_time
- seconds to execute to file. The argument will be treated
- as a decimal value with microsecond precision
-@@ -470,6 +492,10 @@
- The minimum size for blocks allocated by the query cache
- --query-cache-size=#
- The memory allocated to store results from old queries
-+ --query-cache-strip-comments
-+ Enable and disable optimisation "strip comment for query
-+ cache" - optimisation strip all comments from query while
-+ search query result in query cache
- --query-cache-type=name
- OFF = Don't cache or retrieve results. ON = Cache all
- results except SELECT SQL_NO_CACHE ... queries. DEMAND =
-@@ -478,6 +504,12 @@
- Invalidate queries in query cache on LOCK for write
- --query-prealloc-size=#
- Persistent buffer for query parsing and execution
-+ --query-response-time-range-base=#
-+ Select base of log for query_response_time ranges.
-+ WARNING: variable change affect only after flush
-+ --query-response-time-stats
-+ Enable or disable query response time statisics
-+ collecting
- --range-alloc-block-size=#
- Allocation block size for storing ranges during
- optimization
-@@ -655,6 +687,9 @@
- Log slow queries to given log file. Defaults logging to
- hostname-slow.log. Must be enabled to activate other slow
- log options
-+ --slow-query-log-microseconds-timestamp
-+ Log slow statements executed by stored procedure to the
-+ slow log if it is open.
- --socket=name Socket file to use for connection
- --sort-buffer-size=#
- Each thread that needs to do a sort allocates a buffer of
-@@ -697,6 +732,8 @@
- Define threads usage for handling queries, one of
- one-thread-per-connection, no-threads, loaded-dynamically
- --thread-stack=# The stack size for each thread
-+ --thread-statistics Control TABLE_STATISTICS running, when userstat_running
-+ is enabled
- --time-format=name The TIME format (ignored)
- --timed-mutexes Specify whether to time mutexes (only InnoDB mutexes are
- currently supported)
-@@ -721,11 +758,24 @@
- Prohibit update of a VIEW, which does not contain a key
- of the underlying table and the query uses a LIMIT clause
- (usually get from GUI tools)
-+ --use-global-log-slow-control=name
-+ Choose flags, wich always use the global variables.
-+ Multiple flags allowed in a comma-separated string.
-+ [none, log_slow_filter, log_slow_rate_limit,
-+ log_slow_verbosity, long_query_time,
-+ min_examined_row_limit, all]
- -u, --user=name Run mysqld daemon as user.
-+ --userstat-running Control USER_STATISTICS, CLIENT_STATISTICS,
-+ THREAD_STATISTICS, INDEX_STATISTICS and TABLE_STATISTICS
-+ running
- -v, --verbose Used with --help option for detailed help.
- -V, --version Output version information and exit.
- --wait-timeout=# The number of seconds the server waits for activity on a
- connection before closing it
-+ --xtradb-admin-command[=name]
-+ Enable or disable XTRADB_ADMIN_COMMAND plugin. Possible
-+ values are ON, OFF, FORCE (don't start if the plugin
-+ fails to load).
-
- Variables (--variable-name=value)
- abort-slave-event-count 0
-@@ -807,10 +857,16 @@
- log-short-format FALSE
- log-slave-updates FALSE
- log-slow-admin-statements FALSE
-+log-slow-filter
-+log-slow-rate-limit 1
- log-slow-slave-statements FALSE
-+log-slow-sp-statements TRUE
-+log-slow-timestamp-every FALSE
-+log-slow-verbosity
- log-tc tc.log
- log-tc-size 24576
- log-warnings 1
-+log-warnings-silence
- long-query-time 10
- low-priority-updates FALSE
- lower-case-table-names 1
-@@ -885,9 +941,12 @@
- query-cache-limit 1048576
- query-cache-min-res-unit 4096
- query-cache-size 0
-+query-cache-strip-comments FALSE
- query-cache-type ON
- query-cache-wlock-invalidate FALSE
- query-prealloc-size 8192
-+query-response-time-range-base 10
-+query-response-time-stats FALSE
- range-alloc-block-size 4096
- read-buffer-size 131072
- read-only FALSE
-@@ -922,6 +981,7 @@
- slave-type-conversions
- slow-launch-time 2
- slow-query-log FALSE
-+slow-query-log-microseconds-timestamp FALSE
- sort-buffer-size 2097152
- sporadic-binlog-dump-fail FALSE
- sql-mode
-@@ -939,6 +999,7 @@
- thread-cache-size 0
- thread-handling one-thread-per-connection
- thread-stack 262144
-+thread-statistics FALSE
- time-format %H:%i:%s
- timed-mutexes FALSE
- tmp-table-size 16777216
-@@ -946,8 +1007,11 @@
- transaction-isolation REPEATABLE-READ
- transaction-prealloc-size 4096
- updatable-views-with-limit YES
-+use-global-log-slow-control
-+userstat-running FALSE
- verbose TRUE
- wait-timeout 28800
-+xtradb-admin-command ON
-
- To see what values a running MySQL server is using, type
- 'mysqladmin variables' instead of 'mysqld --verbose --help'.
-diff -ruN a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
---- a/mysql-test/r/mysqldump.result 2010-11-03 07:01:12.000000000 +0900
-+++ b/mysql-test/r/mysqldump.result 2010-12-10 16:48:11.013968901 +0900
-@@ -1832,7 +1832,7 @@
- # Bug#21288 mysqldump segmentation fault when using --where
- #
- create table t1 (a int);
--mysqldump: Couldn't execute 'SELECT /*!40001 SQL_NO_CACHE */ * FROM `t1` WHERE xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx': You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' at line 1 (1064)
-+mysqldump: Couldn't execute 'SELECT /*!40001 SQL_NO_CACHE */ /*!50084 SQL_NO_FCACHE */ * FROM `t1` WHERE xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx': You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' at line 1 (1064)
- mysqldump: Got error: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' at line 1 when retrieving data from server
-
- /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
-diff -ruN a/mysql-test/r/mysqlshow.result b/mysql-test/r/mysqlshow.result
---- a/mysql-test/r/mysqlshow.result 2010-12-03 20:58:24.000000000 +0300
-+++ b/mysql-test/r/mysqlshow.result 2011-01-11 16:41:03.000000000 +0300
-@@ -80,14 +80,17 @@
- | Tables |
- +---------------------------------------+
- | CHARACTER_SETS |
-+| CLIENT_STATISTICS |
- | COLLATIONS |
- | COLLATION_CHARACTER_SET_APPLICABILITY |
- | COLUMNS |
- | COLUMN_PRIVILEGES |
-+| INDEX_STATISTICS |
- | ENGINES |
- | EVENTS |
- | FILES |
- | GLOBAL_STATUS |
-+| GLOBAL_TEMPORARY_TABLES |
- | GLOBAL_VARIABLES |
- | KEY_COLUMN_USAGE |
- | PARAMETERS |
-@@ -97,6 +100,7 @@
- | PROFILING |
- | REFERENTIAL_CONSTRAINTS |
- | ROUTINES |
-+| QUERY_RESPONSE_TIME |
- | SCHEMATA |
- | SCHEMA_PRIVILEGES |
- | SESSION_STATUS |
-@@ -106,30 +110,52 @@
- | TABLESPACES |
- | TABLE_CONSTRAINTS |
- | TABLE_PRIVILEGES |
-+| TABLE_STATISTICS |
-+| TEMPORARY_TABLES |
-+| THREAD_STATISTICS |
- | TRIGGERS |
- | USER_PRIVILEGES |
-+| USER_STATISTICS |
- | VIEWS |
--| INNODB_CMP_RESET |
-+| INNODB_SYS_COLUMNS |
-+| INNODB_RSEG |
-+| INNODB_CMP |
- | INNODB_TRX |
--| INNODB_CMPMEM_RESET |
-+| INNODB_SYS_TABLESTATS |
- | INNODB_LOCK_WAITS |
--| INNODB_CMPMEM |
--| INNODB_CMP |
-+| XTRADB_ADMIN_COMMAND |
- | INNODB_LOCKS |
-+| INNODB_SYS_FOREIGN_COLS |
-+| INNODB_CMP_RESET |
-+| INNODB_BUFFER_POOL_PAGES |
-+| INNODB_SYS_TABLES |
-+| INNODB_BUFFER_POOL_PAGES_INDEX |
-+| INNODB_CMPMEM |
-+| INNODB_BUFFER_POOL_PAGES_BLOB |
-+| INNODB_CMPMEM_RESET |
-+| INNODB_SYS_FIELDS |
-+| INNODB_TABLE_STATS |
-+| INNODB_SYS_STATS |
-+| INNODB_SYS_FOREIGN |
-+| INNODB_SYS_INDEXES |
-+| INNODB_INDEX_STATS |
- +---------------------------------------+
- Database: INFORMATION_SCHEMA
- +---------------------------------------+
- | Tables |
- +---------------------------------------+
- | CHARACTER_SETS |
-+| CLIENT_STATISTICS |
- | COLLATIONS |
- | COLLATION_CHARACTER_SET_APPLICABILITY |
- | COLUMNS |
- | COLUMN_PRIVILEGES |
-+| INDEX_STATISTICS |
- | ENGINES |
- | EVENTS |
- | FILES |
- | GLOBAL_STATUS |
-+| GLOBAL_TEMPORARY_TABLES |
- | GLOBAL_VARIABLES |
- | KEY_COLUMN_USAGE |
- | PARAMETERS |
-@@ -139,6 +165,7 @@
- | PROFILING |
- | REFERENTIAL_CONSTRAINTS |
- | ROUTINES |
-+| QUERY_RESPONSE_TIME |
- | SCHEMATA |
- | SCHEMA_PRIVILEGES |
- | SESSION_STATUS |
-@@ -148,16 +175,35 @@
- | TABLESPACES |
- | TABLE_CONSTRAINTS |
- | TABLE_PRIVILEGES |
-+| TABLE_STATISTICS |
-+| TEMPORARY_TABLES |
-+| THREAD_STATISTICS |
- | TRIGGERS |
- | USER_PRIVILEGES |
-+| USER_STATISTICS |
- | VIEWS |
--| INNODB_CMP_RESET |
-+| INNODB_SYS_COLUMNS |
-+| INNODB_RSEG |
-+| INNODB_CMP |
- | INNODB_TRX |
--| INNODB_CMPMEM_RESET |
-+| INNODB_SYS_TABLESTATS |
- | INNODB_LOCK_WAITS |
--| INNODB_CMPMEM |
--| INNODB_CMP |
-+| XTRADB_ADMIN_COMMAND |
- | INNODB_LOCKS |
-+| INNODB_SYS_FOREIGN_COLS |
-+| INNODB_CMP_RESET |
-+| INNODB_BUFFER_POOL_PAGES |
-+| INNODB_SYS_TABLES |
-+| INNODB_BUFFER_POOL_PAGES_INDEX |
-+| INNODB_CMPMEM |
-+| INNODB_BUFFER_POOL_PAGES_BLOB |
-+| INNODB_CMPMEM_RESET |
-+| INNODB_SYS_FIELDS |
-+| INNODB_TABLE_STATS |
-+| INNODB_SYS_STATS |
-+| INNODB_SYS_FOREIGN |
-+| INNODB_SYS_INDEXES |
-+| INNODB_INDEX_STATS |
- +---------------------------------------+
- Wildcard: inf_rmation_schema
- +--------------------+
-diff -ruN a/mysql-test/r/select.result b/mysql-test/r/select.result
---- a/mysql-test/r/select.result 2010-11-03 07:01:12.000000000 +0900
-+++ b/mysql-test/r/select.result 2010-12-10 16:48:11.023052909 +0900
-@@ -2196,10 +2196,10 @@
- select * from (t1 as t2 left join t1 as t3 using (a)) inner join t1 on t1.a>1;
- a a
- 1 2
--2 2
--3 2
- 1 3
-+2 2
- 2 3
-+3 2
- 3 3
- select * from t1 inner join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
- a a
-diff -ruN a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result
---- a/mysql-test/suite/innodb/r/innodb.result 2010-11-03 07:01:12.000000000 +0900
-+++ b/mysql-test/suite/innodb/r/innodb.result 2010-12-10 16:48:11.026994635 +0900
-@@ -1664,7 +1664,7 @@
- drop table t1;
- SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_buffer_pool_pages_total';
- variable_value
--511
-+2047
- SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_page_size';
- variable_value
- 16384
-diff -ruN a/mysql-test/suite/sys_vars/r/all_vars.result b/mysql-test/suite/sys_vars/r/all_vars.result
---- a/mysql-test/suite/sys_vars/r/all_vars.result 2011-01-20 00:37:09.000000000 +0200
-+++ b/mysql-test/suite/sys_vars/r/all_vars.result 2011-02-18 13:04:56.205855418 +0200
-@@ -11,7 +11,99 @@
- select variable_name as `There should be *no* variables listed below:` from t2
- left join t1 on variable_name=test_name where test_name is null;
- There should be *no* variables listed below:
-+QUERY_CACHE_STRIP_COMMENTS
-+LOG_SLOW_SP_STATEMENTS
-+INNODB_THREAD_CONCURRENCY_TIMER_BASED
-+LOG_SLOW_TIMESTAMP_EVERY
-+INNODB_LOG_BLOCK_SIZE
-+THREAD_STATISTICS
-+INNODB_READ_AHEAD
-+INNODB_USE_GLOBAL_FLUSH_LOG_AT_TRX_COMMIT
-+INNODB_PASS_CORRUPT_TABLE
-+QUERY_RESPONSE_TIME_STATS
-+INNODB_FLUSH_NEIGHBOR_PAGES
-+INNODB_BUFFER_POOL_SHM_CHECKSUM
-+LOG_SLOW_VERBOSITY
-+INNODB_SHOW_LOCKS_HELD
-+INNODB_IBUF_ACCEL_RATE
-+INNODB_EXPAND_IMPORT
-+INNODB_CHECKPOINT_AGE_TARGET
-+INNODB_ADAPTIVE_FLUSHING_METHOD
-+INNODB_STATS_METHOD
-+HAVE_RESPONSE_TIME_DISTRIBUTION
-+LOG_SLOW_RATE_LIMIT
-+OPTIMIZER_FIX
-+INNODB_PAGE_SIZE
-+FAST_INDEX_CREATION
-+USE_GLOBAL_LOG_SLOW_CONTROL
-+INNODB_IBUF_MAX_SIZE
-+INNODB_ADAPTIVE_HASH_INDEX_PARTITIONS
-+SLOW_QUERY_LOG_MICROSECONDS_TIMESTAMP
-+INNODB_BUFFER_POOL_SHM_KEY
-+INNODB_FAST_CHECKSUM
-+INNODB_USE_SYS_STATS_TABLE
-+INNODB_STATS_UPDATE_NEED_LOCK
-+INNODB_RECOVERY_STATS
-+USERSTAT_RUNNING
-+QUERY_RESPONSE_TIME_RANGE_BASE
-+INNODB_IBUF_ACTIVE_CONTRACT
-+INNODB_AUTO_LRU_DUMP
-+INNODB_DOUBLEWRITE_FILE
-+INNODB_STATS_AUTO_UPDATE
-+INNODB_DICT_SIZE_LIMIT
- INNODB_FILE_FORMAT_MAX
-+LOG_WARNINGS_SILENCE
-+LOG_SLOW_FILTER
-+INNODB_SHOW_VERBOSE_LOCKS
-+INNODB_EXTRA_RSEGMENTS
-+INNODB_OVERWRITE_RELAY_LOG_INFO
-+LOG_SLOW_SLAVE_STATEMENTS
-+QUERY_CACHE_STRIP_COMMENTS
-+LOG_SLOW_SP_STATEMENTS
-+INNODB_THREAD_CONCURRENCY_TIMER_BASED
-+LOG_SLOW_TIMESTAMP_EVERY
-+INNODB_LOG_BLOCK_SIZE
-+THREAD_STATISTICS
-+INNODB_READ_AHEAD
-+INNODB_USE_GLOBAL_FLUSH_LOG_AT_TRX_COMMIT
-+INNODB_PASS_CORRUPT_TABLE
-+QUERY_RESPONSE_TIME_STATS
-+INNODB_FLUSH_NEIGHBOR_PAGES
-+INNODB_BUFFER_POOL_SHM_CHECKSUM
-+LOG_SLOW_VERBOSITY
-+INNODB_SHOW_LOCKS_HELD
-+INNODB_IBUF_ACCEL_RATE
-+INNODB_EXPAND_IMPORT
-+INNODB_CHECKPOINT_AGE_TARGET
-+INNODB_ADAPTIVE_FLUSHING_METHOD
-+INNODB_STATS_METHOD
-+HAVE_RESPONSE_TIME_DISTRIBUTION
-+LOG_SLOW_RATE_LIMIT
-+OPTIMIZER_FIX
-+INNODB_PAGE_SIZE
-+FAST_INDEX_CREATION
-+USE_GLOBAL_LOG_SLOW_CONTROL
-+INNODB_IBUF_MAX_SIZE
-+INNODB_ADAPTIVE_HASH_INDEX_PARTITIONS
-+SLOW_QUERY_LOG_MICROSECONDS_TIMESTAMP
-+INNODB_BUFFER_POOL_SHM_KEY
-+INNODB_FAST_CHECKSUM
-+INNODB_USE_SYS_STATS_TABLE
-+INNODB_STATS_UPDATE_NEED_LOCK
-+INNODB_RECOVERY_STATS
-+USERSTAT_RUNNING
-+QUERY_RESPONSE_TIME_RANGE_BASE
-+INNODB_IBUF_ACTIVE_CONTRACT
-+INNODB_AUTO_LRU_DUMP
-+INNODB_DOUBLEWRITE_FILE
-+INNODB_STATS_AUTO_UPDATE
-+INNODB_DICT_SIZE_LIMIT
- INNODB_FILE_FORMAT_MAX
-+LOG_WARNINGS_SILENCE
-+LOG_SLOW_FILTER
-+INNODB_SHOW_VERBOSE_LOCKS
-+INNODB_EXTRA_RSEGMENTS
-+INNODB_OVERWRITE_RELAY_LOG_INFO
-+LOG_SLOW_SLAVE_STATEMENTS
- drop table t1;
- drop table t2;
-diff -ruN a/mysql-test/suite/sys_vars/r/innodb_adaptive_flushing_basic.result b/mysql-test/suite/sys_vars/r/innodb_adaptive_flushing_basic.result
---- a/mysql-test/suite/sys_vars/r/innodb_adaptive_flushing_basic.result 2010-11-03 07:01:13.000000000 +0900
-+++ b/mysql-test/suite/sys_vars/r/innodb_adaptive_flushing_basic.result 2010-12-10 16:48:11.031065741 +0900
-@@ -1,28 +1,28 @@
- SET @start_global_value = @@global.innodb_adaptive_flushing;
- SELECT @start_global_value;
- @start_global_value
--1
-+0
- Valid values are 'ON' and 'OFF'
- select @@global.innodb_adaptive_flushing in (0, 1);
- @@global.innodb_adaptive_flushing in (0, 1)
- 1
- select @@global.innodb_adaptive_flushing;
- @@global.innodb_adaptive_flushing
--1
-+0
- select @@session.innodb_adaptive_flushing;
- ERROR HY000: Variable 'innodb_adaptive_flushing' is a GLOBAL variable
- show global variables like 'innodb_adaptive_flushing';
- Variable_name Value
--innodb_adaptive_flushing ON
-+innodb_adaptive_flushing OFF
- show session variables like 'innodb_adaptive_flushing';
- Variable_name Value
--innodb_adaptive_flushing ON
-+innodb_adaptive_flushing OFF
- select * from information_schema.global_variables where variable_name='innodb_adaptive_flushing';
- VARIABLE_NAME VARIABLE_VALUE
--INNODB_ADAPTIVE_FLUSHING ON
-+INNODB_ADAPTIVE_FLUSHING OFF
- select * from information_schema.session_variables where variable_name='innodb_adaptive_flushing';
- VARIABLE_NAME VARIABLE_VALUE
--INNODB_ADAPTIVE_FLUSHING ON
-+INNODB_ADAPTIVE_FLUSHING OFF
- set global innodb_adaptive_flushing='OFF';
- select @@global.innodb_adaptive_flushing;
- @@global.innodb_adaptive_flushing
-@@ -89,4 +89,4 @@
- SET @@global.innodb_adaptive_flushing = @start_global_value;
- SELECT @@global.innodb_adaptive_flushing;
- @@global.innodb_adaptive_flushing
--1
-+0
-diff -ruN a/mysql-test/suite/sys_vars/r/plugin_dir_basic.result b/mysql-test/suite/sys_vars/r/plugin_dir_basic.result
---- a/mysql-test/suite/sys_vars/r/plugin_dir_basic.result 2010-11-03 07:01:13.000000000 +0900
-+++ b/mysql-test/suite/sys_vars/r/plugin_dir_basic.result 2010-12-10 16:48:11.033057415 +0900
-@@ -1,20 +1,20 @@
- select @@global.plugin_dir;
- @@global.plugin_dir
--MYSQL_LIBDIR/plugin
-+MYSQL_LIBDIR64/plugin
- select @@session.plugin_dir;
- ERROR HY000: Variable 'plugin_dir' is a GLOBAL variable
- show global variables like 'plugin_dir';
- Variable_name Value
--plugin_dir MYSQL_LIBDIR/plugin
-+plugin_dir MYSQL_LIBDIR64/plugin
- show session variables like 'plugin_dir';
- Variable_name Value
--plugin_dir MYSQL_LIBDIR/plugin
-+plugin_dir MYSQL_LIBDIR64/plugin
- select * from information_schema.global_variables where variable_name='plugin_dir';
- VARIABLE_NAME VARIABLE_VALUE
--PLUGIN_DIR MYSQL_LIBDIR/plugin
-+PLUGIN_DIR MYSQL_LIBDIR64/plugin
- select * from information_schema.session_variables where variable_name='plugin_dir';
- VARIABLE_NAME VARIABLE_VALUE
--PLUGIN_DIR MYSQL_LIBDIR/plugin
-+PLUGIN_DIR MYSQL_LIBDIR64/plugin
- set global plugin_dir=1;
- ERROR HY000: Variable 'plugin_dir' is a read only variable
- set session plugin_dir=1;
-diff -ruN a/mysql-test/t/connect.test b/mysql-test/t/connect.test
---- a/mysql-test/t/connect.test 2010-11-03 07:01:12.000000000 +0900
-+++ b/mysql-test/t/connect.test 2010-12-10 16:48:11.034065111 +0900
-@@ -1,3 +1,5 @@
-+set global log_warnings=0;
-+
- # This test is to check various cases of connections
- # with right and wrong password, with and without database
- # Unfortunately the check is incomplete as we can't connect without database
-@@ -300,3 +302,4 @@
- # Wait till all disconnects are completed
- --source include/wait_until_count_sessions.inc
-
-+set global log_warnings=1;
# TODO:
-# - make response_time_distribution.patch compatible with i386 alpha sparc ppc arches
# - mysqldump ... (invalid usage) prints to stdout not stderr (idiotic if you want to create dump and get usage in .sql)
# - http://bugs.mysql.com/bug.php?id=16470
# - innodb are dynamic (= as plugins) ?
+++ /dev/null
-# name : mysql_dump_ignore_ct.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
-diff -ruN a/client/client_priv.h b/client/client_priv.h
---- a/client/client_priv.h 2010-11-03 07:01:14.000000000 +0900
-+++ b/client/client_priv.h 2010-12-03 13:39:32.317046060 +0900
-@@ -58,6 +58,7 @@
- OPT_MYSQL_LOCK_DIRECTORY,
- OPT_USE_THREADS,
- OPT_IMPORT_USE_THREADS,
-+ OPT_IGNORE_CREATE_ERROR,
- OPT_MYSQL_NUMBER_OF_QUERY,
- OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
- OPT_TZ_UTC, OPT_CREATE_SLAP_SCHEMA,
---- mysql-5.5.9/client/mysqldump.c~ 2011-03-10 20:05:49.000000000 +0200
-+++ mysql-5.5.9/client/mysqldump.c 2011-03-10 20:19:55.962339580 +0200
-@@ -101,7 +101,7 @@
- opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1,
- opt_slave_apply= 0,
- opt_include_master_host_port= 0,
-- opt_events= 0, opt_comments_used= 0,
-+ opt_events= 0, opt_comments_used= 0, opt_ignore_show_create_table_error=0,
- opt_alltspcs=0, opt_notspcs= 0;
- static my_bool insert_pat_inited= 0, debug_info_flag= 0, debug_check_flag= 0;
- static ulong opt_max_allowed_packet, opt_net_buffer_length;
-@@ -350,6 +350,9 @@
- {"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
- &opt_ignore, &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
- 0, 0},
-+ {"ignore-create-error", OPT_IGNORE_CREATE_ERROR, "Don't exit on show create table errors.",
-+ (uchar**) &opt_ignore_show_create_table_error, (uchar**) &opt_ignore_show_create_table_error, 0, GET_BOOL,
-+ NO_ARG, 0, 0, 0, 0, 0, 0},
- {"lines-terminated-by", OPT_LTB,
- "Lines in the output file are terminated by the given string.",
- &lines_terminated, &lines_terminated, 0, GET_STR,
-@@ -2297,21 +2297,35 @@
- char buff[20+FN_REFLEN];
- MYSQL_FIELD *field;
-
-+ my_bool old_ignore_errors=ignore_errors;
-+ //fprintf(stderr, "ignore create table %d\n", opt_ignore_show_create_table_error);
-+ if (opt_ignore_show_create_table_error)
-+ ignore_errors=1;
-+
- my_snprintf(buff, sizeof(buff), "show create table %s", result_table);
-
- if (opt_set_charset) /* Was forced to false if server is too old. */
- {
- if (switch_character_set_results(mysql, "binary") != 0)
-+ {
-+ ignore_errors=old_ignore_errors;
- DBUG_RETURN(0);
-+ }
- }
-
- if (mysql_query_with_error_report(mysql, &result, buff) != 0)
-+ {
-+ ignore_errors=old_ignore_errors;
- DBUG_RETURN(0);
-+ }
-
- if (opt_set_charset) /* Was forced to false if server is too old. */
- {
- if (switch_character_set_results(mysql, default_charset) != 0)
-+ {
-+ ignore_errors=old_ignore_errors;
- DBUG_RETURN(0);
-+ }
- }
-
- if (path)
+++ /dev/null
-# name : mysql_remove_eol_carret.patch
-# introduced : 11 or before
-# maintainer : Oleg
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/client/client_priv.h
-+++ b/client/client_priv.h
-@@ -89,6 +89,7 @@
- OPT_SYSLOG,
- #endif
- OPT_PLUGIN_DIR,
-+ OPT_NO_REMOVE_EOL_CARRET,
- OPT_DEFAULT_AUTH,
- OPT_DEFAULT_PLUGIN,
- OPT_MAX_CLIENT_OPTION
---- a/client/mysql.cc
-+++ b/client/mysql.cc
-@@ -135,6 +135,8 @@
- enum enum_info_type { INFO_INFO,INFO_ERROR,INFO_RESULT};
- typedef enum enum_info_type INFO_TYPE;
-
-+my_bool opt_no_remove_eol_carret=0;
-+
- static MYSQL mysql; /* The connection */
- static my_bool ignore_errors=0,wait_flag=0,quick=0,
- connected=0,opt_raw_data=0,unbuffered=0,output_tables=0,
-@@ -1454,6 +1456,10 @@
- NO_ARG, 1, 0, 0, 0, 0, 0},
- {"skip-line-numbers", 'L', "Don't write line number for errors.", 0, 0, 0, GET_NO_ARG,
- NO_ARG, 0, 0, 0, 0, 0, 0},
-+ {"no-remove-eol-carret", OPT_NO_REMOVE_EOL_CARRET, "Do not remove \\r before \\n in batch mode",
-+ (uchar**)&opt_no_remove_eol_carret , (uchar**)&opt_no_remove_eol_carret, 0,
-+ GET_BOOL,
-+ NO_ARG, 0, 0, 0, 0, 0, 0},
- {"unbuffered", 'n', "Flush buffer after each query.", &unbuffered,
- &unbuffered, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"column-names", OPT_COLUMN_NAMES, "Write column names in results.",
---- a/client/readline.cc
-+++ b/client/readline.cc
-@@ -23,6 +23,8 @@
- #include <my_dir.h>
- #include "my_readline.h"
-
-+extern my_bool opt_no_remove_eol_carret;
-+
- static bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,
- ulong max_size);
- static bool init_line_buffer_from_string(LINE_BUFFER *buffer,char * str);
-@@ -62,7 +64,7 @@
- if (!(pos=intern_read_line(line_buff, &out_length)))
- return 0;
- if (out_length && pos[out_length-1] == '\n')
-- if (--out_length && pos[out_length-1] == '\r') /* Remove '\n' */
-+ if (--out_length && !opt_no_remove_eol_carret && pos[out_length-1] == '\r') /* Remove '\n' */
- out_length--; /* Remove '\r' */
- line_buff->read_length=out_length;
- pos[out_length]=0;
---- /dev/null
-+++ b/patch_info/mysql_remove_eol_carret.patch
-@@ -0,0 +1,7 @@
-+File=mysql_remove_eol_carret.patch
-+Name=
-+Version=1.1
-+Author=Percona <info@percona.com>
-+License=GPL
-+Comment=Do not remove carret before eol if --no-remove-eol-carret is enabled in MySQL client.
-+Changelog
+++ /dev/null
-# name : mysql-syslog.patch
-# introduced : 12
-# maintainer : Oleg
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/client/client_priv.h
-+++ b/client/client_priv.h
-@@ -85,6 +85,9 @@
- OPT_DEBUG_INFO, OPT_DEBUG_CHECK, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE,
- OPT_WRITE_BINLOG, OPT_DUMP_DATE,
- OPT_INIT_COMMAND,
-+#ifndef __WIN__
-+ OPT_SYSLOG,
-+#endif
- OPT_PLUGIN_DIR,
- OPT_DEFAULT_AUTH,
- OPT_DEFAULT_PLUGIN,
---- a/client/mysql.cc
-+++ b/client/mysql.cc
-@@ -40,6 +40,11 @@
- #include "my_readline.h"
- #include <signal.h>
- #include <violite.h>
-+#ifndef __WIN__
-+#include "syslog.h"
-+#endif
-+
-+#define MAX_SYSLOG_MESSAGE 900
-
- #if defined(USE_LIBEDIT_INTERFACE) && defined(HAVE_LOCALE_H)
- #include <locale.h>
-@@ -142,7 +147,7 @@
- default_pager_set= 0, opt_sigint_ignore= 0,
- auto_vertical_output= 0,
- show_warnings= 0, executing_query= 0, interrupted_query= 0,
-- ignore_spaces= 0;
-+ ignore_spaces= 0, opt_syslog= 0;
- static my_bool debug_info_flag, debug_check_flag;
- static my_bool column_types_flag;
- static my_bool preserve_comments= 0;
-@@ -200,6 +205,7 @@
- void tee_fputs(const char *s, FILE *file);
- void tee_puts(const char *s, FILE *file);
- void tee_putc(int c, FILE *file);
-+void write_syslog(String *buffer);
- static void tee_print_sized_data(const char *, unsigned int, unsigned int, bool);
- /* The names of functions that actually do the manipulation. */
- static int get_options(int argc,char **argv);
-@@ -1565,6 +1571,10 @@
- {"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.",
- &show_warnings, &show_warnings, 0, GET_BOOL, NO_ARG,
- 0, 0, 0, 0, 0, 0},
-+#ifndef __WIN__
-+ {"syslog", OPT_SYSLOG, "Logs all queries to syslog", 0, 0, 0, GET_NO_ARG,
-+ NO_ARG, 0, 0, 0, 0, 0, 0},
-+#endif
- {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
- &opt_plugin_dir, &opt_plugin_dir, 0,
- GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-@@ -1669,6 +1679,11 @@
- opt->name);
- #endif
- break;
-+#ifndef __WIN__
-+ case OPT_SYSLOG:
-+ opt_syslog = 1;
-+ break;
-+#endif
- case OPT_SERVER_ARG:
- #ifdef EMBEDDED_LIBRARY
- /*
-@@ -2022,6 +2037,40 @@
- DBUG_RETURN((COMMANDS *) 0);
- }
-
-+void write_syslog(String *line){
-+#ifndef __WIN__
-+ uint length= line->length();
-+ uint chunk_len= min(MAX_SYSLOG_MESSAGE, length);
-+ char *ptr= line->c_ptr_safe();
-+ char buff[MAX_SYSLOG_MESSAGE + 1];
-+
-+ for (;
-+ length;
-+ length-= chunk_len, ptr+= chunk_len, chunk_len= min(MAX_SYSLOG_MESSAGE,
-+ length))
-+ {
-+ char *str;
-+ if (length == chunk_len)
-+ str= ptr; // last chunk => skip copy
-+ else
-+ {
-+ memcpy(buff, ptr, chunk_len);
-+ buff[chunk_len]= '\0';
-+ str= buff;
-+ }
-+ syslog(LOG_INFO,
-+ "SYSTEM_USER:'%s', MYSQL_USER:'%s', CONNECTION_ID:%lu, "
-+ "DB_SERVER:'%s', DB:'%s', QUERY:'%s'",
-+ getenv("SUDO_USER") ? getenv("SUDO_USER") :
-+ getenv("USER") ? getenv("USER") : "--",
-+ current_user ? current_user : "--",
-+ mysql_thread_id(&mysql),
-+ current_host ? current_host : "--",
-+ current_db ? current_db : "--",
-+ str);
-+ }
-+#endif
-+}
-
- static bool add_line(String &buffer,char *line,char *in_string,
- bool *ml_comment, bool truncated)
-@@ -2998,6 +3047,11 @@
- fix_history(buffer);
- }
- #endif
-+#ifndef __WIN__
-+ if (opt_syslog && buffer->length() && connect_flag == CLIENT_INTERACTIVE){
-+ write_syslog(buffer);
-+ }
-+#endif
-
- buffer->length(0);
-
+++ /dev/null
-# name : optimizer_fix.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- /dev/null
-+++ b/patch_info/optimizer_fix.info
-@@ -0,0 +1,8 @@
-+File=optimizer_fix.patch
-+Name=Unofficial optimizer fixes
-+Version=1.0
-+Author=Percona <info@percona.com>
-+License=GPL
-+Comment=
-+2010-01
-+Ported to 5.1.42
---- a/sql/mysqld.cc
-+++ b/sql/mysqld.cc
-@@ -434,6 +434,7 @@
- MYSQL_PLUGIN_IMPORT uint opt_debug_sync_timeout= 0;
- #endif /* defined(ENABLED_DEBUG_SYNC) */
- my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
-+my_bool opt_optimizer_fix= 0;
- /*
- True if there is at least one per-hour limit for some user, so we should
- check them before each query (and possibly reset counters when hour is
---- a/sql/mysqld.h
-+++ b/sql/mysqld.h
-@@ -109,6 +109,7 @@
- extern ulonglong slave_type_conversions_options;
- extern my_bool read_only, opt_readonly;
- extern my_bool lower_case_file_system;
-+extern my_bool opt_optimizer_fix;
- extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
- extern my_bool opt_secure_auth;
- extern char* opt_secure_file_priv;
---- a/sql/opt_range.cc
-+++ b/sql/opt_range.cc
-@@ -727,7 +727,7 @@
- static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
- bool index_read_must_be_used,
- bool update_tbl_stats,
-- double read_time);
-+ double read_time, ha_rows *estimated_records);
- static
- TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
- double read_time,
-@@ -2151,6 +2151,7 @@
- ha_rows limit, bool force_quick_range)
- {
- uint idx;
-+ ha_rows estimated_records=0;
- double scan_time;
- DBUG_ENTER("SQL_SELECT::test_quick_select");
- DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu",
-@@ -2319,12 +2320,17 @@
-
- /* Get best 'range' plan and prepare data for making other plans */
- if ((range_trp= get_key_scans_params(¶m, tree, FALSE, TRUE,
-- best_read_time)))
-+ best_read_time, &estimated_records)))
- {
- best_trp= range_trp;
- best_read_time= best_trp->read_cost;
- }
-
-+ if (opt_optimizer_fix && estimated_records)
-+ {
-+ records = estimated_records;
-+ }
-+
- /*
- Simultaneous key scans and row deletes on several handler
- objects are not allowed so don't use ROR-intersection for
-@@ -3820,7 +3826,7 @@
- {
- DBUG_EXECUTE("info", print_sel_tree(param, *ptree, &(*ptree)->keys_map,
- "tree in SEL_IMERGE"););
-- if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE, read_time)))
-+ if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE, read_time, NULL)))
- {
- /*
- One of index scans in this index_merge is more expensive than entire
-@@ -4923,11 +4929,12 @@
- static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
- bool index_read_must_be_used,
- bool update_tbl_stats,
-- double read_time)
-+ double read_time, ha_rows *estimated_records)
- {
- int idx;
- SEL_ARG **key,**end, **key_to_read= NULL;
- ha_rows UNINIT_VAR(best_records); /* protected by key_to_read */
-+ ha_rows min_records= HA_POS_ERROR;
- TRP_RANGE* read_plan= NULL;
- bool pk_is_clustered= param->table->file->primary_key_is_clustered();
- DBUG_ENTER("get_key_scans_params");
-@@ -4998,6 +5005,11 @@
- key_to_read= key;
- }
-
-+ if (estimated_records && found_records
-+ && min_records > found_records)
-+ {
-+ min_records = found_records;
-+ }
- }
- }
-
-@@ -5020,6 +5032,12 @@
- else
- DBUG_PRINT("info", ("No 'range' table read plan found"));
-
-+ /* minimum number of records (not 0) as estimated number of records */
-+ if (estimated_records && min_records != HA_POS_ERROR)
-+ {
-+ *estimated_records = min_records;
-+ }
-+
- DBUG_RETURN(read_plan);
- }
-
---- a/sql/sql_select.cc
-+++ b/sql/sql_select.cc
-@@ -2619,6 +2619,11 @@
- table->reginfo.impossible_range=1;
- DBUG_RETURN(0);
- }
-+ if (opt_optimizer_fix && error == 0)
-+ {
-+ /* quick select is not effective. but the estimated value is used. */
-+ DBUG_RETURN(select->records);
-+ }
- DBUG_PRINT("warning",("Couldn't use record count on const keypart"));
- }
- DBUG_RETURN(HA_POS_ERROR); /* This shouldn't happend */
---- a/sql/sys_vars.cc
-+++ b/sql/sys_vars.cc
-@@ -2259,6 +2259,12 @@
- VALID_RANGE(1, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT)),
- DEFAULT(NET_WAIT_TIMEOUT), BLOCK_SIZE(1));
-
-+static Sys_var_mybool Sys_optimizer_fix(
-+ "optimizer_fix",
-+ "Enable unofficial optimizer fixes.",
-+ GLOBAL_VAR(opt_optimizer_fix),
-+ NO_CMD_LINE, DEFAULT(TRUE));
-+
- /** propagates changes to the relevant flag of @@optimizer_switch */
- static bool fix_engine_condition_pushdown(sys_var *self, THD *thd,
- enum_var_type type)
+++ /dev/null
-#!/bin/sh
-# updates percona patches
-# http://www.percona.com/docs/wiki/repositories:start
-# http://bazaar.launchpad.net/~percona-dev/percona-server/5.5.8/files
-# https://launchpad.net/percona-server/5.5
-# bzr branch lp:percona-server/5.5
-
-version=5.5
-bzr_branch=lp:percona-server/$version
-#version=5.5.9
-#bzr_branch=lp:percona-dev/percona-server/$version
-branch=
-
-filter_names() {
- grep -v 'percona-support.patch' | \
- grep -v 'mysqld_safe_syslog.patch' | \
- grep -v 'mysql-test.diff'
-}
-
-filter_files() {
- filterdiff -x '*/configure'
-}
-
-set -e
-
-if [ -d $version ]; then
- cd $version
- bzr pull
- cd ..
-else
- bzr branch $bzr_branch $version
-fi
-
-> .percona.spec
-> .patch.spec
-i=100
-[ -d "$version/patches" ] && dir=$version/patches || dir=$version
-for patch in $(cat $dir/series | filter_names); do
- # if patch already existed, use mysql- prefix
- if [ -f mysql-$patch ]; then
- file=mysql-$patch
- else
- file=$patch
- fi
- cat $dir/$patch | filter_files > $file
-
- if [ -z "$(awk -vfile=$file -F/ '$2 == file{print}' CVS/Entries)" ]; then
- cvs add $file
- ${branch:+cvs up -r $branch $file}
- fi
-
- if [ "$patch" != "$file" ]; then
- echo >&2 "Adding: $file ($patch)"
- else
- echo >&2 "Adding: $file"
- fi
- printf "Patch%d:\t%s\n" $i $(echo "$file" | sed -e 's,^mysql-,%{name}-,') >> .percona.spec
- printf "%%patch%d -p1\n" $i >> .patch.spec
- i=$((i+1))
-done
-
-# update PatchX section
-sed -i -e '
-/^# <percona patches/,/^# <\/percona>/ {
- /^ <\/percona>/b
- /^# <percona patches/ {
- p # print header
- r .percona.spec
- a# </percona>
- }
- d
-}
-' mysql.spec
-
-# update %patchX section
-sed -i -e '
-/^# <percona %patches/,/^# <\/percona>/ {
- /^ <\/percona>/b
- /^# <percona %patches/ {
- p # print header
- r .patch.spec
- a# </percona>
- }
- d
-}
-' mysql.spec
+++ /dev/null
-# name : percona-support.patch
-# introduced : 11 or before
-# maintainer : Oleg
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/scripts/mysql_install_db.sh
-+++ b/scripts/mysql_install_db.sh
-@@ -481,6 +481,9 @@
- echo
- echo "Please report any problems with the $scriptdir/mysqlbug script!"
- echo
-+ echo "Percona recommends that all production deployments be protected with a support"
-+ echo "contract (http://www.percona.com/mysql-suppport/) to ensure the highest uptime,"
-+ echo "be eligible for hot fixes, and boost your team's productivity."
- fi
-
- exit 0
+++ /dev/null
-# name : processlist_row_stats.patch
-# introduced : 11 or before
-# maintainer : Oleg
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/sql/sql_class.cc
-+++ b/sql/sql_class.cc
-@@ -2424,6 +2424,7 @@
-
- thd->sent_row_count++;
- thd->sent_row_count_2++;
-+ DEBUG_SYNC(thd, "sent_row");
-
- if (thd->vio_ok())
- DBUG_RETURN(protocol->write());
---- a/sql/sql_show.cc
-+++ b/sql/sql_show.cc
-@@ -1766,7 +1766,8 @@
-
- /****************************************************************************
- Return info about all processes
-- returns for each thread: thread id, user, host, db, command, info
-+ returns for each thread: thread id, user, host, db, command, info,
-+ rows_sent, rows_examined, rows_read
- ****************************************************************************/
-
- class thread_info :public ilink {
-@@ -1784,6 +1785,7 @@
- uint command;
- const char *user,*host,*db,*proc_info,*state_info;
- CSET_STRING query_string;
-+ ulonglong rows_sent, rows_examined, rows_read;
- };
-
- #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
-@@ -1836,6 +1838,15 @@
- field->maybe_null=1;
- field_list.push_back(field=new Item_empty_string("Info",max_query_length));
- field->maybe_null=1;
-+ field_list.push_back(field= new Item_return_int("Rows_sent",
-+ MY_INT64_NUM_DECIMAL_DIGITS,
-+ MYSQL_TYPE_LONGLONG));
-+ field_list.push_back(field= new Item_return_int("Rows_examined",
-+ MY_INT64_NUM_DECIMAL_DIGITS,
-+ MYSQL_TYPE_LONGLONG));
-+ field_list.push_back(field= new Item_return_int("Rows_read",
-+ MY_INT64_NUM_DECIMAL_DIGITS,
-+ MYSQL_TYPE_LONGLONG));
- if (protocol->send_result_set_metadata(&field_list,
- Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_VOID_RETURN;
-@@ -1889,6 +1900,9 @@
- thd_info->query_string=
- CSET_STRING(q, q ? length : 0, tmp->query_charset());
- }
-+ thd_info->rows_sent= tmp->sent_row_count;
-+ thd_info->rows_examined= tmp->examined_row_count;
-+ thd_info->rows_read= tmp->warning_info->current_row_for_warning();
- mysql_mutex_unlock(&tmp->LOCK_thd_data);
- thd_info->start_time= tmp->start_time;
- thread_infos.append(thd_info);
-@@ -1917,6 +1931,9 @@
- protocol->store(thd_info->state_info, system_charset_info);
- protocol->store(thd_info->query_string.str(),
- thd_info->query_string.charset());
-+ protocol->store(thd_info->rows_sent);
-+ protocol->store(thd_info->rows_examined);
-+ protocol->store(thd_info->rows_read);
- if (protocol->write())
- break; /* purecov: inspected */
- }
-@@ -2027,6 +2044,15 @@
- table->field[8]->store(((tmp->start_utime ?
- now_utime - tmp->start_utime : 0)/ 1000));
-
-+ mysql_mutex_lock(&tmp->LOCK_thd_data);
-+ /* ROWS_SENT */
-+ table->field[9]->store((ulonglong) tmp->sent_row_count);
-+ /* ROWS_EXAMINED */
-+ table->field[10]->store((ulonglong) tmp->examined_row_count);
-+ /* ROWS_READ */
-+ table->field[11]->store((ulonglong) tmp->warning_info->current_row_for_warning());
-+ mysql_mutex_unlock(&tmp->LOCK_thd_data);
-+
- if (schema_table_store_record(thd, table))
- {
- mysql_mutex_unlock(&LOCK_thread_count);
-@@ -8140,6 +8166,12 @@
- SKIP_OPEN_TABLE},
- {"TIME_MS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG,
- 0, 0, "Time_ms", SKIP_OPEN_TABLE},
-+ {"ROWS_SENT", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
-+ MY_I_S_UNSIGNED, "Rows_sent", SKIP_OPEN_TABLE},
-+ {"ROWS_EXAMINED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
-+ MY_I_S_UNSIGNED, "Rows_examined", SKIP_OPEN_TABLE},
-+ {"ROWS_READ", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
-+ MY_I_S_UNSIGNED, "Rows_read", SKIP_OPEN_TABLE},
- {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
- };
-
---- /dev/null
-+++ b/mysql-test/include/percona_processlist_row_stats_show.inc
-@@ -0,0 +1,7 @@
-+--replace_column 1 ### 3 ### 6 ### 7 ###
-+SHOW PROCESSLIST;
-+
-+--replace_column 1 ###
-+SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id;
-+
-+SET DEBUG_SYNC= 'now SIGNAL threads_dumped';
---- /dev/null
-+++ b/mysql-test/r/percona_processlist_row_stats.result
-@@ -0,0 +1,70 @@
-+DROP TABLE IF EXISTS t1;
-+DROP TABLE IF EXISTS t2;
-+CREATE TABLE t2 (a INT);
-+INSERT INTO t2 VALUES(10);
-+INSERT INTO t2 VALUES(10);
-+INSERT INTO t2 VALUES(20);
-+INSERT INTO t2 VALUES(10);
-+INSERT INTO t2 VALUES(20);
-+SET DEBUG_SYNC= 'locked_table_name SIGNAL thread1_ready WAIT_FOR threads_dumped';
-+CREATE TABLE t1 (a INT);
-+SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready';
-+SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread2_ready WAIT_FOR threads_dumped';
-+SELECT a FROM t2 WHERE a > 15;
-+SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready';
-+SHOW PROCESSLIST;
-+Id User Host db Command Time State Info Rows_sent Rows_examined Rows_read
-+### root ### test Query ### ### SHOW PROCESSLIST 0 0 2
-+### root ### test Query ### ### CREATE TABLE t1 (a INT) 0 0 1
-+### root ### test Query ### ### SELECT a FROM t2 WHERE a > 15 2 5 6
-+SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id;
-+id info rows_sent rows_examined rows_read
-+### SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id 0 0 1
-+### CREATE TABLE t1 (a INT) 0 0 1
-+### SELECT a FROM t2 WHERE a > 15 2 5 6
-+SET DEBUG_SYNC= 'now SIGNAL threads_dumped';
-+a
-+20
-+20
-+SET DEBUG_SYNC= 'sent_row SIGNAL thread1_ready WAIT_FOR threads_dumped';
-+SELECT a FROM t2 WHERE a < 15;
-+SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready';
-+SET DEBUG_SYNC= 'sent_row SIGNAL thread2_ready WAIT_FOR threads_dumped';
-+SELECT a FROM t2 WHERE a > 15;
-+SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready';
-+SHOW PROCESSLIST;
-+Id User Host db Command Time State Info Rows_sent Rows_examined Rows_read
-+### root ### test Query ### ### SHOW PROCESSLIST 0 0 4
-+### root ### test Query ### ### SELECT a FROM t2 WHERE a < 15 1 0 1
-+### root ### test Query ### ### SELECT a FROM t2 WHERE a > 15 1 0 3
-+SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id;
-+id info rows_sent rows_examined rows_read
-+### SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id 0 0 1
-+### SELECT a FROM t2 WHERE a < 15 1 0 1
-+### SELECT a FROM t2 WHERE a > 15 1 0 3
-+SET DEBUG_SYNC= 'now SIGNAL threads_dumped';
-+a
-+10
-+10
-+10
-+a
-+20
-+20
-+SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread1_ready WAIT_FOR threads_dumped';
-+UPDATE t2 SET a = 15 WHERE a = 20;
-+SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready';
-+SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread2_ready WAIT_FOR threads_dumped';
-+UPDATE t2 SET a = 15 WHERE a = 10;
-+SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready';
-+SHOW PROCESSLIST;
-+Id User Host db Command Time State Info Rows_sent Rows_examined Rows_read
-+### root ### test Query ### ### SHOW PROCESSLIST 0 0 4
-+### root ### test Query ### ### UPDATE t2 SET a = 15 WHERE a = 20 0 5 6
-+### root ### test Query ### ### UPDATE t2 SET a = 15 WHERE a = 10 0 5 6
-+SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id;
-+id info rows_sent rows_examined rows_read
-+### SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id 0 0 1
-+### UPDATE t2 SET a = 15 WHERE a = 20 0 5 6
-+### UPDATE t2 SET a = 15 WHERE a = 10 0 5 6
-+SET DEBUG_SYNC= 'now SIGNAL threads_dumped';
-+DROP TABLES t1, t2;
---- /dev/null
-+++ b/mysql-test/t/percona_processlist_row_stats.test
-@@ -0,0 +1,79 @@
-+# Testing of INFORMATION_SCHEMA.PROCESSLIST fields ROWS_SENT, ROWS_EXAMINED, ROWS_READ
-+--source include/have_debug_sync.inc
-+
-+--disable_warnings
-+DROP TABLE IF EXISTS t1;
-+DROP TABLE IF EXISTS t2;
-+--enable_warnings
-+
-+CREATE TABLE t2 (a INT);
-+INSERT INTO t2 VALUES(10);
-+INSERT INTO t2 VALUES(10);
-+INSERT INTO t2 VALUES(20);
-+INSERT INTO t2 VALUES(10);
-+INSERT INTO t2 VALUES(20);
-+
-+--connect (conn1, localhost, root, ,)
-+--connect (conn2, localhost, root, ,)
-+
-+--connection conn1
-+SET DEBUG_SYNC= 'locked_table_name SIGNAL thread1_ready WAIT_FOR threads_dumped';
-+send CREATE TABLE t1 (a INT);
-+--connection default
-+SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready';
-+
-+--connection conn2
-+SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread2_ready WAIT_FOR threads_dumped';
-+send SELECT a FROM t2 WHERE a > 15;
-+--connection default
-+SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready';
-+
-+--source include/percona_processlist_row_stats_show.inc
-+
-+--connection conn1
-+reap;
-+--connection conn2
-+reap;
-+
-+--connection conn1
-+SET DEBUG_SYNC= 'sent_row SIGNAL thread1_ready WAIT_FOR threads_dumped';
-+send SELECT a FROM t2 WHERE a < 15;
-+--connection default
-+SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready';
-+
-+--connection conn2
-+SET DEBUG_SYNC= 'sent_row SIGNAL thread2_ready WAIT_FOR threads_dumped';
-+send SELECT a FROM t2 WHERE a > 15;
-+--connection default
-+SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready';
-+
-+--source include/percona_processlist_row_stats_show.inc
-+
-+--connection conn1
-+reap;
-+--connection conn2
-+reap;
-+
-+--connection conn1
-+SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread1_ready WAIT_FOR threads_dumped';
-+send UPDATE t2 SET a = 15 WHERE a = 20;
-+--connection default
-+SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready';
-+
-+--connection conn2
-+SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread2_ready WAIT_FOR threads_dumped';
-+send UPDATE t2 SET a = 15 WHERE a = 10;
-+--connection default
-+SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready';
-+
-+--source include/percona_processlist_row_stats_show.inc
-+
-+--connection conn1
-+reap;
-+--connection conn2
-+reap;
-+
-+--connection default
-+disconnect conn1;
-+disconnect conn2;
-+DROP TABLES t1, t2;
+++ /dev/null
-# name : query_cache_with_comments.patch
-# introduced : 11 or before
-# maintainer : Oleg
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- /dev/null
-+++ b/patch_info/query_cache_enhance.patch
-@@ -0,0 +1,15 @@
-+File=query_cache_enhance.patch
-+Name= query cache Percona's cumulative patch
-+Version=1.0
-+Author=Percona <info@percona.com>
-+License=GPL
-+Comment= 1) Add new status - Waiting on query cache mutex (status_wait_query_cache_mutex.patch)
-+ 2) Remove comments from query (need for cache hit) (query_cache_with_comments.patch)
-+ 3) Totally disable query cache (query_cache_totally_disable.info)
-+2010-05 - First version avaliable (query_cache_with_comments.patch)
-+2010-07 - First version avaliable (status_wait_query_cache_mutex.patch
-+2010-07 - First version avaliable (query_cache_totally_disable.info)
-+2010-07 - Fix crash (query_cache_with_comments.patch)
-+2010-07 - Fix incorrect behavior diff (query_cache_with_comments.patch)
-+2010-09 - Merge patches to one
-+2010-11 - Ported to 5.5
---- a/sql/mysqld.cc
-+++ b/sql/mysqld.cc
-@@ -915,6 +915,7 @@
- #endif
- #ifdef HAVE_QUERY_CACHE
- ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE;
-+my_bool opt_query_cache_strip_comments= FALSE;
- Query_cache query_cache;
- #endif
- #ifdef HAVE_SMEM
---- a/sql/mysqld.h
-+++ b/sql/mysqld.h
-@@ -91,6 +91,7 @@
- extern my_bool opt_log, opt_slow_log;
- extern my_bool opt_backup_history_log;
- extern my_bool opt_backup_progress_log;
-+extern my_bool opt_query_cache_strip_comments;
- extern ulonglong log_output_options;
- extern ulong log_backup_output_options;
- extern my_bool opt_log_queries_not_using_indexes;
---- /dev/null
-+++ b/sql/query_strip_comments.h
-@@ -0,0 +1,37 @@
-+#ifndef _SQL_QUERY_STRIPC_COMMENTS_H_
-+#define _SQL_QUERY_STRIPC_COMMENTS_H_
-+#ifdef HAVE_QUERY_CACHE
-+
-+// implemented in sql_cache.cc
-+class QueryStripComments
-+{
-+private:
-+ QueryStripComments(const QueryStripComments&);
-+ QueryStripComments& operator=(const QueryStripComments&);
-+public:
-+ QueryStripComments();
-+ ~QueryStripComments();
-+ void set(const char* a_query, uint a_query_length, uint a_additional_length);
-+
-+ char* query() { return buffer; }
-+ uint query_length() { return length; }
-+private:
-+ void cleanup();
-+private:
-+ char* buffer;
-+ uint length /*query length, not buffer length*/;
-+ uint buffer_length;
-+};
-+class QueryStripComments_Backup
-+{
-+public:
-+ QueryStripComments_Backup(THD* a_thd,QueryStripComments* qsc);
-+ ~QueryStripComments_Backup();
-+private:
-+ THD* thd;
-+ char* query;
-+ uint length;
-+};
-+
-+#endif // HAVE_QUERY_CACHE
-+#endif // _SQL_QUERY_STRIPC_COMMENTS_H_
---- a/sql/sql_cache.cc
-+++ b/sql/sql_cache.cc
-@@ -344,6 +344,198 @@
- #include "probes_mysql.h"
- #include "transaction.h"
-
-+#include "query_strip_comments.h"
-+
-+/*
-+ Number of bytes to be allocated in a query cache buffer in addition to the
-+ query string length.
-+
-+ The query buffer layout is:
-+
-+ buffer :==
-+ <statement> The input statement(s)
-+ '\0' Terminating null char
-+ <db_length> Length of following current database name (size_t)
-+ <db_name> Name of current database
-+ <flags> Flags struct
-+*/
-+#define QUERY_BUFFER_ADDITIONAL_LENGTH(db_length) \
-+ (1 + sizeof(size_t) + db_length + QUERY_CACHE_FLAGS_SIZE)
-+
-+QueryStripComments::QueryStripComments()
-+{
-+ buffer = 0;
-+ length = 0;
-+ buffer_length = 0;
-+}
-+QueryStripComments::~QueryStripComments()
-+{
-+ cleanup();
-+}
-+
-+inline bool query_strip_comments_is_white_space(char c)
-+{
-+ return ((' ' == c) || ('\t' == c) || ('\r' == c) || ('\n' ==c ));
-+}
-+void QueryStripComments::set(const char* query, uint query_length, uint additional_length)
-+{
-+ uint new_buffer_length = query_length + additional_length;
-+ if(new_buffer_length > buffer_length)
-+ {
-+ cleanup();
-+ buffer = (char*)my_malloc(new_buffer_length,MYF(0));
-+ }
-+ uint query_position = 0;
-+ uint position = 0;
-+ // Skip whitespaces from begin
-+ while((query_position < query_length) && query_strip_comments_is_white_space(query[query_position]))
-+ {
-+ ++query_position;
-+ }
-+ long int last_space = -1;
-+ while(query_position < query_length)
-+ {
-+ char current = query[query_position];
-+ bool insert_space = false; // insert space to buffer, (IMPORTANT) don't update query_position
-+ switch(current)
-+ {
-+ case '\'':
-+ case '"':
-+ {
-+ buffer[position++] = query[query_position++]; // copy current symbol
-+ while(query_position < query_length)
-+ {
-+ if(current == query[query_position]) // found pair quote
-+ {
-+ break;
-+ }
-+ buffer[position++] = query[query_position++]; // copy current symbol
-+ }
-+ break;
-+ }
-+ case '/':
-+ {
-+ if(((query_position + 2) < query_length) && ('*' == query[query_position+1]) && ('!' != query[query_position+2]))
-+ {
-+ query_position += 2; // skip "/*"
-+ do
-+ {
-+ if('*' == query[query_position] && '/' == query[query_position+1]) // check for "*/"
-+ {
-+ query_position += 2; // skip "*/"
-+ insert_space = true;
-+ break;
-+ }
-+ else
-+ {
-+ ++query_position;
-+ }
-+ }
-+ while(query_position < query_length);
-+ if(!insert_space)
-+ {
-+ continue;
-+ }
-+ }
-+ break;
-+ }
-+ case '-':
-+ {
-+ if(query[query_position+1] == '-')
-+ {
-+ ++query_position; // skip "-", and go to search of "\n"
-+ }
-+ else
-+ {
-+ break;
-+ }
-+ }
-+ case '#':
-+ {
-+ do
-+ {
-+ ++query_position; // skip current symbol (# or -)
-+ if('\n' == query[query_position]) // check for '\n'
-+ {
-+ ++query_position; // skip '\n'
-+ insert_space = true;
-+ break;
-+ }
-+ }
-+ while(query_position < query_length);
-+ if(insert_space)
-+ {
-+ break;
-+ }
-+ else
-+ {
-+ continue;
-+ }
-+ }
-+ default:
-+ if(query_strip_comments_is_white_space(current))
-+ {
-+ insert_space = true;
-+ ++query_position;
-+ }
-+ break; // make gcc happy
-+ }
-+ if(insert_space)
-+ {
-+ if((uint) (last_space + 1) != position)
-+ {
-+ last_space = position;
-+ buffer[position++] = ' ';
-+ }
-+ }
-+ else if (query_position < query_length)
-+ {
-+ buffer[position++] = query[query_position++];
-+ }
-+ }
-+ while((0 < position) && query_strip_comments_is_white_space(buffer[position - 1]))
-+ {
-+ --position;
-+ }
-+ buffer[position] = 0;
-+ length = position;
-+}
-+void QueryStripComments::cleanup()
-+{
-+ if(buffer)
-+ {
-+ my_free(buffer);
-+ }
-+ buffer = 0;
-+ length = 0;
-+ buffer_length = 0;
-+}
-+QueryStripComments_Backup::QueryStripComments_Backup(THD* a_thd,QueryStripComments* qsc)
-+{
-+ if(opt_query_cache_strip_comments)
-+ {
-+ thd = a_thd;
-+ query = thd->query();
-+ length = thd->query_length();
-+ qsc->set(query, length, QUERY_BUFFER_ADDITIONAL_LENGTH(thd->db_length));
-+ *(size_t *) (qsc->query() + qsc->query_length() + 1)= thd->db_length;
-+ thd->set_query(qsc->query(),qsc->query_length());
-+ }
-+ else
-+ {
-+ thd = 0;
-+ query = 0;
-+ length = 0;
-+ }
-+}
-+QueryStripComments_Backup::~QueryStripComments_Backup()
-+{
-+ if(thd)
-+ {
-+ thd->set_query(query,length);
-+ }
-+}
-+
- #ifdef EMBEDDED_LIBRARY
- #include "emb_qcache.h"
- #endif
-@@ -454,7 +646,12 @@
- Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
- DBUG_ENTER("Query_cache::try_lock");
-
-+ const char* old_proc_info= thd->proc_info;
-+ thd_proc_info(thd,"Waiting on query cache mutex");
-+ DEBUG_SYNC(thd, "before_query_cache_mutex");
- mysql_mutex_lock(&structure_guard_mutex);
-+ DEBUG_SYNC(thd, "after_query_cache_mutex");
-+ thd->proc_info = old_proc_info;
- while (1)
- {
- if (m_cache_lock_status == Query_cache::UNLOCKED)
-@@ -1274,6 +1471,8 @@
- unlock();
- DBUG_VOID_RETURN;
- }
-+ QueryStripComments *query_strip_comments = &(thd->query_strip_comments);
-+ QueryStripComments_Backup backup(thd,query_strip_comments);
-
- /* Key is query + database + flag */
- if (thd->db_length)
-@@ -1451,6 +1650,9 @@
- Query_cache_block_table *block_table, *block_table_end;
- ulong tot_length;
- Query_cache_query_flags flags;
-+ QueryStripComments *query_strip_comments = &(thd->query_strip_comments);
-+ char *sql_backup = sql;
-+ uint query_length_backup = query_length;
- DBUG_ENTER("Query_cache::send_result_to_client");
-
- /*
-@@ -1472,21 +1674,103 @@
-
- {
- uint i= 0;
-- /*
-- Skip '(' characters in queries like following:
-- (select a from t1) union (select a from t1);
-- */
-- while (sql[i]=='(')
-- i++;
-+ if(opt_query_cache_strip_comments)
-+ {
-+ /* Skip all comments and non-letter symbols */
-+ uint& query_position = i;
-+ char* query = sql;
-+ while(query_position < query_length)
-+ {
-+ bool check = false;
-+ char current = query[query_position];
-+ switch(current)
-+ {
-+ case '/':
-+ if(((query_position + 2) < query_length) && ('*' == query[query_position+1]) && ('!' != query[query_position+2]))
-+ {
-+ query_position += 2; // skip "/*"
-+ do
-+ {
-+ if('*' == query[query_position] && '/' == query[query_position+1]) // check for "*/" (without space)
-+ {
-+ query_position += 2; // skip "*/" (without space)
-+ break;
-+ }
-+ else
-+ {
-+ ++query_position;
-+ }
-+ }
-+ while(query_position < query_length);
-+ continue; // analyze current symbol
-+ }
-+ break;
-+ case '-':
-+ if(query[query_position+1] == '-')
-+ {
-+ ++query_position; // skip "-"
-+ }
-+ else
-+ {
-+ break;
-+ }
-+ case '#':
-+ do
-+ {
-+ ++query_position; // skip current symbol
-+ if('\n' == query[query_position]) // check for '\n'
-+ {
-+ ++query_position; // skip '\n'
-+ break;
-+ }
-+ }
-+ while(query_position < query_length);
-+ continue; // analyze current symbol
-+ case '\r':
-+ case '\n':
-+ case '\t':
-+ case ' ':
-+ case '(':
-+ case ')':
-+ break;
-+ default:
-+ check = true;
-+ break; // make gcc happy
-+ } // switch(current)
-+ if(check)
-+ {
-+ if(query_position + 2 < query_length)
-+ {
-+ // cacheable
-+ break;
-+ }
-+ else
-+ {
-+ DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
-+ goto err;
-+ }
-+ } // if(check)
-+ ++query_position;
-+ } // while(query_position < query_length)
-+ }
-+ else // if(opt_query_cache_strip_comments)
-+ {
-+ /*
-+ Skip '(' characters in queries like following:
-+ (select a from t1) union (select a from t1);
-+ */
-+ while (sql[i]=='(')
-+ i++;
-
-- /*
-- Test if the query is a SELECT
-- (pre-space is removed in dispatch_command).
-+ } // if(opt_query_cache_strip_comments)
-+ /*
-+ Test if the query is a SELECT
-+ (pre-space is removed in dispatch_command).
-
-- First '/' looks like comment before command it is not
-- frequently appeared in real life, consequently we can
-- check all such queries, too.
-- */
-+ First '/' looks like comment before command it is not
-+ frequently appeared in real life, consequently we can
-+ check all such queries, too.
-+ */
- if ((my_toupper(system_charset_info, sql[i]) != 'S' ||
- my_toupper(system_charset_info, sql[i + 1]) != 'E' ||
- my_toupper(system_charset_info, sql[i + 2]) != 'L') &&
-@@ -1543,6 +1827,14 @@
- goto err_unlock;
-
- Query_cache_block *query_block;
-+ if(opt_query_cache_strip_comments)
-+ {
-+ query_strip_comments->set(sql, query_length,
-+ QUERY_BUFFER_ADDITIONAL_LENGTH(thd->db_length));
-+ sql = query_strip_comments->query();
-+ query_length = query_strip_comments->query_length();
-+ *(size_t *) (sql + query_length + 1)= thd->db_length;
-+ }
-
- tot_length= query_length + 1 + sizeof(size_t) +
- thd->db_length + QUERY_CACHE_FLAGS_SIZE;
-@@ -1611,6 +1903,8 @@
- (uchar*) &flags, QUERY_CACHE_FLAGS_SIZE);
- query_block = (Query_cache_block *) my_hash_search(&queries, (uchar*) sql,
- tot_length);
-+ sql = sql_backup;
-+ query_length = query_length_backup;
- /* Quick abort on unlocked data */
- if (query_block == 0 ||
- query_block->query()->result() == 0 ||
---- a/sql/sql_class.h
-+++ b/sql/sql_class.h
-@@ -40,6 +40,9 @@
- #include "thr_lock.h" /* thr_lock_type, THR_LOCK_DATA,
- THR_LOCK_INFO */
-
-+#ifdef HAVE_QUERY_CACHE
-+#include "query_strip_comments.h"
-+#endif // HAVE_QUERY_CACHE
-
- class Reprepare_observer;
- class Relay_log_info;
-@@ -766,6 +769,9 @@
- statement lifetime. FIXME: must be const
- */
- ulong id;
-+#ifdef HAVE_QUERY_CACHE
-+ QueryStripComments query_strip_comments; // see sql_cache.cc
-+#endif //HAVE_QUERY_CACHE
-
- /*
- MARK_COLUMNS_NONE: Means mark_used_colums is not set and no indicator to
---- a/sql/sys_vars.cc
-+++ b/sql/sys_vars.cc
-@@ -1895,6 +1895,11 @@
- NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
- ON_UPDATE(fix_query_cache_size));
-
-+static Sys_var_mybool Sys_query_cache_strip_comments(
-+ "query_cache_strip_comments", "Enable and disable optimisation \"strip comment for query cache\" - optimisation strip all comments from query while search query result in query cache",
-+ GLOBAL_VAR(opt_query_cache_strip_comments), CMD_LINE(OPT_ARG),
-+ DEFAULT(FALSE));
-+
- static Sys_var_ulong Sys_query_cache_limit(
- "query_cache_limit",
- "Don't cache results that are bigger than this",
---- /dev/null
-+++ b/mysql-test/include/percona_query_cache_with_comments.inc
-@@ -0,0 +1,95 @@
-+--source include/percona_query_cache_with_comments_clear.inc
-+let $query=/* with comment first */select * from t1;
-+eval $query;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=# with comment first
-+select * from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=-- with comment first
-+select * from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=/* with comment first and "quote" */select * from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=# with comment first and "quote"
-+select * from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=-- with comment first and "quote"
-+select * from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=
-+ /* with comment and whitespaces first */select * from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=
-+ # with comment and whitespaces first
-+select * from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=
-+ -- with comment and whitespaces first
-+select * from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $internal=* internal comment *;
-+
-+let $query=select * /$internal/ from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+let $query=select */$internal/ from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+let $query=select */$internal/from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $internal=* internal comment with "quote" *;
-+
-+let $query=select * /$internal/ from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+let $query=select */$internal/ from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+let $query=select */$internal/from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select * from t1
-+;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select * from t1 ;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select * from t1 ;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select * from t1
-+/* comment in the end */;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select * from t1
-+/* *\/ */;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select * from t1
-+/* comment in the end */
-+;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select * from t1 #comment in the end;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select * from t1 #comment in the end
-+;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select * from t1 -- comment in the end;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select * from t1 -- comment in the end
-+;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select ' \' ' from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
---- /dev/null
-+++ b/mysql-test/include/percona_query_cache_with_comments_begin.inc
-@@ -0,0 +1,12 @@
-+-- source include/have_query_cache.inc
-+
-+set GLOBAL query_cache_size=1355776;
-+
-+--disable_warnings
-+drop table if exists t1;
-+--enable_warnings
-+
-+create table t1 (a int not null);
-+insert into t1 values (1),(2),(3);
-+
-+--source include/percona_query_cache_with_comments_clear.inc
---- /dev/null
-+++ b/mysql-test/include/percona_query_cache_with_comments_clear.inc
-@@ -0,0 +1,5 @@
-+# Reset query cache variables.
-+flush query cache; # This crashed in some versions
-+flush query cache; # This crashed in some versions
-+reset query cache;
-+flush status;
---- /dev/null
-+++ b/mysql-test/include/percona_query_cache_with_comments_end.inc
-@@ -0,0 +1,3 @@
-+DROP TABLE t1;
-+SET GLOBAL query_cache_size=default;
-+set global query_cache_strip_comments=OFF;
---- /dev/null
-+++ b/mysql-test/include/percona_query_cache_with_comments_eval.inc
-@@ -0,0 +1,7 @@
-+echo -----------------------------------------------------;
-+echo $query;
-+echo -----------------------------------------------------;
-+--source include/percona_query_cache_with_comments_show.inc
-+eval $query;
-+eval $query;
-+--source include/percona_query_cache_with_comments_show.inc
---- /dev/null
-+++ b/mysql-test/include/percona_query_cache_with_comments_show.inc
-@@ -0,0 +1,8 @@
-+let $show=show status like "Qcache_queries_in_cache";
-+eval $show;
-+let $show=show status like "Qcache_inserts";
-+eval $show;
-+let $show=show status like "Qcache_hits";
-+eval $show;
-+
-+
---- /dev/null
-+++ b/mysql-test/r/percona_query_cache_with_comments.result
-@@ -0,0 +1,866 @@
-+set global query_cache_strip_comments=ON;
-+set GLOBAL query_cache_size=1355776;
-+drop table if exists t1;
-+create table t1 (a int not null);
-+insert into t1 values (1),(2),(3);
-+flush query cache;
-+flush query cache;
-+reset query cache;
-+flush status;
-+flush query cache;
-+flush query cache;
-+reset query cache;
-+flush status;
-+/* with comment first */select * from t1;
-+a
-+1
-+2
-+3
-+-----------------------------------------------------
-+/* with comment first */select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 0
-+/* with comment first */select * from t1;
-+a
-+1
-+2
-+3
-+/* with comment first */select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 2
-+-----------------------------------------------------
-+# with comment first
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 2
-+# with comment first
-+select * from t1;
-+a
-+1
-+2
-+3
-+# with comment first
-+select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 4
-+-----------------------------------------------------
-+-- with comment first
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 4
-+-- with comment first
-+select * from t1;
-+a
-+1
-+2
-+3
-+-- with comment first
-+select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 6
-+-----------------------------------------------------
-+/* with comment first and "quote" */select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 6
-+/* with comment first and "quote" */select * from t1;
-+a
-+1
-+2
-+3
-+/* with comment first and "quote" */select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 8
-+-----------------------------------------------------
-+# with comment first and "quote"
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 8
-+# with comment first and "quote"
-+select * from t1;
-+a
-+1
-+2
-+3
-+# with comment first and "quote"
-+select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 10
-+-----------------------------------------------------
-+-- with comment first and "quote"
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 10
-+-- with comment first and "quote"
-+select * from t1;
-+a
-+1
-+2
-+3
-+-- with comment first and "quote"
-+select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 12
-+-----------------------------------------------------
-+/* with comment and whitespaces first */select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 12
-+/* with comment and whitespaces first */select * from t1;
-+a
-+1
-+2
-+3
-+/* with comment and whitespaces first */select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 14
-+-----------------------------------------------------
-+# with comment and whitespaces first
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 14
-+# with comment and whitespaces first
-+select * from t1;
-+a
-+1
-+2
-+3
-+# with comment and whitespaces first
-+select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 16
-+-----------------------------------------------------
-+-- with comment and whitespaces first
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 16
-+-- with comment and whitespaces first
-+select * from t1;
-+a
-+1
-+2
-+3
-+-- with comment and whitespaces first
-+select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 18
-+-----------------------------------------------------
-+select * /* internal comment */ from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 18
-+select * /* internal comment */ from t1;
-+a
-+1
-+2
-+3
-+select * /* internal comment */ from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 20
-+-----------------------------------------------------
-+select */* internal comment */ from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 20
-+select */* internal comment */ from t1;
-+a
-+1
-+2
-+3
-+select */* internal comment */ from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 22
-+-----------------------------------------------------
-+select */* internal comment */from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 22
-+select */* internal comment */from t1;
-+a
-+1
-+2
-+3
-+select */* internal comment */from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 24
-+-----------------------------------------------------
-+select * /* internal comment with "quote" */ from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 24
-+select * /* internal comment with "quote" */ from t1;
-+a
-+1
-+2
-+3
-+select * /* internal comment with "quote" */ from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 26
-+-----------------------------------------------------
-+select */* internal comment with "quote" */ from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 26
-+select */* internal comment with "quote" */ from t1;
-+a
-+1
-+2
-+3
-+select */* internal comment with "quote" */ from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 28
-+-----------------------------------------------------
-+select */* internal comment with "quote" */from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 28
-+select */* internal comment with "quote" */from t1;
-+a
-+1
-+2
-+3
-+select */* internal comment with "quote" */from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 30
-+-----------------------------------------------------
-+select * from t1
-+
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 30
-+select * from t1
-+;
-+a
-+1
-+2
-+3
-+select * from t1
-+;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 32
-+-----------------------------------------------------
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 32
-+select * from t1 ;
-+a
-+1
-+2
-+3
-+select * from t1 ;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 34
-+-----------------------------------------------------
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 34
-+select * from t1 ;
-+a
-+1
-+2
-+3
-+select * from t1 ;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 36
-+-----------------------------------------------------
-+select * from t1
-+/* comment in the end */
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 36
-+select * from t1
-+/* comment in the end */;
-+a
-+1
-+2
-+3
-+select * from t1
-+/* comment in the end */;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 38
-+-----------------------------------------------------
-+select * from t1
-+/* *\/ */
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 38
-+select * from t1
-+/* *\/ */;
-+a
-+1
-+2
-+3
-+select * from t1
-+/* *\/ */;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 40
-+-----------------------------------------------------
-+select * from t1
-+/* comment in the end */
-+
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 40
-+select * from t1
-+/* comment in the end */
-+;
-+a
-+1
-+2
-+3
-+select * from t1
-+/* comment in the end */
-+;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 42
-+-----------------------------------------------------
-+select * from t1 #comment in the end
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 42
-+select * from t1 #comment in the end;
-+a
-+1
-+2
-+3
-+select * from t1 #comment in the end;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 44
-+-----------------------------------------------------
-+select * from t1 #comment in the end
-+
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 44
-+select * from t1 #comment in the end
-+;
-+a
-+1
-+2
-+3
-+select * from t1 #comment in the end
-+;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 46
-+-----------------------------------------------------
-+select * from t1 -- comment in the end
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 46
-+select * from t1 -- comment in the end;
-+a
-+1
-+2
-+3
-+select * from t1 -- comment in the end;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 48
-+-----------------------------------------------------
-+select * from t1 -- comment in the end
-+
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 48
-+select * from t1 -- comment in the end
-+;
-+a
-+1
-+2
-+3
-+select * from t1 -- comment in the end
-+;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 50
-+-----------------------------------------------------
-+select ' \' ' from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 50
-+select ' \' ' from t1;
-+'
-+ '
-+ '
-+ '
-+select ' \' ' from t1;
-+'
-+ '
-+ '
-+ '
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 2
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 2
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 51
-+DROP TABLE t1;
-+SET GLOBAL query_cache_size=default;
-+set global query_cache_strip_comments=OFF;
---- /dev/null
-+++ b/mysql-test/r/percona_query_cache_with_comments_crash.result
-@@ -0,0 +1,21 @@
-+set GLOBAL query_cache_size=1355776;
-+drop table if exists t1;
-+create table t1 (a int not null);
-+insert into t1 values (1),(2),(3);
-+flush query cache;
-+flush query cache;
-+reset query cache;
-+flush status;
-+( select * from t1 );
-+a
-+1
-+2
-+3
-+/*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, @@SQL_MODE := REPLACE(REPLACE(@@SQL_MODE, 'ANSI_QUOTES', ''), ',,', ','), @OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, @@SQL_QUOTE_SHOW_CREATE := 1 */;
-+/* only comment */;
-+# only comment
-+;
-+-- only comment
-+;
-+DROP TABLE t1;
-+SET GLOBAL query_cache_size= default;
---- /dev/null
-+++ b/mysql-test/r/percona_query_cache_with_comments_disable.result
-@@ -0,0 +1,865 @@
-+set GLOBAL query_cache_size=1355776;
-+drop table if exists t1;
-+create table t1 (a int not null);
-+insert into t1 values (1),(2),(3);
-+flush query cache;
-+flush query cache;
-+reset query cache;
-+flush status;
-+flush query cache;
-+flush query cache;
-+reset query cache;
-+flush status;
-+/* with comment first */select * from t1;
-+a
-+1
-+2
-+3
-+-----------------------------------------------------
-+/* with comment first */select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 0
-+/* with comment first */select * from t1;
-+a
-+1
-+2
-+3
-+/* with comment first */select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 2
-+-----------------------------------------------------
-+# with comment first
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 2
-+# with comment first
-+select * from t1;
-+a
-+1
-+2
-+3
-+# with comment first
-+select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 2
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 2
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 2
-+-----------------------------------------------------
-+-- with comment first
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 2
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 2
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 2
-+-- with comment first
-+select * from t1;
-+a
-+1
-+2
-+3
-+-- with comment first
-+select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 3
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 3
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 2
-+-----------------------------------------------------
-+/* with comment first and "quote" */select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 3
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 3
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 2
-+/* with comment first and "quote" */select * from t1;
-+a
-+1
-+2
-+3
-+/* with comment first and "quote" */select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 4
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 4
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 3
-+-----------------------------------------------------
-+# with comment first and "quote"
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 4
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 4
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 3
-+# with comment first and "quote"
-+select * from t1;
-+a
-+1
-+2
-+3
-+# with comment first and "quote"
-+select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 5
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 5
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 3
-+-----------------------------------------------------
-+-- with comment first and "quote"
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 5
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 5
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 3
-+-- with comment first and "quote"
-+select * from t1;
-+a
-+1
-+2
-+3
-+-- with comment first and "quote"
-+select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 6
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 6
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 3
-+-----------------------------------------------------
-+/* with comment and whitespaces first */select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 6
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 6
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 3
-+/* with comment and whitespaces first */select * from t1;
-+a
-+1
-+2
-+3
-+/* with comment and whitespaces first */select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 7
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 7
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 4
-+-----------------------------------------------------
-+# with comment and whitespaces first
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 7
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 7
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 4
-+# with comment and whitespaces first
-+select * from t1;
-+a
-+1
-+2
-+3
-+# with comment and whitespaces first
-+select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 8
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 8
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 4
-+-----------------------------------------------------
-+-- with comment and whitespaces first
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 8
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 8
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 4
-+-- with comment and whitespaces first
-+select * from t1;
-+a
-+1
-+2
-+3
-+-- with comment and whitespaces first
-+select * from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 9
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 9
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 4
-+-----------------------------------------------------
-+select * /* internal comment */ from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 9
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 9
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 4
-+select * /* internal comment */ from t1;
-+a
-+1
-+2
-+3
-+select * /* internal comment */ from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 10
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 10
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 5
-+-----------------------------------------------------
-+select */* internal comment */ from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 10
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 10
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 5
-+select */* internal comment */ from t1;
-+a
-+1
-+2
-+3
-+select */* internal comment */ from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 11
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 11
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 6
-+-----------------------------------------------------
-+select */* internal comment */from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 11
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 11
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 6
-+select */* internal comment */from t1;
-+a
-+1
-+2
-+3
-+select */* internal comment */from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 12
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 12
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 7
-+-----------------------------------------------------
-+select * /* internal comment with "quote" */ from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 12
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 12
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 7
-+select * /* internal comment with "quote" */ from t1;
-+a
-+1
-+2
-+3
-+select * /* internal comment with "quote" */ from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 13
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 13
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 8
-+-----------------------------------------------------
-+select */* internal comment with "quote" */ from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 13
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 13
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 8
-+select */* internal comment with "quote" */ from t1;
-+a
-+1
-+2
-+3
-+select */* internal comment with "quote" */ from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 14
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 14
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 9
-+-----------------------------------------------------
-+select */* internal comment with "quote" */from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 14
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 14
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 9
-+select */* internal comment with "quote" */from t1;
-+a
-+1
-+2
-+3
-+select */* internal comment with "quote" */from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 15
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 15
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 10
-+-----------------------------------------------------
-+select * from t1
-+
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 15
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 15
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 10
-+select * from t1
-+;
-+a
-+1
-+2
-+3
-+select * from t1
-+;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 16
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 16
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 11
-+-----------------------------------------------------
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 16
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 16
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 11
-+select * from t1 ;
-+a
-+1
-+2
-+3
-+select * from t1 ;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 16
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 16
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 13
-+-----------------------------------------------------
-+select * from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 16
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 16
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 13
-+select * from t1 ;
-+a
-+1
-+2
-+3
-+select * from t1 ;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 16
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 16
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 15
-+-----------------------------------------------------
-+select * from t1
-+/* comment in the end */
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 16
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 16
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 15
-+select * from t1
-+/* comment in the end */;
-+a
-+1
-+2
-+3
-+select * from t1
-+/* comment in the end */;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 17
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 17
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 16
-+-----------------------------------------------------
-+select * from t1
-+/* *\/ */
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 17
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 17
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 16
-+select * from t1
-+/* *\/ */;
-+a
-+1
-+2
-+3
-+select * from t1
-+/* *\/ */;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 18
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 18
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 17
-+-----------------------------------------------------
-+select * from t1
-+/* comment in the end */
-+
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 18
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 18
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 17
-+select * from t1
-+/* comment in the end */
-+;
-+a
-+1
-+2
-+3
-+select * from t1
-+/* comment in the end */
-+;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 18
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 18
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 19
-+-----------------------------------------------------
-+select * from t1 #comment in the end
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 18
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 18
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 19
-+select * from t1 #comment in the end;
-+a
-+1
-+2
-+3
-+select * from t1 #comment in the end;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 19
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 19
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 20
-+-----------------------------------------------------
-+select * from t1 #comment in the end
-+
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 19
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 19
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 20
-+select * from t1 #comment in the end
-+;
-+a
-+1
-+2
-+3
-+select * from t1 #comment in the end
-+;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 19
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 19
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 22
-+-----------------------------------------------------
-+select * from t1 -- comment in the end
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 19
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 19
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 22
-+select * from t1 -- comment in the end;
-+a
-+1
-+2
-+3
-+select * from t1 -- comment in the end;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 20
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 20
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 23
-+-----------------------------------------------------
-+select * from t1 -- comment in the end
-+
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 20
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 20
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 23
-+select * from t1 -- comment in the end
-+;
-+a
-+1
-+2
-+3
-+select * from t1 -- comment in the end
-+;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 20
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 20
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 25
-+-----------------------------------------------------
-+select ' \' ' from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 20
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 20
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 25
-+select ' \' ' from t1;
-+'
-+ '
-+ '
-+ '
-+select ' \' ' from t1;
-+'
-+ '
-+ '
-+ '
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 21
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 21
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 26
-+DROP TABLE t1;
-+SET GLOBAL query_cache_size=default;
-+set global query_cache_strip_comments=OFF;
---- /dev/null
-+++ b/mysql-test/r/percona_query_cache_with_comments_prepared_statements.result
-@@ -0,0 +1,396 @@
-+set GLOBAL query_cache_size=1355776;
-+flush query cache;
-+flush query cache;
-+reset query cache;
-+flush status;
-+drop table if exists t1;
-+create table t1 (a int not null);
-+insert into t1 values (1),(2),(3);
-+set global query_cache_strip_comments=ON;
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 0
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 0
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 0
-+prepare stmt from '/* with comment */ select * from t1';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 0
-+execute stmt;
-+a
-+1
-+2
-+3
-+execute stmt;
-+a
-+1
-+2
-+3
-+execute stmt;
-+a
-+1
-+2
-+3
-+execute stmt;
-+a
-+1
-+2
-+3
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 5
-+prepare stmt from 'select * from t1';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 6
-+prepare stmt from 'select * /*internal comment*/from t1';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 7
-+prepare stmt from 'select * /*internal comment*/ from t1';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 8
-+prepare stmt from 'select * from t1 /* at the end */';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 9
-+prepare stmt from 'select * from t1 /* with "quote" */';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 10
-+prepare stmt from 'select * from t1 /* with \'quote\' */';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 11
-+prepare stmt from 'select * from t1 # 123
-+';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 12
-+prepare stmt from 'select * from t1 # 123 with "quote"
-+';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 13
-+prepare stmt from 'select * from t1 # 123 with \'quote\'
-+';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 14
-+prepare stmt from 'select * from t1
-+# 123
-+';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 15
-+prepare stmt from '#456
-+select * from t1
-+# 123
-+';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 16
-+prepare stmt from 'select * from t1 -- 123
-+';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 17
-+prepare stmt from 'select * from t1
-+-- 123
-+';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 18
-+prepare stmt from '-- comment in first
-+select * from t1
-+# 123
-+';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 19
-+prepare stmt from '(#456(
-+select * from t1
-+# 123(
-+)';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 2
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 2
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 19
-+prepare stmt from '/*test*/(-- comment in first(
-+select * from t1
-+-- 123 asdasd
-+/* test */)';
-+execute stmt;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 2
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 2
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 20
-+prepare stmt from 'select "test",a from t1';
-+execute stmt;
-+test a
-+test 1
-+test 2
-+test 3
-+execute stmt;
-+test a
-+test 1
-+test 2
-+test 3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 3
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 3
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 21
-+prepare stmt from 'select "test /* internal \'comment\' */",a from t1';
-+execute stmt;
-+test /* internal 'comment' */ a
-+test /* internal 'comment' */ 1
-+test /* internal 'comment' */ 2
-+test /* internal 'comment' */ 3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 4
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 4
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 21
-+prepare stmt from 'select "test #internal comment" ,a from t1';
-+execute stmt;
-+test #internal comment a
-+test #internal comment 1
-+test #internal comment 2
-+test #internal comment 3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 5
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 5
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 21
-+prepare stmt from 'select "test #internal comment" #external comment
-+,a from t1';
-+execute stmt;
-+test #internal comment a
-+test #internal comment 1
-+test #internal comment 2
-+test #internal comment 3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache 5
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts 5
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits 22
-+DROP TABLE t1;
-+SET GLOBAL query_cache_size= default;
-+set global query_cache_strip_comments=OFF;
---- /dev/null
-+++ b/mysql-test/t/percona_query_cache_with_comments.test
-@@ -0,0 +1,5 @@
-+--disable_ps_protocol
-+set global query_cache_strip_comments=ON;
-+-- source include/percona_query_cache_with_comments_begin.inc
-+-- source include/percona_query_cache_with_comments.inc
-+-- source include/percona_query_cache_with_comments_end.inc
---- /dev/null
-+++ b/mysql-test/t/percona_query_cache_with_comments_crash.test
-@@ -0,0 +1,22 @@
-+-- source include/have_query_cache.inc
-+set GLOBAL query_cache_size=1355776;
-+--disable_warnings
-+drop table if exists t1;
-+--enable_warnings
-+create table t1 (a int not null);
-+insert into t1 values (1),(2),(3);
-+flush query cache; # This crashed in some versions
-+flush query cache; # This crashed in some versions
-+reset query cache;
-+flush status;
-+( select * from t1 );
-+/*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, @@SQL_MODE := REPLACE(REPLACE(@@SQL_MODE, 'ANSI_QUOTES', ''), ',,', ','), @OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, @@SQL_QUOTE_SHOW_CREATE := 1 */;
-+/* only comment */;
-+let query=# only comment
-+;
-+eval $query;
-+let query=-- only comment
-+;
-+eval $query;
-+DROP TABLE t1;
-+SET GLOBAL query_cache_size= default;
---- /dev/null
-+++ b/mysql-test/t/percona_query_cache_with_comments_disable.test
-@@ -0,0 +1,3 @@
-+-- source include/percona_query_cache_with_comments_begin.inc
-+-- source include/percona_query_cache_with_comments.inc
-+-- source include/percona_query_cache_with_comments_end.inc
---- /dev/null
-+++ b/mysql-test/t/percona_query_cache_with_comments_prepared_statements.test
-@@ -0,0 +1,208 @@
-+-- source include/have_query_cache.inc
-+
-+set GLOBAL query_cache_size=1355776;
-+
-+# Reset query cache variables.
-+flush query cache; # This crashed in some versions
-+flush query cache; # This crashed in some versions
-+reset query cache;
-+flush status;
-+--disable_warnings
-+drop table if exists t1;
-+--enable_warnings
-+
-+#
-+# First simple test
-+#
-+
-+create table t1 (a int not null);
-+insert into t1 values (1),(2),(3);
-+
-+set global query_cache_strip_comments=ON;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from '/* with comment */ select * from t1';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+execute stmt;
-+execute stmt;
-+execute stmt;
-+execute stmt;
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select * from t1';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select * /*internal comment*/from t1';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select * /*internal comment*/ from t1';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select * from t1 /* at the end */';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select * from t1 /* with "quote" */';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select * from t1 /* with \'quote\' */';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select * from t1 # 123
-+';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select * from t1 # 123 with "quote"
-+';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select * from t1 # 123 with \'quote\'
-+';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select * from t1
-+# 123
-+';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from '#456
-+select * from t1
-+# 123
-+';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select * from t1 -- 123
-+';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select * from t1
-+-- 123
-+';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from '-- comment in first
-+select * from t1
-+# 123
-+';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from '(#456(
-+select * from t1
-+# 123(
-+)';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from '/*test*/(-- comment in first(
-+select * from t1
-+-- 123 asdasd
-+/* test */)';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select "test",a from t1';
-+execute stmt;
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select "test /* internal \'comment\' */",a from t1';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select "test #internal comment" ,a from t1';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+prepare stmt from 'select "test #internal comment" #external comment
-+,a from t1';
-+execute stmt;
-+
-+show status like "Qcache_queries_in_cache";
-+show status like "Qcache_inserts";
-+show status like "Qcache_hits";
-+
-+DROP TABLE t1;
-+SET GLOBAL query_cache_size= default;
-+set global query_cache_strip_comments=OFF;
---- /dev/null
-+++ b/mysql-test/t/percona_status_wait_query_cache_mutex.test
-@@ -0,0 +1,35 @@
-+--source include/have_query_cache.inc
-+--source include/have_debug.inc
-+--source include/have_debug_sync.inc
-+SET GLOBAL query_cache_size=1355776;
-+--source include/percona_query_cache_with_comments_clear.inc
-+--let try_lock_mutex_query=SELECT "try_lock_mutex_query" as action
-+
-+--connect (mutex_locked_conn, localhost, root,,)
-+--connect (try_mutex_lock_conn, localhost, root,,)
-+
-+--connection mutex_locked_conn
-+SET DEBUG_SYNC='after_query_cache_mutex SIGNAL mutex_locked WAIT_FOR unlock_mutex';
-+send SELECT "mutex_locked_query" as action;
-+
-+--connection default
-+SET DEBUG_SYNC='now WAIT_FOR mutex_locked';
-+
-+--connection try_mutex_lock_conn
-+SET DEBUG_SYNC='before_query_cache_mutex SIGNAL try_lock_mutex';
-+send_eval $try_lock_mutex_query;
-+
-+--connection default
-+SET DEBUG_SYNC='now WAIT_FOR try_lock_mutex';
-+eval SELECT SQL_NO_CACHE state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE info='$try_lock_mutex_query';
-+SET DEBUG_SYNC='now SIGNAL unlock_mutex';
-+
-+--connection mutex_locked_conn
-+reap;
-+--connection try_mutex_lock_conn
-+reap;
-+
-+--connection default
-+--disconnect mutex_locked_conn
-+--disconnect try_mutex_lock_conn
-+SET GLOBAL query_cache_size=0;
---- a/mysql-test/r/mysqld--help-notwin.result
-+++ b/mysql-test/r/mysqld--help-notwin.result
-@@ -500,6 +500,10 @@
- The minimum size for blocks allocated by the query cache
- --query-cache-size=#
- The memory allocated to store results from old queries
-+ --query-cache-strip-comments
-+ Enable and disable optimisation "strip comment for query
-+ cache" - optimisation strip all comments from query while
-+ search query result in query cache
- --query-cache-type=name
- OFF = Don't cache or retrieve results. ON = Cache all
- results except SELECT SQL_NO_CACHE ... queries. DEMAND =
-@@ -942,6 +946,7 @@
- query-cache-limit 1048576
- query-cache-min-res-unit 4096
- query-cache-size 0
-+query-cache-strip-comments FALSE
- query-cache-type ON
- query-cache-wlock-invalidate FALSE
- query-prealloc-size 8192
---- /dev/null
-+++ b/mysql-test/r/percona_status_wait_query_cache_mutex.result
-@@ -0,0 +1,20 @@
-+SET GLOBAL query_cache_size=1355776;
-+flush query cache;
-+flush query cache;
-+reset query cache;
-+flush status;
-+SET DEBUG_SYNC='after_query_cache_mutex SIGNAL mutex_locked WAIT_FOR unlock_mutex';
-+SELECT "mutex_locked_query" as action;
-+SET DEBUG_SYNC='now WAIT_FOR mutex_locked';
-+SET DEBUG_SYNC='before_query_cache_mutex SIGNAL try_lock_mutex';
-+SELECT "try_lock_mutex_query" as action;
-+SET DEBUG_SYNC='now WAIT_FOR try_lock_mutex';
-+SELECT SQL_NO_CACHE state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE info='SELECT "try_lock_mutex_query" as action';
-+state
-+Waiting on query cache mutex
-+SET DEBUG_SYNC='now SIGNAL unlock_mutex';
-+action
-+mutex_locked_query
-+action
-+try_lock_mutex_query
-+SET GLOBAL query_cache_size=0;
---- /dev/null
-+++ b/mysql-test/r/percona_bug856404.result
-@@ -0,0 +1,8 @@
-+DROP TABLE IF EXISTS table17_int;
-+DROP TABLE IF EXISTS table30_int;
-+CREATE TABLE `table17_int` (pk integer auto_increment primary key, `col_char_10_not_null_key` char(10), `col_enum_not_null_key` int);
-+CREATE TABLE `table30_int` (pk integer auto_increment primary key, `col_enum_not_null_key` int);
-+SELECT X . `pk` FROM `table17_int` AS X LEFT JOIN `table30_int` AS Y USING ( `col_enum_not_null_key` ) WHERE X . `col_char_10_not_null_key` != ' you need to translate Views labels into other languages, consider installing the <a href=\" !path\">Internationalization</a> package\'s Views translation module.' LIMIT 7 /*Generated by THREAD_ID 1*/;
-+pk
-+DROP TABLE table17_int;
-+DROP TABLE table30_int;
---- /dev/null
-+++ b/mysql-test/t/percona_bug856404-master.opt
-@@ -0,0 +1 @@
-+--query-cache-size=10M --query-cache-strip-comments
---- /dev/null
-+++ b/mysql-test/t/percona_bug856404.test
-@@ -0,0 +1,15 @@
-+########################################################################
-+# Bug #856404: Crash when query_cache_strip_comments enabled
-+########################################################################
-+
-+--disable_warnings
-+DROP TABLE IF EXISTS table17_int;
-+DROP TABLE IF EXISTS table30_int;
-+--enable_warnings
-+
-+CREATE TABLE `table17_int` (pk integer auto_increment primary key, `col_char_10_not_null_key` char(10), `col_enum_not_null_key` int);
-+CREATE TABLE `table30_int` (pk integer auto_increment primary key, `col_enum_not_null_key` int);
-+SELECT X . `pk` FROM `table17_int` AS X LEFT JOIN `table30_int` AS Y USING ( `col_enum_not_null_key` ) WHERE X . `col_char_10_not_null_key` != ' you need to translate Views labels into other languages, consider installing the <a href=\" !path\">Internationalization</a> package\'s Views translation module.' LIMIT 7 /*Generated by THREAD_ID 1*/;
-+
-+DROP TABLE table17_int;
-+DROP TABLE table30_int;
+++ /dev/null
-# name : remove_fcntl_excessive_calls.patch
-# introduced : 12
-# maintainer : Oleg
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- /dev/null
-+++ b/patch_info/remove_fcntl_excessive_calls.info
-@@ -0,0 +1,6 @@
-+File=remove_fcntl_excessive_calls.patch
-+Name=remove fcntl excessive calls
-+Version=1.0
-+Author=This is a port of the official fix.
-+License=GPL
-+Comment=
---- a/sql/net_serv.cc
-+++ b/sql/net_serv.cc
-@@ -61,7 +61,7 @@
- the client should have a bigger max_allowed_packet.
- */
-
--#if defined(__WIN__) || !defined(MYSQL_SERVER)
-+#if (defined(__WIN__) || !defined(MYSQL_SERVER)) && !defined(NO_ALARM)
- /* The following is because alarms doesn't work on windows. */
- #ifndef NO_ALARM
- #define NO_ALARM
-@@ -133,7 +133,7 @@
- if (vio != 0) /* If real connection */
- {
- net->fd = vio_fd(vio); /* For perl DBI/DBD */
--#if defined(MYSQL_SERVER) && !defined(__WIN__)
-+#if defined(MYSQL_SERVER) && !defined(__WIN__) && !defined(NO_ALARM)
- if (!(test_flags & TEST_BLOCKING))
- {
- my_bool old_mode;
-@@ -632,7 +632,7 @@
- if ((long) (length= vio_write(net->vio,pos,(size_t) (end-pos))) <= 0)
- {
- my_bool interrupted = vio_should_retry(net->vio);
--#if !defined(__WIN__)
-+#if !defined(NO_ALARM) && !defined(__WIN__)
- if ((interrupted || length == 0) && !thr_alarm_in_use(&alarmed))
- {
- if (!thr_alarm(&alarmed, net->write_timeout, &alarm_buff))
-@@ -688,7 +688,7 @@
- pos+=length;
- update_statistics(thd_increment_bytes_sent(length));
- }
--#ifndef __WIN__
-+#if !defined(NO_ALARM) && !defined(__WIN__)
- end:
- #endif
- #ifdef HAVE_COMPRESS
-@@ -820,6 +820,7 @@
- thr_alarm(&alarmed,net->read_timeout,&alarm_buff);
- #else
- /* Read timeout is set in my_net_set_read_timeout */
-+ DBUG_ASSERT(net_blocking);
- #endif /* NO_ALARM */
-
- pos = net->buff + net->where_b; /* net->packet -4 */
-@@ -834,7 +835,7 @@
-
- DBUG_PRINT("info",("vio_read returned %ld errno: %d",
- (long) length, vio_errno(net->vio)));
--#if !defined(__WIN__) || defined(MYSQL_SERVER)
-+#if !defined(NO_ALARM) && (!defined(__WIN__) || defined(MYSQL_SERVER))
- /*
- We got an error that there was no data on the socket. We now set up
- an alarm to not 'read forever', change the socket to non blocking
+++ /dev/null
-# name : response-time-distribution.patch
-# introduced : 12
-# maintainer : Oleg
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -165,7 +165,12 @@
- OPTION (WITH_UNIT_TESTS "Compile MySQL with unit tests" ON)
- MARK_AS_ADVANCED(CYBOZU BACKUP_TEST WITHOUT_SERVER DISABLE_SHARED)
-
--
-+OPTION(WITHOUT_RESPONSE_TIME_DISTRIBUTION "If we want to have response_time_distribution" OFF)
-+IF(WITHOUT_RESPONSE_TIME_DISTRIBUTION)
-+ELSE()
-+ADD_DEFINITIONS(-DHAVE_RESPONSE_TIME_DISTRIBUTION)
-+ENDIF()
-+
- OPTION(ENABLE_DEBUG_SYNC "Enable debug sync (debug builds only)" ON)
- IF(ENABLE_DEBUG_SYNC)
- SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DENABLED_DEBUG_SYNC")
---- a/include/mysql_com.h
-+++ b/include/mysql_com.h
-@@ -141,10 +141,11 @@
- #define REFRESH_FAST 32768 /* Intern flag */
-
- /* RESET (remove all queries) from query cache */
--#define REFRESH_QUERY_CACHE 65536
--#define REFRESH_QUERY_CACHE_FREE 0x20000L /* pack query cache */
--#define REFRESH_DES_KEY_FILE 0x40000L
--#define REFRESH_USER_RESOURCES 0x80000L
-+#define REFRESH_QUERY_CACHE 65536
-+#define REFRESH_QUERY_CACHE_FREE 0x20000L /* pack query cache */
-+#define REFRESH_DES_KEY_FILE 0x40000L
-+#define REFRESH_USER_RESOURCES 0x80000L
-+#define REFRESH_QUERY_RESPONSE_TIME 0x100000L /* response time distibution */
-
- #define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */
- #define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */
---- /dev/null
-+++ b/mysql-test/include/have_response_time_distribution.inc
-@@ -0,0 +1,4 @@
-+-- require r/have_response_time_distribution.require
-+disable_query_log;
-+show variables like 'have_response_time_distribution';
-+enable_query_log;
---- /dev/null
-+++ b/mysql-test/include/query_response_time.inc
-@@ -0,0 +1,43 @@
-+SET SESSION query_exec_time=0.1;
-+
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+EVAL SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=$base;
-+FLUSH QUERY_RESPONSE_TIME;
-+# Following two queries check works of FLUSH and
-+# respecting of "QUERY_RESPONSE_TIME_STATS" variable (see launchpad bug #855312)
-+SHOW QUERY_RESPONSE_TIME;
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+
-+SET SESSION query_exec_time=0.31; SELECT 1;
-+SET SESSION query_exec_time=0.32; SELECT 1;
-+SET SESSION query_exec_time=0.33; SELECT 1;
-+SET SESSION query_exec_time=0.34; SELECT 1;
-+SET SESSION query_exec_time=0.35; SELECT 1;
-+SET SESSION query_exec_time=0.36; SELECT 1;
-+SET SESSION query_exec_time=0.37; SELECT 1;
-+SET SESSION query_exec_time=0.38; SELECT 1;
-+SET SESSION query_exec_time=0.39; SELECT 1;
-+SET SESSION query_exec_time=0.4; SELECT 1;
-+SET SESSION query_exec_time=1.1; SELECT 1;
-+SET SESSION query_exec_time=1.2; SELECT 1;
-+SET SESSION query_exec_time=1.3; SELECT 1;
-+SET SESSION query_exec_time=1.5; SELECT 1;
-+SET SESSION query_exec_time=1.4; SELECT 1;
-+SET SESSION query_exec_time=0.5; SELECT 1;
-+SET SESSION query_exec_time=2.1; SELECT 1;
-+SET SESSION query_exec_time=2.3; SELECT 1;
-+SET SESSION query_exec_time=2.5; SELECT 1;
-+SET SESSION query_exec_time=3.1; SELECT 1;
-+SET SESSION query_exec_time=4.1; SELECT 1;
-+SET SESSION query_exec_time=5.1; SELECT 1;
-+
-+SET SESSION query_exec_time=0.1;
-+
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+SHOW QUERY_RESPONSE_TIME;
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+
-+SET SESSION query_exec_time=default;
---- /dev/null
-+++ b/mysql-test/include/query_response_time-replication.inc
-@@ -0,0 +1,57 @@
-+connection master;
-+
-+CREATE TABLE t(id INT);
-+
-+connection slave;
-+SET GLOBAL query_exec_time = 0.1;
-+--source include/restart_slave_sql.inc
-+
-+connection slave;
-+
-+SET SESSION query_exec_time=0.1;
-+
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+--eval SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=$base
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+
-+connection master;
-+
-+SET SESSION query_exec_time = 0.31; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.32; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.33; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.34; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.35; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.36; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.37; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.38; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.39; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.4; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.1; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.2; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.3; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.5; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.4; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.5; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.1; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.3; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.5; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 3.1; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 4.1; INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 5.1; INSERT INTO t VALUES(1);
-+
-+sync_slave_with_master;
-+
-+connection slave;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+SHOW QUERY_RESPONSE_TIME;
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
-+
-+connection master;
-+DROP TABLE t;
-+
-+sync_slave_with_master;
---- /dev/null
-+++ b/mysql-test/include/query_response_time-stored.inc
-@@ -0,0 +1,37 @@
-+SET SESSION query_exec_time=0.1;
-+
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+EVAL SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=$base;
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+
-+CALL test_f(0.31);
-+CALL test_f(0.32);
-+CALL test_f(0.33);
-+CALL test_f(0.34);
-+CALL test_f(0.35);
-+CALL test_f(0.36);
-+CALL test_f(0.37);
-+CALL test_f(0.38);
-+CALL test_f(0.39);
-+CALL test_f(0.4);
-+CALL test_f(1.1);
-+CALL test_f(1.2);
-+CALL test_f(1.3);
-+CALL test_f(1.5);
-+CALL test_f(1.4);
-+CALL test_f(0.5);
-+CALL test_f(2.1);
-+CALL test_f(2.3);
-+CALL test_f(2.5);
-+CALL test_f(3.1);
-+CALL test_f(4.1);
-+CALL test_f(5.1);
-+
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+SHOW QUERY_RESPONSE_TIME;
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+
-+SET SESSION query_exec_time=default;
---- /dev/null
-+++ b/mysql-test/r/percona_query_response_time-replication.result
-@@ -0,0 +1,727 @@
-+SET GLOBAL query_exec_time=0.1;
-+include/master-slave.inc
-+[connection master]
-+CREATE TABLE t(id INT);
-+SET GLOBAL query_exec_time = 0.1;
-+include/restart_slave.inc
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1;
-+Warnings:
-+Warning 1292 Truncated incorrect query_response_time_range_base value: '1'
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+SET SESSION query_exec_time = 0.31;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.32;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.33;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.34;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.35;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.36;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.37;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.38;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.39;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.4;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.2;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.3;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.4;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.3;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 3.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 4.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 5.1;
-+INSERT INTO t VALUES(1);
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 2
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 1 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 1 0.100000
-+ 0.250000 0 0.000000
-+ 0.500000 30 10.650000
-+ 1.000000 3 1.500000
-+ 2.000000 15 19.500000
-+ 4.000000 12 30.000000
-+ 8.000000 6 27.599997
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 1 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 1 0.100000
-+ 0.250000 0 0.000000
-+ 0.500000 30 10.650000
-+ 1.000000 3 1.500000
-+ 2.000000 15 19.500000
-+ 4.000000 12 30.000000
-+ 8.000000 6 27.599997
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
-+DROP TABLE t;
-+CREATE TABLE t(id INT);
-+SET GLOBAL query_exec_time = 0.1;
-+include/restart_slave.inc
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=2;
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+SET SESSION query_exec_time = 0.31;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.32;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.33;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.34;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.35;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.36;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.37;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.38;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.39;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.4;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.2;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.3;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.4;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.3;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 3.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 4.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 5.1;
-+INSERT INTO t VALUES(1);
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 2
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 1 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 1 0.100000
-+ 0.250000 0 0.000000
-+ 0.500000 30 10.650000
-+ 1.000000 3 1.500000
-+ 2.000000 15 19.500000
-+ 4.000000 12 30.000000
-+ 8.000000 6 27.599997
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 1 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 1 0.100000
-+ 0.250000 0 0.000000
-+ 0.500000 30 10.650000
-+ 1.000000 3 1.500000
-+ 2.000000 15 19.500000
-+ 4.000000 12 30.000000
-+ 8.000000 6 27.599997
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
-+DROP TABLE t;
-+CREATE TABLE t(id INT);
-+SET GLOBAL query_exec_time = 0.1;
-+include/restart_slave.inc
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=10;
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+SET SESSION query_exec_time = 0.31;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.32;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.33;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.34;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.35;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.36;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.37;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.38;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.39;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.4;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.2;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.3;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.4;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.3;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 3.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 4.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 5.1;
-+INSERT INTO t VALUES(1);
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 10
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 1 0.000000
-+ 0.000010 0 0.000000
-+ 0.000100 0 0.000000
-+ 0.001000 0 0.000000
-+ 0.010000 0 0.000000
-+ 0.100000 0 0.000000
-+ 1.000000 34 12.250000
-+ 10.000000 33 77.099997
-+ 100.000000 0 0.000000
-+ 1000.000000 0 0.000000
-+ 10000.000000 0 0.000000
-+ 100000.000000 0 0.000000
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 1 0.000000
-+ 0.000010 0 0.000000
-+ 0.000100 0 0.000000
-+ 0.001000 0 0.000000
-+ 0.010000 0 0.000000
-+ 0.100000 0 0.000000
-+ 1.000000 34 12.250000
-+ 10.000000 33 77.099997
-+ 100.000000 0 0.000000
-+ 1000.000000 0 0.000000
-+ 10000.000000 0 0.000000
-+ 100000.000000 0 0.000000
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
-+DROP TABLE t;
-+CREATE TABLE t(id INT);
-+SET GLOBAL query_exec_time = 0.1;
-+include/restart_slave.inc
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=7;
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+SET SESSION query_exec_time = 0.31;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.32;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.33;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.34;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.35;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.36;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.37;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.38;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.39;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.4;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.2;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.3;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.4;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.3;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 3.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 4.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 5.1;
-+INSERT INTO t VALUES(1);
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 7
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 1 0.000000
-+ 0.000008 0 0.000000
-+ 0.000059 0 0.000000
-+ 0.000416 0 0.000000
-+ 0.002915 0 0.000000
-+ 0.020408 0 0.000000
-+ 0.142857 1 0.100000
-+ 1.000000 33 12.150000
-+ 7.000000 33 77.099997
-+ 49.000000 0 0.000000
-+ 343.000000 0 0.000000
-+ 2401.000000 0 0.000000
-+ 16807.000000 0 0.000000
-+ 117649.000000 0 0.000000
-+ 823543.000000 0 0.000000
-+5764801.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 1 0.000000
-+ 0.000008 0 0.000000
-+ 0.000059 0 0.000000
-+ 0.000416 0 0.000000
-+ 0.002915 0 0.000000
-+ 0.020408 0 0.000000
-+ 0.142857 1 0.100000
-+ 1.000000 33 12.150000
-+ 7.000000 33 77.099997
-+ 49.000000 0 0.000000
-+ 343.000000 0 0.000000
-+ 2401.000000 0 0.000000
-+ 16807.000000 0 0.000000
-+ 117649.000000 0 0.000000
-+ 823543.000000 0 0.000000
-+5764801.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
-+DROP TABLE t;
-+CREATE TABLE t(id INT);
-+SET GLOBAL query_exec_time = 0.1;
-+include/restart_slave.inc
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=156;
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+SET SESSION query_exec_time = 0.31;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.32;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.33;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.34;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.35;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.36;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.37;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.38;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.39;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.4;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.2;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.3;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.4;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.3;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 3.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 4.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 5.1;
-+INSERT INTO t VALUES(1);
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 156
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000041 1 0.000000
-+ 0.006410 0 0.000000
-+ 1.000000 34 12.250000
-+ 156.000000 33 77.099997
-+ 24336.000000 0 0.000000
-+3796416.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000041 1 0.000000
-+ 0.006410 0 0.000000
-+ 1.000000 34 12.250000
-+ 156.000000 33 77.099997
-+ 24336.000000 0 0.000000
-+3796416.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
-+DROP TABLE t;
-+CREATE TABLE t(id INT);
-+SET GLOBAL query_exec_time = 0.1;
-+include/restart_slave.inc
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1000;
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+SET SESSION query_exec_time = 0.31;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.32;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.33;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.34;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.35;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.36;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.37;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.38;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.39;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.4;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.2;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.3;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.4;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.3;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 3.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 4.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 5.1;
-+INSERT INTO t VALUES(1);
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 1000
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 1 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 34 12.250000
-+ 1000.000000 33 77.099997
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 1 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 34 12.250000
-+ 1000.000000 33 77.099997
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
-+DROP TABLE t;
-+CREATE TABLE t(id INT);
-+SET GLOBAL query_exec_time = 0.1;
-+include/restart_slave.inc
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1001;
-+Warnings:
-+Warning 1292 Truncated incorrect query_response_time_range_base value: '1001'
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+SET SESSION query_exec_time = 0.31;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.32;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.33;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.34;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.35;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.36;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.37;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.38;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.39;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.4;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.2;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.3;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 1.4;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 0.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.3;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 2.5;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 3.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 4.1;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time = 5.1;
-+INSERT INTO t VALUES(1);
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 1000
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 1 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 34 12.250000
-+ 1000.000000 33 77.099997
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 1 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 34 12.250000
-+ 1000.000000 33 77.099997
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
-+DROP TABLE t;
-+include/rpl_end.inc
-+SET GLOBAL query_exec_time=default;
-+SET GLOBAL query_exec_time=default;
---- /dev/null
-+++ b/mysql-test/r/percona_query_response_time.result
-@@ -0,0 +1,1307 @@
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1;
-+Warnings:
-+Warning 1292 Truncated incorrect query_response_time_range_base value: '1'
-+FLUSH QUERY_RESPONSE_TIME;
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 0 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 0 0.000000
-+ 0.250000 0 0.000000
-+ 0.500000 0 0.000000
-+ 1.000000 0 0.000000
-+ 2.000000 0 0.000000
-+ 4.000000 0 0.000000
-+ 8.000000 0 0.000000
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 0 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 0 0.000000
-+ 0.250000 0 0.000000
-+ 0.500000 0 0.000000
-+ 1.000000 0 0.000000
-+ 2.000000 0 0.000000
-+ 4.000000 0 0.000000
-+ 8.000000 0 0.000000
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+SET SESSION query_exec_time=0.31;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.32;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.33;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.34;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.35;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.36;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.37;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.38;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.39;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.4;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.2;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.3;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.4;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.3;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=3.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=4.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=5.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 2
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 24 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 0 0.000000
-+ 0.250000 0 0.000000
-+ 0.500000 10 3.550000
-+ 1.000000 1 0.500000
-+ 2.000000 5 6.500000
-+ 4.000000 4 10.000000
-+ 8.000000 2 9.199999
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 24 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 0 0.000000
-+ 0.250000 0 0.000000
-+ 0.500000 10 3.550000
-+ 1.000000 1 0.500000
-+ 2.000000 5 6.500000
-+ 4.000000 4 10.000000
-+ 8.000000 2 9.199999
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET SESSION query_exec_time=default;
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=2;
-+FLUSH QUERY_RESPONSE_TIME;
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 0 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 0 0.000000
-+ 0.250000 0 0.000000
-+ 0.500000 0 0.000000
-+ 1.000000 0 0.000000
-+ 2.000000 0 0.000000
-+ 4.000000 0 0.000000
-+ 8.000000 0 0.000000
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 0 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 0 0.000000
-+ 0.250000 0 0.000000
-+ 0.500000 0 0.000000
-+ 1.000000 0 0.000000
-+ 2.000000 0 0.000000
-+ 4.000000 0 0.000000
-+ 8.000000 0 0.000000
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+SET SESSION query_exec_time=0.31;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.32;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.33;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.34;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.35;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.36;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.37;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.38;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.39;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.4;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.2;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.3;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.4;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.3;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=3.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=4.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=5.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 2
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 24 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 0 0.000000
-+ 0.250000 0 0.000000
-+ 0.500000 10 3.550000
-+ 1.000000 1 0.500000
-+ 2.000000 5 6.500000
-+ 4.000000 4 10.000000
-+ 8.000000 2 9.199999
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 24 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 0 0.000000
-+ 0.250000 0 0.000000
-+ 0.500000 10 3.550000
-+ 1.000000 1 0.500000
-+ 2.000000 5 6.500000
-+ 4.000000 4 10.000000
-+ 8.000000 2 9.199999
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET SESSION query_exec_time=default;
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=10;
-+FLUSH QUERY_RESPONSE_TIME;
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 0 0.000000
-+ 0.000010 0 0.000000
-+ 0.000100 0 0.000000
-+ 0.001000 0 0.000000
-+ 0.010000 0 0.000000
-+ 0.100000 0 0.000000
-+ 1.000000 0 0.000000
-+ 10.000000 0 0.000000
-+ 100.000000 0 0.000000
-+ 1000.000000 0 0.000000
-+ 10000.000000 0 0.000000
-+ 100000.000000 0 0.000000
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 0 0.000000
-+ 0.000010 0 0.000000
-+ 0.000100 0 0.000000
-+ 0.001000 0 0.000000
-+ 0.010000 0 0.000000
-+ 0.100000 0 0.000000
-+ 1.000000 0 0.000000
-+ 10.000000 0 0.000000
-+ 100.000000 0 0.000000
-+ 1000.000000 0 0.000000
-+ 10000.000000 0 0.000000
-+ 100000.000000 0 0.000000
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+SET SESSION query_exec_time=0.31;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.32;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.33;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.34;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.35;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.36;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.37;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.38;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.39;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.4;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.2;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.3;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.4;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.3;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=3.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=4.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=5.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 10
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 24 0.000000
-+ 0.000010 0 0.000000
-+ 0.000100 0 0.000000
-+ 0.001000 0 0.000000
-+ 0.010000 0 0.000000
-+ 0.100000 0 0.000000
-+ 1.000000 11 4.050000
-+ 10.000000 11 25.699999
-+ 100.000000 0 0.000000
-+ 1000.000000 0 0.000000
-+ 10000.000000 0 0.000000
-+ 100000.000000 0 0.000000
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 24 0.000000
-+ 0.000010 0 0.000000
-+ 0.000100 0 0.000000
-+ 0.001000 0 0.000000
-+ 0.010000 0 0.000000
-+ 0.100000 0 0.000000
-+ 1.000000 11 4.050000
-+ 10.000000 11 25.699999
-+ 100.000000 0 0.000000
-+ 1000.000000 0 0.000000
-+ 10000.000000 0 0.000000
-+ 100000.000000 0 0.000000
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET SESSION query_exec_time=default;
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=7;
-+FLUSH QUERY_RESPONSE_TIME;
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 0 0.000000
-+ 0.000008 0 0.000000
-+ 0.000059 0 0.000000
-+ 0.000416 0 0.000000
-+ 0.002915 0 0.000000
-+ 0.020408 0 0.000000
-+ 0.142857 0 0.000000
-+ 1.000000 0 0.000000
-+ 7.000000 0 0.000000
-+ 49.000000 0 0.000000
-+ 343.000000 0 0.000000
-+ 2401.000000 0 0.000000
-+ 16807.000000 0 0.000000
-+ 117649.000000 0 0.000000
-+ 823543.000000 0 0.000000
-+5764801.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 0 0.000000
-+ 0.000008 0 0.000000
-+ 0.000059 0 0.000000
-+ 0.000416 0 0.000000
-+ 0.002915 0 0.000000
-+ 0.020408 0 0.000000
-+ 0.142857 0 0.000000
-+ 1.000000 0 0.000000
-+ 7.000000 0 0.000000
-+ 49.000000 0 0.000000
-+ 343.000000 0 0.000000
-+ 2401.000000 0 0.000000
-+ 16807.000000 0 0.000000
-+ 117649.000000 0 0.000000
-+ 823543.000000 0 0.000000
-+5764801.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+SET SESSION query_exec_time=0.31;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.32;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.33;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.34;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.35;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.36;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.37;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.38;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.39;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.4;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.2;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.3;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.4;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.3;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=3.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=4.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=5.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 7
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 24 0.000000
-+ 0.000008 0 0.000000
-+ 0.000059 0 0.000000
-+ 0.000416 0 0.000000
-+ 0.002915 0 0.000000
-+ 0.020408 0 0.000000
-+ 0.142857 0 0.000000
-+ 1.000000 11 4.050000
-+ 7.000000 11 25.699999
-+ 49.000000 0 0.000000
-+ 343.000000 0 0.000000
-+ 2401.000000 0 0.000000
-+ 16807.000000 0 0.000000
-+ 117649.000000 0 0.000000
-+ 823543.000000 0 0.000000
-+5764801.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 24 0.000000
-+ 0.000008 0 0.000000
-+ 0.000059 0 0.000000
-+ 0.000416 0 0.000000
-+ 0.002915 0 0.000000
-+ 0.020408 0 0.000000
-+ 0.142857 0 0.000000
-+ 1.000000 11 4.050000
-+ 7.000000 11 25.699999
-+ 49.000000 0 0.000000
-+ 343.000000 0 0.000000
-+ 2401.000000 0 0.000000
-+ 16807.000000 0 0.000000
-+ 117649.000000 0 0.000000
-+ 823543.000000 0 0.000000
-+5764801.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET SESSION query_exec_time=default;
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=156;
-+FLUSH QUERY_RESPONSE_TIME;
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000041 0 0.000000
-+ 0.006410 0 0.000000
-+ 1.000000 0 0.000000
-+ 156.000000 0 0.000000
-+ 24336.000000 0 0.000000
-+3796416.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000041 0 0.000000
-+ 0.006410 0 0.000000
-+ 1.000000 0 0.000000
-+ 156.000000 0 0.000000
-+ 24336.000000 0 0.000000
-+3796416.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+SET SESSION query_exec_time=0.31;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.32;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.33;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.34;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.35;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.36;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.37;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.38;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.39;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.4;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.2;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.3;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.4;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.3;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=3.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=4.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=5.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 156
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000041 24 0.000000
-+ 0.006410 0 0.000000
-+ 1.000000 11 4.050000
-+ 156.000000 11 25.699999
-+ 24336.000000 0 0.000000
-+3796416.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000041 24 0.000000
-+ 0.006410 0 0.000000
-+ 1.000000 11 4.050000
-+ 156.000000 11 25.699999
-+ 24336.000000 0 0.000000
-+3796416.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET SESSION query_exec_time=default;
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1000;
-+FLUSH QUERY_RESPONSE_TIME;
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 0 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 0 0.000000
-+ 1000.000000 0 0.000000
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 0 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 0 0.000000
-+ 1000.000000 0 0.000000
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+SET SESSION query_exec_time=0.31;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.32;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.33;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.34;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.35;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.36;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.37;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.38;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.39;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.4;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.2;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.3;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.4;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.3;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=3.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=4.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=5.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 1000
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 24 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 11 4.050000
-+ 1000.000000 11 25.699999
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 24 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 11 4.050000
-+ 1000.000000 11 25.699999
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET SESSION query_exec_time=default;
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1001;
-+Warnings:
-+Warning 1292 Truncated incorrect query_response_time_range_base value: '1001'
-+FLUSH QUERY_RESPONSE_TIME;
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 0 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 0 0.000000
-+ 1000.000000 0 0.000000
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 0 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 0 0.000000
-+ 1000.000000 0 0.000000
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+SET SESSION query_exec_time=0.31;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.32;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.33;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.34;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.35;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.36;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.37;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.38;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.39;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.4;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.2;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.3;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=1.4;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.3;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=2.5;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=3.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=4.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=5.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 1000
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 24 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 11 4.050000
-+ 1000.000000 11 25.699999
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 24 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 11 4.050000
-+ 1000.000000 11 25.699999
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET SESSION query_exec_time=default;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
---- /dev/null
-+++ b/mysql-test/r/percona_query_response_time-stored.result
-@@ -0,0 +1,544 @@
-+CREATE TABLE t(a INT);
-+CREATE PROCEDURE test_f(t DECIMAL(3,2))
-+BEGIN
-+SET SESSION query_exec_time=t;
-+INSERT INTO t VALUES(1);
-+SET SESSION query_exec_time=0.1;
-+DELETE FROM t;
-+END^
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1;
-+Warnings:
-+Warning 1292 Truncated incorrect query_response_time_range_base value: '1'
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+CALL test_f(0.31);
-+CALL test_f(0.32);
-+CALL test_f(0.33);
-+CALL test_f(0.34);
-+CALL test_f(0.35);
-+CALL test_f(0.36);
-+CALL test_f(0.37);
-+CALL test_f(0.38);
-+CALL test_f(0.39);
-+CALL test_f(0.4);
-+CALL test_f(1.1);
-+CALL test_f(1.2);
-+CALL test_f(1.3);
-+CALL test_f(1.5);
-+CALL test_f(1.4);
-+CALL test_f(0.5);
-+CALL test_f(2.1);
-+CALL test_f(2.3);
-+CALL test_f(2.5);
-+CALL test_f(3.1);
-+CALL test_f(4.1);
-+CALL test_f(5.1);
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 2
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 45 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 44 4.400000
-+ 0.250000 0 0.000000
-+ 0.500000 10 3.550000
-+ 1.000000 1 0.500000
-+ 2.000000 5 6.500000
-+ 4.000000 4 10.000000
-+ 8.000000 2 9.199999
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 45 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 44 4.400000
-+ 0.250000 0 0.000000
-+ 0.500000 10 3.550000
-+ 1.000000 1 0.500000
-+ 2.000000 5 6.500000
-+ 4.000000 4 10.000000
-+ 8.000000 2 9.199999
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET SESSION query_exec_time=default;
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=2;
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+CALL test_f(0.31);
-+CALL test_f(0.32);
-+CALL test_f(0.33);
-+CALL test_f(0.34);
-+CALL test_f(0.35);
-+CALL test_f(0.36);
-+CALL test_f(0.37);
-+CALL test_f(0.38);
-+CALL test_f(0.39);
-+CALL test_f(0.4);
-+CALL test_f(1.1);
-+CALL test_f(1.2);
-+CALL test_f(1.3);
-+CALL test_f(1.5);
-+CALL test_f(1.4);
-+CALL test_f(0.5);
-+CALL test_f(2.1);
-+CALL test_f(2.3);
-+CALL test_f(2.5);
-+CALL test_f(3.1);
-+CALL test_f(4.1);
-+CALL test_f(5.1);
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 2
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 45 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 44 4.400000
-+ 0.250000 0 0.000000
-+ 0.500000 10 3.550000
-+ 1.000000 1 0.500000
-+ 2.000000 5 6.500000
-+ 4.000000 4 10.000000
-+ 8.000000 2 9.199999
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 45 0.000000
-+ 0.000003 0 0.000000
-+ 0.000007 0 0.000000
-+ 0.000015 0 0.000000
-+ 0.000030 0 0.000000
-+ 0.000061 0 0.000000
-+ 0.000122 0 0.000000
-+ 0.000244 0 0.000000
-+ 0.000488 0 0.000000
-+ 0.000976 0 0.000000
-+ 0.001953 0 0.000000
-+ 0.003906 0 0.000000
-+ 0.007812 0 0.000000
-+ 0.015625 0 0.000000
-+ 0.031250 0 0.000000
-+ 0.062500 0 0.000000
-+ 0.125000 44 4.400000
-+ 0.250000 0 0.000000
-+ 0.500000 10 3.550000
-+ 1.000000 1 0.500000
-+ 2.000000 5 6.500000
-+ 4.000000 4 10.000000
-+ 8.000000 2 9.199999
-+ 16.000000 0 0.000000
-+ 32.000000 0 0.000000
-+ 64.000000 0 0.000000
-+ 128.000000 0 0.000000
-+ 256.000000 0 0.000000
-+ 512.000000 0 0.000000
-+ 1024.000000 0 0.000000
-+ 2048.000000 0 0.000000
-+ 4096.000000 0 0.000000
-+ 8192.000000 0 0.000000
-+ 16384.000000 0 0.000000
-+ 32768.000000 0 0.000000
-+ 65536.000000 0 0.000000
-+ 131072.000000 0 0.000000
-+ 262144.000000 0 0.000000
-+ 524288.000000 0 0.000000
-+1048576.000000 0 0.000000
-+2097152.000000 0 0.000000
-+4194304.000000 0 0.000000
-+8388608.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET SESSION query_exec_time=default;
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=10;
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+CALL test_f(0.31);
-+CALL test_f(0.32);
-+CALL test_f(0.33);
-+CALL test_f(0.34);
-+CALL test_f(0.35);
-+CALL test_f(0.36);
-+CALL test_f(0.37);
-+CALL test_f(0.38);
-+CALL test_f(0.39);
-+CALL test_f(0.4);
-+CALL test_f(1.1);
-+CALL test_f(1.2);
-+CALL test_f(1.3);
-+CALL test_f(1.5);
-+CALL test_f(1.4);
-+CALL test_f(0.5);
-+CALL test_f(2.1);
-+CALL test_f(2.3);
-+CALL test_f(2.5);
-+CALL test_f(3.1);
-+CALL test_f(4.1);
-+CALL test_f(5.1);
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 10
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 45 0.000000
-+ 0.000010 0 0.000000
-+ 0.000100 0 0.000000
-+ 0.001000 0 0.000000
-+ 0.010000 0 0.000000
-+ 0.100000 0 0.000000
-+ 1.000000 55 8.450000
-+ 10.000000 11 25.699999
-+ 100.000000 0 0.000000
-+ 1000.000000 0 0.000000
-+ 10000.000000 0 0.000000
-+ 100000.000000 0 0.000000
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 45 0.000000
-+ 0.000010 0 0.000000
-+ 0.000100 0 0.000000
-+ 0.001000 0 0.000000
-+ 0.010000 0 0.000000
-+ 0.100000 0 0.000000
-+ 1.000000 55 8.450000
-+ 10.000000 11 25.699999
-+ 100.000000 0 0.000000
-+ 1000.000000 0 0.000000
-+ 10000.000000 0 0.000000
-+ 100000.000000 0 0.000000
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET SESSION query_exec_time=default;
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=7;
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+CALL test_f(0.31);
-+CALL test_f(0.32);
-+CALL test_f(0.33);
-+CALL test_f(0.34);
-+CALL test_f(0.35);
-+CALL test_f(0.36);
-+CALL test_f(0.37);
-+CALL test_f(0.38);
-+CALL test_f(0.39);
-+CALL test_f(0.4);
-+CALL test_f(1.1);
-+CALL test_f(1.2);
-+CALL test_f(1.3);
-+CALL test_f(1.5);
-+CALL test_f(1.4);
-+CALL test_f(0.5);
-+CALL test_f(2.1);
-+CALL test_f(2.3);
-+CALL test_f(2.5);
-+CALL test_f(3.1);
-+CALL test_f(4.1);
-+CALL test_f(5.1);
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 7
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 45 0.000000
-+ 0.000008 0 0.000000
-+ 0.000059 0 0.000000
-+ 0.000416 0 0.000000
-+ 0.002915 0 0.000000
-+ 0.020408 0 0.000000
-+ 0.142857 44 4.400000
-+ 1.000000 11 4.050000
-+ 7.000000 11 25.699999
-+ 49.000000 0 0.000000
-+ 343.000000 0 0.000000
-+ 2401.000000 0 0.000000
-+ 16807.000000 0 0.000000
-+ 117649.000000 0 0.000000
-+ 823543.000000 0 0.000000
-+5764801.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 45 0.000000
-+ 0.000008 0 0.000000
-+ 0.000059 0 0.000000
-+ 0.000416 0 0.000000
-+ 0.002915 0 0.000000
-+ 0.020408 0 0.000000
-+ 0.142857 44 4.400000
-+ 1.000000 11 4.050000
-+ 7.000000 11 25.699999
-+ 49.000000 0 0.000000
-+ 343.000000 0 0.000000
-+ 2401.000000 0 0.000000
-+ 16807.000000 0 0.000000
-+ 117649.000000 0 0.000000
-+ 823543.000000 0 0.000000
-+5764801.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET SESSION query_exec_time=default;
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=156;
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+CALL test_f(0.31);
-+CALL test_f(0.32);
-+CALL test_f(0.33);
-+CALL test_f(0.34);
-+CALL test_f(0.35);
-+CALL test_f(0.36);
-+CALL test_f(0.37);
-+CALL test_f(0.38);
-+CALL test_f(0.39);
-+CALL test_f(0.4);
-+CALL test_f(1.1);
-+CALL test_f(1.2);
-+CALL test_f(1.3);
-+CALL test_f(1.5);
-+CALL test_f(1.4);
-+CALL test_f(0.5);
-+CALL test_f(2.1);
-+CALL test_f(2.3);
-+CALL test_f(2.5);
-+CALL test_f(3.1);
-+CALL test_f(4.1);
-+CALL test_f(5.1);
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 156
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000041 45 0.000000
-+ 0.006410 0 0.000000
-+ 1.000000 55 8.450000
-+ 156.000000 11 25.699999
-+ 24336.000000 0 0.000000
-+3796416.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000041 45 0.000000
-+ 0.006410 0 0.000000
-+ 1.000000 55 8.450000
-+ 156.000000 11 25.699999
-+ 24336.000000 0 0.000000
-+3796416.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET SESSION query_exec_time=default;
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1000;
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+CALL test_f(0.31);
-+CALL test_f(0.32);
-+CALL test_f(0.33);
-+CALL test_f(0.34);
-+CALL test_f(0.35);
-+CALL test_f(0.36);
-+CALL test_f(0.37);
-+CALL test_f(0.38);
-+CALL test_f(0.39);
-+CALL test_f(0.4);
-+CALL test_f(1.1);
-+CALL test_f(1.2);
-+CALL test_f(1.3);
-+CALL test_f(1.5);
-+CALL test_f(1.4);
-+CALL test_f(0.5);
-+CALL test_f(2.1);
-+CALL test_f(2.3);
-+CALL test_f(2.5);
-+CALL test_f(3.1);
-+CALL test_f(4.1);
-+CALL test_f(5.1);
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 1000
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 45 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 55 8.450000
-+ 1000.000000 11 25.699999
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 45 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 55 8.450000
-+ 1000.000000 11 25.699999
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET SESSION query_exec_time=default;
-+SET SESSION query_exec_time=0.1;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1001;
-+Warnings:
-+Warning 1292 Truncated incorrect query_response_time_range_base value: '1001'
-+FLUSH QUERY_RESPONSE_TIME;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=1;
-+CALL test_f(0.31);
-+CALL test_f(0.32);
-+CALL test_f(0.33);
-+CALL test_f(0.34);
-+CALL test_f(0.35);
-+CALL test_f(0.36);
-+CALL test_f(0.37);
-+CALL test_f(0.38);
-+CALL test_f(0.39);
-+CALL test_f(0.4);
-+CALL test_f(1.1);
-+CALL test_f(1.2);
-+CALL test_f(1.3);
-+CALL test_f(1.5);
-+CALL test_f(1.4);
-+CALL test_f(0.5);
-+CALL test_f(2.1);
-+CALL test_f(2.3);
-+CALL test_f(2.5);
-+CALL test_f(3.1);
-+CALL test_f(4.1);
-+CALL test_f(5.1);
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=0;
-+SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE';
-+Variable_name Value
-+query_response_time_range_base 1000
-+SHOW QUERY_RESPONSE_TIME;
-+
-+ 0.000001 45 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 55 8.450000
-+ 1000.000000 11 25.699999
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
-+time count total
-+ 0.000001 45 0.000000
-+ 0.001000 0 0.000000
-+ 1.000000 55 8.450000
-+ 1000.000000 11 25.699999
-+1000000.000000 0 0.000000
-+TOO LONG 0 TOO LONG
-+SET SESSION query_exec_time=default;
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
-+DROP PROCEDURE test_f;
-+DROP TABLE t;
---- /dev/null
-+++ b/mysql-test/t/percona_query_response_time-replication.test
-@@ -0,0 +1,28 @@
-+SET GLOBAL query_exec_time=0.1;
-+
-+--source include/have_response_time_distribution.inc
-+--source include/have_debug.inc
-+--source include/have_binlog_format_statement.inc
-+--source include/master-slave.inc
-+
-+--let base=1
-+--source include/query_response_time-replication.inc
-+--let base=2
-+--source include/query_response_time-replication.inc
-+--let base=10
-+--source include/query_response_time-replication.inc
-+--let base=7
-+--source include/query_response_time-replication.inc
-+--let base=156
-+--source include/query_response_time-replication.inc
-+--let base=1000
-+--source include/query_response_time-replication.inc
-+--let base=1001
-+--source include/query_response_time-replication.inc
-+
-+--source include/rpl_end.inc
-+
-+SET GLOBAL query_exec_time=default;
-+
-+connection slave;
-+SET GLOBAL query_exec_time=default;
---- /dev/null
-+++ b/mysql-test/t/percona_query_response_time-stored.test
-@@ -0,0 +1,36 @@
-+--source include/have_response_time_distribution.inc
-+--source include/have_debug.inc
-+
-+CREATE TABLE t(a INT);
-+
-+delimiter ^;
-+CREATE PROCEDURE test_f(t DECIMAL(3,2))
-+BEGIN
-+ SET SESSION query_exec_time=t;
-+ INSERT INTO t VALUES(1);
-+ SET SESSION query_exec_time=0.1;
-+ DELETE FROM t;
-+END^
-+delimiter ;^
-+
-+--let base=1
-+--source include/query_response_time-stored.inc
-+--let base=2
-+--source include/query_response_time-stored.inc
-+--let base=10
-+--source include/query_response_time-stored.inc
-+--let base=7
-+--source include/query_response_time-stored.inc
-+--let base=156
-+--source include/query_response_time-stored.inc
-+--let base=1000
-+--source include/query_response_time-stored.inc
-+--let base=1001
-+--source include/query_response_time-stored.inc
-+
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
-+
-+DROP PROCEDURE test_f;
-+
-+DROP TABLE t;
---- /dev/null
-+++ b/mysql-test/t/percona_query_response_time.test
-@@ -0,0 +1,20 @@
-+--source include/have_response_time_distribution.inc
-+--source include/have_debug.inc
-+
-+--let base=1
-+--source include/query_response_time.inc
-+--let base=2
-+--source include/query_response_time.inc
-+--let base=10
-+--source include/query_response_time.inc
-+--let base=7
-+--source include/query_response_time.inc
-+--let base=156
-+--source include/query_response_time.inc
-+--let base=1000
-+--source include/query_response_time.inc
-+--let base=1001
-+--source include/query_response_time.inc
-+
-+SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default;
-+SET GLOBAL QUERY_RESPONSE_TIME_STATS=default;
---- /dev/null
-+++ b/patch_info/response-time-distribution.info
-@@ -0,0 +1,9 @@
-+File=response-time-distribution.patch
-+Name=Response time distribution
-+Version=1.0
-+Author=Percona <info@percona.com>
-+License=GPL
-+Comment=
-+Changelog
-+2010-07-02 first version avaliable
-+2010-09-15 add column 'total'
---- a/sql/CMakeLists.txt
-+++ b/sql/CMakeLists.txt
-@@ -52,7 +52,7 @@
- message.h mf_iocache.cc my_decimal.cc ../sql-common/my_time.c
- mysqld.cc net_serv.cc keycaches.cc
- ../sql-common/client_plugin.c
-- opt_range.cc opt_range.h opt_sum.cc
-+ opt_range.cc opt_range.h query_response_time.h opt_sum.cc
- ../sql-common/pack.c parse_file.cc password.c procedure.cc
- protocol.cc records.cc repl_failsafe.cc rpl_filter.cc set_var.cc
- slave.cc sp.cc sp_cache.cc sp_head.cc sp_pcontext.cc
-@@ -60,7 +60,7 @@
- sql_cache.cc sql_class.cc sql_client.cc sql_crypt.cc sql_crypt.h
- sql_cursor.cc sql_db.cc sql_delete.cc sql_derived.cc sql_do.cc
- sql_error.cc sql_handler.cc sql_help.cc sql_insert.cc sql_lex.cc
-- sql_list.cc sql_load.cc sql_manager.cc sql_parse.cc
-+ sql_list.cc sql_load.cc sql_manager.cc sql_parse.cc query_response_time.cc
- sql_partition.cc sql_plugin.cc sql_prepare.cc sql_rename.cc
- debug_sync.cc debug_sync.h
- sql_repl.cc sql_select.cc sql_show.cc sql_state.c sql_string.cc
---- a/sql/handler.h
-+++ b/sql/handler.h
-@@ -581,6 +581,7 @@
- SCH_PROFILES,
- SCH_REFERENTIAL_CONSTRAINTS,
- SCH_PROCEDURES,
-+ SCH_QUERY_RESPONSE_TIME,
- SCH_SCHEMATA,
- SCH_SCHEMA_PRIVILEGES,
- SCH_SESSION_STATUS,
---- a/sql/lex.h
-+++ b/sql/lex.h
-@@ -426,6 +426,7 @@
- { "PURGE", SYM(PURGE)},
- { "QUARTER", SYM(QUARTER_SYM)},
- { "QUERY", SYM(QUERY_SYM)},
-+ { "QUERY_RESPONSE_TIME", SYM(QUERY_RESPONSE_TIME_SYM)},
- { "QUICK", SYM(QUICK)},
- { "RANGE", SYM(RANGE_SYM)},
- { "READ", SYM(READ_SYM)},
---- a/sql/mysqld.cc
-+++ b/sql/mysqld.cc
-@@ -69,6 +69,8 @@
- #include "debug_sync.h"
- #include "sql_callback.h"
-
-+#include "query_response_time.h"
-+
- #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
- #include "../storage/perfschema/pfs_server.h"
- #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
-@@ -615,7 +617,7 @@
- MY_LOCALE *my_default_lc_messages;
- MY_LOCALE *my_default_lc_time_names;
-
--SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache;
-+SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache, have_response_time_distribution;
- SHOW_COMP_OPTION have_geometry, have_rtree_keys;
- SHOW_COMP_OPTION have_crypt, have_compress;
- SHOW_COMP_OPTION have_profiling;
-@@ -917,6 +919,10 @@
- my_bool opt_enable_shared_memory;
- HANDLE smem_event_connect_request= 0;
- #endif
-+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
-+ulong opt_query_response_time_range_base = QRT_DEFAULT_BASE;
-+my_bool opt_query_response_time_stats= 0;
-+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
-
- my_bool opt_use_ssl = 0;
- char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL,
-@@ -1488,6 +1494,9 @@
- my_free(opt_bin_logname);
- bitmap_free(&temp_pool);
- free_max_user_conn();
-+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
-+ query_response_time_free();
-+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
- #ifdef HAVE_REPLICATION
- end_slave_list();
- #endif
-@@ -3860,6 +3869,9 @@
- if (!DEFAULT_ERRMSGS[0][0])
- unireg_abort(1);
-
-+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
-+ query_response_time_init();
-+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
- /* We have to initialize the storage engines before CSV logging */
- if (ha_init())
- {
-@@ -6773,6 +6785,11 @@
- #else
- have_query_cache=SHOW_OPTION_NO;
- #endif
-+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
-+ have_response_time_distribution= SHOW_OPTION_YES;
-+#else // HAVE_RESPONSE_TIME_DISTRIBUTION
-+ have_response_time_distribution= SHOW_OPTION_NO;
-+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
- #ifdef HAVE_SPATIAL
- have_geometry=SHOW_OPTION_YES;
- #else
---- a/sql/mysqld.h
-+++ b/sql/mysqld.h
-@@ -98,6 +98,10 @@
- extern bool opt_disable_networking, opt_skip_show_db;
- extern bool opt_skip_name_resolve;
- extern bool opt_ignore_builtin_innodb;
-+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
-+extern ulong opt_query_response_time_range_base;
-+extern my_bool opt_query_response_time_stats;
-+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
- extern my_bool opt_character_set_client_handshake;
- extern bool volatile abort_loop;
- extern bool in_bootstrap;
---- /dev/null
-+++ b/sql/query_response_time.cc
-@@ -0,0 +1,302 @@
-+#include "mysql_version.h"
-+#include "my_global.h"
-+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
-+#include "mysql_com.h"
-+#include "rpl_tblmap.h"
-+#include "table.h"
-+#include "field.h"
-+#include "sql_show.h"
-+#include "query_response_time.h"
-+
-+#define TIME_STRING_POSITIVE_POWER_LENGTH QRT_TIME_STRING_POSITIVE_POWER_LENGTH
-+#define TIME_STRING_NEGATIVE_POWER_LENGTH 6
-+#define TOTAL_STRING_POSITIVE_POWER_LENGTH QRT_TOTAL_STRING_POSITIVE_POWER_LENGTH
-+#define TOTAL_STRING_NEGATIVE_POWER_LENGTH 6
-+#define MINIMUM_BASE 2
-+#define MAXIMUM_BASE QRT_MAXIMUM_BASE
-+#define POSITIVE_POWER_FILLER QRT_POSITIVE_POWER_FILLER
-+#define NEGATIVE_POWER_FILLER QRT_NEGATIVE_POWER_FILLER
-+#define TIME_OVERFLOW QRT_TIME_OVERFLOW
-+#define DEFAULT_BASE QRT_DEFAULT_BASE
-+
-+#define do_xstr(s) do_str(s)
-+#define do_str(s) #s
-+#define do_format(filler,width) "%" filler width "lld"
-+/*
-+ Format strings for snprintf. Generate from:
-+ POSITIVE_POWER_FILLER and TIME_STRING_POSITIVE_POWER_LENGTH
-+ NEFATIVE_POWER_FILLER and TIME_STRING_NEGATIVE_POWER_LENGTH
-+*/
-+#define TIME_STRING_POSITIVE_POWER_FORMAT do_format(POSITIVE_POWER_FILLER,do_xstr(TIME_STRING_POSITIVE_POWER_LENGTH))
-+#define TIME_STRING_NEGATIVE_POWER_FORMAT do_format(NEGATIVE_POWER_FILLER,do_xstr(TIME_STRING_NEGATIVE_POWER_LENGTH))
-+#define TIME_STRING_FORMAT TIME_STRING_POSITIVE_POWER_FORMAT "." TIME_STRING_NEGATIVE_POWER_FORMAT
-+
-+#define TOTAL_STRING_POSITIVE_POWER_FORMAT do_format(POSITIVE_POWER_FILLER,do_xstr(TOTAL_STRING_POSITIVE_POWER_LENGTH))
-+#define TOTAL_STRING_NEGATIVE_POWER_FORMAT do_format(NEGATIVE_POWER_FILLER,do_xstr(TOTAL_STRING_NEGATIVE_POWER_LENGTH))
-+#define TOTAL_STRING_FORMAT TOTAL_STRING_POSITIVE_POWER_FORMAT "." TOTAL_STRING_NEGATIVE_POWER_FORMAT
-+
-+#define TIME_STRING_LENGTH QRT_TIME_STRING_LENGTH
-+#define TIME_STRING_BUFFER_LENGTH (TIME_STRING_LENGTH + 1 /* '\0' */)
-+
-+#define TOTAL_STRING_LENGTH QRT_TOTAL_STRING_LENGTH
-+#define TOTAL_STRING_BUFFER_LENGTH (TOTAL_STRING_LENGTH + 1 /* '\0' */)
-+
-+/*
-+ Calculate length of "log linear"
-+ 1)
-+ (MINIMUM_BASE ^ result) <= (10 ^ STRING_POWER_LENGTH) < (MINIMUM_BASE ^ (result + 1))
-+
-+ 2)
-+ (MINIMUM_BASE ^ result) <= (10 ^ STRING_POWER_LENGTH)
-+ and
-+ (MINIMUM_BASE ^ (result + 1)) > (10 ^ STRING_POWER_LENGTH)
-+
-+ 3)
-+ result <= LOG(MINIMUM_BASE, 10 ^ STRING_POWER_LENGTH)= STRING_POWER_LENGTH * LOG(MINIMUM_BASE,10)
-+ result + 1 > LOG(MINIMUM_BASE, 10 ^ STRING_POWER_LENGTH)= STRING_POWER_LENGTH * LOG(MINIMUM_BASE,10)
-+
-+ 4) STRING_POWER_LENGTH * LOG(MINIMUM_BASE,10) - 1 < result <= STRING_POWER_LENGTH * LOG(MINIMUM_BASE,10)
-+
-+ MINIMUM_BASE= 2 always, LOG(MINIMUM_BASE,10)= 3.3219280948873626, result= (int)3.3219280948873626 * STRING_POWER_LENGTH
-+
-+ Last counter always use for time overflow
-+*/
-+#define POSITIVE_POWER_COUNT ((int)(3.32192809 * TIME_STRING_POSITIVE_POWER_LENGTH))
-+#define NEGATIVE_POWER_COUNT ((int)(3.32192809 * TIME_STRING_NEGATIVE_POWER_LENGTH))
-+#define OVERALL_POWER_COUNT (NEGATIVE_POWER_COUNT + 1 + POSITIVE_POWER_COUNT)
-+
-+#define MILLION ((unsigned long)1000 * 1000)
-+
-+namespace query_response_time
-+{
-+
-+class utility
-+{
-+public:
-+ utility() : m_base(0)
-+ {
-+ m_max_dec_value= MILLION;
-+ for(int i= 0; TIME_STRING_POSITIVE_POWER_LENGTH > i; ++i)
-+ m_max_dec_value *= 10;
-+ setup(DEFAULT_BASE);
-+ }
-+public:
-+ uint base() const { return m_base; }
-+ uint negative_count() const { return m_negative_count; }
-+ uint positive_count() const { return m_positive_count; }
-+ uint bound_count() const { return m_bound_count; }
-+ ulonglong max_dec_value() const { return m_max_dec_value; }
-+ ulonglong bound(uint index) const { return m_bound[ index ]; }
-+public:
-+ void setup(uint base)
-+ {
-+ if(base != m_base)
-+ {
-+ m_base= base;
-+
-+ const ulonglong million= 1000 * 1000;
-+ ulonglong value= million;
-+ m_negative_count= 0;
-+ while(value > 0)
-+ {
-+ m_negative_count += 1;
-+ value /= m_base;
-+ }
-+ m_negative_count -= 1;
-+
-+ value= million;
-+ m_positive_count= 0;
-+ while(value < m_max_dec_value)
-+ {
-+ m_positive_count += 1;
-+ value *= m_base;
-+ }
-+ m_bound_count= m_negative_count + m_positive_count;
-+
-+ value= million;
-+ for(uint i= 0; i < m_negative_count; ++i)
-+ {
-+ value /= m_base;
-+ m_bound[m_negative_count - i - 1]= value;
-+ }
-+ value= million;
-+ for(uint i= 0; i < m_positive_count; ++i)
-+ {
-+ m_bound[m_negative_count + i]= value;
-+ value *= m_base;
-+ }
-+ }
-+ }
-+private:
-+ uint m_base;
-+ uint m_negative_count;
-+ uint m_positive_count;
-+ uint m_bound_count;
-+ ulonglong m_max_dec_value; /* for TIME_STRING_POSITIVE_POWER_LENGTH=7 is 10000000 */
-+ ulonglong m_bound[OVERALL_POWER_COUNT];
-+};
-+
-+static
-+void print_time(char* buffer, std::size_t buffer_size, const char* format,
-+ uint64 value)
-+{
-+ ulonglong second= (value / MILLION);
-+ ulonglong microsecond= (value % MILLION);
-+ my_snprintf(buffer, buffer_size, format, second, microsecond);
-+}
-+
-+class time_collector
-+{
-+public:
-+ time_collector(utility& u) : m_utility(&u)
-+ {
-+ my_atomic_rwlock_init(&time_collector_lock);
-+ }
-+ ~time_collector()
-+ {
-+ my_atomic_rwlock_destroy(&time_collector_lock);
-+ }
-+ uint32 count(uint index) const
-+ {
-+ my_atomic_rwlock_rdlock(&time_collector_lock);
-+ uint32 result= my_atomic_load32((int32*)&m_count[index]);
-+ my_atomic_rwlock_rdunlock(&time_collector_lock);
-+ return result;
-+ }
-+ uint64 total(uint index) const
-+ {
-+ my_atomic_rwlock_rdlock(&time_collector_lock);
-+ uint64 result= my_atomic_load64((int64*)&m_total[index]);
-+ my_atomic_rwlock_rdunlock(&time_collector_lock);
-+ return result;
-+ }
-+public:
-+ void flush()
-+ {
-+ my_atomic_rwlock_wrlock(&time_collector_lock);
-+ memset((void*)&m_count,0,sizeof(m_count));
-+ memset((void*)&m_total,0,sizeof(m_total));
-+ my_atomic_rwlock_wrunlock(&time_collector_lock);
-+ }
-+ void collect(uint64 time)
-+ {
-+ int i= 0;
-+ for(int count= m_utility->bound_count(); count > i; ++i)
-+ {
-+ if(m_utility->bound(i) > time)
-+ {
-+ my_atomic_rwlock_wrlock(&time_collector_lock);
-+ my_atomic_add32((int32*)(&m_count[i]), 1);
-+ my_atomic_add64((int64*)(&m_total[i]), time);
-+ my_atomic_rwlock_wrunlock(&time_collector_lock);
-+ break;
-+ }
-+ }
-+ }
-+private:
-+ utility* m_utility;
-+ /* The lock for atomic operations on m_count and m_total. Only actually
-+ used on architectures that do not have atomic implementation of atomic
-+ operations. */
-+ my_atomic_rwlock_t time_collector_lock;
-+ uint32 m_count[OVERALL_POWER_COUNT + 1];
-+ uint64 m_total[OVERALL_POWER_COUNT + 1];
-+};
-+
-+class collector
-+{
-+public:
-+ collector() : m_time(m_utility)
-+ {
-+ m_utility.setup(DEFAULT_BASE);
-+ m_time.flush();
-+ }
-+public:
-+ void flush()
-+ {
-+ m_utility.setup(opt_query_response_time_range_base);
-+ m_time.flush();
-+ }
-+ int fill(THD* thd, TABLE_LIST *tables, COND *cond)
-+ {
-+ DBUG_ENTER("fill_schema_query_response_time");
-+ TABLE *table= static_cast<TABLE*>(tables->table);
-+ Field **fields= table->field;
-+ for(uint i= 0, count= bound_count() + 1 /* with overflow */; count > i; ++i)
-+ {
-+ char time[TIME_STRING_BUFFER_LENGTH];
-+ char total[TOTAL_STRING_BUFFER_LENGTH];
-+ if(i == bound_count())
-+ {
-+ assert(sizeof(TIME_OVERFLOW) <= TIME_STRING_BUFFER_LENGTH);
-+ assert(sizeof(TIME_OVERFLOW) <= TOTAL_STRING_BUFFER_LENGTH);
-+ memcpy(time,TIME_OVERFLOW,sizeof(TIME_OVERFLOW));
-+ memcpy(total,TIME_OVERFLOW,sizeof(TIME_OVERFLOW));
-+ }
-+ else
-+ {
-+ print_time(time, sizeof(time), TIME_STRING_FORMAT, this->bound(i));
-+ print_time(total, sizeof(total), TOTAL_STRING_FORMAT, this->total(i));
-+ }
-+ fields[0]->store(time,strlen(time),system_charset_info);
-+ fields[1]->store(this->count(i));
-+ fields[2]->store(total,strlen(total),system_charset_info);
-+ if (schema_table_store_record(thd, table))
-+ {
-+ DBUG_RETURN(1);
-+ }
-+ }
-+ DBUG_RETURN(0);
-+ }
-+ void collect(ulonglong time)
-+ {
-+ m_time.collect(time);
-+ }
-+ uint bound_count() const
-+ {
-+ return m_utility.bound_count();
-+ }
-+ ulonglong bound(uint index)
-+ {
-+ return m_utility.bound(index);
-+ }
-+ ulonglong count(uint index)
-+ {
-+ return m_time.count(index);
-+ }
-+ ulonglong total(uint index)
-+ {
-+ return m_time.total(index);
-+ }
-+private:
-+ utility m_utility;
-+ time_collector m_time;
-+};
-+
-+static collector g_collector;
-+
-+} // namespace query_response_time
-+
-+void query_response_time_init()
-+{
-+}
-+
-+void query_response_time_free()
-+{
-+ query_response_time::g_collector.flush();
-+}
-+
-+void query_response_time_flush()
-+{
-+ query_response_time::g_collector.flush();
-+}
-+void query_response_time_collect(ulonglong query_time)
-+{
-+ query_response_time::g_collector.collect(query_time);
-+}
-+
-+int query_response_time_fill(THD* thd, TABLE_LIST *tables, COND *cond)
-+{
-+ return query_response_time::g_collector.fill(thd,tables,cond);
-+}
-+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
---- /dev/null
-+++ b/sql/query_response_time.h
-@@ -0,0 +1,64 @@
-+#ifndef QUERY_RESPONSE_TIME_H
-+#define QUERY_RESPONSE_TIME_H
-+
-+/*
-+ Settings for query response time
-+*/
-+
-+/*
-+ Maximum string length for (10 ^ (-1 * QRT_STRING_NEGATIVE_POWER_LENGTH)) in text representation.
-+ Example: for 6 is 0.000001
-+ Always 2
-+
-+ Maximum string length for (10 ^ (QRT_STRING_POSITIVE_POWER_LENGTH + 1) - 1) in text representation.
-+ Example: for 7 is 9999999.0
-+*/
-+#define QRT_TIME_STRING_POSITIVE_POWER_LENGTH 7
-+#define QRT_TOTAL_STRING_POSITIVE_POWER_LENGTH 7
-+
-+/*
-+ Minimum base for log - ALWAYS 2
-+ Maximum base for log:
-+*/
-+#define QRT_MAXIMUM_BASE 1000
-+
-+/*
-+ Filler for whole number (positive power)
-+ Example: for
-+ QRT_POSITIVE_POWER_FILLER ' '
-+ QRT_POSITIVE_POWER_LENGTH 7
-+ and number 7234 result is:
-+ ' 7234'
-+*/
-+#define QRT_POSITIVE_POWER_FILLER ""
-+/*
-+ Filler for fractional number. Similiary to whole number
-+*/
-+#define QRT_NEGATIVE_POWER_FILLER "0"
-+
-+/*
-+ Message if time too big for statistic collecting (very long query)
-+*/
-+#define QRT_TIME_OVERFLOW "TOO LONG"
-+
-+#define QRT_DEFAULT_BASE 10
-+
-+#define QRT_TIME_STRING_LENGTH \
-+ max( (QRT_TIME_STRING_POSITIVE_POWER_LENGTH + 1 /* '.' */ + 6 /*QRT_TIME_STRING_NEGATIVE_POWER_LENGTH*/), \
-+ (sizeof(QRT_TIME_OVERFLOW) - 1) )
-+
-+#define QRT_TOTAL_STRING_LENGTH \
-+ max( (QRT_TOTAL_STRING_POSITIVE_POWER_LENGTH + 1 /* '.' */ + 6 /*QRT_TOTAL_STRING_NEGATIVE_POWER_LENGTH*/), \
-+ (sizeof(QRT_TIME_OVERFLOW) - 1) )
-+
-+extern ST_SCHEMA_TABLE query_response_time_table;
-+
-+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
-+extern void query_response_time_init ();
-+extern void query_response_time_free ();
-+extern void query_response_time_flush ();
-+extern void query_response_time_collect(ulonglong query_time);
-+extern int query_response_time_fill (THD* thd, TABLE_LIST *tables, COND *cond);
-+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
-+
-+#endif // QUERY_RESPONSE_TIME_H
---- a/sql/set_var.h
-+++ b/sql/set_var.h
-@@ -294,6 +294,7 @@
-
- extern SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen;
- extern SHOW_COMP_OPTION have_query_cache;
-+extern SHOW_COMP_OPTION have_response_time_distribution;
- extern SHOW_COMP_OPTION have_geometry, have_rtree_keys;
- extern SHOW_COMP_OPTION have_crypt;
- extern SHOW_COMP_OPTION have_compress;
---- a/sql/sql_parse.cc
-+++ b/sql/sql_parse.cc
-@@ -88,6 +88,7 @@
- #include "sp_cache.h"
- #include "events.h"
- #include "sql_trigger.h"
-+#include "query_response_time.h"
- #include "transaction.h"
- #include "sql_audit.h"
- #include "sql_prepare.h"
-@@ -1518,6 +1519,12 @@
-
- ulonglong end_utime_of_query= thd->current_utime();
- ulonglong query_exec_time= get_query_exec_time(thd, end_utime_of_query);
-+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
-+ if (opt_query_response_time_stats)
-+ {
-+ query_response_time_collect(query_exec_time);
-+ }
-+#endif
-
- /*
- Low long_query_time value most likely means user is debugging stuff and even
-@@ -1682,6 +1689,7 @@
- case SCH_CHARSETS:
- case SCH_ENGINES:
- case SCH_COLLATIONS:
-+ case SCH_QUERY_RESPONSE_TIME:
- case SCH_COLLATION_CHARACTER_SET_APPLICABILITY:
- case SCH_USER_PRIVILEGES:
- case SCH_SCHEMA_PRIVILEGES:
---- a/sql/sql_reload.cc
-+++ b/sql/sql_reload.cc
-@@ -25,7 +25,7 @@
- #include "hostname.h" // hostname_cache_refresh
- #include "sql_repl.h" // reset_master, reset_slave
- #include "debug_sync.h"
--
-+#include "query_response_time.h"
-
- /**
- Reload/resets privileges and the different caches.
-@@ -322,6 +322,12 @@
- #endif
- if (options & REFRESH_USER_RESOURCES)
- reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */
-+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
-+ if (options & REFRESH_QUERY_RESPONSE_TIME)
-+ {
-+ query_response_time_flush();
-+ }
-+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
- if (*write_to_binlog != -1)
- *write_to_binlog= tmp_write_to_binlog;
- /*
---- a/sql/sql_show.cc
-+++ b/sql/sql_show.cc
-@@ -50,6 +50,7 @@
- #include "event_data_objects.h"
- #endif
- #include <my_dir.h>
-+#include "query_response_time.h"
- #include "lock.h" // MYSQL_OPEN_IGNORE_FLUSH
- #include "debug_sync.h"
- #include "datadict.h" // dd_frm_type()
-@@ -7888,6 +7889,14 @@
-
- */
-
-+ST_FIELD_INFO query_response_time_fields_info[] =
-+ {
-+ {"time", QRT_TIME_STRING_LENGTH, MYSQL_TYPE_STRING, 0, 0, "", SKIP_OPEN_TABLE },
-+ {"count", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, MY_I_S_UNSIGNED, "", SKIP_OPEN_TABLE },
-+ {"total", QRT_TIME_STRING_LENGTH, MYSQL_TYPE_STRING, 0, 0, "", SKIP_OPEN_TABLE },
-+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE }
-+ };
-+
- ST_SCHEMA_TABLE schema_tables[]=
- {
- {"CHARACTER_SETS", charsets_fields_info, create_schema_table,
-@@ -7941,6 +7950,13 @@
- 1, 9, 0, OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY},
- {"ROUTINES", proc_fields_info, create_schema_table,
- fill_schema_proc, make_proc_old_format, 0, -1, -1, 0, 0},
-+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
-+ {"QUERY_RESPONSE_TIME", query_response_time_fields_info, create_schema_table,
-+ query_response_time_fill, make_old_format, 0, -1, -1, 0, 0},
-+#else
-+ {"QUERY_RESPONSE_TIME", query_response_time_fields_info, create_schema_table,
-+ 0, make_old_format, 0, -1, -1, 0, 0},
-+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
- {"SCHEMATA", schema_fields_info, create_schema_table,
- fill_schema_schemata, make_schemata_old_format, 0, 1, -1, 0, 0},
- {"SCHEMA_PRIVILEGES", schema_privileges_fields_info, create_schema_table,
---- a/sql/sql_yacc.yy
-+++ b/sql/sql_yacc.yy
-@@ -1194,6 +1194,7 @@
- %token PURGE
- %token QUARTER_SYM
- %token QUERY_SYM
-+%token QUERY_RESPONSE_TIME_SYM
- %token QUICK
- %token RANGE_SYM /* SQL-2003-R */
- %token READS_SYM /* SQL-2003-R */
-@@ -11105,6 +11106,15 @@
- {
- Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
- }
-+ | QUERY_RESPONSE_TIME_SYM wild_and_where
-+ {
-+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
-+ LEX *lex= Lex;
-+ lex->sql_command= SQLCOM_SELECT;
-+ if (prepare_schema_table(YYTHD, lex, 0, SCH_QUERY_RESPONSE_TIME))
-+ MYSQL_YYABORT;
-+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
-+ }
- | CREATE PROCEDURE_SYM sp_name
- {
- LEX *lex= Lex;
-@@ -11344,6 +11354,12 @@
- Lex->type|= REFRESH_SLAVE;
- Lex->reset_slave_info.all= false;
- }
-+ | QUERY_RESPONSE_TIME_SYM
-+ {
-+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
-+ Lex->type|= REFRESH_QUERY_RESPONSE_TIME;
-+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
-+ }
- | MASTER_SYM
- { Lex->type|= REFRESH_MASTER; }
- | DES_KEY_FILE
-@@ -12651,6 +12667,7 @@
- | PROXY_SYM {}
- | QUARTER_SYM {}
- | QUERY_SYM {}
-+ | QUERY_RESPONSE_TIME_SYM {}
- | QUICK {}
- | READ_ONLY_SYM {}
- | REBUILD_SYM {}
---- a/sql/sys_vars.cc
-+++ b/sql/sys_vars.cc
-@@ -51,6 +51,7 @@
-
- TYPELIB bool_typelib={ array_elements(bool_values)-1, "", bool_values, 0 };
-
-+#include "query_response_time.h"
- /*
- This forward declaration is needed because including sql_base.h
- causes further includes. [TODO] Eliminate this forward declaration
-@@ -1939,6 +1940,26 @@
- DEFAULT(FALSE));
- #endif /* HAVE_QUERY_CACHE */
-
-+
-+static Sys_var_have Sys_have_response_time_distribution(
-+ "have_response_time_distribution", "have_response_time_distribution",
-+ READ_ONLY GLOBAL_VAR(have_response_time_distribution), NO_CMD_LINE);
-+
-+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
-+static Sys_var_mybool Sys_query_response_time_stats(
-+ "query_response_time_stats", "Enable or disable query response time statisics collecting",
-+ GLOBAL_VAR(opt_query_response_time_stats), CMD_LINE(OPT_ARG),
-+ DEFAULT(FALSE));
-+
-+static Sys_var_ulong Sys_query_response_time_range_base(
-+ "query_response_time_range_base",
-+ "Select base of log for query_response_time ranges. WARNING: variable change affect only after flush",
-+ GLOBAL_VAR(opt_query_response_time_range_base),
-+ CMD_LINE(REQUIRED_ARG), VALID_RANGE(2, QRT_MAXIMUM_BASE),
-+ DEFAULT(QRT_DEFAULT_BASE),
-+ BLOCK_SIZE(1));
-+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
-+
- static Sys_var_mybool Sys_secure_auth(
- "secure_auth",
- "Disallow authentication for accounts that have old (pre-4.1) "
---- /dev/null
-+++ b/mysql-test/r/have_response_time_distribution.require
-@@ -0,0 +1,2 @@
-+Variable_name Value
-+have_response_time_distribution YES
---- a/include/atomic/x86-gcc.h
-+++ b/include/atomic/x86-gcc.h
-@@ -108,27 +108,23 @@
- v=tmp;
-
- /*
-- On some platforms (e.g. Mac OS X and Solaris) the ebx register
-- is held as a pointer to the global offset table. Thus we're not
-- allowed to use the b-register on those platforms when compiling
-- PIC code, to avoid this we push ebx and pop ebx. The new value
-- is copied directly from memory to avoid problems with a implicit
-- manipulation of the stack pointer by the push.
--
- cmpxchg8b works on both 32-bit platforms and 64-bit platforms but
- the code here is only used on 32-bit platforms, on 64-bit
- platforms the much simpler make_atomic_cas_body32 will work
- fine.
- */
--#define make_atomic_cas_body64 \
-- asm volatile ("push %%ebx;" \
-- "movl (%%ecx), %%ebx;" \
-- "movl 4(%%ecx), %%ecx;" \
-- LOCK_prefix "; cmpxchg8b %0;" \
-- "setz %2; pop %%ebx" \
-- : "=m" (*a), "+A" (*cmp), "=c" (ret) \
-- : "c" (&set), "m" (*a) \
-- : "memory", "esp")
-+#define make_atomic_cas_body64 \
-+ asm volatile ("movl %%edi, -4(%%esp);" \
-+ "leal %0, %%edi;" \
-+ "xchgl %%ebx, %%esi;" \
-+ LOCK_prefix "; cmpxchg8b (%%edi);" \
-+ "movl %%esi, %%ebx;" \
-+ "movl -4(%%esp), %%edi;" \
-+ "setz %1;" \
-+ : "+m" (*a), "=q" (ret), "+A" (*cmp) \
-+ : "S" ((int32)(set & 0xFFFFFFFF)), \
-+ "c" ((int32)(set >> 32)) \
-+ : "memory", "flags")
- #endif
-
- /*
---- a/mysql-test/r/mysqld--help-notwin.result
-+++ b/mysql-test/r/mysqld--help-notwin.result
-@@ -505,6 +505,12 @@
- Invalidate queries in query cache on LOCK for write
- --query-prealloc-size=#
- Persistent buffer for query parsing and execution
-+ --query-response-time-range-base=#
-+ Select base of log for query_response_time ranges.
-+ WARNING: variable change affect only after flush
-+ --query-response-time-stats
-+ Enable or disable query response time statisics
-+ collecting
- --range-alloc-block-size=#
- Allocation block size for storing ranges during
- optimization
-@@ -939,6 +945,8 @@
- query-cache-type ON
- query-cache-wlock-invalidate FALSE
- query-prealloc-size 8192
-+query-response-time-range-base 10
-+query-response-time-stats FALSE
- range-alloc-block-size 4096
- read-buffer-size 131072
- read-only FALSE
+++ /dev/null
-# name : show_slave_status_nolock.patch
-# introduced : 12
-# maintainer : Oleg
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- /dev/null
-+++ b/patch_info/show_slave_status_nolock.patch
-@@ -0,0 +1,6 @@
-+File=show_slave_status_nolock.patch
-+Name= SHOW SLAVE STATUS NOLOCK
-+Version=1.0
-+Author=Percona <info@percona.com>
-+License=GPL
-+Comment= Implement SHOW SLAVE STATUS without lock (STOP SLAVE lock the same mutex what lock SHOW SLAVE STATUS)
---- a/sql/lex.h
-+++ b/sql/lex.h
-@@ -378,6 +378,7 @@
- { "NONE", SYM(NONE_SYM)},
- { "NOT", SYM(NOT_SYM)},
- { "NO_WRITE_TO_BINLOG", SYM(NO_WRITE_TO_BINLOG)},
-+ { "NOLOCK", SYM(NOLOCK_SYM)},
- { "NULL", SYM(NULL_SYM)},
- { "NUMERIC", SYM(NUMERIC_SYM)},
- { "NVARCHAR", SYM(NVARCHAR_SYM)},
---- a/sql/mysqld.cc
-+++ b/sql/mysqld.cc
-@@ -2971,6 +2971,7 @@
- {"show_relaylog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_RELAYLOG_EVENTS]), SHOW_LONG_STATUS},
- {"show_slave_hosts", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_HOSTS]), SHOW_LONG_STATUS},
- {"show_slave_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS},
-+ {"show_slave_status_nolock", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_NOLOCK_STAT]), SHOW_LONG_STATUS},
- {"show_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS},
- {"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS},
- {"show_table_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATUS]), SHOW_LONG_STATUS},
---- a/sql/sql_lex.h
-+++ b/sql/sql_lex.h
-@@ -190,6 +190,8 @@
- SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES,
- SQLCOM_SIGNAL, SQLCOM_RESIGNAL,
- SQLCOM_SHOW_RELAYLOG_EVENTS,
-+ /* SHOW SLAVE STATUS NOLOCK */
-+ SQLCOM_SHOW_SLAVE_NOLOCK_STAT,
- /*
- When a command is added here, be sure it's also added in mysqld.cc
- in "struct show_var_st status_vars[]= {" ...
---- a/sql/sql_parse.cc
-+++ b/sql/sql_parse.cc
-@@ -336,6 +336,7 @@
- sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_SLAVE_STAT]= CF_STATUS_COMMAND;
-+ sql_command_flags[SQLCOM_SHOW_SLAVE_NOLOCK_STAT]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_CREATE_PROC]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_CREATE_FUNC]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_CREATE_TRIGGER]= CF_STATUS_COMMAND;
-@@ -2393,12 +2394,17 @@
- mysql_mutex_unlock(&LOCK_active_mi);
- break;
- }
-+ case SQLCOM_SHOW_SLAVE_NOLOCK_STAT:
- case SQLCOM_SHOW_SLAVE_STAT:
- {
- /* Accept one of two privileges */
- if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
- goto error;
-- mysql_mutex_lock(&LOCK_active_mi);
-+ bool do_lock=SQLCOM_SHOW_SLAVE_NOLOCK_STAT != lex->sql_command;
-+ if(do_lock)
-+ {
-+ mysql_mutex_lock(&LOCK_active_mi);
-+ }
- if (active_mi != NULL)
- {
- res = show_master_info(thd, active_mi);
-@@ -2409,7 +2415,19 @@
- WARN_NO_MASTER_INFO, ER(WARN_NO_MASTER_INFO));
- my_ok(thd);
- }
-- mysql_mutex_unlock(&LOCK_active_mi);
-+ if(do_lock)
-+ {
-+ mysql_mutex_unlock(&LOCK_active_mi);
-+ }
-+ DBUG_EXECUTE_IF("after_show_slave_status",
-+ {
-+ const char act[]=
-+ "now "
-+ "signal signal.after_show_slave_status";
-+ DBUG_ASSERT(opt_debug_sync_timeout > 0);
-+ DBUG_ASSERT(!debug_sync_set_action(current_thd,
-+ STRING_WITH_LEN(act)));
-+ };);
- break;
- }
- case SQLCOM_SHOW_MASTER_STAT:
---- a/sql/sql_yacc.yy
-+++ b/sql/sql_yacc.yy
-@@ -1293,6 +1293,7 @@
- %token STARTS_SYM
- %token START_SYM /* SQL-2003-R */
- %token STATUS_SYM
-+%token NOLOCK_SYM /* SHOW SLAVE STATUS NOLOCK */
- %token STDDEV_SAMP_SYM /* SQL-2003-N */
- %token STD_SYM
- %token STOP_SYM
-@@ -11111,6 +11112,11 @@
- {
- Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
- }
-+ /* SHOW SLAVE STATUS NOLOCK */
-+ | SLAVE STATUS_SYM NOLOCK_SYM
-+ {
-+ Lex->sql_command = SQLCOM_SHOW_SLAVE_NOLOCK_STAT; //SQLCOM_SHOW_SLAVE_NOLOCK_STAT;
-+ }
- | QUERY_RESPONSE_TIME_SYM wild_and_where
- {
- #ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
---- /dev/null
-+++ b/mysql-test/t/percona_show_slave_status_nolock.test
-@@ -0,0 +1,90 @@
-+--source include/master-slave.inc
-+--source include/have_debug_sync.inc
-+--source include/have_binlog_format_statement.inc
-+
-+call mtr.add_suppression("Slave SQL: Request to stop slave SQL Thread received while applying a group that has non-transactional changes");
-+
-+--let $rpl_connection_name=slave_lock
-+--let $rpl_server_number=2
-+--source include/rpl_connect.inc
-+
-+--let $rpl_connection_name=slave_nolock
-+--let $rpl_server_number=2
-+--source include/rpl_connect.inc
-+
-+--let $show_statement= SHOW PROCESSLIST
-+--let $field= Info
-+
-+connection master;
-+--echo [master]
-+--disable_warnings
-+DROP TABLE IF EXISTS t;
-+--enable_warnings
-+CREATE TABLE t(id INT);
-+sync_slave_with_master;
-+
-+connection slave;
-+--echo [slave]
-+SET DEBUG_SYNC='RESET';
-+SET GLOBAL DEBUG="+d,after_mysql_insert,after_show_slave_status";
-+
-+connection master;
-+--echo [master]
-+INSERT INTO t VALUES(0);
-+
-+connection slave;
-+--echo [slave]
-+--let $condition= 'INSERT INTO t VALUES(0)'
-+--source include/wait_show_condition.inc
-+
-+--echo check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - both should work fine
-+--source include/percona_show_slave_status_nolock.inc
-+
-+connection master;
-+--echo [master]
-+INSERT INTO t VALUES(1);
-+
-+connection slave;
-+--echo [slave]
-+--let $condition= 'INSERT INTO t VALUES(1)'
-+--source include/wait_show_condition.inc
-+
-+--let $rpl_connection_name=slave_stop
-+--let $rpl_server_number=2
-+--source include/rpl_connect.inc
-+
-+connection slave_stop;
-+--echo [slave_stop]
-+send STOP SLAVE;
-+
-+connection slave;
-+--echo [slave]
-+--let $condition= 'STOP SLAVE'
-+--source include/wait_show_condition.inc
-+
-+--echo check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - just NOLOCK version should works fine
-+--source include/percona_show_slave_status_nolock.inc
-+
-+
-+connection slave_stop;
-+--echo [slave_stop]
-+reap;
-+--source include/wait_for_slave_to_stop.inc
-+START SLAVE;
-+--source include/wait_for_slave_to_start.inc
-+
-+connection master;
-+--echo [master]
-+SET DEBUG_SYNC='RESET';
-+
-+connection slave;
-+--echo [slave]
-+SET GLOBAL DEBUG='';
-+SET DEBUG_SYNC='RESET';
-+
-+connection master;
-+--echo [master]
-+DROP TABLE t;
-+sync_slave_with_master;
-+
-+--source include/rpl_end.inc
---- /dev/null
-+++ b/mysql-test/r/percona_show_slave_status_nolock.result
-@@ -0,0 +1,69 @@
-+include/master-slave.inc
-+[connection master]
-+call mtr.add_suppression("Slave SQL: Request to stop slave SQL Thread received while applying a group that has non-transactional changes");
-+include/rpl_connect.inc [creating slave_lock]
-+include/rpl_connect.inc [creating slave_nolock]
-+[master]
-+DROP TABLE IF EXISTS t;
-+CREATE TABLE t(id INT);
-+[slave]
-+SET DEBUG_SYNC='RESET';
-+SET GLOBAL DEBUG="+d,after_mysql_insert,after_show_slave_status";
-+[master]
-+INSERT INTO t VALUES(0);
-+[slave]
-+check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - both should work fine
-+
-+[slave_lock]
-+SHOW SLAVE STATUS;
-+SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
-+SIGNAL after SHOW SLAVE STATUS is 'signal.after_show_slave_status'
-+[slave]
-+SET DEBUG_SYNC='now SIGNAL signal.empty';
-+[slave_nolock]
-+SHOW SLAVE STATUS NOLOCK;
-+SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
-+# should be 'signal.after_show_slave_status'
-+SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status'
-+[slave]
-+SET DEBUG_SYNC='now SIGNAL signal.continue';
-+[slave]
-+SET DEBUG_SYNC='now SIGNAL signal.empty';
-+
-+[master]
-+INSERT INTO t VALUES(1);
-+[slave]
-+include/rpl_connect.inc [creating slave_stop]
-+[slave_stop]
-+STOP SLAVE;
-+[slave]
-+check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - just NOLOCK version should works fine
-+
-+[slave_lock]
-+SHOW SLAVE STATUS;
-+SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
-+SIGNAL after SHOW SLAVE STATUS is 'signal.empty'
-+[slave]
-+SET DEBUG_SYNC='now SIGNAL signal.empty';
-+[slave_nolock]
-+SHOW SLAVE STATUS NOLOCK;
-+SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
-+# should be 'signal.after_show_slave_status'
-+SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status'
-+[slave]
-+SET DEBUG_SYNC='now SIGNAL signal.continue';
-+[slave]
-+SET DEBUG_SYNC='now SIGNAL signal.empty';
-+
-+[slave_stop]
-+include/wait_for_slave_to_stop.inc
-+START SLAVE;
-+include/wait_for_slave_to_start.inc
-+[master]
-+SET DEBUG_SYNC='RESET';
-+[slave]
-+SET GLOBAL DEBUG='';
-+SET DEBUG_SYNC='RESET';
-+[master]
-+DROP TABLE t;
-+include/rpl_end.inc
---- /dev/null
-+++ b/mysql-test/include/percona_show_slave_status_nolock.inc
-@@ -0,0 +1,56 @@
-+--echo
-+--disable_result_log
-+connection slave_lock;
-+--echo [slave_lock]
-+send SHOW SLAVE STATUS;
-+
-+connection slave;
-+--let $condition= 'SHOW SLAVE STATUS'
-+--source include/wait_show_condition.inc
-+
-+--disable_warnings
-+SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
-+--enable_warnings
-+
-+--let current=`SELECT SUBSTR(Variable_value FROM 22) FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE Variable_name = 'DEBUG_SYNC'`
-+--echo SIGNAL after SHOW SLAVE STATUS is $current
-+
-+connection slave;
-+--echo [slave]
-+SET DEBUG_SYNC='now SIGNAL signal.empty';
-+
-+connection slave_nolock;
-+--echo [slave_nolock]
-+send SHOW SLAVE STATUS NOLOCK;
-+
-+connection slave;
-+--let $condition= 'SHOW SLAVE STATUS NOLOCK'
-+--source include/wait_show_condition.inc
-+
-+--disable_warnings
-+SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
-+--enable_warnings
-+
-+--echo # should be 'signal.after_show_slave_status'
-+--let current=`SELECT SUBSTR(Variable_value FROM 22) FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE Variable_name = 'DEBUG_SYNC'`
-+--echo SIGNAL after SHOW SLAVE STATUS NOLOCK is $current
-+
-+connection slave;
-+--echo [slave]
-+SET DEBUG_SYNC='now SIGNAL signal.continue';
-+
-+connection slave_lock;
-+--disable_result_log
-+reap;
-+--enable_result_log
-+
-+connection slave_nolock;
-+--disable_result_log
-+reap;
-+--enable_result_log
-+
-+connection slave;
-+--echo [slave]
-+SET DEBUG_SYNC='now SIGNAL signal.empty';
-+--enable_result_log
-+--echo
---- a/sql/slave.cc
-+++ b/sql/slave.cc
-@@ -1816,6 +1816,7 @@
-
- if (mi->host[0])
- {
-+ bool do_lock=SQLCOM_SHOW_SLAVE_NOLOCK_STAT != thd->lex->sql_command;
- DBUG_PRINT("info",("host is set: '%s'", mi->host));
- String *packet= &thd->packet;
- protocol->prepare_for_resend();
-@@ -1824,9 +1825,15 @@
- slave_running can be accessed without run_lock but not other
- non-volotile members like mi->io_thd, which is guarded by the mutex.
- */
-- mysql_mutex_lock(&mi->run_lock);
-+ if (do_lock)
-+ {
-+ mysql_mutex_lock(&mi->run_lock);
-+ }
- protocol->store(mi->io_thd ? mi->io_thd->proc_info : "", &my_charset_bin);
-- mysql_mutex_unlock(&mi->run_lock);
-+ if (do_lock)
-+ {
-+ mysql_mutex_unlock(&mi->run_lock);
-+ }
-
- mysql_mutex_lock(&mi->data_lock);
- mysql_mutex_lock(&mi->rli.data_lock);
+++ /dev/null
-# name : show_temp.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/sql/handler.h
-+++ b/sql/handler.h
-@@ -570,6 +570,7 @@
- SCH_EVENTS,
- SCH_FILES,
- SCH_GLOBAL_STATUS,
-+ SCH_GLOBAL_TEMPORARY_TABLES,
- SCH_GLOBAL_VARIABLES,
- SCH_KEY_COLUMN_USAGE,
- SCH_OPEN_TABLES,
-@@ -591,6 +592,7 @@
- SCH_TABLE_CONSTRAINTS,
- SCH_TABLE_NAMES,
- SCH_TABLE_PRIVILEGES,
-+ SCH_TEMPORARY_TABLES,
- SCH_TRIGGERS,
- SCH_USER_PRIVILEGES,
- SCH_VARIABLES,
---- a/sql/mysqld.cc
-+++ b/sql/mysqld.cc
-@@ -2951,6 +2951,7 @@
- {"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS},
- {"show_table_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATUS]), SHOW_LONG_STATUS},
- {"show_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLES]), SHOW_LONG_STATUS},
-+ {"show_temporary_tables",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TEMPORARY_TABLES]), SHOW_LONG_STATUS},
- {"show_triggers", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TRIGGERS]), SHOW_LONG_STATUS},
- {"show_variables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS},
- {"show_warnings", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS},
-@@ -7670,6 +7671,7 @@
- PSI_mutex_key key_LOCK_des_key_file;
- #endif /* HAVE_OPENSSL */
-
-+PSI_mutex_key key_LOCK_temporary_tables;
- PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids,
- key_delayed_insert_mutex, key_hash_filo_lock, key_LOCK_active_mi,
- key_LOCK_connection_count, key_LOCK_crypt, key_LOCK_delayed_create,
-@@ -7723,6 +7725,7 @@
- { &key_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL},
- { &key_LOCK_table_share, "LOCK_table_share", PSI_FLAG_GLOBAL},
- { &key_LOCK_thd_data, "THD::LOCK_thd_data", 0},
-+ { &key_LOCK_temporary_tables, "THD::LOCK_temporary_tables", 0},
- { &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_GLOBAL},
- { &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_GLOBAL},
- { &key_LOG_LOCK_log, "LOG::LOCK_log", 0},
---- a/sql/sql_lex.h
-+++ b/sql/sql_lex.h
-@@ -194,6 +194,7 @@
- When a command is added here, be sure it's also added in mysqld.cc
- in "struct show_var_st status_vars[]= {" ...
- */
-+ SQLCOM_SHOW_TEMPORARY_TABLES,
- /* This should be the last !!! */
- SQLCOM_END
- };
---- a/sql/sql_parse.cc
-+++ b/sql/sql_parse.cc
-@@ -348,6 +348,9 @@
- sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND |
- CF_SHOW_TABLE_COMMAND |
- CF_REEXECUTION_FRAGILE);
-+ sql_command_flags[SQLCOM_SHOW_TEMPORARY_TABLES]= (CF_STATUS_COMMAND |
-+ CF_SHOW_TABLE_COMMAND |
-+ CF_REEXECUTION_FRAGILE);
- sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]= (CF_STATUS_COMMAND |
- CF_SHOW_TABLE_COMMAND |
- CF_REEXECUTION_FRAGILE);
-@@ -1520,6 +1523,8 @@
-
- case SCH_TABLE_NAMES:
- case SCH_TABLES:
-+ case SCH_TEMPORARY_TABLES:
-+ case SCH_GLOBAL_TEMPORARY_TABLES:
- case SCH_VIEWS:
- case SCH_TRIGGERS:
- case SCH_EVENTS:
-@@ -2110,6 +2115,7 @@
- }
- case SQLCOM_SHOW_DATABASES:
- case SQLCOM_SHOW_TABLES:
-+ case SQLCOM_SHOW_TEMPORARY_TABLES:
- case SQLCOM_SHOW_TRIGGERS:
- case SQLCOM_SHOW_TABLE_STATUS:
- case SQLCOM_SHOW_OPEN_TABLES:
-@@ -4919,6 +4925,8 @@
-
- case SCH_TABLE_NAMES:
- case SCH_TABLES:
-+ case SCH_TEMPORARY_TABLES:
-+ case SCH_GLOBAL_TEMPORARY_TABLES:
- case SCH_VIEWS:
- case SCH_TRIGGERS:
- case SCH_EVENTS:
---- a/sql/sql_show.cc
-+++ b/sql/sql_show.cc
-@@ -2692,6 +2692,7 @@
- break;
- case SQLCOM_SHOW_TABLES:
- case SQLCOM_SHOW_TABLE_STATUS:
-+ case SQLCOM_SHOW_TEMPORARY_TABLES:
- case SQLCOM_SHOW_TRIGGERS:
- case SQLCOM_SHOW_EVENTS:
- thd->make_lex_string(&lookup_field_values->db_value,
-@@ -3283,6 +3284,231 @@
- return (uint) OPEN_FULL_TABLE;
- }
-
-+/**
-+ @brief Change I_S table item list for SHOW [GLOBAL] TEMPORARY TABLES [FROM/IN db]
-+
-+ @param[in] thd thread handler
-+ @param[in] schema_table I_S table
-+
-+ @return Operation status
-+ @retval 0 success
-+ @retval 1 error
-+*/
-+int make_temporary_tables_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
-+{
-+ char tmp[128];
-+ String buffer(tmp,sizeof(tmp), thd->charset());
-+ LEX *lex= thd->lex;
-+ Name_resolution_context *context= &lex->select_lex.context;
-+
-+ if (thd->lex->option_type == OPT_GLOBAL) {
-+ ST_FIELD_INFO *field_info= &schema_table->fields_info[0];
-+ Item_field *field= new Item_field(context, NullS, NullS, field_info->field_name);
-+ if (add_item_to_list(thd, field))
-+ return 1;
-+ field->set_name(field_info->old_name, strlen(field_info->old_name), system_charset_info);
-+ }
-+
-+ ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
-+ buffer.length(0);
-+ buffer.append(field_info->old_name);
-+ buffer.append(lex->select_lex.db);
-+
-+ if (lex->wild && lex->wild->ptr())
-+ {
-+ buffer.append(STRING_WITH_LEN(" ("));
-+ buffer.append(lex->wild->ptr());
-+ buffer.append(')');
-+ }
-+
-+ Item_field *field= new Item_field(context, NullS, NullS, field_info->field_name);
-+ if (add_item_to_list(thd, field))
-+ return 1;
-+
-+ field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
-+ return 0;
-+}
-+
-+/**
-+ @brief Fill records for temporary tables by reading info from table object
-+
-+ @param[in] thd thread handler
-+ @param[in] table I_S table
-+ @param[in] tmp_table temporary table
-+ @param[in] db database name
-+
-+ @return Operation status
-+ @retval 0 success
-+ @retval 1 error
-+*/
-+
-+static int store_temporary_table_record(THD *thd, TABLE *table, TABLE *tmp_table, const char *db, bool table_name_only)
-+{
-+ CHARSET_INFO *cs= system_charset_info;
-+ DBUG_ENTER("store_temporary_table_record");
-+
-+ if (db && my_strcasecmp(cs, db, tmp_table->s->db.str))
-+ DBUG_RETURN(0);
-+
-+ restore_record(table, s->default_values);
-+
-+ //session_id
-+ table->field[0]->store((longlong) thd->thread_id, TRUE);
-+
-+ //database
-+ table->field[1]->store(tmp_table->s->db.str, tmp_table->s->db.length, cs);
-+
-+ //table
-+ table->field[2]->store(tmp_table->s->table_name.str, tmp_table->s->table_name.length, cs);
-+
-+ if (table_name_only)
-+ DBUG_RETURN(schema_table_store_record(thd, table));
-+
-+ //engine
-+ handler *handle= tmp_table->file;
-+ char *engineType = (char *)(handle ? handle->table_type() : "UNKNOWN");
-+ table->field[3]->store(engineType, strlen(engineType), cs);
-+
-+ //name
-+ if (tmp_table->s->path.str) {
-+ char *p=strstr(tmp_table->s->path.str, "#sql");
-+ int len=tmp_table->s->path.length-(p-tmp_table->s->path.str);
-+ table->field[4]->store(p, min(FN_REFLEN, len), cs);
-+ }
-+
-+ // file stats
-+ handler *file= tmp_table->file;
-+
-+ if (file) {
-+
-+ MYSQL_TIME time;
-+
-+ /**
-+ TODO: InnoDB stat(file) checks file on short names within data dictionary
-+ rather than using full path, because of that, temp files created in
-+ TMPDIR will not have access/create time as it will not find the file
-+
-+ The fix is to patch InnoDB to use full path
-+ */
-+ file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK);
-+
-+ table->field[5]->store((longlong) file->stats.records, TRUE);
-+ table->field[5]->set_notnull();
-+
-+ table->field[6]->store((longlong) file->stats.mean_rec_length, TRUE);
-+ table->field[7]->store((longlong) file->stats.data_file_length, TRUE);
-+ table->field[8]->store((longlong) file->stats.index_file_length, TRUE);
-+ if (file->stats.create_time)
-+ {
-+ thd->variables.time_zone->gmt_sec_to_TIME(&time,
-+ (my_time_t) file->stats.create_time);
-+ table->field[9]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
-+ table->field[9]->set_notnull();
-+ }
-+ if (file->stats.update_time)
-+ {
-+ thd->variables.time_zone->gmt_sec_to_TIME(&time,
-+ (my_time_t) file->stats.update_time);
-+ table->field[10]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
-+ table->field[10]->set_notnull();
-+ }
-+ }
-+
-+ DBUG_RETURN(schema_table_store_record(thd, table));
-+}
-+
-+/**
-+ @brief Fill I_S tables with global temporary tables
-+
-+ @param[in] thd thread handler
-+ @param[in] tables I_S table
-+ @param[in] cond 'WHERE' condition
-+
-+ @return Operation status
-+ @retval 0 success
-+ @retval 1 error
-+*/
-+
-+static int fill_global_temporary_tables(THD *thd, TABLE_LIST *tables, COND *cond)
-+{
-+ DBUG_ENTER("fill_global_temporary_tables");
-+
-+ mysql_mutex_lock(&LOCK_thread_count);
-+
-+ bool table_names_only= (thd->lex->sql_command == SQLCOM_SHOW_TEMPORARY_TABLES) ? 1 : 0;
-+ I_List_iterator<THD> it(threads);
-+ THD *thd_item;
-+ TABLE *tmp;
-+
-+#ifndef NO_EMBEDDED_ACCESS_CHECKS
-+ Security_context *sctx= thd->security_ctx;
-+ uint db_access;
-+#endif
-+
-+ while ((thd_item=it++)) {
-+ mysql_mutex_lock(&thd_item->LOCK_temporary_tables);
-+ for (tmp=thd_item->temporary_tables; tmp; tmp=tmp->next) {
-+
-+#ifndef NO_EMBEDDED_ACCESS_CHECKS
-+ if (test_all_bits(sctx->master_access, DB_ACLS))
-+ db_access=DB_ACLS;
-+ else
-+ db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, tmp->s->db.str, 0) | sctx->master_access);
-+
-+ if (!(db_access & DB_ACLS) && check_grant_db(thd,tmp->s->db.str)) {
-+ //no access for temp tables within this db for user
-+ continue;
-+ }
-+#endif
-+
-+ THD *t= tmp->in_use;
-+ tmp->in_use= thd;
-+
-+ if (store_temporary_table_record(thd_item, tables->table, tmp, thd->lex->select_lex.db, table_names_only)) {
-+ tmp->in_use= t;
-+ mysql_mutex_unlock(&thd_item->LOCK_temporary_tables);
-+ mysql_mutex_unlock(&LOCK_thread_count);
-+ DBUG_RETURN(1);
-+ }
-+
-+ tmp->in_use= t;
-+ }
-+ mysql_mutex_unlock(&thd_item->LOCK_temporary_tables);
-+ }
-+
-+ mysql_mutex_unlock(&LOCK_thread_count);
-+ DBUG_RETURN(0);
-+}
-+
-+/**
-+ @brief Fill I_S tables with session temporary tables
-+
-+ @param[in] thd thread handler
-+ @param[in] tables I_S table
-+ @param[in] cond 'WHERE' condition
-+
-+ @return Operation status
-+ @retval 0 success
-+ @retval 1 error
-+*/
-+
-+int fill_temporary_tables(THD *thd, TABLE_LIST *tables, COND *cond)
-+{
-+ DBUG_ENTER("fill_temporary_tables");
-+
-+ if (thd->lex->option_type == OPT_GLOBAL)
-+ DBUG_RETURN(fill_global_temporary_tables(thd, tables, cond));
-+
-+ bool table_names_only= (thd->lex->sql_command == SQLCOM_SHOW_TEMPORARY_TABLES) ? 1 : 0;
-+ TABLE *tmp;
-+
-+ for (tmp=thd->temporary_tables; tmp; tmp=tmp->next) {
-+ if (store_temporary_table_record(thd, tables->table, tmp, thd->lex->select_lex.db, table_names_only)) {
-+ DBUG_RETURN(1);
-+ }
-+ }
-+ DBUG_RETURN(0);
-+}
-
- /**
- Try acquire high priority share metadata lock on a table (with
-@@ -7046,6 +7272,25 @@
- {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
- };
-
-+ST_FIELD_INFO temporary_table_fields_info[]=
-+{
-+ {"SESSION_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Session", SKIP_OPEN_TABLE},
-+ {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Db", SKIP_OPEN_TABLE},
-+ {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Temp_tables_in_", SKIP_OPEN_TABLE},
-+ {"ENGINE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Engine", OPEN_FRM_ONLY},
-+ {"NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, "Name", SKIP_OPEN_TABLE},
-+ {"TABLE_ROWS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
-+ MY_I_S_UNSIGNED, "Rows", OPEN_FULL_TABLE},
-+ {"AVG_ROW_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
-+ MY_I_S_UNSIGNED, "Avg Row", OPEN_FULL_TABLE},
-+ {"DATA_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
-+ MY_I_S_UNSIGNED, "Data Length", OPEN_FULL_TABLE},
-+ {"INDEX_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
-+ MY_I_S_UNSIGNED, "Index Size", OPEN_FULL_TABLE},
-+ {"CREATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Create Time", OPEN_FULL_TABLE},
-+ {"UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Update Time", OPEN_FULL_TABLE},
-+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
-+};
-
- ST_FIELD_INFO columns_fields_info[]=
- {
-@@ -7660,6 +7905,9 @@
- hton_fill_schema_table, 0, 0, -1, -1, 0, 0},
- {"GLOBAL_STATUS", variables_fields_info, create_schema_table,
- fill_status, make_old_format, 0, 0, -1, 0, 0},
-+ {"GLOBAL_TEMPORARY_TABLES", temporary_table_fields_info, create_schema_table,
-+ fill_global_temporary_tables, make_temporary_tables_old_format, 0, 2, 3, 0,
-+ OPEN_TABLE_ONLY|OPTIMIZE_I_S_TABLE},
- {"GLOBAL_VARIABLES", variables_fields_info, create_schema_table,
- fill_variables, make_old_format, 0, 0, -1, 0, 0},
- {"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
-@@ -7709,6 +7957,9 @@
- get_all_tables, make_table_names_old_format, 0, 1, 2, 1, 0},
- {"TABLE_PRIVILEGES", table_privileges_fields_info, create_schema_table,
- fill_schema_table_privileges, 0, 0, -1, -1, 0, 0},
-+ {"TEMPORARY_TABLES", temporary_table_fields_info, create_schema_table,
-+ fill_temporary_tables, make_temporary_tables_old_format, 0, 2, 3, 0,
-+ OPEN_TABLE_ONLY|OPTIMIZE_I_S_TABLE},
- {"TRIGGERS", triggers_fields_info, create_schema_table,
- get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0,
- OPEN_TRIGGER_ONLY|OPTIMIZE_I_S_TABLE},
---- a/sql/sql_yacc.yy
-+++ b/sql/sql_yacc.yy
-@@ -10898,6 +10898,15 @@
- if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLE_NAMES))
- MYSQL_YYABORT;
- }
-+ | opt_var_type TEMPORARY TABLES opt_db
-+ {
-+ LEX *lex= Lex;
-+ lex->sql_command= SQLCOM_SHOW_TEMPORARY_TABLES;
-+ lex->option_type= $1;
-+ lex->select_lex.db= $4;
-+ if (prepare_schema_table(YYTHD, lex, 0, SCH_TEMPORARY_TABLES))
-+ MYSQL_YYABORT;
-+ }
- | opt_full TRIGGERS_SYM opt_db wild_and_where
- {
- LEX *lex= Lex;
---- a/sql/mysqld.h
-+++ b/sql/mysqld.h
-@@ -234,6 +234,7 @@
- extern PSI_mutex_key key_LOCK_des_key_file;
- #endif
-
-+extern PSI_mutex_key key_LOCK_temporary_tables;
- extern PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids,
- key_delayed_insert_mutex, key_hash_filo_lock, key_LOCK_active_mi,
- key_LOCK_connection_count, key_LOCK_crypt, key_LOCK_delayed_create,
---- a/sql/sql_base.cc
-+++ b/sql/sql_base.cc
-@@ -1651,12 +1651,16 @@
- if (!mysql_bin_log.is_open())
- {
- TABLE *tmp_next;
-+
-+ mysql_mutex_lock(&thd->LOCK_temporary_tables);
- for (table= thd->temporary_tables; table; table= tmp_next)
- {
- tmp_next= table->next;
- close_temporary(table, 1, 1);
- }
- thd->temporary_tables= 0;
-+ mysql_mutex_unlock(&thd->LOCK_temporary_tables);
-+
- DBUG_RETURN(FALSE);
- }
-
-@@ -1669,6 +1673,8 @@
-
- memcpy(buf, stub, stub_len);
-
-+ mysql_mutex_lock(&thd->LOCK_temporary_tables);
-+
- /*
- Insertion sort of temp tables by pseudo_thread_id to build ordered list
- of sublists of equal pseudo_thread_id
-@@ -1790,6 +1796,8 @@
- thd->variables.option_bits&= ~OPTION_QUOTE_SHOW_CREATE; /* restore option */
- thd->temporary_tables=0;
-
-+ mysql_mutex_unlock(&thd->LOCK_temporary_tables);
-+
- DBUG_RETURN(error);
- }
-
-@@ -2167,6 +2175,8 @@
- table->s->db.str, table->s->table_name.str,
- (long) table, table->alias));
-
-+ mysql_mutex_lock(&thd->LOCK_temporary_tables);
-+
- if (table->prev)
- {
- table->prev->next= table->next;
-@@ -2193,6 +2203,9 @@
- slave_open_temp_tables--;
- }
- close_temporary(table, free_share, delete_table);
-+
-+ mysql_mutex_unlock(&thd->LOCK_temporary_tables);
-+
- DBUG_VOID_RETURN;
- }
-
-@@ -5932,6 +5945,7 @@
- if (add_to_temporary_tables_list)
- {
- /* growing temp list at the head */
-+ mysql_mutex_lock(&thd->LOCK_temporary_tables);
- tmp_table->next= thd->temporary_tables;
- if (tmp_table->next)
- tmp_table->next->prev= tmp_table;
-@@ -5939,6 +5953,7 @@
- thd->temporary_tables->prev= 0;
- if (thd->slave_thread)
- slave_open_temp_tables++;
-+ mysql_mutex_unlock(&thd->LOCK_temporary_tables);
- }
- tmp_table->pos_in_table_list= 0;
- DBUG_PRINT("tmptable", ("opened table: '%s'.'%s' 0x%lx", tmp_table->s->db.str,
---- a/sql/sql_class.cc
-+++ b/sql/sql_class.cc
-@@ -836,6 +836,8 @@
- active_vio = 0;
- #endif
- mysql_mutex_init(key_LOCK_thd_data, &LOCK_thd_data, MY_MUTEX_INIT_FAST);
-+ mysql_mutex_init(key_LOCK_temporary_tables, &LOCK_temporary_tables,
-+ MY_MUTEX_INIT_FAST);
-
- /* Variables with default values */
- proc_info="login";
-@@ -1348,6 +1350,7 @@
- db= NULL;
- free_root(&transaction.mem_root,MYF(0));
- mysql_mutex_destroy(&LOCK_thd_data);
-+ mysql_mutex_destroy(&LOCK_temporary_tables);
- #ifndef DBUG_OFF
- dbug_sentry= THD_SENTRY_GONE;
- #endif
---- a/sql/sql_class.h
-+++ b/sql/sql_class.h
-@@ -1002,6 +1002,11 @@
- XXX Why are internal temporary tables added to this list?
- */
- TABLE *temporary_tables;
-+ /**
-+ Protects temporary_tables.
-+ */
-+ mysql_mutex_t LOCK_temporary_tables;
-+
- TABLE *derived_tables;
- /*
- During a MySQL session, one can lock tables in two modes: automatic
---- /dev/null
-+++ b/mysql-test/r/percona_show_temp_tables.result
-@@ -0,0 +1,58 @@
-+drop table if exists t1,t2,t3;
-+drop database if exists showtemp;
-+create database if not exists showtemp;
-+use test;
-+create temporary table t1(id int);
-+create temporary table t2(id int);
-+create temporary table showtemp.t3(id int);
-+insert into t1 values(10),(20),(30),(40);
-+insert into showtemp.t3 values(999);
-+show temporary tables;
-+Temp_tables_in_test
-+t2
-+t1
-+show temporary tables from test;
-+Temp_tables_in_test
-+t2
-+t1
-+show temporary tables in showtemp;
-+Temp_tables_in_showtemp
-+t3
-+select table_schema, table_name, engine, table_rows from Information_schema.temporary_tables;
-+table_schema table_name engine table_rows
-+showtemp t3 MyISAM 1
-+test t2 MyISAM 0
-+test t1 MyISAM 4
-+select table_schema, table_name, engine, table_rows from Information_schema.global_temporary_tables;
-+table_schema table_name engine table_rows
-+showtemp t3 MyISAM 1
-+test t2 MyISAM 0
-+test t1 MyISAM 4
-+select table_schema, table_name, engine, table_rows from Information_schema.global_temporary_tables where table_schema='showtemp';
-+table_schema table_name engine table_rows
-+showtemp t3 MyISAM 1
-+select table_schema, table_name, engine, table_rows from Information_schema.global_temporary_tables where table_schema='temp';
-+table_schema table_name engine table_rows
-+drop table if exists showtemp.t2;
-+create temporary table t1(id int);
-+create temporary table showtemp.t2(id int);
-+show temporary tables;
-+Temp_tables_in_test
-+t1
-+select table_schema, table_name, engine, table_rows from Information_schema.global_temporary_tables;
-+table_schema table_name engine table_rows
-+showtemp t2 MyISAM 0
-+test t1 MyISAM 0
-+showtemp t3 MyISAM 1
-+test t2 MyISAM 0
-+test t1 MyISAM 4
-+drop table showtemp.t2;
-+drop table t1;
-+select table_schema, table_name, engine, table_rows from Information_schema.global_temporary_tables;
-+table_schema table_name engine table_rows
-+showtemp t3 MyISAM 1
-+test t2 MyISAM 0
-+test t1 MyISAM 4
-+drop table t1, t2;
-+drop table showtemp.t3;
-+drop database showtemp;
---- /dev/null
-+++ b/mysql-test/t/percona_show_temp_tables.test
-@@ -0,0 +1,65 @@
-+# Uses GRANT commands that usually disabled in embedded server
-+-- source include/not_embedded.inc
-+
-+# Save the initial number of concurrent sessions
-+--source include/count_sessions.inc
-+
-+#
-+# Test of SHOW [GLOBAL] TEMPORARY TABLES [FROM/IN] DB and
-+# Information_schema.temporary_tables and global_temporary_tables
-+#
-+
-+connect(stcon1,localhost,root,,test);
-+connect(stcon2,localhost,root,,test);
-+
-+connection stcon1;
-+
-+--disable_warnings
-+drop table if exists t1,t2,t3;
-+drop database if exists showtemp;
-+create database if not exists showtemp;
-+--enable_warnings
-+
-+use test;
-+create temporary table t1(id int);
-+create temporary table t2(id int);
-+create temporary table showtemp.t3(id int);
-+insert into t1 values(10),(20),(30),(40);
-+insert into showtemp.t3 values(999);
-+
-+show temporary tables;
-+# "Session" is not same value always. mysql-test cannot test it always.
-+#show global temporary tables;
-+show temporary tables from test;
-+show temporary tables in showtemp;
-+select table_schema, table_name, engine, table_rows from Information_schema.temporary_tables;
-+select table_schema, table_name, engine, table_rows from Information_schema.global_temporary_tables;
-+select table_schema, table_name, engine, table_rows from Information_schema.global_temporary_tables where table_schema='showtemp';
-+select table_schema, table_name, engine, table_rows from Information_schema.global_temporary_tables where table_schema='temp';
-+
-+connection stcon2;
-+
-+--disable_warnings
-+drop table if exists showtemp.t2;
-+--enable_warnings
-+create temporary table t1(id int);
-+create temporary table showtemp.t2(id int);
-+show temporary tables;
-+select table_schema, table_name, engine, table_rows from Information_schema.global_temporary_tables;
-+drop table showtemp.t2;
-+drop table t1;
-+
-+disconnect stcon2;
-+
-+connection stcon1;
-+select table_schema, table_name, engine, table_rows from Information_schema.global_temporary_tables;
-+
-+drop table t1, t2;
-+drop table showtemp.t3;
-+drop database showtemp;
-+
-+connection default;
-+disconnect stcon1;
-+
-+# Wait till all disconnects are completed
-+--source include/wait_until_count_sessions.inc
+++ /dev/null
---- a/mysql-test/include/wait_for_slave_param.inc
-+++ b/mysql-test/include/wait_for_slave_param.inc
-@@ -79,7 +79,7 @@
-
- # mysqltest doesn't provide any better way to multiply by 10
- --let $_wait_for_slave_param_zero= 0
----let $_slave_timeout_counter= $_slave_timeout$zero
-+--let $_slave_timeout_counter= $_slave_timeout$_wait_for_slave_param_zero
- --let $_slave_continue= 1
- while ($_slave_continue)
- {
+++ /dev/null
-# name : slow_extended.patch
-# introduced : 11 or before
-# maintainer : Oleg
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/include/mysql/plugin_audit.h.pp
-+++ b/include/mysql/plugin_audit.h.pp
-@@ -186,6 +186,16 @@
- char *thd_security_context(void* thd, char *buffer, unsigned int length,
- unsigned int max_query_len);
- void thd_inc_row_count(void* thd);
-+void increment_thd_innodb_stats(void* thd,
-+ unsigned long long trx_id,
-+ long io_reads,
-+ long long io_read,
-+ long io_reads_wait_timer,
-+ long lock_que_wait_timer,
-+ long que_wait_timer,
-+ long page_access);
-+unsigned long thd_log_slow_verbosity(const void* thd);
-+int thd_opt_slow_log();
- int mysql_tmpfile(const char *prefix);
- int thd_killed(const void* thd);
- unsigned long thd_get_thread_id(const void* thd);
---- a/include/mysql/plugin_auth.h.pp
-+++ b/include/mysql/plugin_auth.h.pp
-@@ -186,6 +186,16 @@
- char *thd_security_context(void* thd, char *buffer, unsigned int length,
- unsigned int max_query_len);
- void thd_inc_row_count(void* thd);
-+void increment_thd_innodb_stats(void* thd,
-+ unsigned long long trx_id,
-+ long io_reads,
-+ long long io_read,
-+ long io_reads_wait_timer,
-+ long lock_que_wait_timer,
-+ long que_wait_timer,
-+ long page_access);
-+unsigned long thd_log_slow_verbosity(const void* thd);
-+int thd_opt_slow_log();
- int mysql_tmpfile(const char *prefix);
- int thd_killed(const void* thd);
- unsigned long thd_get_thread_id(const void* thd);
---- a/include/mysql/plugin_ftparser.h.pp
-+++ b/include/mysql/plugin_ftparser.h.pp
-@@ -139,6 +139,16 @@
- char *thd_security_context(void* thd, char *buffer, unsigned int length,
- unsigned int max_query_len);
- void thd_inc_row_count(void* thd);
-+void increment_thd_innodb_stats(void* thd,
-+ unsigned long long trx_id,
-+ long io_reads,
-+ long long io_read,
-+ long io_reads_wait_timer,
-+ long lock_que_wait_timer,
-+ long que_wait_timer,
-+ long page_access);
-+unsigned long thd_log_slow_verbosity(const void* thd);
-+int thd_opt_slow_log();
- int mysql_tmpfile(const char *prefix);
- int thd_killed(const void* thd);
- unsigned long thd_get_thread_id(const void* thd);
---- a/include/mysql/plugin.h
-+++ b/include/mysql/plugin.h
-@@ -545,6 +545,17 @@
- /* Increments the row counter, see THD::row_count */
- void thd_inc_row_count(MYSQL_THD thd);
-
-+void increment_thd_innodb_stats(MYSQL_THD thd,
-+ unsigned long long trx_id,
-+ long io_reads,
-+ long long io_read,
-+ long io_reads_wait_timer,
-+ long lock_que_wait_timer,
-+ long que_wait_timer,
-+ long page_access);
-+unsigned long thd_log_slow_verbosity(const MYSQL_THD thd);
-+int thd_opt_slow_log();
-+#define EXTENDED_SLOWLOG
- /**
- Create a temporary file.
-
---- /dev/null
-+++ b/patch_info/slow_extended.info
-@@ -0,0 +1,25 @@
-+File=slow_extended.patch
-+Name=Extended statistics in slow.log (not InnoDB part)
-+Version=1.3
-+Author=Percona <info@percona.com>
-+License=GPL
-+Comment=
-+Changelog
-+2008-11-26
-+YK: Fix inefficient determination of trx, Make not to call useless gettimeofday when don't use slow log. Make log_slow_queries dynamic (bool).
-+
-+2008-11-07
-+VT: Moved log_slow_rate_limit in SHOW VARIABLE into right place
-+
-+2008-11
-+Arjen Lentz: Fixups (backward compatibility) by Arjen Lentz <arjen@openquery.com.au>
-+
-+2010-07
-+1) Fix overflow of query time and lock time (Bug 600360) (slow_extended_fix_overflow.patch merged)
-+2) Control global slow feature merged (control_global_slow.patch merged)
-+3) Microseconds in slow query log merged (microseconds_in_slow_query_log.patch merged)
-+4) Now use_global_long_query_time and use_global_log_slow_control are synonims. Add value "all" for use_global_log_slow_control (contol-global_slow-2.patch merged)
-+5) Fix innodb_stats on replication (Bug 600684)
-+6) Change variable types (system/command-line)
-+2011-01
-+Patch profiling_slow.patch was merged
---- a/scripts/mysqldumpslow.sh
-+++ b/scripts/mysqldumpslow.sh
-@@ -102,8 +102,8 @@
- s/^#? Time: \d{6}\s+\d+:\d+:\d+.*\n//;
- my ($user,$host) = s/^#? User\@Host:\s+(\S+)\s+\@\s+(\S+).*\n// ? ($1,$2) : ('','');
-
-- s/^# Query_time: ([0-9.]+)\s+Lock_time: ([0-9.]+)\s+Rows_sent: ([0-9.]+).*\n//;
-- my ($t, $l, $r) = ($1, $2, $3);
-+ s/^# Query_time: (\d+(\.\d+)?) Lock_time: (\d+(\.\d+)?) Rows_sent: (\d+(\.\d+)?).*\n//;
-+ my ($t, $l, $r) = ($1, $3, $5);
- $t -= $l unless $opt{l};
-
- # remove fluff that mysqld writes to log when it (re)starts:
---- a/sql/event_scheduler.cc
-+++ b/sql/event_scheduler.cc
-@@ -195,6 +195,7 @@
- thd->client_capabilities|= CLIENT_MULTI_RESULTS;
- mysql_mutex_lock(&LOCK_thread_count);
- thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
-+ thd->write_to_slow_log= true;
- mysql_mutex_unlock(&LOCK_thread_count);
-
- /*
---- a/sql/filesort.cc
-+++ b/sql/filesort.cc
-@@ -193,6 +193,7 @@
- {
- status_var_increment(thd->status_var.filesort_scan_count);
- }
-+ thd->query_plan_flags|= QPLAN_FILESORT;
- #ifdef CAN_TRUST_RANGE
- if (select && select->quick && select->quick->records > 0L)
- {
-@@ -261,6 +262,7 @@
- /* filesort cannot handle zero-length records during merge. */
- DBUG_ASSERT(param.sort_length != 0);
-
-+ thd->query_plan_flags|= QPLAN_FILESORT_DISK;
- if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer)
- {
- my_free(table_sort.buffpek);
-@@ -1209,6 +1211,7 @@
- DBUG_ENTER("merge_buffers");
-
- status_var_increment(current_thd->status_var.filesort_merge_passes);
-+ current_thd->query_plan_fsort_passes++;
- if (param->not_killable)
- {
- killed= ¬_killable;
---- a/sql/log.cc
-+++ b/sql/log.cc
-@@ -715,11 +715,13 @@
- */
-
- bool Log_to_csv_event_handler::
-- log_slow(THD *thd, time_t current_time, time_t query_start_arg,
-+ log_slow(THD *thd, ulonglong current_utime, time_t query_start_arg,
- const char *user_host, uint user_host_len,
- ulonglong query_utime, ulonglong lock_utime, bool is_command,
- const char *sql_text, uint sql_text_len)
- {
-+ time_t current_time= my_time_possible_from_micro(current_utime);
-+
- TABLE_LIST table_list;
- TABLE *table;
- bool result= TRUE;
-@@ -935,14 +937,14 @@
- /** Wrapper around MYSQL_LOG::write() for slow log. */
-
- bool Log_to_file_event_handler::
-- log_slow(THD *thd, time_t current_time, time_t query_start_arg,
-+ log_slow(THD *thd, ulonglong current_utime, time_t query_start_arg,
- const char *user_host, uint user_host_len,
- ulonglong query_utime, ulonglong lock_utime, bool is_command,
- const char *sql_text, uint sql_text_len)
- {
- Silence_log_table_errors error_handler;
- thd->push_internal_handler(&error_handler);
-- bool retval= mysql_slow_log.write(thd, current_time, query_start_arg,
-+ bool retval= mysql_slow_log.write(thd, current_utime, query_start_arg,
- user_host, user_host_len,
- query_utime, lock_utime, is_command,
- sql_text, sql_text_len);
-@@ -1200,8 +1202,6 @@
-
- if (*slow_log_handler_list)
- {
-- time_t current_time;
--
- /* do not log slow queries from replication threads */
- if (thd->slave_thread && !opt_log_slow_slave_statements)
- return 0;
-@@ -1216,16 +1216,29 @@
- /* fill in user_host value: the format is "%s[%s] @ %s [%s]" */
- user_host_len= (strxnmov(user_host_buff, MAX_USER_HOST_SIZE,
- sctx->priv_user ? sctx->priv_user : "", "[",
-- sctx->user ? sctx->user : "", "] @ ",
-+ sctx->user ? sctx->user : (thd->slave_thread ? "SQL_SLAVE" : ""), "] @ ",
- sctx->host ? sctx->host : "", " [",
- sctx->ip ? sctx->ip : "", "]", NullS) -
- user_host_buff);
-
-- current_time= my_time_possible_from_micro(current_utime);
- if (thd->start_utime)
- {
-- query_utime= (current_utime - thd->start_utime);
-- lock_utime= (thd->utime_after_lock - thd->start_utime);
-+ if(current_utime < thd->start_utime)
-+ {
-+ query_utime= 0;
-+ }
-+ else
-+ {
-+ query_utime= (current_utime - thd->start_utime);
-+ }
-+ if(thd->utime_after_lock < thd->start_utime)
-+ {
-+ lock_utime= 0;
-+ }
-+ else
-+ {
-+ lock_utime= (thd->utime_after_lock - thd->start_utime);
-+ }
- }
- else
- {
-@@ -1240,7 +1253,7 @@
- }
-
- for (current_handler= slow_log_handler_list; *current_handler ;)
-- error= (*current_handler++)->log_slow(thd, current_time, thd->start_time,
-+ error= (*current_handler++)->log_slow(thd, current_utime, thd->start_time,
- user_host_buff, user_host_len,
- query_utime, lock_utime, is_command,
- query, query_length) || error;
-@@ -2656,12 +2669,13 @@
- TRUE - error occured
- */
-
--bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time,
-+bool MYSQL_QUERY_LOG::write(THD *thd, ulonglong current_utime,
- time_t query_start_arg, const char *user_host,
- uint user_host_len, ulonglong query_utime,
- ulonglong lock_utime, bool is_command,
- const char *sql_text, uint sql_text_len)
- {
-+ time_t current_time= my_time_possible_from_micro(current_utime);
- bool error= 0;
- DBUG_ENTER("MYSQL_QUERY_LOG::write");
-
-@@ -2683,17 +2697,28 @@
-
- if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT))
- {
-- if (current_time != last_time)
-+ if (opt_slow_query_log_timestamp_always || current_time != last_time)
- {
- last_time= current_time;
- struct tm start;
- localtime_r(¤t_time, &start);
--
-- buff_len= my_snprintf(buff, sizeof buff,
-- "# Time: %02d%02d%02d %2d:%02d:%02d\n",
-- start.tm_year % 100, start.tm_mon + 1,
-- start.tm_mday, start.tm_hour,
-- start.tm_min, start.tm_sec);
-+ if(opt_slow_query_log_timestamp_precision & SLOG_MICROSECOND)
-+ {
-+ ulonglong microsecond = current_utime % (1000 * 1000);
-+ buff_len= snprintf(buff, sizeof buff,
-+ "# Time: %02d%02d%02d %2d:%02d:%02d.%010lld\n",
-+ start.tm_year % 100, start.tm_mon + 1,
-+ start.tm_mday, start.tm_hour,
-+ start.tm_min, start.tm_sec,microsecond);
-+ }
-+ else
-+ {
-+ buff_len= my_snprintf(buff, sizeof buff,
-+ "# Time: %02d%02d%02d %2d:%02d:%02d\n",
-+ start.tm_year % 100, start.tm_mon + 1,
-+ start.tm_mday, start.tm_hour,
-+ start.tm_min, start.tm_sec);
-+ }
-
- /* Note that my_b_write() assumes it knows the length for this */
- if (my_b_write(&log_file, (uchar*) buff, buff_len))
-@@ -2710,13 +2735,71 @@
- /* For slow query log */
- sprintf(query_time_buff, "%.6f", ulonglong2double(query_utime)/1000000.0);
- sprintf(lock_time_buff, "%.6f", ulonglong2double(lock_utime)/1000000.0);
-+ DBUG_PRINT("info", ("Last_errno: %u", thd->last_errno));
- if (my_b_printf(&log_file,
-- "# Query_time: %s Lock_time: %s"
-- " Rows_sent: %lu Rows_examined: %lu\n",
-+ "# Thread_id: %lu Schema: %s Last_errno: %u Killed: %u\n" \
-+ "# Query_time: %s Lock_time: %s Rows_sent: %lu Rows_examined: %lu Rows_affected: %lu Rows_read: %lu\n"
-+ "# Bytes_sent: %lu Tmp_tables: %lu Tmp_disk_tables: %lu Tmp_table_sizes: %lu\n",
-+ (ulong) thd->thread_id, (thd->db ? thd->db : ""),
-+ thd->last_errno, (uint) thd->killed,
- query_time_buff, lock_time_buff,
- (ulong) thd->sent_row_count,
-- (ulong) thd->examined_row_count) == (uint) -1)
-+ (ulong) thd->examined_row_count,
-+ ((long) thd->get_row_count_func() > 0 ) ? (ulong) thd->get_row_count_func() : 0,
-+ (ulong) thd->sent_row_count,
-+ (ulong) (thd->status_var.bytes_sent - thd->bytes_sent_old),
-+ (ulong) thd->tmp_tables_used,
-+ (ulong) thd->tmp_tables_disk_used,
-+ (ulong) thd->tmp_tables_size) == (uint) -1)
- tmp_errno= errno;
-+
-+#if defined(ENABLED_PROFILING)
-+ thd->profiling.print_current(&log_file);
-+#endif
-+ if (thd->innodb_was_used)
-+ {
-+ char buf[20];
-+ snprintf(buf, 20, "%llX", thd->innodb_trx_id);
-+ if (my_b_printf(&log_file,
-+ "# InnoDB_trx_id: %s\n", buf) == (uint) -1)
-+ tmp_errno=errno;
-+ }
-+ if ((thd->variables.log_slow_verbosity & (ULL(1) << SLOG_V_QUERY_PLAN)) &&
-+ my_b_printf(&log_file,
-+ "# QC_Hit: %s Full_scan: %s Full_join: %s Tmp_table: %s Tmp_table_on_disk: %s\n" \
-+ "# Filesort: %s Filesort_on_disk: %s Merge_passes: %lu\n",
-+ ((thd->query_plan_flags & QPLAN_QC) ? "Yes" : "No"),
-+ ((thd->query_plan_flags & QPLAN_FULL_SCAN) ? "Yes" : "No"),
-+ ((thd->query_plan_flags & QPLAN_FULL_JOIN) ? "Yes" : "No"),
-+ ((thd->query_plan_flags & QPLAN_TMP_TABLE) ? "Yes" : "No"),
-+ ((thd->query_plan_flags & QPLAN_TMP_DISK) ? "Yes" : "No"),
-+ ((thd->query_plan_flags & QPLAN_FILESORT) ? "Yes" : "No"),
-+ ((thd->query_plan_flags & QPLAN_FILESORT_DISK) ? "Yes" : "No"),
-+ thd->query_plan_fsort_passes) == (uint) -1)
-+ tmp_errno=errno;
-+ if ((thd->variables.log_slow_verbosity & (ULL(1) << SLOG_V_INNODB)) && thd->innodb_was_used)
-+ {
-+ char buf[3][20];
-+ snprintf(buf[0], 20, "%.6f", thd->innodb_io_reads_wait_timer / 1000000.0);
-+ snprintf(buf[1], 20, "%.6f", thd->innodb_lock_que_wait_timer / 1000000.0);
-+ snprintf(buf[2], 20, "%.6f", thd->innodb_innodb_que_wait_timer / 1000000.0);
-+ if (my_b_printf(&log_file,
-+ "# InnoDB_IO_r_ops: %lu InnoDB_IO_r_bytes: %lu InnoDB_IO_r_wait: %s\n" \
-+ "# InnoDB_rec_lock_wait: %s InnoDB_queue_wait: %s\n" \
-+ "# InnoDB_pages_distinct: %lu\n",
-+ (ulong) thd->innodb_io_reads,
-+ (ulong) thd->innodb_io_read,
-+ buf[0], buf[1], buf[2],
-+ (ulong) thd->innodb_page_access) == (uint) -1)
-+ tmp_errno=errno;
-+ }
-+ else
-+ {
-+ if ((thd->variables.log_slow_verbosity & (ULL(1) << SLOG_V_INNODB)) &&
-+ my_b_printf(&log_file,"# No InnoDB statistics available for this query\n") == (uint) -1)
-+ tmp_errno=errno;
-+ }
-+
- if (thd->db && strcmp(thd->db, db))
- { // Database changed
- if (my_b_printf(&log_file,"use %s;\n",thd->db) == (uint) -1)
---- a/sql/log.h
-+++ b/sql/log.h
-@@ -242,7 +242,7 @@
- uint user_host_len, int thread_id,
- const char *command_type, uint command_type_len,
- const char *sql_text, uint sql_text_len);
-- bool write(THD *thd, time_t current_time, time_t query_start_arg,
-+ bool write(THD *thd, ulonglong current_time, time_t query_start_arg,
- const char *user_host, uint user_host_len,
- ulonglong query_utime, ulonglong lock_utime, bool is_command,
- const char *sql_text, uint sql_text_len);
-@@ -517,7 +517,7 @@
- virtual bool init()= 0;
- virtual void cleanup()= 0;
-
-- virtual bool log_slow(THD *thd, time_t current_time,
-+ virtual bool log_slow(THD *thd, ulonglong current_time,
- time_t query_start_arg, const char *user_host,
- uint user_host_len, ulonglong query_utime,
- ulonglong lock_utime, bool is_command,
-@@ -546,7 +546,7 @@
- virtual bool init();
- virtual void cleanup();
-
-- virtual bool log_slow(THD *thd, time_t current_time,
-+ virtual bool log_slow(THD *thd, ulonglong current_utime,
- time_t query_start_arg, const char *user_host,
- uint user_host_len, ulonglong query_utime,
- ulonglong lock_utime, bool is_command,
-@@ -578,7 +578,7 @@
- virtual bool init();
- virtual void cleanup();
-
-- virtual bool log_slow(THD *thd, time_t current_time,
-+ virtual bool log_slow(THD *thd, ulonglong current_utime,
- time_t query_start_arg, const char *user_host,
- uint user_host_len, ulonglong query_utime,
- ulonglong lock_utime, bool is_command,
---- a/sql/mysqld.cc
-+++ b/sql/mysqld.cc
-@@ -421,6 +421,11 @@
- char* opt_secure_file_priv;
- my_bool opt_log_slow_admin_statements= 0;
- my_bool opt_log_slow_slave_statements= 0;
-+my_bool opt_log_slow_sp_statements= 0;
-+my_bool opt_slow_query_log_timestamp_always= 0;
-+ulonglong opt_slow_query_log_use_global_control= 0;
-+ulong opt_slow_query_log_timestamp_precision= 0;
-+ulong opt_slow_query_log_rate_type= 0;
- my_bool lower_case_file_system= 0;
- my_bool opt_large_pages= 0;
- my_bool opt_super_large_pages= 0;
-@@ -5892,14 +5897,10 @@
- "Don't log extra information to update and slow-query logs.",
- &opt_short_log_format, &opt_short_log_format,
- 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-- {"log-slow-admin-statements", 0,
-- "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to "
-- "the slow log if it is open.", &opt_log_slow_admin_statements,
-- &opt_log_slow_admin_statements, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-- {"log-slow-slave-statements", 0,
-+ /*{"log-slow-slave-statements", 0,
- "Log slow statements executed by slave thread to the slow log if it is open.",
- &opt_log_slow_slave_statements, &opt_log_slow_slave_statements,
-- 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},*/
- {"log-slow-queries", OPT_SLOW_QUERY_LOG,
- "Log slow queries to a table or log file. Defaults logging to table "
- "mysql.slow_log or hostname-slow.log if --log-output=file is used. "
-@@ -7288,6 +7289,10 @@
-
- C_MODE_END
-
-+/* defined in sys_vars.cc */
-+extern void init_log_slow_verbosity();
-+extern void init_slow_query_log_use_global_control();
-+
- /**
- Get server options from the command line,
- and perform related server initializations.
-@@ -7437,6 +7442,8 @@
- global_system_variables.long_query_time= (ulonglong)
- (global_system_variables.long_query_time_double * 1e6);
-
-+ init_log_slow_verbosity();
-+ init_slow_query_log_use_global_control();
- if (opt_short_log_format)
- opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT;
-
---- a/sql/mysqld.h
-+++ b/sql/mysqld.h
-@@ -116,6 +116,11 @@
- extern char* opt_secure_backup_file_priv;
- extern size_t opt_secure_backup_file_priv_len;
- extern my_bool opt_log_slow_admin_statements, opt_log_slow_slave_statements;
-+extern my_bool opt_log_slow_sp_statements;
-+extern my_bool opt_slow_query_log_timestamp_always;
-+extern ulonglong opt_slow_query_log_use_global_control;
-+extern ulong opt_slow_query_log_timestamp_precision;
-+extern ulong opt_slow_query_log_rate_type;
- extern my_bool sp_automatic_privileges, opt_noacl;
- extern my_bool opt_old_style_user_limits, trust_function_creators;
- extern uint opt_crash_binlog_innodb;
---- a/sql/slave.cc
-+++ b/sql/slave.cc
-@@ -2038,6 +2038,7 @@
- + MAX_LOG_EVENT_HEADER; /* note, incr over the global not session var */
- thd->slave_thread = 1;
- thd->enable_slow_log= opt_log_slow_slave_statements;
-+ thd->write_to_slow_log= opt_log_slow_slave_statements;
- set_slave_thread_options(thd);
- thd->client_capabilities = CLIENT_LOCAL_FILES;
- mysql_mutex_lock(&LOCK_thread_count);
---- a/sql/sp_head.cc
-+++ b/sql/sp_head.cc
-@@ -2164,7 +2164,7 @@
- DBUG_PRINT("info",(" %.*s: eval args done", (int) m_name.length,
- m_name.str));
- }
-- if (!(m_flags & LOG_SLOW_STATEMENTS) && thd->enable_slow_log)
-+ if (!(m_flags & LOG_SLOW_STATEMENTS || opt_log_slow_sp_statements) && thd->enable_slow_log)
- {
- DBUG_PRINT("info", ("Disabling slow log for the execution"));
- save_enable_slow_log= true;
---- a/sql/sql_cache.cc
-+++ b/sql/sql_cache.cc
-@@ -1780,6 +1780,7 @@
- response, we can't handle it anyway.
- */
- (void) trans_commit_stmt(thd);
-+ thd->query_plan_flags|= QPLAN_QC;
- if (!thd->stmt_da->is_set())
- thd->stmt_da->disable_status();
-
-@@ -1790,6 +1791,7 @@
- err_unlock:
- unlock();
- err:
-+ thd->query_plan_flags|= QPLAN_QC_NO;
- MYSQL_QUERY_CACHE_MISS(thd->query());
- DBUG_RETURN(0); // Query was not cached
- }
---- a/sql/sql_class.cc
-+++ b/sql/sql_class.cc
-@@ -616,6 +616,37 @@
- thd->warning_info->inc_current_row_for_warning();
- }
-
-+extern "C"
-+void increment_thd_innodb_stats(THD* thd,
-+ unsigned long long trx_id,
-+ long io_reads,
-+ long long io_read,
-+ long io_reads_wait_timer,
-+ long lock_que_wait_timer,
-+ long que_wait_timer,
-+ long page_access)
-+{
-+ thd->innodb_was_used= TRUE;
-+ thd->innodb_trx_id= trx_id;
-+ thd->innodb_io_reads+= io_reads;
-+ thd->innodb_io_read+= io_read;
-+ thd->innodb_io_reads_wait_timer+= io_reads_wait_timer;
-+ thd->innodb_lock_que_wait_timer+= lock_que_wait_timer;
-+ thd->innodb_innodb_que_wait_timer+= que_wait_timer;
-+ thd->innodb_page_access+= page_access;
-+}
-+
-+extern "C"
-+unsigned long thd_log_slow_verbosity(const THD *thd)
-+{
-+ return (unsigned long) thd->variables.log_slow_verbosity;
-+}
-+
-+extern "C"
-+int thd_opt_slow_log()
-+{
-+ return (int) opt_slow_log;
-+}
-
- /**
- Dumps a text description of a thread, its security context
-@@ -942,6 +973,8 @@
- const char* msg,
- MYSQL_ERROR ** cond_hdl)
- {
-+ last_errno= sql_errno;
-+
- if (!m_internal_handler)
- {
- *cond_hdl= NULL;
-@@ -1236,6 +1269,8 @@
- /* Initialize the Debug Sync Facility. See debug_sync.cc. */
- debug_sync_init_thread(this);
- #endif /* defined(ENABLED_DEBUG_SYNC) */
-+
-+ clear_slow_extended();
- }
-
-
-@@ -3687,8 +3722,6 @@
- backup->in_sub_stmt= in_sub_stmt;
- backup->enable_slow_log= enable_slow_log;
- backup->limit_found_rows= limit_found_rows;
-- backup->examined_row_count= examined_row_count;
-- backup->sent_row_count= sent_row_count;
- backup->cuted_fields= cuted_fields;
- backup->client_capabilities= client_capabilities;
- backup->savepoints= transaction.savepoints;
-@@ -3696,6 +3729,7 @@
- first_successful_insert_id_in_prev_stmt;
- backup->first_successful_insert_id_in_cur_stmt=
- first_successful_insert_id_in_cur_stmt;
-+ reset_sub_statement_state_slow_extended(backup);
-
- if ((!lex->requires_prelocking() || is_update_query(lex->sql_command)) &&
- !is_current_stmt_binlog_format_row())
-@@ -3711,13 +3745,74 @@
- /* Disable result sets */
- client_capabilities &= ~CLIENT_MULTI_RESULTS;
- in_sub_stmt|= new_state;
-- examined_row_count= 0;
-- sent_row_count= 0;
- cuted_fields= 0;
- transaction.savepoints= 0;
- first_successful_insert_id_in_cur_stmt= 0;
- }
-
-+void THD::clear_slow_extended()
-+{
-+ DBUG_ENTER("THD::clear_slow_extended");
-+ sent_row_count= 0;
-+ examined_row_count= 0;
-+ bytes_sent_old= status_var.bytes_sent;
-+ tmp_tables_used= 0;
-+ tmp_tables_disk_used= 0;
-+ tmp_tables_size= 0;
-+ innodb_was_used= FALSE;
-+ innodb_trx_id= 0;
-+ innodb_io_reads= 0;
-+ innodb_io_read= 0;
-+ innodb_io_reads_wait_timer= 0;
-+ innodb_lock_que_wait_timer= 0;
-+ innodb_innodb_que_wait_timer= 0;
-+ innodb_page_access= 0;
-+ query_plan_flags= QPLAN_NONE;
-+ query_plan_fsort_passes= 0;
-+ last_errno= 0;
-+ DBUG_VOID_RETURN;
-+}
-+
-+void THD::reset_sub_statement_state_slow_extended(Sub_statement_state *backup)
-+{
-+ DBUG_ENTER("THD::reset_sub_statement_state_slow_extended");
-+ backup->sent_row_count= sent_row_count;
-+ backup->examined_row_count= examined_row_count;
-+ backup->tmp_tables_used= tmp_tables_used;
-+ backup->tmp_tables_disk_used= tmp_tables_disk_used;
-+ backup->tmp_tables_size= tmp_tables_size;
-+ backup->innodb_was_used= innodb_was_used;
-+ backup->innodb_io_reads= innodb_io_reads;
-+ backup->innodb_io_read= innodb_io_read;
-+ backup->innodb_io_reads_wait_timer= innodb_io_reads_wait_timer;
-+ backup->innodb_lock_que_wait_timer= innodb_lock_que_wait_timer;
-+ backup->innodb_innodb_que_wait_timer= innodb_innodb_que_wait_timer;
-+ backup->innodb_page_access= innodb_page_access;
-+ backup->query_plan_flags= query_plan_flags;
-+ backup->query_plan_fsort_passes= query_plan_fsort_passes;
-+ clear_slow_extended();
-+ DBUG_VOID_RETURN;
-+}
-+
-+void THD::restore_sub_statement_state_slow_extended(const Sub_statement_state *backup)
-+{
-+ DBUG_ENTER("THD::restore_sub_statement_state_slow_extended");
-+ sent_row_count= backup->sent_row_count;
-+ examined_row_count+= backup->examined_row_count;
-+ tmp_tables_used+= backup->tmp_tables_used;
-+ tmp_tables_disk_used+= backup->tmp_tables_disk_used;
-+ tmp_tables_size+= backup->tmp_tables_size;
-+ innodb_was_used= (innodb_was_used || backup->innodb_was_used);
-+ innodb_io_reads+= backup->innodb_io_reads;
-+ innodb_io_read+= backup->innodb_io_read;
-+ innodb_io_reads_wait_timer+= backup->innodb_io_reads_wait_timer;
-+ innodb_lock_que_wait_timer+= backup->innodb_lock_que_wait_timer;
-+ innodb_innodb_que_wait_timer+= backup->innodb_innodb_que_wait_timer;
-+ innodb_page_access+= backup->innodb_page_access;
-+ query_plan_flags|= backup->query_plan_flags;
-+ query_plan_fsort_passes+= backup->query_plan_fsort_passes;
-+ DBUG_VOID_RETURN;
-+}
-
- void THD::restore_sub_statement_state(Sub_statement_state *backup)
- {
-@@ -3758,7 +3853,6 @@
- first_successful_insert_id_in_cur_stmt=
- backup->first_successful_insert_id_in_cur_stmt;
- limit_found_rows= backup->limit_found_rows;
-- sent_row_count= backup->sent_row_count;
- client_capabilities= backup->client_capabilities;
- /*
- If we've left sub-statement mode, reset the fatal error flag.
-@@ -3776,8 +3870,8 @@
- The following is added to the old values as we are interested in the
- total complexity of the query
- */
-- examined_row_count+= backup->examined_row_count;
- cuted_fields+= backup->cuted_fields;
-+ restore_sub_statement_state_slow_extended(backup);
- DBUG_VOID_RETURN;
- }
-
-@@ -3802,7 +3896,7 @@
- {
- mysql_mutex_lock(&LOCK_thd_data);
- set_query_inner(query_arg, query_length_arg, cs);
-- query_id= new_query_id;
-+ do_set_query_id(new_query_id);
- mysql_mutex_unlock(&LOCK_thd_data);
- }
-
-@@ -3811,9 +3905,25 @@
- void THD::set_query_id(query_id_t new_query_id)
- {
- mysql_mutex_lock(&LOCK_thd_data);
-- query_id= new_query_id;
-+ do_set_query_id(new_query_id);
- mysql_mutex_unlock(&LOCK_thd_data);
- }
-+void THD::do_set_query_id(query_id_t new_query_id)
-+{
-+#ifndef DBUG_OFF
-+ if (variables.query_exec_id != 0 &&
-+ lex->sql_command != SQLCOM_SET_OPTION)
-+ {
-+ new_query_id= variables.query_exec_id;
-+ }
-+#endif /* DBUG_OFF */
-+ query_id= new_query_id;
-+ if (opt_slow_query_log_rate_type == SLOG_RT_QUERY)
-+ {
-+ const ulong& limit= variables.log_slow_rate_limit;
-+ write_to_slow_log= limit == 0 || (query_id % limit) == 0;
-+ }
-+}
-
- /** Assign a new value to thd->mysys_var. */
- void THD::set_mysys_var(struct st_my_thread_var *new_mysys_var)
---- a/sql/sql_class.h
-+++ b/sql/sql_class.h
-@@ -60,6 +60,36 @@
- enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_UPDATE };
- enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON,
- DELAY_KEY_WRITE_ALL };
-+enum enum_slow_query_log_use_global_control {
-+ SLOG_UG_LOG_SLOW_FILTER, SLOG_UG_LOG_SLOW_RATE_LIMIT
-+ , SLOG_UG_LOG_SLOW_VERBOSITY, SLOG_UG_LONG_QUERY_TIME
-+ , SLOG_UG_MIN_EXAMINED_ROW_LIMIT, SLOG_UG_ALL
-+};
-+enum enum_log_slow_verbosity {
-+ SLOG_V_MICROTIME, SLOG_V_QUERY_PLAN, SLOG_V_INNODB,
-+ SLOG_V_PROFILING, SLOG_V_PROFILING_USE_GETRUSAGE,
-+ SLOG_V_MINIMAL, SLOG_V_STANDARD, SLOG_V_FULL
-+};
-+enum enum_slow_query_log_timestamp_precision {
-+ SLOG_SECOND, SLOG_MICROSECOND
-+};
-+enum enum_slow_query_log_rate_type {
-+ SLOG_RT_SESSION, SLOG_RT_QUERY
-+};
-+#define QPLAN_NONE 0
-+#define QPLAN_QC 1 << 0
-+#define QPLAN_QC_NO 1 << 1
-+#define QPLAN_FULL_SCAN 1 << 2
-+#define QPLAN_FULL_JOIN 1 << 3
-+#define QPLAN_TMP_TABLE 1 << 4
-+#define QPLAN_TMP_DISK 1 << 5
-+#define QPLAN_FILESORT 1 << 6
-+#define QPLAN_FILESORT_DISK 1 << 7
-+enum enum_log_slow_filter {
-+ SLOG_F_QC_NO, SLOG_F_FULL_SCAN, SLOG_F_FULL_JOIN,
-+ SLOG_F_TMP_TABLE, SLOG_F_TMP_DISK, SLOG_F_FILESORT,
-+ SLOG_F_FILESORT_DISK
-+};
- enum enum_slave_exec_mode { SLAVE_EXEC_MODE_STRICT,
- SLAVE_EXEC_MODE_IDEMPOTENT,
- SLAVE_EXEC_MODE_LAST_BIT};
-@@ -508,6 +538,22 @@
-
- my_bool sysdate_is_now;
-
-+#ifndef DBUG_OFF
-+ ulonglong query_exec_time;
-+ double query_exec_time_double;
-+ ulong query_exec_id;
-+#endif
-+ ulong log_slow_rate_limit;
-+ ulonglong log_slow_filter;
-+ ulonglong log_slow_verbosity;
-+
-+ ulong innodb_io_reads;
-+ ulonglong innodb_io_read;
-+ ulong innodb_io_reads_wait_timer;
-+ ulong innodb_lock_que_wait_timer;
-+ ulong innodb_innodb_que_wait_timer;
-+ ulong innodb_page_access;
-+
- double long_query_time_double;
-
- } SV;
-@@ -1140,6 +1186,24 @@
- uint in_sub_stmt;
- bool enable_slow_log;
- bool last_insert_id_used;
-+
-+ /*** Following variables used in slow_extended.patch ***/
-+ ulong tmp_tables_used;
-+ ulong tmp_tables_disk_used;
-+ ulonglong tmp_tables_size;
-+
-+ bool innodb_was_used;
-+ ulong innodb_io_reads;
-+ ulonglong innodb_io_read;
-+ ulong innodb_io_reads_wait_timer;
-+ ulong innodb_lock_que_wait_timer;
-+ ulong innodb_innodb_que_wait_timer;
-+ ulong innodb_page_access;
-+
-+ ulong query_plan_flags;
-+ ulong query_plan_fsort_passes;
-+ /*** The variables above used in slow_extended.patch ***/
-+
- SAVEPOINT *savepoints;
- enum enum_check_fields count_cuted_fields;
- };
-@@ -1588,6 +1652,71 @@
- thr_lock_type update_lock_default;
- Delayed_insert *di;
-
-+ /*** Following variables used in slow_extended.patch ***/
-+ /*
-+ Variable write_to_slow_log:
-+ 1) initialized in
-+ * sql_connect.cc (log_slow_rate_limit support)
-+ * slave.cc (log_slow_slave_statements support)
-+ 2) The variable is initialized on the thread startup and remains
-+ constant afterwards. This will change when
-+ LP #712396 ("log_slow_slave_statements not work on replication
-+ threads without RESTART") is implemented.
-+ 3) An implementation of LP #688646 ("Make query sampling possible by query") should use it.
-+ */
-+ bool write_to_slow_log;
-+ /*
-+ Variable bytes_send_old saves value of thd->status_var.bytes_sent
-+ before query execution.
-+ */
-+ ulonglong bytes_sent_old;
-+ /*
-+ Variables tmp_tables_*** collect statistics about usage of temporary tables
-+ */
-+ ulong tmp_tables_used;
-+ ulong tmp_tables_disk_used;
-+ ulonglong tmp_tables_size;
-+ /*
-+ Variable innodb_was_used shows used or not InnoDB engine in current query.
-+ */
-+ bool innodb_was_used;
-+ /*
-+ Following Variables innodb_*** (is |should be) different from
-+ default values only if (innodb_was_used==TRUE)
-+ */
-+ ulonglong innodb_trx_id;
-+ ulong innodb_io_reads;
-+ ulonglong innodb_io_read;
-+ ulong innodb_io_reads_wait_timer;
-+ ulong innodb_lock_que_wait_timer;
-+ ulong innodb_innodb_que_wait_timer;
-+ ulong innodb_page_access;
-+
-+ /*
-+ Variable query_plan_flags collects information about query plan entites
-+ used on query execution.
-+ */
-+ ulong query_plan_flags;
-+ /*
-+ Variable query_plan_fsort_passes collects information about file sort passes
-+ acquired during query execution.
-+ */
-+ ulong query_plan_fsort_passes;
-+ /*
-+ Query can generate several errors/warnings during execution
-+ (see THD::handle_condition comment in sql_class.h)
-+ Variable last_errno contains the last error/warning acquired during
-+ query execution.
-+ */
-+ uint last_errno;
-+ /*** The variables above used in slow_extended.patch ***/
-+
-+ /*** Following methods used in slow_extended.patch ***/
-+ void clear_slow_extended();
-+ void reset_sub_statement_state_slow_extended(Sub_statement_state *backup);
-+ void restore_sub_statement_state_slow_extended(const Sub_statement_state *backup);
-+ /*** The methods above used in slow_extended.patch ***/
-+
- /* <> 0 if we are inside of trigger or stored function. */
- uint in_sub_stmt;
-
-@@ -2784,6 +2913,9 @@
- void set_query_and_id(char *query_arg, uint32 query_length_arg,
- CHARSET_INFO *cs, query_id_t new_query_id);
- void set_query_id(query_id_t new_query_id);
-+private:
-+ void do_set_query_id(query_id_t new_query_id);
-+public:
- void set_open_tables(TABLE *open_tables_arg)
- {
- mysql_mutex_lock(&LOCK_thd_data);
---- a/sql/sql_connect.cc
-+++ b/sql/sql_connect.cc
-@@ -721,6 +721,14 @@
- MYSQL_CONNECTION_START(thd->thread_id, &thd->security_ctx->priv_user[0],
- (char *) thd->security_ctx->host_or_ip);
-
-+ /*
-+ If rate limiting of slow log writes is enabled, decide whether to log this
-+ new thread's queries or not. Uses extremely simple algorithm. :)
-+ */
-+ const ulong& limit= thd->variables.log_slow_rate_limit;
-+ thd->write_to_slow_log= opt_slow_query_log_rate_type == SLOG_RT_SESSION &&
-+ (limit == 0 || (thd->thread_id % limit) == 0);
-+
- prepare_new_connection_state(thd);
- return FALSE;
- }
---- a/sql/sql_parse.cc
-+++ b/sql/sql_parse.cc
-@@ -114,6 +114,7 @@
-
- static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
- static void sql_kill(THD *thd, ulong id, bool only_kill_query);
-+static inline ulonglong get_query_exec_time(THD *thd, ulonglong cur_utime);
-
- const char *any_db="*any*"; // Special symbol for check_access
-
-@@ -890,6 +891,7 @@
- the slow log only if opt_log_slow_admin_statements is set.
- */
- thd->enable_slow_log= TRUE;
-+ thd->clear_slow_extended();
- thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */
- thd->set_time();
- if (!thd->is_valid_time())
-@@ -1440,6 +1442,60 @@
- DBUG_RETURN(error);
- }
-
-+/**
-+ Calculate execution time for the current query.
-+
-+ For debug builds, check the session value of query_exec_time
-+ and if it is not zero, return it instead of the actual execution time.
-+
-+ SET queries are ignored so that statements changing query_exec_time are not
-+ affected by themselves.
-+
-+ @param thd thread handle
-+ @param lex current relative time in microseconds
-+
-+ @return time in microseconds from utime_after_lock
-+*/
-+
-+static inline ulonglong get_query_exec_time(THD *thd, ulonglong cur_utime)
-+{
-+ ulonglong res;
-+#ifndef DBUG_OFF
-+ if (thd->variables.query_exec_time != 0)
-+ res= thd->lex->sql_command != SQLCOM_SET_OPTION ?
-+ thd->variables.query_exec_time : 0;
-+ else
-+#endif
-+
-+ res= cur_utime - thd->utime_after_lock;
-+
-+ if (res > thd->variables.long_query_time)
-+ thd->server_status|= SERVER_QUERY_WAS_SLOW;
-+ else
-+ thd->server_status&= ~SERVER_QUERY_WAS_SLOW;
-+
-+ return res;
-+}
-+
-+
-+static inline void copy_global_to_session(THD *thd, ulong flag,
-+ const ulong *val)
-+{
-+ my_ptrdiff_t offset = ((char *)val - (char *)&global_system_variables);
-+ if (opt_slow_query_log_use_global_control & (1ULL << flag))
-+ *(ulong *)((char *) &thd->variables + offset) = *val;
-+}
-+
-+
-+static inline void copy_global_to_session(THD *thd, ulong flag,
-+ const ulonglong *val)
-+{
-+ my_ptrdiff_t offset = ((char *)val - (char *)&global_system_variables);
-+ if (opt_slow_query_log_use_global_control & (1ULL << flag))
-+ *(ulonglong *)((char *) &thd->variables + offset) = *val;
-+}
-+
-+
-
- void log_slow_statement(THD *thd)
- {
-@@ -1453,13 +1509,47 @@
- if (unlikely(thd->in_sub_stmt))
- DBUG_VOID_RETURN; // Don't set time for sub stmt
-
-+ /* Follow the slow log filter configuration. */
-+ if (thd->variables.log_slow_filter != 0 &&
-+ (!(thd->variables.log_slow_filter & thd->query_plan_flags) ||
-+ ((thd->variables.log_slow_filter & SLOG_F_QC_NO) &&
-+ (thd->query_plan_flags & QPLAN_QC))))
-+ DBUG_VOID_RETURN;
-+
-+ ulonglong end_utime_of_query= thd->current_utime();
-+ ulonglong query_exec_time= get_query_exec_time(thd, end_utime_of_query);
-+
-+ /*
-+ Low long_query_time value most likely means user is debugging stuff and even
-+ though some thread's queries are not supposed to be logged b/c of the rate
-+ limit, if one of them takes long enough (>= 1 second) it will be sensible
-+ to make an exception and write to slow log anyway.
-+ */
-+
-+ system_variables const &g= global_system_variables;
-+ copy_global_to_session(thd, SLOG_UG_LOG_SLOW_FILTER,
-+ &g.log_slow_filter);
-+ copy_global_to_session(thd, SLOG_UG_LOG_SLOW_RATE_LIMIT,
-+ &g.log_slow_rate_limit);
-+ copy_global_to_session(thd, SLOG_UG_LOG_SLOW_VERBOSITY,
-+ &g.log_slow_verbosity);
-+ copy_global_to_session(thd, SLOG_UG_LONG_QUERY_TIME,
-+ &g.long_query_time);
-+ copy_global_to_session(thd, SLOG_UG_MIN_EXAMINED_ROW_LIMIT,
-+ &g.min_examined_row_limit);
-+
-+ /* Do not log this thread's queries due to rate limiting. */
-+ if (!thd->write_to_slow_log && (thd->variables.long_query_time >= 1000000
-+ || (ulong) query_exec_time < 1000000))
-+ DBUG_VOID_RETURN;
-+
-+
- /*
- Do not log administrative statements unless the appropriate option is
- set.
- */
- if (thd->enable_slow_log)
- {
-- ulonglong end_utime_of_query= thd->current_utime();
- thd_proc_info(thd, "logging slow query");
-
- if (((thd->server_status & SERVER_QUERY_WAS_SLOW) ||
-@@ -5368,7 +5459,8 @@
- thd->stmt_da->reset_diagnostics_area();
- thd->warning_info->reset_for_next_command();
- thd->rand_used= 0;
-- thd->sent_row_count= thd->examined_row_count= 0;
-+
-+ thd->clear_slow_extended();
-
- thd->reset_current_stmt_binlog_format_row();
- thd->binlog_unsafe_warning_flags= 0;
---- a/sql/sql_select.cc
-+++ b/sql/sql_select.cc
-@@ -6912,7 +6912,10 @@
- {
- join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
- if (statistics)
-+ {
- status_var_increment(join->thd->status_var.select_scan_count);
-+ join->thd->query_plan_flags|= QPLAN_FULL_SCAN;
-+ }
- }
- }
- else
-@@ -6926,7 +6929,10 @@
- {
- join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
- if (statistics)
-+ {
- status_var_increment(join->thd->status_var.select_full_join_count);
-+ join->thd->query_plan_flags|= QPLAN_FULL_JOIN;
-+ }
- }
- }
- if (!table->no_keyread)
-@@ -10274,6 +10280,7 @@
- (ulong) rows_limit,test(group)));
-
- status_var_increment(thd->status_var.created_tmp_tables);
-+ thd->query_plan_flags|= QPLAN_TMP_TABLE;
-
- if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES))
- temp_pool_slot = bitmap_lock_set_next(&temp_pool);
-@@ -11175,6 +11182,7 @@
- goto err;
- }
- status_var_increment(table->in_use->status_var.created_tmp_disk_tables);
-+ table->in_use->query_plan_flags|= QPLAN_TMP_DISK;
- share->db_record_offset= 1;
- DBUG_RETURN(0);
- err:
-@@ -11193,6 +11201,14 @@
- save_proc_info=thd->proc_info;
- thd_proc_info(thd, "removing tmp table");
-
-+ thd->tmp_tables_used++;
-+ if (entry->file)
-+ {
-+ thd->tmp_tables_size += entry->file->stats.data_file_length;
-+ if (entry->file->ht->db_type != DB_TYPE_HEAP)
-+ thd->tmp_tables_disk_used++;
-+ }
-+
- // Release latches since this can take a long time
- ha_release_temporary_latches(thd);
-
---- a/sql/sql_show.cc
-+++ b/sql/sql_show.cc
-@@ -1950,8 +1950,17 @@
- table->field[4]->store(command_name[tmp->command].str,
- command_name[tmp->command].length, cs);
- /* MYSQL_TIME */
-- table->field[5]->store((longlong)(tmp->start_time ?
-- now - tmp->start_time : 0), FALSE);
-+ longlong value_in_time_column= 0;
-+ if(tmp->start_time)
-+ {
-+ value_in_time_column = (now - tmp->start_time);
-+ if(value_in_time_column > now)
-+ {
-+ value_in_time_column= 0;
-+ }
-+ }
-+ table->field[5]->store(value_in_time_column, FALSE);
-+
- /* STATE */
- if ((val= thread_state_info(tmp)))
- {
---- a/sql/sys_vars.cc
-+++ b/sql/sys_vars.cc
-@@ -972,6 +972,36 @@
- NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
- ON_UPDATE(update_cached_long_query_time));
-
-+#ifndef DBUG_OFF
-+static bool update_cached_query_exec_time(sys_var *self, THD *thd,
-+ enum_var_type type)
-+{
-+ if (type == OPT_SESSION)
-+ thd->variables.query_exec_time=
-+ double2ulonglong(thd->variables.query_exec_time_double * 1e6);
-+ else
-+ global_system_variables.query_exec_time=
-+ double2ulonglong(global_system_variables.query_exec_time_double * 1e6);
-+ return false;
-+}
-+
-+static Sys_var_double Sys_query_exec_time(
-+ "query_exec_time",
-+ "Pretend queries take this many seconds. When 0 (the default) use the "
-+ "actual execution time. Used only for debugging.",
-+ SESSION_VAR(query_exec_time_double),
-+ NO_CMD_LINE, VALID_RANGE(0, LONG_TIMEOUT), DEFAULT(0),
-+ NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(0),
-+ ON_UPDATE(update_cached_query_exec_time));
-+static Sys_var_ulong sys_query_exec_id(
-+ "query_exec_id",
-+ "Pretend queries take this query id. When 0 (the default) use the"
-+ "actual query id. Used only for debugging.",
-+ SESSION_VAR(query_exec_id),
-+ NO_CMD_LINE, VALID_RANGE(0, ULONG_MAX), DEFAULT(0), BLOCK_SIZE(1),
-+ NO_MUTEX_GUARD, IN_BINLOG);
-+#endif
-+
- static bool fix_low_prio_updates(sys_var *self, THD *thd, enum_var_type type)
- {
- if (type == OPT_SESSION)
-@@ -2898,6 +2928,134 @@
- DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
- ON_UPDATE(fix_log_state));
-
-+const char *log_slow_filter_name[]= { "qc_miss", "full_scan", "full_join",
-+ "tmp_table", "tmp_table_on_disk", "filesort", "filesort_on_disk", 0};
-+static Sys_var_set Sys_log_slow_filter(
-+ "log_slow_filter",
-+ "Log only the queries that followed certain execution plan. "
-+ "Multiple flags allowed in a comma-separated string. "
-+ "[qc_miss, full_scan, full_join, tmp_table, tmp_table_on_disk, "
-+ "filesort, filesort_on_disk]",
-+ SESSION_VAR(log_slow_filter), CMD_LINE(REQUIRED_ARG),
-+ log_slow_filter_name, DEFAULT(0));
-+static Sys_var_ulong sys_log_slow_rate_limit(
-+ "log_slow_rate_limit","Rate limit statement writes to slow log to only those from every (1/log_slow_rate_limit) session.",
-+ SESSION_VAR(log_slow_rate_limit), CMD_LINE(REQUIRED_ARG),
-+ VALID_RANGE(1, ULONG_MAX), DEFAULT(1), BLOCK_SIZE(1));
-+const char* log_slow_verbosity_name[] = {
-+ "microtime", "query_plan", "innodb",
-+ "profiling", "profling_use_getrusage",
-+ "minimal", "standard", "full", 0
-+};
-+static ulonglong update_log_slow_verbosity_replace(ulonglong value, ulonglong what, ulonglong by)
-+{
-+ if((value & what) == what)
-+ {
-+ value = value & (~what);
-+ value = value | by;
-+ }
-+ return value;
-+}
-+void update_log_slow_verbosity(ulonglong* value_ptr)
-+{
-+ ulonglong &value = *value_ptr;
-+ ulonglong microtime= ULL(1) << SLOG_V_MICROTIME;
-+ ulonglong query_plan= ULL(1) << SLOG_V_QUERY_PLAN;
-+ ulonglong innodb= ULL(1) << SLOG_V_INNODB;
-+ ulonglong minimal= ULL(1) << SLOG_V_MINIMAL;
-+ ulonglong standard= ULL(1) << SLOG_V_STANDARD;
-+ ulonglong full= ULL(1) << SLOG_V_FULL;
-+ value= update_log_slow_verbosity_replace(value,minimal,microtime);
-+ value= update_log_slow_verbosity_replace(value,standard,microtime | query_plan);
-+ value= update_log_slow_verbosity_replace(value,full,microtime | query_plan | innodb);
-+}
-+static bool update_log_slow_verbosity_helper(sys_var */*self*/, THD *thd,
-+ enum_var_type type)
-+{
-+ if(type == OPT_SESSION)
-+ {
-+ update_log_slow_verbosity(&(thd->variables.log_slow_verbosity));
-+ }
-+ else
-+ {
-+ update_log_slow_verbosity(&(global_system_variables.log_slow_verbosity));
-+ }
-+ return false;
-+}
-+void init_slow_query_log_use_global_control()
-+{
-+ update_log_slow_verbosity(&(global_system_variables.log_slow_verbosity));
-+}
-+static Sys_var_set Sys_log_slow_verbosity(
-+ "log_slow_verbosity",
-+ "Choose how verbose the messages to your slow log will be. "
-+ "Multiple flags allowed in a comma-separated string. [microtime, query_plan, innodb, profiling, profiling_use_getrusage]",
-+ SESSION_VAR(log_slow_verbosity), CMD_LINE(REQUIRED_ARG),
-+ log_slow_verbosity_name, DEFAULT(SLOG_V_MICROTIME),
-+ NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
-+ ON_UPDATE(update_log_slow_verbosity_helper));
-+static Sys_var_mybool Sys_log_slow_slave_statements(
-+ "log_slow_slave_statements",
-+ "Log queries replayed be the slave SQL thread",
-+ GLOBAL_VAR(opt_log_slow_slave_statements), CMD_LINE(OPT_ARG),
-+ DEFAULT(FALSE));
-+static Sys_var_mybool Sys_log_slow_admin_statements(
-+ "log_slow_admin_statements",
-+ "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements"
-+ " to the slow log if it is open.",
-+ GLOBAL_VAR(opt_log_slow_admin_statements), CMD_LINE(OPT_ARG),
-+ DEFAULT(FALSE));
-+static Sys_var_mybool Sys_log_slow_sp_statements(
-+ "log_slow_sp_statements",
-+ "Log slow statements executed by stored procedure to the slow log if it is open.",
-+ GLOBAL_VAR(opt_log_slow_sp_statements), CMD_LINE(OPT_ARG),
-+ DEFAULT(TRUE));
-+static Sys_var_mybool Sys_slow_query_log_timestamp_always(
-+ "slow_query_log_timestamp_always",
-+ "Timestamp is printed for all records of the slow log even if they are same time.",
-+ GLOBAL_VAR(opt_slow_query_log_timestamp_always), CMD_LINE(OPT_ARG),
-+ DEFAULT(FALSE));
-+const char *slow_query_log_use_global_control_name[]= { "log_slow_filter", "log_slow_rate_limit", "log_slow_verbosity", "long_query_time", "min_examined_row_limit", "all", 0};
-+static bool update_slow_query_log_use_global_control(sys_var */*self*/, THD */*thd*/,
-+ enum_var_type /*type*/)
-+{
-+ if(opt_slow_query_log_use_global_control & (ULL(1) << SLOG_UG_ALL))
-+ {
-+ opt_slow_query_log_use_global_control=
-+ SLOG_UG_LOG_SLOW_FILTER | SLOG_UG_LOG_SLOW_RATE_LIMIT | SLOG_UG_LOG_SLOW_VERBOSITY |
-+ SLOG_UG_LONG_QUERY_TIME | SLOG_UG_MIN_EXAMINED_ROW_LIMIT;
-+ }
-+ return false;
-+}
-+void init_log_slow_verbosity()
-+{
-+ update_slow_query_log_use_global_control(0,0,OPT_GLOBAL);
-+}
-+static Sys_var_set Sys_slow_query_log_use_global_control(
-+ "slow_query_log_use_global_control",
-+ "Choose flags, wich always use the global variables. Multiple flags allowed in a comma-separated string. [none, log_slow_filter, log_slow_rate_limit, log_slow_verbosity, long_query_time, min_examined_row_limit, all]",
-+ GLOBAL_VAR(opt_slow_query_log_use_global_control), CMD_LINE(REQUIRED_ARG),
-+ slow_query_log_use_global_control_name, DEFAULT(0),
-+ NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
-+ ON_UPDATE(update_slow_query_log_use_global_control));
-+const char *slow_query_log_timestamp_precision_name[]= { "second", "microsecond", 0 };
-+static Sys_var_enum Sys_slow_query_log_timestamp_precision(
-+ "slow_query_log_timestamp_precision",
-+ "Log slow statements executed by stored procedure to the slow log if it is open. [second, microsecond]",
-+ GLOBAL_VAR(opt_slow_query_log_timestamp_precision), CMD_LINE(REQUIRED_ARG),
-+ slow_query_log_timestamp_precision_name, DEFAULT(SLOG_SECOND));
-+
-+const char* slow_query_log_rate_name[]= {"session", "query", 0};
-+static Sys_var_enum Sys_slow_query_log_rate_type(
-+ "log_slow_rate_type",
-+ "Choose the log_slow_rate_limit behavior: session or query. "
-+ "When you choose 'session' - every %log_slow_rate_limit connection "
-+ "will be processed to slow query log. "
-+ "When you choose 'query' - every %log_slow_rate_limit query "
-+ "will be processed to slow query log. "
-+ "[session, query]",
-+ GLOBAL_VAR(opt_slow_query_log_rate_type), CMD_LINE(REQUIRED_ARG),
-+ slow_query_log_rate_name, DEFAULT(SLOG_RT_SESSION));
- /* Synonym of "slow_query_log" for consistency with SHOW VARIABLES output */
- static Sys_var_mybool Sys_log_slow(
- "log_slow_queries",
---- a/sql/sql_profile.cc
-+++ b/sql/sql_profile.cc
-@@ -243,7 +243,8 @@
- {
- time_usecs= (double) my_getsystime() / 10.0; /* 1 sec was 1e7, now is 1e6 */
- #ifdef HAVE_GETRUSAGE
-- getrusage(RUSAGE_SELF, &rusage);
-+ if ((profile->get_profiling())->enabled_getrusage())
-+ getrusage(RUSAGE_SELF, &rusage);
- #elif defined(_WIN32)
- FILETIME ftDummy;
- // NOTE: Get{Process|Thread}Times has a granularity of the clock interval,
-@@ -251,6 +252,19 @@
- // measurable by this function.
- GetProcessTimes(GetCurrentProcess(), &ftDummy, &ftDummy, &ftKernel, &ftUser);
- #endif
-+
-+#ifdef HAVE_CLOCK_GETTIME
-+ struct timespec tp;
-+
-+ if (!(clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)))
-+ {
-+ cpu_time_usecs= tp.tv_sec*1000000000.0 + tp.tv_nsec;
-+ }
-+ else
-+#endif
-+ {
-+ cpu_time_usecs= 0;
-+ }
- }
-
-
-@@ -366,7 +380,8 @@
- finish_current_query();
- }
-
-- enabled= ((thd->variables.option_bits & OPTION_PROFILING) != 0);
-+ enabled= ((thd->variables.option_bits & OPTION_PROFILING) != 0) ||
-+ ((thd->variables.log_slow_verbosity & (ULL(1) << SLOG_V_PROFILING)) != 0);
-
- if (! enabled) DBUG_VOID_RETURN;
-
-@@ -404,7 +419,8 @@
- status_change("ending", NULL, NULL, 0);
-
- if ((enabled) && /* ON at start? */
-- ((thd->variables.option_bits & OPTION_PROFILING) != 0) && /* and ON at end? */
-+ (((thd->variables.option_bits & OPTION_PROFILING) != 0) ||
-+ ((thd->variables.log_slow_verbosity & (ULL(1) << SLOG_V_PROFILING)) != 0)) && /* and ON at end? */
- (current->query_source != NULL) &&
- (! current->entries.is_empty()))
- {
-@@ -505,6 +521,118 @@
- DBUG_VOID_RETURN;
- }
-
-+bool PROFILING::enabled_getrusage()
-+{
-+ return ((thd->variables.log_slow_verbosity & (ULL(1) << SLOG_V_PROFILING_USE_GETRUSAGE)) != 0);
-+}
-+
-+/**
-+ For a given profile entry specified by a name and 2 time measurements,
-+ print its normalized name (i.e. with all spaces replaced with underscores)
-+ along with its wall clock and CPU time.
-+*/
-+
-+static void my_b_print_status(IO_CACHE *log_file, const char *status,
-+ PROF_MEASUREMENT *start, PROF_MEASUREMENT *stop)
-+{
-+ DBUG_ENTER("my_b_print_status");
-+ DBUG_ASSERT(log_file != NULL && status != NULL);
-+ char query_time_buff[22+7];
-+ const char *tmp;
-+
-+ my_b_printf(log_file, "Profile_");
-+ for (tmp= status; *tmp; tmp++)
-+ my_b_write_byte(log_file, *tmp == ' ' ? '_' : *tmp);
-+
-+ snprintf(query_time_buff, sizeof(query_time_buff), "%.6f",
-+ (stop->time_usecs - start->time_usecs) / (1000.0 * 1000));
-+ my_b_printf(log_file, ": %s ", query_time_buff);
-+
-+ my_b_printf(log_file, "Profile_");
-+ for (tmp= status; *tmp; tmp++)
-+ my_b_write_byte(log_file, *tmp == ' ' ? '_' : *tmp);
-+ my_b_printf(log_file, "_cpu: ");
-+
-+ snprintf(query_time_buff, sizeof(query_time_buff), "%.6f",
-+ (stop->cpu_time_usecs - start->cpu_time_usecs) /
-+ (1000.0 * 1000 * 1000));
-+ my_b_printf(log_file, "%s ", query_time_buff);
-+
-+ DBUG_VOID_RETURN;
-+}
-+
-+/**
-+ Print output for current query to file
-+*/
-+
-+int PROFILING::print_current(IO_CACHE *log_file)
-+{
-+ DBUG_ENTER("PROFILING::print_current");
-+ ulonglong row_number= 0;
-+
-+ QUERY_PROFILE *query;
-+ /* Get current query */
-+ if (current == NULL)
-+ {
-+ DBUG_RETURN(0);
-+ }
-+
-+ query= current;
-+
-+ my_b_printf(log_file, "# ");
-+
-+ void *entry_iterator;
-+ PROF_MEASUREMENT *entry= NULL, *previous= NULL, *first= NULL;
-+ /* ...and for each query, go through all its state-change steps. */
-+ for (entry_iterator= query->entries.new_iterator();
-+ entry_iterator != NULL;
-+ entry_iterator= query->entries.iterator_next(entry_iterator),
-+ previous=entry, row_number++)
-+ {
-+ entry= query->entries.iterator_value(entry_iterator);
-+
-+ /* Skip the first. We count spans of fence, not fence-posts. */
-+ if (previous == NULL) {first= entry; continue;}
-+
-+ if (thd->lex->sql_command == SQLCOM_SHOW_PROFILE)
-+ {
-+ /*
-+ We got here via a SHOW command. That means that we stored
-+ information about the query we wish to show and that isn't
-+ in a WHERE clause at a higher level to filter out rows we
-+ wish to exclude.
-+
-+ Because that functionality isn't available in the server yet,
-+ we must filter here, at the wrong level. Once one can con-
-+ struct where and having conditions at the SQL layer, then this
-+ condition should be ripped out.
-+ */
-+ if (thd->lex->profile_query_id == 0) /* 0 == show final query */
-+ {
-+ if (query != last)
-+ continue;
-+ }
-+ else
-+ {
-+ if (thd->lex->profile_query_id != query->profiling_query_id)
-+ continue;
-+ }
-+ }
-+
-+ my_b_print_status(log_file, previous->status, previous, entry);
-+ }
-+
-+ my_b_write_byte(log_file, '\n');
-+ if ((entry != NULL) && (first != NULL))
-+ {
-+ my_b_printf(log_file, "# ");
-+ my_b_print_status(log_file, "total", first, entry);
-+ my_b_write_byte(log_file, '\n');
-+ }
-+
-+ DBUG_RETURN(0);
-+}
-+
- /**
- Fill the information schema table, "query_profile", as defined in show.cc .
- There are two ways to get to this function: Selecting from the information
-@@ -600,6 +728,8 @@
-
- #ifdef HAVE_GETRUSAGE
-
-+ if (enabled_getrusage())
-+ {
- my_decimal cpu_utime_decimal, cpu_stime_decimal;
-
- double2my_decimal(E_DEC_FATAL_ERROR,
-@@ -687,6 +817,7 @@
- table->field[14]->store((uint32)(entry->rusage.ru_nswap -
- previous->rusage.ru_nswap), true);
- table->field[14]->set_notnull();
-+ }
- #else
- /* TODO: Add swap info for non-BSD systems */
- #endif
---- a/sql/sql_profile.h
-+++ b/sql/sql_profile.h
-@@ -164,11 +164,15 @@
- */
- class PROF_MEASUREMENT
- {
--private:
-- friend class QUERY_PROFILE;
-- friend class PROFILING;
--
- QUERY_PROFILE *profile;
-+
-+ char *allocated_status_memory;
-+
-+ void set_label(const char *status_arg, const char *function_arg,
-+ const char *file_arg, unsigned int line_arg);
-+ void clean_up();
-+
-+public:
- char *status;
- #ifdef HAVE_GETRUSAGE
- struct rusage rusage;
-@@ -181,12 +185,7 @@
- unsigned int line;
-
- double time_usecs;
-- char *allocated_status_memory;
--
-- void set_label(const char *status_arg, const char *function_arg,
-- const char *file_arg, unsigned int line_arg);
-- void clean_up();
--
-+ double cpu_time_usecs;
- PROF_MEASUREMENT();
- PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg);
- PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg,
-@@ -231,6 +230,11 @@
-
- /* Show this profile. This is called by PROFILING. */
- bool show(uint options);
-+
-+public:
-+
-+ inline PROFILING * get_profiling() { return profiling; };
-+
- };
-
-
-@@ -276,9 +280,11 @@
-
- /* SHOW PROFILES */
- bool show_profiles();
-+ bool enabled_getrusage();
-
- /* ... from INFORMATION_SCHEMA.PROFILING ... */
- int fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond);
-+ int print_current(IO_CACHE *log_file);
- };
-
- # endif /* HAVE_PROFILING */
---- /dev/null
-+++ b/mysql-test/include/log_grep.inc
-@@ -0,0 +1,41 @@
-+--echo [log_grep.inc] file: $log_file pattern: $grep_pattern
-+perl;
-+ $log_file= $ENV{'log_file'};
-+ $log_file_full_path= $ENV{'log_file_full_path'};
-+ $log_slow_rate_test= $ENV{'log_slow_rate_test'};
-+ open(FILE, "$log_file_full_path")
-+ or die("Cannot open file $log_file_full_path: $!\n");
-+
-+ if ($log_slow_rate_test) {
-+ $one= 0;
-+ $two= 0;
-+ $three= 0;
-+ while(<FILE>) {
-+ $one++ if(/'connection_one'/);
-+ $two++ if(/'connection_two'/);
-+ $three++ if(/'connection_three'/);
-+ }
-+ $sum= $one + $two + $three;
-+ $zero= 0;
-+ if ($one == 0) {
-+ $zero++;
-+ }
-+ if ($two == 0) {
-+ $zero++;
-+ }
-+ if ($three == 0) {
-+ $zero++;
-+ }
-+ print "[log_grep.inc] sum: $sum\n";
-+ print "[log_grep.inc] zero: $zero\n";
-+ }
-+ else {
-+ $grep_pattern= $ENV{'grep_pattern'};
-+ $lines= 0;
-+ while(<FILE>) {
-+ $lines++ if (/$grep_pattern/);
-+ }
-+ print "[log_grep.inc] lines: $lines\n";
-+ }
-+ close(FILE);
-+EOF
---- /dev/null
-+++ b/mysql-test/include/log_start.inc
-@@ -0,0 +1,16 @@
-+--disable_query_log
-+--let log_file_full_path = $MYSQLTEST_VARDIR/$log_file
-+SET @slow_query_log_old=@@slow_query_log;
-+SET @slow_query_log_file_old= @@slow_query_log_file;
-+SET GLOBAL slow_query_log=OFF;
-+perl;
-+ $log_file_full_path= $ENV{'log_file_full_path'};
-+ unlink $log_file_full_path;
-+ open(FILE, '>', $log_file_full_path)
-+ or die "Cannot create log file $log_file_full_path, reason: $!";
-+ close(FILE);
-+EOF
-+--echo [log_start.inc] $log_file
-+EVAL SET GLOBAL slow_query_log_file="$log_file_full_path";
-+SET GLOBAL slow_query_log=ON;
-+--enable_query_log
---- /dev/null
-+++ b/mysql-test/include/log_stop.inc
-@@ -0,0 +1,7 @@
-+--disable_query_log
-+FLUSH LOGS;
-+SET GLOBAL slow_query_log=OFF;
-+--echo [log_stop.inc] $log_file
-+SET GLOBAL slow_query_log_file= @slow_query_log_file_old;
-+SET GLOBAL slow_query_log= @slow_query_log_old;
-+--enable_query_log
---- /dev/null
-+++ b/mysql-test/r/percona_bug643149.result
-@@ -0,0 +1,21 @@
-+SET @old_slow_query_log_file=@@global.slow_query_log_file;
-+SET GLOBAL slow_query_log=on;
-+SET LOCAL log_slow_verbosity='profiling';
-+SET LOCAL long_query_time=0;
-+SET GLOBAL slow_query_log_file='MYSQLTEST_VARDIR/percona_bug643149_slow.log';;
-+SELECT 1;
-+1
-+1
-+# User@Host: root[root] @ localhost []
-+# Thread_id: X Schema: test Last_errno: X Killed: X
-+# Query_time: X.X Lock_time: X.X Rows_sent: X Rows_examined: X Rows_affected: X Rows_read: X
-+# Bytes_sent: X Tmp_tables: X Tmp_disk_tables: X Tmp_table_sizes: X
-+# Profile_starting: X.X Profile_starting_cpu: X.X Profile_Opening_tables: X.X Profile_Opening_tables_cpu: X.X Profile_query_end: X.X Profile_query_end_cpu: X.X Profile_closing_tables: X.X Profile_closing_tables_cpu: X.X Profile_freeing_items: X.X Profile_freeing_items_cpu: X.X Profile_logging_slow_query: X.X Profile_logging_slow_query_cpu: X.X
-+# Profile_total: X.X Profile_total_cpu: X.X
-+# User@Host: root[root] @ localhost []
-+# Thread_id: X Schema: test Last_errno: X Killed: X
-+# Query_time: X.X Lock_time: X.X Rows_sent: X Rows_examined: X Rows_affected: X Rows_read: X
-+# Bytes_sent: X Tmp_tables: X Tmp_disk_tables: X Tmp_table_sizes: X
-+# Profile_starting: X.X Profile_starting_cpu: X.X Profile_checking_permissions: X.X Profile_checking_permissions_cpu: X.X Profile_Opening_tables: X.X Profile_Opening_tables_cpu: X.X Profile_init: X.X Profile_init_cpu: X.X Profile_optimizing: X.X Profile_optimizing_cpu: X.X Profile_executing: X.X Profile_executing_cpu: X.X Profile_end: X.X Profile_end_cpu: X.X Profile_query_end: X.X Profile_query_end_cpu: X.X Profile_closing_tables: X.X Profile_closing_tables_cpu: X.X Profile_freeing_items: X.X Profile_freeing_items_cpu: X.X Profile_logging_slow_query: X.X Profile_logging_slow_query_cpu: X.X
-+# Profile_total: X.X Profile_total_cpu: X.X
-+SET GLOBAL slow_query_log_file=@old_slow_query_log_file;
---- /dev/null
-+++ b/mysql-test/r/percona_log_slow_filter-cl.result
-@@ -0,0 +1,6 @@
-+SHOW VARIABLES LIKE 'log_slow_filter';
-+Variable_name Value
-+log_slow_filter full_join
-+SHOW GLOBAL VARIABLES LIKE 'log_slow_filter';
-+Variable_name Value
-+log_slow_filter full_join
---- /dev/null
-+++ b/mysql-test/r/percona_log_slow_filter.result
-@@ -0,0 +1,16 @@
-+CREATE TABLE t(id INT PRIMARY KEY);
-+INSERT INTO t VALUES(1);
-+INSERT INTO t VALUES(2);
-+INSERT INTO t VALUES(3);
-+SET long_query_time=1;
-+SET log_slow_filter=full_join;
-+[log_start.inc] percona.slow_extended.log_slow_filter
-+SET query_exec_time = 1.1;
-+SELECT * FROM t AS t1, t AS t2;
-+SET query_exec_time = default;
-+[log_stop.inc] percona.slow_extended.log_slow_filter
-+SET log_slow_filter=default;
-+SET long_query_time=default;
-+[log_grep.inc] file: percona.slow_extended.log_slow_filter pattern: Query_time
-+[log_grep.inc] lines: 1
-+DROP TABLE t;
---- /dev/null
-+++ b/mysql-test/r/percona_log_slow_slave_statements-cl.result
-@@ -0,0 +1,6 @@
-+SHOW VARIABLES LIKE 'log_slow_slave_statements';
-+Variable_name Value
-+log_slow_slave_statements ON
-+SHOW GLOBAL VARIABLES LIKE 'log_slow_slave_statements';
-+Variable_name Value
-+log_slow_slave_statements ON
---- /dev/null
-+++ b/mysql-test/r/percona_log_slow_slave_statements-innodb.result
-@@ -0,0 +1,19 @@
-+include/master-slave.inc
-+[connection master]
-+DROP TABLE IF EXISTS t;
-+CREATE TABLE t(id INT,data CHAR(30)) ENGINE=InnoDB;
-+INSERT INTO t VALUES
-+(1,"aaaaabbbbbcccccdddddeeeeefffff"),
-+(2,"aaaaabbbbbcccccdddddeeeeefffff"),
-+(3,"aaaaabbbbbcccccdddddeeeeefffff"),
-+(4,"aaaaabbbbbcccccdddddeeeeefffff"),
-+(5,"aaaaabbbbbcccccdddddeeeeefffff");
-+INSERT INTO t SELECT t2.id,t2.data from t as t1, t as t2;
-+INSERT INTO t SELECT t2.id,t2.data from t as t1, t as t2;
-+[log_start.inc] percona.slow_extended.log_slow_slave_statements-innodb
-+INSERT INTO t SELECT t.id,t.data from t;
-+[log_stop.inc] percona.slow_extended.log_slow_slave_statements-innodb
-+[log_grep.inc] file: percona.slow_extended.log_slow_slave_statements-innodb pattern: InnoDB_IO_r_ops
-+[log_grep.inc] lines: 1
-+DROP TABLE t;
-+include/rpl_end.inc
---- /dev/null
-+++ b/mysql-test/r/percona_log_slow_slave_statements.result
-@@ -0,0 +1,45 @@
-+include/master-slave.inc
-+[connection master]
-+DROP TABLE IF EXISTS t;
-+CREATE TABLE t(id INT);
-+[log_start.inc] percona.slow_extended.log_slow_slave_statements
-+LINE 1
-+LOG_SLOW_SLAVE_STATAMENTS is OFF
-+LOG_SLOW_SLAVE_STATEMENTS=ON
-+LOG_SLOW_SLAVE_STATAMENTS is ON
-+LINE 2
-+include/restart_slave.inc
-+LOG_SLOW_SLAVE_STATAMENTS is ON
-+LINE 3
-+LOG_SLOW_SLAVE_STATAMENTS is ON
-+LOG_SLOW_SLAVE_STATEMENTS=OFF
-+LOG_SLOW_SLAVE_STATAMENTS is OFF
-+LINE 4
-+include/restart_slave.inc
-+LOG_SLOW_SLAVE_STATAMENTS is OFF
-+LINE 5
-+LOG_SLOW_SLAVE_STATAMENTS is OFF
-+LOG_SLOW_SLAVE_STATEMENTS=ON
-+LOG_SLOW_SLAVE_STATAMENTS is ON
-+LINE 6
-+include/restart_slave.inc
-+LOG_SLOW_SLAVE_STATAMENTS is ON
-+LINE 7
-+[log_stop.inc] percona.slow_extended.log_slow_slave_statements
-+SET GLOBAL log_slow_slave_statements=default;
-+[log_grep.inc] file: percona.slow_extended.log_slow_slave_statements pattern: INSERT INTO t VALUES \(1\)
-+[log_grep.inc] lines: 0
-+[log_grep.inc] file: percona.slow_extended.log_slow_slave_statements pattern: INSERT INTO t VALUES \(2\)
-+[log_grep.inc] lines: 0
-+[log_grep.inc] file: percona.slow_extended.log_slow_slave_statements pattern: INSERT INTO t VALUES \(3\)
-+[log_grep.inc] lines: 1
-+[log_grep.inc] file: percona.slow_extended.log_slow_slave_statements pattern: INSERT INTO t VALUES \(4\)
-+[log_grep.inc] lines: 0
-+[log_grep.inc] file: percona.slow_extended.log_slow_slave_statements pattern: INSERT INTO t VALUES \(5\)
-+[log_grep.inc] lines: 0
-+[log_grep.inc] file: percona.slow_extended.log_slow_slave_statements pattern: INSERT INTO t VALUES \(6\)
-+[log_grep.inc] lines: 0
-+[log_grep.inc] file: percona.slow_extended.log_slow_slave_statements pattern: INSERT INTO t VALUES \(7\)
-+[log_grep.inc] lines: 1
-+DROP TABLE t;
-+include/rpl_end.inc
---- /dev/null
-+++ b/mysql-test/r/percona_log_slow_sp_statements-cl.result
-@@ -0,0 +1,6 @@
-+SHOW VARIABLES LIKE 'log_slow_sp_statements';
-+Variable_name Value
-+log_slow_sp_statements ON
-+SHOW GLOBAL VARIABLES LIKE 'log_slow_sp_statements';
-+Variable_name Value
-+log_slow_sp_statements ON
---- /dev/null
-+++ b/mysql-test/r/percona_log_slow_sp_statements.result
-@@ -0,0 +1,25 @@
-+SET long_query_time=1;
-+SET GLOBAL log_slow_sp_statements=ON;
-+SET SESSION query_exec_time=0.1;
-+[log_start.inc] percona.slow_extended.log_slow_sp_statements
-+CREATE PROCEDURE test_f()
-+BEGIN
-+SET SESSION query_exec_time=1.1; SELECT 1;
-+SET SESSION query_exec_time=2.1; SELECT 1;
-+SET SESSION query_exec_time=3.1; SELECT 1;
-+SET SESSION query_exec_time=0.1;
-+END^
-+CALL test_f();
-+1
-+1
-+1
-+1
-+1
-+1
-+[log_stop.inc] percona.slow_extended.log_slow_sp_statements
-+SET SESSION query_exec_time=default;
-+SET GLOBAL log_slow_sp_statements=default;
-+SET long_query_time=default;
-+[log_grep.inc] file: percona.slow_extended.log_slow_sp_statements pattern: Query_time
-+[log_grep.inc] lines: 3
-+DROP PROCEDURE test_f;
---- /dev/null
-+++ b/mysql-test/r/percona_log_slow_verbosity-cl.result
-@@ -0,0 +1,6 @@
-+SHOW VARIABLES LIKE 'log_slow_verbosity';
-+Variable_name Value
-+log_slow_verbosity microtime,query_plan,innodb
-+SHOW GLOBAL VARIABLES LIKE 'log_slow_verbosity';
-+Variable_name Value
-+log_slow_verbosity microtime,query_plan,innodb
---- /dev/null
-+++ b/mysql-test/r/percona_log_slow_verbosity.result
-@@ -0,0 +1,16 @@
-+SET SESSION long_query_time=1;
-+[log_start.inc] percona.slow_extended.log_slow_verbosity
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION log_slow_verbosity=innodb;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=default;
-+[log_stop.inc] percona.slow_extended.log_slow_verbosity
-+SET log_slow_verbosity=default;
-+SET long_query_time=default;
-+[log_grep.inc] file: percona.slow_extended.log_slow_verbosity pattern: No InnoDB statistics available for this query
-+[log_grep.inc] lines: 1
---- /dev/null
-+++ b/mysql-test/r/percona_long_query_time.result
-@@ -0,0 +1,33 @@
-+SET long_query_time=2;
-+[log_start.inc] percona.slow_extended.long_query_time
-+SET SESSION query_exec_time=1.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=3.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=5.1;
-+SELECT 1;
-+1
-+1
-+SET long_query_time=4;
-+SET SESSION query_exec_time=1.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=3.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=5.1;
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=default;
-+SET long_query_time=2;
-+[log_stop.inc] percona.slow_extended.long_query_time
-+SET long_query_time=default;
-+[log_grep.inc] file: percona.slow_extended.long_query_time pattern: Query_time
-+[log_grep.inc] lines: 3
---- /dev/null
-+++ b/mysql-test/r/percona_slow_query_log_timestamp_always-cl.result
-@@ -0,0 +1,6 @@
-+SHOW VARIABLES LIKE 'slow_query_log_timestamp_always';
-+Variable_name Value
-+slow_query_log_timestamp_always ON
-+SHOW GLOBAL VARIABLES LIKE 'slow_query_log_timestamp_always';
-+Variable_name Value
-+slow_query_log_timestamp_always ON
---- /dev/null
-+++ b/mysql-test/r/percona_slow_query_log_timestamp_always.result
-@@ -0,0 +1,41 @@
-+SET long_query_time=2;
-+SET GLOBAL slow_query_log_timestamp_always=ON;
-+[log_start.inc] percona.slow_extended.slow_query_log_timestamp_always
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+1
-+1
-+SELECT 1;
-+1
-+1
-+SELECT 1;
-+1
-+1
-+SET GLOBAL slow_query_log_timestamp_always=OFF;
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+1
-+1
-+SELECT 1;
-+1
-+1
-+SELECT 1;
-+1
-+1
-+SET GLOBAL slow_query_log_timestamp_always=ON;
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+1
-+1
-+SELECT 1;
-+1
-+1
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=default;
-+[log_stop.inc] percona.slow_extended.slow_query_log_timestamp_always
-+SET GLOBAL slow_query_log_timestamp_always=default;
-+SET long_query_time=default;
-+[log_grep.inc] file: percona.slow_extended.slow_query_log_timestamp_always pattern: # Time: [0-9]+[ ]+[0-9]+:[0-9]+:[0-9]+
-+[log_grep.inc] lines: 6
---- /dev/null
-+++ b/mysql-test/r/percona_slow_query_log_timestamp_precision-cl.result
-@@ -0,0 +1,6 @@
-+SHOW VARIABLES LIKE 'slow_query_log_timestamp_precision';
-+Variable_name Value
-+slow_query_log_timestamp_precision microsecond
-+SHOW GLOBAL VARIABLES LIKE 'slow_query_log_timestamp_precision';
-+Variable_name Value
-+slow_query_log_timestamp_precision microsecond
---- /dev/null
-+++ b/mysql-test/r/percona_slow_query_log_timestamp_precision.result
-@@ -0,0 +1,18 @@
-+SET long_query_time=2;
-+[log_start.inc] percona.slow_extended.slow_query_log_timestamp_precision
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+1
-+1
-+SET GLOBAL slow_query_log_timestamp_precision='microsecond';
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=default;
-+[log_stop.inc] percona.slow_extended.slow_query_log_timestamp_precision
-+SET GLOBAL slow_query_log_timestamp_precision=default;
-+SET long_query_time=default;
-+[log_grep.inc] file: percona.slow_extended.slow_query_log_timestamp_precision pattern: # Time: [0-9]+[ ]+[0-9]+:[0-9]+:[0-9]+.[0-9]+
-+[log_grep.inc] lines: 1
-+[log_grep.inc] file: percona.slow_extended.slow_query_log_timestamp_precision pattern: # Time: [0-9]+[ ]+[0-9]+:[0-9]+:[0-9]+
-+[log_grep.inc] lines: 2
---- /dev/null
-+++ b/mysql-test/r/percona_slow_query_log_use_global_control.result
-@@ -0,0 +1,18 @@
-+SET GLOBAL long_query_time=1;
-+[log_start.inc] percona.slow_extended.slow_query_log_use_global_control
-+SET SESSION query_exec_time=1.1;
-+SELECT 1;
-+1
-+1
-+SET GLOBAL log_slow_verbosity=innodb;
-+SET GLOBAL slow_query_log_use_global_control="log_slow_verbosity,long_query_time";
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=default;
-+[log_stop.inc] percona.slow_extended.slow_query_log_use_global_control
-+SET GLOBAL slow_query_log_use_global_control=default;
-+SET GLOBAL log_slow_verbosity=default;
-+SET GLOBAL long_query_time=default;
-+[log_grep.inc] file: percona.slow_extended.slow_query_log_use_global_control pattern: No InnoDB statistics available for this query
-+[log_grep.inc] lines: 1
---- /dev/null
-+++ b/mysql-test/t/percona_bug643149.test
-@@ -0,0 +1,49 @@
-+#
-+# This test suffers from server
-+# Bug#38124 "general_log_file" variable silently unset when using expression
-+# In short:
-+# SET GLOBAL general_log_file = @<whatever>
-+# SET GLOBAL slow_query_log = @<whatever>
-+# cause that the value of these server system variables is set to default
-+# instead of the assigned values. There comes no error message or warning.
-+# If this bug is fixed please
-+# 1. try this test with "let $fixed_bug38124 = 0;"
-+# 2. remove all workarounds if 1. was successful.
-+--source include/have_profiling.inc
-+let $fixed_bug38124 = 0;
-+
-+SET @old_slow_query_log_file=@@global.slow_query_log_file;
-+SET GLOBAL slow_query_log=on;
-+SET LOCAL log_slow_verbosity='profiling';
-+SET LOCAL long_query_time=0;
-+
-+let slogfile=$MYSQLTEST_VARDIR/percona_bug643149_slow.log;
-+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-+--eval SET GLOBAL slow_query_log_file='$slogfile';
-+
-+SELECT 1;
-+
-+perl;
-+ $slogfile= $ENV{'slogfile'};
-+
-+ open(FILE, "$slogfile") or
-+ die("Unable to read slow query log file $slogfile: $!\n");
-+ while(<FILE>) {
-+ next if (!/^#/);
-+ next if (/^# Time:/);
-+ s/[0-9]+/X/g;
-+ print;
-+ }
-+
-+ close(FILE);
-+EOF
-+
-+SET GLOBAL slow_query_log_file=@old_slow_query_log_file;
-+
-+if(!$fixed_bug38124)
-+{
-+ --disable_query_log
-+ let $my_var = `SELECT @old_slow_query_log_file`;
-+ eval SET @@global.slow_query_log_file = '$my_var';
-+ --enable_query_log
-+}
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_filter-cl-master.opt
-@@ -0,0 +1 @@
-+--log_slow_filter=full_join
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_filter-cl.test
-@@ -0,0 +1,2 @@
-+SHOW VARIABLES LIKE 'log_slow_filter';
-+SHOW GLOBAL VARIABLES LIKE 'log_slow_filter';
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_filter.test
-@@ -0,0 +1,26 @@
-+--source include/have_debug.inc
-+
-+CREATE TABLE t(id INT PRIMARY KEY);
-+INSERT INTO t VALUES(1);
-+INSERT INTO t VALUES(2);
-+INSERT INTO t VALUES(3);
-+
-+SET long_query_time=1;
-+SET log_slow_filter=full_join;
-+--let log_file=percona.slow_extended.log_slow_filter
-+--source include/log_start.inc
-+
-+SET query_exec_time = 1.1;
-+--disable_result_log
-+SELECT * FROM t AS t1, t AS t2;
-+--enable_result_log
-+SET query_exec_time = default;
-+
-+--source include/log_stop.inc
-+SET log_slow_filter=default;
-+SET long_query_time=default;
-+
-+--let grep_pattern = Query_time
-+--source include/log_grep.inc
-+
-+DROP TABLE t;
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_slave_statements-cl-master.opt
-@@ -0,0 +1 @@
-+--log_slow_slave_statements
-\ No newline at end of file
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_slave_statements-cl.test
-@@ -0,0 +1,3 @@
-+SHOW VARIABLES LIKE 'log_slow_slave_statements';
-+SHOW GLOBAL VARIABLES LIKE 'log_slow_slave_statements';
-+
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_slave_statements-innodb-slave.opt
-@@ -0,0 +1 @@
-+--long_query_time=0 --log_slow_slave_statements --log_slow_verbosity=innodb
-\ No newline at end of file
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_slave_statements-innodb.test
-@@ -0,0 +1,42 @@
-+--source include/have_binlog_format_statement.inc
-+--source include/master-slave.inc
-+--source include/have_innodb.inc
-+--let log_file=percona.slow_extended.log_slow_slave_statements-innodb
-+
-+connection master;
-+-- disable_warnings
-+DROP TABLE IF EXISTS t;
-+-- enable_warnings
-+
-+CREATE TABLE t(id INT,data CHAR(30)) ENGINE=InnoDB;
-+INSERT INTO t VALUES
-+(1,"aaaaabbbbbcccccdddddeeeeefffff"),
-+(2,"aaaaabbbbbcccccdddddeeeeefffff"),
-+(3,"aaaaabbbbbcccccdddddeeeeefffff"),
-+(4,"aaaaabbbbbcccccdddddeeeeefffff"),
-+(5,"aaaaabbbbbcccccdddddeeeeefffff");
-+INSERT INTO t SELECT t2.id,t2.data from t as t1, t as t2;
-+INSERT INTO t SELECT t2.id,t2.data from t as t1, t as t2;
-+sync_slave_with_master;
-+
-+connection slave;
-+--source include/log_start.inc
-+
-+connection master;
-+INSERT INTO t SELECT t.id,t.data from t;
-+sync_slave_with_master;
-+
-+connection slave;
-+--source include/log_stop.inc
-+
-+--enable_query_log
-+--enable_result_log
-+
-+--let grep_pattern = InnoDB_IO_r_ops
-+--source include/log_grep.inc
-+
-+connection master;
-+DROP TABLE t;
-+sync_slave_with_master;
-+
-+--source include/rpl_end.inc
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_slave_statements-slave.opt
-@@ -0,0 +1 @@
-+--long_query_time=0
-\ No newline at end of file
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_slave_statements.test
-@@ -0,0 +1,117 @@
-+-- source include/have_binlog_format_statement.inc
-+-- source include/master-slave.inc
-+--let log_file=percona.slow_extended.log_slow_slave_statements
-+--let show=SELECT Variable_value FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE Variable_name LIKE 'log_slow_slave_statements';
-+
-+connection master;
-+-- disable_warnings
-+DROP TABLE IF EXISTS t;
-+-- enable_warnings
-+
-+CREATE TABLE t(id INT);
-+sync_slave_with_master;
-+
-+connection slave;
-+--source include/log_start.inc
-+
-+--disable_query_log
-+--disable_result_log
-+
-+--echo LINE 1
-+connection master;
-+INSERT INTO t VALUES (1);
-+sync_slave_with_master;
-+
-+connection slave;
-+--let value=`$show`
-+--echo LOG_SLOW_SLAVE_STATAMENTS is $value
-+--echo LOG_SLOW_SLAVE_STATEMENTS=ON
-+SET GLOBAL log_slow_slave_statements=ON;
-+--let value=`$show`
-+--echo LOG_SLOW_SLAVE_STATAMENTS is $value
-+
-+--echo LINE 2
-+connection master;
-+INSERT INTO t VALUES (2);
-+sync_slave_with_master;
-+
-+--source include/restart_slave_sql.inc
-+
-+connection slave;
-+--let value=`$show`
-+--echo LOG_SLOW_SLAVE_STATAMENTS is $value
-+
-+--echo LINE 3
-+connection master;
-+INSERT INTO t VALUES (3);
-+sync_slave_with_master;
-+
-+connection slave;
-+--let value=`$show`
-+--echo LOG_SLOW_SLAVE_STATAMENTS is $value
-+--echo LOG_SLOW_SLAVE_STATEMENTS=OFF
-+SET GLOBAL log_slow_slave_statements=OFF;
-+--let value=`$show`
-+--echo LOG_SLOW_SLAVE_STATAMENTS is $value
-+
-+--echo LINE 4
-+connection master;
-+INSERT INTO t VALUES (4);
-+sync_slave_with_master;
-+
-+--source include/restart_slave_sql.inc
-+
-+connection slave;
-+--let value=`$show`
-+--echo LOG_SLOW_SLAVE_STATAMENTS is $value
-+
-+--echo LINE 5
-+connection master;
-+INSERT INTO t VALUES (5);
-+sync_slave_with_master;
-+
-+connection slave;
-+--let value=`$show`
-+--echo LOG_SLOW_SLAVE_STATAMENTS is $value
-+--echo LOG_SLOW_SLAVE_STATEMENTS=ON
-+SET GLOBAL log_slow_slave_statements=ON;
-+--let value=`$show`
-+--echo LOG_SLOW_SLAVE_STATAMENTS is $value
-+
-+--echo LINE 6
-+connection master;
-+INSERT INTO t VALUES (6);
-+sync_slave_with_master;
-+
-+--source include/restart_slave_sql.inc
-+
-+connection slave;
-+--let value=`$show`
-+--echo LOG_SLOW_SLAVE_STATAMENTS is $value
-+
-+--echo LINE 7
-+connection master;
-+INSERT INTO t VALUES (7);
-+sync_slave_with_master;
-+
-+--enable_query_log
-+--enable_result_log
-+
-+connection slave;
-+--source include/log_stop.inc
-+SET GLOBAL log_slow_slave_statements=default;
-+
-+connection slave;
-+--let i=1
-+while($i < 8)
-+{
-+--let grep_pattern= INSERT INTO t VALUES \($i\)
-+--source include/log_grep.inc
-+ inc $i;
-+}
-+
-+connection master;
-+DROP TABLE t;
-+sync_slave_with_master;
-+
-+--source include/rpl_end.inc
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_sp_statements-cl-master.opt
-@@ -0,0 +1 @@
-+--log_slow_sp_statements
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_sp_statements-cl.test
-@@ -0,0 +1,2 @@
-+SHOW VARIABLES LIKE 'log_slow_sp_statements';
-+SHOW GLOBAL VARIABLES LIKE 'log_slow_sp_statements';
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_sp_statements.test
-@@ -0,0 +1,29 @@
-+--source include/have_debug.inc
-+
-+SET long_query_time=1;
-+SET GLOBAL log_slow_sp_statements=ON;
-+SET SESSION query_exec_time=0.1;
-+--let log_file=percona.slow_extended.log_slow_sp_statements
-+--source include/log_start.inc
-+
-+delimiter ^;
-+CREATE PROCEDURE test_f()
-+BEGIN
-+ SET SESSION query_exec_time=1.1; SELECT 1;
-+ SET SESSION query_exec_time=2.1; SELECT 1;
-+ SET SESSION query_exec_time=3.1; SELECT 1;
-+ SET SESSION query_exec_time=0.1;
-+END^
-+delimiter ;^
-+
-+CALL test_f();
-+
-+--source include/log_stop.inc
-+SET SESSION query_exec_time=default;
-+SET GLOBAL log_slow_sp_statements=default;
-+SET long_query_time=default;
-+
-+--let grep_pattern = Query_time
-+--source include/log_grep.inc
-+
-+DROP PROCEDURE test_f;
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_verbosity-cl-master.opt
-@@ -0,0 +1 @@
-+--log_slow_verbosity="full"
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_verbosity-cl.test
-@@ -0,0 +1,2 @@
-+SHOW VARIABLES LIKE 'log_slow_verbosity';
-+SHOW GLOBAL VARIABLES LIKE 'log_slow_verbosity';
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_verbosity.test
-@@ -0,0 +1,19 @@
-+--source include/have_innodb.inc
-+--source include/have_debug.inc
-+
-+SET SESSION long_query_time=1;
-+--let log_file=percona.slow_extended.log_slow_verbosity
-+--source include/log_start.inc
-+
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+SET SESSION log_slow_verbosity=innodb;
-+SELECT 1;
-+SET SESSION query_exec_time=default;
-+
-+--source include/log_stop.inc
-+SET log_slow_verbosity=default;
-+SET long_query_time=default;
-+
-+--let grep_pattern = No InnoDB statistics available for this query
-+--source include/log_grep.inc
---- /dev/null
-+++ b/mysql-test/t/percona_long_query_time.test
-@@ -0,0 +1,25 @@
-+--source include/have_debug.inc
-+
-+SET long_query_time=2;
-+--let log_file=percona.slow_extended.long_query_time
-+--source include/log_start.inc
-+
-+SET SESSION query_exec_time=1.1; SELECT 1;
-+SET SESSION query_exec_time=3.1; SELECT 1;
-+SET SESSION query_exec_time=5.1; SELECT 1;
-+
-+SET long_query_time=4;
-+
-+SET SESSION query_exec_time=1.1; SELECT 1;
-+SET SESSION query_exec_time=3.1; SELECT 1;
-+SET SESSION query_exec_time=5.1; SELECT 1;
-+
-+SET SESSION query_exec_time=default;
-+
-+SET long_query_time=2;
-+
-+--source include/log_stop.inc
-+SET long_query_time=default;
-+
-+--let grep_pattern = Query_time
-+--source include/log_grep.inc
---- /dev/null
-+++ b/mysql-test/t/percona_slow_query_log_timestamp_always-cl-master.opt
-@@ -0,0 +1 @@
-+--slow_query_log_timestamp_always
-\ No newline at end of file
---- /dev/null
-+++ b/mysql-test/t/percona_slow_query_log_timestamp_always-cl.test
-@@ -0,0 +1,2 @@
-+SHOW VARIABLES LIKE 'slow_query_log_timestamp_always';
-+SHOW GLOBAL VARIABLES LIKE 'slow_query_log_timestamp_always';
---- /dev/null
-+++ b/mysql-test/t/percona_slow_query_log_timestamp_always.test
-@@ -0,0 +1,34 @@
-+--source include/have_debug.inc
-+
-+SET long_query_time=2;
-+SET GLOBAL slow_query_log_timestamp_always=ON;
-+--let log_file=percona.slow_extended.slow_query_log_timestamp_always
-+--source include/log_start.inc
-+
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+SELECT 1;
-+SELECT 1;
-+
-+SET GLOBAL slow_query_log_timestamp_always=OFF;
-+
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+SELECT 1;
-+SELECT 1;
-+
-+SET GLOBAL slow_query_log_timestamp_always=ON;
-+
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+SELECT 1;
-+SELECT 1;
-+
-+SET SESSION query_exec_time=default;
-+
-+--source include/log_stop.inc
-+SET GLOBAL slow_query_log_timestamp_always=default;
-+SET long_query_time=default;
-+
-+--let grep_pattern = # Time: [0-9]+[ ]+[0-9]+:[0-9]+:[0-9]+
-+--source include/log_grep.inc
---- /dev/null
-+++ b/mysql-test/t/percona_slow_query_log_timestamp_precision-cl-master.opt
-@@ -0,0 +1 @@
-+--slow_query_log_timestamp_precision='microsecond'
-\ No newline at end of file
---- /dev/null
-+++ b/mysql-test/t/percona_slow_query_log_timestamp_precision-cl.test
-@@ -0,0 +1,2 @@
-+SHOW VARIABLES LIKE 'slow_query_log_timestamp_precision';
-+SHOW GLOBAL VARIABLES LIKE 'slow_query_log_timestamp_precision';
---- /dev/null
-+++ b/mysql-test/t/percona_slow_query_log_timestamp_precision-master.opt
-@@ -0,0 +1 @@
-+--slow_query_log_timestamp_always
-\ No newline at end of file
---- /dev/null
-+++ b/mysql-test/t/percona_slow_query_log_timestamp_precision.test
-@@ -0,0 +1,25 @@
-+--source include/have_debug.inc
-+
-+SET long_query_time=2;
-+--let log_file=percona.slow_extended.slow_query_log_timestamp_precision
-+--source include/log_start.inc
-+
-+SET SESSION query_exec_time=2.1;
-+
-+SELECT 1;
-+
-+SET GLOBAL slow_query_log_timestamp_precision='microsecond';
-+
-+SELECT 1;
-+
-+SET SESSION query_exec_time=default;
-+
-+--source include/log_stop.inc
-+SET GLOBAL slow_query_log_timestamp_precision=default;
-+SET long_query_time=default;
-+
-+--let grep_pattern = # Time: [0-9]+[ ]+[0-9]+:[0-9]+:[0-9]+.[0-9]+
-+--source include/log_grep.inc
-+
-+--let grep_pattern = # Time: [0-9]+[ ]+[0-9]+:[0-9]+:[0-9]+
-+--source include/log_grep.inc
---- /dev/null
-+++ b/mysql-test/t/percona_slow_query_log_use_global_control.test
-@@ -0,0 +1,28 @@
-+--source include/have_debug.inc
-+--source include/have_innodb.inc
-+
-+SET GLOBAL long_query_time=1;
-+
-+--let log_file=percona.slow_extended.slow_query_log_use_global_control
-+--source include/log_start.inc
-+
-+SET SESSION query_exec_time=1.1;
-+SELECT 1;
-+
-+SET GLOBAL log_slow_verbosity=innodb;
-+SET GLOBAL slow_query_log_use_global_control="log_slow_verbosity,long_query_time";
-+
-+SELECT 1;
-+
-+SET SESSION query_exec_time=default;
-+
-+--source include/log_stop.inc
-+
-+
-+SET GLOBAL slow_query_log_use_global_control=default;
-+SET GLOBAL log_slow_verbosity=default;
-+SET GLOBAL long_query_time=default;
-+
-+--let grep_pattern = No InnoDB statistics available for this query
-+--source include/log_grep.inc
-+
---- /dev/null
-+++ b/mysql-test/r/percona_slow_query_log_use_global_control-cl.result
-@@ -0,0 +1,6 @@
-+SHOW VARIABLES LIKE 'slow_query_log_use_global_control';
-+Variable_name Value
-+slow_query_log_use_global_control log_slow_verbosity,long_query_time
-+SHOW GLOBAL VARIABLES LIKE 'slow_query_log_use_global_control';
-+Variable_name Value
-+slow_query_log_use_global_control log_slow_verbosity,long_query_time
---- /dev/null
-+++ b/mysql-test/t/percona_slow_query_log_use_global_control-cl-master.opt
-@@ -0,0 +1 @@
-+--slow_query_log_use_global_control="log_slow_verbosity,long_query_time"
---- /dev/null
-+++ b/mysql-test/t/percona_slow_query_log_use_global_control-cl.test
-@@ -0,0 +1,2 @@
-+SHOW VARIABLES LIKE 'slow_query_log_use_global_control';
-+SHOW GLOBAL VARIABLES LIKE 'slow_query_log_use_global_control';
---- /dev/null
-+++ b/mysql-test/r/percona_min_examined_row_limit.result
-@@ -0,0 +1,35 @@
-+drop table if exists t;
-+create table t(id INT PRIMARY KEY);
-+insert into t values(1);
-+insert into t values(2);
-+insert into t values(3);
-+SET GLOBAL long_query_time=2;
-+SET GLOBAL slow_query_log_use_global_control='long_query_time,min_examined_row_limit';
-+[log_start.inc] percona.slow_extended.min_examined_row_limit
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+1
-+1
-+SET GLOBAL min_examined_row_limit=5;
-+select * from t as t1, t as t2;
-+id id
-+1 1
-+2 1
-+3 1
-+1 2
-+2 2
-+3 2
-+1 3
-+2 3
-+3 3
-+SELECT 1;
-+1
-+1
-+SET SESSION query_exec_time=default;
-+[log_stop.inc] percona.slow_extended.min_examined_row_limit
-+SET GLOBAL min_examined_row_limit=default;
-+SET GLOBAL slow_query_log_use_global_control=default;
-+SET GLOBAL long_query_time=default;
-+[log_grep.inc] file: percona.slow_extended.min_examined_row_limit pattern: Query_time
-+[log_grep.inc] lines: 1
-+DROP TABLE t;
---- /dev/null
-+++ b/mysql-test/t/percona_min_examined_row_limit.test
-@@ -0,0 +1,35 @@
-+--source include/have_debug.inc
-+
-+--disable_warnings
-+drop table if exists t;
-+--enable_warnings
-+
-+create table t(id INT PRIMARY KEY);
-+insert into t values(1);
-+insert into t values(2);
-+insert into t values(3);
-+
-+SET GLOBAL long_query_time=2;
-+SET GLOBAL slow_query_log_use_global_control='long_query_time,min_examined_row_limit';
-+--let log_file=percona.slow_extended.min_examined_row_limit
-+--source include/log_start.inc
-+
-+SET SESSION query_exec_time=2.1;
-+SELECT 1;
-+
-+SET GLOBAL min_examined_row_limit=5;
-+
-+select * from t as t1, t as t2;
-+SELECT 1;
-+
-+SET SESSION query_exec_time=default;
-+
-+--source include/log_stop.inc
-+SET GLOBAL min_examined_row_limit=default;
-+SET GLOBAL slow_query_log_use_global_control=default;
-+SET GLOBAL long_query_time=default;
-+
-+--let grep_pattern = Query_time
-+--source include/log_grep.inc
-+
-+DROP TABLE t;
---- a/sql/log_event.cc
-+++ b/sql/log_event.cc
-@@ -2385,6 +2385,14 @@
- start+= host.length;
- }
- }
-+#ifndef DBUG_OFF
-+ if (thd && thd->variables.query_exec_time > 0)
-+ {
-+ *start++= Q_QUERY_EXEC_TIME;
-+ int8store(start, thd->variables.query_exec_time);
-+ start+= 8;
-+ }
-+#endif
- /*
- NOTE: When adding new status vars, please don't forget to update
- the MAX_SIZE_LOG_EVENT_STATUS in log_event.h and update the function
-@@ -2871,6 +2879,17 @@
- data_written= master_data_written= uint4korr(pos);
- pos+= 4;
- break;
-+#if !defined(DBUG_OFF) && !defined(MYSQL_CLIENT)
-+ case Q_QUERY_EXEC_TIME:
-+ {
-+ THD *thd= current_thd;
-+ CHECK_SPACE(pos, end, 8);
-+ if (thd)
-+ thd->variables.query_exec_time= uint8korr(pos);
-+ pos+= 8;
-+ break;
-+ }
-+#endif
- case Q_INVOKER:
- {
- CHECK_SPACE(pos, end, 1);
---- a/sql/log_event.h
-+++ b/sql/log_event.h
-@@ -343,6 +343,10 @@
-
- #define Q_INVOKER 11
-
-+#ifndef DBUG_OFF
-+#define Q_QUERY_EXEC_TIME 250
-+#endif
-+
- /* Intvar event post-header */
-
- /* Intvar event data */
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/r/query_exec_time_basic.result
-@@ -0,0 +1,2 @@
-+SET GLOBAL query_exec_time=default;
-+SET SESSION query_exec_time=default;
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/t/query_exec_time_basic.test
-@@ -0,0 +1,4 @@
-+--source include/have_debug.inc
-+
-+SET GLOBAL query_exec_time=default;
-+SET SESSION query_exec_time=default;
---- /dev/null
-+++ b/mysql-test/r/percona_log_slow_global_control_default.result
-@@ -0,0 +1 @@
-+SET GLOBAL slow_query_log_use_global_control=default;
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_global_control_default.test
-@@ -0,0 +1 @@
-+SET GLOBAL slow_query_log_use_global_control=default;
---- /dev/null
-+++ b/mysql-test/r/percona_slow_extended_log_error.result
-@@ -0,0 +1,10 @@
-+SET long_query_time=0;
-+DROP TABLE IF EXISTS t1;
-+CREATE TABLE t(a INT);
-+[log_start.inc] percona.slow_extended.log_error
-+CREATE TABLE t(a INT);
-+ERROR 42S01: Table 't' already exists
-+[log_stop.inc] percona.slow_extended.log_error
-+[log_grep.inc] file: percona.slow_extended.log_error pattern: Last_errno: 1050
-+[log_grep.inc] lines: 1
-+DROP TABLE t;
---- /dev/null
-+++ b/mysql-test/t/percona_slow_extended_log_error.test
-@@ -0,0 +1,15 @@
-+--let log_file=percona.slow_extended.log_error
-+SET long_query_time=0;
-+--disable_warnings
-+DROP TABLE IF EXISTS t1;
-+--enable_warnings
-+CREATE TABLE t(a INT);
-+--source include/log_start.inc
-+
-+--error ER_TABLE_EXISTS_ERROR
-+CREATE TABLE t(a INT);
-+
-+--source include/log_stop.inc
-+--let grep_pattern = Last_errno: 1050
-+--source include/log_grep.inc
-+DROP TABLE t;
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/t/log_slow_admin_statements_basic.test
-@@ -0,0 +1 @@
-+SELECT @@global.log_slow_admin_statements;
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/r/log_slow_admin_statements_basic.result
-@@ -0,0 +1,3 @@
-+SELECT @@global.log_slow_admin_statements;
-+@@global.log_slow_admin_statements
-+0
---- /dev/null
-+++ b/mysql-test/r/percona_log_slow_admin_statements.result
-@@ -0,0 +1,35 @@
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+Variable_name Value
-+log_slow_admin_statements OFF
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
-+VARIABLE_NAME VARIABLE_VALUE
-+LOG_SLOW_ADMIN_STATEMENTS OFF
-+SET GLOBAL log_slow_admin_statements=true;
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+Variable_name Value
-+log_slow_admin_statements ON
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
-+VARIABLE_NAME VARIABLE_VALUE
-+LOG_SLOW_ADMIN_STATEMENTS ON
-+SET GLOBAL log_slow_admin_statements=false;
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+Variable_name Value
-+log_slow_admin_statements OFF
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
-+VARIABLE_NAME VARIABLE_VALUE
-+LOG_SLOW_ADMIN_STATEMENTS OFF
-+SET GLOBAL log_slow_admin_statements=foo;
-+ERROR 42000: Variable 'log_slow_admin_statements' can't be set to the value of 'foo'
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+Variable_name Value
-+log_slow_admin_statements OFF
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
-+VARIABLE_NAME VARIABLE_VALUE
-+LOG_SLOW_ADMIN_STATEMENTS OFF
-+SET GLOBAL log_slow_admin_statements=default;
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+Variable_name Value
-+log_slow_admin_statements OFF
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
-+VARIABLE_NAME VARIABLE_VALUE
-+LOG_SLOW_ADMIN_STATEMENTS OFF
---- /dev/null
-+++ b/mysql-test/r/percona_log_slow_admin_statements-config_false.result
-@@ -0,0 +1,6 @@
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+Variable_name Value
-+log_slow_admin_statements OFF
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
-+VARIABLE_NAME VARIABLE_VALUE
-+LOG_SLOW_ADMIN_STATEMENTS OFF
---- /dev/null
-+++ b/mysql-test/r/percona_log_slow_admin_statements-config_foo.result
-@@ -0,0 +1,7 @@
-+call mtr.add_suppression("option 'log_slow_admin_statements': boolean value 'foo' wasn't recognized. Set to OFF.");
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+Variable_name Value
-+log_slow_admin_statements OFF
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
-+VARIABLE_NAME VARIABLE_VALUE
-+LOG_SLOW_ADMIN_STATEMENTS OFF
---- /dev/null
-+++ b/mysql-test/r/percona_log_slow_admin_statements-config_true.result
-@@ -0,0 +1,6 @@
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+Variable_name Value
-+log_slow_admin_statements ON
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
-+VARIABLE_NAME VARIABLE_VALUE
-+LOG_SLOW_ADMIN_STATEMENTS ON
---- /dev/null
-+++ b/mysql-test/r/percona_log_slow_admin_statements-config.result
-@@ -0,0 +1,6 @@
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+Variable_name Value
-+log_slow_admin_statements ON
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
-+VARIABLE_NAME VARIABLE_VALUE
-+LOG_SLOW_ADMIN_STATEMENTS ON
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_admin_statements-config_false.cnf
-@@ -0,0 +1,2 @@
-+[mysqld.1]
-+log-slow-admin-statements=false
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_admin_statements-config_foo.cnf
-@@ -0,0 +1,2 @@
-+[mysqld.1]
-+log-slow-admin-statements=foo
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_admin_statements-config_true.cnf
-@@ -0,0 +1,2 @@
-+[mysqld.1]
-+log-slow-admin-statements=true
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_admin_statements-config.cnf
-@@ -0,0 +1,2 @@
-+[mysqld.1]
-+log-slow-admin-statements
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_admin_statements.test
-@@ -0,0 +1,20 @@
-+# default value
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
-+# set value to 'true'
-+SET GLOBAL log_slow_admin_statements=true;
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
-+# set value to 'false'
-+SET GLOBAL log_slow_admin_statements=false;
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
-+# set value to 'foo'
-+--error ER_WRONG_VALUE_FOR_VAR
-+SET GLOBAL log_slow_admin_statements=foo;
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
-+# set value to default
-+SET GLOBAL log_slow_admin_statements=default;
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_admin_statements-config_false.test
-@@ -0,0 +1,2 @@
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_admin_statements-config_foo.test
-@@ -0,0 +1,3 @@
-+call mtr.add_suppression("option 'log_slow_admin_statements': boolean value 'foo' wasn't recognized. Set to OFF.");
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_admin_statements-config_true.test
-@@ -0,0 +1,2 @@
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
---- /dev/null
-+++ b/mysql-test/t/percona_log_slow_admin_statements-config.test
-@@ -0,0 +1,2 @@
-+SHOW GLOBAL VARIABLES like 'log_slow_admin_statements';
-+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='log_slow_admin_statements';
---- a/mysql-test/r/mysqld--help-notwin.result
-+++ b/mysql-test/r/mysqld--help-notwin.result
-@@ -250,15 +250,38 @@
- --log-slow-admin-statements
- Log slow OPTIMIZE, ANALYZE, ALTER and other
- administrative statements to the slow log if it is open.
-+ --log-slow-filter=name
-+ Log only the queries that followed certain execution
-+ plan. Multiple flags allowed in a comma-separated string.
-+ [qc_miss, full_scan, full_join, tmp_table,
-+ tmp_table_on_disk, filesort, filesort_on_disk]
- --log-slow-queries[=name]
- Log slow queries to a table or log file. Defaults logging
- to table mysql.slow_log or hostname-slow.log if
- --log-output=file is used. Must be enabled to activate
- other slow log options. Deprecated option, use
- --slow-query-log/--slow-query-log-file instead.
-+ --log-slow-rate-limit=#
-+ Rate limit statement writes to slow log to only those
-+ from every (1/log_slow_rate_limit) session.
-+ --log-slow-rate-type=name
-+ Choose the log_slow_rate_limit behavior: session or
-+ query. When you choose 'session' - every
-+ %log_slow_rate_limit connection will be processed to slow
-+ query log. When you choose 'query' - every
-+ %log_slow_rate_limit query will be processed to slow
-+ query log. [session, query]
- --log-slow-slave-statements
-- Log slow statements executed by slave thread to the slow
-- log if it is open.
-+ Log queries replayed be the slave SQL thread
-+ --log-slow-sp-statements
-+ Log slow statements executed by stored procedure to the
-+ slow log if it is open.
-+ (Defaults to on; use --skip-log-slow-sp-statements to disable.)
-+ --log-slow-verbosity=name
-+ Choose how verbose the messages to your slow log will be.
-+ Multiple flags allowed in a comma-separated string.
-+ [microtime, query_plan, innodb, profiling,
-+ profiling_use_getrusage]
- --log-tc=name Path to transaction coordinator log (used for
- transactions that affect more than one storage engine,
- when binary log is disabled).
-@@ -660,6 +683,18 @@
- Log slow queries to given log file. Defaults logging to
- hostname-slow.log. Must be enabled to activate other slow
- log options
-+ --slow-query-log-timestamp-always
-+ Timestamp is printed for all records of the slow log even
-+ if they are same time.
-+ --slow-query-log-timestamp-precision=name
-+ Log slow statements executed by stored procedure to the
-+ slow log if it is open. [second, microsecond]
-+ --slow-query-log-use-global-control=name
-+ Choose flags, wich always use the global variables.
-+ Multiple flags allowed in a comma-separated string.
-+ [none, log_slow_filter, log_slow_rate_limit,
-+ log_slow_verbosity, long_query_time,
-+ min_examined_row_limit, all]
- --socket=name Socket file to use for connection
- --sort-buffer-size=#
- Each thread that needs to do a sort allocates a buffer of
-@@ -817,7 +852,12 @@
- log-short-format FALSE
- log-slave-updates FALSE
- log-slow-admin-statements FALSE
-+log-slow-filter
-+log-slow-rate-limit 1
-+log-slow-rate-type session
- log-slow-slave-statements FALSE
-+log-slow-sp-statements TRUE
-+log-slow-verbosity
- log-tc tc.log
- log-tc-size 24576
- log-warnings 1
-@@ -933,6 +973,9 @@
- slave-type-conversions
- slow-launch-time 2
- slow-query-log FALSE
-+slow-query-log-timestamp-always FALSE
-+slow-query-log-timestamp-precision second
-+slow-query-log-use-global-control
- sort-buffer-size 2097152
- sporadic-binlog-dump-fail FALSE
- sql-mode
---- /dev/null
-+++ b/mysql-test/r/percona_slow_query_log_rate.result
-@@ -0,0 +1,78 @@
-+SET GLOBAL long_query_time=1;
-+SET GLOBAL log_slow_rate_type='session';
-+SET GLOBAL log_slow_rate_limit=3;
-+[log_start.inc] percona.slow_extended.log_slow_rate_limit
-+SET SESSION query_exec_time=1.1;
-+SET SESSION query_exec_id=1;
-+SELECT 'connection_one';
-+connection_one
-+connection_one
-+SET SESSION query_exec_time=1.1;
-+SET SESSION query_exec_id=2;
-+SELECT 'connection_two';
-+connection_two
-+connection_two
-+SET SESSION query_exec_time=1.1;
-+SET SESSION query_exec_id=3;
-+SELECT 'connection_three';
-+connection_three
-+connection_three
-+SET SESSION query_exec_time=1.1;
-+SET SESSION query_exec_id=4;
-+SELECT 'connection_one';
-+connection_one
-+connection_one
-+SET SESSION query_exec_time=1.1;
-+SET SESSION query_exec_id=5;
-+SELECT 'connection_two';
-+connection_two
-+connection_two
-+SET SESSION query_exec_time=1.1;
-+SET SESSION query_exec_id=6;
-+SELECT 'connection_three';
-+connection_three
-+connection_three
-+[log_stop.inc] percona.slow_extended.log_slow_rate_limit
-+[log_grep.inc] file: percona.slow_extended.log_slow_rate_limit pattern:
-+[log_grep.inc] sum: 2
-+[log_grep.inc] zero: 2
-+SET GLOBAL log_slow_rate_type='query';
-+SET GLOBAL log_slow_rate_limit=2;
-+[log_start.inc] percona.slow_extended.log_slow_rate_limit
-+SET SESSION query_exec_time=1.1;
-+SET SESSION query_exec_id=1;
-+SELECT 'connection_one';
-+connection_one
-+connection_one
-+SET SESSION query_exec_time=1.1;
-+SET SESSION query_exec_id=2;
-+SELECT 'connection_two';
-+connection_two
-+connection_two
-+SET SESSION query_exec_time=1.1;
-+SET SESSION query_exec_id=3;
-+SELECT 'connection_three';
-+connection_three
-+connection_three
-+SET SESSION query_exec_time=1.1;
-+SET SESSION query_exec_id=4;
-+SELECT 'connection_one';
-+connection_one
-+connection_one
-+SET SESSION query_exec_time=1.1;
-+SET SESSION query_exec_id=5;
-+SELECT 'connection_two';
-+connection_two
-+connection_two
-+SET SESSION query_exec_time=1.1;
-+SET SESSION query_exec_id=6;
-+SELECT 'connection_three';
-+connection_three
-+connection_three
-+[log_stop.inc] percona.slow_extended.log_slow_rate_limit
-+[log_grep.inc] file: percona.slow_extended.log_slow_rate_limit pattern:
-+[log_grep.inc] sum: 3
-+[log_grep.inc] zero: 0
-+SET GLOBAL long_query_time=default;
-+SET GLOBAL log_slow_rate_type=default;
-+SET GLOBAL log_slow_rate_limit=default;
---- /dev/null
-+++ b/mysql-test/t/percona_slow_query_log_rate.test
-@@ -0,0 +1,16 @@
-+--source include/have_debug.inc
-+--let log_file=percona.slow_extended.log_slow_rate_limit
-+
-+SET GLOBAL long_query_time=1;
-+
-+SET GLOBAL log_slow_rate_type='session';
-+SET GLOBAL log_slow_rate_limit=3;
-+--source include/percona_slow_query_log_rate.inc
-+
-+SET GLOBAL log_slow_rate_type='query';
-+SET GLOBAL log_slow_rate_limit=2;
-+--source include/percona_slow_query_log_rate.inc
-+
-+SET GLOBAL long_query_time=default;
-+SET GLOBAL log_slow_rate_type=default;
-+SET GLOBAL log_slow_rate_limit=default;
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/t/log_slow_rate_limit_basic.test
-@@ -0,0 +1 @@
-+SELECT @@global.log_slow_rate_limit;
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/r/log_slow_rate_limit_basic.result
-@@ -0,0 +1,3 @@
-+SELECT @@global.log_slow_rate_limit;
-+@@global.log_slow_rate_limit
-+1
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/t/log_slow_rate_type_basic.test
-@@ -0,0 +1 @@
-+SELECT @@global.log_slow_rate_type;
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/r/log_slow_rate_type_basic.result
-@@ -0,0 +1,3 @@
-+SELECT @@global.log_slow_rate_type;
-+@@global.log_slow_rate_type
-+session
---- /dev/null
-+++ b/mysql-test/include/percona_slow_query_log_rate.inc
-@@ -0,0 +1,42 @@
-+--let wait_condition=SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST;
-+--connection default
-+--source include/log_start.inc
-+
-+--connect (connection_one,localhost,root,,)
-+--connect (connection_two,localhost,root,,)
-+--connect (connection_three,localhost,root,,)
-+
-+--let i=2
-+--let k=1
-+
-+while($i)
-+{
-+--connection connection_one
-+SET SESSION query_exec_time=1.1;
-+eval SET SESSION query_exec_id=$k;
-+inc $k;
-+SELECT 'connection_one';
-+
-+--connection connection_two
-+SET SESSION query_exec_time=1.1;
-+eval SET SESSION query_exec_id=$k;
-+inc $k;
-+SELECT 'connection_two';
-+
-+--connection connection_three
-+SET SESSION query_exec_time=1.1;
-+eval SET SESSION query_exec_id=$k;
-+inc $k;
-+SELECT 'connection_three';
-+
-+dec $i;
-+}
-+
-+--connection default
-+--disconnect connection_one
-+--disconnect connection_two
-+--disconnect connection_three
-+--source include/wait_condition.inc
-+--source include/log_stop.inc
-+--let log_slow_rate_test=1
-+--source include/log_grep.inc
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/r/query_exec_id_basic.result
-@@ -0,0 +1,2 @@
-+SET GLOBAL query_exec_id=default;
-+SET SESSION query_exec_id=default;
---- /dev/null
-+++ b/mysql-test/suite/sys_vars/t/query_exec_id_basic.test
-@@ -0,0 +1,4 @@
-+--source include/have_debug.inc
-+
-+SET GLOBAL query_exec_id=default;
-+SET SESSION query_exec_id=default;
+++ /dev/null
-# name : sql_no_fcache.patch
-# introduced : 12
-# maintainer : Oleg
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/client/mysqldump.c
-+++ b/client/mysqldump.c
-@@ -143,6 +143,8 @@
- static uint opt_protocol= 0;
- static char *opt_plugin_dir= 0, *opt_default_auth= 0;
-
-+static my_bool server_supports_sql_no_fcache= FALSE;
-+
- /*
- Dynamic_string wrapper functions. In this file use these
- wrappers, they will terminate the process if there is
-@@ -1496,6 +1498,17 @@
- /* Don't switch charsets for 4.1 and earlier. (bug#34192). */
- server_supports_switching_charsets= FALSE;
- }
-+
-+ /* Check to see if we support SQL_NO_FCACHE on this server. */
-+ if (mysql_query(mysql, "SELECT SQL_NO_FCACHE NOW()") == 0)
-+ {
-+ MYSQL_RES *res = mysql_store_result(mysql);
-+ if (res)
-+ {
-+ mysql_free_result(res);
-+ }
-+ server_supports_sql_no_fcache= TRUE;
-+ }
- /*
- As we're going to set SQL_MODE, it would be lost on reconnect, so we
- cannot reconnect.
-@@ -3177,7 +3190,12 @@
-
- /* now build the query string */
-
-- dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '");
-+ dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ ");
-+ if (server_supports_sql_no_fcache)
-+ {
-+ dynstr_append_checked(&query_string, "/*!50084 SQL_NO_FCACHE */ ");
-+ }
-+ dynstr_append_checked(&query_string, "* INTO OUTFILE '");
- dynstr_append_checked(&query_string, filename);
- dynstr_append_checked(&query_string, "'");
-
-@@ -3227,7 +3245,12 @@
- check_io(md_result_file);
- }
-
-- dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * FROM ");
-+ dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ ");
-+ if (server_supports_sql_no_fcache)
-+ {
-+ dynstr_append_checked(&query_string, "/*!50084 SQL_NO_FCACHE */ ");
-+ }
-+ dynstr_append_checked(&query_string, "* FROM ");
- dynstr_append_checked(&query_string, result_table);
-
- if (where)
---- /dev/null
-+++ b/include/flashcache_ioctl.h
-@@ -0,0 +1,53 @@
-+/****************************************************************************
-+ * flashcache_ioctl.h
-+ * FlashCache: Device mapper target for block-level disk caching
-+ *
-+ * Copyright 2010 Facebook, Inc.
-+ * Author: Mohan Srinivasan (mohan@facebook.com)
-+ *
-+ * Based on DM-Cache:
-+ * Copyright (C) International Business Machines Corp., 2006
-+ * Author: Ming Zhao (mingzhao@ufl.edu)
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; under version 2 of the License.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
-+ ****************************************************************************/
-+
-+#ifndef FLASHCACHE_IOCTL_H
-+#define FLASHCACHE_IOCTL_H
-+
-+#include <linux/types.h>
-+
-+#define FLASHCACHE_IOCTL 0xfe
-+
-+enum {
-+ FLASHCACHEADDNCPID_CMD=200,
-+ FLASHCACHEDELNCPID_CMD,
-+ FLASHCACHEDELNCALL_CMD,
-+ FLASHCACHEADDWHITELIST_CMD,
-+ FLASHCACHEDELWHITELIST_CMD,
-+ FLASHCACHEDELWHITELISTALL_CMD,
-+};
-+
-+#define FLASHCACHEADDNCPID _IOW(FLASHCACHE_IOCTL, FLASHCACHEADDNCPID_CMD, pid_t)
-+#define FLASHCACHEDELNCPID _IOW(FLASHCACHE_IOCTL, FLASHCACHEDELNCPID_CMD, pid_t)
-+#define FLASHCACHEDELNCALL _IOW(FLASHCACHE_IOCTL, FLASHCACHEDELNCALL_CMD, pid_t)
-+
-+#define FLASHCACHEADDBLACKLIST FLASHCACHEADDNCPID
-+#define FLASHCACHEDELBLACKLIST FLASHCACHEDELNCPID
-+#define FLASHCACHEDELALLBLACKLIST FLASHCACHEDELNCALL
-+
-+#define FLASHCACHEADDWHITELIST _IOW(FLASHCACHE_IOCTL, FLASHCACHEADDWHITELIST_CMD, pid_t)
-+#define FLASHCACHEDELWHITELIST _IOW(FLASHCACHE_IOCTL, FLASHCACHEDELWHITELIST_CMD, pid_t)
-+#define FLASHCACHEDELALLWHITELIST _IOW(FLASHCACHE_IOCTL, FLASHCACHEDELWHITELISTALL_CMD, pid_t)
-+
-+#endif
---- /dev/null
-+++ b/patch_info/sql_no_fcache.info
-@@ -0,0 +1,6 @@
-+File=sql_no_fcache.patch
-+Name=Support for flashcache including the SQL_NO_FCACHE option that prevents blocks from being cached during a query.
-+Version=1.0
-+Author=Facebook
-+License=GPL
-+Comment=
---- a/sql/lex.h
-+++ b/sql/lex.h
-@@ -516,6 +516,7 @@
- { "SQL_CACHE", SYM(SQL_CACHE_SYM)},
- { "SQL_CALC_FOUND_ROWS", SYM(SQL_CALC_FOUND_ROWS)},
- { "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM)},
-+ { "SQL_NO_FCACHE", SYM(SQL_NO_FCACHE_SYM)},
- { "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT)},
- { "SQL_THREAD", SYM(SQL_THREAD)},
- { "SQL_TSI_SECOND", SYM(SECOND_SYM)},
---- a/sql/mysqld.h
-+++ b/sql/mysqld.h
-@@ -195,6 +195,8 @@
- extern char language[FN_REFLEN];
- extern "C" MYSQL_PLUGIN_IMPORT ulong server_id;
- extern ulong concurrency;
-+/* flashcache */
-+extern int cachedev_fd;
- extern time_t server_start_time, flush_status_time;
- extern char *opt_mysql_tmpdir, mysql_charsets_dir[];
- extern int mysql_unpacked_real_data_home_len;
---- a/sql/mysqld.cc
-+++ b/sql/mysqld.cc
-@@ -86,6 +86,11 @@
- #ifdef HAVE_SYS_PRCTL_H
- #include <sys/prctl.h>
- #endif
-+#if defined(__linux__)
-+#include <mntent.h>
-+#include <sys/statfs.h>
-+#include "flashcache_ioctl.h"
-+#endif//__linux__
-
- #include <thr_alarm.h>
- #include <ft_global.h>
-@@ -491,6 +496,11 @@
- ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
- ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0;
- ulong max_connections, max_connect_errors;
-+
-+/* flashcache */
-+int cachedev_fd;
-+my_bool cachedev_enabled= FALSE;
-+
- /*
- Maximum length of parameter value which can be set through
- mysql_send_long_data() call.
-@@ -4102,6 +4112,97 @@
- #define decrement_handler_count()
- #endif /* defined(_WIN32) || defined(HAVE_SMEM) */
-
-+#if defined(__linux__)
-+/*
-+ * Auto detect if we support flash cache on the host system.
-+ * This needs to be called before we setuid away from root
-+ * to avoid permission problems on opening the device node.
-+ */
-+static void init_cachedev(void)
-+{
-+ struct statfs stfs_data_home_dir;
-+ struct statfs stfs;
-+ struct mntent *ent;
-+ pid_t pid = getpid();
-+ FILE *mounts;
-+ const char *error_message= NULL;
-+
-+ // disabled by default
-+ cachedev_fd = -1;
-+ cachedev_enabled= FALSE;
-+
-+ if (!mysql_data_home)
-+ {
-+ error_message= "mysql_data_home not set";
-+ goto epilogue;
-+ }
-+
-+ if (statfs(mysql_data_home, &stfs_data_home_dir) < 0)
-+ {
-+ error_message= "statfs failed";
-+ goto epilogue;
-+ }
-+
-+ mounts = setmntent("/etc/mtab", "r");
-+ if (mounts == NULL)
-+ {
-+ error_message= "setmntent failed";
-+ goto epilogue;
-+ }
-+
-+ while ((ent = getmntent(mounts)) != NULL)
-+ {
-+ if (statfs(ent->mnt_dir, &stfs) < 0)
-+ continue;
-+ if (memcmp(&stfs.f_fsid, &stfs_data_home_dir.f_fsid, sizeof(fsid_t)) == 0)
-+ break;
-+ }
-+ endmntent(mounts);
-+
-+ if (ent == NULL)
-+ {
-+ error_message= "getmntent loop failed";
-+ goto epilogue;
-+ }
-+
-+ cachedev_fd = open(ent->mnt_fsname, O_RDONLY);
-+ if (cachedev_fd < 0)
-+ {
-+ error_message= "open flash device failed";
-+ goto epilogue;
-+ }
-+
-+ /* cleanup previous whitelistings */
-+ if (ioctl(cachedev_fd, FLASHCACHEDELALLWHITELIST, &pid) < 0)
-+ {
-+ close(cachedev_fd);
-+ cachedev_fd = -1;
-+ error_message= "ioctl failed";
-+ } else {
-+ ioctl(cachedev_fd, FLASHCACHEADDWHITELIST, &pid);
-+ }
-+
-+epilogue:
-+ sql_print_information("Flashcache bypass: %s",
-+ (cachedev_fd > 0) ? "enabled" : "disabled");
-+ if (error_message)
-+ sql_print_information("Flashcache setup error is : %s\n", error_message);
-+ else
-+ cachedev_enabled= TRUE;
-+
-+}
-+
-+static void cleanup_cachedev(void)
-+{
-+ pid_t pid = getpid();
-+
-+ if (cachedev_enabled) {
-+ ioctl(cachedev_fd, FLASHCACHEDELWHITELIST, &pid);
-+ close(cachedev_fd);
-+ cachedev_fd = -1;
-+ }
-+}
-+#endif//__linux__
-
- #ifndef EMBEDDED_LIBRARY
- #ifndef DBUG_OFF
-@@ -4363,6 +4464,10 @@
- test_lc_time_sz();
- #endif
-
-+#if defined(__linux__)
-+ init_cachedev();
-+#endif//__linux__
-+
- /*
- We have enough space for fiddling with the argv, continue
- */
-@@ -4574,6 +4679,10 @@
- }
- #endif
- clean_up(1);
-+#if defined(__linux__)
-+ cleanup_cachedev();
-+#endif//__linux__
-+
- mysqld_exit(0);
- }
-
-@@ -6421,6 +6530,7 @@
- {"Delayed_errors", (char*) &delayed_insert_errors, SHOW_LONG},
- {"Delayed_insert_threads", (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH},
- {"Delayed_writes", (char*) &delayed_insert_writes, SHOW_LONG},
-+ {"Flashcache_enabled", (char*) &cachedev_enabled, SHOW_BOOL },
- {"Flush_commands", (char*) &refresh_version, SHOW_LONG_NOFLUSH},
- {"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS},
- {"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS},
---- a/sql/sql_lex.cc
-+++ b/sql/sql_lex.cc
-@@ -390,6 +390,7 @@
- lex->describe= 0;
- lex->subqueries= FALSE;
- lex->context_analysis_only= 0;
-+ lex->disable_flashcache= FALSE;
- lex->derived_tables= 0;
- lex->safe_to_cache_query= 1;
- lex->leaf_tables_insert= 0;
---- a/sql/sql_lex.h
-+++ b/sql/sql_lex.h
-@@ -2346,6 +2346,7 @@
-
- enum enum_yes_no_unknown tx_chain, tx_release;
- bool safe_to_cache_query;
-+ bool disable_flashcache;
- bool subqueries, ignore;
- st_parsing_options parsing_options;
- Alter_info alter_info;
---- a/sql/sql_select.cc
-+++ b/sql/sql_select.cc
-@@ -55,6 +55,12 @@
-
- #define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1))
-
-+#include <sys/syscall.h>
-+#include <sys/ioctl.h>
-+#if defined(__linux__)
-+#include "flashcache_ioctl.h"
-+#endif//__linux__
-+
- const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
- "MAYBE_REF","ALL","range","index","fulltext",
- "ref_or_null","unique_subquery","index_subquery",
-@@ -266,8 +272,17 @@
- ulong setup_tables_done_option)
- {
- bool res;
-+ pid_t pid;
- register SELECT_LEX *select_lex = &lex->select_lex;
- DBUG_ENTER("handle_select");
-+#if defined(__linux__)
-+ if(lex->disable_flashcache && cachedev_fd > 0)
-+ {
-+ pid = syscall(SYS_gettid);
-+ ioctl(cachedev_fd, FLASHCACHEADDNCPID, &pid);
-+ }
-+#endif//__linux__
-+
- MYSQL_SELECT_START(thd->query());
-
- if (select_lex->master_unit()->is_union() ||
-@@ -302,6 +317,12 @@
- if (unlikely(res))
- result->abort_result_set();
-
-+#if defined(__linux__)
-+ if (lex->disable_flashcache && cachedev_fd > 0)
-+ {
-+ ioctl(cachedev_fd, FLASHCACHEDELNCPID, &pid);
-+ }
-+#endif//__linux__
- MYSQL_SELECT_DONE((int) res, (ulong) thd->limit_found_rows);
- DBUG_RETURN(res);
- }
---- a/sql/sql_yacc.yy
-+++ b/sql/sql_yacc.yy
-@@ -1284,6 +1284,7 @@
- %token SQL_CACHE_SYM
- %token SQL_CALC_FOUND_ROWS
- %token SQL_NO_CACHE_SYM
-+%token SQL_NO_FCACHE_SYM
- %token SQL_SMALL_RESULT
- %token SQL_SYM /* SQL-2003-R */
- %token SQL_THREAD
-@@ -7362,6 +7363,10 @@
- Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
- }
- }
-+ | SQL_NO_FCACHE_SYM
-+ {
-+ Lex->disable_flashcache= TRUE;
-+ }
- | SQL_CACHE_SYM
- {
- /*
---- /dev/null
-+++ b/mysql-test/r/percona_sql_no_fcache.result
-@@ -0,0 +1,12 @@
-+drop table if exists t1;
-+create table t (a int not null);
-+insert into t values (1),(2),(3);
-+SELECT SQL_NO_FCACHE SLEEP(0);
-+SLEEP(0)
-+0
-+SELECT /*!40001 SQL_NO_CACHE */ /*!50084 SQL_NO_FCACHE */ * FROM t;
-+a
-+1
-+2
-+3
-+DROP TABLE t;
---- /dev/null
-+++ b/mysql-test/t/percona_sql_no_fcache.test
-@@ -0,0 +1,11 @@
-+--disable_warnings
-+drop table if exists t1;
-+--enable_warnings
-+
-+create table t (a int not null);
-+insert into t values (1),(2),(3);
-+
-+SELECT SQL_NO_FCACHE SLEEP(0);
-+SELECT /*!40001 SQL_NO_CACHE */ /*!50084 SQL_NO_FCACHE */ * FROM t;
-+
-+DROP TABLE t;
+++ /dev/null
---- a/scripts/mysqld_multi.sh
-+++ b/scripts/mysqld_multi.sh
-@@ -233,10 +233,10 @@
- {
- my (@groups, $com, $i, @options, $pec);
-
-- print "Reporting MySQL servers\n";
-+ print "Reporting MySQL (Percona Server) servers\n";
- if (!$opt_no_log)
- {
-- w2log("\nReporting MySQL servers","$opt_log",0,0);
-+ w2log("\nReporting MySQL (Percona Server) servers","$opt_log",0,0);
- }
- @groups = &find_groups($groupids);
- for ($i = 0; defined($groups[$i]); $i++)
-@@ -247,19 +247,19 @@
- $pec = $? >> 8;
- if ($pec)
- {
-- print "MySQL server from group: $groups[$i] is not running\n";
-+ print "MySQL (Percona Server) from group: $groups[$i] is not running\n";
- if (!$opt_no_log)
- {
-- w2log("MySQL server from group: $groups[$i] is not running",
-+ w2log("MySQL (Percona Server) from group: $groups[$i] is not running",
- "$opt_log", 0, 0);
- }
- }
- else
- {
-- print "MySQL server from group: $groups[$i] is running\n";
-+ print "MySQL (Percona Server) from group: $groups[$i] is running\n";
- if (!$opt_no_log)
- {
-- w2log("MySQL server from group: $groups[$i] is running",
-+ w2log("MySQL (Percona Server) from group: $groups[$i] is running",
- "$opt_log", 0, 0);
- }
- }
-@@ -284,11 +284,11 @@
-
- if (!$opt_no_log)
- {
-- w2log("\nStarting MySQL servers\n","$opt_log",0,0);
-+ w2log("\nStarting MySQL (Percona Server)\n","$opt_log",0,0);
- }
- else
- {
-- print "\nStarting MySQL servers\n";
-+ print "\nStarting MySQL (Percona Server)\n";
- }
- @groups = &find_groups($groupids);
- for ($i = 0; defined($groups[$i]); $i++)
-@@ -359,7 +359,7 @@
- }
- if (!$i && !$opt_no_log)
- {
-- w2log("No MySQL servers to be started (check your GNRs)",
-+ w2log("No MySQL (Percona Server) servers to be started (check your GNRs)",
- "$opt_log", 0, 0);
- }
- }
-@@ -374,11 +374,11 @@
-
- if (!$opt_no_log)
- {
-- w2log("\nStopping MySQL servers\n","$opt_log",0,0);
-+ w2log("\nStopping MySQL (Percona Server) servers\n","$opt_log",0,0);
- }
- else
- {
-- print "\nStopping MySQL servers\n";
-+ print "\nStopping MySQL (Percona Server) servers\n";
- }
- @groups = &find_groups($groupids);
- for ($i = 0; defined($groups[$i]); $i++)
-@@ -391,7 +391,7 @@
- }
- if (!$i && !$opt_no_log)
- {
-- w2log("No MySQL servers to be stopped (check your GNRs)",
-+ w2log("No MySQL (Percona Server) servers to be stopped (check your GNRs)",
- "$opt_log", 0, 0);
- }
- }
---- a/support-files/mysql.server.sh
-+++ b/support-files/mysql.server.sh
-@@ -2,7 +2,7 @@
- # Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
- # This file is public domain and comes with NO WARRANTY of any kind
-
--# MySQL daemon start/stop script.
-+# MySQL (Percona Server) daemon start/stop script.
-
- # Usually this is put in /etc/init.d (at least on machines SYSV R4 based
- # systems) and linked to /etc/rc3.d/S99mysql and /etc/rc0.d/K01mysql.
-@@ -21,8 +21,8 @@
- # Required-Stop: $local_fs $network $remote_fs
- # Default-Start: 2 3 4 5
- # Default-Stop: 0 1 6
--# Short-Description: start and stop MySQL
--# Description: MySQL is a very fast and reliable SQL database engine.
-+# Short-Description: start and stop MySQL (Percona Server)
-+# Description: Percona-Server is a SQL database engine with focus on high performance.
- ### END INIT INFO
-
- # If you install MySQL on some other places than @prefix@, then you
-@@ -275,7 +275,7 @@
- # Safeguard (relative paths, core dumps..)
- cd $basedir
-
-- echo $echo_n "Starting MySQL"
-+ echo $echo_n "Starting MySQL (Percona Server)"
- if test -x $bindir/mysqld_safe
- then
- # Give extra arguments to mysqld with the my.cnf file. This script
-@@ -305,12 +305,12 @@
-
- if (kill -0 $mysqld_pid 2>/dev/null)
- then
-- echo $echo_n "Shutting down MySQL"
-+ echo $echo_n "Shutting down MySQL (Percona Server)"
- kill $mysqld_pid
- # mysqld should remove the pid file when it exits, so wait for it.
- wait_for_pid removed "$mysqld_pid" "$mysqld_pid_file_path"; return_value=$?
- else
-- log_failure_msg "MySQL server process #$mysqld_pid is not running!"
-+ log_failure_msg "MySQL (Percona Server) server process #$mysqld_pid is not running!"
- rm "$mysqld_pid_file_path"
- fi
-
-@@ -321,7 +321,7 @@
- fi
- exit $return_value
- else
-- log_failure_msg "MySQL server PID file could not be found!"
-+ log_failure_msg "MySQL (Percona Server) PID file could not be found!"
- fi
- ;;
-
-@@ -339,10 +339,10 @@
- 'reload'|'force-reload')
- if test -s "$mysqld_pid_file_path" ; then
- read mysqld_pid < "$mysqld_pid_file_path"
-- kill -HUP $mysqld_pid && log_success_msg "Reloading service MySQL"
-+ kill -HUP $mysqld_pid && log_success_msg "Reloading service MySQL (Percona Server)"
- touch "$mysqld_pid_file_path"
- else
-- log_failure_msg "MySQL PID file could not be found!"
-+ log_failure_msg "MySQL (Percona Server) PID file could not be found!"
- exit 1
- fi
- ;;
-@@ -351,10 +351,10 @@
- if test -s "$mysqld_pid_file_path" ; then
- read mysqld_pid < "$mysqld_pid_file_path"
- if kill -0 $mysqld_pid 2>/dev/null ; then
-- log_success_msg "MySQL running ($mysqld_pid)"
-+ log_success_msg "MySQL (Percona Server) running ($mysqld_pid)"
- exit 0
- else
-- log_failure_msg "MySQL is not running, but PID file exists"
-+ log_failure_msg "MySQL (Percona Server) is not running, but PID file exists"
- exit 1
- fi
- else
-@@ -362,13 +362,13 @@
- mysqld_pid=`pidof $libexecdir/mysqld`
- if test -z $mysqld_pid ; then
- if test -f "$lock_file_path" ; then
-- log_failure_msg "MySQL is not running, but lock file ($lock_file_path) exists"
-+ log_failure_msg "MySQL (Percona Server) is not running, but lock file ($lock_file_path) exists"
- exit 2
- fi
-- log_failure_msg "MySQL is not running"
-+ log_failure_msg "MySQL (Percona Server) is not running"
- exit 3
- else
-- log_failure_msg "MySQL is running but PID file could not be found"
-+ log_failure_msg "MySQL (Percona Server) is running but PID file could not be found"
- exit 4
- fi
- fi
-@@ -376,7 +376,7 @@
- *)
- # usage
- basename=`basename "$0"`
-- echo "Usage: $basename {start|stop|restart|reload|force-reload|status} [ MySQL server options ]"
-+ echo "Usage: $basename {start|stop|restart|reload|force-reload|status} [ MySQL (Percona Server) options ]"
- exit 1
- ;;
- esac
+++ /dev/null
-=== added file 'mysql-test/lib/Subunit.pm'
---- /dev/null
-+++ b/mysql-test/lib/Subunit.pm
-@@ -0,0 +1,94 @@
-+# Perl module for parsing and generating the Subunit protocol
-+# Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@samba.org>
-+#
-+# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
-+# license at the users choice. A copy of both licenses are available in the
-+# project source as Apache-2.0 and BSD. You may not use this file except in
-+# compliance with one of these two licences.
-+#
-+# Unless required by applicable law or agreed to in writing, software
-+# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
-+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-+# license you chose for the specific language governing permissions and
-+# limitations under that license.
-+
-+package Subunit;
-+use POSIX;
-+
-+use vars qw ( $VERSION );
-+
-+$VERSION = '0.0.2';
-+
-+use strict;
-+my $SUBUNIT_OUT= 'test_results.subunit';
-+# reset the file
-+open(SUBUNITOUT, ">$SUBUNIT_OUT");
-+close(SUBUNITOUT);
-+
-+sub subunit_start_test($)
-+{
-+ my ($testname) = @_;
-+ open(SUBUNITOUT, ">>$SUBUNIT_OUT");
-+ print SUBUNITOUT "test: $testname\n";
-+ close(SUBUNITOUT);
-+ return;
-+}
-+
-+sub subunit_end_test($$;$)
-+{
-+ my $name = shift;
-+ my $result = shift;
-+ my $reason = shift;
-+ open(SUBUNITOUT, ">>$SUBUNIT_OUT");
-+ if ($reason) {
-+ print SUBUNITOUT "$result: $name [\n";
-+ print SUBUNITOUT "$reason\n";
-+ print SUBUNITOUT "]\n";
-+ } else {
-+ print SUBUNITOUT "$result: $name\n";
-+ }
-+ close(SUBUNITOUT);
-+ return;
-+}
-+
-+sub subunit_skip_test($;$)
-+{
-+ my $name = shift;
-+ my $reason = shift;
-+ subunit_end_test($name, "skip", $reason);
-+}
-+
-+sub subunit_fail_test($;$)
-+{
-+ my $name = shift;
-+ my $reason = shift;
-+ subunit_end_test($name, "failure", $reason);
-+}
-+
-+sub subunit_pass_test($;$)
-+{
-+ my $name = shift;
-+ my $reason = shift;
-+ subunit_end_test($name, "success", $reason);
-+}
-+
-+sub subunit_xfail_test($;$)
-+{
-+ my $name = shift;
-+ my $reason = shift;
-+ subunit_end_test($name, "xfail", $reason);
-+}
-+
-+sub report_time($)
-+{
-+ my ($time) = @_;
-+ my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($time);
-+ open(SUBUNITOUT, ">>$SUBUNIT_OUT");
-+ printf SUBUNITOUT "time: %04d-%02d-%02d %02d:%02d:%02dZ\n", $year+1900, ($mon+1), $mday, $hour, $min, $sec;
-+ close(SUBUNITOUT);
-+ return;
-+}
-+
-+
-+
-+1;
---- a/mysql-test/lib/mtr_report.pm
-+++ b/mysql-test/lib/mtr_report.pm
-@@ -27,9 +27,11 @@
- mtr_warning mtr_error mtr_debug mtr_verbose
- mtr_verbose_restart mtr_report_test_passed
- mtr_report_test_skipped mtr_print
-+ mtr_report_test_subunit
- mtr_report_test);
-
- use mtr_match;
-+use Subunit;
- use My::Platform;
- use POSIX qw[ _exit ];
- use IO::Handle qw[ flush ];
-@@ -225,6 +227,68 @@
- }
- }
-
-+sub mtr_report_test_subunit ($) {
-+ my ($tinfo)= @_;
-+ my $subunit_testname= $tinfo->{name};
-+ $subunit_testname.= " '$tinfo->{combination}'"
-+ if defined $tinfo->{combination};
-+
-+
-+ my $comment= $tinfo->{'comment'};
-+ my $logfile= $tinfo->{'logfile'};
-+ my $warnings= $tinfo->{'warnings'};
-+ my $result= $tinfo->{'result'};
-+ my $retry= $tinfo->{'retries'} ? "retry-" : "";
-+
-+ my $test_name_sub = $tinfo->{name};
-+
-+ if ($result eq 'MTR_RES_FAILED'){
-+
-+ my $timest = format_time();
-+ my $fail = "fail";
-+
-+ if ( $warnings )
-+ {
-+ Subunit::subunit_start_test($subunit_testname);
-+ Subunit::subunit_fail_test($subunit_testname, "Found warnings/errors in server log file!");
-+ return;
-+ }
-+ my $timeout= $tinfo->{'timeout'};
-+ if ( $timeout )
-+ {
-+ Subunit::subunit_start_test($subunit_testname);
-+ Subunit::subunit_fail_test($subunit_testname, "Timeout after $timeout seconds\n\n$tinfo->{'comment'}");
-+ return;
-+ }
-+ Subunit::subunit_start_test($subunit_testname);
-+ Subunit::subunit_fail_test($subunit_testname, "Comment: $comment\n\nLogfile:\n$logfile");
-+ }
-+ elsif ($result eq 'MTR_RES_SKIPPED')
-+ {
-+ if ( $tinfo->{'disable'} )
-+ {
-+ $comment="DISABLED: $comment";
-+ }
-+ # report into to subunit for Jenkins reporting
-+ Subunit::subunit_start_test($subunit_testname);
-+ Subunit::subunit_skip_test($subunit_testname, $comment);
-+ }
-+ elsif ($result eq 'MTR_RES_PASSED')
-+ {
-+ # Show any problems check-testcase found
-+ if ( defined $tinfo->{'check'} )
-+ {
-+ mtr_report($tinfo->{'check'});
-+ }
-+ # report info to subunit for Jenkins reporting
-+ # TODO: catch 'check-testcase' output??
-+ Subunit::report_time(time() - $tinfo->{timer}/1000);
-+ Subunit::subunit_start_test($subunit_testname);
-+ Subunit::report_time(time());
-+ Subunit::subunit_pass_test($subunit_testname);
-+ }
-+}
-+
-
- sub mtr_report_stats ($$;$) {
- my ($prefix, $tests, $dont_error)= @_;
---- a/mysql-test/mysql-test-run.pl
-+++ b/mysql-test/mysql-test-run.pl
-@@ -99,6 +99,7 @@
- use mtr_results;
- use IO::Socket::INET;
- use IO::Select;
-+use Subunit;
-
- require "lib/mtr_process.pl";
- require "lib/mtr_io.pl";
-@@ -292,6 +293,7 @@
- my $opt_valgrind_path;
- my $valgrind_reports= 0;
- my $opt_callgrind;
-+my $opt_helgrind;
- my %mysqld_logs;
- my $opt_debug_sync_timeout= 300; # Default timeout for WAIT_FOR actions.
-
-@@ -631,6 +633,7 @@
-
- # Report test status
- mtr_report_test($result);
-+ mtr_report_test_subunit($result);
-
- if ( $result->is_failed() ) {
-
-@@ -1144,6 +1147,7 @@
- 'valgrind-option=s' => \@valgrind_args,
- 'valgrind-path=s' => \$opt_valgrind_path,
- 'callgrind' => \$opt_callgrind,
-+ 'helgrind' => \$opt_helgrind,
- 'debug-sync-timeout=i' => \$opt_debug_sync_timeout,
-
- # Directories
-@@ -1705,11 +1709,18 @@
- unless @valgrind_args;
- }
-
-+ if ( $opt_helgrind )
-+ {
-+ mtr_report("Turning on valgrind with helgrind for mysqld(s)");
-+ $opt_valgrind= 1;
-+ $opt_valgrind_mysqld= 1;
-+ }
-+
- if ( $opt_valgrind )
- {
- # Set valgrind_options to default unless already defined
- push(@valgrind_args, @default_valgrind_args)
-- unless @valgrind_args;
-+ unless @valgrind_args || $opt_helgrind;
-
- # Don't add --quiet; you will loose the summary reports.
-
-@@ -5831,6 +5842,10 @@
- mtr_add_arg($args, "--tool=callgrind");
- mtr_add_arg($args, "--base=$opt_vardir/log");
- }
-+ elsif ( $opt_helgrind )
-+ {
-+ mtr_add_arg($args, "--tool=helgrind");
-+ }
- else
- {
- mtr_add_arg($args, "--tool=memcheck"); # From >= 2.1.2 needs this option
+++ /dev/null
-# name : userstat.patch
-# introduced : 11 or before
-# maintainer : Oleg
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/include/mysql/plugin.h
-+++ b/include/mysql/plugin.h
-@@ -556,6 +556,9 @@
- unsigned long thd_log_slow_verbosity(const MYSQL_THD thd);
- int thd_opt_slow_log();
- #define EXTENDED_SLOWLOG
-+
-+#define EXTENDED_FOR_USERSTAT
-+
- /**
- Create a temporary file.
-
---- a/include/mysql_com.h
-+++ b/include/mysql_com.h
-@@ -31,6 +31,7 @@
-
- #define SERVER_VERSION_LENGTH 60
- #define SQLSTATE_LENGTH 5
-+#define LIST_PROCESS_HOST_LEN 64
-
- /*
- Maximum length of comments
-@@ -146,6 +147,11 @@
- #define REFRESH_DES_KEY_FILE 0x40000L
- #define REFRESH_USER_RESOURCES 0x80000L
- #define REFRESH_QUERY_RESPONSE_TIME 0x100000L /* response time distibution */
-+#define REFRESH_TABLE_STATS 0x200000L /* Refresh table stats my_hash table */
-+#define REFRESH_INDEX_STATS 0x400000L /* Refresh index stats my_hash table */
-+#define REFRESH_USER_STATS 0x800000L /* Refresh user stats my_hash table */
-+#define REFRESH_CLIENT_STATS 0x1000000L /* Refresh client stats my_hash table */
-+#define REFRESH_THREAD_STATS 0x2000000L /* Refresh thread stats my_hash table */
-
- #define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */
- #define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */
---- /dev/null
-+++ b/patch_info/userstats.patch
-@@ -0,0 +1,17 @@
-+File=userstats.patch
-+Name=SHOW USER/TABLE/INDEX statistics
-+Version=V2
-+Author=Google
-+License=GPL
-+Comment=Added INFORMATION_SCHEMA.*_STATISTICS
-+2008-12-01
-+YK: fix behavior for prepared statements
-+
-+2008-11-26
-+YK: add switch variable "userstat" to control INFORMATION_SCHEMA.*_STATISTICS (default:OFF)
-+2010-12-31
-+Ported to 5.5.8
-+2011-1-5
-+Fix porting
-+2011-02
-+Rename variable USERSTAT_RUNNING => USERSTAT
---- a/sql/handler.cc
-+++ b/sql/handler.cc
-@@ -1245,6 +1245,8 @@
- goto end;
- }
- DBUG_EXECUTE_IF("crash_commit_after", DBUG_SUICIDE(););
-+ if (is_real_trans)
-+ thd->diff_commit_trans++;
- RUN_HOOK(transaction, after_commit, (thd, FALSE));
- end:
- if (rw_trans && mdl_request.ticket)
-@@ -1399,6 +1401,8 @@
- /* Always cleanup. Even if nht==0. There may be savepoints. */
- if (is_real_trans)
- thd->transaction.cleanup();
-+
-+ thd->diff_rollback_trans++;
- if (all)
- thd->transaction_rollback_request= FALSE;
-
-@@ -1803,6 +1807,7 @@
- ha_info->reset(); /* keep it conveniently zero-filled */
- }
- trans->ha_list= sv->ha_list;
-+ thd->diff_rollback_trans++;
- DBUG_RETURN(error);
- }
-
-@@ -2179,6 +2184,8 @@
- dup_ref=ref+ALIGN_SIZE(ref_length);
- cached_table_flags= table_flags();
- }
-+ rows_read= rows_changed= 0;
-+ memset(index_rows_read, 0, sizeof(index_rows_read));
- DBUG_RETURN(error);
- }
-
-@@ -3644,6 +3651,127 @@
- return;
- }
-
-+// Updates the global table stats with the TABLE this handler represents.
-+void handler::update_global_table_stats()
-+{
-+ if (!opt_userstat)
-+ {
-+ rows_read= rows_changed= 0;
-+ return;
-+ }
-+
-+ if (!rows_read && !rows_changed)
-+ return; // Nothing to update.
-+ // table_cache_key is db_name + '\0' + table_name + '\0'.
-+ if (!table->s || !table->s->table_cache_key.str || !table->s->table_name.str)
-+ return;
-+
-+ TABLE_STATS* table_stats;
-+ char key[NAME_LEN * 2 + 2];
-+ // [db] + '.' + [table]
-+ sprintf(key, "%s.%s", table->s->table_cache_key.str, table->s->table_name.str);
-+
-+ mysql_mutex_lock(&LOCK_global_table_stats);
-+ // Gets the global table stats, creating one if necessary.
-+ if (!(table_stats = (TABLE_STATS *) my_hash_search(&global_table_stats,
-+ (uchar*)key,
-+ strlen(key))))
-+ {
-+ if (!(table_stats = ((TABLE_STATS *)
-+ my_malloc(sizeof(TABLE_STATS), MYF(MY_WME | MY_ZEROFILL)))))
-+ {
-+ // Out of memory.
-+ sql_print_error("Allocating table stats failed.");
-+ goto end;
-+ }
-+ strncpy(table_stats->table, key, sizeof(table_stats->table));
-+ table_stats->rows_read= 0;
-+ table_stats->rows_changed= 0;
-+ table_stats->rows_changed_x_indexes= 0;
-+ table_stats->engine_type= (int) ht->db_type;
-+
-+ if (my_hash_insert(&global_table_stats, (uchar *) table_stats))
-+ {
-+ // Out of memory.
-+ sql_print_error("Inserting table stats failed.");
-+ my_free((char *) table_stats);
-+ goto end;
-+ }
-+ }
-+ // Updates the global table stats.
-+ table_stats->rows_read+= rows_read;
-+ table_stats->rows_changed+= rows_changed;
-+ table_stats->rows_changed_x_indexes+=
-+ rows_changed * (table->s->keys ? table->s->keys : 1);
-+ current_thd->diff_total_read_rows+= rows_read;
-+ rows_read= rows_changed= 0;
-+end:
-+ mysql_mutex_unlock(&LOCK_global_table_stats);
-+}
-+
-+// Updates the global index stats with this handler's accumulated index reads.
-+void handler::update_global_index_stats()
-+{
-+ // table_cache_key is db_name + '\0' + table_name + '\0'.
-+ if (!table->s || !table->s->table_cache_key.str || !table->s->table_name.str)
-+ return;
-+
-+ if (!opt_userstat)
-+ {
-+ for (uint x= 0; x < table->s->keys; ++x)
-+ {
-+ index_rows_read[x]= 0;
-+ }
-+ return;
-+ }
-+
-+ for (uint x = 0; x < table->s->keys; ++x)
-+ {
-+ if (index_rows_read[x])
-+ {
-+ // Rows were read using this index.
-+ KEY* key_info = &table->key_info[x];
-+
-+ if (!key_info->name) continue;
-+
-+ INDEX_STATS* index_stats;
-+ char key[NAME_LEN * 3 + 3];
-+ // [db] + '.' + [table] + '.' + [index]
-+ sprintf(key, "%s.%s.%s", table->s->table_cache_key.str,
-+ table->s->table_name.str, key_info->name);
-+
-+ mysql_mutex_lock(&LOCK_global_index_stats);
-+ // Gets the global index stats, creating one if necessary.
-+ if (!(index_stats = (INDEX_STATS *) my_hash_search(&global_index_stats,
-+ (uchar *) key,
-+ strlen(key))))
-+ {
-+ if (!(index_stats = ((INDEX_STATS *)
-+ my_malloc(sizeof(INDEX_STATS), MYF(MY_WME | MY_ZEROFILL)))))
-+ {
-+ // Out of memory.
-+ sql_print_error("Allocating index stats failed.");
-+ goto end;
-+ }
-+ strncpy(index_stats->index, key, sizeof(index_stats->index));
-+ index_stats->rows_read= 0;
-+
-+ if (my_hash_insert(&global_index_stats, (uchar *) index_stats))
-+ {
-+ // Out of memory.
-+ sql_print_error("Inserting index stats failed.");
-+ my_free((char *) index_stats);
-+ goto end;
-+ }
-+ }
-+ // Updates the global index stats.
-+ index_stats->rows_read+= index_rows_read[x];
-+ index_rows_read[x]= 0;
-+ end:
-+ mysql_mutex_unlock(&LOCK_global_index_stats);
-+ }
-+ }
-+}
-
- /****************************************************************************
- ** Some general functions that isn't in the handler class
---- a/sql/handler.h
-+++ b/sql/handler.h
-@@ -36,6 +36,10 @@
- #include <ft_global.h>
- #include <keycache.h>
-
-+#if MAX_KEY > 128
-+#error MAX_KEY is too large. Values up to 128 are supported.
-+#endif
-+
- // the following is for checking tables
-
- #define HA_ADMIN_ALREADY_DONE 1
-@@ -562,10 +566,12 @@
- enum enum_schema_tables
- {
- SCH_CHARSETS= 0,
-+ SCH_CLIENT_STATS,
- SCH_COLLATIONS,
- SCH_COLLATION_CHARACTER_SET_APPLICABILITY,
- SCH_COLUMNS,
- SCH_COLUMN_PRIVILEGES,
-+ SCH_INDEX_STATS,
- SCH_ENGINES,
- SCH_EVENTS,
- SCH_FILES,
-@@ -593,9 +599,12 @@
- SCH_TABLE_CONSTRAINTS,
- SCH_TABLE_NAMES,
- SCH_TABLE_PRIVILEGES,
-+ SCH_TABLE_STATS,
- SCH_TEMPORARY_TABLES,
-+ SCH_THREAD_STATS,
- SCH_TRIGGERS,
- SCH_USER_PRIVILEGES,
-+ SCH_USER_STATS,
- SCH_VARIABLES,
- SCH_VIEWS
- };
-@@ -1233,6 +1242,9 @@
- bool locked;
- bool implicit_emptied; /* Can be !=0 only if HEAP */
- const COND *pushed_cond;
-+ ulonglong rows_read;
-+ ulonglong rows_changed;
-+ ulonglong index_rows_read[MAX_KEY];
- /**
- next_insert_id is the next value which should be inserted into the
- auto_increment column: in a inserting-multi-row statement (like INSERT
-@@ -1284,10 +1296,12 @@
- ref_length(sizeof(my_off_t)),
- ft_handler(0), inited(NONE),
- locked(FALSE), implicit_emptied(0),
-- pushed_cond(0), next_insert_id(0), insert_id_for_cur_row(0),
-+ pushed_cond(0), rows_read(0), rows_changed(0), next_insert_id(0), insert_id_for_cur_row(0),
- auto_inc_intervals_count(0),
- m_psi(NULL)
-- {}
-+ {
-+ memset(index_rows_read, 0, sizeof(index_rows_read));
-+ }
- virtual ~handler(void)
- {
- DBUG_ASSERT(locked == FALSE);
-@@ -1410,6 +1424,8 @@
- {
- table= table_arg;
- table_share= share;
-+ rows_read = rows_changed= 0;
-+ memset(index_rows_read, 0, sizeof(index_rows_read));
- }
- virtual double scan_time()
- { return ulonglong2double(stats.data_file_length) / IO_SIZE + 2; }
-@@ -1805,6 +1821,8 @@
- virtual bool is_crashed() const { return 0; }
- virtual bool auto_repair() const { return 0; }
-
-+ void update_global_table_stats();
-+ void update_global_index_stats();
-
- #define CHF_CREATE_FLAG 0
- #define CHF_DELETE_FLAG 1
---- a/sql/lex.h
-+++ b/sql/lex.h
-@@ -111,6 +111,7 @@
- { "CIPHER", SYM(CIPHER_SYM)},
- { "CLASS_ORIGIN", SYM(CLASS_ORIGIN_SYM)},
- { "CLIENT", SYM(CLIENT_SYM)},
-+ { "CLIENT_STATISTICS", SYM(CLIENT_STATS_SYM)},
- { "CLOSE", SYM(CLOSE_SYM)},
- { "COALESCE", SYM(COALESCE)},
- { "CODE", SYM(CODE_SYM)},
-@@ -257,6 +258,7 @@
- { "IN", SYM(IN_SYM)},
- { "INDEX", SYM(INDEX_SYM)},
- { "INDEXES", SYM(INDEXES)},
-+ { "INDEX_STATISTICS", SYM(INDEX_STATS_SYM)},
- { "INFILE", SYM(INFILE)},
- { "INITIAL_SIZE", SYM(INITIAL_SIZE_SYM)},
- { "INNER", SYM(INNER_SYM)},
-@@ -550,12 +552,14 @@
- { "TABLES", SYM(TABLES)},
- { "TABLESPACE", SYM(TABLESPACE)},
- { "TABLE_CHECKSUM", SYM(TABLE_CHECKSUM_SYM)},
-+ { "TABLE_STATISTICS", SYM(TABLE_STATS_SYM)},
- { "TEMPORARY", SYM(TEMPORARY)},
- { "TEMPTABLE", SYM(TEMPTABLE_SYM)},
- { "TERMINATED", SYM(TERMINATED)},
- { "TEXT", SYM(TEXT_SYM)},
- { "THAN", SYM(THAN_SYM)},
- { "THEN", SYM(THEN_SYM)},
-+ { "THREAD_STATISTICS", SYM(THREAD_STATS_SYM)},
- { "TIME", SYM(TIME_SYM)},
- { "TIMESTAMP", SYM(TIMESTAMP)},
- { "TIMESTAMPADD", SYM(TIMESTAMP_ADD)},
-@@ -591,6 +595,7 @@
- { "USE", SYM(USE_SYM)},
- { "USER", SYM(USER)},
- { "USER_RESOURCES", SYM(RESOURCES)},
-+ { "USER_STATISTICS", SYM(USER_STATS_SYM)},
- { "USE_FRM", SYM(USE_FRM)},
- { "USING", SYM(USING)},
- { "UTC_DATE", SYM(UTC_DATE_SYM)},
---- a/sql/log.cc
-+++ b/sql/log.cc
-@@ -1007,6 +1007,13 @@
- mysql_slow_log.reopen_file();
- }
-
-+void Log_to_file_event_handler::flush_slow_log()
-+{
-+ /* reopen slow log file */
-+ if (opt_slow_log)
-+ mysql_slow_log.reopen_file();
-+}
-+
- /*
- Log error with all enabled log event handlers
-
-@@ -5062,6 +5069,8 @@
- thd->first_successful_insert_id_in_prev_stmt_for_binlog);
- if (e.write(file))
- goto err;
-+ if (file == &log_file)
-+ thd->binlog_bytes_written+= e.data_written;
- }
- if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0)
- {
-@@ -5073,12 +5082,16 @@
- minimum());
- if (e.write(file))
- goto err;
-+ if (file == &log_file)
-+ thd->binlog_bytes_written+= e.data_written;
- }
- if (thd->rand_used)
- {
- Rand_log_event e(thd,thd->rand_saved_seed1,thd->rand_saved_seed2);
- if (e.write(file))
- goto err;
-+ if (file == &log_file)
-+ thd->binlog_bytes_written+= e.data_written;
- }
- if (thd->user_var_events.elements)
- {
-@@ -5101,6 +5114,8 @@
- flags);
- if (e.write(file))
- goto err;
-+ if (file == &log_file)
-+ thd->binlog_bytes_written+= e.data_written;
- }
- }
- }
-@@ -5112,6 +5127,8 @@
- if (event_info->write(file) ||
- DBUG_EVALUATE_IF("injecting_fault_writing", 1, 0))
- goto err;
-+ if (file == &log_file)
-+ thd->binlog_bytes_written+= event_info->data_written;
-
- error= 0;
- err:
-@@ -5346,7 +5363,8 @@
- be reset as a READ_CACHE to be able to read the contents from it.
- */
-
--int MYSQL_BIN_LOG::write_cache(IO_CACHE *cache, bool lock_log, bool sync_log)
-+int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache,
-+ bool lock_log, bool sync_log)
- {
- Mutex_sentry sentry(lock_log ? &LOCK_log : NULL);
-
-@@ -5393,6 +5411,7 @@
- /* write the first half of the split header */
- if (my_b_write(&log_file, header, carry))
- return ER_ERROR_ON_WRITE;
-+ thd->binlog_bytes_written+= carry;
-
- /*
- copy fixed second half of header to cache so the correct
-@@ -5461,6 +5480,7 @@
- /* Write data to the binary log file */
- if (my_b_write(&log_file, cache->read_pos, length))
- return ER_ERROR_ON_WRITE;
-+ thd->binlog_bytes_written+= length;
- cache->read_pos=cache->read_end; // Mark buffer used up
- } while ((length= my_b_fill(cache)));
-
-@@ -5584,20 +5604,23 @@
- Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE, TRUE, 0);
- if (qinfo.write(&log_file))
- goto err;
-+ thd->binlog_bytes_written+= qinfo.data_written;
- DBUG_EXECUTE_IF("crash_before_writing_xid",
- {
-- if ((write_error= write_cache(cache, false, true)))
-+ if ((write_error= write_cache(thd, cache, false, true)))
- DBUG_PRINT("info", ("error writing binlog cache: %d",
- write_error));
- DBUG_PRINT("info", ("crashing before writing xid"));
- DBUG_SUICIDE();
- });
-
-- if ((write_error= write_cache(cache, false, false)))
-+ if ((write_error= write_cache(thd, cache, false, false)))
- goto err;
-
- if (commit_event && commit_event->write(&log_file))
- goto err;
-+ if (commit_event)
-+ thd->binlog_bytes_written+= commit_event->data_written;
-
- if (incident && write_incident(thd, FALSE))
- goto err;
---- a/sql/log.h
-+++ b/sql/log.h
-@@ -437,7 +437,8 @@
- bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident);
- bool write_incident(THD *thd, bool lock);
-
-- int write_cache(IO_CACHE *cache, bool lock_log, bool flush_and_sync);
-+ int write_cache(THD *thd, IO_CACHE *cache,
-+ bool lock_log, bool flush_and_sync);
- void set_write_error(THD *thd, bool is_transactional);
- bool check_write_error(THD *thd);
-
-@@ -591,6 +592,7 @@
- const char *sql_text, uint sql_text_len,
- CHARSET_INFO *client_cs);
- void flush();
-+ void flush_slow_log();
- void init_pthread_objects();
- MYSQL_QUERY_LOG *get_mysql_slow_log() { return &mysql_slow_log; }
- MYSQL_QUERY_LOG *get_mysql_log() { return &mysql_log; }
---- a/sql/mysqld.cc
-+++ b/sql/mysqld.cc
-@@ -445,6 +445,7 @@
- MYSQL_PLUGIN_IMPORT uint opt_debug_sync_timeout= 0;
- #endif /* defined(ENABLED_DEBUG_SYNC) */
- my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
-+my_bool opt_userstat= 0, opt_thread_statistics= 0;
- my_bool opt_optimizer_fix= 0;
- /*
- True if there is at least one per-hour limit for some user, so we should
-@@ -496,6 +497,7 @@
- ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
- ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0;
- ulong max_connections, max_connect_errors;
-+ulonglong denied_connections= 0;
-
- /* flashcache */
- int cachedev_fd;
-@@ -645,7 +647,9 @@
- LOCK_crypt,
- LOCK_global_system_variables,
- LOCK_user_conn, LOCK_slave_list, LOCK_active_mi,
-- LOCK_connection_count, LOCK_error_messages;
-+ LOCK_connection_count, LOCK_error_messages,
-+ LOCK_stats, LOCK_global_user_client_stats,
-+ LOCK_global_table_stats, LOCK_global_index_stats;
- /**
- The below lock protects access to two global server variables:
- max_prepared_stmt_count and prepared_stmt_count. These variables
-@@ -1509,6 +1513,11 @@
- #ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
- query_response_time_free();
- #endif // HAVE_RESPONSE_TIME_DISTRIBUTION
-+ free_global_user_stats();
-+ free_global_client_stats();
-+ free_global_thread_stats();
-+ free_global_table_stats();
-+ free_global_index_stats();
- #ifdef HAVE_REPLICATION
- end_slave_list();
- #endif
-@@ -1612,6 +1621,10 @@
- mysql_cond_destroy(&COND_thread_cache);
- mysql_cond_destroy(&COND_flush_thread_cache);
- mysql_cond_destroy(&COND_manager);
-+ mysql_mutex_destroy(&LOCK_stats);
-+ mysql_mutex_destroy(&LOCK_global_user_client_stats);
-+ mysql_mutex_destroy(&LOCK_global_table_stats);
-+ mysql_mutex_destroy(&LOCK_global_index_stats);
- }
- #endif /*EMBEDDED_LIBRARY*/
-
-@@ -2938,6 +2951,7 @@
- {"show_binlog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOG_EVENTS]), SHOW_LONG_STATUS},
- {"show_binlogs", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOGS]), SHOW_LONG_STATUS},
- {"show_charsets", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CHARSETS]), SHOW_LONG_STATUS},
-+ {"show_client_statistics",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CLIENT_STATS]), SHOW_LONG_STATUS},
- {"show_collations", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLLATIONS]), SHOW_LONG_STATUS},
- {"show_contributors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CONTRIBUTORS]), SHOW_LONG_STATUS},
- {"show_create_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_DB]), SHOW_LONG_STATUS},
-@@ -2958,6 +2972,7 @@
- #endif
- {"show_function_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_FUNC]), SHOW_LONG_STATUS},
- {"show_grants", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS},
-+ {"show_index_statistics",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_INDEX_STATS]), SHOW_LONG_STATUS},
- {"show_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
- {"show_master_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS},
- {"show_open_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS},
-@@ -2976,10 +2991,13 @@
- {"show_slave_status_nolock", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_NOLOCK_STAT]), SHOW_LONG_STATUS},
- {"show_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS},
- {"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS},
-+ {"show_table_statistics",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATS]), SHOW_LONG_STATUS},
- {"show_table_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATUS]), SHOW_LONG_STATUS},
- {"show_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLES]), SHOW_LONG_STATUS},
- {"show_temporary_tables",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TEMPORARY_TABLES]), SHOW_LONG_STATUS},
-+ {"show_thread_statistics",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_THREAD_STATS]), SHOW_LONG_STATUS},
- {"show_triggers", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TRIGGERS]), SHOW_LONG_STATUS},
-+ {"show_user_statistics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_USER_STATS]), SHOW_LONG_STATUS},
- {"show_variables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS},
- {"show_warnings", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS},
- {"slave_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS},
-@@ -3517,6 +3535,13 @@
- mysql_mutex_init(key_LOCK_server_started,
- &LOCK_server_started, MY_MUTEX_INIT_FAST);
- mysql_cond_init(key_COND_server_started, &COND_server_started, NULL);
-+ mysql_mutex_init(key_LOCK_stats, &LOCK_stats, MY_MUTEX_INIT_FAST);
-+ mysql_mutex_init(key_LOCK_global_user_client_stats,
-+ &LOCK_global_user_client_stats, MY_MUTEX_INIT_FAST);
-+ mysql_mutex_init(key_LOCK_global_table_stats,
-+ &LOCK_global_table_stats, MY_MUTEX_INIT_FAST);
-+ mysql_mutex_init(key_LOCK_global_index_stats,
-+ &LOCK_global_index_stats, MY_MUTEX_INIT_FAST);
- sp_cache_init();
- #ifdef HAVE_EVENT_SCHEDULER
- Events::init_mutexes();
-@@ -3886,6 +3911,9 @@
- query_response_time_init();
- #endif // HAVE_RESPONSE_TIME_DISTRIBUTION
- /* We have to initialize the storage engines before CSV logging */
-+ init_global_table_stats();
-+ init_global_index_stats();
-+
- if (ha_init())
- {
- sql_print_error("Can't init databases");
-@@ -4022,6 +4050,9 @@
-
- init_max_user_conn();
- init_update_queries();
-+ init_global_user_stats();
-+ init_global_client_stats();
-+ init_global_thread_stats();
- DBUG_RETURN(0);
- }
-
-@@ -5087,6 +5118,7 @@
- {
- sql_print_warning("%s", ER_DEFAULT(ER_CON_COUNT_ERROR));
- }
-+ statistic_increment(denied_connections, &LOCK_status);
- delete thd;
- DBUG_VOID_RETURN;
- }
-@@ -7825,6 +7857,8 @@
- key_delayed_insert_mutex, key_hash_filo_lock, key_LOCK_active_mi,
- key_LOCK_connection_count, key_LOCK_crypt, key_LOCK_delayed_create,
- key_LOCK_delayed_insert, key_LOCK_delayed_status, key_LOCK_error_log,
-+ key_LOCK_stats, key_LOCK_global_user_client_stats,
-+ key_LOCK_global_table_stats, key_LOCK_global_index_stats,
- key_LOCK_gdl, key_LOCK_global_system_variables,
- key_LOCK_manager,
- key_LOCK_prepared_stmt_count,
-@@ -7864,6 +7898,13 @@
- { &key_LOCK_delayed_insert, "LOCK_delayed_insert", PSI_FLAG_GLOBAL},
- { &key_LOCK_delayed_status, "LOCK_delayed_status", PSI_FLAG_GLOBAL},
- { &key_LOCK_error_log, "LOCK_error_log", PSI_FLAG_GLOBAL},
-+ { &key_LOCK_stats, "LOCK_stats", PSI_FLAG_GLOBAL},
-+ { &key_LOCK_global_user_client_stats,
-+ "LOCK_global_user_client_stats", PSI_FLAG_GLOBAL},
-+ { &key_LOCK_global_table_stats,
-+ "LOCK_global_table_stats", PSI_FLAG_GLOBAL},
-+ { &key_LOCK_global_index_stats,
-+ "LOCK_global_index_stats", PSI_FLAG_GLOBAL},
- { &key_LOCK_gdl, "LOCK_gdl", PSI_FLAG_GLOBAL},
- { &key_LOCK_global_system_variables, "LOCK_global_system_variables", PSI_FLAG_GLOBAL},
- { &key_LOCK_manager, "LOCK_manager", PSI_FLAG_GLOBAL},
---- a/sql/mysqld.h
-+++ b/sql/mysqld.h
-@@ -23,6 +23,7 @@
- #include "my_atomic.h" /* my_atomic_rwlock_t */
- #include "mysql/psi/mysql_file.h" /* MYSQL_FILE */
- #include "sql_list.h" /* I_List */
-+#include "hash.h"
-
- class THD;
- struct handlerton;
-@@ -114,6 +115,7 @@
- extern ulonglong slave_type_conversions_options;
- extern my_bool read_only, opt_readonly;
- extern my_bool lower_case_file_system;
-+extern my_bool opt_userstat, opt_thread_statistics;
- extern my_bool opt_optimizer_fix;
- extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
- extern my_bool opt_secure_auth;
-@@ -183,6 +185,7 @@
- extern ulong slave_trans_retries;
- extern uint slave_net_timeout;
- extern uint max_user_connections;
-+extern ulonglong denied_connections;
- extern ulong what_to_log,flush_time;
- extern ulong max_prepared_stmt_count, prepared_stmt_count;
- extern ulong open_files_limit;
-@@ -210,6 +213,11 @@
- extern struct system_variables max_system_variables;
- extern struct system_status_var global_status_var;
- extern struct rand_struct sql_rand;
-+extern HASH global_user_stats;
-+extern HASH global_client_stats;
-+extern HASH global_thread_stats;
-+extern HASH global_table_stats;
-+extern HASH global_index_stats;
- extern const char *opt_date_time_formats[];
- extern handlerton *partition_hton;
- extern handlerton *myisam_hton;
-@@ -252,6 +260,8 @@
- key_delayed_insert_mutex, key_hash_filo_lock, key_LOCK_active_mi,
- key_LOCK_connection_count, key_LOCK_crypt, key_LOCK_delayed_create,
- key_LOCK_delayed_insert, key_LOCK_delayed_status, key_LOCK_error_log,
-+ key_LOCK_stats, key_LOCK_global_user_client_stats,
-+ key_LOCK_global_table_stats, key_LOCK_global_index_stats,
- key_LOCK_gdl, key_LOCK_global_system_variables,
- key_LOCK_logger, key_LOCK_manager,
- key_LOCK_prepared_stmt_count,
-@@ -351,7 +361,9 @@
- LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
- LOCK_slave_list, LOCK_active_mi, LOCK_manager,
- LOCK_global_system_variables, LOCK_user_conn,
-- LOCK_prepared_stmt_count, LOCK_error_messages, LOCK_connection_count;
-+ LOCK_prepared_stmt_count, LOCK_error_messages, LOCK_connection_count,
-+ LOCK_stats, LOCK_global_user_client_stats,
-+ LOCK_global_table_stats, LOCK_global_index_stats;
- extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_thread_count;
- #ifdef HAVE_OPENSSL
- extern mysql_mutex_t LOCK_des_key_file;
-@@ -463,6 +475,16 @@
- return id;
- }
-
-+void init_global_user_stats(void);
-+void init_global_table_stats(void);
-+void init_global_index_stats(void);
-+void init_global_client_stats(void);
-+void init_global_thread_stats(void);
-+void free_global_user_stats(void);
-+void free_global_table_stats(void);
-+void free_global_index_stats(void);
-+void free_global_client_stats(void);
-+void free_global_thread_stats(void);
-
- /*
- TODO: Replace this with an inline function.
---- a/sql/sql_base.cc
-+++ b/sql/sql_base.cc
-@@ -1587,6 +1587,11 @@
- table->mdl_ticket= NULL;
-
- mysql_mutex_lock(&thd->LOCK_thd_data);
-+ if(table->file)
-+ {
-+ table->file->update_global_table_stats();
-+ table->file->update_global_index_stats();
-+ }
- *table_ptr=table->next;
- mysql_mutex_unlock(&thd->LOCK_thd_data);
-
-@@ -2225,6 +2230,8 @@
- DBUG_PRINT("tmptable", ("closing table: '%s'.'%s'",
- table->s->db.str, table->s->table_name.str));
-
-+ table->file->update_global_table_stats();
-+ table->file->update_global_index_stats();
- free_io_cache(table);
- closefrm(table, 0);
- if (delete_table)
---- a/sql/sql_class.cc
-+++ b/sql/sql_class.cc
-@@ -978,6 +978,13 @@
- mysys_var=0;
- binlog_evt_union.do_union= FALSE;
- enable_slow_log= 0;
-+ busy_time= 0;
-+ cpu_time= 0;
-+ bytes_received= 0;
-+ bytes_sent= 0;
-+ binlog_bytes_written= 0;
-+ updated_row_count= 0;
-+ sent_row_count_2= 0;
- #ifndef DBUG_OFF
- dbug_sentry=THD_SENTRY_MAGIC;
- #endif
-@@ -1357,6 +1364,7 @@
- variables.option_bits|= OPTION_BIN_LOG;
- else
- variables.option_bits&= ~OPTION_BIN_LOG;
-+ reset_stats();
-
- #if defined(ENABLED_DEBUG_SYNC)
- /* Initialize the Debug Sync Facility. See debug_sync.cc. */
-@@ -1366,6 +1374,94 @@
- clear_slow_extended();
- }
-
-+// Resets stats in a THD.
-+void THD::reset_stats(void)
-+{
-+ current_connect_time= time(NULL);
-+ last_global_update_time= current_connect_time;
-+ reset_diff_stats();
-+}
-+
-+// Resets the 'diff' stats, which are used to update global stats.
-+void THD::reset_diff_stats(void)
-+{
-+ diff_total_busy_time= 0;
-+ diff_total_cpu_time= 0;
-+ diff_total_bytes_received= 0;
-+ diff_total_bytes_sent= 0;
-+ diff_total_binlog_bytes_written= 0;
-+ diff_total_sent_rows= 0;
-+ diff_total_updated_rows= 0;
-+ diff_total_read_rows= 0;
-+ diff_select_commands= 0;
-+ diff_update_commands= 0;
-+ diff_other_commands= 0;
-+ diff_commit_trans= 0;
-+ diff_rollback_trans= 0;
-+ diff_denied_connections= 0;
-+ diff_lost_connections= 0;
-+ diff_access_denied_errors= 0;
-+ diff_empty_queries= 0;
-+}
-+
-+// Updates 'diff' stats of a THD.
-+void THD::update_stats(bool ran_command)
-+{
-+ if (opt_userstat)
-+ {
-+ diff_total_busy_time+= busy_time;
-+ diff_total_cpu_time+= cpu_time;
-+ diff_total_bytes_received+= bytes_received;
-+ diff_total_bytes_sent+= bytes_sent;
-+ diff_total_binlog_bytes_written+= binlog_bytes_written;
-+ diff_total_sent_rows+= sent_row_count_2;
-+ diff_total_updated_rows+= updated_row_count;
-+ // diff_total_read_rows is updated in handler.cc.
-+
-+ if (ran_command)
-+ {
-+ // The replication thread has the COM_CONNECT command.
-+ if ((old_command == COM_QUERY || command == COM_CONNECT) &&
-+ (lex->sql_command >= 0 && lex->sql_command < SQLCOM_END))
-+ {
-+ // A SQL query.
-+ if (lex->sql_command == SQLCOM_SELECT)
-+ {
-+ diff_select_commands++;
-+ if (!sent_row_count_2)
-+ diff_empty_queries++;
-+ }
-+ else if (!sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)
-+ {
-+ // 'SHOW ' commands become SQLCOM_SELECT.
-+ diff_other_commands++;
-+ // 'SHOW ' commands shouldn't inflate total sent row count.
-+ diff_total_sent_rows-= sent_row_count_2;
-+ } else if (is_update_query(lex->sql_command)) {
-+ diff_update_commands++;
-+ } else {
-+ diff_other_commands++;
-+ }
-+ }
-+ }
-+ // diff_commit_trans is updated in handler.cc.
-+ // diff_rollback_trans is updated in handler.cc.
-+ // diff_denied_connections is updated in sql_parse.cc.
-+ // diff_lost_connections is updated in sql_parse.cc.
-+ // diff_access_denied_errors is updated in sql_parse.cc.
-+
-+ /* reset counters to zero to avoid double-counting since values
-+ are already store in diff_total_*.
-+ */
-+ }
-+ busy_time= 0;
-+ cpu_time= 0;
-+ bytes_received= 0;
-+ bytes_sent= 0;
-+ binlog_bytes_written= 0;
-+ updated_row_count= 0;
-+ sent_row_count_2= 0;
-+}
-
- /*
- Init THD for query processing.
-@@ -2125,6 +2221,32 @@
- }
- #endif
-
-+char *THD::get_client_host_port(THD *client)
-+{
-+ Security_context *client_sctx= client->security_ctx;
-+ char *client_host= NULL;
-+
-+ if (client->peer_port && (client_sctx->host || client_sctx->ip) &&
-+ security_ctx->host_or_ip[0])
-+ {
-+ if ((client_host= (char *) this->alloc(LIST_PROCESS_HOST_LEN+1)))
-+ my_snprintf((char *) client_host, LIST_PROCESS_HOST_LEN,
-+ "%s:%u", client_sctx->host_or_ip, client->peer_port);
-+ }
-+ else
-+ client_host= this->strdup(client_sctx->host_or_ip[0] ?
-+ client_sctx->host_or_ip :
-+ client_sctx->host ? client_sctx->host : "");
-+
-+ return client_host;
-+}
-+
-+const char *get_client_host(THD *client)
-+{
-+ return client->security_ctx->host_or_ip[0] ?
-+ client->security_ctx->host_or_ip :
-+ client->security_ctx->host ? client->security_ctx->host : "";
-+}
-
- struct Item_change_record: public ilink
- {
-@@ -2301,6 +2423,7 @@
- }
-
- thd->sent_row_count++;
-+ thd->sent_row_count_2++;
-
- if (thd->vio_ok())
- DBUG_RETURN(protocol->write());
-@@ -2393,6 +2516,7 @@
- select_export::~select_export()
- {
- thd->sent_row_count=row_count;
-+ thd->sent_row_count_2= row_count;
- }
-
-
-@@ -3416,6 +3540,7 @@
- if (likely(thd != 0))
- { /* current_thd==0 when close_connection() calls net_send_error() */
- thd->status_var.bytes_sent+= length;
-+ thd->bytes_sent+= length;
- }
- }
-
-@@ -3423,6 +3548,7 @@
- void thd_increment_bytes_received(ulong length)
- {
- current_thd->status_var.bytes_received+= length;
-+ current_thd->bytes_received+= length;
- }
-
-
---- a/sql/sql_class.h
-+++ b/sql/sql_class.h
-@@ -1705,6 +1705,8 @@
- */
- enum enum_server_command command;
- uint32 server_id;
-+ // Used to save the command, before it is set to COM_SLEEP.
-+ enum enum_server_command old_command;
- uint32 file_id; // for LOAD DATA INFILE
- /* remote (peer) port */
- uint16 peer_port;
-@@ -2214,6 +2216,8 @@
- */
- enum_tx_isolation tx_isolation;
- enum_check_fields count_cuted_fields;
-+ ha_rows updated_row_count;
-+ ha_rows sent_row_count_2; /* for userstat */
-
- DYNAMIC_ARRAY user_var_events; /* For user variables replication */
- MEM_ROOT *user_var_events_alloc; /* Allocate above array elements here */
-@@ -2308,6 +2312,49 @@
- */
- LOG_INFO* current_linfo;
- NET* slave_net; // network connection from slave -> m.
-+
-+ /*
-+ Used to update global user stats. The global user stats are updated
-+ occasionally with the 'diff' variables. After the update, the 'diff'
-+ variables are reset to 0.
-+ */
-+ // Time when the current thread connected to MySQL.
-+ time_t current_connect_time;
-+ // Last time when THD stats were updated in global_user_stats.
-+ time_t last_global_update_time;
-+ // Busy (non-idle) time for just one command.
-+ double busy_time;
-+ // Busy time not updated in global_user_stats yet.
-+ double diff_total_busy_time;
-+ // Cpu (non-idle) time for just one thread.
-+ double cpu_time;
-+ // Cpu time not updated in global_user_stats yet.
-+ double diff_total_cpu_time;
-+ /* bytes counting */
-+ ulonglong bytes_received;
-+ ulonglong diff_total_bytes_received;
-+ ulonglong bytes_sent;
-+ ulonglong diff_total_bytes_sent;
-+ ulonglong binlog_bytes_written;
-+ ulonglong diff_total_binlog_bytes_written;
-+
-+ // Number of rows not reflected in global_user_stats yet.
-+ ha_rows diff_total_sent_rows, diff_total_updated_rows, diff_total_read_rows;
-+ // Number of commands not reflected in global_user_stats yet.
-+ ulonglong diff_select_commands, diff_update_commands, diff_other_commands;
-+ // Number of transactions not reflected in global_user_stats yet.
-+ ulonglong diff_commit_trans, diff_rollback_trans;
-+ // Number of connection errors not reflected in global_user_stats yet.
-+ ulonglong diff_denied_connections, diff_lost_connections;
-+ // Number of db access denied, not reflected in global_user_stats yet.
-+ ulonglong diff_access_denied_errors;
-+ // Number of queries that return 0 rows
-+ ulonglong diff_empty_queries;
-+
-+ // Per account query delay in miliseconds. When not 0, sleep this number of
-+ // milliseconds before every SQL command.
-+ ulonglong query_delay_millis;
-+
- /* Used by the sys_var class to store temporary values */
- union
- {
-@@ -2388,6 +2435,11 @@
- alloc_root.
- */
- void init_for_queries();
-+ void reset_stats(void);
-+ void reset_diff_stats(void);
-+ // ran_command is true when this is called immediately after a
-+ // command has been run.
-+ void update_stats(bool ran_command);
- void change_user(void);
- void cleanup(void);
- void cleanup_after_query();
-@@ -2860,6 +2912,15 @@
- }
- thd_scheduler scheduler;
-
-+ /* Returns string as 'IP:port' for the client-side
-+ of the connnection represented
-+ by 'client' as displayed by SHOW PROCESSLIST.
-+ Allocates memory from the heap of
-+ this THD and that is not reclaimed
-+ immediately, so use sparingly. May return NULL.
-+ */
-+ char *get_client_host_port(THD *client);
-+
- public:
- inline Internal_error_handler *get_internal_handler()
- { return m_internal_handler; }
-@@ -3060,6 +3121,10 @@
- LEX_STRING invoker_host;
- };
-
-+/* Returns string as 'IP' for the client-side of the connection represented by
-+ 'client'. Does not allocate memory. May return "".
-+*/
-+const char *get_client_host(THD *client);
-
- /** A short cut for thd->stmt_da->set_ok_status(). */
-
---- a/sql/sql_connect.cc
-+++ b/sql/sql_connect.cc
-@@ -56,6 +56,24 @@
- #define MIN_HANDSHAKE_SIZE 6
- #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
-
-+// Increments connection count for user.
-+static int increment_connection_count(THD* thd, bool use_lock);
-+
-+// Uses the THD to update the global stats by user name and client IP
-+void update_global_user_stats(THD* thd, bool create_user, time_t now);
-+
-+HASH global_user_stats;
-+HASH global_client_stats;
-+HASH global_thread_stats;
-+// Protects global_user_stats and global_client_stats
-+extern mysql_mutex_t LOCK_global_user_client_stats;
-+
-+HASH global_table_stats;
-+extern mysql_mutex_t LOCK_global_table_stats;
-+
-+HASH global_index_stats;
-+extern mysql_mutex_t LOCK_global_index_stats;
-+
- /*
- Get structure for logging connection data for the current user
- */
-@@ -113,6 +131,586 @@
-
- }
-
-+extern "C" uchar *get_key_user_stats(USER_STATS *user_stats, size_t *length,
-+ my_bool not_used __attribute__((unused)))
-+{
-+ *length= strlen(user_stats->user);
-+ return (uchar*) user_stats->user;
-+}
-+
-+extern "C" uchar *get_key_thread_stats(THREAD_STATS *thread_stats, size_t *length,
-+ my_bool not_used __attribute__((unused)))
-+{
-+ *length= sizeof(my_thread_id);
-+ return (uchar *) &(thread_stats->id);
-+}
-+
-+void free_user_stats(USER_STATS* user_stats)
-+{
-+ my_free((char *) user_stats);
-+}
-+
-+void free_thread_stats(THREAD_STATS* thread_stats)
-+{
-+ my_free((char *) thread_stats);
-+}
-+
-+void init_user_stats(USER_STATS *user_stats,
-+ const char *user,
-+ const char *priv_user,
-+ uint total_connections,
-+ uint concurrent_connections,
-+ time_t connected_time,
-+ double busy_time,
-+ double cpu_time,
-+ ulonglong bytes_received,
-+ ulonglong bytes_sent,
-+ ulonglong binlog_bytes_written,
-+ ha_rows rows_fetched,
-+ ha_rows rows_updated,
-+ ha_rows rows_read,
-+ ulonglong select_commands,
-+ ulonglong update_commands,
-+ ulonglong other_commands,
-+ ulonglong commit_trans,
-+ ulonglong rollback_trans,
-+ ulonglong denied_connections,
-+ ulonglong lost_connections,
-+ ulonglong access_denied_errors,
-+ ulonglong empty_queries)
-+{
-+ DBUG_ENTER("init_user_stats");
-+ DBUG_PRINT("info",
-+ ("Add user_stats entry for user %s - priv_user %s",
-+ user, priv_user));
-+ strncpy(user_stats->user, user, sizeof(user_stats->user));
-+ strncpy(user_stats->priv_user, priv_user, sizeof(user_stats->priv_user));
-+
-+ user_stats->total_connections= total_connections;
-+ user_stats->concurrent_connections= concurrent_connections;
-+ user_stats->connected_time= connected_time;
-+ user_stats->busy_time= busy_time;
-+ user_stats->cpu_time= cpu_time;
-+ user_stats->bytes_received= bytes_received;
-+ user_stats->bytes_sent= bytes_sent;
-+ user_stats->binlog_bytes_written= binlog_bytes_written;
-+ user_stats->rows_fetched= rows_fetched;
-+ user_stats->rows_updated= rows_updated;
-+ user_stats->rows_read= rows_read;
-+ user_stats->select_commands= select_commands;
-+ user_stats->update_commands= update_commands;
-+ user_stats->other_commands= other_commands;
-+ user_stats->commit_trans= commit_trans;
-+ user_stats->rollback_trans= rollback_trans;
-+ user_stats->denied_connections= denied_connections;
-+ user_stats->lost_connections= lost_connections;
-+ user_stats->access_denied_errors= access_denied_errors;
-+ user_stats->empty_queries= empty_queries;
-+ DBUG_VOID_RETURN;
-+}
-+
-+void init_thread_stats(THREAD_STATS *thread_stats,
-+ my_thread_id id,
-+ uint total_connections,
-+ uint concurrent_connections,
-+ time_t connected_time,
-+ double busy_time,
-+ double cpu_time,
-+ ulonglong bytes_received,
-+ ulonglong bytes_sent,
-+ ulonglong binlog_bytes_written,
-+ ha_rows rows_fetched,
-+ ha_rows rows_updated,
-+ ha_rows rows_read,
-+ ulonglong select_commands,
-+ ulonglong update_commands,
-+ ulonglong other_commands,
-+ ulonglong commit_trans,
-+ ulonglong rollback_trans,
-+ ulonglong denied_connections,
-+ ulonglong lost_connections,
-+ ulonglong access_denied_errors,
-+ ulonglong empty_queries)
-+{
-+ DBUG_ENTER("init_thread_stats");
-+ DBUG_PRINT("info",
-+ ("Add thread_stats entry for thread %lu",
-+ id));
-+ thread_stats->id= id;
-+
-+ thread_stats->total_connections= total_connections;
-+ thread_stats->concurrent_connections= concurrent_connections;
-+ thread_stats->connected_time= connected_time;
-+ thread_stats->busy_time= busy_time;
-+ thread_stats->cpu_time= cpu_time;
-+ thread_stats->bytes_received= bytes_received;
-+ thread_stats->bytes_sent= bytes_sent;
-+ thread_stats->binlog_bytes_written= binlog_bytes_written;
-+ thread_stats->rows_fetched= rows_fetched;
-+ thread_stats->rows_updated= rows_updated;
-+ thread_stats->rows_read= rows_read;
-+ thread_stats->select_commands= select_commands;
-+ thread_stats->update_commands= update_commands;
-+ thread_stats->other_commands= other_commands;
-+ thread_stats->commit_trans= commit_trans;
-+ thread_stats->rollback_trans= rollback_trans;
-+ thread_stats->denied_connections= denied_connections;
-+ thread_stats->lost_connections= lost_connections;
-+ thread_stats->access_denied_errors= access_denied_errors;
-+ thread_stats->empty_queries= empty_queries;
-+ DBUG_VOID_RETURN;
-+}
-+
-+void add_user_stats(USER_STATS *user_stats,
-+ uint total_connections,
-+ uint concurrent_connections,
-+ time_t connected_time,
-+ double busy_time,
-+ double cpu_time,
-+ ulonglong bytes_received,
-+ ulonglong bytes_sent,
-+ ulonglong binlog_bytes_written,
-+ ha_rows rows_fetched,
-+ ha_rows rows_updated,
-+ ha_rows rows_read,
-+ ulonglong select_commands,
-+ ulonglong update_commands,
-+ ulonglong other_commands,
-+ ulonglong commit_trans,
-+ ulonglong rollback_trans,
-+ ulonglong denied_connections,
-+ ulonglong lost_connections,
-+ ulonglong access_denied_errors,
-+ ulonglong empty_queries)
-+{
-+ user_stats->total_connections+= total_connections;
-+ user_stats->concurrent_connections+= concurrent_connections;
-+ user_stats->connected_time+= connected_time;
-+ user_stats->busy_time+= busy_time;
-+ user_stats->cpu_time+= cpu_time;
-+ user_stats->bytes_received+= bytes_received;
-+ user_stats->bytes_sent+= bytes_sent;
-+ user_stats->binlog_bytes_written+= binlog_bytes_written;
-+ user_stats->rows_fetched+= rows_fetched;
-+ user_stats->rows_updated+= rows_updated;
-+ user_stats->rows_read+= rows_read;
-+ user_stats->select_commands+= select_commands;
-+ user_stats->update_commands+= update_commands;
-+ user_stats->other_commands+= other_commands;
-+ user_stats->commit_trans+= commit_trans;
-+ user_stats->rollback_trans+= rollback_trans;
-+ user_stats->denied_connections+= denied_connections;
-+ user_stats->lost_connections+= lost_connections;
-+ user_stats->access_denied_errors+= access_denied_errors;
-+ user_stats->empty_queries+= empty_queries;
-+}
-+
-+void add_thread_stats(THREAD_STATS *thread_stats,
-+ uint total_connections,
-+ uint concurrent_connections,
-+ time_t connected_time,
-+ double busy_time,
-+ double cpu_time,
-+ ulonglong bytes_received,
-+ ulonglong bytes_sent,
-+ ulonglong binlog_bytes_written,
-+ ha_rows rows_fetched,
-+ ha_rows rows_updated,
-+ ha_rows rows_read,
-+ ulonglong select_commands,
-+ ulonglong update_commands,
-+ ulonglong other_commands,
-+ ulonglong commit_trans,
-+ ulonglong rollback_trans,
-+ ulonglong denied_connections,
-+ ulonglong lost_connections,
-+ ulonglong access_denied_errors,
-+ ulonglong empty_queries)
-+{
-+ thread_stats->total_connections+= total_connections;
-+ thread_stats->concurrent_connections+= concurrent_connections;
-+ thread_stats->connected_time+= connected_time;
-+ thread_stats->busy_time+= busy_time;
-+ thread_stats->cpu_time+= cpu_time;
-+ thread_stats->bytes_received+= bytes_received;
-+ thread_stats->bytes_sent+= bytes_sent;
-+ thread_stats->binlog_bytes_written+= binlog_bytes_written;
-+ thread_stats->rows_fetched+= rows_fetched;
-+ thread_stats->rows_updated+= rows_updated;
-+ thread_stats->rows_read+= rows_read;
-+ thread_stats->select_commands+= select_commands;
-+ thread_stats->update_commands+= update_commands;
-+ thread_stats->other_commands+= other_commands;
-+ thread_stats->commit_trans+= commit_trans;
-+ thread_stats->rollback_trans+= rollback_trans;
-+ thread_stats->denied_connections+= denied_connections;
-+ thread_stats->lost_connections+= lost_connections;
-+ thread_stats->access_denied_errors+= access_denied_errors;
-+ thread_stats->empty_queries+= empty_queries;
-+}
-+
-+void init_global_user_stats(void)
-+{
-+ if (my_hash_init(&global_user_stats, system_charset_info, max_connections,
-+ 0, 0, (my_hash_get_key)get_key_user_stats,
-+ (my_hash_free_key)free_user_stats, 0)) {
-+ sql_print_error("Initializing global_user_stats failed.");
-+ exit(1);
-+ }
-+}
-+
-+void init_global_client_stats(void)
-+{
-+ if (my_hash_init(&global_client_stats, system_charset_info, max_connections,
-+ 0, 0, (my_hash_get_key)get_key_user_stats,
-+ (my_hash_free_key)free_user_stats, 0)) {
-+ sql_print_error("Initializing global_client_stats failed.");
-+ exit(1);
-+ }
-+}
-+
-+void init_global_thread_stats(void)
-+{
-+ if (my_hash_init(&global_thread_stats, &my_charset_bin, max_connections,
-+ 0, 0, (my_hash_get_key) get_key_thread_stats,
-+ (my_hash_free_key) free_thread_stats, 0))
-+ {
-+ sql_print_error("Initializing global_client_stats failed.");
-+ exit(1);
-+ }
-+}
-+
-+extern "C" uchar *get_key_table_stats(TABLE_STATS *table_stats, size_t *length,
-+ my_bool not_used __attribute__((unused)))
-+{
-+ *length= strlen(table_stats->table);
-+ return (uchar*) table_stats->table;
-+}
-+
-+extern "C" void free_table_stats(TABLE_STATS* table_stats)
-+{
-+ my_free((char*) table_stats);
-+}
-+
-+void init_global_table_stats(void)
-+{
-+ if (my_hash_init(&global_table_stats, system_charset_info, max_connections,
-+ 0, 0, (my_hash_get_key)get_key_table_stats,
-+ (my_hash_free_key)free_table_stats, 0)) {
-+ sql_print_error("Initializing global_table_stats failed.");
-+ exit(1);
-+ }
-+}
-+
-+extern "C" uchar *get_key_index_stats(INDEX_STATS *index_stats, size_t *length,
-+ my_bool not_used __attribute__((unused)))
-+{
-+ *length= strlen(index_stats->index);
-+ return (uchar*) index_stats->index;
-+}
-+
-+extern "C" void free_index_stats(INDEX_STATS* index_stats)
-+{
-+ my_free((char*) index_stats);
-+}
-+
-+void init_global_index_stats(void)
-+{
-+ if (my_hash_init(&global_index_stats, system_charset_info, max_connections,
-+ 0, 0, (my_hash_get_key)get_key_index_stats,
-+ (my_hash_free_key)free_index_stats, 0)) {
-+ sql_print_error("Initializing global_index_stats failed.");
-+ exit(1);
-+ }
-+}
-+
-+void free_global_user_stats(void)
-+{
-+ my_hash_free(&global_user_stats);
-+}
-+
-+void free_global_thread_stats(void)
-+{
-+ my_hash_free(&global_thread_stats);
-+}
-+
-+void free_global_table_stats(void)
-+{
-+ my_hash_free(&global_table_stats);
-+}
-+
-+void free_global_index_stats(void)
-+{
-+ my_hash_free(&global_index_stats);
-+}
-+
-+void free_global_client_stats(void)
-+{
-+ my_hash_free(&global_client_stats);
-+}
-+
-+// 'mysql_system_user' is used for when the user is not defined for a THD.
-+static char mysql_system_user[] = "#mysql_system#";
-+
-+// Returns 'user' if it's not NULL. Returns 'mysql_system_user' otherwise.
-+static char* get_valid_user_string(char* user) {
-+ return user ? user : mysql_system_user;
-+}
-+
-+// Increments the global stats connection count for an entry from
-+// global_client_stats or global_user_stats. Returns 0 on success
-+// and 1 on error.
-+static int increment_count_by_name(const char *name, const char *role_name,
-+ HASH *users_or_clients, THD *thd)
-+{
-+ USER_STATS* user_stats;
-+
-+ if (!(user_stats = (USER_STATS *) my_hash_search(users_or_clients,
-+ (uchar*) name,
-+ strlen(name))))
-+ {
-+ // First connection for this user or client
-+ if (!(user_stats = ((USER_STATS *)
-+ my_malloc(sizeof(USER_STATS), MYF(MY_WME | MY_ZEROFILL)))))
-+ {
-+ return 1; // Out of memory
-+ }
-+
-+ init_user_stats(user_stats, name, role_name,
-+ 0, 0, // connections
-+ 0, 0, 0, // time
-+ 0, 0, 0, // bytes sent, received and written
-+ 0, 0, 0, // rows fetched, updated and read
-+ 0, 0, 0, // select, update and other commands
-+ 0, 0, // commit and rollback trans
-+ thd->diff_denied_connections,
-+ 0, // lost connections
-+ 0, // access denied errors
-+ 0); // empty queries
-+
-+ if (my_hash_insert(users_or_clients, (uchar *) user_stats))
-+ {
-+ my_free((char *) user_stats);
-+ return 1; // Out of memory
-+ }
-+ }
-+ user_stats->total_connections++;
-+ return 0;
-+}
-+
-+static int increment_count_by_id(my_thread_id id,
-+ HASH *users_or_clients, THD *thd)
-+{
-+ THREAD_STATS* thread_stats;
-+
-+ if (!(thread_stats = (THREAD_STATS *) my_hash_search(users_or_clients,
-+ (uchar*) &id,
-+ sizeof(my_thread_id))))
-+ {
-+ // First connection for this user or client
-+ if (!(thread_stats = ((THREAD_STATS *)
-+ my_malloc(sizeof(THREAD_STATS), MYF(MY_WME | MY_ZEROFILL)))))
-+ {
-+ return 1; // Out of memory
-+ }
-+
-+ init_thread_stats(thread_stats, id,
-+ 0, 0, // connections
-+ 0, 0, 0, // time
-+ 0, 0, 0, // bytes sent, received and written
-+ 0, 0, 0, // rows fetched, updated and read
-+ 0, 0, 0, // select, update and other commands
-+ 0, 0, // commit and rollback trans
-+ thd->diff_denied_connections,
-+ 0, // lost connections
-+ 0, // access denied errors
-+ 0); // empty queries
-+
-+ if (my_hash_insert(users_or_clients, (uchar *) thread_stats))
-+ {
-+ my_free((char *) thread_stats);
-+ return 1; // Out of memory
-+ }
-+ }
-+ thread_stats->total_connections++;
-+ return 0;
-+}
-+
-+/* Increments the global user and client stats connection count. If 'use_lock'
-+ is true, LOCK_global_user_client_stats will be locked/unlocked. Returns
-+ 0 on success, 1 on error.
-+*/
-+static int increment_connection_count(THD* thd, bool use_lock)
-+{
-+ char* user_string= get_valid_user_string(thd->main_security_ctx.user);
-+ const char* client_string= get_client_host(thd);
-+ int return_value= 0;
-+
-+ if (!opt_userstat)
-+ return return_value;
-+
-+ if (use_lock)
-+ mysql_mutex_lock(&LOCK_global_user_client_stats);
-+
-+ if (increment_count_by_name(user_string, user_string,
-+ &global_user_stats, thd))
-+ {
-+ return_value= 1;
-+ goto end;
-+ }
-+ if (increment_count_by_name(client_string,
-+ user_string,
-+ &global_client_stats, thd))
-+ {
-+ return_value= 1;
-+ goto end;
-+ }
-+ if (opt_thread_statistics)
-+ {
-+ if (increment_count_by_id(thd->thread_id, &global_thread_stats, thd))
-+ {
-+ return_value= 1;
-+ goto end;
-+ }
-+ }
-+
-+end:
-+ if (use_lock)
-+ mysql_mutex_unlock(&LOCK_global_user_client_stats);
-+ return return_value;
-+}
-+
-+// Used to update the global user and client stats.
-+static void update_global_user_stats_with_user(THD* thd,
-+ USER_STATS* user_stats,
-+ time_t now)
-+{
-+ user_stats->connected_time+= now - thd->last_global_update_time;
-+//thd->last_global_update_time= now;
-+ user_stats->busy_time+= thd->diff_total_busy_time;
-+ user_stats->cpu_time+= thd->diff_total_cpu_time;
-+ user_stats->bytes_received+= thd->diff_total_bytes_received;
-+ user_stats->bytes_sent+= thd->diff_total_bytes_sent;
-+ user_stats->binlog_bytes_written+= thd->diff_total_binlog_bytes_written;
-+ user_stats->rows_fetched+= thd->diff_total_sent_rows;
-+ user_stats->rows_updated+= thd->diff_total_updated_rows;
-+ user_stats->rows_read+= thd->diff_total_read_rows;
-+ user_stats->select_commands+= thd->diff_select_commands;
-+ user_stats->update_commands+= thd->diff_update_commands;
-+ user_stats->other_commands+= thd->diff_other_commands;
-+ user_stats->commit_trans+= thd->diff_commit_trans;
-+ user_stats->rollback_trans+= thd->diff_rollback_trans;
-+ user_stats->denied_connections+= thd->diff_denied_connections;
-+ user_stats->lost_connections+= thd->diff_lost_connections;
-+ user_stats->access_denied_errors+= thd->diff_access_denied_errors;
-+ user_stats->empty_queries+= thd->diff_empty_queries;
-+}
-+
-+static void update_global_thread_stats_with_thread(THD* thd,
-+ THREAD_STATS* thread_stats,
-+ time_t now)
-+{
-+ thread_stats->connected_time+= now - thd->last_global_update_time;
-+//thd->last_global_update_time= now;
-+ thread_stats->busy_time+= thd->diff_total_busy_time;
-+ thread_stats->cpu_time+= thd->diff_total_cpu_time;
-+ thread_stats->bytes_received+= thd->diff_total_bytes_received;
-+ thread_stats->bytes_sent+= thd->diff_total_bytes_sent;
-+ thread_stats->binlog_bytes_written+= thd->diff_total_binlog_bytes_written;
-+ thread_stats->rows_fetched+= thd->diff_total_sent_rows;
-+ thread_stats->rows_updated+= thd->diff_total_updated_rows;
-+ thread_stats->rows_read+= thd->diff_total_read_rows;
-+ thread_stats->select_commands+= thd->diff_select_commands;
-+ thread_stats->update_commands+= thd->diff_update_commands;
-+ thread_stats->other_commands+= thd->diff_other_commands;
-+ thread_stats->commit_trans+= thd->diff_commit_trans;
-+ thread_stats->rollback_trans+= thd->diff_rollback_trans;
-+ thread_stats->denied_connections+= thd->diff_denied_connections;
-+ thread_stats->lost_connections+= thd->diff_lost_connections;
-+ thread_stats->access_denied_errors+= thd->diff_access_denied_errors;
-+ thread_stats->empty_queries+= thd->diff_empty_queries;
-+}
-+
-+// Updates the global stats of a user or client
-+void update_global_user_stats(THD* thd, bool create_user, time_t now)
-+{
-+ if (opt_userstat)
-+ {
-+ char* user_string= get_valid_user_string(thd->main_security_ctx.user);
-+ const char* client_string= get_client_host(thd);
-+
-+ USER_STATS* user_stats;
-+ THREAD_STATS* thread_stats;
-+ mysql_mutex_lock(&LOCK_global_user_client_stats);
-+
-+ // Update by user name
-+ if ((user_stats = (USER_STATS *) my_hash_search(&global_user_stats,
-+ (uchar *) user_string,
-+ strlen(user_string))))
-+ {
-+ // Found user.
-+ update_global_user_stats_with_user(thd, user_stats, now);
-+ }
-+ else
-+ {
-+ // Create the entry
-+ if (create_user)
-+ {
-+ increment_count_by_name(user_string, user_string,
-+ &global_user_stats, thd);
-+ }
-+ }
-+
-+ // Update by client IP
-+ if ((user_stats = (USER_STATS *) my_hash_search(&global_client_stats,
-+ (uchar *) client_string,
-+ strlen(client_string))))
-+ {
-+ // Found by client IP
-+ update_global_user_stats_with_user(thd, user_stats, now);
-+ }
-+ else
-+ {
-+ // Create the entry
-+ if (create_user)
-+ {
-+ increment_count_by_name(client_string,
-+ user_string,
-+ &global_client_stats, thd);
-+ }
-+ }
-+
-+ if (opt_thread_statistics)
-+ {
-+ // Update by thread ID
-+ if ((thread_stats = (THREAD_STATS *) my_hash_search(&global_thread_stats,
-+ (uchar *) &(thd->thread_id),
-+ sizeof(my_thread_id))))
-+ {
-+ // Found by thread ID
-+ update_global_thread_stats_with_thread(thd, thread_stats, now);
-+ }
-+ else
-+ {
-+ // Create the entry
-+ if (create_user)
-+ {
-+ increment_count_by_id(thd->thread_id,
-+ &global_thread_stats, thd);
-+ }
-+ }
-+ }
-+
-+ thd->last_global_update_time = now;
-+ thd->reset_diff_stats();
-+
-+ mysql_mutex_unlock(&LOCK_global_user_client_stats);
-+ }
-+ else
-+ {
-+ thd->reset_diff_stats();
-+ }
-+}
-
- /*
- check if user has already too many connections
-@@ -170,6 +768,7 @@
- if (error)
- {
- uc->connections--; // no need for decrease_user_connections() here
-+ statistic_increment(denied_connections, &LOCK_status);
- /*
- The thread may returned back to the pool and assigned to a user
- that doesn't have a limit. Ensure the user is not using resources
-@@ -589,11 +1188,18 @@
- my_sleep(1000); /* must wait after eof() */
- #endif
- statistic_increment(aborted_connects,&LOCK_status);
-+ thd->diff_denied_connections++;
- DBUG_RETURN(1);
- }
- /* Connect completed, set read/write timeouts back to default */
- my_net_set_read_timeout(net, thd->variables.net_read_timeout);
- my_net_set_write_timeout(net, thd->variables.net_write_timeout);
-+
-+ thd->reset_stats();
-+ // Updates global user connection stats.
-+ if (increment_connection_count(thd, true))
-+ DBUG_RETURN(1);
-+
- DBUG_RETURN(0);
- }
-
-@@ -623,6 +1229,7 @@
- if (thd->killed || (net->error && net->vio != 0))
- {
- statistic_increment(aborted_threads,&LOCK_status);
-+ thd->diff_lost_connections++;
- }
-
- if (net->error && net->vio != 0)
-@@ -787,10 +1394,14 @@
- for (;;)
- {
- bool rc;
-+ bool create_user= TRUE;
-
- rc= thd_prepare_connection(thd);
- if (rc)
-+ {
-+ create_user= FALSE;
- goto end_thread;
-+ }
-
- while (thd_is_connection_alive(thd))
- {
-@@ -802,6 +1413,8 @@
-
- end_thread:
- close_connection(thd);
-+ thd->update_stats(false);
-+ update_global_user_stats(thd, create_user, time(NULL));
- if (MYSQL_CALLBACK_ELSE(thread_scheduler, end_thread, (thd, 1), 0))
- return; // Probably no-threads
-
---- a/sql/sql_delete.cc
-+++ b/sql/sql_delete.cc
-@@ -411,6 +411,7 @@
- my_ok(thd, deleted);
- DBUG_PRINT("info",("%ld records deleted",(long) deleted));
- }
-+ thd->updated_row_count+= deleted;
- DBUG_RETURN(error >= 0 || thd->is_error());
- }
-
-@@ -1005,6 +1006,7 @@
- {
- ::my_ok(thd, deleted);
- }
-+ thd->updated_row_count+= deleted;
- return 0;
- }
-
---- a/sql/sql_insert.cc
-+++ b/sql/sql_insert.cc
-@@ -1072,13 +1072,14 @@
-
- if (error)
- goto abort;
-+ ha_rows row_count;
- if (values_list.elements == 1 && (!(thd->variables.option_bits & OPTION_WARNINGS) ||
- !thd->cuted_fields))
- {
-- my_ok(thd, info.copied + info.deleted +
-+ row_count= info.copied + info.deleted +
- ((thd->client_capabilities & CLIENT_FOUND_ROWS) ?
-- info.touched : info.updated),
-- id);
-+ info.touched : info.updated);
-+ my_ok(thd, row_count, id);
- }
- else
- {
-@@ -1094,8 +1095,10 @@
- sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
- (ulong) (info.deleted + updated),
- (ulong) thd->warning_info->statement_warn_count());
-- ::my_ok(thd, info.copied + info.deleted + updated, id, buff);
-+ row_count= info.copied + info.deleted + updated;
-+ ::my_ok(thd, row_count, id, buff);
- }
-+ thd->updated_row_count+= row_count;
- thd->abort_on_warning= 0;
- DBUG_RETURN(FALSE);
-
-@@ -3540,6 +3543,7 @@
- thd->first_successful_insert_id_in_prev_stmt :
- (info.copied ? autoinc_value_of_last_inserted_row : 0));
- ::my_ok(thd, row_count, id, buff);
-+ thd->updated_row_count+= row_count;
- DBUG_RETURN(0);
- }
-
---- a/sql/sql_lex.h
-+++ b/sql/sql_lex.h
-@@ -197,6 +197,9 @@
- in "struct show_var_st status_vars[]= {" ...
- */
- SQLCOM_SHOW_TEMPORARY_TABLES,
-+ // TODO(mcallaghan): update status_vars in mysqld to export these
-+ SQLCOM_SHOW_USER_STATS, SQLCOM_SHOW_TABLE_STATS, SQLCOM_SHOW_INDEX_STATS,
-+ SQLCOM_SHOW_CLIENT_STATS, SQLCOM_SHOW_THREAD_STATS,
- /* This should be the last !!! */
- SQLCOM_END
- };
---- a/sql/sql_parse.cc
-+++ b/sql/sql_parse.cc
-@@ -117,6 +117,9 @@
- static void sql_kill(THD *thd, ulong id, bool only_kill_query);
- static inline ulonglong get_query_exec_time(THD *thd, ulonglong cur_utime);
-
-+// Uses the THD to update the global stats by user name and client IP
-+void update_global_user_stats(THD* thd, bool create_user, time_t now);
-+
- const char *any_db="*any*"; // Special symbol for check_access
-
- const LEX_STRING command_name[]={
-@@ -703,6 +706,12 @@
- */
- thd->clear_error(); // Clear error message
- thd->stmt_da->reset_diagnostics_area();
-+ thd->updated_row_count= 0;
-+ thd->busy_time= 0;
-+ thd->cpu_time= 0;
-+ thd->bytes_received= 0;
-+ thd->bytes_sent= 0;
-+ thd->binlog_bytes_written= 0;
-
- net_new_transaction(net);
-
-@@ -888,6 +897,10 @@
- (char *) thd->security_ctx->host_or_ip);
-
- thd->command=command;
-+ /* To increment the corrent command counter for user stats, 'command' must
-+ be saved because it is set to COM_SLEEP at the end of this function.
-+ */
-+ thd->old_command= command;
- /*
- Commands which always take a long time are logged into
- the slow log only if opt_log_slow_admin_statements is set.
-@@ -1683,6 +1696,13 @@
- thd->profiling.discard_current_query();
- #endif
- break;
-+ case SCH_USER_STATS:
-+ case SCH_CLIENT_STATS:
-+ case SCH_THREAD_STATS:
-+ if (check_global_access(thd, SUPER_ACL | PROCESS_ACL))
-+ DBUG_RETURN(1);
-+ case SCH_TABLE_STATS:
-+ case SCH_INDEX_STATS:
- case SCH_OPEN_TABLES:
- case SCH_VARIABLES:
- case SCH_STATUS:
-@@ -1857,6 +1877,7 @@
- thd->security_ctx->priv_host)) &&
- check_global_access(thd, SUPER_ACL))
- {
-+ thd->diff_access_denied_errors++;
- my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
- DBUG_RETURN(TRUE);
- }
-@@ -4892,6 +4913,7 @@
- case ACL_INTERNAL_ACCESS_DENIED:
- if (! no_errors)
- {
-+ thd->diff_access_denied_errors++;
- my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
- sctx->priv_user, sctx->priv_host, db);
- }
-@@ -4942,6 +4964,7 @@
- DBUG_PRINT("error",("No possible access"));
- if (!no_errors)
- {
-+ thd->diff_access_denied_errors++;
- if (thd->password == 2)
- my_error(ER_ACCESS_DENIED_NO_PASSWORD_ERROR, MYF(0),
- sctx->priv_user,
-@@ -5058,6 +5081,7 @@
-
- if (!thd->col_access && check_grant_db(thd, dst_db_name))
- {
-+ thd->diff_access_denied_errors++;
- my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
- thd->security_ctx->priv_user,
- thd->security_ctx->priv_host,
-@@ -5328,6 +5352,7 @@
- if ((thd->security_ctx->master_access & want_access))
- return 0;
- get_privilege_desc(command, sizeof(command), want_access);
-+ thd->diff_access_denied_errors++;
- my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command);
- return 1;
- #else
-@@ -5695,6 +5720,32 @@
- lex_start(thd);
- mysql_reset_thd_for_next_command(thd);
-
-+ int start_time_error= 0;
-+ int end_time_error= 0;
-+ struct timeval start_time, end_time;
-+ double start_usecs= 0;
-+ double end_usecs= 0;
-+ /* cpu time */
-+ int cputime_error= 0;
-+ struct timespec tp;
-+ double start_cpu_nsecs= 0;
-+ double end_cpu_nsecs= 0;
-+
-+ if (opt_userstat)
-+ {
-+#ifdef HAVE_CLOCK_GETTIME
-+ /* get start cputime */
-+ if (!(cputime_error = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)))
-+ start_cpu_nsecs = tp.tv_sec*1000000000.0+tp.tv_nsec;
-+#endif
-+
-+ // Gets the start time, in order to measure how long this command takes.
-+ if (!(start_time_error = gettimeofday(&start_time, NULL)))
-+ {
-+ start_usecs = start_time.tv_sec * 1000000.0 + start_time.tv_usec;
-+ }
-+ }
-+
- if (query_cache_send_result_to_client(thd, rawbuf, length) <= 0)
- {
- LEX *lex= thd->lex;
-@@ -5763,6 +5814,52 @@
- DBUG_ASSERT(thd->change_list.is_empty());
- }
-
-+ if (opt_userstat)
-+ {
-+ // Gets the end time.
-+ if (!(end_time_error= gettimeofday(&end_time, NULL)))
-+ {
-+ end_usecs= end_time.tv_sec * 1000000.0 + end_time.tv_usec;
-+ }
-+
-+ // Calculates the difference between the end and start times.
-+ if (start_usecs && end_usecs >= start_usecs && !start_time_error && !end_time_error)
-+ {
-+ thd->busy_time= (end_usecs - start_usecs) / 1000000;
-+ // In case there are bad values, 2629743 is the #seconds in a month.
-+ if (thd->busy_time > 2629743)
-+ {
-+ thd->busy_time= 0;
-+ }
-+ }
-+ else
-+ {
-+ // end time went back in time, or gettimeofday() failed.
-+ thd->busy_time= 0;
-+ }
-+
-+#ifdef HAVE_CLOCK_GETTIME
-+ /* get end cputime */
-+ if (!cputime_error &&
-+ !(cputime_error = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)))
-+ end_cpu_nsecs = tp.tv_sec*1000000000.0+tp.tv_nsec;
-+#endif
-+ if (start_cpu_nsecs && !cputime_error)
-+ {
-+ thd->cpu_time = (end_cpu_nsecs - start_cpu_nsecs) / 1000000000;
-+ // In case there are bad values, 2629743 is the #seconds in a month.
-+ if (thd->cpu_time > 2629743)
-+ {
-+ thd->cpu_time = 0;
-+ }
-+ }
-+ else
-+ thd->cpu_time = 0;
-+ }
-+ // Updates THD stats and the global user stats.
-+ thd->update_stats(true);
-+ update_global_user_stats(thd, true, time(NULL));
-+
- DBUG_VOID_RETURN;
- }
-
---- a/sql/sql_prepare.cc
-+++ b/sql/sql_prepare.cc
-@@ -114,6 +114,9 @@
- #endif
- #include "lock.h" // MYSQL_OPEN_FORCE_SHARED_MDL
-
-+// Uses the THD to update the global stats by user name and client IP
-+void update_global_user_stats(THD* thd, bool create_user, time_t now);
-+
- /**
- A result class used to send cursor rows using the binary protocol.
- */
-@@ -2173,8 +2176,34 @@
- /* First of all clear possible warnings from the previous command */
- mysql_reset_thd_for_next_command(thd);
-
-+ int start_time_error= 0;
-+ int end_time_error= 0;
-+ struct timeval start_time, end_time;
-+ double start_usecs= 0;
-+ double end_usecs= 0;
-+ /* cpu time */
-+ int cputime_error= 0;
-+ struct timespec tp;
-+ double start_cpu_nsecs= 0;
-+ double end_cpu_nsecs= 0;
-+
-+ if (opt_userstat)
-+ {
-+#ifdef HAVE_CLOCK_GETTIME
-+ /* get start cputime */
-+ if (!(cputime_error= clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)))
-+ start_cpu_nsecs= tp.tv_sec * 1000000000.0 + tp.tv_nsec;
-+#endif
-+
-+ // Gets the start time, in order to measure how long this command takes.
-+ if (!(start_time_error= gettimeofday(&start_time, NULL)))
-+ {
-+ start_usecs= start_time.tv_sec * 1000000.0 + start_time.tv_usec;
-+ }
-+ }
-+
- if (! (stmt= new Prepared_statement(thd)))
-- DBUG_VOID_RETURN; /* out of memory: error is set in Sql_alloc */
-+ goto end; /* out of memory: error is set in Sql_alloc */
-
- if (thd->stmt_map.insert(thd, stmt))
- {
-@@ -2182,7 +2211,7 @@
- The error is set in the insert. The statement itself
- will be also deleted there (this is how the hash works).
- */
-- DBUG_VOID_RETURN;
-+ goto end;
- }
-
- thd->protocol= &thd->protocol_binary;
-@@ -2196,6 +2225,53 @@
- thd->protocol= save_protocol;
-
- /* check_prepared_statemnt sends the metadata packet in case of success */
-+end:
-+ if (opt_userstat)
-+ {
-+ // Gets the end time.
-+ if (!(end_time_error= gettimeofday(&end_time, NULL)))
-+ {
-+ end_usecs= end_time.tv_sec * 1000000.0 + end_time.tv_usec;
-+ }
-+
-+ // Calculates the difference between the end and start times.
-+ if (start_usecs && end_usecs >= start_usecs && !start_time_error && !end_time_error)
-+ {
-+ thd->busy_time= (end_usecs - start_usecs) / 1000000;
-+ // In case there are bad values, 2629743 is the #seconds in a month.
-+ if (thd->busy_time > 2629743)
-+ {
-+ thd->busy_time= 0;
-+ }
-+ }
-+ else
-+ {
-+ // end time went back in time, or gettimeofday() failed.
-+ thd->busy_time= 0;
-+ }
-+
-+#ifdef HAVE_CLOCK_GETTIME
-+ /* get end cputime */
-+ if (!cputime_error &&
-+ !(cputime_error= clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)))
-+ end_cpu_nsecs= tp.tv_sec*1000000000.0+tp.tv_nsec;
-+#endif
-+ if (start_cpu_nsecs && !cputime_error)
-+ {
-+ thd->cpu_time= (end_cpu_nsecs - start_cpu_nsecs) / 1000000000;
-+ // In case there are bad values, 2629743 is the #seconds in a month.
-+ if (thd->cpu_time > 2629743)
-+ {
-+ thd->cpu_time= 0;
-+ }
-+ }
-+ else
-+ thd->cpu_time = 0;
-+ }
-+ // Updates THD stats and the global user stats.
-+ thd->update_stats(true);
-+ update_global_user_stats(thd, true, time(NULL));
-+
- DBUG_VOID_RETURN;
- }
-
-@@ -2540,12 +2616,38 @@
- /* First of all clear possible warnings from the previous command */
- mysql_reset_thd_for_next_command(thd);
-
-+ int start_time_error= 0;
-+ int end_time_error= 0;
-+ struct timeval start_time, end_time;
-+ double start_usecs= 0;
-+ double end_usecs= 0;
-+ /* cpu time */
-+ int cputime_error= 0;
-+ struct timespec tp;
-+ double start_cpu_nsecs= 0;
-+ double end_cpu_nsecs= 0;
-+
-+ if (opt_userstat)
-+ {
-+#ifdef HAVE_CLOCK_GETTIME
-+ /* get start cputime */
-+ if (!(cputime_error = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)))
-+ start_cpu_nsecs = tp.tv_sec*1000000000.0+tp.tv_nsec;
-+#endif
-+
-+ // Gets the start time, in order to measure how long this command takes.
-+ if (!(start_time_error = gettimeofday(&start_time, NULL)))
-+ {
-+ start_usecs = start_time.tv_sec * 1000000.0 + start_time.tv_usec;
-+ }
-+ }
-+
- if (!(stmt= find_prepared_statement(thd, stmt_id)))
- {
- char llbuf[22];
- my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), static_cast<int>(sizeof(llbuf)),
- llstr(stmt_id, llbuf), "mysqld_stmt_execute");
-- DBUG_VOID_RETURN;
-+ goto end;
- }
-
- #if defined(ENABLED_PROFILING)
-@@ -2563,6 +2665,53 @@
- /* Close connection socket; for use with client testing (Bug#43560). */
- DBUG_EXECUTE_IF("close_conn_after_stmt_execute", vio_close(thd->net.vio););
-
-+end:
-+ if (opt_userstat)
-+ {
-+ // Gets the end time.
-+ if (!(end_time_error= gettimeofday(&end_time, NULL)))
-+ {
-+ end_usecs= end_time.tv_sec * 1000000.0 + end_time.tv_usec;
-+ }
-+
-+ // Calculates the difference between the end and start times.
-+ if (start_usecs && end_usecs >= start_usecs && !start_time_error && !end_time_error)
-+ {
-+ thd->busy_time= (end_usecs - start_usecs) / 1000000;
-+ // In case there are bad values, 2629743 is the #seconds in a month.
-+ if (thd->busy_time > 2629743)
-+ {
-+ thd->busy_time= 0;
-+ }
-+ }
-+ else
-+ {
-+ // end time went back in time, or gettimeofday() failed.
-+ thd->busy_time= 0;
-+ }
-+
-+#ifdef HAVE_CLOCK_GETTIME
-+ /* get end cputime */
-+ if (!cputime_error &&
-+ !(cputime_error= clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)))
-+ end_cpu_nsecs= tp.tv_sec*1000000000.0+tp.tv_nsec;
-+#endif
-+ if (start_cpu_nsecs && !cputime_error)
-+ {
-+ thd->cpu_time= (end_cpu_nsecs - start_cpu_nsecs) / 1000000000;
-+ // In case there are bad values, 2629743 is the #seconds in a month.
-+ if (thd->cpu_time > 2629743)
-+ {
-+ thd->cpu_time= 0;
-+ }
-+ }
-+ else
-+ thd->cpu_time = 0;
-+ }
-+ // Updates THD stats and the global user stats.
-+ thd->update_stats(true);
-+ update_global_user_stats(thd, true, time(NULL));
-+
- DBUG_VOID_RETURN;
- }
-
-@@ -2635,20 +2784,47 @@
-
- /* First of all clear possible warnings from the previous command */
- mysql_reset_thd_for_next_command(thd);
-+
-+ int start_time_error= 0;
-+ int end_time_error= 0;
-+ struct timeval start_time, end_time;
-+ double start_usecs= 0;
-+ double end_usecs= 0;
-+ /* cpu time */
-+ int cputime_error= 0;
-+ struct timespec tp;
-+ double start_cpu_nsecs= 0;
-+ double end_cpu_nsecs= 0;
-+
-+ if (opt_userstat)
-+ {
-+#ifdef HAVE_CLOCK_GETTIME
-+ /* get start cputime */
-+ if (!(cputime_error= clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)))
-+ start_cpu_nsecs= tp.tv_sec*1000000000.0+tp.tv_nsec;
-+#endif
-+
-+ // Gets the start time, in order to measure how long this command takes.
-+ if (!(start_time_error= gettimeofday(&start_time, NULL)))
-+ {
-+ start_usecs= start_time.tv_sec * 1000000.0 + start_time.tv_usec;
-+ }
-+ }
-+
- status_var_increment(thd->status_var.com_stmt_fetch);
- if (!(stmt= find_prepared_statement(thd, stmt_id)))
- {
- char llbuf[22];
- my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), static_cast<int>(sizeof(llbuf)),
- llstr(stmt_id, llbuf), "mysqld_stmt_fetch");
-- DBUG_VOID_RETURN;
-+ goto end;
- }
-
- cursor= stmt->cursor;
- if (!cursor)
- {
- my_error(ER_STMT_HAS_NO_OPEN_CURSOR, MYF(0), stmt_id);
-- DBUG_VOID_RETURN;
-+ goto end;
- }
-
- thd->stmt_arena= stmt;
-@@ -2665,6 +2841,52 @@
- thd->restore_backup_statement(stmt, &stmt_backup);
- thd->stmt_arena= thd;
-
-+end:
-+ if (opt_userstat)
-+ {
-+ // Gets the end time.
-+ if (!(end_time_error = gettimeofday(&end_time, NULL)))
-+ {
-+ end_usecs = end_time.tv_sec * 1000000.0 + end_time.tv_usec;
-+ }
-+
-+ // Calculates the difference between the end and start times.
-+ if (start_usecs && end_usecs >= start_usecs && !start_time_error && !end_time_error)
-+ {
-+ thd->busy_time= (end_usecs - start_usecs) / 1000000;
-+ // In case there are bad values, 2629743 is the #seconds in a month.
-+ if (thd->busy_time > 2629743)
-+ {
-+ thd->busy_time= 0;
-+ }
-+ }
-+ else
-+ {
-+ // end time went back in time, or gettimeofday() failed.
-+ thd->busy_time= 0;
-+ }
-+
-+#ifdef HAVE_CLOCK_GETTIME
-+ /* get end cputime */
-+ if (!cputime_error &&
-+ !(cputime_error= clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)))
-+ end_cpu_nsecs= tp.tv_sec*1000000000.0+tp.tv_nsec;
-+#endif
-+ if (start_cpu_nsecs && !cputime_error)
-+ {
-+ thd->cpu_time= (end_cpu_nsecs - start_cpu_nsecs) / 1000000000;
-+ // In case there are bad values, 2629743 is the #seconds in a month.
-+ if (thd->cpu_time > 2629743)
-+ {
-+ thd->cpu_time= 0;
-+ }
-+ } else
-+ thd->cpu_time= 0;
-+ }
-+ // Updates THD stats and the global user stats.
-+ thd->update_stats(true);
-+ update_global_user_stats(thd, true, time(NULL));
-+
- DBUG_VOID_RETURN;
- }
-
-@@ -2695,13 +2917,39 @@
- /* First of all clear possible warnings from the previous command */
- mysql_reset_thd_for_next_command(thd);
-
-+ int start_time_error= 0;
-+ int end_time_error= 0;
-+ struct timeval start_time, end_time;
-+ double start_usecs= 0;
-+ double end_usecs= 0;
-+ /* cpu time */
-+ int cputime_error= 0;
-+ struct timespec tp;
-+ double start_cpu_nsecs= 0;
-+ double end_cpu_nsecs= 0;
-+
-+ if (opt_userstat)
-+ {
-+#ifdef HAVE_CLOCK_GETTIME
-+ /* get start cputime */
-+ if (!(cputime_error= clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)))
-+ start_cpu_nsecs= tp.tv_sec * 1000000000.0+tp.tv_nsec;
-+#endif
-+
-+ // Gets the start time, in order to measure how long this command takes.
-+ if (!(start_time_error= gettimeofday(&start_time, NULL)))
-+ {
-+ start_usecs= start_time.tv_sec * 1000000.0 + start_time.tv_usec;
-+ }
-+ }
-+
- status_var_increment(thd->status_var.com_stmt_reset);
- if (!(stmt= find_prepared_statement(thd, stmt_id)))
- {
- char llbuf[22];
- my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), static_cast<int>(sizeof(llbuf)),
- llstr(stmt_id, llbuf), "mysqld_stmt_reset");
-- DBUG_VOID_RETURN;
-+ goto end;
- }
-
- stmt->close_cursor();
-@@ -2718,6 +2966,53 @@
-
- my_ok(thd);
-
-+end:
-+ if (opt_userstat)
-+ {
-+ // Gets the end time.
-+ if (!(end_time_error = gettimeofday(&end_time, NULL)))
-+ {
-+ end_usecs = end_time.tv_sec * 1000000.0 + end_time.tv_usec;
-+ }
-+
-+ // Calculates the difference between the end and start times.
-+ if (start_usecs && end_usecs >= start_usecs && !start_time_error && !end_time_error)
-+ {
-+ thd->busy_time= (end_usecs - start_usecs) / 1000000;
-+ // In case there are bad values, 2629743 is the #seconds in a month.
-+ if (thd->busy_time > 2629743)
-+ {
-+ thd->busy_time= 0;
-+ }
-+ }
-+ else
-+ {
-+ // end time went back in time, or gettimeofday() failed.
-+ thd->busy_time= 0;
-+ }
-+
-+#ifdef HAVE_CLOCK_GETTIME
-+ /* get end cputime */
-+ if (!cputime_error &&
-+ !(cputime_error = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)))
-+ end_cpu_nsecs = tp.tv_sec*1000000000.0+tp.tv_nsec;
-+#endif
-+ if (start_cpu_nsecs && !cputime_error)
-+ {
-+ thd->cpu_time = (end_cpu_nsecs - start_cpu_nsecs) / 1000000000;
-+ // In case there are bad values, 2629743 is the #seconds in a month.
-+ if (thd->cpu_time > 2629743)
-+ {
-+ thd->cpu_time= 0;
-+ }
-+ }
-+ else
-+ thd->cpu_time= 0;
-+ }
-+ // Updates THD stats and the global user stats.
-+ thd->update_stats(true);
-+ update_global_user_stats(thd, true, time(NULL));
-+
- DBUG_VOID_RETURN;
- }
-
---- a/sql/sql_reload.cc
-+++ b/sql/sql_reload.cc
-@@ -320,14 +320,48 @@
- mysql_mutex_unlock(&LOCK_active_mi);
- }
- #endif
-- if (options & REFRESH_USER_RESOURCES)
-- reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */
- #ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
- if (options & REFRESH_QUERY_RESPONSE_TIME)
- {
- query_response_time_flush();
- }
- #endif // HAVE_RESPONSE_TIME_DISTRIBUTION
-+ if (options & REFRESH_USER_RESOURCES)
-+ reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */
-+ if (options & REFRESH_TABLE_STATS)
-+ {
-+ mysql_mutex_lock(&LOCK_global_table_stats);
-+ free_global_table_stats();
-+ init_global_table_stats();
-+ mysql_mutex_unlock(&LOCK_global_table_stats);
-+ }
-+ if (options & REFRESH_INDEX_STATS)
-+ {
-+ mysql_mutex_lock(&LOCK_global_index_stats);
-+ free_global_index_stats();
-+ init_global_index_stats();
-+ mysql_mutex_unlock(&LOCK_global_index_stats);
-+ }
-+ if (options & (REFRESH_USER_STATS | REFRESH_CLIENT_STATS | REFRESH_THREAD_STATS))
-+ {
-+ mysql_mutex_lock(&LOCK_global_user_client_stats);
-+ if (options & REFRESH_USER_STATS)
-+ {
-+ free_global_user_stats();
-+ init_global_user_stats();
-+ }
-+ if (options & REFRESH_CLIENT_STATS)
-+ {
-+ free_global_client_stats();
-+ init_global_client_stats();
-+ }
-+ if (options & REFRESH_THREAD_STATS)
-+ {
-+ free_global_thread_stats();
-+ init_global_thread_stats();
-+ }
-+ mysql_mutex_unlock(&LOCK_global_user_client_stats);
-+ }
- if (*write_to_binlog != -1)
- *write_to_binlog= tmp_write_to_binlog;
- /*
---- a/sql/sql_show.cc
-+++ b/sql/sql_show.cc
-@@ -114,6 +114,43 @@
-
- static COND * make_cond_for_info_schema(COND *cond, TABLE_LIST *table);
-
-+/*
-+ * Solaris 10 does not have strsep().
-+ *
-+ * based on getToken from http://www.winehq.org/pipermail/wine-patches/2001-November/001322.html
-+ *
-+*/
-+
-+#ifndef HAVE_STRSEP
-+static char* strsep(char** str, const char* delims)
-+{
-+ char *token;
-+
-+ if (*str == NULL)
-+ {
-+ /* No more tokens */
-+ return NULL;
-+ }
-+
-+ token= *str;
-+ while (**str != '\0')
-+ {
-+ if (strchr(delims, **str) != NULL)
-+ {
-+ **str= '\0';
-+ (*str)++;
-+ return token;
-+ }
-+ (*str)++;
-+ }
-+
-+ /* There is not another token */
-+ *str= NULL;
-+
-+ return token;
-+}
-+#endif
-+
- /***************************************************************************
- ** List all table types supported
- ***************************************************************************/
-@@ -800,6 +837,7 @@
- sctx->master_access);
- if (!(db_access & DB_ACLS) && check_grant_db(thd,dbname))
- {
-+ thd->diff_access_denied_errors++;
- my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
- sctx->priv_user, sctx->host_or_ip, dbname);
- general_log_print(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
-@@ -2359,6 +2397,284 @@
- DBUG_RETURN(res);
- }
-
-+/*
-+ Write result to network for SHOW USER_STATISTICS
-+
-+ SYNOPSIS
-+ send_user_stats
-+ all_user_stats - values to return
-+ table - I_S table
-+
-+ RETURN
-+ 0 - OK
-+ 1 - error
-+*/
-+int send_user_stats(THD* thd, HASH *all_user_stats, TABLE *table)
-+{
-+ DBUG_ENTER("send_user_stats");
-+ for (uint i = 0; i < all_user_stats->records; ++i)
-+ {
-+ restore_record(table, s->default_values);
-+ USER_STATS *user_stats = (USER_STATS *) my_hash_element(all_user_stats, i);
-+ table->field[0]->store(user_stats->user, strlen(user_stats->user), system_charset_info);
-+ table->field[1]->store((longlong)user_stats->total_connections);
-+ table->field[2]->store((longlong)user_stats->concurrent_connections);
-+ table->field[3]->store((longlong)user_stats->connected_time);
-+ table->field[4]->store((longlong)user_stats->busy_time);
-+ table->field[5]->store((longlong)user_stats->cpu_time);
-+ table->field[6]->store((longlong)user_stats->bytes_received);
-+ table->field[7]->store((longlong)user_stats->bytes_sent);
-+ table->field[8]->store((longlong)user_stats->binlog_bytes_written);
-+ table->field[9]->store((longlong)user_stats->rows_fetched);
-+ table->field[10]->store((longlong)user_stats->rows_updated);
-+ table->field[11]->store((longlong)user_stats->rows_read);
-+ table->field[12]->store((longlong)user_stats->select_commands);
-+ table->field[13]->store((longlong)user_stats->update_commands);
-+ table->field[14]->store((longlong)user_stats->other_commands);
-+ table->field[15]->store((longlong)user_stats->commit_trans);
-+ table->field[16]->store((longlong)user_stats->rollback_trans);
-+ table->field[17]->store((longlong)user_stats->denied_connections);
-+ table->field[18]->store((longlong)user_stats->lost_connections);
-+ table->field[19]->store((longlong)user_stats->access_denied_errors);
-+ table->field[20]->store((longlong)user_stats->empty_queries);
-+ if (schema_table_store_record(thd, table))
-+ {
-+ DBUG_PRINT("error", ("store record error"));
-+ DBUG_RETURN(1);
-+ }
-+ }
-+ DBUG_RETURN(0);
-+}
-+
-+int send_thread_stats(THD* thd, HASH *all_thread_stats, TABLE *table)
-+{
-+ DBUG_ENTER("send_thread_stats");
-+ for (uint i = 0; i < all_thread_stats->records; ++i)
-+ {
-+ restore_record(table, s->default_values);
-+ THREAD_STATS *user_stats = (THREAD_STATS *) my_hash_element(all_thread_stats, i);
-+ table->field[0]->store((longlong)user_stats->id);
-+ table->field[1]->store((longlong)user_stats->total_connections);
-+ table->field[2]->store((longlong)user_stats->concurrent_connections);
-+ table->field[3]->store((longlong)user_stats->connected_time);
-+ table->field[4]->store((longlong)user_stats->busy_time);
-+ table->field[5]->store((longlong)user_stats->cpu_time);
-+ table->field[6]->store((longlong)user_stats->bytes_received);
-+ table->field[7]->store((longlong)user_stats->bytes_sent);
-+ table->field[8]->store((longlong)user_stats->binlog_bytes_written);
-+ table->field[9]->store((longlong)user_stats->rows_fetched);
-+ table->field[10]->store((longlong)user_stats->rows_updated);
-+ table->field[11]->store((longlong)user_stats->rows_read);
-+ table->field[12]->store((longlong)user_stats->select_commands);
-+ table->field[13]->store((longlong)user_stats->update_commands);
-+ table->field[14]->store((longlong)user_stats->other_commands);
-+ table->field[15]->store((longlong)user_stats->commit_trans);
-+ table->field[16]->store((longlong)user_stats->rollback_trans);
-+ table->field[17]->store((longlong)user_stats->denied_connections);
-+ table->field[18]->store((longlong)user_stats->lost_connections);
-+ table->field[19]->store((longlong)user_stats->access_denied_errors);
-+ table->field[20]->store((longlong)user_stats->empty_queries);
-+ if (schema_table_store_record(thd, table))
-+ {
-+ DBUG_PRINT("error", ("store record error"));
-+ DBUG_RETURN(1);
-+ }
-+ }
-+ DBUG_RETURN(0);
-+}
-+
-+/*
-+ Process SHOW USER_STATISTICS
-+
-+ SYNOPSIS
-+ mysqld_show_user_stats
-+ thd - current thread
-+ wild - limit results to the entry for this user
-+ with_roles - when true, display role for mapped users
-+
-+ RETURN
-+ 0 - OK
-+ 1 - error
-+*/
-+
-+
-+int fill_schema_user_stats(THD* thd, TABLE_LIST* tables, COND* cond)
-+{
-+ TABLE *table= tables->table;
-+ DBUG_ENTER("fill_schema_user_stats");
-+
-+ if (check_global_access(thd, SUPER_ACL | PROCESS_ACL))
-+ DBUG_RETURN(1);
-+
-+ // Iterates through all the global stats and sends them to the client.
-+ // Pattern matching on the client IP is supported.
-+
-+ mysql_mutex_lock(&LOCK_global_user_client_stats);
-+ int result= send_user_stats(thd, &global_user_stats, table);
-+ mysql_mutex_unlock(&LOCK_global_user_client_stats);
-+ if (result)
-+ goto err;
-+
-+ DBUG_PRINT("exit", ("fill_schema_user_stats result is 0"));
-+ DBUG_RETURN(0);
-+
-+ err:
-+ DBUG_PRINT("exit", ("fill_schema_user_stats result is 1"));
-+ DBUG_RETURN(1);
-+}
-+
-+/*
-+ Process SHOW CLIENT_STATISTICS
-+
-+ SYNOPSIS
-+ mysqld_show_client_stats
-+ thd - current thread
-+ wild - limit results to the entry for this client
-+
-+ RETURN
-+ 0 - OK
-+ 1 - error
-+*/
-+
-+
-+int fill_schema_client_stats(THD* thd, TABLE_LIST* tables, COND* cond)
-+{
-+ TABLE *table= tables->table;
-+ DBUG_ENTER("fill_schema_client_stats");
-+
-+ if (check_global_access(thd, SUPER_ACL | PROCESS_ACL))
-+ DBUG_RETURN(1);
-+
-+ // Iterates through all the global stats and sends them to the client.
-+ // Pattern matching on the client IP is supported.
-+
-+ mysql_mutex_lock(&LOCK_global_user_client_stats);
-+ int result= send_user_stats(thd, &global_client_stats, table);
-+ mysql_mutex_unlock(&LOCK_global_user_client_stats);
-+ if (result)
-+ goto err;
-+
-+ DBUG_PRINT("exit", ("mysqld_show_client_stats result is 0"));
-+ DBUG_RETURN(0);
-+
-+ err:
-+ DBUG_PRINT("exit", ("mysqld_show_client_stats result is 1"));
-+ DBUG_RETURN(1);
-+}
-+
-+int fill_schema_thread_stats(THD* thd, TABLE_LIST* tables, COND* cond)
-+{
-+ TABLE *table= tables->table;
-+ DBUG_ENTER("fill_schema_thread_stats");
-+
-+ if (check_global_access(thd, SUPER_ACL | PROCESS_ACL))
-+ DBUG_RETURN(1);
-+
-+ // Iterates through all the global stats and sends them to the client.
-+ // Pattern matching on the client IP is supported.
-+
-+ mysql_mutex_lock(&LOCK_global_user_client_stats);
-+ int result= send_thread_stats(thd, &global_thread_stats, table);
-+ mysql_mutex_unlock(&LOCK_global_user_client_stats);
-+ if (result)
-+ goto err;
-+
-+ DBUG_PRINT("exit", ("mysqld_show_thread_stats result is 0"));
-+ DBUG_RETURN(0);
-+
-+ err:
-+ DBUG_PRINT("exit", ("mysqld_show_thread_stats result is 1"));
-+ DBUG_RETURN(1);
-+}
-+
-+// Sends the global table stats back to the client.
-+int fill_schema_table_stats(THD* thd, TABLE_LIST* tables, COND* cond)
-+{
-+ TABLE *table= tables->table;
-+ DBUG_ENTER("fill_schema_table_stats");
-+ char *table_full_name, *table_schema;
-+
-+ mysql_mutex_lock(&LOCK_global_table_stats);
-+ for (uint i = 0; i < global_table_stats.records; ++i)
-+ {
-+ restore_record(table, s->default_values);
-+ TABLE_STATS *table_stats =
-+ (TABLE_STATS *) my_hash_element(&global_table_stats, i);
-+
-+ table_full_name= thd->strdup(table_stats->table);
-+ table_schema= strsep(&table_full_name, ".");
-+
-+ TABLE_LIST tmp_table;
-+ bzero((char *) &tmp_table,sizeof(tmp_table));
-+ tmp_table.table_name= table_full_name;
-+ tmp_table.db= table_schema;
-+ tmp_table.grant.privilege= 0;
-+ if (check_access(thd, SELECT_ACL, tmp_table.db,
-+ &tmp_table.grant.privilege, 0, 0,
-+ is_infoschema_db(table_schema)) ||
-+ check_grant(thd, SELECT_ACL, &tmp_table, 1, UINT_MAX, 1))
-+ continue;
-+
-+ table->field[0]->store(table_schema, strlen(table_schema), system_charset_info);
-+ table->field[1]->store(table_full_name, strlen(table_full_name), system_charset_info);
-+ table->field[2]->store((longlong)table_stats->rows_read, TRUE);
-+ table->field[3]->store((longlong)table_stats->rows_changed, TRUE);
-+ table->field[4]->store((longlong)table_stats->rows_changed_x_indexes, TRUE);
-+
-+ if (schema_table_store_record(thd, table))
-+ {
-+ mysql_mutex_unlock(&LOCK_global_table_stats);
-+ DBUG_RETURN(1);
-+ }
-+ }
-+ mysql_mutex_unlock(&LOCK_global_table_stats);
-+ DBUG_RETURN(0);
-+}
-+
-+// Sends the global index stats back to the client.
-+int fill_schema_index_stats(THD* thd, TABLE_LIST* tables, COND* cond)
-+{
-+ TABLE *table= tables->table;
-+ DBUG_ENTER("fill_schema_index_stats");
-+ char *index_full_name, *table_schema, *table_name;
-+
-+ mysql_mutex_lock(&LOCK_global_index_stats);
-+ for (uint i = 0; i < global_index_stats.records; ++i)
-+ {
-+ restore_record(table, s->default_values);
-+ INDEX_STATS *index_stats =
-+ (INDEX_STATS *) my_hash_element(&global_index_stats, i);
-+
-+ index_full_name= thd->strdup(index_stats->index);
-+ table_schema= strsep(&index_full_name, ".");
-+ table_name= strsep(&index_full_name, ".");
-+
-+ TABLE_LIST tmp_table;
-+ bzero((char *) &tmp_table,sizeof(tmp_table));
-+ tmp_table.table_name= table_name;
-+ tmp_table.db= table_schema;
-+ tmp_table.grant.privilege= 0;
-+ if (check_access(thd, SELECT_ACL, tmp_table.db,
-+ &tmp_table.grant.privilege, 0, 0,
-+ is_infoschema_db(table_schema)) ||
-+ check_grant(thd, SELECT_ACL, &tmp_table, 1, UINT_MAX, 1))
-+ continue;
-+
-+ table->field[0]->store(table_schema, strlen(table_schema), system_charset_info);
-+ table->field[1]->store(table_name, strlen(table_name), system_charset_info);
-+ table->field[2]->store(index_full_name, strlen(index_full_name), system_charset_info);
-+ table->field[3]->store((longlong)index_stats->rows_read, TRUE);
-+
-+ if (schema_table_store_record(thd, table))
-+ {
-+ mysql_mutex_unlock(&LOCK_global_index_stats);
-+ DBUG_RETURN(1);
-+ }
-+ }
-+ mysql_mutex_unlock(&LOCK_global_index_stats);
-+ DBUG_RETURN(0);
-+}
-+
-
- /* collect status for all running threads */
-
-@@ -7712,6 +8028,104 @@
- };
-
-
-+ST_FIELD_INFO user_stats_fields_info[]=
-+{
-+ {"USER", USERNAME_LENGTH, MYSQL_TYPE_STRING, 0, 0, "User", SKIP_OPEN_TABLE},
-+ {"TOTAL_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Total_connections", SKIP_OPEN_TABLE},
-+ {"CONCURRENT_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Concurrent_connections", SKIP_OPEN_TABLE},
-+ {"CONNECTED_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Connected_time", SKIP_OPEN_TABLE},
-+ {"BUSY_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Busy_time", SKIP_OPEN_TABLE},
-+ {"CPU_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Cpu_time", SKIP_OPEN_TABLE},
-+ {"BYTES_RECEIVED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Bytes_received", SKIP_OPEN_TABLE},
-+ {"BYTES_SENT", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Bytes_sent", SKIP_OPEN_TABLE},
-+ {"BINLOG_BYTES_WRITTEN", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Binlog_bytes_written", SKIP_OPEN_TABLE},
-+ {"ROWS_FETCHED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_fetched", SKIP_OPEN_TABLE},
-+ {"ROWS_UPDATED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_updated", SKIP_OPEN_TABLE},
-+ {"TABLE_ROWS_READ", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Table_rows_read", SKIP_OPEN_TABLE},
-+ {"SELECT_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Select_commands", SKIP_OPEN_TABLE},
-+ {"UPDATE_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Update_commands", SKIP_OPEN_TABLE},
-+ {"OTHER_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Other_commands", SKIP_OPEN_TABLE},
-+ {"COMMIT_TRANSACTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Commit_transactions", SKIP_OPEN_TABLE},
-+ {"ROLLBACK_TRANSACTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rollback_transactions", SKIP_OPEN_TABLE},
-+ {"DENIED_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Denied_connections", SKIP_OPEN_TABLE},
-+ {"LOST_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Lost_connections", SKIP_OPEN_TABLE},
-+ {"ACCESS_DENIED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Access_denied", SKIP_OPEN_TABLE},
-+ {"EMPTY_QUERIES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Empty_queries", SKIP_OPEN_TABLE},
-+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0}
-+};
-+
-+ST_FIELD_INFO client_stats_fields_info[]=
-+{
-+ {"CLIENT", LIST_PROCESS_HOST_LEN, MYSQL_TYPE_STRING, 0, 0, "Client", SKIP_OPEN_TABLE},
-+ {"TOTAL_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Total_connections", SKIP_OPEN_TABLE},
-+ {"CONCURRENT_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Concurrent_connections", SKIP_OPEN_TABLE},
-+ {"CONNECTED_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Connected_time", SKIP_OPEN_TABLE},
-+ {"BUSY_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Busy_time", SKIP_OPEN_TABLE},
-+ {"CPU_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Cpu_time", SKIP_OPEN_TABLE},
-+ {"BYTES_RECEIVED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Bytes_received", SKIP_OPEN_TABLE},
-+ {"BYTES_SENT", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Bytes_sent", SKIP_OPEN_TABLE},
-+ {"BINLOG_BYTES_WRITTEN", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Binlog_bytes_written", SKIP_OPEN_TABLE},
-+ {"ROWS_FETCHED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_fetched", SKIP_OPEN_TABLE},
-+ {"ROWS_UPDATED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_updated", SKIP_OPEN_TABLE},
-+ {"TABLE_ROWS_READ", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Table_rows_read", SKIP_OPEN_TABLE},
-+ {"SELECT_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Select_commands", SKIP_OPEN_TABLE},
-+ {"UPDATE_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Update_commands", SKIP_OPEN_TABLE},
-+ {"OTHER_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Other_commands", SKIP_OPEN_TABLE},
-+ {"COMMIT_TRANSACTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Commit_transactions", SKIP_OPEN_TABLE},
-+ {"ROLLBACK_TRANSACTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rollback_transactions", SKIP_OPEN_TABLE},
-+ {"DENIED_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Denied_connections", SKIP_OPEN_TABLE},
-+ {"LOST_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Lost_connections", SKIP_OPEN_TABLE},
-+ {"ACCESS_DENIED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Access_denied", SKIP_OPEN_TABLE},
-+ {"EMPTY_QUERIES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Empty_queries", SKIP_OPEN_TABLE},
-+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0}
-+};
-+
-+ST_FIELD_INFO thread_stats_fields_info[]=
-+{
-+ {"THREAD_ID", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Thread_id", SKIP_OPEN_TABLE},
-+ {"TOTAL_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Total_connections", SKIP_OPEN_TABLE},
-+ {"CONCURRENT_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Concurrent_connections", SKIP_OPEN_TABLE},
-+ {"CONNECTED_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Connected_time", SKIP_OPEN_TABLE},
-+ {"BUSY_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Busy_time", SKIP_OPEN_TABLE},
-+ {"CPU_TIME", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Cpu_time", SKIP_OPEN_TABLE},
-+ {"BYTES_RECEIVED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Bytes_received", SKIP_OPEN_TABLE},
-+ {"BYTES_SENT", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Bytes_sent", SKIP_OPEN_TABLE},
-+ {"BINLOG_BYTES_WRITTEN", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Binlog_bytes_written", SKIP_OPEN_TABLE},
-+ {"ROWS_FETCHED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_fetched", SKIP_OPEN_TABLE},
-+ {"ROWS_UPDATED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_updated", SKIP_OPEN_TABLE},
-+ {"TABLE_ROWS_READ", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Table_rows_read", SKIP_OPEN_TABLE},
-+ {"SELECT_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Select_commands", SKIP_OPEN_TABLE},
-+ {"UPDATE_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Update_commands", SKIP_OPEN_TABLE},
-+ {"OTHER_COMMANDS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Other_commands", SKIP_OPEN_TABLE},
-+ {"COMMIT_TRANSACTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Commit_transactions", SKIP_OPEN_TABLE},
-+ {"ROLLBACK_TRANSACTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rollback_transactions", SKIP_OPEN_TABLE},
-+ {"DENIED_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Denied_connections", SKIP_OPEN_TABLE},
-+ {"LOST_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Lost_connections", SKIP_OPEN_TABLE},
-+ {"ACCESS_DENIED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Access_denied", SKIP_OPEN_TABLE},
-+ {"EMPTY_QUERIES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Empty_queries", SKIP_OPEN_TABLE},
-+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0}
-+};
-+
-+ST_FIELD_INFO table_stats_fields_info[]=
-+{
-+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_schema", SKIP_OPEN_TABLE},
-+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_name", SKIP_OPEN_TABLE},
-+ {"ROWS_READ", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_read", SKIP_OPEN_TABLE},
-+ {"ROWS_CHANGED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_changed", SKIP_OPEN_TABLE},
-+ {"ROWS_CHANGED_X_INDEXES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_changed_x_#indexes", SKIP_OPEN_TABLE},
-+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0}
-+};
-+
-+ST_FIELD_INFO index_stats_fields_info[]=
-+{
-+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_schema", SKIP_OPEN_TABLE},
-+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_name", SKIP_OPEN_TABLE},
-+ {"INDEX_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Index_name", SKIP_OPEN_TABLE},
-+ {"ROWS_READ", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, "Rows_read", SKIP_OPEN_TABLE},
-+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0}
-+};
-+
-+
- ST_FIELD_INFO processlist_fields_info[]=
- {
- {"ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Id", SKIP_OPEN_TABLE},
-@@ -7901,6 +8315,8 @@
- {
- {"CHARACTER_SETS", charsets_fields_info, create_schema_table,
- fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0, 0},
-+ {"CLIENT_STATISTICS", client_stats_fields_info, create_schema_table,
-+ fill_schema_client_stats, make_old_format, 0, -1, -1, 0, 0},
- {"COLLATIONS", collation_fields_info, create_schema_table,
- fill_schema_collation, make_old_format, 0, -1, -1, 0, 0},
- {"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info,
-@@ -7910,6 +8326,8 @@
- OPTIMIZE_I_S_TABLE|OPEN_VIEW_FULL},
- {"COLUMN_PRIVILEGES", column_privileges_fields_info, create_schema_table,
- fill_schema_column_privileges, 0, 0, -1, -1, 0, 0},
-+ {"INDEX_STATISTICS", index_stats_fields_info, create_schema_table,
-+ fill_schema_index_stats, make_old_format, 0, -1, -1, 0, 0},
- {"ENGINES", engines_fields_info, create_schema_table,
- fill_schema_engines, make_old_format, 0, -1, -1, 0, 0},
- #ifdef HAVE_EVENT_SCHEDULER
-@@ -7982,14 +8400,20 @@
- get_all_tables, make_table_names_old_format, 0, 1, 2, 1, 0},
- {"TABLE_PRIVILEGES", table_privileges_fields_info, create_schema_table,
- fill_schema_table_privileges, 0, 0, -1, -1, 0, 0},
-+ {"TABLE_STATISTICS", table_stats_fields_info, create_schema_table,
-+ fill_schema_table_stats, make_old_format, 0, -1, -1, 0, 0},
- {"TEMPORARY_TABLES", temporary_table_fields_info, create_schema_table,
- fill_temporary_tables, make_temporary_tables_old_format, 0, 2, 3, 0,
- OPEN_TABLE_ONLY|OPTIMIZE_I_S_TABLE},
-+ {"THREAD_STATISTICS", thread_stats_fields_info, create_schema_table,
-+ fill_schema_thread_stats, make_old_format, 0, -1, -1, 0, 0},
- {"TRIGGERS", triggers_fields_info, create_schema_table,
- get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0,
- OPEN_TRIGGER_ONLY|OPTIMIZE_I_S_TABLE},
- {"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table,
- fill_schema_user_privileges, 0, 0, -1, -1, 0, 0},
-+ {"USER_STATISTICS", user_stats_fields_info, create_schema_table,
-+ fill_schema_user_stats, make_old_format, 0, -1, -1, 0, 0},
- {"VARIABLES", variables_fields_info, create_schema_table, fill_variables,
- make_old_format, 0, 0, -1, 1, 0},
- {"VIEWS", view_fields_info, create_schema_table,
---- a/sql/sql_update.cc
-+++ b/sql/sql_update.cc
-@@ -900,8 +900,10 @@
- my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found,
- (ulong) updated,
- (ulong) thd->warning_info->statement_warn_count());
-- my_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
-- id, buff);
-+ ha_rows row_count=
-+ (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
-+ my_ok(thd, row_count, id, buff);
-+ thd->updated_row_count += row_count;
- DBUG_PRINT("info",("%ld records updated", (long) updated));
- }
- thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */
-@@ -2252,7 +2254,9 @@
- thd->first_successful_insert_id_in_prev_stmt : 0;
- my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO),
- (ulong) found, (ulong) updated, (ulong) thd->cuted_fields);
-- ::my_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
-- id, buff);
-+ ha_rows row_count=
-+ (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
-+ ::my_ok(thd, row_count, id, buff);
-+ thd->updated_row_count+= row_count;
- DBUG_RETURN(FALSE);
- }
---- a/sql/sql_yacc.yy
-+++ b/sql/sql_yacc.yy
-@@ -865,6 +865,7 @@
- %token CIPHER_SYM
- %token CLASS_ORIGIN_SYM /* SQL-2003-N */
- %token CLIENT_SYM
-+%token CLIENT_STATS_SYM
- %token CLOSE_SYM /* SQL-2003-R */
- %token COALESCE /* SQL-2003-N */
- %token CODE_SYM
-@@ -1018,6 +1019,7 @@
- %token IMPORT
- %token INDEXES
- %token INDEX_SYM
-+%token INDEX_STATS_SYM
- %token INFILE
- %token INITIAL_SIZE_SYM
- %token INNER_SYM /* SQL-2003-R */
-@@ -1316,6 +1318,7 @@
- %token TABLESPACE
- %token TABLE_REF_PRIORITY
- %token TABLE_SYM /* SQL-2003-R */
-+%token TABLE_STATS_SYM
- %token TABLE_CHECKSUM_SYM
- %token TABLE_NAME_SYM /* SQL-2003-N */
- %token TEMPORARY /* SQL-2003-N */
-@@ -1325,6 +1328,7 @@
- %token TEXT_SYM
- %token THAN_SYM
- %token THEN_SYM /* SQL-2003-R */
-+%token THREAD_STATS_SYM
- %token TIMESTAMP /* SQL-2003-R */
- %token TIMESTAMP_ADD
- %token TIMESTAMP_DIFF
-@@ -1362,6 +1366,7 @@
- %token UPGRADE_SYM
- %token USAGE /* SQL-2003-N */
- %token USER /* SQL-2003-R */
-+%token USER_STATS_SYM
- %token USE_FRM
- %token USE_SYM
- %token USING /* SQL-2003-R */
-@@ -11126,6 +11131,41 @@
- MYSQL_YYABORT;
- #endif // HAVE_RESPONSE_TIME_DISTRIBUTION
- }
-+ | CLIENT_STATS_SYM wild_and_where
-+ {
-+ LEX *lex= Lex;
-+ Lex->sql_command= SQLCOM_SELECT;
-+ if (prepare_schema_table(YYTHD, lex, 0, SCH_CLIENT_STATS))
-+ MYSQL_YYABORT;
-+ }
-+ | USER_STATS_SYM wild_and_where
-+ {
-+ LEX *lex= Lex;
-+ lex->sql_command= SQLCOM_SELECT;
-+ if (prepare_schema_table(YYTHD, lex, 0, SCH_USER_STATS))
-+ MYSQL_YYABORT;
-+ }
-+ | THREAD_STATS_SYM wild_and_where
-+ {
-+ LEX *lex= Lex;
-+ Lex->sql_command= SQLCOM_SELECT;
-+ if (prepare_schema_table(YYTHD, lex, 0, SCH_THREAD_STATS))
-+ MYSQL_YYABORT;
-+ }
-+ | TABLE_STATS_SYM wild_and_where
-+ {
-+ LEX *lex= Lex;
-+ lex->sql_command= SQLCOM_SELECT;
-+ if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLE_STATS))
-+ MYSQL_YYABORT;
-+ }
-+ | INDEX_STATS_SYM wild_and_where
-+ {
-+ LEX *lex= Lex;
-+ lex->sql_command= SQLCOM_SELECT;
-+ if (prepare_schema_table(YYTHD, lex, 0, SCH_INDEX_STATS))
-+ MYSQL_YYABORT;
-+ }
- | CREATE PROCEDURE_SYM sp_name
- {
- LEX *lex= Lex;
-@@ -11371,6 +11411,16 @@
- Lex->type|= REFRESH_QUERY_RESPONSE_TIME;
- #endif // HAVE_RESPONSE_TIME_DISTRIBUTION
- }
-+ | CLIENT_STATS_SYM
-+ { Lex->type|= REFRESH_CLIENT_STATS; }
-+ | USER_STATS_SYM
-+ { Lex->type|= REFRESH_USER_STATS; }
-+ | THREAD_STATS_SYM
-+ { Lex->type|= REFRESH_THREAD_STATS; }
-+ | TABLE_STATS_SYM
-+ { Lex->type|= REFRESH_TABLE_STATS; }
-+ | INDEX_STATS_SYM
-+ { Lex->type|= REFRESH_INDEX_STATS; }
- | MASTER_SYM
- { Lex->type|= REFRESH_MASTER; }
- | DES_KEY_FILE
-@@ -12515,6 +12565,7 @@
- | CHAIN_SYM {}
- | CHANGED {}
- | CIPHER_SYM {}
-+ | CLIENT_STATS_SYM {}
- | CLIENT_SYM {}
- | CLASS_ORIGIN_SYM {}
- | COALESCE {}
-@@ -12583,6 +12634,7 @@
- | HOSTS_SYM {}
- | HOUR_SYM {}
- | IDENTIFIED_SYM {}
-+ | INDEX_STATS_SYM {}
- | IGNORE_SERVER_IDS_SYM {}
- | INVOKER_SYM {}
- | IMPORT {}
-@@ -12734,6 +12786,7 @@
- | SUSPEND_SYM {}
- | SWAPS_SYM {}
- | SWITCHES_SYM {}
-+ | TABLE_STATS_SYM {}
- | TABLE_NAME_SYM {}
- | TABLES {}
- | TABLE_CHECKSUM_SYM {}
-@@ -12759,6 +12812,7 @@
- | UNKNOWN_SYM {}
- | UNTIL_SYM {}
- | USER {}
-+ | USER_STATS_SYM {}
- | USE_FRM {}
- | VARIABLES {}
- | VIEW_SYM {}
---- a/sql/structs.h
-+++ b/sql/structs.h
-@@ -25,6 +25,7 @@
- #include "my_time.h" /* enum_mysql_timestamp_type */
- #include "thr_lock.h" /* thr_lock_type */
- #include "my_base.h" /* ha_rows, ha_key_alg */
-+#include "mysql_com.h"
-
- struct TABLE;
- class Field;
-@@ -218,6 +219,171 @@
- USER_RESOURCES user_resources;
- } USER_CONN;
-
-+typedef struct st_user_stats {
-+ char user[max(USERNAME_LENGTH, LIST_PROCESS_HOST_LEN) + 1];
-+ // Account name the user is mapped to when this is a user from mapped_user.
-+ // Otherwise, the same value as user.
-+ char priv_user[max(USERNAME_LENGTH, LIST_PROCESS_HOST_LEN) + 1];
-+ uint total_connections;
-+ uint concurrent_connections;
-+ time_t connected_time; // in seconds
-+ double busy_time; // in seconds
-+ double cpu_time; // in seconds
-+ ulonglong bytes_received;
-+ ulonglong bytes_sent;
-+ ulonglong binlog_bytes_written;
-+ ha_rows rows_fetched, rows_updated, rows_read;
-+ ulonglong select_commands, update_commands, other_commands;
-+ ulonglong commit_trans, rollback_trans;
-+ ulonglong denied_connections, lost_connections;
-+ ulonglong access_denied_errors;
-+ ulonglong empty_queries;
-+} USER_STATS;
-+
-+/* Lookup function for my_hash tables with USER_STATS entries */
-+extern "C" uchar *get_key_user_stats(USER_STATS *user_stats, size_t *length,
-+ my_bool not_used __attribute__((unused)));
-+
-+/* Free all memory for a my_hash table with USER_STATS entries */
-+extern void free_user_stats(USER_STATS* user_stats);
-+
-+/* Intialize an instance of USER_STATS */
-+extern void
-+init_user_stats(USER_STATS *user_stats,
-+ const char *user,
-+ const char *priv_user,
-+ uint total_connections,
-+ uint concurrent_connections,
-+ time_t connected_time,
-+ double busy_time,
-+ double cpu_time,
-+ ulonglong bytes_received,
-+ ulonglong bytes_sent,
-+ ulonglong binlog_bytes_written,
-+ ha_rows rows_fetched,
-+ ha_rows rows_updated,
-+ ha_rows rows_read,
-+ ulonglong select_commands,
-+ ulonglong update_commands,
-+ ulonglong other_commands,
-+ ulonglong commit_trans,
-+ ulonglong rollback_trans,
-+ ulonglong denied_connections,
-+ ulonglong lost_connections,
-+ ulonglong access_denied_errors,
-+ ulonglong empty_queries);
-+
-+/* Increment values of an instance of USER_STATS */
-+extern void
-+add_user_stats(USER_STATS *user_stats,
-+ uint total_connections,
-+ uint concurrent_connections,
-+ time_t connected_time,
-+ double busy_time,
-+ double cpu_time,
-+ ulonglong bytes_received,
-+ ulonglong bytes_sent,
-+ ulonglong binlog_bytes_written,
-+ ha_rows rows_fetched,
-+ ha_rows rows_updated,
-+ ha_rows rows_read,
-+ ulonglong select_commands,
-+ ulonglong update_commands,
-+ ulonglong other_commands,
-+ ulonglong commit_trans,
-+ ulonglong rollback_trans,
-+ ulonglong denied_connections,
-+ ulonglong lost_connections,
-+ ulonglong access_denied_errors,
-+ ulonglong empty_queries);
-+
-+typedef struct st_thread_stats {
-+ my_thread_id id;
-+ uint total_connections;
-+ uint concurrent_connections;
-+ time_t connected_time; // in seconds
-+ double busy_time; // in seconds
-+ double cpu_time; // in seconds
-+ ulonglong bytes_received;
-+ ulonglong bytes_sent;
-+ ulonglong binlog_bytes_written;
-+ ha_rows rows_fetched, rows_updated, rows_read;
-+ ulonglong select_commands, update_commands, other_commands;
-+ ulonglong commit_trans, rollback_trans;
-+ ulonglong denied_connections, lost_connections;
-+ ulonglong access_denied_errors;
-+ ulonglong empty_queries;
-+} THREAD_STATS;
-+
-+/* Lookup function for my_hash tables with THREAD_STATS entries */
-+extern "C" uchar *get_key_thread_stats(THREAD_STATS *thread_stats, size_t *length,
-+ my_bool not_used __attribute__((unused)));
-+
-+/* Free all memory for a my_hash table with THREAD_STATS entries */
-+extern void free_thread_stats(THREAD_STATS* thread_stats);
-+
-+/* Intialize an instance of THREAD_STATS */
-+extern void
-+init_thread_stats(THREAD_STATS *thread_stats,
-+ my_thread_id id,
-+ uint total_connections,
-+ uint concurrent_connections,
-+ time_t connected_time,
-+ double busy_time,
-+ double cpu_time,
-+ ulonglong bytes_received,
-+ ulonglong bytes_sent,
-+ ulonglong binlog_bytes_written,
-+ ha_rows rows_fetched,
-+ ha_rows rows_updated,
-+ ha_rows rows_read,
-+ ulonglong select_commands,
-+ ulonglong update_commands,
-+ ulonglong other_commands,
-+ ulonglong commit_trans,
-+ ulonglong rollback_trans,
-+ ulonglong denied_connections,
-+ ulonglong lost_connections,
-+ ulonglong access_denied_errors,
-+ ulonglong empty_queries);
-+
-+/* Increment values of an instance of THREAD_STATS */
-+extern void
-+add_thread_stats(THREAD_STATS *thread_stats,
-+ uint total_connections,
-+ uint concurrent_connections,
-+ time_t connected_time,
-+ double busy_time,
-+ double cpu_time,
-+ ulonglong bytes_received,
-+ ulonglong bytes_sent,
-+ ulonglong binlog_bytes_written,
-+ ha_rows rows_fetched,
-+ ha_rows rows_updated,
-+ ha_rows rows_read,
-+ ulonglong select_commands,
-+ ulonglong update_commands,
-+ ulonglong other_commands,
-+ ulonglong commit_trans,
-+ ulonglong rollback_trans,
-+ ulonglong denied_connections,
-+ ulonglong lost_connections,
-+ ulonglong access_denied_errors,
-+ ulonglong empty_queries);
-+
-+typedef struct st_table_stats {
-+ char table[NAME_LEN * 2 + 2]; // [db] + '.' + [table] + '\0'
-+ ulonglong rows_read, rows_changed;
-+ ulonglong rows_changed_x_indexes;
-+ /* Stores enum db_type, but forward declarations cannot be done */
-+ int engine_type;
-+} TABLE_STATS;
-+
-+typedef struct st_index_stats {
-+ char index[NAME_LEN * 3 + 3]; // [db] + '.' + [table] + '.' + [index] + '\0'
-+ ulonglong rows_read;
-+} INDEX_STATS;
-+
- /* Bits in form->update */
- #define REG_MAKE_DUPP 1 /* Make a copy of record when read */
- #define REG_NEW_RECORD 2 /* Write a new record if not found */
---- a/sql/sys_vars.cc
-+++ b/sql/sys_vars.cc
-@@ -1711,6 +1711,17 @@
- NO_MUTEX_GUARD, NOT_IN_BINLOG,
- ON_CHECK(check_read_only), ON_UPDATE(fix_read_only));
-
-+static Sys_var_mybool Sys_userstat(
-+ "userstat",
-+ "Control USER_STATISTICS, CLIENT_STATISTICS, THREAD_STATISTICS, "
-+ "INDEX_STATISTICS and TABLE_STATISTICS running",
-+ GLOBAL_VAR(opt_userstat), CMD_LINE(OPT_ARG), DEFAULT(FALSE));
-+
-+static Sys_var_mybool Sys_thread_statistics(
-+ "thread_statistics",
-+ "Control TABLE_STATISTICS running, when userstat is enabled",
-+ GLOBAL_VAR(opt_thread_statistics), CMD_LINE(OPT_ARG), DEFAULT(FALSE));
-+
- // Small lower limit to be able to test MRR
- static Sys_var_ulong Sys_read_rnd_buff_size(
- "read_rnd_buffer_size",
---- a/storage/myisam/ha_myisam.cc
-+++ b/storage/myisam/ha_myisam.cc
-@@ -770,6 +770,7 @@
-
- int ha_myisam::write_row(uchar *buf)
- {
-+ int error;
- ha_statistic_increment(&SSV::ha_write_count);
-
- /* If we have a timestamp column, update it to the current time */
-@@ -782,11 +783,13 @@
- */
- if (table->next_number_field && buf == table->record[0])
- {
-- int error;
- if ((error= update_auto_increment()))
- return error;
- }
-- return mi_write(file,buf);
-+ error=mi_write(file,buf);
-+ if (!error)
-+ rows_changed++;
-+ return error;
- }
-
- int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
-@@ -1553,16 +1556,24 @@
-
- int ha_myisam::update_row(const uchar *old_data, uchar *new_data)
- {
-+ int error;
- ha_statistic_increment(&SSV::ha_update_count);
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
- table->timestamp_field->set_time();
-- return mi_update(file,old_data,new_data);
-+ error=mi_update(file,old_data,new_data);
-+ if (!error)
-+ rows_changed++;
-+ return error;
- }
-
- int ha_myisam::delete_row(const uchar *buf)
- {
-+ int error;
- ha_statistic_increment(&SSV::ha_delete_count);
-- return mi_delete(file,buf);
-+ error=mi_delete(file,buf);
-+ if (!error)
-+ rows_changed++;
-+ return error;
- }
-
- int ha_myisam::index_read_map(uchar *buf, const uchar *key,
-@@ -1574,6 +1585,14 @@
- ha_statistic_increment(&SSV::ha_read_key_count);
- int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag);
- table->status=error ? STATUS_NOT_FOUND: 0;
-+ if (!error)
-+ {
-+ rows_read++;
-+
-+ int inx = (active_index == MAX_KEY) ? file->lastinx : active_index;
-+ if (inx >= 0 && inx < MAX_KEY)
-+ index_rows_read[inx]++;
-+ }
- MYSQL_INDEX_READ_ROW_DONE(error);
- return error;
- }
-@@ -1586,6 +1605,14 @@
- ha_statistic_increment(&SSV::ha_read_key_count);
- int error=mi_rkey(file, buf, index, key, keypart_map, find_flag);
- table->status=error ? STATUS_NOT_FOUND: 0;
-+ if (!error)
-+ {
-+ rows_read++;
-+
-+ int inx = index;
-+ if (inx >= 0 && inx < MAX_KEY)
-+ index_rows_read[inx]++;
-+ }
- MYSQL_INDEX_READ_ROW_DONE(error);
- return error;
- }
-@@ -1600,6 +1627,14 @@
- int error=mi_rkey(file, buf, active_index, key, keypart_map,
- HA_READ_PREFIX_LAST);
- table->status=error ? STATUS_NOT_FOUND: 0;
-+ if (!error)
-+ {
-+ rows_read++;
-+
-+ int inx = (active_index == MAX_KEY) ? file->lastinx : active_index;
-+ if (inx >= 0 && inx < MAX_KEY)
-+ index_rows_read[inx]++;
-+ }
- MYSQL_INDEX_READ_ROW_DONE(error);
- DBUG_RETURN(error);
- }
-@@ -1611,6 +1646,13 @@
- ha_statistic_increment(&SSV::ha_read_next_count);
- int error=mi_rnext(file,buf,active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
-+ if (!error) {
-+ rows_read++;
-+
-+ int inx = (active_index == MAX_KEY) ? file->lastinx : active_index;
-+ if (inx >= 0 && inx < MAX_KEY)
-+ index_rows_read[inx]++;
-+ }
- MYSQL_INDEX_READ_ROW_DONE(error);
- return error;
- }
-@@ -1622,6 +1664,13 @@
- ha_statistic_increment(&SSV::ha_read_prev_count);
- int error=mi_rprev(file,buf, active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
-+ if (!error) {
-+ rows_read++;
-+
-+ int inx = (active_index == MAX_KEY) ? file->lastinx : active_index;
-+ if (inx >= 0 && inx < MAX_KEY)
-+ index_rows_read[inx]++;
-+ }
- MYSQL_INDEX_READ_ROW_DONE(error);
- return error;
- }
-@@ -1633,6 +1682,14 @@
- ha_statistic_increment(&SSV::ha_read_first_count);
- int error=mi_rfirst(file, buf, active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
-+ if (!error)
-+ {
-+ rows_read++;
-+
-+ int inx = (active_index == MAX_KEY) ? file->lastinx : active_index;
-+ if (inx >= 0 && inx < MAX_KEY)
-+ index_rows_read[inx]++;
-+ }
- MYSQL_INDEX_READ_ROW_DONE(error);
- return error;
- }
-@@ -1644,6 +1701,14 @@
- ha_statistic_increment(&SSV::ha_read_last_count);
- int error=mi_rlast(file, buf, active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
-+ if (!error)
-+ {
-+ rows_read++;
-+
-+ int inx = (active_index == MAX_KEY) ? file->lastinx : active_index;
-+ if (inx >= 0 && inx < MAX_KEY)
-+ index_rows_read[inx]++;
-+ }
- MYSQL_INDEX_READ_ROW_DONE(error);
- return error;
- }
-@@ -1661,6 +1726,14 @@
- error= mi_rnext_same(file,buf);
- } while (error == HA_ERR_RECORD_DELETED);
- table->status=error ? STATUS_NOT_FOUND: 0;
-+ if (!error)
-+ {
-+ rows_read++;
-+
-+ int inx = (active_index == MAX_KEY) ? file->lastinx : active_index;
-+ if (inx >= 0 && inx < MAX_KEY)
-+ index_rows_read[inx]++;
-+ }
- MYSQL_INDEX_READ_ROW_DONE(error);
- return error;
- }
-@@ -1680,6 +1753,8 @@
- ha_statistic_increment(&SSV::ha_read_rnd_next_count);
- int error=mi_scan(file, buf);
- table->status=error ? STATUS_NOT_FOUND: 0;
-+ if (!error)
-+ rows_read++;
- MYSQL_READ_ROW_DONE(error);
- return error;
- }
-@@ -1696,6 +1771,8 @@
- ha_statistic_increment(&SSV::ha_read_rnd_count);
- int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length));
- table->status=error ? STATUS_NOT_FOUND: 0;
-+ if (!error)
-+ rows_read++;
- MYSQL_READ_ROW_DONE(error);
- return error;
- }
---- /dev/null
-+++ b/mysql-test/r/userstat_bug602047.result
-@@ -0,0 +1,15 @@
-+DROP TABLE IF EXISTS t1;
-+SET GLOBAL userstat=ON;
-+CREATE TABLE t1 ( id int(10), PRIMARY KEY (id)) ENGINE=InnoDB;
-+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
-+SELECT COUNT(*) FROM t1;
-+COUNT(*)
-+10
-+SELECT ROWS_READ FROM information_schema.table_statistics WHERE TABLE_NAME='t1';
-+ROWS_READ
-+10
-+SELECT ROWS_READ FROM information_schema.index_statistics WHERE TABLE_NAME='t1';
-+ROWS_READ
-+10
-+SET GLOBAL userstat=OFF;
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/t/userstat_bug602047.test
-@@ -0,0 +1,11 @@
-+--disable_warnings
-+DROP TABLE IF EXISTS t1;
-+--enable_warnings
-+SET GLOBAL userstat=ON;
-+CREATE TABLE t1 ( id int(10), PRIMARY KEY (id)) ENGINE=InnoDB;
-+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
-+SELECT COUNT(*) FROM t1;
-+SELECT ROWS_READ FROM information_schema.table_statistics WHERE TABLE_NAME='t1';
-+SELECT ROWS_READ FROM information_schema.index_statistics WHERE TABLE_NAME='t1';
-+SET GLOBAL userstat=OFF;
-+DROP TABLE t1;
-\ No newline at end of file
---- a/mysql-test/r/mysqld--help-notwin.result
-+++ b/mysql-test/r/mysqld--help-notwin.result
-@@ -745,6 +745,8 @@
- Define threads usage for handling queries, one of
- one-thread-per-connection, no-threads, loaded-dynamically
- --thread-stack=# The stack size for each thread
-+ --thread-statistics Control TABLE_STATISTICS running, when userstat is
-+ enabled
- --time-format=name The TIME format (ignored)
- --timed-mutexes Specify whether to time mutexes (only InnoDB mutexes are
- currently supported)
-@@ -770,6 +772,9 @@
- of the underlying table and the query uses a LIMIT clause
- (usually get from GUI tools)
- -u, --user=name Run mysqld daemon as user.
-+ --userstat Control USER_STATISTICS, CLIENT_STATISTICS,
-+ THREAD_STATISTICS, INDEX_STATISTICS and TABLE_STATISTICS
-+ running
- -v, --verbose Used with --help option for detailed help.
- -V, --version Output version information and exit.
- --wait-timeout=# The number of seconds the server waits for activity on a
-@@ -1005,6 +1010,7 @@
- thread-cache-size 0
- thread-handling one-thread-per-connection
- thread-stack 262144
-+thread-statistics FALSE
- time-format %H:%i:%s
- timed-mutexes FALSE
- tmp-table-size 16777216
-@@ -1012,6 +1018,7 @@
- transaction-isolation REPEATABLE-READ
- transaction-prealloc-size 4096
- updatable-views-with-limit YES
-+userstat FALSE
- verbose TRUE
- wait-timeout 28800
- xtradb-admin-command ON
+++ /dev/null
-# MySQL bug#43593 dump/backup/restore/upgrade tools fails
-#
-# The patch is intended to help to those users:
-# - Having indexes on columns with collations
-# utf8_general_ci or ucs2_general_ci
-# - Having German letter SHARP S (SZLIG) in these columns
-# - Upgrading from MySQL from versions 5.0.x or
-# 5.1.23 (and earlier) to version 5.1.24 (and higher).
-#
-# This patch introduces new collations utf8_general50_ci
-# and ucs2_general50_ci which reproduce the "old"
-# sorting order provided by pre-5.1.24 versions of xxx_general_ci.
-#
-# In order to start using new MySQL-5.1.24+ please do the following:
-#
-# - Start new version of mysqld
-# - Convert all affected tables using this query (in case of utf8):
-#
-# ALTER TABLE t1 CONVERT TO CHARACTER SET utf8 COLLATE utf8_general50_ci;
-#
-# Or if you need to apply changes per-column level, use this example:
-#
-# ALTER TABLE t1 MODIFY c1 CHAR(N) CHARACTER SET utf8 COLLATE utf8_general50_ci;
-#
-# (Make sure you're using the old data type and size,
-# NULL/NOT NULL constraints, etc).
-#
-=== modified file 'mysys/charset-def.c'
---- a/mysys/charset-def.c
-+++ b/mysys/charset-def.c
-@@ -22,6 +22,9 @@
- init_compiled_charsets() that only adds those that he wants
- */
-
-+extern CHARSET_INFO my_charset_ucs2_general50_ci;
-+extern CHARSET_INFO my_charset_utf8_general50_ci;
-+
- #ifdef HAVE_UCA_COLLATIONS
-
- #ifdef HAVE_CHARSET_ucs2
-@@ -205,6 +208,7 @@
- add_compiled_collation(&my_charset_ucs2_general_ci);
- add_compiled_collation(&my_charset_ucs2_bin);
- add_compiled_collation(&my_charset_ucs2_general_mysql500_ci);
-+ add_compiled_collation(&my_charset_ucs2_general50_ci);
- #ifdef HAVE_UCA_COLLATIONS
- add_compiled_collation(&my_charset_ucs2_unicode_ci);
- add_compiled_collation(&my_charset_ucs2_icelandic_uca_ci);
-@@ -238,6 +242,7 @@
- add_compiled_collation(&my_charset_utf8_general_ci);
- add_compiled_collation(&my_charset_utf8_bin);
- add_compiled_collation(&my_charset_utf8_general_mysql500_ci);
-+ add_compiled_collation(&my_charset_utf8_general50_ci);
- #ifdef HAVE_UTF8_GENERAL_CS
- add_compiled_collation(&my_charset_utf8_general_cs);
- #endif
---- a/strings/ctype-ucs2.c
-+++ b/strings/ctype-ucs2.c
-@@ -3188,6 +3188,42 @@
- };
-
-
-+
-+extern MY_UNICASE_INFO *my_unicase_general50[256];
-+
-+CHARSET_INFO my_charset_ucs2_general50_ci=
-+{
-+ 159,0,0, /* number */
-+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
-+ "ucs2", /* cs name */
-+ "ucs2_general50_ci", /* name */
-+ "", /* comment */
-+ NULL, /* tailoring */
-+ ctype_ucs2, /* ctype */
-+ to_lower_ucs2, /* to_lower */
-+ to_upper_ucs2, /* to_upper */
-+ to_upper_ucs2, /* sort_order */
-+ NULL, /* contractions */
-+ NULL, /* sort_order_big*/
-+ NULL, /* tab_to_uni */
-+ NULL, /* tab_from_uni */
-+ my_unicase_general50, /* caseinfo */
-+ NULL, /* state_map */
-+ NULL, /* ident_map */
-+ 1, /* strxfrm_multiply */
-+ 1, /* caseup_multiply */
-+ 1, /* casedn_multiply */
-+ 2, /* mbminlen */
-+ 2, /* mbmaxlen */
-+ 0, /* min_sort_char */
-+ 0xFFFF, /* max_sort_char */
-+ ' ', /* pad char */
-+ 0, /* escape_with_backslash_is_dangerous */
-+ &my_charset_ucs2_handler,
-+ &my_collation_ucs2_general_ci_handler
-+};
-+
-+
- CHARSET_INFO my_charset_ucs2_bin=
- {
- 90,0,0, /* number */
---- a/strings/ctype-utf8.c
-+++ b/strings/ctype-utf8.c
-@@ -192,6 +192,138 @@
- {0x00DE,0x00FE,0x00DE}, {0x0178,0x00FF,0x0059}
- };
-
-+static MY_UNICASE_INFO plane00_general50[]={
-+ {0x0000,0x0000,0x0000}, {0x0001,0x0001,0x0001},
-+ {0x0002,0x0002,0x0002}, {0x0003,0x0003,0x0003},
-+ {0x0004,0x0004,0x0004}, {0x0005,0x0005,0x0005},
-+ {0x0006,0x0006,0x0006}, {0x0007,0x0007,0x0007},
-+ {0x0008,0x0008,0x0008}, {0x0009,0x0009,0x0009},
-+ {0x000A,0x000A,0x000A}, {0x000B,0x000B,0x000B},
-+ {0x000C,0x000C,0x000C}, {0x000D,0x000D,0x000D},
-+ {0x000E,0x000E,0x000E}, {0x000F,0x000F,0x000F},
-+ {0x0010,0x0010,0x0010}, {0x0011,0x0011,0x0011},
-+ {0x0012,0x0012,0x0012}, {0x0013,0x0013,0x0013},
-+ {0x0014,0x0014,0x0014}, {0x0015,0x0015,0x0015},
-+ {0x0016,0x0016,0x0016}, {0x0017,0x0017,0x0017},
-+ {0x0018,0x0018,0x0018}, {0x0019,0x0019,0x0019},
-+ {0x001A,0x001A,0x001A}, {0x001B,0x001B,0x001B},
-+ {0x001C,0x001C,0x001C}, {0x001D,0x001D,0x001D},
-+ {0x001E,0x001E,0x001E}, {0x001F,0x001F,0x001F},
-+ {0x0020,0x0020,0x0020}, {0x0021,0x0021,0x0021},
-+ {0x0022,0x0022,0x0022}, {0x0023,0x0023,0x0023},
-+ {0x0024,0x0024,0x0024}, {0x0025,0x0025,0x0025},
-+ {0x0026,0x0026,0x0026}, {0x0027,0x0027,0x0027},
-+ {0x0028,0x0028,0x0028}, {0x0029,0x0029,0x0029},
-+ {0x002A,0x002A,0x002A}, {0x002B,0x002B,0x002B},
-+ {0x002C,0x002C,0x002C}, {0x002D,0x002D,0x002D},
-+ {0x002E,0x002E,0x002E}, {0x002F,0x002F,0x002F},
-+ {0x0030,0x0030,0x0030}, {0x0031,0x0031,0x0031},
-+ {0x0032,0x0032,0x0032}, {0x0033,0x0033,0x0033},
-+ {0x0034,0x0034,0x0034}, {0x0035,0x0035,0x0035},
-+ {0x0036,0x0036,0x0036}, {0x0037,0x0037,0x0037},
-+ {0x0038,0x0038,0x0038}, {0x0039,0x0039,0x0039},
-+ {0x003A,0x003A,0x003A}, {0x003B,0x003B,0x003B},
-+ {0x003C,0x003C,0x003C}, {0x003D,0x003D,0x003D},
-+ {0x003E,0x003E,0x003E}, {0x003F,0x003F,0x003F},
-+ {0x0040,0x0040,0x0040}, {0x0041,0x0061,0x0041},
-+ {0x0042,0x0062,0x0042}, {0x0043,0x0063,0x0043},
-+ {0x0044,0x0064,0x0044}, {0x0045,0x0065,0x0045},
-+ {0x0046,0x0066,0x0046}, {0x0047,0x0067,0x0047},
-+ {0x0048,0x0068,0x0048}, {0x0049,0x0069,0x0049},
-+ {0x004A,0x006A,0x004A}, {0x004B,0x006B,0x004B},
-+ {0x004C,0x006C,0x004C}, {0x004D,0x006D,0x004D},
-+ {0x004E,0x006E,0x004E}, {0x004F,0x006F,0x004F},
-+ {0x0050,0x0070,0x0050}, {0x0051,0x0071,0x0051},
-+ {0x0052,0x0072,0x0052}, {0x0053,0x0073,0x0053},
-+ {0x0054,0x0074,0x0054}, {0x0055,0x0075,0x0055},
-+ {0x0056,0x0076,0x0056}, {0x0057,0x0077,0x0057},
-+ {0x0058,0x0078,0x0058}, {0x0059,0x0079,0x0059},
-+ {0x005A,0x007A,0x005A}, {0x005B,0x005B,0x005B},
-+ {0x005C,0x005C,0x005C}, {0x005D,0x005D,0x005D},
-+ {0x005E,0x005E,0x005E}, {0x005F,0x005F,0x005F},
-+ {0x0060,0x0060,0x0060}, {0x0041,0x0061,0x0041},
-+ {0x0042,0x0062,0x0042}, {0x0043,0x0063,0x0043},
-+ {0x0044,0x0064,0x0044}, {0x0045,0x0065,0x0045},
-+ {0x0046,0x0066,0x0046}, {0x0047,0x0067,0x0047},
-+ {0x0048,0x0068,0x0048}, {0x0049,0x0069,0x0049},
-+ {0x004A,0x006A,0x004A}, {0x004B,0x006B,0x004B},
-+ {0x004C,0x006C,0x004C}, {0x004D,0x006D,0x004D},
-+ {0x004E,0x006E,0x004E}, {0x004F,0x006F,0x004F},
-+ {0x0050,0x0070,0x0050}, {0x0051,0x0071,0x0051},
-+ {0x0052,0x0072,0x0052}, {0x0053,0x0073,0x0053},
-+ {0x0054,0x0074,0x0054}, {0x0055,0x0075,0x0055},
-+ {0x0056,0x0076,0x0056}, {0x0057,0x0077,0x0057},
-+ {0x0058,0x0078,0x0058}, {0x0059,0x0079,0x0059},
-+ {0x005A,0x007A,0x005A}, {0x007B,0x007B,0x007B},
-+ {0x007C,0x007C,0x007C}, {0x007D,0x007D,0x007D},
-+ {0x007E,0x007E,0x007E}, {0x007F,0x007F,0x007F},
-+ {0x0080,0x0080,0x0080}, {0x0081,0x0081,0x0081},
-+ {0x0082,0x0082,0x0082}, {0x0083,0x0083,0x0083},
-+ {0x0084,0x0084,0x0084}, {0x0085,0x0085,0x0085},
-+ {0x0086,0x0086,0x0086}, {0x0087,0x0087,0x0087},
-+ {0x0088,0x0088,0x0088}, {0x0089,0x0089,0x0089},
-+ {0x008A,0x008A,0x008A}, {0x008B,0x008B,0x008B},
-+ {0x008C,0x008C,0x008C}, {0x008D,0x008D,0x008D},
-+ {0x008E,0x008E,0x008E}, {0x008F,0x008F,0x008F},
-+ {0x0090,0x0090,0x0090}, {0x0091,0x0091,0x0091},
-+ {0x0092,0x0092,0x0092}, {0x0093,0x0093,0x0093},
-+ {0x0094,0x0094,0x0094}, {0x0095,0x0095,0x0095},
-+ {0x0096,0x0096,0x0096}, {0x0097,0x0097,0x0097},
-+ {0x0098,0x0098,0x0098}, {0x0099,0x0099,0x0099},
-+ {0x009A,0x009A,0x009A}, {0x009B,0x009B,0x009B},
-+ {0x009C,0x009C,0x009C}, {0x009D,0x009D,0x009D},
-+ {0x009E,0x009E,0x009E}, {0x009F,0x009F,0x009F},
-+ {0x00A0,0x00A0,0x00A0}, {0x00A1,0x00A1,0x00A1},
-+ {0x00A2,0x00A2,0x00A2}, {0x00A3,0x00A3,0x00A3},
-+ {0x00A4,0x00A4,0x00A4}, {0x00A5,0x00A5,0x00A5},
-+ {0x00A6,0x00A6,0x00A6}, {0x00A7,0x00A7,0x00A7},
-+ {0x00A8,0x00A8,0x00A8}, {0x00A9,0x00A9,0x00A9},
-+ {0x00AA,0x00AA,0x00AA}, {0x00AB,0x00AB,0x00AB},
-+ {0x00AC,0x00AC,0x00AC}, {0x00AD,0x00AD,0x00AD},
-+ {0x00AE,0x00AE,0x00AE}, {0x00AF,0x00AF,0x00AF},
-+ {0x00B0,0x00B0,0x00B0}, {0x00B1,0x00B1,0x00B1},
-+ {0x00B2,0x00B2,0x00B2}, {0x00B3,0x00B3,0x00B3},
-+ {0x00B4,0x00B4,0x00B4}, {0x039C,0x00B5,0x039C},
-+ {0x00B6,0x00B6,0x00B6}, {0x00B7,0x00B7,0x00B7},
-+ {0x00B8,0x00B8,0x00B8}, {0x00B9,0x00B9,0x00B9},
-+ {0x00BA,0x00BA,0x00BA}, {0x00BB,0x00BB,0x00BB},
-+ {0x00BC,0x00BC,0x00BC}, {0x00BD,0x00BD,0x00BD},
-+ {0x00BE,0x00BE,0x00BE}, {0x00BF,0x00BF,0x00BF},
-+ {0x00C0,0x00E0,0x0041}, {0x00C1,0x00E1,0x0041},
-+ {0x00C2,0x00E2,0x0041}, {0x00C3,0x00E3,0x0041},
-+ {0x00C4,0x00E4,0x0041}, {0x00C5,0x00E5,0x0041},
-+ {0x00C6,0x00E6,0x00C6}, {0x00C7,0x00E7,0x0043},
-+ {0x00C8,0x00E8,0x0045}, {0x00C9,0x00E9,0x0045},
-+ {0x00CA,0x00EA,0x0045}, {0x00CB,0x00EB,0x0045},
-+ {0x00CC,0x00EC,0x0049}, {0x00CD,0x00ED,0x0049},
-+ {0x00CE,0x00EE,0x0049}, {0x00CF,0x00EF,0x0049},
-+ {0x00D0,0x00F0,0x00D0}, {0x00D1,0x00F1,0x004E},
-+ {0x00D2,0x00F2,0x004F}, {0x00D3,0x00F3,0x004F},
-+ {0x00D4,0x00F4,0x004F}, {0x00D5,0x00F5,0x004F},
-+ {0x00D6,0x00F6,0x004F}, {0x00D7,0x00D7,0x00D7},
-+ {0x00D8,0x00F8,0x00D8}, {0x00D9,0x00F9,0x0055},
-+ {0x00DA,0x00FA,0x0055}, {0x00DB,0x00FB,0x0055},
-+ {0x00DC,0x00FC,0x0055}, {0x00DD,0x00FD,0x0059},
-+ {0x00DE,0x00FE,0x00DE}, {0x00DF,0x00DF,0x00DF},
-+ {0x00C0,0x00E0,0x0041}, {0x00C1,0x00E1,0x0041},
-+ {0x00C2,0x00E2,0x0041}, {0x00C3,0x00E3,0x0041},
-+ {0x00C4,0x00E4,0x0041}, {0x00C5,0x00E5,0x0041},
-+ {0x00C6,0x00E6,0x00C6}, {0x00C7,0x00E7,0x0043},
-+ {0x00C8,0x00E8,0x0045}, {0x00C9,0x00E9,0x0045},
-+ {0x00CA,0x00EA,0x0045}, {0x00CB,0x00EB,0x0045},
-+ {0x00CC,0x00EC,0x0049}, {0x00CD,0x00ED,0x0049},
-+ {0x00CE,0x00EE,0x0049}, {0x00CF,0x00EF,0x0049},
-+ {0x00D0,0x00F0,0x00D0}, {0x00D1,0x00F1,0x004E},
-+ {0x00D2,0x00F2,0x004F}, {0x00D3,0x00F3,0x004F},
-+ {0x00D4,0x00F4,0x004F}, {0x00D5,0x00F5,0x004F},
-+ {0x00D6,0x00F6,0x004F}, {0x00F7,0x00F7,0x00F7},
-+ {0x00D8,0x00F8,0x00D8}, {0x00D9,0x00F9,0x0055},
-+ {0x00DA,0x00FA,0x0055}, {0x00DB,0x00FB,0x0055},
-+ {0x00DC,0x00FC,0x0055}, {0x00DD,0x00FD,0x0059},
-+ {0x00DE,0x00FE,0x00DE}, {0x0178,0x00FF,0x0059}
-+};
-+
-+
-
- /*
- Almost similar to plane00, but maps sorting order
-@@ -1718,6 +1850,48 @@
-
-
- /*
-+ general50: to reproduce old utf8_general_ci behaviour
-+ before we fixed Bug#27877.
-+*/
-+MY_UNICASE_INFO *my_unicase_general50[256]={
-+ plane00_general50,
-+ plane01, plane02, plane03, plane04, plane05, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, plane1E, plane1F,
-+ NULL, plane21, NULL, NULL, plane24, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, planeFF
-+
-+};
-+
-+
-+/*
- Turkish lower/upper mapping:
- 1. LOWER(0x0049 LATIN CAPITAL LETTER I) ->
- 0x0131 LATIN SMALL LETTER DOTLESS I
-@@ -3023,6 +3197,39 @@
- };
-
-
-+CHARSET_INFO my_charset_utf8_general50_ci=
-+{
-+ 253,0,0, /* number */
-+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, /* state */
-+ "utf8", /* cs name */
-+ "utf8_general50_ci", /* name */
-+ "", /* comment */
-+ NULL, /* tailoring */
-+ ctype_utf8, /* ctype */
-+ to_lower_utf8, /* to_lower */
-+ to_upper_utf8, /* to_upper */
-+ to_upper_utf8, /* sort_order */
-+ NULL, /* contractions */
-+ NULL, /* sort_order_big*/
-+ NULL, /* tab_to_uni */
-+ NULL, /* tab_from_uni */
-+ my_unicase_general50, /* caseinfo */
-+ NULL, /* state_map */
-+ NULL, /* ident_map */
-+ 1, /* strxfrm_multiply */
-+ 1, /* caseup_multiply */
-+ 1, /* casedn_multiply */
-+ 1, /* mbminlen */
-+ 3, /* mbmaxlen */
-+ 0, /* min_sort_char */
-+ 0xFFFF, /* max_sort_char */
-+ ' ', /* pad char */
-+ 0, /* escape_with_backslash_is_dangerous */
-+ &my_charset_utf8_handler,
-+ &my_collation_ci_handler
-+};
-+
-+
- CHARSET_INFO my_charset_utf8_bin=
- {
- 83,0,0, /* number */
---- /dev/null
-+++ b/mysql-test/t/percona_ucs2_general50_ci.test
-@@ -0,0 +1,12 @@
-+#
-+# Test that ucs2_general50_ci provides pre-5.1.24 utf8_general_ci behavior,
-+# i.e. SHARP S is only equal to itself.
-+#
-+
-+--source include/have_ucs2.inc
-+
-+SET NAMES latin1;
-+
-+SET collation_connection='ucs2_general50_ci';
-+
-+--source include/ctype_german.inc
---- /dev/null
-+++ b/mysql-test/t/percona_utf8_general50_ci.test
-@@ -0,0 +1,9 @@
-+#
-+# Test that utf8_general50_ci provides pre-5.1.24 utf8_general_ci behavior,
-+# i.e. SHARP S is only equal to itself.
-+#
-+
-+SET NAMES utf8;
-+
-+SET collation_connection='utf8_general50_ci';
-+--source include/ctype_german.inc
---- /dev/null
-+++ b/mysql-test/r/percona_utf8_general50_ci.result
-@@ -0,0 +1,38 @@
-+SET NAMES utf8;
-+SET collation_connection='utf8_general50_ci';
-+drop table if exists t1;
-+create table t1 as select repeat(' ', 64) as s1;
-+select collation(s1) from t1;
-+collation(s1)
-+utf8_general50_ci
-+delete from t1;
-+insert into t1 values ('a'),('ae'),(_latin1 0xE4);
-+insert into t1 values ('o'),('oe'),(_latin1 0xF6);
-+insert into t1 values ('s'),('ss'),(_latin1 0xDF);
-+insert into t1 values ('u'),('ue'),(_latin1 0xFC);
-+select s1, hex(s1) from t1 order by s1, binary s1;
-+s1 hex(s1)
-+a 61
-+ä C3A4
-+ae 6165
-+o 6F
-+ö C3B6
-+oe 6F65
-+s 73
-+ss 7373
-+u 75
-+ü C3BC
-+ue 7565
-+ß C39F
-+select group_concat(s1 order by binary s1) from t1 group by s1;
-+group_concat(s1 order by binary s1)
-+a,ä
-+ae
-+o,ö
-+oe
-+s
-+ss
-+u,ü
-+ue
-+ß
-+drop table t1;
-Binary files /dev/null and b/mysql-test/r/percona_ucs2_general50_ci.result differ
+++ /dev/null
-# valgrind suppression for zlib
-# https://bugs.launchpad.net/percona-server/+bug/794837
---- a/mysql-test/valgrind.supp
-+++ b/mysql-test/valgrind.supp
-@@ -876,6 +876,15 @@
- fun:buf_buddy_free_low
- fun:buf_buddy_free
- }
-+{
-+ zlib longest_match false positive
-+ Memcheck:Cond
-+ fun:longest_match
-+ fun:deflate_slow
-+ fun:deflate
-+ fun:compress
-+ fun:my_compress_alloc
-+}
-
- # Note the wildcard in the (mangled) function signatures of
- # write_keys() and find_all_keys().
+++ /dev/null
---- a/sql/debug_sync.cc
-+++ b/sql/debug_sync.cc
-@@ -1737,7 +1737,7 @@
- if (action->wait_for.length())
- {
- mysql_mutex_t *old_mutex;
-- mysql_cond_t *old_cond;
-+ mysql_cond_t* UNINIT_VAR(old_cond);
- int error= 0;
- struct timespec abstime;
-
---- a/storage/innobase/ibuf/ibuf0ibuf.c
-+++ b/storage/innobase/ibuf/ibuf0ibuf.c
-@@ -1523,7 +1523,7 @@
-
- for (i = 0; i < IBUF_OP_COUNT; i++) {
- #ifdef HAVE_ATOMIC_BUILTINS
-- os_atomic_increment_ulint(&arr[i], ops[i]);
-+ (void) os_atomic_increment_ulint(&arr[i], ops[i]);
- #else /* HAVE_ATOMIC_BUILTINS */
- arr[i] += ops[i];
- #endif /* HAVE_ATOMIC_BUILTINS */
-@@ -4785,7 +4785,7 @@
- mem_heap_free(heap);
-
- #ifdef HAVE_ATOMIC_BUILTINS
-- os_atomic_increment_ulint(&ibuf->n_merges, 1);
-+ (void) os_atomic_increment_ulint(&ibuf->n_merges, 1);
- ibuf_add_ops(ibuf->n_merged_ops, mops);
- ibuf_add_ops(ibuf->n_discarded_ops, dops);
- #else /* HAVE_ATOMIC_BUILTINS */
+++ /dev/null
---- /dev/null
-+++ b/mysql-test/r/percona_xtradb_bug317074.result
-@@ -0,0 +1,5 @@
-+SET @old_innodb_file_format=@@innodb_file_format;
-+SET @old_innodb_file_format_max=@@innodb_file_format_max;
-+SET @old_innodb_file_per_table=@@innodb_file_per_table;
-+SET GLOBAL innodb_file_format='Barracuda';
-+SET GLOBAL innodb_file_per_table=ON;
---- /dev/null
-+++ b/mysql-test/t/percona_xtradb_bug317074.test
-@@ -0,0 +1,47 @@
-+-- source include/have_innodb.inc
-+
-+SET @old_innodb_file_format=@@innodb_file_format;
-+SET @old_innodb_file_format_max=@@innodb_file_format_max;
-+SET @old_innodb_file_per_table=@@innodb_file_per_table;
-+SET GLOBAL innodb_file_format='Barracuda';
-+SET GLOBAL innodb_file_per_table=ON;
-+
-+-- disable_query_log
-+-- disable_result_log
-+
-+DROP TABLE IF EXISTS `test1`;
-+CREATE TABLE IF NOT EXISTS `test1` (
-+ `a` int primary key auto_increment,
-+ `b` int default 0,
-+ `c` char(100) default 'testtest'
-+) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
-+
-+delimiter |;
-+CREATE PROCEDURE insert_many(p1 int)
-+BEGIN
-+SET @x = 0;
-+SET @y = 0;
-+start transaction;
-+REPEAT
-+ insert into test1 set b=1;
-+ SET @x = @x + 1;
-+ SET @y = @y + 1;
-+ IF @y >= 1000 THEN
-+ commit;
-+ start transaction;
-+ SET @y = 0;
-+ END IF;
-+UNTIL @x >= p1 END REPEAT;
-+commit;
-+END|
-+delimiter ;|
-+call insert_many(100000);
-+DROP PROCEDURE insert_many;
-+
-+# The bug is hangup at the following statement
-+ALTER TABLE test1 ENGINE=MyISAM;
-+
-+DROP TABLE test1;
-+SET GLOBAL innodb_file_format=@old_innodb_file_format;
-+SET GLOBAL innodb_file_format_max=@old_innodb_file_format_max;
-+SET GLOBAL innodb_file_per_table=@old_innodb_file_per_table;