[packages/percona-server/v5.1.x: 7/21] - update percona patches from lp:percona-server/5.1 using percona.sh

glen glen at pld-linux.org
Wed Oct 21 16:08:44 CEST 2015


commit 73008a56100860458963408b8dea77acdecb5851
Author: Elan Ruusamäe <glen at pld-linux.org>
Date:   Tue Mar 8 08:52:41 2011 +0000

    - update percona patches from lp:percona-server/5.1 using percona.sh
    
    Changed files:
        mysql-bugfix48929.patch -> 1.1.2.1
        mysql-control_online_alter_index.patch -> 1.1.2.1
        mysql-fix-bug671764.patch -> 1.1.2.1
        mysql-innodb_buffer_pool_shm.patch -> 1.1.2.1
        mysql-innodb_deadlock_count.patch -> 1.1.2.3
        mysql-innodb_fast_shutdown.patch -> 1.1.2.1
        mysql-innodb_fix_misc.patch -> 1.1.2.3
        mysql-innodb_swap_builtin_plugin.patch -> 1.1.2.3
        mysql-log_connection_error.patch -> 1.1.2.1
        mysql-mysql-syslog.patch -> 1.1.2.1
        mysql-mysql_remove_eol_carret.patch -> 1.1.2.1
        mysql-remove_fcntl_excessive_calls.patch -> 1.1.2.1
        mysql-response-time-distribution.patch -> 1.1.2.1
        mysql-show_slave_status_nolock.patch -> 1.1.2.1
        mysql-sql_no_fcache.patch -> 1.1.2.1

 mysql-bugfix48929.patch                  |  166 +++++
 mysql-control_online_alter_index.patch   |  113 +++
 mysql-fix-bug671764.patch                |   28 +
 mysql-innodb_buffer_pool_shm.patch       | 1136 ++++++++++++++++++++++++++++++
 mysql-innodb_deadlock_count.patch        |    6 +-
 mysql-innodb_fast_shutdown.patch         |  241 +++++++
 mysql-innodb_fix_misc.patch              |  495 ++++++++++++-
 mysql-innodb_swap_builtin_plugin.patch   |  108 ---
 mysql-log_connection_error.patch         |   80 +++
 mysql-mysql-syslog.patch                 |  135 ++++
 mysql-mysql_remove_eol_carret.patch      |   72 ++
 mysql-remove_fcntl_excessive_calls.patch |   73 ++
 mysql-response-time-distribution.patch   |  888 +++++++++++++++++++++++
 mysql-show_slave_status_nolock.patch     |  116 +++
 mysql-sql_no_fcache.patch                |  416 +++++++++++
 15 files changed, 3961 insertions(+), 112 deletions(-)
