summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorMichael Widenius <monty@askmonty.org>2011-03-09 15:47:59 +0200
committerMichael Widenius <monty@askmonty.org>2011-03-09 15:47:59 +0200
commit139a2b64bf8ec2e248656835e23a5c98ffc667a8 (patch)
tree7d77d6f1073f8090f275b30cb3f10254497da243 /storage
parentb3f7eac5301529c2d069ebe4d0558980412af3a2 (diff)
parentce675406ca8dbc1532a908803a1371de8432d466 (diff)
downloadmariadb-git-139a2b64bf8ec2e248656835e23a5c98ffc667a8.tar.gz
Merge with 5.2
Diffstat (limited to 'storage')
-rw-r--r--storage/archive/ha_archive.cc5
-rw-r--r--storage/federatedx/Makefile.am8
-rw-r--r--storage/federatedx/ha_federatedx.cc7
-rw-r--r--storage/heap/hp_delete.c2
-rw-r--r--storage/innobase/btr/btr0btr.c2
-rw-r--r--storage/innobase/buf/buf0buf.c4
-rw-r--r--storage/innobase/dict/dict0dict.c2
-rw-r--r--storage/innobase/dict/dict0mem.c2
-rw-r--r--storage/innobase/fsp/fsp0fsp.c2
-rw-r--r--storage/innobase/include/buf0buf.ic4
-rw-r--r--storage/innobase/log/log0recv.c2
-rw-r--r--storage/innobase/row/row0mysql.c2
-rw-r--r--storage/innobase/srv/srv0start.c22
-rw-r--r--storage/innobase/sync/sync0rw.c2
-rw-r--r--storage/innobase/ut/ut0dbg.c2
-rw-r--r--storage/innodb_plugin/ChangeLog93
-rw-r--r--storage/innodb_plugin/btr/btr0btr.c2
-rw-r--r--storage/innodb_plugin/btr/btr0cur.c164
-rw-r--r--storage/innodb_plugin/buf/buf0buf.c4
-rw-r--r--storage/innodb_plugin/buf/buf0flu.c4
-rw-r--r--storage/innodb_plugin/buf/buf0lru.c16
-rw-r--r--storage/innodb_plugin/dict/dict0crea.c2
-rw-r--r--storage/innodb_plugin/dict/dict0dict.c170
-rw-r--r--storage/innodb_plugin/dict/dict0load.c3
-rw-r--r--storage/innodb_plugin/fil/fil0fil.c88
-rw-r--r--storage/innodb_plugin/fsp/fsp0fsp.c52
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.cc396
-rw-r--r--storage/innodb_plugin/handler/handler0alter.cc11
-rw-r--r--storage/innodb_plugin/handler/i_s.cc23
-rw-r--r--storage/innodb_plugin/include/btr0btr.h49
-rw-r--r--storage/innodb_plugin/include/btr0btr.ic38
-rw-r--r--storage/innodb_plugin/include/btr0cur.h44
-rw-r--r--storage/innodb_plugin/include/data0data.h11
-rw-r--r--storage/innodb_plugin/include/data0data.ic22
-rw-r--r--storage/innodb_plugin/include/dict0dict.h43
-rw-r--r--storage/innodb_plugin/include/fil0fil.h8
-rw-r--r--storage/innodb_plugin/include/row0ins.h5
-rw-r--r--storage/innodb_plugin/include/row0upd.h18
-rw-r--r--storage/innodb_plugin/include/trx0i_s.h2
-rw-r--r--storage/innodb_plugin/include/univ.i17
-rw-r--r--storage/innodb_plugin/include/ut0vec.h19
-rw-r--r--storage/innodb_plugin/include/ut0vec.ic29
-rw-r--r--storage/innodb_plugin/lock/lock0lock.c78
-rw-r--r--storage/innodb_plugin/log/log0recv.c2
-rw-r--r--storage/innodb_plugin/plug.in28
-rw-r--r--storage/innodb_plugin/row/row0ins.c9
-rw-r--r--storage/innodb_plugin/row/row0merge.c6
-rw-r--r--storage/innodb_plugin/row/row0mysql.c8
-rw-r--r--storage/innodb_plugin/row/row0purge.c2
-rw-r--r--storage/innodb_plugin/row/row0sel.c12
-rw-r--r--storage/innodb_plugin/row/row0umod.c13
-rw-r--r--storage/innodb_plugin/row/row0upd.c323
-rw-r--r--storage/innodb_plugin/srv/srv0start.c20
-rw-r--r--storage/innodb_plugin/sync/sync0rw.c9
-rw-r--r--storage/innodb_plugin/thr/thr0loc.c30
-rw-r--r--storage/innodb_plugin/trx/trx0i_s.c57
-rw-r--r--storage/innodb_plugin/ut/ut0dbg.c2
-rw-r--r--storage/maria/ha_maria.cc44
-rw-r--r--storage/maria/ma_bitmap.c215
-rw-r--r--storage/maria/ma_blockrec.c68
-rw-r--r--storage/maria/ma_blockrec.h13
-rw-r--r--storage/maria/ma_cache.c11
-rw-r--r--storage/maria/ma_check.c103
-rw-r--r--storage/maria/ma_checkpoint.c11
-rw-r--r--storage/maria/ma_close.c31
-rw-r--r--storage/maria/ma_create.c8
-rw-r--r--storage/maria/ma_delete.c20
-rw-r--r--storage/maria/ma_delete_all.c11
-rw-r--r--storage/maria/ma_delete_table.c25
-rw-r--r--storage/maria/ma_dynrec.c74
-rw-r--r--storage/maria/ma_extra.c56
-rw-r--r--storage/maria/ma_init.c2
-rw-r--r--storage/maria/ma_key.c3
-rw-r--r--storage/maria/ma_key_recover.c4
-rw-r--r--storage/maria/ma_keycache.c4
-rw-r--r--storage/maria/ma_locking.c97
-rw-r--r--storage/maria/ma_loghandler.c21
-rw-r--r--storage/maria/ma_open.c46
-rw-r--r--storage/maria/ma_packrec.c17
-rw-r--r--storage/maria/ma_page.c9
-rw-r--r--storage/maria/ma_pagecache.c190
-rw-r--r--storage/maria/ma_pagecache.h1
-rw-r--r--storage/maria/ma_pagecrc.c10
-rw-r--r--storage/maria/ma_panic.c6
-rw-r--r--storage/maria/ma_recovery.c22
-rw-r--r--storage/maria/ma_recovery_util.c4
-rw-r--r--storage/maria/ma_rkey.c3
-rw-r--r--storage/maria/ma_rt_test.c7
-rw-r--r--storage/maria/ma_search.c30
-rw-r--r--storage/maria/ma_static.c2
-rw-r--r--storage/maria/ma_statrec.c2
-rw-r--r--storage/maria/ma_test1.c7
-rw-r--r--storage/maria/ma_test2.c10
-rw-r--r--storage/maria/ma_update.c20
-rw-r--r--storage/maria/ma_write.c10
-rw-r--r--storage/maria/maria_chk.c90
-rw-r--r--storage/maria/maria_def.h26
-rw-r--r--storage/maria/maria_read_log.c6
-rwxr-xr-xstorage/maria/unittest/ma_test_all-t132
-rwxr-xr-xstorage/maria/unittest/ma_test_recovery.pl8
-rw-r--r--storage/myisam/ft_nlq_search.c1
-rw-r--r--storage/myisam/ha_myisam.cc14
-rw-r--r--storage/myisam/mi_check.c2
-rw-r--r--storage/myisam/mi_panic.c2
-rw-r--r--storage/myisam/myisampack.c2
-rw-r--r--storage/ndb/Makefile.am2
-rwxr-xr-xstorage/ndb/config/make-win-dsw.sh14
-rwxr-xr-xstorage/ndb/config/win-includes15
-rwxr-xr-xstorage/ndb/config/win-libraries15
-rwxr-xr-xstorage/ndb/config/win-name15
-rwxr-xr-xstorage/ndb/config/win-sources15
-rw-r--r--storage/ndb/docs/Makefile.am2
-rw-r--r--storage/ndb/docs/doxygen/Doxyfile.mgmapi17
-rw-r--r--storage/ndb/docs/doxygen/Doxyfile.ndb15
-rw-r--r--storage/ndb/docs/doxygen/Doxyfile.ndbapi17
-rw-r--r--storage/ndb/docs/doxygen/Doxyfile.odbc15
-rw-r--r--storage/ndb/docs/doxygen/header.mgmapi.tex44
-rw-r--r--storage/ndb/docs/doxygen/header.ndbapi.tex44
-rwxr-xr-xstorage/ndb/docs/doxygen/postdoxy.pl15
-rwxr-xr-xstorage/ndb/docs/doxygen/predoxy.pl15
-rw-r--r--storage/ndb/include/kernel/signaldata/FsOpenReq.hpp8
-rw-r--r--storage/ndb/include/ndbapi/NdbDictionary.hpp2
-rw-r--r--storage/ndb/include/util/NdbSqlUtil.hpp1
-rw-r--r--storage/ndb/src/cw/cpcc-win32/csharp/CPC_Form.cs15
-rw-r--r--storage/ndb/src/cw/cpcc-win32/csharp/Computer.cs15
-rw-r--r--storage/ndb/src/cw/cpcc-win32/csharp/ComputerAddDialog.cs15
-rw-r--r--storage/ndb/src/cw/cpcc-win32/csharp/ComputerRemoveDialog.cs15
-rw-r--r--storage/ndb/src/cw/cpcc-win32/csharp/Database.cs15
-rw-r--r--storage/ndb/src/cw/cpcc-win32/csharp/PanelWizard.cs15
-rw-r--r--storage/ndb/src/cw/cpcc-win32/csharp/Process.cs15
-rw-r--r--storage/ndb/src/cw/cpcc-win32/csharp/ProcessDefineDialog.cs15
-rw-r--r--storage/ndb/src/cw/cpcc-win32/csharp/fileaccess/FileMgmt.cs15
-rw-r--r--storage/ndb/src/cw/cpcc-win32/csharp/simpleparser/SimpleCPCParser.cs15
-rw-r--r--storage/ndb/src/cw/cpcc-win32/csharp/socketcomm/SocketComm.cs15
-rw-r--r--storage/ndb/src/cw/cpcc-win32/csharp/socketcomm/myTcpClient.cs15
-rw-r--r--storage/ndb/src/cw/cpcc-win32/csharp/startDatabaseDlg.cs15
-rw-r--r--storage/ndb/src/cw/cpcc-win32/csharp/telnetclient/telnetClient.cs15
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Computer.cls20
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Database.cls18
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Icon 110.icobin766 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Icon 231.icobin766 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Icon 237.icobin766 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Icon 241.icobin766 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Icon 242.icobin766 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Icon 270.icobin766 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Icon 271.icobin766 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Icon 273.icobin766 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Icon 31.icobin766 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Icon 337.icobin766 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Icon 338.icobin766 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Icon 339.icobin766 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/MSSCCPRJ.SCC5
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Module1.bas233
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/NdbCPC.vbp49
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/NdbCPC.vbw13
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/Process.cls22
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/closed folder.icobin10134 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/computer.icobin10134 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/frmAbout.frm245
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/frmLogin.frm119
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/frmMain.frm1207
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/frmNewComputer.frm124
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/frmNewComputer.frxbin4 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase.frxbin12 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase1.frm187
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase2.frm136
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase2.log1
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase3.frm88
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/frmOptions.frm231
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/frmSplash.frxbin70450 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/networking.icobin10134 -> 0 bytes
-rw-r--r--storage/ndb/src/cw/cpcc-win32/vb6/open folder.icobin10134 -> 0 bytes
-rw-r--r--storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp2
-rw-r--r--storage/ndb/src/libndb.ver.in15
-rw-r--r--storage/ndb/test/ndbapi/slow_select.cpp14
-rw-r--r--storage/ndb/test/ndbapi/testBitfield.cpp14
-rw-r--r--storage/ndb/test/ndbapi/testLcp.cpp14
-rw-r--r--storage/ndb/test/ndbnet/test.run15
-rw-r--r--storage/ndb/test/ndbnet/testError.run17
-rw-r--r--storage/ndb/test/ndbnet/testMNF.run17
-rw-r--r--storage/ndb/test/ndbnet/testNR.run15
-rw-r--r--storage/ndb/test/ndbnet/testNR1.run17
-rw-r--r--storage/ndb/test/ndbnet/testNR4.run17
-rw-r--r--storage/ndb/test/ndbnet/testSRhang.run15
-rw-r--r--storage/ndb/test/ndbnet/testTR295.run17
-rw-r--r--storage/ndb/test/run-test/16node-tests.txt15
-rwxr-xr-xstorage/ndb/test/run-test/atrt-analyze-result.sh17
-rwxr-xr-xstorage/ndb/test/run-test/atrt-clear-result.sh17
-rwxr-xr-xstorage/ndb/test/run-test/atrt-gather-result.sh17
-rwxr-xr-xstorage/ndb/test/run-test/atrt-mysql-test-run17
-rwxr-xr-xstorage/ndb/test/run-test/atrt-setup.sh17
-rwxr-xr-xstorage/ndb/test/run-test/atrt-testBackup17
-rw-r--r--storage/ndb/test/run-test/basic.txt15
-rw-r--r--storage/ndb/test/run-test/daily-basic-tests.txt15
-rw-r--r--storage/ndb/test/run-test/daily-devel-tests.txt15
-rwxr-xr-xstorage/ndb/test/run-test/make-config.sh17
-rwxr-xr-xstorage/ndb/test/run-test/make-html-reports.sh17
-rwxr-xr-xstorage/ndb/test/run-test/make-index.sh18
-rwxr-xr-xstorage/ndb/test/run-test/ndb-autotest.sh18
-rw-r--r--storage/ndb/test/sql/test_create_drop.pl17
-rw-r--r--storage/ndb/test/sql/test_range_bounds.pl17
-rwxr-xr-xstorage/ndb/tools/clean-links.sh15
-rw-r--r--storage/ndb/tools/make-errors.pl15
-rwxr-xr-xstorage/ndb/tools/make-links.sh15
-rw-r--r--storage/ndb/tools/ndb_error_reporter15
-rwxr-xr-xstorage/ndb/tools/rgrep15
-rw-r--r--storage/pbxt/src/lock_xt.cc6
-rw-r--r--storage/pbxt/src/table_xt.cc2
-rw-r--r--storage/xtradb/ChangeLog93
-rw-r--r--storage/xtradb/btr/btr0btr.c2
-rw-r--r--storage/xtradb/btr/btr0cur.c166
-rw-r--r--storage/xtradb/buf/buf0buf.c462
-rw-r--r--storage/xtradb/buf/buf0flu.c4
-rw-r--r--storage/xtradb/buf/buf0lru.c18
-rw-r--r--storage/xtradb/dict/dict0crea.c2
-rw-r--r--storage/xtradb/dict/dict0dict.c183
-rw-r--r--storage/xtradb/dict/dict0load.c5
-rw-r--r--storage/xtradb/fil/fil0fil.c110
-rw-r--r--storage/xtradb/fsp/fsp0fsp.c52
-rw-r--r--storage/xtradb/ha/hash0hash.c64
-rw-r--r--storage/xtradb/handler/ha_innodb.cc475
-rw-r--r--storage/xtradb/handler/handler0alter.cc11
-rw-r--r--storage/xtradb/handler/i_s.cc23
-rw-r--r--storage/xtradb/handler/innodb_patch_info.h1
-rw-r--r--storage/xtradb/include/btr0btr.h49
-rw-r--r--storage/xtradb/include/btr0btr.ic38
-rw-r--r--storage/xtradb/include/btr0cur.h44
-rw-r--r--storage/xtradb/include/buf0buf.h6
-rw-r--r--storage/xtradb/include/data0data.h11
-rw-r--r--storage/xtradb/include/data0data.ic22
-rw-r--r--storage/xtradb/include/dict0dict.h44
-rw-r--r--storage/xtradb/include/fil0fil.h9
-rw-r--r--storage/xtradb/include/hash0hash.h49
-rw-r--r--storage/xtradb/include/log0log.h3
-rw-r--r--storage/xtradb/include/os0file.h4
-rw-r--r--storage/xtradb/include/os0proc.h28
-rw-r--r--storage/xtradb/include/os0sync.h2
-rw-r--r--storage/xtradb/include/row0ins.h5
-rw-r--r--storage/xtradb/include/row0upd.h18
-rw-r--r--storage/xtradb/include/srv0srv.h4
-rw-r--r--storage/xtradb/include/srv0start.h3
-rw-r--r--storage/xtradb/include/trx0i_s.h2
-rw-r--r--storage/xtradb/include/trx0sys.h2
-rw-r--r--storage/xtradb/include/trx0sys.ic2
-rw-r--r--storage/xtradb/include/univ.i19
-rw-r--r--storage/xtradb/include/ut0lst.h43
-rw-r--r--storage/xtradb/include/ut0vec.h19
-rw-r--r--storage/xtradb/include/ut0vec.ic29
-rw-r--r--storage/xtradb/lock/lock0lock.c78
-rw-r--r--storage/xtradb/log/log0log.c7
-rw-r--r--storage/xtradb/log/log0recv.c21
-rw-r--r--storage/xtradb/os/os0proc.c170
-rw-r--r--storage/xtradb/os/os0sync.c10
-rw-r--r--storage/xtradb/plug.in25
-rw-r--r--storage/xtradb/row/row0ins.c9
-rw-r--r--storage/xtradb/row/row0merge.c6
-rw-r--r--storage/xtradb/row/row0mysql.c8
-rw-r--r--storage/xtradb/row/row0purge.c2
-rw-r--r--storage/xtradb/row/row0sel.c12
-rw-r--r--storage/xtradb/row/row0umod.c13
-rw-r--r--storage/xtradb/row/row0upd.c323
-rw-r--r--storage/xtradb/srv/srv0srv.c149
-rw-r--r--storage/xtradb/srv/srv0start.c57
-rw-r--r--storage/xtradb/sync/sync0rw.c9
-rw-r--r--storage/xtradb/thr/thr0loc.c30
-rw-r--r--storage/xtradb/trx/trx0i_s.c57
-rw-r--r--storage/xtradb/trx/trx0undo.c2
-rw-r--r--storage/xtradb/ut/ut0dbg.c2
-rw-r--r--storage/xtradb/ut/ut0ut.c4
269 files changed, 5539 insertions, 4798 deletions
diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc
index f3f5788360a..a7fda9a471a 100644
--- a/storage/archive/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -1449,12 +1449,13 @@ THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
/*
Here is where we get into the guts of a row level lock.
If TL_UNLOCK is set
- If we are not doing a LOCK TABLE or DISCARD/IMPORT
+ If we are not doing a LOCK TABLE, DELAYED LOCK or DISCARD/IMPORT
TABLESPACE, then allow multiple writers
*/
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
- lock_type <= TL_WRITE) && !thd_in_lock_tables(thd)
+ lock_type <= TL_WRITE) && delayed_insert == FALSE &&
+ !thd_in_lock_tables(thd)
&& !thd_tablespace_op(thd))
lock_type = TL_WRITE_ALLOW_WRITE;
diff --git a/storage/federatedx/Makefile.am b/storage/federatedx/Makefile.am
index 731b5dee01e..8dd6770e03f 100644
--- a/storage/federatedx/Makefile.am
+++ b/storage/federatedx/Makefile.am
@@ -22,23 +22,19 @@ pkgplugin_LTLIBRARIES = @plugin_federatedx_shared_target@
ha_federatedx_la_LDFLAGS = -module -rpath $(pkgplugindir) \
-L$(top_builddir)/libservices -lmysqlservices
ha_federatedx_la_CXXFLAGS= -shared $(AM_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-ha_federatedx_la_CFLAGS = -shared $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
noinst_LTLIBRARIES = @plugin_federatedx_static_target@ @plugin_federatedx_embedded_static_target@
libfederatedx_common_la_CXXFLAGS = $(AM_CXXFLAGS)
-libfederatedx_common_la_CFLAGS = $(AM_CFLAGS)
libfederatedx_common_la_SOURCES= federatedx_txn.cc \
federatedx_io.cc federatedx_io_null.cc \
federatedx_io_mysql.cc
-libfederatedx_la_CXXFLAGS = $(AM_CFLAGS)
-libfederatedx_la_CFLAGS = $(AM_CFLAGS)
+libfederatedx_la_CXXFLAGS = $(AM_CXXFLAGS)
libfederatedx_la_LIBADD = libfederatedx_common.la
libfederatedx_la_SOURCES= ha_federatedx.cc
-libfederatedx_embedded_la_CXXFLAGS = $(AM_CFLAGS) @plugin_embedded_defs@
-libfederatedx_embedded_la_CFLAGS = $(AM_CFLAGS) @plugin_embedded_defs@
+libfederatedx_embedded_la_CXXFLAGS = $(AM_CXXCFLAGS) @plugin_embedded_defs@
libfederatedx_embedded_la_LDFLAGS = $(AM_LDFLAGS)
libfederatedx_embedded_la_LIBADD = libfederatedx_common.la
libfederatedx_embedded_la_SOURCES= ha_federatedx.cc
diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc
index 434423b78b3..be90a1d1a08 100644
--- a/storage/federatedx/ha_federatedx.cc
+++ b/storage/federatedx/ha_federatedx.cc
@@ -400,7 +400,7 @@ int federatedx_db_init(void *p)
federatedx_hton->commit= ha_federatedx::commit;
federatedx_hton->rollback= ha_federatedx::rollback;
federatedx_hton->create= federatedx_create_handler;
- federatedx_hton->flags= HTON_ALTER_NOT_SUPPORTED | HTON_NO_PARTITION;
+ federatedx_hton->flags= HTON_ALTER_NOT_SUPPORTED;
if (pthread_mutex_init(&federatedx_mutex, MY_MUTEX_INIT_FAST))
goto error;
@@ -1456,7 +1456,8 @@ static void fill_server(MEM_ROOT *mem_root, FEDERATEDX_SERVER *server,
key.c_ptr_safe(); // Ensure we have end \0
server->key_length= key.length();
- server->key= (uchar *) memdup_root(mem_root, key.ptr(), key.length()+1);
+ /* Copy and add end \0 */
+ server->key= (uchar *) strmake_root(mem_root, key.ptr(), key.length());
/* pointer magic */
server->scheme+= (intptr) server->key;
@@ -1584,6 +1585,7 @@ static FEDERATEDX_SHARE *get_share(const char *table_name, TABLE *table)
tmp_share.table_name_length, ident_quote_char);
if (!(share= (FEDERATEDX_SHARE *) memdup_root(&mem_root, (char*)&tmp_share, sizeof(*share))) ||
+ !(share->share_key= (char*) memdup_root(&mem_root, tmp_share.share_key, tmp_share.share_key_length+1)) ||
!(share->select_query= (char*) strmake_root(&mem_root, query.ptr(), query.length())))
goto error;
@@ -1723,6 +1725,7 @@ int ha_federatedx::disconnect(handlerton *hton, MYSQL_THD thd)
{
federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton);
delete txn;
+ *((federatedx_txn **) thd_ha_data(thd, hton))= 0;
return 0;
}
diff --git a/storage/heap/hp_delete.c b/storage/heap/hp_delete.c
index 1af9cf26f8c..db2c0df6128 100644
--- a/storage/heap/hp_delete.c
+++ b/storage/heap/hp_delete.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2002, 2004-200 MySQL AB
+/* Copyright (C) 2000-2002, 2004-2007 MySQL AB
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
diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c
index b1b59227883..9438277050d 100644
--- a/storage/innobase/btr/btr0btr.c
+++ b/storage/innobase/btr/btr0btr.c
@@ -610,7 +610,7 @@ btr_page_get_father_for_rec(
"InnoDB: corruption. If the crash happens at "
"the database startup, see\n"
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
- "forcing-recovery.html about\n"
+ "forcing-innodb-recovery.html about\n"
"InnoDB: forcing recovery. "
"Then dump + drop + reimport.\n", stderr);
}
diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
index 500088c3901..08e033e7a63 100644
--- a/storage/innobase/buf/buf0buf.c
+++ b/storage/innobase/buf/buf0buf.c
@@ -334,7 +334,7 @@ buf_page_is_corrupted(
"InnoDB: tablespace but not the InnoDB "
"log files. See\n"
"InnoDB: http://dev.mysql.com/doc/refman/"
- "5.1/en/forcing-recovery.html\n"
+ "5.1/en/forcing-innodb-recovery.html\n"
"InnoDB: for more information.\n",
(ulong) mach_read_from_4(read_buf
+ FIL_PAGE_OFFSET),
@@ -2067,7 +2067,7 @@ buf_page_io_complete(
" table for corruption.\n"
"InnoDB: See also"
" http://dev.mysql.com/doc/refman/5.1/en/"
- "forcing-recovery.html\n"
+ "forcing-innodb-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
index b52a94c3348..fda6555e082 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -2217,7 +2217,7 @@ dict_scan_to(
quote = '\0';
} else if (quote) {
/* Within quotes: do nothing. */
- } else if (*ptr == '`' || *ptr == '"') {
+ } else if (*ptr == '`' || *ptr == '"' || *ptr == '\'') {
/* Starting quote: remember the quote character. */
quote = *ptr;
} else {
diff --git a/storage/innobase/dict/dict0mem.c b/storage/innobase/dict/dict0mem.c
index 168771ca307..9573ea18fde 100644
--- a/storage/innobase/dict/dict0mem.c
+++ b/storage/innobase/dict/dict0mem.c
@@ -87,6 +87,8 @@ dict_mem_table_create(
table->big_rows = 0;
+ table->fk_max_recusive_level = 0;
+
mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
table->autoinc = 0;
diff --git a/storage/innobase/fsp/fsp0fsp.c b/storage/innobase/fsp/fsp0fsp.c
index 1f033c4b140..d228e683957 100644
--- a/storage/innobase/fsp/fsp0fsp.c
+++ b/storage/innobase/fsp/fsp0fsp.c
@@ -3046,7 +3046,7 @@ fseg_free_page_low(
crash:
fputs("InnoDB: Please refer to\n"
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
- "forcing-recovery.html\n"
+ "forcing-innodb-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
ut_error;
}
diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
index b077ff0c181..58c5fd9ef3d 100644
--- a/storage/innobase/include/buf0buf.ic
+++ b/storage/innobase/include/buf0buf.ic
@@ -218,7 +218,7 @@ buf_block_align(
"InnoDB: corruption. If this happens in an"
" InnoDB database recovery, see\n"
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
- "forcing-recovery.html\n"
+ "forcing-innodb-recovery.html\n"
"InnoDB: how to force recovery.\n",
ptr, frame_zero,
buf_pool->high_end);
@@ -257,7 +257,7 @@ buf_frame_align(
"InnoDB: corruption. If this happens in an"
" InnoDB database recovery, see\n"
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
- "forcing-recovery.html\n"
+ "forcing-innodb-recovery.html\n"
"InnoDB: how to force recovery.\n",
ptr, buf_pool->frame_zero,
buf_pool->high_end);
diff --git a/storage/innobase/log/log0recv.c b/storage/innobase/log/log0recv.c
index 6e1ca58cb15..9683486238c 100644
--- a/storage/innobase/log/log0recv.c
+++ b/storage/innobase/log/log0recv.c
@@ -1826,7 +1826,7 @@ recv_report_corrupt_log(
"InnoDB: on your InnoDB tables to check that they are ok!\n"
"InnoDB: If mysqld crashes after this recovery, look at\n"
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
- "forcing-recovery.html\n"
+ "forcing-innodb-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
fflush(stderr);
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index 4fdd92c7cba..cee97871470 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -552,7 +552,7 @@ handle_new_error:
" after the startup or when\n"
"InnoDB: you dump the tables, look at\n"
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
- "forcing-recovery.html"
+ "forcing-innodb-recovery.html"
" for help.\n", stderr);
} else if (err == DB_FOREIGN_EXCEED_MAX_CASCADE) {
diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c
index 9d057110d11..4c4360f819e 100644
--- a/storage/innobase/srv/srv0start.c
+++ b/storage/innobase/srv/srv0start.c
@@ -1247,6 +1247,23 @@ innobase_start_or_create_for_mysql(void)
fil_init(srv_max_n_open_files);
+ /* Print time to initialize the buffer pool */
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Initializing buffer pool, size =");
+
+ if (srv_pool_size * UNIV_PAGE_SIZE >= 1024 * 1024 * 1024) {
+ fprintf(stderr,
+ " %.1fG\n",
+ ((double) (srv_pool_size * UNIV_PAGE_SIZE))
+ / (1024 * 1024 * 1024));
+ } else {
+ fprintf(stderr,
+ " %.1fM\n",
+ ((double) (srv_pool_size * UNIV_PAGE_SIZE))
+ / (1024 * 1024));
+ }
+
if (srv_use_awe) {
fprintf(stderr,
"InnoDB: Using AWE: Memory window is %lu MB"
@@ -1267,6 +1284,8 @@ innobase_start_or_create_for_mysql(void)
srv_pool_size);
}
+ ut_print_timestamp(stderr);
+
if (ret == NULL) {
fprintf(stderr,
"InnoDB: Fatal error: cannot allocate the memory"
@@ -1275,6 +1294,9 @@ innobase_start_or_create_for_mysql(void)
return(DB_ERROR);
}
+ fprintf(stderr,
+ " InnoDB: Completed initialization of buffer pool\n");
+
fsp_init();
log_init();
diff --git a/storage/innobase/sync/sync0rw.c b/storage/innobase/sync/sync0rw.c
index 367f019ce55..0b05fb826ac 100644
--- a/storage/innobase/sync/sync0rw.c
+++ b/storage/innobase/sync/sync0rw.c
@@ -888,7 +888,7 @@ rw_lock_debug_print(
rwt = info->lock_type;
- fprintf(stderr, "Locked: thread %ld file %s line %ld ",
+ fprintf(stderr, "Locked: thread %lu file %s line %lu ",
(ulong) os_thread_pf(info->thread_id), info->file_name,
(ulong) info->line);
if (rwt == RW_LOCK_SHARED) {
diff --git a/storage/innobase/ut/ut0dbg.c b/storage/innobase/ut/ut0dbg.c
index 8c4be190d77..88be1b34d9b 100644
--- a/storage/innobase/ut/ut0dbg.c
+++ b/storage/innobase/ut/ut0dbg.c
@@ -58,7 +58,7 @@ ut_dbg_assertion_failed(
"InnoDB: immediately after the mysqld startup, there may be\n"
"InnoDB: corruption in the InnoDB tablespace. Please refer to\n"
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
- "forcing-recovery.html\n"
+ "forcing-innodb-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT)
ut_dbg_stop_threads = TRUE;
diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog
index 0cd8ac8a7e6..bf003b810d2 100644
--- a/storage/innodb_plugin/ChangeLog
+++ b/storage/innodb_plugin/ChangeLog
@@ -1,13 +1,96 @@
+2011-01-06 The InnoDB Team
+ * row/row0merge.c:
+ Fix Bug#59312 Examine MAX_FULL_NAME_LEN in InnoDB to address
+ possible insufficient name buffer
+
+2011-01-06 The InnoDB Team
+ * dict/dict0dict.c, handler/ha_innodb.cc, handler/i_s.cc,
+ include/univ.i:
+ Fix Bug#58643 InnoDB: too long table name
+
+2011-01-06 The InnoDB Team
+ * handler/i_s.cc, include/trx0i_s.h, trx/trx0i_s.c:
+ Fix Bug#55397 cannot select from innodb_trx when trx_query contains
+ blobs that aren't strings
+
+2011-01-04 The InnoDB Team
+ * dict/dict0dict.c:
+ Fix Bug#59197 double quote in field comment prevents foreign
+ key constraint creation
+
+2010-12-21 The InnoDB Team
+ * include/btr0cur.h, include/row0upd.h, btr/btr0cur.c,
+ row/row0umod.c, row/row0upd.c:
+ Fix Bug#55284 Double free of off-page columns due to lock wait
+ while updating PRIMARY KEY
+
+2010-12-21 The InnoDB Team
+
+ * include/data0data.h, include/data0data.ic, include/row0upd.h,
+ btr/btr0cur.c, row/row0purge.c, row/row0umod.c, row/row0upd.c,
+ innodb.result, innodb.test:
+ Fix Bug#58912 InnoDB unnecessarily avoids update-in-place
+ on column prefix indexes
+
+2010-12-09 The InnoDB Team
+
+ * buf/buf0lru.c:
+ Fix Bug#57600 output of I/O sum[%lu] can go negative
+
+2010-11-11 The InnoDB Team
+
+ * thr/thr0loc.c, trx/trx0i_s.c:
+ Fix Bug#57802 Empty ASSERTION parameter passed to the HASH_SEARCH macro
+
+2010-11-10 The InnoDB Team
+
+ * dict/dict0dict.c, handler/handler0alter.cc, include/dict0dict.h
+ row/row0merge.c:
+ Fix Bug#55084 InnoDB crash and corruption after ALTER TABLE
+
+2010-11-10 The InnoDB Team
+
+ * srv/srv0start.c:
+ Fix Bug#48026 Log start and end of InnoDB buffer pool
+ initialization to the error log
+
+2010-11-03 The InnoDB Team
+
+ * include/btr0btr.h, include/btr0btr.ic, dict/dict0crea.c:
+ Fix Bug#57947 InnoDB diagnostics shows btr_block_get calls
+ instead of real callers
+
+2010-11-03 The InnoDB Team
+
+ * fil/fil0fil.c, fsp/fsp0fsp.c, handler/ha_innodb.cc,
+ include/fil0fil.h, include/univ.i:
+ Fix Bug #54538 - use of exclusive innodb dictionary lock limits
+ performance.
+
+2010-11-02 The InnoDB Team
+
+ * btr/btr0cur.c, dict/dict0dict.c, dict/dict0load.c,
+ handler/ha_innodb.cc, include/dict0dict.h, row/row0mysql.c,
+ innodb_bug53046.result, innodb_bug53046.test:
+ Fix Bug#53046 dict_update_statistics_low can still be run
+ concurrently on same table
+
+2010-11-02 The InnoDB Team
+
+ * row/row0sel.c:
+ Fix Bug#57799 READ UNCOMMITTED access failure of off-page
+ DYNAMIC or COMPRESSED columns again
+
2010-10-24 The InnoDB Team
* row/row0mysql.c
- Fix Bug #57700 Latching order violation in
+ Fix Bug#57700 Latching order violation in
row_truncate_table_for_mysql()
2010-10-20 The InnoDB Team
* dict/dict0load.c
- Fix Bug #57616 Sig 11 in dict_load_table() when failed to load
+ Fix Bug#57616 Sig 11 in dict_load_table() when failed to load
index or foreign key
2010-10-19 The InnoDB Team
@@ -17,7 +100,7 @@
include/ibuf0ibuf.h, include/row0mysql.h,
row/row0mysql.c, row/row0sel.c,
innodb_bug56680.test, innodb_bug56680.result:
- Fix Bug #56680 InnoDB may return wrong results from a
+ Fix Bug#56680 InnoDB may return wrong results from a
case-insensitive covering index
2010-10-18 The InnoDB Team
@@ -72,7 +155,7 @@
2010-08-03 The InnoDB Team
* include/dict0dict.h, include/dict0dict.ic, row/row0mysql.c:
- Fix bug #54678, InnoDB, TRUNCATE, ALTER, I_S SELECT, crash or deadlock
+ Fix Bug#54678 InnoDB, TRUNCATE, ALTER, I_S SELECT, crash or deadlock
2010-08-03 The InnoDB Team
@@ -146,7 +229,7 @@
* dict/dict0load.c, fil/fil0fil.c:
Fix Bug#54658: InnoDB: Warning: allocated tablespace %lu,
- old maximum was 0 (introduced in Bug #53578 fix)
+ old maximum was 0 (introduced in Bug#53578 fix)
2010-06-16 The InnoDB Team
diff --git a/storage/innodb_plugin/btr/btr0btr.c b/storage/innodb_plugin/btr/btr0btr.c
index 29cd470e650..32e2caecdb8 100644
--- a/storage/innodb_plugin/btr/btr0btr.c
+++ b/storage/innodb_plugin/btr/btr0btr.c
@@ -663,7 +663,7 @@ btr_page_get_father_node_ptr_func(
" to fix the\n"
"InnoDB: corruption. If the crash happens at "
"the database startup, see\n"
- "InnoDB: " REFMAN "forcing-recovery.html about\n"
+ "InnoDB: " REFMAN "forcing-innodb-recovery.html about\n"
"InnoDB: forcing recovery. "
"Then dump + drop + reimport.\n", stderr);
diff --git a/storage/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c
index 79fe328a631..c57255a25ae 100644
--- a/storage/innodb_plugin/btr/btr0cur.c
+++ b/storage/innodb_plugin/btr/btr0cur.c
@@ -953,7 +953,7 @@ btr_cur_ins_lock_and_undo(
not zero, the parameters index and thr
should be specified */
btr_cur_t* cursor, /*!< in: cursor on page after which to insert */
- const dtuple_t* entry, /*!< in: entry to insert */
+ dtuple_t* entry, /*!< in/out: entry to insert */
que_thr_t* thr, /*!< in: query thread or NULL */
mtr_t* mtr, /*!< in/out: mini-transaction */
ibool* inherit)/*!< out: TRUE if the inserted new record maybe
@@ -1756,7 +1756,8 @@ btr_cur_update_in_place(
NOT call it if index is secondary */
if (!dict_index_is_clust(index)
- || row_upd_changes_ord_field_binary(NULL, index, update)) {
+ || row_upd_changes_ord_field_binary(NULL, NULL,
+ index, update)) {
/* Remove possible hash index pointer to this record */
btr_search_update_hash_on_delete(cursor);
@@ -2508,27 +2509,24 @@ ulint
btr_cur_del_mark_set_clust_rec(
/*===========================*/
ulint flags, /*!< in: undo logging and locking flags */
- btr_cur_t* cursor, /*!< in: cursor */
+ buf_block_t* block, /*!< in/out: buffer block of the record */
+ rec_t* rec, /*!< in/out: record */
+ dict_index_t* index, /*!< in: clustered index of the record */
+ const ulint* offsets,/*!< in: rec_get_offsets(rec) */
ibool val, /*!< in: value to set */
que_thr_t* thr, /*!< in: query thread */
mtr_t* mtr) /*!< in: mtr */
{
- dict_index_t* index;
- buf_block_t* block;
roll_ptr_t roll_ptr;
ulint err;
- rec_t* rec;
page_zip_des_t* page_zip;
trx_t* trx;
- mem_heap_t* heap = NULL;
- ulint offsets_[REC_OFFS_NORMAL_SIZE];
- ulint* offsets = offsets_;
- rec_offs_init(offsets_);
- rec = btr_cur_get_rec(cursor);
- index = cursor->index;
+ ut_ad(dict_index_is_clust(index));
+ ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
- offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
+ ut_ad(buf_block_get_frame(block) == page_align(rec));
+ ut_ad(page_is_leaf(page_align(rec)));
#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
@@ -2540,13 +2538,12 @@ btr_cur_del_mark_set_clust_rec(
ut_ad(dict_index_is_clust(index));
ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
- err = lock_clust_rec_modify_check_and_lock(flags,
- btr_cur_get_block(cursor),
+ err = lock_clust_rec_modify_check_and_lock(flags, block,
rec, index, offsets, thr);
if (err != DB_SUCCESS) {
- goto func_exit;
+ return(err);
}
err = trx_undo_report_row_operation(flags, TRX_UNDO_MODIFY_OP, thr,
@@ -2554,11 +2551,9 @@ btr_cur_del_mark_set_clust_rec(
&roll_ptr);
if (err != DB_SUCCESS) {
- goto func_exit;
+ return(err);
}
- block = btr_cur_get_block(cursor);
-
if (block->is_hashed) {
rw_lock_x_lock(&btr_search_latch);
}
@@ -2581,10 +2576,6 @@ btr_cur_del_mark_set_clust_rec(
btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx,
roll_ptr, mtr);
-func_exit:
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
return(err);
}
@@ -3355,8 +3346,6 @@ btr_estimate_number_of_different_key_vals(
also the pages used for external storage of fields (those pages are
included in index->stat_n_leaf_pages) */
- dict_index_stat_mutex_enter(index);
-
for (j = 0; j <= n_cols; j++) {
index->stat_n_diff_key_vals[j]
= ((n_diff[j]
@@ -3386,8 +3375,6 @@ btr_estimate_number_of_different_key_vals(
index->stat_n_diff_key_vals[j] += add_on;
}
- dict_index_stat_mutex_exit(index);
-
mem_free(n_diff);
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
@@ -3480,108 +3467,36 @@ btr_cur_set_ownership_of_extern_field(
}
/*******************************************************************//**
-Marks not updated extern fields as not-owned by this record. The ownership
-is transferred to the updated record which is inserted elsewhere in the
+Marks non-updated off-page fields as disowned by this record. The ownership
+must be transferred to the updated record which is inserted elsewhere in the
index tree. In purge only the owner of externally stored field is allowed
-to free the field.
-@return TRUE if BLOB ownership was transferred */
+to free the field. */
UNIV_INTERN
-ibool
-btr_cur_mark_extern_inherited_fields(
-/*=================================*/
+void
+btr_cur_disown_inherited_fields(
+/*============================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
part will be updated, or NULL */
rec_t* rec, /*!< in/out: record in a clustered index */
dict_index_t* index, /*!< in: index of the page */
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
const upd_t* update, /*!< in: update vector */
- mtr_t* mtr) /*!< in: mtr, or NULL if not logged */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
- ulint n;
- ulint j;
ulint i;
- ibool change_ownership = FALSE;
- ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
+ ut_ad(rec_offs_any_extern(offsets));
+ ut_ad(mtr);
- if (!rec_offs_any_extern(offsets)) {
-
- return(FALSE);
- }
-
- n = rec_offs_n_fields(offsets);
-
- for (i = 0; i < n; i++) {
- if (rec_offs_nth_extern(offsets, i)) {
-
- /* Check it is not in updated fields */
-
- if (update) {
- for (j = 0; j < upd_get_n_fields(update);
- j++) {
- if (upd_get_nth_field(update, j)
- ->field_no == i) {
-
- goto updated;
- }
- }
- }
-
+ for (i = 0; i < rec_offs_n_fields(offsets); i++) {
+ if (rec_offs_nth_extern(offsets, i)
+ && !upd_get_field_by_field_no(update, i)) {
btr_cur_set_ownership_of_extern_field(
page_zip, rec, index, offsets, i, FALSE, mtr);
-
- change_ownership = TRUE;
-updated:
- ;
}
}
-
- return(change_ownership);
-}
-
-/*******************************************************************//**
-The complement of the previous function: in an update entry may inherit
-some externally stored fields from a record. We must mark them as inherited
-in entry, so that they are not freed in a rollback. */
-UNIV_INTERN
-void
-btr_cur_mark_dtuple_inherited_extern(
-/*=================================*/
- dtuple_t* entry, /*!< in/out: updated entry to be
- inserted to clustered index */
- const upd_t* update) /*!< in: update vector */
-{
- ulint i;
-
- for (i = 0; i < dtuple_get_n_fields(entry); i++) {
-
- dfield_t* dfield = dtuple_get_nth_field(entry, i);
- byte* data;
- ulint len;
- ulint j;
-
- if (!dfield_is_ext(dfield)) {
- continue;
- }
-
- /* Check if it is in updated fields */
-
- for (j = 0; j < upd_get_n_fields(update); j++) {
- if (upd_get_nth_field(update, j)->field_no == i) {
-
- goto is_updated;
- }
- }
-
- data = dfield_get_data(dfield);
- len = dfield_get_len(dfield);
- data[len - BTR_EXTERN_FIELD_REF_SIZE + BTR_EXTERN_LEN]
- |= BTR_EXTERN_INHERITED_FLAG;
-
-is_updated:
- ;
- }
}
/*******************************************************************//**
@@ -3620,29 +3535,6 @@ btr_cur_unmark_extern_fields(
}
/*******************************************************************//**
-Marks all extern fields in a dtuple as owned by the record. */
-UNIV_INTERN
-void
-btr_cur_unmark_dtuple_extern_fields(
-/*================================*/
- dtuple_t* entry) /*!< in/out: clustered index entry */
-{
- ulint i;
-
- for (i = 0; i < dtuple_get_n_fields(entry); i++) {
- dfield_t* dfield = dtuple_get_nth_field(entry, i);
-
- if (dfield_is_ext(dfield)) {
- byte* data = dfield_get_data(dfield);
- ulint len = dfield_get_len(dfield);
-
- data[len - BTR_EXTERN_FIELD_REF_SIZE + BTR_EXTERN_LEN]
- &= ~BTR_EXTERN_OWNER_FLAG;
- }
- }
-}
-
-/*******************************************************************//**
Flags the data tuple fields that are marked as extern storage in the
update vector. We use this function to remember which fields we must
mark as extern storage in a record inserted for an update.
@@ -3794,7 +3686,7 @@ Stores the fields in big_rec_vec to the tablespace and puts pointers to
them in rec. The extern flags in rec will have to be set beforehand.
The fields are stored on pages allocated from leaf node
file segment of the index tree.
-@return DB_SUCCESS or error */
+@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN
ulint
btr_store_big_rec_extern_fields(
diff --git a/storage/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c
index 65d4311b840..dac416f9472 100644
--- a/storage/innodb_plugin/buf/buf0buf.c
+++ b/storage/innodb_plugin/buf/buf0buf.c
@@ -375,7 +375,7 @@ buf_page_is_corrupted(
"you may have copied the InnoDB\n"
"InnoDB: tablespace but not the InnoDB "
"log files. See\n"
- "InnoDB: " REFMAN "forcing-recovery.html\n"
+ "InnoDB: " REFMAN "forcing-innodb-recovery.html\n"
"InnoDB: for more information.\n",
(ulong) mach_read_from_4(read_buf
+ FIL_PAGE_OFFSET),
@@ -3240,7 +3240,7 @@ corrupt:
"InnoDB: TABLE to scan your"
" table for corruption.\n"
"InnoDB: See also "
- REFMAN "forcing-recovery.html\n"
+ REFMAN "forcing-innodb-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
diff --git a/storage/innodb_plugin/buf/buf0flu.c b/storage/innodb_plugin/buf/buf0flu.c
index 2123f8a060d..3a9975ce4b7 100644
--- a/storage/innodb_plugin/buf/buf0flu.c
+++ b/storage/innodb_plugin/buf/buf0flu.c
@@ -1710,9 +1710,9 @@ buf_flush_validate_low(void)
ut_a(om > 0);
if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
+ buf_page_t* rpage;
ut_a(rnode);
- buf_page_t* rpage = *rbt_value(buf_page_t*,
- rnode);
+ rpage = *rbt_value(buf_page_t*, rnode);
ut_a(rpage);
ut_a(rpage == bpage);
rnode = rbt_next(buf_pool->flush_rbt, rnode);
diff --git a/storage/innodb_plugin/buf/buf0lru.c b/storage/innodb_plugin/buf/buf0lru.c
index 78d8d348e2a..e4cf218bf2e 100644
--- a/storage/innodb_plugin/buf/buf0lru.c
+++ b/storage/innodb_plugin/buf/buf0lru.c
@@ -1942,6 +1942,7 @@ buf_LRU_stat_update(void)
/*=====================*/
{
buf_LRU_stat_t* item;
+ buf_LRU_stat_t cur_stat;
/* If we haven't started eviction yet then don't update stats. */
if (buf_pool->freed_page_clock == 0) {
@@ -1955,12 +1956,19 @@ buf_LRU_stat_update(void)
buf_LRU_stat_arr_ind++;
buf_LRU_stat_arr_ind %= BUF_LRU_STAT_N_INTERVAL;
- /* Add the current value and subtract the obsolete entry. */
- buf_LRU_stat_sum.io += buf_LRU_stat_cur.io - item->io;
- buf_LRU_stat_sum.unzip += buf_LRU_stat_cur.unzip - item->unzip;
+ /* Add the current value and subtract the obsolete entry.
+ Since buf_LRU_stat_cur is not protected by any mutex,
+ it can be changing between adding to buf_LRU_stat_sum
+ and copying to item. Assign it to local variables to make
+ sure the same value assign to the buf_LRU_stat_sum
+ and item */
+ cur_stat = buf_LRU_stat_cur;
+
+ buf_LRU_stat_sum.io += cur_stat.io - item->io;
+ buf_LRU_stat_sum.unzip += cur_stat.unzip - item->unzip;
/* Put current entry in the array. */
- memcpy(item, &buf_LRU_stat_cur, sizeof *item);
+ memcpy(item, &cur_stat, sizeof *item);
buf_pool_mutex_exit();
diff --git a/storage/innodb_plugin/dict/dict0crea.c b/storage/innodb_plugin/dict/dict0crea.c
index e63f8bc3e6a..7d6cbc8c1c8 100644
--- a/storage/innodb_plugin/dict/dict0crea.c
+++ b/storage/innodb_plugin/dict/dict0crea.c
@@ -828,7 +828,7 @@ dict_truncate_index_tree(
appropriate field in the SYS_INDEXES record: this mini-transaction
marks the B-tree totally truncated */
- btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
+ btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
btr_free_root(space, zip_size, root_page_no, mtr);
create:
diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c
index a3575c283cd..9474ab3582a 100644
--- a/storage/innodb_plugin/dict/dict0dict.c
+++ b/storage/innodb_plugin/dict/dict0dict.c
@@ -80,9 +80,18 @@ UNIV_INTERN rw_lock_t dict_operation_lock;
/** Identifies generated InnoDB foreign key names */
static char dict_ibfk[] = "_ibfk_";
-/** array of mutexes protecting dict_index_t::stat_n_diff_key_vals[] */
-#define DICT_INDEX_STAT_MUTEX_SIZE 32
-static mutex_t dict_index_stat_mutex[DICT_INDEX_STAT_MUTEX_SIZE];
+/** array of rw locks protecting
+dict_table_t::stat_initialized
+dict_table_t::stat_n_rows (*)
+dict_table_t::stat_clustered_index_size
+dict_table_t::stat_sum_of_other_index_sizes
+dict_table_t::stat_modified_counter (*)
+dict_table_t::indexes*::stat_n_diff_key_vals[]
+dict_table_t::indexes*::stat_index_size
+dict_table_t::indexes*::stat_n_leaf_pages
+(*) those are not always protected for performance reasons */
+#define DICT_TABLE_STATS_LATCHES_SIZE 64
+static rw_lock_t dict_table_stats_latches[DICT_TABLE_STATS_LATCHES_SIZE];
/*******************************************************************//**
Tries to find column names for the index and sets the col field of the
@@ -243,43 +252,65 @@ dict_mutex_exit_for_mysql(void)
mutex_exit(&(dict_sys->mutex));
}
-/** Get the mutex that protects index->stat_n_diff_key_vals[] */
-#define GET_INDEX_STAT_MUTEX(index) \
- (&dict_index_stat_mutex[ut_fold_dulint(index->id) \
- % DICT_INDEX_STAT_MUTEX_SIZE])
+/** Get the latch that protects the stats of a given table */
+#define GET_TABLE_STATS_LATCH(table) \
+ (&dict_table_stats_latches[ut_fold_dulint(table->id) \
+ % DICT_TABLE_STATS_LATCHES_SIZE])
/**********************************************************************//**
-Lock the appropriate mutex to protect index->stat_n_diff_key_vals[].
-index->id is used to pick the right mutex and it should not change
-before dict_index_stat_mutex_exit() is called on this index. */
+Lock the appropriate latch to protect a given table's statistics.
+table->id is used to pick the corresponding latch from a global array of
+latches. */
UNIV_INTERN
void
-dict_index_stat_mutex_enter(
-/*========================*/
- const dict_index_t* index) /*!< in: index */
+dict_table_stats_lock(
+/*==================*/
+ const dict_table_t* table, /*!< in: table */
+ ulint latch_mode) /*!< in: RW_S_LATCH or
+ RW_X_LATCH */
{
- ut_ad(index != NULL);
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
- ut_ad(index->cached);
- ut_ad(!index->to_be_dropped);
+ ut_ad(table != NULL);
+ ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
- mutex_enter(GET_INDEX_STAT_MUTEX(index));
+ switch (latch_mode) {
+ case RW_S_LATCH:
+ rw_lock_s_lock(GET_TABLE_STATS_LATCH(table));
+ break;
+ case RW_X_LATCH:
+ rw_lock_x_lock(GET_TABLE_STATS_LATCH(table));
+ break;
+ case RW_NO_LATCH:
+ /* fall through */
+ default:
+ ut_error;
+ }
}
/**********************************************************************//**
-Unlock the appropriate mutex that protects index->stat_n_diff_key_vals[]. */
+Unlock the latch that has been locked by dict_table_stats_lock() */
UNIV_INTERN
void
-dict_index_stat_mutex_exit(
-/*=======================*/
- const dict_index_t* index) /*!< in: index */
+dict_table_stats_unlock(
+/*====================*/
+ const dict_table_t* table, /*!< in: table */
+ ulint latch_mode) /*!< in: RW_S_LATCH or
+ RW_X_LATCH */
{
- ut_ad(index != NULL);
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
- ut_ad(index->cached);
- ut_ad(!index->to_be_dropped);
+ ut_ad(table != NULL);
+ ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
- mutex_exit(GET_INDEX_STAT_MUTEX(index));
+ switch (latch_mode) {
+ case RW_S_LATCH:
+ rw_lock_s_unlock(GET_TABLE_STATS_LATCH(table));
+ break;
+ case RW_X_LATCH:
+ rw_lock_x_unlock(GET_TABLE_STATS_LATCH(table));
+ break;
+ case RW_NO_LATCH:
+ /* fall through */
+ default:
+ ut_error;
+ }
}
/********************************************************************//**
@@ -668,8 +699,8 @@ dict_init(void)
mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
- for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
- mutex_create(&dict_index_stat_mutex[i], SYNC_INDEX_TREE);
+ for (i = 0; i < DICT_TABLE_STATS_LATCHES_SIZE; i++) {
+ rw_lock_create(&dict_table_stats_latches[i], SYNC_INDEX_TREE);
}
}
@@ -700,12 +731,11 @@ dict_table_get(
mutex_exit(&(dict_sys->mutex));
if (table != NULL) {
- if (!table->stat_initialized) {
- /* If table->ibd_file_missing == TRUE, this will
- print an error message and return without doing
- anything. */
- dict_update_statistics(table);
- }
+ /* If table->ibd_file_missing == TRUE, this will
+ print an error message and return without doing
+ anything. */
+ dict_update_statistics(table, TRUE /* only update stats
+ if they have not been initialized */);
}
return(table);
@@ -902,7 +932,7 @@ dict_table_rename_in_cache(
dict_foreign_t* foreign;
dict_index_t* index;
ulint fold;
- char old_name[MAX_TABLE_NAME_LEN + 1];
+ char old_name[MAX_FULL_NAME_LEN + 1];
ut_ad(table);
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -914,7 +944,7 @@ dict_table_rename_in_cache(
ut_print_timestamp(stderr);
fprintf(stderr, "InnoDB: too long table name: '%s', "
"max length is %d\n", table->name,
- MAX_TABLE_NAME_LEN);
+ MAX_FULL_NAME_LEN);
ut_error;
}
@@ -964,11 +994,11 @@ dict_table_rename_in_cache(
ut_fold_string(old_name), table);
if (strlen(new_name) > strlen(table->name)) {
- /* We allocate MAX_TABLE_NAME_LEN+1 bytes here to avoid
+ /* We allocate MAX_FULL_NAME_LEN + 1 bytes here to avoid
memory fragmentation, we assume a repeated calls of
ut_realloc() with the same size do not cause fragmentation */
- ut_a(strlen(new_name) <= MAX_TABLE_NAME_LEN);
- table->name = ut_realloc(table->name, MAX_TABLE_NAME_LEN + 1);
+ ut_a(strlen(new_name) <= MAX_FULL_NAME_LEN);
+ table->name = ut_realloc(table->name, MAX_FULL_NAME_LEN + 1);
}
memcpy(table->name, new_name, strlen(new_name) + 1);
@@ -2658,7 +2688,7 @@ dict_scan_to(
quote = '\0';
} else if (quote) {
/* Within quotes: do nothing. */
- } else if (*ptr == '`' || *ptr == '"') {
+ } else if (*ptr == '`' || *ptr == '"' || *ptr == '\'') {
/* Starting quote: remember the quote character. */
quote = *ptr;
} else {
@@ -4183,12 +4213,13 @@ Calculates new estimates for table and index statistics. The statistics
are used in query optimization. */
UNIV_INTERN
void
-dict_update_statistics_low(
-/*=======================*/
+dict_update_statistics(
+/*===================*/
dict_table_t* table, /*!< in/out: table */
- ibool has_dict_mutex __attribute__((unused)))
- /*!< in: TRUE if the caller has the
- dictionary mutex */
+ ibool only_calc_if_missing_stats)/*!< in: only
+ update/recalc the stats if they have
+ not been initialized yet, otherwise
+ do nothing */
{
dict_index_t* index;
ulint sum_of_index_sizes = 0;
@@ -4216,6 +4247,12 @@ dict_update_statistics_low(
return;
}
+ dict_table_stats_lock(table, RW_X_LATCH);
+
+ if (only_calc_if_missing_stats && table->stat_initialized) {
+ dict_table_stats_unlock(table, RW_X_LATCH);
+ return;
+ }
do {
if (UNIV_LIKELY
@@ -4261,13 +4298,9 @@ dict_update_statistics_low(
index = dict_table_get_first_index(table);
- dict_index_stat_mutex_enter(index);
-
table->stat_n_rows = index->stat_n_diff_key_vals[
dict_index_get_n_unique(index)];
- dict_index_stat_mutex_exit(index);
-
table->stat_clustered_index_size = index->stat_index_size;
table->stat_sum_of_other_index_sizes = sum_of_index_sizes
@@ -4276,18 +4309,8 @@ dict_update_statistics_low(
table->stat_initialized = TRUE;
table->stat_modified_counter = 0;
-}
-/*********************************************************************//**
-Calculates new estimates for table and index statistics. The statistics
-are used in query optimization. */
-UNIV_INTERN
-void
-dict_update_statistics(
-/*===================*/
- dict_table_t* table) /*!< in/out: table */
-{
- dict_update_statistics_low(table, FALSE);
+ dict_table_stats_unlock(table, RW_X_LATCH);
}
/**********************************************************************//**
@@ -4367,7 +4390,9 @@ dict_table_print_low(
ut_ad(mutex_own(&(dict_sys->mutex)));
- dict_update_statistics_low(table, TRUE);
+ dict_update_statistics(table, FALSE /* update even if initialized */);
+
+ dict_table_stats_lock(table, RW_S_LATCH);
fprintf(stderr,
"--------------------------------------\n"
@@ -4396,6 +4421,8 @@ dict_table_print_low(
index = UT_LIST_GET_NEXT(indexes, index);
}
+ dict_table_stats_unlock(table, RW_S_LATCH);
+
foreign = UT_LIST_GET_FIRST(table->foreign_list);
while (foreign != NULL) {
@@ -4444,8 +4471,6 @@ dict_index_print_low(
ut_ad(mutex_own(&(dict_sys->mutex)));
- dict_index_stat_mutex_enter(index);
-
if (index->n_user_defined_cols > 0) {
n_vals = index->stat_n_diff_key_vals[
index->n_user_defined_cols];
@@ -4453,8 +4478,6 @@ dict_index_print_low(
n_vals = index->stat_n_diff_key_vals[1];
}
- dict_index_stat_mutex_exit(index);
-
fprintf(stderr,
" INDEX: name %s, id %lu %lu, fields %lu/%lu,"
" uniq %lu, type %lu\n"
@@ -4798,7 +4821,8 @@ void
dict_table_replace_index_in_foreign_list(
/*=====================================*/
dict_table_t* table, /*!< in/out: table */
- dict_index_t* index) /*!< in: index to be replaced */
+ dict_index_t* index, /*!< in: index to be replaced */
+ const trx_t* trx) /*!< in: transaction handle */
{
dict_foreign_t* foreign;
@@ -4809,7 +4833,13 @@ dict_table_replace_index_in_foreign_list(
if (foreign->foreign_index == index) {
dict_index_t* new_index
= dict_foreign_find_equiv_index(foreign);
- ut_a(new_index);
+
+ /* There must exist an alternative index if
+ check_foreigns (FOREIGN_KEY_CHECKS) is on,
+ since ha_innobase::prepare_drop_index had done
+ the check before we reach here. */
+
+ ut_a(new_index || !trx->check_foreigns);
foreign->foreign_index = new_index;
}
@@ -4943,8 +4973,8 @@ dict_close(void)
mem_free(dict_sys);
dict_sys = NULL;
- for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
- mutex_free(&dict_index_stat_mutex[i]);
+ for (i = 0; i < DICT_TABLE_STATS_LATCHES_SIZE; i++) {
+ rw_lock_free(&dict_table_stats_latches[i]);
}
}
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/innodb_plugin/dict/dict0load.c b/storage/innodb_plugin/dict/dict0load.c
index 3dcee46b92c..c3825902536 100644
--- a/storage/innodb_plugin/dict/dict0load.c
+++ b/storage/innodb_plugin/dict/dict0load.c
@@ -222,7 +222,8 @@ loop:
is no index */
if (dict_table_get_first_index(table)) {
- dict_update_statistics_low(table, TRUE);
+ dict_update_statistics(table, FALSE /* update
+ even if initialized */);
}
dict_table_print_low(table);
diff --git a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c
index 796fe921a7e..0f774dcaaa1 100644
--- a/storage/innodb_plugin/fil/fil0fil.c
+++ b/storage/innodb_plugin/fil/fil0fil.c
@@ -329,14 +329,15 @@ fil_get_space_id_for_table(
/*******************************************************************//**
Frees a space object from the tablespace memory cache. Closes the files in
the chain but does not delete them. There must not be any pending i/o's or
-flushes on the files. */
+flushes on the files.
+@return TRUE on success */
static
ibool
fil_space_free(
/*===========*/
- /* out: TRUE if success */
- ulint id, /* in: space id */
- ibool own_mutex);/* in: TRUE if own system->mutex */
+ ulint id, /* in: space id */
+ ibool x_latched); /* in: TRUE if caller has space->latch
+ in X mode */
/********************************************************************//**
Reads data from a space to a buffer. Remember that the possible incomplete
blocks at the end of file are ignored: they are not taken into account when
@@ -1123,6 +1124,7 @@ try_again:
space = fil_space_get_by_name(name);
if (UNIV_LIKELY_NULL(space)) {
+ ibool success;
ulint namesake_id;
ut_print_timestamp(stderr);
@@ -1161,9 +1163,10 @@ try_again:
namesake_id = space->id;
- mutex_exit(&fil_system->mutex);
+ success = fil_space_free(namesake_id, FALSE);
+ ut_a(success);
- fil_space_free(namesake_id, FALSE);
+ mutex_exit(&fil_system->mutex);
goto try_again;
}
@@ -1314,15 +1317,14 @@ fil_space_free(
/*===========*/
/* out: TRUE if success */
ulint id, /* in: space id */
- ibool own_mutex) /* in: TRUE if own system->mutex */
+ ibool x_latched) /* in: TRUE if caller has space->latch
+ in X mode */
{
fil_space_t* space;
fil_space_t* namespace;
fil_node_t* fil_node;
- if (!own_mutex) {
- mutex_enter(&fil_system->mutex);
- }
+ ut_ad(mutex_own(&fil_system->mutex));
space = fil_space_get_by_id(id);
@@ -1333,8 +1335,6 @@ fil_space_free(
" from the cache but\n"
"InnoDB: it is not there.\n", (ulong) id);
- mutex_exit(&fil_system->mutex);
-
return(FALSE);
}
@@ -1369,8 +1369,8 @@ fil_space_free(
ut_a(0 == UT_LIST_GET_LEN(space->chain));
- if (!own_mutex) {
- mutex_exit(&fil_system->mutex);
+ if (x_latched) {
+ rw_lock_x_unlock(&space->latch);
}
rw_lock_free(&(space->latch));
@@ -1615,25 +1615,27 @@ fil_close_all_files(void)
/*=====================*/
{
fil_space_t* space;
- fil_node_t* node;
mutex_enter(&fil_system->mutex);
space = UT_LIST_GET_FIRST(fil_system->space_list);
while (space != NULL) {
+ fil_node_t* node;
fil_space_t* prev_space = space;
- node = UT_LIST_GET_FIRST(space->chain);
+ for (node = UT_LIST_GET_FIRST(space->chain);
+ node != NULL;
+ node = UT_LIST_GET_NEXT(chain, node)) {
- while (node != NULL) {
if (node->open) {
fil_node_close_file(node, fil_system);
}
- node = UT_LIST_GET_NEXT(chain, node);
}
+
space = UT_LIST_GET_NEXT(space_list, space);
- fil_space_free(prev_space->id, TRUE);
+
+ fil_space_free(prev_space->id, FALSE);
}
mutex_exit(&fil_system->mutex);
@@ -2253,6 +2255,19 @@ try_again:
path = mem_strdup(space->name);
mutex_exit(&fil_system->mutex);
+
+ /* Important: We rely on the data dictionary mutex to ensure
+ that a race is not possible here. It should serialize the tablespace
+ drop/free. We acquire an X latch only to avoid a race condition
+ when accessing the tablespace instance via:
+
+ fsp_get_available_space_in_free_extents().
+
+ There our main motivation is to reduce the contention on the
+ dictionary mutex. */
+
+ rw_lock_x_lock(&space->latch);
+
#ifndef UNIV_HOTBACKUP
/* Invalidate in the buffer pool all pages belonging to the
tablespace. Since we have set space->is_being_deleted = TRUE, readahead
@@ -2265,7 +2280,11 @@ try_again:
#endif
/* printf("Deleting tablespace %s id %lu\n", space->name, id); */
- success = fil_space_free(id, FALSE);
+ mutex_enter(&fil_system->mutex);
+
+ success = fil_space_free(id, TRUE);
+
+ mutex_exit(&fil_system->mutex);
if (success) {
success = os_file_delete(path);
@@ -2273,6 +2292,8 @@ try_again:
if (!success) {
success = os_file_delete_if_exists(path);
}
+ } else {
+ rw_lock_x_unlock(&space->latch);
}
if (success) {
@@ -2300,6 +2321,31 @@ try_again:
return(FALSE);
}
+/*******************************************************************//**
+Returns TRUE if a single-table tablespace is being deleted.
+@return TRUE if being deleted */
+UNIV_INTERN
+ibool
+fil_tablespace_is_being_deleted(
+/*============================*/
+ ulint id) /*!< in: space id */
+{
+ fil_space_t* space;
+ ibool is_being_deleted;
+
+ mutex_enter(&fil_system->mutex);
+
+ space = fil_space_get_by_id(id);
+
+ ut_a(space != NULL);
+
+ is_being_deleted = space->is_being_deleted;
+
+ mutex_exit(&fil_system->mutex);
+
+ return(is_being_deleted);
+}
+
#ifndef UNIV_HOTBACKUP
/*******************************************************************//**
Discards a single-table tablespace. The tablespace must be cached in the
@@ -4763,7 +4809,7 @@ fil_page_get_type(
return(mach_read_from_2(page + FIL_PAGE_TYPE));
}
-/********************************************************************
+/****************************************************************//**
Initializes the tablespace memory cache. */
UNIV_INTERN
void
diff --git a/storage/innodb_plugin/fsp/fsp0fsp.c b/storage/innodb_plugin/fsp/fsp0fsp.c
index 2bae8481d20..e9d24b8fdf6 100644
--- a/storage/innodb_plugin/fsp/fsp0fsp.c
+++ b/storage/innodb_plugin/fsp/fsp0fsp.c
@@ -3102,13 +3102,63 @@ fsp_get_available_space_in_free_extents(
ut_ad(!mutex_own(&kernel_mutex));
+ /* The convoluted mutex acquire is to overcome latching order
+ issues: The problem is that the fil_mutex is at a lower level
+ than the tablespace latch and the buffer pool mutex. We have to
+ first prevent any operations on the file system by acquiring the
+ dictionary mutex. Then acquire the tablespace latch to obey the
+ latching order and then release the dictionary mutex. That way we
+ ensure that the tablespace instance can't be freed while we are
+ examining its contents (see fil_space_free()).
+
+ However, there is one further complication, we release the fil_mutex
+ when we need to invalidate the the pages in the buffer pool and we
+ reacquire the fil_mutex when deleting and freeing the tablespace
+ instance in fil0fil.c. Here we need to account for that situation
+ too. */
+
+ mutex_enter(&dict_sys->mutex);
+
+ /* At this stage there is no guarantee that the tablespace even
+ exists in the cache. */
+
+ if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) {
+
+ mutex_exit(&dict_sys->mutex);
+
+ return(ULLINT_UNDEFINED);
+ }
+
mtr_start(&mtr);
latch = fil_space_get_latch(space, &flags);
+
+ /* This should ensure that the tablespace instance can't be freed
+ by another thread. However, the tablespace pages can still be freed
+ from the buffer pool. We need to check for that again. */
+
zip_size = dict_table_flags_to_zip_size(flags);
mtr_x_lock(latch, &mtr);
+ mutex_exit(&dict_sys->mutex);
+
+ /* At this point it is possible for the tablespace to be deleted and
+ its pages removed from the buffer pool. We need to check for that
+ situation. However, the tablespace instance can't be deleted because
+ our latching above should ensure that. */
+
+ if (fil_tablespace_is_being_deleted(space)) {
+
+ mtr_commit(&mtr);
+
+ return(ULLINT_UNDEFINED);
+ }
+
+ /* From here on even if the user has dropped the tablespace, the
+ pages _must_ still exist in the buffer pool and the tablespace
+ instance _must_ be in the file system hash table. */
+
space_header = fsp_get_space_header(space, zip_size, &mtr);
size = mtr_read_ulint(space_header + FSP_SIZE, MLOG_4BYTES, &mtr);
@@ -3276,7 +3326,7 @@ fseg_free_page_low(
"InnoDB: database!\n", (ulong) page);
crash:
fputs("InnoDB: Please refer to\n"
- "InnoDB: " REFMAN "forcing-recovery.html\n"
+ "InnoDB: " REFMAN "forcing-innodb-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
ut_error;
}
diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
index 116ee12e76f..74dba9d2c31 100644
--- a/storage/innodb_plugin/handler/ha_innodb.cc
+++ b/storage/innodb_plugin/handler/ha_innodb.cc
@@ -6010,6 +6010,16 @@ create_table_def(
DBUG_RETURN(HA_ERR_GENERIC);
}
+ /* MySQL does the name length check. But we do additional check
+ on the name length here */
+ if (strlen(table_name) > MAX_FULL_NAME_LEN) {
+ push_warning_printf(
+ (THD*) trx->mysql_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TABLE_NAME,
+ "InnoDB: Table Name or Database Name is too long");
+ DBUG_RETURN(ER_TABLE_NAME);
+ }
+
n_cols = form->s->fields;
/* We pass 0 as the space id, and determine at a lower level the space
@@ -6292,6 +6302,60 @@ create_clustered_index_when_no_primary(
}
/*****************************************************************//**
+Return a display name for the row format
+@return row format name */
+UNIV_INTERN
+const char*
+get_row_format_name(
+/*================*/
+ enum row_type row_format) /*!< in: Row Format */
+{
+ switch (row_format) {
+ case ROW_TYPE_COMPACT:
+ return("COMPACT");
+ case ROW_TYPE_COMPRESSED:
+ return("COMPRESSED");
+ case ROW_TYPE_DYNAMIC:
+ return("DYNAMIC");
+ case ROW_TYPE_REDUNDANT:
+ return("REDUNDANT");
+ case ROW_TYPE_DEFAULT:
+ return("DEFAULT");
+ case ROW_TYPE_FIXED:
+ return("FIXED");
+ case ROW_TYPE_PAGE:
+ case ROW_TYPE_NOT_USED:
+ break;
+ }
+ return("NOT USED");
+}
+
+/** If file-per-table is missing, issue warning and set ret false */
+#define CHECK_ERROR_ROW_TYPE_NEEDS_FILE_PER_TABLE \
+ if (!srv_file_per_table) { \
+ push_warning_printf( \
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN, \
+ ER_ILLEGAL_HA_CREATE_OPTION, \
+ "InnoDB: ROW_FORMAT=%s requires" \
+ " innodb_file_per_table.", \
+ get_row_format_name(row_format)); \
+ ret = FALSE; \
+ }
+
+/** If file-format is Antelope, issue warning and set ret false */
+#define CHECK_ERROR_ROW_TYPE_NEEDS_GT_ANTELOPE \
+ if (srv_file_format < DICT_TF_FORMAT_ZIP) { \
+ push_warning_printf( \
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN, \
+ ER_ILLEGAL_HA_CREATE_OPTION, \
+ "InnoDB: ROW_FORMAT=%s requires" \
+ " innodb_file_format > Antelope.", \
+ get_row_format_name(row_format)); \
+ ret = FALSE; \
+ }
+
+
+/*****************************************************************//**
Validates the create options. We may build on this function
in future. For now, it checks two specifiers:
KEY_BLOCK_SIZE and ROW_FORMAT
@@ -6306,9 +6370,9 @@ create_options_are_valid(
columns and indexes */
HA_CREATE_INFO* create_info) /*!< in: create info. */
{
- ibool kbs_specified = FALSE;
+ ibool kbs_specified = FALSE;
ibool ret = TRUE;
-
+ enum row_type row_format = form->s->row_type;
ut_ad(thd != NULL);
@@ -6320,10 +6384,8 @@ create_options_are_valid(
ut_ad(form != NULL);
ut_ad(create_info != NULL);
- /* First check if KEY_BLOCK_SIZE was specified. */
- if (create_info->key_block_size
- || (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) {
-
+ /* First check if a non-zero KEY_BLOCK_SIZE was specified. */
+ if (create_info->key_block_size) {
kbs_specified = TRUE;
switch (create_info->key_block_size) {
case 1:
@@ -6331,127 +6393,71 @@ create_options_are_valid(
case 4:
case 8:
case 16:
- /* Valid value. */
- break;
- default:
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: invalid"
- " KEY_BLOCK_SIZE = %lu."
- " Valid values are"
- " [1, 2, 4, 8, 16]",
- create_info->key_block_size);
- ret = FALSE;
- }
- }
-
- /* If KEY_BLOCK_SIZE was specified, check for its
- dependencies. */
- if (kbs_specified && !srv_file_per_table) {
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: KEY_BLOCK_SIZE"
- " requires innodb_file_per_table.");
- ret = FALSE;
- }
-
- if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) {
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: KEY_BLOCK_SIZE"
- " requires innodb_file_format >"
- " Antelope.");
- ret = FALSE;
- }
-
- /* Now check for ROW_FORMAT specifier. */
- if (create_info->used_fields & HA_CREATE_USED_ROW_FORMAT) {
- switch (form->s->row_type) {
- const char* row_format_name;
- case ROW_TYPE_COMPRESSED:
- case ROW_TYPE_DYNAMIC:
- row_format_name
- = form->s->row_type == ROW_TYPE_COMPRESSED
- ? "COMPRESSED"
- : "DYNAMIC";
-
- /* These two ROW_FORMATs require srv_file_per_table
- and srv_file_format > Antelope */
+ /* Valid KEY_BLOCK_SIZE, check its dependencies. */
if (!srv_file_per_table) {
- push_warning_printf(
- thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: ROW_FORMAT=%s"
- " requires innodb_file_per_table.",
- row_format_name);
- ret = FALSE;
+ "InnoDB: KEY_BLOCK_SIZE requires"
+ " innodb_file_per_table.");
+ ret = FALSE;
}
-
if (srv_file_format < DICT_TF_FORMAT_ZIP) {
- push_warning_printf(
- thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: ROW_FORMAT=%s"
- " requires innodb_file_format >"
- " Antelope.",
- row_format_name);
+ "InnoDB: KEY_BLOCK_SIZE requires"
+ " innodb_file_format > Antelope.");
ret = FALSE;
}
-
- /* Cannot specify KEY_BLOCK_SIZE with
- ROW_FORMAT = DYNAMIC.
- However, we do allow COMPRESSED to be
- specified with KEY_BLOCK_SIZE. */
- if (kbs_specified
- && form->s->row_type == ROW_TYPE_DYNAMIC) {
- push_warning_printf(
- thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: cannot specify"
- " ROW_FORMAT = DYNAMIC with"
- " KEY_BLOCK_SIZE.");
- ret = FALSE;
- }
-
break;
-
- case ROW_TYPE_REDUNDANT:
- case ROW_TYPE_COMPACT:
- case ROW_TYPE_DEFAULT:
- /* Default is COMPACT. */
- row_format_name
- = form->s->row_type == ROW_TYPE_REDUNDANT
- ? "REDUNDANT"
- : "COMPACT";
-
- /* Cannot specify KEY_BLOCK_SIZE with these
- format specifiers. */
- if (kbs_specified) {
- push_warning_printf(
- thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: cannot specify"
- " ROW_FORMAT = %s with"
- " KEY_BLOCK_SIZE.",
- row_format_name);
- ret = FALSE;
- }
-
- break;
-
default:
- push_warning(thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: invalid ROW_FORMAT specifier.");
+ push_warning_printf(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION,
+ "InnoDB: invalid KEY_BLOCK_SIZE = %lu."
+ " Valid values are [1, 2, 4, 8, 16]",
+ create_info->key_block_size);
ret = FALSE;
-
+ break;
}
}
+
+ /* Check for a valid Innodb ROW_FORMAT specifier and
+ other incompatibilities. */
+ switch (row_format) {
+ case ROW_TYPE_COMPRESSED:
+ CHECK_ERROR_ROW_TYPE_NEEDS_FILE_PER_TABLE;
+ CHECK_ERROR_ROW_TYPE_NEEDS_GT_ANTELOPE;
+ break;
+ case ROW_TYPE_DYNAMIC:
+ CHECK_ERROR_ROW_TYPE_NEEDS_FILE_PER_TABLE;
+ CHECK_ERROR_ROW_TYPE_NEEDS_GT_ANTELOPE;
+ /* fall through since dynamic also shuns KBS */
+ case ROW_TYPE_COMPACT:
+ case ROW_TYPE_REDUNDANT:
+ if (kbs_specified) {
+ push_warning_printf(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION,
+ "InnoDB: cannot specify ROW_FORMAT = %s"
+ " with KEY_BLOCK_SIZE.",
+ get_row_format_name(row_format));
+ ret = FALSE;
+ }
+ break;
+ case ROW_TYPE_DEFAULT:
+ break;
+ case ROW_TYPE_FIXED:
+ case ROW_TYPE_PAGE:
+ case ROW_TYPE_NOT_USED:
+ push_warning(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION, \
+ "InnoDB: invalid ROW_FORMAT specifier.");
+ ret = FALSE;
+ break;
+ }
return(ret);
}
@@ -6500,7 +6506,7 @@ ha_innobase::create(
const ulint file_format = srv_file_format;
const char* stmt;
size_t stmt_len;
- enum row_type row_type;
+ enum row_type row_format;
DBUG_ENTER("ha_innobase::create");
@@ -6576,8 +6582,7 @@ ha_innobase::create(
goto cleanup;
}
- if (create_info->key_block_size
- || (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) {
+ if (create_info->key_block_size) {
/* Determine the page_zip.ssize corresponding to the
requested page size (key_block_size) in kilobytes. */
@@ -6598,40 +6603,40 @@ ha_innobase::create(
}
if (!srv_file_per_table) {
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: KEY_BLOCK_SIZE"
- " requires innodb_file_per_table.");
+ push_warning(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION,
+ "InnoDB: KEY_BLOCK_SIZE requires"
+ " innodb_file_per_table.");
flags = 0;
}
if (file_format < DICT_TF_FORMAT_ZIP) {
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: KEY_BLOCK_SIZE"
- " requires innodb_file_format >"
- " Antelope.");
+ push_warning(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION,
+ "InnoDB: KEY_BLOCK_SIZE requires"
+ " innodb_file_format > Antelope.");
flags = 0;
}
if (!flags) {
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: ignoring"
- " KEY_BLOCK_SIZE=%lu.",
- create_info->key_block_size);
+ push_warning_printf(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION,
+ "InnoDB: ignoring KEY_BLOCK_SIZE=%lu.",
+ create_info->key_block_size);
}
}
- row_type = form->s->row_type;
+ row_format = form->s->row_type;
if (flags) {
- /* if KEY_BLOCK_SIZE was specified on this statement and
- ROW_FORMAT was not, automatically change ROW_FORMAT to COMPRESSED.*/
- if ( (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)
- && !(create_info->used_fields & HA_CREATE_USED_ROW_FORMAT)) {
- row_type = ROW_TYPE_COMPRESSED;
- } else if (row_type != ROW_TYPE_COMPRESSED) {
+ /* if ROW_FORMAT is set to default,
+ automatically change it to COMPRESSED.*/
+ if (row_format == ROW_TYPE_DEFAULT) {
+ row_format = ROW_TYPE_COMPRESSED;
+ } else if (row_format != ROW_TYPE_COMPRESSED) {
/* ROW_FORMAT other than COMPRESSED
ignores KEY_BLOCK_SIZE. It does not
make sense to reject conflicting
@@ -6639,8 +6644,7 @@ ha_innobase::create(
such combinations can be obtained
with ALTER TABLE anyway. */
push_warning_printf(
- thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ignoring KEY_BLOCK_SIZE=%lu"
" unless ROW_FORMAT=COMPRESSED.",
@@ -6649,7 +6653,7 @@ ha_innobase::create(
}
} else {
/* flags == 0 means no KEY_BLOCK_SIZE.*/
- if (row_type == ROW_TYPE_COMPRESSED) {
+ if (row_format == ROW_TYPE_COMPRESSED) {
/* ROW_FORMAT=COMPRESSED without
KEY_BLOCK_SIZE implies half the
maximum KEY_BLOCK_SIZE. */
@@ -6664,49 +6668,40 @@ ha_innobase::create(
}
}
- switch (row_type) {
- const char* row_format_name;
+ switch (row_format) {
case ROW_TYPE_REDUNDANT:
break;
case ROW_TYPE_COMPRESSED:
case ROW_TYPE_DYNAMIC:
- row_format_name
- = row_type == ROW_TYPE_COMPRESSED
- ? "COMPRESSED"
- : "DYNAMIC";
-
if (!srv_file_per_table) {
push_warning_printf(
- thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: ROW_FORMAT=%s"
- " requires innodb_file_per_table.",
- row_format_name);
+ "InnoDB: ROW_FORMAT=%s requires"
+ " innodb_file_per_table.",
+ get_row_format_name(row_format));
} else if (file_format < DICT_TF_FORMAT_ZIP) {
push_warning_printf(
- thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: ROW_FORMAT=%s"
- " requires innodb_file_format >"
- " Antelope.",
- row_format_name);
+ "InnoDB: ROW_FORMAT=%s requires"
+ " innodb_file_format > Antelope.",
+ get_row_format_name(row_format));
} else {
flags |= DICT_TF_COMPACT
- | (DICT_TF_FORMAT_ZIP
- << DICT_TF_FORMAT_SHIFT);
+ | (DICT_TF_FORMAT_ZIP
+ << DICT_TF_FORMAT_SHIFT);
break;
}
/* fall through */
case ROW_TYPE_NOT_USED:
case ROW_TYPE_FIXED:
- default:
- push_warning(thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: assuming ROW_FORMAT=COMPACT.");
+ case ROW_TYPE_PAGE:
+ push_warning(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION,
+ "InnoDB: assuming ROW_FORMAT=COMPACT.");
case ROW_TYPE_DEFAULT:
case ROW_TYPE_COMPACT:
flags = DICT_TF_COMPACT;
@@ -6820,23 +6815,25 @@ ha_innobase::create(
setup at this stage and so we use thd. */
/* We need to copy the AUTOINC value from the old table if
- this is an ALTER TABLE or CREATE INDEX because CREATE INDEX
- does a table copy too. */
+ this is an ALTER|OPTIMIZE TABLE or CREATE INDEX because CREATE INDEX
+ does a table copy too. If query was one of :
+
+ CREATE TABLE ...AUTO_INCREMENT = x; or
+ ALTER TABLE...AUTO_INCREMENT = x; or
+ OPTIMIZE TABLE t; or
+ CREATE INDEX x on t(...);
+
+ Find out a table definition from the dictionary and get
+ the current value of the auto increment field. Set a new
+ value to the auto increment field if the value is greater
+ than the maximum value in the column. */
if (((create_info->used_fields & HA_CREATE_USED_AUTO)
|| thd_sql_command(thd) == SQLCOM_ALTER_TABLE
+ || thd_sql_command(thd) == SQLCOM_OPTIMIZE
|| thd_sql_command(thd) == SQLCOM_CREATE_INDEX)
&& create_info->auto_increment_value > 0) {
- /* Query was one of :
- CREATE TABLE ...AUTO_INCREMENT = x; or
- ALTER TABLE...AUTO_INCREMENT = x; or
- CREATE INDEX x on t(...);
- Find out a table definition from the dictionary and get
- the current value of the auto increment field. Set a new
- value to the auto increment field if the value is greater
- than the maximum value in the column. */
-
auto_inc_value = create_info->auto_increment_value;
dict_table_autoinc_lock(innobase_table);
@@ -7344,6 +7341,7 @@ ha_innobase::estimate_rows_upper_bound(void)
dict_index_t* index;
ulonglong estimate;
ulonglong local_data_file_length;
+ ulint stat_n_leaf_pages;
DBUG_ENTER("estimate_rows_upper_bound");
@@ -7363,10 +7361,12 @@ ha_innobase::estimate_rows_upper_bound(void)
index = dict_table_get_first_index(prebuilt->table);
- ut_a(index->stat_n_leaf_pages > 0);
+ stat_n_leaf_pages = index->stat_n_leaf_pages;
+
+ ut_a(stat_n_leaf_pages > 0);
local_data_file_length =
- ((ulonglong) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
+ ((ulonglong) stat_n_leaf_pages) * UNIV_PAGE_SIZE;
/* Calculate a minimum length for a clustered index record and from
@@ -7565,7 +7565,9 @@ ha_innobase::info_low(
prebuilt->trx->op_info = "updating table statistics";
- dict_update_statistics(ib_table);
+ dict_update_statistics(ib_table,
+ FALSE /* update even if stats
+ are initialized */);
prebuilt->trx->op_info = "returning various info to MySQL";
}
@@ -7584,6 +7586,9 @@ ha_innobase::info_low(
}
if (flag & HA_STATUS_VARIABLE) {
+
+ dict_table_stats_lock(ib_table, RW_S_LATCH);
+
n_rows = ib_table->stat_n_rows;
/* Because we do not protect stat_n_rows by any mutex in a
@@ -7633,6 +7638,8 @@ ha_innobase::info_low(
ib_table->stat_sum_of_other_index_sizes)
* UNIV_PAGE_SIZE;
+ dict_table_stats_unlock(ib_table, RW_S_LATCH);
+
/* Since fsp_get_available_space_in_free_extents() is
acquiring latches inside InnoDB, we do not call it if we
are asked by MySQL to avoid locking. Another reason to
@@ -7649,19 +7656,12 @@ ha_innobase::info_low(
innodb_crash_recovery is set to a high value. */
stats.delete_length = 0;
} else {
- /* lock the data dictionary to avoid races with
- ibd_file_missing and tablespace_discarded */
- row_mysql_lock_data_dictionary(prebuilt->trx);
+ ullint avail_space;
- /* ib_table->space must be an existent tablespace */
- if (!ib_table->ibd_file_missing
- && !ib_table->tablespace_discarded) {
-
- stats.delete_length =
- fsp_get_available_space_in_free_extents(
- ib_table->space) * 1024;
- } else {
+ avail_space = fsp_get_available_space_in_free_extents(
+ ib_table->space);
+ if (avail_space == ULLINT_UNDEFINED) {
THD* thd;
thd = ha_thd();
@@ -7678,9 +7678,9 @@ ha_innobase::info_low(
ib_table->name);
stats.delete_length = 0;
+ } else {
+ stats.delete_length = avail_space * 1024;
}
-
- row_mysql_unlock_data_dictionary(prebuilt->trx);
}
stats.check_time = 0;
@@ -7711,6 +7711,8 @@ ha_innobase::info_low(
table->s->keys);
}
+ dict_table_stats_lock(ib_table, RW_S_LATCH);
+
for (i = 0; i < table->s->keys; i++) {
ulong j;
/* We could get index quickly through internal
@@ -7748,8 +7750,6 @@ ha_innobase::info_low(
break;
}
- dict_index_stat_mutex_enter(index);
-
if (index->stat_n_diff_key_vals[j + 1] == 0) {
rec_per_key = stats.records;
@@ -7758,8 +7758,6 @@ ha_innobase::info_low(
index->stat_n_diff_key_vals[j + 1]);
}
- dict_index_stat_mutex_exit(index);
-
/* Since MySQL seems to favor table scans
too much over index searches, we pretend
index selectivity is 2 times better than
@@ -7776,6 +7774,8 @@ ha_innobase::info_low(
(ulong) rec_per_key;
}
}
+
+ dict_table_stats_unlock(ib_table, RW_S_LATCH);
}
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
diff --git a/storage/innodb_plugin/handler/handler0alter.cc b/storage/innodb_plugin/handler/handler0alter.cc
index e936bfafa0e..517445f7e69 100644
--- a/storage/innodb_plugin/handler/handler0alter.cc
+++ b/storage/innodb_plugin/handler/handler0alter.cc
@@ -1012,12 +1012,13 @@ ha_innobase::prepare_drop_index(
index->to_be_dropped = TRUE;
}
- /* If FOREIGN_KEY_CHECK = 1 you may not drop an index defined
+ /* If FOREIGN_KEY_CHECKS = 1 you may not drop an index defined
for a foreign key constraint because InnoDB requires that both
- tables contain indexes for the constraint. Note that CREATE
- INDEX id ON table does a CREATE INDEX and DROP INDEX, and we
- can ignore here foreign keys because a new index for the
- foreign key has already been created.
+ tables contain indexes for the constraint. Such index can
+ be dropped only if FOREIGN_KEY_CHECKS is set to 0.
+ Note that CREATE INDEX id ON table does a CREATE INDEX and
+ DROP INDEX, and we can ignore here foreign keys because a
+ new index for the foreign key has already been created.
We check for the foreign key constraints after marking the
candidate indexes for deletion, because when we check for an
diff --git a/storage/innodb_plugin/handler/i_s.cc b/storage/innodb_plugin/handler/i_s.cc
index 9ad2d656365..b0149967e9b 100644
--- a/storage/innodb_plugin/handler/i_s.cc
+++ b/storage/innodb_plugin/handler/i_s.cc
@@ -371,8 +371,16 @@ fill_innodb_trx_from_cache(
row->trx_mysql_thread_id));
/* trx_query */
- OK(field_store_string(fields[IDX_TRX_QUERY],
- row->trx_query));
+ if (row->trx_query) {
+ /* store will do appropriate character set
+ conversion check */
+ fields[IDX_TRX_QUERY]->store(
+ row->trx_query, strlen(row->trx_query),
+ row->trx_query_cs);
+ fields[IDX_TRX_QUERY]->set_notnull();
+ } else {
+ fields[IDX_TRX_QUERY]->set_null();
+ }
OK(schema_table_store_record(thd, table));
}
@@ -579,16 +587,7 @@ fill_innodb_locks_from_cache(
for (i = 0; i < rows_num; i++) {
i_s_locks_row_t* row;
-
- /* note that the decoded database or table name is
- never expected to be longer than NAME_LEN;
- NAME_LEN for database name
- 2 for surrounding quotes around database name
- NAME_LEN for table name
- 2 for surrounding quotes around table name
- 1 for the separating dot (.)
- 9 for the #mysql50# prefix */
- char buf[2 * NAME_LEN + 14];
+ char buf[MAX_FULL_NAME_LEN + 1];
const char* bufend;
char lock_trx_id[TRX_ID_MAX_LEN + 1];
diff --git a/storage/innodb_plugin/include/btr0btr.h b/storage/innodb_plugin/include/btr0btr.h
index 5e6a76c7d21..dde3a0bab69 100644
--- a/storage/innodb_plugin/include/btr0btr.h
+++ b/storage/innodb_plugin/include/btr0btr.h
@@ -94,26 +94,35 @@ btr_root_get(
Gets a buffer page and declares its latching order level. */
UNIV_INLINE
buf_block_t*
-btr_block_get(
-/*==========*/
- ulint space, /*!< in: space id */
- ulint zip_size, /*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
- ulint page_no, /*!< in: page number */
- ulint mode, /*!< in: latch mode */
- mtr_t* mtr); /*!< in: mtr */
-/**************************************************************//**
-Gets a buffer page and declares its latching order level. */
-UNIV_INLINE
-page_t*
-btr_page_get(
-/*=========*/
- ulint space, /*!< in: space id */
- ulint zip_size, /*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
- ulint page_no, /*!< in: page number */
- ulint mode, /*!< in: latch mode */
- mtr_t* mtr); /*!< in: mtr */
+btr_block_get_func(
+/*===============*/
+ ulint space, /*!< in: space id */
+ ulint zip_size, /*!< in: compressed page size in bytes
+ or 0 for uncompressed pages */
+ ulint page_no, /*!< in: page number */
+ ulint mode, /*!< in: latch mode */
+ const char* file, /*!< in: file name */
+ ulint line, /*!< in: line where called */
+ mtr_t* mtr) /*!< in/out: mtr */
+ __attribute__((nonnull));
+/** Gets a buffer page and declares its latching order level.
+@param space tablespace identifier
+@param zip_size compressed page size in bytes or 0 for uncompressed pages
+@param page_no page number
+@param mode latch mode
+@param mtr mini-transaction handle
+@return the block descriptor */
+# define btr_block_get(space,zip_size,page_no,mode,mtr) \
+ btr_block_get_func(space,zip_size,page_no,mode,__FILE__,__LINE__,mtr)
+/** Gets a buffer page and declares its latching order level.
+@param space tablespace identifier
+@param zip_size compressed page size in bytes or 0 for uncompressed pages
+@param page_no page number
+@param mode latch mode
+@param mtr mini-transaction handle
+@return the uncompressed page frame */
+# define btr_page_get(space,zip_size,page_no,mode,mtr) \
+ buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,mtr))
#endif /* !UNIV_HOTBACKUP */
/**************************************************************//**
Gets the index id field of a page.
diff --git a/storage/innodb_plugin/include/btr0btr.ic b/storage/innodb_plugin/include/btr0btr.ic
index 97944cc2e26..83eb3627abb 100644
--- a/storage/innodb_plugin/include/btr0btr.ic
+++ b/storage/innodb_plugin/include/btr0btr.ic
@@ -39,18 +39,21 @@ Created 6/2/1994 Heikki Tuuri
Gets a buffer page and declares its latching order level. */
UNIV_INLINE
buf_block_t*
-btr_block_get(
-/*==========*/
- ulint space, /*!< in: space id */
- ulint zip_size, /*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
- ulint page_no, /*!< in: page number */
- ulint mode, /*!< in: latch mode */
- mtr_t* mtr) /*!< in: mtr */
+btr_block_get_func(
+/*===============*/
+ ulint space, /*!< in: space id */
+ ulint zip_size, /*!< in: compressed page size in bytes
+ or 0 for uncompressed pages */
+ ulint page_no, /*!< in: page number */
+ ulint mode, /*!< in: latch mode */
+ const char* file, /*!< in: file name */
+ ulint line, /*!< in: line where called */
+ mtr_t* mtr) /*!< in/out: mtr */
{
buf_block_t* block;
- block = buf_page_get(space, zip_size, page_no, mode, mtr);
+ block = buf_page_get_gen(space, zip_size, page_no, mode,
+ NULL, BUF_GET, file, line, mtr);
if (mode != RW_NO_LATCH) {
@@ -61,23 +64,6 @@ btr_block_get(
}
/**************************************************************//**
-Gets a buffer page and declares its latching order level. */
-UNIV_INLINE
-page_t*
-btr_page_get(
-/*=========*/
- ulint space, /*!< in: space id */
- ulint zip_size, /*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
- ulint page_no, /*!< in: page number */
- ulint mode, /*!< in: latch mode */
- mtr_t* mtr) /*!< in: mtr */
-{
- return(buf_block_get_frame(btr_block_get(space, zip_size, page_no,
- mode, mtr)));
-}
-
-/**************************************************************//**
Sets the index id field of a page. */
UNIV_INLINE
void
diff --git a/storage/innodb_plugin/include/btr0cur.h b/storage/innodb_plugin/include/btr0cur.h
index 7f6bff11f84..b477ad0320a 100644
--- a/storage/innodb_plugin/include/btr0cur.h
+++ b/storage/innodb_plugin/include/btr0cur.h
@@ -332,10 +332,14 @@ ulint
btr_cur_del_mark_set_clust_rec(
/*===========================*/
ulint flags, /*!< in: undo logging and locking flags */
- btr_cur_t* cursor, /*!< in: cursor */
+ buf_block_t* block, /*!< in/out: buffer block of the record */
+ rec_t* rec, /*!< in/out: record */
+ dict_index_t* index, /*!< in: clustered index of the record */
+ const ulint* offsets,/*!< in: rec_get_offsets(rec) */
ibool val, /*!< in: value to set */
que_thr_t* thr, /*!< in: query thread */
- mtr_t* mtr); /*!< in: mtr */
+ mtr_t* mtr) /*!< in: mtr */
+ __attribute__((nonnull));
/***********************************************************//**
Sets a secondary index record delete mark to TRUE or FALSE.
@return DB_SUCCESS, DB_LOCK_WAIT, or error number */
@@ -481,46 +485,28 @@ btr_estimate_number_of_different_key_vals(
/*======================================*/
dict_index_t* index); /*!< in: index */
/*******************************************************************//**
-Marks not updated extern fields as not-owned by this record. The ownership
-is transferred to the updated record which is inserted elsewhere in the
+Marks non-updated off-page fields as disowned by this record. The ownership
+must be transferred to the updated record which is inserted elsewhere in the
index tree. In purge only the owner of externally stored field is allowed
-to free the field.
-@return TRUE if BLOB ownership was transferred */
+to free the field. */
UNIV_INTERN
-ibool
-btr_cur_mark_extern_inherited_fields(
-/*=================================*/
+void
+btr_cur_disown_inherited_fields(
+/*============================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
part will be updated, or NULL */
rec_t* rec, /*!< in/out: record in a clustered index */
dict_index_t* index, /*!< in: index of the page */
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
const upd_t* update, /*!< in: update vector */
- mtr_t* mtr); /*!< in: mtr, or NULL if not logged */
-/*******************************************************************//**
-The complement of the previous function: in an update entry may inherit
-some externally stored fields from a record. We must mark them as inherited
-in entry, so that they are not freed in a rollback. */
-UNIV_INTERN
-void
-btr_cur_mark_dtuple_inherited_extern(
-/*=================================*/
- dtuple_t* entry, /*!< in/out: updated entry to be
- inserted to clustered index */
- const upd_t* update); /*!< in: update vector */
-/*******************************************************************//**
-Marks all extern fields in a dtuple as owned by the record. */
-UNIV_INTERN
-void
-btr_cur_unmark_dtuple_extern_fields(
-/*================================*/
- dtuple_t* entry); /*!< in/out: clustered index entry */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((nonnull(2,3,4,5,6)));
/*******************************************************************//**
Stores the fields in big_rec_vec to the tablespace and puts pointers to
them in rec. The extern flags in rec will have to be set beforehand.
The fields are stored on pages allocated from leaf node
file segment of the index tree.
-@return DB_SUCCESS or error */
+@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN
ulint
btr_store_big_rec_extern_fields(
diff --git a/storage/innodb_plugin/include/data0data.h b/storage/innodb_plugin/include/data0data.h
index f9fce3f3657..cab8d790ac1 100644
--- a/storage/innodb_plugin/include/data0data.h
+++ b/storage/innodb_plugin/include/data0data.h
@@ -154,14 +154,19 @@ dfield_dup(
dfield_t* field, /*!< in/out: data field */
mem_heap_t* heap); /*!< in: memory heap where allocated */
/*********************************************************************//**
-Tests if data length and content is equal for two dfields.
-@return TRUE if equal */
+Tests if two data fields are equal.
+If len==0, tests the data length and content for equality.
+If len>0, tests the first len bytes of the content for equality.
+@return TRUE if both fields are NULL or if they are equal */
UNIV_INLINE
ibool
dfield_datas_are_binary_equal(
/*==========================*/
const dfield_t* field1, /*!< in: field */
- const dfield_t* field2);/*!< in: field */
+ const dfield_t* field2, /*!< in: field */
+ ulint len) /*!< in: maximum prefix to compare,
+ or 0 to compare the whole field length */
+ __attribute__((nonnull, warn_unused_result));
/*********************************************************************//**
Tests if dfield data length and content is equal to the given.
@return TRUE if equal */
diff --git a/storage/innodb_plugin/include/data0data.ic b/storage/innodb_plugin/include/data0data.ic
index da79aa33702..74e0f7d09a0 100644
--- a/storage/innodb_plugin/include/data0data.ic
+++ b/storage/innodb_plugin/include/data0data.ic
@@ -229,20 +229,30 @@ dfield_dup(
}
/*********************************************************************//**
-Tests if data length and content is equal for two dfields.
-@return TRUE if equal */
+Tests if two data fields are equal.
+If len==0, tests the data length and content for equality.
+If len>0, tests the first len bytes of the content for equality.
+@return TRUE if both fields are NULL or if they are equal */
UNIV_INLINE
ibool
dfield_datas_are_binary_equal(
/*==========================*/
const dfield_t* field1, /*!< in: field */
- const dfield_t* field2) /*!< in: field */
+ const dfield_t* field2, /*!< in: field */
+ ulint len) /*!< in: maximum prefix to compare,
+ or 0 to compare the whole field length */
{
- ulint len;
+ ulint len2 = len;
- len = field1->len;
+ if (field1->len == UNIV_SQL_NULL || len == 0 || field1->len < len) {
+ len = field1->len;
+ }
+
+ if (field2->len == UNIV_SQL_NULL || len2 == 0 || field2->len < len2) {
+ len2 = field2->len;
+ }
- return(len == field2->len
+ return(len == len2
&& (len == UNIV_SQL_NULL
|| !memcmp(field1->data, field2->data, len)));
}
diff --git a/storage/innodb_plugin/include/dict0dict.h b/storage/innodb_plugin/include/dict0dict.h
index 5ffa59538c8..fdb3bd5d50c 100644
--- a/storage/innodb_plugin/include/dict0dict.h
+++ b/storage/innodb_plugin/include/dict0dict.h
@@ -318,7 +318,8 @@ void
dict_table_replace_index_in_foreign_list(
/*=====================================*/
dict_table_t* table, /*!< in/out: table */
- dict_index_t* index); /*!< in: index to be replaced */
+ dict_index_t* index, /*!< in: index to be replaced */
+ const trx_t* trx); /*!< in: transaction handle */
/*********************************************************************//**
Checks if a index is defined for a foreign key constraint. Index is a part
of a foreign key constraint if the index is referenced by foreign key
@@ -1053,19 +1054,13 @@ Calculates new estimates for table and index statistics. The statistics
are used in query optimization. */
UNIV_INTERN
void
-dict_update_statistics_low(
-/*=======================*/
- dict_table_t* table, /*!< in/out: table */
- ibool has_dict_mutex);/*!< in: TRUE if the caller has the
- dictionary mutex */
-/*********************************************************************//**
-Calculates new estimates for table and index statistics. The statistics
-are used in query optimization. */
-UNIV_INTERN
-void
dict_update_statistics(
/*===================*/
- dict_table_t* table); /*!< in/out: table */
+ dict_table_t* table, /*!< in/out: table */
+ ibool only_calc_if_missing_stats);/*!< in: only
+ update/recalc the stats if they have
+ not been initialized yet, otherwise
+ do nothing */
/********************************************************************//**
Reserves the dictionary system mutex for MySQL. */
UNIV_INTERN
@@ -1079,21 +1074,25 @@ void
dict_mutex_exit_for_mysql(void);
/*===========================*/
/**********************************************************************//**
-Lock the appropriate mutex to protect index->stat_n_diff_key_vals[].
-index->id is used to pick the right mutex and it should not change
-before dict_index_stat_mutex_exit() is called on this index. */
+Lock the appropriate latch to protect a given table's statistics.
+table->id is used to pick the corresponding latch from a global array of
+latches. */
UNIV_INTERN
void
-dict_index_stat_mutex_enter(
-/*========================*/
- const dict_index_t* index); /*!< in: index */
+dict_table_stats_lock(
+/*==================*/
+ const dict_table_t* table, /*!< in: table */
+ ulint latch_mode); /*!< in: RW_S_LATCH or
+ RW_X_LATCH */
/**********************************************************************//**
-Unlock the appropriate mutex that protects index->stat_n_diff_key_vals[]. */
+Unlock the latch that has been locked by dict_table_stats_lock() */
UNIV_INTERN
void
-dict_index_stat_mutex_exit(
-/*=======================*/
- const dict_index_t* index); /*!< in: index */
+dict_table_stats_unlock(
+/*====================*/
+ const dict_table_t* table, /*!< in: table */
+ ulint latch_mode); /*!< in: RW_S_LATCH or
+ RW_X_LATCH */
/********************************************************************//**
Checks if the database name in two table names is the same.
@return TRUE if same db name */
diff --git a/storage/innodb_plugin/include/fil0fil.h b/storage/innodb_plugin/include/fil0fil.h
index c894875b352..f6a19646292 100644
--- a/storage/innodb_plugin/include/fil0fil.h
+++ b/storage/innodb_plugin/include/fil0fil.h
@@ -716,6 +716,14 @@ fil_page_get_type(
/*==============*/
const byte* page); /*!< in: file page */
+/*******************************************************************//**
+Returns TRUE if a single-table tablespace is being deleted.
+@return TRUE if being deleted */
+UNIV_INTERN
+ibool
+fil_tablespace_is_being_deleted(
+/*============================*/
+ ulint id); /*!< in: space id */
typedef struct fil_space_struct fil_space_t;
diff --git a/storage/innodb_plugin/include/row0ins.h b/storage/innodb_plugin/include/row0ins.h
index 9f93565ddb7..810973e61a7 100644
--- a/storage/innodb_plugin/include/row0ins.h
+++ b/storage/innodb_plugin/include/row0ins.h
@@ -84,9 +84,10 @@ ulint
row_ins_index_entry(
/*================*/
dict_index_t* index, /*!< in: index */
- dtuple_t* entry, /*!< in: index entry to insert */
+ dtuple_t* entry, /*!< in/out: index entry to insert */
ulint n_ext, /*!< in: number of externally stored columns */
- ibool foreign,/*!< in: TRUE=check foreign key constraints */
+ ibool foreign,/*!< in: TRUE=check foreign key constraints
+ (foreign=FALSE only during CREATE INDEX) */
que_thr_t* thr); /*!< in: query thread */
/***********************************************************//**
Inserts a row to a table. This is a high-level function used in
diff --git a/storage/innodb_plugin/include/row0upd.h b/storage/innodb_plugin/include/row0upd.h
index 4e2de9bd2ec..b61e6b6dca1 100644
--- a/storage/innodb_plugin/include/row0upd.h
+++ b/storage/innodb_plugin/include/row0upd.h
@@ -126,8 +126,8 @@ UNIV_INTERN
void
row_upd_index_entry_sys_field(
/*==========================*/
- const dtuple_t* entry, /*!< in: index entry, where the memory buffers
- for sys fields are already allocated:
+ dtuple_t* entry, /*!< in/out: index entry, where the memory
+ buffers for sys fields are already allocated:
the function just copies the new values to
them */
dict_index_t* index, /*!< in: clustered index */
@@ -286,10 +286,13 @@ row_upd_changes_ord_field_binary(
row and the data values in update are not
known when this function is called, e.g., at
compile time */
+ const row_ext_t*ext, /*!< NULL, or prefixes of the externally
+ stored columns in the old row */
dict_index_t* index, /*!< in: index of the record */
- const upd_t* update);/*!< in: update vector for the row; NOTE: the
+ const upd_t* update) /*!< in: update vector for the row; NOTE: the
field numbers in this MUST be clustered index
positions! */
+ __attribute__((nonnull(3,4), warn_unused_result));
/***********************************************************//**
Checks if an update vector changes an ordering field of an index record.
This function is fast if the update vector is short or the number of ordering
@@ -462,11 +465,16 @@ struct upd_node_struct{
#define UPD_NODE_INSERT_CLUSTERED 3 /* clustered index record should be
inserted, old record is already delete
marked */
-#define UPD_NODE_UPDATE_ALL_SEC 4 /* an ordering field of the clustered
+#define UPD_NODE_INSERT_BLOB 4 /* clustered index record should be
+ inserted, old record is already
+ delete-marked; non-updated BLOBs
+ should be inherited by the new record
+ and disowned by the old record */
+#define UPD_NODE_UPDATE_ALL_SEC 5 /* an ordering field of the clustered
index record was changed, or this is
a delete operation: should update
all the secondary index records */
-#define UPD_NODE_UPDATE_SOME_SEC 5 /* secondary index entries should be
+#define UPD_NODE_UPDATE_SOME_SEC 6 /* secondary index entries should be
looked at and updated if an ordering
field changed */
diff --git a/storage/innodb_plugin/include/trx0i_s.h b/storage/innodb_plugin/include/trx0i_s.h
index 7bd4e1b88c8..48d41038ea4 100644
--- a/storage/innodb_plugin/include/trx0i_s.h
+++ b/storage/innodb_plugin/include/trx0i_s.h
@@ -110,6 +110,8 @@ struct i_s_trx_row_struct {
/*!< thd_get_thread_id() */
const char* trx_query; /*!< MySQL statement being
executed in the transaction */
+ struct charset_info_st* trx_query_cs; /*!< charset encode the MySQL
+ statement */
};
/** This structure represents INFORMATION_SCHEMA.innodb_lock_waits row */
diff --git a/storage/innodb_plugin/include/univ.i b/storage/innodb_plugin/include/univ.i
index 0bb4b744d05..b721e0406a8 100644
--- a/storage/innodb_plugin/include/univ.i
+++ b/storage/innodb_plugin/include/univ.i
@@ -46,7 +46,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 1
#define INNODB_VERSION_MINOR 0
-#define INNODB_VERSION_BUGFIX 13
+#define INNODB_VERSION_BUGFIX 15
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
@@ -296,6 +296,18 @@ number does not include a terminating '\0'. InnoDB probably can handle
longer names internally */
#define MAX_TABLE_NAME_LEN 192
+/* The maximum length of a database name. Like MAX_TABLE_NAME_LEN this is
+the MySQL's NAME_LEN, see check_and_convert_db_name(). */
+#define MAX_DATABASE_NAME_LEN MAX_TABLE_NAME_LEN
+
+/* MAX_FULL_NAME_LEN defines the full name path including the
+database name and table name. In addition, 14 bytes is added for:
+ 2 for surrounding quotes around table name
+ 1 for the separating dot (.)
+ 9 for the #mysql50# prefix */
+#define MAX_FULL_NAME_LEN \
+ (MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN + 14)
+
/*
UNIVERSAL TYPE DEFINITIONS
==========================
@@ -360,6 +372,9 @@ typedef unsigned long long int ullint;
/* Maximum value for ib_uint64_t */
#define IB_ULONGLONG_MAX ((ib_uint64_t) (~0ULL))
+/* THe 'undefined' value for ullint */
+#define ULLINT_UNDEFINED ((ullint)(-1))
+
/* This 'ibool' type is used within Innobase. Remember that different included
headers may define 'bool' differently. Do not assume that 'bool' is a ulint! */
#define ibool ulint
diff --git a/storage/innodb_plugin/include/ut0vec.h b/storage/innodb_plugin/include/ut0vec.h
index a770f671cfc..0f8b955b098 100644
--- a/storage/innodb_plugin/include/ut0vec.h
+++ b/storage/innodb_plugin/include/ut0vec.h
@@ -94,6 +94,25 @@ ib_vector_get(
ulint n); /*!< in: element index to get */
/****************************************************************//**
+Get last element. The vector must not be empty.
+@return last element */
+UNIV_INLINE
+void*
+ib_vector_get_last(
+/*===============*/
+ ib_vector_t* vec); /*!< in: vector */
+
+/****************************************************************//**
+Set the n'th element. */
+UNIV_INLINE
+void
+ib_vector_set(
+/*==========*/
+ ib_vector_t* vec, /*!< in/out: vector */
+ ulint n, /*!< in: element index to set */
+ void* elem); /*!< in: data element */
+
+/****************************************************************//**
Remove the last element from the vector. */
UNIV_INLINE
void*
diff --git a/storage/innodb_plugin/include/ut0vec.ic b/storage/innodb_plugin/include/ut0vec.ic
index 02e881f9bca..34c858868ce 100644
--- a/storage/innodb_plugin/include/ut0vec.ic
+++ b/storage/innodb_plugin/include/ut0vec.ic
@@ -51,6 +51,35 @@ ib_vector_get(
}
/****************************************************************//**
+Get last element. The vector must not be empty.
+@return last element */
+UNIV_INLINE
+void*
+ib_vector_get_last(
+/*===============*/
+ ib_vector_t* vec) /*!< in: vector */
+{
+ ut_a(vec->used > 0);
+
+ return(vec->data[vec->used - 1]);
+}
+
+/****************************************************************//**
+Set the n'th element. */
+UNIV_INLINE
+void
+ib_vector_set(
+/*==========*/
+ ib_vector_t* vec, /*!< in/out: vector */
+ ulint n, /*!< in: element index to set */
+ void* elem) /*!< in: data element */
+{
+ ut_a(n < vec->used);
+
+ vec->data[n] = elem;
+}
+
+/****************************************************************//**
Remove the last element from the vector.
@return last vector element */
UNIV_INLINE
diff --git a/storage/innodb_plugin/lock/lock0lock.c b/storage/innodb_plugin/lock/lock0lock.c
index 77d69d11a2d..c8bbc5c02bd 100644
--- a/storage/innodb_plugin/lock/lock0lock.c
+++ b/storage/innodb_plugin/lock/lock0lock.c
@@ -3625,6 +3625,80 @@ lock_table_create(
}
/*************************************************************//**
+Pops autoinc lock requests from the transaction's autoinc_locks. We
+handle the case where there are gaps in the array and they need to
+be popped off the stack. */
+UNIV_INLINE
+void
+lock_table_pop_autoinc_locks(
+/*=========================*/
+ trx_t* trx) /*!< in/out: transaction that owns the AUTOINC locks */
+{
+ ut_ad(mutex_own(&kernel_mutex));
+ ut_ad(!ib_vector_is_empty(trx->autoinc_locks));
+
+ /* Skip any gaps, gaps are NULL lock entries in the
+ trx->autoinc_locks vector. */
+
+ do {
+ ib_vector_pop(trx->autoinc_locks);
+
+ if (ib_vector_is_empty(trx->autoinc_locks)) {
+ return;
+ }
+
+ } while (ib_vector_get_last(trx->autoinc_locks) == NULL);
+}
+
+/*************************************************************//**
+Removes an autoinc lock request from the transaction's autoinc_locks. */
+UNIV_INLINE
+void
+lock_table_remove_autoinc_lock(
+/*===========================*/
+ lock_t* lock, /*!< in: table lock */
+ trx_t* trx) /*!< in/out: transaction that owns the lock */
+{
+ lock_t* autoinc_lock;
+ lint i = ib_vector_size(trx->autoinc_locks) - 1;
+
+ ut_ad(mutex_own(&kernel_mutex));
+ ut_ad(lock_get_mode(lock) == LOCK_AUTO_INC);
+ ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
+ ut_ad(!ib_vector_is_empty(trx->autoinc_locks));
+
+ /* With stored functions and procedures the user may drop
+ a table within the same "statement". This special case has
+ to be handled by deleting only those AUTOINC locks that were
+ held by the table being dropped. */
+
+ autoinc_lock = ib_vector_get(trx->autoinc_locks, i);
+
+ /* This is the default fast case. */
+
+ if (autoinc_lock == lock) {
+ lock_table_pop_autoinc_locks(trx);
+ } else {
+ /* The last element should never be NULL */
+ ut_a(autoinc_lock != NULL);
+
+ /* Handle freeing the locks from within the stack. */
+
+ while (--i >= 0) {
+ autoinc_lock = ib_vector_get(trx->autoinc_locks, i);
+
+ if (UNIV_LIKELY(autoinc_lock == lock)) {
+ ib_vector_set(trx->autoinc_locks, i, NULL);
+ return;
+ }
+ }
+
+ /* Must find the autoinc lock. */
+ ut_error;
+ }
+}
+
+/*************************************************************//**
Removes a table lock request from the queue and the trx list of locks;
this is a low-level function which does NOT check if waiting requests
can now be granted. */
@@ -3663,10 +3737,8 @@ lock_table_remove_low(
if (!lock_get_wait(lock)
&& !ib_vector_is_empty(trx->autoinc_locks)) {
- lock_t* autoinc_lock;
- autoinc_lock = ib_vector_pop(trx->autoinc_locks);
- ut_a(autoinc_lock == lock);
+ lock_table_remove_autoinc_lock(lock, trx);
}
ut_a(table->n_waiting_or_granted_auto_inc_locks > 0);
diff --git a/storage/innodb_plugin/log/log0recv.c b/storage/innodb_plugin/log/log0recv.c
index c1d12dad413..1591bb02ec2 100644
--- a/storage/innodb_plugin/log/log0recv.c
+++ b/storage/innodb_plugin/log/log0recv.c
@@ -2188,7 +2188,7 @@ recv_report_corrupt_log(
"InnoDB: far enough in recovery! Please run CHECK TABLE\n"
"InnoDB: on your InnoDB tables to check that they are ok!\n"
"InnoDB: If mysqld crashes after this recovery, look at\n"
- "InnoDB: " REFMAN "forcing-recovery.html\n"
+ "InnoDB: " REFMAN "forcing-innodb-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
fflush(stderr);
diff --git a/storage/innodb_plugin/plug.in b/storage/innodb_plugin/plug.in
index c99703415f9..ebaa3f574a0 100644
--- a/storage/innodb_plugin/plug.in
+++ b/storage/innodb_plugin/plug.in
@@ -17,6 +17,9 @@
MYSQL_STORAGE_ENGINE(innodb_plugin,, [InnoDB Storage Engine],
[Transactional Tables using InnoDB], [])
MYSQL_PLUGIN_DIRECTORY(innodb_plugin, [storage/innodb_plugin])
+# Enable if you know what you are doing (trying to link both InnoDB and
+# InnoDB Plugin statically into MySQL does not work).
+#MYSQL_PLUGIN_STATIC(innodb_plugin, [libinnobase.a])
MYSQL_PLUGIN_DYNAMIC(innodb_plugin, [ha_innodb_plugin.la])
MYSQL_PLUGIN_ACTIONS(innodb_plugin, [
AC_CHECK_HEADERS(sched.h)
@@ -136,17 +139,24 @@ MYSQL_PLUGIN_ACTIONS(innodb_plugin, [
)
AC_MSG_CHECKING(whether Solaris libc atomic functions are available)
- # either define HAVE_IB_SOLARIS_ATOMICS or not
- AC_CHECK_FUNCS(atomic_cas_ulong \
+ # Define HAVE_IB_SOLARIS_ATOMICS if _all_ of the following
+ # functions are present.
+ AC_CHECK_FUNCS(atomic_add_long_nv \
atomic_cas_32 \
atomic_cas_64 \
- atomic_add_long_nv \
- atomic_swap_uchar,
-
- AC_DEFINE([HAVE_IB_SOLARIS_ATOMICS], [1],
- [Define to 1 if Solaris libc atomic functions \
- are available])
- )
+ atomic_cas_ulong \
+ atomic_swap_uchar)
+
+ if test "${ac_cv_func_atomic_add_long_nv}" = "yes" -a \
+ "${ac_cv_func_atomic_cas_32}" = "yes" -a \
+ "${ac_cv_func_atomic_cas_64}" = "yes" -a \
+ "${ac_cv_func_atomic_cas_ulong}" = "yes" -a \
+ "${ac_cv_func_atomic_swap_uchar}" = "yes" ; then
+
+ AC_DEFINE([HAVE_IB_SOLARIS_ATOMICS], [1],
+ [Define to 1 if Solaris libc atomic functions are available]
+ )
+ fi
AC_MSG_CHECKING(whether pthread_t can be used by Solaris libc atomic functions)
# either define HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS or not
diff --git a/storage/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c
index a193bf21f7c..298c601c7e3 100644
--- a/storage/innodb_plugin/row/row0ins.c
+++ b/storage/innodb_plugin/row/row0ins.c
@@ -1781,7 +1781,7 @@ ulint
row_ins_duplicate_error_in_clust(
/*=============================*/
btr_cur_t* cursor, /*!< in: B-tree cursor */
- dtuple_t* entry, /*!< in: entry to insert */
+ const dtuple_t* entry, /*!< in: entry to insert */
que_thr_t* thr, /*!< in: query thread */
mtr_t* mtr) /*!< in: mtr */
{
@@ -1977,7 +1977,7 @@ row_ins_index_entry_low(
depending on whether we wish optimistic or
pessimistic descent down the index tree */
dict_index_t* index, /*!< in: index */
- dtuple_t* entry, /*!< in: index entry to insert */
+ dtuple_t* entry, /*!< in/out: index entry to insert */
ulint n_ext, /*!< in: number of externally stored columns */
que_thr_t* thr) /*!< in: query thread */
{
@@ -2158,9 +2158,10 @@ ulint
row_ins_index_entry(
/*================*/
dict_index_t* index, /*!< in: index */
- dtuple_t* entry, /*!< in: index entry to insert */
+ dtuple_t* entry, /*!< in/out: index entry to insert */
ulint n_ext, /*!< in: number of externally stored columns */
- ibool foreign,/*!< in: TRUE=check foreign key constraints */
+ ibool foreign,/*!< in: TRUE=check foreign key constraints
+ (foreign=FALSE only during CREATE INDEX) */
que_thr_t* thr) /*!< in: query thread */
{
ulint err;
diff --git a/storage/innodb_plugin/row/row0merge.c b/storage/innodb_plugin/row/row0merge.c
index 05d77ad7f19..647d0031635 100644
--- a/storage/innodb_plugin/row/row0merge.c
+++ b/storage/innodb_plugin/row/row0merge.c
@@ -2043,7 +2043,7 @@ row_merge_drop_index(
/* Replace this index with another equivalent index for all
foreign key constraints on this table where this index is used */
- dict_table_replace_index_in_foreign_list(table, index);
+ dict_table_replace_index_in_foreign_list(table, index, trx);
dict_index_remove_from_cache(table, index);
trx->op_info = "";
@@ -2341,7 +2341,7 @@ row_merge_rename_tables(
{
ulint err = DB_ERROR;
pars_info_t* info;
- char old_name[MAX_TABLE_NAME_LEN + 1];
+ char old_name[MAX_FULL_NAME_LEN + 1];
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_ad(old_table != new_table);
@@ -2356,7 +2356,7 @@ row_merge_rename_tables(
ut_print_timestamp(stderr);
fprintf(stderr, "InnoDB: too long table name: '%s', "
"max length is %d\n", old_table->name,
- MAX_TABLE_NAME_LEN);
+ MAX_FULL_NAME_LEN);
ut_error;
}
diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c
index 9e8d0a884f4..c4911400cee 100644
--- a/storage/innodb_plugin/row/row0mysql.c
+++ b/storage/innodb_plugin/row/row0mysql.c
@@ -573,7 +573,7 @@ handle_new_error:
"InnoDB: If the mysqld server crashes"
" after the startup or when\n"
"InnoDB: you dump the tables, look at\n"
- "InnoDB: " REFMAN "forcing-recovery.html"
+ "InnoDB: " REFMAN "forcing-innodb-recovery.html"
" for help.\n", stderr);
break;
case DB_FOREIGN_EXCEED_MAX_CASCADE:
@@ -871,7 +871,8 @@ row_update_statistics_if_needed(
if (counter > 2000000000
|| ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) {
- dict_update_statistics(table);
+ dict_update_statistics(table, FALSE /* update even if stats
+ are initialized */);
}
}
@@ -2964,7 +2965,8 @@ next_rec:
dict_table_autoinc_lock(table);
dict_table_autoinc_initialize(table, 1);
dict_table_autoinc_unlock(table);
- dict_update_statistics(table);
+ dict_update_statistics(table, FALSE /* update even if stats are
+ initialized */);
trx_commit_for_mysql(trx);
diff --git a/storage/innodb_plugin/row/row0purge.c b/storage/innodb_plugin/row/row0purge.c
index 31b255cf2d4..8bf2ae0f458 100644
--- a/storage/innodb_plugin/row/row0purge.c
+++ b/storage/innodb_plugin/row/row0purge.c
@@ -413,7 +413,7 @@ row_purge_upd_exist_or_extern(
while (node->index != NULL) {
index = node->index;
- if (row_upd_changes_ord_field_binary(NULL, node->index,
+ if (row_upd_changes_ord_field_binary(NULL, NULL, node->index,
node->update)) {
/* Build the older version of the index entry */
entry = row_build_index_entry(node->row, NULL,
diff --git a/storage/innodb_plugin/row/row0sel.c b/storage/innodb_plugin/row/row0sel.c
index ac78a95839c..423ddfade22 100644
--- a/storage/innodb_plugin/row/row0sel.c
+++ b/storage/innodb_plugin/row/row0sel.c
@@ -106,6 +106,18 @@ row_sel_sec_rec_is_for_blob(
ulint len;
byte buf[DICT_MAX_INDEX_COL_LEN];
+ ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE);
+
+ if (UNIV_UNLIKELY
+ (!memcmp(clust_field + clust_len - BTR_EXTERN_FIELD_REF_SIZE,
+ field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE))) {
+ /* The externally stored field was not written yet.
+ This record should only be seen by
+ recv_recovery_rollback_active() or any
+ TRX_ISO_READ_UNCOMMITTED transactions. */
+ return(FALSE);
+ }
+
len = btr_copy_externally_stored_field_prefix(buf, sizeof buf,
zip_size,
clust_field, clust_len);
diff --git a/storage/innodb_plugin/row/row0umod.c b/storage/innodb_plugin/row/row0umod.c
index 5998dadd16d..562f8093c38 100644
--- a/storage/innodb_plugin/row/row0umod.c
+++ b/storage/innodb_plugin/row/row0umod.c
@@ -668,19 +668,18 @@ row_undo_mod_upd_exist_sec(
while (node->index != NULL) {
index = node->index;
- if (row_upd_changes_ord_field_binary(node->row, node->index,
- node->update)) {
+ if (row_upd_changes_ord_field_binary(
+ node->row, node->ext, node->index, node->update)) {
/* Build the newest version of the index entry */
entry = row_build_index_entry(node->row, node->ext,
index, heap);
if (UNIV_UNLIKELY(!entry)) {
/* The server must have crashed in
- row_upd_clust_rec_by_insert(), in
- row_ins_index_entry_low() before
- btr_store_big_rec_extern_fields()
- has written the externally stored columns
- (BLOBs) of the new clustered index entry. */
+ row_upd_clust_rec_by_insert() before
+ the updated externally stored columns (BLOBs)
+ of the new clustered index entry were
+ written. */
/* The table must be in DYNAMIC or COMPRESSED
format. REDUNDANT and COMPACT formats
diff --git a/storage/innodb_plugin/row/row0upd.c b/storage/innodb_plugin/row/row0upd.c
index 444003ba3f0..e1c78949603 100644
--- a/storage/innodb_plugin/row/row0upd.c
+++ b/storage/innodb_plugin/row/row0upd.c
@@ -371,8 +371,8 @@ UNIV_INTERN
void
row_upd_index_entry_sys_field(
/*==========================*/
- const dtuple_t* entry, /*!< in: index entry, where the memory buffers
- for sys fields are already allocated:
+ dtuple_t* entry, /*!< in/out: index entry, where the memory
+ buffers for sys fields are already allocated:
the function just copies the new values to
them */
dict_index_t* index, /*!< in: clustered index */
@@ -1198,20 +1198,21 @@ row_upd_changes_ord_field_binary(
row and the data values in update are not
known when this function is called, e.g., at
compile time */
+ const row_ext_t*ext, /*!< NULL, or prefixes of the externally
+ stored columns in the old row */
dict_index_t* index, /*!< in: index of the record */
const upd_t* update) /*!< in: update vector for the row; NOTE: the
field numbers in this MUST be clustered index
positions! */
{
- ulint n_unique;
- ulint n_upd_fields;
- ulint i, j;
- dict_index_t* clust_index;
+ ulint n_unique;
+ ulint i;
+ const dict_index_t* clust_index;
- ut_ad(update && index);
+ ut_ad(update);
+ ut_ad(index);
n_unique = dict_index_get_n_unique(index);
- n_upd_fields = upd_get_n_fields(update);
clust_index = dict_table_get_first_index(index->table);
@@ -1219,33 +1220,72 @@ row_upd_changes_ord_field_binary(
const dict_field_t* ind_field;
const dict_col_t* col;
- ulint col_pos;
ulint col_no;
+ const upd_field_t* upd_field;
+ const dfield_t* dfield;
+ dfield_t dfield_ext;
+ ulint dfield_len= 0;
+ const byte* buf;
ind_field = dict_index_get_nth_field(index, i);
col = dict_field_get_col(ind_field);
- col_pos = dict_col_get_clust_pos(col, clust_index);
col_no = dict_col_get_no(col);
- for (j = 0; j < n_upd_fields; j++) {
+ upd_field = upd_get_field_by_field_no(
+ update, dict_col_get_clust_pos(col, clust_index));
- const upd_field_t* upd_field
- = upd_get_nth_field(update, j);
+ if (upd_field == NULL) {
+ continue;
+ }
+
+ if (row == NULL) {
+ ut_ad(ext == NULL);
+ return(TRUE);
+ }
- /* Note that if the index field is a column prefix
- then it may be that row does not contain an externally
- stored part of the column value, and we cannot compare
- the datas */
+ dfield = dtuple_get_nth_field(row, col_no);
- if (col_pos == upd_field->field_no
- && (row == NULL
- || ind_field->prefix_len > 0
- || !dfield_datas_are_binary_equal(
- dtuple_get_nth_field(row, col_no),
- &(upd_field->new_val)))) {
+ /* This treatment of column prefix indexes is loosely
+ based on row_build_index_entry(). */
- return(TRUE);
+ if (UNIV_LIKELY(ind_field->prefix_len == 0)
+ || dfield_is_null(dfield)) {
+ /* do nothing special */
+ } else if (UNIV_LIKELY_NULL(ext)) {
+ /* See if the column is stored externally. */
+ buf = row_ext_lookup(ext, col_no, &dfield_len);
+
+ ut_ad(col->ord_part);
+
+ if (UNIV_LIKELY_NULL(buf)) {
+ if (UNIV_UNLIKELY(buf == field_ref_zero)) {
+ /* This should never happen, but
+ we try to fail safe here. */
+ ut_ad(0);
+ return(TRUE);
+ }
+
+ goto copy_dfield;
}
+ } else if (dfield_is_ext(dfield)) {
+ dfield_len = dfield_get_len(dfield);
+ ut_a(dfield_len > BTR_EXTERN_FIELD_REF_SIZE);
+ dfield_len -= BTR_EXTERN_FIELD_REF_SIZE;
+ ut_a(dict_index_is_clust(index)
+ || ind_field->prefix_len <= dfield_len);
+ buf = dfield_get_data(dfield);
+copy_dfield:
+ ut_a(dfield_len > 0);
+ dfield_copy(&dfield_ext, dfield);
+ dfield_set_data(&dfield_ext, buf, dfield_len);
+ dfield = &dfield_ext;
+ }
+
+ if (!dfield_datas_are_binary_equal(
+ dfield, &upd_field->new_val,
+ ind_field->prefix_len)) {
+
+ return(TRUE);
}
}
@@ -1329,7 +1369,7 @@ row_upd_changes_first_fields_binary(
if (col_pos == upd_field->field_no
&& !dfield_datas_are_binary_equal(
dtuple_get_nth_field(entry, i),
- &(upd_field->new_val))) {
+ &upd_field->new_val, 0)) {
return(TRUE);
}
@@ -1568,14 +1608,99 @@ row_upd_sec_step(
ut_ad(!dict_index_is_clust(node->index));
if (node->state == UPD_NODE_UPDATE_ALL_SEC
- || row_upd_changes_ord_field_binary(node->row, node->index,
- node->update)) {
+ || row_upd_changes_ord_field_binary(node->row, node->ext,
+ node->index, node->update)) {
return(row_upd_sec_index_entry(node, thr));
}
return(DB_SUCCESS);
}
+#ifdef UNIV_DEBUG
+# define row_upd_clust_rec_by_insert_inherit(rec,offsets,entry,update) \
+ row_upd_clust_rec_by_insert_inherit_func(rec,offsets,entry,update)
+#else /* UNIV_DEBUG */
+# define row_upd_clust_rec_by_insert_inherit(rec,offsets,entry,update) \
+ row_upd_clust_rec_by_insert_inherit_func(entry,update)
+#endif /* UNIV_DEBUG */
+/*******************************************************************//**
+Mark non-updated off-page columns inherited when the primary key is
+updated. We must mark them as inherited in entry, so that they are not
+freed in a rollback. A limited version of this function used to be
+called btr_cur_mark_dtuple_inherited_extern().
+@return TRUE if any columns were inherited */
+static __attribute__((warn_unused_result))
+ibool
+row_upd_clust_rec_by_insert_inherit_func(
+/*=====================================*/
+#ifdef UNIV_DEBUG
+ const rec_t* rec, /*!< in: old record, or NULL */
+ const ulint* offsets,/*!< in: rec_get_offsets(rec), or NULL */
+#endif /* UNIV_DEBUG */
+ dtuple_t* entry, /*!< in/out: updated entry to be
+ inserted into the clustered index */
+ const upd_t* update) /*!< in: update vector */
+{
+ ibool inherit = FALSE;
+ ulint i;
+
+ ut_ad(!rec == !offsets);
+ ut_ad(!rec || rec_offs_any_extern(offsets));
+
+ for (i = 0; i < dtuple_get_n_fields(entry); i++) {
+ dfield_t* dfield = dtuple_get_nth_field(entry, i);
+ byte* data;
+ ulint len;
+
+ ut_ad(!offsets
+ || !rec_offs_nth_extern(offsets, i)
+ == !dfield_is_ext(dfield)
+ || upd_get_field_by_field_no(update, i));
+ if (!dfield_is_ext(dfield)
+ || upd_get_field_by_field_no(update, i)) {
+ continue;
+ }
+
+#ifdef UNIV_DEBUG
+ if (UNIV_LIKELY(rec != NULL)) {
+ const byte* rec_data
+ = rec_get_nth_field(rec, offsets, i, &len);
+ ut_ad(len == dfield_get_len(dfield));
+ ut_ad(len != UNIV_SQL_NULL);
+ ut_ad(len >= BTR_EXTERN_FIELD_REF_SIZE);
+
+ rec_data += len - BTR_EXTERN_FIELD_REF_SIZE;
+
+ /* The pointer must not be zero. */
+ ut_ad(memcmp(rec_data, field_ref_zero,
+ BTR_EXTERN_FIELD_REF_SIZE));
+ /* The BLOB must be owned. */
+ ut_ad(!(rec_data[BTR_EXTERN_LEN]
+ & BTR_EXTERN_OWNER_FLAG));
+ }
+#endif /* UNIV_DEBUG */
+
+ len = dfield_get_len(dfield);
+ ut_a(len != UNIV_SQL_NULL);
+ ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
+ data = dfield_get_data(dfield);
+ data += len - BTR_EXTERN_FIELD_REF_SIZE;
+ /* The pointer must not be zero. */
+ ut_a(memcmp(data, field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE));
+ /* The BLOB must be owned. */
+ ut_a(!(data[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
+
+ data[BTR_EXTERN_LEN] |= BTR_EXTERN_INHERITED_FLAG;
+ /* The BTR_EXTERN_INHERITED_FLAG only matters in
+ rollback. Purge will always free the extern fields of
+ a delete-marked row. */
+
+ inherit = TRUE;
+ }
+
+ return(inherit);
+}
+
/***********************************************************//**
Marks the clustered index record deleted and inserts the updated version
of the record to the index. This function should be used when the ordering
@@ -1587,21 +1712,23 @@ static
ulint
row_upd_clust_rec_by_insert(
/*========================*/
- upd_node_t* node, /*!< in: row update node */
+ upd_node_t* node, /*!< in/out: row update node */
dict_index_t* index, /*!< in: clustered index of the record */
que_thr_t* thr, /*!< in: query thread */
ibool check_ref,/*!< in: TRUE if index may be referenced in
a foreign key constraint */
- mtr_t* mtr) /*!< in: mtr; gets committed here */
+ mtr_t* mtr) /*!< in/out: mtr; gets committed here */
{
- mem_heap_t* heap = NULL;
+ mem_heap_t* heap;
btr_pcur_t* pcur;
btr_cur_t* btr_cur;
trx_t* trx;
dict_table_t* table;
dtuple_t* entry;
ulint err;
- ibool change_ownership = FALSE;
+ ibool change_ownership = FALSE;
+ rec_t* rec;
+ ulint* offsets = NULL;
ut_ad(node);
ut_ad(dict_index_is_clust(index));
@@ -1611,77 +1738,112 @@ row_upd_clust_rec_by_insert(
pcur = node->pcur;
btr_cur = btr_pcur_get_btr_cur(pcur);
- if (node->state != UPD_NODE_INSERT_CLUSTERED) {
- rec_t* rec;
- dict_index_t* index;
- ulint offsets_[REC_OFFS_NORMAL_SIZE];
- ulint* offsets;
- rec_offs_init(offsets_);
+ heap = mem_heap_create(1000);
+
+ entry = row_build_index_entry(node->upd_row, node->upd_ext,
+ index, heap);
+ ut_a(entry);
- err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
- btr_cur, TRUE, thr, mtr);
+ row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
+
+ switch (node->state) {
+ default:
+ ut_error;
+ case UPD_NODE_INSERT_BLOB:
+ /* A lock wait occurred in row_ins_index_entry() in
+ the previous invocation of this function. Mark the
+ off-page columns in the entry inherited. */
+
+ change_ownership = row_upd_clust_rec_by_insert_inherit(
+ NULL, NULL, entry, node->update);
+ ut_a(change_ownership);
+ /* fall through */
+ case UPD_NODE_INSERT_CLUSTERED:
+ /* A lock wait occurred in row_ins_index_entry() in
+ the previous invocation of this function. */
+ break;
+ case UPD_NODE_UPDATE_CLUSTERED:
+ /* This is the first invocation of the function where
+ we update the primary key. Delete-mark the old record
+ in the clustered index and prepare to insert a new entry. */
+ rec = btr_cur_get_rec(btr_cur);
+ offsets = rec_get_offsets(rec, index, NULL,
+ ULINT_UNDEFINED, &heap);
+ ut_ad(page_rec_is_user_rec(rec));
+
+ err = btr_cur_del_mark_set_clust_rec(
+ BTR_NO_LOCKING_FLAG, btr_cur_get_block(btr_cur),
+ rec, index, offsets, TRUE, thr, mtr);
if (err != DB_SUCCESS) {
+err_exit:
mtr_commit(mtr);
+ mem_heap_free(heap);
return(err);
}
- /* Mark as not-owned the externally stored fields which the new
- row inherits from the delete marked record: purge should not
- free those externally stored fields even if the delete marked
- record is removed from the index tree, or updated. */
+ /* If the the new row inherits externally stored
+ fields (off-page columns a.k.a. BLOBs) from the
+ delete-marked old record, mark them disowned by the
+ old record and owned by the new entry. */
+
+ if (rec_offs_any_extern(offsets)) {
+ change_ownership = row_upd_clust_rec_by_insert_inherit(
+ rec, offsets, entry, node->update);
+
+ if (change_ownership) {
+ btr_pcur_store_position(pcur, mtr);
+ }
+ }
- rec = btr_cur_get_rec(btr_cur);
- index = dict_table_get_first_index(table);
- offsets = rec_get_offsets(rec, index, offsets_,
- ULINT_UNDEFINED, &heap);
- change_ownership = btr_cur_mark_extern_inherited_fields(
- btr_cur_get_page_zip(btr_cur), rec, index, offsets,
- node->update, mtr);
if (check_ref) {
/* NOTE that the following call loses
the position of pcur ! */
err = row_upd_check_references_constraints(
node, pcur, table, index, offsets, thr, mtr);
if (err != DB_SUCCESS) {
- mtr_commit(mtr);
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- return(err);
+ goto err_exit;
}
}
}
mtr_commit(mtr);
- if (!heap) {
- heap = mem_heap_create(500);
- }
- node->state = UPD_NODE_INSERT_CLUSTERED;
+ err = row_ins_index_entry(index, entry,
+ node->upd_ext ? node->upd_ext->n_ext : 0,
+ TRUE, thr);
+ node->state = change_ownership
+ ? UPD_NODE_INSERT_BLOB
+ : UPD_NODE_INSERT_CLUSTERED;
- entry = row_build_index_entry(node->upd_row, node->upd_ext,
- index, heap);
- ut_a(entry);
+ if (err == DB_SUCCESS && change_ownership) {
+ /* Mark the non-updated fields disowned by the old record. */
- row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
+ /* NOTE: this transaction has an x-lock on the record
+ and therefore other transactions cannot modify the
+ record when we have no latch on the page. In addition,
+ we assume that other query threads of the same
+ transaction do not modify the record in the meantime.
+ Therefore we can assert that the restoration of the
+ cursor succeeds. */
- if (change_ownership) {
- /* If we return from a lock wait, for example, we may have
- extern fields marked as not-owned in entry (marked in the
- if-branch above). We must unmark them, take the ownership
- back. */
+ mtr_start(mtr);
- btr_cur_unmark_dtuple_extern_fields(entry);
+ if (!btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr)) {
+ ut_error;
+ }
- /* We must mark non-updated extern fields in entry as
- inherited, so that a possible rollback will not free them. */
+ rec = btr_cur_get_rec(btr_cur);
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ ut_ad(page_rec_is_user_rec(rec));
- btr_cur_mark_dtuple_inherited_extern(entry, node->update);
+ btr_cur_disown_inherited_fields(
+ btr_cur_get_page_zip(btr_cur),
+ rec, index, offsets, node->update, mtr);
+
+ mtr_commit(mtr);
}
- err = row_ins_index_entry(index, entry,
- node->upd_ext ? node->upd_ext->n_ext : 0,
- TRUE, thr);
mem_heap_free(heap);
return(err);
@@ -1825,8 +1987,9 @@ row_upd_del_mark_clust_rec(
/* Mark the clustered index record deleted; we do not have to check
locks, because we assume that we have an x-lock on the record */
- err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
- btr_cur, TRUE, thr, mtr);
+ err = btr_cur_del_mark_set_clust_rec(
+ BTR_NO_LOCKING_FLAG, btr_cur_get_block(btr_cur),
+ btr_cur_get_rec(btr_cur), index, offsets, TRUE, thr, mtr);
if (err == DB_SUCCESS && check_ref) {
/* NOTE that the following call loses the position of pcur ! */
@@ -1973,7 +2136,8 @@ exit_func:
row_upd_store_row(node);
- if (row_upd_changes_ord_field_binary(node->row, index, node->update)) {
+ if (row_upd_changes_ord_field_binary(node->row, node->ext, index,
+ node->update)) {
/* Update causes an ordering field (ordering fields within
the B-tree) of the clustered index record to change: perform
@@ -2042,7 +2206,8 @@ row_upd(
}
if (node->state == UPD_NODE_UPDATE_CLUSTERED
- || node->state == UPD_NODE_INSERT_CLUSTERED) {
+ || node->state == UPD_NODE_INSERT_CLUSTERED
+ || node->state == UPD_NODE_INSERT_BLOB) {
log_free_check();
err = row_upd_clust_step(node, thr);
diff --git a/storage/innodb_plugin/srv/srv0start.c b/storage/innodb_plugin/srv/srv0start.c
index f823b72fbc1..73f8f319704 100644
--- a/storage/innodb_plugin/srv/srv0start.c
+++ b/storage/innodb_plugin/srv/srv0start.c
@@ -1286,8 +1286,25 @@ innobase_start_or_create_for_mysql(void)
fil_init(srv_file_per_table ? 50000 : 5000,
srv_max_n_open_files);
+ /* Print time to initialize the buffer pool */
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Initializing buffer pool, size =");
+
+ if (srv_buf_pool_size >= 1024 * 1024 * 1024) {
+ fprintf(stderr,
+ " %.1fG\n",
+ ((double) srv_buf_pool_size) / (1024 * 1024 * 1024));
+ } else {
+ fprintf(stderr,
+ " %.1fM\n",
+ ((double) srv_buf_pool_size) / (1024 * 1024));
+ }
+
ret = buf_pool_init();
+ ut_print_timestamp(stderr);
+
if (ret == NULL) {
fprintf(stderr,
"InnoDB: Fatal error: cannot allocate the memory"
@@ -1296,6 +1313,9 @@ innobase_start_or_create_for_mysql(void)
return(DB_ERROR);
}
+ fprintf(stderr,
+ " InnoDB: Completed initialization of buffer pool\n");
+
#ifdef UNIV_DEBUG
/* We have observed deadlocks with a 5MB buffer pool but
the actual lower limit could very well be a little higher. */
diff --git a/storage/innodb_plugin/sync/sync0rw.c b/storage/innodb_plugin/sync/sync0rw.c
index 52eaa5d0f43..572c3690a7f 100644
--- a/storage/innodb_plugin/sync/sync0rw.c
+++ b/storage/innodb_plugin/sync/sync0rw.c
@@ -335,10 +335,13 @@ rw_lock_validate(
/*=============*/
rw_lock_t* lock) /*!< in: rw-lock */
{
+ ulint waiters;
+ lint lock_word;
+
ut_a(lock);
- ulint waiters = rw_lock_get_waiters(lock);
- lint lock_word = lock->lock_word;
+ waiters = rw_lock_get_waiters(lock);
+ lock_word = lock->lock_word;
ut_ad(lock->magic_n == RW_LOCK_MAGIC_N);
ut_a(waiters == 0 || waiters == 1);
@@ -988,7 +991,7 @@ rw_lock_debug_print(
rwt = info->lock_type;
- fprintf(stderr, "Locked: thread %ld file %s line %ld ",
+ fprintf(stderr, "Locked: thread %lu file %s line %lu ",
(ulong) os_thread_pf(info->thread_id), info->file_name,
(ulong) info->line);
if (rwt == RW_LOCK_SHARED) {
diff --git a/storage/innodb_plugin/thr/thr0loc.c b/storage/innodb_plugin/thr/thr0loc.c
index 59a234a6b72..94b84b11fbe 100644
--- a/storage/innodb_plugin/thr/thr0loc.c
+++ b/storage/innodb_plugin/thr/thr0loc.c
@@ -71,6 +71,24 @@ struct thr_local_struct{
/** The value of thr_local_struct::magic_n */
#define THR_LOCAL_MAGIC_N 1231234
+#ifdef UNIV_DEBUG
+/*******************************************************************//**
+Validates thread local data.
+@return TRUE if valid */
+static
+ibool
+thr_local_validate(
+/*===============*/
+ const thr_local_t* local) /*!< in: data to validate */
+{
+ ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
+ ut_ad(local->slot_no == ULINT_UNDEFINED
+ || local->slot_no < OS_THREAD_MAX_N);
+ ut_ad(local->in_ibuf == FALSE || local->in_ibuf == TRUE);
+ return(TRUE);
+}
+#endif /* UNIV_DEBUG */
+
/*******************************************************************//**
Returns the local storage struct for a thread.
@return local storage */
@@ -91,7 +109,8 @@ try_again:
local = NULL;
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
- thr_local_t*, local,, os_thread_eq(local->id, id));
+ thr_local_t*, local, ut_ad(thr_local_validate(local)),
+ os_thread_eq(local->id, id));
if (local == NULL) {
mutex_exit(&thr_local_mutex);
@@ -102,7 +121,7 @@ try_again:
goto try_again;
}
- ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
+ ut_ad(thr_local_validate(local));
return(local);
}
@@ -188,7 +207,7 @@ thr_local_create(void)
local->id = os_thread_get_curr_id();
local->handle = os_thread_get_curr();
local->magic_n = THR_LOCAL_MAGIC_N;
-
+ local->slot_no = ULINT_UNDEFINED;
local->in_ibuf = FALSE;
mutex_enter(&thr_local_mutex);
@@ -215,7 +234,8 @@ thr_local_free(
/* Look for the local struct in the hash table */
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
- thr_local_t*, local,, os_thread_eq(local->id, id));
+ thr_local_t*, local, ut_ad(thr_local_validate(local)),
+ os_thread_eq(local->id, id));
if (local == NULL) {
mutex_exit(&thr_local_mutex);
@@ -228,6 +248,7 @@ thr_local_free(
mutex_exit(&thr_local_mutex);
ut_a(local->magic_n == THR_LOCAL_MAGIC_N);
+ ut_ad(thr_local_validate(local));
mem_free(local);
}
@@ -270,6 +291,7 @@ thr_local_close(void)
local = HASH_GET_NEXT(hash, prev_local);
ut_a(prev_local->magic_n == THR_LOCAL_MAGIC_N);
+ ut_ad(thr_local_validate(prev_local));
mem_free(prev_local);
}
}
diff --git a/storage/innodb_plugin/trx/trx0i_s.c b/storage/innodb_plugin/trx/trx0i_s.c
index c0b9a73a68c..e148234888b 100644
--- a/storage/innodb_plugin/trx/trx0i_s.c
+++ b/storage/innodb_plugin/trx/trx0i_s.c
@@ -404,6 +404,42 @@ table_cache_create_empty_row(
return(row);
}
+#ifdef UNIV_DEBUG
+/*******************************************************************//**
+Validates a row in the locks cache.
+@return TRUE if valid */
+static
+ibool
+i_s_locks_row_validate(
+/*===================*/
+ const i_s_locks_row_t* row) /*!< in: row to validate */
+{
+ ut_ad(row->lock_trx_id != 0);
+ ut_ad(row->lock_mode != NULL);
+ ut_ad(row->lock_type != NULL);
+ ut_ad(row->lock_table != NULL);
+ ut_ad(row->lock_table_id != 0);
+
+ if (row->lock_space == ULINT_UNDEFINED) {
+ /* table lock */
+ ut_ad(!strcmp("TABLE", row->lock_type));
+ ut_ad(row->lock_index == NULL);
+ ut_ad(row->lock_data == NULL);
+ ut_ad(row->lock_page == ULINT_UNDEFINED);
+ ut_ad(row->lock_rec == ULINT_UNDEFINED);
+ } else {
+ /* record lock */
+ ut_ad(!strcmp("RECORD", row->lock_type));
+ ut_ad(row->lock_index != NULL);
+ /* row->lock_data == NULL if buf_page_try_get() == NULL */
+ ut_ad(row->lock_page != ULINT_UNDEFINED);
+ ut_ad(row->lock_rec != ULINT_UNDEFINED);
+ }
+
+ return(TRUE);
+}
+#endif /* UNIV_DEBUG */
+
/*******************************************************************//**
Fills i_s_trx_row_t object.
If memory can not be allocated then FALSE is returned.
@@ -431,18 +467,15 @@ fill_trx_row(
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);
+ row->requested_lock_row = requested_lock_row;
+ ut_ad(requested_lock_row == NULL
+ || i_s_locks_row_validate(requested_lock_row));
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;
}
@@ -461,7 +494,6 @@ fill_trx_row(
stmt = innobase_get_stmt(trx->mysql_thd, &stmt_len);
if (stmt != NULL) {
-
char query[TRX_I_S_TRX_QUERY_MAX_LEN + 1];
if (stmt_len > TRX_I_S_TRX_QUERY_MAX_LEN) {
@@ -475,6 +507,8 @@ fill_trx_row(
cache->storage, stmt, stmt_len + 1,
MAX_ALLOWED_FOR_STORAGE(cache));
+ row->trx_query_cs = innobase_get_charset(trx->mysql_thd);
+
if (row->trx_query == NULL) {
return(FALSE);
@@ -725,6 +759,7 @@ fill_locks_row(
row->lock_table_id = lock_get_table_id(lock);
row->hash_chain.value = row;
+ ut_ad(i_s_locks_row_validate(row));
return(TRUE);
}
@@ -745,6 +780,9 @@ fill_lock_waits_row(
relevant blocking lock
row in innodb_locks */
{
+ ut_ad(i_s_locks_row_validate(requested_lock_row));
+ ut_ad(i_s_locks_row_validate(blocking_lock_row));
+
row->requested_lock_row = requested_lock_row;
row->blocking_lock_row = blocking_lock_row;
@@ -816,6 +854,7 @@ locks_row_eq_lock(
or ULINT_UNDEFINED if the lock
is a table lock */
{
+ ut_ad(i_s_locks_row_validate(row));
#ifdef TEST_NO_LOCKS_ROW_IS_EVER_EQUAL_TO_LOCK_T
return(0);
#else
@@ -873,7 +912,7 @@ search_innodb_locks(
/* auxiliary variable */
hash_chain,
/* assertion on every traversed item */
- ,
+ ut_ad(i_s_locks_row_validate(hash_chain->value)),
/* this determines if we have found the lock */
locks_row_eq_lock(hash_chain->value, lock, heap_no));
@@ -913,6 +952,7 @@ add_lock_to_cache(
dst_row = search_innodb_locks(cache, lock, heap_no);
if (dst_row != NULL) {
+ ut_ad(i_s_locks_row_validate(dst_row));
return(dst_row);
}
#endif
@@ -950,6 +990,7 @@ add_lock_to_cache(
} /* for()-loop */
#endif
+ ut_ad(i_s_locks_row_validate(dst_row));
return(dst_row);
}
diff --git a/storage/innodb_plugin/ut/ut0dbg.c b/storage/innodb_plugin/ut/ut0dbg.c
index 4484e6c36de..7839466e16f 100644
--- a/storage/innodb_plugin/ut/ut0dbg.c
+++ b/storage/innodb_plugin/ut/ut0dbg.c
@@ -79,7 +79,7 @@ ut_dbg_assertion_failed(
" or crashes, even\n"
"InnoDB: immediately after the mysqld startup, there may be\n"
"InnoDB: corruption in the InnoDB tablespace. Please refer to\n"
- "InnoDB: " REFMAN "forcing-recovery.html\n"
+ "InnoDB: " REFMAN "forcing-innodb-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT)
ut_dbg_stop_threads = TRUE;
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc
index e29904897ba..e8a66a3265f 100644
--- a/storage/maria/ha_maria.cc
+++ b/storage/maria/ha_maria.cc
@@ -1120,8 +1120,7 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt)
if (!maria_is_crashed(file) &&
(((param.testflag & T_CHECK_ONLY_CHANGED) &&
- !(share->state.changed & (STATE_CHANGED | STATE_CRASHED |
- STATE_CRASHED_ON_REPAIR |
+ !(share->state.changed & (STATE_CHANGED | STATE_CRASHED_FLAGS |
STATE_IN_REPAIR)) &&
share->state.open_count == 0) ||
((param.testflag & T_FAST) && (share->state.open_count ==
@@ -1159,15 +1158,15 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt)
if (!error)
{
if ((share->state.changed & (STATE_CHANGED |
- STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR |
- STATE_CRASHED | STATE_NOT_ANALYZED)) ||
+ STATE_CRASHED_FLAGS |
+ STATE_IN_REPAIR | STATE_NOT_ANALYZED)) ||
(param.testflag & T_STATISTICS) || maria_is_crashed(file))
{
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
pthread_mutex_lock(&share->intern_lock);
DBUG_PRINT("info", ("Reseting crashed state"));
- share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
- STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR);
+ share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED_FLAGS |
+ STATE_IN_REPAIR);
if (!(table->db_stat & HA_READ_ONLY))
error= maria_update_state_info(&param, file,
UPDATE_TIME | UPDATE_OPEN_COUNT |
@@ -1599,8 +1598,8 @@ int ha_maria::repair(THD *thd, HA_CHECK *param, bool do_optimize)
if ((share->state.changed & STATE_CHANGED) || maria_is_crashed(file))
{
DBUG_PRINT("info", ("Reseting crashed state"));
- share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
- STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR);
+ share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED_FLAGS |
+ STATE_IN_REPAIR);
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
}
/*
@@ -1624,7 +1623,7 @@ int ha_maria::repair(THD *thd, HA_CHECK *param, bool do_optimize)
llstr(rows, llbuff),
llstr(file->state->records, llbuff2));
/* Abort if warning was converted to error */
- if (current_thd->is_error())
+ if (table->in_use->is_error())
error= 1;
}
}
@@ -1859,7 +1858,7 @@ int ha_maria::enable_indexes(uint mode)
}
else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
{
- THD *thd= current_thd;
+ THD *thd= table->in_use;
HA_CHECK &param= *(HA_CHECK*) thd->alloc(sizeof(param));
if (!&param)
return HA_ADMIN_INTERNAL_ERROR;
@@ -1961,7 +1960,7 @@ int ha_maria::indexes_are_disabled(void)
void ha_maria::start_bulk_insert(ha_rows rows)
{
DBUG_ENTER("ha_maria::start_bulk_insert");
- THD *thd= current_thd;
+ THD *thd= table->in_use;
ulong size= min(thd->variables.read_buff_size,
(ulong) (table->s->avg_row_length * rows));
MARIA_SHARE *share= file->s;
@@ -2087,8 +2086,7 @@ bool ha_maria::check_and_repair(THD *thd)
check_opt.flags= T_MEDIUM | T_AUTO_REPAIR;
error= 1;
- if ((file->s->state.changed &
- (STATE_CRASHED | STATE_CRASHED_ON_REPAIR | STATE_MOVED)) ==
+ if ((file->s->state.changed & (STATE_CRASHED_FLAGS | STATE_MOVED)) ==
STATE_MOVED)
{
sql_print_information("Zerofilling moved table: '%s'",
@@ -2139,7 +2137,7 @@ bool ha_maria::check_and_repair(THD *thd)
bool ha_maria::is_crashed() const
{
- return (file->s->state.changed & (STATE_CRASHED | STATE_MOVED) ||
+ return (file->s->state.changed & (STATE_CRASHED_FLAGS | STATE_MOVED) ||
(my_disable_locking && file->s->state.open_count));
}
@@ -2480,7 +2478,7 @@ int ha_maria::extra_opt(enum ha_extra_function operation, ulong cache_size)
int ha_maria::delete_all_rows()
{
- THD *thd= current_thd;
+ THD *thd= table->in_use;
(void) translog_log_debug_info(file->trn, LOGREC_DEBUG_INFO_QUERY,
(uchar*) thd->query(), thd->query_length());
if (file->s->now_transactional &&
@@ -2510,8 +2508,9 @@ int ha_maria::delete_table(const char *name)
void ha_maria::drop_table(const char *name)
{
+ DBUG_ASSERT(file->s->temporary);
(void) close();
- (void) maria_delete_table(name);
+ (void) maria_delete_table_files(name, 0);
}
@@ -2605,6 +2604,7 @@ int ha_maria::external_lock(THD *thd, int lock_type)
{
DBUG_PRINT("info",
("locked_tables: %u", trnman_has_locked_tables(trn)));
+ DBUG_ASSERT(trnman_has_locked_tables(trn) > 0);
if (trnman_has_locked_tables(trn) &&
!trnman_decrement_locked_tables(trn))
{
@@ -2738,12 +2738,12 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn)
statement assuming they have a trn (see ha_maria::start_stmt()).
*/
trn= trnman_new_trn(& thd->transaction.wt);
- /* This is just a commit, tables stay locked if they were: */
- trnman_reset_locked_tables(trn, locked_tables);
THD_TRN= trn;
if (unlikely(trn == NULL))
+ {
error= HA_ERR_OUT_OF_MEM;
-
+ goto end;
+ }
/*
Move all locked tables to the new transaction
We must do it here as otherwise file->thd and file->state may be
@@ -2768,6 +2768,8 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn)
}
}
}
+ /* This is just a commit, tables stay locked if they were: */
+ trnman_reset_locked_tables(trn, locked_tables);
}
end:
DBUG_RETURN(error);
@@ -2904,7 +2906,7 @@ int ha_maria::create(const char *name, register TABLE *table_arg,
ha_create_info->row_type != ROW_TYPE_PAGE &&
ha_create_info->row_type != ROW_TYPE_NOT_USED &&
ha_create_info->row_type != ROW_TYPE_DEFAULT)
- push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_ILLEGAL_HA_CREATE_OPTION,
"Row format set to PAGE because of TRANSACTIONAL=1 option");
@@ -3380,6 +3382,8 @@ static int ha_maria_init(void *p)
ma_checkpoint_init(checkpoint_interval);
maria_multi_threaded= maria_in_ha_maria= TRUE;
maria_create_trn_hook= maria_create_trn_for_mysql;
+ maria_pagecache->extra_debug= 1;
+ maria_assert_if_crashed_table= debug_assert_if_crashed_table;
#if defined(HAVE_REALPATH) && !defined(HAVE_valgrind) && !defined(HAVE_BROKEN_REALPATH)
/* We can only test for sub paths if my_symlink.c is using realpath */
diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c
index bc83f6ea0e9..5b3be5d7bf4 100644
--- a/storage/maria/ma_bitmap.c
+++ b/storage/maria/ma_bitmap.c
@@ -104,10 +104,11 @@
- On checkpoint
(Ie: When we do a checkpoint, we have to ensure that all bitmaps are
put on disk even if they are not in the page cache).
- - When explicitely requested (for example on backup or after recvoery,
+ - When explicitely requested (for example on backup or after recovery,
to simplify things)
The flow of writing a row is that:
+ - Mark the bitmap not flushable (_ma_bitmap_flushable(X, 1))
- Lock the bitmap
- Decide which data pages we will write to
- Mark them full in the bitmap page so that other threads do not try to
@@ -119,6 +120,7 @@
pages (that is, we marked pages full but when we are done we realize
we didn't fill them)
- Unlock the bitmap.
+ - Mark the bitmap flushable (_ma_bitmap_flushable(X, -1))
*/
#include "maria_def.h"
@@ -127,6 +129,12 @@
#define FULL_HEAD_PAGE 4
#define FULL_TAIL_PAGE 7
+const char *bits_to_txt[]=
+{
+ "empty", "00-30% full", "30-60% full", "60-90% full", "full",
+ "tail 00-40 % full", "tail 40-80 % full", "tail/blob full"
+};
+
/*#define WRONG_BITMAP_FLUSH 1*/ /*define only for provoking bugs*/
#undef WRONG_BITMAP_FLUSH
@@ -136,12 +144,15 @@ static my_bool _ma_read_bitmap_page(MARIA_HA *info,
static my_bool _ma_bitmap_create_missing(MARIA_HA *info,
MARIA_FILE_BITMAP *bitmap,
pgcache_page_no_t page);
+static void _ma_bitmap_unpin_all(MARIA_SHARE *share);
+
/* Write bitmap page to key cache */
static inline my_bool write_changed_bitmap(MARIA_SHARE *share,
MARIA_FILE_BITMAP *bitmap)
{
+ my_bool res;
DBUG_ENTER("write_changed_bitmap");
DBUG_ASSERT(share->pagecache->block_size == bitmap->block_size);
DBUG_ASSERT(bitmap->file.write_callback != 0);
@@ -159,7 +170,7 @@ static inline my_bool write_changed_bitmap(MARIA_SHARE *share,
#endif
)
{
- my_bool res= pagecache_write(share->pagecache,
+ res= pagecache_write(share->pagecache,
&bitmap->file, bitmap->page, 0,
bitmap->map, PAGECACHE_PLAIN_PAGE,
PAGECACHE_LOCK_LEFT_UNLOCKED,
@@ -169,8 +180,17 @@ static inline my_bool write_changed_bitmap(MARIA_SHARE *share,
}
else
{
+ /*
+ bitmap->non_flushable means that someone has changed the bitmap,
+ but it's not yet complete so it can't yet be written to disk.
+ In this case we write the changed bitmap to the disk cache,
+ but keep it pinned until the change is completed. The page will
+ be unpinned later by _ma_bitmap_unpin_all() as soon as non_flushable
+ is set back to 0.
+ */
MARIA_PINNED_PAGE page_link;
- int res= pagecache_write(share->pagecache,
+ DBUG_PRINT("info", ("Writing pinned bitmap page"));
+ res= pagecache_write(share->pagecache,
&bitmap->file, bitmap->page, 0,
bitmap->map, PAGECACHE_PLAIN_PAGE,
PAGECACHE_LOCK_LEFT_UNLOCKED, PAGECACHE_PIN,
@@ -178,7 +198,7 @@ static inline my_bool write_changed_bitmap(MARIA_SHARE *share,
LSN_IMPOSSIBLE);
page_link.unlock= PAGECACHE_LOCK_LEFT_UNLOCKED;
page_link.changed= 1;
- push_dynamic(&bitmap->pinned_pages, (void*) &page_link);
+ push_dynamic(&bitmap->pinned_pages, (const uchar*) (void*) &page_link);
DBUG_RETURN(res);
}
}
@@ -227,7 +247,8 @@ my_bool _ma_bitmap_init(MARIA_SHARE *share, File file)
The +1 is to add the bitmap page, as this doesn't have to be covered
*/
bitmap->pages_covered= aligned_bit_blocks * 16 + 1;
- bitmap->flush_all_requested= 0;
+ bitmap->flush_all_requested= bitmap->waiting_for_flush_all_requested=
+ bitmap->waiting_for_non_flushable= 0;
bitmap->non_flushable= 0;
/* Update size for bits */
@@ -266,13 +287,26 @@ my_bool _ma_bitmap_init(MARIA_SHARE *share, File file)
my_bool _ma_bitmap_end(MARIA_SHARE *share)
{
- my_bool res= _ma_bitmap_flush(share);
+ my_bool res;
safe_mutex_assert_owner(&share->close_lock);
+ DBUG_ASSERT(share->bitmap.non_flushable == 0);
+ DBUG_ASSERT(share->bitmap.flush_all_requested == 0);
+ DBUG_ASSERT(share->bitmap.waiting_for_non_flushable == 0 &&
+ share->bitmap.waiting_for_flush_all_requested == 0);
+ DBUG_ASSERT(share->bitmap.pinned_pages.elements == 0);
+
+ res= _ma_bitmap_flush(share);
pthread_mutex_destroy(&share->bitmap.bitmap_lock);
pthread_cond_destroy(&share->bitmap.bitmap_cond);
delete_dynamic(&share->bitmap.pinned_pages);
my_free(share->bitmap.map, MYF(MY_ALLOW_ZERO_PTR));
share->bitmap.map= 0;
+ /*
+ This is to not get an assert in checkpoint. The bitmap will be flushed
+ at once by _ma_once_end_block_record() as part of the normal flush
+ of the kfile.
+ */
+ share->bitmap.changed_not_flushed= 0;
return res;
}
@@ -351,12 +385,56 @@ filter_flush_bitmap_pages(enum pagecache_page_type type
my_bool _ma_bitmap_flush_all(MARIA_SHARE *share)
{
my_bool res= 0;
+ uint send_signal= 0;
MARIA_FILE_BITMAP *bitmap= &share->bitmap;
DBUG_ENTER("_ma_bitmap_flush_all");
+
+#ifdef EXTRA_DEBUG_BITMAP
+ {
+ char buff[160];
+ uint len= my_sprintf(buff,
+ (buff, "bitmap_flush: fd: %d id: %u "
+ "changed: %d changed_not_flushed: %d "
+ "flush_all_requested: %d",
+ share->bitmap.file.file,
+ share->id,
+ bitmap->changed,
+ bitmap->changed_not_flushed,
+ bitmap->flush_all_requested));
+ (void) translog_log_debug_info(0, LOGREC_DEBUG_INFO_QUERY,
+ (uchar*) buff, len);
+ }
+#endif
+
pthread_mutex_lock(&bitmap->bitmap_lock);
+ if (!bitmap->changed && !bitmap->changed_not_flushed)
+ {
+ pthread_mutex_unlock(&bitmap->bitmap_lock);
+ DBUG_RETURN(0);
+ }
+
+ /*
+ Before flusing bitmap, ensure that we have incremented open count.
+ This is needed to ensure that we don't call
+ _ma_mark_file_changed() as part of flushing bitmap page as in this
+ case we would use mutex lock in wrong order.
+ It's extremely unlikely that the following test is true as normally
+ this is happening when table is flushed.
+ */
+ if (unlikely(!share->global_changed))
+ {
+ /* purecov: begin inspected */
+ /* unlock bitmap mutex as it can't be hold during _ma_mark_file_changed */
+ pthread_mutex_unlock(&bitmap->bitmap_lock);
+ _ma_mark_file_changed(share);
+ pthread_mutex_lock(&bitmap->bitmap_lock);
+ /* purecov: end */
+ }
+
if (bitmap->changed || bitmap->changed_not_flushed)
{
bitmap->flush_all_requested++;
+ bitmap->waiting_for_non_flushable++;
#ifndef WRONG_BITMAP_FLUSH
while (bitmap->non_flushable > 0)
{
@@ -364,6 +442,16 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE *share)
pthread_cond_wait(&bitmap->bitmap_cond, &bitmap->bitmap_lock);
}
#endif
+ bitmap->waiting_for_non_flushable--;
+#ifdef EXTRA_DEBUG_BITMAP
+ {
+ char tmp[MAX_BITMAP_INFO_LENGTH];
+ _ma_get_bitmap_description(bitmap, bitmap->map, bitmap->page, tmp);
+ (void) translog_log_debug_info(0, LOGREC_DEBUG_INFO_QUERY,
+ (uchar*) tmp, strlen(tmp));
+ }
+#endif
+
DBUG_ASSERT(bitmap->flush_all_requested == 1);
/*
Bitmap is in a flushable state: its contents in memory are reflected by
@@ -399,10 +487,12 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE *share)
become false, wake them up.
*/
DBUG_PRINT("info", ("bitmap flusher waking up others"));
- if (bitmap->flush_all_requested)
- pthread_cond_broadcast(&bitmap->bitmap_cond);
+ send_signal= (bitmap->waiting_for_flush_all_requested |
+ bitmap->waiting_for_non_flushable);
}
pthread_mutex_unlock(&bitmap->bitmap_lock);
+ if (send_signal)
+ pthread_cond_broadcast(&bitmap->bitmap_cond);
DBUG_RETURN(res);
}
@@ -432,11 +522,13 @@ void _ma_bitmap_lock(MARIA_SHARE *share)
pthread_mutex_lock(&bitmap->bitmap_lock);
bitmap->flush_all_requested++;
+ bitmap->waiting_for_non_flushable++;
while (bitmap->non_flushable)
{
DBUG_PRINT("info", ("waiting for bitmap to be flushable"));
pthread_cond_wait(&bitmap->bitmap_cond, &bitmap->bitmap_lock);
}
+ bitmap->waiting_for_non_flushable--;
/*
Ensure that _ma_bitmap_flush_all() and _ma_bitmap_lock() are blocked.
ma_bitmap_flushable() is blocked thanks to 'flush_all_requested'.
@@ -456,6 +548,7 @@ void _ma_bitmap_lock(MARIA_SHARE *share)
void _ma_bitmap_unlock(MARIA_SHARE *share)
{
MARIA_FILE_BITMAP *bitmap= &share->bitmap;
+ uint send_signal;
DBUG_ENTER("_ma_bitmap_unlock");
if (!share->now_transactional)
@@ -463,10 +556,13 @@ void _ma_bitmap_unlock(MARIA_SHARE *share)
DBUG_ASSERT(bitmap->flush_all_requested > 0 && bitmap->non_flushable == 1);
pthread_mutex_lock(&bitmap->bitmap_lock);
- bitmap->flush_all_requested--;
bitmap->non_flushable= 0;
+ _ma_bitmap_unpin_all(share);
+ send_signal= bitmap->waiting_for_non_flushable;
+ if (!--bitmap->flush_all_requested)
+ send_signal|= bitmap->waiting_for_flush_all_requested;
pthread_mutex_unlock(&bitmap->bitmap_lock);
- if (bitmap->flush_all_requested > 0)
+ if (send_signal)
pthread_cond_broadcast(&bitmap->bitmap_cond);
DBUG_VOID_RETURN;
}
@@ -680,7 +776,7 @@ static inline uint pattern_to_size(MARIA_FILE_BITMAP *bitmap, uint pattern)
Print bitmap for debugging
SYNOPSIS
- _ma_print_bitmap()
+ _ma_print_bitmap_changes()
bitmap Bitmap to print
IMPLEMENTATION
@@ -691,12 +787,6 @@ static inline uint pattern_to_size(MARIA_FILE_BITMAP *bitmap, uint pattern)
#ifndef DBUG_OFF
-const char *bits_to_txt[]=
-{
- "empty", "00-30% full", "30-60% full", "60-90% full", "full",
- "tail 00-40 % full", "tail 40-80 % full", "tail/blob full"
-};
-
static void _ma_print_bitmap_changes(MARIA_FILE_BITMAP *bitmap)
{
uchar *pos, *end, *org_pos;
@@ -747,7 +837,6 @@ void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data,
uchar *pos, *end;
char llbuff[22];
- end= bitmap->map + bitmap->used_size;
DBUG_LOCK_FILE;
fprintf(DBUG_FILE,"\nDump of bitmap page at %s\n", llstr(page, llbuff));
@@ -781,6 +870,56 @@ void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data,
#endif /* DBUG_OFF */
+/*
+ Return content of bitmap as a printable string
+*/
+
+void _ma_get_bitmap_description(MARIA_FILE_BITMAP *bitmap,
+ uchar *bitmap_data,
+ pgcache_page_no_t page,
+ char *out)
+{
+ uchar *pos, *end;
+ uint count=0, dot_printed= 0, len;
+ char buff[80], last[80];
+
+ page++;
+ last[0]=0;
+ for (pos= bitmap_data, end= pos+ bitmap->used_size ; pos < end ; pos+= 6)
+ {
+ ulonglong bits= uint6korr(pos); /* 6 bytes = 6*8/3= 16 patterns */
+ uint i;
+
+ for (i= 0; i < 16 ; i++, bits>>= 3)
+ {
+ if (count > 60)
+ {
+ if (memcmp(buff, last, count))
+ {
+ memcpy(last, buff, count);
+ len= my_sprintf(out, (out, "%8lu: ", (ulong) page - count));
+ memcpy(out+len, buff, count);
+ out+= len + count + 1;
+ out[-1]= '\n';
+ dot_printed= 0;
+ }
+ else if (!(dot_printed++))
+ {
+ out= strmov(out, "...\n");
+ }
+ count= 0;
+ }
+ buff[count++]= '0' + (uint) (bits & 7);
+ page++;
+ }
+ }
+ len= my_sprintf(out, (out, "%8lu: ", (ulong) page - count));
+ memcpy(out+len, buff, count);
+ out[len + count]= '\n';
+ out[len + count + 1]= 0;
+}
+
+
/***************************************************************************
Reading & writing bitmap pages
***************************************************************************/
@@ -2250,7 +2389,7 @@ void _ma_bitmap_flushable(MARIA_HA *info, int non_flushable_inc)
the bitmap's mutex.
*/
_ma_bitmap_unpin_all(share);
- if (unlikely(bitmap->flush_all_requested))
+ if (unlikely(bitmap->waiting_for_non_flushable))
{
DBUG_PRINT("info", ("bitmap flushable waking up flusher"));
pthread_cond_broadcast(&bitmap->bitmap_cond);
@@ -2263,6 +2402,8 @@ void _ma_bitmap_flushable(MARIA_HA *info, int non_flushable_inc)
}
DBUG_ASSERT(non_flushable_inc == 1);
DBUG_ASSERT(info->non_flushable_state == 0);
+
+ bitmap->waiting_for_flush_all_requested++;
while (unlikely(bitmap->flush_all_requested))
{
/*
@@ -2279,6 +2420,7 @@ void _ma_bitmap_flushable(MARIA_HA *info, int non_flushable_inc)
DBUG_PRINT("info", ("waiting for bitmap flusher"));
pthread_cond_wait(&bitmap->bitmap_cond, &bitmap->bitmap_lock);
}
+ bitmap->waiting_for_flush_all_requested--;
bitmap->non_flushable++;
DBUG_PRINT("info", ("bitmap->non_flushable: %u", bitmap->non_flushable));
pthread_mutex_unlock(&bitmap->bitmap_lock);
@@ -2383,16 +2525,14 @@ my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks)
The page has all bits set; The following test is an optimization
to not set the bits to the same value as before.
*/
+ DBUG_ASSERT(current_bitmap_value ==
+ _ma_bitmap_get_page_bits(info, bitmap, block->page));
+
if (bits != current_bitmap_value)
{
if (set_page_bits(info, bitmap, block->page, bits))
goto err;
}
- else
- {
- DBUG_ASSERT(current_bitmap_value ==
- _ma_bitmap_get_page_bits(info, bitmap, block->page));
- }
}
else if (!(block->used & BLOCKUSED_USED) &&
_ma_bitmap_reset_full_page_bits(info, bitmap,
@@ -2408,7 +2548,7 @@ my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks)
if (--bitmap->non_flushable == 0)
{
_ma_bitmap_unpin_all(info->s);
- if (unlikely(bitmap->flush_all_requested))
+ if (unlikely(bitmap->waiting_for_non_flushable))
{
DBUG_PRINT("info", ("bitmap flushable waking up flusher"));
pthread_cond_broadcast(&bitmap->bitmap_cond);
@@ -2448,9 +2588,9 @@ my_bool _ma_bitmap_free_full_pages(MARIA_HA *info, const uchar *extents,
uint count)
{
MARIA_FILE_BITMAP *bitmap= &info->s->bitmap;
+ my_bool res;
DBUG_ENTER("_ma_bitmap_free_full_pages");
- pthread_mutex_lock(&bitmap->bitmap_lock);
for (; count--; extents+= ROW_EXTENT_SIZE)
{
pgcache_page_no_t page= uint5korr(extents);
@@ -2461,15 +2601,15 @@ my_bool _ma_bitmap_free_full_pages(MARIA_HA *info, const uchar *extents,
if (page == 0 && page_count == 0)
continue; /* Not used extent */
if (pagecache_delete_pages(info->s->pagecache, &info->dfile, page,
- page_count, PAGECACHE_LOCK_WRITE, 1) ||
- _ma_bitmap_reset_full_page_bits(info, bitmap, page, page_count))
- {
- pthread_mutex_unlock(&bitmap->bitmap_lock);
+ page_count, PAGECACHE_LOCK_WRITE, 1))
+ DBUG_RETURN(1);
+ pthread_mutex_lock(&bitmap->bitmap_lock);
+ res= _ma_bitmap_reset_full_page_bits(info, bitmap, page, page_count);
+ pthread_mutex_unlock(&bitmap->bitmap_lock);
+ if (res)
DBUG_RETURN(1);
- }
}
}
- pthread_mutex_unlock(&bitmap->bitmap_lock);
DBUG_RETURN(0);
}
@@ -2521,17 +2661,15 @@ my_bool _ma_bitmap_set(MARIA_HA *info, pgcache_page_no_t page, my_bool head,
page_type What kind of page this is
page Adress to page
empty_space Empty space on page
- bitmap_pattern Store here the pattern that was in the bitmap for the
- page. This is always updated.
+ bitmap_pattern Bitmap pattern for page (from bitmap)
RETURN
0 ok
1 error
*/
-my_bool _ma_check_bitmap_data(MARIA_HA *info,
- enum en_page_type page_type, pgcache_page_no_t page,
- uint empty_space, uint *bitmap_pattern)
+my_bool _ma_check_bitmap_data(MARIA_HA *info, enum en_page_type page_type,
+ uint empty_space, uint bitmap_pattern)
{
uint bits;
switch (page_type) {
@@ -2552,8 +2690,7 @@ my_bool _ma_check_bitmap_data(MARIA_HA *info,
bits= 0; /* to satisfy compiler */
DBUG_ASSERT(0);
}
- return ((*bitmap_pattern= _ma_bitmap_get_page_bits(info, &info->s->bitmap,
- page)) != bits);
+ return (bitmap_pattern != bits);
}
diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c
index a2faeb6e7fa..c3b6110f4d1 100644
--- a/storage/maria/ma_blockrec.c
+++ b/storage/maria/ma_blockrec.c
@@ -891,8 +891,7 @@ static my_bool extend_area_on_page(MARIA_HA *info,
DBUG_PRINT("error", ("Not enough space: "
"length: %u request_length: %u",
length, request_length));
- my_errno= HA_ERR_WRONG_IN_RECORD; /* File crashed */
- DBUG_ASSERT(0); /* For debugging */
+ _ma_set_fatal_error(info->s, HA_ERR_WRONG_IN_RECORD);
DBUG_RETURN(1); /* Error in block */
}
*empty_space= length; /* All space is here */
@@ -1777,7 +1776,7 @@ static my_bool get_head_or_tail_page(MARIA_HA *info,
DBUG_RETURN(0);
crashed:
- my_errno= HA_ERR_WRONG_IN_RECORD; /* File crashed */
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD); /* File crashed */
DBUG_RETURN(1);
}
@@ -1870,7 +1869,7 @@ static my_bool get_rowpos_in_head_or_tail_page(MARIA_HA *info,
DBUG_RETURN(0);
err:
- my_errno= HA_ERR_WRONG_IN_RECORD; /* File crashed */
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD); /* File crashed */
DBUG_RETURN(1);
}
@@ -2018,6 +2017,7 @@ static my_bool write_tail(MARIA_HA *info,
PAGECACHE_WRITE_DELAY, &page_link.link,
LSN_IMPOSSIBLE)))
{
+ DBUG_ASSERT(page_link.link);
page_link.unlock= PAGECACHE_LOCK_READ_UNLOCK;
page_link.changed= 1;
push_dynamic(&info->pinned_pages, (void*) &page_link);
@@ -2094,8 +2094,7 @@ static my_bool write_full_pages(MARIA_HA *info,
{
if (!--sub_blocks)
{
- DBUG_ASSERT(0); /* Wrong in bitmap or UNDO */
- my_errno= HA_ERR_WRONG_IN_RECORD; /* File crashed */
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
DBUG_RETURN(1);
}
@@ -3148,6 +3147,7 @@ static my_bool write_block_record(MARIA_HA *info,
PAGECACHE_WRITE_DELAY, &page_link.link,
LSN_IMPOSSIBLE))
goto disk_err;
+ DBUG_ASSERT(page_link.link);
page_link.unlock= PAGECACHE_LOCK_READ_UNLOCK;
page_link.changed= 1;
push_dynamic(&info->pinned_pages, (void*) &page_link);
@@ -3419,7 +3419,7 @@ static my_bool write_block_record(MARIA_HA *info,
crashed:
/* Something was wrong with data on page */
- my_errno= HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
disk_err:
/**
@@ -3891,7 +3891,7 @@ static my_bool _ma_update_at_original_place(MARIA_HA *info,
("org_empty_size: %u head_length: %u length_on_page: %u",
org_empty_size, (uint) cur_row->head_length,
length_on_head_page));
- my_errno= HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
goto err;
}
@@ -3924,8 +3924,11 @@ static my_bool _ma_update_at_original_place(MARIA_HA *info,
goto err;
block= blocks->block;
block->empty_space= row_pos.empty_space;
- block->org_bitmap_value= _ma_free_size_to_head_pattern(&share->bitmap,
- org_empty_size);
+ block->org_bitmap_value=
+ _ma_free_size_to_head_pattern(&share->bitmap,
+ (enough_free_entries_on_page(share, buff) ?
+ org_empty_size : 0));
+
DBUG_ASSERT(block->org_bitmap_value ==
_ma_bitmap_get_page_bits(info, &info->s->bitmap, page));
block->used|= BLOCKUSED_USE_ORG_BITMAP;
@@ -4106,11 +4109,11 @@ static my_bool delete_head_or_tail(MARIA_HA *info,
{
MARIA_SHARE *share= info->s;
uint empty_space;
- uint block_size= share->block_size;
+ int res;
+ my_bool page_is_empty;
uchar *buff;
LSN lsn;
MARIA_PINNED_PAGE page_link;
- int res;
enum pagecache_page_lock lock_at_write, lock_at_unpin;
DBUG_ENTER("delete_head_or_tail");
DBUG_PRINT("enter", ("id: %lu (%lu:%u)",
@@ -4140,13 +4143,14 @@ static my_bool delete_head_or_tail(MARIA_HA *info,
lock_at_unpin= PAGECACHE_LOCK_READ_UNLOCK;
}
- res= delete_dir_entry(buff, block_size, record_number, &empty_space);
+ res= delete_dir_entry(buff, share->block_size, record_number, &empty_space);
if (res < 0)
DBUG_RETURN(1);
if (res == 0) /* after our deletion, page is still not empty */
{
uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + DIRPOS_STORE_SIZE];
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 1];
+ page_is_empty= 0;
if (share->now_transactional)
{
/* Log REDO data */
@@ -4167,6 +4171,7 @@ static my_bool delete_head_or_tail(MARIA_HA *info,
}
else /* page is now empty */
{
+ page_is_empty= 1;
if (share->now_transactional)
{
uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE];
@@ -4205,8 +4210,8 @@ static my_bool delete_head_or_tail(MARIA_HA *info,
If there is not enough space for all possible tails, mark the
page full
*/
- if (!head && !enough_free_entries(buff, share->block_size,
- 1 + share->base.blobs))
+ if (!head && !page_is_empty && !enough_free_entries(buff, share->block_size,
+ 1 + share->base.blobs))
empty_space= 0;
DBUG_RETURN(_ma_bitmap_set(info, page, head, empty_space));
@@ -4528,7 +4533,7 @@ static uchar *read_next_extent(MARIA_HA *info, MARIA_EXTENT_CURSOR *extent,
crashed:
- my_errno= HA_ERR_WRONG_IN_RECORD; /* File crashed */
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
DBUG_PRINT("error", ("wrong extent information"));
DBUG_RETURN(0);
}
@@ -4673,7 +4678,11 @@ int _ma_read_block_record2(MARIA_HA *info, uchar *record,
{
cur_row->trid= transid_korr(data+1);
if (!info->trn)
- DBUG_RETURN(my_errno= HA_ERR_WRONG_IN_RECORD); /* File crashed */
+ {
+ /* File crashed */
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
+ DBUG_RETURN(HA_ERR_WRONG_IN_RECORD);
+ }
if (!trnman_can_read_from(info->trn, cur_row->trid))
DBUG_RETURN(my_errno= HA_ERR_ROW_NOT_VISIBLE);
}
@@ -4954,7 +4963,8 @@ int _ma_read_block_record2(MARIA_HA *info, uchar *record,
err:
/* Something was wrong with data on record */
DBUG_PRINT("error", ("Found record with wrong data"));
- DBUG_RETURN((my_errno= HA_ERR_WRONG_IN_RECORD));
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
+ DBUG_RETURN(HA_ERR_WRONG_IN_RECORD);
}
@@ -5404,7 +5414,8 @@ restart_bitmap_scan:
(uint) (uchar) info->scan.page_buff[DIR_COUNT_OFFSET]) == 0)
{
DBUG_PRINT("error", ("Wrong page header"));
- DBUG_RETURN((my_errno= HA_ERR_WRONG_IN_RECORD));
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
+ DBUG_RETURN(HA_ERR_WRONG_IN_RECORD);
}
DBUG_PRINT("info", ("Page %lu has %u rows",
(ulong) page, info->scan.number_of_rows));
@@ -5450,7 +5461,8 @@ restart_bitmap_scan:
err:
DBUG_PRINT("error", ("Wrong data on page"));
- DBUG_RETURN((my_errno= HA_ERR_WRONG_IN_RECORD));
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
+ DBUG_RETURN(HA_ERR_WRONG_IN_RECORD);
}
@@ -6334,6 +6346,12 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
empty_space-= (uint) data_length;
int2store(buff + EMPTY_SPACE_OFFSET, empty_space);
+ /* Fix bitmap */
+ if (!enough_free_entries_on_page(share, buff))
+ empty_space= 0; /* Page is full */
+ if (_ma_bitmap_set(info, page, page_type == HEAD_PAGE, empty_space))
+ goto err;
+
/*
If page was not read before, write it but keep it pinned.
We don't update its LSN When we have processed all REDOs for this page
@@ -6351,12 +6369,6 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
LSN_IMPOSSIBLE))
result= my_errno;
- /* Fix bitmap */
- if (!enough_free_entries_on_page(share, buff))
- empty_space= 0; /* Page is full */
- if (_ma_bitmap_set(info, page, page_type == HEAD_PAGE, empty_space))
- goto err;
-
page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK;
page_link.changed= 1;
push_dynamic(&info->pinned_pages, (void*) &page_link);
@@ -6370,7 +6382,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
DBUG_RETURN(result);
crashed_file:
- my_errno= HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
err:
error= my_errno;
if (unlock_method == PAGECACHE_LOCK_LEFT_WRITELOCKED)
@@ -6458,7 +6470,7 @@ uint _ma_apply_redo_purge_row_head_or_tail(MARIA_HA *info, LSN lsn,
if (delete_dir_entry(buff, block_size, rownr, &empty_space) < 0)
{
- my_errno= HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
goto err;
}
diff --git a/storage/maria/ma_blockrec.h b/storage/maria/ma_blockrec.h
index e63af8eed5b..3201998e31c 100644
--- a/storage/maria/ma_blockrec.h
+++ b/storage/maria/ma_blockrec.h
@@ -78,6 +78,10 @@ enum en_page_type { UNALLOCATED_PAGE, HEAD_PAGE, TAIL_PAGE, BLOB_PAGE, MAX_PAGE_
#define ROW_FLAG_EXTENTS 128
#define ROW_FLAG_ALL (1+2+4+8+128)
+/* Size for buffer to hold information about bitmap */
+#define MAX_BITMAP_INFO_LENGTH ((MARIA_MAX_KEY_BLOCK_LENGTH*8/3)*(61*11/60)+10)
+
+
/******** Variables that affects how data pages are utilized ********/
/* Minium size of tail segment */
@@ -181,6 +185,8 @@ TRANSLOG_ADDRESS
maria_page_get_lsn(uchar *page, pgcache_page_no_t page_no, uchar* data_ptr);
/* ma_bitmap.c */
+extern const char *bits_to_txt[];
+
my_bool _ma_bitmap_init(MARIA_SHARE *share, File file);
my_bool _ma_bitmap_end(MARIA_SHARE *share);
my_bool _ma_bitmap_flush(MARIA_SHARE *share);
@@ -206,8 +212,7 @@ my_bool _ma_bitmap_find_new_place(MARIA_HA *info, MARIA_ROW *new_row,
MARIA_BITMAP_BLOCKS *result_blocks);
my_bool _ma_check_bitmap_data(MARIA_HA *info,
enum en_page_type page_type,
- pgcache_page_no_t page,
- uint empty_space, uint *bitmap_pattern);
+ uint empty_space, uint bitmap_pattern);
my_bool _ma_check_if_right_bitmap_type(MARIA_HA *info,
enum en_page_type page_type,
pgcache_page_no_t page,
@@ -225,6 +230,10 @@ void _ma_bitmap_set_pagecache_callbacks(PAGECACHE_FILE *file,
void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data,
pgcache_page_no_t page);
#endif
+void _ma_get_bitmap_description(MARIA_FILE_BITMAP *bitmap,
+ uchar *bitmap_data,
+ pgcache_page_no_t page,
+ char *out);
uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
uint page_type,
diff --git a/storage/maria/ma_cache.c b/storage/maria/ma_cache.c
index 82b5ddd8047..059e815ae1b 100644
--- a/storage/maria/ma_cache.c
+++ b/storage/maria/ma_cache.c
@@ -35,8 +35,8 @@
#include "maria_def.h"
-my_bool _ma_read_cache(IO_CACHE *info, uchar *buff, my_off_t pos,
- size_t length, uint flag)
+my_bool _ma_read_cache(MARIA_HA *handler, IO_CACHE *info, uchar *buff,
+ my_off_t pos, size_t length, uint flag)
{
size_t read_length,in_buff_length;
my_off_t offset;
@@ -98,7 +98,12 @@ my_bool _ma_read_cache(IO_CACHE *info, uchar *buff, my_off_t pos,
("Error %d reading next-multi-part block (Got %d bytes)",
my_errno, (int) read_length));
if (!my_errno || my_errno == HA_ERR_FILE_TOO_SHORT)
- my_errno= HA_ERR_WRONG_IN_RECORD;
+ {
+ if (!handler->in_check_table)
+ _ma_set_fatal_error(handler->s, HA_ERR_WRONG_IN_RECORD);
+ else
+ my_errno= HA_ERR_WRONG_IN_RECORD;
+ }
DBUG_RETURN(1);
}
bzero(buff+read_length,MARIA_BLOCK_INFO_HEADER_LENGTH - in_buff_length -
diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c
index 4877f5c6d71..62eac2d8873 100644
--- a/storage/maria/ma_check.c
+++ b/storage/maria/ma_check.c
@@ -1249,7 +1249,7 @@ static int check_dynamic_record(HA_CHECK *param, MARIA_HA *info, int extend,
block_info.next_filepos=pos;
do
{
- if (_ma_read_cache(&param->read_cache, block_info.header,
+ if (_ma_read_cache(info, &param->read_cache, block_info.header,
(start_block=block_info.next_filepos),
sizeof(block_info.header),
(flag ? 0 : READING_NEXT) | READING_HEADER))
@@ -1267,7 +1267,7 @@ static int check_dynamic_record(HA_CHECK *param, MARIA_HA *info, int extend,
llstr(start_block,llbuff));
DBUG_RETURN(1);
}
- b_type= _ma_get_block_info(&block_info,-1,start_block);
+ b_type= _ma_get_block_info(info, &block_info,-1,start_block);
if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
BLOCK_FATAL_ERROR))
{
@@ -1363,7 +1363,7 @@ static int check_dynamic_record(HA_CHECK *param, MARIA_HA *info, int extend,
got_error=1;
break;
}
- if (_ma_read_cache(&param->read_cache, to, block_info.filepos,
+ if (_ma_read_cache(info, &param->read_cache, to, block_info.filepos,
(uint) block_info.data_len,
flag == 1 ? READING_NEXT : 0))
{
@@ -1466,7 +1466,7 @@ static int check_compressed_record(HA_CHECK *param, MARIA_HA *info, int extend,
if (_ma_killed_ptr(param))
DBUG_RETURN(-1);
- if (_ma_read_cache(&param->read_cache, block_info.header, pos,
+ if (_ma_read_cache(info, &param->read_cache, block_info.header, pos,
share->pack.ref_length, READING_NEXT))
{
_ma_check_print_error(param,
@@ -1491,7 +1491,7 @@ static int check_compressed_record(HA_CHECK *param, MARIA_HA *info, int extend,
got_error=1;
goto end;
}
- if (_ma_read_cache(&param->read_cache, info->rec_buff,
+ if (_ma_read_cache(info, &param->read_cache, info->rec_buff,
block_info.filepos, block_info.rec_len, READING_NEXT))
{
_ma_check_print_error(param,
@@ -1824,6 +1824,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
pos+= block_size, page++)
{
uint row_count, real_row_count, empty_space, page_type, bitmap_pattern;
+ uint bitmap_for_page;
LINT_INIT(row_count);
LINT_INIT(empty_space);
@@ -1858,7 +1859,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
offset= offset_page & 7;
data= bitmap_buff + offset_page / 8;
bitmap_pattern= uint2korr(data);
- if (!((bitmap_pattern >> offset) & 7))
+ if (!(bitmap_for_page= ((bitmap_pattern >> offset) & 7)))
{
param->empty+= block_size;
param->del_blocks++;
@@ -1881,8 +1882,9 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
if (page_type == UNALLOCATED_PAGE || page_type >= MAX_PAGE_TYPE)
{
_ma_check_print_error(param,
- "Page: %9s Found wrong page type %d",
- llstr(page, llbuff), page_type);
+ "Page: %9s Found wrong page type %d. Bitmap: %d '%s'",
+ llstr(page, llbuff), page_type,
+ bitmap_for_page, bits_to_txt[bitmap_for_page]);
if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE))
goto err;
continue;
@@ -1929,20 +1931,17 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
param->used+= block_size;
break;
}
- if (_ma_check_bitmap_data(info, page_type, page,
+ if (_ma_check_bitmap_data(info, page_type,
full_dir ? 0 : empty_space,
- &bitmap_pattern))
+ bitmap_for_page))
{
- if (bitmap_pattern == ~(uint) 0)
- _ma_check_print_error(param,
- "Page %9s: Wrong bitmap for data on page",
- llstr(page, llbuff));
- else
_ma_check_print_error(param,
"Page %9s: Wrong data in bitmap. Page_type: "
- "%d full: %d empty_space: %u Bitmap-bits: %d",
+ "%d full: %d empty_space: %u Bitmap-bits: %d "
+ "'%s'",
llstr(page, llbuff), page_type, full_dir,
- empty_space, bitmap_pattern);
+ empty_space, bitmap_for_page,
+ bits_to_txt[bitmap_for_page]);
if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE))
goto err;
}
@@ -3494,7 +3493,7 @@ int maria_zerofill(HA_CHECK *param, MARIA_HA *info, const char *name)
_ma_tmp_disable_logging_for_table(info, 0);
if (!(error= (maria_zerofill_index(param, info, name) ||
maria_zerofill_data(param, info, name) ||
- _ma_set_uuid(info, 0))))
+ _ma_set_uuid(info->s, 0))))
{
/*
Mark that we have done zerofill of data and index. If we zeroed pages'
@@ -3873,11 +3872,13 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
if (param->testflag & T_SAFE_REPAIR)
{
/* Don't repair if we loosed more than one row */
- if (share->state.state.records+1 < start_records)
+ if (sort_info.new_info->s->state.state.records+1 < start_records)
{
_ma_check_print_error(param,
- "Rows lost; Aborting because safe repair was "
- "requested");
+ "Rows lost (Found %lu of %lu); Aborting "
+ "because safe repair was requested",
+ (ulong) share->state.state.records,
+ (ulong) start_records);
share->state.state.records=start_records;
goto err;
}
@@ -4436,8 +4437,13 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
if (param->testflag & T_SAFE_REPAIR)
{
/* Don't repair if we loosed more than one row */
- if (share->state.state.records+1 < start_records)
+ if (sort_info.new_info->s->state.state.records+1 < start_records)
{
+ _ma_check_print_error(param,
+ "Rows lost (Found %lu of %lu); Aborting "
+ "because safe repair was requested",
+ (ulong) share->state.state.records,
+ (ulong) start_records);
share->state.state.records=start_records;
goto err;
}
@@ -4866,7 +4872,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
_ma_check_print_info(param,"Block: %s used by record at %s",
llstr(param->search_after_block,llbuff),
llstr(sort_param->start_recpos,llbuff2));
- if (_ma_read_cache(&sort_param->read_cache,
+ if (_ma_read_cache(info, &sort_param->read_cache,
block_info.header, pos,
MARIA_BLOCK_INFO_HEADER_LENGTH,
(! found_record ? READING_NEXT : 0) |
@@ -4888,7 +4894,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
param->testflag|=T_RETRY_WITHOUT_QUICK;
DBUG_RETURN(1); /* Something wrong with data */
}
- b_type= _ma_get_block_info(&block_info,-1,pos);
+ b_type= _ma_get_block_info(info, &block_info,-1,pos);
if ((b_type & (BLOCK_ERROR | BLOCK_FATAL_ERROR)) ||
((b_type & BLOCK_FIRST) &&
(block_info.rec_len < (uint) share->base.min_pack_length ||
@@ -5079,7 +5085,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
}
}
if (block_info.data_len &&
- _ma_read_cache(&sort_param->read_cache,to,block_info.filepos,
+ _ma_read_cache(info, &sort_param->read_cache,to,block_info.filepos,
block_info.data_len,
(found_record == 1 ? READING_NEXT : 0) |
parallel_flag))
@@ -5149,7 +5155,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
case COMPRESSED_RECORD:
for (searching=0 ;; searching=1, sort_param->pos++)
{
- if (_ma_read_cache(&sort_param->read_cache, block_info.header,
+ if (_ma_read_cache(info, &sort_param->read_cache, block_info.header,
sort_param->pos,
share->pack.ref_length,READING_NEXT))
DBUG_RETURN(-1);
@@ -5181,7 +5187,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
llstr(sort_param->pos,llbuff));
continue;
}
- if (_ma_read_cache(&sort_param->read_cache, sort_param->rec_buff,
+ if (_ma_read_cache(info, &sort_param->read_cache, sort_param->rec_buff,
block_info.filepos, block_info.rec_len,
READING_NEXT))
{
@@ -6089,6 +6095,7 @@ int maria_update_state_info(HA_CHECK *param, MARIA_HA *info,uint update)
{
share->state.open_count=0;
share->global_changed=0;
+ share->changed= 1;
}
if (update & UPDATE_STAT)
{
@@ -6116,7 +6123,6 @@ int maria_update_state_info(HA_CHECK *param, MARIA_HA *info,uint update)
MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET |
MA_STATE_INFO_WRITE_FULL_INFO))
goto err;
- share->changed=0;
}
{ /* Force update of status */
int error;
@@ -6850,39 +6856,10 @@ static void print_bitmap_description(MARIA_SHARE *share,
pgcache_page_no_t page,
uchar *bitmap_data)
{
- uchar *pos, *end;
- MARIA_FILE_BITMAP *bitmap= &share->bitmap;
- uint count=0, dot_printed= 0;
- char buff[80], last[80];
-
- printf("Bitmap page %lu\n", (ulong) page);
- page++;
- last[0]=0;
- for (pos= bitmap_data, end= pos+ bitmap->used_size ; pos < end ; pos+= 6)
- {
- ulonglong bits= uint6korr(pos); /* 6 bytes = 6*8/3= 16 patterns */
- uint i;
-
- for (i= 0; i < 16 ; i++, bits>>= 3)
- {
- if (count > 60)
- {
- buff[count]= 0;
- if (strcmp(buff, last))
- {
- memcpy(last, buff, count+1);
- printf("%8lu: %s\n", (ulong) page - count, buff);
- dot_printed= 0;
- }
- else if (!(dot_printed++))
- printf("...\n");
- count= 0;
- }
- buff[count++]= '0' + (uint) (bits & 7);
- page++;
- }
- }
- buff[count]= 0;
- printf("%8lu: %s\n", (ulong) page - count, buff);
- fputs("\n", stdout);
+ char *tmp= my_malloc(MAX_BITMAP_INFO_LENGTH, MYF(MY_WME));
+ if (!tmp)
+ return;
+ _ma_get_bitmap_description(&share->bitmap, bitmap_data, page, tmp);
+ printf("Bitmap page %lu\n%s", (ulong) page, tmp);
+ my_free(tmp, MYF(0));
}
diff --git a/storage/maria/ma_checkpoint.c b/storage/maria/ma_checkpoint.c
index cf13cee9452..79a9e790e70 100644
--- a/storage/maria/ma_checkpoint.c
+++ b/storage/maria/ma_checkpoint.c
@@ -130,6 +130,9 @@ int ma_checkpoint_execute(CHECKPOINT_LEVEL level, my_bool no_wait)
/* from then on, we are sure to be and stay the only checkpointer */
result= really_execute_checkpoint();
+ DBUG_EXECUTE_IF("maria_crash_after_checkpoint",
+ { DBUG_PRINT("maria_crash", ("now")); DBUG_ABORT(); });
+
pthread_cond_broadcast(&COND_checkpoint);
end:
DBUG_RETURN(result);
@@ -1027,6 +1030,14 @@ static int collect_tables(LEX_STRING *str, LSN checkpoint_start_log_horizon)
*/
}
}
+#ifdef EXTRA_DEBUG_BITMAP
+ else
+ {
+ DBUG_ASSERT(share->bitmap.changed == 0 &&
+ share->bitmap.changed_not_flushed == 0);
+ }
+#endif
+
/*
_ma_bitmap_flush_all() may wait, so don't keep intern_lock as
otherwise this would deadlock with allocate_and_write_block_record()
diff --git a/storage/maria/ma_close.c b/storage/maria/ma_close.c
index df525d45d14..e97664ebe42 100644
--- a/storage/maria/ma_close.c
+++ b/storage/maria/ma_close.c
@@ -39,9 +39,6 @@ int maria_close(register MARIA_HA *info)
if (info->lock_type == F_EXTRA_LCK)
info->lock_type=F_UNLCK; /* HA_EXTRA_NO_USER_CHANGE */
- if (share->reopen == 1 && share->kfile.file >= 0)
- _ma_decrement_open_count(info);
-
if (info->lock_type != F_UNLCK)
{
if (maria_lock_database(info,F_UNLCK))
@@ -76,6 +73,11 @@ int maria_close(register MARIA_HA *info)
if (share->kfile.file >= 0)
{
+ my_bool save_global_changed= share->global_changed;
+
+ /* Avoid _ma_mark_file_changed() when flushing pages */
+ share->global_changed= 1;
+
if ((*share->once_end)(share))
error= my_errno;
if (flush_pagecache_blocks(share->pagecache, &share->kfile,
@@ -97,6 +99,16 @@ int maria_close(register MARIA_HA *info)
if (((share->changed && share->base.born_transactional) ||
maria_is_crashed(info)))
{
+ if (save_global_changed)
+ {
+ /*
+ Reset effect of _ma_mark_file_changed(). Better to do it
+ here than in _ma_decrement_open_count(), as
+ _ma_state_info_write() will write the open_count.
+ */
+ save_global_changed= 0;
+ share->state.open_count--;
+ }
/*
State must be written to file as it was not done at table's
unlocking.
@@ -104,6 +116,19 @@ int maria_close(register MARIA_HA *info)
if (_ma_state_info_write(share, MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET))
error= my_errno;
}
+ DBUG_ASSERT(maria_is_crashed(info) || !share->base.born_transactional ||
+ share->state.open_count == 0 ||
+ share->open_count_not_zero_on_open);
+
+ /* Ensure that open_count is zero on close */
+ share->global_changed= save_global_changed;
+ _ma_decrement_open_count(info, 0);
+
+ /* Ensure that open_count really is zero */
+ DBUG_ASSERT(maria_is_crashed(info) || share->temporary ||
+ share->state.open_count == 0 ||
+ share->open_count_not_zero_on_open);
+
/*
File must be synced as it is going out of the maria_open_list and so
becoming unknown to future Checkpoints.
diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c
index 0a74cad6a37..0ed7b7d62d2 100644
--- a/storage/maria/ma_create.c
+++ b/storage/maria/ma_create.c
@@ -1395,7 +1395,13 @@ int _ma_update_state_lsns_sub(MARIA_SHARE *share, LSN lsn, TrID create_trid,
share->state.skip_redo_lsn= share->state.is_of_horizon= lsn;
share->state.create_trid= create_trid;
mi_int8store(trid_buff, create_trid);
- if (update_create_rename_lsn)
+
+ /*
+ Update create_rename_lsn if update was requested or if the old one had an
+ impossible value.
+ */
+ if (update_create_rename_lsn ||
+ (share->state.create_rename_lsn > lsn && lsn != LSN_IMPOSSIBLE))
{
share->state.create_rename_lsn= lsn;
if (share->id != 0)
diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c
index 5c04f358b14..ab66499ecfe 100644
--- a/storage/maria/ma_delete.c
+++ b/storage/maria/ma_delete.c
@@ -63,7 +63,7 @@ int maria_delete(MARIA_HA *info,const uchar *record)
if ((*share->compare_record)(info,record))
goto err; /* Error on read-check */
- if (_ma_mark_file_changed(info))
+ if (_ma_mark_file_changed(share))
goto err;
/* Ensure we don't change the autoincrement value */
@@ -135,18 +135,13 @@ err:
save_errno= HA_ERR_INTERNAL_ERROR; /* Should never happen */
mi_sizestore(lastpos, info->cur_row.lastpos);
- if (save_errno != HA_ERR_RECORD_CHANGED)
- {
- maria_print_error(share, HA_ERR_CRASHED);
- maria_mark_crashed(info); /* mark table crashed */
- }
VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
info->update|=HA_STATE_WRITTEN; /* Buffer changed */
allow_break(); /* Allow SIGHUP & SIGINT */
- if (save_errno == HA_ERR_KEY_NOT_FOUND)
+ if (save_errno != HA_ERR_RECORD_CHANGED)
{
- maria_print_error(share, HA_ERR_CRASHED);
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
+ save_errno= HA_ERR_CRASHED;
}
DBUG_RETURN(my_errno= save_errno);
} /* maria_delete */
@@ -213,7 +208,7 @@ my_bool _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key,
if ((old_root=*root) == HA_OFFSET_ERROR)
{
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(info->s, HA_ERR_CRASHED);
DBUG_RETURN(1);
}
if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
@@ -348,7 +343,7 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
if (!(tmp_key_length=(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag,
&kpos)))
{
- my_errno= HA_ERR_CRASHED;
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
DBUG_RETURN(-1);
}
root= _ma_row_pos_from_key(&tmp_key);
@@ -410,8 +405,9 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
{
if (!nod_flag)
{
+ /* This should newer happend */
DBUG_PRINT("error",("Didn't find key"));
- my_errno=HA_ERR_CRASHED; /* This should newer happend */
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
goto err;
}
save_flag=0;
diff --git a/storage/maria/ma_delete_all.c b/storage/maria/ma_delete_all.c
index 4661ea0ab59..c6dfa97e89f 100644
--- a/storage/maria/ma_delete_all.c
+++ b/storage/maria/ma_delete_all.c
@@ -52,8 +52,6 @@ int maria_delete_all_rows(MARIA_HA *info)
if (_ma_readinfo(info,F_WRLCK,1))
DBUG_RETURN(my_errno);
log_record= share->now_transactional && !share->temporary;
- if (_ma_mark_file_changed(info))
- goto err;
if (log_record)
{
@@ -75,14 +73,19 @@ int maria_delete_all_rows(MARIA_HA *info)
If we fail in this function after this point, log and table will be
inconsistent.
*/
+ if (_ma_mark_file_changed(share))
+ goto err;
}
else
{
+ if (_ma_mark_file_changed(share))
+ goto err;
/* Other branch called function below when writing log record, in hook */
_ma_reset_status(info);
}
/* Remove old history as the table is now empty for everyone */
_ma_reset_state(info);
+ share->state.changed= 0;
/*
If we are using delayed keys or if the user has done changes to the tables
@@ -180,6 +183,10 @@ void _ma_reset_status(MARIA_HA *info)
state->state.data_file_length= 0;
state->state.empty= state->state.key_empty= 0;
state->state.checksum= 0;
+ share->state.open_count= 0;
+ share->global_changed= 0;
+
+ share->changed= 1; /* We must write state */
*info->state= state->state;
diff --git a/storage/maria/ma_delete_table.c b/storage/maria/ma_delete_table.c
index 0237bb884c5..2913b97d958 100644
--- a/storage/maria/ma_delete_table.c
+++ b/storage/maria/ma_delete_table.c
@@ -28,10 +28,6 @@
int maria_delete_table(const char *name)
{
- char from[FN_REFLEN];
-#ifdef USE_RAID
- uint raid_type=0,raid_chunks=0;
-#endif
MARIA_HA *info;
myf sync_dir;
DBUG_ENTER("maria_delete_table");
@@ -53,17 +49,10 @@ int maria_delete_table(const char *name)
*/
if (!(info= maria_open(name, O_RDONLY, HA_OPEN_FOR_REPAIR)))
{
-#ifdef USE_RAID
- raid_type= 0;
-#endif
sync_dir= 0;
}
else
{
-#ifdef USE_RAID
- raid_type= info->s->base.raid_type;
- raid_chunks= info->s->base.raid_chunks;
-#endif
sync_dir= (info->s->now_transactional && !info->s->temporary &&
!maria_in_recovery) ?
MY_SYNC_DIR : 0;
@@ -93,15 +82,19 @@ int maria_delete_table(const char *name)
DBUG_RETURN(1);
}
+ DBUG_RETURN(maria_delete_table_files(name, sync_dir));
+}
+
+
+int maria_delete_table_files(const char *name, myf sync_dir)
+{
+ char from[FN_REFLEN];
+ DBUG_ENTER("maria_delete_table_files");
+
fn_format(from,name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
if (my_delete_with_symlink(from, MYF(MY_WME | sync_dir)))
DBUG_RETURN(my_errno);
fn_format(from,name,"",MARIA_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
-#ifdef USE_RAID
- if (raid_type)
- DBUG_RETURN(my_raid_delete(from, raid_chunks, MYF(MY_WME | sync_dir)) ?
- my_errno : 0);
-#endif
DBUG_RETURN(my_delete_with_symlink(from, MYF(MY_WME | sync_dir)) ?
my_errno : 0);
}
diff --git a/storage/maria/ma_dynrec.c b/storage/maria/ma_dynrec.c
index 57b76b713f4..7b120910a42 100644
--- a/storage/maria/ma_dynrec.c
+++ b/storage/maria/ma_dynrec.c
@@ -391,12 +391,12 @@ static int _ma_find_writepos(MARIA_HA *info,
*filepos=info->s->state.dellink;
block_info.second_read=0;
info->rec_cache.seek_not_done=1;
- if (!(_ma_get_block_info(&block_info, info->dfile.file,
+ if (!(_ma_get_block_info(info, &block_info, info->dfile.file,
info->s->state.dellink) &
BLOCK_DELETED))
{
DBUG_PRINT("error",("Delete link crashed"));
- my_errno=HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(info->s, HA_ERR_WRONG_IN_RECORD);
DBUG_RETURN(-1);
}
info->s->state.dellink=block_info.next_filepos;
@@ -452,7 +452,8 @@ static my_bool unlink_deleted_block(MARIA_HA *info,
MARIA_BLOCK_INFO tmp;
tmp.second_read=0;
/* Unlink block from the previous block */
- if (!(_ma_get_block_info(&tmp, info->dfile.file, block_info->prev_filepos)
+ if (!(_ma_get_block_info(info, &tmp, info->dfile.file,
+ block_info->prev_filepos)
& BLOCK_DELETED))
DBUG_RETURN(1); /* Something is wrong */
mi_sizestore(tmp.header+4,block_info->next_filepos);
@@ -462,7 +463,7 @@ static my_bool unlink_deleted_block(MARIA_HA *info,
/* Unlink block from next block */
if (block_info->next_filepos != HA_OFFSET_ERROR)
{
- if (!(_ma_get_block_info(&tmp, info->dfile.file,
+ if (!(_ma_get_block_info(info, &tmp, info->dfile.file,
block_info->next_filepos)
& BLOCK_DELETED))
DBUG_RETURN(1); /* Something is wrong */
@@ -514,7 +515,7 @@ static my_bool update_backward_delete_link(MARIA_HA *info,
if (delete_block != HA_OFFSET_ERROR)
{
block_info.second_read=0;
- if (_ma_get_block_info(&block_info, info->dfile.file, delete_block)
+ if (_ma_get_block_info(info, &block_info, info->dfile.file, delete_block)
& BLOCK_DELETED)
{
uchar buff[8];
@@ -524,7 +525,7 @@ static my_bool update_backward_delete_link(MARIA_HA *info,
}
else
{
- my_errno=HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(info->s, HA_ERR_WRONG_IN_RECORD);
DBUG_RETURN(1); /* Wrong delete link */
}
}
@@ -550,19 +551,21 @@ static my_bool delete_dynamic_record(MARIA_HA *info, MARIA_RECORD_POS filepos,
do
{
/* Remove block at 'filepos' */
- if ((b_type= _ma_get_block_info(&block_info, info->dfile.file, filepos))
+ if ((b_type= _ma_get_block_info(info, &block_info, info->dfile.file,
+ filepos))
& (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
BLOCK_FATAL_ERROR) ||
(length=(uint) (block_info.filepos-filepos) +block_info.block_len) <
MARIA_MIN_BLOCK_LENGTH)
{
- my_errno=HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(info->s, HA_ERR_WRONG_IN_RECORD);
DBUG_RETURN(1);
}
/* Check if next block is a delete block */
del_block.second_read=0;
remove_next_block=0;
- if (_ma_get_block_info(&del_block, info->dfile.file, filepos + length) &
+ if (_ma_get_block_info(info, &del_block, info->dfile.file,
+ filepos + length) &
BLOCK_DELETED && del_block.block_len+length <
MARIA_DYN_MAX_BLOCK_LENGTH)
{
@@ -722,7 +725,7 @@ int _ma_write_part_record(MARIA_HA *info,
if (next_block < info->state->data_file_length &&
info->s->state.dellink != HA_OFFSET_ERROR)
{
- if ((_ma_get_block_info(&del_block, info->dfile.file, next_block)
+ if ((_ma_get_block_info(info, &del_block, info->dfile.file, next_block)
& BLOCK_DELETED) &&
res_length + del_block.block_len < MARIA_DYN_MAX_BLOCK_LENGTH)
{
@@ -834,13 +837,14 @@ static my_bool update_dynamic_record(MARIA_HA *info, MARIA_RECORD_POS filepos,
if (filepos != info->s->state.dellink)
{
block_info.next_filepos= HA_OFFSET_ERROR;
- if ((error= _ma_get_block_info(&block_info, info->dfile.file, filepos))
+ if ((error= _ma_get_block_info(info, &block_info, info->dfile.file,
+ filepos))
& (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
BLOCK_FATAL_ERROR))
{
DBUG_PRINT("error",("Got wrong block info"));
if (!(error & BLOCK_FATAL_ERROR))
- my_errno=HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(info->s, HA_ERR_WRONG_IN_RECORD);
goto err;
}
length=(ulong) (block_info.filepos-filepos) + block_info.block_len;
@@ -875,7 +879,7 @@ static my_bool update_dynamic_record(MARIA_HA *info, MARIA_RECORD_POS filepos,
MARIA_BLOCK_INFO del_block;
del_block.second_read=0;
- if (_ma_get_block_info(&del_block, info->dfile.file,
+ if (_ma_get_block_info(info, &del_block, info->dfile.file,
block_info.filepos + block_info.block_len) &
BLOCK_DELETED)
{
@@ -1346,7 +1350,7 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register uchar *to, uchar *from,
DBUG_RETURN(found_length);
err:
- my_errno= HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(info->s, HA_ERR_WRONG_IN_RECORD);
DBUG_PRINT("error",("to_end: 0x%lx -> 0x%lx from_end: 0x%lx -> 0x%lx",
(long) to, (long) to_end, (long) from, (long) from_end));
DBUG_DUMP("from", info->rec_buff, info->s->base.min_pack_length);
@@ -1473,7 +1477,7 @@ int _ma_read_dynamic_record(MARIA_HA *info, uchar *buf,
flush_io_cache(&info->rec_cache))
goto err;
info->rec_cache.seek_not_done=1;
- if ((b_type= _ma_get_block_info(&block_info, file, filepos)) &
+ if ((b_type= _ma_get_block_info(info, &block_info, file, filepos)) &
(BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
BLOCK_FATAL_ERROR))
{
@@ -1545,7 +1549,7 @@ err:
DBUG_RETURN(my_errno);
panic:
- my_errno=HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(info->s, HA_ERR_WRONG_IN_RECORD);
goto err;
}
@@ -1627,7 +1631,7 @@ my_bool _ma_cmp_dynamic_record(register MARIA_HA *info,
block_info.next_filepos=filepos;
while (reclength > 0)
{
- if ((b_type= _ma_get_block_info(&block_info, info->dfile.file,
+ if ((b_type= _ma_get_block_info(info, &block_info, info->dfile.file,
block_info.next_filepos))
& (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
BLOCK_FATAL_ERROR))
@@ -1646,7 +1650,7 @@ my_bool _ma_cmp_dynamic_record(register MARIA_HA *info,
}
} else if (reclength < block_info.data_len)
{
- my_errno=HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(info->s, HA_ERR_WRONG_IN_RECORD);
goto err;
}
reclength-= block_info.data_len;
@@ -1779,12 +1783,12 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info,
}
if (info->opt_flag & READ_CACHE_USED)
{
- if (_ma_read_cache(&info->rec_cache, block_info.header, filepos,
+ if (_ma_read_cache(info, &info->rec_cache, block_info.header, filepos,
sizeof(block_info.header),
(!block_of_record && skip_deleted_blocks ?
READING_NEXT : 0) | READING_HEADER))
goto panic;
- b_type= _ma_get_block_info(&block_info,-1,filepos);
+ b_type= _ma_get_block_info(info, &block_info,-1,filepos);
}
else
{
@@ -1793,7 +1797,7 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info,
flush_io_cache(&info->rec_cache))
DBUG_RETURN(my_errno);
info->rec_cache.seek_not_done=1;
- b_type= _ma_get_block_info(&block_info, info->dfile.file, filepos);
+ b_type= _ma_get_block_info(info, &block_info, info->dfile.file, filepos);
}
if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
@@ -1855,7 +1859,7 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info,
{
if (info->opt_flag & READ_CACHE_USED)
{
- if (_ma_read_cache(&info->rec_cache, to,filepos,
+ if (_ma_read_cache(info, &info->rec_cache, to,filepos,
block_info.data_len,
(!block_of_record && skip_deleted_blocks) ?
READING_NEXT : 0))
@@ -1872,7 +1876,10 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info,
if (my_read(info->dfile.file, to, block_info.data_len, MYF(MY_NABP)))
{
if (my_errno == HA_ERR_FILE_TOO_SHORT)
- my_errno= HA_ERR_WRONG_IN_RECORD; /* Unexpected end of file */
+ {
+ /* Unexpected end of file */
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
+ }
goto err;
}
}
@@ -1899,7 +1906,8 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info,
DBUG_RETURN(my_errno); /* Wrong record */
panic:
- my_errno=HA_ERR_WRONG_IN_RECORD; /* Something is fatal wrong */
+ /* Something is fatal wrong */
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
err:
fast_ma_writeinfo(info);
DBUG_RETURN(my_errno);
@@ -1908,7 +1916,8 @@ err:
/* Read and process header from a dynamic-record-file */
-uint _ma_get_block_info(MARIA_BLOCK_INFO *info, File file, my_off_t filepos)
+uint _ma_get_block_info(MARIA_HA *handler, MARIA_BLOCK_INFO *info, File file,
+ my_off_t filepos)
{
uint return_val=0;
uchar *header=info->header;
@@ -1923,7 +1932,14 @@ uint _ma_get_block_info(MARIA_BLOCK_INFO *info, File file, my_off_t filepos)
VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
if (my_read(file, header, sizeof(info->header),MYF(0)) !=
sizeof(info->header))
- goto err;
+ {
+ /*
+ This is either an error or just reading at end of file.
+ Don't give a fatal error for this case.
+ */
+ my_errno= HA_ERR_WRONG_IN_RECORD;
+ return BLOCK_ERROR;
+ }
}
DBUG_DUMP("header",header,MARIA_BLOCK_INFO_HEADER_LENGTH);
if (info->second_read)
@@ -2037,6 +2053,10 @@ uint _ma_get_block_info(MARIA_BLOCK_INFO *info, File file, my_off_t filepos)
}
err:
- my_errno=HA_ERR_WRONG_IN_RECORD; /* Garbage */
+ if (!handler->in_check_table)
+ {
+ /* We may be scanning the table for new rows; Don't give an error */
+ _ma_set_fatal_error(handler->s, HA_ERR_WRONG_IN_RECORD);
+ }
return BLOCK_ERROR;
}
diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c
index 2d1ed6d3405..a5c4c2ab251 100644
--- a/storage/maria/ma_extra.c
+++ b/storage/maria/ma_extra.c
@@ -175,8 +175,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
{
if ((error= flush_io_cache(&info->rec_cache)))
{
- maria_print_error(info->s, HA_ERR_CRASHED);
- maria_mark_crashed(info); /* Fatal error found */
+ /* Fatal error found */
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
}
}
break;
@@ -254,8 +254,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
if (!share->changed)
{
- share->state.changed|= STATE_CHANGED | STATE_NOT_ANALYZED;
share->changed= 1; /* Update on close */
+ share->state.changed|= STATE_CHANGED | STATE_NOT_ANALYZED;
if (!share->global_changed)
{
share->global_changed= 1;
@@ -291,14 +291,15 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
if (!error && share->changed)
{
pthread_mutex_lock(&share->intern_lock);
- if (!(error= _ma_state_info_write(share,
- MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET|
- MA_STATE_INFO_WRITE_FULL_INFO)))
- share->changed= 0;
+ error= _ma_state_info_write(share,
+ MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET|
+ MA_STATE_INFO_WRITE_FULL_INFO);
pthread_mutex_unlock(&share->intern_lock);
}
pthread_mutex_lock(&THR_LOCK_maria);
pthread_mutex_lock(&share->intern_lock); /* protect against Checkpoint */
+ /* Safety against assert in checkpoint */
+ share->bitmap.changed_not_flushed= 0;
/* this makes the share not be re-used next time the table is opened */
share->last_version= 0L; /* Impossible version */
pthread_mutex_unlock(&share->intern_lock);
@@ -309,11 +310,14 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
share->deleting= TRUE;
share->global_changed= FALSE; /* force writing changed flag */
/* To force repair if reopened */
- _ma_mark_file_changed(info);
+ share->state.open_count= 1;
+ share->changed= 1;
+ _ma_mark_file_changed_now(share);
/* Fall trough */
case HA_EXTRA_PREPARE_FOR_RENAME:
{
my_bool do_flush= test(function != HA_EXTRA_PREPARE_FOR_DROP);
+ my_bool save_global_changed;
enum flush_type type;
pthread_mutex_lock(&THR_LOCK_maria);
/*
@@ -338,7 +342,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
*/
pthread_mutex_lock(&share->intern_lock);
if (share->kfile.file >= 0 && function != HA_EXTRA_PREPARE_FOR_DROP)
- _ma_decrement_open_count(info);
+ _ma_decrement_open_count(info, 0);
if (info->trn)
{
_ma_remove_table_from_trnman(share, info->trn);
@@ -347,12 +351,15 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
}
type= do_flush ? FLUSH_RELEASE : FLUSH_IGNORE_CHANGED;
+ save_global_changed= share->global_changed;
+ share->global_changed= 1; /* Don't increment open count */
if (_ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
type, type))
{
error=my_errno;
share->changed= 1;
}
+ share->global_changed= save_global_changed;
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
{
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
@@ -370,20 +377,23 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
MA_STATE_INFO_WRITE_FULL_INFO)) ||
my_sync(share->kfile.file, MYF(0)))
error= my_errno;
- else
- share->changed= 0;
}
else
{
/* be sure that state is not tried for write as file may be closed */
share->changed= 0;
+ share->global_changed= 0;
+ share->state.open_count= 0;
}
}
if (share->data_file_type == BLOCK_RECORD &&
share->bitmap.file.file >= 0)
{
+ DBUG_ASSERT(share->bitmap.non_flushable == 0 &&
+ share->bitmap.changed == 0);
if (do_flush && my_sync(share->bitmap.file.file, MYF(0)))
error= my_errno;
+ share->bitmap.changed_not_flushed= 0;
}
/* For protection against Checkpoint, we set under intern_lock: */
share->last_version= 0L; /* Impossible version */
@@ -405,8 +415,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
if (!share->temporary)
error= _ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
FLUSH_KEEP, FLUSH_KEEP);
-#ifdef HAVE_PWRITE
- _ma_decrement_open_count(info);
+#ifdef HAVE_PREAD
+ _ma_decrement_open_count(info, 1);
#endif
if (share->not_flushed)
{
@@ -415,9 +425,9 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
error= my_errno;
if (error)
{
+ /* Fatal error found */
share->changed= 1;
- maria_print_error(info->s, HA_ERR_CRASHED);
- maria_mark_crashed(info); /* Fatal error found */
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
}
}
break;
@@ -568,6 +578,12 @@ int _ma_sync_table_files(const MARIA_HA *info)
my_sync(info->s->kfile.file, MYF(MY_WME)));
}
+uint _ma_file_callback_to_id(void *callback_data)
+{
+ MARIA_SHARE *share= (MARIA_SHARE*) callback_data;
+ return share ? share->id : 0;
+}
+
/**
@brief flushes the data and/or index file of a table
@@ -598,6 +614,8 @@ int _ma_flush_table_files(MARIA_HA *info, uint flush_data_or_index,
{
int error= 0;
MARIA_SHARE *share= info->s;
+ DBUG_ENTER("_ma_flush_table_files");
+
/* flush data file first because it's more critical */
if (flush_data_or_index & MARIA_FLUSH_DATA)
{
@@ -616,6 +634,7 @@ int _ma_flush_table_files(MARIA_HA *info, uint flush_data_or_index,
{
pthread_mutex_lock(&share->bitmap.bitmap_lock);
share->bitmap.changed= 0;
+ share->bitmap.changed_not_flushed= 0;
pthread_mutex_unlock(&share->bitmap.bitmap_lock);
}
if (flush_pagecache_blocks(share->pagecache, &info->dfile,
@@ -628,11 +647,10 @@ int _ma_flush_table_files(MARIA_HA *info, uint flush_data_or_index,
flush_type_for_index))
error= 1;
if (!error)
- return 0;
+ DBUG_RETURN(0);
- maria_print_error(info->s, HA_ERR_CRASHED);
- maria_mark_crashed(info);
- return 1;
+ _ma_set_fatal_error(info->s, HA_ERR_CRASHED);
+ DBUG_RETURN(1);
}
diff --git a/storage/maria/ma_init.c b/storage/maria/ma_init.c
index 902f06d93e5..b050d61b5a2 100644
--- a/storage/maria/ma_init.c
+++ b/storage/maria/ma_init.c
@@ -104,7 +104,7 @@ void maria_end(void)
trid, recovery_failures);
}
trnman_destroy();
- if (translog_status == TRANSLOG_OK)
+ if (translog_status == TRANSLOG_OK || translog_status == TRANSLOG_READONLY)
translog_destroy();
end_pagecache(maria_log_pagecache, TRUE);
end_pagecache(maria_pagecache, TRUE);
diff --git a/storage/maria/ma_key.c b/storage/maria/ma_key.c
index df15d029ce6..1e60e6a8c06 100644
--- a/storage/maria/ma_key.c
+++ b/storage/maria/ma_key.c
@@ -644,8 +644,7 @@ int _ma_read_key_record(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos)
{ /* Read only key */
if (_ma_put_key_in_record(info, (uint)info->lastinx, TRUE, buf))
{
- maria_print_error(info->s, HA_ERR_CRASHED);
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(info->s, HA_ERR_CRASHED);
return -1;
}
info->update|= HA_STATE_AKTIV; /* We should find a record */
diff --git a/storage/maria/ma_key_recover.c b/storage/maria/ma_key_recover.c
index 6de5253a2dd..71af3a011e3 100644
--- a/storage/maria/ma_key_recover.c
+++ b/storage/maria/ma_key_recover.c
@@ -66,7 +66,7 @@ void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn)
#ifdef EXTRA_DEBUG
DBUG_ASSERT((!pinned_page->changed ||
undo_lsn != LSN_IMPOSSIBLE || !info->s->now_transactional) ||
- (info->s->state.changed & STATE_CRASHED));
+ (info->s->state.changed & STATE_CRASHED_FLAGS));
#endif
pagecache_unlock_by_link(info->s->pagecache, pinned_page->link,
pinned_page->unlock, PAGECACHE_UNPIN,
@@ -1027,7 +1027,7 @@ uint _ma_apply_redo_index(MARIA_HA *info,
insert_length, changed_length));
DBUG_ASSERT(insert_length <= changed_length &&
- page_length + changed_length <= max_page_size);
+ page_length + insert_length <= max_page_size);
bmove_upp(buff + page_length + insert_length, buff + page_length,
page_length - keypage_header);
diff --git a/storage/maria/ma_keycache.c b/storage/maria/ma_keycache.c
index 39fc7d421ae..1eb40821a36 100644
--- a/storage/maria/ma_keycache.c
+++ b/storage/maria/ma_keycache.c
@@ -79,8 +79,8 @@ int maria_assign_to_pagecache(MARIA_HA *info,
if (flush_pagecache_blocks(share->pagecache, &share->kfile, FLUSH_RELEASE))
{
error= my_errno;
- maria_print_error(info->s, HA_ERR_CRASHED);
- maria_mark_crashed(info); /* Mark that table must be checked */
+ /* Mark that table must be checked */
+ _ma_set_fatal_error(share, error);
}
/*
diff --git a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c
index 6bb308e5959..633fd59ef2a 100644
--- a/storage/maria/ma_locking.c
+++ b/storage/maria/ma_locking.c
@@ -80,9 +80,8 @@ int maria_lock_database(MARIA_HA *info, int lock_type)
{
if (end_io_cache(&info->rec_cache))
{
- error=my_errno;
- maria_print_error(info->s, HA_ERR_CRASHED);
- maria_mark_crashed(info);
+ error= my_errno;
+ _ma_set_fatal_error(share, error);
}
}
if (!count)
@@ -129,10 +128,7 @@ int maria_lock_database(MARIA_HA *info, int lock_type)
else
share->not_flushed=1;
if (error)
- {
- maria_print_error(info->s, HA_ERR_CRASHED);
- maria_mark_crashed(info);
- }
+ _ma_set_fatal_error(share, error);
}
}
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
@@ -390,12 +386,39 @@ int _ma_test_if_changed(register MARIA_HA *info)
#define _MA_ALREADY_MARKED_FILE_CHANGED \
((share->state.changed & STATE_CHANGED) && share->global_changed)
-int _ma_mark_file_changed(MARIA_HA *info)
+int _ma_mark_file_changed(register MARIA_SHARE *share)
+{
+ if (!share->base.born_transactional)
+ {
+ if (!_MA_ALREADY_MARKED_FILE_CHANGED)
+ return _ma_mark_file_changed_now(share);
+ }
+ else
+ {
+ /*
+ For transactional tables, the table is marked changed when the first page
+ is written. Here we just mark the state to be updated so that caller
+ can do 'anaylze table' and find that is has changed before any pages
+ are written.
+ */
+ if (! test_all_bits(share->state.changed,
+ (STATE_CHANGED | STATE_NOT_ANALYZED |
+ STATE_NOT_OPTIMIZED_KEYS)))
+ {
+ pthread_mutex_lock(&share->intern_lock);
+ share->state.changed|=(STATE_CHANGED | STATE_NOT_ANALYZED |
+ STATE_NOT_OPTIMIZED_KEYS);
+ pthread_mutex_unlock(&share->intern_lock);
+ }
+ }
+ return 0;
+}
+
+int _ma_mark_file_changed_now(register MARIA_SHARE *share)
{
uchar buff[3];
- register MARIA_SHARE *share= info->s;
int error= 1;
- DBUG_ENTER("_ma_mark_file_changed");
+ DBUG_ENTER("_ma_mark_file_changed_now");
if (_MA_ALREADY_MARKED_FILE_CHANGED)
DBUG_RETURN(0);
@@ -406,7 +429,7 @@ int _ma_mark_file_changed(MARIA_HA *info)
STATE_NOT_OPTIMIZED_KEYS);
if (!share->global_changed)
{
- share->global_changed=1;
+ share->changed= share->global_changed= 1;
share->state.open_count++;
}
/*
@@ -434,7 +457,7 @@ int _ma_mark_file_changed(MARIA_HA *info)
!(share->state.changed & STATE_NOT_MOVABLE))
{
/* Lock table to current installation */
- if (_ma_set_uuid(info, 0) ||
+ if (_ma_set_uuid(share, 0) ||
(share->state.create_rename_lsn == LSN_NEEDS_NEW_STATE_LSNS &&
_ma_update_state_lsns_sub(share, LSN_IMPOSSIBLE,
trnman_get_min_trid(),
@@ -476,22 +499,31 @@ my_bool _ma_check_if_zero(uchar *pos, size_t length)
call. In these context the following code should be safe!
*/
-int _ma_decrement_open_count(MARIA_HA *info)
+int _ma_decrement_open_count(MARIA_HA *info, my_bool lock_tables)
{
uchar buff[2];
register MARIA_SHARE *share= info->s;
int lock_error=0,write_error=0;
+ DBUG_ENTER("_ma_decrement_open_count");
+
if (share->global_changed)
{
uint old_lock=info->lock_type;
share->global_changed=0;
- lock_error= my_disable_locking ? 0 : maria_lock_database(info, F_WRLCK);
+ lock_error= (my_disable_locking || ! lock_tables ? 0 :
+ maria_lock_database(info, F_WRLCK));
/* Its not fatal even if we couldn't get the lock ! */
if (share->state.open_count > 0)
{
share->state.open_count--;
share->changed= 1; /* We have to update state */
- if (!share->temporary)
+ /*
+ For temporary tables that will just be deleted, we don't have
+ to decrement state. For transactional tables the state will be
+ updated in maria_close().
+ */
+
+ if (!share->temporary && !share->now_transactional)
{
mi_int2store(buff,share->state.open_count);
write_error= (int) my_pwrite(share->kfile.file, buff, sizeof(buff),
@@ -500,10 +532,10 @@ int _ma_decrement_open_count(MARIA_HA *info)
MYF(MY_NABP));
}
}
- if (!lock_error && !my_disable_locking)
+ if (!lock_error && !my_disable_locking && lock_tables)
lock_error=maria_lock_database(info,old_lock);
}
- return test(lock_error || write_error);
+ DBUG_RETURN(test(lock_error || write_error));
}
@@ -528,17 +560,40 @@ void _ma_mark_file_crashed(MARIA_SHARE *share)
DBUG_VOID_RETURN;
}
+/*
+ Handle a fatal error
+
+ - Mark the table as crashed
+ - Print an error message, if we had not issued an error message before
+ that the table had been crashed.
+ - set my_errno to error
+ - If 'maria_assert_if_crashed_table is set, then assert.
+*/
+
+void _ma_set_fatal_error(MARIA_SHARE *share, int error)
+{
+ DBUG_PRINT("error", ("error: %d", error));
+ maria_mark_crashed_share(share);
+ if (!(share->state.changed & STATE_CRASHED_PRINTED))
+ {
+ share->state.changed|= STATE_CRASHED_PRINTED;
+ maria_print_error(share, error);
+ }
+ my_errno= error;
+ DBUG_ASSERT(!maria_assert_if_crashed_table);
+}
+
/**
@brief Set uuid of for a Maria file
@fn _ma_set_uuid()
- @param info Maria handler
+ @param share Maria share
@param reset_uuid Instead of setting file to maria_uuid, set it to
0 to mark it as movable
*/
-my_bool _ma_set_uuid(MARIA_HA *info, my_bool reset_uuid)
+my_bool _ma_set_uuid(MARIA_SHARE *share, my_bool reset_uuid)
{
uchar buff[MY_UUID_SIZE], *uuid;
@@ -548,7 +603,7 @@ my_bool _ma_set_uuid(MARIA_HA *info, my_bool reset_uuid)
bzero(buff, sizeof(buff));
uuid= buff;
}
- return (my_bool) my_pwrite(info->s->kfile.file, uuid, MY_UUID_SIZE,
- mi_uint2korr(info->s->state.header.base_pos),
+ return (my_bool) my_pwrite(share->kfile.file, uuid, MY_UUID_SIZE,
+ mi_uint2korr(share->state.header.base_pos),
MYF(MY_NABP));
}
diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c
index 948cd2bf712..fc8edbe36e4 100644
--- a/storage/maria/ma_loghandler.c
+++ b/storage/maria/ma_loghandler.c
@@ -6230,7 +6230,7 @@ my_bool translog_write_record(LSN *lsn,
DBUG_RETURN(1);
}
- if (tbl_info)
+ if (tbl_info && type != LOGREC_FILE_ID)
{
MARIA_SHARE *share= tbl_info->s;
DBUG_ASSERT(share->now_transactional);
@@ -8090,6 +8090,7 @@ out:
int translog_assign_id_to_share(MARIA_HA *tbl_info, TRN *trn)
{
+ uint16 id;
MARIA_SHARE *share= tbl_info->s;
/*
If you give an id to a non-BLOCK_RECORD table, you also need to release
@@ -8098,13 +8099,14 @@ int translog_assign_id_to_share(MARIA_HA *tbl_info, TRN *trn)
DBUG_ASSERT(share->data_file_type == BLOCK_RECORD);
/* re-check under mutex to avoid having 2 ids for the same share */
pthread_mutex_lock(&share->intern_lock);
- if (unlikely(share->id == 0))
+ if (likely(share->id == 0))
{
LSN lsn;
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 2];
uchar log_data[FILEID_STORE_SIZE];
/* Inspired by set_short_trid() of trnman.c */
uint i= share->kfile.file % SHARE_ID_MAX + 1;
+ id= 0;
do
{
my_atomic_rwlock_wrlock(&LOCK_id_to_share);
@@ -8114,14 +8116,15 @@ int translog_assign_id_to_share(MARIA_HA *tbl_info, TRN *trn)
if (id_to_share[i] == NULL &&
my_atomic_casptr((void **)&id_to_share[i], &tmp, share))
{
- share->id= (uint16)i;
+ id= (uint16) i;
break;
}
}
my_atomic_rwlock_wrunlock(&LOCK_id_to_share);
i= 1; /* scan the whole array */
- } while (share->id == 0);
- DBUG_PRINT("info", ("id_to_share: 0x%lx -> %u", (ulong)share, share->id));
+ } while (id == 0);
+ DBUG_PRINT("info", ("id_to_share: 0x%lx -> %u", (ulong)share, id));
+ fileid_store(log_data, id);
log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data;
log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data);
/*
@@ -8143,11 +8146,17 @@ int translog_assign_id_to_share(MARIA_HA *tbl_info, TRN *trn)
log_array[TRANSLOG_INTERNAL_PARTS +
1].length),
sizeof(log_array)/sizeof(log_array[0]),
- log_array, log_data, NULL)))
+ log_array, NULL, NULL)))
{
pthread_mutex_unlock(&share->intern_lock);
return 1;
}
+ /*
+ Now when translog record is done, we can set share->id.
+ If we set it before, then translog_write_record may pick up the id
+ before it's written to the log.
+ */
+ share->id= id;
}
pthread_mutex_unlock(&share->intern_lock);
return 0;
diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c
index c679fba7a12..1dd5a58b71c 100644
--- a/storage/maria/ma_open.c
+++ b/storage/maria/ma_open.c
@@ -41,10 +41,10 @@ static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state);
pos+=size;}
-#define disk_pos_assert(pos, end_pos) \
+#define disk_pos_assert(share, pos, end_pos) \
if (pos > end_pos) \
{ \
- my_errno=HA_ERR_CRASHED; \
+ _ma_set_fatal_error(share, HA_ERR_CRASHED); \
goto err; \
}
@@ -390,7 +390,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
errpos= 3;
if (my_pread(kfile, disk_cache, info_length, 0L, MYF(MY_NABP)))
{
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
goto err;
}
len=mi_uint2korr(share->state.header.state_info_length);
@@ -416,9 +416,11 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
}
disk_pos= _ma_base_info_read(disk_cache + base_pos, &share->base);
share->state.state_length=base_pos;
+ /* For newly opened tables we reset the error-has-been-printed flag */
+ share->state.changed&= ~STATE_CRASHED_PRINTED;
if (!(open_flags & HA_OPEN_FOR_REPAIR) &&
- ((share->state.changed & STATE_CRASHED) ||
+ ((share->state.changed & STATE_CRASHED_FLAGS) ||
((open_flags & HA_OPEN_ABORT_IF_CRASHED) &&
(my_disable_locking && share->state.open_count))))
{
@@ -430,6 +432,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
goto err;
}
+ if (share->state.open_count)
+ share->open_count_not_zero_on_open= 1;
/*
We can ignore testing uuid if STATE_NOT_MOVABLE is set, as in this
@@ -459,7 +463,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
/* sanity check */
if (share->base.keystart > 65535 || share->base.rec_reflength > 8)
{
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
goto err;
}
@@ -574,7 +578,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
share->keyinfo[i].share= share;
disk_pos=_ma_keydef_read(disk_pos, &share->keyinfo[i]);
share->keyinfo[i].key_nr= i;
- disk_pos_assert(disk_pos + share->keyinfo[i].keysegs * HA_KEYSEG_SIZE,
+ disk_pos_assert(share,
+ disk_pos + share->keyinfo[i].keysegs * HA_KEYSEG_SIZE,
end_pos);
if (share->keyinfo[i].key_alg == HA_KEY_ALG_RTREE)
share->have_rtree= 1;
@@ -622,7 +627,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
pos[0].language= pos[-1].language;
if (!(pos[0].charset= pos[-1].charset))
{
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
goto err;
}
pos++;
@@ -654,7 +659,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
for (i=0 ; i < uniques ; i++)
{
disk_pos=_ma_uniquedef_read(disk_pos, &share->uniqueinfo[i]);
- disk_pos_assert(disk_pos + share->uniqueinfo[i].keysegs *
+ disk_pos_assert(share,
+ disk_pos + share->uniqueinfo[i].keysegs *
HA_KEYSEG_SIZE, end_pos);
share->uniqueinfo[i].seg=pos;
for (j=0 ; j < share->uniqueinfo[i].keysegs; j++,pos++)
@@ -758,7 +764,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
share->base.extra_rec_buff_size,
share->base.max_key_length);
- disk_pos_assert(disk_pos + share->base.fields *MARIA_COLUMNDEF_SIZE,
+ disk_pos_assert(share,
+ disk_pos + share->base.fields *MARIA_COLUMNDEF_SIZE,
end_pos);
for (i= j= 0 ; i < share->base.fields ; i++)
{
@@ -796,7 +803,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
share->options|= HA_OPTION_READ_ONLY_DATA;
share->is_log_table= FALSE;
- if (open_flags & HA_OPEN_TMP_TABLE)
+ if (open_flags & HA_OPEN_TMP_TABLE ||
+ (share->options & HA_OPTION_TMP_TABLE))
{
share->options|= HA_OPTION_TMP_TABLE;
share->temporary= share->delay_key_write= 1;
@@ -920,6 +928,19 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
}
}
#endif
+#ifdef SAFE_MUTEX
+ if (share->data_file_type == BLOCK_RECORD)
+ {
+ /*
+ We must have internal_lock before bitmap_lock because we call
+ _ma_flush_tables_files() with internal_lock locked.
+ */
+ pthread_mutex_lock(&share->intern_lock);
+ pthread_mutex_lock(&share->bitmap.bitmap_lock);
+ pthread_mutex_unlock(&share->bitmap.bitmap_lock);
+ pthread_mutex_unlock(&share->intern_lock);
+ }
+#endif
/*
Memory mapping can only be requested after initializing intern_lock.
*/
@@ -1273,7 +1294,8 @@ uint _ma_state_info_write(MARIA_SHARE *share, uint pWrite)
res= _ma_state_info_write_sub(share->kfile.file, &share->state, pWrite);
if (pWrite & MA_STATE_INFO_WRITE_LOCK)
pthread_mutex_unlock(&share->intern_lock);
- share->changed= 0;
+ /* If open_count != 0 we have to write the state again at close */
+ share->changed= share->state.open_count != 0;
return res;
}
@@ -1902,7 +1924,7 @@ int maria_enable_indexes(MARIA_HA *info)
DBUG_PRINT("error", ("data_file_length: %lu key_file_length: %lu",
(ulong) share->state.state.data_file_length,
(ulong) share->state.state.key_file_length));
- maria_print_error(info->s, HA_ERR_CRASHED);
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
error= HA_ERR_CRASHED;
}
else
diff --git a/storage/maria/ma_packrec.c b/storage/maria/ma_packrec.c
index 4df00d9bb88..90c8b4c49df 100644
--- a/storage/maria/ma_packrec.c
+++ b/storage/maria/ma_packrec.c
@@ -193,7 +193,7 @@ static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file,
/* Only the first three bytes of magic number are independent of version. */
if (memcmp(header, maria_pack_file_magic, 3))
{
- my_errno=HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
goto err0;
}
share->pack.version= header[3]; /* fourth uchar of magic number */
@@ -330,7 +330,7 @@ static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file,
DBUG_RETURN(0);
err3:
- my_errno=HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
err2:
my_free(share->decode_tables, MYF(0));
err1:
@@ -759,7 +759,7 @@ int _ma_read_pack_record(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos)
DBUG_RETURN(_ma_pack_rec_unpack(info,&info->bit_buff, buf,
info->rec_buff, block_info.rec_len));
panic:
- my_errno=HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(info->s, HA_ERR_WRONG_IN_RECORD);
err:
DBUG_RETURN(my_errno);
}
@@ -794,7 +794,8 @@ int _ma_pack_rec_unpack(register MARIA_HA *info, MARIA_BIT_BUFF *bit_buff,
bit_buff->pos - bit_buff->bits / 8 == bit_buff->end)
DBUG_RETURN(0);
info->update&= ~HA_STATE_AKTIV;
- DBUG_RETURN(my_errno=HA_ERR_WRONG_IN_RECORD);
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
+ DBUG_RETURN(HA_ERR_WRONG_IN_RECORD);
} /* _ma_pack_rec_unpack */
@@ -1359,7 +1360,7 @@ int _ma_read_rnd_pack_record(MARIA_HA *info,
file= info->dfile.file;
if (info->opt_flag & READ_CACHE_USED)
{
- if (_ma_read_cache(&info->rec_cache, block_info.header,
+ if (_ma_read_cache(info, &info->rec_cache, block_info.header,
filepos, share->pack.ref_length,
skip_deleted_blocks ? READING_NEXT : 0))
goto err;
@@ -1372,14 +1373,14 @@ int _ma_read_rnd_pack_record(MARIA_HA *info,
#ifndef DBUG_OFF
if (block_info.rec_len > share->max_pack_length)
{
- my_errno=HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
goto err;
}
#endif
if (info->opt_flag & READ_CACHE_USED)
{
- if (_ma_read_cache(&info->rec_cache, info->rec_buff,
+ if (_ma_read_cache(info, &info->rec_cache, info->rec_buff,
block_info.filepos, block_info.rec_len,
skip_deleted_blocks ? READING_NEXT : 0))
goto err;
@@ -1645,7 +1646,7 @@ static int _ma_read_rnd_mempack_record(MARIA_HA *info,
#ifndef DBUG_OFF
if (block_info.rec_len > info->s->max_pack_length)
{
- my_errno=HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
goto err;
}
#endif
diff --git a/storage/maria/ma_page.c b/storage/maria/ma_page.c
index a4423133270..bcd50f028ec 100644
--- a/storage/maria/ma_page.c
+++ b/storage/maria/ma_page.c
@@ -127,8 +127,7 @@ my_bool _ma_fetch_keypage(MARIA_PAGE *page, MARIA_HA *info,
{
DBUG_PRINT("error",("Got errno: %d from pagecache_read",my_errno));
info->last_keypage=HA_OFFSET_ERROR;
- maria_print_error(share, HA_ERR_CRASHED);
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
DBUG_RETURN(1);
}
info->last_keypage= pos;
@@ -159,8 +158,7 @@ my_bool _ma_fetch_keypage(MARIA_PAGE *page, MARIA_HA *info,
_ma_get_keynr(share, tmp)));
DBUG_DUMP("page", tmp, page_size);
info->last_keypage = HA_OFFSET_ERROR;
- maria_print_error(share, HA_ERR_CRASHED);
- my_errno= HA_ERR_CRASHED;
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
DBUG_RETURN(1);
}
}
@@ -552,8 +550,7 @@ my_bool _ma_compact_keypage(MARIA_PAGE *ma_page, TrID min_read_from)
{
DBUG_PRINT("error",("Couldn't find last key: page_pos: 0x%lx",
(long) page));
- maria_print_error(share, HA_ERR_CRASHED);
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
DBUG_RETURN(1);
}
if (key_has_transid(page-1))
diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c
index 42a42b65b8d..0e44b0e7a22 100644
--- a/storage/maria/ma_pagecache.c
+++ b/storage/maria/ma_pagecache.c
@@ -97,9 +97,9 @@
#define PCBLOCK_INFO(B) \
DBUG_PRINT("info", \
- ("block: 0x%lx fd: %lu page: %lu s: %0x hshL: " \
- " 0x%lx req: %u/%u wrlocks: %u rdlocks %u " \
- "rdlocks_q: %u pins: %u status: %u type: %s", \
+ ("block: 0x%lx fd: %lu page: %lu status: 0x%x " \
+ "hshL: 0x%lx requests: %u/%u wrlocks: %u rdlocks: %u " \
+ "rdlocks_q: %u pins: %u type: %s", \
(ulong)(B), \
(ulong)((B)->hash_link ? \
(B)->hash_link->file.file : \
@@ -107,14 +107,14 @@
(ulong)((B)->hash_link ? \
(B)->hash_link->pageno : \
0), \
- (B)->status, \
+ (uint) (B)->status, \
(ulong)(B)->hash_link, \
(uint) (B)->requests, \
(uint)((B)->hash_link ? \
(B)->hash_link->requests : \
0), \
- block->wlocks, block->rlocks, block->rlocks_queue, \
- (uint)(B)->pins, (uint)(B)->status, \
+ (B)->wlocks, (B)->rlocks, (B)->rlocks_queue, \
+ (uint)(B)->pins, \
page_cache_page_type_str[(B)->type]))
/* TODO: put it to my_static.c */
@@ -153,8 +153,23 @@ struct st_pagecache_hash_link
/* simple states of a block */
#define PCBLOCK_ERROR 1 /* an error occurred when performing disk i/o */
#define PCBLOCK_READ 2 /* the is page in the block buffer */
-#define PCBLOCK_IN_SWITCH 4 /* block is preparing to read new page */
-#define PCBLOCK_REASSIGNED 8 /* block does not accept requests for old page */
+
+/*
+ A tread is reading the data to the page.
+ If the page contained old changed data, it will be written out with
+ this state set on the block.
+ The page is not yet ready to be used for reading.
+*/
+#define PCBLOCK_IN_SWITCH 4
+/*
+ Block does not accept new requests for old page that would cause
+ the page to be pinned or written to.
+ (Reads that copies the block can still continue).
+ This state happens when another thread is waiting for readers to finish
+ to read data to the block (after the block, if it was changed, has been
+ flushed out to disk).
+*/
+#define PCBLOCK_REASSIGNED 8
#define PCBLOCK_IN_FLUSH 16 /* block is in flush operation */
#define PCBLOCK_CHANGED 32 /* block buffer contains a dirty page */
#define PCBLOCK_DIRECT_W 64 /* possible direct write to the block */
@@ -516,6 +531,7 @@ static void pagecache_debug_print _VARARGS((const char *fmt, ...));
#endif /* defined(PAGECACHE_DEBUG_LOG) */
#if defined(PAGECACHE_DEBUG_LOG) && defined(PAGECACHE_DEBUG)
+#define KEYCACHE_PRINT(l, m) KEYCACHE_DBUG_PRINT(l,m)
#define KEYCACHE_DBUG_PRINT(l, m) \
{ if (pagecache_debug_log) \
fprintf(pagecache_debug_log, "%s: ", l); \
@@ -526,6 +542,7 @@ static void pagecache_debug_print _VARARGS((const char *fmt, ...));
fclose(pagecache_debug_log); \
assert(a); }
#else
+#define KEYCACHE_PRINT(l, m)
#define KEYCACHE_DBUG_PRINT(l, m) DBUG_PRINT(l, m)
#define KEYCACHE_DBUG_ASSERT(a) DBUG_ASSERT(a)
#endif /* defined(PAGECACHE_DEBUG_LOG) && defined(PAGECACHE_DEBUG) */
@@ -549,6 +566,7 @@ static long pagecache_thread_id;
#define KEYCACHE_THREAD_TRACE_END(l) KEYCACHE_DBUG_PRINT(l,(""))
#endif /* THREAD */
#else
+#define KEYCACHE_PRINT(l,m)
#define KEYCACHE_THREAD_TRACE_BEGIN(l)
#define KEYCACHE_THREAD_TRACE_END(l)
#define KEYCACHE_THREAD_TRACE(l)
@@ -615,6 +633,26 @@ static my_bool pagecache_fwrite(PAGECACHE *pagecache,
DBUG_ENTER("pagecache_fwrite");
DBUG_ASSERT(type != PAGECACHE_READ_UNKNOWN_PAGE);
+#ifdef EXTRA_DEBUG_BITMAP
+ /*
+ This code is very good when debugging changes in bitmaps or dirty lists
+ The above define should be defined for all Aria files if you want to
+ debug either of the above issues.
+ */
+
+ if (pagecache->extra_debug)
+ {
+ char buff[80];
+ uint len= my_sprintf(buff,
+ (buff, "fwrite: fd: %d id: %u page: %lu",
+ filedesc->file,
+ _ma_file_callback_to_id(filedesc->callback_data),
+ (ulong) pageno));
+ (void) translog_log_debug_info(0, LOGREC_DEBUG_INFO_QUERY,
+ (uchar*) buff, len);
+ }
+#endif
+
/* Todo: Integrate this with write_callback so we have only one callback */
if ((*filedesc->flush_log_callback)(buffer, pageno, filedesc->callback_data))
DBUG_RETURN(1);
@@ -1343,6 +1381,8 @@ static void link_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block,
else
{
/* The LRU chain is empty */
+ /* QQ: Ask sanja if next line is correct; Should we really put block
+ in both chain if one chain is empty ? */
pagecache->used_last= pagecache->used_ins= block->next_used= block;
block->prev_used= &block->next_used;
}
@@ -1377,7 +1417,7 @@ static void link_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block,
static void unlink_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block)
{
DBUG_ENTER("unlink_block");
- DBUG_PRINT("unlink_block", ("unlink 0x%lx", (ulong)block));
+ DBUG_PRINT("pagecache", ("unlink 0x%lx", (ulong)block));
DBUG_ASSERT(block->next_used != NULL);
if (block->next_used == block)
{
@@ -1401,7 +1441,7 @@ static void unlink_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block)
#if defined(PAGECACHE_DEBUG)
KEYCACHE_DBUG_ASSERT(pagecache->blocks_available != 0);
pagecache->blocks_available--;
- KEYCACHE_DBUG_PRINT("unlink_block",
+ KEYCACHE_DBUG_PRINT("pagecache",
("unlinked block: 0x%lx (%u) status: %x #requests: %u #available: %u",
(ulong)block, PCBLOCK_NUMBER(pagecache, block),
block->status,
@@ -1429,9 +1469,6 @@ static void reg_requests(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block,
int count)
{
DBUG_ENTER("reg_requests");
- DBUG_PRINT("enter", ("block: 0x%lx (%u) status: %x reqs: %u",
- (ulong)block, PCBLOCK_NUMBER(pagecache, block),
- block->status, block->requests));
PCBLOCK_INFO(block);
if (! block->requests)
/* First request for the block unlinks it */
@@ -1663,9 +1700,9 @@ static PAGECACHE_HASH_LINK *get_present_hash_link(PAGECACHE *pagecache,
int cnt;
#endif
DBUG_ENTER("get_present_hash_link");
-
- KEYCACHE_DBUG_PRINT("get_present_hash_link", ("fd: %u pos: %lu",
- (uint) file->file, (ulong) pageno));
+ DBUG_PRINT("enter", ("fd: %u pos: %lu", (uint) file->file, (ulong) pageno));
+ KEYCACHE_PRINT("get_present_hash_link", ("fd: %u pos: %lu",
+ (uint) file->file, (ulong) pageno));
/*
Find the bucket in the hash table for the pair (file, pageno);
@@ -1769,6 +1806,7 @@ restart:
link_hash(start, hash_link);
/* Register the request for the page */
hash_link->requests++;
+ DBUG_ASSERT(hash_link->block == 0);
}
return hash_link;
@@ -1788,7 +1826,12 @@ restart:
pageno number of the page in the file
init_hits_left how initialize the block counter for the page
wrmode <-> get for writing
- reg_req Register request to thye page
+ block_is_copied 1 if block will be copied from page cache under
+ the pagelock mutex.
+ reg_req Register request to the page. Normally all pages
+ should be registered; The only time it's ok to
+ not register a page is when the page is already
+ pinned (and thus registered) by the same thread.
page_st out {PAGE_READ,PAGE_TO_BE_READ,PAGE_WAIT_TO_BE_READ}
RETURN VALUE
@@ -1817,6 +1860,7 @@ static PAGECACHE_BLOCK_LINK *find_block(PAGECACHE *pagecache,
pgcache_page_no_t pageno,
int init_hits_left,
my_bool wrmode,
+ my_bool block_is_copied,
my_bool reg_req,
int *page_st)
{
@@ -1824,14 +1868,12 @@ static PAGECACHE_BLOCK_LINK *find_block(PAGECACHE *pagecache,
PAGECACHE_BLOCK_LINK *block;
int error= 0;
int page_status;
-
DBUG_ENTER("find_block");
- KEYCACHE_THREAD_TRACE("find_block:begin");
- DBUG_PRINT("enter", ("fd: %d pos: %lu wrmode: %d",
- file->file, (ulong) pageno, wrmode));
- KEYCACHE_DBUG_PRINT("find_block", ("fd: %d pos: %lu wrmode: %d",
- file->file, (ulong) pageno,
- wrmode));
+ DBUG_PRINT("enter", ("fd: %d pos: %lu wrmode: %d block_is_copied: %d",
+ file->file, (ulong) pageno, wrmode, block_is_copied));
+ KEYCACHE_PRINT("find_block", ("fd: %d pos: %lu wrmode: %d",
+ file->file, (ulong) pageno,
+ wrmode));
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
DBUG_EXECUTE("check_pagecache",
test_key_cache(pagecache, "start of find_block", 0););
@@ -1922,7 +1964,7 @@ restart:
Only reading requests can proceed until the old dirty page is flushed,
all others are to be suspended, then resubmitted
*/
- if (!wrmode && !(block->status & PCBLOCK_REASSIGNED))
+ if (!wrmode && block_is_copied && !(block->status & PCBLOCK_REASSIGNED))
{
if (reg_req)
reg_requests(pagecache, block, 1);
@@ -1993,6 +2035,7 @@ restart:
#ifndef DBUG_OFF
block->type= PAGECACHE_EMPTY_PAGE;
#endif
+ DBUG_ASSERT(reg_req);
block->requests= 1;
block->temperature= PCBLOCK_COLD;
block->hits_left= init_hits_left;
@@ -2002,11 +2045,11 @@ restart:
block->hash_link= hash_link;
hash_link->block= block;
page_status= PAGE_TO_BE_READ;
- DBUG_PRINT("info", ("page to be read set for page 0x%lx",
- (ulong)block));
- KEYCACHE_DBUG_PRINT("find_block",
- ("got free or never used block %u",
- PCBLOCK_NUMBER(pagecache, block)));
+ DBUG_PRINT("info", ("page to be read set for page 0x%lx (%u)",
+ (ulong) block, PCBLOCK_NUMBER(pagecache, block)));
+ KEYCACHE_PRINT("find_block",
+ ("got free or never used block %u",
+ PCBLOCK_NUMBER(pagecache, block)));
}
else
{
@@ -2033,12 +2076,17 @@ restart:
}
while (thread->next);
thread->opt_info= NULL;
+ block= hash_link->block;
+ /*
+ Ensure that we are register this block (all blocks not used by this
+ thread has to be registered).
+ */
+ DBUG_ASSERT(reg_req);
}
+ else
#else
KEYCACHE_DBUG_ASSERT(pagecache->used_last);
#endif
- block= hash_link->block;
- if (! block)
{
/*
Take the first block from the LRU chain
@@ -2116,7 +2164,7 @@ restart:
(my_bool)(block->hash_link ? 1 : 0));
PCBLOCK_INFO(block);
block->status= error ? PCBLOCK_ERROR : 0;
- block->error= (int16) my_errno;
+ block->error= error ? (int16) my_errno : 0;
#ifndef DBUG_OFF
block->type= PAGECACHE_EMPTY_PAGE;
if (error)
@@ -2163,11 +2211,11 @@ restart:
("block: 0x%lx fd: %u pos: %lu block->status: %u page_status: %u",
(ulong) block, (uint) file->file,
(ulong) pageno, block->status, (uint) page_status));
- KEYCACHE_DBUG_PRINT("find_block",
- ("block: 0x%lx fd: %d pos: %lu block->status: %u page_status: %d",
- (ulong) block,
- file->file, (ulong) pageno, block->status,
- page_status));
+ KEYCACHE_PRINT("find_block",
+ ("block: 0x%lx fd: %d pos: %lu block->status: %u page_status: %d",
+ (ulong) block,
+ file->file, (ulong) pageno, block->status,
+ page_status));
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
DBUG_EXECUTE("check_pagecache",
@@ -2517,22 +2565,13 @@ static my_bool make_lock_and_pin(PAGECACHE *pagecache,
my_bool any)
{
DBUG_ENTER("make_lock_and_pin");
+ DBUG_PRINT("enter", ("block: 0x%lx (%u) lock: %s pin: %s any %d",
+ (ulong)block, PCBLOCK_NUMBER(pagecache, block),
+ page_cache_page_lock_str[lock],
+ page_cache_page_pin_str[pin], (int)any));
+ PCBLOCK_INFO(block);
- DBUG_PRINT("enter", ("block: 0x%lx", (ulong)block));
-#ifndef DBUG_OFF
- if (block)
- {
- DBUG_PRINT("enter", ("block: 0x%lx (%u) wrlocks: %u rdlocks: %u "
- "rdlocks_q: %u pins: %u lock: %s pin: %s any %d",
- (ulong)block, PCBLOCK_NUMBER(pagecache, block),
- block->wlocks, block->rlocks, block->rlocks_queue,
- block->pins,
- page_cache_page_lock_str[lock],
- page_cache_page_pin_str[pin], (int)any));
- PCBLOCK_INFO(block);
- }
-#endif
-
+ DBUG_ASSERT(block);
DBUG_ASSERT(!any ||
((lock == PAGECACHE_LOCK_LEFT_UNLOCKED) &&
(pin == PAGECACHE_UNPIN)));
@@ -2600,17 +2639,13 @@ static my_bool make_lock_and_pin(PAGECACHE *pagecache,
DBUG_ASSERT(0); /* Never should happened */
}
-#ifndef DBUG_OFF
- if (block)
- PCBLOCK_INFO(block);
-#endif
+ PCBLOCK_INFO(block);
DBUG_RETURN(0);
retry:
DBUG_PRINT("INFO", ("Retry block 0x%lx", (ulong)block));
PCBLOCK_INFO(block);
DBUG_ASSERT(block->hash_link->requests > 0);
block->hash_link->requests--;
- PCBLOCK_INFO(block);
DBUG_RETURN(1);
}
@@ -2642,7 +2677,6 @@ static void read_block(PAGECACHE *pagecache,
PAGECACHE_BLOCK_LINK *block,
my_bool primary)
{
-
DBUG_ENTER("read_block");
DBUG_PRINT("enter", ("read block: 0x%lx primary: %d",
(ulong)block, primary));
@@ -2804,8 +2838,7 @@ void pagecache_unlock(PAGECACHE *pagecache,
page_cache_page_pin_str[pin]));
/* we do not allow any lock/pin increasing here */
DBUG_ASSERT(pin != PAGECACHE_PIN);
- DBUG_ASSERT(lock != PAGECACHE_LOCK_READ);
- DBUG_ASSERT(lock != PAGECACHE_LOCK_WRITE);
+ DBUG_ASSERT(lock != PAGECACHE_LOCK_READ && lock != PAGECACHE_LOCK_WRITE);
pagecache_pthread_mutex_lock(&pagecache->cache_lock);
/*
@@ -2816,7 +2849,7 @@ void pagecache_unlock(PAGECACHE *pagecache,
inc_counter_for_resize_op(pagecache);
/* See NOTE for pagecache_unlock about registering requests */
- block= find_block(pagecache, file, pageno, 0, 0,
+ block= find_block(pagecache, file, pageno, 0, 0, 0,
pin == PAGECACHE_PIN_LEFT_UNPINNED, &page_st);
PCBLOCK_INFO(block);
DBUG_ASSERT(block != 0 && page_st == PAGE_READ);
@@ -2905,7 +2938,7 @@ void pagecache_unpin(PAGECACHE *pagecache,
inc_counter_for_resize_op(pagecache);
/* See NOTE for pagecache_unlock about registering requests */
- block= find_block(pagecache, file, pageno, 0, 0, 0, &page_st);
+ block= find_block(pagecache, file, pageno, 0, 0, 0, 0, &page_st);
DBUG_ASSERT(block != 0);
DBUG_ASSERT(page_st == PAGE_READ);
/* we can't unpin such page without unlock */
@@ -3349,7 +3382,7 @@ restart:
reg_request= ((new_pin == PAGECACHE_PIN_LEFT_UNPINNED) ||
(new_pin == PAGECACHE_PIN));
block= find_block(pagecache, file, pageno, level,
- lock == PAGECACHE_LOCK_WRITE,
+ lock == PAGECACHE_LOCK_WRITE, buff != 0,
reg_request, &page_st);
DBUG_PRINT("info", ("Block type: %s current type %s",
page_cache_page_type_str[block->type],
@@ -3402,8 +3435,7 @@ restart:
buff= block->buffer;
/* possibly we will write here (resolved on unlock) */
if ((lock == PAGECACHE_LOCK_WRITE ||
- lock == PAGECACHE_LOCK_LEFT_WRITELOCKED) &&
- !(block->status & PCBLOCK_CHANGED))
+ lock == PAGECACHE_LOCK_LEFT_WRITELOCKED))
{
block->status|= PCBLOCK_DIRECT_W;
DBUG_PRINT("info", ("Set PCBLOCK_DIRECT_W for block: 0x%lx",
@@ -3436,7 +3468,10 @@ restart:
if (make_lock_and_pin(pagecache, block,
lock_to_read[lock].unlock_lock,
unlock_pin, FALSE))
+ {
DBUG_ASSERT(0);
+ return (uchar*) 0;
+ }
}
/*
Link the block into the LRU chain if it's the last submitted request
@@ -3792,7 +3827,6 @@ restart:
/* See NOTE for pagecache_unlock about registering requests. */
if (pin == PAGECACHE_PIN)
reg_requests(pagecache, block, 1);
- DBUG_ASSERT(block != 0);
if (make_lock_and_pin(pagecache, block, lock, pin, FALSE))
{
/*
@@ -3967,11 +4001,14 @@ restart:
inc_counter_for_resize_op(pagecache);
pagecache->global_cache_w_requests++;
- /* See NOTE for pagecache_unlock about registering requests. */
+ /*
+ Here we register a request if the page was not already pinned.
+ See NOTE for pagecache_unlock about registering requests.
+ */
reg_request= ((pin == PAGECACHE_PIN_LEFT_UNPINNED) ||
(pin == PAGECACHE_PIN));
block= find_block(pagecache, file, pageno, level,
- TRUE,
+ TRUE, FALSE,
reg_request, &page_st);
if (!block)
{
@@ -4116,7 +4153,10 @@ restart:
block->hash_link->requests--;
/* See NOTE for pagecache_unlock about registering requests. */
if (pin == PAGECACHE_PIN_LEFT_UNPINNED || pin == PAGECACHE_UNPIN)
+ {
unreg_request(pagecache, block, 1);
+ DBUG_ASSERT(page_link == &fake_link);
+ }
else
*page_link= block;
@@ -4331,15 +4371,13 @@ static int flush_cached_blocks(PAGECACHE *pagecache,
PAGECACHE_LOCK_READ, PAGECACHE_PIN, FALSE))
DBUG_ASSERT(0);
- KEYCACHE_DBUG_PRINT("flush_cached_blocks",
- ("block: %u (0x%lx) to be flushed",
- PCBLOCK_NUMBER(pagecache, block), (ulong)block));
- DBUG_PRINT("info", ("block: %u (0x%lx) to be flushed",
+ KEYCACHE_PRINT("flush_cached_blocks",
+ ("block: %u (0x%lx) to be flushed",
+ PCBLOCK_NUMBER(pagecache, block), (ulong)block));
+ DBUG_PRINT("info", ("block: %u (0x%lx) to be flushed",
PCBLOCK_NUMBER(pagecache, block), (ulong)block));
PCBLOCK_INFO(block);
- DBUG_PRINT("info", ("block: %u (0x%lx) pins: %u",
- PCBLOCK_NUMBER(pagecache, block), (ulong)block,
- block->pins));
+
/**
@todo IO If page is contiguous with next page to flush, group flushes
in one single my_pwrite().
diff --git a/storage/maria/ma_pagecache.h b/storage/maria/ma_pagecache.h
index 475729bd46d..ca2a3822f66 100644
--- a/storage/maria/ma_pagecache.h
+++ b/storage/maria/ma_pagecache.h
@@ -173,6 +173,7 @@ typedef struct st_pagecache
my_bool resize_in_flush; /* true during flush of resize operation */
my_bool can_be_used; /* usage of cache for read/write is allowed */
my_bool in_init; /* Set to 1 in MySQL during init/resize */
+ my_bool extra_debug; /* set to 1 if one wants extra logging */
HASH files_in_flush; /**< files in flush_pagecache_blocks_int() */
} PAGECACHE;
diff --git a/storage/maria/ma_pagecrc.c b/storage/maria/ma_pagecrc.c
index 640bb8880f4..58e3b4b203d 100644
--- a/storage/maria/ma_pagecrc.c
+++ b/storage/maria/ma_pagecrc.c
@@ -355,9 +355,7 @@ my_bool maria_flush_log_for_page(uchar *page,
uchar *data_ptr __attribute__((unused)))
{
LSN lsn;
-#ifndef DBUG_OFF
- const MARIA_SHARE *share= (MARIA_SHARE*) data_ptr;
-#endif
+ MARIA_SHARE *share= (MARIA_SHARE*) data_ptr;
DBUG_ENTER("maria_flush_log_for_page");
/* share is 0 here only in unittest */
DBUG_ASSERT(!share || (share->page_type == PAGECACHE_LSN_PAGE &&
@@ -365,6 +363,12 @@ my_bool maria_flush_log_for_page(uchar *page,
lsn= lsn_korr(page);
if (translog_flush(lsn))
DBUG_RETURN(1);
+ /*
+ Now when log is written, it's safe to incremented 'open' counter for
+ the table so that we know it was not closed properly.
+ */
+ if (share && !share->global_changed)
+ _ma_mark_file_changed_now(share);
DBUG_RETURN(0);
}
diff --git a/storage/maria/ma_panic.c b/storage/maria/ma_panic.c
index a86563f31fb..c723ab0b2b8 100644
--- a/storage/maria/ma_panic.c
+++ b/storage/maria/ma_panic.c
@@ -67,8 +67,8 @@ int maria_panic(enum ha_panic_function flag)
if (info->s->options & HA_OPTION_READ_ONLY_DATA)
break;
#endif
- if (flush_pagecache_blocks(info->s->pagecache, &info->s->kfile,
- FLUSH_RELEASE))
+ if (_ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
+ FLUSH_RELEASE, FLUSH_RELEASE))
error=my_errno;
if (info->opt_flag & WRITE_CACHE_USED)
if (flush_io_cache(&info->rec_cache))
@@ -92,8 +92,8 @@ int maria_panic(enum ha_panic_function flag)
if (info->dfile.file >= 0 && my_close(info->dfile.file, MYF(0)))
error = my_errno;
info->s->kfile.file= info->dfile.file= -1;/* Files aren't open anymore */
- break;
#endif
+ break;
case HA_PANIC_READ: /* Restore to before WRITE */
#ifdef CANT_OPEN_FILES_TWICE
{ /* Open closed files */
diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c
index d2c7bf3d381..5be30dee0b5 100644
--- a/storage/maria/ma_recovery.c
+++ b/storage/maria/ma_recovery.c
@@ -1,5 +1,5 @@
/* Copyright (C) 2006, 2007 MySQL AB
- Copyright (C) 2010 Monty Program Ab
+ Copyright (C) 2010-2011 Monty Program Ab
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
@@ -642,6 +642,7 @@ static void new_transaction(uint16 sid, TrID long_id, LSN undo_lsn,
prototype_redo_exec_hook_dummy(CHECKPOINT)
{
/* the only checkpoint we care about was found via control file, ignore */
+ tprint(tracef, "CHECKPOINT found\n");
return 0;
}
@@ -1291,6 +1292,22 @@ prototype_redo_exec_hook(FILE_ID)
{
tprint(tracef, " Closing table '%s'\n", info->s->open_file_name.str);
prepare_table_for_close(info, rec->lsn);
+
+ /*
+ Ensure that open count is 1 on close. This is needed as the
+ table may initially had an open_count > 0 when we initially
+ opened it as the server may have crashed without closing it
+ properly. As we now have applied all redo's for the table up to
+ now, we know the table is ok, so it's safe to reset the open
+ count to 0.
+ */
+ if (info->s->state.open_count != 0 && info->s->reopen == 1)
+ {
+ /* let ma_close() mark the table properly closed */
+ info->s->state.open_count= 1;
+ info->s->global_changed= 1;
+ info->s->changed= 1;
+ }
if (maria_close(info))
{
eprint(tracef, "Failed to close table");
@@ -3411,9 +3428,10 @@ static int close_all_tables(void)
*/
if (info->s->state.open_count != 0)
{
- /* let ma_close() mark the table properly closed */
+ /* let maria_close() mark the table properly closed */
info->s->state.open_count= 1;
info->s->global_changed= 1;
+ info->s->changed= 1;
}
prepare_table_for_close(info, addr);
error|= maria_close(info);
diff --git a/storage/maria/ma_recovery_util.c b/storage/maria/ma_recovery_util.c
index ed9d8efc81b..2d65f59fd0a 100644
--- a/storage/maria/ma_recovery_util.c
+++ b/storage/maria/ma_recovery_util.c
@@ -59,9 +59,11 @@ void tprint(FILE *trace_file __attribute__ ((unused)),
va_list args;
#ifndef DBUG_OFF
{
- char buff[1024];
+ char buff[1024], *end;
va_start(args, format);
vsnprintf(buff, sizeof(buff)-1, format, args);
+ if (*(end= strend(buff)) == '\n')
+ *end= 0; /* Don't print end \n */
DBUG_PRINT("info", ("%s", buff));
va_end(args);
}
diff --git a/storage/maria/ma_rkey.c b/storage/maria/ma_rkey.c
index 4b0dde1860a..1ece9e0049e 100644
--- a/storage/maria/ma_rkey.c
+++ b/storage/maria/ma_rkey.c
@@ -93,8 +93,7 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data,
case HA_KEY_ALG_RTREE:
if (maria_rtree_find_first(info, &key, nextflag) < 0)
{
- maria_print_error(info->s, HA_ERR_CRASHED);
- my_errno= HA_ERR_CRASHED;
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
info->cur_row.lastpos= HA_OFFSET_ERROR;
}
break;
diff --git a/storage/maria/ma_rt_test.c b/storage/maria/ma_rt_test.c
index af54e6b27be..ed48883b858 100644
--- a/storage/maria/ma_rt_test.c
+++ b/storage/maria/ma_rt_test.c
@@ -93,9 +93,10 @@ static enum data_file_type record_type= DYNAMIC_RECORD;
int main(int argc, char *argv[])
{
+ char buff[FN_REFLEN];
MY_INIT(argv[0]);
- get_options(argc, argv);
maria_data_root= (char *)".";
+ get_options(argc, argv);
/* Maria requires that we always have a page cache */
if (maria_init() ||
(init_pagecache(maria_pagecache, maria_block_size * 16, 0, 0,
@@ -113,7 +114,7 @@ int main(int argc, char *argv[])
exit(1);
}
- exit(run_test("rt_test"));
+ exit(run_test(fn_format(buff, "test1", maria_data_root, "", MYF(0))));
}
@@ -614,6 +615,8 @@ static struct my_option my_long_options[] =
#endif
{"help", '?', "Display help and exit",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"datadir", 'h', "Path to the database root.", &maria_data_root,
+ &maria_data_root, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"row-fixed-size", 'S', "Fixed size records",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"rows-in-block", 'M', "Store rows in block format",
diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c
index df74fed842a..84123fec93a 100644
--- a/storage/maria/ma_search.c
+++ b/storage/maria/ma_search.c
@@ -383,8 +383,7 @@ int _ma_seq_search(const MARIA_KEY *key, const MARIA_PAGE *ma_page,
length=(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag, &page);
if (length == 0 || page > end)
{
- maria_print_error(share, HA_ERR_CRASHED);
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
DBUG_PRINT("error",
("Found wrong key: length: %u page: 0x%lx end: 0x%lx",
length, (long) page, (long) end));
@@ -566,8 +565,7 @@ int _ma_prefix_search(const MARIA_KEY *key, const MARIA_PAGE *ma_page,
if (page > end)
{
- maria_print_error(share, HA_ERR_CRASHED);
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
DBUG_PRINT("error",
("Found wrong key: length: %u page: 0x%lx end: %lx",
length, (long) page, (long) end));
@@ -1049,8 +1047,7 @@ uint _ma_get_pack_key(MARIA_KEY *int_key, uint page_flag,
{
if (length > (uint) keyseg->length)
{
- maria_print_error(keyinfo->share, HA_ERR_CRASHED);
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
return 0; /* Error */
}
if (length == 0) /* Same key */
@@ -1065,8 +1062,7 @@ uint _ma_get_pack_key(MARIA_KEY *int_key, uint page_flag,
("Found too long null packed key: %u of %u at 0x%lx",
length, keyseg->length, (long) *page_pos));
DBUG_DUMP("key", *page_pos, 16);
- maria_print_error(keyinfo->share, HA_ERR_CRASHED);
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
return 0;
}
continue;
@@ -1123,8 +1119,7 @@ uint _ma_get_pack_key(MARIA_KEY *int_key, uint page_flag,
DBUG_PRINT("error",("Found too long packed key: %u of %u at 0x%lx",
length, keyseg->length, (long) *page_pos));
DBUG_DUMP("key", *page_pos, 16);
- maria_print_error(keyinfo->share, HA_ERR_CRASHED);
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
return 0; /* Error */
}
store_key_length_inc(key,length);
@@ -1283,8 +1278,7 @@ uint _ma_get_binary_pack_key(MARIA_KEY *int_key, uint page_flag, uint nod_flag,
("Found too long binary packed key: %u of %u at 0x%lx",
length, keyinfo->maxlength, (long) *page_pos));
DBUG_DUMP("key", *page_pos, 16);
- maria_print_error(keyinfo->share, HA_ERR_CRASHED);
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
DBUG_RETURN(0); /* Wrong key */
}
/* Key is packed against prev key, take prefix from prev key. */
@@ -1375,8 +1369,7 @@ uint _ma_get_binary_pack_key(MARIA_KEY *int_key, uint page_flag, uint nod_flag,
if (from_end != page_end)
{
DBUG_PRINT("error",("Error when unpacking key"));
- maria_print_error(keyinfo->share, HA_ERR_CRASHED);
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
DBUG_RETURN(0); /* Error */
}
}
@@ -1462,8 +1455,7 @@ uchar *_ma_get_key(MARIA_KEY *key, MARIA_PAGE *ma_page, uchar *keypos)
{
if (!(*keyinfo->get_key)(key, page_flag, nod_flag, &page))
{
- maria_print_error(keyinfo->share, HA_ERR_CRASHED);
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
DBUG_RETURN(0);
}
}
@@ -1513,8 +1505,7 @@ static my_bool _ma_get_prev_key(MARIA_KEY *key, MARIA_PAGE *ma_page,
{
if (! (*keyinfo->get_key)(key, page_flag, nod_flag, &page))
{
- maria_print_error(keyinfo->share, HA_ERR_CRASHED);
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
DBUG_RETURN(1);
}
}
@@ -1567,8 +1558,7 @@ uchar *_ma_get_last_key(MARIA_KEY *key, MARIA_PAGE *ma_page, uchar *endpos)
{
DBUG_PRINT("error",("Couldn't find last key: page: 0x%lx",
(long) page));
- maria_print_error(keyinfo->share, HA_ERR_CRASHED);
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
DBUG_RETURN(0);
}
}
diff --git a/storage/maria/ma_static.c b/storage/maria/ma_static.c
index 37814b42dc2..a97f642547a 100644
--- a/storage/maria/ma_static.c
+++ b/storage/maria/ma_static.c
@@ -38,6 +38,8 @@ my_bool maria_delay_key_write= 0, maria_page_checksums= 1;
my_bool maria_inited= FALSE;
my_bool maria_in_ha_maria= FALSE; /* If used from ha_maria or not */
my_bool maria_recovery_changed_data= 0, maria_recovery_verbose= 0;
+my_bool maria_assert_if_crashed_table= 0;
+
pthread_mutex_t THR_LOCK_maria;
#if defined(THREAD) && !defined(DONT_USE_RW_LOCKS)
ulong maria_concurrent_insert= 2;
diff --git a/storage/maria/ma_statrec.c b/storage/maria/ma_statrec.c
index 0aa3a3acbc1..f059132e370 100644
--- a/storage/maria/ma_statrec.c
+++ b/storage/maria/ma_statrec.c
@@ -297,6 +297,6 @@ int _ma_read_rnd_static_record(MARIA_HA *info, uchar *buf,
}
/* my_errno should be set if rec_cache.error == -1 */
if (info->rec_cache.error != -1 || my_errno == 0)
- my_errno=HA_ERR_WRONG_IN_RECORD;
+ _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD);
DBUG_RETURN(my_errno); /* Something wrong (EOF?) */
}
diff --git a/storage/maria/ma_test1.c b/storage/maria/ma_test1.c
index 1df1e6fd19b..4b0eb0f5644 100644
--- a/storage/maria/ma_test1.c
+++ b/storage/maria/ma_test1.c
@@ -70,12 +70,13 @@ extern int _ma_flush_table_files(MARIA_HA *info, uint flush_data_or_index,
int main(int argc,char *argv[])
{
+ char buff[FN_REFLEN];
#if defined(SAFE_MUTEX) && defined(THREAD)
safe_mutex_deadlock_detector= 1;
#endif
MY_INIT(argv[0]);
- get_options(argc,argv);
maria_data_root= (char *)".";
+ get_options(argc,argv);
/* Maria requires that we always have a page cache */
if (maria_init() ||
(init_pagecache(maria_pagecache, maria_block_size * 16, 0, 0,
@@ -95,7 +96,7 @@ int main(int argc,char *argv[])
if (opt_versioning)
init_thr_lock();
- exit(run_test("test1"));
+ exit(run_test(fn_format(buff, "test1", maria_data_root, "", MYF(0))));
}
@@ -734,6 +735,8 @@ static struct my_option my_long_options[] =
{"debug", '#', "Undocumented",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
+ {"datadir", 'h', "Path to the database root.", &maria_data_root,
+ &maria_data_root, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"delete-rows", 'd', "Abort after this many rows has been deleted",
(uchar**) &remove_count, (uchar**) &remove_count, 0, GET_UINT, REQUIRED_ARG,
1000, 0, 0, 0, 0, 0},
diff --git a/storage/maria/ma_test2.c b/storage/maria/ma_test2.c
index 9e2f32f767b..6ab8cae2915 100644
--- a/storage/maria/ma_test2.c
+++ b/storage/maria/ma_test2.c
@@ -69,24 +69,25 @@ int main(int argc, char *argv[])
MARIA_KEYDEF keyinfo[10];
MARIA_COLUMNDEF recinfo[10];
MARIA_INFO info;
- const char *filename;
char *blob_buffer;
MARIA_CREATE_INFO create_info;
+ char filename[FN_REFLEN];
#if defined(SAFE_MUTEX) && defined(THREAD)
safe_mutex_deadlock_detector= 1;
#endif
MY_INIT(argv[0]);
- filename= "test2";
+ maria_data_root= (char *)".";
get_options(argc,argv);
+ fn_format(filename, "test2", maria_data_root, "", MYF(0));
+
if (! async_io)
my_disable_async_io=1;
/* If we sync or not have no affect on this test */
my_disable_sync= 1;
- maria_data_root= (char *)".";
/* Maria requires that we always have a page cache */
if (maria_init() ||
(init_pagecache(maria_pagecache, pagecache_size, 0, 0,
@@ -1101,6 +1102,9 @@ static void get_options(int argc, char **argv)
case 'H':
checkpoint= atoi(++pos);
break;
+ case 'h':
+ maria_data_root= ++pos;
+ break;
case 'k':
if ((keys=(uint) atoi(++pos)) < 1 ||
keys > (uint) (MARIA_KEYS-first_key))
diff --git a/storage/maria/ma_update.c b/storage/maria/ma_update.c
index 7b9e006ec43..abd9116a711 100644
--- a/storage/maria/ma_update.c
+++ b/storage/maria/ma_update.c
@@ -74,7 +74,8 @@ int maria_update(register MARIA_HA *info, const uchar *oldrec, uchar *newrec)
goto err_end;
}
}
- if (_ma_mark_file_changed(info))
+
+ if (_ma_mark_file_changed(share))
{
save_errno=my_errno;
goto err_end;
@@ -216,7 +217,10 @@ err:
{
if ((flag++ && _ma_ft_del(info,i,new_key_buff,newrec,pos)) ||
_ma_ft_add(info,i,old_key_buff,oldrec,pos))
+ {
+ _ma_set_fatal_error(share, my_errno);
break;
+ }
}
else
{
@@ -228,16 +232,17 @@ err:
oldrec, pos, info->cur_row.trid);
if ((flag++ && _ma_ck_delete(info, &new_key)) ||
_ma_ck_write(info, &old_key))
+ {
+ _ma_set_fatal_error(share, my_errno);
break;
+ }
}
}
} while (i-- != 0);
}
else
- {
- maria_print_error(share, HA_ERR_CRASHED);
- maria_mark_crashed(info);
- }
+ _ma_set_fatal_error(share, save_errno);
+
info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_ROW_CHANGED |
key_changed);
@@ -245,9 +250,6 @@ err:
VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
allow_break(); /* Allow SIGHUP & SIGINT */
if (save_errno == HA_ERR_KEY_NOT_FOUND)
- {
- maria_print_error(share, HA_ERR_CRASHED);
- save_errno=HA_ERR_CRASHED;
- }
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
DBUG_RETURN(my_errno=save_errno);
} /* maria_update */
diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c
index 4057cce6c96..f3357bfb921 100644
--- a/storage/maria/ma_write.c
+++ b/storage/maria/ma_write.c
@@ -120,7 +120,7 @@ int maria_write(MARIA_HA *info, uchar *record)
my_errno=HA_ERR_INDEX_FILE_FULL;
goto err2;
}
- if (_ma_mark_file_changed(info))
+ if (_ma_mark_file_changed(share))
goto err2;
/* Calculate and check all unique constraints */
@@ -813,7 +813,7 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key,
{
if (t_length >= keyinfo->maxlength*2+MARIA_INDEX_OVERHEAD_SIZE)
{
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
DBUG_RETURN(-1);
}
bmove_upp(endpos+t_length, endpos, (uint) (endpos-key_pos));
@@ -822,7 +822,7 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key,
{
if (-t_length >= keyinfo->maxlength*2+MARIA_INDEX_OVERHEAD_SIZE)
{
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
DBUG_RETURN(-1);
}
bmove(key_pos,key_pos-t_length,(uint) (endpos-key_pos)+t_length);
@@ -1187,7 +1187,7 @@ static uchar *_ma_find_last_pos(MARIA_KEY *int_key, MARIA_PAGE *ma_page,
if (!(length=(*keyinfo->get_key)(&tmp_key, page_flag, 0, &page)))
{
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
DBUG_RETURN(0);
}
@@ -1200,7 +1200,7 @@ static uchar *_ma_find_last_pos(MARIA_KEY *int_key, MARIA_PAGE *ma_page,
memcpy(int_key->data, key_buff, length); /* previous key */
if (!(length=(*keyinfo->get_key)(&tmp_key, page_flag, 0, &page)))
{
- my_errno=HA_ERR_CRASHED;
+ _ma_set_fatal_error(share, HA_ERR_CRASHED);
DBUG_RETURN(0);
}
} while (page < end);
diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c
index 07ec9d6cd39..29cb56f426b 100644
--- a/storage/maria/maria_chk.c
+++ b/storage/maria/maria_chk.c
@@ -38,11 +38,13 @@ static uint decode_bits;
static char **default_argv;
static const char *load_default_groups[]= { "aria_chk", 0 };
static const char *set_collation_name, *opt_tmpdir, *opt_log_dir;
+static const char *default_log_dir;
static CHARSET_INFO *set_collation;
static int stopwords_inited= 0;
static MY_TMPDIR maria_chk_tmpdir;
-static my_bool opt_transaction_logging, opt_debug, opt_require_control_file;
-static my_bool opt_warning_for_wrong_transid;
+static my_bool opt_transaction_logging, opt_debug;
+static my_bool opt_ignore_control_file, opt_require_control_file;
+static my_bool opt_warning_for_wrong_transid, opt_update_state;
static const char *type_names[]=
{
@@ -105,7 +107,7 @@ int main(int argc, char **argv)
int error;
MY_INIT(argv[0]);
- opt_log_dir= maria_data_root= (char *)".";
+ default_log_dir= opt_log_dir= maria_data_root= (char *)".";
maria_chk_init(&check_param);
check_param.opt_lock_memory= 1; /* Lock memory if possible */
check_param.using_global_keycache = 0;
@@ -115,10 +117,11 @@ int main(int argc, char **argv)
maria_init();
maria_block_size= 0; /* Use block size from control file */
- if (ma_control_file_open(FALSE, opt_require_control_file ||
- !(check_param.testflag & T_SILENT)) &&
- (opt_require_control_file ||
- (opt_transaction_logging && (check_param.testflag & T_REP_ANY))))
+ if (!opt_ignore_control_file &&
+ (ma_control_file_open(FALSE, opt_require_control_file ||
+ !(check_param.testflag & T_SILENT)) &&
+ (opt_require_control_file ||
+ (opt_transaction_logging && (check_param.testflag & T_REP_ANY)))))
{
error= 1;
goto end;
@@ -203,8 +206,9 @@ enum options_mc {
OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN,
OPT_FT_MAX_WORD_LEN, OPT_FT_STOPWORD_FILE,
OPT_MAX_RECORD_LENGTH, OPT_AUTO_CLOSE, OPT_STATS_METHOD, OPT_TRANSACTION_LOG,
- OPT_SKIP_SAFEMALLOC, OPT_ZEROFILL_KEEP_LSN, OPT_REQUIRE_CONTROL_FILE,
- OPT_LOG_DIR, OPT_DATADIR, OPT_WARNING_FOR_WRONG_TRANSID
+ OPT_SKIP_SAFEMALLOC, OPT_ZEROFILL_KEEP_LSN,
+ OPT_REQUIRE_CONTROL_FILE, OPT_IGNORE_CONTROL_FILE,
+ OPT_LOG_DIR, OPT_WARNING_FOR_WRONG_TRANSID
};
static struct my_option my_long_options[] =
@@ -265,12 +269,16 @@ static struct my_option my_long_options[] =
{"information", 'i',
"Print statistics information about table that is checked.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ { "ignore-control-file", OPT_IGNORE_CONTROL_FILE,
+ "Ignore the control file",
+ (uchar**)&opt_ignore_control_file, 0, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
{"keys-used", 'k',
"Tell Aria to update only some specific keys. # is a bit mask of which keys to use. This can be used to get faster inserts.",
&check_param.keys_in_use,
&check_param.keys_in_use,
0, GET_ULL, REQUIRED_ARG, -1, 0, 0, 0, 0, 0},
- {"datadir", OPT_DATADIR,
+ {"datadir", 'h',
"Path for control file (and logs if --logdir not used).",
&maria_data_root, 0, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
@@ -345,10 +353,13 @@ static struct my_option my_long_options[] =
&opt_transaction_logging, &opt_transaction_logging,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"update-state", 'U',
- "Mark tables as crashed if any errors were found and clean if check didn't "
- "find any errors. This allows one to get rid of warnings like 'table not "
- "properly closed'",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ "Mark tables as crashed if any errors were found and clean if check "
+ "didn't find any errors but table was marked as 'not clean' before. This "
+ "allows one to get rid of warnings like 'table not properly closed'. "
+ "If table was updated, update also the timestamp for when check was made. "
+ "This option is on by default!",
+ &opt_update_state, &opt_update_state, 0, GET_BOOL, NO_ARG,
+ 1, 0, 0, 0, 0, 0},
{"unpack", 'u',
"Unpack file packed with aria_pack.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -449,6 +460,9 @@ static void usage(void)
-?, --help Display this help and exit.\n\
--datadir=path Path for control file (and logs if --logdir not used)\n\
--logdir=path Path for log files\n\
+ --ignore-control-file Don't open the control file. Only use this if you\n\
+ are sure the tables are not in use by another\n\
+ program!\n\
--require-control-file Abort if we can't find/read the maria_log_control\n\
file\n\
-s, --silent Only print errors. One can use two -s to make\n\
@@ -483,8 +497,18 @@ static void usage(void)
-i, --information Print statistics information about table that is checked.\n\
-m, --medium-check Faster than extend-check, but only finds 99.99% of\n\
all errors. Should be good enough for most cases.\n\
- -U, --update-state Mark tables as crashed if you find any errors.\n\
- -T, --read-only Don't mark table as checked.\n");
+ -T, --read-only Don't mark table as checked.\n\
+ -U, --update-state Mark tables as crashed if any errors were found and\n\
+ clean if check didn't find any errors but table was\n\
+ marked as 'not clean' before. This allows one to get\n\
+ rid of warnings like 'table not properly closed'. If\n\
+ table was updated, update also the timestamp for when\n\
+ the check was made. This option is on by default!\n\
+ Use --skip-update-state to disable.\n\
+ --warning-for-wrong-transaction-id\n\
+ Give a warning if we find a transaction id in the table that is bigger\n\
+ than what exists in the control file. Use --skip-... to disable warning\n\
+ ");
puts("\
Recover (repair)/ options (When using '--recover' or '--safe-recover'):\n\
@@ -856,6 +880,7 @@ static void get_options(register int *argc,register char ***argv)
default_argv= *argv;
if (isatty(fileno(stdout)))
check_param.testflag|=T_WRITE_LOOP;
+ check_param.testflag= T_UPDATE_STATE;
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
exit(ho_error);
@@ -904,6 +929,11 @@ static void get_options(register int *argc,register char ***argv)
MYF(MY_WME))))
exit(1);
+ if (maria_data_root != default_log_dir && opt_log_dir == default_log_dir)
+ {
+ /* --datadir was used and --log-dir was not. Set log-dir to datadir */
+ opt_log_dir= maria_data_root;
+ }
return;
} /* get options */
@@ -1012,8 +1042,8 @@ static int maria_chk(HA_CHECK *param, char *filename)
share->state.open_count != 0);
if ((param->testflag & (T_REP_ANY | T_SORT_RECORDS)) &&
- ((share->state.changed & (STATE_CHANGED | STATE_CRASHED |
- STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR) ||
+ ((share->state.changed & (STATE_CHANGED | STATE_CRASHED_FLAGS |
+ STATE_IN_REPAIR) ||
!(param->testflag & T_CHECK_ONLY_CHANGED))))
need_to_check=1;
@@ -1030,8 +1060,8 @@ static int maria_chk(HA_CHECK *param, char *filename)
need_to_check=1;
}
if ((param->testflag & T_CHECK_ONLY_CHANGED) &&
- (share->state.changed & (STATE_CHANGED | STATE_CRASHED |
- STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR)))
+ (share->state.changed & (STATE_CHANGED | STATE_CRASHED_FLAGS |
+ STATE_IN_REPAIR)))
need_to_check=1;
if (!need_to_check)
{
@@ -1250,8 +1280,8 @@ static int maria_chk(HA_CHECK *param, char *filename)
if (!error)
{
DBUG_PRINT("info", ("Reseting crashed state"));
- share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
- STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR);
+ share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED_FLAGS |
+ STATE_IN_REPAIR);
}
else
maria_mark_crashed(info);
@@ -1304,14 +1334,13 @@ static int maria_chk(HA_CHECK *param, char *filename)
if (!error)
{
if (((share->state.changed &
- (STATE_CHANGED | STATE_CRASHED | STATE_CRASHED_ON_REPAIR |
- STATE_IN_REPAIR)) ||
+ (STATE_CHANGED | STATE_CRASHED_FLAGS | STATE_IN_REPAIR)) ||
share->state.open_count != 0)
&& (param->testflag & T_UPDATE_STATE))
info->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
DBUG_PRINT("info", ("Reseting crashed state"));
- share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
- STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR);
+ share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED_FLAGS |
+ STATE_IN_REPAIR);
}
else if (!maria_is_crashed(info) &&
(param->testflag & T_UPDATE_STATE))
@@ -1327,13 +1356,18 @@ static int maria_chk(HA_CHECK *param, char *filename)
(my_bool) !test(param->testflag & T_AUTO_INC));
if (info->update & HA_STATE_CHANGED && ! (param->testflag & T_READONLY))
+ {
error|=maria_update_state_info(param, info,
UPDATE_OPEN_COUNT |
- (((param->testflag & T_REP_ANY) ?
+ (((param->testflag &
+ (T_REP_ANY | T_UPDATE_STATE)) ?
UPDATE_TIME : 0) |
(state_updated ? UPDATE_STAT : 0) |
((param->testflag & T_SORT_RECORDS) ?
UPDATE_SORT : 0)));
+ if (!(param->testflag & T_SILENT))
+ printf("State updated\n");
+ }
info->update&= ~HA_STATE_CHANGED;
_ma_reenable_logging_for_table(info, FALSE);
maria_lock_database(info, F_UNLCK);
@@ -1439,7 +1473,7 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name)
if (share->state.check_time)
{
get_date(buff,1,share->state.check_time);
- printf("Recover time: %s\n",buff);
+ printf("Check/recover time: %s\n",buff);
}
if (share->base.born_transactional)
{
diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h
index dd190e4e4ec..03f0641b023 100644
--- a/storage/maria/maria_def.h
+++ b/storage/maria/maria_def.h
@@ -249,7 +249,9 @@ typedef struct st_maria_file_bitmap
my_bool changed; /* 1 if page needs to be written */
my_bool changed_not_flushed; /* 1 if some bitmap is not flushed */
uint flush_all_requested; /**< If _ma_bitmap_flush_all waiting */
+ uint waiting_for_flush_all_requested; /* If someone is waiting for above */
uint non_flushable; /**< 0 if bitmap and log are in sync */
+ uint waiting_for_non_flushable; /* If someone is waiting for above */
PAGECACHE_FILE file; /* datafile where bitmap is stored */
#ifdef THREAD
@@ -380,6 +382,11 @@ typedef struct st_maria_share
my_bool is_log_table;
my_bool has_null_fields;
my_bool has_varchar_fields; /* If table has varchar fields */
+ /*
+ Set to 1 if open_count was wrong at open. Set to avoid asserts for
+ wrong open count on close.
+ */
+ my_bool open_count_not_zero_on_open;
my_bool changed, /* If changed since lock */
global_changed, /* If changed since open */
@@ -626,6 +633,9 @@ struct st_maria_handler
#define STATE_NOT_MOVABLE 256
#define STATE_MOVED 512 /* set if base->uuid != maria_uuid */
#define STATE_IN_REPAIR 1024 /* We are running repair on table */
+#define STATE_CRASHED_PRINTED 2048
+
+#define STATE_CRASHED_FLAGS (STATE_CRASHED | STATE_CRASHED_ON_REPAIR | STATE_CRASHED_PRINTED)
/* options to maria_read_cache */
@@ -708,7 +718,6 @@ struct st_maria_handler
#endif
#define DBUG_DUMP_KEY(name, key) DBUG_DUMP(name, (key)->data, (key)->data_length + (key)->ref_length)
-
/* Functions to store length of space packed keys, VARCHAR or BLOB keys */
#define store_key_length(key,length) \
@@ -812,6 +821,7 @@ extern char *maria_data_root;
extern uchar maria_zero_string[];
extern my_bool maria_inited, maria_in_ha_maria, maria_recovery_changed_data;
extern my_bool maria_recovery_verbose;
+extern my_bool maria_assert_if_crashed_table;
extern HASH maria_stored_state;
extern int (*maria_create_trn_hook)(MARIA_HA *);
extern my_bool (*ma_killed)(MARIA_HA *);
@@ -936,11 +946,13 @@ extern my_bool _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key,
extern int _ma_readinfo(MARIA_HA *info, int lock_flag, int check_keybuffer);
extern int _ma_writeinfo(MARIA_HA *info, uint options);
extern int _ma_test_if_changed(MARIA_HA *info);
-extern int _ma_mark_file_changed(MARIA_HA *info);
+extern int _ma_mark_file_changed(MARIA_SHARE *info);
+extern int _ma_mark_file_changed_now(MARIA_SHARE *info);
extern void _ma_mark_file_crashed(MARIA_SHARE *share);
-extern my_bool _ma_set_uuid(MARIA_HA *info, my_bool reset_uuid);
+void _ma_set_fatal_error(MARIA_SHARE *share, int error);
+extern my_bool _ma_set_uuid(MARIA_SHARE *info, my_bool reset_uuid);
extern my_bool _ma_check_if_zero(uchar *pos, size_t size);
-extern int _ma_decrement_open_count(MARIA_HA *info);
+extern int _ma_decrement_open_count(MARIA_HA *info, my_bool lock_table);
extern int _ma_check_index(MARIA_HA *info, int inx);
extern int _ma_search(MARIA_HA *info, MARIA_KEY *key, uint32 nextflag,
my_off_t pos);
@@ -1034,7 +1046,7 @@ extern MARIA_KEY *_ma_pack_key(MARIA_HA *info, MARIA_KEY *int_key,
HA_KEYSEG ** last_used_keyseg);
extern void _ma_copy_key(MARIA_KEY *to, const MARIA_KEY *from);
extern int _ma_read_key_record(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS);
-extern my_bool _ma_read_cache(IO_CACHE *info, uchar *buff,
+extern my_bool _ma_read_cache(MARIA_HA *, IO_CACHE *info, uchar *buff,
MARIA_RECORD_POS pos, size_t length,
uint re_read_if_possibly);
extern ulonglong ma_retrieve_auto_increment(const uchar *key, uint8 key_type);
@@ -1116,7 +1128,7 @@ typedef struct st_maria_block_info
#define fast_ma_writeinfo(INFO) if (!(INFO)->s->tot_locks) (void) _ma_writeinfo((INFO),0)
#define fast_ma_readinfo(INFO) ((INFO)->lock_type == F_UNLCK) && _ma_readinfo((INFO),F_RDLCK,1)
-extern uint _ma_get_block_info(MARIA_BLOCK_INFO *, File, my_off_t);
+extern uint _ma_get_block_info(MARIA_HA *, MARIA_BLOCK_INFO *, File, my_off_t);
extern uint _ma_rec_pack(MARIA_HA *info, uchar *to, const uchar *from);
extern uint _ma_pack_get_block_info(MARIA_HA *maria, MARIA_BIT_BUFF *bit_buff,
MARIA_BLOCK_INFO *info, uchar **rec_buff_p,
@@ -1195,6 +1207,7 @@ void _ma_remap_file(MARIA_HA *info, my_off_t size);
MARIA_RECORD_POS _ma_write_init_default(MARIA_HA *info, const uchar *record);
my_bool _ma_write_abort_default(MARIA_HA *info);
+int maria_delete_table_files(const char *name, myf sync_dir);
C_MODE_START
#define MARIA_FLUSH_DATA 1
@@ -1288,3 +1301,4 @@ ICP_RESULT ma_check_index_cond(register MARIA_HA *info, uint keynr, uchar *recor
extern my_bool ma_yield_and_check_if_killed(MARIA_HA *info, int inx);
extern my_bool ma_killed_standalone(MARIA_HA *);
+extern uint _ma_file_callback_to_id(void *callback_data);
diff --git a/storage/maria/maria_read_log.c b/storage/maria/maria_read_log.c
index 7a630e274e3..b335aa3692e 100644
--- a/storage/maria/maria_read_log.c
+++ b/storage/maria/maria_read_log.c
@@ -44,9 +44,9 @@ int main(int argc, char **argv)
uint warnings_count;
MY_INIT(argv[0]);
+ maria_data_root= (char *)".";
load_defaults("my", load_default_groups, &argc, &argv);
default_argv= argv;
- maria_data_root= (char *)".";
get_options(&argc, &argv);
maria_in_recovery= TRUE;
@@ -195,12 +195,12 @@ static struct my_option my_long_options[] =
{ "end-lsn", 'e', "Stop applying at this lsn. If end-lsn is used, UNDO:s "
"will not be applied", &opt_end_lsn, &opt_end_lsn,
0, GET_ULL, REQUIRED_ARG, 0, 0, ~(longlong) 0, 0, 0, 0 },
- {"aria-log-dir-path", 'l',
+ {"aria-log-dir-path", 'h',
"Path to the directory where to store transactional log",
(uchar **) &maria_data_root, (uchar **) &maria_data_root, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{ "page-buffer-size", 'P',
- "The size of the buffer used for index blocks for Maria tables",
+ "The size of the buffer used for index blocks for Aria tables",
&opt_page_buffer_size, &opt_page_buffer_size, 0,
GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT,
1024L*1024L, (long) ~(ulong) 0, (long) MALLOC_OVERHEAD,
diff --git a/storage/maria/unittest/ma_test_all-t b/storage/maria/unittest/ma_test_all-t
index 5ba730afc95..f92a25617d7 100755
--- a/storage/maria/unittest/ma_test_all-t
+++ b/storage/maria/unittest/ma_test_all-t
@@ -8,7 +8,7 @@ use File::Basename;
$|= 1;
$^W = 1; # warnings, because env cannot parse 'perl -w'
-$VER= "1.4";
+$VER= "1.5";
$opt_version= 0;
$opt_help= 0;
@@ -28,6 +28,8 @@ my $NEW_TEST= 0; # Test group separator in an array of tests
my $test_begin= 0;
my $test_end= 0;
my $test_counter= 0;
+my $full_tmpdir;
+my $tmpdir="tmp";
run_tests();
@@ -46,6 +48,7 @@ sub run_tests
"abort-on-error" => \$opt_abort_on_error,
"valgrind=s" => \$opt_valgrind,
"silent=s" => \$opt_silent,
+ "tmpdir=s" => \$full_tmpdir,
"number-of-tests" => \$opt_number_of_tests,
"run-tests=s" => \$opt_run_tests,
"start-from=s" => \$opt_run_tests))
@@ -77,10 +80,23 @@ sub run_tests
}
}
}
- }
+ }
usage() if ($opt_help || $flag_exit);
+ if (defined($full_tmpdir))
+ {
+ $tmpdir= $full_tmpdir;
+ }
+ else
+ {
+ $full_tmpdir= "tmp";
+ if (! -d "$full_tmpdir")
+ {
+ die if (!mkdir("$full_tmpdir"));
+ }
+ }
+
#
# IMPORTANT: If you modify this file, please read this:
#
@@ -146,7 +162,7 @@ sub run_tests
# clean-up
#
- unlink <*.TMD aria_log*>; # Delete temporary files
+ unlink_all_possible_tmp_files();
#
# Run tests
@@ -210,6 +226,7 @@ sub run_tests
run_ma_test_recovery($opt_verbose, 0);
run_tests_on_clrs($suffix, $opt_verbose, 0);
+ unlink_all_possible_tmp_files();
exit($runtime_error);
}
@@ -281,38 +298,38 @@ sub run_check_tests
for ($i= 0; defined($ma_test1_opt[$i]); $i++)
{
- unlink <aria_log_control aria_log.*>;
- ok("$maria_exe_path/ma_test1$suffix $silent $ma_test1_opt[$i][0] $row_type",
+ unlink_log_files();
+ ok("$maria_exe_path/ma_test1$suffix $silent -h$tmpdir $ma_test1_opt[$i][0] $row_type",
$verbose, $i + 1);
- ok("$maria_exe_path/aria_chk$suffix $ma_test1_opt[$i][1] test1",
+ ok("$maria_exe_path/aria_chk$suffix -h$tmpdir $ma_test1_opt[$i][1] $tmpdir/test1",
$verbose, $i + 1);
}
#
# These tests are outside the loops. Make sure to include them in
# nr_tests manually
#
- ok("$maria_exe_path/aria_pack$suffix --force -s test1", $verbose, 0);
- ok("$maria_exe_path/aria_chk$suffix -ess test1", $verbose, 0);
+ ok("$maria_exe_path/aria_pack$suffix --force -s $tmpdir/test1", $verbose, 0);
+ ok("$maria_exe_path/aria_chk$suffix -ess $tmpdir/test1", $verbose, 0);
for ($i= 0; defined($ma_test2_opt[$i]); $i++)
{
- unlink <aria_log_control aria_log.*>;
- ok("$maria_exe_path/ma_test2$suffix $silent $ma_test2_opt[$i][0] $row_type",
+ unlink_log_files();
+ ok("$maria_exe_path/ma_test2$suffix $silent -h$tmpdir $ma_test2_opt[$i][0] $row_type",
$verbose, $i + 1);
- ok("$maria_exe_path/aria_chk$suffix $ma_test2_opt[$i][1] test2",
+ ok("$maria_exe_path/aria_chk$suffix -h$tmpdir $ma_test2_opt[$i][1] $tmpdir/test2",
$verbose, $i + 1);
}
for ($i= 0; defined($ma_rt_test_opt[$i]); $i++)
{
- unlink <aria_log_control aria_log.*>;
- ok("$maria_exe_path/ma_rt_test$suffix $silent $ma_rt_test_opt[$i][0] $row_type",
+ unlink_log_files();
+ ok("$maria_exe_path/ma_rt_test$suffix $silent -h$tmpdir $ma_rt_test_opt[$i][0] $row_type",
$verbose, $i + 1);
- ok("$maria_exe_path/aria_chk$suffix $ma_rt_test_opt[$i][1] rt_test",
+ ok("$maria_exe_path/aria_chk$suffix -h$tmpdir $ma_rt_test_opt[$i][1] $tmpdir/rt_test",
$verbose, $i + 1);
}
- unlink <aria_log_control aria_log.*>;
+ unlink_log_files();
return 0;
}
@@ -434,25 +451,25 @@ sub run_tests_on_warnings_and_errors
return 9 if ($count); # Number of tests in this function, e.g. calls to ok()
- ok("$maria_exe_path/ma_test2$suffix $silent -L -K -W -P -S -R1 -m500",
+ ok("$maria_exe_path/ma_test2$suffix -h$tmpdir $silent -L -K -W -P -S -R1 -m500",
$verbose, 0);
- ok("$maria_exe_path/aria_chk$suffix -sm test2", $verbose, 0);
+ ok("$maria_exe_path/aria_chk$suffix -h$tmpdir -sm $tmpdir/test2", $verbose, 0);
# ma_test2$suffix $silent -L -K -R1 -m2000 ; Should give error 135\n
# In the following a failure is a success and success is a failure
- $com= "$maria_exe_path/ma_test2$suffix $silent -L -K -R1 -m2000 ";
+ $com= "$maria_exe_path/ma_test2$suffix -h$tmpdir $silent -L -K -R1 -m2000 ";
$com.= ">ma_test2_message.txt 2>&1";
ok($com, $verbose, 0, 1);
ok("cat ma_test2_message.txt", $verbose, 0);
ok("grep \"Error: 135\" ma_test2_message.txt > /dev/null", $verbose, 0);
- # maria_exe_path/aria_chk$suffix -sm test2 will warn that
+ # maria_exe_path/aria_chk$suffix -h$tmpdir -sm $tmpdir/test2 will warn that
# Datafile is almost full
- ok("$maria_exe_path/aria_chk$suffix -sm test2 >ma_test2_message.txt 2>&1",
+ ok("$maria_exe_path/aria_chk$suffix -h$tmpdir -sm $tmpdir/test2 >ma_test2_message.txt 2>&1",
$verbose, 0);
ok("cat ma_test2_message.txt", $verbose, 0);
ok("grep \"warning: Datafile is almost full\" ma_test2_message.txt>/dev/null",
$verbose, 0);
unlink <ma_test2_message.txt>;
- ok("$maria_exe_path/aria_chk$suffix -ssm test2", $verbose, 0);
+ ok("$maria_exe_path/aria_chk$suffix -h$tmpdir -ssm $tmpdir/test2", $verbose, 0);
return 0;
}
@@ -480,33 +497,33 @@ sub run_tests_on_clrs
my ($i);
my @t= ($NEW_TEST,
- "$maria_exe_path/ma_test2$suffix -s -L -K -W -P -M -T -c -b -t2 -A1",
- "cp aria_log_control tmp",
- "$maria_exe_path/aria_read_log$suffix -a -s",
- "$maria_exe_path/aria_chk$suffix -s -e test2",
- "cp tmp/aria_log_control .",
- "rm test2.MA?",
- "$maria_exe_path/aria_read_log$suffix -a -s",
- "$maria_exe_path/aria_chk$suffix -s -e test2",
- "rm test2.MA?",
+ "$maria_exe_path/ma_test2$suffix -h$tmpdir -s -L -K -W -P -M -T -c -b -t2 -A1",
+ "cp $tmpdir/aria_log_control $tmpdir/aria_log_control.backup",
+ "$maria_exe_path/aria_read_log$suffix -a -s -h$tmpdir",
+ "$maria_exe_path/aria_chk$suffix -h$tmpdir -s -e $tmpdir/test2",
+ "mv $tmpdir/aria_log_control.backup $tmpdir/aria_log_control",
+ "rm $tmpdir/test2.MA?",
+ "$maria_exe_path/aria_read_log$suffix -a -s -h$tmpdir",
+ "$maria_exe_path/aria_chk$suffix -h$tmpdir -s -e $tmpdir/test2",
+ "rm $tmpdir/test2.MA?",
$NEW_TEST,
- "$maria_exe_path/ma_test2$suffix -s -L -K -W -P -M -T -c -b -t2 -A1",
- "$maria_exe_path/aria_read_log$suffix -a -s",
- "$maria_exe_path/aria_chk$suffix -s -e test2",
- "rm test2.MA?",
- "$maria_exe_path/aria_read_log$suffix -a -s",
- "$maria_exe_path/aria_chk$suffix -e -s test2",
- "rm test2.MA?",
+ "$maria_exe_path/ma_test2$suffix -h$tmpdir -s -L -K -W -P -M -T -c -b -t2 -A1",
+ "$maria_exe_path/aria_read_log$suffix -a -s -h$tmpdir ",
+ "$maria_exe_path/aria_chk$suffix -h$tmpdir -s -e $tmpdir/test2",
+ "rm $tmpdir/test2.MA?",
+ "$maria_exe_path/aria_read_log$suffix -a -s -h$tmpdir",
+ "$maria_exe_path/aria_chk$suffix -h$tmpdir -e -s $tmpdir/test2",
+ "rm $tmpdir/test2.MA?",
$NEW_TEST,
- "$maria_exe_path/ma_test2$suffix -s -L -K -W -P -M -T -c -b32768 -t4 -A1",
- "$maria_exe_path/aria_read_log$suffix -a -s",
- "$maria_exe_path/aria_chk$suffix -es test2",
- "$maria_exe_path/aria_read_log$suffix -a -s",
- "$maria_exe_path/aria_chk$suffix -es test2",
- "rm test2.MA?",
- "$maria_exe_path/aria_read_log$suffix -a -s",
- "$maria_exe_path/aria_chk$suffix -es test2",
- "rm test2.MA?"
+ "$maria_exe_path/ma_test2$suffix -h$tmpdir -s -L -K -W -P -M -T -c -b32768 -t4 -A1",
+ "$maria_exe_path/aria_read_log$suffix -a -s -h$tmpdir",
+ "$maria_exe_path/aria_chk$suffix -h$tmpdir -es $tmpdir/test2",
+ "$maria_exe_path/aria_read_log$suffix -a -s -h$tmpdir ",
+ "$maria_exe_path/aria_chk$suffix -h$tmpdir -es $tmpdir/test2",
+ "rm $tmpdir/test2.MA?",
+ "$maria_exe_path/aria_read_log$suffix -a -s -h$tmpdir",
+ "$maria_exe_path/aria_chk$suffix -h$tmpdir -es $tmpdir/test2",
+ "rm $tmpdir/test2.MA?"
);
return &count_tests(\@t) if ($count);
@@ -551,10 +568,14 @@ sub ok
if ($verbose)
{
- print "$com ";
+ # Print command with out the long unittest/../ prefix
+ my $tmp;
+ $tmp= $com;
+ $tmp =~ s|^unittest/../||;
+ print "$tmp ";
+ $len= length($tmp);
}
$output= `$com 2>&1`;
- $len= length($com);
if ($verbose)
{
print " " x (62 - $len);
@@ -651,6 +672,19 @@ sub count_tests
return $nr_tests;
}
+sub unlink_log_files
+{
+ unlink "$full_tmpdir/aria_log_control", "$full_tmpdir/aria_log.00000001", "$full_tmpdir/aria_log.00000002";
+}
+
+sub unlink_all_possible_tmp_files()
+{
+ unlink_log_files();
+
+ # Unlink tmp files that may have been created when testing the test programs
+ unlink <$full_tmpdir/*.TMD aria_log_control aria_log.00000001 aria_log.00000002 aria_logtest1.MA? test2.MA? test3.MA?>;
+}
+
####
#### Run a bunch of tests
#### Arguments: $t: an array of the tests
@@ -667,7 +701,7 @@ sub run_test_bunch
{
if ($clear && @$t[$i] eq $NEW_TEST)
{
- unlink <aria_log.* aria_log_control>;
+ unlink_log_files();
}
if (@$t[$i] ne $NEW_TEST)
{
diff --git a/storage/maria/unittest/ma_test_recovery.pl b/storage/maria/unittest/ma_test_recovery.pl
index d9be82f4e58..f3a5bffbc36 100755
--- a/storage/maria/unittest/ma_test_recovery.pl
+++ b/storage/maria/unittest/ma_test_recovery.pl
@@ -114,7 +114,7 @@ sub main
die("can't guess table name");
}
$com= "$maria_exe_path/aria_chk$suffix -dvv $table ";
- $com.= "| grep -v \"Creation time:\" | grep -v \"file length\" | grep -v \"LSNs:\" | grep -v \"UUID:\"";
+ $com.= "| grep -v \"Creation time:\" | grep -v \"recover time:\" | grep -v \"file length\" | grep -v \"LSNs:\" | grep -v \"UUID:\"";
$com.= "> $tmp/aria_chk_message.good.txt 2>&1";
my_exec($com);
my $checksum= my_exec("$maria_exe_path/aria_chk$suffix -dss $table");
@@ -197,7 +197,7 @@ sub main
die("can't guess table name");
}
$com= "$maria_exe_path/aria_chk$suffix -dvv $table ";
- $com.= "| grep -v \"Creation time:\" | grep -v \"file length\" | grep -v \"LSNs:\" | grep -v \"UUID:\" ";
+ $com.= "| grep -v \"Creation time:\" | grep -v \"recover time:\" | grep -v \"recover time:\" |grep -v \"file length\" | grep -v \"LSNs:\" | grep -v \"UUID:\" ";
$com.= "> $tmp/aria_chk_message.good.txt 2>&1";
$res= my_exec($com);
print MY_LOG $res;
@@ -296,7 +296,7 @@ sub check_table_is_same
print "checking if table $table has changed\n";
}
- $com= "$maria_exe_path/aria_chk$suffix -dvv $table | grep -v \"Creation time:\" ";
+ $com= "$maria_exe_path/aria_chk$suffix -dvv $table | grep -v \"Creation time:\" | grep -v \"recover time:\"";
$com.= "| grep -v \"file length\" | grep -v \"LSNs:\" | grep -v \"UUID:\" > $tmp/aria_chk_message.txt 2>&1";
$res= `$com`;
print MY_LOG $res;
@@ -415,7 +415,7 @@ sub physical_cmp
# save original tables to restore them later
copy("$table.MAD", "$tmp/before_zerofill$table_no.MAD") || die();
copy("$table.MAI", "$tmp/before_zerofill$table_no.MAI") || die();
- $com= "$maria_exe_path/aria_chk$suffix -ss --zerofill-keep-lsn $table";
+ $com= "$maria_exe_path/aria_chk$suffix -ss --zerofill-keep-lsn --skip-update-state $table";
$res= `$com`;
print MY_LOG $res;
$table_no= $table_no + 1;
diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c
index bcce2cc8d60..edca8c25105 100644
--- a/storage/myisam/ft_nlq_search.c
+++ b/storage/myisam/ft_nlq_search.c
@@ -79,7 +79,6 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
#else
#error
#endif
-
DBUG_ENTER("walk_and_match");
word->weight=LWS_FOR_QUERY;
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index 7d5a81f7943..1edecf5289a 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -598,7 +598,11 @@ int ha_myisam::net_read_dump(NET* net)
int data_fd = file->dfile;
int error = 0;
- my_seek(data_fd, 0L, MY_SEEK_SET, MYF(MY_WME));
+ if (my_seek(data_fd, 0L, MY_SEEK_SET, MYF(MY_WME)) == MY_FILEPOS_ERROR)
+ {
+ error= my_errno;
+ goto err;
+ }
for (;;)
{
ulong packet_len = my_net_read(net);
@@ -634,7 +638,11 @@ int ha_myisam::dump(THD* thd, int fd)
return ENOMEM;
int error = 0;
- my_seek(data_fd, 0L, MY_SEEK_SET, MYF(MY_WME));
+ if (my_seek(data_fd, 0L, MY_SEEK_SET, MYF(MY_WME)) == MY_FILEPOS_ERROR)
+ {
+ error= my_errno;
+ goto err;
+ }
for (; bytes_to_read > 0;)
{
size_t bytes = my_read(data_fd, buf, blocksize, MYF(MY_WME));
@@ -1491,7 +1499,7 @@ int ha_myisam::enable_indexes(uint mode)
}
else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
{
- THD *thd=current_thd;
+ THD *thd= table->in_use;
HA_CHECK &param= *(HA_CHECK*) thd->alloc(sizeof(param));
const char *save_proc_info=thd->proc_info;
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c
index 3f569bda39c..8dc73443f50 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -1743,6 +1743,8 @@ err:
MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
mi_open_datafile(info,share,name,-1))
got_error=1;
+
+ param->retry_repair= 0;
}
}
if (got_error)
diff --git a/storage/myisam/mi_panic.c b/storage/myisam/mi_panic.c
index 2d06b66f834..99aef372027 100644
--- a/storage/myisam/mi_panic.c
+++ b/storage/myisam/mi_panic.c
@@ -72,8 +72,8 @@ int mi_panic(enum ha_panic_function flag)
if (info->dfile >= 0 && my_close(info->dfile,MYF(0)))
error = my_errno;
info->s->kfile=info->dfile= -1; /* Files aren't open anymore */
- break;
#endif
+ break;
case HA_PANIC_READ: /* Restore to before WRITE */
#ifdef CANT_OPEN_FILES_TWICE
{ /* Open closed files */
diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c
index 17add155193..6c63f5afaef 100644
--- a/storage/myisam/myisampack.c
+++ b/storage/myisam/myisampack.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/* Copyright (C) 2000-2007 MySQL AB
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
diff --git a/storage/ndb/Makefile.am b/storage/ndb/Makefile.am
index 0da8ec136c9..835b8c83fd8 100644
--- a/storage/ndb/Makefile.am
+++ b/storage/ndb/Makefile.am
@@ -35,7 +35,7 @@ dist-hook:
done
windoze:
- for i in `find . -name 'old_dirs' -prune -o -name 'Makefile.am' -print`; \
+ for i in `find . -name 'Makefile.am' -print`; \
do make -C `dirname $$i` windoze-dsp; done
windoze-dsp:
diff --git a/storage/ndb/config/make-win-dsw.sh b/storage/ndb/config/make-win-dsw.sh
index b0613620f8a..070a3665bc0 100755
--- a/storage/ndb/config/make-win-dsw.sh
+++ b/storage/ndb/config/make-win-dsw.sh
@@ -1,3 +1,17 @@
+# Copyright (C) 2004 MySQL AB
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
cat <<EOF
Microsoft Developer Studio Workspace File, Format Version 6.00
diff --git a/storage/ndb/config/win-includes b/storage/ndb/config/win-includes
index fa5984fd25e..0d6eec83ae7 100755
--- a/storage/ndb/config/win-includes
+++ b/storage/ndb/config/win-includes
@@ -1,5 +1,20 @@
#!/bin/sh
+# Copyright (C) 2004 MySQL AB
+#
+# 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
+
dst=$1
shift
diff --git a/storage/ndb/config/win-libraries b/storage/ndb/config/win-libraries
index c7a6fb696ee..bc9275f9a7b 100755
--- a/storage/ndb/config/win-libraries
+++ b/storage/ndb/config/win-libraries
@@ -1,5 +1,20 @@
#!/bin/sh
+# Copyright (C) 2004 MySQL AB
+#
+# 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
+
dst=$1
shift
diff --git a/storage/ndb/config/win-name b/storage/ndb/config/win-name
index 036f2b9cc2e..1ceb7019d3f 100755
--- a/storage/ndb/config/win-name
+++ b/storage/ndb/config/win-name
@@ -1,5 +1,20 @@
#!/bin/sh
+# Copyright (C) 2004 MySQL AB
+#
+# 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
+
dst=$1
shift
diff --git a/storage/ndb/config/win-sources b/storage/ndb/config/win-sources
index a383bb0e613..ccf0f6b7618 100755
--- a/storage/ndb/config/win-sources
+++ b/storage/ndb/config/win-sources
@@ -1,5 +1,20 @@
#!/bin/sh
+# Copyright (C) 2004 MySQL AB
+#
+# 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
+
dst=$1
shift
diff --git a/storage/ndb/docs/Makefile.am b/storage/ndb/docs/Makefile.am
index b0166d40779..a16fa1325c3 100644
--- a/storage/ndb/docs/Makefile.am
+++ b/storage/ndb/docs/Makefile.am
@@ -14,7 +14,7 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
DOXYDIR = doxygen
-noinst_HEADERS = $(DOXYDIR)/predoxy.pl $(DOXYDIR)/postdoxy.pl $(DOXYDIR)/Doxyfile.ndbapi $(DOXYDIR)/Doxyfile.mgmapi $(DOXYDIR)/header.ndbapi.tex $(DOXYDIR)/header.mgmapi.tex
+noinst_HEADERS = $(DOXYDIR)/predoxy.pl $(DOXYDIR)/postdoxy.pl $(DOXYDIR)/Doxyfile.ndbapi $(DOXYDIR)/Doxyfile.mgmapi
all-local: do-check-html ndbapidoc-html mgmapidoc-html
all-pdf: do-check-pdf ndbapidoc-pdf mgmapidoc-pdf
diff --git a/storage/ndb/docs/doxygen/Doxyfile.mgmapi b/storage/ndb/docs/doxygen/Doxyfile.mgmapi
index 1e743dcb60e..59090d9dd95 100644
--- a/storage/ndb/docs/doxygen/Doxyfile.mgmapi
+++ b/storage/ndb/docs/doxygen/Doxyfile.mgmapi
@@ -1,3 +1,18 @@
+# Copyright (C) 2004, 2005 MySQL AB
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
# Doxyfile 1.2.12
# This file describes the settings to be used by the documentation system
@@ -537,7 +552,7 @@ EXTRA_PACKAGES =
# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!
-LATEX_HEADER = ../doxygen/header.mgmapi.tex
+LATEX_HEADER =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
diff --git a/storage/ndb/docs/doxygen/Doxyfile.ndb b/storage/ndb/docs/doxygen/Doxyfile.ndb
index 3986a7cd17f..96365c8868f 100644
--- a/storage/ndb/docs/doxygen/Doxyfile.ndb
+++ b/storage/ndb/docs/doxygen/Doxyfile.ndb
@@ -1,3 +1,18 @@
+# Copyright (C) 2004, 2005 MySQL AB
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
# Doxyfile 1.2.14
# This file describes the settings to be used by the documentation system
diff --git a/storage/ndb/docs/doxygen/Doxyfile.ndbapi b/storage/ndb/docs/doxygen/Doxyfile.ndbapi
index da610148468..fb41b58a89f 100644
--- a/storage/ndb/docs/doxygen/Doxyfile.ndbapi
+++ b/storage/ndb/docs/doxygen/Doxyfile.ndbapi
@@ -1,3 +1,18 @@
+# Copyright (C) 2004, 2005 MySQL AB
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
# Doxyfile 1.2.12
# This file describes the settings to be used by the documentation system
@@ -537,7 +552,7 @@ EXTRA_PACKAGES =
# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!
-LATEX_HEADER = ../doxygen/header.ndbapi.tex
+LATEX_HEADER =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
diff --git a/storage/ndb/docs/doxygen/Doxyfile.odbc b/storage/ndb/docs/doxygen/Doxyfile.odbc
index 262513852b7..aa0d97ffdf7 100644
--- a/storage/ndb/docs/doxygen/Doxyfile.odbc
+++ b/storage/ndb/docs/doxygen/Doxyfile.odbc
@@ -1,3 +1,18 @@
+# Copyright (C) 2004, 2005 MySQL AB
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
# Doxyfile 1.2.14
# This file describes the settings to be used by the documentation system
diff --git a/storage/ndb/docs/doxygen/header.mgmapi.tex b/storage/ndb/docs/doxygen/header.mgmapi.tex
deleted file mode 100644
index 1b55ceb15c7..00000000000
--- a/storage/ndb/docs/doxygen/header.mgmapi.tex
+++ /dev/null
@@ -1,44 +0,0 @@
-\documentclass[a4paper]{book}
-\usepackage{a4wide}
-\usepackage{makeidx}
-\usepackage{fancyhdr}
-\usepackage{graphicx}
-\usepackage{multicol}
-\usepackage{float}
-\usepackage{textcomp}
-\usepackage{alltt}
-\usepackage{times}
-\ifx\pdfoutput\undefined
-\usepackage[ps2pdf,
- pagebackref=true,
- colorlinks=true,
- linkcolor=blue
- ]{hyperref}
-\usepackage{pspicture}
-\else
-\usepackage[pdftex,
- pagebackref=true,
- colorlinks=true,
- linkcolor=blue
- ]{hyperref}
-\fi
-\usepackage{doxygen}
-\makeindex
-\setcounter{tocdepth}{1}
-\renewcommand{\footrulewidth}{0.4pt}
-\begin{document}
-\begin{titlepage}
-\vspace*{7cm}
-\begin{center}
-{\Huge NDB Cluster MGM API Guide \mbox{}\vspace{-3cm}\mbox{}\hrule\bigskip\bigskip\bigskip\bigskip\mbox{}\Huge{}}\\\vspace*{1cm}
-\begin{center}\LARGE{MySQL AB}\end{center}\hfill\bigskip\bigskip\bigskip\hrule\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip NDB Cluster Release RELEASE
-\bigskip\bigskip\bigskip\bigskip\bigskip\hfill\vspace*{0.5cm}
-{\small DATE}\\
-\end{center}
-\end{titlepage}
-\clearemptydoublepage
-\pagenumbering{roman}
-\tableofcontents
-\clearemptydoublepage
-\pagenumbering{arabic}
-
diff --git a/storage/ndb/docs/doxygen/header.ndbapi.tex b/storage/ndb/docs/doxygen/header.ndbapi.tex
deleted file mode 100644
index c37ce286ed8..00000000000
--- a/storage/ndb/docs/doxygen/header.ndbapi.tex
+++ /dev/null
@@ -1,44 +0,0 @@
-\documentclass[a4paper]{book}
-\usepackage{a4wide}
-\usepackage{makeidx}
-\usepackage{fancyhdr}
-\usepackage{graphicx}
-\usepackage{multicol}
-\usepackage{float}
-\usepackage{textcomp}
-\usepackage{alltt}
-\usepackage{times}
-\ifx\pdfoutput\undefined
-\usepackage[ps2pdf,
- pagebackref=true,
- colorlinks=true,
- linkcolor=blue
- ]{hyperref}
-\usepackage{pspicture}
-\else
-\usepackage[pdftex,
- pagebackref=true,
- colorlinks=true,
- linkcolor=blue
- ]{hyperref}
-\fi
-\usepackage{doxygen}
-\makeindex
-\setcounter{tocdepth}{1}
-\renewcommand{\footrulewidth}{0.4pt}
-\begin{document}
-\begin{titlepage}
-\vspace*{7cm}
-\begin{center}
-{\Huge NDB API Programmer's Guide \mbox{}\vspace{-3cm}\mbox{}\hrule\bigskip\bigskip\bigskip\bigskip\mbox{}\Huge{}}\\\vspace*{1cm}
-\begin{center}\LARGE{MySQL AB}\end{center}\hfill\bigskip\bigskip\bigskip\hrule\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip\bigskip NDB Cluster Release RELEASE
-\bigskip\bigskip\bigskip\bigskip\bigskip\hfill\vspace*{0.5cm}
-{\small DATE}\\
-\end{center}
-\end{titlepage}
-\clearemptydoublepage
-\pagenumbering{roman}
-\tableofcontents
-\clearemptydoublepage
-\pagenumbering{arabic}
-
diff --git a/storage/ndb/docs/doxygen/postdoxy.pl b/storage/ndb/docs/doxygen/postdoxy.pl
index 3bf54e4ff75..a8eab31d47d 100755
--- a/storage/ndb/docs/doxygen/postdoxy.pl
+++ b/storage/ndb/docs/doxygen/postdoxy.pl
@@ -1,3 +1,18 @@
+# Copyright (C) 2004 MySQL AB
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
#
# Written by Lars Thalmann, lars@mysql.com, 2003.
#
diff --git a/storage/ndb/docs/doxygen/predoxy.pl b/storage/ndb/docs/doxygen/predoxy.pl
index 3994054dcf6..553052648af 100755
--- a/storage/ndb/docs/doxygen/predoxy.pl
+++ b/storage/ndb/docs/doxygen/predoxy.pl
@@ -1,3 +1,18 @@
+# Copyright (C) 2004 MySQL AB
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
#
# Written by Lars Thalmann, lars@mysql.com, 2003.
#
diff --git a/storage/ndb/include/kernel/signaldata/FsOpenReq.hpp b/storage/ndb/include/kernel/signaldata/FsOpenReq.hpp
index 8126267f946..95dbf5204f1 100644
--- a/storage/ndb/include/kernel/signaldata/FsOpenReq.hpp
+++ b/storage/ndb/include/kernel/signaldata/FsOpenReq.hpp
@@ -203,7 +203,7 @@ Uint32 FsOpenReq::getVersion(const Uint32 fileNumber[]){
inline
void FsOpenReq::setVersion(Uint32 fileNumber[], Uint8 val){
const Uint32 t = fileNumber[3];
- fileNumber[3] = t & 0x00FFFFFF | (((Uint32)val) << 24);
+ fileNumber[3] = (t & 0x00FFFFFF) | (((Uint32)val) << 24);
}
inline
@@ -214,7 +214,7 @@ Uint32 FsOpenReq::getSuffix(const Uint32 fileNumber[]){
inline
void FsOpenReq::setSuffix(Uint32 fileNumber[], Uint8 val){
const Uint32 t = fileNumber[3];
- fileNumber[3] = t & 0xFF00FFFF | (((Uint32)val) << 16);
+ fileNumber[3] = (t & 0xFF00FFFF) | (((Uint32)val) << 16);
}
inline
@@ -225,7 +225,7 @@ Uint32 FsOpenReq::v1_getDisk(const Uint32 fileNumber[]){
inline
void FsOpenReq::v1_setDisk(Uint32 fileNumber[], Uint8 val){
const Uint32 t = fileNumber[3];
- fileNumber[3] = t & 0xFFFF00FF | (((Uint32)val) << 8);
+ fileNumber[3] = (t & 0xFFFF00FF) | (((Uint32)val) << 8);
}
inline
@@ -266,7 +266,7 @@ Uint32 FsOpenReq::v1_getP(const Uint32 fileNumber[]){
inline
void FsOpenReq::v1_setP(Uint32 fileNumber[], Uint8 val){
const Uint32 t = fileNumber[3];
- fileNumber[3] = t & 0xFFFFFF00 | val;
+ fileNumber[3] = (t & 0xFFFFFF00) | val;
}
/****************/
diff --git a/storage/ndb/include/ndbapi/NdbDictionary.hpp b/storage/ndb/include/ndbapi/NdbDictionary.hpp
index 0e782ba9214..8a23802e797 100644
--- a/storage/ndb/include/ndbapi/NdbDictionary.hpp
+++ b/storage/ndb/include/ndbapi/NdbDictionary.hpp
@@ -20,7 +20,7 @@
class Ndb;
struct charset_info_st;
-typedef struct charset_info_st CHARSET_INFO;
+typedef const struct charset_info_st CHARSET_INFO;
/**
* @class NdbDictionary
diff --git a/storage/ndb/include/util/NdbSqlUtil.hpp b/storage/ndb/include/util/NdbSqlUtil.hpp
index 8d063f1908b..77bb79aca82 100644
--- a/storage/ndb/include/util/NdbSqlUtil.hpp
+++ b/storage/ndb/include/util/NdbSqlUtil.hpp
@@ -20,7 +20,6 @@
#include <kernel/ndb_limits.h>
struct charset_info_st;
-typedef struct charset_info_st CHARSET_INFO;
class NdbSqlUtil {
public:
diff --git a/storage/ndb/src/cw/cpcc-win32/csharp/CPC_Form.cs b/storage/ndb/src/cw/cpcc-win32/csharp/CPC_Form.cs
index ea1798c8c67..b19875b97ef 100644
--- a/storage/ndb/src/cw/cpcc-win32/csharp/CPC_Form.cs
+++ b/storage/ndb/src/cw/cpcc-win32/csharp/CPC_Form.cs
@@ -1,3 +1,18 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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 */
+
using System;
using System.Drawing;
using System.Collections;
diff --git a/storage/ndb/src/cw/cpcc-win32/csharp/Computer.cs b/storage/ndb/src/cw/cpcc-win32/csharp/Computer.cs
index 9763fac5622..5ee35e5e90e 100644
--- a/storage/ndb/src/cw/cpcc-win32/csharp/Computer.cs
+++ b/storage/ndb/src/cw/cpcc-win32/csharp/Computer.cs
@@ -1,3 +1,18 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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 */
+
using System;
using System.Drawing;
using System.Collections;
diff --git a/storage/ndb/src/cw/cpcc-win32/csharp/ComputerAddDialog.cs b/storage/ndb/src/cw/cpcc-win32/csharp/ComputerAddDialog.cs
index c01e41f3e60..506cb6777f0 100644
--- a/storage/ndb/src/cw/cpcc-win32/csharp/ComputerAddDialog.cs
+++ b/storage/ndb/src/cw/cpcc-win32/csharp/ComputerAddDialog.cs
@@ -1,3 +1,18 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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 */
+
using System;
using System.Drawing;
using System.Collections;
diff --git a/storage/ndb/src/cw/cpcc-win32/csharp/ComputerRemoveDialog.cs b/storage/ndb/src/cw/cpcc-win32/csharp/ComputerRemoveDialog.cs
index 5b4d1b56df7..a126c632ffd 100644
--- a/storage/ndb/src/cw/cpcc-win32/csharp/ComputerRemoveDialog.cs
+++ b/storage/ndb/src/cw/cpcc-win32/csharp/ComputerRemoveDialog.cs
@@ -1,3 +1,18 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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 */
+
using System;
using System.Drawing;
using System.Collections;
diff --git a/storage/ndb/src/cw/cpcc-win32/csharp/Database.cs b/storage/ndb/src/cw/cpcc-win32/csharp/Database.cs
index 39b8c160159..80a8daee2d0 100644
--- a/storage/ndb/src/cw/cpcc-win32/csharp/Database.cs
+++ b/storage/ndb/src/cw/cpcc-win32/csharp/Database.cs
@@ -1,3 +1,18 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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 */
+
using System;
using System.Drawing;
using System.Collections;
diff --git a/storage/ndb/src/cw/cpcc-win32/csharp/PanelWizard.cs b/storage/ndb/src/cw/cpcc-win32/csharp/PanelWizard.cs
index f492aa64c60..a780190f86c 100644
--- a/storage/ndb/src/cw/cpcc-win32/csharp/PanelWizard.cs
+++ b/storage/ndb/src/cw/cpcc-win32/csharp/PanelWizard.cs
@@ -1,3 +1,18 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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 */
+
//author:Arun
//date:Nov 13,2002
//Wizard using panel
diff --git a/storage/ndb/src/cw/cpcc-win32/csharp/Process.cs b/storage/ndb/src/cw/cpcc-win32/csharp/Process.cs
index c1ee1b2fe9e..eac12d4868e 100644
--- a/storage/ndb/src/cw/cpcc-win32/csharp/Process.cs
+++ b/storage/ndb/src/cw/cpcc-win32/csharp/Process.cs
@@ -1,3 +1,18 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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 */
+
using System;
using System.Drawing;
using System.Collections;
diff --git a/storage/ndb/src/cw/cpcc-win32/csharp/ProcessDefineDialog.cs b/storage/ndb/src/cw/cpcc-win32/csharp/ProcessDefineDialog.cs
index 581b8383e7c..ab8d58ed11f 100644
--- a/storage/ndb/src/cw/cpcc-win32/csharp/ProcessDefineDialog.cs
+++ b/storage/ndb/src/cw/cpcc-win32/csharp/ProcessDefineDialog.cs
@@ -1,3 +1,18 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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 */
+
using System;
using System.Drawing;
using System.Collections;
diff --git a/storage/ndb/src/cw/cpcc-win32/csharp/fileaccess/FileMgmt.cs b/storage/ndb/src/cw/cpcc-win32/csharp/fileaccess/FileMgmt.cs
index b3a2361bcb0..41929c104d0 100644
--- a/storage/ndb/src/cw/cpcc-win32/csharp/fileaccess/FileMgmt.cs
+++ b/storage/ndb/src/cw/cpcc-win32/csharp/fileaccess/FileMgmt.cs
@@ -1,3 +1,18 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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 */
+
using System;
using System.Text;
using System.Collections.Specialized;
diff --git a/storage/ndb/src/cw/cpcc-win32/csharp/simpleparser/SimpleCPCParser.cs b/storage/ndb/src/cw/cpcc-win32/csharp/simpleparser/SimpleCPCParser.cs
index b8ff2844af9..6e070875b25 100644
--- a/storage/ndb/src/cw/cpcc-win32/csharp/simpleparser/SimpleCPCParser.cs
+++ b/storage/ndb/src/cw/cpcc-win32/csharp/simpleparser/SimpleCPCParser.cs
@@ -1,3 +1,18 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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 */
+
using System;
using System.Collections;
using System.IO;
diff --git a/storage/ndb/src/cw/cpcc-win32/csharp/socketcomm/SocketComm.cs b/storage/ndb/src/cw/cpcc-win32/csharp/socketcomm/SocketComm.cs
index 2cef5d34f17..9025f122994 100644
--- a/storage/ndb/src/cw/cpcc-win32/csharp/socketcomm/SocketComm.cs
+++ b/storage/ndb/src/cw/cpcc-win32/csharp/socketcomm/SocketComm.cs
@@ -1,3 +1,18 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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 */
+
using System;
using System.Net;
using System.Net.Sockets;
diff --git a/storage/ndb/src/cw/cpcc-win32/csharp/socketcomm/myTcpClient.cs b/storage/ndb/src/cw/cpcc-win32/csharp/socketcomm/myTcpClient.cs
index 9c0d82a0b27..25d0d9947d6 100644
--- a/storage/ndb/src/cw/cpcc-win32/csharp/socketcomm/myTcpClient.cs
+++ b/storage/ndb/src/cw/cpcc-win32/csharp/socketcomm/myTcpClient.cs
@@ -1,3 +1,18 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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 */
+
using System;
using System.Net;
using System.Net.Sockets;
diff --git a/storage/ndb/src/cw/cpcc-win32/csharp/startDatabaseDlg.cs b/storage/ndb/src/cw/cpcc-win32/csharp/startDatabaseDlg.cs
index cecfcaeb0f3..4261efc8a29 100644
--- a/storage/ndb/src/cw/cpcc-win32/csharp/startDatabaseDlg.cs
+++ b/storage/ndb/src/cw/cpcc-win32/csharp/startDatabaseDlg.cs
@@ -1,3 +1,18 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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 */
+
using System;
using System.Drawing;
using System.Collections;
diff --git a/storage/ndb/src/cw/cpcc-win32/csharp/telnetclient/telnetClient.cs b/storage/ndb/src/cw/cpcc-win32/csharp/telnetclient/telnetClient.cs
index a7966947e1f..5258ad290fc 100644
--- a/storage/ndb/src/cw/cpcc-win32/csharp/telnetclient/telnetClient.cs
+++ b/storage/ndb/src/cw/cpcc-win32/csharp/telnetclient/telnetClient.cs
@@ -1,3 +1,18 @@
+/* Copyright (C) 2004 MySQL AB
+
+ 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 */
+
using System;
using System.Drawing;
using System.Collections;
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Computer.cls b/storage/ndb/src/cw/cpcc-win32/vb6/Computer.cls
deleted file mode 100644
index 5b42dfeadb6..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Computer.cls
+++ /dev/null
@@ -1,20 +0,0 @@
-VERSION 1.0 CLASS
-BEGIN
- MultiUse = -1 'True
- Persistable = 0 'NotPersistable
- DataBindingBehavior = 0 'vbNone
- DataSourceBehavior = 0 'vbNone
- MTSTransactionMode = 0 'NotAnMTSObject
-END
-Attribute VB_Name = "Computer"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = True
-Attribute VB_PredeclaredId = False
-Attribute VB_Exposed = False
-Attribute VB_Ext_KEY = "SavedWithClassBuilder6" ,"Yes"
-Attribute VB_Ext_KEY = "Top_Level" ,"Yes"
-Public m_ip As String
-Public m_name As String
-Public m_status As String
-Public m_processes As Collection
-
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Database.cls b/storage/ndb/src/cw/cpcc-win32/vb6/Database.cls
deleted file mode 100644
index dfb1195d910..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Database.cls
+++ /dev/null
@@ -1,18 +0,0 @@
-VERSION 1.0 CLASS
-BEGIN
- MultiUse = -1 'True
- Persistable = 0 'NotPersistable
- DataBindingBehavior = 0 'vbNone
- DataSourceBehavior = 0 'vbNone
- MTSTransactionMode = 0 'NotAnMTSObject
-END
-Attribute VB_Name = "Database_"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = True
-Attribute VB_PredeclaredId = False
-Attribute VB_Exposed = False
-Attribute VB_Ext_KEY = "SavedWithClassBuilder6" ,"Yes"
-Attribute VB_Ext_KEY = "Top_Level" ,"Yes"
-Public m_name As String
-Public m_processes As Collection
-Public m_status As String
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 110.ico b/storage/ndb/src/cw/cpcc-win32/vb6/Icon 110.ico
deleted file mode 100644
index 34b85992394..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 110.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 231.ico b/storage/ndb/src/cw/cpcc-win32/vb6/Icon 231.ico
deleted file mode 100644
index fe30ff5d1e6..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 231.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 237.ico b/storage/ndb/src/cw/cpcc-win32/vb6/Icon 237.ico
deleted file mode 100644
index af0a1294f9e..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 237.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 241.ico b/storage/ndb/src/cw/cpcc-win32/vb6/Icon 241.ico
deleted file mode 100644
index e8caf6e9a73..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 241.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 242.ico b/storage/ndb/src/cw/cpcc-win32/vb6/Icon 242.ico
deleted file mode 100644
index 2deff5472bc..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 242.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 270.ico b/storage/ndb/src/cw/cpcc-win32/vb6/Icon 270.ico
deleted file mode 100644
index 9cab239de23..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 270.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 271.ico b/storage/ndb/src/cw/cpcc-win32/vb6/Icon 271.ico
deleted file mode 100644
index f05c95f74fe..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 271.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 273.ico b/storage/ndb/src/cw/cpcc-win32/vb6/Icon 273.ico
deleted file mode 100644
index 800606eda0c..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 273.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 31.ico b/storage/ndb/src/cw/cpcc-win32/vb6/Icon 31.ico
deleted file mode 100644
index a2404977771..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 31.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 337.ico b/storage/ndb/src/cw/cpcc-win32/vb6/Icon 337.ico
deleted file mode 100644
index 9dadb12cfbe..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 337.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 338.ico b/storage/ndb/src/cw/cpcc-win32/vb6/Icon 338.ico
deleted file mode 100644
index a13c80c81b4..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 338.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 339.ico b/storage/ndb/src/cw/cpcc-win32/vb6/Icon 339.ico
deleted file mode 100644
index 5eb4c06815d..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Icon 339.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/MSSCCPRJ.SCC b/storage/ndb/src/cw/cpcc-win32/vb6/MSSCCPRJ.SCC
deleted file mode 100644
index 3100640f8bd..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/MSSCCPRJ.SCC
+++ /dev/null
@@ -1,5 +0,0 @@
-[SCC]
-SCC=This is a source code control file
-[NdbCPC.vbp]
-SCC_Project_Name=this project is not under source code control
-SCC_Aux_Path=<This is an empty string for the mssccprj.scc file>
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Module1.bas b/storage/ndb/src/cw/cpcc-win32/vb6/Module1.bas
deleted file mode 100644
index ae8ed444a41..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Module1.bas
+++ /dev/null
@@ -1,233 +0,0 @@
-Attribute VB_Name = "Module1"
-Option Explicit
-Public fMainForm As frmMain
-Public g_computers As New Collection
-Public g_databases As New Collection
-
-Sub Main()
- If False Then
- Dim fLogin As New frmLogin
- fLogin.Show vbModal
- If Not fLogin.OK Then
- 'Login Failed so exit app
- End
- End If
- Unload fLogin
-
- frmSplash.Show
- frmSplash.Refresh
- End If
-
- init
-
- Set fMainForm = New frmMain
- Load fMainForm
- Unload frmSplash
-
- fMainForm.Show
-End Sub
-
-Private Sub init()
- Dim c As Computer
- Dim p As Process
-
- ' ---
- ' One node configuration
- '
- Set c = New Computer
- With c
- .m_ip = "130.100.232.31"
- .m_name = "ndb-client31"
- .m_status = "Connected"
- Set .m_processes = New Collection
- End With
- addComputer c
-
- Set p = New Process
- With p
- .m_id = "1"
- .m_name = "mgm-1"
- .m_database = "elathal"
- .m_status = "Running"
- .m_owner = "elathal"
- Set .m_computer = c
- End With
- addProcess c, p
-
- Set p = New Process
- With p
- .m_id = "2"
- .m_name = "ndb-2"
- .m_database = "elathal"
- .m_status = "Running"
- .m_owner = "elathal"
- Set .m_computer = c
- End With
- addProcess c, p
-
- Set p = New Process
- With p
- .m_id = "3"
- .m_name = "api-3"
- .m_database = "elathal"
- .m_status = "Running"
- .m_owner = "elathal"
- Set .m_computer = c
- End With
- addProcess c, p
-
- ' ---
- ' Two node configuration
- '
- Set p = New Process
- With p
- .m_id = "4"
- .m_name = "mgm-1"
- .m_database = "ejonore-2-node"
- .m_status = "Running"
- .m_owner = "ejonore"
- Set .m_computer = c
- End With
- addProcess c, p
-
- Set c = New Computer
- With c
- .m_ip = "10.0.1.1"
- .m_name = "cluster-1"
- .m_status = "Connected"
- Set .m_processes = New Collection
- End With
- addComputer c
-
- Set p = New Process
- With p
- .m_id = "1"
- .m_name = "ndb-2"
- .m_database = "ejonore-2-node"
- .m_status = "Running"
- .m_owner = "ejonore"
- Set .m_computer = c
- End With
- addProcess c, p
-
- Set c = New Computer
- With c
- .m_ip = "10.0.2.1"
- .m_name = "cluster-2"
- .m_status = "Connected"
- Set .m_processes = New Collection
- End With
- addComputer c
-
- Set p = New Process
- With p
- .m_id = "1"
- .m_name = "ndb-3"
- .m_database = "ejonore-2-node"
- .m_status = "Running"
- .m_owner = "ejonore"
- Set .m_computer = c
- End With
- addProcess c, p
-
- Set c = New Computer
- With c
- .m_ip = "10.0.3.1"
- .m_name = "cluster-3"
- .m_status = "Connected"
- Set .m_processes = New Collection
- End With
- addComputer c
-
- Set p = New Process
- With p
- .m_id = "1"
- .m_name = "api-4"
- .m_database = "ejonore-2-node"
- .m_status = "Running"
- .m_owner = "ejonore"
- Set .m_computer = c
- End With
- addProcess c, p
-
- Set c = New Computer
- With c
- .m_ip = "10.0.4.1"
- .m_name = "cluster-4"
- .m_status = "Connected"
- Set .m_processes = New Collection
- End With
- addComputer c
-
- Set p = New Process
- With p
- .m_id = "1"
- .m_name = "api-5"
- .m_database = "ejonore-2-node"
- .m_status = "Running"
- .m_owner = "ejonore"
- Set .m_computer = c
- End With
- addProcess c, p
-
- Set c = New Computer
- With c
- .m_ip = "130.100.232.5"
- .m_name = "ndbs05"
- .m_status = "Not connected"
- Set .m_processes = New Collection
- End With
- addComputer c
-
- Set c = New Computer
- With c
- .m_ip = "130.100.232.7"
- .m_name = "ndb-srv7"
- .m_status = "No contact"
- Set .m_processes = New Collection
- End With
- addComputer c
-
-End Sub
-
-Public Sub addComputer(ByRef c As Computer)
- g_computers.Add c, "_" & c.m_name
-End Sub
-
-Private Sub addProcess(ByRef c As Computer, ByRef p As Process)
- c.m_processes.Add p, "_" & p.m_id
-
- Dim cl As Database_
- If Not Exists(g_databases, "_" & p.m_database) Then
- Set cl = New Database_
- With cl
- .m_name = p.m_database
- .m_status = "Unknown"
- Set .m_processes = New Collection
- End With
- g_databases.Add cl, "_" & p.m_database
- Else
- Set cl = g_databases("_" & p.m_database)
- End If
- cl.m_processes.Add p, "_" & p.m_computer.m_name & "_" & p.m_id
-End Sub
-
-Public Function Exists(ByRef c As Collection, ByVal k As String) As Boolean
- Dim r As Boolean
- Dim o As Object
-
- r = True
-
- On Error GoTo NotFound
- Set o = c.Item(k)
- GoTo Continue
-NotFound:
- If Err.Number <> 5 Then
- Err.Raise Err.Number, Err.Source, Err.Description
- End If
-
- r = False
-Continue:
- Exists = r
-End Function
-
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/NdbCPC.vbp b/storage/ndb/src/cw/cpcc-win32/vb6/NdbCPC.vbp
deleted file mode 100644
index dc8f3780a74..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/NdbCPC.vbp
+++ /dev/null
@@ -1,49 +0,0 @@
-Type=Exe
-Object={831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0; mscomctl.ocx
-Module=Module1; Module1.bas
-Form=frmMain.frm
-Form=frmSplash.frm
-Form=frmLogin.frm
-Form=frmOptions.frm
-Form=frmAbout.frm
-Class=Computer; Computer.cls
-Class=Process; Process.cls
-Class=Database_; Database.cls
-Form=frmNewComputer.frm
-Form=frmNewDatabase3.frm
-Form=frmNewDatabase1.frm
-Form=frmNewDatabase2.frm
-IconForm="frmAbout"
-Startup="Sub Main"
-HelpFile=""
-Title="NdbCPC"
-ExeName32="NdbCPC.exe"
-Command32=""
-Name="NdbCPC"
-HelpContextID="0"
-CompatibleMode="0"
-MajorVer=1
-MinorVer=0
-RevisionVer=0
-AutoIncrementVer=0
-ServerSupportFiles=0
-VersionCompanyName="ctp"
-CompilationType=0
-OptimizationType=0
-FavorPentiumPro(tm)=0
-CodeViewDebugInfo=0
-NoAliasing=0
-BoundsCheck=0
-OverflowCheck=0
-FlPointCheck=0
-FDIVCheck=0
-UnroundedFP=0
-StartMode=0
-Unattended=0
-Retained=0
-ThreadPerObject=0
-MaxNumberOfThreads=1
-DebugStartupOption=0
-
-[MS Transaction Server]
-AutoRefresh=1
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/NdbCPC.vbw b/storage/ndb/src/cw/cpcc-win32/vb6/NdbCPC.vbw
deleted file mode 100644
index 825abbc923a..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/NdbCPC.vbw
+++ /dev/null
@@ -1,13 +0,0 @@
-Module1 = 44, 44, 577, 492,
-frmMain = 44, 44, 577, 492, , 66, 66, 599, 514, C
-frmSplash = 132, 132, 670, 576, C, 88, 88, 621, 536, C
-frmLogin = 0, 0, 538, 444, C, 110, 110, 643, 558, C
-frmOptions = 176, 176, 714, 620, C, 132, 132, 665, 580, C
-frmAbout = 132, 132, 759, 511, C, 154, 154, 687, 602, C
-Computer = 110, 110, 648, 554,
-Process = 132, 132, 670, 576, C
-Database_ = 88, 88, 626, 532, C
-frmNewComputer = 44, 44, 582, 488, , 22, 22, 390, 218, C
-frmNewDatabase3 = 0, 0, 506, 444, , 0, 0, 506, 444, C
-frmNewDatabase1 = 132, 132, 638, 550, , 154, 154, 660, 572, C
-frmNewDatabase2 = 198, 198, 704, 616, , 176, 176, 682, 594, C
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/Process.cls b/storage/ndb/src/cw/cpcc-win32/vb6/Process.cls
deleted file mode 100644
index fcb4c2cbb2c..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/Process.cls
+++ /dev/null
@@ -1,22 +0,0 @@
-VERSION 1.0 CLASS
-BEGIN
- MultiUse = -1 'True
- Persistable = 0 'NotPersistable
- DataBindingBehavior = 0 'vbNone
- DataSourceBehavior = 0 'vbNone
- MTSTransactionMode = 0 'NotAnMTSObject
-END
-Attribute VB_Name = "Process"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = True
-Attribute VB_PredeclaredId = False
-Attribute VB_Exposed = False
-Attribute VB_Ext_KEY = "SavedWithClassBuilder6" ,"Yes"
-Attribute VB_Ext_KEY = "Top_Level" ,"Yes"
-Public m_computer As Computer
-Public m_id As String
-Public m_name As String
-Public m_database As String
-Public m_status As String
-Public m_owner As String
-
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/closed folder.ico b/storage/ndb/src/cw/cpcc-win32/vb6/closed folder.ico
deleted file mode 100644
index fe82350d376..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/closed folder.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/computer.ico b/storage/ndb/src/cw/cpcc-win32/vb6/computer.ico
deleted file mode 100644
index d73302d1cd5..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/computer.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/frmAbout.frm b/storage/ndb/src/cw/cpcc-win32/vb6/frmAbout.frm
deleted file mode 100644
index b842d20de21..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/frmAbout.frm
+++ /dev/null
@@ -1,245 +0,0 @@
-VERSION 5.00
-Begin VB.Form frmAbout
- BorderStyle = 3 'Fixed Dialog
- Caption = "About NdbCPC"
- ClientHeight = 3630
- ClientLeft = 45
- ClientTop = 330
- ClientWidth = 5865
- ClipControls = 0 'False
- LinkTopic = "Form1"
- MaxButton = 0 'False
- MinButton = 0 'False
- ScaleHeight = 3630
- ScaleWidth = 5865
- ShowInTaskbar = 0 'False
- StartUpPosition = 1 'CenterOwner
- Tag = "About NdbCPC"
- Begin VB.PictureBox picIcon
- AutoSize = -1 'True
- BackColor = &H00C0C0C0&
- ClipControls = 0 'False
- Height = 540
- Left = 240
- Picture = "frmAbout.frx":0000
- ScaleHeight = 480
- ScaleMode = 0 'User
- ScaleWidth = 480
- TabIndex = 2
- TabStop = 0 'False
- Top = 240
- Width = 540
- End
- Begin VB.CommandButton cmdOK
- Cancel = -1 'True
- Caption = "OK"
- Default = -1 'True
- Height = 345
- Left = 4245
- TabIndex = 0
- Tag = "OK"
- Top = 2625
- Width = 1467
- End
- Begin VB.CommandButton cmdSysInfo
- Caption = "&System Info..."
- Height = 345
- Left = 4260
- TabIndex = 1
- Tag = "&System Info..."
- Top = 3075
- Width = 1452
- End
- Begin VB.Label lblDescription
- Caption = "App Description"
- ForeColor = &H00000000&
- Height = 1170
- Left = 1050
- TabIndex = 6
- Tag = "App Description"
- Top = 1125
- Width = 4092
- End
- Begin VB.Label lblTitle
- Caption = "Application Title"
- ForeColor = &H00000000&
- Height = 480
- Left = 1050
- TabIndex = 5
- Tag = "Application Title"
- Top = 240
- Width = 4092
- End
- Begin VB.Line Line1
- BorderColor = &H00808080&
- BorderStyle = 6 'Inside Solid
- Index = 1
- X1 = 225
- X2 = 5657
- Y1 = 2430
- Y2 = 2430
- End
- Begin VB.Line Line1
- BorderColor = &H00FFFFFF&
- BorderWidth = 2
- Index = 0
- X1 = 240
- X2 = 5657
- Y1 = 2445
- Y2 = 2445
- End
- Begin VB.Label lblVersion
- Caption = "Version"
- Height = 225
- Left = 1050
- TabIndex = 4
- Tag = "Version"
- Top = 780
- Width = 4092
- End
- Begin VB.Label lblDisclaimer
- Caption = "Warning: ..."
- ForeColor = &H00000000&
- Height = 825
- Left = 255
- TabIndex = 3
- Tag = "Warning: ..."
- Top = 2625
- Width = 3870
- End
-End
-Attribute VB_Name = "frmAbout"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = False
-Attribute VB_PredeclaredId = True
-Attribute VB_Exposed = False
-' Reg Key Security Options...
-Const KEY_ALL_ACCESS = &H2003F
-
-
-' Reg Key ROOT Types...
-Const HKEY_LOCAL_MACHINE = &H80000002
-Const ERROR_SUCCESS = 0
-Const REG_SZ = 1 ' Unicode nul terminated string
-Const REG_DWORD = 4 ' 32-bit number
-
-
-Const gREGKEYSYSINFOLOC = "SOFTWARE\Microsoft\Shared Tools Location"
-Const gREGVALSYSINFOLOC = "MSINFO"
-Const gREGKEYSYSINFO = "SOFTWARE\Microsoft\Shared Tools\MSINFO"
-Const gREGVALSYSINFO = "PATH"
-
-
-Private Declare Function RegOpenKeyEx Lib "advapi32" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, ByRef phkResult As Long) As Long
-Private Declare Function RegQueryValueEx Lib "advapi32" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, ByRef lpType As Long, ByVal lpData As String, ByRef lpcbData As Long) As Long
-Private Declare Function RegCloseKey Lib "advapi32" (ByVal hKey As Long) As Long
-
-Private Sub Form_Load()
- lblVersion.Caption = "Version " & App.Major & "." & App.Minor & "." & App.Revision
- lblTitle.Caption = App.Title
-End Sub
-
-
-
-Private Sub cmdSysInfo_Click()
- Call StartSysInfo
-End Sub
-
-
-Private Sub cmdOK_Click()
- Unload Me
-End Sub
-
-
-Public Sub StartSysInfo()
- On Error GoTo SysInfoErr
-
-
- Dim rc As Long
- Dim SysInfoPath As String
-
-
- ' Try To Get System Info Program Path\Name From Registry...
- If GetKeyValue(HKEY_LOCAL_MACHINE, gREGKEYSYSINFO, gREGVALSYSINFO, SysInfoPath) Then
- ' Try To Get System Info Program Path Only From Registry...
- ElseIf GetKeyValue(HKEY_LOCAL_MACHINE, gREGKEYSYSINFOLOC, gREGVALSYSINFOLOC, SysInfoPath) Then
- ' Validate Existance Of Known 32 Bit File Version
- If (Dir(SysInfoPath & "\MSINFO32.EXE") <> "") Then
- SysInfoPath = SysInfoPath & "\MSINFO32.EXE"
-
-
- ' Error - File Can Not Be Found...
- Else
- GoTo SysInfoErr
- End If
- ' Error - Registry Entry Can Not Be Found...
- Else
- GoTo SysInfoErr
- End If
-
-
- Call Shell(SysInfoPath, vbNormalFocus)
-
-
- Exit Sub
-SysInfoErr:
- MsgBox "System Information Is Unavailable At This Time", vbOKOnly
-End Sub
-
-
-Public Function GetKeyValue(KeyRoot As Long, KeyName As String, SubKeyRef As String, ByRef KeyVal As String) As Boolean
- Dim i As Long ' Loop Counter
- Dim rc As Long ' Return Code
- Dim hKey As Long ' Handle To An Open Registry Key
- Dim hDepth As Long '
- Dim KeyValType As Long ' Data Type Of A Registry Key
- Dim tmpVal As String ' Tempory Storage For A Registry Key Value
- Dim KeyValSize As Long ' Size Of Registry Key Variable
- '------------------------------------------------------------
- ' Open RegKey Under KeyRoot {HKEY_LOCAL_MACHINE...}
- '------------------------------------------------------------
- rc = RegOpenKeyEx(KeyRoot, KeyName, 0, KEY_ALL_ACCESS, hKey) ' Open Registry Key
-
-
- If (rc <> ERROR_SUCCESS) Then GoTo GetKeyError ' Handle Error...
-
-
- tmpVal = String$(1024, 0) ' Allocate Variable Space
- KeyValSize = 1024 ' Mark Variable Size
-
-
- '------------------------------------------------------------
- ' Retrieve Registry Key Value...
- '------------------------------------------------------------
- rc = RegQueryValueEx(hKey, SubKeyRef, 0, KeyValType, tmpVal, KeyValSize) ' Get/Create Key Value
-
-
- If (rc <> ERROR_SUCCESS) Then GoTo GetKeyError ' Handle Errors
-
-
- tmpVal = VBA.Left(tmpVal, InStr(tmpVal, VBA.Chr(0)) - 1)
- '------------------------------------------------------------
- ' Determine Key Value Type For Conversion...
- '------------------------------------------------------------
- Select Case KeyValType ' Search Data Types...
- Case REG_SZ ' String Registry Key Data Type
- KeyVal = tmpVal ' Copy String Value
- Case REG_DWORD ' Double Word Registry Key Data Type
- For i = Len(tmpVal) To 1 Step -1 ' Convert Each Bit
- KeyVal = KeyVal + Hex(Asc(Mid(tmpVal, i, 1))) ' Build Value Char. By Char.
- Next
- KeyVal = Format$("&h" + KeyVal) ' Convert Double Word To String
- End Select
-
-
- GetKeyValue = True ' Return Success
- rc = RegCloseKey(hKey) ' Close Registry Key
- Exit Function ' Exit
-
-
-GetKeyError: ' Cleanup After An Error Has Occured...
- KeyVal = "" ' Set Return Val To Empty String
- GetKeyValue = False ' Return Failure
- rc = RegCloseKey(hKey) ' Close Registry Key
-End Function
-
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/frmLogin.frm b/storage/ndb/src/cw/cpcc-win32/vb6/frmLogin.frm
deleted file mode 100644
index d4d663c93c2..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/frmLogin.frm
+++ /dev/null
@@ -1,119 +0,0 @@
-VERSION 5.00
-Begin VB.Form frmLogin
- BorderStyle = 3 'Fixed Dialog
- Caption = "Login"
- ClientHeight = 1590
- ClientLeft = 45
- ClientTop = 330
- ClientWidth = 3750
- LinkTopic = "Form1"
- MaxButton = 0 'False
- MinButton = 0 'False
- ScaleHeight = 1590
- ScaleWidth = 3750
- ShowInTaskbar = 0 'False
- StartUpPosition = 2 'CenterScreen
- Tag = "Login"
- Begin VB.CommandButton cmdCancel
- Cancel = -1 'True
- Caption = "Cancel"
- Height = 360
- Left = 2100
- TabIndex = 5
- Tag = "Cancel"
- Top = 1020
- Width = 1140
- End
- Begin VB.CommandButton cmdOK
- Caption = "OK"
- Default = -1 'True
- Height = 360
- Left = 495
- TabIndex = 4
- Tag = "OK"
- Top = 1020
- Width = 1140
- End
- Begin VB.TextBox txtPassword
- Height = 285
- IMEMode = 3 'DISABLE
- Left = 1305
- PasswordChar = "*"
- TabIndex = 1
- Top = 525
- Width = 2325
- End
- Begin VB.TextBox txtUserName
- Height = 285
- Left = 1305
- TabIndex = 3
- Top = 135
- Width = 2325
- End
- Begin VB.Label lblLabels
- Caption = "&Password:"
- Height = 248
- Index = 1
- Left = 105
- TabIndex = 0
- Tag = "&Password:"
- Top = 540
- Width = 1080
- End
- Begin VB.Label lblLabels
- Caption = "&User Name:"
- Height = 248
- Index = 0
- Left = 105
- TabIndex = 2
- Tag = "&User Name:"
- Top = 150
- Width = 1080
- End
-End
-Attribute VB_Name = "frmLogin"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = False
-Attribute VB_PredeclaredId = True
-Attribute VB_Exposed = False
-Private Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" (ByVal lpbuffer As String, nSize As Long) As Long
-
-
-Public OK As Boolean
-Private Sub Form_Load()
- Dim sBuffer As String
- Dim lSize As Long
-
-
- sBuffer = Space$(255)
- lSize = Len(sBuffer)
- Call GetUserName(sBuffer, lSize)
- If lSize > 0 Then
- txtUserName.Text = Left$(sBuffer, lSize)
- Else
- txtUserName.Text = vbNullString
- End If
-End Sub
-
-
-
-Private Sub cmdCancel_Click()
- OK = False
- Me.Hide
-End Sub
-
-
-Private Sub cmdOK_Click()
- 'ToDo: create test for correct password
- 'check for correct password
- If txtPassword.Text = "" Then
- OK = True
- Me.Hide
- Else
- MsgBox "Invalid Password, try again!", , "Login"
- txtPassword.SetFocus
- txtPassword.SelStart = 0
- txtPassword.SelLength = Len(txtPassword.Text)
- End If
-End Sub
-
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/frmMain.frm b/storage/ndb/src/cw/cpcc-win32/vb6/frmMain.frm
deleted file mode 100644
index a4bf5b58941..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/frmMain.frm
+++ /dev/null
@@ -1,1207 +0,0 @@
-VERSION 5.00
-Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0"; "mscomctl.ocx"
-Begin VB.Form frmMain
- Caption = "NdbCPC"
- ClientHeight = 5955
- ClientLeft = 2115
- ClientTop = 2250
- ClientWidth = 8880
- LinkTopic = "Form1"
- ScaleHeight = 5955
- ScaleWidth = 8880
- Begin MSComctlLib.ImageList ImageList1
- Left = 6840
- Top = 3120
- _ExtentX = 1005
- _ExtentY = 1005
- BackColor = 16777215
- ImageWidth = 16
- ImageHeight = 16
- MaskColor = 12632256
- _Version = 393216
- BeginProperty Images {2C247F25-8591-11D1-B16A-00C0F0283628}
- NumListImages = 11
- BeginProperty ListImage1 {2C247F27-8591-11D1-B16A-00C0F0283628}
- Picture = "frmMain.frx":0000
- Key = "close"
- EndProperty
- BeginProperty ListImage2 {2C247F27-8591-11D1-B16A-00C0F0283628}
- Picture = "frmMain.frx":27B4
- Key = "open"
- EndProperty
- BeginProperty ListImage3 {2C247F27-8591-11D1-B16A-00C0F0283628}
- Picture = "frmMain.frx":4F68
- Key = "computer_unknown"
- EndProperty
- BeginProperty ListImage4 {2C247F27-8591-11D1-B16A-00C0F0283628}
- Picture = "frmMain.frx":5284
- Key = "computer_stopped"
- EndProperty
- BeginProperty ListImage5 {2C247F27-8591-11D1-B16A-00C0F0283628}
- Picture = "frmMain.frx":55A0
- Key = "computer_started"
- EndProperty
- BeginProperty ListImage6 {2C247F27-8591-11D1-B16A-00C0F0283628}
- Picture = "frmMain.frx":58BC
- Key = ""
- EndProperty
- BeginProperty ListImage7 {2C247F27-8591-11D1-B16A-00C0F0283628}
- Picture = "frmMain.frx":5BD8
- Key = ""
- EndProperty
- BeginProperty ListImage8 {2C247F27-8591-11D1-B16A-00C0F0283628}
- Picture = "frmMain.frx":5EF4
- Key = ""
- EndProperty
- BeginProperty ListImage9 {2C247F27-8591-11D1-B16A-00C0F0283628}
- Picture = "frmMain.frx":6210
- Key = "db"
- EndProperty
- BeginProperty ListImage10 {2C247F27-8591-11D1-B16A-00C0F0283628}
- Picture = "frmMain.frx":652A
- Key = "computer"
- EndProperty
- BeginProperty ListImage11 {2C247F27-8591-11D1-B16A-00C0F0283628}
- Picture = "frmMain.frx":6844
- Key = "properties"
- EndProperty
- EndProperty
- End
- Begin VB.PictureBox picSplitter
- BackColor = &H00808080&
- BorderStyle = 0 'None
- FillColor = &H00808080&
- Height = 4800
- Left = 5400
- ScaleHeight = 2090.126
- ScaleMode = 0 'User
- ScaleWidth = 780
- TabIndex = 6
- Top = 705
- Width = 72
- Visible = 0 'False
- End
- Begin MSComctlLib.TreeView tvTreeView
- Height = 4800
- Left = 0
- TabIndex = 5
- Top = 705
- Width = 2016
- _ExtentX = 3545
- _ExtentY = 8467
- _Version = 393217
- HideSelection = 0 'False
- Indentation = 0
- LineStyle = 1
- Sorted = -1 'True
- Style = 7
- FullRowSelect = -1 'True
- ImageList = "ImageList1"
- Appearance = 1
- End
- Begin VB.PictureBox picTitles
- Align = 1 'Align Top
- Appearance = 0 'Flat
- BorderStyle = 0 'None
- ForeColor = &H80000008&
- Height = 300
- Left = 0
- ScaleHeight = 300
- ScaleWidth = 8880
- TabIndex = 2
- TabStop = 0 'False
- Top = 420
- Width = 8880
- Begin VB.Label lblTitle
- BorderStyle = 1 'Fixed Single
- Caption = " ListView:"
- Height = 270
- Index = 1
- Left = 2078
- TabIndex = 4
- Tag = " ListView:"
- Top = 12
- Width = 3216
- End
- Begin VB.Label lblTitle
- BorderStyle = 1 'Fixed Single
- Caption = " TreeView:"
- Height = 270
- Index = 0
- Left = 0
- TabIndex = 3
- Tag = " TreeView:"
- Top = 12
- Width = 2016
- End
- End
- Begin MSComctlLib.Toolbar tbToolBar
- Align = 1 'Align Top
- Height = 420
- Left = 0
- TabIndex = 1
- Top = 0
- Width = 8880
- _ExtentX = 15663
- _ExtentY = 741
- ButtonWidth = 609
- ButtonHeight = 582
- Appearance = 1
- ImageList = "ImageList1"
- _Version = 393216
- BeginProperty Buttons {66833FE8-8583-11D1-B16A-00C0F0283628}
- NumButtons = 5
- BeginProperty Button1 {66833FEA-8583-11D1-B16A-00C0F0283628}
- Style = 3
- EndProperty
- BeginProperty Button2 {66833FEA-8583-11D1-B16A-00C0F0283628}
- Key = "Add computer"
- Object.ToolTipText = "Add computer"
- ImageKey = "computer"
- EndProperty
- BeginProperty Button3 {66833FEA-8583-11D1-B16A-00C0F0283628}
- Key = "New database"
- Object.ToolTipText = "New database"
- ImageKey = "db"
- EndProperty
- BeginProperty Button4 {66833FEA-8583-11D1-B16A-00C0F0283628}
- Style = 3
- EndProperty
- BeginProperty Button5 {66833FEA-8583-11D1-B16A-00C0F0283628}
- Key = "Properties"
- Object.ToolTipText = "Properties"
- ImageKey = "properties"
- EndProperty
- EndProperty
- End
- Begin MSComctlLib.StatusBar sbStatusBar
- Align = 2 'Align Bottom
- Height = 270
- Left = 0
- TabIndex = 0
- Top = 5685
- Width = 8880
- _ExtentX = 15663
- _ExtentY = 476
- _Version = 393216
- BeginProperty Panels {8E3867A5-8586-11D1-B16A-00C0F0283628}
- NumPanels = 3
- BeginProperty Panel1 {8E3867AB-8586-11D1-B16A-00C0F0283628}
- AutoSize = 1
- Object.Width = 10028
- Text = "Status"
- TextSave = "Status"
- EndProperty
- BeginProperty Panel2 {8E3867AB-8586-11D1-B16A-00C0F0283628}
- Style = 6
- AutoSize = 2
- TextSave = "2002-10-15"
- EndProperty
- BeginProperty Panel3 {8E3867AB-8586-11D1-B16A-00C0F0283628}
- Style = 5
- AutoSize = 2
- TextSave = "09:44"
- EndProperty
- EndProperty
- End
- Begin MSComctlLib.ListView lvProcesses
- Height = 4815
- Left = 2040
- TabIndex = 8
- Top = 720
- Width = 3255
- _ExtentX = 5741
- _ExtentY = 8493
- Sorted = -1 'True
- MultiSelect = -1 'True
- LabelWrap = -1 'True
- HideSelection = 0 'False
- AllowReorder = -1 'True
- FullRowSelect = -1 'True
- _Version = 393217
- ForeColor = -2147483640
- BackColor = -2147483643
- BorderStyle = 1
- Appearance = 1
- NumItems = 6
- BeginProperty ColumnHeader(1) {BDD1F052-858B-11D1-B16A-00C0F0283628}
- Key = "Id"
- Text = "Id"
- Object.Width = 2540
- EndProperty
- BeginProperty ColumnHeader(2) {BDD1F052-858B-11D1-B16A-00C0F0283628}
- SubItemIndex = 1
- Key = "Computer"
- Text = "Computer"
- Object.Width = 2540
- EndProperty
- BeginProperty ColumnHeader(3) {BDD1F052-858B-11D1-B16A-00C0F0283628}
- SubItemIndex = 2
- Key = "Database"
- Text = "Database"
- Object.Width = 2540
- EndProperty
- BeginProperty ColumnHeader(4) {BDD1F052-858B-11D1-B16A-00C0F0283628}
- SubItemIndex = 3
- Key = "Name"
- Text = "Name"
- Object.Width = 2540
- EndProperty
- BeginProperty ColumnHeader(5) {BDD1F052-858B-11D1-B16A-00C0F0283628}
- SubItemIndex = 4
- Key = "Status"
- Text = "Status"
- Object.Width = 2540
- EndProperty
- BeginProperty ColumnHeader(6) {BDD1F052-858B-11D1-B16A-00C0F0283628}
- SubItemIndex = 5
- Key = "Owner"
- Text = "Owner"
- Object.Width = 2540
- EndProperty
- End
- Begin MSComctlLib.ListView lvComputers
- Height = 4815
- Left = 2040
- TabIndex = 7
- Top = 720
- Width = 3255
- _ExtentX = 5741
- _ExtentY = 8493
- Sorted = -1 'True
- MultiSelect = -1 'True
- LabelWrap = -1 'True
- HideSelection = -1 'True
- AllowReorder = -1 'True
- FullRowSelect = -1 'True
- _Version = 393217
- Icons = "ImageList1"
- SmallIcons = "ImageList1"
- ForeColor = -2147483640
- BackColor = -2147483643
- BorderStyle = 1
- Appearance = 1
- NumItems = 2
- BeginProperty ColumnHeader(1) {BDD1F052-858B-11D1-B16A-00C0F0283628}
- Text = "Computer"
- Object.Width = 2540
- EndProperty
- BeginProperty ColumnHeader(2) {BDD1F052-858B-11D1-B16A-00C0F0283628}
- SubItemIndex = 1
- Text = "Status"
- Object.Width = 2540
- EndProperty
- End
- Begin MSComctlLib.ListView lvDatabases
- Height = 4815
- Left = 2040
- TabIndex = 9
- Top = 720
- Width = 3255
- _ExtentX = 5741
- _ExtentY = 8493
- View = 3
- Sorted = -1 'True
- MultiSelect = -1 'True
- LabelWrap = -1 'True
- HideSelection = -1 'True
- AllowReorder = -1 'True
- FullRowSelect = -1 'True
- _Version = 393217
- Icons = "ImageList1"
- SmallIcons = "ImageList1"
- ForeColor = -2147483640
- BackColor = -2147483643
- BorderStyle = 1
- Appearance = 1
- NumItems = 2
- BeginProperty ColumnHeader(1) {BDD1F052-858B-11D1-B16A-00C0F0283628}
- Key = "Database"
- Text = "Database"
- Object.Width = 2540
- EndProperty
- BeginProperty ColumnHeader(2) {BDD1F052-858B-11D1-B16A-00C0F0283628}
- SubItemIndex = 1
- Key = "Status"
- Text = "Status"
- Object.Width = 2540
- EndProperty
- End
- Begin VB.Image imgSplitter
- Height = 4788
- Left = 1965
- MousePointer = 9 'Size W E
- Top = 705
- Width = 150
- End
- Begin VB.Menu mnuFile
- Caption = "&File"
- Begin VB.Menu mnuFileOpen
- Caption = "&Open..."
- End
- Begin VB.Menu mnuFileFind
- Caption = "&Find"
- End
- Begin VB.Menu mnuFileBar0
- Caption = "-"
- End
- Begin VB.Menu mnuFileSendTo
- Caption = "Sen&d to"
- End
- Begin VB.Menu mnuFileBar1
- Caption = "-"
- End
- Begin VB.Menu mnuFileNew
- Caption = "&New"
- Shortcut = ^N
- End
- Begin VB.Menu mnuFileBar2
- Caption = "-"
- End
- Begin VB.Menu mnuFileDelete
- Caption = "&Delete"
- End
- Begin VB.Menu mnuFileRename
- Caption = "Rena&me"
- End
- Begin VB.Menu mnuFileProperties
- Caption = "Propert&ies"
- End
- Begin VB.Menu mnuFileBar3
- Caption = "-"
- End
- Begin VB.Menu mnuFileMRU
- Caption = ""
- Index = 1
- Visible = 0 'False
- End
- Begin VB.Menu mnuFileMRU
- Caption = ""
- Index = 2
- Visible = 0 'False
- End
- Begin VB.Menu mnuFileMRU
- Caption = ""
- Index = 3
- Visible = 0 'False
- End
- Begin VB.Menu mnuFileBar4
- Caption = "-"
- Visible = 0 'False
- End
- Begin VB.Menu mnuFileBar5
- Caption = "-"
- End
- Begin VB.Menu mnuFileClose
- Caption = "&Close"
- End
- End
- Begin VB.Menu mnuEdit
- Caption = "&Edit"
- Begin VB.Menu mnuEditUndo
- Caption = "&Undo"
- End
- Begin VB.Menu mnuEditBar0
- Caption = "-"
- End
- Begin VB.Menu mnuEditCut
- Caption = "Cu&t"
- Shortcut = ^X
- End
- Begin VB.Menu mnuEditCopy
- Caption = "&Copy"
- Shortcut = ^C
- End
- Begin VB.Menu mnuEditPaste
- Caption = "&Paste"
- Shortcut = ^V
- End
- Begin VB.Menu mnuEditPasteSpecial
- Caption = "Paste &Special..."
- End
- Begin VB.Menu mnuEditBar1
- Caption = "-"
- End
- Begin VB.Menu mnuEditSelectAll
- Caption = "Select &All"
- Shortcut = ^A
- End
- Begin VB.Menu mnuEditInvertSelection
- Caption = "&Invert Selection"
- End
- End
- Begin VB.Menu mnuView
- Caption = "&View"
- Begin VB.Menu mnuViewToolbar
- Caption = "&Toolbar"
- Checked = -1 'True
- End
- Begin VB.Menu mnuViewStatusBar
- Caption = "Status &Bar"
- Checked = -1 'True
- End
- Begin VB.Menu mnuViewBar0
- Caption = "-"
- End
- Begin VB.Menu mnuListViewMode
- Caption = "Lar&ge Icons"
- Index = 0
- End
- Begin VB.Menu mnuListViewMode
- Caption = "S&mall Icons"
- Index = 1
- End
- Begin VB.Menu mnuListViewMode
- Caption = "&List"
- Index = 2
- End
- Begin VB.Menu mnuListViewMode
- Caption = "&Details"
- Index = 3
- End
- Begin VB.Menu mnuViewBar1
- Caption = "-"
- End
- Begin VB.Menu mnuViewArrangeIcons
- Caption = "Arrange &Icons"
- End
- Begin VB.Menu mnuViewBar2
- Caption = "-"
- End
- Begin VB.Menu mnuViewRefresh
- Caption = "&Refresh"
- End
- Begin VB.Menu mnuViewOptions
- Caption = "&Options..."
- End
- Begin VB.Menu mnuViewWebBrowser
- Caption = "&Web Browser"
- End
- End
- Begin VB.Menu mnuHelp
- Caption = "&Help"
- Begin VB.Menu mnuHelpContents
- Caption = "&Contents"
- End
- Begin VB.Menu mnuHelpSearchForHelpOn
- Caption = "&Search For Help On..."
- End
- Begin VB.Menu mnuHelpBar0
- Caption = "-"
- End
- Begin VB.Menu mnuHelpAbout
- Caption = "&About "
- End
- End
- Begin VB.Menu mnuPopComputers
- Caption = ""
- Visible = 0 'False
- Begin VB.Menu mnuPopAddComputer
- Caption = "Add computer"
- End
- Begin VB.Menu mnuPop__
- Caption = "-"
- End
- Begin VB.Menu mnuPopSortComputers
- Caption = "Sorted"
- End
- End
- Begin VB.Menu mnuPopDatabases
- Caption = ""
- Visible = 0 'False
- Begin VB.Menu mnuPopNewDatabase
- Caption = "New database"
- End
- Begin VB.Menu mnuPopSortDatabases0
- Caption = "-"
- End
- Begin VB.Menu mnuPopSortDatabases
- Caption = "Sorted"
- End
- End
- Begin VB.Menu mnuPopComputer
- Caption = ""
- Visible = 0 'False
- Begin VB.Menu mnuPopComputerName
- Caption = "ComputerName"
- Enabled = 0 'False
- End
- Begin VB.Menu mnuPopComputer0
- Caption = "-"
- End
- Begin VB.Menu mnuPopConnectComputer
- Caption = "Connect"
- End
- Begin VB.Menu mnuPopDisconnectComputer
- Caption = "Disconnect"
- End
- Begin VB.Menu mnuPopRemoveComputer
- Caption = "Remove"
- End
- Begin VB.Menu mnuComputer1
- Caption = "-"
- End
- Begin VB.Menu mnuPopComputerProperties
- Caption = "Properties"
- End
- End
-End
-Attribute VB_Name = "frmMain"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = False
-Attribute VB_PredeclaredId = True
-Attribute VB_Exposed = False
-Option Explicit
-Private Declare Function OSWinHelp% Lib "user32" Alias "WinHelpA" (ByVal hwnd&, ByVal HelpFile$, ByVal wCommand%, dwData As Any)
-
-Dim mbMoving As Boolean
-Const sglSplitLimit = 500
-Dim m_currentNode As MSComctlLib.Node
-Dim m_currentList As ListView
-
-Dim m_currentView As Integer
-Dim m_computerWidth As Integer
-Dim m_databaseWidth As Integer
-
-Dim m_currentComputer As Computer
-Dim m_currentDatabase As Database_
-
-Private Sub Form_Load()
- tvTreeView.Nodes.Clear
- lvComputers.ListItems.Clear
- lvProcesses.ListItems.Clear
- lvDatabases.ListItems.Clear
-
- Me.Left = GetSetting(App.Title, "Settings", "MainLeft", 1000)
- Me.Top = GetSetting(App.Title, "Settings", "MainTop", 1000)
- Me.Width = GetSetting(App.Title, "Settings", "MainWidth", 6500)
- Me.Height = GetSetting(App.Title, "Settings", "MainHeight", 6500)
-
- tvTreeView.Nodes.Add , tvwChild, "Computers", "Computers", 1, 2
- Dim c As Computer
- For Each c In g_computers
- addComputer c
- Next
-
- Set m_currentNode = tvTreeView.Nodes("Computers")
- Set m_currentList = lvComputers
-
- tvTreeView.Nodes.Add , tvwChild, "Databases", "Databases", 1, 2
- Dim d As Database_
- For Each d In g_databases
- AddDatabase d
- Next
-
- lvComputers.Visible = True
- lvProcesses.Visible = False
- lvDatabases.Visible = False
- lvComputers.View = lvwReport
- lvProcesses.View = lvwReport
- lvDatabases.View = lvwReport
- m_computerWidth = lvProcesses.ColumnHeaders("Computer").Width
- m_databaseWidth = lvProcesses.ColumnHeaders("Database").Width
- lvProcesses.ColumnHeaders("Id").Width = 0
-End Sub
-
-Private Sub setComputer(ByVal f_ip As String)
- Dim c As Computer
- Set c = g_computers(f_ip)
- If c Is Nothing Then
- MsgBox "Unknown computer: " & f_ip
- Exit Sub
- End If
-
- Set m_currentComputer = c
-
- lblTitle(1).Caption = "Processes defined on computer: " & c.m_name
- setProcesses c.m_processes
-
- If lvProcesses.ColumnHeaders("Computer").Width <> 0 Then
- m_computerWidth = lvProcesses.ColumnHeaders("Computer").Width
- lvProcesses.ColumnHeaders("Computer").Width = 0
- End If
-
- If lvProcesses.ColumnHeaders("Database").Width = 0 Then
- lvProcesses.ColumnHeaders("Database").Width = m_databaseWidth
- End If
-End Sub
-
-Private Sub setDatabase(ByVal f_name As String)
- Dim c As Database_
- Set c = g_databases(f_name)
- If c Is Nothing Then
- MsgBox "Unknown database: " & f_name
- Exit Sub
- End If
-
- Set m_currentDatabase = c
-
- lblTitle(1).Caption = "Processes defined for database: " & c.m_name
- setProcesses c.m_processes
-
- If lvProcesses.ColumnHeaders("Database").Width <> 0 Then
- m_databaseWidth = lvProcesses.ColumnHeaders("Database").Width
- lvProcesses.ColumnHeaders("Database").Width = 0
- End If
-
- If lvProcesses.ColumnHeaders("Computer").Width = 0 Then
- lvProcesses.ColumnHeaders("Computer").Width = m_computerWidth
- End If
-
-End Sub
-
-Private Sub setProcesses(ByRef c As Collection)
- lvProcesses.ListItems.Clear
- Dim p As Process
- For Each p In c
- Dim li As ListItem
- Set li = lvProcesses.ListItems.Add(, "_" & p.m_computer.m_name & "_" & p.m_id, p.m_id)
- li.SubItems(1) = p.m_computer.m_name
- li.SubItems(2) = p.m_database
- li.SubItems(3) = p.m_name
- li.SubItems(4) = p.m_status
- li.SubItems(5) = p.m_owner
- Next
-End Sub
-
-Public Sub addComputer(ByRef c As Computer)
- Dim icon As Integer
- Select Case c.m_status
- Case "No contact"
- icon = 4
- Case "Connected"
- icon = 5
- Case Else
- icon = 3
- End Select
-
- Dim li As ListItem
- Set li = lvComputers.ListItems.Add(, "_" & c.m_name, c.m_name, icon, icon)
- li.SubItems(1) = c.m_status
-
- tvTreeView.Nodes.Add "Computers", tvwChild, "_" & c.m_name, c.m_name, icon, icon
-End Sub
-
-Public Sub removeComputer(ByRef name As String)
- lvComputers.ListItems.Remove "_" & name
- tvTreeView.Nodes.Remove "_" & name
-
- '
- ' Check if should remove database
- Dim c As Computer
- Set c = g_computers("_" & name)
- Dim db As Database_
- Dim dbs As New Collection
- Dim p As Process
- For Each p In c.m_processes
- Set db = g_databases("_" & p.m_database)
- db.m_processes.Remove "_" & p.m_computer.m_name & "_" & p.m_id
- If Not Exists(dbs, p.m_database) Then dbs.Add db, p.m_database
- Next
-
- For Each db In dbs
- If db.m_processes.Count = 0 Then
- g_databases.Remove "_" & db.m_name
- tvTreeView.Nodes.Remove "_" & db.m_name
- End If
- Next
-
- g_computers.Remove "_" & name
-
- '
- ' Check if should remove database
-
- Dim n As MSComctlLib.Node
- Set n = tvTreeView.SelectedItem
- selectNode n
-End Sub
-
-Private Sub AddDatabase(ByRef c As Database_)
- Dim li As ListItem
- Set li = lvDatabases.ListItems.Add(, "_" & c.m_name, c.m_name, 9, 9)
- li.SubItems(1) = c.m_status
- tvTreeView.Nodes.Add "Databases", tvwChild, "_" & c.m_name, c.m_name, 9, 9
-End Sub
-
-Private Sub Form_Unload(Cancel As Integer)
- Dim i As Integer
-
-
- 'close all sub forms
- For i = Forms.Count - 1 To 1 Step -1
- Unload Forms(i)
- Next
- If Me.WindowState <> vbMinimized Then
- SaveSetting App.Title, "Settings", "MainLeft", Me.Left
- SaveSetting App.Title, "Settings", "MainTop", Me.Top
- SaveSetting App.Title, "Settings", "MainWidth", Me.Width
- SaveSetting App.Title, "Settings", "MainHeight", Me.Height
- End If
-End Sub
-
-Private Sub Form_Resize()
- On Error Resume Next
- If Me.Width < 3000 Then Me.Width = 3000
- SizeControls imgSplitter.Left
-End Sub
-
-Private Sub imgSplitter_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
- With imgSplitter
- picSplitter.Move .Left, .Top, .Width \ 2, .Height - 20
- End With
- picSplitter.Visible = True
- mbMoving = True
-End Sub
-
-Private Sub imgSplitter_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
- Dim sglPos As Single
-
-
- If mbMoving Then
- sglPos = X + imgSplitter.Left
- If sglPos < sglSplitLimit Then
- picSplitter.Left = sglSplitLimit
- ElseIf sglPos > Me.Width - sglSplitLimit Then
- picSplitter.Left = Me.Width - sglSplitLimit
- Else
- picSplitter.Left = sglPos
- End If
- End If
-End Sub
-
-
-Private Sub imgSplitter_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
- SizeControls picSplitter.Left
- picSplitter.Visible = False
- mbMoving = False
-End Sub
-
-
-Private Sub TreeView1_DragDrop(Source As Control, X As Single, Y As Single)
- If Source = imgSplitter Then
- SizeControls X
- End If
-End Sub
-
-
-Sub SizeControls(X As Single)
- On Error Resume Next
-
- 'set the width
- If X < 1500 Then X = 1500
- If X > (Me.Width - 1500) Then X = Me.Width - 1500
- tvTreeView.Width = X
- imgSplitter.Left = X
-
- Dim t_left, t_width As Integer
- t_left = X + 40
- t_width = Me.Width - (tvTreeView.Width + 140)
-
- lblTitle(0).Width = tvTreeView.Width
- lblTitle(1).Left = t_left + 20
- lblTitle(1).Width = t_width - 40
-
-
- 'set the top
- If tbToolBar.Visible Then
- tvTreeView.Top = tbToolBar.Height + picTitles.Height
- Else
- tvTreeView.Top = picTitles.Height
- End If
-
-
- 'set the height
- If sbStatusBar.Visible Then
- tvTreeView.Height = Me.ScaleHeight - (picTitles.Top + picTitles.Height + sbStatusBar.Height)
- Else
- tvTreeView.Height = Me.ScaleHeight - (picTitles.Top + picTitles.Height)
- End If
-
-
- imgSplitter.Top = tvTreeView.Top
- imgSplitter.Height = tvTreeView.Height
-
- setListDimensions t_left, t_width, tvTreeView.Top, tvTreeView.Height
-End Sub
-
-Private Sub setListView(ByVal f_View As Integer)
- lvComputers.View = f_View
- lvProcesses.View = f_View
-End Sub
-
-Private Sub setListDimensions(ByVal f_Left As Integer, ByVal f_Width As Integer, ByVal f_Top As Integer, ByVal f_Height As Integer)
- With lvComputers
- .Left = f_Left
- .Width = f_Width
- .Top = f_Top
- .Height = f_Height
- End With
- With lvProcesses
- .Left = f_Left
- .Width = f_Width
- .Top = f_Top
- .Height = f_Height
- End With
- With lvDatabases
- .Left = f_Left
- .Width = f_Width
- .Top = f_Top
- .Height = f_Height
- End With
-End Sub
-
-Private Sub tbToolBar_ButtonClick(ByVal Button As MSComctlLib.Button)
- On Error Resume Next
- Select Case Button.Key
- Case "New database"
- 'ToDo: Add 'Back' button code.
- mnuPopNewDatabase_Click
- Case "Add computer"
- 'ToDo: Add 'Forward' button code.
- frmNewComputer.Show vbModal, Me
- Dim c As Computer
- For Each c In frmNewComputer.m_hosts
- addComputer c
- g_computers.Add c, "_" & c.m_name
- Next
- Case "Properties"
- mnuFileProperties_Click
- End Select
-End Sub
-
-Private Sub mnuHelpAbout_Click()
- frmAbout.Show vbModal, Me
-End Sub
-
-Private Sub mnuHelpSearchForHelpOn_Click()
- Dim nRet As Integer
-
-
- 'if there is no helpfile for this project display a message to the user
- 'you can set the HelpFile for your application in the
- 'Project Properties dialog
- If Len(App.HelpFile) = 0 Then
- MsgBox "Unable to display Help Contents. There is no Help associated with this project.", vbInformation, Me.Caption
- Else
- On Error Resume Next
- nRet = OSWinHelp(Me.hwnd, App.HelpFile, 261, 0)
- If Err Then
- MsgBox Err.Description
- End If
- End If
-
-End Sub
-
-Private Sub mnuHelpContents_Click()
- Dim nRet As Integer
-
-
- 'if there is no helpfile for this project display a message to the user
- 'you can set the HelpFile for your application in the
- 'Project Properties dialog
- If Len(App.HelpFile) = 0 Then
- MsgBox "Unable to display Help Contents. There is no Help associated with this project.", vbInformation, Me.Caption
- Else
- On Error Resume Next
- nRet = OSWinHelp(Me.hwnd, App.HelpFile, 3, 0)
- If Err Then
- MsgBox Err.Description
- End If
- End If
-
-End Sub
-
-
-Private Sub mnuViewWebBrowser_Click()
- 'ToDo: Add 'mnuViewWebBrowser_Click' code.
- MsgBox "Add 'mnuViewWebBrowser_Click' code."
-End Sub
-
-Private Sub mnuViewOptions_Click()
- frmOptions.Show vbModal, Me
-End Sub
-
-Private Sub mnuViewRefresh_Click()
- 'ToDo: Add 'mnuViewRefresh_Click' code.
- MsgBox "Add 'mnuViewRefresh_Click' code."
-End Sub
-
-
-Private Sub mnuViewStatusBar_Click()
- mnuViewStatusBar.Checked = Not mnuViewStatusBar.Checked
- sbStatusBar.Visible = mnuViewStatusBar.Checked
- SizeControls imgSplitter.Left
-End Sub
-
-Private Sub mnuViewToolbar_Click()
- mnuViewToolbar.Checked = Not mnuViewToolbar.Checked
- tbToolBar.Visible = mnuViewToolbar.Checked
- SizeControls imgSplitter.Left
-End Sub
-
-Private Sub mnuEditInvertSelection_Click()
- 'ToDo: Add 'mnuEditInvertSelection_Click' code.
- MsgBox "Add 'mnuEditInvertSelection_Click' code."
-End Sub
-
-Private Sub mnuEditSelectAll_Click()
- 'ToDo: Add 'mnuEditSelectAll_Click' code.
- MsgBox "Add 'mnuEditSelectAll_Click' code."
-End Sub
-
-Private Sub mnuEditPasteSpecial_Click()
- 'ToDo: Add 'mnuEditPasteSpecial_Click' code.
- MsgBox "Add 'mnuEditPasteSpecial_Click' code."
-End Sub
-
-Private Sub mnuEditPaste_Click()
- 'ToDo: Add 'mnuEditPaste_Click' code.
- MsgBox "Add 'mnuEditPaste_Click' code."
-End Sub
-
-Private Sub mnuEditCopy_Click()
- 'ToDo: Add 'mnuEditCopy_Click' code.
- MsgBox "Add 'mnuEditCopy_Click' code."
-End Sub
-
-Private Sub mnuEditCut_Click()
- 'ToDo: Add 'mnuEditCut_Click' code.
- MsgBox "Add 'mnuEditCut_Click' code."
-End Sub
-
-Private Sub mnuEditUndo_Click()
- 'ToDo: Add 'mnuEditUndo_Click' code.
- MsgBox "Add 'mnuEditUndo_Click' code."
-End Sub
-
-Private Sub mnuFileClose_Click()
- 'unload the form
- Unload Me
-
-End Sub
-
-Private Sub mnuFileProperties_Click()
- 'ToDo: Add 'mnuFileProperties_Click' code.
- MsgBox "Add 'mnuFileProperties_Click' code."
-End Sub
-
-Private Sub mnuFileRename_Click()
- 'ToDo: Add 'mnuFileRename_Click' code.
- MsgBox "Add 'mnuFileRename_Click' code."
-End Sub
-
-Private Sub mnuFileDelete_Click()
- 'ToDo: Add 'mnuFileDelete_Click' code.
- MsgBox "Add 'mnuFileDelete_Click' code."
-End Sub
-
-Private Sub mnuFileNew_Click()
- 'ToDo: Add 'mnuFileNew_Click' code.
- MsgBox "Add 'mnuFileNew_Click' code."
-End Sub
-
-Private Sub mnuFileSendTo_Click()
- 'ToDo: Add 'mnuFileSendTo_Click' code.
- MsgBox "Add 'mnuFileSendTo_Click' code."
-End Sub
-
-Private Sub mnuFileFind_Click()
- 'ToDo: Add 'mnuFileFind_Click' code.
- MsgBox "Add 'mnuFileFind_Click' code."
-End Sub
-
-Private Sub mnuFileOpen_Click()
- Dim sFile As String
-End Sub
-
-Private Sub mnuPopComputerProperties_Click()
- mnuFileProperties_Click
-End Sub
-
-Private Sub mnuPopNewDatabase_Click()
- frmNewDatabase1.Show vbModal, Me
- frmNewDatabase2.Show vbModal, Me
- frmNewDatabase3.Show vbModal, Me
-End Sub
-
-Private Sub mnuPopAddComputer_Click()
- frmNewComputer.Show vbModal, Me
- Dim c As Computer
- For Each c In frmNewComputer.m_hosts
- addComputer c
- g_computers.Add c, "_" & c.m_name
- Next
-End Sub
-
-Private Sub mnuPopSortComputers_Click()
- If m_currentNode.Sorted = True Then
- mnuPopSortComputers.Checked = False
- m_currentNode.Sorted = False
- Else
- mnuPopSortComputers.Checked = True
- m_currentNode.Sorted = True
- End If
-End Sub
-
-Private Sub mnuPopRemoveComputer_Click()
- Dim res As VbMsgBoxResult
- Dim str As String
- str = "Remove computer " & m_currentComputer.m_name
- res = MsgBox(str, vbOKCancel, str)
- If res = vbOK Then
- removeComputer (m_currentComputer.m_name)
- End If
-End Sub
-
-Private Sub mnuPopSortDatabases_Click()
- If m_currentNode.Sorted = True Then
- mnuPopSortDatabases.Checked = False
- m_currentNode.Sorted = False
- Else
- mnuPopSortDatabases.Checked = True
- m_currentNode.Sorted = True
- End If
-End Sub
-
-Private Sub tvTreeView_BeforeLabelEdit(Cancel As Integer)
- Cancel = True
-End Sub
-
-Private Sub tvTreeView_Collapse(ByVal Node As MSComctlLib.Node)
- 'MsgBox "tvTreeView_Collapse"
-End Sub
-
-Private Sub tvTreeView_Expand(ByVal Node As MSComctlLib.Node)
- 'MsgBox "tvTreeView_Expand"
-End Sub
-
-Private Sub tvTreeView_NodeClick(ByVal Node As MSComctlLib.Node)
- selectNode Node
-End Sub
-
-Private Sub tvTreeView_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
- 'MsgBox "tvTreeView_MouseUp Button: " & Button & " Shift: " & Shift
- Dim Node As MSComctlLib.Node
- Dim place As Integer
-
- Set Node = tvTreeView.HitTest(X, Y)
- place = selectNode(Node)
- If Button = vbRightButton Then
- ShowPopup place
- End If
-End Sub
-
-Private Function selectNode(ByRef n As MSComctlLib.Node) As Integer
- Dim list As ListView
- Dim place As Integer
-
- If n Is Nothing Then
- If Not m_currentNode Is Nothing Then
- place = 1
- m_currentNode.Selected = False
- Else
- place = 2
- End If
- Else
- n.Selected = True
- If n.Text = "Computers" Then
- place = 3
- Set list = lvComputers
- lblTitle(1).Caption = "Computers"
- ElseIf n.Text = "Databases" Then
- place = 4
- Set list = lvDatabases
- lblTitle(1).Caption = "Databases"
- ElseIf n.Parent.Text = "Computers" Then
- place = 5
- Set list = lvProcesses
- setComputer (n.Key)
- ElseIf n.Parent.Text = "Databases" Then
- place = 6
- Set list = lvProcesses
- setDatabase (n.Key)
- End If
-
- If m_currentList.hwnd <> list.hwnd Then
- m_currentList.Visible = False
- list.Visible = True
- Set m_currentList = list
- End If
- End If
- Set m_currentNode = n
- selectNode = place
-End Function
-
-Private Sub lvComputers_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
- Dim li As ListItem
- Set li = lvComputers.HitTest(X, Y)
- If Button = vbRightButton And Not li Is Nothing Then
- Dim c As Computer
- Set m_currentComputer = g_computers(li.Key)
- ShowPopup 5
- End If
-End Sub
-
-Private Sub ShowPopup(ByVal place As Integer)
- Select Case place
- Case 3
- PopupMenu mnuPopComputers
- Case 4
- PopupMenu mnuPopDatabases
- Case 5
- mnuPopComputerName.Caption = m_currentComputer.m_name & ": " & m_currentComputer.m_status
- Select Case m_currentComputer.m_status
- Case "Connected"
- mnuPopConnectComputer.Enabled = False
- mnuPopDisconnectComputer.Enabled = True
- Case "Connecting"
- mnuPopConnectComputer.Enabled = False
- mnuPopDisconnectComputer.Enabled = True
- Case "Not connected"
- mnuPopConnectComputer.Enabled = True
- mnuPopDisconnectComputer.Enabled = False
- Case "No contact"
- mnuPopConnectComputer.Enabled = True
- mnuPopDisconnectComputer.Enabled = False
- Case Else
- mnuPopConnectComputer.Enabled = False
- mnuPopDisconnectComputer.Enabled = False
- End Select
-
- PopupMenu mnuPopComputer, , , , mnuPopComputerName
- End Select
-End Sub
-
-Private Sub lvComputers_BeforeLabelEdit(Cancel As Integer)
- Cancel = True
-End Sub
-
-Private Sub lvProcesses_BeforeLabelEdit(Cancel As Integer)
- Cancel = True
-End Sub
-
-Private Sub lvDatabases_BeforeLabelEdit(Cancel As Integer)
- Cancel = True
-End Sub
-
-Private Sub ColumnClick(ByRef list As ListView, i As Integer)
- i = i - 1
- If list.SortKey = i Then
- list.SortOrder = 1 - list.SortOrder
- Else
- list.SortKey = i
- End If
-End Sub
-
-Private Sub lvComputers_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)
- ColumnClick lvComputers, ColumnHeader.Index
-End Sub
-
-Private Sub lvProcesses_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)
- ColumnClick lvProcesses, ColumnHeader.Index
-End Sub
-
-Private Sub lvDatabases_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)
- ColumnClick lvDatabases, ColumnHeader.Index
-End Sub
-
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/frmNewComputer.frm b/storage/ndb/src/cw/cpcc-win32/vb6/frmNewComputer.frm
deleted file mode 100644
index eae5802493c..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/frmNewComputer.frm
+++ /dev/null
@@ -1,124 +0,0 @@
-VERSION 5.00
-Begin VB.Form frmNewComputer
- Caption = "Add computer"
- ClientHeight = 1545
- ClientLeft = 60
- ClientTop = 345
- ClientWidth = 4605
- LinkTopic = "Form1"
- ScaleHeight = 1545
- ScaleWidth = 4605
- StartUpPosition = 3 'Windows Default
- Begin VB.CommandButton Command3
- Caption = "Apply"
- Default = -1 'True
- Height = 360
- Left = 3240
- TabIndex = 4
- Tag = "OK"
- Top = 840
- Width = 1140
- End
- Begin VB.CommandButton Command2
- Caption = "Cancel"
- Height = 360
- Left = 1920
- TabIndex = 3
- Tag = "OK"
- Top = 840
- Width = 1140
- End
- Begin VB.CommandButton Command1
- Caption = "OK"
- Height = 360
- Left = 600
- TabIndex = 2
- Tag = "OK"
- Top = 840
- Width = 1140
- End
- Begin VB.TextBox Text1
- Height = 285
- Left = 1440
- TabIndex = 1
- Top = 240
- Width = 2925
- End
- Begin VB.Label lblLabels
- Caption = "Computer name:"
- Height = 255
- Index = 1
- Left = 120
- TabIndex = 0
- Tag = "&User Name:"
- Top = 240
- Width = 1440
- End
-End
-Attribute VB_Name = "frmNewComputer"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = False
-Attribute VB_PredeclaredId = True
-Attribute VB_Exposed = False
-Public m_hosts As New Collection
-
-Private Sub Form_Load()
- If m_hosts.Count > 0 Then
- For i = m_hosts.Count To 1 Step -1
- m_hosts.Remove i
- Next
- End If
-End Sub
-
-Private Sub Command1_Click()
- If Text1.Text = "" Then
- MsgBox "Invalid hostname"
- Exit Sub
- End If
-
- If Exists(g_computers, "_" & Text1.Text) Then
- MsgBox Text1.Text & " already exists"
- Exit Sub
- End If
-
- Dim c As New Computer
- With c
- .m_ip = ""
- .m_name = Text1.Text
- .m_status = "Not connected"
- Set .m_processes = New Collection
- End With
-
- m_hosts.Add c
-
- Unload Me
-End Sub
-
-Private Sub Command2_Click()
- Unload Me
-End Sub
-
-Private Sub Command3_Click()
- If Text1.Text = "" Then
- MsgBox "Invalid hostname"
- Exit Sub
- End If
-
- If Exists(g_computers, "_" & Text1.Text) Then
- MsgBox Text1.Text & " already exists"
- Exit Sub
- End If
-
- Dim c As New Computer
- With c
- .m_ip = ""
- .m_name = Text1.Text
- .m_status = "Not connected"
- Set .m_processes = New Collection
- End With
-
- m_hosts.Add c
-
- Text1.Text = ""
-End Sub
-
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/frmNewComputer.frx b/storage/ndb/src/cw/cpcc-win32/vb6/frmNewComputer.frx
deleted file mode 100644
index 593f4708db8..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/frmNewComputer.frx
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase.frx b/storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase.frx
deleted file mode 100644
index b20c2b651ae..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase.frx
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase1.frm b/storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase1.frm
deleted file mode 100644
index 3fa1fd4c4e8..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase1.frm
+++ /dev/null
@@ -1,187 +0,0 @@
-VERSION 5.00
-Begin VB.Form frmNewDatabase1
- BorderStyle = 5 'Sizable ToolWindow
- Caption = "Nodes"
- ClientHeight = 3000
- ClientLeft = 2850
- ClientTop = 3450
- ClientWidth = 6240
- LinkTopic = "Form1"
- MaxButton = 0 'False
- MinButton = 0 'False
- ScaleHeight = 3281.25
- ScaleMode = 0 'User
- ScaleWidth = 6359.712
- ShowInTaskbar = 0 'False
- StartUpPosition = 2 'CenterScreen
- Begin VB.TextBox textApiNodes
- Height = 285
- Left = 2760
- TabIndex = 12
- Text = "4"
- Top = 1665
- Width = 375
- End
- Begin VB.VScrollBar VScroll1
- Height = 255
- Left = 3240
- TabIndex = 11
- Top = 1680
- Width = 135
- End
- Begin VB.OptionButton Option4
- Alignment = 1 'Right Justify
- Caption = "1"
- Height = 375
- Left = 2760
- TabIndex = 10
- Top = 1020
- Width = 375
- End
- Begin VB.OptionButton Option3
- Alignment = 1 'Right Justify
- Caption = "4"
- Height = 375
- Left = 3960
- TabIndex = 9
- Top = 360
- Width = 375
- End
- Begin VB.OptionButton Option2
- Alignment = 1 'Right Justify
- Caption = "2"
- Height = 375
- Left = 3360
- TabIndex = 8
- Top = 360
- Width = 375
- End
- Begin VB.OptionButton Option1
- Alignment = 1 'Right Justify
- Caption = "1"
- Height = 375
- Left = 2760
- TabIndex = 7
- Top = 360
- Value = -1 'True
- Width = 375
- End
- Begin VB.CommandButton cmdCancel
- Cancel = -1 'True
- Caption = "Cancel"
- Height = 305
- Left = 1320
- TabIndex = 3
- Top = 2400
- Width = 1140
- End
- Begin VB.CommandButton cmdFinish
- Caption = "Finish"
- Enabled = 0 'False
- Height = 305
- Left = 5040
- TabIndex = 2
- Top = 2400
- Width = 1140
- End
- Begin VB.CommandButton cmdBack
- Caption = "Back"
- Default = -1 'True
- Enabled = 0 'False
- Height = 305
- Left = 2640
- TabIndex = 0
- Top = 2400
- Width = 1140
- End
- Begin VB.CommandButton cmdNext
- Caption = "Next"
- Height = 305
- Left = 3720
- TabIndex = 1
- Top = 2400
- Width = 1140
- End
- Begin VB.Label Label3
- Caption = "No of api nodes"
- Height = 255
- Left = 240
- TabIndex = 6
- Top = 1680
- Width = 2415
- End
- Begin VB.Label Label2
- Caption = "No of management nodes"
- Height = 255
- Left = 240
- TabIndex = 5
- Top = 1080
- Width = 2415
- End
- Begin VB.Label Label1
- Caption = "No of database nodes"
- Height = 255
- Left = 240
- TabIndex = 4
- Top = 420
- Width = 2415
- End
- Begin VB.Line Line1
- BorderColor = &H80000003&
- X1 = 122.302
- X2 = 6237.41
- Y1 = 2493.75
- Y2 = 2493.75
- End
-End
-Attribute VB_Name = "frmNewDatabase1"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = False
-Attribute VB_PredeclaredId = True
-Attribute VB_Exposed = False
-Option Explicit
-
-Private Sub Form_Resize()
- If Me.Width < 6375 Then Me.Width = 6375
- cmdCancel.Left = Me.ScaleWidth - 5136 + 400
- cmdBack.Left = Me.ScaleWidth - 3897 + 400
- cmdNext.Left = Me.ScaleWidth - 2883 + 400
- cmdFinish.Left = Me.ScaleWidth - 1643 + 400
- Line1.X2 = Me.ScaleWidth - 480 + 400
-
- cmdCancel.Top = Me.ScaleHeight - 375
- cmdBack.Top = Me.ScaleHeight - 375
- cmdNext.Top = Me.ScaleHeight - 375
- cmdFinish.Top = Me.ScaleHeight - 375
- Line1.Y1 = Me.ScaleHeight - 475
- Line1.Y2 = Me.ScaleHeight - 475
-End Sub
-
-Private Sub cmdCancel_Click()
- 'set the global var to false
- 'to denote a failed login
- Unload Me
-End Sub
-
-Private Sub Option1_Click()
- Option2.Value = False
- Option3.Value = False
-End Sub
-
-Private Sub Option2_Click()
- Option1.Value = False
- Option3.Value = False
-End Sub
-
-Private Sub Option3_Click()
- Option1.Value = False
- Option2.Value = False
-End Sub
-
-Private Sub Option4_Click()
- Option4.Value = True
-End Sub
-
-Private Sub textApiNodes_Validate(Cancel As Boolean)
- 'If Not isnumber(textApiNodes.Text) Then Cancel = False
-End Sub
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase2.frm b/storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase2.frm
deleted file mode 100644
index 49806a695ea..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase2.frm
+++ /dev/null
@@ -1,136 +0,0 @@
-VERSION 5.00
-Begin VB.Form frmNewDatabase2
- BorderStyle = 5 'Sizable ToolWindow
- Caption = "Computers"
- ClientHeight = 2895
- ClientLeft = 2850
- ClientTop = 3450
- ClientWidth = 6240
- LinkTopic = "Form1"
- MaxButton = 0 'False
- MinButton = 0 'False
- ScaleHeight = 3166.406
- ScaleMode = 0 'User
- ScaleWidth = 6359.712
- ShowInTaskbar = 0 'False
- StartUpPosition = 2 'CenterScreen
- Begin VB.ComboBox Combo1
- Height = 315
- Left = 2400
- TabIndex = 7
- Text = "Combo1"
- Top = 360
- Width = 1455
- End
- Begin VB.VScrollBar VScroll2
- Height = 255
- Left = 4560
- TabIndex = 6
- Top = 375
- Width = 135
- End
- Begin VB.TextBox Text1
- Height = 285
- Left = 4080
- TabIndex = 5
- Text = "4"
- Top = 360
- Width = 375
- End
- Begin VB.CommandButton cmdCancel
- Cancel = -1 'True
- Caption = "Cancel"
- Height = 305
- Left = 1320
- TabIndex = 3
- Top = 2400
- Width = 1140
- End
- Begin VB.CommandButton cmdFinish
- Caption = "Finish"
- Enabled = 0 'False
- Height = 305
- Left = 5040
- TabIndex = 2
- Top = 2400
- Width = 1140
- End
- Begin VB.CommandButton cmdBack
- Caption = "Back"
- Default = -1 'True
- Enabled = 0 'False
- Height = 305
- Left = 2640
- TabIndex = 0
- Top = 2400
- Width = 1140
- End
- Begin VB.CommandButton cmdNext
- Caption = "Next"
- Height = 305
- Left = 3720
- TabIndex = 1
- Top = 2400
- Width = 1140
- End
- Begin VB.Label Label5
- Caption = "Computer"
- Height = 255
- Left = 2400
- TabIndex = 9
- Top = 0
- Width = 975
- End
- Begin VB.Label Label4
- Caption = "Node id"
- Height = 255
- Left = 4080
- TabIndex = 8
- Top = 120
- Width = 615
- End
- Begin VB.Label Label1
- Caption = "Database node 1"
- Height = 255
- Left = 240
- TabIndex = 4
- Top = 420
- Width = 2415
- End
- Begin VB.Line Line1
- BorderColor = &H80000003&
- X1 = 122.302
- X2 = 6237.41
- Y1 = 2493.75
- Y2 = 2493.75
- End
-End
-Attribute VB_Name = "frmNewDatabase2"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = False
-Attribute VB_PredeclaredId = True
-Attribute VB_Exposed = False
-Option Explicit
-
-Private Sub Form_Resize()
- If Me.Width < 6375 Then Me.Width = 6375
- cmdCancel.Left = Me.ScaleWidth - 5136 + 400
- cmdBack.Left = Me.ScaleWidth - 3897 + 400
- cmdNext.Left = Me.ScaleWidth - 2883 + 400
- cmdFinish.Left = Me.ScaleWidth - 1643 + 400
- Line1.X2 = Me.ScaleWidth - 480 + 400
-
- cmdCancel.Top = Me.ScaleHeight - 375
- cmdBack.Top = Me.ScaleHeight - 375
- cmdNext.Top = Me.ScaleHeight - 375
- cmdFinish.Top = Me.ScaleHeight - 375
- Line1.Y1 = Me.ScaleHeight - 475
- Line1.Y2 = Me.ScaleHeight - 475
-End Sub
-
-Private Sub cmdCancel_Click()
- 'set the global var to false
- 'to denote a failed login
- Unload Me
-End Sub
-
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase2.log b/storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase2.log
deleted file mode 100644
index 808b21866e5..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase2.log
+++ /dev/null
@@ -1 +0,0 @@
-Line 2: The Form or MDIForm name frmNewDatabase1 is already in use; cannot load this form.
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase3.frm b/storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase3.frm
deleted file mode 100644
index ba050a58a09..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/frmNewDatabase3.frm
+++ /dev/null
@@ -1,88 +0,0 @@
-VERSION 5.00
-Begin VB.Form frmNewDatabase3
- BorderStyle = 5 'Sizable ToolWindow
- Caption = "Database configuration"
- ClientHeight = 3000
- ClientLeft = 2850
- ClientTop = 3450
- ClientWidth = 6240
- LinkTopic = "Form1"
- MaxButton = 0 'False
- MinButton = 0 'False
- ScaleHeight = 3281.25
- ScaleMode = 0 'User
- ScaleWidth = 6359.712
- ShowInTaskbar = 0 'False
- StartUpPosition = 2 'CenterScreen
- Begin VB.CommandButton cmdCancel
- Cancel = -1 'True
- Caption = "Cancel"
- Height = 305
- Left = 1320
- TabIndex = 3
- Top = 2400
- Width = 1140
- End
- Begin VB.CommandButton cmdFinish
- Caption = "Finish"
- Enabled = 0 'False
- Height = 305
- Left = 5040
- TabIndex = 2
- Top = 2400
- Width = 1140
- End
- Begin VB.CommandButton cmdBack
- Caption = "Back"
- Default = -1 'True
- Enabled = 0 'False
- Height = 305
- Left = 2640
- TabIndex = 0
- Top = 2400
- Width = 1140
- End
- Begin VB.CommandButton cmdNext
- Caption = "Next"
- Height = 305
- Left = 3720
- TabIndex = 1
- Top = 2400
- Width = 1140
- End
- Begin VB.Line Line1
- BorderColor = &H80000003&
- X1 = 122.302
- X2 = 6237.41
- Y1 = 2493.75
- Y2 = 2493.75
- End
-End
-Attribute VB_Name = "frmNewDatabase3"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = False
-Attribute VB_PredeclaredId = True
-Attribute VB_Exposed = False
-Option Explicit
-
-Private Sub Form_Resize()
- If Me.Width < 6375 Then Me.Width = 6375
- cmdCancel.Left = Me.ScaleWidth - 5136 + 400
- cmdBack.Left = Me.ScaleWidth - 3897 + 400
- cmdNext.Left = Me.ScaleWidth - 2883 + 400
- cmdFinish.Left = Me.ScaleWidth - 1643 + 400
- Line1.X2 = Me.ScaleWidth - 480 + 400
-
- cmdCancel.Top = Me.ScaleHeight - 375
- cmdBack.Top = Me.ScaleHeight - 375
- cmdNext.Top = Me.ScaleHeight - 375
- cmdFinish.Top = Me.ScaleHeight - 375
- Line1.Y1 = Me.ScaleHeight - 475
- Line1.Y2 = Me.ScaleHeight - 475
-End Sub
-
-Private Sub cmdCancel_Click()
- 'set the global var to false
- 'to denote a failed login
- Unload Me
-End Sub
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/frmOptions.frm b/storage/ndb/src/cw/cpcc-win32/vb6/frmOptions.frm
deleted file mode 100644
index e526a35b3ec..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/frmOptions.frm
+++ /dev/null
@@ -1,231 +0,0 @@
-VERSION 5.00
-Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0"; "mscomctl.ocx"
-Begin VB.Form frmOptions
- BorderStyle = 3 'Fixed Dialog
- Caption = "Options"
- ClientHeight = 5040
- ClientLeft = 6600
- ClientTop = 4575
- ClientWidth = 6150
- KeyPreview = -1 'True
- LinkTopic = "Form1"
- MaxButton = 0 'False
- MinButton = 0 'False
- ScaleHeight = 5040
- ScaleWidth = 6150
- ShowInTaskbar = 0 'False
- Tag = "Options"
- Begin VB.CommandButton cmdOK
- Caption = "OK"
- Height = 375
- Left = 2490
- TabIndex = 1
- Tag = "OK"
- Top = 4455
- Width = 1095
- End
- Begin VB.CommandButton cmdCancel
- Cancel = -1 'True
- Caption = "Cancel"
- Height = 375
- Left = 3720
- TabIndex = 3
- Tag = "Cancel"
- Top = 4455
- Width = 1095
- End
- Begin VB.CommandButton cmdApply
- Caption = "&Apply"
- Height = 375
- Left = 4920
- TabIndex = 5
- Tag = "&Apply"
- Top = 4455
- Width = 1095
- End
- Begin VB.PictureBox picOptions
- BorderStyle = 0 'None
- Height = 3780
- Index = 3
- Left = -20000
- ScaleHeight = 3840.968
- ScaleMode = 0 'User
- ScaleWidth = 5745.64
- TabIndex = 7
- TabStop = 0 'False
- Top = 480
- Width = 5685
- Begin VB.Frame fraSample4
- Caption = "Sample 4"
- Height = 2022
- Left = 505
- TabIndex = 11
- Tag = "Sample 4"
- Top = 502
- Width = 2033
- End
- End
- Begin VB.PictureBox picOptions
- BorderStyle = 0 'None
- Height = 3780
- Index = 2
- Left = -20000
- ScaleHeight = 3840.968
- ScaleMode = 0 'User
- ScaleWidth = 5745.64
- TabIndex = 9
- TabStop = 0 'False
- Top = 480
- Width = 5685
- Begin VB.Frame fraSample3
- Caption = "Sample 3"
- Height = 2022
- Left = 406
- TabIndex = 10
- Tag = "Sample 3"
- Top = 403
- Width = 2033
- End
- End
- Begin VB.PictureBox picOptions
- BorderStyle = 0 'None
- Height = 3780
- Index = 1
- Left = -20000
- ScaleHeight = 3840.968
- ScaleMode = 0 'User
- ScaleWidth = 5745.64
- TabIndex = 6
- TabStop = 0 'False
- Top = 480
- Width = 5685
- Begin VB.Frame fraSample2
- Caption = "Sample 2"
- Height = 2022
- Left = 307
- TabIndex = 8
- Tag = "Sample 2"
- Top = 305
- Width = 2033
- End
- End
- Begin VB.PictureBox picOptions
- BorderStyle = 0 'None
- Height = 3780
- Index = 0
- Left = 210
- ScaleHeight = 3840.968
- ScaleMode = 0 'User
- ScaleWidth = 5745.64
- TabIndex = 2
- TabStop = 0 'False
- Top = 480
- Width = 5685
- Begin VB.Frame fraSample1
- Caption = "Sample 1"
- Height = 2022
- Left = 208
- TabIndex = 4
- Tag = "Sample 1"
- Top = 207
- Width = 2033
- End
- End
- Begin MSComctlLib.TabStrip tbsOptions
- Height = 4245
- Left = 105
- TabIndex = 0
- Top = 120
- Width = 5895
- _ExtentX = 10398
- _ExtentY = 7488
- _Version = 393216
- BeginProperty Tabs {1EFB6598-857C-11D1-B16A-00C0F0283628}
- NumTabs = 4
- BeginProperty Tab1 {1EFB659A-857C-11D1-B16A-00C0F0283628}
- Caption = "Group 1"
- ImageVarType = 2
- EndProperty
- BeginProperty Tab2 {1EFB659A-857C-11D1-B16A-00C0F0283628}
- Caption = "Group 2"
- ImageVarType = 2
- EndProperty
- BeginProperty Tab3 {1EFB659A-857C-11D1-B16A-00C0F0283628}
- Caption = "Group 3"
- ImageVarType = 2
- EndProperty
- BeginProperty Tab4 {1EFB659A-857C-11D1-B16A-00C0F0283628}
- Caption = "Group 4"
- ImageVarType = 2
- EndProperty
- EndProperty
- End
-End
-Attribute VB_Name = "frmOptions"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = False
-Attribute VB_PredeclaredId = True
-Attribute VB_Exposed = False
-Private Sub cmdApply_Click()
- 'ToDo: Add 'cmdApply_Click' code.
- MsgBox "Apply Code goes here to set options w/o closing dialog!"
-End Sub
-
-
-Private Sub cmdCancel_Click()
- Unload Me
-End Sub
-
-
-Private Sub cmdOK_Click()
- 'ToDo: Add 'cmdOK_Click' code.
- MsgBox "Code goes here to set options and close dialog!"
- Unload Me
-End Sub
-
-
-Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
- Dim i As Integer
- i = tbsOptions.SelectedItem.Index
- 'handle ctrl+tab to move to the next tab
- If (Shift And 3) = 2 And KeyCode = vbKeyTab Then
- If i = tbsOptions.Tabs.Count Then
- 'last tab so we need to wrap to tab 1
- Set tbsOptions.SelectedItem = tbsOptions.Tabs(1)
- Else
- 'increment the tab
- Set tbsOptions.SelectedItem = tbsOptions.Tabs(i + 1)
- End If
- ElseIf (Shift And 3) = 3 And KeyCode = vbKeyTab Then
- If i = 1 Then
- 'last tab so we need to wrap to tab 1
- Set tbsOptions.SelectedItem = tbsOptions.Tabs(tbsOptions.Tabs.Count)
- Else
- 'increment the tab
- Set tbsOptions.SelectedItem = tbsOptions.Tabs(i - 1)
- End If
- End If
-End Sub
-
-
-
-
-Private Sub tbsOptions_Click()
-
-
- Dim i As Integer
- 'show and enable the selected tab's controls
- 'and hide and disable all others
- For i = 0 To tbsOptions.Tabs.Count - 1
- If i = tbsOptions.SelectedItem.Index - 1 Then
- picOptions(i).Left = 210
- picOptions(i).Enabled = True
- Else
- picOptions(i).Left = -20000
- picOptions(i).Enabled = False
- End If
- Next
-
-
-End Sub
-
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/frmSplash.frx b/storage/ndb/src/cw/cpcc-win32/vb6/frmSplash.frx
deleted file mode 100644
index fee0c5c59de..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/frmSplash.frx
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/networking.ico b/storage/ndb/src/cw/cpcc-win32/vb6/networking.ico
deleted file mode 100644
index 6bbf8022fc6..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/networking.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/cw/cpcc-win32/vb6/open folder.ico b/storage/ndb/src/cw/cpcc-win32/vb6/open folder.ico
deleted file mode 100644
index 7bb32cc83d3..00000000000
--- a/storage/ndb/src/cw/cpcc-win32/vb6/open folder.ico
+++ /dev/null
Binary files differ
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
index 8c096681b58..e25c15d50a0 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
@@ -2253,7 +2253,7 @@ int Dbtup::interpreterNextLab(Signal* signal,
if(AttributeOffset::getCharsetFlag(TattrDesc2))
{
Uint32 pos = AttributeOffset::getCharsetPos(TattrDesc2);
- cs = tabptr.p->charsetArray[pos];
+ cs = (void*) tabptr.p->charsetArray[pos];
}
const NdbSqlUtil::Type& sqlType = NdbSqlUtil::getType(typeId);
diff --git a/storage/ndb/src/libndb.ver.in b/storage/ndb/src/libndb.ver.in
index 72bf93d196f..c7b97876d44 100644
--- a/storage/ndb/src/libndb.ver.in
+++ b/storage/ndb/src/libndb.ver.in
@@ -1,2 +1,17 @@
+# Copyright (C) 2007 MySQL AB
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
libndbclient_@NDB_SHARED_LIB_MAJOR_VERSION@ { global: *; };
diff --git a/storage/ndb/test/ndbapi/slow_select.cpp b/storage/ndb/test/ndbapi/slow_select.cpp
index 8d615fa5771..21e3ce7400c 100644
--- a/storage/ndb/test/ndbapi/slow_select.cpp
+++ b/storage/ndb/test/ndbapi/slow_select.cpp
@@ -1,3 +1,17 @@
+/* Copyright (C) 2004, 2005 MySQL AB
+
+ 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 */
#include <ndb_global.h>
#include <NdbApi.hpp>
diff --git a/storage/ndb/test/ndbapi/testBitfield.cpp b/storage/ndb/test/ndbapi/testBitfield.cpp
index 41bb7b4622c..27ee870705f 100644
--- a/storage/ndb/test/ndbapi/testBitfield.cpp
+++ b/storage/ndb/test/ndbapi/testBitfield.cpp
@@ -1,3 +1,17 @@
+/* Copyright (C) 2004, 2008 MySQL AB
+
+ 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 */
#include <ndb_global.h>
#include <ndb_opts.h>
diff --git a/storage/ndb/test/ndbapi/testLcp.cpp b/storage/ndb/test/ndbapi/testLcp.cpp
index 69789b0191f..d8bf1611dfb 100644
--- a/storage/ndb/test/ndbapi/testLcp.cpp
+++ b/storage/ndb/test/ndbapi/testLcp.cpp
@@ -1,3 +1,17 @@
+/* Copyright (C) 2004, 2005 MySQL AB
+
+ 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 */
#include <NDBT.hpp>
#include <NdbApi.hpp>
diff --git a/storage/ndb/test/ndbnet/test.run b/storage/ndb/test/ndbnet/test.run
index 30042488c92..195a657aeb5 100644
--- a/storage/ndb/test/ndbnet/test.run
+++ b/storage/ndb/test/ndbnet/test.run
@@ -1,3 +1,18 @@
+# Copyright (C) 2004 MySQL AB
#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
system("printenv|sort");
diff --git a/storage/ndb/test/ndbnet/testError.run b/storage/ndb/test/ndbnet/testError.run
index 3cce489a3da..6ace2cbbd20 100644
--- a/storage/ndb/test/ndbnet/testError.run
+++ b/storage/ndb/test/ndbnet/testError.run
@@ -1,3 +1,20 @@
+# Copyright (C) 2004 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
#
# file : test/ndbnet/testError.run
# usage: perl testError.run
diff --git a/storage/ndb/test/ndbnet/testMNF.run b/storage/ndb/test/ndbnet/testMNF.run
index df226cd3359..2903313f306 100644
--- a/storage/ndb/test/ndbnet/testMNF.run
+++ b/storage/ndb/test/ndbnet/testMNF.run
@@ -1,3 +1,20 @@
+# Copyright (C) 2004 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
#
# file : test/ndbnet/testError.run
# usage: perl testError.run
diff --git a/storage/ndb/test/ndbnet/testNR.run b/storage/ndb/test/ndbnet/testNR.run
index 01a3d76266d..5019f597b42 100644
--- a/storage/ndb/test/ndbnet/testNR.run
+++ b/storage/ndb/test/ndbnet/testNR.run
@@ -1,4 +1,19 @@
+# Copyright (C) 2004 MySQL AB
#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
use strict;
use NDB::Run;
diff --git a/storage/ndb/test/ndbnet/testNR1.run b/storage/ndb/test/ndbnet/testNR1.run
index 8819a92c8ca..a02b487b663 100644
--- a/storage/ndb/test/ndbnet/testNR1.run
+++ b/storage/ndb/test/ndbnet/testNR1.run
@@ -1,3 +1,20 @@
+# Copyright (C) 2004 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
# Node recovery killing 1 node out of 4 at the time and waiting for recover
use strict;
diff --git a/storage/ndb/test/ndbnet/testNR4.run b/storage/ndb/test/ndbnet/testNR4.run
index f7a5eef3494..378d2743145 100644
--- a/storage/ndb/test/ndbnet/testNR4.run
+++ b/storage/ndb/test/ndbnet/testNR4.run
@@ -1,3 +1,20 @@
+# Copyright (C) 2004 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
# Node recovery killing 1 node out of 4 at the time and waiting for recover
use strict;
diff --git a/storage/ndb/test/ndbnet/testSRhang.run b/storage/ndb/test/ndbnet/testSRhang.run
index 8cb65a75ded..570ed897eef 100644
--- a/storage/ndb/test/ndbnet/testSRhang.run
+++ b/storage/ndb/test/ndbnet/testSRhang.run
@@ -1,4 +1,19 @@
+# Copyright (C) 2004 MySQL AB
#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
use strict;
use NDB::Run;
diff --git a/storage/ndb/test/ndbnet/testTR295.run b/storage/ndb/test/ndbnet/testTR295.run
index ce4250b60ae..df26000cbda 100644
--- a/storage/ndb/test/ndbnet/testTR295.run
+++ b/storage/ndb/test/ndbnet/testTR295.run
@@ -1,3 +1,20 @@
+# Copyright (C) 2004 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
# testing TR295, kill non-master when recovering in phase 4
use strict;
diff --git a/storage/ndb/test/run-test/16node-tests.txt b/storage/ndb/test/run-test/16node-tests.txt
index 11ade56c28c..21dd67c9b4b 100644
--- a/storage/ndb/test/run-test/16node-tests.txt
+++ b/storage/ndb/test/run-test/16node-tests.txt
@@ -1,3 +1,18 @@
+# Copyright (C) 2005 MySQL AB
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
# BASIC FUNCTIONALITY
max-time: 500
cmd: testBasic
diff --git a/storage/ndb/test/run-test/atrt-analyze-result.sh b/storage/ndb/test/run-test/atrt-analyze-result.sh
index 0fa46e918ef..9a482faee86 100755
--- a/storage/ndb/test/run-test/atrt-analyze-result.sh
+++ b/storage/ndb/test/run-test/atrt-analyze-result.sh
@@ -1,5 +1,22 @@
#!/bin/sh
+# Copyright (C) 2004 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
f=`find result -name 'log.out' | xargs grep "NDBT_ProgramExit: " | grep -c "Failed"`
o=`find result -name 'log.out' | xargs grep "NDBT_ProgramExit: " | grep -c "OK"`
diff --git a/storage/ndb/test/run-test/atrt-clear-result.sh b/storage/ndb/test/run-test/atrt-clear-result.sh
index 57d3d43d247..7eeb54daef3 100755
--- a/storage/ndb/test/run-test/atrt-clear-result.sh
+++ b/storage/ndb/test/run-test/atrt-clear-result.sh
@@ -1,4 +1,21 @@
#!/bin/sh
+# Copyright (C) 2004 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
set -e
rm -rf result
diff --git a/storage/ndb/test/run-test/atrt-gather-result.sh b/storage/ndb/test/run-test/atrt-gather-result.sh
index f2473578b41..36989d04c07 100755
--- a/storage/ndb/test/run-test/atrt-gather-result.sh
+++ b/storage/ndb/test/run-test/atrt-gather-result.sh
@@ -1,5 +1,22 @@
#!/bin/sh
+# Copyright (C) 2004 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
set -e
mkdir -p result
diff --git a/storage/ndb/test/run-test/atrt-mysql-test-run b/storage/ndb/test/run-test/atrt-mysql-test-run
index 2ebc11b0070..55afc45bef9 100755
--- a/storage/ndb/test/run-test/atrt-mysql-test-run
+++ b/storage/ndb/test/run-test/atrt-mysql-test-run
@@ -1,5 +1,22 @@
#!/bin/sh
+# Copyright (C) 2004, 2005 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
set -x
p=`pwd`
cd $MYSQL_BASE_DIR/mysql-test
diff --git a/storage/ndb/test/run-test/atrt-setup.sh b/storage/ndb/test/run-test/atrt-setup.sh
index aff5d4119dc..786b1d812de 100755
--- a/storage/ndb/test/run-test/atrt-setup.sh
+++ b/storage/ndb/test/run-test/atrt-setup.sh
@@ -1,5 +1,22 @@
#!/bin/sh
+# Copyright (C) 2004 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
set -e
ssh $1 mkdir -p $3
diff --git a/storage/ndb/test/run-test/atrt-testBackup b/storage/ndb/test/run-test/atrt-testBackup
index 3ed7641a42e..2ed6f70b7aa 100755
--- a/storage/ndb/test/run-test/atrt-testBackup
+++ b/storage/ndb/test/run-test/atrt-testBackup
@@ -1,5 +1,22 @@
#!/bin/sh
+# Copyright (C) 2004 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
PATH=$PATH:$MYSQL_BASE_DIR/bin
export PATH
diff --git a/storage/ndb/test/run-test/basic.txt b/storage/ndb/test/run-test/basic.txt
index ec9e21359e5..69555b8c587 100644
--- a/storage/ndb/test/run-test/basic.txt
+++ b/storage/ndb/test/run-test/basic.txt
@@ -1,3 +1,18 @@
+# Copyright (C) 2004, 2005 MySQL AB
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
# BASIC FUNCTIONALITY
max-time: 500
cmd: testBasic
diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt
index 70c395fab17..84c1111bd78 100644
--- a/storage/ndb/test/run-test/daily-basic-tests.txt
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt
@@ -1,3 +1,18 @@
+# Copyright (C) 2004-2008 MySQL AB
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
max-time: 600
cmd: atrt-testBackup
args: -n NFMaster T1
diff --git a/storage/ndb/test/run-test/daily-devel-tests.txt b/storage/ndb/test/run-test/daily-devel-tests.txt
index f73bd021440..dc17e31de6a 100644
--- a/storage/ndb/test/run-test/daily-devel-tests.txt
+++ b/storage/ndb/test/run-test/daily-devel-tests.txt
@@ -1,3 +1,18 @@
+# Copyright (C) 2004, 2005 MySQL AB
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
#
# INDEX
#
diff --git a/storage/ndb/test/run-test/make-config.sh b/storage/ndb/test/run-test/make-config.sh
index a5ea2e58ae6..3ce780f9551 100755
--- a/storage/ndb/test/run-test/make-config.sh
+++ b/storage/ndb/test/run-test/make-config.sh
@@ -1,5 +1,22 @@
#!/bin/sh
+# Copyright (C) 2004, 2005 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
baseport=""
basedir=""
proc_no=1
diff --git a/storage/ndb/test/run-test/make-html-reports.sh b/storage/ndb/test/run-test/make-html-reports.sh
index 67395ceba47..dc6d1225dbe 100755
--- a/storage/ndb/test/run-test/make-html-reports.sh
+++ b/storage/ndb/test/run-test/make-html-reports.sh
@@ -1,5 +1,22 @@
#!/bin/sh
+# Copyright (C) 2004, 2005 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
src_dir=$1
run=$2
date=$3
diff --git a/storage/ndb/test/run-test/make-index.sh b/storage/ndb/test/run-test/make-index.sh
index 944f0df790b..f13ac098567 100755
--- a/storage/ndb/test/run-test/make-index.sh
+++ b/storage/ndb/test/run-test/make-index.sh
@@ -1,4 +1,22 @@
#!/bin/sh
+
+# Copyright (C) 2004 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
# NAME
# make-index.sh
#
diff --git a/storage/ndb/test/run-test/ndb-autotest.sh b/storage/ndb/test/run-test/ndb-autotest.sh
index 289f1045b21..a144c7a0329 100755
--- a/storage/ndb/test/run-test/ndb-autotest.sh
+++ b/storage/ndb/test/run-test/ndb-autotest.sh
@@ -1,4 +1,22 @@
#!/bin/sh
+
+# Copyright (C) 2005, 2006 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
#############################################################
# This script created by Jonas does the following #
# Cleans up clones and pevious builds, pulls new clones, #
diff --git a/storage/ndb/test/sql/test_create_drop.pl b/storage/ndb/test/sql/test_create_drop.pl
index 7f62898b3d1..eb9d5e31dc8 100644
--- a/storage/ndb/test/sql/test_create_drop.pl
+++ b/storage/ndb/test/sql/test_create_drop.pl
@@ -1,3 +1,20 @@
+# Copyright (C) 2005 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
use strict;
use IO::Socket;
use DBI;
diff --git a/storage/ndb/test/sql/test_range_bounds.pl b/storage/ndb/test/sql/test_range_bounds.pl
index abe1ea28298..964847044de 100644
--- a/storage/ndb/test/sql/test_range_bounds.pl
+++ b/storage/ndb/test/sql/test_range_bounds.pl
@@ -1,3 +1,20 @@
+# Copyright (C) 2005 MySQL AB
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
#
# test range scan bounds
# give option --all to test all cases
diff --git a/storage/ndb/tools/clean-links.sh b/storage/ndb/tools/clean-links.sh
index 01820f30616..84052a619d0 100755
--- a/storage/ndb/tools/clean-links.sh
+++ b/storage/ndb/tools/clean-links.sh
@@ -1,5 +1,20 @@
#! /bin/sh
+# Copyright (C) 2004 MySQL AB
+#
+# 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
+
# 1 - Dir
# 2 - Link dst
diff --git a/storage/ndb/tools/make-errors.pl b/storage/ndb/tools/make-errors.pl
index 65819209a89..ac9c7d1d58a 100644
--- a/storage/ndb/tools/make-errors.pl
+++ b/storage/ndb/tools/make-errors.pl
@@ -1,5 +1,20 @@
#! /usr/local/bin/perl
+# Copyright (C) 2004 MySQL AB
+#
+# 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
+
use strict;
use Getopt::Long;
use XML::Parser;
diff --git a/storage/ndb/tools/make-links.sh b/storage/ndb/tools/make-links.sh
index e0c4f55986e..6008406ad6a 100755
--- a/storage/ndb/tools/make-links.sh
+++ b/storage/ndb/tools/make-links.sh
@@ -1,5 +1,20 @@
#! /bin/sh
+# Copyright (C) 2004 MySQL AB
+#
+# 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
+
# 1 - Link top src
# 2 - Link dst
diff --git a/storage/ndb/tools/ndb_error_reporter b/storage/ndb/tools/ndb_error_reporter
index 7ad7a2f478a..1af3bf83469 100644
--- a/storage/ndb/tools/ndb_error_reporter
+++ b/storage/ndb/tools/ndb_error_reporter
@@ -1,5 +1,20 @@
#!/usr/bin/perl -w
+# Copyright (C) 2005 MySQL AB
+#
+# 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
+
use strict;
if(@ARGV < 1)
diff --git a/storage/ndb/tools/rgrep b/storage/ndb/tools/rgrep
index 212b068639d..b1ed4fb6f5e 100755
--- a/storage/ndb/tools/rgrep
+++ b/storage/ndb/tools/rgrep
@@ -1,5 +1,20 @@
#!/vobs/wds/swt/bin/perl
+# Copyright (C) 2004 MySQL AB
+#
+# 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
+
die "Usage: rgrep [-iredblLn] regexp filepat ...\n rgrep -h for help\n"
if $#ARGV < $[;
diff --git a/storage/pbxt/src/lock_xt.cc b/storage/pbxt/src/lock_xt.cc
index 7ae7645ddc6..946adfecccc 100644
--- a/storage/pbxt/src/lock_xt.cc
+++ b/storage/pbxt/src/lock_xt.cc
@@ -2058,12 +2058,12 @@ static void lck_free_thread_data(XTThreadPtr XT_UNUSED(self), void *XT_UNUSED(da
static void lck_do_job(XTThreadPtr self, int job, XSLockTestPtr data, xtBool reader)
{
- char b1[2048], b2[2048];
+ char b1[1024], b2[1024];
switch (job) {
case JOB_MEMCPY:
- b2[0]=0;
- memcpy(b1, b2, 2048);
+ memset(b1, 0, sizeof(b1));
+ memset(b2, 1, sizeof(b2));
data->xs_inc++;
break;
case JOB_SLEEP:
diff --git a/storage/pbxt/src/table_xt.cc b/storage/pbxt/src/table_xt.cc
index 8441c5a687e..35b4ea3be3d 100644
--- a/storage/pbxt/src/table_xt.cc
+++ b/storage/pbxt/src/table_xt.cc
@@ -1755,6 +1755,8 @@ xtPublic void xt_drop_table(XTThreadPtr self, XTPathStrPtr tab_name, xtBool drop
tab_close_mapped_files(self, tab);
tab_delete_table_files(self, tab_name, tab_id);
+ /* Remove table from "repair-pending" */
+ xt_tab_table_repaired(tab);
ASSERT(xt_get_self() == self);
if ((te_ptr = (XTTableEntryPtr) xt_sl_find(self, db->db_table_by_id, &tab_id))) {
diff --git a/storage/xtradb/ChangeLog b/storage/xtradb/ChangeLog
index 0cd8ac8a7e6..bf003b810d2 100644
--- a/storage/xtradb/ChangeLog
+++ b/storage/xtradb/ChangeLog
@@ -1,13 +1,96 @@
+2011-01-06 The InnoDB Team
+ * row/row0merge.c:
+ Fix Bug#59312 Examine MAX_FULL_NAME_LEN in InnoDB to address
+ possible insufficient name buffer
+
+2011-01-06 The InnoDB Team
+ * dict/dict0dict.c, handler/ha_innodb.cc, handler/i_s.cc,
+ include/univ.i:
+ Fix Bug#58643 InnoDB: too long table name
+
+2011-01-06 The InnoDB Team
+ * handler/i_s.cc, include/trx0i_s.h, trx/trx0i_s.c:
+ Fix Bug#55397 cannot select from innodb_trx when trx_query contains
+ blobs that aren't strings
+
+2011-01-04 The InnoDB Team
+ * dict/dict0dict.c:
+ Fix Bug#59197 double quote in field comment prevents foreign
+ key constraint creation
+
+2010-12-21 The InnoDB Team
+ * include/btr0cur.h, include/row0upd.h, btr/btr0cur.c,
+ row/row0umod.c, row/row0upd.c:
+ Fix Bug#55284 Double free of off-page columns due to lock wait
+ while updating PRIMARY KEY
+
+2010-12-21 The InnoDB Team
+
+ * include/data0data.h, include/data0data.ic, include/row0upd.h,
+ btr/btr0cur.c, row/row0purge.c, row/row0umod.c, row/row0upd.c,
+ innodb.result, innodb.test:
+ Fix Bug#58912 InnoDB unnecessarily avoids update-in-place
+ on column prefix indexes
+
+2010-12-09 The InnoDB Team
+
+ * buf/buf0lru.c:
+ Fix Bug#57600 output of I/O sum[%lu] can go negative
+
+2010-11-11 The InnoDB Team
+
+ * thr/thr0loc.c, trx/trx0i_s.c:
+ Fix Bug#57802 Empty ASSERTION parameter passed to the HASH_SEARCH macro
+
+2010-11-10 The InnoDB Team
+
+ * dict/dict0dict.c, handler/handler0alter.cc, include/dict0dict.h
+ row/row0merge.c:
+ Fix Bug#55084 InnoDB crash and corruption after ALTER TABLE
+
+2010-11-10 The InnoDB Team
+
+ * srv/srv0start.c:
+ Fix Bug#48026 Log start and end of InnoDB buffer pool
+ initialization to the error log
+
+2010-11-03 The InnoDB Team
+
+ * include/btr0btr.h, include/btr0btr.ic, dict/dict0crea.c:
+ Fix Bug#57947 InnoDB diagnostics shows btr_block_get calls
+ instead of real callers
+
+2010-11-03 The InnoDB Team
+
+ * fil/fil0fil.c, fsp/fsp0fsp.c, handler/ha_innodb.cc,
+ include/fil0fil.h, include/univ.i:
+ Fix Bug #54538 - use of exclusive innodb dictionary lock limits
+ performance.
+
+2010-11-02 The InnoDB Team
+
+ * btr/btr0cur.c, dict/dict0dict.c, dict/dict0load.c,
+ handler/ha_innodb.cc, include/dict0dict.h, row/row0mysql.c,
+ innodb_bug53046.result, innodb_bug53046.test:
+ Fix Bug#53046 dict_update_statistics_low can still be run
+ concurrently on same table
+
+2010-11-02 The InnoDB Team
+
+ * row/row0sel.c:
+ Fix Bug#57799 READ UNCOMMITTED access failure of off-page
+ DYNAMIC or COMPRESSED columns again
+
2010-10-24 The InnoDB Team
* row/row0mysql.c
- Fix Bug #57700 Latching order violation in
+ Fix Bug#57700 Latching order violation in
row_truncate_table_for_mysql()
2010-10-20 The InnoDB Team
* dict/dict0load.c
- Fix Bug #57616 Sig 11 in dict_load_table() when failed to load
+ Fix Bug#57616 Sig 11 in dict_load_table() when failed to load
index or foreign key
2010-10-19 The InnoDB Team
@@ -17,7 +100,7 @@
include/ibuf0ibuf.h, include/row0mysql.h,
row/row0mysql.c, row/row0sel.c,
innodb_bug56680.test, innodb_bug56680.result:
- Fix Bug #56680 InnoDB may return wrong results from a
+ Fix Bug#56680 InnoDB may return wrong results from a
case-insensitive covering index
2010-10-18 The InnoDB Team
@@ -72,7 +155,7 @@
2010-08-03 The InnoDB Team
* include/dict0dict.h, include/dict0dict.ic, row/row0mysql.c:
- Fix bug #54678, InnoDB, TRUNCATE, ALTER, I_S SELECT, crash or deadlock
+ Fix Bug#54678 InnoDB, TRUNCATE, ALTER, I_S SELECT, crash or deadlock
2010-08-03 The InnoDB Team
@@ -146,7 +229,7 @@
* dict/dict0load.c, fil/fil0fil.c:
Fix Bug#54658: InnoDB: Warning: allocated tablespace %lu,
- old maximum was 0 (introduced in Bug #53578 fix)
+ old maximum was 0 (introduced in Bug#53578 fix)
2010-06-16 The InnoDB Team
diff --git a/storage/xtradb/btr/btr0btr.c b/storage/xtradb/btr/btr0btr.c
index 4d6cd8d80fc..55204691400 100644
--- a/storage/xtradb/btr/btr0btr.c
+++ b/storage/xtradb/btr/btr0btr.c
@@ -675,7 +675,7 @@ btr_page_get_father_node_ptr_func(
" to fix the\n"
"InnoDB: corruption. If the crash happens at "
"the database startup, see\n"
- "InnoDB: " REFMAN "forcing-recovery.html about\n"
+ "InnoDB: " REFMAN "forcing-innodb-recovery.html about\n"
"InnoDB: forcing recovery. "
"Then dump + drop + reimport.\n", stderr);
diff --git a/storage/xtradb/btr/btr0cur.c b/storage/xtradb/btr/btr0cur.c
index daa94a549a0..321504a2b25 100644
--- a/storage/xtradb/btr/btr0cur.c
+++ b/storage/xtradb/btr/btr0cur.c
@@ -1124,7 +1124,7 @@ btr_cur_ins_lock_and_undo(
not zero, the parameters index and thr
should be specified */
btr_cur_t* cursor, /*!< in: cursor on page after which to insert */
- const dtuple_t* entry, /*!< in: entry to insert */
+ dtuple_t* entry, /*!< in/out: entry to insert */
que_thr_t* thr, /*!< in: query thread or NULL */
mtr_t* mtr, /*!< in/out: mini-transaction */
ibool* inherit)/*!< out: TRUE if the inserted new record maybe
@@ -1933,7 +1933,8 @@ btr_cur_update_in_place(
NOT call it if index is secondary */
if (!dict_index_is_clust(index)
- || row_upd_changes_ord_field_binary(NULL, index, update)) {
+ || row_upd_changes_ord_field_binary(NULL, NULL,
+ index, update)) {
/* Remove possible hash index pointer to this record */
btr_search_update_hash_on_delete(cursor);
@@ -2685,27 +2686,24 @@ ulint
btr_cur_del_mark_set_clust_rec(
/*===========================*/
ulint flags, /*!< in: undo logging and locking flags */
- btr_cur_t* cursor, /*!< in: cursor */
+ buf_block_t* block, /*!< in/out: buffer block of the record */
+ rec_t* rec, /*!< in/out: record */
+ dict_index_t* index, /*!< in: clustered index of the record */
+ const ulint* offsets,/*!< in: rec_get_offsets(rec) */
ibool val, /*!< in: value to set */
que_thr_t* thr, /*!< in: query thread */
mtr_t* mtr) /*!< in: mtr */
{
- dict_index_t* index;
- buf_block_t* block;
roll_ptr_t roll_ptr;
ulint err;
- rec_t* rec;
page_zip_des_t* page_zip;
trx_t* trx;
- mem_heap_t* heap = NULL;
- ulint offsets_[REC_OFFS_NORMAL_SIZE];
- ulint* offsets = offsets_;
- rec_offs_init(offsets_);
- rec = btr_cur_get_rec(cursor);
- index = cursor->index;
+ ut_ad(dict_index_is_clust(index));
+ ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
- offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
+ ut_ad(buf_block_get_frame(block) == page_align(rec));
+ ut_ad(page_is_leaf(page_align(rec)));
#ifdef UNIV_DEBUG
if (btr_cur_print_record_ops && thr) {
@@ -2717,13 +2715,12 @@ btr_cur_del_mark_set_clust_rec(
ut_ad(dict_index_is_clust(index));
ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
- err = lock_clust_rec_modify_check_and_lock(flags,
- btr_cur_get_block(cursor),
+ err = lock_clust_rec_modify_check_and_lock(flags, block,
rec, index, offsets, thr);
if (err != DB_SUCCESS) {
- goto func_exit;
+ return(err);
}
err = trx_undo_report_row_operation(flags, TRX_UNDO_MODIFY_OP, thr,
@@ -2731,11 +2728,9 @@ btr_cur_del_mark_set_clust_rec(
&roll_ptr);
if (err != DB_SUCCESS) {
- goto func_exit;
+ return(err);
}
- block = btr_cur_get_block(cursor);
-
if (block->is_hashed) {
rw_lock_x_lock(&btr_search_latch);
}
@@ -2758,10 +2753,6 @@ btr_cur_del_mark_set_clust_rec(
btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx,
roll_ptr, mtr);
-func_exit:
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
return(err);
}
@@ -3582,11 +3573,9 @@ btr_estimate_number_of_different_key_vals(
effective_pages = btr_estimate_n_pages_not_null(index, 1 /*k*/, first_rec_path);
if (!effective_pages) {
- dict_index_stat_mutex_enter(index);
for (j = 0; j <= n_cols; j++) {
index->stat_n_diff_key_vals[j] = (ib_int64_t)index->stat_n_leaf_pages;
}
- dict_index_stat_mutex_exit(index);
return;
} else if (effective_pages > index->stat_n_leaf_pages) {
effective_pages = index->stat_n_leaf_pages;
@@ -3728,8 +3717,6 @@ btr_estimate_number_of_different_key_vals(
also the pages used for external storage of fields (those pages are
included in index->stat_n_leaf_pages) */
- dict_index_stat_mutex_enter(index);
-
for (j = 0; j <= n_cols; j++) {
index->stat_n_diff_key_vals[j]
= ((n_diff[j]
@@ -3768,8 +3755,6 @@ btr_estimate_number_of_different_key_vals(
}
}
- dict_index_stat_mutex_exit(index);
-
mem_free(n_diff);
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
@@ -3862,108 +3847,36 @@ btr_cur_set_ownership_of_extern_field(
}
/*******************************************************************//**
-Marks not updated extern fields as not-owned by this record. The ownership
-is transferred to the updated record which is inserted elsewhere in the
+Marks non-updated off-page fields as disowned by this record. The ownership
+must be transferred to the updated record which is inserted elsewhere in the
index tree. In purge only the owner of externally stored field is allowed
-to free the field.
-@return TRUE if BLOB ownership was transferred */
+to free the field. */
UNIV_INTERN
-ibool
-btr_cur_mark_extern_inherited_fields(
-/*=================================*/
+void
+btr_cur_disown_inherited_fields(
+/*============================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
part will be updated, or NULL */
rec_t* rec, /*!< in/out: record in a clustered index */
dict_index_t* index, /*!< in: index of the page */
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
const upd_t* update, /*!< in: update vector */
- mtr_t* mtr) /*!< in: mtr, or NULL if not logged */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
- ulint n;
- ulint j;
ulint i;
- ibool change_ownership = FALSE;
- ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
+ ut_ad(rec_offs_any_extern(offsets));
+ ut_ad(mtr);
- if (!rec_offs_any_extern(offsets)) {
-
- return(FALSE);
- }
-
- n = rec_offs_n_fields(offsets);
-
- for (i = 0; i < n; i++) {
- if (rec_offs_nth_extern(offsets, i)) {
-
- /* Check it is not in updated fields */
-
- if (update) {
- for (j = 0; j < upd_get_n_fields(update);
- j++) {
- if (upd_get_nth_field(update, j)
- ->field_no == i) {
-
- goto updated;
- }
- }
- }
-
+ for (i = 0; i < rec_offs_n_fields(offsets); i++) {
+ if (rec_offs_nth_extern(offsets, i)
+ && !upd_get_field_by_field_no(update, i)) {
btr_cur_set_ownership_of_extern_field(
page_zip, rec, index, offsets, i, FALSE, mtr);
-
- change_ownership = TRUE;
-updated:
- ;
}
}
-
- return(change_ownership);
-}
-
-/*******************************************************************//**
-The complement of the previous function: in an update entry may inherit
-some externally stored fields from a record. We must mark them as inherited
-in entry, so that they are not freed in a rollback. */
-UNIV_INTERN
-void
-btr_cur_mark_dtuple_inherited_extern(
-/*=================================*/
- dtuple_t* entry, /*!< in/out: updated entry to be
- inserted to clustered index */
- const upd_t* update) /*!< in: update vector */
-{
- ulint i;
-
- for (i = 0; i < dtuple_get_n_fields(entry); i++) {
-
- dfield_t* dfield = dtuple_get_nth_field(entry, i);
- byte* data;
- ulint len;
- ulint j;
-
- if (!dfield_is_ext(dfield)) {
- continue;
- }
-
- /* Check if it is in updated fields */
-
- for (j = 0; j < upd_get_n_fields(update); j++) {
- if (upd_get_nth_field(update, j)->field_no == i) {
-
- goto is_updated;
- }
- }
-
- data = dfield_get_data(dfield);
- len = dfield_get_len(dfield);
- data[len - BTR_EXTERN_FIELD_REF_SIZE + BTR_EXTERN_LEN]
- |= BTR_EXTERN_INHERITED_FLAG;
-
-is_updated:
- ;
- }
}
/*******************************************************************//**
@@ -4002,29 +3915,6 @@ btr_cur_unmark_extern_fields(
}
/*******************************************************************//**
-Marks all extern fields in a dtuple as owned by the record. */
-UNIV_INTERN
-void
-btr_cur_unmark_dtuple_extern_fields(
-/*================================*/
- dtuple_t* entry) /*!< in/out: clustered index entry */
-{
- ulint i;
-
- for (i = 0; i < dtuple_get_n_fields(entry); i++) {
- dfield_t* dfield = dtuple_get_nth_field(entry, i);
-
- if (dfield_is_ext(dfield)) {
- byte* data = dfield_get_data(dfield);
- ulint len = dfield_get_len(dfield);
-
- data[len - BTR_EXTERN_FIELD_REF_SIZE + BTR_EXTERN_LEN]
- &= ~BTR_EXTERN_OWNER_FLAG;
- }
- }
-}
-
-/*******************************************************************//**
Flags the data tuple fields that are marked as extern storage in the
update vector. We use this function to remember which fields we must
mark as extern storage in a record inserted for an update.
@@ -4182,7 +4072,7 @@ Stores the fields in big_rec_vec to the tablespace and puts pointers to
them in rec. The extern flags in rec will have to be set beforehand.
The fields are stored on pages allocated from leaf node
file segment of the index tree.
-@return DB_SUCCESS or error */
+@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN
ulint
btr_store_big_rec_extern_fields(
diff --git a/storage/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c
index 9e09075ae9f..9dc5da2069a 100644
--- a/storage/xtradb/buf/buf0buf.c
+++ b/storage/xtradb/buf/buf0buf.c
@@ -53,6 +53,10 @@ Created 11/5/1995 Heikki Tuuri
#include "page0zip.h"
#include "trx0trx.h"
#include "srv0start.h"
+#include "que0que.h"
+#include "read0read.h"
+#include "row0row.h"
+#include "ha_prototypes.h"
/* prototypes for new functions added to ha_innodb.cc */
trx_t* innobase_get_trx();
@@ -310,6 +314,30 @@ read-ahead or flush occurs */
UNIV_INTERN ibool buf_debug_prints = FALSE;
#endif /* UNIV_DEBUG */
+/* Buffer pool shared memory segment information */
+typedef struct buf_shm_info_struct buf_shm_info_t;
+
+struct buf_shm_info_struct {
+ char head_str[8];
+ ulint binary_id;
+ ibool is_new; /* during initializing */
+ ibool clean; /* clean shutdowned and free */
+ ibool reusable; /* reusable */
+ ulint buf_pool_size; /* backup value */
+ ulint page_size; /* backup value */
+ ulint frame_offset; /* offset of the first frame based on chunk->mem */
+ ulint zip_hash_offset;
+ ulint zip_hash_n;
+
+ ulint checksum;
+
+ buf_pool_t buf_pool_backup;
+ buf_chunk_t chunk_backup;
+
+ ib_uint64_t dummy;
+};
+
+#define BUF_SHM_INFO_HEAD "XTRA_SHM"
#endif /* !UNIV_HOTBACKUP */
/********************************************************************//**
@@ -429,7 +457,7 @@ buf_page_is_corrupted(
"you may have copied the InnoDB\n"
"InnoDB: tablespace but not the InnoDB "
"log files. See\n"
- "InnoDB: " REFMAN "forcing-recovery.html\n"
+ "InnoDB: " REFMAN "forcing-innodb-recovery.html\n"
"InnoDB: for more information.\n",
(ulong) mach_read_from_4(read_buf
+ FIL_PAGE_OFFSET),
@@ -756,6 +784,45 @@ buf_block_init(
#endif /* UNIV_SYNC_DEBUG */
}
+static
+void
+buf_block_reuse(
+/*============*/
+ buf_block_t* block,
+ ptrdiff_t frame_offset)
+{
+ /* block_init */
+ block->frame += frame_offset;
+
+ UNIV_MEM_DESC(block->frame, UNIV_PAGE_SIZE, block);
+
+ block->index = NULL;
+
+#ifdef UNIV_DEBUG
+ /* recreate later */
+ block->page.in_page_hash = FALSE;
+ block->page.in_zip_hash = FALSE;
+#endif /* UNIV_DEBUG */
+
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ block->n_pointers = 0;
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+
+ if (block->page.zip.data)
+ block->page.zip.data += frame_offset;
+
+ block->is_hashed = FALSE;
+
+ mutex_create(&block->mutex, SYNC_BUF_BLOCK);
+
+ rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
+ ut_ad(rw_lock_validate(&(block->lock)));
+
+#ifdef UNIV_SYNC_DEBUG
+ rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
+#endif /* UNIV_SYNC_DEBUG */
+}
+
/********************************************************************//**
Allocates a chunk of buffer frames.
@return chunk, or NULL on failure */
@@ -768,26 +835,188 @@ buf_chunk_init(
{
buf_block_t* block;
byte* frame;
+ ulint zip_hash_n = 0;
+ ulint zip_hash_mem_size = 0;
+ hash_table_t* zip_hash_tmp = NULL;
ulint i;
+ buf_shm_info_t* shm_info = NULL;
/* Round down to a multiple of page size,
although it already should be. */
mem_size = ut_2pow_round(mem_size, UNIV_PAGE_SIZE);
+
+ srv_buffer_pool_shm_is_reused = FALSE;
+
+ if (srv_buffer_pool_shm_key) {
+ /* zip_hash size */
+ zip_hash_n = (mem_size / UNIV_PAGE_SIZE) * 2;
+ zip_hash_mem_size = ut_2pow_round(hash_create_needed(zip_hash_n)
+ + (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
+ }
+
/* Reserve space for the block descriptors. */
mem_size += ut_2pow_round((mem_size / UNIV_PAGE_SIZE) * (sizeof *block)
+ (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
+ if (srv_buffer_pool_shm_key) {
+ mem_size += ut_2pow_round(sizeof(buf_shm_info_t)
+ + (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
+ mem_size += zip_hash_mem_size;
+ }
chunk->mem_size = mem_size;
+
+ if (srv_buffer_pool_shm_key) {
+ ulint binary_id;
+ ibool is_new;
+
+ ut_a(buf_pool->n_chunks == 1);
+
+ fprintf(stderr,
+ "InnoDB: Warning: The innodb_buffer_pool_shm_key option has been specified.\n"
+ "InnoDB: Do not change the following between restarts of the server while this option is being used:\n"
+ "InnoDB: * the mysqld executable between restarts of the server.\n"
+ "InnoDB: * the value of innodb_buffer_pool_size.\n"
+ "InnoDB: * the value of innodb_page_size.\n"
+ "InnoDB: * datafiles created by InnoDB during this session.\n"
+ "InnoDB: Otherwise, data corruption in datafiles may result.\n");
+
+ /* FIXME: This is vague id still */
+ binary_id = (ulint) ((byte*)mtr_commit - (byte*)btr_root_get)
+ + (ulint) ((byte*)os_get_os_version - (byte*)buf_calc_page_new_checksum)
+ + (ulint) ((byte*)page_dir_find_owner_slot - (byte*)dfield_data_is_binary_equal)
+ + (ulint) ((byte*)que_graph_publish - (byte*)dict_casedn_str)
+ + (ulint) ((byte*)read_view_oldest_copy_or_open_new - (byte*)fil_space_get_version)
+ + (ulint) ((byte*)rec_get_n_extern_new - (byte*)fsp_get_size_low)
+ + (ulint) ((byte*)row_get_trx_id_offset - (byte*)ha_create_func)
+ + (ulint) ((byte*)srv_set_io_thread_op_info - (byte*)thd_is_replication_slave_thread)
+ + (ulint) ((byte*)mutex_create_func - (byte*)ibuf_inside)
+ + (ulint) ((byte*)trx_set_detailed_error - (byte*)lock_check_trx_id_sanity)
+ + (ulint) ((byte*)ut_time - (byte*)mem_heap_strdup);
+
+ chunk->mem = os_shm_alloc(&chunk->mem_size, srv_buffer_pool_shm_key, &is_new);
+
+ if (UNIV_UNLIKELY(chunk->mem == NULL)) {
+ return(NULL);
+ }
+init_again:
+#ifdef UNIV_SET_MEM_TO_ZERO
+ if (is_new) {
+ memset(chunk->mem, '\0', chunk->mem_size);
+ }
+#endif
+ /* for ut_fold_binary_32(), these values should be 32-bit aligned */
+ ut_a(sizeof(buf_shm_info_t) % 4 == 0);
+ ut_a((ulint)chunk->mem % 4 == 0);
+ ut_a(chunk->mem_size % 4 == 0);
+
+ shm_info = chunk->mem;
+
+ zip_hash_tmp = (hash_table_t*)((byte*)chunk->mem + chunk->mem_size - zip_hash_mem_size);
+
+ if (is_new) {
+ strncpy(shm_info->head_str, BUF_SHM_INFO_HEAD, 8);
+ shm_info->binary_id = binary_id;
+ shm_info->is_new = TRUE; /* changed to FALSE when the initialization is finished */
+ shm_info->clean = FALSE; /* changed to TRUE when free the segment. */
+ shm_info->reusable = FALSE; /* changed to TRUE when validation is finished. */
+ shm_info->buf_pool_size = srv_buf_pool_size;
+ shm_info->page_size = srv_page_size;
+ shm_info->zip_hash_offset = chunk->mem_size - zip_hash_mem_size;
+ shm_info->zip_hash_n = zip_hash_n;
+ } else {
+ ulint checksum;
+
+ if (strncmp(shm_info->head_str, BUF_SHM_INFO_HEAD, 8)) {
+ fprintf(stderr,
+ "InnoDB: Error: The shared memory segment seems not to be for buffer pool.\n");
+ return(NULL);
+ }
+ if (shm_info->binary_id != binary_id) {
+ fprintf(stderr,
+ "InnoDB: Error: The shared memory segment seems not to be for this binary.\n");
+ return(NULL);
+ }
+ if (shm_info->is_new) {
+ fprintf(stderr,
+ "InnoDB: Error: The shared memory was not initialized yet.\n");
+ return(NULL);
+ }
+ if (shm_info->buf_pool_size != srv_buf_pool_size) {
+ fprintf(stderr,
+ "InnoDB: Error: srv_buf_pool_size is different (shm=%lu current=%lu).\n",
+ shm_info->buf_pool_size, srv_buf_pool_size);
+ return(NULL);
+ }
+ if (shm_info->page_size != srv_page_size) {
+ fprintf(stderr,
+ "InnoDB: Error: srv_page_size is different (shm=%lu current=%lu).\n",
+ shm_info->page_size, srv_page_size);
+ return(NULL);
+ }
+ if (!shm_info->reusable) {
+ fprintf(stderr,
+ "InnoDB: Warning: The shared memory has unrecoverable contents.\n"
+ "InnoDB: The shared memory segment is initialized.\n");
+ is_new = TRUE;
+ goto init_again;
+ }
+ if (!shm_info->clean) {
+ fprintf(stderr,
+ "InnoDB: Warning: The shared memory was not shut down cleanly.\n"
+ "InnoDB: The shared memory segment is initialized.\n");
+ is_new = TRUE;
+ goto init_again;
+ }
+
+ ut_a(shm_info->zip_hash_offset == chunk->mem_size - zip_hash_mem_size);
+ ut_a(shm_info->zip_hash_n == zip_hash_n);
+
+ /* check checksum */
+ if (srv_buffer_pool_shm_checksum) {
+ checksum = ut_fold_binary_32((byte*)chunk->mem + sizeof(buf_shm_info_t),
+ chunk->mem_size - sizeof(buf_shm_info_t));
+ } else {
+ checksum = BUF_NO_CHECKSUM_MAGIC;
+ }
+
+ if (shm_info->checksum != BUF_NO_CHECKSUM_MAGIC
+ && shm_info->checksum != checksum) {
+ fprintf(stderr,
+ "InnoDB: Error: checksum of the shared memory is not match. "
+ "(stored=%lu calculated=%lu)\n",
+ shm_info->checksum, checksum);
+ return(NULL);
+ }
+
+ /* flag to use the segment. */
+ shm_info->clean = FALSE; /* changed to TRUE when free the segment. */
+ }
+
+ /* init zip_hash contents */
+ if (is_new) {
+ hash_create_init(zip_hash_tmp, zip_hash_n);
+ } else {
+ /* adjust offset is done later */
+ hash_create_reuse(zip_hash_tmp);
+
+ srv_buffer_pool_shm_is_reused = TRUE;
+ }
+ } else {
chunk->mem = os_mem_alloc_large(&chunk->mem_size);
if (UNIV_UNLIKELY(chunk->mem == NULL)) {
return(NULL);
}
+ }
/* Allocate the block descriptors from
the start of the memory block. */
+ if (srv_buffer_pool_shm_key) {
+ chunk->blocks = (buf_block_t*)((byte*)chunk->mem + sizeof(buf_shm_info_t));
+ } else {
chunk->blocks = chunk->mem;
+ }
/* Align a pointer to the first frame. Note that when
os_large_page_size is smaller than UNIV_PAGE_SIZE,
@@ -795,8 +1024,13 @@ buf_chunk_init(
it is bigger, we may allocate more blocks than requested. */
frame = ut_align(chunk->mem, UNIV_PAGE_SIZE);
+ if (srv_buffer_pool_shm_key) {
+ /* reserve zip_hash space and always -1 for reproductibity */
+ chunk->size = (chunk->mem_size - zip_hash_mem_size) / UNIV_PAGE_SIZE - 1;
+ } else {
chunk->size = chunk->mem_size / UNIV_PAGE_SIZE
- (frame != chunk->mem);
+ }
/* Subtract the space needed for block descriptors. */
{
@@ -810,6 +1044,99 @@ buf_chunk_init(
chunk->size = size;
}
+ if (shm_info && !(shm_info->is_new)) {
+ /* convert the shared memory segment for reuse */
+ ptrdiff_t phys_offset;
+ ptrdiff_t logi_offset;
+ ptrdiff_t blocks_offset;
+ void* previous_frame_address;
+
+ if (chunk->size < shm_info->chunk_backup.size) {
+ fprintf(stderr,
+ "InnoDB: Error: The buffer pool became smaller because of allocated address.\n"
+ "InnoDB: Retrying may avoid this situation.\n");
+ shm_info->clean = TRUE; /* release the flag for retrying */
+ return(NULL);
+ }
+
+ chunk->size = shm_info->chunk_backup.size;
+ phys_offset = frame - ((byte*)chunk->mem + shm_info->frame_offset);
+ logi_offset = frame - chunk->blocks[0].frame;
+ previous_frame_address = chunk->blocks[0].frame;
+ blocks_offset = (byte*)chunk->blocks - (byte*)shm_info->chunk_backup.blocks;
+
+ if (phys_offset || logi_offset || blocks_offset) {
+ fprintf(stderr,
+ "InnoDB: Buffer pool in the shared memory segment should be converted.\n"
+ "InnoDB: Previous frames in address : %p\n"
+ "InnoDB: Previous frames were located : %p\n"
+ "InnoDB: Current frames should be located: %p\n"
+ "InnoDB: Pysical offset : %ld (%#lx)\n"
+ "InnoDB: Logical offset (frames) : %ld (%#lx)\n"
+ "InnoDB: Logical offset (blocks) : %ld (%#lx)\n",
+ (byte*)chunk->mem + shm_info->frame_offset,
+ chunk->blocks[0].frame, frame,
+ (long) phys_offset, (long) phys_offset,
+ (long) logi_offset, (long) logi_offset,
+ (long) blocks_offset, (long) blocks_offset);
+ } else {
+ fprintf(stderr,
+ "InnoDB: Buffer pool in the shared memory segment can be used as it is.\n");
+ }
+
+ if (phys_offset) {
+ fprintf(stderr,
+ "InnoDB: Aligning physical offset...");
+
+ memmove(frame, (byte*)chunk->mem + shm_info->frame_offset,
+ chunk->size * UNIV_PAGE_SIZE);
+
+ fprintf(stderr,
+ " Done.\n");
+ }
+
+ /* buf_block_t */
+ block = chunk->blocks;
+ for (i = chunk->size; i--; ) {
+ buf_block_reuse(block, logi_offset);
+ block++;
+ }
+
+ if (logi_offset || blocks_offset) {
+ fprintf(stderr,
+ "InnoDB: Aligning logical offset...");
+
+
+ /* buf_pool_t buf_pool_backup */
+ UT_LIST_OFFSET(flush_list, buf_page_t, shm_info->buf_pool_backup.flush_list,
+ previous_frame_address, logi_offset, blocks_offset);
+ UT_LIST_OFFSET(free, buf_page_t, shm_info->buf_pool_backup.free,
+ previous_frame_address, logi_offset, blocks_offset);
+ UT_LIST_OFFSET(LRU, buf_page_t, shm_info->buf_pool_backup.LRU,
+ previous_frame_address, logi_offset, blocks_offset);
+ if (shm_info->buf_pool_backup.LRU_old)
+ shm_info->buf_pool_backup.LRU_old =
+ (buf_page_t*)((byte*)(shm_info->buf_pool_backup.LRU_old)
+ + (((void*)shm_info->buf_pool_backup.LRU_old > previous_frame_address)
+ ? logi_offset : blocks_offset));
+
+ UT_LIST_OFFSET(unzip_LRU, buf_block_t, shm_info->buf_pool_backup.unzip_LRU,
+ previous_frame_address, logi_offset, blocks_offset);
+
+ UT_LIST_OFFSET(zip_list, buf_page_t, shm_info->buf_pool_backup.zip_clean,
+ previous_frame_address, logi_offset, blocks_offset);
+ for (i = 0; i < BUF_BUDDY_SIZES_MAX; i++) {
+ UT_LIST_OFFSET(zip_list, buf_page_t, shm_info->buf_pool_backup.zip_free[i],
+ previous_frame_address, logi_offset, blocks_offset);
+ }
+
+ HASH_OFFSET(zip_hash_tmp, buf_page_t, hash,
+ previous_frame_address, logi_offset, blocks_offset);
+
+ fprintf(stderr,
+ " Done.\n");
+ }
+ } else {
/* Init block structs and assign frames for them. Then we
assign the frames to the first blocks (we already mapped the
memory above). */
@@ -833,6 +1160,11 @@ buf_chunk_init(
block++;
frame += UNIV_PAGE_SIZE;
}
+ }
+
+ if (shm_info) {
+ shm_info->frame_offset = chunk->blocks[0].frame - (byte*)chunk->mem;
+ }
return(chunk);
}
@@ -1014,6 +1346,8 @@ buf_chunk_free(
UNIV_MEM_UNDESC(block);
}
+ ut_a(!srv_buffer_pool_shm_key);
+
os_mem_free_large(chunk->mem, chunk->mem_size);
}
@@ -1063,7 +1397,10 @@ buf_pool_init(void)
srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
+ /* zip_hash is allocated to shm when srv_buffer_pool_shm_key is enabled */
+ if (!srv_buffer_pool_shm_key) {
buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
+ }
buf_pool->last_printout_time = time(NULL);
@@ -1078,6 +1415,86 @@ buf_pool_init(void)
--------------------------- */
/* All fields are initialized by mem_zalloc(). */
+ if (srv_buffer_pool_shm_key) {
+ buf_shm_info_t* shm_info;
+
+ ut_a((byte*)chunk->blocks == (byte*)chunk->mem + sizeof(buf_shm_info_t));
+ shm_info = chunk->mem;
+
+ buf_pool->zip_hash = (hash_table_t*)((byte*)chunk->mem + shm_info->zip_hash_offset);
+
+ if(shm_info->is_new) {
+ shm_info->is_new = FALSE; /* initialization was finished */
+ } else {
+ buf_block_t* block = chunk->blocks;
+ buf_page_t* b;
+
+ /* shm_info->buf_pool_backup should be converted */
+ /* at buf_chunk_init(). So copy simply. */
+ buf_pool->flush_list = shm_info->buf_pool_backup.flush_list;
+ buf_pool->freed_page_clock = shm_info->buf_pool_backup.freed_page_clock;
+ buf_pool->free = shm_info->buf_pool_backup.free;
+ buf_pool->LRU = shm_info->buf_pool_backup.LRU;
+ buf_pool->LRU_old = shm_info->buf_pool_backup.LRU_old;
+ buf_pool->LRU_old_len = shm_info->buf_pool_backup.LRU_old_len;
+ buf_pool->unzip_LRU = shm_info->buf_pool_backup.unzip_LRU;
+ buf_pool->zip_clean = shm_info->buf_pool_backup.zip_clean;
+ for (i = 0; i < BUF_BUDDY_SIZES_MAX; i++) {
+ buf_pool->zip_free[i] = shm_info->buf_pool_backup.zip_free[i];
+ }
+
+ for (i = 0; i < chunk->size; i++, block++) {
+ if (buf_block_get_state(block)
+ == BUF_BLOCK_FILE_PAGE) {
+ ut_d(block->page.in_page_hash = TRUE);
+ HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
+ buf_page_address_fold(
+ block->page.space,
+ block->page.offset),
+ &block->page);
+ }
+ }
+
+ for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
+ b = UT_LIST_GET_NEXT(zip_list, b)) {
+ ut_ad(!b->in_flush_list);
+ ut_ad(b->in_LRU_list);
+
+ ut_d(b->in_page_hash = TRUE);
+ HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
+ buf_page_address_fold(b->space, b->offset), b);
+ }
+
+ for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
+ b = UT_LIST_GET_NEXT(flush_list, b)) {
+ ut_ad(b->in_flush_list);
+ ut_ad(b->in_LRU_list);
+
+ switch (buf_page_get_state(b)) {
+ case BUF_BLOCK_ZIP_DIRTY:
+ ut_d(b->in_page_hash = TRUE);
+ HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
+ buf_page_address_fold(b->space,
+ b->offset), b);
+ break;
+ case BUF_BLOCK_FILE_PAGE:
+ /* uncompressed page */
+ break;
+ case BUF_BLOCK_ZIP_FREE:
+ case BUF_BLOCK_ZIP_PAGE:
+ case BUF_BLOCK_NOT_USED:
+ case BUF_BLOCK_READY_FOR_USE:
+ case BUF_BLOCK_MEMORY:
+ case BUF_BLOCK_REMOVE_HASH:
+ ut_error;
+ break;
+ }
+ }
+
+
+ }
+ }
+
mutex_exit(&LRU_list_mutex);
rw_lock_x_unlock(&page_hash_latch);
buf_pool_mutex_exit();
@@ -1102,6 +1519,34 @@ buf_pool_free(void)
buf_chunk_t* chunk;
buf_chunk_t* chunks;
+ if (srv_buffer_pool_shm_key) {
+ buf_shm_info_t* shm_info;
+
+ ut_a(buf_pool->n_chunks == 1);
+
+ chunk = buf_pool->chunks;
+ shm_info = chunk->mem;
+ ut_a((byte*)chunk->blocks == (byte*)chunk->mem + sizeof(buf_shm_info_t));
+
+ /* validation the shared memory segment doesn't have unrecoverable contents. */
+ /* Currently, validation became not needed */
+ shm_info->reusable = TRUE;
+
+ memcpy(&(shm_info->buf_pool_backup), buf_pool, sizeof(buf_pool_t));
+ memcpy(&(shm_info->chunk_backup), chunk, sizeof(buf_chunk_t));
+
+ if (srv_fast_shutdown < 2) {
+ if (srv_buffer_pool_shm_checksum) {
+ shm_info->checksum = ut_fold_binary_32((byte*)chunk->mem + sizeof(buf_shm_info_t),
+ chunk->mem_size - sizeof(buf_shm_info_t));
+ } else {
+ shm_info->checksum = BUF_NO_CHECKSUM_MAGIC;
+ }
+ shm_info->clean = TRUE;
+ }
+
+ os_shm_free(chunk->mem, chunk->mem_size);
+ } else {
chunks = buf_pool->chunks;
chunk = chunks + buf_pool->n_chunks;
@@ -1110,10 +1555,13 @@ buf_pool_free(void)
would fail at shutdown. */
os_mem_free_large(chunk->mem, chunk->mem_size);
}
+ }
mem_free(buf_pool->chunks);
hash_table_free(buf_pool->page_hash);
+ if (!srv_buffer_pool_shm_key) {
hash_table_free(buf_pool->zip_hash);
+ }
mem_free(buf_pool);
buf_pool = NULL;
}
@@ -1308,6 +1756,11 @@ try_again:
//buf_pool_mutex_enter();
mutex_enter(&LRU_list_mutex);
+ if (srv_buffer_pool_shm_key) {
+ /* Cannot support shrink */
+ goto func_done;
+ }
+
shrink_again:
if (buf_pool->n_chunks <= 1) {
@@ -1551,6 +2004,11 @@ void
buf_pool_resize(void)
/*=================*/
{
+ if (srv_buffer_pool_shm_key) {
+ /* Cannot support resize */
+ return;
+ }
+
//buf_pool_mutex_enter();
mutex_enter(&LRU_list_mutex);
@@ -3542,7 +4000,7 @@ corrupt:
"InnoDB: TABLE to scan your"
" table for corruption.\n"
"InnoDB: See also "
- REFMAN "forcing-recovery.html\n"
+ REFMAN "forcing-innodb-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
if (srv_pass_corrupt_table && !trx_sys_sys_space(bpage->space)
diff --git a/storage/xtradb/buf/buf0flu.c b/storage/xtradb/buf/buf0flu.c
index 0ef91137aef..5db6f816aab 100644
--- a/storage/xtradb/buf/buf0flu.c
+++ b/storage/xtradb/buf/buf0flu.c
@@ -1811,9 +1811,9 @@ buf_flush_validate_low(void)
ut_a(om > 0);
if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
+ buf_page_t* rpage;
ut_a(rnode);
- buf_page_t* rpage = *rbt_value(buf_page_t*,
- rnode);
+ rpage = *rbt_value(buf_page_t*, rnode);
ut_a(rpage);
ut_a(rpage == bpage);
rnode = rbt_next(buf_pool->flush_rbt, rnode);
diff --git a/storage/xtradb/buf/buf0lru.c b/storage/xtradb/buf/buf0lru.c
index 94828940fd4..92a645ef2f5 100644
--- a/storage/xtradb/buf/buf0lru.c
+++ b/storage/xtradb/buf/buf0lru.c
@@ -2093,6 +2093,7 @@ buf_LRU_stat_update(void)
/*=====================*/
{
buf_LRU_stat_t* item;
+ buf_LRU_stat_t cur_stat;
/* If we haven't started eviction yet then don't update stats. */
if (buf_pool->freed_page_clock == 0) {
@@ -2107,12 +2108,19 @@ buf_LRU_stat_update(void)
buf_LRU_stat_arr_ind++;
buf_LRU_stat_arr_ind %= BUF_LRU_STAT_N_INTERVAL;
- /* Add the current value and subtract the obsolete entry. */
- buf_LRU_stat_sum.io += buf_LRU_stat_cur.io - item->io;
- buf_LRU_stat_sum.unzip += buf_LRU_stat_cur.unzip - item->unzip;
+ /* Add the current value and subtract the obsolete entry.
+ Since buf_LRU_stat_cur is not protected by any mutex,
+ it can be changing between adding to buf_LRU_stat_sum
+ and copying to item. Assign it to local variables to make
+ sure the same value assign to the buf_LRU_stat_sum
+ and item */
+ cur_stat = buf_LRU_stat_cur;
+
+ buf_LRU_stat_sum.io += cur_stat.io - item->io;
+ buf_LRU_stat_sum.unzip += cur_stat.unzip - item->unzip;
/* Put current entry in the array. */
- memcpy(item, &buf_LRU_stat_cur, sizeof *item);
+ memcpy(item, &cur_stat, sizeof *item);
//buf_pool_mutex_exit();
mutex_exit(&buf_pool_mutex);
@@ -2265,7 +2273,7 @@ buf_LRU_file_restore(void)
ulint req = 0;
ibool terminated = FALSE;
ibool ret = FALSE;
- dump_record_t* records= 0;
+ dump_record_t* records = NULL;
ulint size;
ulint size_high;
ulint length;
diff --git a/storage/xtradb/dict/dict0crea.c b/storage/xtradb/dict/dict0crea.c
index 992a7000eda..c63ff57be97 100644
--- a/storage/xtradb/dict/dict0crea.c
+++ b/storage/xtradb/dict/dict0crea.c
@@ -894,7 +894,7 @@ dict_truncate_index_tree(
appropriate field in the SYS_INDEXES record: this mini-transaction
marks the B-tree totally truncated */
- btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
+ btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
btr_free_root(space, zip_size, root_page_no, mtr);
create:
diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c
index 40380067bd2..638ab55703b 100644
--- a/storage/xtradb/dict/dict0dict.c
+++ b/storage/xtradb/dict/dict0dict.c
@@ -81,9 +81,18 @@ UNIV_INTERN rw_lock_t dict_operation_lock;
/** Identifies generated InnoDB foreign key names */
static char dict_ibfk[] = "_ibfk_";
-/** array of mutexes protecting dict_index_t::stat_n_diff_key_vals[] */
-#define DICT_INDEX_STAT_MUTEX_SIZE 32
-static mutex_t dict_index_stat_mutex[DICT_INDEX_STAT_MUTEX_SIZE];
+/** array of rw locks protecting
+dict_table_t::stat_initialized
+dict_table_t::stat_n_rows (*)
+dict_table_t::stat_clustered_index_size
+dict_table_t::stat_sum_of_other_index_sizes
+dict_table_t::stat_modified_counter (*)
+dict_table_t::indexes*::stat_n_diff_key_vals[]
+dict_table_t::indexes*::stat_index_size
+dict_table_t::indexes*::stat_n_leaf_pages
+(*) those are not always protected for performance reasons */
+#define DICT_TABLE_STATS_LATCHES_SIZE 64
+static rw_lock_t dict_table_stats_latches[DICT_TABLE_STATS_LATCHES_SIZE];
/*******************************************************************//**
Tries to find column names for the index and sets the col field of the
@@ -244,43 +253,65 @@ dict_mutex_exit_for_mysql(void)
mutex_exit(&(dict_sys->mutex));
}
-/** Get the mutex that protects index->stat_n_diff_key_vals[] */
-#define GET_INDEX_STAT_MUTEX(index) \
- (&dict_index_stat_mutex[ut_fold_dulint(index->id) \
- % DICT_INDEX_STAT_MUTEX_SIZE])
+/** Get the latch that protects the stats of a given table */
+#define GET_TABLE_STATS_LATCH(table) \
+ (&dict_table_stats_latches[ut_fold_dulint(table->id) \
+ % DICT_TABLE_STATS_LATCHES_SIZE])
/**********************************************************************//**
-Lock the appropriate mutex to protect index->stat_n_diff_key_vals[].
-index->id is used to pick the right mutex and it should not change
-before dict_index_stat_mutex_exit() is called on this index. */
+Lock the appropriate latch to protect a given table's statistics.
+table->id is used to pick the corresponding latch from a global array of
+latches. */
UNIV_INTERN
void
-dict_index_stat_mutex_enter(
-/*========================*/
- const dict_index_t* index) /*!< in: index */
+dict_table_stats_lock(
+/*==================*/
+ const dict_table_t* table, /*!< in: table */
+ ulint latch_mode) /*!< in: RW_S_LATCH or
+ RW_X_LATCH */
{
- ut_ad(index != NULL);
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
- ut_ad(index->cached);
- ut_ad(!index->to_be_dropped);
+ ut_ad(table != NULL);
+ ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
- mutex_enter(GET_INDEX_STAT_MUTEX(index));
+ switch (latch_mode) {
+ case RW_S_LATCH:
+ rw_lock_s_lock(GET_TABLE_STATS_LATCH(table));
+ break;
+ case RW_X_LATCH:
+ rw_lock_x_lock(GET_TABLE_STATS_LATCH(table));
+ break;
+ case RW_NO_LATCH:
+ /* fall through */
+ default:
+ ut_error;
+ }
}
/**********************************************************************//**
-Unlock the appropriate mutex that protects index->stat_n_diff_key_vals[]. */
+Unlock the latch that has been locked by dict_table_stats_lock() */
UNIV_INTERN
void
-dict_index_stat_mutex_exit(
-/*=======================*/
- const dict_index_t* index) /*!< in: index */
+dict_table_stats_unlock(
+/*====================*/
+ const dict_table_t* table, /*!< in: table */
+ ulint latch_mode) /*!< in: RW_S_LATCH or
+ RW_X_LATCH */
{
- ut_ad(index != NULL);
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
- ut_ad(index->cached);
- ut_ad(!index->to_be_dropped);
+ ut_ad(table != NULL);
+ ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
- mutex_exit(GET_INDEX_STAT_MUTEX(index));
+ switch (latch_mode) {
+ case RW_S_LATCH:
+ rw_lock_s_unlock(GET_TABLE_STATS_LATCH(table));
+ break;
+ case RW_X_LATCH:
+ rw_lock_x_unlock(GET_TABLE_STATS_LATCH(table));
+ break;
+ case RW_NO_LATCH:
+ /* fall through */
+ default:
+ ut_error;
+ }
}
/********************************************************************//**
@@ -671,8 +702,8 @@ dict_init(void)
mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
- for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
- mutex_create(&dict_index_stat_mutex[i], SYNC_INDEX_TREE);
+ for (i = 0; i < DICT_TABLE_STATS_LATCHES_SIZE; i++) {
+ rw_lock_create(&dict_table_stats_latches[i], SYNC_INDEX_TREE);
}
}
@@ -704,13 +735,12 @@ dict_table_get(
mutex_exit(&(dict_sys->mutex));
- if (table != NULL) {
- if (!table->stat_initialized && !table->is_corrupt) {
- /* If table->ibd_file_missing == TRUE, this will
- print an error message and return without doing
- anything. */
- dict_update_statistics(table, FALSE);
- }
+ if (table != NULL && !table->is_corrupt) {
+ /* If table->ibd_file_missing == TRUE, this will
+ print an error message and return without doing
+ anything. */
+ dict_update_statistics(table, TRUE /* only update stats
+ if they have not been initialized */, FALSE);
}
return(table);
@@ -907,7 +937,7 @@ dict_table_rename_in_cache(
dict_foreign_t* foreign;
dict_index_t* index;
ulint fold;
- char old_name[MAX_TABLE_NAME_LEN + 1];
+ char old_name[MAX_FULL_NAME_LEN + 1];
ut_ad(table);
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -919,7 +949,7 @@ dict_table_rename_in_cache(
ut_print_timestamp(stderr);
fprintf(stderr, "InnoDB: too long table name: '%s', "
"max length is %d\n", table->name,
- MAX_TABLE_NAME_LEN);
+ MAX_FULL_NAME_LEN);
ut_error;
}
@@ -969,11 +999,11 @@ dict_table_rename_in_cache(
ut_fold_string(old_name), table);
if (strlen(new_name) > strlen(table->name)) {
- /* We allocate MAX_TABLE_NAME_LEN+1 bytes here to avoid
+ /* We allocate MAX_FULL_NAME_LEN + 1 bytes here to avoid
memory fragmentation, we assume a repeated calls of
ut_realloc() with the same size do not cause fragmentation */
- ut_a(strlen(new_name) <= MAX_TABLE_NAME_LEN);
- table->name = ut_realloc(table->name, MAX_TABLE_NAME_LEN + 1);
+ ut_a(strlen(new_name) <= MAX_FULL_NAME_LEN);
+ table->name = ut_realloc(table->name, MAX_FULL_NAME_LEN + 1);
}
memcpy(table->name, new_name, strlen(new_name) + 1);
@@ -2726,7 +2756,7 @@ dict_scan_to(
quote = '\0';
} else if (quote) {
/* Within quotes: do nothing. */
- } else if (*ptr == '`' || *ptr == '"') {
+ } else if (*ptr == '`' || *ptr == '"' || *ptr == '\'') {
/* Starting quote: remember the quote character. */
quote = *ptr;
} else {
@@ -4366,11 +4396,9 @@ next_rec:
btr_pcur_close(&pcur);
mtr_commit(&mtr);
- dict_index_stat_mutex_enter(index);
for (i = 0; i <= n_cols; i++) {
index->stat_n_diff_key_vals[i] = stat_n_diff_key_vals_tmp[i];
}
- dict_index_stat_mutex_exit(index);
}
/*===========================================*/
@@ -4424,11 +4452,9 @@ dict_store_statistics(
n_cols = dict_index_get_n_unique(index);
stat_n_diff_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
- dict_index_stat_mutex_enter(index);
for (i = 0; i <= n_cols; i++) {
stat_n_diff_key_vals_tmp[i] = index->stat_n_diff_key_vals[i];
}
- dict_index_stat_mutex_exit(index);
sys_stats = dict_sys->sys_stats;
sys_index = UT_LIST_GET_FIRST(sys_stats->indexes);
@@ -4504,12 +4530,13 @@ Calculates new estimates for table and index statistics. The statistics
are used in query optimization. */
UNIV_INTERN
void
-dict_update_statistics_low(
-/*=======================*/
+dict_update_statistics(
+/*===================*/
dict_table_t* table, /*!< in/out: table */
- ibool has_dict_mutex __attribute__((unused)),
- /*!< in: TRUE if the caller has the
- dictionary mutex */
+ ibool only_calc_if_missing_stats, /*!< in: only
+ update/recalc the stats if they have
+ not been initialized yet, otherwise
+ do nothing */
ibool sync) /*!< in: TRUE if must update SYS_STATS */
{
dict_index_t* index;
@@ -4528,6 +4555,8 @@ dict_update_statistics_low(
}
if (srv_use_sys_stats_table && !((table->flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY) && !sync) {
+ dict_table_stats_lock(table, RW_X_LATCH);
+
/* reload statistics from SYS_STATS table */
if (dict_reload_statistics(table, &sum_of_index_sizes)) {
/* success */
@@ -4537,6 +4566,8 @@ dict_update_statistics_low(
#endif
goto end;
}
+
+ dict_table_stats_unlock(table, RW_X_LATCH);
}
#ifdef UNIV_DEBUG
fprintf(stderr, "InnoDB: DEBUG: update_statistics for %s.\n",
@@ -4555,6 +4586,13 @@ dict_update_statistics_low(
return;
}
+ dict_table_stats_lock(table, RW_X_LATCH);
+
+ if (only_calc_if_missing_stats && table->stat_initialized) {
+ dict_table_stats_unlock(table, RW_X_LATCH);
+ return;
+ }
+
do {
if (table->is_corrupt) {
ut_a(srv_pass_corrupt_table);
@@ -4609,13 +4647,9 @@ dict_update_statistics_low(
end:
index = dict_table_get_first_index(table);
- dict_index_stat_mutex_enter(index);
-
table->stat_n_rows = index->stat_n_diff_key_vals[
dict_index_get_n_unique(index)];
- dict_index_stat_mutex_exit(index);
-
table->stat_clustered_index_size = index->stat_index_size;
table->stat_sum_of_other_index_sizes = sum_of_index_sizes
@@ -4624,19 +4658,8 @@ end:
table->stat_initialized = TRUE;
table->stat_modified_counter = 0;
-}
-/*********************************************************************//**
-Calculates new estimates for table and index statistics. The statistics
-are used in query optimization. */
-UNIV_INTERN
-void
-dict_update_statistics(
-/*===================*/
- dict_table_t* table, /*!< in/out: table */
- ibool sync)
-{
- dict_update_statistics_low(table, FALSE, sync);
+ dict_table_stats_unlock(table, RW_X_LATCH);
}
/**********************************************************************//**
@@ -4716,8 +4739,9 @@ dict_table_print_low(
ut_ad(mutex_own(&(dict_sys->mutex)));
- if (srv_stats_auto_update)
- dict_update_statistics_low(table, TRUE, FALSE);
+ dict_update_statistics(table, FALSE /* update even if initialized */, FALSE);
+
+ dict_table_stats_lock(table, RW_S_LATCH);
fprintf(stderr,
"--------------------------------------\n"
@@ -4746,6 +4770,8 @@ dict_table_print_low(
index = UT_LIST_GET_NEXT(indexes, index);
}
+ dict_table_stats_unlock(table, RW_S_LATCH);
+
foreign = UT_LIST_GET_FIRST(table->foreign_list);
while (foreign != NULL) {
@@ -4794,8 +4820,6 @@ dict_index_print_low(
ut_ad(mutex_own(&(dict_sys->mutex)));
- dict_index_stat_mutex_enter(index);
-
if (index->n_user_defined_cols > 0) {
n_vals = index->stat_n_diff_key_vals[
index->n_user_defined_cols];
@@ -4803,8 +4827,6 @@ dict_index_print_low(
n_vals = index->stat_n_diff_key_vals[1];
}
- dict_index_stat_mutex_exit(index);
-
fprintf(stderr,
" INDEX: name %s, id %lu %lu, fields %lu/%lu,"
" uniq %lu, type %lu\n"
@@ -5148,7 +5170,8 @@ void
dict_table_replace_index_in_foreign_list(
/*=====================================*/
dict_table_t* table, /*!< in/out: table */
- dict_index_t* index) /*!< in: index to be replaced */
+ dict_index_t* index, /*!< in: index to be replaced */
+ const trx_t* trx) /*!< in: transaction handle */
{
dict_foreign_t* foreign;
@@ -5159,7 +5182,13 @@ dict_table_replace_index_in_foreign_list(
if (foreign->foreign_index == index) {
dict_index_t* new_index
= dict_foreign_find_equiv_index(foreign);
- ut_a(new_index);
+
+ /* There must exist an alternative index if
+ check_foreigns (FOREIGN_KEY_CHECKS) is on,
+ since ha_innobase::prepare_drop_index had done
+ the check before we reach here. */
+
+ ut_a(new_index || !trx->check_foreigns);
foreign->foreign_index = new_index;
}
@@ -5293,8 +5322,8 @@ dict_close(void)
mem_free(dict_sys);
dict_sys = NULL;
- for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
- mutex_free(&dict_index_stat_mutex[i]);
+ for (i = 0; i < DICT_TABLE_STATS_LATCHES_SIZE; i++) {
+ rw_lock_free(&dict_table_stats_latches[i]);
}
}
diff --git a/storage/xtradb/dict/dict0load.c b/storage/xtradb/dict/dict0load.c
index 19de5bf8264..edd77e2530f 100644
--- a/storage/xtradb/dict/dict0load.c
+++ b/storage/xtradb/dict/dict0load.c
@@ -222,8 +222,9 @@ loop:
/* The table definition was corrupt if there
is no index */
- if (srv_stats_auto_update && dict_table_get_first_index(table)) {
- dict_update_statistics_low(table, TRUE, FALSE);
+ if (dict_table_get_first_index(table)) {
+ dict_update_statistics(table, FALSE /* update
+ even if initialized */, FALSE);
}
dict_table_print_low(table);
diff --git a/storage/xtradb/fil/fil0fil.c b/storage/xtradb/fil/fil0fil.c
index 926b1de3051..dd15576edf7 100644
--- a/storage/xtradb/fil/fil0fil.c
+++ b/storage/xtradb/fil/fil0fil.c
@@ -336,14 +336,15 @@ fil_get_space_id_for_table(
/*******************************************************************//**
Frees a space object from the tablespace memory cache. Closes the files in
the chain but does not delete them. There must not be any pending i/o's or
-flushes on the files. */
+flushes on the files.
+@return TRUE on success */
static
ibool
fil_space_free(
/*===========*/
- /* out: TRUE if success */
- ulint id, /* in: space id */
- ibool own_mutex);/* in: TRUE if own system->mutex */
+ ulint id, /* in: space id */
+ ibool x_latched); /* in: TRUE if caller has space->latch
+ in X mode */
/********************************************************************//**
Reads data from a space to a buffer. Remember that the possible incomplete
blocks at the end of file are ignored: they are not taken into account when
@@ -617,7 +618,7 @@ fil_node_create(
UT_LIST_ADD_LAST(chain, space->chain, node);
- if (id < SRV_LOG_SPACE_FIRST_ID && fil_system->max_assigned_id < id) {
+ if (id < SRV_EXTRA_SYS_SPACE_FIRST_ID && fil_system->max_assigned_id < id) {
fil_system->max_assigned_id = id;
}
@@ -1130,6 +1131,7 @@ try_again:
space = fil_space_get_by_name(name);
if (UNIV_LIKELY_NULL(space)) {
+ ibool success;
ulint namesake_id;
ut_print_timestamp(stderr);
@@ -1168,9 +1170,10 @@ try_again:
namesake_id = space->id;
- mutex_exit(&fil_system->mutex);
+ success = fil_space_free(namesake_id, FALSE);
+ ut_a(success);
- fil_space_free(namesake_id, FALSE);
+ mutex_exit(&fil_system->mutex);
goto try_again;
}
@@ -1205,6 +1208,7 @@ try_again:
space->mark = FALSE;
if (UNIV_LIKELY(purpose == FIL_TABLESPACE && !recv_recovery_on)
+ && UNIV_UNLIKELY(id < SRV_EXTRA_SYS_SPACE_FIRST_ID)
&& UNIV_UNLIKELY(id > fil_system->max_assigned_id)) {
if (!fil_system->space_id_reuse_warned) {
fil_system->space_id_reuse_warned = TRUE;
@@ -1290,7 +1294,7 @@ fil_assign_new_space_id(
(ulong) SRV_LOG_SPACE_FIRST_ID);
}
- success = (id < SRV_LOG_SPACE_FIRST_ID);
+ success = (id < SRV_EXTRA_SYS_SPACE_FIRST_ID);
if (success) {
*space_id = fil_system->max_assigned_id = id;
@@ -1323,15 +1327,14 @@ fil_space_free(
/*===========*/
/* out: TRUE if success */
ulint id, /* in: space id */
- ibool own_mutex) /* in: TRUE if own system->mutex */
+ ibool x_latched) /* in: TRUE if caller has space->latch
+ in X mode */
{
fil_space_t* space;
fil_space_t* namespace;
fil_node_t* fil_node;
- if (!own_mutex) {
- mutex_enter(&fil_system->mutex);
- }
+ ut_ad(mutex_own(&fil_system->mutex));
space = fil_space_get_by_id(id);
@@ -1342,8 +1345,6 @@ fil_space_free(
" from the cache but\n"
"InnoDB: it is not there.\n", (ulong) id);
- mutex_exit(&fil_system->mutex);
-
return(FALSE);
}
@@ -1378,8 +1379,8 @@ fil_space_free(
ut_a(0 == UT_LIST_GET_LEN(space->chain));
- if (!own_mutex) {
- mutex_exit(&fil_system->mutex);
+ if (x_latched) {
+ rw_lock_x_unlock(&space->latch);
}
rw_lock_free(&(space->latch));
@@ -1626,25 +1627,27 @@ fil_close_all_files(void)
/*=====================*/
{
fil_space_t* space;
- fil_node_t* node;
mutex_enter(&fil_system->mutex);
space = UT_LIST_GET_FIRST(fil_system->space_list);
while (space != NULL) {
+ fil_node_t* node;
fil_space_t* prev_space = space;
- node = UT_LIST_GET_FIRST(space->chain);
+ for (node = UT_LIST_GET_FIRST(space->chain);
+ node != NULL;
+ node = UT_LIST_GET_NEXT(chain, node)) {
- while (node != NULL) {
if (node->open) {
fil_node_close_file(node, fil_system);
}
- node = UT_LIST_GET_NEXT(chain, node);
}
+
space = UT_LIST_GET_NEXT(space_list, space);
- fil_space_free(prev_space->id, TRUE);
+
+ fil_space_free(prev_space->id, FALSE);
}
mutex_exit(&fil_system->mutex);
@@ -1666,6 +1669,10 @@ fil_set_max_space_id_if_bigger(
ut_error;
}
+ if (max_id >= SRV_EXTRA_SYS_SPACE_FIRST_ID) {
+ return;
+ }
+
mutex_enter(&fil_system->mutex);
if (fil_system->max_assigned_id < max_id) {
@@ -1684,6 +1691,7 @@ static
ulint
fil_write_lsn_and_arch_no_to_file(
/*==============================*/
+ ulint space_id,
ulint sum_of_sizes, /*!< in: combined size of previous files
in space, in database pages */
ib_uint64_t lsn, /*!< in: lsn to write */
@@ -1693,14 +1701,16 @@ fil_write_lsn_and_arch_no_to_file(
byte* buf1;
byte* buf;
+ ut_a(trx_sys_sys_space(space_id));
+
buf1 = mem_alloc(2 * UNIV_PAGE_SIZE);
buf = ut_align(buf1, UNIV_PAGE_SIZE);
- fil_read(TRUE, 0, 0, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL);
+ fil_read(TRUE, space_id, 0, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL);
mach_write_ull(buf + FIL_PAGE_FILE_FLUSH_LSN, lsn);
- fil_write(TRUE, 0, 0, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL);
+ fil_write(TRUE, space_id, 0, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL);
mem_free(buf1);
@@ -1736,7 +1746,7 @@ fil_write_flushed_lsn_to_data_files(
always open. */
if (space->purpose == FIL_TABLESPACE
- && space->id == 0) {
+ && trx_sys_sys_space(space->id)) {
sum_of_sizes = 0;
node = UT_LIST_GET_FIRST(space->chain);
@@ -1744,7 +1754,7 @@ fil_write_flushed_lsn_to_data_files(
mutex_exit(&fil_system->mutex);
err = fil_write_lsn_and_arch_no_to_file(
- sum_of_sizes, lsn, arch_log_no);
+ space->id, sum_of_sizes, lsn, arch_log_no);
if (err != DB_SUCCESS) {
return(err);
@@ -2264,6 +2274,19 @@ try_again:
path = mem_strdup(space->name);
mutex_exit(&fil_system->mutex);
+
+ /* Important: We rely on the data dictionary mutex to ensure
+ that a race is not possible here. It should serialize the tablespace
+ drop/free. We acquire an X latch only to avoid a race condition
+ when accessing the tablespace instance via:
+
+ fsp_get_available_space_in_free_extents().
+
+ There our main motivation is to reduce the contention on the
+ dictionary mutex. */
+
+ rw_lock_x_lock(&space->latch);
+
#ifndef UNIV_HOTBACKUP
/* Invalidate in the buffer pool all pages belonging to the
tablespace. Since we have set space->is_being_deleted = TRUE, readahead
@@ -2276,7 +2299,11 @@ try_again:
#endif
/* printf("Deleting tablespace %s id %lu\n", space->name, id); */
- success = fil_space_free(id, FALSE);
+ mutex_enter(&fil_system->mutex);
+
+ success = fil_space_free(id, TRUE);
+
+ mutex_exit(&fil_system->mutex);
if (success) {
success = os_file_delete(path);
@@ -2284,6 +2311,8 @@ try_again:
if (!success) {
success = os_file_delete_if_exists(path);
}
+ } else {
+ rw_lock_x_unlock(&space->latch);
}
if (success) {
@@ -2311,6 +2340,31 @@ try_again:
return(FALSE);
}
+/*******************************************************************//**
+Returns TRUE if a single-table tablespace is being deleted.
+@return TRUE if being deleted */
+UNIV_INTERN
+ibool
+fil_tablespace_is_being_deleted(
+/*============================*/
+ ulint id) /*!< in: space id */
+{
+ fil_space_t* space;
+ ibool is_being_deleted;
+
+ mutex_enter(&fil_system->mutex);
+
+ space = fil_space_get_by_id(id);
+
+ ut_a(space != NULL);
+
+ is_being_deleted = space->is_being_deleted;
+
+ mutex_exit(&fil_system->mutex);
+
+ return(is_being_deleted);
+}
+
#ifndef UNIV_HOTBACKUP
/*******************************************************************//**
Discards a single-table tablespace. The tablespace must be cached in the
@@ -3313,7 +3367,7 @@ skip_info:
}
if (page_is_corrupt) {
- fprintf(stderr, " [errp:%lld]", (longlong) (offset / UNIV_PAGE_SIZE));
+ fprintf(stderr, " [errp:%ld]", (long) (offset / UNIV_PAGE_SIZE));
/* cannot treat corrupt page */
goto skip_write;
@@ -5342,7 +5396,7 @@ fil_page_get_type(
return(mach_read_from_2(page + FIL_PAGE_TYPE));
}
-/********************************************************************
+/****************************************************************//**
Initializes the tablespace memory cache. */
UNIV_INTERN
void
diff --git a/storage/xtradb/fsp/fsp0fsp.c b/storage/xtradb/fsp/fsp0fsp.c
index cd28186109f..44ebe6819b7 100644
--- a/storage/xtradb/fsp/fsp0fsp.c
+++ b/storage/xtradb/fsp/fsp0fsp.c
@@ -3126,13 +3126,63 @@ fsp_get_available_space_in_free_extents(
ut_ad(!mutex_own(&kernel_mutex));
+ /* The convoluted mutex acquire is to overcome latching order
+ issues: The problem is that the fil_mutex is at a lower level
+ than the tablespace latch and the buffer pool mutex. We have to
+ first prevent any operations on the file system by acquiring the
+ dictionary mutex. Then acquire the tablespace latch to obey the
+ latching order and then release the dictionary mutex. That way we
+ ensure that the tablespace instance can't be freed while we are
+ examining its contents (see fil_space_free()).
+
+ However, there is one further complication, we release the fil_mutex
+ when we need to invalidate the the pages in the buffer pool and we
+ reacquire the fil_mutex when deleting and freeing the tablespace
+ instance in fil0fil.c. Here we need to account for that situation
+ too. */
+
+ mutex_enter(&dict_sys->mutex);
+
+ /* At this stage there is no guarantee that the tablespace even
+ exists in the cache. */
+
+ if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) {
+
+ mutex_exit(&dict_sys->mutex);
+
+ return(ULLINT_UNDEFINED);
+ }
+
mtr_start(&mtr);
latch = fil_space_get_latch(space, &flags);
+
+ /* This should ensure that the tablespace instance can't be freed
+ by another thread. However, the tablespace pages can still be freed
+ from the buffer pool. We need to check for that again. */
+
zip_size = dict_table_flags_to_zip_size(flags);
mtr_x_lock(latch, &mtr);
+ mutex_exit(&dict_sys->mutex);
+
+ /* At this point it is possible for the tablespace to be deleted and
+ its pages removed from the buffer pool. We need to check for that
+ situation. However, the tablespace instance can't be deleted because
+ our latching above should ensure that. */
+
+ if (fil_tablespace_is_being_deleted(space)) {
+
+ mtr_commit(&mtr);
+
+ return(ULLINT_UNDEFINED);
+ }
+
+ /* From here on even if the user has dropped the tablespace, the
+ pages _must_ still exist in the buffer pool and the tablespace
+ instance _must_ be in the file system hash table. */
+
space_header = fsp_get_space_header(space, zip_size, &mtr);
size = mtr_read_ulint(space_header + FSP_SIZE, MLOG_4BYTES, &mtr);
@@ -3305,7 +3355,7 @@ fseg_free_page_low(
"InnoDB: database!\n", (ulong) page);
crash:
fputs("InnoDB: Please refer to\n"
- "InnoDB: " REFMAN "forcing-recovery.html\n"
+ "InnoDB: " REFMAN "forcing-innodb-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
ut_error;
}
diff --git a/storage/xtradb/ha/hash0hash.c b/storage/xtradb/ha/hash0hash.c
index 30c304dafcd..0f4fc55d895 100644
--- a/storage/xtradb/ha/hash0hash.c
+++ b/storage/xtradb/ha/hash0hash.c
@@ -128,6 +128,70 @@ hash_create(
}
/*************************************************************//**
+*/
+UNIV_INTERN
+ulint
+hash_create_needed(
+/*===============*/
+ ulint n)
+{
+ ulint prime;
+ ulint offset;
+
+ prime = ut_find_prime(n);
+
+ offset = (sizeof(hash_table_t) + 7) / 8;
+ offset *= 8;
+
+ return(offset + sizeof(hash_cell_t) * prime);
+}
+
+UNIV_INTERN
+void
+hash_create_init(
+/*=============*/
+ hash_table_t* table,
+ ulint n)
+{
+ ulint prime;
+ ulint offset;
+
+ prime = ut_find_prime(n);
+
+ offset = (sizeof(hash_table_t) + 7) / 8;
+ offset *= 8;
+
+ table->array = (hash_cell_t*)(((byte*)table) + offset);
+ table->n_cells = prime;
+# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ table->adaptive = FALSE;
+# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+ table->n_mutexes = 0;
+ table->mutexes = NULL;
+ table->heaps = NULL;
+ table->heap = NULL;
+ ut_d(table->magic_n = HASH_TABLE_MAGIC_N);
+
+ /* Initialize the cell array */
+ hash_table_clear(table);
+}
+
+UNIV_INTERN
+void
+hash_create_reuse(
+/*==============*/
+ hash_table_t* table)
+{
+ ulint offset;
+
+ offset = (sizeof(hash_table_t) + 7) / 8;
+ offset *= 8;
+
+ table->array = (hash_cell_t*)(((byte*)table) + offset);
+ ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
+}
+
+/*************************************************************//**
Frees a hash table. */
UNIV_INTERN
void
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index b595da58b85..a55cd92fc86 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -155,6 +155,7 @@ static ulong innobase_read_io_threads;
static ulong innobase_write_io_threads;
static ulong innobase_page_size;
+static ulong innobase_log_block_size;
static my_bool innobase_thread_concurrency_timer_based;
static long long innobase_buffer_pool_size, innobase_log_file_size;
@@ -200,6 +201,7 @@ static my_bool innobase_rollback_on_timeout = FALSE;
static my_bool innobase_create_status_file = FALSE;
static my_bool innobase_stats_on_metadata = TRUE;
static my_bool innobase_use_sys_stats_table = FALSE;
+static my_bool innobase_buffer_pool_shm_checksum = TRUE;
static char* internal_innobase_data_file_path = NULL;
@@ -2123,6 +2125,32 @@ innobase_init(
goto error;
}
+ srv_log_block_size = 0;
+ if (innobase_log_block_size != (1 << 9)) { /*!=512*/
+ uint n_shift;
+
+ fprintf(stderr,
+ "InnoDB: Warning: innodb_log_block_size has been changed from default value 512. (###EXPERIMENTAL### operation)\n");
+ for (n_shift = 9; n_shift <= UNIV_PAGE_SIZE_SHIFT_MAX; n_shift++) {
+ if (innobase_log_block_size == ((ulong)1 << n_shift)) {
+ srv_log_block_size = (1 << n_shift);
+ fprintf(stderr,
+ "InnoDB: The log block size is set to %lu.\n",
+ srv_log_block_size);
+ break;
+ }
+ }
+ } else {
+ srv_log_block_size = 512;
+ }
+
+ if (!srv_log_block_size) {
+ fprintf(stderr,
+ "InnoDB: Error: %lu is not valid value for innodb_log_block_size.\n",
+ innobase_log_block_size);
+ goto error;
+ }
+
#ifndef MYSQL_SERVER
innodb_overwrite_relay_log_info = FALSE;
#endif
@@ -2426,7 +2454,7 @@ innobase_change_buffering_inited_ok:
srv_n_write_io_threads = (ulint) innobase_write_io_threads;
srv_read_ahead &= 3;
- srv_adaptive_checkpoint %= 3;
+ srv_adaptive_checkpoint %= 4;
srv_force_recovery = (ulint) innobase_force_recovery;
@@ -2435,6 +2463,7 @@ innobase_change_buffering_inited_ok:
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
srv_use_checksums = (ibool) innobase_use_checksums;
srv_fast_checksum = (ibool) innobase_fast_checksum;
+ srv_buffer_pool_shm_checksum = (ibool) innobase_buffer_pool_shm_checksum;
#ifdef HAVE_LARGE_PAGES
if ((os_use_large_pages = (ibool) my_use_large_pages))
@@ -3880,6 +3909,7 @@ retry:
of length ref_length! */
if (!row_table_got_default_clust_index(ib_table)) {
+
prebuilt->clust_index_was_generated = FALSE;
if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
@@ -6448,6 +6478,16 @@ create_table_def(
DBUG_RETURN(HA_ERR_GENERIC);
}
+ /* MySQL does the name length check. But we do additional check
+ on the name length here */
+ if (strlen(table_name) > MAX_FULL_NAME_LEN) {
+ push_warning_printf(
+ (THD*) trx->mysql_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TABLE_NAME,
+ "InnoDB: Table Name or Database Name is too long");
+ DBUG_RETURN(ER_TABLE_NAME);
+ }
+
n_cols = form->s->fields;
/* We pass 0 as the space id, and determine at a lower level the space
@@ -6732,6 +6772,60 @@ create_clustered_index_when_no_primary(
}
/*****************************************************************//**
+Return a display name for the row format
+@return row format name */
+UNIV_INTERN
+const char*
+get_row_format_name(
+/*================*/
+ enum row_type row_format) /*!< in: Row Format */
+{
+ switch (row_format) {
+ case ROW_TYPE_COMPACT:
+ return("COMPACT");
+ case ROW_TYPE_COMPRESSED:
+ return("COMPRESSED");
+ case ROW_TYPE_DYNAMIC:
+ return("DYNAMIC");
+ case ROW_TYPE_REDUNDANT:
+ return("REDUNDANT");
+ case ROW_TYPE_DEFAULT:
+ return("DEFAULT");
+ case ROW_TYPE_FIXED:
+ return("FIXED");
+ case ROW_TYPE_PAGE:
+ case ROW_TYPE_NOT_USED:
+ break;
+ }
+ return("NOT USED");
+}
+
+/** If file-per-table is missing, issue warning and set ret false */
+#define CHECK_ERROR_ROW_TYPE_NEEDS_FILE_PER_TABLE \
+ if (!srv_file_per_table) { \
+ push_warning_printf( \
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN, \
+ ER_ILLEGAL_HA_CREATE_OPTION, \
+ "InnoDB: ROW_FORMAT=%s requires" \
+ " innodb_file_per_table.", \
+ get_row_format_name(row_format)); \
+ ret = FALSE; \
+ }
+
+/** If file-format is Antelope, issue warning and set ret false */
+#define CHECK_ERROR_ROW_TYPE_NEEDS_GT_ANTELOPE \
+ if (srv_file_format < DICT_TF_FORMAT_ZIP) { \
+ push_warning_printf( \
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN, \
+ ER_ILLEGAL_HA_CREATE_OPTION, \
+ "InnoDB: ROW_FORMAT=%s requires" \
+ " innodb_file_format > Antelope.", \
+ get_row_format_name(row_format)); \
+ ret = FALSE; \
+ }
+
+
+/*****************************************************************//**
Validates the create options. We may build on this function
in future. For now, it checks two specifiers:
KEY_BLOCK_SIZE and ROW_FORMAT
@@ -6746,9 +6840,9 @@ create_options_are_valid(
columns and indexes */
HA_CREATE_INFO* create_info) /*!< in: create info. */
{
- ibool kbs_specified = FALSE;
+ ibool kbs_specified = FALSE;
ibool ret = TRUE;
-
+ enum row_type row_format = form->s->row_type;
ut_ad(thd != NULL);
@@ -6760,10 +6854,8 @@ create_options_are_valid(
ut_ad(form != NULL);
ut_ad(create_info != NULL);
- /* First check if KEY_BLOCK_SIZE was specified. */
- if (create_info->key_block_size
- || (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) {
-
+ /* First check if a non-zero KEY_BLOCK_SIZE was specified. */
+ if (create_info->key_block_size) {
kbs_specified = TRUE;
switch (create_info->key_block_size) {
case 1:
@@ -6771,127 +6863,71 @@ create_options_are_valid(
case 4:
case 8:
case 16:
- /* Valid value. */
- break;
- default:
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: invalid"
- " KEY_BLOCK_SIZE = %lu."
- " Valid values are"
- " [1, 2, 4, 8, 16]",
- create_info->key_block_size);
- ret = FALSE;
- }
- }
-
- /* If KEY_BLOCK_SIZE was specified, check for its
- dependencies. */
- if (kbs_specified && !srv_file_per_table) {
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: KEY_BLOCK_SIZE"
- " requires innodb_file_per_table.");
- ret = FALSE;
- }
-
- if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) {
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: KEY_BLOCK_SIZE"
- " requires innodb_file_format >"
- " Antelope.");
- ret = FALSE;
- }
-
- /* Now check for ROW_FORMAT specifier. */
- if (create_info->used_fields & HA_CREATE_USED_ROW_FORMAT) {
- switch (form->s->row_type) {
- const char* row_format_name;
- case ROW_TYPE_COMPRESSED:
- case ROW_TYPE_DYNAMIC:
- row_format_name
- = form->s->row_type == ROW_TYPE_COMPRESSED
- ? "COMPRESSED"
- : "DYNAMIC";
-
- /* These two ROW_FORMATs require srv_file_per_table
- and srv_file_format > Antelope */
+ /* Valid KEY_BLOCK_SIZE, check its dependencies. */
if (!srv_file_per_table) {
- push_warning_printf(
- thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: ROW_FORMAT=%s"
- " requires innodb_file_per_table.",
- row_format_name);
- ret = FALSE;
+ "InnoDB: KEY_BLOCK_SIZE requires"
+ " innodb_file_per_table.");
+ ret = FALSE;
}
-
if (srv_file_format < DICT_TF_FORMAT_ZIP) {
- push_warning_printf(
- thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: ROW_FORMAT=%s"
- " requires innodb_file_format >"
- " Antelope.",
- row_format_name);
- ret = FALSE;
- }
-
- /* Cannot specify KEY_BLOCK_SIZE with
- ROW_FORMAT = DYNAMIC.
- However, we do allow COMPRESSED to be
- specified with KEY_BLOCK_SIZE. */
- if (kbs_specified
- && form->s->row_type == ROW_TYPE_DYNAMIC) {
- push_warning_printf(
- thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: cannot specify"
- " ROW_FORMAT = DYNAMIC with"
- " KEY_BLOCK_SIZE.");
+ "InnoDB: KEY_BLOCK_SIZE requires"
+ " innodb_file_format > Antelope.");
ret = FALSE;
}
-
break;
-
- case ROW_TYPE_REDUNDANT:
- case ROW_TYPE_COMPACT:
- case ROW_TYPE_DEFAULT:
- /* Default is COMPACT. */
- row_format_name
- = form->s->row_type == ROW_TYPE_REDUNDANT
- ? "REDUNDANT"
- : "COMPACT";
-
- /* Cannot specify KEY_BLOCK_SIZE with these
- format specifiers. */
- if (kbs_specified) {
- push_warning_printf(
- thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: cannot specify"
- " ROW_FORMAT = %s with"
- " KEY_BLOCK_SIZE.",
- row_format_name);
- ret = FALSE;
- }
-
- break;
-
default:
- push_warning(thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: invalid ROW_FORMAT specifier.");
+ push_warning_printf(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION,
+ "InnoDB: invalid KEY_BLOCK_SIZE = %lu."
+ " Valid values are [1, 2, 4, 8, 16]",
+ create_info->key_block_size);
ret = FALSE;
-
+ break;
}
}
+
+ /* Check for a valid Innodb ROW_FORMAT specifier and
+ other incompatibilities. */
+ switch (row_format) {
+ case ROW_TYPE_COMPRESSED:
+ CHECK_ERROR_ROW_TYPE_NEEDS_FILE_PER_TABLE;
+ CHECK_ERROR_ROW_TYPE_NEEDS_GT_ANTELOPE;
+ break;
+ case ROW_TYPE_DYNAMIC:
+ CHECK_ERROR_ROW_TYPE_NEEDS_FILE_PER_TABLE;
+ CHECK_ERROR_ROW_TYPE_NEEDS_GT_ANTELOPE;
+ /* fall through since dynamic also shuns KBS */
+ case ROW_TYPE_COMPACT:
+ case ROW_TYPE_REDUNDANT:
+ if (kbs_specified) {
+ push_warning_printf(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION,
+ "InnoDB: cannot specify ROW_FORMAT = %s"
+ " with KEY_BLOCK_SIZE.",
+ get_row_format_name(row_format));
+ ret = FALSE;
+ }
+ break;
+ case ROW_TYPE_DEFAULT:
+ break;
+ case ROW_TYPE_FIXED:
+ case ROW_TYPE_PAGE:
+ case ROW_TYPE_NOT_USED:
+ push_warning(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION, \
+ "InnoDB: invalid ROW_FORMAT specifier.");
+ ret = FALSE;
+ break;
+ }
return(ret);
}
@@ -6940,7 +6976,7 @@ ha_innobase::create(
const ulint file_format = srv_file_format;
const char* stmt;
size_t stmt_len;
- enum row_type row_type;
+ enum row_type row_format;
DBUG_ENTER("ha_innobase::create");
@@ -7016,8 +7052,7 @@ ha_innobase::create(
goto cleanup;
}
- if (create_info->key_block_size
- || (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) {
+ if (create_info->key_block_size) {
/* Determine the page_zip.ssize corresponding to the
requested page size (key_block_size) in kilobytes. */
@@ -7038,40 +7073,40 @@ ha_innobase::create(
}
if (!srv_file_per_table) {
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: KEY_BLOCK_SIZE"
- " requires innodb_file_per_table.");
+ push_warning(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION,
+ "InnoDB: KEY_BLOCK_SIZE requires"
+ " innodb_file_per_table.");
flags = 0;
}
if (file_format < DICT_TF_FORMAT_ZIP) {
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: KEY_BLOCK_SIZE"
- " requires innodb_file_format >"
- " Antelope.");
+ push_warning(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION,
+ "InnoDB: KEY_BLOCK_SIZE requires"
+ " innodb_file_format > Antelope.");
flags = 0;
}
if (!flags) {
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: ignoring"
- " KEY_BLOCK_SIZE=%lu.",
- create_info->key_block_size);
+ push_warning_printf(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION,
+ "InnoDB: ignoring KEY_BLOCK_SIZE=%lu.",
+ create_info->key_block_size);
}
}
- row_type = form->s->row_type;
+ row_format = form->s->row_type;
if (flags) {
- /* if KEY_BLOCK_SIZE was specified on this statement and
- ROW_FORMAT was not, automatically change ROW_FORMAT to COMPRESSED.*/
- if ( (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)
- && !(create_info->used_fields & HA_CREATE_USED_ROW_FORMAT)) {
- row_type = ROW_TYPE_COMPRESSED;
- } else if (row_type != ROW_TYPE_COMPRESSED) {
+ /* if ROW_FORMAT is set to default,
+ automatically change it to COMPRESSED.*/
+ if (row_format == ROW_TYPE_DEFAULT) {
+ row_format = ROW_TYPE_COMPRESSED;
+ } else if (row_format != ROW_TYPE_COMPRESSED) {
/* ROW_FORMAT other than COMPRESSED
ignores KEY_BLOCK_SIZE. It does not
make sense to reject conflicting
@@ -7079,8 +7114,7 @@ ha_innobase::create(
such combinations can be obtained
with ALTER TABLE anyway. */
push_warning_printf(
- thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ignoring KEY_BLOCK_SIZE=%lu"
" unless ROW_FORMAT=COMPRESSED.",
@@ -7089,7 +7123,7 @@ ha_innobase::create(
}
} else {
/* flags == 0 means no KEY_BLOCK_SIZE.*/
- if (row_type == ROW_TYPE_COMPRESSED) {
+ if (row_format == ROW_TYPE_COMPRESSED) {
/* ROW_FORMAT=COMPRESSED without
KEY_BLOCK_SIZE implies half the
maximum KEY_BLOCK_SIZE. */
@@ -7104,49 +7138,40 @@ ha_innobase::create(
}
}
- switch (row_type) {
- const char* row_format_name;
+ switch (row_format) {
case ROW_TYPE_REDUNDANT:
break;
case ROW_TYPE_COMPRESSED:
case ROW_TYPE_DYNAMIC:
- row_format_name
- = row_type == ROW_TYPE_COMPRESSED
- ? "COMPRESSED"
- : "DYNAMIC";
-
if (!srv_file_per_table) {
push_warning_printf(
- thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: ROW_FORMAT=%s"
- " requires innodb_file_per_table.",
- row_format_name);
+ "InnoDB: ROW_FORMAT=%s requires"
+ " innodb_file_per_table.",
+ get_row_format_name(row_format));
} else if (file_format < DICT_TF_FORMAT_ZIP) {
push_warning_printf(
- thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: ROW_FORMAT=%s"
- " requires innodb_file_format >"
- " Antelope.",
- row_format_name);
+ "InnoDB: ROW_FORMAT=%s requires"
+ " innodb_file_format > Antelope.",
+ get_row_format_name(row_format));
} else {
flags |= DICT_TF_COMPACT
- | (DICT_TF_FORMAT_ZIP
- << DICT_TF_FORMAT_SHIFT);
+ | (DICT_TF_FORMAT_ZIP
+ << DICT_TF_FORMAT_SHIFT);
break;
}
/* fall through */
case ROW_TYPE_NOT_USED:
case ROW_TYPE_FIXED:
- default:
- push_warning(thd,
- MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA_CREATE_OPTION,
- "InnoDB: assuming ROW_FORMAT=COMPACT.");
+ case ROW_TYPE_PAGE:
+ push_warning(
+ thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION,
+ "InnoDB: assuming ROW_FORMAT=COMPACT.");
case ROW_TYPE_DEFAULT:
case ROW_TYPE_COMPACT:
flags = DICT_TF_COMPACT;
@@ -7260,23 +7285,25 @@ ha_innobase::create(
setup at this stage and so we use thd. */
/* We need to copy the AUTOINC value from the old table if
- this is an ALTER TABLE or CREATE INDEX because CREATE INDEX
- does a table copy too. */
+ this is an ALTER|OPTIMIZE TABLE or CREATE INDEX because CREATE INDEX
+ does a table copy too. If query was one of :
+
+ CREATE TABLE ...AUTO_INCREMENT = x; or
+ ALTER TABLE...AUTO_INCREMENT = x; or
+ OPTIMIZE TABLE t; or
+ CREATE INDEX x on t(...);
+
+ Find out a table definition from the dictionary and get
+ the current value of the auto increment field. Set a new
+ value to the auto increment field if the value is greater
+ than the maximum value in the column. */
if (((create_info->used_fields & HA_CREATE_USED_AUTO)
|| thd_sql_command(thd) == SQLCOM_ALTER_TABLE
+ || thd_sql_command(thd) == SQLCOM_OPTIMIZE
|| thd_sql_command(thd) == SQLCOM_CREATE_INDEX)
&& create_info->auto_increment_value > 0) {
- /* Query was one of :
- CREATE TABLE ...AUTO_INCREMENT = x; or
- ALTER TABLE...AUTO_INCREMENT = x; or
- CREATE INDEX x on t(...);
- Find out a table definition from the dictionary and get
- the current value of the auto increment field. Set a new
- value to the auto increment field if the value is greater
- than the maximum value in the column. */
-
auto_inc_value = create_info->auto_increment_value;
dict_table_autoinc_lock(innobase_table);
@@ -7329,6 +7356,14 @@ ha_innobase::discard_or_import_tablespace(
err = row_discard_tablespace_for_mysql(dict_table->name, trx);
} else {
err = row_import_tablespace_for_mysql(dict_table->name, trx);
+
+ /* in expanded import mode re-initialize auto_increment again */
+ if ((err == DB_SUCCESS) && srv_expand_import &&
+ (table->found_next_number_field != NULL)) {
+ dict_table_autoinc_lock(dict_table);
+ innobase_initialize_autoinc();
+ dict_table_autoinc_unlock(dict_table);
+ }
}
err = convert_error_code_to_mysql(err, dict_table->flags, NULL);
@@ -7794,6 +7829,7 @@ ha_innobase::estimate_rows_upper_bound(void)
dict_index_t* index;
ulonglong estimate;
ulonglong local_data_file_length;
+ ulint stat_n_leaf_pages;
DBUG_ENTER("estimate_rows_upper_bound");
@@ -7813,10 +7849,12 @@ ha_innobase::estimate_rows_upper_bound(void)
index = dict_table_get_first_index(prebuilt->table);
- ut_a(index->stat_n_leaf_pages > 0);
+ stat_n_leaf_pages = index->stat_n_leaf_pages;
+
+ ut_a(stat_n_leaf_pages > 0);
local_data_file_length =
- ((ulonglong) index->stat_n_leaf_pages) * UNIV_PAGE_SIZE;
+ ((ulonglong) stat_n_leaf_pages) * UNIV_PAGE_SIZE;
/* Calculate a minimum length for a clustered index record and from
@@ -8019,13 +8057,12 @@ ha_innobase::info_low(
ib_table = prebuilt->table;
if (flag & HA_STATUS_TIME) {
- if ((called_from_analyze || innobase_stats_on_metadata)
- && !share->ib_table->is_corrupt) {
+ if ((called_from_analyze || innobase_stats_on_metadata) && !share->ib_table->is_corrupt) {
/* In sql_show we call with this flag: update
then statistics so that they are up-to-date */
if (srv_use_sys_stats_table && !((ib_table->flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY)
- && thd_sql_command(user_thd) == SQLCOM_ANALYZE) {
+ && called_from_analyze) {
/* If the indexes on the table don't have enough rows in SYS_STATS system table, */
/* they need to be created. */
dict_index_t* index;
@@ -8047,7 +8084,8 @@ ha_innobase::info_low(
prebuilt->trx->op_info = "updating table statistics";
dict_update_statistics(ib_table,
- (thd_sql_command(user_thd) == SQLCOM_ANALYZE)?TRUE:FALSE);
+ FALSE /* update even if stats
+ are initialized */, called_from_analyze);
prebuilt->trx->op_info = "returning various info to MySQL";
}
@@ -8066,6 +8104,9 @@ ha_innobase::info_low(
}
if (flag & HA_STATUS_VARIABLE) {
+
+ dict_table_stats_lock(ib_table, RW_S_LATCH);
+
n_rows = ib_table->stat_n_rows;
/* Because we do not protect stat_n_rows by any mutex in a
@@ -8115,12 +8156,14 @@ ha_innobase::info_low(
ib_table->stat_sum_of_other_index_sizes)
* UNIV_PAGE_SIZE;
+ dict_table_stats_unlock(ib_table, RW_S_LATCH);
+
/* Since fsp_get_available_space_in_free_extents() is
acquiring latches inside InnoDB, we do not call it if we
are asked by MySQL to avoid locking. Another reason to
avoid the call is that it uses quite a lot of CPU.
See Bug#38185. */
- if (flag & HA_STATUS_NO_LOCK) {
+ if (flag & HA_STATUS_NO_LOCK || !srv_stats_update_need_lock) {
/* We do not update delete_length if no
locking is requested so the "old" value can
remain. delete_length is initialized to 0 in
@@ -8130,21 +8173,13 @@ ha_innobase::info_low(
/* Avoid accessing the tablespace if
innodb_crash_recovery is set to a high value. */
stats.delete_length = 0;
- } else if (srv_stats_update_need_lock) {
-
- /* lock the data dictionary to avoid races with
- ibd_file_missing and tablespace_discarded */
- row_mysql_lock_data_dictionary(prebuilt->trx);
+ } else {
+ ullint avail_space;
- /* ib_table->space must be an existent tablespace */
- if (!ib_table->ibd_file_missing
- && !ib_table->tablespace_discarded) {
-
- stats.delete_length =
- fsp_get_available_space_in_free_extents(
- ib_table->space) * 1024;
- } else {
+ avail_space = fsp_get_available_space_in_free_extents(
+ ib_table->space);
+ if (avail_space == ULLINT_UNDEFINED) {
THD* thd;
thd = ha_thd();
@@ -8161,9 +8196,9 @@ ha_innobase::info_low(
ib_table->name);
stats.delete_length = 0;
+ } else {
+ stats.delete_length = avail_space * 1024;
}
-
- row_mysql_unlock_data_dictionary(prebuilt->trx);
}
stats.check_time = 0;
@@ -8193,6 +8228,8 @@ ha_innobase::info_low(
table->s->keys);
}
+ dict_table_stats_lock(ib_table, RW_S_LATCH);
+
for (i = 0; i < table->s->keys; i++) {
ulong j;
/* We could get index quickly through internal
@@ -8230,8 +8267,6 @@ ha_innobase::info_low(
break;
}
- dict_index_stat_mutex_enter(index);
-
if (index->stat_n_diff_key_vals[j + 1] == 0) {
rec_per_key = stats.records;
@@ -8240,8 +8275,6 @@ ha_innobase::info_low(
index->stat_n_diff_key_vals[j + 1]);
}
- dict_index_stat_mutex_exit(index);
-
/* Since MySQL seems to favor table scans
too much over index searches, we pretend
index selectivity is 2 times better than
@@ -8258,6 +8291,8 @@ ha_innobase::info_low(
(ulong) rec_per_key;
}
}
+
+ dict_table_stats_unlock(ib_table, RW_S_LATCH);
}
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
@@ -11249,6 +11284,11 @@ static MYSQL_SYSVAR_ULONG(page_size, innobase_page_size,
"###EXPERIMENTAL###: The universal page size of the database. Changing for created database is not supported. Use on your own risk!",
NULL, NULL, (1 << 14), (1 << 12), (1 << UNIV_PAGE_SIZE_SHIFT_MAX), 0);
+static MYSQL_SYSVAR_ULONG(log_block_size, innobase_log_block_size,
+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
+ "###EXPERIMENTAL###: The log block size of the transaction log file. Changing for created log file is not supported. Use on your own risk!",
+ NULL, NULL, (1 << 9)/*512*/, (1 << 9)/*512*/, (1 << UNIV_PAGE_SIZE_SHIFT_MAX), 0);
+
static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
PLUGIN_VAR_READONLY,
"The common part for InnoDB table spaces.",
@@ -11467,6 +11507,16 @@ static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
NULL, NULL, 128*1024*1024L, 32*1024*1024L, LONGLONG_MAX, 1024*1024L);
+static MYSQL_SYSVAR_UINT(buffer_pool_shm_key, srv_buffer_pool_shm_key,
+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
+ "[experimental] The key value of shared memory segment for the buffer pool. 0 (default) disables the feature.",
+ NULL, NULL, 0, 0, INT_MAX32, 0);
+
+static MYSQL_SYSVAR_BOOL(buffer_pool_shm_checksum, innobase_buffer_pool_shm_checksum,
+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
+ "Enable buffer_pool_shm checksum validation (enabled by default).",
+ NULL, NULL, TRUE);
+
static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
PLUGIN_VAR_RQCMDARG,
"Helps in performance tuning in heavily concurrent environments.",
@@ -11677,17 +11727,19 @@ innodb_adaptive_checkpoint_update(
void* var_ptr,
const void* save)
{
- *(long *)var_ptr= (*(long *)save) % 3;
+ *(long *)var_ptr= (*(long *)save) % 4;
}
const char *adaptive_checkpoint_names[]=
{
"none", /* 0 */
"reflex", /* 1 */
"estimate", /* 2 */
+ "keep_average", /* 3 */
/* For compatibility of the older patch */
- "0", /* 3 ("none" + 3) */
- "1", /* 4 ("reflex" + 3) */
- "2", /* 5 ("estimate" + 3) */
+ "0", /* 4 ("none" + 3) */
+ "1", /* 5 ("reflex" + 3) */
+ "2", /* 6 ("estimate" + 3) */
+ "3", /* 7 ("keep_average" + 4) */
NullS
};
TYPELIB adaptive_checkpoint_typelib=
@@ -11697,7 +11749,7 @@ TYPELIB adaptive_checkpoint_typelib=
};
static MYSQL_SYSVAR_ENUM(adaptive_checkpoint, srv_adaptive_checkpoint,
PLUGIN_VAR_RQCMDARG,
- "Enable/Disable flushing along modified age. (none, reflex, [estimate])",
+ "Enable/Disable flushing along modified age. (none, reflex, [estimate], keep_average)",
NULL, innodb_adaptive_checkpoint_update, 2, &adaptive_checkpoint_typelib);
static MYSQL_SYSVAR_ULONG(enable_unsafe_group_commit, srv_enable_unsafe_group_commit,
@@ -11736,9 +11788,12 @@ static MYSQL_SYSVAR_ULINT(pass_corrupt_table, srv_pass_corrupt_table,
static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(page_size),
+ MYSQL_SYSVAR(log_block_size),
MYSQL_SYSVAR(additional_mem_pool_size),
MYSQL_SYSVAR(autoextend_increment),
MYSQL_SYSVAR(buffer_pool_size),
+ MYSQL_SYSVAR(buffer_pool_shm_key),
+ MYSQL_SYSVAR(buffer_pool_shm_checksum),
MYSQL_SYSVAR(checksums),
MYSQL_SYSVAR(fast_checksum),
MYSQL_SYSVAR(commit_concurrency),
diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc
index 3a32ed9cf36..c54b4a17fd2 100644
--- a/storage/xtradb/handler/handler0alter.cc
+++ b/storage/xtradb/handler/handler0alter.cc
@@ -1012,12 +1012,13 @@ ha_innobase::prepare_drop_index(
index->to_be_dropped = TRUE;
}
- /* If FOREIGN_KEY_CHECK = 1 you may not drop an index defined
+ /* If FOREIGN_KEY_CHECKS = 1 you may not drop an index defined
for a foreign key constraint because InnoDB requires that both
- tables contain indexes for the constraint. Note that CREATE
- INDEX id ON table does a CREATE INDEX and DROP INDEX, and we
- can ignore here foreign keys because a new index for the
- foreign key has already been created.
+ tables contain indexes for the constraint. Such index can
+ be dropped only if FOREIGN_KEY_CHECKS is set to 0.
+ Note that CREATE INDEX id ON table does a CREATE INDEX and
+ DROP INDEX, and we can ignore here foreign keys because a
+ new index for the foreign key has already been created.
We check for the foreign key constraints after marking the
candidate indexes for deletion, because when we check for an
diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc
index 0793daf7650..dead374e782 100644
--- a/storage/xtradb/handler/i_s.cc
+++ b/storage/xtradb/handler/i_s.cc
@@ -1451,8 +1451,16 @@ fill_innodb_trx_from_cache(
row->trx_mysql_thread_id));
/* trx_query */
- OK(field_store_string(fields[IDX_TRX_QUERY],
- row->trx_query));
+ if (row->trx_query) {
+ /* store will do appropriate character set
+ conversion check */
+ fields[IDX_TRX_QUERY]->store(
+ row->trx_query, strlen(row->trx_query),
+ row->trx_query_cs);
+ fields[IDX_TRX_QUERY]->set_notnull();
+ } else {
+ fields[IDX_TRX_QUERY]->set_null();
+ }
OK(schema_table_store_record(thd, table));
}
@@ -1709,16 +1717,7 @@ fill_innodb_locks_from_cache(
for (i = 0; i < rows_num; i++) {
i_s_locks_row_t* row;
-
- /* note that the decoded database or table name is
- never expected to be longer than NAME_LEN;
- NAME_LEN for database name
- 2 for surrounding quotes around database name
- NAME_LEN for table name
- 2 for surrounding quotes around table name
- 1 for the separating dot (.)
- 9 for the #mysql50# prefix */
- char buf[2 * NAME_LEN + 14];
+ char buf[MAX_FULL_NAME_LEN + 1];
const char* bufend;
char lock_trx_id[TRX_ID_MAX_LEN + 1];
diff --git a/storage/xtradb/handler/innodb_patch_info.h b/storage/xtradb/handler/innodb_patch_info.h
index 38b97411340..e68f12d0fec 100644
--- a/storage/xtradb/handler/innodb_patch_info.h
+++ b/storage/xtradb/handler/innodb_patch_info.h
@@ -47,5 +47,6 @@ struct innodb_enhancement {
{"innodb_fast_checksum","Using the checksum on 32bit-unit calculation","incompatible for unpatched ver.","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_files_extend","allow >4GB transaction log files, and can vary universal page size of datafiles","incompatible for unpatched ver.","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_sys_tables_sys_indexes","Expose InnoDB SYS_TABLES and SYS_INDEXES schema tables","","http://www.percona.com/docs/wiki/percona-xtradb"},
+{"innodb_buffer_pool_shm","Put buffer pool contents to shared memory segment and reuse it at clean restart [experimental]","","http://www.percona.com/docs/wiki/percona-xtradb"},
{NULL, NULL, NULL, NULL}
};
diff --git a/storage/xtradb/include/btr0btr.h b/storage/xtradb/include/btr0btr.h
index 5e6a76c7d21..dde3a0bab69 100644
--- a/storage/xtradb/include/btr0btr.h
+++ b/storage/xtradb/include/btr0btr.h
@@ -94,26 +94,35 @@ btr_root_get(
Gets a buffer page and declares its latching order level. */
UNIV_INLINE
buf_block_t*
-btr_block_get(
-/*==========*/
- ulint space, /*!< in: space id */
- ulint zip_size, /*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
- ulint page_no, /*!< in: page number */
- ulint mode, /*!< in: latch mode */
- mtr_t* mtr); /*!< in: mtr */
-/**************************************************************//**
-Gets a buffer page and declares its latching order level. */
-UNIV_INLINE
-page_t*
-btr_page_get(
-/*=========*/
- ulint space, /*!< in: space id */
- ulint zip_size, /*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
- ulint page_no, /*!< in: page number */
- ulint mode, /*!< in: latch mode */
- mtr_t* mtr); /*!< in: mtr */
+btr_block_get_func(
+/*===============*/
+ ulint space, /*!< in: space id */
+ ulint zip_size, /*!< in: compressed page size in bytes
+ or 0 for uncompressed pages */
+ ulint page_no, /*!< in: page number */
+ ulint mode, /*!< in: latch mode */
+ const char* file, /*!< in: file name */
+ ulint line, /*!< in: line where called */
+ mtr_t* mtr) /*!< in/out: mtr */
+ __attribute__((nonnull));
+/** Gets a buffer page and declares its latching order level.
+@param space tablespace identifier
+@param zip_size compressed page size in bytes or 0 for uncompressed pages
+@param page_no page number
+@param mode latch mode
+@param mtr mini-transaction handle
+@return the block descriptor */
+# define btr_block_get(space,zip_size,page_no,mode,mtr) \
+ btr_block_get_func(space,zip_size,page_no,mode,__FILE__,__LINE__,mtr)
+/** Gets a buffer page and declares its latching order level.
+@param space tablespace identifier
+@param zip_size compressed page size in bytes or 0 for uncompressed pages
+@param page_no page number
+@param mode latch mode
+@param mtr mini-transaction handle
+@return the uncompressed page frame */
+# define btr_page_get(space,zip_size,page_no,mode,mtr) \
+ buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,mtr))
#endif /* !UNIV_HOTBACKUP */
/**************************************************************//**
Gets the index id field of a page.
diff --git a/storage/xtradb/include/btr0btr.ic b/storage/xtradb/include/btr0btr.ic
index c9c38f3c3b3..e19c863300a 100644
--- a/storage/xtradb/include/btr0btr.ic
+++ b/storage/xtradb/include/btr0btr.ic
@@ -39,18 +39,21 @@ Created 6/2/1994 Heikki Tuuri
Gets a buffer page and declares its latching order level. */
UNIV_INLINE
buf_block_t*
-btr_block_get(
-/*==========*/
- ulint space, /*!< in: space id */
- ulint zip_size, /*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
- ulint page_no, /*!< in: page number */
- ulint mode, /*!< in: latch mode */
- mtr_t* mtr) /*!< in: mtr */
+btr_block_get_func(
+/*===============*/
+ ulint space, /*!< in: space id */
+ ulint zip_size, /*!< in: compressed page size in bytes
+ or 0 for uncompressed pages */
+ ulint page_no, /*!< in: page number */
+ ulint mode, /*!< in: latch mode */
+ const char* file, /*!< in: file name */
+ ulint line, /*!< in: line where called */
+ mtr_t* mtr) /*!< in/out: mtr */
{
buf_block_t* block;
- block = buf_page_get(space, zip_size, page_no, mode, mtr);
+ block = buf_page_get_gen(space, zip_size, page_no, mode,
+ NULL, BUF_GET, file, line, mtr);
ut_a(srv_pass_corrupt_table || block);
@@ -63,23 +66,6 @@ btr_block_get(
}
/**************************************************************//**
-Gets a buffer page and declares its latching order level. */
-UNIV_INLINE
-page_t*
-btr_page_get(
-/*=========*/
- ulint space, /*!< in: space id */
- ulint zip_size, /*!< in: compressed page size in bytes
- or 0 for uncompressed pages */
- ulint page_no, /*!< in: page number */
- ulint mode, /*!< in: latch mode */
- mtr_t* mtr) /*!< in: mtr */
-{
- return(buf_block_get_frame(btr_block_get(space, zip_size, page_no,
- mode, mtr)));
-}
-
-/**************************************************************//**
Sets the index id field of a page. */
UNIV_INLINE
void
diff --git a/storage/xtradb/include/btr0cur.h b/storage/xtradb/include/btr0cur.h
index 7f6bff11f84..b477ad0320a 100644
--- a/storage/xtradb/include/btr0cur.h
+++ b/storage/xtradb/include/btr0cur.h
@@ -332,10 +332,14 @@ ulint
btr_cur_del_mark_set_clust_rec(
/*===========================*/
ulint flags, /*!< in: undo logging and locking flags */
- btr_cur_t* cursor, /*!< in: cursor */
+ buf_block_t* block, /*!< in/out: buffer block of the record */
+ rec_t* rec, /*!< in/out: record */
+ dict_index_t* index, /*!< in: clustered index of the record */
+ const ulint* offsets,/*!< in: rec_get_offsets(rec) */
ibool val, /*!< in: value to set */
que_thr_t* thr, /*!< in: query thread */
- mtr_t* mtr); /*!< in: mtr */
+ mtr_t* mtr) /*!< in: mtr */
+ __attribute__((nonnull));
/***********************************************************//**
Sets a secondary index record delete mark to TRUE or FALSE.
@return DB_SUCCESS, DB_LOCK_WAIT, or error number */
@@ -481,46 +485,28 @@ btr_estimate_number_of_different_key_vals(
/*======================================*/
dict_index_t* index); /*!< in: index */
/*******************************************************************//**
-Marks not updated extern fields as not-owned by this record. The ownership
-is transferred to the updated record which is inserted elsewhere in the
+Marks non-updated off-page fields as disowned by this record. The ownership
+must be transferred to the updated record which is inserted elsewhere in the
index tree. In purge only the owner of externally stored field is allowed
-to free the field.
-@return TRUE if BLOB ownership was transferred */
+to free the field. */
UNIV_INTERN
-ibool
-btr_cur_mark_extern_inherited_fields(
-/*=================================*/
+void
+btr_cur_disown_inherited_fields(
+/*============================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
part will be updated, or NULL */
rec_t* rec, /*!< in/out: record in a clustered index */
dict_index_t* index, /*!< in: index of the page */
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
const upd_t* update, /*!< in: update vector */
- mtr_t* mtr); /*!< in: mtr, or NULL if not logged */
-/*******************************************************************//**
-The complement of the previous function: in an update entry may inherit
-some externally stored fields from a record. We must mark them as inherited
-in entry, so that they are not freed in a rollback. */
-UNIV_INTERN
-void
-btr_cur_mark_dtuple_inherited_extern(
-/*=================================*/
- dtuple_t* entry, /*!< in/out: updated entry to be
- inserted to clustered index */
- const upd_t* update); /*!< in: update vector */
-/*******************************************************************//**
-Marks all extern fields in a dtuple as owned by the record. */
-UNIV_INTERN
-void
-btr_cur_unmark_dtuple_extern_fields(
-/*================================*/
- dtuple_t* entry); /*!< in/out: clustered index entry */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((nonnull(2,3,4,5,6)));
/*******************************************************************//**
Stores the fields in big_rec_vec to the tablespace and puts pointers to
them in rec. The extern flags in rec will have to be set beforehand.
The fields are stored on pages allocated from leaf node
file segment of the index tree.
-@return DB_SUCCESS or error */
+@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN
ulint
btr_store_big_rec_extern_fields(
diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h
index d6cc63bb6af..e06927f42f0 100644
--- a/storage/xtradb/include/buf0buf.h
+++ b/storage/xtradb/include/buf0buf.h
@@ -36,6 +36,7 @@ Created 11/5/1995 Heikki Tuuri
#include "ut0rbt.h"
#ifndef UNIV_HOTBACKUP
#include "os0proc.h"
+#include "srv0srv.h"
/** @name Modes for buf_page_get_gen */
/* @{ */
@@ -1301,7 +1302,10 @@ struct buf_block_struct{
/**********************************************************************//**
Compute the hash fold value for blocks in buf_pool->zip_hash. */
/* @{ */
-#define BUF_POOL_ZIP_FOLD_PTR(ptr) ((ulint) (ptr) / UNIV_PAGE_SIZE)
+/* the fold should be relative when srv_buffer_pool_shm_key is enabled */
+#define BUF_POOL_ZIP_FOLD_PTR(ptr) (!srv_buffer_pool_shm_key\
+ ?((ulint) (ptr) / UNIV_PAGE_SIZE)\
+ :((ulint) ((byte*)ptr - (byte*)(buf_pool->chunks->blocks->frame)) / UNIV_PAGE_SIZE))
#define BUF_POOL_ZIP_FOLD(b) BUF_POOL_ZIP_FOLD_PTR((b)->frame)
#define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b))
/* @} */
diff --git a/storage/xtradb/include/data0data.h b/storage/xtradb/include/data0data.h
index f9fce3f3657..cab8d790ac1 100644
--- a/storage/xtradb/include/data0data.h
+++ b/storage/xtradb/include/data0data.h
@@ -154,14 +154,19 @@ dfield_dup(
dfield_t* field, /*!< in/out: data field */
mem_heap_t* heap); /*!< in: memory heap where allocated */
/*********************************************************************//**
-Tests if data length and content is equal for two dfields.
-@return TRUE if equal */
+Tests if two data fields are equal.
+If len==0, tests the data length and content for equality.
+If len>0, tests the first len bytes of the content for equality.
+@return TRUE if both fields are NULL or if they are equal */
UNIV_INLINE
ibool
dfield_datas_are_binary_equal(
/*==========================*/
const dfield_t* field1, /*!< in: field */
- const dfield_t* field2);/*!< in: field */
+ const dfield_t* field2, /*!< in: field */
+ ulint len) /*!< in: maximum prefix to compare,
+ or 0 to compare the whole field length */
+ __attribute__((nonnull, warn_unused_result));
/*********************************************************************//**
Tests if dfield data length and content is equal to the given.
@return TRUE if equal */
diff --git a/storage/xtradb/include/data0data.ic b/storage/xtradb/include/data0data.ic
index da79aa33702..74e0f7d09a0 100644
--- a/storage/xtradb/include/data0data.ic
+++ b/storage/xtradb/include/data0data.ic
@@ -229,20 +229,30 @@ dfield_dup(
}
/*********************************************************************//**
-Tests if data length and content is equal for two dfields.
-@return TRUE if equal */
+Tests if two data fields are equal.
+If len==0, tests the data length and content for equality.
+If len>0, tests the first len bytes of the content for equality.
+@return TRUE if both fields are NULL or if they are equal */
UNIV_INLINE
ibool
dfield_datas_are_binary_equal(
/*==========================*/
const dfield_t* field1, /*!< in: field */
- const dfield_t* field2) /*!< in: field */
+ const dfield_t* field2, /*!< in: field */
+ ulint len) /*!< in: maximum prefix to compare,
+ or 0 to compare the whole field length */
{
- ulint len;
+ ulint len2 = len;
- len = field1->len;
+ if (field1->len == UNIV_SQL_NULL || len == 0 || field1->len < len) {
+ len = field1->len;
+ }
+
+ if (field2->len == UNIV_SQL_NULL || len2 == 0 || field2->len < len2) {
+ len2 = field2->len;
+ }
- return(len == field2->len
+ return(len == len2
&& (len == UNIV_SQL_NULL
|| !memcmp(field1->data, field2->data, len)));
}
diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h
index d18b3ecb1b0..7baacdd6055 100644
--- a/storage/xtradb/include/dict0dict.h
+++ b/storage/xtradb/include/dict0dict.h
@@ -318,7 +318,8 @@ void
dict_table_replace_index_in_foreign_list(
/*=====================================*/
dict_table_t* table, /*!< in/out: table */
- dict_index_t* index); /*!< in: index to be replaced */
+ dict_index_t* index, /*!< in: index to be replaced */
+ const trx_t* trx); /*!< in: transaction handle */
/*********************************************************************//**
Checks if a index is defined for a foreign key constraint. Index is a part
of a foreign key constraint if the index is referenced by foreign key
@@ -1053,20 +1054,13 @@ Calculates new estimates for table and index statistics. The statistics
are used in query optimization. */
UNIV_INTERN
void
-dict_update_statistics_low(
-/*=======================*/
- dict_table_t* table, /*!< in/out: table */
- ibool has_dict_mutex, /*!< in: TRUE if the caller has the
- dictionary mutex */
- ibool sync);
-/*********************************************************************//**
-Calculates new estimates for table and index statistics. The statistics
-are used in query optimization. */
-UNIV_INTERN
-void
dict_update_statistics(
/*===================*/
- dict_table_t* table, /*!< in/out: table */
+ dict_table_t* table, /*!< in/out: table */
+ ibool only_calc_if_missing_stats, /*!< in: only
+ update/recalc the stats if they have
+ not been initialized yet, otherwise
+ do nothing */
ibool sync);
/********************************************************************//**
Reserves the dictionary system mutex for MySQL. */
@@ -1081,21 +1075,25 @@ void
dict_mutex_exit_for_mysql(void);
/*===========================*/
/**********************************************************************//**
-Lock the appropriate mutex to protect index->stat_n_diff_key_vals[].
-index->id is used to pick the right mutex and it should not change
-before dict_index_stat_mutex_exit() is called on this index. */
+Lock the appropriate latch to protect a given table's statistics.
+table->id is used to pick the corresponding latch from a global array of
+latches. */
UNIV_INTERN
void
-dict_index_stat_mutex_enter(
-/*========================*/
- const dict_index_t* index); /*!< in: index */
+dict_table_stats_lock(
+/*==================*/
+ const dict_table_t* table, /*!< in: table */
+ ulint latch_mode); /*!< in: RW_S_LATCH or
+ RW_X_LATCH */
/**********************************************************************//**
-Unlock the appropriate mutex that protects index->stat_n_diff_key_vals[]. */
+Unlock the latch that has been locked by dict_table_stats_lock() */
UNIV_INTERN
void
-dict_index_stat_mutex_exit(
-/*=======================*/
- const dict_index_t* index); /*!< in: index */
+dict_table_stats_unlock(
+/*====================*/
+ const dict_table_t* table, /*!< in: table */
+ ulint latch_mode); /*!< in: RW_S_LATCH or
+ RW_X_LATCH */
/********************************************************************//**
Checks if the database name in two table names is the same.
@return TRUE if same db name */
diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h
index 07c80ef8609..a262ec8f9cc 100644
--- a/storage/xtradb/include/fil0fil.h
+++ b/storage/xtradb/include/fil0fil.h
@@ -737,6 +737,15 @@ fil_page_get_type(
/*==============*/
const byte* page); /*!< in: file page */
+/*******************************************************************//**
+Returns TRUE if a single-table tablespace is being deleted.
+@return TRUE if being deleted */
+UNIV_INTERN
+ibool
+fil_tablespace_is_being_deleted(
+/*============================*/
+ ulint id); /*!< in: space id */
+
/*************************************************************************
Return local hash table informations. */
diff --git a/storage/xtradb/include/hash0hash.h b/storage/xtradb/include/hash0hash.h
index b17c21a45ef..492c767acc4 100644
--- a/storage/xtradb/include/hash0hash.h
+++ b/storage/xtradb/include/hash0hash.h
@@ -49,6 +49,28 @@ hash_table_t*
hash_create(
/*========*/
ulint n); /*!< in: number of array cells */
+
+/*************************************************************//**
+*/
+UNIV_INTERN
+ulint
+hash_create_needed(
+/*===============*/
+ ulint n);
+
+UNIV_INTERN
+void
+hash_create_init(
+/*=============*/
+ hash_table_t* table,
+ ulint n);
+
+UNIV_INTERN
+void
+hash_create_reuse(
+/*==============*/
+ hash_table_t* table);
+
#ifndef UNIV_HOTBACKUP
/*************************************************************//**
Creates a mutex array to protect a hash table. */
@@ -328,6 +350,33 @@ do {\
}\
} while (0)
+/********************************************************************//**
+Align nodes with moving location.*/
+#define HASH_OFFSET(TABLE, NODE_TYPE, PTR_NAME, FADDR, FOFFSET, BOFFSET) \
+do {\
+ ulint i2222;\
+ ulint cell_count2222;\
+\
+ cell_count2222 = hash_get_n_cells(TABLE);\
+\
+ for (i2222 = 0; i2222 < cell_count2222; i2222++) {\
+ NODE_TYPE* node2222;\
+\
+ if ((TABLE)->array[i2222].node) \
+ (TABLE)->array[i2222].node = (void*)((byte*)(TABLE)->array[i2222].node \
+ + (((TABLE)->array[i2222].node > (void*)FADDR)?FOFFSET:BOFFSET));\
+ node2222 = HASH_GET_FIRST((TABLE), i2222);\
+\
+ while (node2222) {\
+ if (node2222->PTR_NAME) \
+ node2222->PTR_NAME = (void*)((byte*)(node2222->PTR_NAME) \
+ + ((((void*)node2222->PTR_NAME) > (void*)FADDR)?FOFFSET:BOFFSET));\
+\
+ node2222 = node2222->PTR_NAME;\
+ }\
+ }\
+} while (0)
+
/************************************************************//**
Gets the mutex index for a fold value in a hash table.
@return mutex number */
diff --git a/storage/xtradb/include/log0log.h b/storage/xtradb/include/log0log.h
index 8fce4ef96bc..2b4b34f2600 100644
--- a/storage/xtradb/include/log0log.h
+++ b/storage/xtradb/include/log0log.h
@@ -672,6 +672,9 @@ extern log_t* log_sys;
when mysqld is first time started
on the restored database, it can
print helpful info for the user */
+#define LOG_FILE_OS_FILE_LOG_BLOCK_SIZE 64
+ /* extend to record log_block_size
+ of XtraDB. 0 means default 512 */
#define LOG_FILE_ARCH_COMPLETED OS_FILE_LOG_BLOCK_SIZE
/* this 4-byte field is TRUE when
the writing of an archived log file
diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h
index eeab8a2b5d9..cbbec2cf55e 100644
--- a/storage/xtradb/include/os0file.h
+++ b/storage/xtradb/include/os0file.h
@@ -107,7 +107,7 @@ whole block gets written. This should be true even in most cases of a crash:
if this fails for a log block, then it is equivalent to a media failure in the
log. */
-#define OS_FILE_LOG_BLOCK_SIZE 512
+#define OS_FILE_LOG_BLOCK_SIZE srv_log_block_size
/** Options for file_create @{ */
#define OS_FILE_OPEN 51
@@ -188,6 +188,8 @@ extern ulint os_n_file_reads;
extern ulint os_n_file_writes;
extern ulint os_n_fsyncs;
+extern ulint srv_log_block_size;
+
/* File types for directory entry data type */
enum os_file_type_enum{
diff --git a/storage/xtradb/include/os0proc.h b/storage/xtradb/include/os0proc.h
index fd46bd7db87..582cef6f803 100644
--- a/storage/xtradb/include/os0proc.h
+++ b/storage/xtradb/include/os0proc.h
@@ -32,6 +32,11 @@ Created 9/30/1995 Heikki Tuuri
#ifdef UNIV_LINUX
#include <sys/ipc.h>
#include <sys/shm.h>
+#else
+# if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H
+#include <sys/ipc.h>
+#include <sys/shm.h>
+# endif
#endif
typedef void* os_process_t;
@@ -70,6 +75,29 @@ os_mem_free_large(
ulint size); /*!< in: size returned by
os_mem_alloc_large() */
+
+/****************************************************************//**
+Allocates or attaches and reuses shared memory segment.
+The content is not cleared automatically.
+@return allocated memory */
+UNIV_INTERN
+void*
+os_shm_alloc(
+/*=========*/
+ ulint* n, /*!< in/out: number of bytes */
+ uint key,
+ ibool* is_new);
+
+/****************************************************************//**
+Detach shared memory segment. */
+UNIV_INTERN
+void
+os_shm_free(
+/*========*/
+ void *ptr, /*!< in: pointer returned by
+ os_shm_alloc() */
+ ulint size); /*!< in: size returned by
+ os_shm_alloc() */
#ifndef UNIV_NONINL
#include "os0proc.ic"
#endif
diff --git a/storage/xtradb/include/os0sync.h b/storage/xtradb/include/os0sync.h
index 2cf9ea0ec84..7366e2c3402 100644
--- a/storage/xtradb/include/os0sync.h
+++ b/storage/xtradb/include/os0sync.h
@@ -196,7 +196,7 @@ ulint
os_event_wait_time(
/*===============*/
os_event_t event, /*!< in: event to wait */
- ulint time); /*!< in: timeout in microseconds, or
+ ulint wtime); /*!< in: timeout in microseconds, or
OS_SYNC_INFINITE_TIME */
#ifdef __WIN__
/**********************************************************//**
diff --git a/storage/xtradb/include/row0ins.h b/storage/xtradb/include/row0ins.h
index 9f93565ddb7..810973e61a7 100644
--- a/storage/xtradb/include/row0ins.h
+++ b/storage/xtradb/include/row0ins.h
@@ -84,9 +84,10 @@ ulint
row_ins_index_entry(
/*================*/
dict_index_t* index, /*!< in: index */
- dtuple_t* entry, /*!< in: index entry to insert */
+ dtuple_t* entry, /*!< in/out: index entry to insert */
ulint n_ext, /*!< in: number of externally stored columns */
- ibool foreign,/*!< in: TRUE=check foreign key constraints */
+ ibool foreign,/*!< in: TRUE=check foreign key constraints
+ (foreign=FALSE only during CREATE INDEX) */
que_thr_t* thr); /*!< in: query thread */
/***********************************************************//**
Inserts a row to a table. This is a high-level function used in
diff --git a/storage/xtradb/include/row0upd.h b/storage/xtradb/include/row0upd.h
index 4e2de9bd2ec..b61e6b6dca1 100644
--- a/storage/xtradb/include/row0upd.h
+++ b/storage/xtradb/include/row0upd.h
@@ -126,8 +126,8 @@ UNIV_INTERN
void
row_upd_index_entry_sys_field(
/*==========================*/
- const dtuple_t* entry, /*!< in: index entry, where the memory buffers
- for sys fields are already allocated:
+ dtuple_t* entry, /*!< in/out: index entry, where the memory
+ buffers for sys fields are already allocated:
the function just copies the new values to
them */
dict_index_t* index, /*!< in: clustered index */
@@ -286,10 +286,13 @@ row_upd_changes_ord_field_binary(
row and the data values in update are not
known when this function is called, e.g., at
compile time */
+ const row_ext_t*ext, /*!< NULL, or prefixes of the externally
+ stored columns in the old row */
dict_index_t* index, /*!< in: index of the record */
- const upd_t* update);/*!< in: update vector for the row; NOTE: the
+ const upd_t* update) /*!< in: update vector for the row; NOTE: the
field numbers in this MUST be clustered index
positions! */
+ __attribute__((nonnull(3,4), warn_unused_result));
/***********************************************************//**
Checks if an update vector changes an ordering field of an index record.
This function is fast if the update vector is short or the number of ordering
@@ -462,11 +465,16 @@ struct upd_node_struct{
#define UPD_NODE_INSERT_CLUSTERED 3 /* clustered index record should be
inserted, old record is already delete
marked */
-#define UPD_NODE_UPDATE_ALL_SEC 4 /* an ordering field of the clustered
+#define UPD_NODE_INSERT_BLOB 4 /* clustered index record should be
+ inserted, old record is already
+ delete-marked; non-updated BLOBs
+ should be inherited by the new record
+ and disowned by the old record */
+#define UPD_NODE_UPDATE_ALL_SEC 5 /* an ordering field of the clustered
index record was changed, or this is
a delete operation: should update
all the secondary index records */
-#define UPD_NODE_UPDATE_SOME_SEC 5 /* secondary index entries should be
+#define UPD_NODE_UPDATE_SOME_SEC 6 /* secondary index entries should be
looked at and updated if an ordering
field changed */
diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h
index 8148dffd13b..f4c9704741c 100644
--- a/storage/xtradb/include/srv0srv.h
+++ b/storage/xtradb/include/srv0srv.h
@@ -159,6 +159,10 @@ extern ulint srv_buf_pool_curr_size; /*!< current size in bytes */
extern ulint srv_mem_pool_size;
extern ulint srv_lock_table_size;
+extern uint srv_buffer_pool_shm_key;
+extern ibool srv_buffer_pool_shm_is_reused;
+extern ibool srv_buffer_pool_shm_checksum;
+
extern ibool srv_thread_concurrency_timer_based;
extern ulint srv_n_file_io_threads;
diff --git a/storage/xtradb/include/srv0start.h b/storage/xtradb/include/srv0start.h
index 8abf15da9c1..7eb7e96bd50 100644
--- a/storage/xtradb/include/srv0start.h
+++ b/storage/xtradb/include/srv0start.h
@@ -131,4 +131,7 @@ extern enum srv_shutdown_state srv_shutdown_state;
/** Log 'spaces' have id's >= this */
#define SRV_LOG_SPACE_FIRST_ID 0xFFFFFFF0UL
+/** reserved for extra system tables */
+#define SRV_EXTRA_SYS_SPACE_FIRST_ID 0xFFFFFFE0UL
+
#endif
diff --git a/storage/xtradb/include/trx0i_s.h b/storage/xtradb/include/trx0i_s.h
index 7bd4e1b88c8..48d41038ea4 100644
--- a/storage/xtradb/include/trx0i_s.h
+++ b/storage/xtradb/include/trx0i_s.h
@@ -110,6 +110,8 @@ struct i_s_trx_row_struct {
/*!< thd_get_thread_id() */
const char* trx_query; /*!< MySQL statement being
executed in the transaction */
+ struct charset_info_st* trx_query_cs; /*!< charset encode the MySQL
+ statement */
};
/** This structure represents INFORMATION_SCHEMA.innodb_lock_waits row */
diff --git a/storage/xtradb/include/trx0sys.h b/storage/xtradb/include/trx0sys.h
index 9ef9485b611..2637189f37e 100644
--- a/storage/xtradb/include/trx0sys.h
+++ b/storage/xtradb/include/trx0sys.h
@@ -470,7 +470,7 @@ trx_sys_file_format_id_to_name(
/* Space id and page no where the trx system file copy resides */
#define TRX_SYS_SPACE 0 /* the SYSTEM tablespace */
-#define TRX_DOUBLEWRITE_SPACE 1 /* the doublewrite buffer tablespace if used */
+#define TRX_DOUBLEWRITE_SPACE 0xFFFFFFE0UL /* the doublewrite buffer tablespace if used */
#define TRX_SYS_SPACE_MAX 9 /* reserved max space id for system tablespaces */
#include "fsp0fsp.h"
#define TRX_SYS_PAGE_NO FSP_TRX_SYS_PAGE_NO
diff --git a/storage/xtradb/include/trx0sys.ic b/storage/xtradb/include/trx0sys.ic
index c7b09d4aec2..5e0f07c8b9d 100644
--- a/storage/xtradb/include/trx0sys.ic
+++ b/storage/xtradb/include/trx0sys.ic
@@ -81,7 +81,7 @@ trx_sys_sys_space(
{
if (srv_doublewrite_file) {
/* several spaces are reserved */
- return((ibool)(space <= TRX_SYS_SPACE_MAX));
+ return((ibool)(space == TRX_SYS_SPACE || space == TRX_DOUBLEWRITE_SPACE));
} else {
return((ibool)(space == TRX_SYS_SPACE));
}
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index 487c291ef80..111bda1a3c5 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -46,8 +46,8 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 1
#define INNODB_VERSION_MINOR 0
-#define INNODB_VERSION_BUGFIX 13
-#define PERCONA_INNODB_VERSION 11.6
+#define INNODB_VERSION_BUGFIX 15
+#define PERCONA_INNODB_VERSION 12.5
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
@@ -303,6 +303,18 @@ number does not include a terminating '\0'. InnoDB probably can handle
longer names internally */
#define MAX_TABLE_NAME_LEN 192
+/* The maximum length of a database name. Like MAX_TABLE_NAME_LEN this is
+the MySQL's NAME_LEN, see check_and_convert_db_name(). */
+#define MAX_DATABASE_NAME_LEN MAX_TABLE_NAME_LEN
+
+/* MAX_FULL_NAME_LEN defines the full name path including the
+database name and table name. In addition, 14 bytes is added for:
+ 2 for surrounding quotes around table name
+ 1 for the separating dot (.)
+ 9 for the #mysql50# prefix */
+#define MAX_FULL_NAME_LEN \
+ (MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN + 14)
+
/*
UNIVERSAL TYPE DEFINITIONS
==========================
@@ -369,6 +381,9 @@ typedef unsigned long long int ullint;
/* Maximum value for ib_uint64_t */
#define IB_ULONGLONG_MAX ((ib_uint64_t) (~0ULL))
+/* The 'undefined' value for ullint */
+#define ULLINT_UNDEFINED ((ullint)(-1))
+
/* This 'ibool' type is used within Innobase. Remember that different included
headers may define 'bool' differently. Do not assume that 'bool' is a ulint! */
#define ibool ulint
diff --git a/storage/xtradb/include/ut0lst.h b/storage/xtradb/include/ut0lst.h
index 7b15c052978..245dfc226c3 100644
--- a/storage/xtradb/include/ut0lst.h
+++ b/storage/xtradb/include/ut0lst.h
@@ -257,5 +257,48 @@ do { \
ut_a(ut_list_node_313 == NULL); \
} while (0)
+/********************************************************************//**
+Align nodes with moving location.
+@param NAME the name of the list
+@param TYPE node type
+@param BASE base node (not a pointer to it)
+@param OFFSET offset moved */
+#define UT_LIST_OFFSET(NAME, TYPE, BASE, FADDR, FOFFSET, BOFFSET) \
+do { \
+ ulint ut_list_i_313; \
+ TYPE* ut_list_node_313; \
+ \
+ if ((BASE).start) \
+ (BASE).start = (void*)((byte*)((BASE).start) \
+ + (((void*)((BASE).start) > (void*)FADDR)?FOFFSET:BOFFSET));\
+ if ((BASE).end) \
+ (BASE).end = (void*)((byte*)((BASE).end) \
+ + (((void*)((BASE).end) > (void*)FADDR)?FOFFSET:BOFFSET));\
+ \
+ ut_list_node_313 = (BASE).start; \
+ \
+ for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) { \
+ ut_a(ut_list_node_313); \
+ if ((ut_list_node_313->NAME).prev) \
+ (ut_list_node_313->NAME).prev = (void*)((byte*)((ut_list_node_313->NAME).prev)\
+ + (((void*)((ut_list_node_313->NAME).prev) > (void*)FADDR)?FOFFSET:BOFFSET));\
+ if ((ut_list_node_313->NAME).next) \
+ (ut_list_node_313->NAME).next = (void*)((byte*)((ut_list_node_313->NAME).next)\
+ + (((void*)((ut_list_node_313->NAME).next)> (void*)FADDR)?FOFFSET:BOFFSET));\
+ ut_list_node_313 = (ut_list_node_313->NAME).next; \
+ } \
+ \
+ ut_a(ut_list_node_313 == NULL); \
+ \
+ ut_list_node_313 = (BASE).end; \
+ \
+ for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) { \
+ ut_a(ut_list_node_313); \
+ ut_list_node_313 = (ut_list_node_313->NAME).prev; \
+ } \
+ \
+ ut_a(ut_list_node_313 == NULL); \
+} while (0)
+
#endif
diff --git a/storage/xtradb/include/ut0vec.h b/storage/xtradb/include/ut0vec.h
index a770f671cfc..0f8b955b098 100644
--- a/storage/xtradb/include/ut0vec.h
+++ b/storage/xtradb/include/ut0vec.h
@@ -94,6 +94,25 @@ ib_vector_get(
ulint n); /*!< in: element index to get */
/****************************************************************//**
+Get last element. The vector must not be empty.
+@return last element */
+UNIV_INLINE
+void*
+ib_vector_get_last(
+/*===============*/
+ ib_vector_t* vec); /*!< in: vector */
+
+/****************************************************************//**
+Set the n'th element. */
+UNIV_INLINE
+void
+ib_vector_set(
+/*==========*/
+ ib_vector_t* vec, /*!< in/out: vector */
+ ulint n, /*!< in: element index to set */
+ void* elem); /*!< in: data element */
+
+/****************************************************************//**
Remove the last element from the vector. */
UNIV_INLINE
void*
diff --git a/storage/xtradb/include/ut0vec.ic b/storage/xtradb/include/ut0vec.ic
index 02e881f9bca..34c858868ce 100644
--- a/storage/xtradb/include/ut0vec.ic
+++ b/storage/xtradb/include/ut0vec.ic
@@ -51,6 +51,35 @@ ib_vector_get(
}
/****************************************************************//**
+Get last element. The vector must not be empty.
+@return last element */
+UNIV_INLINE
+void*
+ib_vector_get_last(
+/*===============*/
+ ib_vector_t* vec) /*!< in: vector */
+{
+ ut_a(vec->used > 0);
+
+ return(vec->data[vec->used - 1]);
+}
+
+/****************************************************************//**
+Set the n'th element. */
+UNIV_INLINE
+void
+ib_vector_set(
+/*==========*/
+ ib_vector_t* vec, /*!< in/out: vector */
+ ulint n, /*!< in: element index to set */
+ void* elem) /*!< in: data element */
+{
+ ut_a(n < vec->used);
+
+ vec->data[n] = elem;
+}
+
+/****************************************************************//**
Remove the last element from the vector.
@return last vector element */
UNIV_INLINE
diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c
index 1ded67d9147..4fcb5b2c522 100644
--- a/storage/xtradb/lock/lock0lock.c
+++ b/storage/xtradb/lock/lock0lock.c
@@ -3632,6 +3632,80 @@ lock_table_create(
}
/*************************************************************//**
+Pops autoinc lock requests from the transaction's autoinc_locks. We
+handle the case where there are gaps in the array and they need to
+be popped off the stack. */
+UNIV_INLINE
+void
+lock_table_pop_autoinc_locks(
+/*=========================*/
+ trx_t* trx) /*!< in/out: transaction that owns the AUTOINC locks */
+{
+ ut_ad(mutex_own(&kernel_mutex));
+ ut_ad(!ib_vector_is_empty(trx->autoinc_locks));
+
+ /* Skip any gaps, gaps are NULL lock entries in the
+ trx->autoinc_locks vector. */
+
+ do {
+ ib_vector_pop(trx->autoinc_locks);
+
+ if (ib_vector_is_empty(trx->autoinc_locks)) {
+ return;
+ }
+
+ } while (ib_vector_get_last(trx->autoinc_locks) == NULL);
+}
+
+/*************************************************************//**
+Removes an autoinc lock request from the transaction's autoinc_locks. */
+UNIV_INLINE
+void
+lock_table_remove_autoinc_lock(
+/*===========================*/
+ lock_t* lock, /*!< in: table lock */
+ trx_t* trx) /*!< in/out: transaction that owns the lock */
+{
+ lock_t* autoinc_lock;
+ lint i = ib_vector_size(trx->autoinc_locks) - 1;
+
+ ut_ad(mutex_own(&kernel_mutex));
+ ut_ad(lock_get_mode(lock) == LOCK_AUTO_INC);
+ ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
+ ut_ad(!ib_vector_is_empty(trx->autoinc_locks));
+
+ /* With stored functions and procedures the user may drop
+ a table within the same "statement". This special case has
+ to be handled by deleting only those AUTOINC locks that were
+ held by the table being dropped. */
+
+ autoinc_lock = ib_vector_get(trx->autoinc_locks, i);
+
+ /* This is the default fast case. */
+
+ if (autoinc_lock == lock) {
+ lock_table_pop_autoinc_locks(trx);
+ } else {
+ /* The last element should never be NULL */
+ ut_a(autoinc_lock != NULL);
+
+ /* Handle freeing the locks from within the stack. */
+
+ while (--i >= 0) {
+ autoinc_lock = ib_vector_get(trx->autoinc_locks, i);
+
+ if (UNIV_LIKELY(autoinc_lock == lock)) {
+ ib_vector_set(trx->autoinc_locks, i, NULL);
+ return;
+ }
+ }
+
+ /* Must find the autoinc lock. */
+ ut_error;
+ }
+}
+
+/*************************************************************//**
Removes a table lock request from the queue and the trx list of locks;
this is a low-level function which does NOT check if waiting requests
can now be granted. */
@@ -3670,10 +3744,8 @@ lock_table_remove_low(
if (!lock_get_wait(lock)
&& !ib_vector_is_empty(trx->autoinc_locks)) {
- lock_t* autoinc_lock;
- autoinc_lock = ib_vector_pop(trx->autoinc_locks);
- ut_a(autoinc_lock == lock);
+ lock_table_remove_autoinc_lock(lock, trx);
}
ut_a(table->n_waiting_or_granted_auto_inc_locks > 0);
diff --git a/storage/xtradb/log/log0log.c b/storage/xtradb/log/log0log.c
index 3f14d84ac72..c39f60bd4b9 100644
--- a/storage/xtradb/log/log0log.c
+++ b/storage/xtradb/log/log0log.c
@@ -1184,6 +1184,9 @@ log_group_file_header_flush(
/* Wipe over possible label of ibbackup --restore */
memcpy(buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, " ", 4);
+ mach_write_to_4(buf + LOG_FILE_OS_FILE_LOG_BLOCK_SIZE,
+ srv_log_block_size);
+
dest_offset = nth_file * group->file_size;
#ifdef UNIV_DEBUG
@@ -1777,9 +1780,7 @@ log_group_checkpoint(
ulint i;
ut_ad(mutex_own(&(log_sys->mutex)));
-#if LOG_CHECKPOINT_SIZE > OS_FILE_LOG_BLOCK_SIZE
-# error "LOG_CHECKPOINT_SIZE > OS_FILE_LOG_BLOCK_SIZE"
-#endif
+ ut_a(LOG_CHECKPOINT_SIZE <= OS_FILE_LOG_BLOCK_SIZE);
buf = group->checkpoint_buf;
diff --git a/storage/xtradb/log/log0recv.c b/storage/xtradb/log/log0recv.c
index 2aaffe4c031..895067c700a 100644
--- a/storage/xtradb/log/log0recv.c
+++ b/storage/xtradb/log/log0recv.c
@@ -2260,7 +2260,7 @@ recv_report_corrupt_log(
"InnoDB: far enough in recovery! Please run CHECK TABLE\n"
"InnoDB: on your InnoDB tables to check that they are ok!\n"
"InnoDB: If mysqld crashes after this recovery, look at\n"
- "InnoDB: " REFMAN "forcing-recovery.html\n"
+ "InnoDB: " REFMAN "forcing-innodb-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
fflush(stderr);
@@ -2899,6 +2899,7 @@ recv_init_crash_recovery(void)
/*==========================*/
{
ut_a(!recv_needed_recovery);
+ ut_a(!srv_buffer_pool_shm_is_reused);
recv_needed_recovery = TRUE;
@@ -2956,6 +2957,7 @@ recv_recovery_from_checkpoint_start_func(
log_group_t* max_cp_group;
log_group_t* up_to_date_group;
ulint max_cp_field;
+ ulint log_hdr_log_block_size;
ib_uint64_t checkpoint_lsn;
ib_uint64_t checkpoint_no;
ib_uint64_t old_scanned_lsn;
@@ -2966,9 +2968,10 @@ recv_recovery_from_checkpoint_start_func(
#endif /* UNIV_LOG_ARCHIVE */
byte* buf;
byte* log_hdr_buf;
- byte log_hdr_buf_base[LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE];
+ byte *log_hdr_buf_base;
ulint err;
+ log_hdr_buf_base= alloca(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE);
log_hdr_buf = ut_align(log_hdr_buf_base, OS_FILE_LOG_BLOCK_SIZE);
#ifdef UNIV_LOG_ARCHIVE
@@ -3057,6 +3060,20 @@ recv_recovery_from_checkpoint_start_func(
log_hdr_buf, max_cp_group);
}
+ log_hdr_log_block_size
+ = mach_read_from_4(log_hdr_buf + LOG_FILE_OS_FILE_LOG_BLOCK_SIZE);
+ if (log_hdr_log_block_size == 0) {
+ /* 0 means default value */
+ log_hdr_log_block_size = 512;
+ }
+ if (log_hdr_log_block_size != srv_log_block_size) {
+ fprintf(stderr,
+ "InnoDB: Error: The block size of ib_logfile (%lu) "
+ "is not equal to innodb_log_block_size.\n",
+ log_hdr_log_block_size);
+ return(DB_ERROR);
+ }
+
#ifdef UNIV_LOG_ARCHIVE
group = UT_LIST_GET_FIRST(log_sys->log_groups);
diff --git a/storage/xtradb/os/os0proc.c b/storage/xtradb/os/os0proc.c
index 48922886f23..4567d96b6f4 100644
--- a/storage/xtradb/os/os0proc.c
+++ b/storage/xtradb/os/os0proc.c
@@ -229,3 +229,173 @@ os_mem_free_large(
}
#endif
}
+
+/****************************************************************//**
+Allocates or attaches and reuses shared memory segment.
+The content is not cleared automatically.
+@return allocated memory */
+UNIV_INTERN
+void*
+os_shm_alloc(
+/*=========*/
+ ulint* n, /*!< in/out: number of bytes */
+ uint key,
+ ibool* is_new)
+{
+ void* ptr;
+#if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H
+ ulint size;
+ int shmid;
+
+ *is_new = FALSE;
+ fprintf(stderr,
+ "InnoDB: The shared memory segment containing the buffer pool is: key %#x (%d).\n",
+ key, key);
+# if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
+ if (!os_use_large_pages || !os_large_page_size) {
+ goto skip;
+ }
+
+ /* Align block size to os_large_page_size */
+ ut_ad(ut_is_2pow(os_large_page_size));
+ size = ut_2pow_round(*n + (os_large_page_size - 1),
+ os_large_page_size);
+
+ shmid = shmget((key_t)key, (size_t)size,
+ IPC_CREAT | IPC_EXCL | SHM_HUGETLB | SHM_R | SHM_W);
+ if (shmid < 0) {
+ if (errno == EEXIST) {
+ fprintf(stderr,
+ "InnoDB: HugeTLB: The shared memory segment exists.\n");
+ shmid = shmget((key_t)key, (size_t)size,
+ SHM_HUGETLB | SHM_R | SHM_W);
+ if (shmid < 0) {
+ fprintf(stderr,
+ "InnoDB: HugeTLB: Warning: Failed to allocate %lu bytes. (reuse) errno %d\n",
+ size, errno);
+ goto skip;
+ } else {
+ fprintf(stderr,
+ "InnoDB: HugeTLB: The existent shared memory segment is used.\n");
+ }
+ } else {
+ fprintf(stderr,
+ "InnoDB: HugeTLB: Warning: Failed to allocate %lu bytes. (new) errno %d\n",
+ size, errno);
+ goto skip;
+ }
+ } else {
+ *is_new = TRUE;
+ fprintf(stderr,
+ "InnoDB: HugeTLB: A new shared memory segment has been created .\n");
+ }
+
+ ptr = shmat(shmid, NULL, 0);
+ if (ptr == (void *)-1) {
+ fprintf(stderr,
+ "InnoDB: HugeTLB: Warning: Failed to attach shared memory segment, errno %d\n",
+ errno);
+ ptr = NULL;
+ }
+
+ if (ptr) {
+ *n = size;
+ os_fast_mutex_lock(&ut_list_mutex);
+ ut_total_allocated_memory += size;
+ os_fast_mutex_unlock(&ut_list_mutex);
+ UNIV_MEM_ALLOC(ptr, size);
+ return(ptr);
+ }
+skip:
+ *is_new = FALSE;
+# endif /* HAVE_LARGE_PAGES && defined UNIV_LINUX */
+# ifdef HAVE_GETPAGESIZE
+ size = getpagesize();
+# else
+ size = UNIV_PAGE_SIZE;
+# endif
+ /* Align block size to system page size */
+ ut_ad(ut_is_2pow(size));
+ size = *n = ut_2pow_round(*n + (size - 1), size);
+
+ shmid = shmget((key_t)key, (size_t)size,
+ IPC_CREAT | IPC_EXCL | SHM_R | SHM_W);
+ if (shmid < 0) {
+ if (errno == EEXIST) {
+ fprintf(stderr,
+ "InnoDB: A shared memory segment containing the buffer pool seems to already exist.\n");
+ shmid = shmget((key_t)key, (size_t)size,
+ SHM_R | SHM_W);
+ if (shmid < 0) {
+ fprintf(stderr,
+ "InnoDB: Warning: Failed to allocate %lu bytes. (reuse) errno %d\n",
+ size, errno);
+ ptr = NULL;
+ goto end;
+ } else {
+ fprintf(stderr,
+ "InnoDB: The existent shared memory segment is used.\n");
+ }
+ } else {
+ fprintf(stderr,
+ "InnoDB: Warning: Failed to allocate %lu bytes. (new) errno %d\n",
+ size, errno);
+ ptr = NULL;
+ goto end;
+ }
+ } else {
+ *is_new = TRUE;
+ fprintf(stderr,
+ "InnoDB: A new shared memory segment has been created.\n");
+ }
+
+ ptr = shmat(shmid, NULL, 0);
+ if (ptr == (void *)-1) {
+ fprintf(stderr,
+ "InnoDB: Warning: Failed to attach shared memory segment, errno %d\n",
+ errno);
+ ptr = NULL;
+ }
+
+ if (ptr) {
+ *n = size;
+ os_fast_mutex_lock(&ut_list_mutex);
+ ut_total_allocated_memory += size;
+ os_fast_mutex_unlock(&ut_list_mutex);
+ UNIV_MEM_ALLOC(ptr, size);
+ }
+end:
+#else /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
+ fprintf(stderr, "InnoDB: shared memory segment is not supported.\n");
+ ptr = NULL;
+#endif /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
+ return(ptr);
+}
+
+/****************************************************************//**
+Detach shared memory segment. */
+UNIV_INTERN
+void
+os_shm_free(
+/*========*/
+ void *ptr, /*!< in: pointer returned by
+ os_shm_alloc() */
+ ulint size) /*!< in: size returned by
+ os_shm_alloc() */
+{
+ os_fast_mutex_lock(&ut_list_mutex);
+ ut_a(ut_total_allocated_memory >= size);
+ os_fast_mutex_unlock(&ut_list_mutex);
+
+#if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H
+ if (!shmdt(ptr)) {
+ os_fast_mutex_lock(&ut_list_mutex);
+ ut_a(ut_total_allocated_memory >= size);
+ ut_total_allocated_memory -= size;
+ os_fast_mutex_unlock(&ut_list_mutex);
+ UNIV_MEM_FREE(ptr, size);
+ }
+#else /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
+ fprintf(stderr, "InnoDB: shared memory segment is not supported.\n");
+#endif /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */
+}
diff --git a/storage/xtradb/os/os0sync.c b/storage/xtradb/os/os0sync.c
index f9ab58c2ee4..dba997927cb 100644
--- a/storage/xtradb/os/os0sync.c
+++ b/storage/xtradb/os/os0sync.c
@@ -442,12 +442,12 @@ os_event_wait_time(
return(1000000); /* dummy value to eliminate compiler warn. */
}
#else
- int err;
- int ret = 0;
- ulint tmp;
+ int err;
+ int ret = 0;
+ ulint tmp;
ib_int64_t old_count;
- struct timeval tv_start;
- struct timespec timeout;
+ struct timeval tv_start;
+ struct timespec timeout;
if (wtime == OS_SYNC_INFINITE_TIME) {
os_event_wait(event);
diff --git a/storage/xtradb/plug.in b/storage/xtradb/plug.in
index b68b59725d4..2e0c873094a 100644
--- a/storage/xtradb/plug.in
+++ b/storage/xtradb/plug.in
@@ -140,17 +140,24 @@ MYSQL_PLUGIN_ACTIONS(xtradb, [
)
AC_MSG_CHECKING(whether Solaris libc atomic functions are available)
- # either define HAVE_IB_SOLARIS_ATOMICS or not
- AC_CHECK_FUNCS(atomic_cas_ulong \
+ # Define HAVE_IB_SOLARIS_ATOMICS if _all_ of the following
+ # functions are present.
+ AC_CHECK_FUNCS(atomic_add_long_nv \
atomic_cas_32 \
atomic_cas_64 \
- atomic_add_long_nv \
- atomic_swap_uchar,
-
- AC_DEFINE([HAVE_IB_SOLARIS_ATOMICS], [1],
- [Define to 1 if Solaris libc atomic functions \
- are available])
- )
+ atomic_cas_ulong \
+ atomic_swap_uchar)
+
+ if test "${ac_cv_func_atomic_add_long_nv}" = "yes" -a \
+ "${ac_cv_func_atomic_cas_32}" = "yes" -a \
+ "${ac_cv_func_atomic_cas_64}" = "yes" -a \
+ "${ac_cv_func_atomic_cas_ulong}" = "yes" -a \
+ "${ac_cv_func_atomic_swap_uchar}" = "yes" ; then
+
+ AC_DEFINE([HAVE_IB_SOLARIS_ATOMICS], [1],
+ [Define to 1 if Solaris libc atomic functions are available]
+ )
+ fi
AC_MSG_CHECKING(whether pthread_t can be used by Solaris libc atomic functions)
# either define HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS or not
diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c
index d4925e46f97..3372e1480b5 100644
--- a/storage/xtradb/row/row0ins.c
+++ b/storage/xtradb/row/row0ins.c
@@ -1787,7 +1787,7 @@ ulint
row_ins_duplicate_error_in_clust(
/*=============================*/
btr_cur_t* cursor, /*!< in: B-tree cursor */
- dtuple_t* entry, /*!< in: entry to insert */
+ const dtuple_t* entry, /*!< in: entry to insert */
que_thr_t* thr, /*!< in: query thread */
mtr_t* mtr) /*!< in: mtr */
{
@@ -1983,7 +1983,7 @@ row_ins_index_entry_low(
depending on whether we wish optimistic or
pessimistic descent down the index tree */
dict_index_t* index, /*!< in: index */
- dtuple_t* entry, /*!< in: index entry to insert */
+ dtuple_t* entry, /*!< in/out: index entry to insert */
ulint n_ext, /*!< in: number of externally stored columns */
que_thr_t* thr) /*!< in: query thread */
{
@@ -2164,9 +2164,10 @@ ulint
row_ins_index_entry(
/*================*/
dict_index_t* index, /*!< in: index */
- dtuple_t* entry, /*!< in: index entry to insert */
+ dtuple_t* entry, /*!< in/out: index entry to insert */
ulint n_ext, /*!< in: number of externally stored columns */
- ibool foreign,/*!< in: TRUE=check foreign key constraints */
+ ibool foreign,/*!< in: TRUE=check foreign key constraints
+ (foreign=FALSE only during CREATE INDEX) */
que_thr_t* thr) /*!< in: query thread */
{
ulint err;
diff --git a/storage/xtradb/row/row0merge.c b/storage/xtradb/row/row0merge.c
index 65102851bdf..782c029fbcc 100644
--- a/storage/xtradb/row/row0merge.c
+++ b/storage/xtradb/row/row0merge.c
@@ -2052,7 +2052,7 @@ row_merge_drop_index(
/* Replace this index with another equivalent index for all
foreign key constraints on this table where this index is used */
- dict_table_replace_index_in_foreign_list(table, index);
+ dict_table_replace_index_in_foreign_list(table, index, trx);
dict_index_remove_from_cache(table, index);
trx->op_info = "";
@@ -2350,7 +2350,7 @@ row_merge_rename_tables(
{
ulint err = DB_ERROR;
pars_info_t* info;
- char old_name[MAX_TABLE_NAME_LEN + 1];
+ char old_name[MAX_FULL_NAME_LEN + 1];
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_ad(old_table != new_table);
@@ -2365,7 +2365,7 @@ row_merge_rename_tables(
ut_print_timestamp(stderr);
fprintf(stderr, "InnoDB: too long table name: '%s', "
"max length is %d\n", old_table->name,
- MAX_TABLE_NAME_LEN);
+ MAX_FULL_NAME_LEN);
ut_error;
}
diff --git a/storage/xtradb/row/row0mysql.c b/storage/xtradb/row/row0mysql.c
index e9b272abab4..205aead8efe 100644
--- a/storage/xtradb/row/row0mysql.c
+++ b/storage/xtradb/row/row0mysql.c
@@ -574,7 +574,7 @@ handle_new_error:
"InnoDB: If the mysqld server crashes"
" after the startup or when\n"
"InnoDB: you dump the tables, look at\n"
- "InnoDB: " REFMAN "forcing-recovery.html"
+ "InnoDB: " REFMAN "forcing-innodb-recovery.html"
" for help.\n", stderr);
break;
case DB_FOREIGN_EXCEED_MAX_CASCADE:
@@ -875,7 +875,8 @@ row_update_statistics_if_needed(
if (counter > 2000000000
|| ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) {
- dict_update_statistics(table, TRUE);
+ dict_update_statistics(table, FALSE /* update even if stats
+ are initialized */, TRUE);
}
}
@@ -3014,7 +3015,8 @@ next_rec:
dict_table_autoinc_lock(table);
dict_table_autoinc_initialize(table, 1);
dict_table_autoinc_unlock(table);
- dict_update_statistics(table, TRUE);
+ dict_update_statistics(table, FALSE /* update even if stats are
+ initialized */, TRUE);
trx_commit_for_mysql(trx);
diff --git a/storage/xtradb/row/row0purge.c b/storage/xtradb/row/row0purge.c
index 31b255cf2d4..8bf2ae0f458 100644
--- a/storage/xtradb/row/row0purge.c
+++ b/storage/xtradb/row/row0purge.c
@@ -413,7 +413,7 @@ row_purge_upd_exist_or_extern(
while (node->index != NULL) {
index = node->index;
- if (row_upd_changes_ord_field_binary(NULL, node->index,
+ if (row_upd_changes_ord_field_binary(NULL, NULL, node->index,
node->update)) {
/* Build the older version of the index entry */
entry = row_build_index_entry(node->row, NULL,
diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c
index 79cf88904eb..13dccdffb96 100644
--- a/storage/xtradb/row/row0sel.c
+++ b/storage/xtradb/row/row0sel.c
@@ -106,6 +106,18 @@ row_sel_sec_rec_is_for_blob(
ulint len;
byte buf[DICT_MAX_INDEX_COL_LEN];
+ ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE);
+
+ if (UNIV_UNLIKELY
+ (!memcmp(clust_field + clust_len - BTR_EXTERN_FIELD_REF_SIZE,
+ field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE))) {
+ /* The externally stored field was not written yet.
+ This record should only be seen by
+ recv_recovery_rollback_active() or any
+ TRX_ISO_READ_UNCOMMITTED transactions. */
+ return(FALSE);
+ }
+
len = btr_copy_externally_stored_field_prefix(buf, sizeof buf,
zip_size,
clust_field, clust_len);
diff --git a/storage/xtradb/row/row0umod.c b/storage/xtradb/row/row0umod.c
index 5998dadd16d..562f8093c38 100644
--- a/storage/xtradb/row/row0umod.c
+++ b/storage/xtradb/row/row0umod.c
@@ -668,19 +668,18 @@ row_undo_mod_upd_exist_sec(
while (node->index != NULL) {
index = node->index;
- if (row_upd_changes_ord_field_binary(node->row, node->index,
- node->update)) {
+ if (row_upd_changes_ord_field_binary(
+ node->row, node->ext, node->index, node->update)) {
/* Build the newest version of the index entry */
entry = row_build_index_entry(node->row, node->ext,
index, heap);
if (UNIV_UNLIKELY(!entry)) {
/* The server must have crashed in
- row_upd_clust_rec_by_insert(), in
- row_ins_index_entry_low() before
- btr_store_big_rec_extern_fields()
- has written the externally stored columns
- (BLOBs) of the new clustered index entry. */
+ row_upd_clust_rec_by_insert() before
+ the updated externally stored columns (BLOBs)
+ of the new clustered index entry were
+ written. */
/* The table must be in DYNAMIC or COMPRESSED
format. REDUNDANT and COMPACT formats
diff --git a/storage/xtradb/row/row0upd.c b/storage/xtradb/row/row0upd.c
index 444003ba3f0..e1c78949603 100644
--- a/storage/xtradb/row/row0upd.c
+++ b/storage/xtradb/row/row0upd.c
@@ -371,8 +371,8 @@ UNIV_INTERN
void
row_upd_index_entry_sys_field(
/*==========================*/
- const dtuple_t* entry, /*!< in: index entry, where the memory buffers
- for sys fields are already allocated:
+ dtuple_t* entry, /*!< in/out: index entry, where the memory
+ buffers for sys fields are already allocated:
the function just copies the new values to
them */
dict_index_t* index, /*!< in: clustered index */
@@ -1198,20 +1198,21 @@ row_upd_changes_ord_field_binary(
row and the data values in update are not
known when this function is called, e.g., at
compile time */
+ const row_ext_t*ext, /*!< NULL, or prefixes of the externally
+ stored columns in the old row */
dict_index_t* index, /*!< in: index of the record */
const upd_t* update) /*!< in: update vector for the row; NOTE: the
field numbers in this MUST be clustered index
positions! */
{
- ulint n_unique;
- ulint n_upd_fields;
- ulint i, j;
- dict_index_t* clust_index;
+ ulint n_unique;
+ ulint i;
+ const dict_index_t* clust_index;
- ut_ad(update && index);
+ ut_ad(update);
+ ut_ad(index);
n_unique = dict_index_get_n_unique(index);
- n_upd_fields = upd_get_n_fields(update);
clust_index = dict_table_get_first_index(index->table);
@@ -1219,33 +1220,72 @@ row_upd_changes_ord_field_binary(
const dict_field_t* ind_field;
const dict_col_t* col;
- ulint col_pos;
ulint col_no;
+ const upd_field_t* upd_field;
+ const dfield_t* dfield;
+ dfield_t dfield_ext;
+ ulint dfield_len= 0;
+ const byte* buf;
ind_field = dict_index_get_nth_field(index, i);
col = dict_field_get_col(ind_field);
- col_pos = dict_col_get_clust_pos(col, clust_index);
col_no = dict_col_get_no(col);
- for (j = 0; j < n_upd_fields; j++) {
+ upd_field = upd_get_field_by_field_no(
+ update, dict_col_get_clust_pos(col, clust_index));
- const upd_field_t* upd_field
- = upd_get_nth_field(update, j);
+ if (upd_field == NULL) {
+ continue;
+ }
+
+ if (row == NULL) {
+ ut_ad(ext == NULL);
+ return(TRUE);
+ }
- /* Note that if the index field is a column prefix
- then it may be that row does not contain an externally
- stored part of the column value, and we cannot compare
- the datas */
+ dfield = dtuple_get_nth_field(row, col_no);
- if (col_pos == upd_field->field_no
- && (row == NULL
- || ind_field->prefix_len > 0
- || !dfield_datas_are_binary_equal(
- dtuple_get_nth_field(row, col_no),
- &(upd_field->new_val)))) {
+ /* This treatment of column prefix indexes is loosely
+ based on row_build_index_entry(). */
- return(TRUE);
+ if (UNIV_LIKELY(ind_field->prefix_len == 0)
+ || dfield_is_null(dfield)) {
+ /* do nothing special */
+ } else if (UNIV_LIKELY_NULL(ext)) {
+ /* See if the column is stored externally. */
+ buf = row_ext_lookup(ext, col_no, &dfield_len);
+
+ ut_ad(col->ord_part);
+
+ if (UNIV_LIKELY_NULL(buf)) {
+ if (UNIV_UNLIKELY(buf == field_ref_zero)) {
+ /* This should never happen, but
+ we try to fail safe here. */
+ ut_ad(0);
+ return(TRUE);
+ }
+
+ goto copy_dfield;
}
+ } else if (dfield_is_ext(dfield)) {
+ dfield_len = dfield_get_len(dfield);
+ ut_a(dfield_len > BTR_EXTERN_FIELD_REF_SIZE);
+ dfield_len -= BTR_EXTERN_FIELD_REF_SIZE;
+ ut_a(dict_index_is_clust(index)
+ || ind_field->prefix_len <= dfield_len);
+ buf = dfield_get_data(dfield);
+copy_dfield:
+ ut_a(dfield_len > 0);
+ dfield_copy(&dfield_ext, dfield);
+ dfield_set_data(&dfield_ext, buf, dfield_len);
+ dfield = &dfield_ext;
+ }
+
+ if (!dfield_datas_are_binary_equal(
+ dfield, &upd_field->new_val,
+ ind_field->prefix_len)) {
+
+ return(TRUE);
}
}
@@ -1329,7 +1369,7 @@ row_upd_changes_first_fields_binary(
if (col_pos == upd_field->field_no
&& !dfield_datas_are_binary_equal(
dtuple_get_nth_field(entry, i),
- &(upd_field->new_val))) {
+ &upd_field->new_val, 0)) {
return(TRUE);
}
@@ -1568,14 +1608,99 @@ row_upd_sec_step(
ut_ad(!dict_index_is_clust(node->index));
if (node->state == UPD_NODE_UPDATE_ALL_SEC
- || row_upd_changes_ord_field_binary(node->row, node->index,
- node->update)) {
+ || row_upd_changes_ord_field_binary(node->row, node->ext,
+ node->index, node->update)) {
return(row_upd_sec_index_entry(node, thr));
}
return(DB_SUCCESS);
}
+#ifdef UNIV_DEBUG
+# define row_upd_clust_rec_by_insert_inherit(rec,offsets,entry,update) \
+ row_upd_clust_rec_by_insert_inherit_func(rec,offsets,entry,update)
+#else /* UNIV_DEBUG */
+# define row_upd_clust_rec_by_insert_inherit(rec,offsets,entry,update) \
+ row_upd_clust_rec_by_insert_inherit_func(entry,update)
+#endif /* UNIV_DEBUG */
+/*******************************************************************//**
+Mark non-updated off-page columns inherited when the primary key is
+updated. We must mark them as inherited in entry, so that they are not
+freed in a rollback. A limited version of this function used to be
+called btr_cur_mark_dtuple_inherited_extern().
+@return TRUE if any columns were inherited */
+static __attribute__((warn_unused_result))
+ibool
+row_upd_clust_rec_by_insert_inherit_func(
+/*=====================================*/
+#ifdef UNIV_DEBUG
+ const rec_t* rec, /*!< in: old record, or NULL */
+ const ulint* offsets,/*!< in: rec_get_offsets(rec), or NULL */
+#endif /* UNIV_DEBUG */
+ dtuple_t* entry, /*!< in/out: updated entry to be
+ inserted into the clustered index */
+ const upd_t* update) /*!< in: update vector */
+{
+ ibool inherit = FALSE;
+ ulint i;
+
+ ut_ad(!rec == !offsets);
+ ut_ad(!rec || rec_offs_any_extern(offsets));
+
+ for (i = 0; i < dtuple_get_n_fields(entry); i++) {
+ dfield_t* dfield = dtuple_get_nth_field(entry, i);
+ byte* data;
+ ulint len;
+
+ ut_ad(!offsets
+ || !rec_offs_nth_extern(offsets, i)
+ == !dfield_is_ext(dfield)
+ || upd_get_field_by_field_no(update, i));
+ if (!dfield_is_ext(dfield)
+ || upd_get_field_by_field_no(update, i)) {
+ continue;
+ }
+
+#ifdef UNIV_DEBUG
+ if (UNIV_LIKELY(rec != NULL)) {
+ const byte* rec_data
+ = rec_get_nth_field(rec, offsets, i, &len);
+ ut_ad(len == dfield_get_len(dfield));
+ ut_ad(len != UNIV_SQL_NULL);
+ ut_ad(len >= BTR_EXTERN_FIELD_REF_SIZE);
+
+ rec_data += len - BTR_EXTERN_FIELD_REF_SIZE;
+
+ /* The pointer must not be zero. */
+ ut_ad(memcmp(rec_data, field_ref_zero,
+ BTR_EXTERN_FIELD_REF_SIZE));
+ /* The BLOB must be owned. */
+ ut_ad(!(rec_data[BTR_EXTERN_LEN]
+ & BTR_EXTERN_OWNER_FLAG));
+ }
+#endif /* UNIV_DEBUG */
+
+ len = dfield_get_len(dfield);
+ ut_a(len != UNIV_SQL_NULL);
+ ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
+ data = dfield_get_data(dfield);
+ data += len - BTR_EXTERN_FIELD_REF_SIZE;
+ /* The pointer must not be zero. */
+ ut_a(memcmp(data, field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE));
+ /* The BLOB must be owned. */
+ ut_a(!(data[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
+
+ data[BTR_EXTERN_LEN] |= BTR_EXTERN_INHERITED_FLAG;
+ /* The BTR_EXTERN_INHERITED_FLAG only matters in
+ rollback. Purge will always free the extern fields of
+ a delete-marked row. */
+
+ inherit = TRUE;
+ }
+
+ return(inherit);
+}
+
/***********************************************************//**
Marks the clustered index record deleted and inserts the updated version
of the record to the index. This function should be used when the ordering
@@ -1587,21 +1712,23 @@ static
ulint
row_upd_clust_rec_by_insert(
/*========================*/
- upd_node_t* node, /*!< in: row update node */
+ upd_node_t* node, /*!< in/out: row update node */
dict_index_t* index, /*!< in: clustered index of the record */
que_thr_t* thr, /*!< in: query thread */
ibool check_ref,/*!< in: TRUE if index may be referenced in
a foreign key constraint */
- mtr_t* mtr) /*!< in: mtr; gets committed here */
+ mtr_t* mtr) /*!< in/out: mtr; gets committed here */
{
- mem_heap_t* heap = NULL;
+ mem_heap_t* heap;
btr_pcur_t* pcur;
btr_cur_t* btr_cur;
trx_t* trx;
dict_table_t* table;
dtuple_t* entry;
ulint err;
- ibool change_ownership = FALSE;
+ ibool change_ownership = FALSE;
+ rec_t* rec;
+ ulint* offsets = NULL;
ut_ad(node);
ut_ad(dict_index_is_clust(index));
@@ -1611,77 +1738,112 @@ row_upd_clust_rec_by_insert(
pcur = node->pcur;
btr_cur = btr_pcur_get_btr_cur(pcur);
- if (node->state != UPD_NODE_INSERT_CLUSTERED) {
- rec_t* rec;
- dict_index_t* index;
- ulint offsets_[REC_OFFS_NORMAL_SIZE];
- ulint* offsets;
- rec_offs_init(offsets_);
+ heap = mem_heap_create(1000);
+
+ entry = row_build_index_entry(node->upd_row, node->upd_ext,
+ index, heap);
+ ut_a(entry);
- err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
- btr_cur, TRUE, thr, mtr);
+ row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
+
+ switch (node->state) {
+ default:
+ ut_error;
+ case UPD_NODE_INSERT_BLOB:
+ /* A lock wait occurred in row_ins_index_entry() in
+ the previous invocation of this function. Mark the
+ off-page columns in the entry inherited. */
+
+ change_ownership = row_upd_clust_rec_by_insert_inherit(
+ NULL, NULL, entry, node->update);
+ ut_a(change_ownership);
+ /* fall through */
+ case UPD_NODE_INSERT_CLUSTERED:
+ /* A lock wait occurred in row_ins_index_entry() in
+ the previous invocation of this function. */
+ break;
+ case UPD_NODE_UPDATE_CLUSTERED:
+ /* This is the first invocation of the function where
+ we update the primary key. Delete-mark the old record
+ in the clustered index and prepare to insert a new entry. */
+ rec = btr_cur_get_rec(btr_cur);
+ offsets = rec_get_offsets(rec, index, NULL,
+ ULINT_UNDEFINED, &heap);
+ ut_ad(page_rec_is_user_rec(rec));
+
+ err = btr_cur_del_mark_set_clust_rec(
+ BTR_NO_LOCKING_FLAG, btr_cur_get_block(btr_cur),
+ rec, index, offsets, TRUE, thr, mtr);
if (err != DB_SUCCESS) {
+err_exit:
mtr_commit(mtr);
+ mem_heap_free(heap);
return(err);
}
- /* Mark as not-owned the externally stored fields which the new
- row inherits from the delete marked record: purge should not
- free those externally stored fields even if the delete marked
- record is removed from the index tree, or updated. */
+ /* If the the new row inherits externally stored
+ fields (off-page columns a.k.a. BLOBs) from the
+ delete-marked old record, mark them disowned by the
+ old record and owned by the new entry. */
+
+ if (rec_offs_any_extern(offsets)) {
+ change_ownership = row_upd_clust_rec_by_insert_inherit(
+ rec, offsets, entry, node->update);
+
+ if (change_ownership) {
+ btr_pcur_store_position(pcur, mtr);
+ }
+ }
- rec = btr_cur_get_rec(btr_cur);
- index = dict_table_get_first_index(table);
- offsets = rec_get_offsets(rec, index, offsets_,
- ULINT_UNDEFINED, &heap);
- change_ownership = btr_cur_mark_extern_inherited_fields(
- btr_cur_get_page_zip(btr_cur), rec, index, offsets,
- node->update, mtr);
if (check_ref) {
/* NOTE that the following call loses
the position of pcur ! */
err = row_upd_check_references_constraints(
node, pcur, table, index, offsets, thr, mtr);
if (err != DB_SUCCESS) {
- mtr_commit(mtr);
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
- return(err);
+ goto err_exit;
}
}
}
mtr_commit(mtr);
- if (!heap) {
- heap = mem_heap_create(500);
- }
- node->state = UPD_NODE_INSERT_CLUSTERED;
+ err = row_ins_index_entry(index, entry,
+ node->upd_ext ? node->upd_ext->n_ext : 0,
+ TRUE, thr);
+ node->state = change_ownership
+ ? UPD_NODE_INSERT_BLOB
+ : UPD_NODE_INSERT_CLUSTERED;
- entry = row_build_index_entry(node->upd_row, node->upd_ext,
- index, heap);
- ut_a(entry);
+ if (err == DB_SUCCESS && change_ownership) {
+ /* Mark the non-updated fields disowned by the old record. */
- row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
+ /* NOTE: this transaction has an x-lock on the record
+ and therefore other transactions cannot modify the
+ record when we have no latch on the page. In addition,
+ we assume that other query threads of the same
+ transaction do not modify the record in the meantime.
+ Therefore we can assert that the restoration of the
+ cursor succeeds. */
- if (change_ownership) {
- /* If we return from a lock wait, for example, we may have
- extern fields marked as not-owned in entry (marked in the
- if-branch above). We must unmark them, take the ownership
- back. */
+ mtr_start(mtr);
- btr_cur_unmark_dtuple_extern_fields(entry);
+ if (!btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr)) {
+ ut_error;
+ }
- /* We must mark non-updated extern fields in entry as
- inherited, so that a possible rollback will not free them. */
+ rec = btr_cur_get_rec(btr_cur);
+ offsets = rec_get_offsets(rec, index, offsets,
+ ULINT_UNDEFINED, &heap);
+ ut_ad(page_rec_is_user_rec(rec));
- btr_cur_mark_dtuple_inherited_extern(entry, node->update);
+ btr_cur_disown_inherited_fields(
+ btr_cur_get_page_zip(btr_cur),
+ rec, index, offsets, node->update, mtr);
+
+ mtr_commit(mtr);
}
- err = row_ins_index_entry(index, entry,
- node->upd_ext ? node->upd_ext->n_ext : 0,
- TRUE, thr);
mem_heap_free(heap);
return(err);
@@ -1825,8 +1987,9 @@ row_upd_del_mark_clust_rec(
/* Mark the clustered index record deleted; we do not have to check
locks, because we assume that we have an x-lock on the record */
- err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
- btr_cur, TRUE, thr, mtr);
+ err = btr_cur_del_mark_set_clust_rec(
+ BTR_NO_LOCKING_FLAG, btr_cur_get_block(btr_cur),
+ btr_cur_get_rec(btr_cur), index, offsets, TRUE, thr, mtr);
if (err == DB_SUCCESS && check_ref) {
/* NOTE that the following call loses the position of pcur ! */
@@ -1973,7 +2136,8 @@ exit_func:
row_upd_store_row(node);
- if (row_upd_changes_ord_field_binary(node->row, index, node->update)) {
+ if (row_upd_changes_ord_field_binary(node->row, node->ext, index,
+ node->update)) {
/* Update causes an ordering field (ordering fields within
the B-tree) of the clustered index record to change: perform
@@ -2042,7 +2206,8 @@ row_upd(
}
if (node->state == UPD_NODE_UPDATE_CLUSTERED
- || node->state == UPD_NODE_INSERT_CLUSTERED) {
+ || node->state == UPD_NODE_INSERT_CLUSTERED
+ || node->state == UPD_NODE_INSERT_BLOB) {
log_free_check();
err = row_upd_clust_step(node, thr);
diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c
index 637b9e2df28..3184308f573 100644
--- a/storage/xtradb/srv/srv0srv.c
+++ b/storage/xtradb/srv/srv0srv.c
@@ -211,6 +211,11 @@ UNIV_INTERN ulint srv_buf_pool_curr_size = 0;
UNIV_INTERN ulint srv_mem_pool_size = ULINT_MAX;
UNIV_INTERN ulint srv_lock_table_size = ULINT_MAX;
+/* key value for shm */
+UNIV_INTERN uint srv_buffer_pool_shm_key = 0;
+UNIV_INTERN ibool srv_buffer_pool_shm_is_reused = FALSE;
+UNIV_INTERN ibool srv_buffer_pool_shm_checksum = TRUE;
+
/* This parameter is deprecated. Use srv_n_io_[read|write]_threads
instead. */
UNIV_INTERN ulint srv_n_file_io_threads = ULINT_MAX;
@@ -221,6 +226,9 @@ UNIV_INTERN ulint srv_n_write_io_threads = ULINT_MAX;
UNIV_INTERN ulint srv_page_size_shift = 0;
UNIV_INTERN ulint srv_page_size = 0;
+/* The log block size */
+UNIV_INTERN ulint srv_log_block_size = 0;
+
/* User settable value of the number of pages that must be present
in the buffer cache and accessed sequentially for InnoDB to trigger a
readahead request. */
@@ -2683,15 +2691,26 @@ srv_master_thread(
ulint n_pages_purged = 0;
ulint n_bytes_merged;
ulint n_pages_flushed;
+ ulint n_pages_flushed_prev = 0;
ulint n_bytes_archived;
ulint n_tables_to_drop;
ulint n_ios;
ulint n_ios_old;
ulint n_ios_very_old;
ulint n_pend_ios;
+ ulint next_itr_time;
+ ulint prev_adaptive_checkpoint = ULINT_UNDEFINED;
+ ulint inner_loop = 0;
ibool skip_sleep = FALSE;
ulint i;
+ struct t_prev_flush_info_struct {
+ ulint count;
+ unsigned space:32;
+ unsigned offset:32;
+ ib_uint64_t oldest_modification;
+ } prev_flush_info;
+
ib_uint64_t lsn_old;
ib_uint64_t oldest_lsn;
@@ -2704,6 +2723,7 @@ srv_master_thread(
srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
+ memset(&prev_flush_info, 0, sizeof(prev_flush_info));
mutex_enter(&kernel_mutex);
srv_table_reserve_slot(SRV_MASTER);
@@ -2723,6 +2743,8 @@ loop:
n_ios_very_old = log_sys->n_log_ios + buf_pool->stat.n_pages_read
+ buf_pool->stat.n_pages_written;
+ n_pages_flushed= 0;
+
mutex_enter(&kernel_mutex);
/* Store the user activity counter at the start of this loop */
@@ -2741,15 +2763,20 @@ loop:
srv_last_log_flush_time = time(NULL);
skip_sleep = FALSE;
+ next_itr_time = ut_time_ms() + 1000;
+
for (i = 0; i < 10; i++) {
+ ulint cur_time = ut_time_ms();
+
n_ios_old = log_sys->n_log_ios + buf_pool->stat.n_pages_read
+ buf_pool->stat.n_pages_written;
srv_main_thread_op_info = "sleeping";
srv_main_1_second_loops++;
if (!skip_sleep) {
+ if (next_itr_time > cur_time) {
- os_event_wait_time(srv_shutdown_event, 1000000);
+ os_event_wait_time(srv_shutdown_event, ut_min(1000000, (next_itr_time - cur_time) * 1000));
srv_main_sleeps++;
/*
@@ -2766,6 +2793,10 @@ loop:
*/
}
+ /* Each iteration should happen at 1 second interval. */
+ next_itr_time = ut_time_ms() + 1000;
+ }
+
skip_sleep = FALSE;
/* ALTER TABLE in MySQL requires on Unix that the table handler
@@ -2828,6 +2859,7 @@ loop:
mutex_enter(&(log_sys->mutex));
lsn_old = log_sys->lsn;
mutex_exit(&(log_sys->mutex));
+ prev_adaptive_checkpoint = ULINT_UNDEFINED;
} else if (srv_adaptive_flushing) {
/* Try to keep the rate of flushing of dirty
@@ -2853,6 +2885,7 @@ loop:
mutex_enter(&(log_sys->mutex));
lsn_old = log_sys->lsn;
mutex_exit(&(log_sys->mutex));
+ prev_adaptive_checkpoint = ULINT_UNDEFINED;
} else if (srv_adaptive_checkpoint == 1) {
/* adaptive_flushing option is prior to adaptive_checkpoint option, for now */
@@ -2896,6 +2929,7 @@ loop:
mutex_exit(&(log_sys->mutex));
}
}
+ prev_adaptive_checkpoint = 1;
} else if (srv_adaptive_checkpoint == 2) {
/* Try to keep modified age not to exceed
@@ -2978,11 +3012,124 @@ retry_flush_batch:
mutex_exit(&(log_sys->mutex));
}
}
+ prev_adaptive_checkpoint = 2;
+ } else if (srv_adaptive_checkpoint == 3) {
+ buf_page_t* bpage;
+ ib_uint64_t lsn;
+
+ mutex_enter(&(log_sys->mutex));
+ oldest_lsn = buf_pool_get_oldest_modification();
+ lsn = log_sys->lsn;
+ mutex_exit(&(log_sys->mutex));
+ /* upper loop/sec. (x10) */
+ next_itr_time -= 900; /* 1000 - 900 == 100 */
+ inner_loop++;
+ if (inner_loop < 10) {
+ i--;
+ } else {
+ inner_loop = 0;
+ }
+
+ if (prev_adaptive_checkpoint == 3) {
+ lint n_flush;
+ lint blocks_sum, new_blocks_sum, flushed_blocks_sum;
+
+ blocks_sum = new_blocks_sum = flushed_blocks_sum = 0;
+
+ /* prev_flush_info should be the previous loop's */
+ {
+ lint blocks_num, new_blocks_num, flushed_blocks_num;
+ ibool found;
+
+ blocks_num = UT_LIST_GET_LEN(buf_pool->flush_list);
+ bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
+ new_blocks_num = 0;
+
+ found = FALSE;
+ while (bpage != NULL) {
+ if (prev_flush_info.space == bpage->space
+ && prev_flush_info.offset == bpage->offset
+ && prev_flush_info.oldest_modification
+ == bpage->oldest_modification) {
+ found = TRUE;
+ break;
+ }
+ bpage = UT_LIST_GET_NEXT(flush_list, bpage);
+ new_blocks_num++;
+ }
+ if (!found) {
+ new_blocks_num = blocks_num;
+ }
+
+ flushed_blocks_num = new_blocks_num + prev_flush_info.count
+ - blocks_num;
+ if (flushed_blocks_num < 0) {
+ flushed_blocks_num = 0;
+ }
+
+ bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
+
+ prev_flush_info.count = UT_LIST_GET_LEN(buf_pool->flush_list);
+ if (bpage) {
+ prev_flush_info.space = bpage->space;
+ prev_flush_info.offset = bpage->offset;
+ prev_flush_info.oldest_modification = bpage->oldest_modification;
+ } else {
+ prev_flush_info.space = 0;
+ prev_flush_info.offset = 0;
+ prev_flush_info.oldest_modification = 0;
+ }
+
+ new_blocks_sum += new_blocks_num;
+ flushed_blocks_sum += flushed_blocks_num;
+ blocks_sum += blocks_num;
+ }
+
+ n_flush = (lint) (blocks_sum * (lsn - lsn_old) / log_sys->max_modified_age_async);
+ if ((ulint) flushed_blocks_sum > n_pages_flushed_prev) {
+ n_flush -= (flushed_blocks_sum - n_pages_flushed_prev);
+ }
+
+ if (n_flush > 0) {
+ n_flush++;
+ n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, n_flush,
+ oldest_lsn + (lsn - lsn_old));
+ } else {
+ n_pages_flushed = 0;
+ }
+ } else {
+ /* store previous first pages of the flush_list */
+ {
+ bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
+
+ prev_flush_info.count = UT_LIST_GET_LEN(buf_pool->flush_list);
+ if (bpage) {
+ prev_flush_info.space = bpage->space;
+ prev_flush_info.offset = bpage->offset;
+ prev_flush_info.oldest_modification = bpage->oldest_modification;
+ } else {
+ prev_flush_info.space = 0;
+ prev_flush_info.offset = 0;
+ prev_flush_info.oldest_modification = 0;
+ }
+ }
+ n_pages_flushed = 0;
+ }
+
+ lsn_old = lsn;
+ prev_adaptive_checkpoint = 3;
} else {
mutex_enter(&(log_sys->mutex));
lsn_old = log_sys->lsn;
mutex_exit(&(log_sys->mutex));
+ prev_adaptive_checkpoint = ULINT_UNDEFINED;
+ }
+
+ if (n_pages_flushed == ULINT_UNDEFINED) {
+ n_pages_flushed_prev = 0;
+ } else {
+ n_pages_flushed_prev = n_pages_flushed;
}
if (srv_activity_count == old_activity_count) {
diff --git a/storage/xtradb/srv/srv0start.c b/storage/xtradb/srv/srv0start.c
index 27804e78a32..cef045d72e1 100644
--- a/storage/xtradb/srv/srv0start.c
+++ b/storage/xtradb/srv/srv0start.c
@@ -1439,8 +1439,25 @@ innobase_start_or_create_for_mysql(void)
fil_init(srv_file_per_table ? 50000 : 5000,
srv_max_n_open_files);
+ /* Print time to initialize the buffer pool */
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Initializing buffer pool, size =");
+
+ if (srv_buf_pool_size >= 1024 * 1024 * 1024) {
+ fprintf(stderr,
+ " %.1fG\n",
+ ((double) srv_buf_pool_size) / (1024 * 1024 * 1024));
+ } else {
+ fprintf(stderr,
+ " %.1fM\n",
+ ((double) srv_buf_pool_size) / (1024 * 1024));
+ }
+
ret = buf_pool_init();
+ ut_print_timestamp(stderr);
+
if (ret == NULL) {
fprintf(stderr,
"InnoDB: Fatal error: cannot allocate the memory"
@@ -1449,6 +1466,9 @@ innobase_start_or_create_for_mysql(void)
return(DB_ERROR);
}
+ fprintf(stderr,
+ " InnoDB: Completed initialization of buffer pool\n");
+
#ifdef UNIV_DEBUG
/* We have observed deadlocks with a 5MB buffer pool but
the actual lower limit could very well be a little higher. */
@@ -1639,14 +1659,6 @@ innobase_start_or_create_for_mysql(void)
trx_sys_file_format_init();
- if (create_new_doublewrite_file) {
- mtr_start(&mtr);
- fsp_header_init(TRX_DOUBLEWRITE_SPACE, TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9, &mtr);
- mtr_commit(&mtr);
-
- trx_sys_dummy_create(TRX_DOUBLEWRITE_SPACE);
- }
-
if (create_new_db) {
mtr_start(&mtr);
fsp_header_init(0, sum_of_new_sizes, &mtr);
@@ -1654,6 +1666,15 @@ innobase_start_or_create_for_mysql(void)
mtr_commit(&mtr);
trx_sys_create();
+
+ if (create_new_doublewrite_file) {
+ mtr_start(&mtr);
+ fsp_header_init(TRX_DOUBLEWRITE_SPACE, TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9, &mtr);
+ mtr_commit(&mtr);
+
+ trx_sys_dummy_create(TRX_DOUBLEWRITE_SPACE);
+ }
+
dict_create();
srv_startup_is_before_trx_rollback_phase = FALSE;
@@ -1691,6 +1712,13 @@ innobase_start_or_create_for_mysql(void)
recv_recovery_from_archive_finish();
#endif /* UNIV_LOG_ARCHIVE */
} else {
+ char* save_srv_doublewrite_file = NULL;
+
+ if (create_new_doublewrite_file) {
+ /* doublewrite_file cannot be used for recovery yet. */
+ save_srv_doublewrite_file = srv_doublewrite_file;
+ srv_doublewrite_file = NULL;
+ }
/* Check if we support the max format that is stamped
on the system tablespace.
@@ -1716,6 +1744,8 @@ innobase_start_or_create_for_mysql(void)
Note that this is not as heavy weight as it seems. At
this point there will be only ONE page in the buf_LRU
and there must be no page in the buf_flush list. */
+ /* buffer_pool_shm should not be reused when recovery was needed. */
+ if (!srv_buffer_pool_shm_is_reused)
buf_pool_invalidate();
/* We always try to do a recovery, even if the database had
@@ -1777,6 +1807,17 @@ innobase_start_or_create_for_mysql(void)
we have finished the recovery process so that the
image of TRX_SYS_PAGE_NO is not stale. */
trx_sys_file_format_tag_init();
+
+ if (create_new_doublewrite_file) {
+ /* restore the value */
+ srv_doublewrite_file = save_srv_doublewrite_file;
+
+ mtr_start(&mtr);
+ fsp_header_init(TRX_DOUBLEWRITE_SPACE, TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9, &mtr);
+ mtr_commit(&mtr);
+
+ trx_sys_dummy_create(TRX_DOUBLEWRITE_SPACE);
+ }
}
if (!create_new_db && sum_of_new_sizes > 0) {
diff --git a/storage/xtradb/sync/sync0rw.c b/storage/xtradb/sync/sync0rw.c
index f1018522fdf..0bdffcb98b0 100644
--- a/storage/xtradb/sync/sync0rw.c
+++ b/storage/xtradb/sync/sync0rw.c
@@ -334,10 +334,13 @@ rw_lock_validate(
/*=============*/
rw_lock_t* lock) /*!< in: rw-lock */
{
+ ulint waiters;
+ lint lock_word;
+
ut_a(lock);
- ulint waiters = rw_lock_get_waiters(lock);
- lint lock_word = lock->lock_word;
+ waiters = rw_lock_get_waiters(lock);
+ lock_word = lock->lock_word;
ut_ad(lock->magic_n == RW_LOCK_MAGIC_N);
ut_a(waiters == 0 || waiters == 1);
@@ -986,7 +989,7 @@ rw_lock_debug_print(
rwt = info->lock_type;
- fprintf(stderr, "Locked: thread %ld file %s line %ld ",
+ fprintf(stderr, "Locked: thread %lu file %s line %lu ",
(ulong) os_thread_pf(info->thread_id), info->file_name,
(ulong) info->line);
if (rwt == RW_LOCK_SHARED) {
diff --git a/storage/xtradb/thr/thr0loc.c b/storage/xtradb/thr/thr0loc.c
index 5b9e83be920..e702b37afb4 100644
--- a/storage/xtradb/thr/thr0loc.c
+++ b/storage/xtradb/thr/thr0loc.c
@@ -72,6 +72,24 @@ struct thr_local_struct{
/** The value of thr_local_struct::magic_n */
#define THR_LOCAL_MAGIC_N 1231234
+#ifdef UNIV_DEBUG
+/*******************************************************************//**
+Validates thread local data.
+@return TRUE if valid */
+static
+ibool
+thr_local_validate(
+/*===============*/
+ const thr_local_t* local) /*!< in: data to validate */
+{
+ ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
+ ut_ad(local->slot_no == ULINT_UNDEFINED
+ || local->slot_no < OS_THREAD_MAX_N);
+ ut_ad(local->in_ibuf == FALSE || local->in_ibuf == TRUE);
+ return(TRUE);
+}
+#endif /* UNIV_DEBUG */
+
/*******************************************************************//**
Returns the local storage struct for a thread.
@return local storage */
@@ -92,7 +110,8 @@ try_again:
local = NULL;
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
- thr_local_t*, local,, os_thread_eq(local->id, id));
+ thr_local_t*, local, ut_ad(thr_local_validate(local)),
+ os_thread_eq(local->id, id));
if (local == NULL) {
mutex_exit(&thr_local_mutex);
@@ -103,7 +122,7 @@ try_again:
goto try_again;
}
- ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
+ ut_ad(thr_local_validate(local));
return(local);
}
@@ -189,7 +208,7 @@ thr_local_create(void)
local->id = os_thread_get_curr_id();
local->handle = os_thread_get_curr();
local->magic_n = THR_LOCAL_MAGIC_N;
-
+ local->slot_no = ULINT_UNDEFINED;
local->in_ibuf = FALSE;
mutex_enter(&thr_local_mutex);
@@ -217,7 +236,8 @@ thr_local_free(
/* Look for the local struct in the hash table */
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
- thr_local_t*, local,, os_thread_eq(local->id, id));
+ thr_local_t*, local, ut_ad(thr_local_validate(local)),
+ os_thread_eq(local->id, id));
if (local == NULL) {
mutex_exit(&thr_local_mutex);
@@ -231,6 +251,7 @@ thr_local_free(
mutex_exit(&thr_local_mutex);
ut_a(local->magic_n == THR_LOCAL_MAGIC_N);
+ ut_ad(thr_local_validate(local));
mem_free(local);
}
@@ -273,6 +294,7 @@ thr_local_close(void)
local = HASH_GET_NEXT(hash, prev_local);
ut_a(prev_local->magic_n == THR_LOCAL_MAGIC_N);
+ ut_ad(thr_local_validate(prev_local));
mem_free(prev_local);
}
}
diff --git a/storage/xtradb/trx/trx0i_s.c b/storage/xtradb/trx/trx0i_s.c
index c0b9a73a68c..e148234888b 100644
--- a/storage/xtradb/trx/trx0i_s.c
+++ b/storage/xtradb/trx/trx0i_s.c
@@ -404,6 +404,42 @@ table_cache_create_empty_row(
return(row);
}
+#ifdef UNIV_DEBUG
+/*******************************************************************//**
+Validates a row in the locks cache.
+@return TRUE if valid */
+static
+ibool
+i_s_locks_row_validate(
+/*===================*/
+ const i_s_locks_row_t* row) /*!< in: row to validate */
+{
+ ut_ad(row->lock_trx_id != 0);
+ ut_ad(row->lock_mode != NULL);
+ ut_ad(row->lock_type != NULL);
+ ut_ad(row->lock_table != NULL);
+ ut_ad(row->lock_table_id != 0);
+
+ if (row->lock_space == ULINT_UNDEFINED) {
+ /* table lock */
+ ut_ad(!strcmp("TABLE", row->lock_type));
+ ut_ad(row->lock_index == NULL);
+ ut_ad(row->lock_data == NULL);
+ ut_ad(row->lock_page == ULINT_UNDEFINED);
+ ut_ad(row->lock_rec == ULINT_UNDEFINED);
+ } else {
+ /* record lock */
+ ut_ad(!strcmp("RECORD", row->lock_type));
+ ut_ad(row->lock_index != NULL);
+ /* row->lock_data == NULL if buf_page_try_get() == NULL */
+ ut_ad(row->lock_page != ULINT_UNDEFINED);
+ ut_ad(row->lock_rec != ULINT_UNDEFINED);
+ }
+
+ return(TRUE);
+}
+#endif /* UNIV_DEBUG */
+
/*******************************************************************//**
Fills i_s_trx_row_t object.
If memory can not be allocated then FALSE is returned.
@@ -431,18 +467,15 @@ fill_trx_row(
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);
+ row->requested_lock_row = requested_lock_row;
+ ut_ad(requested_lock_row == NULL
+ || i_s_locks_row_validate(requested_lock_row));
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;
}
@@ -461,7 +494,6 @@ fill_trx_row(
stmt = innobase_get_stmt(trx->mysql_thd, &stmt_len);
if (stmt != NULL) {
-
char query[TRX_I_S_TRX_QUERY_MAX_LEN + 1];
if (stmt_len > TRX_I_S_TRX_QUERY_MAX_LEN) {
@@ -475,6 +507,8 @@ fill_trx_row(
cache->storage, stmt, stmt_len + 1,
MAX_ALLOWED_FOR_STORAGE(cache));
+ row->trx_query_cs = innobase_get_charset(trx->mysql_thd);
+
if (row->trx_query == NULL) {
return(FALSE);
@@ -725,6 +759,7 @@ fill_locks_row(
row->lock_table_id = lock_get_table_id(lock);
row->hash_chain.value = row;
+ ut_ad(i_s_locks_row_validate(row));
return(TRUE);
}
@@ -745,6 +780,9 @@ fill_lock_waits_row(
relevant blocking lock
row in innodb_locks */
{
+ ut_ad(i_s_locks_row_validate(requested_lock_row));
+ ut_ad(i_s_locks_row_validate(blocking_lock_row));
+
row->requested_lock_row = requested_lock_row;
row->blocking_lock_row = blocking_lock_row;
@@ -816,6 +854,7 @@ locks_row_eq_lock(
or ULINT_UNDEFINED if the lock
is a table lock */
{
+ ut_ad(i_s_locks_row_validate(row));
#ifdef TEST_NO_LOCKS_ROW_IS_EVER_EQUAL_TO_LOCK_T
return(0);
#else
@@ -873,7 +912,7 @@ search_innodb_locks(
/* auxiliary variable */
hash_chain,
/* assertion on every traversed item */
- ,
+ ut_ad(i_s_locks_row_validate(hash_chain->value)),
/* this determines if we have found the lock */
locks_row_eq_lock(hash_chain->value, lock, heap_no));
@@ -913,6 +952,7 @@ add_lock_to_cache(
dst_row = search_innodb_locks(cache, lock, heap_no);
if (dst_row != NULL) {
+ ut_ad(i_s_locks_row_validate(dst_row));
return(dst_row);
}
#endif
@@ -950,6 +990,7 @@ add_lock_to_cache(
} /* for()-loop */
#endif
+ ut_ad(i_s_locks_row_validate(dst_row));
return(dst_row);
}
diff --git a/storage/xtradb/trx/trx0undo.c b/storage/xtradb/trx/trx0undo.c
index 6f06de593a9..9ed83b5d5c1 100644
--- a/storage/xtradb/trx/trx0undo.c
+++ b/storage/xtradb/trx/trx0undo.c
@@ -1408,7 +1408,7 @@ trx_undo_lists_init(
page_no = mtr_read_ulint(rseg_header + TRX_RSEG_UNDO_SLOTS
+ i * TRX_RSEG_SLOT_SIZE,
MLOG_4BYTES, &mtr);
- if (page_no != FIL_NULL) {
+ if (page_no != 0 && page_no != FIL_NULL) {
srv_extra_undoslots = TRUE;
fprintf(stderr,
"InnoDB: Error: innodb_extra_undoslots option is disabled, but it was enabled before.\n"
diff --git a/storage/xtradb/ut/ut0dbg.c b/storage/xtradb/ut/ut0dbg.c
index 4484e6c36de..7839466e16f 100644
--- a/storage/xtradb/ut/ut0dbg.c
+++ b/storage/xtradb/ut/ut0dbg.c
@@ -79,7 +79,7 @@ ut_dbg_assertion_failed(
" or crashes, even\n"
"InnoDB: immediately after the mysqld startup, there may be\n"
"InnoDB: corruption in the InnoDB tablespace. Please refer to\n"
- "InnoDB: " REFMAN "forcing-recovery.html\n"
+ "InnoDB: " REFMAN "forcing-innodb-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT)
ut_dbg_stop_threads = TRUE;
diff --git a/storage/xtradb/ut/ut0ut.c b/storage/xtradb/ut/ut0ut.c
index 498873e290a..fc1bdffcf38 100644
--- a/storage/xtradb/ut/ut0ut.c
+++ b/storage/xtradb/ut/ut0ut.c
@@ -553,7 +553,7 @@ ut_print_namel(
trx ? trx->mysql_thd : NULL,
table_id);
- fwrite(buf, 1, bufend - buf, f);
+ (void) fwrite(buf, 1, bufend - buf, f);
}
/**********************************************************************//**
@@ -574,7 +574,7 @@ ut_copy_file(
? (size_t) len
: sizeof buf;
size_t size = fread(buf, 1, maxs, src);
- fwrite(buf, 1, size, dest);
+ (void) fwrite(buf, 1, size, dest);
len -= (long) size;
if (size < maxs) {
break;