]> git.pld-linux.org Git - packages/mysql.git/commitdiff
- removed outdated patches
authorJakub Bogusz <qboosh@pld-linux.org>
Sat, 13 Jul 2013 12:20:25 +0000 (14:20 +0200)
committerJakub Bogusz <qboosh@pld-linux.org>
Sat, 13 Jul 2013 12:20:25 +0000 (14:20 +0200)
70 files changed:
bug45702.patch [deleted file]
bug54330.patch [deleted file]
bug580324.patch [deleted file]
bug813587.patch [deleted file]
bug860910.patch [deleted file]
bug917246.patch [deleted file]
bug933969.patch [deleted file]
bug966844_page_size_error_on_5520_upgrade.patch [deleted file]
control_online_alter_index.patch [deleted file]
error_pad.patch [deleted file]
file-contents.patch [deleted file]
group_commit.patch [deleted file]
innodb_adaptive_hash_index_partitions.patch [deleted file]
innodb_admin_command_base.patch [deleted file]
innodb_buffer_pool_pages_i_s.patch [deleted file]
innodb_buffer_pool_shm.patch [deleted file]
innodb_bug60788.patch [deleted file]
innodb_deadlock_count.patch [deleted file]
innodb_dict_size_limit.patch [deleted file]
innodb_expand_fast_index_creation.patch [deleted file]
innodb_expand_import.patch [deleted file]
innodb_extend_slow.patch [deleted file]
innodb_extra_rseg.patch [deleted file]
innodb_fake_changes.patch [deleted file]
innodb_fast_checksum.patch [deleted file]
innodb_files_extend.patch [deleted file]
innodb_fix_misc.patch [deleted file]
innodb_io_patches.patch [deleted file]
innodb_kill_idle_transaction.patch [deleted file]
innodb_lru_dump_restore.patch [deleted file]
innodb_opt_lru_count.patch [deleted file]
innodb_overwrite_relay_log_info.patch [deleted file]
innodb_pass_corrupt_table.patch [deleted file]
innodb_recovery_patches.patch [deleted file]
innodb_separate_doublewrite.patch [deleted file]
innodb_show_lock_name.patch [deleted file]
innodb_show_status.patch [deleted file]
innodb_show_status_extend.patch [deleted file]
innodb_show_sys_tables.patch [deleted file]
innodb_split_buf_pool_mutex.patch [deleted file]
innodb_stats.patch [deleted file]
innodb_thread_concurrency_timer_based.patch [deleted file]
log_connection_error.patch [deleted file]
log_warnings_suppress.patch [deleted file]
memory_dynamic_rows.patch [deleted file]
microsec_process.patch [deleted file]
mysql-test.diff [deleted file]
mysql.spec
mysql_dump_ignore_ct.patch [deleted file]
mysql_remove_eol_carret.patch [deleted file]
mysql_syslog.patch [deleted file]
optimizer_fix.patch [deleted file]
percona.sh [deleted file]
percona_support.patch [deleted file]
processlist_row_stats.patch [deleted file]
query_cache_enhance.patch [deleted file]
remove_fcntl_excessive_calls.patch [deleted file]
response_time_distribution.patch [deleted file]
show_slave_status_nolock.patch [deleted file]
show_temp.patch [deleted file]
slave_timeout_fix.patch [deleted file]
slow_extended.patch [deleted file]
sql_no_fcache.patch [deleted file]
start-stop-messages.patch [deleted file]
subunit.patch [deleted file]
userstat.patch [deleted file]
utf8_general50_ci.patch [deleted file]
valgrind_zlib_suppression.patch [deleted file]
warning_fixes.patch [deleted file]
xtradb_bug317074.patch [deleted file]

