From 648fb98eb6834781e5ff7bd13f26e7b3755fdf81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= <jplindst@mariadb.org> Date: Tue, 8 Jul 2014 18:51:34 +0300 Subject: [PATCH] MDEV-6348: mariadb crash signal 11 Analysis: sync array output function, should make sure that all used pointers are valid before using them. Merge revision 4225 from lp:maria/5.5. --- .../include/innodb_simulate_comp_failures.inc | 147 ++++++++++++++++++ .../r/innodb_simulate_comp_failures.result | 8 + ...innodb_simulate_comp_failures_small.result | 8 + .../innodb_simulate_comp_failures-master.opt | 2 + .../t/innodb_simulate_comp_failures.test | 8 + ...db_simulate_comp_failures_small-master.opt | 2 + .../innodb_simulate_comp_failures_small.test | 5 + .../innodb_simulate_comp_failures_basic.test | 64 ++++++++ storage/innobase/handler/ha_innodb.cc | 6 + storage/innobase/include/srv0srv.h | 4 + storage/innobase/page/page0zip.cc | 22 +++ storage/innobase/srv/srv0srv.cc | 4 + storage/innobase/sync/sync0arr.cc | 72 +++++---- storage/xtradb/handler/ha_innodb.cc | 6 + storage/xtradb/include/srv0srv.h | 3 + storage/xtradb/page/page0zip.cc | 23 +++ storage/xtradb/srv/srv0srv.cc | 4 + storage/xtradb/sync/sync0arr.cc | 102 ++++++------ 18 files changed, 410 insertions(+), 80 deletions(-) create mode 100644 mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc create mode 100644 mysql-test/suite/innodb/r/innodb_simulate_comp_failures.result create mode 100644 mysql-test/suite/innodb/r/innodb_simulate_comp_failures_small.result create mode 100644 mysql-test/suite/innodb/t/innodb_simulate_comp_failures-master.opt create mode 100644 mysql-test/suite/innodb/t/innodb_simulate_comp_failures.test create mode 100644 mysql-test/suite/innodb/t/innodb_simulate_comp_failures_small-master.opt create mode 100644 mysql-test/suite/innodb/t/innodb_simulate_comp_failures_small.test create mode 100644 mysql-test/suite/sys_vars/t/innodb_simulate_comp_failures_basic.test diff --git a/mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc b/mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc new file mode 100644 index 0000000000..47494d6037 --- /dev/null +++ b/mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc @@ -0,0 +1,147 @@ +--echo # +--echo # Testing robustness against random compression failures +--echo # + +--source include/not_embedded.inc +--source include/have_innodb.inc + +--disable_query_log +# record the file format in order to restore in the end. +--let $file_format_save = `SELECT @@innodb_file_format` +--let $file_format_max_save = `SELECT @@innodb_file_format_max` +--let $simulate_comp_failures_save = `SELECT @@innodb_simulate_comp_failures` + +--disable_warnings +DROP TABLE IF EXISTS t1; +SET GLOBAL INNODB_FILE_FORMAT='Barracuda'; +--enable_warnings + +# since this test generates lot of errors in log, suppress checking errors +call mtr.add_suppression(".*"); +--enable_query_log + +# create the table with compressed pages of size 8K. +CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255), KEY msg_i(msg)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; + +# percentage of compressions that will be forced to fail +SET GLOBAL innodb_simulate_comp_failures = 25; + +--disable_query_log +--disable_result_log + +let $num_inserts_ind = $num_inserts; +while ($num_inserts_ind) +{ + let $repeat = `select floor(rand() * 10)`; + eval +INSERT INTO t1(id, msg) +VALUES ($num_inserts_ind, REPEAT('abcdefghijklmnopqrstuvwxyz', $repeat)); + dec $num_inserts_ind; +} + +--enable_query_log +--enable_result_log + +SELECT COUNT(*) FROM t1; + +--disable_query_log +--disable_result_log + +# do random ops, making sure that some pages will get fragmented and reorganized. +let $num_ops_ind = $num_ops; + +while($num_ops_ind) +{ + let $idx = `select floor(rand()*$num_inserts)`; + let $insert_or_update = `select floor(rand()*3)`; + + let $repeat = `select floor(rand() * 9) + 1`; + + let $msg = query_get_value(`select repeat('abcdefghijklmnopqrstuvwxyz', $repeat) as x`, x, 1); + + let $single_or_multi = `select floor(rand()*10)`; + + if ($insert_or_update) + { + let $cnt = query_get_value(SELECT COUNT(*) cnt FROM t1 WHERE id=$idx, cnt, 1); + + if ($cnt) + { + let $update = `select floor(rand()*2)`; + + if ($update) + { + if ($single_or_multi) + { + eval UPDATE t1 SET msg=\"$msg\" WHERE id=$idx; + } + + if (!$single_or_multi) + { + eval UPDATE t1 SET msg=\"$msg\" WHERE id >= $idx - 100 AND id <= $idx + 100; + } + + } + + if (!$update) + { + if ($single_or_multi) + { + eval INSERT INTO t1(msg, id) VALUES (\"$msg\", $idx) ON DUPLICATE KEY UPDATE msg=VALUES(msg), id = VALUES(id); + } + + if (!$single_or_multi) + { + let $diff = 200; + + while ($diff) + { + eval INSERT INTO t1(msg, id) VALUES (\"$msg\", $idx + 100 - $diff) ON DUPLICATE KEY UPDATE msg=VALUES(msg), id=VALUES(id); + + dec $diff; + } + } + } + } + + if (!$cnt) + { + let $null_msg = `select floor(rand()*2)`; + + if ($null_msg) + { + eval INSERT INTO t1(id,msg) VALUES ($idx, NULL); + } + + if (!$null_msg) + { + eval INSERT INTO t1(id, msg) VALUES ($idx, \"$msg\"); + } + } + } + + if (!$insert_or_update) + { + if ($single_or_multi) + { + eval DELETE from t1 WHERE id=$idx; + } + + if (!$single_or_multi) + { + eval DELETE from t1 WHERE id >= $idx - 100 AND id <= $idx + 100; + } + } + + dec $num_ops_ind; +} + +# final cleanup +DROP TABLE t1; + +# restore innodb_file_format and innodb_file_format_max +eval SET GLOBAL innodb_file_format = \"$file_format_save\"; +eval SET GLOBAL innodb_file_format_max = \"$file_format_max_save\"; +eval SET GLOBAL innodb_simulate_comp_failures = $simulate_comp_failures_save; + +--enable_query_log diff --git a/mysql-test/suite/innodb/r/innodb_simulate_comp_failures.result b/mysql-test/suite/innodb/r/innodb_simulate_comp_failures.result new file mode 100644 index 0000000000..cb7a3b9c28 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_simulate_comp_failures.result @@ -0,0 +1,8 @@ +# +# Testing robustness against random compression failures +# +CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255), KEY msg_i(msg)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; +SET GLOBAL innodb_simulate_comp_failures = 25; +SELECT COUNT(*) FROM t1; +COUNT(*) +100000 diff --git a/mysql-test/suite/innodb/r/innodb_simulate_comp_failures_small.result b/mysql-test/suite/innodb/r/innodb_simulate_comp_failures_small.result new file mode 100644 index 0000000000..1cb2cf7705 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_simulate_comp_failures_small.result @@ -0,0 +1,8 @@ +# +# Testing robustness against random compression failures +# +CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255), KEY msg_i(msg)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; +SET GLOBAL innodb_simulate_comp_failures = 25; +SELECT COUNT(*) FROM t1; +COUNT(*) +10000 diff --git a/mysql-test/suite/innodb/t/innodb_simulate_comp_failures-master.opt b/mysql-test/suite/innodb/t/innodb_simulate_comp_failures-master.opt new file mode 100644 index 0000000000..fae3205924 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_simulate_comp_failures-master.opt @@ -0,0 +1,2 @@ +--innodb-file-per-table + diff --git a/mysql-test/suite/innodb/t/innodb_simulate_comp_failures.test b/mysql-test/suite/innodb/t/innodb_simulate_comp_failures.test new file mode 100644 index 0000000000..a940a926f8 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_simulate_comp_failures.test @@ -0,0 +1,8 @@ +--source include/big_test.inc +# test takes too long with valgrind +--source include/not_valgrind.inc +--let $num_inserts = 100000 +--let $num_ops = 30000 +--source suite/innodb/include/innodb_simulate_comp_failures.inc +# clean exit +--exit diff --git a/mysql-test/suite/innodb/t/innodb_simulate_comp_failures_small-master.opt b/mysql-test/suite/innodb/t/innodb_simulate_comp_failures_small-master.opt new file mode 100644 index 0000000000..fae3205924 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_simulate_comp_failures_small-master.opt @@ -0,0 +1,2 @@ +--innodb-file-per-table + diff --git a/mysql-test/suite/innodb/t/innodb_simulate_comp_failures_small.test b/mysql-test/suite/innodb/t/innodb_simulate_comp_failures_small.test new file mode 100644 index 0000000000..7332a8c6ba --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_simulate_comp_failures_small.test @@ -0,0 +1,5 @@ +--let $num_inserts = 10000 +--let $num_ops = 3000 +--source suite/innodb/include/innodb_simulate_comp_failures.inc +# clean exit +--exit diff --git a/mysql-test/suite/sys_vars/t/innodb_simulate_comp_failures_basic.test b/mysql-test/suite/sys_vars/t/innodb_simulate_comp_failures_basic.test new file mode 100644 index 0000000000..97e69e3f32 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_simulate_comp_failures_basic.test @@ -0,0 +1,64 @@ +--source include/have_innodb.inc + +SET @start_global_value = @@global.innodb_simulate_comp_failures; +SELECT @start_global_value; + +# +# exists as global only +# + +--echo Valid values are between 0 and 99 +select @@global.innodb_simulate_comp_failures between 0 and 99; +select @@global.innodb_simulate_comp_failures; + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +select @@session.innodb_simulate_comp_failures; + +show global variables like 'innodb_simulate_comp_failures'; +show session variables like 'innodb_simulate_comp_failures'; +select * from information_schema.global_variables where variable_name='innodb_simulate_comp_failures'; +select * from information_schema.session_variables where variable_name='innodb_simulate_comp_failures'; + +# +# show that it's writable +# + +set global innodb_simulate_comp_failures=10; +select @@global.innodb_simulate_comp_failures; +select * from information_schema.global_variables where variable_name='innodb_simulate_comp_failures'; +select * from information_schema.session_variables where variable_name='innodb_simulate_comp_failures'; + +--error ER_GLOBAL_VARIABLE +set session innodb_simulate_comp_failures=1; + +# +# incorrect types +# + +--error ER_WRONG_TYPE_FOR_VAR +set global innodb_simulate_comp_failures=1.1; +--error ER_WRONG_TYPE_FOR_VAR +set global innodb_simulate_comp_failures=1e1; +--error ER_WRONG_TYPE_FOR_VAR +set global innodb_simulate_comp_failures="foo"; + +set global innodb_simulate_comp_failures=-7; +select @@global.innodb_simulate_comp_failures; +select * from information_schema.global_variables where variable_name='innodb_simulate_comp_failures'; +set global innodb_simulate_comp_failures=106; +select @@global.innodb_simulate_comp_failures; +select * from information_schema.global_variables where variable_name='innodb_simulate_comp_failures'; + +# +# min/max/DEFAULT values +# + +set global innodb_simulate_comp_failures=0; +select @@global.innodb_simulate_comp_failures; +set global innodb_simulate_comp_failures=99; +select @@global.innodb_simulate_comp_failures; +set global innodb_simulate_comp_failures=DEFAULT; +select @@global.innodb_simulate_comp_failures; + +SET @@global.innodb_simulate_comp_failures = @start_global_value; +SELECT @@global.innodb_simulate_comp_failures; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 3673dd2906..009ba9bd70 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -16793,6 +16793,11 @@ static MYSQL_SYSVAR_ULONG(saved_page_number_debug, NULL, innodb_save_page_no, 0, 0, UINT_MAX32, 0); #endif /* UNIV_DEBUG */ +static MYSQL_SYSVAR_UINT(simulate_comp_failures, srv_simulate_comp_failures, + PLUGIN_VAR_NOCMDARG, + "Simulate compression failures.", + NULL, NULL, 0, 0, 99, 0); + static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(additional_mem_pool_size), MYSQL_SYSVAR(api_trx_level), @@ -16950,6 +16955,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(fil_make_page_dirty_debug), MYSQL_SYSVAR(saved_page_number_debug), #endif /* UNIV_DEBUG */ + MYSQL_SYSVAR(simulate_comp_failures), NULL }; diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 79eaee7375..7bf698f0a6 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -3,6 +3,7 @@ Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. +Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -449,6 +450,9 @@ extern struct export_var_t export_vars; /** Global counters */ extern srv_stats_t srv_stats; +/** Simulate compression failures. */ +extern uint srv_simulate_comp_failures; + # ifdef UNIV_PFS_THREAD /* Keys to register InnoDB threads with performance schema */ extern mysql_pfs_key_t buf_page_cleaner_thread_key; diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index ab7a19795a..3b80236eb4 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -1309,6 +1309,28 @@ page_zip_compress( MONITOR_INC(MONITOR_PAGE_COMPRESS); + /* Simulate a compression failure with a probability determined by + innodb_simulate_comp_failures, only if the page has 2 or more + records. */ + + if (srv_simulate_comp_failures + && page_get_n_recs(page) >= 2 + && ((ulint)(rand() % 100) < srv_simulate_comp_failures)) { + +#ifdef UNIV_DEBUG + fprintf(stderr, + "InnoDB: Simulating a compression failure" + " for table %s, index %s, page %lu (%s)\n", + index->table_name, + index->name, + page_get_page_no(page), + page_is_leaf(page) ? "leaf" : "non-leaf"); + +#endif + + goto err_exit; + } + heap = mem_heap_create(page_zip_get_size(page_zip) + n_fields * (2 + sizeof(ulint)) + REC_OFFS_HEADER_SIZE diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 9b52ba4215..d9ace82834 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -3,6 +3,7 @@ Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. +Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -465,6 +466,9 @@ current_time % 5 != 0. */ #endif /* MEM_PERIODIC_CHECK */ # define SRV_MASTER_DICT_LRU_INTERVAL (47) +/** Simulate compression failures. */ +UNIV_INTERN uint srv_simulate_comp_failures = 0; + /** Acquire the system_mutex. */ #define srv_sys_mutex_enter() do { \ mutex_enter(&srv_sys->mutex); \ diff --git a/storage/innobase/sync/sync0arr.cc b/storage/innobase/sync/sync0arr.cc index 2cfb693f8b..8e1b8180eb 100644 --- a/storage/innobase/sync/sync0arr.cc +++ b/storage/innobase/sync/sync0arr.cc @@ -454,19 +454,21 @@ sync_array_cell_print( been freed meanwhile */ mutex = cell->old_wait_mutex; - fprintf(file, - "Mutex at %p created file %s line %lu, lock var %lu\n" + if (mutex) { + fprintf(file, + "Mutex at %p created file %s line %lu, lock var %lu\n" #ifdef UNIV_SYNC_DEBUG - "Last time reserved in file %s line %lu, " + "Last time reserved in file %s line %lu, " #endif /* UNIV_SYNC_DEBUG */ - "waiters flag %lu\n", - (void*) mutex, innobase_basename(mutex->cfile_name), - (ulong) mutex->cline, - (ulong) mutex->lock_word, + "waiters flag %lu\n", + (void*) mutex, innobase_basename(mutex->cfile_name), + (ulong) mutex->cline, + (ulong) mutex->lock_word, #ifdef UNIV_SYNC_DEBUG - mutex->file_name, (ulong) mutex->line, + mutex->file_name, (ulong) mutex->line, #endif /* UNIV_SYNC_DEBUG */ - (ulong) mutex->waiters); + (ulong) mutex->waiters); + } } else if (type == RW_LOCK_EX || type == RW_LOCK_WAIT_EX @@ -478,33 +480,35 @@ sync_array_cell_print( rwlock = cell->old_wait_rw_lock; - fprintf(file, - " RW-latch at %p created in file %s line %lu\n", - (void*) rwlock, innobase_basename(rwlock->cfile_name), - (ulong) rwlock->cline); - writer = rw_lock_get_writer(rwlock); - if (writer != RW_LOCK_NOT_LOCKED) { + if (rwlock) { fprintf(file, - "a writer (thread id %lu) has" - " reserved it in mode %s", - (ulong) os_thread_pf(rwlock->writer_thread), - writer == RW_LOCK_EX - ? " exclusive\n" - : " wait exclusive\n"); - } + " RW-latch at %p created in file %s line %lu\n", + (void*) rwlock, innobase_basename(rwlock->cfile_name), + (ulong) rwlock->cline); + writer = rw_lock_get_writer(rwlock); + if (writer != RW_LOCK_NOT_LOCKED) { + fprintf(file, + "a writer (thread id %lu) has" + " reserved it in mode %s", + (ulong) os_thread_pf(rwlock->writer_thread), + writer == RW_LOCK_EX + ? " exclusive\n" + : " wait exclusive\n"); + } - fprintf(file, - "number of readers %lu, waiters flag %lu, " - "lock_word: %lx\n" - "Last time read locked in file %s line %lu\n" - "Last time write locked in file %s line %lu\n", - (ulong) rw_lock_get_reader_count(rwlock), - (ulong) rwlock->waiters, - rwlock->lock_word, - innobase_basename(rwlock->last_s_file_name), - (ulong) rwlock->last_s_line, - rwlock->last_x_file_name, - (ulong) rwlock->last_x_line); + fprintf(file, + "number of readers %lu, waiters flag %lu, " + "lock_word: %lx\n" + "Last time read locked in file %s line %lu\n" + "Last time write locked in file %s line %lu\n", + (ulong) rw_lock_get_reader_count(rwlock), + (ulong) rwlock->waiters, + rwlock->lock_word, + innobase_basename(rwlock->last_s_file_name), + (ulong) rwlock->last_s_line, + rwlock->last_x_file_name, + (ulong) rwlock->last_x_line); + } } else { ut_error; } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index d5f0966cda..9159def162 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -17938,6 +17938,11 @@ static MYSQL_SYSVAR_ULONG(saved_page_number_debug, NULL, innodb_save_page_no, 0, 0, UINT_MAX32, 0); #endif /* UNIV_DEBUG */ +static MYSQL_SYSVAR_UINT(simulate_comp_failures, srv_simulate_comp_failures, + PLUGIN_VAR_NOCMDARG, + "Simulate compression failures.", + NULL, NULL, 0, 0, 99, 0); + const char *corrupt_table_action_names[]= { "assert", /* 0 */ @@ -18165,6 +18170,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(fake_changes), MYSQL_SYSVAR(locking_fake_changes), MYSQL_SYSVAR(use_stacktrace), + MYSQL_SYSVAR(simulate_comp_failures), NULL }; diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index 4bbace02eb..d7e77842b7 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -3,6 +3,7 @@ Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. +Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -587,6 +588,8 @@ extern srv_stats_t srv_stats; When FALSE, row locks are not taken at all. */ extern my_bool srv_fake_changes_locks; +/** Simulate compression failures. */ +extern uint srv_simulate_comp_failures; # ifdef UNIV_PFS_THREAD /* Keys to register InnoDB threads with performance schema */ diff --git a/storage/xtradb/page/page0zip.cc b/storage/xtradb/page/page0zip.cc index 1e533a4bbb..923684964a 100644 --- a/storage/xtradb/page/page0zip.cc +++ b/storage/xtradb/page/page0zip.cc @@ -2,6 +2,7 @@ Copyright (c) 2005, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2014, SkySQL Ab. 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 @@ -1313,6 +1314,28 @@ page_zip_compress( MONITOR_INC(MONITOR_PAGE_COMPRESS); + /* Simulate a compression failure with a probability determined by + innodb_simulate_comp_failures, only if the page has 2 or more + records. */ + + if (srv_simulate_comp_failures + && page_get_n_recs(page) >= 2 + && ((ulint)(rand() % 100) < srv_simulate_comp_failures)) { + +#ifdef UNIV_DEBUG + fprintf(stderr, + "InnoDB: Simulating a compression failure" + " for table %s, index %s, page %lu (%s)\n", + index->table_name, + index->name, + page_get_page_no(page), + page_is_leaf(page) ? "leaf" : "non-leaf"); + +#endif + + goto err_exit; + } + heap = mem_heap_create(page_zip_get_size(page_zip) + n_fields * (2 + sizeof(ulint)) + REC_OFFS_HEADER_SIZE diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index b9ed26b9c9..001a9257c9 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -3,6 +3,7 @@ Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. +Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -619,6 +620,9 @@ current_time % 5 != 0. */ ? thd_lock_wait_timeout((trx)->mysql_thd) \ : 0) +/** Simulate compression failures. */ +UNIV_INTERN uint srv_simulate_comp_failures = 0; + /* IMPLEMENTATION OF THE SERVER MAIN PROGRAM ========================================= diff --git a/storage/xtradb/sync/sync0arr.cc b/storage/xtradb/sync/sync0arr.cc index 126cf8de0d..880f47237d 100644 --- a/storage/xtradb/sync/sync0arr.cc +++ b/storage/xtradb/sync/sync0arr.cc @@ -2,6 +2,7 @@ Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. +Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -460,16 +461,9 @@ sync_array_cell_print( innobase_basename(cell->file), (ulong) cell->line, difftime(time(NULL), cell->reservation_time)); - /* If stacktrace feature is enabled we will send a SIGUSR2 - signal to thread waiting for the semaphore. Signal handler - will then dump the current stack to error log. */ - if (srv_use_stacktrace) { -#ifdef __linux__ - pthread_kill(cell->thread, SIGUSR2); -#endif - } if (type == SYNC_MUTEX || type == SYNC_PRIO_MUTEX) { + /* We use old_wait_mutex in case the cell has already been freed meanwhile */ if (type == SYNC_MUTEX) { @@ -483,18 +477,29 @@ sync_array_cell_print( } - fprintf(file, - "Mutex at %p '%s', lock var %lu\n" + if (mutex) { + fprintf(file, + "Mutex at %p '%s', lock var %lu\n" #ifdef UNIV_SYNC_DEBUG - "Last time reserved in file %s line %lu, " + "Last time reserved in file %s line %lu, " #endif /* UNIV_SYNC_DEBUG */ - "waiters flag %lu\n", - (void*) mutex, mutex->cmutex_name, - (ulong) mutex->lock_word, + "waiters flag %lu\n", + (void*) mutex, mutex->cmutex_name, + (ulong) mutex->lock_word, #ifdef UNIV_SYNC_DEBUG - mutex->file_name, (ulong) mutex->line, + mutex->file_name, (ulong) mutex->line, #endif /* UNIV_SYNC_DEBUG */ - (ulong) mutex->waiters); + (ulong) mutex->waiters); + } + + /* If stacktrace feature is enabled we will send a SIGUSR2 + signal to thread waiting for the semaphore. Signal handler + will then dump the current stack to error log. */ + if (srv_use_stacktrace && cell && cell->thread) { +#ifdef __linux__ + pthread_kill(cell->thread, SIGUSR2); +#endif + } if (type == SYNC_PRIO_MUTEX) { @@ -529,40 +534,45 @@ sync_array_cell_print( rwlock = &prio_rwlock->base_lock; } - fprintf(file, - " RW-latch at %p '%s'\n", - (void*) rwlock, rwlock->lock_name); - writer = rw_lock_get_writer(rwlock); - if (writer != RW_LOCK_NOT_LOCKED) { + if (rwlock) { fprintf(file, - "a writer (thread id %lu) has" - " reserved it in mode %s", - (ulong) os_thread_pf(rwlock->writer_thread), - writer == RW_LOCK_EX - ? " exclusive\n" - : " wait exclusive\n"); - } - - fprintf(file, - "number of readers %lu, waiters flag %lu, " - "lock_word: %lx\n" - "Last time read locked in file %s line %lu\n" - "Last time write locked in file %s line %lu\n", - (ulong) rw_lock_get_reader_count(rwlock), - (ulong) rwlock->waiters, - rwlock->lock_word, - innobase_basename(rwlock->last_s_file_name), - (ulong) rwlock->last_s_line, - rwlock->last_x_file_name, - (ulong) rwlock->last_x_line); + " RW-latch at %p '%s'\n", + (void*) rwlock, rwlock->lock_name); + + writer = rw_lock_get_writer(rwlock); + + if (writer && writer != RW_LOCK_NOT_LOCKED) { + fprintf(file, + "a writer (thread id %lu) has" + " reserved it in mode %s", + (ulong) os_thread_pf(rwlock->writer_thread), + writer == RW_LOCK_EX + ? " exclusive\n" + : " wait exclusive\n"); + } - /* If stacktrace feature is enabled we will send a SIGUSR2 - signal to thread that has locked RW-latch with write mode. - Signal handler will then dump the current stack to error log. */ - if (writer != RW_LOCK_NOT_LOCKED && srv_use_stacktrace) { + fprintf(file, + "number of readers %lu, waiters flag %lu, " + "lock_word: %lx\n" + "Last time read locked in file %s line %lu\n" + "Last time write locked in file %s line %lu\n", + (ulong) rw_lock_get_reader_count(rwlock), + (ulong) rwlock->waiters, + rwlock->lock_word, + innobase_basename(rwlock->last_s_file_name), + (ulong) rwlock->last_s_line, + rwlock->last_x_file_name, + (ulong) rwlock->last_x_line); + + /* If stacktrace feature is enabled we will send a SIGUSR2 + signal to thread that has locked RW-latch with write mode. + Signal handler will then dump the current stack to error log. */ + if (writer != RW_LOCK_NOT_LOCKED && srv_use_stacktrace && + rwlock && rwlock->writer_thread) { #ifdef __linux__ - pthread_kill(rwlock->writer_thread, SIGUSR2); + pthread_kill(rwlock->writer_thread, SIGUSR2); #endif + } } if (prio_rwlock) { -- 2.30.9