---
diff --git a/mysql-bugfix48929.patch b/mysql-bugfix48929.patch
new file mode 100644
index 0000000..04444a0
--- /dev/null
+++ b/mysql-bugfix48929.patch
@@ -0,0 +1,166 @@
+# name       : bugfix48929.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!
+diff -ruN a/configure.in b/configure.in
+--- a/configure.in	2010-07-07 03:33:05.008972002 +0400
++++ b/configure.in	2010-07-07 03:33:05.788972002 +0400
+@@ -815,7 +815,7 @@
+ AC_HEADER_STDC
+ AC_HEADER_SYS_WAIT
+ AC_CHECK_HEADERS(fcntl.h fenv.h float.h floatingpoint.h fpu_control.h \
+- ieeefp.h limits.h memory.h pwd.h select.h \
++ ieeefp.h limits.h memory.h pwd.h select.h poll.h \
+  stdlib.h stddef.h \
+  strings.h string.h synch.h sys/mman.h sys/socket.h netinet/in.h arpa/inet.h \
+  sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \
+diff -ruN a/configure b/configure
+diff -ruN a/include/config.h.in b/include/config.h.in
+--- a/include/config.h.in	2010-07-26 18:29:12.192113524 +0900
++++ b/include/config.h.in	2010-07-26 20:46:08.265182869 +0900
+@@ -609,6 +609,9 @@
+ /* Define to 1 if you have the `poll' function. */
+ #undef HAVE_POLL
+ 
++/* Define to 1 if you have the <poll.h> header file. */
++#undef HAVE_POLL_H
++
+ /* Define to 1 if you have the `port_create' function. */
+ #undef HAVE_PORT_CREATE
+ 
+diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
+--- a/sql/mysqld.cc	2010-07-07 03:33:05.278972002 +0400
++++ b/sql/mysqld.cc	2010-07-07 03:33:05.788972002 +0400
+@@ -55,6 +55,10 @@
+ #include "sp_rcontext.h"
+ #include "sp_cache.h"
+ 
++#ifdef HAVE_POLL_H
++#include <poll.h>
++#endif
++
+ #define mysqld_charset &my_charset_latin1
+ 
+ #ifdef HAVE_purify
+@@ -5100,28 +5104,49 @@
+ {
+   my_socket sock,new_sock;
+   uint error_count=0;
+-  uint max_used_connection= (uint) (max(ip_sock,unix_sock)+1);
+-  fd_set readFDs,clientFDs;
+   THD *thd;
+   struct sockaddr_in cAddr;
+-  int ip_flags=0,socket_flags=0,flags;
++  int ip_flags=0,socket_flags=0,flags,retval;
+   st_vio *vio_tmp;
++#ifdef HAVE_POLL
++  int socket_count= 0;
++  struct pollfd fds[2]; // for ip_sock and unix_sock
++#else
++  fd_set readFDs,clientFDs;
++  uint max_used_connection= (uint) (max(ip_sock,unix_sock)+1);
++#endif
++
+   DBUG_ENTER("handle_connections_sockets");
+ 
+   LINT_INIT(new_sock);
+ 
+   (void) my_pthread_getprio(pthread_self());		// For debugging
+ 
++#ifndef HAVE_POLL
+   FD_ZERO(&clientFDs);
++#endif
++
+   if (ip_sock != INVALID_SOCKET)
+   {
++#ifdef HAVE_POLL
++    fds[socket_count].fd= ip_sock;
++    fds[socket_count].events= POLLIN;
++    socket_count++;
++#else
+     FD_SET(ip_sock,&clientFDs);
++#endif
+ #ifdef HAVE_FCNTL
+     ip_flags = fcntl(ip_sock, F_GETFL, 0);
+ #endif
+   }
+ #ifdef HAVE_SYS_UN_H
++#ifdef HAVE_POLL
++  fds[socket_count].fd= unix_sock;
++  fds[socket_count].events= POLLIN;
++  socket_count++;
++#else
+   FD_SET(unix_sock,&clientFDs);
++#endif
+ #ifdef HAVE_FCNTL
+   socket_flags=fcntl(unix_sock, F_GETFL, 0);
+ #endif
+@@ -5131,12 +5156,15 @@
+   MAYBE_BROKEN_SYSCALL;
+   while (!abort_loop)
+   {
+-    readFDs=clientFDs;
+-#ifdef HPUX10
+-    if (select(max_used_connection,(int*) &readFDs,0,0,0) < 0)
+-      continue;
++#ifdef HAVE_POLL
++    retval= poll(fds, socket_count, -1);
+ #else
+-    if (select((int) max_used_connection,&readFDs,0,0,0) < 0)
++    readFDs=clientFDs;
++
++    retval= select((int) max_used_connection,&readFDs,0,0,0);
++#endif
++
++    if (retval < 0)
+     {
+       if (socket_errno != SOCKET_EINTR)
+       {
+@@ -5146,7 +5174,7 @@
+       MAYBE_BROKEN_SYSCALL
+       continue;
+     }
+-#endif	/* HPUX10 */
++
+     if (abort_loop)
+     {
+       MAYBE_BROKEN_SYSCALL;
+@@ -5154,6 +5182,21 @@
+     }
+ 
+     /* Is this a new connection request ? */
++#ifdef HAVE_POLL
++    for (int i= 0; i < socket_count; ++i) 
++    {
++      if (fds[i].revents & POLLIN)
++      {
++        sock= fds[i].fd;
++#ifdef HAVE_FCNTL
++        flags= fcntl(sock, F_GETFL, 0);
++#else
++        flags= 0;
++#endif // HAVE_FCNTL
++        break;
++      }
++    }
++#else  // HAVE_POLL
+ #ifdef HAVE_SYS_UN_H
+     if (FD_ISSET(unix_sock,&readFDs))
+     {
+@@ -5161,11 +5204,12 @@
+       flags= socket_flags;
+     }
+     else
+-#endif
++#endif // HAVE_SYS_UN_H
+     {
+       sock = ip_sock;
+       flags= ip_flags;
+     }
++#endif // HAVE_POOL
+ 
+ #if !defined(NO_FCNTL_NONBLOCK)
+     if (!(test_flags & TEST_BLOCKING))
diff --git a/mysql-control_online_alter_index.patch b/mysql-control_online_alter_index.patch
new file mode 100644
index 0000000..6f05020
--- /dev/null
+++ b/mysql-control_online_alter_index.patch
@@ -0,0 +1,113 @@
+# 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!
+diff -ruN a/sql/handler.h b/sql/handler.h
+--- a/sql/handler.h	2010-07-21 22:49:53.660561079 +0900
++++ b/sql/handler.h	2010-07-21 22:50:24.106530090 +0900
+@@ -170,6 +170,19 @@
+ #define HA_ONLINE_DROP_UNIQUE_INDEX             (1L << 9) /*drop uniq. online*/
+ #define HA_ONLINE_ADD_PK_INDEX                  (1L << 10)/*add prim. online*/
+ #define HA_ONLINE_DROP_PK_INDEX                 (1L << 11)/*drop prim. online*/
++
++#define HA_ONLINE_ALTER_INDEX_MASK	(HA_ONLINE_ADD_INDEX_NO_WRITES \
++						| HA_ONLINE_DROP_INDEX_NO_WRITES \
++						| HA_ONLINE_ADD_UNIQUE_INDEX_NO_WRITES \
++						| HA_ONLINE_DROP_UNIQUE_INDEX_NO_WRITES \
++						| HA_ONLINE_ADD_PK_INDEX_NO_WRITES \
++						| HA_ONLINE_DROP_PK_INDEX_NO_WRITES \
++						| HA_ONLINE_ADD_INDEX \
++						| HA_ONLINE_DROP_INDEX \
++						| HA_ONLINE_ADD_UNIQUE_INDEX \
++						| HA_ONLINE_DROP_UNIQUE_INDEX \
++						| HA_ONLINE_ADD_PK_INDEX \
++						| HA_ONLINE_DROP_PK_INDEX)
+ /*
+   HA_PARTITION_FUNCTION_SUPPORTED indicates that the function is
+   supported at all.
+diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
+--- a/sql/mysqld.cc	2010-07-21 22:49:54.011529414 +0900
++++ b/sql/mysqld.cc	2010-07-21 22:50:24.112527179 +0900
+@@ -5874,6 +5874,7 @@
+   OPT_USERSTAT_RUNNING,
+   OPT_THREAD_STATISTICS,
+   OPT_OPTIMIZER_FIX,
++  OPT_ONLINE_ALTER_INDEX,
+   OPT_SUPPRESS_LOG_WARNING_1592,
+   OPT_QUERY_CACHE_STRIP_COMMENTS,
+   OPT_USE_GLOBAL_LONG_QUERY_TIME,
+@@ -5905,6 +5906,13 @@
+    "from libc.so",
+    &opt_allow_suspicious_udfs, &opt_allow_suspicious_udfs,
+    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"fast_index_creation",
++   OPT_ONLINE_ALTER_INDEX,
++   "If disabled, suppresses online operations for indexes of ALTER TABLE "
++   "(e.g. fast index creation of InnoDB Plugin) for the session.",
++   (uchar**) &global_system_variables.online_alter_index,
++   (uchar**) &global_system_variables.online_alter_index,
++   0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+   {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax. This mode "
+    "will also set transaction isolation level 'serializable'.", 0, 0, 0,
+    GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+diff -ruN a/sql/set_var.cc b/sql/set_var.cc
+--- a/sql/set_var.cc	2010-07-21 22:49:54.019529438 +0900
++++ b/sql/set_var.cc	2010-07-21 22:50:24.122532110 +0900
+@@ -748,6 +748,11 @@
+ sys_engine_condition_pushdown(&vars, "engine_condition_pushdown",
+ 			      &SV::engine_condition_pushdown);
+ 
++/* Control online operations of ALTER TABLE */
++static sys_var_thd_bool
++sys_online_alter_index(&vars, "fast_index_creation",
++			&SV::online_alter_index);
++
+ #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
+ /* ndb thread specific variable settings */
+ static sys_var_thd_ulong
+diff -ruN a/sql/sql_class.h b/sql/sql_class.h
+--- a/sql/sql_class.h	2010-07-21 22:49:53.742561560 +0900
++++ b/sql/sql_class.h	2010-07-21 22:50:24.130529404 +0900
+@@ -381,6 +381,8 @@
+   my_bool ndb_use_transactions;
+   my_bool ndb_index_stat_enable;
+ 
++  my_bool online_alter_index;
++
+   my_bool old_alter_table;
+   my_bool old_passwords;
+ 
+diff -ruN a/sql/sql_partition.cc b/sql/sql_partition.cc
+--- a/sql/sql_partition.cc	2010-06-04 00:50:11.000000000 +0900
++++ b/sql/sql_partition.cc	2010-07-21 22:50:24.140530183 +0900
+@@ -4359,7 +4359,12 @@
+         alter_info->no_parts= curr_part_no - new_part_no;
+       }
+     }
+-    if (!(flags= table->file->alter_table_flags(alter_info->flags)))
++    flags= table->file->alter_table_flags(alter_info->flags);
++    if (!thd->variables.online_alter_index)
++    {
++      flags&= ~((uint)HA_ONLINE_ALTER_INDEX_MASK);
++    }
++    if (!flags)
+     {
+       my_error(ER_PARTITION_FUNCTION_FAILURE, MYF(0));
+       DBUG_RETURN(1);
+diff -ruN a/sql/sql_table.cc b/sql/sql_table.cc
+--- a/sql/sql_table.cc	2010-06-04 00:50:11.000000000 +0900
++++ b/sql/sql_table.cc	2010-07-21 22:50:24.146531063 +0900
+@@ -6993,6 +6993,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_ONLINE_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;
diff --git a/mysql-fix-bug671764.patch b/mysql-fix-bug671764.patch
new file mode 100644
index 0000000..128d6eb
--- /dev/null
+++ b/mysql-fix-bug671764.patch
@@ -0,0 +1,28 @@
+# name       : fix-bug671764.patch
+# introduced : 12
+# maintainer : Alexander
+#
+#!!! notice !!!
+# Any small change to this file in the main branch
+# should be done or reviewed by the maintainer!
+diff -Nur a/configure.in b/configure.in
+--- a/configure.in	2010-11-29 18:45:47.000000000 +0000
++++ b/configure.in	2010-11-29 18:45:51.000000000 +0000
+@@ -2718,7 +2718,7 @@
+     MAN_DROP="$MAN_DROP embedded"
+     grep -v 'embedded' $MANLISTFIL > $TMPLISTFIL ; mv -f $TMPLISTFIL $MANLISTFIL
+   fi
+-  if test X"$with_plugin_innobase" != Xyes
++  if test X"$with_plugin_innodb_plugin" != Xyes
+   then
+     MAN_DROP="$MAN_DROP innodb"
+     grep -v 'inno' $MANLISTFIL > $TMPLISTFIL ; mv -f $TMPLISTFIL $MANLISTFIL
+@@ -2797,7 +2797,7 @@
+ fi
+
+ # "innochecksum" is not in the "innobase/" subdirectory, but should be switched
+-AM_CONDITIONAL([BUILD_INNODB_TOOLS], [test X"$with_plugin_innobase" = Xyes])
++AM_CONDITIONAL([BUILD_INNODB_TOOLS], [test X"$with_plugin_innodb_plugin" = Xyes])
+
+ # IMPORTANT - do not modify LIBS past this line - this hack is the only way
+ # I know to add the static NSS magic if we have static NSS libraries with
diff --git a/mysql-innodb_buffer_pool_shm.patch b/mysql-innodb_buffer_pool_shm.patch
new file mode 100644
index 0000000..be6d0f2
--- /dev/null
+++ b/mysql-innodb_buffer_pool_shm.patch
@@ -0,0 +1,1136 @@
+# 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!
+diff -ruN a/storage/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c
+--- a/storage/innodb_plugin/buf/buf0buf.c	2010-07-14 16:32:49.669501663 +0900
++++ b/storage/innodb_plugin/buf/buf0buf.c	2010-07-14 16:40:16.149438645 +0900
+@@ -53,6 +53,10 @@
+ #include "page0zip.h"
+ #include "trx0trx.h"
+ #include "srv0start.h"
++#include "que0que.h"
++#include "read0read.h"
++#include "row0row.h"
++#include "ha_prototypes.h"
+ 
+ /* prototypes for new functions added to ha_innodb.cc */
+ trx_t* innobase_get_trx();
+@@ -310,6 +314,30 @@
+ UNIV_INTERN ibool		buf_debug_prints = FALSE;
+ #endif /* UNIV_DEBUG */
+ 
++/* Buffer pool shared memory segment information */
++typedef	struct buf_shm_info_struct	buf_shm_info_t;
++
++struct buf_shm_info_struct {
++	char	head_str[8];
++	ulint	binary_id;
++	ibool	is_new;		/* during initializing */
++	ibool	clean;		/* clean shutdowned and free */
++	ibool	reusable;	/* reusable */
++	ulint	buf_pool_size;	/* backup value */
++	ulint	page_size;	/* backup value */
++	ulint	frame_offset;	/* offset of the first frame based on chunk->mem */
++	ulint	zip_hash_offset;
++	ulint	zip_hash_n;
++
++	ulint	checksum;
++
++	buf_pool_t	buf_pool_backup;
++	buf_chunk_t	chunk_backup;
++
++	ib_uint64_t	dummy;
++};
++
++#define BUF_SHM_INFO_HEAD "XTRA_SHM"
+ #endif /* !UNIV_HOTBACKUP */
+ 
+ /********************************************************************//**
+@@ -756,6 +784,45 @@
+ #endif /* UNIV_SYNC_DEBUG */
+ }
+ 
++static
++void
++buf_block_reuse(
++/*============*/
++	buf_block_t*	block,
++	ptrdiff_t	frame_offset)
++{
++	/* block_init */
++	block->frame += frame_offset;
++
++	UNIV_MEM_DESC(block->frame, UNIV_PAGE_SIZE, block);
++
++	block->index = NULL;
++
++#ifdef UNIV_DEBUG
++	/* recreate later */
++	block->page.in_page_hash = FALSE;
++	block->page.in_zip_hash = FALSE;
++#endif /* UNIV_DEBUG */
++
++#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
++	block->n_pointers = 0;
++#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
++
++	if (block->page.zip.data)
++		block->page.zip.data += frame_offset;
++
++	block->is_hashed = FALSE;
++
++	mutex_create(&block->mutex, SYNC_BUF_BLOCK);
++
++	rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
++	ut_ad(rw_lock_validate(&(block->lock)));
++
++#ifdef UNIV_SYNC_DEBUG
++	rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
++#endif /* UNIV_SYNC_DEBUG */
++}
++
+ /********************************************************************//**
+ Allocates a chunk of buffer frames.
+ @return	chunk, or NULL on failure */
+@@ -768,26 +835,188 @@
+ {
+ 	buf_block_t*	block;
+ 	byte*		frame;
++	ulint		zip_hash_n = 0;
++	ulint		zip_hash_mem_size = 0;
++	hash_table_t*	zip_hash_tmp = NULL;
+ 	ulint		i;
++	buf_shm_info_t*	shm_info = NULL;
+ 
+ 	/* Round down to a multiple of page size,
+ 	although it already should be. */
+ 	mem_size = ut_2pow_round(mem_size, UNIV_PAGE_SIZE);
++
++	srv_buffer_pool_shm_is_reused = FALSE;
++
++	if (srv_buffer_pool_shm_key) {
++		/* zip_hash size */
++		zip_hash_n = (mem_size / UNIV_PAGE_SIZE) * 2;
++		zip_hash_mem_size = ut_2pow_round(hash_create_needed(zip_hash_n)
++						  + (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
++	}
++
+ 	/* 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);
++	if (srv_buffer_pool_shm_key) {
++		 mem_size += ut_2pow_round(sizeof(buf_shm_info_t)
++					   + (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
++		 mem_size += zip_hash_mem_size;
++	}
+ 
+ 	chunk->mem_size = mem_size;
++
++	if (srv_buffer_pool_shm_key) {
++		ulint	binary_id;
++		ibool	is_new;
++
++		ut_a(buf_pool->n_chunks == 1);
++
++		fprintf(stderr,
++		"InnoDB: Warning: The innodb_buffer_pool_shm_key option has been specified.\n"
++		"InnoDB: Do not change the following between restarts of the server while this option is being used:\n"
++		"InnoDB:   * the mysqld executable between restarts of the server.\n"
++		"InnoDB:   * the value of innodb_buffer_pool_size.\n"
++		"InnoDB:   * the value of innodb_page_size.\n"
++		"InnoDB:   * datafiles created by InnoDB during this session.\n"
++		"InnoDB: Otherwise, data corruption in datafiles may result.\n");
++
++		/* FIXME: This is vague id still */
++		binary_id = (ulint) ((byte*)mtr_commit - (byte*)btr_root_get)
++			  + (ulint) ((byte*)os_get_os_version - (byte*)buf_calc_page_new_checksum)
++			  + (ulint) ((byte*)page_dir_find_owner_slot - (byte*)dfield_data_is_binary_equal)
++			  + (ulint) ((byte*)que_graph_publish - (byte*)dict_casedn_str)
++			  + (ulint) ((byte*)read_view_oldest_copy_or_open_new - (byte*)fil_space_get_version)
++			  + (ulint) ((byte*)rec_get_n_extern_new - (byte*)fsp_get_size_low)
++			  + (ulint) ((byte*)row_get_trx_id_offset - (byte*)ha_create_func)
++			  + (ulint) ((byte*)srv_set_io_thread_op_info - (byte*)thd_is_replication_slave_thread)
++			  + (ulint) ((byte*)mutex_create_func - (byte*)ibuf_inside)
++			  + (ulint) ((byte*)trx_set_detailed_error - (byte*)lock_check_trx_id_sanity)
++			  + (ulint) ((byte*)ut_time - (byte*)mem_heap_strdup);
++
++		chunk->mem = os_shm_alloc(&chunk->mem_size, srv_buffer_pool_shm_key, &is_new);
++
++		if (UNIV_UNLIKELY(chunk->mem == NULL)) {
++			return(NULL);
++		}
++init_again:
++#ifdef UNIV_SET_MEM_TO_ZERO
++		if (is_new) {
++			memset(chunk->mem, '\0', chunk->mem_size);
++		}
++#endif
++		/* for ut_fold_binary_32(), these values should be 32-bit aligned */
++		ut_a(sizeof(buf_shm_info_t) % 4 == 0);
++		ut_a((ulint)chunk->mem % 4 == 0);
++		ut_a(chunk->mem_size % 4 == 0);
++
++		shm_info = chunk->mem;
++
++		zip_hash_tmp = (hash_table_t*)((byte*)chunk->mem + chunk->mem_size - zip_hash_mem_size);
++
++		if (is_new) {
++			strncpy(shm_info->head_str, BUF_SHM_INFO_HEAD, 8);
++			shm_info->binary_id = binary_id;
++			shm_info->is_new = TRUE;	/* changed to FALSE when the initialization is finished */
++			shm_info->clean = FALSE;	/* changed to TRUE when free the segment. */
++			shm_info->reusable = FALSE;	/* changed to TRUE when validation is finished. */
++			shm_info->buf_pool_size = srv_buf_pool_size;
++			shm_info->page_size = srv_page_size;
++			shm_info->zip_hash_offset = chunk->mem_size - zip_hash_mem_size;
++			shm_info->zip_hash_n = zip_hash_n;
++		} else {
++			ulint	checksum;
++
++			if (strncmp(shm_info->head_str, BUF_SHM_INFO_HEAD, 8)) {
++				fprintf(stderr,
++				"InnoDB: Error: The shared memory segment seems not to be for buffer pool.\n");
++				return(NULL);
++			}
++			if (shm_info->binary_id != binary_id) {
++				fprintf(stderr,
++				"InnoDB: Error: The shared memory segment seems not to be for this binary.\n");
++				return(NULL);
++			}
++			if (shm_info->is_new) {
++				fprintf(stderr,
++				"InnoDB: Error: The shared memory was not initialized yet.\n");
++				return(NULL);
++			}
++			if (shm_info->buf_pool_size != srv_buf_pool_size) {
++				fprintf(stderr,
++				"InnoDB: Error: srv_buf_pool_size is different (shm=%lu current=%lu).\n",
++				shm_info->buf_pool_size, srv_buf_pool_size);
++				return(NULL);
++			}
++			if (shm_info->page_size != srv_page_size) {
++				fprintf(stderr,
++				"InnoDB: Error: srv_page_size is different (shm=%lu current=%lu).\n",
++				shm_info->page_size, srv_page_size);
++				return(NULL);
++			}
++			if (!shm_info->reusable) {
++				fprintf(stderr,
++				"InnoDB: Warning: The shared memory has unrecoverable contents.\n"
++				"InnoDB: The shared memory segment is initialized.\n");
++				is_new = TRUE;
++				goto init_again;
++			}
++			if (!shm_info->clean) {
++				fprintf(stderr,
++				"InnoDB: Warning: The shared memory was not shut down cleanly.\n"
++				"InnoDB: The shared memory segment is initialized.\n");
++				is_new = TRUE;
++				goto init_again;
++			}
++
++			ut_a(shm_info->zip_hash_offset == chunk->mem_size - zip_hash_mem_size);
++			ut_a(shm_info->zip_hash_n == zip_hash_n);
++
++			/* check checksum */
++			if (srv_buffer_pool_shm_checksum) {
++				checksum = ut_fold_binary_32((byte*)chunk->mem + sizeof(buf_shm_info_t),
++							     chunk->mem_size - sizeof(buf_shm_info_t));
++			} else {
++				checksum = BUF_NO_CHECKSUM_MAGIC;
++			}
++
++			if (shm_info->checksum != BUF_NO_CHECKSUM_MAGIC
++			    && shm_info->checksum != checksum) {
++				fprintf(stderr,
++				"InnoDB: Error: checksum of the shared memory is not match. "
++				"(stored=%lu calculated=%lu)\n",
++				shm_info->checksum, checksum);
++				return(NULL);
++			}
++
++			/* flag to use the segment. */
++			shm_info->clean = FALSE;	/* changed to TRUE when free the segment. */
++		}
++
++		/* init zip_hash contents */
++		if (is_new) {
++			hash_create_init(zip_hash_tmp, zip_hash_n);
++		} else {
++			/* adjust offset is done later */
++			hash_create_reuse(zip_hash_tmp);
++
++			srv_buffer_pool_shm_is_reused = TRUE;
++		}
++	} else {
+ 	chunk->mem = os_mem_alloc_large(&chunk->mem_size);
+ 
+ 	if (UNIV_UNLIKELY(chunk->mem == NULL)) {
+ 
+ 		return(NULL);
+ 	}
++	}
+ 
+ 	/* Allocate the block descriptors from
+ 	the start of the memory block. */
++	if (srv_buffer_pool_shm_key) {
++		chunk->blocks = (buf_block_t*)((byte*)chunk->mem + sizeof(buf_shm_info_t));
++	} else {
+ 	chunk->blocks = chunk->mem;
++	}
+ 
+ 	/* Align a pointer to the first frame.  Note that when
+ 	os_large_page_size is smaller than UNIV_PAGE_SIZE,
+@@ -795,8 +1024,13 @@
+ 	it is bigger, we may allocate more blocks than requested. */
+ 
+ 	frame = ut_align(chunk->mem, UNIV_PAGE_SIZE);
++	if (srv_buffer_pool_shm_key) {
++		/* reserve zip_hash space and always -1 for reproductibity */
++		chunk->size = (chunk->mem_size - zip_hash_mem_size) / UNIV_PAGE_SIZE - 1;
++	} else {
+ 	chunk->size = chunk->mem_size / UNIV_PAGE_SIZE
+ 		- (frame != chunk->mem);
++	}
+ 
+ 	/* Subtract the space needed for block descriptors. */
+ 	{
+@@ -810,6 +1044,98 @@
+ 		chunk->size = size;
+ 	}
+ 
++	if (shm_info && !(shm_info->is_new)) {
++		/* convert the shared memory segment for reuse */
++		ptrdiff_t	phys_offset;
++		ptrdiff_t	logi_offset;
++		ptrdiff_t	blocks_offset;
++		void*		previous_frame_address;
++
++		if (chunk->size < shm_info->chunk_backup.size) {
++			fprintf(stderr,
++			"InnoDB: Error: The buffer pool became smaller because of allocated address.\n"
++			"InnoDB: Retrying may avoid this situation.\n");
++			shm_info->clean = TRUE; /* release the flag for retrying */
++			return(NULL);
++		}
++
++		chunk->size = shm_info->chunk_backup.size;
++		phys_offset = frame - ((byte*)chunk->mem + shm_info->frame_offset);
++		logi_offset = frame - chunk->blocks[0].frame;
++		previous_frame_address = chunk->blocks[0].frame;
++		blocks_offset = (byte*)chunk->blocks - (byte*)shm_info->chunk_backup.blocks;
++
++		if (phys_offset || logi_offset || blocks_offset) {
++			fprintf(stderr,
++			"InnoDB: Buffer pool in the shared memory segment should be converted.\n"
++			"InnoDB: Previous frames in address      : %p\n"
++			"InnoDB: Previous frames were located    : %p\n"
++			"InnoDB: Current frames should be located: %p\n"
++			"InnoDB: Pysical offset                  : %ld (%#lx)\n"
++			"InnoDB: Logical offset (frames)         : %ld (%#lx)\n"
++			"InnoDB: Logical offset (blocks)         : %ld (%#lx)\n",
++				(byte*)chunk->mem + shm_info->frame_offset,
++				chunk->blocks[0].frame, frame,
++				phys_offset, phys_offset, logi_offset, logi_offset,
++				blocks_offset, blocks_offset);
++		} else {
++			fprintf(stderr,
++			"InnoDB: Buffer pool in the shared memory segment can be used as it is.\n");
++		}
++
++		if (phys_offset) {
++			fprintf(stderr,
++			"InnoDB: Aligning physical offset...");
++
++			memmove(frame, (byte*)chunk->mem + shm_info->frame_offset,
++				chunk->size * UNIV_PAGE_SIZE);
++
++			fprintf(stderr,
++			" Done.\n");
++		}
++
++		/* buf_block_t */
++		block = chunk->blocks;
++		for (i = chunk->size; i--; ) {
++			buf_block_reuse(block, logi_offset);
++			block++;
++		}
++
++		if (logi_offset || blocks_offset) {
++			fprintf(stderr,
++			"InnoDB: Aligning logical offset...");
++
++
++			/* buf_pool_t buf_pool_backup */
++			UT_LIST_OFFSET(flush_list, buf_page_t, shm_info->buf_pool_backup.flush_list,
++					previous_frame_address, logi_offset, blocks_offset);
++			UT_LIST_OFFSET(free, buf_page_t, shm_info->buf_pool_backup.free,
++					previous_frame_address, logi_offset, blocks_offset);
++			UT_LIST_OFFSET(LRU, buf_page_t, shm_info->buf_pool_backup.LRU,
++					previous_frame_address, logi_offset, blocks_offset);
++			if (shm_info->buf_pool_backup.LRU_old)
++				shm_info->buf_pool_backup.LRU_old =
++					(buf_page_t*)((byte*)(shm_info->buf_pool_backup.LRU_old)
++						+ (((void*)shm_info->buf_pool_backup.LRU_old > previous_frame_address)
++						  ? logi_offset : blocks_offset));
++
++			UT_LIST_OFFSET(unzip_LRU, buf_block_t, shm_info->buf_pool_backup.unzip_LRU,
++					previous_frame_address, logi_offset, blocks_offset);
++
++			UT_LIST_OFFSET(zip_list, buf_page_t, shm_info->buf_pool_backup.zip_clean,
++					previous_frame_address, logi_offset, blocks_offset);
++			for (i = 0; i < BUF_BUDDY_SIZES_MAX; i++) {
++				UT_LIST_OFFSET(zip_list, buf_page_t, shm_info->buf_pool_backup.zip_free[i],
++					previous_frame_address, logi_offset, blocks_offset);
++			}
++
++			HASH_OFFSET(zip_hash_tmp, buf_page_t, hash,
++					previous_frame_address, logi_offset, blocks_offset);
++
++			fprintf(stderr,
++			" Done.\n");
++		}
++	} else {
+ 	/* Init block structs and assign frames for them. Then we
+ 	assign the frames to the first blocks (we already mapped the
+ 	memory above). */
+@@ -833,6 +1159,11 @@
+ 		block++;
+ 		frame += UNIV_PAGE_SIZE;
+ 	}
++	}
++
++	if (shm_info) {
++		shm_info->frame_offset = chunk->blocks[0].frame - (byte*)chunk->mem;
++	}
+ 
+ 	return(chunk);
+ }
+@@ -1014,6 +1345,8 @@
+ 		UNIV_MEM_UNDESC(block);
+ 	}
+ 
++	ut_a(!srv_buffer_pool_shm_key);
++
+ 	os_mem_free_large(chunk->mem, chunk->mem_size);
+ }
+ 
+@@ -1063,7 +1396,10 @@
+ 	srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
+ 
+ 	buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
++	/* zip_hash is allocated to shm when srv_buffer_pool_shm_key is enabled */
++	if (!srv_buffer_pool_shm_key) {
+ 	buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
++	}
+ 
+ 	buf_pool->last_printout_time = time(NULL);
+ 
+@@ -1078,6 +1414,86 @@
+ 	--------------------------- */
+ 	/* All fields are initialized by mem_zalloc(). */
+ 
++	if (srv_buffer_pool_shm_key) {
++		buf_shm_info_t*	shm_info;
++
++		ut_a((byte*)chunk->blocks == (byte*)chunk->mem + sizeof(buf_shm_info_t));
++		shm_info = chunk->mem;
++
++		buf_pool->zip_hash = (hash_table_t*)((byte*)chunk->mem + shm_info->zip_hash_offset);
++
++		if(shm_info->is_new) {
++			shm_info->is_new = FALSE; /* initialization was finished */
++		} else {
++			buf_block_t*	block = chunk->blocks;
++			buf_page_t*	b;
++
++			/* shm_info->buf_pool_backup should be converted */
++			/* at buf_chunk_init(). So copy simply. */
++			buf_pool->flush_list 		= shm_info->buf_pool_backup.flush_list;
++			buf_pool->freed_page_clock 	= shm_info->buf_pool_backup.freed_page_clock;
++			buf_pool->free			= shm_info->buf_pool_backup.free;
++			buf_pool->LRU			= shm_info->buf_pool_backup.LRU;
++			buf_pool->LRU_old		= shm_info->buf_pool_backup.LRU_old;
++			buf_pool->LRU_old_len		= shm_info->buf_pool_backup.LRU_old_len;
++			buf_pool->unzip_LRU		= shm_info->buf_pool_backup.unzip_LRU;
++			buf_pool->zip_clean		= shm_info->buf_pool_backup.zip_clean;
++			for (i = 0; i < BUF_BUDDY_SIZES_MAX; i++) {
++				buf_pool->zip_free[i]	= shm_info->buf_pool_backup.zip_free[i];
++			}
++
++			for (i = 0; i < chunk->size; i++, block++) {
++				if (buf_block_get_state(block)
++				    == BUF_BLOCK_FILE_PAGE) {
++					ut_d(block->page.in_page_hash = TRUE);
++					HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
++						    buf_page_address_fold(
++							    block->page.space,
++							    block->page.offset),
++						    &block->page);
++				}
++			}
++
++			for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
++			     b = UT_LIST_GET_NEXT(zip_list, b)) {
++				ut_ad(!b->in_flush_list);
++				ut_ad(b->in_LRU_list);
++
++				ut_d(b->in_page_hash = TRUE);
++				HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
++					    buf_page_address_fold(b->space, b->offset), b);
++			}
++
++			for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
++			     b = UT_LIST_GET_NEXT(flush_list, b)) {
++				ut_ad(b->in_flush_list);
++				ut_ad(b->in_LRU_list);
++
++				switch (buf_page_get_state(b)) {
++				case BUF_BLOCK_ZIP_DIRTY:
++					ut_d(b->in_page_hash = TRUE);
++					HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
++						    buf_page_address_fold(b->space,
++							    		  b->offset), b);
++					break;
++				case BUF_BLOCK_FILE_PAGE:
++					/* uncompressed page */
++					break;
++				case BUF_BLOCK_ZIP_FREE:
++				case BUF_BLOCK_ZIP_PAGE:
++				case BUF_BLOCK_NOT_USED:
++				case BUF_BLOCK_READY_FOR_USE:
++				case BUF_BLOCK_MEMORY:
++				case BUF_BLOCK_REMOVE_HASH:
++					ut_error;
++					break;
++				}
++			}
++
++
++		}
++	}
++
+ 	mutex_exit(&LRU_list_mutex);
+ 	rw_lock_x_unlock(&page_hash_latch);
+ 	buf_pool_mutex_exit();
+@@ -1102,6 +1518,34 @@
+ 	buf_chunk_t*	chunk;
+ 	buf_chunk_t*	chunks;
+ 
++	if (srv_buffer_pool_shm_key) {
++		buf_shm_info_t*	shm_info;
++
++		ut_a(buf_pool->n_chunks == 1);
++
++		chunk = buf_pool->chunks;
++		shm_info = chunk->mem;
++		ut_a((byte*)chunk->blocks == (byte*)chunk->mem + sizeof(buf_shm_info_t));
++
++		/* validation the shared memory segment doesn't have unrecoverable contents. */
++		/* Currently, validation became not needed */
++		shm_info->reusable = TRUE;
++
++		memcpy(&(shm_info->buf_pool_backup), buf_pool, sizeof(buf_pool_t));
++		memcpy(&(shm_info->chunk_backup), chunk, sizeof(buf_chunk_t));
++
++		if (srv_fast_shutdown < 2) {
++			if (srv_buffer_pool_shm_checksum) {
++				shm_info->checksum = ut_fold_binary_32((byte*)chunk->mem + sizeof(buf_shm_info_t),
++								       chunk->mem_size - sizeof(buf_shm_info_t));
++			} else {
++				shm_info->checksum = BUF_NO_CHECKSUM_MAGIC;
++			}
++			shm_info->clean = TRUE;
++		}
++
++		os_shm_free(chunk->mem, chunk->mem_size);
++	} else {
+ 	chunks = buf_pool->chunks;
+ 	chunk = chunks + buf_pool->n_chunks;
+ 
+@@ -1110,10 +1554,13 @@
+ 		would fail at shutdown. */
+ 		os_mem_free_large(chunk->mem, chunk->mem_size);
+ 	}
++	}
+ 
+ 	mem_free(buf_pool->chunks);
+ 	hash_table_free(buf_pool->page_hash);
++	if (!srv_buffer_pool_shm_key) {
+ 	hash_table_free(buf_pool->zip_hash);
++	}
+ 	mem_free(buf_pool);
+ 	buf_pool = NULL;
+ }
+@@ -1308,6 +1755,11 @@
+ 	//buf_pool_mutex_enter();
+ 	mutex_enter(&LRU_list_mutex);
+ 
++	if (srv_buffer_pool_shm_key) {
++		/* Cannot support shrink */
++		goto func_done;
++	}
++
+ shrink_again:
+ 	if (buf_pool->n_chunks <= 1) {
+ 
+@@ -1551,6 +2003,11 @@
+ buf_pool_resize(void)
+ /*=================*/
+ {
++	if (srv_buffer_pool_shm_key) {
++		/* Cannot support resize */
++		return;
++	}
++
+ 	//buf_pool_mutex_enter();
+ 	mutex_enter(&LRU_list_mutex);
+ 
+diff -ruN a/storage/innodb_plugin/ha/hash0hash.c b/storage/innodb_plugin/ha/hash0hash.c
+--- a/storage/innodb_plugin/ha/hash0hash.c	2010-06-04 00:49:59.000000000 +0900
++++ b/storage/innodb_plugin/ha/hash0hash.c	2010-07-14 16:40:16.150438366 +0900
+@@ -128,6 +128,70 @@
+ }
+ 
+ /*************************************************************//**
++*/
++UNIV_INTERN
++ulint
++hash_create_needed(
++/*===============*/
++	ulint	n)
++{
++	ulint	prime;
++	ulint	offset;
++
++	prime = ut_find_prime(n);
++
++	offset = (sizeof(hash_table_t) + 7) / 8;
++	offset *= 8;
++
++	return(offset + sizeof(hash_cell_t) * prime);
++}
++
++UNIV_INTERN
++void
++hash_create_init(
++/*=============*/
++	hash_table_t*	table,
++	ulint		n)
++{
++	ulint	prime;
++	ulint	offset;
++
++	prime = ut_find_prime(n);
++
++	offset = (sizeof(hash_table_t) + 7) / 8;
++	offset *= 8;
++
++	table->array = (hash_cell_t*)(((byte*)table) + offset);
++	table->n_cells = prime;
++# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
++	table->adaptive = FALSE;
++# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
++	table->n_mutexes = 0;
++	table->mutexes = NULL;
++	table->heaps = NULL;
++	table->heap = NULL;
++	ut_d(table->magic_n = HASH_TABLE_MAGIC_N);
++
++	/* Initialize the cell array */
++	hash_table_clear(table);
++}
++
++UNIV_INTERN
++void
++hash_create_reuse(
++/*==============*/
++	hash_table_t*	table)
++{
++	ulint	offset;
++
++	offset = (sizeof(hash_table_t) + 7) / 8;
++	offset *= 8;
++
++	table->array = (hash_cell_t*)(((byte*)table) + offset);
++	ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
++}
++
++/*************************************************************//**
+ Frees a hash table. */
+ UNIV_INTERN
+ void
+diff -ruN a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
+--- a/storage/innodb_plugin/handler/ha_innodb.cc	2010-07-14 16:34:18.597725479 +0900
++++ b/storage/innodb_plugin/handler/ha_innodb.cc	2010-07-14 16:40:16.159323612 +0900
+@@ -198,6 +198,7 @@
+ static my_bool	innobase_create_status_file		= FALSE;
+ static my_bool	innobase_stats_on_metadata		= TRUE;
+ static my_bool	innobase_use_sys_stats_table		= FALSE;
++static my_bool	innobase_buffer_pool_shm_checksum	= TRUE;
+ 
+ static char*	internal_innobase_data_file_path	= NULL;
+ 
+@@ -2457,6 +2458,7 @@
+ 	srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
+ 	srv_use_checksums = (ibool) innobase_use_checksums;
+ 	srv_fast_checksum = (ibool) innobase_fast_checksum;
++	srv_buffer_pool_shm_checksum = (ibool) innobase_buffer_pool_shm_checksum;
+ 
+ #ifdef HAVE_LARGE_PAGES
+         if ((os_use_large_pages = (ibool) my_use_large_pages))
+@@ -11418,6 +11420,16 @@
+   "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
+   NULL, NULL, 128*1024*1024L, 32*1024*1024L, LONGLONG_MAX, 1024*1024L);
+ 
++static MYSQL_SYSVAR_UINT(buffer_pool_shm_key, srv_buffer_pool_shm_key,
++  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
++  "[experimental] The key value of shared memory segment for the buffer pool. 0 (default) disables the feature.",
++  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,
++  "Enable buffer_pool_shm checksum validation (enabled by default).",
++  NULL, NULL, TRUE);
++
+ static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
+   PLUGIN_VAR_RQCMDARG,
+   "Helps in performance tuning in heavily concurrent environments.",
+@@ -11699,6 +11711,8 @@
+   MYSQL_SYSVAR(additional_mem_pool_size),
+   MYSQL_SYSVAR(autoextend_increment),
+   MYSQL_SYSVAR(buffer_pool_size),
++  MYSQL_SYSVAR(buffer_pool_shm_key),
++  MYSQL_SYSVAR(buffer_pool_shm_checksum),
+   MYSQL_SYSVAR(checksums),
+   MYSQL_SYSVAR(fast_checksum),
+   MYSQL_SYSVAR(commit_concurrency),
+diff -ruN a/storage/innodb_plugin/handler/innodb_patch_info.h b/storage/innodb_plugin/handler/innodb_patch_info.h
+--- a/storage/innodb_plugin/handler/innodb_patch_info.h	2010-07-14 16:34:18.603733950 +0900
++++ b/storage/innodb_plugin/handler/innodb_patch_info.h	2010-07-14 16:40:16.164323927 +0900
+@@ -47,5 +47,6 @@
+ {"innodb_fast_checksum","Using the checksum on 32bit-unit calculation","incompatible for unpatched ver.","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_files_extend","allow >4GB transaction log files, and can vary universal page size of datafiles","incompatible for unpatched ver.","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_sys_tables_sys_indexes","Expose InnoDB SYS_TABLES and SYS_INDEXES schema tables","","http://www.percona.com/docs/wiki/percona-xtradb"},
++{"innodb_buffer_pool_shm","Put buffer pool contents to shared memory segment and reuse it at clean restart [experimental]","","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {NULL, NULL, NULL, NULL}
+ };
+diff -ruN a/storage/innodb_plugin/include/buf0buf.h b/storage/innodb_plugin/include/buf0buf.h
+--- a/storage/innodb_plugin/include/buf0buf.h	2010-07-14 16:33:23.823323393 +0900
++++ b/storage/innodb_plugin/include/buf0buf.h	2010-07-14 16:40:16.166323436 +0900
+@@ -36,6 +36,7 @@
+ #include "ut0rbt.h"
+ #ifndef UNIV_HOTBACKUP
+ #include "os0proc.h"
++#include "srv0srv.h"
+ 
+ /** @name Modes for buf_page_get_gen */
+ /* @{ */
+@@ -1302,7 +1303,10 @@
+ /**********************************************************************//**
+ Compute the hash fold value for blocks in buf_pool->zip_hash. */
+ /* @{ */
+-#define BUF_POOL_ZIP_FOLD_PTR(ptr) ((ulint) (ptr) / UNIV_PAGE_SIZE)
++/* the fold should be relative when srv_buffer_pool_shm_key is enabled */
++#define BUF_POOL_ZIP_FOLD_PTR(ptr) (!srv_buffer_pool_shm_key\
++					?((ulint) (ptr) / UNIV_PAGE_SIZE)\
++					:((ulint) ((byte*)ptr - (byte*)(buf_pool->chunks->blocks->frame)) / UNIV_PAGE_SIZE))
+ #define BUF_POOL_ZIP_FOLD(b) BUF_POOL_ZIP_FOLD_PTR((b)->frame)
+ #define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b))
+ /* @} */
+diff -ruN a/storage/innodb_plugin/include/hash0hash.h b/storage/innodb_plugin/include/hash0hash.h
+--- a/storage/innodb_plugin/include/hash0hash.h	2010-06-04 00:49:59.000000000 +0900
++++ b/storage/innodb_plugin/include/hash0hash.h	2010-07-14 16:40:16.168323262 +0900
+@@ -49,6 +49,28 @@
+ hash_create(
+ /*========*/
+ 	ulint	n);	/*!< in: number of array cells */
++
++/*************************************************************//**
++*/
++UNIV_INTERN
++ulint
++hash_create_needed(
++/*===============*/
++	ulint	n);
++
++UNIV_INTERN
++void
++hash_create_init(
++/*=============*/
++	hash_table_t*	table,
++	ulint		n);
++
++UNIV_INTERN
++void
++hash_create_reuse(
++/*==============*/
++	hash_table_t*	table);
++
+ #ifndef UNIV_HOTBACKUP
+ /*************************************************************//**
+ Creates a mutex array to protect a hash table. */
+@@ -327,6 +349,33 @@
+ 		}\
+ 	}\
+ } while (0)
++
++/********************************************************************//**
++Align nodes with moving location.*/
++#define HASH_OFFSET(TABLE, NODE_TYPE, PTR_NAME, FADDR, FOFFSET, BOFFSET) \
++do {\
++	ulint		i2222;\
++	ulint		cell_count2222;\
++\
++	cell_count2222 = hash_get_n_cells(TABLE);\
++\
++	for (i2222 = 0; i2222 < cell_count2222; i2222++) {\
++		NODE_TYPE*	node2222;\
++\
++		if ((TABLE)->array[i2222].node) \
++			(TABLE)->array[i2222].node = (void*)((byte*)(TABLE)->array[i2222].node \
++			+ (((TABLE)->array[i2222].node > (void*)FADDR)?FOFFSET:BOFFSET));\
++		node2222 = HASH_GET_FIRST((TABLE), i2222);\
++\
++		while (node2222) {\
++			if (node2222->PTR_NAME) \
++				node2222->PTR_NAME = (void*)((byte*)(node2222->PTR_NAME) \
++				+ ((((void*)node2222->PTR_NAME) > (void*)FADDR)?FOFFSET:BOFFSET));\
++\
++			node2222 = node2222->PTR_NAME;\
++		}\
++	}\
++} while (0)
+ 
+ /************************************************************//**
+ Gets the mutex index for a fold value in a hash table.
+diff -ruN a/storage/innodb_plugin/include/os0proc.h b/storage/innodb_plugin/include/os0proc.h
+--- a/storage/innodb_plugin/include/os0proc.h	2010-06-04 00:49:59.000000000 +0900
++++ b/storage/innodb_plugin/include/os0proc.h	2010-07-14 16:40:16.169321536 +0900
+@@ -32,6 +32,11 @@
+ #ifdef UNIV_LINUX
+ #include <sys/ipc.h>
+ #include <sys/shm.h>
++#else
++# if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H
++#include <sys/ipc.h>
++#include <sys/shm.h>
++# endif
+ #endif
+ 
+ typedef void*			os_process_t;
+@@ -70,6 +75,29 @@
+ 	ulint	size);			/*!< in: size returned by
+ 					os_mem_alloc_large() */
+ 
++
++/****************************************************************//**
++Allocates or attaches and reuses shared memory segment.
++The content is not cleared automatically.
++ at return	allocated memory */
++UNIV_INTERN
++void*
++os_shm_alloc(
++/*=========*/
++	ulint*	n,			/*!< in/out: number of bytes */
++	uint	key,
++	ibool*	is_new);
++
++/****************************************************************//**
++Detach shared memory segment. */
++UNIV_INTERN
++void
++os_shm_free(
++/*========*/
++	void	*ptr,			/*!< in: pointer returned by
++					os_shm_alloc() */
++	ulint	size);			/*!< in: size returned by
++					os_shm_alloc() */
+ #ifndef UNIV_NONINL
+ #include "os0proc.ic"
+ #endif
+diff -ruN a/storage/innodb_plugin/include/srv0srv.h b/storage/innodb_plugin/include/srv0srv.h
+--- a/storage/innodb_plugin/include/srv0srv.h	2010-07-14 16:32:49.695323045 +0900
++++ b/storage/innodb_plugin/include/srv0srv.h	2010-07-14 16:40:16.171325784 +0900
+@@ -156,6 +156,10 @@
+ extern ulint	srv_mem_pool_size;
+ extern ulint	srv_lock_table_size;
+ 
++extern uint	srv_buffer_pool_shm_key;
++extern ibool	srv_buffer_pool_shm_is_reused;
++extern ibool	srv_buffer_pool_shm_checksum;
++
+ extern ibool	srv_thread_concurrency_timer_based;
+ 
+ extern ulint	srv_n_file_io_threads;
+diff -ruN a/storage/innodb_plugin/include/ut0lst.h b/storage/innodb_plugin/include/ut0lst.h
+--- a/storage/innodb_plugin/include/ut0lst.h	2010-06-04 00:49:59.000000000 +0900
++++ b/storage/innodb_plugin/include/ut0lst.h	2010-07-14 16:40:16.172321547 +0900
+@@ -257,5 +257,48 @@
+ 	ut_a(ut_list_node_313 == NULL);					\
+ } while (0)
+ 
++/********************************************************************//**
++Align nodes with moving location.
++ at param NAME		the name of the list
++ at param TYPE		node type
++ at param BASE		base node (not a pointer to it)
++ at param OFFSET		offset moved */
++#define UT_LIST_OFFSET(NAME, TYPE, BASE, FADDR, FOFFSET, BOFFSET)	\
++do {									\
++	ulint	ut_list_i_313;						\
++	TYPE*	ut_list_node_313;					\
++									\
++	if ((BASE).start)						\
++		(BASE).start = (void*)((byte*)((BASE).start)			\
++			+ (((void*)((BASE).start) > (void*)FADDR)?FOFFSET:BOFFSET));\
++	if ((BASE).end)							\
++		(BASE).end   = (void*)((byte*)((BASE).end)			\
++			+ (((void*)((BASE).end) > (void*)FADDR)?FOFFSET:BOFFSET));\
++									\
++	ut_list_node_313 = (BASE).start;				\
++									\
++	for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) {		\
++		ut_a(ut_list_node_313);					\
++		if ((ut_list_node_313->NAME).prev)			\
++			(ut_list_node_313->NAME).prev = (void*)((byte*)((ut_list_node_313->NAME).prev)\
++				+ (((void*)((ut_list_node_313->NAME).prev) > (void*)FADDR)?FOFFSET:BOFFSET));\
++		if ((ut_list_node_313->NAME).next)			\
++			(ut_list_node_313->NAME).next =	(void*)((byte*)((ut_list_node_313->NAME).next)\
++				+ (((void*)((ut_list_node_313->NAME).next)> (void*)FADDR)?FOFFSET:BOFFSET));\
++		ut_list_node_313 = (ut_list_node_313->NAME).next;	\
++	}								\
++									\
++	ut_a(ut_list_node_313 == NULL);					\
++									\
++	ut_list_node_313 = (BASE).end;					\
++									\
++	for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) {		\
++		ut_a(ut_list_node_313);					\
++		ut_list_node_313 = (ut_list_node_313->NAME).prev;	\
++	}								\
++									\
++	ut_a(ut_list_node_313 == NULL);					\
++} while (0)
++
+ #endif
+ 
+diff -ruN a/storage/innodb_plugin/log/log0recv.c b/storage/innodb_plugin/log/log0recv.c
+--- a/storage/innodb_plugin/log/log0recv.c	2010-10-01 15:25:27.106299166 +0900
++++ b/storage/innodb_plugin/log/log0recv.c	2010-10-01 15:26:33.689261436 +0900
+@@ -2899,6 +2899,7 @@
+ /*==========================*/
+ {
+ 	ut_a(!recv_needed_recovery);
++	ut_a(!srv_buffer_pool_shm_is_reused);
+ 
+ 	recv_needed_recovery = TRUE;
+ 
+diff -ruN a/storage/innodb_plugin/os/os0proc.c b/storage/innodb_plugin/os/os0proc.c
+--- a/storage/innodb_plugin/os/os0proc.c	2010-06-04 00:49:59.000000000 +0900
++++ b/storage/innodb_plugin/os/os0proc.c	2010-07-14 16:40:16.174322953 +0900
+@@ -229,3 +229,173 @@
+ 	}
+ #endif
+ }
++
++/****************************************************************//**
++Allocates or attaches and reuses shared memory segment.
++The content is not cleared automatically.
++ at return	allocated memory */
++UNIV_INTERN
++void*
++os_shm_alloc(
++/*=========*/
++	ulint*	n,			/*!< in/out: number of bytes */
++	uint	key,
++	ibool*	is_new)
++{
++	void*	ptr;
++#if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H
++	ulint	size;
++	int	shmid;
++
++	*is_new = FALSE;
++	fprintf(stderr,
++		"InnoDB: The shared memory segment containing the buffer pool is: key  %#x (%d).\n",
++		key, key);
++# if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
++	if (!os_use_large_pages || !os_large_page_size) {
++		goto skip;
++	}
++
++	/* Align block size to os_large_page_size */
++	ut_ad(ut_is_2pow(os_large_page_size));
++	size = ut_2pow_round(*n + (os_large_page_size - 1),
++			     os_large_page_size);
++
++	shmid = shmget((key_t)key, (size_t)size,
++			IPC_CREAT | IPC_EXCL | SHM_HUGETLB | SHM_R | SHM_W);
++	if (shmid < 0) {
++		if (errno == EEXIST) {
++			fprintf(stderr,
++				"InnoDB: HugeTLB: The shared memory segment exists.\n");
++			shmid = shmget((key_t)key, (size_t)size,
++					SHM_HUGETLB | SHM_R | SHM_W);
++			if (shmid < 0) {
++				fprintf(stderr,
++					"InnoDB: HugeTLB: Warning: Failed to allocate %lu bytes. (reuse) errno %d\n",
++					size, errno);
++				goto skip;
++			} else {
++				fprintf(stderr,
++					"InnoDB: HugeTLB: The existent shared memory segment is used.\n");
++			}
++		} else {
++			fprintf(stderr,
++				"InnoDB: HugeTLB: Warning: Failed to allocate %lu bytes. (new) errno %d\n",
++				size, errno);
++			goto skip;
++		}
++	} else {
++		*is_new = TRUE;
++		fprintf(stderr,
++			"InnoDB: HugeTLB: A new shared memory segment has been created .\n");
++	}
++
++	ptr = shmat(shmid, NULL, 0);
++	if (ptr == (void *)-1) {
++		fprintf(stderr,
++			"InnoDB: HugeTLB: Warning: Failed to attach shared memory segment, errno %d\n",
++			errno);
++		ptr = NULL;
++	}
++
++	if (ptr) {
++		*n = size;
++		os_fast_mutex_lock(&ut_list_mutex);
++		ut_total_allocated_memory += size;
++		os_fast_mutex_unlock(&ut_list_mutex);
++		UNIV_MEM_ALLOC(ptr, size);
++		return(ptr);
++	}
++skip:
++	*is_new = FALSE;
++# endif /* HAVE_LARGE_PAGES && defined UNIV_LINUX */
++# ifdef HAVE_GETPAGESIZE
++	size = getpagesize();
++# else
++	size = UNIV_PAGE_SIZE;
++# endif
++	/* Align block size to system page size */
++	ut_ad(ut_is_2pow(size));
++	size = *n = ut_2pow_round(*n + (size - 1), size);
++
++	shmid = shmget((key_t)key, (size_t)size,
++			IPC_CREAT | IPC_EXCL | SHM_R | SHM_W);
++	if (shmid < 0) {
++		if (errno == EEXIST) {
++			fprintf(stderr,
++				"InnoDB: A shared memory segment containing the buffer pool seems to already exist.\n");
++			shmid = shmget((key_t)key, (size_t)size,
++					SHM_R | SHM_W);
++			if (shmid < 0) {
++				fprintf(stderr,
++					"InnoDB: Warning: Failed to allocate %lu bytes. (reuse) errno %d\n",
++					size, errno);
++				ptr = NULL;
++				goto end;
++			} else {
++				fprintf(stderr,
++					"InnoDB: The existent shared memory segment is used.\n");
++			}
++		} else {
++			fprintf(stderr,
++				"InnoDB: Warning: Failed to allocate %lu bytes. (new) errno %d\n",
++				size, errno);
++			ptr = NULL;
++			goto end;
++		}
++	} else {
++		*is_new = TRUE;
++		fprintf(stderr,
++			"InnoDB: A new shared memory segment has been created.\n");
++	}
++
++	ptr = shmat(shmid, NULL, 0);
++	if (ptr == (void *)-1) {
++		fprintf(stderr,
++			"InnoDB: Warning: Failed to attach shared memory segment, errno %d\n",
++			errno);
++		ptr = NULL;
++	}
++
++	if (ptr) {
++		*n = size;
++		os_fast_mutex_lock(&ut_list_mutex);
++		ut_total_allocated_memory += size;
++		os_fast_mutex_unlock(&ut_list_mutex);
++		UNIV_MEM_ALLOC(ptr, size);
++	}
++end:
++#else /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
++	fprintf(stderr, "InnoDB: shared memory segment is not supported.\n");
++	ptr = NULL;
++#endif /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
++	return(ptr);
++}
++
++/****************************************************************//**
++Detach shared memory segment. */
++UNIV_INTERN
++void
++os_shm_free(
++/*========*/
++	void	*ptr,			/*!< in: pointer returned by
++					os_shm_alloc() */
++	ulint	size)			/*!< in: size returned by
++					os_shm_alloc() */
++{
++	os_fast_mutex_lock(&ut_list_mutex);
++	ut_a(ut_total_allocated_memory >= size);
++	os_fast_mutex_unlock(&ut_list_mutex);
++
++#if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H
++	if (!shmdt(ptr)) {
++		os_fast_mutex_lock(&ut_list_mutex);
++		ut_a(ut_total_allocated_memory >= size);
++		ut_total_allocated_memory -= size;
++		os_fast_mutex_unlock(&ut_list_mutex);
++		UNIV_MEM_FREE(ptr, size);
++	}
++#else /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
++	fprintf(stderr, "InnoDB: shared memory segment is not supported.\n");
++#endif /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
++}
+diff -ruN a/storage/innodb_plugin/srv/srv0srv.c b/storage/innodb_plugin/srv/srv0srv.c
+--- a/storage/innodb_plugin/srv/srv0srv.c	2010-07-14 16:33:23.848391648 +0900
++++ b/storage/innodb_plugin/srv/srv0srv.c	2010-07-14 16:40:16.177323553 +0900
+@@ -211,6 +211,11 @@
+ UNIV_INTERN ulint	srv_mem_pool_size	= ULINT_MAX;
+ UNIV_INTERN ulint	srv_lock_table_size	= ULINT_MAX;
+ 
++/* key value for shm */
++UNIV_INTERN uint	srv_buffer_pool_shm_key	= 0;
++UNIV_INTERN ibool	srv_buffer_pool_shm_is_reused = FALSE;
++UNIV_INTERN ibool	srv_buffer_pool_shm_checksum = TRUE;
++
+ /* This parameter is deprecated. Use srv_n_io_[read|write]_threads
+ instead. */
+ UNIV_INTERN ulint	srv_n_file_io_threads	= ULINT_MAX;
+diff -ruN a/storage/innodb_plugin/srv/srv0start.c b/storage/innodb_plugin/srv/srv0start.c
+--- a/storage/innodb_plugin/srv/srv0start.c	2010-07-14 16:33:23.851391514 +0900
++++ b/storage/innodb_plugin/srv/srv0start.c	2010-07-14 16:40:16.180321173 +0900
+@@ -1744,6 +1744,8 @@
+ 		Note that this is not as heavy weight as it seems. At
+ 		this point there will be only ONE page in the buf_LRU
+ 		and there must be no page in the buf_flush list. */
++		/* buffer_pool_shm should not be reused when recovery was needed. */
++		if (!srv_buffer_pool_shm_is_reused)
+ 		buf_pool_invalidate();
+ 
+ 		/* We always try to do a recovery, even if the database had
diff --git a/mysql-innodb_deadlock_count.patch b/mysql-innodb_deadlock_count.patch
index 079e36b..ecb6c84 100644
--- a/mysql-innodb_deadlock_count.patch
+++ b/mysql-innodb_deadlock_count.patch
@@ -31,7 +31,7 @@ diff -ruN a/storage/innodb_plugin/include/lock0lock.h b/storage/innodb_plugin/in
 diff -ruN a/storage/innodb_plugin/include/srv0srv.h b/storage/innodb_plugin/include/srv0srv.h
 --- a/storage/innodb_plugin/include/srv0srv.h	2010-08-10 15:32:14.478241628 +0400
 +++ b/storage/innodb_plugin/include/srv0srv.h	2010-08-10 15:32:14.936991959 +0400
-@@ -673,6 +673,7 @@
+@@ -675,6 +675,7 @@
  	ulint innodb_buffer_pool_write_requests;/*!< srv_buf_pool_write_requests */
  	ulint innodb_buffer_pool_read_ahead;	/*!< srv_read_ahead */
  	ulint innodb_buffer_pool_read_ahead_evicted;/*!< srv_read_ahead evicted*/
