mirror of
https://github.com/MariaDB/server.git
synced 2025-01-21 22:34:18 +01:00
67cd330256
------------------------------------------------------------------------ r6130 | marko | 2009-11-02 11:42:56 +0200 (Mon, 02 Nov 2009) | 9 lines Changed paths: M /branches/zip/ChangeLog M /branches/zip/btr/btr0sea.c M /branches/zip/buf/buf0buf.c M /branches/zip/dict/dict0dict.c M /branches/zip/fil/fil0fil.c M /branches/zip/ibuf/ibuf0ibuf.c M /branches/zip/include/btr0sea.h M /branches/zip/include/dict0dict.h M /branches/zip/include/fil0fil.h M /branches/zip/include/ibuf0ibuf.h M /branches/zip/include/lock0lock.h M /branches/zip/include/log0log.h M /branches/zip/include/log0recv.h M /branches/zip/include/mem0mem.h M /branches/zip/include/mem0pool.h M /branches/zip/include/os0file.h M /branches/zip/include/pars0pars.h M /branches/zip/include/srv0srv.h M /branches/zip/include/thr0loc.h M /branches/zip/include/trx0i_s.h M /branches/zip/include/trx0purge.h M /branches/zip/include/trx0rseg.h M /branches/zip/include/trx0sys.h M /branches/zip/include/trx0undo.h M /branches/zip/include/usr0sess.h M /branches/zip/lock/lock0lock.c M /branches/zip/log/log0log.c M /branches/zip/log/log0recv.c M /branches/zip/mem/mem0dbg.c M /branches/zip/mem/mem0pool.c M /branches/zip/os/os0file.c M /branches/zip/os/os0sync.c M /branches/zip/os/os0thread.c M /branches/zip/pars/lexyy.c M /branches/zip/pars/pars0lex.l M /branches/zip/que/que0que.c M /branches/zip/srv/srv0srv.c M /branches/zip/srv/srv0start.c M /branches/zip/sync/sync0arr.c M /branches/zip/sync/sync0sync.c M /branches/zip/thr/thr0loc.c M /branches/zip/trx/trx0i_s.c M /branches/zip/trx/trx0purge.c M /branches/zip/trx/trx0rseg.c M /branches/zip/trx/trx0sys.c M /branches/zip/trx/trx0undo.c M /branches/zip/usr/usr0sess.c M /branches/zip/ut/ut0mem.c branches/zip: Free all resources at shutdown. Set pointers to NULL, so that Valgrind will not complain about freed data structures that are reachable via pointers. This addresses Bug #45992 and Bug #46656. This patch is mostly based on changes copied from branches/embedded-1.0, mainly c5432, c3439, c3134, c2994, c2978, but also some other code was copied. Some added cleanup code is specific to MySQL/InnoDB. rb://199 approved by Sunny Bains ------------------------------------------------------------------------ r6134 | marko | 2009-11-04 09:57:29 +0200 (Wed, 04 Nov 2009) | 5 lines Changed paths: M /branches/zip/ChangeLog M /branches/zip/handler/ha_innodb.cc branches/zip: innobase_convert_identifier(): Convert table names with explain_filename() to address Bug #32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs. rb://134 approved by Sunny Bains ------------------------------------------------------------------------ r6137 | marko | 2009-11-04 15:24:28 +0200 (Wed, 04 Nov 2009) | 1 line Changed paths: M /branches/zip/dict/dict0dict.c branches/zip: dict_index_too_big_for_undo(): Correct a typo. ------------------------------------------------------------------------ r6153 | vasil | 2009-11-10 15:33:22 +0200 (Tue, 10 Nov 2009) | 145 lines Changed paths: M /branches/zip/handler/ha_innodb.cc branches/zip: Merge r6125:6152 from branches/5.1: (everything except the last white-space change was skipped as it is already in branches/zip) ------------------------------------------------------------------------ r6127 | vasil | 2009-10-30 11:18:25 +0200 (Fri, 30 Oct 2009) | 18 lines Changed paths: M /branches/5.1/Makefile.am M /branches/5.1/mysql-test/innodb-autoinc.result M /branches/5.1/mysql-test/innodb-autoinc.test branches/5.1: Backport c6121 from branches/zip: ------------------------------------------------------------------------ r6121 | sunny | 2009-10-30 01:42:11 +0200 (Fri, 30 Oct 2009) | 7 lines Changed paths: M /branches/zip/mysql-test/innodb-autoinc.result branches/zip: This test has been problematic for sometime now. The underlying bug is that the data dictionaries get out of sync. In the AUTOINC code we try and apply salve to the symptoms. In the past MySQL made some unrelated change and the dictionaries stopped getting out of sync and this test started to fail. Now, it seems they have reverted that changed and the test is passing again. I suspect this is not he last time that this test will change. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r6129 | vasil | 2009-10-30 17:14:22 +0200 (Fri, 30 Oct 2009) | 4 lines Changed paths: M /branches/5.1/Makefile.am branches/5.1: Revert a change to Makefile.am that sneaked unnoticed in c6127. ------------------------------------------------------------------------ r6136 | marko | 2009-11-04 12:28:10 +0200 (Wed, 04 Nov 2009) | 15 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc M /branches/5.1/include/ha_prototypes.h M /branches/5.1/ut/ut0ut.c branches/5.1: Port r6134 from branches/zip: ------------------------------------------------------------------------ r6134 | marko | 2009-11-04 07:57:29 +0000 (Wed, 04 Nov 2009) | 5 lines branches/zip: innobase_convert_identifier(): Convert table names with explain_filename() to address Bug #32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs. rb://134 approved by Sunny Bains ------------------------------------------------------------------------ innobase_print_identifier(): Replace with innobase_convert_name(). innobase_convert_identifier(): New function, called by innobase_convert_name(). ------------------------------------------------------------------------ r6149 | vasil | 2009-11-09 11:15:01 +0200 (Mon, 09 Nov 2009) | 5 lines Changed paths: M /branches/5.1/CMakeLists.txt branches/5.1: Followup to r5700: Adjust the changes so they are the same as in the BZR repository. ------------------------------------------------------------------------ r6150 | vasil | 2009-11-09 11:43:31 +0200 (Mon, 09 Nov 2009) | 58 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc branches/5.1: Merge a part of r2911.5.5 from MySQL: (the other part of this was merged in c5700) ------------------------------------------------------------ revno: 2911.5.5 committer: Vladislav Vaintroub <vvaintroub@mysql.com> branch nick: 5.1-innodb_plugin timestamp: Wed 2009-06-10 10:59:49 +0200 message: Backport WL#3653 to 5.1 to enable bundled innodb plugin. Remove custom DLL loader code from innodb plugin code, use symbols exported from mysqld. removed: storage/innodb_plugin/handler/handler0vars.h storage/innodb_plugin/handler/win_delay_loader.cc added: storage/mysql_storage_engine.cmake win/create_def_file.js modified: CMakeLists.txt include/m_ctype.h include/my_global.h include/my_sys.h include/mysql/plugin.h libmysqld/CMakeLists.txt mysql-test/mysql-test-run.pl mysql-test/t/plugin.test mysql-test/t/plugin_load-master.opt mysys/charset.c sql/CMakeLists.txt sql/handler.h sql/mysql_priv.h sql/mysqld.cc sql/sql_class.cc sql/sql_class.h sql/sql_list.h sql/sql_profile.h storage/Makefile.am storage/archive/CMakeLists.txt storage/blackhole/CMakeLists.txt storage/csv/CMakeLists.txt storage/example/CMakeLists.txt storage/federated/CMakeLists.txt storage/heap/CMakeLists.txt storage/innobase/CMakeLists.txt storage/innobase/handler/ha_innodb.cc storage/innodb_plugin/CMakeLists.txt storage/innodb_plugin/handler/ha_innodb.cc storage/innodb_plugin/handler/handler0alter.cc storage/innodb_plugin/handler/i_s.cc storage/innodb_plugin/plug.in storage/myisam/CMakeLists.txt storage/myisammrg/CMakeLists.txt win/Makefile.am win/configure.js ------------------------------------------------------------------------ r6152 | vasil | 2009-11-10 15:30:20 +0200 (Tue, 10 Nov 2009) | 4 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc branches/5.1: White space fixup. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r6157 | jyang | 2009-11-11 14:27:09 +0200 (Wed, 11 Nov 2009) | 10 lines Changed paths: M /branches/zip/handler/ha_innodb.cc A /branches/zip/mysql-test/innodb_bug47167.result A /branches/zip/mysql-test/innodb_bug47167.test M /branches/zip/mysql-test/innodb_file_format.result branches/zip: Fix an issue that a local variable defined in innodb_file_format_check_validate() is being referenced across function in innodb_file_format_check_update(). In addition, fix "set global innodb_file_format_check = DEFAULT" call. Bug #47167: "set global innodb_file_format_check" cannot set value by User-Defined Variable." rb://169 approved by Sunny Bains and Marko. ------------------------------------------------------------------------ r6159 | vasil | 2009-11-11 15:13:01 +0200 (Wed, 11 Nov 2009) | 37 lines Changed paths: M /branches/zip/handler/ha_innodb.cc M /branches/zip/handler/ha_innodb.h branches/zip: Merge a change from MySQL: (this has been reviewed by Calvin and Marko, and Calvin says Luis has incorporated Marko's suggestions) ------------------------------------------------------------ revno: 3092.5.1 committer: Luis Soares <luis.soares@sun.com> branch nick: mysql-5.1-bugteam timestamp: Thu 2009-09-24 15:52:52 +0100 message: BUG#42829: binlogging enabled for all schemas regardless of binlog-db-db / binlog-ignore-db InnoDB will return an error if statement based replication is used along with transaction isolation level READ-COMMITTED (or weaker), even if the statement in question is filtered out according to the binlog-do-db rules set. In this case, an error should not be printed. This patch addresses this issue by extending the existing check in external_lock to take into account the filter rules before deciding to print an error. Furthermore, it also changes decide_logging_format to take into consideration whether the statement is filtered out from binlog before decision is made. added: mysql-test/suite/binlog/r/binlog_stm_do_db.result mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt mysql-test/suite/binlog/t/binlog_stm_do_db.test modified: sql/sql_base.cc sql/sql_class.cc storage/innobase/handler/ha_innodb.cc storage/innobase/handler/ha_innodb.h storage/innodb_plugin/handler/ha_innodb.cc storage/innodb_plugin/handler/ha_innodb.h ------------------------------------------------------------------------ r6160 | vasil | 2009-11-11 15:33:49 +0200 (Wed, 11 Nov 2009) | 72 lines Changed paths: M /branches/zip/include/os0file.h M /branches/zip/os/os0file.c branches/zip: Merge r6152:6159 from branches/5.1: (r6158 was skipped as an equivallent change has already been merged from MySQL) ------------------------------------------------------------------------ r6154 | calvin | 2009-11-11 02:51:17 +0200 (Wed, 11 Nov 2009) | 17 lines Changed paths: M /branches/5.1/include/os0file.h M /branches/5.1/os/os0file.c branches/5.1: fix bug#3139: Mysql crashes: 'windows error 995' after several selects on a large DB During stress environment, Windows AIO may fail with error code ERROR_OPERATION_ABORTED. InnoDB does not handle the error, rather crashes. The cause of the error is unknown, but likely due to faulty hardware or driver. This patch introduces a new error code OS_FILE_OPERATION_ABORTED, which maps to Windows ERROR_OPERATION_ABORTED (995). When the error is detected during AIO, the InnoDB will issue a synchronous retry (read/write). This patch has been extensively tested by MySQL support. Approved by: Marko rb://196 ------------------------------------------------------------------------ r6158 | vasil | 2009-11-11 14:52:14 +0200 (Wed, 11 Nov 2009) | 37 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc M /branches/5.1/handler/ha_innodb.h branches/5.1: Merge a change from MySQL: (this has been reviewed by Calvin and Marko, and Calvin says Luis has incorporated Marko's suggestions) ------------------------------------------------------------ revno: 3092.5.1 committer: Luis Soares <luis.soares@sun.com> branch nick: mysql-5.1-bugteam timestamp: Thu 2009-09-24 15:52:52 +0100 message: BUG#42829: binlogging enabled for all schemas regardless of binlog-db-db / binlog-ignore-db InnoDB will return an error if statement based replication is used along with transaction isolation level READ-COMMITTED (or weaker), even if the statement in question is filtered out according to the binlog-do-db rules set. In this case, an error should not be printed. This patch addresses this issue by extending the existing check in external_lock to take into account the filter rules before deciding to print an error. Furthermore, it also changes decide_logging_format to take into consideration whether the statement is filtered out from binlog before decision is made. added: mysql-test/suite/binlog/r/binlog_stm_do_db.result mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt mysql-test/suite/binlog/t/binlog_stm_do_db.test modified: sql/sql_base.cc sql/sql_class.cc storage/innobase/handler/ha_innodb.cc storage/innobase/handler/ha_innodb.h storage/innodb_plugin/handler/ha_innodb.cc storage/innodb_plugin/handler/ha_innodb.h ------------------------------------------------------------------------ ------------------------------------------------------------------------ r6161 | vasil | 2009-11-11 15:36:16 +0200 (Wed, 11 Nov 2009) | 4 lines Changed paths: M /branches/zip/ChangeLog branches/zip: Add changelog entry for r6160. ------------------------------------------------------------------------ r6162 | vasil | 2009-11-11 16:00:12 +0200 (Wed, 11 Nov 2009) | 4 lines Changed paths: M /branches/zip/ChangeLog branches/zip: Add ChangeLog for r6157. ------------------------------------------------------------------------ r6163 | calvin | 2009-11-11 17:53:20 +0200 (Wed, 11 Nov 2009) | 8 lines Changed paths: M /branches/zip/handler/ha_innodb.cc M /branches/zip/handler/ha_innodb.h branches/zip: Exclude thd_binlog_filter_ok() when building with older version of MySQL. thd_binlog_filter_ok() is introduced in MySQL 5.1.41. But the plugin can be built with MySQL prior to 5.1.41. Approved by Heikki (on IM). ------------------------------------------------------------------------ r6169 | calvin | 2009-11-12 14:40:43 +0200 (Thu, 12 Nov 2009) | 6 lines Changed paths: A /branches/zip/mysql-test/innodb_bug46676.result A /branches/zip/mysql-test/innodb_bug46676.test branches/zip: add test case for bug#46676 This crash is reproducible with InnoDB plugin 1.0.4 + MySQL 5.1.37. But no longer reproducible after MySQL 5.1.38 (with plugin 1.0.5). Add test case to catch future regression. ------------------------------------------------------------------------ r6170 | marko | 2009-11-12 15:49:08 +0200 (Thu, 12 Nov 2009) | 4 lines Changed paths: M /branches/zip/ChangeLog M /branches/zip/handler/ha_innodb.cc M /branches/zip/include/db0err.h M /branches/zip/row/row0merge.c M /branches/zip/row/row0mysql.c branches/zip: Allow CREATE INDEX to be interrupted. (Issue #354) rb://183 approved by Heikki Tuuri ------------------------------------------------------------------------ r6175 | vasil | 2009-11-16 20:07:39 +0200 (Mon, 16 Nov 2009) | 4 lines Changed paths: M /branches/zip/ChangeLog branches/zip: Wrap line at 78th char in the ChangeLog ------------------------------------------------------------------------ r6177 | calvin | 2009-11-16 20:20:38 +0200 (Mon, 16 Nov 2009) | 2 lines Changed paths: M /branches/zip/ChangeLog branches/zip: add an entry to ChangeLog for r6065 ------------------------------------------------------------------------ r6179 | marko | 2009-11-17 10:19:34 +0200 (Tue, 17 Nov 2009) | 2 lines Changed paths: M /branches/zip/handler/ha_innodb.cc branches/zip: ha_innobase::change_active_index(): When the history is missing, report it to the client, not to the error log. ------------------------------------------------------------------------ r6181 | vasil | 2009-11-17 12:21:41 +0200 (Tue, 17 Nov 2009) | 33 lines Changed paths: M /branches/zip/mysql-test/innodb-index.test branches/zip: At the end of innodb-index.test: restore the environment as it was before the test was started to silence this warning: MTR's internal check of the test case 'main.innodb-index' failed. This means that the test case does not preserve the state that existed before the test case was executed. Most likely the test case did not do a proper clean-up. This is the diff of the states of the servers before and after the test case was executed: mysqltest: Logging to '/tmp/autotest.sh-20091117_033000-zip.btyZwu/mysql-5.1/mysql-test/var/tmp/check-mysqld_1.log'. mysqltest: Results saved in '/tmp/autotest.sh-20091117_033000-zip.btyZwu/mysql-5.1/mysql-test/var/tmp/check-mysqld_1.result'. mysqltest: Connecting to server localhost:13000 (socket /tmp/autotest.sh-20091117_033000-zip.btyZwu/mysql-5.1/mysql-test/var/tmp/mysqld.1.sock) as 'root', connection 'default', attempt 0 ... mysqltest: ... Connected. mysqltest: Start processing test commands from './include/check-testcase.test' ... mysqltest: ... Done processing test commands. --- /tmp/autotest.sh-20091117_033000-zip.btyZwu/mysql-5.1/mysql-test/var/tmp/check-mysqld_1.result 2009-11-17 13:10:40.000000000 +0300 +++ /tmp/autotest.sh-20091117_033000-zip.btyZwu/mysql-5.1/mysql-test/var/tmp/check-mysqld_1.reject 2009-11-17 13:10:54.000000000 +0300 @@ -84,7 +84,7 @@ INNODB_DOUBLEWRITE ON INNODB_FAST_SHUTDOWN 1 INNODB_FILE_FORMAT Antelope -INNODB_FILE_FORMAT_CHECK Antelope +INNODB_FILE_FORMAT_CHECK Barracuda INNODB_FILE_PER_TABLE OFF INNODB_FLUSH_LOG_AT_TRX_COMMIT 1 INNODB_FLUSH_METHOD mysqltest: Result content mismatch not ok ------------------------------------------------------------------------ r6182 | marko | 2009-11-17 13:49:15 +0200 (Tue, 17 Nov 2009) | 1 line Changed paths: M /branches/zip/mysql-test/innodb-consistent-master.opt M /branches/zip/mysql-test/innodb-consistent.result M /branches/zip/mysql-test/innodb-consistent.test M /branches/zip/mysql-test/innodb-use-sys-malloc-master.opt M /branches/zip/mysql-test/innodb-use-sys-malloc.result M /branches/zip/mysql-test/innodb-use-sys-malloc.test M /branches/zip/mysql-test/innodb_bug21704.result M /branches/zip/mysql-test/innodb_bug21704.test M /branches/zip/mysql-test/innodb_bug40360.test M /branches/zip/mysql-test/innodb_bug40565.result M /branches/zip/mysql-test/innodb_bug40565.test M /branches/zip/mysql-test/innodb_bug41904.result M /branches/zip/mysql-test/innodb_bug41904.test M /branches/zip/mysql-test/innodb_bug42101-nonzero-master.opt M /branches/zip/mysql-test/innodb_bug42101-nonzero.result M /branches/zip/mysql-test/innodb_bug42101-nonzero.test M /branches/zip/mysql-test/innodb_bug42101.result M /branches/zip/mysql-test/innodb_bug42101.test M /branches/zip/mysql-test/innodb_bug44032.result M /branches/zip/mysql-test/innodb_bug44032.test M /branches/zip/mysql-test/innodb_bug44369.result M /branches/zip/mysql-test/innodb_bug44369.test M /branches/zip/mysql-test/innodb_bug44571.result M /branches/zip/mysql-test/innodb_bug44571.test M /branches/zip/mysql-test/innodb_bug45357.test M /branches/zip/mysql-test/innodb_bug46000.result M /branches/zip/mysql-test/innodb_bug46000.test M /branches/zip/mysql-test/innodb_bug46676.result M /branches/zip/mysql-test/innodb_bug46676.test M /branches/zip/mysql-test/innodb_bug47167.result M /branches/zip/mysql-test/innodb_bug47167.test M /branches/zip/mysql-test/innodb_bug47777.result M /branches/zip/mysql-test/innodb_bug47777.test M /branches/zip/mysql-test/innodb_file_format.result M /branches/zip/mysql-test/innodb_file_format.test branches/zip: Set svn:eol-style on mysql-test files. ------------------------------------------------------------------------ r6183 | marko | 2009-11-17 13:51:16 +0200 (Tue, 17 Nov 2009) | 1 line Changed paths: M /branches/zip/mysql-test/innodb-consistent-master.opt M /branches/zip/mysql-test/innodb-master.opt M /branches/zip/mysql-test/innodb-semi-consistent-master.opt M /branches/zip/mysql-test/innodb-use-sys-malloc-master.opt M /branches/zip/mysql-test/innodb_bug42101-nonzero-master.opt branches/zip: Prepend loose_ to plugin-only mysql-test options. ------------------------------------------------------------------------ r6184 | marko | 2009-11-17 13:52:01 +0200 (Tue, 17 Nov 2009) | 1 line Changed paths: M /branches/zip/mysql-test/innodb-index.result M /branches/zip/mysql-test/innodb-index.test branches/zip: innodb-index.test: Restore innodb_file_format_check. ------------------------------------------------------------------------ r6185 | marko | 2009-11-17 16:44:20 +0200 (Tue, 17 Nov 2009) | 16 lines Changed paths: M /branches/zip/handler/ha_innodb.cc M /branches/zip/mysql-test/innodb.result M /branches/zip/mysql-test/innodb.test M /branches/zip/mysql-test/innodb_bug44369.result M /branches/zip/mysql-test/innodb_bug44369.test D /branches/zip/mysql-test/patches/innodb-index.diff M /branches/zip/row/row0mysql.c branches/zip: Report duplicate table names to the client connection, not to the error log. This change will allow innodb-index.test to be re-enabled. It was previously disabled, because mysql-test-run does not like output in the error log. row_create_table_for_mysql(): Do not output anything to the error log when reporting DB_DUPLICATE_KEY. Let the caller report the error. Add a TODO comment that the dict_table_t object is apparently not freed when an error occurs. create_table_def(): Convert InnoDB table names to the character set of the client connection for reporting. Use my_error(ER_WRONG_COLUMN_NAME) for reporting reserved column names. Report my_error(ER_TABLE_EXISTS_ERROR) when row_create_table_for_mysql() returns DB_DUPLICATE_KEY. rb://206 ------------------------------------------------------------------------ r6186 | vasil | 2009-11-17 16:48:14 +0200 (Tue, 17 Nov 2009) | 4 lines Changed paths: M /branches/zip/ChangeLog branches/zip: Add ChangeLog entry for r6185. ------------------------------------------------------------------------ r6189 | marko | 2009-11-18 11:36:18 +0200 (Wed, 18 Nov 2009) | 5 lines Changed paths: M /branches/zip/ChangeLog M /branches/zip/handler/handler0alter.cc branches/zip: ha_innobase::add_index(): When creating the primary key and the table is being locked by another transaction, do not attempt to drop the table. (Bug #48782) Approved by Sunny Bains over IM ------------------------------------------------------------------------ r6194 | vasil | 2009-11-19 09:24:45 +0200 (Thu, 19 Nov 2009) | 5 lines Changed paths: M /branches/zip/include/univ.i branches/zip: Increment version number from 1.0.5 to 1.0.6 since 1.0.5 was just released by MySQL and we will soon release 1.0.6. ------------------------------------------------------------------------ r6197 | calvin | 2009-11-19 09:32:55 +0200 (Thu, 19 Nov 2009) | 6 lines Changed paths: M /branches/zip/CMakeLists.txt branches/zip: merge the fix of bug#48317 (CMake file) Due to MySQL changes to the CMake, it is no longer able to build InnoDB plugin as a static library on Windows. The fix is proposed by Vlad of MySQL. ------------------------------------------------------------------------ r6198 | vasil | 2009-11-19 09:44:31 +0200 (Thu, 19 Nov 2009) | 4 lines Changed paths: M /branches/zip/ChangeLog branches/zip: Add ChangeLog entry for r6197. ------------------------------------------------------------------------ r6199 | vasil | 2009-11-19 12:10:12 +0200 (Thu, 19 Nov 2009) | 31 lines Changed paths: M /branches/zip/ChangeLog M /branches/zip/btr/btr0btr.c M /branches/zip/data/data0type.c branches/zip: Merge r6159:6198 from branches/5.1: ------------------------------------------------------------------------ r6187 | jyang | 2009-11-18 05:27:30 +0200 (Wed, 18 Nov 2009) | 9 lines Changed paths: M /branches/5.1/btr/btr0btr.c branches/5.1: Fix bug #48469 "when innodb tablespace is configured too small, crash and corruption!". Function btr_create() did not check the return status of fseg_create(), and continue the index creation even there is no sufficient space. rb://205 Approved by Marko ------------------------------------------------------------------------ r6188 | jyang | 2009-11-18 07:14:23 +0200 (Wed, 18 Nov 2009) | 8 lines Changed paths: M /branches/5.1/data/data0type.c branches/5.1: Fix bug #48526 "Data type for float and double is incorrectly reported in InnoDB table monitor". Certain datatypes are not printed correctly in dtype_print(). rb://204 Approved by Marko. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r6201 | marko | 2009-11-19 14:09:11 +0200 (Thu, 19 Nov 2009) | 2 lines Changed paths: M /branches/zip/handler/handler0alter.cc branches/zip: ha_innobase::add_index(): Clarify the comment on orphaned tables when creating a primary key. ------------------------------------------------------------------------ r6202 | jyang | 2009-11-19 15:01:00 +0200 (Thu, 19 Nov 2009) | 8 lines Changed paths: M /branches/zip/btr/btr0btr.c branches/zip: Function fseg_free() is no longer defined in branches/zip. To port fix for bug #48469 to zip, we can use btr_free_root() which frees the page, and also does not require mini-transaction. Approved by Marko. ------------------------------------------------------------------------ r6207 | vasil | 2009-11-20 10:19:14 +0200 (Fri, 20 Nov 2009) | 54 lines Changed paths: M /branches/zip/handler/ha_innodb.cc branches/zip: Merge r6198:6206 from branches/5.1: (r6203 was skipped as it is already in branches/zip) ------------------------------------------------------------------------ r6200 | vasil | 2009-11-19 12:14:23 +0200 (Thu, 19 Nov 2009) | 4 lines Changed paths: M /branches/5.1/btr/btr0btr.c branches/5.1: White space fixup - indent under the opening ( ------------------------------------------------------------------------ r6203 | jyang | 2009-11-19 15:12:22 +0200 (Thu, 19 Nov 2009) | 8 lines Changed paths: M /branches/5.1/btr/btr0btr.c branches/5.1: Use btr_free_root() instead of fseg_free() for the fix of bug #48469, because fseg_free() is not defined in the zip branch. And we could save one mini-trasaction started by fseg_free(). Approved by Marko. ------------------------------------------------------------------------ r6205 | jyang | 2009-11-20 07:55:48 +0200 (Fri, 20 Nov 2009) | 11 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc branches/5.1: Add a special case to handle the Duplicated Key error and return DB_ERROR instead. This is to avoid a possible SIGSEGV by mysql error handling re-entering the storage layer for dup key info without proper table handle. This is to prevent a server crash when error situation in bug #45961 "DDL on partitioned innodb tables leaves data dictionary in an inconsistent state" happens. rb://157 approved by Sunny Bains. ------------------------------------------------------------------------ r6206 | jyang | 2009-11-20 09:38:43 +0200 (Fri, 20 Nov 2009) | 5 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc branches/5.1: Fix a minor code formating issue for the parenthesis iplacement of the if condition in rename_table(). ------------------------------------------------------------------------ ------------------------------------------------------------------------ r6208 | vasil | 2009-11-20 10:49:24 +0200 (Fri, 20 Nov 2009) | 4 lines Changed paths: M /branches/zip/ChangeLog branches/zip: Add ChangeLog entry for c6207. ------------------------------------------------------------------------ r6210 | vasil | 2009-11-20 23:39:48 +0200 (Fri, 20 Nov 2009) | 3 lines Changed paths: M /branches/zip/trx/trx0i_s.c branches/zip: Whitespace fixup. ------------------------------------------------------------------------ r6248 | marko | 2009-11-30 12:19:50 +0200 (Mon, 30 Nov 2009) | 1 line Changed paths: M /branches/zip/ChangeLog branches/zip: ChangeLog: Document r4922 that was forgotten. ------------------------------------------------------------------------ r6252 | marko | 2009-11-30 12:50:11 +0200 (Mon, 30 Nov 2009) | 23 lines Changed paths: M /branches/zip/ChangeLog M /branches/zip/dict/dict0boot.c M /branches/zip/dict/dict0crea.c M /branches/zip/dict/dict0load.c M /branches/zip/dict/dict0mem.c M /branches/zip/fil/fil0fil.c M /branches/zip/handler/ha_innodb.cc M /branches/zip/include/dict0mem.h M /branches/zip/row/row0mysql.c branches/zip: Suppress errors about non-found temporary tables. Write the is_temp flag to SYS_TABLES.MIX_LEN. dict_table_t:🎏 Add a flag for is_temporary, DICT_TF2_TEMPORARY. Unlike other flags, this will not be written to the tablespace flags or SYS_TABLES.TYPE, but only to SYS_TABLES.MIX_LEN. dict_build_table_def_step(): Only pass DICT_TF_BITS to tablespaces. dict_check_tablespaces_and_store_max_id(), dict_load_table(): Suppress errors about temporary tables not being found. dict_create_sys_tables_tuple(): Write the DICT_TF2_TEMPORARY flag to SYS_TABLES.MIX_LEN. fil_space_create(), fil_create_new_single_table_tablespace(): Add assertions about space->flags. row_drop_table_for_mysql(): Do not complain about non-found temporary tables. rb://160 approved by Heikki Tuuri. This addresses the second part of Bug #41609 Crash recovery does not work for InnoDB temporary tables. ------------------------------------------------------------------------ r6263 | vasil | 2009-12-01 14:49:05 +0200 (Tue, 01 Dec 2009) | 4 lines Changed paths: M /branches/zip/include/univ.i branches/zip: Increment version number from 1.0.6 to 1.0.7 1.0.6 has been released ------------------------------------------------------------------------ r6264 | vasil | 2009-12-01 16:19:44 +0200 (Tue, 01 Dec 2009) | 1 line Changed paths: M /branches/zip/ChangeLog branches/zip: Add ChangeLog entry for the release of 1.0.6. ------------------------------------------------------------------------ r6269 | marko | 2009-12-02 11:35:22 +0200 (Wed, 02 Dec 2009) | 2 lines Changed paths: M /branches/zip/srv/srv0start.c branches/zip: innobase_start_or_create_for_mysql(): UNIV_IBUF_DEBUG should not break crash recovery, but UNIV_IBUF_COUNT_DEBUG will. ------------------------------------------------------------------------ r6270 | marko | 2009-12-02 11:36:47 +0200 (Wed, 02 Dec 2009) | 1 line Changed paths: M /branches/zip/srv/srv0start.c branches/zip: innobase_start_or_create_for_mysql(): Log the zlib version. ------------------------------------------------------------------------ r6271 | marko | 2009-12-02 11:43:49 +0200 (Wed, 02 Dec 2009) | 2 lines Changed paths: M /branches/zip/ChangeLog M /branches/zip/Makefile.am M /branches/zip/include/univ.i M /branches/zip/plug.in branches/zip: ChangeLog: Document that since r6270, the zlib version number will be displayed at start-up. ------------------------------------------------------------------------ r6272 | marko | 2009-12-02 11:46:05 +0200 (Wed, 02 Dec 2009) | 1 line Changed paths: M /branches/zip/Makefile.am M /branches/zip/include/univ.i M /branches/zip/plug.in branches/zip: Revert changes that were accidentally committed in r6271. ------------------------------------------------------------------------ r6274 | marko | 2009-12-03 14:47:12 +0200 (Thu, 03 Dec 2009) | 6 lines Changed paths: M /branches/zip/dict/dict0dict.c branches/zip: dict_table_check_for_dup_indexes(): Assert that the data dictionary mutex is being held while table->indexes is accessed. This is already the case. Currently, only dict_table_get_next_index() and dict_table_get_first_index() are being invoked without holding dict_sys->mutex. ------------------------------------------------------------------------ r6275 | pekka | 2009-12-03 18:32:47 +0200 (Thu, 03 Dec 2009) | 10 lines Changed paths: M /branches/zip/include/log0recv.h M /branches/zip/include/trx0sys.h M /branches/zip/log/log0recv.c M /branches/zip/trx/trx0sys.c branches/zip: Minor changes which allow build with UNIV_HOTBACKUP defined to succeed: include/trx0sys.h: Allow Hot Backup build to see some TRX_SYS_DOUBLEWRITE_... macros. trx/trx0sys.c: Exclude trx_sys_close() function from Hot Backup build. log/log0recv.[ch]: Exclude recv_sys_var_init() function from Hot Backup build. This change should not affect !UNIV_HOTBACKUP build. ------------------------------------------------------------------------ r6277 | marko | 2009-12-08 11:13:36 +0200 (Tue, 08 Dec 2009) | 1 line Changed paths: M /branches/zip/fsp/fsp0fsp.c branches/zip: fsp0fsp.c: Add some missing in/out and const qualifiers. ------------------------------------------------------------------------ r6285 | marko | 2009-12-09 09:24:50 +0200 (Wed, 09 Dec 2009) | 13 lines Changed paths: M /branches/zip/row/row0sel.c branches/zip: row_sel_fetch_columns(): Remove redundant code that was accidentally added in r1591, which introduced dfield_t::ext in order to make the merge sort of fast index creation support externally stored columns, Initially, I tried to allocate the bit for dfield_t::ext from dfield_t::len by making the length 31 bits and mapping UNIV_SQL_NULL to something that would fit in it. Then I decided that it would be too risky. The redundant check was part of the mapping. The condition may have been dfield_is_null() initially. This redundant code was noticed by Sergey Petrunya on the MySQL internals list. ------------------------------------------------------------------------ r6288 | marko | 2009-12-09 09:51:00 +0200 (Wed, 09 Dec 2009) | 15 lines Changed paths: M /branches/zip/row/row0upd.c branches/zip: row_upd_copy_columns(): Remove redundant code that was accidentally added in r1591, which introduced dfield_t::ext in order to make the merge sort of fast index creation support externally stored columns. Initially, I tried to allocate the bit for dfield_t::ext from dfield_t::len by making the length 31 bits and mapping UNIV_SQL_NULL to something that would fit in it. Then I decided that it would be too risky. The redundant check was part of the mapping. The condition may have been dfield_is_null() initially. This is similar to the redundant code in row_sel_fetch_columns() that was noticed by Sergey Petrunya on the MySQL internals list and removed in r6285. As far as I can tell, there are no redundant UNIV_SQL_NULL assignments remaining after this change. ------------------------------------------------------------------------ r6305 | marko | 2009-12-14 13:03:57 +0200 (Mon, 14 Dec 2009) | 2 lines Changed paths: M /branches/zip/row/row0umod.c branches/zip: row_undo_mod_del_unmark_sec_and_undo_update(): Add a missing const qualifier. ------------------------------------------------------------------------ r6309 | marko | 2009-12-15 14:05:50 +0200 (Tue, 15 Dec 2009) | 3 lines Changed paths: M /branches/zip/lock/lock0lock.c branches/zip: lock_rec_insert_check_and_lock(): Avoid casting away constness. Use page_rec_get_next_const() instead. This silences a gcc 4.2.4 warning. Reported by Sunny Bains. ------------------------------------------------------------------------ r6312 | marko | 2009-12-16 10:10:36 +0200 (Wed, 16 Dec 2009) | 6 lines Changed paths: M /branches/zip/fil/fil0fil.c branches/zip: fil_close(): Add #ifndef UNIV_HOTBACKUP around a debug assertion on mutex.magic_n. InnoDB Hot Backup is a single-threaded program and does not contain mutexes. This change allows InnoDB Hot Backup to be compiled with UNIV_DEBUG. Suggested by Michael Izioumtchenko. ------------------------------------------------------------------------ r6321 | marko | 2009-12-16 16:16:33 +0200 (Wed, 16 Dec 2009) | 4 lines Changed paths: M /branches/zip/row/row0merge.c branches/zip: row_merge_drop_temp_indexes(): Revert a hack to transaction isolation level that was made unnecessary by r5826 (Issue #337). When this function is called, any active data dictionary transaction should have been rolled back. ------------------------------------------------------------------------ r6345 | marko | 2009-12-21 10:46:14 +0200 (Mon, 21 Dec 2009) | 7 lines Changed paths: M /branches/zip/log/log0recv.c branches/zip: recv_scan_log_recs(): Non-functional change: Replace a debug assertion ut_ad(len > 0) with ut_ad(len >= OS_FILE_LOG_BLOCK_SIZE). This change is only for readability, for Issue #428. Another assertion on len being an integer multiple of OS_FILE_LOG_BLOCK_SIZE already ensured together with the old ut_ad(len > 0) that actually len must be at least OS_FILE_LOG_BLOCK_SIZE. ------------------------------------------------------------------------ r6346 | marko | 2009-12-21 12:03:25 +0200 (Mon, 21 Dec 2009) | 2 lines Changed paths: M /branches/zip/log/log0recv.c branches/zip: recv_recovery_from_checkpoint_finish(): Revert a change that was accidentally committed in r6345. ------------------------------------------------------------------------ r6348 | marko | 2009-12-22 11:04:34 +0200 (Tue, 22 Dec 2009) | 37 lines Changed paths: M /branches/zip/handler/ha_innodb.cc M /branches/zip/include/ha_prototypes.h M /branches/zip/include/trx0trx.h M /branches/zip/lock/lock0lock.c M /branches/zip/trx/trx0i_s.c M /branches/zip/trx/trx0trx.c branches/zip: Merge a change from MySQL: ------------------------------------------------------------ revno: 3236 committer: Satya B <satya.bn@sun.com> branch nick: mysql-5.1-bugteam timestamp: Tue 2009-12-01 17:48:57 +0530 message: merge to mysql-5.1-bugteam ------------------------------------------------------------ revno: 3234.1.1 committer: Gleb Shchepa <gshchepa@mysql.com> branch nick: mysql-5.1-bugteam timestamp: Tue 2009-12-01 14:38:40 +0400 message: Bug #38883 (reopened): thd_security_context is not thread safe, crashes? manual merge 5.0-->5.1, updating InnoDB plugin. ------------------------------------------------------------ revno: 1810.3968.13 committer: Gleb Shchepa <gshchepa@mysql.com> branch nick: mysql-5.0-bugteam timestamp: Tue 2009-12-01 14:24:44 +0400 message: Bug #38883 (reopened): thd_security_context is not thread safe, crashes? The bug 38816 changed the lock that protects THD::query from LOCK_thread_count to LOCK_thd_data, but didn't update the associated InnoDB functions. 1. The innobase_mysql_prepare_print_arbitrary_thd and the innobase_mysql_end_print_arbitrary_thd InnoDB functions have been removed, since now we have a per-thread mutex: now we don't need to wrap several inter-thread access tries to THD::query with a single global LOCK_thread_count lock, so we can simplify the code. 2. The innobase_mysql_print_thd function has been modified to lock LOCK_thd_data in direct way. ------------------------------------------------------------------------ r6351 | marko | 2009-12-22 11:11:18 +0200 (Tue, 22 Dec 2009) | 1 line Changed paths: M /branches/zip/handler/ha_innodb.cc branches/zip: Remove an obsolete declaration of LOCK_thread_count. ------------------------------------------------------------------------ r6352 | marko | 2009-12-22 12:33:01 +0200 (Tue, 22 Dec 2009) | 104 lines Changed paths: M /branches/zip/handler/ha_innodb.cc M /branches/zip/include/lock0lock.h M /branches/zip/include/srv0srv.h M /branches/zip/lock/lock0lock.c M /branches/zip/log/log0log.c M /branches/zip/mysql-test/innodb-autoinc.result M /branches/zip/mysql-test/innodb-autoinc.test M /branches/zip/row/row0sel.c M /branches/zip/srv/srv0srv.c M /branches/zip/srv/srv0start.c branches/zip: Merge revisions 6206:6350 from branches/5.1, except r6347, r6349, r6350 which were committed separately to both branches, and r6310, which was backported from zip to 5.1. ------------------------------------------------------------------------ r6206 | jyang | 2009-11-20 09:38:43 +0200 (Fri, 20 Nov 2009) | 3 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc branches/5.1: Non-functional change, fix formatting. ------------------------------------------------------------------------ r6230 | sunny | 2009-11-24 23:52:43 +0200 (Tue, 24 Nov 2009) | 3 lines Changed paths: M /branches/5.1/mysql-test/innodb-autoinc.result branches/5.1: Fix autoinc failing test results. (this should be skipped when merging 5.1 into zip) ------------------------------------------------------------------------ r6231 | sunny | 2009-11-25 10:26:27 +0200 (Wed, 25 Nov 2009) | 7 lines Changed paths: M /branches/5.1/mysql-test/innodb-autoinc.result M /branches/5.1/mysql-test/innodb-autoinc.test M /branches/5.1/row/row0sel.c branches/5.1: Fix BUG#49032 - auto_increment field does not initialize to last value in InnoDB Storage Engine. We use the appropriate function to read the column value for non-integer autoinc column types, namely float and double. rb://208. Approved by Marko. ------------------------------------------------------------------------ r6232 | sunny | 2009-11-25 10:27:39 +0200 (Wed, 25 Nov 2009) | 2 lines Changed paths: M /branches/5.1/row/row0sel.c branches/5.1: This is an interim fix, fix white space errors. ------------------------------------------------------------------------ r6233 | sunny | 2009-11-25 10:28:35 +0200 (Wed, 25 Nov 2009) | 2 lines Changed paths: M /branches/5.1/include/mach0data.h M /branches/5.1/include/mach0data.ic M /branches/5.1/mysql-test/innodb-autoinc.result M /branches/5.1/mysql-test/innodb-autoinc.test M /branches/5.1/row/row0sel.c branches/5.1: This is an interim fix, fix tests and make read float/double arg const. ------------------------------------------------------------------------ r6234 | sunny | 2009-11-25 10:29:03 +0200 (Wed, 25 Nov 2009) | 2 lines Changed paths: M /branches/5.1/row/row0sel.c branches/5.1: This is an interim fix, fix whitepsace issues. ------------------------------------------------------------------------ r6235 | sunny | 2009-11-26 01:14:42 +0200 (Thu, 26 Nov 2009) | 9 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc M /branches/5.1/mysql-test/innodb-autoinc.result M /branches/5.1/mysql-test/innodb-autoinc.test branches/5.1: Fix Bug#47720 - REPLACE INTO Autoincrement column with negative values. This bug is similiar to the negative autoinc filter patch from earlier, with the additional handling of filtering out the negative column values set explicitly by the user. rb://184 Approved by Heikki. ------------------------------------------------------------------------ r6242 | vasil | 2009-11-27 22:07:12 +0200 (Fri, 27 Nov 2009) | 4 lines Changed paths: M /branches/5.1/export.sh branches/5.1: Minor changes to support plugin snapshots. ------------------------------------------------------------------------ r6306 | calvin | 2009-12-14 15:12:46 +0200 (Mon, 14 Dec 2009) | 5 lines Changed paths: M /branches/5.1/mysql-test/innodb-autoinc.result M /branches/5.1/mysql-test/innodb-autoinc.test branches/5.1: fix bug#49267: innodb-autoinc.test fails on windows because of different case mode There is no change to the InnoDB code, only to fix test case by changing "T1" to "t1". ------------------------------------------------------------------------ r6324 | jyang | 2009-12-17 06:54:24 +0200 (Thu, 17 Dec 2009) | 8 lines Changed paths: M /branches/5.1/handler/ha_innodb.cc M /branches/5.1/include/lock0lock.h M /branches/5.1/include/srv0srv.h M /branches/5.1/lock/lock0lock.c M /branches/5.1/log/log0log.c M /branches/5.1/srv/srv0srv.c M /branches/5.1/srv/srv0start.c branches/5.1: Fix bug #47814 - Diagnostics are frequently not printed after a long lock wait in InnoDB. Separate out the lock wait timeout check thread from monitor information printing thread. rb://200 Approved by Marko. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r6364 | marko | 2009-12-26 21:06:31 +0200 (Sat, 26 Dec 2009) | 4 lines Changed paths: M /branches/zip/ibuf/ibuf0ibuf.c branches/zip: ibuf_bitmap_get_map_page(): Define a wrapper macro that passes __FILE__, __LINE__ of the caller to buf_page_get_gen(). This will ease the diagnosis of the likes of Issue #135. ------------------------------------------------------------------------
1476 lines
38 KiB
C
1476 lines
38 KiB
C
/*****************************************************************************
|
|
|
|
Copyright (c) 2007, 2009, Innobase Oy. All Rights Reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free Software
|
|
Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
/**************************************************//**
|
|
@file trx/trx0i_s.c
|
|
INFORMATION SCHEMA innodb_trx, innodb_locks and
|
|
innodb_lock_waits tables fetch code.
|
|
|
|
The code below fetches information needed to fill those
|
|
3 dynamic tables and uploads it into a "transactions
|
|
table cache" for later retrieval.
|
|
|
|
Created July 17, 2007 Vasil Dimov
|
|
*******************************************************/
|
|
|
|
#include <mysql/plugin.h>
|
|
|
|
#include "mysql_addons.h"
|
|
|
|
#include "univ.i"
|
|
#include "buf0buf.h"
|
|
#include "dict0dict.h"
|
|
#include "ha0storage.h"
|
|
#include "ha_prototypes.h"
|
|
#include "hash0hash.h"
|
|
#include "lock0iter.h"
|
|
#include "lock0lock.h"
|
|
#include "mem0mem.h"
|
|
#include "page0page.h"
|
|
#include "rem0rec.h"
|
|
#include "row0row.h"
|
|
#include "srv0srv.h"
|
|
#include "sync0rw.h"
|
|
#include "sync0sync.h"
|
|
#include "sync0types.h"
|
|
#include "trx0i_s.h"
|
|
#include "trx0sys.h"
|
|
#include "trx0trx.h"
|
|
#include "ut0mem.h"
|
|
#include "ut0ut.h"
|
|
|
|
/** Initial number of rows in the table cache */
|
|
#define TABLE_CACHE_INITIAL_ROWSNUM 1024
|
|
|
|
/** @brief The maximum number of chunks to allocate for a table cache.
|
|
|
|
The rows of a table cache are stored in a set of chunks. When a new
|
|
row is added a new chunk is allocated if necessary. Assuming that the
|
|
first one is 1024 rows (TABLE_CACHE_INITIAL_ROWSNUM) and each
|
|
subsequent is N/2 where N is the number of rows we have allocated till
|
|
now, then 39th chunk would accommodate 1677416425 rows and all chunks
|
|
would accommodate 3354832851 rows. */
|
|
#define MEM_CHUNKS_IN_TABLE_CACHE 39
|
|
|
|
/** The following are some testing auxiliary macros. Do not enable them
|
|
in a production environment. */
|
|
/* @{ */
|
|
|
|
#if 0
|
|
/** If this is enabled then lock folds will always be different
|
|
resulting in equal rows being put in a different cells of the hash
|
|
table. Checking for duplicates will be flawed because different
|
|
fold will be calculated when a row is searched in the hash table. */
|
|
#define TEST_LOCK_FOLD_ALWAYS_DIFFERENT
|
|
#endif
|
|
|
|
#if 0
|
|
/** This effectively kills the search-for-duplicate-before-adding-a-row
|
|
function, but searching in the hash is still performed. It will always
|
|
be assumed that lock is not present and insertion will be performed in
|
|
the hash table. */
|
|
#define TEST_NO_LOCKS_ROW_IS_EVER_EQUAL_TO_LOCK_T
|
|
#endif
|
|
|
|
#if 0
|
|
/** This aggressively repeats adding each row many times. Depending on
|
|
the above settings this may be noop or may result in lots of rows being
|
|
added. */
|
|
#define TEST_ADD_EACH_LOCKS_ROW_MANY_TIMES
|
|
#endif
|
|
|
|
#if 0
|
|
/** Very similar to TEST_NO_LOCKS_ROW_IS_EVER_EQUAL_TO_LOCK_T but hash
|
|
table search is not performed at all. */
|
|
#define TEST_DO_NOT_CHECK_FOR_DUPLICATE_ROWS
|
|
#endif
|
|
|
|
#if 0
|
|
/** Do not insert each row into the hash table, duplicates may appear
|
|
if this is enabled, also if this is enabled searching into the hash is
|
|
noop because it will be empty. */
|
|
#define TEST_DO_NOT_INSERT_INTO_THE_HASH_TABLE
|
|
#endif
|
|
/* @} */
|
|
|
|
/** Memory limit passed to ha_storage_put_memlim().
|
|
@param cache hash storage
|
|
@return maximum allowed allocation size */
|
|
#define MAX_ALLOWED_FOR_STORAGE(cache) \
|
|
(TRX_I_S_MEM_LIMIT \
|
|
- (cache)->mem_allocd)
|
|
|
|
/** Memory limit in table_cache_create_empty_row().
|
|
@param cache hash storage
|
|
@return maximum allowed allocation size */
|
|
#define MAX_ALLOWED_FOR_ALLOC(cache) \
|
|
(TRX_I_S_MEM_LIMIT \
|
|
- (cache)->mem_allocd \
|
|
- ha_storage_get_size((cache)->storage))
|
|
|
|
/** Memory for each table in the intermediate buffer is allocated in
|
|
separate chunks. These chunks are considered to be concatenated to
|
|
represent one flat array of rows. */
|
|
typedef struct i_s_mem_chunk_struct {
|
|
ulint offset; /*!< offset, in number of rows */
|
|
ulint rows_allocd; /*!< the size of this chunk, in number
|
|
of rows */
|
|
void* base; /*!< start of the chunk */
|
|
} i_s_mem_chunk_t;
|
|
|
|
/** This represents one table's cache. */
|
|
typedef struct i_s_table_cache_struct {
|
|
ulint rows_used; /*!< number of used rows */
|
|
ulint rows_allocd; /*!< number of allocated rows */
|
|
ulint row_size; /*!< size of a single row */
|
|
i_s_mem_chunk_t chunks[MEM_CHUNKS_IN_TABLE_CACHE]; /*!< array of
|
|
memory chunks that stores the
|
|
rows */
|
|
} i_s_table_cache_t;
|
|
|
|
/** This structure describes the intermediate buffer */
|
|
struct trx_i_s_cache_struct {
|
|
rw_lock_t rw_lock; /*!< read-write lock protecting
|
|
the rest of this structure */
|
|
ullint last_read; /*!< last time the cache was read;
|
|
measured in microseconds since
|
|
epoch */
|
|
mutex_t last_read_mutex;/*!< mutex protecting the
|
|
last_read member - it is updated
|
|
inside a shared lock of the
|
|
rw_lock member */
|
|
i_s_table_cache_t innodb_trx; /*!< innodb_trx table */
|
|
i_s_table_cache_t innodb_locks; /*!< innodb_locks table */
|
|
i_s_table_cache_t innodb_lock_waits;/*!< innodb_lock_waits table */
|
|
/** the hash table size is LOCKS_HASH_CELLS_NUM * sizeof(void*) bytes */
|
|
#define LOCKS_HASH_CELLS_NUM 10000
|
|
hash_table_t* locks_hash; /*!< hash table used to eliminate
|
|
duplicate entries in the
|
|
innodb_locks table */
|
|
/** Initial size of the cache storage */
|
|
#define CACHE_STORAGE_INITIAL_SIZE 1024
|
|
/** Number of hash cells in the cache storage */
|
|
#define CACHE_STORAGE_HASH_CELLS 2048
|
|
ha_storage_t* storage; /*!< storage for external volatile
|
|
data that can possibly not be
|
|
available later, when we release
|
|
the kernel mutex */
|
|
ulint mem_allocd; /*!< the amount of memory
|
|
allocated with mem_alloc*() */
|
|
ibool is_truncated; /*!< this is TRUE if the memory
|
|
limit was hit and thus the data
|
|
in the cache is truncated */
|
|
};
|
|
|
|
/** This is the intermediate buffer where data needed to fill the
|
|
INFORMATION SCHEMA tables is fetched and later retrieved by the C++
|
|
code in handler/i_s.cc. */
|
|
static trx_i_s_cache_t trx_i_s_cache_static;
|
|
/** This is the intermediate buffer where data needed to fill the
|
|
INFORMATION SCHEMA tables is fetched and later retrieved by the C++
|
|
code in handler/i_s.cc. */
|
|
UNIV_INTERN trx_i_s_cache_t* trx_i_s_cache = &trx_i_s_cache_static;
|
|
|
|
/*******************************************************************//**
|
|
For a record lock that is in waiting state retrieves the only bit that
|
|
is set, for a table lock returns ULINT_UNDEFINED.
|
|
@return record number within the heap */
|
|
static
|
|
ulint
|
|
wait_lock_get_heap_no(
|
|
/*==================*/
|
|
const lock_t* lock) /*!< in: lock */
|
|
{
|
|
ulint ret;
|
|
|
|
switch (lock_get_type(lock)) {
|
|
case LOCK_REC:
|
|
ret = lock_rec_find_set_bit(lock);
|
|
ut_a(ret != ULINT_UNDEFINED);
|
|
break;
|
|
case LOCK_TABLE:
|
|
ret = ULINT_UNDEFINED;
|
|
break;
|
|
default:
|
|
ut_error;
|
|
}
|
|
|
|
return(ret);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Initializes the members of a table cache. */
|
|
static
|
|
void
|
|
table_cache_init(
|
|
/*=============*/
|
|
i_s_table_cache_t* table_cache, /*!< out: table cache */
|
|
size_t row_size) /*!< in: the size of a
|
|
row */
|
|
{
|
|
ulint i;
|
|
|
|
table_cache->rows_used = 0;
|
|
table_cache->rows_allocd = 0;
|
|
table_cache->row_size = row_size;
|
|
|
|
for (i = 0; i < MEM_CHUNKS_IN_TABLE_CACHE; i++) {
|
|
|
|
/* the memory is actually allocated in
|
|
table_cache_create_empty_row() */
|
|
table_cache->chunks[i].base = NULL;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Frees a table cache. */
|
|
static
|
|
void
|
|
table_cache_free(
|
|
/*=============*/
|
|
i_s_table_cache_t* table_cache) /*!< in/out: table cache */
|
|
{
|
|
ulint i;
|
|
|
|
for (i = 0; i < MEM_CHUNKS_IN_TABLE_CACHE; i++) {
|
|
|
|
/* the memory is actually allocated in
|
|
table_cache_create_empty_row() */
|
|
if (table_cache->chunks[i].base) {
|
|
mem_free(table_cache->chunks[i].base);
|
|
table_cache->chunks[i].base = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Returns an empty row from a table cache. The row is allocated if no more
|
|
empty rows are available. The number of used rows is incremented.
|
|
If the memory limit is hit then NULL is returned and nothing is
|
|
allocated.
|
|
@return empty row, or NULL if out of memory */
|
|
static
|
|
void*
|
|
table_cache_create_empty_row(
|
|
/*=========================*/
|
|
i_s_table_cache_t* table_cache, /*!< in/out: table cache */
|
|
trx_i_s_cache_t* cache) /*!< in/out: cache to record
|
|
how many bytes are
|
|
allocated */
|
|
{
|
|
ulint i;
|
|
void* row;
|
|
|
|
ut_a(table_cache->rows_used <= table_cache->rows_allocd);
|
|
|
|
if (table_cache->rows_used == table_cache->rows_allocd) {
|
|
|
|
/* rows_used == rows_allocd means that new chunk needs
|
|
to be allocated: either no more empty rows in the
|
|
last allocated chunk or nothing has been allocated yet
|
|
(rows_num == rows_allocd == 0); */
|
|
|
|
i_s_mem_chunk_t* chunk;
|
|
ulint req_bytes;
|
|
ulint got_bytes;
|
|
ulint req_rows;
|
|
ulint got_rows;
|
|
|
|
/* find the first not allocated chunk */
|
|
for (i = 0; i < MEM_CHUNKS_IN_TABLE_CACHE; i++) {
|
|
|
|
if (table_cache->chunks[i].base == NULL) {
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* i == MEM_CHUNKS_IN_TABLE_CACHE means that all chunks
|
|
have been allocated :-X */
|
|
ut_a(i < MEM_CHUNKS_IN_TABLE_CACHE);
|
|
|
|
/* allocate the chunk we just found */
|
|
|
|
if (i == 0) {
|
|
|
|
/* first chunk, nothing is allocated yet */
|
|
req_rows = TABLE_CACHE_INITIAL_ROWSNUM;
|
|
} else {
|
|
|
|
/* Memory is increased by the formula
|
|
new = old + old / 2; We are trying not to be
|
|
aggressive here (= using the common new = old * 2)
|
|
because the allocated memory will not be freed
|
|
until InnoDB exit (it is reused). So it is better
|
|
to once allocate the memory in more steps, but
|
|
have less unused/wasted memory than to use less
|
|
steps in allocation (which is done once in a
|
|
lifetime) but end up with lots of unused/wasted
|
|
memory. */
|
|
req_rows = table_cache->rows_allocd / 2;
|
|
}
|
|
req_bytes = req_rows * table_cache->row_size;
|
|
|
|
if (req_bytes > MAX_ALLOWED_FOR_ALLOC(cache)) {
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
chunk = &table_cache->chunks[i];
|
|
|
|
chunk->base = mem_alloc2(req_bytes, &got_bytes);
|
|
|
|
got_rows = got_bytes / table_cache->row_size;
|
|
|
|
cache->mem_allocd += got_bytes;
|
|
|
|
#if 0
|
|
printf("allocating chunk %d req bytes=%lu, got bytes=%lu, "
|
|
"row size=%lu, "
|
|
"req rows=%lu, got rows=%lu\n",
|
|
i, req_bytes, got_bytes,
|
|
table_cache->row_size,
|
|
req_rows, got_rows);
|
|
#endif
|
|
|
|
chunk->rows_allocd = got_rows;
|
|
|
|
table_cache->rows_allocd += got_rows;
|
|
|
|
/* adjust the offset of the next chunk */
|
|
if (i < MEM_CHUNKS_IN_TABLE_CACHE - 1) {
|
|
|
|
table_cache->chunks[i + 1].offset
|
|
= chunk->offset + chunk->rows_allocd;
|
|
}
|
|
|
|
/* return the first empty row in the newly allocated
|
|
chunk */
|
|
row = chunk->base;
|
|
} else {
|
|
|
|
char* chunk_start;
|
|
ulint offset;
|
|
|
|
/* there is an empty row, no need to allocate new
|
|
chunks */
|
|
|
|
/* find the first chunk that contains allocated but
|
|
empty/unused rows */
|
|
for (i = 0; i < MEM_CHUNKS_IN_TABLE_CACHE; i++) {
|
|
|
|
if (table_cache->chunks[i].offset
|
|
+ table_cache->chunks[i].rows_allocd
|
|
> table_cache->rows_used) {
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* i == MEM_CHUNKS_IN_TABLE_CACHE means that all chunks
|
|
are full, but
|
|
table_cache->rows_used != table_cache->rows_allocd means
|
|
exactly the opposite - there are allocated but
|
|
empty/unused rows :-X */
|
|
ut_a(i < MEM_CHUNKS_IN_TABLE_CACHE);
|
|
|
|
chunk_start = (char*) table_cache->chunks[i].base;
|
|
offset = table_cache->rows_used
|
|
- table_cache->chunks[i].offset;
|
|
|
|
row = chunk_start + offset * table_cache->row_size;
|
|
}
|
|
|
|
table_cache->rows_used++;
|
|
|
|
return(row);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Fills i_s_trx_row_t object.
|
|
If memory can not be allocated then FALSE is returned.
|
|
@return FALSE if allocation fails */
|
|
static
|
|
ibool
|
|
fill_trx_row(
|
|
/*=========*/
|
|
i_s_trx_row_t* row, /*!< out: result object
|
|
that's filled */
|
|
const trx_t* trx, /*!< in: transaction to
|
|
get data from */
|
|
const i_s_locks_row_t* requested_lock_row,/*!< in: pointer to the
|
|
corresponding row in
|
|
innodb_locks if trx is
|
|
waiting or NULL if trx
|
|
is not waiting */
|
|
trx_i_s_cache_t* cache) /*!< in/out: cache into
|
|
which to copy volatile
|
|
strings */
|
|
{
|
|
row->trx_id = trx_get_id(trx);
|
|
row->trx_started = (ib_time_t) trx->start_time;
|
|
row->trx_state = trx_get_que_state_str(trx);
|
|
|
|
if (trx->wait_lock != NULL) {
|
|
|
|
ut_a(requested_lock_row != NULL);
|
|
|
|
row->requested_lock_row = requested_lock_row;
|
|
row->trx_wait_started = (ib_time_t) trx->wait_started;
|
|
} else {
|
|
|
|
ut_a(requested_lock_row == NULL);
|
|
|
|
row->requested_lock_row = NULL;
|
|
row->trx_wait_started = 0;
|
|
}
|
|
|
|
row->trx_weight = (ullint) ut_conv_dulint_to_longlong(TRX_WEIGHT(trx));
|
|
|
|
if (trx->mysql_thd != NULL) {
|
|
row->trx_mysql_thread_id
|
|
= thd_get_thread_id(trx->mysql_thd);
|
|
} else {
|
|
/* For internal transactions e.g., purge and transactions
|
|
being recovered at startup there is no associated MySQL
|
|
thread data structure. */
|
|
row->trx_mysql_thread_id = 0;
|
|
}
|
|
|
|
if (trx->mysql_query_str != NULL && *trx->mysql_query_str != NULL) {
|
|
|
|
if (strlen(*trx->mysql_query_str)
|
|
> TRX_I_S_TRX_QUERY_MAX_LEN) {
|
|
|
|
char query[TRX_I_S_TRX_QUERY_MAX_LEN + 1];
|
|
|
|
memcpy(query, *trx->mysql_query_str,
|
|
TRX_I_S_TRX_QUERY_MAX_LEN);
|
|
query[TRX_I_S_TRX_QUERY_MAX_LEN] = '\0';
|
|
|
|
row->trx_query = ha_storage_put_memlim(
|
|
cache->storage, query,
|
|
TRX_I_S_TRX_QUERY_MAX_LEN + 1,
|
|
MAX_ALLOWED_FOR_STORAGE(cache));
|
|
} else {
|
|
|
|
row->trx_query = ha_storage_put_str_memlim(
|
|
cache->storage, *trx->mysql_query_str,
|
|
MAX_ALLOWED_FOR_STORAGE(cache));
|
|
}
|
|
|
|
if (row->trx_query == NULL) {
|
|
|
|
return(FALSE);
|
|
}
|
|
} else {
|
|
|
|
row->trx_query = NULL;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Format the nth field of "rec" and put it in "buf". The result is always
|
|
NUL-terminated. Returns the number of bytes that were written to "buf"
|
|
(including the terminating NUL).
|
|
@return end of the result */
|
|
static
|
|
ulint
|
|
put_nth_field(
|
|
/*==========*/
|
|
char* buf, /*!< out: buffer */
|
|
ulint buf_size,/*!< in: buffer size in bytes */
|
|
ulint n, /*!< in: number of field */
|
|
const dict_index_t* index, /*!< in: index */
|
|
const rec_t* rec, /*!< in: record */
|
|
const ulint* offsets)/*!< in: record offsets, returned
|
|
by rec_get_offsets() */
|
|
{
|
|
const byte* data;
|
|
ulint data_len;
|
|
dict_field_t* dict_field;
|
|
ulint ret;
|
|
|
|
ut_ad(rec_offs_validate(rec, NULL, offsets));
|
|
|
|
if (buf_size == 0) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
if (n > 0) {
|
|
/* we must append ", " before the actual data */
|
|
|
|
if (buf_size < 3) {
|
|
|
|
buf[0] = '\0';
|
|
return(1);
|
|
}
|
|
|
|
memcpy(buf, ", ", 3);
|
|
|
|
buf += 2;
|
|
buf_size -= 2;
|
|
ret += 2;
|
|
}
|
|
|
|
/* now buf_size >= 1 */
|
|
|
|
data = rec_get_nth_field(rec, offsets, n, &data_len);
|
|
|
|
dict_field = dict_index_get_nth_field(index, n);
|
|
|
|
ret += row_raw_format((const char*) data, data_len,
|
|
dict_field, buf, buf_size);
|
|
|
|
return(ret);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Fills the "lock_data" member of i_s_locks_row_t object.
|
|
If memory can not be allocated then FALSE is returned.
|
|
@return FALSE if allocation fails */
|
|
static
|
|
ibool
|
|
fill_lock_data(
|
|
/*===========*/
|
|
const char** lock_data,/*!< out: "lock_data" to fill */
|
|
const lock_t* lock, /*!< in: lock used to find the data */
|
|
ulint heap_no,/*!< in: rec num used to find the data */
|
|
trx_i_s_cache_t* cache) /*!< in/out: cache where to store
|
|
volatile data */
|
|
{
|
|
mtr_t mtr;
|
|
|
|
const buf_block_t* block;
|
|
const page_t* page;
|
|
const rec_t* rec;
|
|
|
|
ut_a(lock_get_type(lock) == LOCK_REC);
|
|
|
|
mtr_start(&mtr);
|
|
|
|
block = buf_page_try_get(lock_rec_get_space_id(lock),
|
|
lock_rec_get_page_no(lock),
|
|
&mtr);
|
|
|
|
if (block == NULL) {
|
|
|
|
*lock_data = NULL;
|
|
|
|
mtr_commit(&mtr);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
page = (const page_t*) buf_block_get_frame(block);
|
|
|
|
rec = page_find_rec_with_heap_no(page, heap_no);
|
|
|
|
if (page_rec_is_infimum(rec)) {
|
|
|
|
*lock_data = ha_storage_put_str_memlim(
|
|
cache->storage, "infimum pseudo-record",
|
|
MAX_ALLOWED_FOR_STORAGE(cache));
|
|
} else if (page_rec_is_supremum(rec)) {
|
|
|
|
*lock_data = ha_storage_put_str_memlim(
|
|
cache->storage, "supremum pseudo-record",
|
|
MAX_ALLOWED_FOR_STORAGE(cache));
|
|
} else {
|
|
|
|
const dict_index_t* index;
|
|
ulint n_fields;
|
|
mem_heap_t* heap;
|
|
ulint offsets_onstack[REC_OFFS_NORMAL_SIZE];
|
|
ulint* offsets;
|
|
char buf[TRX_I_S_LOCK_DATA_MAX_LEN];
|
|
ulint buf_used;
|
|
ulint i;
|
|
|
|
rec_offs_init(offsets_onstack);
|
|
offsets = offsets_onstack;
|
|
|
|
index = lock_rec_get_index(lock);
|
|
|
|
n_fields = dict_index_get_n_unique(index);
|
|
|
|
ut_a(n_fields > 0);
|
|
|
|
heap = NULL;
|
|
offsets = rec_get_offsets(rec, index, offsets, n_fields,
|
|
&heap);
|
|
|
|
/* format and store the data */
|
|
|
|
buf_used = 0;
|
|
for (i = 0; i < n_fields; i++) {
|
|
|
|
buf_used += put_nth_field(
|
|
buf + buf_used, sizeof(buf) - buf_used,
|
|
i, index, rec, offsets) - 1;
|
|
}
|
|
|
|
*lock_data = (const char*) ha_storage_put_memlim(
|
|
cache->storage, buf, buf_used + 1,
|
|
MAX_ALLOWED_FOR_STORAGE(cache));
|
|
|
|
if (UNIV_UNLIKELY(heap != NULL)) {
|
|
|
|
/* this means that rec_get_offsets() has created a new
|
|
heap and has stored offsets in it; check that this is
|
|
really the case and free the heap */
|
|
ut_a(offsets != offsets_onstack);
|
|
mem_heap_free(heap);
|
|
}
|
|
}
|
|
|
|
mtr_commit(&mtr);
|
|
|
|
if (*lock_data == NULL) {
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Fills i_s_locks_row_t object. Returns its first argument.
|
|
If memory can not be allocated then FALSE is returned.
|
|
@return FALSE if allocation fails */
|
|
static
|
|
ibool
|
|
fill_locks_row(
|
|
/*===========*/
|
|
i_s_locks_row_t* row, /*!< out: result object that's filled */
|
|
const lock_t* lock, /*!< in: lock to get data from */
|
|
ulint heap_no,/*!< in: lock's record number
|
|
or ULINT_UNDEFINED if the lock
|
|
is a table lock */
|
|
trx_i_s_cache_t* cache) /*!< in/out: cache into which to copy
|
|
volatile strings */
|
|
{
|
|
row->lock_trx_id = lock_get_trx_id(lock);
|
|
row->lock_mode = lock_get_mode_str(lock);
|
|
row->lock_type = lock_get_type_str(lock);
|
|
|
|
row->lock_table = ha_storage_put_str_memlim(
|
|
cache->storage, lock_get_table_name(lock),
|
|
MAX_ALLOWED_FOR_STORAGE(cache));
|
|
|
|
/* memory could not be allocated */
|
|
if (row->lock_table == NULL) {
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
switch (lock_get_type(lock)) {
|
|
case LOCK_REC:
|
|
row->lock_index = ha_storage_put_str_memlim(
|
|
cache->storage, lock_rec_get_index_name(lock),
|
|
MAX_ALLOWED_FOR_STORAGE(cache));
|
|
|
|
/* memory could not be allocated */
|
|
if (row->lock_index == NULL) {
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
row->lock_space = lock_rec_get_space_id(lock);
|
|
row->lock_page = lock_rec_get_page_no(lock);
|
|
row->lock_rec = heap_no;
|
|
|
|
if (!fill_lock_data(&row->lock_data, lock, heap_no, cache)) {
|
|
|
|
/* memory could not be allocated */
|
|
return(FALSE);
|
|
}
|
|
|
|
break;
|
|
case LOCK_TABLE:
|
|
row->lock_index = NULL;
|
|
|
|
row->lock_space = ULINT_UNDEFINED;
|
|
row->lock_page = ULINT_UNDEFINED;
|
|
row->lock_rec = ULINT_UNDEFINED;
|
|
|
|
row->lock_data = NULL;
|
|
|
|
break;
|
|
default:
|
|
ut_error;
|
|
}
|
|
|
|
row->lock_table_id = lock_get_table_id(lock);
|
|
|
|
row->hash_chain.value = row;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Fills i_s_lock_waits_row_t object. Returns its first argument.
|
|
@return result object that's filled */
|
|
static
|
|
i_s_lock_waits_row_t*
|
|
fill_lock_waits_row(
|
|
/*================*/
|
|
i_s_lock_waits_row_t* row, /*!< out: result object
|
|
that's filled */
|
|
const i_s_locks_row_t* requested_lock_row,/*!< in: pointer to the
|
|
relevant requested lock
|
|
row in innodb_locks */
|
|
const i_s_locks_row_t* blocking_lock_row)/*!< in: pointer to the
|
|
relevant blocking lock
|
|
row in innodb_locks */
|
|
{
|
|
row->requested_lock_row = requested_lock_row;
|
|
row->blocking_lock_row = blocking_lock_row;
|
|
|
|
return(row);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Calculates a hash fold for a lock. For a record lock the fold is
|
|
calculated from 4 elements, which uniquely identify a lock at a given
|
|
point in time: transaction id, space id, page number, record number.
|
|
For a table lock the fold is table's id.
|
|
@return fold */
|
|
static
|
|
ulint
|
|
fold_lock(
|
|
/*======*/
|
|
const lock_t* lock, /*!< in: lock object to fold */
|
|
ulint heap_no)/*!< in: lock's record number
|
|
or ULINT_UNDEFINED if the lock
|
|
is a table lock */
|
|
{
|
|
#ifdef TEST_LOCK_FOLD_ALWAYS_DIFFERENT
|
|
static ulint fold = 0;
|
|
|
|
return(fold++);
|
|
#else
|
|
ulint ret;
|
|
|
|
switch (lock_get_type(lock)) {
|
|
case LOCK_REC:
|
|
ut_a(heap_no != ULINT_UNDEFINED);
|
|
|
|
ret = ut_fold_ulint_pair((ulint) lock_get_trx_id(lock),
|
|
lock_rec_get_space_id(lock));
|
|
|
|
ret = ut_fold_ulint_pair(ret,
|
|
lock_rec_get_page_no(lock));
|
|
|
|
ret = ut_fold_ulint_pair(ret, heap_no);
|
|
|
|
break;
|
|
case LOCK_TABLE:
|
|
/* this check is actually not necessary for continuing
|
|
correct operation, but something must have gone wrong if
|
|
it fails. */
|
|
ut_a(heap_no == ULINT_UNDEFINED);
|
|
|
|
ret = (ulint) lock_get_table_id(lock);
|
|
|
|
break;
|
|
default:
|
|
ut_error;
|
|
}
|
|
|
|
return(ret);
|
|
#endif
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Checks whether i_s_locks_row_t object represents a lock_t object.
|
|
@return TRUE if they match */
|
|
static
|
|
ibool
|
|
locks_row_eq_lock(
|
|
/*==============*/
|
|
const i_s_locks_row_t* row, /*!< in: innodb_locks row */
|
|
const lock_t* lock, /*!< in: lock object */
|
|
ulint heap_no)/*!< in: lock's record number
|
|
or ULINT_UNDEFINED if the lock
|
|
is a table lock */
|
|
{
|
|
#ifdef TEST_NO_LOCKS_ROW_IS_EVER_EQUAL_TO_LOCK_T
|
|
return(0);
|
|
#else
|
|
switch (lock_get_type(lock)) {
|
|
case LOCK_REC:
|
|
ut_a(heap_no != ULINT_UNDEFINED);
|
|
|
|
return(row->lock_trx_id == lock_get_trx_id(lock)
|
|
&& row->lock_space == lock_rec_get_space_id(lock)
|
|
&& row->lock_page == lock_rec_get_page_no(lock)
|
|
&& row->lock_rec == heap_no);
|
|
|
|
case LOCK_TABLE:
|
|
/* this check is actually not necessary for continuing
|
|
correct operation, but something must have gone wrong if
|
|
it fails. */
|
|
ut_a(heap_no == ULINT_UNDEFINED);
|
|
|
|
return(row->lock_trx_id == lock_get_trx_id(lock)
|
|
&& row->lock_table_id == lock_get_table_id(lock));
|
|
|
|
default:
|
|
ut_error;
|
|
return(FALSE);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Searches for a row in the innodb_locks cache that has a specified id.
|
|
This happens in O(1) time since a hash table is used. Returns pointer to
|
|
the row or NULL if none is found.
|
|
@return row or NULL */
|
|
static
|
|
i_s_locks_row_t*
|
|
search_innodb_locks(
|
|
/*================*/
|
|
trx_i_s_cache_t* cache, /*!< in: cache */
|
|
const lock_t* lock, /*!< in: lock to search for */
|
|
ulint heap_no)/*!< in: lock's record number
|
|
or ULINT_UNDEFINED if the lock
|
|
is a table lock */
|
|
{
|
|
i_s_hash_chain_t* hash_chain;
|
|
|
|
HASH_SEARCH(
|
|
/* hash_chain->"next" */
|
|
next,
|
|
/* the hash table */
|
|
cache->locks_hash,
|
|
/* fold */
|
|
fold_lock(lock, heap_no),
|
|
/* the type of the next variable */
|
|
i_s_hash_chain_t*,
|
|
/* auxiliary variable */
|
|
hash_chain,
|
|
/* assertion on every traversed item */
|
|
,
|
|
/* this determines if we have found the lock */
|
|
locks_row_eq_lock(hash_chain->value, lock, heap_no));
|
|
|
|
if (hash_chain == NULL) {
|
|
|
|
return(NULL);
|
|
}
|
|
/* else */
|
|
|
|
return(hash_chain->value);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Adds new element to the locks cache, enlarging it if necessary.
|
|
Returns a pointer to the added row. If the row is already present then
|
|
no row is added and a pointer to the existing row is returned.
|
|
If row can not be allocated then NULL is returned.
|
|
@return row */
|
|
static
|
|
i_s_locks_row_t*
|
|
add_lock_to_cache(
|
|
/*==============*/
|
|
trx_i_s_cache_t* cache, /*!< in/out: cache */
|
|
const lock_t* lock, /*!< in: the element to add */
|
|
ulint heap_no)/*!< in: lock's record number
|
|
or ULINT_UNDEFINED if the lock
|
|
is a table lock */
|
|
{
|
|
i_s_locks_row_t* dst_row;
|
|
|
|
#ifdef TEST_ADD_EACH_LOCKS_ROW_MANY_TIMES
|
|
ulint i;
|
|
for (i = 0; i < 10000; i++) {
|
|
#endif
|
|
#ifndef TEST_DO_NOT_CHECK_FOR_DUPLICATE_ROWS
|
|
/* quit if this lock is already present */
|
|
dst_row = search_innodb_locks(cache, lock, heap_no);
|
|
if (dst_row != NULL) {
|
|
|
|
return(dst_row);
|
|
}
|
|
#endif
|
|
|
|
dst_row = (i_s_locks_row_t*)
|
|
table_cache_create_empty_row(&cache->innodb_locks, cache);
|
|
|
|
/* memory could not be allocated */
|
|
if (dst_row == NULL) {
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
if (!fill_locks_row(dst_row, lock, heap_no, cache)) {
|
|
|
|
/* memory could not be allocated */
|
|
cache->innodb_locks.rows_used--;
|
|
return(NULL);
|
|
}
|
|
|
|
#ifndef TEST_DO_NOT_INSERT_INTO_THE_HASH_TABLE
|
|
HASH_INSERT(
|
|
/* the type used in the hash chain */
|
|
i_s_hash_chain_t,
|
|
/* hash_chain->"next" */
|
|
next,
|
|
/* the hash table */
|
|
cache->locks_hash,
|
|
/* fold */
|
|
fold_lock(lock, heap_no),
|
|
/* add this data to the hash */
|
|
&dst_row->hash_chain);
|
|
#endif
|
|
#ifdef TEST_ADD_EACH_LOCKS_ROW_MANY_TIMES
|
|
} /* for()-loop */
|
|
#endif
|
|
|
|
return(dst_row);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Adds new pair of locks to the lock waits cache.
|
|
If memory can not be allocated then FALSE is returned.
|
|
@return FALSE if allocation fails */
|
|
static
|
|
ibool
|
|
add_lock_wait_to_cache(
|
|
/*===================*/
|
|
trx_i_s_cache_t* cache, /*!< in/out: cache */
|
|
const i_s_locks_row_t* requested_lock_row,/*!< in: pointer to the
|
|
relevant requested lock
|
|
row in innodb_locks */
|
|
const i_s_locks_row_t* blocking_lock_row)/*!< in: pointer to the
|
|
relevant blocking lock
|
|
row in innodb_locks */
|
|
{
|
|
i_s_lock_waits_row_t* dst_row;
|
|
|
|
dst_row = (i_s_lock_waits_row_t*)
|
|
table_cache_create_empty_row(&cache->innodb_lock_waits,
|
|
cache);
|
|
|
|
/* memory could not be allocated */
|
|
if (dst_row == NULL) {
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
fill_lock_waits_row(dst_row, requested_lock_row, blocking_lock_row);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Adds transaction's relevant (important) locks to cache.
|
|
If the transaction is waiting, then the wait lock is added to
|
|
innodb_locks and a pointer to the added row is returned in
|
|
requested_lock_row, otherwise requested_lock_row is set to NULL.
|
|
If rows can not be allocated then FALSE is returned and the value of
|
|
requested_lock_row is undefined.
|
|
@return FALSE if allocation fails */
|
|
static
|
|
ibool
|
|
add_trx_relevant_locks_to_cache(
|
|
/*============================*/
|
|
trx_i_s_cache_t* cache, /*!< in/out: cache */
|
|
const trx_t* trx, /*!< in: transaction */
|
|
i_s_locks_row_t** requested_lock_row)/*!< out: pointer to the
|
|
requested lock row, or NULL or
|
|
undefined */
|
|
{
|
|
ut_ad(mutex_own(&kernel_mutex));
|
|
|
|
/* If transaction is waiting we add the wait lock and all locks
|
|
from another transactions that are blocking the wait lock. */
|
|
if (trx->que_state == TRX_QUE_LOCK_WAIT) {
|
|
|
|
const lock_t* curr_lock;
|
|
ulint wait_lock_heap_no;
|
|
i_s_locks_row_t* blocking_lock_row;
|
|
lock_queue_iterator_t iter;
|
|
|
|
ut_a(trx->wait_lock != NULL);
|
|
|
|
wait_lock_heap_no
|
|
= wait_lock_get_heap_no(trx->wait_lock);
|
|
|
|
/* add the requested lock */
|
|
*requested_lock_row
|
|
= add_lock_to_cache(cache, trx->wait_lock,
|
|
wait_lock_heap_no);
|
|
|
|
/* memory could not be allocated */
|
|
if (*requested_lock_row == NULL) {
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
/* then iterate over the locks before the wait lock and
|
|
add the ones that are blocking it */
|
|
|
|
lock_queue_iterator_reset(&iter, trx->wait_lock,
|
|
ULINT_UNDEFINED);
|
|
|
|
curr_lock = lock_queue_iterator_get_prev(&iter);
|
|
while (curr_lock != NULL) {
|
|
|
|
if (lock_has_to_wait(trx->wait_lock,
|
|
curr_lock)) {
|
|
|
|
/* add the lock that is
|
|
blocking trx->wait_lock */
|
|
blocking_lock_row
|
|
= add_lock_to_cache(
|
|
cache, curr_lock,
|
|
/* heap_no is the same
|
|
for the wait and waited
|
|
locks */
|
|
wait_lock_heap_no);
|
|
|
|
/* memory could not be allocated */
|
|
if (blocking_lock_row == NULL) {
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
/* add the relation between both locks
|
|
to innodb_lock_waits */
|
|
if (!add_lock_wait_to_cache(
|
|
cache, *requested_lock_row,
|
|
blocking_lock_row)) {
|
|
|
|
/* memory could not be allocated */
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
curr_lock = lock_queue_iterator_get_prev(&iter);
|
|
}
|
|
} else {
|
|
|
|
*requested_lock_row = NULL;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/** The minimum time that a cache must not be updated after it has been
|
|
read for the last time; measured in microseconds. We use this technique
|
|
to ensure that SELECTs which join several INFORMATION SCHEMA tables read
|
|
the same version of the cache. */
|
|
#define CACHE_MIN_IDLE_TIME_US 100000 /* 0.1 sec */
|
|
|
|
/*******************************************************************//**
|
|
Checks if the cache can safely be updated.
|
|
@return TRUE if can be updated */
|
|
static
|
|
ibool
|
|
can_cache_be_updated(
|
|
/*=================*/
|
|
trx_i_s_cache_t* cache) /*!< in: cache */
|
|
{
|
|
ullint now;
|
|
|
|
/* Here we read cache->last_read without acquiring its mutex
|
|
because last_read is only updated when a shared rw lock on the
|
|
whole cache is being held (see trx_i_s_cache_end_read()) and
|
|
we are currently holding an exclusive rw lock on the cache.
|
|
So it is not possible for last_read to be updated while we are
|
|
reading it. */
|
|
|
|
#ifdef UNIV_SYNC_DEBUG
|
|
ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_EX));
|
|
#endif
|
|
|
|
now = ut_time_us(NULL);
|
|
if (now - cache->last_read > CACHE_MIN_IDLE_TIME_US) {
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Declare a cache empty, preparing it to be filled up. Not all resources
|
|
are freed because they can be reused. */
|
|
static
|
|
void
|
|
trx_i_s_cache_clear(
|
|
/*================*/
|
|
trx_i_s_cache_t* cache) /*!< out: cache to clear */
|
|
{
|
|
cache->innodb_trx.rows_used = 0;
|
|
cache->innodb_locks.rows_used = 0;
|
|
cache->innodb_lock_waits.rows_used = 0;
|
|
|
|
hash_table_clear(cache->locks_hash);
|
|
|
|
ha_storage_empty(&cache->storage);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Fetches the data needed to fill the 3 INFORMATION SCHEMA tables into the
|
|
table cache buffer. Cache must be locked for write. */
|
|
static
|
|
void
|
|
fetch_data_into_cache(
|
|
/*==================*/
|
|
trx_i_s_cache_t* cache) /*!< in/out: cache */
|
|
{
|
|
trx_t* trx;
|
|
i_s_trx_row_t* trx_row;
|
|
i_s_locks_row_t* requested_lock_row;
|
|
|
|
ut_ad(mutex_own(&kernel_mutex));
|
|
|
|
trx_i_s_cache_clear(cache);
|
|
|
|
/* We iterate over the list of all transactions and add each one
|
|
to innodb_trx's cache. We also add all locks that are relevant
|
|
to each transaction into innodb_locks' and innodb_lock_waits'
|
|
caches. */
|
|
|
|
for (trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
|
|
trx != NULL;
|
|
trx = UT_LIST_GET_NEXT(trx_list, trx)) {
|
|
|
|
if (!add_trx_relevant_locks_to_cache(cache, trx,
|
|
&requested_lock_row)) {
|
|
|
|
cache->is_truncated = TRUE;
|
|
return;
|
|
}
|
|
|
|
trx_row = (i_s_trx_row_t*)
|
|
table_cache_create_empty_row(&cache->innodb_trx,
|
|
cache);
|
|
|
|
/* memory could not be allocated */
|
|
if (trx_row == NULL) {
|
|
|
|
cache->is_truncated = TRUE;
|
|
return;
|
|
}
|
|
|
|
if (!fill_trx_row(trx_row, trx, requested_lock_row, cache)) {
|
|
|
|
/* memory could not be allocated */
|
|
cache->innodb_trx.rows_used--;
|
|
cache->is_truncated = TRUE;
|
|
return;
|
|
}
|
|
}
|
|
|
|
cache->is_truncated = FALSE;
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Update the transactions cache if it has not been read for some time.
|
|
Called from handler/i_s.cc.
|
|
@return 0 - fetched, 1 - not */
|
|
UNIV_INTERN
|
|
int
|
|
trx_i_s_possibly_fetch_data_into_cache(
|
|
/*===================================*/
|
|
trx_i_s_cache_t* cache) /*!< in/out: cache */
|
|
{
|
|
if (!can_cache_be_updated(cache)) {
|
|
|
|
return(1);
|
|
}
|
|
|
|
/* We need to read trx_sys and record/table lock queues */
|
|
mutex_enter(&kernel_mutex);
|
|
|
|
fetch_data_into_cache(cache);
|
|
|
|
mutex_exit(&kernel_mutex);
|
|
|
|
return(0);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Returns TRUE if the data in the cache is truncated due to the memory
|
|
limit posed by TRX_I_S_MEM_LIMIT.
|
|
@return TRUE if truncated */
|
|
UNIV_INTERN
|
|
ibool
|
|
trx_i_s_cache_is_truncated(
|
|
/*=======================*/
|
|
trx_i_s_cache_t* cache) /*!< in: cache */
|
|
{
|
|
return(cache->is_truncated);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Initialize INFORMATION SCHEMA trx related cache. */
|
|
UNIV_INTERN
|
|
void
|
|
trx_i_s_cache_init(
|
|
/*===============*/
|
|
trx_i_s_cache_t* cache) /*!< out: cache to init */
|
|
{
|
|
/* The latching is done in the following order:
|
|
acquire trx_i_s_cache_t::rw_lock, X
|
|
acquire kernel_mutex
|
|
release kernel_mutex
|
|
release trx_i_s_cache_t::rw_lock
|
|
acquire trx_i_s_cache_t::rw_lock, S
|
|
acquire trx_i_s_cache_t::last_read_mutex
|
|
release trx_i_s_cache_t::last_read_mutex
|
|
release trx_i_s_cache_t::rw_lock */
|
|
|
|
rw_lock_create(&cache->rw_lock, SYNC_TRX_I_S_RWLOCK);
|
|
|
|
cache->last_read = 0;
|
|
|
|
mutex_create(&cache->last_read_mutex, SYNC_TRX_I_S_LAST_READ);
|
|
|
|
table_cache_init(&cache->innodb_trx, sizeof(i_s_trx_row_t));
|
|
table_cache_init(&cache->innodb_locks, sizeof(i_s_locks_row_t));
|
|
table_cache_init(&cache->innodb_lock_waits,
|
|
sizeof(i_s_lock_waits_row_t));
|
|
|
|
cache->locks_hash = hash_create(LOCKS_HASH_CELLS_NUM);
|
|
|
|
cache->storage = ha_storage_create(CACHE_STORAGE_INITIAL_SIZE,
|
|
CACHE_STORAGE_HASH_CELLS);
|
|
|
|
cache->mem_allocd = 0;
|
|
|
|
cache->is_truncated = FALSE;
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Free the INFORMATION SCHEMA trx related cache. */
|
|
UNIV_INTERN
|
|
void
|
|
trx_i_s_cache_free(
|
|
/*===============*/
|
|
trx_i_s_cache_t* cache) /*!< in, own: cache to free */
|
|
{
|
|
hash_table_free(cache->locks_hash);
|
|
ha_storage_free(cache->storage);
|
|
table_cache_free(&cache->innodb_trx);
|
|
table_cache_free(&cache->innodb_locks);
|
|
table_cache_free(&cache->innodb_lock_waits);
|
|
memset(cache, 0, sizeof *cache);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Issue a shared/read lock on the tables cache. */
|
|
UNIV_INTERN
|
|
void
|
|
trx_i_s_cache_start_read(
|
|
/*=====================*/
|
|
trx_i_s_cache_t* cache) /*!< in: cache */
|
|
{
|
|
rw_lock_s_lock(&cache->rw_lock);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Release a shared/read lock on the tables cache. */
|
|
UNIV_INTERN
|
|
void
|
|
trx_i_s_cache_end_read(
|
|
/*===================*/
|
|
trx_i_s_cache_t* cache) /*!< in: cache */
|
|
{
|
|
ullint now;
|
|
|
|
#ifdef UNIV_SYNC_DEBUG
|
|
ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_SHARED));
|
|
#endif
|
|
|
|
/* update cache last read time */
|
|
now = ut_time_us(NULL);
|
|
mutex_enter(&cache->last_read_mutex);
|
|
cache->last_read = now;
|
|
mutex_exit(&cache->last_read_mutex);
|
|
|
|
rw_lock_s_unlock(&cache->rw_lock);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Issue an exclusive/write lock on the tables cache. */
|
|
UNIV_INTERN
|
|
void
|
|
trx_i_s_cache_start_write(
|
|
/*======================*/
|
|
trx_i_s_cache_t* cache) /*!< in: cache */
|
|
{
|
|
rw_lock_x_lock(&cache->rw_lock);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Release an exclusive/write lock on the tables cache. */
|
|
UNIV_INTERN
|
|
void
|
|
trx_i_s_cache_end_write(
|
|
/*====================*/
|
|
trx_i_s_cache_t* cache) /*!< in: cache */
|
|
{
|
|
#ifdef UNIV_SYNC_DEBUG
|
|
ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_EX));
|
|
#endif
|
|
|
|
rw_lock_x_unlock(&cache->rw_lock);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Selects a INFORMATION SCHEMA table cache from the whole cache.
|
|
@return table cache */
|
|
static
|
|
i_s_table_cache_t*
|
|
cache_select_table(
|
|
/*===============*/
|
|
trx_i_s_cache_t* cache, /*!< in: whole cache */
|
|
enum i_s_table table) /*!< in: which table */
|
|
{
|
|
i_s_table_cache_t* table_cache;
|
|
|
|
#ifdef UNIV_SYNC_DEBUG
|
|
ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_SHARED)
|
|
|| rw_lock_own(&cache->rw_lock, RW_LOCK_EX));
|
|
#endif
|
|
|
|
switch (table) {
|
|
case I_S_INNODB_TRX:
|
|
table_cache = &cache->innodb_trx;
|
|
break;
|
|
case I_S_INNODB_LOCKS:
|
|
table_cache = &cache->innodb_locks;
|
|
break;
|
|
case I_S_INNODB_LOCK_WAITS:
|
|
table_cache = &cache->innodb_lock_waits;
|
|
break;
|
|
default:
|
|
ut_error;
|
|
}
|
|
|
|
return(table_cache);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Retrieves the number of used rows in the cache for a given
|
|
INFORMATION SCHEMA table.
|
|
@return number of rows */
|
|
UNIV_INTERN
|
|
ulint
|
|
trx_i_s_cache_get_rows_used(
|
|
/*========================*/
|
|
trx_i_s_cache_t* cache, /*!< in: cache */
|
|
enum i_s_table table) /*!< in: which table */
|
|
{
|
|
i_s_table_cache_t* table_cache;
|
|
|
|
table_cache = cache_select_table(cache, table);
|
|
|
|
return(table_cache->rows_used);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Retrieves the nth row (zero-based) in the cache for a given
|
|
INFORMATION SCHEMA table.
|
|
@return row */
|
|
UNIV_INTERN
|
|
void*
|
|
trx_i_s_cache_get_nth_row(
|
|
/*======================*/
|
|
trx_i_s_cache_t* cache, /*!< in: cache */
|
|
enum i_s_table table, /*!< in: which table */
|
|
ulint n) /*!< in: row number */
|
|
{
|
|
i_s_table_cache_t* table_cache;
|
|
ulint i;
|
|
void* row;
|
|
|
|
table_cache = cache_select_table(cache, table);
|
|
|
|
ut_a(n < table_cache->rows_used);
|
|
|
|
row = NULL;
|
|
|
|
for (i = 0; i < MEM_CHUNKS_IN_TABLE_CACHE; i++) {
|
|
|
|
if (table_cache->chunks[i].offset
|
|
+ table_cache->chunks[i].rows_allocd > n) {
|
|
|
|
row = (char*) table_cache->chunks[i].base
|
|
+ (n - table_cache->chunks[i].offset)
|
|
* table_cache->row_size;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ut_a(row != NULL);
|
|
|
|
return(row);
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Crafts a lock id string from a i_s_locks_row_t object. Returns its
|
|
second argument. This function aborts if there is not enough space in
|
|
lock_id. Be sure to provide at least TRX_I_S_LOCK_ID_MAX_LEN + 1 if you
|
|
want to be 100% sure that it will not abort.
|
|
@return resulting lock id */
|
|
UNIV_INTERN
|
|
char*
|
|
trx_i_s_create_lock_id(
|
|
/*===================*/
|
|
const i_s_locks_row_t* row, /*!< in: innodb_locks row */
|
|
char* lock_id,/*!< out: resulting lock_id */
|
|
ulint lock_id_size)/*!< in: size of the lock id
|
|
buffer */
|
|
{
|
|
int res_len;
|
|
|
|
/* please adjust TRX_I_S_LOCK_ID_MAX_LEN if you change this */
|
|
|
|
if (row->lock_space != ULINT_UNDEFINED) {
|
|
/* record lock */
|
|
res_len = ut_snprintf(lock_id, lock_id_size,
|
|
TRX_ID_FMT ":%lu:%lu:%lu",
|
|
row->lock_trx_id, row->lock_space,
|
|
row->lock_page, row->lock_rec);
|
|
} else {
|
|
/* table lock */
|
|
res_len = ut_snprintf(lock_id, lock_id_size,
|
|
TRX_ID_FMT ":%llu",
|
|
row->lock_trx_id,
|
|
row->lock_table_id);
|
|
}
|
|
|
|
/* the typecast is safe because snprintf(3) never returns
|
|
negative result */
|
|
ut_a(res_len >= 0);
|
|
ut_a((ulint) res_len < lock_id_size);
|
|
|
|
return(lock_id);
|
|
}
|