diff --git a/bug45702.patch b/bug45702.patch
deleted file mode 100644 (file)
index 7800f01..0000000
+++ /dev/null
@@ -1,728 +0,0 @@
---- 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++)
-     {
diff --git a/bug54330.patch b/bug54330.patch
deleted file mode 100644 (file)
index 850f838..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
---- 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;
diff --git a/bug580324.patch b/bug580324.patch
deleted file mode 100644 (file)
index f8f5bc3..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-# 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;
diff --git a/bug813587.patch b/bug813587.patch
deleted file mode 100644 (file)
index ea8e838..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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));
- }
diff --git a/bug860910.patch b/bug860910.patch
deleted file mode 100644 (file)
index f35a187..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-# 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)
diff --git a/bug917246.patch b/bug917246.patch
deleted file mode 100644 (file)
index 9c43316..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
---- /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;
diff --git a/bug933969.patch b/bug933969.patch
deleted file mode 100644 (file)
index 2590716..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
---- /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
-   {
diff --git a/bug966844_page_size_error_on_5520_upgrade.patch b/bug966844_page_size_error_on_5520_upgrade.patch
deleted file mode 100644 (file)
index 826ad4c..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-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,
diff --git a/control_online_alter_index.patch b/control_online_alter_index.patch
deleted file mode 100644 (file)
index 29c0051..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-# 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)
diff --git a/error_pad.patch b/error_pad.patch
deleted file mode 100644 (file)
index 87d396a..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-# 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));
- }
diff --git a/file-contents.patch b/file-contents.patch
deleted file mode 100644 (file)
index 5cbd412..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
---- 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)
diff --git a/group_commit.patch b/group_commit.patch
deleted file mode 100644 (file)
index ec57a9e..0000000
+++ /dev/null
@@ -1,2610 +0,0 @@
---- 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;
diff --git a/innodb_adaptive_hash_index_partitions.patch b/innodb_adaptive_hash_index_partitions.patch
deleted file mode 100644 (file)
index ed42237..0000000
+++ /dev/null
@@ -1,1439 +0,0 @@
-# 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:
diff --git a/innodb_admin_command_base.patch b/innodb_admin_command_base.patch
deleted file mode 100644 (file)
index 9177386..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-# 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'.
diff --git a/innodb_buffer_pool_pages_i_s.patch b/innodb_buffer_pool_pages_i_s.patch
deleted file mode 100644 (file)
index 9465995..0000000
+++ /dev/null
@@ -1,810 +0,0 @@
-# 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 */
diff --git a/innodb_buffer_pool_shm.patch b/innodb_buffer_pool_shm.patch
deleted file mode 100644 (file)
index 3dca118..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-# 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%';
diff --git a/innodb_bug60788.patch b/innodb_bug60788.patch
deleted file mode 100644 (file)
index d043fb4..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-# 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
diff --git a/innodb_deadlock_count.patch b/innodb_deadlock_count.patch
deleted file mode 100644 (file)
index 4e64e5e..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-# 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;
diff --git a/innodb_dict_size_limit.patch b/innodb_dict_size_limit.patch
deleted file mode 100644 (file)
index 49da2f3..0000000
+++ /dev/null
@@ -1,534 +0,0 @@
-# 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;
diff --git a/innodb_expand_fast_index_creation.patch b/innodb_expand_fast_index_creation.patch
deleted file mode 100644 (file)
index dda5b1a..0000000
+++ /dev/null
@@ -1,1435 +0,0 @@
-# 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
diff --git a/innodb_expand_import.patch b/innodb_expand_import.patch
deleted file mode 100644 (file)
index 3605d61..0000000
+++ /dev/null
@@ -1,1135 +0,0 @@
-# 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
diff --git a/innodb_extend_slow.patch b/innodb_extend_slow.patch
deleted file mode 100644 (file)
index 28c495f..0000000
+++ /dev/null
@@ -1,1036 +0,0 @@
-# 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;
- }
diff --git a/innodb_extra_rseg.patch b/innodb_extra_rseg.patch
deleted file mode 100644 (file)
index 90ab33c..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-# 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 */
diff --git a/innodb_fake_changes.patch b/innodb_fake_changes.patch
deleted file mode 100644 (file)
index e6ec1d4..0000000
+++ /dev/null
@@ -1,767 +0,0 @@
-# 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;
diff --git a/innodb_fast_checksum.patch b/innodb_fast_checksum.patch
deleted file mode 100644 (file)
index 0a733db..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-# 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;
diff --git a/innodb_files_extend.patch b/innodb_files_extend.patch
deleted file mode 100644 (file)
index dd08f6e..0000000
+++ /dev/null
@@ -1,565 +0,0 @@
-# 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"
diff --git a/innodb_fix_misc.patch b/innodb_fix_misc.patch
deleted file mode 100644 (file)
index e58c5e5..0000000
+++ /dev/null
@@ -1,921 +0,0 @@
-# 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) {
diff --git a/innodb_io_patches.patch b/innodb_io_patches.patch
deleted file mode 100644 (file)
index 97e546b..0000000
+++ /dev/null
@@ -1,1648 +0,0 @@
-# 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
diff --git a/innodb_kill_idle_transaction.patch b/innodb_kill_idle_transaction.patch
deleted file mode 100644 (file)
index ed7bdf3..0000000
+++ /dev/null
@@ -1,455 +0,0 @@
-# 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';
diff --git a/innodb_lru_dump_restore.patch b/innodb_lru_dump_restore.patch
deleted file mode 100644 (file)
index 957cf02..0000000
+++ /dev/null
@@ -1,711 +0,0 @@
-# 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;
diff --git a/innodb_opt_lru_count.patch b/innodb_opt_lru_count.patch
deleted file mode 100644 (file)
index d2f80fd..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-# 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. */
diff --git a/innodb_overwrite_relay_log_info.patch b/innodb_overwrite_relay_log_info.patch
deleted file mode 100644 (file)
index ee69f58..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-# 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
diff --git a/innodb_pass_corrupt_table.patch b/innodb_pass_corrupt_table.patch
deleted file mode 100644 (file)
index 63b1c65..0000000
+++ /dev/null
@@ -1,1373 +0,0 @@
-# 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,
diff --git a/innodb_recovery_patches.patch b/innodb_recovery_patches.patch
deleted file mode 100644 (file)
index 0972c42..0000000
+++ /dev/null
@@ -1,496 +0,0 @@
-# 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");
diff --git a/innodb_separate_doublewrite.patch b/innodb_separate_doublewrite.patch
deleted file mode 100644 (file)
index c7d098f..0000000
+++ /dev/null
@@ -1,1086 +0,0 @@
-# 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%';
diff --git a/innodb_show_lock_name.patch b/innodb_show_lock_name.patch
deleted file mode 100644 (file)
index 2fd62c1..0000000
+++ /dev/null
@@ -1,506 +0,0 @@
-# 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;
diff --git a/innodb_show_status.patch b/innodb_show_status.patch
deleted file mode 100644 (file)
index de505e4..0000000
+++ /dev/null
@@ -1,526 +0,0 @@
-# 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",
diff --git a/innodb_show_status_extend.patch b/innodb_show_status_extend.patch
deleted file mode 100644 (file)
index 5758429..0000000
+++ /dev/null
@@ -1,547 +0,0 @@
-# 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;
diff --git a/innodb_show_sys_tables.patch b/innodb_show_sys_tables.patch
deleted file mode 100644 (file)
index 5ad8beb..0000000
+++ /dev/null
@@ -1,1791 +0,0 @@
-# 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 */
diff --git a/innodb_split_buf_pool_mutex.patch b/innodb_split_buf_pool_mutex.patch
deleted file mode 100644 (file)
index dd69aee..0000000
+++ /dev/null
@@ -1,3802 +0,0 @@
-# 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:
diff --git a/innodb_stats.patch b/innodb_stats.patch
deleted file mode 100644 (file)
index 8e79026..0000000
+++ /dev/null
@@ -1,2172 +0,0 @@
-# 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%';
diff --git a/innodb_thread_concurrency_timer_based.patch b/innodb_thread_concurrency_timer_based.patch
deleted file mode 100644 (file)
index d3eb06a..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-# 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);
diff --git a/log_connection_error.patch b/log_connection_error.patch
deleted file mode 100644 (file)
index 0f6440a..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-# 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
-+
diff --git a/log_warnings_suppress.patch b/log_warnings_suppress.patch
deleted file mode 100644 (file)
index 9d03cdc..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-# 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
diff --git a/memory_dynamic_rows.patch b/memory_dynamic_rows.patch
deleted file mode 100644 (file)
index 2b86c84..0000000
+++ /dev/null
@@ -1,5276 +0,0 @@
---- 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;
diff --git a/microsec_process.patch b/microsec_process.patch
deleted file mode 100644 (file)
index 4a17c29..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-# 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}
- };
diff --git a/mysql-test.diff b/mysql-test.diff
deleted file mode 100644 (file)
index b0758e5..0000000
+++ /dev/null
@@ -1,861 +0,0 @@
-# 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;
index 1a0a501642b9010e5d839c2db3c188e98d153875..1f9ca434c27ef4efd9ebc4d31bcfbd98bd939eb1 100644 (file)
@@ -1,5 +1,4 @@
 # 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) ?