@@ -53,7 +53,7 @@ diff -ruN a/storage/innodb_plugin/lock/lock0lock.c b/storage/innodb_plugin/lock/
 diff -ruN a/storage/innodb_plugin/srv/srv0srv.c b/storage/innodb_plugin/srv/srv0srv.c
 --- a/storage/innodb_plugin/srv/srv0srv.c	2010-08-10 15:32:14.478241628 +0400
 +++ b/storage/innodb_plugin/srv/srv0srv.c	2010-08-10 15:32:14.936991959 +0400
-@@ -438,7 +438,7 @@
+@@ -440,7 +440,7 @@
  static ulint	srv_n_rows_updated_old		= 0;
  static ulint	srv_n_rows_deleted_old		= 0;
  static ulint	srv_n_rows_read_old		= 0;
@@ -62,7 +62,7 @@ diff -ruN a/storage/innodb_plugin/srv/srv0srv.c b/storage/innodb_plugin/srv/srv0
  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;
-@@ -2149,6 +2149,8 @@
+@@ -2151,6 +2151,8 @@
  		= UT_LIST_GET_LEN(buf_pool->flush_list);
  	export_vars.innodb_buffer_pool_pages_free
  		= UT_LIST_GET_LEN(buf_pool->free);
diff --git a/mysql-innodb_fast_shutdown.patch b/mysql-innodb_fast_shutdown.patch
new file mode 100644
index 0000000..22ba723
--- /dev/null
+++ b/mysql-innodb_fast_shutdown.patch
@@ -0,0 +1,241 @@
+# name       : innodb_fast_shutdown
+# introduced : 13
+# maintainer : Alexey
+#
+# Shutting down XtraDB takes uninterruptible sleep()s up to 10
+# seconds, even when there is no actual work to do during shutdown.
+#
+# This patch removes most such delays during shutdown, as found using
+# PMP. This makes standard test run very close in speed to with
+# --loose-innodb-fast-shutdown=2, and greatly speeds up running the test
+# suite.
+#
+# The patch also implements os_event_wait_time() for POSIX systems.
+diff -ruN /dev/null b/COPYING.innodb_fast_shutdown
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ b/COPYING.innodb_fast_shutdown	2010-11-16 21:37:51.000000000 +0300
+@@ -0,0 +1,10 @@
++Copyright (c) 2010, Kristian Nielsen
++All rights reserved.
++
++Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
++
++    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
++    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
++    * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+diff -ruN a/storage/innodb_plugin/include/os0sync.h b/storage/innodb_plugin/include/os0sync.h
+--- a/storage/innodb_plugin/include/os0sync.h	2010-11-16 21:33:00.000000000 +0300
++++ b/storage/innodb_plugin/include/os0sync.h	2010-11-16 21:34:06.000000000 +0300
+@@ -189,14 +189,14 @@
+ 
+ /**********************************************************//**
+ Waits for an event object until it is in the signaled state or
+-a timeout is exceeded. In Unix the timeout is always infinite.
++a timeout is exceeded.
+ @return	0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
+ UNIV_INTERN
+ ulint
+ os_event_wait_time(
+ /*===============*/
+ 	os_event_t	event,	/*!< in: event to wait */
+-	ulint		time);	/*!< in: timeout in microseconds, or
++	ulint		wtime);	/*!< in: timeout in microseconds, or
+ 				OS_SYNC_INFINITE_TIME */
+ #ifdef __WIN__
+ /**********************************************************//**
+diff -ruN a/storage/innodb_plugin/include/srv0srv.h b/storage/innodb_plugin/include/srv0srv.h
+--- a/storage/innodb_plugin/include/srv0srv.h	2010-11-16 21:33:00.000000000 +0300
++++ b/storage/innodb_plugin/include/srv0srv.h	2010-11-16 21:34:06.000000000 +0300
+@@ -57,6 +57,9 @@
+ thread starts running */
+ extern os_event_t	srv_lock_timeout_thread_event;
+ 
++/* This event is set at shutdown to wakeup threads from sleep */
++extern os_event_t	srv_shutdown_event;
++
+ /* If the last data file is auto-extended, we add this many pages to it
+ at a time */
+ #define SRV_AUTO_EXTEND_INCREMENT	\
+diff -ruN a/storage/innodb_plugin/log/log0log.c b/storage/innodb_plugin/log/log0log.c
+--- a/storage/innodb_plugin/log/log0log.c	2010-11-16 21:33:00.000000000 +0300
++++ b/storage/innodb_plugin/log/log0log.c	2010-11-16 21:34:06.000000000 +0300
+@@ -3103,6 +3103,7 @@
+ 	algorithm only works if the server is idle at shutdown */
+ 
+ 	srv_shutdown_state = SRV_SHUTDOWN_CLEANUP;
++	os_event_set(srv_shutdown_event);
+ loop:
+ 	os_thread_sleep(100000);
+ 
+diff -ruN a/storage/innodb_plugin/os/os0sync.c b/storage/innodb_plugin/os/os0sync.c
+--- a/storage/innodb_plugin/os/os0sync.c	2010-11-16 21:33:00.000000000 +0300
++++ b/storage/innodb_plugin/os/os0sync.c	2010-11-16 21:34:06.000000000 +0300
+@@ -31,6 +31,9 @@
+ 
+ #ifdef __WIN__
+ #include <windows.h>
++#else
++#include <sys/time.h>
++#include <time.h>
+ #endif
+ 
+ #include "ut0mem.h"
+@@ -407,14 +410,14 @@
+ 
+ /**********************************************************//**
+ Waits for an event object until it is in the signaled state or
+-a timeout is exceeded. In Unix the timeout is always infinite.
++a timeout is exceeded.
+ @return	0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */
+ UNIV_INTERN
+ ulint
+ os_event_wait_time(
+ /*===============*/
+ 	os_event_t	event,	/*!< in: event to wait */
+-	ulint		time)	/*!< in: timeout in microseconds, or
++	ulint		wtime)	/*!< in: timeout in microseconds, or
+ 				OS_SYNC_INFINITE_TIME */
+ {
+ #ifdef __WIN__
+@@ -422,8 +425,8 @@
+ 
+ 	ut_a(event);
+ 
+-	if (time != OS_SYNC_INFINITE_TIME) {
+-		err = WaitForSingleObject(event->handle, (DWORD) time / 1000);
++	if (wtime != OS_SYNC_INFINITE_TIME) {
++		err = WaitForSingleObject(event->handle, (DWORD) wtime / 1000);
+ 	} else {
+ 		err = WaitForSingleObject(event->handle, INFINITE);
+ 	}
+@@ -439,13 +442,47 @@
+ 		return(1000000); /* dummy value to eliminate compiler warn. */
+ 	}
+ #else
+-	UT_NOT_USED(time);
++	int		err;
++	int		ret = 0;
++	ulint		tmp;
++	ib_int64_t	old_count;
++	struct timeval	tv_start;
++	struct timespec	timeout;
++
++	if (wtime == OS_SYNC_INFINITE_TIME) {
++		os_event_wait(event);
++		return 0;
++	}
++
++	/* Compute the absolute point in time at which to time out. */
++	gettimeofday(&tv_start, NULL);
++	tmp = tv_start.tv_usec + wtime;
++	timeout.tv_sec = tv_start.tv_sec + (tmp / 1000000);
++	timeout.tv_nsec = (tmp % 1000000) * 1000;
++
++	os_fast_mutex_lock(&(event->os_mutex));
++	old_count = event->signal_count;
+ 
+-	/* In Posix this is just an ordinary, infinite wait */
++	for (;;) {
++		if (event->is_set == TRUE || event->signal_count != old_count)
++			break;
++
++		err = pthread_cond_timedwait(&(event->cond_var),
++					     &(event->os_mutex), &timeout);
++		if (err == ETIMEDOUT) {
++			ret = OS_SYNC_TIME_EXCEEDED;
++			break;
++		}
++	}
+ 
+-	os_event_wait(event);
++	os_fast_mutex_unlock(&(event->os_mutex));
++
++	if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
++
++		os_thread_exit(NULL);
++	}
+ 
+-	return(0);
++	return ret;
+ #endif
+ }
+ 
+diff -ruN a/storage/innodb_plugin/srv/srv0srv.c b/storage/innodb_plugin/srv/srv0srv.c
+--- a/storage/innodb_plugin/srv/srv0srv.c	2010-11-16 21:33:00.000000000 +0300
++++ b/storage/innodb_plugin/srv/srv0srv.c	2010-11-16 21:34:06.000000000 +0300
+@@ -709,6 +709,8 @@
+ 
+ UNIV_INTERN os_event_t	srv_lock_timeout_thread_event;
+ 
++UNIV_INTERN os_event_t	srv_shutdown_event;
++
+ UNIV_INTERN srv_sys_t*	srv_sys	= NULL;
+ 
+ /* padding to prevent other memory update hotspots from residing on
+@@ -1014,6 +1016,7 @@
+ 	}
+ 
+ 	srv_lock_timeout_thread_event = os_event_create(NULL);
++	srv_shutdown_event = os_event_create(NULL);
+ 
+ 	for (i = 0; i < SRV_MASTER + 1; i++) {
+ 		srv_n_threads_active[i] = 0;
+@@ -2241,7 +2244,7 @@
+ 	/* Wake up every 5 seconds to see if we need to print
+ 	monitor information. */
+ 
+-	os_thread_sleep(5000000);
++	os_event_wait_time(srv_shutdown_event, 5000000);
+ 
+ 	current_time = time(NULL);
+ 
+@@ -2383,7 +2386,7 @@
+ 	/* When someone is waiting for a lock, we wake up every second
+ 	and check if a timeout has passed for a lock wait */
+ 
+-	os_thread_sleep(1000000);
++	os_event_wait_time(srv_shutdown_event, 1000000);
+ 
+ 	srv_lock_timeout_active = TRUE;
+ 
+@@ -2548,7 +2551,7 @@
+ 
+ 	fflush(stderr);
+ 
+-	os_thread_sleep(1000000);
++	os_event_wait_time(srv_shutdown_event, 1000000);
+ 
+ 	if (srv_shutdown_state < SRV_SHUTDOWN_CLEANUP) {
+ 
+@@ -2592,7 +2595,7 @@
+ 	last_dump_time = time(NULL);
+ 
+ loop:
+-	os_thread_sleep(5000000);
++	os_event_wait_time(srv_shutdown_event, 5000000);
+ 
+ 	if (srv_shutdown_state >= SRV_SHUTDOWN_CLEANUP) {
+ 		goto exit_func;
+@@ -2775,7 +2778,7 @@
+ 		if (!skip_sleep) {
+ 		if (next_itr_time > cur_time) {
+ 
+-			os_thread_sleep(ut_min(1000000, (next_itr_time - cur_time) * 1000));
++			os_event_wait_time(srv_shutdown_event, ut_min(1000000, (next_itr_time - cur_time) * 1000));
+ 			srv_main_sleeps++;
+ 
+ 			/*
+@@ -3482,9 +3485,10 @@
+ 		mutex_exit(&kernel_mutex);
+ 
+ 		sleep_ms = 10;
++		os_event_reset(srv_shutdown_event);
+ 	}
+ 
+-	os_thread_sleep( sleep_ms * 1000 );
++	os_event_wait_time(srv_shutdown_event, sleep_ms * 1000);
+ 
+ 	history_len = trx_sys->rseg_history_len;
+ 	if (history_len > 1000)
diff --git a/mysql-innodb_fix_misc.patch b/mysql-innodb_fix_misc.patch
index d95d662..5165bee 100644
--- a/mysql-innodb_fix_misc.patch
+++ b/mysql-innodb_fix_misc.patch
@@ -2,13 +2,308 @@
 # 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!
+diff -ruN a/storage/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c
+--- a/storage/innodb_plugin/buf/buf0buf.c	2011-02-21 20:31:57.781983359 +0900
++++ b/storage/innodb_plugin/buf/buf0buf.c	2011-02-21 20:32:39.523946003 +0900
+@@ -3224,6 +3224,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;
+diff -ruN a/storage/innodb_plugin/buf/buf0flu.c b/storage/innodb_plugin/buf/buf0flu.c
+--- a/storage/innodb_plugin/buf/buf0flu.c	2011-02-21 20:31:57.784983260 +0900
++++ b/storage/innodb_plugin/buf/buf0flu.c	2011-02-21 20:32:39.524915732 +0900
+@@ -367,7 +367,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);
+ 	}
+@@ -406,6 +406,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);
+diff -ruN a/storage/innodb_plugin/buf/buf0lru.c b/storage/innodb_plugin/buf/buf0lru.c
+--- a/storage/innodb_plugin/buf/buf0lru.c	2011-02-21 20:31:57.451983310 +0900
++++ b/storage/innodb_plugin/buf/buf0lru.c	2011-02-21 20:32:39.526949096 +0900
+@@ -530,6 +530,30 @@
+ 	}
+ }
+ 
++/******************************************************************//**
++*/
++UNIV_INTERN
++void
++buf_LRU_mark_space_was_deleted(
++/*===========================*/
++	ulint	id)	/*!< in: space id */
++{
++	buf_page_t*	bpage;
++
++	mutex_enter(&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(&LRU_list_mutex);
++}
++
+ /********************************************************************//**
+ Insert a compressed block into buf_pool->zip_clean in the LRU order. */
+ UNIV_INTERN
+@@ -1498,6 +1522,10 @@
+ 		return(BUF_LRU_NOT_FREED);
+ 	}
+ 
++	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 */
+diff -ruN a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c
+--- a/storage/innodb_plugin/fil/fil0fil.c	2011-02-21 20:31:57.838984412 +0900
++++ b/storage/innodb_plugin/fil/fil0fil.c	2011-02-21 20:32:39.528914782 +0900
+@@ -242,6 +242,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
+@@ -816,7 +817,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 || srv_lazy_drop_table);
+ 	ut_a(node->n_pending_flushes == 0);
+ 	ut_a(node->modification_counter == node->flush_counter);
+ 
+@@ -1028,7 +1029,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 || srv_lazy_drop_table);
+ 
+ 	if (node->open) {
+ 		/* We fool the assertion in fil_node_close_file() to think
+@@ -1549,6 +1550,7 @@
+ 	fil_system = mem_zalloc(sizeof(fil_system_t));
+ 
+ 	mutex_create(&fil_system->mutex, SYNC_ANY_LATCH);
++	mutex_create(&fil_system->file_extend_mutex, SYNC_OUTER_ANY_LATCH);
+ 
+ 	fil_system->spaces = hash_create(hash_size);
+ 	fil_system->name_hash = hash_create(hash_size);
+@@ -2295,7 +2297,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); */
+ 
+@@ -4348,6 +4354,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);
+@@ -4359,6 +4369,7 @@
+ 		*actual_size = space->size;
+ 
+ 		mutex_exit(&fil_system->mutex);
++		mutex_exit(&fil_system->file_extend_mutex);
+ 
+ 		return(TRUE);
+ 	}
+@@ -4391,6 +4402,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,
+@@ -4400,8 +4413,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;
+@@ -4447,6 +4462,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);
+ 
+@@ -4811,6 +4827,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, trx);
++			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 */
+ 
+@@ -4940,10 +4972,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) {
+@@ -5043,6 +5089,7 @@
+ 	fil_node_t*	fil_node;
+ 	void*		message;
+ 	ulint		type;
++	ulint		space_id = 0;
+ 
+ 	ut_ad(fil_validate());
+ 
+@@ -5050,7 +5097,7 @@
+ 		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);
+ #else
+ 		ret = 0; /* Eliminate compiler warning */
+ 		ut_error;
+@@ -5059,7 +5106,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, NULL);
++		return;
+ 	}
+ 
+ 	ut_a(ret);
 diff -ruN a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
 --- a/storage/innodb_plugin/handler/ha_innodb.cc	2010-08-27 16:50:59.626327847 +0900
 +++ b/storage/innodb_plugin/handler/ha_innodb.cc	2010-08-27 16:55:20.281021252 +0900
