summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Lindström <jan.lindstrom@skysql.com>2015-02-21 21:45:16 +0200
committerJan Lindström <jan.lindstrom@skysql.com>2015-02-21 21:45:16 +0200
commit1cc7befc14cd2ad637ffb6fc29fae0f978735acf (patch)
tree8221773550b173d5b1d41243605b1f5ad72fe7f3
parent9152b83973419ea034bb6040703c18b3ee87e084 (diff)
downloadmariadb-git-1cc7befc14cd2ad637ffb6fc29fae0f978735acf.tar.gz
MDEV-7109: Add support for INFORMATION_SCHEMA.INNODB_SEMAPHORE_WAITS
MDEV-7399: Add support for INFORMATION_SCHEMA.INNODB_MUTEXES MDEV-7618: Improve semaphore instrumentation Introduced two new information schema tables to monitor mutex waits and semaphore waits. Added a new configuration variable innodb_intrument_semaphores to add thread_id, file name and line of current holder of mutex/rw_lock.
-rw-r--r--mysql-test/r/information_schema_all_engines.result8
-rw-r--r--mysql-test/suite/innodb/r/innodb_mutexes.result21
-rw-r--r--mysql-test/suite/innodb/r/innodb_sys_semaphore_waits.result26
-rw-r--r--mysql-test/suite/innodb/t/innodb_mutexes-master.opt1
-rw-r--r--mysql-test/suite/innodb/t/innodb_mutexes.test66
-rw-r--r--mysql-test/suite/innodb/t/innodb_sys_semaphore_waits-master.opt3
-rw-r--r--mysql-test/suite/innodb/t/innodb_sys_semaphore_waits.test119
-rw-r--r--mysql-test/suite/sys_vars/r/all_vars.result1
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_instrument_semaphores.result45
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_innodb.result14
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_instrument_semaphores.test42
-rw-r--r--mysql-test/t/information_schema_all_engines-master.opt1
-rw-r--r--storage/innobase/handler/ha_innodb.cc9
-rw-r--r--storage/innobase/handler/i_s.cc551
-rw-r--r--storage/innobase/handler/i_s.h88
-rw-r--r--storage/innobase/include/srv0srv.h3
-rw-r--r--storage/innobase/include/sync0arr.h12
-rw-r--r--storage/innobase/include/sync0rw.h13
-rw-r--r--storage/innobase/include/sync0rw.ic16
-rw-r--r--storage/innobase/include/sync0sync.h21
-rw-r--r--storage/innobase/include/sync0sync.ic13
-rw-r--r--storage/innobase/srv/srv0srv.cc6
-rw-r--r--storage/innobase/sync/sync0arr.cc170
-rw-r--r--storage/innobase/sync/sync0rw.cc22
-rw-r--r--storage/innobase/sync/sync0sync.cc26
-rw-r--r--storage/xtradb/handler/ha_innodb.cc10
-rw-r--r--storage/xtradb/handler/i_s.cc550
-rw-r--r--storage/xtradb/handler/i_s.h87
-rw-r--r--storage/xtradb/handler/xtradb_i_s.cc89
-rw-r--r--storage/xtradb/include/srv0srv.h3
-rw-r--r--storage/xtradb/include/sync0arr.h12
-rw-r--r--storage/xtradb/include/sync0rw.h46
-rw-r--r--storage/xtradb/include/sync0rw.ic36
-rw-r--r--storage/xtradb/include/sync0sync.h36
-rw-r--r--storage/xtradb/include/sync0sync.ic26
-rw-r--r--storage/xtradb/srv/srv0srv.cc6
-rw-r--r--storage/xtradb/sync/sync0arr.cc189
-rw-r--r--storage/xtradb/sync/sync0rw.cc47
-rw-r--r--storage/xtradb/sync/sync0sync.cc32
39 files changed, 2173 insertions, 293 deletions
diff --git a/mysql-test/r/information_schema_all_engines.result b/mysql-test/r/information_schema_all_engines.result
index 731fabf57f5..7f79dd883e2 100644
--- a/mysql-test/r/information_schema_all_engines.result
+++ b/mysql-test/r/information_schema_all_engines.result
@@ -24,6 +24,7 @@ INNODB_CMPMEM_RESET
INNODB_CMP_PER_INDEX
INNODB_CMP_RESET
INNODB_LOCK_WAITS
+INNODB_MUTEXES
INNODB_SYS_COLUMNS
INNODB_SYS_FIELDS
INNODB_SYS_FOREIGN
@@ -97,6 +98,7 @@ INNODB_CMPMEM_RESET page_size
INNODB_CMP_PER_INDEX database_name
INNODB_CMP_RESET page_size
INNODB_LOCK_WAITS requesting_trx_id
+INNODB_MUTEXES NAME
INNODB_SYS_COLUMNS TABLE_ID
INNODB_SYS_FIELDS INDEX_ID
INNODB_SYS_FOREIGN ID
@@ -170,6 +172,7 @@ INNODB_CMPMEM_RESET page_size
INNODB_CMP_PER_INDEX database_name
INNODB_CMP_RESET page_size
INNODB_LOCK_WAITS requesting_trx_id
+INNODB_MUTEXES NAME
INNODB_SYS_COLUMNS TABLE_ID
INNODB_SYS_FIELDS INDEX_ID
INNODB_SYS_FOREIGN ID
@@ -248,6 +251,7 @@ INNODB_CMPMEM_RESET information_schema.INNODB_CMPMEM_RESET 1
INNODB_CMP_PER_INDEX information_schema.INNODB_CMP_PER_INDEX 1
INNODB_CMP_RESET information_schema.INNODB_CMP_RESET 1
INNODB_LOCK_WAITS information_schema.INNODB_LOCK_WAITS 1
+INNODB_MUTEXES information_schema.INNODB_MUTEXES 1
INNODB_SYS_COLUMNS information_schema.INNODB_SYS_COLUMNS 1
INNODB_SYS_FIELDS information_schema.INNODB_SYS_FIELDS 1
INNODB_SYS_FOREIGN information_schema.INNODB_SYS_FOREIGN 1
@@ -311,6 +315,7 @@ Database: information_schema
| INNODB_CMP_PER_INDEX |
| INNODB_CMP_RESET |
| INNODB_LOCK_WAITS |
+| INNODB_MUTEXES |
| INNODB_SYS_COLUMNS |
| INNODB_SYS_FIELDS |
| INNODB_SYS_FOREIGN |
@@ -374,6 +379,7 @@ Database: INFORMATION_SCHEMA
| INNODB_CMP_PER_INDEX |
| INNODB_CMP_RESET |
| INNODB_LOCK_WAITS |
+| INNODB_MUTEXES |
| INNODB_SYS_COLUMNS |
| INNODB_SYS_FIELDS |
| INNODB_SYS_FOREIGN |
@@ -417,5 +423,5 @@ Wildcard: inf_rmation_schema
| information_schema |
SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') GROUP BY TABLE_SCHEMA;
table_schema count(*)
-information_schema 58
+information_schema 59
mysql 30
diff --git a/mysql-test/suite/innodb/r/innodb_mutexes.result b/mysql-test/suite/innodb/r/innodb_mutexes.result
new file mode 100644
index 00000000000..129d7f0762b
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb_mutexes.result
@@ -0,0 +1,21 @@
+create table t1(a int not null primary key, b int, c int,d CHAR(100)) engine=innodb;
+create procedure innodb_insert_proc (repeat_count int)
+begin
+declare current_num int;
+set current_num = 0;
+while current_num < repeat_count do
+insert into t1 values(current_num, RAND(), RAND(), substring(MD5(RAND()), -64));
+set current_num = current_num + 1;
+end while;
+end//
+commit;
+set autocommit=0;
+call innodb_insert_proc(20000);
+commit;
+set autocommit=1;
+delete from t1 where a between 1000 and 1300;
+update t1 set b=b+1 where a between 2000 and 2600;
+insert into t1 select a+30000,b,c,d from t1 where a between 3000 and 4000;
+delete from t1 where a between 6000 and 7000;
+drop procedure innodb_insert_proc;
+drop table t1;
diff --git a/mysql-test/suite/innodb/r/innodb_sys_semaphore_waits.result b/mysql-test/suite/innodb/r/innodb_sys_semaphore_waits.result
new file mode 100644
index 00000000000..4164e043b2c
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb_sys_semaphore_waits.result
@@ -0,0 +1,26 @@
+# Establish connection con1 (user=root)
+# Establish connection con2 (user=root)
+drop table if exists t1;
+# Switch to connection con1
+create table t1 (id integer, x integer) engine = InnoDB;
+insert into t1 values(0, 0);
+set DEBUG_DBUG='+d,fatal-semaphore-timeout';
+set autocommit=0;
+# Sending query on con1,
+# the session will hold lock table mutex and sleep
+SELECT * from t1 where id = 0 FOR UPDATE;
+# Switch to connection con2
+set autocommit=0;
+# Sending query on con2,
+# the session will be blocked on the lock table mutex and
+# thus be put into sync arry
+SELECT * from t1 where id = 0 FOR UPDATE;
+# Switched to the default connection
+# Waitting for mysqld to crash
+# Mysqld crash was detected
+# Waitting for reconnect after mysqld restarts
+# Reconnected after mysqld was successfully restarted
+# Cleaning up before exit
+set DEBUG_DBUG=NULL;
+drop table if exists t1;
+# Clean exit
diff --git a/mysql-test/suite/innodb/t/innodb_mutexes-master.opt b/mysql-test/suite/innodb/t/innodb_mutexes-master.opt
new file mode 100644
index 00000000000..493faf1903e
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb_mutexes-master.opt
@@ -0,0 +1 @@
+--innodb-mutexes \ No newline at end of file
diff --git a/mysql-test/suite/innodb/t/innodb_mutexes.test b/mysql-test/suite/innodb/t/innodb_mutexes.test
new file mode 100644
index 00000000000..3b6b949c25d
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb_mutexes.test
@@ -0,0 +1,66 @@
+--source include/have_innodb.inc
+
+connect(con1,localhost,root,,);
+connect(con2,localhost,root,,);
+connect(con3,localhost,root,,);
+
+create table t1(a int not null primary key, b int, c int,d CHAR(100)) engine=innodb;
+
+delimiter //;
+create procedure innodb_insert_proc (repeat_count int)
+begin
+ declare current_num int;
+ set current_num = 0;
+ while current_num < repeat_count do
+ insert into t1 values(current_num, RAND(), RAND(), substring(MD5(RAND()), -64));
+ set current_num = current_num + 1;
+ end while;
+end//
+delimiter ;//
+commit;
+
+set autocommit=0;
+call innodb_insert_proc(20000);
+commit;
+set autocommit=1;
+
+connection con1;
+send delete from t1 where a between 1000 and 1300;
+
+connection con2;
+send update t1 set b=b+1 where a between 2000 and 2600;
+
+connection con3;
+send insert into t1 select a+30000,b,c,d from t1 where a between 3000 and 4000;
+
+connection default;
+send delete from t1 where a between 6000 and 7000;
+
+connection con1;
+reap;
+
+connection con2;
+reap;
+
+connection con3;
+reap;
+
+connection default;
+reap;
+
+disconnect con1;
+disconnect con2;
+disconnect con3;
+
+# test that below does not crash, actual result is not
+# repeatable
+--disable_query_log
+--disable_result_log
+--disable_warnings
+select * from information_schema.innodb_mutexes;
+--enable_query_log
+--enable_result_log
+--enable_warnings
+
+drop procedure innodb_insert_proc;
+drop table t1; \ No newline at end of file
diff --git a/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits-master.opt b/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits-master.opt
new file mode 100644
index 00000000000..22272485540
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits-master.opt
@@ -0,0 +1,3 @@
+--innodb-fatal-semaphore-wait-threshold=1
+--innodb-sys-semaphore-waits=1
+--innodb-instrument-semaphores=1
diff --git a/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits.test b/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits.test
new file mode 100644
index 00000000000..eda798e4e12
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits.test
@@ -0,0 +1,119 @@
+--source include/have_innodb.inc
+--source include/not_windows.inc
+--source include/not_valgrind.inc
+--source include/not_embedded.inc
+# DEBUG_SYNC must be compiled in.
+--source include/have_debug_sync.inc
+
+--echo # Establish connection con1 (user=root)
+connect (con1,localhost,root,,);
+--echo # Establish connection con2 (user=root)
+connect (con2,localhost,root,,);
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+--echo # Switch to connection con1
+connection con1;
+eval create table t1 (id integer, x integer) engine = InnoDB;
+insert into t1 values(0, 0);
+
+# Enable the debug injection.
+set DEBUG_DBUG='+d,fatal-semaphore-timeout';
+set autocommit=0;
+
+# The following query will hang for an hour since the debug injection
+# code will sleep an hour after holding the lock table mutex
+--echo # Sending query on con1,
+--echo # the session will hold lock table mutex and sleep
+--send
+SELECT * from t1 where id = 0 FOR UPDATE;
+
+# To make sure con1 holding the lock table mutex and sleeping
+--sleep 2
+
+--echo # Switch to connection con2
+connection con2;
+set autocommit=0;
+
+# The following query will be blocked on the lock table mutex held by
+# con1 so it will be put into sync array.
+--echo # Sending query on con2,
+--echo # the session will be blocked on the lock table mutex and
+--echo # thus be put into sync arry
+--send
+SELECT * from t1 where id = 0 FOR UPDATE;
+
+# Waitting for mysqld to abort due to fatal semaphore timeout.
+# Please note that, in the master.opt file, the fatal timeout
+# was set to 1 second, but in mysqld debug mode, this timeout
+# value will be timed 10 because UNIV_DEBUG_VALGRIND is set
+# (see sync_array_print_long_waits_low() in storage/innobase/sync/sync0arr.cc)
+# so the actual timeout will be 1 * 10 = 10 seconds. Besides,
+# mysqld will abort after detecting this fatal timeout 10 times in
+# a loop with interval of 1 second (see srv_error_monitor_thread
+# thread in torage/innobase/srv/srv0srv.cc), so mysqld will abort
+# in 1 * 10 + 1 * 10 = 20 seconds after con2 being blocked on
+# the lock table mutex.
+#
+# P.S. the default fatal sempahore timeout is 600 seconds,
+# so mysqld will abort after 600 * 10 + 1 * 10 = 6010 seconds
+# in debug mode and 600 + 1 * 10 = 610 seconds in release mode.
+
+--echo # Switched to the default connection
+connection default;
+
+--disable_result_log
+--disable_query_log
+
+# Since this test generates lot of errors in log, suppress checking errors
+call mtr.add_suppression(".*");
+
+# The crash is expected
+exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect;
+
+--echo # Waitting for mysqld to crash
+
+# It will take 20 seconds to detect the long semaphore and mysqld to abort.
+# This test will be treated as pass as long as mysqld crash/restart is dectected
+# in 60 seconds.
+let $counter= 60;
+let $mysql_errno= 0;
+while (!$mysql_errno)
+{
+ --error 0,1040,1053,2002,2003,2006,2013
+ show status;
+
+ --error 0,1040,1053,2002,2003,2006,2013
+ select * from information_schema.innodb_sys_semaphore_waits;
+
+ dec $counter;
+ if (!$counter)
+ {
+ # This will fail this test.
+ --die Server failed to dissapear
+ }
+ --sleep 1
+}
+
+--echo # Mysqld crash was detected
+--echo # Waitting for reconnect after mysqld restarts
+
+enable_reconnect;
+connection default;
+
+--exec echo "restart:--log-error=$error_log" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+
+# Call script that will poll the server waiting for it to be back online again
+source include/wait_until_connected_again.inc;
+
+--echo # Reconnected after mysqld was successfully restarted
+
+--echo # Cleaning up before exit
+--disable_warnings
+set DEBUG_DBUG=NULL;
+drop table if exists t1;
+--enable_warnings
+
+--echo # Clean exit
diff --git a/mysql-test/suite/sys_vars/r/all_vars.result b/mysql-test/suite/sys_vars/r/all_vars.result
index 840da8405c3..0ace47d1378 100644
--- a/mysql-test/suite/sys_vars/r/all_vars.result
+++ b/mysql-test/suite/sys_vars/r/all_vars.result
@@ -10,6 +10,7 @@ there should be *no* long test name listed below:
select distinct variable_name as `there should be *no* variables listed below:` from t2
left join t1 on variable_name=test_name where test_name is null;
there should be *no* variables listed below:
+innodb_instrument_semaphores
strict_password_validation
drop table t1;
drop table t2;
diff --git a/mysql-test/suite/sys_vars/r/innodb_instrument_semaphores.result b/mysql-test/suite/sys_vars/r/innodb_instrument_semaphores.result
new file mode 100644
index 00000000000..dc8fba41e0b
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/innodb_instrument_semaphores.result
@@ -0,0 +1,45 @@
+#
+# innodb_instrument_semaphores
+#
+# save the initial value
+SET @innodb_instrument_semaphores_global_saved = @@global.innodb_instrument_semaphores;
+# default
+SELECT @@global.innodb_instrument_semaphores;
+@@global.innodb_instrument_semaphores
+0
+
+# scope
+SELECT @@session.innodb_instrument_semaphores;
+ERROR HY000: Variable 'innodb_instrument_semaphores' is a GLOBAL variable
+SET @@global.innodb_instrument_semaphores=OFF;
+SELECT @@global.innodb_instrument_semaphores;
+@@global.innodb_instrument_semaphores
+0
+SET @@global.innodb_instrument_semaphores=ON;
+SELECT @@global.innodb_instrument_semaphores;
+@@global.innodb_instrument_semaphores
+1
+
+# valid values
+SET @@global.innodb_instrument_semaphores='OFF';
+SELECT @@global.innodb_instrument_semaphores;
+@@global.innodb_instrument_semaphores
+0
+SET @@global.innodb_instrument_semaphores=ON;
+SELECT @@global.innodb_instrument_semaphores;
+@@global.innodb_instrument_semaphores
+1
+SET @@global.innodb_instrument_semaphores=default;
+SELECT @@global.innodb_instrument_semaphores;
+@@global.innodb_instrument_semaphores
+0
+
+# invalid values
+SET @@global.innodb_instrument_semaphores=NULL;
+ERROR 42000: Variable 'innodb_instrument_semaphores' can't be set to the value of 'NULL'
+SET @@global.innodb_instrument_semaphores='junk';
+ERROR 42000: Variable 'innodb_instrument_semaphores' can't be set to the value of 'junk'
+
+# restore the initial value
+SET @@global.innodb_instrument_semaphores = @innodb_instrument_semaphores_global_saved;
+# End of test
diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
index b3e974a75f6..030b8cd367c 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
@@ -1209,6 +1209,20 @@ NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
+VARIABLE_NAME INNODB_INSTRUMENT_SEMAPHORES
+SESSION_VALUE NULL
+GLOBAL_VALUE OFF
+GLOBAL_VALUE_ORIGIN COMPILE-TIME
+DEFAULT_VALUE OFF
+VARIABLE_SCOPE GLOBAL
+VARIABLE_TYPE BOOLEAN
+VARIABLE_COMMENT Enable semaphore request instrumentation. This could have some effect on performance but allows better information on long semaphore wait problems. (Default: not enabled)
+NUMERIC_MIN_VALUE NULL
+NUMERIC_MAX_VALUE NULL
+NUMERIC_BLOCK_SIZE NULL
+ENUM_VALUE_LIST NULL
+READ_ONLY NO
+COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_IO_CAPACITY
SESSION_VALUE NULL
GLOBAL_VALUE 200
diff --git a/mysql-test/suite/sys_vars/t/innodb_instrument_semaphores.test b/mysql-test/suite/sys_vars/t/innodb_instrument_semaphores.test
new file mode 100644
index 00000000000..9b302be79b5
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/innodb_instrument_semaphores.test
@@ -0,0 +1,42 @@
+--source include/have_innodb.inc
+
+--echo #
+--echo # innodb_instrument_semaphores
+--echo #
+
+--echo # save the initial value
+SET @innodb_instrument_semaphores_global_saved = @@global.innodb_instrument_semaphores;
+
+--echo # default
+SELECT @@global.innodb_instrument_semaphores;
+
+--echo
+--echo # scope
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT @@session.innodb_instrument_semaphores;
+SET @@global.innodb_instrument_semaphores=OFF;
+SELECT @@global.innodb_instrument_semaphores;
+SET @@global.innodb_instrument_semaphores=ON;
+SELECT @@global.innodb_instrument_semaphores;
+
+--echo
+--echo # valid values
+SET @@global.innodb_instrument_semaphores='OFF';
+SELECT @@global.innodb_instrument_semaphores;
+SET @@global.innodb_instrument_semaphores=ON;
+SELECT @@global.innodb_instrument_semaphores;
+SET @@global.innodb_instrument_semaphores=default;
+SELECT @@global.innodb_instrument_semaphores;
+
+--echo
+--echo # invalid values
+--error ER_WRONG_VALUE_FOR_VAR
+SET @@global.innodb_instrument_semaphores=NULL;
+--error ER_WRONG_VALUE_FOR_VAR
+SET @@global.innodb_instrument_semaphores='junk';
+
+--echo
+--echo # restore the initial value
+SET @@global.innodb_instrument_semaphores = @innodb_instrument_semaphores_global_saved;
+
+--echo # End of test
diff --git a/mysql-test/t/information_schema_all_engines-master.opt b/mysql-test/t/information_schema_all_engines-master.opt
index dec3b51813f..43411c5033a 100644
--- a/mysql-test/t/information_schema_all_engines-master.opt
+++ b/mysql-test/t/information_schema_all_engines-master.opt
@@ -13,5 +13,6 @@
--loose-innodb-sys-foreign-cols
--loose-innodb-sys-tables
--loose-innodb-sys-tablestats
+--loose-innodb-mutexes
--loose-innodb-tablespaces-encryption
--loose-innodb-tablespaces-scrubbing
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index a8cece74666..bd81ae2bb26 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -19221,6 +19221,12 @@ static MYSQL_SYSVAR_BOOL(scrub_force_testing,
NULL, NULL, FALSE);
#endif /* UNIV_DEBUG */
+static MYSQL_SYSVAR_BOOL(instrument_semaphores, srv_instrument_semaphores,
+ PLUGIN_VAR_OPCMDARG,
+ "Enable semaphore request instrumentation. This could have some effect on performance but allows better"
+ " information on long semaphore wait problems. (Default: not enabled)",
+ 0, 0, FALSE);
+
static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(additional_mem_pool_size),
MYSQL_SYSVAR(api_trx_level),
@@ -19418,6 +19424,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
#ifdef UNIV_DEBUG
MYSQL_SYSVAR(scrub_force_testing),
#endif
+ MYSQL_SYSVAR(instrument_semaphores),
NULL
};
@@ -19465,6 +19472,8 @@ i_s_innodb_sys_foreign,
i_s_innodb_sys_foreign_cols,
i_s_innodb_sys_tablespaces,
i_s_innodb_sys_datafiles,
+i_s_innodb_mutexes,
+i_s_innodb_sys_semaphore_waits,
i_s_innodb_tablespaces_encryption,
i_s_innodb_tablespaces_scrubbing
maria_declare_plugin_end;
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index f0202e232b7..3664c05e69e 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyrigth (c) 2014, 2015, MariaDB Corporation
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
@@ -21,8 +22,11 @@ this program; if not, write to the Free Software Foundation, Inc.,
InnoDB INFORMATION SCHEMA tables interface to MySQL.
Created July 18, 2007 Vasil Dimov
+Modified Dec 29, 2014 Jan Lindström (Added sys_semaphore_waits)
*******************************************************/
+#include "univ.i"
+
#include <mysqld_error.h>
#include <sql_acl.h>
@@ -56,6 +60,7 @@ Created July 18, 2007 Vasil Dimov
#include "fts0priv.h"
#include "btr0btr.h"
#include "page0zip.h"
+#include "sync0arr.h"
/** structure associates a name string with a file page type and/or buffer
page state. */
@@ -137,45 +142,6 @@ struct buf_page_info_t{
index_id_t index_id; /*!< Index ID if a index page */
};
-/** maximum number of buffer page info we would cache. */
-#define MAX_BUF_INFO_CACHED 10000
-
-#define OK(expr) \
- if ((expr) != 0) { \
- DBUG_RETURN(1); \
- }
-
-#define RETURN_IF_INNODB_NOT_STARTED(plugin_name) \
-do { \
- if (!srv_was_started) { \
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, \
- ER_CANT_FIND_SYSTEM_REC, \
- "InnoDB: SELECTing from " \
- "INFORMATION_SCHEMA.%s but " \
- "the InnoDB storage engine " \
- "is not installed", plugin_name); \
- DBUG_RETURN(0); \
- } \
-} while (0)
-
-#if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 && \
- !defined __INTEL_COMPILER && !defined __clang__
-#define STRUCT_FLD(name, value) name: value
-#else
-#define STRUCT_FLD(name, value) value
-#endif
-
-/* Don't use a static const variable here, as some C++ compilers (notably
-HPUX aCC: HP ANSI C++ B3910B A.03.65) can't handle it. */
-#define END_OF_ST_FIELD_INFO \
- {STRUCT_FLD(field_name, NULL), \
- STRUCT_FLD(field_length, 0), \
- STRUCT_FLD(field_type, MYSQL_TYPE_NULL), \
- STRUCT_FLD(value, 0), \
- STRUCT_FLD(field_flags, 0), \
- STRUCT_FLD(old_name, ""), \
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}
-
/*
Use the following types mapping:
@@ -204,6 +170,20 @@ time_t MYSQL_TYPE_DATETIME
---------------------------------
*/
+/** Implemented on sync0arr.cc */
+/*******************************************************************//**
+Function to populate INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
+Loop through each item on sync array, and extract the column
+information and fill the INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
+@return 0 on success */
+UNIV_INTERN
+int
+sync_arr_fill_sys_semphore_waits_table(
+/*===================================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ Item* ); /*!< in: condition (not used) */
+
/*******************************************************************//**
Common function to fill any of the dynamic tables:
INFORMATION_SCHEMA.innodb_trx
@@ -261,7 +241,6 @@ field_store_time_t(
/*******************************************************************//**
Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
@return 0 on success */
-static
int
field_store_string(
/*===============*/
@@ -328,7 +307,6 @@ field_store_index_name(
Auxiliary function to store ulint value in MYSQL_TYPE_LONGLONG field.
If the value is ULINT_UNDEFINED then the field it set to NULL.
@return 0 on success */
-static
int
field_store_ulint(
/*==============*/
@@ -8654,3 +8632,494 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_tablespaces_scrubbing =
STRUCT_FLD(version_info, INNODB_VERSION_STR),
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
};
+
+/** INNODB_MUTEXES *********************************************/
+/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_MUTEXES */
+static ST_FIELD_INFO innodb_mutexes_fields_info[] =
+{
+#define MUTEXES_NAME 0
+ {STRUCT_FLD(field_name, "NAME"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+#define MUTEXES_CREATE_FILE 1
+ {STRUCT_FLD(field_name, "CREATE_FILE"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+#define MUTEXES_CREATE_LINE 2
+ {STRUCT_FLD(field_name, "CREATE_LINE"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+#define MUTEXES_OS_WAITS 3
+ {STRUCT_FLD(field_name, "OS_WAITS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ END_OF_ST_FIELD_INFO
+};
+
+/*******************************************************************//**
+Function to populate INFORMATION_SCHEMA.INNODB_MUTEXES table.
+Loop through each record in mutex and rw_lock lists, and extract the column
+information and fill the INFORMATION_SCHEMA.INNODB_MUTEXES table.
+@return 0 on success */
+static
+int
+i_s_innodb_mutexes_fill_table(
+/*==========================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ Item* ) /*!< in: condition (not used) */
+{
+ ib_mutex_t* mutex;
+ rw_lock_t* lock;
+ ulint block_mutex_oswait_count = 0;
+ ulint block_lock_oswait_count = 0;
+ ib_mutex_t* block_mutex = NULL;
+ rw_lock_t* block_lock = NULL;
+ Field** fields = tables->table->field;
+
+ DBUG_ENTER("i_s_innodb_mutexes_fill_table");
+ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
+
+ /* deny access to user without PROCESS_ACL privilege */
+ if (check_global_access(thd, PROCESS_ACL)) {
+ DBUG_RETURN(0);
+ }
+
+ mutex_enter(&mutex_list_mutex);
+
+ for (mutex = UT_LIST_GET_FIRST(mutex_list); mutex != NULL;
+ mutex = UT_LIST_GET_NEXT(list, mutex)) {
+ if (mutex->count_os_wait == 0) {
+ continue;
+ }
+
+ if (buf_pool_is_block_mutex(mutex)) {
+ block_mutex = mutex;
+ block_mutex_oswait_count += mutex->count_os_wait;
+ continue;
+ }
+
+ OK(field_store_string(fields[MUTEXES_NAME], mutex->cmutex_name));
+ OK(field_store_string(fields[MUTEXES_CREATE_FILE], innobase_basename(mutex->cfile_name)));
+ OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], mutex->cline));
+ OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)mutex->count_os_wait));
+ OK(schema_table_store_record(thd, tables->table));
+ }
+
+ if (block_mutex) {
+ char buf1[IO_SIZE];
+
+ my_snprintf(buf1, sizeof buf1, "combined %s",
+ innobase_basename(block_mutex->cfile_name));
+
+ OK(field_store_string(fields[MUTEXES_NAME], block_mutex->cmutex_name));
+ OK(field_store_string(fields[MUTEXES_CREATE_FILE], buf1));
+ OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], block_mutex->cline));
+ OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)block_mutex_oswait_count));
+ OK(schema_table_store_record(thd, tables->table));
+ }
+
+ mutex_exit(&mutex_list_mutex);
+
+ mutex_enter(&rw_lock_list_mutex);
+
+ for (lock = UT_LIST_GET_FIRST(rw_lock_list); lock != NULL;
+ lock = UT_LIST_GET_NEXT(list, lock)) {
+ if (lock->count_os_wait == 0) {
+ continue;
+ }
+
+ if (buf_pool_is_block_lock(lock)) {
+ block_lock = lock;
+ block_lock_oswait_count += lock->count_os_wait;
+ continue;
+ }
+
+ OK(field_store_string(fields[MUTEXES_NAME], lock->lock_name));
+ OK(field_store_string(fields[MUTEXES_CREATE_FILE], innobase_basename(lock->cfile_name)));
+ OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], lock->cline));
+ OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)lock->count_os_wait));
+ OK(schema_table_store_record(thd, tables->table));
+ }
+
+ if (block_lock) {
+ char buf1[IO_SIZE];
+
+ my_snprintf(buf1, sizeof buf1, "combined %s",
+ innobase_basename(block_lock->cfile_name));
+
+ OK(field_store_string(fields[MUTEXES_NAME], block_lock->lock_name));
+ OK(field_store_string(fields[MUTEXES_CREATE_FILE], buf1));
+ OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], block_lock->cline));
+ OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)block_lock_oswait_count));
+ OK(schema_table_store_record(thd, tables->table));
+ }
+
+ mutex_exit(&rw_lock_list_mutex);
+
+ DBUG_RETURN(0);
+}
+
+/*******************************************************************//**
+Bind the dynamic table INFORMATION_SCHEMA.INNODB_MUTEXES
+@return 0 on success */
+static
+int
+innodb_mutexes_init(
+/*================*/
+ void* p) /*!< in/out: table schema object */
+{
+ ST_SCHEMA_TABLE* schema;
+
+ DBUG_ENTER("innodb_mutexes_init");
+
+ schema = (ST_SCHEMA_TABLE*) p;
+
+ schema->fields_info = innodb_mutexes_fields_info;
+ schema->fill_table = i_s_innodb_mutexes_fill_table;
+
+ DBUG_RETURN(0);
+}
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_mutexes =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_MUTEXES"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB SYS_DATAFILES"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_mutexes_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* Maria extension */
+ STRUCT_FLD(version_info, INNODB_VERSION_STR),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE),
+};
+
+/** SYS_SEMAPHORE_WAITS ************************************************/
+/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS */
+static ST_FIELD_INFO innodb_sys_semaphore_waits_fields_info[] =
+{
+ // SYS_SEMAPHORE_WAITS_THREAD_ID 0
+ {STRUCT_FLD(field_name, "THREAD_ID"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_OBJECT_NAME 1
+ {STRUCT_FLD(field_name, "OBJECT_NAME"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_FILE 2
+ {STRUCT_FLD(field_name, "FILE"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_LINE 3
+ {STRUCT_FLD(field_name, "LINE"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_WAIT_TIME 4
+ {STRUCT_FLD(field_name, "WAIT_TIME"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_WAIT_OBJECT 5
+ {STRUCT_FLD(field_name, "WAIT_OBJECT"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_WAIT_TYPE 6
+ {STRUCT_FLD(field_name, "WAIT_TYPE"),
+ STRUCT_FLD(field_length, 16),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID 7
+ {STRUCT_FLD(field_name, "HOLDER_THREAD_ID"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_HOLDER_FILE 8
+ {STRUCT_FLD(field_name, "HOLDER_FILE"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_HOLDER_LINE 9
+ {STRUCT_FLD(field_name, "HOLDER_LINE"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_CREATED_FILE 10
+ {STRUCT_FLD(field_name, "CREATED_FILE"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_CREATED_LINE 11
+ {STRUCT_FLD(field_name, "CREATED_LINE"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_WRITER_THREAD 12
+ {STRUCT_FLD(field_name, "WRITER_THREAD"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_RESERVATION_MODE 13
+ {STRUCT_FLD(field_name, "RESERVATION_MODE"),
+ STRUCT_FLD(field_length, 16),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_READERS 14
+ {STRUCT_FLD(field_name, "READERS"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_WAITERS_FLAG 15
+ {STRUCT_FLD(field_name, "WAITERS_FLAG"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_LOCK_WORD 16
+ {STRUCT_FLD(field_name, "LOCK_WORD"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_LAST_READER_FILE 17
+ {STRUCT_FLD(field_name, "LAST_READER_FILE"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_LAST_READER_LINE 18
+ {STRUCT_FLD(field_name, "LAST_READER_LINE"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE 19
+ {STRUCT_FLD(field_name, "LAST_WRITER_FILE"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE 20
+ {STRUCT_FLD(field_name, "LAST_WRITER_LINE"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT 21
+ {STRUCT_FLD(field_name, "OS_WAIT_COUNT"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ END_OF_ST_FIELD_INFO
+};
+
+
+
+/*******************************************************************//**
+Bind the dynamic table INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS
+@return 0 on success */
+static
+int
+innodb_sys_semaphore_waits_init(
+/*============================*/
+ void* p) /*!< in/out: table schema object */
+{
+ ST_SCHEMA_TABLE* schema;
+
+ DBUG_ENTER("innodb_sys_semaphore_waits_init");
+
+ schema = (ST_SCHEMA_TABLE*) p;
+
+ schema->fields_info = innodb_sys_semaphore_waits_fields_info;
+ schema->fill_table = sync_arr_fill_sys_semphore_waits_table;
+
+ DBUG_RETURN(0);
+}
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_semaphore_waits =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_SYS_SEMAPHORE_WAITS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, maria_plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB SYS_SEMAPHORE_WAITS"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_sys_semaphore_waits_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* Maria extension */
+ STRUCT_FLD(version_info, INNODB_VERSION_STR),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE),
+};
diff --git a/storage/innobase/handler/i_s.h b/storage/innobase/handler/i_s.h
index 4b248b0673a..296f64ddd74 100644
--- a/storage/innobase/handler/i_s.h
+++ b/storage/innobase/handler/i_s.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyrigth (c) 2014, 2015, MariaDB Corporation
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
@@ -21,12 +22,14 @@ this program; if not, write to the Free Software Foundation, Inc.,
InnoDB INFORMATION SCHEMA tables interface to MySQL.
Created July 18, 2007 Vasil Dimov
+Modified Dec 29, 2014 Jan Lindström
*******************************************************/
#ifndef i_s_h
#define i_s_h
const char plugin_author[] = "Oracle Corporation";
+const char maria_plugin_author[] = "MariaDB Corporation";
extern struct st_maria_plugin i_s_innodb_trx;
extern struct st_maria_plugin i_s_innodb_locks;
@@ -56,7 +59,92 @@ extern struct st_maria_plugin i_s_innodb_sys_foreign;
extern struct st_maria_plugin i_s_innodb_sys_foreign_cols;
extern struct st_maria_plugin i_s_innodb_sys_tablespaces;
extern struct st_maria_plugin i_s_innodb_sys_datafiles;
+extern struct st_maria_plugin i_s_innodb_mutexes;
extern struct st_maria_plugin i_s_innodb_tablespaces_encryption;
extern struct st_maria_plugin i_s_innodb_tablespaces_scrubbing;
+extern struct st_maria_plugin i_s_innodb_sys_semaphore_waits;
+
+/** maximum number of buffer page info we would cache. */
+#define MAX_BUF_INFO_CACHED 10000
+
+#define OK(expr) \
+ if ((expr) != 0) { \
+ DBUG_RETURN(1); \
+ }
+
+#define RETURN_IF_INNODB_NOT_STARTED(plugin_name) \
+do { \
+ if (!srv_was_started) { \
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, \
+ ER_CANT_FIND_SYSTEM_REC, \
+ "InnoDB: SELECTing from " \
+ "INFORMATION_SCHEMA.%s but " \
+ "the InnoDB storage engine " \
+ "is not installed", plugin_name); \
+ DBUG_RETURN(0); \
+ } \
+} while (0)
+
+#if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 && \
+ !defined __INTEL_COMPILER && !defined __clang__
+#define STRUCT_FLD(name, value) name: value
+#else
+#define STRUCT_FLD(name, value) value
+#endif
+
+/* Don't use a static const variable here, as some C++ compilers (notably
+HPUX aCC: HP ANSI C++ B3910B A.03.65) can't handle it. */
+#define END_OF_ST_FIELD_INFO \
+ {STRUCT_FLD(field_name, NULL), \
+ STRUCT_FLD(field_length, 0), \
+ STRUCT_FLD(field_type, MYSQL_TYPE_NULL), \
+ STRUCT_FLD(value, 0), \
+ STRUCT_FLD(field_flags, 0), \
+ STRUCT_FLD(old_name, ""), \
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}
+
+/** Fields on INFORMATION_SCHEMA.SYS_SEMAMPHORE_WAITS table */
+#define SYS_SEMAPHORE_WAITS_THREAD_ID 0
+#define SYS_SEMAPHORE_WAITS_OBJECT_NAME 1
+#define SYS_SEMAPHORE_WAITS_FILE 2
+#define SYS_SEMAPHORE_WAITS_LINE 3
+#define SYS_SEMAPHORE_WAITS_WAIT_TIME 4
+#define SYS_SEMAPHORE_WAITS_WAIT_OBJECT 5
+#define SYS_SEMAPHORE_WAITS_WAIT_TYPE 6
+#define SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID 7
+#define SYS_SEMAPHORE_WAITS_HOLDER_FILE 8
+#define SYS_SEMAPHORE_WAITS_HOLDER_LINE 9
+#define SYS_SEMAPHORE_WAITS_CREATED_FILE 10
+#define SYS_SEMAPHORE_WAITS_CREATED_LINE 11
+#define SYS_SEMAPHORE_WAITS_WRITER_THREAD 12
+#define SYS_SEMAPHORE_WAITS_RESERVATION_MODE 13
+#define SYS_SEMAPHORE_WAITS_READERS 14
+#define SYS_SEMAPHORE_WAITS_WAITERS_FLAG 15
+#define SYS_SEMAPHORE_WAITS_LOCK_WORD 16
+#define SYS_SEMAPHORE_WAITS_LAST_READER_FILE 17
+#define SYS_SEMAPHORE_WAITS_LAST_READER_LINE 18
+#define SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE 19
+#define SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE 20
+#define SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT 21
+
+/*******************************************************************//**
+Auxiliary function to store ulint value in MYSQL_TYPE_LONGLONG field.
+If the value is ULINT_UNDEFINED then the field it set to NULL.
+@return 0 on success */
+int
+field_store_ulint(
+/*==============*/
+ Field* field, /*!< in/out: target field for storage */
+ ulint n); /*!< in: value to store */
+
+/*******************************************************************//**
+Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
+@return 0 on success */
+int
+field_store_string(
+/*===============*/
+ Field* field, /*!< in/out: target field for storage */
+ const char* str); /*!< in: NUL-terminated utf-8 string,
+ or NULL */
#endif /* i_s_h */
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index a23e9306716..31db78ae5ee 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -565,6 +565,9 @@ extern ulong srv_fatal_semaphore_wait_threshold;
/** Default encryption key used for page encryption */
extern uint srv_default_page_encryption_key;
+/** Enable semaphore request instrumentation */
+extern my_bool srv_instrument_semaphores;
+
# 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/include/sync0arr.h b/storage/innobase/include/sync0arr.h
index 0e735192024..6c3225b1826 100644
--- a/storage/innobase/include/sync0arr.h
+++ b/storage/innobase/include/sync0arr.h
@@ -31,7 +31,7 @@ Created 9/5/1995 Heikki Tuuri
#include "ut0mem.h"
#include "os0thread.h"
-/** Synchronization wait array cell */
+/** Synchonization cell */
struct sync_cell_t;
/** Synchronization wait array */
struct sync_array_t;
@@ -154,6 +154,16 @@ UNIV_INTERN
void
sync_array_print_innodb(void);
+/*****************************************************************//**
+Gets the nth cell in array.
+@return cell */
+UNIV_INTERN
+sync_cell_t*
+sync_array_get_nth_cell(
+/*====================*/
+ sync_array_t* arr, /*!< in: sync array */
+ ulint n); /*!< in: index */
+
#ifndef UNIV_NONINL
#include "sync0arr.ic"
#endif
diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h
index b36e04f2810..cfd9776959f 100644
--- a/storage/innobase/include/sync0rw.h
+++ b/storage/innobase/include/sync0rw.h
@@ -40,6 +40,9 @@ Created 9/11/1995 Heikki Tuuri
#include "sync0sync.h"
#include "os0sync.h"
+/** Enable semaphore request instrumentation */
+extern my_bool srv_instrument_semaphores;
+
/* The following undef is to prevent a name conflict with a macro
in MySQL: */
#undef rw_lock_t
@@ -224,7 +227,7 @@ unlocking, not the corresponding function. */
# endif/* UNIV_SYNC_DEBUG */
# else /* UNIV_DEBUG */
# define rw_lock_create(K, L, level) \
- pfs_rw_lock_create_func((K), (L), __FILE__, __LINE__)
+ pfs_rw_lock_create_func((K), (L), #L, __FILE__, __LINE__)
# endif /* UNIV_DEBUG */
/******************************************************************
@@ -294,8 +297,8 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
- const char* cmutex_name, /*!< in: mutex name */
#endif /* UNIV_DEBUG */
+ const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline); /*!< in: file line where created */
/******************************************************************//**
@@ -610,6 +613,10 @@ struct rw_lock_t {
#endif
ulint count_os_wait; /*!< Count of os_waits. May not be accurate */
const char* cfile_name;/*!< File name where lock created */
+ const char* lock_name; /*!< lock name */
+ os_thread_id_t thread_id;/*!< thread id */
+ const char* file_name;/*!< File name where the lock was obtained */
+ ulint line; /*!< Line where the rw-lock was locked */
/* last s-lock file/line is not guaranteed to be correct */
const char* last_s_file_name;/*!< File name where last s-locked */
const char* last_x_file_name;/*!< File name where last x-locked */
@@ -688,8 +695,8 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
- const char* cmutex_name, /*!< in: mutex name */
#endif /* UNIV_DEBUG */
+ const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline); /*!< in: file line where created */
diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic
index bb05ae7daf1..afd25f3a071 100644
--- a/storage/innobase/include/sync0rw.ic
+++ b/storage/innobase/include/sync0rw.ic
@@ -325,6 +325,12 @@ rw_lock_s_lock_low(
lock->last_s_file_name = file_name;
lock->last_s_line = line;
+ if (srv_instrument_semaphores) {
+ lock->thread_id = os_thread_get_curr_id();
+ lock->file_name = file_name;
+ lock->line = line;
+ }
+
return(TRUE); /* locking succeeded */
}
@@ -426,6 +432,12 @@ rw_lock_x_lock_func_nowait(
rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
#endif
+ if (srv_instrument_semaphores) {
+ lock->thread_id = os_thread_get_curr_id();
+ lock->file_name = file_name;
+ lock->line = line;
+ }
+
lock->last_x_file_name = file_name;
lock->last_x_line = line;
@@ -546,8 +558,8 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
- const char* cmutex_name, /*!< in: mutex name */
# endif /* UNIV_DEBUG */
+ const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline) /*!< in: file line where created */
{
@@ -560,8 +572,8 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */
- cmutex_name,
# endif /* UNIV_DEBUG */
+ cmutex_name,
cfile_name,
cline);
}
diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h
index f26e66f1a87..2ffa14fd7fb 100644
--- a/storage/innobase/include/sync0sync.h
+++ b/storage/innobase/include/sync0sync.h
@@ -42,6 +42,9 @@ Created 9/5/1995 Heikki Tuuri
#include "os0sync.h"
#include "sync0arr.h"
+/** Enable semaphore request instrumentation */
+extern my_bool srv_instrument_semaphores;
+
#if defined(UNIV_DEBUG) && !defined(UNIV_HOTBACKUP)
extern "C" my_bool timed_mutexes;
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
@@ -180,7 +183,7 @@ necessary only if the memory block containing it is freed. */
# endif/* UNIV_SYNC_DEBUG */
# else
# define mutex_create(K, M, level) \
- pfs_mutex_create_func((K), (M), __FILE__, __LINE__)
+ pfs_mutex_create_func((K), (M), #M, __FILE__, __LINE__)
# endif /* UNIV_DEBUG */
# define mutex_enter(M) \
@@ -231,8 +234,8 @@ void
mutex_create_func(
/*==============*/
ib_mutex_t* mutex, /*!< in: pointer to memory */
-#ifdef UNIV_DEBUG
const char* cmutex_name, /*!< in: mutex name */
+#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
@@ -305,8 +308,8 @@ pfs_mutex_create_func(
/*==================*/
PSI_mutex_key key, /*!< in: Performance Schema key */
ib_mutex_t* mutex, /*!< in: pointer to memory */
-# ifdef UNIV_DEBUG
const char* cmutex_name, /*!< in: mutex name */
+# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
@@ -763,22 +766,22 @@ struct ib_mutex_t {
UT_LIST_NODE_T(ib_mutex_t) list; /*!< All allocated mutexes are put into
a list. Pointers to the next and prev. */
#ifdef UNIV_SYNC_DEBUG
- const char* file_name; /*!< File where the mutex was locked */
- ulint line; /*!< Line where the mutex was locked */
ulint level; /*!< Level in the global latching order */
#endif /* UNIV_SYNC_DEBUG */
+
+ const char* file_name; /*!< File where the mutex was locked */
+ ulint line; /*!< Line where the mutex was locked */
const char* cfile_name;/*!< File name where mutex created */
ulint cline; /*!< Line where created */
ulong count_os_wait; /*!< count of os_wait */
+ const char* cmutex_name; /*!< mutex name */
+ os_thread_id_t thread_id; /*!< The thread id of the thread
+ which locked the mutex. */
#ifdef UNIV_DEBUG
/** Value of mutex_t::magic_n */
# define MUTEX_MAGIC_N 979585UL
-
- os_thread_id_t thread_id; /*!< The thread id of the thread
- which locked the mutex. */
ulint magic_n; /*!< MUTEX_MAGIC_N */
- const char* cmutex_name; /*!< mutex name */
ulint ib_mutex_type; /*!< 0=usual mutex, 1=rw_lock mutex */
#endif /* UNIV_DEBUG */
#ifdef UNIV_PFS_MUTEX
diff --git a/storage/innobase/include/sync0sync.ic b/storage/innobase/include/sync0sync.ic
index a5887b1fd6f..d29932b39a6 100644
--- a/storage/innobase/include/sync0sync.ic
+++ b/storage/innobase/include/sync0sync.ic
@@ -162,7 +162,7 @@ mutex_exit_func(
{
ut_ad(mutex_own(mutex));
- ut_d(mutex->thread_id = (os_thread_id_t) ULINT_UNDEFINED);
+ mutex->thread_id = (os_thread_id_t) ULINT_UNDEFINED;
#ifdef UNIV_SYNC_DEBUG
sync_thread_reset_level(mutex);
@@ -213,10 +213,15 @@ mutex_enter_func(
the atomic test_and_set; we could peek, and possibly save time. */
if (!ib_mutex_test_and_set(mutex)) {
- ut_d(mutex->thread_id = os_thread_get_curr_id());
+ mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
+ if (srv_instrument_semaphores) {
+ mutex->file_name = file_name;
+ mutex->line = line;
+ }
+
return; /* Succeeded! */
}
@@ -324,8 +329,8 @@ pfs_mutex_create_func(
/*==================*/
mysql_pfs_key_t key, /*!< in: Performance Schema key */
ib_mutex_t* mutex, /*!< in: pointer to memory */
-# ifdef UNIV_DEBUG
const char* cmutex_name, /*!< in: mutex name */
+# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
@@ -336,8 +341,8 @@ pfs_mutex_create_func(
mutex->pfs_psi = PSI_MUTEX_CALL(init_mutex)(key, mutex);
mutex_create_func(mutex,
-# ifdef UNIV_DEBUG
cmutex_name,
+# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 07d8539836a..77b5e218723 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -76,6 +76,7 @@ Created 10/8/1995 Heikki Tuuri
#include "fil0fil.h"
#include "fil0pagecompress.h"
#include "btr0scrub.h"
+#include "fil0pageencryption.h"
#ifdef WITH_WSREP
extern int wsrep_debug;
@@ -523,7 +524,10 @@ second. */
static time_t srv_last_log_flush_time;
/** Default encryption key used for page encryption */
-UNIV_INTERN uint srv_default_page_encryption_key;
+UNIV_INTERN uint srv_default_page_encryption_key = DEFAULT_ENCRYPTION_KEY;
+
+/** Enable semaphore request instrumentation */
+UNIV_INTERN my_bool srv_instrument_semaphores = FALSE;
/* Interval in seconds at which various tasks are performed by the
master thread when server is active. In order to balance the workload,
diff --git a/storage/innobase/sync/sync0arr.cc b/storage/innobase/sync/sync0arr.cc
index 10c201e990e..e501423f222 100644
--- a/storage/innobase/sync/sync0arr.cc
+++ b/storage/innobase/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, 2015, MariaDB Corporation. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -30,11 +31,26 @@ The wait array used in synchronization primitives
Created 9/5/1995 Heikki Tuuri
*******************************************************/
+#include "univ.i"
+
#include "sync0arr.h"
#ifdef UNIV_NONINL
#include "sync0arr.ic"
#endif
+#include <mysqld_error.h>
+#include <mysql/plugin.h>
+#include <hash.h>
+#include <myisampack.h>
+#include <sql_acl.h>
+#include <mysys_err.h>
+#include <my_sys.h>
+#include "srv0srv.h"
+#include "srv0start.h"
+#include "i_s.h"
+#include <sql_plugin.h>
+#include <innodb_priv.h>
+
#include "sync0sync.h"
#include "sync0rw.h"
#include "os0sync.h"
@@ -115,7 +131,6 @@ for an event allocated for the array without owning the
protecting mutex (depending on the case: OS or database mutex), but
all changes (set or reset) to the state of the event must be made
while owning the mutex. */
-
/** Synchronization array */
struct sync_array_t {
ulint n_reserved; /*!< number of currently reserved
@@ -168,7 +183,6 @@ sync_array_detect_deadlock(
/*****************************************************************//**
Gets the nth cell in array.
@return cell */
-static
sync_cell_t*
sync_array_get_nth_cell(
/*====================*/
@@ -507,7 +521,7 @@ sync_array_cell_print(
: type == RW_LOCK_WAIT_EX ? "X-lock (wait_ex) on"
: "S-lock on", file);
- rwlock = cell->old_wait_rw_lock;
+ rwlock = (rw_lock_t*)cell->old_wait_rw_lock;
if (rwlock) {
fprintf(file,
@@ -1282,3 +1296,153 @@ sync_array_print_innodb(void)
fputs("InnoDB: Semaphore wait debug output ended:\n", stderr);
}
+
+/**********************************************************************//**
+Get number of items on sync array. */
+UNIV_INTERN
+ulint
+sync_arr_get_n_items(void)
+/*======================*/
+{
+ sync_array_t* sync_arr = sync_array_get();
+ return (ulint) sync_arr->n_cells;
+}
+
+/******************************************************************//**
+Get specified item from sync array if it is reserved. Set given
+pointer to array item if it is reserved.
+@return true if item is reserved, false othervise */
+UNIV_INTERN
+ibool
+sync_arr_get_item(
+/*==============*/
+ ulint i, /*!< in: requested item */
+ sync_cell_t **cell) /*!< out: cell contents if item
+ reserved */
+{
+ sync_array_t* sync_arr;
+ sync_cell_t* wait_cell;
+ void* wait_object;
+ ibool found = FALSE;
+
+ sync_arr = sync_array_get();
+ wait_cell = sync_array_get_nth_cell(sync_arr, i);
+
+ if (wait_cell) {
+ wait_object = wait_cell->wait_object;
+
+ if(wait_object != NULL && wait_cell->waiting) {
+ found = TRUE;
+ *cell = wait_cell;
+ }
+ }
+
+ return found;
+}
+
+/*******************************************************************//**
+Function to populate INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
+Loop through each item on sync array, and extract the column
+information and fill the INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
+@return 0 on success */
+UNIV_INTERN
+int
+sync_arr_fill_sys_semphore_waits_table(
+/*===================================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ Item* ) /*!< in: condition (not used) */
+{
+ Field** fields;
+ ulint n_items;
+
+ DBUG_ENTER("i_s_sys_semaphore_waits_fill_table");
+ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
+
+ /* deny access to user without PROCESS_ACL privilege */
+ if (check_global_access(thd, PROCESS_ACL)) {
+ DBUG_RETURN(0);
+ }
+
+ fields = tables->table->field;
+ n_items = sync_arr_get_n_items();
+ ulint type;
+
+ for(ulint i=0; i < n_items;i++) {
+ sync_cell_t *cell=NULL;
+ if (sync_arr_get_item(i, &cell)) {
+ ib_mutex_t* mutex;
+ type = cell->request_type;
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_THREAD_ID], (longlong)os_thread_pf(cell->thread)));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_FILE], innobase_basename(cell->file)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LINE], cell->line));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAIT_TIME], (longlong)difftime(time(NULL), cell->reservation_time)));
+
+ if (type == SYNC_MUTEX) {
+ mutex = static_cast<ib_mutex_t*>(cell->old_wait_mutex);
+
+ if (mutex) {
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_OBJECT_NAME], mutex->cmutex_name));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAIT_OBJECT], (longlong)mutex));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "MUTEX"));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID], (longlong)mutex->thread_id));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_HOLDER_FILE], innobase_basename(mutex->file_name)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_LINE], mutex->line));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_CREATED_FILE], innobase_basename(mutex->cfile_name)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_CREATED_LINE], mutex->cline));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAITERS_FLAG], (longlong)mutex->waiters));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LOCK_WORD], (longlong)mutex->lock_word));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE], innobase_basename(mutex->file_name)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE], mutex->line));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT], mutex->count_os_wait));
+ }
+ } else if (type == RW_LOCK_EX
+ || type == RW_LOCK_WAIT_EX
+ || type == RW_LOCK_SHARED) {
+ rw_lock_t* rwlock=NULL;
+
+ rwlock = static_cast<rw_lock_t *> (cell->old_wait_rw_lock);
+
+ if (rwlock) {
+ ulint writer = rw_lock_get_writer(rwlock);
+
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAIT_OBJECT], (longlong)rwlock));
+ if (type == RW_LOCK_EX) {
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "RW_LOCK_EX"));
+ } else if (type == RW_LOCK_WAIT_EX) {
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "RW_LOCK_WAIT_EX"));
+ } else if (type == RW_LOCK_SHARED) {
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "RW_LOCK_SHARED"));
+ }
+
+ if (writer != RW_LOCK_NOT_LOCKED) {
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_OBJECT_NAME], rwlock->lock_name));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WRITER_THREAD], (longlong)os_thread_pf(rwlock->writer_thread)));
+
+ if (writer == RW_LOCK_EX) {
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_RESERVATION_MODE], "RW_LOCK_EX"));
+ } else if (writer == RW_LOCK_WAIT_EX) {
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_RESERVATION_MODE], "RW_LOCK_WAIT_EX"));
+ }
+
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID], (longlong)rwlock->thread_id));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_HOLDER_FILE], innobase_basename(rwlock->file_name)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_LINE], rwlock->line));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_READERS], rw_lock_get_reader_count(rwlock)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAITERS_FLAG], (longlong)rwlock->waiters));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LOCK_WORD], (longlong)rwlock->lock_word));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_LAST_READER_FILE], innobase_basename(rwlock->last_s_file_name)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LAST_READER_LINE], rwlock->last_s_line));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE], innobase_basename(rwlock->last_x_file_name)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE], rwlock->last_x_line));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT], rwlock->count_os_wait));
+ }
+ }
+ }
+
+ OK(schema_table_store_record(thd, tables->table));
+ }
+ }
+
+ DBUG_RETURN(0);
+}
diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc
index 4ff330791a0..8e5faed08dd 100644
--- a/storage/innobase/sync/sync0rw.cc
+++ b/storage/innobase/sync/sync0rw.cc
@@ -209,8 +209,8 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
- const char* cmutex_name, /*!< in: mutex name */
#endif /* UNIV_DEBUG */
+ const char* cmutex_name, /*!< in: mutex name */
const char* cfile_name, /*!< in: file name where created */
ulint cline) /*!< in: file line where created */
{
@@ -223,8 +223,7 @@ rw_lock_create_func(
lock->mutex.cfile_name = cfile_name;
lock->mutex.cline = cline;
-
- ut_d(lock->mutex.cmutex_name = cmutex_name);
+ lock->mutex.lock_name = cmutex_name;
ut_d(lock->mutex.ib_mutex_type = 1);
#else /* INNODB_RW_LOCKS_USE_ATOMICS */
# ifdef UNIV_DEBUG
@@ -253,8 +252,10 @@ rw_lock_create_func(
lock->cfile_name = cfile_name;
lock->cline = (unsigned int) cline;
-
+ lock->lock_name = cmutex_name;
lock->count_os_wait = 0;
+ lock->file_name = "not yet reserved";
+ lock->line = 0;
lock->last_s_file_name = "not yet reserved";
lock->last_x_file_name = "not yet reserved";
lock->last_s_line = 0;
@@ -516,6 +517,12 @@ rw_lock_x_lock_wait(
file_name, line);
#endif
+ if (srv_instrument_semaphores) {
+ lock->thread_id = os_thread_get_curr_id();
+ lock->file_name = file_name;
+ lock->line = line;
+ }
+
sync_array_wait_event(sync_arr, index);
#ifdef UNIV_SYNC_DEBUG
rw_lock_remove_debug_info(
@@ -588,6 +595,13 @@ rw_lock_x_lock_low(
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, file_name, line);
#endif
+
+ if (srv_instrument_semaphores) {
+ lock->thread_id = os_thread_get_curr_id();
+ lock->file_name = file_name;
+ lock->line = line;
+ }
+
lock->last_x_file_name = file_name;
lock->last_x_line = (unsigned int) line;
diff --git a/storage/innobase/sync/sync0sync.cc b/storage/innobase/sync/sync0sync.cc
index aa2b5fa29db..5f5c6d2a5f2 100644
--- a/storage/innobase/sync/sync0sync.cc
+++ b/storage/innobase/sync/sync0sync.cc
@@ -265,8 +265,8 @@ void
mutex_create_func(
/*==============*/
ib_mutex_t* mutex, /*!< in: pointer to memory */
-#ifdef UNIV_DEBUG
const char* cmutex_name, /*!< in: mutex name */
+#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
@@ -285,9 +285,10 @@ mutex_create_func(
#ifdef UNIV_DEBUG
mutex->magic_n = MUTEX_MAGIC_N;
#endif /* UNIV_DEBUG */
-#ifdef UNIV_SYNC_DEBUG
+
mutex->line = 0;
mutex->file_name = "not yet reserved";
+#ifdef UNIV_SYNC_DEBUG
mutex->level = level;
#endif /* UNIV_SYNC_DEBUG */
mutex->cfile_name = cfile_name;
@@ -398,11 +399,15 @@ mutex_enter_nowait_func(
if (!ib_mutex_test_and_set(mutex)) {
- ut_d(mutex->thread_id = os_thread_get_curr_id());
+ mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
+#else
+ if (srv_instrument_semaphores) {
+ mutex->file_name = file_name;
+ mutex->line = line;
+ }
#endif
-
return(0); /* Succeeded! */
}
@@ -520,10 +525,15 @@ spin_loop:
if (ib_mutex_test_and_set(mutex) == 0) {
/* Succeeded! */
- ut_d(mutex->thread_id = os_thread_get_curr_id());
+ mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
+ if (srv_instrument_semaphores) {
+ mutex->file_name = file_name;
+ mutex->line = line;
+ }
+
return;
}
@@ -563,10 +573,14 @@ spin_loop:
sync_array_free_cell(sync_arr, index);
- ut_d(mutex->thread_id = os_thread_get_curr_id());
+ mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
+ if (srv_instrument_semaphores) {
+ mutex->file_name = file_name;
+ mutex->line = line;
+ }
return;
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index ee62dbc2d6a..e764d44c748 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -20412,6 +20412,12 @@ static MYSQL_SYSVAR_BOOL(scrub_force_testing,
NULL, NULL, FALSE);
#endif /* UNIV_DEBUG */
+static MYSQL_SYSVAR_BOOL(instrument_semaphores, srv_instrument_semaphores,
+ PLUGIN_VAR_OPCMDARG,
+ "Enable semaphore request instrumentation. This could have some effect on performance but allows better"
+ " information on long semaphore wait problems. (Default: not enabled)",
+ 0, 0, FALSE);
+
static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(log_block_size),
MYSQL_SYSVAR(additional_mem_pool_size),
@@ -20646,7 +20652,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
#ifdef UNIV_DEBUG
MYSQL_SYSVAR(scrub_force_testing),
#endif
-
+ MYSQL_SYSVAR(instrument_semaphores),
NULL
};
@@ -20698,6 +20704,8 @@ i_s_innodb_sys_foreign_cols,
i_s_innodb_sys_tablespaces,
i_s_innodb_sys_datafiles,
i_s_innodb_changed_pages,
+i_s_innodb_mutexes,
+i_s_innodb_sys_semaphore_waits,
i_s_innodb_tablespaces_encryption,
i_s_innodb_tablespaces_scrubbing
maria_declare_plugin_end;
diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc
index 99b1f486862..79870c755f6 100644
--- a/storage/xtradb/handler/i_s.cc
+++ b/storage/xtradb/handler/i_s.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyrigth (c) 2014, 2015, MariaDB Corporation
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
@@ -21,7 +22,9 @@ this program; if not, write to the Free Software Foundation, Inc.,
InnoDB INFORMATION SCHEMA tables interface to MySQL.
Created July 18, 2007 Vasil Dimov
+Modified Dec 29, 2014 Jan Lindström (Added sys_semaphore_waits)
*******************************************************/
+#include "univ.i"
#include <my_global.h>
#ifndef MYSQL_SERVER
#define MYSQL_SERVER /* For Item_* classes */
@@ -68,6 +71,7 @@ Created July 18, 2007 Vasil Dimov
#include "log0online.h"
#include "btr0btr.h"
#include "page0zip.h"
+#include "sync0arr.h"
/** structure associates a name string with a file page type and/or buffer
page state. */
@@ -149,45 +153,6 @@ struct buf_page_info_t{
index_id_t index_id; /*!< Index ID if a index page */
};
-/** maximum number of buffer page info we would cache. */
-#define MAX_BUF_INFO_CACHED 10000
-
-#define OK(expr) \
- if ((expr) != 0) { \
- DBUG_RETURN(1); \
- }
-
-#define RETURN_IF_INNODB_NOT_STARTED(plugin_name) \
-do { \
- if (!srv_was_started) { \
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, \
- ER_CANT_FIND_SYSTEM_REC, \
- "InnoDB: SELECTing from " \
- "INFORMATION_SCHEMA.%s but " \
- "the InnoDB storage engine " \
- "is not installed", plugin_name); \
- DBUG_RETURN(0); \
- } \
-} while (0)
-
-#if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 && \
- !defined __INTEL_COMPILER && !defined __clang__
-#define STRUCT_FLD(name, value) name: value
-#else
-#define STRUCT_FLD(name, value) value
-#endif
-
-/* Don't use a static const variable here, as some C++ compilers (notably
-HPUX aCC: HP ANSI C++ B3910B A.03.65) can't handle it. */
-#define END_OF_ST_FIELD_INFO \
- {STRUCT_FLD(field_name, NULL), \
- STRUCT_FLD(field_length, 0), \
- STRUCT_FLD(field_type, MYSQL_TYPE_NULL), \
- STRUCT_FLD(value, 0), \
- STRUCT_FLD(field_flags, 0), \
- STRUCT_FLD(old_name, ""), \
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}
-
/*
Use the following types mapping:
@@ -216,6 +181,20 @@ time_t MYSQL_TYPE_DATETIME
---------------------------------
*/
+/** Implemented on sync0arr.cc */
+/*******************************************************************//**
+Function to populate INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
+Loop through each item on sync array, and extract the column
+information and fill the INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
+@return 0 on success */
+UNIV_INTERN
+int
+sync_arr_fill_sys_semphore_waits_table(
+/*===================================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ Item* ); /*!< in: condition (not used) */
+
/*******************************************************************//**
Common function to fill any of the dynamic tables:
INFORMATION_SCHEMA.innodb_trx
@@ -273,7 +252,6 @@ field_store_time_t(
/*******************************************************************//**
Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
@return 0 on success */
-static
int
field_store_string(
/*===============*/
@@ -340,7 +318,6 @@ field_store_index_name(
Auxiliary function to store ulint value in MYSQL_TYPE_LONGLONG field.
If the value is ULINT_UNDEFINED then the field it set to NULL.
@return 0 on success */
-static
int
field_store_ulint(
/*==============*/
@@ -8992,3 +8969,494 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_tablespaces_scrubbing =
STRUCT_FLD(version_info, INNODB_VERSION_STR),
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
};
+
+/** INNODB_MUTEXES *********************************************/
+/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_MUTEXES */
+static ST_FIELD_INFO innodb_mutexes_fields_info[] =
+{
+#define MUTEXES_NAME 0
+ {STRUCT_FLD(field_name, "NAME"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+#define MUTEXES_CREATE_FILE 1
+ {STRUCT_FLD(field_name, "CREATE_FILE"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+#define MUTEXES_CREATE_LINE 2
+ {STRUCT_FLD(field_name, "CREATE_LINE"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+#define MUTEXES_OS_WAITS 3
+ {STRUCT_FLD(field_name, "OS_WAITS"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ END_OF_ST_FIELD_INFO
+};
+
+/*******************************************************************//**
+Function to populate INFORMATION_SCHEMA.INNODB_MUTEXES table.
+Loop through each record in mutex and rw_lock lists, and extract the column
+information and fill the INFORMATION_SCHEMA.INNODB_MUTEXES table.
+@return 0 on success */
+static
+int
+i_s_innodb_mutexes_fill_table(
+/*==========================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ Item* ) /*!< in: condition (not used) */
+{
+ ib_mutex_t* mutex;
+ rw_lock_t* lock;
+ ulint block_mutex_oswait_count = 0;
+ ulint block_lock_oswait_count = 0;
+ ib_mutex_t* block_mutex = NULL;
+ rw_lock_t* block_lock = NULL;
+ Field** fields = tables->table->field;
+
+ DBUG_ENTER("i_s_innodb_mutexes_fill_table");
+ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
+
+ /* deny access to user without PROCESS_ACL privilege */
+ if (check_global_access(thd, PROCESS_ACL)) {
+ DBUG_RETURN(0);
+ }
+
+ mutex_enter(&mutex_list_mutex);
+
+ for (mutex = UT_LIST_GET_FIRST(mutex_list); mutex != NULL;
+ mutex = UT_LIST_GET_NEXT(list, mutex)) {
+ if (mutex->count_os_wait == 0) {
+ continue;
+ }
+
+ if (buf_pool_is_block_mutex(mutex)) {
+ block_mutex = mutex;
+ block_mutex_oswait_count += mutex->count_os_wait;
+ continue;
+ }
+
+ OK(field_store_string(fields[MUTEXES_NAME], mutex->cmutex_name));
+ OK(field_store_string(fields[MUTEXES_CREATE_FILE], innobase_basename(mutex->cfile_name)));
+ OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], mutex->cline));
+ OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)mutex->count_os_wait));
+ OK(schema_table_store_record(thd, tables->table));
+ }
+
+ if (block_mutex) {
+ char buf1[IO_SIZE];
+
+ my_snprintf(buf1, sizeof buf1, "combined %s",
+ innobase_basename(block_mutex->cfile_name));
+
+ OK(field_store_string(fields[MUTEXES_NAME], block_mutex->cmutex_name));
+ OK(field_store_string(fields[MUTEXES_CREATE_FILE], buf1));
+ OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], block_mutex->cline));
+ OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)block_mutex_oswait_count));
+ OK(schema_table_store_record(thd, tables->table));
+ }
+
+ mutex_exit(&mutex_list_mutex);
+
+ mutex_enter(&rw_lock_list_mutex);
+
+ for (lock = UT_LIST_GET_FIRST(rw_lock_list); lock != NULL;
+ lock = UT_LIST_GET_NEXT(list, lock)) {
+ if (lock->count_os_wait == 0) {
+ continue;
+ }
+
+ if (buf_pool_is_block_lock(lock)) {
+ block_lock = lock;
+ block_lock_oswait_count += lock->count_os_wait;
+ continue;
+ }
+
+ OK(field_store_string(fields[MUTEXES_NAME], lock->lock_name));
+ OK(field_store_string(fields[MUTEXES_CREATE_FILE], innobase_basename(lock->cfile_name)));
+ OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], lock->cline));
+ OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)lock->count_os_wait));
+ OK(schema_table_store_record(thd, tables->table));
+ }
+
+ if (block_lock) {
+ char buf1[IO_SIZE];
+
+ my_snprintf(buf1, sizeof buf1, "combined %s",
+ innobase_basename(block_lock->cfile_name));
+
+ OK(field_store_string(fields[MUTEXES_NAME], block_lock->lock_name));
+ OK(field_store_string(fields[MUTEXES_CREATE_FILE], buf1));
+ OK(field_store_ulint(fields[MUTEXES_CREATE_LINE], block_lock->cline));
+ OK(field_store_ulint(fields[MUTEXES_OS_WAITS], (longlong)block_lock_oswait_count));
+ OK(schema_table_store_record(thd, tables->table));
+ }
+
+ mutex_exit(&rw_lock_list_mutex);
+
+ DBUG_RETURN(0);
+}
+
+/*******************************************************************//**
+Bind the dynamic table INFORMATION_SCHEMA.INNODB_MUTEXES
+@return 0 on success */
+static
+int
+innodb_mutexes_init(
+/*================*/
+ void* p) /*!< in/out: table schema object */
+{
+ ST_SCHEMA_TABLE* schema;
+
+ DBUG_ENTER("innodb_mutexes_init");
+
+ schema = (ST_SCHEMA_TABLE*) p;
+
+ schema->fields_info = innodb_mutexes_fields_info;
+ schema->fill_table = i_s_innodb_mutexes_fill_table;
+
+ DBUG_RETURN(0);
+}
+
+UNIV_INTERN struct st_mysql_plugin i_s_innodb_mutexes =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_MUTEXES"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB SYS_DATAFILES"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_mutexes_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* Maria extension */
+ STRUCT_FLD(version_info, INNODB_VERSION_STR),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE),
+};
+
+/** SYS_SEMAPHORE_WAITS ************************************************/
+/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS */
+static ST_FIELD_INFO innodb_sys_semaphore_waits_fields_info[] =
+{
+ // SYS_SEMAPHORE_WAITS_THREAD_ID 0
+ {STRUCT_FLD(field_name, "THREAD_ID"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_OBJECT_NAME 1
+ {STRUCT_FLD(field_name, "OBJECT_NAME"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_FILE 2
+ {STRUCT_FLD(field_name, "FILE"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_LINE 3
+ {STRUCT_FLD(field_name, "LINE"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_WAIT_TIME 4
+ {STRUCT_FLD(field_name, "WAIT_TIME"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_WAIT_OBJECT 5
+ {STRUCT_FLD(field_name, "WAIT_OBJECT"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_WAIT_TYPE 6
+ {STRUCT_FLD(field_name, "WAIT_TYPE"),
+ STRUCT_FLD(field_length, 16),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID 7
+ {STRUCT_FLD(field_name, "HOLDER_THREAD_ID"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_HOLDER_FILE 8
+ {STRUCT_FLD(field_name, "HOLDER_FILE"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_HOLDER_LINE 9
+ {STRUCT_FLD(field_name, "HOLDER_LINE"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_CREATED_FILE 10
+ {STRUCT_FLD(field_name, "CREATED_FILE"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_CREATED_LINE 11
+ {STRUCT_FLD(field_name, "CREATED_LINE"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_WRITER_THREAD 12
+ {STRUCT_FLD(field_name, "WRITER_THREAD"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_RESERVATION_MODE 13
+ {STRUCT_FLD(field_name, "RESERVATION_MODE"),
+ STRUCT_FLD(field_length, 16),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_READERS 14
+ {STRUCT_FLD(field_name, "READERS"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_WAITERS_FLAG 15
+ {STRUCT_FLD(field_name, "WAITERS_FLAG"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_LOCK_WORD 16
+ {STRUCT_FLD(field_name, "LOCK_WORD"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_LAST_READER_FILE 17
+ {STRUCT_FLD(field_name, "LAST_READER_FILE"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_LAST_READER_LINE 18
+ {STRUCT_FLD(field_name, "LAST_READER_LINE"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE 19
+ {STRUCT_FLD(field_name, "LAST_WRITER_FILE"),
+ STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
+ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE 20
+ {STRUCT_FLD(field_name, "LAST_WRITER_LINE"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ // SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT 21
+ {STRUCT_FLD(field_name, "OS_WAIT_COUNT"),
+ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
+ END_OF_ST_FIELD_INFO
+};
+
+
+
+/*******************************************************************//**
+Bind the dynamic table INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS
+@return 0 on success */
+static
+int
+innodb_sys_semaphore_waits_init(
+/*============================*/
+ void* p) /*!< in/out: table schema object */
+{
+ ST_SCHEMA_TABLE* schema;
+
+ DBUG_ENTER("innodb_sys_semaphore_waits_init");
+
+ schema = (ST_SCHEMA_TABLE*) p;
+
+ schema->fields_info = innodb_sys_semaphore_waits_fields_info;
+ schema->fill_table = sync_arr_fill_sys_semphore_waits_table;
+
+ DBUG_RETURN(0);
+}
+
+UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_semaphore_waits =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_SYS_SEMAPHORE_WAITS"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, maria_plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB SYS_SEMAPHORE_WAITS"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_sys_semaphore_waits_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* Maria extension */
+ STRUCT_FLD(version_info, INNODB_VERSION_STR),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE),
+};
diff --git a/storage/xtradb/handler/i_s.h b/storage/xtradb/handler/i_s.h
index f141af40c87..ee2442a22f2 100644
--- a/storage/xtradb/handler/i_s.h
+++ b/storage/xtradb/handler/i_s.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyrigth (c) 2014, 2015, MariaDB Corporation
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
@@ -21,12 +22,14 @@ this program; if not, write to the Free Software Foundation, Inc.,
InnoDB INFORMATION SCHEMA tables interface to MySQL.
Created July 18, 2007 Vasil Dimov
+Modified Dec 29, 2014 Jan Lindström
*******************************************************/
#ifndef i_s_h
#define i_s_h
const char plugin_author[] = "Oracle Corporation";
+const char maria_plugin_author[] = "MariaDB Corporation";
#define st_mysql_plugin st_maria_plugin
@@ -60,7 +63,91 @@ extern struct st_mysql_plugin i_s_innodb_sys_foreign_cols;
extern struct st_mysql_plugin i_s_innodb_sys_tablespaces;
extern struct st_mysql_plugin i_s_innodb_sys_datafiles;
extern struct st_mysql_plugin i_s_innodb_changed_pages;
+extern struct st_mysql_plugin i_s_innodb_mutexes;
extern struct st_maria_plugin i_s_innodb_tablespaces_encryption;
extern struct st_maria_plugin i_s_innodb_tablespaces_scrubbing;
+extern struct st_mysql_plugin i_s_innodb_sys_semaphore_waits;
+/** maximum number of buffer page info we would cache. */
+#define MAX_BUF_INFO_CACHED 10000
+
+#define OK(expr) \
+ if ((expr) != 0) { \
+ DBUG_RETURN(1); \
+ }
+
+#define RETURN_IF_INNODB_NOT_STARTED(plugin_name) \
+do { \
+ if (!srv_was_started) { \
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, \
+ ER_CANT_FIND_SYSTEM_REC, \
+ "InnoDB: SELECTing from " \
+ "INFORMATION_SCHEMA.%s but " \
+ "the InnoDB storage engine " \
+ "is not installed", plugin_name); \
+ DBUG_RETURN(0); \
+ } \
+} while (0)
+
+#if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 && \
+ !defined __INTEL_COMPILER && !defined __clang__
+#define STRUCT_FLD(name, value) name: value
+#else
+#define STRUCT_FLD(name, value) value
+#endif
+
+/* Don't use a static const variable here, as some C++ compilers (notably
+HPUX aCC: HP ANSI C++ B3910B A.03.65) can't handle it. */
+#define END_OF_ST_FIELD_INFO \
+ {STRUCT_FLD(field_name, NULL), \
+ STRUCT_FLD(field_length, 0), \
+ STRUCT_FLD(field_type, MYSQL_TYPE_NULL), \
+ STRUCT_FLD(value, 0), \
+ STRUCT_FLD(field_flags, 0), \
+ STRUCT_FLD(old_name, ""), \
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}
+
+/** Fields on INFORMATION_SCHEMA.SYS_SEMAMPHORE_WAITS table */
+#define SYS_SEMAPHORE_WAITS_THREAD_ID 0
+#define SYS_SEMAPHORE_WAITS_OBJECT_NAME 1
+#define SYS_SEMAPHORE_WAITS_FILE 2
+#define SYS_SEMAPHORE_WAITS_LINE 3
+#define SYS_SEMAPHORE_WAITS_WAIT_TIME 4
+#define SYS_SEMAPHORE_WAITS_WAIT_OBJECT 5
+#define SYS_SEMAPHORE_WAITS_WAIT_TYPE 6
+#define SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID 7
+#define SYS_SEMAPHORE_WAITS_HOLDER_FILE 8
+#define SYS_SEMAPHORE_WAITS_HOLDER_LINE 9
+#define SYS_SEMAPHORE_WAITS_CREATED_FILE 10
+#define SYS_SEMAPHORE_WAITS_CREATED_LINE 11
+#define SYS_SEMAPHORE_WAITS_WRITER_THREAD 12
+#define SYS_SEMAPHORE_WAITS_RESERVATION_MODE 13
+#define SYS_SEMAPHORE_WAITS_READERS 14
+#define SYS_SEMAPHORE_WAITS_WAITERS_FLAG 15
+#define SYS_SEMAPHORE_WAITS_LOCK_WORD 16
+#define SYS_SEMAPHORE_WAITS_LAST_READER_FILE 17
+#define SYS_SEMAPHORE_WAITS_LAST_READER_LINE 18
+#define SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE 19
+#define SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE 20
+#define SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT 21
+
+/*******************************************************************//**
+Auxiliary function to store ulint value in MYSQL_TYPE_LONGLONG field.
+If the value is ULINT_UNDEFINED then the field it set to NULL.
+@return 0 on success */
+int
+field_store_ulint(
+/*==============*/
+ Field* field, /*!< in/out: target field for storage */
+ ulint n); /*!< in: value to store */
+
+/*******************************************************************//**
+Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
+@return 0 on success */
+int
+field_store_string(
+/*===============*/
+ Field* field, /*!< in/out: target field for storage */
+ const char* str); /*!< in: NUL-terminated utf-8 string,
+ or NULL */
#endif /* i_s_h */
diff --git a/storage/xtradb/handler/xtradb_i_s.cc b/storage/xtradb/handler/xtradb_i_s.cc
index 7078ab752c2..96e31b94470 100644
--- a/storage/xtradb/handler/xtradb_i_s.cc
+++ b/storage/xtradb/handler/xtradb_i_s.cc
@@ -17,6 +17,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
*****************************************************************************/
+#include "univ.i"
#include <mysqld_error.h>
#include <sql_acl.h> // PROCESS_ACL
@@ -43,94 +44,6 @@ this program; if not, write to the Free Software Foundation, Inc.,
#define PLUGIN_AUTHOR "Percona Inc."
-#define OK(expr) \
- if ((expr) != 0) { \
- DBUG_RETURN(1); \
- }
-
-#define RETURN_IF_INNODB_NOT_STARTED(plugin_name) \
-do { \
- if (!srv_was_started) { \
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, \
- ER_CANT_FIND_SYSTEM_REC, \
- "InnoDB: SELECTing from " \
- "INFORMATION_SCHEMA.%s but " \
- "the InnoDB storage engine " \
- "is not installed", plugin_name); \
- DBUG_RETURN(0); \
- } \
-} while (0)
-
-#if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 && \
- !defined __INTEL_COMPILER && !defined __clang__
-#define STRUCT_FLD(name, value) name: value
-#else
-#define STRUCT_FLD(name, value) value
-#endif
-
-#define END_OF_ST_FIELD_INFO \
- {STRUCT_FLD(field_name, NULL), \
- STRUCT_FLD(field_length, 0), \
- STRUCT_FLD(field_type, MYSQL_TYPE_NULL), \
- STRUCT_FLD(value, 0), \
- STRUCT_FLD(field_flags, 0), \
- STRUCT_FLD(old_name, ""), \
- STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}
-
-
-/*******************************************************************//**
-Auxiliary function to store ulint value in MYSQL_TYPE_LONGLONG field.
-If the value is ULINT_UNDEFINED then the field it set to NULL.
-@return 0 on success */
-static
-int
-field_store_ulint(
-/*==============*/
- Field* field, /*!< in/out: target field for storage */
- ulint n) /*!< in: value to store */
-{
- int ret;
-
- if (n != ULINT_UNDEFINED) {
-
- ret = field->store(n);
- field->set_notnull();
- } else {
-
- ret = 0; /* success */
- field->set_null();
- }
-
- return(ret);
-}
-
-/*******************************************************************//**
-Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
-@return 0 on success */
-static
-int
-field_store_string(
-/*===============*/
- Field* field, /*!< in/out: target field for storage */
- const char* str) /*!< in: NUL-terminated utf-8 string,
- or NULL */
-{
- int ret;
-
- if (str != NULL) {
-
- ret = field->store(str, strlen(str),
- system_charset_info);
- field->set_notnull();
- } else {
-
- ret = 0; /* success */
- field->set_null();
- }
-
- return(ret);
-}
-
static
int
i_s_common_deinit(
diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h
index de994e79b30..de33f767021 100644
--- a/storage/xtradb/include/srv0srv.h
+++ b/storage/xtradb/include/srv0srv.h
@@ -708,6 +708,9 @@ extern ulong srv_fatal_semaphore_wait_threshold;
/** Default encryption key used for page encryption */
extern uint srv_default_page_encryption_key;
+/** Enable semaphore request instrumentation */
+extern my_bool srv_instrument_semaphores;
+
# 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/xtradb/include/sync0arr.h b/storage/xtradb/include/sync0arr.h
index 46e192d05f1..a3a326a0d1d 100644
--- a/storage/xtradb/include/sync0arr.h
+++ b/storage/xtradb/include/sync0arr.h
@@ -31,7 +31,7 @@ Created 9/5/1995 Heikki Tuuri
#include "ut0mem.h"
#include "os0thread.h"
-/** Synchronization wait array cell */
+/** Synchonization cell */
struct sync_cell_t;
/** Synchronization wait array */
struct sync_array_t;
@@ -154,6 +154,16 @@ UNIV_INTERN
void
sync_array_print_xtradb(void);
+/*****************************************************************//**
+Gets the nth cell in array.
+@return cell */
+UNIV_INTERN
+sync_cell_t*
+sync_array_get_nth_cell(
+/*====================*/
+ sync_array_t* arr, /*!< in: sync array */
+ ulint n); /*!< in: index */
+
#ifndef UNIV_NONINL
#include "sync0arr.ic"
#endif
diff --git a/storage/xtradb/include/sync0rw.h b/storage/xtradb/include/sync0rw.h
index 0ac6b0f3f69..1df6a793637 100644
--- a/storage/xtradb/include/sync0rw.h
+++ b/storage/xtradb/include/sync0rw.h
@@ -40,6 +40,9 @@ Created 9/11/1995 Heikki Tuuri
#include "sync0sync.h"
#include "os0sync.h"
+/** Enable semaphore request instrumentation */
+extern my_bool srv_instrument_semaphores;
+
/* The following undef is to prevent a name conflict with a macro
in MySQL: */
#undef rw_lock_t
@@ -153,14 +156,14 @@ defined, the rwlock are instrumented with performance schema probes. */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_create(K, L, level) \
- rw_lock_create_func((L), (level), __FILE__, __LINE__, #L)
+ rw_lock_create_func((L), (level), #L, __FILE__, __LINE__)
# else /* UNIV_SYNC_DEBUG */
# define rw_lock_create(K, L, level) \
- rw_lock_create_func((L), __FILE__, __LINE__, #L)
+ rw_lock_create_func((L), #L, __FILE__, __LINE__)
# endif/* UNIV_SYNC_DEBUG */
# else /* UNIV_DEBUG */
# define rw_lock_create(K, L, level) \
- rw_lock_create_func((L), #L)
+ rw_lock_create_func((L), __FILE__, __LINE__)
# endif /* UNIV_DEBUG */
/**************************************************************//**
@@ -218,14 +221,14 @@ unlocking, not the corresponding function. */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_create(K, L, level) \
- pfs_rw_lock_create_func((K), (L), (level), __FILE__, __LINE__, #L)
+ pfs_rw_lock_create_func((K), (L), (level), #L, __FILE__, __LINE__)
# else /* UNIV_SYNC_DEBUG */
# define rw_lock_create(K, L, level) \
- pfs_rw_lock_create_func((K), (L), __FILE__, __LINE__, #L)
+ pfs_rw_lock_create_func((K), (L), #L, __FILE__, __LINE__)
# endif/* UNIV_SYNC_DEBUG */
# else /* UNIV_DEBUG */
# define rw_lock_create(K, L, level) \
- pfs_rw_lock_create_func((K), (L), #L)
+ pfs_rw_lock_create_func((K), (L), #L, __FILE__, __LINE__)
# endif /* UNIV_DEBUG */
/******************************************************************
@@ -295,10 +298,10 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
- ulint cline, /*!< in: file line where created */
#endif /* UNIV_DEBUG */
- const char* cmutex_name); /*!< in: mutex name */
+ const char* cmutex_name, /*!< in: mutex name */
+ const char* cfile_name, /*!< in: file name where created */
+ ulint cline); /*!< in: file line where created */
/******************************************************************//**
Creates, or rather, initializes a priority rw-lock object in a specified memory
location (which must be appropriately aligned). The rw-lock is initialized
@@ -313,10 +316,10 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
- ulint cline, /*!< in: file line where created */
#endif /* UNIV_DEBUG */
- const char* cmutex_name); /*!< in: mutex name */
+ const char* cmutex_name, /*!< in: mutex name */
+ const char* cfile_name, /*!< in: file name where created */
+ ulint cline); /*!< in: file line where created */
/******************************************************************//**
Calling this function is obligatory only if the memory buffer containing
the rw-lock is freed. Removes an rw-lock object from the global list. The
@@ -752,8 +755,11 @@ struct rw_lock_t {
struct PSI_rwlock *pfs_psi;/*!< The instrumentation hook */
#endif
ulint count_os_wait; /*!< Count of os_waits. May not be accurate */
- //const char* cfile_name;/*!< File name where lock created */
+ const char* cfile_name;/*!< File name where lock created */
const char* lock_name;/*!< lock name */
+ os_thread_id_t thread_id;/*!< thread id */
+ const char* file_name;/*!< File name where the lock was obtained */
+ ulint line; /*!< Line where the rw-lock was locked */
/* last s-lock file/line is not guaranteed to be correct */
const char* last_s_file_name;/*!< File name where last s-locked */
const char* last_x_file_name;/*!< File name where last x-locked */
@@ -764,7 +770,7 @@ struct rw_lock_t {
are at the start of this struct, thus we can
peek this field without causing much memory
bus traffic */
- //unsigned cline:14; /*!< Line where created */
+ unsigned cline:14; /*!< Line where created */
unsigned last_s_line:14; /*!< Line number where last time s-locked */
unsigned last_x_line:14; /*!< Line number where last time x-locked */
#ifdef UNIV_DEBUG
@@ -853,10 +859,10 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
- ulint cline, /*!< in: file line where created */
#endif /* UNIV_DEBUG */
- const char* cmutex_name); /*!< in: mutex name */
+ const char* cmutex_name, /*!< in: mutex name */
+ const char* cfile_name, /*!< in: file name where created */
+ ulint cline); /*!< in: file line where created */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_create_func()
@@ -873,10 +879,10 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
- ulint cline, /*!< in: file line where created */
#endif /* UNIV_DEBUG */
- const char* cmutex_name); /*!< in: mutex name */
+ const char* cmutex_name, /*!< in: mutex name */
+ const char* cfile_name, /*!< in: file name where created */
+ ulint cline); /*!< in: file line where created */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_x_lock_func()
diff --git a/storage/xtradb/include/sync0rw.ic b/storage/xtradb/include/sync0rw.ic
index 8aadc406132..72bce228170 100644
--- a/storage/xtradb/include/sync0rw.ic
+++ b/storage/xtradb/include/sync0rw.ic
@@ -382,6 +382,12 @@ rw_lock_s_lock_low(
lock->last_s_file_name = file_name;
lock->last_s_line = line;
+ if (srv_instrument_semaphores) {
+ lock->thread_id = os_thread_get_curr_id();
+ lock->file_name = file_name;
+ lock->line = line;
+ }
+
return(TRUE); /* locking succeeded */
}
@@ -551,6 +557,12 @@ rw_lock_x_lock_func_nowait(
rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
#endif
+ if (srv_instrument_semaphores) {
+ lock->thread_id = os_thread_get_curr_id();
+ lock->file_name = file_name;
+ lock->line = line;
+ }
+
lock->last_x_file_name = file_name;
lock->last_x_line = line;
@@ -799,10 +811,10 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
- ulint cline, /*!< in: file line where created */
# endif /* UNIV_DEBUG */
- const char* cmutex_name) /*!< in: mutex name */
+ const char* cmutex_name, /*!< in: mutex name */
+ const char* cfile_name, /*!< in: file name where created */
+ ulint cline) /*!< in: file line where created */
{
/* Initialize the rwlock for performance schema */
lock->pfs_psi = PSI_RWLOCK_CALL(init_rwlock)(key, lock);
@@ -813,10 +825,10 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */
- cfile_name,
- cline,
# endif /* UNIV_DEBUG */
- cmutex_name);
+ cmutex_name,
+ cfile_name,
+ cline);
}
/******************************************************************//**
@@ -834,10 +846,10 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
- ulint cline, /*!< in: file line where created */
# endif /* UNIV_DEBUG */
- const char* cmutex_name) /*!< in: mutex name */
+ const char* cmutex_name, /*!< in: mutex name */
+ const char* cfile_name, /*!< in: file name where created */
+ ulint cline) /*!< in: file line where created */
{
/* Initialize the rwlock for performance schema */
lock->base_lock.pfs_psi = PSI_RWLOCK_CALL(init_rwlock)(key, lock);
@@ -848,10 +860,10 @@ pfs_rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */
- cfile_name,
- cline,
# endif /* UNIV_DEBUG */
- cmutex_name);
+ cmutex_name,
+ cfile_name,
+ cline);
}
/******************************************************************//**
diff --git a/storage/xtradb/include/sync0sync.h b/storage/xtradb/include/sync0sync.h
index 72cfbf61dd8..8112fff8a30 100644
--- a/storage/xtradb/include/sync0sync.h
+++ b/storage/xtradb/include/sync0sync.h
@@ -43,6 +43,9 @@ Created 9/5/1995 Heikki Tuuri
#include "sync0arr.h"
#include "ut0counter.h"
+/** Enable semaphore request instrumentation */
+extern my_bool srv_instrument_semaphores;
+
#if defined(UNIV_DEBUG) && !defined(UNIV_HOTBACKUP)
extern "C" my_bool timed_mutexes;
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
@@ -189,7 +192,7 @@ necessary only if the memory block containing it is freed. */
# endif/* UNIV_SYNC_DEBUG */
# else
# define mutex_create(K, M, level) \
- pfs_mutex_create_func((K), (M), #M)
+ pfs_mutex_create_func((K), (M), __FILE__, __LINE__, #M)
# endif /* UNIV_DEBUG */
# define mutex_enter(M) \
@@ -256,9 +259,9 @@ mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
+#endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
-#endif /* UNIV_DEBUG */
const char* cmutex_name); /*!< in: mutex name */
/******************************************************************//**
@@ -275,11 +278,11 @@ mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
+#endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where
created */
ulint cline, /*!< in: file line where
created */
-#endif /* UNIV_DEBUG */
const char* cmutex_name); /*!< in: mutex name */
/******************************************************************//**
NOTE! Use the corresponding macro mutex_free(), not directly this function!
@@ -402,9 +405,9 @@ pfs_mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
+# endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
-# endif /* UNIV_DEBUG */
const char* cmutex_name);
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_create(), not directly
@@ -423,11 +426,11 @@ pfs_mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
+# endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where
created */
ulint cline, /*!< in: file line where
created */
-# endif /* UNIV_DEBUG */
const char* cmutex_name);
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_enter(), not directly
@@ -947,27 +950,28 @@ struct ib_mutex_t {
Otherwise, this is 0. */
UT_LIST_NODE_T(ib_mutex_t) list; /*!< All allocated mutexes are put into
a list. Pointers to the next and prev. */
+
#ifdef UNIV_SYNC_DEBUG
- const char* file_name; /*!< File where the mutex was locked */
- ulint line; /*!< Line where the mutex was locked */
- ulint level; /*!< Level in the global latching order */
+ ulint level; /*!< Level in the global latching order */
#endif /* UNIV_SYNC_DEBUG */
-#ifdef UNIV_DEBUG
- const char* cfile_name;/*!< File name where mutex created */
- ulint cline; /*!< Line where created */
-#endif
+
+ const char* file_name; /*!< File where the mutex was locked */
+ ulint line; /*!< Line where the mutex was locked */
+ const char* cfile_name; /*!< File name where mutex created */
+ ulint cline; /*!< Line where created */
ulong count_os_wait; /*!< count of os_wait */
+ const char* cmutex_name; /*!< mutex name */
+ os_thread_id_t thread_id; /*!< The thread id of the thread
+ which locked the mutex. */
+
#ifdef UNIV_DEBUG
/** Value of mutex_t::magic_n */
# define MUTEX_MAGIC_N 979585UL
-
- os_thread_id_t thread_id; /*!< The thread id of the thread
- which locked the mutex. */
ulint magic_n; /*!< MUTEX_MAGIC_N */
ulint ib_mutex_type; /*!< 0=usual mutex, 1=rw_lock mutex */
#endif /* UNIV_DEBUG */
- const char* cmutex_name; /*!< mutex name */
+
#ifdef UNIV_PFS_MUTEX
struct PSI_mutex* pfs_psi; /*!< The performance schema
instrumentation hook */
diff --git a/storage/xtradb/include/sync0sync.ic b/storage/xtradb/include/sync0sync.ic
index 8176ae55fd8..90789339249 100644
--- a/storage/xtradb/include/sync0sync.ic
+++ b/storage/xtradb/include/sync0sync.ic
@@ -165,7 +165,7 @@ mutex_exit_func(
{
ut_ad(mutex_own(mutex));
- ut_d(mutex->thread_id = (os_thread_id_t) ULINT_UNDEFINED);
+ mutex->thread_id = (os_thread_id_t) ULINT_UNDEFINED;
#ifdef UNIV_SYNC_DEBUG
sync_thread_reset_level(mutex);
@@ -205,7 +205,7 @@ mutex_exit_func(
{
ut_ad(mutex_own(mutex));
- ut_d(mutex->base_mutex.thread_id = (os_thread_id_t) ULINT_UNDEFINED);
+ mutex->base_mutex.thread_id = (os_thread_id_t) ULINT_UNDEFINED;
#ifdef UNIV_SYNC_DEBUG
sync_thread_reset_level(&mutex->base_mutex);
@@ -264,10 +264,15 @@ mutex_enter_func(
the atomic test_and_set; we could peek, and possibly save time. */
if (!ib_mutex_test_and_set(mutex)) {
- ut_d(mutex->thread_id = os_thread_get_curr_id());
+ mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
+ if (srv_instrument_semaphores) {
+ mutex->file_name = file_name;
+ mutex->line = line;
+ }
+
return; /* Succeeded! */
}
@@ -304,10 +309,15 @@ mutex_enter_func(
the atomic test_and_set; we could peek, and possibly save time. */
if (!ib_mutex_test_and_set(&mutex->base_mutex)) {
- ut_d(mutex->base_mutex.thread_id = os_thread_get_curr_id());
+ mutex->base_mutex.thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(&mutex->base_mutex, file_name, line);
#endif
+ if(srv_instrument_semaphores) {
+ mutex->base_mutex.file_name = file_name;
+ mutex->base_mutex.line = line;
+ }
+
return; /* Succeeded! */
}
@@ -515,9 +525,9 @@ pfs_mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
+# endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
-# endif /* UNIV_DEBUG */
const char* cmutex_name) /*!< in: mutex name */
{
mutex->pfs_psi = PSI_MUTEX_CALL(init_mutex)(key, mutex);
@@ -527,9 +537,9 @@ pfs_mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */
+# endif /* UNIV_DEBUG */
cfile_name,
cline,
-# endif /* UNIV_DEBUG */
cmutex_name);
}
@@ -550,11 +560,11 @@ pfs_mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
+# endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where
created */
ulint cline, /*!< in: file line where
created */
-# endif /* UNIV_DEBUG */
const char* cmutex_name)
{
mutex->base_mutex.pfs_psi = PSI_MUTEX_CALL(init_mutex)(key, mutex);
@@ -564,9 +574,9 @@ pfs_mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */
+# endif /* UNIV_DEBUG */
cfile_name,
cline,
-# endif /* UNIV_DEBUG */
cmutex_name);
}
diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc
index f3d71fac155..37adca6975b 100644
--- a/storage/xtradb/srv/srv0srv.cc
+++ b/storage/xtradb/srv/srv0srv.cc
@@ -78,6 +78,7 @@ Created 10/8/1995 Heikki Tuuri
#include "fil0pagecompress.h"
#include <my_rdtsc.h>
#include "btr0scrub.h"
+#include "fil0pageencryption.h"
/* prototypes of new functions added to ha_innodb.cc for kill_idle_transaction */
ibool innobase_thd_is_idle(const void* thd);
@@ -670,7 +671,10 @@ second. */
static time_t srv_last_log_flush_time;
/** Default encryption key used for page encryption */
-UNIV_INTERN uint srv_default_page_encryption_key;
+UNIV_INTERN uint srv_default_page_encryption_key = DEFAULT_ENCRYPTION_KEY;
+
+/** Enable semaphore request instrumentation */
+UNIV_INTERN my_bool srv_instrument_semaphores = FALSE;
/* Interval in seconds at which various tasks are performed by the
master thread when server is active. In order to balance the workload,
diff --git a/storage/xtradb/sync/sync0arr.cc b/storage/xtradb/sync/sync0arr.cc
index 1701c705c5b..ebabc3d674e 100644
--- a/storage/xtradb/sync/sync0arr.cc
+++ b/storage/xtradb/sync/sync0arr.cc
@@ -2,7 +2,7 @@
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
-Copyright (c) 2013, 2014, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2013, 2015, MariaDB Corporation. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -31,11 +31,26 @@ The wait array used in synchronization primitives
Created 9/5/1995 Heikki Tuuri
*******************************************************/
+#include "univ.i"
+
#include "sync0arr.h"
#ifdef UNIV_NONINL
#include "sync0arr.ic"
#endif
+#include <mysqld_error.h>
+#include <mysql/plugin.h>
+#include <hash.h>
+#include <myisampack.h>
+#include <sql_acl.h>
+#include <mysys_err.h>
+#include <my_sys.h>
+#include "srv0srv.h"
+#include "srv0start.h"
+#include "i_s.h"
+#include <sql_plugin.h>
+#include <innodb_priv.h>
+
#include "sync0sync.h"
#include "sync0rw.h"
#include "os0sync.h"
@@ -117,7 +132,6 @@ for an event allocated for the array without owning the
protecting mutex (depending on the case: OS or database mutex), but
all changes (set or reset) to the state of the event must be made
while owning the mutex. */
-
/** Synchronization array */
struct sync_array_t {
ulint n_reserved; /*!< number of currently reserved
@@ -170,7 +184,6 @@ sync_array_detect_deadlock(
/*****************************************************************//**
Gets the nth cell in array.
@return cell */
-static
sync_cell_t*
sync_array_get_nth_cell(
/*====================*/
@@ -1374,3 +1387,173 @@ sync_array_print_xtradb(void)
fputs("InnoDB: Semaphore wait debug output ended:\n", stderr);
}
+/**********************************************************************//**
+Get number of items on sync array. */
+UNIV_INTERN
+ulint
+sync_arr_get_n_items(void)
+/*======================*/
+{
+ sync_array_t* sync_arr = sync_array_get();
+ return (ulint) sync_arr->n_cells;
+}
+
+/******************************************************************//**
+Get specified item from sync array if it is reserved. Set given
+pointer to array item if it is reserved.
+@return true if item is reserved, false othervise */
+UNIV_INTERN
+ibool
+sync_arr_get_item(
+/*==============*/
+ ulint i, /*!< in: requested item */
+ sync_cell_t **cell) /*!< out: cell contents if item
+ reserved */
+{
+ sync_array_t* sync_arr;
+ sync_cell_t* wait_cell;
+ void* wait_object;
+ ibool found = FALSE;
+
+ sync_arr = sync_array_get();
+ wait_cell = sync_array_get_nth_cell(sync_arr, i);
+
+ if (wait_cell) {
+ wait_object = wait_cell->wait_object;
+
+ if(wait_object != NULL && wait_cell->waiting) {
+ found = TRUE;
+ *cell = wait_cell;
+ }
+ }
+
+ return found;
+}
+
+/*******************************************************************//**
+Function to populate INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
+Loop through each item on sync array, and extract the column
+information and fill the INFORMATION_SCHEMA.INNODB_SYS_SEMAPHORE_WAITS table.
+@return 0 on success */
+UNIV_INTERN
+int
+sync_arr_fill_sys_semphore_waits_table(
+/*===================================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ Item* ) /*!< in: condition (not used) */
+{
+ Field** fields;
+ ulint n_items;
+
+ DBUG_ENTER("i_s_sys_semaphore_waits_fill_table");
+ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
+
+ /* deny access to user without PROCESS_ACL privilege */
+ if (check_global_access(thd, PROCESS_ACL)) {
+ DBUG_RETURN(0);
+ }
+
+ fields = tables->table->field;
+ n_items = sync_arr_get_n_items();
+ ulint type;
+
+ for(ulint i=0; i < n_items;i++) {
+ sync_cell_t *cell=NULL;
+ if (sync_arr_get_item(i, &cell)) {
+ ib_prio_mutex_t* prio_mutex;
+ ib_mutex_t* mutex;
+ type = cell->request_type;
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_THREAD_ID], (longlong)os_thread_pf(cell->thread)));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_FILE], innobase_basename(cell->file)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LINE], cell->line));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAIT_TIME], (longlong)difftime(time(NULL), cell->reservation_time)));
+
+ if (type == SYNC_MUTEX || type == SYNC_PRIO_MUTEX) {
+ if (type == SYNC_MUTEX) {
+ mutex = static_cast<ib_mutex_t*>(cell->old_wait_mutex);
+ } else {
+
+ prio_mutex = static_cast<ib_prio_mutex_t*>
+ (cell->old_wait_mutex);
+ mutex = &prio_mutex->base_mutex;
+ }
+
+ if (mutex) {
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_OBJECT_NAME], mutex->cmutex_name));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAIT_OBJECT], (longlong)mutex));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "MUTEX"));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID], (longlong)mutex->thread_id));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_HOLDER_FILE], innobase_basename(mutex->file_name)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_LINE], mutex->line));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_CREATED_FILE], innobase_basename(mutex->cfile_name)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_CREATED_LINE], mutex->cline));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAITERS_FLAG], (longlong)mutex->waiters));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LOCK_WORD], (longlong)mutex->lock_word));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE], innobase_basename(mutex->file_name)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE], mutex->line));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT], mutex->count_os_wait));
+ }
+ } else if (type == RW_LOCK_EX
+ || type == RW_LOCK_WAIT_EX
+ || type == RW_LOCK_SHARED
+ || type == PRIO_RW_LOCK_SHARED
+ || type == PRIO_RW_LOCK_EX) {
+ rw_lock_t* rwlock=NULL;
+ prio_rw_lock_t* prio_rwlock=NULL;
+
+ if (type == RW_LOCK_EX || type == RW_LOCK_WAIT_EX
+ || type == RW_LOCK_SHARED) {
+
+ rwlock = static_cast<rw_lock_t *>
+ (cell->old_wait_rw_lock);
+ } else {
+
+ prio_rwlock = static_cast<prio_rw_lock_t *>
+ (cell->old_wait_rw_lock);
+ rwlock = &prio_rwlock->base_lock;
+ }
+
+ if (rwlock) {
+ ulint writer = rw_lock_get_writer(rwlock);
+
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAIT_OBJECT], (longlong)rwlock));
+ if (type == RW_LOCK_EX) {
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "RW_LOCK_EX"));
+ } else if (type == RW_LOCK_WAIT_EX) {
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "RW_LOCK_WAIT_EX"));
+ } else if (type == RW_LOCK_SHARED) {
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_WAIT_TYPE], "RW_LOCK_SHARED"));
+ }
+
+ if (writer != RW_LOCK_NOT_LOCKED) {
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_OBJECT_NAME], rwlock->lock_name));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WRITER_THREAD], (longlong)os_thread_pf(rwlock->writer_thread)));
+
+ if (writer == RW_LOCK_EX) {
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_RESERVATION_MODE], "RW_LOCK_EX"));
+ } else if (writer == RW_LOCK_WAIT_EX) {
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_RESERVATION_MODE], "RW_LOCK_WAIT_EX"));
+ }
+
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_THREAD_ID], (longlong)rwlock->thread_id));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_HOLDER_FILE], innobase_basename(rwlock->file_name)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_HOLDER_LINE], rwlock->line));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_READERS], rw_lock_get_reader_count(rwlock)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAITERS_FLAG], (longlong)rwlock->waiters));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LOCK_WORD], (longlong)rwlock->lock_word));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_LAST_READER_FILE], innobase_basename(rwlock->last_s_file_name)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LAST_READER_LINE], rwlock->last_s_line));
+ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE], innobase_basename(rwlock->last_x_file_name)));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE], rwlock->last_x_line));
+ OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_OS_WAIT_COUNT], rwlock->count_os_wait));
+ }
+ }
+ }
+
+ OK(schema_table_store_record(thd, tables->table));
+ }
+ }
+
+ DBUG_RETURN(0);
+}
diff --git a/storage/xtradb/sync/sync0rw.cc b/storage/xtradb/sync/sync0rw.cc
index 3296e2e74a7..eac085513dc 100644
--- a/storage/xtradb/sync/sync0rw.cc
+++ b/storage/xtradb/sync/sync0rw.cc
@@ -209,10 +209,10 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
- ulint cline, /*!< in: file line where created */
#endif /* UNIV_DEBUG */
- const char* cmutex_name) /*!< in: mutex name */
+ const char* cmutex_name, /*!< in: mutex name */
+ const char* cfile_name, /*!< in: file name where created */
+ ulint cline) /*!< in: file line where created */
{
/* If this is the very first time a synchronization object is
created, then the following call initializes the sync system. */
@@ -221,15 +221,14 @@ rw_lock_create_func(
mutex_create(rw_lock_mutex_key, rw_lock_get_mutex(lock),
SYNC_NO_ORDER_CHECK);
- ut_d(lock->mutex.cfile_name = cfile_name);
- ut_d(lock->mutex.cline = cline);
-
- lock->mutex.cmutex_name = cmutex_name;
+ lock->mutex.cfile_name = cfile_name;
+ lock->mutex.cline = cline;
+ lock->mutex.lock_name = cmutex_name;
ut_d(lock->mutex.ib_mutex_type = 1);
+
#else /* INNODB_RW_LOCKS_USE_ATOMICS */
# ifdef UNIV_DEBUG
- UT_NOT_USED(cfile_name);
- UT_NOT_USED(cline);
+ UT_NOT_USED(cmutex_name);
# endif
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */
@@ -252,9 +251,12 @@ rw_lock_create_func(
ut_d(lock->magic_n = RW_LOCK_MAGIC_N);
+ lock->cfile_name = cfile_name;
+ lock->cline = (unsigned int) cline;
lock->lock_name = cmutex_name;
-
lock->count_os_wait = 0;
+ lock->file_name = "not yet reserved";
+ lock->line = 0;
lock->last_s_file_name = "not yet reserved";
lock->last_x_file_name = "not yet reserved";
lock->last_s_line = 0;
@@ -286,20 +288,21 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
- const char* cfile_name, /*!< in: file name where created */
- ulint cline, /*!< in: file line where created */
#endif /* UNIV_DEBUG */
- const char* cmutex_name) /*!< in: mutex name */
+ const char* cmutex_name, /*!< in: mutex name */
+ const char* cfile_name, /*!< in: file name where created */
+ ulint cline) /*!< in: file line where created */
{
rw_lock_create_func(&lock->base_lock,
#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
level,
# endif
- cfile_name,
- cline,
#endif
- cmutex_name);
+ cmutex_name,
+ cfile_name,
+ cline);
+
lock->high_priority_s_waiters = 0;
lock->high_priority_s_event = os_event_create();
lock->high_priority_x_waiters = 0;
@@ -655,6 +658,12 @@ rw_lock_x_lock_wait(
file_name, line);
#endif
+ if (srv_instrument_semaphores) {
+ lock->thread_id = os_thread_get_curr_id();
+ lock->file_name = file_name;
+ lock->line = line;
+ }
+
sync_array_wait_event(sync_arr, index);
#ifdef UNIV_SYNC_DEBUG
rw_lock_remove_debug_info(
@@ -740,6 +749,12 @@ rw_lock_x_lock_low(
lock->last_x_file_name = file_name;
lock->last_x_line = (unsigned int) line;
+ if (srv_instrument_semaphores) {
+ lock->thread_id = os_thread_get_curr_id();
+ lock->file_name = file_name;
+ lock->line = line;
+ }
+
return(TRUE);
}
diff --git a/storage/xtradb/sync/sync0sync.cc b/storage/xtradb/sync/sync0sync.cc
index 5732e1075cf..2bdaaa35a0e 100644
--- a/storage/xtradb/sync/sync0sync.cc
+++ b/storage/xtradb/sync/sync0sync.cc
@@ -273,9 +273,9 @@ mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
+#endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline, /*!< in: file line where created */
-#endif /* UNIV_DEBUG */
const char* cmutex_name) /*!< in: mutex name */
{
#if defined(HAVE_ATOMIC_BUILTINS)
@@ -288,16 +288,13 @@ mutex_create_func(
mutex_set_waiters(mutex, 0);
#ifdef UNIV_DEBUG
mutex->magic_n = MUTEX_MAGIC_N;
+ mutex->level = level;
#endif /* UNIV_DEBUG */
-#ifdef UNIV_SYNC_DEBUG
+
mutex->line = 0;
mutex->file_name = "not yet reserved";
- mutex->level = level;
-#endif /* UNIV_SYNC_DEBUG */
-#ifdef UNIV_DEBUG
mutex->cfile_name = cfile_name;
mutex->cline = cline;
-#endif /* UNIV_DEBUG */
mutex->count_os_wait = 0;
mutex->cmutex_name= cmutex_name;
@@ -339,11 +336,11 @@ mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
+#endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where
created */
ulint cline, /*!< in: file line where
created */
-#endif /* UNIV_DEBUG */
const char* cmutex_name) /*!< in: mutex name */
{
mutex_create_func(&mutex->base_mutex,
@@ -351,9 +348,9 @@ mutex_create_func(
# ifdef UNIV_SYNC_DEBUG
level,
#endif /* UNIV_SYNC_DEBUG */
+#endif /* UNIV_DEBUG */
cfile_name,
cline,
-#endif /* UNIV_DEBUG */
cmutex_name);
mutex->high_priority_waiters = 0;
mutex->high_priority_event = os_event_create();
@@ -463,10 +460,14 @@ mutex_enter_nowait_func(
if (!ib_mutex_test_and_set(mutex)) {
- ut_d(mutex->thread_id = os_thread_get_curr_id());
+ mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
+ if (srv_instrument_semaphores) {
+ mutex->file_name = file_name;
+ mutex->line = line;
+ }
return(0); /* Succeeded! */
}
@@ -607,10 +608,15 @@ spin_loop:
if (ib_mutex_test_and_set(mutex) == 0) {
/* Succeeded! */
- ut_d(mutex->thread_id = os_thread_get_curr_id());
+ mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
+ if (srv_instrument_semaphores) {
+ mutex->file_name = file_name;
+ mutex->line = line;
+ }
+
return;
}
@@ -661,10 +667,14 @@ spin_loop:
sync_array_free_cell(sync_arr, index);
- ut_d(mutex->thread_id = os_thread_get_curr_id());
+ mutex->thread_id = os_thread_get_curr_id();
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
+ if (srv_instrument_semaphores) {
+ mutex->file_name = file_name;
+ mutex->line = line;
+ }
if (prio_mutex) {
os_atomic_decrement_ulint(