summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2012-08-22 16:13:54 +0200
committerSergei Golubchik <sergii@pisem.net>2012-08-22 16:13:54 +0200
commit1fd8150a5b5e3f56aa3c253225929a07ee9a4026 (patch)
tree6fb814b28d2a0b8227b7a9f835f2b888c2a2596f /storage
parent60561ae6133cf40f4fc445e1d6e8f395a20b2573 (diff)
parent115a2967563d3ac734ce371260098710ba42cdf0 (diff)
downloadmariadb-git-1fd8150a5b5e3f56aa3c253225929a07ee9a4026.tar.gz
5.1 merge
increase xtradb verson from 13.0 to 13.01
Diffstat (limited to 'storage')
-rw-r--r--storage/innobase/btr/btr0cur.c2
-rw-r--r--storage/innobase/dict/dict0load.c4
-rw-r--r--storage/innobase/handler/ha_innodb.cc33
-rw-r--r--storage/innobase/handler/ha_innodb.h1
-rw-r--r--storage/innobase/include/srv0srv.h1
-rw-r--r--storage/innobase/row/row0mysql.c4
-rw-r--r--storage/innobase/sync/sync0arr.c5
-rw-r--r--storage/innodb_plugin/btr/btr0cur.c2
-rw-r--r--storage/innodb_plugin/dict/dict0dict.c22
-rw-r--r--storage/innodb_plugin/dict/dict0load.c4
-rw-r--r--storage/innodb_plugin/fil/fil0fil.c2
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.cc41
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.h1
-rw-r--r--storage/innodb_plugin/handler/handler0alter.cc4
-rw-r--r--storage/innodb_plugin/include/srv0srv.h1
-rw-r--r--storage/innodb_plugin/row/row0ins.c6
-rw-r--r--storage/innodb_plugin/row/row0vers.c12
-rw-r--r--storage/innodb_plugin/sync/sync0arr.c5
-rw-r--r--storage/myisam/ft_boolean_search.c16
-rw-r--r--storage/myisam/ft_nlq_search.c18
-rw-r--r--storage/xtradb/ChangeLog178
-rw-r--r--storage/xtradb/btr/btr0btr.c244
-rw-r--r--storage/xtradb/btr/btr0cur.c357
-rw-r--r--storage/xtradb/btr/btr0pcur.c80
-rw-r--r--storage/xtradb/btr/btr0sea.c262
-rw-r--r--storage/xtradb/buf/buf0buddy.c2
-rw-r--r--storage/xtradb/buf/buf0buf.c183
-rw-r--r--storage/xtradb/buf/buf0lru.c8
-rw-r--r--storage/xtradb/compile-innodb24
-rw-r--r--storage/xtradb/compile-innodb-debug24
-rw-r--r--storage/xtradb/dict/dict0crea.c4
-rw-r--r--storage/xtradb/dict/dict0dict.c82
-rw-r--r--storage/xtradb/dict/dict0load.c4
-rw-r--r--storage/xtradb/fil/fil0fil.c107
-rw-r--r--storage/xtradb/fsp/fsp0fsp.c444
-rw-r--r--storage/xtradb/ha/ha0ha.c69
-rw-r--r--storage/xtradb/handler/ha_innodb.cc269
-rw-r--r--storage/xtradb/handler/ha_innodb.h1
-rw-r--r--storage/xtradb/handler/handler0alter.cc12
-rw-r--r--storage/xtradb/handler/i_s.cc2
-rw-r--r--storage/xtradb/ibuf/ibuf0ibuf.c87
-rw-r--r--storage/xtradb/include/btr0btr.h57
-rw-r--r--storage/xtradb/include/btr0btr.ic10
-rw-r--r--storage/xtradb/include/btr0cur.h84
-rw-r--r--storage/xtradb/include/btr0cur.ic29
-rw-r--r--storage/xtradb/include/btr0pcur.h8
-rw-r--r--storage/xtradb/include/btr0pcur.ic32
-rw-r--r--storage/xtradb/include/btr0sea.h34
-rw-r--r--storage/xtradb/include/btr0types.h25
-rw-r--r--storage/xtradb/include/buf0buf.h59
-rw-r--r--storage/xtradb/include/buf0buf.ic6
-rw-r--r--storage/xtradb/include/db0err.h2
-rw-r--r--storage/xtradb/include/dict0dict.h14
-rw-r--r--storage/xtradb/include/dict0dict.ic21
-rw-r--r--storage/xtradb/include/dict0mem.h10
-rw-r--r--storage/xtradb/include/fil0fil.h20
-rw-r--r--storage/xtradb/include/fsp0fsp.h44
-rw-r--r--storage/xtradb/include/ha0ha.h23
-rw-r--r--storage/xtradb/include/ha0ha.ic54
-rw-r--r--storage/xtradb/include/log0log.h6
-rw-r--r--storage/xtradb/include/mem0mem.ic4
-rw-r--r--storage/xtradb/include/mtr0mtr.h17
-rw-r--r--storage/xtradb/include/mtr0mtr.ic7
-rw-r--r--storage/xtradb/include/page0page.h15
-rw-r--r--storage/xtradb/include/page0page.ic6
-rw-r--r--storage/xtradb/include/row0upd.ic6
-rw-r--r--storage/xtradb/include/sync0rw.h3
-rw-r--r--storage/xtradb/include/sync0rw.ic5
-rw-r--r--storage/xtradb/include/sync0sync.h10
-rw-r--r--storage/xtradb/include/trx0purge.h4
-rw-r--r--storage/xtradb/include/trx0rec.ic7
-rw-r--r--storage/xtradb/include/trx0rseg.ic9
-rw-r--r--storage/xtradb/include/trx0sys.h6
-rw-r--r--storage/xtradb/include/trx0undo.h57
-rw-r--r--storage/xtradb/include/univ.i19
-rw-r--r--storage/xtradb/include/ut0mem.h31
-rw-r--r--storage/xtradb/include/ut0rnd.ic2
-rw-r--r--storage/xtradb/lock/lock0lock.c14
-rw-r--r--storage/xtradb/log/log0log.c6
-rw-r--r--storage/xtradb/mem/mem0pool.c6
-rw-r--r--storage/xtradb/mtr/mtr0mtr.c4
-rw-r--r--storage/xtradb/mysql-test/patches/README30
-rw-r--r--storage/xtradb/mysql-test/patches/index_merge_innodb-explain.diff31
-rw-r--r--storage/xtradb/mysql-test/patches/information_schema.diff124
-rw-r--r--storage/xtradb/mysql-test/patches/innodb_file_per_table.diff47
-rw-r--r--storage/xtradb/mysql-test/patches/innodb_lock_wait_timeout.diff55
-rw-r--r--storage/xtradb/mysql-test/patches/innodb_thread_concurrency_basic.diff31
-rw-r--r--storage/xtradb/mysql-test/patches/partition_innodb.diff59
-rw-r--r--storage/xtradb/os/os0file.c7
-rw-r--r--storage/xtradb/os/os0proc.c3
-rw-r--r--storage/xtradb/page/page0cur.c6
-rw-r--r--storage/xtradb/page/page0page.c20
-rw-r--r--storage/xtradb/revert_gen.sh8
-rw-r--r--storage/xtradb/row/row0ins.c79
-rw-r--r--storage/xtradb/row/row0merge.c35
-rw-r--r--storage/xtradb/row/row0mysql.c106
-rw-r--r--storage/xtradb/row/row0purge.c20
-rw-r--r--storage/xtradb/row/row0row.c29
-rw-r--r--storage/xtradb/row/row0sel.c24
-rw-r--r--storage/xtradb/row/row0upd.c61
-rw-r--r--storage/xtradb/scripts/export.sh74
-rw-r--r--storage/xtradb/scripts/install_innodb_plugins.sql8
-rw-r--r--storage/xtradb/scripts/install_innodb_plugins_win.sql8
-rw-r--r--storage/xtradb/setup.sh47
-rw-r--r--storage/xtradb/sync/sync0rw.c7
-rw-r--r--storage/xtradb/sync/sync0sync.c35
-rw-r--r--storage/xtradb/trx/trx0purge.c4
-rw-r--r--storage/xtradb/trx/trx0rec.c105
-rw-r--r--storage/xtradb/trx/trx0sys.c42
-rw-r--r--storage/xtradb/trx/trx0trx.c2
-rw-r--r--storage/xtradb/trx/trx0undo.c109
-rw-r--r--storage/xtradb/ut/ut0auxconf_atomic_pthread_t_gcc.c43
-rw-r--r--storage/xtradb/ut/ut0auxconf_atomic_pthread_t_solaris.c54
-rw-r--r--storage/xtradb/ut/ut0auxconf_have_gcc_atomics.c61
-rw-r--r--storage/xtradb/ut/ut0auxconf_have_solaris_atomics.c39
-rw-r--r--storage/xtradb/ut/ut0auxconf_pause.c32
-rw-r--r--storage/xtradb/ut/ut0auxconf_sizeof_pthread_t.c35
-rw-r--r--storage/xtradb/ut/ut0mem.c82
118 files changed, 3270 insertions, 1695 deletions
diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
index c09d6408fa0..4678ea8cd22 100644
--- a/storage/innobase/btr/btr0cur.c
+++ b/storage/innobase/btr/btr0cur.c
@@ -2792,6 +2792,8 @@ btr_estimate_n_rows_in_range(
n_rows = n_rows * 2;
}
+ DBUG_EXECUTE_IF("bug14007649", return(n_rows););
+
/* Do not estimate the number of rows in the range
to over 1 / 2 of the estimated rows in the whole
table */
diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c
index 7e820cfb08d..3c3c0d10c7c 100644
--- a/storage/innobase/dict/dict0load.c
+++ b/storage/innobase/dict/dict0load.c
@@ -150,7 +150,7 @@ dict_print(void)
monitor printout */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold += SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
mutex_enter(&(dict_sys->mutex));
@@ -178,7 +178,7 @@ loop:
/* Restore the fatal semaphore wait timeout */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold -= SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
return;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 6576016501f..796f51d737b 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -3180,6 +3180,30 @@ table_opened:
DBUG_RETURN(0);
}
+handler*
+ha_innobase::clone(
+/*===============*/
+ const char* name, /*!< in: table name */
+ MEM_ROOT* mem_root) /*!< in: memory context */
+{
+ ha_innobase* new_handler;
+
+ DBUG_ENTER("ha_innobase::clone");
+
+ new_handler = static_cast<ha_innobase*>(handler::clone(name,
+ mem_root));
+ if (new_handler) {
+ DBUG_ASSERT(new_handler->prebuilt != NULL);
+ DBUG_ASSERT(new_handler->user_thd == user_thd);
+ DBUG_ASSERT(new_handler->prebuilt->trx == prebuilt->trx);
+
+ new_handler->prebuilt->select_lock_type
+ = prebuilt->select_lock_type;
+ }
+
+ DBUG_RETURN(new_handler);
+}
+
uint
ha_innobase::max_supported_key_part_length() const
{
@@ -4869,6 +4893,7 @@ ha_innobase::index_read(
ulint ret;
DBUG_ENTER("index_read");
+ DEBUG_SYNC_C("ha_innobase_index_read_begin");
ut_a(prebuilt->trx == thd_to_trx(user_thd));
ut_ad(key_len != 0 || find_flag != HA_READ_KEY_EXACT);
@@ -9103,7 +9128,7 @@ static MYSQL_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
static MYSQL_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
PLUGIN_VAR_RQCMDARG,
"Desired maximum length of the purge queue (0 = no limit)",
- NULL, NULL, 0, 0, ~0L, 0);
+ NULL, NULL, 0, 0, ~0UL, 0);
static MYSQL_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
@@ -9157,7 +9182,7 @@ static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
PLUGIN_VAR_RQCMDARG,
"Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
- NULL, NULL, 500L, 1L, ~0L, 0);
+ NULL, NULL, 500L, 1L, ~0UL, 0);
static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
@@ -9202,7 +9227,7 @@ static MYSQL_SYSVAR_LONG(open_files, innobase_open_files,
static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
PLUGIN_VAR_RQCMDARG,
"Count of spin-loop rounds in InnoDB mutexes",
- NULL, NULL, 20L, 0L, ~0L, 0);
+ NULL, NULL, 20L, 0L, ~0UL, 0);
static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
PLUGIN_VAR_RQCMDARG,
@@ -9212,7 +9237,7 @@ static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
static MYSQL_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay,
PLUGIN_VAR_RQCMDARG,
"Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep",
- NULL, NULL, 10000L, 0L, ~0L, 0);
+ NULL, NULL, 10000L, 0L, ~0UL, 0);
static MYSQL_SYSVAR_STR(data_file_path, innobase_data_file_path,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 8b91f7d4c51..93229ad9185 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -117,6 +117,7 @@ class ha_innobase: public handler
const key_map *keys_to_use_for_scanning() { return &key_map_full; }
int open(const char *name, int mode, uint test_if_locked);
+ handler* clone(const char *name, MEM_ROOT *mem_root);
int close(void);
double scan_time();
double read_time(uint index, uint ranges, ha_rows rows);
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index 811074b2be8..aa6c88e0538 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -173,6 +173,7 @@ extern ibool srv_print_latch_waits;
extern ulint srv_activity_count;
extern ulint srv_fatal_semaphore_wait_threshold;
+#define SRV_SEMAPHORE_WAIT_EXTENSION 7200
extern ulint srv_dml_needed_delay;
extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index e8b3c485b0e..6c2f910eec7 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -4189,7 +4189,7 @@ row_check_table_for_mysql(
/* Enlarge the fatal lock wait timeout during CHECK TABLE. */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold += SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
index = dict_table_get_first_index(table);
@@ -4247,7 +4247,7 @@ row_check_table_for_mysql(
/* Restore the fatal lock wait timeout after CHECK TABLE. */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold -= SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
prebuilt->trx->op_info = "";
diff --git a/storage/innobase/sync/sync0arr.c b/storage/innobase/sync/sync0arr.c
index 93a7398f252..60a96fe4388 100644
--- a/storage/innobase/sync/sync0arr.c
+++ b/storage/innobase/sync/sync0arr.c
@@ -931,6 +931,11 @@ sync_array_print_long_waits(
ibool fatal = FALSE;
double longest_diff = 0;
+ /* For huge tables, skip the check during CHECK TABLE etc... */
+ if (fatal_timeout > SRV_SEMAPHORE_WAIT_EXTENSION) {
+ return(FALSE);
+ }
+
for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
double diff;
diff --git a/storage/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c
index b67da53ec8a..223b976dea7 100644
--- a/storage/innodb_plugin/btr/btr0cur.c
+++ b/storage/innodb_plugin/btr/btr0cur.c
@@ -3194,6 +3194,8 @@ btr_estimate_n_rows_in_range(
n_rows = n_rows * 2;
}
+ DBUG_EXECUTE_IF("bug14007649", return(n_rows););
+
/* Do not estimate the number of rows in the range
to over 1 / 2 of the estimated rows in the whole
table */
diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c
index df7ac85681c..cfeba015723 100644
--- a/storage/innodb_plugin/dict/dict0dict.c
+++ b/storage/innodb_plugin/dict/dict0dict.c
@@ -4872,6 +4872,28 @@ dict_table_replace_index_in_foreign_list(
foreign->foreign_index = new_index;
}
}
+
+
+ for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
+ foreign;
+ foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
+
+ dict_index_t* new_index;
+
+ if (foreign->referenced_index == index) {
+ ut_ad(foreign->referenced_table == index->table);
+
+ new_index = dict_foreign_find_index(
+ foreign->referenced_table,
+ foreign->referenced_col_names,
+ foreign->n_fields, index,
+ /*check_charsets=*/TRUE, /*check_null=*/FALSE);
+ ut_ad(new_index || !trx->check_foreigns);
+ ut_ad(!new_index || new_index->table == index->table);
+
+ foreign->referenced_index = new_index;
+ }
+ }
}
/**********************************************************************//**
diff --git a/storage/innodb_plugin/dict/dict0load.c b/storage/innodb_plugin/dict/dict0load.c
index 7a0b6edcb08..7231fadabe1 100644
--- a/storage/innodb_plugin/dict/dict0load.c
+++ b/storage/innodb_plugin/dict/dict0load.c
@@ -164,7 +164,7 @@ dict_print(void)
monitor printout */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold += SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
mutex_enter(&(dict_sys->mutex));
@@ -192,7 +192,7 @@ loop:
/* Restore the fatal semaphore wait timeout */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold -= SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
return;
diff --git a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c
index eebfbd9ccad..6f2ab938042 100644
--- a/storage/innodb_plugin/fil/fil0fil.c
+++ b/storage/innodb_plugin/fil/fil0fil.c
@@ -1853,7 +1853,7 @@ fil_inc_pending_ops(
if (space == NULL) {
fprintf(stderr,
- "InnoDB: Error: trying to do ibuf merge to a"
+ "InnoDB: Error: trying to do an operation on a"
" dropped tablespace %lu\n",
(ulong) id);
}
diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
index b822d2b447e..0e954424365 100644
--- a/storage/innodb_plugin/handler/ha_innodb.cc
+++ b/storage/innodb_plugin/handler/ha_innodb.cc
@@ -3890,6 +3890,31 @@ table_opened:
}
UNIV_INTERN
+handler*
+ha_innobase::clone(
+/*===============*/
+ const char* name, /*!< in: table name */
+ MEM_ROOT* mem_root) /*!< in: memory context */
+{
+ ha_innobase* new_handler;
+
+ DBUG_ENTER("ha_innobase::clone");
+
+ new_handler = static_cast<ha_innobase*>(handler::clone(name,
+ mem_root));
+ if (new_handler) {
+ DBUG_ASSERT(new_handler->prebuilt != NULL);
+ DBUG_ASSERT(new_handler->user_thd == user_thd);
+ DBUG_ASSERT(new_handler->prebuilt->trx == prebuilt->trx);
+
+ new_handler->prebuilt->select_lock_type
+ = prebuilt->select_lock_type;
+ }
+
+ DBUG_RETURN(new_handler);
+}
+
+UNIV_INTERN
uint
ha_innobase::max_supported_key_part_length() const
{
@@ -8153,7 +8178,7 @@ ha_innobase::check(
/* Enlarge the fatal lock wait timeout during CHECK TABLE. */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold += SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
for (index = dict_table_get_first_index(prebuilt->table);
@@ -8249,7 +8274,7 @@ ha_innobase::check(
/* Restore the fatal lock wait timeout after CHECK TABLE. */
mutex_enter(&kernel_mutex);
- srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
+ srv_fatal_semaphore_wait_threshold -= SRV_SEMAPHORE_WAIT_EXTENSION;
mutex_exit(&kernel_mutex);
prebuilt->trx->op_info = "";
@@ -10950,7 +10975,7 @@ static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
static MYSQL_SYSVAR_ULONG(io_capacity, srv_io_capacity,
PLUGIN_VAR_RQCMDARG,
"Number of IOPs the server can do. Tunes the background IO rate",
- NULL, NULL, 200, 100, ~0L, 0);
+ NULL, NULL, 200, 100, ~0UL, 0);
static MYSQL_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown,
PLUGIN_VAR_OPCMDARG,
@@ -11028,7 +11053,7 @@ static MYSQL_SYSVAR_BOOL(adaptive_flushing, srv_adaptive_flushing,
static MYSQL_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
PLUGIN_VAR_RQCMDARG,
"Desired maximum length of the purge queue (0 = no limit)",
- NULL, NULL, 0, 0, ~0L, 0);
+ NULL, NULL, 0, 0, ~0UL, 0);
static MYSQL_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
@@ -11085,7 +11110,7 @@ static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
PLUGIN_VAR_RQCMDARG,
"Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
- NULL, NULL, 500L, 1L, ~0L, 0);
+ NULL, NULL, 500L, 1L, ~0UL, 0);
static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR,
@@ -11147,12 +11172,12 @@ static MYSQL_SYSVAR_LONG(open_files, innobase_open_files,
static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
PLUGIN_VAR_RQCMDARG,
"Count of spin-loop rounds in InnoDB mutexes (30 by default)",
- NULL, NULL, 30L, 0L, ~0L, 0);
+ NULL, NULL, 30L, 0L, ~0UL, 0);
static MYSQL_SYSVAR_ULONG(spin_wait_delay, srv_spin_wait_delay,
PLUGIN_VAR_OPCMDARG,
"Maximum delay between polling for a spin lock (6 by default)",
- NULL, NULL, 6L, 0L, ~0L, 0);
+ NULL, NULL, 6L, 0L, ~0UL, 0);
static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
PLUGIN_VAR_RQCMDARG,
@@ -11162,7 +11187,7 @@ static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
static MYSQL_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay,
PLUGIN_VAR_RQCMDARG,
"Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep",
- NULL, NULL, 10000L, 0L, ~0L, 0);
+ NULL, NULL, 10000L, 0L, ~0UL, 0);
static MYSQL_SYSVAR_STR(data_file_path, innobase_data_file_path,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
diff --git a/storage/innodb_plugin/handler/ha_innodb.h b/storage/innodb_plugin/handler/ha_innodb.h
index f7a5456b1a7..15cc4a77b6f 100644
--- a/storage/innodb_plugin/handler/ha_innodb.h
+++ b/storage/innodb_plugin/handler/ha_innodb.h
@@ -132,6 +132,7 @@ class ha_innobase: public handler
const key_map* keys_to_use_for_scanning();
int open(const char *name, int mode, uint test_if_locked);
+ handler* clone(const char *name, MEM_ROOT *mem_root);
int close(void);
double scan_time();
double read_time(uint index, uint ranges, ha_rows rows);
diff --git a/storage/innodb_plugin/handler/handler0alter.cc b/storage/innodb_plugin/handler/handler0alter.cc
index e2702b157af..6f02b500d96 100644
--- a/storage/innodb_plugin/handler/handler0alter.cc
+++ b/storage/innodb_plugin/handler/handler0alter.cc
@@ -665,6 +665,10 @@ ha_innobase::add_index(
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
}
+ if (innodb_table->tablespace_discarded) {
+ DBUG_RETURN(-1);
+ }
+
/* Check that index keys are sensible */
error = innobase_check_index_keys(key_info, num_of_keys, innodb_table);
diff --git a/storage/innodb_plugin/include/srv0srv.h b/storage/innodb_plugin/include/srv0srv.h
index 7c63a5f0d45..1a9f54882c5 100644
--- a/storage/innodb_plugin/include/srv0srv.h
+++ b/storage/innodb_plugin/include/srv0srv.h
@@ -244,6 +244,7 @@ extern ibool srv_print_latch_waits;
extern ulint srv_activity_count;
extern ulint srv_fatal_semaphore_wait_threshold;
+#define SRV_SEMAPHORE_WAIT_EXTENSION 7200
extern ulint srv_dml_needed_delay;
extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
diff --git a/storage/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c
index 2d4afa6c5ed..4994a91dd23 100644
--- a/storage/innodb_plugin/row/row0ins.c
+++ b/storage/innodb_plugin/row/row0ins.c
@@ -1296,7 +1296,8 @@ run_again:
check_index = foreign->foreign_index;
}
- if (check_table == NULL || check_table->ibd_file_missing) {
+ if (check_table == NULL || check_table->ibd_file_missing
+ || check_index == NULL) {
if (check_ref) {
FILE* ef = dict_foreign_err_file;
@@ -1331,9 +1332,6 @@ run_again:
goto exit_func;
}
- ut_a(check_table);
- ut_a(check_index);
-
if (check_table != table) {
/* We already have a LOCK_IX on table, but not necessarily
on check_table */
diff --git a/storage/innodb_plugin/row/row0vers.c b/storage/innodb_plugin/row/row0vers.c
index 8a7bb842293..9aeaa2db6c0 100644
--- a/storage/innodb_plugin/row/row0vers.c
+++ b/storage/innodb_plugin/row/row0vers.c
@@ -208,18 +208,6 @@ row_vers_impl_x_locked_off_kernel(
vers_del = rec_get_deleted_flag(prev_version, comp);
prev_trx_id = row_get_rec_trx_id(prev_version, clust_index,
clust_offsets);
-
- /* If the trx_id and prev_trx_id are different and if
- the prev_version is marked deleted then the
- prev_trx_id must have already committed for the trx_id
- to be able to modify the row. Therefore, prev_trx_id
- cannot hold any implicit lock. */
- if (vers_del && 0 != ut_dulint_cmp(trx_id, prev_trx_id)) {
-
- mutex_enter(&kernel_mutex);
- break;
- }
-
/* The stack of versions is locked by mtr. Thus, it
is safe to fetch the prefixes for externally stored
columns. */
diff --git a/storage/innodb_plugin/sync/sync0arr.c b/storage/innodb_plugin/sync/sync0arr.c
index 13970023573..90ea50b641b 100644
--- a/storage/innodb_plugin/sync/sync0arr.c
+++ b/storage/innodb_plugin/sync/sync0arr.c
@@ -927,6 +927,11 @@ sync_array_print_long_waits(
ibool fatal = FALSE;
double longest_diff = 0;
+ /* For huge tables, skip the check during CHECK TABLE etc... */
+ if (fatal_timeout > SRV_SEMAPHORE_WAIT_EXTENSION) {
+ return(FALSE);
+ }
+
for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
double diff;
diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c
index 32ac71a422c..3f3e0230135 100644
--- a/storage/myisam/ft_boolean_search.c
+++ b/storage/myisam/ft_boolean_search.c
@@ -354,7 +354,7 @@ static int _ftb_no_dupes_cmp(void* not_used __attribute__((unused)),
returns 1 if the search was finished (must-word wasn't found)
*/
-static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
+static int _ft2_search_no_lock(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
{
int r;
int subkeys=1;
@@ -454,7 +454,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
ftbw->key_root=info->s->state.key_root[ftb->keynr];
ftbw->keyinfo=info->s->keyinfo+ftb->keynr;
ftbw->off=0;
- return _ft2_search(ftb, ftbw, 0);
+ return _ft2_search_no_lock(ftb, ftbw, 0);
}
/* matching key found */
@@ -482,6 +482,18 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
return 0;
}
+static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
+{
+ int r;
+ MYISAM_SHARE *share= ftb->info->s;
+ if (share->concurrent_insert)
+ rw_rdlock(&share->key_root_lock[ftb->keynr]);
+ r= _ft2_search_no_lock(ftb, ftbw, init_search);
+ if (share->concurrent_insert)
+ rw_unlock(&share->key_root_lock[ftb->keynr]);
+ return r;
+}
+
static void _ftb_init_index_search(FT_INFO *ftb)
{
int i;
diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c
index 85557b5e6c4..9ebdef582c9 100644
--- a/storage/myisam/ft_nlq_search.c
+++ b/storage/myisam/ft_nlq_search.c
@@ -72,9 +72,10 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
TREE_ELEMENT *selem;
double gweight=1;
MI_INFO *info=aio->info;
+ MYISAM_SHARE *share= info->s;
uchar *keybuff=aio->keybuff;
MI_KEYDEF *keyinfo=info->s->keyinfo+aio->keynr;
- my_off_t key_root=info->s->state.key_root[aio->keynr];
+ my_off_t key_root;
uint extra= HA_FT_WLEN + info->s->rec_reflength;
#if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
float tmp_weight;
@@ -89,6 +90,11 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
keylen-=HA_FT_WLEN;
doc_cnt=0;
+ if (share->concurrent_insert)
+ rw_rdlock(&share->key_root_lock[aio->keynr]);
+
+ key_root= share->state.key_root[aio->keynr];
+
/* Skip rows inserted by current inserted */
for (r=_mi_search(info, keyinfo, keybuff, keylen, SEARCH_FIND, key_root) ;
!r &&
@@ -98,6 +104,9 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
info->lastkey_length, SEARCH_BIGGER, key_root))
;
+ if (share->concurrent_insert)
+ rw_unlock(&share->key_root_lock[aio->keynr]);
+
info->update|= HA_STATE_AKTIV; /* for _mi_test_if_changed() */
/* The following should be safe, even if we compare doubles */
@@ -121,6 +130,8 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
keyinfo=& info->s->ft2_keyinfo;
key_root=info->lastpos;
keylen=0;
+ if (share->concurrent_insert)
+ rw_rdlock(&share->key_root_lock[aio->keynr]);
r=_mi_search_first(info, keyinfo, key_root);
goto do_skip;
}
@@ -156,6 +167,9 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
if (gweight < 0 || doc_cnt > 2000000)
gweight=0;
+ if (share->concurrent_insert)
+ rw_rdlock(&share->key_root_lock[aio->keynr]);
+
if (_mi_test_if_changed(info) == 0)
r=_mi_search_next(info, keyinfo, info->lastkey, info->lastkey_length,
SEARCH_BIGGER, key_root);
@@ -168,6 +182,8 @@ do_skip:
r= _mi_search_next(info, keyinfo, info->lastkey, info->lastkey_length,
SEARCH_BIGGER, key_root);
+ if (share->concurrent_insert)
+ rw_unlock(&share->key_root_lock[aio->keynr]);
}
word->weight=gweight;
diff --git a/storage/xtradb/ChangeLog b/storage/xtradb/ChangeLog
index 7a4cacb5b43..1588132fc8b 100644
--- a/storage/xtradb/ChangeLog
+++ b/storage/xtradb/ChangeLog
@@ -1,8 +1,182 @@
+2012-03-15 The InnoDB Team
+
+ * fil/fil0fil.c, ibuf/ibuf0ibuf.c, include/fil0fil.h,
+ lock/lock0lock.c:
+ Fix Bug#13825266 RACE IN LOCK_VALIDATE() WHEN ACCESSING PAGES
+ DIRECTLY FROM BUFFER POOL
+
+2012-03-15 The InnoDB Team
+
+ * handler/ha_innodb.cc:
+ Fix Bug#13851171STRING OVERFLOW IN INNODB CODE FOUND BY STATIC
+ ANALYSIS
+
+2012-03-15 The InnoDB Team
+
+ * include/sync0rw.ic:
+ Fix Bug#13537504 VALGRIND: COND. JUMP/MOVE DEPENDS ON
+ UNINITIALISED VALUES IN OS_THREAD_EQ
+
+2012-03-08 The InnoDB Team
+
+ * btr/btr0pcur.c:
+ Fix Bug#13807811 BTR_PCUR_RESTORE_POSITION() CAN SKIP A RECORD
+
+2012-02-28 The InnoDB Team
+
+ * btr/btr0btr.c, dict/dict0dict.c, include/btr0btr.h,
+ include/dict0dict.h, include/dict0dict.ic, include/dict0mem.h,
+ handler/handler0alter.cc, row/row0mysql.c:
+ Fix Bug#12861864 RACE CONDITION IN BTR_GET_SIZE() AND
+ DROP INDEX/TABLE/DATABASE
+
+2012-02-15 The InnoDB Team
+
+ * btr/btr0btr.c, btr/btr0cur.c, fsp/fsp0fsp.c, ibuf/ibuf0ibuf.c,
+ include/btr0btr.h, include/btr0cur.h, include/btr0cur.ic,
+ include/buf0buf.h, include/buf0buf.ic, include/fsp0fsp.h,
+ include/mtr0mtr.h, include/mtr0mtr.ic, include/page0page.h,
+ include/page0page.ic, include/trx0rec.ic, include/trx0undo.h,
+ mtr/mtr0mtr.c, page/page0cur.c, page/page0page.c, row/row0ins.c,
+ row/row0row.c, row/row0upd.c, trx/trx0rec.c, trx/trx0sys.c,
+ trx/trx0undo.c:
+ Fix Bug#13721257 RACE CONDITION IN UPDATES OR INSERTS OF WIDE RECORDS
+
+2012-02-06 The InnoDB Team
+
+ * handler/ha_innodb.cc:
+ Fix Bug#11754376 45976: INNODB LOST FILES FOR TEMPORARY TABLES ON
+ GRACEFUL SHUTDOWN
+
+2012-01-30 The InnoDB Team
+
+ * fil/fil0fil.c:
+ Fix Bug#13636122 THE ORIGINAL TABLE MISSING WHILE EXECUTE THE
+ DDL 'ALTER TABLE ADD COLUMN'
+
+2012-01-16 The InnoDB Team
+
+ * ibuf/ibuf0ibuf.c:
+ Fix Bug#13496818 ASSERTION: REC_PAGE_NO > 4 IN IBUF CONTRACTION
+
+2012-01-16 The InnoDB Team
+
+ * handler/ha_innodb.cc:
+ Fix Bug#11765438: 58406: ISSUES WITH COPYING PARTITIONED INNODB
+ TABLES FROM LINUX TO WINDOWS
+
+2012-01-04 The InnoDB Team
+
+ * row/row0mysql.c:
+ Fix Bug#12400341: INNODB CAN LEAVE ORPHAN IBD FILES AROUND
+
+2011-12-22 The InnoDB Team
+
+ * row/row0sel.c:
+ Fix Bug#63775 Server crash on handler read next after delete record.
+2011-12-21 The InnoDB Team
+
+ * include/ut0rnd.ic:
+ Fix Bug#11866367:FPE WHEN SETTING INNODB_SPIN_WAIT_DELAY
+
+2011-12-13 The InnoDB Team
+
+ * handler/ha_innodb.cc, innodb.test, innodb.result:
+ Fix Bug#13117023: InnoDB was incrementing the handler_read_key,
+ also the SSV::ha_read_key_count, at the wrong place.
+
+2011-12-10 The InnoDB Team
+
+ * include/page0page.h, page/page0page.c:
+ Fix Bug#13418887 ERROR IN DIAGNOSTIC FUNCTION PAGE_REC_PRINT()
+
+2011-11-10 The InnoDB Team
+
+ * handler/ha_innodb.cc, row/row0ins.c, innodb_replace.test:
+ Fix Bug#11759688 52020: InnoDB can still deadlock
+ on just INSERT...ON DUPLICATE KEY a.k.a. the reintroduction of
+ Bug#7975 deadlock without any locking, simple select and update
+
+2011-11-08 The InnoDB Team
+
+ * btr/btr0pcur.c, include/btr0pcur.h, include/btr0pcur.ic:
+ Fix Bug#13358468 ASSERTION FAILURE IN BTR_PCUR_GET_BLOCK
+
+2011-10-27 The InnoDB Team
+
+ * row/row0mysql.c:
+ Fix Bug #12884631 62146: TABLES ARE LOST FOR DDL
+
2011-10-25 The InnoDB Team
* handler/ha_innodb.cc, row/row0ins.c:
Fix Bug#13002783 PARTIALLY UNINITIALIZED CASCADE UPDATE VECTOR
+2011-10-20 The InnoDB Team
+
+ * btr/btr0cur.c:
+ Fix Bug#13116045 Compilation failure using GCC 4.6.1 in btr/btr0cur.c
+
+2011-10-12 The InnoDB Team
+
+ * btr/btr0cur.c, btr/btr0sea.c, buf/buf0buf.c, buf/buf0lru.c,
+ ha/ha0ha.c, handler/ha_innodb.cc, ibuf/ibuf0ibuf.c, include/btr0sea.h,
+ include/btr0types.h, include/buf0buf.h, include/ha0ha.h,
+ include/ha0ha.ic, include/row0upd.ic, include/sync0sync.h,
+ page/page0page.c, sync/sync0sync.c:
+ Fix Bug#13006367 62487: innodb takes 3 minutes to clean up
+ the adaptive hash index at shutdown
+
+2011-10-04 The InnoDB Team
+
+ * include/sync0rw.h, sync/sync0rw.c:
+ Fix Bug#13034534 RQG TESTS FAIL ON WINDOWS WITH CRASH NEAR
+ RW_LOCK_DEBUG_PRINT
+
+2011-09-20 The InnoDB Team
+
+ * row/row0purge.c:
+ Fix Bug#12963823 CRASH IN PURGE THREAD UNDER UNUSUAL CIRCUMSTANCES
+
+2011-09-12 The InnoDB Team
+
+ * row/row0sel.c:
+ Fix Bug#12601439 CONSISTENT READ FAILURE IN COLUMN PREFIX INDEX
+
+2011-09-08 The InnoDB Team
+
+ * btr/btr0cur.c, include/page0page.h, include/row0upd.ic:
+ Fix Bug#12948130 UNNECESSARY X-LOCKING OF ADAPTIVE HASH INDEX
+
+2011-09-06 The InnoDB Team
+
+ * buf/buf0buddy.c:
+ Fix Bug#12950803 62294: BUF_BUDDY_RELOCATE CALLS GETTIMEOFDAY
+ WHILE HOLDING BUFFER POOL MUTEX
+
+2011-09-06 The InnoDB Team
+
+ * include/trx0undo.h, trx/trx0rec.c, trx/trx0undo.c:
+ Fix Bug#12547647 UPDATE LOGGING COULD EXCEED LOG PAGE SIZE
+
+2011-08-29 The InnoDB Team
+
+ * btr/btr0btr.c, btr/btr0cur.c, fsp/fsp0fsp.c,
+ include/btr0btr.h, include/btr0cur.h, include/fsp0fsp.h,
+ include/mtr0mtr.h, include/mtr0mtr.ic, mtr/mtr0mtr.c,
+ row/row0ins.c, row/row0row.c, row/row0upd.c, trx/trx0undo.c:
+ Fix Bug#12704861 Corruption after a crash during BLOB update
+ and other regressions from the fix of Bug#12612184
+
+2011-08-15 The InnoDB Team
+
+ * btr/btr0btr.c, btr/btr0cur.c, btr/btr0pcur.c, btr/btr0sea.c,
+ dict/dict0crea.c, dict/dict0dict.c, ibuf/ibuf0ibuf.c,
+ include/btr0btr.h, include/btr0btr.ic, include/sync0sync.h,
+ sync/sync0sync.c:
+ Fix Bug#11766591 59733: Possible deadlock when buffered changes
+ are to be discarded in buf_page_create()
+
2011-08-08 The InnoDB Team
* row/row0sel.c:
@@ -170,7 +344,7 @@
2011-01-06 The InnoDB Team
* dict/dict0dict.c, handler/ha_innodb.cc, handler/i_s.cc,
- include/univ.i:
+ include/univ.i:
Fix Bug#58643 InnoDB: too long table name
2011-01-06 The InnoDB Team
@@ -436,7 +610,7 @@
* handler/ha_innodb.cc, include/row0mysql.h, row/row0mysql.c:
Fix Bug#53592: crash replacing duplicates into table after fast
- alter table added unique key
+ alter table added unique key
2010-05-24 The InnoDB Team
diff --git a/storage/xtradb/btr/btr0btr.c b/storage/xtradb/btr/btr0btr.c
index 396ad422010..75cc80d0967 100644
--- a/storage/xtradb/btr/btr0btr.c
+++ b/storage/xtradb/btr/btr0btr.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -690,7 +690,8 @@ btr_root_block_get(
zip_size = dict_table_zip_size(index->table);
root_page_no = dict_index_get_page(index);
- block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
+ block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
+ index, mtr);
if (srv_pass_corrupt_table && !block) {
return(0);
@@ -897,7 +898,7 @@ btr_page_alloc_for_ibuf(
dict_table_zip_size(index->table),
node_addr.page, RW_X_LATCH, mtr);
new_page = buf_block_get_frame(new_block);
- buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW);
+ buf_block_dbg_add_level(new_block, SYNC_IBUF_TREE_NODE_NEW);
flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE,
@@ -911,28 +912,31 @@ btr_page_alloc_for_ibuf(
/**************************************************************//**
Allocates a new file page to be used in an index tree. NOTE: we assume
that the caller has made the reservation for free extents!
-@return new allocated block, x-latched; NULL if out of space */
-UNIV_INTERN
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
+static __attribute__((nonnull, warn_unused_result))
buf_block_t*
-btr_page_alloc(
-/*===========*/
+btr_page_alloc_low(
+/*===============*/
dict_index_t* index, /*!< in: index */
ulint hint_page_no, /*!< in: hint of a good page */
byte file_direction, /*!< in: direction where a possible
page split is made */
ulint level, /*!< in: level where the page is placed
in the tree */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr, /*!< in/out: mini-transaction
+ for the allocation */
+ mtr_t* init_mtr) /*!< in/out: mtr or another
+ mini-transaction in which the
+ page should be initialized.
+ If init_mtr!=mtr, but the page
+ is already X-latched in mtr, do
+ not initialize the page. */
{
fseg_header_t* seg_header;
page_t* root;
- buf_block_t* new_block;
- ulint new_page_no;
-
- if (dict_index_is_ibuf(index)) {
-
- return(btr_page_alloc_for_ibuf(index, mtr));
- }
root = btr_root_get(index, mtr);
@@ -946,45 +950,81 @@ btr_page_alloc(
reservation for free extents, and thus we know that a page can
be allocated: */
- new_page_no = fseg_alloc_free_page_general(seg_header, hint_page_no,
- file_direction, TRUE, mtr);
- if (new_page_no == FIL_NULL) {
+ return(fseg_alloc_free_page_general(
+ seg_header, hint_page_no, file_direction,
+ TRUE, mtr, init_mtr));
+}
- return(NULL);
+/**************************************************************//**
+Allocates a new file page to be used in an index tree. NOTE: we assume
+that the caller has made the reservation for free extents!
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
+UNIV_INTERN
+buf_block_t*
+btr_page_alloc(
+/*===========*/
+ dict_index_t* index, /*!< in: index */
+ ulint hint_page_no, /*!< in: hint of a good page */
+ byte file_direction, /*!< in: direction where a possible
+ page split is made */
+ ulint level, /*!< in: level where the page is placed
+ in the tree */
+ mtr_t* mtr, /*!< in/out: mini-transaction
+ for the allocation */
+ mtr_t* init_mtr) /*!< in/out: mini-transaction
+ for x-latching and initializing
+ the page */
+{
+ buf_block_t* new_block;
+
+ if (dict_index_is_ibuf(index)) {
+
+ return(btr_page_alloc_for_ibuf(index, mtr));
}
- new_block = buf_page_get(dict_index_get_space(index),
- dict_table_zip_size(index->table),
- new_page_no, RW_X_LATCH, mtr);
- buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW);
+ new_block = btr_page_alloc_low(
+ index, hint_page_no, file_direction, level, mtr, init_mtr);
+
+ if (new_block) {
+ buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW);
+ }
return(new_block);
}
/**************************************************************//**
Gets the number of pages in a B-tree.
-@return number of pages */
+@return number of pages, or ULINT_UNDEFINED if the index is unavailable */
UNIV_INTERN
ulint
btr_get_size(
/*=========*/
dict_index_t* index, /*!< in: index */
- ulint flag) /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
+ ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
+ mtr_t* mtr) /*!< in/out: mini-transaction where index
+ is s-latched */
{
fseg_header_t* seg_header;
page_t* root;
ulint n;
ulint dummy;
- mtr_t mtr;
- mtr_start(&mtr);
+ ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
+ MTR_MEMO_S_LOCK));
- mtr_s_lock(dict_index_get_lock(index), &mtr);
+ if (index->page == FIL_NULL
+ || index->to_be_dropped
+ || *index->name == TEMP_INDEX_PREFIX) {
+ return(ULINT_UNDEFINED);
+ }
- root = btr_root_get(index, &mtr);
+ root = btr_root_get(index, mtr);
if (srv_pass_corrupt_table && !root) {
- mtr_commit(&mtr);
+ mtr_commit(mtr);
return(0);
}
ut_a(root);
@@ -992,22 +1032,20 @@ btr_get_size(
if (flag == BTR_N_LEAF_PAGES) {
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
- fseg_n_reserved_pages(seg_header, &n, &mtr);
+ fseg_n_reserved_pages(seg_header, &n, mtr);
} else if (flag == BTR_TOTAL_SIZE) {
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP;
- n = fseg_n_reserved_pages(seg_header, &dummy, &mtr);
+ n = fseg_n_reserved_pages(seg_header, &dummy, mtr);
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
- n += fseg_n_reserved_pages(seg_header, &dummy, &mtr);
+ n += fseg_n_reserved_pages(seg_header, &dummy, mtr);
} else {
ut_error;
}
- mtr_commit(&mtr);
-
return(n);
}
@@ -1076,6 +1114,15 @@ btr_page_free_low(
fseg_free_page(seg_header,
buf_block_get_space(block),
buf_block_get_page_no(block), mtr);
+
+ /* The page was marked free in the allocation bitmap, but it
+ should remain buffer-fixed until mtr_commit(mtr) or until it
+ is explicitly freed from the mini-transaction. */
+ ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ /* TODO: Discard any operations on the page from the redo log
+ and remove the block from the flush list and the buffer pool.
+ This would free up buffer pool earlier and reduce writes to
+ both the tablespace and the redo log. */
}
/**************************************************************//**
@@ -1089,10 +1136,10 @@ btr_page_free(
buf_block_t* block, /*!< in: block to be freed, x-latched */
mtr_t* mtr) /*!< in: mtr */
{
- ulint level;
-
- level = btr_page_get_level(buf_block_get_frame(block), mtr);
+ const page_t* page = buf_block_get_frame(block);
+ ulint level = btr_page_get_level(page, mtr);
+ ut_ad(fil_page_get_type(block->frame) == FIL_PAGE_INDEX);
btr_page_free_low(index, block, level, mtr);
}
@@ -1151,7 +1198,7 @@ btr_node_ptr_get_child(
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
return(btr_block_get(space, dict_table_zip_size(index->table),
- page_no, RW_X_LATCH, mtr));
+ page_no, RW_X_LATCH, index, mtr));
}
/************************************************************//**
@@ -1323,23 +1370,20 @@ btr_create(
space, 0,
IBUF_HEADER + IBUF_TREE_SEG_HEADER, mtr);
- buf_block_dbg_add_level(ibuf_hdr_block, SYNC_TREE_NODE_NEW);
+ buf_block_dbg_add_level(
+ ibuf_hdr_block, SYNC_IBUF_TREE_NODE_NEW);
ut_ad(buf_block_get_page_no(ibuf_hdr_block)
== IBUF_HEADER_PAGE_NO);
/* Allocate then the next page to the segment: it will be the
tree root page */
- page_no = fseg_alloc_free_page(buf_block_get_frame(
- ibuf_hdr_block)
- + IBUF_HEADER
- + IBUF_TREE_SEG_HEADER,
- IBUF_TREE_ROOT_PAGE_NO,
- FSP_UP, mtr);
- ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
-
- block = buf_page_get(space, zip_size, page_no,
- RW_X_LATCH, mtr);
+ block = fseg_alloc_free_page(
+ buf_block_get_frame(ibuf_hdr_block)
+ + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
+ IBUF_TREE_ROOT_PAGE_NO,
+ FSP_UP, mtr);
+ ut_ad(buf_block_get_page_no(block) == IBUF_TREE_ROOT_PAGE_NO);
} else {
#ifdef UNIV_BLOB_DEBUG
if ((type & DICT_CLUSTERED) && !index->blobs) {
@@ -1360,10 +1404,9 @@ btr_create(
page_no = buf_block_get_page_no(block);
frame = buf_block_get_frame(block);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
-
if (type & DICT_IBUF) {
/* It is an insert buffer tree: initialize the free list */
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
@@ -1371,6 +1414,8 @@ btr_create(
} else {
/* It is a non-ibuf tree: create a file segment for leaf
pages */
+ buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
+
if (!fseg_create(space, page_no,
PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) {
/* Not enough space for new segment, free root
@@ -1442,14 +1487,15 @@ btr_free_but_not_root(
leaf_loop:
mtr_start(&mtr);
- root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr);
+ root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
+ NULL, &mtr);
if (srv_pass_corrupt_table && !root) {
mtr_commit(&mtr);
return;
}
ut_a(root);
-
+
#ifdef UNIV_BTR_DEBUG
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
+ root, space));
@@ -1471,7 +1517,8 @@ leaf_loop:
top_loop:
mtr_start(&mtr);
- root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr);
+ root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
+ NULL, &mtr);
if (srv_pass_corrupt_table && !root) {
mtr_commit(&mtr);
@@ -1503,13 +1550,13 @@ btr_free_root(
ulint zip_size, /*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint root_page_no, /*!< in: root page number */
- mtr_t* mtr) /*!< in: a mini-transaction which has already
- been started */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
buf_block_t* block;
fseg_header_t* header;
- block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
+ block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
+ NULL, mtr);
if (srv_pass_corrupt_table && !block) {
return;
@@ -1831,7 +1878,7 @@ btr_root_raise_and_insert(
level = btr_page_get_level(root, mtr);
- new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr);
+ new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr);
new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block);
ut_a(!new_page_zip == !root_page_zip);
@@ -2392,9 +2439,8 @@ btr_attach_half_pages(
/* Update page links of the level */
if (prev_page_no != FIL_NULL) {
- buf_block_t* prev_block = btr_block_get(space, zip_size,
- prev_page_no,
- RW_X_LATCH, mtr);
+ buf_block_t* prev_block = btr_block_get(
+ space, zip_size, prev_page_no, RW_X_LATCH, index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(prev_block->frame) == page_is_comp(page));
ut_a(btr_page_get_next(prev_block->frame, mtr)
@@ -2407,9 +2453,8 @@ btr_attach_half_pages(
}
if (next_page_no != FIL_NULL) {
- buf_block_t* next_block = btr_block_get(space, zip_size,
- next_page_no,
- RW_X_LATCH, mtr);
+ buf_block_t* next_block = btr_block_get(
+ space, zip_size, next_page_no, RW_X_LATCH, index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(next_block->frame) == page_is_comp(page));
ut_a(btr_page_get_prev(next_block->frame, mtr)
@@ -2569,7 +2614,7 @@ func_start:
/* 2. Allocate a new page to the index */
new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
- btr_page_get_level(page, mtr), mtr);
+ btr_page_get_level(page, mtr), mtr, mtr);
new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block);
btr_page_create(new_block, new_page_zip, cursor->index,
@@ -2831,17 +2876,42 @@ func_exit:
return(rec);
}
+#ifdef UNIV_SYNC_DEBUG
+/*************************************************************//**
+Removes a page from the level list of pages.
+@param space in: space where removed
+@param zip_size in: compressed page size in bytes, or 0 for uncompressed
+@param page in/out: page to remove
+@param index in: index tree
+@param mtr in/out: mini-transaction */
+# define btr_level_list_remove(space,zip_size,page,index,mtr) \
+ btr_level_list_remove_func(space,zip_size,page,index,mtr)
+#else /* UNIV_SYNC_DEBUG */
+/*************************************************************//**
+Removes a page from the level list of pages.
+@param space in: space where removed
+@param zip_size in: compressed page size in bytes, or 0 for uncompressed
+@param page in/out: page to remove
+@param index in: index tree
+@param mtr in/out: mini-transaction */
+# define btr_level_list_remove(space,zip_size,page,index,mtr) \
+ btr_level_list_remove_func(space,zip_size,page,mtr)
+#endif /* UNIV_SYNC_DEBUG */
+
/*************************************************************//**
Removes a page from the level list of pages. */
-static
+static __attribute__((nonnull))
void
-btr_level_list_remove(
-/*==================*/
- ulint space, /*!< in: space where removed */
- ulint zip_size,/*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
- page_t* page, /*!< in: page to remove */
- mtr_t* mtr) /*!< in: mtr */
+btr_level_list_remove_func(
+/*=======================*/
+ ulint space, /*!< in: space where removed */
+ ulint zip_size,/*!< in: compressed page size in bytes
+ or 0 for uncompressed pages */
+ page_t* page, /*!< in/out: page to remove */
+#ifdef UNIV_SYNC_DEBUG
+ const dict_index_t* index, /*!< in: index tree */
+#endif /* UNIV_SYNC_DEBUG */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint prev_page_no;
ulint next_page_no;
@@ -2859,7 +2929,7 @@ btr_level_list_remove(
if (prev_page_no != FIL_NULL) {
buf_block_t* prev_block
= btr_block_get(space, zip_size, prev_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
page_t* prev_page
= buf_block_get_frame(prev_block);
#ifdef UNIV_BTR_DEBUG
@@ -2876,7 +2946,7 @@ btr_level_list_remove(
if (next_page_no != FIL_NULL) {
buf_block_t* next_block
= btr_block_get(space, zip_size, next_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
page_t* next_page
= buf_block_get_frame(next_block);
#ifdef UNIV_BTR_DEBUG
@@ -3202,7 +3272,7 @@ btr_compress(
if (is_left) {
merge_block = btr_block_get(space, zip_size, left_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_next(merge_page, mtr)
@@ -3211,7 +3281,7 @@ btr_compress(
} else if (right_page_no != FIL_NULL) {
merge_block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_prev(merge_page, mtr)
@@ -3300,7 +3370,7 @@ err_exit:
btr_search_drop_page_hash_index(block);
/* Remove the page from the level list */
- btr_level_list_remove(space, zip_size, page, mtr);
+ btr_level_list_remove(space, zip_size, page, index, mtr);
btr_node_ptr_delete(index, block, mtr);
lock_update_merge_left(merge_block, orig_pred, block);
@@ -3357,7 +3427,7 @@ err_exit:
#endif /* UNIV_BTR_DEBUG */
/* Remove the page from the level list */
- btr_level_list_remove(space, zip_size, page, mtr);
+ btr_level_list_remove(space, zip_size, page, index, mtr);
/* Replace the address of the old child node (= page) with the
address of the merge page to the right */
@@ -3549,7 +3619,7 @@ btr_discard_page(
if (left_page_no != FIL_NULL) {
merge_block = btr_block_get(space, zip_size, left_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_next(merge_page, mtr)
@@ -3557,7 +3627,7 @@ btr_discard_page(
#endif /* UNIV_BTR_DEBUG */
} else if (right_page_no != FIL_NULL) {
merge_block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, mtr);
+ RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_prev(merge_page, mtr)
@@ -3592,7 +3662,7 @@ btr_discard_page(
btr_node_ptr_delete(index, block, mtr);
/* Remove the page from the level list */
- btr_level_list_remove(space, zip_size, page, mtr);
+ btr_level_list_remove(space, zip_size, page, index, mtr);
#ifdef UNIV_ZIP_DEBUG
{
page_zip_des_t* merge_page_zip
@@ -4110,7 +4180,7 @@ loop:
if (right_page_no != FIL_NULL) {
const rec_t* right_rec;
right_block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, &mtr);
+ RW_X_LATCH, index, &mtr);
right_page = buf_block_get_frame(right_block);
if (UNIV_UNLIKELY(btr_page_get_prev(right_page, &mtr)
!= page_get_page_no(page))) {
@@ -4336,7 +4406,7 @@ node_ptr_fails:
mtr_start(&mtr);
block = btr_block_get(space, zip_size, right_page_no,
- RW_X_LATCH, &mtr);
+ RW_X_LATCH, index, &mtr);
page = buf_block_get_frame(block);
goto loop;
diff --git a/storage/xtradb/btr/btr0cur.c b/storage/xtradb/btr/btr0cur.c
index 51a2f784fbf..4161be93a90 100644
--- a/storage/xtradb/btr/btr0cur.c
+++ b/storage/xtradb/btr/btr0cur.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -18,8 +18,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -238,7 +238,9 @@ btr_cur_latch_leaves(
case BTR_SEARCH_LEAF:
case BTR_MODIFY_LEAF:
mode = latch_mode == BTR_SEARCH_LEAF ? RW_S_LATCH : RW_X_LATCH;
- get_block = btr_block_get(space, zip_size, page_no, mode, mtr);
+
+ get_block = btr_block_get(
+ space, zip_size, page_no, mode, cursor->index, mtr);
if (srv_pass_corrupt_table && !get_block) {
return;
@@ -254,9 +256,9 @@ btr_cur_latch_leaves(
left_page_no = btr_page_get_prev(page, mtr);
if (left_page_no != FIL_NULL) {
- get_block = btr_block_get(space, zip_size,
- left_page_no,
- RW_X_LATCH, mtr);
+ get_block = btr_block_get(
+ space, zip_size, left_page_no,
+ RW_X_LATCH, cursor->index, mtr);
if (srv_pass_corrupt_table && !get_block) {
return;
@@ -271,8 +273,9 @@ btr_cur_latch_leaves(
get_block->check_index_page_at_flush = TRUE;
}
- get_block = btr_block_get(space, zip_size, page_no,
- RW_X_LATCH, mtr);
+ get_block = btr_block_get(
+ space, zip_size, page_no,
+ RW_X_LATCH, cursor->index, mtr);
if (srv_pass_corrupt_table && !get_block) {
return;
@@ -286,9 +289,9 @@ btr_cur_latch_leaves(
right_page_no = btr_page_get_next(page, mtr);
if (right_page_no != FIL_NULL) {
- get_block = btr_block_get(space, zip_size,
- right_page_no,
- RW_X_LATCH, mtr);
+ get_block = btr_block_get(
+ space, zip_size, right_page_no,
+ RW_X_LATCH, cursor->index, mtr);
if (srv_pass_corrupt_table && !get_block) {
return;
@@ -312,8 +315,9 @@ btr_cur_latch_leaves(
left_page_no = btr_page_get_prev(page, mtr);
if (left_page_no != FIL_NULL) {
- get_block = btr_block_get(space, zip_size,
- left_page_no, mode, mtr);
+ get_block = btr_block_get(
+ space, zip_size,
+ left_page_no, mode, cursor->index, mtr);
cursor->left_block = get_block;
if (srv_pass_corrupt_table && !get_block) {
@@ -329,7 +333,8 @@ btr_cur_latch_leaves(
get_block->check_index_page_at_flush = TRUE;
}
- get_block = btr_block_get(space, zip_size, page_no, mode, mtr);
+ get_block = btr_block_get(
+ space, zip_size, page_no, mode, cursor->index, mtr);
if (srv_pass_corrupt_table && !get_block) {
return;
@@ -419,7 +424,12 @@ btr_cur_search_to_nth_level(
ut_ad(dict_index_check_search_tuple(index, tuple));
ut_ad(!dict_index_is_ibuf(index) || ibuf_inside());
ut_ad(dtuple_check_typed(tuple));
+ ut_ad(index->page != FIL_NULL);
+ UNIV_MEM_INVALID(&cursor->up_match, sizeof cursor->up_match);
+ UNIV_MEM_INVALID(&cursor->up_bytes, sizeof cursor->up_bytes);
+ UNIV_MEM_INVALID(&cursor->low_match, sizeof cursor->low_match);
+ UNIV_MEM_INVALID(&cursor->low_bytes, sizeof cursor->low_bytes);
#ifdef UNIV_DEBUG
cursor->up_match = ULINT_UNDEFINED;
cursor->low_match = ULINT_UNDEFINED;
@@ -622,7 +632,9 @@ retry_page_get:
ut_a(!page_zip || page_zip_validate(page_zip, page));
#endif /* UNIV_ZIP_DEBUG */
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(
+ block, dict_index_is_ibuf(index)
+ ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
}
ut_ad(0 == ut_dulint_cmp(index->id,
@@ -680,8 +692,8 @@ retry_page_get:
if (level > 0) {
/* x-latch the page */
- page = btr_page_get(space, zip_size,
- page_no, RW_X_LATCH, mtr);
+ page = btr_page_get(space, zip_size, page_no,
+ RW_X_LATCH, index, mtr);
ut_a((ibool)!!page_is_comp(page)
== dict_table_is_comp(index->table));
}
@@ -1822,6 +1834,7 @@ btr_cur_update_in_place(
roll_ptr_t roll_ptr = ut_dulint_zero;
trx_t* trx;
ulint was_delete_marked;
+ ibool is_hashed;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
@@ -1846,7 +1859,7 @@ btr_cur_update_in_place(
page_zip = buf_block_get_page_zip(block);
/* Check that enough space is available on the compressed page. */
- if (UNIV_LIKELY_NULL(page_zip)
+ if (page_zip
&& !btr_cur_update_alloc_zip(page_zip, block, index,
rec_offs_size(offsets), FALSE, mtr)) {
return(DB_ZIP_OVERFLOW);
@@ -1871,7 +1884,21 @@ btr_cur_update_in_place(
return(err); /* == DB_SUCCESS */
}
- if (block->is_hashed) {
+ if (!(flags & BTR_KEEP_SYS_FLAG)) {
+ row_upd_rec_sys_fields(rec, NULL,
+ index, offsets, trx, roll_ptr);
+ }
+
+ was_delete_marked = rec_get_deleted_flag(
+ rec, page_is_comp(buf_block_get_frame(block)));
+
+ is_hashed = (block->index != NULL);
+
+ if (is_hashed) {
+ /* TO DO: Can we skip this if none of the fields
+ index->search_info->curr_n_fields
+ are being updated? */
+
/* The function row_upd_changes_ord_field_binary works only
if the update vector was built for a clustered index, we must
NOT call it if index is secondary */
@@ -1887,17 +1914,9 @@ btr_cur_update_in_place(
rw_lock_x_lock(&btr_search_latch);
}
- if (!(flags & BTR_KEEP_SYS_FLAG)) {
- row_upd_rec_sys_fields(rec, NULL,
- index, offsets, trx, roll_ptr);
- }
-
- was_delete_marked = rec_get_deleted_flag(
- rec, page_is_comp(buf_block_get_frame(block)));
-
row_upd_rec_in_place(rec, index, offsets, update, page_zip);
- if (block->is_hashed) {
+ if (is_hashed) {
rw_lock_x_unlock(&btr_search_latch);
}
@@ -2039,7 +2058,7 @@ any_extern:
ut_a(!page_zip || page_zip_validate(page_zip, page));
#endif /* UNIV_ZIP_DEBUG */
- if (UNIV_LIKELY_NULL(page_zip)
+ if (page_zip
&& !btr_cur_update_alloc_zip(page_zip, block, index,
new_rec_size, TRUE, mtr)) {
err = DB_ZIP_OVERFLOW;
@@ -2347,7 +2366,7 @@ btr_cur_pessimistic_update(
ut_ad(rec_offs_validate(rec, index, offsets));
n_ext += btr_push_update_extern_fields(new_entry, update, *heap);
- if (UNIV_LIKELY_NULL(page_zip)) {
+ if (page_zip) {
ut_ad(page_is_comp(page));
if (page_zip_rec_needs_ext(
rec_get_converted_size(index, new_entry, n_ext),
@@ -2531,39 +2550,6 @@ return_after_reservations:
return(err);
}
-/**************************************************************//**
-Commits and restarts a mini-transaction so that it will retain an
-x-lock on index->lock and the cursor page. */
-UNIV_INTERN
-void
-btr_cur_mtr_commit_and_start(
-/*=========================*/
- btr_cur_t* cursor, /*!< in: cursor */
- mtr_t* mtr) /*!< in/out: mini-transaction */
-{
- buf_block_t* block;
-
- block = btr_cur_get_block(cursor);
-
- ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(cursor->index),
- MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
- /* Keep the locks across the mtr_commit(mtr). */
- rw_lock_x_lock(dict_index_get_lock(cursor->index));
- rw_lock_x_lock(&block->lock);
- mutex_enter(&block->mutex);
- buf_block_buf_fix_inc(block, __FILE__, __LINE__);
- mutex_exit(&block->mutex);
- /* Write out the redo log. */
- mtr_commit(mtr);
- mtr_start(mtr);
- /* Reassociate the locks with the mini-transaction.
- They will be released on mtr_commit(mtr). */
- mtr_memo_push(mtr, dict_index_get_lock(cursor->index),
- MTR_MEMO_X_LOCK);
- mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX);
-}
-
/*==================== B-TREE DELETE MARK AND UNMARK ===============*/
/****************************************************************//**
@@ -2670,7 +2656,8 @@ btr_cur_parse_del_mark_set_clust_rec(
/* We do not need to reserve btr_search_latch, as the page
is only being recovered, and there cannot be a hash index to
- it. */
+ it. Besides, these fields are being updated in place
+ and the adaptive hash index does not depend on them. */
btr_rec_set_deleted_flag(rec, page_zip, val);
@@ -2755,9 +2742,9 @@ btr_cur_del_mark_set_clust_rec(
return(err);
}
- if (block->is_hashed) {
- rw_lock_x_lock(&btr_search_latch);
- }
+ /* The btr_search_latch is not needed here, because
+ the adaptive hash index does not depend on the delete-mark
+ and the delete-mark is being updated in place. */
page_zip = buf_block_get_page_zip(block);
@@ -2771,10 +2758,6 @@ btr_cur_del_mark_set_clust_rec(
index, offsets, trx, roll_ptr);
}
- if (block->is_hashed) {
- rw_lock_x_unlock(&btr_search_latch);
- }
-
btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx,
roll_ptr, mtr);
@@ -2850,7 +2833,8 @@ btr_cur_parse_del_mark_set_sec_rec(
/* We do not need to reserve btr_search_latch, as the page
is only being recovered, and there cannot be a hash index to
- it. */
+ it. Besides, the delete-mark flag is being updated in place
+ and the adaptive hash index does not depend on it. */
btr_rec_set_deleted_flag(rec, page_zip, val);
}
@@ -2903,16 +2887,11 @@ btr_cur_del_mark_set_sec_rec(
ut_ad(!!page_rec_is_comp(rec)
== dict_table_is_comp(cursor->index->table));
- if (block->is_hashed) {
- rw_lock_x_lock(&btr_search_latch);
- }
-
+ /* We do not need to reserve btr_search_latch, as the
+ delete-mark flag is being updated in place and the adaptive
+ hash index does not depend on it. */
btr_rec_set_deleted_flag(rec, buf_block_get_page_zip(block), val);
- if (block->is_hashed) {
- rw_lock_x_unlock(&btr_search_latch);
- }
-
btr_cur_del_mark_set_sec_rec_log(rec, val, mtr);
return(DB_SUCCESS);
@@ -2932,8 +2911,11 @@ btr_cur_del_unmark_for_ibuf(
uncompressed */
mtr_t* mtr) /*!< in: mtr */
{
- /* We do not need to reserve btr_search_latch, as the page has just
- been read to the buffer pool and there cannot be a hash index to it. */
+ /* We do not need to reserve btr_search_latch, as the page
+ has just been read to the buffer pool and there cannot be
+ a hash index to it. Besides, the delete-mark flag is being
+ updated in place and the adaptive hash index does not depend
+ on it. */
btr_rec_set_deleted_flag(rec, page_zip, FALSE);
@@ -3581,7 +3563,6 @@ static
void
btr_record_not_null_field_in_rec(
/*=============================*/
- rec_t* rec __attribute__ ((unused)),/*!< in: physical record */
ulint n_unique, /*!< in: dict_index_get_n_unique(index),
number of columns uniquely determine
an index entry */
@@ -3600,16 +3581,11 @@ btr_record_not_null_field_in_rec(
}
for (i = 0; i < n_unique; i++) {
- ulint rec_len;
-
- rec_get_nth_field_offs(offsets, i, &rec_len);
-
- if (rec_len != UNIV_SQL_NULL) {
- n_not_null[i]++;
- } else {
+ if (rec_offs_nth_sql_null(offsets, i)) {
/* Break if we hit the first NULL value */
break;
}
+ n_not_null[i]++;
}
}
@@ -3722,7 +3698,7 @@ btr_estimate_number_of_different_key_vals(
if (n_not_null) {
btr_record_not_null_field_in_rec(
- rec, n_cols, offsets_rec, n_not_null);
+ n_cols, offsets_rec, n_not_null);
}
}
@@ -3757,8 +3733,7 @@ btr_estimate_number_of_different_key_vals(
if (n_not_null) {
btr_record_not_null_field_in_rec(
- next_rec, n_cols, offsets_next_rec,
- n_not_null);
+ n_cols, offsets_next_rec, n_not_null);
}
total_external_size
@@ -3949,10 +3924,10 @@ btr_cur_set_ownership_of_extern_field(
byte_val = byte_val | BTR_EXTERN_OWNER_FLAG;
}
- if (UNIV_LIKELY_NULL(page_zip)) {
+ if (page_zip) {
mach_write_to_1(data + local_len + BTR_EXTERN_LEN, byte_val);
page_zip_write_blob_ptr(page_zip, rec, index, offsets, i, mtr);
- } else if (UNIV_LIKELY(mtr != NULL)) {
+ } else if (mtr != NULL) {
mlog_write_ulint(data + local_len + BTR_EXTERN_LEN, byte_val,
MLOG_1BYTE, mtr);
@@ -4190,9 +4165,9 @@ The fields are stored on pages allocated from leaf node
file segment of the index tree.
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN
-ulint
-btr_store_big_rec_extern_fields_func(
-/*=================================*/
+enum db_err
+btr_store_big_rec_extern_fields(
+/*============================*/
dict_index_t* index, /*!< in: index of rec; the index tree
MUST be X-latched */
buf_block_t* rec_block, /*!< in/out: block containing rec */
@@ -4201,38 +4176,37 @@ btr_store_big_rec_extern_fields_func(
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
-#ifdef UNIV_DEBUG
- mtr_t* local_mtr, /*!< in: mtr containing the
- latch to rec and to the tree */
-#endif /* UNIV_DEBUG */
-#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
- ibool update_in_place,/*! in: TRUE if the record is updated
- in place (not delete+insert) */
-#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
- const big_rec_t*big_rec_vec) /*!< in: vector containing fields
+ const big_rec_t*big_rec_vec, /*!< in: vector containing fields
to be stored externally */
-
+ mtr_t* btr_mtr, /*!< in: mtr containing the
+ latches to the clustered index */
+ enum blob_op op) /*! in: operation code */
{
- ulint rec_page_no;
- byte* field_ref;
- ulint extern_len;
- ulint store_len;
- ulint page_no;
- ulint space_id;
- ulint zip_size;
- ulint prev_page_no;
- ulint hint_page_no;
- ulint i;
- mtr_t mtr;
- mem_heap_t* heap = NULL;
+ ulint rec_page_no;
+ byte* field_ref;
+ ulint extern_len;
+ ulint store_len;
+ ulint page_no;
+ ulint space_id;
+ ulint zip_size;
+ ulint prev_page_no;
+ ulint hint_page_no;
+ ulint i;
+ mtr_t mtr;
+ mtr_t* alloc_mtr;
+ mem_heap_t* heap = NULL;
page_zip_des_t* page_zip;
- z_stream c_stream;
+ z_stream c_stream;
+ buf_block_t** freed_pages = NULL;
+ ulint n_freed_pages = 0;
+ enum db_err error = DB_SUCCESS;
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(rec_offs_any_extern(offsets));
- ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index),
+ ut_ad(btr_mtr);
+ ut_ad(mtr_memo_contains(btr_mtr, dict_index_get_lock(index),
MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains(local_mtr, rec_block, MTR_MEMO_PAGE_X_FIX));
+ ut_ad(mtr_memo_contains(btr_mtr, rec_block, MTR_MEMO_PAGE_X_FIX));
ut_ad(buf_block_get_frame(rec_block) == page_align(rec));
ut_a(dict_index_is_clust(index));
@@ -4245,7 +4219,7 @@ btr_store_big_rec_extern_fields_func(
rec_page_no = buf_block_get_page_no(rec_block);
ut_a(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX);
- if (UNIV_LIKELY_NULL(page_zip)) {
+ if (page_zip) {
int err;
/* Zlib deflate needs 128 kilobytes for the default
@@ -4261,6 +4235,42 @@ btr_store_big_rec_extern_fields_func(
ut_a(err == Z_OK);
}
+ if (btr_blob_op_is_update(op)) {
+ /* Avoid reusing pages that have been previously freed
+ in btr_mtr. */
+ if (btr_mtr->n_freed_pages) {
+ if (heap == NULL) {
+ heap = mem_heap_create(
+ btr_mtr->n_freed_pages
+ * sizeof *freed_pages);
+ }
+
+ freed_pages = mem_heap_alloc(
+ heap,
+ btr_mtr->n_freed_pages
+ * sizeof *freed_pages);
+ n_freed_pages = 0;
+ }
+
+ /* Because btr_mtr will be committed after mtr, it is
+ possible that the tablespace has been extended when
+ the B-tree record was updated or inserted, or it will
+ be extended while allocating pages for big_rec.
+
+ TODO: In mtr (not btr_mtr), write a redo log record
+ about extending the tablespace to its current size,
+ and remember the current size. Whenever the tablespace
+ grows as pages are allocated, write further redo log
+ records to mtr. (Currently tablespace extension is not
+ covered by the redo log. If it were, the record would
+ only be written to btr_mtr, which is committed after
+ mtr.) */
+ alloc_mtr = btr_mtr;
+ } else {
+ /* Use the local mtr for allocations. */
+ alloc_mtr = &mtr;
+ }
+
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
/* All pointers to externally stored columns in the record
must either be zero or they must be pointers to inherited
@@ -4275,7 +4285,7 @@ btr_store_big_rec_extern_fields_func(
/* Either this must be an update in place,
or the BLOB must be inherited, or the BLOB pointer
must be zero (will be written in this function). */
- ut_a(update_in_place
+ ut_a(op == BTR_STORE_UPDATE
|| (field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_INHERITED_FLAG)
|| !memcmp(field_ref, field_ref_zero,
BTR_EXTERN_FIELD_REF_SIZE));
@@ -4300,7 +4310,7 @@ btr_store_big_rec_extern_fields_func(
prev_page_no = FIL_NULL;
- if (UNIV_LIKELY_NULL(page_zip)) {
+ if (page_zip) {
int err = deflateReset(&c_stream);
ut_a(err == Z_OK);
@@ -4320,18 +4330,24 @@ btr_store_big_rec_extern_fields_func(
hint_page_no = prev_page_no + 1;
}
+alloc_another:
block = btr_page_alloc(index, hint_page_no,
- FSP_NO_DIR, 0, &mtr);
+ FSP_NO_DIR, 0, alloc_mtr, &mtr);
if (UNIV_UNLIKELY(block == NULL)) {
-
mtr_commit(&mtr);
+ error = DB_OUT_OF_FILE_SPACE;
+ goto func_exit;
+ }
- if (UNIV_LIKELY_NULL(page_zip)) {
- deflateEnd(&c_stream);
- mem_heap_free(heap);
- }
-
- return(DB_OUT_OF_FILE_SPACE);
+ if (rw_lock_get_x_lock_count(&block->lock) > 1) {
+ /* This page must have been freed in
+ btr_mtr previously. Put it aside, and
+ allocate another page for the BLOB data. */
+ ut_ad(alloc_mtr == btr_mtr);
+ ut_ad(btr_blob_op_is_update(op));
+ ut_ad(n_freed_pages < btr_mtr->n_freed_pages);
+ freed_pages[n_freed_pages++] = block;
+ goto alloc_another;
}
page_no = buf_block_get_page_no(block);
@@ -4348,7 +4364,7 @@ btr_store_big_rec_extern_fields_func(
SYNC_EXTERN_STORAGE);
prev_page = buf_block_get_frame(prev_block);
- if (UNIV_LIKELY_NULL(page_zip)) {
+ if (page_zip) {
mlog_write_ulint(
prev_page + FIL_PAGE_NEXT,
page_no, MLOG_4BYTES, &mtr);
@@ -4365,7 +4381,7 @@ btr_store_big_rec_extern_fields_func(
}
- if (UNIV_LIKELY_NULL(page_zip)) {
+ if (page_zip) {
int err;
page_zip_des_t* blob_page_zip;
@@ -4448,11 +4464,15 @@ btr_store_big_rec_extern_fields_func(
goto next_zip_page;
}
- rec_block = buf_page_get(space_id, zip_size,
- rec_page_no,
- RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(rec_block,
- SYNC_NO_ORDER_CHECK);
+ if (alloc_mtr == &mtr) {
+ rec_block = buf_page_get(
+ space_id, zip_size,
+ rec_page_no,
+ RW_X_LATCH, &mtr);
+ buf_block_dbg_add_level(
+ rec_block,
+ SYNC_NO_ORDER_CHECK);
+ }
if (err == Z_STREAM_END) {
mach_write_to_4(field_ref
@@ -4486,7 +4506,8 @@ btr_store_big_rec_extern_fields_func(
page_zip_write_blob_ptr(
page_zip, rec, index, offsets,
- big_rec_vec->fields[i].field_no, &mtr);
+ big_rec_vec->fields[i].field_no,
+ alloc_mtr);
next_zip_page:
prev_page_no = page_no;
@@ -4531,19 +4552,23 @@ next_zip_page:
extern_len -= store_len;
- rec_block = buf_page_get(space_id, zip_size,
- rec_page_no,
- RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(rec_block,
- SYNC_NO_ORDER_CHECK);
+ if (alloc_mtr == &mtr) {
+ rec_block = buf_page_get(
+ space_id, zip_size,
+ rec_page_no,
+ RW_X_LATCH, &mtr);
+ buf_block_dbg_add_level(
+ rec_block,
+ SYNC_NO_ORDER_CHECK);
+ }
mlog_write_ulint(field_ref + BTR_EXTERN_LEN, 0,
- MLOG_4BYTES, &mtr);
+ MLOG_4BYTES, alloc_mtr);
mlog_write_ulint(field_ref
+ BTR_EXTERN_LEN + 4,
big_rec_vec->fields[i].len
- extern_len,
- MLOG_4BYTES, &mtr);
+ MLOG_4BYTES, alloc_mtr);
if (prev_page_no == FIL_NULL) {
btr_blob_dbg_add_blob(
@@ -4553,18 +4578,19 @@ next_zip_page:
mlog_write_ulint(field_ref
+ BTR_EXTERN_SPACE_ID,
- space_id,
- MLOG_4BYTES, &mtr);
+ space_id, MLOG_4BYTES,
+ alloc_mtr);
mlog_write_ulint(field_ref
+ BTR_EXTERN_PAGE_NO,
- page_no,
- MLOG_4BYTES, &mtr);
+ page_no, MLOG_4BYTES,
+ alloc_mtr);
mlog_write_ulint(field_ref
+ BTR_EXTERN_OFFSET,
FIL_PAGE_DATA,
- MLOG_4BYTES, &mtr);
+ MLOG_4BYTES,
+ alloc_mtr);
}
prev_page_no = page_no;
@@ -4578,8 +4604,23 @@ next_zip_page:
}
}
- if (UNIV_LIKELY_NULL(page_zip)) {
+func_exit:
+ if (page_zip) {
deflateEnd(&c_stream);
+ }
+
+ if (n_freed_pages) {
+ ulint i;
+
+ ut_ad(alloc_mtr == btr_mtr);
+ ut_ad(btr_blob_op_is_update(op));
+
+ for (i = 0; i < n_freed_pages; i++) {
+ btr_page_free_low(index, freed_pages[i], 0, alloc_mtr);
+ }
+ }
+
+ if (heap != NULL) {
mem_heap_free(heap);
}
@@ -4600,7 +4641,7 @@ next_zip_page:
ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
}
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
- return(DB_SUCCESS);
+ return(error);
}
/*******************************************************************//**
@@ -4805,7 +4846,7 @@ btr_free_externally_stored_field(
btr_page_free_low(index, ext_block, 0, &mtr);
- if (UNIV_LIKELY(page_zip != NULL)) {
+ if (page_zip) {
mach_write_to_4(field_ref + BTR_EXTERN_PAGE_NO,
next_page_no);
mach_write_to_4(field_ref + BTR_EXTERN_LEN + 4,
diff --git a/storage/xtradb/btr/btr0pcur.c b/storage/xtradb/btr/btr0pcur.c
index 97fe06f0f5e..be1a6cbd8ee 100644
--- a/storage/xtradb/btr/btr0pcur.c
+++ b/storage/xtradb/btr/btr0pcur.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -127,6 +127,8 @@ btr_pcur_store_position(
ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
ut_a(btr_page_get_prev(page, mtr) == FIL_NULL);
+ ut_ad(page_is_leaf(page));
+ ut_ad(page_get_page_no(page) == index->page);
cursor->old_stored = BTR_PCUR_OLD_STORED;
@@ -253,6 +255,8 @@ btr_pcur_restore_position_func(
cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
index, latch_mode, btr_pcur_get_btr_cur(cursor), mtr);
+ cursor->latch_mode = latch_mode;
+ cursor->pos_state = BTR_PCUR_IS_POSITIONED;
cursor->block_when_stored = btr_pcur_get_block(cursor);
return(FALSE);
@@ -272,8 +276,10 @@ btr_pcur_restore_position_func(
file, line, mtr))) {
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
- buf_block_dbg_add_level(btr_pcur_get_block(cursor),
- SYNC_TREE_NODE);
+ buf_block_dbg_add_level(
+ btr_pcur_get_block(cursor),
+ dict_index_is_ibuf(index)
+ ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
if (cursor->rel_pos == BTR_PCUR_ON) {
#ifdef UNIV_DEBUG
@@ -315,13 +321,19 @@ btr_pcur_restore_position_func(
/* Save the old search mode of the cursor */
old_mode = cursor->search_mode;
- if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) {
+ switch (cursor->rel_pos) {
+ case BTR_PCUR_ON:
mode = PAGE_CUR_LE;
- } else if (cursor->rel_pos == BTR_PCUR_AFTER) {
+ break;
+ case BTR_PCUR_AFTER:
mode = PAGE_CUR_G;
- } else {
- ut_ad(cursor->rel_pos == BTR_PCUR_BEFORE);
+ break;
+ case BTR_PCUR_BEFORE:
mode = PAGE_CUR_L;
+ break;
+ default:
+ ut_error;
+ mode = 0;
}
btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode,
@@ -330,25 +342,44 @@ btr_pcur_restore_position_func(
/* Restore the old search mode */
cursor->search_mode = old_mode;
- if (cursor->rel_pos == BTR_PCUR_ON
- && btr_pcur_is_on_user_rec(cursor)
- && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor),
- rec_get_offsets(
- btr_pcur_get_rec(cursor), index,
- NULL, ULINT_UNDEFINED, &heap))) {
-
- /* We have to store the NEW value for the modify clock, since
- the cursor can now be on a different page! But we can retain
- the value of old_rec */
+ if (btr_pcur_is_on_user_rec(cursor)) {
+ switch (cursor->rel_pos) {
+ case BTR_PCUR_ON:
+ if (!cmp_dtuple_rec(
+ tuple, btr_pcur_get_rec(cursor),
+ rec_get_offsets(btr_pcur_get_rec(cursor),
+ index, NULL,
+ ULINT_UNDEFINED, &heap))) {
+
+ /* We have to store the NEW value for
+ the modify clock, since the cursor can
+ now be on a different page! But we can
+ retain the value of old_rec */
+
+ cursor->block_when_stored =
+ btr_pcur_get_block(cursor);
+ cursor->modify_clock =
+ buf_block_get_modify_clock(
+ cursor->block_when_stored);
+ cursor->old_stored = BTR_PCUR_OLD_STORED;
- cursor->block_when_stored = btr_pcur_get_block(cursor);
- cursor->modify_clock = buf_block_get_modify_clock(
- cursor->block_when_stored);
- cursor->old_stored = BTR_PCUR_OLD_STORED;
+ mem_heap_free(heap);
- mem_heap_free(heap);
+ return(TRUE);
+ }
- return(TRUE);
+ break;
+ case BTR_PCUR_BEFORE:
+ page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
+ break;
+ case BTR_PCUR_AFTER:
+ page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
+ break;
+#ifdef UNIV_DEBUG
+ default:
+ ut_error;
+#endif /* UNIV_DEBUG */
+ }
}
mem_heap_free(heap);
@@ -396,7 +427,8 @@ btr_pcur_move_to_next_page(
ut_ad(next_page_no != FIL_NULL);
next_block = btr_block_get(space, zip_size, next_page_no,
- cursor->latch_mode, mtr);
+ cursor->latch_mode,
+ btr_pcur_get_btr_cur(cursor)->index, mtr);
next_page = buf_block_get_frame(next_block);
if (srv_pass_corrupt_table && !next_page) {
diff --git a/storage/xtradb/btr/btr0sea.c b/storage/xtradb/btr/btr0sea.c
index 6e6c533f4af..3d710b653c0 100644
--- a/storage/xtradb/btr/btr0sea.c
+++ b/storage/xtradb/btr/btr0sea.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -44,12 +44,8 @@ Created 2/17/1996 Heikki Tuuri
#include "ha0ha.h"
#include "srv0srv.h"
/** Flag: has the search system been enabled?
-Protected by btr_search_latch and btr_search_enabled_mutex. */
+Protected by btr_search_latch. */
UNIV_INTERN char btr_search_enabled = TRUE;
-UNIV_INTERN ibool btr_search_fully_disabled = FALSE;
-
-/** Mutex protecting btr_search_enabled */
-static mutex_t btr_search_enabled_mutex;
/** A dummy variable to fool the compiler */
UNIV_INTERN ulint btr_search_this_is_zero = 0;
@@ -169,7 +165,6 @@ btr_search_sys_create(
btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
rw_lock_create(&btr_search_latch, SYNC_SEARCH_SYS);
- mutex_create(&btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF);
btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
@@ -199,27 +194,37 @@ void
btr_search_disable(void)
/*====================*/
{
- mutex_enter(&btr_search_enabled_mutex);
+ dict_table_t* table;
+
+ mutex_enter(&dict_sys->mutex);
rw_lock_x_lock(&btr_search_latch);
- /* Disable access to hash index, also tell ha_insert_for_fold()
- stop adding new nodes to hash index, but still allow updating
- existing nodes */
btr_search_enabled = FALSE;
- /* Clear all block->is_hashed flags and remove all entries
- from btr_search_sys->hash_index. */
- buf_pool_drop_hash_index();
+ /* Clear the index->search_info->ref_count of every index in
+ the data dictionary cache. */
+ for (table = UT_LIST_GET_FIRST(dict_sys->table_LRU); table;
+ table = UT_LIST_GET_NEXT(table_LRU, table)) {
+
+ dict_index_t* index;
- /* hash index has been cleaned up, disallow any operation to
- the hash index */
- btr_search_fully_disabled = TRUE;
+ for (index = dict_table_get_first_index(table); index;
+ index = dict_table_get_next_index(index)) {
+
+ index->search_info->ref_count = 0;
+ }
+ }
- /* btr_search_enabled_mutex should guarantee this. */
- ut_ad(!btr_search_enabled);
+ mutex_exit(&dict_sys->mutex);
+
+ /* Set all block->index = NULL. */
+ buf_pool_clear_hash_index();
+
+ /* Clear the adaptive hash index. */
+ hash_table_clear(btr_search_sys->hash_index);
+ mem_heap_empty(btr_search_sys->hash_index->heap);
rw_lock_x_unlock(&btr_search_latch);
- mutex_exit(&btr_search_enabled_mutex);
}
/********************************************************************//**
@@ -229,14 +234,11 @@ void
btr_search_enable(void)
/*====================*/
{
- mutex_enter(&btr_search_enabled_mutex);
rw_lock_x_lock(&btr_search_latch);
btr_search_enabled = TRUE;
- btr_search_fully_disabled = FALSE;
rw_lock_x_unlock(&btr_search_latch);
- mutex_exit(&btr_search_enabled_mutex);
}
/*****************************************************************//**
@@ -459,7 +461,7 @@ btr_search_update_block_hash_info(
&& (block->n_bytes == info->n_bytes)
&& (block->left_side == info->left_side)) {
- if ((block->is_hashed)
+ if ((block->index)
&& (block->curr_n_fields == info->n_fields)
&& (block->curr_n_bytes == info->n_bytes)
&& (block->curr_left_side == info->left_side)) {
@@ -488,7 +490,7 @@ btr_search_update_block_hash_info(
/ BTR_SEARCH_PAGE_BUILD_LIMIT)
&& (info->n_hash_potential >= BTR_SEARCH_BUILD_LIMIT)) {
- if ((!block->is_hashed)
+ if ((!block->index)
|| (block->n_hash_helps
> 2 * page_get_n_recs(block->frame))
|| (block->n_fields != block->curr_n_fields)
@@ -520,9 +522,9 @@ btr_search_update_hash_ref(
buf_block_t* block, /*!< in: buffer block where cursor positioned */
btr_cur_t* cursor) /*!< in: cursor */
{
- ulint fold;
- rec_t* rec;
- dulint index_id;
+ dict_index_t* index;
+ ulint fold;
+ const rec_t* rec;
ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
#ifdef UNIV_SYNC_DEBUG
@@ -533,13 +535,15 @@ btr_search_update_hash_ref(
ut_ad(page_align(btr_cur_get_rec(cursor))
== buf_block_get_frame(block));
- if (!block->is_hashed) {
+ index = block->index;
+
+ if (!index) {
return;
}
- ut_a(block->index == cursor->index);
- ut_a(!dict_index_is_ibuf(cursor->index));
+ ut_a(index == cursor->index);
+ ut_a(!dict_index_is_ibuf(index));
if ((info->n_hash_potential > 0)
&& (block->curr_n_fields == info->n_fields)
@@ -556,12 +560,11 @@ btr_search_update_hash_ref(
return;
}
- index_id = cursor->index->id;
fold = rec_fold(rec,
- rec_get_offsets(rec, cursor->index, offsets_,
+ rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
block->curr_n_fields,
- block->curr_n_bytes, index_id);
+ block->curr_n_bytes, index->id);
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -829,7 +832,7 @@ btr_search_guess_on_hash(
mtr_t* mtr) /*!< in: mtr */
{
buf_block_t* block;
- rec_t* rec;
+ const rec_t* rec;
ulint fold;
dulint index_id;
#ifdef notdefined
@@ -837,6 +840,7 @@ btr_search_guess_on_hash(
btr_pcur_t pcur;
#endif
ut_ad(index && info && tuple && cursor && mtr);
+ ut_ad(!dict_index_is_ibuf(index));
ut_ad((latch_mode == BTR_SEARCH_LEAF)
|| (latch_mode == BTR_MODIFY_LEAF));
@@ -914,7 +918,7 @@ btr_search_guess_on_hash(
ut_ad(page_rec_is_user_rec(rec));
- btr_cur_position(index, rec, block, cursor);
+ btr_cur_position(index, (rec_t*) rec, block, cursor);
/* Check the validity of the guess within the page */
@@ -1045,15 +1049,16 @@ btr_search_drop_page_hash_index(
retry:
rw_lock_s_lock(&btr_search_latch);
- page = block->frame;
+ index = block->index;
- if (UNIV_LIKELY(!block->is_hashed)) {
+ if (UNIV_LIKELY(!index)) {
rw_lock_s_unlock(&btr_search_latch);
return;
}
+ ut_a(!dict_index_is_ibuf(index));
table = btr_search_sys->hash_index;
#ifdef UNIV_SYNC_DEBUG
@@ -1064,8 +1069,6 @@ retry:
n_fields = block->curr_n_fields;
n_bytes = block->curr_n_bytes;
- index = block->index;
- ut_a(!dict_index_is_ibuf(index));
/* NOTE: The fields of block must not be accessed after
releasing btr_search_latch, as the index page might only
@@ -1075,6 +1078,7 @@ retry:
ut_a(n_fields + n_bytes > 0);
+ page = block->frame;
n_recs = page_get_n_recs(page);
/* Calculate and cache fold values into an array for fast deletion
@@ -1123,7 +1127,7 @@ next_rec:
rw_lock_x_lock(&btr_search_latch);
- if (UNIV_UNLIKELY(!block->is_hashed)) {
+ if (UNIV_UNLIKELY(!block->index)) {
/* Someone else has meanwhile dropped the hash index */
goto cleanup;
@@ -1151,9 +1155,8 @@ next_rec:
ut_a(index->search_info->ref_count > 0);
index->search_info->ref_count--;
- block->is_hashed = FALSE;
block->index = NULL;
-
+
cleanup:
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
if (UNIV_UNLIKELY(block->n_pointers)) {
@@ -1223,7 +1226,7 @@ retry:
if (buf_block_get_state(block)
!= BUF_BLOCK_FILE_PAGE
|| block->index != index
- || !block->is_hashed) {
+ || !(block->index != NULL)) {
continue;
}
@@ -1289,7 +1292,7 @@ next_rec:
rw_lock_x_lock(&btr_search_latch);
- if (UNIV_UNLIKELY(!block->is_hashed)) {
+ if (UNIV_UNLIKELY(!(block->index != NULL))) {
goto cleanup;
}
@@ -1314,7 +1317,6 @@ next_rec:
ut_a(index->search_info->ref_count > 0);
index->search_info->ref_count--;
- block->is_hashed = FALSE;
block->index = NULL;
cleanup:
@@ -1346,8 +1348,8 @@ cleanup:
}
/********************************************************************//**
-Drops a page hash index when a page is freed from a fseg to the file system.
-Drops possible hash index if the page happens to be in the buffer pool. */
+Drops a possible page hash index when a page is evicted from the buffer pool
+or freed in a file segment. */
UNIV_INTERN
void
btr_search_drop_page_hash_when_freed(
@@ -1360,28 +1362,19 @@ btr_search_drop_page_hash_when_freed(
buf_block_t* block;
mtr_t mtr;
- if (!buf_page_peek_if_search_hashed(space, page_no)) {
-
- return;
- }
-
mtr_start(&mtr);
- /* We assume that if the caller has a latch on the page, then the
- caller has already dropped the hash index for the page, and we never
- get here. Therefore we can acquire the s-latch to the page without
- having to fear a deadlock. */
+ /* If the caller has a latch on the page, then the caller must
+ have a x-latch on the page and it must have already dropped
+ the hash index for the page. Because of the x-latch that we
+ are possibly holding, we cannot s-latch the page, but must
+ (recursively) x-latch it, even though we are only reading. */
- block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH, NULL,
+ block = buf_page_get_gen(space, zip_size, page_no, RW_X_LATCH, NULL,
BUF_PEEK_IF_IN_POOL, __FILE__, __LINE__,
&mtr);
- /* Because the buffer pool mutex was released by
- buf_page_peek_if_search_hashed(), it is possible that the
- block was removed from the buffer pool by another thread
- before buf_page_get_gen() got a chance to acquire the buffer
- pool mutex again. Thus, we must check for a NULL return. */
- if (UNIV_LIKELY(block != NULL)) {
+ if (block && block->index) {
buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
@@ -1413,7 +1406,6 @@ btr_search_build_page_hash_index(
rec_t* next_rec;
ulint fold;
ulint next_fold;
- dulint index_id;
ulint n_cached;
ulint n_recs;
ulint* folds;
@@ -1427,9 +1419,6 @@ btr_search_build_page_hash_index(
ut_ad(index);
ut_a(!dict_index_is_ibuf(index));
- table = btr_search_sys->hash_index;
- page = buf_block_get_frame(block);
-
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
@@ -1438,9 +1427,17 @@ btr_search_build_page_hash_index(
rw_lock_s_lock(&btr_search_latch);
- if (block->is_hashed && ((block->curr_n_fields != n_fields)
- || (block->curr_n_bytes != n_bytes)
- || (block->curr_left_side != left_side))) {
+ if (!btr_search_enabled) {
+ rw_lock_s_unlock(&btr_search_latch);
+ return;
+ }
+
+ table = btr_search_sys->hash_index;
+ page = buf_block_get_frame(block);
+
+ if (block->index && ((block->curr_n_fields != n_fields)
+ || (block->curr_n_bytes != n_bytes)
+ || (block->curr_left_side != left_side))) {
rw_lock_s_unlock(&btr_search_latch);
@@ -1477,7 +1474,7 @@ btr_search_build_page_hash_index(
n_cached = 0;
- index_id = btr_page_get_index_id(page);
+ ut_a(UT_DULINT_EQ(index->id, btr_page_get_index_id(page)));
rec = page_rec_get_next(page_get_infimum_rec(page));
@@ -1492,7 +1489,7 @@ btr_search_build_page_hash_index(
}
}
- fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
+ fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id);
if (left_side) {
@@ -1519,7 +1516,7 @@ btr_search_build_page_hash_index(
offsets = rec_get_offsets(next_rec, index, offsets,
n_fields + (n_bytes > 0), &heap);
next_fold = rec_fold(next_rec, offsets, n_fields,
- n_bytes, index_id);
+ n_bytes, index->id);
if (fold != next_fold) {
/* Insert an entry into the hash index */
@@ -1544,13 +1541,13 @@ btr_search_build_page_hash_index(
rw_lock_x_lock(&btr_search_latch);
- if (UNIV_UNLIKELY(btr_search_fully_disabled)) {
+ if (UNIV_UNLIKELY(!btr_search_enabled)) {
goto exit_func;
}
- if (block->is_hashed && ((block->curr_n_fields != n_fields)
- || (block->curr_n_bytes != n_bytes)
- || (block->curr_left_side != left_side))) {
+ if (block->index && ((block->curr_n_fields != n_fields)
+ || (block->curr_n_bytes != n_bytes)
+ || (block->curr_left_side != left_side))) {
goto exit_func;
}
@@ -1559,11 +1556,10 @@ btr_search_build_page_hash_index(
rebuild hash index for a page that is already hashed, we
have to take care not to increment the counter in that
case. */
- if (!block->is_hashed) {
+ if (!block->index) {
index->search_info->ref_count++;
}
- block->is_hashed = TRUE;
block->n_hash_helps = 0;
block->curr_n_fields = n_fields;
@@ -1611,14 +1607,15 @@ btr_search_move_or_delete_hash_entries(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- ut_a(!new_block->is_hashed || new_block->index == index);
- ut_a(!block->is_hashed || block->index == index);
- ut_a(!(new_block->is_hashed || block->is_hashed)
- || !dict_index_is_ibuf(index));
rw_lock_s_lock(&btr_search_latch);
- if (new_block->is_hashed) {
+ ut_a(!new_block->index || new_block->index == index);
+ ut_a(!block->index || block->index == index);
+ ut_a(!(new_block->index || block->index)
+ || !dict_index_is_ibuf(index));
+
+ if (new_block->index) {
rw_lock_s_unlock(&btr_search_latch);
@@ -1627,7 +1624,7 @@ btr_search_move_or_delete_hash_entries(
return;
}
- if (block->is_hashed) {
+ if (block->index) {
n_fields = block->curr_n_fields;
n_bytes = block->curr_n_bytes;
@@ -1664,42 +1661,48 @@ btr_search_update_hash_on_delete(
{
hash_table_t* table;
buf_block_t* block;
- rec_t* rec;
+ const rec_t* rec;
ulint fold;
- dulint index_id;
+ dict_index_t* index;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
mem_heap_t* heap = NULL;
rec_offs_init(offsets_);
- rec = btr_cur_get_rec(cursor);
-
block = btr_cur_get_block(cursor);
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- if (!block->is_hashed) {
+ index = block->index;
+
+ if (!index) {
return;
}
- ut_a(block->index == cursor->index);
+ ut_a(index == cursor->index);
ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
- ut_a(!dict_index_is_ibuf(cursor->index));
+ ut_a(!dict_index_is_ibuf(index));
table = btr_search_sys->hash_index;
- index_id = cursor->index->id;
- fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_,
+ rec = btr_cur_get_rec(cursor);
+
+ fold = rec_fold(rec, rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
- block->curr_n_fields, block->curr_n_bytes, index_id);
+ block->curr_n_fields, block->curr_n_bytes, index->id);
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
+
rw_lock_x_lock(&btr_search_latch);
- ha_search_and_delete_if_found(table, fold, rec);
+ if (block->index) {
+ ut_a(block->index == index);
+
+ ha_search_and_delete_if_found(table, fold, rec);
+ }
rw_lock_x_unlock(&btr_search_latch);
}
@@ -1717,6 +1720,7 @@ btr_search_update_hash_node_on_insert(
{
hash_table_t* table;
buf_block_t* block;
+ dict_index_t* index;
rec_t* rec;
rec = btr_cur_get_rec(cursor);
@@ -1727,16 +1731,25 @@ btr_search_update_hash_node_on_insert(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- if (!block->is_hashed) {
+ index = block->index;
+
+ if (!index) {
return;
}
- ut_a(block->index == cursor->index);
- ut_a(!dict_index_is_ibuf(cursor->index));
+ ut_a(cursor->index == index);
+ ut_a(!dict_index_is_ibuf(index));
rw_lock_x_lock(&btr_search_latch);
+ if (!block->index) {
+
+ goto func_exit;
+ }
+
+ ut_a(block->index == index);
+
if ((cursor->flag == BTR_CUR_HASH)
&& (cursor->n_fields == block->curr_n_fields)
&& (cursor->n_bytes == block->curr_n_bytes)
@@ -1747,6 +1760,7 @@ btr_search_update_hash_node_on_insert(
ha_search_and_update_if_found(table, cursor->fold, rec,
block, page_rec_get_next(rec));
+func_exit:
rw_lock_x_unlock(&btr_search_latch);
} else {
rw_lock_x_unlock(&btr_search_latch);
@@ -1768,10 +1782,10 @@ btr_search_update_hash_on_insert(
{
hash_table_t* table;
buf_block_t* block;
+ dict_index_t* index;
rec_t* rec;
rec_t* ins_rec;
rec_t* next_rec;
- dulint index_id;
ulint fold;
ulint ins_fold;
ulint next_fold = 0; /* remove warning (??? bug ???) */
@@ -1796,15 +1810,15 @@ btr_search_update_hash_on_insert(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- if (!block->is_hashed) {
+ index = block->index;
+
+ if (!index) {
return;
}
- ut_a(block->index == cursor->index);
- ut_a(!dict_index_is_ibuf(cursor->index));
-
- index_id = cursor->index->id;
+ ut_a(index == cursor->index);
+ ut_a(!dict_index_is_ibuf(index));
n_fields = block->curr_n_fields;
n_bytes = block->curr_n_bytes;
@@ -1813,21 +1827,21 @@ btr_search_update_hash_on_insert(
ins_rec = page_rec_get_next(rec);
next_rec = page_rec_get_next(ins_rec);
- offsets = rec_get_offsets(ins_rec, cursor->index, offsets,
+ offsets = rec_get_offsets(ins_rec, index, offsets,
ULINT_UNDEFINED, &heap);
- ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index_id);
+ ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index->id);
if (!page_rec_is_supremum(next_rec)) {
- offsets = rec_get_offsets(next_rec, cursor->index, offsets,
+ offsets = rec_get_offsets(next_rec, index, offsets,
n_fields + (n_bytes > 0), &heap);
next_fold = rec_fold(next_rec, offsets, n_fields,
- n_bytes, index_id);
+ n_bytes, index->id);
}
if (!page_rec_is_infimum(rec)) {
- offsets = rec_get_offsets(rec, cursor->index, offsets,
+ offsets = rec_get_offsets(rec, index, offsets,
n_fields + (n_bytes > 0), &heap);
- fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
+ fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id);
} else {
if (left_side) {
@@ -1835,6 +1849,10 @@ btr_search_update_hash_on_insert(
locked = TRUE;
+ if (!btr_search_enabled) {
+ goto function_exit;
+ }
+
ha_insert_for_fold(table, ins_fold, block, ins_rec);
}
@@ -1848,6 +1866,10 @@ btr_search_update_hash_on_insert(
rw_lock_x_lock(&btr_search_latch);
locked = TRUE;
+
+ if (!btr_search_enabled) {
+ goto function_exit;
+ }
}
if (!left_side) {
@@ -1866,6 +1888,10 @@ check_next_rec:
rw_lock_x_lock(&btr_search_latch);
locked = TRUE;
+
+ if (!btr_search_enabled) {
+ goto function_exit;
+ }
}
ha_insert_for_fold(table, ins_fold, block, ins_rec);
@@ -1881,6 +1907,10 @@ check_next_rec:
rw_lock_x_lock(&btr_search_latch);
locked = TRUE;
+
+ if (!btr_search_enabled) {
+ goto function_exit;
+ }
}
if (!left_side) {
@@ -1888,7 +1918,7 @@ check_next_rec:
ha_insert_for_fold(table, ins_fold, block, ins_rec);
/*
fputs("Hash insert for ", stderr);
- dict_index_name_print(stderr, cursor->index);
+ dict_index_name_print(stderr, index);
fprintf(stderr, " fold %lu\n", ins_fold);
*/
} else {
@@ -1995,7 +2025,7 @@ btr_search_validate(void)
+ (block->curr_n_bytes > 0),
&heap);
- if (!block->is_hashed || node->fold
+ if (!block->index || node->fold
!= rec_fold((rec_t*)(node->data),
offsets,
block->curr_n_fields,
@@ -2030,10 +2060,10 @@ btr_search_validate(void)
rec_print_new(stderr, (rec_t*)node->data,
offsets);
fprintf(stderr, "\nInnoDB: on that page."
- " Page mem address %p, is hashed %lu,"
+ " Page mem address %p, is hashed %p,"
" n fields %lu, n bytes %lu\n"
"InnoDB: side %lu\n",
- (void*) page, (ulong) block->is_hashed,
+ (void*) page, (void*) block->index,
(ulong) block->curr_n_fields,
(ulong) block->curr_n_bytes,
(ulong) block->curr_left_side);
diff --git a/storage/xtradb/buf/buf0buddy.c b/storage/xtradb/buf/buf0buddy.c
index 673d6c55efc..71d897d367c 100644
--- a/storage/xtradb/buf/buf0buddy.c
+++ b/storage/xtradb/buf/buf0buddy.c
@@ -354,7 +354,6 @@ buf_buddy_relocate(
{
buf_page_t* bpage;
const ulint size = BUF_BUDDY_LOW << i;
- ullint usec = ut_time_us(NULL);
mutex_t* mutex;
ulint space;
ulint page_no;
@@ -442,6 +441,7 @@ buf_buddy_relocate(
if (mutex && buf_page_can_relocate(bpage)) {
/* Relocate the compressed page. */
+ ullint usec = ut_time_us(NULL);
ut_a(bpage->zip.data == src);
memcpy(dst, src, size);
bpage->zip.data = dst;
diff --git a/storage/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c
index c76973a42ef..6998f1b53ac 100644
--- a/storage/xtradb/buf/buf0buf.c
+++ b/storage/xtradb/buf/buf0buf.c
@@ -57,7 +57,9 @@ Created 11/5/1995 Heikki Tuuri
/* prototypes for new functions added to ha_innodb.cc */
trx_t* innobase_get_trx();
-inline void _increment_page_get_statistics(buf_block_t* block, trx_t* trx)
+static inline
+void
+_increment_page_get_statistics(buf_block_t* block, trx_t* trx)
{
ulint block_hash;
ulint block_hash_byte;
@@ -829,11 +831,8 @@ buf_chunk_init(
for (i = chunk->size; i--; ) {
buf_block_init(block, frame);
+ UNIV_MEM_INVALID(block->frame, UNIV_PAGE_SIZE);
-#ifdef HAVE_valgrind
- /* Wipe contents of frame to eliminate a Purify warning */
- memset(block->frame, '\0', UNIV_PAGE_SIZE);
-#endif
/* Add the block to the free list */
mutex_enter(&free_list_mutex);
UT_LIST_ADD_LAST(free, buf_pool->free, (&block->page));
@@ -1043,6 +1042,24 @@ buf_pool_free(void)
{
buf_chunk_t* chunk;
buf_chunk_t* chunks;
+ buf_page_t* bpage;
+
+ bpage = UT_LIST_GET_LAST(buf_pool->LRU);
+ while (bpage != NULL) {
+ buf_page_t* prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
+ enum buf_page_state state = buf_page_get_state(bpage);
+
+ ut_ad(buf_page_in_file(bpage));
+ ut_ad(bpage->in_LRU_list);
+
+ if (state != BUF_BLOCK_FILE_PAGE) {
+ /* We must not have any dirty block. */
+ ut_ad(state == BUF_BLOCK_ZIP_PAGE);
+ buf_page_free_descriptor(bpage);
+ }
+
+ bpage = prev_bpage;
+ }
chunks = buf_pool->chunks;
chunk = chunks + buf_pool->n_chunks;
@@ -1059,86 +1076,42 @@ buf_pool_free(void)
}
/********************************************************************//**
-Drops the adaptive hash index. To prevent a livelock, this function
-is only to be called while holding btr_search_latch and while
-btr_search_enabled == FALSE. */
+Clears the adaptive hash index on all pages in the buffer pool. */
UNIV_INTERN
void
-buf_pool_drop_hash_index(void)
-/*==========================*/
+buf_pool_clear_hash_index(void)
+/*===========================*/
{
- ibool released_search_latch;
+ buf_chunk_t* chunks = buf_pool->chunks;
+ buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(!btr_search_enabled);
- do {
- buf_chunk_t* chunks = buf_pool->chunks;
- buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
-
- released_search_latch = FALSE;
-
- while (--chunk >= chunks) {
- buf_block_t* block = chunk->blocks;
- ulint i = chunk->size;
+ while (--chunk >= chunks) {
+ buf_block_t* block = chunk->blocks;
+ ulint i = chunk->size;
- for (; i--; block++) {
- /* block->is_hashed cannot be modified
- when we have an x-latch on btr_search_latch;
- see the comment in buf0buf.h */
+ for (; i--; block++) {
+ dict_index_t* index = block->index;
- if (buf_block_get_state(block)
- != BUF_BLOCK_FILE_PAGE
- || !block->is_hashed) {
- continue;
- }
+ /* We can set block->index = NULL
+ when we have an x-latch on btr_search_latch;
+ see the comment in buf0buf.h */
- /* To follow the latching order, we
- have to release btr_search_latch
- before acquiring block->latch. */
- rw_lock_x_unlock(&btr_search_latch);
- /* When we release the search latch,
- we must rescan all blocks, because
- some may become hashed again. */
- released_search_latch = TRUE;
-
- rw_lock_x_lock(&block->lock);
-
- /* This should be guaranteed by the
- callers, which will be holding
- btr_search_enabled_mutex. */
- ut_ad(!btr_search_enabled);
-
- /* Because we did not buffer-fix the
- block by calling buf_block_get_gen(),
- it is possible that the block has been
- allocated for some other use after
- btr_search_latch was released above.
- We do not care which file page the
- block is mapped to. All we want to do
- is to drop any hash entries referring
- to the page. */
-
- /* It is possible that
- block->page.state != BUF_FILE_PAGE.
- Even that does not matter, because
- btr_search_drop_page_hash_index() will
- check block->is_hashed before doing
- anything. block->is_hashed can only
- be set on uncompressed file pages. */
-
- btr_search_drop_page_hash_index(block);
-
- rw_lock_x_unlock(&block->lock);
-
- rw_lock_x_lock(&btr_search_latch);
-
- ut_ad(!btr_search_enabled);
+ if (!index) {
+ /* Not hashed */
+ continue;
}
+
+ block->index = NULL;
+# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ block->n_pointers = 0;
+# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
}
- } while (released_search_latch);
+ }
}
/********************************************************************//**
@@ -1283,63 +1256,6 @@ buf_page_set_accessed_make_young(
}
}
-/********************************************************************//**
-Resets the check_index_page_at_flush field of a page if found in the buffer
-pool. */
-UNIV_INTERN
-void
-buf_reset_check_index_page_at_flush(
-/*================================*/
- ulint space, /*!< in: space id */
- ulint offset) /*!< in: page number */
-{
- buf_block_t* block;
-
- //buf_pool_mutex_enter();
- rw_lock_s_lock(&page_hash_latch);
-
- block = (buf_block_t*) buf_page_hash_get(space, offset);
-
- if (block && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE) {
- block->check_index_page_at_flush = FALSE;
- }
-
- //buf_pool_mutex_exit();
- rw_lock_s_unlock(&page_hash_latch);
-}
-
-/********************************************************************//**
-Returns the current state of is_hashed of a page. FALSE if the page is
-not in the pool. NOTE that this operation does not fix the page in the
-pool if it is found there.
-@return TRUE if page hash index is built in search system */
-UNIV_INTERN
-ibool
-buf_page_peek_if_search_hashed(
-/*===========================*/
- ulint space, /*!< in: space id */
- ulint offset) /*!< in: page number */
-{
- buf_block_t* block;
- ibool is_hashed;
-
- //buf_pool_mutex_enter();
- rw_lock_s_lock(&page_hash_latch);
-
- block = (buf_block_t*) buf_page_hash_get(space, offset);
-
- if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
- is_hashed = FALSE;
- } else {
- is_hashed = block->is_hashed;
- }
-
- //buf_pool_mutex_exit();
- rw_lock_s_unlock(&page_hash_latch);
-
- return(is_hashed);
-}
-
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
/********************************************************************//**
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
@@ -1623,7 +1539,6 @@ buf_block_init_low(
block->index = NULL;
block->n_hash_helps = 0;
- block->is_hashed = FALSE;
block->n_fields = 1;
block->n_bytes = 0;
block->left_side = TRUE;
@@ -2540,7 +2455,7 @@ buf_page_get_known_nowait(
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
- ut_a(block->page.file_page_was_freed == FALSE);
+ ut_a(mode == BUF_KEEP_OLD || !block->page.file_page_was_freed);
#endif
#ifdef UNIV_IBUF_COUNT_DEBUG
@@ -3312,14 +3227,8 @@ corrupt:
}
}
- //enum buf_flush flush_type;
- //buf_pool_mutex_enter();
if (io_type == BUF_IO_WRITE) {
- //flush_type = buf_page_get_flush_type(bpage);
- /* to keep consistency at buf_LRU_insert_zip_clean() */
- //if (flush_type == BUF_FLUSH_LRU) { /* optimistic! */
- mutex_enter(&LRU_list_mutex);
- //}
+ mutex_enter(&LRU_list_mutex);
}
block_mutex = buf_page_get_mutex_enter(bpage);
ut_a(block_mutex);
diff --git a/storage/xtradb/buf/buf0lru.c b/storage/xtradb/buf/buf0lru.c
index df74ccf500f..c53b71632c2 100644
--- a/storage/xtradb/buf/buf0lru.c
+++ b/storage/xtradb/buf/buf0lru.c
@@ -292,7 +292,7 @@ next_page:
//mutex_enter(&((buf_block_t*) bpage)->mutex);
is_fixed = bpage->buf_fix_count > 0
- || !((buf_block_t*) bpage)->is_hashed;
+ || !((buf_block_t*) bpage)->index;
//mutex_exit(&((buf_block_t*) bpage)->mutex);
if (is_fixed) {
@@ -451,7 +451,7 @@ scan_again:
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
/* This is a compressed-only block
descriptor. Do nothing. */
- } else if (((buf_block_t*) bpage)->is_hashed) {
+ } else if (((buf_block_t*) bpage)->index) {
ulint page_no;
ulint zip_size;
@@ -465,7 +465,7 @@ scan_again:
mutex_exit(block_mutex);
/* Note that the following call will acquire
- an S-latch on the page */
+ and release an X-latch on the page. */
btr_search_drop_page_hash_when_freed(
id, zip_size, page_no);
@@ -537,7 +537,7 @@ buf_LRU_mark_space_was_deleted(
for (j = chunk->size; j--; block++) {
if (buf_block_get_state(block)
!= BUF_BLOCK_FILE_PAGE
- || !block->is_hashed
+ || !(block->index != NULL)
|| buf_page_get_space(&block->page) != id) {
continue;
}
diff --git a/storage/xtradb/compile-innodb b/storage/xtradb/compile-innodb
new file mode 100644
index 00000000000..82601f03ae9
--- /dev/null
+++ b/storage/xtradb/compile-innodb
@@ -0,0 +1,24 @@
+#! /bin/sh
+#
+# Copyright (c) 2006, 2009, Innobase Oy. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+extra_flags="$pentium_cflags $fast_cflags -g"
+extra_configs="$pentium_configs $static_link --with-plugins=innobase"
+
+. "$path/FINISH.sh"
diff --git a/storage/xtradb/compile-innodb-debug b/storage/xtradb/compile-innodb-debug
new file mode 100644
index 00000000000..efb4abf88d5
--- /dev/null
+++ b/storage/xtradb/compile-innodb-debug
@@ -0,0 +1,24 @@
+#! /bin/sh
+#
+# Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+path=`dirname $0`
+. "$path/SETUP.sh" $@ --with-debug=full
+
+extra_flags="$pentium_cflags $debug_cflags"
+extra_configs="$pentium_configs $debug_configs --with-plugins=innobase"
+
+. "$path/FINISH.sh"
diff --git a/storage/xtradb/dict/dict0crea.c b/storage/xtradb/dict/dict0crea.c
index c6e7d588e72..a913d4f0840 100644
--- a/storage/xtradb/dict/dict0crea.c
+++ b/storage/xtradb/dict/dict0crea.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -899,7 +899,7 @@ dict_truncate_index_tree(
appropriate field in the SYS_INDEXES record: this mini-transaction
marks the B-tree totally truncated */
- btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
+ btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, NULL, mtr);
btr_free_root(space, zip_size, root_page_no, mtr);
create:
diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c
index a8a1d7a11e6..574b0e5d7da 100644
--- a/storage/xtradb/dict/dict0dict.c
+++ b/storage/xtradb/dict/dict0dict.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -24,6 +24,8 @@ Created 1/8/1996 Heikki Tuuri
***********************************************************************/
#include "dict0dict.h"
+#include "m_string.h"
+#include "my_sys.h"
#ifdef UNIV_NONINL
#include "dict0dict.ic"
@@ -270,15 +272,39 @@ dict_table_stats_lock(
ulint latch_mode) /*!< in: RW_S_LATCH or
RW_X_LATCH */
{
+ rw_lock_t *want, *got;
+
ut_ad(table != NULL);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
switch (latch_mode) {
case RW_S_LATCH:
- rw_lock_s_lock(GET_TABLE_STATS_LATCH(table));
+ /* Lock one of dict_table_stats_latches in S-mode.
+ Latch is picked using table->id. table->id might be
+ changed while we are waiting for lock to be grabbed */
+ for (;;) {
+ want= GET_TABLE_STATS_LATCH(table);
+ rw_lock_s_lock(want);
+ got= GET_TABLE_STATS_LATCH(table);
+ if (want == got) {
+ break;
+ }
+ rw_lock_s_unlock(want);
+ }
break;
case RW_X_LATCH:
- rw_lock_x_lock(GET_TABLE_STATS_LATCH(table));
+ /* Lock one of dict_table_stats_latches in X-mode.
+ Latch is picked using table->id. table->id might be
+ changed while we are waiting for lock to be grabbed */
+ for (;;) {
+ want= GET_TABLE_STATS_LATCH(table);
+ rw_lock_x_lock(want);
+ got= GET_TABLE_STATS_LATCH(table);
+ if (want == got) {
+ break;
+ }
+ rw_lock_x_unlock(want);
+ }
break;
case RW_NO_LATCH:
/* fall through */
@@ -1164,12 +1190,21 @@ dict_table_change_id_in_cache(
dict_table_t* table, /*!< in/out: table object already in cache */
dulint new_id) /*!< in: new id to set */
{
+ dict_table_t table_tmp;
+
ut_ad(table);
ut_ad(mutex_own(&(dict_sys->mutex)));
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
/* Remove the table from the hash table of id's */
+ /* Lock is needed to prevent dict_table_stats_latches from
+ being leaked. dict_table_stats_lock picks one latch using
+ table->id. We are changing table->id below. That is why
+ we also should remember the old value to unlock table */
+ dict_table_stats_lock(table, RW_X_LATCH);
+ table_tmp= *table;
+
HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
ut_fold_dulint(table->id), table);
table->id = new_id;
@@ -1177,6 +1212,8 @@ dict_table_change_id_in_cache(
/* Add the table back to the hash table */
HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash,
ut_fold_dulint(table->id), table);
+
+ dict_table_stats_unlock(&table_tmp, RW_X_LATCH);
}
/**********************************************************************//**
@@ -1724,7 +1761,9 @@ undo_size_ok:
new_index->stat_n_leaf_pages = 1;
new_index->page = page_no;
- rw_lock_create(&new_index->lock, SYNC_INDEX_TREE);
+ rw_lock_create(&new_index->lock,
+ dict_index_is_ibuf(index)
+ ? SYNC_IBUF_INDEX_TREE : SYNC_INDEX_TREE);
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
@@ -2338,6 +2377,8 @@ dict_foreign_free(
/*==============*/
dict_foreign_t* foreign) /*!< in, own: foreign key struct */
{
+ ut_a(foreign->foreign_table->n_foreign_key_checks_running == 0);
+
mem_heap_free(foreign->heap);
}
@@ -4306,19 +4347,26 @@ dict_reload_statistics(
heap = mem_heap_create(1000);
while (index) {
+ mtr_t mtr;
+
if (table->is_corrupt) {
ut_a(srv_pass_corrupt_table);
mem_heap_free(heap);
return(FALSE);
}
- size = btr_get_size(index, BTR_TOTAL_SIZE);
+ mtr_start(&mtr);
+ mtr_s_lock(dict_index_get_lock(index), &mtr);
+
+ size = btr_get_size(index, BTR_TOTAL_SIZE, &mtr);
index->stat_index_size = size;
*sum_of_index_sizes += size;
- size = btr_get_size(index, BTR_N_LEAF_PAGES);
+ size = btr_get_size(index, BTR_N_LEAF_PAGES, &mtr);
+
+ mtr_commit(&mtr);
if (size == 0) {
/* The root node of the tree is a leaf */
@@ -4668,16 +4716,27 @@ dict_update_statistics(
(srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE
|| (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
&& dict_index_is_clust(index)))) {
+ mtr_t mtr;
ulint size;
- size = btr_get_size(index, BTR_TOTAL_SIZE);
- index->stat_index_size = size;
+ mtr_start(&mtr);
+ mtr_s_lock(dict_index_get_lock(index), &mtr);
- sum_of_index_sizes += size;
+ size = btr_get_size(index, BTR_TOTAL_SIZE, &mtr);
- size = btr_get_size(index, BTR_N_LEAF_PAGES);
+ if (size != ULINT_UNDEFINED) {
+ sum_of_index_sizes += size;
+ index->stat_index_size = size;
+ size = btr_get_size(
+ index, BTR_N_LEAF_PAGES, &mtr);
+ }
+
+ mtr_commit(&mtr);
- if (size == 0) {
+ switch (size) {
+ case ULINT_UNDEFINED:
+ goto fake_statistics;
+ case 0:
/* The root node of the tree is a leaf */
size = 1;
}
@@ -4694,6 +4753,7 @@ dict_update_statistics(
various means, also via secondary indexes. */
ulint i;
+fake_statistics:
sum_of_index_sizes++;
index->stat_index_size = index->stat_n_leaf_pages = 1;
diff --git a/storage/xtradb/dict/dict0load.c b/storage/xtradb/dict/dict0load.c
index 64d7fad3557..d026306a646 100644
--- a/storage/xtradb/dict/dict0load.c
+++ b/storage/xtradb/dict/dict0load.c
@@ -430,7 +430,7 @@ loop:
object and check that the .ibd file exists. */
fil_open_single_table_tablespace(FALSE, space_id,
- flags, name);
+ flags, name, NULL);
}
mem_free(name);
@@ -1023,7 +1023,7 @@ err_exit:
if (!fil_open_single_table_tablespace(
TRUE, space,
flags == DICT_TF_COMPACT ? 0 :
- flags & ~(~0 << DICT_TF_BITS), name)) {
+ flags & ~(~0 << DICT_TF_BITS), name, NULL)) {
/* We failed to find a sensible
tablespace file */
diff --git a/storage/xtradb/fil/fil0fil.c b/storage/xtradb/fil/fil0fil.c
index 17ca4cb1745..1cc6654a88e 100644
--- a/storage/xtradb/fil/fil0fil.c
+++ b/storage/xtradb/fil/fil0fil.c
@@ -183,7 +183,7 @@ struct fil_space_struct {
.ibd file of tablespace and want to
stop temporarily posting of new i/o
requests on the file */
- ibool stop_ibuf_merges;
+ ibool stop_new_ops;
/*!< we set this TRUE when we start
deleting a single-table tablespace */
ibool is_being_deleted;
@@ -208,12 +208,13 @@ struct fil_space_struct {
ulint n_pending_flushes; /*!< this is positive when flushing
the tablespace to disk; dropping of the
tablespace is forbidden if this is positive */
- ulint n_pending_ibuf_merges;/*!< this is positive
- when merging insert buffer entries to
- a page so that we may need to access
- the ibuf bitmap page in the
- tablespade: dropping of the tablespace
- is forbidden if this is positive */
+ ulint n_pending_ops;/*!< this is positive when we
+ have pending operations against this
+ tablespace. The pending operations can
+ be ibuf merges or lock validation code
+ trying to read a block.
+ Dropping of the tablespace is forbidden
+ if this is positive */
hash_node_t hash; /*!< hash chain node */
hash_node_t name_hash;/*!< hash chain the name_hash table */
#ifndef UNIV_HOTBACKUP
@@ -928,11 +929,6 @@ retry:
return;
}
- if (fil_system->n_open < fil_system->max_n_open) {
-
- return;
- }
-
space = fil_space_get_by_id(space_id);
if (space != NULL && space->stop_ios) {
@@ -949,6 +945,25 @@ retry:
mutex_exit(&fil_system->mutex);
+#ifndef UNIV_HOTBACKUP
+
+ /* Wake the i/o-handler threads to make sure pending
+ i/o's are performed */
+ os_aio_simulated_wake_handler_threads();
+
+ /* The sleep here is just to give IO helper threads a
+ bit of time to do some work. It is not required that
+ all IO related to the tablespace being renamed must
+ be flushed here as we do fil_flush() in
+ fil_rename_tablespace() as well. */
+ os_thread_sleep(20000);
+
+#endif /* UNIV_HOTBACKUP */
+
+ /* Flush tablespaces so that we can close modified
+ files in the LRU list */
+ fil_flush_file_spaces(FIL_TABLESPACE);
+
os_thread_sleep(20000);
count2++;
@@ -956,6 +971,11 @@ retry:
goto retry;
}
+ if (fil_system->n_open < fil_system->max_n_open) {
+
+ return;
+ }
+
/* If the file is already open, no need to do anything; if the space
does not exist, we handle the situation in the function which called
this function */
@@ -1228,7 +1248,7 @@ try_again:
}
space->stop_ios = FALSE;
- space->stop_ibuf_merges = FALSE;
+ space->stop_new_ops = FALSE;
space->is_being_deleted = FALSE;
space->purpose = purpose;
space->size = 0;
@@ -1237,7 +1257,7 @@ try_again:
space->n_reserved_extents = 0;
space->n_pending_flushes = 0;
- space->n_pending_ibuf_merges = 0;
+ space->n_pending_ops = 0;
UT_LIST_INIT(space->chain);
space->magic_n = FIL_SPACE_MAGIC_N;
@@ -1840,13 +1860,12 @@ fil_read_flushed_lsn_and_arch_log_no(
#ifndef UNIV_HOTBACKUP
/*******************************************************************//**
-Increments the count of pending insert buffer page merges, if space is not
-being deleted.
-@return TRUE if being deleted, and ibuf merges should be skipped */
+Increments the count of pending operation, if space is not being deleted.
+@return TRUE if being deleted, and operation should be skipped */
UNIV_INTERN
ibool
-fil_inc_pending_ibuf_merges(
-/*========================*/
+fil_inc_pending_ops(
+/*================*/
ulint id) /*!< in: space id */
{
fil_space_t* space;
@@ -1862,13 +1881,13 @@ fil_inc_pending_ibuf_merges(
(ulong) id);
}
- if (space == NULL || space->stop_ibuf_merges) {
+ if (space == NULL || space->stop_new_ops) {
mutex_exit(&fil_system->mutex);
return(TRUE);
}
- space->n_pending_ibuf_merges++;
+ space->n_pending_ops++;
mutex_exit(&fil_system->mutex);
@@ -1876,11 +1895,11 @@ fil_inc_pending_ibuf_merges(
}
/*******************************************************************//**
-Decrements the count of pending insert buffer page merges. */
+Decrements the count of pending operations. */
UNIV_INTERN
void
-fil_decr_pending_ibuf_merges(
-/*=========================*/
+fil_decr_pending_ops(
+/*=================*/
ulint id) /*!< in: space id */
{
fil_space_t* space;
@@ -1891,13 +1910,13 @@ fil_decr_pending_ibuf_merges(
if (space == NULL) {
fprintf(stderr,
- "InnoDB: Error: decrementing ibuf merge of a"
- " dropped tablespace %lu\n",
+ "InnoDB: Error: decrementing pending operation"
+ " of a dropped tablespace %lu\n",
(ulong) id);
}
if (space != NULL) {
- space->n_pending_ibuf_merges--;
+ space->n_pending_ops--;
}
mutex_exit(&fil_system->mutex);
@@ -2187,15 +2206,15 @@ fil_delete_tablespace(
char* path;
ut_a(id != 0);
-stop_ibuf_merges:
+stop_new_ops:
mutex_enter(&fil_system->mutex);
space = fil_space_get_by_id(id);
if (space != NULL) {
- space->stop_ibuf_merges = TRUE;
+ space->stop_new_ops = TRUE;
- if (space->n_pending_ibuf_merges == 0) {
+ if (space->n_pending_ops == 0) {
mutex_exit(&fil_system->mutex);
count = 0;
@@ -2209,9 +2228,10 @@ stop_ibuf_merges:
ut_print_filename(stderr, space->name);
fprintf(stderr, ",\n"
"InnoDB: but there are %lu pending"
- " ibuf merges on it.\n"
+ " operations (most likely ibuf merges)"
+ " on it.\n"
"InnoDB: Loop %lu.\n",
- (ulong) space->n_pending_ibuf_merges,
+ (ulong) space->n_pending_ops,
(ulong) count);
}
@@ -2220,7 +2240,7 @@ stop_ibuf_merges:
os_thread_sleep(20000);
count++;
- goto stop_ibuf_merges;
+ goto stop_new_ops;
}
}
@@ -2246,7 +2266,7 @@ try_again:
}
ut_a(space);
- ut_a(space->n_pending_ibuf_merges == 0);
+ ut_a(space->n_pending_ops == 0);
space->is_being_deleted = TRUE;
@@ -2523,7 +2543,7 @@ fil_rename_tablespace(
retry:
count++;
- if (count > 1000) {
+ if (!(count % 1000)) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Warning: problems renaming ", stderr);
ut_print_filename(stderr, old_name);
@@ -3124,8 +3144,11 @@ fil_open_single_table_tablespace(
accessing the first page of the file */
ulint id, /*!< in: space id */
ulint flags, /*!< in: tablespace flags */
- const char* name) /*!< in: table name in the
+ const char* name, /*!< in: table name in the
databasename/tablename format */
+ trx_t* trx) /*!< in: transaction. This is only used
+ for IMPORT TABLESPACE, must be NULL
+ otherwise */
{
os_file_t file;
char* filepath;
@@ -3342,6 +3365,11 @@ skip_info:
/* over write space id of all pages */
rec_offs_init(offsets_);
+ /* Unlock the data dictionary to not block queries
+ accessing other tables */
+ ut_a(trx);
+ row_mysql_unlock_data_dictionary(trx);
+
fprintf(stderr, "InnoDB: Progress in %%:");
for (offset = 0; offset < free_limit_bytes;
@@ -3543,6 +3571,9 @@ skip_write:
fprintf(stderr, " done.\n");
+ /* Reacquire the data dictionary lock */
+ row_mysql_lock_data_dictionary(trx);
+
/* update SYS_INDEXES set root page */
index = dict_table_get_first_index(table);
while (index) {
@@ -3835,7 +3866,7 @@ convert_err_exit:
level = btr_page_get_level(page, &mtr);
- new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, &mtr);
+ new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, &mtr, &mtr);
new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block);
btr_page_create(new_block, new_page_zip, index, level, &mtr);
@@ -3883,7 +3914,7 @@ convert_err_exit:
split_rec = page_get_middle_rec(page);
new_block = btr_page_alloc(index, page_no + 1, FSP_UP,
- btr_page_get_level(page, &mtr), &mtr);
+ btr_page_get_level(page, &mtr), &mtr, &mtr);
new_page = buf_block_get_frame(new_block);
new_page_zip = buf_block_get_page_zip(new_block);
btr_page_create(new_block, new_page_zip, index,
diff --git a/storage/xtradb/fsp/fsp0fsp.c b/storage/xtradb/fsp/fsp0fsp.c
index c8e4f8e269c..1b437c226a7 100644
--- a/storage/xtradb/fsp/fsp0fsp.c
+++ b/storage/xtradb/fsp/fsp0fsp.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -273,15 +273,13 @@ fseg_n_reserved_pages_low(
/********************************************************************//**
Marks a page used. The page must reside within the extents of the given
segment. */
-static
+static __attribute__((nonnull))
void
fseg_mark_page_used(
/*================*/
fseg_inode_t* seg_inode,/*!< in: segment inode */
- ulint space, /*!< in: space id */
- ulint zip_size,/*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
ulint page, /*!< in: page offset */
+ xdes_t* descr, /* extent descriptor */
mtr_t* mtr); /*!< in: mtr */
/**********************************************************************//**
Returns the first extent descriptor for a segment. We think of the extent
@@ -312,28 +310,38 @@ fsp_fill_free_list(
descriptor page and ibuf bitmap page;
then we do not allocate more extents */
ulint space, /*!< in: space */
- fsp_header_t* header, /*!< in: space header */
- mtr_t* mtr); /*!< in: mtr */
+ fsp_header_t* header, /*!< in/out: space header */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((nonnull));
/**********************************************************************//**
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
fragmentation.
-@return the allocated page number, FIL_NULL if no page could be allocated */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
static
-ulint
+buf_block_t*
fseg_alloc_free_page_low(
/*=====================*/
ulint space, /*!< in: space */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
- fseg_inode_t* seg_inode, /*!< in: segment inode */
- ulint hint, /*!< in: hint of which page would be desirable */
+ fseg_inode_t* seg_inode, /*!< in/out: segment inode */
+ ulint hint, /*!< in: hint of which page would be
+ desirable */
byte direction, /*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR */
- mtr_t* mtr); /*!< in: mtr handle */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
+ in which the page should be initialized.
+ If init_mtr!=mtr, but the page is already
+ latched in mtr, do not initialize the page. */
+ __attribute__((warn_unused_result, nonnull));
#endif /* !UNIV_HOTBACKUP */
/**********************************************************************//**
@@ -703,23 +711,22 @@ xdes_calc_descriptor_index(
/********************************************************************//**
Gets pointer to a the extent descriptor of a page. The page where the extent
-descriptor resides is x-locked. If the page offset is equal to the free limit
-of the space, adds new extents from above the free limit to the space free
-list, if not free limit == space size. This adding is necessary to make the
-descriptor defined, as they are uninitialized above the free limit.
+descriptor resides is x-locked. This function no longer extends the data
+file.
@return pointer to the extent descriptor, NULL if the page does not
-exist in the space or if the offset exceeds the free limit */
-UNIV_INLINE
+exist in the space or if the offset is >= the free limit */
+UNIV_INLINE __attribute__((nonnull, warn_unused_result))
xdes_t*
xdes_get_descriptor_with_space_hdr(
/*===============================*/
- fsp_header_t* sp_header,/*!< in/out: space header, x-latched */
- ulint space, /*!< in: space id */
- ulint offset, /*!< in: page offset;
- if equal to the free limit,
- we try to add new extents to
- the space free list */
- mtr_t* mtr) /*!< in: mtr handle */
+ fsp_header_t* sp_header, /*!< in/out: space header, x-latched
+ in mtr */
+ ulint space, /*!< in: space id */
+ ulint offset, /*!< in: page offset; if equal
+ to the free limit, we try to
+ add new extents to the space
+ free list */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint limit;
ulint size;
@@ -727,11 +734,9 @@ xdes_get_descriptor_with_space_hdr(
ulint descr_page_no;
page_t* descr_page;
- ut_ad(mtr);
ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_S_FIX)
- || mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
+ ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET);
/* Read free limit and space size */
limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT);
@@ -739,19 +744,10 @@ xdes_get_descriptor_with_space_hdr(
zip_size = dict_table_flags_to_zip_size(
mach_read_from_4(sp_header + FSP_SPACE_FLAGS));
- /* If offset is >= size or > limit, return NULL */
-
- if ((offset >= size) || (offset > limit)) {
-
+ if ((offset >= size) || (offset >= limit)) {
return(NULL);
}
- /* If offset is == limit, fill free list of the space. */
-
- if (offset == limit) {
- fsp_fill_free_list(FALSE, space, sp_header, mtr);
- }
-
descr_page_no = xdes_calc_descriptor_page(zip_size, offset);
if (descr_page_no == 0) {
@@ -781,7 +777,7 @@ is necessary to make the descriptor defined, as they are uninitialized
above the free limit.
@return pointer to the extent descriptor, NULL if the page does not
exist in the space or if the offset exceeds the free limit */
-static
+static __attribute__((nonnull, warn_unused_result))
xdes_t*
xdes_get_descriptor(
/*================*/
@@ -790,7 +786,7 @@ xdes_get_descriptor(
or 0 for uncompressed pages */
ulint offset, /*!< in: page offset; if equal to the free limit,
we try to add new extents to the space free list */
- mtr_t* mtr) /*!< in: mtr handle */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
buf_block_t* block;
fsp_header_t* sp_header;
@@ -1174,14 +1170,14 @@ fsp_header_get_tablespace_size(void)
Tries to extend a single-table tablespace so that a page would fit in the
data file.
@return TRUE if success */
-static
+static __attribute__((nonnull, warn_unused_result))
ibool
fsp_try_extend_data_file_with_pages(
/*================================*/
ulint space, /*!< in: space */
ulint page_no, /*!< in: page number */
- fsp_header_t* header, /*!< in: space header */
- mtr_t* mtr) /*!< in: mtr */
+ fsp_header_t* header, /*!< in/out: space header */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ibool success;
ulint actual_size;
@@ -1206,7 +1202,7 @@ fsp_try_extend_data_file_with_pages(
/***********************************************************************//**
Tries to extend the last data file of a tablespace if it is auto-extending.
@return FALSE if not auto-extending */
-static
+static __attribute__((nonnull))
ibool
fsp_try_extend_data_file(
/*=====================*/
@@ -1216,8 +1212,8 @@ fsp_try_extend_data_file(
the actual file size rounded down to
megabyte */
ulint space, /*!< in: space */
- fsp_header_t* header, /*!< in: space header */
- mtr_t* mtr) /*!< in: mtr */
+ fsp_header_t* header, /*!< in/out: space header */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint size;
ulint zip_size;
@@ -1353,7 +1349,7 @@ fsp_fill_free_list(
then we do not allocate more extents */
ulint space, /*!< in: space */
fsp_header_t* header, /*!< in/out: space header */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint limit;
ulint size;
@@ -1552,29 +1548,120 @@ fsp_alloc_free_extent(
}
/**********************************************************************//**
-Allocates a single free page from a space. The page is marked as used.
-@return the page offset, FIL_NULL if no page could be allocated */
+Allocates a single free page from a space. */
+static __attribute__((nonnull))
+void
+fsp_alloc_from_free_frag(
+/*=====================*/
+ fsp_header_t* header, /*!< in/out: tablespace header */
+ xdes_t* descr, /*!< in/out: extent descriptor */
+ ulint bit, /*!< in: slot to allocate in the extent */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+{
+ ulint frag_n_used;
+
+ ut_ad(xdes_get_state(descr, mtr) == XDES_FREE_FRAG);
+ ut_a(xdes_get_bit(descr, XDES_FREE_BIT, bit, mtr));
+ xdes_set_bit(descr, XDES_FREE_BIT, bit, FALSE, mtr);
+
+ /* Update the FRAG_N_USED field */
+ frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
+ mtr);
+ frag_n_used++;
+ mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
+ mtr);
+ if (xdes_is_full(descr, mtr)) {
+ /* The fragment is full: move it to another list */
+ flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
+ mtr);
+ xdes_set_state(descr, XDES_FULL_FRAG, mtr);
+
+ flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
+ mtr);
+ mlog_write_ulint(header + FSP_FRAG_N_USED,
+ frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
+ mtr);
+ }
+}
+
+/**********************************************************************//**
+Gets a buffer block for an allocated page.
+
+NOTE: If init_mtr != mtr, the block will only be initialized if it was
+not previously x-latched. It is assumed that the block has been
+x-latched only by mtr, and freed in mtr in that case.
+
+@return block, initialized if init_mtr==mtr
+or rw_lock_x_lock_count(&block->lock) == 1 */
static
-ulint
+buf_block_t*
+fsp_page_create(
+/*============*/
+ ulint space, /*!< in: space id of the allocated page */
+ ulint zip_size, /*!< in: compressed page size in bytes
+ or 0 for uncompressed pages */
+ ulint page_no, /*!< in: page number of the allocated page */
+ mtr_t* mtr, /*!< in: mini-transaction of the allocation */
+ mtr_t* init_mtr) /*!< in: mini-transaction for initializing
+ the page */
+{
+ buf_block_t* block
+ = buf_page_create(space, page_no, zip_size, init_mtr);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)
+ == rw_lock_own(&block->lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
+ /* Mimic buf_page_get(), but avoid the buf_pool->page_hash lookup. */
+ rw_lock_x_lock(&block->lock);
+ mutex_enter(&block->mutex);
+ buf_block_buf_fix_inc(block, __FILE__, __LINE__);
+ mutex_exit(&block->mutex);
+ mtr_memo_push(init_mtr, block, MTR_MEMO_PAGE_X_FIX);
+
+ if (init_mtr == mtr
+ || rw_lock_get_x_lock_count(&block->lock) == 1) {
+
+ /* Initialize the page, unless it was already
+ X-latched in mtr. (In this case, we would want to
+ allocate another page that has not been freed in mtr.) */
+ ut_ad(init_mtr == mtr
+ || !mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+
+ fsp_init_file_page(block, init_mtr);
+ }
+
+ return(block);
+}
+
+/**********************************************************************//**
+Allocates a single free page from a space. The page is marked as used.
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
+static __attribute__((nonnull, warn_unused_result))
+buf_block_t*
fsp_alloc_free_page(
/*================*/
ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint hint, /*!< in: hint of which page would be desirable */
- mtr_t* mtr) /*!< in: mtr handle */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ mtr_t* init_mtr)/*!< in/out: mini-transaction in which the
+ page should be initialized
+ (may be the same as mtr) */
{
fsp_header_t* header;
fil_addr_t first;
xdes_t* descr;
- buf_block_t* block;
ulint free;
- ulint frag_n_used;
ulint page_no;
ulint space_size;
- ibool success;
ut_ad(mtr);
+ ut_ad(init_mtr);
header = fsp_get_space_header(space, zip_size, mtr);
@@ -1601,7 +1688,7 @@ fsp_alloc_free_page(
if (descr == NULL) {
/* No free space left */
- return(FIL_NULL);
+ return(NULL);
}
xdes_set_state(descr, XDES_FREE_FRAG, mtr);
@@ -1646,50 +1733,18 @@ fsp_alloc_free_page(
" space size %lu. Page no %lu.\n",
(ulong) space, (ulong) space_size,
(ulong) page_no);
- return(FIL_NULL);
+ return(NULL);
}
- success = fsp_try_extend_data_file_with_pages(space, page_no,
- header, mtr);
- if (!success) {
+ if (!fsp_try_extend_data_file_with_pages(space, page_no,
+ header, mtr)) {
/* No disk space left */
- return(FIL_NULL);
+ return(NULL);
}
}
- xdes_set_bit(descr, XDES_FREE_BIT, free, FALSE, mtr);
+ fsp_alloc_from_free_frag(header, descr, free, mtr);
- /* Update the FRAG_N_USED field */
- frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
- mtr);
- frag_n_used++;
- mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
- mtr);
- if (xdes_is_full(descr, mtr)) {
- /* The fragment is full: move it to another list */
- flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
- mtr);
- xdes_set_state(descr, XDES_FULL_FRAG, mtr);
-
- flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
- mtr);
- mlog_write_ulint(header + FSP_FRAG_N_USED,
- frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
- mtr);
- }
-
- /* Initialize the allocated page to the buffer pool, so that it can
- be obtained immediately with buf_page_get without need for a disk
- read. */
-
- buf_page_create(space, page_no, zip_size, mtr);
-
- block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
- buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
-
- /* Prior contents of the page should be ignored */
- fsp_init_file_page(block, mtr);
-
- return(page_no);
+ return(fsp_page_create(space, zip_size, page_no, mtr, init_mtr));
}
/**********************************************************************//**
@@ -1728,6 +1783,9 @@ fsp_free_page(
fputs("InnoDB: Dump of descriptor: ", stderr);
ut_print_buf(stderr, ((byte*)descr) - 50, 200);
putc('\n', stderr);
+ /* Crash in debug version, so that we get a core dump
+ of this corruption. */
+ ut_ad(0);
if (state == XDES_FREE) {
/* We put here some fault tolerance: if the page
@@ -1746,6 +1804,9 @@ fsp_free_page(
"InnoDB: Dump of descriptor: ", (ulong) page);
ut_print_buf(stderr, ((byte*)descr) - 50, 200);
putc('\n', stderr);
+ /* Crash in debug version, so that we get a core dump
+ of this corruption. */
+ ut_ad(0);
/* We put here some fault tolerance: if the page
is already free, return without doing anything! */
@@ -1780,6 +1841,8 @@ fsp_free_page(
mtr);
fsp_free_extent(space, zip_size, page, mtr);
}
+
+ mtr->n_freed_pages++;
}
/**********************************************************************//**
@@ -1917,7 +1980,6 @@ fsp_alloc_seg_inode_page(
fseg_inode_t* inode;
buf_block_t* block;
page_t* page;
- ulint page_no;
ulint space;
ulint zip_size;
ulint i;
@@ -1928,15 +1990,15 @@ fsp_alloc_seg_inode_page(
zip_size = dict_table_flags_to_zip_size(
mach_read_from_4(FSP_SPACE_FLAGS + space_header));
- page_no = fsp_alloc_free_page(space, zip_size, 0, mtr);
+ block = fsp_alloc_free_page(space, zip_size, 0, mtr, mtr);
- if (page_no == FIL_NULL) {
+ if (block == NULL) {
return(FALSE);
}
- block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
+ ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
block->check_index_page_at_flush = FALSE;
@@ -2351,19 +2413,20 @@ fseg_create_general(
}
if (page == 0) {
- page = fseg_alloc_free_page_low(space, zip_size,
- inode, 0, FSP_UP, mtr);
+ block = fseg_alloc_free_page_low(space, zip_size,
+ inode, 0, FSP_UP, mtr, mtr);
- if (page == FIL_NULL) {
+ if (block == NULL) {
fsp_free_seg_inode(space, zip_size, inode, mtr);
goto funct_exit;
}
- block = buf_page_get(space, zip_size, page, RW_X_LATCH, mtr);
+ ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
+
header = byte_offset + buf_block_get_frame(block);
- mlog_write_ulint(header - byte_offset + FIL_PAGE_TYPE,
+ mlog_write_ulint(buf_block_get_frame(block) + FIL_PAGE_TYPE,
FIL_PAGE_TYPE_SYS, MLOG_2BYTES, mtr);
}
@@ -2540,8 +2603,10 @@ fseg_fill_free_list(
Allocates a free extent for the segment: looks first in the free list of the
segment, then tries to allocate from the space free list. NOTE that the extent
returned still resides in the segment free list, it is not yet taken off it!
-@return allocated extent, still placed in the segment free list, NULL
-if could not be allocated */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
static
xdes_t*
fseg_alloc_free_extent(
@@ -2593,22 +2658,30 @@ fseg_alloc_free_extent(
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
fragmentation.
-@return the allocated page number, FIL_NULL if no page could be allocated */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
static
-ulint
+buf_block_t*
fseg_alloc_free_page_low(
/*=====================*/
ulint space, /*!< in: space */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
- fseg_inode_t* seg_inode, /*!< in: segment inode */
- ulint hint, /*!< in: hint of which page would be desirable */
+ fseg_inode_t* seg_inode, /*!< in/out: segment inode */
+ ulint hint, /*!< in: hint of which page would be
+ desirable */
byte direction, /*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR */
- mtr_t* mtr) /*!< in: mtr handle */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
+ in which the page should be initialized.
+ If init_mtr!=mtr, but the page is already
+ latched in mtr, do not initialize the page. */
{
fsp_header_t* space_header;
ulint space_size;
@@ -2619,7 +2692,6 @@ fseg_alloc_free_page_low(
ulint ret_page; /*!< the allocated page offset, FIL_NULL
if could not be allocated */
xdes_t* ret_descr; /*!< the extent of the allocated page */
- ibool frag_page_allocated = FALSE;
ibool success;
ulint n;
@@ -2641,6 +2713,7 @@ fseg_alloc_free_page_low(
if (descr == NULL) {
/* Hint outside space or too high above free limit: reset
hint */
+ /* The file space header page is always allocated. */
hint = 0;
descr = xdes_get_descriptor(space, zip_size, hint, mtr);
}
@@ -2652,15 +2725,19 @@ fseg_alloc_free_page_low(
mtr), seg_id))
&& (xdes_get_bit(descr, XDES_FREE_BIT,
hint % FSP_EXTENT_SIZE, mtr) == TRUE)) {
-
+take_hinted_page:
/* 1. We can take the hinted page
=================================*/
ret_descr = descr;
ret_page = hint;
+ /* Skip the check for extending the tablespace. If the
+ page hint were not within the size of the tablespace,
+ we would have got (descr == NULL) above and reset the hint. */
+ goto got_hinted_page;
/*-----------------------------------------------------------*/
- } else if ((xdes_get_state(descr, mtr) == XDES_FREE)
- && ((reserved - used) < reserved / FSEG_FILLFACTOR)
- && (used >= FSEG_FRAG_LIMIT)) {
+ } else if (xdes_get_state(descr, mtr) == XDES_FREE
+ && reserved - used < reserved / FSEG_FILLFACTOR
+ && used >= FSEG_FRAG_LIMIT) {
/* 2. We allocate the free extent from space and can take
=========================================================
@@ -2678,7 +2755,7 @@ fseg_alloc_free_page_low(
/* Try to fill the segment free list */
fseg_fill_free_list(seg_inode, space, zip_size,
hint + FSP_EXTENT_SIZE, mtr);
- ret_page = hint;
+ goto take_hinted_page;
/*-----------------------------------------------------------*/
} else if ((direction != FSP_NO_DIR)
&& ((reserved - used) < reserved / FSEG_FILLFACTOR)
@@ -2727,7 +2804,7 @@ fseg_alloc_free_page_low(
first = flst_get_first(seg_inode + FSEG_FREE, mtr);
} else {
ut_error;
- return(FIL_NULL);
+ return(NULL);
}
ret_descr = xdes_lst_get_descriptor(space, zip_size,
@@ -2739,20 +2816,23 @@ fseg_alloc_free_page_low(
} else if (used < FSEG_FRAG_LIMIT) {
/* 6. We allocate an individual page from the space
===================================================*/
- ret_page = fsp_alloc_free_page(space, zip_size, hint, mtr);
- ret_descr = NULL;
-
- frag_page_allocated = TRUE;
+ buf_block_t* block = fsp_alloc_free_page(
+ space, zip_size, hint, mtr, init_mtr);
- if (ret_page != FIL_NULL) {
+ if (block != NULL) {
/* Put the page in the fragment page array of the
segment */
n = fseg_find_free_frag_page_slot(seg_inode, mtr);
- ut_a(n != FIL_NULL);
+ ut_a(n != ULINT_UNDEFINED);
- fseg_set_nth_frag_page_no(seg_inode, n, ret_page,
- mtr);
+ fseg_set_nth_frag_page_no(
+ seg_inode, n, buf_block_get_page_no(block),
+ mtr);
}
+
+ /* fsp_alloc_free_page() invoked fsp_init_file_page()
+ already. */
+ return(block);
/*-----------------------------------------------------------*/
} else {
/* 7. We allocate a new extent and take its first page
@@ -2770,7 +2850,7 @@ fseg_alloc_free_page_low(
if (ret_page == FIL_NULL) {
/* Page could not be allocated */
- return(FIL_NULL);
+ return(NULL);
}
if (space != 0) {
@@ -2788,38 +2868,22 @@ fseg_alloc_free_page_low(
" the space size %lu. Page no %lu.\n",
(ulong) space, (ulong) space_size,
(ulong) ret_page);
- return(FIL_NULL);
+ return(NULL);
}
success = fsp_try_extend_data_file_with_pages(
space, ret_page, space_header, mtr);
if (!success) {
/* No disk space left */
- return(FIL_NULL);
+ return(NULL);
}
}
}
- if (!frag_page_allocated) {
- /* Initialize the allocated page to buffer pool, so that it
- can be obtained immediately with buf_page_get without need
- for a disk read */
- buf_block_t* block;
- ulint zip_size = dict_table_flags_to_zip_size(
- mach_read_from_4(FSP_SPACE_FLAGS + space_header));
-
- block = buf_page_create(space, ret_page, zip_size, mtr);
- buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
-
- if (UNIV_UNLIKELY(block != buf_page_get(space, zip_size,
- ret_page, RW_X_LATCH,
- mtr))) {
- ut_error;
- }
-
- /* The prior contents of the page should be ignored */
- fsp_init_file_page(block, mtr);
-
+got_hinted_page:
+ /* ret_descr == NULL if the block was allocated from free_frag
+ (XDES_FREE_FRAG) */
+ if (ret_descr != NULL) {
/* At this point we know the extent and the page offset.
The extent is still in the appropriate list (FSEG_NOT_FULL
or FSEG_FREE), and the page is not yet marked as used. */
@@ -2829,25 +2893,31 @@ fseg_alloc_free_page_low(
ut_ad(xdes_get_bit(ret_descr, XDES_FREE_BIT,
ret_page % FSP_EXTENT_SIZE, mtr) == TRUE);
- fseg_mark_page_used(seg_inode, space, zip_size, ret_page, mtr);
+ fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr);
}
- buf_reset_check_index_page_at_flush(space, ret_page);
-
- return(ret_page);
+ return(fsp_page_create(
+ space, dict_table_flags_to_zip_size(
+ mach_read_from_4(FSP_SPACE_FLAGS
+ + space_header)),
+ ret_page, mtr, init_mtr));
}
/**********************************************************************//**
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
fragmentation.
-@return allocated page offset, FIL_NULL if no page could be allocated */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
UNIV_INTERN
-ulint
+buf_block_t*
fseg_alloc_free_page_general(
/*=========================*/
- fseg_header_t* seg_header,/*!< in: segment header */
- ulint hint, /*!< in: hint of which page would be desirable */
+ fseg_header_t* seg_header,/*!< in/out: segment header */
+ ulint hint, /*!< in: hint of which page would be
+ desirable */
byte direction,/*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
@@ -2858,15 +2928,18 @@ fseg_alloc_free_page_general(
with fsp_reserve_free_extents, then there
is no need to do the check for this individual
page */
- mtr_t* mtr) /*!< in: mtr handle */
+ mtr_t* mtr, /*!< in/out: mini-transaction handle */
+ mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
+ in which the page should be initialized.
+ If init_mtr!=mtr, but the page is already
+ latched in mtr, do not initialize the page. */
{
fseg_inode_t* inode;
ulint space;
ulint flags;
ulint zip_size;
rw_lock_t* latch;
- ibool success;
- ulint page_no;
+ buf_block_t* block;
ulint n_reserved;
space = page_get_space_id(page_align(seg_header));
@@ -2891,43 +2964,20 @@ fseg_alloc_free_page_general(
inode = fseg_inode_get(seg_header, space, zip_size, mtr);
- if (!has_done_reservation) {
- success = fsp_reserve_free_extents(&n_reserved, space, 2,
- FSP_NORMAL, mtr);
- if (!success) {
- return(FIL_NULL);
- }
+ if (!has_done_reservation
+ && !fsp_reserve_free_extents(&n_reserved, space, 2,
+ FSP_NORMAL, mtr)) {
+ return(NULL);
}
- page_no = fseg_alloc_free_page_low(space, zip_size,
- inode, hint, direction, mtr);
+ block = fseg_alloc_free_page_low(space, zip_size,
+ inode, hint, direction,
+ mtr, init_mtr);
if (!has_done_reservation) {
fil_space_release_free_extents(space, n_reserved);
}
- return(page_no);
-}
-
-/**********************************************************************//**
-Allocates a single free page from a segment. This function implements
-the intelligent allocation strategy which tries to minimize file space
-fragmentation.
-@return allocated page offset, FIL_NULL if no page could be allocated */
-UNIV_INTERN
-ulint
-fseg_alloc_free_page(
-/*=================*/
- fseg_header_t* seg_header,/*!< in: segment header */
- ulint hint, /*!< in: hint of which page would be desirable */
- byte direction,/*!< in: if the new page is needed because
- of an index page split, and records are
- inserted there in order, into which
- direction they go alphabetically: FSP_DOWN,
- FSP_UP, FSP_NO_DIR */
- mtr_t* mtr) /*!< in: mtr handle */
-{
- return(fseg_alloc_free_page_general(seg_header, hint, direction,
- FALSE, mtr));
+ return(block);
}
/**********************************************************************//**
@@ -3249,27 +3299,21 @@ fsp_get_available_space_in_free_extents(
/********************************************************************//**
Marks a page used. The page must reside within the extents of the given
segment. */
-static
+static __attribute__((nonnull))
void
fseg_mark_page_used(
/*================*/
fseg_inode_t* seg_inode,/*!< in: segment inode */
- ulint space, /*!< in: space id */
- ulint zip_size,/*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
ulint page, /*!< in: page offset */
+ xdes_t* descr, /* extent descriptor */
mtr_t* mtr) /*!< in: mtr */
{
- xdes_t* descr;
ulint not_full_n_used;
- ut_ad(seg_inode && mtr);
ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
== FSEG_MAGIC_N_VALUE);
- descr = xdes_get_descriptor(space, zip_size, page, mtr);
-
ut_ad(mtr_read_ulint(seg_inode + FSEG_ID, MLOG_4BYTES, mtr)
== mtr_read_ulint(descr + XDES_ID, MLOG_4BYTES, mtr));
@@ -3448,6 +3492,8 @@ crash:
descr + XDES_FLST_NODE, mtr);
fsp_free_extent(space, zip_size, page, mtr);
}
+
+ mtr->n_freed_pages++;
}
/**********************************************************************//**
diff --git a/storage/xtradb/ha/ha0ha.c b/storage/xtradb/ha/ha0ha.c
index 7f11917de0a..65046138275 100644
--- a/storage/xtradb/ha/ha0ha.c
+++ b/storage/xtradb/ha/ha0ha.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -89,40 +89,6 @@ ha_create_func(
}
/*************************************************************//**
-Empties a hash table and frees the memory heaps. */
-UNIV_INTERN
-void
-ha_clear(
-/*=====*/
- hash_table_t* table) /*!< in, own: hash table */
-{
- ulint i;
- ulint n;
-
- ut_ad(table);
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
-#endif /* UNIV_SYNC_DEBUG */
-
-#ifndef UNIV_HOTBACKUP
- /* Free the memory heaps. */
- n = table->n_mutexes;
-
- for (i = 0; i < n; i++) {
- mem_heap_free(table->heaps[i]);
- }
-#endif /* !UNIV_HOTBACKUP */
-
- /* Clear the hash table. */
- n = hash_get_n_cells(table);
-
- for (i = 0; i < n; i++) {
- hash_get_nth_cell(table, i)->node = NULL;
- }
-}
-
-/*************************************************************//**
Inserts an entry into a hash table. If an entry with the same fold number
is found, its node is updated to point to the new data, and no new node
is inserted. If btr_search_enabled is set to FALSE, we will only allow
@@ -140,7 +106,7 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block, /*!< in: buffer block containing the data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* data) /*!< in: data, must not be NULL */
+ const rec_t* data) /*!< in: data, must not be NULL */
{
hash_cell_t* cell;
ha_node_t* node;
@@ -153,7 +119,11 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ut_a(block->frame == page_align(data));
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
ASSERT_HASH_MUTEX_OWN(table, fold);
+ ut_ad(btr_search_enabled);
hash = hash_calc_hash(fold, table);
@@ -173,7 +143,6 @@ ha_insert_for_fold_func(
prev_block->n_pointers--;
block->n_pointers++;
}
- ut_ad(!btr_search_fully_disabled);
# endif /* !UNIV_HOTBACKUP */
prev_node->block = block;
@@ -186,13 +155,6 @@ ha_insert_for_fold_func(
prev_node = prev_node->next;
}
- /* We are in the process of disabling hash index, do not add
- new chain node */
- if (!btr_search_enabled) {
- ut_ad(!btr_search_fully_disabled);
- return(TRUE);
- }
-
/* We have to allocate a new chain node */
node = mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t));
@@ -250,6 +212,10 @@ ha_delete_hash_node(
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+ ut_ad(btr_search_enabled);
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
# ifndef UNIV_HOTBACKUP
if (table->adaptive) {
@@ -272,11 +238,11 @@ ha_search_and_update_if_found_func(
/*===============================*/
hash_table_t* table, /*!< in/out: hash table */
ulint fold, /*!< in: folded value of the searched data */
- void* data, /*!< in: pointer to the data */
+ const rec_t* data, /*!< in: pointer to the data */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* new_block,/*!< in: block containing new_data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* new_data)/*!< in: new pointer to the data */
+ const rec_t* new_data)/*!< in: new pointer to the data */
{
ha_node_t* node;
@@ -286,6 +252,13 @@ ha_search_and_update_if_found_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ut_a(new_block->frame == page_align(new_data));
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
+ if (!btr_search_enabled) {
+ return;
+ }
node = ha_search_with_data(table, fold, data);
@@ -322,6 +295,10 @@ ha_remove_all_nodes_to_page(
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ASSERT_HASH_MUTEX_OWN(table, fold);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+ ut_ad(btr_search_enabled);
node = ha_chain_get_first(table, fold);
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 55b9aaff109..f3ba44f1139 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -26,8 +26,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -778,6 +778,12 @@ thd_to_trx(
return(*(trx_t**) thd_ha_data(thd, innodb_hton_ptr));
}
+my_bool
+ha_innobase::is_fake_change_enabled(THD* thd)
+{
+ trx_t* trx = thd_to_trx(thd);
+ return (trx && trx->fake_changes);
+}
/********************************************************************//**
Call this function when mysqld passes control to the client. That is to
avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more
@@ -924,6 +930,9 @@ convert_error_code_to_mysql(
case DB_OUT_OF_FILE_SPACE:
return(HA_ERR_RECORD_FILE_FULL);
+ case DB_TABLE_IN_FK_CHECK:
+ return(HA_ERR_TABLE_IN_FK_CHECK);
+
case DB_TABLE_IS_BEING_USED:
return(HA_ERR_WRONG_COMMAND);
@@ -1095,6 +1104,20 @@ innobase_get_charset(
}
/**********************************************************************//**
+Get the current setting of the lower_case_table_names global parameter from
+mysqld.cc. We do a dirty read because for one there is no synchronization
+object and secondly there is little harm in doing so even if we get a torn
+read.
+@return value of lower_case_table_names */
+ulint
+innobase_get_lower_case_table_names(void)
+/*=====================================*/
+{
+ return(lower_case_table_names);
+}
+
+
+/**********************************************************************//**
Determines the current SQL statement.
@return SQL statement string */
extern "C" UNIV_INTERN
@@ -2634,7 +2657,6 @@ skip_overwrite:
/* Get the current high water mark format. */
innobase_file_format_check = (char*) trx_sys_file_format_max_get();
- btr_search_fully_disabled = (!btr_search_enabled);
DBUG_RETURN(FALSE);
error:
DBUG_RETURN(TRUE);
@@ -3366,51 +3388,139 @@ ha_innobase::primary_key_is_clustered()
return(true);
}
+/** Always normalize table name to lower case on Windows */
+#ifdef __WIN__
+#define normalize_table_name(norm_name, name) \
+ normalize_table_name_low(norm_name, name, TRUE)
+#else
+#define normalize_table_name(norm_name, name) \
+ normalize_table_name_low(norm_name, name, FALSE)
+#endif /* __WIN__ */
+
/*****************************************************************//**
Normalizes a table name string. A normalized name consists of the
database name catenated to '/' and table name. An example:
test/mytable. On Windows normalization puts both the database name and the
-table name always to lower case. */
+table name always to lower case if "set_lower_case" is set to TRUE. */
static
void
-normalize_table_name(
-/*=================*/
+normalize_table_name_low(
+/*=====================*/
char* norm_name, /*!< out: normalized name as a
null-terminated string */
- const char* name) /*!< in: table name string */
+ const char* name, /*!< in: table name string */
+ ibool set_lower_case) /*!< in: TRUE if we want to set
+ name to lower case */
{
char* name_ptr;
char* db_ptr;
+ ulint db_len;
char* ptr;
/* Scan name from the end */
- ptr = strend(name)-1;
+ ptr = strend(name) - 1;
+ /* seek to the last path separator */
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
ptr--;
}
name_ptr = ptr + 1;
- DBUG_ASSERT(ptr > name);
+ /* skip any number of path separators */
+ while (ptr >= name && (*ptr == '\\' || *ptr == '/')) {
+ ptr--;
+ }
- ptr--;
+ DBUG_ASSERT(ptr >= name);
+ /* seek to the last but one path separator or one char before
+ the beginning of name */
+ db_len = 0;
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
ptr--;
+ db_len++;
}
db_ptr = ptr + 1;
- memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
+ memcpy(norm_name, db_ptr, db_len);
- norm_name[name_ptr - db_ptr - 1] = '/';
+ norm_name[db_len] = '/';
-#ifdef __WIN__
- innobase_casedn_str(norm_name);
-#endif
+ memcpy(norm_name + db_len + 1, name_ptr, strlen(name_ptr) + 1);
+
+ if (set_lower_case) {
+ innobase_casedn_str(norm_name);
+ }
+}
+
+#if !defined(DBUG_OFF)
+/*********************************************************************
+Test normalize_table_name_low(). */
+static
+void
+test_normalize_table_name_low()
+/*===========================*/
+{
+ char norm_name[128];
+ const char* test_data[][2] = {
+ /* input, expected result */
+ {"./mysqltest/t1", "mysqltest/t1"},
+ {"./test/#sql-842b_2", "test/#sql-842b_2"},
+ {"./test/#sql-85a3_10", "test/#sql-85a3_10"},
+ {"./test/#sql2-842b-2", "test/#sql2-842b-2"},
+ {"./test/bug29807", "test/bug29807"},
+ {"./test/foo", "test/foo"},
+ {"./test/innodb_bug52663", "test/innodb_bug52663"},
+ {"./test/t", "test/t"},
+ {"./test/t1", "test/t1"},
+ {"./test/t10", "test/t10"},
+ {"/a/b/db/table", "db/table"},
+ {"/a/b/db///////table", "db/table"},
+ {"/a/b////db///////table", "db/table"},
+ {"/var/tmp/mysqld.1/#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
+ {"db/table", "db/table"},
+ {"ddd/t", "ddd/t"},
+ {"d/ttt", "d/ttt"},
+ {"d/t", "d/t"},
+ {".\\mysqltest\\t1", "mysqltest/t1"},
+ {".\\test\\#sql-842b_2", "test/#sql-842b_2"},
+ {".\\test\\#sql-85a3_10", "test/#sql-85a3_10"},
+ {".\\test\\#sql2-842b-2", "test/#sql2-842b-2"},
+ {".\\test\\bug29807", "test/bug29807"},
+ {".\\test\\foo", "test/foo"},
+ {".\\test\\innodb_bug52663", "test/innodb_bug52663"},
+ {".\\test\\t", "test/t"},
+ {".\\test\\t1", "test/t1"},
+ {".\\test\\t10", "test/t10"},
+ {"C:\\a\\b\\db\\table", "db/table"},
+ {"C:\\a\\b\\db\\\\\\\\\\\\\\table", "db/table"},
+ {"C:\\a\\b\\\\\\\\db\\\\\\\\\\\\\\table", "db/table"},
+ {"C:\\var\\tmp\\mysqld.1\\#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
+ {"db\\table", "db/table"},
+ {"ddd\\t", "ddd/t"},
+ {"d\\ttt", "d/ttt"},
+ {"d\\t", "d/t"},
+ };
+
+ for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) {
+ printf("test_normalize_table_name_low(): "
+ "testing \"%s\", expected \"%s\"... ",
+ test_data[i][0], test_data[i][1]);
+
+ normalize_table_name_low(norm_name, test_data[i][0], FALSE);
+
+ if (strcmp(norm_name, test_data[i][1]) == 0) {
+ printf("ok\n");
+ } else {
+ printf("got \"%s\"\n", norm_name);
+ ut_error;
+ }
+ }
}
+#endif /* !DBUG_OFF */
/********************************************************************//**
Get the upper limit of the MySQL integral and floating-point type.
@@ -3803,6 +3913,8 @@ ha_innobase::open(
THD* thd;
ulint retries = 0;
char* is_part = NULL;
+ ibool par_case_name_set = FALSE;
+ char par_case_name[MAX_FULL_NAME_LEN + 1];
DBUG_ENTER("ha_innobase::open");
@@ -3855,11 +3967,16 @@ ha_innobase::open(
workaround for http://bugs.mysql.com/bug.php?id=33349. Look
at support issue https://support.mysql.com/view.php?id=21080
for more details. */
+#ifdef __WIN__
+ is_part = strstr(norm_name, "#p#");
+#else
is_part = strstr(norm_name, "#P#");
+#endif /* __WIN__ */
+
retry:
/* Get pointer to a table object in InnoDB dictionary cache */
ib_table = dict_table_get(norm_name, TRUE);
-
+
if (srv_pass_corrupt_table <= 1 && ib_table && ib_table->is_corrupt) {
free_share(share);
my_free(upd_buff, MYF(0));
@@ -3869,15 +3986,77 @@ retry:
share->ib_table = ib_table;
-
-
-
-
if (NULL == ib_table) {
if (is_part && retries < 10) {
- ++retries;
- os_thread_sleep(100000);
- goto retry;
+ /* MySQL partition engine hard codes the file name
+ separator as "#P#". The text case is fixed even if
+ lower_case_table_names is set to 1 or 2. This is true
+ for sub-partition names as well. InnoDB always
+ normalises file names to lower case on Windows, this
+ can potentially cause problems when copying/moving
+ tables between platforms.
+
+ 1) If boot against an installation from Windows
+ platform, then its partition table name could
+ be all be in lower case in system tables. So we
+ will need to check lower case name when load table.
+
+ 2) If we boot an installation from other case
+ sensitive platform in Windows, we might need to
+ check the existence of table name without lowering
+ case them in the system table. */
+ if (innobase_get_lower_case_table_names() == 1) {
+
+ if (!par_case_name_set) {
+#ifndef __WIN__
+ /* Check for the table using lower
+ case name, including the partition
+ separator "P" */
+ memcpy(par_case_name, norm_name,
+ strlen(norm_name));
+ par_case_name[strlen(norm_name)] = 0;
+ innobase_casedn_str(par_case_name);
+#else
+ /* On Windows platfrom, check
+ whether there exists table name in
+ system table whose name is
+ not being normalized to lower case */
+ normalize_table_name_low(
+ par_case_name, name, FALSE);
+#endif
+ par_case_name_set = TRUE;
+ }
+
+ ib_table = dict_table_get(
+ par_case_name, FALSE);
+ }
+ if (!ib_table) {
+ ++retries;
+ os_thread_sleep(100000);
+ goto retry;
+ } else {
+#ifndef __WIN__
+ sql_print_warning("Partition table %s opened "
+ "after converting to lower "
+ "case. The table may have "
+ "been moved from a case "
+ "in-sensitive file system. "
+ "Please recreate table in "
+ "the current file system\n",
+ norm_name);
+#else
+ sql_print_warning("Partition table %s opened "
+ "after skipping the step to "
+ "lower case the table name. "
+ "The table may have been "
+ "moved from a case sensitive "
+ "file system. Please "
+ "recreate table in the "
+ "current file system\n",
+ norm_name);
+#endif
+ goto table_opened;
+ }
}
if (is_part) {
@@ -3908,6 +4087,8 @@ retry:
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
}
+table_opened:
+
if (ib_table->ibd_file_missing && !thd_tablespace_op(thd)) {
sql_print_error("MySQL is trying to open a table handle but "
"the .ibd file for\ntable %s does not exist.\n"
@@ -5183,8 +5364,7 @@ no_commit:
switch (sql_command) {
case SQLCOM_LOAD:
- if ((trx->duplicates
- & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
+ if (trx->duplicates) {
goto set_max_autoinc;
}
@@ -5472,8 +5652,7 @@ ha_innobase::update_row(
&& table->next_number_field
&& new_row == table->record[0]
&& thd_sql_command(user_thd) == SQLCOM_INSERT
- && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
- == TRX_DUP_IGNORE) {
+ && trx->duplicates) {
ulonglong auto_inc;
ulonglong col_max_value;
@@ -5819,6 +5998,7 @@ ha_innobase::index_read(
DBUG_ENTER("index_read");
ut_a(prebuilt->trx == thd_to_trx(user_thd));
+ ut_ad(key_len != 0 || find_flag != HA_READ_KEY_EXACT);
ha_statistic_increment(&SSV::ha_read_key_count);
@@ -5855,6 +6035,7 @@ ha_innobase::index_read(
(byte*) key_ptr,
(ulint) key_len,
prebuilt->trx);
+ DBUG_ASSERT(prebuilt->search_tuple->n_fields > 0);
} else {
/* We position the cursor to the last or the first entry
in the index */
@@ -6997,6 +7178,8 @@ ha_innobase::create(
DBUG_RETURN(HA_ERR_TO_BIG_ROW);
}
+ ut_a(strlen(name) < sizeof(name2));
+
strcpy(name2, name);
normalize_table_name(norm_name, name2);
@@ -7429,6 +7612,11 @@ ha_innobase::delete_table(
DBUG_ENTER("ha_innobase::delete_table");
+ DBUG_EXECUTE_IF(
+ "test_normalize_table_name_low",
+ test_normalize_table_name_low();
+ );
+
/* Strangely, MySQL passes the table name without the '.frm'
extension, in contrast to ::create */
normalize_table_name(norm_name, name);
@@ -7726,6 +7914,7 @@ ha_innobase::records_in_range(
mem_heap_t* heap;
DBUG_ENTER("records_in_range");
+ DBUG_ASSERT(min_key || max_key);
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
@@ -7771,6 +7960,9 @@ ha_innobase::records_in_range(
(const uchar*) 0),
(ulint) (min_key ? min_key->length : 0),
prebuilt->trx);
+ DBUG_ASSERT(min_key
+ ? range_start->n_fields > 0
+ : range_start->n_fields == 0);
row_sel_convert_mysql_key_to_innobase(
range_end, (byte*) key_val_buff2,
@@ -7779,6 +7971,9 @@ ha_innobase::records_in_range(
(const uchar*) 0),
(ulint) (max_key ? max_key->length : 0),
prebuilt->trx);
+ DBUG_ASSERT(max_key
+ ? range_end->n_fields > 0
+ : range_end->n_fields == 0);
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
HA_READ_KEY_EXACT);
@@ -8961,6 +9156,7 @@ ha_innobase::extra(
break;
case HA_EXTRA_RESET_STATE:
reset_template(prebuilt);
+ thd_to_trx(ha_thd())->duplicates = 0;
break;
case HA_EXTRA_NO_KEYREAD:
prebuilt->read_just_key = 0;
@@ -8978,19 +9174,18 @@ ha_innobase::extra(
parameters below. We must not invoke update_thd()
either, because the calling threads may change.
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
- case HA_EXTRA_IGNORE_DUP_KEY:
+ case HA_EXTRA_INSERT_WITH_UPDATE:
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
break;
+ case HA_EXTRA_NO_IGNORE_DUP_KEY:
+ thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_IGNORE;
+ break;
case HA_EXTRA_WRITE_CAN_REPLACE:
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
break;
case HA_EXTRA_WRITE_CANNOT_REPLACE:
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
break;
- case HA_EXTRA_NO_IGNORE_DUP_KEY:
- thd_to_trx(ha_thd())->duplicates &=
- ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
- break;
default:/* Do nothing */
;
}
@@ -11905,6 +12100,13 @@ static MYSQL_SYSVAR_ULINT(lazy_drop_table, srv_lazy_drop_table,
"e.g. for http://bugs.mysql.com/51325",
NULL, NULL, 0, 0, 1, 0);
+#ifdef UNIV_DEBUG
+static MYSQL_SYSVAR_UINT(trx_rseg_n_slots_debug, trx_rseg_n_slots_debug,
+ PLUGIN_VAR_RQCMDARG,
+ "Debug flags for InnoDB to limit TRX_RSEG_N_SLOTS for trx_rsegf_undo_find_free()",
+ NULL, NULL, 0, 0, 1024, 0);
+#endif /* UNIV_DEBUG */
+
static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(page_size),
MYSQL_SYSVAR(log_block_size),
@@ -12001,6 +12203,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(pass_corrupt_table),
MYSQL_SYSVAR(lazy_drop_table),
MYSQL_SYSVAR(fake_changes),
+#ifdef UNIV_DEBUG
+ MYSQL_SYSVAR(trx_rseg_n_slots_debug),
+#endif /* UNIV_DEBUG */
NULL
};
diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h
index bfe7432b32d..1e18b3a22b9 100644
--- a/storage/xtradb/handler/ha_innodb.h
+++ b/storage/xtradb/handler/ha_innodb.h
@@ -136,6 +136,7 @@ class ha_innobase: public handler
int close(void);
double scan_time();
double read_time(uint index, uint ranges, ha_rows rows);
+ my_bool is_fake_change_enabled(THD *thd);
bool is_corrupt() const;
int write_row(uchar * buf);
diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc
index 37fddf71cbc..5efc3f96fa3 100644
--- a/storage/xtradb/handler/handler0alter.cc
+++ b/storage/xtradb/handler/handler0alter.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 2005, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -1024,7 +1024,9 @@ ha_innobase::prepare_drop_index(
goto func_exit;
}
+ rw_lock_x_lock(dict_index_get_lock(index));
index->to_be_dropped = TRUE;
+ rw_lock_x_unlock(dict_index_get_lock(index));
}
/* If FOREIGN_KEY_CHECKS = 1 you may not drop an index defined
@@ -1143,7 +1145,9 @@ func_exit:
= dict_table_get_first_index(prebuilt->table);
do {
+ rw_lock_x_lock(dict_index_get_lock(index));
index->to_be_dropped = FALSE;
+ rw_lock_x_unlock(dict_index_get_lock(index));
index = dict_table_get_next_index(index);
} while (index);
}
@@ -1209,7 +1213,9 @@ ha_innobase::final_drop_index(
for (index = dict_table_get_first_index(prebuilt->table);
index; index = dict_table_get_next_index(index)) {
+ rw_lock_x_lock(dict_index_get_lock(index));
index->to_be_dropped = FALSE;
+ rw_lock_x_unlock(dict_index_get_lock(index));
}
goto func_exit;
diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc
index d8be00afa6f..af5c7278231 100644
--- a/storage/xtradb/handler/i_s.cc
+++ b/storage/xtradb/handler/i_s.cc
@@ -821,7 +821,7 @@ i_s_innodb_buffer_pool_pages_index_fill(
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[5]->store(block->index != NULL); /* 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);
diff --git a/storage/xtradb/ibuf/ibuf0ibuf.c b/storage/xtradb/ibuf/ibuf0ibuf.c
index 64dc9a5591d..ee9b85fa38c 100644
--- a/storage/xtradb/ibuf/ibuf0ibuf.c
+++ b/storage/xtradb/ibuf/ibuf0ibuf.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -356,7 +356,7 @@ ibuf_tree_root_get(
block = buf_page_get(
IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH, mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
return(buf_block_get_frame(block));
}
@@ -498,7 +498,7 @@ ibuf_init_at_db_start(void)
block = buf_page_get(
IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO,
RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
root = buf_block_get_frame(block);
}
@@ -1725,14 +1725,14 @@ ulint
ibuf_add_free_page(void)
/*====================*/
{
- mtr_t mtr;
- page_t* header_page;
- ulint flags;
- ulint zip_size;
- ulint page_no;
- page_t* page;
- page_t* root;
- page_t* bitmap_page;
+ mtr_t mtr;
+ page_t* header_page;
+ ulint flags;
+ ulint zip_size;
+ buf_block_t* block;
+ page_t* page;
+ page_t* root;
+ page_t* bitmap_page;
mtr_start(&mtr);
@@ -1753,34 +1753,24 @@ ibuf_add_free_page(void)
of a deadlock. This is the reason why we created a special ibuf
header page apart from the ibuf tree. */
- page_no = fseg_alloc_free_page(
+ block = fseg_alloc_free_page(
header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 0, FSP_UP,
&mtr);
- if (page_no == FIL_NULL) {
+ if (block == NULL) {
mtr_commit(&mtr);
return(DB_STRONG_FAIL);
}
- {
- buf_block_t* block;
-
- block = buf_page_get(
- IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
-
- buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
-
-
- page = buf_block_get_frame(block);
- }
-
+ ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
ibuf_enter();
-
mutex_enter(&ibuf_mutex);
-
root = ibuf_tree_root_get(&mtr);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
+ page = buf_block_get_frame(block);
+
/* Add the page to the free list and update the ibuf size data */
flst_add_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
@@ -1796,10 +1786,11 @@ ibuf_add_free_page(void)
(level 2 page) */
bitmap_page = ibuf_bitmap_get_map_page(
- IBUF_SPACE_ID, page_no, zip_size, &mtr);
+ IBUF_SPACE_ID, buf_block_get_page_no(block), zip_size, &mtr);
ibuf_bitmap_page_set_bits(
- bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, TRUE, &mtr);
+ bitmap_page, buf_block_get_page_no(block), zip_size,
+ IBUF_BITMAP_IBUF, TRUE, &mtr);
mtr_commit(&mtr);
@@ -1900,8 +1891,7 @@ ibuf_remove_free_page(void)
block = buf_page_get(
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
-
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
page = buf_block_get_frame(block);
}
@@ -2095,7 +2085,15 @@ ibuf_get_merge_page_nos(
} else {
rec_page_no = ibuf_rec_get_page_no(rec);
rec_space_id = ibuf_rec_get_space(rec);
- ut_ad(rec_page_no > IBUF_TREE_ROOT_PAGE_NO);
+ /* In the system tablespace, the smallest
+ possible secondary index leaf page number is
+ bigger than IBUF_TREE_ROOT_PAGE_NO (4). In
+ other tablespaces, the clustered index tree is
+ created at page 3, which makes page 4 the
+ smallest possible secondary index leaf page
+ (and that only after DROP INDEX). */
+ ut_ad(rec_page_no
+ > IBUF_TREE_ROOT_PAGE_NO - (rec_space_id != 0));
}
#ifdef UNIV_IBUF_DEBUG
@@ -2413,7 +2411,7 @@ ibuf_get_volume_buffered(
block = buf_page_get(
IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH, mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
prev_page = buf_block_get_frame(block);
@@ -2487,7 +2485,7 @@ count_later:
block = buf_page_get(
IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH, mtr);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
next_page = buf_block_get_frame(block);
@@ -2980,7 +2978,7 @@ ibuf_insert_to_index_page(
ut_ad(ibuf_inside());
ut_ad(dtuple_check_typed(entry));
- ut_ad(!buf_block_align(page)->is_hashed);
+ ut_ad(!buf_block_align(page)->index);
if (UNIV_UNLIKELY(dict_table_is_comp(index->table)
!= (ibool)!!page_is_comp(page))) {
@@ -3255,6 +3253,7 @@ ibuf_merge_or_delete_for_page(
ut_ad(!block || buf_block_get_space(block) == space);
ut_ad(!block || buf_block_get_page_no(block) == page_no);
ut_ad(!block || buf_block_get_zip_size(block) == zip_size);
+ ut_ad(!block || buf_block_get_io_fix(block) == BUF_IO_READ);
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE
|| trx_sys_hdr_page(space, page_no)) {
@@ -3289,7 +3288,7 @@ ibuf_merge_or_delete_for_page(
function. When the counter is > 0, that prevents tablespace
from being dropped. */
- tablespace_being_deleted = fil_inc_pending_ibuf_merges(space);
+ tablespace_being_deleted = fil_inc_pending_ops(space);
if (UNIV_UNLIKELY(tablespace_being_deleted)) {
/* Do not try to read the bitmap page from space;
@@ -3313,7 +3312,7 @@ ibuf_merge_or_delete_for_page(
mtr_commit(&mtr);
if (!tablespace_being_deleted) {
- fil_decr_pending_ibuf_merges(space);
+ fil_decr_pending_ops(space);
}
return;
@@ -3410,7 +3409,13 @@ loop:
ut_a(success);
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ /* This is a user page (secondary index leaf page),
+ but we pretend that it is a change buffer page in
+ order to obey the latching order. This should be OK,
+ because buffered changes are applied immediately while
+ the block is io-fixed. Other threads must not try to
+ latch an io-fixed block. */
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
}
/* Position pcur in the insert buffer at the first entry for this
@@ -3539,7 +3544,7 @@ reset_bit:
if (update_ibuf_bitmap && !tablespace_being_deleted) {
- fil_decr_pending_ibuf_merges(space);
+ fil_decr_pending_ops(space);
}
ibuf_exit();
diff --git a/storage/xtradb/include/btr0btr.h b/storage/xtradb/include/btr0btr.h
index 1fe40965c0f..827f81eab97 100644
--- a/storage/xtradb/include/btr0btr.h
+++ b/storage/xtradb/include/btr0btr.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -188,26 +188,45 @@ btr_block_get_func(
ulint mode, /*!< in: latch mode */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
- mtr_t* mtr) /*!< in/out: mtr */
- __attribute__((nonnull));
+# ifdef UNIV_SYNC_DEBUG
+ const dict_index_t* index, /*!< in: index tree, may be NULL
+ if it is not an insert buffer tree */
+# endif /* UNIV_SYNC_DEBUG */
+ mtr_t* mtr); /*!< in/out: mini-transaction */
+# ifdef UNIV_SYNC_DEBUG
/** Gets a buffer page and declares its latching order level.
@param space tablespace identifier
@param zip_size compressed page size in bytes or 0 for uncompressed pages
@param page_no page number
@param mode latch mode
+@param index index tree, may be NULL if not the insert buffer tree
@param mtr mini-transaction handle
@return the block descriptor */
-# define btr_block_get(space,zip_size,page_no,mode,mtr) \
+# define btr_block_get(space,zip_size,page_no,mode,index,mtr) \
+ btr_block_get_func(space,zip_size,page_no,mode, \
+ __FILE__,__LINE__,index,mtr)
+# else /* UNIV_SYNC_DEBUG */
+/** Gets a buffer page and declares its latching order level.
+@param space tablespace identifier
+@param zip_size compressed page size in bytes or 0 for uncompressed pages
+@param page_no page number
+@param mode latch mode
+@param idx index tree, may be NULL if not the insert buffer tree
+@param mtr mini-transaction handle
+@return the block descriptor */
+# define btr_block_get(space,zip_size,page_no,mode,idx,mtr) \
btr_block_get_func(space,zip_size,page_no,mode,__FILE__,__LINE__,mtr)
+# endif /* UNIV_SYNC_DEBUG */
/** Gets a buffer page and declares its latching order level.
@param space tablespace identifier
@param zip_size compressed page size in bytes or 0 for uncompressed pages
@param page_no page number
@param mode latch mode
+@param idx index tree, may be NULL if not the insert buffer tree
@param mtr mini-transaction handle
@return the uncompressed page frame */
-# define btr_page_get(space,zip_size,page_no,mode,mtr) \
- buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,mtr))
+# define btr_page_get(space,zip_size,page_no,mode,idx,mtr) \
+ buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,idx,mtr))
/**************************************************************//**
Sets the index id field of a page. */
UNIV_INLINE
@@ -378,8 +397,7 @@ btr_free_root(
ulint zip_size, /*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint root_page_no, /*!< in: root page number */
- mtr_t* mtr); /*!< in: a mini-transaction which has already
- been started */
+ mtr_t* mtr); /*!< in/out: mini-transaction */
/*************************************************************//**
Makes tree one level higher by splitting the root, and inserts
the tuple. It is assumed that mtr contains an x-latch on the tree.
@@ -588,17 +606,23 @@ btr_parse_page_reorganize(
#ifndef UNIV_HOTBACKUP
/**************************************************************//**
Gets the number of pages in a B-tree.
-@return number of pages */
+@return number of pages, or ULINT_UNDEFINED if the index is unavailable */
UNIV_INTERN
ulint
btr_get_size(
/*=========*/
dict_index_t* index, /*!< in: index */
- ulint flag); /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
+ ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
+ mtr_t* mtr) /*!< in/out: mini-transaction where index
+ is s-latched */
+ __attribute__((nonnull, warn_unused_result));
/**************************************************************//**
Allocates a new file page to be used in an index tree. NOTE: we assume
that the caller has made the reservation for free extents!
-@return new allocated block, x-latched; NULL if out of space */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
UNIV_INTERN
buf_block_t*
btr_page_alloc(
@@ -609,7 +633,12 @@ btr_page_alloc(
page split is made */
ulint level, /*!< in: level where the page is placed
in the tree */
- mtr_t* mtr); /*!< in: mtr */
+ mtr_t* mtr, /*!< in/out: mini-transaction
+ for the allocation */
+ mtr_t* init_mtr) /*!< in/out: mini-transaction
+ for x-latching and initializing
+ the page */
+ __attribute__((nonnull, warn_unused_result));
/**************************************************************//**
Frees a file page used in an index tree. NOTE: cannot free field external
storage pages because the page must contain info on its level. */
diff --git a/storage/xtradb/include/btr0btr.ic b/storage/xtradb/include/btr0btr.ic
index e19c863300a..d729a58f9c7 100644
--- a/storage/xtradb/include/btr0btr.ic
+++ b/storage/xtradb/include/btr0btr.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -48,6 +48,10 @@ btr_block_get_func(
ulint mode, /*!< in: latch mode */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
+#ifdef UNIV_SYNC_DEBUG
+ const dict_index_t* index, /*!< in: index tree, may be NULL
+ if it is not an insert buffer tree */
+#endif /* UNIV_SYNC_DEBUG */
mtr_t* mtr) /*!< in/out: mtr */
{
buf_block_t* block;
@@ -59,7 +63,9 @@ btr_block_get_func(
if (block && mode != RW_NO_LATCH) {
- buf_block_dbg_add_level(block, SYNC_TREE_NODE);
+ buf_block_dbg_add_level(
+ block, index != NULL && dict_index_is_ibuf(index)
+ ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
}
return(block);
diff --git a/storage/xtradb/include/btr0cur.h b/storage/xtradb/include/btr0cur.h
index 6f4ce95d72f..a8ec0a88867 100644
--- a/storage/xtradb/include/btr0cur.h
+++ b/storage/xtradb/include/btr0cur.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -326,16 +326,6 @@ btr_cur_pessimistic_update(
que_thr_t* thr, /*!< in: query thread */
mtr_t* mtr); /*!< in: mtr; must be committed before
latching any further pages */
-/*****************************************************************
-Commits and restarts a mini-transaction so that it will retain an
-x-lock on index->lock and the cursor page. */
-UNIV_INTERN
-void
-btr_cur_mtr_commit_and_start(
-/*=========================*/
- btr_cur_t* cursor, /*!< in: cursor */
- mtr_t* mtr) /*!< in/out: mini-transaction */
- __attribute__((nonnull));
/***********************************************************//**
Marks a clustered index record deleted. Writes an undo log record to
undo log on this delete marking. Writes in the trx id field the id
@@ -522,6 +512,27 @@ btr_cur_disown_inherited_fields(
const upd_t* update, /*!< in: update vector */
mtr_t* mtr) /*!< in/out: mini-transaction */
__attribute__((nonnull(2,3,4,5,6)));
+
+/** Operation code for btr_store_big_rec_extern_fields(). */
+enum blob_op {
+ /** Store off-page columns for a freshly inserted record */
+ BTR_STORE_INSERT = 0,
+ /** Store off-page columns for an insert by update */
+ BTR_STORE_INSERT_UPDATE,
+ /** Store off-page columns for an update */
+ BTR_STORE_UPDATE
+};
+
+/*******************************************************************//**
+Determine if an operation on off-page columns is an update.
+@return TRUE if op != BTR_STORE_INSERT */
+UNIV_INLINE
+ibool
+btr_blob_op_is_update(
+/*==================*/
+ enum blob_op op) /*!< in: operation */
+ __attribute__((warn_unused_result));
+
/*******************************************************************//**
Stores the fields in big_rec_vec to the tablespace and puts pointers to
them in rec. The extern flags in rec will have to be set beforehand.
@@ -529,52 +540,23 @@ The fields are stored on pages allocated from leaf node
file segment of the index tree.
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN
-ulint
-btr_store_big_rec_extern_fields_func(
-/*=================================*/
+enum db_err
+btr_store_big_rec_extern_fields(
+/*============================*/
dict_index_t* index, /*!< in: index of rec; the index tree
MUST be X-latched */
buf_block_t* rec_block, /*!< in/out: block containing rec */
- rec_t* rec, /*!< in: record */
+ rec_t* rec, /*!< in/out: record */
const ulint* offsets, /*!< in: rec_get_offsets(rec, index);
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
-#ifdef UNIV_DEBUG
- mtr_t* local_mtr, /*!< in: mtr containing the
- latch to rec and to the tree */
-#endif /* UNIV_DEBUG */
-#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
- ibool update_in_place,/*! in: TRUE if the record is updated
- in place (not delete+insert) */
-#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
- const big_rec_t*big_rec_vec) /*!< in: vector containing fields
+ const big_rec_t*big_rec_vec, /*!< in: vector containing fields
to be stored externally */
- __attribute__((nonnull));
-
-/** Stores the fields in big_rec_vec to the tablespace and puts pointers to
-them in rec. The extern flags in rec will have to be set beforehand.
-The fields are stored on pages allocated from leaf node
-file segment of the index tree.
-@param index in: clustered index; MUST be X-latched by mtr
-@param b in/out: block containing rec; MUST be X-latched by mtr
-@param rec in/out: clustered index record
-@param offsets in: rec_get_offsets(rec, index);
- the "external storage" flags in offsets will not be adjusted
-@param mtr in: mini-transaction that holds x-latch on index and b
-@param upd in: TRUE if the record is updated in place (not delete+insert)
-@param big in: vector containing fields to be stored externally
-@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
-#ifdef UNIV_DEBUG
-# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
- btr_store_big_rec_extern_fields_func(index,b,rec,offsets,mtr,upd,big)
-#elif defined UNIV_BLOB_LIGHT_DEBUG
-# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
- btr_store_big_rec_extern_fields_func(index,b,rec,offsets,upd,big)
-#else
-# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
- btr_store_big_rec_extern_fields_func(index,b,rec,offsets,big)
-#endif
+ mtr_t* btr_mtr, /*!< in: mtr containing the
+ latches to the clustered index */
+ enum blob_op op) /*! in: operation code */
+ __attribute__((nonnull, warn_unused_result));
/*******************************************************************//**
Frees the space in an externally stored field to the file space
diff --git a/storage/xtradb/include/btr0cur.ic b/storage/xtradb/include/btr0cur.ic
index c833b3e8572..e31f77c77eb 100644
--- a/storage/xtradb/include/btr0cur.ic
+++ b/storage/xtradb/include/btr0cur.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -139,7 +139,7 @@ btr_cur_compress_recommendation(
btr_cur_t* cursor, /*!< in: btr cursor */
mtr_t* mtr) /*!< in: mtr */
{
- const page_t* page;
+ const page_t* page;
ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
MTR_MEMO_PAGE_X_FIX));
@@ -197,4 +197,25 @@ btr_cur_can_delete_without_compress(
return(TRUE);
}
+
+/*******************************************************************//**
+Determine if an operation on off-page columns is an update.
+@return TRUE if op != BTR_STORE_INSERT */
+UNIV_INLINE
+ibool
+btr_blob_op_is_update(
+/*==================*/
+ enum blob_op op) /*!< in: operation */
+{
+ switch (op) {
+ case BTR_STORE_INSERT:
+ return(FALSE);
+ case BTR_STORE_INSERT_UPDATE:
+ case BTR_STORE_UPDATE:
+ return(TRUE);
+ }
+
+ ut_ad(0);
+ return(FALSE);
+}
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/xtradb/include/btr0pcur.h b/storage/xtradb/include/btr0pcur.h
index f59514d04b3..40ecc77dcd1 100644
--- a/storage/xtradb/include/btr0pcur.h
+++ b/storage/xtradb/include/btr0pcur.h
@@ -279,14 +279,6 @@ btr_pcur_commit_specify_mtr(
/*========================*/
btr_pcur_t* pcur, /*!< in: persistent cursor */
mtr_t* mtr); /*!< in: mtr to commit */
-/**************************************************************//**
-Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES.
-@return TRUE if detached */
-UNIV_INLINE
-ibool
-btr_pcur_is_detached(
-/*=================*/
- btr_pcur_t* pcur); /*!< in: persistent cursor */
/*********************************************************//**
Moves the persistent cursor to the next record in the tree. If no records are
left, the cursor stays 'after last in tree'.
diff --git a/storage/xtradb/include/btr0pcur.ic b/storage/xtradb/include/btr0pcur.ic
index 0f9b969e7c5..f49e155f97e 100644
--- a/storage/xtradb/include/btr0pcur.ic
+++ b/storage/xtradb/include/btr0pcur.ic
@@ -416,38 +416,6 @@ btr_pcur_commit_specify_mtr(
}
/**************************************************************//**
-Sets the pcur latch mode to BTR_NO_LATCHES. */
-UNIV_INLINE
-void
-btr_pcur_detach(
-/*============*/
- btr_pcur_t* pcur) /*!< in: persistent cursor */
-{
- ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
-
- pcur->latch_mode = BTR_NO_LATCHES;
-
- pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
-}
-
-/**************************************************************//**
-Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES.
-@return TRUE if detached */
-UNIV_INLINE
-ibool
-btr_pcur_is_detached(
-/*=================*/
- btr_pcur_t* pcur) /*!< in: persistent cursor */
-{
- if (pcur->latch_mode == BTR_NO_LATCHES) {
-
- return(TRUE);
- }
-
- return(FALSE);
-}
-
-/**************************************************************//**
Sets the old_rec_buf field to NULL. */
UNIV_INLINE
void
diff --git a/storage/xtradb/include/btr0sea.h b/storage/xtradb/include/btr0sea.h
index f6d194319ae..9281be63f67 100644
--- a/storage/xtradb/include/btr0sea.h
+++ b/storage/xtradb/include/btr0sea.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -148,8 +148,8 @@ btr_search_drop_page_hash_index_on_index(
/*=====================================*/
dict_index_t* index); /* in: record descriptor */
/********************************************************************//**
-Drops a page hash index when a page is freed from a fseg to the file system.
-Drops possible hash index if the page happens to be in the buffer pool. */
+Drops a possible page hash index when a page is evicted from the buffer pool
+or freed in a file segment. */
UNIV_INTERN
void
btr_search_drop_page_hash_when_freed(
@@ -199,16 +199,6 @@ btr_search_validate(void);
# define btr_search_validate() TRUE
#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
-/** Flag: has the search system been enabled?
-Protected by btr_search_latch and btr_search_enabled_mutex. */
-extern char btr_search_enabled;
-
-/** Flag: whether the search system has completed its disabling process,
-It is set to TRUE right after buf_pool_drop_hash_index() in
-btr_search_disable(), indicating hash index entries are cleaned up.
-Protected by btr_search_latch and btr_search_enabled_mutex. */
-extern ibool btr_search_fully_disabled;
-
/** The search info struct in an index */
struct btr_search_struct{
ulint ref_count; /*!< Number of blocks in this index tree
@@ -277,24 +267,6 @@ struct btr_search_sys_struct{
/** The adaptive hash index */
extern btr_search_sys_t* btr_search_sys;
-/** @brief The latch protecting the adaptive search system
-
-This latch protects the
-(1) hash index;
-(2) columns of a record to which we have a pointer in the hash index;
-
-but does NOT protect:
-
-(3) next record offset field in a record;
-(4) next or previous records on the same page.
-
-Bear in mind (3) and (4) when using the hash index.
-*/
-extern rw_lock_t* btr_search_latch_temp;
-
-/** The latch protecting the adaptive search system */
-#define btr_search_latch (*btr_search_latch_temp)
-
#ifdef UNIV_SEARCH_PERF_STAT
/** Number of successful adaptive hash index lookups */
extern ulint btr_search_n_succ;
diff --git a/storage/xtradb/include/btr0types.h b/storage/xtradb/include/btr0types.h
index 07c06fb18d7..5adc858b931 100644
--- a/storage/xtradb/include/btr0types.h
+++ b/storage/xtradb/include/btr0types.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -30,6 +30,7 @@ Created 2/17/1996 Heikki Tuuri
#include "rem0types.h"
#include "page0types.h"
+#include "sync0rw.h"
/** Persistent cursor */
typedef struct btr_pcur_struct btr_pcur_t;
@@ -38,6 +39,28 @@ typedef struct btr_cur_struct btr_cur_t;
/** B-tree search information for the adaptive hash index */
typedef struct btr_search_struct btr_search_t;
+/** @brief The latch protecting the adaptive search system
+
+This latch protects the
+(1) hash index;
+(2) columns of a record to which we have a pointer in the hash index;
+
+but does NOT protect:
+
+(3) next record offset field in a record;
+(4) next or previous records on the same page.
+
+Bear in mind (3) and (4) when using the hash index.
+*/
+extern rw_lock_t* btr_search_latch_temp;
+
+/** The latch protecting the adaptive search system */
+#define btr_search_latch (*btr_search_latch_temp)
+
+/** Flag: has the search system been enabled?
+Protected by btr_search_latch. */
+extern char btr_search_enabled;
+
#ifdef UNIV_BLOB_DEBUG
# include "buf0types.h"
/** An index->blobs entry for keeping track of off-page column references */
diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h
index 838dd7f3900..e3039fe520c 100644
--- a/storage/xtradb/include/buf0buf.h
+++ b/storage/xtradb/include/buf0buf.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -120,13 +120,11 @@ buf_pool_free(void);
/*===============*/
/********************************************************************//**
-Drops the adaptive hash index. To prevent a livelock, this function
-is only to be called while holding btr_search_latch and while
-btr_search_enabled == FALSE. */
+Clears the adaptive hash index on all pages in the buffer pool. */
UNIV_INTERN
void
-buf_pool_drop_hash_index(void);
-/*==========================*/
+buf_pool_clear_hash_index(void);
+/*===========================*/
/********************************************************************//**
Relocate a buffer control block. Relocates the block on the LRU list
@@ -372,15 +370,6 @@ buf_page_peek(
/*==========*/
ulint space, /*!< in: space id */
ulint offset);/*!< in: page number */
-/********************************************************************//**
-Resets the check_index_page_at_flush field of a page if found in the buffer
-pool. */
-UNIV_INTERN
-void
-buf_reset_check_index_page_at_flush(
-/*================================*/
- ulint space, /*!< in: space id */
- ulint offset);/*!< in: page number */
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
/********************************************************************//**
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
@@ -449,17 +438,6 @@ buf_page_peek_if_too_old(
/*=====================*/
const buf_page_t* bpage); /*!< in: block to make younger */
/********************************************************************//**
-Returns the current state of is_hashed of a page. FALSE if the page is
-not in the pool. NOTE that this operation does not fix the page in the
-pool if it is found there.
-@return TRUE if page hash index is built in search system */
-UNIV_INTERN
-ibool
-buf_page_peek_if_search_hashed(
-/*===========================*/
- ulint space, /*!< in: space id */
- ulint offset);/*!< in: page number */
-/********************************************************************//**
Gets the youngest modification log sequence number for a frame.
Returns zero if not file page or no modification occurred yet.
@return newest modification to page */
@@ -1296,13 +1274,16 @@ struct buf_block_struct{
/* @} */
/** @name Hash search fields
- These 6 fields may only be modified when we have
+ These 5 fields may only be modified when we have
an x-latch on btr_search_latch AND
- we are holding an s-latch or x-latch on buf_block_struct::lock or
- we know that buf_block_struct::buf_fix_count == 0.
An exception to this is when we init or create a page
- in the buffer pool in buf0buf.c. */
+ in the buffer pool in buf0buf.c.
+
+ Another exception is that assigning block->index = NULL
+ is allowed whenever holding an x-latch on btr_search_latch. */
/* @{ */
@@ -1311,20 +1292,20 @@ struct buf_block_struct{
pointers in the adaptive hash index
pointing to this frame */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- unsigned is_hashed:1; /*!< TRUE if hash index has
- already been built on this
- page; note that it does not
- guarantee that the index is
- complete, though: there may
- have been hash collisions,
- record deletions, etc. */
unsigned curr_n_fields:10;/*!< prefix length for hash indexing:
number of full fields */
unsigned curr_n_bytes:15;/*!< number of bytes in hash
indexing */
unsigned curr_left_side:1;/*!< TRUE or FALSE in hash indexing */
- dict_index_t* index; /*!< Index for which the adaptive
- hash index has been created. */
+ dict_index_t* index; /*!< Index for which the
+ adaptive hash index has been
+ created, or NULL if the page
+ does not exist in the
+ index. Note that it does not
+ guarantee that the index is
+ complete, though: there may
+ have been hash collisions,
+ record deletions, etc. */
/* @} */
# ifdef UNIV_SYNC_DEBUG
/** @name Debug fields */
diff --git a/storage/xtradb/include/buf0buf.ic b/storage/xtradb/include/buf0buf.ic
index a081d6a34c0..92e0edf0444 100644
--- a/storage/xtradb/include/buf0buf.ic
+++ b/storage/xtradb/include/buf0buf.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -18,8 +18,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
diff --git a/storage/xtradb/include/db0err.h b/storage/xtradb/include/db0err.h
index c7fa6d2a444..e4a3844cd22 100644
--- a/storage/xtradb/include/db0err.h
+++ b/storage/xtradb/include/db0err.h
@@ -97,6 +97,8 @@ enum db_err {
DB_FOREIGN_EXCEED_MAX_CASCADE, /* Foreign key constraint related
cascading delete/update exceeds
maximum allowed depth */
+ DB_TABLE_IN_FK_CHECK, /* table is being used in foreign
+ key check */
/* The following are partial failure codes */
DB_FAIL = 1000,
diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h
index 2baecdc958a..be8bd20dba9 100644
--- a/storage/xtradb/include/dict0dict.h
+++ b/storage/xtradb/include/dict0dict.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -1018,14 +1018,6 @@ dict_index_get_page(
/*================*/
const dict_index_t* tree); /*!< in: index */
/*********************************************************************//**
-Sets the page number of the root of index tree. */
-UNIV_INLINE
-void
-dict_index_set_page(
-/*================*/
- dict_index_t* index, /*!< in/out: index */
- ulint page); /*!< in: page number */
-/*********************************************************************//**
Gets the read-write lock of the index tree.
@return read-write lock */
UNIV_INLINE
diff --git a/storage/xtradb/include/dict0dict.ic b/storage/xtradb/include/dict0dict.ic
index bd7534dc7e2..1c1c3d7f202 100644
--- a/storage/xtradb/include/dict0dict.ic
+++ b/storage/xtradb/include/dict0dict.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -723,21 +723,6 @@ dict_index_get_page(
}
/*********************************************************************//**
-Sets the page number of the root of index tree. */
-UNIV_INLINE
-void
-dict_index_set_page(
-/*================*/
- dict_index_t* index, /*!< in/out: index */
- ulint page) /*!< in: page number */
-{
- ut_ad(index);
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
-
- index->page = page;
-}
-
-/*********************************************************************//**
Gets the read-write lock of the index tree.
@return read-write lock */
UNIV_INLINE
diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h
index 3554274847c..a729ed8816f 100644
--- a/storage/xtradb/include/dict0mem.h
+++ b/storage/xtradb/include/dict0mem.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -305,7 +305,9 @@ struct dict_index_struct{
unsigned to_be_dropped:1;
/*!< TRUE if this index is marked to be
dropped in ha_innobase::prepare_drop_index(),
- otherwise FALSE */
+ otherwise FALSE. Protected by
+ dict_sys->mutex, dict_operation_lock and
+ index->lock.*/
dict_field_t* fields; /*!< array of field descriptions */
#ifndef UNIV_HOTBACKUP
UT_LIST_NODE_T(dict_index_t)
diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h
index 11c4cb4ba03..d3300b6b8aa 100644
--- a/storage/xtradb/include/fil0fil.h
+++ b/storage/xtradb/include/fil0fil.h
@@ -341,20 +341,19 @@ fil_read_flushed_lsn_and_arch_log_no(
ib_uint64_t* min_flushed_lsn, /*!< in/out: */
ib_uint64_t* max_flushed_lsn); /*!< in/out: */
/*******************************************************************//**
-Increments the count of pending insert buffer page merges, if space is not
-being deleted.
-@return TRUE if being deleted, and ibuf merges should be skipped */
+Increments the count of pending operation, if space is not being deleted.
+@return TRUE if being deleted, and operation should be skipped */
UNIV_INTERN
ibool
-fil_inc_pending_ibuf_merges(
-/*========================*/
+fil_inc_pending_ops(
+/*================*/
ulint id); /*!< in: space id */
/*******************************************************************//**
-Decrements the count of pending insert buffer page merges. */
+Decrements the count of pending operations. */
UNIV_INTERN
void
-fil_decr_pending_ibuf_merges(
-/*=========================*/
+fil_decr_pending_ops(
+/*=================*/
ulint id); /*!< in: space id */
#endif /* !UNIV_HOTBACKUP */
/*******************************************************************//**
@@ -473,8 +472,11 @@ fil_open_single_table_tablespace(
accessing the first page of the file */
ulint id, /*!< in: space id */
ulint flags, /*!< in: tablespace flags */
- const char* name); /*!< in: table name in the
+ const char* name, /*!< in: table name in the
databasename/tablename format */
+ trx_t* trx); /*!< in: transaction. This is only
+ used for IMPORT TABLESPACE, must be NULL
+ otherwise */
/********************************************************************//**
It is possible, though very improbable, that the lsn's in the tablespace to be
imported have risen above the current system lsn, if a lengthy purge, ibuf
diff --git a/storage/xtradb/include/fsp0fsp.h b/storage/xtradb/include/fsp0fsp.h
index 7abd3914eda..8506748ae03 100644
--- a/storage/xtradb/include/fsp0fsp.h
+++ b/storage/xtradb/include/fsp0fsp.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -176,30 +176,33 @@ fseg_n_reserved_pages(
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize
file space fragmentation.
-@return the allocated page offset FIL_NULL if no page could be allocated */
-UNIV_INTERN
-ulint
-fseg_alloc_free_page(
-/*=================*/
- fseg_header_t* seg_header, /*!< in: segment header */
- ulint hint, /*!< in: hint of which page would be desirable */
- byte direction, /*!< in: if the new page is needed because
+@param[in/out] seg_header segment header
+@param[in] hint hint of which page would be desirable
+@param[in] direction if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
- FSP_UP, FSP_NO_DIR */
- mtr_t* mtr); /*!< in: mtr handle */
+ FSP_UP, FSP_NO_DIR
+@param[in/out] mtr mini-transaction
+@return X-latched block, or NULL if no page could be allocated */
+#define fseg_alloc_free_page(seg_header, hint, direction, mtr) \
+ fseg_alloc_free_page_general(seg_header, hint, direction, \
+ FALSE, mtr, mtr)
/**********************************************************************//**
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
fragmentation.
-@return allocated page offset, FIL_NULL if no page could be allocated */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
UNIV_INTERN
-ulint
+buf_block_t*
fseg_alloc_free_page_general(
/*=========================*/
- fseg_header_t* seg_header,/*!< in: segment header */
- ulint hint, /*!< in: hint of which page would be desirable */
+ fseg_header_t* seg_header,/*!< in/out: segment header */
+ ulint hint, /*!< in: hint of which page would be
+ desirable */
byte direction,/*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
@@ -210,7 +213,12 @@ fseg_alloc_free_page_general(
with fsp_reserve_free_extents, then there
is no need to do the check for this individual
page */
- mtr_t* mtr); /*!< in: mtr handle */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
+ in which the page should be initialized.
+ If init_mtr!=mtr, but the page is already
+ latched in mtr, do not initialize the page. */
+ __attribute__((warn_unused_result, nonnull));
/**********************************************************************//**
Reserves free pages from a tablespace. All mini-transactions which may
use several pages from the tablespace should call this function beforehand
diff --git a/storage/xtradb/include/ha0ha.h b/storage/xtradb/include/ha0ha.h
index 3299000bf3c..8bba564d153 100644
--- a/storage/xtradb/include/ha0ha.h
+++ b/storage/xtradb/include/ha0ha.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -31,13 +31,14 @@ Created 8/18/1994 Heikki Tuuri
#include "hash0hash.h"
#include "page0types.h"
#include "buf0types.h"
+#include "rem0types.h"
/*************************************************************//**
Looks for an element in a hash table.
@return pointer to the data of the first hash table node in chain
having the fold number, NULL if not found */
UNIV_INLINE
-void*
+const rec_t*
ha_search_and_get_data(
/*===================*/
hash_table_t* table, /*!< in: hash table */
@@ -51,11 +52,11 @@ ha_search_and_update_if_found_func(
/*===============================*/
hash_table_t* table, /*!< in/out: hash table */
ulint fold, /*!< in: folded value of the searched data */
- void* data, /*!< in: pointer to the data */
+ const rec_t* data, /*!< in: pointer to the data */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* new_block,/*!< in: block containing new_data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* new_data);/*!< in: new pointer to the data */
+ const rec_t* new_data);/*!< in: new pointer to the data */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
/** Looks for an element when we know the pointer to the data and
@@ -114,14 +115,6 @@ chosen to be a slightly bigger prime number.
#endif /* UNIV_SYNC_DEBUG */
/*************************************************************//**
-Empties a hash table and frees the memory heaps. */
-UNIV_INTERN
-void
-ha_clear(
-/*=====*/
- hash_table_t* table); /*!< in, own: hash table */
-
-/*************************************************************//**
Inserts an entry into a hash table. If an entry with the same fold number
is found, its node is updated to point to the new data, and no new node
is inserted.
@@ -138,7 +131,7 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block, /*!< in: buffer block containing the data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* data); /*!< in: data, must not be NULL */
+ const rec_t* data); /*!< in: data, must not be NULL */
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
/**
@@ -174,7 +167,7 @@ ha_search_and_delete_if_found(
/*==========================*/
hash_table_t* table, /*!< in: hash table */
ulint fold, /*!< in: folded value of the searched data */
- void* data); /*!< in: pointer to the data */
+ const rec_t* data); /*!< in: pointer to the data */
#ifndef UNIV_HOTBACKUP
/*****************************************************************//**
Removes from the chain determined by fold all nodes whose data pointer
@@ -217,7 +210,7 @@ struct ha_node_struct {
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block; /*!< buffer block containing the data, or NULL */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* data; /*!< pointer to the data */
+ const rec_t* data; /*!< pointer to the data */
ulint fold; /*!< fold value for the data */
};
diff --git a/storage/xtradb/include/ha0ha.ic b/storage/xtradb/include/ha0ha.ic
index 734403c4cd9..5656e9b7eba 100644
--- a/storage/xtradb/include/ha0ha.ic
+++ b/storage/xtradb/include/ha0ha.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -25,6 +25,7 @@ Created 8/18/1994 Heikki Tuuri
#include "ut0rnd.h"
#include "mem0mem.h"
+#include "btr0types.h"
/***********************************************************//**
Deletes a hash node. */
@@ -39,10 +40,10 @@ ha_delete_hash_node(
Gets a hash node data.
@return pointer to the data */
UNIV_INLINE
-void*
+const rec_t*
ha_node_get_data(
/*=============*/
- ha_node_t* node) /*!< in: hash chain node */
+ const ha_node_t* node) /*!< in: hash chain node */
{
return(node->data);
}
@@ -57,7 +58,7 @@ ha_node_set_data_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
buf_block_t* block, /*!< in: buffer block containing the data */
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- void* data) /*!< in: pointer to the data */
+ const rec_t* data) /*!< in: pointer to the data */
{
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
node->block = block;
@@ -107,39 +108,10 @@ ha_chain_get_first(
/*************************************************************//**
Looks for an element in a hash table.
-@return pointer to the first hash table node in chain having the fold
-number, NULL if not found */
-UNIV_INLINE
-ha_node_t*
-ha_search(
-/*======*/
- hash_table_t* table, /*!< in: hash table */
- ulint fold) /*!< in: folded value of the searched data */
-{
- ha_node_t* node;
-
- ASSERT_HASH_MUTEX_OWN(table, fold);
-
- node = ha_chain_get_first(table, fold);
-
- while (node) {
- if (node->fold == fold) {
-
- return(node);
- }
-
- node = ha_chain_get_next(node);
- }
-
- return(NULL);
-}
-
-/*************************************************************//**
-Looks for an element in a hash table.
@return pointer to the data of the first hash table node in chain
having the fold number, NULL if not found */
UNIV_INLINE
-void*
+const rec_t*
ha_search_and_get_data(
/*===================*/
hash_table_t* table, /*!< in: hash table */
@@ -148,6 +120,10 @@ ha_search_and_get_data(
ha_node_t* node;
ASSERT_HASH_MUTEX_OWN(table, fold);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
+ ut_ad(btr_search_enabled);
node = ha_chain_get_first(table, fold);
@@ -172,12 +148,14 @@ ha_search_with_data(
/*================*/
hash_table_t* table, /*!< in: hash table */
ulint fold, /*!< in: folded value of the searched data */
- void* data) /*!< in: pointer to the data */
+ const rec_t* data) /*!< in: pointer to the data */
{
ha_node_t* node;
ASSERT_HASH_MUTEX_OWN(table, fold);
+ ut_ad(btr_search_enabled);
+
node = ha_chain_get_first(table, fold);
while (node) {
@@ -202,11 +180,15 @@ ha_search_and_delete_if_found(
/*==========================*/
hash_table_t* table, /*!< in: hash table */
ulint fold, /*!< in: folded value of the searched data */
- void* data) /*!< in: pointer to the data */
+ const rec_t* data) /*!< in: pointer to the data */
{
ha_node_t* node;
ASSERT_HASH_MUTEX_OWN(table, fold);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+ ut_ad(btr_search_enabled);
node = ha_search_with_data(table, fold, data);
diff --git a/storage/xtradb/include/log0log.h b/storage/xtradb/include/log0log.h
index 2b4b34f2600..152d83a191f 100644
--- a/storage/xtradb/include/log0log.h
+++ b/storage/xtradb/include/log0log.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2010, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -18,8 +18,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
diff --git a/storage/xtradb/include/mem0mem.ic b/storage/xtradb/include/mem0mem.ic
index cbce2edc661..bf7b1c20cb4 100644
--- a/storage/xtradb/include/mem0mem.ic
+++ b/storage/xtradb/include/mem0mem.ic
@@ -209,10 +209,6 @@ mem_heap_alloc(
buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
#endif
-#ifdef UNIV_SET_MEM_TO_ZERO
- UNIV_MEM_ALLOC(buf, n);
- memset(buf, '\0', n);
-#endif
UNIV_MEM_ALLOC(buf, n);
return(buf);
}
diff --git a/storage/xtradb/include/mtr0mtr.h b/storage/xtradb/include/mtr0mtr.h
index 8a9ec8ea7f0..ecbfe750577 100644
--- a/storage/xtradb/include/mtr0mtr.h
+++ b/storage/xtradb/include/mtr0mtr.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -50,7 +50,9 @@ first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
#define MTR_MEMO_PAGE_S_FIX RW_S_LATCH
#define MTR_MEMO_PAGE_X_FIX RW_X_LATCH
#define MTR_MEMO_BUF_FIX RW_NO_LATCH
-#define MTR_MEMO_MODIFY 54
+#ifdef UNIV_DEBUG
+# define MTR_MEMO_MODIFY 54
+#endif /* UNIV_DEBUG */
#define MTR_MEMO_S_LOCK 55
#define MTR_MEMO_X_LOCK 56
@@ -378,11 +380,14 @@ struct mtr_struct{
dyn_array_t memo; /*!< memo stack for locks etc. */
dyn_array_t log; /*!< mini-transaction log */
ibool modifications;
- /* TRUE if the mtr made modifications to
- buffer pool pages */
+ /*!< TRUE if the mini-transaction
+ modified buffer pool pages */
ulint n_log_recs;
/* count of how many page initial log records
have been written to the mtr log */
+ ulint n_freed_pages;
+ /* number of pages that have been freed in
+ this mini-transaction */
ulint log_mode; /* specifies which operations should be
logged; default value MTR_LOG_ALL */
ib_uint64_t start_lsn;/* start lsn of the possible log entry for
diff --git a/storage/xtradb/include/mtr0mtr.ic b/storage/xtradb/include/mtr0mtr.ic
index 18f8e87b3cf..4489e8e1c1e 100644
--- a/storage/xtradb/include/mtr0mtr.ic
+++ b/storage/xtradb/include/mtr0mtr.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -45,6 +45,7 @@ mtr_start(
mtr->log_mode = MTR_LOG_ALL;
mtr->modifications = FALSE;
mtr->n_log_recs = 0;
+ mtr->n_freed_pages = 0;
ut_d(mtr->state = MTR_ACTIVE);
ut_d(mtr->magic_n = MTR_MAGIC_N);
diff --git a/storage/xtradb/include/page0page.h b/storage/xtradb/include/page0page.h
index aeaef030505..512f9ca0834 100644
--- a/storage/xtradb/include/page0page.h
+++ b/storage/xtradb/include/page0page.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -68,10 +68,7 @@ typedef byte page_header_t;
#define PAGE_MAX_TRX_ID 18 /* highest id of a trx which may have modified
a record on the page; a dulint; defined only
in secondary indexes and in the insert buffer
- tree; NOTE: this may be modified only
- when the thread has an x-latch to the page,
- and ALSO an x-latch to btr_search_latch
- if there is a hash index to the page! */
+ tree */
#define PAGE_HEADER_PRIV_END 26 /* end of private data structure of the page
header which are set in a page create */
/*----*/
@@ -922,6 +919,7 @@ page_parse_create(
ulint comp, /*!< in: nonzero=compact page format */
buf_block_t* block, /*!< in: block or NULL */
mtr_t* mtr); /*!< in: mtr or NULL */
+#ifndef UNIV_HOTBACKUP
/************************************************************//**
Prints record contents including the data relevant only in
the index page context. */
@@ -931,6 +929,7 @@ page_rec_print(
/*===========*/
const rec_t* rec, /*!< in: physical record */
const ulint* offsets);/*!< in: record descriptor */
+# ifdef UNIV_BTR_PRINT
/***************************************************************//**
This is used to print the contents of the directory for
debugging purposes. */
@@ -970,6 +969,8 @@ page_print(
in directory */
ulint rn); /*!< in: print rn first and last records
in directory */
+# endif /* UNIV_BTR_PRINT */
+#endif /* !UNIV_HOTBACKUP */
/***************************************************************//**
The following is used to validate a record on a page. This function
differs from rec_validate as it can also check the n_owned field and
diff --git a/storage/xtradb/include/page0page.ic b/storage/xtradb/include/page0page.ic
index b34408aed17..005fba2e5a1 100644
--- a/storage/xtradb/include/page0page.ic
+++ b/storage/xtradb/include/page0page.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
diff --git a/storage/xtradb/include/row0upd.ic b/storage/xtradb/include/row0upd.ic
index 0894ed373b0..10646241125 100644
--- a/storage/xtradb/include/row0upd.ic
+++ b/storage/xtradb/include/row0upd.ic
@@ -28,7 +28,6 @@ Created 12/27/1996 Heikki Tuuri
# include "trx0trx.h"
# include "trx0undo.h"
# include "row0row.h"
-# include "btr0sea.h"
#endif /* !UNIV_HOTBACKUP */
#include "page0zip.h"
@@ -157,11 +156,6 @@ row_upd_rec_sys_fields(
{
ut_ad(dict_index_is_clust(index));
ut_ad(rec_offs_validate(rec, index, offsets));
-#ifdef UNIV_SYNC_DEBUG
- if (!rw_lock_own(&btr_search_latch, RW_LOCK_EX)) {
- ut_ad(!buf_block_align(rec)->is_hashed);
- }
-#endif /* UNIV_SYNC_DEBUG */
if (UNIV_LIKELY_NULL(page_zip)) {
ulint pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
diff --git a/storage/xtradb/include/sync0rw.h b/storage/xtradb/include/sync0rw.h
index 22de1bfdd93..bf365e502c4 100644
--- a/storage/xtradb/include/sync0rw.h
+++ b/storage/xtradb/include/sync0rw.h
@@ -565,7 +565,8 @@ struct rw_lock_struct {
};
#ifdef UNIV_SYNC_DEBUG
-/** The structure for storing debug info of an rw-lock */
+/** The structure for storing debug info of an rw-lock. All access to this
+structure must be protected by rw_lock_debug_mutex_enter(). */
struct rw_lock_debug_struct {
os_thread_id_t thread_id; /*!< The thread id of the thread which
diff --git a/storage/xtradb/include/sync0rw.ic b/storage/xtradb/include/sync0rw.ic
index 485a63a1b18..cd997febc30 100644
--- a/storage/xtradb/include/sync0rw.ic
+++ b/storage/xtradb/include/sync0rw.ic
@@ -406,6 +406,7 @@ rw_lock_s_lock_func(
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
+ ut_ad(!rw_lock_own(lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
/* TODO: study performance of UNIV_LIKELY branch prediction hints. */
@@ -563,8 +564,6 @@ rw_lock_x_unlock_func(
if (lock->lock_word == 0) {
/* Last caller in a possible recursive chain. */
lock->recursive = FALSE;
- UNIV_MEM_INVALID(&lock->writer_thread,
- sizeof lock->writer_thread);
}
#ifdef UNIV_SYNC_DEBUG
@@ -605,8 +604,6 @@ rw_lock_x_unlock_direct(
if (lock->lock_word == 0) {
lock->recursive = FALSE;
- UNIV_MEM_INVALID(&lock->writer_thread,
- sizeof lock->writer_thread);
}
#ifdef UNIV_SYNC_DEBUG
diff --git a/storage/xtradb/include/sync0sync.h b/storage/xtradb/include/sync0sync.h
index 8b9a075e875..bb3c21f40f5 100644
--- a/storage/xtradb/include/sync0sync.h
+++ b/storage/xtradb/include/sync0sync.h
@@ -448,10 +448,6 @@ or row lock! */
#define SYNC_DICT_HEADER 995
#define SYNC_IBUF_HEADER 914
#define SYNC_IBUF_PESS_INSERT_MUTEX 912
-#define SYNC_IBUF_MUTEX 910 /* ibuf mutex is really below
- SYNC_FSP_PAGE: we assign a value this
- high only to make the program to pass
- the debug checks */
/*-------------------------------*/
#define SYNC_INDEX_TREE 900
#define SYNC_TREE_NODE_NEW 892
@@ -468,8 +464,11 @@ or row lock! */
#define SYNC_FSP 400
#define SYNC_FSP_PAGE 395
/*------------------------------------- Insert buffer headers */
-/*------------------------------------- ibuf_mutex */
+#define SYNC_IBUF_MUTEX 370 /* ibuf_mutex */
/*------------------------------------- Insert buffer tree */
+#define SYNC_IBUF_INDEX_TREE 360
+#define SYNC_IBUF_TREE_NODE_NEW 359
+#define SYNC_IBUF_TREE_NODE 358
#define SYNC_IBUF_BITMAP_MUTEX 351
#define SYNC_IBUF_BITMAP 350
/*------------------------------------- MySQL query cache mutex */
@@ -482,7 +481,6 @@ or row lock! */
#define SYNC_LOG 170
#define SYNC_RECV 168
#define SYNC_WORK_QUEUE 162
-#define SYNC_SEARCH_SYS_CONF 161 /* for assigning btr_search_enabled */
#define SYNC_SEARCH_SYS 160 /* NOTE that if we have a memory
heap that can be extended to the
buffer pool, its logical level is
diff --git a/storage/xtradb/include/trx0purge.h b/storage/xtradb/include/trx0purge.h
index ae5bc6f90be..264e91b2432 100644
--- a/storage/xtradb/include/trx0purge.h
+++ b/storage/xtradb/include/trx0purge.h
@@ -164,9 +164,9 @@ struct trx_purge_struct{
read_view_t* view; /*!< The purge will not remove undo logs
which are >= this view (purge view) */
mutex_t mutex; /*!< Mutex protecting the fields below */
- ulint n_pages_handled;/*!< Approximate number of undo log
+ ulonglong n_pages_handled;/*!< Approximate number of undo log
pages processed in purge */
- ulint handle_limit; /*!< Target of how many pages to get
+ ulonglong handle_limit; /*!< Target of how many pages to get
processed in the current purge */
/*------------------------------*/
/* The following two fields form the 'purge pointer' which advances
diff --git a/storage/xtradb/include/trx0rec.ic b/storage/xtradb/include/trx0rec.ic
index e7e41d6d9f6..6c411047dc6 100644
--- a/storage/xtradb/include/trx0rec.ic
+++ b/storage/xtradb/include/trx0rec.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -107,6 +107,7 @@ trx_undo_rec_copy(
len = mach_read_from_2(undo_rec)
- ut_align_offset(undo_rec, UNIV_PAGE_SIZE);
+ ut_ad(len < UNIV_PAGE_SIZE);
return(mem_heap_dup(heap, undo_rec, len));
}
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/xtradb/include/trx0rseg.ic b/storage/xtradb/include/trx0rseg.ic
index daffa92fc7d..5e8d2b41120 100644
--- a/storage/xtradb/include/trx0rseg.ic
+++ b/storage/xtradb/include/trx0rseg.ic
@@ -25,6 +25,7 @@ Created 3/26/1996 Heikki Tuuri
#include "srv0srv.h"
#include "mtr0log.h"
+#include "trx0sys.h"
/******************************************************************//**
Gets a rollback segment header.
@@ -131,7 +132,13 @@ trx_rsegf_undo_find_free(
ulint i;
ulint page_no;
- for (i = 0; i < TRX_RSEG_N_SLOTS; i++) {
+ for (i = 0;
+#ifndef UNIV_DEBUG
+ i < TRX_RSEG_N_SLOTS;
+#else
+ i < (trx_rseg_n_slots_debug ? trx_rseg_n_slots_debug : TRX_RSEG_N_SLOTS);
+#endif
+ i++) {
page_no = trx_rsegf_get_nth_undo(rsegf, i, mtr);
diff --git a/storage/xtradb/include/trx0sys.h b/storage/xtradb/include/trx0sys.h
index eafa1ab6409..8341592feb7 100644
--- a/storage/xtradb/include/trx0sys.h
+++ b/storage/xtradb/include/trx0sys.h
@@ -262,6 +262,12 @@ trx_id_t
trx_sys_get_new_trx_no(void);
/*========================*/
#endif /* !UNIV_HOTBACKUP */
+
+#ifdef UNIV_DEBUG
+/* Flag to control TRX_RSEG_N_SLOTS behavior debugging. */
+extern uint trx_rseg_n_slots_debug;
+#endif
+
/*****************************************************************//**
Writes a trx id to an index page. In case that the id size changes in
some future version, this function should be used instead of
diff --git a/storage/xtradb/include/trx0undo.h b/storage/xtradb/include/trx0undo.h
index 4f15cd85833..585b5f36696 100644
--- a/storage/xtradb/include/trx0undo.h
+++ b/storage/xtradb/include/trx0undo.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -194,27 +194,62 @@ trx_undo_get_first_rec(
mtr_t* mtr); /*!< in: mtr */
/********************************************************************//**
Tries to add a page to the undo log segment where the undo log is placed.
-@return page number if success, else FIL_NULL */
+@return X-latched block if success, else NULL */
UNIV_INTERN
-ulint
+buf_block_t*
trx_undo_add_page(
/*==============*/
trx_t* trx, /*!< in: transaction */
trx_undo_t* undo, /*!< in: undo log memory object */
- mtr_t* mtr); /*!< in: mtr which does not have a latch to any
+ mtr_t* mtr) /*!< in: mtr which does not have a latch to any
undo log page; the caller must have reserved
the rollback segment mutex */
+ __attribute__((nonnull, warn_unused_result));
+/********************************************************************//**
+Frees the last undo log page.
+The caller must hold the rollback segment mutex. */
+UNIV_INTERN
+void
+trx_undo_free_last_page_func(
+/*==========================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction */
+#endif /* UNIV_DEBUG */
+ trx_undo_t* undo, /*!< in/out: undo log memory copy */
+ mtr_t* mtr) /*!< in/out: mini-transaction which does not
+ have a latch to any undo log page or which
+ has allocated the undo log page */
+ __attribute__((nonnull));
+#ifdef UNIV_DEBUG
+# define trx_undo_free_last_page(trx,undo,mtr) \
+ trx_undo_free_last_page_func(trx,undo,mtr)
+#else /* UNIV_DEBUG */
+# define trx_undo_free_last_page(trx,undo,mtr) \
+ trx_undo_free_last_page_func(undo,mtr)
+#endif /* UNIV_DEBUG */
+
/***********************************************************************//**
Truncates an undo log from the end. This function is used during a rollback
to free space from an undo log. */
UNIV_INTERN
void
-trx_undo_truncate_end(
-/*==================*/
- trx_t* trx, /*!< in: transaction whose undo log it is */
- trx_undo_t* undo, /*!< in: undo log */
- undo_no_t limit); /*!< in: all undo records with undo number
+trx_undo_truncate_end_func(
+/*=======================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction whose undo log it is */
+#endif /* UNIV_DEBUG */
+ trx_undo_t* undo, /*!< in/out: undo log */
+ undo_no_t limit) /*!< in: all undo records with undo number
>= this value should be truncated */
+ __attribute__((nonnull));
+#ifdef UNIV_DEBUG
+# define trx_undo_truncate_end(trx,undo,limit) \
+ trx_undo_truncate_end_func(trx,undo,limit)
+#else /* UNIV_DEBUG */
+# define trx_undo_truncate_end(trx,undo,limit) \
+ trx_undo_truncate_end_func(undo,limit)
+#endif /* UNIV_DEBUG */
+
/***********************************************************************//**
Truncates an undo log from the start. This function is used during a purge
operation. */
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index 902d0c94ddd..1ae4a48be31 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -46,7 +46,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 1
#define INNODB_VERSION_MINOR 0
#define INNODB_VERSION_BUGFIX 17
-#define PERCONA_INNODB_VERSION 13.0
+#define PERCONA_INNODB_VERSION 13.01
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
@@ -149,14 +149,6 @@ Sun Studio */
/* DEBUG VERSION CONTROL
===================== */
-/* The following flag will make InnoDB to initialize
-all memory it allocates to zero. It hides Purify
-warnings about reading unallocated memory unless
-memory is read outside the allocated blocks. */
-/*
-#define UNIV_INIT_MEM_TO_ZERO
-*/
-
/* When this macro is defined then additional test functions will be
compiled. These functions live at the end of each relevant source file
and have "test_" prefix. These functions are not called from anywhere in
@@ -221,15 +213,6 @@ operations (very slow); also UNIV_DEBUG must be defined */
#define UNIV_BTR_DEBUG /* check B-tree links */
#define UNIV_LIGHT_MEM_DEBUG /* light memory debugging */
-#ifdef HAVE_valgrind
-/* The following sets all new allocated memory to zero before use:
-this can be used to eliminate unnecessary Purify warnings, but note that
-it also masks many bugs Purify could detect. For detailed Purify analysis it
-is best to remove the define below and look through the warnings one
-by one. */
-#define UNIV_SET_MEM_TO_ZERO
-#endif
-
/*
#define UNIV_SQL_DEBUG
#define UNIV_LOG_DEBUG
diff --git a/storage/xtradb/include/ut0mem.h b/storage/xtradb/include/ut0mem.h
index 9c6ee9049ec..5002c9e3801 100644
--- a/storage/xtradb/include/ut0mem.h
+++ b/storage/xtradb/include/ut0mem.h
@@ -78,40 +78,19 @@ ut_mem_init(void);
/*=============*/
/**********************************************************************//**
-Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
-defined and set_to_zero is TRUE.
+Allocates memory.
@return own: allocated memory */
UNIV_INTERN
void*
ut_malloc_low(
/*==========*/
ulint n, /*!< in: number of bytes to allocate */
- ibool set_to_zero, /*!< in: TRUE if allocated memory
- should be set to zero if
- UNIV_SET_MEM_TO_ZERO is defined */
- ibool assert_on_error); /*!< in: if TRUE, we crash mysqld if
+ ibool assert_on_error) /*!< in: if TRUE, we crash mysqld if
the memory cannot be allocated */
+ __attribute__((malloc));
/**********************************************************************//**
-Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
-defined.
-@return own: allocated memory */
-UNIV_INTERN
-void*
-ut_malloc(
-/*======*/
- ulint n); /*!< in: number of bytes to allocate */
-#ifndef UNIV_HOTBACKUP
-/**********************************************************************//**
-Tests if malloc of n bytes would succeed. ut_malloc() asserts if memory runs
-out. It cannot be used if we want to return an error message. Prints to
-stderr a message if fails.
-@return TRUE if succeeded */
-UNIV_INTERN
-ibool
-ut_test_malloc(
-/*===========*/
- ulint n); /*!< in: try to allocate this many bytes */
-#endif /* !UNIV_HOTBACKUP */
+Allocates memory. */
+#define ut_malloc(n) ut_malloc_low(n, TRUE)
/**********************************************************************//**
Frees a memory block allocated with ut_malloc. Freeing a NULL pointer is
a nop. */
diff --git a/storage/xtradb/include/ut0rnd.ic b/storage/xtradb/include/ut0rnd.ic
index d17036d83fc..1e62a7771ef 100644
--- a/storage/xtradb/include/ut0rnd.ic
+++ b/storage/xtradb/include/ut0rnd.ic
@@ -114,7 +114,7 @@ ut_rnd_interval(
rnd = ut_rnd_gen_ulint();
- return(low + (rnd % (high - low + 1)));
+ return(low + (rnd % (high - low)));
}
/*********************************************************//**
diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c
index e5da4f46ec9..d5ab6836134 100644
--- a/storage/xtradb/lock/lock0lock.c
+++ b/storage/xtradb/lock/lock0lock.c
@@ -5059,9 +5059,17 @@ lock_validate(void)
lock_mutex_exit_kernel();
- lock_rec_validate_page(space,
- fil_space_get_zip_size(space),
- page_no);
+ /* Make sure that the tablespace is not
+ deleted while we are trying to access
+ the page. */
+ if (!fil_inc_pending_ops(space)) {
+ lock_rec_validate_page(
+ space,
+ fil_space_get_zip_size(space),
+ page_no);
+
+ fil_decr_pending_ops(space);
+ }
lock_mutex_enter_kernel();
diff --git a/storage/xtradb/log/log0log.c b/storage/xtradb/log/log0log.c
index fc8745629d6..a1da38c4579 100644
--- a/storage/xtradb/log/log0log.c
+++ b/storage/xtradb/log/log0log.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2010, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -18,8 +18,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
diff --git a/storage/xtradb/mem/mem0pool.c b/storage/xtradb/mem/mem0pool.c
index 3291453eeb5..8a01be66506 100644
--- a/storage/xtradb/mem/mem0pool.c
+++ b/storage/xtradb/mem/mem0pool.c
@@ -223,11 +223,7 @@ mem_pool_create(
pool = ut_malloc(sizeof(mem_pool_t));
- /* We do not set the memory to zero (FALSE) in the pool,
- but only when allocated at a higher level in mem0mem.c.
- This is to avoid masking useful Purify warnings. */
-
- pool->buf = ut_malloc_low(size, FALSE, TRUE);
+ pool->buf = ut_malloc_low(size, TRUE);
pool->size = size;
mutex_create(&pool->mutex, SYNC_MEM_POOL);
diff --git a/storage/xtradb/mtr/mtr0mtr.c b/storage/xtradb/mtr/mtr0mtr.c
index a9f1c35f84c..3b6dfa7bd26 100644
--- a/storage/xtradb/mtr/mtr0mtr.c
+++ b/storage/xtradb/mtr/mtr0mtr.c
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
diff --git a/storage/xtradb/mysql-test/patches/README b/storage/xtradb/mysql-test/patches/README
new file mode 100644
index 00000000000..122d756e9e3
--- /dev/null
+++ b/storage/xtradb/mysql-test/patches/README
@@ -0,0 +1,30 @@
+This directory contains patches that need to be applied to the MySQL
+source tree in order to get the mysql-test suite to succeed (when
+storage/innobase is replaced with this InnoDB branch). Things to keep
+in mind when adding new patches here:
+
+* The patch must be appliable from the mysql top-level source directory.
+
+* The patch filename must end in ".diff".
+
+* All patches here are expected to apply cleanly to the latest MySQL 5.1
+ tree when storage/innobase is replaced with this InnoDB branch. If
+ changes to either of those cause the patch to fail, then please check
+ whether the patch is still needed and, if yes, adjust it so it applies
+ cleanly.
+
+* If applicable, always submit the patch at http://bugs.mysql.com and
+ name the file here like bug%d.diff. Once the patch is committed to
+ MySQL remove the file from here.
+
+* If the patch cannot be proposed for inclusion in the MySQL source tree
+ (via http://bugs.mysql.com) then add a comment at the beginning of the
+ patch, explaining the problem it is solving, how it does solve it and
+ why it is not applicable for inclusion in the MySQL source tree.
+ Obviously this is a very bad situation and should be avoided at all
+ costs, especially for files that are in the MySQL source repository
+ (not in storage/innobase).
+
+* If you ever need to add a patch here that is not related to mysql-test
+ suite, then please move this directory from ./mysql-test/patches to
+ ./patches and remove this text.
diff --git a/storage/xtradb/mysql-test/patches/index_merge_innodb-explain.diff b/storage/xtradb/mysql-test/patches/index_merge_innodb-explain.diff
new file mode 100644
index 00000000000..d1ed8afc778
--- /dev/null
+++ b/storage/xtradb/mysql-test/patches/index_merge_innodb-explain.diff
@@ -0,0 +1,31 @@
+InnoDB's estimate for the index cardinality depends on a pseudo random
+number generator (it picks up random pages to sample). After an
+optimization that was made in r2625 the following EXPLAINs started
+returning a different number of rows (3 instead of 4).
+
+This patch adjusts the result file.
+
+This patch cannot be proposed to MySQL because the failures occur only
+in this tree and do not occur in the standard InnoDB 5.1. Furthermore,
+the file index_merge2.inc is used by other engines too.
+
+--- mysql-test/r/index_merge_innodb.result.orig 2008-09-30 18:32:13.000000000 +0300
++++ mysql-test/r/index_merge_innodb.result 2008-09-30 18:33:01.000000000 +0300
+@@ -111,7 +111,7 @@
+ explain select count(*) from t1 where
+ key1a = 2 and key1b is null and key2a = 2 and key2b is null;
+ id select_type table type possible_keys key key_len ref rows Extra
+-1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL 4 Using intersect(i1,i2); Using where; Using index
++1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL 3 Using intersect(i1,i2); Using where; Using index
+ select count(*) from t1 where
+ key1a = 2 and key1b is null and key2a = 2 and key2b is null;
+ count(*)
+@@ -119,7 +119,7 @@
+ explain select count(*) from t1 where
+ key1a = 2 and key1b is null and key3a = 2 and key3b is null;
+ id select_type table type possible_keys key key_len ref rows Extra
+-1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL 4 Using intersect(i1,i3); Using where; Using index
++1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL 3 Using intersect(i1,i3); Using where; Using index
+ select count(*) from t1 where
+ key1a = 2 and key1b is null and key3a = 2 and key3b is null;
+ count(*)
diff --git a/storage/xtradb/mysql-test/patches/information_schema.diff b/storage/xtradb/mysql-test/patches/information_schema.diff
new file mode 100644
index 00000000000..a3a21f7a08d
--- /dev/null
+++ b/storage/xtradb/mysql-test/patches/information_schema.diff
@@ -0,0 +1,124 @@
+--- mysql-test/r/information_schema.result.orig 2009-01-31 03:38:50.000000000 +0200
++++ mysql-test/r/information_schema.result 2009-01-31 07:51:58.000000000 +0200
+@@ -71,6 +71,13 @@
+ TRIGGERS
+ USER_PRIVILEGES
+ VIEWS
++INNODB_CMP_RESET
++INNODB_TRX
++INNODB_CMPMEM_RESET
++INNODB_LOCK_WAITS
++INNODB_CMPMEM
++INNODB_CMP
++INNODB_LOCKS
+ columns_priv
+ db
+ event
+@@ -799,6 +806,8 @@
+ TABLES UPDATE_TIME datetime
+ TABLES CHECK_TIME datetime
+ TRIGGERS CREATED datetime
++INNODB_TRX trx_started datetime
++INNODB_TRX trx_wait_started datetime
+ event execute_at datetime
+ event last_executed datetime
+ event starts datetime
+@@ -852,7 +861,7 @@
+ flush privileges;
+ SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA;
+ table_schema count(*)
+-information_schema 28
++information_schema 35
+ mysql 22
+ create table t1 (i int, j int);
+ create trigger trg1 before insert on t1 for each row
+@@ -1267,6 +1276,13 @@
+ TRIGGERS TRIGGER_SCHEMA
+ USER_PRIVILEGES GRANTEE
+ VIEWS TABLE_SCHEMA
++INNODB_CMP_RESET page_size
++INNODB_TRX trx_id
++INNODB_CMPMEM_RESET page_size
++INNODB_LOCK_WAITS requesting_trx_id
++INNODB_CMPMEM page_size
++INNODB_CMP page_size
++INNODB_LOCKS lock_id
+ SELECT t.table_name, c1.column_name
+ FROM information_schema.tables t
+ INNER JOIN
+@@ -1310,6 +1326,13 @@
+ TRIGGERS TRIGGER_SCHEMA
+ USER_PRIVILEGES GRANTEE
+ VIEWS TABLE_SCHEMA
++INNODB_CMP_RESET page_size
++INNODB_TRX trx_id
++INNODB_CMPMEM_RESET page_size
++INNODB_LOCK_WAITS requesting_trx_id
++INNODB_CMPMEM page_size
++INNODB_CMP page_size
++INNODB_LOCKS lock_id
+ SELECT MAX(table_name) FROM information_schema.tables WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test');
+ MAX(table_name)
+ VIEWS
+@@ -1386,6 +1409,13 @@
+ FILES information_schema.FILES 1
+ GLOBAL_STATUS information_schema.GLOBAL_STATUS 1
+ GLOBAL_VARIABLES information_schema.GLOBAL_VARIABLES 1
++INNODB_CMP information_schema.INNODB_CMP 1
++INNODB_CMPMEM information_schema.INNODB_CMPMEM 1
++INNODB_CMPMEM_RESET information_schema.INNODB_CMPMEM_RESET 1
++INNODB_CMP_RESET information_schema.INNODB_CMP_RESET 1
++INNODB_LOCKS information_schema.INNODB_LOCKS 1
++INNODB_LOCK_WAITS information_schema.INNODB_LOCK_WAITS 1
++INNODB_TRX information_schema.INNODB_TRX 1
+ KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
+ PARTITIONS information_schema.PARTITIONS 1
+ PLUGINS information_schema.PLUGINS 1
+diff mysql-test/r/information_schema_db.result.orig mysql-test/r/information_schema_db.result
+--- mysql-test/r/information_schema_db.result.orig 2008-08-04 09:27:49.000000000 +0300
++++ mysql-test/r/information_schema_db.result 2008-10-07 12:26:31.000000000 +0300
+@@ -33,6 +33,13 @@
+ TRIGGERS
+ USER_PRIVILEGES
+ VIEWS
++INNODB_CMP_RESET
++INNODB_TRX
++INNODB_CMPMEM_RESET
++INNODB_LOCK_WAITS
++INNODB_CMPMEM
++INNODB_CMP
++INNODB_LOCKS
+ show tables from INFORMATION_SCHEMA like 'T%';
+ Tables_in_information_schema (T%)
+ TABLES
+diff mysql-test/r/mysqlshow.result.orig mysql-test/r/mysqlshow.result
+--- mysql-test/r/mysqlshow.result.orig 2008-08-04 09:27:51.000000000 +0300
++++ mysql-test/r/mysqlshow.result 2008-10-07 12:35:39.000000000 +0300
+@@ -107,6 +107,13 @@
+ | TRIGGERS |
+ | USER_PRIVILEGES |
+ | VIEWS |
++| INNODB_CMP_RESET |
++| INNODB_TRX |
++| INNODB_CMPMEM_RESET |
++| INNODB_LOCK_WAITS |
++| INNODB_CMPMEM |
++| INNODB_CMP |
++| INNODB_LOCKS |
+ +---------------------------------------+
+ Database: INFORMATION_SCHEMA
+ +---------------------------------------+
+@@ -140,6 +147,13 @@
+ | TRIGGERS |
+ | USER_PRIVILEGES |
+ | VIEWS |
++| INNODB_CMP_RESET |
++| INNODB_TRX |
++| INNODB_CMPMEM_RESET |
++| INNODB_LOCK_WAITS |
++| INNODB_CMPMEM |
++| INNODB_CMP |
++| INNODB_LOCKS |
+ +---------------------------------------+
+ Wildcard: inf_rmation_schema
+ +--------------------+
diff --git a/storage/xtradb/mysql-test/patches/innodb_file_per_table.diff b/storage/xtradb/mysql-test/patches/innodb_file_per_table.diff
new file mode 100644
index 00000000000..8b7ae2036c9
--- /dev/null
+++ b/storage/xtradb/mysql-test/patches/innodb_file_per_table.diff
@@ -0,0 +1,47 @@
+diff mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test.orig mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test
+--- mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test.orig 2008-10-07 11:32:30.000000000 +0300
++++ mysql-test/suite/sys_vars/t/innodb_file_per_table_basic.test 2008-10-07 11:52:14.000000000 +0300
+@@ -37,10 +37,6 @@
+ # Check if Value can set #
+ ####################################################################
+
+---error ER_INCORRECT_GLOBAL_LOCAL_VAR
+-SET @@GLOBAL.innodb_file_per_table=1;
+---echo Expected error 'Read only variable'
+-
+ SELECT COUNT(@@GLOBAL.innodb_file_per_table);
+ --echo 1 Expected
+
+@@ -52,7 +48,7 @@
+ # Check if the value in GLOBAL Table matches value in variable #
+ #################################################################
+
+-SELECT @@GLOBAL.innodb_file_per_table = VARIABLE_VALUE
++SELECT IF(@@GLOBAL.innodb_file_per_table,'ON','OFF') = VARIABLE_VALUE
+ FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+ WHERE VARIABLE_NAME='innodb_file_per_table';
+ --echo 1 Expected
+diff mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result.orig mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result
+--- mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result.orig 2008-10-07 11:32:02.000000000 +0300
++++ mysql-test/suite/sys_vars/r/innodb_file_per_table_basic.result 2008-10-07 11:52:47.000000000 +0300
+@@ -4,18 +4,15 @@
+ 1
+ 1 Expected
+ '#---------------------BS_STVARS_028_02----------------------#'
+-SET @@GLOBAL.innodb_file_per_table=1;
+-ERROR HY000: Variable 'innodb_file_per_table' is a read only variable
+-Expected error 'Read only variable'
+ SELECT COUNT(@@GLOBAL.innodb_file_per_table);
+ COUNT(@@GLOBAL.innodb_file_per_table)
+ 1
+ 1 Expected
+ '#---------------------BS_STVARS_028_03----------------------#'
+-SELECT @@GLOBAL.innodb_file_per_table = VARIABLE_VALUE
++SELECT IF(@@GLOBAL.innodb_file_per_table,'ON','OFF') = VARIABLE_VALUE
+ FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+ WHERE VARIABLE_NAME='innodb_file_per_table';
+-@@GLOBAL.innodb_file_per_table = VARIABLE_VALUE
++IF(@@GLOBAL.innodb_file_per_table,'ON','OFF') = VARIABLE_VALUE
+ 1
+ 1 Expected
+ SELECT COUNT(@@GLOBAL.innodb_file_per_table);
diff --git a/storage/xtradb/mysql-test/patches/innodb_lock_wait_timeout.diff b/storage/xtradb/mysql-test/patches/innodb_lock_wait_timeout.diff
new file mode 100644
index 00000000000..bc61a0f5841
--- /dev/null
+++ b/storage/xtradb/mysql-test/patches/innodb_lock_wait_timeout.diff
@@ -0,0 +1,55 @@
+--- mysql-test/suite/sys_vars/t/innodb_lock_wait_timeout_basic.test.orig 2008-08-04 09:28:16.000000000 +0300
++++ mysql-test/suite/sys_vars/t/innodb_lock_wait_timeout_basic.test 2008-10-07 11:14:15.000000000 +0300
+@@ -37,10 +37,6 @@
+ # Check if Value can set #
+ ####################################################################
+
+---error ER_INCORRECT_GLOBAL_LOCAL_VAR
+-SET @@GLOBAL.innodb_lock_wait_timeout=1;
+---echo Expected error 'Read only variable'
+-
+ SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
+ --echo 1 Expected
+
+@@ -84,13 +80,9 @@
+ SELECT COUNT(@@innodb_lock_wait_timeout);
+ --echo 1 Expected
+
+---Error ER_INCORRECT_GLOBAL_LOCAL_VAR
+ SELECT COUNT(@@local.innodb_lock_wait_timeout);
+---echo Expected error 'Variable is a GLOBAL variable'
+
+---Error ER_INCORRECT_GLOBAL_LOCAL_VAR
+ SELECT COUNT(@@SESSION.innodb_lock_wait_timeout);
+---echo Expected error 'Variable is a GLOBAL variable'
+
+ SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
+ --echo 1 Expected
+--- mysql-test/suite/sys_vars/r/innodb_lock_wait_timeout_basic.result.orig 2008-08-04 09:27:50.000000000 +0300
++++ mysql-test/suite/sys_vars/r/innodb_lock_wait_timeout_basic.result 2008-10-07 11:15:14.000000000 +0300
+@@ -4,9 +4,6 @@
+ 1
+ 1 Expected
+ '#---------------------BS_STVARS_032_02----------------------#'
+-SET @@GLOBAL.innodb_lock_wait_timeout=1;
+-ERROR HY000: Variable 'innodb_lock_wait_timeout' is a read only variable
+-Expected error 'Read only variable'
+ SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
+ COUNT(@@GLOBAL.innodb_lock_wait_timeout)
+ 1
+@@ -39,11 +36,11 @@
+ 1
+ 1 Expected
+ SELECT COUNT(@@local.innodb_lock_wait_timeout);
+-ERROR HY000: Variable 'innodb_lock_wait_timeout' is a GLOBAL variable
+-Expected error 'Variable is a GLOBAL variable'
++COUNT(@@local.innodb_lock_wait_timeout)
++1
+ SELECT COUNT(@@SESSION.innodb_lock_wait_timeout);
+-ERROR HY000: Variable 'innodb_lock_wait_timeout' is a GLOBAL variable
+-Expected error 'Variable is a GLOBAL variable'
++COUNT(@@SESSION.innodb_lock_wait_timeout)
++1
+ SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
+ COUNT(@@GLOBAL.innodb_lock_wait_timeout)
+ 1
diff --git a/storage/xtradb/mysql-test/patches/innodb_thread_concurrency_basic.diff b/storage/xtradb/mysql-test/patches/innodb_thread_concurrency_basic.diff
new file mode 100644
index 00000000000..72e5457905f
--- /dev/null
+++ b/storage/xtradb/mysql-test/patches/innodb_thread_concurrency_basic.diff
@@ -0,0 +1,31 @@
+--- mysql-test/suite/sys_vars/r/innodb_thread_concurrency_basic.result.orig 2008-12-04 18:45:52 -06:00
++++ mysql-test/suite/sys_vars/r/innodb_thread_concurrency_basic.result 2009-02-12 02:05:48 -06:00
+@@ -1,19 +1,19 @@
+ SET @global_start_value = @@global.innodb_thread_concurrency;
+ SELECT @global_start_value;
+ @global_start_value
+-8
++0
+ '#--------------------FN_DYNVARS_046_01------------------------#'
+ SET @@global.innodb_thread_concurrency = 0;
+ SET @@global.innodb_thread_concurrency = DEFAULT;
+ SELECT @@global.innodb_thread_concurrency;
+ @@global.innodb_thread_concurrency
+-8
++0
+ '#---------------------FN_DYNVARS_046_02-------------------------#'
+ SET innodb_thread_concurrency = 1;
+ ERROR HY000: Variable 'innodb_thread_concurrency' is a GLOBAL variable and should be set with SET GLOBAL
+ SELECT @@innodb_thread_concurrency;
+ @@innodb_thread_concurrency
+-8
++0
+ SELECT local.innodb_thread_concurrency;
+ ERROR 42S02: Unknown table 'local' in field list
+ SET global innodb_thread_concurrency = 0;
+@@ -93,4 +93,4 @@
+ SET @@global.innodb_thread_concurrency = @global_start_value;
+ SELECT @@global.innodb_thread_concurrency;
+ @@global.innodb_thread_concurrency
+-8
++0
diff --git a/storage/xtradb/mysql-test/patches/partition_innodb.diff b/storage/xtradb/mysql-test/patches/partition_innodb.diff
new file mode 100644
index 00000000000..01bc073008e
--- /dev/null
+++ b/storage/xtradb/mysql-test/patches/partition_innodb.diff
@@ -0,0 +1,59 @@
+The partition_innodb test only fails if run immediately after innodb_trx_weight.
+The reason for this failure is that innodb_trx_weight creates deadlocks and
+leaves something like this in the SHOW ENGINE INNODB STATUS output:
+
+ ------------------------
+ LATEST DETECTED DEADLOCK
+ ------------------------
+ 090213 10:26:25
+ *** (1) TRANSACTION:
+ TRANSACTION 313, ACTIVE 0 sec, OS thread id 13644672 inserting
+ mysql tables in use 1, locked 1
+ LOCK WAIT 4 lock struct(s), heap size 488, 3 row lock(s)
+ MySQL thread id 3, query id 36 localhost root update
+
+The regular expressions that partition_innodb is using are intended to extract
+the lock structs and row locks numbers from another part of the output:
+
+ ------------
+ TRANSACTIONS
+ ------------
+ Trx id counter 31D
+ Purge done for trx's n:o < 0 undo n:o < 0
+ History list length 4
+ LIST OF TRANSACTIONS FOR EACH SESSION:
+ ---TRANSACTION 0, not started, OS thread id 13645056
+ 0 lock struct(s), heap size 488, 0 row lock(s)
+ MySQL thread id 8, query id 81 localhost root
+
+In the InnoDB Plugin a transaction id is not printed as 2 consecutive
+decimal integers (as it is in InnoDB 5.1) but rather as a single
+hexadecimal integer. Thus the regular expressions somehow pick the wrong
+part of the SHOW ENGINE INNODB STATUS output.
+
+So after the regular expressions are adjusted to the InnoDB Plugin's variant
+of trx_id prinout, then they pick the expected part of the output.
+
+This patch cannot be proposed to MySQL because the failures occur only
+in this tree and do not occur in the standard InnoDB 5.1.
+
+--- mysql-test/t/partition_innodb.test 2008-11-14 22:51:17 +0000
++++ mysql-test/t/partition_innodb.test 2009-02-13 07:36:07 +0000
+@@ -27,14 +27,14 @@
+
+ # grouping/referencing in replace_regex is very slow on long strings,
+ # removing all before/after the interesting row before grouping/referencing
+---replace_regex /.*---TRANSACTION [0-9]+ [0-9]+, .*, OS thread id [0-9]+// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
++--replace_regex /.*---TRANSACTION [0-9A-F]+, .*, OS thread id [0-9]+// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
+ SHOW ENGINE InnoDB STATUS;
+
+ UPDATE t1 SET data = data*2 WHERE data = 2;
+
+ # grouping/referencing in replace_regex is very slow on long strings,
+ # removing all before/after the interesting row before grouping/referencing
+---replace_regex /.*---TRANSACTION [0-9]+ [0-9]+, .*, OS thread id [0-9]+// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
++--replace_regex /.*---TRANSACTION [0-9A-F]+, .*, OS thread id [0-9]+// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
+ SHOW ENGINE InnoDB STATUS;
+
+ SET @@session.tx_isolation = @old_tx_isolation;
+
diff --git a/storage/xtradb/os/os0file.c b/storage/xtradb/os/os0file.c
index b502be1eb00..ef048188353 100644
--- a/storage/xtradb/os/os0file.c
+++ b/storage/xtradb/os/os0file.c
@@ -3593,13 +3593,12 @@ os_aio_simulated_wake_handler_thread(
{
os_aio_array_t* array;
os_aio_slot_t* slot;
- ulint segment __attribute__ ((unused));
ulint n;
ulint i;
ut_ad(!os_aio_use_native_aio);
- segment = os_aio_get_array_and_local_segment(&array, global_segment);
+ os_aio_get_array_and_local_segment(&array, global_segment);
n = array->n_slots;
@@ -4079,7 +4078,6 @@ os_aio_simulated_handle(
ulint* space_id)
{
os_aio_array_t* array;
- ulint segment __attribute__ ((unused));
os_aio_slot_t* slot;
os_aio_slot_t* slot2;
os_aio_slot_t* consecutive_ios[OS_AIO_MERGE_N_CONSECUTIVE];
@@ -4102,7 +4100,7 @@ os_aio_simulated_handle(
/* Fix compiler warning */
*consecutive_ios = NULL;
- segment = os_aio_get_array_and_local_segment(&array, global_segment);
+ os_aio_get_array_and_local_segment(&array, global_segment);
restart:
/* NOTE! We only access constant fields in os_aio_array. Therefore
@@ -4111,7 +4109,6 @@ restart:
srv_set_io_thread_op_info(global_segment,
"looking for i/o requests (a)");
ut_ad(os_aio_validate());
- ut_ad(segment < array->n_segments);
n = array->n_slots;
diff --git a/storage/xtradb/os/os0proc.c b/storage/xtradb/os/os0proc.c
index 48922886f23..a0679e31570 100644
--- a/storage/xtradb/os/os0proc.c
+++ b/storage/xtradb/os/os0proc.c
@@ -111,9 +111,6 @@ os_mem_alloc_large(
os_fast_mutex_lock(&ut_list_mutex);
ut_total_allocated_memory += size;
os_fast_mutex_unlock(&ut_list_mutex);
-# ifdef UNIV_SET_MEM_TO_ZERO
- memset(ptr, '\0', size);
-# endif
UNIV_MEM_ALLOC(ptr, size);
return(ptr);
}
diff --git a/storage/xtradb/page/page0cur.c b/storage/xtradb/page/page0cur.c
index b8c492328e8..88ee6bc09a9 100644
--- a/storage/xtradb/page/page0cur.c
+++ b/storage/xtradb/page/page0cur.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
diff --git a/storage/xtradb/page/page0page.c b/storage/xtradb/page/page0page.c
index 6243029019d..7b72a22fd1c 100644
--- a/storage/xtradb/page/page0page.c
+++ b/storage/xtradb/page/page0page.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -215,12 +215,6 @@ page_set_max_trx_id(
{
page_t* page = buf_block_get_frame(block);
#ifndef UNIV_HOTBACKUP
- const ibool is_hashed = block->is_hashed;
-
- if (is_hashed) {
- rw_lock_x_lock(&btr_search_latch);
- }
-
ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
#endif /* !UNIV_HOTBACKUP */
@@ -241,12 +235,6 @@ page_set_max_trx_id(
} else {
mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id);
}
-
-#ifndef UNIV_HOTBACKUP
- if (is_hashed) {
- rw_lock_x_unlock(&btr_search_latch);
- }
-#endif /* !UNIV_HOTBACKUP */
}
/************************************************************//**
@@ -1632,6 +1620,7 @@ page_rec_print(
rec_validate(rec, offsets);
}
+# ifdef UNIV_BTR_PRINT
/***************************************************************//**
This is used to print the contents of the directory for
debugging purposes. */
@@ -1792,6 +1781,7 @@ page_print(
page_dir_print(page, dn);
page_print_list(block, index, rn);
}
+# endif /* UNIV_BTR_PRINT */
#endif /* !UNIV_HOTBACKUP */
/***************************************************************//**
diff --git a/storage/xtradb/revert_gen.sh b/storage/xtradb/revert_gen.sh
new file mode 100644
index 00000000000..231e05a21e0
--- /dev/null
+++ b/storage/xtradb/revert_gen.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+#
+# revert changes to all generated files. this is useful in some situations
+# when merging changes between branches.
+
+set -eu
+
+svn revert include/pars0grm.h pars/pars0grm.h pars/lexyy.c pars/pars0grm.c
diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c
index 0bcbc14fbf6..d6f486e5c1b 100644
--- a/storage/xtradb/row/row0ins.c
+++ b/storage/xtradb/row/row0ins.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -23,6 +23,15 @@ Insert into a table
Created 4/20/1996 Heikki Tuuri
*******************************************************/
+#ifdef __WIN__
+/* error LNK2001: unresolved external symbol _debug_sync_C_callback_ptr */
+# define DEBUG_SYNC_C(dummy) ((void) 0)
+#else
+# include "my_global.h" /* HAVE_* */
+# include "m_string.h" /* for my_sys.h */
+# include "my_sys.h" /* DEBUG_SYNC_C */
+#endif
+
#include "row0ins.h"
#ifdef UNIV_NONINL
@@ -1093,6 +1102,9 @@ row_ins_foreign_check_on_constraint(
release the latch. */
row_mysql_unfreeze_data_dictionary(thr_get_trx(thr));
+
+ DEBUG_SYNC_C("innodb_dml_cascade_dict_unfreeze");
+
row_mysql_freeze_data_dictionary(thr_get_trx(thr));
mtr_start(mtr);
@@ -1676,7 +1688,7 @@ row_ins_scan_sec_index_for_duplicate(
ulint n_fields_cmp;
btr_pcur_t pcur;
ulint err = DB_SUCCESS;
- unsigned allow_duplicates;
+ ulint allow_duplicates;
mtr_t mtr;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
@@ -1707,7 +1719,7 @@ row_ins_scan_sec_index_for_duplicate(
btr_pcur_open(index, entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr);
- allow_duplicates = thr_get_trx(thr)->duplicates & TRX_DUP_IGNORE;
+ allow_duplicates = thr_get_trx(thr)->duplicates;
/* Scan index records and check if there is a duplicate */
@@ -1841,7 +1853,7 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate
errors as in original execution */
- if (trx->duplicates & TRX_DUP_IGNORE) {
+ if (trx->duplicates) {
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
@@ -1885,7 +1897,7 @@ row_ins_duplicate_error_in_clust(
offsets = rec_get_offsets(rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap);
- if (trx->duplicates & TRX_DUP_IGNORE) {
+ if (trx->duplicates) {
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
@@ -2111,23 +2123,39 @@ row_ins_index_entry_low(
ut_a(err == DB_SUCCESS);
/* Write out the externally stored
columns while still x-latching
- index->lock and block->lock. We have
- to mtr_commit(mtr) first, so that the
- redo log will be written in the
- correct order. Otherwise, we would run
- into trouble on crash recovery if mtr
- freed B-tree pages on which some of
- the big_rec fields will be written. */
- btr_cur_mtr_commit_and_start(&cursor, &mtr);
+ index->lock and block->lock. Allocate
+ pages for big_rec in the mtr that
+ modified the B-tree, but be sure to skip
+ any pages that were freed in mtr. We will
+ write out the big_rec pages before
+ committing the B-tree mini-transaction. If
+ the system crashes so that crash recovery
+ will not replay the mtr_commit(&mtr), the
+ big_rec pages will be left orphaned until
+ the pages are allocated for something else.
+
+ TODO: If the allocation extends the
+ tablespace, it will not be redo
+ logged, in either mini-transaction.
+ Tablespace extension should be
+ redo-logged in the big_rec
+ mini-transaction, so that recovery
+ will not fail when the big_rec was
+ written to the extended portion of the
+ file, in case the file was somehow
+ truncated in the crash. */
rec = btr_cur_get_rec(&cursor);
offsets = rec_get_offsets(
rec, index, NULL,
ULINT_UNDEFINED, &heap);
+ DEBUG_SYNC_C("before_row_ins_upd_extern");
err = btr_store_big_rec_extern_fields(
index, btr_cur_get_block(&cursor),
- rec, offsets, &mtr, FALSE, big_rec);
+ rec, offsets, big_rec, &mtr,
+ BTR_STORE_INSERT_UPDATE);
+ DEBUG_SYNC_C("after_row_ins_upd_extern");
/* If writing big_rec fails (for
example, because of DB_OUT_OF_FILE_SPACE),
the record will be corrupted. Even if
@@ -2138,7 +2166,13 @@ row_ins_index_entry_low(
external storage. This non-update
would not have been written to the
undo log, and thus the record cannot
- be rolled back. */
+ be rolled back.
+
+ However, because we have not executed
+ mtr_commit(mtr) yet, the update will
+ not be replayed in crash recovery, and
+ the following assertion failure will
+ effectively "roll back" the operation. */
ut_a(err == DB_SUCCESS);
goto stored_big_rec;
}
@@ -2170,6 +2204,8 @@ function_exit:
mtr_commit(&mtr);
if (UNIV_LIKELY_NULL(big_rec)) {
+ rec_t* rec;
+ ulint* offsets;
if (thr_get_trx(thr)->fake_changes) {
/* skip store extern */
@@ -2186,8 +2222,13 @@ function_exit:
return(err);
}
+ DBUG_EXECUTE_IF(
+ "row_ins_extern_checkpoint",
+ log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE););
+
mtr_start(&mtr);
+ DEBUG_SYNC_C("before_row_ins_extern_latch");
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, 0,
__FILE__, __LINE__, &mtr);
@@ -2195,9 +2236,11 @@ function_exit:
offsets = rec_get_offsets(rec, index, NULL,
ULINT_UNDEFINED, &heap);
+ DEBUG_SYNC_C("before_row_ins_extern");
err = btr_store_big_rec_extern_fields(
index, btr_cur_get_block(&cursor),
- rec, offsets, &mtr, FALSE, big_rec);
+ rec, offsets, big_rec, &mtr, BTR_STORE_INSERT);
+ DEBUG_SYNC_C("after_row_ins_extern");
stored_big_rec:
if (modify) {
diff --git a/storage/xtradb/row/row0merge.c b/storage/xtradb/row/row0merge.c
index 782c029fbcc..efff92aa361 100644
--- a/storage/xtradb/row/row0merge.c
+++ b/storage/xtradb/row/row0merge.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -576,7 +576,7 @@ row_merge_buf_write(
REC_STATUS_ORDINARY,
entry, n_fields,
&extra_size);
- ut_ad(size > extra_size);
+ ut_ad(size >= extra_size);
ut_ad(extra_size >= REC_N_NEW_EXTRA_BYTES);
extra_size -= REC_N_NEW_EXTRA_BYTES;
size -= REC_N_NEW_EXTRA_BYTES;
@@ -2019,7 +2019,7 @@ row_merge_drop_index(
tables in Innobase. Deleting a row from SYS_INDEXES table also
frees the file segments of the B-tree associated with the index. */
- static const char str1[] =
+ static const char sql[] =
"PROCEDURE DROP_INDEX_PROC () IS\n"
"BEGIN\n"
/* Rename the index, so that it will be dropped by
@@ -2045,9 +2045,19 @@ row_merge_drop_index(
ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
- err = que_eval_sql(info, str1, FALSE, trx);
+ err = que_eval_sql(info, sql, FALSE, trx);
- ut_a(err == DB_SUCCESS);
+
+ if (err != DB_SUCCESS) {
+ /* Even though we ensure that DDL transactions are WAIT
+ and DEADLOCK free, we could encounter other errors e.g.,
+ DB_TOO_MANY_TRANSACTIONS. */
+ trx->error_state = DB_SUCCESS;
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Error: row_merge_drop_index failed "
+ "with error code: %lu.\n", (ulint) err);
+ }
/* Replace this index with another equivalent index for all
foreign key constraints on this table where this index is used */
@@ -2299,7 +2309,7 @@ row_merge_rename_indexes(
/* We use the private SQL parser of Innobase to generate the
query graphs needed in renaming indexes. */
- static const char rename_indexes[] =
+ static const char sql[] =
"PROCEDURE RENAME_INDEXES_PROC () IS\n"
"BEGIN\n"
"UPDATE SYS_INDEXES SET NAME=SUBSTR(NAME,1,LENGTH(NAME)-1)\n"
@@ -2315,7 +2325,7 @@ row_merge_rename_indexes(
pars_info_add_dulint_literal(info, "tableid", table->id);
- err = que_eval_sql(info, rename_indexes, FALSE, trx);
+ err = que_eval_sql(info, sql, FALSE, trx);
if (err == DB_SUCCESS) {
dict_index_t* index = dict_table_get_first_index(table);
@@ -2325,6 +2335,15 @@ row_merge_rename_indexes(
}
index = dict_table_get_next_index(index);
} while (index);
+ } else {
+ /* Even though we ensure that DDL transactions are WAIT
+ and DEADLOCK free, we could encounter other errors e.g.,
+ DB_TOO_MANY_TRANSACTIONS. */
+ trx->error_state = DB_SUCCESS;
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Error: row_merge_rename_indexes "
+ "failed with error code: %lu.\n", (ulint) err);
}
trx->op_info = "";
@@ -2363,7 +2382,7 @@ row_merge_rename_tables(
memcpy(old_name, old_table->name, strlen(old_table->name) + 1);
} else {
ut_print_timestamp(stderr);
- fprintf(stderr, "InnoDB: too long table name: '%s', "
+ fprintf(stderr, " InnoDB: too long table name: '%s', "
"max length is %d\n", old_table->name,
MAX_FULL_NAME_LEN);
ut_error;
diff --git a/storage/xtradb/row/row0mysql.c b/storage/xtradb/row/row0mysql.c
index cb003ad62e0..07cb1578024 100644
--- a/storage/xtradb/row/row0mysql.c
+++ b/storage/xtradb/row/row0mysql.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 2000, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -54,6 +54,14 @@ Created 9/17/2000 Heikki Tuuri
#include "ibuf0ibuf.h"
#include "ha_prototypes.h"
+#ifdef __WIN__
+/* error LNK2001: unresolved external symbol _debug_sync_C_callback_ptr */
+# define DEBUG_SYNC_C(dummy) ((void) 0)
+#else
+# include "m_string.h" /* for my_sys.h */
+# include "my_sys.h" /* DEBUG_SYNC_C */
+#endif
+
/** Provide optional 4.x backwards compatibility for 5.0 and above */
UNIV_INTERN ibool row_rollback_on_timeout = FALSE;
@@ -1363,6 +1371,8 @@ row_update_for_mysql(
return(DB_ERROR);
}
+ DEBUG_SYNC_C("innodb_row_update_for_mysql_begin");
+
trx->op_info = "updating or deleting";
row_mysql_delay_if_needed();
@@ -1915,6 +1925,20 @@ err_exit:
}
break;
+ case DB_TOO_MANY_CONCURRENT_TRXS:
+ /* We already have .ibd file here. it should be deleted. */
+
+ if (table->space && !fil_delete_tablespace(table->space)) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Error: not able to"
+ " delete tablespace %lu of table ",
+ (ulong) table->space);
+ ut_print_name(stderr, trx, TRUE, table->name);
+ fputs("!\n", stderr);
+ }
+ /* fall through */
+
case DB_DUPLICATE_KEY:
default:
/* We may also get err == DB_ERROR if the .ibd file for the
@@ -2709,7 +2733,7 @@ row_import_tablespace_for_mysql(
success = fil_open_single_table_tablespace(
TRUE, table->space,
table->flags == DICT_TF_COMPACT ? 0 : table->flags,
- table->name);
+ table->name, trx);
if (success) {
table->ibd_file_missing = FALSE;
table->tablespace_discarded = FALSE;
@@ -3121,6 +3145,7 @@ row_drop_table_for_mysql(
{
dict_foreign_t* foreign;
dict_table_t* table;
+ dict_index_t* index;
ulint space_id;
ulint err;
const char* table_name;
@@ -3327,6 +3352,18 @@ check_next_foreign:
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
trx->table_id = table->id;
+ /* Mark all indexes unavailable in the data dictionary cache
+ before starting to drop the table. */
+
+ for (index = dict_table_get_first_index(table);
+ index != NULL;
+ index = dict_table_get_next_index(index)) {
+ rw_lock_x_lock(dict_index_get_lock(index));
+ ut_ad(!index->to_be_dropped);
+ index->to_be_dropped = TRUE;
+ rw_lock_x_unlock(dict_index_get_lock(index));
+ }
+
/* We use the private SQL parser of Innobase to generate the
query graphs needed in deleting the dictionary data from system
tables in Innobase. Deleting a row from SYS_INDEXES table also
@@ -3343,6 +3380,19 @@ check_next_foreign:
"index_id CHAR;\n"
"foreign_id CHAR;\n"
"found INT;\n"
+
+ "DECLARE CURSOR cur_fk IS\n"
+ "SELECT ID FROM SYS_FOREIGN\n"
+ "WHERE FOR_NAME = :table_name\n"
+ "AND TO_BINARY(FOR_NAME)\n"
+ " = TO_BINARY(:table_name)\n"
+ "LOCK IN SHARE MODE;\n"
+
+ "DECLARE CURSOR cur_idx IS\n"
+ "SELECT ID FROM SYS_INDEXES\n"
+ "WHERE TABLE_ID = table_id\n"
+ "LOCK IN SHARE MODE;\n"
+
"BEGIN\n"
"SELECT ID INTO table_id\n"
"FROM SYS_TABLES\n"
@@ -3365,13 +3415,9 @@ check_next_foreign:
"IF (:table_name = 'SYS_FOREIGN_COLS') THEN\n"
" found := 0;\n"
"END IF;\n"
+ "OPEN cur_fk;\n"
"WHILE found = 1 LOOP\n"
- " SELECT ID INTO foreign_id\n"
- " FROM SYS_FOREIGN\n"
- " WHERE FOR_NAME = :table_name\n"
- " AND TO_BINARY(FOR_NAME)\n"
- " = TO_BINARY(:table_name)\n"
- " LOCK IN SHARE MODE;\n"
+ " FETCH cur_fk INTO foreign_id;\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE\n"
@@ -3381,12 +3427,11 @@ check_next_foreign:
" WHERE ID = foreign_id;\n"
" END IF;\n"
"END LOOP;\n"
+ "CLOSE cur_fk;\n"
"found := 1;\n"
+ "OPEN cur_idx;\n"
"WHILE found = 1 LOOP\n"
- " SELECT ID INTO index_id\n"
- " FROM SYS_INDEXES\n"
- " WHERE TABLE_ID = table_id\n"
- " LOCK IN SHARE MODE;\n"
+ " FETCH cur_idx INTO index_id;\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE\n"
@@ -3399,6 +3444,7 @@ check_next_foreign:
" AND TABLE_ID = table_id;\n"
" END IF;\n"
"END LOOP;\n"
+ "CLOSE cur_idx;\n"
"DELETE FROM SYS_COLUMNS\n"
"WHERE TABLE_ID = table_id;\n"
"DELETE FROM SYS_TABLES\n"
@@ -3485,6 +3531,17 @@ check_next_foreign:
the undo log. We can directly exit here
and return the DB_TOO_MANY_CONCURRENT_TRXS
error. */
+
+ /* Mark all indexes available in the data dictionary
+ cache again. */
+
+ for (index = dict_table_get_first_index(table);
+ index != NULL;
+ index = dict_table_get_next_index(index)) {
+ rw_lock_x_lock(dict_index_get_lock(index));
+ index->to_be_dropped = FALSE;
+ rw_lock_x_unlock(dict_index_get_lock(index));
+ }
break;
case DB_OUT_OF_FILE_SPACE:
@@ -3842,6 +3899,7 @@ row_rename_table_for_mysql(
ulint n_constraints_to_drop = 0;
ibool old_is_tmp, new_is_tmp;
pars_info_t* info = NULL;
+ ulint retry = 0;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_a(old_name != NULL);
@@ -3925,6 +3983,25 @@ row_rename_table_for_mysql(
}
}
+ /* Is a foreign key check running on this table? */
+ for (retry = 0; retry < 100
+ && table->n_foreign_key_checks_running > 0; ++retry) {
+ row_mysql_unlock_data_dictionary(trx);
+ os_thread_yield();
+ row_mysql_lock_data_dictionary(trx);
+ }
+
+ if (table->n_foreign_key_checks_running > 0) {
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: Error: in ALTER TABLE ", stderr);
+ ut_print_name(stderr, trx, TRUE, old_name);
+ fprintf(stderr, "\n"
+ "InnoDB: a FOREIGN KEY check is running.\n"
+ "InnoDB: Cannot rename table.\n");
+ err = DB_TABLE_IN_FK_CHECK;
+ goto funct_exit;
+ }
+
/* We use the private SQL parser of Innobase to generate the query
graphs needed in updating the dictionary data from system tables. */
@@ -4086,6 +4163,7 @@ end:
trx->error_state = DB_SUCCESS;
trx_general_rollback_for_mysql(trx, NULL);
trx->error_state = DB_SUCCESS;
+ err = DB_ERROR;
goto funct_exit;
}
diff --git a/storage/xtradb/row/row0purge.c b/storage/xtradb/row/row0purge.c
index 752a2ec9e83..4d4c1afc458 100644
--- a/storage/xtradb/row/row0purge.c
+++ b/storage/xtradb/row/row0purge.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -406,7 +406,8 @@ row_purge_upd_exist_or_extern_func(
ut_ad(node);
- if (node->rec_type == TRX_UNDO_UPD_DEL_REC) {
+ if (node->rec_type == TRX_UNDO_UPD_DEL_REC
+ || (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
goto skip_secondaries;
}
@@ -530,14 +531,14 @@ row_purge_parse_undo_rec(
roll_ptr_t roll_ptr;
ulint info_bits;
ulint type;
- ulint cmpl_info;
ut_ad(node && thr);
trx = thr_get_trx(thr);
- ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info,
- updated_extern, &undo_no, &table_id);
+ ptr = trx_undo_rec_get_pars(
+ node->undo_rec, &type, &node->cmpl_info,
+ updated_extern, &undo_no, &table_id);
node->rec_type = type;
if (type == TRX_UNDO_UPD_DEL_REC && !(*updated_extern)) {
@@ -550,7 +551,8 @@ row_purge_parse_undo_rec(
node->table = NULL;
if (type == TRX_UNDO_UPD_EXIST_REC
- && cmpl_info & UPD_NODE_NO_ORD_CHANGE && !(*updated_extern)) {
+ && node->cmpl_info & UPD_NODE_NO_ORD_CHANGE
+ && !(*updated_extern)) {
/* Purge requires no changes to indexes: we may return */
@@ -600,7 +602,7 @@ err_exit:
/* Read to the partial row the fields that occur in indexes */
- if (!(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
+ if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
ptr = trx_undo_rec_get_partial_row(
ptr, clust_index, &node->row,
type == TRX_UNDO_UPD_DEL_REC,
diff --git a/storage/xtradb/row/row0row.c b/storage/xtradb/row/row0row.c
index cea70e98dee..380d438c59a 100644
--- a/storage/xtradb/row/row0row.c
+++ b/storage/xtradb/row/row0row.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -243,19 +243,16 @@ row_build(
}
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
- /* This condition can occur during crash recovery before
- trx_rollback_active() has completed execution.
-
- This condition is possible if the server crashed
- during an insert or update before
- btr_store_big_rec_extern_fields() did mtr_commit() all
- BLOB pointers to the clustered index record.
-
- If the record contains a null BLOB pointer, look up the
- transaction that holds the implicit lock on this record, and
- assert that it was recovered (and will soon be rolled back). */
- ut_a(!rec_offs_any_null_extern(rec, offsets)
- || trx_assert_recovered(row_get_rec_trx_id(rec, index, offsets)));
+ if (rec_offs_any_null_extern(rec, offsets)) {
+ /* This condition can occur during crash recovery
+ before trx_rollback_active() has completed execution,
+ or when a concurrently executing
+ row_ins_index_entry_low() has committed the B-tree
+ mini-transaction but has not yet managed to restore
+ the cursor position for writing the big_rec. */
+ ut_a(trx_undo_roll_ptr_is_insert(
+ row_get_rec_roll_ptr(rec, index, offsets)));
+ }
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
if (type != ROW_COPY_POINTERS) {
diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c
index edfccfc495d..ba3db5bc022 100644
--- a/storage/xtradb/row/row0sel.c
+++ b/storage/xtradb/row/row0sel.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -101,12 +101,17 @@ row_sel_sec_rec_is_for_blob(
ulint clust_len, /*!< in: length of clust_field */
const byte* sec_field, /*!< in: column in secondary index */
ulint sec_len, /*!< in: length of sec_field */
+ ulint prefix_len, /*!< in: index column prefix length
+ in bytes */
ulint zip_size) /*!< in: compressed page size, or 0 */
{
ulint len;
byte buf[DICT_MAX_INDEX_COL_LEN];
ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE);
+ ut_ad(prefix_len >= sec_len);
+ ut_ad(prefix_len > 0);
+ ut_a(prefix_len <= sizeof buf);
if (UNIV_UNLIKELY
(!memcmp(clust_field + clust_len - BTR_EXTERN_FIELD_REF_SIZE,
@@ -118,7 +123,7 @@ row_sel_sec_rec_is_for_blob(
return(FALSE);
}
- len = btr_copy_externally_stored_field_prefix(buf, sizeof buf,
+ len = btr_copy_externally_stored_field_prefix(buf, prefix_len,
zip_size,
clust_field, clust_len);
@@ -132,7 +137,7 @@ row_sel_sec_rec_is_for_blob(
}
len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen,
- sec_len, len, (const char*) buf);
+ prefix_len, len, (const char*) buf);
return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
}
@@ -219,11 +224,20 @@ row_sel_sec_rec_is_for_clust_rec(
if (rec_offs_nth_extern(clust_offs, clust_pos)
&& len < sec_len) {
+ /* This function should never be
+ invoked on an Antelope format table,
+ because they should always contain
+ enough prefix in the clustered index
+ record. */
+ ut_ad(dict_table_get_format(clust_index->table)
+ >= DICT_TF_FORMAT_ZIP);
+
if (!row_sel_sec_rec_is_for_blob(
col->mtype, col->prtype,
col->mbminlen, col->mbmaxlen,
clust_field, clust_len,
sec_field, sec_len,
+ ifield->prefix_len,
dict_table_zip_size(
clust_index->table))) {
goto inequal;
@@ -494,7 +508,7 @@ sel_col_prefetch_buf_alloc(
sel_buf = column->prefetch_buf + i;
sel_buf->data = NULL;
-
+ sel_buf->len = 0;
sel_buf->val_buf_size = 0;
}
}
@@ -519,6 +533,8 @@ sel_col_prefetch_buf_free(
mem_free(sel_buf->data);
}
}
+
+ mem_free(prefetch_buf);
}
/*********************************************************************//**
diff --git a/storage/xtradb/row/row0upd.c b/storage/xtradb/row/row0upd.c
index 5765d3b76d2..56e55e89c82 100644
--- a/storage/xtradb/row/row0upd.c
+++ b/storage/xtradb/row/row0upd.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -23,6 +23,15 @@ Update of a row
Created 12/27/1996 Heikki Tuuri
*******************************************************/
+#ifdef __WIN__
+/* error LNK2001: unresolved external symbol _debug_sync_C_callback_ptr */
+# define DEBUG_SYNC_C(dummy) ((void) 0)
+#else
+# include "my_global.h" /* HAVE_* */
+# include "m_string.h" /* for my_sys.h */
+# include "my_sys.h" /* DEBUG_SYNC_C */
+#endif
+
#include "row0upd.h"
#ifdef UNIV_NONINL
@@ -1995,27 +2004,42 @@ row_upd_clust_rec(
BTR_NO_LOCKING_FLAG | BTR_KEEP_POS_FLAG, btr_cur,
&heap, &big_rec, node->update, node->cmpl_info, thr, mtr);
/* skip store extern for fake_changes */
- if (big_rec && !(thr_get_trx(thr)->fake_changes)) {
- ulint offsets_[REC_OFFS_NORMAL_SIZE];
- rec_t* rec;
+ if (err == DB_SUCCESS && big_rec && !(thr_get_trx(thr)->fake_changes)) {
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ rec_t* rec;
+
rec_offs_init(offsets_);
ut_a(err == DB_SUCCESS);
- /* Write out the externally stored columns while still
- x-latching index->lock and block->lock. We have to
- mtr_commit(mtr) first, so that the redo log will be
- written in the correct order. Otherwise, we would run
- into trouble on crash recovery if mtr freed B-tree
- pages on which some of the big_rec fields will be
- written. */
- btr_cur_mtr_commit_and_start(btr_cur, mtr);
+ /* Write out the externally stored
+ columns while still x-latching
+ index->lock and block->lock. Allocate
+ pages for big_rec in the mtr that
+ modified the B-tree, but be sure to skip
+ any pages that were freed in mtr. We will
+ write out the big_rec pages before
+ committing the B-tree mini-transaction. If
+ the system crashes so that crash recovery
+ will not replay the mtr_commit(&mtr), the
+ big_rec pages will be left orphaned until
+ the pages are allocated for something else.
+
+ TODO: If the allocation extends the tablespace, it
+ will not be redo logged, in either mini-transaction.
+ Tablespace extension should be redo-logged in the
+ big_rec mini-transaction, so that recovery will not
+ fail when the big_rec was written to the extended
+ portion of the file, in case the file was somehow
+ truncated in the crash. */
rec = btr_cur_get_rec(btr_cur);
+ DEBUG_SYNC_C("before_row_upd_extern");
err = btr_store_big_rec_extern_fields(
index, btr_cur_get_block(btr_cur), rec,
rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap),
- mtr, TRUE, big_rec);
+ big_rec, mtr, BTR_STORE_UPDATE);
+ DEBUG_SYNC_C("after_row_upd_extern");
/* If writing big_rec fails (for example, because of
DB_OUT_OF_FILE_SPACE), the record will be corrupted.
Even if we did not update any externally stored
@@ -2023,7 +2047,12 @@ row_upd_clust_rec(
that a non-updated column was selected for external
storage. This non-update would not have been written
to the undo log, and thus the record cannot be rolled
- back. */
+ back.
+
+ However, because we have not executed mtr_commit(mtr)
+ yet, the update will not be replayed in crash
+ recovery, and the following assertion failure will
+ effectively "roll back" the operation. */
ut_a(err == DB_SUCCESS);
}
diff --git a/storage/xtradb/scripts/export.sh b/storage/xtradb/scripts/export.sh
new file mode 100644
index 00000000000..2a4355c1e43
--- /dev/null
+++ b/storage/xtradb/scripts/export.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+#
+# export current working directory in a format suitable for sending to MySQL
+# as a snapshot. also generates the actual snapshot and sends it to MySQL.
+
+set -eu
+
+die () {
+ echo $*
+ exit 1
+}
+
+if [ $# -ne 2 ] ; then
+ die "Usage: export.sh revision-number-of-last-snapshot current-revision-number"
+fi
+
+# If we are run from within the scripts/ directory then change directory to
+# one level up so that the relative paths work.
+DIR=`basename $PWD`
+
+if [ "${DIR}" = "scripts" ]; then
+ cd ..
+fi
+
+START_REV=$(($1 + 1))
+END_REV=$2
+
+set +u
+if test -z $EDITOR; then
+ die "\$EDITOR is not set"
+fi
+set -u
+
+rm -rf to-mysql
+mkdir to-mysql{,/storage,/patches,/mysql-test{,/t,/r,/include}}
+svn log -v -r "$START_REV:BASE" > to-mysql/log
+svn export -q . to-mysql/storage/innobase
+
+REV=$START_REV
+while [ $REV -le $END_REV ]
+do
+ PATCH=to-mysql/patches/r$REV.patch
+ svn log -v -r$REV > $PATCH
+ if [ $(wc -c < $PATCH) -gt 73 ]
+ then
+ svn diff -r$(($REV-1)):$REV >> $PATCH
+ else
+ rm $PATCH
+ fi
+ REV=$(($REV + 1))
+done
+
+cd to-mysql/storage/innobase
+
+mv mysql-test/*.test mysql-test/*.opt ../../mysql-test/t
+mv mysql-test/*.result ../../mysql-test/r
+mv mysql-test/*.inc ../../mysql-test/include
+rmdir mysql-test
+
+rm setup.sh export.sh revert_gen.sh compile-innodb-debug compile-innodb
+
+cd ../..
+$EDITOR log
+cd ..
+
+fname="innodb-5.1-ss$2.tar.gz"
+
+rm -f $fname
+tar czf $fname to-mysql
+scp $fname mysql:snapshots
+rm $fname
+rm -rf to-mysql
+
+echo "Sent $fname to MySQL"
diff --git a/storage/xtradb/scripts/install_innodb_plugins.sql b/storage/xtradb/scripts/install_innodb_plugins.sql
index 5a555a652f7..3fdb8f11e22 100644
--- a/storage/xtradb/scripts/install_innodb_plugins.sql
+++ b/storage/xtradb/scripts/install_innodb_plugins.sql
@@ -7,11 +7,3 @@ INSTALL PLUGIN innodb_cmp SONAME 'ha_innodb.so';
INSTALL PLUGIN innodb_cmp_reset SONAME 'ha_innodb.so';
INSTALL PLUGIN innodb_cmpmem SONAME 'ha_innodb.so';
INSTALL PLUGIN innodb_cmpmem_reset SONAME 'ha_innodb.so';
-INSTALL PLUGIN XTRADB_ENHANCEMENTS SONAME 'ha_innodb.so';
-INSTALL PLUGIN INNODB_BUFFER_POOL_PAGES SONAME 'ha_innodb.so';
-INSTALL PLUGIN INNODB_BUFFER_POOL_PAGES_BLOB SONAME 'ha_innodb.so';
-INSTALL PLUGIN INNODB_BUFFER_POOL_PAGES_INDEX SONAME 'ha_innodb.so';
-INSTALL PLUGIN innodb_rseg SONAME 'ha_innodb.so';
-INSTALL PLUGIN innodb_table_stats SONAME 'ha_innodb.so';
-INSTALL PLUGIN innodb_index_stats SONAME 'ha_innodb.so';
-INSTALL PLUGIN xtradb_admin_command SONAME 'ha_innodb.so';
diff --git a/storage/xtradb/scripts/install_innodb_plugins_win.sql b/storage/xtradb/scripts/install_innodb_plugins_win.sql
index 7cda3335694..8c94b4e240d 100644
--- a/storage/xtradb/scripts/install_innodb_plugins_win.sql
+++ b/storage/xtradb/scripts/install_innodb_plugins_win.sql
@@ -7,11 +7,3 @@ INSTALL PLUGIN innodb_cmp SONAME 'ha_innodb.dll';
INSTALL PLUGIN innodb_cmp_reset SONAME 'ha_innodb.dll';
INSTALL PLUGIN innodb_cmpmem SONAME 'ha_innodb.dll';
INSTALL PLUGIN innodb_cmpmem_reset SONAME 'ha_innodb.dll';
-INSTALL PLUGIN XTRADB_ENHANCEMENTS SONAME 'ha_innodb.dll';
-INSTALL PLUGIN INNODB_BUFFER_POOL_PAGES SONAME 'ha_innodb.dll';
-INSTALL PLUGIN INNODB_BUFFER_POOL_PAGES_BLOB SONAME 'ha_innodb.dll';
-INSTALL PLUGIN INNODB_BUFFER_POOL_PAGES_INDEX SONAME 'ha_innodb.dll';
-INSTALL PLUGIN innodb_rseg SONAME 'ha_innodb.dll';
-INSTALL PLUGIN innodb_table_stats SONAME 'ha_innodb.dll';
-INSTALL PLUGIN innodb_index_stats SONAME 'ha_innodb.dll';
-INSTALL PLUGIN xtradb_admin_command SONAME 'ha_innodb.dll';
diff --git a/storage/xtradb/setup.sh b/storage/xtradb/setup.sh
new file mode 100644
index 00000000000..b5d8299d411
--- /dev/null
+++ b/storage/xtradb/setup.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+#
+# Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Prepare the MySQL source code tree for building
+# with checked-out InnoDB Subversion directory.
+
+# This script assumes that the current directory is storage/innobase.
+
+set -eu
+
+TARGETDIR=../storage/innodb_plugin
+
+# link the build scripts
+BUILDSCRIPTS="compile-innodb compile-innodb-debug"
+for script in $BUILDSCRIPTS ; do
+ ln -sf $TARGETDIR/$script ../../BUILD/
+done
+
+cd ../../mysql-test/t
+ln -sf ../$TARGETDIR/mysql-test/*.test ../$TARGETDIR/mysql-test/*.opt .
+cd ../r
+ln -sf ../$TARGETDIR/mysql-test/*.result .
+cd ../include
+ln -sf ../$TARGETDIR/mysql-test/*.inc .
+
+# Apply any patches that are needed to make the mysql-test suite successful.
+# These patches are usually needed because of deviations of behavior between
+# the stock InnoDB and the InnoDB Plugin.
+cd ../..
+for patch in storage/innobase/mysql-test/patches/*.diff ; do
+ if [ "${patch}" != "storage/innobase/mysql-test/patches/*.diff" ] ; then
+ patch -p0 < ${patch}
+ fi
+done
diff --git a/storage/xtradb/sync/sync0rw.c b/storage/xtradb/sync/sync0rw.c
index fe000e7d008..054423f9116 100644
--- a/storage/xtradb/sync/sync0rw.c
+++ b/storage/xtradb/sync/sync0rw.c
@@ -611,6 +611,9 @@ rw_lock_x_lock_func(
ibool spinning = FALSE;
ut_ad(rw_lock_validate(lock));
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED));
+#endif /* UNIV_SYNC_DEBUG */
i = 0;
@@ -927,11 +930,13 @@ rw_lock_list_print_info(
putc('\n', file);
}
+ rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
rw_lock_debug_print(file, info);
info = UT_LIST_GET_NEXT(list, info);
}
+ rw_lock_debug_mutex_exit();
}
#ifndef INNODB_RW_LOCKS_USE_ATOMICS
mutex_exit(&(lock->mutex));
@@ -975,11 +980,13 @@ rw_lock_print(
putc('\n', stderr);
}
+ rw_lock_debug_mutex_enter();
info = UT_LIST_GET_FIRST(lock->debug_list);
while (info != NULL) {
rw_lock_debug_print(stderr, info);
info = UT_LIST_GET_NEXT(list, info);
}
+ rw_lock_debug_mutex_exit();
}
}
diff --git a/storage/xtradb/sync/sync0sync.c b/storage/xtradb/sync/sync0sync.c
index 277a53e4fb2..18a961ac18b 100644
--- a/storage/xtradb/sync/sync0sync.c
+++ b/storage/xtradb/sync/sync0sync.c
@@ -1178,7 +1178,6 @@ sync_thread_add_level(
case SYNC_BUF_ZIP_HASH:
case SYNC_BUF_POOL:
case SYNC_SEARCH_SYS:
- case SYNC_SEARCH_SYS_CONF:
case SYNC_TRX_LOCK_HEAP:
case SYNC_KERNEL:
case SYNC_IBUF_BITMAP_MUTEX:
@@ -1191,6 +1190,7 @@ sync_thread_add_level(
case SYNC_DICT_HEADER:
case SYNC_TRX_I_S_RWLOCK:
case SYNC_TRX_I_S_LAST_READ:
+ case SYNC_IBUF_MUTEX:
if (!sync_thread_levels_g(array, level, TRUE)) {
fprintf(stderr,
"InnoDB: sync_thread_levels_g(array, %lu)"
@@ -1254,22 +1254,33 @@ sync_thread_add_level(
|| sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE));
break;
case SYNC_TREE_NODE_NEW:
- ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE)
- || sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
+ ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE));
break;
case SYNC_INDEX_TREE:
- if (sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
- && sync_thread_levels_contain(array, SYNC_FSP)) {
- ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1,
- TRUE));
+ ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE));
+ break;
+ case SYNC_IBUF_TREE_NODE:
+ ut_a(sync_thread_levels_contain(array, SYNC_IBUF_INDEX_TREE)
+ || sync_thread_levels_g(array, SYNC_IBUF_TREE_NODE - 1,
+ TRUE));
+ break;
+ case SYNC_IBUF_TREE_NODE_NEW:
+ /* ibuf_add_free_page() allocates new pages for the
+ change buffer while only holding the tablespace
+ x-latch. These pre-allocated new pages may only be
+ taken in use while holding ibuf_mutex, in
+ btr_page_alloc_for_ibuf(). */
+ ut_a(sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
+ || sync_thread_levels_contain(array, SYNC_FSP));
+ break;
+ case SYNC_IBUF_INDEX_TREE:
+ if (sync_thread_levels_contain(array, SYNC_FSP)) {
+ ut_a(sync_thread_levels_g(array, level - 1, TRUE));
} else {
- ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1,
- TRUE));
+ ut_a(sync_thread_levels_g(
+ array, SYNC_IBUF_TREE_NODE - 1, TRUE));
}
break;
- case SYNC_IBUF_MUTEX:
- ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1, TRUE));
- break;
case SYNC_IBUF_PESS_INSERT_MUTEX:
ut_a(sync_thread_levels_g(array, SYNC_FSP - 1, TRUE));
ut_a(!sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
diff --git a/storage/xtradb/trx/trx0purge.c b/storage/xtradb/trx/trx0purge.c
index 5a8b42af3af..6c49c5d7ff8 100644
--- a/storage/xtradb/trx/trx0purge.c
+++ b/storage/xtradb/trx/trx0purge.c
@@ -1111,7 +1111,7 @@ trx_purge(void)
{
que_thr_t* thr;
/* que_thr_t* thr2; */
- ulint old_pages_handled;
+ ulonglong old_pages_handled;
mutex_enter(&(purge_sys->mutex));
@@ -1210,7 +1210,7 @@ trx_purge(void)
(ulong) purge_sys->n_pages_handled);
}
- return(purge_sys->n_pages_handled - old_pages_handled);
+ return((ulint) (purge_sys->n_pages_handled - old_pages_handled));
}
/**********************************************************************
diff --git a/storage/xtradb/trx/trx0rec.c b/storage/xtradb/trx/trx0rec.c
index a7a393d31c8..124d22eec63 100644
--- a/storage/xtradb/trx/trx0rec.c
+++ b/storage/xtradb/trx/trx0rec.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -1110,13 +1110,14 @@ trx_undo_rec_get_partial_row(
#endif /* !UNIV_HOTBACKUP */
/***********************************************************************//**
-Erases the unused undo log page end. */
-static
-void
+Erases the unused undo log page end.
+@return TRUE if the page contained something, FALSE if it was empty */
+static __attribute__((nonnull))
+ibool
trx_undo_erase_page_end(
/*====================*/
- page_t* undo_page, /*!< in: undo page whose end to erase */
- mtr_t* mtr) /*!< in: mtr */
+ page_t* undo_page, /*!< in/out: undo page whose end to erase */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint first_free;
@@ -1126,6 +1127,7 @@ trx_undo_erase_page_end(
(UNIV_PAGE_SIZE - FIL_PAGE_DATA_END) - first_free);
mlog_write_initial_log_record(undo_page, MLOG_UNDO_ERASE_END, mtr);
+ return(first_free != TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE);
}
/***********************************************************//**
@@ -1187,12 +1189,16 @@ trx_undo_report_row_operation(
trx_t* trx;
trx_undo_t* undo;
ulint page_no;
+ buf_block_t* undo_block;
trx_rseg_t* rseg;
mtr_t mtr;
ulint err = DB_SUCCESS;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
+#ifdef UNIV_DEBUG
+ int loop_count = 0;
+#endif /* UNIV_DEBUG */
rec_offs_init(offsets_);
ut_a(dict_index_is_clust(index));
@@ -1226,10 +1232,13 @@ trx_undo_report_row_operation(
if (UNIV_UNLIKELY(!undo)) {
/* Did not succeed */
+ ut_ad(err != DB_SUCCESS);
mutex_exit(&(trx->undo_mutex));
return(err);
}
+
+ ut_ad(err == DB_SUCCESS);
} else {
ut_ad(op_type == TRX_UNDO_MODIFY_OP);
@@ -1243,30 +1252,30 @@ trx_undo_report_row_operation(
if (UNIV_UNLIKELY(!undo)) {
/* Did not succeed */
+ ut_ad(err != DB_SUCCESS);
mutex_exit(&(trx->undo_mutex));
return(err);
}
+ ut_ad(err == DB_SUCCESS);
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
}
- page_no = undo->last_page_no;
-
mtr_start(&mtr);
- for (;;) {
- buf_block_t* undo_block;
+ page_no = undo->last_page_no;
+ undo_block = buf_page_get_gen(
+ undo->space, undo->zip_size, page_no, RW_X_LATCH,
+ undo->guess_block, BUF_GET, __FILE__, __LINE__, &mtr);
+ buf_block_dbg_add_level(undo_block, SYNC_TRX_UNDO_PAGE);
+
+ do {
page_t* undo_page;
ulint offset;
- undo_block = buf_page_get_gen(undo->space, undo->zip_size,
- page_no, RW_X_LATCH,
- undo->guess_block, BUF_GET,
- __FILE__, __LINE__, &mtr);
- buf_block_dbg_add_level(undo_block, SYNC_TRX_UNDO_PAGE);
-
undo_page = buf_block_get_frame(undo_block);
+ ut_ad(page_no == buf_block_get_page_no(undo_block));
if (op_type == TRX_UNDO_INSERT_OP) {
offset = trx_undo_page_report_insert(
@@ -1284,7 +1293,31 @@ trx_undo_report_row_operation(
version the replicate page constructed using the log
records stays identical to the original page */
- trx_undo_erase_page_end(undo_page, &mtr);
+ if (!trx_undo_erase_page_end(undo_page, &mtr)) {
+ /* The record did not fit on an empty
+ undo page. Discard the freshly allocated
+ page and return an error. */
+
+ /* When we remove a page from an undo
+ log, this is analogous to a
+ pessimistic insert in a B-tree, and we
+ must reserve the counterpart of the
+ tree latch, which is the rseg
+ mutex. We must commit the mini-transaction
+ first, because it may be holding lower-level
+ latches, such as SYNC_FSP and SYNC_FSP_PAGE. */
+
+ mtr_commit(&mtr);
+ mtr_start(&mtr);
+
+ mutex_enter(&rseg->mutex);
+ trx_undo_free_last_page(trx, undo, &mtr);
+ mutex_exit(&rseg->mutex);
+
+ err = DB_TOO_BIG_RECORD;
+ goto err_exit;
+ }
+
mtr_commit(&mtr);
} else {
/* Success */
@@ -1304,39 +1337,39 @@ trx_undo_report_row_operation(
*roll_ptr = trx_undo_build_roll_ptr(
op_type == TRX_UNDO_INSERT_OP,
rseg->id, page_no, offset);
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- return(DB_SUCCESS);
+ err = DB_SUCCESS;
+ goto func_exit;
}
ut_ad(page_no == undo->last_page_no);
/* We have to extend the undo log by one page */
+ ut_ad(++loop_count < 2);
mtr_start(&mtr);
/* When we add a page to an undo log, this is analogous to
a pessimistic insert in a B-tree, and we must reserve the
counterpart of the tree latch, which is the rseg mutex. */
- mutex_enter(&(rseg->mutex));
+ mutex_enter(&rseg->mutex);
+ undo_block = trx_undo_add_page(trx, undo, &mtr);
+ mutex_exit(&rseg->mutex);
- page_no = trx_undo_add_page(trx, undo, &mtr);
+ page_no = undo->last_page_no;
+ } while (undo_block != NULL);
- mutex_exit(&(rseg->mutex));
+ /* Did not succeed: out of space */
+ err = DB_OUT_OF_FILE_SPACE;
- if (UNIV_UNLIKELY(page_no == FIL_NULL)) {
- /* Did not succeed: out of space */
-
- mutex_exit(&(trx->undo_mutex));
- mtr_commit(&mtr);
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- return(DB_OUT_OF_FILE_SPACE);
- }
+err_exit:
+ mutex_exit(&trx->undo_mutex);
+ mtr_commit(&mtr);
+func_exit:
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
}
+ return(err);
}
/*============== BUILDING PREVIOUS VERSION OF A RECORD ===============*/
diff --git a/storage/xtradb/trx/trx0sys.c b/storage/xtradb/trx/trx0sys.c
index b5bec64ee37..56fc86427ce 100644
--- a/storage/xtradb/trx/trx0sys.c
+++ b/storage/xtradb/trx/trx0sys.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -131,6 +131,11 @@ static const char* file_format_name_map[] = {
static const ulint FILE_FORMAT_NAME_N
= sizeof(file_format_name_map) / sizeof(file_format_name_map[0]);
+#ifdef UNIV_DEBUG
+/* Flag to control TRX_RSEG_N_SLOTS behavior debugging. */
+uint trx_rseg_n_slots_debug = 0;
+#endif
+
#ifndef UNIV_HOTBACKUP
/** This is used to track the maximum file format id known to InnoDB. It's
updated via SET GLOBAL innodb_file_format_check = 'x' or when we open
@@ -246,9 +251,7 @@ trx_sys_create_doublewrite_buf(void)
{
buf_block_t* block;
buf_block_t* block2;
-#ifdef UNIV_SYNC_DEBUG
buf_block_t* new_block;
-#endif /* UNIV_SYNC_DEBUG */
byte* doublewrite;
byte* fseg_header;
ulint page_no;
@@ -327,10 +330,9 @@ start_again:
for (i = 0; i < 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
+ FSP_EXTENT_SIZE / 2; i++) {
- page_no = fseg_alloc_free_page(fseg_header,
- prev_page_no + 1,
- FSP_UP, &mtr);
- if (page_no == FIL_NULL) {
+ new_block = fseg_alloc_free_page(
+ fseg_header, prev_page_no + 1, FSP_UP, &mtr);
+ if (new_block == NULL) {
fprintf(stderr,
"InnoDB: Cannot create doublewrite"
" buffer: you must\n"
@@ -351,13 +353,8 @@ start_again:
the page position in the tablespace, then the page
has not been written to in doublewrite. */
-#ifdef UNIV_SYNC_DEBUG
- new_block =
-#endif /* UNIV_SYNC_DEBUG */
- buf_page_get(TRX_SYS_SPACE, 0, page_no,
- RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(new_block,
- SYNC_NO_ORDER_CHECK);
+ ut_ad(rw_lock_get_x_lock_count(&new_block->lock) == 1);
+ page_no = buf_block_get_page_no(new_block);
if (i == FSP_EXTENT_SIZE / 2) {
ut_a(page_no == FSP_EXTENT_SIZE);
@@ -474,10 +471,10 @@ start_again:
for (i = 0; i < 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
+ FSP_EXTENT_SIZE / 2; i++) {
- page_no = fseg_alloc_free_page(fseg_header,
+ new_block = fseg_alloc_free_page(fseg_header,
prev_page_no + 1,
FSP_UP, &mtr);
- if (page_no == FIL_NULL) {
+ if (new_block == NULL) {
fprintf(stderr,
"InnoDB: Cannot create doublewrite"
" buffer: you must\n"
@@ -498,13 +495,8 @@ start_again:
the page position in the tablespace, then the page
has not been written to in doublewrite. */
-#ifdef UNIV_SYNC_DEBUG
- new_block =
-#endif /* UNIV_SYNC_DEBUG */
- buf_page_get(TRX_DOUBLEWRITE_SPACE, 0, page_no,
- RW_X_LATCH, &mtr);
- buf_block_dbg_add_level(new_block,
- SYNC_NO_ORDER_CHECK);
+ ut_ad(rw_lock_get_x_lock_count(&new_block->lock) == 1);
+ page_no = buf_block_get_page_no(new_block);
if (i == FSP_EXTENT_SIZE / 2) {
ut_a(page_no == FSP_EXTENT_SIZE);
diff --git a/storage/xtradb/trx/trx0trx.c b/storage/xtradb/trx/trx0trx.c
index bf042db4972..0cecbf2eea9 100644
--- a/storage/xtradb/trx/trx0trx.c
+++ b/storage/xtradb/trx/trx0trx.c
@@ -1078,6 +1078,8 @@ trx_commit_off_kernel(
ut_ad(UT_LIST_GET_LEN(trx->trx_locks) == 0);
UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx);
+
+ trx->error_state = DB_SUCCESS;
}
/****************************************************************//**
diff --git a/storage/xtradb/trx/trx0undo.c b/storage/xtradb/trx/trx0undo.c
index ec1cd2d2c43..fd89936fd33 100644
--- a/storage/xtradb/trx/trx0undo.c
+++ b/storage/xtradb/trx/trx0undo.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -870,9 +870,9 @@ trx_undo_discard_latest_update_undo(
#ifndef UNIV_HOTBACKUP
/********************************************************************//**
Tries to add a page to the undo log segment where the undo log is placed.
-@return page number if success, else FIL_NULL */
+@return X-latched block if success, else NULL */
UNIV_INTERN
-ulint
+buf_block_t*
trx_undo_add_page(
/*==============*/
trx_t* trx, /*!< in: transaction */
@@ -882,11 +882,10 @@ trx_undo_add_page(
the rollback segment mutex */
{
page_t* header_page;
+ buf_block_t* new_block;
page_t* new_page;
trx_rseg_t* rseg;
- ulint page_no;
ulint n_reserved;
- ibool success;
ut_ad(mutex_own(&(trx->undo_mutex)));
ut_ad(!mutex_own(&kernel_mutex));
@@ -896,37 +895,37 @@ trx_undo_add_page(
if (rseg->curr_size == rseg->max_size) {
- return(FIL_NULL);
+ return(NULL);
}
header_page = trx_undo_page_get(undo->space, undo->zip_size,
undo->hdr_page_no, mtr);
- success = fsp_reserve_free_extents(&n_reserved, undo->space, 1,
- FSP_UNDO, mtr);
- if (!success) {
+ if (!fsp_reserve_free_extents(&n_reserved, undo->space, 1,
+ FSP_UNDO, mtr)) {
- return(FIL_NULL);
+ return(NULL);
}
- page_no = fseg_alloc_free_page_general(header_page + TRX_UNDO_SEG_HDR
- + TRX_UNDO_FSEG_HEADER,
- undo->top_page_no + 1, FSP_UP,
- TRUE, mtr);
+ new_block = fseg_alloc_free_page_general(
+ TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER
+ + header_page,
+ undo->top_page_no + 1, FSP_UP, TRUE, mtr, mtr);
fil_space_release_free_extents(undo->space, n_reserved);
- if (page_no == FIL_NULL) {
+ if (new_block == NULL) {
/* No space left */
- return(FIL_NULL);
+ return(NULL);
}
- undo->last_page_no = page_no;
+ ut_ad(rw_lock_get_x_lock_count(&new_block->lock) == 1);
+ buf_block_dbg_add_level(new_block, SYNC_TRX_UNDO_PAGE);
+ undo->last_page_no = buf_block_get_page_no(new_block);
- new_page = trx_undo_page_get(undo->space, undo->zip_size,
- page_no, mtr);
+ new_page = buf_block_get_frame(new_block);
trx_undo_page_init(new_page, undo->type, mtr);
@@ -935,7 +934,7 @@ trx_undo_add_page(
undo->size++;
rseg->curr_size++;
- return(page_no);
+ return(new_block);
}
/********************************************************************//**
@@ -998,29 +997,28 @@ trx_undo_free_page(
}
/********************************************************************//**
-Frees an undo log page when there is also the memory object for the undo
-log. */
-static
+Frees the last undo log page.
+The caller must hold the rollback segment mutex. */
+UNIV_INTERN
void
-trx_undo_free_page_in_rollback(
-/*===========================*/
- trx_t* trx __attribute__((unused)), /*!< in: transaction */
- trx_undo_t* undo, /*!< in: undo log memory copy */
- ulint page_no,/*!< in: page number to free: must not be the
- header page */
- mtr_t* mtr) /*!< in: mtr which does not have a latch to any
- undo log page; the caller must have reserved
- the rollback segment mutex */
+trx_undo_free_last_page_func(
+/*==========================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction */
+#endif /* UNIV_DEBUG */
+ trx_undo_t* undo, /*!< in/out: undo log memory copy */
+ mtr_t* mtr) /*!< in/out: mini-transaction which does not
+ have a latch to any undo log page or which
+ has allocated the undo log page */
{
- ulint last_page_no;
-
- ut_ad(undo->hdr_page_no != page_no);
- ut_ad(mutex_own(&(trx->undo_mutex)));
+ ut_ad(mutex_own(&trx->undo_mutex));
+ ut_ad(undo->hdr_page_no != undo->last_page_no);
+ ut_ad(undo->size > 0);
- last_page_no = trx_undo_free_page(undo->rseg, FALSE, undo->space,
- undo->hdr_page_no, page_no, mtr);
+ undo->last_page_no = trx_undo_free_page(
+ undo->rseg, FALSE, undo->space,
+ undo->hdr_page_no, undo->last_page_no, mtr);
- undo->last_page_no = last_page_no;
undo->size--;
}
@@ -1056,9 +1054,11 @@ Truncates an undo log from the end. This function is used during a rollback
to free space from an undo log. */
UNIV_INTERN
void
-trx_undo_truncate_end(
-/*==================*/
- trx_t* trx, /*!< in: transaction whose undo log it is */
+trx_undo_truncate_end_func(
+/*=======================*/
+#ifdef UNIV_DEBUG
+ const trx_t* trx, /*!< in: transaction whose undo log it is */
+#endif /* UNIV_DEBUG */
trx_undo_t* undo, /*!< in: undo log */
undo_no_t limit) /*!< in: all undo records with undo number
>= this value should be truncated */
@@ -1084,18 +1084,7 @@ trx_undo_truncate_end(
rec = trx_undo_page_get_last_rec(undo_page, undo->hdr_page_no,
undo->hdr_offset);
- for (;;) {
- if (rec == NULL) {
- if (last_page_no == undo->hdr_page_no) {
-
- goto function_exit;
- }
-
- trx_undo_free_page_in_rollback(
- trx, undo, last_page_no, &mtr);
- break;
- }
-
+ while (rec) {
if (ut_dulint_cmp(trx_undo_rec_get_undo_no(rec), limit)
>= 0) {
/* Truncate at least this record off, maybe
@@ -1110,6 +1099,14 @@ trx_undo_truncate_end(
undo->hdr_offset);
}
+ if (last_page_no == undo->hdr_page_no) {
+
+ goto function_exit;
+ }
+
+ ut_ad(last_page_no == undo->last_page_no);
+ trx_undo_free_last_page(trx, undo, &mtr);
+
mtr_commit(&mtr);
}
diff --git a/storage/xtradb/ut/ut0auxconf_atomic_pthread_t_gcc.c b/storage/xtradb/ut/ut0auxconf_atomic_pthread_t_gcc.c
new file mode 100644
index 00000000000..30de5aa6f17
--- /dev/null
+++ b/storage/xtradb/ut/ut0auxconf_atomic_pthread_t_gcc.c
@@ -0,0 +1,43 @@
+/*****************************************************************************
+
+Copyright (c) 2009, Innobase Oy. All Rights Reserved.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/*****************************************************************************
+If this program compiles, then pthread_t objects can be used as arguments
+to GCC atomic builtin functions.
+
+Created March 5, 2009 Vasil Dimov
+*****************************************************************************/
+
+#include <pthread.h>
+#include <string.h>
+
+int
+main(int argc, char** argv)
+{
+ pthread_t x1;
+ pthread_t x2;
+ pthread_t x3;
+
+ memset(&x1, 0x0, sizeof(x1));
+ memset(&x2, 0x0, sizeof(x2));
+ memset(&x3, 0x0, sizeof(x3));
+
+ __sync_bool_compare_and_swap(&x1, x2, x3);
+
+ return(0);
+}
diff --git a/storage/xtradb/ut/ut0auxconf_atomic_pthread_t_solaris.c b/storage/xtradb/ut/ut0auxconf_atomic_pthread_t_solaris.c
new file mode 100644
index 00000000000..310603c7503
--- /dev/null
+++ b/storage/xtradb/ut/ut0auxconf_atomic_pthread_t_solaris.c
@@ -0,0 +1,54 @@
+/*****************************************************************************
+
+Copyright (c) 2009, Innobase Oy. All Rights Reserved.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/*****************************************************************************
+If this program compiles and returns 0, then pthread_t objects can be used as
+arguments to Solaris libc atomic functions.
+
+Created April 18, 2009 Vasil Dimov
+*****************************************************************************/
+
+#include <pthread.h>
+#include <string.h>
+
+int
+main(int argc, char** argv)
+{
+ pthread_t x1;
+ pthread_t x2;
+ pthread_t x3;
+
+ memset(&x1, 0x0, sizeof(x1));
+ memset(&x2, 0x0, sizeof(x2));
+ memset(&x3, 0x0, sizeof(x3));
+
+ if (sizeof(pthread_t) == 4) {
+
+ atomic_cas_32(&x1, x2, x3);
+
+ } else if (sizeof(pthread_t) == 8) {
+
+ atomic_cas_64(&x1, x2, x3);
+
+ } else {
+
+ return(1);
+ }
+
+ return(0);
+}
diff --git a/storage/xtradb/ut/ut0auxconf_have_gcc_atomics.c b/storage/xtradb/ut/ut0auxconf_have_gcc_atomics.c
new file mode 100644
index 00000000000..da5c13d7d79
--- /dev/null
+++ b/storage/xtradb/ut/ut0auxconf_have_gcc_atomics.c
@@ -0,0 +1,61 @@
+/*****************************************************************************
+
+Copyright (c) 2009, Innobase Oy. All Rights Reserved.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/*****************************************************************************
+If this program compiles and returns 0, then GCC atomic funcions are available.
+
+Created September 12, 2009 Vasil Dimov
+*****************************************************************************/
+
+int
+main(int argc, char** argv)
+{
+ long x;
+ long y;
+ long res;
+ char c;
+
+ x = 10;
+ y = 123;
+ res = __sync_bool_compare_and_swap(&x, x, y);
+ if (!res || x != y) {
+ return(1);
+ }
+
+ x = 10;
+ y = 123;
+ res = __sync_bool_compare_and_swap(&x, x + 1, y);
+ if (res || x != 10) {
+ return(1);
+ }
+
+ x = 10;
+ y = 123;
+ res = __sync_add_and_fetch(&x, y);
+ if (res != 123 + 10 || x != 123 + 10) {
+ return(1);
+ }
+
+ c = 10;
+ res = __sync_lock_test_and_set(&c, 123);
+ if (res != 10 || c != 123) {
+ return(1);
+ }
+
+ return(0);
+}
diff --git a/storage/xtradb/ut/ut0auxconf_have_solaris_atomics.c b/storage/xtradb/ut/ut0auxconf_have_solaris_atomics.c
new file mode 100644
index 00000000000..7eb704edd4b
--- /dev/null
+++ b/storage/xtradb/ut/ut0auxconf_have_solaris_atomics.c
@@ -0,0 +1,39 @@
+/*****************************************************************************
+
+Copyright (c) 2009, Innobase Oy. All Rights Reserved.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/*****************************************************************************
+If this program compiles, then Solaris libc atomic funcions are available.
+
+Created April 18, 2009 Vasil Dimov
+*****************************************************************************/
+#include <atomic.h>
+
+int
+main(int argc, char** argv)
+{
+ ulong_t ulong = 0;
+ uint32_t uint32 = 0;
+ uint64_t uint64 = 0;
+
+ atomic_cas_ulong(&ulong, 0, 1);
+ atomic_cas_32(&uint32, 0, 1);
+ atomic_cas_64(&uint64, 0, 1);
+ atomic_add_long(&ulong, 0);
+
+ return(0);
+}
diff --git a/storage/xtradb/ut/ut0auxconf_pause.c b/storage/xtradb/ut/ut0auxconf_pause.c
new file mode 100644
index 00000000000..54d63bdd9bc
--- /dev/null
+++ b/storage/xtradb/ut/ut0auxconf_pause.c
@@ -0,0 +1,32 @@
+/*****************************************************************************
+
+Copyright (c) 2009, Innobase Oy. All Rights Reserved.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/*****************************************************************************
+If this program compiles and can be run and returns 0, then the pause
+instruction is available.
+
+Created Jul 21, 2009 Vasil Dimov
+*****************************************************************************/
+
+int
+main(int argc, char** argv)
+{
+ __asm__ __volatile__ ("pause");
+
+ return(0);
+}
diff --git a/storage/xtradb/ut/ut0auxconf_sizeof_pthread_t.c b/storage/xtradb/ut/ut0auxconf_sizeof_pthread_t.c
new file mode 100644
index 00000000000..96add4526ef
--- /dev/null
+++ b/storage/xtradb/ut/ut0auxconf_sizeof_pthread_t.c
@@ -0,0 +1,35 @@
+/*****************************************************************************
+
+Copyright (c) 2009, Innobase Oy. All Rights Reserved.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/*****************************************************************************
+This program should compile and when run, print a single line like:
+#define SIZEOF_PTHREAD_T %d
+
+Created April 18, 2009 Vasil Dimov
+*****************************************************************************/
+
+#include <stdio.h>
+#include <pthread.h>
+
+int
+main(int argc, char** argv)
+{
+ printf("#define SIZEOF_PTHREAD_T %d\n", (int) sizeof(pthread_t));
+
+ return(0);
+}
diff --git a/storage/xtradb/ut/ut0mem.c b/storage/xtradb/ut/ut0mem.c
index 95fb2187b79..9f9eb1c4d49 100644
--- a/storage/xtradb/ut/ut0mem.c
+++ b/storage/xtradb/ut/ut0mem.c
@@ -84,17 +84,13 @@ ut_mem_init(void)
#endif /* !UNIV_HOTBACKUP */
/**********************************************************************//**
-Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
-defined and set_to_zero is TRUE.
+Allocates memory.
@return own: allocated memory */
UNIV_INTERN
void*
ut_malloc_low(
/*==========*/
ulint n, /*!< in: number of bytes to allocate */
- ibool set_to_zero, /*!< in: TRUE if allocated memory should be
- set to zero if UNIV_SET_MEM_TO_ZERO is
- defined */
ibool assert_on_error)/*!< in: if TRUE, we crash mysqld if the
memory cannot be allocated */
{
@@ -106,12 +102,6 @@ ut_malloc_low(
ret = malloc(n);
ut_a(ret || !assert_on_error);
-#ifdef UNIV_SET_MEM_TO_ZERO
- if (set_to_zero) {
- memset(ret, '\0', n);
- UNIV_MEM_ALLOC(ret, n);
- }
-#endif
return(ret);
}
@@ -199,12 +189,6 @@ retry:
#endif
}
- if (set_to_zero) {
-#ifdef UNIV_SET_MEM_TO_ZERO
- memset(ret, '\0', n + sizeof(ut_mem_block_t));
-#endif
- }
-
UNIV_MEM_ALLOC(ret, n + sizeof(ut_mem_block_t));
((ut_mem_block_t*)ret)->size = n + sizeof(ut_mem_block_t);
@@ -221,75 +205,11 @@ retry:
void* ret = malloc(n);
ut_a(ret || !assert_on_error);
-# ifdef UNIV_SET_MEM_TO_ZERO
- if (set_to_zero) {
- memset(ret, '\0', n);
- }
-# endif
return(ret);
#endif /* !UNIV_HOTBACKUP */
}
/**********************************************************************//**
-Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
-defined.
-@return own: allocated memory */
-UNIV_INTERN
-void*
-ut_malloc(
-/*======*/
- ulint n) /*!< in: number of bytes to allocate */
-{
-#ifndef UNIV_HOTBACKUP
- return(ut_malloc_low(n, TRUE, TRUE));
-#else /* !UNIV_HOTBACKUP */
- return(malloc(n));
-#endif /* !UNIV_HOTBACKUP */
-}
-
-#ifndef UNIV_HOTBACKUP
-/**********************************************************************//**
-Tests if malloc of n bytes would succeed. ut_malloc() asserts if memory runs
-out. It cannot be used if we want to return an error message. Prints to
-stderr a message if fails.
-@return TRUE if succeeded */
-UNIV_INTERN
-ibool
-ut_test_malloc(
-/*===========*/
- ulint n) /*!< in: try to allocate this many bytes */
-{
- void* ret;
-
- ret = malloc(n);
-
- if (ret == NULL) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: cannot allocate"
- " %lu bytes of memory for\n"
- "InnoDB: a BLOB with malloc! Total allocated memory\n"
- "InnoDB: by InnoDB %lu bytes."
- " Operating system errno: %d\n"
- "InnoDB: Check if you should increase"
- " the swap file or\n"
- "InnoDB: ulimits of your operating system.\n"
- "InnoDB: On FreeBSD check you have"
- " compiled the OS with\n"
- "InnoDB: a big enough maximum process size.\n",
- (ulong) n,
- (ulong) ut_total_allocated_memory,
- (int) errno);
- return(FALSE);
- }
-
- free(ret);
-
- return(TRUE);
-}
-#endif /* !UNIV_HOTBACKUP */
-
-/**********************************************************************//**
Frees a memory block allocated with ut_malloc. Freeing a NULL pointer is
a nop. */
UNIV_INTERN