-@@ -11783,7 +11783,7 @@
+@@ -11685,6 +11685,12 @@
+   "except for the deletion.",
+   NULL, NULL, 0, 0, 1, 0);
+ 
++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),
+@@ -11774,6 +11780,7 @@
+   MYSQL_SYSVAR(auto_lru_dump),
+   MYSQL_SYSVAR(use_purge_thread),
+   MYSQL_SYSVAR(pass_corrupt_table),
++  MYSQL_SYSVAR(lazy_drop_table),
+   NULL
+ };
+ 
+@@ -11783,7 +11790,7 @@
    &innobase_storage_engine,
    innobase_hton_name,
    "Innobase Oy",
@@ -17,6 +312,99 @@ diff -ruN a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/h
    PLUGIN_LICENSE_GPL,
    innobase_init, /* Plugin Init */
    NULL, /* Plugin Deinit */
+diff -ruN a/storage/innodb_plugin/include/buf0buf.h b/storage/innodb_plugin/include/buf0buf.h
+--- a/storage/innodb_plugin/include/buf0buf.h	2011-02-21 20:31:57.863983187 +0900
++++ b/storage/innodb_plugin/include/buf0buf.h	2011-02-21 20:32:39.537912716 +0900
+@@ -1156,6 +1156,7 @@
+ 					0 if the block was never accessed
+ 					in the buffer pool */
+ 	/* @} */
++	ibool		space_was_being_deleted;
+ 	ibool		is_corrupt;
+ # ifdef UNIV_DEBUG_FILE_ACCESSES
+ 	ibool		file_page_was_freed;
+diff -ruN a/storage/innodb_plugin/include/buf0buf.ic b/storage/innodb_plugin/include/buf0buf.ic
+--- a/storage/innodb_plugin/include/buf0buf.ic	2011-02-21 20:31:57.725983812 +0900
++++ b/storage/innodb_plugin/include/buf0buf.ic	2011-02-21 20:32:39.538913061 +0900
+@@ -384,6 +384,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;
+ }
+ 
+ /*********************************************************************//**
+diff -ruN a/storage/innodb_plugin/include/buf0lru.h b/storage/innodb_plugin/include/buf0lru.h
+--- a/storage/innodb_plugin/include/buf0lru.h	2011-02-21 20:31:57.480924269 +0900
++++ b/storage/innodb_plugin/include/buf0lru.h	2011-02-21 20:32:39.539912965 +0900
+@@ -84,6 +84,13 @@
+ buf_LRU_invalidate_tablespace(
+ /*==========================*/
+ 	ulint	id);	/*!< in: space id */
++/******************************************************************//**
++*/
++UNIV_INTERN
++void
++buf_LRU_mark_space_was_deleted(
++/*===========================*/
++	ulint	id);	/*!< in: space id */
+ /********************************************************************//**
+ Insert a compressed block into buf_pool->zip_clean in the LRU order. */
+ UNIV_INTERN
+diff -ruN a/storage/innodb_plugin/include/os0file.h b/storage/innodb_plugin/include/os0file.h
+--- a/storage/innodb_plugin/include/os0file.h	2011-02-21 20:31:57.870987755 +0900
++++ b/storage/innodb_plugin/include/os0file.h	2011-02-21 20:32:39.540912738 +0900
+@@ -657,6 +657,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
+@@ -717,7 +718,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
+ 
+ /**********************************************************************//**
+@@ -739,7 +741,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 */
+diff -ruN a/storage/innodb_plugin/include/srv0srv.h b/storage/innodb_plugin/include/srv0srv.h
+--- a/storage/innodb_plugin/include/srv0srv.h	2011-02-21 20:31:57.824983518 +0900
++++ b/storage/innodb_plugin/include/srv0srv.h	2011-02-21 20:32:39.541913033 +0900
+@@ -235,6 +235,8 @@
+ 
+ extern ulint	srv_extra_rsegments;
+ extern ulint	srv_dict_size_limit;
++
++extern ulint	srv_lazy_drop_table;
+ /*-------------------------------------------*/
+ 
+ extern ulint	srv_n_rows_inserted;
+diff -ruN a/storage/innodb_plugin/include/sync0sync.h b/storage/innodb_plugin/include/sync0sync.h
+--- a/storage/innodb_plugin/include/sync0sync.h	2011-02-21 20:31:57.382982949 +0900
++++ b/storage/innodb_plugin/include/sync0sync.h	2011-02-21 20:32:39.543913340 +0900
+@@ -496,6 +496,7 @@
+ #define	SYNC_BUF_POOL		150
+ #define SYNC_BUF_FLUSH_LIST	149
+ #define SYNC_DOUBLEWRITE	140
++#define	SYNC_OUTER_ANY_LATCH	136
+ #define	SYNC_ANY_LATCH		135
+ #define SYNC_THR_LOCAL		133
+ #define	SYNC_MEM_HASH		131
 diff -ruN a/storage/innodb_plugin/include/univ.i b/storage/innodb_plugin/include/univ.i
 --- a/storage/innodb_plugin/include/univ.i	2010-04-30 16:37:05.000000000 +0900
 +++ b/storage/innodb_plugin/include/univ.i	2010-04-30 16:41:46.000000000 +0900
