[packages/percona-server/v5.1.x: 5/21] - add percona patches (release-5.1.53-11)
glen
glen at pld-linux.org
Wed Oct 21 16:08:34 CEST 2015
commit 8c0fcd576584cf0397e2b088fb33bc07c1813ba8
Author: Elan Ruusamäe <glen at pld-linux.org>
Date: Fri Dec 17 11:41:48 2010 +0000
- add percona patches (release-5.1.53-11)
Changed files:
mysql-bug580324.patch -> 1.1.2.1
mysql-bug677407.patch -> 1.1.2.1
mysql-error_pad.patch -> 1.1.2.1
mysql-i_s_innodb_buffer_pool_pages.patch -> 1.1.2.1
mysql-innodb_adjust_defaults.patch -> 1.1.2.1
mysql-innodb_admin_command_base.patch -> 1.1.2.1
mysql-innodb_deadlock_count.patch -> 1.1.2.1
mysql-innodb_expand_import.patch -> 1.1.2.1
mysql-innodb_expand_undo_slots.patch -> 1.1.2.1
mysql-innodb_fast_checksum.patch -> 1.1.2.1
mysql-innodb_files_extend.patch -> 1.1.2.1
mysql-innodb_fix_misc.patch -> 1.1.2.1
mysql-innodb_lru_dump_restore.patch -> 1.1.2.1
mysql-innodb_opt_lru_count.patch -> 1.1.2.1
mysql-innodb_overwrite_relay_log_info.patch -> 1.1.2.1
mysql-innodb_pass_corrupt_table.patch -> 1.1.2.1
mysql-innodb_purge_thread.patch -> 1.1.2.1
mysql-innodb_separate_doublewrite.patch -> 1.1.2.1
mysql-innodb_show_enhancements.patch -> 1.1.2.1
mysql-innodb_show_lock_name.patch -> 1.1.2.1
mysql-innodb_show_status.patch -> 1.1.2.1
mysql-innodb_show_sys_tables.patch -> 1.1.2.1
mysql-innodb_stats.patch -> 1.1.2.1
mysql-innodb_swap_builtin_plugin.patch -> 1.1.2.1
mysql-mysql_dump_ignore_ct.patch -> 1.1.2.1
mysql-optimizer_fix.patch -> 1.1.2.1
mysql-query_cache_enhance.patch -> 1.1.2.1
mysql-show_temp_51.patch -> 1.1.2.1
mysql-slow_extended.patch -> 1.1.2.1
mysql-suppress_log_warning_1592.patch -> 1.1.2.1
mysql-bug580324.patch | 105 ++
mysql-bug677407.patch | 138 ++
mysql-error_pad.patch | 267 ++++
mysql-i_s_innodb_buffer_pool_pages.patch | 797 ++++++++++
mysql-innodb_adjust_defaults.patch | 48 +
mysql-innodb_admin_command_base.patch | 181 +++
mysql-innodb_deadlock_count.patch | 73 +
mysql-innodb_expand_import.patch | 555 +++++++
mysql-innodb_expand_undo_slots.patch | 150 ++
mysql-innodb_fast_checksum.patch | 311 ++++
mysql-innodb_files_extend.patch | 422 ++++++
mysql-innodb_fix_misc.patch | 137 ++
mysql-innodb_lru_dump_restore.patch | 698 +++++++++
mysql-innodb_opt_lru_count.patch | 313 ++++
mysql-innodb_overwrite_relay_log_info.patch | 499 +++++++
mysql-innodb_pass_corrupt_table.patch | 1370 +++++++++++++++++
mysql-innodb_purge_thread.patch | 522 +++++++
mysql-innodb_separate_doublewrite.patch | 963 ++++++++++++
mysql-innodb_show_enhancements.patch | 275 ++++
mysql-innodb_show_lock_name.patch | 338 +++++
mysql-innodb_show_status.patch | 456 ++++++
mysql-innodb_show_sys_tables.patch | 718 +++++++++
mysql-innodb_stats.patch | 2135 +++++++++++++++++++++++++++
mysql-innodb_swap_builtin_plugin.patch | 163 ++
mysql-mysql_dump_ignore_ct.patch | 62 +
mysql-optimizer_fix.patch | 174 +++
mysql-query_cache_enhance.patch | 892 +++++++++++
mysql-show_temp_51.patch | 393 +++++
mysql-slow_extended.patch | 1474 ++++++++++++++++++
mysql-suppress_log_warning_1592.patch | 71 +
30 files changed, 14700 insertions(+)
---
diff --git a/mysql-bug580324.patch b/mysql-bug580324.patch
new file mode 100644
index 0000000..3947fde
--- /dev/null
+++ b/mysql-bug580324.patch
@@ -0,0 +1,105 @@
+# name : bug580324.patch
+# introduced : 11 or before
+# maintainer : Oleg
+#
+#!!! notice !!!
+# Any small change to this file in the main branch
+# should be done or reviewed by the maintainer!
+diff -ruN a/sql/sql_base.cc b/sql/sql_base.cc
+--- a/sql/sql_base.cc 2010-05-27 19:54:18.000000000 +0400
++++ b/sql/sql_base.cc 2010-05-27 19:55:20.000000000 +0400
+@@ -233,8 +233,12 @@
+ uint create_table_def_key(THD *thd, char *key, TABLE_LIST *table_list,
+ bool tmp_table)
+ {
+- uint key_length= (uint) (strmov(strmov(key, table_list->db)+1,
+- table_list->table_name)-key)+1;
++ char *db_end= strnmov(key, table_list->db, MAX_DBKEY_LENGTH - 2);
++ *db_end++= '\0';
++ char *table_end= strnmov(db_end, table_list->table_name,
++ key + MAX_DBKEY_LENGTH - 1 - db_end);
++ *table_end++= '\0';
++ uint key_length= (uint) (table_end-key);
+ if (tmp_table)
+ {
+ int4store(key + key_length, thd->server_id);
+diff -ruN a/sql/sql_parse.cc b/sql/sql_parse.cc
+--- a/sql/sql_parse.cc 2010-05-27 19:54:18.000000000 +0400
++++ b/sql/sql_parse.cc 2010-05-27 20:03:20.000000000 +0400
+@@ -1327,10 +1327,12 @@
+ break;
+ #else
+ {
+- char *fields, *packet_end= packet + packet_length, *arg_end;
++ char *fields, *packet_end= packet + packet_length, *wildcard;
+ /* Locked closure of all tables */
+ TABLE_LIST table_list;
+- LEX_STRING conv_name;
++ char db_buff[NAME_LEN+1];
++ uint32 db_length;
++ uint dummy_errors;
+
+ /* used as fields initializator */
+ lex_start(thd);
+@@ -1342,26 +1344,22 @@
+ /*
+ We have name + wildcard in packet, separated by endzero
+ */
+- arg_end= strend(packet);
+- uint arg_length= arg_end - packet;
+-
+- /* Check given table name length. */
+- if (arg_length >= packet_length || arg_length > NAME_LEN)
++ wildcard= strend(packet);
++ db_length= wildcard - packet;
++ wildcard++;
++ uint query_length= (uint) (packet_end - wildcard); // Don't count end \0
++ if (db_length > NAME_LEN || query_length > NAME_LEN)
+ {
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
+ break;
+ }
+- thd->convert_string(&conv_name, system_charset_info,
+- packet, arg_length, thd->charset());
+- if (check_table_name(conv_name.str, conv_name.length, FALSE))
+- {
+- /* this is OK due to convert_string() null-terminating the string */
+- my_error(ER_WRONG_TABLE_NAME, MYF(0), conv_name.str);
++ db_length= copy_and_convert(db_buff, sizeof(db_buff)-1,
++ system_charset_info, packet, db_length,
++ thd->charset(), &dummy_errors);
++ db_buff[db_length]= '\0';
++ table_list.alias= table_list.table_name= db_buff;
++ if (!(fields= (char *) thd->memdup(wildcard, query_length + 1)))
+ break;
+- }
+-
+- table_list.alias= table_list.table_name= conv_name.str;
+- packet= arg_end + 1;
+
+ if (is_schema_db(table_list.db, table_list.db_length))
+ {
+@@ -1370,9 +1368,6 @@
+ table_list.schema_table= schema_table;
+ }
+
+- uint query_length= (uint) (packet_end - packet); // Don't count end \0
+- if (!(fields= (char *) thd->memdup(packet, query_length + 1)))
+- break;
+ thd->set_query(fields, query_length);
+ general_log_print(thd, command, "%s %s", table_list.table_name, fields);
+ if (lower_case_table_names)
+diff -ruN a/strings/ctype-utf8.c b/strings/ctype-utf8.c
+--- a/strings/ctype-utf8.c 2010-05-06 19:28:05.000000000 +0400
++++ b/strings/ctype-utf8.c 2010-05-27 20:04:20.000000000 +0400
+@@ -4116,6 +4116,10 @@
+ {
+ int code;
+ char hex[]= "0123456789abcdef";
++
++ if (s >= e)
++ return MY_CS_TOOSMALL;
++
+ if (wc < 128 && filename_safe_char[wc])
+ {
+ *s= (uchar) wc;
diff --git a/mysql-bug677407.patch b/mysql-bug677407.patch
new file mode 100644
index 0000000..873a6a1
--- /dev/null
+++ b/mysql-bug677407.patch
@@ -0,0 +1,138 @@
+# name : bug677407
+# introduced : 13
+# maintainer : Alexey
+
+LP bug#677407 / MySQL Bug#48883: Stale data from INNODB_LOCKS table.
+
+The innodb.innodb_information_schema test could fail sporadically due to
+the flawed logic in the INFORMATION_SCHEMA.INNODB_LOCKS caching
+mechanism.
+
+The logic for how to check when to update the table cache for
+INNODB_LOCKS with real data was flawed. This could result in both not
+updating the cache often enough (when the table is queried repeatedly
+with less than 100 milliseconds in-between) resulting in stale data; as
+well as updating too often (when multiple queries against the table
+start at around the same time).
+
+Fixed by updating the "last updated" timestamp in the right place, when
+the cache is updated, not when it is read.
+
+I hereby grant Percona the following BSD license to this patch for
+inclusion in Percona Server:
+
+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.
+
+--- a/storage/innodb_plugin/trx/trx0i_s.c 2010-11-03 16:39:54.000000000 +0300
++++ b/storage/innodb_plugin/trx/trx0i_s.c 2010-11-30 13:57:03.000000000 +0300
+@@ -157,10 +157,6 @@
+ ullint last_read; /*!< last time the cache was read;
+ measured in microseconds since
+ epoch */
+- mutex_t last_read_mutex;/*!< mutex protecting the
+- last_read member - it is updated
+- inside a shared lock of the
+- rw_lock member */
+ i_s_table_cache_t innodb_trx; /*!< innodb_trx table */
+ i_s_table_cache_t innodb_locks; /*!< innodb_locks table */
+ i_s_table_cache_t innodb_lock_waits;/*!< innodb_lock_waits table */
+@@ -1101,13 +1097,6 @@
+ {
+ ullint now;
+
+- /* Here we read cache->last_read without acquiring its mutex
+- because last_read is only updated when a shared rw lock on the
+- whole cache is being held (see trx_i_s_cache_end_read()) and
+- we are currently holding an exclusive rw lock on the cache.
+- So it is not possible for last_read to be updated while we are
+- reading it. */
+-
+ #ifdef UNIV_SYNC_DEBUG
+ ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_EX));
+ #endif
+@@ -1205,6 +1194,12 @@
+ /*===================================*/
+ trx_i_s_cache_t* cache) /*!< in/out: cache */
+ {
++ ullint now;
++
++#ifdef UNIV_SYNC_DEBUG
++ ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_EX));
++#endif
++
+ if (!can_cache_be_updated(cache)) {
+
+ return(1);
+@@ -1217,6 +1212,10 @@
+
+ mutex_exit(&kernel_mutex);
+
++ /* update cache last read time */
++ now = ut_time_us(NULL);
++ cache->last_read = now;
++
+ return(0);
+ }
+
+@@ -1247,16 +1246,12 @@
+ release kernel_mutex
+ release trx_i_s_cache_t::rw_lock
+ acquire trx_i_s_cache_t::rw_lock, S
+- acquire trx_i_s_cache_t::last_read_mutex
+- release trx_i_s_cache_t::last_read_mutex
+ release trx_i_s_cache_t::rw_lock */
+
+ rw_lock_create(&cache->rw_lock, SYNC_TRX_I_S_RWLOCK);
+
+ cache->last_read = 0;
+
+- mutex_create(&cache->last_read_mutex, SYNC_TRX_I_S_LAST_READ);
+-
+ table_cache_init(&cache->innodb_trx, sizeof(i_s_trx_row_t));
+ table_cache_init(&cache->innodb_locks, sizeof(i_s_locks_row_t));
+ table_cache_init(&cache->innodb_lock_waits,
+@@ -1307,18 +1302,10 @@
+ /*===================*/
+ trx_i_s_cache_t* cache) /*!< in: cache */
+ {
+- ullint now;
+-
+ #ifdef UNIV_SYNC_DEBUG
+ ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_SHARED));
+ #endif
+
+- /* update cache last read time */
+- now = ut_time_us(NULL);
+- mutex_enter(&cache->last_read_mutex);
+- cache->last_read = now;
+- mutex_exit(&cache->last_read_mutex);
+-
+ rw_lock_s_unlock(&cache->rw_lock);
+ }
+
diff --git a/mysql-error_pad.patch b/mysql-error_pad.patch
new file mode 100644
index 0000000..fa452c7
--- /dev/null
+++ b/mysql-error_pad.patch
@@ -0,0 +1,267 @@
+# name : error_pad.patch
+# introduced : 12
+# maintainer : Oleg
+#
+#!!! notice !!!
+# Any small change to this file in the main branch
+# should be done or reviewed by the maintainer!
+diff -ruN a/extra/comp_err.c b/extra/comp_err.c
+--- a/extra/comp_err.c 2010-08-03 17:24:24.000000000 +0000
++++ b/extra/comp_err.c 2010-09-14 16:49:28.000000000 +0000
+@@ -30,11 +30,12 @@
+ #include <assert.h>
+ #include <my_dir.h>
+
+-#define MAX_ROWS 1000
++#define MAX_ROWS 5000
+ #define HEADER_LENGTH 32 /* Length of header in errmsg.sys */
+ #define DEFAULT_CHARSET_DIR "../sql/share/charsets"
+ #define ER_PREFIX "ER_"
+ #define WARN_PREFIX "WARN_"
++#define PADD_PREFIX "PADD_"
+ static char *OUTFILE= (char*) "errmsg.sys";
+ static char *HEADERFILE= (char*) "mysqld_error.h";
+ static char *NAMEFILE= (char*) "mysqld_ername.h";
+@@ -89,6 +90,7 @@
+ const char *sql_code1; /* sql state */
+ const char *sql_code2; /* ODBC state */
+ struct errors *next_error; /* Pointer to next error */
++ my_bool is_padding; /* If true - padd this er_name while er_code != d_code*/
+ DYNAMIC_ARRAY msg; /* All language texts for this error */
+ };
+
+@@ -127,6 +129,7 @@
+
+
+ static struct languages *parse_charset_string(char *str);
++static struct errors *parse_padd_string(char *ptr, int er_count);
+ static struct errors *parse_error_string(char *ptr, int er_count);
+ static struct message *parse_message_string(struct message *new_message,
+ char *str);
+@@ -229,6 +232,11 @@
+
+ for (tmp_error= error_head; tmp_error; tmp_error= tmp_error->next_error)
+ {
++ if (tmp_error->is_padding)
++ {
++ er_last= tmp_error->d_code;
++ continue;
++ }
+ /*
+ generating mysqld_error.h
+ fprintf() will automatically add \r on windows
+@@ -318,12 +326,29 @@
+ "language\n", tmp_error->er_name, tmp_lang->lang_short_name);
+ goto err;
+ }
+- if (copy_rows(to, tmp->text, row_nr, start_pos))
++ if (tmp_error->is_padding)
+ {
+- fprintf(stderr, "Failed to copy rows to %s\n", outfile);
+- goto err;
++ int padd_to= tmp_error->d_code;
++ char* padd_message= tmp->text;
++ while ((row_nr+er_offset) < padd_to)
++ {
++ if (copy_rows(to, padd_message,row_nr,start_pos))
++ {
++ fprintf(stderr, "Failed to copy rows to %s\n", outfile);
++ goto err;
++ }
++ row_nr++;
++ }
++ }
++ else
++ {
++ if (copy_rows(to, tmp->text, row_nr, start_pos))
++ {
++ fprintf(stderr, "Failed to copy rows to %s\n", outfile);
++ goto err;
++ }
++ row_nr++;
+ }
+- row_nr++;
+ }
+
+ /* continue with header of the errmsg.sys file */
+@@ -474,14 +499,26 @@
+ DBUG_RETURN(0);
+ continue;
+ }
+- if (is_prefix(str, ER_PREFIX) || is_prefix(str, WARN_PREFIX))
++ if (is_prefix(str, ER_PREFIX) || is_prefix(str, WARN_PREFIX) || is_prefix(str, PADD_PREFIX))
+ {
+- if (!(current_error= parse_error_string(str, rcount)))
++ if (is_prefix(str, PADD_PREFIX))
+ {
+- fprintf(stderr, "Failed to parse the error name string\n");
+- DBUG_RETURN(0);
++ if (!(current_error= parse_padd_string(str, rcount)))
++ {
++ fprintf(stderr, "Failed to parse the error padd string\n");
++ DBUG_RETURN(0);
++ }
++ rcount= current_error->d_code - er_offset; /* Count number of unique errors */
++ }
++ else
++ {
++ if (!(current_error= parse_error_string(str, rcount)))
++ {
++ fprintf(stderr, "Failed to parse the error name string\n");
++ DBUG_RETURN(0);
++ }
++ rcount++; /* Count number of unique errors */
+ }
+- rcount++; /* Count number of unique errors */
+
+ /* add error to the list */
+ *tail_error= current_error;
+@@ -822,78 +859,122 @@
+ DBUG_RETURN(new_message);
+ }
+
++static struct errors* create_new_error(my_bool is_padding, char *er_name, int d_code, const char *sql_code1, const char *sql_code2)
++{
++ struct errors *new_error;
++ DBUG_ENTER("create_new_error");
++ /* create a new element */
++ new_error= (struct errors *) my_malloc(sizeof(*new_error), MYF(MY_WME));
++ if (my_init_dynamic_array(&new_error->msg, sizeof(struct message), 0, 0))
++ DBUG_RETURN(0); /* OOM: Fatal error */
++ new_error->is_padding= is_padding;
++ DBUG_PRINT("info", ("is_padding: %s", (is_padding ? "true" : "false")));
++ new_error->er_name= er_name;
++ DBUG_PRINT("info", ("er_name: %s", er_name));
++ new_error->d_code= d_code;
++ DBUG_PRINT("info", ("d_code: %d", d_code));
++ new_error->sql_code1= sql_code1;
++ DBUG_PRINT("info", ("sql_code1: %s", sql_code1));
++ new_error->sql_code2= sql_code2;
++ DBUG_PRINT("info", ("sql_code2: %s", sql_code2));
++ DBUG_RETURN(new_error);
++}
+
+ /*
+- Parsing the string with error name and codes; returns the pointer to
++ Parsing the string with padd syntax (name + error to pad); returns the pointer to
+ the errors struct
+ */
+
+-static struct errors *parse_error_string(char *str, int er_count)
++static struct errors *parse_padd_string(char* str, int er_count)
+ {
+- struct errors *new_error;
++ char *er_name;
++ uint d_code;
++ char *start;
+ DBUG_ENTER("parse_error_string");
+ DBUG_PRINT("enter", ("str: %s", str));
+
+- /* create a new element */
+- new_error= (struct errors *) my_malloc(sizeof(*new_error), MYF(MY_WME));
++ start= str;
++ str= skip_delimiters(str);
+
+- if (my_init_dynamic_array(&new_error->msg, sizeof(struct message), 0, 0))
++ /* getting the error name */
++
++ if (!(er_name= get_word(&str)))
+ DBUG_RETURN(0); /* OOM: Fatal error */
+
+- /* getting the error name */
+ str= skip_delimiters(str);
+
+- if (!(new_error->er_name= get_word(&str)))
++ if (!(d_code= parse_error_offset(start)))
++ {
++ fprintf(stderr, "Failed to parse the error padd string '%s' '%s' (d_code doesn't parse)!\n",er_name,str);
++ DBUG_RETURN(0);
++ }
++ if (d_code < (er_offset + er_count))
++ {
++ fprintf(stderr, "Error to padding less current error number!\n");
++ DBUG_RETURN(0);
++ }
++ DBUG_RETURN(create_new_error(TRUE,er_name,d_code,empty_string,empty_string));
++}
++
++/*
++ Parsing the string with error name and codes; returns the pointer to
++ the errors struct
++*/
++
++static struct errors *parse_error_string(char *str, int er_count)
++{
++ char *er_name;
++ int d_code;
++ const char *sql_code1= empty_string;
++ const char *sql_code2= empty_string;
++ DBUG_ENTER("parse_error_string");
++ DBUG_PRINT("enter", ("str: %s", str));
++
++ str= skip_delimiters(str);
++
++ /* getting the error name */
++
++ if (!(er_name= get_word(&str)))
+ DBUG_RETURN(0); /* OOM: Fatal error */
+- DBUG_PRINT("info", ("er_name: %s", new_error->er_name));
+
+ str= skip_delimiters(str);
+
+ /* getting the code1 */
+-
+- new_error->d_code= er_offset + er_count;
+- DBUG_PRINT("info", ("d_code: %d", new_error->d_code));
++ d_code= er_offset + er_count;
+
+ str= skip_delimiters(str);
+
+ /* if we reached EOL => no more codes, but this can happen */
+ if (!*str)
+ {
+- new_error->sql_code1= empty_string;
+- new_error->sql_code2= empty_string;
+ DBUG_PRINT("info", ("str: %s", str));
+- DBUG_RETURN(new_error);
++ goto complete_create;
+ }
+-
+ /* getting the sql_code 1 */
+-
+- if (!(new_error->sql_code1= get_word(&str)))
++ if (!(sql_code1= get_word(&str)))
+ DBUG_RETURN(0); /* OOM: Fatal error */
+- DBUG_PRINT("info", ("sql_code1: %s", new_error->sql_code1));
+
+ str= skip_delimiters(str);
+
+ /* if we reached EOL => no more codes, but this can happen */
+ if (!*str)
+ {
+- new_error->sql_code2= empty_string;
+ DBUG_PRINT("info", ("str: %s", str));
+- DBUG_RETURN(new_error);
++ goto complete_create;
+ }
+-
+ /* getting the sql_code 2 */
+- if (!(new_error->sql_code2= get_word(&str)))
++ if (!(sql_code2= get_word(&str)))
+ DBUG_RETURN(0); /* OOM: Fatal error */
+- DBUG_PRINT("info", ("sql_code2: %s", new_error->sql_code2));
+
+ str= skip_delimiters(str);
++
+ if (*str)
+ {
+ fprintf(stderr, "The error line did not end with sql/odbc code!");
+ DBUG_RETURN(0);
+ }
+-
+- DBUG_RETURN(new_error);
++complete_create:
++ DBUG_RETURN(create_new_error(FALSE,er_name,d_code,sql_code1,sql_code2));
+ }
+
+
diff --git a/mysql-i_s_innodb_buffer_pool_pages.patch b/mysql-i_s_innodb_buffer_pool_pages.patch
new file mode 100644
index 0000000..1adf1b5
--- /dev/null
+++ b/mysql-i_s_innodb_buffer_pool_pages.patch
@@ -0,0 +1,797 @@
+# name : i_s_innodb_buffer_pool_pages.patch
+# introduced : 11 or before
+# maintainer : Yasufumi
+#
+#!!! notice !!!
+# Any small change to this file in the main branch
+# should be done or reviewed by the maintainer!
+diff -ruN a/storage/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c
+--- a/storage/innodb_plugin/buf/buf0buf.c 2010-07-14 15:57:23.322321253 +0900
++++ b/storage/innodb_plugin/buf/buf0buf.c 2010-07-14 16:04:45.521321527 +0900
+@@ -269,14 +269,6 @@
+ UNIV_INTERN ibool buf_debug_prints = FALSE;
+ #endif /* UNIV_DEBUG */
+
+-/** A chunk of buffers. The buffer pool is allocated in chunks. */
+-struct buf_chunk_struct{
+- ulint mem_size; /*!< allocated size of the chunk */
+- ulint size; /*!< size of frames[] and blocks[] */
+- void* mem; /*!< pointer to the memory area which
+- was allocated for the frames */
+- buf_block_t* blocks; /*!< array of buffer control blocks */
+-};
+ #endif /* !UNIV_HOTBACKUP */
+
+ /********************************************************************//**
+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-04-29 15:55:25.000000000 +0900
++++ b/storage/innodb_plugin/handler/ha_innodb.cc 2010-04-29 16:04:05.000000000 +0900
+@@ -11173,6 +11173,9 @@
+ innobase_system_variables, /* system variables */
+ NULL /* reserved */
+ },
++i_s_innodb_buffer_pool_pages,
++i_s_innodb_buffer_pool_pages_index,
++i_s_innodb_buffer_pool_pages_blob,
+ i_s_innodb_trx,
+ i_s_innodb_locks,
+ i_s_innodb_lock_waits,
+diff -ruN a/storage/innodb_plugin/handler/i_s.cc b/storage/innodb_plugin/handler/i_s.cc
+--- a/storage/innodb_plugin/handler/i_s.cc 2010-04-29 15:28:20.000000000 +0900
++++ b/storage/innodb_plugin/handler/i_s.cc 2010-04-29 16:04:05.000000000 +0900
+@@ -42,6 +42,7 @@
+ #include "buf0buf.h" /* for buf_pool and PAGE_ZIP_MIN_SIZE */
+ #include "ha_prototypes.h" /* for innobase_convert_name() */
+ #include "srv0start.h" /* for srv_was_started */
++#include "btr0btr.h" /* for btr_page_get_index_id */
+ }
+
+ static const char plugin_author[] = "Innobase Oy";
+@@ -380,6 +381,705 @@
+ };
+
+
++static ST_FIELD_INFO i_s_innodb_buffer_pool_pages_fields_info[] =
++{
++ {STRUCT_FLD(field_name, "page_type"),
++ STRUCT_FLD(field_length, 64),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "space_id"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "page_no"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "lru_position"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "fix_count"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "flush_type"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ END_OF_ST_FIELD_INFO
++};
++
++static ST_FIELD_INFO i_s_innodb_buffer_pool_pages_index_fields_info[] =
++{
++ {STRUCT_FLD(field_name, "index_id"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "space_id"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "page_no"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "n_recs"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "data_size"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "hashed"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "access_time"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "modified"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "dirty"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "old"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "lru_position"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "fix_count"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "flush_type"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ END_OF_ST_FIELD_INFO
++};
++
++static ST_FIELD_INFO i_s_innodb_buffer_pool_pages_blob_fields_info[] =
++{
++ {STRUCT_FLD(field_name, "space_id"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "page_no"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "compressed"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "part_len"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "next_page_no"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "lru_position"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "fix_count"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ {STRUCT_FLD(field_name, "flush_type"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ END_OF_ST_FIELD_INFO
++};
++
++/***********************************************************************
++Fill the dynamic table information_schema.innodb_buffer_pool_pages. */
++static
++int
++i_s_innodb_buffer_pool_pages_fill(
++/*================*/
++ /* out: 0 on success, 1 on failure */
++ THD* thd, /* in: thread */
++ TABLE_LIST* tables, /* in/out: tables to fill */
++ COND* cond) /* in: condition (ignored) */
++{
++ TABLE* table = (TABLE *) tables->table;
++ int status = 0;
++
++ ulint n_chunks, n_blocks;
++
++ buf_chunk_t* chunk;
++
++ DBUG_ENTER("i_s_innodb_buffer_pool_pages_fill");
++
++ /* deny access to non-superusers */
++ if (check_global_access(thd, PROCESS_ACL)) {
++
++ DBUG_RETURN(0);
++ }
++
++ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
++
++ buf_pool_mutex_enter();
++
++ chunk = buf_pool->chunks;
++
++ for (n_chunks = buf_pool->n_chunks; n_chunks--; chunk++) {
++ buf_block_t* block = chunk->blocks;
++
++ for (n_blocks = chunk->size; n_blocks--; block++) {
++ const buf_frame_t* frame = block->frame;
++
++ char page_type[64];
++
++ switch(fil_page_get_type(frame))
++ {
++ case FIL_PAGE_INDEX:
++ strcpy(page_type, "index");
++ break;
++ case FIL_PAGE_UNDO_LOG:
++ strcpy(page_type, "undo_log");
++ break;
++ case FIL_PAGE_INODE:
++ strcpy(page_type, "inode");
++ break;
++ case FIL_PAGE_IBUF_FREE_LIST:
++ strcpy(page_type, "ibuf_free_list");
++ break;
++ case FIL_PAGE_TYPE_ALLOCATED:
++ strcpy(page_type, "allocated");
++ break;
++ case FIL_PAGE_IBUF_BITMAP:
++ strcpy(page_type, "bitmap");
++ break;
++ case FIL_PAGE_TYPE_SYS:
++ strcpy(page_type, "sys");
++ break;
++ case FIL_PAGE_TYPE_TRX_SYS:
++ strcpy(page_type, "trx_sys");
++ break;
++ case FIL_PAGE_TYPE_FSP_HDR:
++ strcpy(page_type, "fsp_hdr");
++ break;
++ case FIL_PAGE_TYPE_XDES:
++ strcpy(page_type, "xdes");
++ break;
++ case FIL_PAGE_TYPE_BLOB:
++ strcpy(page_type, "blob");
++ break;
++ case FIL_PAGE_TYPE_ZBLOB:
++ strcpy(page_type, "zblob");
++ break;
++ case FIL_PAGE_TYPE_ZBLOB2:
++ strcpy(page_type, "zblob2");
++ break;
++ default:
++ sprintf(page_type, "unknown (type=%li)", fil_page_get_type(frame));
++ }
++
++ field_store_string(table->field[0], page_type);
++ table->field[1]->store(block->page.space);
++ table->field[2]->store(block->page.offset);
++ table->field[3]->store(0);
++ table->field[4]->store(block->page.buf_fix_count);
++ table->field[5]->store(block->page.flush_type);
++
++ if (schema_table_store_record(thd, table)) {
++ status = 1;
++ break;
++ }
++
++ }
++ }
++
++ buf_pool_mutex_exit();
++
++ DBUG_RETURN(status);
++}
++
++/***********************************************************************
++Fill the dynamic table information_schema.innodb_buffer_pool_pages_index. */
++static
++int
++i_s_innodb_buffer_pool_pages_index_fill(
++/*================*/
++ /* out: 0 on success, 1 on failure */
++ THD* thd, /* in: thread */
++ TABLE_LIST* tables, /* in/out: tables to fill */
++ COND* cond) /* in: condition (ignored) */
++{
++ TABLE* table = (TABLE *) tables->table;
++ int status = 0;
++
++ ulint n_chunks, n_blocks;
++ dulint index_id;
++
++ buf_chunk_t* chunk;
++
++ DBUG_ENTER("i_s_innodb_buffer_pool_pages_index_fill");
++
++ /* deny access to non-superusers */
++ if (check_global_access(thd, PROCESS_ACL)) {
++
++ DBUG_RETURN(0);
++ }
++
++ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
++
++ buf_pool_mutex_enter();
++
++ chunk = buf_pool->chunks;
++
++ for (n_chunks = buf_pool->n_chunks; n_chunks--; chunk++) {
++ buf_block_t* block = chunk->blocks;
++
++ for (n_blocks = chunk->size; n_blocks--; block++) {
++ const buf_frame_t* frame = block->frame;
++
++ if (fil_page_get_type(frame) == FIL_PAGE_INDEX) {
++ index_id = btr_page_get_index_id(frame);
++ table->field[0]->store(ut_conv_dulint_to_longlong(index_id));
++ table->field[1]->store(block->page.space);
++ table->field[2]->store(block->page.offset);
++ table->field[3]->store(page_get_n_recs(frame));
++ table->field[4]->store(page_get_data_size(frame));
++ table->field[5]->store(block->is_hashed);
++ table->field[6]->store(block->page.access_time);
++ table->field[7]->store(block->page.newest_modification != 0);
++ table->field[8]->store(block->page.oldest_modification != 0);
++ table->field[9]->store(block->page.old);
++ table->field[10]->store(0);
++ table->field[11]->store(block->page.buf_fix_count);
++ table->field[12]->store(block->page.flush_type);
++
++ if (schema_table_store_record(thd, table)) {
++ status = 1;
++ break;
++ }
++ }
++ }
++ }
++
++ buf_pool_mutex_exit();
++
++ DBUG_RETURN(status);
++}
++
++/***********************************************************************
++Fill the dynamic table information_schema.innodb_buffer_pool_pages_index. */
++static
++int
++i_s_innodb_buffer_pool_pages_blob_fill(
++/*================*/
++ /* out: 0 on success, 1 on failure */
++ THD* thd, /* in: thread */
++ TABLE_LIST* tables, /* in/out: tables to fill */
++ COND* cond) /* in: condition (ignored) */
++{
++ TABLE* table = (TABLE *) tables->table;
++ int status = 0;
++
++ ulint n_chunks, n_blocks;
++ buf_chunk_t* chunk;
++ page_zip_des_t* block_page_zip;
++
++ ulint part_len;
++ ulint next_page_no;
++
++ DBUG_ENTER("i_s_innodb_buffer_pool_pages_blob_fill");
++
++ /* deny access to non-superusers */
++ if (check_global_access(thd, PROCESS_ACL)) {
++
++ DBUG_RETURN(0);
++ }
++
++ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
++
++ buf_pool_mutex_enter();
++
++ chunk = buf_pool->chunks;
++
++ for (n_chunks = buf_pool->n_chunks; n_chunks--; chunk++) {
++ buf_block_t* block = chunk->blocks;
++ block_page_zip = buf_block_get_page_zip(block);
++
++ for (n_blocks = chunk->size; n_blocks--; block++) {
++ const buf_frame_t* frame = block->frame;
++
++ if (fil_page_get_type(frame) == FIL_PAGE_TYPE_BLOB) {
++
++ if (UNIV_LIKELY_NULL(block_page_zip)) {
++ part_len = 0; /* hmm, can't figure it out */
++
++ next_page_no = mach_read_from_4(
++ buf_block_get_frame(block)
++ + FIL_PAGE_NEXT);
++ } else {
++ part_len = mach_read_from_4(
++ buf_block_get_frame(block)
++ + FIL_PAGE_DATA
++ + 0 /*BTR_BLOB_HDR_PART_LEN*/);
++
++ next_page_no = mach_read_from_4(
++ buf_block_get_frame(block)
++ + FIL_PAGE_DATA
++ + 4 /*BTR_BLOB_HDR_NEXT_PAGE_NO*/);
++ }
++
++ table->field[0]->store(block->page.space);
++ table->field[1]->store(block->page.offset);
++ table->field[2]->store(block_page_zip != NULL);
++ table->field[3]->store(part_len);
++
++ if(next_page_no == FIL_NULL)
++ {
++ table->field[4]->store(0);
++ } else {
++ table->field[4]->store(block->page.offset);
++ }
++
++ table->field[5]->store(0);
++ table->field[6]->store(block->page.buf_fix_count);
++ table->field[7]->store(block->page.flush_type);
++
++ if (schema_table_store_record(thd, table)) {
++ status = 1;
++ break;
++ }
++
++ }
++ }
++ }
++
++ buf_pool_mutex_exit();
++
++ DBUG_RETURN(status);
++}
++
++/***********************************************************************
++Bind the dynamic table information_schema.innodb_buffer_pool_pages. */
++static
++int
++i_s_innodb_buffer_pool_pages_init(
++/*=========*/
++ /* out: 0 on success */
++ void* p) /* in/out: table schema object */
++{
++ DBUG_ENTER("i_s_innodb_buffer_pool_pages_init");
++ ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
++
++ schema->fields_info = i_s_innodb_buffer_pool_pages_fields_info;
++ schema->fill_table = i_s_innodb_buffer_pool_pages_fill;
++
++ DBUG_RETURN(0);
++}
++
++/***********************************************************************
++Bind the dynamic table information_schema.innodb_buffer_pool_pages. */
++static
++int
++i_s_innodb_buffer_pool_pages_index_init(
++/*=========*/
++ /* out: 0 on success */
++ void* p) /* in/out: table schema object */
++{
++ DBUG_ENTER("i_s_innodb_buffer_pool_pages_index_init");
++ ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
++
++ schema->fields_info = i_s_innodb_buffer_pool_pages_index_fields_info;
++ schema->fill_table = i_s_innodb_buffer_pool_pages_index_fill;
++
++ DBUG_RETURN(0);
++}
++
++/***********************************************************************
++Bind the dynamic table information_schema.innodb_buffer_pool_pages. */
++static
++int
++i_s_innodb_buffer_pool_pages_blob_init(
++/*=========*/
++ /* out: 0 on success */
++ void* p) /* in/out: table schema object */
++{
++ DBUG_ENTER("i_s_innodb_buffer_pool_pages_blob_init");
++ ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
++
++ schema->fields_info = i_s_innodb_buffer_pool_pages_blob_fields_info;
++ schema->fill_table = i_s_innodb_buffer_pool_pages_blob_fill;
++
++ DBUG_RETURN(0);
++}
++
++
++UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages =
++{
++ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
++ /* int */
++ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
++
++ /* pointer to type-specific plugin descriptor */
++ /* void* */
++ STRUCT_FLD(info, &i_s_info),
++
++ /* plugin name */
++ /* const char* */
++ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES"),
++
++ /* plugin author (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(author, plugin_author),
++
++ /* general descriptive text (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(descr, "InnoDB buffer pool pages"),
++
++ /* the plugin license (PLUGIN_LICENSE_XXX) */
++ /* int */
++ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
++
++ /* the function to invoke when plugin is loaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_init),
++
++ /* the function to invoke when plugin is unloaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(deinit, i_s_common_deinit),
++
++ /* plugin version (for SHOW PLUGINS) */
++ /* unsigned int */
++ STRUCT_FLD(version, 0x0100 /* 1.0 */),
++
++ /* struct st_mysql_show_var* */
++ STRUCT_FLD(status_vars, NULL),
++
++ /* struct st_mysql_sys_var** */
++ STRUCT_FLD(system_vars, NULL),
++
++ /* reserved for dependency checking */
++ /* void* */
++ STRUCT_FLD(__reserved1, NULL)
++};
++
++UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_index =
++{
++ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
++ /* int */
++ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
++
++ /* pointer to type-specific plugin descriptor */
++ /* void* */
++ STRUCT_FLD(info, &i_s_info),
++
++ /* plugin name */
++ /* const char* */
++ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES_INDEX"),
++
++ /* plugin author (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(author, plugin_author),
++
++ /* general descriptive text (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(descr, "InnoDB buffer pool index pages"),
++
++ /* the plugin license (PLUGIN_LICENSE_XXX) */
++ /* int */
++ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
++
++ /* the function to invoke when plugin is loaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_index_init),
++
++ /* the function to invoke when plugin is unloaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(deinit, i_s_common_deinit),
++
++ /* plugin version (for SHOW PLUGINS) */
++ /* unsigned int */
++ STRUCT_FLD(version, 0x0100 /* 1.0 */),
++
++ /* struct st_mysql_show_var* */
++ STRUCT_FLD(status_vars, NULL),
++
++ /* struct st_mysql_sys_var** */
++ STRUCT_FLD(system_vars, NULL),
++
++ /* reserved for dependency checking */
++ /* void* */
++ STRUCT_FLD(__reserved1, NULL)
++};
++
++UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_pool_pages_blob =
++{
++ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
++ /* int */
++ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
++
++ /* pointer to type-specific plugin descriptor */
++ /* void* */
++ STRUCT_FLD(info, &i_s_info),
++
++ /* plugin name */
++ /* const char* */
++ STRUCT_FLD(name, "INNODB_BUFFER_POOL_PAGES_BLOB"),
++
++ /* plugin author (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(author, plugin_author),
++
++ /* general descriptive text (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(descr, "InnoDB buffer pool blob pages"),
++
++ /* the plugin license (PLUGIN_LICENSE_XXX) */
++ /* int */
++ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
++
++ /* the function to invoke when plugin is loaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(init, i_s_innodb_buffer_pool_pages_blob_init),
++
++ /* the function to invoke when plugin is unloaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(deinit, i_s_common_deinit),
++
++ /* plugin version (for SHOW PLUGINS) */
++ /* unsigned int */
++ STRUCT_FLD(version, 0x0100 /* 1.0 */),
++
++ /* struct st_mysql_show_var* */
++ STRUCT_FLD(status_vars, NULL),
++
++ /* struct st_mysql_sys_var** */
++ STRUCT_FLD(system_vars, NULL),
++
++ /* reserved for dependency checking */
++ /* void* */
++ STRUCT_FLD(__reserved1, NULL)
++};
++
++
+ /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */
+ static ST_FIELD_INFO innodb_trx_fields_info[] =
+ {
+diff -ruN a/storage/innodb_plugin/handler/i_s.h b/storage/innodb_plugin/handler/i_s.h
+--- a/storage/innodb_plugin/handler/i_s.h 2010-04-29 15:28:20.000000000 +0900
++++ b/storage/innodb_plugin/handler/i_s.h 2010-04-29 16:04:05.000000000 +0900
+@@ -26,6 +26,9 @@
+ #ifndef i_s_h
+ #define i_s_h
+
++extern struct st_mysql_plugin i_s_innodb_buffer_pool_pages;
++extern struct st_mysql_plugin i_s_innodb_buffer_pool_pages_index;
++extern struct st_mysql_plugin i_s_innodb_buffer_pool_pages_blob;
+ extern struct st_mysql_plugin i_s_innodb_trx;
+ extern struct st_mysql_plugin i_s_innodb_locks;
+ extern struct st_mysql_plugin i_s_innodb_lock_waits;
+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-04-29 16:03:34.000000000 +0900
++++ b/storage/innodb_plugin/handler/innodb_patch_info.h 2010-04-29 16:04:05.000000000 +0900
+@@ -27,5 +27,6 @@
+ {"innodb_show_status","Improvements to SHOW INNODB STATUS","Memory information and lock info fixes","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_io","Improvements to InnoDB IO","","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_opt_lru_count","Fix of buffer_pool mutex","Decreases contention on buffer_pool mutex on LRU operations","http://www.percona.com/docs/wiki/percona-xtradb"},
++{"innodb_buffer_pool_pages","Information of buffer pool content","","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 15:57:23.333331973 +0900
++++ b/storage/innodb_plugin/include/buf0buf.h 2010-07-14 16:03:45.885392395 +0900
+@@ -1286,6 +1286,15 @@
+ #define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b))
+ /* @} */
+
++/** A chunk of buffers. The buffer pool is allocated in chunks. */
++struct buf_chunk_struct{
++ ulint mem_size; /*!< allocated size of the chunk */
++ ulint size; /*!< size of frames[] and blocks[] */
++ void* mem; /*!< pointer to the memory area which
++ was allocated for the frames */
++ buf_block_t* blocks; /*!< array of buffer control blocks */
++};
++
+ /** @brief The buffer pool statistics structure. */
+ struct buf_pool_stat_struct{
+ ulint n_page_gets; /*!< number of page gets performed;
diff --git a/mysql-innodb_adjust_defaults.patch b/mysql-innodb_adjust_defaults.patch
new file mode 100644
index 0000000..e08a02b
--- /dev/null
+++ b/mysql-innodb_adjust_defaults.patch
@@ -0,0 +1,48 @@
+# name : innodb_adjust_defaults.patch
+# introduced : 11 or before
+# maintainer : Yasufumi
+#
+#!!! notice !!!
+# Any small change to this file in the main branch
+# should be done or reviewed by the maintainer!
+diff -ruN a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
+--- a/storage/innodb_plugin/handler/ha_innodb.cc 2010-04-30 16:39:14.000000000 +0900
++++ b/storage/innodb_plugin/handler/ha_innodb.cc 2010-04-30 16:43:26.000000000 +0900
+@@ -11178,7 +11178,7 @@
+ static MYSQL_SYSVAR_ULONG(use_purge_thread, srv_use_purge_thread,
+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
+ "Number of purge devoted threads. #### over 1 is EXPERIMENTAL ####",
+- NULL, NULL, 0, 0, 64, 0);
++ NULL, NULL, 1, 0, 64, 0);
+
+ static MYSQL_SYSVAR_BOOL(overwrite_relay_log_info, innobase_overwrite_relay_log_info,
+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
+@@ -11278,7 +11278,7 @@
+ static MYSQL_SYSVAR_BOOL(adaptive_flushing, srv_adaptive_flushing,
+ PLUGIN_VAR_NOCMDARG,
+ "Attempt flushing dirty pages to avoid IO bursts at checkpoints.",
+- NULL, NULL, TRUE);
++ NULL, NULL, FALSE);
+
+ static MYSQL_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
+ PLUGIN_VAR_RQCMDARG,
+@@ -11523,7 +11523,7 @@
+ static MYSQL_SYSVAR_ULONG(ibuf_active_contract, srv_ibuf_active_contract,
+ PLUGIN_VAR_RQCMDARG,
+ "Enable/Disable active_contract of insert buffer. 0:disable 1:enable",
+- NULL, NULL, 0, 0, 1, 0);
++ NULL, NULL, 1, 0, 1, 0);
+
+ static MYSQL_SYSVAR_ULONG(ibuf_accel_rate, srv_ibuf_accel_rate,
+ PLUGIN_VAR_RQCMDARG,
+@@ -11601,8 +11601,8 @@
+ };
+ static MYSQL_SYSVAR_ENUM(adaptive_checkpoint, srv_adaptive_checkpoint,
+ PLUGIN_VAR_RQCMDARG,
+- "Enable/Disable flushing along modified age. ([none], reflex, estimate)",
+- NULL, innodb_adaptive_checkpoint_update, 0, &adaptive_checkpoint_typelib);
++ "Enable/Disable flushing along modified age. (none, reflex, [estimate])",
++ NULL, innodb_adaptive_checkpoint_update, 2, &adaptive_checkpoint_typelib);
+
+ static MYSQL_SYSVAR_ULONG(enable_unsafe_group_commit, srv_enable_unsafe_group_commit,
+ PLUGIN_VAR_RQCMDARG,
diff --git a/mysql-innodb_admin_command_base.patch b/mysql-innodb_admin_command_base.patch
new file mode 100644
index 0000000..2619ed9
--- /dev/null
+++ b/mysql-innodb_admin_command_base.patch
@@ -0,0 +1,181 @@
+# name : innodb_admin_command_base.patch
+# introduced : 11 or before
+# maintainer : Yasufumi
+#
+#!!! notice !!!
+# Any small change to this file in the main branch
+# should be done or reviewed by the maintainer!
+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:27:30.222410116 +0900
++++ b/storage/innodb_plugin/handler/ha_innodb.cc 2010-08-27 16:27:44.073104773 +0900
+@@ -11532,6 +11532,7 @@
+ i_s_innodb_cmpmem_reset,
+ i_s_innodb_table_stats,
+ i_s_innodb_index_stats,
++i_s_innodb_admin_command,
+ i_s_innodb_patches
+ mysql_declare_plugin_end;
+
+diff -ruN a/storage/innodb_plugin/handler/i_s.cc b/storage/innodb_plugin/handler/i_s.cc
+--- a/storage/innodb_plugin/handler/i_s.cc 2010-08-27 16:22:04.261021936 +0900
++++ b/storage/innodb_plugin/handler/i_s.cc 2010-08-27 16:27:44.077058655 +0900
+@@ -2948,3 +2948,139 @@
+ STRUCT_FLD(system_vars, NULL),
+ STRUCT_FLD(__reserved1, NULL)
+ };
++
++/***********************************************************************
++*/
++static ST_FIELD_INFO i_s_innodb_admin_command_info[] =
++{
++ {STRUCT_FLD(field_name, "result_message"),
++ STRUCT_FLD(field_length, 1024),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ END_OF_ST_FIELD_INFO
++};
++
++#ifndef INNODB_COMPATIBILITY_HOOKS
++#error InnoDB needs MySQL to be built with #define INNODB_COMPATIBILITY_HOOKS
++#endif
++
++extern "C" {
++char **thd_query(MYSQL_THD thd);
++}
++
++static
++int
++i_s_innodb_admin_command_fill(
++/*==========================*/
++ THD* thd,
++ TABLE_LIST* tables,
++ COND* cond)
++{
++ TABLE* i_s_table = (TABLE *) tables->table;
++ char** query_str;
++ char* ptr;
++ char quote = '\0';
++ const char* command_head = "XTRA_";
++
++ DBUG_ENTER("i_s_innodb_admin_command_fill");
++
++ /* deny access to non-superusers */
++ if (check_global_access(thd, PROCESS_ACL)) {
++ DBUG_RETURN(0);
++ }
++
++ if(thd_sql_command(thd) != SQLCOM_SELECT) {
++ field_store_string(i_s_table->field[0],
++ "SELECT command is only accepted.");
++ goto end_func;
++ }
++
++ query_str = thd_query(thd);
++ ptr = *query_str;
++
++ for (; *ptr; ptr++) {
++ if (*ptr == quote) {
++ quote = '\0';
++ } else if (quote) {
++ } else if (*ptr == '`' || *ptr == '"') {
++ quote = *ptr;
++ } else {
++ long i;
++ for (i = 0; command_head[i]; i++) {
++ if (toupper((int)(unsigned char)(ptr[i]))
++ != toupper((int)(unsigned char)
++ (command_head[i]))) {
++ goto nomatch;
++ }
++ }
++ break;
++nomatch:
++ ;
++ }
++ }
++
++ if (!*ptr) {
++ field_store_string(i_s_table->field[0],
++ "No XTRA_* command in the SQL statement."
++ " Please add /*!XTRA_xxxx*/ to the SQL.");
++ goto end_func;
++ }
++
++ if (!strncasecmp("XTRA_HELLO", ptr, 10)) {
++ /* This is example command XTRA_HELLO */
++
++ ut_print_timestamp(stderr);
++ fprintf(stderr, " InnoDB: administration command test for XtraDB"
++ " 'XTRA_HELLO' was detected.\n");
++
++ field_store_string(i_s_table->field[0],
++ "Hello!");
++ goto end_func;
++ }
++
++ field_store_string(i_s_table->field[0],
++ "Undefined XTRA_* command.");
++ goto end_func;
++
++end_func:
++ if (schema_table_store_record(thd, i_s_table)) {
++ DBUG_RETURN(1);
++ } else {
++ DBUG_RETURN(0);
++ }
++}
++
++static
++int
++i_s_innodb_admin_command_init(
++/*==========================*/
++ void* p)
++{
++ DBUG_ENTER("i_s_innodb_admin_command_init");
++ ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
++
++ schema->fields_info = i_s_innodb_admin_command_info;
++ schema->fill_table = i_s_innodb_admin_command_fill;
++
++ DBUG_RETURN(0);
++}
++
++UNIV_INTERN struct st_mysql_plugin i_s_innodb_admin_command =
++{
++ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
++ STRUCT_FLD(info, &i_s_info),
++ STRUCT_FLD(name, "XTRADB_ADMIN_COMMAND"),
++ STRUCT_FLD(author, plugin_author),
++ STRUCT_FLD(descr, "XtraDB specific command acceptor"),
++ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
++ STRUCT_FLD(init, i_s_innodb_admin_command_init),
++ STRUCT_FLD(deinit, i_s_common_deinit),
++ STRUCT_FLD(version, 0x0100 /* 1.0 */),
++ STRUCT_FLD(status_vars, NULL),
++ STRUCT_FLD(system_vars, NULL),
++ STRUCT_FLD(__reserved1, NULL)
++};
+diff -ruN a/storage/innodb_plugin/handler/i_s.h b/storage/innodb_plugin/handler/i_s.h
+--- a/storage/innodb_plugin/handler/i_s.h 2010-08-27 16:22:04.261987654 +0900
++++ b/storage/innodb_plugin/handler/i_s.h 2010-08-27 16:27:44.079059299 +0900
+@@ -40,5 +40,6 @@
+ extern struct st_mysql_plugin i_s_innodb_rseg;
+ extern struct st_mysql_plugin i_s_innodb_table_stats;
+ extern struct st_mysql_plugin i_s_innodb_index_stats;
++extern struct st_mysql_plugin i_s_innodb_admin_command;
+
+ #endif /* i_s_h */
+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-08-27 16:27:30.223001821 +0900
++++ b/storage/innodb_plugin/handler/innodb_patch_info.h 2010-08-27 16:27:44.074104321 +0900
+@@ -38,5 +38,6 @@
+ {"innodb_stats","Additional features about InnoDB statistics/optimizer","","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_recovery_patches","Bugfixes and adjustments about recovery process","","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_purge_thread","Enable to use purge devoted thread","","http://www.percona.com/docs/wiki/percona-xtradb"},
++{"innodb_admin_command_base","XtraDB specific command interface through i_s","","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {NULL, NULL, NULL, NULL}
+ };
diff --git a/mysql-innodb_deadlock_count.patch b/mysql-innodb_deadlock_count.patch
new file mode 100644
index 0000000..7a33d6a
--- /dev/null
+++ b/mysql-innodb_deadlock_count.patch
@@ -0,0 +1,73 @@
+# name : innodb_deadlock_count.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/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-10 15:32:14.468241191 +0400
++++ b/storage/innodb_plugin/handler/ha_innodb.cc 2010-08-10 15:32:14.926992081 +0400
+@@ -546,6 +546,8 @@
+ (char*) &export_vars.innodb_data_written, SHOW_LONG},
+ {"dblwr_pages_written",
+ (char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG},
++ {"deadlocks",
++ (char*) &export_vars.innodb_deadlocks, SHOW_LONG},
+ {"dblwr_writes",
+ (char*) &export_vars.innodb_dblwr_writes, SHOW_LONG},
+ {"dict_tables",
+diff -ruN a/storage/innodb_plugin/include/lock0lock.h b/storage/innodb_plugin/include/lock0lock.h
+--- a/storage/innodb_plugin/include/lock0lock.h 2010-08-10 15:32:14.478241628 +0400
++++ b/storage/innodb_plugin/include/lock0lock.h 2010-08-10 15:32:14.926992081 +0400
+@@ -43,6 +43,7 @@
+ #endif /* UNIV_DEBUG */
+ /* Buffer for storing information about the most recent deadlock error */
+ extern FILE* lock_latest_err_file;
++extern ulint srv_n_lock_deadlock_count;
+
+ /*********************************************************************//**
+ Gets the size of a lock struct.
+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 @@
+ 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*/
++ ulint innodb_deadlocks; /* ??? */
+ ulint innodb_dblwr_pages_written; /*!< srv_dblwr_pages_written */
+ ulint innodb_dblwr_writes; /*!< srv_dblwr_writes */
+ ibool innodb_have_atomic_builtins; /*!< HAVE_ATOMIC_BUILTINS */
+diff -ruN a/storage/innodb_plugin/lock/lock0lock.c b/storage/innodb_plugin/lock/lock0lock.c
+--- a/storage/innodb_plugin/lock/lock0lock.c 2010-08-10 15:32:14.478241628 +0400
++++ b/storage/innodb_plugin/lock/lock0lock.c 2010-08-10 15:32:14.936991959 +0400
+@@ -3330,6 +3330,7 @@
+ break;
+
+ case LOCK_VICTIM_IS_START:
++ srv_n_lock_deadlock_count++;
+ fputs("*** WE ROLL BACK TRANSACTION (2)\n",
+ lock_latest_err_file);
+ break;
+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
+@@ -435,7 +435,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;
+-
++UNIV_INTERN ulint srv_n_lock_deadlock_count = 0;
+ UNIV_INTERN ulint srv_n_lock_wait_count = 0;
+ UNIV_INTERN ulint srv_n_lock_wait_current_count = 0;
+ UNIV_INTERN ib_int64_t srv_n_lock_wait_time = 0;
+@@ -2146,6 +2146,8 @@
+ = UT_LIST_GET_LEN(buf_pool->flush_list);
+ export_vars.innodb_buffer_pool_pages_free
+ = UT_LIST_GET_LEN(buf_pool->free);
++ export_vars.innodb_deadlocks
++ = srv_n_lock_deadlock_count;
+ #ifdef UNIV_DEBUG
+ export_vars.innodb_buffer_pool_pages_latched
+ = buf_get_latched_pages_number();
diff --git a/mysql-innodb_expand_import.patch b/mysql-innodb_expand_import.patch
new file mode 100644
index 0000000..98d9de2
--- /dev/null
+++ b/mysql-innodb_expand_import.patch
@@ -0,0 +1,555 @@
+# name : innodb_expand_import.patch
+# introduced : 11 or before
+# maintainer : Yasufumi
+#
+#!!! notice !!!
+# Any small change to this file in the main branch
+# should be done or reviewed by the maintainer!
+diff -ruN a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c
+--- a/storage/innodb_plugin/fil/fil0fil.c 2010-04-29 15:44:28.000000000 +0900
++++ b/storage/innodb_plugin/fil/fil0fil.c 2010-04-30 10:43:13.000000000 +0900
+@@ -40,6 +40,12 @@
+ #include "dict0dict.h"
+ #include "page0page.h"
+ #include "page0zip.h"
++#include "trx0trx.h"
++#include "trx0sys.h"
++#include "pars0pars.h"
++#include "row0mysql.h"
++#include "row0row.h"
++#include "que0que.h"
+ #ifndef UNIV_HOTBACKUP
+ # include "buf0lru.h"
+ # include "ibuf0ibuf.h"
+@@ -2983,7 +2989,7 @@
+ ut_a(!(flags & (~0UL << DICT_TF_BITS)));
+
+ file = os_file_create_simple_no_error_handling(
+- filepath, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
++ filepath, OS_FILE_OPEN, OS_FILE_READ_WRITE, &success);
+ if (!success) {
+ /* The following call prints an error message */
+ os_file_get_last_error(TRUE);
+@@ -3030,6 +3036,464 @@
+ space_id = fsp_header_get_space_id(page);
+ space_flags = fsp_header_get_flags(page);
+
++ if (srv_expand_import
++ && (space_id != id || space_flags != (flags & ~(~0 << DICT_TF_BITS)))) {
++ ibool file_is_corrupt = FALSE;
++ byte* buf3;
++ byte* descr_page;
++ ibool descr_is_corrupt = FALSE;
++ dulint old_id[31];
++ dulint new_id[31];
++ ulint root_page[31];
++ ulint n_index;
++ os_file_t info_file = -1;
++ char* info_file_path;
++ ulint i;
++ int len;
++ ib_uint64_t current_lsn;
++ ulint size_low, size_high, size, free_limit;
++ ib_int64_t size_bytes, free_limit_bytes;
++ dict_table_t* table;
++ dict_index_t* index;
++ fil_system_t* system;
++ fil_node_t* node = NULL;
++ fil_space_t* space;
++
++ buf3 = ut_malloc(2 * UNIV_PAGE_SIZE);
++ descr_page = ut_align(buf3, UNIV_PAGE_SIZE);
++
++ current_lsn = log_get_lsn();
++
++ /* check the header page's consistency */
++ if (buf_page_is_corrupted(page,
++ dict_table_flags_to_zip_size(space_flags))) {
++ fprintf(stderr, "InnoDB: page 0 of %s seems corrupt.\n", filepath);
++ file_is_corrupt = TRUE;
++ descr_is_corrupt = TRUE;
++ }
++
++ /* store as first descr page */
++ memcpy(descr_page, page, UNIV_PAGE_SIZE);
++
++ /* get free limit (page number) of the table space */
++/* these should be same to the definition in fsp0fsp.c */
++#define FSP_HEADER_OFFSET FIL_PAGE_DATA
++#define FSP_FREE_LIMIT 12
++ free_limit = mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT + page);
++ free_limit_bytes = (ib_int64_t)free_limit * (ib_int64_t)UNIV_PAGE_SIZE;
++
++ /* overwrite fsp header */
++ fsp_header_init_fields(page, id, flags);
++ mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, id);
++ space_id = id;
++ space_flags = flags;
++ if (mach_read_ull(page + FIL_PAGE_FILE_FLUSH_LSN) > current_lsn)
++ mach_write_ull(page + FIL_PAGE_FILE_FLUSH_LSN, current_lsn);
++ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
++ srv_use_checksums
++ ? buf_calc_page_new_checksum(page)
++ : BUF_NO_CHECKSUM_MAGIC);
++ mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
++ srv_use_checksums
++ ? buf_calc_page_old_checksum(page)
++ : BUF_NO_CHECKSUM_MAGIC);
++ success = os_file_write(filepath, file, page, 0, 0, UNIV_PAGE_SIZE);
++
++ /* get file size */
++ os_file_get_size(file, &size_low, &size_high);
++ size_bytes = (((ib_int64_t)size_high) << 32)
++ + (ib_int64_t)size_low;
++
++ if (size_bytes < free_limit_bytes) {
++ free_limit_bytes = size_bytes;
++ fprintf(stderr, "InnoDB: free limit of %s is larger than its real size.\n", filepath);
++ file_is_corrupt = TRUE;
++ }
++
++ /* get cruster index information */
++ table = dict_table_get_low(name);
++ index = dict_table_get_first_index(table);
++ ut_a(index->page==3);
++
++ /* read metadata from .exp file */
++ n_index = 0;
++ memset(old_id, 0, sizeof(old_id));
++ memset(new_id, 0, sizeof(new_id));
++ memset(root_page, 0, sizeof(root_page));
++
++ info_file_path = fil_make_ibd_name(name, FALSE);
++ len = strlen(info_file_path);
++ info_file_path[len - 3] = 'e';
++ info_file_path[len - 2] = 'x';
++ info_file_path[len - 1] = 'p';
++
++ info_file = os_file_create_simple_no_error_handling(
++ info_file_path, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
++ if (!success) {
++ fprintf(stderr, "InnoDB: cannot open %s\n", info_file_path);
++ file_is_corrupt = TRUE;
++ goto skip_info;
++ }
++ success = os_file_read(info_file, page, 0, 0, UNIV_PAGE_SIZE);
++ if (!success) {
++ fprintf(stderr, "InnoDB: cannot read %s\n", info_file_path);
++ file_is_corrupt = TRUE;
++ goto skip_info;
++ }
++ if (mach_read_from_4(page) != 0x78706f72UL
++ || mach_read_from_4(page + 4) != 0x74696e66UL) {
++ fprintf(stderr, "InnoDB: %s seems not to be a correct .exp file\n", info_file_path);
++ file_is_corrupt = TRUE;
++ goto skip_info;
++ }
++
++ fprintf(stderr, "InnoDB: import: extended import of %s is started.\n", name);
++
++ n_index = mach_read_from_4(page + 8);
++ fprintf(stderr, "InnoDB: import: %lu indexes are detected.\n", (ulong)n_index);
++ for (i = 0; i < n_index; i++) {
++ new_id[i] =
++ dict_table_get_index_on_name(table,
++ (char*)(page + (i + 1) * 512 + 12))->id;
++ old_id[i] = mach_read_from_8(page + (i + 1) * 512);
++ root_page[i] = mach_read_from_4(page + (i + 1) * 512 + 8);
++ }
++
++skip_info:
++ if (info_file != -1)
++ os_file_close(info_file);
++
++ /*
++ if (size_bytes >= 1024 * 1024) {
++ size_bytes = ut_2pow_round(size_bytes, 1024 * 1024);
++ }
++ */
++ if (!(flags & DICT_TF_ZSSIZE_MASK)) {
++ mem_heap_t* heap = NULL;
++ ulint offsets_[REC_OFFS_NORMAL_SIZE];
++ ulint* offsets = offsets_;
++ ib_int64_t offset;
++
++ size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
++ /* over write space id of all pages */
++ rec_offs_init(offsets_);
++
++ fprintf(stderr, "InnoDB: Progress in %%:");
++
++ for (offset = 0; offset < free_limit_bytes; offset += UNIV_PAGE_SIZE) {
++ ulint checksum_field;
++ ulint old_checksum_field;
++ ibool page_is_corrupt;
++
++ success = os_file_read(file, page,
++ (ulint)(offset & 0xFFFFFFFFUL),
++ (ulint)(offset >> 32), UNIV_PAGE_SIZE);
++
++ page_is_corrupt = FALSE;
++
++ /* check consistency */
++ if (memcmp(page + FIL_PAGE_LSN + 4,
++ page + UNIV_PAGE_SIZE
++ - FIL_PAGE_END_LSN_OLD_CHKSUM + 4, 4)) {
++
++ page_is_corrupt = TRUE;
++ }
++
++ if (mach_read_from_4(page + FIL_PAGE_OFFSET)
++ != offset / UNIV_PAGE_SIZE) {
++
++ page_is_corrupt = TRUE;
++ }
++
++ checksum_field = mach_read_from_4(page
++ + FIL_PAGE_SPACE_OR_CHKSUM);
++
++ old_checksum_field = mach_read_from_4(
++ page + UNIV_PAGE_SIZE
++ - FIL_PAGE_END_LSN_OLD_CHKSUM);
++
++ if (old_checksum_field != mach_read_from_4(page
++ + FIL_PAGE_LSN)
++ && old_checksum_field != BUF_NO_CHECKSUM_MAGIC
++ && old_checksum_field
++ != buf_calc_page_old_checksum(page)) {
++
++ page_is_corrupt = TRUE;
++ }
++
++ if (checksum_field != 0
++ && checksum_field != BUF_NO_CHECKSUM_MAGIC
++ && checksum_field
++ != buf_calc_page_new_checksum(page)) {
++
++ page_is_corrupt = TRUE;
++ }
++
++ /* if it is free page, inconsistency is acceptable */
++ if (!offset) {
++ /* header page*/
++ /* it should be overwritten already */
++ ut_a(!page_is_corrupt);
++
++ } else if (!((offset / UNIV_PAGE_SIZE) % UNIV_PAGE_SIZE)) {
++ /* descr page (not header) */
++ if (page_is_corrupt) {
++ file_is_corrupt = TRUE;
++ descr_is_corrupt = TRUE;
++ } else {
++ ut_a(fil_page_get_type(page) == FIL_PAGE_TYPE_XDES);
++ descr_is_corrupt = FALSE;
++ }
++
++ /* store as descr page */
++ memcpy(descr_page, page, UNIV_PAGE_SIZE);
++
++ } else if (descr_is_corrupt) {
++ /* unknown state of the page */
++ if (page_is_corrupt) {
++ file_is_corrupt = TRUE;
++ }
++
++ } else {
++ /* check free page or not */
++ /* These definitions should be same to fsp0fsp.c */
++#define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE)
++
++#define XDES_BITMAP (FLST_NODE_SIZE + 12)
++#define XDES_BITS_PER_PAGE 2
++#define XDES_FREE_BIT 0
++#define XDES_SIZE \
++ (XDES_BITMAP + UT_BITS_IN_BYTES(FSP_EXTENT_SIZE * XDES_BITS_PER_PAGE))
++#define XDES_ARR_OFFSET (FSP_HEADER_OFFSET + FSP_HEADER_SIZE)
++
++ /*descr = descr_page + XDES_ARR_OFFSET + XDES_SIZE * xdes_calc_descriptor_index(zip_size, offset)*/
++ /*xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)*/
++ byte* descr;
++ ulint index;
++ ulint byte_index;
++ ulint bit_index;
++
++ descr = descr_page + XDES_ARR_OFFSET
++ + XDES_SIZE * (ut_2pow_remainder((offset / UNIV_PAGE_SIZE), UNIV_PAGE_SIZE) / FSP_EXTENT_SIZE);
++
++ index = XDES_FREE_BIT + XDES_BITS_PER_PAGE * ((offset / UNIV_PAGE_SIZE) % FSP_EXTENT_SIZE);
++ byte_index = index / 8;
++ bit_index = index % 8;
++
++ if (ut_bit_get_nth(mach_read_from_1(descr + XDES_BITMAP + byte_index), bit_index)) {
++ /* free page */
++ if (page_is_corrupt) {
++ goto skip_write;
++ }
++ } else {
++ /* not free */
++ if (page_is_corrupt) {
++ file_is_corrupt = TRUE;
++ }
++ }
++ }
++
++ if (page_is_corrupt) {
++ fprintf(stderr, " [errp:%lld]", offset / UNIV_PAGE_SIZE);
++
++ /* cannot treat corrupt page */
++ goto skip_write;
++ }
++
++ if (mach_read_from_4(page + FIL_PAGE_OFFSET) || !offset) {
++ mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, id);
++
++ for (i = 0; i < n_index; i++) {
++ if (offset / UNIV_PAGE_SIZE == root_page[i]) {
++ /* this is index root page */
++ mach_write_to_4(page + FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
++ + FSEG_HDR_SPACE, id);
++ mach_write_to_4(page + FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
++ + FSEG_HDR_SPACE, id);
++ break;
++ }
++ }
++
++ if (fil_page_get_type(page) == FIL_PAGE_INDEX) {
++ dulint tmp = mach_read_from_8(page + (PAGE_HEADER + PAGE_INDEX_ID));
++
++ if (mach_read_from_2(page + PAGE_HEADER + PAGE_LEVEL) == 0
++ && ut_dulint_cmp(old_id[0], tmp) == 0) {
++ /* leaf page of cluster index, reset trx_id of records */
++ rec_t* rec;
++ rec_t* supremum;
++ ulint n_recs;
++
++ supremum = page_get_supremum_rec(page);
++ rec = page_rec_get_next(page_get_infimum_rec(page));
++ n_recs = page_get_n_recs(page);
++
++ while (rec && rec != supremum && n_recs > 0) {
++ ulint n_fields;
++ ulint i;
++ ulint offset = index->trx_id_offset;
++ offsets = rec_get_offsets(rec, index, offsets,
++ ULINT_UNDEFINED, &heap);
++ n_fields = rec_offs_n_fields(offsets);
++ if (!offset) {
++ offset = row_get_trx_id_offset(rec, index, offsets);
++ }
++ trx_write_trx_id(rec + offset, ut_dulint_create(0, 1));
++
++ for (i = 0; i < n_fields; i++) {
++ if (rec_offs_nth_extern(offsets, i)) {
++ ulint local_len;
++ byte* data;
++
++ data = rec_get_nth_field(rec, offsets, i, &local_len);
++
++ local_len -= BTR_EXTERN_FIELD_REF_SIZE;
++
++ mach_write_to_4(data + local_len + BTR_EXTERN_SPACE_ID, id);
++ }
++ }
++
++ rec = page_rec_get_next(rec);
++ n_recs--;
++ }
++ }
++
++ for (i = 0; i < n_index; i++) {
++ if (ut_dulint_cmp(old_id[i], tmp) == 0) {
++ mach_write_to_8(page + (PAGE_HEADER + PAGE_INDEX_ID), new_id[i]);
++ break;
++ }
++ }
++ }
++
++ if (mach_read_ull(page + FIL_PAGE_LSN) > current_lsn) {
++ mach_write_ull(page + FIL_PAGE_LSN, current_lsn);
++ mach_write_ull(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
++ current_lsn);
++ }
++
++ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
++ srv_use_checksums
++ ? buf_calc_page_new_checksum(page)
++ : BUF_NO_CHECKSUM_MAGIC);
++ mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
++ srv_use_checksums
++ ? buf_calc_page_old_checksum(page)
++ : BUF_NO_CHECKSUM_MAGIC);
++
++ success = os_file_write(filepath, file, page,
++ (ulint)(offset & 0xFFFFFFFFUL),
++ (ulint)(offset >> 32), UNIV_PAGE_SIZE);
++ }
++
++skip_write:
++ if (free_limit_bytes
++ && ((ib_int64_t)((offset + UNIV_PAGE_SIZE) * 100) / free_limit_bytes)
++ != ((offset * 100) / free_limit_bytes)) {
++ fprintf(stderr, " %lu",
++ (ulong)((ib_int64_t)((offset + UNIV_PAGE_SIZE) * 100) / free_limit_bytes));
++ }
++ }
++
++ fprintf(stderr, " done.\n");
++
++ /* update SYS_INDEXES set root page */
++ index = dict_table_get_first_index(table);
++ while (index) {
++ for (i = 0; i < n_index; i++) {
++ if (ut_dulint_cmp(new_id[i], index->id) == 0) {
++ break;
++ }
++ }
++
++ if (i != n_index
++ && root_page[i] != index->page) {
++ /* must update */
++ ulint error;
++ trx_t* trx;
++ pars_info_t* info = NULL;
++
++ trx = trx_allocate_for_mysql();
++ trx->op_info = "extended import";
++
++ info = pars_info_create();
++
++ pars_info_add_dulint_literal(info, "indexid", new_id[i]);
++ pars_info_add_int4_literal(info, "new_page", (lint) root_page[i]);
++
++ error = que_eval_sql(info,
++ "PROCEDURE UPDATE_INDEX_PAGE () IS\n"
++ "BEGIN\n"
++ "UPDATE SYS_INDEXES"
++ " SET PAGE_NO = :new_page"
++ " WHERE ID = :indexid;\n"
++ "COMMIT WORK;\n"
++ "END;\n",
++ FALSE, trx);
++
++ if (error != DB_SUCCESS) {
++ fprintf(stderr, "InnoDB: failed to update SYS_INDEXES\n");
++ }
++
++ trx_commit_for_mysql(trx);
++
++ trx_free_for_mysql(trx);
++
++ index->page = root_page[i];
++ }
++
++ index = dict_table_get_next_index(index);
++ }
++ if (UNIV_LIKELY_NULL(heap)) {
++ mem_heap_free(heap);
++ }
++ } else {
++ /* zip page? */
++ size = (ulint)
++ (size_bytes
++ / dict_table_flags_to_zip_size(flags));
++ fprintf(stderr, "InnoDB: import: table %s seems to be in newer format."
++ " It may not be able to treated for now.\n", name);
++ }
++ /* .exp file should be removed */
++ success = os_file_delete(info_file_path);
++ if (!success) {
++ success = os_file_delete_if_exists(info_file_path);
++ }
++ mem_free(info_file_path);
++
++ system = fil_system;
++ mutex_enter(&(system->mutex));
++ space = fil_space_get_by_id(id);
++ if (space)
++ node = UT_LIST_GET_FIRST(space->chain);
++ if (node && node->size < size) {
++ space->size += (size - node->size);
++ node->size = size;
++ }
++ mutex_exit(&(system->mutex));
++
++ ut_free(buf3);
++
++ if (file_is_corrupt) {
++ ut_print_timestamp(stderr);
++ fputs(" InnoDB: Error: file ",
++ stderr);
++ ut_print_filename(stderr, filepath);
++ fprintf(stderr, " seems to be corrupt.\n"
++ "InnoDB: anyway, all not corrupt pages were tried to be converted to salvage.\n"
++ "InnoDB: ##### CAUTION #####\n"
++ "InnoDB: ## The .ibd must cause to crash InnoDB, though re-import would seem to be succeeded.\n"
++ "InnoDB: ## If you don't have knowledge about salvaging data from .ibd, you should not use the file.\n"
++ "InnoDB: ###################\n");
++ success = FALSE;
++
++ ut_free(buf2);
++
++ goto func_exit;
++ }
++ }
++
+ ut_free(buf2);
+
+ if (UNIV_UNLIKELY(space_id != id
+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-04-29 16:54:08.000000000 +0900
++++ b/storage/innodb_plugin/handler/ha_innodb.cc 2010-04-30 10:28:05.000000000 +0900
+@@ -11305,6 +11305,11 @@
+ "Enable/Disable unsafe group commit when support_xa=OFF and use with binlog or other XA storage engine.",
+ NULL, NULL, 0, 0, 1, 0);
+
++static MYSQL_SYSVAR_ULONG(expand_import, srv_expand_import,
++ PLUGIN_VAR_RQCMDARG,
++ "Enable/Disable converting automatically *.ibd files when import tablespace.",
++ NULL, NULL, 0, 0, 1, 0);
++
+ static MYSQL_SYSVAR_ULONG(extra_rsegments, srv_extra_rsegments,
+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
+ "Number of extra user rollback segments when create new database.",
+@@ -11381,6 +11386,7 @@
+ MYSQL_SYSVAR(adaptive_checkpoint),
+ MYSQL_SYSVAR(flush_log_at_trx_commit_session),
+ MYSQL_SYSVAR(enable_unsafe_group_commit),
++ MYSQL_SYSVAR(expand_import),
+ MYSQL_SYSVAR(extra_rsegments),
+ MYSQL_SYSVAR(dict_size_limit),
+ MYSQL_SYSVAR(use_sys_malloc),
+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-04-29 18:58:20.000000000 +0900
++++ b/storage/innodb_plugin/handler/innodb_patch_info.h 2010-04-30 10:28:05.000000000 +0900
+@@ -32,6 +32,7 @@
+ {"innodb_extra_rseg","allow to create extra rollback segments","When create new db, the new parameter allows to create more rollback segments","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_overwrite_relay_log_info","overwrite relay-log.info when slave recovery","Building as plugin, it is not used.","http://www.percona.com/docs/wiki/percona-xtradb:innodb_overwrite_relay_log_info"},
+ {"innodb_thread_concurrency_timer_based","use InnoDB timer based concurrency throttling (backport from MySQL 5.4.0)","",""},
++{"innodb_expand_import","convert .ibd file automatically when import tablespace","the files are generated by xtrabackup export mode.","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_dict_size_limit","Limit dictionary cache size","Variable innodb_dict_size_limit in bytes","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_split_buf_pool_mutex","More fix of buffer_pool mutex","Spliting buf_pool_mutex and optimizing based on innodb_opt_lru_count","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {NULL, NULL, NULL, NULL}
+diff -ruN a/storage/innodb_plugin/include/srv0srv.h b/storage/innodb_plugin/include/srv0srv.h
+--- a/storage/innodb_plugin/include/srv0srv.h 2010-04-29 16:54:08.000000000 +0900
++++ b/storage/innodb_plugin/include/srv0srv.h 2010-04-30 10:28:05.000000000 +0900
+@@ -213,6 +213,8 @@
+ extern ulint srv_read_ahead;
+ extern ulint srv_adaptive_checkpoint;
+
++extern ulint srv_expand_import;
++
+ extern ulint srv_extra_rsegments;
+ extern ulint srv_dict_size_limit;
+ /*-------------------------------------------*/
+diff -ruN a/storage/innodb_plugin/srv/srv0srv.c b/storage/innodb_plugin/srv/srv0srv.c
+--- a/storage/innodb_plugin/srv/srv0srv.c 2010-04-29 18:58:20.000000000 +0900
++++ b/storage/innodb_plugin/srv/srv0srv.c 2010-04-30 10:28:05.000000000 +0900
+@@ -385,6 +385,8 @@
+ UNIV_INTERN ulint srv_read_ahead = 3; /* 1: random 2: linear 3: Both */
+ UNIV_INTERN ulint srv_adaptive_checkpoint = 0; /* 0: none 1: reflex 2: estimate */
+
++UNIV_INTERN ulint srv_expand_import = 0; /* 0:disable 1:enable */
++
+ UNIV_INTERN ulint srv_extra_rsegments = 0; /* extra rseg for users */
+ UNIV_INTERN ulint srv_dict_size_limit = 0;
+ /*-------------------------------------------*/
diff --git a/mysql-innodb_expand_undo_slots.patch b/mysql-innodb_expand_undo_slots.patch
new file mode 100644
index 0000000..29a07e8
--- /dev/null
+++ b/mysql-innodb_expand_undo_slots.patch
@@ -0,0 +1,150 @@
+# name : innodb_expand_undo_slots.patch
+# introduced : 11 or before
+# maintainer : Yasufumi
+#
+#!!! notice !!!
+# Any small change to this file in the main branch
+# should be done or reviewed by the maintainer!
+diff -ruN a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
+--- a/storage/innodb_plugin/handler/ha_innodb.cc 2010-04-29 16:06:22.000000000 +0900
++++ b/storage/innodb_plugin/handler/ha_innodb.cc 2010-04-29 16:06:59.000000000 +0900
+@@ -165,6 +165,7 @@
+ #endif /* UNIV_LOG_ARCHIVE */
+ static my_bool innobase_use_doublewrite = TRUE;
+ static my_bool innobase_use_checksums = TRUE;
++static my_bool innobase_extra_undoslots = FALSE;
+ static my_bool innobase_locks_unsafe_for_binlog = FALSE;
+ static my_bool innobase_rollback_on_timeout = FALSE;
+ static my_bool innobase_create_status_file = FALSE;
+@@ -2103,6 +2104,8 @@
+ goto error;
+ }
+
++ srv_extra_undoslots = (ibool) innobase_extra_undoslots;
++
+ /* -------------- Log files ---------------------------*/
+
+ /* The default dir for log files is the datadir of MySQL */
+@@ -10712,6 +10715,13 @@
+ "The common part for InnoDB table spaces.",
+ NULL, NULL, NULL);
+
++static MYSQL_SYSVAR_BOOL(extra_undoslots, innobase_extra_undoslots,
++ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
++ "Enable to use about 4000 undo slots instead of default 1024. "
++ "#### Attention: Once you enable this parameter, "
++ "don't use the datafile for normal mysqld or ibbackup! ####",
++ NULL, NULL, FALSE);
++
+ static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
+ "Enable InnoDB doublewrite buffer (enabled by default). "
+@@ -11095,6 +11105,7 @@
+ MYSQL_SYSVAR(data_file_path),
+ MYSQL_SYSVAR(data_home_dir),
+ MYSQL_SYSVAR(doublewrite),
++ MYSQL_SYSVAR(extra_undoslots),
+ MYSQL_SYSVAR(fast_shutdown),
+ MYSQL_SYSVAR(file_io_threads),
+ MYSQL_SYSVAR(read_io_threads),
+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-04-29 16:06:22.000000000 +0900
++++ b/storage/innodb_plugin/handler/innodb_patch_info.h 2010-04-29 16:06:59.000000000 +0900
+@@ -28,5 +28,6 @@
+ {"innodb_io","Improvements to InnoDB IO","","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_opt_lru_count","Fix of buffer_pool mutex","Decreases contention on buffer_pool mutex on LRU operations","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_buffer_pool_pages","Information of buffer pool content","","http://www.percona.com/docs/wiki/percona-xtradb"},
++{"innodb_expand_undo_slots","expandable maximum number of undo slots","from 1024 (default) to about 4000","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {NULL, NULL, NULL, NULL}
+ };
+diff -ruN a/storage/innodb_plugin/include/srv0srv.h b/storage/innodb_plugin/include/srv0srv.h
+--- a/storage/innodb_plugin/include/srv0srv.h 2010-04-29 15:55:25.000000000 +0900
++++ b/storage/innodb_plugin/include/srv0srv.h 2010-04-29 16:06:59.000000000 +0900
+@@ -112,6 +112,8 @@
+ extern ulint* srv_data_file_sizes;
+ extern ulint* srv_data_file_is_raw_partition;
+
++extern ibool srv_extra_undoslots;
++
+ extern ibool srv_auto_extend_last_data_file;
+ extern ulint srv_last_file_size_max;
+ extern char** srv_log_group_home_dirs;
+diff -ruN a/storage/innodb_plugin/include/trx0rseg.h b/storage/innodb_plugin/include/trx0rseg.h
+--- a/storage/innodb_plugin/include/trx0rseg.h 2010-04-06 23:07:13.000000000 +0900
++++ b/storage/innodb_plugin/include/trx0rseg.h 2010-04-29 16:06:59.000000000 +0900
+@@ -123,8 +123,11 @@
+ trx_rseg_t* rseg); /* in, own: instance to free */
+
+
++/* Real max value may be 4076 in usual. But reserve 4 slot for safety or etc... */
++#define TRX_RSEG_N_EXTRA_SLOTS (((UNIV_PAGE_SIZE - (FIL_PAGE_DATA + FIL_PAGE_DATA_END + TRX_RSEG_UNDO_SLOTS)) / TRX_RSEG_SLOT_SIZE) - 4)
++
+ /* Number of undo log slots in a rollback segment file copy */
+-#define TRX_RSEG_N_SLOTS (UNIV_PAGE_SIZE / 16)
++#define TRX_RSEG_N_SLOTS (srv_extra_undoslots ? TRX_RSEG_N_EXTRA_SLOTS : (UNIV_PAGE_SIZE / 16))
+
+ /* Maximum number of transactions supported by a single rollback segment */
+ #define TRX_RSEG_MAX_N_TRXS (TRX_RSEG_N_SLOTS / 2)
+diff -ruN a/storage/innodb_plugin/srv/srv0srv.c b/storage/innodb_plugin/srv/srv0srv.c
+--- a/storage/innodb_plugin/srv/srv0srv.c 2010-04-29 15:55:25.000000000 +0900
++++ b/storage/innodb_plugin/srv/srv0srv.c 2010-04-29 16:06:59.000000000 +0900
+@@ -142,6 +142,8 @@
+ /* size in database pages */
+ UNIV_INTERN ulint* srv_data_file_sizes = NULL;
+
++UNIV_INTERN ibool srv_extra_undoslots = FALSE;
++
+ /* if TRUE, then we auto-extend the last data file */
+ UNIV_INTERN ibool srv_auto_extend_last_data_file = FALSE;
+ /* if != 0, this tells the max size auto-extending may increase the
+diff -ruN a/storage/innodb_plugin/trx/trx0undo.c b/storage/innodb_plugin/trx/trx0undo.c
+--- a/storage/innodb_plugin/trx/trx0undo.c 2010-04-06 23:07:14.000000000 +0900
++++ b/storage/innodb_plugin/trx/trx0undo.c 2010-04-29 16:06:59.000000000 +0900
+@@ -1395,9 +1395,47 @@
+ rseg_header = trx_rsegf_get_new(rseg->space, rseg->zip_size,
+ rseg->page_no, &mtr);
+
++ if (!srv_extra_undoslots) {
++ /* uses direct call for avoid "Assertion failure" */
++ //page_no = trx_rsegf_get_nth_undo(rseg_header, TRX_RSEG_N_EXTRA_SLOTS - 1, &mtr);
++ page_no = mtr_read_ulint(rseg_header + TRX_RSEG_UNDO_SLOTS
++ + (TRX_RSEG_N_EXTRA_SLOTS - 1) * TRX_RSEG_SLOT_SIZE,
++ MLOG_4BYTES, &mtr);
++ if (page_no != 0) {
++ /* check extended slots are not used */
++ for (i = TRX_RSEG_N_SLOTS; i < TRX_RSEG_N_EXTRA_SLOTS; i++) {
++ /* uses direct call for avoid "Assertion failure" */
++ page_no = mtr_read_ulint(rseg_header + TRX_RSEG_UNDO_SLOTS
++ + i * TRX_RSEG_SLOT_SIZE,
++ MLOG_4BYTES, &mtr);
++ if (page_no != 0 && page_no != FIL_NULL) {
++ srv_extra_undoslots = TRUE;
++ fprintf(stderr,
++"InnoDB: Error: innodb_extra_undoslots option is disabled, but it was enabled before.\n"
++"InnoDB: The datafile is not normal for mysqld and disabled innodb_extra_undoslots.\n"
++"InnoDB: Enable innodb_extra_undoslots if it was enabled before, and\n"
++"InnoDB: ### don't use this datafile with other mysqld or ibbackup! ###\n"
++"InnoDB: Cannot continue operation for the safety. Calling exit(1).\n");
++ exit(1);
++ }
++ }
++ fprintf(stderr,
++"InnoDB: Warning: innodb_extra_undoslots option is disabled, but it was enabled before.\n"
++"InnoDB: But extended undo slots seem not used, so continue operation.\n");
++ }
++ }
++
+ for (i = 0; i < TRX_RSEG_N_SLOTS; i++) {
+ page_no = trx_rsegf_get_nth_undo(rseg_header, i, &mtr);
+
++ /* If it was not initialized when the datafile created,
++ page_no will be 0 for the extended slots after that */
++
++ if (page_no == 0) {
++ page_no = FIL_NULL;
++ trx_rsegf_set_nth_undo(rseg_header, i, page_no, &mtr);
++ }
++
+ /* In forced recovery: try to avoid operations which look
+ at database pages; undo logs are rapidly changing data, and
+ the probability that they are in an inconsistent state is
diff --git a/mysql-innodb_fast_checksum.patch b/mysql-innodb_fast_checksum.patch
new file mode 100644
index 0000000..4d830c9
--- /dev/null
+++ b/mysql-innodb_fast_checksum.patch
@@ -0,0 +1,311 @@
+# name : innodb_fast_checksum.patch
+# introduced : 11 or before
+# maintainer : Yasufumi
+#
+#!!! notice !!!
+# Any small change to this file in the main branch
+# should be done or reviewed by the maintainer!
+diff -ruN a/storage/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c
+--- a/storage/innodb_plugin/buf/buf0buf.c 2010-08-27 16:40:36.508988536 +0900
++++ b/storage/innodb_plugin/buf/buf0buf.c 2010-08-27 16:42:03.596041861 +0900
+@@ -343,6 +343,27 @@
+ return(checksum);
+ }
+
++UNIV_INTERN
++ulint
++buf_calc_page_new_checksum_32(
++/*==========================*/
++ const byte* page) /*!< in: buffer page */
++{
++ ulint checksum;
++
++ checksum = ut_fold_binary(page + FIL_PAGE_OFFSET,
++ FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
++ + ut_fold_binary(page + FIL_PAGE_DATA,
++ FIL_PAGE_DATA_ALIGN_32 - FIL_PAGE_DATA)
++ + ut_fold_binary_32(page + FIL_PAGE_DATA_ALIGN_32,
++ UNIV_PAGE_SIZE - FIL_PAGE_DATA_ALIGN_32
++ - FIL_PAGE_END_LSN_OLD_CHKSUM);
++
++ checksum = checksum & 0xFFFFFFFFUL;
++
++ return(checksum);
++}
++
+ /********************************************************************//**
+ In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only
+ looked at the first few bytes of the page. This calculates that old
+@@ -457,9 +478,21 @@
+ /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
+ (always equal to 0), to FIL_PAGE_SPACE_OR_CHKSUM */
+
+- if (checksum_field != 0
++ if (!srv_fast_checksum
++ && checksum_field != 0
++ && checksum_field != BUF_NO_CHECKSUM_MAGIC
++ && checksum_field
++ != buf_calc_page_new_checksum(read_buf)) {
++
++ return(TRUE);
++ }
++
++ if (srv_fast_checksum
++ && checksum_field != 0
+ && checksum_field != BUF_NO_CHECKSUM_MAGIC
+ && checksum_field
++ != buf_calc_page_new_checksum_32(read_buf)
++ && checksum_field
+ != buf_calc_page_new_checksum(read_buf)) {
+
+ return(TRUE);
+@@ -483,6 +516,7 @@
+ dict_index_t* index;
+ #endif /* !UNIV_HOTBACKUP */
+ ulint checksum;
++ ulint checksum_32;
+ ulint old_checksum;
+ ulint size = zip_size;
+
+@@ -569,12 +603,14 @@
+
+ checksum = srv_use_checksums
+ ? buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
++ checksum_32 = srv_use_checksums
++ ? buf_calc_page_new_checksum_32(read_buf) : BUF_NO_CHECKSUM_MAGIC;
+ old_checksum = srv_use_checksums
+ ? buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+- " InnoDB: Page checksum %lu, prior-to-4.0.14-form"
++ " InnoDB: Page checksum %lu (32bit_calc: %lu), prior-to-4.0.14-form"
+ " checksum %lu\n"
+ "InnoDB: stored checksum %lu, prior-to-4.0.14-form"
+ " stored checksum %lu\n"
+@@ -583,7 +619,7 @@
+ "InnoDB: Page number (if stored to page already) %lu,\n"
+ "InnoDB: space id (if created with >= MySQL-4.1.1"
+ " and stored already) %lu\n",
+- (ulong) checksum, (ulong) old_checksum,
++ (ulong) checksum, (ulong) checksum_32, (ulong) old_checksum,
+ (ulong) mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM),
+ (ulong) mach_read_from_4(read_buf + UNIV_PAGE_SIZE
+ - FIL_PAGE_END_LSN_OLD_CHKSUM),
+diff -ruN a/storage/innodb_plugin/buf/buf0flu.c b/storage/innodb_plugin/buf/buf0flu.c
+--- a/storage/innodb_plugin/buf/buf0flu.c 2010-08-27 16:38:38.226023489 +0900
++++ b/storage/innodb_plugin/buf/buf0flu.c 2010-08-27 16:42:03.597411439 +0900
+@@ -957,7 +957,9 @@
+
+ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
+ srv_use_checksums
+- ? buf_calc_page_new_checksum(page)
++ ? (!srv_fast_checksum
++ ? buf_calc_page_new_checksum(page)
++ : buf_calc_page_new_checksum_32(page))
+ : BUF_NO_CHECKSUM_MAGIC);
+
+ /* We overwrite the first 4 bytes of the end lsn field to store
+diff -ruN a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c
+--- a/storage/innodb_plugin/fil/fil0fil.c 2010-08-27 16:40:36.522990504 +0900
++++ b/storage/innodb_plugin/fil/fil0fil.c 2010-08-27 16:42:03.602023484 +0900
+@@ -3096,7 +3096,9 @@
+ mach_write_ull(page + FIL_PAGE_FILE_FLUSH_LSN, current_lsn);
+ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
+ srv_use_checksums
+- ? buf_calc_page_new_checksum(page)
++ ? (!srv_fast_checksum
++ ? buf_calc_page_new_checksum(page)
++ : buf_calc_page_new_checksum_32(page))
+ : BUF_NO_CHECKSUM_MAGIC);
+ mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
+ srv_use_checksums
+@@ -3226,7 +3228,8 @@
+ page_is_corrupt = TRUE;
+ }
+
+- if (checksum_field != 0
++ if (!srv_fast_checksum
++ && checksum_field != 0
+ && checksum_field != BUF_NO_CHECKSUM_MAGIC
+ && checksum_field
+ != buf_calc_page_new_checksum(page)) {
+@@ -3234,6 +3237,17 @@
+ page_is_corrupt = TRUE;
+ }
+
++ if (srv_fast_checksum
++ && checksum_field != 0
++ && checksum_field != BUF_NO_CHECKSUM_MAGIC
++ && checksum_field
++ != buf_calc_page_new_checksum_32(page)
++ && checksum_field
++ != buf_calc_page_new_checksum(page)) {
++
++ page_is_corrupt = TRUE;
++ }
++
+ /* if it is free page, inconsistency is acceptable */
+ if (!offset) {
+ /* header page*/
+@@ -3379,7 +3393,9 @@
+
+ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
+ srv_use_checksums
+- ? buf_calc_page_new_checksum(page)
++ ? (!srv_fast_checksum
++ ? buf_calc_page_new_checksum(page)
++ : buf_calc_page_new_checksum_32(page))
+ : BUF_NO_CHECKSUM_MAGIC);
+ mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
+ srv_use_checksums
+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:40:36.538021443 +0900
++++ b/storage/innodb_plugin/handler/ha_innodb.cc 2010-08-27 16:42:03.611021803 +0900
+@@ -185,6 +185,7 @@
+ #endif /* UNIV_LOG_ARCHIVE */
+ static my_bool innobase_use_doublewrite = TRUE;
+ static my_bool innobase_use_checksums = TRUE;
++static my_bool innobase_fast_checksum = FALSE;
+ static my_bool innobase_extra_undoslots = FALSE;
+ static my_bool innobase_fast_recovery = FALSE;
+ static my_bool innobase_recovery_stats = TRUE;
+@@ -2394,6 +2395,7 @@
+
+ srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
+ srv_use_checksums = (ibool) innobase_use_checksums;
++ srv_fast_checksum = (ibool) innobase_fast_checksum;
+
+ #ifdef HAVE_LARGE_PAGES
+ if ((os_use_large_pages = (ibool) my_use_large_pages))
+@@ -11105,6 +11107,15 @@
+ "Disable with --skip-innodb-checksums.",
+ NULL, NULL, TRUE);
+
++static MYSQL_SYSVAR_BOOL(fast_checksum, innobase_fast_checksum,
++ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
++ "Change the algorithm of checksum for the whole of datapage to 4-bytes word based. "
++ "The original checksum is checked after the new one. It may be slow for reading page"
++ " which has orginal checksum. Overwrite the page or recreate the InnoDB database, "
++ "if you want the entire benefit for performance at once. "
++ "#### Attention: The checksum is not compatible for normal or disabled version! ####",
++ NULL, NULL, FALSE);
++
+ static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
+ PLUGIN_VAR_READONLY,
+ "The common part for InnoDB table spaces.",
+@@ -11595,6 +11606,7 @@
+ MYSQL_SYSVAR(autoextend_increment),
+ MYSQL_SYSVAR(buffer_pool_size),
+ MYSQL_SYSVAR(checksums),
++ MYSQL_SYSVAR(fast_checksum),
+ MYSQL_SYSVAR(commit_concurrency),
+ MYSQL_SYSVAR(concurrency_tickets),
+ MYSQL_SYSVAR(data_file_path),
+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-08-27 16:40:36.560063279 +0900
++++ b/storage/innodb_plugin/handler/innodb_patch_info.h 2010-08-27 16:42:03.615988127 +0900
+@@ -44,5 +44,6 @@
+ {"innodb_lru_dump_restore","Dump and restore command for content of buffer pool","","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_separate_doublewrite","Add option 'innodb_doublewrite_file' to separate doublewrite dedicated tablespace","","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_pass_corrupt_table","Treat tables as corrupt instead of crash, when meet corrupt blocks","","http://www.percona.com/docs/wiki/percona-xtradb"},
++{"innodb_fast_checksum","Using the checksum on 32bit-unit calculation","incompatible for unpatched ver.","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-08-27 16:40:36.563059330 +0900
++++ b/storage/innodb_plugin/include/buf0buf.h 2010-08-27 16:42:03.638058638 +0900
+@@ -477,6 +477,11 @@
+ buf_calc_page_new_checksum(
+ /*=======================*/
+ const byte* page); /*!< in: buffer page */
++UNIV_INTERN
++ulint
++buf_calc_page_new_checksum_32(
++/*==========================*/
++ const byte* page); /*!< in: buffer page */
+ /********************************************************************//**
+ In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only
+ looked at the first few bytes of the page. This calculates that old
+diff -ruN a/storage/innodb_plugin/include/fil0fil.h b/storage/innodb_plugin/include/fil0fil.h
+--- a/storage/innodb_plugin/include/fil0fil.h 2010-08-27 16:40:36.572063042 +0900
++++ b/storage/innodb_plugin/include/fil0fil.h 2010-08-27 16:42:03.640021168 +0900
+@@ -117,6 +117,7 @@
+ #define FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID 34 /*!< starting from 4.1.x this
+ contains the space id of the page */
+ #define FIL_PAGE_DATA 38 /*!< start of the data on the page */
++#define FIL_PAGE_DATA_ALIGN_32 40
+ /* @} */
+ /** File page trailer @{ */
+ #define FIL_PAGE_END_LSN_OLD_CHKSUM 8 /*!< the low 4 bytes of this are used
+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-27 16:40:36.580092150 +0900
++++ b/storage/innodb_plugin/include/srv0srv.h 2010-08-27 16:42:03.640988120 +0900
+@@ -211,6 +211,7 @@
+
+ extern ibool srv_use_doublewrite_buf;
+ extern ibool srv_use_checksums;
++extern ibool srv_fast_checksum;
+
+ extern ibool srv_set_thread_priorities;
+ extern int srv_query_thread_priority;
+diff -ruN a/storage/innodb_plugin/include/ut0rnd.h b/storage/innodb_plugin/include/ut0rnd.h
+--- a/storage/innodb_plugin/include/ut0rnd.h 2010-08-04 02:24:20.000000000 +0900
++++ b/storage/innodb_plugin/include/ut0rnd.h 2010-08-27 16:42:03.642990139 +0900
+@@ -124,6 +124,13 @@
+ const byte* str, /*!< in: string of bytes */
+ ulint len) /*!< in: length */
+ __attribute__((pure));
++UNIV_INLINE
++ulint
++ut_fold_binary_32(
++/*==============*/
++ const byte* str, /*!< in: string of bytes */
++ ulint len) /*!< in: length */
++ __attribute__((pure));
+ /***********************************************************//**
+ Looks for a prime number slightly greater than the given argument.
+ The prime is chosen so that it is not near any power of 2.
+diff -ruN a/storage/innodb_plugin/include/ut0rnd.ic b/storage/innodb_plugin/include/ut0rnd.ic
+--- a/storage/innodb_plugin/include/ut0rnd.ic 2010-08-04 02:24:20.000000000 +0900
++++ b/storage/innodb_plugin/include/ut0rnd.ic 2010-08-27 16:42:03.643990557 +0900
+@@ -226,3 +226,28 @@
+
+ return(fold);
+ }
++
++UNIV_INLINE
++ulint
++ut_fold_binary_32(
++/*==============*/
++ const byte* str, /*!< in: string of bytes */
++ ulint len) /*!< in: length */
++{
++ const ib_uint32_t* str_end = (const ib_uint32_t*) (str + len);
++ const ib_uint32_t* str_32 = (const ib_uint32_t*) str;
++ ulint fold = 0;
++
++ ut_ad(str);
++ /* This function is only for word-aligned data */
++ ut_ad(len % 4 == 0);
++ ut_ad((ulint)str % 4 == 0);
++
++ while (str_32 < str_end) {
++ fold = ut_fold_ulint_pair(fold, (ulint)(*str_32));
++
++ str_32++;
++ }
++
++ return(fold);
++}
+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-27 16:40:36.599058304 +0900
++++ b/storage/innodb_plugin/srv/srv0srv.c 2010-08-27 16:42:03.647012289 +0900
+@@ -383,6 +383,7 @@
+
+ UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE;
+ UNIV_INTERN ibool srv_use_checksums = TRUE;
++UNIV_INTERN ibool srv_fast_checksum = FALSE;
+
+ UNIV_INTERN ibool srv_set_thread_priorities = TRUE;
+ UNIV_INTERN int srv_query_thread_priority = 0;
diff --git a/mysql-innodb_files_extend.patch b/mysql-innodb_files_extend.patch
new file mode 100644
index 0000000..513a5d8
--- /dev/null
+++ b/mysql-innodb_files_extend.patch
@@ -0,0 +1,422 @@
+# name : innodb_files_extend.patch
+# introduced : 11 or before
+# maintainer : Yasufumi
+#
+#!!! notice !!!
+# Any small change to this file in the main branch
+# should be done or reviewed by the maintainer!
+diff -ruN a/storage/innodb_plugin/buf/buf0buddy.c b/storage/innodb_plugin/buf/buf0buddy.c
+--- a/storage/innodb_plugin/buf/buf0buddy.c 2010-08-27 16:13:11.055058310 +0900
++++ b/storage/innodb_plugin/buf/buf0buddy.c 2010-08-27 16:44:21.664059035 +0900
+@@ -43,7 +43,7 @@
+ #endif /* UNIV_DEBUG */
+ /** Statistics of the buddy system, indexed by block size.
+ Protected by buf_pool_mutex. */
+-UNIV_INTERN buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES + 1];
++UNIV_INTERN buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES_MAX + 1];
+
+ /**********************************************************************//**
+ Get the offset of the buddy of a compressed page frame.
+diff -ruN a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c
+--- a/storage/innodb_plugin/fil/fil0fil.c 2010-08-27 16:43:11.941989968 +0900
++++ b/storage/innodb_plugin/fil/fil0fil.c 2010-08-27 16:44:21.668058937 +0900
+@@ -4722,9 +4722,9 @@
+ ut_ad(ut_is_2pow(zip_size));
+ ut_ad(buf);
+ ut_ad(len > 0);
+-#if (1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE
+-# error "(1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE"
+-#endif
++//#if (1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE
++//# error "(1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE"
++//#endif
+ ut_ad(fil_validate());
+ #ifndef UNIV_HOTBACKUP
+ # ifndef UNIV_LOG_DEBUG
+diff -ruN a/storage/innodb_plugin/fsp/fsp0fsp.c b/storage/innodb_plugin/fsp/fsp0fsp.c
+--- a/storage/innodb_plugin/fsp/fsp0fsp.c 2010-08-27 16:40:36.528021375 +0900
++++ b/storage/innodb_plugin/fsp/fsp0fsp.c 2010-08-27 16:44:21.673058570 +0900
+@@ -658,15 +658,16 @@
+ ulint offset) /*!< in: page offset */
+ {
+ #ifndef DOXYGEN /* Doxygen gets confused of these */
+-# if UNIV_PAGE_SIZE <= XDES_ARR_OFFSET \
+- + (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE
+-# error
+-# endif
++//# if UNIV_PAGE_SIZE <= XDES_ARR_OFFSET
++// + (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE
++//# error
++//# endif
+ # if PAGE_ZIP_MIN_SIZE <= XDES_ARR_OFFSET \
+ + (PAGE_ZIP_MIN_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE
+ # error
+ # endif
+ #endif /* !DOXYGEN */
++ ut_a(UNIV_PAGE_SIZE > XDES_ARR_OFFSET + (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE);
+ ut_ad(ut_is_2pow(zip_size));
+
+ if (!zip_size) {
+@@ -1465,12 +1466,12 @@
+ mtr);
+ xdes_init(descr, mtr);
+
+-#if UNIV_PAGE_SIZE % FSP_EXTENT_SIZE
+-# error "UNIV_PAGE_SIZE % FSP_EXTENT_SIZE != 0"
+-#endif
+-#if PAGE_ZIP_MIN_SIZE % FSP_EXTENT_SIZE
+-# error "PAGE_ZIP_MIN_SIZE % FSP_EXTENT_SIZE != 0"
+-#endif
++//#if UNIV_PAGE_SIZE % FSP_EXTENT_SIZE
++//# error "UNIV_PAGE_SIZE % FSP_EXTENT_SIZE != 0"
++//#endif
++//#if PAGE_ZIP_MIN_SIZE % FSP_EXTENT_SIZE
++//# error "PAGE_ZIP_MIN_SIZE % FSP_EXTENT_SIZE != 0"
++//#endif
+
+ if (UNIV_UNLIKELY(init_xdes)) {
+
+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:43:11.951020997 +0900
++++ b/storage/innodb_plugin/handler/ha_innodb.cc 2010-08-27 16:44:21.682059132 +0900
+@@ -151,6 +151,8 @@
+ static ulong innobase_read_io_threads;
+ static ulong innobase_write_io_threads;
+
++static ulong innobase_page_size;
++
+ static my_bool innobase_thread_concurrency_timer_based;
+ static long long innobase_buffer_pool_size, innobase_log_file_size;
+
+@@ -2084,6 +2086,36 @@
+ }
+ #endif /* UNIV_DEBUG */
+
++ srv_page_size = 0;
++ srv_page_size_shift = 0;
++
++ if (innobase_page_size != (1 << 14)) {
++ uint n_shift;
++
++ fprintf(stderr,
++ "InnoDB: Warning: innodb_page_size has been changed from default value 16384. (###EXPERIMENTAL### operation)\n");
++ for (n_shift = 12; n_shift <= UNIV_PAGE_SIZE_SHIFT_MAX; n_shift++) {
++ if (innobase_page_size == ((ulong)1 << n_shift)) {
++ srv_page_size_shift = n_shift;
++ srv_page_size = (1 << srv_page_size_shift);
++ fprintf(stderr,
++ "InnoDB: The universal page size of the database is set to %lu.\n",
++ srv_page_size);
++ break;
++ }
++ }
++ } else {
++ srv_page_size_shift = 14;
++ srv_page_size = (1 << srv_page_size_shift);
++ }
++
++ if (!srv_page_size_shift) {
++ fprintf(stderr,
++ "InnoDB: Error: %lu is not valid value for innodb_page_size.\n",
++ innobase_page_size);
++ goto error;
++ }
++
+ #ifndef MYSQL_SERVER
+ innodb_overwrite_relay_log_info = FALSE;
+ #endif
+@@ -7006,9 +7038,9 @@
+ | DICT_TF_COMPACT
+ | DICT_TF_FORMAT_ZIP
+ << DICT_TF_FORMAT_SHIFT;
+-#if DICT_TF_ZSSIZE_MAX < 1
+-# error "DICT_TF_ZSSIZE_MAX < 1"
+-#endif
++//#if DICT_TF_ZSSIZE_MAX < 1
++//# error "DICT_TF_ZSSIZE_MAX < 1"
++//#endif
+ }
+ }
+
+@@ -11116,6 +11148,11 @@
+ "#### Attention: The checksum is not compatible for normal or disabled version! ####",
+ NULL, NULL, FALSE);
+
++static MYSQL_SYSVAR_ULONG(page_size, innobase_page_size,
++ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
++ "###EXPERIMENTAL###: The universal page size of the database. Changing for created database is not supported. Use on your own risk!",
++ NULL, NULL, (1 << 14), (1 << 12), (1 << UNIV_PAGE_SIZE_SHIFT_MAX), 0);
++
+ static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
+ PLUGIN_VAR_READONLY,
+ "The common part for InnoDB table spaces.",
+@@ -11602,6 +11639,7 @@
+ NULL, NULL, 0, 0, 1, 0);
+
+ static struct st_mysql_sys_var* innobase_system_variables[]= {
++ MYSQL_SYSVAR(page_size),
+ MYSQL_SYSVAR(additional_mem_pool_size),
+ MYSQL_SYSVAR(autoextend_increment),
+ MYSQL_SYSVAR(buffer_pool_size),
+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-08-27 16:43:11.956017166 +0900
++++ b/storage/innodb_plugin/handler/innodb_patch_info.h 2010-08-27 16:44:21.687100395 +0900
+@@ -45,5 +45,6 @@
+ {"innodb_separate_doublewrite","Add option 'innodb_doublewrite_file' to separate doublewrite dedicated tablespace","","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_pass_corrupt_table","Treat tables as corrupt instead of crash, when meet corrupt blocks","","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"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"},
+ {NULL, NULL, NULL, NULL}
+ };
+diff -ruN a/storage/innodb_plugin/include/buf0buddy.h b/storage/innodb_plugin/include/buf0buddy.h
+--- a/storage/innodb_plugin/include/buf0buddy.h 2010-08-27 16:13:11.077063445 +0900
++++ b/storage/innodb_plugin/include/buf0buddy.h 2010-08-27 16:44:21.689059215 +0900
+@@ -83,7 +83,7 @@
+
+ /** Statistics of the buddy system, indexed by block size.
+ Protected by buf_pool_mutex. */
+-extern buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES + 1];
++extern buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES_MAX + 1];
+
+ #ifndef UNIV_NONINL
+ # include "buf0buddy.ic"
+diff -ruN a/storage/innodb_plugin/include/buf0buf.h b/storage/innodb_plugin/include/buf0buf.h
+--- a/storage/innodb_plugin/include/buf0buf.h 2010-08-27 16:43:11.959021085 +0900
++++ b/storage/innodb_plugin/include/buf0buf.h 2010-08-27 16:44:21.691058408 +0900
+@@ -1452,11 +1452,11 @@
+ /* @{ */
+ UT_LIST_BASE_NODE_T(buf_page_t) zip_clean;
+ /*!< unmodified compressed pages */
+- UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES];
++ UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES_MAX];
+ /*!< buddy free lists */
+-#if BUF_BUDDY_HIGH != UNIV_PAGE_SIZE
+-# error "BUF_BUDDY_HIGH != UNIV_PAGE_SIZE"
+-#endif
++//#if BUF_BUDDY_HIGH != UNIV_PAGE_SIZE
++//# error "BUF_BUDDY_HIGH != UNIV_PAGE_SIZE"
++//#endif
+ #if BUF_BUDDY_LOW > PAGE_ZIP_MIN_SIZE
+ # error "BUF_BUDDY_LOW > PAGE_ZIP_MIN_SIZE"
+ #endif
+diff -ruN a/storage/innodb_plugin/include/buf0types.h b/storage/innodb_plugin/include/buf0types.h
+--- a/storage/innodb_plugin/include/buf0types.h 2010-08-04 02:24:19.000000000 +0900
++++ b/storage/innodb_plugin/include/buf0types.h 2010-08-27 16:44:21.692071229 +0900
+@@ -70,6 +70,7 @@
+ buddy system; must be at least
+ sizeof(buf_page_t) */
+ #define BUF_BUDDY_SIZES (UNIV_PAGE_SIZE_SHIFT - BUF_BUDDY_LOW_SHIFT)
++#define BUF_BUDDY_SIZES_MAX (UNIV_PAGE_SIZE_SHIFT_MAX - BUF_BUDDY_LOW_SHIFT)
+ /*!< number of buddy sizes */
+
+ /** twice the maximum block size of the buddy system;
+diff -ruN a/storage/innodb_plugin/include/mtr0log.ic b/storage/innodb_plugin/include/mtr0log.ic
+--- a/storage/innodb_plugin/include/mtr0log.ic 2010-08-27 16:38:38.273059844 +0900
++++ b/storage/innodb_plugin/include/mtr0log.ic 2010-08-27 16:44:21.693073476 +0900
+@@ -203,7 +203,7 @@
+ system tablespace */
+ if ((space == TRX_SYS_SPACE
+ || (srv_doublewrite_file && space == TRX_DOUBLEWRITE_SPACE))
+- && offset >= FSP_EXTENT_SIZE && offset < 3 * FSP_EXTENT_SIZE) {
++ && offset >= (ulint)FSP_EXTENT_SIZE && offset < 3 * (ulint)FSP_EXTENT_SIZE) {
+ if (trx_doublewrite_buf_is_being_created) {
+ /* Do nothing: we only come to this branch in an
+ InnoDB database creation. We do not redo log
+diff -ruN a/storage/innodb_plugin/include/page0types.h b/storage/innodb_plugin/include/page0types.h
+--- a/storage/innodb_plugin/include/page0types.h 2010-08-04 02:24:19.000000000 +0900
++++ b/storage/innodb_plugin/include/page0types.h 2010-08-27 16:44:21.695063547 +0900
+@@ -56,8 +56,9 @@
+
+ /** Number of supported compressed page sizes */
+ #define PAGE_ZIP_NUM_SSIZE (UNIV_PAGE_SIZE_SHIFT - PAGE_ZIP_MIN_SIZE_SHIFT + 2)
+-#if PAGE_ZIP_NUM_SSIZE > (1 << PAGE_ZIP_SSIZE_BITS)
+-# error "PAGE_ZIP_NUM_SSIZE > (1 << PAGE_ZIP_SSIZE_BITS)"
++#define PAGE_ZIP_NUM_SSIZE_MAX (UNIV_PAGE_SIZE_SHIFT_MAX - PAGE_ZIP_MIN_SIZE_SHIFT + 2)
++#if PAGE_ZIP_NUM_SSIZE_MAX > (1 << PAGE_ZIP_SSIZE_BITS)
++# error "PAGE_ZIP_NUM_SSIZE_MAX > (1 << PAGE_ZIP_SSIZE_BITS)"
+ #endif
+
+ /** Compressed page descriptor */
+@@ -98,7 +99,7 @@
+ typedef struct page_zip_stat_struct page_zip_stat_t;
+
+ /** Statistics on compression, indexed by page_zip_des_struct::ssize - 1 */
+-extern page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE - 1];
++extern page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE_MAX - 1];
+
+ /**********************************************************************//**
+ Write the "deleted" flag of a record on a compressed page. The flag must
+diff -ruN a/storage/innodb_plugin/include/trx0sys.h b/storage/innodb_plugin/include/trx0sys.h
+--- a/storage/innodb_plugin/include/trx0sys.h 2010-08-27 16:38:38.277021207 +0900
++++ b/storage/innodb_plugin/include/trx0sys.h 2010-08-27 16:44:21.696063957 +0900
+@@ -515,9 +515,9 @@
+ /** Contents of TRX_SYS_MYSQL_LOG_MAGIC_N_FLD */
+ #define TRX_SYS_MYSQL_LOG_MAGIC_N 873422344
+
+-#if UNIV_PAGE_SIZE < 4096
+-# error "UNIV_PAGE_SIZE < 4096"
+-#endif
++//#if UNIV_PAGE_SIZE < 4096
++//# error "UNIV_PAGE_SIZE < 4096"
++//#endif
+ /** The offset of the MySQL replication info in the trx system header;
+ this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
+ #define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
+diff -ruN a/storage/innodb_plugin/include/univ.i b/storage/innodb_plugin/include/univ.i
+--- a/storage/innodb_plugin/include/univ.i 2010-08-04 02:24:19.000000000 +0900
++++ b/storage/innodb_plugin/include/univ.i 2010-08-27 16:44:21.698059254 +0900
+@@ -283,9 +283,13 @@
+ */
+
+ /* The 2-logarithm of UNIV_PAGE_SIZE: */
+-#define UNIV_PAGE_SIZE_SHIFT 14
++/* #define UNIV_PAGE_SIZE_SHIFT 14 */
++#define UNIV_PAGE_SIZE_SHIFT_MAX 14
++#define UNIV_PAGE_SIZE_SHIFT srv_page_size_shift
+ /* The universal page size of the database */
+-#define UNIV_PAGE_SIZE (1 << UNIV_PAGE_SIZE_SHIFT)
++/* #define UNIV_PAGE_SIZE (1 << UNIV_PAGE_SIZE_SHIFT) */
++#define UNIV_PAGE_SIZE srv_page_size
++#define UNIV_PAGE_SIZE_MAX (1 << UNIV_PAGE_SIZE_SHIFT_MAX)
+
+ /* Maximum number of parallel threads in a parallelized operation */
+ #define UNIV_MAX_PARALLELISM 32
+@@ -384,7 +388,7 @@
+ stored part of the field in the tablespace. The length field then
+ contains the sum of the following flag and the locally stored len. */
+
+-#define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE)
++#define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE_MAX)
+
+ /* Some macros to improve branch prediction and reduce cache misses */
+ #if defined(__GNUC__) && (__GNUC__ > 2) && ! defined(__INTEL_COMPILER)
+@@ -487,4 +491,6 @@
+ UNIV_MEM_ALLOC(addr, size); \
+ } while (0)
+
++extern ulint srv_page_size_shift;
++extern ulint srv_page_size;
+ #endif
+diff -ruN a/storage/innodb_plugin/log/log0log.c b/storage/innodb_plugin/log/log0log.c
+--- a/storage/innodb_plugin/log/log0log.c 2010-08-27 16:27:30.229021112 +0900
++++ b/storage/innodb_plugin/log/log0log.c 2010-08-27 16:44:21.701058790 +0900
+@@ -591,7 +591,9 @@
+
+ offset = (gr_lsn_size_offset + difference) % group_size;
+
++ if (sizeof(ulint) == 4) {
+ ut_a(offset < (((ib_int64_t) 1) << 32)); /* offset must be < 4 GB */
++ }
+
+ /* fprintf(stderr,
+ "Offset is %lu gr_lsn_offset is %lu difference is %lu\n",
+@@ -1791,6 +1793,7 @@
+ mach_write_to_4(buf + LOG_CHECKPOINT_LOG_BUF_SIZE, log_sys->buf_size);
+
+ #ifdef UNIV_LOG_ARCHIVE
++#error "UNIV_LOG_ARCHIVE could not be enabled"
+ if (log_sys->archiving_state == LOG_ARCH_OFF) {
+ archived_lsn = IB_ULONGLONG_MAX;
+ } else {
+@@ -1804,7 +1807,9 @@
+
+ mach_write_ull(buf + LOG_CHECKPOINT_ARCHIVED_LSN, archived_lsn);
+ #else /* UNIV_LOG_ARCHIVE */
+- mach_write_ull(buf + LOG_CHECKPOINT_ARCHIVED_LSN, IB_ULONGLONG_MAX);
++ mach_write_ull(buf + LOG_CHECKPOINT_ARCHIVED_LSN,
++ (ib_uint64_t)log_group_calc_lsn_offset(
++ log_sys->next_checkpoint_lsn, group));
+ #endif /* UNIV_LOG_ARCHIVE */
+
+ for (i = 0; i < LOG_MAX_N_GROUPS; i++) {
+diff -ruN a/storage/innodb_plugin/log/log0recv.c b/storage/innodb_plugin/log/log0recv.c
+--- a/storage/innodb_plugin/log/log0recv.c 2010-08-27 16:23:31.034058951 +0900
++++ b/storage/innodb_plugin/log/log0recv.c 2010-08-27 16:44:21.705059074 +0900
+@@ -702,8 +702,22 @@
+
+ group->lsn = mach_read_ull(
+ buf + LOG_CHECKPOINT_LSN);
++
++#ifdef UNIV_LOG_ARCHIVE
++#error "UNIV_LOG_ARCHIVE could not be enabled"
++#endif
++ {
++ ib_uint64_t tmp_lsn_offset = mach_read_ull(
++ buf + LOG_CHECKPOINT_ARCHIVED_LSN);
++ if (sizeof(ulint) != 4
++ && tmp_lsn_offset != IB_ULONGLONG_MAX) {
++ group->lsn_offset = (ulint) tmp_lsn_offset;
++ } else {
+ group->lsn_offset = mach_read_from_4(
+ buf + LOG_CHECKPOINT_OFFSET);
++ }
++ }
++
+ checkpoint_no = mach_read_ull(
+ buf + LOG_CHECKPOINT_NO);
+
+diff -ruN a/storage/innodb_plugin/page/page0zip.c b/storage/innodb_plugin/page/page0zip.c
+--- a/storage/innodb_plugin/page/page0zip.c 2010-08-27 16:40:36.584058988 +0900
++++ b/storage/innodb_plugin/page/page0zip.c 2010-08-27 16:44:21.709058243 +0900
+@@ -49,7 +49,7 @@
+
+ #ifndef UNIV_HOTBACKUP
+ /** Statistics on compression, indexed by page_zip_des_t::ssize - 1 */
+-UNIV_INTERN page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE - 1];
++UNIV_INTERN page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE_MAX - 1];
+ #endif /* !UNIV_HOTBACKUP */
+
+ /* Please refer to ../include/page0zip.ic for a description of the
+diff -ruN a/storage/innodb_plugin/row/row0merge.c b/storage/innodb_plugin/row/row0merge.c
+--- a/storage/innodb_plugin/row/row0merge.c 2010-08-27 16:40:36.591058306 +0900
++++ b/storage/innodb_plugin/row/row0merge.c 2010-08-27 16:44:21.713021156 +0900
+@@ -92,7 +92,7 @@
+ row_merge_block_t. Thus, it must be able to hold one merge record,
+ whose maximum size is the same as the minimum size of
+ row_merge_block_t. */
+-typedef byte mrec_buf_t[UNIV_PAGE_SIZE];
++typedef byte mrec_buf_t[UNIV_PAGE_SIZE_MAX];
+
+ /** @brief Merge record in row_merge_block_t.
+
+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-27 16:43:11.968059077 +0900
++++ b/storage/innodb_plugin/srv/srv0srv.c 2010-08-27 16:44:21.716988122 +0900
+@@ -217,6 +217,10 @@
+ UNIV_INTERN ulint srv_n_read_io_threads = ULINT_MAX;
+ UNIV_INTERN ulint srv_n_write_io_threads = ULINT_MAX;
+
++/* The universal page size of the database */
++UNIV_INTERN ulint srv_page_size_shift = 0;
++UNIV_INTERN ulint srv_page_size = 0;
++
+ /* User settable value of the number of pages that must be present
+ in the buffer cache and accessed sequentially for InnoDB to trigger a
+ readahead request. */
+diff -ruN a/storage/innodb_plugin/srv/srv0start.c b/storage/innodb_plugin/srv/srv0start.c
+--- a/storage/innodb_plugin/srv/srv0start.c 2010-08-27 16:40:36.602058774 +0900
++++ b/storage/innodb_plugin/srv/srv0start.c 2010-08-27 16:44:21.720021228 +0900
+@@ -1486,10 +1486,12 @@
+ }
+ #endif /* UNIV_LOG_ARCHIVE */
+
+- if (srv_n_log_files * srv_log_file_size >= 262144) {
++ if (sizeof(ulint) == 4
++ && srv_n_log_files * srv_log_file_size
++ >= ((ulint)1 << (32 - UNIV_PAGE_SIZE_SHIFT))) {
+ fprintf(stderr,
+ "InnoDB: Error: combined size of log files"
+- " must be < 4 GB\n");
++ " must be < 4 GB on 32-bit systems\n");
+
+ return(DB_ERROR);
+ }
+@@ -1498,7 +1500,7 @@
+
+ for (i = 0; i < srv_n_data_files; i++) {
+ #ifndef __WIN__
+- if (sizeof(off_t) < 5 && srv_data_file_sizes[i] >= 262144) {
++ if (sizeof(off_t) < 5 && srv_data_file_sizes[i] >= ((ulint)1 << (32 - UNIV_PAGE_SIZE_SHIFT))) {
+ fprintf(stderr,
+ "InnoDB: Error: file size must be < 4 GB"
+ " with this MySQL binary\n"
diff --git a/mysql-innodb_fix_misc.patch b/mysql-innodb_fix_misc.patch
new file mode 100644
index 0000000..1c78be2
--- /dev/null
+++ b/mysql-innodb_fix_misc.patch
@@ -0,0 +1,137 @@
+# name : innodb_fix_misc.patch
+# introduced : 11 or before
+# maintainer : Yasufumi
+#
+#!!! notice !!!
+# Any small change to this file in the main branch
+# should be done or reviewed by the maintainer!
+diff -ruN a/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
+@@ -11735,7 +11735,7 @@
+ &innobase_storage_engine,
+ innobase_hton_name,
+ "Innobase Oy",
+- "Supports transactions, row-level locking, and foreign keys",
++ "Percona-XtraDB, Supports transactions, row-level locking, and foreign keys",
+ PLUGIN_LICENSE_GPL,
+ innobase_init, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+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
+@@ -48,6 +48,11 @@
+ #define INNODB_VERSION_MINOR 0
+ #define INNODB_VERSION_BUGFIX 13
+
++#ifndef PERCONA_INNODB_VERSION
++#define PERCONA_INNODB_VERSION 12.1
++#endif
++
++
+ /* The following is the InnoDB version as shown in
+ SELECT plugin_version FROM information_schema.plugins;
+ calculated in make_version_string() in sql/sql_show.cc like this:
+@@ -58,13 +63,15 @@
+ (INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR)
+
+ /* auxiliary macros to help creating the version as string */
+-#define __INNODB_VERSION(a, b, c) (#a "." #b "." #c)
+-#define _INNODB_VERSION(a, b, c) __INNODB_VERSION(a, b, c)
++#define __INNODB_VERSION(a, b, c, d) (#a "." #b "." #c "-" #d)
++#define _INNODB_VERSION(a, b, c, d) __INNODB_VERSION(a, b, c, d)
++
+
+ #define INNODB_VERSION_STR \
+ _INNODB_VERSION(INNODB_VERSION_MAJOR, \
+ INNODB_VERSION_MINOR, \
+- INNODB_VERSION_BUGFIX)
++ INNODB_VERSION_BUGFIX, \
++ PERCONA_INNODB_VERSION)
+
+ #define REFMAN "http://dev.mysql.com/doc/refman/5.1/en/"
+
+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
+@@ -1134,6 +1134,13 @@
+
+ thr = que_fork_get_first_thr(prebuilt->ins_graph);
+
++ if (!prebuilt->mysql_has_locked) {
++ fprintf(stderr, "InnoDB: Error: row_insert_for_mysql is called without ha_innobase::external_lock()\n");
++ if (trx->mysql_thd != NULL) {
++ innobase_mysql_print_thd(stderr, trx->mysql_thd, 600);
++ }
++ }
++
+ if (prebuilt->sql_stat_start) {
+ node->state = INS_NODE_SET_IX_LOCK;
+ prebuilt->sql_stat_start = FALSE;
+diff -ruN a/storage/innodb_plugin/row/row0sel.c b/storage/innodb_plugin/row/row0sel.c
+--- a/storage/innodb_plugin/row/row0sel.c 2010-07-20 16:33:04.204866103 +0900
++++ b/storage/innodb_plugin/row/row0sel.c 2010-07-20 16:33:53.998864025 +0900
+@@ -3362,6 +3362,7 @@
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ ibool table_lock_waited = FALSE;
++ ibool problematic_use = FALSE;
+
+ rec_offs_init(offsets_);
+
+@@ -3728,6 +3729,15 @@
+
+ /* Do some start-of-statement preparations */
+
++ if (!prebuilt->mysql_has_locked) {
++ fprintf(stderr, "InnoDB: Error: row_search_for_mysql() is called without ha_innobase::external_lock()\n");
++ if (trx->mysql_thd != NULL) {
++ innobase_mysql_print_thd(stderr, trx->mysql_thd, 600);
++ }
++ problematic_use = TRUE;
++ }
++retry_check:
++
+ if (!prebuilt->sql_stat_start) {
+ /* No need to set an intention lock or assign a read view */
+
+@@ -3738,6 +3748,14 @@
+ " perform a consistent read\n"
+ "InnoDB: but the read view is not assigned!\n",
+ stderr);
++ if (problematic_use) {
++ fprintf(stderr, "InnoDB: It may be caused by calling "
++ "without ha_innobase::external_lock()\n"
++ "InnoDB: For the first-aid, avoiding the crash. "
++ "But it should be fixed ASAP.\n");
++ prebuilt->sql_stat_start = TRUE;
++ goto retry_check;
++ }
+ trx_print(stderr, trx, 600);
+ fputc('\n', stderr);
+ ut_error;
+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
+@@ -1967,7 +1967,7 @@
+ if (srv_print_verbose_log) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+- " InnoDB Plugin %s started; "
++ " Percona XtraDB (http://www.percona.com) %s started; "
+ "log sequence number %llu\n",
+ INNODB_VERSION_STR, srv_start_lsn);
+ }
+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
+@@ -1144,8 +1144,7 @@
+ /* If we cannot advance the 'purge view' because of an old
+ 'consistent read view', then the DML statements cannot be delayed.
+ Also, srv_max_purge_lag <= 0 means 'infinity'. */
+- if (srv_max_purge_lag > 0
+- && !UT_LIST_GET_LAST(trx_sys->view_list)) {
++ if (srv_max_purge_lag > 0) {
+ float ratio = (float) trx_sys->rseg_history_len
+ / srv_max_purge_lag;
+ if (ratio > ULINT_MAX / 10000) {
diff --git a/mysql-innodb_lru_dump_restore.patch b/mysql-innodb_lru_dump_restore.patch
new file mode 100644
index 0000000..f2222b4
--- /dev/null
+++ b/mysql-innodb_lru_dump_restore.patch
@@ -0,0 +1,698 @@
+# name : innodb_lru_dump_restore.patch
+# introduced : 11 or before
+# maintainer : Yasufumi
+#
+#!!! notice !!!
+# Any small change to this file in the main branch
+# should be done or reviewed by the maintainer!
+diff -ruN a/storage/innodb_plugin/buf/buf0lru.c b/storage/innodb_plugin/buf/buf0lru.c
+--- a/storage/innodb_plugin/buf/buf0lru.c 2010-08-27 16:13:11.070058073 +0900
++++ b/storage/innodb_plugin/buf/buf0lru.c 2010-08-27 16:34:33.860400549 +0900
+@@ -2122,6 +2122,278 @@
+ memset(&buf_LRU_stat_cur, 0, sizeof buf_LRU_stat_cur);
+ }
+
++/********************************************************************//**
++Dump the LRU page list to the specific file. */
++#define LRU_DUMP_FILE "ib_lru_dump"
++
++UNIV_INTERN
++ibool
++buf_LRU_file_dump(void)
++/*===================*/
++{
++ os_file_t dump_file = -1;
++ ibool success;
++ byte* buffer_base = NULL;
++ byte* buffer = NULL;
++ buf_page_t* bpage;
++ ulint buffers;
++ ulint offset;
++ ibool ret = FALSE;
++ ulint i;
++
++ for (i = 0; i < srv_n_data_files; i++) {
++ if (strstr(srv_data_file_names[i], LRU_DUMP_FILE) != NULL) {
++ fprintf(stderr,
++ " InnoDB: The name '%s' seems to be used for"
++ " innodb_data_file_path. Dumping LRU list is not"
++ " done for safeness.\n", LRU_DUMP_FILE);
++ goto end;
++ }
++ }
++
++ buffer_base = ut_malloc(2 * UNIV_PAGE_SIZE);
++ buffer = ut_align(buffer_base, UNIV_PAGE_SIZE);
++ if (!buffer) {
++ fprintf(stderr,
++ " InnoDB: cannot allocate buffer.\n");
++ goto end;
++ }
++
++ dump_file = os_file_create(LRU_DUMP_FILE, OS_FILE_OVERWRITE,
++ OS_FILE_NORMAL, OS_DATA_FILE, &success);
++ if (!success) {
++ os_file_get_last_error(TRUE);
++ fprintf(stderr,
++ " InnoDB: cannot open %s\n", LRU_DUMP_FILE);
++ goto end;
++ }
++
++ mutex_enter(&LRU_list_mutex);
++ bpage = UT_LIST_GET_LAST(buf_pool->LRU);
++
++ buffers = offset = 0;
++ while (bpage != NULL) {
++ if (offset == 0) {
++ memset(buffer, 0, UNIV_PAGE_SIZE);
++ }
++
++ mach_write_to_4(buffer + offset * 4, bpage->space);
++ offset++;
++ mach_write_to_4(buffer + offset * 4, bpage->offset);
++ offset++;
++
++ if (offset == UNIV_PAGE_SIZE/4) {
++ success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
++ (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
++ (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
++ UNIV_PAGE_SIZE);
++ if (!success) {
++ mutex_exit(&LRU_list_mutex);
++ fprintf(stderr,
++ " InnoDB: cannot write page %lu of %s\n",
++ buffers, LRU_DUMP_FILE);
++ goto end;
++ }
++ buffers++;
++ offset = 0;
++ }
++
++ bpage = UT_LIST_GET_PREV(LRU, bpage);
++ }
++ mutex_exit(&LRU_list_mutex);
++
++ if (offset == 0) {
++ memset(buffer, 0, UNIV_PAGE_SIZE);
++ }
++
++ mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
++ offset++;
++ mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
++ offset++;
++
++ success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
++ (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
++ (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
++ UNIV_PAGE_SIZE);
++ if (!success) {
++ goto end;
++ }
++
++ ret = TRUE;
++end:
++ if (dump_file != -1)
++ os_file_close(dump_file);
++ if (buffer_base)
++ ut_free(buffer_base);
++
++ return(ret);
++}
++
++typedef struct {
++ ib_uint32_t space_id;
++ ib_uint32_t page_no;
++} dump_record_t;
++
++static int dump_record_cmp(const void *a, const void *b)
++{
++ const dump_record_t *rec1 = (dump_record_t *) a;
++ const dump_record_t *rec2 = (dump_record_t *) b;
++
++ if (rec1->space_id < rec2->space_id)
++ return -1;
++ if (rec1->space_id > rec2->space_id)
++ return 1;
++ if (rec1->page_no < rec2->page_no)
++ return -1;
++ return rec1->page_no > rec2->page_no;
++}
++
++/********************************************************************//**
++Read the pages based on the specific file.*/
++UNIV_INTERN
++ibool
++buf_LRU_file_restore(void)
++/*======================*/
++{
++ os_file_t dump_file = -1;
++ ibool success;
++ byte* buffer_base = NULL;
++ byte* buffer = NULL;
++ ulint buffers;
++ ulint offset;
++ ulint reads = 0;
++ ulint req = 0;
++ ibool terminated = FALSE;
++ ibool ret = FALSE;
++ dump_record_t* records;
++ ulint size;
++ ulint size_high;
++ ulint length;
++
++ dump_file = os_file_create_simple_no_error_handling(
++ LRU_DUMP_FILE, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
++ if (!success || !os_file_get_size(dump_file, &size, &size_high)) {
++ os_file_get_last_error(TRUE);
++ fprintf(stderr,
++ " InnoDB: cannot open %s\n", LRU_DUMP_FILE);
++ goto end;
++ }
++ if (size == 0 || size_high > 0 || size % 8) {
++ fprintf(stderr, " InnoDB: broken LRU dump file\n");
++ goto end;
++ }
++ buffer_base = ut_malloc(2 * UNIV_PAGE_SIZE);
++ buffer = ut_align(buffer_base, UNIV_PAGE_SIZE);
++ records = ut_malloc(size);
++ if (!buffer || !records) {
++ fprintf(stderr,
++ " InnoDB: cannot allocate buffer.\n");
++ goto end;
++ }
++
++ buffers = 0;
++ length = 0;
++ while (!terminated) {
++ success = os_file_read(dump_file, buffer,
++ (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
++ (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
++ UNIV_PAGE_SIZE);
++ if (!success) {
++ fprintf(stderr,
++ " InnoDB: cannot read page %lu of %s,"
++ " or meet unexpected terminal.\n",
++ buffers, LRU_DUMP_FILE);
++ goto end;
++ }
++
++ for (offset = 0; offset < UNIV_PAGE_SIZE/4; offset += 2) {
++ ulint space_id;
++ ulint page_no;
++
++ space_id = mach_read_from_4(buffer + offset * 4);
++ page_no = mach_read_from_4(buffer + (offset + 1) * 4);
++ if (space_id == 0xFFFFFFFFUL
++ || page_no == 0xFFFFFFFFUL) {
++ terminated = TRUE;
++ break;
++ }
++
++ records[length].space_id = space_id;
++ records[length].page_no = page_no;
++ length++;
++ if (length * 8 >= size) {
++ fprintf(stderr,
++ " InnoDB: could not find the "
++ "end-of-file marker after reading "
++ "the expected %lu bytes from the "
++ "LRU dump file.\n"
++ " InnoDB: this could be caused by a "
++ "broken or incomplete file.\n"
++ " InnoDB: trying to process what has "
++ "been read so far.\n",
++ size);
++ terminated= TRUE;
++ break;
++ }
++ }
++ buffers++;
++ }
++
++ qsort(records, length, sizeof(dump_record_t), dump_record_cmp);
++
++ for (offset = 0; offset < length; offset++) {
++ ulint space_id;
++ ulint page_no;
++ ulint zip_size;
++ ulint err;
++ ib_int64_t tablespace_version;
++
++ space_id = records[offset].space_id;
++ page_no = records[offset].page_no;
++
++ if (offset % 16 == 15) {
++ os_aio_simulated_wake_handler_threads();
++ buf_flush_free_margin(FALSE);
++ }
++
++ zip_size = fil_space_get_zip_size(space_id);
++ if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
++ continue;
++ }
++
++ if (fil_area_is_exist(space_id, zip_size, page_no, 0,
++ zip_size ? zip_size : UNIV_PAGE_SIZE)) {
++
++ tablespace_version = fil_space_get_version(space_id);
++
++ req++;
++ reads += buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE
++ | OS_AIO_SIMULATED_WAKE_LATER,
++ space_id, zip_size, TRUE,
++ tablespace_version, page_no, NULL);
++ buf_LRU_stat_inc_io();
++ }
++ }
++
++ os_aio_simulated_wake_handler_threads();
++ buf_flush_free_margin(FALSE);
++
++ ut_print_timestamp(stderr);
++ fprintf(stderr,
++ " InnoDB: reading pages based on the dumped LRU list was done."
++ " (requested: %lu, read: %lu)\n", req, reads);
++ ret = TRUE;
++end:
++ if (dump_file != -1)
++ os_file_close(dump_file);
++ if (buffer_base)
++ ut_free(buffer_base);
++ if (records)
++ ut_free(records);
++
++ return(ret);
++}
++
+ #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
+ /**********************************************************************//**
+ Validates the LRU list.
+diff -ruN a/storage/innodb_plugin/buf/buf0rea.c b/storage/innodb_plugin/buf/buf0rea.c
+--- a/storage/innodb_plugin/buf/buf0rea.c 2010-08-27 16:32:40.293411717 +0900
++++ b/storage/innodb_plugin/buf/buf0rea.c 2010-08-27 16:34:33.863409016 +0900
+@@ -56,7 +56,7 @@
+ which case it is never read into the pool, or if the tablespace does
+ not exist or is being dropped
+ @return 1 if read request is issued. 0 if it is not */
+-static
++UNIV_INTERN
+ ulint
+ buf_read_page_low(
+ /*==============*/
+diff -ruN a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c
+--- a/storage/innodb_plugin/fil/fil0fil.c 2010-08-27 16:32:40.298411400 +0900
++++ b/storage/innodb_plugin/fil/fil0fil.c 2010-08-27 16:34:33.868058362 +0900
+@@ -4869,6 +4869,78 @@
+ return(DB_SUCCESS);
+ }
+
++/********************************************************************//**
++Confirm whether the parameters are valid or not */
++UNIV_INTERN
++ibool
++fil_area_is_exist(
++/*==============*/
++ ulint space_id, /*!< in: space id */
++ ulint zip_size, /*!< in: compressed page size in bytes;
++ 0 for uncompressed pages */
++ ulint block_offset, /*!< in: offset in number of blocks */
++ ulint byte_offset, /*!< in: remainder of offset in bytes; in
++ aio this must be divisible by the OS block
++ size */
++ ulint len) /*!< in: how many bytes to read or write; this
++ must not cross a file boundary; in aio this
++ must be a block size multiple */
++{
++ fil_space_t* space;
++ fil_node_t* node;
++
++ /* Reserve the fil_system mutex and make sure that we can open at
++ least one file while holding it, if the file is not already open */
++
++ fil_mutex_enter_and_prepare_for_io(space_id);
++
++ space = fil_space_get_by_id(space_id);
++
++ if (!space) {
++ mutex_exit(&fil_system->mutex);
++ return(FALSE);
++ }
++
++ node = UT_LIST_GET_FIRST(space->chain);
++
++ for (;;) {
++ if (UNIV_UNLIKELY(node == NULL)) {
++ mutex_exit(&fil_system->mutex);
++ return(FALSE);
++ }
++
++ if (space->id != 0 && node->size == 0) {
++ /* We do not know the size of a single-table tablespace
++ before we open the file */
++
++ break;
++ }
++
++ if (node->size > block_offset) {
++ /* Found! */
++ break;
++ } else {
++ block_offset -= node->size;
++ node = UT_LIST_GET_NEXT(chain, node);
++ }
++ }
++
++ /* Open file if closed */
++ fil_node_prepare_for_io(node, fil_system, space);
++ fil_node_complete_io(node, fil_system, OS_FILE_READ);
++
++ /* Check that at least the start offset is within the bounds of a
++ single-table tablespace */
++ if (UNIV_UNLIKELY(node->size <= block_offset)
++ && space->id != 0 && space->purpose == FIL_TABLESPACE) {
++ mutex_exit(&fil_system->mutex);
++ return(FALSE);
++ }
++
++ mutex_exit(&fil_system->mutex);
++ return(TRUE);
++}
++
+ #ifndef UNIV_HOTBACKUP
+ /**********************************************************************//**
+ Waits for an aio operation to complete. This function is used to write the
+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-10-01 09:57:56.486228425 +0900
++++ b/storage/innodb_plugin/handler/ha_innodb.cc 2010-10-01 10:00:13.292228546 +0900
+@@ -11471,6 +11471,12 @@
+ "Limit the allocated memory for dictionary cache. (0: unlimited)",
+ NULL, NULL, 0, 0, LONG_MAX, 0);
+
++static MYSQL_SYSVAR_UINT(auto_lru_dump, srv_auto_lru_dump,
++ PLUGIN_VAR_RQCMDARG,
++ "Time in seconds between automatic buffer pool dumps. "
++ "0 (the default) disables automatic dumps.",
++ NULL, NULL, 0, 0, UINT_MAX32, 0);
++
+ static struct st_mysql_sys_var* innobase_system_variables[]= {
+ MYSQL_SYSVAR(additional_mem_pool_size),
+ MYSQL_SYSVAR(autoextend_increment),
+@@ -11553,6 +11559,7 @@
+ #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+ MYSQL_SYSVAR(read_ahead_threshold),
+ MYSQL_SYSVAR(io_capacity),
++ MYSQL_SYSVAR(auto_lru_dump),
+ MYSQL_SYSVAR(use_purge_thread),
+ NULL
+ };
+diff -ruN a/storage/innodb_plugin/handler/i_s.cc b/storage/innodb_plugin/handler/i_s.cc
+--- a/storage/innodb_plugin/handler/i_s.cc 2010-08-27 16:29:12.540979608 +0900
++++ b/storage/innodb_plugin/handler/i_s.cc 2010-08-27 16:34:33.873058189 +0900
+@@ -46,6 +46,7 @@
+ #include "trx0rseg.h" /* for trx_rseg_struct */
+ #include "trx0sys.h" /* for trx_sys */
+ #include "dict0dict.h" /* for dict_sys */
++#include "buf0lru.h" /* for XTRA_LRU_[DUMP/RESTORE] */
+ }
+
+ static const char plugin_author[] = "Innobase Oy";
+@@ -3041,6 +3042,36 @@
+ "Hello!");
+ goto end_func;
+ }
++ else if (!strncasecmp("XTRA_LRU_DUMP", ptr, 13)) {
++ ut_print_timestamp(stderr);
++ fprintf(stderr, " InnoDB: administration command 'XTRA_LRU_DUMP'"
++ " was detected.\n");
++
++ if (buf_LRU_file_dump()) {
++ field_store_string(i_s_table->field[0],
++ "XTRA_LRU_DUMP was succeeded.");
++ } else {
++ field_store_string(i_s_table->field[0],
++ "XTRA_LRU_DUMP was failed.");
++ }
++
++ goto end_func;
++ }
++ else if (!strncasecmp("XTRA_LRU_RESTORE", ptr, 16)) {
++ ut_print_timestamp(stderr);
++ fprintf(stderr, " InnoDB: administration command 'XTRA_LRU_RESTORE'"
++ " was detected.\n");
++
++ if (buf_LRU_file_restore()) {
++ field_store_string(i_s_table->field[0],
++ "XTRA_LRU_RESTORE was succeeded.");
++ } else {
++ field_store_string(i_s_table->field[0],
++ "XTRA_LRU_RESTORE was failed.");
++ }
++
++ goto end_func;
++ }
+
+ field_store_string(i_s_table->field[0],
+ "Undefined XTRA_* command.");
+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-08-27 16:32:40.313021803 +0900
++++ b/storage/innodb_plugin/handler/innodb_patch_info.h 2010-08-27 16:34:33.871059345 +0900
+@@ -41,5 +41,6 @@
+ {"innodb_admin_command_base","XtraDB specific command interface through i_s","","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_show_lock_name","Show mutex/lock name instead of crated file/line","","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {"innodb_extend_slow","Extended statistics in slow.log","It is InnoDB-part only. It needs to patch also to mysqld.","http://www.percona.com/docs/wiki/percona-xtradb"},
++{"innodb_lru_dump_restore","Dump and restore command for content of buffer pool","","http://www.percona.com/docs/wiki/percona-xtradb"},
+ {NULL, NULL, NULL, NULL}
+ };
+diff -ruN a/storage/innodb_plugin/include/buf0lru.h b/storage/innodb_plugin/include/buf0lru.h
+--- a/storage/innodb_plugin/include/buf0lru.h 2010-08-27 16:13:11.085978393 +0900
++++ b/storage/innodb_plugin/include/buf0lru.h 2010-08-27 16:34:33.875100517 +0900
+@@ -213,6 +213,18 @@
+ void
+ buf_LRU_stat_update(void);
+ /*=====================*/
++/********************************************************************//**
++Dump the LRU page list to the specific file. */
++UNIV_INTERN
++ibool
++buf_LRU_file_dump(void);
++/*===================*/
++/********************************************************************//**
++Read the pages based on the specific file.*/
++UNIV_INTERN
++ibool
++buf_LRU_file_restore(void);
++/*======================*/
+
+ #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
+ /**********************************************************************//**
+diff -ruN a/storage/innodb_plugin/include/buf0rea.h b/storage/innodb_plugin/include/buf0rea.h
+--- a/storage/innodb_plugin/include/buf0rea.h 2010-08-27 16:32:40.314021595 +0900
++++ b/storage/innodb_plugin/include/buf0rea.h 2010-08-27 16:34:33.877059445 +0900
+@@ -31,6 +31,37 @@
+ #include "buf0types.h"
+
+ /********************************************************************//**
++Low-level function which reads a page asynchronously from a file to the
++buffer buf_pool if it is not already there, in which case does nothing.
++Sets the io_fix flag and sets an exclusive lock on the buffer frame. The
++flag is cleared and the x-lock released by an i/o-handler thread.
++ at return 1 if a read request was queued, 0 if the page already resided
++in buf_pool, or if the page is in the doublewrite buffer blocks in
++which case it is never read into the pool, or if the tablespace does
++not exist or is being dropped
++ at return 1 if read request is issued. 0 if it is not */
++UNIV_INTERN
++ulint
++buf_read_page_low(
++/*==============*/
++ ulint* err, /*!< out: DB_SUCCESS or DB_TABLESPACE_DELETED if we are
++ trying to read from a non-existent tablespace, or a
++ tablespace which is just now being dropped */
++ ibool sync, /*!< in: TRUE if synchronous aio is desired */
++ ulint mode, /*!< in: BUF_READ_IBUF_PAGES_ONLY, ...,
++ ORed to OS_AIO_SIMULATED_WAKE_LATER (see below
++ at read-ahead functions) */
++ ulint space, /*!< in: space id */
++ ulint zip_size,/*!< in: compressed page size, or 0 */
++ ibool unzip, /*!< in: TRUE=request uncompressed page */
++ ib_int64_t tablespace_version, /*!< in: if the space memory object has
++ this timestamp different from what we are giving here,
++ treat the tablespace as dropped; this is a timestamp we
++ use to stop dangling page reads from a tablespace
++ which we have DISCARDed + IMPORTed back */
++ ulint offset, /*!< in: page number */
++ trx_t* trx);
++/********************************************************************//**
+ High-level function which reads a page asynchronously from a file to the
+ buffer buf_pool if it is not already there. Sets the io_fix flag and sets
+ an exclusive lock on the buffer frame. The flag is cleared and the x-lock
+diff -ruN a/storage/innodb_plugin/include/fil0fil.h b/storage/innodb_plugin/include/fil0fil.h
+--- a/storage/innodb_plugin/include/fil0fil.h 2010-08-27 16:32:40.315012507 +0900
++++ b/storage/innodb_plugin/include/fil0fil.h 2010-08-27 16:34:33.878063455 +0900
+@@ -643,6 +643,22 @@
+ void* message, /*!< in: message for aio handler if non-sync
+ aio used, else ignored */
+ trx_t* trx);
++/********************************************************************//**
++Confirm whether the parameters are valid or not */
++UNIV_INTERN
++ibool
++fil_area_is_exist(
++/*==============*/
++ ulint space_id, /*!< in: space id */
++ ulint zip_size, /*!< in: compressed page size in bytes;
++ 0 for uncompressed pages */
++ ulint block_offset, /*!< in: offset in number of blocks */
++ ulint byte_offset, /*!< in: remainder of offset in bytes; in
++ aio this must be divisible by the OS block
++ size */
++ ulint len); /*!< in: how many bytes to read or write; this
++ must not cross a file boundary; in aio this
++ must be a block size multiple */
+ /**********************************************************************//**
+ Waits for an aio operation to complete. This function is used to write the
+ handler for completed requests. The aio array of pending requests is divided
+diff -ruN a/storage/innodb_plugin/include/srv0srv.h b/storage/innodb_plugin/include/srv0srv.h
+--- a/storage/innodb_plugin/include/srv0srv.h 2010-10-01 09:57:56.500228711 +0900
++++ b/storage/innodb_plugin/include/srv0srv.h 2010-10-01 10:00:13.302223409 +0900
+@@ -334,6 +334,9 @@
+ reading of a disk page */
+ extern ulint srv_buf_pool_reads;
+
++/** Time in seconds between automatic buffer pool dumps */
++extern uint srv_auto_lru_dump;
++
+ /** Status variables to be passed to MySQL */
+ typedef struct export_var_struct export_struc;
+
+@@ -602,6 +605,16 @@
+ /*=====================*/
+ void* arg); /*!< in: a dummy parameter required by
+ os_thread_create */
++/*********************************************************************//**
++A thread which restores the buffer pool from a dump file on startup and does
++periodic buffer pool dumps.
++ at return a dummy parameter */
++UNIV_INTERN
++os_thread_ret_t
++srv_LRU_dump_restore_thread(
++/*====================*/
++ void* arg); /*!< in: a dummy parameter required by
++ os_thread_create */
+ /******************************************************************//**
+ Outputs to a file the output of the InnoDB Monitor.
+ @return FALSE if not all information printed
+diff -ruN a/storage/innodb_plugin/srv/srv0srv.c b/storage/innodb_plugin/srv/srv0srv.c
+--- a/storage/innodb_plugin/srv/srv0srv.c 2010-10-01 09:57:56.516255101 +0900
++++ b/storage/innodb_plugin/srv/srv0srv.c 2010-10-01 10:00:13.304230973 +0900
+@@ -298,6 +298,9 @@
+ reading of a disk page */
+ UNIV_INTERN ulint srv_buf_pool_reads = 0;
+
++/** Time in seconds between automatic buffer pool dumps */
++UNIV_INTERN uint srv_auto_lru_dump = 0;
++
+ /* structure to pass status variables to MySQL */
+ UNIV_INTERN export_struc export_vars;
+
+@@ -2537,6 +2540,56 @@
+ /* We count the number of threads in os_thread_exit(). A created
+ thread should always use that to exit and not use return() to exit. */
+
++ os_thread_exit(NULL);
++
++ OS_THREAD_DUMMY_RETURN;
++}
++
++/*********************************************************************//**
++A thread which restores the buffer pool from a dump file on startup and does
++periodic buffer pool dumps.
++ at return a dummy parameter */
++UNIV_INTERN
++os_thread_ret_t
++srv_LRU_dump_restore_thread(
++/*====================*/
++ void* arg __attribute__((unused)))
++ /*!< in: a dummy parameter required by
++ os_thread_create */
++{
++ uint auto_lru_dump;
++ time_t last_dump_time;
++ time_t time_elapsed;
++
++#ifdef UNIV_DEBUG_THREAD_CREATION
++ fprintf(stderr, "LRU dump/restore thread starts, id %lu\n",
++ os_thread_pf(os_thread_get_curr_id()));
++#endif
++
++ if (srv_auto_lru_dump)
++ buf_LRU_file_restore();
++
++ last_dump_time = time(NULL);
++
++loop:
++ os_thread_sleep(5000000);
++
++ if (srv_shutdown_state >= SRV_SHUTDOWN_CLEANUP) {
++ goto exit_func;
++ }
++
++ time_elapsed = time(NULL) - last_dump_time;
++ auto_lru_dump = srv_auto_lru_dump;
++ if (auto_lru_dump > 0 && (time_t) auto_lru_dump < time_elapsed) {
++ last_dump_time = time(NULL);
++ buf_LRU_file_dump();
++ }
++
++ goto loop;
++exit_func:
++ /* We count the number of threads in os_thread_exit(). A created
++ thread should always use that to exit and not use return() to exit. */
++
+ os_thread_exit(NULL);
+
+ OS_THREAD_DUMMY_RETURN;
<Skipped 10963 lines>
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/percona-server.git/commitdiff/bf636d07b36bfd2921b9ecf2033c78270355c98c
More information about the pld-cvs-commit
mailing list