diff --git a/mysql_dump_ignore_ct.patch b/mysql_dump_ignore_ct.patch
deleted file mode 100644 (file)
index 8cbdb14..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-# 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)
diff --git a/mysql_remove_eol_carret.patch b/mysql_remove_eol_carret.patch
deleted file mode 100644 (file)
index c276786..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-# 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
diff --git a/mysql_syslog.patch b/mysql_syslog.patch
deleted file mode 100644 (file)
index 0611876..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-# 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);
diff --git a/optimizer_fix.patch b/optimizer_fix.patch
deleted file mode 100644 (file)
index c3dac07..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-# 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(&param, 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)
diff --git a/percona.sh b/percona.sh
deleted file mode 100644 (file)
index 722a35a..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/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
diff --git a/percona_support.patch b/percona_support.patch
deleted file mode 100644 (file)
index 63c951a..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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
diff --git a/processlist_row_stats.patch b/processlist_row_stats.patch
deleted file mode 100644 (file)
index 6bddefd..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-# 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;
diff --git a/query_cache_enhance.patch b/query_cache_enhance.patch
deleted file mode 100644 (file)
index eb1754c..0000000
+++ /dev/null
@@ -1,3168 +0,0 @@
-# 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;
diff --git a/remove_fcntl_excessive_calls.patch b/remove_fcntl_excessive_calls.patch
deleted file mode 100644 (file)
index fcafe1a..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-# 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
diff --git a/response_time_distribution.patch b/response_time_distribution.patch
deleted file mode 100644 (file)
index 603c8e8..0000000
+++ /dev/null
@@ -1,3633 +0,0 @@
-# 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
diff --git a/show_slave_status_nolock.patch b/show_slave_status_nolock.patch
deleted file mode 100644 (file)
index 32dcd7f..0000000
+++ /dev/null
@@ -1,371 +0,0 @@
-# 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);
diff --git a/show_temp.patch b/show_temp.patch
deleted file mode 100644 (file)
index 77fca60..0000000
+++ /dev/null
@@ -1,649 +0,0 @@
-# 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
diff --git a/slave_timeout_fix.patch b/slave_timeout_fix.patch
deleted file mode 100644 (file)
index 925b2f0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---- 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)
- {
diff --git a/slow_extended.patch b/slow_extended.patch
deleted file mode 100644 (file)
index 315b08a..0000000
+++ /dev/null
@@ -1,3054 +0,0 @@
-# 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= &not_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(&current_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;
diff --git a/sql_no_fcache.patch b/sql_no_fcache.patch
deleted file mode 100644 (file)
index 930a0c1..0000000
+++ /dev/null
@@ -1,420 +0,0 @@
-# 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;
diff --git a/start-stop-messages.patch b/start-stop-messages.patch
deleted file mode 100644 (file)
index bb32c38..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
---- 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
diff --git a/subunit.patch b/subunit.patch
deleted file mode 100644 (file)
index 8dc034c..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-=== 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
diff --git a/userstat.patch b/userstat.patch
deleted file mode 100644 (file)
index 5c2265a..0000000
+++ /dev/null
@@ -1,3498 +0,0 @@
-# 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
diff --git a/utf8_general50_ci.patch b/utf8_general50_ci.patch
deleted file mode 100644 (file)
index 3f100e7..0000000
+++ /dev/null
@@ -1,400 +0,0 @@
-# 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
diff --git a/valgrind_zlib_suppression.patch b/valgrind_zlib_suppression.patch
deleted file mode 100644 (file)
index 1504176..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#  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().
diff --git a/warning_fixes.patch b/warning_fixes.patch
deleted file mode 100644 (file)
index c9eab67..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
---- 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 */
diff --git a/xtradb_bug317074.patch b/xtradb_bug317074.patch
deleted file mode 100644 (file)
index 0b50a73..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
---- /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;
This page took 2.620625 seconds and 4 git commands to generate.