@@ -63,6 +451,88 @@ diff -ruN a/storage/innodb_plugin/mtr/mtr0log.c b/storage/innodb_plugin/mtr/mtr0
  		recv_sys->found_corrupt_log = TRUE;
  
  		return(NULL);
+diff -ruN a/storage/innodb_plugin/os/os0file.c b/storage/innodb_plugin/os/os0file.c
+--- a/storage/innodb_plugin/os/os0file.c	2011-02-21 20:31:57.437945953 +0900
++++ b/storage/innodb_plugin/os/os0file.c	2011-02-21 20:32:39.546945763 +0900
+@@ -142,6 +142,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
+@@ -3390,7 +3391,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;
+ 	ulint		i;
+@@ -3472,6 +3474,7 @@
+ 	slot->offset_high = offset_high;
+ //	slot->io_already_done = FALSE;
+ 	slot->status = OS_AIO_NOT_ISSUED;
++	slot->space_id = space_id;
+ 
+ #ifdef WIN_ASYNC_IO
+ 	control = &(slot->control);
+@@ -3680,6 +3683,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;
+@@ -3762,7 +3766,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 (os_aio_use_native_aio) {
+ #ifdef WIN_ASYNC_IO
+@@ -3872,7 +3876,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;
+@@ -3926,6 +3931,7 @@
+ 	*message2 = slot->message2;
+ 
+ 	*type = slot->type;
++	*space_id = slot->space_id;
+ 
+ 	if (ret && len == slot->len) {
+ 		ret_val = TRUE;
+@@ -4009,7 +4015,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;
+@@ -4300,6 +4307,7 @@
+ 	*message2 = slot->message2;
+ 
+ 	*type = slot->type;
++	*space_id = slot->space_id;
+ 
+ 	os_mutex_exit(array->mutex);
+ 
 diff -ruN a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c
 --- a/storage/innodb_plugin/row/row0mysql.c	2010-07-20 16:33:04.097866666 +0900
 +++ b/storage/innodb_plugin/row/row0mysql.c	2010-07-20 16:33:53.995828763 +0900
@@ -130,6 +600,18 @@ diff -ruN a/storage/innodb_plugin/row/row0sel.c b/storage/innodb_plugin/row/row0
  			trx_print(stderr, trx, 600);
  			fputc('\n', stderr);
  			ut_error;
+diff -ruN a/storage/innodb_plugin/srv/srv0srv.c b/storage/innodb_plugin/srv/srv0srv.c
+--- a/storage/innodb_plugin/srv/srv0srv.c	2011-02-21 20:31:57.900982316 +0900
++++ b/storage/innodb_plugin/srv/srv0srv.c	2011-02-21 20:32:39.549912950 +0900
+@@ -414,6 +414,8 @@
+ 
+ UNIV_INTERN ulint	srv_extra_rsegments = 0; /* extra rseg for users */
+ 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;
 diff -ruN a/storage/innodb_plugin/srv/srv0start.c b/storage/innodb_plugin/srv/srv0start.c
 --- a/storage/innodb_plugin/srv/srv0start.c	2010-04-30 16:37:05.000000000 +0900
 +++ b/storage/innodb_plugin/srv/srv0start.c	2010-04-30 16:41:46.000000000 +0900
@@ -142,6 +624,17 @@ diff -ruN a/storage/innodb_plugin/srv/srv0start.c b/storage/innodb_plugin/srv/sr
  			"log sequence number %llu\n",
  			INNODB_VERSION_STR, srv_start_lsn);
  	}
+diff -ruN a/storage/innodb_plugin/sync/sync0sync.c b/storage/innodb_plugin/sync/sync0sync.c
+--- a/storage/innodb_plugin/sync/sync0sync.c	2011-02-25 14:09:57.710270419 +0900
++++ b/storage/innodb_plugin/sync/sync0sync.c	2011-02-25 14:12:20.138232965 +0900
+@@ -1161,6 +1161,7 @@
+ 	case SYNC_LOG:
+ 	case SYNC_THR_LOCAL:
+ 	case SYNC_ANY_LATCH:
++	case SYNC_OUTER_ANY_LATCH:
+ 	case SYNC_TRX_SYS_HEADER:
+ 	case SYNC_FILE_FORMAT_TAG:
+ 	case SYNC_DOUBLEWRITE:
 diff -ruN a/storage/innodb_plugin/trx/trx0purge.c b/storage/innodb_plugin/trx/trx0purge.c
 --- a/storage/innodb_plugin/trx/trx0purge.c	2010-07-21 14:52:46.538653893 +0900
 +++ b/storage/innodb_plugin/trx/trx0purge.c	2010-07-21 14:57:46.505530034 +0900
diff --git a/mysql-innodb_swap_builtin_plugin.patch b/mysql-innodb_swap_builtin_plugin.patch
index efd83d4..c75588f 100644
--- a/mysql-innodb_swap_builtin_plugin.patch
+++ b/mysql-innodb_swap_builtin_plugin.patch
@@ -6,114 +6,6 @@
 # Any small change to this file in the main branch
 # should be done or reviewed by the maintainer!
 diff -ruN a/configure b/configure
---- a/configure	2010-04-06 23:13:20.000000000 +0900
-+++ b/configure	2010-04-28 19:12:59.000000000 +0900
-@@ -2056,13 +2056,13 @@
-    === InnoDB Storage Engine ===
-   Plugin Name:      innobase
-   Description:      Transactional Tables using InnoDB
--  Supports build:   static and dynamic
-+  Supports build:   dynamic
-   Configurations:   max, max-no-ndb
- 
-    === InnoDB Storage Engine ===
-   Plugin Name:      innodb_plugin
-   Description:      Transactional Tables using InnoDB
--  Supports build:   dynamic
-+  Supports build:   static and dynamic
-   Configurations:   max, max-no-ndb
- 
-    === MyISAM Storage Engine ===
-@@ -41806,7 +41806,8 @@
- 
- 
- 
--      mysql_plugin_innobase=yes
-+      { $as_echo "$as_me:$LINENO: WARNING: InnoDB Storage Engine can only be built as a plugin" >&5
-+$as_echo "$as_me: WARNING: InnoDB Storage Engine can only be built as a plugin" >&2;}
- 
- 
- 
-@@ -41818,8 +41819,7 @@
- 
- 
- 
--      { $as_echo "$as_me:$LINENO: WARNING: InnoDB Storage Engine can only be built as a plugin" >&5
--$as_echo "$as_me: WARNING: InnoDB Storage Engine can only be built as a plugin" >&2;}
-+      mysql_plugin_innodb_plugin=yes
- 
- 
- 
-@@ -43107,7 +43107,7 @@
-     { $as_echo "$as_me:$LINENO: result: no" >&5
- $as_echo "no" >&6; }
-   else
--
-+    with_plugin_innobase=''
-     if test "X$mysql_plugin_innobase" != Xyes -a \
-             "X$with_plugin_innobase" != Xyes; then
- 
-@@ -43133,20 +43133,11 @@
-     else
- 
- 
--
--         mysql_use_plugin_dir="storage/innobase"
--         mysql_plugin_libs="$mysql_plugin_libs \$(top_builddir)/storage/innobase/libinnobase.a"
--
--
--
--        cat >>confdefs.h <<\_ACEOF
--#define WITH_INNOBASE_STORAGE_ENGINE 1
--_ACEOF
--
--
--       plugin_innobase_static_target="libinnobase.a"
--
--       plugin_innobase_shared_target=""
-+        { $as_echo "$as_me:$LINENO: result: error" >&5
-+$as_echo "error" >&6; }
-+        { { $as_echo "$as_me:$LINENO: error: Plugin innobase does not support static linking" >&5
-+$as_echo "$as_me: error: Plugin innobase does not support static linking" >&2;}
-+   { (exit 1); exit 1; }; }
- 
- 
-       mysql_plugin_defs="$mysql_plugin_defs, builtin_innobase_plugin"
-@@ -43234,7 +43225,7 @@
-     { $as_echo "$as_me:$LINENO: result: no" >&5
- $as_echo "no" >&6; }
-   else
--    with_plugin_innodb_plugin=''
-+
-     if test "X$mysql_plugin_innodb_plugin" != Xyes -a \
-             "X$with_plugin_innodb_plugin" != Xyes; then
- 
-@@ -43260,11 +43251,20 @@
-     else
- 
- 
--        { $as_echo "$as_me:$LINENO: result: error" >&5
--$as_echo "error" >&6; }
--        { { $as_echo "$as_me:$LINENO: error: Plugin innodb_plugin does not support static linking" >&5
--$as_echo "$as_me: error: Plugin innodb_plugin does not support static linking" >&2;}
--   { (exit 1); exit 1; }; }
-+
-+         mysql_use_plugin_dir="storage/innodb_plugin"
-+         mysql_plugin_libs="$mysql_plugin_libs \$(top_builddir)/storage/innodb_plugin/libinnobase.a"
-+
-+
-+
-+        cat >>confdefs.h <<\_ACEOF
-+#define WITH_INNODB_PLUGIN_STORAGE_ENGINE 1
-+_ACEOF
-+
-+
-+       plugin_innodb_plugin_static_target="libinnobase.a"
-+
-+       plugin_innodb_plugin_shared_target=""
- 
- 
-       mysql_plugin_defs="$mysql_plugin_defs, builtin_innodb_plugin_plugin"
 diff -ruN a/mysql-test/include/have_innodb_plugin.inc b/mysql-test/include/have_innodb_plugin.inc
 --- a/mysql-test/include/have_innodb_plugin.inc	2010-05-07 00:59:10.000000000 +0900
 +++ b/mysql-test/include/have_innodb_plugin.inc	2010-05-25 18:12:49.000000000 +0900
diff --git a/mysql-log_connection_error.patch b/mysql-log_connection_error.patch
new file mode 100644
index 0000000..d10d1e7
--- /dev/null
+++ b/mysql-log_connection_error.patch
@@ -0,0 +1,80 @@
+# 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!
+diff -ruN a/mysql-test/r/connect.result b/mysql-test/r/connect.result
+--- a/mysql-test/r/connect.result	2010-07-28 16:47:46.895318726 +0400
++++ b/mysql-test/r/connect.result	2010-07-28 16:47:48.234134231 +0400
+@@ -1,3 +1,4 @@
++set global log_warnings=0;
+ drop table if exists t1,t2;
+ show tables;
+ Tables_in_mysql
+@@ -229,3 +230,4 @@
+ # ------------------------------------------------------------------
+ # -- End of 5.1 tests
+ # ------------------------------------------------------------------
++set global log_warnings=1;
+diff -ruN a/mysql-test/t/connect.test b/mysql-test/t/connect.test
+--- a/mysql-test/t/connect.test	2010-07-28 16:47:46.865318816 +0400
++++ b/mysql-test/t/connect.test	2010-07-28 16:47:48.057260581 +0400
+@@ -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
+@@ -328,3 +330,4 @@
+ # Wait till all disconnects are completed
+ --source include/wait_until_count_sessions.inc
+ 
++set global log_warnings=1;
+diff -ruN a/patch_info/log_connection_error.patch b/patch_info/log_connection_error.patch
+--- a/patch_info/log_connection_error.patch	1970-01-01 03:00:00.000000000 +0300
++++ b/patch_info/log_connection_error.patch	2010-07-28 16:47:47.634070367 +0400
+@@ -0,0 +1,6 @@
++File=log_connection_error.patch
++Name=logging abandoned connections
++Version=1.0
++Author=Percona <info at percona.com>
++License=GPL
++Comment=
+diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
+--- a/sql/mysqld.cc	2010-07-28 16:47:47.105319218 +0400
++++ b/sql/mysqld.cc	2010-07-28 16:47:47.644101813 +0400
+@@ -5046,6 +5046,10 @@
+ 
+     DBUG_PRINT("error",("Too many connections"));
+     close_connection(thd, ER_CON_COUNT_ERROR, 1);
++    if (global_system_variables.log_warnings)
++    {
++      sql_print_warning("%s", ER(ER_CON_COUNT_ERROR));
++    }
+     statistic_increment(denied_connections, &LOCK_status);
+     delete thd;
+     DBUG_VOID_RETURN;
+@@ -5433,6 +5437,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(ER_OUT_OF_RESOURCES));
++      }
+       close_connection(thd, ER_OUT_OF_RESOURCES, 1);
+       delete thd;
+       continue;
+@@ -5628,6 +5636,10 @@
+                                                    event_conn_closed)) ||
+                         my_net_init(&thd->net, thd->net.vio))
+     {
++      if (global_system_variables.log_warnings)
++      {
++        sql_print_warning("%s", ER(ER_OUT_OF_RESOURCES));
++      }
+       close_connection(thd, ER_OUT_OF_RESOURCES, 1);
+       errmsg= 0;
+       goto errorconn;
diff --git a/mysql-mysql-syslog.patch b/mysql-mysql-syslog.patch
new file mode 100644
index 0000000..c5d56be
--- /dev/null
+++ b/mysql-mysql-syslog.patch
@@ -0,0 +1,135 @@
+# 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!
+diff -ruN a/client/client_priv.h c/client/client_priv.h
+--- a/client/client_priv.h	2011-01-07 18:46:05.000000000 +0300
++++ c/client/client_priv.h	2011-01-07 18:53:03.000000000 +0300
+@@ -90,6 +90,9 @@
+   OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT,
+   OPT_DEBUG_INFO, OPT_DEBUG_CHECK, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE,
+   OPT_WRITE_BINLOG, OPT_DUMP_DATE,
++#ifndef __WIN__
++  OPT_SYSLOG,
++#endif
+   OPT_FIRST_SLAVE,
+   OPT_ALL,
+   OPT_MAX_CLIENT_OPTION
+diff -ruN a/client/mysql.cc c/client/mysql.cc
+--- a/client/mysql.cc	2010-11-29 13:37:59.000000000 +0300
++++ c/client/mysql.cc	2011-01-07 18:57:05.000000000 +0300
+@@ -43,6 +43,9 @@
+ #include "my_readline.h"
+ #include <signal.h>
+ #include <violite.h>
++#ifndef __WIN__
++#include "syslog.h"
++#endif
+ 
+ #if defined(USE_LIBEDIT_INTERFACE) && defined(HAVE_LOCALE_H)
+ #include <locale.h>
+@@ -62,6 +65,8 @@
+ /* Version numbers for deprecation messages */
+ #define VER_CELOSIA "5.6"
+ 
++#define MAX_SYSLOG_MESSAGE 900
++
+ void* sql_alloc(unsigned size);	     // Don't use mysqld alloc for these
+ void sql_element_free(void *ptr);
+ #include "sql_string.h"
+@@ -151,7 +156,7 @@
+ 	       default_charset_used= 0, opt_secure_auth= 0,
+                default_pager_set= 0, opt_sigint_ignore= 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;
+@@ -206,6 +211,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);
+@@ -1561,6 +1567,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
+   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+ };
+ 
+@@ -1684,6 +1694,11 @@
+                                     opt->name);
+ #endif
+     break;
++#ifndef __WIN__
++  case OPT_SYSLOG:
++    opt_syslog = 1;
++    break;
++#endif
+   case OPT_SERVER_ARG:
+ #ifdef EMBEDDED_LIBRARY
+     /*
+@@ -2060,6 +2075,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)
+@@ -3035,6 +3076,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/mysql-mysql_remove_eol_carret.patch b/mysql-mysql_remove_eol_carret.patch
new file mode 100644
index 0000000..bf36271
--- /dev/null
+++ b/mysql-mysql_remove_eol_carret.patch
@@ -0,0 +1,72 @@
+# 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!
+diff -ruN a/client/client_priv.h b/client/client_priv.h
+--- a/client/client_priv.h	2010-07-06 15:06:50.000000000 -0700
++++ b/client/client_priv.h	2010-07-06 15:07:18.000000000 -0700
+@@ -95,5 +95,6 @@
+ #endif
+   OPT_FIRST_SLAVE,
+   OPT_ALL,
++  OPT_NO_REMOVE_EOL_CARRET,
+   OPT_MAX_CLIENT_OPTION
+ };
+diff -ruN a/client/mysql.cc b/client/mysql.cc
+--- a/client/mysql.cc	2010-06-03 08:50:02.000000000 -0700
++++ b/client/mysql.cc	2010-07-06 15:07:18.000000000 -0700
+@@ -145,6 +145,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,
+@@ -1439,6 +1441,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.",
+diff -ruN a/client/readline.cc b/client/readline.cc
+--- a/client/readline.cc	2010-06-03 08:50:23.000000000 -0700
++++ b/client/readline.cc	2010-07-06 15:07:18.000000000 -0700
+@@ -20,6 +20,8 @@
+ #include <m_string.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);
+@@ -51,7 +53,7 @@
+   if (!(pos=intern_read_line(line_buff,&out_length, truncated)))
+     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;
+diff -ruN a/patch_info/mysql_remove_eol_carret.patch b/patch_info/mysql_remove_eol_carret.patch
+--- a/patch_info/mysql_remove_eol_carret.patch	1969-12-31 16:00:00.000000000 -0800
++++ b/patch_info/mysql_remove_eol_carret.patch	2010-07-06 15:10:10.000000000 -0700
+@@ -0,0 +1,7 @@
++File=mysql_remove_eol_carret.patch
++Name=
++Version=1.1
++Author=Percona <info at 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-remove_fcntl_excessive_calls.patch b/mysql-remove_fcntl_excessive_calls.patch
new file mode 100644
index 0000000..d7acc74
--- /dev/null
+++ b/mysql-remove_fcntl_excessive_calls.patch
@@ -0,0 +1,73 @@
+# 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!
+diff -ruN a/patch_info/remove_fcntl_excessive_calls.info b/patch_info/remove_fcntl_excessive_calls.info
+--- a/patch_info/remove_fcntl_excessive_calls.info	1970-01-01 03:00:00.000000000 +0300
++++ b/patch_info/remove_fcntl_excessive_calls.info	2010-07-22 21:42:08.560424001 +0400
+@@ -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=
+diff -ruN a/sql/net_serv.cc b/sql/net_serv.cc
+--- a/sql/net_serv.cc	2010-06-03 19:50:27.000000000 +0400
++++ b/sql/net_serv.cc	2010-07-22 21:40:30.680424001 +0400
+@@ -64,7 +64,7 @@
+   can't normally do this 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. */
+ #define NO_ALARM
+ #endif
+@@ -139,7 +139,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;
+@@ -617,7 +617,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))
+@@ -673,7 +673,7 @@
+     pos+=length;
+     update_statistics(thd_increment_bytes_sent(length));
+   }
+-#ifndef __WIN__
++#if !defined(NO_ALARM) && !defined(__WIN__)
+  end:
+ #endif
+ #ifdef HAVE_COMPRESS
+@@ -805,6 +805,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 */
+@@ -819,7 +820,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/mysql-response-time-distribution.patch b/mysql-response-time-distribution.patch
new file mode 100644
index 0000000..2dadb31
--- /dev/null
+++ b/mysql-response-time-distribution.patch
@@ -0,0 +1,888 @@
+# 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!
+diff -ruN a/include/mysql_com.h b/include/mysql_com.h
+--- a/include/mysql_com.h	2010-11-01 08:43:53.000000000 +0000
++++ b/include/mysql_com.h	2010-11-01 08:52:40.000000000 +0000
+@@ -128,10 +128,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 */
+diff -ruN a/patch_info/response-time-distribution.info b/patch_info/response-time-distribution.info
+--- a/patch_info/response-time-distribution.info	1970-01-01 00:00:00.000000000 +0000
++++ b/patch_info/response-time-distribution.info	2010-11-01 08:52:40.000000000 +0000
+@@ -0,0 +1,9 @@
++File=response-time-distribution.patch
++Name=Response time distribution
++Version=1.0
++Author=Percona <info at percona.com>
++License=GPL
++Comment=
++Changelog
++2010-07-02 first version avaliable
++2010-09-15 add column 'total'
+diff -ruN a/sql/Makefile.am b/sql/Makefile.am
+--- a/sql/Makefile.am	2010-11-01 08:43:52.000000000 +0000
++++ b/sql/Makefile.am	2010-11-01 08:52:40.000000000 +0000
+@@ -66,7 +66,7 @@
+ 			sql_repl.h slave.h rpl_filter.h rpl_injector.h \
+ 			log_event.h rpl_record.h \
+ 			log_event_old.h rpl_record_old.h \
+-			sql_sort.h sql_cache.h set_var.h \
++			sql_sort.h sql_cache.h set_var.h query_response_time.h \
+ 			spatial.h gstream.h client_settings.h tzfile.h \
+ 			tztime.h my_decimal.h\
+ 			sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
+@@ -89,7 +89,7 @@
+ 			sql_string.cc sql_manager.cc sql_map.cc \
+ 			mysqld.cc password.c hash_filo.cc hostname.cc \
+ 			sql_connect.cc scheduler.cc sql_parse.cc \
+-			set_var.cc sql_yacc.yy \
++			set_var.cc query_response_time.cc sql_yacc.yy \
+ 			sql_base.cc table.cc sql_select.cc sql_insert.cc \
+ 			sql_profile.cc \
+ 			sql_prepare.cc sql_error.cc sql_locale.cc \
+diff -ruN a/sql/Makefile.in b/sql/Makefile.in
+--- a/sql/Makefile.in	2010-11-01 08:43:52.000000000 +0000
++++ b/sql/Makefile.in	2010-11-01 08:52:40.000000000 +0000
+@@ -122,7 +122,7 @@
+ 	sql_string.$(OBJEXT) sql_manager.$(OBJEXT) sql_map.$(OBJEXT) \
+ 	mysqld.$(OBJEXT) password.$(OBJEXT) hash_filo.$(OBJEXT) \
+ 	hostname.$(OBJEXT) sql_connect.$(OBJEXT) scheduler.$(OBJEXT) \
+-	sql_parse.$(OBJEXT) set_var.$(OBJEXT) sql_yacc.$(OBJEXT) \
++	sql_parse.$(OBJEXT) set_var.$(OBJEXT) query_response_time.${OBJEXT} sql_yacc.$(OBJEXT) \
+ 	sql_base.$(OBJEXT) table.$(OBJEXT) sql_select.$(OBJEXT) \
+ 	sql_insert.$(OBJEXT) sql_profile.$(OBJEXT) \
+ 	sql_prepare.$(OBJEXT) sql_error.$(OBJEXT) sql_locale.$(OBJEXT) \
+@@ -562,7 +562,7 @@
+ 			sql_repl.h slave.h rpl_filter.h rpl_injector.h \
+ 			log_event.h rpl_record.h \
+ 			log_event_old.h rpl_record_old.h \
+-			sql_sort.h sql_cache.h set_var.h \
++			sql_sort.h sql_cache.h set_var.h query_response_time.h \
+ 			spatial.h gstream.h client_settings.h tzfile.h \
+ 			tztime.h my_decimal.h\
+ 			sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
+@@ -585,7 +585,7 @@
+ 			sql_string.cc sql_manager.cc sql_map.cc \
+ 			mysqld.cc password.c hash_filo.cc hostname.cc \
+ 			sql_connect.cc scheduler.cc sql_parse.cc \
+-			set_var.cc sql_yacc.yy \
++			set_var.cc query_response_time.cc sql_yacc.yy \
+ 			sql_base.cc table.cc sql_select.cc sql_insert.cc \
+ 			sql_profile.cc \
+ 			sql_prepare.cc sql_error.cc sql_locale.cc \
+@@ -828,6 +828,7 @@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/password.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/procedure.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/protocol.Po at am__quote@
++ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/query_response_time.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/records.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/repl_failsafe.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/rpl_filter.Po at am__quote@
+diff -ruN a/sql/lex.h b/sql/lex.h
+--- a/sql/lex.h	2010-11-01 08:43:53.000000000 +0000
++++ b/sql/lex.h	2010-11-01 08:52:40.000000000 +0000
+@@ -415,6 +415,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)},
+diff -ruN a/sql/mysql_priv.h b/sql/mysql_priv.h
+--- a/sql/mysql_priv.h	2010-11-01 08:43:57.000000000 +0000
++++ b/sql/mysql_priv.h	2010-11-01 08:52:40.000000000 +0000
+@@ -2116,6 +2116,11 @@
+ extern my_bool opt_query_cache_strip_comments;
+ extern my_bool opt_use_global_long_query_time;
+ extern my_bool opt_slow_query_log_microseconds_timestamp;
++#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
++extern ulong   opt_query_response_time_range_base;
++extern my_bool opt_enable_query_response_time_stats;
++#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
++extern SHOW_COMP_OPTION have_response_time_distribution;
+ 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;
+diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
+--- a/sql/mysqld.cc	2010-11-01 08:43:57.000000000 +0000
++++ b/sql/mysqld.cc	2010-11-01 08:52:40.000000000 +0000
+@@ -32,6 +32,7 @@
+ 
+ #include "rpl_injector.h"
+ 
++#include "query_response_time.h"
+ #ifdef HAVE_SYS_PRCTL_H
+ #include <sys/prctl.h>
+ #endif
+@@ -528,6 +529,10 @@
+ my_bool opt_query_cache_strip_comments = 0;
+ my_bool opt_use_global_long_query_time= 0;
+ my_bool opt_slow_query_log_microseconds_timestamp= 0;
++#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
++ulong   opt_query_response_time_range_base  = QRT_DEFAULT_BASE;
++my_bool opt_enable_query_response_time_stats= 0;
++#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
+ my_bool lower_case_file_system= 0;
+ my_bool opt_large_pages= 0;
+ my_bool opt_myisam_use_mmap= 0;
+@@ -673,6 +678,7 @@
+ MY_LOCALE *my_default_lc_time_names;
+ 
+ SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache;
++SHOW_COMP_OPTION have_response_time_distribution;
+ SHOW_COMP_OPTION have_geometry, have_rtree_keys;
+ SHOW_COMP_OPTION have_crypt, have_compress;
+ SHOW_COMP_OPTION have_community_features;
+@@ -1383,6 +1389,9 @@
+   free_global_thread_stats();
+   free_global_table_stats();
+   free_global_index_stats();
++#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
++  query_response_time_free();
++#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
+ #ifdef HAVE_REPLICATION
+   end_slave_list();
+ #endif
+@@ -4079,6 +4088,9 @@
+ 
+   init_global_table_stats();
+   init_global_index_stats();
++#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())
+@@ -5892,6 +5904,10 @@
+   OPT_USE_GLOBAL_LONG_QUERY_TIME,
+   OPT_USE_GLOBAL_LOG_SLOW_CONTROL,
+   OPT_SLOW_QUERY_LOG_MICROSECONDS_TIMESTAMP,
++#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
++  OPT_QRT_RANGE_BASE,
++  OPT_ENABLE_QRT_STATS,
++#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
+   OPT_IGNORE_BUILTIN_INNODB,
+   OPT_BINLOG_DIRECT_NON_TRANS_UPDATE,
+   OPT_DEFAULT_CHARACTER_SET_OLD
+@@ -6962,6 +6978,23 @@
+    "Use microsecond time's precision in slow query log",
+    (uchar**) &opt_slow_query_log_microseconds_timestamp, (uchar**) &opt_slow_query_log_microseconds_timestamp,
+    0, GET_BOOL, OPT_ARG, 0, 0, 1, 0, 1, 0},
++#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
++  {"query_response_time_range_base", OPT_QRT_RANGE_BASE,
++     "Select base of log for query_response_time ranges. WARNING: variable change affect only after flush",
++   (uchar**) &opt_query_response_time_range_base, (uchar**) &opt_query_response_time_range_base,
++   0, GET_ULONG, REQUIRED_ARG, 
++   /* def_value */  QRT_DEFAULT_BASE,
++   /* min_value */  2,
++   /* max_value */  QRT_MAXIMUM_BASE, 
++   /* sub_size */   0,
++   /* block_size */ 1,
++   /* app_type */ 0
++  },
++  {"enable_query_response_time_stats", OPT_ENABLE_QRT_STATS,
++   "Enable or disable query response time statisics collecting",
++   (uchar**) &opt_enable_query_response_time_stats, (uchar**) &opt_enable_query_response_time_stats,
++   0, GET_BOOL, REQUIRED_ARG, 0, 0, 1, 0, 1, 0},
++#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
+   {"lower_case_table_names", OPT_LOWER_CASE_TABLE_NAMES,
+    "If set to 1, table names are stored in lowercase on disk and table names "
+    "will be case-insensitive.  Should be set to 2 if you are using a case-"
+@@ -8176,6 +8209,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
+diff -ruN a/sql/query_response_time.cc b/sql/query_response_time.cc
+--- a/sql/query_response_time.cc	1970-01-01 00:00:00.000000000 +0000
++++ b/sql/query_response_time.cc	2010-11-02 15:34:52.000000000 +0000
+@@ -0,0 +1,369 @@
++#ifdef __FreeBSD__
++#include <sys/types.h>
++#include <machine/atomic.h>
++#endif // __FreeBSD__
++#include "my_global.h"
++#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
++#include "mysql_priv.h"
++#include "mysql_com.h"
++#include "rpl_tblmap.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 STRING_OVERFLOW QRT_STRING_OVERFLOW
++#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];
++};
++
++void print_time(char* buffer, std::size_t buffer_size, std::size_t string_positive_power_length, const char* format, uint64 value)
++{
++  memset(buffer,'X',buffer_size);
++  buffer[string_positive_power_length]= '.';
++  ulonglong second=      (value / MILLION);
++  ulonglong microsecond= (value % MILLION);
++  int result_length= snprintf(buffer, buffer_size, format, second, microsecond);
++  if(result_length < 0)
++  {
++    assert(sizeof(STRING_OVERFLOW) <= buffer_size);
++    memcpy(buffer, STRING_OVERFLOW, sizeof(STRING_OVERFLOW));
++    return;
++  }
++  buffer[result_length]= 0;
++}
++#ifdef __x86_64__
++typedef uint64 TimeCounter;
++void add_time_atomic(TimeCounter* counter, uint64 time)
++{
++  __sync_fetch_and_add(counter,time);  
++}
++#endif // __x86_64__
++#ifdef __i386__
++inline uint32 get_high(uint64 value)
++{
++  return ((value >> 32) << 32);
++}
++inline uint32 get_low(uint64 value)
++{
++  return ((value << 32) >> 32);
++}
++#ifdef __FreeBSD__
++inline bool compare_and_swap(volatile uint32 *target, uint32 old, uint32 new_value)
++{
++  return atomic_cmpset_32(target,old,new_value);
++}
++#else // __FreeBSD__
++inline bool compare_and_swap(volatile uint32* target, uint32 old, uint32 new_value)
++{
++  return __sync_bool_compare_and_swap(target,old,new_value);
++}
++#endif // __FreeBSD__
++class TimeCounter
++{
++public:
++  TimeCounter& operator=(uint64 time)
++  {
++    this->m_high= get_high(time);
++    this->m_low=  get_low(time);
++    return *this;
++  }
++  operator uint64() const
++  {
++    return ((static_cast<uint64>(m_high) << 32) + static_cast<uint64>(m_low));
++  }
++  void add(uint64 time)
++  {
++    uint32 time_high = get_high(time);
++    uint32 time_low  = get_low(time);
++    uint64 time_low64= time_low;
++    while(true)
++    {
++      uint32 old_low= this->m_low;
++      uint64 old_low64= old_low;
++
++      uint64 new_low64= old_low64 + time_low64;
++      uint32 new_low= (get_low(new_low64));
++      bool add_high= (get_high(new_low64) != 0);
++
++      if(!compare_and_swap(&m_low,old_low,new_low))
++      {
++	continue;
++      }
++      if(add_high)
++      {
++	++time_high;
++      }
++      if(time_high > 0)
++      {
++        __sync_fetch_and_add(&m_high,time_high);
++      }
++      break;
++    }
++  }
++private:
++  uint32 m_low;
++  uint32 m_high;
++};
++void add_time_atomic(TimeCounter* counter, uint64 time)
++{
++  counter->add(time);
++}
++#endif // __i386__
++
++class time_collector
++{
++public:
++  time_collector(utility& u) : m_utility(&u)
++  {
++  }
++  uint32 count(uint index) const { return m_count[index]; }
++  uint64 total(uint index) const { return m_total[index]; }
++public:
++  void flush()
++  {
++    memset(&m_count,0,sizeof(m_count));
++    memset((void*)&m_total,0,sizeof(m_total));
++  }
++  void collect(uint64 time)
++  {
++    bool no_collect= false;
++    DBUG_EXECUTE_IF("response_time_distribution_log_only_more_300_milliseconds", {   \
++        no_collect= time < 300 * 1000; \
++      });
++    if(no_collect) return;
++    int i= 0;
++    for(int count= m_utility->bound_count(); count > i; ++i)
++    {
++      if(m_utility->bound(i) > time)
++      {
++        __sync_fetch_and_add(&(m_count[i]),(uint32)1);
++	 add_time_atomic(&(m_total[i]),time);
++        break;
++      }
++    }
++  }
++private:
++  utility* m_utility;
++  uint32   m_count[OVERALL_POWER_COUNT + 1];
++  TimeCounter 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_POSITIVE_POWER_LENGTH,TIME_STRING_FORMAT,this->bound(i));
++        print_time(total,sizeof(total),TOTAL_STRING_POSITIVE_POWER_LENGTH,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 */
+diff -ruN a/sql/query_response_time.h b/sql/query_response_time.h
+--- a/sql/query_response_time.h	1970-01-01 00:00:00.000000000 +0000
++++ b/sql/query_response_time.h	2010-11-01 08:52:40.000000000 +0000
+@@ -0,0 +1,71 @@
++#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 string overflow (string overflow - internal error, this string say about bug in QRT)
++*/
++#define QRT_STRING_OVERFLOW "TOO BIG STRING"
++
++/*
++  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*/), \
++       max( (sizeof(QRT_TIME_OVERFLOW) - 1),		\
++	    (sizeof(QRT_STRING_OVERFLOW) - 1) ) )
++
++#define QRT_TOTAL_STRING_LENGTH				\
++  max( (QRT_TOTAL_STRING_POSITIVE_POWER_LENGTH + 1 /* '.' */ + 6 /*QRT_TOTAL_STRING_NEGATIVE_POWER_LENGTH*/), \
++       max( (sizeof(QRT_TIME_OVERFLOW) - 1),		\
++	    (sizeof(QRT_STRING_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
+diff -ruN a/sql/set_var.cc b/sql/set_var.cc
+--- a/sql/set_var.cc	2010-11-01 08:43:57.000000000 +0000
++++ b/sql/set_var.cc	2010-11-01 08:52:40.000000000 +0000
+@@ -1007,6 +1007,14 @@
+ static sys_var_use_global_long_query_time sys_use_global_long_query_time;
+ static sys_var_bool_ptr       sys_slow_query_log_microseconds_timestamp(&vars, "slow_query_log_microseconds_timestamp",
+                                                        &opt_slow_query_log_microseconds_timestamp);
++#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
++static sys_var_bool_ptr       sys_enable_query_response_time_stats(&vars, "enable_query_response_time_stats",
++                                                       &opt_enable_query_response_time_stats);
++static sys_var_long_ptr       sys_query_response_time_range_base(&vars, "query_response_time_range_base",
++					               &opt_query_response_time_range_base);
++#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
++static sys_var_have_variable sys_have_response_time_distribution(&vars, "have_response_time_distribution",
++                                                       &have_response_time_distribution);
+ /* Synonym of "slow_query_log" for consistency with SHOW VARIABLES output */
+ static sys_var_log_state sys_var_log_slow(&vars, "log_slow_queries",
+                                           &opt_slow_log, QUERY_LOG_SLOW);
+diff -ruN a/sql/sql_parse.cc b/sql/sql_parse.cc
+--- a/sql/sql_parse.cc	2010-11-01 08:43:57.000000000 +0000
++++ b/sql/sql_parse.cc	2010-11-01 08:52:40.000000000 +0000
+@@ -28,6 +28,7 @@
+ #include "events.h"
+ #include "sql_trigger.h"
+ #include "debug_sync.h"
++#include "query_response_time.h"
+ 
+ /**
+   @defgroup Runtime_Environment Runtime Environment
+@@ -1750,23 +1751,37 @@
+     Do not log administrative statements unless the appropriate option is
+     set.
+   */
++#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
++  if (opt_enable_query_response_time_stats || thd->enable_slow_log)
++#else /* HAVE_RESPONSE_TIME_DISTRIBUTION */
+   if (thd->enable_slow_log)
++#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
+   {
+-    ulonglong end_utime_of_query= thd->current_utime();
+-    thd_proc_info(thd, "logging slow query");
+-
+-    if (((end_utime_of_query - thd->utime_after_lock) >
+-         thd->variables.long_query_time ||
+-         ((thd->server_status &
+-           (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
+-          opt_log_queries_not_using_indexes &&
+-           !(sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND))) &&
+-        thd->examined_row_count >= thd->variables.min_examined_row_limit)
++    ulonglong end_utime_of_query   = thd->current_utime();
++    ulonglong query_execution_time = end_utime_of_query - thd->utime_after_lock;
++    #ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
++    if(opt_enable_query_response_time_stats)
++    {
++      query_response_time_collect(query_execution_time);
++    }
++    #endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
++    if (thd->enable_slow_log)
+     {
+       thd_proc_info(thd, "logging slow query");
+-      thd->status_var.long_query_count++;
+-      slow_log_print(thd, thd->query(), thd->query_length(), 
+-                     end_utime_of_query);
++
++      if ((query_execution_time >
++           thd->variables.long_query_time ||
++           ((thd->server_status &
++             (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
++            opt_log_queries_not_using_indexes &&
++             !(sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND))) &&
++          thd->examined_row_count >= thd->variables.min_examined_row_limit)
++      {
++        thd_proc_info(thd, "logging slow query");
++        thd->status_var.long_query_count++;
++        slow_log_print(thd, thd->query(), thd->query_length(), 
++                       end_utime_of_query);
++      }
+     }
+   }
+   DBUG_VOID_RETURN;
+@@ -1891,6 +1906,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:
+@@ -7251,6 +7267,12 @@
+     init_global_index_stats();
+     pthread_mutex_unlock(&LOCK_global_index_stats);
+   }
++#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
++  if (options & REFRESH_QUERY_RESPONSE_TIME)
++  {
++    query_response_time_flush();
++  }
++#endif /* HAVE_RESPONSE_TIME_DISTRIBUTION */
+   if (options & (REFRESH_USER_STATS | REFRESH_CLIENT_STATS | REFRESH_THREAD_STATS))
+   {
+     pthread_mutex_lock(&LOCK_global_user_client_stats);
+diff -ruN a/sql/sql_show.cc b/sql/sql_show.cc
+--- a/sql/sql_show.cc	2010-11-01 08:43:53.000000000 +0000
++++ b/sql/sql_show.cc	2010-11-01 08:52:40.000000000 +0000
+@@ -31,6 +31,7 @@
+ #include "event_data_objects.h"
+ #endif
+ #include <my_dir.h>
++#include "query_response_time.h"
+ #include "debug_sync.h"
+ 
+ #define STR_OR_NIL(S) ((S) ? (S) : "<nil>")
+@@ -7488,6 +7489,13 @@
+ 
+ */
+ 
++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, 
+@@ -7542,6 +7550,13 @@
+    1, 9, 0, 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 /* HAVE_RESPONSE_TIME_DISTRIBUTION */
++  {"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,
+diff -ruN a/sql/sql_yacc.yy b/sql/sql_yacc.yy
+--- a/sql/sql_yacc.yy	2010-11-01 08:43:53.000000000 +0000
++++ b/sql/sql_yacc.yy	2010-11-01 08:52:40.000000000 +0000
+@@ -1079,6 +1079,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 */
+@@ -10396,6 +10397,15 @@
+            if (prepare_schema_table(YYTHD, lex, 0, SCH_INDEX_STATS))
+              MYSQL_YYABORT;
+           }
++        | 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 sp_name
+           {
+             LEX *lex= Lex;
+@@ -10616,6 +10626,12 @@
+           { Lex->type|= REFRESH_TABLE_STATS; }
+         | INDEX_STATS_SYM
+           { Lex->type|= REFRESH_INDEX_STATS; }
++        | 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
+@@ -11895,6 +11911,7 @@
+         | PROFILES_SYM             {}
+         | QUARTER_SYM              {}
+         | QUERY_SYM                {}
++        | QUERY_RESPONSE_TIME_SYM  {}
+         | QUICK                    {}
+         | READ_ONLY_SYM            {}
+         | REBUILD_SYM              {}
+diff -ruN a/sql/table.h b/sql/table.h
+--- a/sql/table.h	2010-11-01 08:43:53.000000000 +0000
++++ b/sql/table.h	2010-11-01 08:52:40.000000000 +0000
+@@ -964,6 +964,7 @@
+   SCH_PROFILES,
+   SCH_REFERENTIAL_CONSTRAINTS,
+   SCH_PROCEDURES,
++  SCH_QUERY_RESPONSE_TIME,
+   SCH_SCHEMATA,
+   SCH_SCHEMA_PRIVILEGES,
+   SCH_SESSION_STATUS,
+diff -ruN a/configure.in b/configure.in
+--- a/configure.in	2010-12-07 19:19:42.000000000 +0300
++++ b/configure.in	2010-12-07 19:21:39.000000000 +0300
+@@ -2678,7 +2678,16 @@
+ AC_SUBST(readline_link)
+ AC_SUBST(readline_h_ln_cmd)
+ 
++AC_ARG_WITH(response_time_distribution,
++    AC_HELP_STRING([--without-response_time_distribution],[Disable response_time_distribution feature.]),
++    [with_response_time_distribution=$withval],
++    [with_response_time_distribution=yes]
++)
+ 
++if test "$with_response_time_distribution" = "yes"
++then
++  AC_DEFINE([HAVE_RESPONSE_TIME_DISTRIBUTION], [1], [If we want to have response_time_distribution])
++fi
+ 
+ # Include man pages, if desired, adapted to the configured parts.
+ if test X"$with_man" = Xyes
diff --git a/mysql-show_slave_status_nolock.patch b/mysql-show_slave_status_nolock.patch
new file mode 100644
index 0000000..b22184e
--- /dev/null
+++ b/mysql-show_slave_status_nolock.patch
@@ -0,0 +1,116 @@
+# 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!
+diff -ruN a/patch_info/show_slave_status_nolock.patch b/patch_info/show_slave_status_nolock.patch
+--- a/patch_info/show_slave_status_nolock.patch	1970-01-01 05:00:00.000000000 +0500
++++ b/patch_info/show_slave_status_nolock.patch	2010-10-29 14:44:13.000000000 +0600
+@@ -0,0 +1,6 @@
++File=show_slave_status_nolock.patch
++Name= SHOW SLAVE STATUS NOLOCK
++Version=1.0
++Author=Percona <info at percona.com>
++License=GPL
++Comment= Implement SHOW SLAVE STATUS without lock (STOP SLAVE lock the same mutex what lock SHOW SLAVE STATUS)
+diff -ruN a/sql/lex.h b/sql/lex.h
+--- a/sql/lex.h	2010-10-29 14:39:13.000000000 +0600
++++ b/sql/lex.h	2010-10-29 14:41:48.000000000 +0600
+@@ -367,6 +367,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)},
+diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
+--- a/sql/mysqld.cc	2010-11-17 18:45:47.000000000 +0300
++++ b/sql/mysqld.cc	2010-11-17 18:46:55.000000000 +0300
+@@ -3244,6 +3244,7 @@
+   {"show_profiles",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILES]), 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_statistics",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATS]), SHOW_LONG_STATUS},
+diff -ruN a/sql/sql_lex.h b/sql/sql_lex.h
+--- a/sql/sql_lex.h	2010-10-29 14:39:13.000000000 +0600
++++ b/sql/sql_lex.h	2010-10-29 14:41:56.000000000 +0600
+@@ -119,7 +119,8 @@
+   SQLCOM_ALTER_DB_UPGRADE, SQLCOM_SHOW_TEMPORARY_TABLES,
+   SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES,
+   SQLCOM_SHOW_PATCHES,
+-
++  /* 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[]= {" ...
+diff -ruN a/sql/sql_parse.cc b/sql/sql_parse.cc
+--- a/sql/sql_parse.cc	2010-10-29 14:39:13.000000000 +0600
++++ b/sql/sql_parse.cc	2010-10-29 14:42:03.000000000 +0600
+@@ -327,6 +327,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;
+@@ -2546,12 +2547,16 @@
+     pthread_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;
+-    pthread_mutex_lock(&LOCK_active_mi);
++    if(SQLCOM_SHOW_SLAVE_NOLOCK_STAT != lex->sql_command)
++    {
++      pthread_mutex_lock(&LOCK_active_mi);
++    }
+     if (active_mi != NULL)
+     {
+       res = show_master_info(thd, active_mi);
+@@ -2562,7 +2567,10 @@
+                    WARN_NO_MASTER_INFO, ER(WARN_NO_MASTER_INFO));
+       my_ok(thd);
+     }
+-    pthread_mutex_unlock(&LOCK_active_mi);
++    if(SQLCOM_SHOW_SLAVE_NOLOCK_STAT != lex->sql_command)
++    {
++      pthread_mutex_unlock(&LOCK_active_mi);
++    }
+     break;
+   }
+   case SQLCOM_SHOW_MASTER_STAT:
+diff -ruN a/sql/sql_yacc.yy b/sql/sql_yacc.yy
+--- a/sql/sql_yacc.yy	2010-10-29 14:39:13.000000000 +0600
++++ b/sql/sql_yacc.yy	2010-10-29 14:41:39.000000000 +0600
+@@ -1173,6 +1173,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
+@@ -10367,6 +10368,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;
++          }
+         | CLIENT_STATS_SYM wild_and_where 
+           {
+            LEX *lex= Lex;
diff --git a/mysql-sql_no_fcache.patch b/mysql-sql_no_fcache.patch
new file mode 100644
index 0000000..6be7045
--- /dev/null
+++ b/mysql-sql_no_fcache.patch
@@ -0,0 +1,416 @@
+# 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!
+diff -ruN a/client/mysqldump.c b/client/mysqldump.c
+--- a/client/mysqldump.c	2010-07-28 16:47:58.264067653 +0400
++++ b/client/mysqldump.c	2010-07-28 16:47:59.604985656 +0400
+@@ -132,6 +132,8 @@
+ #endif
+ static uint opt_protocol= 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
+@@ -1512,6 +1514,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.
+@@ -3166,7 +3179,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, "'");
+ 
+@@ -3216,7 +3234,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)
+diff -ruN a/include/flashcache_ioctl.h b/include/flashcache_ioctl.h
+--- a/include/flashcache_ioctl.h	1970-01-01 03:00:00.000000000 +0300
++++ b/include/flashcache_ioctl.h	2010-07-28 16:47:59.744079911 +0400
+@@ -0,0 +1,53 @@
++/****************************************************************************
++ *  flashcache_ioctl.h
++ *  FlashCache: Device mapper target for block-level disk caching
++ *
++ *  Copyright 2010 Facebook, Inc.
++ *  Author: Mohan Srinivasan (mohan at facebook.com)
++ *
++ *  Based on DM-Cache:
++ *   Copyright (C) International Business Machines Corp., 2006
++ *   Author: Ming Zhao (mingzhao at 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
+diff -ruN a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
+--- a/mysql-test/r/mysqldump.result	2010-07-28 16:47:58.334083833 +0400
++++ b/mysql-test/r/mysqldump.result	2010-07-28 16:48:14.805318437 +0400
+@@ -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/patch_info/sql_no_fcache.info b/patch_info/sql_no_fcache.info
+--- a/patch_info/sql_no_fcache.info	1970-01-01 03:00:00.000000000 +0300
<Skipped 279 lines>
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/percona-server.git/commitdiff/bf636d07b36bfd2921b9ecf2033c78270355c98c




More information about the pld-cvs-commit mailing list